2012-03-02 23:34:43 +08:00
|
|
|
; RUN: opt -correlated-propagation -S < %s | FileCheck %s
|
|
|
|
|
|
|
|
declare i32 @foo()
|
|
|
|
|
|
|
|
define i32 @test1(i32 %a) nounwind {
|
|
|
|
%a.off = add i32 %a, -8
|
|
|
|
%cmp = icmp ult i32 %a.off, 8
|
|
|
|
br i1 %cmp, label %then, label %else
|
|
|
|
|
|
|
|
then:
|
|
|
|
%dead = icmp eq i32 %a, 7
|
|
|
|
br i1 %dead, label %end, label %else
|
|
|
|
|
|
|
|
else:
|
|
|
|
ret i32 1
|
|
|
|
|
|
|
|
end:
|
|
|
|
ret i32 2
|
|
|
|
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test1(
|
2012-03-02 23:34:43 +08:00
|
|
|
; CHECK: then:
|
|
|
|
; CHECK-NEXT: br i1 false, label %end, label %else
|
|
|
|
}
|
|
|
|
|
|
|
|
define i32 @test2(i32 %a) nounwind {
|
|
|
|
%a.off = add i32 %a, -8
|
|
|
|
%cmp = icmp ult i32 %a.off, 8
|
|
|
|
br i1 %cmp, label %then, label %else
|
|
|
|
|
|
|
|
then:
|
|
|
|
%dead = icmp ugt i32 %a, 15
|
|
|
|
br i1 %dead, label %end, label %else
|
|
|
|
|
|
|
|
else:
|
|
|
|
ret i32 1
|
|
|
|
|
|
|
|
end:
|
|
|
|
ret i32 2
|
|
|
|
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test2(
|
2012-03-02 23:34:43 +08:00
|
|
|
; CHECK: then:
|
|
|
|
; CHECK-NEXT: br i1 false, label %end, label %else
|
|
|
|
}
|
2012-05-19 01:44:58 +08:00
|
|
|
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test3(
|
2012-05-19 01:44:58 +08:00
|
|
|
define i32 @test3(i32 %c) nounwind {
|
|
|
|
%cmp = icmp slt i32 %c, 2
|
|
|
|
br i1 %cmp, label %if.then, label %if.end
|
|
|
|
|
|
|
|
if.then:
|
|
|
|
ret i32 1
|
|
|
|
|
|
|
|
if.end:
|
|
|
|
%cmp1 = icmp slt i32 %c, 3
|
|
|
|
br i1 %cmp1, label %if.then2, label %if.end8
|
|
|
|
|
|
|
|
; CHECK: if.then2
|
|
|
|
if.then2:
|
|
|
|
%cmp2 = icmp eq i32 %c, 2
|
|
|
|
; CHECK: br i1 true
|
|
|
|
br i1 %cmp2, label %if.then4, label %if.end6
|
|
|
|
|
|
|
|
; CHECK: if.end6
|
|
|
|
if.end6:
|
|
|
|
ret i32 2
|
|
|
|
|
|
|
|
if.then4:
|
|
|
|
ret i32 3
|
|
|
|
|
|
|
|
if.end8:
|
|
|
|
ret i32 4
|
|
|
|
}
|
2012-05-19 05:02:10 +08:00
|
|
|
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test4(
|
2012-05-19 05:02:10 +08:00
|
|
|
define i32 @test4(i32 %c) nounwind {
|
|
|
|
switch i32 %c, label %sw.default [
|
|
|
|
i32 1, label %sw.bb
|
|
|
|
i32 2, label %sw.bb
|
|
|
|
i32 4, label %sw.bb
|
|
|
|
]
|
|
|
|
|
|
|
|
; CHECK: sw.bb
|
|
|
|
sw.bb:
|
|
|
|
%cmp = icmp sge i32 %c, 1
|
|
|
|
; CHECK: br i1 true
|
|
|
|
br i1 %cmp, label %if.then, label %if.end
|
|
|
|
|
|
|
|
if.then:
|
|
|
|
br label %return
|
|
|
|
|
|
|
|
if.end:
|
|
|
|
br label %return
|
|
|
|
|
|
|
|
sw.default:
|
|
|
|
br label %return
|
|
|
|
|
|
|
|
return:
|
|
|
|
%retval.0 = phi i32 [ 42, %sw.default ], [ 4, %if.then ], [ 9, %if.end ]
|
|
|
|
ret i32 %retval.0
|
|
|
|
}
|
2012-06-28 09:16:18 +08:00
|
|
|
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test5(
|
2012-06-28 09:16:18 +08:00
|
|
|
define i1 @test5(i32 %c) nounwind {
|
|
|
|
%cmp = icmp slt i32 %c, 5
|
|
|
|
br i1 %cmp, label %if.then, label %if.end
|
|
|
|
|
|
|
|
if.then:
|
|
|
|
%cmp1 = icmp eq i32 %c, 4
|
|
|
|
br i1 %cmp1, label %if.end, label %if.end8
|
|
|
|
|
|
|
|
if.end:
|
|
|
|
ret i1 true
|
|
|
|
|
|
|
|
if.end8:
|
|
|
|
%cmp2 = icmp eq i32 %c, 3
|
|
|
|
%cmp3 = icmp eq i32 %c, 4
|
|
|
|
%cmp4 = icmp eq i32 %c, 6
|
|
|
|
; CHECK: %or = or i1 false, false
|
|
|
|
%or = or i1 %cmp3, %cmp4
|
|
|
|
; CHECK: ret i1 %cmp2
|
|
|
|
ret i1 %cmp2
|
|
|
|
}
|
|
|
|
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test6(
|
2012-06-28 09:16:18 +08:00
|
|
|
define i1 @test6(i32 %c) nounwind {
|
|
|
|
%cmp = icmp ule i32 %c, 7
|
|
|
|
br i1 %cmp, label %if.then, label %if.end
|
|
|
|
|
|
|
|
if.then:
|
|
|
|
; CHECK: icmp eq i32 %c, 6
|
|
|
|
; CHECK: br i1
|
|
|
|
switch i32 %c, label %if.end [
|
|
|
|
i32 6, label %sw.bb
|
|
|
|
i32 8, label %sw.bb
|
|
|
|
]
|
|
|
|
|
|
|
|
if.end:
|
|
|
|
ret i1 true
|
|
|
|
|
|
|
|
sw.bb:
|
|
|
|
%cmp2 = icmp eq i32 %c, 6
|
|
|
|
; CHECK: ret i1 true
|
|
|
|
ret i1 %cmp2
|
|
|
|
}
|
2012-06-29 00:13:37 +08:00
|
|
|
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test7(
|
2012-06-29 00:13:37 +08:00
|
|
|
define i1 @test7(i32 %c) nounwind {
|
|
|
|
entry:
|
|
|
|
switch i32 %c, label %sw.default [
|
|
|
|
i32 6, label %sw.bb
|
|
|
|
i32 7, label %sw.bb
|
|
|
|
]
|
|
|
|
|
|
|
|
sw.bb:
|
|
|
|
ret i1 true
|
|
|
|
|
|
|
|
sw.default:
|
|
|
|
%cmp5 = icmp eq i32 %c, 5
|
|
|
|
%cmp6 = icmp eq i32 %c, 6
|
|
|
|
%cmp7 = icmp eq i32 %c, 7
|
|
|
|
%cmp8 = icmp eq i32 %c, 8
|
|
|
|
; CHECK: %or = or i1 %cmp5, false
|
|
|
|
%or = or i1 %cmp5, %cmp6
|
|
|
|
; CHECK: %or2 = or i1 false, %cmp8
|
|
|
|
%or2 = or i1 %cmp7, %cmp8
|
|
|
|
ret i1 false
|
|
|
|
}
|
[LVI/CVP] Teach LVI about range metadata
Somewhat shockingly for an analysis pass which is computing constant ranges, LVI did not understand the ranges provided by range metadata.
As part of this change, I included a change to CVP primarily because doing so made it much easier to write small self contained test cases. CVP was previously only handling the non-local operand case, but given that LVI can sometimes figure out information about instructions standalone, I don't see any reason to restrict this. There could possibly be a compile time impact from this, but I suspect it should be minimal. If anyone has an example which substaintially regresses, please let me know. I could restrict the block local handling to ICmps feeding Terminator instructions if needed.
Note that this patch continues a somewhat bad practice in LVI. In many cases, we know facts about values, and separate context sensitive facts about values. LVI makes no effort to distinguish and will frequently cache the same value fact repeatedly for different contexts. I would like to change this, but that's a large enough change that I want it to go in separately with clear documentation of what's changing. Other examples of this include the non-null handling, and arguments.
As a meta comment: the entire motivation of this change was being able to write smaller (aka reasonable sized) test cases for a future patch teaching LVI about select instructions.
Differential Revision: http://reviews.llvm.org/D13543
llvm-svn: 251606
2015-10-29 11:57:17 +08:00
|
|
|
|
|
|
|
define i1 @test8(i64* %p) {
|
|
|
|
; CHECK-LABEL: @test8
|
|
|
|
; CHECK: ret i1 false
|
|
|
|
%a = load i64, i64* %p, !range !{i64 4, i64 255}
|
|
|
|
%res = icmp eq i64 %a, 0
|
|
|
|
ret i1 %res
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test9(i64* %p) {
|
|
|
|
; CHECK-LABEL: @test9
|
|
|
|
; CHECK: ret i1 true
|
|
|
|
%a = load i64, i64* %p, !range !{i64 0, i64 1}
|
|
|
|
%res = icmp eq i64 %a, 0
|
|
|
|
ret i1 %res
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test10(i64* %p) {
|
|
|
|
; CHECK-LABEL: @test10
|
|
|
|
; CHECK: ret i1 false
|
|
|
|
%a = load i64, i64* %p, !range !{i64 4, i64 8, i64 15, i64 20}
|
|
|
|
%res = icmp eq i64 %a, 0
|
|
|
|
ret i1 %res
|
|
|
|
}
|
2016-03-05 06:27:39 +08:00
|
|
|
|
|
|
|
@g = external global i32
|
|
|
|
|
|
|
|
define i1 @test11() {
|
|
|
|
; CHECK: @test11
|
|
|
|
; CHECK: ret i1 true
|
|
|
|
%positive = load i32, i32* @g, !range !{i32 1, i32 2048}
|
|
|
|
%add = add i32 %positive, 1
|
|
|
|
%test = icmp sgt i32 %add, 0
|
|
|
|
br label %next
|
|
|
|
|
|
|
|
next:
|
|
|
|
ret i1 %test
|
|
|
|
}
|
2016-08-09 22:50:08 +08:00
|
|
|
|
|
|
|
define i32 @test12(i32 %a, i32 %b) {
|
|
|
|
; CHECK-LABEL: @test12(
|
|
|
|
; CHECK: then:
|
|
|
|
; CHECK-NEXT: br i1 false, label %end, label %else
|
|
|
|
%cmp = icmp ult i32 %a, %b
|
|
|
|
br i1 %cmp, label %then, label %else
|
|
|
|
|
|
|
|
then:
|
|
|
|
%dead = icmp eq i32 %a, -1
|
|
|
|
br i1 %dead, label %end, label %else
|
|
|
|
|
|
|
|
else:
|
|
|
|
ret i32 1
|
|
|
|
|
|
|
|
end:
|
|
|
|
ret i32 2
|
|
|
|
}
|
|
|
|
|
|
|
|
define i32 @test12_swap(i32 %a, i32 %b) {
|
|
|
|
; CHECK-LABEL: @test12_swap(
|
|
|
|
; CHECK: then:
|
|
|
|
; CHECK-NEXT: br i1 false, label %end, label %else
|
|
|
|
%cmp = icmp ugt i32 %b, %a
|
|
|
|
br i1 %cmp, label %then, label %else
|
|
|
|
|
|
|
|
then:
|
|
|
|
%dead = icmp eq i32 %a, -1
|
|
|
|
br i1 %dead, label %end, label %else
|
|
|
|
|
|
|
|
else:
|
|
|
|
ret i32 1
|
|
|
|
|
|
|
|
end:
|
|
|
|
ret i32 2
|
|
|
|
}
|
|
|
|
|
|
|
|
define i32 @test12_neg(i32 %a, i32 %b) {
|
|
|
|
; The same as @test12 but the second check is on the false path
|
|
|
|
; CHECK-LABEL: @test12_neg(
|
|
|
|
; CHECK: else:
|
|
|
|
; CHECK-NEXT: %alive = icmp eq i32 %a, -1
|
|
|
|
%cmp = icmp ult i32 %a, %b
|
|
|
|
br i1 %cmp, label %then, label %else
|
|
|
|
|
|
|
|
else:
|
|
|
|
%alive = icmp eq i32 %a, -1
|
|
|
|
br i1 %alive, label %end, label %then
|
|
|
|
|
|
|
|
then:
|
|
|
|
ret i32 1
|
|
|
|
|
|
|
|
end:
|
|
|
|
ret i32 2
|
|
|
|
}
|
|
|
|
|
|
|
|
define i32 @test12_signed(i32 %a, i32 %b) {
|
|
|
|
; The same as @test12 but with signed comparison
|
|
|
|
; CHECK-LABEL: @test12_signed(
|
|
|
|
; CHECK: then:
|
|
|
|
; CHECK-NEXT: br i1 false, label %end, label %else
|
|
|
|
%cmp = icmp slt i32 %a, %b
|
|
|
|
br i1 %cmp, label %then, label %else
|
|
|
|
|
|
|
|
then:
|
|
|
|
%dead = icmp eq i32 %a, 2147483647
|
|
|
|
br i1 %dead, label %end, label %else
|
|
|
|
|
|
|
|
else:
|
|
|
|
ret i32 1
|
|
|
|
|
|
|
|
end:
|
|
|
|
ret i32 2
|
|
|
|
}
|
|
|
|
|
|
|
|
define i32 @test13(i32 %a, i32 %b) {
|
|
|
|
; CHECK-LABEL: @test13(
|
|
|
|
; CHECK: then:
|
|
|
|
; CHECK-NEXT: br i1 false, label %end, label %else
|
|
|
|
%a.off = add i32 %a, -8
|
|
|
|
%cmp = icmp ult i32 %a.off, %b
|
|
|
|
br i1 %cmp, label %then, label %else
|
|
|
|
|
|
|
|
then:
|
|
|
|
%dead = icmp eq i32 %a, 7
|
|
|
|
br i1 %dead, label %end, label %else
|
|
|
|
|
|
|
|
else:
|
|
|
|
ret i32 1
|
|
|
|
|
|
|
|
end:
|
|
|
|
ret i32 2
|
|
|
|
}
|
|
|
|
|
|
|
|
define i32 @test13_swap(i32 %a, i32 %b) {
|
|
|
|
; CHECK-LABEL: @test13_swap(
|
|
|
|
; CHECK: then:
|
|
|
|
; CHECK-NEXT: br i1 false, label %end, label %else
|
|
|
|
%a.off = add i32 %a, -8
|
|
|
|
%cmp = icmp ugt i32 %b, %a.off
|
|
|
|
br i1 %cmp, label %then, label %else
|
|
|
|
|
|
|
|
then:
|
|
|
|
%dead = icmp eq i32 %a, 7
|
|
|
|
br i1 %dead, label %end, label %else
|
|
|
|
|
|
|
|
else:
|
|
|
|
ret i32 1
|
|
|
|
|
|
|
|
end:
|
|
|
|
ret i32 2
|
|
|
|
}
|
2016-08-12 18:05:11 +08:00
|
|
|
|
|
|
|
define i1 @test14_slt(i32 %a) {
|
|
|
|
; CHECK-LABEL: @test14_slt(
|
|
|
|
; CHECK: then:
|
|
|
|
; CHECK-NEXT: %result = or i1 false, false
|
|
|
|
%a.off = add i32 %a, -8
|
|
|
|
%cmp = icmp slt i32 %a.off, 8
|
|
|
|
br i1 %cmp, label %then, label %else
|
|
|
|
|
|
|
|
then:
|
|
|
|
%dead.1 = icmp eq i32 %a, -2147483641
|
|
|
|
%dead.2 = icmp eq i32 %a, 16
|
|
|
|
%result = or i1 %dead.1, %dead.2
|
|
|
|
ret i1 %result
|
|
|
|
|
|
|
|
else:
|
|
|
|
ret i1 false
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test14_sle(i32 %a) {
|
|
|
|
; CHECK-LABEL: @test14_sle(
|
|
|
|
; CHECK: then:
|
|
|
|
; CHECK-NEXT: %alive = icmp eq i32 %a, 16
|
|
|
|
; CHECK-NEXT: %result = or i1 false, %alive
|
|
|
|
%a.off = add i32 %a, -8
|
|
|
|
%cmp = icmp sle i32 %a.off, 8
|
|
|
|
br i1 %cmp, label %then, label %else
|
|
|
|
|
|
|
|
then:
|
|
|
|
%dead = icmp eq i32 %a, -2147483641
|
|
|
|
%alive = icmp eq i32 %a, 16
|
|
|
|
%result = or i1 %dead, %alive
|
|
|
|
ret i1 %result
|
|
|
|
|
|
|
|
else:
|
|
|
|
ret i1 false
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test14_sgt(i32 %a) {
|
|
|
|
; CHECK-LABEL: @test14_sgt(
|
|
|
|
; CHECK: then:
|
|
|
|
; CHECK-NEXT: %result = or i1 false, false
|
|
|
|
%a.off = add i32 %a, -8
|
|
|
|
%cmp = icmp sgt i32 %a.off, 8
|
|
|
|
br i1 %cmp, label %then, label %else
|
|
|
|
|
|
|
|
then:
|
|
|
|
%dead.1 = icmp eq i32 %a, -2147483640
|
|
|
|
%dead.2 = icmp eq i32 %a, 16
|
|
|
|
%result = or i1 %dead.1, %dead.2
|
|
|
|
ret i1 %result
|
|
|
|
|
|
|
|
else:
|
|
|
|
ret i1 false
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test14_sge(i32 %a) {
|
|
|
|
; CHECK-LABEL: @test14_sge(
|
|
|
|
; CHECK: then:
|
|
|
|
; CHECK-NEXT: %alive = icmp eq i32 %a, 16
|
|
|
|
; CHECK-NEXT: %result = or i1 false, %alive
|
|
|
|
%a.off = add i32 %a, -8
|
|
|
|
%cmp = icmp sge i32 %a.off, 8
|
|
|
|
br i1 %cmp, label %then, label %else
|
|
|
|
|
|
|
|
then:
|
|
|
|
%dead = icmp eq i32 %a, -2147483640
|
|
|
|
%alive = icmp eq i32 %a, 16
|
|
|
|
%result = or i1 %dead, %alive
|
|
|
|
ret i1 %result
|
|
|
|
|
|
|
|
else:
|
|
|
|
ret i1 false
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test14_ule(i32 %a) {
|
|
|
|
; CHECK-LABEL: @test14_ule(
|
|
|
|
; CHECK: then:
|
|
|
|
; CHECK-NEXT: %alive = icmp eq i32 %a, 16
|
|
|
|
; CHECK-NEXT: %result = or i1 false, %alive
|
|
|
|
%a.off = add i32 %a, -8
|
|
|
|
%cmp = icmp ule i32 %a.off, 8
|
|
|
|
br i1 %cmp, label %then, label %else
|
|
|
|
|
|
|
|
then:
|
|
|
|
%dead = icmp eq i32 %a, 7
|
|
|
|
%alive = icmp eq i32 %a, 16
|
|
|
|
%result = or i1 %dead, %alive
|
|
|
|
ret i1 %result
|
|
|
|
|
|
|
|
else:
|
|
|
|
ret i1 false
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test14_ugt(i32 %a) {
|
|
|
|
; CHECK-LABEL: @test14_ugt(
|
|
|
|
; CHECK: then:
|
|
|
|
; CHECK-NEXT: %result = or i1 false, false
|
|
|
|
%a.off = add i32 %a, -8
|
|
|
|
%cmp = icmp ugt i32 %a.off, 8
|
|
|
|
br i1 %cmp, label %then, label %else
|
|
|
|
|
|
|
|
then:
|
|
|
|
%dead.1 = icmp eq i32 %a, 8
|
|
|
|
%dead.2 = icmp eq i32 %a, 16
|
|
|
|
%result = or i1 %dead.1, %dead.2
|
|
|
|
ret i1 %result
|
|
|
|
|
|
|
|
else:
|
|
|
|
ret i1 false
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test14_uge(i32 %a) {
|
|
|
|
; CHECK-LABEL: @test14_uge(
|
|
|
|
; CHECK: then:
|
|
|
|
; CHECK-NEXT: %alive = icmp eq i32 %a, 16
|
|
|
|
; CHECK-NEXT: %result = or i1 false, %alive
|
|
|
|
%a.off = add i32 %a, -8
|
|
|
|
%cmp = icmp uge i32 %a.off, 8
|
|
|
|
br i1 %cmp, label %then, label %else
|
|
|
|
|
|
|
|
then:
|
|
|
|
%dead = icmp eq i32 %a, 8
|
|
|
|
%alive = icmp eq i32 %a, 16
|
|
|
|
%result = or i1 %dead, %alive
|
|
|
|
ret i1 %result
|
|
|
|
|
|
|
|
else:
|
|
|
|
ret i1 false
|
|
|
|
}
|
2016-08-12 18:14:11 +08:00
|
|
|
|
|
|
|
@limit = external global i32
|
|
|
|
define i1 @test15(i32 %a) {
|
|
|
|
; CHECK-LABEL: @test15(
|
|
|
|
; CHECK: then:
|
|
|
|
; CHECK-NEXT: ret i1 false
|
|
|
|
%limit = load i32, i32* @limit, !range !{i32 0, i32 256}
|
|
|
|
%cmp = icmp ult i32 %a, %limit
|
|
|
|
br i1 %cmp, label %then, label %else
|
|
|
|
|
|
|
|
then:
|
|
|
|
%result = icmp eq i32 %a, 255
|
|
|
|
ret i1 %result
|
|
|
|
|
|
|
|
else:
|
|
|
|
ret i1 false
|
|
|
|
}
|
2017-08-04 05:11:30 +08:00
|
|
|
|
|
|
|
define i32 @test16(i8 %a) {
|
|
|
|
entry:
|
|
|
|
%b = zext i8 %a to i32
|
|
|
|
br label %dispatch
|
|
|
|
|
|
|
|
dispatch:
|
|
|
|
%cmp = icmp eq i8 %a, 93
|
|
|
|
br i1 %cmp, label %target93, label %dispatch
|
|
|
|
|
|
|
|
; CHECK-LABEL: @test16(
|
|
|
|
; CHECK: target93:
|
|
|
|
; CHECK-NEXT: ret i32 93
|
|
|
|
target93:
|
|
|
|
ret i32 %b
|
|
|
|
}
|
|
|
|
|
|
|
|
define i32 @test16_i1(i1 %a) {
|
|
|
|
entry:
|
|
|
|
%b = zext i1 %a to i32
|
|
|
|
br label %dispatch
|
|
|
|
|
|
|
|
dispatch:
|
|
|
|
br i1 %a, label %true, label %dispatch
|
|
|
|
|
|
|
|
; CHECK-LABEL: @test16_i1(
|
|
|
|
; CHECK: true:
|
|
|
|
; CHECK-NEXT: ret i32 1
|
|
|
|
true:
|
|
|
|
ret i32 %b
|
|
|
|
}
|
|
|
|
|
|
|
|
define i8 @test17(i8 %a) {
|
|
|
|
entry:
|
|
|
|
%c = add i8 %a, 3
|
|
|
|
br label %dispatch
|
|
|
|
|
|
|
|
dispatch:
|
|
|
|
%cmp = icmp eq i8 %a, 93
|
|
|
|
br i1 %cmp, label %target93, label %dispatch
|
|
|
|
|
|
|
|
; CHECK-LABEL: @test17(
|
|
|
|
; CHECK: target93:
|
|
|
|
; CHECK-NEXT: ret i8 96
|
|
|
|
target93:
|
|
|
|
ret i8 %c
|
|
|
|
}
|
|
|
|
|
|
|
|
define i8 @test17_2(i8 %a) {
|
|
|
|
entry:
|
|
|
|
%c = add i8 %a, %a
|
|
|
|
br label %dispatch
|
|
|
|
|
|
|
|
dispatch:
|
|
|
|
%cmp = icmp eq i8 %a, 93
|
|
|
|
br i1 %cmp, label %target93, label %dispatch
|
|
|
|
|
|
|
|
; CHECK-LABEL: @test17_2(
|
|
|
|
; CHECK: target93:
|
|
|
|
; CHECK-NEXT: ret i8 -70
|
|
|
|
target93:
|
|
|
|
ret i8 %c
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test17_i1(i1 %a) {
|
|
|
|
entry:
|
|
|
|
%c = and i1 %a, true
|
|
|
|
br label %dispatch
|
|
|
|
|
|
|
|
dispatch:
|
|
|
|
br i1 %a, label %true, label %dispatch
|
|
|
|
|
|
|
|
; CHECK-LABEL: @test17_i1(
|
|
|
|
; CHECK: true:
|
|
|
|
; CHECK-NEXT: ret i1 true
|
|
|
|
true:
|
|
|
|
ret i1 %c
|
|
|
|
}
|
|
|
|
|
|
|
|
define i32 @test18(i8 %a) {
|
|
|
|
entry:
|
|
|
|
%b = zext i8 %a to i32
|
|
|
|
br label %dispatch
|
|
|
|
|
|
|
|
dispatch:
|
|
|
|
switch i8 %a, label %dispatch [
|
|
|
|
i8 93, label %target93
|
|
|
|
i8 -111, label %dispatch
|
|
|
|
]
|
|
|
|
|
|
|
|
; CHECK-LABEL: @test18(
|
|
|
|
; CHECK: target93:
|
|
|
|
; CHECK-NEXT: ret i32 93
|
|
|
|
target93:
|
|
|
|
ret i32 %b
|
|
|
|
}
|
|
|
|
|
|
|
|
define i8 @test19(i8 %a) {
|
|
|
|
entry:
|
|
|
|
%c = add i8 %a, 3
|
|
|
|
br label %dispatch
|
|
|
|
|
|
|
|
dispatch:
|
|
|
|
switch i8 %a, label %dispatch [
|
|
|
|
i8 93, label %target93
|
|
|
|
i8 -111, label %dispatch
|
|
|
|
]
|
|
|
|
|
|
|
|
; CHECK-LABEL: @test19(
|
|
|
|
; CHECK: target93:
|
|
|
|
; CHECK-NEXT: ret i8 96
|
|
|
|
target93:
|
|
|
|
ret i8 %c
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test20(i64 %a) {
|
|
|
|
entry:
|
|
|
|
%b = and i64 %a, 7
|
|
|
|
br label %dispatch
|
|
|
|
|
|
|
|
dispatch:
|
|
|
|
switch i64 %a, label %default [
|
|
|
|
i64 0, label %exit2
|
|
|
|
i64 -2147483647, label %exit2
|
|
|
|
]
|
|
|
|
|
|
|
|
default:
|
|
|
|
%c = icmp eq i64 %b, 0
|
|
|
|
br label %exit
|
|
|
|
|
|
|
|
exit:
|
|
|
|
; Negative test. Shouldn't be incorrectly optimized to "ret i1 false".
|
|
|
|
; CHECK-LABEL: @test20(
|
|
|
|
; CHECK: exit:
|
|
|
|
; CHECK-NOT: ret i1 false
|
|
|
|
; CHECK: exit2:
|
|
|
|
ret i1 %c
|
|
|
|
|
|
|
|
exit2:
|
|
|
|
ret i1 false
|
|
|
|
}
|