[PowerPC] eliminate redundant compare instruction
If multiple conditional branches are executed based on the same comparison, we can execute multiple conditional branches based on the result of one comparison on PPC. For example,
if (a == 0) { ... }
else if (a < 0) { ... }
can be executed by one compare and two conditional branches instead of two pairs of a compare and a conditional branch.
This patch identifies a code sequence of the two pairs of a compare and a conditional branch and merge the compares if possible.
To maximize the opportunity, we do canonicalization of code sequence before merging compares.
For the above example, the input for this pass looks like:
cmplwi r3, 0
beq 0, .LBB0_3
cmpwi r3, -1
bgt 0, .LBB0_4
So, before merging two compares, we canonicalize it as
cmpwi r3, 0 ; cmplwi and cmpwi yield same result for beq
beq 0, .LBB0_3
cmpwi r3, 0 ; greather than -1 means greater or equal to 0
bge 0, .LBB0_4
The generated code should be
cmpwi r3, 0
beq 0, .LBB0_3
bge 0, .LBB0_4
Differential Revision: https://reviews.llvm.org/D37211
llvm-svn: 312514
2017-09-05 12:15:17 +08:00
|
|
|
; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc64-unknown-linux-gnu | FileCheck %s
|
|
|
|
; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc64le-unknown-linux-gnu | FileCheck %s
|
|
|
|
|
|
|
|
; Test cases for compare elimination in PPCMIPeephole pass
|
|
|
|
|
|
|
|
define void @func1(i32 signext %a) {
|
|
|
|
; We should have only one compare instruction
|
|
|
|
; CHECK-LABEL: @func1
|
|
|
|
; CHECK: cmp
|
|
|
|
; CHECK-NOT: cmp
|
|
|
|
; CHECK: blr
|
|
|
|
entry:
|
|
|
|
%cmp = icmp eq i32 %a, 100
|
|
|
|
br i1 %cmp, label %if.then, label %if.else
|
|
|
|
|
|
|
|
if.then:
|
|
|
|
tail call void @dummy1()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.else:
|
|
|
|
%cmp1 = icmp slt i32 %a, 100
|
|
|
|
br i1 %cmp1, label %if.then2, label %if.end3
|
|
|
|
|
|
|
|
if.then2:
|
|
|
|
tail call void @dummy2()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.end3:
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
define void @func2(i32 signext %a) {
|
|
|
|
; CHECK-LABEL: @func2
|
|
|
|
; CHECK: cmp
|
|
|
|
; CHECK-NOT: cmp
|
|
|
|
; CHECK: blr
|
|
|
|
entry:
|
|
|
|
%cmp = icmp slt i32 %a, 100
|
|
|
|
br i1 %cmp, label %if.then, label %if.else
|
|
|
|
|
|
|
|
if.then:
|
|
|
|
tail call void @dummy1()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.else:
|
|
|
|
%cmp1 = icmp eq i32 %a, 100
|
|
|
|
br i1 %cmp1, label %if.end3, label %if.then2
|
|
|
|
|
|
|
|
if.then2:
|
|
|
|
tail call void @dummy2()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.end3:
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
define void @func3(i32 signext %a) {
|
|
|
|
; CHECK-LABEL: @func3
|
|
|
|
; CHECK: cmp
|
|
|
|
; CHECK-NOT: cmp
|
|
|
|
; CHECK: blr
|
|
|
|
entry:
|
|
|
|
%cmp = icmp sgt i32 %a, 100
|
|
|
|
br i1 %cmp, label %if.then, label %if.else
|
|
|
|
|
|
|
|
if.then:
|
|
|
|
tail call void @dummy1()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.else:
|
|
|
|
%cmp1 = icmp eq i32 %a, 100
|
|
|
|
br i1 %cmp1, label %if.then2, label %if.end3
|
|
|
|
|
|
|
|
if.then2:
|
|
|
|
tail call void @dummy2()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.end3:
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
define void @func4(i32 zeroext %a) {
|
|
|
|
; CHECK-LABEL: @func4
|
|
|
|
; CHECK: cmp
|
|
|
|
; CHECK-NOT: cmp
|
|
|
|
; CHECK: blr
|
|
|
|
entry:
|
|
|
|
%cmp = icmp eq i32 %a, 100
|
|
|
|
br i1 %cmp, label %if.then, label %if.else
|
|
|
|
|
|
|
|
if.then:
|
|
|
|
tail call void @dummy1()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.else:
|
|
|
|
%cmp1 = icmp ult i32 %a, 100
|
|
|
|
br i1 %cmp1, label %if.then2, label %if.end3
|
|
|
|
|
|
|
|
if.then2:
|
|
|
|
tail call void @dummy2()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.end3:
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
define void @func5(i32 zeroext %a) {
|
|
|
|
; CHECK-LABEL: @func5
|
|
|
|
; CHECK: cmp
|
|
|
|
; CHECK-NOT: cmp
|
|
|
|
; CHECK: blr
|
|
|
|
entry:
|
|
|
|
%cmp = icmp ult i32 %a, 100
|
|
|
|
br i1 %cmp, label %if.then, label %if.else
|
|
|
|
|
|
|
|
if.then:
|
|
|
|
tail call void @dummy1()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.else:
|
|
|
|
%cmp1 = icmp eq i32 %a, 100
|
|
|
|
br i1 %cmp1, label %if.end3, label %if.then2
|
|
|
|
|
|
|
|
if.then2:
|
|
|
|
tail call void @dummy2()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.end3:
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
define void @func6(i32 zeroext %a) {
|
|
|
|
; CHECK-LABEL: @func6
|
|
|
|
; CHECK: cmp
|
|
|
|
; CHECK-NOT: cmp
|
|
|
|
; CHECK: blr
|
|
|
|
entry:
|
|
|
|
%cmp = icmp ugt i32 %a, 100
|
|
|
|
br i1 %cmp, label %if.then, label %if.else
|
|
|
|
|
|
|
|
if.then:
|
|
|
|
tail call void @dummy1()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.else:
|
|
|
|
%cmp1 = icmp eq i32 %a, 100
|
|
|
|
br i1 %cmp1, label %if.then2, label %if.end3
|
|
|
|
|
|
|
|
if.then2:
|
|
|
|
tail call void @dummy2()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.end3:
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
define void @func7(i64 %a) {
|
|
|
|
; CHECK-LABEL: @func7
|
|
|
|
; CHECK: cmp
|
|
|
|
; CHECK-NOT: cmp
|
|
|
|
; CHECK: blr
|
|
|
|
entry:
|
|
|
|
%cmp = icmp eq i64 %a, 100
|
|
|
|
br i1 %cmp, label %if.then, label %if.else
|
|
|
|
|
|
|
|
if.then:
|
|
|
|
tail call void @dummy1()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.else:
|
|
|
|
%cmp1 = icmp slt i64 %a, 100
|
|
|
|
br i1 %cmp1, label %if.then2, label %if.end3
|
|
|
|
|
|
|
|
if.then2:
|
|
|
|
tail call void @dummy2()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.end3:
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
define void @func8(i64 %a) {
|
|
|
|
; CHECK-LABEL: @func8
|
|
|
|
; CHECK: cmp
|
|
|
|
; CHECK-NOT: cmp
|
|
|
|
; CHECK: blr
|
|
|
|
entry:
|
|
|
|
%cmp = icmp slt i64 %a, 100
|
|
|
|
br i1 %cmp, label %if.then, label %if.else
|
|
|
|
|
|
|
|
if.then:
|
|
|
|
tail call void @dummy1()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.else:
|
|
|
|
%cmp1 = icmp eq i64 %a, 100
|
|
|
|
br i1 %cmp1, label %if.end3, label %if.then2
|
|
|
|
|
|
|
|
if.then2:
|
|
|
|
tail call void @dummy2()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.end3:
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
define void @func9(i64 %a) {
|
|
|
|
; CHECK-LABEL: @func9
|
|
|
|
; CHECK: cmp
|
|
|
|
; CHECK-NOT: cmp
|
|
|
|
; CHECK: blr
|
|
|
|
entry:
|
|
|
|
%cmp = icmp sgt i64 %a, 100
|
|
|
|
br i1 %cmp, label %if.then, label %if.else
|
|
|
|
|
|
|
|
if.then:
|
|
|
|
tail call void @dummy1()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.else:
|
|
|
|
%cmp1 = icmp eq i64 %a, 100
|
|
|
|
br i1 %cmp1, label %if.then2, label %if.end3
|
|
|
|
|
|
|
|
if.then2:
|
|
|
|
tail call void @dummy2()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.end3:
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
define void @func10(i64 %a) {
|
|
|
|
; CHECK-LABEL: @func10
|
|
|
|
; CHECK: cmp
|
|
|
|
; CHECK-NOT: cmp
|
|
|
|
; CHECK: blr
|
|
|
|
entry:
|
|
|
|
%cmp = icmp eq i64 %a, 100
|
|
|
|
br i1 %cmp, label %if.then, label %if.else
|
|
|
|
|
|
|
|
if.then:
|
|
|
|
tail call void @dummy1()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.else:
|
|
|
|
%cmp1 = icmp ult i64 %a, 100
|
|
|
|
br i1 %cmp1, label %if.then2, label %if.end3
|
|
|
|
|
|
|
|
if.then2:
|
|
|
|
tail call void @dummy2()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.end3:
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
define void @func11(i64 %a) {
|
|
|
|
; CHECK-LABEL: @func11
|
|
|
|
; CHECK: cmp
|
|
|
|
; CHECK-NOT: cmp
|
|
|
|
; CHECK: blr
|
|
|
|
entry:
|
|
|
|
%cmp = icmp ult i64 %a, 100
|
|
|
|
br i1 %cmp, label %if.then, label %if.else
|
|
|
|
|
|
|
|
if.then:
|
|
|
|
tail call void @dummy1()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.else:
|
|
|
|
%cmp1 = icmp eq i64 %a, 100
|
|
|
|
br i1 %cmp1, label %if.end3, label %if.then2
|
|
|
|
|
|
|
|
if.then2:
|
|
|
|
tail call void @dummy2()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.end3:
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
define void @func12(i64 %a) {
|
|
|
|
; CHECK-LABEL: @func12
|
|
|
|
; CHECK: cmp
|
|
|
|
; CHECK-NOT: cmp
|
|
|
|
; CHECK: blr
|
|
|
|
entry:
|
|
|
|
%cmp = icmp ugt i64 %a, 100
|
|
|
|
br i1 %cmp, label %if.then, label %if.else
|
|
|
|
|
|
|
|
if.then:
|
|
|
|
tail call void @dummy1()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.else:
|
|
|
|
%cmp1 = icmp eq i64 %a, 100
|
|
|
|
br i1 %cmp1, label %if.then2, label %if.end3
|
|
|
|
|
|
|
|
if.then2:
|
|
|
|
tail call void @dummy2()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.end3:
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
define void @func13(i32 signext %a, i32 signext %b) {
|
|
|
|
; CHECK-LABEL: @func13
|
|
|
|
; CHECK: cmp
|
|
|
|
; CHECK-NOT: cmp
|
|
|
|
; CHECK: blr
|
|
|
|
entry:
|
|
|
|
%cmp = icmp eq i32 %a, %b
|
|
|
|
br i1 %cmp, label %if.then, label %if.else
|
|
|
|
|
|
|
|
if.then:
|
|
|
|
tail call void @dummy1()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.else:
|
|
|
|
%cmp1 = icmp slt i32 %a, %b
|
|
|
|
br i1 %cmp1, label %if.then2, label %if.end3
|
|
|
|
|
|
|
|
if.then2:
|
|
|
|
tail call void @dummy2()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.end3:
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
define void @func14(i32 signext %a, i32 signext %b) {
|
|
|
|
; CHECK-LABEL: @func14
|
|
|
|
; CHECK: cmp
|
|
|
|
; CHECK-NOT: cmp
|
|
|
|
; CHECK: blr
|
|
|
|
entry:
|
|
|
|
%cmp = icmp slt i32 %a, %b
|
|
|
|
br i1 %cmp, label %if.then, label %if.else
|
|
|
|
|
|
|
|
if.then:
|
|
|
|
tail call void @dummy1()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.else:
|
|
|
|
%cmp1 = icmp sgt i32 %a, %b
|
|
|
|
br i1 %cmp1, label %if.then2, label %if.end3
|
|
|
|
|
|
|
|
if.then2:
|
|
|
|
tail call void @dummy2()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.end3:
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
define void @func15(i32 signext %a, i32 signext %b) {
|
|
|
|
; CHECK-LABEL: @func15
|
|
|
|
; CHECK: cmp
|
|
|
|
; CHECK-NOT: cmp
|
|
|
|
; CHECK: blr
|
|
|
|
entry:
|
|
|
|
%cmp = icmp slt i32 %b, %a
|
|
|
|
br i1 %cmp, label %if.then, label %if.else
|
|
|
|
|
|
|
|
if.then:
|
|
|
|
tail call void @dummy1()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.else:
|
|
|
|
%cmp1 = icmp eq i32 %a, %b
|
|
|
|
br i1 %cmp1, label %if.then2, label %if.end3
|
|
|
|
|
|
|
|
if.then2:
|
|
|
|
tail call void @dummy2()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.end3:
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
define void @func16(i32 zeroext %a, i32 zeroext %b) {
|
|
|
|
; CHECK-LABEL: @func16
|
|
|
|
; CHECK: cmp
|
|
|
|
; CHECK-NOT: cmp
|
|
|
|
; CHECK: blr
|
|
|
|
entry:
|
|
|
|
%cmp = icmp eq i32 %a, %b
|
|
|
|
br i1 %cmp, label %if.then, label %if.else
|
|
|
|
|
|
|
|
if.then:
|
|
|
|
tail call void @dummy1()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.else:
|
|
|
|
%cmp1 = icmp ult i32 %a, %b
|
|
|
|
br i1 %cmp1, label %if.then2, label %if.end3
|
|
|
|
|
|
|
|
if.then2:
|
|
|
|
tail call void @dummy2()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.end3:
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
define void @func17(i32 zeroext %a, i32 zeroext %b) {
|
|
|
|
; CHECK-LABEL: @func17
|
|
|
|
; CHECK: cmp
|
|
|
|
; CHECK-NOT: cmp
|
|
|
|
; CHECK: blr
|
|
|
|
entry:
|
|
|
|
%cmp = icmp ult i32 %a, %b
|
|
|
|
br i1 %cmp, label %if.then, label %if.else
|
|
|
|
|
|
|
|
if.then:
|
|
|
|
tail call void @dummy1()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.else:
|
|
|
|
%cmp1 = icmp ugt i32 %a, %b
|
|
|
|
br i1 %cmp1, label %if.then2, label %if.end3
|
|
|
|
|
|
|
|
if.then2:
|
|
|
|
tail call void @dummy2()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.end3:
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
define void @func18(i32 zeroext %a, i32 zeroext %b) {
|
|
|
|
; CHECK-LABEL: @func18
|
|
|
|
; CHECK: cmp
|
|
|
|
; CHECK-NOT: cmp
|
|
|
|
; CHECK: blr
|
|
|
|
entry:
|
|
|
|
%cmp = icmp ult i32 %b, %a
|
|
|
|
br i1 %cmp, label %if.then, label %if.else
|
|
|
|
|
|
|
|
if.then:
|
|
|
|
tail call void @dummy1()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.else:
|
|
|
|
%cmp1 = icmp eq i32 %a, %b
|
|
|
|
br i1 %cmp1, label %if.then2, label %if.end3
|
|
|
|
|
|
|
|
if.then2:
|
|
|
|
tail call void @dummy2()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.end3:
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
define void @func19(i64 %a, i64 %b) {
|
|
|
|
; CHECK-LABEL: @func19
|
|
|
|
; CHECK: cmp
|
|
|
|
; CHECK-NOT: cmp
|
|
|
|
; CHECK: blr
|
|
|
|
entry:
|
|
|
|
%cmp = icmp eq i64 %a, %b
|
|
|
|
br i1 %cmp, label %if.then, label %if.else
|
|
|
|
|
|
|
|
if.then:
|
|
|
|
tail call void @dummy1()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.else:
|
|
|
|
%cmp1 = icmp slt i64 %a, %b
|
|
|
|
br i1 %cmp1, label %if.then2, label %if.end3
|
|
|
|
|
|
|
|
if.then2:
|
|
|
|
tail call void @dummy2()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.end3:
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
define void @func20(i64 %a, i64 %b) {
|
|
|
|
; CHECK-LABEL: @func20
|
|
|
|
; CHECK: cmp
|
|
|
|
; CHECK-NOT: cmp
|
|
|
|
; CHECK: blr
|
|
|
|
entry:
|
|
|
|
%cmp = icmp slt i64 %a, %b
|
|
|
|
br i1 %cmp, label %if.then, label %if.else
|
|
|
|
|
|
|
|
if.then:
|
|
|
|
tail call void @dummy1()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.else:
|
|
|
|
%cmp1 = icmp sgt i64 %a, %b
|
|
|
|
br i1 %cmp1, label %if.then2, label %if.end3
|
|
|
|
|
|
|
|
if.then2:
|
|
|
|
tail call void @dummy2()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.end3:
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
define void @func21(i64 %a, i64 %b) {
|
|
|
|
; CHECK-LABEL: @func21
|
|
|
|
; CHECK: cmp
|
|
|
|
; CHECK-NOT: cmp
|
|
|
|
; CHECK: blr
|
|
|
|
entry:
|
|
|
|
%cmp = icmp slt i64 %b, %a
|
|
|
|
br i1 %cmp, label %if.then, label %if.else
|
|
|
|
|
|
|
|
if.then:
|
|
|
|
tail call void @dummy1()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.else:
|
|
|
|
%cmp1 = icmp eq i64 %a, %b
|
|
|
|
br i1 %cmp1, label %if.then2, label %if.end3
|
|
|
|
|
|
|
|
if.then2:
|
|
|
|
tail call void @dummy2()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.end3:
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
define void @func22(i64 %a, i64 %b) {
|
|
|
|
; CHECK-LABEL: @func22
|
|
|
|
; CHECK: cmp
|
|
|
|
; CHECK-NOT: cmp
|
|
|
|
; CHECK: blr
|
|
|
|
entry:
|
|
|
|
%cmp = icmp eq i64 %a, %b
|
|
|
|
br i1 %cmp, label %if.then, label %if.else
|
|
|
|
|
|
|
|
if.then:
|
|
|
|
tail call void @dummy1()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.else:
|
|
|
|
%cmp1 = icmp ult i64 %a, %b
|
|
|
|
br i1 %cmp1, label %if.then2, label %if.end3
|
|
|
|
|
|
|
|
if.then2:
|
|
|
|
tail call void @dummy2()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.end3:
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
define void @func23(i64 %a, i64 %b) {
|
|
|
|
; CHECK-LABEL: @func23
|
|
|
|
; CHECK: cmp
|
|
|
|
; CHECK-NOT: cmp
|
|
|
|
; CHECK: blr
|
|
|
|
entry:
|
|
|
|
%cmp = icmp ult i64 %a, %b
|
|
|
|
br i1 %cmp, label %if.then, label %if.else
|
|
|
|
|
|
|
|
if.then:
|
|
|
|
tail call void @dummy1()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.else:
|
|
|
|
%cmp1 = icmp ugt i64 %a, %b
|
|
|
|
br i1 %cmp1, label %if.then2, label %if.end3
|
|
|
|
|
|
|
|
if.then2:
|
|
|
|
tail call void @dummy2()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.end3:
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
define void @func24(i64 %a, i64 %b) {
|
|
|
|
; CHECK-LABEL: @func24
|
|
|
|
; CHECK: cmp
|
|
|
|
; CHECK-NOT: cmp
|
|
|
|
; CHECK: blr
|
|
|
|
entry:
|
|
|
|
%cmp = icmp ult i64 %b, %a
|
|
|
|
br i1 %cmp, label %if.then, label %if.else
|
|
|
|
|
|
|
|
if.then:
|
|
|
|
tail call void @dummy1()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.else:
|
|
|
|
%cmp1 = icmp eq i64 %a, %b
|
|
|
|
br i1 %cmp1, label %if.then2, label %if.end3
|
|
|
|
|
|
|
|
if.then2:
|
|
|
|
tail call void @dummy2()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.end3:
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
define void @func25(i64 %a, i64 %b) {
|
|
|
|
; CHECK-LABEL: @func25
|
|
|
|
; CHECK: cmp
|
|
|
|
; CHECK-NOT: cmp
|
|
|
|
; CHECK: blr
|
|
|
|
entry:
|
|
|
|
%cmp = icmp slt i64 %b, %a
|
|
|
|
br i1 %cmp, label %if.then, label %if.else, !prof !1
|
|
|
|
|
|
|
|
if.then:
|
|
|
|
tail call void @dummy1()
|
|
|
|
br label %if.end6
|
|
|
|
|
|
|
|
if.else:
|
|
|
|
%cmp2 = icmp eq i64 %a, %b
|
|
|
|
br i1 %cmp2, label %if.then4, label %if.else5
|
|
|
|
|
|
|
|
if.then4:
|
|
|
|
tail call void @dummy2()
|
|
|
|
br label %if.end6
|
|
|
|
|
|
|
|
if.else5:
|
|
|
|
tail call void @dummy3()
|
|
|
|
br label %if.end6
|
|
|
|
|
|
|
|
if.end6:
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
define void @func26(i32 signext %a) {
|
|
|
|
; CHECK-LABEL: @func26
|
|
|
|
; CHECK: cmp
|
|
|
|
; CHECK-NOT: cmp
|
|
|
|
; CHECK: blr
|
|
|
|
entry:
|
|
|
|
%cmp = icmp sgt i32 %a, 0
|
|
|
|
br i1 %cmp, label %if.then, label %if.else, !prof !2
|
|
|
|
|
|
|
|
if.then:
|
|
|
|
tail call void @dummy1()
|
|
|
|
br label %if.end9
|
|
|
|
|
|
|
|
if.else:
|
|
|
|
%cmp2 = icmp eq i32 %a, 0
|
|
|
|
br i1 %cmp2, label %if.then7, label %if.else8, !prof !2
|
|
|
|
|
|
|
|
if.then7:
|
|
|
|
tail call void @dummy2()
|
|
|
|
br label %if.end9
|
|
|
|
|
|
|
|
if.else8:
|
|
|
|
tail call void @dummy3()
|
|
|
|
br label %if.end9
|
|
|
|
|
|
|
|
if.end9:
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
@g1 = external local_unnamed_addr global i32, align 4
|
|
|
|
@g2 = external local_unnamed_addr global i32, align 4
|
|
|
|
|
|
|
|
define void @func27(i32 signext %a) {
|
|
|
|
; CHECK-LABEL: @func27
|
|
|
|
; CHECK: cmp
|
|
|
|
; CHECK: beq
|
|
|
|
; CHECK-NOT: cmp
|
|
|
|
; CHECK: bgelr
|
|
|
|
; CHECK: blr
|
|
|
|
entry:
|
|
|
|
%cmp = icmp eq i32 %a, 0
|
|
|
|
br i1 %cmp, label %if.end3.sink.split, label %if.else
|
|
|
|
|
|
|
|
if.else:
|
|
|
|
%cmp1 = icmp slt i32 %a, 0
|
|
|
|
br i1 %cmp1, label %if.end3.sink.split, label %if.end
|
|
|
|
|
|
|
|
if.end3.sink.split:
|
|
|
|
%g2.sink = phi i32* [ @g2, %if.else ], [ @g1, %entry ]
|
|
|
|
store i32 0, i32* %g2.sink, align 4
|
|
|
|
br label %if.end
|
|
|
|
|
|
|
|
if.end:
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
2017-09-28 16:38:19 +08:00
|
|
|
; partially redundant case
|
|
|
|
define void @func28(i32 signext %a) {
|
|
|
|
; CHECK-LABEL: @func28
|
|
|
|
; CHECK: cmplwi [[REG1:[0-9]+]], [[REG2:[0-9]+]]
|
2019-08-30 03:03:58 +08:00
|
|
|
; CHECK: .[[LABEL2:[A-Z0-9_]+]]:
|
|
|
|
; CHECK: cmpwi [[REG1]], [[REG2]]
|
|
|
|
; CHECK: ble 0, .[[LABEL1:[A-Z0-9_]+]]
|
2017-09-28 16:38:19 +08:00
|
|
|
; CHECK-NOT: cmp
|
2019-08-30 03:03:58 +08:00
|
|
|
; CHECK: bne 0, .[[LABEL2]]
|
2017-09-28 16:38:19 +08:00
|
|
|
; CHECK: bl dummy1
|
2019-08-30 03:03:58 +08:00
|
|
|
; CHECK: b .[[LABEL2]]
|
|
|
|
; CHECK: .[[LABEL1]]:
|
2017-09-28 16:38:19 +08:00
|
|
|
; CHECK: blr
|
|
|
|
entry:
|
|
|
|
br label %do.body
|
|
|
|
|
|
|
|
do.body:
|
|
|
|
%a.addr.0 = phi i32 [ %a, %entry ], [ %call, %if.end ]
|
|
|
|
%cmp = icmp eq i32 %a.addr.0, 0
|
|
|
|
br i1 %cmp, label %if.then, label %if.end
|
|
|
|
|
|
|
|
if.then:
|
|
|
|
tail call void @dummy1() #2
|
|
|
|
br label %if.end
|
|
|
|
|
|
|
|
if.end:
|
|
|
|
%call = tail call signext i32 @func(i32 signext %a.addr.0) #2
|
|
|
|
%cmp1 = icmp sgt i32 %call, 0
|
|
|
|
br i1 %cmp1, label %do.body, label %do.end
|
|
|
|
|
|
|
|
do.end:
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
2017-12-20 13:18:19 +08:00
|
|
|
define void @func29(i32 signext %a) {
|
|
|
|
; We cannot merge two compares due to difference in sign extension behaviors.
|
|
|
|
; equivalent C code example:
|
|
|
|
; int a = .. ;
|
|
|
|
; if (a == -1) dummy1();
|
|
|
|
; if (a == (uint16_t)-1) dummy2();
|
|
|
|
|
|
|
|
; CHECK-LABEL: @func29
|
|
|
|
; CHECK: cmp
|
|
|
|
; CHECK: cmp
|
|
|
|
; CHECK: blr
|
|
|
|
entry:
|
|
|
|
%cmp = icmp eq i32 %a, -1
|
|
|
|
br i1 %cmp, label %if.then, label %if.else
|
|
|
|
|
|
|
|
if.then:
|
|
|
|
tail call void @dummy1()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.else:
|
|
|
|
%cmp1 = icmp eq i32 %a, 65535
|
|
|
|
br i1 %cmp1, label %if.then2, label %if.end3
|
|
|
|
|
|
|
|
if.then2:
|
|
|
|
tail call void @dummy2()
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.end3:
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
[PowerPC] eliminate redundant compare instruction
If multiple conditional branches are executed based on the same comparison, we can execute multiple conditional branches based on the result of one comparison on PPC. For example,
if (a == 0) { ... }
else if (a < 0) { ... }
can be executed by one compare and two conditional branches instead of two pairs of a compare and a conditional branch.
This patch identifies a code sequence of the two pairs of a compare and a conditional branch and merge the compares if possible.
To maximize the opportunity, we do canonicalization of code sequence before merging compares.
For the above example, the input for this pass looks like:
cmplwi r3, 0
beq 0, .LBB0_3
cmpwi r3, -1
bgt 0, .LBB0_4
So, before merging two compares, we canonicalize it as
cmpwi r3, 0 ; cmplwi and cmpwi yield same result for beq
beq 0, .LBB0_3
cmpwi r3, 0 ; greather than -1 means greater or equal to 0
bge 0, .LBB0_4
The generated code should be
cmpwi r3, 0
beq 0, .LBB0_3
bge 0, .LBB0_4
Differential Revision: https://reviews.llvm.org/D37211
llvm-svn: 312514
2017-09-05 12:15:17 +08:00
|
|
|
declare void @dummy1()
|
|
|
|
declare void @dummy2()
|
|
|
|
declare void @dummy3()
|
2017-09-28 16:38:19 +08:00
|
|
|
declare signext i32 @func(i32 signext)
|
[PowerPC] eliminate redundant compare instruction
If multiple conditional branches are executed based on the same comparison, we can execute multiple conditional branches based on the result of one comparison on PPC. For example,
if (a == 0) { ... }
else if (a < 0) { ... }
can be executed by one compare and two conditional branches instead of two pairs of a compare and a conditional branch.
This patch identifies a code sequence of the two pairs of a compare and a conditional branch and merge the compares if possible.
To maximize the opportunity, we do canonicalization of code sequence before merging compares.
For the above example, the input for this pass looks like:
cmplwi r3, 0
beq 0, .LBB0_3
cmpwi r3, -1
bgt 0, .LBB0_4
So, before merging two compares, we canonicalize it as
cmpwi r3, 0 ; cmplwi and cmpwi yield same result for beq
beq 0, .LBB0_3
cmpwi r3, 0 ; greather than -1 means greater or equal to 0
bge 0, .LBB0_4
The generated code should be
cmpwi r3, 0
beq 0, .LBB0_3
bge 0, .LBB0_4
Differential Revision: https://reviews.llvm.org/D37211
llvm-svn: 312514
2017-09-05 12:15:17 +08:00
|
|
|
|
|
|
|
!1 = !{!"branch_weights", i32 2000, i32 1}
|
|
|
|
!2 = !{!"branch_weights", i32 1, i32 2000}
|