diff options
Diffstat (limited to 'llvm/test/Transforms')
88 files changed, 5710 insertions, 0 deletions
diff --git a/llvm/test/Transforms/NewGVN/2007-07-25-DominatedLoop.ll b/llvm/test/Transforms/NewGVN/2007-07-25-DominatedLoop.ll new file mode 100644 index 00000000000..76ff8999501 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/2007-07-25-DominatedLoop.ll @@ -0,0 +1,86 @@ +; RUN: opt < %s -newgvn | llvm-dis + + %struct.PerlInterpreter = type { i8 } +@PL_sv_count = external global i32 ; <i32*> [#uses=2] + +define void @perl_destruct(%struct.PerlInterpreter* %sv_interp) { +entry: + br i1 false, label %cond_next25, label %cond_true16 + +cond_true16: ; preds = %entry + ret void + +cond_next25: ; preds = %entry + br i1 false, label %cond_next33, label %cond_true32 + +cond_true32: ; preds = %cond_next25 + ret void + +cond_next33: ; preds = %cond_next25 + br i1 false, label %cond_next61, label %cond_true.i46 + +cond_true.i46: ; preds = %cond_next33 + ret void + +cond_next61: ; preds = %cond_next33 + br i1 false, label %cond_next69, label %cond_true66 + +cond_true66: ; preds = %cond_next61 + ret void + +cond_next69: ; preds = %cond_next61 + br i1 false, label %Perl_safefree.exit52, label %cond_true.i50 + +cond_true.i50: ; preds = %cond_next69 + ret void + +Perl_safefree.exit52: ; preds = %cond_next69 + br i1 false, label %cond_next80, label %cond_true77 + +cond_true77: ; preds = %Perl_safefree.exit52 + ret void + +cond_next80: ; preds = %Perl_safefree.exit52 + br i1 false, label %Perl_safefree.exit56, label %cond_true.i54 + +cond_true.i54: ; preds = %cond_next80 + ret void + +Perl_safefree.exit56: ; preds = %cond_next80 + br i1 false, label %Perl_safefree.exit60, label %cond_true.i58 + +cond_true.i58: ; preds = %Perl_safefree.exit56 + ret void + +Perl_safefree.exit60: ; preds = %Perl_safefree.exit56 + br i1 false, label %Perl_safefree.exit64, label %cond_true.i62 + +cond_true.i62: ; preds = %Perl_safefree.exit60 + ret void + +Perl_safefree.exit64: ; preds = %Perl_safefree.exit60 + br i1 false, label %Perl_safefree.exit68, label %cond_true.i66 + +cond_true.i66: ; preds = %Perl_safefree.exit64 + ret void + +Perl_safefree.exit68: ; preds = %Perl_safefree.exit64 + br i1 false, label %cond_next150, label %cond_true23.i + +cond_true23.i: ; preds = %Perl_safefree.exit68 + ret void + +cond_next150: ; preds = %Perl_safefree.exit68 + %tmp16092 = load i32, i32* @PL_sv_count, align 4 ; <i32> [#uses=0] + br label %cond_next165 + +bb157: ; preds = %cond_next165 + %tmp158 = load i32, i32* @PL_sv_count, align 4 ; <i32> [#uses=0] + br label %cond_next165 + +cond_next165: ; preds = %bb157, %cond_next150 + br i1 false, label %bb171, label %bb157 + +bb171: ; preds = %cond_next165 + ret void +} diff --git a/llvm/test/Transforms/NewGVN/2007-07-25-InfiniteLoop.ll b/llvm/test/Transforms/NewGVN/2007-07-25-InfiniteLoop.ll new file mode 100644 index 00000000000..fcbfb4c216b --- /dev/null +++ b/llvm/test/Transforms/NewGVN/2007-07-25-InfiniteLoop.ll @@ -0,0 +1,15 @@ +; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s + + %struct.INT2 = type { i32, i32 } +@blkshifts = external global %struct.INT2* ; <%struct.INT2**> [#uses=2] + +define i32 @xcompact() { +entry: + store %struct.INT2* null, %struct.INT2** @blkshifts, align 4 + br label %bb + +bb: ; preds = %bb, %entry + %tmp10 = load %struct.INT2*, %struct.INT2** @blkshifts, align 4 ; <%struct.INT2*> [#uses=0] +; CHECK-NOT: %tmp10 + br label %bb +} diff --git a/llvm/test/Transforms/NewGVN/2007-07-25-Loop.ll b/llvm/test/Transforms/NewGVN/2007-07-25-Loop.ll new file mode 100644 index 00000000000..aea5b7261d9 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/2007-07-25-Loop.ll @@ -0,0 +1,15 @@ +; RUN: opt < %s -newgvn | llvm-dis + + %struct.s_segment_inf = type { float, i32, i16, i16, float, float, i32, float, float } + +define void @print_arch(i8* %arch_file, i32 %route_type, i64 %det_routing_arch.0.0, i64 %det_routing_arch.0.1, i64 %det_routing_arch.0.2, i64 %det_routing_arch.0.3, i64 %det_routing_arch.0.4, %struct.s_segment_inf* %segment_inf, i64 %timing_inf.0.0, i64 %timing_inf.0.1, i64 %timing_inf.0.2, i64 %timing_inf.0.3, i64 %timing_inf.0.4, i32 %timing_inf.1) { +entry: + br i1 false, label %bb278, label %bb344 + +bb278: ; preds = %bb278, %entry + br i1 false, label %bb278, label %bb344 + +bb344: ; preds = %bb278, %entry + %tmp38758 = load i16, i16* null, align 2 ; <i16> [#uses=0] + ret void +} diff --git a/llvm/test/Transforms/NewGVN/2007-07-25-NestedLoop.ll b/llvm/test/Transforms/NewGVN/2007-07-25-NestedLoop.ll new file mode 100644 index 00000000000..63468248522 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/2007-07-25-NestedLoop.ll @@ -0,0 +1,38 @@ +; RUN: opt < %s -newgvn | llvm-dis + + %struct.TypHeader = type { i32, %struct.TypHeader**, [3 x i8], i8 } + +define %struct.TypHeader* @LtRec(%struct.TypHeader* %hdL, %struct.TypHeader* %hdR) { +entry: + br i1 false, label %bb556.preheader, label %bb534.preheader + +bb534.preheader: ; preds = %entry + ret %struct.TypHeader* null + +bb556.preheader: ; preds = %entry + %tmp56119 = getelementptr %struct.TypHeader, %struct.TypHeader* %hdR, i32 0, i32 0 ; <i32*> [#uses=1] + %tmp56220 = load i32, i32* %tmp56119 ; <i32> [#uses=0] + br i1 false, label %bb.nph23, label %bb675.preheader + +bb.nph23: ; preds = %bb556.preheader + ret %struct.TypHeader* null + +bb656: ; preds = %bb675.outer, %bb656 + %tmp678 = load i32, i32* %tmp677 ; <i32> [#uses=0] + br i1 false, label %bb684, label %bb656 + +bb684: ; preds = %bb675.outer, %bb656 + br i1 false, label %bb924.preheader, label %bb675.outer + +bb675.outer: ; preds = %bb675.preheader, %bb684 + %tmp67812 = load i32, i32* %tmp67711 ; <i32> [#uses=0] + br i1 false, label %bb684, label %bb656 + +bb675.preheader: ; preds = %bb556.preheader + %tmp67711 = getelementptr %struct.TypHeader, %struct.TypHeader* %hdR, i32 0, i32 0 ; <i32*> [#uses=1] + %tmp677 = getelementptr %struct.TypHeader, %struct.TypHeader* %hdR, i32 0, i32 0 ; <i32*> [#uses=1] + br label %bb675.outer + +bb924.preheader: ; preds = %bb684 + ret %struct.TypHeader* null +} diff --git a/llvm/test/Transforms/NewGVN/2007-07-25-SinglePredecessor.ll b/llvm/test/Transforms/NewGVN/2007-07-25-SinglePredecessor.ll new file mode 100644 index 00000000000..dfbdac09e9f --- /dev/null +++ b/llvm/test/Transforms/NewGVN/2007-07-25-SinglePredecessor.ll @@ -0,0 +1,29 @@ +; RUN: opt < %s -newgvn | llvm-dis + + %struct.ggBRDF = type { i32 (...)** } + %struct.ggBox3 = type { %struct.ggPoint3, %struct.ggPoint3 } + %struct.ggMaterialRecord = type { %struct.ggPoint2, %struct.ggBox3, %struct.ggBox3, %struct.ggSpectrum, %struct.ggSpectrum, %struct.ggSpectrum, %struct.ggBRDF*, i32, i32, i32, i32 } + %struct.ggONB3 = type { %struct.ggPoint3, %struct.ggPoint3, %struct.ggPoint3 } + %struct.ggPoint2 = type { [2 x double] } + %struct.ggPoint3 = type { [3 x double] } + %struct.ggSpectrum = type { [8 x float] } + %struct.mrViewingHitRecord = type { double, %struct.ggPoint3, %struct.ggONB3, %struct.ggPoint2, double, %struct.ggSpectrum, %struct.ggSpectrum, i32, i32, i32, i32 } + %struct.mrXEllipticalCylinder = type { %struct.ggBRDF, float, float, float, float, float, float } + +define i32 @_ZNK21mrZEllipticalCylinder10viewingHitERK6ggRay3dddR18mrViewingHitRecordR16ggMaterialRecord(%struct.mrXEllipticalCylinder* %this, %struct.ggBox3* %ray, double %unnamed_arg, double %tmin, double %tmax, %struct.mrViewingHitRecord* %VHR, %struct.ggMaterialRecord* %unnamed_arg2) { +entry: + %tmp80.i = getelementptr %struct.mrViewingHitRecord, %struct.mrViewingHitRecord* %VHR, i32 0, i32 1, i32 0, i32 0 ; <double*> [#uses=1] + store double 0.000000e+00, double* %tmp80.i + br i1 false, label %return, label %cond_next.i + +cond_next.i: ; preds = %entry + br i1 false, label %return, label %cond_true + +cond_true: ; preds = %cond_next.i + %tmp3.i8 = getelementptr %struct.mrViewingHitRecord, %struct.mrViewingHitRecord* %VHR, i32 0, i32 1, i32 0, i32 0 ; <double*> [#uses=1] + %tmp46 = load double, double* %tmp3.i8 ; <double> [#uses=0] + ret i32 1 + +return: ; preds = %cond_next.i, %entry + ret i32 0 +} diff --git a/llvm/test/Transforms/NewGVN/2007-07-26-InterlockingLoops.ll b/llvm/test/Transforms/NewGVN/2007-07-26-InterlockingLoops.ll new file mode 100644 index 00000000000..1eb90ad2a1f --- /dev/null +++ b/llvm/test/Transforms/NewGVN/2007-07-26-InterlockingLoops.ll @@ -0,0 +1,40 @@ +; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s + +@last = external global [65 x i32*] + +define i32 @NextRootMove(i32 %wtm, i32 %x, i32 %y, i32 %z) { +entry: + %A = alloca i32* + %tmp17618 = load i32*, i32** getelementptr ([65 x i32*], [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 + br label %cond_true116 + +cond_true116: + %cmp = icmp eq i32 %x, %y + br i1 %cmp, label %cond_true128, label %cond_true145 + +cond_true128: + %tmp17625 = load i32*, i32** getelementptr ([65 x i32*], [65 x i32*]* @last, i32 0, i32 1), align 4 + store i32* %tmp17625, i32** %A + %cmp1 = icmp eq i32 %x, %z + br i1 %cmp1 , label %bb98.backedge, label %return.loopexit + +bb98.backedge: + br label %cond_true116 + +cond_true145: + %tmp17631 = load i32*, i32** getelementptr ([65 x i32*], [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: + br label %return + +return: + ret i32 0 +} diff --git a/llvm/test/Transforms/NewGVN/2007-07-26-NonRedundant.ll b/llvm/test/Transforms/NewGVN/2007-07-26-NonRedundant.ll new file mode 100644 index 00000000000..344af2c2abb --- /dev/null +++ b/llvm/test/Transforms/NewGVN/2007-07-26-NonRedundant.ll @@ -0,0 +1,16 @@ +; RUN: opt < %s -newgvn | llvm-dis + +@bsLive = external global i32 ; <i32*> [#uses=2] + +define i32 @bsR(i32 %n) { +entry: + br i1 false, label %cond_next, label %bb19 + +cond_next: ; preds = %entry + store i32 0, i32* @bsLive, align 4 + br label %bb19 + +bb19: ; preds = %cond_next, %entry + %tmp29 = load i32, i32* @bsLive, align 4 ; <i32> [#uses=0] + ret i32 0 +} diff --git a/llvm/test/Transforms/NewGVN/2007-07-26-PhiErasure.ll b/llvm/test/Transforms/NewGVN/2007-07-26-PhiErasure.ll new file mode 100644 index 00000000000..402de50c72c --- /dev/null +++ b/llvm/test/Transforms/NewGVN/2007-07-26-PhiErasure.ll @@ -0,0 +1,45 @@ +; XFAIL: * +; RUN: opt < %s -newgvn -S | FileCheck %s + + %struct..0anon = type { i32 } + %struct.FILE = type { i8*, i32, i32, i16, i16, %struct.__sbuf, i32, i8*, i32 (i8*)*, i32 (i8*, i8*, i32)*, i64 (i8*, i64, i32)*, i32 (i8*, i8*, i32)*, %struct.__sbuf, %struct.__sFILEX*, i32, [3 x i8], [1 x i8], %struct.__sbuf, i32, i64 } + %struct.__sFILEX = type opaque + %struct.__sbuf = type { i8*, i32 } + %struct.rtx_def = type { i16, i8, i8, [1 x %struct..0anon] } +@n_spills = external global i32 ; <i32*> [#uses=2] + +define i32 @reload(%struct.rtx_def* %first, i32 %global, %struct.FILE* %dumpfile) { +cond_next2835.1: ; preds = %cond_next2861 + %tmp2922 = load i32, i32* @n_spills, align 4 ; <i32> [#uses=0] + br label %bb2928 + +bb2928: ; preds = %cond_next2835.1, %cond_next2943 + br i1 false, label %cond_next2943, label %cond_true2935 + +cond_true2935: ; preds = %bb2928 + br label %cond_next2943 + +cond_next2943: ; preds = %cond_true2935, %bb2928 + br i1 false, label %bb2982.preheader, label %bb2928 + +bb2982.preheader: ; preds = %cond_next2943 + %tmp298316 = load i32, i32* @n_spills, align 4 ; <i32> [#uses=0] + ret i32 %tmp298316 + +} + +; CHECK: define i32 @reload(%struct.rtx_def* %first, i32 %global, %struct.FILE* %dumpfile) { +; CHECK-NEXT: cond_next2835.1: +; CHECK-NEXT: br label %bb2928 +; CHECK: bb2928: +; CHECK-NEXT: br i1 false, label %bb2928.cond_next2943_crit_edge, label %cond_true2935 +; CHECK: bb2928.cond_next2943_crit_edge: +; CHECK-NEXT: br label %cond_next2943 +; CHECK: cond_true2935: +; CHECK-NEXT: br label %cond_next2943 +; CHECK: cond_next2943: +; CHECK-NEXT: br i1 false, label %bb2982.preheader, label %bb2928 +; CHECK: bb2982.preheader: +; CHECK-NEXT: %tmp298316 = load i32, i32* @n_spills, align 4 +; CHECK-NEXT: ret i32 %tmp298316 +; CHECK-NEXT: } diff --git a/llvm/test/Transforms/NewGVN/2007-07-30-PredIDom.ll b/llvm/test/Transforms/NewGVN/2007-07-30-PredIDom.ll new file mode 100644 index 00000000000..ddb1e9a674c --- /dev/null +++ b/llvm/test/Transforms/NewGVN/2007-07-30-PredIDom.ll @@ -0,0 +1,274 @@ +; RUN: opt < %s -newgvn | llvm-dis + + %"struct.Block::$_16" = type { i32 } + %struct.Exp = type { %struct.Exp_*, i32, i32, i32, %struct.Exp*, %struct.Exp*, %"struct.Exp::$_10", %"struct.Block::$_16", %"struct.Exp::$_12" } + %"struct.Exp::$_10" = type { %struct.Exp* } + %"struct.Exp::$_12" = type { %struct.Exp** } + %struct.Exp_ = type { i32, i32, i32, i32, %struct.Id* } + %struct.Id = type { i8*, i32, i32, i32, %"struct.Id::$_13" } + %"struct.Id::$_13" = type { double } + +define i8* @_ZN3Exp8toStringEj(%struct.Exp* %this, i32 %nextpc) { +entry: + switch i32 0, label %bb970 [ + i32 1, label %bb + i32 2, label %bb39 + i32 3, label %bb195 + i32 4, label %bb270 + i32 5, label %bb418 + i32 6, label %bb633 + i32 7, label %bb810 + i32 8, label %bb882 + i32 9, label %bb925 + ] + +bb: ; preds = %entry + store i8* null, i8** null + br label %return + +bb39: ; preds = %entry + br i1 false, label %cond_true, label %cond_false132 + +cond_true: ; preds = %bb39 + br i1 false, label %cond_true73, label %cond_false + +cond_true73: ; preds = %cond_true + br i1 false, label %cond_true108, label %cond_next + +cond_true108: ; preds = %cond_true73 + br label %cond_next + +cond_next: ; preds = %cond_true108, %cond_true73 + br label %cond_next131 + +cond_false: ; preds = %cond_true + br label %cond_next131 + +cond_next131: ; preds = %cond_false, %cond_next + br label %cond_next141 + +cond_false132: ; preds = %bb39 + br label %cond_next141 + +cond_next141: ; preds = %cond_false132, %cond_next131 + br i1 false, label %cond_true169, label %cond_false175 + +cond_true169: ; preds = %cond_next141 + br label %cond_next181 + +cond_false175: ; preds = %cond_next141 + br label %cond_next181 + +cond_next181: ; preds = %cond_false175, %cond_true169 + br i1 false, label %cond_true189, label %cond_next191 + +cond_true189: ; preds = %cond_next181 + br label %cond_next191 + +cond_next191: ; preds = %cond_true189, %cond_next181 + store i8* null, i8** null + br label %return + +bb195: ; preds = %entry + br i1 false, label %cond_true248, label %cond_false250 + +cond_true248: ; preds = %bb195 + br label %cond_next252 + +cond_false250: ; preds = %bb195 + br label %cond_next252 + +cond_next252: ; preds = %cond_false250, %cond_true248 + br i1 false, label %cond_true265, label %cond_next267 + +cond_true265: ; preds = %cond_next252 + br label %cond_next267 + +cond_next267: ; preds = %cond_true265, %cond_next252 + store i8* null, i8** null + br label %return + +bb270: ; preds = %entry + br i1 false, label %cond_true338, label %cond_false340 + +cond_true338: ; preds = %bb270 + br label %cond_next342 + +cond_false340: ; preds = %bb270 + br label %cond_next342 + +cond_next342: ; preds = %cond_false340, %cond_true338 + br i1 false, label %cond_true362, label %cond_false364 + +cond_true362: ; preds = %cond_next342 + br label %cond_next366 + +cond_false364: ; preds = %cond_next342 + br label %cond_next366 + +cond_next366: ; preds = %cond_false364, %cond_true362 + br i1 false, label %cond_true393, label %cond_next395 + +cond_true393: ; preds = %cond_next366 + br label %cond_next395 + +cond_next395: ; preds = %cond_true393, %cond_next366 + br i1 false, label %cond_true406, label %cond_next408 + +cond_true406: ; preds = %cond_next395 + br label %cond_next408 + +cond_next408: ; preds = %cond_true406, %cond_next395 + br i1 false, label %cond_true413, label %cond_next415 + +cond_true413: ; preds = %cond_next408 + br label %cond_next415 + +cond_next415: ; preds = %cond_true413, %cond_next408 + store i8* null, i8** null + br label %return + +bb418: ; preds = %entry + br i1 false, label %cond_true512, label %cond_false514 + +cond_true512: ; preds = %bb418 + br label %cond_next516 + +cond_false514: ; preds = %bb418 + br label %cond_next516 + +cond_next516: ; preds = %cond_false514, %cond_true512 + br i1 false, label %cond_true536, label %cond_false538 + +cond_true536: ; preds = %cond_next516 + br label %cond_next540 + +cond_false538: ; preds = %cond_next516 + br label %cond_next540 + +cond_next540: ; preds = %cond_false538, %cond_true536 + br i1 false, label %cond_true560, label %cond_false562 + +cond_true560: ; preds = %cond_next540 + br label %cond_next564 + +cond_false562: ; preds = %cond_next540 + br label %cond_next564 + +cond_next564: ; preds = %cond_false562, %cond_true560 + br i1 false, label %cond_true597, label %cond_next599 + +cond_true597: ; preds = %cond_next564 + br label %cond_next599 + +cond_next599: ; preds = %cond_true597, %cond_next564 + br i1 false, label %cond_true614, label %cond_next616 + +cond_true614: ; preds = %cond_next599 + br label %cond_next616 + +cond_next616: ; preds = %cond_true614, %cond_next599 + br i1 false, label %cond_true621, label %cond_next623 + +cond_true621: ; preds = %cond_next616 + br label %cond_next623 + +cond_next623: ; preds = %cond_true621, %cond_next616 + br i1 false, label %cond_true628, label %cond_next630 + +cond_true628: ; preds = %cond_next623 + br label %cond_next630 + +cond_next630: ; preds = %cond_true628, %cond_next623 + store i8* null, i8** null + br label %return + +bb633: ; preds = %entry + br i1 false, label %cond_true667, label %cond_next669 + +cond_true667: ; preds = %bb633 + br label %cond_next669 + +cond_next669: ; preds = %cond_true667, %bb633 + br i1 false, label %cond_true678, label %cond_next791 + +cond_true678: ; preds = %cond_next669 + br label %bb735 + +bb679: ; preds = %bb735 + br i1 false, label %cond_true729, label %cond_next731 + +cond_true729: ; preds = %bb679 + br label %cond_next731 + +cond_next731: ; preds = %cond_true729, %bb679 + br label %bb735 + +bb735: ; preds = %cond_next731, %cond_true678 + br i1 false, label %bb679, label %bb743 + +bb743: ; preds = %bb735 + br i1 false, label %cond_true788, label %cond_next790 + +cond_true788: ; preds = %bb743 + br label %cond_next790 + +cond_next790: ; preds = %cond_true788, %bb743 + br label %cond_next791 + +cond_next791: ; preds = %cond_next790, %cond_next669 + br i1 false, label %cond_true805, label %cond_next807 + +cond_true805: ; preds = %cond_next791 + br label %cond_next807 + +cond_next807: ; preds = %cond_true805, %cond_next791 + store i8* null, i8** null + br label %return + +bb810: ; preds = %entry + br i1 false, label %cond_true870, label %cond_next872 + +cond_true870: ; preds = %bb810 + br label %cond_next872 + +cond_next872: ; preds = %cond_true870, %bb810 + br i1 false, label %cond_true877, label %cond_next879 + +cond_true877: ; preds = %cond_next872 + br label %cond_next879 + +cond_next879: ; preds = %cond_true877, %cond_next872 + store i8* null, i8** null + br label %return + +bb882: ; preds = %entry + br i1 false, label %cond_true920, label %cond_next922 + +cond_true920: ; preds = %bb882 + br label %cond_next922 + +cond_next922: ; preds = %cond_true920, %bb882 + store i8* null, i8** null + br label %return + +bb925: ; preds = %entry + br i1 false, label %cond_true965, label %cond_next967 + +cond_true965: ; preds = %bb925 + br label %cond_next967 + +cond_next967: ; preds = %cond_true965, %bb925 + store i8* null, i8** null + br label %return + +bb970: ; preds = %entry + unreachable + ; No predecessors! + store i8* null, i8** null + br label %return + +return: ; preds = %0, %cond_next967, %cond_next922, %cond_next879, %cond_next807, %cond_next630, %cond_next415, %cond_next267, %cond_next191, %bb + %retval980 = load i8*, i8** null ; <i8*> [#uses=1] + ret i8* %retval980 +} diff --git a/llvm/test/Transforms/NewGVN/2007-07-31-NoDomInherit.ll b/llvm/test/Transforms/NewGVN/2007-07-31-NoDomInherit.ll new file mode 100644 index 00000000000..0fd7588b8ad --- /dev/null +++ b/llvm/test/Transforms/NewGVN/2007-07-31-NoDomInherit.ll @@ -0,0 +1,315 @@ +; XFAIL: * +; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s + + %struct.anon = type { i32 (i32, i32, i32)*, i32, i32, [3 x i32], i8*, i8*, i8* } +@debug = external constant i32 ; <i32*> [#uses=0] +@counters = external constant i32 ; <i32*> [#uses=1] +@trialx = external global [17 x i32] ; <[17 x i32]*> [#uses=1] +@dummy1 = external global [7 x i32] ; <[7 x i32]*> [#uses=0] +@dummy2 = external global [4 x i32] ; <[4 x i32]*> [#uses=0] +@unacceptable = external global i32 ; <i32*> [#uses=0] +@isa = external global [13 x %struct.anon] ; <[13 x %struct.anon]*> [#uses=3] +@.str = external constant [4 x i8] ; <[4 x i8]*> [#uses=0] +@.str1 = external constant [3 x i8] ; <[3 x i8]*> [#uses=0] +@.str2 = external constant [1 x i8] ; <[1 x i8]*> [#uses=0] +@.str3 = external constant [4 x i8] ; <[4 x i8]*> [#uses=0] +@.str4 = external constant [3 x i8] ; <[3 x i8]*> [#uses=0] +@.str5 = external constant [4 x i8] ; <[4 x i8]*> [#uses=0] +@.str6 = external constant [2 x i8] ; <[2 x i8]*> [#uses=0] +@.str7 = external constant [4 x i8] ; <[4 x i8]*> [#uses=0] +@.str8 = external constant [4 x i8] ; <[4 x i8]*> [#uses=0] +@.str9 = external constant [4 x i8] ; <[4 x i8]*> [#uses=0] +@.str10 = external constant [4 x i8] ; <[4 x i8]*> [#uses=0] +@.str11 = external constant [2 x i8] ; <[2 x i8]*> [#uses=0] +@.str12 = external constant [4 x i8] ; <[4 x i8]*> [#uses=0] +@.str13 = external constant [2 x i8] ; <[2 x i8]*> [#uses=0] +@.str14 = external constant [5 x i8] ; <[5 x i8]*> [#uses=0] +@.str15 = external constant [5 x i8] ; <[5 x i8]*> [#uses=0] +@.str16 = external constant [4 x i8] ; <[4 x i8]*> [#uses=0] +@.str17 = external constant [4 x i8] ; <[4 x i8]*> [#uses=0] +@.str18 = external constant [3 x i8] ; <[3 x i8]*> [#uses=0] +@.str19 = external constant [4 x i8] ; <[4 x i8]*> [#uses=0] +@.str20 = external constant [4 x i8] ; <[4 x i8]*> [#uses=0] +@.str21 = external constant [4 x i8] ; <[4 x i8]*> [#uses=0] +@.str22 = external constant [4 x i8] ; <[4 x i8]*> [#uses=0] +@.str23 = external constant [5 x i8] ; <[5 x i8]*> [#uses=0] +@.str24 = external constant [4 x i8] ; <[4 x i8]*> [#uses=0] +@.str25 = external constant [6 x i8] ; <[6 x i8]*> [#uses=0] +@.str26 = external constant [5 x i8] ; <[5 x i8]*> [#uses=0] +@.str27 = external constant [6 x i8] ; <[6 x i8]*> [#uses=0] +@r = external global [17 x i32] ; <[17 x i32]*> [#uses=0] +@.str28 = external constant [3 x i8] ; <[3 x i8]*> [#uses=0] +@.str29 = external constant [5 x i8] ; <[5 x i8]*> [#uses=0] +@pgm = external global [5 x { i32, [3 x i32] }] ; <[5 x { i32, [3 x i32] }]*> [#uses=4] +@.str30 = external constant [3 x i8] ; <[3 x i8]*> [#uses=0] +@.str31 = external constant [13 x i8] ; <[13 x i8]*> [#uses=0] +@.str32 = external constant [3 x i8] ; <[3 x i8]*> [#uses=0] +@.str33 = external constant [4 x i8] ; <[4 x i8]*> [#uses=0] +@.str34 = external constant [20 x i8] ; <[20 x i8]*> [#uses=0] +@numi = external global i32 ; <i32*> [#uses=7] +@.str35 = external constant [10 x i8] ; <[10 x i8]*> [#uses=0] +@counter = external global [5 x i32] ; <[5 x i32]*> [#uses=2] +@itrialx.2510 = external global i32 ; <i32*> [#uses=0] +@.str36 = external constant [43 x i8] ; <[43 x i8]*> [#uses=0] +@.str37 = external constant [42 x i8] ; <[42 x i8]*> [#uses=0] +@corr_result = external global i32 ; <i32*> [#uses=0] +@.str38 = external constant [3 x i8] ; <[3 x i8]*> [#uses=0] +@.str39 = external constant [5 x i8] ; <[5 x i8]*> [#uses=0] +@.str40 = external constant [47 x i8] ; <[47 x i8]*> [#uses=0] +@correct_result = external global [17 x i32] ; <[17 x i32]*> [#uses=1] +@.str41 = external constant [46 x i8] ; <[46 x i8]*> [#uses=0] +@.str42 = external constant [32 x i8] ; <[32 x i8]*> [#uses=0] +@.str43 = external constant [44 x i8] ; <[44 x i8]*> [#uses=1] +@.str44 = external constant [21 x i8] ; <[21 x i8]*> [#uses=1] +@.str45 = external constant [12 x i8] ; <[12 x i8]*> [#uses=1] +@.str46 = external constant [5 x i8] ; <[5 x i8]*> [#uses=1] +@.str47 = external constant [12 x i8] ; <[12 x i8]*> [#uses=1] + +declare i32 @neg(i32, i32, i32) + +declare i32 @Not(i32, i32, i32) + +declare i32 @pop(i32, i32, i32) + +declare i32 @nlz(i32, i32, i32) + +declare i32 @rev(i32, i32, i32) + +declare i32 @add(i32, i32, i32) + +declare i32 @sub(i32, i32, i32) + +declare i32 @mul(i32, i32, i32) + +declare i32 @divide(i32, i32, i32) + +declare i32 @divu(i32, i32, i32) + +declare i32 @And(i32, i32, i32) + +declare i32 @Or(i32, i32, i32) + +declare i32 @Xor(i32, i32, i32) + +declare i32 @rotl(i32, i32, i32) + +declare i32 @shl(i32, i32, i32) + +declare i32 @shr(i32, i32, i32) + +declare i32 @shrs(i32, i32, i32) + +declare i32 @cmpeq(i32, i32, i32) + +declare i32 @cmplt(i32, i32, i32) + +declare i32 @cmpltu(i32, i32, i32) + +declare i32 @seleq(i32, i32, i32) + +declare i32 @sellt(i32, i32, i32) + +declare i32 @selle(i32, i32, i32) + +declare void @print_expr(i32) + +declare i32 @printf(i8*, ...) + +declare i32 @putchar(i32) + +declare void @print_pgm() + +declare void @simulate_one_instruction(i32) + +declare i32 @check(i32) + +declare i32 @puts(i8*) + +declare void @fix_operands(i32) + +declare void @abort() + +declare i32 @increment() + +declare i32 @search() + +define i32 @main(i32 %argc, i8** %argv) { +entry: + %argc_addr = alloca i32 ; <i32*> [#uses=1] + %argv_addr = alloca i8** ; <i8***> [#uses=1] + %retval = alloca i32, align 4 ; <i32*> [#uses=2] + %tmp = alloca i32, align 4 ; <i32*> [#uses=2] + %i = alloca i32, align 4 ; <i32*> [#uses=21] + %num_sol = alloca i32, align 4 ; <i32*> [#uses=4] + %total = alloca i32, align 4 ; <i32*> [#uses=4] + %"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0] + store i32 %argc, i32* %argc_addr + store i8** %argv, i8*** %argv_addr + store i32 0, i32* %num_sol + store i32 1, i32* @numi + br label %bb91 + +bb: ; preds = %cond_next97 + %tmp1 = load i32, i32* @numi ; <i32> [#uses=1] + %tmp2 = getelementptr [44 x i8], [44 x i8]* @.str43, i32 0, i32 0 ; <i8*> [#uses=1] + %tmp3 = call i32 (i8*, ...) @printf( i8* %tmp2, i32 %tmp1 ) ; <i32> [#uses=0] + store i32 0, i32* %i + br label %bb13 + +bb4: ; preds = %bb13 + %tmp5 = load i32, i32* %i ; <i32> [#uses=1] + %tmp6 = load i32, i32* %i ; <i32> [#uses=1] + %tmp7 = getelementptr [17 x i32], [17 x i32]* @trialx, i32 0, i32 %tmp6 ; <i32*> [#uses=1] + %tmp8 = load i32, i32* %tmp7 ; <i32> [#uses=1] + %tmp9 = call i32 @userfun( i32 %tmp8 ) ; <i32> [#uses=1] + %tmp10 = getelementptr [17 x i32], [17 x i32]* @correct_result, i32 0, i32 %tmp5 ; <i32*> [#uses=1] + store i32 %tmp9, i32* %tmp10 + %tmp11 = load i32, i32* %i ; <i32> [#uses=1] + %tmp12 = add i32 %tmp11, 1 ; <i32> [#uses=1] + store i32 %tmp12, i32* %i + br label %bb13 + +bb13: ; preds = %bb4, %bb + %tmp14 = load i32, i32* %i ; <i32> [#uses=1] + %tmp15 = icmp sle i32 %tmp14, 16 ; <i1> [#uses=1] + %tmp1516 = zext i1 %tmp15 to i32 ; <i32> [#uses=1] + %toBool = icmp ne i32 %tmp1516, 0 ; <i1> [#uses=1] + br i1 %toBool, label %bb4, label %bb17 + +bb17: ; preds = %bb13 + store i32 0, i32* %i + br label %bb49 + +bb18: ; preds = %bb49 + %tmp19 = load i32, i32* %i ; <i32> [#uses=1] + %tmp20 = getelementptr [5 x { i32, [3 x i32] }], [5 x { i32, [3 x i32] }]* @pgm, i32 0, i32 %tmp19 ; <{ i32, [3 x i32] }*> [#uses=1] + %tmp21 = getelementptr { i32, [3 x i32] }, { i32, [3 x i32] }* %tmp20, i32 0, i32 0 ; <i32*> [#uses=1] + store i32 0, i32* %tmp21 + %tmp22 = load i32, i32* %i ; <i32> [#uses=1] + %tmp23 = getelementptr [13 x %struct.anon], [13 x %struct.anon]* @isa, i32 0, i32 0 ; <%struct.anon*> [#uses=1] + %tmp24 = getelementptr %struct.anon, %struct.anon* %tmp23, i32 0, i32 3 ; <[3 x i32]*> [#uses=1] + %tmp25 = getelementptr [3 x i32], [3 x i32]* %tmp24, i32 0, i32 0 ; <i32*> [#uses=1] + %tmp26 = load i32, i32* %tmp25 ; <i32> [#uses=1] + %tmp27 = getelementptr [5 x { i32, [3 x i32] }], [5 x { i32, [3 x i32] }]* @pgm, i32 0, i32 %tmp22 ; <{ i32, [3 x i32] }*> [#uses=1] + %tmp28 = getelementptr { i32, [3 x i32] }, { i32, [3 x i32] }* %tmp27, i32 0, i32 1 ; <[3 x i32]*> [#uses=1] + %tmp29 = getelementptr [3 x i32], [3 x i32]* %tmp28, i32 0, i32 0 ; <i32*> [#uses=1] + store i32 %tmp26, i32* %tmp29 + %tmp30 = load i32, i32* %i ; <i32> [#uses=1] + %tmp31 = getelementptr [13 x %struct.anon], [13 x %struct.anon]* @isa, i32 0, i32 0 ; <%struct.anon*> [#uses=1] + %tmp32 = getelementptr %struct.anon, %struct.anon* %tmp31, i32 0, i32 3 ; <[3 x i32]*> [#uses=1] + %tmp33 = getelementptr [3 x i32], [3 x i32]* %tmp32, i32 0, i32 1 ; <i32*> [#uses=1] + %tmp34 = load i32, i32* %tmp33 ; <i32> [#uses=1] + %tmp35 = getelementptr [5 x { i32, [3 x i32] }], [5 x { i32, [3 x i32] }]* @pgm, i32 0, i32 %tmp30 ; <{ i32, [3 x i32] }*> [#uses=1] + %tmp36 = getelementptr { i32, [3 x i32] }, { i32, [3 x i32] }* %tmp35, i32 0, i32 1 ; <[3 x i32]*> [#uses=1] + %tmp37 = getelementptr [3 x i32], [3 x i32]* %tmp36, i32 0, i32 1 ; <i32*> [#uses=1] + store i32 %tmp34, i32* %tmp37 + %tmp38 = load i32, i32* %i ; <i32> [#uses=1] + %tmp39 = getelementptr [13 x %struct.anon], [13 x %struct.anon]* @isa, i32 0, i32 0 ; <%struct.anon*> [#uses=1] + %tmp40 = getelementptr %struct.anon, %struct.anon* %tmp39, i32 0, i32 3 ; <[3 x i32]*> [#uses=1] + %tmp41 = getelementptr [3 x i32], [3 x i32]* %tmp40, i32 0, i32 2 ; <i32*> [#uses=1] + %tmp42 = load i32, i32* %tmp41 ; <i32> [#uses=1] + %tmp43 = getelementptr [5 x { i32, [3 x i32] }], [5 x { i32, [3 x i32] }]* @pgm, i32 0, i32 %tmp38 ; <{ i32, [3 x i32] }*> [#uses=1] + %tmp44 = getelementptr { i32, [3 x i32] }, { i32, [3 x i32] }* %tmp43, i32 0, i32 1 ; <[3 x i32]*> [#uses=1] + %tmp45 = getelementptr [3 x i32], [3 x i32]* %tmp44, i32 0, i32 2 ; <i32*> [#uses=1] + store i32 %tmp42, i32* %tmp45 + %tmp46 = load i32, i32* %i ; <i32> [#uses=1] + call void @fix_operands( i32 %tmp46 ) + %tmp47 = load i32, i32* %i ; <i32> [#uses=1] +; CHECK: %tmp47 = phi i32 [ %tmp48, %bb18 ], [ 0, %bb17 ] + %tmp48 = add i32 %tmp47, 1 ; <i32> [#uses=1] + store i32 %tmp48, i32* %i + br label %bb49 + +bb49: ; preds = %bb18, %bb17 + %tmp50 = load i32, i32* @numi ; <i32> [#uses=1] + %tmp51 = load i32, i32* %i ; <i32> [#uses=1] + %tmp52 = icmp slt i32 %tmp51, %tmp50 ; <i1> [#uses=1] + %tmp5253 = zext i1 %tmp52 to i32 ; <i32> [#uses=1] + %toBool54 = icmp ne i32 %tmp5253, 0 ; <i1> [#uses=1] + br i1 %toBool54, label %bb18, label %bb55 + +bb55: ; preds = %bb49 + %tmp56 = call i32 @search( ) ; <i32> [#uses=1] + store i32 %tmp56, i32* %num_sol + %tmp57 = getelementptr [21 x i8], [21 x i8]* @.str44, i32 0, i32 0 ; <i8*> [#uses=1] + %tmp58 = load i32, i32* %num_sol ; <i32> [#uses=1] + %tmp59 = call i32 (i8*, ...) @printf( i8* %tmp57, i32 %tmp58 ) ; <i32> [#uses=0] + %tmp60 = load i32, i32* @counters ; <i32> [#uses=1] + %tmp61 = icmp ne i32 %tmp60, 0 ; <i1> [#uses=1] + %tmp6162 = zext i1 %tmp61 to i32 ; <i32> [#uses=1] + %toBool63 = icmp ne i32 %tmp6162, 0 ; <i1> [#uses=1] + br i1 %toBool63, label %cond_true, label %cond_next + +cond_true: ; preds = %bb55 + store i32 0, i32* %total + %tmp64 = getelementptr [12 x i8], [12 x i8]* @.str45, i32 0, i32 0 ; <i8*> [#uses=1] + %tmp65 = call i32 (i8*, ...) @printf( i8* %tmp64 ) ; <i32> [#uses=0] + store i32 0, i32* %i + br label %bb79 + +bb66: ; preds = %bb79 + %tmp67 = load i32, i32* %i ; <i32> [#uses=1] + %tmp68 = getelementptr [5 x i32], [5 x i32]* @counter, i32 0, i32 %tmp67 ; <i32*> [#uses=1] + %tmp69 = load i32, i32* %tmp68 ; <i32> [#uses=1] + %tmp70 = getelementptr [5 x i8], [5 x i8]* @.str46, i32 0, i32 0 ; <i8*> [#uses=1] + %tmp71 = call i32 (i8*, ...) @printf( i8* %tmp70, i32 %tmp69 ) ; <i32> [#uses=0] + %tmp72 = load i32, i32* %i ; <i32> [#uses=1] + %tmp73 = getelementptr [5 x i32], [5 x i32]* @counter, i32 0, i32 %tmp72 ; <i32*> [#uses=1] + %tmp74 = load i32, i32* %tmp73 ; <i32> [#uses=1] + %tmp75 = load i32, i32* %total ; <i32> [#uses=1] + %tmp76 = add i32 %tmp74, %tmp75 ; <i32> [#uses=1] + store i32 %tmp76, i32* %total + %tmp77 = load i32, i32* %i ; <i32> [#uses=1] + %tmp78 = add i32 %tmp77, 1 ; <i32> [#uses=1] + store i32 %tmp78, i32* %i + br label %bb79 + +bb79: ; preds = %bb66, %cond_true + %tmp80 = load i32, i32* @numi ; <i32> [#uses=1] + %tmp81 = load i32, i32* %i ; <i32> [#uses=1] + %tmp82 = icmp slt i32 %tmp81, %tmp80 ; <i1> [#uses=1] + %tmp8283 = zext i1 %tmp82 to i32 ; <i32> [#uses=1] + %toBool84 = icmp ne i32 %tmp8283, 0 ; <i1> [#uses=1] + br i1 %toBool84, label %bb66, label %bb85 + +bb85: ; preds = %bb79 + %tmp86 = getelementptr [12 x i8], [12 x i8]* @.str47, i32 0, i32 0 ; <i8*> [#uses=1] + %tmp87 = load i32, i32* %total ; <i32> [#uses=1] + %tmp88 = call i32 (i8*, ...) @printf( i8* %tmp86, i32 %tmp87 ) ; <i32> [#uses=0] + br label %cond_next + +cond_next: ; preds = %bb85, %bb55 + %tmp89 = load i32, i32* @numi ; <i32> [#uses=1] + %tmp90 = add i32 %tmp89, 1 ; <i32> [#uses=1] + store i32 %tmp90, i32* @numi + br label %bb91 + +bb91: ; preds = %cond_next, %entry + %tmp92 = load i32, i32* @numi ; <i32> [#uses=1] + %tmp93 = icmp sgt i32 %tmp92, 5 ; <i1> [#uses=1] + %tmp9394 = zext i1 %tmp93 to i32 ; <i32> [#uses=1] + %toBool95 = icmp ne i32 %tmp9394, 0 ; <i1> [#uses=1] + br i1 %toBool95, label %cond_true96, label %cond_next97 + +cond_true96: ; preds = %bb91 + br label %bb102 + +cond_next97: ; preds = %bb91 + %tmp98 = load i32, i32* %num_sol ; <i32> [#uses=1] + %tmp99 = icmp eq i32 %tmp98, 0 ; <i1> [#uses=1] + %tmp99100 = zext i1 %tmp99 to i32 ; <i32> [#uses=1] + %toBool101 = icmp ne i32 %tmp99100, 0 ; <i1> [#uses=1] + br i1 %toBool101, label %bb, label %bb102 + +bb102: ; preds = %cond_next97, %cond_true96 + store i32 0, i32* %tmp + %tmp103 = load i32, i32* %tmp ; <i32> [#uses=1] + store i32 %tmp103, i32* %retval + br label %return + +return: ; preds = %bb102 + %retval104 = load i32, i32* %retval ; <i32> [#uses=1] + ret i32 %retval104 +} + +declare i32 @userfun(i32) diff --git a/llvm/test/Transforms/NewGVN/2007-07-31-RedundantPhi.ll b/llvm/test/Transforms/NewGVN/2007-07-31-RedundantPhi.ll new file mode 100644 index 00000000000..3b59bad1824 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/2007-07-31-RedundantPhi.ll @@ -0,0 +1,23 @@ +; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s + +@img_width = external global i16 ; <i16*> [#uses=2] + +define i32 @smpUMHEXBipredIntegerPelBlockMotionSearch(i16* %cur_pic, i16 signext %ref, i32 %list, i32 %pic_pix_x, i32 %pic_pix_y, i32 %blocktype, i16 signext %pred_mv_x1, i16 signext %pred_mv_y1, i16 signext %pred_mv_x2, i16 signext %pred_mv_y2, i16* %mv_x, i16* %mv_y, i16* %s_mv_x, i16* %s_mv_y, i32 %search_range, i32 %min_mcost, i32 %lambda_factor) { +cond_next143: ; preds = %entry + store i16 0, i16* @img_width, align 2 + br i1 false, label %cond_next449, label %cond_false434 + +cond_false434: ; preds = %cond_true415 + br label %cond_next449 + +cond_next449: ; preds = %cond_false434, %cond_true415 + br i1 false, label %cond_next698, label %cond_false470 + +cond_false470: ; preds = %cond_next449 + br label %cond_next698 + +cond_next698: ; preds = %cond_true492 + %tmp701 = load i16, i16* @img_width, align 2 ; <i16> [#uses=0] +; CHECK-NOT: %tmp701 = + ret i32 0 +} diff --git a/llvm/test/Transforms/NewGVN/2008-02-12-UndefLoad.ll b/llvm/test/Transforms/NewGVN/2008-02-12-UndefLoad.ll new file mode 100644 index 00000000000..ee30cfc6b87 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/2008-02-12-UndefLoad.ll @@ -0,0 +1,22 @@ +; XFAIL: * +; RUN: opt < %s -newgvn -S | FileCheck %s +; PR1996 + +%struct.anon = type { i32, i8, i8, i8, i8 } + +define i32 @a() { +entry: + %c = alloca %struct.anon ; <%struct.anon*> [#uses=2] + %tmp = getelementptr %struct.anon, %struct.anon* %c, i32 0, i32 0 ; <i32*> [#uses=1] + %tmp1 = getelementptr i32, i32* %tmp, i32 1 ; <i32*> [#uses=2] + %tmp2 = load i32, i32* %tmp1, align 4 ; <i32> [#uses=1] +; CHECK-NOT: load + %tmp3 = or i32 %tmp2, 11 ; <i32> [#uses=1] + %tmp4 = and i32 %tmp3, -21 ; <i32> [#uses=1] + store i32 %tmp4, i32* %tmp1, align 4 + %call = call i32 (...) @x( %struct.anon* %c ) ; <i32> [#uses=0] + ret i32 undef +} + + +declare i32 @x(...) diff --git a/llvm/test/Transforms/NewGVN/2008-02-13-NewPHI.ll b/llvm/test/Transforms/NewGVN/2008-02-13-NewPHI.ll new file mode 100644 index 00000000000..5d6038230f5 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/2008-02-13-NewPHI.ll @@ -0,0 +1,22 @@ +; RUN: opt < %s -newgvn +; PR2032 + +define i32 @sscal(i32 %n, double %sa1, float* %sx, i32 %incx) { +entry: + %sx_addr = alloca float* ; <float**> [#uses=3] + store float* %sx, float** %sx_addr, align 4 + br label %bb33 + +bb: ; preds = %bb33 + %tmp27 = load float*, float** %sx_addr, align 4 ; <float*> [#uses=1] + store float 0.000000e+00, float* %tmp27, align 4 + store float* null, float** %sx_addr, align 4 + br label %bb33 + +bb33: ; preds = %bb, %entry + br i1 false, label %bb, label %return + +return: ; preds = %bb33 + %retval59 = load i32, i32* null, align 4 ; <i32> [#uses=1] + ret i32 %retval59 +} diff --git a/llvm/test/Transforms/NewGVN/2008-07-02-Unreachable.ll b/llvm/test/Transforms/NewGVN/2008-07-02-Unreachable.ll new file mode 100644 index 00000000000..797cf574f01 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/2008-07-02-Unreachable.ll @@ -0,0 +1,36 @@ +; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s +; PR2503 + +@g_3 = external global i8 ; <i8*> [#uses=2] + +define i8 @func_1(i32 %x, i32 %y) nounwind { +entry: + %A = alloca i8 + %cmp = icmp eq i32 %x, %y + br i1 %cmp, label %ifelse, label %ifthen + +ifthen: ; preds = %entry + br label %ifend + +ifelse: ; preds = %entry + %tmp3 = load i8, i8* @g_3 ; <i8> [#uses=0] + store i8 %tmp3, i8* %A + br label %afterfor + +forcond: ; preds = %forinc + br i1 false, label %afterfor, label %forbody + +forbody: ; preds = %forcond + br label %forinc + +forinc: ; preds = %forbody + br label %forcond + +afterfor: ; preds = %forcond, %forcond.thread + %tmp10 = load i8, i8* @g_3 ; <i8> [#uses=0] + ret i8 %tmp10 +; CHECK: ret i8 %tmp3 + +ifend: ; preds = %afterfor, %ifthen + ret i8 0 +} diff --git a/llvm/test/Transforms/NewGVN/2008-12-09-SelfRemove.ll b/llvm/test/Transforms/NewGVN/2008-12-09-SelfRemove.ll new file mode 100644 index 00000000000..c1b5cc81fb5 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/2008-12-09-SelfRemove.ll @@ -0,0 +1,38 @@ +; RUN: opt < %s -newgvn -S | FileCheck %s + +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" +target triple = "i386-apple-darwin9.5" + %struct.anon = type { i8*, i32 } + %struct.d_print_info = type { i32, i8*, i32, i32, %struct.d_print_template*, %struct.d_print_mod*, i32 } + %struct.d_print_mod = type { %struct.d_print_mod*, %struct.demangle_component*, i32, %struct.d_print_template* } + %struct.d_print_template = type { %struct.d_print_template*, %struct.demangle_component* } + %struct.demangle_component = type { i32, { %struct.anon } } + +define void @d_print_mod_list(%struct.d_print_info* %dpi, %struct.d_print_mod* %mods, i32 %suffix) nounwind { +entry: + %0 = getelementptr %struct.d_print_info, %struct.d_print_info* %dpi, i32 0, i32 1 ; <i8**> [#uses=1] + br i1 false, label %return, label %bb + +bb: ; preds = %entry + %1 = load i8*, i8** %0, align 4 ; <i8*> [#uses=0] + %2 = getelementptr %struct.d_print_info, %struct.d_print_info* %dpi, i32 0, i32 1 ; <i8**> [#uses=0] + br label %bb21 + +bb21: ; preds = %bb21, %bb + br label %bb21 + +return: ; preds = %entry + ret void +} + +; CHECK: define void @d_print_mod_list(%struct.d_print_info* %dpi, %struct.d_print_mod* %mods, i32 %suffix) #0 { +; CHECK: entry: +; CHECK: %0 = getelementptr %struct.d_print_info, %struct.d_print_info* %dpi, i32 0, i32 1 +; CHECK: br i1 false, label %return, label %bb +; CHECK: bb: +; CHECK: br label %bb21 +; CHECK: bb21: +; CHECK: br label %bb21 +; CHECK: return: +; CHECK: ret void +; CHECK: } diff --git a/llvm/test/Transforms/NewGVN/2008-12-12-RLE-Crash.ll b/llvm/test/Transforms/NewGVN/2008-12-12-RLE-Crash.ll new file mode 100644 index 00000000000..54644ada6c6 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/2008-12-12-RLE-Crash.ll @@ -0,0 +1,35 @@ +; RUN: opt < %s -newgvn | llvm-dis +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" +target triple = "i386-apple-darwin7" + +define i32 @main(i32 %argc, i8** %argv) nounwind { +entry: + br label %bb84 + +bb41: ; preds = %bb82 + %tmp = load i8, i8* %opt.0, align 1 ; <i8> [#uses=0] + %tmp1 = getelementptr i8, i8* %opt.0, i32 1 ; <i8*> [#uses=2] + switch i32 0, label %bb81 [ + i32 102, label %bb82 + i32 110, label %bb79 + i32 118, label %bb80 + ] + +bb79: ; preds = %bb41 + br label %bb82 + +bb80: ; preds = %bb41 + ret i32 0 + +bb81: ; preds = %bb41 + ret i32 1 + +bb82: ; preds = %bb84, %bb79, %bb41 + %opt.0 = phi i8* [ %tmp3, %bb84 ], [ %tmp1, %bb79 ], [ %tmp1, %bb41 ] ; <i8*> [#uses=3] + %tmp2 = load i8, i8* %opt.0, align 1 ; <i8> [#uses=0] + br i1 false, label %bb84, label %bb41 + +bb84: ; preds = %bb82, %entry + %tmp3 = getelementptr i8, i8* null, i32 1 ; <i8*> [#uses=1] + br label %bb82 +} diff --git a/llvm/test/Transforms/NewGVN/2008-12-14-rle-reanalyze.ll b/llvm/test/Transforms/NewGVN/2008-12-14-rle-reanalyze.ll new file mode 100644 index 00000000000..44cbdeee63b --- /dev/null +++ b/llvm/test/Transforms/NewGVN/2008-12-14-rle-reanalyze.ll @@ -0,0 +1,18 @@ +; RUN: opt < %s -newgvn | llvm-dis +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" +target triple = "i386-apple-darwin7" +@sort_value = external global [256 x i32], align 32 ; <[256 x i32]*> [#uses=2] + +define i32 @Quiesce(i32 %alpha, i32 %beta, i32 %wtm, i32 %ply) nounwind { +entry: + br label %bb22 + +bb22: ; preds = %bb23, %bb22, %entry + br i1 false, label %bb23, label %bb22 + +bb23: ; preds = %bb23, %bb22 + %sortv.233 = phi i32* [ getelementptr ([256 x i32], [256 x i32]* @sort_value, i32 0, i32 0), %bb22 ], [ %sortv.2, %bb23 ] ; <i32*> [#uses=1] + %0 = load i32, i32* %sortv.233, align 4 ; <i32> [#uses=0] + %sortv.2 = getelementptr [256 x i32], [256 x i32]* @sort_value, i32 0, i32 0 ; <i32*> [#uses=1] + br i1 false, label %bb23, label %bb22 +} diff --git a/llvm/test/Transforms/NewGVN/2008-12-15-CacheVisited.ll b/llvm/test/Transforms/NewGVN/2008-12-15-CacheVisited.ll new file mode 100644 index 00000000000..6a6c0d99188 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/2008-12-15-CacheVisited.ll @@ -0,0 +1,28 @@ +; RUN: opt < %s -newgvn | llvm-dis +; Cached results must be added to and verified against the visited sets. +; PR3217 + +define fastcc void @gen_field_die(i32* %decl) nounwind { +entry: + br i1 false, label %bb203, label %bb202 + +bb202: ; preds = %entry + unreachable + +bb203: ; preds = %entry + %tmp = getelementptr i32, i32* %decl, i32 1 ; <i32*> [#uses=1] + %tmp1 = load i32, i32* %tmp, align 4 ; <i32> [#uses=0] + br i1 false, label %bb207, label %bb204 + +bb204: ; preds = %bb203 + %tmp2 = getelementptr i32, i32* %decl, i32 1 ; <i32*> [#uses=1] + br label %bb208 + +bb207: ; preds = %bb203 + br label %bb208 + +bb208: ; preds = %bb207, %bb204 + %iftmp.1374.0.in = phi i32* [ null, %bb207 ], [ %tmp2, %bb204 ] ; <i32*> [#uses=1] + %iftmp.1374.0 = load i32, i32* %iftmp.1374.0.in ; <i32> [#uses=0] + unreachable +} diff --git a/llvm/test/Transforms/NewGVN/2009-01-21-SortInvalidation.ll b/llvm/test/Transforms/NewGVN/2009-01-21-SortInvalidation.ll new file mode 100644 index 00000000000..07cdd4e2578 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/2009-01-21-SortInvalidation.ll @@ -0,0 +1,55 @@ +; RUN: opt < %s -newgvn | llvm-dis +; PR3358 +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" +target triple = "x86_64-unknown-linux-gnu" + %struct.re_pattern_buffer = type { i8*, i64, i64, i64, i8*, i8*, i64, i8 } + %struct.re_registers = type { i32, i32*, i32* } + +define fastcc i32 @byte_re_match_2_internal(%struct.re_pattern_buffer* nocapture %bufp, i8* %string1, i32 %size1, i8* %string2, i32 %size2, i32 %pos, %struct.re_registers* %regs, i32 %stop) nounwind { +entry: + br label %bb159 + +succeed_label: ; preds = %bb159 + ret i32 0 + +bb159: ; preds = %bb664, %bb554, %bb159, %bb159, %bb159, %entry + %d.0 = phi i8* [ null, %entry ], [ %d.0, %bb159 ], [ %d.0, %bb554 ], [ %d.0, %bb159 ], [ %d.0, %bb159 ], [ %d.12, %bb664 ] ; <i8*> [#uses=5] + switch i32 0, label %bb661 [ + i32 0, label %bb159 + i32 1, label %succeed_label + i32 13, label %bb159 + i32 14, label %bb159 + i32 16, label %bb411 + i32 24, label %bb622 + i32 28, label %bb543 + ] + +bb411: ; preds = %bb411, %bb159 + br label %bb411 + +bb543: ; preds = %bb159 + br i1 false, label %bb549, label %bb550 + +bb549: ; preds = %bb543 + br label %bb554 + +bb550: ; preds = %bb543 + br i1 false, label %bb554, label %bb552 + +bb552: ; preds = %bb550 + %0 = load i8, i8* %d.0, align 8 ; <i8> [#uses=0] + br label %bb554 + +bb554: ; preds = %bb552, %bb550, %bb549 + br i1 false, label %bb159, label %bb661 + +bb622: ; preds = %bb622, %bb159 + br label %bb622 + +bb661: ; preds = %bb554, %bb159 + %d.12 = select i1 false, i8* null, i8* null ; <i8*> [#uses=1] + br label %bb664 + +bb664: ; preds = %bb664, %bb661 + br i1 false, label %bb159, label %bb664 +} diff --git a/llvm/test/Transforms/NewGVN/2009-01-22-SortInvalidation.ll b/llvm/test/Transforms/NewGVN/2009-01-22-SortInvalidation.ll new file mode 100644 index 00000000000..d02c5f2ed73 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/2009-01-22-SortInvalidation.ll @@ -0,0 +1,100 @@ +; RUN: opt < %s -newgvn | llvm-dis + +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" +target triple = "i386-apple-darwin7" + %struct..4sPragmaType = type { i8*, i32 } + %struct.AggInfo = type { i8, i8, i32, %struct.ExprList*, i32, %struct.AggInfo_col*, i32, i32, i32, %struct.AggInfo_func*, i32, i32 } + %struct.AggInfo_col = type { %struct.Table*, i32, i32, i32, i32, %struct.Expr* } + %struct.AggInfo_func = type { %struct.Expr*, %struct.FuncDef*, i32, i32 } + %struct.AuxData = type { i8*, void (i8*)* } + %struct.Bitvec = type { i32, i32, i32, { [125 x i32] } } + %struct.BtCursor = type { %struct.Btree*, %struct.BtShared*, %struct.BtCursor*, %struct.BtCursor*, i32 (i8*, i32, i8*, i32, i8*)*, i8*, i32, %struct.MemPage*, i32, %struct.CellInfo, i8, i8, i8*, i64, i32, i8, i32* } + %struct.BtLock = type { %struct.Btree*, i32, i8, %struct.BtLock* } + %struct.BtShared = type { %struct.Pager*, %struct.sqlite3*, %struct.BtCursor*, %struct.MemPage*, i8, i8, i8, i8, i8, i8, i8, i8, i32, i16, i16, i32, i32, i32, i32, i8, i32, i8*, void (i8*)*, %struct.sqlite3_mutex*, %struct.BusyHandler, i32, %struct.BtShared*, %struct.BtLock*, %struct.Btree* } + %struct.Btree = type { %struct.sqlite3*, %struct.BtShared*, i8, i8, i8, i32, %struct.Btree*, %struct.Btree* } + %struct.BtreeMutexArray = type { i32, [11 x %struct.Btree*] } + %struct.BusyHandler = type { i32 (i8*, i32)*, i8*, i32 } + %struct.CellInfo = type { i8*, i64, i32, i32, i16, i16, i16, i16 } + %struct.CollSeq = type { i8*, i8, i8, i8*, i32 (i8*, i32, i8*, i32, i8*)*, void (i8*)* } + %struct.Column = type { i8*, %struct.Expr*, i8*, i8*, i8, i8, i8, i8 } + %struct.Context = type { i64, i32, %struct.Fifo } + %struct.CountCtx = type { i64 } + %struct.Cursor = type { %struct.BtCursor*, i32, i64, i64, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i64, %struct.Btree*, i32, i8*, i64, i8*, %struct.KeyInfo*, i32, i64, %struct.sqlite3_vtab_cursor*, %struct.sqlite3_module*, i32, i32, i32*, i32*, i8* } + %struct.Db = type { i8*, %struct.Btree*, i8, i8, i8*, void (i8*)*, %struct.Schema* } + %struct.Expr = type { i8, i8, i16, %struct.CollSeq*, %struct.Expr*, %struct.Expr*, %struct.ExprList*, %struct..4sPragmaType, %struct..4sPragmaType, i32, i32, %struct.AggInfo*, i32, i32, %struct.Select*, %struct.Table*, i32 } + %struct.ExprList = type { i32, i32, i32, %struct.ExprList_item* } + %struct.ExprList_item = type { %struct.Expr*, i8*, i8, i8, i8 } + %struct.FKey = type { %struct.Table*, %struct.FKey*, i8*, %struct.FKey*, i32, %struct.sColMap*, i8, i8, i8, i8 } + %struct.Fifo = type { i32, %struct.FifoPage*, %struct.FifoPage* } + %struct.FifoPage = type { i32, i32, i32, %struct.FifoPage*, [1 x i64] } + %struct.FuncDef = type { i16, i8, i8, i8, i8*, %struct.FuncDef*, void (%struct.sqlite3_context*, i32, %struct.Mem**)*, void (%struct.sqlite3_context*, i32, %struct.Mem**)*, void (%struct.sqlite3_context*)*, [1 x i8] } + %struct.Hash = type { i8, i8, i32, i32, %struct.HashElem*, %struct._ht* } + %struct.HashElem = type { %struct.HashElem*, %struct.HashElem*, i8*, i8*, i32 } + %struct.IdList = type { %struct..4sPragmaType*, i32, i32 } + %struct.Index = type { i8*, i32, i32*, i32*, %struct.Table*, i32, i8, i8, i8*, %struct.Index*, %struct.Schema*, i8*, i8** } + %struct.KeyInfo = type { %struct.sqlite3*, i8, i8, i8, i32, i8*, [1 x %struct.CollSeq*] } + %struct.Mem = type { %struct.CountCtx, double, %struct.sqlite3*, i8*, i32, i16, i8, i8, void (i8*)* } + %struct.MemPage = type { i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i16, i16, i16, i16, i16, i16, [5 x %struct._OvflCell], %struct.BtShared*, i8*, %struct.PgHdr*, i32, %struct.MemPage* } + %struct.Module = type { %struct.sqlite3_module*, i8*, i8*, void (i8*)* } + %struct.Op = type { i8, i8, i8, i8, i32, i32, i32, { i32 } } + %struct.Pager = type { %struct.sqlite3_vfs*, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, %struct.Bitvec*, %struct.Bitvec*, i8*, i8*, i8*, i8*, %struct.sqlite3_file*, %struct.sqlite3_file*, %struct.sqlite3_file*, %struct.BusyHandler*, %struct.PagerLruList, %struct.PgHdr*, %struct.PgHdr*, %struct.PgHdr*, i64, i64, i64, i64, i64, i32, void (%struct.PgHdr*, i32)*, void (%struct.PgHdr*, i32)*, i32, %struct.PgHdr**, i8*, [16 x i8] } + %struct.PagerLruLink = type { %struct.PgHdr*, %struct.PgHdr* } + %struct.PagerLruList = type { %struct.PgHdr*, %struct.PgHdr*, %struct.PgHdr* } + %struct.Parse = type { %struct.sqlite3*, i32, i8*, %struct.Vdbe*, i8, i8, i8, i8, i8, i8, i8, [8 x i32], i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, [12 x i32], i32, %struct.TableLock*, i32, i32, i32, i32, i32, %struct.Expr**, i8, %struct..4sPragmaType, %struct..4sPragmaType, %struct..4sPragmaType, i8*, i8*, %struct.Table*, %struct.Trigger*, %struct.TriggerStack*, i8*, %struct..4sPragmaType, i8, %struct.Table*, i32 } + %struct.PgHdr = type { %struct.Pager*, i32, %struct.PgHdr*, %struct.PgHdr*, %struct.PagerLruLink, %struct.PgHdr*, i8, i8, i8, i8, i8, i16, %struct.PgHdr*, %struct.PgHdr*, i8* } + %struct.Schema = type { i32, %struct.Hash, %struct.Hash, %struct.Hash, %struct.Hash, %struct.Table*, i8, i8, i16, i32, %struct.sqlite3* } + %struct.Select = type { %struct.ExprList*, i8, i8, i8, i8, i8, i8, i8, %struct.SrcList*, %struct.Expr*, %struct.ExprList*, %struct.Expr*, %struct.ExprList*, %struct.Select*, %struct.Select*, %struct.Select*, %struct.Expr*, %struct.Expr*, i32, i32, [3 x i32] } + %struct.SrcList = type { i16, i16, [1 x %struct.SrcList_item] } + %struct.SrcList_item = type { i8*, i8*, i8*, %struct.Table*, %struct.Select*, i8, i8, i32, %struct.Expr*, %struct.IdList*, i64 } + %struct.Table = type { i8*, i32, %struct.Column*, i32, %struct.Index*, i32, %struct.Select*, i32, %struct.Trigger*, %struct.FKey*, i8*, %struct.Expr*, i32, i8, i8, i8, i8, i8, i8, i8, %struct.Module*, %struct.sqlite3_vtab*, i32, i8**, %struct.Schema* } + %struct.TableLock = type { i32, i32, i8, i8* } + %struct.Trigger = type { i8*, i8*, i8, i8, %struct.Expr*, %struct.IdList*, %struct..4sPragmaType, %struct.Schema*, %struct.Schema*, %struct.TriggerStep*, %struct.Trigger* } + %struct.TriggerStack = type { %struct.Table*, i32, i32, i32, i32, i32, i32, %struct.Trigger*, %struct.TriggerStack* } + %struct.TriggerStep = type { i32, i32, %struct.Trigger*, %struct.Select*, %struct..4sPragmaType, %struct.Expr*, %struct.ExprList*, %struct.IdList*, %struct.TriggerStep*, %struct.TriggerStep* } + %struct.Vdbe = type { %struct.sqlite3*, %struct.Vdbe*, %struct.Vdbe*, i32, i32, %struct.Op*, i32, i32, i32*, %struct.Mem**, %struct.Mem*, i32, %struct.Cursor**, i32, %struct.Mem*, i8**, i32, i32, i32, %struct.Mem*, i32, i32, %struct.Fifo, i32, i32, %struct.Context*, i32, i32, i32, i32, i32, [25 x i32], i32, i32, i8**, i8*, %struct.Mem*, i8, i8, i8, i8, i8, i8, i32, i64, i32, %struct.BtreeMutexArray, i32, i8*, i32 } + %struct.VdbeFunc = type { %struct.FuncDef*, i32, [1 x %struct.AuxData] } + %struct._OvflCell = type { i8*, i16 } + %struct._ht = type { i32, %struct.HashElem* } + %struct.anon = type { double } + %struct.sColMap = type { i32, i8* } + %struct.sqlite3 = type { %struct.sqlite3_vfs*, i32, %struct.Db*, i32, i32, i32, i32, i8, i8, i8, i8, i32, %struct.CollSeq*, i64, i64, i32, i32, i32, %struct.sqlite3_mutex*, %struct.sqlite3InitInfo, i32, i8**, %struct.Vdbe*, i32, void (i8*, i8*)*, i8*, void (i8*, i8*, i64)*, i8*, i8*, i32 (i8*)*, i8*, void (i8*)*, i8*, void (i8*, i32, i8*, i8*, i64)*, void (i8*, %struct.sqlite3*, i32, i8*)*, void (i8*, %struct.sqlite3*, i32, i8*)*, i8*, %struct.Mem*, i8*, i8*, %struct.anon, i32 (i8*, i32, i8*, i8*, i8*, i8*)*, i8*, i32 (i8*)*, i8*, i32, %struct.Hash, %struct.Table*, %struct.sqlite3_vtab**, i32, %struct.Hash, %struct.Hash, %struct.BusyHandler, i32, [2 x %struct.Db], i8 } + %struct.sqlite3InitInfo = type { i32, i32, i8 } + %struct.sqlite3_context = type { %struct.FuncDef*, %struct.VdbeFunc*, %struct.Mem, %struct.Mem*, i32, %struct.CollSeq* } + %struct.sqlite3_file = type { %struct.sqlite3_io_methods* } + %struct.sqlite3_index_constraint = type { i32, i8, i8, i32 } + %struct.sqlite3_index_constraint_usage = type { i32, i8 } + %struct.sqlite3_index_info = type { i32, %struct.sqlite3_index_constraint*, i32, %struct.sqlite3_index_constraint_usage*, %struct.sqlite3_index_constraint_usage*, i32, i8*, i32, i32, double } + %struct.sqlite3_io_methods = type { i32, i32 (%struct.sqlite3_file*)*, i32 (%struct.sqlite3_file*, i8*, i32, i64)*, i32 (%struct.sqlite3_file*, i8*, i32, i64)*, i32 (%struct.sqlite3_file*, i64)*, i32 (%struct.sqlite3_file*, i32)*, i32 (%struct.sqlite3_file*, i64*)*, i32 (%struct.sqlite3_file*, i32)*, i32 (%struct.sqlite3_file*, i32)*, i32 (%struct.sqlite3_file*)*, i32 (%struct.sqlite3_file*, i32, i8*)*, i32 (%struct.sqlite3_file*)*, i32 (%struct.sqlite3_file*)* } + %struct.sqlite3_module = type { i32, i32 (%struct.sqlite3*, i8*, i32, i8**, %struct.sqlite3_vtab**, i8**)*, i32 (%struct.sqlite3*, i8*, i32, i8**, %struct.sqlite3_vtab**, i8**)*, i32 (%struct.sqlite3_vtab*, %struct.sqlite3_index_info*)*, i32 (%struct.sqlite3_vtab*)*, i32 (%struct.sqlite3_vtab*)*, i32 (%struct.sqlite3_vtab*, %struct.sqlite3_vtab_cursor**)*, i32 (%struct.sqlite3_vtab_cursor*)*, i32 (%struct.sqlite3_vtab_cursor*, i32, i8*, i32, %struct.Mem**)*, i32 (%struct.sqlite3_vtab_cursor*)*, i32 (%struct.sqlite3_vtab_cursor*)*, i32 (%struct.sqlite3_vtab_cursor*, %struct.sqlite3_context*, i32)*, i32 (%struct.sqlite3_vtab_cursor*, i64*)*, i32 (%struct.sqlite3_vtab*, i32, %struct.Mem**, i64*)*, i32 (%struct.sqlite3_vtab*)*, i32 (%struct.sqlite3_vtab*)*, i32 (%struct.sqlite3_vtab*)*, i32 (%struct.sqlite3_vtab*)*, i32 (%struct.sqlite3_vtab*, i32, i8*, void (%struct.sqlite3_context*, i32, %struct.Mem**)**, i8**)*, i32 (%struct.sqlite3_vtab*, i8*)* } + %struct.sqlite3_mutex = type opaque + %struct.sqlite3_vfs = type { i32, i32, i32, %struct.sqlite3_vfs*, i8*, i8*, i32 (%struct.sqlite3_vfs*, i8*, %struct.sqlite3_file*, i32, i32*)*, i32 (%struct.sqlite3_vfs*, i8*, i32)*, i32 (%struct.sqlite3_vfs*, i8*, i32)*, i32 (%struct.sqlite3_vfs*, i32, i8*)*, i32 (%struct.sqlite3_vfs*, i8*, i32, i8*)*, i8* (%struct.sqlite3_vfs*, i8*)*, void (%struct.sqlite3_vfs*, i32, i8*)*, i8* (%struct.sqlite3_vfs*, i8*, i8*)*, void (%struct.sqlite3_vfs*, i8*)*, i32 (%struct.sqlite3_vfs*, i32, i8*)*, i32 (%struct.sqlite3_vfs*, i32)*, i32 (%struct.sqlite3_vfs*, double*)* } + %struct.sqlite3_vtab = type { %struct.sqlite3_module*, i32, i8* } + %struct.sqlite3_vtab_cursor = type { %struct.sqlite3_vtab* } + +define fastcc void @sqlite3Insert(%struct.Parse* %pParse, %struct.SrcList* %pTabList, %struct.ExprList* %pList, %struct.Select* %pSelect, %struct.IdList* %pColumn, i32 %onError) nounwind { +entry: + br i1 false, label %bb54, label %bb69.loopexit + +bb54: ; preds = %entry + br label %bb69.loopexit + +bb59: ; preds = %bb63.preheader + %0 = load %struct..4sPragmaType*, %struct..4sPragmaType** %3, align 4 ; <%struct..4sPragmaType*> [#uses=0] + br label %bb65 + +bb65: ; preds = %bb63.preheader, %bb59 + %1 = load %struct..4sPragmaType*, %struct..4sPragmaType** %4, align 4 ; <%struct..4sPragmaType*> [#uses=0] + br i1 false, label %bb67, label %bb63.preheader + +bb67: ; preds = %bb65 + %2 = getelementptr %struct.IdList, %struct.IdList* %pColumn, i32 0, i32 0 ; <%struct..4sPragmaType**> [#uses=0] + unreachable + +bb69.loopexit: ; preds = %bb54, %entry + %3 = getelementptr %struct.IdList, %struct.IdList* %pColumn, i32 0, i32 0 ; <%struct..4sPragmaType**> [#uses=1] + %4 = getelementptr %struct.IdList, %struct.IdList* %pColumn, i32 0, i32 0 ; <%struct..4sPragmaType**> [#uses=1] + br label %bb63.preheader + +bb63.preheader: ; preds = %bb69.loopexit, %bb65 + br i1 false, label %bb59, label %bb65 +} diff --git a/llvm/test/Transforms/NewGVN/2009-03-10-PREOnVoid.ll b/llvm/test/Transforms/NewGVN/2009-03-10-PREOnVoid.ll new file mode 100644 index 00000000000..701556e57eb --- /dev/null +++ b/llvm/test/Transforms/NewGVN/2009-03-10-PREOnVoid.ll @@ -0,0 +1,110 @@ +; RUN: opt < %s -newgvn -disable-output +; PR3775 + +; ModuleID = 'bugpoint-reduced-simplified.bc' +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:32:32" +target triple = "i386-pc-linux-gnu" + %llvm.dbg.anchor.type = type { i32, i32 } + %"struct.__gnu_cxx::hash<void*>" = type <{ i8 }> + %struct.__sched_param = type { i32 } + %struct._pthread_descr_struct = type opaque + %struct.pthread_attr_t = type { i32, i32, %struct.__sched_param, i32, i32, i32, i32, i8*, i32 } + %struct.pthread_mutex_t = type { i32, i32, %struct._pthread_descr_struct*, i32, %llvm.dbg.anchor.type } + %"struct.std::_Rb_tree<void*,std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > >,std::_Select1st<std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > >,std::less<void*>,std::allocator<std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > > >" = type { %"struct.std::_Rb_tree<void*,std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > >,std::_Select1st<std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > >,std::less<void*>,std::allocator<std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > > >::_Rb_tree_impl<std::less<void*>,false>" } + %"struct.std::_Rb_tree<void*,std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > >,std::_Select1st<std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > >,std::less<void*>,std::allocator<std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > > >::_Rb_tree_impl<std::less<void*>,false>" = type { %"struct.__gnu_cxx::hash<void*>", %"struct.std::_Rb_tree_node_base", i32 } + %"struct.std::_Rb_tree_iterator<std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > >" = type { %"struct.std::_Rb_tree_node_base"* } + %"struct.std::_Rb_tree_node_base" = type { i32, %"struct.std::_Rb_tree_node_base"*, %"struct.std::_Rb_tree_node_base"*, %"struct.std::_Rb_tree_node_base"* } + %"struct.std::pair<std::_Rb_tree_iterator<std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > >,bool>" = type { %"struct.std::_Rb_tree_iterator<std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > >", i8 } + %"struct.std::pair<void* const,void*>" = type { i8*, i8* } + +@_ZL20__gthrw_pthread_oncePiPFvvE = weak alias i32 (i32*, void ()*), i32 (i32*, void ()*)* @pthread_once ; <i32 (i32*, void ()*)*> [#uses=0] +@_ZL27__gthrw_pthread_getspecificj = weak alias i8* (i32), i8* (i32)* @pthread_getspecific ; <i8* (i32)*> [#uses=0] +@_ZL27__gthrw_pthread_setspecificjPKv = weak alias i32 (i32, i8*), i32 (i32, i8*)* @pthread_setspecific ; <i32 (i32, i8*)*> [#uses=0] +@_ZL22__gthrw_pthread_createPmPK16__pthread_attr_sPFPvS3_ES3_ = weak alias i32 (i32*, %struct.pthread_attr_t*, i8* (i8*)*, i8*), i32 (i32*, %struct.pthread_attr_t*, i8* (i8*)*, i8*)* @pthread_create ; <i32 (i32*, %struct.pthread_attr_t*, i8* (i8*)*, i8*)*> [#uses=0] +@_ZL22__gthrw_pthread_cancelm = weak alias i32 (i32), i32 (i32)* @pthread_cancel ; <i32 (i32)*> [#uses=0] +@_ZL26__gthrw_pthread_mutex_lockP15pthread_mutex_t = weak alias i32 (%struct.pthread_mutex_t*), i32 (%struct.pthread_mutex_t*)* @pthread_mutex_lock ; <i32 (%struct.pthread_mutex_t*)*> [#uses=0] +@_ZL29__gthrw_pthread_mutex_trylockP15pthread_mutex_t = weak alias i32 (%struct.pthread_mutex_t*), i32 (%struct.pthread_mutex_t*)* @pthread_mutex_trylock ; <i32 (%struct.pthread_mutex_t*)*> [#uses=0] +@_ZL28__gthrw_pthread_mutex_unlockP15pthread_mutex_t = weak alias i32 (%struct.pthread_mutex_t*), i32 (%struct.pthread_mutex_t*)* @pthread_mutex_unlock ; <i32 (%struct.pthread_mutex_t*)*> [#uses=0] +@_ZL26__gthrw_pthread_mutex_initP15pthread_mutex_tPK19pthread_mutexattr_t = weak alias i32 (%struct.pthread_mutex_t*, %struct.__sched_param*), i32 (%struct.pthread_mutex_t*, %struct.__sched_param*)* @pthread_mutex_init ; <i32 (%struct.pthread_mutex_t*, %struct.__sched_param*)*> [#uses=0] +@_ZL26__gthrw_pthread_key_createPjPFvPvE = weak alias i32 (i32*, void (i8*)*), i32 (i32*, void (i8*)*)* @pthread_key_create ; <i32 (i32*, void (i8*)*)*> [#uses=0] +@_ZL26__gthrw_pthread_key_deletej = weak alias i32 (i32), i32 (i32)* @pthread_key_delete ; <i32 (i32)*> [#uses=0] +@_ZL30__gthrw_pthread_mutexattr_initP19pthread_mutexattr_t = weak alias i32 (%struct.__sched_param*), i32 (%struct.__sched_param*)* @pthread_mutexattr_init ; <i32 (%struct.__sched_param*)*> [#uses=0] +@_ZL33__gthrw_pthread_mutexattr_settypeP19pthread_mutexattr_ti = weak alias i32 (%struct.__sched_param*, i32), i32 (%struct.__sched_param*, i32)* @pthread_mutexattr_settype ; <i32 (%struct.__sched_param*, i32)*> [#uses=0] +@_ZL33__gthrw_pthread_mutexattr_destroyP19pthread_mutexattr_t = weak alias i32 (%struct.__sched_param*), i32 (%struct.__sched_param*)* @pthread_mutexattr_destroy ; <i32 (%struct.__sched_param*)*> [#uses=0] + +declare fastcc void @_ZNSt10_Select1stISt4pairIKPvS1_EEC1Ev() nounwind readnone + +define fastcc void @_ZNSt8_Rb_treeIPvSt4pairIKS0_S0_ESt10_Select1stIS3_ESt4lessIS0_ESaIS3_EE16_M_insert_uniqueERKS3_(%"struct.std::pair<std::_Rb_tree_iterator<std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > >,bool>"* noalias nocapture sret %agg.result, %"struct.std::_Rb_tree<void*,std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > >,std::_Select1st<std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > >,std::less<void*>,std::allocator<std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > > >"* %this, %"struct.std::pair<void* const,void*>"* %__v) nounwind { +entry: + br i1 false, label %bb7, label %bb + +bb: ; preds = %bb, %entry + br i1 false, label %bb5, label %bb + +bb5: ; preds = %bb + call fastcc void @_ZNSt10_Select1stISt4pairIKPvS1_EEC1Ev() nounwind + br i1 false, label %bb11, label %bb7 + +bb7: ; preds = %bb5, %entry + br label %bb11 + +bb11: ; preds = %bb7, %bb5 + call fastcc void @_ZNSt10_Select1stISt4pairIKPvS1_EEC1Ev() nounwind + unreachable +} + +define i32 @pthread_once(i32*, void ()*) { + ret i32 0 +} + +define i8* @pthread_getspecific(i32) { + ret i8* null +} + +define i32 @pthread_setspecific(i32, i8*) { + ret i32 0 +} + +define i32 @pthread_create(i32*, %struct.pthread_attr_t*, i8* (i8*)*, i8*) { + ret i32 0 +} + +define i32 @pthread_cancel(i32) { + ret i32 0 +} + +define i32 @pthread_mutex_lock(%struct.pthread_mutex_t*) { + ret i32 0 +} + +define i32 @pthread_mutex_trylock(%struct.pthread_mutex_t*) { + ret i32 0 +} + +define i32 @pthread_mutex_unlock(%struct.pthread_mutex_t*) { + ret i32 0 +} + +define i32 @pthread_mutex_init(%struct.pthread_mutex_t*, %struct.__sched_param*) { + ret i32 0 +} + +define i32 @pthread_key_create(i32*, void (i8*)*) { + ret i32 0 +} + +define i32 @pthread_key_delete(i32) { + ret i32 0 +} + +define i32 @pthread_mutexattr_init(%struct.__sched_param*) { + ret i32 0 +} + +define i32 @pthread_mutexattr_settype(%struct.__sched_param*, i32) { + ret i32 0 +} + +define i32 @pthread_mutexattr_destroy(%struct.__sched_param*) { + ret i32 0 +} diff --git a/llvm/test/Transforms/NewGVN/2009-07-13-MemDepSortFail.ll b/llvm/test/Transforms/NewGVN/2009-07-13-MemDepSortFail.ll new file mode 100644 index 00000000000..e95c1aeb9c8 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/2009-07-13-MemDepSortFail.ll @@ -0,0 +1,67 @@ +; RUN: opt < %s -newgvn | llvm-dis +; PR4256 +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:32:32" +target triple = "i386-pc-linux-gnu" + %llvm.dbg.anchor.type = type { i32, i32 } + %struct.cset = type { i8*, i8, i8, i32, i8* } + %struct.lmat = type { %struct.re_guts*, i32, %llvm.dbg.anchor.type*, i8*, i8*, i8*, i8*, i8**, i32, i8*, i8*, i8*, i8*, i8* } + %struct.re_guts = type { i32*, %struct.cset*, i8*, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i8*, i8*, i32, i32, i32, i32, [1 x i8] } + +define i8* @lbackref(%struct.lmat* %m, i8* %start, i8* %stop, i32 %startst, i32 %stopst, i32 %lev, i32 %rec) nounwind { +entry: + br label %bb63 + +bb: ; preds = %bb63 + switch i32 0, label %bb62 [ + i32 268435456, label %bb2 + i32 805306368, label %bb9 + i32 -1610612736, label %bb51 + ] + +bb2: ; preds = %bb + br label %bb62 + +bb9: ; preds = %bb + %0 = load i8, i8* %sp.1, align 1 ; <i8> [#uses=0] + br label %bb62 + +bb51: ; preds = %bb + %1 = load i8, i8* %sp.1, align 1 ; <i8> [#uses=0] + ret i8* null + +bb62: ; preds = %bb9, %bb2, %bb + br label %bb63 + +bb63: ; preds = %bb84, %bb69, %bb62, %entry + %sp.1 = phi i8* [ null, %bb62 ], [ %sp.1.lcssa, %bb84 ], [ %start, %entry ], [ %sp.1.lcssa, %bb69 ] ; <i8*> [#uses=3] + br i1 false, label %bb, label %bb65 + +bb65: ; preds = %bb63 + %sp.1.lcssa = phi i8* [ %sp.1, %bb63 ] ; <i8*> [#uses=4] + br i1 false, label %bb66, label %bb69 + +bb66: ; preds = %bb65 + ret i8* null + +bb69: ; preds = %bb65 + switch i32 0, label %bb108.loopexit2.loopexit.loopexit [ + i32 1342177280, label %bb63 + i32 1476395008, label %bb84 + i32 1879048192, label %bb104 + i32 2013265920, label %bb93 + ] + +bb84: ; preds = %bb69 + %2 = tail call i8* @lbackref(%struct.lmat* %m, i8* %sp.1.lcssa, i8* %stop, i32 0, i32 %stopst, i32 0, i32 0) nounwind ; <i8*> [#uses=0] + br label %bb63 + +bb93: ; preds = %bb69 + ret i8* null + +bb104: ; preds = %bb69 + %sp.1.lcssa.lcssa33 = phi i8* [ %sp.1.lcssa, %bb69 ] ; <i8*> [#uses=0] + unreachable + +bb108.loopexit2.loopexit.loopexit: ; preds = %bb69 + ret i8* null +} diff --git a/llvm/test/Transforms/NewGVN/2009-11-12-MemDepMallocBitCast.ll b/llvm/test/Transforms/NewGVN/2009-11-12-MemDepMallocBitCast.ll new file mode 100644 index 00000000000..a1121575aa7 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/2009-11-12-MemDepMallocBitCast.ll @@ -0,0 +1,15 @@ +; Test to make sure malloc's bitcast does not block detection of a store +; to aliased memory; GVN should not optimize away the load in this program. +; RUN: opt < %s -newgvn -S | FileCheck %s + +define i64 @test() { + %1 = tail call i8* @malloc(i64 mul (i64 4, i64 ptrtoint (i64* getelementptr (i64, i64* null, i64 1) to i64))) ; <i8*> [#uses=2] + store i8 42, i8* %1 + %X = bitcast i8* %1 to i64* ; <i64*> [#uses=1] + %Y = load i64, i64* %X ; <i64> [#uses=1] + ret i64 %Y +; CHECK: %Y = load i64, i64* %X +; CHECK: ret i64 %Y +} + +declare noalias i8* @malloc(i64) diff --git a/llvm/test/Transforms/NewGVN/2010-03-31-RedundantPHIs.ll b/llvm/test/Transforms/NewGVN/2010-03-31-RedundantPHIs.ll new file mode 100644 index 00000000000..0ff199182f1 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/2010-03-31-RedundantPHIs.ll @@ -0,0 +1,42 @@ +; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s + +; CHECK-NOT: load +; CHECK-NOT: phi + +define i8* @cat(i8* %s1, ...) nounwind { +entry: + br i1 undef, label %bb, label %bb3 + +bb: ; preds = %entry + unreachable + +bb3: ; preds = %entry + store i8* undef, i8** undef, align 4 + br i1 undef, label %bb5, label %bb6 + +bb5: ; preds = %bb3 + unreachable + +bb6: ; preds = %bb3 + br label %bb12 + +bb8: ; preds = %bb12 + br i1 undef, label %bb9, label %bb10 + +bb9: ; preds = %bb8 + %0 = load i8*, i8** undef, align 4 ; <i8*> [#uses=0] + %1 = load i8*, i8** undef, align 4 ; <i8*> [#uses=0] + br label %bb11 + +bb10: ; preds = %bb8 + br label %bb11 + +bb11: ; preds = %bb10, %bb9 + br label %bb12 + +bb12: ; preds = %bb11, %bb6 + br i1 undef, label %bb8, label %bb13 + +bb13: ; preds = %bb12 + ret i8* undef +} diff --git a/llvm/test/Transforms/NewGVN/2010-05-08-OneBit.ll b/llvm/test/Transforms/NewGVN/2010-05-08-OneBit.ll new file mode 100644 index 00000000000..d4acc188cb2 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/2010-05-08-OneBit.ll @@ -0,0 +1,67 @@ +; RUN: opt < %s -newgvn +; PR7052 + +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" + +define i32 @main(i32 %argc, i8** nocapture %argv) personality i32 (...)* @__gxx_personality_v0 { +entry: + %0 = getelementptr inbounds i8, i8* undef, i64 5 ; <i8*> [#uses=1] + %1 = bitcast i8* %0 to i32* ; <i32*> [#uses=1] + store i32 undef, i32* %1, align 1 + br i1 undef, label %k121.i.i, label %l117.i.i + +l117.i.i: ; preds = %entry + invoke fastcc void @foo() + to label %.noexc5 unwind label %landing_pad + +.noexc5: ; preds = %l117.i.i + unreachable + +k121.i.i: ; preds = %entry + br i1 undef, label %l129.i.i, label %k133.i.i + +l129.i.i: ; preds = %k121.i.i + invoke fastcc void @foo() + to label %.noexc7 unwind label %landing_pad + +.noexc7: ; preds = %l129.i.i + unreachable + +k133.i.i: ; preds = %k121.i.i + %2 = getelementptr i8, i8* undef, i64 5 ; <i8*> [#uses=1] + %3 = bitcast i8* %2 to i1* ; <i1*> [#uses=1] + %4 = load i1, i1* %3 ; <i1> [#uses=1] + br i1 %4, label %k151.i.i, label %l147.i.i + +l147.i.i: ; preds = %k133.i.i + invoke fastcc void @foo() + to label %.noexc10 unwind label %landing_pad + +.noexc10: ; preds = %l147.i.i + unreachable + +k151.i.i: ; preds = %k133.i.i + ret i32 0 + +landing_pad: ; preds = %l147.i.i, %l129.i.i, %l117.i.i + %exn = landingpad {i8*, i32} + cleanup + switch i32 undef, label %fin [ + i32 1, label %catch1 + i32 2, label %catch + ] + +fin: ; preds = %landing_pad + unreachable + +catch: ; preds = %landing_pad + ret i32 1 + +catch1: ; preds = %landing_pad + ret i32 2 +} + +declare fastcc void @foo() + +declare i32 @__gxx_personality_v0(...) diff --git a/llvm/test/Transforms/NewGVN/2010-11-13-Simplify.ll b/llvm/test/Transforms/NewGVN/2010-11-13-Simplify.ll new file mode 100644 index 00000000000..635c4b801b4 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/2010-11-13-Simplify.ll @@ -0,0 +1,15 @@ +; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s + +declare i32 @foo(i32) readnone + +define i1 @bar() { +; CHECK-LABEL: @bar( + %a = call i32 @foo (i32 0) readnone + %b = call i32 @foo (i32 0) readnone + %c = and i32 %a, %b + %x = call i32 @foo (i32 %a) readnone + %y = call i32 @foo (i32 %c) readnone + %z = icmp eq i32 %x, %y + ret i1 %z +; CHECK: ret i1 true +} diff --git a/llvm/test/Transforms/NewGVN/2011-04-27-phioperands.ll b/llvm/test/Transforms/NewGVN/2011-04-27-phioperands.ll new file mode 100644 index 00000000000..4904c35b315 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/2011-04-27-phioperands.ll @@ -0,0 +1,106 @@ +; RUN: opt -newgvn -disable-output < %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" + +@nuls = external global [10 x i8] + +define fastcc void @p_ere() nounwind { +entry: + br label %"<bb 5>" + +"<L18>.i": + br i1 undef, label %"<bb 3>.i30.i", label %doemit.exit51.i + +"<bb 3>.i30.i": + unreachable + +doemit.exit51.i: + br label %"<bb 53>.i" + +"<L19>.i": + br i1 undef, label %"<bb 3>.i55.i", label %doemit.exit76.i + +"<bb 3>.i55.i": + unreachable + +doemit.exit76.i: + br label %"<bb 53>.i" + +"<L98>.i": + store i8* getelementptr inbounds ([10 x i8], [10 x i8]* @nuls, i64 0, i64 0), i8** undef, align 8 + br label %"<bb 53>.i" + +"<L99>.i": + br label %"<bb 53>.i" + +"<L24>.i": + br i1 undef, label %"<bb 53>.i", label %"<bb 35>.i" + +"<bb 35>.i": + br label %"<bb 53>.i" + +"<L28>.i": + br label %"<bb 53>.i" + +"<L29>.i": + br label %"<bb 53>.i" + +"<L39>.i": + br label %"<bb 53>.i" + +"<bb 53>.i": + %wascaret_2.i = phi i32 [ 0, %"<L39>.i" ], [ 0, %"<L29>.i" ], [ 0, %"<L28>.i" ], [ 0, %"<bb 35>.i" ], [ 0, %"<L99>.i" ], [ 0, %"<L98>.i" ], [ 0, %doemit.exit76.i ], [ 1, %doemit.exit51.i ], [ 0, %"<L24>.i" ] + %D.5496_84.i = load i8*, i8** undef, align 8 + br i1 undef, label %"<bb 54>.i", label %"<bb 5>" + +"<bb 54>.i": + br i1 undef, label %"<bb 5>", label %"<bb 58>.i" + +"<bb 58>.i": + br i1 undef, label %"<bb 64>.i", label %"<bb 59>.i" + +"<bb 59>.i": + br label %"<bb 64>.i" + +"<bb 64>.i": + switch i32 undef, label %"<bb 5>" [ + i32 42, label %"<L54>.i" + i32 43, label %"<L55>.i" + i32 63, label %"<L56>.i" + i32 123, label %"<bb 5>.i258.i" + ] + +"<L54>.i": + br i1 undef, label %"<bb 3>.i105.i", label %doemit.exit127.i + +"<bb 3>.i105.i": + unreachable + +doemit.exit127.i: + unreachable + +"<L55>.i": + br i1 undef, label %"<bb 3>.i157.i", label %"<bb 5>" + +"<bb 3>.i157.i": + unreachable + +"<L56>.i": + br label %"<bb 5>" + +"<bb 5>.i258.i": + unreachable + +"<bb 5>": + switch i32 undef, label %"<L39>.i" [ + i32 36, label %"<L19>.i" + i32 94, label %"<L18>.i" + i32 124, label %"<L98>.i" + i32 42, label %"<L99>.i" + i32 43, label %"<L99>.i" + i32 46, label %"<L24>.i" + i32 63, label %"<L99>.i" + i32 91, label %"<L28>.i" + i32 92, label %"<L29>.i" + ] +} diff --git a/llvm/test/Transforms/NewGVN/2011-07-07-MatchIntrinsicExtract.ll b/llvm/test/Transforms/NewGVN/2011-07-07-MatchIntrinsicExtract.ll new file mode 100644 index 00000000000..4b47b06f165 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/2011-07-07-MatchIntrinsicExtract.ll @@ -0,0 +1,86 @@ +; XFAIL: * +; RUN: opt < %s -newgvn -S | FileCheck %s +; + +%0 = type { i64, i1 } + +define i64 @test1(i64 %a, i64 %b) nounwind ssp { +entry: + %uadd = tail call %0 @llvm.uadd.with.overflow.i64(i64 %a, i64 %b) + %uadd.0 = extractvalue %0 %uadd, 0 + %add1 = add i64 %a, %b + ret i64 %add1 +} + +; CHECK-LABEL: @test1( +; CHECK-NOT: add1 +; CHECK: ret + +define i64 @test2(i64 %a, i64 %b) nounwind ssp { +entry: + %usub = tail call %0 @llvm.usub.with.overflow.i64(i64 %a, i64 %b) + %usub.0 = extractvalue %0 %usub, 0 + %sub1 = sub i64 %a, %b + ret i64 %sub1 +} + +; CHECK-LABEL: @test2( +; CHECK-NOT: sub1 +; CHECK: ret + +define i64 @test3(i64 %a, i64 %b) nounwind ssp { +entry: + %umul = tail call %0 @llvm.umul.with.overflow.i64(i64 %a, i64 %b) + %umul.0 = extractvalue %0 %umul, 0 + %mul1 = mul i64 %a, %b + ret i64 %mul1 +} + +; CHECK-LABEL: @test3( +; CHECK-NOT: mul1 +; CHECK: ret + +define i64 @test4(i64 %a, i64 %b) nounwind ssp { +entry: + %sadd = tail call %0 @llvm.sadd.with.overflow.i64(i64 %a, i64 %b) + %sadd.0 = extractvalue %0 %sadd, 0 + %add1 = add i64 %a, %b + ret i64 %add1 +} + +; CHECK-LABEL: @test4( +; CHECK-NOT: add1 +; CHECK: ret + +define i64 @test5(i64 %a, i64 %b) nounwind ssp { +entry: + %ssub = tail call %0 @llvm.ssub.with.overflow.i64(i64 %a, i64 %b) + %ssub.0 = extractvalue %0 %ssub, 0 + %sub1 = sub i64 %a, %b + ret i64 %sub1 +} + +; CHECK-LABEL: @test5( +; CHECK-NOT: sub1 +; CHECK: ret + +define i64 @test6(i64 %a, i64 %b) nounwind ssp { +entry: + %smul = tail call %0 @llvm.smul.with.overflow.i64(i64 %a, i64 %b) + %smul.0 = extractvalue %0 %smul, 0 + %mul1 = mul i64 %a, %b + ret i64 %mul1 +} + +; CHECK-LABEL: @test6( +; CHECK-NOT: mul1 +; CHECK: ret + +declare void @exit(i32) noreturn +declare %0 @llvm.uadd.with.overflow.i64(i64, i64) nounwind readnone +declare %0 @llvm.usub.with.overflow.i64(i64, i64) nounwind readnone +declare %0 @llvm.umul.with.overflow.i64(i64, i64) nounwind readnone +declare %0 @llvm.sadd.with.overflow.i64(i64, i64) nounwind readnone +declare %0 @llvm.ssub.with.overflow.i64(i64, i64) nounwind readnone +declare %0 @llvm.smul.with.overflow.i64(i64, i64) nounwind readnone + diff --git a/llvm/test/Transforms/NewGVN/2011-09-07-TypeIdFor.ll b/llvm/test/Transforms/NewGVN/2011-09-07-TypeIdFor.ll new file mode 100644 index 00000000000..719ce6d5f38 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/2011-09-07-TypeIdFor.ll @@ -0,0 +1,81 @@ +; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s +%struct.__fundamental_type_info_pseudo = type { %struct.__type_info_pseudo } +%struct.__type_info_pseudo = type { i8*, i8* } + +@_ZTIi = external constant %struct.__fundamental_type_info_pseudo +@_ZTIb = external constant %struct.__fundamental_type_info_pseudo + +declare void @_Z4barv() + +declare void @_Z7cleanupv() + +declare i32 @llvm.eh.typeid.for(i8*) nounwind readonly + +declare i8* @__cxa_begin_catch(i8*) nounwind + +declare void @__cxa_end_catch() + +declare i32 @__gxx_personality_v0(i32, i64, i8*, i8*) + +define void @_Z3foov() uwtable personality i32 (i32, i64, i8*, i8*)* @__gxx_personality_v0 { +entry: + invoke void @_Z4barv() + to label %return unwind label %lpad + +lpad: ; preds = %entry + %0 = landingpad { i8*, i32 } + catch %struct.__fundamental_type_info_pseudo* @_ZTIi + catch %struct.__fundamental_type_info_pseudo* @_ZTIb + catch %struct.__fundamental_type_info_pseudo* @_ZTIi + catch %struct.__fundamental_type_info_pseudo* @_ZTIb + %exc_ptr2.i = extractvalue { i8*, i32 } %0, 0 + %filter3.i = extractvalue { i8*, i32 } %0, 1 + %typeid.i = tail call i32 @llvm.eh.typeid.for(i8* bitcast (%struct.__fundamental_type_info_pseudo* @_ZTIi to i8*)) +; CHECK: call i32 @llvm.eh.typeid.for + %1 = icmp eq i32 %filter3.i, %typeid.i + br i1 %1, label %ppad, label %next + +next: ; preds = %lpad + %typeid1.i = tail call i32 @llvm.eh.typeid.for(i8* bitcast (%struct.__fundamental_type_info_pseudo* @_ZTIb to i8*)) +; CHECK: call i32 @llvm.eh.typeid.for + %2 = icmp eq i32 %filter3.i, %typeid1.i + br i1 %2, label %ppad2, label %next2 + +ppad: ; preds = %lpad + %3 = tail call i8* @__cxa_begin_catch(i8* %exc_ptr2.i) nounwind + tail call void @__cxa_end_catch() nounwind + br label %return + +ppad2: ; preds = %next + %D.2073_5.i = tail call i8* @__cxa_begin_catch(i8* %exc_ptr2.i) nounwind + tail call void @__cxa_end_catch() nounwind + br label %return + +next2: ; preds = %next + call void @_Z7cleanupv() + %typeid = tail call i32 @llvm.eh.typeid.for(i8* bitcast (%struct.__fundamental_type_info_pseudo* @_ZTIi to i8*)) +; CHECK-NOT: call i32 @llvm.eh.typeid.for + %4 = icmp eq i32 %filter3.i, %typeid + br i1 %4, label %ppad3, label %next3 + +next3: ; preds = %next2 + %typeid1 = tail call i32 @llvm.eh.typeid.for(i8* bitcast (%struct.__fundamental_type_info_pseudo* @_ZTIb to i8*)) + %5 = icmp eq i32 %filter3.i, %typeid1 + br i1 %5, label %ppad4, label %unwind + +unwind: ; preds = %next3 + resume { i8*, i32 } %0 + +ppad3: ; preds = %next2 + %6 = tail call i8* @__cxa_begin_catch(i8* %exc_ptr2.i) nounwind + tail call void @__cxa_end_catch() nounwind + br label %return + +ppad4: ; preds = %next3 + %D.2080_5 = tail call i8* @__cxa_begin_catch(i8* %exc_ptr2.i) nounwind + tail call void @__cxa_end_catch() nounwind + br label %return + +return: ; preds = %ppad4, %ppad3, %ppad2, %ppad, %entry + ret void +} diff --git a/llvm/test/Transforms/NewGVN/2012-05-22-PreCrash.ll b/llvm/test/Transforms/NewGVN/2012-05-22-PreCrash.ll new file mode 100644 index 00000000000..ba3cec8aebd --- /dev/null +++ b/llvm/test/Transforms/NewGVN/2012-05-22-PreCrash.ll @@ -0,0 +1,33 @@ +; RUN: opt < %s -newgvn +; PR12858 + +define void @fn5(i16 signext %p1, i8 signext %p2) nounwind uwtable { +entry: + br i1 undef, label %if.else, label %if.then + +if.then: ; preds = %entry + br label %if.end + +if.else: ; preds = %entry + %conv = sext i16 %p1 to i32 + br label %if.end + +if.end: ; preds = %if.else, %if.then + %conv1 = sext i16 %p1 to i32 + br i1 undef, label %if.then3, label %if.else4 + +if.then3: ; preds = %if.end + br label %if.end12 + +if.else4: ; preds = %if.end + %conv7 = sext i8 %p2 to i32 + %cmp8 = icmp eq i32 %conv1, %conv7 + br i1 %cmp8, label %if.then10, label %if.end12 + +if.then10: ; preds = %if.else4 + br label %if.end12 + +if.end12: ; preds = %if.then10, %if.else4, %if.then3 + %conv13 = sext i8 %p2 to i32 + ret void +} diff --git a/llvm/test/Transforms/NewGVN/2016-08-30-MaskedScatterGather.ll b/llvm/test/Transforms/NewGVN/2016-08-30-MaskedScatterGather.ll new file mode 100644 index 00000000000..a3511c3ae96 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/2016-08-30-MaskedScatterGather.ll @@ -0,0 +1,43 @@ +; XFAIL: * +; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s + +declare void @llvm.masked.scatter.v2i32(<2 x i32> , <2 x i32*> , i32 , <2 x i1> ) +declare <2 x i32> @llvm.masked.gather.v2i32(<2 x i32*>, i32, <2 x i1>, <2 x i32>) + +; This test ensures that masked scatter and gather operations, which take vectors of pointers, +; do not have pointer aliasing ignored when being processed. +; No scatter/gather calls should end up eliminated +; CHECK: llvm.masked.gather +; CHECK: llvm.masked.gather +; CHECK: llvm.masked.scatter +; CHECK: llvm.masked.gather +; CHECK: llvm.masked.scatter +; CHECK: llvm.masked.gather +define spir_kernel void @test(<2 x i32*> %in1, <2 x i32*> %in2, i32* %out) { +entry: + ; Just some temporary storage + %tmp.0 = alloca i32 + %tmp.1 = alloca i32 + %tmp.i = insertelement <2 x i32*> undef, i32* %tmp.0, i32 0 + %tmp = insertelement <2 x i32*> %tmp.i, i32* %tmp.1, i32 1 + ; Read from in1 and in2 + %in1.v = call <2 x i32> @llvm.masked.gather.v2i32(<2 x i32*> %in1, i32 1, <2 x i1> <i1 true, i1 true>, <2 x i32> undef) #1 + %in2.v = call <2 x i32> @llvm.masked.gather.v2i32(<2 x i32*> %in2, i32 1, <2 x i1> <i1 true, i1 true>, <2 x i32> undef) #1 + ; Store in1 to the allocas + call void @llvm.masked.scatter.v2i32(<2 x i32> %in1.v, <2 x i32*> %tmp, i32 1, <2 x i1> <i1 true, i1 true>); + ; Read in1 from the allocas + ; This gather should alias the scatter we just saw + %tmp.v.0 = call <2 x i32> @llvm.masked.gather.v2i32(<2 x i32*> %tmp, i32 1, <2 x i1> <i1 true, i1 true>, <2 x i32> undef) #1 + ; Store in2 to the allocas + call void @llvm.masked.scatter.v2i32(<2 x i32> %in2.v, <2 x i32*> %tmp, i32 1, <2 x i1> <i1 true, i1 true>); + ; Read in2 from the allocas + ; This gather should alias the scatter we just saw, and not be eliminated + %tmp.v.1 = call <2 x i32> @llvm.masked.gather.v2i32(<2 x i32*> %tmp, i32 1, <2 x i1> <i1 true, i1 true>, <2 x i32> undef) #1 + ; Store in2 to out for good measure + %tmp.v.1.0 = extractelement <2 x i32> %tmp.v.1, i32 0 + %tmp.v.1.1 = extractelement <2 x i32> %tmp.v.1, i32 1 + store i32 %tmp.v.1.0, i32* %out + %out.1 = getelementptr i32, i32* %out, i32 1 + store i32 %tmp.v.1.1, i32* %out.1 + ret void +} diff --git a/llvm/test/Transforms/NewGVN/MemdepMiscompile.ll b/llvm/test/Transforms/NewGVN/MemdepMiscompile.ll new file mode 100644 index 00000000000..559882cdc4c --- /dev/null +++ b/llvm/test/Transforms/NewGVN/MemdepMiscompile.ll @@ -0,0 +1,54 @@ +; RUN: opt < %s -basicaa -newgvn -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.7.0" + +; rdar://12801584 +; Value of %shouldExit can be changed by RunInMode. +; Make sure we do not replace load %shouldExit in while.cond.backedge +; with a phi node where the value from while.body is 0. +define i32 @test() nounwind ssp { +entry: +; CHECK: test() +; CHECK: while.body: +; CHECK: call void @RunInMode +; CHECK: br i1 %tobool, label %while.cond.backedge, label %if.then +; CHECK: while.cond.backedge: +; CHECK: load i32, i32* %shouldExit +; CHECK: br i1 %cmp, label %while.body + %shouldExit = alloca i32, align 4 + %tasksIdle = alloca i32, align 4 + store i32 0, i32* %shouldExit, align 4 + store i32 0, i32* %tasksIdle, align 4 + call void @CTestInitialize(i32* %tasksIdle) nounwind + %0 = load i32, i32* %shouldExit, align 4 + %cmp1 = icmp eq i32 %0, 0 + br i1 %cmp1, label %while.body.lr.ph, label %while.end + +while.body.lr.ph: + br label %while.body + +while.body: + call void @RunInMode(i32 100) nounwind + %1 = load i32, i32* %tasksIdle, align 4 + %tobool = icmp eq i32 %1, 0 + br i1 %tobool, label %while.cond.backedge, label %if.then + +if.then: + store i32 0, i32* %tasksIdle, align 4 + call void @TimerCreate(i32* %shouldExit) nounwind + br label %while.cond.backedge + +while.cond.backedge: + %2 = load i32, i32* %shouldExit, align 4 + %cmp = icmp eq i32 %2, 0 + br i1 %cmp, label %while.body, label %while.cond.while.end_crit_edge + +while.cond.while.end_crit_edge: + br label %while.end + +while.end: + ret i32 0 +} +declare void @CTestInitialize(i32*) +declare void @RunInMode(i32) +declare void @TimerCreate(i32*) diff --git a/llvm/test/Transforms/NewGVN/assume-equal.ll b/llvm/test/Transforms/NewGVN/assume-equal.ll new file mode 100644 index 00000000000..b6c2a7afb29 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/assume-equal.ll @@ -0,0 +1,276 @@ +; XFAIL: * +; RUN: opt < %s -newgvn -S | FileCheck %s + +%struct.A = type { i32 (...)** } +@_ZTV1A = available_externally unnamed_addr constant [4 x i8*] [i8* null, i8* bitcast (i8** @_ZTI1A to i8*), i8* bitcast (i32 (%struct.A*)* @_ZN1A3fooEv to i8*), i8* bitcast (i32 (%struct.A*)* @_ZN1A3barEv to i8*)], align 8 +@_ZTI1A = external constant i8* + +; Checks if indirect calls can be replaced with direct +; assuming that %vtable == @_ZTV1A (with alignment). +; Checking const propagation across other BBs +; CHECK-LABEL: define void @_Z1gb( + +define void @_Z1gb(i1 zeroext %p) { +entry: + %call = tail call noalias i8* @_Znwm(i64 8) #4 + %0 = bitcast i8* %call to %struct.A* + tail call void @_ZN1AC1Ev(%struct.A* %0) #1 + %1 = bitcast i8* %call to i8*** + %vtable = load i8**, i8*** %1, align 8 + %cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([4 x i8*], [4 x i8*]* @_ZTV1A, i64 0, i64 2) + tail call void @llvm.assume(i1 %cmp.vtables) + br i1 %p, label %if.then, label %if.else + +if.then: ; preds = %entry + %vtable1.cast = bitcast i8** %vtable to i32 (%struct.A*)** + %2 = load i32 (%struct.A*)*, i32 (%struct.A*)** %vtable1.cast, align 8 + + ; CHECK: call i32 @_ZN1A3fooEv( + %call2 = tail call i32 %2(%struct.A* %0) #1 + + br label %if.end + +if.else: ; preds = %entry + %vfn47 = getelementptr inbounds i8*, i8** %vtable, i64 1 + %vfn4 = bitcast i8** %vfn47 to i32 (%struct.A*)** + + ; CHECK: call i32 @_ZN1A3barEv( + %3 = load i32 (%struct.A*)*, i32 (%struct.A*)** %vfn4, align 8 + + %call5 = tail call i32 %3(%struct.A* %0) #1 + br label %if.end + +if.end: ; preds = %if.else, %if.then + ret void +} + +; Check integration with invariant.group handling +; CHECK-LABEL: define void @invariantGroupHandling(i1 zeroext %p) { +define void @invariantGroupHandling(i1 zeroext %p) { +entry: + %call = tail call noalias i8* @_Znwm(i64 8) #4 + %0 = bitcast i8* %call to %struct.A* + tail call void @_ZN1AC1Ev(%struct.A* %0) #1 + %1 = bitcast i8* %call to i8*** + %vtable = load i8**, i8*** %1, align 8, !invariant.group !0 + %cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([4 x i8*], [4 x i8*]* @_ZTV1A, i64 0, i64 2) + tail call void @llvm.assume(i1 %cmp.vtables) + br i1 %p, label %if.then, label %if.else + +if.then: ; preds = %entry + %vtable1.cast = bitcast i8** %vtable to i32 (%struct.A*)** + %2 = load i32 (%struct.A*)*, i32 (%struct.A*)** %vtable1.cast, align 8 + +; CHECK: call i32 @_ZN1A3fooEv( + %call2 = tail call i32 %2(%struct.A* %0) #1 + %vtable1 = load i8**, i8*** %1, align 8, !invariant.group !0 + %vtable2.cast = bitcast i8** %vtable1 to i32 (%struct.A*)** + %call1 = load i32 (%struct.A*)*, i32 (%struct.A*)** %vtable2.cast, align 8 +; FIXME: those loads could be also direct, but right now the invariant.group +; analysis works only on single block +; CHECK-NOT: call i32 @_ZN1A3fooEv( + %callx = tail call i32 %call1(%struct.A* %0) #1 + + %vtable2 = load i8**, i8*** %1, align 8, !invariant.group !0 + %vtable3.cast = bitcast i8** %vtable2 to i32 (%struct.A*)** + %call4 = load i32 (%struct.A*)*, i32 (%struct.A*)** %vtable3.cast, align 8 +; CHECK-NOT: call i32 @_ZN1A3fooEv( + %cally = tail call i32 %call4(%struct.A* %0) #1 + + %b = bitcast i8* %call to %struct.A** + %vtable3 = load %struct.A*, %struct.A** %b, align 8, !invariant.group !0 + %vtable4.cast = bitcast %struct.A* %vtable3 to i32 (%struct.A*)** + %vfun = load i32 (%struct.A*)*, i32 (%struct.A*)** %vtable4.cast, align 8 +; CHECK-NOT: call i32 @_ZN1A3fooEv( + %unknown = tail call i32 %vfun(%struct.A* %0) #1 + + br label %if.end + +if.else: ; preds = %entry + %vfn47 = getelementptr inbounds i8*, i8** %vtable, i64 1 + %vfn4 = bitcast i8** %vfn47 to i32 (%struct.A*)** + + ; CHECK: call i32 @_ZN1A3barEv( + %3 = load i32 (%struct.A*)*, i32 (%struct.A*)** %vfn4, align 8 + + %call5 = tail call i32 %3(%struct.A* %0) #1 + br label %if.end + +if.end: ; preds = %if.else, %if.then + ret void +} + + +; Checking const propagation in the same BB +; CHECK-LABEL: define i32 @main() + +define i32 @main() { +entry: + %call = tail call noalias i8* @_Znwm(i64 8) + %0 = bitcast i8* %call to %struct.A* + tail call void @_ZN1AC1Ev(%struct.A* %0) + %1 = bitcast i8* %call to i8*** + %vtable = load i8**, i8*** %1, align 8 + %cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([4 x i8*], [4 x i8*]* @_ZTV1A, i64 0, i64 2) + tail call void @llvm.assume(i1 %cmp.vtables) + %vtable1.cast = bitcast i8** %vtable to i32 (%struct.A*)** + + ; CHECK: call i32 @_ZN1A3fooEv( + %2 = load i32 (%struct.A*)*, i32 (%struct.A*)** %vtable1.cast, align 8 + + %call2 = tail call i32 %2(%struct.A* %0) + ret i32 0 +} + +; This tests checks const propatation with fcmp instruction. +; CHECK-LABEL: define float @_Z1gf(float %p) + +define float @_Z1gf(float %p) { +entry: + %p.addr = alloca float, align 4 + %f = alloca float, align 4 + store float %p, float* %p.addr, align 4 + + store float 3.000000e+00, float* %f, align 4 + %0 = load float, float* %p.addr, align 4 + %1 = load float, float* %f, align 4 + %cmp = fcmp oeq float %1, %0 ; note const on lhs + call void @llvm.assume(i1 %cmp) + + ; CHECK: ret float 3.000000e+00 + ret float %0 +} + +; CHECK-LABEL: define float @_Z1hf(float %p) + +define float @_Z1hf(float %p) { +entry: + %p.addr = alloca float, align 4 + store float %p, float* %p.addr, align 4 + + %0 = load float, float* %p.addr, align 4 + %cmp = fcmp nnan ueq float %0, 3.000000e+00 + call void @llvm.assume(i1 %cmp) + + ; CHECK: ret float 3.000000e+00 + ret float %0 +} + +; CHECK-LABEL: define float @_Z1if(float %p) +define float @_Z1if(float %p) { +entry: + %p.addr = alloca float, align 4 + store float %p, float* %p.addr, align 4 + + %0 = load float, float* %p.addr, align 4 + %cmp = fcmp ueq float %0, 3.000000e+00 ; no nnan flag - can't propagate + call void @llvm.assume(i1 %cmp) + + ; CHECK-NOT: ret float 3.000000e+00 + ret float %0 +} + +; This test checks if constant propagation works for multiple node edges +; CHECK-LABEL: define i32 @_Z1ii(i32 %p) +define i32 @_Z1ii(i32 %p) { +entry: + %cmp = icmp eq i32 %p, 42 + call void @llvm.assume(i1 %cmp) + + ; CHECK: br i1 true, label %bb2, label %bb2 + br i1 %cmp, label %bb2, label %bb2 +bb2: + call void @llvm.assume(i1 true) + ; CHECK: br i1 true, label %bb2, label %bb2 + br i1 %cmp, label %bb2, label %bb2 + + ; CHECK: ret i32 42 + ret i32 %p +} + +; CHECK-LABEL: define i32 @_Z1ij(i32 %p) +define i32 @_Z1ij(i32 %p) { +entry: + %cmp = icmp eq i32 %p, 42 + call void @llvm.assume(i1 %cmp) + + ; CHECK: br i1 true, label %bb2, label %bb2 + br i1 %cmp, label %bb2, label %bb2 +bb2: + ; CHECK-NOT: %cmp2 = + %cmp2 = icmp eq i32 %p, 42 + ; CHECK-NOT: call void @llvm.assume( + call void @llvm.assume(i1 %cmp2) + + ; CHECK: br i1 true, label %bb2, label %bb2 + br i1 %cmp, label %bb2, label %bb2 + + ; CHECK: ret i32 42 + ret i32 %p +} + +; CHECK-LABEL: define i32 @_Z1ik(i32 %p) +define i32 @_Z1ik(i32 %p) { +entry: + %cmp = icmp eq i32 %p, 42 + call void @llvm.assume(i1 %cmp) + + ; CHECK: br i1 true, label %bb2, label %bb3 + br i1 %cmp, label %bb2, label %bb3 +bb2: + ; CHECK-NOT: %cmp3 = + %cmp3 = icmp eq i32 %p, 43 + ; CHECK: store i8 undef, i8* null + call void @llvm.assume(i1 %cmp3) + ret i32 15 +bb3: + ret i32 17 +} + +; This test checks if GVN can do the constant propagation correctly +; when there are multiple uses of the same assume value in the +; basic block that has a loop back-edge pointing to itself. +; +; CHECK-LABEL: define i32 @_Z1il(i32 %val, i1 %k) +define i32 @_Z1il(i32 %val, i1 %k) { + br label %next + +next: +; CHECK: tail call void @llvm.assume(i1 %k) +; CHECK-NEXT: %cmp = icmp eq i32 %val, 50 + tail call void @llvm.assume(i1 %k) + tail call void @llvm.assume(i1 %k) + %cmp = icmp eq i32 %val, 50 + br i1 %cmp, label %next, label %meh + +meh: + ret i32 0 +} + +; This test checks if GVN can prevent the constant propagation correctly +; in the successor blocks that are not dominated by the basic block +; with the assume instruction. +; +; CHECK-LABEL: define i1 @_z1im(i32 %val, i1 %k, i1 %j) +define i1 @_z1im(i32 %val, i1 %k, i1 %j) { + br i1 %j, label %next, label %meh + +next: +; CHECK: tail call void @llvm.assume(i1 %k) +; CHECK-NEXT: br label %meh + tail call void @llvm.assume(i1 %k) + tail call void @llvm.assume(i1 %k) + br label %meh + +meh: +; CHECK: ret i1 %k + ret i1 %k +} + +declare noalias i8* @_Znwm(i64) +declare void @_ZN1AC1Ev(%struct.A*) +declare void @llvm.assume(i1) +declare i32 @_ZN1A3fooEv(%struct.A*) +declare i32 @_ZN1A3barEv(%struct.A*) + +!0 = !{!"struct A"} diff --git a/llvm/test/Transforms/NewGVN/basic-undef-test.ll b/llvm/test/Transforms/NewGVN/basic-undef-test.ll new file mode 100644 index 00000000000..681e77b2629 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/basic-undef-test.ll @@ -0,0 +1,15 @@ +; RUN: opt -basicaa -newgvn -S < %s | FileCheck %s +; ModuleID = 'test3.ll' +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" + +define i32 @main(i32 *%foo) { +entry: +; CHECK: load i32, i32* %foo, align 4 + %0 = load i32, i32* %foo, align 4 + store i32 5, i32* undef, align 4 +; CHECK-NOT: load i32, i32* %foo, align 4 + %1 = load i32, i32* %foo, align 4 +; CHECK: add i32 %0, %0 + %2 = add i32 %0, %1 + ret i32 %2 +} diff --git a/llvm/test/Transforms/NewGVN/basic.ll b/llvm/test/Transforms/NewGVN/basic.ll new file mode 100644 index 00000000000..40c83a1d03f --- /dev/null +++ b/llvm/test/Transforms/NewGVN/basic.ll @@ -0,0 +1,17 @@ +; XFAIL: * +; RUN: opt < %s -newgvn -S | FileCheck %s +; RUN: opt < %s -passes=gvn -S | FileCheck %s + +define i32 @main() { +block1: + %z1 = bitcast i32 0 to i32 + br label %block2 +block2: + %z2 = bitcast i32 0 to i32 + ret i32 %z2 +} + +; CHECK: define i32 @main() { +; CHECK-NEXT: block1: +; CHECK-NEXT: ret i32 0 +; CHECK-NEXT: } diff --git a/llvm/test/Transforms/NewGVN/big-endian.ll b/llvm/test/Transforms/NewGVN/big-endian.ll new file mode 100644 index 00000000000..46b336b2e66 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/big-endian.ll @@ -0,0 +1,40 @@ +; RUN: opt -newgvn -S < %s | FileCheck %s + +target datalayout = "E-m:e-i64:64-n32:64" +target triple = "powerpc64-unknown-linux-gnu" + +;; Make sure we use correct bit shift based on storage size for +;; loads reusing a load value. +define i64 @test1({ i1, i8 }* %predA, { i1, i8 }* %predB) { +; CHECK-LABEL: @test1 +; CHECK-NOT: [[V1:%.*]] = load i16, i16* %{{.*}} +; CHECK-NOT: [[V2:%.*]] = lshr i16 [[V1]], 8 +; CHECK-NOT: trunc i16 [[V2]] to i1 + + %valueLoadA.fca.0.gep = getelementptr inbounds { i1, i8 }, { i1, i8 }* %predA, i64 0, i32 0 + %valueLoadA.fca.0.load = load i1, i1* %valueLoadA.fca.0.gep, align 8 + %valueLoadB.fca.0.gep = getelementptr inbounds { i1, i8 }, { i1, i8 }* %predB, i64 0, i32 0 + %valueLoadB.fca.0.load = load i1, i1* %valueLoadB.fca.0.gep, align 8 + %isTrue = and i1 %valueLoadA.fca.0.load, %valueLoadB.fca.0.load + %valueLoadA.fca.1.gep = getelementptr inbounds { i1, i8 }, { i1, i8 }* %predA, i64 0, i32 1 + %valueLoadA.fca.1.load = load i8, i8* %valueLoadA.fca.1.gep, align 1 + %isNotNullA = icmp ne i8 %valueLoadA.fca.1.load, 0 + %valueLoadB.fca.1.gep = getelementptr inbounds { i1, i8 }, { i1, i8 }* %predB, i64 0, i32 1 + %valueLoadB.fca.1.load = load i8, i8* %valueLoadB.fca.1.gep, align 1 + %isNotNullB = icmp ne i8 %valueLoadB.fca.1.load, 0 + %isNotNull = and i1 %isNotNullA, %isNotNullB + %isTrueAndNotNull = and i1 %isTrue, %isNotNull + %ret = zext i1 %isTrueAndNotNull to i64 + ret i64 %ret +} + +;; And likewise for loads reusing a store value. +define i1 @test2(i8 %V, i8* %P) { +; CHECK-LABEL: @test2 +; CHECK-NOT: lshr + store i8 %V, i8* %P + %P2 = bitcast i8* %P to i1* + %A = load i1, i1* %P2 + ret i1 %A +} + diff --git a/llvm/test/Transforms/NewGVN/bitcast-of-call.ll b/llvm/test/Transforms/NewGVN/bitcast-of-call.ll new file mode 100644 index 00000000000..7b25038275b --- /dev/null +++ b/llvm/test/Transforms/NewGVN/bitcast-of-call.ll @@ -0,0 +1,14 @@ +; XFAIL: * +; RUN: opt < %s -newgvn -S | FileCheck %s +; PR2213 + +define i32* @f(i8* %x) { +entry: + %tmp = call i8* @m( i32 12 ) ; <i8*> [#uses=2] + %tmp1 = bitcast i8* %tmp to i32* ; <i32*> [#uses=0] + %tmp2 = bitcast i8* %tmp to i32* ; <i32*> [#uses=0] +; CHECK-NOT: %tmp2 + ret i32* %tmp2 +} + +declare i8* @m(i32) diff --git a/llvm/test/Transforms/NewGVN/br-identical.ll b/llvm/test/Transforms/NewGVN/br-identical.ll new file mode 100644 index 00000000000..672887ccf19 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/br-identical.ll @@ -0,0 +1,38 @@ +; RUN: opt -newgvn -S -o - %s | FileCheck %s + +; If a branch has two identical successors, we cannot declare either dead. + +define void @widget(i1 %p) { +entry: + br label %bb2 + +bb2: + %t1 = phi i64 [ 0, %entry ], [ %t5, %bb7 ] + %t2 = add i64 %t1, 1 + %t3 = icmp ult i64 0, %t2 + br i1 %t3, label %bb3, label %bb4 + +bb3: + %t4 = call i64 @f() + br label %bb4 + +bb4: + ; CHECK-NOT: phi {{.*}} undef + %foo = phi i64 [ %t4, %bb3 ], [ 0, %bb2 ] + br i1 %p, label %bb5, label %bb6 + +bb5: + br i1 true, label %bb7, label %bb7 + +bb6: + br i1 true, label %bb7, label %bb7 + +bb7: + %t5 = add i64 %t1, 1 + br i1 %p, label %bb2, label %bb8 + +bb8: + ret void +} + +declare i64 @f() diff --git a/llvm/test/Transforms/NewGVN/calloc-load-removal.ll b/llvm/test/Transforms/NewGVN/calloc-load-removal.ll new file mode 100644 index 00000000000..e6870442064 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/calloc-load-removal.ll @@ -0,0 +1,26 @@ +; XFAIL: * +; RUN: opt -S -basicaa -newgvn < %s | FileCheck %s +; RUN: opt -S -basicaa -newgvn -disable-simplify-libcalls < %s | FileCheck %s -check-prefix=CHECK_NO_LIBCALLS +; Check that loads from calloc are recognized as being zero. + +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-S128" + +; Function Attrs: nounwind uwtable +define i32 @test1() { + %1 = tail call noalias i8* @calloc(i64 1, i64 4) + %2 = bitcast i8* %1 to i32* + ; This load is trivially constant zero + %3 = load i32, i32* %2, align 4 + ret i32 %3 + +; CHECK-LABEL: @test1( +; CHECK-NOT: %3 = load i32, i32* %2, align 4 +; CHECK: ret i32 0 + +; CHECK_NO_LIBCALLS-LABEL: @test1( +; CHECK_NO_LIBCALLS: load +; CHECK_NO_LIBCALLS: ret i32 % + +} + +declare noalias i8* @calloc(i64, i64) diff --git a/llvm/test/Transforms/NewGVN/calls-nonlocal.ll b/llvm/test/Transforms/NewGVN/calls-nonlocal.ll new file mode 100644 index 00000000000..292060db812 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/calls-nonlocal.ll @@ -0,0 +1,76 @@ +; XFAIL: * +; Two occurrences of strlen should be zapped. +; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s +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" +target triple = "i386-apple-darwin9" + +define i32 @test(i32 %g, i8* %P) nounwind { +entry: + %tmp2 = call i32 @strlen( i8* %P ) nounwind readonly ; <i32> [#uses=1] + %tmp3 = icmp eq i32 %tmp2, 100 ; <i1> [#uses=1] + %tmp34 = zext i1 %tmp3 to i8 ; <i8> [#uses=1] + %toBool = icmp ne i8 %tmp34, 0 ; <i1> [#uses=1] + br i1 %toBool, label %bb, label %bb6 + +bb: ; preds = %entry + br label %bb27 + +bb6: ; preds = %entry + %tmp8 = add i32 %g, 42 ; <i32> [#uses=2] + %tmp10 = call i32 @strlen( i8* %P ) nounwind readonly ; <i32> [#uses=1] + %tmp11 = icmp eq i32 %tmp10, 100 ; <i1> [#uses=1] + %tmp1112 = zext i1 %tmp11 to i8 ; <i8> [#uses=1] + %toBool13 = icmp ne i8 %tmp1112, 0 ; <i1> [#uses=1] + br i1 %toBool13, label %bb14, label %bb16 + +bb14: ; preds = %bb6 + br label %bb27 + +bb16: ; preds = %bb6 + %tmp18 = mul i32 %tmp8, 2 ; <i32> [#uses=1] + %tmp20 = call i32 @strlen( i8* %P ) nounwind readonly ; <i32> [#uses=1] + %tmp21 = icmp eq i32 %tmp20, 100 ; <i1> [#uses=1] + %tmp2122 = zext i1 %tmp21 to i8 ; <i8> [#uses=1] + %toBool23 = icmp ne i8 %tmp2122, 0 ; <i1> [#uses=1] + br i1 %toBool23, label %bb24, label %bb26 + +bb24: ; preds = %bb16 + br label %bb27 + +bb26: ; preds = %bb16 + br label %bb27 + +bb27: ; preds = %bb26, %bb24, %bb14, %bb + %tmp.0 = phi i32 [ 11, %bb26 ], [ %tmp18, %bb24 ], [ %tmp8, %bb14 ], [ %g, %bb ] ; <i32> [#uses=1] + br label %return + +return: ; preds = %bb27 + ret i32 %tmp.0 +} + +; CHECK: define i32 @test(i32 %g, i8* %P) #0 { +; CHECK: entry: +; CHECK: %tmp2 = call i32 @strlen(i8* %P) #1 +; CHECK: %tmp3 = icmp eq i32 %tmp2, 100 +; CHECK: %tmp34 = zext i1 %tmp3 to i8 +; CHECK: br i1 %tmp3, label %bb, label %bb6 +; CHECK: bb: +; CHECK: br label %bb27 +; CHECK: bb6: +; CHECK: %tmp8 = add i32 %g, 42 +; CHECK: br i1 false, label %bb14, label %bb16 +; CHECK: bb14: +; CHECK: br label %bb27 +; CHECK: bb16: +; CHECK: %tmp18 = mul i32 %tmp8, 2 +; CHECK: br i1 false, label %bb24, label %bb26 +; CHECK: bb24: +; CHECK: br label %bb27 +; CHECK: bb26: +; CHECK: br label %bb27 +; CHECK: bb27: +; CHECK: %tmp.0 = phi i32 [ 11, %bb26 ], [ undef, %bb24 ], [ undef, %bb14 ], [ %g, %bb ] +; CHECK: ret i32 %tmp.0 +; CHECK: } + +declare i32 @strlen(i8*) nounwind readonly diff --git a/llvm/test/Transforms/NewGVN/calls-readonly.ll b/llvm/test/Transforms/NewGVN/calls-readonly.ll new file mode 100644 index 00000000000..8bc3bf2b48c --- /dev/null +++ b/llvm/test/Transforms/NewGVN/calls-readonly.ll @@ -0,0 +1,45 @@ +; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s +; Should delete the second call to strlen even though the intervening strchr call exists. + +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" +target triple = "i386-apple-darwin7" + +define i8* @test(i8* %P, i8* %Q, i32 %x, i32 %y) nounwind readonly { +entry: + %0 = tail call i32 @strlen(i8* %P) ; <i32> [#uses=2] + %1 = icmp eq i32 %0, 0 ; <i1> [#uses=1] + br i1 %1, label %bb, label %bb1 + +bb: ; preds = %entry + %2 = sdiv i32 %x, %y ; <i32> [#uses=1] + br label %bb1 + +bb1: ; preds = %bb, %entry + %x_addr.0 = phi i32 [ %2, %bb ], [ %x, %entry ] ; <i32> [#uses=1] + %3 = tail call i8* @strchr(i8* %Q, i32 97) ; <i8*> [#uses=1] + %4 = tail call i32 @strlen(i8* %P) ; <i32> [#uses=1] + %5 = add i32 %x_addr.0, %0 ; <i32> [#uses=1] + %.sum = sub i32 %5, %4 ; <i32> [#uses=1] + %6 = getelementptr i8, i8* %3, i32 %.sum ; <i8*> [#uses=1] + ret i8* %6 +} + +; CHECK: define i8* @test(i8* %P, i8* %Q, i32 %x, i32 %y) #0 { +; CHECK: entry: +; CHECK-NEXT: %0 = tail call i32 @strlen(i8* %P) +; CHECK-NEXT: %1 = icmp eq i32 %0, 0 +; CHECK-NEXT: br i1 %1, label %bb, label %bb1 +; CHECK: bb: +; CHECK-NEXT: %2 = sdiv i32 %x, %y +; CHECK-NEXT: br label %bb1 +; CHECK: bb1: +; CHECK-NEXT: %x_addr.0 = phi i32 [ %2, %bb ], [ %x, %entry ] +; CHECK-NEXT: %3 = tail call i8* @strchr(i8* %Q, i32 97) +; CHECK-NEXT: %4 = add i32 %x_addr.0, %0 +; CHECK-NEXT: %5 = getelementptr i8, i8* %3, i32 %x_addr.0 +; CHECK-NEXT: ret i8* %5 +; CHECK: } + +declare i32 @strlen(i8*) nounwind readonly + +declare i8* @strchr(i8*, i32) nounwind readonly diff --git a/llvm/test/Transforms/NewGVN/commute.ll b/llvm/test/Transforms/NewGVN/commute.ll new file mode 100644 index 00000000000..ab7541bd502 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/commute.ll @@ -0,0 +1,23 @@ +; RUN: opt -newgvn -S < %s | FileCheck %s + +declare void @use(i32, i32) + +define void @foo(i32 %x, i32 %y) { + ; CHECK-LABEL: @foo( + %add1 = add i32 %x, %y + %add2 = add i32 %y, %x + call void @use(i32 %add1, i32 %add2) + ; CHECK: @use(i32 %add1, i32 %add1) + ret void +} + +declare void @vse(i1, i1) + +define void @bar(i32 %x, i32 %y) { + ; CHECK-LABEL: @bar( + %cmp1 = icmp ult i32 %x, %y + %cmp2 = icmp ugt i32 %y, %x + call void @vse(i1 %cmp1, i1 %cmp2) + ; CHECK: @vse(i1 %cmp1, i1 %cmp1) + ret void +} diff --git a/llvm/test/Transforms/NewGVN/cond_br.ll b/llvm/test/Transforms/NewGVN/cond_br.ll new file mode 100644 index 00000000000..a2584f3aa29 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/cond_br.ll @@ -0,0 +1,55 @@ +; RUN: opt -basicaa -newgvn -S < %s | FileCheck %s +@y = external global i32 +@z = external global i32 + +; Function Attrs: nounwind ssp uwtable +define void @foo(i32 %x) { +; CHECK: @foo(i32 %x) +; CHECK: %.pre = load i32, i32* @y +; CHECK: call void @bar(i32 %.pre) + + %t = sub i32 %x, %x + %.pre = load i32, i32* @y, align 4 + %cmp = icmp sgt i32 %t, 2 + br i1 %cmp, label %if.then, label %entry.if.end_crit_edge + +entry.if.end_crit_edge: ; preds = %entry + br label %if.end + +if.then: ; preds = %entry + %add = add nsw i32 %x, 3 + store i32 %add, i32* @y, align 4 + br label %if.end + +if.end: ; preds = %entry.if.end_crit_edge, %if.then + %1 = phi i32 [ %.pre, %entry.if.end_crit_edge ], [ %add, %if.then ] + tail call void @bar(i32 %1) + ret void +} + +define void @foo2(i32 %x) { +; CHECK: @foo2(i32 %x) +; CHECK: %.pre = load i32, i32* @y +; CHECK: tail call void @bar(i32 %.pre) +entry: + %t = sub i32 %x, %x + %.pre = load i32, i32* @y, align 4 + %cmp = icmp sgt i32 %t, 2 + br i1 %cmp, label %if.then, label %if.else + +if.then: ; preds = %entry + %add = add nsw i32 %x, 3 + store i32 %add, i32* @y, align 4 + br label %if.end + +if.else: ; preds = %entry + store i32 1, i32* @z, align 4 + br label %if.end + +if.end: ; preds = %if.else, %if.then + %0 = phi i32 [ %.pre, %if.else ], [ %add, %if.then ] + tail call void @bar(i32 %0) + ret void +} + +declare void @bar(i32) diff --git a/llvm/test/Transforms/NewGVN/cond_br2.ll b/llvm/test/Transforms/NewGVN/cond_br2.ll new file mode 100644 index 00000000000..e511ff7ed51 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/cond_br2.ll @@ -0,0 +1,141 @@ +; XFAIL: * +; RUN: opt -basicaa -newgvn -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-n8:16:32:64-S128" + +%"class.llvm::SmallVector" = type { %"class.llvm::SmallVectorImpl", [1 x %"union.llvm::SmallVectorBase::U"] } +%"class.llvm::SmallVectorImpl" = type { %"class.llvm::SmallVectorTemplateBase" } +%"class.llvm::SmallVectorTemplateBase" = type { %"class.llvm::SmallVectorTemplateCommon" } +%"class.llvm::SmallVectorTemplateCommon" = type { %"class.llvm::SmallVectorBase" } +%"class.llvm::SmallVectorBase" = type { i8*, i8*, i8*, %"union.llvm::SmallVectorBase::U" } +%"union.llvm::SmallVectorBase::U" = type { x86_fp80 } + +; Function Attrs: ssp uwtable +define void @_Z4testv() #0 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { +; CHECK: @_Z4testv() +; CHECK: invoke.cont: +; CHECK: br i1 true, label %new.notnull.i11, label %if.end.i14 +; CHECK: Retry.i10: + +entry: + %sv = alloca %"class.llvm::SmallVector", align 16 + %0 = bitcast %"class.llvm::SmallVector"* %sv to i8* + call void @llvm.lifetime.start(i64 64, i8* %0) #1 + %BeginX.i.i.i.i.i.i = getelementptr inbounds %"class.llvm::SmallVector", %"class.llvm::SmallVector"* %sv, i64 0, i32 0, i32 0, i32 0, i32 0, i32 0 + %FirstEl.i.i.i.i.i.i = getelementptr inbounds %"class.llvm::SmallVector", %"class.llvm::SmallVector"* %sv, i64 0, i32 0, i32 0, i32 0, i32 0, i32 3 + %1 = bitcast %"union.llvm::SmallVectorBase::U"* %FirstEl.i.i.i.i.i.i to i8* + store i8* %1, i8** %BeginX.i.i.i.i.i.i, align 16, !tbaa !4 + %EndX.i.i.i.i.i.i = getelementptr inbounds %"class.llvm::SmallVector", %"class.llvm::SmallVector"* %sv, i64 0, i32 0, i32 0, i32 0, i32 0, i32 1 + store i8* %1, i8** %EndX.i.i.i.i.i.i, align 8, !tbaa !4 + %CapacityX.i.i.i.i.i.i = getelementptr inbounds %"class.llvm::SmallVector", %"class.llvm::SmallVector"* %sv, i64 0, i32 0, i32 0, i32 0, i32 0, i32 2 + %add.ptr.i.i.i.i2.i.i = getelementptr inbounds %"union.llvm::SmallVectorBase::U", %"union.llvm::SmallVectorBase::U"* %FirstEl.i.i.i.i.i.i, i64 2 + %add.ptr.i.i.i.i.i.i = bitcast %"union.llvm::SmallVectorBase::U"* %add.ptr.i.i.i.i2.i.i to i8* + store i8* %add.ptr.i.i.i.i.i.i, i8** %CapacityX.i.i.i.i.i.i, align 16, !tbaa !4 + %EndX.i = getelementptr inbounds %"class.llvm::SmallVector", %"class.llvm::SmallVector"* %sv, i64 0, i32 0, i32 0, i32 0, i32 0, i32 1 + %2 = load i8*, i8** %EndX.i, align 8, !tbaa !4 + %CapacityX.i = getelementptr inbounds %"class.llvm::SmallVector", %"class.llvm::SmallVector"* %sv, i64 0, i32 0, i32 0, i32 0, i32 0, i32 2 + %cmp.i = icmp ult i8* %2, %add.ptr.i.i.i.i.i.i + br i1 %cmp.i, label %Retry.i, label %if.end.i + +Retry.i: ; preds = %.noexc, %entry + %3 = phi i8* [ %2, %entry ], [ %.pre.i, %.noexc ] + %new.isnull.i = icmp eq i8* %3, null + br i1 %new.isnull.i, label %invoke.cont, label %new.notnull.i + +new.notnull.i: ; preds = %Retry.i + %4 = bitcast i8* %3 to i32* + store i32 1, i32* %4, align 4, !tbaa !5 + br label %invoke.cont + +if.end.i: ; preds = %entry + %5 = getelementptr inbounds %"class.llvm::SmallVector", %"class.llvm::SmallVector"* %sv, i64 0, i32 0, i32 0, i32 0, i32 0 + invoke void @_ZN4llvm15SmallVectorBase8grow_podEmm(%"class.llvm::SmallVectorBase"* %5, i64 0, i64 4) + to label %.noexc unwind label %lpad + +.noexc: ; preds = %if.end.i + %.pre.i = load i8*, i8** %EndX.i, align 8, !tbaa !4 + br label %Retry.i + +invoke.cont: ; preds = %new.notnull.i, %Retry.i + %add.ptr.i = getelementptr inbounds i8, i8* %3, i64 4 + store i8* %add.ptr.i, i8** %EndX.i, align 8, !tbaa !4 + %6 = load i8*, i8** %CapacityX.i, align 16, !tbaa !4 + %cmp.i8 = icmp ult i8* %add.ptr.i, %6 + br i1 %cmp.i8, label %new.notnull.i11, label %if.end.i14 + +Retry.i10: ; preds = %if.end.i14 + %.pre.i13 = load i8*, i8** %EndX.i, align 8, !tbaa !4 + %new.isnull.i9 = icmp eq i8* %.pre.i13, null + br i1 %new.isnull.i9, label %invoke.cont2, label %new.notnull.i11 + +new.notnull.i11: ; preds = %invoke.cont, %Retry.i10 + %7 = phi i8* [ %.pre.i13, %Retry.i10 ], [ %add.ptr.i, %invoke.cont ] + %8 = bitcast i8* %7 to i32* + store i32 2, i32* %8, align 4, !tbaa !5 + br label %invoke.cont2 + +if.end.i14: ; preds = %invoke.cont + %9 = getelementptr inbounds %"class.llvm::SmallVector", %"class.llvm::SmallVector"* %sv, i64 0, i32 0, i32 0, i32 0, i32 0 + invoke void @_ZN4llvm15SmallVectorBase8grow_podEmm(%"class.llvm::SmallVectorBase"* %9, i64 0, i64 4) + to label %Retry.i10 unwind label %lpad + +invoke.cont2: ; preds = %new.notnull.i11, %Retry.i10 + %10 = phi i8* [ null, %Retry.i10 ], [ %7, %new.notnull.i11 ] + %add.ptr.i12 = getelementptr inbounds i8, i8* %10, i64 4 + store i8* %add.ptr.i12, i8** %EndX.i, align 8, !tbaa !4 + invoke void @_Z1gRN4llvm11SmallVectorIiLj8EEE(%"class.llvm::SmallVector"* %sv) + to label %invoke.cont3 unwind label %lpad + +invoke.cont3: ; preds = %invoke.cont2 + %11 = load i8*, i8** %BeginX.i.i.i.i.i.i, align 16, !tbaa !4 + %cmp.i.i.i.i19 = icmp eq i8* %11, %1 + br i1 %cmp.i.i.i.i19, label %_ZN4llvm11SmallVectorIiLj8EED1Ev.exit21, label %if.then.i.i.i20 + +if.then.i.i.i20: ; preds = %invoke.cont3 + call void @free(i8* %11) #1 + br label %_ZN4llvm11SmallVectorIiLj8EED1Ev.exit21 + +_ZN4llvm11SmallVectorIiLj8EED1Ev.exit21: ; preds = %invoke.cont3, %if.then.i.i.i20 + call void @llvm.lifetime.end(i64 64, i8* %0) #1 + ret void + +lpad: ; preds = %if.end.i14, %if.end.i, %invoke.cont2 + %12 = landingpad { i8*, i32 } + cleanup + %13 = load i8*, i8** %BeginX.i.i.i.i.i.i, align 16, !tbaa !4 + %cmp.i.i.i.i = icmp eq i8* %13, %1 + br i1 %cmp.i.i.i.i, label %eh.resume, label %if.then.i.i.i + +if.then.i.i.i: ; preds = %lpad + call void @free(i8* %13) #1 + br label %eh.resume + +eh.resume: ; preds = %if.then.i.i.i, %lpad + resume { i8*, i32 } %12 +} + +; Function Attrs: nounwind +declare void @llvm.lifetime.start(i64, i8* nocapture) #1 + +declare i32 @__gxx_personality_v0(...) + +declare void @_Z1gRN4llvm11SmallVectorIiLj8EEE(%"class.llvm::SmallVector"*) #2 + +; Function Attrs: nounwind +declare void @llvm.lifetime.end(i64, i8* nocapture) #1 + +declare void @_ZN4llvm15SmallVectorBase8grow_podEmm(%"class.llvm::SmallVectorBase"*, i64, i64) #2 + +; Function Attrs: nounwind +declare void @free(i8* nocapture) #3 + +attributes #0 = { ssp uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { nounwind } +attributes #2 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #3 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } + +!0 = !{!"any pointer", !1} +!1 = !{!"omnipotent char", !2} +!2 = !{!"Simple C/C++ TBAA"} +!3 = !{!"int", !1} +!4 = !{!0, !0, i64 0} +!5 = !{!3, !3, i64 0} diff --git a/llvm/test/Transforms/NewGVN/condprop.ll b/llvm/test/Transforms/NewGVN/condprop.ll new file mode 100644 index 00000000000..898690dec19 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/condprop.ll @@ -0,0 +1,300 @@ +; XFAIL: * +; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s + +@a = external global i32 ; <i32*> [#uses=7] + +; CHECK-LABEL: @test1( +define i32 @test1() nounwind { +entry: + %0 = load i32, i32* @a, align 4 + %1 = icmp eq i32 %0, 4 + br i1 %1, label %bb, label %bb1 + +bb: ; preds = %entry + br label %bb8 + +bb1: ; preds = %entry + %2 = load i32, i32* @a, align 4 + %3 = icmp eq i32 %2, 5 + br i1 %3, label %bb2, label %bb3 + +bb2: ; preds = %bb1 + br label %bb8 + +bb3: ; preds = %bb1 + %4 = load i32, i32* @a, align 4 + %5 = icmp eq i32 %4, 4 +; CHECK: br i1 false, label %bb4, label %bb5 + br i1 %5, label %bb4, label %bb5 + +bb4: ; preds = %bb3 + %6 = load i32, i32* @a, align 4 + %7 = add i32 %6, 5 + br label %bb8 + +bb5: ; preds = %bb3 + %8 = load i32, i32* @a, align 4 + %9 = icmp eq i32 %8, 5 +; CHECK: br i1 false, label %bb6, label %bb7 + br i1 %9, label %bb6, label %bb7 + +bb6: ; preds = %bb5 + %10 = load i32, i32* @a, align 4 + %11 = add i32 %10, 4 + br label %bb8 + +bb7: ; preds = %bb5 + %12 = load i32, i32* @a, align 4 + br label %bb8 + +bb8: ; preds = %bb7, %bb6, %bb4, %bb2, %bb + %.0 = phi i32 [ %12, %bb7 ], [ %11, %bb6 ], [ %7, %bb4 ], [ 4, %bb2 ], [ 5, %bb ] + br label %return + +return: ; preds = %bb8 + ret i32 %.0 +} + +declare void @foo(i1) +declare void @bar(i32) + +; CHECK-LABEL: @test3( +define void @test3(i32 %x, i32 %y) { + %xz = icmp eq i32 %x, 0 + %yz = icmp eq i32 %y, 0 + %z = and i1 %xz, %yz + br i1 %z, label %both_zero, label %nope +both_zero: + call void @foo(i1 %xz) +; CHECK: call void @foo(i1 true) + call void @foo(i1 %yz) +; CHECK: call void @foo(i1 true) + call void @bar(i32 %x) +; CHECK: call void @bar(i32 0) + call void @bar(i32 %y) +; CHECK: call void @bar(i32 0) + ret void +nope: + call void @foo(i1 %z) +; CHECK: call void @foo(i1 false) + ret void +} + +; CHECK-LABEL: @test4( +define void @test4(i1 %b, i32 %x) { + br i1 %b, label %sw, label %case3 +sw: + switch i32 %x, label %default [ + i32 0, label %case0 + i32 1, label %case1 + i32 2, label %case0 + i32 3, label %case3 + i32 4, label %default + ] +default: +; CHECK: default: + call void @bar(i32 %x) +; CHECK: call void @bar(i32 %x) + ret void +case0: +; CHECK: case0: + call void @bar(i32 %x) +; CHECK: call void @bar(i32 %x) + ret void +case1: +; CHECK: case1: + call void @bar(i32 %x) +; CHECK: call void @bar(i32 1) + ret void +case3: +; CHECK: case3: + call void @bar(i32 %x) +; CHECK: call void @bar(i32 %x) + ret void +} + +; CHECK-LABEL: @test5( +define i1 @test5(i32 %x, i32 %y) { + %cmp = icmp eq i32 %x, %y + br i1 %cmp, label %same, label %different + +same: + %cmp2 = icmp ne i32 %x, %y +; CHECK: ret i1 false + ret i1 %cmp2 + +different: + %cmp3 = icmp eq i32 %x, %y +; CHECK: ret i1 false + ret i1 %cmp3 +} + +; CHECK-LABEL: @test6( +define i1 @test6(i32 %x, i32 %y) { + %cmp2 = icmp ne i32 %x, %y + %cmp = icmp eq i32 %x, %y + %cmp3 = icmp eq i32 %x, %y + br i1 %cmp, label %same, label %different + +same: +; CHECK: ret i1 false + ret i1 %cmp2 + +different: +; CHECK: ret i1 false + ret i1 %cmp3 +} + +; CHECK-LABEL: @test6_fp( +define i1 @test6_fp(float %x, float %y) { + %cmp2 = fcmp une float %x, %y + %cmp = fcmp oeq float %x, %y + %cmp3 = fcmp oeq float %x, %y + br i1 %cmp, label %same, label %different + +same: +; CHECK: ret i1 false + ret i1 %cmp2 + +different: +; CHECK: ret i1 false + ret i1 %cmp3 +} + +; CHECK-LABEL: @test7( +define i1 @test7(i32 %x, i32 %y) { + %cmp = icmp sgt i32 %x, %y + br i1 %cmp, label %same, label %different + +same: + %cmp2 = icmp sle i32 %x, %y +; CHECK: ret i1 false + ret i1 %cmp2 + +different: + %cmp3 = icmp sgt i32 %x, %y +; CHECK: ret i1 false + ret i1 %cmp3 +} + +; CHECK-LABEL: @test7_fp( +define i1 @test7_fp(float %x, float %y) { + %cmp = fcmp ogt float %x, %y + br i1 %cmp, label %same, label %different + +same: + %cmp2 = fcmp ule float %x, %y +; CHECK: ret i1 false + ret i1 %cmp2 + +different: + %cmp3 = fcmp ogt float %x, %y +; CHECK: ret i1 false + ret i1 %cmp3 +} + +; CHECK-LABEL: @test8( +define i1 @test8(i32 %x, i32 %y) { + %cmp2 = icmp sle i32 %x, %y + %cmp = icmp sgt i32 %x, %y + %cmp3 = icmp sgt i32 %x, %y + br i1 %cmp, label %same, label %different + +same: +; CHECK: ret i1 false + ret i1 %cmp2 + +different: +; CHECK: ret i1 false + ret i1 %cmp3 +} + +; CHECK-LABEL: @test8_fp( +define i1 @test8_fp(float %x, float %y) { + %cmp2 = fcmp ule float %x, %y + %cmp = fcmp ogt float %x, %y + %cmp3 = fcmp ogt float %x, %y + br i1 %cmp, label %same, label %different + +same: +; CHECK: ret i1 false + ret i1 %cmp2 + +different: +; CHECK: ret i1 false + ret i1 %cmp3 +} + +; PR1768 +; CHECK-LABEL: @test9( +define i32 @test9(i32 %i, i32 %j) { + %cmp = icmp eq i32 %i, %j + br i1 %cmp, label %cond_true, label %ret + +cond_true: + %diff = sub i32 %i, %j + ret i32 %diff +; CHECK: ret i32 0 + +ret: + ret i32 5 +; CHECK: ret i32 5 +} + +; PR1768 +; CHECK-LABEL: @test10( +define i32 @test10(i32 %j, i32 %i) { + %cmp = icmp eq i32 %i, %j + br i1 %cmp, label %cond_true, label %ret + +cond_true: + %diff = sub i32 %i, %j + ret i32 %diff +; CHECK: ret i32 0 + +ret: + ret i32 5 +; CHECK: ret i32 5 +} + +declare i32 @yogibar() + +; CHECK-LABEL: @test11( +define i32 @test11(i32 %x) { + %v0 = call i32 @yogibar() + %v1 = call i32 @yogibar() + %cmp = icmp eq i32 %v0, %v1 + br i1 %cmp, label %cond_true, label %next + +cond_true: + ret i32 %v1 +; CHECK: ret i32 %v0 + +next: + %cmp2 = icmp eq i32 %x, %v0 + br i1 %cmp2, label %cond_true2, label %next2 + +cond_true2: + ret i32 %v0 +; CHECK: ret i32 %x + +next2: + ret i32 0 +} + +; CHECK-LABEL: @test12( +define i32 @test12(i32 %x) { + %cmp = icmp eq i32 %x, 0 + br i1 %cmp, label %cond_true, label %cond_false + +cond_true: + br label %ret + +cond_false: + br label %ret + +ret: + %res = phi i32 [ %x, %cond_true ], [ %x, %cond_false ] +; CHECK: %res = phi i32 [ 0, %cond_true ], [ %x, %cond_false ] + ret i32 %res +} diff --git a/llvm/test/Transforms/NewGVN/crash-no-aa.ll b/llvm/test/Transforms/NewGVN/crash-no-aa.ll new file mode 100644 index 00000000000..d511422e797 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/crash-no-aa.ll @@ -0,0 +1,15 @@ +; RUN: opt -disable-basicaa -newgvn -S < %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-unknown-freebsd8.0" + +; PR5744 +define i32 @test1({i16, i32} *%P) { + %P2 = getelementptr {i16, i32}, {i16, i32} *%P, i32 0, i32 0 + store i16 42, i16* %P2 + + %P3 = getelementptr {i16, i32}, {i16, i32} *%P, i32 0, i32 1 + %V = load i32, i32* %P3 + ret i32 %V +} + diff --git a/llvm/test/Transforms/NewGVN/crash.ll b/llvm/test/Transforms/NewGVN/crash.ll new file mode 100644 index 00000000000..9fbe281cfb6 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/crash.ll @@ -0,0 +1,201 @@ +; RUN: opt -newgvn -disable-output < %s + +; PR5631 + +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" + +define i32* @test1(i8* %name, i32 %namelen, i32* %o, i32 %expected_type) nounwind ssp { +entry: + br i1 undef, label %if.end13, label %while.body.preheader + + +if.end13: ; preds = %if.then6 + br label %while.body.preheader + +while.body.preheader: ; preds = %if.end13, %if.end + br label %while.body + +while.body: ; preds = %while.body.backedge, %while.body.preheader + %o.addr.0 = phi i32* [ undef, %while.body.preheader ], [ %o.addr.0.be, %while.body.backedge ] ; <i32*> [#uses=2] + br i1 false, label %return.loopexit, label %lor.lhs.false + +lor.lhs.false: ; preds = %while.body + %tmp20 = bitcast i32* %o.addr.0 to i32* ; <i32*> [#uses=1] + %tmp22 = load i32, i32* %tmp20 ; <i32> [#uses=0] + br i1 undef, label %land.lhs.true24, label %if.end31 + +land.lhs.true24: ; preds = %lor.lhs.false + %call28 = call i32* @parse_object(i8* undef) nounwind ; <i32*> [#uses=0] + br i1 undef, label %return.loopexit, label %if.end31 + +if.end31: ; preds = %land.lhs.true24, %lor.lhs.false + br i1 undef, label %return.loopexit, label %if.end41 + +if.end41: ; preds = %if.end31 + %tmp43 = bitcast i32* %o.addr.0 to i32* ; <i32*> [#uses=1] + %tmp45 = load i32, i32* %tmp43 ; <i32> [#uses=0] + br i1 undef, label %if.then50, label %if.else + +if.then50: ; preds = %if.end41 + %tmp53 = load i32*, i32** undef ; <i32*> [#uses=1] + br label %while.body.backedge + +if.else: ; preds = %if.end41 + br i1 undef, label %if.then62, label %if.else67 + +if.then62: ; preds = %if.else + br label %while.body.backedge + +while.body.backedge: ; preds = %if.then62, %if.then50 + %o.addr.0.be = phi i32* [ %tmp53, %if.then50 ], [ undef, %if.then62 ] ; <i32*> [#uses=1] + br label %while.body + +if.else67: ; preds = %if.else + ret i32* null + +return.loopexit: ; preds = %if.end31, %land.lhs.true24, %while.body + ret i32* undef +} + +declare i32* @parse_object(i8*) + + + + + + +%struct.attribute_spec = type { i8*, i32, i32, i8, i8, i8 } + +@attribute_tables = external global [4 x %struct.attribute_spec*] ; <[4 x %struct.attribute_spec*]*> [#uses=2] + +define void @test2() nounwind { +entry: + br label %bb69.i + +bb69.i: ; preds = %bb57.i.preheader + %tmp4 = getelementptr inbounds [4 x %struct.attribute_spec*], [4 x %struct.attribute_spec*]* @attribute_tables, i32 0, i32 undef ; <%struct.attribute_spec**> [#uses=1] + %tmp3 = load %struct.attribute_spec*, %struct.attribute_spec** %tmp4, align 4 ; <%struct.attribute_spec*> [#uses=1] + br label %bb65.i + +bb65.i: ; preds = %bb65.i.preheader, %bb64.i + %storemerge6.i = phi i32 [ 1, %bb64.i ], [ 0, %bb69.i ] ; <i32> [#uses=3] + %scevgep14 = getelementptr inbounds %struct.attribute_spec, %struct.attribute_spec* %tmp3, i32 %storemerge6.i, i32 0 ; <i8**> [#uses=1] + %tmp2 = load i8*, i8** %scevgep14, align 4 ; <i8*> [#uses=0] + %tmp = load %struct.attribute_spec*, %struct.attribute_spec** %tmp4, align 4 ; <%struct.attribute_spec*> [#uses=1] + %scevgep1516 = getelementptr inbounds %struct.attribute_spec, %struct.attribute_spec* %tmp, i32 %storemerge6.i, i32 0 ; <i8**> [#uses=0] + unreachable + +bb64.i: ; Unreachable + br label %bb65.i + +bb66.i: ; Unreachable + br label %bb69.i +} + + + +; rdar://7438974 + +@g = external global i64, align 8 + +define i32* @test3() { +do.end17.i: + %tmp18.i = load i7*, i7** undef + %tmp1 = bitcast i7* %tmp18.i to i8* + br i1 undef, label %do.body36.i, label %if.then21.i + +if.then21.i: + %tmp2 = bitcast i7* %tmp18.i to i8* + ret i32* undef + +do.body36.i: + %ivar38.i = load i64, i64* @g + %tmp3 = bitcast i7* %tmp18.i to i8* + %add.ptr39.sum.i = add i64 %ivar38.i, 8 + %tmp40.i = getelementptr inbounds i8, i8* %tmp3, i64 %add.ptr39.sum.i + %tmp4 = bitcast i8* %tmp40.i to i64* + %tmp41.i = load i64, i64* %tmp4 + br i1 undef, label %if.then48.i, label %do.body57.i + +if.then48.i: + %call54.i = call i32 @foo2() + br label %do.body57.i + +do.body57.i: + %tmp58.i = load i7*, i7** undef + %ivar59.i = load i64, i64* @g + %tmp5 = bitcast i7* %tmp58.i to i8* + %add.ptr65.sum.i = add i64 %ivar59.i, 8 + %tmp66.i = getelementptr inbounds i8, i8* %tmp5, i64 %add.ptr65.sum.i + %tmp6 = bitcast i8* %tmp66.i to i64* + %tmp67.i = load i64, i64* %tmp6 + ret i32* undef +} + +declare i32 @foo2() + + + +define i32 @test4() { +entry: + ret i32 0 + +dead: + %P2 = getelementptr i32, i32 *%P2, i32 52 + %Q2 = getelementptr i32, i32 *%Q2, i32 52 + store i32 4, i32* %P2 + %A = load i32, i32* %Q2 + br i1 true, label %dead, label %dead2 + +dead2: + ret i32 %A +} + + +; PR9841 +define fastcc i8 @test5(i8* %P) nounwind { +entry: + %0 = load i8, i8* %P, align 2 + + %Q = getelementptr i8, i8* %P, i32 1 + %1 = load i8, i8* %Q, align 1 + ret i8 %1 +} + + +; Test that a GEP in an unreachable block with the following form doesn't crash +; GVN: +; +; %x = gep %some.type %x, ... + +%struct.type = type { i64, i32, i32 } + +define fastcc void @func() nounwind uwtable ssp align 2 { +entry: + br label %reachable.bb + +;; Unreachable code. + +unreachable.bb: + %gep.val = getelementptr inbounds %struct.type, %struct.type* %gep.val, i64 1 + br i1 undef, label %u2.bb, label %u1.bb + +u1.bb: + %tmp1 = getelementptr inbounds %struct.type, %struct.type* %gep.val, i64 0, i32 0 + store i64 -1, i64* %tmp1, align 8 + br label %unreachable.bb + +u2.bb: + %0 = load i32, i32* undef, align 4 + %conv.i.i.i.i.i = zext i32 %0 to i64 + br label %u2.bb + +;; Reachable code. + +reachable.bb: + br label %r1.bb + +r1.bb: + br label %u2.bb +} diff --git a/llvm/test/Transforms/NewGVN/dbg-redundant-load.ll b/llvm/test/Transforms/NewGVN/dbg-redundant-load.ll new file mode 100644 index 00000000000..11d5bde5068 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/dbg-redundant-load.ll @@ -0,0 +1,52 @@ +; RUN: opt -newgvn -S < %s | FileCheck %s + +; Check that the redundant load from %if.then is removed. +; Also, check that the debug location associated to load %0 still refers to +; line 3 and not line 6. + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + +; CHECK: @test_redundant_load( +; CHECK-LABEL: entry: +; CHECK-NEXT: load i32, i32* %Y, align 4, !dbg ![[LOC:[0-9]+]] +; CHECK-LABEL: if.then: +; CHECK-NOT: load +; CHECK-LABEL: if.end: +; CHECK: ![[LOC]] = !DILocation(line: 3, scope: !{{.*}}) + +define i32 @test_redundant_load(i32 %X, i32* %Y) !dbg !6 { +entry: + %0 = load i32, i32* %Y, align 4, !dbg !8 + %cmp = icmp sgt i32 %X, -1, !dbg !9 + br i1 %cmp, label %if.then, label %if.end, !dbg !9 + +if.then: ; preds = %entry + %1 = load i32, i32* %Y, align 4, !dbg !10 + %add = add nsw i32 %0, %1, !dbg !10 + call void @foo(), !dbg !11 + br label %if.end, !dbg !12 + +if.end: ; preds = %if.then, %entry + %Result.0 = phi i32 [ %add, %if.then ], [ %0, %entry ] + ret i32 %Result.0, !dbg !13 +} + +declare void @foo() + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, isOptimized: false, runtimeVersion: 0, emissionKind: LineTablesOnly, enums: !2) +!1 = !DIFile(filename: "test.cpp", directory: "") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"PIC Level", i32 2} +!6 = distinct !DISubprogram(name: "test_redundant_load", scope: !1, file: !1, line: 2, type: !7, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2) +!7 = !DISubroutineType(types: !2) +!8 = !DILocation(line: 3, scope: !6) +!9 = !DILocation(line: 5, scope: !6) +!10 = !DILocation(line: 6, scope: !6) +!11 = !DILocation(line: 7, scope: !6) +!12 = !DILocation(line: 8, scope: !6) +!13 = !DILocation(line: 10, scope: !6) diff --git a/llvm/test/Transforms/NewGVN/edge.ll b/llvm/test/Transforms/NewGVN/edge.ll new file mode 100644 index 00000000000..2d453bda5a4 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/edge.ll @@ -0,0 +1,171 @@ +; XFAIL: * +; RUN: opt -newgvn -S < %s | FileCheck %s + +define i32 @f1(i32 %x) { + ; CHECK-LABEL: define i32 @f1( +bb0: + %cmp = icmp eq i32 %x, 0 + br i1 %cmp, label %bb2, label %bb1 +bb1: + br label %bb2 +bb2: + %cond = phi i32 [ %x, %bb0 ], [ 0, %bb1 ] + %foo = add i32 %cond, %x + ret i32 %foo + ; CHECK: bb2: + ; CHECK: ret i32 %x +} + +define i32 @f2(i32 %x) { + ; CHECK-LABEL: define i32 @f2( +bb0: + %cmp = icmp ne i32 %x, 0 + br i1 %cmp, label %bb1, label %bb2 +bb1: + br label %bb2 +bb2: + %cond = phi i32 [ %x, %bb0 ], [ 0, %bb1 ] + %foo = add i32 %cond, %x + ret i32 %foo + ; CHECK: bb2: + ; CHECK: ret i32 %x +} + +define i32 @f3(i32 %x) { + ; CHECK-LABEL: define i32 @f3( +bb0: + switch i32 %x, label %bb1 [ i32 0, label %bb2] +bb1: + br label %bb2 +bb2: + %cond = phi i32 [ %x, %bb0 ], [ 0, %bb1 ] + %foo = add i32 %cond, %x + ret i32 %foo + ; CHECK: bb2: + ; CHECK: ret i32 %x +} + +declare void @g(i1) +define void @f4(i8 * %x) { +; CHECK-LABEL: define void @f4( +bb0: + %y = icmp eq i8* null, %x + br i1 %y, label %bb2, label %bb1 +bb1: + br label %bb2 +bb2: + %zed = icmp eq i8* null, %x + call void @g(i1 %zed) +; CHECK: call void @g(i1 %y) + ret void +} + +define double @fcmp_oeq_not_zero(double %x, double %y) { +entry: + %cmp = fcmp oeq double %y, 2.0 + br i1 %cmp, label %if, label %return + +if: + %div = fdiv double %x, %y + br label %return + +return: + %retval = phi double [ %div, %if ], [ %x, %entry ] + ret double %retval + +; CHECK-LABEL: define double @fcmp_oeq_not_zero( +; CHECK: %div = fdiv double %x, 2.0 +} + +define double @fcmp_une_not_zero(double %x, double %y) { +entry: + %cmp = fcmp une double %y, 2.0 + br i1 %cmp, label %return, label %else + +else: + %div = fdiv double %x, %y + br label %return + +return: + %retval = phi double [ %div, %else ], [ %x, %entry ] + ret double %retval + +; CHECK-LABEL: define double @fcmp_une_not_zero( +; CHECK: %div = fdiv double %x, 2.0 +} + +; PR22376 - We can't propagate zero constants because -0.0 +; compares equal to 0.0. If %y is -0.0 in this test case, +; we would produce the wrong sign on the infinity return value. +define double @fcmp_oeq_zero(double %x, double %y) { +entry: + %cmp = fcmp oeq double %y, 0.0 + br i1 %cmp, label %if, label %return + +if: + %div = fdiv double %x, %y + br label %return + +return: + %retval = phi double [ %div, %if ], [ %x, %entry ] + ret double %retval + +; CHECK-LABEL: define double @fcmp_oeq_zero( +; CHECK: %div = fdiv double %x, %y +} + +define double @fcmp_une_zero(double %x, double %y) { +entry: + %cmp = fcmp une double %y, -0.0 + br i1 %cmp, label %return, label %else + +else: + %div = fdiv double %x, %y + br label %return + +return: + %retval = phi double [ %div, %else ], [ %x, %entry ] + ret double %retval + +; CHECK-LABEL: define double @fcmp_une_zero( +; CHECK: %div = fdiv double %x, %y +} + +; We also cannot propagate a value if it's not a constant. +; This is because the value could be 0.0 or -0.0. + +define double @fcmp_oeq_maybe_zero(double %x, double %y, double %z1, double %z2) { +entry: + %z = fadd double %z1, %z2 + %cmp = fcmp oeq double %y, %z + br i1 %cmp, label %if, label %return + +if: + %div = fdiv double %x, %z + br label %return + +return: + %retval = phi double [ %div, %if ], [ %x, %entry ] + ret double %retval + +; CHECK-LABEL: define double @fcmp_oeq_maybe_zero( +; CHECK: %div = fdiv double %x, %z +} + +define double @fcmp_une_maybe_zero(double %x, double %y, double %z1, double %z2) { +entry: + %z = fadd double %z1, %z2 + %cmp = fcmp une double %y, %z + br i1 %cmp, label %return, label %else + +else: + %div = fdiv double %x, %z + br label %return + +return: + %retval = phi double [ %div, %else ], [ %x, %entry ] + ret double %retval + +; CHECK-LABEL: define double @fcmp_une_maybe_zero( +; CHECK: %div = fdiv double %x, %z +} diff --git a/llvm/test/Transforms/NewGVN/fence.ll b/llvm/test/Transforms/NewGVN/fence.ll new file mode 100644 index 00000000000..ac4270d9ace --- /dev/null +++ b/llvm/test/Transforms/NewGVN/fence.ll @@ -0,0 +1,70 @@ +; XFAIL: * +; RUN: opt -S -basicaa -newgvn < %s | FileCheck %s + +; We can value forward across the fence since we can (semantically) +; reorder the following load before the fence. +define i32 @test(i32* %addr.i) { +; CHECK-LABEL: @test +; CHECK: store +; CHECK: fence +; CHECK-NOT: load +; CHECK: ret + store i32 5, i32* %addr.i, align 4 + fence release + %a = load i32, i32* %addr.i, align 4 + ret i32 %a +} + +; Same as above +define i32 @test2(i32* %addr.i) { +; CHECK-LABEL: @test2 +; CHECK-NEXT: fence +; CHECK-NOT: load +; CHECK: ret + %a = load i32, i32* %addr.i, align 4 + fence release + %a2 = load i32, i32* %addr.i, align 4 + %res = sub i32 %a, %a2 + ret i32 %res +} + +; We can not value forward across an acquire barrier since we might +; be syncronizing with another thread storing to the same variable +; followed by a release fence. This is not so much enforcing an +; ordering property (though it is that too), but a liveness +; property. We expect to eventually see the value of store by +; another thread when spinning on that location. +define i32 @test3(i32* noalias %addr.i, i32* noalias %otheraddr) { +; CHECK-LABEL: @test3 +; CHECK: load +; CHECK: fence +; CHECK: load +; CHECK: ret i32 %res + ; the following code is intented to model the unrolling of + ; two iterations in a spin loop of the form: + ; do { fence acquire: tmp = *%addr.i; ) while (!tmp); + ; It's hopefully clear that allowing PRE to turn this into: + ; if (!*%addr.i) while(true) {} would be unfortunate + fence acquire + %a = load i32, i32* %addr.i, align 4 + fence acquire + %a2 = load i32, i32* %addr.i, align 4 + %res = sub i32 %a, %a2 + ret i32 %res +} + +; Another example of why forwarding across an acquire fence is problematic +; can be seen in a normal locking operation. Say we had: +; *p = 5; unlock(l); lock(l); use(p); +; forwarding the store to p would be invalid. A reasonable implementation +; of unlock and lock might be: +; unlock() { atomicrmw sub %l, 1 unordered; fence release } +; lock() { +; do { +; %res = cmpxchg %p, 0, 1, monotonic monotonic +; } while(!%res.success) +; fence acquire; +; } +; Given we chose to forward across the release fence, we clearly can't forward +; across the acquire fence as well. + diff --git a/llvm/test/Transforms/NewGVN/flags.ll b/llvm/test/Transforms/NewGVN/flags.ll new file mode 100644 index 00000000000..d03edd6776c --- /dev/null +++ b/llvm/test/Transforms/NewGVN/flags.ll @@ -0,0 +1,19 @@ +; XFAIL: * +; RUN: opt -newgvn -S < %s | FileCheck %s + +declare void @use(i1) + +define void @test1(float %x, float %y) { +entry: + %cmp1 = fcmp nnan oeq float %y, %x + %cmp2 = fcmp oeq float %x, %y + call void @use(i1 %cmp1) + call void @use(i1 %cmp2) + ret void +} + +; CHECK-LABEL: define void @test1( +; CHECK: %[[cmp:.*]] = fcmp oeq float %y, %x +; CHECK-NEXT: call void @use(i1 %[[cmp]]) +; CHECK-NEXT: call void @use(i1 %[[cmp]]) +; CHECK-NEXT: ret void diff --git a/llvm/test/Transforms/NewGVN/fold-const-expr.ll b/llvm/test/Transforms/NewGVN/fold-const-expr.ll new file mode 100644 index 00000000000..8e3b39a04c9 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/fold-const-expr.ll @@ -0,0 +1,100 @@ +; XFAIL: *
+; GVN failed to do constant expression folding and expanded
+; them unfolded in many places, producing exponentially large const
+; expressions. As a result, the compilation never fisished.
+; This test checks that we are folding constant expression
+; PR 28418
+; RUN: opt -newgvn -S < %s | FileCheck %s
+
+%2 = type { i32, i32, i32, i32, i32 }
+define i32 @_Z16vector3util_mainv(i32 %x, i32 %y) {
+ %tmp1 = alloca %2, align 4
+ %tmp114 = getelementptr inbounds %2, %2* %tmp1, i64 0, i32 1
+ %tmp115 = bitcast i32* %tmp114 to <4 x i32>*
+ store <4 x i32> <i32 234567891, i32 345678912, i32 456789123, i32 0>, <4 x i32>* %tmp115, align 4
+ %tmp1683 = getelementptr inbounds %2, %2* %tmp1, i64 0, i32 1
+ %tmp1688 = load i32, i32* %tmp1683, align 4
+ %tmp1693 = shl i32 %tmp1688, 5
+ %tmp1694 = xor i32 %tmp1693, %tmp1688
+ %tmp1695 = lshr i32 %tmp1694, 7
+ %tmp1696 = xor i32 %tmp1695, %tmp1694
+ %tmp1697 = shl i32 %tmp1696, 22
+ %tmp1698 = xor i32 %tmp1697, %tmp1696
+ %tmp1707 = shl i32 %tmp1698, 5
+ %tmp1708 = xor i32 %tmp1707, %tmp1698
+ %tmp1709 = lshr i32 %tmp1708, 7
+ %tmp1710 = xor i32 %tmp1709, %tmp1708
+ %tmp1711 = shl i32 %tmp1710, 22
+ %tmp1712 = xor i32 %tmp1711, %tmp1710
+ %tmp1721 = shl i32 %tmp1712, 5
+ %tmp1722 = xor i32 %tmp1721, %tmp1712
+ %tmp1723 = lshr i32 %tmp1722, 7
+ %tmp1724 = xor i32 %tmp1723, %tmp1722
+ %tmp1725 = shl i32 %tmp1724, 22
+ %tmp1726 = xor i32 %tmp1725, %tmp1724
+ %tmp1735 = shl i32 %tmp1726, 5
+ %tmp1736 = xor i32 %tmp1735, %tmp1726
+ %tmp1737 = lshr i32 %tmp1736, 7
+ %tmp1738 = xor i32 %tmp1737, %tmp1736
+ %tmp1739 = shl i32 %tmp1738, 22
+ %tmp1740 = xor i32 %tmp1739, %tmp1738
+ store i32 %tmp1740, i32* %tmp1683, align 4
+; CHECK: store i32 310393545, i32* %tmp114, align 4
+ %tmp1756 = getelementptr inbounds %2, %2* %tmp1, i64 0, i32 1
+ %tmp1761 = load i32, i32* %tmp1756, align 4
+ %tmp1766 = shl i32 %tmp1761, 5
+ %tmp1767 = xor i32 %tmp1766, %tmp1761
+ %tmp1768 = lshr i32 %tmp1767, 7
+ %tmp1769 = xor i32 %tmp1768, %tmp1767
+ %tmp1770 = shl i32 %tmp1769, 22
+ %tmp1771 = xor i32 %tmp1770, %tmp1769
+ %tmp1780 = shl i32 %tmp1771, 5
+ %tmp1781 = xor i32 %tmp1780, %tmp1771
+ %tmp1782 = lshr i32 %tmp1781, 7
+ %tmp1783 = xor i32 %tmp1782, %tmp1781
+ %tmp1784 = shl i32 %tmp1783, 22
+ %tmp1785 = xor i32 %tmp1784, %tmp1783
+ %tmp1794 = shl i32 %tmp1785, 5
+ %tmp1795 = xor i32 %tmp1794, %tmp1785
+ %tmp1796 = lshr i32 %tmp1795, 7
+ %tmp1797 = xor i32 %tmp1796, %tmp1795
+ %tmp1798 = shl i32 %tmp1797, 22
+ %tmp1799 = xor i32 %tmp1798, %tmp1797
+ %tmp1808 = shl i32 %tmp1799, 5
+ %tmp1809 = xor i32 %tmp1808, %tmp1799
+ %tmp1810 = lshr i32 %tmp1809, 7
+ %tmp1811 = xor i32 %tmp1810, %tmp1809
+ %tmp1812 = shl i32 %tmp1811, 22
+ %tmp1813 = xor i32 %tmp1812, %tmp1811
+ store i32 %tmp1813, i32* %tmp1756, align 4
+; CHECK: store i32 -383584258, i32* %tmp114, align 4
+ %tmp2645 = getelementptr inbounds %2, %2* %tmp1, i64 0, i32 1
+ %tmp2650 = load i32, i32* %tmp2645, align 4
+ %tmp2655 = shl i32 %tmp2650, 5
+ %tmp2656 = xor i32 %tmp2655, %tmp2650
+ %tmp2657 = lshr i32 %tmp2656, 7
+ %tmp2658 = xor i32 %tmp2657, %tmp2656
+ %tmp2659 = shl i32 %tmp2658, 22
+ %tmp2660 = xor i32 %tmp2659, %tmp2658
+ %tmp2669 = shl i32 %tmp2660, 5
+ %tmp2670 = xor i32 %tmp2669, %tmp2660
+ %tmp2671 = lshr i32 %tmp2670, 7
+ %tmp2672 = xor i32 %tmp2671, %tmp2670
+ %tmp2673 = shl i32 %tmp2672, 22
+ %tmp2674 = xor i32 %tmp2673, %tmp2672
+ %tmp2683 = shl i32 %tmp2674, 5
+ %tmp2684 = xor i32 %tmp2683, %tmp2674
+ %tmp2685 = lshr i32 %tmp2684, 7
+ %tmp2686 = xor i32 %tmp2685, %tmp2684
+ %tmp2687 = shl i32 %tmp2686, 22
+ %tmp2688 = xor i32 %tmp2687, %tmp2686
+ %tmp2697 = shl i32 %tmp2688, 5
+ %tmp2698 = xor i32 %tmp2697, %tmp2688
+ %tmp2699 = lshr i32 %tmp2698, 7
+ %tmp2700 = xor i32 %tmp2699, %tmp2698
+ %tmp2701 = shl i32 %tmp2700, 22
+ %tmp2702 = xor i32 %tmp2701, %tmp2700
+ store i32 %tmp2702, i32* %tmp2645, align 4
+; CHECK: store i32 -57163022, i32* %tmp114, align 4
+ ret i32 0
+}
diff --git a/llvm/test/Transforms/NewGVN/fpmath.ll b/llvm/test/Transforms/NewGVN/fpmath.ll new file mode 100644 index 00000000000..2ff8fffe899 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/fpmath.ll @@ -0,0 +1,45 @@ +; RUN: opt -newgvn -S < %s | FileCheck %s + +define double @test1(double %x, double %y) { +; CHECK: @test1(double %x, double %y) +; CHECK: %add1 = fadd double %x, %y +; CHECK-NOT: fpmath +; CHECK: %foo = fadd double %add1, %add1 + %add1 = fadd double %x, %y, !fpmath !0 + %add2 = fadd double %x, %y + %foo = fadd double %add1, %add2 + ret double %foo +} + +define double @test2(double %x, double %y) { +; CHECK: @test2(double %x, double %y) +; CHECK: %add1 = fadd double %x, %y, !fpmath !0 +; CHECK: %foo = fadd double %add1, %add1 + %add1 = fadd double %x, %y, !fpmath !0 + %add2 = fadd double %x, %y, !fpmath !0 + %foo = fadd double %add1, %add2 + ret double %foo +} + +define double @test3(double %x, double %y) { +; CHECK: @test3(double %x, double %y) +; CHECK: %add1 = fadd double %x, %y, !fpmath !1 +; CHECK: %foo = fadd double %add1, %add1 + %add1 = fadd double %x, %y, !fpmath !1 + %add2 = fadd double %x, %y, !fpmath !0 + %foo = fadd double %add1, %add2 + ret double %foo +} + +define double @test4(double %x, double %y) { +; CHECK: @test4(double %x, double %y) +; CHECK: %add1 = fadd double %x, %y, !fpmath !1 +; CHECK: %foo = fadd double %add1, %add1 + %add1 = fadd double %x, %y, !fpmath !0 + %add2 = fadd double %x, %y, !fpmath !1 + %foo = fadd double %add1, %add2 + ret double %foo +} + +!0 = !{ float 5.0 } +!1 = !{ float 2.5 } diff --git a/llvm/test/Transforms/NewGVN/funclet.ll b/llvm/test/Transforms/NewGVN/funclet.ll new file mode 100644 index 00000000000..44cb3ae0c36 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/funclet.ll @@ -0,0 +1,44 @@ +; RUN: opt -basicaa -newgvn -S < %s | FileCheck %s +target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32" +target triple = "i686-pc-windows-msvc" + +%eh.ThrowInfo = type { i32, i8*, i8*, i8* } +%struct.A = type { i32* } + +@"_TI1?AUA@@" = external constant %eh.ThrowInfo + +define i8 @f() personality i32 (...)* @__CxxFrameHandler3 { +entry: + %b = alloca i8 + %c = alloca i8 + store i8 42, i8* %b + store i8 13, i8* %c + invoke void @_CxxThrowException(i8* %b, %eh.ThrowInfo* nonnull @"_TI1?AUA@@") + to label %unreachable unwind label %catch.dispatch + +catch.dispatch: ; preds = %entry + %cs1 = catchswitch within none [label %catch] unwind to caller + +catch: ; preds = %catch.dispatch + %catchpad = catchpad within %cs1 [i8* null, i32 64, i8* null] + store i8 5, i8* %b + catchret from %catchpad to label %try.cont + +try.cont: ; preds = %catch + %load_b = load i8, i8* %b + %load_c = load i8, i8* %c + %add = add i8 %load_b, %load_c + ret i8 %add + +unreachable: ; preds = %entry + unreachable +} +; CHECK-LABEL: define i8 @f( +; CHECK: %[[load_b:.*]] = load i8, i8* %b +; CHECK-NEXT: %[[load_c:.*]] = load i8, i8* %c +; CHECK-NEXT: %[[add:.*]] = add i8 %[[load_b]], %[[load_c]] +; CHECK-NEXT: ret i8 %[[add]] + +declare i32 @__CxxFrameHandler3(...) + +declare x86_stdcallcc void @_CxxThrowException(i8*, %eh.ThrowInfo*) diff --git a/llvm/test/Transforms/NewGVN/invariant.group.ll b/llvm/test/Transforms/NewGVN/invariant.group.ll new file mode 100644 index 00000000000..11510924e03 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/invariant.group.ll @@ -0,0 +1,338 @@ +; XFAIL: * +; RUN: opt < %s -newgvn -S | FileCheck %s + +%struct.A = type { i32 (...)** } +@_ZTV1A = available_externally unnamed_addr constant [3 x i8*] [i8* null, i8* bitcast (i8** @_ZTI1A to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A3fooEv to i8*)], align 8 +@_ZTI1A = external constant i8* + +@unknownPtr = external global i8 + +; CHECK-LABEL: define i8 @simple() { +define i8 @simple() { +entry: + %ptr = alloca i8 + store i8 42, i8* %ptr, !invariant.group !0 + call void @foo(i8* %ptr) + + %a = load i8, i8* %ptr, !invariant.group !0 + %b = load i8, i8* %ptr, !invariant.group !0 + %c = load i8, i8* %ptr, !invariant.group !0 +; CHECK: ret i8 42 + ret i8 %a +} + +; CHECK-LABEL: define i8 @optimizable1() { +define i8 @optimizable1() { +entry: + %ptr = alloca i8 + store i8 42, i8* %ptr, !invariant.group !0 + %ptr2 = call i8* @llvm.invariant.group.barrier(i8* %ptr) + %a = load i8, i8* %ptr, !invariant.group !0 + + call void @foo(i8* %ptr2); call to use %ptr2 +; CHECK: ret i8 42 + ret i8 %a +} + +; CHECK-LABEL: define i8 @optimizable2() { +define i8 @optimizable2() { +entry: + %ptr = alloca i8 + store i8 42, i8* %ptr, !invariant.group !0 + call void @foo(i8* %ptr) + + store i8 13, i8* %ptr ; can't use this store with invariant.group + %a = load i8, i8* %ptr + call void @bar(i8 %a) ; call to use %a + + call void @foo(i8* %ptr) + %b = load i8, i8* %ptr, !invariant.group !0 + +; CHECK: ret i8 42 + ret i8 %b +} + +; CHECK-LABEL: define i8 @unoptimizable1() { +define i8 @unoptimizable1() { +entry: + %ptr = alloca i8 + store i8 42, i8* %ptr + call void @foo(i8* %ptr) + %a = load i8, i8* %ptr, !invariant.group !0 +; CHECK: ret i8 %a + ret i8 %a +} + +; CHECK-LABEL: define void @indirectLoads() { +define void @indirectLoads() { +entry: + %a = alloca %struct.A*, align 8 + %0 = bitcast %struct.A** %a to i8* + + %call = call i8* @getPointer(i8* null) + %1 = bitcast i8* %call to %struct.A* + call void @_ZN1AC1Ev(%struct.A* %1) + %2 = bitcast %struct.A* %1 to i8*** + +; CHECK: %vtable = load {{.*}} !invariant.group + %vtable = load i8**, i8*** %2, align 8, !invariant.group !2 + %cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1A, i64 0, i64 2) + call void @llvm.assume(i1 %cmp.vtables) + + store %struct.A* %1, %struct.A** %a, align 8 + %3 = load %struct.A*, %struct.A** %a, align 8 + %4 = bitcast %struct.A* %3 to void (%struct.A*)*** + +; CHECK: call void @_ZN1A3fooEv( + %vtable1 = load void (%struct.A*)**, void (%struct.A*)*** %4, align 8, !invariant.group !2 + %vfn = getelementptr inbounds void (%struct.A*)*, void (%struct.A*)** %vtable1, i64 0 + %5 = load void (%struct.A*)*, void (%struct.A*)** %vfn, align 8 + call void %5(%struct.A* %3) + %6 = load %struct.A*, %struct.A** %a, align 8 + %7 = bitcast %struct.A* %6 to void (%struct.A*)*** + +; CHECK: call void @_ZN1A3fooEv( + %vtable2 = load void (%struct.A*)**, void (%struct.A*)*** %7, align 8, !invariant.group !2 + %vfn3 = getelementptr inbounds void (%struct.A*)*, void (%struct.A*)** %vtable2, i64 0 + %8 = load void (%struct.A*)*, void (%struct.A*)** %vfn3, align 8 + + call void %8(%struct.A* %6) + %9 = load %struct.A*, %struct.A** %a, align 8 + %10 = bitcast %struct.A* %9 to void (%struct.A*)*** + + %vtable4 = load void (%struct.A*)**, void (%struct.A*)*** %10, align 8, !invariant.group !2 + %vfn5 = getelementptr inbounds void (%struct.A*)*, void (%struct.A*)** %vtable4, i64 0 + %11 = load void (%struct.A*)*, void (%struct.A*)** %vfn5, align 8 +; CHECK: call void @_ZN1A3fooEv( + call void %11(%struct.A* %9) + + %vtable5 = load i8**, i8*** %2, align 8, !invariant.group !2 + %vfn6 = getelementptr inbounds i8*, i8** %vtable5, i64 0 + %12 = bitcast i8** %vfn6 to void (%struct.A*)** + %13 = load void (%struct.A*)*, void (%struct.A*)** %12, align 8 +; CHECK: call void @_ZN1A3fooEv( + call void %13(%struct.A* %9) + + ret void +} + +; CHECK-LABEL: define void @combiningBitCastWithLoad() { +define void @combiningBitCastWithLoad() { +entry: + %a = alloca %struct.A*, align 8 + %0 = bitcast %struct.A** %a to i8* + + %call = call i8* @getPointer(i8* null) + %1 = bitcast i8* %call to %struct.A* + call void @_ZN1AC1Ev(%struct.A* %1) + %2 = bitcast %struct.A* %1 to i8*** + +; CHECK: %vtable = load {{.*}} !invariant.group + %vtable = load i8**, i8*** %2, align 8, !invariant.group !2 + %cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1A, i64 0, i64 2) + + store %struct.A* %1, %struct.A** %a, align 8 +; CHECK-NOT: !invariant.group + %3 = load %struct.A*, %struct.A** %a, align 8 + %4 = bitcast %struct.A* %3 to void (%struct.A*)*** + + %vtable1 = load void (%struct.A*)**, void (%struct.A*)*** %4, align 8, !invariant.group !2 + %vfn = getelementptr inbounds void (%struct.A*)*, void (%struct.A*)** %vtable1, i64 0 + %5 = load void (%struct.A*)*, void (%struct.A*)** %vfn, align 8 + call void %5(%struct.A* %3) + + ret void +} + +; CHECK-LABEL:define void @loadCombine() { +define void @loadCombine() { +enter: + %ptr = alloca i8 + store i8 42, i8* %ptr + call void @foo(i8* %ptr) +; CHECK: %[[A:.*]] = load i8, i8* %ptr, !invariant.group + %a = load i8, i8* %ptr, !invariant.group !0 +; CHECK-NOT: load + %b = load i8, i8* %ptr, !invariant.group !1 +; CHECK: call void @bar(i8 %[[A]]) + call void @bar(i8 %a) +; CHECK: call void @bar(i8 %[[A]]) + call void @bar(i8 %b) + ret void +} + +; CHECK-LABEL: define void @loadCombine1() { +define void @loadCombine1() { +enter: + %ptr = alloca i8 + store i8 42, i8* %ptr + call void @foo(i8* %ptr) +; CHECK: %[[D:.*]] = load i8, i8* %ptr, !invariant.group + %c = load i8, i8* %ptr +; CHECK-NOT: load + %d = load i8, i8* %ptr, !invariant.group !1 +; CHECK: call void @bar(i8 %[[D]]) + call void @bar(i8 %c) +; CHECK: call void @bar(i8 %[[D]]) + call void @bar(i8 %d) + ret void +} + +; CHECK-LABEL: define void @loadCombine2() { +define void @loadCombine2() { +enter: + %ptr = alloca i8 + store i8 42, i8* %ptr + call void @foo(i8* %ptr) +; CHECK: %[[E:.*]] = load i8, i8* %ptr, !invariant.group + %e = load i8, i8* %ptr, !invariant.group !1 +; CHECK-NOT: load + %f = load i8, i8* %ptr +; CHECK: call void @bar(i8 %[[E]]) + call void @bar(i8 %e) +; CHECK: call void @bar(i8 %[[E]]) + call void @bar(i8 %f) + ret void +} + +; CHECK-LABEL: define void @loadCombine3() { +define void @loadCombine3() { +enter: + %ptr = alloca i8 + store i8 42, i8* %ptr + call void @foo(i8* %ptr) +; CHECK: %[[E:.*]] = load i8, i8* %ptr, !invariant.group ![[OneMD:[0-9]]] + %e = load i8, i8* %ptr, !invariant.group !1 +; CHECK-NOT: load + %f = load i8, i8* %ptr, !invariant.group !1 +; CHECK: call void @bar(i8 %[[E]]) + call void @bar(i8 %e) +; CHECK: call void @bar(i8 %[[E]]) + call void @bar(i8 %f) + ret void +} + +; CHECK-LABEL: define i8 @unoptimizable2() { +define i8 @unoptimizable2() { +entry: + %ptr = alloca i8 + store i8 42, i8* %ptr + call void @foo(i8* %ptr) + %a = load i8, i8* %ptr + call void @foo(i8* %ptr) + %b = load i8, i8* %ptr, !invariant.group !0 + +; CHECK: ret i8 %a + ret i8 %a +} + +; CHECK-LABEL: define i8 @unoptimizable3() { +define i8 @unoptimizable3() { +entry: + %ptr = alloca i8 + store i8 42, i8* %ptr, !invariant.group !0 + %ptr2 = call i8* @getPointer(i8* %ptr) + %a = load i8, i8* %ptr2, !invariant.group !0 + +; CHECK: ret i8 %a + ret i8 %a +} + +; CHECK-LABEL: define i8 @unoptimizable4() { +define i8 @unoptimizable4() { +entry: + %ptr = alloca i8 + store i8 42, i8* %ptr, !invariant.group !0 + %ptr2 = call i8* @llvm.invariant.group.barrier(i8* %ptr) + %a = load i8, i8* %ptr2, !invariant.group !0 + +; CHECK: ret i8 %a + ret i8 %a +} + +; CHECK-LABEL: define i8 @volatile1() { +define i8 @volatile1() { +entry: + %ptr = alloca i8 + store i8 42, i8* %ptr, !invariant.group !0 + call void @foo(i8* %ptr) + %a = load i8, i8* %ptr, !invariant.group !0 + %b = load volatile i8, i8* %ptr +; CHECK: call void @bar(i8 %b) + call void @bar(i8 %b) + + %c = load volatile i8, i8* %ptr, !invariant.group !0 +; FIXME: we could change %c to 42, preserving volatile load +; CHECK: call void @bar(i8 %c) + call void @bar(i8 %c) +; CHECK: ret i8 42 + ret i8 %a +} + +; CHECK-LABEL: define i8 @volatile2() { +define i8 @volatile2() { +entry: + %ptr = alloca i8 + store i8 42, i8* %ptr, !invariant.group !0 + call void @foo(i8* %ptr) + %a = load i8, i8* %ptr, !invariant.group !0 + %b = load volatile i8, i8* %ptr +; CHECK: call void @bar(i8 %b) + call void @bar(i8 %b) + + %c = load volatile i8, i8* %ptr, !invariant.group !0 +; FIXME: we could change %c to 42, preserving volatile load +; CHECK: call void @bar(i8 %c) + call void @bar(i8 %c) +; CHECK: ret i8 42 + ret i8 %a +} + +; CHECK-LABEL: define i8 @fun() { +define i8 @fun() { +entry: + %ptr = alloca i8 + store i8 42, i8* %ptr, !invariant.group !0 + call void @foo(i8* %ptr) + + %a = load i8, i8* %ptr, !invariant.group !0 ; Can assume that value under %ptr didn't change +; CHECK: call void @bar(i8 42) + call void @bar(i8 %a) + + call void @foo(i8* %ptr) + %b = load i8, i8* %ptr, !invariant.group !1 ; Can't assume anything, because group changed +; CHECK: call void @bar(i8 %b) + call void @bar(i8 %b) + + %newPtr = call i8* @getPointer(i8* %ptr) + %c = load i8, i8* %newPtr, !invariant.group !0 ; Can't assume anything, because we only have information about %ptr +; CHECK: call void @bar(i8 %c) + call void @bar(i8 %c) + + %unknownValue = load i8, i8* @unknownPtr +; FIXME: Can assume that %unknownValue == 42 +; CHECK: store i8 %unknownValue, i8* %ptr, !invariant.group !0 + store i8 %unknownValue, i8* %ptr, !invariant.group !0 + + %newPtr2 = call i8* @llvm.invariant.group.barrier(i8* %ptr) + %d = load i8, i8* %newPtr2, !invariant.group !0 ; Can't step through invariant.group.barrier to get value of %ptr +; CHECK: ret i8 %d + ret i8 %d +} + +declare void @foo(i8*) +declare void @bar(i8) +declare i8* @getPointer(i8*) +declare void @_ZN1A3fooEv(%struct.A*) +declare void @_ZN1AC1Ev(%struct.A*) +declare i8* @llvm.invariant.group.barrier(i8*) + +; Function Attrs: nounwind +declare void @llvm.assume(i1 %cmp.vtables) #0 + + +attributes #0 = { nounwind } +; CHECK: ![[OneMD]] = !{!"other ptr"} +!0 = !{!"magic ptr"} +!1 = !{!"other ptr"} +!2 = !{!"vtable_of_a"} diff --git a/llvm/test/Transforms/NewGVN/invariant.start.ll b/llvm/test/Transforms/NewGVN/invariant.start.ll new file mode 100644 index 00000000000..69c89011806 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/invariant.start.ll @@ -0,0 +1,59 @@ +; Test to make sure llvm.invariant.start calls are not treated as clobbers. +; RUN: opt < %s -newgvn -S | FileCheck %s + + +declare {}* @llvm.invariant.start.p0i8(i64, i8* nocapture) nounwind readonly +declare void @llvm.invariant.end.p0i8({}*, i64, i8* nocapture) nounwind + +; We forward store to the load across the invariant.start intrinsic +define i8 @forward_store() { +; CHECK-LABEL: @forward_store +; CHECK: call {}* @llvm.invariant.start.p0i8(i64 1, i8* %a) +; CHECK-NOT: load +; CHECK: ret i8 0 + %a = alloca i8 + store i8 0, i8* %a + %i = call {}* @llvm.invariant.start.p0i8(i64 1, i8* %a) + %r = load i8, i8* %a + ret i8 %r +} + +declare i8 @dummy(i8* nocapture) nounwind readonly + +; We forward store to the load in the non-local analysis case, +; i.e. invariant.start is in another basic block. +define i8 @forward_store_nonlocal(i1 %cond) { +; CHECK-LABEL: forward_store_nonlocal +; CHECK: call {}* @llvm.invariant.start.p0i8(i64 1, i8* %a) +; CHECK: ret i8 0 +; CHECK: ret i8 %val + %a = alloca i8 + store i8 0, i8* %a + %i = call {}* @llvm.invariant.start.p0i8(i64 1, i8* %a) + br i1 %cond, label %loadblock, label %exit + +loadblock: + %r = load i8, i8* %a + ret i8 %r + +exit: + %val = call i8 @dummy(i8* %a) + ret i8 %val +} + +; We should not value forward %foo to the invariant.end corresponding to %bar. +define i8 @forward_store1() { +; CHECK-LABEL: forward_store1 +; CHECK: %foo = call {}* @llvm.invariant.start.p0i8 +; CHECK-NOT: load +; CHECK: %bar = call {}* @llvm.invariant.start.p0i8 +; CHECK: call void @llvm.invariant.end.p0i8({}* %bar, i64 1, i8* %a) +; CHECK: ret i8 0 + %a = alloca i8 + store i8 0, i8* %a + %foo = call {}* @llvm.invariant.start.p0i8(i64 1, i8* %a) + %r = load i8, i8* %a + %bar = call {}* @llvm.invariant.start.p0i8(i64 1, i8* %a) + call void @llvm.invariant.end.p0i8({}* %bar, i64 1, i8* %a) + ret i8 %r +} diff --git a/llvm/test/Transforms/NewGVN/lifetime-simple.ll b/llvm/test/Transforms/NewGVN/lifetime-simple.ll new file mode 100644 index 00000000000..63e361c49eb --- /dev/null +++ b/llvm/test/Transforms/NewGVN/lifetime-simple.ll @@ -0,0 +1,20 @@ +; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s + +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" +target triple = "i386-apple-darwin7" + +define i8 @test(i8* %P) nounwind { +; CHECK: lifetime.start +; CHECK-NOT: load +; CHECK: lifetime.end +entry: + call void @llvm.lifetime.start(i64 32, i8* %P) + %0 = load i8, i8* %P + store i8 1, i8* %P + call void @llvm.lifetime.end(i64 32, i8* %P) + %1 = load i8, i8* %P + ret i8 %1 +} + +declare void @llvm.lifetime.start(i64 %S, i8* nocapture %P) readonly +declare void @llvm.lifetime.end(i64 %S, i8* nocapture %P) diff --git a/llvm/test/Transforms/NewGVN/load-constant-mem.ll b/llvm/test/Transforms/NewGVN/load-constant-mem.ll new file mode 100644 index 00000000000..215258b934c --- /dev/null +++ b/llvm/test/Transforms/NewGVN/load-constant-mem.ll @@ -0,0 +1,19 @@ +; RUN: opt < %s -basicaa -newgvn -instcombine -S | FileCheck %s +; PR4189 +@G = external constant [4 x i32] + +define i32 @test(i8* %p, i32 %i) nounwind { +entry: + %P = getelementptr [4 x i32], [4 x i32]* @G, i32 0, i32 %i + %A = load i32, i32* %P + store i8 4, i8* %p + %B = load i32, i32* %P + %C = sub i32 %A, %B + ret i32 %C +} + +; CHECK: define i32 @test(i8* %p, i32 %i) #0 { +; CHECK-NEXT: entry: +; CHECK-NEXT: store i8 4, i8* %p, align 1 +; CHECK-NEXT: ret i32 0 +; CHECK-NEXT: } diff --git a/llvm/test/Transforms/NewGVN/load-from-unreachable-predecessor.ll b/llvm/test/Transforms/NewGVN/load-from-unreachable-predecessor.ll new file mode 100644 index 00000000000..2098c905ce9 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/load-from-unreachable-predecessor.ll @@ -0,0 +1,20 @@ +; RUN: opt -newgvn -S < %s | FileCheck %s + +; Check that an unreachable predecessor to a PHI node doesn't cause a crash. +; PR21625. + +define i32 @f(i32** %f) { +; CHECK: bb0: +; Load should be removed, since it's ignored. +; CHECK-NEXT: br label +bb0: + %bar = load i32*, i32** %f + br label %bb2 +bb1: + %zed = load i32*, i32** %f + br i1 false, label %bb1, label %bb2 +bb2: + %foo = phi i32* [ null, %bb0 ], [ %zed, %bb1 ] + %storemerge = load i32, i32* %foo + ret i32 %storemerge +} diff --git a/llvm/test/Transforms/NewGVN/malloc-load-removal.ll b/llvm/test/Transforms/NewGVN/malloc-load-removal.ll new file mode 100644 index 00000000000..c91b6e17f79 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/malloc-load-removal.ll @@ -0,0 +1,57 @@ +; XFAIL: * +; RUN: opt -S -basicaa -newgvn < %s | FileCheck %s +; RUN: opt -S -basicaa -newgvn -disable-simplify-libcalls < %s | FileCheck %s -check-prefix=CHECK_NO_LIBCALLS +; PR13694 + +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-S128" +target triple = "x86_64-apple-macosx10.8.0" + +declare i8* @malloc(i64) nounwind + +define noalias i8* @test1() nounwind uwtable ssp { +entry: + %call = tail call i8* @malloc(i64 100) nounwind + %0 = load i8, i8* %call, align 1 + %tobool = icmp eq i8 %0, 0 + br i1 %tobool, label %if.end, label %if.then + +if.then: ; preds = %entry + store i8 0, i8* %call, align 1 + br label %if.end + +if.end: ; preds = %if.then, %entry + ret i8* %call + +; CHECK-LABEL: @test1( +; CHECK-NOT: load +; CHECK-NOT: icmp + +; CHECK_NO_LIBCALLS-LABEL: @test1( +; CHECK_NO_LIBCALLS: load +; CHECK_NO_LIBCALLS: icmp +} + +declare i8* @_Znwm(i64) nounwind + +define noalias i8* @test2() nounwind uwtable ssp { +entry: + %call = tail call i8* @_Znwm(i64 100) nounwind + %0 = load i8, i8* %call, align 1 + %tobool = icmp eq i8 %0, 0 + br i1 %tobool, label %if.end, label %if.then + +if.then: ; preds = %entry + store i8 0, i8* %call, align 1 + br label %if.end + +if.end: ; preds = %if.then, %entry + ret i8* %call + +; CHECK-LABEL: @test2( +; CHECK-NOT: load +; CHECK-NOT: icmp + +; CHECK_NO_LIBCALLS-LABEL: @test2( +; CHECK_NO_LIBCALLS: load +; CHECK_NO_LIBCALLS: icmp +} diff --git a/llvm/test/Transforms/NewGVN/no_speculative_loads_with_asan.ll b/llvm/test/Transforms/NewGVN/no_speculative_loads_with_asan.ll new file mode 100644 index 00000000000..a83d7b62d39 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/no_speculative_loads_with_asan.ll @@ -0,0 +1,55 @@ +; RUN: opt -O3 -S %s | FileCheck %s +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +declare noalias i8* @_Znam(i64) #1 + +define i32 @TestNoAsan() { + %1 = tail call noalias i8* @_Znam(i64 2) + %2 = getelementptr inbounds i8, i8* %1, i64 1 + store i8 0, i8* %2, align 1 + store i8 0, i8* %1, align 1 + %3 = bitcast i8* %1 to i16* + %4 = load i16, i16* %3, align 4 + %5 = icmp eq i16 %4, 0 + br i1 %5, label %11, label %6 + +; <label>:6 ; preds = %0 + %7 = getelementptr inbounds i8, i8* %1, i64 2 + %8 = bitcast i8* %7 to i16* + %9 = load i16, i16* %8, align 2 + %10 = sext i16 %9 to i32 + br label %11 + +; <label>:11 ; preds = %0, %6 + %12 = phi i32 [ %10, %6 ], [ 0, %0 ] + ret i32 %12 +} + +; CHECK-LABEL: @TestNoAsan +; CHECK: ret i32 0 + +define i32 @TestAsan() sanitize_address { + %1 = tail call noalias i8* @_Znam(i64 2) + %2 = getelementptr inbounds i8, i8* %1, i64 1 + store i8 0, i8* %2, align 1 + store i8 0, i8* %1, align 1 + %3 = bitcast i8* %1 to i16* + %4 = load i16, i16* %3, align 4 + %5 = icmp eq i16 %4, 0 + br i1 %5, label %11, label %6 + +; <label>:6 ; preds = %0 + %7 = getelementptr inbounds i8, i8* %1, i64 2 + %8 = bitcast i8* %7 to i16* + %9 = load i16, i16* %8, align 2 + %10 = sext i16 %9 to i32 + br label %11 + +; <label>:11 ; preds = %0, %6 + %12 = phi i32 [ %10, %6 ], [ 0, %0 ] + ret i32 %12 +} + +; CHECK-LABEL: @TestAsan +; CHECK-NOT: %[[LOAD:[^ ]+]] = load i32 +; CHECK: {{.*}} = phi + diff --git a/llvm/test/Transforms/NewGVN/noalias.ll b/llvm/test/Transforms/NewGVN/noalias.ll new file mode 100644 index 00000000000..8823ec6a65b --- /dev/null +++ b/llvm/test/Transforms/NewGVN/noalias.ll @@ -0,0 +1,43 @@ +; RUN: opt -scoped-noalias -basicaa -newgvn -S < %s | FileCheck %s + +define i32 @test1(i32* %p, i32* %q) { +; CHECK-LABEL: @test1(i32* %p, i32* %q) +; CHECK: load i32, i32* %p +; CHECK-NOT: noalias +; CHECK: %c = add i32 %a, %a + %a = load i32, i32* %p, !noalias !0 + %b = load i32, i32* %p + %c = add i32 %a, %b + ret i32 %c +} + +define i32 @test2(i32* %p, i32* %q) { +; CHECK-LABEL: @test2(i32* %p, i32* %q) +; CHECK: load i32, i32* %p, !alias.scope !0 +; CHECK: %c = add i32 %a, %a + %a = load i32, i32* %p, !alias.scope !0 + %b = load i32, i32* %p, !alias.scope !0 + %c = add i32 %a, %b + ret i32 %c +} + +; FIXME: In this case we can do better than intersecting the scopes, and can +; concatenate them instead. Both loads are in the same basic block, the first +; makes the second safe to speculatively execute, and there are no calls that may +; throw in between. +define i32 @test3(i32* %p, i32* %q) { +; CHECK-LABEL: @test3(i32* %p, i32* %q) +; CHECK: load i32, i32* %p, !alias.scope !1 +; CHECK: %c = add i32 %a, %a + %a = load i32, i32* %p, !alias.scope !1 + %b = load i32, i32* %p, !alias.scope !2 + %c = add i32 %a, %b + ret i32 %c +} + +declare i32 @foo(i32*) readonly + +!0 = !{!0} +!1 = !{!1} +!2 = !{!0, !1} + diff --git a/llvm/test/Transforms/NewGVN/non-local-offset.ll b/llvm/test/Transforms/NewGVN/non-local-offset.ll new file mode 100644 index 00000000000..4a934127e7c --- /dev/null +++ b/llvm/test/Transforms/NewGVN/non-local-offset.ll @@ -0,0 +1,59 @@ +; RUN: opt -basicaa -newgvn -S < %s | FileCheck %s + +target datalayout = "e-p:64:64:64" + +; GVN should ignore the store to p[1] to see that the load from p[0] is +; fully redundant. + +; CHECK-LABEL: @yes( +; CHECK: if.then: +; CHECK-NEXT: store i32 0, i32* %q +; CHECK-NEXT: ret void + +define void @yes(i1 %c, i32* %p, i32* %q) nounwind { +entry: + store i32 0, i32* %p + %p1 = getelementptr inbounds i32, i32* %p, i64 1 + store i32 1, i32* %p1 + br i1 %c, label %if.else, label %if.then + +if.then: + %t = load i32, i32* %p + store i32 %t, i32* %q + ret void + +if.else: + ret void +} + +; GVN should ignore the store to p[1] to see that the first load from p[0] is +; fully redundant. However, the second load is larger, so it's not a simple +; redundancy. + +; CHECK-LABEL: @watch_out_for_size_change( +; CHECK: if.then: +; CHECK-NEXT: store i32 0, i32* %q +; CHECK-NEXT: ret void +; CHECK: if.else: +; CHECK: load i64, i64* %pc +; CHECK: store i64 + +define void @watch_out_for_size_change(i1 %c, i32* %p, i32* %q) nounwind { +entry: + store i32 0, i32* %p + %p1 = getelementptr inbounds i32, i32* %p, i64 1 + store i32 1, i32* %p1 + br i1 %c, label %if.else, label %if.then + +if.then: + %t = load i32, i32* %p + store i32 %t, i32* %q + ret void + +if.else: + %pc = bitcast i32* %p to i64* + %qc = bitcast i32* %q to i64* + %t64 = load i64, i64* %pc + store i64 %t64, i64* %qc + ret void +} diff --git a/llvm/test/Transforms/NewGVN/nonescaping-malloc.ll b/llvm/test/Transforms/NewGVN/nonescaping-malloc.ll new file mode 100644 index 00000000000..27d93e270d3 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/nonescaping-malloc.ll @@ -0,0 +1,112 @@ +; XFAIL: * +; REQUIRES: asserts +; RUN: opt < %s -basicaa -newgvn -stats -disable-output 2>&1 | FileCheck %s +; rdar://7363102 + +; CHECK: Number of loads deleted + +; GVN should be able to eliminate load %tmp22.i, because it is redundant with +; load %tmp8.i. This requires being able to prove that %tmp7.i doesn't +; alias the malloc'd value %tmp.i20.i.i, which it can do since %tmp7.i +; is derived from %tmp5.i which is computed from a load, and %tmp.i20.i.i +; is never stored and does not escape. + +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" +target triple = "x86_64-apple-darwin10.0" + +%"struct.llvm::MallocAllocator" = type <{ i8 }> +%"struct.llvm::StringMap<void*,llvm::MallocAllocator>" = type { %"struct.llvm::StringMapImpl", %"struct.llvm::MallocAllocator" } +%"struct.llvm::StringMapEntry<void*>" = type { %"struct.llvm::StringMapEntryBase", i8* } +%"struct.llvm::StringMapEntryBase" = type { i32 } +%"struct.llvm::StringMapImpl" = type { %"struct.llvm::StringMapImpl::ItemBucket"*, i32, i32, i32, i32 } +%"struct.llvm::StringMapImpl::ItemBucket" = type { i32, %"struct.llvm::StringMapEntryBase"* } +%"struct.llvm::StringRef" = type { i8*, i64 } + +define %"struct.llvm::StringMapEntry<void*>"* @_Z3fooRN4llvm9StringMapIPvNS_15MallocAllocatorEEEPKc(%"struct.llvm::StringMap<void*,llvm::MallocAllocator>"* %X, i8* %P) ssp { +entry: + %tmp = alloca %"struct.llvm::StringRef", align 8 + %tmp.i = getelementptr inbounds %"struct.llvm::StringRef", %"struct.llvm::StringRef"* %tmp, i64 0, i32 0 + store i8* %P, i8** %tmp.i, align 8 + %tmp1.i = call i64 @strlen(i8* %P) nounwind readonly + %tmp2.i = getelementptr inbounds %"struct.llvm::StringRef", %"struct.llvm::StringRef"* %tmp, i64 0, i32 1 + store i64 %tmp1.i, i64* %tmp2.i, align 8 + %tmp1 = call %"struct.llvm::StringMapEntry<void*>"* @_ZN4llvm9StringMapIPvNS_15MallocAllocatorEE16GetOrCreateValueERKNS_9StringRefE(%"struct.llvm::StringMap<void*,llvm::MallocAllocator>"* %X, %"struct.llvm::StringRef"* %tmp) ssp + ret %"struct.llvm::StringMapEntry<void*>"* %tmp1 +} + +declare i64 @strlen(i8* nocapture) nounwind readonly + +declare noalias i8* @malloc(i64) nounwind + +declare i32 @_ZN4llvm13StringMapImpl15LookupBucketForENS_9StringRefE(%"struct.llvm::StringMapImpl"*, i64, i64) + +define linkonce_odr %"struct.llvm::StringMapEntry<void*>"* @_ZN4llvm9StringMapIPvNS_15MallocAllocatorEE16GetOrCreateValueERKNS_9StringRefE(%"struct.llvm::StringMap<void*,llvm::MallocAllocator>"* %this, %"struct.llvm::StringRef"* nocapture %Key) ssp align 2 { +entry: + %elt = bitcast %"struct.llvm::StringRef"* %Key to i64* + %val = load i64, i64* %elt + %tmp = getelementptr inbounds %"struct.llvm::StringRef", %"struct.llvm::StringRef"* %Key, i64 0, i32 1 + %val2 = load i64, i64* %tmp + %tmp2.i = getelementptr inbounds %"struct.llvm::StringMap<void*,llvm::MallocAllocator>", %"struct.llvm::StringMap<void*,llvm::MallocAllocator>"* %this, i64 0, i32 0 + %tmp3.i = tail call i32 @_ZN4llvm13StringMapImpl15LookupBucketForENS_9StringRefE(%"struct.llvm::StringMapImpl"* %tmp2.i, i64 %val, i64 %val2) + %tmp4.i = getelementptr inbounds %"struct.llvm::StringMap<void*,llvm::MallocAllocator>", %"struct.llvm::StringMap<void*,llvm::MallocAllocator>"* %this, i64 0, i32 0, i32 0 + %tmp5.i = load %"struct.llvm::StringMapImpl::ItemBucket"*, %"struct.llvm::StringMapImpl::ItemBucket"** %tmp4.i, align 8 + %tmp6.i = zext i32 %tmp3.i to i64 + %tmp7.i = getelementptr inbounds %"struct.llvm::StringMapImpl::ItemBucket", %"struct.llvm::StringMapImpl::ItemBucket"* %tmp5.i, i64 %tmp6.i, i32 1 + %tmp8.i = load %"struct.llvm::StringMapEntryBase"*, %"struct.llvm::StringMapEntryBase"** %tmp7.i, align 8 + %tmp9.i = icmp eq %"struct.llvm::StringMapEntryBase"* %tmp8.i, null + %tmp13.i = icmp eq %"struct.llvm::StringMapEntryBase"* %tmp8.i, inttoptr (i64 -1 to %"struct.llvm::StringMapEntryBase"*) + %or.cond.i = or i1 %tmp9.i, %tmp13.i + br i1 %or.cond.i, label %bb4.i, label %bb6.i + +bb4.i: ; preds = %entry + %tmp41.i = inttoptr i64 %val to i8* + %tmp4.i35.i = getelementptr inbounds i8, i8* %tmp41.i, i64 %val2 + %tmp.i.i = ptrtoint i8* %tmp4.i35.i to i64 + %tmp1.i.i = trunc i64 %tmp.i.i to i32 + %tmp3.i.i = trunc i64 %val to i32 + %tmp4.i.i = sub i32 %tmp1.i.i, %tmp3.i.i + %tmp5.i.i = add i32 %tmp4.i.i, 17 + %tmp8.i.i = zext i32 %tmp5.i.i to i64 + %tmp.i20.i.i = tail call noalias i8* @malloc(i64 %tmp8.i.i) nounwind + %tmp10.i.i = bitcast i8* %tmp.i20.i.i to %"struct.llvm::StringMapEntry<void*>"* + %tmp12.i.i = icmp eq i8* %tmp.i20.i.i, null + br i1 %tmp12.i.i, label %_ZN4llvm14StringMapEntryIPvE6CreateINS_15MallocAllocatorES1_EEPS2_PKcS7_RT_T0_.exit.i, label %bb.i.i + +bb.i.i: ; preds = %bb4.i + %tmp.i.i.i.i = bitcast i8* %tmp.i20.i.i to i32* + store i32 %tmp4.i.i, i32* %tmp.i.i.i.i, align 4 + %tmp1.i19.i.i = getelementptr inbounds i8, i8* %tmp.i20.i.i, i64 8 + %0 = bitcast i8* %tmp1.i19.i.i to i8** + store i8* null, i8** %0, align 8 + br label %_ZN4llvm14StringMapEntryIPvE6CreateINS_15MallocAllocatorES1_EEPS2_PKcS7_RT_T0_.exit.i + +_ZN4llvm14StringMapEntryIPvE6CreateINS_15MallocAllocatorES1_EEPS2_PKcS7_RT_T0_.exit.i: ; preds = %bb.i.i, %bb4.i + %tmp.i18.i.i = getelementptr inbounds i8, i8* %tmp.i20.i.i, i64 16 + %tmp15.i.i = zext i32 %tmp4.i.i to i64 + tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %tmp.i18.i.i, i8* %tmp41.i, i64 %tmp15.i.i, i32 1, i1 false) + %tmp.i18.sum.i.i = add i64 %tmp15.i.i, 16 + %tmp17.i.i = getelementptr inbounds i8, i8* %tmp.i20.i.i, i64 %tmp.i18.sum.i.i + store i8 0, i8* %tmp17.i.i, align 1 + %tmp.i.i.i = getelementptr inbounds i8, i8* %tmp.i20.i.i, i64 8 + %1 = bitcast i8* %tmp.i.i.i to i8** + store i8* null, i8** %1, align 8 + %tmp22.i = load %"struct.llvm::StringMapEntryBase"*, %"struct.llvm::StringMapEntryBase"** %tmp7.i, align 8 + %tmp24.i = icmp eq %"struct.llvm::StringMapEntryBase"* %tmp22.i, inttoptr (i64 -1 to %"struct.llvm::StringMapEntryBase"*) + br i1 %tmp24.i, label %bb9.i, label %_ZN4llvm9StringMapIPvNS_15MallocAllocatorEE16GetOrCreateValueIS1_EERNS_14StringMapEntryIS1_EENS_9StringRefET_.exit + +bb6.i: ; preds = %entry + %tmp16.i = bitcast %"struct.llvm::StringMapEntryBase"* %tmp8.i to %"struct.llvm::StringMapEntry<void*>"* + ret %"struct.llvm::StringMapEntry<void*>"* %tmp16.i + +bb9.i: ; preds = %_ZN4llvm14StringMapEntryIPvE6CreateINS_15MallocAllocatorES1_EEPS2_PKcS7_RT_T0_.exit.i + %tmp25.i = getelementptr inbounds %"struct.llvm::StringMap<void*,llvm::MallocAllocator>", %"struct.llvm::StringMap<void*,llvm::MallocAllocator>"* %this, i64 0, i32 0, i32 3 + %tmp26.i = load i32, i32* %tmp25.i, align 8 + %tmp27.i = add i32 %tmp26.i, -1 + store i32 %tmp27.i, i32* %tmp25.i, align 8 + ret %"struct.llvm::StringMapEntry<void*>"* %tmp10.i.i + +_ZN4llvm9StringMapIPvNS_15MallocAllocatorEE16GetOrCreateValueIS1_EERNS_14StringMapEntryIS1_EENS_9StringRefET_.exit: ; preds = %_ZN4llvm14StringMapEntryIPvE6CreateINS_15MallocAllocatorES1_EEPS2_PKcS7_RT_T0_.exit.i + ret %"struct.llvm::StringMapEntry<void*>"* %tmp10.i.i +} + +declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i32, i1) nounwind diff --git a/llvm/test/Transforms/NewGVN/null-aliases-nothing.ll b/llvm/test/Transforms/NewGVN/null-aliases-nothing.ll new file mode 100644 index 00000000000..801832bf041 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/null-aliases-nothing.ll @@ -0,0 +1,20 @@ +; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s + +%t = type { i32 } +declare void @test1f(i8*) + +define void @test1(%t* noalias %stuff ) { + %p = getelementptr inbounds %t, %t* %stuff, i32 0, i32 0 + %before = load i32, i32* %p + + call void @test1f(i8* null) + + %after = load i32, i32* %p ; <--- This should be a dead load + %sum = add i32 %before, %after + + store i32 %sum, i32* %p + ret void +; CHECK: load +; CHECK-NOT: load +; CHECK: ret void +} diff --git a/llvm/test/Transforms/NewGVN/opt-remarks.ll b/llvm/test/Transforms/NewGVN/opt-remarks.ll new file mode 100644 index 00000000000..528b4545288 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/opt-remarks.ll @@ -0,0 +1,109 @@ +; XFAIL: * +; RUN: opt < %s -newgvn -o /dev/null -pass-remarks-output=%t -S -pass-remarks=gvn \ +; RUN: 2>&1 | FileCheck %s +; RUN: cat %t | FileCheck -check-prefix=YAML %s + +; CHECK: remark: <unknown>:0:0: load of type i32 eliminated{{$}} +; CHECK-NEXT: remark: <unknown>:0:0: load of type i32 eliminated{{$}} +; CHECK-NEXT: remark: <unknown>:0:0: load of type i32 eliminated{{$}} +; CHECK-NOT: remark: + +; YAML: --- !Passed +; YAML-NEXT: Pass: gvn +; YAML-NEXT: Name: LoadElim +; YAML-NEXT: Function: arg +; YAML-NEXT: Args: +; YAML-NEXT: - String: 'load of type ' +; YAML-NEXT: - Type: i32 +; YAML-NEXT: - String: ' eliminated' +; YAML-NEXT: - String: ' in favor of ' +; YAML-NEXT: - InfavorOfValue: i +; YAML-NEXT: ... +; YAML-NEXT: --- !Passed +; YAML-NEXT: Pass: gvn +; YAML-NEXT: Name: LoadElim +; YAML-NEXT: Function: const +; YAML-NEXT: Args: +; YAML-NEXT: - String: 'load of type ' +; YAML-NEXT: - Type: i32 +; YAML-NEXT: - String: ' eliminated' +; YAML-NEXT: - String: ' in favor of ' +; YAML-NEXT: - InfavorOfValue: '4' +; YAML-NEXT: ... +; YAML-NEXT: --- !Passed +; YAML-NEXT: Pass: gvn +; YAML-NEXT: Name: LoadElim +; YAML-NEXT: Function: inst +; YAML-NEXT: Args: +; YAML-NEXT: - String: 'load of type ' +; YAML-NEXT: - Type: i32 +; YAML-NEXT: - String: ' eliminated' +; YAML-NEXT: - String: ' in favor of ' +; YAML-NEXT: - InfavorOfValue: load +; YAML-NEXT: ... +; YAML-NEXT: --- !Missed +; YAML-NEXT: Pass: gvn +; YAML-NEXT: Name: LoadClobbered +; YAML-NEXT: DebugLoc: { File: /tmp/s.c, Line: 3, Column: 3 } +; YAML-NEXT: Function: may_alias +; YAML-NEXT: Args: +; YAML-NEXT: - String: 'load of type ' +; YAML-NEXT: - Type: i32 +; YAML-NEXT: - String: ' not eliminated' +; YAML-NEXT: - String: ' in favor of ' +; YAML-NEXT: - OtherAccess: load +; YAML-NEXT: DebugLoc: { File: /tmp/s.c, Line: 1, Column: 13 } +; YAML-NEXT: - String: ' because it is clobbered by ' +; YAML-NEXT: - ClobberedBy: store +; YAML-NEXT: DebugLoc: { File: /tmp/s.c, Line: 2, Column: 10 } +; YAML-NEXT: ... + +define i32 @arg(i32* %p, i32 %i) { +entry: + store i32 %i, i32* %p + %load = load i32, i32* %p + ret i32 %load +} + +define i32 @const(i32* %p) { +entry: + store i32 4, i32* %p + %load = load i32, i32* %p + ret i32 %load +} + +define i32 @inst(i32* %p) { +entry: + %load1 = load i32, i32* %p + %load = load i32, i32* %p + %add = add i32 %load1, %load + ret i32 %add +} + +define i32 @may_alias(i32* %p, i32* %r) !dbg !7 { +entry: + %load1 = load i32, i32* %p, !tbaa !13, !dbg !9 + store i32 4, i32* %r, !tbaa !13, !dbg !10 + %load = load i32, i32* %p, !tbaa !13, !dbg !11 + %add = add i32 %load1, %load + ret i32 %add +} +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 4.0.0 (trunk 282540) (llvm/trunk 282542)", isOptimized: true, runtimeVersion: 0, emissionKind: LineTablesOnly, enums: !2) +!1 = !DIFile(filename: "/tmp/s.c", directory: "/tmp") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"PIC Level", i32 2} +!6 = !{!"clang version 4.0.0 (trunk 282540) (llvm/trunk 282542)"} +!7 = distinct !DISubprogram(name: "may_alias", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: true, unit: !0, variables: !2) +!8 = !DISubroutineType(types: !2) +!9 = !DILocation(line: 1, column: 13, scope: !7) +!10 = !DILocation(line: 2, column: 10, scope: !7) +!11 = !DILocation(line: 3, column: 3, scope: !7) + +!12 = !{ !"tbaa root" } +!13 = !{ !"int", !12 } diff --git a/llvm/test/Transforms/NewGVN/phi-translate-partial-alias.ll b/llvm/test/Transforms/NewGVN/phi-translate-partial-alias.ll new file mode 100644 index 00000000000..cd4a9a2ff01 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/phi-translate-partial-alias.ll @@ -0,0 +1,27 @@ +; RUN: opt -basicaa -newgvn -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, i8* %phi +; CHECK: call void @bar(i8 %l0) +; CHECK: %l1 = load i8, i8* %phi +define void @test0(i8* %begin) { +entry: + br label %loop + +loop: + %phi = phi i8* [ %begin, %entry ], [ %next, %loop ] + %l0 = load i8, i8* %phi + call void @bar(i8 %l0) + %l1 = load i8, i8* %phi + %next = getelementptr inbounds i8, i8* %phi, i8 %l1 + br label %loop +} + +declare void @bar(i8) diff --git a/llvm/test/Transforms/NewGVN/pr10820.ll b/llvm/test/Transforms/NewGVN/pr10820.ll new file mode 100644 index 00000000000..d7a02b570aa --- /dev/null +++ b/llvm/test/Transforms/NewGVN/pr10820.ll @@ -0,0 +1,19 @@ +; XFAIL: * +; RUN: opt < %s -basicaa -newgvn -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" +target triple = "x86_64-unknown-linux-gnu" + +@g = external global i31 + +define void @main() nounwind uwtable { +entry: +; CHECK: store i32 + store i32 402662078, i32* bitcast (i31* @g to i32*), align 8 +; CHECK-NOT: load i31 + %0 = load i31, i31* @g, align 8 +; CHECK: store i31 + store i31 %0, i31* undef, align 1 + unreachable +} diff --git a/llvm/test/Transforms/NewGVN/pr12979.ll b/llvm/test/Transforms/NewGVN/pr12979.ll new file mode 100644 index 00000000000..ed36b707f4a --- /dev/null +++ b/llvm/test/Transforms/NewGVN/pr12979.ll @@ -0,0 +1,93 @@ +; RUN: opt -newgvn -S < %s | FileCheck %s + +define i32 @test1(i32 %x, i32 %y) { +; CHECK: @test1(i32 %x, i32 %y) +; CHECK: %add1 = add i32 %x, %y +; CHECK: %foo = add i32 %add1, %add1 + + %add1 = add nsw i32 %x, %y + %add2 = add i32 %x, %y + %foo = add i32 %add1, %add2 + ret i32 %foo +} + +define i32 @test2(i32 %x, i32 %y) { +; CHECK: @test2(i32 %x, i32 %y) +; CHECK: %add1 = add i32 %x, %y +; CHECK: %foo = add i32 %add1, %add1 + + %add1 = add nuw i32 %x, %y + %add2 = add i32 %x, %y + %foo = add i32 %add1, %add2 + ret i32 %foo +} + +define i32 @test3(i32 %x, i32 %y) { +; CHECK: @test3(i32 %x, i32 %y) +; CHECK: %add1 = add i32 %x, %y +; CHECK: %foo = add i32 %add1, %add1 + + %add1 = add nuw nsw i32 %x, %y + %add2 = add i32 %x, %y + %foo = add i32 %add1, %add2 + ret i32 %foo +} + +define i32 @test4(i32 %x, i32 %y) { +; CHECK: @test4(i32 %x, i32 %y) +; CHECK: %add1 = add nsw i32 %x, %y +; CHECK: %foo = add i32 %add1, %add1 + + %add1 = add nsw i32 %x, %y + %add2 = add nsw i32 %x, %y + %foo = add i32 %add1, %add2 + ret i32 %foo +} + +define i32 @test5(i32 %x, i32 %y) { +; CHECK: @test5(i32 %x, i32 %y) +; CHECK: %add1 = add i32 %x, %y +; CHECK: %foo = add i32 %add1, %add1 + + %add1 = add nuw i32 %x, %y + %add2 = add nsw i32 %x, %y + %foo = add i32 %add1, %add2 + ret i32 %foo +} + +define i32 @test6(i32 %x, i32 %y) { +; CHECK: @test6(i32 %x, i32 %y) +; CHECK: %add1 = add nsw i32 %x, %y +; CHECK: %foo = add i32 %add1, %add1 + + %add1 = add nuw nsw i32 %x, %y + %add2 = add nsw i32 %x, %y + %foo = add i32 %add1, %add2 + ret i32 %foo +} + +define i32 @test7(i32 %x, i32 %y) { +; CHECK: @test7(i32 %x, i32 %y) +; CHECK: %add1 = add i32 %x, %y +; CHECK-NOT: what_is_this +; CHECK: %foo = add i32 %add1, %add1 + + %add1 = add i32 %x, %y, !what_is_this !{} + %add2 = add i32 %x, %y + %foo = add i32 %add1, %add2 + ret i32 %foo +} + +declare void @mumble(i2, i2) + +define void @test8(i2 %x) { +; CHECK-LABEL: @test8( +; CHECK: %[[ashr:.*]] = ashr i2 %x, 1 +; CHECK-NEXT: call void @mumble(i2 %[[ashr]], i2 %[[ashr]]) +; CHECK-NEXT: ret void + + %ashr0 = ashr exact i2 %x, 1 + %ashr1 = ashr i2 %x, 1 + call void @mumble(i2 %ashr0, i2 %ashr1) + ret void +} diff --git a/llvm/test/Transforms/NewGVN/pr14166.ll b/llvm/test/Transforms/NewGVN/pr14166.ll new file mode 100644 index 00000000000..daf27cdb7fd --- /dev/null +++ b/llvm/test/Transforms/NewGVN/pr14166.ll @@ -0,0 +1,25 @@ +; XFAIL: * +; RUN: opt -disable-basicaa -newgvn -S < %s | FileCheck %s +target datalayout = "e-p:32:32:32" +target triple = "i386-pc-linux-gnu" +define <2 x i32> @test1() { + %v1 = alloca <2 x i32> + call void @anything(<2 x i32>* %v1) + %v2 = load <2 x i32>, <2 x i32>* %v1 + %v3 = inttoptr <2 x i32> %v2 to <2 x i8*> + %v4 = bitcast <2 x i32>* %v1 to <2 x i8*>* + store <2 x i8*> %v3, <2 x i8*>* %v4 + %v5 = load <2 x i32>, <2 x i32>* %v1 + ret <2 x i32> %v5 +; CHECK-LABEL: @test1( +; CHECK: %v1 = alloca <2 x i32> +; CHECK: call void @anything(<2 x i32>* %v1) +; CHECK: %v2 = load <2 x i32>, <2 x i32>* %v1 +; CHECK: %v3 = inttoptr <2 x i32> %v2 to <2 x i8*> +; CHECK: %v4 = bitcast <2 x i32>* %v1 to <2 x i8*>* +; CHECK: store <2 x i8*> %v3, <2 x i8*>* %v4 +; CHECK: ret <2 x i32> %v2 +} + +declare void @anything(<2 x i32>*) + diff --git a/llvm/test/Transforms/NewGVN/pr17732.ll b/llvm/test/Transforms/NewGVN/pr17732.ll new file mode 100644 index 00000000000..4a194e6a08b --- /dev/null +++ b/llvm/test/Transforms/NewGVN/pr17732.ll @@ -0,0 +1,31 @@ +; XFAIL: * +; RUN: opt -newgvn -S -o - < %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-S128" +target triple = "x86_64-unknown-linux-gnu" + +%struct.with_array = type { [2 x i8], i32, i8 } +%struct.with_vector = type { <2 x i8>, i32, i8 } + +@main.obj_with_array = private unnamed_addr constant { [2 x i8], i32, i8, [3 x i8] } { [2 x i8] zeroinitializer, i32 0, i8 1, [3 x i8] undef }, align 4 +@array_with_zeroinit = common global %struct.with_array zeroinitializer, align 4 + +@main.obj_with_vector = private unnamed_addr constant { <2 x i8>, i32, i8, [3 x i8] } { <2 x i8> zeroinitializer, i32 0, i8 1, [3 x i8] undef }, align 4 +@vector_with_zeroinit = common global %struct.with_vector zeroinitializer, align 4 + +define i32 @main() { +entry: + tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* getelementptr inbounds (%struct.with_array, %struct.with_array* @array_with_zeroinit, i64 0, i32 0, i64 0), i8* getelementptr inbounds ({ [2 x i8], i32, i8, [3 x i8] }, { [2 x i8], i32, i8, [3 x i8] }* @main.obj_with_array, i64 0, i32 0, i64 0), i64 12, i32 4, i1 false) + %0 = load i8, i8* getelementptr inbounds (%struct.with_array, %struct.with_array* @array_with_zeroinit, i64 0, i32 2), align 4 + + tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* getelementptr inbounds (%struct.with_vector, %struct.with_vector* @vector_with_zeroinit, i64 0, i32 0, i64 0), i8* getelementptr inbounds ({ <2 x i8>, i32, i8, [3 x i8] }, { <2 x i8>, i32, i8, [3 x i8] }* @main.obj_with_vector, i64 0, i32 0, i64 0), i64 12, i32 4, i1 false) + %1 = load i8, i8* getelementptr inbounds (%struct.with_vector, %struct.with_vector* @vector_with_zeroinit, i64 0, i32 2), align 4 + %conv0 = sext i8 %0 to i32 + %conv1 = sext i8 %1 to i32 + %and = and i32 %conv0, %conv1 + ret i32 %and +; CHECK-LABEL: define i32 @main( +; CHECK: ret i32 1 +} + +declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32, i1) diff --git a/llvm/test/Transforms/NewGVN/pr17852.ll b/llvm/test/Transforms/NewGVN/pr17852.ll new file mode 100644 index 00000000000..31eb7c9ceac --- /dev/null +++ b/llvm/test/Transforms/NewGVN/pr17852.ll @@ -0,0 +1,66 @@ +; RUN: opt < %s -basicaa -newgvn +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-S128" +%struct.S0 = type { [2 x i8], [2 x i8], [4 x i8], [2 x i8], i32, i32, i32, i32 } +define void @fn1(%struct.S0* byval align 8 %p1) { + br label %for.cond +for.cond: ; preds = %1, %0 + br label %for.end + %f2 = getelementptr inbounds %struct.S0, %struct.S0* %p1, i64 0, i32 2 + %f9 = getelementptr inbounds %struct.S0, %struct.S0* %p1, i64 0, i32 7 + br label %for.cond +for.end: ; preds = %for.cond + br i1 true, label %if.else, label %if.then +if.then: ; preds = %for.end + %f22 = getelementptr inbounds %struct.S0, %struct.S0* %p1, i64 0, i32 2 + %f7 = getelementptr inbounds %struct.S0, %struct.S0* %p1, i64 0, i32 5 + %tmp7 = load i32, i32* %f7, align 8 + br label %if.end40 +if.else: ; preds = %for.end + br i1 false, label %for.cond18, label %if.then6 +if.then6: ; preds = %if.else + %f3 = getelementptr inbounds %struct.S0, %struct.S0* %p1, i64 0, i32 2 + %tmp10 = bitcast %struct.S0* %p1 to i16* + %f5 = getelementptr inbounds %struct.S0, %struct.S0* %p1, i64 0, i32 3 + %tmp11 = bitcast [2 x i8]* %f5 to i16* + %bf.load13 = load i16, i16* %tmp11, align 8 + br label %if.end36 +for.cond18: ; preds = %if.else + call void @fn4() + br i1 true, label %if.end, label %if.end36 +if.end: ; preds = %for.cond18 + %f321 = getelementptr inbounds %struct.S0, %struct.S0* %p1, i64 0, i32 2 + %f925 = getelementptr inbounds %struct.S0, %struct.S0* %p1, i64 0, i32 7 + %f526 = getelementptr inbounds %struct.S0, %struct.S0* %p1, i64 0, i32 3 + %tmp15 = bitcast [2 x i8]* %f526 to i16* + %bf.load27 = load i16, i16* %tmp15, align 8 + %tmp16 = bitcast %struct.S0* %p1 to i16* + br label %if.end36 +if.end36: ; preds = %if.end, %for.cond18, %if.then6 + %f537 = getelementptr inbounds %struct.S0, %struct.S0* %p1, i64 0, i32 3 + %tmp17 = bitcast [2 x i8]* %f537 to i16* + %bf.load38 = load i16, i16* %tmp17, align 8 + %bf.clear39 = and i16 %bf.load38, -16384 + br label %if.end40 +if.end40: ; preds = %if.end36, %if.then + %f6 = getelementptr inbounds %struct.S0, %struct.S0* %p1, i64 0, i32 4 + %tmp18 = load i32, i32* %f6, align 4 + call void @fn2(i32 %tmp18) + %f8 = getelementptr inbounds %struct.S0, %struct.S0* %p1, i64 0, i32 6 + %tmp19 = load i32, i32* %f8, align 4 + %tobool41 = icmp eq i32 %tmp19, 0 + br i1 true, label %if.end50, label %if.then42 +if.then42: ; preds = %if.end40 + %tmp20 = bitcast %struct.S0* %p1 to i16* + %f547 = getelementptr inbounds %struct.S0, %struct.S0* %p1, i64 0, i32 3 + %tmp21 = bitcast [2 x i8]* %f547 to i16* + %bf.load48 = load i16, i16* %tmp21, align 8 + br label %if.end50 +if.end50: ; preds = %if.then42, %if.end40 + %f551 = getelementptr inbounds %struct.S0, %struct.S0* %p1, i64 0, i32 3 + %tmp22 = bitcast [2 x i8]* %f551 to i16* + %bf.load52 = load i16, i16* %tmp22, align 8 + %bf.clear53 = and i16 %bf.load52, -16384 + ret void +} +declare void @fn2(i32) +declare void @fn4() diff --git a/llvm/test/Transforms/NewGVN/pr24397.ll b/llvm/test/Transforms/NewGVN/pr24397.ll new file mode 100644 index 00000000000..247eaa2e1bc --- /dev/null +++ b/llvm/test/Transforms/NewGVN/pr24397.ll @@ -0,0 +1,18 @@ +; RUN: opt -basicaa -newgvn -disable-output < %s + +target triple = "x86_64-unknown-linux-gnu" + +define i64 @foo(i64** %arrayidx) { +entry: + %p = load i64*, i64** %arrayidx, align 8 + %cmpnull = icmp eq i64* %p, null + br label %BB2 + +entry2: ; No predecessors! + br label %BB2 + +BB2: ; preds = %entry2, %entry + %bc = bitcast i64** %arrayidx to i64* + %load = load i64, i64* %bc, align 8 + ret i64 %load +} diff --git a/llvm/test/Transforms/NewGVN/pr24426.ll b/llvm/test/Transforms/NewGVN/pr24426.ll new file mode 100644 index 00000000000..26e7a9f223f --- /dev/null +++ b/llvm/test/Transforms/NewGVN/pr24426.ll @@ -0,0 +1,18 @@ +; RUN: opt < %s -memcpyopt -mldst-motion -newgvn -S | FileCheck %s + +declare void @check(i8) + +declare void @write(i8* %res) + +define void @test1() { + %1 = alloca [10 x i8] + %2 = bitcast [10 x i8]* %1 to i8* + call void @write(i8* %2) + %3 = load i8, i8* %2 + +; CHECK-NOT: undef + call void @check(i8 %3) + + ret void +} + diff --git a/llvm/test/Transforms/NewGVN/pr25440.ll b/llvm/test/Transforms/NewGVN/pr25440.ll new file mode 100644 index 00000000000..ff94a82ff66 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/pr25440.ll @@ -0,0 +1,108 @@ +;RUN: opt -newgvn -S < %s | FileCheck %s + +target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n8:16:32-S64" +target triple = "thumbv7--linux-gnueabi" + +%struct.a = type { i16, i16, [1 x %union.a] } +%union.a = type { i32 } + +@length = external global [0 x i32], align 4 + +; Function Attrs: nounwind +define fastcc void @foo(%struct.a* nocapture readonly %x) { +;CHECK-LABEL: foo +entry: + br label %bb0 + +bb0: ; preds = %land.lhs.true, %entry +;CHECK: bb0: + %x.tr = phi %struct.a* [ %x, %entry ], [ null, %land.lhs.true ] + %code1 = getelementptr inbounds %struct.a, %struct.a* %x.tr, i32 0, i32 0 + %0 = load i16, i16* %code1, align 4 +; CHECK: load i16, i16* + %conv = zext i16 %0 to i32 + switch i32 %conv, label %if.end.50 [ + i32 43, label %cleanup + i32 52, label %if.then.5 + ] + +if.then.5: ; preds = %bb0 + br i1 undef, label %land.lhs.true, label %if.then.26 + +land.lhs.true: ; preds = %if.then.5 + br i1 undef, label %cleanup, label %bb0 + +if.then.26: ; preds = %if.then.5 + %x.tr.lcssa163 = phi %struct.a* [ %x.tr, %if.then.5 ] + br i1 undef, label %cond.end, label %cond.false + +cond.false: ; preds = %if.then.26 +; CHECK: cond.false: +; CHECK: load i16 + %mode = getelementptr inbounds %struct.a, %struct.a* %x.tr.lcssa163, i32 0, i32 1 + %bf.load = load i16, i16* %mode, align 2 + %bf.shl = shl i16 %bf.load, 8 + br label %cond.end + +cond.end: ; preds = %cond.false, %if.then.26 + br i1 undef, label %if.then.44, label %cleanup + +if.then.44: ; preds = %cond.end + unreachable + +if.end.50: ; preds = %bb0 +;%CHECK: if.end.50: + %conv.lcssa = phi i32 [ %conv, %bb0 ] + %arrayidx52 = getelementptr inbounds [0 x i32], [0 x i32]* @length, i32 0, i32 %conv.lcssa + %1 = load i32, i32* %arrayidx52, align 4 + br i1 undef, label %for.body.57, label %cleanup + +for.body.57: ; preds = %if.end.50 + %i.2157 = add nsw i32 %1, -1 + unreachable + +cleanup: ; preds = %if.end.50, %cond.end, %land.lhs.true, %bb0 + ret void +} + +@yy_c_buf_p = external unnamed_addr global i8*, align 4 +@dfg_text = external global i8*, align 4 + +define void @dfg_lex() { +;CHECK-LABEL: dfg_lex +entry: + br label %while.bodythread-pre-split + +while.bodythread-pre-split: ; preds = %while.end, %while.end, %entry + br i1 undef, label %if.then.14, label %if.end.15 + +if.then.14: ; preds = %while.end, %while.bodythread-pre-split + %v1 = load i32, i32* bitcast (i8** @dfg_text to i32*), align 4 + %sub.ptr.sub = sub i32 undef, %v1 + br label %if.end.15 + +if.end.15: ; preds = %if.then.14, %while.bodythread-pre-split + %v2 = load i8*, i8** @yy_c_buf_p, align 4 + br label %while.cond.16 + +while.cond.16: ; preds = %while.cond.16, %if.end.15 + br i1 undef, label %while.cond.16, label %while.end + +while.end: ; preds = %while.cond.16 + %add.ptr = getelementptr inbounds i8, i8* %v2, i32 undef + store i8* %add.ptr, i8** @dfg_text, align 4 + %sub.ptr.rhs.cast25 = ptrtoint i8* %add.ptr to i32 + %sub.ptr.sub26 = sub i32 0, %sub.ptr.rhs.cast25 + switch i32 undef, label %sw.default [ + i32 65, label %while.bodythread-pre-split + i32 3, label %return + i32 57, label %while.bodythread-pre-split + i32 60, label %if.then.14 + ] + +sw.default: ; preds = %while.end + unreachable + +return: ; preds = %while.end + ret void +} diff --git a/llvm/test/Transforms/NewGVN/pr28562.ll b/llvm/test/Transforms/NewGVN/pr28562.ll new file mode 100644 index 00000000000..e4a17df4b27 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/pr28562.ll @@ -0,0 +1,9 @@ +; RUN: opt -S -newgvn < %s | FileCheck %s +define i32* @test1(i32* %a) { + %x1 = getelementptr inbounds i32, i32* %a, i32 10 + %x2 = getelementptr i32, i32* %a, i32 10 + ret i32* %x2 +; CHECK-LABEL: @test1( +; CHECK: %[[x:.*]] = getelementptr i32, i32* %a, i32 10 +; CHECK: ret i32* %[[x]] +} diff --git a/llvm/test/Transforms/NewGVN/pre-compare.ll b/llvm/test/Transforms/NewGVN/pre-compare.ll new file mode 100644 index 00000000000..3bd695b4835 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/pre-compare.ll @@ -0,0 +1,68 @@ +; RUN: opt -newgvn -S < %s | FileCheck %s + +; C source: +; +; void f(int x) { +; if (x != 1) +; puts (x == 2 ? "a" : "b"); +; for (;;) { +; puts("step 1"); +; if (x == 2) +; continue; +; printf("step 2: %d\n", x); +; } +; } +; +; If we PRE %cmp3, CodeGenPrepare won't be able to sink the compare down to its +; uses, and we are forced to keep both %x and %cmp3 in registers in the loop. +; +; It is just as cheap to recompute the icmp against %x as it is to compare a +; GPR against 0. On x86-64, the br i1 %cmp3 becomes: +; +; testb %r12b, %r12b +; jne LBB0_3 +; +; The sunk icmp is: +; +; cmpl $2, %ebx +; je LBB0_3 +; +; This is just as good, and it doesn't require a separate register. +; +; CHECK-NOT: phi i1 + +@.str = private unnamed_addr constant [2 x i8] c"a\00", align 1 +@.str1 = private unnamed_addr constant [2 x i8] c"b\00", align 1 +@.str2 = private unnamed_addr constant [7 x i8] c"step 1\00", align 1 +@.str3 = private unnamed_addr constant [12 x i8] c"step 2: %d\0A\00", align 1 + +define void @f(i32 %x) noreturn nounwind uwtable ssp { +entry: + %cmp = icmp eq i32 %x, 1 + br i1 %cmp, label %for.cond.preheader, label %if.then + +if.then: ; preds = %entry + %cmp1 = icmp eq i32 %x, 2 + %cond = select i1 %cmp1, i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str1, i64 0, i64 0) + %call = tail call i32 @puts(i8* %cond) nounwind + br label %for.cond.preheader + +for.cond.preheader: ; preds = %entry, %if.then + %cmp3 = icmp eq i32 %x, 2 + br label %for.cond + +for.cond: ; preds = %for.cond.backedge, %for.cond.preheader + %call2 = tail call i32 @puts(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str2, i64 0, i64 0)) nounwind + br i1 %cmp3, label %for.cond.backedge, label %if.end5 + +if.end5: ; preds = %for.cond + %call6 = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str3, i64 0, i64 0), i32 %x) nounwind + br label %for.cond.backedge + +for.cond.backedge: ; preds = %if.end5, %for.cond + br label %for.cond +} + +declare i32 @puts(i8* nocapture) nounwind + +declare i32 @printf(i8* nocapture, ...) nounwind diff --git a/llvm/test/Transforms/NewGVN/pre-new-inst.ll b/llvm/test/Transforms/NewGVN/pre-new-inst.ll new file mode 100644 index 00000000000..2b6fc2f2c05 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/pre-new-inst.ll @@ -0,0 +1,30 @@ +; XFAIL: * +; RUN: opt -basicaa -newgvn -S %s | FileCheck %s + +%MyStruct = type { i32, i32 } +define i8 @foo(i64 %in, i8* %arr) { + %addr = alloca %MyStruct + %dead = trunc i64 %in to i32 + br i1 undef, label %next, label %tmp + +tmp: + call void @bar() + br label %next + +next: + %addr64 = bitcast %MyStruct* %addr to i64* + store i64 %in, i64* %addr64 + br label %final + +final: + %addr32 = getelementptr %MyStruct, %MyStruct* %addr, i32 0, i32 0 + %idx32 = load i32, i32* %addr32 + +; CHECK: %resptr = getelementptr i8, i8* %arr, i32 %dead + %resptr = getelementptr i8, i8* %arr, i32 %idx32 + %res = load i8, i8* %resptr + + ret i8 %res +} + +declare void @bar() diff --git a/llvm/test/Transforms/NewGVN/propagate-ir-flags.ll b/llvm/test/Transforms/NewGVN/propagate-ir-flags.ll new file mode 100644 index 00000000000..bb2f78d41d4 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/propagate-ir-flags.ll @@ -0,0 +1,29 @@ +; XFAIL: * +; RUN: opt < %s -newgvn -S | FileCheck %s + +; CHECK-LABEL: func_fast +; CHECK: fadd fast double +; CHECK-NEXT: store +; CHECK-NEXT: ret +define double @func_fast(double %a, double %b) { +entry: + %a.addr = alloca double, align 8 + %add = fadd fast double %b, 3.000000e+00 + store double %add, double* %a.addr, align 8 + %load_add = load double, double* %a.addr, align 8 + ret double %load_add +} + +; CHECK-LABEL: func_no_fast +; CHECK: fadd double +; CHECK-NEXT: store +; CHECK-NEXT: ret +define double @func_no_fast(double %a, double %b) { +entry: + %a.addr = alloca double, align 8 + %add = fadd fast double %b, 3.000000e+00 + store double %add, double* %a.addr, align 8 + %duplicated_add = fadd double %b, 3.000000e+00 + ret double %duplicated_add +} + diff --git a/llvm/test/Transforms/NewGVN/range.ll b/llvm/test/Transforms/NewGVN/range.ll new file mode 100644 index 00000000000..55efa5955b1 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/range.ll @@ -0,0 +1,101 @@ +; RUN: opt -basicaa -newgvn -S < %s | FileCheck %s + +define i32 @test1(i32* %p) { +; CHECK-LABEL: @test1(i32* %p) +; CHECK: %a = load i32, i32* %p, !range !0 +; CHECK: %c = add i32 %a, %a + %a = load i32, i32* %p, !range !0 + %b = load i32, i32* %p, !range !0 + %c = add i32 %a, %b + ret i32 %c +} + +define i32 @test2(i32* %p) { +; CHECK-LABEL: @test2(i32* %p) +; CHECK: %a = load i32, i32* %p +; CHECK-NOT: range +; CHECK: %c = add i32 %a, %a + %a = load i32, i32* %p, !range !0 + %b = load i32, i32* %p + %c = add i32 %a, %b + ret i32 %c +} + +define i32 @test3(i32* %p) { +; CHECK-LABEL: @test3(i32* %p) +; CHECK: %a = load i32, i32* %p, !range ![[DISJOINT_RANGE:[0-9]+]] +; CHECK: %c = add i32 %a, %a + %a = load i32, i32* %p, !range !0 + %b = load i32, i32* %p, !range !1 + %c = add i32 %a, %b + ret i32 %c +} + +define i32 @test4(i32* %p) { +; CHECK-LABEL: @test4(i32* %p) +; CHECK: %a = load i32, i32* %p, !range ![[MERGED_RANGE:[0-9]+]] +; CHECK: %c = add i32 %a, %a + %a = load i32, i32* %p, !range !0 + %b = load i32, i32* %p, !range !2 + %c = add i32 %a, %b + ret i32 %c +} + +define i32 @test5(i32* %p) { +; CHECK-LABEL: @test5(i32* %p) +; CHECK: %a = load i32, i32* %p, !range ![[MERGED_SIGNED_RANGE:[0-9]+]] +; CHECK: %c = add i32 %a, %a + %a = load i32, i32* %p, !range !3 + %b = load i32, i32* %p, !range !4 + %c = add i32 %a, %b + ret i32 %c +} + +define i32 @test6(i32* %p) { +; CHECK-LABEL: @test6(i32* %p) +; CHECK: %a = load i32, i32* %p, !range ![[MERGED_TEST6:[0-9]+]] +; CHECK: %c = add i32 %a, %a + %a = load i32, i32* %p, !range !5 + %b = load i32, i32* %p, !range !6 + %c = add i32 %a, %b + ret i32 %c +} + +define i32 @test7(i32* %p) { +; CHECK-LABEL: @test7(i32* %p) +; CHECK: %a = load i32, i32* %p, !range ![[MERGED_TEST7:[0-9]+]] +; CHECK: %c = add i32 %a, %a + %a = load i32, i32* %p, !range !7 + %b = load i32, i32* %p, !range !8 + %c = add i32 %a, %b + ret i32 %c +} + +define i32 @test8(i32* %p) { +; CHECK-LABEL: @test8(i32* %p) +; CHECK: %a = load i32, i32* %p +; CHECK-NOT: range +; CHECK: %c = add i32 %a, %a + %a = load i32, i32* %p, !range !9 + %b = load i32, i32* %p, !range !10 + %c = add i32 %a, %b + ret i32 %c +} + +; CHECK: ![[DISJOINT_RANGE]] = !{i32 0, i32 2, i32 3, i32 5} +; CHECK: ![[MERGED_RANGE]] = !{i32 0, i32 5} +; CHECK: ![[MERGED_SIGNED_RANGE]] = !{i32 -5, i32 -2, i32 1, i32 5} +; CHECK: ![[MERGED_TEST6]] = !{i32 10, i32 1} +; CHECK: ![[MERGED_TEST7]] = !{i32 3, i32 4, i32 5, i32 2} + +!0 = !{i32 0, i32 2} +!1 = !{i32 3, i32 5} +!2 = !{i32 2, i32 5} +!3 = !{i32 -5, i32 -2} +!4 = !{i32 1, i32 5} +!5 = !{i32 10, i32 1} +!6 = !{i32 12, i32 16} +!7 = !{i32 1, i32 2, i32 3, i32 4} +!8 = !{i32 5, i32 1} +!9 = !{i32 1, i32 5} +!10 = !{i32 5, i32 1} diff --git a/llvm/test/Transforms/NewGVN/readattrs.ll b/llvm/test/Transforms/NewGVN/readattrs.ll new file mode 100644 index 00000000000..be5fbf5a806 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/readattrs.ll @@ -0,0 +1,18 @@ +; XFAIL: * +; RUN: opt -newgvn -S -o - < %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" +target triple = "x86_64-unknown-linux-gnu" + +declare void @use(i8* readonly nocapture) + +define i8 @test() { + %a = alloca i8 + store i8 1, i8* %a + call void @use(i8* %a) + %b = load i8, i8* %a + ret i8 %b +; CHECK-LABEL: define i8 @test( +; CHECK: call void @use(i8* %a) +; CHECK-NEXT: ret i8 1 +} diff --git a/llvm/test/Transforms/NewGVN/rle-must-alias.ll b/llvm/test/Transforms/NewGVN/rle-must-alias.ll new file mode 100644 index 00000000000..7e4941754dd --- /dev/null +++ b/llvm/test/Transforms/NewGVN/rle-must-alias.ll @@ -0,0 +1,48 @@ +; XFAIL: * +; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s + +; GVN should eliminate the fully redundant %9 GEP which +; allows DEAD to be removed. This is PR3198. + +; The %7 and %4 loads combine to make %DEAD unneeded. +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" +target triple = "i386-apple-darwin7" +@H = common global [100 x i32] zeroinitializer, align 32 ; <[100 x i32]*> [#uses=3] +@G = common global i32 0 ; <i32*> [#uses=2] + +define i32 @test(i32 %i) nounwind { +entry: + %0 = tail call i32 (...) @foo() nounwind ; <i32> [#uses=1] + %1 = icmp eq i32 %0, 0 ; <i1> [#uses=1] + br i1 %1, label %bb1, label %bb + +bb: ; preds = %entry + %2 = tail call i32 (...) @bar() nounwind ; <i32> [#uses=0] + %3 = getelementptr [100 x i32], [100 x i32]* @H, i32 0, i32 %i ; <i32*> [#uses=1] + %4 = load i32, i32* %3, align 4 ; <i32> [#uses=1] + store i32 %4, i32* @G, align 4 + br label %bb3 + +bb1: ; preds = %entry + %5 = tail call i32 (...) @baz() nounwind ; <i32> [#uses=0] + %6 = getelementptr [100 x i32], [100 x i32]* @H, i32 0, i32 %i ; <i32*> [#uses=1] + %7 = load i32, i32* %6, align 4 ; <i32> [#uses=2] + store i32 %7, i32* @G, align 4 + %8 = icmp eq i32 %7, 0 ; <i1> [#uses=1] + br i1 %8, label %bb3, label %bb4 + +bb3: ; preds = %bb1, %bb + %9 = getelementptr [100 x i32], [100 x i32]* @H, i32 0, i32 %i ; <i32*> [#uses=1] + %DEAD = load i32, i32* %9, align 4 ; <i32> [#uses=1] +; CHECK: %DEAD = phi i32 [ 0, %bb1 ], [ %4, %bb ] + ret i32 %DEAD + +bb4: ; preds = %bb1 + ret i32 0 +} + +declare i32 @foo(...) + +declare i32 @bar(...) + +declare i32 @baz(...) diff --git a/llvm/test/Transforms/NewGVN/rle-no-phi-translate.ll b/llvm/test/Transforms/NewGVN/rle-no-phi-translate.ll new file mode 100644 index 00000000000..8900e3b17ac --- /dev/null +++ b/llvm/test/Transforms/NewGVN/rle-no-phi-translate.ll @@ -0,0 +1,28 @@ +; RUN: opt < %s -newgvn -S | FileCheck %s +; XFAIL: * +; FIXME: This should be promotable, but memdep/gvn don't track values +; path/edge sensitively enough. + +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" +target triple = "i386-apple-darwin7" + +define i32 @g(i32* %b, i32* %c) nounwind { +entry: + store i32 1, i32* %b + store i32 2, i32* %c + + %t1 = icmp eq i32* %b, null ; <i1> [#uses=1] + br i1 %t1, label %bb, label %bb2 + +bb: ; preds = %entry + br label %bb2 + +bb2: ; preds = %bb1, %bb + %c_addr.0 = phi i32* [ %b, %entry ], [ %c, %bb ] ; <i32*> [#uses=1] + %cv = load i32, i32* %c_addr.0, align 4 ; <i32> [#uses=1] + ret i32 %cv +; CHECK: bb2: +; CHECK-NOT: load i32 +; CHECK: ret i32 +} + diff --git a/llvm/test/Transforms/NewGVN/rle-nonlocal.ll b/llvm/test/Transforms/NewGVN/rle-nonlocal.ll new file mode 100644 index 00000000000..89f5a6affde --- /dev/null +++ b/llvm/test/Transforms/NewGVN/rle-nonlocal.ll @@ -0,0 +1,26 @@ +; XFAIL: * +; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s + +define i32 @main(i32** %p, i32 %x, i32 %y) { +block1: + %cmp = icmp eq i32 %x, %y + br i1 %cmp , label %block2, label %block3 + +block2: + %a = load i32*, i32** %p + br label %block4 + +block3: + %b = load i32*, i32** %p + br label %block4 + +block4: +; CHECK-NOT: %existingPHI = phi +; CHECK: %DEAD = phi + %existingPHI = phi i32* [ %a, %block2 ], [ %b, %block3 ] + %DEAD = load i32*, i32** %p + %c = load i32, i32* %DEAD + %d = load i32, i32* %existingPHI + %e = add i32 %c, %d + ret i32 %e +} diff --git a/llvm/test/Transforms/NewGVN/stale-loop-info.ll b/llvm/test/Transforms/NewGVN/stale-loop-info.ll new file mode 100644 index 00000000000..6bd7d473c39 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/stale-loop-info.ll @@ -0,0 +1,50 @@ +; RUN: opt -loops -newgvn -S < %s | FileCheck %s + +; This used to fail with ASAN enabled and if for some reason LoopInfo remained +; available during GVN. In this case BasicAA will use LI but +; MergeBlockIntoPredecessor in GVN failed to update LI. + +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" + +%struct.wibble.1028 = type { i32, i32, %struct.barney.881 } +%struct.barney.881 = type { %struct.zot.882 } +%struct.zot.882 = type { [64 x i8] } + +; Function Attrs: argmemonly +declare void @snork.1(i8*) local_unnamed_addr #0 + +define hidden zeroext i1 @eggs(%struct.wibble.1028* %arg, i1 %arg2) unnamed_addr align 2 { +bb: + br i1 %arg2, label %bb14, label %bb3 + +bb3: ; preds = %bb + %tmp = getelementptr inbounds %struct.wibble.1028, %struct.wibble.1028* %arg, i64 0, i32 2, i32 0, i32 0, i64 0 + %tmp5 = bitcast i8* %tmp to %struct.wibble.1028** + br label %bb6 + +bb6: ; preds = %bb12, %bb3 + br label %bb7 + +bb7: ; preds = %bb6 + br i1 undef, label %bb11, label %bb8 + +bb8: ; preds = %bb7 + %tmp9 = load %struct.wibble.1028*, %struct.wibble.1028** %tmp5, align 8 +; CHECK: %tmp9 = load %struct.wibble.1028*, %struct.wibble.1028** %tmp5, align 8 + %tmp10 = bitcast %struct.wibble.1028* %tmp9 to i8* + br label %bb12 + +bb11: ; preds = %bb7 + br label %bb12 + +bb12: ; preds = %bb11, %bb8 + %tmp13 = phi i8* [ %tmp, %bb11 ], [ %tmp10, %bb8 ] + call void @snork.1(i8* %tmp13) #1 + br label %bb6 + +bb14: ; preds = %bb + ret i1 false +} + +attributes #0 = { argmemonly } +attributes #1 = { nounwind } diff --git a/llvm/test/Transforms/NewGVN/tbaa.ll b/llvm/test/Transforms/NewGVN/tbaa.ll new file mode 100644 index 00000000000..47e20fae7f9 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/tbaa.ll @@ -0,0 +1,130 @@ +; XFAIL: * +; RUN: opt -tbaa -basicaa -newgvn -S < %s | FileCheck %s + +define i32 @test1(i8* %p, i8* %q) { +; CHECK: @test1(i8* %p, i8* %q) +; CHECK: call i32 @foo(i8* %p) +; CHECK-NOT: tbaa +; CHECK: %c = add i32 %a, %a + %a = call i32 @foo(i8* %p), !tbaa !0 + %b = call i32 @foo(i8* %p) + %c = add i32 %a, %b + ret i32 %c +} + +define i32 @test2(i8* %p, i8* %q) { +; CHECK: @test2(i8* %p, i8* %q) +; CHECK: call i32 @foo(i8* %p), !tbaa [[TAGC:!.*]] +; CHECK: %c = add i32 %a, %a + %a = call i32 @foo(i8* %p), !tbaa !0 + %b = call i32 @foo(i8* %p), !tbaa !0 + %c = add i32 %a, %b + ret i32 %c +} + +define i32 @test3(i8* %p, i8* %q) { +; CHECK: @test3(i8* %p, i8* %q) +; CHECK: call i32 @foo(i8* %p), !tbaa [[TAGB:!.*]] +; CHECK: %c = add i32 %a, %a + %a = call i32 @foo(i8* %p), !tbaa !3 + %b = call i32 @foo(i8* %p), !tbaa !3 + %c = add i32 %a, %b + ret i32 %c +} + +define i32 @test4(i8* %p, i8* %q) { +; CHECK: @test4(i8* %p, i8* %q) +; CHECK: call i32 @foo(i8* %p), !tbaa [[TAGA:!.*]] +; CHECK: %c = add i32 %a, %a + %a = call i32 @foo(i8* %p), !tbaa !1 + %b = call i32 @foo(i8* %p), !tbaa !0 + %c = add i32 %a, %b + ret i32 %c +} + +define i32 @test5(i8* %p, i8* %q) { +; CHECK: @test5(i8* %p, i8* %q) +; CHECK: call i32 @foo(i8* %p), !tbaa [[TAGA:!.*]] +; CHECK: %c = add i32 %a, %a + %a = call i32 @foo(i8* %p), !tbaa !0 + %b = call i32 @foo(i8* %p), !tbaa !1 + %c = add i32 %a, %b + ret i32 %c +} + +define i32 @test6(i8* %p, i8* %q) { +; CHECK: @test6(i8* %p, i8* %q) +; CHECK: call i32 @foo(i8* %p), !tbaa [[TAGA:!.*]] +; CHECK: %c = add i32 %a, %a + %a = call i32 @foo(i8* %p), !tbaa !0 + %b = call i32 @foo(i8* %p), !tbaa !3 + %c = add i32 %a, %b + ret i32 %c +} + +define i32 @test7(i8* %p, i8* %q) { +; CHECK: @test7(i8* %p, i8* %q) +; CHECK: call i32 @foo(i8* %p) +; CHECK-NOT: tbaa +; CHECK: %c = add i32 %a, %a + %a = call i32 @foo(i8* %p), !tbaa !4 + %b = call i32 @foo(i8* %p), !tbaa !3 + %c = add i32 %a, %b + ret i32 %c +} + + + +define i32 @test8(i32* %p, i32* %q) { +; CHECK-LABEL: test8 +; CHECK-NEXT: store i32 15, i32* %p +; CHECK-NEXT: ret i32 0 +; Since we know the location is invariant, we can forward the +; load across the potentially aliasing store. + + %a = load i32, i32* %q, !tbaa !10 + store i32 15, i32* %p + %b = load i32, i32* %q, !tbaa !10 + %c = sub i32 %a, %b + ret i32 %c +} +define i32 @test9(i32* %p, i32* %q) { +; CHECK-LABEL: test9 +; CHECK-NEXT: call void @clobber() +; CHECK-NEXT: ret i32 0 +; Since we know the location is invariant, we can forward the +; load across the potentially aliasing store (within the call). + + %a = load i32, i32* %q, !tbaa !10 + call void @clobber() + %b = load i32, i32* %q, !tbaa !10 + %c = sub i32 %a, %b + ret i32 %c +} + + +declare void @clobber() +declare i32 @foo(i8*) readonly + +; CHECK: [[TAGC]] = !{[[TYPEC:!.*]], [[TYPEC]], i64 0} +; CHECK: [[TYPEC]] = !{!"C", [[TYPEA:!.*]]} +; CHECK: [[TYPEA]] = !{!"A", !{{.*}}} +; CHECK: [[TAGB]] = !{[[TYPEB:!.*]], [[TYPEB]], i64 0} +; CHECK: [[TYPEB]] = !{!"B", [[TYPEA]]} +; CHECK: [[TAGA]] = !{[[TYPEA]], [[TYPEA]], i64 0} +!0 = !{!5, !5, i64 0} +!1 = !{!6, !6, i64 0} +!2 = !{!"tbaa root"} +!3 = !{!7, !7, i64 0} +!4 = !{!11, !11, i64 0} +!5 = !{!"C", !6} +!6 = !{!"A", !2} +!7 = !{!"B", !6} +!8 = !{!"another root"} +!11 = !{!"scalar type", !8} + + +;; A TBAA structure who's only point is to have a constant location +!9 = !{!"yet another root"} +!10 = !{!"node", !9, i64 1} + diff --git a/llvm/test/Transforms/NewGVN/unreachable_block_infinite_loop.ll b/llvm/test/Transforms/NewGVN/unreachable_block_infinite_loop.ll new file mode 100644 index 00000000000..705218785f0 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/unreachable_block_infinite_loop.ll @@ -0,0 +1,43 @@ +; RUN: opt -memdep -newgvn -disable-output < %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" + +define i32 @test2() nounwind ssp { +entry: + ret i32 0 + +unreachable_block: + %a = add i32 %a, 1 + ret i32 %a +} + +define i32 @pr23096_test0() { +entry: + br label %bb0 + +bb1: + %ptr1 = ptrtoint i32* %ptr2 to i64 + %ptr2 = inttoptr i64 %ptr1 to i32* + br i1 undef, label %bb0, label %bb1 + +bb0: + %phi = phi i32* [ undef, %entry ], [ %ptr2, %bb1 ] + %load = load i32, i32* %phi + ret i32 %load +} + +define i32 @pr23096_test1() { +entry: + br label %bb0 + +bb1: + %ptr1 = getelementptr i32, i32* %ptr2, i32 0 + %ptr2 = getelementptr i32, i32* %ptr1, i32 0 + br i1 undef, label %bb0, label %bb1 + +bb0: + %phi = phi i32* [ undef, %entry ], [ %ptr2, %bb1 ] + %load = load i32, i32* %phi + ret i32 %load +} diff --git a/llvm/test/Transforms/NewGVN/volatile-nonvolatile.ll b/llvm/test/Transforms/NewGVN/volatile-nonvolatile.ll new file mode 100644 index 00000000000..8c74f8b28ef --- /dev/null +++ b/llvm/test/Transforms/NewGVN/volatile-nonvolatile.ll @@ -0,0 +1,62 @@ +; XFAIL: * +; RUN: opt -tbaa -newgvn -S < %s | FileCheck %s + +%struct.t = type { i32* } + +; The loaded address and the location of the address itself are not aliased, +; so the second reload is not necessary. Check that it can be eliminated. +; CHECK-LABEL: test1 +; CHECK: load +; CHECK-NOT: load +define void @test1(%struct.t* nocapture readonly %p, i32 %v) #0 { +entry: + %m = getelementptr inbounds %struct.t, %struct.t* %p, i32 0, i32 0 + %0 = load i32*, i32** %m, align 4, !tbaa !1 + store volatile i32 %v, i32* %0, align 4, !tbaa !6 + %1 = load i32*, i32** %m, align 4, !tbaa !1 + store volatile i32 %v, i32* %1, align 4, !tbaa !6 + ret void +} + +; The store via the loaded address may overwrite the address itself. +; Make sure that both loads remain. +; CHECK-LABEL: test2 +; CHECK: load +; CHECK: store +; CHECK: load +define void @test2(%struct.t* nocapture readonly %p, i32 %v) #0 { +entry: + %m = getelementptr inbounds %struct.t, %struct.t* %p, i32 0, i32 0 + %0 = load i32*, i32** %m, align 4, !tbaa !1 + store volatile i32 %v, i32* %0, align 4, !tbaa !1 + %1 = load i32*, i32** %m, align 4, !tbaa !1 + store volatile i32 %v, i32* %1, align 4, !tbaa !1 + ret void +} + +; The loads are ordered and non-monotonic. Although they are not aliased to +; the stores, make sure both are preserved. +; CHECK-LABEL: test3 +; CHECK: load +; CHECK: store +; CHECK: load +define void @test3(%struct.t* nocapture readonly %p, i32 %v) #0 { +entry: + %m = getelementptr inbounds %struct.t, %struct.t* %p, i32 0, i32 0 + %0 = load atomic i32*, i32** %m acquire, align 4, !tbaa !1 + store volatile i32 %v, i32* %0, align 4, !tbaa !6 + %1 = load atomic i32*, i32** %m acquire, align 4, !tbaa !1 + store volatile i32 %v, i32* %1, align 4, !tbaa !6 + ret void +} + +attributes #0 = { norecurse nounwind } + +!1 = !{!2, !3, i64 0} +!2 = !{!"", !3, i64 0} +!3 = !{!"any pointer", !4, i64 0} +!4 = !{!"omnipotent char", !5, i64 0} +!5 = !{!"Simple C/C++ TBAA"} +!6 = !{!7, !7, i64 0} +!7 = !{!"int", !4, i64 0} + |