diff options
Diffstat (limited to 'test/Transforms/InstCombine')
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 |