summaryrefslogtreecommitdiffstats
path: root/test/Transforms/InstCombine
diff options
context:
space:
mode:
Diffstat (limited to 'test/Transforms/InstCombine')
-rw-r--r--test/Transforms/InstCombine/2003-08-12-AllocaNonNull.ll3
-rw-r--r--test/Transforms/InstCombine/2006-04-28-ShiftShiftLongLong.ll2
-rw-r--r--test/Transforms/InstCombine/2007-03-26-BadShiftMask.ll3
-rw-r--r--test/Transforms/InstCombine/2008-11-20-DivMulRem.ll43
-rw-r--r--test/Transforms/InstCombine/2010-11-01-lshr-mask.ll46
-rw-r--r--test/Transforms/InstCombine/2010-11-21-SizeZeroTypeGEP.ll17
-rw-r--r--test/Transforms/InstCombine/2010-11-23-Distributed.ll23
-rw-r--r--test/Transforms/InstCombine/2011-02-14-InfLoop.ll19
-rw-r--r--test/Transforms/InstCombine/2011-02-16-InsertelementHang.ll11
-rw-r--r--test/Transforms/InstCombine/add.ll24
-rw-r--r--test/Transforms/InstCombine/add2.ll25
-rw-r--r--test/Transforms/InstCombine/and2.ll18
-rw-r--r--test/Transforms/InstCombine/bit-checks.ll348
-rw-r--r--test/Transforms/InstCombine/bitcast-store.ll21
-rw-r--r--test/Transforms/InstCombine/bitcast-vec-uniform.ll70
-rw-r--r--test/Transforms/InstCombine/cast.ll32
-rw-r--r--test/Transforms/InstCombine/constant-fold-gep.ll19
-rw-r--r--test/Transforms/InstCombine/crash.ll118
-rw-r--r--test/Transforms/InstCombine/div-cmp-overflow.ll8
-rw-r--r--test/Transforms/InstCombine/exact-sdiv.ll52
-rw-r--r--test/Transforms/InstCombine/exact.ll154
-rw-r--r--test/Transforms/InstCombine/extractvalue.ll81
-rw-r--r--test/Transforms/InstCombine/fold-calls.ll19
-rw-r--r--test/Transforms/InstCombine/fold-vector-select.ll13
-rw-r--r--test/Transforms/InstCombine/icmp.ll223
-rw-r--r--test/Transforms/InstCombine/intrinsics.ll19
-rw-r--r--test/Transforms/InstCombine/memcpy.ll19
-rw-r--r--test/Transforms/InstCombine/memset2.ll15
-rw-r--r--test/Transforms/InstCombine/neon-intrinsics.ll25
-rw-r--r--test/Transforms/InstCombine/nsw.ll41
-rw-r--r--test/Transforms/InstCombine/objsize.ll10
-rw-r--r--test/Transforms/InstCombine/or-fcmp.ll28
-rw-r--r--test/Transforms/InstCombine/or.ll48
-rw-r--r--test/Transforms/InstCombine/overflow.ll133
-rw-r--r--test/Transforms/InstCombine/phi.ll125
-rw-r--r--test/Transforms/InstCombine/pr8547.ll26
-rw-r--r--test/Transforms/InstCombine/rem.ll5
-rw-r--r--test/Transforms/InstCombine/select-crash.ll20
-rw-r--r--test/Transforms/InstCombine/select.ll244
-rw-r--r--test/Transforms/InstCombine/sext.ll2
-rw-r--r--test/Transforms/InstCombine/shift.ll50
-rw-r--r--test/Transforms/InstCombine/signext.ll12
-rw-r--r--test/Transforms/InstCombine/sub.ll28
-rw-r--r--test/Transforms/InstCombine/trunc.ll24
-rw-r--r--test/Transforms/InstCombine/vec_demanded_elts-2.ll19
-rw-r--r--test/Transforms/InstCombine/vec_demanded_elts-3.ll14
-rw-r--r--test/Transforms/InstCombine/vec_demanded_elts.ll129
-rw-r--r--test/Transforms/InstCombine/vec_sext.ll22
-rw-r--r--test/Transforms/InstCombine/vec_shuffle.ll23
-rw-r--r--test/Transforms/InstCombine/vector-casts.ll28
-rw-r--r--test/Transforms/InstCombine/xor2.ll2
51 files changed, 2314 insertions, 189 deletions
diff --git a/test/Transforms/InstCombine/2003-08-12-AllocaNonNull.ll b/test/Transforms/InstCombine/2003-08-12-AllocaNonNull.ll
index 6d22754..c02d33c 100644
--- a/test/Transforms/InstCombine/2003-08-12-AllocaNonNull.ll
+++ b/test/Transforms/InstCombine/2003-08-12-AllocaNonNull.ll
@@ -1,7 +1,6 @@
; This testcase can be simplified by "realizing" that alloca can never return
; null.
-; RUN: opt < %s -instcombine -simplifycfg | \
-; RUN: llvm-dis | not grep br
+; RUN: opt < %s -instcombine -simplifycfg -S | not grep br
declare i32 @bitmap_clear(...)
diff --git a/test/Transforms/InstCombine/2006-04-28-ShiftShiftLongLong.ll b/test/Transforms/InstCombine/2006-04-28-ShiftShiftLongLong.ll
index c337ea7..baaafef 100644
--- a/test/Transforms/InstCombine/2006-04-28-ShiftShiftLongLong.ll
+++ b/test/Transforms/InstCombine/2006-04-28-ShiftShiftLongLong.ll
@@ -6,7 +6,7 @@ define i64 @test(i64 %X) {
%Y = shl i64 %X, 16 ; <i64> [#uses=1]
; CHECK: %Y = shl i64 %X, 16
%Z = ashr i64 %Y, 16 ; <i64> [#uses=1]
-; CHECK: %Z = ashr i64 %Y, 16
+; CHECK: %Z = ashr exact i64 %Y, 16
ret i64 %Z
; CHECK: ret i64 %Z
}
diff --git a/test/Transforms/InstCombine/2007-03-26-BadShiftMask.ll b/test/Transforms/InstCombine/2007-03-26-BadShiftMask.ll
index 5bcb543..807efcf 100644
--- a/test/Transforms/InstCombine/2007-03-26-BadShiftMask.ll
+++ b/test/Transforms/InstCombine/2007-03-26-BadShiftMask.ll
@@ -1,7 +1,6 @@
; PR1271
; RUN: opt < %s -instcombine -S | \
-; RUN: grep {ashr i32 %.mp137, 2}
-; END.
+; RUN: grep {ashr exact i32 %.mp137, 2}
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64"
target triple = "i686-pc-linux-gnu"
diff --git a/test/Transforms/InstCombine/2008-11-20-DivMulRem.ll b/test/Transforms/InstCombine/2008-11-20-DivMulRem.ll
index b2774d6..43af190 100644
--- a/test/Transforms/InstCombine/2008-11-20-DivMulRem.ll
+++ b/test/Transforms/InstCombine/2008-11-20-DivMulRem.ll
@@ -1,34 +1,67 @@
-; RUN: opt < %s -instcombine -S > %t
-; RUN: grep urem %t | count 3
-; RUN: grep srem %t | count 1
-; RUN: grep sub %t | count 2
-; RUN: grep add %t | count 1
+; RUN: opt < %s -instcombine -S | FileCheck %s
; PR3103
define i8 @test1(i8 %x, i8 %y) {
+; CHECK: @test1
%A = udiv i8 %x, %y
+; CHECK-NEXT: urem
%B = mul i8 %A, %y
%C = sub i8 %x, %B
ret i8 %C
+; CHECK-NEXT: ret
}
define i8 @test2(i8 %x, i8 %y) {
+; CHECK: @test2
%A = sdiv i8 %x, %y
+; CHECK-NEXT: srem
%B = mul i8 %A, %y
%C = sub i8 %x, %B
ret i8 %C
+; CHECK-NEXT: ret
}
define i8 @test3(i8 %x, i8 %y) {
+; CHECK: @test3
%A = udiv i8 %x, %y
+; CHECK-NEXT: urem
%B = mul i8 %A, %y
%C = sub i8 %B, %x
+; CHECK-NEXT: sub
ret i8 %C
+; CHECK-NEXT: ret
}
define i8 @test4(i8 %x) {
+; CHECK: @test4
%A = udiv i8 %x, 3
+; CHECK-NEXT: urem
%B = mul i8 %A, -3
+; CHECK-NEXT: sub
%C = sub i8 %x, %B
+; CHECK-NEXT: add
ret i8 %C
+; CHECK-NEXT: ret
+}
+
+define i32 @test5(i32 %x, i32 %y) {
+; CHECK: @test5
+; (((X / Y) * Y) / Y) -> X / Y
+ %div = sdiv i32 %x, %y
+; CHECK-NEXT: sdiv
+ %mul = mul i32 %div, %y
+ %r = sdiv i32 %mul, %y
+ ret i32 %r
+; CHECK-NEXT: ret
+}
+
+define i32 @test6(i32 %x, i32 %y) {
+; CHECK: @test6
+; (((X / Y) * Y) / Y) -> X / Y
+ %div = udiv i32 %x, %y
+; CHECK-NEXT: udiv
+ %mul = mul i32 %div, %y
+ %r = udiv i32 %mul, %y
+ ret i32 %r
+; CHECK-NEXT: ret
}
diff --git a/test/Transforms/InstCombine/2010-11-01-lshr-mask.ll b/test/Transforms/InstCombine/2010-11-01-lshr-mask.ll
new file mode 100644
index 0000000..441d5f9
--- /dev/null
+++ b/test/Transforms/InstCombine/2010-11-01-lshr-mask.ll
@@ -0,0 +1,46 @@
+; RUN: opt -instcombine -S < %s | FileCheck %s
+
+; <rdar://problem/8606771>
+; CHECK: @main
+define i32 @main(i32 %argc) nounwind ssp {
+entry:
+ %tmp3151 = trunc i32 %argc to i8
+; CHECK: %tmp3162 = shl i8 %tmp3151, 5
+; CHECK: and i8 %tmp3162, 64
+; CHECK-NOT: shl
+; CHECK-NOT: shr
+ %tmp3161 = or i8 %tmp3151, -17
+ %tmp3162 = and i8 %tmp3151, 122
+ %tmp3163 = xor i8 %tmp3162, -17
+ %tmp4114 = shl i8 %tmp3163, 6
+ %tmp4115 = xor i8 %tmp4114, %tmp3163
+ %tmp4120 = xor i8 %tmp3161, %tmp4115
+ %tmp4126 = lshr i8 %tmp4120, 7
+ %tmp4127 = mul i8 %tmp4126, 64
+ %tmp4086 = zext i8 %tmp4127 to i32
+; CHECK: ret i32
+ ret i32 %tmp4086
+}
+
+; rdar://8739316
+; CHECK: @foo
+define i8 @foo(i8 %arg, i8 %arg1) nounwind {
+bb:
+ %tmp = shl i8 %arg, 7
+ %tmp2 = and i8 %arg1, 84
+ %tmp3 = and i8 %arg1, -118
+ %tmp4 = and i8 %arg1, 33
+ %tmp5 = sub i8 -88, %tmp2
+ %tmp6 = and i8 %tmp5, 84
+ %tmp7 = or i8 %tmp4, %tmp6
+ %tmp8 = xor i8 %tmp, %tmp3
+ %tmp9 = or i8 %tmp7, %tmp8
+ %tmp10 = lshr i8 %tmp8, 7
+ %tmp11 = shl i8 %tmp10, 5
+
+; CHECK: %0 = lshr i8 %tmp8, 2
+; CHECK: %tmp11 = and i8 %0, 32
+
+ %tmp12 = xor i8 %tmp11, %tmp9
+ ret i8 %tmp12
+}
diff --git a/test/Transforms/InstCombine/2010-11-21-SizeZeroTypeGEP.ll b/test/Transforms/InstCombine/2010-11-21-SizeZeroTypeGEP.ll
new file mode 100644
index 0000000..720365c
--- /dev/null
+++ b/test/Transforms/InstCombine/2010-11-21-SizeZeroTypeGEP.ll
@@ -0,0 +1,17 @@
+; RUN: opt < %s -instcombine -S | FileCheck %s
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+
+define {}* @foo({}* %x, i32 %n) {
+; CHECK: @foo
+; CHECK-NOT: getelementptr
+ %p = getelementptr {}* %x, i32 %n
+ ret {}* %p
+}
+
+define i8* @bar(i64 %n, {{}, [0 x {[0 x i8]}]}* %p) {
+; CHECK: @bar
+ %g = getelementptr {{}, [0 x {[0 x i8]}]}* %p, i64 %n, i32 1, i64 %n, i32 0, i64 %n
+; CHECK: %p, i64 0, i32 1, i64 0, i32 0, i64 %n
+ ret i8* %g
+}
diff --git a/test/Transforms/InstCombine/2010-11-23-Distributed.ll b/test/Transforms/InstCombine/2010-11-23-Distributed.ll
new file mode 100644
index 0000000..4f8e8dc
--- /dev/null
+++ b/test/Transforms/InstCombine/2010-11-23-Distributed.ll
@@ -0,0 +1,23 @@
+; RUN: opt < %s -instcombine -S | FileCheck %s
+define i32 @foo(i32 %x, i32 %y) {
+; CHECK: @foo
+ %add = add nsw i32 %y, %x
+ %mul = mul nsw i32 %add, %y
+ %square = mul nsw i32 %y, %y
+ %res = sub i32 %mul, %square
+ ret i32 %res
+; CHECK-NEXT: mul i32 %x, %y
+; CHECK-NEXT: ret i32
+}
+
+define i1 @bar(i64 %x, i64 %y) {
+; CHECK: @bar
+ %a = and i64 %y, %x
+; CHECK: and
+; CHECK-NOT: and
+ %not = xor i64 %a, -1
+ %b = and i64 %y, %not
+ %r = icmp eq i64 %b, 0
+ ret i1 %r
+; CHECK: ret i1
+}
diff --git a/test/Transforms/InstCombine/2011-02-14-InfLoop.ll b/test/Transforms/InstCombine/2011-02-14-InfLoop.ll
new file mode 100644
index 0000000..6d8a7dd
--- /dev/null
+++ b/test/Transforms/InstCombine/2011-02-14-InfLoop.ll
@@ -0,0 +1,19 @@
+; This testcase causes an infinite loop in the instruction combiner,
+; because it changes a pattern and the original pattern is almost
+; identical to the newly-generated pattern.
+; RUN: opt < %s -instcombine -disable-output
+
+;PR PR9216
+
+target triple = "x86_64-unknown-linux-gnu"
+
+define <4 x float> @m_387(i8* noalias nocapture %A, i8* nocapture %B, <4 x i1> %C) nounwind {
+entry:
+ %movcsext20 = sext <4 x i1> %C to <4 x i32>
+ %tmp2389 = xor <4 x i32> %movcsext20, <i32 -1, i32 -1, i32 -1, i32 -1>
+ %movcand25 = and <4 x i32> %tmp2389, <i32 undef, i32 undef, i32 undef, i32 -1>
+ %movcor26 = or <4 x i32> %movcand25, zeroinitializer
+ %L2 = bitcast <4 x i32> %movcor26 to <4 x float>
+ %L3 = shufflevector <4 x float> zeroinitializer, <4 x float> %L2, <4 x i32> <i32 0, i32 1, i32 2, i32 7>
+ ret <4 x float> %L3
+}
diff --git a/test/Transforms/InstCombine/2011-02-16-InsertelementHang.ll b/test/Transforms/InstCombine/2011-02-16-InsertelementHang.ll
new file mode 100644
index 0000000..2f6034e
--- /dev/null
+++ b/test/Transforms/InstCombine/2011-02-16-InsertelementHang.ll
@@ -0,0 +1,11 @@
+; RUN: opt < %s -instcombine -S | FileCheck %s
+; PR9218
+
+%vec2x2 = type { <2 x double>, <2 x double> }
+
+define %vec2x2 @split(double) nounwind alwaysinline {
+; CHECK: @split
+; CHECK: ret %vec2x2 undef
+ %vba = insertelement <2 x double> undef, double %0, i32 2
+ ret <2 x double> %vba, <2 x double> %vba
+}
diff --git a/test/Transforms/InstCombine/add.ll b/test/Transforms/InstCombine/add.ll
index 4719809..a316d06 100644
--- a/test/Transforms/InstCombine/add.ll
+++ b/test/Transforms/InstCombine/add.ll
@@ -275,3 +275,27 @@ define i32 @test36(i32 %a) {
%q = and i32 %z, 1 ; always zero
ret i32 %q
}
+
+define i1 @test37(i32 %a, i32 %b) nounwind readnone {
+ %add = add i32 %a, %b
+ %cmp = icmp eq i32 %add, %a
+ ret i1 %cmp
+}
+
+define i1 @test38(i32 %a, i32 %b) nounwind readnone {
+ %add = add i32 %a, %b
+ %cmp = icmp eq i32 %add, %b
+ ret i1 %cmp
+}
+
+define i1 @test39(i32 %a, i32 %b) nounwind readnone {
+ %add = add i32 %b, %a
+ %cmp = icmp eq i32 %add, %a
+ ret i1 %cmp
+}
+
+define i1 @test40(i32 %a, i32 %b) nounwind readnone {
+ %add = add i32 %b, %a
+ %cmp = icmp eq i32 %add, %b
+ ret i1 %cmp
+}
diff --git a/test/Transforms/InstCombine/add2.ll b/test/Transforms/InstCombine/add2.ll
index 1cbdd3a..c5109c5 100644
--- a/test/Transforms/InstCombine/add2.ll
+++ b/test/Transforms/InstCombine/add2.ll
@@ -1,4 +1,4 @@
-; RUN: opt < %s -instcombine -S | not grep add
+; RUN: opt < %s -instcombine -S | FileCheck %s
define i64 @test1(i64 %A, i32 %B) {
%tmp12 = zext i32 %B to i64
@@ -6,19 +6,38 @@ define i64 @test1(i64 %A, i32 %B) {
%tmp5 = add i64 %tmp3, %A
%tmp6 = and i64 %tmp5, 123
ret i64 %tmp6
+; CHECK: @test1
+; CHECK-NEXT: and i64 %A, 123
+; CHECK-NEXT: ret i64
}
-define i32 @test3(i32 %A) {
+define i32 @test2(i32 %A) {
%B = and i32 %A, 7
%C = and i32 %A, 32
%F = add i32 %B, %C
ret i32 %F
+; CHECK: @test2
+; CHECK-NEXT: and i32 %A, 39
+; CHECK-NEXT: ret i32
}
-define i32 @test4(i32 %A) {
+define i32 @test3(i32 %A) {
%B = and i32 %A, 128
%C = lshr i32 %A, 30
%F = add i32 %B, %C
ret i32 %F
+; CHECK: @test3
+; CHECK-NEXT: and
+; CHECK-NEXT: lshr
+; CHECK-NEXT: or i32 %B, %C
+; CHECK-NEXT: ret i32
+}
+
+define i32 @test4(i32 %A) {
+ %B = add nuw i32 %A, %A
+ ret i32 %B
+; CHECK: @test4
+; CHECK-NEXT: %B = shl nuw i32 %A, 1
+; CHECK-NEXT: ret i32 %B
}
diff --git a/test/Transforms/InstCombine/and2.ll b/test/Transforms/InstCombine/and2.ll
index a5a6574..d898ea3 100644
--- a/test/Transforms/InstCombine/and2.ll
+++ b/test/Transforms/InstCombine/and2.ll
@@ -8,3 +8,21 @@ define i1 @test1(double %X, double %Y) {
ret i1 %bothcond
; CHECK: fcmp ord double %Y, %X
}
+
+define i1 @test2(i1 %X, i1 %Y) {
+ %a = and i1 %X, %Y
+ %b = and i1 %a, %X
+ ret i1 %b
+; CHECK: @test2
+; CHECK-NEXT: and i1 %X, %Y
+; CHECK-NEXT: ret
+}
+
+define i32 @test3(i32 %X, i32 %Y) {
+ %a = and i32 %X, %Y
+ %b = and i32 %Y, %a
+ ret i32 %b
+; CHECK: @test3
+; CHECK-NEXT: and i32 %X, %Y
+; CHECK-NEXT: ret
+}
diff --git a/test/Transforms/InstCombine/bit-checks.ll b/test/Transforms/InstCombine/bit-checks.ll
index d774c09..79a096f 100644
--- a/test/Transforms/InstCombine/bit-checks.ll
+++ b/test/Transforms/InstCombine/bit-checks.ll
@@ -23,4 +23,350 @@ entry:
%or.cond = or i1 %tobool, %tobool3 ; <i1> [#uses=1]
%storemerge = select i1 %or.cond, i32 0, i32 1 ; <i32> [#uses=1]
ret i32 %storemerge
-} \ No newline at end of file
+}
+
+; tests to check combining (icmp eq (A & B), C) & (icmp eq (A & D), E)
+; tests to check if (icmp eq (A & B), 0) is treated like (icmp eq (A & B), B)
+; if B is a single bit constant
+
+; (icmp eq (A & B), 0) & (icmp eq (A & D), 0) -> (icmp eq (A & (B|D)), 0)
+define i32 @main3(i32 %argc, i8** nocapture %argv) nounwind readnone ssp {
+entry:
+ %and = and i32 %argc, 7 ; <i32> [#uses=1]
+ %tobool = icmp eq i32 %and, 0 ; <i1> [#uses=1]
+ %and2 = and i32 %argc, 48 ; <i32> [#uses=1]
+ %tobool3 = icmp eq i32 %and2, 0 ; <i1> [#uses=1]
+ %and.cond = and i1 %tobool, %tobool3 ; <i1> [#uses=1]
+ %storemerge = select i1 %and.cond, i32 0, i32 1 ; <i32> [#uses=1]
+ ret i32 %storemerge
+}
+
+define i32 @main3b(i32 %argc, i8** nocapture %argv) nounwind readnone ssp {
+entry:
+ %and = and i32 %argc, 7 ; <i32> [#uses=1]
+ %tobool = icmp eq i32 %and, 0 ; <i1> [#uses=1]
+ %and2 = and i32 %argc, 16 ; <i32> [#uses=1]
+ %tobool3 = icmp ne i32 %and2, 16 ; <i1> [#uses=1]
+ %and.cond = and i1 %tobool, %tobool3 ; <i1> [#uses=1]
+ %storemerge = select i1 %and.cond, i32 0, i32 1 ; <i32> [#uses=1]
+ ret i32 %storemerge
+}
+
+define i32 @main3e_like(i32 %argc, i32 %argc2, i32 %argc3, i8** nocapture %argv)
+ nounwind readnone ssp {
+entry:
+ %and = and i32 %argc, %argc2 ; <i32> [#uses=1]
+ %tobool = icmp eq i32 %and, 0 ; <i1> [#uses=1]
+ %and2 = and i32 %argc, %argc3 ; <i32> [#uses=1]
+ %tobool3 = icmp eq i32 %and2, 0 ; <i1> [#uses=1]
+ %and.cond = and i1 %tobool, %tobool3 ; <i1> [#uses=1]
+ %storemerge = select i1 %and.cond, i32 0, i32 1 ; <i32> [#uses=1]
+ ret i32 %storemerge
+}
+
+; (icmp ne (A & B), 0) | (icmp ne (A & D), 0) -> (icmp ne (A & (B|D)), 0)
+define i32 @main3c(i32 %argc, i8** nocapture %argv) nounwind readnone ssp {
+entry:
+ %and = and i32 %argc, 7 ; <i32> [#uses=1]
+ %tobool = icmp ne i32 %and, 0 ; <i1> [#uses=1]
+ %and2 = and i32 %argc, 48 ; <i32> [#uses=1]
+ %tobool3 = icmp ne i32 %and2, 0 ; <i1> [#uses=1]
+ %or.cond = or i1 %tobool, %tobool3 ; <i1> [#uses=1]
+ %storemerge = select i1 %or.cond, i32 0, i32 1 ; <i32> [#uses=1]
+ ret i32 %storemerge
+}
+
+define i32 @main3d(i32 %argc, i8** nocapture %argv) nounwind readnone ssp {
+entry:
+ %and = and i32 %argc, 7 ; <i32> [#uses=1]
+ %tobool = icmp ne i32 %and, 0 ; <i1> [#uses=1]
+ %and2 = and i32 %argc, 16 ; <i32> [#uses=1]
+ %tobool3 = icmp eq i32 %and2, 16 ; <i1> [#uses=1]
+ %or.cond = or i1 %tobool, %tobool3 ; <i1> [#uses=1]
+ %storemerge = select i1 %or.cond, i32 0, i32 1 ; <i32> [#uses=1]
+ ret i32 %storemerge
+}
+
+define i32 @main3f_like(i32 %argc, i32 %argc2, i32 %argc3, i8** nocapture %argv)
+ nounwind readnone ssp {
+entry:
+ %and = and i32 %argc, %argc2 ; <i32> [#uses=1]
+ %tobool = icmp ne i32 %and, 0 ; <i1> [#uses=1]
+ %and2 = and i32 %argc, %argc3 ; <i32> [#uses=1]
+ %tobool3 = icmp ne i32 %and2, 0 ; <i1> [#uses=1]
+ %or.cond = or i1 %tobool, %tobool3 ; <i1> [#uses=1]
+ %storemerge = select i1 %or.cond, i32 0, i32 1 ; <i32> [#uses=1]
+ ret i32 %storemerge
+}
+
+; (icmp eq (A & B), B) & (icmp eq (A & D), D) -> (icmp eq (A & (B|D)), (B|D))
+define i32 @main4(i32 %argc, i8** nocapture %argv) nounwind readnone ssp {
+entry:
+ %and = and i32 %argc, 7 ; <i32> [#uses=1]
+ %tobool = icmp eq i32 %and, 7 ; <i1> [#uses=1]
+ %and2 = and i32 %argc, 48 ; <i32> [#uses=1]
+ %tobool3 = icmp eq i32 %and2, 48 ; <i1> [#uses=1]
+ %and.cond = and i1 %tobool, %tobool3 ; <i1> [#uses=1]
+ %storemerge = select i1 %and.cond, i32 0, i32 1 ; <i32> [#uses=1]
+ ret i32 %storemerge
+}
+
+define i32 @main4b(i32 %argc, i8** nocapture %argv) nounwind readnone ssp {
+entry:
+ %and = and i32 %argc, 7 ; <i32> [#uses=1]
+ %tobool = icmp eq i32 %and, 7 ; <i1> [#uses=1]
+ %and2 = and i32 %argc, 16 ; <i32> [#uses=1]
+ %tobool3 = icmp ne i32 %and2, 0 ; <i1> [#uses=1]
+ %and.cond = and i1 %tobool, %tobool3 ; <i1> [#uses=1]
+ %storemerge = select i1 %and.cond, i32 0, i32 1 ; <i32> [#uses=1]
+ ret i32 %storemerge
+}
+
+define i32 @main4e_like(i32 %argc, i32 %argc2, i32 %argc3, i8** nocapture %argv)
+ nounwind readnone ssp {
+entry:
+ %and = and i32 %argc, %argc2 ; <i32> [#uses=1]
+ %tobool = icmp eq i32 %and, %argc2 ; <i1> [#uses=1]
+ %and2 = and i32 %argc, %argc3 ; <i32> [#uses=1]
+ %tobool3 = icmp eq i32 %and2, %argc3 ; <i1> [#uses=1]
+ %and.cond = and i1 %tobool, %tobool3 ; <i1> [#uses=1]
+ %storemerge = select i1 %and.cond, i32 0, i32 1 ; <i32> [#uses=1]
+ ret i32 %storemerge
+}
+
+; (icmp ne (A & B), B) | (icmp ne (A & D), D) -> (icmp ne (A & (B|D)), (B|D))
+define i32 @main4c(i32 %argc, i8** nocapture %argv) nounwind readnone ssp {
+entry:
+ %and = and i32 %argc, 7 ; <i32> [#uses=1]
+ %tobool = icmp ne i32 %and, 7 ; <i1> [#uses=1]
+ %and2 = and i32 %argc, 48 ; <i32> [#uses=1]
+ %tobool3 = icmp ne i32 %and2, 48 ; <i1> [#uses=1]
+ %or.cond = or i1 %tobool, %tobool3 ; <i1> [#uses=1]
+ %storemerge = select i1 %or.cond, i32 0, i32 1 ; <i32> [#uses=1]
+ ret i32 %storemerge
+}
+
+define i32 @main4d(i32 %argc, i8** nocapture %argv) nounwind readnone ssp {
+entry:
+ %and = and i32 %argc, 7 ; <i32> [#uses=1]
+ %tobool = icmp ne i32 %and, 7 ; <i1> [#uses=1]
+ %and2 = and i32 %argc, 16 ; <i32> [#uses=1]
+ %tobool3 = icmp eq i32 %and2, 0 ; <i1> [#uses=1]
+ %or.cond = or i1 %tobool, %tobool3 ; <i1> [#uses=1]
+ %storemerge = select i1 %or.cond, i32 0, i32 1 ; <i32> [#uses=1]
+ ret i32 %storemerge
+}
+
+define i32 @main4f_like(i32 %argc, i32 %argc2, i32 %argc3, i8** nocapture %argv)
+ nounwind readnone ssp {
+entry:
+ %and = and i32 %argc, %argc2 ; <i32> [#uses=1]
+ %tobool = icmp ne i32 %and, %argc2 ; <i1> [#uses=1]
+ %and2 = and i32 %argc, %argc3 ; <i32> [#uses=1]
+ %tobool3 = icmp ne i32 %and2, %argc3 ; <i1> [#uses=1]
+ %or.cond = or i1 %tobool, %tobool3 ; <i1> [#uses=1]
+ %storemerge = select i1 %or.cond, i32 0, i32 1 ; <i32> [#uses=1]
+ ret i32 %storemerge
+}
+
+; (icmp eq (A & B), A) & (icmp eq (A & D), A) -> (icmp eq (A & (B&D)), A)
+define i32 @main5_like(i32 %argc, i32 %argc2, i8** nocapture %argv)
+ nounwind readnone ssp {
+entry:
+ %and = and i32 %argc, 7 ; <i32> [#uses=1]
+ %tobool = icmp eq i32 %and, 7 ; <i1> [#uses=1]
+ %and2 = and i32 %argc2, 7 ; <i32> [#uses=1]
+ %tobool3 = icmp eq i32 %and2, 7 ; <i1> [#uses=1]
+ %and.cond = and i1 %tobool, %tobool3 ; <i1> [#uses=1]
+ %storemerge = select i1 %and.cond, i32 0, i32 1 ; <i32> [#uses=1]
+ ret i32 %storemerge
+}
+
+define i32 @main5e_like(i32 %argc, i32 %argc2, i32 %argc3, i8** nocapture %argv)
+ nounwind readnone ssp {
+entry:
+ %and = and i32 %argc, %argc2 ; <i32> [#uses=1]
+ %tobool = icmp eq i32 %and, %argc ; <i1> [#uses=1]
+ %and2 = and i32 %argc, %argc3 ; <i32> [#uses=1]
+ %tobool3 = icmp eq i32 %and2, %argc ; <i1> [#uses=1]
+ %and.cond = and i1 %tobool, %tobool3 ; <i1> [#uses=1]
+ %storemerge = select i1 %and.cond, i32 0, i32 1 ; <i32> [#uses=1]
+ ret i32 %storemerge
+}
+
+; (icmp ne (A & B), A) | (icmp ne (A & D), A) -> (icmp ne (A & (B&D)), A)
+define i32 @main5c_like(i32 %argc, i32 %argc2, i8** nocapture %argv)
+ nounwind readnone ssp {
+entry:
+ %and = and i32 %argc, 7 ; <i32> [#uses=1]
+ %tobool = icmp ne i32 %and, 7 ; <i1> [#uses=1]
+ %and2 = and i32 %argc2, 7 ; <i32> [#uses=1]
+ %tobool3 = icmp ne i32 %and2, 7 ; <i1> [#uses=1]
+ %or.cond = or i1 %tobool, %tobool3 ; <i1> [#uses=1]
+ %storemerge = select i1 %or.cond, i32 0, i32 1 ; <i32> [#uses=1]
+ ret i32 %storemerge
+}
+
+define i32 @main5f_like(i32 %argc, i32 %argc2, i32 %argc3, i8** nocapture %argv)
+ nounwind readnone ssp {
+entry:
+ %and = and i32 %argc, %argc2 ; <i32> [#uses=1]
+ %tobool = icmp ne i32 %and, %argc ; <i1> [#uses=1]
+ %and2 = and i32 %argc, %argc3 ; <i32> [#uses=1]
+ %tobool3 = icmp ne i32 %and2, %argc ; <i1> [#uses=1]
+ %or.cond = or i1 %tobool, %tobool3 ; <i1> [#uses=1]
+ %storemerge = select i1 %or.cond, i32 0, i32 1 ; <i32> [#uses=1]
+ ret i32 %storemerge
+}
+
+; (icmp eq (A & B), C) & (icmp eq (A & D), E) -> (icmp eq (A & (B|D)), (C|E))
+; if B, C, D, E are constant, and it's possible
+define i32 @main6(i32 %argc, i8** nocapture %argv) nounwind readnone ssp {
+entry:
+ %and = and i32 %argc, 7 ; <i32> [#uses=1]
+ %tobool = icmp eq i32 %and, 3 ; <i1> [#uses=1]
+ %and2 = and i32 %argc, 48 ; <i32> [#uses=1]
+ %tobool3 = icmp eq i32 %and2, 16 ; <i1> [#uses=1]
+ %and.cond = and i1 %tobool, %tobool3 ; <i1> [#uses=1]
+ %storemerge = select i1 %and.cond, i32 0, i32 1 ; <i32> [#uses=1]
+ ret i32 %storemerge
+}
+
+define i32 @main6b(i32 %argc, i8** nocapture %argv) nounwind readnone ssp {
+entry:
+ %and = and i32 %argc, 7 ; <i32> [#uses=1]
+ %tobool = icmp eq i32 %and, 3 ; <i1> [#uses=1]
+ %and2 = and i32 %argc, 16 ; <i32> [#uses=1]
+ %tobool3 = icmp ne i32 %and2, 0 ; <i1> [#uses=1]
+ %and.cond = and i1 %tobool, %tobool3 ; <i1> [#uses=1]
+ %storemerge = select i1 %and.cond, i32 0, i32 1 ; <i32> [#uses=1]
+ ret i32 %storemerge
+}
+
+; (icmp ne (A & B), C) | (icmp ne (A & D), E) -> (icmp ne (A & (B|D)), (C|E))
+; if B, C, D, E are constant, and it's possible
+define i32 @main6c(i32 %argc, i8** nocapture %argv) nounwind readnone ssp {
+entry:
+ %and = and i32 %argc, 7 ; <i32> [#uses=1]
+ %tobool = icmp ne i32 %and, 3 ; <i1> [#uses=1]
+ %and2 = and i32 %argc, 48 ; <i32> [#uses=1]
+ %tobool3 = icmp ne i32 %and2, 16 ; <i1> [#uses=1]
+ %or.cond = or i1 %tobool, %tobool3 ; <i1> [#uses=1]
+ %storemerge = select i1 %or.cond, i32 0, i32 1 ; <i32> [#uses=1]
+ ret i32 %storemerge
+}
+
+define i32 @main6d(i32 %argc, i8** nocapture %argv) nounwind readnone ssp {
+entry:
+ %and = and i32 %argc, 7 ; <i32> [#uses=1]
+ %tobool = icmp ne i32 %and, 3 ; <i1> [#uses=1]
+ %and2 = and i32 %argc, 16 ; <i32> [#uses=1]
+ %tobool3 = icmp eq i32 %and2, 0 ; <i1> [#uses=1]
+ %or.cond = or i1 %tobool, %tobool3 ; <i1> [#uses=1]
+ %storemerge = select i1 %or.cond, i32 0, i32 1 ; <i32> [#uses=1]
+ ret i32 %storemerge
+}
+
+; test parameter permutations
+; (B & A) == B & (D & A) == D
+define i32 @main7a(i32 %argc, i32 %argc2, i32 %argc3, i8** nocapture %argv)
+ nounwind readnone ssp {
+entry:
+ %and1 = and i32 %argc2, %argc ; <i32> [#uses=1]
+ %tobool = icmp eq i32 %and1, %argc2 ; <i1> [#uses=1]
+ %and2 = and i32 %argc3, %argc ; <i32> [#uses=1]
+ %tobool3 = icmp eq i32 %and2, %argc3 ; <i1> [#uses=1]
+ %and.cond = and i1 %tobool, %tobool3 ; <i1> [#uses=1]
+ %storemerge = select i1 %and.cond, i32 0, i32 1 ; <i32> [#uses=1]
+ ret i32 %storemerge
+}
+
+; B == (A & B) & D == (A & D)
+define i32 @main7b(i32 %argc, i32 %argc2, i32 %argc3, i8** nocapture %argv)
+ nounwind readnone ssp {
+entry:
+ %and1 = and i32 %argc, %argc2 ; <i32> [#uses=1]
+ %tobool = icmp eq i32 %argc2, %and1 ; <i1> [#uses=1]
+ %and2 = and i32 %argc, %argc3 ; <i32> [#uses=1]
+ %tobool3 = icmp eq i32 %argc3, %and2 ; <i1> [#uses=1]
+ %and.cond = and i1 %tobool, %tobool3 ; <i1> [#uses=1]
+ %storemerge = select i1 %and.cond, i32 0, i32 1 ; <i32> [#uses=1]
+ ret i32 %storemerge
+}
+
+; B == (B & A) & D == (D & A)
+define i32 @main7c(i32 %argc, i32 %argc2, i32 %argc3, i8** nocapture %argv)
+ nounwind readnone ssp {
+entry:
+ %and1 = and i32 %argc2, %argc ; <i32> [#uses=1]
+ %tobool = icmp eq i32 %argc2, %and1 ; <i1> [#uses=1]
+ %and2 = and i32 %argc3, %argc ; <i32> [#uses=1]
+ %tobool3 = icmp eq i32 %argc3, %and2 ; <i1> [#uses=1]
+ %and.cond = and i1 %tobool, %tobool3 ; <i1> [#uses=1]
+ %storemerge = select i1 %and.cond, i32 0, i32 1 ; <i32> [#uses=1]
+ ret i32 %storemerge
+}
+
+; (A & (B & C)) == (B & C) & (A & (D & E)) == (D & E)
+define i32 @main7d(i32 %argc, i32 %argc2, i32 %argc3,
+ i32 %argc4, i32 %argc5, i8** nocapture %argv)
+ nounwind readnone ssp {
+entry:
+ %bc = and i32 %argc2, %argc4 ; <i32> [#uses=1]
+ %de = and i32 %argc3, %argc5 ; <i32> [#uses=1]
+ %and1 = and i32 %argc, %bc ; <i32> [#uses=1]
+ %tobool = icmp eq i32 %and1, %bc ; <i1> [#uses=1]
+ %and2 = and i32 %argc, %de ; <i32> [#uses=1]
+ %tobool3 = icmp eq i32 %and2, %de ; <i1> [#uses=1]
+ %and.cond = and i1 %tobool, %tobool3 ; <i1> [#uses=1]
+ %storemerge = select i1 %and.cond, i32 0, i32 1 ; <i32> [#uses=1]
+ ret i32 %storemerge
+}
+
+; ((B & C) & A) == (B & C) & ((D & E) & A) == (D & E)
+define i32 @main7e(i32 %argc, i32 %argc2, i32 %argc3,
+ i32 %argc4, i32 %argc5, i8** nocapture %argv)
+ nounwind readnone ssp {
+entry:
+ %bc = and i32 %argc2, %argc4 ; <i32> [#uses=1]
+ %de = and i32 %argc3, %argc5 ; <i32> [#uses=1]
+ %and1 = and i32 %bc, %argc ; <i32> [#uses=1]
+ %tobool = icmp eq i32 %and1, %bc ; <i1> [#uses=1]
+ %and2 = and i32 %de, %argc ; <i32> [#uses=1]
+ %tobool3 = icmp eq i32 %and2, %de ; <i1> [#uses=1]
+ %and.cond = and i1 %tobool, %tobool3 ; <i1> [#uses=1]
+ %storemerge = select i1 %and.cond, i32 0, i32 1 ; <i32> [#uses=1]
+ ret i32 %storemerge
+}
+
+; (B & C) == (A & (B & C)) & (D & E) == (A & (D & E))
+define i32 @main7f(i32 %argc, i32 %argc2, i32 %argc3,
+ i32 %argc4, i32 %argc5, i8** nocapture %argv)
+ nounwind readnone ssp {
+entry:
+ %bc = and i32 %argc2, %argc4 ; <i32> [#uses=1]
+ %de = and i32 %argc3, %argc5 ; <i32> [#uses=1]
+ %and1 = and i32 %argc, %bc ; <i32> [#uses=1]
+ %tobool = icmp eq i32 %bc, %and1 ; <i1> [#uses=1]
+ %and2 = and i32 %argc, %de ; <i32> [#uses=1]
+ %tobool3 = icmp eq i32 %de, %and2 ; <i1> [#uses=1]
+ %and.cond = and i1 %tobool, %tobool3 ; <i1> [#uses=1]
+ %storemerge = select i1 %and.cond, i32 0, i32 1 ; <i32> [#uses=1]
+ ret i32 %storemerge
+}
+
+; (B & C) == ((B & C) & A) & (D & E) == ((D & E) & A)
+define i32 @main7g(i32 %argc, i32 %argc2, i32 %argc3,
+ i32 %argc4, i32 %argc5, i8** nocapture %argv)
+ nounwind readnone ssp {
+entry:
+ %bc = and i32 %argc2, %argc4 ; <i32> [#uses=1]
+ %de = and i32 %argc3, %argc5 ; <i32> [#uses=1]
+ %and1 = and i32 %bc, %argc ; <i32> [#uses=1]
+ %tobool = icmp eq i32 %bc, %and1 ; <i1> [#uses=1]
+ %and2 = and i32 %de, %argc ; <i32> [#uses=1]
+ %tobool3 = icmp eq i32 %de, %and2 ; <i1> [#uses=1]
+ %and.cond = and i1 %tobool, %tobool3 ; <i1> [#uses=1]
+ %storemerge = select i1 %and.cond, i32 0, i32 1 ; <i32> [#uses=1]
+ ret i32 %storemerge
+}
diff --git a/test/Transforms/InstCombine/bitcast-store.ll b/test/Transforms/InstCombine/bitcast-store.ll
new file mode 100644
index 0000000..e4a61e9
--- /dev/null
+++ b/test/Transforms/InstCombine/bitcast-store.ll
@@ -0,0 +1,21 @@
+; RUN: opt -S -instcombine < %s | FileCheck %s
+
+; Instcombine should preserve metadata and alignment while
+; folding a bitcast into a store.
+
+; CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([5 x i8*]* @G, i64 0, i64 2) to i32 (...)**), i32 (...)*** %0, align 16, !tag !0
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+
+%struct.A = type { i32 (...)** }
+
+@G = external constant [5 x i8*]
+
+define void @foo(%struct.A* %a) nounwind {
+entry:
+ %0 = bitcast %struct.A* %a to i8***
+ store i8** getelementptr inbounds ([5 x i8*]* @G, i64 0, i64 2), i8*** %0, align 16, !tag !0
+ ret void
+}
+
+!0 = metadata !{metadata !"hello"}
diff --git a/test/Transforms/InstCombine/bitcast-vec-uniform.ll b/test/Transforms/InstCombine/bitcast-vec-uniform.ll
new file mode 100644
index 0000000..5975f1e
--- /dev/null
+++ b/test/Transforms/InstCombine/bitcast-vec-uniform.ll
@@ -0,0 +1,70 @@
+; RUN: opt < %s -instcombine -S | FileCheck %s
+
+; CHECK: @a
+; CHECK-NOT: bitcast
+; CHECK: ret
+define <4 x i32> @a(<1 x i64> %y) {
+ %c = bitcast <2 x i64> <i64 0, i64 0> to <4 x i32>
+ ret <4 x i32> %c
+}
+
+; CHECK: @b
+; CHECK-NOT: bitcast
+; CHECK: ret
+
+define <4 x i32> @b(<1 x i64> %y) {
+ %c = bitcast <2 x i64> <i64 -1, i64 -1> to <4 x i32>
+ ret <4 x i32> %c
+}
+
+; CHECK: @foo
+; CHECK-NOT: bitcast
+; CHECK: ret
+
+; from MultiSource/Benchmarks/Bullet
+define <2 x float> @foo() {
+ %cast = bitcast i64 -1 to <2 x float>
+ ret <2 x float> %cast
+}
+
+
+; CHECK: @foo2
+; CHECK-NOT: bitcast
+; CHECK: ret
+define <2 x double> @foo2() {
+ %cast = bitcast i128 -1 to <2 x double>
+ ret <2 x double> %cast
+}
+
+; CHECK: @foo3
+; CHECK-NOT: bitcast
+; CHECK: ret
+define <1 x float> @foo3() {
+ %cast = bitcast i32 -1 to <1 x float>
+ ret <1 x float> %cast
+}
+
+; CHECK: @foo4
+; CHECK-NOT: bitcast
+; CHECK: ret
+define float @foo4() {
+ %cast = bitcast <1 x i32 ><i32 -1> to float
+ ret float %cast
+}
+
+; CHECK: @foo5
+; CHECK-NOT: bitcast
+; CHECK: ret
+define double @foo5() {
+ %cast = bitcast <2 x i32 ><i32 -1, i32 -1> to double
+ ret double %cast
+}
+
+
+; CHECK: @foo6
+; CHECK-NOT: bitcast
+; CHECK: ret
+define <2 x double> @foo6() {
+ %cast = bitcast <4 x i32><i32 -1, i32 -1, i32 -1, i32 -1> to <2 x double>
+ ret <2 x double> %cast
+}
diff --git a/test/Transforms/InstCombine/cast.ll b/test/Transforms/InstCombine/cast.ll
index 102d2f0..bc5e365 100644
--- a/test/Transforms/InstCombine/cast.ll
+++ b/test/Transforms/InstCombine/cast.ll
@@ -437,8 +437,8 @@ define i64 @test47(i8 %A) {
ret i64 %E
; CHECK: @test47
; CHECK-NEXT: %B = sext i8 %A to i64
-; CHECK-NEXT: %C = or i64 %B, 42
-; CHECK-NEXT: %E = and i64 %C, 4294967295
+; CHECK-NEXT: %C = and i64 %B, 4294967253
+; CHECK-NEXT: %E = or i64 %C, 42
; CHECK-NEXT: ret i64 %E
}
@@ -452,7 +452,7 @@ define i64 @test48(i8 %A, i8 %a) {
; CHECK: @test48
; CHECK-NEXT: %b = zext i8 %a to i64
; CHECK-NEXT: %B = zext i8 %A to i64
-; CHECK-NEXT: %C = shl i64 %B, 8
+; CHECK-NEXT: %C = shl nuw nsw i64 %B, 8
; CHECK-NEXT: %D = or i64 %C, %b
; CHECK-NEXT: ret i64 %D
}
@@ -464,7 +464,7 @@ define i64 @test49(i64 %A) {
ret i64 %D
; CHECK: @test49
; CHECK-NEXT: %C = shl i64 %A, 32
-; CHECK-NEXT: ashr i64 %C, 32
+; CHECK-NEXT: ashr exact i64 %C, 32
; CHECK-NEXT: %D = or i64 {{.*}}, 1
; CHECK-NEXT: ret i64 %D
}
@@ -478,8 +478,8 @@ define i64 @test50(i64 %A) {
; CHECK: @test50
; CHECK-NEXT: shl i64 %A, 30
; CHECK-NEXT: add i64 {{.*}}, -4294967296
-; CHECK-NEXT: %E = ashr i64 {{.*}}, 32
-; CHECK-NEXT: ret i64 %E
+; CHECK-NEXT: %sext = ashr i64 {{.*}}, 32
+; CHECK-NEXT: ret i64 %sext
}
define i64 @test51(i64 %A, i1 %cond) {
@@ -508,8 +508,8 @@ define i32 @test52(i64 %A) {
ret i32 %E
; CHECK: @test52
; CHECK-NEXT: %B = trunc i64 %A to i32
-; CHECK-NEXT: %C = or i32 %B, 32962
-; CHECK-NEXT: %D = and i32 %C, 40186
+; CHECK-NEXT: %C = and i32 %B, 7224
+; CHECK-NEXT: %D = or i32 %C, 32962
; CHECK-NEXT: ret i32 %D
}
@@ -521,8 +521,8 @@ define i64 @test53(i32 %A) {
ret i64 %E
; CHECK: @test53
; CHECK-NEXT: %B = zext i32 %A to i64
-; CHECK-NEXT: %C = or i64 %B, 32962
-; CHECK-NEXT: %D = and i64 %C, 40186
+; CHECK-NEXT: %C = and i64 %B, 7224
+; CHECK-NEXT: %D = or i64 %C, 32962
; CHECK-NEXT: ret i64 %D
}
@@ -534,8 +534,8 @@ define i32 @test54(i64 %A) {
ret i32 %E
; CHECK: @test54
; CHECK-NEXT: %B = trunc i64 %A to i32
-; CHECK-NEXT: %C = or i32 %B, -32574
-; CHECK-NEXT: %D = and i32 %C, -25350
+; CHECK-NEXT: %C = and i32 %B, 7224
+; CHECK-NEXT: %D = or i32 %C, -32574
; CHECK-NEXT: ret i32 %D
}
@@ -547,8 +547,8 @@ define i64 @test55(i32 %A) {
ret i64 %E
; CHECK: @test55
; CHECK-NEXT: %B = zext i32 %A to i64
-; CHECK-NEXT: %C = or i64 %B, -32574
-; CHECK-NEXT: %D = and i64 %C, -25350
+; CHECK-NEXT: %C = and i64 %B, 7224
+; CHECK-NEXT: %D = or i64 %C, -32574
; CHECK-NEXT: ret i64 %D
}
@@ -584,8 +584,8 @@ define i64 @test58(i64 %A) nounwind {
; CHECK: @test58
; CHECK-NEXT: %C = lshr i64 %A, 8
-; CHECK-NEXT: %D = or i64 %C, 128
-; CHECK-NEXT: %E = and i64 %D, 16777215
+; CHECK-NEXT: %D = and i64 %C, 16777087
+; CHECK-NEXT: %E = or i64 %D, 128
; CHECK-NEXT: ret i64 %E
}
diff --git a/test/Transforms/InstCombine/constant-fold-gep.ll b/test/Transforms/InstCombine/constant-fold-gep.ll
index 4be1a9c..c679226 100644
--- a/test/Transforms/InstCombine/constant-fold-gep.ll
+++ b/test/Transforms/InstCombine/constant-fold-gep.ll
@@ -53,3 +53,22 @@ define void @frob() {
store i32 1, i32* getelementptr ([3 x %struct.X]* @Y, i64 0, i64 0, i32 0, i64 19), align 8
ret void
}
+
+
+; PR8883 - Constant fold exotic gep subtract
+; CHECK: @test2
+@X = global [1000 x i8] zeroinitializer, align 16
+
+define i64 @test2() {
+entry:
+ %A = bitcast i8* getelementptr inbounds ([1000 x i8]* @X, i64 1, i64 0) to i8*
+ %B = bitcast i8* getelementptr inbounds ([1000 x i8]* @X, i64 0, i64 0) to i8*
+
+ %B2 = ptrtoint i8* %B to i64
+ %C = sub i64 0, %B2
+ %D = getelementptr i8* %A, i64 %C
+ %E = ptrtoint i8* %D to i64
+
+ ret i64 %E
+ ; CHECK: ret i64 1000
+}
diff --git a/test/Transforms/InstCombine/crash.ll b/test/Transforms/InstCombine/crash.ll
index 30d467e..e17774d 100644
--- a/test/Transforms/InstCombine/crash.ll
+++ b/test/Transforms/InstCombine/crash.ll
@@ -252,3 +252,121 @@ entry:
%conv6 = zext i1 %cmp5 to i32 ; <i32> [#uses=0]
ret void
}
+
+%s1 = type { %s2, %s2, [6 x %s2], i32, i32, i32, [1 x i32], [0 x i8] }
+%s2 = type { i64 }
+define void @test13() nounwind ssp {
+entry:
+ %0 = getelementptr inbounds %s1* null, i64 0, i32 2, i64 0, i32 0
+ %1 = bitcast i64* %0 to i32*
+ %2 = getelementptr inbounds %s1* null, i64 0, i32 2, i64 1, i32 0
+ %.pre = load i32* %1, align 8
+ %3 = lshr i32 %.pre, 19
+ %brmerge = or i1 undef, undef
+ %4 = and i32 %3, 3
+ %5 = add nsw i32 %4, 1
+ %6 = shl i32 %5, 19
+ %7 = add i32 %6, 1572864
+ %8 = and i32 %7, 1572864
+ %9 = load i64* %2, align 8
+ %trunc156 = trunc i64 %9 to i32
+ %10 = and i32 %trunc156, -1537
+ %11 = and i32 %10, -6145
+ %12 = or i32 %11, 2048
+ %13 = and i32 %12, -24577
+ %14 = or i32 %13, 16384
+ %15 = or i32 %14, 98304
+ store i32 %15, i32* undef, align 8
+ %16 = and i32 %15, -1572865
+ %17 = or i32 %16, %8
+ store i32 %17, i32* undef, align 8
+ %18 = and i32 %17, -449
+ %19 = or i32 %18, 64
+ store i32 %19, i32* undef, align 8
+ unreachable
+}
+
+
+; PR8807
+declare i32 @test14f(i8* (i8*)*) nounwind
+
+define void @test14() nounwind readnone {
+entry:
+ %tmp = bitcast i32 (i8* (i8*)*)* @test14f to i32 (i32*)*
+ %call10 = call i32 %tmp(i32* byval undef)
+ ret void
+}
+
+
+; PR8896
+@g_54 = external global [7 x i16]
+
+define void @test15(i32* %p_92) nounwind {
+entry:
+%0 = load i32* %p_92, align 4
+%1 = icmp ne i32 %0, 0
+%2 = zext i1 %1 to i32
+%3 = call i32 @func_14() nounwind
+%4 = trunc i32 %3 to i16
+%5 = sext i16 %4 to i32
+%6 = trunc i32 %5 to i16
+br i1 undef, label %"3", label %"5"
+
+"3": ; preds = %entry
+%7 = sext i16 %6 to i32
+%8 = ashr i32 %7, -1649554541
+%9 = trunc i32 %8 to i16
+br label %"5"
+
+"5": ; preds = %"3", %entry
+%10 = phi i16 [ %9, %"3" ], [ %6, %entry ]
+%11 = sext i16 %10 to i32
+%12 = xor i32 %2, %11
+%13 = sext i32 %12 to i64
+%14 = icmp ne i64 %13, 0
+br i1 %14, label %return, label %"7"
+
+"7": ; preds = %"5"
+ret void
+
+return: ; preds = %"5"
+ret void
+}
+
+declare i32 @func_14()
+
+
+define double @test16(i32 %a) nounwind {
+ %cmp = icmp slt i32 %a, 2
+ %select = select i1 %cmp, double 2.000000e+00, double 3.141592e+00
+ ret double %select
+}
+
+
+; PR8983
+%struct.basic_ios = type { i8 }
+
+define %struct.basic_ios *@test17() ssp {
+entry:
+ %add.ptr.i = getelementptr i8* null, i64 undef
+ %0 = bitcast i8* %add.ptr.i to %struct.basic_ios*
+ ret %struct.basic_ios* %0
+}
+
+; PR9013
+define void @test18() nounwind ssp {
+entry:
+ br label %for.cond
+
+for.cond: ; preds = %for.inc, %entry
+ %l_197.0 = phi i32 [ 0, %entry ], [ %sub.i, %for.inc ]
+ br label %for.inc
+
+for.inc: ; preds = %for.cond
+ %conv = and i32 %l_197.0, 255
+ %sub.i = add nsw i32 %conv, -1
+ br label %for.cond
+
+return: ; No predecessors!
+ ret void
+}
diff --git a/test/Transforms/InstCombine/div-cmp-overflow.ll b/test/Transforms/InstCombine/div-cmp-overflow.ll
deleted file mode 100644
index 6f63adc..0000000
--- a/test/Transforms/InstCombine/div-cmp-overflow.ll
+++ /dev/null
@@ -1,8 +0,0 @@
-; RUN: opt < %s -instcombine -S | not grep sdiv
-; PR2740
-
-define i1 @func_75(i32 %i2) nounwind {
- %i3 = sdiv i32 %i2, -1328634635
- %i4 = icmp eq i32 %i3, -1
- ret i1 %i4
-}
diff --git a/test/Transforms/InstCombine/exact-sdiv.ll b/test/Transforms/InstCombine/exact-sdiv.ll
deleted file mode 100644
index e567754..0000000
--- a/test/Transforms/InstCombine/exact-sdiv.ll
+++ /dev/null
@@ -1,52 +0,0 @@
-; RUN: opt < %s -instcombine -S | FileCheck %s
-
-; CHECK: define i32 @foo
-; CHECK: sdiv i32 %x, 8
-define i32 @foo(i32 %x) {
- %y = sdiv i32 %x, 8
- ret i32 %y
-}
-
-; CHECK: define i32 @bar
-; CHECK: ashr i32 %x, 3
-define i32 @bar(i32 %x) {
- %y = sdiv exact i32 %x, 8
- ret i32 %y
-}
-
-; CHECK: i32 @a0
-; CHECK: %y = srem i32 %x, 3
-; CHECK: %z = sub i32 %x, %y
-; CHECK: ret i32 %z
-define i32 @a0(i32 %x) {
- %y = sdiv i32 %x, 3
- %z = mul i32 %y, 3
- ret i32 %z
-}
-
-; CHECK: i32 @b0
-; CHECK: ret i32 %x
-define i32 @b0(i32 %x) {
- %y = sdiv exact i32 %x, 3
- %z = mul i32 %y, 3
- ret i32 %z
-}
-
-; CHECK: i32 @a1
-; CHECK: %y = srem i32 %x, 3
-; CHECK: %z = sub i32 %y, %x
-; CHECK: ret i32 %z
-define i32 @a1(i32 %x) {
- %y = sdiv i32 %x, 3
- %z = mul i32 %y, -3
- ret i32 %z
-}
-
-; CHECK: i32 @b1
-; CHECK: %z = sub i32 0, %x
-; CHECK: ret i32 %z
-define i32 @b1(i32 %x) {
- %y = sdiv exact i32 %x, 3
- %z = mul i32 %y, -3
- ret i32 %z
-}
diff --git a/test/Transforms/InstCombine/exact.ll b/test/Transforms/InstCombine/exact.ll
new file mode 100644
index 0000000..58f8b5d
--- /dev/null
+++ b/test/Transforms/InstCombine/exact.ll
@@ -0,0 +1,154 @@
+; RUN: opt < %s -instcombine -S | FileCheck %s
+
+; CHECK: @sdiv1
+; CHECK: sdiv i32 %x, 8
+define i32 @sdiv1(i32 %x) {
+ %y = sdiv i32 %x, 8
+ ret i32 %y
+}
+
+; CHECK: @sdiv2
+; CHECK: ashr exact i32 %x, 3
+define i32 @sdiv2(i32 %x) {
+ %y = sdiv exact i32 %x, 8
+ ret i32 %y
+}
+
+; CHECK: @sdiv3
+; CHECK: %y = srem i32 %x, 3
+; CHECK: %z = sub i32 %x, %y
+; CHECK: ret i32 %z
+define i32 @sdiv3(i32 %x) {
+ %y = sdiv i32 %x, 3
+ %z = mul i32 %y, 3
+ ret i32 %z
+}
+
+; CHECK: @sdiv4
+; CHECK: ret i32 %x
+define i32 @sdiv4(i32 %x) {
+ %y = sdiv exact i32 %x, 3
+ %z = mul i32 %y, 3
+ ret i32 %z
+}
+
+; CHECK: i32 @sdiv5
+; CHECK: %y = srem i32 %x, 3
+; CHECK: %z = sub i32 %y, %x
+; CHECK: ret i32 %z
+define i32 @sdiv5(i32 %x) {
+ %y = sdiv i32 %x, 3
+ %z = mul i32 %y, -3
+ ret i32 %z
+}
+
+; CHECK: @sdiv6
+; CHECK: %z = sub i32 0, %x
+; CHECK: ret i32 %z
+define i32 @sdiv6(i32 %x) {
+ %y = sdiv exact i32 %x, 3
+ %z = mul i32 %y, -3
+ ret i32 %z
+}
+
+; CHECK: @udiv1
+; CHECK: ret i32 %x
+define i32 @udiv1(i32 %x, i32 %w) {
+ %y = udiv exact i32 %x, %w
+ %z = mul i32 %y, %w
+ ret i32 %z
+}
+
+; CHECK: @udiv2
+; CHECK: %z = lshr exact i32 %x, %w
+; CHECK: ret i32 %z
+define i32 @udiv2(i32 %x, i32 %w) {
+ %y = shl i32 1, %w
+ %z = udiv exact i32 %x, %y
+ ret i32 %z
+}
+
+; CHECK: @ashr1
+; CHECK: %B = ashr exact i64 %A, 2
+; CHECK: ret i64 %B
+define i64 @ashr1(i64 %X) nounwind {
+ %A = shl i64 %X, 8
+ %B = ashr i64 %A, 2 ; X/4
+ ret i64 %B
+}
+
+; PR9120
+; CHECK: @ashr_icmp1
+; CHECK: %B = icmp eq i64 %X, 0
+; CHECK: ret i1 %B
+define i1 @ashr_icmp1(i64 %X) nounwind {
+ %A = ashr exact i64 %X, 2 ; X/4
+ %B = icmp eq i64 %A, 0
+ ret i1 %B
+}
+
+; CHECK: @ashr_icmp2
+; CHECK: %Z = icmp slt i64 %X, 16
+; CHECK: ret i1 %Z
+define i1 @ashr_icmp2(i64 %X) nounwind {
+ %Y = ashr exact i64 %X, 2 ; x / 4
+ %Z = icmp slt i64 %Y, 4 ; x < 16
+ ret i1 %Z
+}
+
+; CHECK: @udiv_icmp1
+; CHECK: icmp ne i64 %X, 0
+define i1 @udiv_icmp1(i64 %X) nounwind {
+ %A = udiv exact i64 %X, 5 ; X/5
+ %B = icmp ne i64 %A, 0
+ ret i1 %B
+}
+
+; CHECK: @sdiv_icmp1
+; CHECK: icmp eq i64 %X, 0
+define i1 @sdiv_icmp1(i64 %X) nounwind {
+ %A = sdiv exact i64 %X, 5 ; X/5 == 0 --> x == 0
+ %B = icmp eq i64 %A, 0
+ ret i1 %B
+}
+
+; CHECK: @sdiv_icmp2
+; CHECK: icmp eq i64 %X, 5
+define i1 @sdiv_icmp2(i64 %X) nounwind {
+ %A = sdiv exact i64 %X, 5 ; X/5 == 1 --> x == 5
+ %B = icmp eq i64 %A, 1
+ ret i1 %B
+}
+
+; CHECK: @sdiv_icmp3
+; CHECK: icmp eq i64 %X, -5
+define i1 @sdiv_icmp3(i64 %X) nounwind {
+ %A = sdiv exact i64 %X, 5 ; X/5 == -1 --> x == -5
+ %B = icmp eq i64 %A, -1
+ ret i1 %B
+}
+
+; CHECK: @sdiv_icmp4
+; CHECK: icmp eq i64 %X, 0
+define i1 @sdiv_icmp4(i64 %X) nounwind {
+ %A = sdiv exact i64 %X, -5 ; X/-5 == 0 --> x == 0
+ %B = icmp eq i64 %A, 0
+ ret i1 %B
+}
+
+; CHECK: @sdiv_icmp5
+; CHECK: icmp eq i64 %X, -5
+define i1 @sdiv_icmp5(i64 %X) nounwind {
+ %A = sdiv exact i64 %X, -5 ; X/-5 == 1 --> x == -5
+ %B = icmp eq i64 %A, 1
+ ret i1 %B
+}
+
+; CHECK: @sdiv_icmp6
+; CHECK: icmp eq i64 %X, 5
+define i1 @sdiv_icmp6(i64 %X) nounwind {
+ %A = sdiv exact i64 %X, -5 ; X/-5 == 1 --> x == 5
+ %B = icmp eq i64 %A, -1
+ ret i1 %B
+}
+
diff --git a/test/Transforms/InstCombine/extractvalue.ll b/test/Transforms/InstCombine/extractvalue.ll
index 875f860..64edc18 100644
--- a/test/Transforms/InstCombine/extractvalue.ll
+++ b/test/Transforms/InstCombine/extractvalue.ll
@@ -1,13 +1,16 @@
-; RUN: opt < %s -instcombine -S | not grep extractvalue
+; RUN: opt < %s -instcombine -S | FileCheck %s
-; Instcombine should fold various combinations of insertvalue and extractvalue
-; together
declare void @bar({i32, i32} %a)
+declare i32 @baz(i32 %a)
-define i32 @foo() {
+; CHECK: define i32 @foo
+; CHECK-NOT: extractvalue
+define i32 @foo(i32 %a, i32 %b) {
+; Instcombine should fold various combinations of insertvalue and extractvalue
+; together
; Build a simple struct and pull values out again
- %s1.1 = insertvalue {i32, i32} undef, i32 0, 0
- %s1 = insertvalue {i32, i32} %s1.1, i32 1, 1
+ %s1.1 = insertvalue {i32, i32} undef, i32 %a, 0
+ %s1 = insertvalue {i32, i32} %s1.1, i32 %b, 1
%v1 = extractvalue {i32, i32} %s1, 0
%v2 = extractvalue {i32, i32} %s1, 1
@@ -36,3 +39,69 @@ define i32 @foo() {
ret i32 %v5
}
+; CHECK: define i32 @extract2gep
+; CHECK-NEXT: [[GEP:%[a-z0-9]+]] = getelementptr inbounds {{.*}}* %pair, i32 0, i32 1
+; CHECK-NEXT: [[LOAD:%[A-Za-z0-9]+]] = load i32* [[GEP]]
+; CHECK-NEXT: store
+; CHECK-NEXT: br label %loop
+; CHECK-NOT: extractvalue
+; CHECK: call {{.*}}(i32 [[LOAD]])
+; CHECK-NOT: extractvalue
+; CHECK: ret i32 [[LOAD]]
+define i32 @extract2gep({i32, i32}* %pair, i32* %P) {
+ ; The load + extractvalue should be converted
+ ; to an inbounds gep + smaller load.
+ ; The new load should be in the same spot as the old load.
+ %L = load {i32, i32}* %pair
+ store i32 0, i32* %P
+ br label %loop
+
+loop:
+ %E = extractvalue {i32, i32} %L, 1
+ %C = call i32 @baz(i32 %E)
+ store i32 %C, i32* %P
+ %cond = icmp eq i32 %C, 0
+ br i1 %cond, label %end, label %loop
+
+end:
+ ret i32 %E
+}
+
+; CHECK: define i32 @doubleextract2gep
+; CHECK-NEXT: [[GEP:%[a-z0-9]+]] = getelementptr inbounds {{.*}}* %arg, i32 0, i32 1, i32 1
+; CHECK-NEXT: [[LOAD:%[A-Za-z0-9]+]] = load i32* [[GEP]]
+; CHECK-NEXT: ret i32 [[LOAD]]
+define i32 @doubleextract2gep({i32, {i32, i32}}* %arg) {
+ ; The load + extractvalues should be converted
+ ; to a 3-index inbounds gep + smaller load.
+ %L = load {i32, {i32, i32}}* %arg
+ %E1 = extractvalue {i32, {i32, i32}} %L, 1
+ %E2 = extractvalue {i32, i32} %E1, 1
+ ret i32 %E2
+}
+
+; CHECK: define i32 @nogep-multiuse
+; CHECK-NEXT: load {{.*}} %pair
+; CHECK-NEXT: extractvalue
+; CHECK-NEXT: extractvalue
+; CHECK-NEXT: add
+; CHECK-NEXT: ret
+define i32 @nogep-multiuse({i32, i32}* %pair) {
+ ; The load should be left unchanged since both parts are needed.
+ %L = volatile load {i32, i32}* %pair
+ %LHS = extractvalue {i32, i32} %L, 0
+ %RHS = extractvalue {i32, i32} %L, 1
+ %R = add i32 %LHS, %RHS
+ ret i32 %R
+}
+
+; CHECK: define i32 @nogep-volatile
+; CHECK-NEXT: volatile load {{.*}} %pair
+; CHECK-NEXT: extractvalue
+; CHECK-NEXT: ret
+define i32 @nogep-volatile({i32, i32}* %pair) {
+ ; The volatile load should be left unchanged.
+ %L = volatile load {i32, i32}* %pair
+ %E = extractvalue {i32, i32} %L, 1
+ ret i32 %E
+}
diff --git a/test/Transforms/InstCombine/fold-calls.ll b/test/Transforms/InstCombine/fold-calls.ll
new file mode 100644
index 0000000..504f874
--- /dev/null
+++ b/test/Transforms/InstCombine/fold-calls.ll
@@ -0,0 +1,19 @@
+; RUN: opt -instcombine -S < %s | FileCheck %s
+
+; This shouldn't fold, because sin(inf) is invalid.
+; CHECK: @foo
+; CHECK: %t = call double @sin(double 0x7FF0000000000000)
+define double @foo() {
+ %t = call double @sin(double 0x7FF0000000000000)
+ ret double %t
+}
+
+; This should fold.
+; CHECK: @bar
+; CHECK: ret double 0.0
+define double @bar() {
+ %t = call double @sin(double 0.0)
+ ret double %t
+}
+
+declare double @sin(double)
diff --git a/test/Transforms/InstCombine/fold-vector-select.ll b/test/Transforms/InstCombine/fold-vector-select.ll
new file mode 100644
index 0000000..3f22522
--- /dev/null
+++ b/test/Transforms/InstCombine/fold-vector-select.ll
@@ -0,0 +1,13 @@
+; RUN: opt < %s -instcombine -S | not grep select
+
+define void @foo(<4 x i32> *%A, <4 x i32> *%B, <4 x i32> *%C, <4 x i32> *%D) {
+ %r = select <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> <i32 1, i32 2, i32 3, i32 4>, <4 x i32> zeroinitializer
+ %g = select <4 x i1> <i1 false, i1 false, i1 false, i1 false>, <4 x i32> zeroinitializer, <4 x i32> <i32 3, i32 6, i32 9, i32 1>
+ %b = select <4 x i1> <i1 false, i1 true, i1 false, i1 true>, <4 x i32> zeroinitializer, <4 x i32> <i32 7, i32 1, i32 4, i32 9>
+ %a = select <4 x i1> zeroinitializer, <4 x i32> zeroinitializer, <4 x i32> <i32 3, i32 2, i32 8, i32 5>
+ store <4 x i32> %r, <4 x i32>* %A
+ store <4 x i32> %g, <4 x i32>* %B
+ store <4 x i32> %b, <4 x i32>* %C
+ store <4 x i32> %a, <4 x i32>* %D
+ ret void
+}
diff --git a/test/Transforms/InstCombine/icmp.ll b/test/Transforms/InstCombine/icmp.ll
index 802957f..3150883 100644
--- a/test/Transforms/InstCombine/icmp.ll
+++ b/test/Transforms/InstCombine/icmp.ll
@@ -1,5 +1,8 @@
; RUN: opt < %s -instcombine -S | FileCheck %s
+target datalayout =
+"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+
define i32 @test1(i32 %X) {
entry:
icmp slt i32 %X, 0 ; <i1>:0 [#uses=1]
@@ -154,3 +157,223 @@ entry:
; CHECK: @test16
; CHECK: ret i1 undef
}
+
+define i1 @test17(i32 %x) nounwind {
+ %shl = shl i32 1, %x
+ %and = and i32 %shl, 8
+ %cmp = icmp eq i32 %and, 0
+ ret i1 %cmp
+; CHECK: @test17
+; CHECK-NEXT: %cmp = icmp ne i32 %x, 3
+}
+
+
+define i1 @test18(i32 %x) nounwind {
+ %sh = lshr i32 8, %x
+ %and = and i32 %sh, 1
+ %cmp = icmp eq i32 %and, 0
+ ret i1 %cmp
+; CHECK: @test18
+; CHECK-NEXT: %cmp = icmp ne i32 %x, 3
+}
+
+define i1 @test19(i32 %x) nounwind {
+ %shl = shl i32 1, %x
+ %and = and i32 %shl, 8
+ %cmp = icmp eq i32 %and, 8
+ ret i1 %cmp
+; CHECK: @test19
+; CHECK-NEXT: %cmp = icmp eq i32 %x, 3
+}
+
+define i1 @test20(i32 %x) nounwind {
+ %shl = shl i32 1, %x
+ %and = and i32 %shl, 8
+ %cmp = icmp ne i32 %and, 0
+ ret i1 %cmp
+; CHECK: @test20
+; CHECK-NEXT: %cmp = icmp eq i32 %x, 3
+}
+
+define i1 @test21(i8 %x, i8 %y) {
+; CHECK: @test21
+; CHECK-NOT: or i8
+; CHECK: icmp ugt
+ %A = or i8 %x, 1
+ %B = icmp ugt i8 %A, 3
+ ret i1 %B
+}
+
+define i1 @test22(i8 %x, i8 %y) {
+; CHECK: @test22
+; CHECK-NOT: or i8
+; CHECK: icmp ult
+ %A = or i8 %x, 1
+ %B = icmp ult i8 %A, 4
+ ret i1 %B
+}
+
+; PR2740
+; CHECK: @test23
+; CHECK: icmp sgt i32 %x, 1328634634
+define i1 @test23(i32 %x) nounwind {
+ %i3 = sdiv i32 %x, -1328634635
+ %i4 = icmp eq i32 %i3, -1
+ ret i1 %i4
+}
+
+@X = global [1000 x i32] zeroinitializer
+
+; PR8882
+; CHECK: @test24
+; CHECK: %cmp = icmp eq i64 %i, 1000
+; CHECK: ret i1 %cmp
+define i1 @test24(i64 %i) {
+ %p1 = getelementptr inbounds i32* getelementptr inbounds ([1000 x i32]* @X, i64 0, i64 0), i64 %i
+ %cmp = icmp eq i32* %p1, getelementptr inbounds ([1000 x i32]* @X, i64 1, i64 0)
+ ret i1 %cmp
+}
+
+; CHECK: @test25
+; X + Z > Y + Z -> X > Y if there is no overflow.
+; CHECK: %c = icmp sgt i32 %x, %y
+; CHECK: ret i1 %c
+define i1 @test25(i32 %x, i32 %y, i32 %z) {
+ %lhs = add nsw i32 %x, %z
+ %rhs = add nsw i32 %y, %z
+ %c = icmp sgt i32 %lhs, %rhs
+ ret i1 %c
+}
+
+; CHECK: @test26
+; X + Z > Y + Z -> X > Y if there is no overflow.
+; CHECK: %c = icmp ugt i32 %x, %y
+; CHECK: ret i1 %c
+define i1 @test26(i32 %x, i32 %y, i32 %z) {
+ %lhs = add nuw i32 %x, %z
+ %rhs = add nuw i32 %y, %z
+ %c = icmp ugt i32 %lhs, %rhs
+ ret i1 %c
+}
+
+; CHECK: @test27
+; X - Z > Y - Z -> X > Y if there is no overflow.
+; CHECK: %c = icmp sgt i32 %x, %y
+; CHECK: ret i1 %c
+define i1 @test27(i32 %x, i32 %y, i32 %z) {
+ %lhs = sub nsw i32 %x, %z
+ %rhs = sub nsw i32 %y, %z
+ %c = icmp sgt i32 %lhs, %rhs
+ ret i1 %c
+}
+
+; CHECK: @test28
+; X - Z > Y - Z -> X > Y if there is no overflow.
+; CHECK: %c = icmp ugt i32 %x, %y
+; CHECK: ret i1 %c
+define i1 @test28(i32 %x, i32 %y, i32 %z) {
+ %lhs = sub nuw i32 %x, %z
+ %rhs = sub nuw i32 %y, %z
+ %c = icmp ugt i32 %lhs, %rhs
+ ret i1 %c
+}
+
+; CHECK: @test29
+; X + Y > X -> Y > 0 if there is no overflow.
+; CHECK: %c = icmp sgt i32 %y, 0
+; CHECK: ret i1 %c
+define i1 @test29(i32 %x, i32 %y) {
+ %lhs = add nsw i32 %x, %y
+ %c = icmp sgt i32 %lhs, %x
+ ret i1 %c
+}
+
+; CHECK: @test30
+; X + Y > X -> Y > 0 if there is no overflow.
+; CHECK: %c = icmp ne i32 %y, 0
+; CHECK: ret i1 %c
+define i1 @test30(i32 %x, i32 %y) {
+ %lhs = add nuw i32 %x, %y
+ %c = icmp ugt i32 %lhs, %x
+ ret i1 %c
+}
+
+; CHECK: @test31
+; X > X + Y -> 0 > Y if there is no overflow.
+; CHECK: %c = icmp slt i32 %y, 0
+; CHECK: ret i1 %c
+define i1 @test31(i32 %x, i32 %y) {
+ %rhs = add nsw i32 %x, %y
+ %c = icmp sgt i32 %x, %rhs
+ ret i1 %c
+}
+
+; CHECK: @test32
+; X > X + Y -> 0 > Y if there is no overflow.
+; CHECK: ret i1 false
+define i1 @test32(i32 %x, i32 %y) {
+ %rhs = add nuw i32 %x, %y
+ %c = icmp ugt i32 %x, %rhs
+ ret i1 %c
+}
+
+; CHECK: @test33
+; X - Y > X -> 0 > Y if there is no overflow.
+; CHECK: %c = icmp slt i32 %y, 0
+; CHECK: ret i1 %c
+define i1 @test33(i32 %x, i32 %y) {
+ %lhs = sub nsw i32 %x, %y
+ %c = icmp sgt i32 %lhs, %x
+ ret i1 %c
+}
+
+; CHECK: @test34
+; X - Y > X -> 0 > Y if there is no overflow.
+; CHECK: ret i1 false
+define i1 @test34(i32 %x, i32 %y) {
+ %lhs = sub nuw i32 %x, %y
+ %c = icmp ugt i32 %lhs, %x
+ ret i1 %c
+}
+
+; CHECK: @test35
+; X > X - Y -> Y > 0 if there is no overflow.
+; CHECK: %c = icmp sgt i32 %y, 0
+; CHECK: ret i1 %c
+define i1 @test35(i32 %x, i32 %y) {
+ %rhs = sub nsw i32 %x, %y
+ %c = icmp sgt i32 %x, %rhs
+ ret i1 %c
+}
+
+; CHECK: @test36
+; X > X - Y -> Y > 0 if there is no overflow.
+; CHECK: %c = icmp ne i32 %y, 0
+; CHECK: ret i1 %c
+define i1 @test36(i32 %x, i32 %y) {
+ %rhs = sub nuw i32 %x, %y
+ %c = icmp ugt i32 %x, %rhs
+ ret i1 %c
+}
+
+; CHECK: @test37
+; X - Y > X - Z -> Z > Y if there is no overflow.
+; CHECK: %c = icmp sgt i32 %z, %y
+; CHECK: ret i1 %c
+define i1 @test37(i32 %x, i32 %y, i32 %z) {
+ %lhs = sub nsw i32 %x, %y
+ %rhs = sub nsw i32 %x, %z
+ %c = icmp sgt i32 %lhs, %rhs
+ ret i1 %c
+}
+
+; CHECK: @test38
+; X - Y > X - Z -> Z > Y if there is no overflow.
+; CHECK: %c = icmp ugt i32 %z, %y
+; CHECK: ret i1 %c
+define i1 @test38(i32 %x, i32 %y, i32 %z) {
+ %lhs = sub nuw i32 %x, %y
+ %rhs = sub nuw i32 %x, %z
+ %c = icmp ugt i32 %lhs, %rhs
+ ret i1 %c
+}
diff --git a/test/Transforms/InstCombine/intrinsics.ll b/test/Transforms/InstCombine/intrinsics.ll
index d672d8c..50e7f1f 100644
--- a/test/Transforms/InstCombine/intrinsics.ll
+++ b/test/Transforms/InstCombine/intrinsics.ll
@@ -71,6 +71,25 @@ define i8 @uaddtest5(i8 %A, i1* %overflowPtr) {
; CHECK: ret i8 %A
}
+define i1 @uaddtest6(i8 %A, i8 %B) {
+ %x = call %overflow.result @llvm.uadd.with.overflow.i8(i8 %A, i8 -4)
+ %z = extractvalue %overflow.result %x, 1
+ ret i1 %z
+; CHECK: @uaddtest6
+; CHECK-NEXT: %z = icmp ugt i8 %A, 3
+; CHECK-NEXT: ret i1 %z
+}
+
+define i8 @uaddtest7(i8 %A, i8 %B) {
+ %x = call %overflow.result @llvm.uadd.with.overflow.i8(i8 %A, i8 %B)
+ %z = extractvalue %overflow.result %x, 0
+ ret i8 %z
+; CHECK: @uaddtest7
+; CHECK-NEXT: %z = add i8 %A, %B
+; CHECK-NEXT: ret i8 %z
+}
+
+
define i8 @umultest1(i8 %A, i1* %overflowPtr) {
%x = call %overflow.result @llvm.umul.with.overflow.i8(i8 0, i8 %A)
%y = extractvalue %overflow.result %x, 0
diff --git a/test/Transforms/InstCombine/memcpy.ll b/test/Transforms/InstCombine/memcpy.ll
index 2e7b2c0..8a2e3aa 100644
--- a/test/Transforms/InstCombine/memcpy.ll
+++ b/test/Transforms/InstCombine/memcpy.ll
@@ -1,10 +1,19 @@
; RUN: opt < %s -instcombine -S | FileCheck %s
-declare void @llvm.memcpy.i32(i8*, i8*, i32, i32)
+declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i32, i1) nounwind
-define void @test4(i8* %a) {
- tail call void @llvm.memcpy.i32( i8* %a, i8* %a, i32 100, i32 1 )
+define void @test1(i8* %a) {
+ tail call void @llvm.memcpy.p0i8.p0i8.i32(i8* %a, i8* %a, i32 100, i32 1, i1 false)
ret void
-}
-; CHECK: define void @test4
+; CHECK: define void @test1
; CHECK-NEXT: ret void
+}
+
+
+; PR8267
+define void @test2(i8* %a) {
+ tail call void @llvm.memcpy.p0i8.p0i8.i32(i8* %a, i8* %a, i32 100, i32 1, i1 true)
+ ret void
+; CHECK: define void @test2
+; CHECK-NEXT: call void @llvm.memcpy
+}
diff --git a/test/Transforms/InstCombine/memset2.ll b/test/Transforms/InstCombine/memset2.ll
new file mode 100644
index 0000000..87639f0
--- /dev/null
+++ b/test/Transforms/InstCombine/memset2.ll
@@ -0,0 +1,15 @@
+; RUN: opt < %s -instcombine -S | FileCheck %s
+
+; Test to check that instcombine doesn't drop the address space when optimizing
+; memset.
+%struct.Moves = type { [9 x i8], i8, i8, i8, [5 x i8] }
+
+define i32 @test(%struct.Moves addrspace(1)* nocapture %moves) {
+entry:
+; CHECK: bitcast i8 addrspace(1)* %gep to i64 addrspace(1)*
+ %gep = getelementptr inbounds %struct.Moves addrspace(1)* %moves, i32 1, i32 0, i32 9
+ call void @llvm.memset.p1i8.i64(i8 addrspace(1)* %gep, i8 0, i64 8, i32 1, i1 false)
+ ret i32 0
+}
+
+declare void @llvm.memset.p1i8.i64(i8addrspace(1)* nocapture, i8, i64, i32, i1) nounwind
diff --git a/test/Transforms/InstCombine/neon-intrinsics.ll b/test/Transforms/InstCombine/neon-intrinsics.ll
new file mode 100644
index 0000000..3ad09cc
--- /dev/null
+++ b/test/Transforms/InstCombine/neon-intrinsics.ll
@@ -0,0 +1,25 @@
+; RUN: opt < %s -instcombine -S | FileCheck %s
+
+; The alignment arguments for NEON load/store intrinsics can be increased
+; by instcombine. Check for this.
+
+; CHECK: vld4.v2i32({{.*}}, i32 32)
+; CHECK: vst4.v2i32({{.*}}, i32 16)
+
+@x = common global [8 x i32] zeroinitializer, align 32
+@y = common global [8 x i32] zeroinitializer, align 16
+
+%struct.__neon_int32x2x4_t = type { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> }
+
+define void @test() nounwind ssp {
+ %tmp1 = call %struct.__neon_int32x2x4_t @llvm.arm.neon.vld4.v2i32(i8* bitcast ([8 x i32]* @x to i8*), i32 1)
+ %tmp2 = extractvalue %struct.__neon_int32x2x4_t %tmp1, 0
+ %tmp3 = extractvalue %struct.__neon_int32x2x4_t %tmp1, 1
+ %tmp4 = extractvalue %struct.__neon_int32x2x4_t %tmp1, 2
+ %tmp5 = extractvalue %struct.__neon_int32x2x4_t %tmp1, 3
+ call void @llvm.arm.neon.vst4.v2i32(i8* bitcast ([8 x i32]* @y to i8*), <2 x i32> %tmp2, <2 x i32> %tmp3, <2 x i32> %tmp4, <2 x i32> %tmp5, i32 1)
+ ret void
+}
+
+declare %struct.__neon_int32x2x4_t @llvm.arm.neon.vld4.v2i32(i8*, i32) nounwind readonly
+declare void @llvm.arm.neon.vst4.v2i32(i8*, <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32>, i32) nounwind
diff --git a/test/Transforms/InstCombine/nsw.ll b/test/Transforms/InstCombine/nsw.ll
index 821cebe..681bdc2 100644
--- a/test/Transforms/InstCombine/nsw.ll
+++ b/test/Transforms/InstCombine/nsw.ll
@@ -1,20 +1,39 @@
; RUN: opt < %s -instcombine -S | FileCheck %s
-; CHECK: define i32 @foo
-; %y = sub i32 0, %x
-; %z = sdiv i32 %y, 337
-; ret i32 %y
-define i32 @foo(i32 %x) {
+; CHECK: @sub1
+; CHECK: %y = sub i32 0, %x
+; CHECK: %z = sdiv i32 %y, 337
+; CHECK: ret i32 %z
+define i32 @sub1(i32 %x) {
%y = sub i32 0, %x
%z = sdiv i32 %y, 337
- ret i32 %y
+ ret i32 %z
}
-; CHECK: define i32 @bar
-; %y = sdiv i32 %x, -337
-; ret i32 %y
-define i32 @bar(i32 %x) {
+; CHECK: @sub2
+; CHECK: %z = sdiv i32 %x, -337
+; CHECK: ret i32 %z
+define i32 @sub2(i32 %x) {
%y = sub nsw i32 0, %x
%z = sdiv i32 %y, 337
- ret i32 %y
+ ret i32 %z
+}
+
+; CHECK: @shl_icmp
+; CHECK: %B = icmp eq i64 %X, 0
+; CHECK: ret i1 %B
+define i1 @shl_icmp(i64 %X) nounwind {
+ %A = shl nuw i64 %X, 2 ; X/4
+ %B = icmp eq i64 %A, 0
+ ret i1 %B
+}
+
+; CHECK: @shl1
+; CHECK: %B = shl nuw nsw i64 %A, 8
+; CHECK: ret i64 %B
+define i64 @shl1(i64 %X, i64* %P) nounwind {
+ %A = and i64 %X, 312
+ store i64 %A, i64* %P ; multiple uses of A.
+ %B = shl i64 %A, 8
+ ret i64 %B
}
diff --git a/test/Transforms/InstCombine/objsize.ll b/test/Transforms/InstCombine/objsize.ll
index 664701b..043525b 100644
--- a/test/Transforms/InstCombine/objsize.ll
+++ b/test/Transforms/InstCombine/objsize.ll
@@ -150,3 +150,13 @@ declare i8* @__memset_chk(i8*, i32, i32, i32) nounwind
declare noalias i8* @malloc(i32) nounwind
declare i32 @llvm.objectsize.i32(i8*, i1) nounwind readonly
+
+define i32 @test7() {
+; CHECK: @test7
+ %alloc = call noalias i8* @malloc(i32 48) nounwind
+ %gep = getelementptr inbounds i8* %alloc, i32 16
+ %objsize = call i32 @llvm.objectsize.i32(i8* %gep, i1 false) nounwind readonly
+; CHECK-NEXT: ret i32 32
+ ret i32 %objsize
+}
+
diff --git a/test/Transforms/InstCombine/or-fcmp.ll b/test/Transforms/InstCombine/or-fcmp.ll
index 9692bfc..09a3c99 100644
--- a/test/Transforms/InstCombine/or-fcmp.ll
+++ b/test/Transforms/InstCombine/or-fcmp.ll
@@ -1,34 +1,58 @@
-; RUN: opt < %s -instcombine -S | grep fcmp | count 3
-; RUN: opt < %s -instcombine -S | grep ret | grep 1
+; RUN: opt < %s -instcombine -S | FileCheck %s
+; CHECK: @t1
define zeroext i8 @t1(float %x, float %y) nounwind {
%a = fcmp ueq float %x, %y ; <i1> [#uses=1]
%b = fcmp uno float %x, %y ; <i1> [#uses=1]
%c = or i1 %a, %b
+; CHECK-NOT: fcmp uno
+; CHECK: fcmp ueq
%retval = zext i1 %c to i8
ret i8 %retval
}
+; CHECK: @t2
define zeroext i8 @t2(float %x, float %y) nounwind {
%a = fcmp olt float %x, %y ; <i1> [#uses=1]
%b = fcmp oeq float %x, %y ; <i1> [#uses=1]
+; CHECK-NOT: fcmp olt
+; CHECK-NOT: fcmp oeq
+; CHECK: fcmp ole
%c = or i1 %a, %b
%retval = zext i1 %c to i8
ret i8 %retval
}
+; CHECK: @t3
define zeroext i8 @t3(float %x, float %y) nounwind {
%a = fcmp ult float %x, %y ; <i1> [#uses=1]
%b = fcmp uge float %x, %y ; <i1> [#uses=1]
%c = or i1 %a, %b
%retval = zext i1 %c to i8
+; CHECK: ret i8 1
ret i8 %retval
}
+; CHECK: @t4
define zeroext i8 @t4(float %x, float %y) nounwind {
%a = fcmp ult float %x, %y ; <i1> [#uses=1]
%b = fcmp ugt float %x, %y ; <i1> [#uses=1]
%c = or i1 %a, %b
+; CHECK-NOT: fcmp ult
+; CHECK-NOT: fcmp ugt
+; CHECK: fcmp une
+ %retval = zext i1 %c to i8
+ ret i8 %retval
+}
+
+; CHECK: @t5
+define zeroext i8 @t5(float %x, float %y) nounwind {
+ %a = fcmp olt float %x, %y ; <i1> [#uses=1]
+ %b = fcmp oge float %x, %y ; <i1> [#uses=1]
+ %c = or i1 %a, %b
+; CHECK-NOT: fcmp olt
+; CHECK-NOT: fcmp oge
+; CHECK: fcmp ord
%retval = zext i1 %c to i8
ret i8 %retval
}
diff --git a/test/Transforms/InstCombine/or.ll b/test/Transforms/InstCombine/or.ll
index c3526b7..f82f9fa 100644
--- a/test/Transforms/InstCombine/or.ll
+++ b/test/Transforms/InstCombine/or.ll
@@ -316,8 +316,8 @@ entry:
%E = or i32 %D, %C
ret i32 %E
; CHECK: @test30
-; CHECK: %B = or i32 %A, 32962
-; CHECK: %E = and i32 %B, -25350
+; CHECK: %D = and i32 %A, -58312
+; CHECK: %E = or i32 %D, 32962
; CHECK: ret i32 %E
}
@@ -332,8 +332,8 @@ define i64 @test31(i64 %A) nounwind readnone ssp noredzone {
%F = or i64 %D, %E
ret i64 %F
; CHECK: @test31
-; CHECK-NEXT: %bitfield = or i64 %A, 32962
-; CHECK-NEXT: %F = and i64 %bitfield, 4294941946
+; CHECK-NEXT: %E1 = and i64 %A, 4294908984
+; CHECK-NEXT: %F = or i64 %E1, 32962
; CHECK-NEXT: ret i64 %F
}
@@ -350,3 +350,43 @@ define <4 x i32> @test32(<4 x i1> %and.i1352, <4 x i32> %vecinit6.i176, <4 x i32
; CHECK: or <4 x i32> %and.i, %and.i129
}
+define i1 @test33(i1 %X, i1 %Y) {
+ %a = or i1 %X, %Y
+ %b = or i1 %a, %X
+ ret i1 %b
+; CHECK: @test33
+; CHECK-NEXT: or i1 %X, %Y
+; CHECK-NEXT: ret
+}
+
+define i32 @test34(i32 %X, i32 %Y) {
+ %a = or i32 %X, %Y
+ %b = or i32 %Y, %a
+ ret i32 %b
+; CHECK: @test34
+; CHECK-NEXT: or i32 %X, %Y
+; CHECK-NEXT: ret
+}
+
+define i32 @test35(i32 %a, i32 %b) {
+ %1 = or i32 %a, 1135
+ %2 = or i32 %1, %b
+ ret i32 %2
+ ; CHECK: @test35
+ ; CHECK-NEXT: or i32 %a, %b
+ ; CHECK-NEXT: or i32 %1, 1135
+}
+
+define i1 @test36(i32 %x) {
+ %cmp1 = icmp eq i32 %x, 23
+ %cmp2 = icmp eq i32 %x, 24
+ %ret1 = or i1 %cmp1, %cmp2
+ %cmp3 = icmp eq i32 %x, 25
+ %ret2 = or i1 %ret1, %cmp3
+ ret i1 %ret2
+; CHECK: @test36
+; CHECK-NEXT: %x.off = add i32 %x, -23
+; CHECK-NEXT: icmp ult i32 %x.off, 3
+; CHECK-NEXT: ret i1
+}
+
diff --git a/test/Transforms/InstCombine/overflow.ll b/test/Transforms/InstCombine/overflow.ll
new file mode 100644
index 0000000..9123283
--- /dev/null
+++ b/test/Transforms/InstCombine/overflow.ll
@@ -0,0 +1,133 @@
+; RUN: opt -S -instcombine < %s | FileCheck %s
+; <rdar://problem/8558713>
+
+declare void @throwAnExceptionOrWhatever()
+
+; CHECK: @test1
+define i32 @test1(i32 %a, i32 %b) nounwind ssp {
+entry:
+; CHECK-NOT: sext
+ %conv = sext i32 %a to i64
+ %conv2 = sext i32 %b to i64
+ %add = add nsw i64 %conv2, %conv
+ %add.off = add i64 %add, 2147483648
+; CHECK: llvm.sadd.with.overflow.i32
+ %0 = icmp ugt i64 %add.off, 4294967295
+ br i1 %0, label %if.then, label %if.end
+
+if.then:
+ tail call void @throwAnExceptionOrWhatever() nounwind
+ br label %if.end
+
+if.end:
+; CHECK-NOT: trunc
+ %conv9 = trunc i64 %add to i32
+; CHECK: ret i32
+ ret i32 %conv9
+}
+
+; CHECK: @test2
+; This form should not be promoted for two reasons: 1) it is unprofitable to
+; promote it since the add.off instruction has another use, and 2) it is unsafe
+; because the add-with-off makes the high bits of the original add live.
+define i32 @test2(i32 %a, i32 %b, i64* %P) nounwind ssp {
+entry:
+ %conv = sext i32 %a to i64
+ %conv2 = sext i32 %b to i64
+ %add = add nsw i64 %conv2, %conv
+ %add.off = add i64 %add, 2147483648
+
+ store i64 %add.off, i64* %P
+
+; CHECK-NOT: llvm.sadd.with.overflow
+ %0 = icmp ugt i64 %add.off, 4294967295
+ br i1 %0, label %if.then, label %if.end
+
+if.then:
+ tail call void @throwAnExceptionOrWhatever() nounwind
+ br label %if.end
+
+if.end:
+ %conv9 = trunc i64 %add to i32
+; CHECK: ret i32
+ ret i32 %conv9
+}
+
+; CHECK: test3
+; PR8816
+; This is illegal to transform because the high bits of the original add are
+; live out.
+define i64 @test3(i32 %a, i32 %b) nounwind ssp {
+entry:
+ %conv = sext i32 %a to i64
+ %conv2 = sext i32 %b to i64
+ %add = add nsw i64 %conv2, %conv
+ %add.off = add i64 %add, 2147483648
+; CHECK-NOT: llvm.sadd.with.overflow
+ %0 = icmp ugt i64 %add.off, 4294967295
+ br i1 %0, label %if.then, label %if.end
+
+if.then:
+ tail call void @throwAnExceptionOrWhatever() nounwind
+ br label %if.end
+
+if.end:
+ ret i64 %add
+; CHECK: ret i64
+}
+
+; CHECK: @test4
+; Should be able to form an i8 sadd computed in an i32.
+define zeroext i8 @test4(i8 signext %a, i8 signext %b) nounwind ssp {
+entry:
+ %conv = sext i8 %a to i32
+ %conv2 = sext i8 %b to i32
+ %add = add nsw i32 %conv2, %conv
+ %add4 = add nsw i32 %add, 128
+ %cmp = icmp ugt i32 %add4, 255
+ br i1 %cmp, label %if.then, label %if.end
+; CHECK: llvm.sadd.with.overflow.i8
+if.then: ; preds = %entry
+ tail call void @throwAnExceptionOrWhatever() nounwind
+ unreachable
+
+if.end: ; preds = %entry
+ %conv7 = trunc i32 %add to i8
+ ret i8 %conv7
+; CHECK: ret i8
+}
+
+; CHECK: @test5
+; CHECK: llvm.uadd.with.overflow
+; CHECK: ret i64
+define i64 @test5(i64 %a, i64 %b) nounwind ssp {
+entry:
+ %add = add i64 %b, %a
+ %cmp = icmp ult i64 %add, %a
+ %Q = select i1 %cmp, i64 %b, i64 42
+ ret i64 %Q
+}
+
+; CHECK: @test6
+; CHECK: llvm.uadd.with.overflow
+; CHECK: ret i64
+define i64 @test6(i64 %a, i64 %b) nounwind ssp {
+entry:
+ %add = add i64 %b, %a
+ %cmp = icmp ult i64 %add, %b
+ %Q = select i1 %cmp, i64 %b, i64 42
+ ret i64 %Q
+}
+
+; CHECK: @test7
+; CHECK: llvm.uadd.with.overflow
+; CHECK: ret i64
+define i64 @test7(i64 %a, i64 %b) nounwind ssp {
+entry:
+ %add = add i64 %b, %a
+ %cmp = icmp ugt i64 %b, %add
+ %Q = select i1 %cmp, i64 %b, i64 42
+ ret i64 %Q
+}
+
+
diff --git a/test/Transforms/InstCombine/phi.ll b/test/Transforms/InstCombine/phi.ll
index c6c3f2f..62c6a63 100644
--- a/test/Transforms/InstCombine/phi.ll
+++ b/test/Transforms/InstCombine/phi.ll
@@ -125,7 +125,7 @@ Exit: ; preds = %Loop
define i32* @test8({ i32, i32 } *%A, i1 %b) {
BB0:
- %X = getelementptr { i32, i32 } *%A, i32 0, i32 1
+ %X = getelementptr inbounds { i32, i32 } *%A, i32 0, i32 1
br i1 %b, label %BB1, label %BB2
BB1:
@@ -139,7 +139,7 @@ BB2:
; CHECK: @test8
; CHECK-NOT: phi
; CHECK: BB2:
-; CHECK-NEXT: %B = getelementptr
+; CHECK-NEXT: %B = getelementptr %0
; CHECK-NEXT: ret i32* %B
}
@@ -423,3 +423,124 @@ bb2: ; preds = %bb1, %entry
ret i32 %res
}
+define i1 @test18(i1 %cond) {
+ %zero = alloca i32
+ %one = alloca i32
+ br i1 %cond, label %true, label %false
+true:
+ br label %ret
+false:
+ br label %ret
+ret:
+ %ptr = phi i32* [ %zero, %true ] , [ %one, %false ]
+ %isnull = icmp eq i32* %ptr, null
+ ret i1 %isnull
+; CHECK: @test18
+; CHECK: ret i1 false
+}
+
+define i1 @test19(i1 %cond, double %x) {
+ br i1 %cond, label %true, label %false
+true:
+ br label %ret
+false:
+ br label %ret
+ret:
+ %p = phi double [ %x, %true ], [ 0x7FF0000000000000, %false ]; RHS = +infty
+ %cmp = fcmp ule double %x, %p
+ ret i1 %cmp
+; CHECK: @test19
+; CHECK: ret i1 true
+}
+
+define i1 @test20(i1 %cond) {
+ %a = alloca i32
+ %b = alloca i32
+ %c = alloca i32
+ br i1 %cond, label %true, label %false
+true:
+ br label %ret
+false:
+ br label %ret
+ret:
+ %p = phi i32* [ %a, %true ], [ %b, %false ]
+ %r = icmp eq i32* %p, %c
+ ret i1 %r
+; CHECK: @test20
+; CHECK: ret i1 false
+}
+
+define i1 @test21(i1 %c1, i1 %c2) {
+ %a = alloca i32
+ %b = alloca i32
+ %c = alloca i32
+ br i1 %c1, label %true, label %false
+true:
+ br label %loop
+false:
+ br label %loop
+loop:
+ %p = phi i32* [ %a, %true ], [ %b, %false ], [ %p, %loop ]
+ %r = icmp eq i32* %p, %c
+ br i1 %c2, label %ret, label %loop
+ret:
+ ret i1 %r
+; CHECK: @test21
+; CHECK: ret i1 false
+}
+
+define void @test22() {
+; CHECK: @test22
+entry:
+ br label %loop
+loop:
+ %phi = phi i32 [ 0, %entry ], [ %y, %loop ]
+ %y = add i32 %phi, 1
+ %o = or i32 %y, %phi
+ %e = icmp eq i32 %o, %y
+ br i1 %e, label %loop, label %ret
+; CHECK: br i1 %e
+ret:
+ ret void
+}
+
+define i32 @test23(i32 %A, i1 %b, i32 * %P) {
+BB0:
+ br label %Loop
+
+Loop: ; preds = %Loop, %BB0
+ ; PHI has same value always.
+ %B = phi i32 [ %A, %BB0 ], [ 42, %Loop ]
+ %D = add i32 %B, 19
+ store i32 %D, i32* %P
+ br i1 %b, label %Loop, label %Exit
+
+Exit: ; preds = %Loop
+ %E = add i32 %B, 19
+ ret i32 %E
+; CHECK: @test23
+; CHECK: %phitmp = add i32 %A, 19
+; CHECK: Loop:
+; CHECK-NEXT: %B = phi i32 [ %phitmp, %BB0 ], [ 61, %Loop ]
+; CHECK: Exit:
+; CHECK-NEXT: ret i32 %B
+}
+
+define i32 @test24(i32 %A, i1 %cond) {
+BB0:
+ %X = add nuw nsw i32 %A, 1
+ br i1 %cond, label %BB1, label %BB2
+
+BB1:
+ %Y = add nuw i32 %A, 1
+ br label %BB2
+
+BB2:
+ %C = phi i32 [ %X, %BB0 ], [ %Y, %BB1 ]
+ ret i32 %C
+; CHECK: @test24
+; CHECK-NOT: phi
+; CHECK: BB2:
+; CHECK-NEXT: %C = add nuw i32 %A, 1
+; CHECK-NEXT: ret i32 %C
+}
diff --git a/test/Transforms/InstCombine/pr8547.ll b/test/Transforms/InstCombine/pr8547.ll
new file mode 100644
index 0000000..485f4d9
--- /dev/null
+++ b/test/Transforms/InstCombine/pr8547.ll
@@ -0,0 +1,26 @@
+; RUN: opt < %s -instcombine -S | FileCheck %s
+; Converting the 2 shifts to SHL 6 without the AND is wrong. PR 8547.
+
+@g_2 = global i32 0, align 4
+@.str = constant [10 x i8] c"g_2 = %d\0A\00"
+
+declare i32 @printf(i8*, ...)
+
+define i32 @main() nounwind {
+codeRepl:
+ br label %for.cond
+
+for.cond: ; preds = %for.cond, %codeRepl
+ %storemerge = phi i32 [ 0, %codeRepl ], [ 5, %for.cond ]
+ store i32 %storemerge, i32* @g_2, align 4
+ %shl = shl i32 %storemerge, 30
+ %conv2 = lshr i32 %shl, 24
+; CHECK: %0 = shl nuw nsw i32 %storemerge, 6
+; CHECK: %conv2 = and i32 %0, 64
+ %tobool = icmp eq i32 %conv2, 0
+ br i1 %tobool, label %for.cond, label %codeRepl2
+
+codeRepl2: ; preds = %for.cond
+ %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([10 x i8]* @.str, i64 0, i64 0), i32 %conv2) nounwind
+ ret i32 0
+} \ No newline at end of file
diff --git a/test/Transforms/InstCombine/rem.ll b/test/Transforms/InstCombine/rem.ll
index bac248e..b421b7c 100644
--- a/test/Transforms/InstCombine/rem.ll
+++ b/test/Transforms/InstCombine/rem.ll
@@ -81,3 +81,8 @@ define i32 @test12(i32 %i) {
%tmp.5 = srem i32 %tmp.1, 2
ret i32 %tmp.5
}
+
+define i32 @test13(i32 %i) {
+ %x = srem i32 %i, %i
+ ret i32 %x
+}
diff --git a/test/Transforms/InstCombine/select-crash.ll b/test/Transforms/InstCombine/select-crash.ll
new file mode 100644
index 0000000..8ee3369
--- /dev/null
+++ b/test/Transforms/InstCombine/select-crash.ll
@@ -0,0 +1,20 @@
+; RUN: opt < %s -instcombine -S | FileCheck %s
+; Formerly crashed, PR8490.
+
+define fastcc double @gimp_operation_color_balance_map(float %value, double %highlights) nounwind readnone inlinehint {
+entry:
+; CHECK: gimp_operation_color_balance_map
+; CHECK: fsub double -0.000000
+ %conv = fpext float %value to double
+ %div = fdiv double %conv, 1.600000e+01
+ %add = fadd double %div, 1.000000e+00
+ %div1 = fdiv double 1.000000e+00, %add
+ %sub = fsub double 1.075000e+00, %div1
+ %sub24 = fsub double 1.000000e+00, %sub
+ %add26 = fadd double %sub, 1.000000e+00
+ %cmp86 = fcmp ogt double %highlights, 0.000000e+00
+ %cond90 = select i1 %cmp86, double %sub24, double %add26
+ %mul91 = fmul double %highlights, %cond90
+ %add94 = fadd double undef, %mul91
+ ret double %add94
+}
diff --git a/test/Transforms/InstCombine/select.ll b/test/Transforms/InstCombine/select.ll
index 246a7bc..ba9d99c 100644
--- a/test/Transforms/InstCombine/select.ll
+++ b/test/Transforms/InstCombine/select.ll
@@ -223,6 +223,81 @@ define i32 @test15d(i32 %X) {
; CHECK: ret i32 %t1
}
+;; (a & 128) ? 256 : 0
+define i32 @test15e(i32 %X) {
+ %t1 = and i32 %X, 128
+ %t2 = icmp ne i32 %t1, 0
+ %t3 = select i1 %t2, i32 256, i32 0
+ ret i32 %t3
+; CHECK: @test15e
+; CHECK: %t1 = shl i32 %X, 1
+; CHECK: and i32 %t1, 256
+; CHECK: ret i32
+}
+
+;; (a & 128) ? 0 : 256
+define i32 @test15f(i32 %X) {
+ %t1 = and i32 %X, 128
+ %t2 = icmp ne i32 %t1, 0
+ %t3 = select i1 %t2, i32 0, i32 256
+ ret i32 %t3
+; CHECK: @test15f
+; CHECK: %t1 = shl i32 %X, 1
+; CHECK: and i32 %t1, 256
+; CHECK: xor i32 %{{.*}}, 256
+; CHECK: ret i32
+}
+
+;; (a & 8) ? -1 : -9
+define i32 @test15g(i32 %X) {
+ %t1 = and i32 %X, 8
+ %t2 = icmp ne i32 %t1, 0
+ %t3 = select i1 %t2, i32 -1, i32 -9
+ ret i32 %t3
+; CHECK: @test15g
+; CHECK-NEXT: %1 = or i32 %X, -9
+; CHECK-NEXT: ret i32 %1
+}
+
+;; (a & 8) ? -9 : -1
+define i32 @test15h(i32 %X) {
+ %t1 = and i32 %X, 8
+ %t2 = icmp ne i32 %t1, 0
+ %t3 = select i1 %t2, i32 -9, i32 -1
+ ret i32 %t3
+; CHECK: @test15h
+; CHECK-NEXT: %1 = or i32 %X, -9
+; CHECK-NEXT: %2 = xor i32 %1, 8
+; CHECK-NEXT: ret i32 %2
+}
+
+;; (a & 2) ? 577 : 1089
+define i32 @test15i(i32 %X) {
+ %t1 = and i32 %X, 2
+ %t2 = icmp ne i32 %t1, 0
+ %t3 = select i1 %t2, i32 577, i32 1089
+ ret i32 %t3
+; CHECK: @test15i
+; CHECK-NEXT: %t1 = shl i32 %X, 8
+; CHECK-NEXT: %1 = and i32 %t1, 512
+; CHECK-NEXT: %2 = xor i32 %1, 512
+; CHECK-NEXT: %3 = add i32 %2, 577
+; CHECK-NEXT: ret i32 %3
+}
+
+;; (a & 2) ? 1089 : 577
+define i32 @test15j(i32 %X) {
+ %t1 = and i32 %X, 2
+ %t2 = icmp ne i32 %t1, 0
+ %t3 = select i1 %t2, i32 1089, i32 577
+ ret i32 %t3
+; CHECK: @test15j
+; CHECK-NEXT: %t1 = shl i32 %X, 8
+; CHECK-NEXT: %1 = and i32 %t1, 512
+; CHECK-NEXT: %2 = add i32 %1, 577
+; CHECK-NEXT: ret i32 %2
+}
+
define i32 @test16(i1 %C, i32* %P) {
%P2 = select i1 %C, i32* %P, i32* null
%V = load i32* %P2
@@ -470,3 +545,172 @@ define i32 @test37(i32 %x) {
; CHECK: or i32 {{.*}}, 1
; CHECK: ret
}
+
+define i1 @test38(i1 %cond) {
+ %zero = alloca i32
+ %one = alloca i32
+ %ptr = select i1 %cond, i32* %zero, i32* %one
+ %isnull = icmp eq i32* %ptr, null
+ ret i1 %isnull
+; CHECK: @test38
+; CHECK: ret i1 false
+}
+
+define i1 @test39(i1 %cond, double %x) {
+ %s = select i1 %cond, double %x, double 0x7FF0000000000000 ; RHS = +infty
+ %cmp = fcmp ule double %x, %s
+ ret i1 %cmp
+; CHECK: @test39
+; CHECK: ret i1 true
+}
+
+define i1 @test40(i1 %cond) {
+ %a = alloca i32
+ %b = alloca i32
+ %c = alloca i32
+ %s = select i1 %cond, i32* %a, i32* %b
+ %r = icmp eq i32* %s, %c
+ ret i1 %r
+; CHECK: @test40
+; CHECK: ret i1 false
+}
+
+define i32 @test41(i1 %cond, i32 %x, i32 %y) {
+ %z = and i32 %x, %y
+ %s = select i1 %cond, i32 %y, i32 %z
+ %r = and i32 %x, %s
+ ret i32 %r
+; CHECK: @test41
+; CHECK-NEXT: and i32 %x, %y
+; CHECK-NEXT: ret i32
+}
+
+define i32 @test42(i32 %x, i32 %y) {
+ %b = add i32 %y, -1
+ %cond = icmp eq i32 %x, 0
+ %c = select i1 %cond, i32 %b, i32 %y
+ ret i32 %c
+; CHECK: @test42
+; CHECK-NEXT: %cond = icmp eq i32 %x, 0
+; CHECK-NEXT: %b = sext i1 %cond to i32
+; CHECK-NEXT: %c = add i32 %b, %y
+; CHECK-NEXT: ret i32 %c
+}
+
+define i64 @test43(i32 %a) nounwind {
+ %a_ext = sext i32 %a to i64
+ %is_a_nonnegative = icmp sgt i32 %a, -1
+ %max = select i1 %is_a_nonnegative, i64 %a_ext, i64 0
+ ret i64 %max
+; CHECK: @test43
+; CHECK-NEXT: %a_ext = sext i32 %a to i64
+; CHECK-NEXT: %is_a_nonnegative = icmp slt i64 %a_ext, 0
+; CHECK-NEXT: %max = select i1 %is_a_nonnegative, i64 0, i64 %a_ext
+; CHECK-NEXT: ret i64 %max
+}
+
+define i64 @test44(i32 %a) nounwind {
+ %a_ext = sext i32 %a to i64
+ %is_a_nonpositive = icmp slt i32 %a, 1
+ %min = select i1 %is_a_nonpositive, i64 %a_ext, i64 0
+ ret i64 %min
+; CHECK: @test44
+; CHECK-NEXT: %a_ext = sext i32 %a to i64
+; CHECK-NEXT: %is_a_nonpositive = icmp sgt i64 %a_ext, 0
+; CHECK-NEXT: %min = select i1 %is_a_nonpositive, i64 0, i64 %a_ext
+; CHECK-NEXT: ret i64 %min
+}
+define i64 @test45(i32 %a) nounwind {
+ %a_ext = zext i32 %a to i64
+ %is_a_nonnegative = icmp ugt i32 %a, 2
+ %max = select i1 %is_a_nonnegative, i64 %a_ext, i64 3
+ ret i64 %max
+; CHECK: @test45
+; CHECK-NEXT: %a_ext = zext i32 %a to i64
+; CHECK-NEXT: %is_a_nonnegative = icmp ult i64 %a_ext, 3
+; CHECK-NEXT: %max = select i1 %is_a_nonnegative, i64 3, i64 %a_ext
+; CHECK-NEXT: ret i64 %max
+}
+
+define i64 @test46(i32 %a) nounwind {
+ %a_ext = zext i32 %a to i64
+ %is_a_nonpositive = icmp ult i32 %a, 3
+ %min = select i1 %is_a_nonpositive, i64 %a_ext, i64 2
+ ret i64 %min
+; CHECK: @test46
+; CHECK-NEXT: %a_ext = zext i32 %a to i64
+; CHECK-NEXT: %is_a_nonpositive = icmp ugt i64 %a_ext, 2
+; CHECK-NEXT: %min = select i1 %is_a_nonpositive, i64 2, i64 %a_ext
+; CHECK-NEXT: ret i64 %min
+}
+define i64 @test47(i32 %a) nounwind {
+ %a_ext = sext i32 %a to i64
+ %is_a_nonnegative = icmp ugt i32 %a, 2
+ %max = select i1 %is_a_nonnegative, i64 %a_ext, i64 3
+ ret i64 %max
+; CHECK: @test47
+; CHECK-NEXT: %a_ext = sext i32 %a to i64
+; CHECK-NEXT: %is_a_nonnegative = icmp ult i64 %a_ext, 3
+; CHECK-NEXT: %max = select i1 %is_a_nonnegative, i64 3, i64 %a_ext
+; CHECK-NEXT: ret i64 %max
+}
+
+define i64 @test48(i32 %a) nounwind {
+ %a_ext = sext i32 %a to i64
+ %is_a_nonpositive = icmp ult i32 %a, 3
+ %min = select i1 %is_a_nonpositive, i64 %a_ext, i64 2
+ ret i64 %min
+; CHECK: @test48
+; CHECK-NEXT: %a_ext = sext i32 %a to i64
+; CHECK-NEXT: %is_a_nonpositive = icmp ugt i64 %a_ext, 2
+; CHECK-NEXT: %min = select i1 %is_a_nonpositive, i64 2, i64 %a_ext
+; CHECK-NEXT: ret i64 %min
+}
+
+define i64 @test49(i32 %a) nounwind {
+ %a_ext = sext i32 %a to i64
+ %is_a_nonpositive = icmp ult i32 %a, 3
+ %min = select i1 %is_a_nonpositive, i64 2, i64 %a_ext
+ ret i64 %min
+; CHECK: @test49
+; CHECK-NEXT: %a_ext = sext i32 %a to i64
+; CHECK-NEXT: %is_a_nonpositive = icmp ugt i64 %a_ext, 2
+; CHECK-NEXT: %min = select i1 %is_a_nonpositive, i64 %a_ext, i64 2
+; CHECK-NEXT: ret i64 %min
+}
+define i64 @test50(i32 %a) nounwind {
+ %is_a_nonpositive = icmp ult i32 %a, 3
+ %a_ext = sext i32 %a to i64
+ %min = select i1 %is_a_nonpositive, i64 2, i64 %a_ext
+ ret i64 %min
+; CHECK: @test50
+; CHECK-NEXT: %a_ext = sext i32 %a to i64
+; CHECK-NEXT: %is_a_nonpositive = icmp ugt i64 %a_ext, 2
+; CHECK-NEXT: %min = select i1 %is_a_nonpositive, i64 %a_ext, i64 2
+; CHECK-NEXT: ret i64 %min
+}
+
+; PR8994
+
+; This select instruction can't be eliminated because trying to do so would
+; change the number of vector elements. This used to assert.
+define i48 @test51(<3 x i1> %icmp, <3 x i16> %tmp) {
+; CHECK: @test51
+ %select = select <3 x i1> %icmp, <3 x i16> zeroinitializer, <3 x i16> %tmp
+; CHECK: select <3 x i1>
+ %tmp2 = bitcast <3 x i16> %select to i48
+ ret i48 %tmp2
+}
+
+; PR8575
+
+define i32 @test52(i32 %n, i32 %m) nounwind {
+; CHECK: @test52
+ %cmp = icmp sgt i32 %n, %m
+ %. = select i1 %cmp, i32 1, i32 3
+ %add = add nsw i32 %., 3
+ %storemerge = select i1 %cmp, i32 %., i32 %add
+; CHECK: select i1 %cmp, i32 1, i32 6
+ ret i32 %storemerge
+}
+
diff --git a/test/Transforms/InstCombine/sext.ll b/test/Transforms/InstCombine/sext.ll
index 6deee1f..60669b7 100644
--- a/test/Transforms/InstCombine/sext.ll
+++ b/test/Transforms/InstCombine/sext.ll
@@ -110,7 +110,7 @@ entry:
ret i32 %b
; CHECK: @test10
; CHECK: shl i32 %i, 30
-; CHECK-NEXT: ashr i32
+; CHECK-NEXT: ashr exact i32
; CHECK-NEXT: ret i32
}
diff --git a/test/Transforms/InstCombine/shift.ll b/test/Transforms/InstCombine/shift.ll
index 871e9fe..7fab1d2 100644
--- a/test/Transforms/InstCombine/shift.ll
+++ b/test/Transforms/InstCombine/shift.ll
@@ -35,18 +35,32 @@ define i32 @test4(i8 %A) {
define i32 @test5(i32 %A) {
; CHECK: @test5
-; CHECK: ret i32 0
+; CHECK: ret i32 undef
%B = lshr i32 %A, 32 ;; shift all bits out
ret i32 %B
}
define i32 @test5a(i32 %A) {
; CHECK: @test5a
-; CHECK: ret i32 0
+; CHECK: ret i32 undef
%B = shl i32 %A, 32 ;; shift all bits out
ret i32 %B
}
+define i32 @test5b() {
+; CHECK: @test5b
+; CHECK: ret i32 -1
+ %B = ashr i32 undef, 2 ;; top two bits must be equal, so not undef
+ ret i32 %B
+}
+
+define i32 @test5b2(i32 %A) {
+; CHECK: @test5b2
+; CHECK: ret i32 -1
+ %B = ashr i32 undef, %A ;; top %A bits must be equal, so not undef
+ ret i32 %B
+}
+
define i32 @test6(i32 %A) {
; CHECK: @test6
; CHECK-NEXT: mul i32 %A, 6
@@ -437,7 +451,37 @@ entry:
ret i64 %tmp46
; CHECK: @test37
-; CHECK: %tmp23 = shl i128 %tmp22, 32
+; CHECK: %tmp23 = shl nuw nsw i128 %tmp22, 32
; CHECK: %ins = or i128 %tmp23, %A
; CHECK: %tmp46 = trunc i128 %ins to i64
}
+
+define i32 @test38(i32 %x) nounwind readnone {
+ %rem = srem i32 %x, 32
+ %shl = shl i32 1, %rem
+ ret i32 %shl
+; CHECK: @test38
+; CHECK-NEXT: and i32 %x, 31
+; CHECK-NEXT: shl i32 1
+; CHECK-NEXT: ret i32
+}
+
+; <rdar://problem/8756731>
+; CHECK: @test39
+define i8 @test39(i32 %a0) {
+entry:
+ %tmp4 = trunc i32 %a0 to i8
+; CHECK: and i8 %tmp49, 64
+ %tmp5 = shl i8 %tmp4, 5
+ %tmp48 = and i8 %tmp5, 32
+ %tmp49 = lshr i8 %tmp48, 5
+ %tmp50 = mul i8 %tmp49, 64
+ %tmp51 = xor i8 %tmp50, %tmp5
+; CHECK: and i8 %0, 16
+ %tmp52 = and i8 %tmp51, -128
+ %tmp53 = lshr i8 %tmp52, 7
+ %tmp54 = mul i8 %tmp53, 16
+ %tmp55 = xor i8 %tmp54, %tmp51
+; CHECK: ret i8 %tmp551
+ ret i8 %tmp55
+}
diff --git a/test/Transforms/InstCombine/signext.ll b/test/Transforms/InstCombine/signext.ll
index 49384d6..ecee983 100644
--- a/test/Transforms/InstCombine/signext.ll
+++ b/test/Transforms/InstCombine/signext.ll
@@ -9,7 +9,7 @@ define i32 @test1(i32 %x) {
ret i32 %tmp.3
; CHECK: @test1
; CHECK: %sext = shl i32 %x, 16
-; CHECK: %tmp.3 = ashr i32 %sext, 16
+; CHECK: %tmp.3 = ashr exact i32 %sext, 16
; CHECK: ret i32 %tmp.3
}
@@ -20,7 +20,7 @@ define i32 @test2(i32 %x) {
ret i32 %tmp.3
; CHECK: @test2
; CHECK: %sext = shl i32 %x, 16
-; CHECK: %tmp.3 = ashr i32 %sext, 16
+; CHECK: %tmp.3 = ashr exact i32 %sext, 16
; CHECK: ret i32 %tmp.3
}
@@ -51,7 +51,7 @@ define i32 @test5(i32 %x) {
ret i32 %tmp.3
; CHECK: @test5
; CHECK: %sext = shl i32 %x, 24
-; CHECK: %tmp.3 = ashr i32 %sext, 24
+; CHECK: %tmp.3 = ashr exact i32 %sext, 24
; CHECK: ret i32 %tmp.3
}
@@ -61,7 +61,7 @@ define i32 @test6(i32 %x) {
ret i32 %tmp.4
; CHECK: @test6
; CHECK: %tmp.2 = shl i32 %x, 16
-; CHECK: %tmp.4 = ashr i32 %tmp.2, 16
+; CHECK: %tmp.4 = ashr exact i32 %tmp.2, 16
; CHECK: ret i32 %tmp.4
}
@@ -82,6 +82,6 @@ entry:
%sub = add i32 %xor, -67108864 ; <i32> [#uses=1]
ret i32 %sub
; CHECK: @test8
-; CHECK: %sub = ashr i32 %x, 5
-; CHECK: ret i32 %sub
+; CHECK: %shr = ashr i32 %x, 5
+; CHECK: ret i32 %shr
}
diff --git a/test/Transforms/InstCombine/sub.ll b/test/Transforms/InstCombine/sub.ll
index 29bd7be..9656a7e 100644
--- a/test/Transforms/InstCombine/sub.ll
+++ b/test/Transforms/InstCombine/sub.ll
@@ -40,7 +40,7 @@ define i32 @test5(i32 %A, i32 %B, i32 %C) {
%E = sub i32 %A, %D
ret i32 %E
; CHECK: @test5
-; CHECK: %D = sub i32 %C, %B
+; CHECK: %D1 = sub i32 %C, %B
; CHECK: %E = add
; CHECK: ret i32 %E
}
@@ -209,7 +209,7 @@ define i1 @test22(i32 %a, i32 %b) zeroext nounwind {
%tmp5 = icmp eq i32 %tmp2, %tmp4
ret i1 %tmp5
; CHECK: @test22
-; CHECK: %tmp5 = icmp eq i32 %a, %b
+; CHECK: %tmp5 = icmp eq i32 %b, %a
; CHECK: ret i1 %tmp5
}
@@ -256,7 +256,7 @@ define i64 @test24b(i8* %P, i64 %A){
%G = sub i64 %C, ptrtoint ([42 x i16]* @Arr to i64)
ret i64 %G
; CHECK: @test24b
-; CHECK-NEXT: shl i64 %A, 1
+; CHECK-NEXT: shl nuw i64 %A, 1
; CHECK-NEXT: ret i64
}
@@ -267,7 +267,7 @@ define i64 @test25(i8* %P, i64 %A){
%G = sub i64 %C, ptrtoint (i16* getelementptr ([42 x i16]* @Arr, i64 1, i64 0) to i64)
ret i64 %G
; CHECK: @test25
-; CHECK-NEXT: shl i64 %A, 1
+; CHECK-NEXT: shl nuw i64 %A, 1
; CHECK-NEXT: add i64 {{.*}}, -84
; CHECK-NEXT: ret i64
}
@@ -281,3 +281,23 @@ define i32 @test26(i32 %x) {
; CHECK-NEXT: ret i32
}
+define i32 @test27(i32 %x, i32 %y) {
+ %mul = mul i32 %y, -8
+ %sub = sub i32 %x, %mul
+ ret i32 %sub
+; CHECK: @test27
+; CHECK-NEXT: shl i32 %y, 3
+; CHECK-NEXT: add i32
+; CHECK-NEXT: ret i32
+}
+
+define i32 @test28(i32 %x, i32 %y, i32 %z) {
+ %neg = sub i32 0, %z
+ %mul = mul i32 %neg, %y
+ %sub = sub i32 %x, %mul
+ ret i32 %sub
+; CHECK: @test28
+; CHECK-NEXT: mul i32 %z, %y
+; CHECK-NEXT: add i32
+; CHECK-NEXT: ret i32
+}
diff --git a/test/Transforms/InstCombine/trunc.ll b/test/Transforms/InstCombine/trunc.ll
index f98bfd9..6ec342a 100644
--- a/test/Transforms/InstCombine/trunc.ll
+++ b/test/Transforms/InstCombine/trunc.ll
@@ -24,7 +24,7 @@ define i64 @test2(i64 %a) {
ret i64 %d
; CHECK: @test2
; CHECK: shl i64 %a, 36
-; CHECK: %d = ashr i64 {{.*}}, 36
+; CHECK: %d = ashr exact i64 {{.*}}, 36
; CHECK: ret i64 %d
}
define i64 @test3(i64 %a) {
@@ -92,8 +92,28 @@ define i64 @test8(i32 %A, i32 %B) {
; CHECK: @test8
; CHECK: %tmp38 = zext i32 %A to i64
; CHECK: %tmp32 = zext i32 %B to i64
-; CHECK: %tmp33 = shl i64 %tmp32, 32
+; CHECK: %tmp33 = shl nuw i64 %tmp32, 32
; CHECK: %ins35 = or i64 %tmp33, %tmp38
; CHECK: ret i64 %ins35
}
+define i8 @test9(i32 %X) {
+ %Y = and i32 %X, 42
+ %Z = trunc i32 %Y to i8
+ ret i8 %Z
+; CHECK: @test9
+; CHECK: trunc
+; CHECK: and
+; CHECK: ret
+}
+
+; rdar://8808586
+define i8 @test10(i32 %X) {
+ %Y = trunc i32 %X to i8
+ %Z = and i8 %Y, 42
+ ret i8 %Z
+; CHECK: @test10
+; CHECK: trunc
+; CHECK: and
+; CHECK: ret
+}
diff --git a/test/Transforms/InstCombine/vec_demanded_elts-2.ll b/test/Transforms/InstCombine/vec_demanded_elts-2.ll
deleted file mode 100644
index 4159361..0000000
--- a/test/Transforms/InstCombine/vec_demanded_elts-2.ll
+++ /dev/null
@@ -1,19 +0,0 @@
-; RUN: opt < %s -instcombine -S | not grep extractelement
-
-define void @get_image() nounwind {
-entry:
- %0 = call i32 @fgetc(i8* null) nounwind ; <i32> [#uses=1]
- %1 = trunc i32 %0 to i8 ; <i8> [#uses=1]
- %tmp2 = insertelement <100 x i8> zeroinitializer, i8 %1, i32 1 ; <<100 x i8>> [#uses=1]
- %tmp1 = extractelement <100 x i8> %tmp2, i32 0 ; <i8> [#uses=1]
- %2 = icmp eq i8 %tmp1, 80 ; <i1> [#uses=1]
- br i1 %2, label %bb2, label %bb3
-
-bb2: ; preds = %entry
- br label %bb3
-
-bb3: ; preds = %bb2, %entry
- unreachable
-}
-
-declare i32 @fgetc(i8*)
diff --git a/test/Transforms/InstCombine/vec_demanded_elts-3.ll b/test/Transforms/InstCombine/vec_demanded_elts-3.ll
deleted file mode 100644
index 62e4370..0000000
--- a/test/Transforms/InstCombine/vec_demanded_elts-3.ll
+++ /dev/null
@@ -1,14 +0,0 @@
-; RUN: opt < %s -instcombine -S | not grep load
-; PR4340
-
-define void @vac(<4 x float>* nocapture %a) nounwind {
-entry:
- %tmp1 = load <4 x float>* %a ; <<4 x float>> [#uses=1]
- %vecins = insertelement <4 x float> %tmp1, float 0.000000e+00, i32 0 ; <<4 x float>> [#uses=1]
- %vecins4 = insertelement <4 x float> %vecins, float 0.000000e+00, i32 1; <<4 x float>> [#uses=1]
- %vecins6 = insertelement <4 x float> %vecins4, float 0.000000e+00, i32 2; <<4 x float>> [#uses=1]
- %vecins8 = insertelement <4 x float> %vecins6, float 0.000000e+00, i32 3; <<4 x float>> [#uses=1]
- store <4 x float> %vecins8, <4 x float>* %a
- ret void
-}
-
diff --git a/test/Transforms/InstCombine/vec_demanded_elts.ll b/test/Transforms/InstCombine/vec_demanded_elts.ll
index 2009a77..9f308aa 100644
--- a/test/Transforms/InstCombine/vec_demanded_elts.ll
+++ b/test/Transforms/InstCombine/vec_demanded_elts.ll
@@ -1,17 +1,13 @@
-; RUN: opt < %s -instcombine -S | \
-; RUN: grep {fadd float}
-; RUN: opt < %s -instcombine -S | \
-; RUN: grep {fmul float}
-; RUN: opt < %s -instcombine -S | \
-; RUN: not grep {insertelement.*0.00}
-; RUN: opt < %s -instcombine -S | \
-; RUN: not grep {call.*llvm.x86.sse.mul}
-; RUN: opt < %s -instcombine -S | \
-; RUN: not grep {call.*llvm.x86.sse.sub}
-; END.
+; RUN: opt < %s -instcombine -S | FileCheck %s
define i16 @test1(float %f) {
entry:
+; CHECK: @test1
+; CHECK: fmul float
+; CHECK-NOT: insertelement {{.*}} 0.00
+; CHECK-NOT: call {{.*}} @llvm.x86.sse.mul
+; CHECK-NOT: call {{.*}} @llvm.x86.sse.sub
+; CHECK: ret
%tmp = insertelement <4 x float> undef, float %f, i32 0 ; <<4 x float>> [#uses=1]
%tmp10 = insertelement <4 x float> %tmp, float 0.000000e+00, i32 1 ; <<4 x float>> [#uses=1]
%tmp11 = insertelement <4 x float> %tmp10, float 0.000000e+00, i32 2 ; <<4 x float>> [#uses=1]
@@ -26,16 +22,104 @@ entry:
}
define i32 @test2(float %f) {
- %tmp5 = fmul float %f, %f
- %tmp9 = insertelement <4 x float> undef, float %tmp5, i32 0
- %tmp10 = insertelement <4 x float> %tmp9, float 0.000000e+00, i32 1
- %tmp11 = insertelement <4 x float> %tmp10, float 0.000000e+00, i32 2
- %tmp12 = insertelement <4 x float> %tmp11, float 0.000000e+00, i32 3
- %tmp19 = bitcast <4 x float> %tmp12 to <4 x i32>
- %tmp21 = extractelement <4 x i32> %tmp19, i32 0
- ret i32 %tmp21
+; CHECK: @test2
+; CHECK-NOT: insertelement
+; CHECK-NOT: extractelement
+; CHECK: ret
+ %tmp5 = fmul float %f, %f
+ %tmp9 = insertelement <4 x float> undef, float %tmp5, i32 0
+ %tmp10 = insertelement <4 x float> %tmp9, float 0.000000e+00, i32 1
+ %tmp11 = insertelement <4 x float> %tmp10, float 0.000000e+00, i32 2
+ %tmp12 = insertelement <4 x float> %tmp11, float 0.000000e+00, i32 3
+ %tmp19 = bitcast <4 x float> %tmp12 to <4 x i32>
+ %tmp21 = extractelement <4 x i32> %tmp19, i32 0
+ ret i32 %tmp21
}
+define i64 @test3(float %f, double %d) {
+; CHECK: @test3
+; CHECK-NOT: insertelement {{.*}} 0.00
+; CHECK: ret
+entry:
+ %v00 = insertelement <4 x float> undef, float %f, i32 0
+ %v01 = insertelement <4 x float> %v00, float 0.000000e+00, i32 1
+ %v02 = insertelement <4 x float> %v01, float 0.000000e+00, i32 2
+ %v03 = insertelement <4 x float> %v02, float 0.000000e+00, i32 3
+ %tmp0 = tail call i32 @llvm.x86.sse.cvtss2si(<4 x float> %v03)
+ %v10 = insertelement <4 x float> undef, float %f, i32 0
+ %v11 = insertelement <4 x float> %v10, float 0.000000e+00, i32 1
+ %v12 = insertelement <4 x float> %v11, float 0.000000e+00, i32 2
+ %v13 = insertelement <4 x float> %v12, float 0.000000e+00, i32 3
+ %tmp1 = tail call i64 @llvm.x86.sse.cvtss2si64(<4 x float> %v13)
+ %v20 = insertelement <4 x float> undef, float %f, i32 0
+ %v21 = insertelement <4 x float> %v20, float 0.000000e+00, i32 1
+ %v22 = insertelement <4 x float> %v21, float 0.000000e+00, i32 2
+ %v23 = insertelement <4 x float> %v22, float 0.000000e+00, i32 3
+ %tmp2 = tail call i32 @llvm.x86.sse.cvttss2si(<4 x float> %v23)
+ %v30 = insertelement <4 x float> undef, float %f, i32 0
+ %v31 = insertelement <4 x float> %v30, float 0.000000e+00, i32 1
+ %v32 = insertelement <4 x float> %v31, float 0.000000e+00, i32 2
+ %v33 = insertelement <4 x float> %v32, float 0.000000e+00, i32 3
+ %tmp3 = tail call i64 @llvm.x86.sse.cvttss2si64(<4 x float> %v33)
+ %v40 = insertelement <2 x double> undef, double %d, i32 0
+ %v41 = insertelement <2 x double> %v40, double 0.000000e+00, i32 1
+ %tmp4 = tail call i32 @llvm.x86.sse2.cvtsd2si(<2 x double> %v41)
+ %v50 = insertelement <2 x double> undef, double %d, i32 0
+ %v51 = insertelement <2 x double> %v50, double 0.000000e+00, i32 1
+ %tmp5 = tail call i64 @llvm.x86.sse2.cvtsd2si64(<2 x double> %v51)
+ %v60 = insertelement <2 x double> undef, double %d, i32 0
+ %v61 = insertelement <2 x double> %v60, double 0.000000e+00, i32 1
+ %tmp6 = tail call i32 @llvm.x86.sse2.cvttsd2si(<2 x double> %v61)
+ %v70 = insertelement <2 x double> undef, double %d, i32 0
+ %v71 = insertelement <2 x double> %v70, double 0.000000e+00, i32 1
+ %tmp7 = tail call i64 @llvm.x86.sse2.cvttsd2si64(<2 x double> %v71)
+ %tmp8 = add i32 %tmp0, %tmp2
+ %tmp9 = add i32 %tmp4, %tmp6
+ %tmp10 = add i32 %tmp8, %tmp9
+ %tmp11 = sext i32 %tmp10 to i64
+ %tmp12 = add i64 %tmp1, %tmp3
+ %tmp13 = add i64 %tmp5, %tmp7
+ %tmp14 = add i64 %tmp12, %tmp13
+ %tmp15 = add i64 %tmp11, %tmp14
+ ret i64 %tmp15
+}
+
+define void @get_image() nounwind {
+; CHECK: @get_image
+; CHECK-NOT: extractelement
+; CHECK: unreachable
+entry:
+ %0 = call i32 @fgetc(i8* null) nounwind ; <i32> [#uses=1]
+ %1 = trunc i32 %0 to i8 ; <i8> [#uses=1]
+ %tmp2 = insertelement <100 x i8> zeroinitializer, i8 %1, i32 1 ; <<100 x i8>> [#uses=1]
+ %tmp1 = extractelement <100 x i8> %tmp2, i32 0 ; <i8> [#uses=1]
+ %2 = icmp eq i8 %tmp1, 80 ; <i1> [#uses=1]
+ br i1 %2, label %bb2, label %bb3
+
+bb2: ; preds = %entry
+ br label %bb3
+
+bb3: ; preds = %bb2, %entry
+ unreachable
+}
+
+; PR4340
+define void @vac(<4 x float>* nocapture %a) nounwind {
+; CHECK: @vac
+; CHECK-NOT: load
+; CHECK: ret
+entry:
+ %tmp1 = load <4 x float>* %a ; <<4 x float>> [#uses=1]
+ %vecins = insertelement <4 x float> %tmp1, float 0.000000e+00, i32 0 ; <<4 x float>> [#uses=1]
+ %vecins4 = insertelement <4 x float> %vecins, float 0.000000e+00, i32 1; <<4 x float>> [#uses=1]
+ %vecins6 = insertelement <4 x float> %vecins4, float 0.000000e+00, i32 2; <<4 x float>> [#uses=1]
+ %vecins8 = insertelement <4 x float> %vecins6, float 0.000000e+00, i32 3; <<4 x float>> [#uses=1]
+ store <4 x float> %vecins8, <4 x float>* %a
+ ret void
+}
+
+declare i32 @fgetc(i8*)
+
declare <4 x float> @llvm.x86.sse.sub.ss(<4 x float>, <4 x float>)
declare <4 x float> @llvm.x86.sse.mul.ss(<4 x float>, <4 x float>)
@@ -44,4 +128,11 @@ declare <4 x float> @llvm.x86.sse.min.ss(<4 x float>, <4 x float>)
declare <4 x float> @llvm.x86.sse.max.ss(<4 x float>, <4 x float>)
+declare i32 @llvm.x86.sse.cvtss2si(<4 x float>)
+declare i64 @llvm.x86.sse.cvtss2si64(<4 x float>)
declare i32 @llvm.x86.sse.cvttss2si(<4 x float>)
+declare i64 @llvm.x86.sse.cvttss2si64(<4 x float>)
+declare i32 @llvm.x86.sse2.cvtsd2si(<2 x double>)
+declare i64 @llvm.x86.sse2.cvtsd2si64(<2 x double>)
+declare i32 @llvm.x86.sse2.cvttsd2si(<2 x double>)
+declare i64 @llvm.x86.sse2.cvttsd2si64(<2 x double>)
diff --git a/test/Transforms/InstCombine/vec_sext.ll b/test/Transforms/InstCombine/vec_sext.ll
new file mode 100644
index 0000000..d7ab96b
--- /dev/null
+++ b/test/Transforms/InstCombine/vec_sext.ll
@@ -0,0 +1,22 @@
+; RUN: opt < %s -instcombine -S | FileCheck %s
+
+define <4 x i32> @psignd_3(<4 x i32> %a, <4 x i32> %b) nounwind ssp {
+entry:
+ %cmp = icmp slt <4 x i32> %b, zeroinitializer
+ %sext = sext <4 x i1> %cmp to <4 x i32>
+ %sub = sub nsw <4 x i32> zeroinitializer, %a
+ %0 = icmp slt <4 x i32> %sext, zeroinitializer
+ %sext3 = sext <4 x i1> %0 to <4 x i32>
+ %1 = xor <4 x i32> %sext3, <i32 -1, i32 -1, i32 -1, i32 -1>
+ %2 = and <4 x i32> %a, %1
+ %3 = and <4 x i32> %sext3, %sub
+ %cond = or <4 x i32> %2, %3
+ ret <4 x i32> %cond
+
+; CHECK: ashr <4 x i32> %b, <i32 31, i32 31, i32 31, i32 31>
+; CHECK: sub nsw <4 x i32> zeroinitializer, %a
+; CHECK: xor <4 x i32> %b.lobit, <i32 -1, i32 -1, i32 -1, i32 -1>
+; CHECK: and <4 x i32> %a, %0
+; CHECK: and <4 x i32> %b.lobit, %sub
+; CHECK: or <4 x i32> %1, %2
+}
diff --git a/test/Transforms/InstCombine/vec_shuffle.ll b/test/Transforms/InstCombine/vec_shuffle.ll
index 5132a8f..bd36e9e 100644
--- a/test/Transforms/InstCombine/vec_shuffle.ll
+++ b/test/Transforms/InstCombine/vec_shuffle.ll
@@ -87,3 +87,26 @@ define <4 x i8> @test9(<16 x i8> %tmp6) nounwind {
%tmp9 = shufflevector <4 x i8> %tmp7, <4 x i8> undef, <4 x i32> < i32 3, i32 1, i32 2, i32 0 > ; <<4 x i8>> [#uses=1]
ret <4 x i8> %tmp9
}
+
+; Same as test9, but make sure that "undef" mask values are not confused with
+; mask values of 2*N, where N is the mask length. These shuffles should not
+; be folded (because [8,9,4,8] may not be a mask supported by the target).
+define <4 x i8> @test9a(<16 x i8> %tmp6) nounwind {
+; CHECK: @test9a
+; CHECK-NEXT: shufflevector
+; CHECK-NEXT: shufflevector
+; CHECK-NEXT: ret
+ %tmp7 = shufflevector <16 x i8> %tmp6, <16 x i8> undef, <4 x i32> < i32 undef, i32 9, i32 4, i32 8 > ; <<4 x i8>> [#uses=1]
+ %tmp9 = shufflevector <4 x i8> %tmp7, <4 x i8> undef, <4 x i32> < i32 3, i32 1, i32 2, i32 0 > ; <<4 x i8>> [#uses=1]
+ ret <4 x i8> %tmp9
+}
+
+; Redundant vector splats should be removed. Radar 8597790.
+define <4 x i32> @test10(<4 x i32> %tmp5) nounwind {
+; CHECK: @test10
+; CHECK-NEXT: shufflevector
+; CHECK-NEXT: ret
+ %tmp6 = shufflevector <4 x i32> %tmp5, <4 x i32> undef, <4 x i32> <i32 1, i32 undef, i32 undef, i32 undef>
+ %tmp7 = shufflevector <4 x i32> %tmp6, <4 x i32> undef, <4 x i32> zeroinitializer
+ ret <4 x i32> %tmp7
+}
diff --git a/test/Transforms/InstCombine/vector-casts.ll b/test/Transforms/InstCombine/vector-casts.ll
index 24bd04d..e931dc7 100644
--- a/test/Transforms/InstCombine/vector-casts.ll
+++ b/test/Transforms/InstCombine/vector-casts.ll
@@ -121,3 +121,31 @@ define <2 x double> @fc(<2 x double> %t) {
%b = sitofp <2 x i64> %a to <2 x double>
ret <2 x double> %b
}
+
+; PR9228
+; This was a crasher, so no CHECK statements.
+define <4 x float> @f(i32 %a) nounwind alwaysinline {
+; CHECK: @f
+entry:
+ %dim = insertelement <4 x i32> undef, i32 %a, i32 0
+ %dim30 = insertelement <4 x i32> %dim, i32 %a, i32 1
+ %dim31 = insertelement <4 x i32> %dim30, i32 %a, i32 2
+ %dim32 = insertelement <4 x i32> %dim31, i32 %a, i32 3
+
+ %offset_ptr = getelementptr <4 x float>* null, i32 1
+ %offset_int = ptrtoint <4 x float>* %offset_ptr to i64
+ %sizeof32 = trunc i64 %offset_int to i32
+
+ %smearinsert33 = insertelement <4 x i32> undef, i32 %sizeof32, i32 0
+ %smearinsert34 = insertelement <4 x i32> %smearinsert33, i32 %sizeof32, i32 1
+ %smearinsert35 = insertelement <4 x i32> %smearinsert34, i32 %sizeof32, i32 2
+ %smearinsert36 = insertelement <4 x i32> %smearinsert35, i32 %sizeof32, i32 3
+
+ %delta_scale = mul <4 x i32> %dim32, %smearinsert36
+ %offset_delta = add <4 x i32> zeroinitializer, %delta_scale
+
+ %offset_varying_delta = add <4 x i32> %offset_delta, undef
+
+ ret <4 x float> undef
+}
+
diff --git a/test/Transforms/InstCombine/xor2.ll b/test/Transforms/InstCombine/xor2.ll
index 67f05ef..89f00bd 100644
--- a/test/Transforms/InstCombine/xor2.ll
+++ b/test/Transforms/InstCombine/xor2.ll
@@ -34,7 +34,7 @@ define i32 @test2(i32 %tmp1) {
define i32 @test3(i32 %tmp1) {
; CHECK: @test3
; CHECK-NEXT: and i32 %tmp1, 32
-; CHECK-NEXT: or i32 %tmp, 8
+; CHECK-NEXT: or i32 %ovm, 8
; CHECK-NEXT: ret i32
%ovm = or i32 %tmp1, 145
%ov31 = and i32 %ovm, 177
OpenPOWER on IntegriCloud