diff options
Diffstat (limited to 'test/Transforms/InstCombine')
21 files changed, 799 insertions, 15 deletions
diff --git a/test/Transforms/InstCombine/2011-03-08-SRemMinusOneBadOpt.ll b/test/Transforms/InstCombine/2011-03-08-SRemMinusOneBadOpt.ll new file mode 100644 index 000000000000..6a3e3e40e6d4 --- /dev/null +++ b/test/Transforms/InstCombine/2011-03-08-SRemMinusOneBadOpt.ll @@ -0,0 +1,12 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s +; PR9346 + +define i32 @test(i64 %x) nounwind { +; CHECK: ret i32 0 +entry: + %or = or i64 %x, 4294967294 + %conv = trunc i64 %or to i32 + %rem.i = srem i32 %conv, -1 + ret i32 %rem.i +} + diff --git a/test/Transforms/InstCombine/ExtractCast.ll b/test/Transforms/InstCombine/ExtractCast.ll new file mode 100644 index 000000000000..5ebbefd97b3e --- /dev/null +++ b/test/Transforms/InstCombine/ExtractCast.ll @@ -0,0 +1,27 @@ +; RUN: opt < %s -instcombine -S -o - | FileCheck %s + +; CHECK: @a +define i32 @a(<4 x i64> %I) { +entry: +; CHECK-NOT: trunc <4 x i64> + %J = trunc <4 x i64> %I to <4 x i32> + %K = extractelement <4 x i32> %J, i32 3 +; CHECK: extractelement <4 x i64> +; CHECK: trunc i64 +; CHECK: ret + ret i32 %K +} + + +; CHECK: @b +define i32 @b(<4 x float> %I) { +entry: +; CHECK-NOT: fptosi <4 x float> + %J = fptosi <4 x float> %I to <4 x i32> + %K = extractelement <4 x i32> %J, i32 3 +; CHECK: extractelement <4 x float> +; CHECK: fptosi float +; CHECK: ret + ret i32 %K +} + diff --git a/test/Transforms/InstCombine/and-or-not.ll b/test/Transforms/InstCombine/and-or-not.ll index 37ec3bc1aabb..bd878b04a350 100644 --- a/test/Transforms/InstCombine/and-or-not.ll +++ b/test/Transforms/InstCombine/and-or-not.ll @@ -4,7 +4,7 @@ ; PR1510 -; These are all equivelent to A^B +; These are all equivalent to A^B define i32 @test1(i32 %a, i32 %b) { entry: diff --git a/test/Transforms/InstCombine/and2.ll b/test/Transforms/InstCombine/and2.ll index d898ea3b037a..a8881522eac4 100644 --- a/test/Transforms/InstCombine/and2.ll +++ b/test/Transforms/InstCombine/and2.ll @@ -26,3 +26,12 @@ define i32 @test3(i32 %X, i32 %Y) { ; CHECK-NEXT: and i32 %X, %Y ; CHECK-NEXT: ret } + +define i1 @test4(i32 %X) { + %a = icmp ult i32 %X, 31 + %b = icmp slt i32 %X, 0 + %c = and i1 %a, %b + ret i1 %c +; CHECK: @test4 +; CHECK-NEXT: ret i1 false +} diff --git a/test/Transforms/InstCombine/debuginfo.ll b/test/Transforms/InstCombine/debuginfo.ll new file mode 100644 index 000000000000..f6892fc3e1f9 --- /dev/null +++ b/test/Transforms/InstCombine/debuginfo.ll @@ -0,0 +1,57 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +declare void @llvm.dbg.declare(metadata, metadata) nounwind readnone + +declare i64 @llvm.objectsize.i64(i8*, i1) nounwind readnone + +declare i8* @foo(i8*, i32, i64, i64) nounwind + +define hidden i8* @foobar(i8* %__dest, i32 %__val, i64 %__len) nounwind inlinehint ssp { +entry: + %__dest.addr = alloca i8*, align 8 + %__val.addr = alloca i32, align 4 + %__len.addr = alloca i64, align 8 + store i8* %__dest, i8** %__dest.addr, align 8, !tbaa !1 +; CHECK-NOT: call void @llvm.dbg.declare +; CHECK: call void @llvm.dbg.value + call void @llvm.dbg.declare(metadata !{i8** %__dest.addr}, metadata !0), !dbg !16 + store i32 %__val, i32* %__val.addr, align 4, !tbaa !17 + call void @llvm.dbg.declare(metadata !{i32* %__val.addr}, metadata !7), !dbg !18 + store i64 %__len, i64* %__len.addr, align 8, !tbaa !19 + call void @llvm.dbg.declare(metadata !{i64* %__len.addr}, metadata !9), !dbg !20 + %tmp = load i8** %__dest.addr, align 8, !dbg !21, !tbaa !13 + %tmp1 = load i32* %__val.addr, align 4, !dbg !21, !tbaa !17 + %tmp2 = load i64* %__len.addr, align 8, !dbg !21, !tbaa !19 + %tmp3 = load i8** %__dest.addr, align 8, !dbg !21, !tbaa !13 + %0 = call i64 @llvm.objectsize.i64(i8* %tmp3, i1 false), !dbg !21 + %call = call i8* @foo(i8* %tmp, i32 %tmp1, i64 %tmp2, i64 %0), !dbg !21 + ret i8* %call, !dbg !21 +} + +!llvm.dbg.lv.foobar = !{!0, !7, !9} +!llvm.dbg.sp = !{!1} + +!0 = metadata !{i32 590081, metadata !1, metadata !"__dest", metadata !2, i32 16777294, metadata !6, i32 0} ; [ DW_TAG_arg_variable ] +!1 = metadata !{i32 589870, i32 0, metadata !2, metadata !"foobar", metadata !"foobar", metadata !"", metadata !2, i32 79, metadata !4, i1 true, i1 true, i32 0, i32 0, i32 0, i32 256, i1 true, i8* (i8*, i32, i64)* @foobar} ; [ DW_TAG_subprogram ] +!2 = metadata !{i32 589865, metadata !"string.h", metadata !"Game", metadata !3} ; [ DW_TAG_file_type ] +!3 = metadata !{i32 589841, i32 0, i32 12, metadata !"bits.c", metadata !"Game", metadata !"clang version 3.0 (trunk 127710)", i1 true, i1 true, metadata !"", i32 0} ; [ DW_TAG_compile_unit ] +!4 = metadata !{i32 589845, metadata !2, metadata !"", metadata !2, i32 0, i64 0, i64 0, i32 0, i32 0, i32 0, metadata !5, i32 0, i32 0} ; [ DW_TAG_subroutine_type ] +!5 = metadata !{metadata !6} +!6 = metadata !{i32 589839, metadata !3, metadata !"", null, i32 0, i64 64, i64 64, i64 0, i32 0, null} ; [ DW_TAG_pointer_type ] +!7 = metadata !{i32 590081, metadata !1, metadata !"__val", metadata !2, i32 33554510, metadata !8, i32 0} ; [ DW_TAG_arg_variable ] +!8 = metadata !{i32 589860, metadata !3, metadata !"int", null, i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] +!9 = metadata !{i32 590081, metadata !1, metadata !"__len", metadata !2, i32 50331726, metadata !10, i32 0} ; [ DW_TAG_arg_variable ] +!10 = metadata !{i32 589846, metadata !3, metadata !"size_t", metadata !2, i32 80, i64 0, i64 0, i64 0, i32 0, metadata !11} ; [ DW_TAG_typedef ] +!11 = metadata !{i32 589846, metadata !3, metadata !"__darwin_size_t", metadata !2, i32 90, i64 0, i64 0, i64 0, i32 0, metadata !12} ; [ DW_TAG_typedef ] +!12 = metadata !{i32 589860, metadata !3, metadata !"long unsigned int", null, i32 0, i64 64, i64 64, i64 0, i32 0, i32 7} ; [ DW_TAG_base_type ] +!13 = metadata !{metadata !"any pointer", metadata !14} +!14 = metadata !{metadata !"omnipotent char", metadata !15} +!15 = metadata !{metadata !"Simple C/C++ TBAA", null} +!16 = metadata !{i32 78, i32 28, metadata !1, null} +!17 = metadata !{metadata !"int", metadata !14} +!18 = metadata !{i32 78, i32 40, metadata !1, null} +!19 = metadata !{metadata !"long", metadata !14} +!20 = metadata !{i32 78, i32 54, metadata !1, null} +!21 = metadata !{i32 80, i32 3, metadata !22, null} +!22 = metadata !{i32 589835, metadata !23, i32 80, i32 3, metadata !2, i32 7} ; [ DW_TAG_lexical_block ] +!23 = metadata !{i32 589835, metadata !1, i32 79, i32 1, metadata !2, i32 6} ; [ DW_TAG_lexical_block ] diff --git a/test/Transforms/InstCombine/div.ll b/test/Transforms/InstCombine/div.ll index 0d1398082601..2e24f19dce4c 100644 --- a/test/Transforms/InstCombine/div.ll +++ b/test/Transforms/InstCombine/div.ll @@ -1,34 +1,44 @@ ; This test makes sure that div instructions are properly eliminated. -; RUN: opt < %s -instcombine -S | not grep div +; RUN: opt < %s -instcombine -S | FileCheck %s define i32 @test1(i32 %A) { %B = sdiv i32 %A, 1 ; <i32> [#uses=1] ret i32 %B +; CHECK: @test1 +; CHECK-NEXT: ret i32 %A } define i32 @test2(i32 %A) { ; => Shift %B = udiv i32 %A, 8 ; <i32> [#uses=1] ret i32 %B +; CHECK: @test2 +; CHECK-NEXT: lshr i32 %A, 3 } define i32 @test3(i32 %A) { ; => 0, don't need to keep traps %B = sdiv i32 0, %A ; <i32> [#uses=1] ret i32 %B +; CHECK: @test3 +; CHECK-NEXT: ret i32 0 } define i32 @test4(i32 %A) { ; 0-A %B = sdiv i32 %A, -1 ; <i32> [#uses=1] ret i32 %B +; CHECK: @test4 +; CHECK-NEXT: sub i32 0, %A } define i32 @test5(i32 %A) { %B = udiv i32 %A, -16 ; <i32> [#uses=1] %C = udiv i32 %B, -4 ; <i32> [#uses=1] ret i32 %C +; CHECK: @test5 +; CHECK-NEXT: ret i32 0 } define i1 @test6(i32 %A) { @@ -36,6 +46,8 @@ define i1 @test6(i32 %A) { ; A < 123 %C = icmp eq i32 %B, 0 ; <i1> [#uses=1] ret i1 %C +; CHECK: @test6 +; CHECK-NEXT: icmp ult i32 %A, 123 } define i1 @test7(i32 %A) { @@ -43,6 +55,9 @@ define i1 @test7(i32 %A) { ; A >= 20 && A < 30 %C = icmp eq i32 %B, 2 ; <i1> [#uses=1] ret i1 %C +; CHECK: @test7 +; CHECK-NEXT: add i32 %A, -20 +; CHECK-NEXT: icmp ult i32 } define i1 @test8(i8 %A) { @@ -50,6 +65,8 @@ define i1 @test8(i8 %A) { ; A >= 246 %C = icmp eq i8 %B, 2 ; <i1> [#uses=1] ret i1 %C +; CHECK: @test8 +; CHECK-NEXT: icmp ugt i8 %A, -11 } define i1 @test9(i8 %A) { @@ -57,28 +74,47 @@ define i1 @test9(i8 %A) { ; A < 246 %C = icmp ne i8 %B, 2 ; <i1> [#uses=1] ret i1 %C +; CHECK: @test9 +; CHECK-NEXT: icmp ult i8 %A, -10 } define i32 @test10(i32 %X, i1 %C) { %V = select i1 %C, i32 64, i32 8 ; <i32> [#uses=1] %R = udiv i32 %X, %V ; <i32> [#uses=1] ret i32 %R +; CHECK: @test10 +; CHECK-NEXT: select i1 %C, i32 6, i32 3 +; CHECK-NEXT: lshr i32 %X } define i32 @test11(i32 %X, i1 %C) { %A = select i1 %C, i32 1024, i32 32 ; <i32> [#uses=1] %B = udiv i32 %X, %A ; <i32> [#uses=1] ret i32 %B +; CHECK: @test11 +; CHECK-NEXT: select i1 %C, i32 10, i32 5 +; CHECK-NEXT: lshr i32 %X } ; PR2328 define i32 @test12(i32 %x) nounwind { %tmp3 = udiv i32 %x, %x ; 1 ret i32 %tmp3 +; CHECK: @test12 +; CHECK-NEXT: ret i32 1 } define i32 @test13(i32 %x) nounwind { %tmp3 = sdiv i32 %x, %x ; 1 ret i32 %tmp3 +; CHECK: @test13 +; CHECK-NEXT: ret i32 1 } +define i32 @test14(i8 %x) nounwind { + %zext = zext i8 %x to i32 + %div = udiv i32 %zext, 257 ; 0 + ret i32 %div +; CHECK: @test14 +; CHECK-NEXT: ret i32 0 +} diff --git a/test/Transforms/InstCombine/fcmp.ll b/test/Transforms/InstCombine/fcmp.ll new file mode 100644 index 000000000000..2eb4f058692d --- /dev/null +++ b/test/Transforms/InstCombine/fcmp.ll @@ -0,0 +1,60 @@ +; RUN: opt -S -instcombine < %s | FileCheck %s + +define i1 @test1(float %x, float %y) nounwind { + %ext1 = fpext float %x to double + %ext2 = fpext float %y to double + %cmp = fcmp ogt double %ext1, %ext2 + ret i1 %cmp +; CHECK: @test1 +; CHECK-NEXT: fcmp ogt float %x, %y +} + +define i1 @test2(float %a) nounwind { + %ext = fpext float %a to double + %cmp = fcmp ogt double %ext, 1.000000e+00 + ret i1 %cmp +; CHECK: @test2 +; CHECK-NEXT: fcmp ogt float %a, 1.0 +} + +define i1 @test3(float %a) nounwind { + %ext = fpext float %a to double + %cmp = fcmp ogt double %ext, 0x3FF0000000000001 ; more precision than float. + ret i1 %cmp +; CHECK: @test3 +; CHECK-NEXT: fpext float %a to double +} + +define i1 @test4(float %a) nounwind { + %ext = fpext float %a to double + %cmp = fcmp ogt double %ext, 0x36A0000000000000 ; denormal in float. + ret i1 %cmp +; CHECK: @test4 +; CHECK-NEXT: fpext float %a to double +} + +define i1 @test5(float %a) nounwind { + %neg = fsub float -0.000000e+00, %a + %cmp = fcmp ogt float %neg, 1.000000e+00 + ret i1 %cmp +; CHECK: @test5 +; CHECK-NEXT: fcmp olt float %a, -1.0 +} + +define i1 @test6(float %x, float %y) nounwind { + %neg1 = fsub float -0.000000e+00, %x + %neg2 = fsub float -0.000000e+00, %y + %cmp = fcmp olt float %neg1, %neg2 + ret i1 %cmp +; CHECK: @test6 +; CHECK-NEXT: fcmp ogt float %x, %y +} + +define i1 @test7(float %x) nounwind readnone ssp noredzone { + %ext = fpext float %x to ppc_fp128 + %cmp = fcmp ogt ppc_fp128 %ext, 0xM00000000000000000000000000000000 + ret i1 %cmp +; Can't convert ppc_fp128 +; CHECK: @test7 +; CHECK-NEXT: fpext float %x to ppc_fp128 +} diff --git a/test/Transforms/InstCombine/fdiv.ll b/test/Transforms/InstCombine/fdiv.ll new file mode 100644 index 000000000000..a2cce016e188 --- /dev/null +++ b/test/Transforms/InstCombine/fdiv.ll @@ -0,0 +1,25 @@ +; RUN: opt -S -instcombine < %s | FileCheck %s + +define float @test1(float %x) nounwind readnone ssp { + %div = fdiv float %x, 0x3810000000000000 + ret float %div + +; CHECK: @test1 +; CHECK-NEXT: fmul float %x, 0x47D0000000000000 +} + +define float @test2(float %x) nounwind readnone ssp { + %div = fdiv float %x, 0x47E0000000000000 + ret float %div + +; CHECK: @test2 +; CHECK-NEXT: fdiv float %x, 0x47E0000000000000 +} + +define float @test3(float %x) nounwind readnone ssp { + %div = fdiv float %x, 0x36A0000000000000 + ret float %div + +; CHECK: @test3 +; CHECK-NEXT: fdiv float %x, 0x36A0000000000000 +} diff --git a/test/Transforms/InstCombine/fold-bin-operand.ll b/test/Transforms/InstCombine/fold-bin-operand.ll index d0d072ac6bb5..a8bad0df5960 100644 --- a/test/Transforms/InstCombine/fold-bin-operand.ll +++ b/test/Transforms/InstCombine/fold-bin-operand.ll @@ -1,14 +1,17 @@ -; RUN: opt < %s -instcombine -S | not grep icmp +; RUN: opt < %s -instcombine -S | FileCheck %s target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128" define i1 @f(i1 %x) { +; CHECK: @f +; CHECK: ret i1 false %b = and i1 %x, icmp eq (i8* inttoptr (i32 1 to i8*), i8* inttoptr (i32 2 to i8*)) ret i1 %b } -; FIXME: This doesn't fold at the moment! -; define i32 @f(i32 %x) { -; %b = add i32 %x, zext (i1 icmp eq (i8* inttoptr (i32 1000000 to i8*), i8* inttoptr (i32 2000000 to i8*)) to i32) -; ret i32 %b -;} +define i32 @g(i32 %x) { +; CHECK: @g +; CHECK: ret i32 %x + %b = add i32 %x, zext (i1 icmp eq (i8* inttoptr (i32 1000000 to i8*), i8* inttoptr (i32 2000000 to i8*)) to i32) + ret i32 %b +} diff --git a/test/Transforms/InstCombine/gep-addrspace.ll b/test/Transforms/InstCombine/gep-addrspace.ll new file mode 100644 index 000000000000..dfe12dbfaf7f --- /dev/null +++ b/test/Transforms/InstCombine/gep-addrspace.ll @@ -0,0 +1,19 @@ +; RUN: opt < %s -instcombine -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" +target triple = "x86_64-pc-win32" + +%myStruct = type { float, [3 x float], [4 x float], i32 } + +; make sure that we are not crashing when creating an illegal type +define void @func(%myStruct addrspace(1)* nocapture %p) nounwind { +ST: + %A = getelementptr inbounds %myStruct addrspace(1)* %p, i64 0 + %B = bitcast %myStruct addrspace(1)* %A to %myStruct* + %C = getelementptr inbounds %myStruct* %B, i32 0, i32 1 + %D = getelementptr inbounds [3 x float]* %C, i32 0, i32 2 + %E = load float* %D, align 4 + %F = fsub float %E, undef + ret void +} + diff --git a/test/Transforms/InstCombine/icmp.ll b/test/Transforms/InstCombine/icmp.ll index 3150883e7d71..099540ac7453 100644 --- a/test/Transforms/InstCombine/icmp.ll +++ b/test/Transforms/InstCombine/icmp.ll @@ -377,3 +377,136 @@ define i1 @test38(i32 %x, i32 %y, i32 %z) { %c = icmp ugt i32 %lhs, %rhs ret i1 %c } + +; PR9343 #1 +; CHECK: @test39 +; CHECK: %B = icmp eq i32 %X, 0 +define i1 @test39(i32 %X, i32 %Y) { + %A = ashr exact i32 %X, %Y + %B = icmp eq i32 %A, 0 + ret i1 %B +} + +; CHECK: @test40 +; CHECK: %B = icmp ne i32 %X, 0 +define i1 @test40(i32 %X, i32 %Y) { + %A = lshr exact i32 %X, %Y + %B = icmp ne i32 %A, 0 + ret i1 %B +} + +; PR9343 #3 +; CHECK: @test41 +; CHECK: ret i1 true +define i1 @test41(i32 %X, i32 %Y) { + %A = urem i32 %X, %Y + %B = icmp ugt i32 %Y, %A + ret i1 %B +} + +; CHECK: @test42 +; CHECK: %B = icmp sgt i32 %Y, -1 +define i1 @test42(i32 %X, i32 %Y) { + %A = srem i32 %X, %Y + %B = icmp slt i32 %A, %Y + ret i1 %B +} + +; CHECK: @test43 +; CHECK: %B = icmp slt i32 %Y, 0 +define i1 @test43(i32 %X, i32 %Y) { + %A = srem i32 %X, %Y + %B = icmp slt i32 %Y, %A + ret i1 %B +} + +; CHECK: @test44 +; CHECK: %B = icmp sgt i32 %Y, -1 +define i1 @test44(i32 %X, i32 %Y) { + %A = srem i32 %X, %Y + %B = icmp slt i32 %A, %Y + ret i1 %B +} + +; CHECK: @test45 +; CHECK: %B = icmp slt i32 %Y, 0 +define i1 @test45(i32 %X, i32 %Y) { + %A = srem i32 %X, %Y + %B = icmp slt i32 %Y, %A + ret i1 %B +} + +; PR9343 #4 +; CHECK: @test46 +; CHECK: %C = icmp ult i32 %X, %Y +define i1 @test46(i32 %X, i32 %Y, i32 %Z) { + %A = ashr exact i32 %X, %Z + %B = ashr exact i32 %Y, %Z + %C = icmp ult i32 %A, %B + ret i1 %C +} + +; PR9343 #5 +; CHECK: @test47 +; CHECK: %C = icmp ugt i32 %X, %Y +define i1 @test47(i32 %X, i32 %Y, i32 %Z) { + %A = ashr exact i32 %X, %Z + %B = ashr exact i32 %Y, %Z + %C = icmp ugt i32 %A, %B + ret i1 %C +} + +; PR9343 #8 +; CHECK: @test48 +; CHECK: %C = icmp eq i32 %X, %Y +define i1 @test48(i32 %X, i32 %Y, i32 %Z) { + %A = sdiv exact i32 %X, %Z + %B = sdiv exact i32 %Y, %Z + %C = icmp eq i32 %A, %B + ret i1 %C +} + +; PR8469 +; CHECK: @test49 +; CHECK: ret <2 x i1> <i1 true, i1 true> +define <2 x i1> @test49(<2 x i32> %tmp3) { +entry: + %tmp11 = and <2 x i32> %tmp3, <i32 3, i32 3> + %cmp = icmp ult <2 x i32> %tmp11, <i32 4, i32 4> + ret <2 x i1> %cmp +} + +; PR9343 #7 +; CHECK: @test50 +; CHECK: ret i1 true +define i1 @test50(i16 %X, i32 %Y) { + %A = zext i16 %X to i32 + %B = srem i32 %A, %Y + %C = icmp sgt i32 %B, -1 + ret i1 %C +} + +; CHECK: @test51 +; CHECK: ret i1 %C +define i1 @test51(i32 %X, i32 %Y) { + %A = and i32 %X, 2147483648 + %B = srem i32 %A, %Y + %C = icmp sgt i32 %B, -1 + ret i1 %C +} + +; CHECK: @test52 +; CHECK-NEXT: and i32 %x1, 16711935 +; CHECK-NEXT: icmp eq i32 {{.*}}, 4980863 +; CHECK-NEXT: ret i1 +define i1 @test52(i32 %x1) nounwind { + %conv = and i32 %x1, 255 + %cmp = icmp eq i32 %conv, 127 + %tmp2 = lshr i32 %x1, 16 + %tmp3 = trunc i32 %tmp2 to i8 + %cmp15 = icmp eq i8 %tmp3, 76 + + %A = and i1 %cmp, %cmp15 + ret i1 %A +} + diff --git a/test/Transforms/InstCombine/intrinsics.ll b/test/Transforms/InstCombine/intrinsics.ll index 50e7f1f7c92d..332cd46098ce 100644 --- a/test/Transforms/InstCombine/intrinsics.ll +++ b/test/Transforms/InstCombine/intrinsics.ll @@ -112,6 +112,33 @@ define i8 @umultest2(i8 %A, i1* %overflowPtr) { ; CHECK-NEXT: ret i8 %A } +%ov.result.32 = type { i32, i1 } +declare %ov.result.32 @llvm.umul.with.overflow.i32(i32, i32) nounwind readnone + +define i32 @umultest3(i32 %n) nounwind { + %shr = lshr i32 %n, 2 + %mul = call %ov.result.32 @llvm.umul.with.overflow.i32(i32 %shr, i32 3) + %ov = extractvalue %ov.result.32 %mul, 1 + %res = extractvalue %ov.result.32 %mul, 0 + %ret = select i1 %ov, i32 -1, i32 %res + ret i32 %ret +; CHECK: @umultest3 +; CHECK-NEXT: shr +; CHECK-NEXT: mul nuw +; CHECK-NEXT: ret +} + +define i32 @umultest4(i32 %n) nounwind { + %shr = lshr i32 %n, 1 + %mul = call %ov.result.32 @llvm.umul.with.overflow.i32(i32 %shr, i32 4) + %ov = extractvalue %ov.result.32 %mul, 1 + %res = extractvalue %ov.result.32 %mul, 0 + %ret = select i1 %ov, i32 -1, i32 %res + ret i32 %ret +; CHECK: @umultest4 +; CHECK: umul.with.overflow +} + define void @powi(double %V, double *%P) { entry: %A = tail call double @llvm.powi.f64(double %V, i32 -1) nounwind diff --git a/test/Transforms/InstCombine/merge-icmp.ll b/test/Transforms/InstCombine/merge-icmp.ll new file mode 100644 index 000000000000..00020b157e0f --- /dev/null +++ b/test/Transforms/InstCombine/merge-icmp.ll @@ -0,0 +1,29 @@ +; RUN: opt -S -instcombine < %s | FileCheck %s + +define i1 @test1(i16* %x) { + %load = load i16* %x, align 4 + %trunc = trunc i16 %load to i8 + %cmp1 = icmp eq i8 %trunc, 127 + %and = and i16 %load, -256 + %cmp2 = icmp eq i16 %and, 17664 + %or = and i1 %cmp1, %cmp2 + ret i1 %or +; CHECK: @test1 +; CHECK-NEXT: load i16 +; CHECK-NEXT: icmp eq i16 %load, 17791 +; CHECK-NEXT: ret i1 +} + +define i1 @test2(i16* %x) { + %load = load i16* %x, align 4 + %and = and i16 %load, -256 + %cmp1 = icmp eq i16 %and, 32512 + %trunc = trunc i16 %load to i8 + %cmp2 = icmp eq i8 %trunc, 69 + %or = and i1 %cmp1, %cmp2 + ret i1 %or +; CHECK: @test2 +; CHECK-NEXT: load i16 +; CHECK-NEXT: icmp eq i16 %load, 32581 +; CHECK-NEXT: ret i1 +} diff --git a/test/Transforms/InstCombine/or.ll b/test/Transforms/InstCombine/or.ll index f82f9faab2d5..94a57321862f 100644 --- a/test/Transforms/InstCombine/or.ll +++ b/test/Transforms/InstCombine/or.ll @@ -390,3 +390,22 @@ define i1 @test36(i32 %x) { ; CHECK-NEXT: ret i1 } +define i32 @test37(i32* %xp, i32 %y) { +; CHECK: @test37 +; CHECK: select i1 %tobool, i32 -1, i32 %x + %tobool = icmp ne i32 %y, 0 + %sext = sext i1 %tobool to i32 + %x = load i32* %xp + %or = or i32 %sext, %x + ret i32 %or +} + +define i32 @test38(i32* %xp, i32 %y) { +; CHECK: @test38 +; CHECK: select i1 %tobool, i32 -1, i32 %x + %tobool = icmp ne i32 %y, 0 + %sext = sext i1 %tobool to i32 + %x = load i32* %xp + %or = or i32 %x, %sext + ret i32 %or +} diff --git a/test/Transforms/InstCombine/phi.ll b/test/Transforms/InstCombine/phi.ll index 62c6a63a7e58..cd865ae81baf 100644 --- a/test/Transforms/InstCombine/phi.ll +++ b/test/Transforms/InstCombine/phi.ll @@ -197,25 +197,25 @@ declare i1 @test11a() define i1 @test11() { entry: %a = alloca i32 - %i = ptrtoint i32* %a to i32 + %i = ptrtoint i32* %a to i64 %b = call i1 @test11a() br i1 %b, label %one, label %two one: - %x = phi i32 [%i, %entry], [%y, %two] + %x = phi i64 [%i, %entry], [%y, %two] %c = call i1 @test11a() br i1 %c, label %two, label %end two: - %y = phi i32 [%i, %entry], [%x, %one] + %y = phi i64 [%i, %entry], [%x, %one] %d = call i1 @test11a() br i1 %d, label %one, label %end end: - %f = phi i32 [ %x, %one], [%y, %two] + %f = phi i64 [ %x, %one], [%y, %two] ; Change the %f to %i, and the optimizer suddenly becomes a lot smarter ; even though %f must equal %i at this point - %g = inttoptr i32 %f to i32* + %g = inttoptr i64 %f to i32* store i32 10, i32* %g %z = call i1 @test11a() ret i1 %z @@ -544,3 +544,79 @@ BB2: ; CHECK-NEXT: %C = add nuw i32 %A, 1 ; CHECK-NEXT: ret i32 %C } + +; Same as test11, but used to be missed due to a bug. +declare i1 @test25a() + +define i1 @test25() { +entry: + %a = alloca i32 + %i = ptrtoint i32* %a to i64 + %b = call i1 @test25a() + br i1 %b, label %one, label %two + +one: + %x = phi i64 [%y, %two], [%i, %entry] + %c = call i1 @test25a() + br i1 %c, label %two, label %end + +two: + %y = phi i64 [%x, %one], [%i, %entry] + %d = call i1 @test25a() + br i1 %d, label %one, label %end + +end: + %f = phi i64 [ %x, %one], [%y, %two] + ; Change the %f to %i, and the optimizer suddenly becomes a lot smarter + ; even though %f must equal %i at this point + %g = inttoptr i64 %f to i32* + store i32 10, i32* %g + %z = call i1 @test25a() + ret i1 %z +; CHECK: @test25 +; CHECK-NOT: phi i32 +; CHECK: ret i1 %z +} + +declare i1 @test26a() + +define i1 @test26(i32 %n) { +entry: + %a = alloca i32 + %i = ptrtoint i32* %a to i64 + %b = call i1 @test26a() + br label %one + +one: + %x = phi i64 [%y, %two], [%w, %three], [%i, %entry] + %c = call i1 @test26a() + switch i32 %n, label %end [ + i32 2, label %two + i32 3, label %three + ] + +two: + %y = phi i64 [%x, %one], [%w, %three] + %d = call i1 @test26a() + switch i32 %n, label %end [ + i32 10, label %one + i32 30, label %three + ] + +three: + %w = phi i64 [%y, %two], [%x, %one] + %e = call i1 @test26a() + br i1 %e, label %one, label %two + +end: + %f = phi i64 [ %x, %one], [%y, %two] + ; Change the %f to %i, and the optimizer suddenly becomes a lot smarter + ; even though %f must equal %i at this point + %g = inttoptr i64 %f to i32* + store i32 10, i32* %g + %z = call i1 @test26a() + ret i1 %z +; CHECK: @test26 +; CHECK-NOT: phi i32 +; CHECK: ret i1 %z +} diff --git a/test/Transforms/InstCombine/select.ll b/test/Transforms/InstCombine/select.ll index ba9d99c97dd5..39259078b877 100644 --- a/test/Transforms/InstCombine/select.ll +++ b/test/Transforms/InstCombine/select.ll @@ -714,3 +714,38 @@ define i32 @test52(i32 %n, i32 %m) nounwind { ret i32 %storemerge } +; PR9454 +define i32 @test53(i32 %x) nounwind { + %and = and i32 %x, 2 + %cmp = icmp eq i32 %and, %x + %sel = select i1 %cmp, i32 2, i32 1 + ret i32 %sel +; CHECK: @test53 +; CHECK: select i1 %cmp +; CHECK: ret +} + +define i32 @test54(i32 %X, i32 %Y) { + %A = ashr exact i32 %X, %Y + %B = icmp eq i32 %A, 0 + %C = select i1 %B, i32 %A, i32 1 + ret i32 %C +; CHECK: @test54 +; CHECK-NOT: ashr +; CHECK-NOT: select +; CHECK: icmp ne i32 %X, 0 +; CHECK: zext +; CHECK: ret +} + +define i1 @test55(i1 %X, i32 %Y, i32 %Z) { + %A = ashr exact i32 %Y, %Z + %B = select i1 %X, i32 %Y, i32 %A + %C = icmp eq i32 %B, 0 + ret i1 %C +; CHECK: @test55 +; CHECK-NOT: ashr +; CHECK-NOT: select +; CHECK: icmp eq +; CHECK: ret i1 +} diff --git a/test/Transforms/InstCombine/sext.ll b/test/Transforms/InstCombine/sext.ll index 60669b7a109f..f49a2efb39d8 100644 --- a/test/Transforms/InstCombine/sext.ll +++ b/test/Transforms/InstCombine/sext.ll @@ -126,3 +126,61 @@ define void @test11(<2 x i16> %srcA, <2 x i16> %srcB, <2 x i16>* %dst) { ; CHECK-NEXT: store <2 x i16> ; CHECK-NEXT: ret } + +define i64 @test12(i32 %x) nounwind { + %shr = lshr i32 %x, 1 + %sub = sub nsw i32 0, %shr + %conv = sext i32 %sub to i64 + ret i64 %conv +; CHECK: @test12 +; CHECK: sext +; CHECK: ret +} + +define i32 @test13(i32 %x) nounwind { + %and = and i32 %x, 8 + %cmp = icmp eq i32 %and, 0 + %ext = sext i1 %cmp to i32 + ret i32 %ext +; CHECK: @test13 +; CHECK-NEXT: %and = lshr i32 %x, 3 +; CHECK-NEXT: %1 = and i32 %and, 1 +; CHECK-NEXT: %sext = add i32 %1, -1 +; CHECK-NEXT: ret i32 %sext +} + +define i32 @test14(i16 %x) nounwind { + %and = and i16 %x, 16 + %cmp = icmp ne i16 %and, 16 + %ext = sext i1 %cmp to i32 + ret i32 %ext +; CHECK: @test14 +; CHECK-NEXT: %and = lshr i16 %x, 4 +; CHECK-NEXT: %1 = and i16 %and, 1 +; CHECK-NEXT: %sext = add i16 %1, -1 +; CHECK-NEXT: %ext = sext i16 %sext to i32 +; CHECK-NEXT: ret i32 %ext +} + +define i32 @test15(i32 %x) nounwind { + %and = and i32 %x, 16 + %cmp = icmp ne i32 %and, 0 + %ext = sext i1 %cmp to i32 + ret i32 %ext +; CHECK: @test15 +; CHECK-NEXT: %1 = shl i32 %x, 27 +; CHECK-NEXT: %sext = ashr i32 %1, 31 +; CHECK-NEXT: ret i32 %sext +} + +define i32 @test16(i16 %x) nounwind { + %and = and i16 %x, 8 + %cmp = icmp eq i16 %and, 8 + %ext = sext i1 %cmp to i32 + ret i32 %ext +; CHECK: @test16 +; CHECK-NEXT: %1 = shl i16 %x, 12 +; CHECK-NEXT: %sext = ashr i16 %1, 15 +; CHECK-NEXT: %ext = sext i16 %sext to i32 +; CHECK-NEXT: ret i32 %ext +} diff --git a/test/Transforms/InstCombine/shift.ll b/test/Transforms/InstCombine/shift.ll index 7fab1d2cab54..bded68ac4755 100644 --- a/test/Transforms/InstCombine/shift.ll +++ b/test/Transforms/InstCombine/shift.ll @@ -485,3 +485,24 @@ entry: ; CHECK: ret i8 %tmp551 ret i8 %tmp55 } + +; PR9809 +define i32 @test40(i32 %a, i32 %b) nounwind { + %shl1 = shl i32 1, %b + %shl2 = shl i32 %shl1, 2 + %div = udiv i32 %a, %shl2 + ret i32 %div +; CHECK: @test40 +; CHECK-NEXT: add i32 %b, 2 +; CHECK-NEXT: lshr i32 %a +; CHECK-NEXT: ret i32 +} + +define i32 @test41(i32 %a, i32 %b) nounwind { + %1 = shl i32 1, %b + %2 = shl i32 %1, 3 + ret i32 %2 +; CHECK: @test41 +; CHECK-NEXT: shl i32 8, %b +; CHECK-NEXT: ret i32 +} diff --git a/test/Transforms/InstCombine/sign-test-and-or.ll b/test/Transforms/InstCombine/sign-test-and-or.ll new file mode 100644 index 000000000000..47f5f3051e46 --- /dev/null +++ b/test/Transforms/InstCombine/sign-test-and-or.ll @@ -0,0 +1,79 @@ +; RUN: opt -S -instcombine < %s | FileCheck %s + +declare void @foo() + +define void @test1(i32 %a, i32 %b) nounwind { + %1 = icmp slt i32 %a, 0 + %2 = icmp slt i32 %b, 0 + %or.cond = or i1 %1, %2 + br i1 %or.cond, label %if.then, label %if.end + +; CHECK: @test1 +; CHECK-NEXT: %1 = or i32 %a, %b +; CHECK-NEXT: %2 = icmp slt i32 %1, 0 +; CHECK-NEXT: br + +if.then: + tail call void @foo() nounwind + ret void + +if.end: + ret void +} + +define void @test2(i32 %a, i32 %b) nounwind { + %1 = icmp sgt i32 %a, -1 + %2 = icmp sgt i32 %b, -1 + %or.cond = or i1 %1, %2 + br i1 %or.cond, label %if.then, label %if.end + +; CHECK: @test2 +; CHECK-NEXT: %1 = and i32 %a, %b +; CHECK-NEXT: %2 = icmp sgt i32 %1, -1 +; CHECK-NEXT: br + +if.then: + tail call void @foo() nounwind + ret void + +if.end: + ret void +} + +define void @test3(i32 %a, i32 %b) nounwind { + %1 = icmp slt i32 %a, 0 + %2 = icmp slt i32 %b, 0 + %or.cond = and i1 %1, %2 + br i1 %or.cond, label %if.then, label %if.end + +; CHECK: @test3 +; CHECK-NEXT: %1 = and i32 %a, %b +; CHECK-NEXT: %2 = icmp slt i32 %1, 0 +; CHECK-NEXT: br + +if.then: + tail call void @foo() nounwind + ret void + +if.end: + ret void +} + +define void @test4(i32 %a, i32 %b) nounwind { + %1 = icmp sgt i32 %a, -1 + %2 = icmp sgt i32 %b, -1 + %or.cond = and i1 %1, %2 + br i1 %or.cond, label %if.then, label %if.end + +; CHECK: @test4 +; CHECK-NEXT: %1 = or i32 %a, %b +; CHECK-NEXT: %2 = icmp sgt i32 %1, -1 +; CHECK-NEXT: br + +if.then: + tail call void @foo() nounwind + ret void + +if.end: + ret void +} diff --git a/test/Transforms/InstCombine/strcpy_chk-64.ll b/test/Transforms/InstCombine/strcpy_chk-64.ll new file mode 100644 index 000000000000..036fcbe6de1d --- /dev/null +++ b/test/Transforms/InstCombine/strcpy_chk-64.ll @@ -0,0 +1,18 @@ +; 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" +target triple = "x86_64-apple-darwin10.0.0" + +define void @func(i8* %i) nounwind ssp { +; CHECK: @func +; CHECK: @__strcpy_chk(i8* %arraydecay, i8* %i, i64 32) +entry: + %s = alloca [32 x i8], align 16 + %arraydecay = getelementptr inbounds [32 x i8]* %s, i32 0, i32 0 + %call = call i8* @__strcpy_chk(i8* %arraydecay, i8* %i, i64 32) + call void @func2(i8* %arraydecay) + ret void +} + +declare i8* @__strcpy_chk(i8*, i8*, i64) nounwind + +declare void @func2(i8*) diff --git a/test/Transforms/InstCombine/udivrem-change-width.ll b/test/Transforms/InstCombine/udivrem-change-width.ll index 9983944df8d7..b388a3b0634e 100644 --- a/test/Transforms/InstCombine/udivrem-change-width.ll +++ b/test/Transforms/InstCombine/udivrem-change-width.ll @@ -1,14 +1,16 @@ -; RUN: opt < %s -instcombine -S | not grep zext -; PR4548 +; 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" +; PR4548 define i8 @udiv_i8(i8 %a, i8 %b) nounwind { %conv = zext i8 %a to i32 %conv2 = zext i8 %b to i32 %div = udiv i32 %conv, %conv2 %conv3 = trunc i32 %div to i8 ret i8 %conv3 +; CHECK: @udiv_i8 +; CHECK: udiv i8 %a, %b } define i8 @urem_i8(i8 %a, i8 %b) nounwind { @@ -17,5 +19,44 @@ define i8 @urem_i8(i8 %a, i8 %b) nounwind { %div = urem i32 %conv, %conv2 %conv3 = trunc i32 %div to i8 ret i8 %conv3 +; CHECK: @urem_i8 +; CHECK: urem i8 %a, %b } +define i32 @udiv_i32(i8 %a, i8 %b) nounwind { + %conv = zext i8 %a to i32 + %conv2 = zext i8 %b to i32 + %div = udiv i32 %conv, %conv2 + ret i32 %div +; CHECK: @udiv_i32 +; CHECK: udiv i8 %a, %b +; CHECK: zext +} + +define i32 @urem_i32(i8 %a, i8 %b) nounwind { + %conv = zext i8 %a to i32 + %conv2 = zext i8 %b to i32 + %div = urem i32 %conv, %conv2 + ret i32 %div +; CHECK: @urem_i32 +; CHECK: urem i8 %a, %b +; CHECK: zext +} + +define i32 @udiv_i32_c(i8 %a) nounwind { + %conv = zext i8 %a to i32 + %div = udiv i32 %conv, 10 + ret i32 %div +; CHECK: @udiv_i32_c +; CHECK: udiv i8 %a, 10 +; CHECK: zext +} + +define i32 @urem_i32_c(i8 %a) nounwind { + %conv = zext i8 %a to i32 + %div = urem i32 %conv, 10 + ret i32 %div +; CHECK: @urem_i32_c +; CHECK: urem i8 %a, 10 +; CHECK: zext +} |
