diff options
author | dim <dim@FreeBSD.org> | 2011-06-12 15:42:51 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2011-06-12 15:42:51 +0000 |
commit | ece02cd5829cea836e9365b0845a8ef042d17b0a (patch) | |
tree | b3032e51d630e8070e9e08d6641648f195316a80 /test/Transforms | |
parent | 2b066988909948dc3d53d01760bc2d71d32f3feb (diff) | |
download | FreeBSD-src-ece02cd5829cea836e9365b0845a8ef042d17b0a.zip FreeBSD-src-ece02cd5829cea836e9365b0845a8ef042d17b0a.tar.gz |
Vendor import of llvm trunk r132879:
http://llvm.org/svn/llvm-project/llvm/trunk@132879
Diffstat (limited to 'test/Transforms')
55 files changed, 1991 insertions, 51 deletions
diff --git a/test/Transforms/ConstProp/calls.ll b/test/Transforms/ConstProp/calls.ll index 82d7324..3b6010a 100644 --- a/test/Transforms/ConstProp/calls.ll +++ b/test/Transforms/ConstProp/calls.ll @@ -7,6 +7,7 @@ declare double @sin(double) declare double @tan(double) declare double @sqrt(double) +declare double @exp2(double) define double @T() { ; CHECK: @T @@ -19,7 +20,11 @@ define double @T() { %b = fadd double %a, %C %D = call double @sqrt(double 4.000000e+00) %c = fadd double %b, %D - ret double %c + + ; PR9315 + %E = call double @exp2(double 4.0) + %d = fadd double %c, %E + ret double %d } define i1 @test_sse_cvt() nounwind readnone { diff --git a/test/Transforms/DeadArgElim/2008-06-23-DeadAfterLive.ll b/test/Transforms/DeadArgElim/2008-06-23-DeadAfterLive.ll index adfd019..858c935 100644 --- a/test/Transforms/DeadArgElim/2008-06-23-DeadAfterLive.ll +++ b/test/Transforms/DeadArgElim/2008-06-23-DeadAfterLive.ll @@ -2,7 +2,7 @@ ; RUN: cat %t | grep 123 ; This test tries to catch wrongful removal of return values for a specific case -; that was break llvm-gcc builds. +; that was breaking llvm-gcc builds. ; This function has a live return value, it is used by @alive. define internal i32 @test5() { diff --git a/test/Transforms/DeadStoreElimination/simple.ll b/test/Transforms/DeadStoreElimination/simple.ll index a61eac9..23576dad 100644 --- a/test/Transforms/DeadStoreElimination/simple.ll +++ b/test/Transforms/DeadStoreElimination/simple.ll @@ -236,3 +236,20 @@ define void @test18(i8* %P, i8* %Q, i8* %R) nounwind ssp { ; CHECK-NEXT: call void @llvm.memcpy ; CHECK-NEXT: ret } + + +; The store here is not dead because the byval call reads it. +declare void @test19f({i32}* byval align 4 %P) + +define void @test19({i32} * nocapture byval align 4 %arg5) nounwind ssp { +bb: + %tmp7 = getelementptr inbounds {i32}* %arg5, i32 0, i32 0 + store i32 912, i32* %tmp7 + call void @test19f({i32}* byval align 4 %arg5) + ret void + +; CHECK: @test19( +; CHECK: store i32 912 +; CHECK: call void @test19f +} + diff --git a/test/Transforms/GVN/2007-07-26-InterlockingLoops.ll b/test/Transforms/GVN/2007-07-26-InterlockingLoops.ll index 14cb91b..a1cc008 100644 --- a/test/Transforms/GVN/2007-07-26-InterlockingLoops.ll +++ b/test/Transforms/GVN/2007-07-26-InterlockingLoops.ll @@ -4,8 +4,11 @@ define i32 @NextRootMove(i32 %wtm) { entry: + %A = alloca i32* %tmp17618 = load i32** getelementptr ([65 x i32*]* @last, i32 0, i32 1), align 4 + store i32* %tmp17618, i32** %A ; CHECK: entry: +; CHECK-NEXT: alloca i32 ; CHECK-NEXT: %tmp17618 = load ; CHECK-NOT: load ; CHECK-NOT: phi @@ -16,6 +19,7 @@ cond_true116: cond_true128: %tmp17625 = load i32** getelementptr ([65 x i32*]* @last, i32 0, i32 1), align 4 + store i32* %tmp17625, i32** %A br i1 false, label %bb98.backedge, label %return.loopexit bb98.backedge: @@ -23,6 +27,7 @@ bb98.backedge: cond_true145: %tmp17631 = load i32** getelementptr ([65 x i32*]* @last, i32 0, i32 1), align 4 + store i32* %tmp17631, i32** %A br i1 false, label %bb98.backedge, label %return.loopexit return.loopexit: diff --git a/test/Transforms/GVN/2008-07-02-Unreachable.ll b/test/Transforms/GVN/2008-07-02-Unreachable.ll index be69cfc..407940b 100644 --- a/test/Transforms/GVN/2008-07-02-Unreachable.ll +++ b/test/Transforms/GVN/2008-07-02-Unreachable.ll @@ -5,6 +5,7 @@ define i8 @func_1() nounwind { entry: + %A = alloca i8 br i1 false, label %ifelse, label %ifthen ifthen: ; preds = %entry @@ -12,6 +13,7 @@ ifthen: ; preds = %entry ifelse: ; preds = %entry %tmp3 = load i8* @g_3 ; <i8> [#uses=0] + store i8 %tmp3, i8* %A br label %forcond.thread forcond.thread: ; preds = %ifelse diff --git a/test/Transforms/GVN/2011-06-01-NonLocalMemdepMiscompile.ll b/test/Transforms/GVN/2011-06-01-NonLocalMemdepMiscompile.ll new file mode 100644 index 0000000..f24e956 --- /dev/null +++ b/test/Transforms/GVN/2011-06-01-NonLocalMemdepMiscompile.ll @@ -0,0 +1,61 @@ +; RUN: opt < %s -basicaa -gvn -S | FileCheck %s +; This test is checking that (a) this doesn't crash, and (b) we don't +; conclude the value of %tmp17 is available in bb1.bb15_crit_edge. +; rdar://9429882 + +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-macosx10.7.0" + +define i1 @rb_intern() nounwind ssp { +; CHECK: @rb_intern + +bb: + %tmp = alloca i8*, align 8 + store i8* null, i8** %tmp, align 8 + store i8 undef, i8* null, align 536870912 + br label %bb1 + +bb1: + br i1 undef, label %bb3, label %bb15 + +; CHECK: bb1: +; CHECK: %tmp16 = phi i8* [ getelementptr (i8* null, i64 undef), %bb10 ], [ null, %bb ] + +; CHECK: bb1.bb15_crit_edge: +; CHECK: %tmp17.pre = load i8* %tmp16, align 1 + +bb3: + call void @isalnum() + br i1 undef, label %bb10, label %bb5 + +bb5: + br i1 undef, label %bb10, label %bb6 + +bb6: + %tmp7 = load i8** %tmp, align 8 + %tmp8 = load i8* %tmp7, align 1 + %tmp9 = zext i8 %tmp8 to i64 + br i1 undef, label %bb15, label %bb10 + +bb10: + %tmp11 = load i8** %tmp, align 8 + %tmp12 = load i8* %tmp11, align 1 + %tmp13 = zext i8 %tmp12 to i64 + %tmp14 = getelementptr inbounds i8* null, i64 undef + store i8* %tmp14, i8** %tmp, align 8 + br label %bb1 + +bb15: + %tmp16 = load i8** %tmp, align 8 + %tmp17 = load i8* %tmp16, align 1 + %tmp18 = icmp eq i8 %tmp17, 0 + br label %bb19 + +; CHECK: bb15: +; CHECK: %tmp17 = phi i8 [ %tmp17.pre, %bb1.bb15_crit_edge ], [ %tmp8, %bb6 ] + +bb19: ; preds = %bb15 + ret i1 %tmp18 +} + +declare void @isalnum() nounwind inlinehint ssp diff --git a/test/Transforms/GVN/crash.ll b/test/Transforms/GVN/crash.ll index 4a3aa1c..31eae25 100644 --- a/test/Transforms/GVN/crash.ll +++ b/test/Transforms/GVN/crash.ll @@ -151,3 +151,15 @@ dead: dead2: ret i32 %A } + + +; PR9841 +define fastcc i8 @test5(i8* %P) nounwind { +entry: + %0 = load i8* %P, align 2 + + %Q = getelementptr i8* %P, i32 1 + %1 = load i8* %Q, align 1 + ret i8 %1 +} + diff --git a/test/Transforms/GVN/mixed.ll b/test/Transforms/GVN/mixed.ll deleted file mode 100644 index 6bfada2..0000000 --- a/test/Transforms/GVN/mixed.ll +++ /dev/null @@ -1,13 +0,0 @@ -; RUN: opt < %s -basicaa -gvn -S | not grep DEADLOAD -; RUN: opt < %s -basicaa -gvn -S | not grep DEADGEP - -define i32 @main(i32** %p) { -block1: - %z1 = load i32** %p - %z2 = getelementptr i32* %z1, i32 0 - %z3 = load i32* %z2 - %DEADLOAD = load i32** %p - %DEADGEP = getelementptr i32* %DEADLOAD, i32 0 - %DEADLOAD2 = load i32* %DEADGEP - ret i32 %DEADLOAD2 -} diff --git a/test/Transforms/GVN/phi-translate-partial-alias.ll b/test/Transforms/GVN/phi-translate-partial-alias.ll new file mode 100644 index 0000000..47bec41 --- /dev/null +++ b/test/Transforms/GVN/phi-translate-partial-alias.ll @@ -0,0 +1,27 @@ +; RUN: opt -basicaa -gvn -S < %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-f128:128:128-n8:16:32:64" + +; GVN shouldn't PRE the load around the loop backedge because it's +; not actually redundant around the loop backedge, despite appearances +; if phi-translation is ignored. + +; CHECK: define void @test0(i8* %begin) +; CHECK: loop: +; CHECK: %l0 = load i8* %phi +; CHECK: call void @bar(i8 %l0) +; CHECK: %l1 = load i8* %phi +define void @test0(i8* %begin) { +entry: + br label %loop + +loop: + %phi = phi i8* [ %begin, %entry ], [ %next, %loop ] + %l0 = load i8* %phi + call void @bar(i8 %l0) + %l1 = load i8* %phi + %next = getelementptr inbounds i8* %phi, i8 %l1 + br label %loop +} + +declare void @bar(i8) diff --git a/test/Transforms/GVN/preserve-tbaa.ll b/test/Transforms/GVN/preserve-tbaa.ll index 2fcfc47..a936755 100644 --- a/test/Transforms/GVN/preserve-tbaa.ll +++ b/test/Transforms/GVN/preserve-tbaa.ll @@ -5,9 +5,9 @@ target datalayout = "e-p:64:64:64" ; GVN should preserve the TBAA tag on loads when doing PRE. ; CHECK: @test -; CHECK: %tmp33.pre = load i16* undef, align 2, !tbaa !0 +; CHECK: %tmp33.pre = load i16* %P, align 2, !tbaa !0 ; CHECK: br label %for.body -define void @test() nounwind { +define void @test(i16 *%P, i16* %Q) nounwind { entry: br i1 undef, label %bb.nph, label %for.end @@ -15,8 +15,10 @@ bb.nph: ; preds = %entry br label %for.body for.body: ; preds = %for.body, %bb.nph - %tmp33 = load i16* undef, align 2, !tbaa !0 - store i16 undef, i16* undef, align 2, !tbaa !0 + %tmp33 = load i16* %P, align 2, !tbaa !0 + store i16 %tmp33, i16* %Q + + store i16 0, i16* %P, align 2, !tbaa !0 br i1 false, label %for.end, label %for.body for.end: ; preds = %for.body, %entry diff --git a/test/Transforms/GVN/rle.ll b/test/Transforms/GVN/rle.ll index 4ff5bec..28b1fc7 100644 --- a/test/Transforms/GVN/rle.ll +++ b/test/Transforms/GVN/rle.ll @@ -360,8 +360,11 @@ Cont: define i32 @chained_load(i32** %p) { block1: + %A = alloca i32* + %z = load i32** %p - br i1 true, label %block2, label %block3 + store i32* %z, i32** %A + br i1 true, label %block2, label %block3 block2: %a = load i32** %p @@ -559,14 +562,14 @@ entry: %add = add nsw i32 %tmp2, %conv ret i32 %add -; CHECK: @load_load_partial_alias -; CHECK: load i32* -; CHECK-NOT: load -; CHECK: lshr i32 {{.*}}, 8 -; CHECK-NOT: load -; CHECK: trunc i32 {{.*}} to i8 -; CHECK-NOT: load -; CHECK: ret i32 +; TEMPORARILYDISABLED: @load_load_partial_alias +; TEMPORARILYDISABLED: load i32* +; TEMPORARILYDISABLED-NOT: load +; TEMPORARILYDISABLED: lshr i32 {{.*}}, 8 +; TEMPORARILYDISABLED-NOT: load +; TEMPORARILYDISABLED: trunc i32 {{.*}} to i8 +; TEMPORARILYDISABLED-NOT: load +; TEMPORARILYDISABLED: ret i32 } @@ -586,10 +589,10 @@ land.lhs.true: ; preds = %entry if.end: ret i32 52 -; CHECK: @load_load_partial_alias_cross_block -; CHECK: land.lhs.true: -; CHECK-NOT: load i8 -; CHECK: ret i32 %conv6 +; TEMPORARILY_DISABLED: @load_load_partial_alias_cross_block +; TEMPORARILY_DISABLED: land.lhs.true: +; TEMPORARILY_DISABLED-NOT: load i8 +; TEMPORARILY_DISABLED: ret i32 %conv6 } diff --git a/test/Transforms/GlobalOpt/crash.ll b/test/Transforms/GlobalOpt/crash.ll index 9da5a5e..366a874 100644 --- a/test/Transforms/GlobalOpt/crash.ll +++ b/test/Transforms/GlobalOpt/crash.ll @@ -64,3 +64,17 @@ define void @memset_with_strange_user() ssp { ret void } declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) nounwind + + +; PR9856 +@g_52 = internal global i32** null, align 8 +@g_90 = external global i32*, align 8 + +define void @icmp_user_of_stored_once() nounwind ssp { +entry: + %tmp4 = load i32*** @g_52, align 8 + store i32** @g_90, i32*** @g_52 + %cmp17 = icmp ne i32*** undef, @g_52 + ret void +} + diff --git a/test/Transforms/GlobalOpt/memset-null.ll b/test/Transforms/GlobalOpt/memset-null.ll new file mode 100644 index 0000000..01534025 --- /dev/null +++ b/test/Transforms/GlobalOpt/memset-null.ll @@ -0,0 +1,29 @@ +; RUN: opt -globalopt %s -S -o - | FileCheck %s +; PR10047 + +%0 = type { i32, void ()* } +%struct.A = type { [100 x i32] } + +; CHECK: @a +@a = global %struct.A zeroinitializer, align 4 +@llvm.global_ctors = appending global [2 x %0] [%0 { i32 65535, void ()* @_GLOBAL__I_a }, %0 { i32 65535, void ()* @_GLOBAL__I_b }] + +declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) nounwind + +; CHECK-NOT: GLOBAL__I_a +define internal void @_GLOBAL__I_a() nounwind { +entry: + tail call void @llvm.memset.p0i8.i64(i8* bitcast (%struct.A* @a to i8*), i8 0, i64 400, i32 4, i1 false) nounwind + ret void +} + +%struct.X = type { i8 } +@y = global i8* null, align 8 +@x = global %struct.X zeroinitializer, align 1 + +define internal void @_GLOBAL__I_b() nounwind { +entry: + %tmp.i.i.i = load i8** @y, align 8 + tail call void @llvm.memset.p0i8.i64(i8* %tmp.i.i.i, i8 0, i64 10, i32 1, i1 false) nounwind + ret void +} diff --git a/test/Transforms/IndVarSimplify/elim-extend.ll b/test/Transforms/IndVarSimplify/elim-extend.ll new file mode 100644 index 0000000..0367e11 --- /dev/null +++ b/test/Transforms/IndVarSimplify/elim-extend.ll @@ -0,0 +1,153 @@ +; RUN: opt < %s -indvars -disable-iv-rewrite -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" + +; IV with constant start, preinc and postinc sign extends, with and without NSW. +; IV rewrite only removes one sext. WidenIVs removes all three. +define void @postincConstIV(i8* %base, i32 %limit) nounwind { +entry: + br label %loop +; CHECK: loop: +; CHECK-NOT: sext +; CHECK: exit: +loop: + %iv = phi i32 [ %postiv, %loop ], [ 0, %entry ] + %ivnsw = phi i32 [ %postivnsw, %loop ], [ 0, %entry ] + %preofs = sext i32 %iv to i64 + %preadr = getelementptr i8* %base, i64 %preofs + store i8 0, i8* %preadr + %postiv = add i32 %iv, 1 + %postofs = sext i32 %postiv to i64 + %postadr = getelementptr i8* %base, i64 %postofs + store i8 0, i8* %postadr + %postivnsw = add nsw i32 %ivnsw, 1 + %postofsnsw = sext i32 %postivnsw to i64 + %postadrnsw = getelementptr i8* %base, i64 %postofsnsw + store i8 0, i8* %postadrnsw + %cond = icmp sgt i32 %limit, %iv + br i1 %cond, label %loop, label %exit +exit: + br label %return +return: + ret void +} + +; IV with nonconstant start, preinc and postinc sign extends, +; with and without NSW. +; As with postincConstIV, WidenIVs removes all three sexts. +define void @postincVarIV(i8* %base, i32 %init, i32 %limit) nounwind { +entry: + %precond = icmp sgt i32 %limit, %init + br i1 %precond, label %loop, label %return +; CHECK: loop: +; CHECK-NOT: sext +; CHECK: exit: +loop: + %iv = phi i32 [ %postiv, %loop ], [ %init, %entry ] + %ivnsw = phi i32 [ %postivnsw, %loop ], [ %init, %entry ] + %preofs = sext i32 %iv to i64 + %preadr = getelementptr i8* %base, i64 %preofs + store i8 0, i8* %preadr + %postiv = add i32 %iv, 1 + %postofs = sext i32 %postiv to i64 + %postadr = getelementptr i8* %base, i64 %postofs + store i8 0, i8* %postadr + %postivnsw = add nsw i32 %ivnsw, 1 + %postofsnsw = sext i32 %postivnsw to i64 + %postadrnsw = getelementptr i8* %base, i64 %postofsnsw + store i8 0, i8* %postadrnsw + %cond = icmp sgt i32 %limit, %postiv + br i1 %cond, label %loop, label %exit +exit: + br label %return +return: + ret void +} + +; Test sign extend elimination in the inner and outer loop. +; %outercount is straightforward to widen, besides being in an outer loop. +; %innercount is currently blocked by lcssa, so is not widened. +; %inneriv can be widened only after proving it has no signed-overflow +; based on the loop test. +define void @nestedIV(i8* %address, i32 %limit) nounwind { +entry: + %limitdec = add i32 %limit, -1 + br label %outerloop + +; CHECK: outerloop: +; +; Eliminate %ofs1 after widening outercount. +; CHECK-NOT: sext +; CHECK: getelementptr +; +; IV rewriting hoists a gep into this block. We don't like that. +; CHECK-NOT: getelementptr +outerloop: + %outercount = phi i32 [ %outerpostcount, %outermerge ], [ 0, %entry ] + %innercount = phi i32 [ %innercount.merge, %outermerge ], [ 0, %entry ] + + %outercountdec = add i32 %outercount, -1 + %ofs1 = sext i32 %outercountdec to i64 + %adr1 = getelementptr i8* %address, i64 %ofs1 + store i8 0, i8* %adr1 + + br label %innerpreheader + +innerpreheader: + %innerprecmp = icmp sgt i32 %limitdec, %innercount + br i1 %innerprecmp, label %innerloop, label %outermerge + +; CHECK: innerloop: +; +; Eliminate %ofs2 after widening inneriv. +; Eliminate %ofs3 after normalizing sext(innerpostiv) +; CHECK-NOT: sext +; CHECK: getelementptr +; +; FIXME: We should check that indvars does not increase the number of +; IVs in this loop. sext elimination plus LFTR currently results in 2 final +; IVs. Waiting to remove LFTR. +innerloop: + %inneriv = phi i32 [ %innerpostiv, %innerloop ], [ %innercount, %innerpreheader ] + %innerpostiv = add i32 %inneriv, 1 + + %ofs2 = sext i32 %inneriv to i64 + %adr2 = getelementptr i8* %address, i64 %ofs2 + store i8 0, i8* %adr2 + + %ofs3 = sext i32 %innerpostiv to i64 + %adr3 = getelementptr i8* %address, i64 %ofs3 + store i8 0, i8* %adr3 + + %innercmp = icmp sgt i32 %limitdec, %innerpostiv + br i1 %innercmp, label %innerloop, label %innerexit + +innerexit: + %innercount.lcssa = phi i32 [ %innerpostiv, %innerloop ] + br label %outermerge + +; CHECK: outermerge: +; +; Eliminate %ofs4 after widening outercount +; CHECK-NOT: sext +; CHECK: getelementptr +; +; TODO: Eliminate %ofs5 after removing lcssa +outermerge: + %innercount.merge = phi i32 [ %innercount.lcssa, %innerexit ], [ %innercount, %innerpreheader ] + + %ofs4 = sext i32 %outercount to i64 + %adr4 = getelementptr i8* %address, i64 %ofs4 + store i8 0, i8* %adr4 + + %ofs5 = sext i32 %innercount.merge to i64 + %adr5 = getelementptr i8* %address, i64 %ofs5 + store i8 0, i8* %adr5 + + %outerpostcount = add i32 %outercount, 1 + %tmp47 = icmp slt i32 %outerpostcount, %limit + br i1 %tmp47, label %outerloop, label %return + +return: + ret void +} diff --git a/test/Transforms/IndVarSimplify/iv-sext.ll b/test/Transforms/IndVarSimplify/iv-sext.ll index 3e90873..6c7a627 100644 --- a/test/Transforms/IndVarSimplify/iv-sext.ll +++ b/test/Transforms/IndVarSimplify/iv-sext.ll @@ -1,6 +1,4 @@ -; RUN: opt < %s -indvars -S > %t -; RUN: grep {= sext} %t | count 4 -; RUN: grep {phi i64} %t | count 2 +; RUN: opt < %s -indvars -S | FileCheck %s ; Indvars should be able to promote the hiPart induction variable in the ; inner loop to i64. @@ -18,6 +16,9 @@ bb.nph22: ; preds = %entry %tmp3 = add i32 %bandEdgeIndex, -1 ; <i32> [#uses=2] br label %bb +; CHECK: bb: +; CHECK: phi i64 +; CHECK-NOT: phi i64 bb: ; preds = %bb8, %bb.nph22 %distERBhi.121 = phi float [ %distERBhi.2.lcssa, %bb8 ], [ 0.000000e+00, %bb.nph22 ] ; <float> [#uses=2] %distERBlo.120 = phi float [ %distERBlo.0.lcssa, %bb8 ], [ 0.000000e+00, %bb.nph22 ] ; <float> [#uses=2] @@ -28,6 +29,7 @@ bb: ; preds = %bb8, %bb.nph22 %tmp4 = icmp sgt i32 %part.016, 0 ; <i1> [#uses=1] br i1 %tmp4, label %bb1, label %bb3.preheader +; CHECK: bb1: bb1: ; preds = %bb %tmp5 = add i32 %part.016, -1 ; <i32> [#uses=1] %tmp6 = sext i32 %tmp5 to i64 ; <i64> [#uses=1] @@ -86,7 +88,10 @@ bb5.preheader: ; preds = %bb3.bb5.preheader_crit_edge, %bb3.preheader bb.nph12: ; preds = %bb5.preheader br label %bb4 - +; CHECK: bb4: +; CHECK: phi i64 +; CHECK-NOT: phi i64 +; CHECK-NOT: sext bb4: ; preds = %bb5, %bb.nph12 %distERBhi.29 = phi float [ %tmp30, %bb5 ], [ %distERBhi.0.ph, %bb.nph12 ] ; <float> [#uses=1] %hiPart.08 = phi i32 [ %tmp31, %bb5 ], [ %hiPart.119, %bb.nph12 ] ; <i32> [#uses=2] @@ -102,6 +107,7 @@ bb4: ; preds = %bb5, %bb.nph12 %tmp35 = fadd float %tmp34, %peakCount.27 ; <float> [#uses=2] br label %bb5 +; CHECK: bb5: bb5: ; preds = %bb4 %.not = fcmp olt float %tmp30, 2.500000e+00 ; <i1> [#uses=1] %tmp36 = icmp sgt i32 %tmp3, %tmp31 ; <i1> [#uses=1] diff --git a/test/Transforms/IndVarSimplify/iv-zext.ll b/test/Transforms/IndVarSimplify/iv-zext.ll index 80a77b6..00018ec 100644 --- a/test/Transforms/IndVarSimplify/iv-zext.ll +++ b/test/Transforms/IndVarSimplify/iv-zext.ll @@ -1,6 +1,6 @@ -; RUN: opt < %s -indvars -S > %t -; RUN: not grep and %t -; RUN: not grep zext %t +; RUN: opt < %s -indvars -S | FileCheck %s +; CHECK-NOT: and +; CHECK-NOT: zext target datalayout = "-p:64:64:64-n:32:64" diff --git a/test/Transforms/IndVarSimplify/no-iv-rewrite.ll b/test/Transforms/IndVarSimplify/no-iv-rewrite.ll new file mode 100644 index 0000000..c35feef --- /dev/null +++ b/test/Transforms/IndVarSimplify/no-iv-rewrite.ll @@ -0,0 +1,123 @@ +; RUN: opt < %s -indvars -disable-iv-rewrite -S | FileCheck %s +; +; Make sure that indvars isn't inserting canonical IVs. +; This is kinda hard to do until linear function test replacement is removed. + +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 @sum(i32* %arr, i32 %n) nounwind { +entry: + %precond = icmp slt i32 0, %n + br i1 %precond, label %ph, label %return + +ph: + br label %loop + +; CHECK: loop: +; +; We should only have 2 IVs. +; CHECK: phi +; CHECK: phi +; CHECK-NOT: phi +; +; sext should be eliminated while preserving gep inboundsness. +; CHECK-NOT: sext +; CHECK: getelementptr inbounds +loop: + %i.02 = phi i32 [ 0, %ph ], [ %iinc, %loop ] + %s.01 = phi i32 [ 0, %ph ], [ %sinc, %loop ] + %ofs = sext i32 %i.02 to i64 + %adr = getelementptr inbounds i32* %arr, i64 %ofs + %val = load i32* %adr + %sinc = add nsw i32 %s.01, %val + %iinc = add nsw i32 %i.02, 1 + %cond = icmp slt i32 %iinc, %n + br i1 %cond, label %loop, label %exit + +exit: + %s.lcssa = phi i32 [ %sinc, %loop ] + br label %return + +return: + %s.0.lcssa = phi i32 [ %s.lcssa, %exit ], [ 0, %entry ] + ret i32 %s.0.lcssa +} + +define i64 @suml(i32* %arr, i32 %n) nounwind { +entry: + %precond = icmp slt i32 0, %n + br i1 %precond, label %ph, label %return + +ph: + br label %loop + +; CHECK: loop: +; +; We should only have 2 IVs. +; CHECK: phi +; CHECK: phi +; CHECK-NOT: phi +; +; %ofs sext should be eliminated while preserving gep inboundsness. +; CHECK-NOT: sext +; CHECK: getelementptr inbounds +; %vall sext should obviously not be eliminated +; CHECK: sext +loop: + %i.02 = phi i32 [ 0, %ph ], [ %iinc, %loop ] + %s.01 = phi i64 [ 0, %ph ], [ %sinc, %loop ] + %ofs = sext i32 %i.02 to i64 + %adr = getelementptr inbounds i32* %arr, i64 %ofs + %val = load i32* %adr + %vall = sext i32 %val to i64 + %sinc = add nsw i64 %s.01, %vall + %iinc = add nsw i32 %i.02, 1 + %cond = icmp slt i32 %iinc, %n + br i1 %cond, label %loop, label %exit + +exit: + %s.lcssa = phi i64 [ %sinc, %loop ] + br label %return + +return: + %s.0.lcssa = phi i64 [ %s.lcssa, %exit ], [ 0, %entry ] + ret i64 %s.0.lcssa +} + +define void @outofbounds(i32* %first, i32* %last, i32 %idx) nounwind { + %precond = icmp ne i32* %first, %last + br i1 %precond, label %ph, label %return + +; CHECK: ph: +; It's not indvars' job to perform LICM on %ofs +; CHECK-NOT: sext +ph: + br label %loop + +; CHECK: loop: +; +; Preserve exactly one pointer type IV. +; CHECK: phi i32* +; CHECK-NOT: phi +; +; Don't create any extra adds. +; CHECK-NOT: add +; +; Preserve gep inboundsness, and don't factor it. +; CHECK: getelementptr inbounds i32* %ptriv, i32 1 +; CHECK-NOT: add +loop: + %ptriv = phi i32* [ %first, %ph ], [ %ptrpost, %loop ] + %ofs = sext i32 %idx to i64 + %adr = getelementptr inbounds i32* %ptriv, i64 %ofs + store i32 3, i32* %adr + %ptrpost = getelementptr inbounds i32* %ptriv, i32 1 + %cond = icmp ne i32* %ptrpost, %last + br i1 %cond, label %loop, label %exit + +exit: + br label %return + +return: + ret void +} diff --git a/test/Transforms/IndVarSimplify/phi-uses-value-multiple-times.ll b/test/Transforms/IndVarSimplify/phi-uses-value-multiple-times.ll index 34d432b..52c9e5c 100644 --- a/test/Transforms/IndVarSimplify/phi-uses-value-multiple-times.ll +++ b/test/Transforms/IndVarSimplify/phi-uses-value-multiple-times.ll @@ -1,4 +1,8 @@ -; RUN: opt < %s -indvars +; RUN: opt < %s -indvars -disable-output -stats -info-output-file - | FileCheck %s +; Check that IndVarSimplify is not creating unnecessary canonical IVs +; that will never be used. +; CHECK-NOT: indvars + 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" @ue = external global i64 diff --git a/test/Transforms/Inline/array_merge.ll b/test/Transforms/Inline/array_merge.ll index 0d176b8..b2eafeb 100644 --- a/test/Transforms/Inline/array_merge.ll +++ b/test/Transforms/Inline/array_merge.ll @@ -19,7 +19,7 @@ entry: ; CHECK-NEXT: entry: ; CHECK-NEXT: %A.i = alloca ; CHECK-NEXT: %B.i = alloca -; CHECK-NEXT: call void +; CHECK-NOT: alloca call void @foo() nounwind call void @foo() nounwind ret void diff --git a/test/Transforms/Inline/inline_invoke.ll b/test/Transforms/Inline/inline_invoke.ll new file mode 100644 index 0000000..2a1b883 --- /dev/null +++ b/test/Transforms/Inline/inline_invoke.ll @@ -0,0 +1,336 @@ +; RUN: opt < %s -inline -S | FileCheck %s + +; Test that the inliner correctly handles inlining into invoke sites +; by appending selectors and forwarding _Unwind_Resume directly to the +; enclosing landing pad. + +;; Test 0 - basic functionality. + +%struct.A = type { i8 } + +@_ZTIi = external constant i8* + +declare void @_ZN1AC1Ev(%struct.A*) + +declare void @_ZN1AD1Ev(%struct.A*) + +declare void @use(i32) nounwind + +declare void @opaque() + +declare i8* @llvm.eh.exception() nounwind readonly + +declare i32 @llvm.eh.selector(i8*, i8*, ...) nounwind + +declare i32 @llvm.eh.typeid.for(i8*) nounwind + +declare void @llvm.eh.resume(i8*, i32) + +declare i32 @__gxx_personality_v0(...) + +declare i8* @__cxa_begin_catch(i8*) + +declare void @__cxa_end_catch() + +declare void @_ZSt9terminatev() + +define internal void @test0_in() alwaysinline uwtable ssp { +entry: + %a = alloca %struct.A, align 1 + %b = alloca %struct.A, align 1 + call void @_ZN1AC1Ev(%struct.A* %a) + invoke void @_ZN1AC1Ev(%struct.A* %b) + to label %invoke.cont unwind label %lpad + +invoke.cont: + invoke void @_ZN1AD1Ev(%struct.A* %b) + to label %invoke.cont1 unwind label %lpad + +invoke.cont1: + call void @_ZN1AD1Ev(%struct.A* %a) + ret void + +lpad: + %exn = call i8* @llvm.eh.exception() nounwind + %eh.selector = call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* %exn, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i32 0) nounwind + invoke void @_ZN1AD1Ev(%struct.A* %a) + to label %invoke.cont2 unwind label %terminate.lpad + +invoke.cont2: + call void @llvm.eh.resume(i8* %exn, i32 %eh.selector) noreturn + unreachable + +terminate.lpad: + %exn3 = call i8* @llvm.eh.exception() nounwind + %eh.selector4 = call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* %exn3, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* null) nounwind + call void @_ZSt9terminatev() noreturn nounwind + unreachable +} + +define void @test0_out() uwtable ssp { +entry: + invoke void @test0_in() + to label %ret unwind label %lpad + +ret: + ret void + +lpad: ; preds = %entry + %exn = call i8* @llvm.eh.exception() nounwind + %eh.selector = call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* %exn, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* bitcast (i8** @_ZTIi to i8*)) nounwind + %0 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) nounwind + %1 = icmp eq i32 %eh.selector, %0 + br i1 %1, label %catch, label %eh.resume + +catch: + %ignored = call i8* @__cxa_begin_catch(i8* %exn) nounwind + call void @__cxa_end_catch() nounwind + br label %ret + +eh.resume: + call void @llvm.eh.resume(i8* %exn, i32 %eh.selector) noreturn + unreachable +} + +; CHECK: define void @test0_out() +; CHECK: [[A:%.*]] = alloca %struct.A, +; CHECK: [[B:%.*]] = alloca %struct.A, +; CHECK: invoke void @_ZN1AC1Ev(%struct.A* [[A]]) +; CHECK: invoke void @_ZN1AC1Ev(%struct.A* [[B]]) +; CHECK: invoke void @_ZN1AD1Ev(%struct.A* [[B]]) +; CHECK: invoke void @_ZN1AD1Ev(%struct.A* [[A]]) +; CHECK: call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* {{%.*}}, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i32 0, i8* bitcast (i8** @_ZTIi to i8*)) +; CHECK-NEXT: invoke void @_ZN1AD1Ev(%struct.A* [[A]]) +; CHECK-NEXT: to label %[[LBL:[^\s]+]] unwind +; CHECK: [[LBL]]: +; CHECK-NEXT: br label %[[LPAD:[^\s]+]] +; CHECK: ret void +; CHECK: call i8* @llvm.eh.exception() +; CHECK-NEXT: call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* {{%.*}}, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* bitcast (i8** @_ZTIi to i8*)) +; CHECK-NEXT: br label %[[LPAD]] +; CHECK: [[LPAD]]: +; CHECK-NEXT: phi i8* [ +; CHECK-NEXT: phi i32 [ +; CHECK-NEXT: call i32 @llvm.eh.typeid.for( + + +;; Test 1 - Correctly handle phis in outer landing pads. + +define void @test1_out() uwtable ssp { +entry: + invoke void @test0_in() + to label %cont unwind label %lpad + +cont: + invoke void @test0_in() + to label %ret unwind label %lpad + +ret: + ret void + +lpad: + %x = phi i32 [ 0, %entry ], [ 1, %cont ] + %y = phi i32 [ 1, %entry ], [ 4, %cont ] + %exn = call i8* @llvm.eh.exception() nounwind + %eh.selector = call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* %exn, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* bitcast (i8** @_ZTIi to i8*)) nounwind + %0 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) nounwind + %1 = icmp eq i32 %eh.selector, %0 + br i1 %1, label %catch, label %eh.resume + +catch: + %ignored = call i8* @__cxa_begin_catch(i8* %exn) nounwind + call void @use(i32 %x) + call void @use(i32 %y) + call void @__cxa_end_catch() nounwind + br label %ret + +eh.resume: + call void @llvm.eh.resume(i8* %exn, i32 %eh.selector) noreturn + unreachable +} + +; CHECK: define void @test1_out() +; CHECK: [[A2:%.*]] = alloca %struct.A, +; CHECK: [[B2:%.*]] = alloca %struct.A, +; CHECK: [[A1:%.*]] = alloca %struct.A, +; CHECK: [[B1:%.*]] = alloca %struct.A, +; CHECK: invoke void @_ZN1AC1Ev(%struct.A* [[A1]]) +; CHECK-NEXT: unwind label %[[LPAD:[^\s]+]] +; CHECK: invoke void @_ZN1AC1Ev(%struct.A* [[B1]]) +; CHECK-NEXT: unwind label %[[LPAD1:[^\s]+]] +; CHECK: invoke void @_ZN1AD1Ev(%struct.A* [[B1]]) +; CHECK-NEXT: unwind label %[[LPAD1]] +; CHECK: invoke void @_ZN1AD1Ev(%struct.A* [[A1]]) +; CHECK-NEXT: unwind label %[[LPAD]] + +; Inner landing pad from first inlining. +; CHECK: [[LPAD1]]: +; CHECK-NEXT: [[EXN1:%.*]] = call i8* @llvm.eh.exception() +; CHECK-NEXT: [[SEL1:%.*]] = call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* [[EXN1]], i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i32 0, i8* bitcast (i8** @_ZTIi to i8*)) +; CHECK-NEXT: invoke void @_ZN1AD1Ev(%struct.A* [[A1]]) +; CHECK-NEXT: to label %[[RESUME1:[^\s]+]] unwind +; CHECK: [[RESUME1]]: +; CHECK-NEXT: br label %[[LPAD_JOIN1:[^\s]+]] + +; CHECK: invoke void @_ZN1AC1Ev(%struct.A* [[A2]]) +; CHECK-NEXT: unwind label %[[LPAD]] +; CHECK: invoke void @_ZN1AC1Ev(%struct.A* [[B2]]) +; CHECK-NEXT: unwind label %[[LPAD2:[^\s]+]] +; CHECK: invoke void @_ZN1AD1Ev(%struct.A* [[B2]]) +; CHECK-NEXT: unwind label %[[LPAD2]] +; CHECK: invoke void @_ZN1AD1Ev(%struct.A* [[A2]]) +; CHECK-NEXT: unwind label %[[LPAD]] + +; Inner landing pad from second inlining. +; CHECK: [[LPAD2]]: +; CHECK-NEXT: [[EXN2:%.*]] = call i8* @llvm.eh.exception() +; CHECK-NEXT: [[SEL2:%.*]] = call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* [[EXN2]], i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i32 0, i8* bitcast (i8** @_ZTIi to i8*)) +; CHECK-NEXT: invoke void @_ZN1AD1Ev(%struct.A* [[A2]]) +; CHECK-NEXT: to label %[[RESUME2:[^\s]+]] unwind +; CHECK: [[RESUME2]]: +; CHECK-NEXT: br label %[[LPAD_JOIN2:[^\s]+]] + +; CHECK: ret void + +; CHECK: [[LPAD]]: +; CHECK-NEXT: [[X:%.*]] = phi i32 [ 0, %entry ], [ 0, {{%.*}} ], [ 1, %cont ], [ 1, {{%.*}} ] +; CHECK-NEXT: [[Y:%.*]] = phi i32 [ 1, %entry ], [ 1, {{%.*}} ], [ 4, %cont ], [ 4, {{%.*}} ] +; CHECK-NEXT: [[EXN:%.*]] = call i8* @llvm.eh.exception() +; CHECK-NEXT: [[SEL:%.*]] = call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* [[EXN]], i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* bitcast (i8** @_ZTIi to i8*)) +; CHECK-NEXT: br label %[[LPAD_JOIN2]] + +; CHECK: [[LPAD_JOIN2]]: +; CHECK-NEXT: [[XJ2:%.*]] = phi i32 [ [[X]], %[[LPAD]] ], [ 1, %[[RESUME2]] ] +; CHECK-NEXT: [[YJ2:%.*]] = phi i32 [ [[Y]], %[[LPAD]] ], [ 4, %[[RESUME2]] ] +; CHECK-NEXT: [[EXNJ2:%.*]] = phi i8* [ [[EXN]], %[[LPAD]] ], [ [[EXN2]], %[[RESUME2]] ] +; CHECK-NEXT: [[SELJ2:%.*]] = phi i32 [ [[SEL]], %[[LPAD]] ], [ [[SEL2]], %[[RESUME2]] ] +; CHECK-NEXT: br label %[[LPAD_JOIN1]] + +; CHECK: [[LPAD_JOIN1]]: +; CHECK-NEXT: [[XJ1:%.*]] = phi i32 [ [[XJ2]], %[[LPAD_JOIN2]] ], [ 0, %[[RESUME1]] ] +; CHECK-NEXT: [[YJ1:%.*]] = phi i32 [ [[YJ2]], %[[LPAD_JOIN2]] ], [ 1, %[[RESUME1]] ] +; CHECK-NEXT: [[EXNJ1:%.*]] = phi i8* [ [[EXNJ2]], %[[LPAD_JOIN2]] ], [ [[EXN1]], %[[RESUME1]] ] +; CHECK-NEXT: [[SELJ1:%.*]] = phi i32 [ [[SELJ2]], %[[LPAD_JOIN2]] ], [ [[SEL1]], %[[RESUME1]] ] +; CHECK-NEXT: [[T:%.*]] = call i32 @llvm.eh.typeid.for( +; CHECK-NEXT: icmp eq i32 [[SELJ1]], [[T]] + +; CHECK: call void @use(i32 [[XJ1]]) +; CHECK: call void @use(i32 [[YJ1]]) + +; CHECK: call void @llvm.eh.resume(i8* [[EXNJ1]], i32 [[SELJ1]]) + + +;; Test 2 - Don't make invalid IR for inlines into landing pads without eh.exception calls +define void @test2_out() uwtable ssp { +entry: + invoke void @test0_in() + to label %ret unwind label %lpad + +ret: + ret void + +lpad: + call void @_ZSt9terminatev() + unreachable +} + +; CHECK: define void @test2_out() +; CHECK: [[A:%.*]] = alloca %struct.A, +; CHECK: [[B:%.*]] = alloca %struct.A, +; CHECK: invoke void @_ZN1AC1Ev(%struct.A* [[A]]) +; CHECK-NEXT: unwind label %[[LPAD:[^\s]+]] +; CHECK: invoke void @_ZN1AC1Ev(%struct.A* [[B]]) +; CHECK-NEXT: unwind label %[[LPAD2:[^\s]+]] +; CHECK: invoke void @_ZN1AD1Ev(%struct.A* [[B]]) +; CHECK-NEXT: unwind label %[[LPAD2]] +; CHECK: invoke void @_ZN1AD1Ev(%struct.A* [[A]]) +; CHECK-NEXT: unwind label %[[LPAD]] + + +;; Test 3 - Deal correctly with split unwind edges. +define void @test3_out() uwtable ssp { +entry: + invoke void @test0_in() + to label %ret unwind label %lpad + +ret: + ret void + +lpad: + br label %lpad.cont + +lpad.cont: + %exn = call i8* @llvm.eh.exception() nounwind + %eh.selector = call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* %exn, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* bitcast (i8** @_ZTIi to i8*)) nounwind + call void @_ZSt9terminatev() + unreachable +} + +; CHECK: define void @test3_out() +; CHECK: call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* {{%.*}}, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i32 0, i8* bitcast (i8** @_ZTIi to i8*)) +; CHECK-NEXT: invoke void @_ZN1AD1Ev( +; CHECK-NEXT: to label %[[L:[^\s]+]] unwind +; CHECK: [[L]]: +; CHECK-NEXT: br label %[[JOIN:[^\s]+]] +; CHECK: [[JOIN]]: +; CHECK-NEXT: phi +; CHECK-NEXT: phi +; CHECK-NEXT: br label %lpad.cont +; CHECK: lpad.cont: +; CHECK-NEXT: call void @_ZSt9terminatev() + + +;; Test 4 - Split unwind edges with a dominance problem +define void @test4_out() uwtable ssp { +entry: + invoke void @test0_in() + to label %cont unwind label %lpad.crit + +cont: + invoke void @opaque() + to label %ret unwind label %lpad + +ret: + ret void + +lpad.crit: + call void @opaque() nounwind + br label %lpad + +lpad: + %phi = phi i32 [ 0, %lpad.crit ], [ 1, %cont ] + %exn = call i8* @llvm.eh.exception() nounwind + %eh.selector = call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* %exn, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* bitcast (i8** @_ZTIi to i8*)) nounwind + call void @use(i32 %phi) + call void @_ZSt9terminatev() + unreachable +} + +; CHECK: define void @test4_out() +; CHECK: call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* {{%.*}}, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i32 0, i8* bitcast (i8** @_ZTIi to i8*)) +; CHECK-NEXT: invoke void @_ZN1AD1Ev( +; CHECK-NEXT: to label %[[L:[^\s]+]] unwind +; CHECK: [[L]]: +; CHECK-NEXT: br label %[[JOIN:[^\s]+]] +; CHECK: invoke void @opaque() +; CHECK-NEXT: unwind label %lpad +; CHECK: lpad.crit: +; CHECK-NEXT: call i8* @llvm.eh.exception() +; CHECK-NEXT: call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* %4, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* bitcast (i8** @_ZTIi to i8*)) +; CHECK-NEXT: br label %[[JOIN]] +; CHECK: [[JOIN]]: +; CHECK-NEXT: phi i8* +; CHECK-NEXT: phi i32 +; CHECK-NEXT: call void @opaque() nounwind +; CHECK-NEXT: br label %[[FIX:[^\s]+]] +; CHECK: lpad: +; CHECK-NEXT: [[T0:%.*]] = phi i32 [ 1, %cont ] +; CHECK-NEXT: call i8* @llvm.eh.exception() nounwind +; CHECK-NEXT: call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* %exn, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* bitcast (i8** @_ZTIi to i8*)) +; CHECK-NEXT: br label %[[FIX]] +; CHECK: [[FIX]]: +; CHECK-NEXT: [[T1:%.*]] = phi i32 [ [[T0]], %lpad ], [ 0, %[[JOIN]] ] +; CHECK-NEXT: phi i8* +; CHECK-NEXT: phi i32 +; CHECK-NEXT: call void @use(i32 [[T1]]) +; CHECK-NEXT: call void @_ZSt9terminatev() diff --git a/test/Transforms/Inline/lifetime.ll b/test/Transforms/Inline/lifetime.ll new file mode 100644 index 0000000..a95c836 --- /dev/null +++ b/test/Transforms/Inline/lifetime.ll @@ -0,0 +1,78 @@ +; RUN: opt -inline %s -S -o - | FileCheck %s + +declare void @llvm.lifetime.start(i64, i8*) +declare void @llvm.lifetime.end(i64, i8*) + +define void @helper_both_markers() { + %a = alloca i8 + call void @llvm.lifetime.start(i64 1, i8* %a) + call void @llvm.lifetime.end(i64 1, i8* %a) + ret void +} + +define void @test_both_markers() { +; CHECK: @test_both_markers +; CHECK: llvm.lifetime.start(i64 1 +; CHECK-NEXT: llvm.lifetime.end(i64 1 + call void @helper_both_markers() +; CHECK-NEXT: llvm.lifetime.start(i64 1 +; CHECK-NEXT: llvm.lifetime.end(i64 1 + call void @helper_both_markers() +; CHECK-NEXT: ret void + ret void +} + +;; Without this, the inliner will simplify out @test_no_marker before adding +;; any lifetime markers. +declare void @use(i8* %a) + +define void @helper_no_markers() { + %a = alloca i8 + call void @use(i8* %a) + ret void +} + +;; We can't use CHECK-NEXT because there's an extra call void @use in between. +;; Instead, we use CHECK-NOT to verify that there are no other lifetime calls. +define void @test_no_marker() { +; CHECK: @test_no_marker +; CHECK-NOT: lifetime +; CHECK: llvm.lifetime.start(i64 -1 +; CHECK-NOT: lifetime +; CHECK: llvm.lifetime.end(i64 -1 + call void @helper_no_markers() +; CHECK-NOT: lifetime +; CHECK: llvm.lifetime.start(i64 -1 +; CHECK-NOT: lifetime +; CHECK: llvm.lifetime.end(i64 -1 + call void @helper_no_markers() +; CHECK-NOT: lifetime +; CHECK: ret void + ret void +} + +define void @helper_two_casts() { + %a = alloca i32 + %b = bitcast i32* %a to i8* + call void @llvm.lifetime.start(i64 4, i8* %b) + %c = bitcast i32* %a to i8* + call void @llvm.lifetime.end(i64 4, i8* %c) + ret void +} + +define void @test_two_casts() { +; CHECK: @test_two_casts +; CHECK-NOT: lifetime +; CHECK: llvm.lifetime.start(i64 4 +; CHECK-NOT: lifetime +; CHECK: llvm.lifetime.end(i64 4 + call void @helper_two_casts() +; CHECK-NOT: lifetime +; CHECK: llvm.lifetime.start(i64 4 +; CHECK-NOT: lifetime +; CHECK: llvm.lifetime.end(i64 4 + call void @helper_two_casts() +; CHECK-NOT: lifetime +; CHECK: ret void + ret void +} diff --git a/test/Transforms/InstCombine/2011-05-02-VectorBoolean.ll b/test/Transforms/InstCombine/2011-05-02-VectorBoolean.ll new file mode 100644 index 0000000..02b64e3 --- /dev/null +++ b/test/Transforms/InstCombine/2011-05-02-VectorBoolean.ll @@ -0,0 +1,15 @@ +; RUN: opt < %s -instcombine +; PR9579 + +define <2 x i16> @entry(<2 x i16> %a) nounwind { +entry: + %a.addr = alloca <2 x i16>, align 4 + %.compoundliteral = alloca <2 x i16>, align 4 + store <2 x i16> %a, <2 x i16>* %a.addr, align 4 + %tmp = load <2 x i16>* %a.addr, align 4 + store <2 x i16> zeroinitializer, <2 x i16>* %.compoundliteral + %tmp1 = load <2 x i16>* %.compoundliteral + %cmp = icmp uge <2 x i16> %tmp, %tmp1 + %sext = sext <2 x i1> %cmp to <2 x i16> + ret <2 x i16> %sext +} diff --git a/test/Transforms/InstCombine/2011-05-13-InBoundsGEP.ll b/test/Transforms/InstCombine/2011-05-13-InBoundsGEP.ll new file mode 100644 index 0000000..fba7239 --- /dev/null +++ b/test/Transforms/InstCombine/2011-05-13-InBoundsGEP.ll @@ -0,0 +1,21 @@ +; RUN: opt < %s -S -instcombine | FileCheck %s +; rdar://problem/9267970 +; ideally this test will run on a 32-bit host +; must not discard GEPs that might overflow at runtime (aren't inbounds) + +define i32 @main(i32 %argc) { +entry: + %tmp1 = add i32 %argc, -2 + %tmp2 = add i32 %argc, 1879048192 + %p = alloca i8 +; CHECK: getelementptr + %p1 = getelementptr i8* %p, i32 %tmp1 +; CHECK: getelementptr + %p2 = getelementptr i8* %p, i32 %tmp2 + %cmp = icmp ult i8* %p1, %p2 + br i1 %cmp, label %bbtrue, label %bbfalse +bbtrue: ; preds = %entry + ret i32 -1 +bbfalse: ; preds = %entry + ret i32 0 +} diff --git a/test/Transforms/InstCombine/2011-05-28-swapmulsub.ll b/test/Transforms/InstCombine/2011-05-28-swapmulsub.ll new file mode 100644 index 0000000..b096d1f --- /dev/null +++ b/test/Transforms/InstCombine/2011-05-28-swapmulsub.ll @@ -0,0 +1,57 @@ +; ModuleID = 'test1.c' +; RUN: opt -S -instcombine < %s | FileCheck %s +target triple = "x86_64-apple-macosx10.6.6" + +define zeroext i16 @foo1(i32 %on_off) nounwind uwtable ssp { +entry: + %on_off.addr = alloca i32, align 4 + %a = alloca i32, align 4 + store i32 %on_off, i32* %on_off.addr, align 4 + %tmp = load i32* %on_off.addr, align 4 + %sub = sub i32 1, %tmp +; CHECK-NOT: mul i32 + %mul = mul i32 %sub, -2 +; CHECK: shl +; CHECK-NEXT: add + store i32 %mul, i32* %a, align 4 + %tmp1 = load i32* %a, align 4 + %conv = trunc i32 %tmp1 to i16 + ret i16 %conv +} + +define zeroext i16 @foo2(i32 %on_off, i32 %q) nounwind uwtable ssp { +entry: + %on_off.addr = alloca i32, align 4 + %q.addr = alloca i32, align 4 + %a = alloca i32, align 4 + store i32 %on_off, i32* %on_off.addr, align 4 + store i32 %q, i32* %q.addr, align 4 + %tmp = load i32* %q.addr, align 4 + %tmp1 = load i32* %on_off.addr, align 4 + %sub = sub i32 %tmp, %tmp1 +; CHECK-NOT: mul i32 + %mul = mul i32 %sub, -4 +; CHECK: sub i32 +; CHECK-NEXT: shl + store i32 %mul, i32* %a, align 4 + %tmp2 = load i32* %a, align 4 + %conv = trunc i32 %tmp2 to i16 + ret i16 %conv +} + +define zeroext i16 @foo3(i32 %on_off) nounwind uwtable ssp { +entry: + %on_off.addr = alloca i32, align 4 + %a = alloca i32, align 4 + store i32 %on_off, i32* %on_off.addr, align 4 + %tmp = load i32* %on_off.addr, align 4 + %sub = sub i32 7, %tmp +; CHECK-NOT: mul i32 + %mul = mul i32 %sub, -4 +; CHECK: shl +; CHECK-NEXT: add + store i32 %mul, i32* %a, align 4 + %tmp1 = load i32* %a, align 4 + %conv = trunc i32 %tmp1 to i16 + ret i16 %conv +} diff --git a/test/Transforms/InstCombine/call.ll b/test/Transforms/InstCombine/call.ll index 2ef8dc0..d084873 100644 --- a/test/Transforms/InstCombine/call.ll +++ b/test/Transforms/InstCombine/call.ll @@ -53,8 +53,8 @@ define i8 @test4a() { define i32 @test4() { %X = call i32 bitcast (i8 ()* @test4a to i32 ()*)( ) ; <i32> [#uses=1] ret i32 %X -; CHECK: %X1 = call i8 @test4a() -; CHECK: %tmp = zext i8 %X1 to i32 +; CHECK: %X = call i8 @test4a() +; CHECK: %tmp = zext i8 %X to i32 ; CHECK: ret i32 %tmp } @@ -77,8 +77,8 @@ declare i32 @test6a(i32) define i32 @test6() { %X = call i32 bitcast (i32 (i32)* @test6a to i32 ()*)( ) ret i32 %X -; CHECK: %X1 = call i32 @test6a(i32 0) -; CHECK: ret i32 %X1 +; CHECK: %X = call i32 @test6a(i32 0) +; CHECK: ret i32 %X } diff --git a/test/Transforms/InstCombine/div.ll b/test/Transforms/InstCombine/div.ll index 2e24f19..8a0897b 100644 --- a/test/Transforms/InstCombine/div.ll +++ b/test/Transforms/InstCombine/div.ll @@ -118,3 +118,17 @@ define i32 @test14(i8 %x) nounwind { ; CHECK: @test14 ; CHECK-NEXT: ret i32 0 } + +; PR9814 +define i32 @test15(i32 %a, i32 %b) nounwind { + %shl = shl i32 1, %b + %div = lshr i32 %shl, 2 + %div2 = udiv i32 %a, %div + ret i32 %div2 +; CHECK: @test15 +; CHECK-NEXT: add i32 %b, -2 +; CHECK-NEXT: lshr i32 %a, +; CHECK-NEXT: ret i32 +} + + diff --git a/test/Transforms/InstCombine/exact.ll b/test/Transforms/InstCombine/exact.ll index 58f8b5d..14741e3 100644 --- a/test/Transforms/InstCombine/exact.ll +++ b/test/Transforms/InstCombine/exact.ll @@ -96,6 +96,22 @@ define i1 @ashr_icmp2(i64 %X) nounwind { ret i1 %Z } +; PR9998 +; Make sure we don't transform the ashr here into an sdiv +; CHECK: @pr9998 +; CHECK: = and i32 %V, 1 +; CHECK: %Z = icmp ne +; CHECK: ret i1 %Z +define i1 @pr9998(i32 %V) nounwind { +entry: + %W = shl i32 %V, 31 + %X = ashr exact i32 %W, 31 + %Y = sext i32 %X to i64 + %Z = icmp ugt i64 %Y, 7297771788697658747 + ret i1 %Z +} + + ; CHECK: @udiv_icmp1 ; CHECK: icmp ne i64 %X, 0 define i1 @udiv_icmp1(i64 %X) nounwind { diff --git a/test/Transforms/InstCombine/icmp.ll b/test/Transforms/InstCombine/icmp.ll index 099540a..1237ade 100644 --- a/test/Transforms/InstCombine/icmp.ll +++ b/test/Transforms/InstCombine/icmp.ll @@ -510,3 +510,14 @@ define i1 @test52(i32 %x1) nounwind { ret i1 %A } +; PR9838 +; CHECK: @test53 +; CHECK-NEXT: ashr exact +; CHECK-NEXT: ashr +; CHECK-NEXT: icmp +define i1 @test53(i32 %a, i32 %b) nounwind { + %x = ashr exact i32 %a, 30 + %y = ashr i32 %b, 30 + %z = icmp eq i32 %x, %y + ret i1 %z +} diff --git a/test/Transforms/InstCombine/intrinsics.ll b/test/Transforms/InstCombine/intrinsics.ll index 332cd46..107f313 100644 --- a/test/Transforms/InstCombine/intrinsics.ll +++ b/test/Transforms/InstCombine/intrinsics.ll @@ -30,9 +30,9 @@ define i8 @uaddtest2(i8 %A, i8 %B, i1* %overflowPtr) { ; CHECK: @uaddtest2 ; CHECK-NEXT: %and.A = and i8 %A, 127 ; CHECK-NEXT: %and.B = and i8 %B, 127 -; CHECK-NEXT: %1 = add nuw i8 %and.A, %and.B +; CHECK-NEXT: %x = add nuw i8 %and.A, %and.B ; CHECK-NEXT: store i1 false, i1* %overflowPtr -; CHECK-NEXT: ret i8 %1 +; CHECK-NEXT: ret i8 %x } define i8 @uaddtest3(i8 %A, i8 %B, i1* %overflowPtr) { @@ -46,9 +46,9 @@ define i8 @uaddtest3(i8 %A, i8 %B, i1* %overflowPtr) { ; CHECK: @uaddtest3 ; CHECK-NEXT: %or.A = or i8 %A, -128 ; CHECK-NEXT: %or.B = or i8 %B, -128 -; CHECK-NEXT: %1 = add i8 %or.A, %or.B +; CHECK-NEXT: %x = add i8 %or.A, %or.B ; CHECK-NEXT: store i1 true, i1* %overflowPtr -; CHECK-NEXT: ret i8 %1 +; CHECK-NEXT: ret i8 %x } define i8 @uaddtest4(i8 %A, i1* %overflowPtr) { diff --git a/test/Transforms/InstCombine/or.ll b/test/Transforms/InstCombine/or.ll index 94a5732..c0bb28d 100644 --- a/test/Transforms/InstCombine/or.ll +++ b/test/Transforms/InstCombine/or.ll @@ -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: %E1 = and i64 %A, 4294908984 -; CHECK-NEXT: %F = or i64 %E1, 32962 +; CHECK-NEXT: %E = and i64 %A, 4294908984 +; CHECK-NEXT: %F = or i64 %E, 32962 ; CHECK-NEXT: ret i64 %F } diff --git a/test/Transforms/InstCombine/select.ll b/test/Transforms/InstCombine/select.ll index 3925907..4ca9bd2 100644 --- a/test/Transforms/InstCombine/select.ll +++ b/test/Transforms/InstCombine/select.ll @@ -749,3 +749,53 @@ define i1 @test55(i1 %X, i32 %Y, i32 %Z) { ; CHECK: icmp eq ; CHECK: ret i1 } + +define i32 @test56(i16 %x) nounwind { + %tobool = icmp eq i16 %x, 0 + %conv = zext i16 %x to i32 + %cond = select i1 %tobool, i32 0, i32 %conv + ret i32 %cond +; CHECK: @test56 +; CHECK-NEXT: zext +; CHECK-NEXT: ret +} + +define i32 @test57(i32 %x, i32 %y) nounwind { + %and = and i32 %x, %y + %tobool = icmp eq i32 %x, 0 + %.and = select i1 %tobool, i32 0, i32 %and + ret i32 %.and +; CHECK: @test57 +; CHECK-NEXT: and i32 %x, %y +; CHECK-NEXT: ret +} + +define i32 @test58(i16 %x) nounwind { + %tobool = icmp ne i16 %x, 1 + %conv = zext i16 %x to i32 + %cond = select i1 %tobool, i32 %conv, i32 1 + ret i32 %cond +; CHECK: @test58 +; CHECK-NEXT: zext +; CHECK-NEXT: ret +} + +define i32 @test59(i32 %x, i32 %y) nounwind { + %and = and i32 %x, %y + %tobool = icmp ne i32 %x, %y + %.and = select i1 %tobool, i32 %and, i32 %y + ret i32 %.and +; CHECK: @test59 +; CHECK-NEXT: and i32 %x, %y +; CHECK-NEXT: ret +} + +define i1 @test60(i32 %x, i1* %y) nounwind { + %cmp = icmp eq i32 %x, 0 + %load = load i1* %y, align 1 + %cmp1 = icmp slt i32 %x, 1 + %sel = select i1 %cmp, i1 %load, i1 %cmp1 + ret i1 %sel +; CHECK: @test60 +; CHECK: select +} diff --git a/test/Transforms/InstCombine/shift.ll b/test/Transforms/InstCombine/shift.ll index bded68a..d9ac9cb 100644 --- a/test/Transforms/InstCombine/shift.ll +++ b/test/Transforms/InstCombine/shift.ll @@ -506,3 +506,24 @@ define i32 @test41(i32 %a, i32 %b) nounwind { ; CHECK-NEXT: shl i32 8, %b ; CHECK-NEXT: ret i32 } + +define i32 @test42(i32 %a, i32 %b) nounwind { + %div = lshr i32 4096, %b ; must be exact otherwise we'd divide by zero + %div2 = udiv i32 %a, %div + ret i32 %div2 +; CHECK: @test42 +; CHECK-NEXT: lshr exact i32 4096, %b +} + +define i32 @test43(i32 %a, i32 %b) nounwind { + %div = shl i32 4096, %b ; must be exact otherwise we'd divide by zero + %div2 = udiv i32 %a, %div + ret i32 %div2 +; CHECK: @test43 +; CHECK-NEXT: add i32 %b, 12 +; CHECK-NEXT: lshr +; CHECK-NEXT: ret +} + + + diff --git a/test/Transforms/InstCombine/vec_demanded_elts.ll b/test/Transforms/InstCombine/vec_demanded_elts.ll index 9f308aa..e0188fe 100644 --- a/test/Transforms/InstCombine/vec_demanded_elts.ll +++ b/test/Transforms/InstCombine/vec_demanded_elts.ll @@ -136,3 +136,19 @@ 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>) + +; <rdar://problem/6945110> +define <4 x i32> @kernel3_vertical(<4 x i16> * %src, <8 x i16> * %foo) nounwind { +entry: + %tmp = load <4 x i16>* %src + %tmp1 = load <8 x i16>* %foo +; CHECK: %tmp2 = shufflevector + %tmp2 = shufflevector <4 x i16> %tmp, <4 x i16> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef> +; pmovzxwd ignores the upper 64-bits of its input; -instcombine should remove this shuffle: +; CHECK-NOT: shufflevector + %tmp3 = shufflevector <8 x i16> %tmp1, <8 x i16> %tmp2, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 4, i32 5, i32 6, i32 7> +; CHECK-NEXT: pmovzxwd + %0 = call <4 x i32> @llvm.x86.sse41.pmovzxwd(<8 x i16> %tmp3) + ret <4 x i32> %0 +} +declare <4 x i32> @llvm.x86.sse41.pmovzxwd(<8 x i16>) nounwind readnone diff --git a/test/Transforms/InstCombine/x86-crc32-demanded.ll b/test/Transforms/InstCombine/x86-crc32-demanded.ll new file mode 100644 index 0000000..878b97d --- /dev/null +++ b/test/Transforms/InstCombine/x86-crc32-demanded.ll @@ -0,0 +1,17 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +; crc32 with 64-bit destination zeros high 32-bit. +; rdar://9467055 + +define i64 @test() nounwind { +entry: +; CHECK: test +; CHECK: tail call i64 @llvm.x86.sse42.crc32.64.64 +; CHECK-NOT: and +; CHECK: ret + %0 = tail call i64 @llvm.x86.sse42.crc32.64.64(i64 0, i64 4) nounwind + %1 = and i64 %0, 4294967295 + ret i64 %1 +} + +declare i64 @llvm.x86.sse42.crc32.64.64(i64, i64) nounwind readnone diff --git a/test/Transforms/InstSimplify/maxmin.ll b/test/Transforms/InstSimplify/maxmin.ll new file mode 100644 index 0000000..e921214 --- /dev/null +++ b/test/Transforms/InstSimplify/maxmin.ll @@ -0,0 +1,269 @@ +; RUN: opt < %s -instsimplify -S | FileCheck %s + +define i1 @max1(i32 %x, i32 %y) { +; CHECK: @max1 + %c = icmp sgt i32 %x, %y + %m = select i1 %c, i32 %x, i32 %y + %r = icmp slt i32 %m, %x + ret i1 %r +; CHECK: ret i1 false +} + +define i1 @max2(i32 %x, i32 %y) { +; CHECK: @max2 + %c = icmp sge i32 %x, %y + %m = select i1 %c, i32 %x, i32 %y + %r = icmp sge i32 %m, %x + ret i1 %r +; CHECK: ret i1 true +} + +define i1 @max3(i32 %x, i32 %y) { +; CHECK: @max3 + %c = icmp ugt i32 %x, %y + %m = select i1 %c, i32 %x, i32 %y + %r = icmp ult i32 %m, %x + ret i1 %r +; CHECK: ret i1 false +} + +define i1 @max4(i32 %x, i32 %y) { +; CHECK: @max4 + %c = icmp uge i32 %x, %y + %m = select i1 %c, i32 %x, i32 %y + %r = icmp uge i32 %m, %x + ret i1 %r +; CHECK: ret i1 true +} + +define i1 @max5(i32 %x, i32 %y) { +; CHECK: @max5 + %c = icmp sgt i32 %x, %y + %m = select i1 %c, i32 %x, i32 %y + %r = icmp sgt i32 %x, %m + ret i1 %r +; CHECK: ret i1 false +} + +define i1 @max6(i32 %x, i32 %y) { +; CHECK: @max6 + %c = icmp sge i32 %x, %y + %m = select i1 %c, i32 %x, i32 %y + %r = icmp sle i32 %x, %m + ret i1 %r +; CHECK: ret i1 true +} + +define i1 @max7(i32 %x, i32 %y) { +; CHECK: @max7 + %c = icmp ugt i32 %x, %y + %m = select i1 %c, i32 %x, i32 %y + %r = icmp ugt i32 %x, %m + ret i1 %r +; CHECK: ret i1 false +} + +define i1 @max8(i32 %x, i32 %y) { +; CHECK: @max8 + %c = icmp uge i32 %x, %y + %m = select i1 %c, i32 %x, i32 %y + %r = icmp ule i32 %x, %m + ret i1 %r +; CHECK: ret i1 true +} + +define i1 @min1(i32 %x, i32 %y) { +; CHECK: @min1 + %c = icmp sgt i32 %x, %y + %m = select i1 %c, i32 %y, i32 %x + %r = icmp sgt i32 %m, %x + ret i1 %r +; CHECK: ret i1 false +} + +define i1 @min2(i32 %x, i32 %y) { +; CHECK: @min2 + %c = icmp sge i32 %x, %y + %m = select i1 %c, i32 %y, i32 %x + %r = icmp sle i32 %m, %x + ret i1 %r +; CHECK: ret i1 true +} + +define i1 @min3(i32 %x, i32 %y) { +; CHECK: @min3 + %c = icmp ugt i32 %x, %y + %m = select i1 %c, i32 %y, i32 %x + %r = icmp ugt i32 %m, %x + ret i1 %r +; CHECK: ret i1 false +} + +define i1 @min4(i32 %x, i32 %y) { +; CHECK: @min4 + %c = icmp uge i32 %x, %y + %m = select i1 %c, i32 %y, i32 %x + %r = icmp ule i32 %m, %x + ret i1 %r +; CHECK: ret i1 true +} + +define i1 @min5(i32 %x, i32 %y) { +; CHECK: @min5 + %c = icmp sgt i32 %x, %y + %m = select i1 %c, i32 %y, i32 %x + %r = icmp slt i32 %x, %m + ret i1 %r +; CHECK: ret i1 false +} + +define i1 @min6(i32 %x, i32 %y) { +; CHECK: @min6 + %c = icmp sge i32 %x, %y + %m = select i1 %c, i32 %y, i32 %x + %r = icmp sge i32 %x, %m + ret i1 %r +; CHECK: ret i1 true +} + +define i1 @min7(i32 %x, i32 %y) { +; CHECK: @min7 + %c = icmp ugt i32 %x, %y + %m = select i1 %c, i32 %y, i32 %x + %r = icmp ult i32 %x, %m + ret i1 %r +; CHECK: ret i1 false +} + +define i1 @min8(i32 %x, i32 %y) { +; CHECK: @min8 + %c = icmp uge i32 %x, %y + %m = select i1 %c, i32 %y, i32 %x + %r = icmp uge i32 %x, %m + ret i1 %r +; CHECK: ret i1 true +} + +define i1 @maxmin1(i32 %x, i32 %y, i32 %z) { +; CHECK: @maxmin1 + %c1 = icmp sge i32 %x, %y + %max = select i1 %c1, i32 %x, i32 %y + %c2 = icmp sge i32 %x, %z + %min = select i1 %c2, i32 %z, i32 %x + %c = icmp sge i32 %max, %min + ret i1 %c +; CHECK: ret i1 true +} + +define i1 @maxmin2(i32 %x, i32 %y, i32 %z) { +; CHECK: @maxmin2 + %c1 = icmp sge i32 %x, %y + %max = select i1 %c1, i32 %x, i32 %y + %c2 = icmp sge i32 %x, %z + %min = select i1 %c2, i32 %z, i32 %x + %c = icmp sgt i32 %min, %max + ret i1 %c +; CHECK: ret i1 false +} + +define i1 @maxmin3(i32 %x, i32 %y, i32 %z) { +; CHECK: @maxmin3 + %c1 = icmp sge i32 %x, %y + %max = select i1 %c1, i32 %x, i32 %y + %c2 = icmp sge i32 %x, %z + %min = select i1 %c2, i32 %z, i32 %x + %c = icmp sle i32 %min, %max + ret i1 %c +; CHECK: ret i1 true +} + +define i1 @maxmin4(i32 %x, i32 %y, i32 %z) { +; CHECK: @maxmin4 + %c1 = icmp sge i32 %x, %y + %max = select i1 %c1, i32 %x, i32 %y + %c2 = icmp sge i32 %x, %z + %min = select i1 %c2, i32 %z, i32 %x + %c = icmp slt i32 %max, %min + ret i1 %c +; CHECK: ret i1 false +} + +define i1 @maxmin5(i32 %x, i32 %y, i32 %z) { +; CHECK: @maxmin5 + %c1 = icmp uge i32 %x, %y + %max = select i1 %c1, i32 %x, i32 %y + %c2 = icmp uge i32 %x, %z + %min = select i1 %c2, i32 %z, i32 %x + %c = icmp uge i32 %max, %min + ret i1 %c +; CHECK: ret i1 true +} + +define i1 @maxmin6(i32 %x, i32 %y, i32 %z) { +; CHECK: @maxmin6 + %c1 = icmp uge i32 %x, %y + %max = select i1 %c1, i32 %x, i32 %y + %c2 = icmp uge i32 %x, %z + %min = select i1 %c2, i32 %z, i32 %x + %c = icmp ugt i32 %min, %max + ret i1 %c +; CHECK: ret i1 false +} + +define i1 @maxmin7(i32 %x, i32 %y, i32 %z) { +; CHECK: @maxmin7 + %c1 = icmp uge i32 %x, %y + %max = select i1 %c1, i32 %x, i32 %y + %c2 = icmp uge i32 %x, %z + %min = select i1 %c2, i32 %z, i32 %x + %c = icmp ule i32 %min, %max + ret i1 %c +; CHECK: ret i1 true +} + +define i1 @maxmin8(i32 %x, i32 %y, i32 %z) { +; CHECK: @maxmin8 + %c1 = icmp uge i32 %x, %y + %max = select i1 %c1, i32 %x, i32 %y + %c2 = icmp uge i32 %x, %z + %min = select i1 %c2, i32 %z, i32 %x + %c = icmp ult i32 %max, %min + ret i1 %c +; CHECK: ret i1 false +} + +define i1 @eqcmp1(i32 %x, i32 %y) { +; CHECK: @eqcmp1 + %c = icmp sge i32 %x, %y + %max = select i1 %c, i32 %x, i32 %y + %r = icmp eq i32 %max, %x + ret i1 %r +; CHECK: ret i1 %c +} + +define i1 @eqcmp2(i32 %x, i32 %y) { +; CHECK: @eqcmp2 + %c = icmp sge i32 %x, %y + %max = select i1 %c, i32 %x, i32 %y + %r = icmp eq i32 %x, %max + ret i1 %r +; CHECK: ret i1 %c +} + +define i1 @eqcmp3(i32 %x, i32 %y) { +; CHECK: @eqcmp3 + %c = icmp uge i32 %x, %y + %max = select i1 %c, i32 %x, i32 %y + %r = icmp eq i32 %max, %x + ret i1 %r +; CHECK: ret i1 %c +} + +define i1 @eqcmp4(i32 %x, i32 %y) { +; CHECK: @eqcmp4 + %c = icmp uge i32 %x, %y + %max = select i1 %c, i32 %x, i32 %y + %r = icmp eq i32 %x, %max + ret i1 %r +; CHECK: ret i1 %c +} diff --git a/test/Transforms/LoopIdiom/basic.ll b/test/Transforms/LoopIdiom/basic.ll index 485114c..9695418 100644 --- a/test/Transforms/LoopIdiom/basic.ll +++ b/test/Transforms/LoopIdiom/basic.ll @@ -347,3 +347,40 @@ for.end: ; preds = %for.body ; CHECK-NOT: store ; CHECK: ret void } + + + +; PR9815 - This is a partial overlap case that cannot be safely transformed +; into a memcpy. +@g_50 = global [7 x i32] [i32 0, i32 0, i32 0, i32 0, i32 1, i32 0, i32 0], align 16 + +define i32 @test14() nounwind { +entry: + br label %for.body + +for.body: ; preds = %for.inc, %for.body.lr.ph + %tmp5 = phi i32 [ %inc, %for.body ], [ 0, %entry ] + %add = add nsw i32 %tmp5, 4 + %idxprom = sext i32 %add to i64 + %arrayidx = getelementptr inbounds [7 x i32]* @g_50, i32 0, i64 %idxprom + %tmp2 = load i32* %arrayidx, align 4 + %add4 = add nsw i32 %tmp5, 5 + %idxprom5 = sext i32 %add4 to i64 + %arrayidx6 = getelementptr inbounds [7 x i32]* @g_50, i32 0, i64 %idxprom5 + store i32 %tmp2, i32* %arrayidx6, align 4 + %inc = add nsw i32 %tmp5, 1 + %cmp = icmp slt i32 %inc, 2 + br i1 %cmp, label %for.body, label %for.end + +for.end: ; preds = %for.inc + %tmp8 = load i32* getelementptr inbounds ([7 x i32]* @g_50, i32 0, i64 6), align 4 + ret i32 %tmp8 +; CHECK: @test14 +; CHECK: for.body: +; CHECK: load i32 +; CHECK: store i32 +; CHECK: br i1 %cmp + +} + + diff --git a/test/Transforms/LoopStrengthReduce/2009-11-10-LSRCrash.ll b/test/Transforms/LoopStrengthReduce/X86/2009-11-10-LSRCrash.ll index 4032a59..4032a59 100644 --- a/test/Transforms/LoopStrengthReduce/2009-11-10-LSRCrash.ll +++ b/test/Transforms/LoopStrengthReduce/X86/2009-11-10-LSRCrash.ll diff --git a/test/Transforms/LoopStrengthReduce/X86/dg.exp b/test/Transforms/LoopStrengthReduce/X86/dg.exp new file mode 100644 index 0000000..7b7bd4e --- /dev/null +++ b/test/Transforms/LoopStrengthReduce/X86/dg.exp @@ -0,0 +1,5 @@ +load_lib llvm.exp + +if { [llvm_supports_target X86] } { + RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll}]] +} diff --git a/test/Transforms/LoopStrengthReduce/post-inc-icmpzero.ll b/test/Transforms/LoopStrengthReduce/post-inc-icmpzero.ll new file mode 100644 index 0000000..294c090 --- /dev/null +++ b/test/Transforms/LoopStrengthReduce/post-inc-icmpzero.ll @@ -0,0 +1,91 @@ +; RUN: opt -loop-reduce -S < %s | FileCheck %s +; PR9939 + +; LSR should property handle the post-inc offset when folding the +; non-IV operand of an icmp into the IV. + +; CHECK: %tmp2 = sub i64 %sub.ptr.lhs.cast, %sub.ptr.rhs.cast +; CHECK: %tmp3 = lshr i64 %tmp2, 1 +; CHECK: %tmp4 = mul i64 %tmp3, 2 +; CHECK: br label %for.body +; CHECK: for.body: +; CHECK: %lsr.iv5 = phi i64 [ %lsr.iv.next, %for.body ], [ %tmp4, %for.body.lr.ph ] +; CHECK: %lsr.iv.next = add i64 %lsr.iv5, -2 +; CHECK: %lsr.iv.next6 = inttoptr i64 %lsr.iv.next to i16* +; CHECK: %cmp27 = icmp eq i16* %lsr.iv.next6, null + +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-unknown-linux-gnu" + +%struct.Vector2 = type { i16*, [64 x i16], i32 } + +@.str = private unnamed_addr constant [37 x i8] c"0123456789abcdefghijklmnopqrstuvwxyz\00" + +define void @_Z15IntegerToStringjjR7Vector2(i32 %i, i32 %radix, %struct.Vector2* nocapture %result) nounwind noinline { +entry: + %buffer = alloca [33 x i16], align 16 + %add.ptr = getelementptr inbounds [33 x i16]* %buffer, i64 0, i64 33 + br label %do.body + +do.body: ; preds = %do.body, %entry + %0 = phi i64 [ %indvar.next44, %do.body ], [ 0, %entry ] + %i.addr.0 = phi i32 [ %div, %do.body ], [ %i, %entry ] + %tmp51 = sub i64 32, %0 + %incdec.ptr = getelementptr [33 x i16]* %buffer, i64 0, i64 %tmp51 + %rem = urem i32 %i.addr.0, 10 + %div = udiv i32 %i.addr.0, 10 + %idxprom = zext i32 %rem to i64 + %arrayidx = getelementptr inbounds [37 x i8]* @.str, i64 0, i64 %idxprom + %tmp5 = load i8* %arrayidx, align 1 + %conv = sext i8 %tmp5 to i16 + store i16 %conv, i16* %incdec.ptr, align 2 + %1 = icmp ugt i32 %i.addr.0, 9 + %indvar.next44 = add i64 %0, 1 + br i1 %1, label %do.body, label %do.end + +do.end: ; preds = %do.body + %xap.0 = inttoptr i64 %0 to i1* + %cap.0 = ptrtoint i1* %xap.0 to i64 + %sub.ptr.lhs.cast = ptrtoint i16* %add.ptr to i64 + %sub.ptr.rhs.cast = ptrtoint i16* %incdec.ptr to i64 + %sub.ptr.sub = sub i64 %sub.ptr.lhs.cast, %sub.ptr.rhs.cast + %sub.ptr.div39 = lshr exact i64 %sub.ptr.sub, 1 + %conv11 = trunc i64 %sub.ptr.div39 to i32 + %mLength = getelementptr inbounds %struct.Vector2* %result, i64 0, i32 2 + %idx.ext21 = bitcast i64 %sub.ptr.div39 to i64 + %incdec.ptr.sum = add i64 %idx.ext21, -1 + %cp.0.sum = sub i64 %incdec.ptr.sum, %0 + %add.ptr22 = getelementptr [33 x i16]* %buffer, i64 1, i64 %cp.0.sum + %cmp2740 = icmp eq i64 %idx.ext21, 0 + br i1 %cmp2740, label %for.end, label %for.body.lr.ph + +for.body.lr.ph: ; preds = %do.end + %tmp16 = load i32* %mLength, align 4 + %mBegin = getelementptr inbounds %struct.Vector2* %result, i64 0, i32 0 + %tmp14 = load i16** %mBegin, align 8 + %tmp48 = zext i32 %tmp16 to i64 + br label %for.body + +for.body: ; preds = %for.body, %for.body.lr.ph + %indvar = phi i64 [ 0, %for.body.lr.ph ], [ %indvar.next, %for.body ] + %tmp46 = add i64 %tmp51, %indvar + %p.042 = getelementptr [33 x i16]* %buffer, i64 0, i64 %tmp46 + %tmp47 = sub i64 %indvar, %0 + %incdec.ptr32 = getelementptr [33 x i16]* %buffer, i64 1, i64 %tmp47 + %tmp49 = add i64 %tmp48, %indvar + %dst.041 = getelementptr i16* %tmp14, i64 %tmp49 + %tmp29 = load i16* %p.042, align 2 + store i16 %tmp29, i16* %dst.041, align 2 + %cmp27 = icmp eq i16* %incdec.ptr32, %add.ptr22 + %indvar.next = add i64 %indvar, 1 + br i1 %cmp27, label %for.end.loopexit, label %for.body + +for.end.loopexit: ; preds = %for.body + br label %for.end + +for.end: ; preds = %for.end.loopexit, %do.end + %tmp38 = load i32* %mLength, align 4 + %add = add i32 %tmp38, %conv11 + store i32 %add, i32* %mLength, align 4 + ret void +} diff --git a/test/Transforms/LoopUnswitch/2011-06-02-CritSwitch.ll b/test/Transforms/LoopUnswitch/2011-06-02-CritSwitch.ll new file mode 100644 index 0000000..61c54dd --- /dev/null +++ b/test/Transforms/LoopUnswitch/2011-06-02-CritSwitch.ll @@ -0,0 +1,28 @@ +; RUN: opt -loop-unswitch -disable-output +; PR10031 + +define i32 @test(i32 %command) { +entry: + br label %tailrecurse + +tailrecurse: ; preds = %if.then14, %tailrecurse, %entry + br i1 undef, label %if.then, label %tailrecurse + +if.then: ; preds = %tailrecurse + switch i32 %command, label %sw.bb [ + i32 2, label %land.lhs.true + i32 0, label %land.lhs.true + ] + +land.lhs.true: ; preds = %if.then, %if.then + br i1 undef, label %sw.bb, label %if.then14 + +if.then14: ; preds = %land.lhs.true + switch i32 %command, label %tailrecurse [ + i32 0, label %sw.bb + i32 1, label %sw.bb + ] + +sw.bb: ; preds = %if.then14 + unreachable +} diff --git a/test/Transforms/MemCpyOpt/2011-06-02-CallSlotOverwritten.ll b/test/Transforms/MemCpyOpt/2011-06-02-CallSlotOverwritten.ll new file mode 100644 index 0000000..132966e --- /dev/null +++ b/test/Transforms/MemCpyOpt/2011-06-02-CallSlotOverwritten.ll @@ -0,0 +1,36 @@ +; RUN: opt < %s -basicaa -memcpyopt -S | FileCheck %s +; PR10067 +; Make sure the call+copy isn't optimized in such a way that +; %ret ends up with the wrong value. + +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-f80:128:128-n8:16:32" +target triple = "i386-apple-darwin10" + +%struct1 = type { i32, i32 } +%struct2 = type { %struct1, i8* } + +declare void @bar(%struct1* nocapture sret %agg.result) nounwind + +define i32 @foo() nounwind { + %x = alloca %struct1, align 8 + %y = alloca %struct2, align 8 + call void @bar(%struct1* sret %x) nounwind +; CHECK: call void @bar(%struct1* sret %x) + + %gepn1 = getelementptr inbounds %struct2* %y, i32 0, i32 0, i32 0 + store i32 0, i32* %gepn1, align 8 + %gepn2 = getelementptr inbounds %struct2* %y, i32 0, i32 0, i32 1 + store i32 0, i32* %gepn2, align 4 + + %bit1 = bitcast %struct1* %x to i64* + %bit2 = bitcast %struct2* %y to i64* + %load = load i64* %bit1, align 8 + store i64 %load, i64* %bit2, align 8 + +; CHECK: %load = load i64* %bit1, align 8 +; CHECK: store i64 %load, i64* %bit2, align 8 + + %gep1 = getelementptr %struct2* %y, i32 0, i32 0, i32 0 + %ret = load i32* %gep1 + ret i32 %ret +} diff --git a/test/Transforms/MemCpyOpt/memcpy.ll b/test/Transforms/MemCpyOpt/memcpy.ll index b387d32..5c6a94c 100644 --- a/test/Transforms/MemCpyOpt/memcpy.ll +++ b/test/Transforms/MemCpyOpt/memcpy.ll @@ -109,3 +109,23 @@ define void @test6(i8 *%P) { ; CHECK-NEXT: ret void } + +; PR9794 - Should forward memcpy into byval argument even though the memcpy +; isn't itself 8 byte aligned. +%struct.p = type { i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32 } + +define i32 @test7(%struct.p* nocapture byval align 8 %q) nounwind ssp { +entry: + %agg.tmp = alloca %struct.p, align 4 + %tmp = bitcast %struct.p* %agg.tmp to i8* + %tmp1 = bitcast %struct.p* %q to i8* + call void @llvm.memcpy.p0i8.p0i8.i64(i8* %tmp, i8* %tmp1, i64 48, i32 4, i1 false) + %call = call i32 @g(%struct.p* byval align 8 %agg.tmp) nounwind + ret i32 %call +; CHECK: @test7 +; CHECK: call i32 @g(%struct.p* byval align 8 %q) nounwind +} + +declare i32 @g(%struct.p* byval align 8) + + diff --git a/test/Transforms/PhaseOrdering/basic.ll b/test/Transforms/PhaseOrdering/basic.ll index c66e150..e5b2ba4 100644 --- a/test/Transforms/PhaseOrdering/basic.ll +++ b/test/Transforms/PhaseOrdering/basic.ll @@ -1,4 +1,5 @@ ; RUN: opt -O3 -S %s | FileCheck %s +; XFAIL: * 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-macosx10.6.7" diff --git a/test/Transforms/PhaseOrdering/dg.exp b/test/Transforms/PhaseOrdering/dg.exp new file mode 100644 index 0000000..f200589 --- /dev/null +++ b/test/Transforms/PhaseOrdering/dg.exp @@ -0,0 +1,3 @@ +load_lib llvm.exp + +RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll,c,cpp}]] diff --git a/test/Transforms/ScalarRepl/2011-05-06-CapturedAlloca.ll b/test/Transforms/ScalarRepl/2011-05-06-CapturedAlloca.ll new file mode 100644 index 0000000..816cb60 --- /dev/null +++ b/test/Transforms/ScalarRepl/2011-05-06-CapturedAlloca.ll @@ -0,0 +1,26 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s +; PR9820 + +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-unknown-linux-gnu" + +@func_1.l_10 = internal unnamed_addr constant [4 x i32] [i32 1, i32 0, i32 0, i32 0], align 16 + +define i32* @noop(i32* %p_29) nounwind readnone { +entry: + ret i32* %p_29 +} + +define i32 @main() nounwind { +entry: + %l_10 = alloca [4 x i32], align 16 + %tmp = bitcast [4 x i32]* %l_10 to i8* + call void @llvm.memcpy.p0i8.p0i8.i64(i8* %tmp, i8* bitcast ([4 x i32]* @func_1.l_10 to i8*), i64 16, i32 16, i1 false) +; CHECK: call void @llvm.memcpy + %arrayidx = getelementptr inbounds [4 x i32]* %l_10, i64 0, i64 0 + %call = call i32* @noop(i32* %arrayidx) + store i32 0, i32* %call + ret i32 0 +} + +declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i32, i1) nounwind diff --git a/test/Transforms/ScalarRepl/2011-06-08-VectorExtractValue.ll b/test/Transforms/ScalarRepl/2011-06-08-VectorExtractValue.ll new file mode 100644 index 0000000..32e67fb --- /dev/null +++ b/test/Transforms/ScalarRepl/2011-06-08-VectorExtractValue.ll @@ -0,0 +1,62 @@ +; RUN: opt < %s -S -scalarrepl | FileCheck %s +; RUN: opt < %s -S -scalarrepl-ssa | 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-macosx10.7.0" + +%0 = type { <2 x float>, float } +%struct.PointC3 = type { %struct.array } +%struct.Point_3 = type { %struct.PointC3 } +%struct.array = type { [3 x float], [4 x i8] } + +; CHECK: main +; CHECK-NOT: alloca +; CHECK: extractelement <2 x float> zeroinitializer + +define void @main() uwtable ssp { +entry: + %ref.tmp2 = alloca %0, align 16 + %tmpcast = bitcast %0* %ref.tmp2 to %struct.Point_3* + %0 = getelementptr %0* %ref.tmp2, i64 0, i32 0 + store <2 x float> zeroinitializer, <2 x float>* %0, align 16 + %1 = getelementptr inbounds %struct.Point_3* %tmpcast, i64 0, i32 0 + %base.i.i.i = getelementptr inbounds %struct.PointC3* %1, i64 0, i32 0 + %arrayidx.i.i.i.i = getelementptr inbounds %struct.array* %base.i.i.i, i64 0, i32 0, i64 0 + %tmp5.i.i = load float* %arrayidx.i.i.i.i, align 4 + ret void +} + +; CHECK: test1 +; CHECK-NOT: alloca +; CHECK: extractelement <2 x float> zeroinitializer + +define void @test1() uwtable ssp { +entry: + %ref.tmp2 = alloca {<2 x float>, float}, align 16 + %tmpcast = bitcast {<2 x float>, float}* %ref.tmp2 to float* + %0 = getelementptr {<2 x float>, float}* %ref.tmp2, i64 0, i32 0 + store <2 x float> zeroinitializer, <2 x float>* %0, align 16 + %tmp5.i.i = load float* %tmpcast, align 4 + ret void +} + +; CHECK: test2 +; CHECK-NOT: alloca +; CHECK: and i128 +; CHECK: or i128 +; CHECK: trunc i128 +; CHECK-NOT: insertelement +; CHECK-NOT: extractelement + +define float @test2() uwtable ssp { +entry: + %ref.tmp2 = alloca {<2 x float>, float}, align 16 + %tmpcast = bitcast {<2 x float>, float}* %ref.tmp2 to float* + %tmpcast2 = getelementptr {<2 x float>, float}* %ref.tmp2, i64 0, i32 1 + %0 = getelementptr {<2 x float>, float}* %ref.tmp2, i64 0, i32 0 + store <2 x float> zeroinitializer, <2 x float>* %0, align 16 + store float 1.0, float* %tmpcast2, align 4 + %r1 = load float* %tmpcast, align 4 + %r2 = load float* %tmpcast2, align 4 + %r = fadd float %r1, %r2 + ret float %r +} diff --git a/test/Transforms/ScalarRepl/debuginfo-preserved.ll b/test/Transforms/ScalarRepl/debuginfo-preserved.ll new file mode 100644 index 0000000..c149134 --- /dev/null +++ b/test/Transforms/ScalarRepl/debuginfo-preserved.ll @@ -0,0 +1,61 @@ +; RUN: opt < %s -scalarrepl -S | FileCheck %s +; RUN: opt < %s -scalarrepl-ssa -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-macosx10.6.0" + +; CHECK: f +; CHECK-NOT: llvm.dbg.declare +; CHECK: llvm.dbg.value +; CHECK: llvm.dbg.value +; CHECK: llvm.dbg.value +; CHECK: llvm.dbg.value +; CHECK: llvm.dbg.value + +define i32 @f(i32 %a, i32 %b) nounwind ssp { +entry: + %a.addr = alloca i32, align 4 + %b.addr = alloca i32, align 4 + %c = alloca i32, align 4 + store i32 %a, i32* %a.addr, align 4 + call void @llvm.dbg.declare(metadata !{i32* %a.addr}, metadata !6), !dbg !7 + store i32 %b, i32* %b.addr, align 4 + call void @llvm.dbg.declare(metadata !{i32* %b.addr}, metadata !8), !dbg !9 + call void @llvm.dbg.declare(metadata !{i32* %c}, metadata !10), !dbg !12 + %tmp = load i32* %a.addr, align 4, !dbg !13 + store i32 %tmp, i32* %c, align 4, !dbg !13 + %tmp1 = load i32* %a.addr, align 4, !dbg !14 + %tmp2 = load i32* %b.addr, align 4, !dbg !14 + %add = add nsw i32 %tmp1, %tmp2, !dbg !14 + store i32 %add, i32* %a.addr, align 4, !dbg !14 + %tmp3 = load i32* %c, align 4, !dbg !15 + %tmp4 = load i32* %b.addr, align 4, !dbg !15 + %sub = sub nsw i32 %tmp3, %tmp4, !dbg !15 + store i32 %sub, i32* %b.addr, align 4, !dbg !15 + %tmp5 = load i32* %a.addr, align 4, !dbg !16 + %tmp6 = load i32* %b.addr, align 4, !dbg !16 + %add7 = add nsw i32 %tmp5, %tmp6, !dbg !16 + ret i32 %add7, !dbg !16 +} + +declare void @llvm.dbg.declare(metadata, metadata) nounwind readnone + +!llvm.dbg.cu = !{!0} +!llvm.dbg.sp = !{!1} + +!0 = metadata !{i32 589841, i32 0, i32 12, metadata !"/d/j/debug-test.c", metadata !"/Volumes/Data/b", metadata !"clang version 3.0 (trunk 131941)", i1 true, i1 false, metadata !"", i32 0} ; [ DW_TAG_compile_unit ] +!1 = metadata !{i32 589870, i32 0, metadata !2, metadata !"f", metadata !"f", metadata !"", metadata !2, i32 1, metadata !3, i1 false, i1 true, i32 0, i32 0, i32 0, i32 256, i1 false, i32 (i32, i32)* @f, null, null} ; [ DW_TAG_subprogram ] +!2 = metadata !{i32 589865, metadata !"/d/j/debug-test.c", metadata !"/Volumes/Data/b", metadata !0} ; [ DW_TAG_file_type ] +!3 = metadata !{i32 589845, metadata !2, metadata !"", metadata !2, i32 0, i64 0, i64 0, i32 0, i32 0, i32 0, metadata !4, i32 0, i32 0} ; [ DW_TAG_subroutine_type ] +!4 = metadata !{metadata !5} +!5 = metadata !{i32 589860, metadata !0, metadata !"int", null, i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] +!6 = metadata !{i32 590081, metadata !1, metadata !"a", metadata !2, i32 16777217, metadata !5, i32 0} ; [ DW_TAG_arg_variable ] +!7 = metadata !{i32 1, i32 11, metadata !1, null} +!8 = metadata !{i32 590081, metadata !1, metadata !"b", metadata !2, i32 33554433, metadata !5, i32 0} ; [ DW_TAG_arg_variable ] +!9 = metadata !{i32 1, i32 18, metadata !1, null} +!10 = metadata !{i32 590080, metadata !11, metadata !"c", metadata !2, i32 2, metadata !5, i32 0} ; [ DW_TAG_auto_variable ] +!11 = metadata !{i32 589835, metadata !1, i32 1, i32 21, metadata !2, i32 0} ; [ DW_TAG_lexical_block ] +!12 = metadata !{i32 2, i32 9, metadata !11, null} +!13 = metadata !{i32 2, i32 14, metadata !11, null} +!14 = metadata !{i32 3, i32 5, metadata !11, null} +!15 = metadata !{i32 4, i32 5, metadata !11, null} +!16 = metadata !{i32 5, i32 5, metadata !11, null} diff --git a/test/Transforms/ScalarRepl/debuginfo.ll b/test/Transforms/ScalarRepl/debuginfo.ll index 6b8422c..ae2c6cc 100644 --- a/test/Transforms/ScalarRepl/debuginfo.ll +++ b/test/Transforms/ScalarRepl/debuginfo.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -scalarrepl -S | not grep alloca +; RUN: opt < %s -scalarrepl-ssa -S | not grep alloca target datalayout = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64" %llvm.dbg.anchor.type = type { i32, i32 } %llvm.dbg.basictype.type = type { i32, { }*, i8*, { }*, i32, i64, i64, i64, i32, i32 } diff --git a/test/Transforms/SimplifyCFG/PR9946.ll b/test/Transforms/SimplifyCFG/PR9946.ll new file mode 100644 index 0000000..4a61b84 --- /dev/null +++ b/test/Transforms/SimplifyCFG/PR9946.ll @@ -0,0 +1,18 @@ +; RUN: opt %s -simplifycfg -disable-output + +@foo = external constant i32 + +define i32 @f() { +entry: + br i1 icmp eq (i64 and (i64 ptrtoint (i32* @foo to i64), i64 15), i64 0), label %if.end, label %if.then + +if.then: ; preds = %entry + br label %return + +if.end: ; preds = %entry + br label %return + +return: ; preds = %if.end, %if.then + %storemerge = phi i32 [ 1, %if.end ], [ 0, %if.then ] + ret i32 %storemerge +} diff --git a/test/Transforms/SimplifyCFG/dce-cond-after-folding-terminator.ll b/test/Transforms/SimplifyCFG/dce-cond-after-folding-terminator.ll new file mode 100644 index 0000000..3996efd --- /dev/null +++ b/test/Transforms/SimplifyCFG/dce-cond-after-folding-terminator.ll @@ -0,0 +1,52 @@ +; RUN: opt -S <%s -simplifycfg | FileCheck %s + +define void @test_br(i32 %x) { +entry: +; CHECK: @test_br +; CHECK-NEXT: entry: +; CHECK-NEXT: ret void + %cmp = icmp eq i32 %x, 10 + br i1 %cmp, label %if.then, label %if.then + +if.then: ; preds = %entry + br label %if.end + +if.end: ; preds = %if.else, %if.then + ret void +} + +define void @test_switch(i32 %x) nounwind { +entry: +; CHECK: @test_switch +; CHECK-NEXT: entry: +; CHECK-NEXT: ret void + %rem = srem i32 %x, 3 + switch i32 %rem, label %sw.bb [ + i32 1, label %sw.bb + i32 10, label %sw.bb + ] + +sw.bb: ; preds = %sw.default, %entry, %entry + br label %sw.epilog + +sw.epilog: ; preds = %sw.bb + ret void +} + +define void @test_indirectbr(i32 %x) { +entry: +; CHECK: @test_indirectbr +; CHECK-NEXT: entry: +; Ideally this should now check: +; CHK-NEXT: ret void +; But that doesn't happen yet. Instead: +; CHECK-NEXT: br label %L1 + + %label = bitcast i8* blockaddress(@test_indirectbr, %L1) to i8* + indirectbr i8* %label, [label %L1, label %L2] + +L1: ; preds = %entry + ret void +L2: ; preds = %entry + ret void +} diff --git a/test/Transforms/SimplifyCFG/indirectbr.ll b/test/Transforms/SimplifyCFG/indirectbr.ll index 7fb4def..7853e9a 100644 --- a/test/Transforms/SimplifyCFG/indirectbr.ll +++ b/test/Transforms/SimplifyCFG/indirectbr.ll @@ -180,3 +180,72 @@ L3: ; before SimplifyCFG even looks at the indirectbr. indirectbr i8* %anchor, [label %L1, label %L2] } + +; PR10072 + +@xblkx.bbs = internal unnamed_addr constant [9 x i8*] [i8* blockaddress(@indbrtest7, %xblkx.begin), i8* blockaddress(@indbrtest7, %xblkx.begin3), i8* blockaddress(@indbrtest7, %xblkx.begin4), i8* blockaddress(@indbrtest7, %xblkx.begin5), i8* blockaddress(@indbrtest7, %xblkx.begin6), i8* blockaddress(@indbrtest7, %xblkx.begin7), i8* blockaddress(@indbrtest7, %xblkx.begin8), i8* blockaddress(@indbrtest7, %xblkx.begin9), i8* blockaddress(@indbrtest7, %xblkx.end)] + +define void @indbrtest7() { +escape-string.top: + %xval202x = call i32 @xfunc5x() + br label %xlab5x + +xlab8x: ; preds = %xlab5x + %xvaluex = call i32 @xselectorx() + %xblkx.x = getelementptr [9 x i8*]* @xblkx.bbs, i32 0, i32 %xvaluex + %xblkx.load = load i8** %xblkx.x + indirectbr i8* %xblkx.load, [label %xblkx.begin, label %xblkx.begin3, label %xblkx.begin4, label %xblkx.begin5, label %xblkx.begin6, label %xblkx.begin7, label %xblkx.begin8, label %xblkx.begin9, label %xblkx.end] + +xblkx.begin: + br label %xblkx.end + +xblkx.begin3: + br label %xblkx.end + +xblkx.begin4: + br label %xblkx.end + +xblkx.begin5: + br label %xblkx.end + +xblkx.begin6: + br label %xblkx.end + +xblkx.begin7: + br label %xblkx.end + +xblkx.begin8: + br label %xblkx.end + +xblkx.begin9: + br label %xblkx.end + +xblkx.end: + %yes.0 = phi i1 [ false, %xblkx.begin ], [ true, %xlab8x ], [ false, %xblkx.begin9 ], [ false, %xblkx.begin8 ], [ false, %xblkx.begin7 ], [ false, %xblkx.begin6 ], [ false, %xblkx.begin5 ], [ true, %xblkx.begin4 ], [ false, %xblkx.begin3 ] + br i1 %yes.0, label %v2j, label %xlab17x + +v2j: +; CHECK: %xunusedx = call i32 @xactionx() + %xunusedx = call i32 @xactionx() + br label %xlab4x + +xlab17x: + br label %xlab4x + +xlab4x: + %incr19 = add i32 %xval704x.0, 1 + br label %xlab5x + +xlab5x: + %xval704x.0 = phi i32 [ 0, %escape-string.top ], [ %incr19, %xlab4x ] + %xval10x = icmp ult i32 %xval704x.0, %xval202x + br i1 %xval10x, label %xlab8x, label %xlab9x + +xlab9x: + ret void +} + +declare i32 @xfunc5x() +declare i8 @xfunc7x() +declare i32 @xselectorx() +declare i32 @xactionx() diff --git a/test/Transforms/SimplifyCFG/switch-masked-bits.ll b/test/Transforms/SimplifyCFG/switch-masked-bits.ll new file mode 100644 index 0000000..fc83ec2 --- /dev/null +++ b/test/Transforms/SimplifyCFG/switch-masked-bits.ll @@ -0,0 +1,38 @@ +; RUN: opt -S -simplifycfg < %s | FileCheck %s + +define i32 @test1(i32 %x) nounwind { + %i = shl i32 %x, 1 + switch i32 %i, label %a [ + i32 21, label %b + i32 24, label %c + ] + +a: + ret i32 0 +b: + ret i32 3 +c: + ret i32 5 +; CHECK: @test1 +; CHECK: %cond = icmp eq i32 %i, 24 +; CHECK: %merge = select i1 %cond, i32 5, i32 0 +; CHECK: ret i32 %merge +} + + +define i32 @test2(i32 %x) nounwind { + %i = shl i32 %x, 1 + switch i32 %i, label %a [ + i32 21, label %b + i32 23, label %c + ] + +a: + ret i32 0 +b: + ret i32 3 +c: + ret i32 5 +; CHECK: @test2 +; CHECK: ret i32 0 +} diff --git a/test/Transforms/TailCallElim/setjmp.ll b/test/Transforms/TailCallElim/setjmp.ll new file mode 100644 index 0000000..7b7fe56 --- /dev/null +++ b/test/Transforms/TailCallElim/setjmp.ll @@ -0,0 +1,16 @@ +; RUN: opt < %s -tailcallelim -S | FileCheck %s + +; Test that we don't tail call in a functions that calls setjmp. + +; CHECK-NOT: tail call void @bar() + +define void @foo(i32* %x) { +bb: + %tmp75 = tail call i32 @setjmp(i32* %x) + call void @bar() + ret void +} + +declare i32 @setjmp(i32*) + +declare void @bar() diff --git a/test/Transforms/TailDup/X86/dg.exp b/test/Transforms/TailDup/X86/dg.exp new file mode 100644 index 0000000..7b7bd4e --- /dev/null +++ b/test/Transforms/TailDup/X86/dg.exp @@ -0,0 +1,5 @@ +load_lib llvm.exp + +if { [llvm_supports_target X86] } { + RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll}]] +} diff --git a/test/Transforms/TailDup/if-tail-dup.ll b/test/Transforms/TailDup/X86/if-tail-dup.ll index 2e4f5be..2e4f5be 100644 --- a/test/Transforms/TailDup/if-tail-dup.ll +++ b/test/Transforms/TailDup/X86/if-tail-dup.ll |