diff options
author | Shih-wei Liao <sliao@google.com> | 2010-02-10 11:10:31 -0800 |
---|---|---|
committer | Shih-wei Liao <sliao@google.com> | 2010-02-10 11:10:31 -0800 |
commit | e264f62ca09a8f65c87a46d562a4d0f9ec5d457e (patch) | |
tree | 59e3d57ef656cef79afa708ae0a3daf25cd91fcf /test/Transforms/GVN | |
download | external_llvm-e264f62ca09a8f65c87a46d562a4d0f9ec5d457e.zip external_llvm-e264f62ca09a8f65c87a46d562a4d0f9ec5d457e.tar.gz external_llvm-e264f62ca09a8f65c87a46d562a4d0f9ec5d457e.tar.bz2 |
Check in LLVM r95781.
Diffstat (limited to 'test/Transforms/GVN')
55 files changed, 3666 insertions, 0 deletions
diff --git a/test/Transforms/GVN/2007-07-25-DominatedLoop.ll b/test/Transforms/GVN/2007-07-25-DominatedLoop.ll new file mode 100644 index 0000000..ad580ce --- /dev/null +++ b/test/Transforms/GVN/2007-07-25-DominatedLoop.ll @@ -0,0 +1,86 @@ +; RUN: opt < %s -gvn | 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* @PL_sv_count, align 4 ; <i32> [#uses=0] + br label %cond_next165 + +bb157: ; preds = %cond_next165 + %tmp158 = load 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/test/Transforms/GVN/2007-07-25-InfiniteLoop.ll b/test/Transforms/GVN/2007-07-25-InfiniteLoop.ll new file mode 100644 index 0000000..2e0a101 --- /dev/null +++ b/test/Transforms/GVN/2007-07-25-InfiniteLoop.ll @@ -0,0 +1,14 @@ +; RUN: opt < %s -gvn -S | not grep {tmp10 =} + + %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** @blkshifts, align 4 ; <%struct.INT2*> [#uses=0] + br label %bb +} diff --git a/test/Transforms/GVN/2007-07-25-Loop.ll b/test/Transforms/GVN/2007-07-25-Loop.ll new file mode 100644 index 0000000..6a9f58e --- /dev/null +++ b/test/Transforms/GVN/2007-07-25-Loop.ll @@ -0,0 +1,15 @@ +; RUN: opt < %s -gvn | 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* null, align 2 ; <i16> [#uses=0] + ret void +} diff --git a/test/Transforms/GVN/2007-07-25-NestedLoop.ll b/test/Transforms/GVN/2007-07-25-NestedLoop.ll new file mode 100644 index 0000000..c6d7750 --- /dev/null +++ b/test/Transforms/GVN/2007-07-25-NestedLoop.ll @@ -0,0 +1,38 @@ +; RUN: opt < %s -gvn | 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* %hdR, i32 0, i32 0 ; <i32*> [#uses=1] + %tmp56220 = load 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* %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* %tmp67711 ; <i32> [#uses=0] + br i1 false, label %bb684, label %bb656 + +bb675.preheader: ; preds = %bb556.preheader + %tmp67711 = getelementptr %struct.TypHeader* %hdR, i32 0, i32 0 ; <i32*> [#uses=1] + %tmp677 = getelementptr %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/test/Transforms/GVN/2007-07-25-SinglePredecessor.ll b/test/Transforms/GVN/2007-07-25-SinglePredecessor.ll new file mode 100644 index 0000000..ecff657 --- /dev/null +++ b/test/Transforms/GVN/2007-07-25-SinglePredecessor.ll @@ -0,0 +1,29 @@ +; RUN: opt < %s -gvn | 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* %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* %VHR, i32 0, i32 1, i32 0, i32 0 ; <double*> [#uses=1] + %tmp46 = load double* %tmp3.i8 ; <double> [#uses=0] + ret i32 1 + +return: ; preds = %cond_next.i, %entry + ret i32 0 +} diff --git a/test/Transforms/GVN/2007-07-26-InterlockingLoops.ll b/test/Transforms/GVN/2007-07-26-InterlockingLoops.ll new file mode 100644 index 0000000..0be3379 --- /dev/null +++ b/test/Transforms/GVN/2007-07-26-InterlockingLoops.ll @@ -0,0 +1,30 @@ +; RUN: opt < %s -gvn -S | grep {tmp17625.* = phi i32. } +; RUN: opt < %s -gvn -S | grep {tmp17631.* = phi i32. } + +@last = external global [65 x i32*] ; <[65 x i32*]*> [#uses=1] + +define i32 @NextRootMove(i32 %wtm) { +cond_next95: ; preds = %cond_true85, %cond_true79, %cond_true73, %bb68 + %tmp17618 = load i32** getelementptr ([65 x i32*]* @last, i32 0, i32 1), align 4 ; <i32*> [#uses=0] + br label %cond_true116 + +cond_true116: ; preds = %cond_true111 + br i1 false, label %cond_true128, label %cond_true145 + +cond_true128: ; preds = %cond_true121 + %tmp17625 = load i32** getelementptr ([65 x i32*]* @last, i32 0, i32 1), align 4 ; <i32*> [#uses=0] + br i1 false, label %bb98.backedge, label %return.loopexit + +bb98.backedge: ; preds = %bb171, %cond_true145, %cond_true128 + br label %cond_true116 + +cond_true145: ; preds = %cond_false + %tmp17631 = load i32** getelementptr ([65 x i32*]* @last, i32 0, i32 1), align 4 ; <i32*> [#uses=0] + br i1 false, label %bb98.backedge, label %return.loopexit + +return.loopexit: ; preds = %bb171, %cond_true145, %cond_true128 + br label %return + +return: ; preds = %return.loopexit, %cond_next95, %cond_true85 + ret i32 0 +} diff --git a/test/Transforms/GVN/2007-07-26-NonRedundant.ll b/test/Transforms/GVN/2007-07-26-NonRedundant.ll new file mode 100644 index 0000000..7579e8a --- /dev/null +++ b/test/Transforms/GVN/2007-07-26-NonRedundant.ll @@ -0,0 +1,16 @@ +; RUN: opt < %s -gvn | 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* @bsLive, align 4 ; <i32> [#uses=0] + ret i32 0 +} diff --git a/test/Transforms/GVN/2007-07-26-PhiErasure.ll b/test/Transforms/GVN/2007-07-26-PhiErasure.ll new file mode 100644 index 0000000..d898ab8 --- /dev/null +++ b/test/Transforms/GVN/2007-07-26-PhiErasure.ll @@ -0,0 +1,28 @@ +; RUN: opt < %s -gvn -S | not grep phi + + %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* @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* @n_spills, align 4 ; <i32> [#uses=0] + ret i32 %tmp298316 + +} diff --git a/test/Transforms/GVN/2007-07-30-PredIDom.ll b/test/Transforms/GVN/2007-07-30-PredIDom.ll new file mode 100644 index 0000000..5cb6bb3 --- /dev/null +++ b/test/Transforms/GVN/2007-07-30-PredIDom.ll @@ -0,0 +1,274 @@ +; RUN: opt < %s -gvn | 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** null ; <i8*> [#uses=1] + ret i8* %retval980 +} diff --git a/test/Transforms/GVN/2007-07-31-NoDomInherit.ll b/test/Transforms/GVN/2007-07-31-NoDomInherit.ll new file mode 100644 index 0000000..faa1157 --- /dev/null +++ b/test/Transforms/GVN/2007-07-31-NoDomInherit.ll @@ -0,0 +1,313 @@ +; RUN: opt < %s -gvn -S | grep {tmp47 = phi i32 } + + %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* @numi ; <i32> [#uses=1] + %tmp2 = getelementptr [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* %i ; <i32> [#uses=1] + %tmp6 = load i32* %i ; <i32> [#uses=1] + %tmp7 = getelementptr [17 x i32]* @trialx, i32 0, i32 %tmp6 ; <i32*> [#uses=1] + %tmp8 = load i32* %tmp7 ; <i32> [#uses=1] + %tmp9 = call i32 @userfun( i32 %tmp8 ) ; <i32> [#uses=1] + %tmp10 = getelementptr [17 x i32]* @correct_result, i32 0, i32 %tmp5 ; <i32*> [#uses=1] + store i32 %tmp9, i32* %tmp10 + %tmp11 = load 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* %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* %i ; <i32> [#uses=1] + %tmp20 = getelementptr [5 x { i32, [3 x i32] }]* @pgm, i32 0, i32 %tmp19 ; <{ i32, [3 x i32] }*> [#uses=1] + %tmp21 = getelementptr { i32, [3 x i32] }* %tmp20, i32 0, i32 0 ; <i32*> [#uses=1] + store i32 0, i32* %tmp21 + %tmp22 = load i32* %i ; <i32> [#uses=1] + %tmp23 = getelementptr [13 x %struct.anon]* @isa, i32 0, i32 0 ; <%struct.anon*> [#uses=1] + %tmp24 = getelementptr %struct.anon* %tmp23, i32 0, i32 3 ; <[3 x i32]*> [#uses=1] + %tmp25 = getelementptr [3 x i32]* %tmp24, i32 0, i32 0 ; <i32*> [#uses=1] + %tmp26 = load i32* %tmp25 ; <i32> [#uses=1] + %tmp27 = getelementptr [5 x { i32, [3 x i32] }]* @pgm, i32 0, i32 %tmp22 ; <{ i32, [3 x i32] }*> [#uses=1] + %tmp28 = getelementptr { i32, [3 x i32] }* %tmp27, i32 0, i32 1 ; <[3 x i32]*> [#uses=1] + %tmp29 = getelementptr [3 x i32]* %tmp28, i32 0, i32 0 ; <i32*> [#uses=1] + store i32 %tmp26, i32* %tmp29 + %tmp30 = load i32* %i ; <i32> [#uses=1] + %tmp31 = getelementptr [13 x %struct.anon]* @isa, i32 0, i32 0 ; <%struct.anon*> [#uses=1] + %tmp32 = getelementptr %struct.anon* %tmp31, i32 0, i32 3 ; <[3 x i32]*> [#uses=1] + %tmp33 = getelementptr [3 x i32]* %tmp32, i32 0, i32 1 ; <i32*> [#uses=1] + %tmp34 = load i32* %tmp33 ; <i32> [#uses=1] + %tmp35 = getelementptr [5 x { i32, [3 x i32] }]* @pgm, i32 0, i32 %tmp30 ; <{ i32, [3 x i32] }*> [#uses=1] + %tmp36 = getelementptr { i32, [3 x i32] }* %tmp35, i32 0, i32 1 ; <[3 x i32]*> [#uses=1] + %tmp37 = getelementptr [3 x i32]* %tmp36, i32 0, i32 1 ; <i32*> [#uses=1] + store i32 %tmp34, i32* %tmp37 + %tmp38 = load i32* %i ; <i32> [#uses=1] + %tmp39 = getelementptr [13 x %struct.anon]* @isa, i32 0, i32 0 ; <%struct.anon*> [#uses=1] + %tmp40 = getelementptr %struct.anon* %tmp39, i32 0, i32 3 ; <[3 x i32]*> [#uses=1] + %tmp41 = getelementptr [3 x i32]* %tmp40, i32 0, i32 2 ; <i32*> [#uses=1] + %tmp42 = load i32* %tmp41 ; <i32> [#uses=1] + %tmp43 = getelementptr [5 x { i32, [3 x i32] }]* @pgm, i32 0, i32 %tmp38 ; <{ i32, [3 x i32] }*> [#uses=1] + %tmp44 = getelementptr { i32, [3 x i32] }* %tmp43, i32 0, i32 1 ; <[3 x i32]*> [#uses=1] + %tmp45 = getelementptr [3 x i32]* %tmp44, i32 0, i32 2 ; <i32*> [#uses=1] + store i32 %tmp42, i32* %tmp45 + %tmp46 = load i32* %i ; <i32> [#uses=1] + call void @fix_operands( i32 %tmp46 ) + %tmp47 = load i32* %i ; <i32> [#uses=1] + %tmp48 = add i32 %tmp47, 1 ; <i32> [#uses=1] + store i32 %tmp48, i32* %i + br label %bb49 + +bb49: ; preds = %bb18, %bb17 + %tmp50 = load i32* @numi ; <i32> [#uses=1] + %tmp51 = load 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]* @.str44, i32 0, i32 0 ; <i8*> [#uses=1] + %tmp58 = load i32* %num_sol ; <i32> [#uses=1] + %tmp59 = call i32 (i8*, ...)* @printf( i8* %tmp57, i32 %tmp58 ) ; <i32> [#uses=0] + %tmp60 = load 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]* @.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* %i ; <i32> [#uses=1] + %tmp68 = getelementptr [5 x i32]* @counter, i32 0, i32 %tmp67 ; <i32*> [#uses=1] + %tmp69 = load i32* %tmp68 ; <i32> [#uses=1] + %tmp70 = getelementptr [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* %i ; <i32> [#uses=1] + %tmp73 = getelementptr [5 x i32]* @counter, i32 0, i32 %tmp72 ; <i32*> [#uses=1] + %tmp74 = load i32* %tmp73 ; <i32> [#uses=1] + %tmp75 = load i32* %total ; <i32> [#uses=1] + %tmp76 = add i32 %tmp74, %tmp75 ; <i32> [#uses=1] + store i32 %tmp76, i32* %total + %tmp77 = load 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* @numi ; <i32> [#uses=1] + %tmp81 = load 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]* @.str47, i32 0, i32 0 ; <i8*> [#uses=1] + %tmp87 = load 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* @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* @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* %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* %tmp ; <i32> [#uses=1] + store i32 %tmp103, i32* %retval + br label %return + +return: ; preds = %bb102 + %retval104 = load i32* %retval ; <i32> [#uses=1] + ret i32 %retval104 +} + +declare i32 @userfun(i32) diff --git a/test/Transforms/GVN/2007-07-31-RedundantPhi.ll b/test/Transforms/GVN/2007-07-31-RedundantPhi.ll new file mode 100644 index 0000000..0d1d8bc --- /dev/null +++ b/test/Transforms/GVN/2007-07-31-RedundantPhi.ll @@ -0,0 +1,22 @@ +; RUN: opt < %s -gvn -S | not grep {tmp701 =} + +@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* @img_width, align 2 ; <i16> [#uses=0] + ret i32 0 +} diff --git a/test/Transforms/GVN/2008-02-12-UndefLoad.ll b/test/Transforms/GVN/2008-02-12-UndefLoad.ll new file mode 100644 index 0000000..de2aa61 --- /dev/null +++ b/test/Transforms/GVN/2008-02-12-UndefLoad.ll @@ -0,0 +1,20 @@ +; RUN: opt < %s -gvn -S | not grep load +; 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* %c, i32 0, i32 0 ; <i32*> [#uses=1] + %tmp1 = getelementptr i32* %tmp, i32 1 ; <i32*> [#uses=2] + %tmp2 = load i32* %tmp1, align 4 ; <i32> [#uses=1] + %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/test/Transforms/GVN/2008-02-13-NewPHI.ll b/test/Transforms/GVN/2008-02-13-NewPHI.ll new file mode 100644 index 0000000..54998db --- /dev/null +++ b/test/Transforms/GVN/2008-02-13-NewPHI.ll @@ -0,0 +1,22 @@ +; RUN: opt < %s -anders-aa -gvn +; 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** %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* null, align 4 ; <i32> [#uses=1] + ret i32 %retval59 +} diff --git a/test/Transforms/GVN/2008-02-24-NonDominatedMemcpy.ll b/test/Transforms/GVN/2008-02-24-NonDominatedMemcpy.ll new file mode 100644 index 0000000..9a75e1a --- /dev/null +++ b/test/Transforms/GVN/2008-02-24-NonDominatedMemcpy.ll @@ -0,0 +1,25 @@ +; RUN: opt < %s -gvn -dse -S | grep {call.*memcpy} | count 1 + +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-darwin8" + %struct.ggFrame3 = type { %struct.ggPoint3, %struct.ggONB3 } + %struct.ggHMatrix3 = type { [4 x [4 x double]] } + %struct.ggONB3 = type { %struct.ggPoint3, %struct.ggPoint3, %struct.ggPoint3 } + %struct.ggPoint3 = type { [3 x double] } + %struct.ggQuaternion = type { [4 x double], i32, %struct.ggHMatrix3 } + +declare void @llvm.memcpy.i64(i8*, i8*, i64, i32) nounwind + +define void @_Z10ggCRSplineRK8ggFrame3S1_S1_S1_d(%struct.ggFrame3* noalias sret %agg.result, %struct.ggFrame3* %f0, %struct.ggFrame3* %f1, %struct.ggFrame3* %f2, %struct.ggFrame3* %f3, double %t) nounwind { +entry: + %qresult = alloca %struct.ggQuaternion ; <%struct.ggQuaternion*> [#uses=1] + %tmp = alloca %struct.ggONB3 ; <%struct.ggONB3*> [#uses=2] + call void @_ZN12ggQuaternion7getONB3Ev( %struct.ggONB3* noalias sret %tmp, %struct.ggQuaternion* %qresult ) nounwind + %tmp1.i = getelementptr %struct.ggFrame3* %agg.result, i32 0, i32 1 ; <%struct.ggONB3*> [#uses=1] + %tmp13.i = bitcast %struct.ggONB3* %tmp1.i to i8* ; <i8*> [#uses=1] + %tmp24.i = bitcast %struct.ggONB3* %tmp to i8* ; <i8*> [#uses=1] + call void @llvm.memcpy.i64( i8* %tmp13.i, i8* %tmp24.i, i64 72, i32 8 ) nounwind + ret void +} + +declare void @_ZN12ggQuaternion7getONB3Ev(%struct.ggONB3* noalias sret , %struct.ggQuaternion*) nounwind diff --git a/test/Transforms/GVN/2008-02-26-MemCpySize.ll b/test/Transforms/GVN/2008-02-26-MemCpySize.ll new file mode 100644 index 0000000..6ed8a76 --- /dev/null +++ b/test/Transforms/GVN/2008-02-26-MemCpySize.ll @@ -0,0 +1,46 @@ +; RUN: opt < %s -gvn -dse -S | grep {call.*memcpy.*cell} | count 2 +; PR2099 + +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 = "i686-apple-darwin9" + %struct.s = type { [11 x i8], i32 } +@.str = internal constant [11 x i8] c"0123456789\00" ; <[11 x i8]*> [#uses=1] +@cell = weak global %struct.s zeroinitializer ; <%struct.s*> [#uses=2] + +declare i32 @check(%struct.s* byval %p) nounwind + +declare i32 @strcmp(i8*, i8*) nounwind readonly + +define i32 @main() noreturn nounwind { +entry: + %p = alloca %struct.s, align 8 ; <%struct.s*> [#uses=2] + store i32 99, i32* getelementptr (%struct.s* @cell, i32 0, i32 1), align 4 + call void @llvm.memcpy.i32( i8* getelementptr (%struct.s* @cell, i32 0, i32 0, i32 0), i8* getelementptr ([11 x i8]* @.str, i32 0, i32 0), i32 11, i32 1 ) + %tmp = getelementptr %struct.s* %p, i32 0, i32 0, i32 0 ; <i8*> [#uses=2] + call void @llvm.memcpy.i64( i8* %tmp, i8* getelementptr (%struct.s* @cell, i32 0, i32 0, i32 0), i64 16, i32 8 ) + %tmp1.i = getelementptr %struct.s* %p, i32 0, i32 1 ; <i32*> [#uses=1] + %tmp2.i = load i32* %tmp1.i, align 4 ; <i32> [#uses=1] + %tmp3.i = icmp eq i32 %tmp2.i, 99 ; <i1> [#uses=1] + br i1 %tmp3.i, label %bb5.i, label %bb + +bb5.i: ; preds = %entry + %tmp91.i = call i32 @strcmp( i8* %tmp, i8* getelementptr ([11 x i8]* @.str, i32 0, i32 0) ) nounwind readonly ; <i32> [#uses=1] + %tmp53 = icmp eq i32 %tmp91.i, 0 ; <i1> [#uses=1] + br i1 %tmp53, label %bb7, label %bb + +bb: ; preds = %bb5.i, %entry + call void @abort( ) noreturn nounwind + unreachable + +bb7: ; preds = %bb5.i + call void @exit( i32 0 ) noreturn nounwind + unreachable +} + +declare void @llvm.memcpy.i32(i8*, i8*, i32, i32) nounwind + +declare void @abort() noreturn nounwind + +declare void @exit(i32) noreturn nounwind + +declare void @llvm.memcpy.i64(i8*, i8*, i64, i32) nounwind diff --git a/test/Transforms/GVN/2008-07-02-Unreachable.ll b/test/Transforms/GVN/2008-07-02-Unreachable.ll new file mode 100644 index 0000000..361c155 --- /dev/null +++ b/test/Transforms/GVN/2008-07-02-Unreachable.ll @@ -0,0 +1,35 @@ +; RUN: opt < %s -gvn -S | grep {ret i8 \[%\]tmp3} +; PR2503 + +@g_3 = external global i8 ; <i8*> [#uses=2] + +define i8 @func_1() nounwind { +entry: + br i1 false, label %ifelse, label %ifthen + +ifthen: ; preds = %entry + br label %ifend + +ifelse: ; preds = %entry + %tmp3 = load i8* @g_3 ; <i8> [#uses=0] + br label %forcond.thread + +forcond.thread: ; preds = %ifelse + 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* @g_3 ; <i8> [#uses=0] + ret i8 %tmp10 + +ifend: ; preds = %afterfor, %ifthen + ret i8 0 +} diff --git a/test/Transforms/GVN/2008-12-09-SelfRemove.ll b/test/Transforms/GVN/2008-12-09-SelfRemove.ll new file mode 100644 index 0000000..c6833e3 --- /dev/null +++ b/test/Transforms/GVN/2008-12-09-SelfRemove.ll @@ -0,0 +1,26 @@ +; RUN: opt < %s -gvn -S | grep getelementptr | count 1 + +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* %dpi, i32 0, i32 1 ; <i8**> [#uses=1] + br i1 false, label %return, label %bb + +bb: ; preds = %entry + %1 = load i8** %0, align 4 ; <i8*> [#uses=0] + %2 = getelementptr %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 +} diff --git a/test/Transforms/GVN/2008-12-12-RLE-Crash.ll b/test/Transforms/GVN/2008-12-12-RLE-Crash.ll new file mode 100644 index 0000000..da67ee7 --- /dev/null +++ b/test/Transforms/GVN/2008-12-12-RLE-Crash.ll @@ -0,0 +1,35 @@ +; RUN: opt < %s -gvn | 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* %opt.0, align 1 ; <i8> [#uses=0] + %tmp1 = getelementptr 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* %opt.0, align 1 ; <i8> [#uses=0] + br i1 false, label %bb84, label %bb41 + +bb84: ; preds = %bb82, %entry + %tmp3 = getelementptr i8* null, i32 1 ; <i8*> [#uses=1] + br label %bb82 +} diff --git a/test/Transforms/GVN/2008-12-14-rle-reanalyze.ll b/test/Transforms/GVN/2008-12-14-rle-reanalyze.ll new file mode 100644 index 0000000..41f76c8 --- /dev/null +++ b/test/Transforms/GVN/2008-12-14-rle-reanalyze.ll @@ -0,0 +1,18 @@ +; RUN: opt < %s -gvn | 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]* @sort_value, i32 0, i32 0), %bb22 ], [ %sortv.2, %bb23 ] ; <i32*> [#uses=1] + %0 = load i32* %sortv.233, align 4 ; <i32> [#uses=0] + %sortv.2 = getelementptr [256 x i32]* @sort_value, i32 0, i32 0 ; <i32*> [#uses=1] + br i1 false, label %bb23, label %bb22 +} diff --git a/test/Transforms/GVN/2008-12-15-CacheVisited.ll b/test/Transforms/GVN/2008-12-15-CacheVisited.ll new file mode 100644 index 0000000..0a63f3f --- /dev/null +++ b/test/Transforms/GVN/2008-12-15-CacheVisited.ll @@ -0,0 +1,28 @@ +; RUN: opt < %s -gvn | 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* %decl, i32 1 ; <i32*> [#uses=1] + %tmp1 = load i32* %tmp, align 4 ; <i32> [#uses=0] + br i1 false, label %bb207, label %bb204 + +bb204: ; preds = %bb203 + %tmp2 = getelementptr 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* %iftmp.1374.0.in ; <i32> [#uses=0] + unreachable +} diff --git a/test/Transforms/GVN/2009-01-21-SortInvalidation.ll b/test/Transforms/GVN/2009-01-21-SortInvalidation.ll new file mode 100644 index 0000000..3677593 --- /dev/null +++ b/test/Transforms/GVN/2009-01-21-SortInvalidation.ll @@ -0,0 +1,55 @@ +; RUN: opt < %s -gvn | 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* %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/test/Transforms/GVN/2009-01-22-SortInvalidation.ll b/test/Transforms/GVN/2009-01-22-SortInvalidation.ll new file mode 100644 index 0000000..95690a5 --- /dev/null +++ b/test/Transforms/GVN/2009-01-22-SortInvalidation.ll @@ -0,0 +1,100 @@ +; RUN: opt < %s -gvn | 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** %3, align 4 ; <%struct..4sPragmaType*> [#uses=0] + br label %bb65 + +bb65: ; preds = %bb63.preheader, %bb59 + %1 = load %struct..4sPragmaType** %4, align 4 ; <%struct..4sPragmaType*> [#uses=0] + br i1 false, label %bb67, label %bb63.preheader + +bb67: ; preds = %bb65 + %2 = getelementptr %struct.IdList* %pColumn, i32 0, i32 0 ; <%struct..4sPragmaType**> [#uses=0] + unreachable + +bb69.loopexit: ; preds = %bb54, %entry + %3 = getelementptr %struct.IdList* %pColumn, i32 0, i32 0 ; <%struct..4sPragmaType**> [#uses=1] + %4 = getelementptr %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/test/Transforms/GVN/2009-02-17-LoadPRECrash.ll b/test/Transforms/GVN/2009-02-17-LoadPRECrash.ll new file mode 100644 index 0000000..c2d57a1 --- /dev/null +++ b/test/Transforms/GVN/2009-02-17-LoadPRECrash.ll @@ -0,0 +1,193 @@ +; RUN: opt < %s -gvn -enable-load-pre -disable-output + + %struct.VEC_rtx_base = type { i32, i32, [1 x %struct.rtx_def*] } + %struct.VEC_rtx_gc = type { %struct.VEC_rtx_base } + %struct.block_symbol = type { [3 x %struct.cgraph_rtl_info], %struct.object_block*, i64 } + %struct.cgraph_rtl_info = type { i32 } + %struct.object_block = type { %struct.section*, i32, i64, %struct.VEC_rtx_gc*, %struct.VEC_rtx_gc* } + %struct.rtvec_def = type { i32, [1 x %struct.rtx_def*] } + %struct.rtx_def = type { i16, i8, i8, %struct.u } + %struct.section = type { %struct.unnamed_section } + %struct.u = type { %struct.block_symbol } + %struct.unnamed_section = type { %struct.cgraph_rtl_info, void (i8*)*, i8*, %struct.section* } + +declare %struct.rtvec_def* @gen_rtvec(i32, ...) + +declare %struct.rtx_def* @plus_constant(%struct.rtx_def*, i64) + +declare %struct.rtx_def* @gen_rtx_fmt_Ei(i32, i32, %struct.rtvec_def*, i32) + +declare i32 @local_symbolic_operand(%struct.rtx_def*, i32) + +define %struct.rtx_def* @legitimize_pic_address(%struct.rtx_def* %orig, %struct.rtx_def* %reg) nounwind { +entry: + %addr = alloca %struct.rtx_def* ; <%struct.rtx_def**> [#uses=5] + %iftmp.1532 = alloca %struct.rtx_def* ; <%struct.rtx_def**> [#uses=3] + store %struct.rtx_def* %orig, %struct.rtx_def** null + %0 = load %struct.rtx_def** null, align 4 ; <%struct.rtx_def*> [#uses=0] + br i1 false, label %bb96, label %bb59 + +bb59: ; preds = %entry + %1 = load %struct.rtx_def** %addr, align 4 ; <%struct.rtx_def*> [#uses=1] + %2 = call i32 @local_symbolic_operand(%struct.rtx_def* %1, i32 0) nounwind ; <i32> [#uses=0] + br i1 false, label %bb96, label %bb63 + +bb63: ; preds = %bb59 + br i1 false, label %bb64, label %bb74 + +bb64: ; preds = %bb63 + br i1 false, label %bb72, label %bb65 + +bb65: ; preds = %bb64 + br label %bb72 + +bb72: ; preds = %bb65, %bb64 + br label %bb74 + +bb74: ; preds = %bb72, %bb63 + br i1 false, label %bb75, label %bb76 + +bb75: ; preds = %bb74 + br label %bb76 + +bb76: ; preds = %bb75, %bb74 + br i1 false, label %bb77, label %bb84 + +bb77: ; preds = %bb76 + %3 = getelementptr [1 x %struct.cgraph_rtl_info]* null, i32 0, i32 0 ; <%struct.cgraph_rtl_info*> [#uses=0] + unreachable + +bb84: ; preds = %bb76 + br i1 false, label %bb85, label %bb86 + +bb85: ; preds = %bb84 + br label %bb87 + +bb86: ; preds = %bb84 + br label %bb87 + +bb87: ; preds = %bb86, %bb85 + %4 = call %struct.rtx_def* @gen_rtx_fmt_Ei(i32 16, i32 0, %struct.rtvec_def* null, i32 1) nounwind ; <%struct.rtx_def*> [#uses=0] + br i1 false, label %bb89, label %bb90 + +bb89: ; preds = %bb87 + br label %bb91 + +bb90: ; preds = %bb87 + br label %bb91 + +bb91: ; preds = %bb90, %bb89 + br i1 false, label %bb92, label %bb93 + +bb92: ; preds = %bb91 + br label %bb94 + +bb93: ; preds = %bb91 + br label %bb94 + +bb94: ; preds = %bb93, %bb92 + unreachable + +bb96: ; preds = %bb59, %entry + %5 = load %struct.rtx_def** %addr, align 4 ; <%struct.rtx_def*> [#uses=1] + %6 = getelementptr %struct.rtx_def* %5, i32 0, i32 0 ; <i16*> [#uses=1] + %7 = load i16* %6, align 2 ; <i16> [#uses=0] + br i1 false, label %bb147, label %bb97 + +bb97: ; preds = %bb96 + %8 = load %struct.rtx_def** %addr, align 4 ; <%struct.rtx_def*> [#uses=0] + br i1 false, label %bb147, label %bb99 + +bb99: ; preds = %bb97 + unreachable + +bb147: ; preds = %bb97, %bb96 + %9 = load %struct.rtx_def** %addr, align 4 ; <%struct.rtx_def*> [#uses=1] + %10 = getelementptr %struct.rtx_def* %9, i32 0, i32 0 ; <i16*> [#uses=1] + %11 = load i16* %10, align 2 ; <i16> [#uses=0] + br i1 false, label %bb164, label %bb148 + +bb148: ; preds = %bb147 + br i1 false, label %bb164, label %bb149 + +bb149: ; preds = %bb148 + br i1 false, label %bb150, label %bb152 + +bb150: ; preds = %bb149 + unreachable + +bb152: ; preds = %bb149 + br label %bb164 + +bb164: ; preds = %bb152, %bb148, %bb147 + %12 = getelementptr [1 x %struct.cgraph_rtl_info]* null, i32 0, i32 1 ; <%struct.cgraph_rtl_info*> [#uses=0] + br i1 false, label %bb165, label %bb166 + +bb165: ; preds = %bb164 + br label %bb167 + +bb166: ; preds = %bb164 + br label %bb167 + +bb167: ; preds = %bb166, %bb165 + br i1 false, label %bb211, label %bb168 + +bb168: ; preds = %bb167 + br i1 false, label %bb211, label %bb170 + +bb170: ; preds = %bb168 + br i1 false, label %bb172, label %bb181 + +bb172: ; preds = %bb170 + br i1 false, label %bb179, label %bb174 + +bb174: ; preds = %bb172 + br i1 false, label %bb177, label %bb175 + +bb175: ; preds = %bb174 + br i1 false, label %bb177, label %bb176 + +bb176: ; preds = %bb175 + br label %bb178 + +bb177: ; preds = %bb175, %bb174 + br label %bb178 + +bb178: ; preds = %bb177, %bb176 + br label %bb180 + +bb179: ; preds = %bb172 + br label %bb180 + +bb180: ; preds = %bb179, %bb178 + br label %bb181 + +bb181: ; preds = %bb180, %bb170 + %13 = call %struct.rtvec_def* (i32, ...)* @gen_rtvec(i32 1, %struct.rtx_def* null) nounwind ; <%struct.rtvec_def*> [#uses=0] + unreachable + +bb211: ; preds = %bb168, %bb167 + %14 = load %struct.rtx_def** %addr, align 4 ; <%struct.rtx_def*> [#uses=0] + %15 = getelementptr [1 x %struct.cgraph_rtl_info]* null, i32 0, i32 0 ; <%struct.cgraph_rtl_info*> [#uses=0] + store %struct.rtx_def* null, %struct.rtx_def** null, align 4 + br i1 false, label %bb212, label %bb213 + +bb212: ; preds = %bb211 + store %struct.rtx_def* null, %struct.rtx_def** %iftmp.1532, align 4 + br label %bb214 + +bb213: ; preds = %bb211 + store %struct.rtx_def* null, %struct.rtx_def** %iftmp.1532, align 4 + br label %bb214 + +bb214: ; preds = %bb213, %bb212 + %16 = bitcast %struct.block_symbol* null to [1 x %struct.cgraph_rtl_info]* ; <[1 x %struct.cgraph_rtl_info]*> [#uses=1] + %17 = getelementptr [1 x %struct.cgraph_rtl_info]* %16, i32 0, i32 1 ; <%struct.cgraph_rtl_info*> [#uses=0] + %18 = load %struct.rtx_def** %iftmp.1532, align 4 ; <%struct.rtx_def*> [#uses=0] + %19 = getelementptr %struct.rtx_def* null, i32 0, i32 3 ; <%struct.u*> [#uses=1] + %20 = getelementptr %struct.u* %19, i32 0, i32 0 ; <%struct.block_symbol*> [#uses=1] + %21 = bitcast %struct.block_symbol* %20 to [1 x i64]* ; <[1 x i64]*> [#uses=1] + %22 = getelementptr [1 x i64]* %21, i32 0, i32 0 ; <i64*> [#uses=0] + %23 = call %struct.rtx_def* @plus_constant(%struct.rtx_def* null, i64 0) nounwind ; <%struct.rtx_def*> [#uses=0] + unreachable +} diff --git a/test/Transforms/GVN/2009-03-05-dbg.ll b/test/Transforms/GVN/2009-03-05-dbg.ll new file mode 100644 index 0000000..cad3312 --- /dev/null +++ b/test/Transforms/GVN/2009-03-05-dbg.ll @@ -0,0 +1,66 @@ +; RUN: opt < %s -gvn -disable-output + %llvm.dbg.compile_unit.type = type { i32, { }*, i32, i8*, i8*, i8*, i1, i1, i8*, i32 } +@llvm.dbg.compile_unit298 = external constant %llvm.dbg.compile_unit.type ; <%llvm.dbg.compile_unit.type*> [#uses=1] + +declare void @llvm.dbg.stoppoint(i32, i32, { }*) nounwind + +define i8* @__deregister_frame_info_bases(i8* %begin) { +entry: + br i1 false, label %bb17, label %bb + +bb: ; preds = %entry + br i1 false, label %bb17, label %bb6.preheader + +bb6.preheader: ; preds = %bb + br label %bb6 + +bb3: ; preds = %bb6 + br i1 false, label %bb4, label %bb6 + +bb4: ; preds = %bb3 + br label %out + +bb6: ; preds = %bb3, %bb6.preheader + br i1 false, label %bb14.loopexit, label %bb3 + +bb8: ; preds = %bb14 + br i1 false, label %bb9, label %bb11 + +bb9: ; preds = %bb8 + br i1 false, label %bb10, label %bb13 + +bb10: ; preds = %bb9 + br label %out + +bb11: ; preds = %bb8 + br i1 false, label %bb12, label %bb13 + +bb12: ; preds = %bb11 + br label %out + +bb13: ; preds = %bb11, %bb9 + br label %bb14 + +bb14.loopexit: ; preds = %bb6 + br label %bb14 + +bb14: ; preds = %bb14.loopexit, %bb13 + br i1 false, label %bb15.loopexit, label %bb8 + +out: ; preds = %bb12, %bb10, %bb4 + tail call void @llvm.dbg.stoppoint(i32 217, i32 0, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit298 to { }*)) + br i1 false, label %bb15, label %bb16 + +bb15.loopexit: ; preds = %bb14 + br label %bb15 + +bb15: ; preds = %bb15.loopexit, %out + tail call void @llvm.dbg.stoppoint(i32 217, i32 0, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit298 to { }*)) + unreachable + +bb16: ; preds = %out + ret i8* null + +bb17: ; preds = %bb, %entry + ret i8* null +} diff --git a/test/Transforms/GVN/2009-03-10-PREOnVoid.ll b/test/Transforms/GVN/2009-03-10-PREOnVoid.ll new file mode 100644 index 0000000..89d6a5f --- /dev/null +++ b/test/Transforms/GVN/2009-03-10-PREOnVoid.ll @@ -0,0 +1,82 @@ +; RUN: opt < %s -gvn -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 = alias weak i32 (i32*, void ()*)* @pthread_once ; <i32 (i32*, void ()*)*> [#uses=0] +@_ZL27__gthrw_pthread_getspecificj = alias weak i8* (i32)* @pthread_getspecific ; <i8* (i32)*> [#uses=0] +@_ZL27__gthrw_pthread_setspecificjPKv = alias weak i32 (i32, i8*)* @pthread_setspecific ; <i32 (i32, i8*)*> [#uses=0] +@_ZL22__gthrw_pthread_createPmPK16__pthread_attr_sPFPvS3_ES3_ = alias weak 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 = alias weak i32 (i32)* @pthread_cancel ; <i32 (i32)*> [#uses=0] +@_ZL26__gthrw_pthread_mutex_lockP15pthread_mutex_t = alias weak i32 (%struct.pthread_mutex_t*)* @pthread_mutex_lock ; <i32 (%struct.pthread_mutex_t*)*> [#uses=0] +@_ZL29__gthrw_pthread_mutex_trylockP15pthread_mutex_t = alias weak i32 (%struct.pthread_mutex_t*)* @pthread_mutex_trylock ; <i32 (%struct.pthread_mutex_t*)*> [#uses=0] +@_ZL28__gthrw_pthread_mutex_unlockP15pthread_mutex_t = alias weak i32 (%struct.pthread_mutex_t*)* @pthread_mutex_unlock ; <i32 (%struct.pthread_mutex_t*)*> [#uses=0] +@_ZL26__gthrw_pthread_mutex_initP15pthread_mutex_tPK19pthread_mutexattr_t = alias weak 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 = alias weak i32 (i32*, void (i8*)*)* @pthread_key_create ; <i32 (i32*, void (i8*)*)*> [#uses=0] +@_ZL26__gthrw_pthread_key_deletej = alias weak i32 (i32)* @pthread_key_delete ; <i32 (i32)*> [#uses=0] +@_ZL30__gthrw_pthread_mutexattr_initP19pthread_mutexattr_t = alias weak i32 (%struct.__sched_param*)* @pthread_mutexattr_init ; <i32 (%struct.__sched_param*)*> [#uses=0] +@_ZL33__gthrw_pthread_mutexattr_settypeP19pthread_mutexattr_ti = alias weak i32 (%struct.__sched_param*, i32)* @pthread_mutexattr_settype ; <i32 (%struct.__sched_param*, i32)*> [#uses=0] +@_ZL33__gthrw_pthread_mutexattr_destroyP19pthread_mutexattr_t = alias weak 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 +} + +declare i32 @pthread_once(i32*, void ()*) + +declare i8* @pthread_getspecific(i32) + +declare i32 @pthread_setspecific(i32, i8*) + +declare i32 @pthread_create(i32*, %struct.pthread_attr_t*, i8* (i8*)*, i8*) + +declare i32 @pthread_cancel(i32) + +declare i32 @pthread_mutex_lock(%struct.pthread_mutex_t*) + +declare i32 @pthread_mutex_trylock(%struct.pthread_mutex_t*) + +declare i32 @pthread_mutex_unlock(%struct.pthread_mutex_t*) + +declare i32 @pthread_mutex_init(%struct.pthread_mutex_t*, %struct.__sched_param*) + +declare i32 @pthread_key_create(i32*, void (i8*)*) + +declare i32 @pthread_key_delete(i32) + +declare i32 @pthread_mutexattr_init(%struct.__sched_param*) + +declare i32 @pthread_mutexattr_settype(%struct.__sched_param*, i32) + +declare i32 @pthread_mutexattr_destroy(%struct.__sched_param*) diff --git a/test/Transforms/GVN/2009-06-17-InvalidPRE.ll b/test/Transforms/GVN/2009-06-17-InvalidPRE.ll new file mode 100644 index 0000000..6ac6072 --- /dev/null +++ b/test/Transforms/GVN/2009-06-17-InvalidPRE.ll @@ -0,0 +1,72 @@ +; RUN: opt < %s -gvn -enable-load-pre -S | not grep pre1 +; GVN load pre was hoisting the loads at %13 and %16 up to bb4.outer. +; This is invalid as it bypasses the check for %m.0.ph==null in bb4. +; ModuleID = 'mbuf.c' +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.6" + %struct.mbuf = type { %struct.mbuf*, %struct.mbuf*, i32, i8*, i16, i16, i32 } + +define void @m_adj(%struct.mbuf* %mp, i32 %req_len) nounwind optsize { +entry: + %0 = icmp eq %struct.mbuf* %mp, null ; <i1> [#uses=1] + %1 = icmp slt i32 %req_len, 0 ; <i1> [#uses=1] + %or.cond = or i1 %1, %0 ; <i1> [#uses=1] + br i1 %or.cond, label %return, label %bb4.preheader + +bb4.preheader: ; preds = %entry + br label %bb4.outer + +bb2: ; preds = %bb1 + %2 = sub i32 %len.0, %13 ; <i32> [#uses=1] + %3 = getelementptr %struct.mbuf* %m.0.ph, i32 0, i32 2 ; <i32*> [#uses=1] + store i32 0, i32* %3, align 4 + %4 = getelementptr %struct.mbuf* %m.0.ph, i32 0, i32 0 ; <%struct.mbuf**> [#uses=1] + %5 = load %struct.mbuf** %4, align 4 ; <%struct.mbuf*> [#uses=1] + br label %bb4.outer + +bb4.outer: ; preds = %bb4.preheader, %bb2 + %m.0.ph = phi %struct.mbuf* [ %5, %bb2 ], [ %mp, %bb4.preheader ] ; <%struct.mbuf*> [#uses=7] + %len.0.ph = phi i32 [ %2, %bb2 ], [ %req_len, %bb4.preheader ] ; <i32> [#uses=1] + %6 = icmp ne %struct.mbuf* %m.0.ph, null ; <i1> [#uses=1] + %7 = getelementptr %struct.mbuf* %m.0.ph, i32 0, i32 2 ; <i32*> [#uses=1] + %8 = getelementptr %struct.mbuf* %m.0.ph, i32 0, i32 2 ; <i32*> [#uses=1] + %9 = getelementptr %struct.mbuf* %m.0.ph, i32 0, i32 3 ; <i8**> [#uses=1] + %10 = getelementptr %struct.mbuf* %m.0.ph, i32 0, i32 3 ; <i8**> [#uses=1] + br label %bb4 + +bb4: ; preds = %bb4.outer, %bb3 + %len.0 = phi i32 [ 0, %bb3 ], [ %len.0.ph, %bb4.outer ] ; <i32> [#uses=6] + %11 = icmp sgt i32 %len.0, 0 ; <i1> [#uses=1] + %12 = and i1 %11, %6 ; <i1> [#uses=1] + br i1 %12, label %bb1, label %bb7 + +bb1: ; preds = %bb4 + %13 = load i32* %7, align 4 ; <i32> [#uses=3] + %14 = icmp sgt i32 %13, %len.0 ; <i1> [#uses=1] + br i1 %14, label %bb3, label %bb2 + +bb3: ; preds = %bb1 + %15 = sub i32 %13, %len.0 ; <i32> [#uses=1] + store i32 %15, i32* %8, align 4 + %16 = load i8** %9, align 4 ; <i8*> [#uses=1] + %17 = getelementptr i8* %16, i32 %len.0 ; <i8*> [#uses=1] + store i8* %17, i8** %10, align 4 + br label %bb4 + +bb7: ; preds = %bb4 + %18 = getelementptr %struct.mbuf* %mp, i32 0, i32 5 ; <i16*> [#uses=1] + %19 = load i16* %18, align 2 ; <i16> [#uses=1] + %20 = zext i16 %19 to i32 ; <i32> [#uses=1] + %21 = and i32 %20, 2 ; <i32> [#uses=1] + %22 = icmp eq i32 %21, 0 ; <i1> [#uses=1] + br i1 %22, label %return, label %bb8 + +bb8: ; preds = %bb7 + %23 = sub i32 %req_len, %len.0 ; <i32> [#uses=1] + %24 = getelementptr %struct.mbuf* %mp, i32 0, i32 6 ; <i32*> [#uses=1] + store i32 %23, i32* %24, align 4 + ret void + +return: ; preds = %bb7, %entry + ret void +} diff --git a/test/Transforms/GVN/2009-07-13-MemDepSortFail.ll b/test/Transforms/GVN/2009-07-13-MemDepSortFail.ll new file mode 100644 index 0000000..641e920 --- /dev/null +++ b/test/Transforms/GVN/2009-07-13-MemDepSortFail.ll @@ -0,0 +1,67 @@ +; RUN: opt < %s -gvn | 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-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* %sp.1, align 1 ; <i8> [#uses=0] + br label %bb62 + +bb51: ; preds = %bb + %1 = load 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/test/Transforms/GVN/2009-11-12-MemDepMallocBitCast.ll b/test/Transforms/GVN/2009-11-12-MemDepMallocBitCast.ll new file mode 100644 index 0000000..b433297 --- /dev/null +++ b/test/Transforms/GVN/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 -gvn -S | FileCheck %s + +define i64 @test() { + %1 = tail call i8* @malloc(i64 mul (i64 4, i64 ptrtoint (i64* getelementptr (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* %X ; <i64> [#uses=1] + ret i64 %Y +; CHECK: %Y = load i64* %X +; CHECK: ret i64 %Y +} + +declare noalias i8* @malloc(i64) diff --git a/test/Transforms/GVN/basic.ll b/test/Transforms/GVN/basic.ll new file mode 100644 index 0000000..1decafa --- /dev/null +++ b/test/Transforms/GVN/basic.ll @@ -0,0 +1,10 @@ +; RUN: opt < %s -gvn -S | not grep {%z2 =} + +define i32 @main() { +block1: + %z1 = bitcast i32 0 to i32 + br label %block2 +block2: + %z2 = bitcast i32 0 to i32 + ret i32 %z2 +} diff --git a/test/Transforms/GVN/bitcast-of-call.ll b/test/Transforms/GVN/bitcast-of-call.ll new file mode 100644 index 0000000..55b4b6e --- /dev/null +++ b/test/Transforms/GVN/bitcast-of-call.ll @@ -0,0 +1,12 @@ +; RUN: opt < %s -gvn -S | not grep tmp2 +; 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] + ret i32* %tmp2 +} + +declare i8* @m(i32) diff --git a/test/Transforms/GVN/calls-nonlocal.ll b/test/Transforms/GVN/calls-nonlocal.ll new file mode 100644 index 0000000..f0edf09 --- /dev/null +++ b/test/Transforms/GVN/calls-nonlocal.ll @@ -0,0 +1,49 @@ +; RUN: opt < %s -gvn -S | grep strlen | count 2 +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-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 +} + +declare i32 @strlen(i8*) nounwind readonly diff --git a/test/Transforms/GVN/calls-readonly.ll b/test/Transforms/GVN/calls-readonly.ll new file mode 100644 index 0000000..97ec915 --- /dev/null +++ b/test/Transforms/GVN/calls-readonly.ll @@ -0,0 +1,29 @@ +; RUN: opt < %s -basicaa -gvn -S | grep {call.*strlen} | count 1 +; 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* %3, i32 %.sum ; <i8*> [#uses=1] + ret i8* %6 +} + +declare i32 @strlen(i8*) nounwind readonly + +declare i8* @strchr(i8*, i32) nounwind readonly diff --git a/test/Transforms/GVN/condprop.ll b/test/Transforms/GVN/condprop.ll new file mode 100644 index 0000000..e212d79 --- /dev/null +++ b/test/Transforms/GVN/condprop.ll @@ -0,0 +1,52 @@ +; RUN: opt < %s -gvn -S | grep {br i1 false} + +@a = external global i32 ; <i32*> [#uses=7] + +define i32 @foo() nounwind { +entry: + %0 = load i32* @a, align 4 ; <i32> [#uses=1] + %1 = icmp eq i32 %0, 4 ; <i1> [#uses=1] + br i1 %1, label %bb, label %bb1 + +bb: ; preds = %entry + br label %bb8 + +bb1: ; preds = %entry + %2 = load i32* @a, align 4 ; <i32> [#uses=1] + %3 = icmp eq i32 %2, 5 ; <i1> [#uses=1] + br i1 %3, label %bb2, label %bb3 + +bb2: ; preds = %bb1 + br label %bb8 + +bb3: ; preds = %bb1 + %4 = load i32* @a, align 4 ; <i32> [#uses=1] + %5 = icmp eq i32 %4, 4 ; <i1> [#uses=1] + br i1 %5, label %bb4, label %bb5 + +bb4: ; preds = %bb3 + %6 = load i32* @a, align 4 ; <i32> [#uses=1] + %7 = add i32 %6, 5 ; <i32> [#uses=1] + br label %bb8 + +bb5: ; preds = %bb3 + %8 = load i32* @a, align 4 ; <i32> [#uses=1] + %9 = icmp eq i32 %8, 5 ; <i1> [#uses=1] + br i1 %9, label %bb6, label %bb7 + +bb6: ; preds = %bb5 + %10 = load i32* @a, align 4 ; <i32> [#uses=1] + %11 = add i32 %10, 4 ; <i32> [#uses=1] + br label %bb8 + +bb7: ; preds = %bb5 + %12 = load i32* @a, align 4 ; <i32> [#uses=1] + br label %bb8 + +bb8: ; preds = %bb7, %bb6, %bb4, %bb2, %bb + %.0 = phi i32 [ %12, %bb7 ], [ %11, %bb6 ], [ %7, %bb4 ], [ 4, %bb2 ], [ 5, %bb ] ; <i32> [#uses=1] + br label %return + +return: ; preds = %bb8 + ret i32 %.0 +} diff --git a/test/Transforms/GVN/crash-no-aa.ll b/test/Transforms/GVN/crash-no-aa.ll new file mode 100644 index 0000000..dae65dd --- /dev/null +++ b/test/Transforms/GVN/crash-no-aa.ll @@ -0,0 +1,16 @@ +; RUN: opt -no-aa -gvn -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-v1 +28: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} *%P, i32 0, i32 0 + store i16 42, i16* %P2 + + %P3 = getelementptr {i16, i32} *%P, i32 0, i32 1 + %V = load i32* %P3 + ret i32 %V +} + diff --git a/test/Transforms/GVN/crash.ll b/test/Transforms/GVN/crash.ll new file mode 100644 index 0000000..9167b6e --- /dev/null +++ b/test/Transforms/GVN/crash.ll @@ -0,0 +1,137 @@ +; RUN: opt -gvn %s -disable-output + +; 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* @peel_to_type(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* %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* %tmp43 ; <i32> [#uses=0] + br i1 undef, label %if.then50, label %if.else + +if.then50: ; preds = %if.end41 + %tmp53 = load 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 @decl_attributes() nounwind { +entry: + br label %bb69.i + +bb69.i: ; preds = %bb57.i.preheader + %tmp4 = getelementptr inbounds [4 x %struct.attribute_spec*]* @attribute_tables, i32 0, i32 undef ; <%struct.attribute_spec**> [#uses=1] + %tmp3 = load %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* %tmp3, i32 %storemerge6.i, i32 0 ; <i8**> [#uses=1] + %tmp2 = load i8** %scevgep14, align 4 ; <i8*> [#uses=0] + %tmp = load %struct.attribute_spec** %tmp4, align 4 ; <%struct.attribute_spec*> [#uses=1] + %scevgep1516 = getelementptr inbounds %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* @foo() { +do.end17.i: + %tmp18.i = load 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* @g + %tmp3 = bitcast i7* %tmp18.i to i8* + %add.ptr39.sum.i = add i64 %ivar38.i, 8 + %tmp40.i = getelementptr inbounds i8* %tmp3, i64 %add.ptr39.sum.i + %tmp4 = bitcast i8* %tmp40.i to i64* + %tmp41.i = load 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** undef + %ivar59.i = load i64* @g + %tmp5 = bitcast i7* %tmp58.i to i8* + %add.ptr65.sum.i = add i64 %ivar59.i, 8 + %tmp66.i = getelementptr inbounds i8* %tmp5, i64 %add.ptr65.sum.i + %tmp6 = bitcast i8* %tmp66.i to i64* + %tmp67.i = load i64* %tmp6 + ret i32* undef +} + +declare i32 @foo2() + diff --git a/test/Transforms/GVN/dg.exp b/test/Transforms/GVN/dg.exp new file mode 100644 index 0000000..f200589 --- /dev/null +++ b/test/Transforms/GVN/dg.exp @@ -0,0 +1,3 @@ +load_lib llvm.exp + +RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll,c,cpp}]] diff --git a/test/Transforms/GVN/invariant-simple.ll b/test/Transforms/GVN/invariant-simple.ll new file mode 100644 index 0000000..6de75f1 --- /dev/null +++ b/test/Transforms/GVN/invariant-simple.ll @@ -0,0 +1,36 @@ +; RUN: opt < %s -gvn -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: @test +; CHECK-NOT: load +; CHECK: ret i8 +entry: + store i8 1, i8* %P + %0 = call {}* @llvm.invariant.start(i64 32, i8* %P) + %1 = tail call i32 @foo(i8* %P) + call void @llvm.invariant.end({}* %0, i64 32, i8* %P) + %2 = load i8* %P + ret i8 %2 +} + +define i8 @test2(i8* %P) nounwind { +; CHECK: @test2 +; CHECK: store i8 1 +; CHECK: store i8 2 +; CHECK: ret i8 0 +entry: + store i8 1, i8* %P + %0 = call {}* @llvm.invariant.start(i64 32, i8* %P) + %1 = tail call i32 @bar(i8* %P) + call void @llvm.invariant.end({}* %0, i64 32, i8* %P) + store i8 2, i8* %P + ret i8 0 +} + +declare i32 @foo(i8*) nounwind +declare i32 @bar(i8*) nounwind readonly +declare {}* @llvm.invariant.start(i64 %S, i8* nocapture %P) readonly +declare void @llvm.invariant.end({}* %S, i64 %SS, i8* nocapture %P)
\ No newline at end of file diff --git a/test/Transforms/GVN/lifetime-simple.ll b/test/Transforms/GVN/lifetime-simple.ll new file mode 100644 index 0000000..8139246 --- /dev/null +++ b/test/Transforms/GVN/lifetime-simple.ll @@ -0,0 +1,20 @@ +; RUN: opt < %s -gvn -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* %P + store i8 1, i8* %P + call void @llvm.lifetime.end(i64 32, i8* %P) + %1 = load i8* %P + ret i8 %1 +} + +declare {}* @llvm.lifetime.start(i64 %S, i8* nocapture %P) readonly +declare void @llvm.lifetime.end(i64 %S, i8* nocapture %P)
\ No newline at end of file diff --git a/test/Transforms/GVN/load-constant-mem.ll b/test/Transforms/GVN/load-constant-mem.ll new file mode 100644 index 0000000..87f33ea --- /dev/null +++ b/test/Transforms/GVN/load-constant-mem.ll @@ -0,0 +1,13 @@ +; RUN: opt < %s -gvn -instcombine -S | grep {ret i32 0} +; PR4189 +@G = external constant [4 x i32] + +define i32 @test(i8* %p, i32 %i) nounwind { +entry: + %P = getelementptr [4 x i32]* @G, i32 0, i32 %i + %A = load i32* %P + store i8 4, i8* %p + %B = load i32* %P + %C = sub i32 %A, %B + ret i32 %C +} diff --git a/test/Transforms/GVN/load-pre-align.ll b/test/Transforms/GVN/load-pre-align.ll new file mode 100644 index 0000000..3a66c0b --- /dev/null +++ b/test/Transforms/GVN/load-pre-align.ll @@ -0,0 +1,44 @@ +; RUN: opt < %s -gvn -S | FileCheck %s + +target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:64:64-v128:128:128-a0:0:32-n32" + +@p = external global i32 + +define arm_apcscc i32 @test(i32 %n) nounwind { +; CHECK: @test +entry: + br label %for.cond + +; loads aligned greater than the memory should not be moved past conditionals +; CHECK-NOT: load +; CHECK: br i1 + +for.cond: + %i.0 = phi i32 [ 0, %entry ], [ %indvar.next, %for.inc ] + %cmp = icmp slt i32 %i.0, %n + br i1 %cmp, label %for.body, label %for.cond.for.end_crit_edge + +for.cond.for.end_crit_edge: +; ...but PRE can still move the load out of for.end to here. +; CHECK: for.cond.for.end_crit_edge: +; CHECK-NEXT: load + br label %for.end + +for.body: + %tmp3 = load i32* @p, align 8 + %dec = add i32 %tmp3, -1 + store i32 %dec, i32* @p + %cmp6 = icmp slt i32 %dec, 0 + br i1 %cmp6, label %for.body.for.end_crit_edge, label %for.inc + +for.body.for.end_crit_edge: + br label %for.end + +for.inc: + %indvar.next = add i32 %i.0, 1 + br label %for.cond + +for.end: + %tmp9 = load i32* @p, align 8 + ret i32 %tmp9 +} diff --git a/test/Transforms/GVN/local-pre.ll b/test/Transforms/GVN/local-pre.ll new file mode 100644 index 0000000..5f03984 --- /dev/null +++ b/test/Transforms/GVN/local-pre.ll @@ -0,0 +1,18 @@ +; RUN: opt < %s -gvn -enable-pre -S | grep {b.pre} + +define i32 @main(i32 %p) { +block1: + + br i1 true, label %block2, label %block3 + +block2: + %a = add i32 %p, 1 + br label %block4 + +block3: + br label %block4 + +block4: + %b = add i32 %p, 1 + ret i32 %b +} diff --git a/test/Transforms/GVN/lpre-call-wrap-2.ll b/test/Transforms/GVN/lpre-call-wrap-2.ll new file mode 100644 index 0000000..79512a3 --- /dev/null +++ b/test/Transforms/GVN/lpre-call-wrap-2.ll @@ -0,0 +1,40 @@ +; RUN: opt -S -gvn -enable-load-pre %s | FileCheck %s +; +; The partially redundant load in bb1 should be hoisted to "bb". This comes +; from this C code (GCC PR 23455): +; unsigned outcnt; extern void flush_outbuf(void); +; void bi_windup(unsigned char *outbuf, unsigned char bi_buf) { +; outbuf[outcnt] = bi_buf; +; if (outcnt == 16384) +; flush_outbuf(); +; outbuf[outcnt] = bi_buf; +; } +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" +@outcnt = common global i32 0 ; <i32*> [#uses=3] + +define void @bi_windup(i8* %outbuf, i8 zeroext %bi_buf) nounwind { +entry: + %"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0] + %0 = load i32* @outcnt, align 4 ; <i32> [#uses=1] + %1 = getelementptr i8* %outbuf, i32 %0 ; <i8*> [#uses=1] + store i8 %bi_buf, i8* %1, align 1 + %2 = load i32* @outcnt, align 4 ; <i32> [#uses=1] + %3 = icmp eq i32 %2, 16384 ; <i1> [#uses=1] + br i1 %3, label %bb, label %bb1 + +bb: ; preds = %entry + call void @flush_outbuf() nounwind + br label %bb1 + +bb1: ; preds = %bb, %entry +; CHECK: bb1: +; CHECK-NEXT: phi +; CHECK-NEXT: getelementptr + %4 = load i32* @outcnt, align 4 ; <i32> [#uses=1] + %5 = getelementptr i8* %outbuf, i32 %4 ; <i8*> [#uses=1] + store i8 %bi_buf, i8* %5, align 1 + ret void +} + +declare void @flush_outbuf() diff --git a/test/Transforms/GVN/lpre-call-wrap.ll b/test/Transforms/GVN/lpre-call-wrap.ll new file mode 100644 index 0000000..4046279 --- /dev/null +++ b/test/Transforms/GVN/lpre-call-wrap.ll @@ -0,0 +1,55 @@ +; RUN: opt -S -gvn -enable-load-pre %s | FileCheck %s +; +; Make sure the load in bb3.backedge is removed and moved into bb1 after the +; call. This makes the non-call case faster. +; +; This test is derived from this C++ code (GCC PR 37810): +; void g(); +; struct A { +; int n; int m; +; A& operator++(void) { ++n; if (n == m) g(); return *this; } +; A() : n(0), m(0) { } +; friend bool operator!=(A const& a1, A const& a2) { return a1.n != a2.n; } +; }; +; void testfunction(A& iter) { A const end; while (iter != end) ++iter; } +; +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.A = type { i32, i32 } + +define void @_Z12testfunctionR1A(%struct.A* %iter) { +entry: + %0 = getelementptr %struct.A* %iter, i32 0, i32 0 ; <i32*> [#uses=3] + %1 = load i32* %0, align 4 ; <i32> [#uses=2] + %2 = icmp eq i32 %1, 0 ; <i1> [#uses=1] + br i1 %2, label %return, label %bb.nph + +bb.nph: ; preds = %entry + %3 = getelementptr %struct.A* %iter, i32 0, i32 1 ; <i32*> [#uses=1] + br label %bb + +bb: ; preds = %bb3.backedge, %bb.nph + %.rle = phi i32 [ %1, %bb.nph ], [ %7, %bb3.backedge ] ; <i32> [#uses=1] + %4 = add i32 %.rle, 1 ; <i32> [#uses=2] + store i32 %4, i32* %0, align 4 + %5 = load i32* %3, align 4 ; <i32> [#uses=1] + %6 = icmp eq i32 %4, %5 ; <i1> [#uses=1] + br i1 %6, label %bb1, label %bb3.backedge + +bb1: ; preds = %bb + tail call void @_Z1gv() + br label %bb3.backedge + +bb3.backedge: ; preds = %bb, %bb1 +; CHECK: bb3.backedge: +; CHECK-NEXT: phi +; CHECK-NEXT: icmp + %7 = load i32* %0, align 4 ; <i32> [#uses=2] + %8 = icmp eq i32 %7, 0 ; <i1> [#uses=1] + br i1 %8, label %return, label %bb + +return: ; preds = %bb3.backedge, %entry + ret void +} + +declare void @_Z1gv() diff --git a/test/Transforms/GVN/mixed.ll b/test/Transforms/GVN/mixed.ll new file mode 100644 index 0000000..5152f68 --- /dev/null +++ b/test/Transforms/GVN/mixed.ll @@ -0,0 +1,13 @@ +; RUN: opt < %s -gvn -S | not grep DEADLOAD +; RUN: opt < %s -gvn -S | not grep DEADGEP + +define i32 @main(i32** %p) { +block1: + %z1 = load i32** %p + %z2 = getelementptr i32* %z1, i32 0 + %z3 = load i32* %z2 + %DEADLOAD = load i32** %p + %DEADGEP = getelementptr i32* %DEADLOAD, i32 0 + %DEADLOAD2 = load i32* %DEADGEP + ret i32 %DEADLOAD2 +} diff --git a/test/Transforms/GVN/nonescaping-malloc.ll b/test/Transforms/GVN/nonescaping-malloc.ll new file mode 100644 index 0000000..5a42d95 --- /dev/null +++ b/test/Transforms/GVN/nonescaping-malloc.ll @@ -0,0 +1,108 @@ +; RUN: opt < %s -gvn -stats -disable-output |& grep {Number of loads deleted} +; rdar://7363102 + +; 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 ; <%"struct.llvm::StringRef"*> [#uses=3] + %tmp.i = getelementptr inbounds %"struct.llvm::StringRef"* %tmp, i64 0, i32 0 ; <i8**> [#uses=1] + store i8* %P, i8** %tmp.i, align 8 + %tmp1.i = call i64 @strlen(i8* %P) nounwind readonly ; <i64> [#uses=1] + %tmp2.i = getelementptr inbounds %"struct.llvm::StringRef"* %tmp, i64 0, i32 1 ; <i64*> [#uses=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 ; <%"struct.llvm::StringMapEntry<void*>"*> [#uses=1] + ret %"struct.llvm::StringMapEntry<void*>"* %tmp1 +} + +declare i64 @strlen(i8* nocapture) nounwind readonly + +declare noalias i8* @malloc(i64) nounwind + +declare void @llvm.memcpy.i64(i8* nocapture, i8* nocapture, i64, i32) 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* ; <i64*> [#uses=1] + %val = load i64* %elt ; <i64> [#uses=3] + %tmp = getelementptr inbounds %"struct.llvm::StringRef"* %Key, i64 0, i32 1 ; <i64*> [#uses=1] + %val2 = load i64* %tmp ; <i64> [#uses=2] + %tmp2.i = getelementptr inbounds %"struct.llvm::StringMap<void*,llvm::MallocAllocator>"* %this, i64 0, i32 0 ; <%"struct.llvm::StringMapImpl"*> [#uses=1] + %tmp3.i = tail call i32 @_ZN4llvm13StringMapImpl15LookupBucketForENS_9StringRefE(%"struct.llvm::StringMapImpl"* %tmp2.i, i64 %val, i64 %val2) ; <i32> [#uses=1] + %tmp4.i = getelementptr inbounds %"struct.llvm::StringMap<void*,llvm::MallocAllocator>"* %this, i64 0, i32 0, i32 0 ; <%"struct.llvm::StringMapImpl::ItemBucket"**> [#uses=1] + %tmp5.i = load %"struct.llvm::StringMapImpl::ItemBucket"** %tmp4.i, align 8 ; <%"struct.llvm::StringMapImpl::ItemBucket"*> [#uses=1] + %tmp6.i = zext i32 %tmp3.i to i64 ; <i64> [#uses=1] + %tmp7.i = getelementptr inbounds %"struct.llvm::StringMapImpl::ItemBucket"* %tmp5.i, i64 %tmp6.i, i32 1 ; <%"struct.llvm::StringMapEntryBase"**> [#uses=2] + %tmp8.i = load %"struct.llvm::StringMapEntryBase"** %tmp7.i, align 8 ; <%"struct.llvm::StringMapEntryBase"*> [#uses=3] + %tmp9.i = icmp eq %"struct.llvm::StringMapEntryBase"* %tmp8.i, null ; <i1> [#uses=1] + %tmp13.i = icmp eq %"struct.llvm::StringMapEntryBase"* %tmp8.i, inttoptr (i64 -1 to %"struct.llvm::StringMapEntryBase"*) ; <i1> [#uses=1] + %or.cond.i = or i1 %tmp9.i, %tmp13.i ; <i1> [#uses=1] + br i1 %or.cond.i, label %bb4.i, label %bb6.i + +bb4.i: ; preds = %entry + %tmp41.i = inttoptr i64 %val to i8* ; <i8*> [#uses=2] + %tmp4.i35.i = getelementptr inbounds i8* %tmp41.i, i64 %val2 ; <i8*> [#uses=1] + %tmp.i.i = ptrtoint i8* %tmp4.i35.i to i64 ; <i64> [#uses=1] + %tmp1.i.i = trunc i64 %tmp.i.i to i32 ; <i32> [#uses=1] + %tmp3.i.i = trunc i64 %val to i32 ; <i32> [#uses=1] + %tmp4.i.i = sub i32 %tmp1.i.i, %tmp3.i.i ; <i32> [#uses=3] + %tmp5.i.i = add i32 %tmp4.i.i, 17 ; <i32> [#uses=1] + %tmp8.i.i = zext i32 %tmp5.i.i to i64 ; <i64> [#uses=1] + %tmp.i20.i.i = tail call noalias i8* @malloc(i64 %tmp8.i.i) nounwind ; <i8*> [#uses=7] + %tmp10.i.i = bitcast i8* %tmp.i20.i.i to %"struct.llvm::StringMapEntry<void*>"* ; <%"struct.llvm::StringMapEntry<void*>"*> [#uses=2] + %tmp12.i.i = icmp eq i8* %tmp.i20.i.i, null ; <i1> [#uses=1] + 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* ; <i32*> [#uses=1] + store i32 %tmp4.i.i, i32* %tmp.i.i.i.i, align 4 + %tmp1.i19.i.i = getelementptr inbounds i8* %tmp.i20.i.i, i64 8 ; <i8*> [#uses=1] + %0 = bitcast i8* %tmp1.i19.i.i to i8** ; <i8**> [#uses=1] + 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 = %bb4.i, %bb.i.i + %tmp.i18.i.i = getelementptr inbounds i8* %tmp.i20.i.i, i64 16 ; <i8*> [#uses=1] + %tmp15.i.i = zext i32 %tmp4.i.i to i64 ; <i64> [#uses=2] + tail call void @llvm.memcpy.i64(i8* %tmp.i18.i.i, i8* %tmp41.i, i64 %tmp15.i.i, i32 1) nounwind + %tmp.i18.sum.i.i = add i64 %tmp15.i.i, 16 ; <i64> [#uses=1] + %tmp17.i.i = getelementptr inbounds i8* %tmp.i20.i.i, i64 %tmp.i18.sum.i.i ; <i8*> [#uses=1] + store i8 0, i8* %tmp17.i.i, align 1 + %tmp.i.i.i = getelementptr inbounds i8* %tmp.i20.i.i, i64 8 ; <i8*> [#uses=1] + %1 = bitcast i8* %tmp.i.i.i to i8** ; <i8**> [#uses=1] + store i8* null, i8** %1, align 8 + %tmp22.i = load %"struct.llvm::StringMapEntryBase"** %tmp7.i, align 8 ; <%"struct.llvm::StringMapEntryBase"*> [#uses=1] + %tmp24.i = icmp eq %"struct.llvm::StringMapEntryBase"* %tmp22.i, inttoptr (i64 -1 to %"struct.llvm::StringMapEntryBase"*) ; <i1> [#uses=1] + 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*>"* ; <%"struct.llvm::StringMapEntry<void*>"*> [#uses=1] + 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>"* %this, i64 0, i32 0, i32 3 ; <i32*> [#uses=2] + %tmp26.i = load i32* %tmp25.i, align 8 ; <i32> [#uses=1] + %tmp27.i = add i32 %tmp26.i, -1 ; <i32> [#uses=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 +} diff --git a/test/Transforms/GVN/null-aliases-nothing.ll b/test/Transforms/GVN/null-aliases-nothing.ll new file mode 100644 index 0000000..4d533bb --- /dev/null +++ b/test/Transforms/GVN/null-aliases-nothing.ll @@ -0,0 +1,20 @@ +; RUN: opt %s -gvn -S | FileCheck %s + +%t = type { i32 } +declare void @test1f(i8*) + +define void @test1(%t* noalias %stuff ) { + %p = getelementptr inbounds %t* %stuff, i32 0, i32 0 + %before = load i32* %p + + call void @test1f(i8* null) + + %after = load 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/test/Transforms/GVN/pre-basic-add.ll b/test/Transforms/GVN/pre-basic-add.ll new file mode 100644 index 0000000..c13099f --- /dev/null +++ b/test/Transforms/GVN/pre-basic-add.ll @@ -0,0 +1,27 @@ +; RUN: opt < %s -gvn -enable-pre -S | grep {.pre} + +@H = common global i32 0 ; <i32*> [#uses=2] +@G = common global i32 0 ; <i32*> [#uses=1] + +define i32 @test() nounwind { +entry: + %0 = load i32* @H, align 4 ; <i32> [#uses=2] + %1 = call i32 (...)* @foo() nounwind ; <i32> [#uses=1] + %2 = icmp ne i32 %1, 0 ; <i1> [#uses=1] + br i1 %2, label %bb, label %bb1 + +bb: ; preds = %entry + %3 = add i32 %0, 42 ; <i32> [#uses=1] + store i32 %3, i32* @G, align 4 + br label %bb1 + +bb1: ; preds = %bb, %entry + %4 = add i32 %0, 42 ; <i32> [#uses=1] + store i32 %4, i32* @H, align 4 + br label %return + +return: ; preds = %bb1 + ret i32 0 +} + +declare i32 @foo(...) diff --git a/test/Transforms/GVN/pre-load.ll b/test/Transforms/GVN/pre-load.ll new file mode 100644 index 0000000..7047d4e --- /dev/null +++ b/test/Transforms/GVN/pre-load.ll @@ -0,0 +1,364 @@ +; RUN: opt < %s -gvn -enable-load-pre -S | FileCheck %s +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" + +define i32 @test1(i32* %p, i1 %C) { +; CHECK: @test1 +block1: + br i1 %C, label %block2, label %block3 + +block2: + br label %block4 +; CHECK: block2: +; CHECK-NEXT: load i32* %p + +block3: + store i32 0, i32* %p + br label %block4 + +block4: + %PRE = load i32* %p + ret i32 %PRE +; CHECK: block4: +; CHECK-NEXT: phi i32 +; CHECK-NEXT: ret i32 +} + +; This is a simple phi translation case. +define i32 @test2(i32* %p, i32* %q, i1 %C) { +; CHECK: @test2 +block1: + br i1 %C, label %block2, label %block3 + +block2: + br label %block4 +; CHECK: block2: +; CHECK-NEXT: load i32* %q + +block3: + store i32 0, i32* %p + br label %block4 + +block4: + %P2 = phi i32* [%p, %block3], [%q, %block2] + %PRE = load i32* %P2 + ret i32 %PRE +; CHECK: block4: +; CHECK-NEXT: phi i32 [ +; CHECK-NOT: load +; CHECK: ret i32 +} + +; This is a PRE case that requires phi translation through a GEP. +define i32 @test3(i32* %p, i32* %q, i32** %Hack, i1 %C) { +; CHECK: @test3 +block1: + %B = getelementptr i32* %q, i32 1 + store i32* %B, i32** %Hack + br i1 %C, label %block2, label %block3 + +block2: + br label %block4 +; CHECK: block2: +; CHECK-NEXT: load i32* %B + +block3: + %A = getelementptr i32* %p, i32 1 + store i32 0, i32* %A + br label %block4 + +block4: + %P2 = phi i32* [%p, %block3], [%q, %block2] + %P3 = getelementptr i32* %P2, i32 1 + %PRE = load i32* %P3 + ret i32 %PRE +; CHECK: block4: +; CHECK-NEXT: phi i32 [ +; CHECK-NOT: load +; CHECK: ret i32 +} + +;; Here the loaded address is available, but the computation is in 'block3' +;; which does not dominate 'block2'. +define i32 @test4(i32* %p, i32* %q, i32** %Hack, i1 %C) { +; CHECK: @test4 +block1: + br i1 %C, label %block2, label %block3 + +block2: + br label %block4 +; CHECK: block2: +; CHECK: load i32* +; CHECK: br label %block4 + +block3: + %B = getelementptr i32* %q, i32 1 + store i32* %B, i32** %Hack + + %A = getelementptr i32* %p, i32 1 + store i32 0, i32* %A + br label %block4 + +block4: + %P2 = phi i32* [%p, %block3], [%q, %block2] + %P3 = getelementptr i32* %P2, i32 1 + %PRE = load i32* %P3 + ret i32 %PRE +; CHECK: block4: +; CHECK-NEXT: phi i32 [ +; CHECK-NOT: load +; CHECK: ret i32 +} + +;void test5(int N, double *G) { +; int j; +; for (j = 0; j < N - 1; j++) +; G[j] = G[j] + G[j+1]; +;} + +define void @test5(i32 %N, double* nocapture %G) nounwind ssp { +; CHECK: @test5 +entry: + %0 = add i32 %N, -1 + %1 = icmp sgt i32 %0, 0 + br i1 %1, label %bb.nph, label %return + +bb.nph: + %tmp = zext i32 %0 to i64 + br label %bb + +; CHECK: bb.nph: +; CHECK: load double* +; CHECK: br label %bb + +bb: + %indvar = phi i64 [ 0, %bb.nph ], [ %tmp6, %bb ] + %tmp6 = add i64 %indvar, 1 + %scevgep = getelementptr double* %G, i64 %tmp6 + %scevgep7 = getelementptr double* %G, i64 %indvar + %2 = load double* %scevgep7, align 8 + %3 = load double* %scevgep, align 8 + %4 = fadd double %2, %3 + store double %4, double* %scevgep7, align 8 + %exitcond = icmp eq i64 %tmp6, %tmp + br i1 %exitcond, label %return, label %bb + +; Should only be one load in the loop. +; CHECK: bb: +; CHECK: load double* +; CHECK-NOT: load double* +; CHECK: br i1 %exitcond + +return: + ret void +} + +;void test6(int N, double *G) { +; int j; +; for (j = 0; j < N - 1; j++) +; G[j+1] = G[j] + G[j+1]; +;} + +define void @test6(i32 %N, double* nocapture %G) nounwind ssp { +; CHECK: @test6 +entry: + %0 = add i32 %N, -1 + %1 = icmp sgt i32 %0, 0 + br i1 %1, label %bb.nph, label %return + +bb.nph: + %tmp = zext i32 %0 to i64 + br label %bb + +; CHECK: bb.nph: +; CHECK: load double* +; CHECK: br label %bb + +bb: + %indvar = phi i64 [ 0, %bb.nph ], [ %tmp6, %bb ] + %tmp6 = add i64 %indvar, 1 + %scevgep = getelementptr double* %G, i64 %tmp6 + %scevgep7 = getelementptr double* %G, i64 %indvar + %2 = load double* %scevgep7, align 8 + %3 = load double* %scevgep, align 8 + %4 = fadd double %2, %3 + store double %4, double* %scevgep, align 8 + %exitcond = icmp eq i64 %tmp6, %tmp + br i1 %exitcond, label %return, label %bb + +; Should only be one load in the loop. +; CHECK: bb: +; CHECK: load double* +; CHECK-NOT: load double* +; CHECK: br i1 %exitcond + +return: + ret void +} + +;void test7(int N, double* G) { +; long j; +; G[1] = 1; +; for (j = 1; j < N - 1; j++) +; G[j+1] = G[j] + G[j+1]; +;} + +; This requires phi translation of the adds. +define void @test7(i32 %N, double* nocapture %G) nounwind ssp { +entry: + %0 = getelementptr inbounds double* %G, i64 1 + store double 1.000000e+00, double* %0, align 8 + %1 = add i32 %N, -1 + %2 = icmp sgt i32 %1, 1 + br i1 %2, label %bb.nph, label %return + +bb.nph: + %tmp = sext i32 %1 to i64 + %tmp7 = add i64 %tmp, -1 + br label %bb + +bb: + %indvar = phi i64 [ 0, %bb.nph ], [ %tmp9, %bb ] + %tmp8 = add i64 %indvar, 2 + %scevgep = getelementptr double* %G, i64 %tmp8 + %tmp9 = add i64 %indvar, 1 + %scevgep10 = getelementptr double* %G, i64 %tmp9 + %3 = load double* %scevgep10, align 8 + %4 = load double* %scevgep, align 8 + %5 = fadd double %3, %4 + store double %5, double* %scevgep, align 8 + %exitcond = icmp eq i64 %tmp9, %tmp7 + br i1 %exitcond, label %return, label %bb + +; Should only be one load in the loop. +; CHECK: bb: +; CHECK: load double* +; CHECK-NOT: load double* +; CHECK: br i1 %exitcond + +return: + ret void +} + +;; Here the loaded address isn't available in 'block2' at all, requiring a new +;; GEP to be inserted into it. +define i32 @test8(i32* %p, i32* %q, i32** %Hack, i1 %C) { +; CHECK: @test8 +block1: + br i1 %C, label %block2, label %block3 + +block2: + br label %block4 +; CHECK: block2: +; CHECK: load i32* +; CHECK: br label %block4 + +block3: + %A = getelementptr i32* %p, i32 1 + store i32 0, i32* %A + br label %block4 + +block4: + %P2 = phi i32* [%p, %block3], [%q, %block2] + %P3 = getelementptr i32* %P2, i32 1 + %PRE = load i32* %P3 + ret i32 %PRE +; CHECK: block4: +; CHECK-NEXT: phi i32 [ +; CHECK-NOT: load +; CHECK: ret i32 +} + +;void test9(int N, double* G) { +; long j; +; for (j = 1; j < N - 1; j++) +; G[j+1] = G[j] + G[j+1]; +;} + +; This requires phi translation of the adds. +define void @test9(i32 %N, double* nocapture %G) nounwind ssp { +entry: + add i32 0, 0 + %1 = add i32 %N, -1 + %2 = icmp sgt i32 %1, 1 + br i1 %2, label %bb.nph, label %return + +bb.nph: + %tmp = sext i32 %1 to i64 + %tmp7 = add i64 %tmp, -1 + br label %bb + +; CHECK: bb.nph: +; CHECK: load double* +; CHECK: br label %bb + +bb: + %indvar = phi i64 [ 0, %bb.nph ], [ %tmp9, %bb ] + %tmp8 = add i64 %indvar, 2 + %scevgep = getelementptr double* %G, i64 %tmp8 + %tmp9 = add i64 %indvar, 1 + %scevgep10 = getelementptr double* %G, i64 %tmp9 + %3 = load double* %scevgep10, align 8 + %4 = load double* %scevgep, align 8 + %5 = fadd double %3, %4 + store double %5, double* %scevgep, align 8 + %exitcond = icmp eq i64 %tmp9, %tmp7 + br i1 %exitcond, label %return, label %bb + +; Should only be one load in the loop. +; CHECK: bb: +; CHECK: load double* +; CHECK-NOT: load double* +; CHECK: br i1 %exitcond + +return: + ret void +} + +;void test10(int N, double* G) { +; long j; +; for (j = 1; j < N - 1; j++) +; G[j] = G[j] + G[j+1] + G[j-1]; +;} + +; PR5501 +define void @test10(i32 %N, double* nocapture %G) nounwind ssp { +entry: + %0 = add i32 %N, -1 + %1 = icmp sgt i32 %0, 1 + br i1 %1, label %bb.nph, label %return + +bb.nph: + %tmp = sext i32 %0 to i64 + %tmp8 = add i64 %tmp, -1 + br label %bb +; CHECK: bb.nph: +; CHECK: load double* +; CHECK: load double* +; CHECK: br label %bb + + +bb: + %indvar = phi i64 [ 0, %bb.nph ], [ %tmp11, %bb ] + %scevgep = getelementptr double* %G, i64 %indvar + %tmp9 = add i64 %indvar, 2 + %scevgep10 = getelementptr double* %G, i64 %tmp9 + %tmp11 = add i64 %indvar, 1 + %scevgep12 = getelementptr double* %G, i64 %tmp11 + %2 = load double* %scevgep12, align 8 + %3 = load double* %scevgep10, align 8 + %4 = fadd double %2, %3 + %5 = load double* %scevgep, align 8 + %6 = fadd double %4, %5 + store double %6, double* %scevgep12, align 8 + %exitcond = icmp eq i64 %tmp11, %tmp8 + br i1 %exitcond, label %return, label %bb + +; Should only be one load in the loop. +; CHECK: bb: +; CHECK: load double* +; CHECK-NOT: load double* +; CHECK: br i1 %exitcond + +return: + ret void +} diff --git a/test/Transforms/GVN/pre-single-pred.ll b/test/Transforms/GVN/pre-single-pred.ll new file mode 100644 index 0000000..706a16b --- /dev/null +++ b/test/Transforms/GVN/pre-single-pred.ll @@ -0,0 +1,33 @@ +; RUN: opt < %s -gvn -enable-load-pre -S | not grep {tmp3 = load} + +@p = external global i32 +define i32 @f(i32 %n) nounwind { +entry: + br label %for.cond + +for.cond: ; preds = %for.inc, %entry + %i.0 = phi i32 [ 0, %entry ], [ %indvar.next, %for.inc ] ; <i32> [#uses=2] + %cmp = icmp slt i32 %i.0, %n ; <i1> [#uses=1] + br i1 %cmp, label %for.body, label %for.cond.for.end_crit_edge + +for.cond.for.end_crit_edge: ; preds = %for.cond + br label %for.end + +for.body: ; preds = %for.cond + %tmp3 = load i32* @p ; <i32> [#uses=1] + %dec = add i32 %tmp3, -1 ; <i32> [#uses=2] + store i32 %dec, i32* @p + %cmp6 = icmp slt i32 %dec, 0 ; <i1> [#uses=1] + br i1 %cmp6, label %for.body.for.end_crit_edge, label %for.inc + +for.body.for.end_crit_edge: ; preds = %for.body + br label %for.end + +for.inc: ; preds = %for.body + %indvar.next = add i32 %i.0, 1 ; <i32> [#uses=1] + br label %for.cond + +for.end: ; preds = %for.body.for.end_crit_edge, %for.cond.for.end_crit_edge + %tmp9 = load i32* @p ; <i32> [#uses=1] + ret i32 %tmp9 +} diff --git a/test/Transforms/GVN/rle-must-alias.ll b/test/Transforms/GVN/rle-must-alias.ll new file mode 100644 index 0000000..d61eb81 --- /dev/null +++ b/test/Transforms/GVN/rle-must-alias.ll @@ -0,0 +1,46 @@ +; RUN: opt < %s -gvn -S | grep {DEAD = phi i32 } + +; 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]* @H, i32 0, i32 %i ; <i32*> [#uses=1] + %4 = load 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]* @H, i32 0, i32 %i ; <i32*> [#uses=1] + %7 = load 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]* @H, i32 0, i32 %i ; <i32*> [#uses=1] + %DEAD = load i32* %9, align 4 ; <i32> [#uses=1] + ret i32 %DEAD + +bb4: ; preds = %bb1 + ret i32 0 +} + +declare i32 @foo(...) + +declare i32 @bar(...) + +declare i32 @baz(...) diff --git a/test/Transforms/GVN/rle-no-phi-translate.ll b/test/Transforms/GVN/rle-no-phi-translate.ll new file mode 100644 index 0000000..96dbf48 --- /dev/null +++ b/test/Transforms/GVN/rle-no-phi-translate.ll @@ -0,0 +1,28 @@ +; RUN: opt < %s -gvn -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* %c_addr.0, align 4 ; <i32> [#uses=1] + ret i32 %cv +; CHECK: bb2: +; CHECK-NOT: load i32 +; CHECK: ret i32 +} + diff --git a/test/Transforms/GVN/rle-nonlocal.ll b/test/Transforms/GVN/rle-nonlocal.ll new file mode 100644 index 0000000..5c73dad --- /dev/null +++ b/test/Transforms/GVN/rle-nonlocal.ll @@ -0,0 +1,24 @@ +; RUN: opt < %s -gvn -S | FileCheck %s + +define i32 @main(i32** %p) { +block1: + br i1 true, label %block2, label %block3 + +block2: + %a = load i32** %p + br label %block4 + +block3: + %b = load i32** %p + br label %block4 + +block4: +; CHECK-NOT: %existingPHI = phi +; CHECK: %DEAD = phi + %existingPHI = phi i32* [ %a, %block2 ], [ %b, %block3 ] + %DEAD = load i32** %p + %c = load i32* %DEAD + %d = load i32* %existingPHI + %e = add i32 %c, %d + ret i32 %e +} diff --git a/test/Transforms/GVN/rle-phi-translate.ll b/test/Transforms/GVN/rle-phi-translate.ll new file mode 100644 index 0000000..6731f43 --- /dev/null +++ b/test/Transforms/GVN/rle-phi-translate.ll @@ -0,0 +1,146 @@ +; RUN: opt < %s -gvn -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 i32 @test1(i32* %b, i32* %c) nounwind { +; CHECK: @test1 +entry: + %g = alloca i32 + %t1 = icmp eq i32* %b, null + br i1 %t1, label %bb, label %bb1 + +bb: + %t2 = load i32* %c, align 4 + %t3 = add i32 %t2, 1 + store i32 %t3, i32* %g, align 4 + br label %bb2 + +bb1: ; preds = %entry + %t5 = load i32* %b, align 4 + %t6 = add i32 %t5, 1 + store i32 %t6, i32* %g, align 4 + br label %bb2 + +bb2: ; preds = %bb1, %bb + %c_addr.0 = phi i32* [ %g, %bb1 ], [ %c, %bb ] + %b_addr.0 = phi i32* [ %b, %bb1 ], [ %g, %bb ] + %cv = load i32* %c_addr.0, align 4 + %bv = load i32* %b_addr.0, align 4 +; CHECK: %bv = phi i32 +; CHECK: %cv = phi i32 +; CHECK-NOT: load +; CHECK: ret i32 + %ret = add i32 %cv, %bv + ret i32 %ret +} + +define i8 @test2(i1 %cond, i32* %b, i32* %c) nounwind { +; CHECK: @test2 +entry: + br i1 %cond, label %bb, label %bb1 + +bb: + %b1 = bitcast i32* %b to i8* + store i8 4, i8* %b1 + br label %bb2 + +bb1: + %c1 = bitcast i32* %c to i8* + store i8 92, i8* %c1 + br label %bb2 + +bb2: + %d = phi i32* [ %c, %bb1 ], [ %b, %bb ] + %d1 = bitcast i32* %d to i8* + %dv = load i8* %d1 +; CHECK: %dv = phi i8 [ 92, %bb1 ], [ 4, %bb ] +; CHECK-NOT: load +; CHECK: ret i8 %dv + ret i8 %dv +} + +define i32 @test3(i1 %cond, i32* %b, i32* %c) nounwind { +; CHECK: @test3 +entry: + br i1 %cond, label %bb, label %bb1 + +bb: + %b1 = getelementptr i32* %b, i32 17 + store i32 4, i32* %b1 + br label %bb2 + +bb1: + %c1 = getelementptr i32* %c, i32 7 + store i32 82, i32* %c1 + br label %bb2 + +bb2: + %d = phi i32* [ %c, %bb1 ], [ %b, %bb ] + %i = phi i32 [ 7, %bb1 ], [ 17, %bb ] + %d1 = getelementptr i32* %d, i32 %i + %dv = load i32* %d1 +; CHECK: %dv = phi i32 [ 82, %bb1 ], [ 4, %bb ] +; CHECK-NOT: load +; CHECK: ret i32 %dv + ret i32 %dv +} + +; PR5313 +define i32 @test4(i1 %cond, i32* %b, i32* %c) nounwind { +; CHECK: @test4 +entry: + br i1 %cond, label %bb, label %bb1 + +bb: + store i32 4, i32* %b + br label %bb2 + +bb1: + %c1 = getelementptr i32* %c, i32 7 + store i32 82, i32* %c1 + br label %bb2 + +bb2: + %d = phi i32* [ %c, %bb1 ], [ %b, %bb ] + %i = phi i32 [ 7, %bb1 ], [ 0, %bb ] + %d1 = getelementptr i32* %d, i32 %i + %dv = load i32* %d1 +; CHECK: %dv = phi i32 [ 82, %bb1 ], [ 4, %bb ] +; CHECK-NOT: load +; CHECK: ret i32 %dv + ret i32 %dv +} + + + +; void test5(int N, double* G) { +; for (long j = 1; j < 1000; j++) +; G[j] = G[j] + G[j-1]; +; } +; +; Should compile into one load in the loop. +define void @test5(i32 %N, double* nocapture %G) nounwind ssp { +; CHECK: @test5 +bb.nph: + br label %for.body + +for.body: + %indvar = phi i64 [ 0, %bb.nph ], [ %tmp, %for.body ] + %arrayidx6 = getelementptr double* %G, i64 %indvar + %tmp = add i64 %indvar, 1 + %arrayidx = getelementptr double* %G, i64 %tmp + %tmp3 = load double* %arrayidx + %tmp7 = load double* %arrayidx6 + %add = fadd double %tmp3, %tmp7 + store double %add, double* %arrayidx + %exitcond = icmp eq i64 %tmp, 999 + br i1 %exitcond, label %for.end, label %for.body +; CHECK: for.body: +; CHECK: phi double +; CHECK: load double +; CHECK-NOT: load double +; CHECK: br i1 +for.end: + ret void +} diff --git a/test/Transforms/GVN/rle-semidominated.ll b/test/Transforms/GVN/rle-semidominated.ll new file mode 100644 index 0000000..04e8c38 --- /dev/null +++ b/test/Transforms/GVN/rle-semidominated.ll @@ -0,0 +1,19 @@ +; RUN: opt < %s -gvn -S | grep {DEAD = phi i32 } + +define i32 @main(i32* %p) { +block1: + %z = load i32* %p + br i1 true, label %block2, label %block3 + +block2: + br label %block4 + +block3: + %b = bitcast i32 0 to i32 + store i32 %b, i32* %p + br label %block4 + +block4: + %DEAD = load i32* %p + ret i32 %DEAD +} diff --git a/test/Transforms/GVN/rle.ll b/test/Transforms/GVN/rle.ll new file mode 100644 index 0000000..d419fd2 --- /dev/null +++ b/test/Transforms/GVN/rle.ll @@ -0,0 +1,534 @@ +; RUN: opt < %s -gvn -S | FileCheck %s + +; 32-bit little endian target. +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" + +;; Trivial RLE test. +define i32 @test0(i32 %V, i32* %P) { + store i32 %V, i32* %P + + %A = load i32* %P + ret i32 %A +; CHECK: @test0 +; CHECK: ret i32 %V +} + + +;;===----------------------------------------------------------------------===;; +;; Tests for crashers +;;===----------------------------------------------------------------------===;; + +;; PR5016 +define i8 @crash0({i32, i32} %A, {i32, i32}* %P) { + store {i32, i32} %A, {i32, i32}* %P + %X = bitcast {i32, i32}* %P to i8* + %Y = load i8* %X + ret i8 %Y +} + + +;;===----------------------------------------------------------------------===;; +;; Store -> Load and Load -> Load forwarding where src and dst are different +;; types, but where the base pointer is a must alias. +;;===----------------------------------------------------------------------===;; + +;; i32 -> f32 forwarding. +define float @coerce_mustalias1(i32 %V, i32* %P) { + store i32 %V, i32* %P + + %P2 = bitcast i32* %P to float* + + %A = load float* %P2 + ret float %A +; CHECK: @coerce_mustalias1 +; CHECK-NOT: load +; CHECK: ret float +} + +;; i32* -> float forwarding. +define float @coerce_mustalias2(i32* %V, i32** %P) { + store i32* %V, i32** %P + + %P2 = bitcast i32** %P to float* + + %A = load float* %P2 + ret float %A +; CHECK: @coerce_mustalias2 +; CHECK-NOT: load +; CHECK: ret float +} + +;; float -> i32* forwarding. +define i32* @coerce_mustalias3(float %V, float* %P) { + store float %V, float* %P + + %P2 = bitcast float* %P to i32** + + %A = load i32** %P2 + ret i32* %A +; CHECK: @coerce_mustalias3 +; CHECK-NOT: load +; CHECK: ret i32* +} + +;; i32 -> f32 load forwarding. +define float @coerce_mustalias4(i32* %P, i1 %cond) { + %A = load i32* %P + + %P2 = bitcast i32* %P to float* + %B = load float* %P2 + br i1 %cond, label %T, label %F +T: + ret float %B + +F: + %X = bitcast i32 %A to float + ret float %X + +; CHECK: @coerce_mustalias4 +; CHECK: %A = load i32* %P +; CHECK-NOT: load +; CHECK: ret float +; CHECK: F: +} + +;; i32 -> i8 forwarding +define i8 @coerce_mustalias5(i32 %V, i32* %P) { + store i32 %V, i32* %P + + %P2 = bitcast i32* %P to i8* + + %A = load i8* %P2 + ret i8 %A +; CHECK: @coerce_mustalias5 +; CHECK-NOT: load +; CHECK: ret i8 +} + +;; i64 -> float forwarding +define float @coerce_mustalias6(i64 %V, i64* %P) { + store i64 %V, i64* %P + + %P2 = bitcast i64* %P to float* + + %A = load float* %P2 + ret float %A +; CHECK: @coerce_mustalias6 +; CHECK-NOT: load +; CHECK: ret float +} + +;; i64 -> i8* (32-bit) forwarding +define i8* @coerce_mustalias7(i64 %V, i64* %P) { + store i64 %V, i64* %P + + %P2 = bitcast i64* %P to i8** + + %A = load i8** %P2 + ret i8* %A +; CHECK: @coerce_mustalias7 +; CHECK-NOT: load +; CHECK: ret i8* +} + +; memset -> i16 forwarding. +define signext i16 @memset_to_i16_local(i16* %A) nounwind ssp { +entry: + %conv = bitcast i16* %A to i8* + tail call void @llvm.memset.i64(i8* %conv, i8 1, i64 200, i32 1) + %arrayidx = getelementptr inbounds i16* %A, i64 42 + %tmp2 = load i16* %arrayidx + ret i16 %tmp2 +; CHECK: @memset_to_i16_local +; CHECK-NOT: load +; CHECK: ret i16 257 +} + +; memset -> float forwarding. +define float @memset_to_float_local(float* %A, i8 %Val) nounwind ssp { +entry: + %conv = bitcast float* %A to i8* ; <i8*> [#uses=1] + tail call void @llvm.memset.i64(i8* %conv, i8 %Val, i64 400, i32 1) + %arrayidx = getelementptr inbounds float* %A, i64 42 ; <float*> [#uses=1] + %tmp2 = load float* %arrayidx ; <float> [#uses=1] + ret float %tmp2 +; CHECK: @memset_to_float_local +; CHECK-NOT: load +; CHECK: zext +; CHECK-NEXT: shl +; CHECK-NEXT: or +; CHECK-NEXT: shl +; CHECK-NEXT: or +; CHECK-NEXT: bitcast +; CHECK-NEXT: ret float +} + +;; non-local memset -> i16 load forwarding. +define i16 @memset_to_i16_nonlocal0(i16* %P, i1 %cond) { + %P3 = bitcast i16* %P to i8* + br i1 %cond, label %T, label %F +T: + tail call void @llvm.memset.i64(i8* %P3, i8 1, i64 400, i32 1) + br label %Cont + +F: + tail call void @llvm.memset.i64(i8* %P3, i8 2, i64 400, i32 1) + br label %Cont + +Cont: + %P2 = getelementptr i16* %P, i32 4 + %A = load i16* %P2 + ret i16 %A + +; CHECK: @memset_to_i16_nonlocal0 +; CHECK: Cont: +; CHECK-NEXT: %A = phi i16 [ 514, %F ], [ 257, %T ] +; CHECK-NOT: load +; CHECK: ret i16 %A +} + +@GCst = constant {i32, float, i32 } { i32 42, float 14., i32 97 } + +; memset -> float forwarding. +define float @memcpy_to_float_local(float* %A) nounwind ssp { +entry: + %conv = bitcast float* %A to i8* ; <i8*> [#uses=1] + tail call void @llvm.memcpy.i64(i8* %conv, i8* bitcast ({i32, float, i32 }* @GCst to i8*), i64 12, i32 1) + %arrayidx = getelementptr inbounds float* %A, i64 1 ; <float*> [#uses=1] + %tmp2 = load float* %arrayidx ; <float> [#uses=1] + ret float %tmp2 +; CHECK: @memcpy_to_float_local +; CHECK-NOT: load +; CHECK: ret float 1.400000e+01 +} + + +declare void @llvm.memset.i64(i8* nocapture, i8, i64, i32) nounwind +declare void @llvm.memcpy.i64(i8* nocapture, i8* nocapture, i64, i32) nounwind + + + + +;; non-local i32/float -> i8 load forwarding. +define i8 @coerce_mustalias_nonlocal0(i32* %P, i1 %cond) { + %P2 = bitcast i32* %P to float* + %P3 = bitcast i32* %P to i8* + br i1 %cond, label %T, label %F +T: + store i32 42, i32* %P + br label %Cont + +F: + store float 1.0, float* %P2 + br label %Cont + +Cont: + %A = load i8* %P3 + ret i8 %A + +; CHECK: @coerce_mustalias_nonlocal0 +; CHECK: Cont: +; CHECK: %A = phi i8 [ +; CHECK-NOT: load +; CHECK: ret i8 %A +} + + +;; non-local i32/float -> i8 load forwarding. This also tests that the "P3" +;; bitcast equivalence can be properly phi translated. +define i8 @coerce_mustalias_nonlocal1(i32* %P, i1 %cond) { + %P2 = bitcast i32* %P to float* + br i1 %cond, label %T, label %F +T: + store i32 42, i32* %P + br label %Cont + +F: + store float 1.0, float* %P2 + br label %Cont + +Cont: + %P3 = bitcast i32* %P to i8* + %A = load i8* %P3 + ret i8 %A + +;; FIXME: This is disabled because this caused a miscompile in the llvm-gcc +;; bootstrap, see r82411 +; +; HECK: @coerce_mustalias_nonlocal1 +; HECK: Cont: +; HECK: %A = phi i8 [ +; HECK-NOT: load +; HECK: ret i8 %A +} + + +;; non-local i32 -> i8 partial redundancy load forwarding. +define i8 @coerce_mustalias_pre0(i32* %P, i1 %cond) { + %P3 = bitcast i32* %P to i8* + br i1 %cond, label %T, label %F +T: + store i32 42, i32* %P + br label %Cont + +F: + br label %Cont + +Cont: + %A = load i8* %P3 + ret i8 %A + +; CHECK: @coerce_mustalias_pre0 +; CHECK: F: +; CHECK: load i8* %P3 +; CHECK: Cont: +; CHECK: %A = phi i8 [ +; CHECK-NOT: load +; CHECK: ret i8 %A +} + +;;===----------------------------------------------------------------------===;; +;; Store -> Load and Load -> Load forwarding where src and dst are different +;; types, and the reload is an offset from the store pointer. +;;===----------------------------------------------------------------------===;; + +;; i32 -> i8 forwarding. +;; PR4216 +define i8 @coerce_offset0(i32 %V, i32* %P) { + store i32 %V, i32* %P + + %P2 = bitcast i32* %P to i8* + %P3 = getelementptr i8* %P2, i32 2 + + %A = load i8* %P3 + ret i8 %A +; CHECK: @coerce_offset0 +; CHECK-NOT: load +; CHECK: ret i8 +} + +;; non-local i32/float -> i8 load forwarding. +define i8 @coerce_offset_nonlocal0(i32* %P, i1 %cond) { + %P2 = bitcast i32* %P to float* + %P3 = bitcast i32* %P to i8* + %P4 = getelementptr i8* %P3, i32 2 + br i1 %cond, label %T, label %F +T: + store i32 42, i32* %P + br label %Cont + +F: + store float 1.0, float* %P2 + br label %Cont + +Cont: + %A = load i8* %P4 + ret i8 %A + +; CHECK: @coerce_offset_nonlocal0 +; CHECK: Cont: +; CHECK: %A = phi i8 [ +; CHECK-NOT: load +; CHECK: ret i8 %A +} + + +;; non-local i32 -> i8 partial redundancy load forwarding. +define i8 @coerce_offset_pre0(i32* %P, i1 %cond) { + %P3 = bitcast i32* %P to i8* + %P4 = getelementptr i8* %P3, i32 2 + br i1 %cond, label %T, label %F +T: + store i32 42, i32* %P + br label %Cont + +F: + br label %Cont + +Cont: + %A = load i8* %P4 + ret i8 %A + +; CHECK: @coerce_offset_pre0 +; CHECK: F: +; CHECK: load i8* %P4 +; CHECK: Cont: +; CHECK: %A = phi i8 [ +; CHECK-NOT: load +; CHECK: ret i8 %A +} + +define i32 @chained_load(i32** %p) { +block1: + %z = load i32** %p + br i1 true, label %block2, label %block3 + +block2: + %a = load i32** %p + br label %block4 + +block3: + %b = load i32** %p + br label %block4 + +block4: + %c = load i32** %p + %d = load i32* %c + ret i32 %d + +; CHECK: @chained_load +; CHECK: %z = load i32** %p +; CHECK-NOT: load +; CHECK: %d = load i32* %z +; CHECK-NEXT: ret i32 %d +} + + +declare i1 @cond() readonly +declare i1 @cond2() readonly + +define i32 @phi_trans2() { +; CHECK: @phi_trans2 +entry: + %P = alloca i32, i32 400 + br label %F1 + +F1: + %A = phi i32 [1, %entry], [2, %F] + %cond2 = call i1 @cond() + br i1 %cond2, label %T1, label %TY + +T1: + %P2 = getelementptr i32* %P, i32 %A + %x = load i32* %P2 + %cond = call i1 @cond2() + br i1 %cond, label %TX, label %F + +F: + %P3 = getelementptr i32* %P, i32 2 + store i32 17, i32* %P3 + + store i32 42, i32* %P2 ; Provides "P[A]". + br label %F1 + +TX: + ; This load should not be compiled to 'ret i32 42'. An overly clever + ; implementation of GVN would see that we're returning 17 if the loop + ; executes once or 42 if it executes more than that, but we'd have to do + ; loop restructuring to expose this, and GVN shouldn't do this sort of CFG + ; transformation. + +; CHECK: TX: +; CHECK: ret i32 %x + ret i32 %x +TY: + ret i32 0 +} + +define i32 @phi_trans3(i32* %p) { +; CHECK: @phi_trans3 +block1: + br i1 true, label %block2, label %block3 + +block2: + store i32 87, i32* %p + br label %block4 + +block3: + %p2 = getelementptr i32* %p, i32 43 + store i32 97, i32* %p2 + br label %block4 + +block4: + %A = phi i32 [-1, %block2], [42, %block3] + br i1 true, label %block5, label %exit + +; CHECK: block4: +; CHECK-NEXT: %D = phi i32 [ 87, %block2 ], [ 97, %block3 ] +; CHECK-NOT: load + +block5: + %B = add i32 %A, 1 + br i1 true, label %block6, label %exit + +block6: + %C = getelementptr i32* %p, i32 %B + br i1 true, label %block7, label %exit + +block7: + %D = load i32* %C + ret i32 %D + +; CHECK: block7: +; CHECK-NEXT: ret i32 %D + +exit: + ret i32 -1 +} + +define i8 @phi_trans4(i8* %p) { +; CHECK: @phi_trans4 +entry: + %X3 = getelementptr i8* %p, i32 192 + store i8 192, i8* %X3 + + %X = getelementptr i8* %p, i32 4 + %Y = load i8* %X + br label %loop + +loop: + %i = phi i32 [4, %entry], [192, %loop] + %X2 = getelementptr i8* %p, i32 %i + %Y2 = load i8* %X2 + +; CHECK: loop: +; CHECK-NEXT: %Y2 = phi i8 [ %Y, %entry ], [ 0, %loop ] +; CHECK-NOT: load i8 + + %cond = call i1 @cond2() + + %Z = bitcast i8 *%X3 to i32* + store i32 0, i32* %Z + br i1 %cond, label %loop, label %out + +out: + %R = add i8 %Y, %Y2 + ret i8 %R +} + +define i8 @phi_trans5(i8* %p) { +; CHECK: @phi_trans5 +entry: + + %X4 = getelementptr i8* %p, i32 2 + store i8 19, i8* %X4 + + %X = getelementptr i8* %p, i32 4 + %Y = load i8* %X + br label %loop + +loop: + %i = phi i32 [4, %entry], [3, %cont] + %X2 = getelementptr i8* %p, i32 %i + %Y2 = load i8* %X2 ; Ensure this load is not being incorrectly replaced. + %cond = call i1 @cond2() + br i1 %cond, label %cont, label %out + +cont: + %Z = getelementptr i8* %X2, i32 -1 + %Z2 = bitcast i8 *%Z to i32* + store i32 50462976, i32* %Z2 ;; (1 << 8) | (2 << 16) | (3 << 24) + + +; CHECK: store i32 +; CHECK-NEXT: getelementptr i8* %p, i32 3 +; CHECK-NEXT: load i8* + br label %loop + +out: + %R = add i8 %Y, %Y2 + ret i8 %R +} + + + |