diff options
Diffstat (limited to 'test/Transforms')
212 files changed, 5802 insertions, 1869 deletions
diff --git a/test/Transforms/ADCE/2003-09-10-UnwindInstFail.ll b/test/Transforms/ADCE/2003-09-10-UnwindInstFail.ll index 444ca8ec904b9..6bbcfdb67ec58 100644 --- a/test/Transforms/ADCE/2003-09-10-UnwindInstFail.ll +++ b/test/Transforms/ADCE/2003-09-10-UnwindInstFail.ll @@ -8,7 +8,9 @@ then: ; preds = %0 to label %invoke_cont unwind label %invoke_catch invoke_catch: ; preds = %then - unwind + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup + resume { i8*, i32 } %exn invoke_cont: ; preds = %then ret void @@ -17,3 +19,4 @@ endif: ; preds = %0 ret void } +declare i32 @__gxx_personality_v0(...) diff --git a/test/Transforms/ADCE/2004-05-04-UnreachableBlock.ll b/test/Transforms/ADCE/2004-05-04-UnreachableBlock.ll index a6a41fd69effe..7ee0f468af0b9 100644 --- a/test/Transforms/ADCE/2004-05-04-UnreachableBlock.ll +++ b/test/Transforms/ADCE/2004-05-04-UnreachableBlock.ll @@ -11,6 +11,6 @@ invoke_catch.0: ; No predecessors! br i1 false, label %UnifiedUnwindBlock, label %UnifiedReturnBlock UnifiedUnwindBlock: ; preds = %invoke_catch.0 - unwind + unreachable } diff --git a/test/Transforms/ADCE/2005-02-17-PHI-Invoke-Crash.ll b/test/Transforms/ADCE/2005-02-17-PHI-Invoke-Crash.ll index 991e876a25b77..4ddc2f180a2d3 100644 --- a/test/Transforms/ADCE/2005-02-17-PHI-Invoke-Crash.ll +++ b/test/Transforms/ADCE/2005-02-17-PHI-Invoke-Crash.ll @@ -15,17 +15,21 @@ tmp.3.i.noexc: ; preds = %entry br i1 false, label %then.0, label %else.0 invoke_catch.0: ; preds = %entry + %exn.0 = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup invoke void @q_atomic_decrement( ) to label %tmp.1.i.i183.noexc unwind label %terminate tmp.1.i.i183.noexc: ; preds = %invoke_catch.0 - unwind + ret void then.0: ; preds = %tmp.3.i.noexc invoke void @_ZN10QByteArray6resizeEi( ) to label %invoke_cont.1 unwind label %invoke_catch.1 invoke_catch.1: ; preds = %then.0 + %exn.1 = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup invoke void @q_atomic_decrement( ) to label %tmp.1.i.i162.noexc unwind label %terminate @@ -40,6 +44,9 @@ else.0: ; preds = %tmp.3.i.noexc terminate: ; preds = %invoke_catch.1, %invoke_catch.0 %dbg.0.1 = phi { }* [ null, %invoke_catch.1 ], [ null, %invoke_catch.0 ] ; <{ }*> [#uses=0] + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup unreachable } +declare i32 @__gxx_personality_v0(...) diff --git a/test/Transforms/ADCE/dce_pure_invoke.ll b/test/Transforms/ADCE/dce_pure_invoke.ll index c16d45cc23939..8e7851804575b 100644 --- a/test/Transforms/ADCE/dce_pure_invoke.ll +++ b/test/Transforms/ADCE/dce_pure_invoke.ll @@ -11,5 +11,9 @@ Cont: ; preds = %0 ret i32 0 Other: ; preds = %0 + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup ret i32 1 } + +declare i32 @__gxx_personality_v0(...) diff --git a/test/Transforms/CodeExtractor/2004-03-18-InvokeHandling.ll b/test/Transforms/CodeExtractor/2004-03-18-InvokeHandling.ll index 91e9799ad9cab..ff5de6b73e210 100644 --- a/test/Transforms/CodeExtractor/2004-03-18-InvokeHandling.ll +++ b/test/Transforms/CodeExtractor/2004-03-18-InvokeHandling.ll @@ -190,5 +190,9 @@ return: ; preds = %entry ret void LongJmpBlkPre: ; preds = %endif.52, %then.40 + %exn = landingpad { i8*, i32 } personality i32 (...)* @__gcc_personality_v0 + catch i8* null ret void } + +declare i32 @__gcc_personality_v0(...) diff --git a/test/Transforms/CodeExtractor/2004-11-12-InvokeExtract.ll b/test/Transforms/CodeExtractor/2004-11-12-InvokeExtract.ll index fc58577f67abf..92603d9e634ea 100644 --- a/test/Transforms/CodeExtractor/2004-11-12-InvokeExtract.ll +++ b/test/Transforms/CodeExtractor/2004-11-12-InvokeExtract.ll @@ -10,6 +10,9 @@ Cont: ; preds = %EB ret i32 %V Unw: ; preds = %EB - unwind + %exn = landingpad { i8*, i32 } personality i32 (...)* @__gcc_personality_v0 + catch i8* null + resume { i8*, i32 } %exn } +declare i32 @__gcc_personality_v0(...) diff --git a/test/Transforms/ConstantMerge/merge-both.ll b/test/Transforms/ConstantMerge/merge-both.ll index 0282f464aeee9..b71eb437dbc3f 100644 --- a/test/Transforms/ConstantMerge/merge-both.ll +++ b/test/Transforms/ConstantMerge/merge-both.ll @@ -1,5 +1,7 @@ ; RUN: opt -constmerge %s -S -o - | FileCheck %s ; Test that in one run var3 is merged into var2 and var1 into var4. +; Test that we merge @var5 and @var6 into one with the higher alignment, and +; don't merge var7/var8 into var5/var6. declare void @zed(%struct.foobar*, %struct.foobar*) @@ -14,13 +16,24 @@ declare void @zed(%struct.foobar*, %struct.foobar*) ; CHECK-NOT: @ ; CHECK: @var2 = constant %struct.foobar { i32 2 } ; CHECK-NEXT: @var4 = constant %struct.foobar { i32 2 } -; CHECK-NOT: @ -; CHECK: declare void @zed(%struct.foobar*, %struct.foobar*) + +declare void @helper([16 x i8]*) +@var5 = internal constant [16 x i8] c"foo1bar2foo3bar\00", align 16 +@var6 = private unnamed_addr constant [16 x i8] c"foo1bar2foo3bar\00", align 1 +@var7 = internal constant [16 x i8] c"foo1bar2foo3bar\00" +@var8 = private unnamed_addr constant [16 x i8] c"foo1bar2foo3bar\00" + +; CHECK-NEXT: @var6 = private constant [16 x i8] c"foo1bar2foo3bar\00", align 16 +; CHECK-NEXT: @var8 = private constant [16 x i8] c"foo1bar2foo3bar\00" define i32 @main() { entry: call void @zed(%struct.foobar* @var1, %struct.foobar* @var2) call void @zed(%struct.foobar* @var3, %struct.foobar* @var4) + call void @helper([16 x i8]* @var5) + call void @helper([16 x i8]* @var6) + call void @helper([16 x i8]* @var7) + call void @helper([16 x i8]* @var8) ret i32 0 } diff --git a/test/Transforms/DeadArgElim/2009-03-17-MRE-Invoke.ll b/test/Transforms/DeadArgElim/2009-03-17-MRE-Invoke.ll index 161821f3f8f79..fc25daca1c2ed 100644 --- a/test/Transforms/DeadArgElim/2009-03-17-MRE-Invoke.ll +++ b/test/Transforms/DeadArgElim/2009-03-17-MRE-Invoke.ll @@ -11,6 +11,8 @@ T: %y = extractvalue {i32,i32} %x, 1 ret i32 %y T2: + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup unreachable } @@ -22,5 +24,9 @@ T: %y = extractvalue {i32,i32} %x, 1 ret i32 %y T2: + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup unreachable } + +declare i32 @__gxx_personality_v0(...) diff --git a/test/Transforms/DeadArgElim/deadexternal.ll b/test/Transforms/DeadArgElim/deadexternal.ll index 84092613130b7..b2d63ec772095 100644 --- a/test/Transforms/DeadArgElim/deadexternal.ll +++ b/test/Transforms/DeadArgElim/deadexternal.ll @@ -31,7 +31,7 @@ define void @h() { entry: %i = alloca i32, align 4 volatile store i32 10, i32* %i, align 4 -; CHECK: %tmp = volatile load i32* %i, align 4 +; CHECK: %tmp = load volatile i32* %i, align 4 ; CHECK-next: call void @f(i32 undef) %tmp = volatile load i32* %i, align 4 call void @f(i32 %tmp) diff --git a/test/Transforms/DeadStoreElimination/2011-09-06-EndOfFunction.ll b/test/Transforms/DeadStoreElimination/2011-09-06-EndOfFunction.ll new file mode 100644 index 0000000000000..c5cc101a5f7b3 --- /dev/null +++ b/test/Transforms/DeadStoreElimination/2011-09-06-EndOfFunction.ll @@ -0,0 +1,27 @@ +; RUN: opt -dse -S < %s | FileCheck %s + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" +target triple = "x86_64-apple-darwin" + +%"class.std::auto_ptr" = type { i32* } + +; CHECK: @_Z3foov +define void @_Z3foov(%"class.std::auto_ptr"* noalias nocapture sret %agg.result) uwtable ssp { +_ZNSt8auto_ptrIiED1Ev.exit: + %temp.lvalue = alloca %"class.std::auto_ptr", align 8 + call void @_Z3barv(%"class.std::auto_ptr"* sret %temp.lvalue) + %_M_ptr.i.i = getelementptr inbounds %"class.std::auto_ptr"* %temp.lvalue, i64 0, i32 0 + %tmp.i.i = load i32** %_M_ptr.i.i, align 8, !tbaa !0 +; CHECK-NOT: store i32* null + store i32* null, i32** %_M_ptr.i.i, align 8, !tbaa !0 + %_M_ptr.i.i4 = getelementptr inbounds %"class.std::auto_ptr"* %agg.result, i64 0, i32 0 + store i32* %tmp.i.i, i32** %_M_ptr.i.i4, align 8, !tbaa !0 +; CHECK: ret void + ret void +} + +declare void @_Z3barv(%"class.std::auto_ptr"* sret) + +!0 = metadata !{metadata !"any pointer", metadata !1} +!1 = metadata !{metadata !"omnipotent char", metadata !2} +!2 = metadata !{metadata !"Simple C/C++ TBAA", null} diff --git a/test/Transforms/DeadStoreElimination/2011-09-06-MemCpy.ll b/test/Transforms/DeadStoreElimination/2011-09-06-MemCpy.ll new file mode 100644 index 0000000000000..22b87864c0632 --- /dev/null +++ b/test/Transforms/DeadStoreElimination/2011-09-06-MemCpy.ll @@ -0,0 +1,85 @@ +; RUN: opt -dse -S < %s | FileCheck %s +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-f128:128:128-n8:16:32:64" +target triple = "x86_64-unknown-linux-gnu" + +%struct.pair.162 = type { %struct.BasicBlock*, i32, [4 x i8] } +%struct.BasicBlock = type { %struct.Value, %struct.ilist_node.24, %struct.iplist.22, %struct.Function* } +%struct.Value = type { i32 (...)**, i8, i8, i16, %struct.Type*, %struct.Use*, %struct.StringMapEntry* } +%struct.Type = type { %struct.LLVMContext*, i8, [3 x i8], i32, {}* } +%struct.LLVMContext = type { %struct.LLVMContextImpl* } +%struct.LLVMContextImpl = type opaque +%struct.Use = type { %struct.Value*, %struct.Use*, %struct.PointerIntPair } +%struct.PointerIntPair = type { i64 } +%struct.StringMapEntry = type opaque +%struct.ilist_node.24 = type { %struct.ilist_half_node.23, %struct.BasicBlock* } +%struct.ilist_half_node.23 = type { %struct.BasicBlock* } +%struct.iplist.22 = type { %struct.ilist_traits.21, %struct.Instruction* } +%struct.ilist_traits.21 = type { %struct.ilist_half_node.25 } +%struct.ilist_half_node.25 = type { %struct.Instruction* } +%struct.Instruction = type { [52 x i8], %struct.ilist_node.26, %struct.BasicBlock*, %struct.DebugLoc } +%struct.ilist_node.26 = type { %struct.ilist_half_node.25, %struct.Instruction* } +%struct.DebugLoc = type { i32, i32 } +%struct.Function = type { %struct.GlobalValue, %struct.ilist_node.14, %struct.iplist.4, %struct.iplist, %struct.ValueSymbolTable*, %struct.AttrListPtr } +%struct.GlobalValue = type <{ [52 x i8], [4 x i8], %struct.Module*, i8, i16, [5 x i8], %struct.basic_string }> +%struct.Module = type { %struct.LLVMContext*, %struct.iplist.20, %struct.iplist.16, %struct.iplist.12, %struct.vector.2, %struct.ilist, %struct.basic_string, %struct.ValueSymbolTable*, %struct.OwningPtr, %struct.basic_string, %struct.basic_string, %struct.basic_string, i8* } +%struct.iplist.20 = type { %struct.ilist_traits.19, %struct.GlobalVariable* } +%struct.ilist_traits.19 = type { %struct.ilist_node.18 } +%struct.ilist_node.18 = type { %struct.ilist_half_node.17, %struct.GlobalVariable* } +%struct.ilist_half_node.17 = type { %struct.GlobalVariable* } +%struct.GlobalVariable = type { %struct.GlobalValue, %struct.ilist_node.18, i8, [7 x i8] } +%struct.iplist.16 = type { %struct.ilist_traits.15, %struct.Function* } +%struct.ilist_traits.15 = type { %struct.ilist_node.14 } +%struct.ilist_node.14 = type { %struct.ilist_half_node.13, %struct.Function* } +%struct.ilist_half_node.13 = type { %struct.Function* } +%struct.iplist.12 = type { %struct.ilist_traits.11, %struct.GlobalAlias* } +%struct.ilist_traits.11 = type { %struct.ilist_node.10 } +%struct.ilist_node.10 = type { %struct.ilist_half_node.9, %struct.GlobalAlias* } +%struct.ilist_half_node.9 = type { %struct.GlobalAlias* } +%struct.GlobalAlias = type { %struct.GlobalValue, %struct.ilist_node.10 } +%struct.vector.2 = type { %struct._Vector_base.1 } +%struct._Vector_base.1 = type { %struct._Vector_impl.0 } +%struct._Vector_impl.0 = type { %struct.basic_string*, %struct.basic_string*, %struct.basic_string* } +%struct.basic_string = type { %struct._Alloc_hider } +%struct._Alloc_hider = type { i8* } +%struct.ilist = type { %struct.iplist.8 } +%struct.iplist.8 = type { %struct.ilist_traits.7, %struct.NamedMDNode* } +%struct.ilist_traits.7 = type { %struct.ilist_node.6 } +%struct.ilist_node.6 = type { %struct.ilist_half_node.5, %struct.NamedMDNode* } +%struct.ilist_half_node.5 = type { %struct.NamedMDNode* } +%struct.NamedMDNode = type { %struct.ilist_node.6, %struct.basic_string, %struct.Module*, i8* } +%struct.ValueSymbolTable = type opaque +%struct.OwningPtr = type { %struct.GVMaterializer* } +%struct.GVMaterializer = type opaque +%struct.iplist.4 = type { %struct.ilist_traits.3, %struct.BasicBlock* } +%struct.ilist_traits.3 = type { %struct.ilist_half_node.23 } +%struct.iplist = type { %struct.ilist_traits, %struct.Argument* } +%struct.ilist_traits = type { %struct.ilist_half_node } +%struct.ilist_half_node = type { %struct.Argument* } +%struct.Argument = type { %struct.Value, %struct.ilist_node, %struct.Function* } +%struct.ilist_node = type { %struct.ilist_half_node, %struct.Argument* } +%struct.AttrListPtr = type { %struct.AttributeListImpl* } +%struct.AttributeListImpl = type opaque + +declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i32, i1) nounwind + +; CHECK: _ZSt9iter_swapIPSt4pairIPN4llvm10BasicBlockEjES5_EvT_T0_ +; CHECK: store +; CHECK: ret void +define void @_ZSt9iter_swapIPSt4pairIPN4llvm10BasicBlockEjES5_EvT_T0_(%struct.pair.162* %__a, %struct.pair.162* %__b) nounwind uwtable inlinehint { +entry: + %memtmp = alloca %struct.pair.162, align 8 + %0 = getelementptr inbounds %struct.pair.162* %memtmp, i64 0, i32 0 + %1 = getelementptr inbounds %struct.pair.162* %__a, i64 0, i32 0 + %2 = load %struct.BasicBlock** %1, align 8 + store %struct.BasicBlock* %2, %struct.BasicBlock** %0, align 8 + %3 = getelementptr inbounds %struct.pair.162* %memtmp, i64 0, i32 1 + %4 = getelementptr inbounds %struct.pair.162* %__a, i64 0, i32 1 + %5 = load i32* %4, align 4 + store i32 %5, i32* %3, align 8 + %6 = bitcast %struct.pair.162* %__a to i8* + %7 = bitcast %struct.pair.162* %__b to i8* + call void @llvm.memcpy.p0i8.p0i8.i64(i8* %6, i8* %7, i64 12, i32 1, i1 false) + %8 = bitcast %struct.pair.162* %memtmp to i8* + call void @llvm.memcpy.p0i8.p0i8.i64(i8* %7, i8* %8, i64 12, i32 1, i1 false) + ret void +} diff --git a/test/Transforms/DeadStoreElimination/atomic.ll b/test/Transforms/DeadStoreElimination/atomic.ll new file mode 100644 index 0000000000000..2e84298ad400a --- /dev/null +++ b/test/Transforms/DeadStoreElimination/atomic.ll @@ -0,0 +1,107 @@ +; RUN: opt -basicaa -dse -S < %s | FileCheck %s + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" +target triple = "x86_64-apple-macosx10.7.0" + +; Sanity tests for atomic stores. +; Note that it turns out essentially every transformation DSE does is legal on +; atomic ops, just some transformations are not allowed across them. + +@x = common global i32 0, align 4 +@y = common global i32 0, align 4 + +declare void @randomop(i32*) + +; DSE across unordered store (allowed) +define void @test1() nounwind uwtable ssp { +; CHECK: test1 +; CHECK-NOT: store i32 0 +; CHECK: store i32 1 +entry: + store i32 0, i32* @x + store atomic i32 0, i32* @y unordered, align 4 + store i32 1, i32* @x + ret void +} + +; DSE across seq_cst load (allowed in theory; not implemented ATM) +define i32 @test2() nounwind uwtable ssp { +; CHECK: test2 +; CHECK: store i32 0 +; CHECK: store i32 1 +entry: + store i32 0, i32* @x + %x = load atomic i32* @y seq_cst, align 4 + store i32 1, i32* @x + ret i32 %x +} + +; DSE across seq_cst store (store before atomic store must not be removed) +define void @test3() nounwind uwtable ssp { +; CHECK: test3 +; CHECK: store i32 +; CHECK: store atomic i32 2 +entry: + store i32 0, i32* @x + store atomic i32 2, i32* @y seq_cst, align 4 + store i32 1, i32* @x + ret void +} + +; DSE remove unordered store (allowed) +define void @test4() nounwind uwtable ssp { +; CHECK: test4 +; CHECK-NOT: store atomic +; CHECK: store i32 1 +entry: + store atomic i32 0, i32* @x unordered, align 4 + store i32 1, i32* @x + ret void +} + +; DSE unordered store overwriting non-atomic store (allowed) +define void @test5() nounwind uwtable ssp { +; CHECK: test5 +; CHECK: store atomic i32 1 +entry: + store i32 0, i32* @x + store atomic i32 1, i32* @x unordered, align 4 + ret void +} + +; DSE no-op unordered atomic store (allowed) +define void @test6() nounwind uwtable ssp { +; CHECK: test6 +; CHECK-NOT: store +; CHECK: ret void +entry: + %x = load atomic i32* @x unordered, align 4 + store atomic i32 %x, i32* @x unordered, align 4 + ret void +} + +; DSE seq_cst store (be conservative; DSE doesn't have infrastructure +; to reason about atomic operations). +define void @test7() nounwind uwtable ssp { +; CHECK: test7 +; CHECK: store atomic +entry: + %a = alloca i32 + store atomic i32 0, i32* %a seq_cst, align 4 + ret void +} + +; DSE and seq_cst load (be conservative; DSE doesn't have infrastructure +; to reason about atomic operations). +define i32 @test8() nounwind uwtable ssp { +; CHECK: test8 +; CHECK: store +; CHECK: load atomic +entry: + %a = alloca i32 + call void @randomop(i32* %a) + store i32 0, i32* %a, align 4 + %x = load atomic i32* @x seq_cst, align 4 + ret i32 %x +} + diff --git a/test/Transforms/DeadStoreElimination/simple.ll b/test/Transforms/DeadStoreElimination/simple.ll index 5f143fcd1ede3..ec2f15737a379 100644 --- a/test/Transforms/DeadStoreElimination/simple.ll +++ b/test/Transforms/DeadStoreElimination/simple.ll @@ -42,20 +42,20 @@ define i32 @test3(i32* %g_addr) nounwind { define void @test4(i32* %Q) { %a = load i32* %Q - volatile store i32 %a, i32* %Q + store volatile i32 %a, i32* %Q ret void ; CHECK: @test4 ; CHECK-NEXT: load i32 -; CHECK-NEXT: volatile store +; CHECK-NEXT: store volatile ; CHECK-NEXT: ret void } define void @test5(i32* %Q) { - %a = volatile load i32* %Q + %a = load volatile i32* %Q store i32 %a, i32* %Q ret void ; CHECK: @test5 -; CHECK-NEXT: volatile load +; CHECK-NEXT: load volatile ; CHECK-NEXT: ret void } diff --git a/test/Transforms/EarlyCSE/basic.ll b/test/Transforms/EarlyCSE/basic.ll index e3c75f97dcfcf..57b1697ff4deb 100644 --- a/test/Transforms/EarlyCSE/basic.ll +++ b/test/Transforms/EarlyCSE/basic.ll @@ -13,21 +13,21 @@ define void @test1(i8 %V, i32 *%P) { volatile store i32 %C, i32* %P volatile store i32 %D, i32* %P ; CHECK-NEXT: %C = zext i8 %V to i32 - ; CHECK-NEXT: volatile store i32 %C - ; CHECK-NEXT: volatile store i32 %C + ; CHECK-NEXT: store volatile i32 %C + ; CHECK-NEXT: store volatile i32 %C %E = add i32 %C, %C %F = add i32 %C, %C volatile store i32 %E, i32* %P volatile store i32 %F, i32* %P ; CHECK-NEXT: %E = add i32 %C, %C - ; CHECK-NEXT: volatile store i32 %E - ; CHECK-NEXT: volatile store i32 %E + ; CHECK-NEXT: store volatile i32 %E + ; CHECK-NEXT: store volatile i32 %E %G = add nuw i32 %C, %C ;; not a CSE with E volatile store i32 %G, i32* %P ; CHECK-NEXT: %G = add nuw i32 %C, %C - ; CHECK-NEXT: volatile store i32 %G + ; CHECK-NEXT: store volatile i32 %G ret void } diff --git a/test/Transforms/FunctionAttrs/2008-12-31-NoCapture.ll b/test/Transforms/FunctionAttrs/2008-12-31-NoCapture.ll index 53857f61ce582..e2bab19e7efdd 100644 --- a/test/Transforms/FunctionAttrs/2008-12-31-NoCapture.ll +++ b/test/Transforms/FunctionAttrs/2008-12-31-NoCapture.ll @@ -46,9 +46,13 @@ define i1 @c6(i8* %q, i8 %bit) { ret0: ret i1 0 ret1: + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup ret i1 1 } +declare i32 @__gxx_personality_v0(...) + define i1* @lookup_bit(i32* %q, i32 %bitno) readnone nounwind { %tmp = ptrtoint i32* %q to i32 %tmp2 = lshr i32 %tmp, %bitno diff --git a/test/Transforms/FunctionAttrs/atomic.ll b/test/Transforms/FunctionAttrs/atomic.ll new file mode 100644 index 0000000000000..7c2bff7a05f71 --- /dev/null +++ b/test/Transforms/FunctionAttrs/atomic.ll @@ -0,0 +1,21 @@ +; RUN: opt -basicaa -functionattrs -S < %s | FileCheck %s + +; Atomic load/store to local doesn't affect whether a function is +; readnone/readonly. +define i32 @test1(i32 %x) uwtable ssp { +; CHECK: define i32 @test1(i32 %x) uwtable readnone ssp { +entry: + %x.addr = alloca i32, align 4 + store atomic i32 %x, i32* %x.addr seq_cst, align 4 + %r = load atomic i32* %x.addr seq_cst, align 4 + ret i32 %r +} + +; A function with an Acquire load is not readonly. +define i32 @test2(i32* %x) uwtable ssp { +; CHECK: define i32 @test2(i32* nocapture %x) uwtable ssp { +entry: + %r = load atomic i32* %x seq_cst, align 4 + ret i32 %r +} + diff --git a/test/Transforms/GVN/2010-05-08-OneBit.ll b/test/Transforms/GVN/2010-05-08-OneBit.ll index 1809cf03f900f..480ce8ba0ae13 100644 --- a/test/Transforms/GVN/2010-05-08-OneBit.ll +++ b/test/Transforms/GVN/2010-05-08-OneBit.ll @@ -45,6 +45,8 @@ k151.i.i: ; preds = %k133.i.i ret i32 0 landing_pad: ; preds = %l147.i.i, %l129.i.i, %l117.i.i + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup switch i32 undef, label %fin [ i32 1, label %catch1 i32 2, label %catch @@ -61,3 +63,5 @@ catch1: ; preds = %landing_pad } declare fastcc void @foo() + +declare i32 @__gxx_personality_v0(...) diff --git a/test/Transforms/GVN/2011-09-07-TypeIdFor.ll b/test/Transforms/GVN/2011-09-07-TypeIdFor.ll new file mode 100644 index 0000000000000..314b5bb113a68 --- /dev/null +++ b/test/Transforms/GVN/2011-09-07-TypeIdFor.ll @@ -0,0 +1,81 @@ +; RUN: opt < %s -basicaa -gvn -S | FileCheck %s +%struct.__fundamental_type_info_pseudo = type { %struct.__type_info_pseudo } +%struct.__type_info_pseudo = type { i8*, i8* } + +@_ZTIi = external constant %struct.__fundamental_type_info_pseudo +@_ZTIb = external constant %struct.__fundamental_type_info_pseudo + +declare void @_Z4barv() + +declare void @_Z7cleanupv() + +declare i32 @llvm.eh.typeid.for(i8*) nounwind readonly + +declare i8* @__cxa_begin_catch(i8*) nounwind + +declare void @__cxa_end_catch() + +declare i32 @__gxx_personality_v0(i32, i64, i8*, i8*) + +define void @_Z3foov() uwtable { +entry: + invoke void @_Z4barv() + to label %return unwind label %lpad + +lpad: ; preds = %entry + %0 = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @__gxx_personality_v0 + catch %struct.__fundamental_type_info_pseudo* @_ZTIi + catch %struct.__fundamental_type_info_pseudo* @_ZTIb + catch %struct.__fundamental_type_info_pseudo* @_ZTIi + catch %struct.__fundamental_type_info_pseudo* @_ZTIb + %exc_ptr2.i = extractvalue { i8*, i32 } %0, 0 + %filter3.i = extractvalue { i8*, i32 } %0, 1 + %typeid.i = tail call i32 @llvm.eh.typeid.for(i8* bitcast (%struct.__fundamental_type_info_pseudo* @_ZTIi to i8*)) +; CHECK: call i32 @llvm.eh.typeid.for + %1 = icmp eq i32 %filter3.i, %typeid.i + br i1 %1, label %ppad, label %next + +next: ; preds = %lpad + %typeid1.i = tail call i32 @llvm.eh.typeid.for(i8* bitcast (%struct.__fundamental_type_info_pseudo* @_ZTIb to i8*)) +; CHECK: call i32 @llvm.eh.typeid.for + %2 = icmp eq i32 %filter3.i, %typeid1.i + br i1 %2, label %ppad2, label %next2 + +ppad: ; preds = %lpad + %3 = tail call i8* @__cxa_begin_catch(i8* %exc_ptr2.i) nounwind + tail call void @__cxa_end_catch() nounwind + br label %return + +ppad2: ; preds = %next + %D.2073_5.i = tail call i8* @__cxa_begin_catch(i8* %exc_ptr2.i) nounwind + tail call void @__cxa_end_catch() nounwind + br label %return + +next2: ; preds = %next + call void @_Z7cleanupv() + %typeid = tail call i32 @llvm.eh.typeid.for(i8* bitcast (%struct.__fundamental_type_info_pseudo* @_ZTIi to i8*)) +; CHECK-NOT: call i32 @llvm.eh.typeid.for + %4 = icmp eq i32 %filter3.i, %typeid + br i1 %4, label %ppad3, label %next3 + +next3: ; preds = %next2 + %typeid1 = tail call i32 @llvm.eh.typeid.for(i8* bitcast (%struct.__fundamental_type_info_pseudo* @_ZTIb to i8*)) + %5 = icmp eq i32 %filter3.i, %typeid1 + br i1 %5, label %ppad4, label %unwind + +unwind: ; preds = %next3 + resume { i8*, i32 } %0 + +ppad3: ; preds = %next2 + %6 = tail call i8* @__cxa_begin_catch(i8* %exc_ptr2.i) nounwind + tail call void @__cxa_end_catch() nounwind + br label %return + +ppad4: ; preds = %next3 + %D.2080_5 = tail call i8* @__cxa_begin_catch(i8* %exc_ptr2.i) nounwind + tail call void @__cxa_end_catch() nounwind + br label %return + +return: ; preds = %ppad4, %ppad3, %ppad2, %ppad, %entry + ret void +} diff --git a/test/Transforms/GVN/atomic.ll b/test/Transforms/GVN/atomic.ll new file mode 100644 index 0000000000000..094e22bd07e19 --- /dev/null +++ b/test/Transforms/GVN/atomic.ll @@ -0,0 +1,80 @@ +; RUN: opt -basicaa -gvn -S < %s | FileCheck %s + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" +target triple = "x86_64-apple-macosx10.7.0" + +@x = common global i32 0, align 4 +@y = common global i32 0, align 4 + +; GVN across unordered store (allowed) +define i32 @test1() nounwind uwtable ssp { +; CHECK: test1 +; CHECK: add i32 %x, %x +entry: + %x = load i32* @y + store atomic i32 %x, i32* @x unordered, align 4 + %y = load i32* @y + %z = add i32 %x, %y + ret i32 %z +} + +; GVN across seq_cst store (allowed in theory; not implemented ATM) +define i32 @test2() nounwind uwtable ssp { +; CHECK: test2 +; CHECK: add i32 %x, %y +entry: + %x = load i32* @y + store atomic i32 %x, i32* @x seq_cst, align 4 + %y = load i32* @y + %z = add i32 %x, %y + ret i32 %z +} + +; GVN across unordered load (allowed) +define i32 @test3() nounwind uwtable ssp { +; CHECK: test3 +; CHECK: add i32 %x, %x +entry: + %x = load i32* @y + %y = load atomic i32* @x unordered, align 4 + %z = load i32* @y + %a = add i32 %x, %z + %b = add i32 %y, %a + ret i32 %b +} + +; GVN across acquire load (load after atomic load must not be removed) +define i32 @test4() nounwind uwtable ssp { +; CHECK: test4 +; CHECK: load atomic i32* @x +; CHECK: load i32* @y +entry: + %x = load i32* @y + %y = load atomic i32* @x seq_cst, align 4 + %x2 = load i32* @y + %x3 = add i32 %x, %x2 + %y2 = add i32 %y, %x3 + ret i32 %y2 +} + +; GVN load to unordered load (allowed) +define i32 @test5() nounwind uwtable ssp { +; CHECK: test5 +; CHECK: add i32 %x, %x +entry: + %x = load atomic i32* @x unordered, align 4 + %y = load i32* @x + %z = add i32 %x, %y + ret i32 %z +} + +; GVN unordered load to load (unordered load must not be removed) +define i32 @test6() nounwind uwtable ssp { +; CHECK: test6 +; CHECK: load atomic i32* @x unordered +entry: + %x = load i32* @x + %x2 = load atomic i32* @x unordered, align 4 + %x3 = add i32 %x, %x2 + ret i32 %x3 +} diff --git a/test/Transforms/GVN/condprop.ll b/test/Transforms/GVN/condprop.ll index be6c3498fe409..0b31b01b7b143 100644 --- a/test/Transforms/GVN/condprop.ll +++ b/test/Transforms/GVN/condprop.ll @@ -2,8 +2,8 @@ @a = external global i32 ; <i32*> [#uses=7] -; CHECK: @foo -define i32 @foo() nounwind { +; CHECK: @test1 +define i32 @test1() nounwind { entry: %0 = load i32* @a, align 4 %1 = icmp eq i32 %0, 4 @@ -52,4 +52,81 @@ bb8: ; preds = %bb7, %bb6, %bb4, %bb2, %bb return: ; preds = %bb8 ret i32 %.0 -}
\ No newline at end of file +} + +declare void @foo(i1) + +; CHECK: @test2 +define void @test2(i1 %x, i1 %y) { + %z = or i1 %x, %y + br i1 %z, label %true, label %false +true: +; CHECK: true: + %z2 = or i1 %x, %y + call void @foo(i1 %z2) +; CHECK: call void @foo(i1 true) + br label %true +false: +; CHECK: false: + %z3 = or i1 %x, %y + call void @foo(i1 %z3) +; CHECK: call void @foo(i1 false) + br label %false +} + +declare void @bar(i32) + +; CHECK: @test3 +define void @test3(i32 %x, i32 %y) { + %xz = icmp eq i32 %x, 0 + %yz = icmp eq i32 %y, 0 + %z = and i1 %xz, %yz + br i1 %z, label %both_zero, label %nope +both_zero: + call void @foo(i1 %xz) +; CHECK: call void @foo(i1 true) + call void @foo(i1 %yz) +; CHECK: call void @foo(i1 true) + call void @bar(i32 %x) +; CHECK: call void @bar(i32 0) + call void @bar(i32 %y) +; CHECK: call void @bar(i32 0) + ret void +nope: + call void @foo(i1 %z) +; CHECK: call void @foo(i1 false) + ret void +} + +; CHECK: @test4 +define void @test4(i1 %b, i32 %x) { + br i1 %b, label %sw, label %case3 +sw: + switch i32 %x, label %default [ + i32 0, label %case0 + i32 1, label %case1 + i32 2, label %case0 + i32 3, label %case3 + i32 4, label %default + ] +default: +; CHECK: default: + call void @bar(i32 %x) +; CHECK: call void @bar(i32 %x) + ret void +case0: +; CHECK: case0: + call void @bar(i32 %x) +; CHECK: call void @bar(i32 %x) + ret void +case1: +; CHECK: case1: + call void @bar(i32 %x) +; CHECK: call void @bar(i32 1) + ret void +case3: +; CHECK: case3: + call void @bar(i32 %x) +; CHECK: call void @bar(i32 %x) + ret void +} diff --git a/test/Transforms/GVN/phi-translate.ll b/test/Transforms/GVN/phi-translate.ll index f10537e0c9300..fa91d2919eb20 100644 --- a/test/Transforms/GVN/phi-translate.ll +++ b/test/Transforms/GVN/phi-translate.ll @@ -14,7 +14,7 @@ target datalayout = "e-p:64:64:64" @G = external global [100 x i32] define i32 @foo(i32 %x, i32 %z) { entry: - %tobool = icmp eq i32 %x, 0 + %tobool = icmp eq i32 %z, 0 br i1 %tobool, label %end, label %then then: diff --git a/test/Transforms/GVN/pr10820.ll b/test/Transforms/GVN/pr10820.ll new file mode 100644 index 0000000000000..12c1e70fc3877 --- /dev/null +++ b/test/Transforms/GVN/pr10820.ll @@ -0,0 +1,18 @@ +; RUN: opt < %s -basicaa -gvn -S | FileCheck %s + +target datalayout = +"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-f128:128:128-n8:16:32:64" +target triple = "x86_64-unknown-linux-gnu" + +@g = external global i31 + +define void @main() nounwind uwtable { +entry: +; CHECK: store i32 + store i32 402662078, i32* bitcast (i31* @g to i32*), align 8 +; CHECK-NOT: load i31 + %0 = load i31* @g, align 8 +; CHECK: store i31 + store i31 %0, i31* undef, align 1 + unreachable +} diff --git a/test/Transforms/GlobalOpt/2008-01-29-VolatileGlobal.ll b/test/Transforms/GlobalOpt/2008-01-29-VolatileGlobal.ll index 0c817005c2737..a6803abc5d360 100644 --- a/test/Transforms/GlobalOpt/2008-01-29-VolatileGlobal.ll +++ b/test/Transforms/GlobalOpt/2008-01-29-VolatileGlobal.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -globalopt -S | grep {volatile load} +; RUN: opt < %s -globalopt -S | grep {load volatile} @t0.1441 = internal global double 0x3FD5555555555555, align 8 ; <double*> [#uses=1] define double @foo() nounwind { diff --git a/test/Transforms/IPConstantProp/global.ll b/test/Transforms/IPConstantProp/global.ll new file mode 100644 index 0000000000000..67152937beec7 --- /dev/null +++ b/test/Transforms/IPConstantProp/global.ll @@ -0,0 +1,26 @@ +; RUN: opt < %s -S -ipsccp | FileCheck %s + +@_ZL6test1g = internal global i32 42, align 4 + +define void @_Z7test1f1v() nounwind { +entry: + %tmp = load i32* @_ZL6test1g, align 4 + %cmp = icmp eq i32 %tmp, 0 + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry + store i32 0, i32* @_ZL6test1g, align 4 + br label %if.end + +if.end: ; preds = %if.then, %entry + ret void +} + +; CHECK: @_Z7test1f2v() +; CHECK: entry: +; CHECK-NEXT: ret i32 42 +define i32 @_Z7test1f2v() nounwind { +entry: + %tmp = load i32* @_ZL6test1g, align 4 + ret i32 %tmp +} diff --git a/test/Transforms/IPConstantProp/return-argument.ll b/test/Transforms/IPConstantProp/return-argument.ll index 6d6eb24cf5425..f4b7018222e94 100644 --- a/test/Transforms/IPConstantProp/return-argument.ll +++ b/test/Transforms/IPConstantProp/return-argument.ll @@ -36,14 +36,22 @@ define void @caller(i1 %C) { ;; propagated per-caller). %S1 = call { i32, i32 } @foo(i32 1, i32 2) %X1 = extractvalue { i32, i32 } %S1, 0 - %S2 = invoke { i32, i32 } @foo(i32 3, i32 4) to label %OK unwind label %RET + %S2 = invoke { i32, i32 } @foo(i32 3, i32 4) to label %OK unwind label %LPAD + OK: %X2 = extractvalue { i32, i32 } %S2, 0 ;; Do some stuff with the returned values which we can grep for %Z = add i32 %X1, %X2 store i32 %Z, i32* %W br label %RET + +LPAD: + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup + br label %RET + RET: ret void } +declare i32 @__gxx_personality_v0(...) diff --git a/test/Transforms/IPConstantProp/return-constant.ll b/test/Transforms/IPConstantProp/return-constant.ll index b25585952873d..ff15df738816d 100644 --- a/test/Transforms/IPConstantProp/return-constant.ll +++ b/test/Transforms/IPConstantProp/return-constant.ll @@ -22,5 +22,9 @@ OK: %Y = icmp ne i32 %X, 0 ; <i1> [#uses=1] ret i1 %Y FAIL: + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup ret i1 false } + +declare i32 @__gxx_personality_v0(...) diff --git a/test/Transforms/IndVarSimplify/2003-09-12-MultiplePred.ll b/test/Transforms/IndVarSimplify/2003-09-12-MultiplePred.ll deleted file mode 100644 index ecd5086f73089..0000000000000 --- a/test/Transforms/IndVarSimplify/2003-09-12-MultiplePred.ll +++ /dev/null @@ -1,15 +0,0 @@ -; RUN: opt < %s -indvars -S | grep indvar - -define i32 @test() { -; <label>:0 - br i1 true, label %LoopHead, label %LoopHead - -LoopHead: ; preds = %LoopHead, %0, %0 - %A = phi i32 [ 7, %0 ], [ 7, %0 ], [ %B, %LoopHead ] ; <i32> [#uses=1] - %B = add i32 %A, 1 ; <i32> [#uses=2] - br i1 true, label %LoopHead, label %Out - -Out: ; preds = %LoopHead - ret i32 %B -} - diff --git a/test/Transforms/IndVarSimplify/2003-12-21-IndVarSize.ll b/test/Transforms/IndVarSimplify/2003-12-21-IndVarSize.ll deleted file mode 100644 index 0fc9c8547d9d3..0000000000000 --- a/test/Transforms/IndVarSimplify/2003-12-21-IndVarSize.ll +++ /dev/null @@ -1,15 +0,0 @@ -; RUN: opt < %s -indvars -S | grep indvar | not grep i32 - -@G = global i64 0 ; <i64*> [#uses=1] - -define void @test() { -; <label>:0 - br label %Loop - -Loop: ; preds = %Loop, %0 - %X = phi i64 [ 1, %0 ], [ %X.next, %Loop ] ; <i64> [#uses=2] - %X.next = add i64 %X, 1 ; <i64> [#uses=1] - store i64 %X, i64* @G - br label %Loop -} - diff --git a/test/Transforms/IndVarSimplify/2004-04-05-InvokeCastCrash.ll b/test/Transforms/IndVarSimplify/2004-04-05-InvokeCastCrash.ll index 1ed4c44d2650c..708a961272b5a 100644 --- a/test/Transforms/IndVarSimplify/2004-04-05-InvokeCastCrash.ll +++ b/test/Transforms/IndVarSimplify/2004-04-05-InvokeCastCrash.ll @@ -110,12 +110,16 @@ declare void @_ZNK4llvm19MachineInstrBuilder7addMRegEiNS_14MachineOperand7UseTyp declare void @_ZNK4llvm19MachineInstrBuilder7addSImmEi() +declare i32 @__gxx_personality_v0(...) + define void @_ZN4llvm11_GLOBAL__N_22InsertPrologEpilogCode20runOnMachineFunctionERNS_15MachineFunctionE(%"struct.llvm::MachineFunction"* %F) { entry: %tmp.8.i = invoke %"struct.llvm::TargetFrameInfo"* null( %"struct.llvm::TargetMachine"* null ) to label %invoke_cont.0.i unwind label %invoke_catch.0.i ; <%"struct.llvm::TargetFrameInfo"*> [#uses=0] invoke_catch.0.i: ; preds = %invoke_cont.49.i, %invoke_cont.48.i, %invoke_cont.47.i, %invoke_cont.i53.i, %no_exit.i, %invoke_cont.44.i, %invoke_cont.43.i, %invoke_cont.42.i, %invoke_cont.41.i, %invoke_cont.40.i, %invoke_cont.39.i, %invoke_cont.38.i, %invoke_cont.37.i, %then.2.i, %invoke_cont.35.i, %invoke_cont.34.i, %then.1.i, %endif.0.i, %invoke_cont.9.i, %invoke_cont.8.i, %invoke_cont.7.i, %invoke_cont.i.i, %then.0.i, %invoke_cont.4.i, %invoke_cont.3.i, %invoke_cont.2.i, %invoke_cont.1.i, %endif.0.i.i, %tmp.7.i.noexc.i, %invoke_cont.0.i, %entry + %exn0.i = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup ret void invoke_cont.0.i: ; preds = %entry @@ -164,6 +168,8 @@ tmp.0.i.noexc.i: ; preds = %then.0.i to label %invoke_cont.i.i unwind label %cond_true.i.i cond_true.i.i: ; preds = %tmp.0.i.noexc.i + %exn.i.i = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup ret void invoke_cont.i.i: ; preds = %tmp.0.i.noexc.i @@ -256,6 +262,8 @@ tmp.0.i.noexc55.i: ; preds = %no_exit.i to label %invoke_cont.i53.i unwind label %cond_true.i52.i cond_true.i52.i: ; preds = %tmp.0.i.noexc55.i + %exn.i52.i = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup ret void invoke_cont.i53.i: ; preds = %tmp.0.i.noexc55.i diff --git a/test/Transforms/IndVarSimplify/2005-02-11-InvokeCrash.ll b/test/Transforms/IndVarSimplify/2005-02-11-InvokeCrash.ll index aee67ccacc5f4..a5706ca6198eb 100644 --- a/test/Transforms/IndVarSimplify/2005-02-11-InvokeCrash.ll +++ b/test/Transforms/IndVarSimplify/2005-02-11-InvokeCrash.ll @@ -5,9 +5,6 @@ entry: %tmp.7 = invoke i32 @_ZN5ArrayISt7complexIdEE8get_sizeERK10dim_vector( ) to label %invoke_cont.0 unwind label %cond_true.1 ; <i32> [#uses=2] -cond_true.1: ; preds = %entry - unwind - invoke_cont.0: ; preds = %entry %tmp.4.i = bitcast i32 %tmp.7 to i32 ; <i32> [#uses=0] %tmp.14.0.i5 = add i32 %tmp.7, -1 ; <i32> [#uses=1] @@ -17,7 +14,14 @@ no_exit.i: ; preds = %no_exit.i, %invoke_cont.0 %tmp.14.0.i.0 = phi i32 [ %tmp.14.0.i, %no_exit.i ], [ %tmp.14.0.i5, %invoke_cont.0 ] ; <i32> [#uses=1] %tmp.14.0.i = add i32 %tmp.14.0.i.0, -1 ; <i32> [#uses=1] br label %no_exit.i + +cond_true.1: ; preds = %entry + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup + resume { i8*, i32 } %exn } +declare i32 @__gxx_personality_v0(...) + declare i32 @_ZN5ArrayISt7complexIdEE8get_sizeERK10dim_vector() diff --git a/test/Transforms/IndVarSimplify/2005-02-17-TruncateExprCrash.ll b/test/Transforms/IndVarSimplify/2005-02-17-TruncateExprCrash.ll index 70a7a9de05f08..ce043beb7fd95 100644 --- a/test/Transforms/IndVarSimplify/2005-02-17-TruncateExprCrash.ll +++ b/test/Transforms/IndVarSimplify/2005-02-17-TruncateExprCrash.ll @@ -10,6 +10,8 @@ entry: to label %endif.1 unwind label %then.i.i551 then.i.i551: ; preds = %entry + %exn551 = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup ret void endif.1: ; preds = %entry @@ -20,6 +22,8 @@ then.2: ; preds = %endif.1 to label %loopentry.0 unwind label %invoke_catch.6 invoke_catch.6: ; preds = %then.2 + %exn6 = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup ret void loopentry.0: ; preds = %then.2 @@ -59,3 +63,5 @@ loopexit.1: ; preds = %no_exit.0, %endif.4 then.i.i: ; preds = %endif.1 ret void } + +declare i32 @__gxx_personality_v0(...) diff --git a/test/Transforms/IndVarSimplify/2009-04-14-shorten_iv_vars.ll b/test/Transforms/IndVarSimplify/2009-04-14-shorten_iv_vars.ll index 0f6267bd17991..dd400beaa5fa7 100644 --- a/test/Transforms/IndVarSimplify/2009-04-14-shorten_iv_vars.ll +++ b/test/Transforms/IndVarSimplify/2009-04-14-shorten_iv_vars.ll @@ -1,6 +1,6 @@ ; RUN: opt < %s -indvars -S | not grep {sext} ; ModuleID = '<stdin>' -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-n:32:64" +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-n32:64" target triple = "x86_64-apple-darwin9.6" @a = external global i32* ; <i32**> [#uses=3] @b = external global i32* ; <i32**> [#uses=3] diff --git a/test/Transforms/IndVarSimplify/2009-04-15-shorten-iv-vars-2.ll b/test/Transforms/IndVarSimplify/2009-04-15-shorten-iv-vars-2.ll index 46d6b380f0000..55e8a5073cf19 100644 --- a/test/Transforms/IndVarSimplify/2009-04-15-shorten-iv-vars-2.ll +++ b/test/Transforms/IndVarSimplify/2009-04-15-shorten-iv-vars-2.ll @@ -13,7 +13,7 @@ ; d[(i+2)&15] = e[(i+2)&15]+f[(i+2)&15]+K[i+2]; ; } ;} -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-n:32:64" +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-n32:64" target triple = "x86_64-apple-darwin9.6" @a = external global i32* ; <i32**> [#uses=3] @b = external global i32* ; <i32**> [#uses=3] diff --git a/test/Transforms/IndVarSimplify/2011-09-10-widen-nsw.ll b/test/Transforms/IndVarSimplify/2011-09-10-widen-nsw.ll new file mode 100644 index 0000000000000..77354f75106ac --- /dev/null +++ b/test/Transforms/IndVarSimplify/2011-09-10-widen-nsw.ll @@ -0,0 +1,30 @@ +; RUN: opt < %s -indvars -enable-iv-rewrite=false -S | FileCheck %s +; Test WidenIV::GetExtendedOperandRecurrence. +; add219 should be extended to i64 because it is nsw, even though its +; sext cannot be hoisted outside the loop. + +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 void @test() nounwind { +entry: + br i1 undef, label %for.body11, label %for.end285 + +for.body11: ; preds = %entry + %shl = shl i32 1, 1 + %shl132 = shl i32 %shl, 1 + br label %for.body153 + +for.body153: ; preds = %for.body153, %for.body11 + br i1 undef, label %for.body170, label %for.body153 + +; CHECK: add nsw i64 %indvars.iv, 1 +for.body170: ; preds = %for.body170, %for.body153 + %i2.19 = phi i32 [ %add249, %for.body170 ], [ undef, %for.body153 ] + %add219 = add nsw i32 %i2.19, 1 + %idxprom220 = sext i32 %add219 to i64 + %add249 = add nsw i32 %i2.19, %shl132 + br label %for.body170 + +for.end285: ; preds = %entry + ret void +} diff --git a/test/Transforms/IndVarSimplify/2011-09-19-vectoriv.ll b/test/Transforms/IndVarSimplify/2011-09-19-vectoriv.ll new file mode 100644 index 0000000000000..6a01012fe22ff --- /dev/null +++ b/test/Transforms/IndVarSimplify/2011-09-19-vectoriv.ll @@ -0,0 +1,16 @@ +; RUN: opt < %s -indvars -S | FileCheck %s +; PR10946: Vector IVs are not SCEVable. +; CHECK-NOT: phi +define void @test() nounwind { +allocas: + br i1 undef, label %cif_done, label %for_loop398 + +cif_done: ; preds = %allocas + ret void + +for_loop398: ; preds = %for_loop398, %allocas + %storemerge35 = phi <4 x i32> [ %storemerge, %for_loop398 ], [ undef, %allocas ] + %bincmp431 = icmp sge <4 x i32> %storemerge35, <i32 5, i32 5, i32 5, i32 5> + %storemerge = bitcast <4 x float> undef to <4 x i32> + br label %for_loop398 +} diff --git a/test/Transforms/IndVarSimplify/2011-09-27-hoistsext.ll b/test/Transforms/IndVarSimplify/2011-09-27-hoistsext.ll new file mode 100644 index 0000000000000..0737489aad5b5 --- /dev/null +++ b/test/Transforms/IndVarSimplify/2011-09-27-hoistsext.ll @@ -0,0 +1,28 @@ +; RUN: opt < %s -indvars -S | FileCheck %s +; Test indvars' ability to hoist new sext created by WidenIV. +; From ffbench. + +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 internal double @fourn(double* %data, i32 %x, i32 %y, i32 %n) nounwind { +; CHECK: entry: +; CHECK: sext +; CHECK: sext +entry: + br label %for.body + +; CHECK: for.body: +; CHECK-NOT: sext +; CHECK: br +for.body: + %i2.115 = phi i32 [ 0, %entry ], [ %add249, %for.body ] + %add174 = add nsw i32 %i2.115, %x + %idxprom177 = sext i32 %add174 to i64 + %arrayidx179 = getelementptr inbounds double* %data, i64 %idxprom177 + %tmp180 = load double* %arrayidx179, align 8 + %add249 = add nsw i32 %i2.115, %y + %cmp168 = icmp sgt i32 %add249, %n + br i1 %cmp168, label %exit, label %for.body + +exit: + ret double %tmp180 +} diff --git a/test/Transforms/IndVarSimplify/ada-loops.ll b/test/Transforms/IndVarSimplify/ada-loops.ll index 9e635fdc0067b..154de6fea4b6e 100644 --- a/test/Transforms/IndVarSimplify/ada-loops.ll +++ b/test/Transforms/IndVarSimplify/ada-loops.ll @@ -1,5 +1,5 @@ ; RUN: opt < %s -indvars -S | FileCheck %s -; RUN: opt < %s -indvars -disable-iv-rewrite -S | FileCheck %s +; RUN: opt < %s -indvars -enable-iv-rewrite=false -S | FileCheck %s ; ; PR1301 @@ -9,13 +9,12 @@ ; Note that all four functions should actually be converted to ; memset. However, this test case validates indvars behavior. We ; don't check that phis are "folded together" because that is a job -; for loop strength reduction. But indvars must remove sext, zext, -; trunc, and add i8. +; for loop strength reduction. But indvars must remove sext, zext, and add i8. ; -; CHECK-NOT: {{sext|zext|trunc|add i8}} +; CHECK-NOT: {{sext|zext|add i8}} ; ModuleID = 'ada.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-n:8:16:32" +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-n8:16:32" target triple = "i686-pc-linux-gnu" define void @kinds__sbytezero([256 x i32]* nocapture %a) nounwind { diff --git a/test/Transforms/IndVarSimplify/addrec-gep.ll b/test/Transforms/IndVarSimplify/addrec-gep.ll index 58cba6057045d..b62d093960c32 100644 --- a/test/Transforms/IndVarSimplify/addrec-gep.ll +++ b/test/Transforms/IndVarSimplify/addrec-gep.ll @@ -1,15 +1,15 @@ -; RUN: opt < %s -indvars -S > %t -; RUN: grep getelementptr %t | count 1 -; RUN: grep {mul .*, 37} %t | count 1 -; RUN: grep {add .*, 5203} %t | count 1 -; RUN: not grep cast %t +; RUN: opt < %s -indvars -S -enable-iv-rewrite | FileCheck %s +; CHECK: getelementptr +; CHECK: mul {{.*}}, 37 +; CHECK: add {{.*}}, 5203 +; CHECK-NOT: cast ; This test tests several things. The load and store should use the ; same address instead of having it computed twice, and SCEVExpander should ; be able to reconstruct the full getelementptr, despite it having a few ; obstacles set in its way. -target datalayout = "e-p:64:64:64-n:32:64" +target datalayout = "e-p:64:64:64-n32:64" define void @foo(i64 %n, i64 %m, i64 %o, i64 %q, double* nocapture %p) nounwind { entry: diff --git a/test/Transforms/IndVarSimplify/ashr-tripcount.ll b/test/Transforms/IndVarSimplify/ashr-tripcount.ll index 09d559fe51149..b47c8ad471841 100644 --- a/test/Transforms/IndVarSimplify/ashr-tripcount.ll +++ b/test/Transforms/IndVarSimplify/ashr-tripcount.ll @@ -4,7 +4,7 @@ ; Indvars should be able to eliminate all of the sign extensions ; inside the loop. -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-n:32:64" +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-n32:64" @pow_2_tab = external constant [0 x float] ; <[0 x float]*> [#uses=1] @pow_2_025_tab = external constant [0 x float] ; <[0 x float]*> [#uses=1] @i_pow_2_tab = external constant [0 x float] ; <[0 x float]*> [#uses=1] diff --git a/test/Transforms/IndVarSimplify/complex-scev.ll b/test/Transforms/IndVarSimplify/complex-scev.ll index 434c4ec995251..395377e3a48eb 100644 --- a/test/Transforms/IndVarSimplify/complex-scev.ll +++ b/test/Transforms/IndVarSimplify/complex-scev.ll @@ -1,7 +1,9 @@ ; The i induction variable looks like a wrap-around, but it really is just ; a simple affine IV. Make sure that indvars eliminates it. -; RUN: opt < %s -indvars -S | grep phi | count 1 +; RUN: opt < %s -indvars -S -enable-iv-rewrite | FileCheck %s +; CHECK: phi +; CHECK-NOT: phi define void @foo() { entry: diff --git a/test/Transforms/IndVarSimplify/crash.ll b/test/Transforms/IndVarSimplify/crash.ll index 516fd8084d9e9..3335be781dfc6 100644 --- a/test/Transforms/IndVarSimplify/crash.ll +++ b/test/Transforms/IndVarSimplify/crash.ll @@ -53,3 +53,37 @@ bb30: ; preds = %bb29 %2 = add nsw i32 %r.0, 1 ; <i32> [#uses=1] br label %bb24 } + +; PR10770 + +declare void @__go_panic() noreturn + +declare void @__go_undefer() + +declare i32 @__gccgo_personality_v0(i32, i64, i8*, i8*) + +define void @main.main() uwtable { +entry: + invoke void @__go_panic() noreturn + to label %0 unwind label %"5.i" + +; <label>:0 ; preds = %entry + unreachable + +"3.i": ; preds = %"7.i", %"5.i" + invoke void @__go_undefer() + to label %main.f.exit unwind label %"7.i" + +"5.i": ; preds = %entry + %1 = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @__gccgo_personality_v0 + catch i8* null + br label %"3.i" + +"7.i": ; preds = %"3.i" + %2 = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @__gccgo_personality_v0 + catch i8* null + br label %"3.i" + +main.f.exit: ; preds = %"3.i" + unreachable +} diff --git a/test/Transforms/IndVarSimplify/elim-extend.ll b/test/Transforms/IndVarSimplify/elim-extend.ll index 0367e117e677d..43c162fed7f1c 100644 --- a/test/Transforms/IndVarSimplify/elim-extend.ll +++ b/test/Transforms/IndVarSimplify/elim-extend.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -indvars -disable-iv-rewrite -S | FileCheck %s +; RUN: opt < %s -indvars -enable-iv-rewrite=false -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" diff --git a/test/Transforms/IndVarSimplify/floating-point-iv.ll b/test/Transforms/IndVarSimplify/floating-point-iv.ll index 8f4b87048a4d3..266eebd5bb656 100644 --- a/test/Transforms/IndVarSimplify/floating-point-iv.ll +++ b/test/Transforms/IndVarSimplify/floating-point-iv.ll @@ -67,7 +67,8 @@ bb: ; preds = %bb, %entry return: ret void ; CHECK: @test4 -; CHECK: fcmp +; CHECK-NOT: cmp +; CHECK: br i1 false } ; PR6761 @@ -84,9 +85,8 @@ define void @test5() nounwind { exit: ret void - + ; CHECK: @test5 -; CHECK: icmp eq i32 {{.*}}, 10 +; CHECK: icmp slt i32 {{.*}}, 0 ; CHECK-NEXT: br i1 } - diff --git a/test/Transforms/IndVarSimplify/gep-with-mul-base.ll b/test/Transforms/IndVarSimplify/gep-with-mul-base.ll index 19d54ff2a22fd..7e1e2a31768c6 100644 --- a/test/Transforms/IndVarSimplify/gep-with-mul-base.ll +++ b/test/Transforms/IndVarSimplify/gep-with-mul-base.ll @@ -1,7 +1,16 @@ -; RUN: opt < %s -indvars -S > %t -; RUN: grep add %t | count 6 -; RUN: grep sub %t | count 2 -; RUN: grep mul %t | count 6 +; RUN: opt < %s -indvars -S -enable-iv-rewrite | FileCheck %s +; CHECK: define void @foo +; CHECK: mul +; CHECK: mul +; CHECK: mul +; CHECK: add +; CHECK: sub +; CHECK: define void @bar +; CHECK: mul +; CHECK: mul +; CHECK: mul +; CHECK: add +; CHECK: sub define void @foo(i64 %n, i64 %m, i64 %o, double* nocapture %p) nounwind { entry: diff --git a/test/Transforms/IndVarSimplify/interesting-invoke-use.ll b/test/Transforms/IndVarSimplify/interesting-invoke-use.ll index 8adc0e5257777..69bea6eaaed4d 100644 --- a/test/Transforms/IndVarSimplify/interesting-invoke-use.ll +++ b/test/Transforms/IndVarSimplify/interesting-invoke-use.ll @@ -47,9 +47,13 @@ bb178: ; preds = %invcont127 br label %bb123 lpad266: ; preds = %invcont129, %bb128, %bb123 + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup unreachable } +declare i32 @__gxx_personality_v0(...) + declare void @system__img_int__image_integer(%struct.string___XUP* noalias sret, i32) declare void @system__string_ops__str_concat(%struct.string___XUP* noalias sret, [0 x i8]*, %struct.string___XUB*, [0 x i8]*, %struct.string___XUB*) diff --git a/test/Transforms/IndVarSimplify/iv-fold.ll b/test/Transforms/IndVarSimplify/iv-fold.ll new file mode 100644 index 0000000000000..2e191184225c0 --- /dev/null +++ b/test/Transforms/IndVarSimplify/iv-fold.ll @@ -0,0 +1,56 @@ +; RUN: opt < %s -indvars -enable-iv-rewrite=false -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-n32:64" + +; Indvars should be able to fold IV increments into shr when low bits are zero. +; +; CHECK: @foldIncShr +; CHECK: shr.1 = lshr i32 %0, 5 +define i32 @foldIncShr(i32* %bitmap, i32 %bit_addr, i32 %nbits) nounwind { +entry: + br label %while.body + +while.body: + %0 = phi i32 [ 0, %entry ], [ %inc.2, %while.body ] + %shr = lshr i32 %0, 5 + %arrayidx = getelementptr inbounds i32* %bitmap, i32 %shr + %tmp6 = load i32* %arrayidx, align 4 + %inc.1 = add i32 %0, 1 + %shr.1 = lshr i32 %inc.1, 5 + %arrayidx.1 = getelementptr inbounds i32* %bitmap, i32 %shr.1 + %tmp6.1 = load i32* %arrayidx.1, align 4 + %inc.2 = add i32 %inc.1, 1 + %exitcond.3 = icmp eq i32 %inc.2, 128 + br i1 %exitcond.3, label %while.end, label %while.body + +while.end: + %r = add i32 %tmp6, %tmp6.1 + ret i32 %r +} + +; Invdars should not fold an increment into shr unless 2^shiftBits is +; a multiple of the recurrence step. +; +; CHECK: @noFoldIncShr +; CHECK: shr.1 = lshr i32 %inc.1, 5 +define i32 @noFoldIncShr(i32* %bitmap, i32 %bit_addr, i32 %nbits) nounwind { +entry: + br label %while.body + +while.body: + %0 = phi i32 [ 0, %entry ], [ %inc.3, %while.body ] + %shr = lshr i32 %0, 5 + %arrayidx = getelementptr inbounds i32* %bitmap, i32 %shr + %tmp6 = load i32* %arrayidx, align 4 + %inc.1 = add i32 %0, 1 + %shr.1 = lshr i32 %inc.1, 5 + %arrayidx.1 = getelementptr inbounds i32* %bitmap, i32 %shr.1 + %tmp6.1 = load i32* %arrayidx.1, align 4 + %inc.3 = add i32 %inc.1, 2 + %exitcond.3 = icmp eq i32 %inc.3, 96 + br i1 %exitcond.3, label %while.end, label %while.body + +while.end: + %r = add i32 %tmp6, %tmp6.1 + ret i32 %r +} diff --git a/test/Transforms/IndVarSimplify/iv-sext.ll b/test/Transforms/IndVarSimplify/iv-sext.ll index 6c7a6279ab3f8..04df0f9aa5fa0 100644 --- a/test/Transforms/IndVarSimplify/iv-sext.ll +++ b/test/Transforms/IndVarSimplify/iv-sext.ll @@ -4,7 +4,7 @@ ; inner loop to i64. ; TODO: it should promote hiPart to i64 in the outer loop too. -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-n:32:64" +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-n32:64" define void @t(float* %pTmp1, float* %peakWeight, float* %nrgReducePeakrate, i32 %bandEdgeIndex, float %tmp1) nounwind { entry: diff --git a/test/Transforms/IndVarSimplify/iv-zext.ll b/test/Transforms/IndVarSimplify/iv-zext.ll index 3a05c893fb49e..646e6c00ce6f3 100644 --- a/test/Transforms/IndVarSimplify/iv-zext.ll +++ b/test/Transforms/IndVarSimplify/iv-zext.ll @@ -1,9 +1,9 @@ ; RUN: opt < %s -indvars -S | FileCheck %s -; RUN: opt < %s -indvars -disable-iv-rewrite -S | FileCheck %s +; RUN: opt < %s -indvars -enable-iv-rewrite=false -S | FileCheck %s ; CHECK-NOT: and ; CHECK-NOT: zext -target datalayout = "-p:64:64:64-n:32:64" +target datalayout = "-p:64:64:64-n32:64" define void @foo(double* %d, i64 %n) nounwind { entry: diff --git a/test/Transforms/IndVarSimplify/lftr-reuse.ll b/test/Transforms/IndVarSimplify/lftr-reuse.ll new file mode 100644 index 0000000000000..490eee9c221d2 --- /dev/null +++ b/test/Transforms/IndVarSimplify/lftr-reuse.ll @@ -0,0 +1,230 @@ +; RUN: opt < %s -indvars -enable-iv-rewrite=false -S | FileCheck %s +; +; Make sure that indvars can perform LFTR without a canonical IV. + +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" + +; Perform LFTR using the original pointer-type IV. + +; for(char* p = base; p < base + n; ++p) { +; *p = p-base; +; } +define void @ptriv(i8* %base, i32 %n) nounwind { +entry: + %idx.ext = sext i32 %n to i64 + %add.ptr = getelementptr inbounds i8* %base, i64 %idx.ext + %cmp1 = icmp ult i8* %base, %add.ptr + br i1 %cmp1, label %for.body, label %for.end + +; CHECK: for.body: +; CHECK: phi i8* +; CHECK-NOT: phi +; CHECK-NOT: add +; CHECK: icmp ne i8* +; CHECK: br i1 +for.body: + %p.02 = phi i8* [ %base, %entry ], [ %incdec.ptr, %for.body ] + ; cruft to make the IV useful + %sub.ptr.lhs.cast = ptrtoint i8* %p.02 to i64 + %sub.ptr.rhs.cast = ptrtoint i8* %base to i64 + %sub.ptr.sub = sub i64 %sub.ptr.lhs.cast, %sub.ptr.rhs.cast + %conv = trunc i64 %sub.ptr.sub to i8 + store i8 %conv, i8* %p.02 + %incdec.ptr = getelementptr inbounds i8* %p.02, i32 1 + %cmp = icmp ult i8* %incdec.ptr, %add.ptr + br i1 %cmp, label %for.body, label %for.end + +for.end: + ret void +} + +; It would be nice if SCEV and any loop analysis could assume that +; preheaders exist. Unfortunately it is not always the case. This test +; checks that SCEVExpander can handle an outer loop that has not yet +; been simplified. As a result, the inner loop's exit test will not be +; rewritten. +define void @expandOuterRecurrence(i32 %arg) nounwind { +entry: + %sub1 = sub nsw i32 %arg, 1 + %cmp1 = icmp slt i32 0, %sub1 + br i1 %cmp1, label %outer, label %exit + +outer: + %i = phi i32 [ 0, %entry ], [ %i.inc, %outer.inc ] + %sub2 = sub nsw i32 %arg, %i + %sub3 = sub nsw i32 %sub2, 1 + %cmp2 = icmp slt i32 0, %sub3 + br i1 %cmp2, label %inner.ph, label %outer.inc + +inner.ph: + br label %inner + +; CHECK: inner: +; CHECK: icmp slt +; CHECK: br i1 +inner: + %j = phi i32 [ 0, %inner.ph ], [ %j.inc, %inner ] + %j.inc = add nsw i32 %j, 1 + %cmp3 = icmp slt i32 %j.inc, %sub3 + br i1 %cmp3, label %inner, label %outer.inc + +; CHECK: outer.inc: +; CHECK: icmp ne +; CHECK: br i1 +outer.inc: + %i.inc = add nsw i32 %i, 1 + %cmp4 = icmp slt i32 %i.inc, %sub1 + br i1 %cmp4, label %outer, label %exit + +exit: + ret void +} + +; Force SCEVExpander to look for an existing well-formed phi. +; Perform LFTR without generating extra preheader code. +define void @guardedloop([0 x double]* %matrix, [0 x double]* %vector, + i32 %irow, i32 %ilead) nounwind { +; CHECK: entry: +; CHECK-NOT: zext +; CHECK-NOT: add +; CHECK: loop: +; CHECK: phi i64 +; CHECK: phi i64 +; CHECK-NOT: phi +; CHECK: icmp ne +; CHECK: br i1 +entry: + %cmp = icmp slt i32 1, %irow + br i1 %cmp, label %loop, label %return + +loop: + %rowidx = phi i32 [ 0, %entry ], [ %row.inc, %loop ] + %i = phi i32 [ 0, %entry ], [ %i.inc, %loop ] + %diagidx = add nsw i32 %rowidx, %i + %diagidxw = sext i32 %diagidx to i64 + %matrixp = getelementptr inbounds [0 x double]* %matrix, i32 0, i64 %diagidxw + %v1 = load double* %matrixp + %iw = sext i32 %i to i64 + %vectorp = getelementptr inbounds [0 x double]* %vector, i32 0, i64 %iw + %v2 = load double* %vectorp + %row.inc = add nsw i32 %rowidx, %ilead + %i.inc = add nsw i32 %i, 1 + %cmp196 = icmp slt i32 %i.inc, %irow + br i1 %cmp196, label %loop, label %return + +return: + ret void +} + +; Avoid generating extra code to materialize a trip count. Skip LFTR. +define void @unguardedloop([0 x double]* %matrix, [0 x double]* %vector, + i32 %irow, i32 %ilead) nounwind { +entry: + br label %loop + +; CHECK: entry: +; CHECK-NOT: zext +; CHECK-NOT: add +; CHECK: loop: +; CHECK: phi i64 +; CHECK: phi i64 +; CHECK-NOT: phi +; CHECK: icmp slt +; CHECK: br i1 +loop: + %rowidx = phi i32 [ 0, %entry ], [ %row.inc, %loop ] + %i = phi i32 [ 0, %entry ], [ %i.inc, %loop ] + %diagidx = add nsw i32 %rowidx, %i + %diagidxw = sext i32 %diagidx to i64 + %matrixp = getelementptr inbounds [0 x double]* %matrix, i32 0, i64 %diagidxw + %v1 = load double* %matrixp + %iw = sext i32 %i to i64 + %vectorp = getelementptr inbounds [0 x double]* %vector, i32 0, i64 %iw + %v2 = load double* %vectorp + %row.inc = add nsw i32 %rowidx, %ilead + %i.inc = add nsw i32 %i, 1 + %cmp196 = icmp slt i32 %i.inc, %irow + br i1 %cmp196, label %loop, label %return + +return: + ret void +} + +; Remove %i which is only used by the exit test. +; Verify that SCEV can still compute a backedge count from the sign +; extended %n, used for pointer comparison by LFTR. +define void @geplftr(i8* %base, i32 %x, i32 %y, i32 %n) nounwind { +entry: + %x.ext = sext i32 %x to i64 + %add.ptr = getelementptr inbounds i8* %base, i64 %x.ext + %y.ext = sext i32 %y to i64 + %add.ptr10 = getelementptr inbounds i8* %add.ptr, i64 %y.ext + %lim = add i32 %x, %n + %cmp.ph = icmp ult i32 %x, %lim + br i1 %cmp.ph, label %loop, label %exit + +; CHECK: loop: +; CHECK: phi i8* +; CHECK-NOT: phi +; CHECK: getelementptr +; CHECK: store +; CHECK: icmp ne i8* +; CHECK: br i1 +loop: + %i = phi i32 [ %x, %entry ], [ %inc, %loop ] + %aptr = phi i8* [ %add.ptr10, %entry ], [ %incdec.ptr, %loop ] + %incdec.ptr = getelementptr inbounds i8* %aptr, i32 1 + store i8 3, i8* %aptr + %inc = add i32 %i, 1 + %cmp = icmp ult i32 %inc, %lim + br i1 %cmp, label %loop, label %exit + +exit: + ret void +} + +; Exercise backedge taken count verification with a never-taken loop. +define void @nevertaken() nounwind uwtable ssp { +entry: + br label %loop + +; CHECK: loop: +; CHECK-NOT: phi +; CHECK-NOT: add +; CHECK-NOT: icmp +; CHECK: exit: +loop: + %i = phi i32 [ 0, %entry ], [ %inc, %loop ] + %inc = add nsw i32 %i, 1 + %cmp = icmp sle i32 %inc, 0 + br i1 %cmp, label %loop, label %exit + +exit: + ret void +} + +; Test LFTR on an IV whose recurrence start is a non-unit pointer type. +define void @aryptriv([256 x i8]* %base, i32 %n) nounwind { +entry: + %ivstart = getelementptr inbounds [256 x i8]* %base, i32 0, i32 0 + %ivend = getelementptr inbounds [256 x i8]* %base, i32 0, i32 %n + %cmp.ph = icmp ult i8* %ivstart, %ivend + br i1 %cmp.ph, label %loop, label %exit + +; CHECK: loop: +; CHECK: phi i8* +; CHECK-NOT: phi +; CHECK: getelementptr +; CHECK: store +; CHECK: icmp ne i8* +; CHECK: br i1 +loop: + %aptr = phi i8* [ %ivstart, %entry ], [ %incdec.ptr, %loop ] + %incdec.ptr = getelementptr inbounds i8* %aptr, i32 1 + store i8 3, i8* %aptr + %cmp = icmp ult i8* %incdec.ptr, %ivend + br i1 %cmp, label %loop, label %exit + +exit: + ret void +} diff --git a/test/Transforms/IndVarSimplify/max-pointer.ll b/test/Transforms/IndVarSimplify/max-pointer.ll deleted file mode 100644 index 46ac2d89b5043..0000000000000 --- a/test/Transforms/IndVarSimplify/max-pointer.ll +++ /dev/null @@ -1,39 +0,0 @@ -; RUN: opt < %s -indvars -S > %t -; RUN: grep {icmp ugt i8\\\*} %t | count 1 -; RUN: grep {icmp sgt i8\\\*} %t | 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-n:32:64" - - %struct.CKenCodeCodec = type <{ i8 }> - -define void @foo(i8* %str1Ptr, i8* %str2Ptr, i8* %inLastBytePtr) nounwind { -entry: - %0 = icmp ult i8* %str2Ptr, %str1Ptr ; <i1> [#uses=1] - %str2Ptr_addr.0 = select i1 %0, i8* %str1Ptr, i8* %str2Ptr ; <i8*> [#uses=1] - br label %bb2 - -bb2: ; preds = %bb2, %entry - %str2Ptr_addr.1 = phi i8* [ %str2Ptr_addr.0, %entry ], [ %1, %bb2 ] ; <i8*> [#uses=1] - %1 = getelementptr i8* %str2Ptr_addr.1, i64 1 ; <i8*> [#uses=2] - %2 = icmp ult i8* %1, %inLastBytePtr ; <i1> [#uses=0] - br i1 undef, label %bb2, label %return - -return: ; preds = %bb2 - ret void -} - -define void @sfoo(i8* %str1Ptr, i8* %str2Ptr, i8* %inLastBytePtr) nounwind { -entry: - %0 = icmp slt i8* %str2Ptr, %str1Ptr ; <i1> [#uses=1] - %str2Ptr_addr.0 = select i1 %0, i8* %str1Ptr, i8* %str2Ptr ; <i8*> [#uses=1] - br label %bb2 - -bb2: ; preds = %bb2, %entry - %str2Ptr_addr.1 = phi i8* [ %str2Ptr_addr.0, %entry ], [ %1, %bb2 ] ; <i8*> [#uses=1] - %1 = getelementptr i8* %str2Ptr_addr.1, i64 1 ; <i8*> [#uses=2] - %2 = icmp slt i8* %1, %inLastBytePtr ; <i1> [#uses=0] - br i1 undef, label %bb2, label %return - -return: ; preds = %bb2 - ret void -} diff --git a/test/Transforms/IndVarSimplify/no-iv-rewrite.ll b/test/Transforms/IndVarSimplify/no-iv-rewrite.ll index 9605670b86e1f..9c2abd0f31c7d 100644 --- a/test/Transforms/IndVarSimplify/no-iv-rewrite.ll +++ b/test/Transforms/IndVarSimplify/no-iv-rewrite.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -indvars -disable-iv-rewrite -S | FileCheck %s +; RUN: opt < %s -indvars -enable-iv-rewrite=false -S | FileCheck %s ; ; Make sure that indvars isn't inserting canonical IVs. ; This is kinda hard to do until linear function test replacement is removed. @@ -125,9 +125,9 @@ return: ret void } -%struct = type { i32 } +%structI = type { i32 } -define void @bitcastiv(i32 %start, i32 %limit, i32 %step, %struct* %base) +define void @bitcastiv(i32 %start, i32 %limit, i32 %step, %structI* %base) nounwind { entry: @@ -142,12 +142,12 @@ entry: ; CHECK: exit: loop: %iv = phi i32 [%start, %entry], [%next, %loop] - %p = phi %struct* [%base, %entry], [%pinc, %loop] - %adr = getelementptr %struct* %p, i32 0, i32 0 + %p = phi %structI* [%base, %entry], [%pinc, %loop] + %adr = getelementptr %structI* %p, i32 0, i32 0 store i32 3, i32* %adr - %pp = bitcast %struct* %p to i32* + %pp = bitcast %structI* %p to i32* store i32 4, i32* %pp - %pinc = getelementptr %struct* %p, i32 1 + %pinc = getelementptr %structI* %p, i32 1 %next = add i32 %iv, 1 %cond = icmp ne i32 %next, %limit br i1 %cond, label %loop, label %exit @@ -281,6 +281,7 @@ return: ; CHECK-NOT: phi ; CHECK: add i32 ; CHECK: add i32 +; CHECK: add i32 ; CHECK-NOT: add ; CHECK: return: ; @@ -320,3 +321,72 @@ return: %sum4 = add i32 %sum1, %l.next ret i32 %sum4 } + +; Test a GEP IV that is derived from another GEP IV by a nop gep that +; lowers the type without changing the expression. +%structIF = type { i32, float } + +define void @congruentgepiv(%structIF* %base) nounwind uwtable ssp { +entry: + %first = getelementptr inbounds %structIF* %base, i64 0, i32 0 + br label %loop + +; CHECK: loop: +; CHECK: phi %structIF* +; CHECK: phi i32* +; CHECK: getelementptr inbounds +; CHECK: getelementptr inbounds +; CHECK: exit: +loop: + %ptr.iv = phi %structIF* [ %ptr.inc, %latch ], [ %base, %entry ] + %next = phi i32* [ %next.inc, %latch ], [ %first, %entry ] + store i32 4, i32* %next + br i1 undef, label %latch, label %exit + +latch: ; preds = %for.inc50.i + %ptr.inc = getelementptr inbounds %structIF* %ptr.iv, i64 1 + %next.inc = getelementptr inbounds %structIF* %ptr.inc, i64 0, i32 0 + br label %loop + +exit: + ret void +} + +; Test a widened IV that is used by a phi on different paths within the loop. +; +; CHECK: for.body: +; CHECK: phi i64 +; CHECK: trunc i64 +; CHECK: if.then: +; CHECK: for.inc: +; CHECK: phi i32 +; CHECK: for.end: +define void @phiUsesTrunc() nounwind { +entry: + br i1 undef, label %for.body, label %for.end + +for.body: + %iv = phi i32 [ %inc, %for.inc ], [ 1, %entry ] + br i1 undef, label %if.then, label %if.else + +if.then: + br i1 undef, label %if.then33, label %for.inc + +if.then33: + br label %for.inc + +if.else: + br i1 undef, label %if.then97, label %for.inc + +if.then97: + %idxprom100 = sext i32 %iv to i64 + br label %for.inc + +for.inc: + %kmin.1 = phi i32 [ %iv, %if.then33 ], [ 0, %if.then ], [ %iv, %if.then97 ], [ 0, %if.else ] + %inc = add nsw i32 %iv, 1 + br i1 undef, label %for.body, label %for.end + +for.end: + ret void +} diff --git a/test/Transforms/IndVarSimplify/pointer-indvars.ll b/test/Transforms/IndVarSimplify/pointer-indvars.ll deleted file mode 100644 index 6d25f90542ca1..0000000000000 --- a/test/Transforms/IndVarSimplify/pointer-indvars.ll +++ /dev/null @@ -1,15 +0,0 @@ -; RUN: opt < %s -indvars -S | grep indvar -@G = global i32* null ; <i32**> [#uses=1] -@Array = external global [40 x i32] ; <[40 x i32]*> [#uses=1] - -define void @test() { -; <label>:0 - br label %Loop - -Loop: ; preds = %Loop, %0 - %X = phi i32* [ getelementptr ([40 x i32]* @Array, i64 0, i64 0), %0 ], [ %X.next, %Loop ] ; <i32*> [#uses=2] - %X.next = getelementptr i32* %X, i64 1 ; <i32*> [#uses=1] - store i32* %X, i32** @G - br label %Loop -} - diff --git a/test/Transforms/IndVarSimplify/pointer.ll b/test/Transforms/IndVarSimplify/pointer.ll deleted file mode 100644 index d55bf98d31362..0000000000000 --- a/test/Transforms/IndVarSimplify/pointer.ll +++ /dev/null @@ -1,38 +0,0 @@ -; RUN: opt < %s -indvars -S > %t -; RUN: grep {%exitcond = icmp eq i64 %indvar.next, %n} %t -; RUN: grep {getelementptr i8\\* %A, i64 %indvar} %t -; RUN: grep getelementptr %t | count 1 -; RUN: grep add %t | count 1 -; RUN: not grep scevgep %t -; RUN: not grep ptrtoint %t - -; Indvars should be able to expand the pointer-arithmetic -; IV into an integer IV indexing into a simple getelementptr. - -target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-n:32:64" - -define void @foo(i8* %A, i64 %n) nounwind { -entry: - %0 = icmp eq i64 %n, 0 ; <i1> [#uses=1] - br i1 %0, label %return, label %bb.nph - -bb.nph: ; preds = %entry - %1 = getelementptr i8* %A, i64 %n ; <i8*> [#uses=1] - br label %bb - -bb: ; preds = %bb1, %bb.nph - %q.01 = phi i8* [ %2, %bb1 ], [ %A, %bb.nph ] ; <i8*> [#uses=2] - store i8 0, i8* %q.01, align 1 - %2 = getelementptr i8* %q.01, i64 1 ; <i8*> [#uses=2] - br label %bb1 - -bb1: ; preds = %bb - %3 = icmp eq i8* %1, %2 ; <i1> [#uses=1] - br i1 %3, label %bb1.return_crit_edge, label %bb - -bb1.return_crit_edge: ; preds = %bb1 - br label %return - -return: ; preds = %bb1.return_crit_edge, %entry - ret void -} diff --git a/test/Transforms/IndVarSimplify/preserve-gep-loop-variant.ll b/test/Transforms/IndVarSimplify/preserve-gep-loop-variant.ll index 26f05c4b1ee91..251d34ec383ad 100644 --- a/test/Transforms/IndVarSimplify/preserve-gep-loop-variant.ll +++ b/test/Transforms/IndVarSimplify/preserve-gep-loop-variant.ll @@ -1,8 +1,8 @@ -; RUN: opt < %s -indvars -S > %t -; RUN: not grep inttoptr %t -; RUN: not grep ptrtoint %t -; RUN: grep scevgep %t -target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128-n:32:64" +; RUN: opt < %s -indvars -S -enable-iv-rewrite | FileCheck %s +; CHECK-NOT: {{inttoptr|ptrtoint}} +; CHECK: scevgep +; CHECK-NOT: {{inttoptr|ptrtoint}} +target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128-n32:64" ; Indvars shouldn't need inttoptr/ptrtoint to expand an address here. diff --git a/test/Transforms/IndVarSimplify/preserve-gep-nested.ll b/test/Transforms/IndVarSimplify/preserve-gep-nested.ll index b41de5828a9dd..cdcaaa0c9254a 100644 --- a/test/Transforms/IndVarSimplify/preserve-gep-nested.ll +++ b/test/Transforms/IndVarSimplify/preserve-gep-nested.ll @@ -1,19 +1,20 @@ -; RUN: opt < %s -indvars -S > %t -; Exactly one getelementptr for each load+store. -; RUN: grep getelementptr %t | count 6 -; Each getelementptr using %struct.Q* %s as a base and not i8*. -; RUN: grep {getelementptr \[%\]struct\\.Q\\* \[%\]s,} %t | count 6 +; RUN: opt < %s -indvars -S -enable-iv-rewrite | FileCheck %s ; No explicit integer multiplications! -; RUN: not grep {= mul} %t ; No i8* arithmetic or pointer casting anywhere! -; RUN: not grep {i8\\*} %t -; RUN: not grep bitcast %t -; RUN: not grep inttoptr %t -; RUN: not grep ptrtoint %t +; CHECK-NOT: = {{= mul|i8\*|bitcast|inttoptr|ptrtoint}} +; Exactly one getelementptr for each load+store. +; Each getelementptr using %struct.Q* %s as a base and not i8*. +; CHECK: getelementptr %struct.Q* %s, +; CHECK: getelementptr %struct.Q* %s, +; CHECK: getelementptr %struct.Q* %s, +; CHECK: getelementptr %struct.Q* %s, +; CHECK: getelementptr %struct.Q* %s, +; CHECK: getelementptr %struct.Q* %s, +; CHECK-NOT: = {{= mul|i8\*|bitcast|inttoptr|ptrtoint}} ; FIXME: This test should pass with or without TargetData. Until opt ; supports running tests without targetdata, just hardware this in. -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-n:32:64" +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-n32:64" %struct.Q = type { [10 x %struct.N] } %struct.N = type { %struct.S } diff --git a/test/Transforms/IndVarSimplify/preserve-gep-remainder.ll b/test/Transforms/IndVarSimplify/preserve-gep-remainder.ll index ca0c399927602..2f3100fcafbdc 100644 --- a/test/Transforms/IndVarSimplify/preserve-gep-remainder.ll +++ b/test/Transforms/IndVarSimplify/preserve-gep-remainder.ll @@ -1,6 +1,6 @@ -; RUN: opt < %s -indvars -S \ -; RUN: | grep {\[%\]p.2.ip.1 = getelementptr \\\[3 x \\\[3 x double\\\]\\\]\\* \[%\]p, i64 2, i64 \[%\]tmp, i64 1} -target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128-n:32:64" +; RUN: opt < %s -indvars -S -enable-iv-rewrite | FileCheck %s +; CHECK: %p.2.ip.1 = getelementptr [3 x [3 x double]]* %p, i64 2, i64 %0, i64 1 +target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128-n32:64" ; Indvars shouldn't expand this to ; %p.2.ip.1 = getelementptr [3 x [3 x double]]* %p, i64 0, i64 %tmp, i64 19 diff --git a/test/Transforms/IndVarSimplify/preserve-gep.ll b/test/Transforms/IndVarSimplify/preserve-gep.ll index 82eda0386e7fd..fec8a28959889 100644 --- a/test/Transforms/IndVarSimplify/preserve-gep.ll +++ b/test/Transforms/IndVarSimplify/preserve-gep.ll @@ -1,12 +1,12 @@ -; RUN: opt < %s -indvars -S > %t -; RUN: not grep ptrtoint %t -; RUN: not grep inttoptr %t -; RUN: grep getelementptr %t | count 1 +; RUN: opt < %s -indvars -S -enable-iv-rewrite | FileCheck %s +; CHECK-NOT: {{ptrtoint|inttoptr}} +; CHECK: getelementptr +; CHECK-NOT: {{ptrtoint|inttoptr|getelementptr}} ; Indvars shouldn't leave getelementptrs expanded out as ; inttoptr+ptrtoint in its output in common cases. -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-n:32:64" +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-n32:64" target triple = "x86_64-unknown-linux-gnu" %struct.Foo = type { i32, i32, [10 x i32], i32 } diff --git a/test/Transforms/IndVarSimplify/preserve-signed-wrap.ll b/test/Transforms/IndVarSimplify/preserve-signed-wrap.ll index 5063b17454422..22e209283b769 100644 --- a/test/Transforms/IndVarSimplify/preserve-signed-wrap.ll +++ b/test/Transforms/IndVarSimplify/preserve-signed-wrap.ll @@ -1,5 +1,5 @@ ; RUN: opt < %s -indvars -S | FileCheck %s -; RUN: opt < %s -indvars -disable-iv-rewrite -S | FileCheck %s +; RUN: opt < %s -indvars -enable-iv-rewrite=false -S | FileCheck %s ; Indvars should insert a 64-bit induction variable to eliminate the ; sext for the addressing, however it shouldn't eliminate the sext diff --git a/test/Transforms/IndVarSimplify/subtract.ll b/test/Transforms/IndVarSimplify/subtract.ll deleted file mode 100644 index f45bdab4be587..0000000000000 --- a/test/Transforms/IndVarSimplify/subtract.ll +++ /dev/null @@ -1,15 +0,0 @@ -; RUN: opt < %s -indvars -S | grep indvar - -@G = global i64 0 ; <i64*> [#uses=1] - -define void @test(i64 %V) { -; <label>:0 - br label %Loop - -Loop: ; preds = %Loop, %0 - %X = phi i64 [ 1, %0 ], [ %X.next, %Loop ] ; <i64> [#uses=2] - %X.next = sub i64 %X, %V ; <i64> [#uses=1] - store i64 %X, i64* @G - br label %Loop -} - diff --git a/test/Transforms/IndVarSimplify/variable-stride-ivs-0.ll b/test/Transforms/IndVarSimplify/variable-stride-ivs-0.ll index ace74ffb8622d..fc906cdcfb152 100644 --- a/test/Transforms/IndVarSimplify/variable-stride-ivs-0.ll +++ b/test/Transforms/IndVarSimplify/variable-stride-ivs-0.ll @@ -1,5 +1,5 @@ ; RUN: opt < %s -indvars -instcombine -S | FileCheck %s -; RUN: opt < %s -indvars -disable-iv-rewrite -instcombine -S | FileCheck %s +; RUN: opt < %s -indvars -enable-iv-rewrite=false -instcombine -S | FileCheck %s ; ; Test that -indvars can reduce variable stride IVs. If it can reduce variable ; stride iv's, it will make %iv. and %m.0.0 isomorphic to each other without diff --git a/test/Transforms/Inline/2003-09-14-InlineValue.ll b/test/Transforms/Inline/2003-09-14-InlineValue.ll index 49a27e195e2a7..98bc08b378e0a 100644 --- a/test/Transforms/Inline/2003-09-14-InlineValue.ll +++ b/test/Transforms/Inline/2003-09-14-InlineValue.ll @@ -16,6 +16,10 @@ Ok: ; preds = %0 ret i32 %V Bad: ; preds = %0 + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup ret i32 0 } +declare i32 @__gxx_personality_v0(...) + diff --git a/test/Transforms/Inline/2003-09-22-PHINodesInExceptionDest.ll b/test/Transforms/Inline/2003-09-22-PHINodesInExceptionDest.ll index 4418f77c9d0b4..9af93325f1422 100644 --- a/test/Transforms/Inline/2003-09-22-PHINodesInExceptionDest.ll +++ b/test/Transforms/Inline/2003-09-22-PHINodesInExceptionDest.ll @@ -6,10 +6,15 @@ entry: to label %Call2Invoke unwind label %LongJmpBlkPre Call2Invoke: ; preds = %entry - br label %LongJmpBlkPre + br label %exit LongJmpBlkPre: ; preds = %Call2Invoke, %entry %i.3 = phi i32 [ 0, %entry ], [ 0, %Call2Invoke ] ; <i32> [#uses=0] + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup + br label %exit + +exit: ret i32 0 } @@ -19,6 +24,8 @@ define void @__main() { ret void } +declare i32 @__gxx_personality_v0(...) + declare void @__llvm_getGlobalCtors() declare void @__llvm_getGlobalDtors() diff --git a/test/Transforms/Inline/2003-10-26-InlineInvokeExceptionDestPhi.ll b/test/Transforms/Inline/2003-10-26-InlineInvokeExceptionDestPhi.ll deleted file mode 100644 index 9afd45040ca97..0000000000000 --- a/test/Transforms/Inline/2003-10-26-InlineInvokeExceptionDestPhi.ll +++ /dev/null @@ -1,20 +0,0 @@ -; The inliner is breaking inlining invoke instructions where there is a PHI -; node in the exception destination, and the inlined function contains an -; unwind instruction. - -; RUN: opt < %s -inline -disable-output - -define linkonce void @foo() { - unwind -} - -define i32 @test() { -BB1: - invoke void @foo( ) - to label %Cont unwind label %Cont - -Cont: ; preds = %BB1, %BB1 - %A = phi i32 [ 0, %BB1 ], [ 0, %BB1 ] ; <i32> [#uses=1] - ret i32 %A -} - diff --git a/test/Transforms/Inline/2004-04-15-InlineDeletesCall.ll b/test/Transforms/Inline/2004-04-15-InlineDeletesCall.ll index 38994519cea45..62a7594ba437b 100644 --- a/test/Transforms/Inline/2004-04-15-InlineDeletesCall.ll +++ b/test/Transforms/Inline/2004-04-15-InlineDeletesCall.ll @@ -5,7 +5,7 @@ ; exists. define internal void @Callee1() { - unwind + unreachable } define void @Callee2() { diff --git a/test/Transforms/Inline/2004-10-17-InlineFunctionWithoutReturn.ll b/test/Transforms/Inline/2004-10-17-InlineFunctionWithoutReturn.ll index 733cbb9c754f4..866327f64a8f2 100644 --- a/test/Transforms/Inline/2004-10-17-InlineFunctionWithoutReturn.ll +++ b/test/Transforms/Inline/2004-10-17-InlineFunctionWithoutReturn.ll @@ -1,7 +1,7 @@ ; RUN: opt < %s -inline -disable-output define i32 @test() { - unwind + unreachable } define i32 @caller() { diff --git a/test/Transforms/Inline/2006-11-09-InlineCGUpdate-2.ll b/test/Transforms/Inline/2006-11-09-InlineCGUpdate-2.ll index 37cba9801caa4..b4380d01e483f 100644 --- a/test/Transforms/Inline/2006-11-09-InlineCGUpdate-2.ll +++ b/test/Transforms/Inline/2006-11-09-InlineCGUpdate-2.ll @@ -114,7 +114,7 @@ entry: define fastcc void @_ZSt19__throw_ios_failurePKc() { entry: call fastcc void @_ZNSsC1EPKcRKSaIcE( ) - unwind + unreachable } define void @_GLOBAL__D__ZSt23lexicographical_compareIPKaS1_EbT_S2_T0_S3_() { @@ -133,10 +133,12 @@ entry: to label %try_exit.0 unwind label %try_catch.0 try_catch.0: ; preds = %entry - unreachable + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + catch i8* null + resume { i8*, i32 } %exn try_exit.0: ; preds = %entry - unwind + unreachable } define fastcc void @_ZNSt11logic_errorC1ERKSs() { @@ -153,7 +155,7 @@ entry: define fastcc void @_ZSt20__throw_length_errorPKc() { entry: call fastcc void @_ZNSt12length_errorC1ERKSs( ) - unwind + unreachable } define fastcc void @_ZNSt12length_errorC1ERKSs() { @@ -162,7 +164,9 @@ entry: to label %_ZNSt11logic_errorC2ERKSs.exit unwind label %invoke_catch.i invoke_catch.i: ; preds = %entry - unwind + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + catch i8* null + resume { i8*, i32 } %exn _ZNSt11logic_errorC2ERKSs.exit: ; preds = %entry ret void @@ -199,8 +203,10 @@ entry: to label %invoke_cont.1 unwind label %invoke_catch.1 invoke_catch.1: ; preds = %entry + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + catch i8* null call fastcc void @_ZNSaIcED1Ev( ) - unwind + resume { i8*, i32 } %exn invoke_cont.1: ; preds = %entry call fastcc void @_ZNSaIcEC2ERKS_( ) @@ -243,3 +249,5 @@ define fastcc void @_ZN9__gnu_cxx12__pool_allocILb1ELi0EE9_S_refillEj() { entry: unreachable } + +declare i32 @__gxx_personality_v0(...) diff --git a/test/Transforms/Inline/2006-11-09-InlineCGUpdate.ll b/test/Transforms/Inline/2006-11-09-InlineCGUpdate.ll index 279823a4b2811..b754d9f9f5d9c 100644 --- a/test/Transforms/Inline/2006-11-09-InlineCGUpdate.ll +++ b/test/Transforms/Inline/2006-11-09-InlineCGUpdate.ll @@ -155,7 +155,7 @@ endif.0: ; preds = %entry define fastcc void @_ZSt20__throw_length_errorPKc() { entry: call fastcc void @_ZNSt12length_errorC1ERKSs( ) - unwind + ret void } define fastcc void @_ZNSs16_S_construct_auxIPKcEEPcT_S3_RKSaIcE12__false_type() { @@ -178,8 +178,10 @@ entry: to label %invoke_cont.1 unwind label %invoke_catch.1 invoke_catch.1: ; preds = %entry + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + catch i8* null call fastcc void @_ZNSaIcED1Ev( ) - unwind + resume { i8*, i32 } %exn invoke_cont.1: ; preds = %entry call fastcc void @_ZNSaIcEC2ERKS_( ) @@ -306,7 +308,9 @@ entry: to label %_ZNSt11logic_errorC2ERKSs.exit unwind label %invoke_catch.i invoke_catch.i: ; preds = %entry - unwind + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + catch i8* null + resume { i8*, i32 } %exn _ZNSt11logic_errorC2ERKSs.exit: ; preds = %entry ret void @@ -336,3 +340,5 @@ define fastcc void @_ZNSt5ctypeIcEC1EPKtbj() { entry: ret void } + +declare i32 @__gxx_personality_v0(...) diff --git a/test/Transforms/Inline/2007-04-15-InlineEH.ll b/test/Transforms/Inline/2007-04-15-InlineEH.ll index 635f93e824285..8fbcf929d024f 100644 --- a/test/Transforms/Inline/2007-04-15-InlineEH.ll +++ b/test/Transforms/Inline/2007-04-15-InlineEH.ll @@ -33,9 +33,13 @@ invcont67: ; preds = %invcont65 ret void cleanup144: ; preds = %invcont65, %invcont64, %invcont, %entry - unwind + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup + resume { i8*, i32 } %exn } +declare i32 @__gxx_personality_v0(...) + declare void @gnat__os_lib__getenv(%struct.gnat__strings__string_access*) declare void @ada__calendar__delays__delay_for() diff --git a/test/Transforms/Inline/2007-12-19-InlineNoUnwind.ll b/test/Transforms/Inline/2007-12-19-InlineNoUnwind.ll index 979157ebc8b40..a5cfc3b9264c4 100644 --- a/test/Transforms/Inline/2007-12-19-InlineNoUnwind.ll +++ b/test/Transforms/Inline/2007-12-19-InlineNoUnwind.ll @@ -10,7 +10,7 @@ entry: r: ret i32 0 u: - unwind + unreachable } define i32 @caller() { diff --git a/test/Transforms/Inline/callgraph-update.ll b/test/Transforms/Inline/callgraph-update.ll index ff0120b733065..b96fbc39c2ff2 100644 --- a/test/Transforms/Inline/callgraph-update.ll +++ b/test/Transforms/Inline/callgraph-update.ll @@ -29,5 +29,8 @@ invcont: unreachable lpad: + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup unreachable } +declare i32 @__gxx_personality_v0(...) diff --git a/test/Transforms/Inline/crash.ll b/test/Transforms/Inline/crash.ll index 1df4d6063e84c..e2cd49c2516c8 100644 --- a/test/Transforms/Inline/crash.ll +++ b/test/Transforms/Inline/crash.ll @@ -69,9 +69,13 @@ invcont98: unreachable lpad156: + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup unreachable } +declare i32 @__gxx_personality_v0(...) + declare fastcc void @YYY() define internal fastcc void @XXX() { @@ -84,7 +88,9 @@ bb260: ret void lpad: - unwind + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup + resume { i8*, i32 } %exn } @@ -105,6 +111,8 @@ invcont3: ; preds = %bb1 ret void lpad18: ; preds = %invcont3, %bb1 + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup unreachable } diff --git a/test/Transforms/Inline/inline_invoke.ll b/test/Transforms/Inline/inline_invoke.ll index 2a1b8836c76e5..9f5f670b859bc 100644 --- a/test/Transforms/Inline/inline_invoke.ll +++ b/test/Transforms/Inline/inline_invoke.ll @@ -18,14 +18,8 @@ declare void @use(i32) nounwind declare void @opaque() -declare i8* @llvm.eh.exception() nounwind readonly - -declare i32 @llvm.eh.selector(i8*, i8*, ...) nounwind - declare i32 @llvm.eh.typeid.for(i8*) nounwind -declare void @llvm.eh.resume(i8*, i32) - declare i32 @__gxx_personality_v0(...) declare i8* @__cxa_begin_catch(i8*) @@ -51,18 +45,17 @@ invoke.cont1: ret void lpad: - %exn = call i8* @llvm.eh.exception() nounwind - %eh.selector = call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* %exn, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i32 0) nounwind + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup invoke void @_ZN1AD1Ev(%struct.A* %a) to label %invoke.cont2 unwind label %terminate.lpad invoke.cont2: - call void @llvm.eh.resume(i8* %exn, i32 %eh.selector) noreturn - unreachable + resume { i8*, i32 } %exn terminate.lpad: - %exn3 = call i8* @llvm.eh.exception() nounwind - %eh.selector4 = call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* %exn3, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* null) nounwind + %exn1 = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + catch i8* null call void @_ZSt9terminatev() noreturn nounwind unreachable } @@ -76,20 +69,21 @@ ret: ret void lpad: ; preds = %entry - %exn = call i8* @llvm.eh.exception() nounwind - %eh.selector = call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* %exn, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* bitcast (i8** @_ZTIi to i8*)) nounwind + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + catch i8* bitcast (i8** @_ZTIi to i8*) + %eh.exc = extractvalue { i8*, i32 } %exn, 0 + %eh.selector = extractvalue { i8*, i32 } %exn, 1 %0 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) nounwind %1 = icmp eq i32 %eh.selector, %0 br i1 %1, label %catch, label %eh.resume catch: - %ignored = call i8* @__cxa_begin_catch(i8* %exn) nounwind + %ignored = call i8* @__cxa_begin_catch(i8* %eh.exc) nounwind call void @__cxa_end_catch() nounwind br label %ret eh.resume: - call void @llvm.eh.resume(i8* %exn, i32 %eh.selector) noreturn - unreachable + resume { i8*, i32 } %exn } ; CHECK: define void @test0_out() @@ -99,18 +93,21 @@ eh.resume: ; CHECK: invoke void @_ZN1AC1Ev(%struct.A* [[B]]) ; CHECK: invoke void @_ZN1AD1Ev(%struct.A* [[B]]) ; CHECK: invoke void @_ZN1AD1Ev(%struct.A* [[A]]) -; CHECK: call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* {{%.*}}, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i32 0, i8* bitcast (i8** @_ZTIi to i8*)) +; CHECK: landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0 +; CHECK-NEXT: cleanup +; CHECK-NEXT: catch i8* bitcast (i8** @_ZTIi to i8*) ; CHECK-NEXT: invoke void @_ZN1AD1Ev(%struct.A* [[A]]) ; CHECK-NEXT: to label %[[LBL:[^\s]+]] unwind ; CHECK: [[LBL]]: ; CHECK-NEXT: br label %[[LPAD:[^\s]+]] ; CHECK: ret void -; CHECK: call i8* @llvm.eh.exception() -; CHECK-NEXT: call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* {{%.*}}, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* bitcast (i8** @_ZTIi to i8*)) +; CHECK: landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0 +; CHECK-NEXT: catch i8* bitcast (i8** @_ZTIi to i8*) ; CHECK-NEXT: br label %[[LPAD]] ; CHECK: [[LPAD]]: -; CHECK-NEXT: phi i8* [ -; CHECK-NEXT: phi i32 [ +; CHECK-NEXT: phi { i8*, i32 } [ +; CHECK-NEXT: extractvalue { i8*, i32 } +; CHECK-NEXT: extractvalue { i8*, i32 } ; CHECK-NEXT: call i32 @llvm.eh.typeid.for( @@ -131,22 +128,23 @@ ret: lpad: %x = phi i32 [ 0, %entry ], [ 1, %cont ] %y = phi i32 [ 1, %entry ], [ 4, %cont ] - %exn = call i8* @llvm.eh.exception() nounwind - %eh.selector = call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* %exn, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* bitcast (i8** @_ZTIi to i8*)) nounwind + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + catch i8* bitcast (i8** @_ZTIi to i8*) + %eh.exc = extractvalue { i8*, i32 } %exn, 0 + %eh.selector = extractvalue { i8*, i32 } %exn, 1 %0 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) nounwind %1 = icmp eq i32 %eh.selector, %0 br i1 %1, label %catch, label %eh.resume catch: - %ignored = call i8* @__cxa_begin_catch(i8* %exn) nounwind + %ignored = call i8* @__cxa_begin_catch(i8* %eh.exc) nounwind call void @use(i32 %x) call void @use(i32 %y) call void @__cxa_end_catch() nounwind br label %ret eh.resume: - call void @llvm.eh.resume(i8* %exn, i32 %eh.selector) noreturn - unreachable + resume { i8*, i32 } %exn } ; CHECK: define void @test1_out() @@ -165,8 +163,9 @@ eh.resume: ; Inner landing pad from first inlining. ; CHECK: [[LPAD1]]: -; CHECK-NEXT: [[EXN1:%.*]] = call i8* @llvm.eh.exception() -; CHECK-NEXT: [[SEL1:%.*]] = call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* [[EXN1]], i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i32 0, i8* bitcast (i8** @_ZTIi to i8*)) +; CHECK-NEXT: [[LPADVAL1:%.*]] = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0 +; CHECK-NEXT: cleanup +; CHECK-NEXT: catch i8* bitcast (i8** @_ZTIi to i8*) ; CHECK-NEXT: invoke void @_ZN1AD1Ev(%struct.A* [[A1]]) ; CHECK-NEXT: to label %[[RESUME1:[^\s]+]] unwind ; CHECK: [[RESUME1]]: @@ -183,8 +182,9 @@ eh.resume: ; Inner landing pad from second inlining. ; CHECK: [[LPAD2]]: -; CHECK-NEXT: [[EXN2:%.*]] = call i8* @llvm.eh.exception() -; CHECK-NEXT: [[SEL2:%.*]] = call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* [[EXN2]], i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i32 0, i8* bitcast (i8** @_ZTIi to i8*)) +; CHECK-NEXT: [[LPADVAL2:%.*]] = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0 +; CHECK-NEXT: cleanup +; CHECK-NEXT: catch i8* bitcast (i8** @_ZTIi to i8*) ; CHECK-NEXT: invoke void @_ZN1AD1Ev(%struct.A* [[A2]]) ; CHECK-NEXT: to label %[[RESUME2:[^\s]+]] unwind ; CHECK: [[RESUME2]]: @@ -195,29 +195,29 @@ eh.resume: ; CHECK: [[LPAD]]: ; CHECK-NEXT: [[X:%.*]] = phi i32 [ 0, %entry ], [ 0, {{%.*}} ], [ 1, %cont ], [ 1, {{%.*}} ] ; CHECK-NEXT: [[Y:%.*]] = phi i32 [ 1, %entry ], [ 1, {{%.*}} ], [ 4, %cont ], [ 4, {{%.*}} ] -; CHECK-NEXT: [[EXN:%.*]] = call i8* @llvm.eh.exception() -; CHECK-NEXT: [[SEL:%.*]] = call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* [[EXN]], i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* bitcast (i8** @_ZTIi to i8*)) +; CHECK-NEXT: [[LPADVAL:%.*]] = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0 +; CHECK-NEXT: catch i8* bitcast (i8** @_ZTIi to i8*) ; CHECK-NEXT: br label %[[LPAD_JOIN2]] ; CHECK: [[LPAD_JOIN2]]: ; CHECK-NEXT: [[XJ2:%.*]] = phi i32 [ [[X]], %[[LPAD]] ], [ 1, %[[RESUME2]] ] ; CHECK-NEXT: [[YJ2:%.*]] = phi i32 [ [[Y]], %[[LPAD]] ], [ 4, %[[RESUME2]] ] -; CHECK-NEXT: [[EXNJ2:%.*]] = phi i8* [ [[EXN]], %[[LPAD]] ], [ [[EXN2]], %[[RESUME2]] ] -; CHECK-NEXT: [[SELJ2:%.*]] = phi i32 [ [[SEL]], %[[LPAD]] ], [ [[SEL2]], %[[RESUME2]] ] +; CHECK-NEXT: [[EXNJ2:%.*]] = phi { i8*, i32 } [ [[LPADVAL]], %[[LPAD]] ], [ [[LPADVAL2]], %[[RESUME2]] ] ; CHECK-NEXT: br label %[[LPAD_JOIN1]] ; CHECK: [[LPAD_JOIN1]]: ; CHECK-NEXT: [[XJ1:%.*]] = phi i32 [ [[XJ2]], %[[LPAD_JOIN2]] ], [ 0, %[[RESUME1]] ] ; CHECK-NEXT: [[YJ1:%.*]] = phi i32 [ [[YJ2]], %[[LPAD_JOIN2]] ], [ 1, %[[RESUME1]] ] -; CHECK-NEXT: [[EXNJ1:%.*]] = phi i8* [ [[EXNJ2]], %[[LPAD_JOIN2]] ], [ [[EXN1]], %[[RESUME1]] ] -; CHECK-NEXT: [[SELJ1:%.*]] = phi i32 [ [[SELJ2]], %[[LPAD_JOIN2]] ], [ [[SEL1]], %[[RESUME1]] ] +; CHECK-NEXT: [[EXNJ1:%.*]] = phi { i8*, i32 } [ [[EXNJ2]], %[[LPAD_JOIN2]] ], [ [[LPADVAL1]], %[[RESUME1]] ] +; CHECK-NEXT: extractvalue { i8*, i32 } [[EXNJ1]], 0 +; CHECK-NEXT: [[SELJ1:%.*]] = extractvalue { i8*, i32 } [[EXNJ1]], 1 ; CHECK-NEXT: [[T:%.*]] = call i32 @llvm.eh.typeid.for( ; CHECK-NEXT: icmp eq i32 [[SELJ1]], [[T]] ; CHECK: call void @use(i32 [[XJ1]]) ; CHECK: call void @use(i32 [[YJ1]]) -; CHECK: call void @llvm.eh.resume(i8* [[EXNJ1]], i32 [[SELJ1]]) +; CHECK: resume { i8*, i32 } ;; Test 2 - Don't make invalid IR for inlines into landing pads without eh.exception calls @@ -230,6 +230,8 @@ ret: ret void lpad: + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup call void @_ZSt9terminatev() unreachable } @@ -257,24 +259,25 @@ ret: ret void lpad: + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + catch i8* bitcast (i8** @_ZTIi to i8*) br label %lpad.cont lpad.cont: - %exn = call i8* @llvm.eh.exception() nounwind - %eh.selector = call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* %exn, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* bitcast (i8** @_ZTIi to i8*)) nounwind call void @_ZSt9terminatev() unreachable } ; CHECK: define void @test3_out() -; CHECK: call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* {{%.*}}, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i32 0, i8* bitcast (i8** @_ZTIi to i8*)) +; CHECK: landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0 +; CHECK-NEXT: cleanup +; CHECK-NEXT: catch i8* bitcast (i8** @_ZTIi to i8*) ; CHECK-NEXT: invoke void @_ZN1AD1Ev( ; CHECK-NEXT: to label %[[L:[^\s]+]] unwind ; CHECK: [[L]]: ; CHECK-NEXT: br label %[[JOIN:[^\s]+]] ; CHECK: [[JOIN]]: -; CHECK-NEXT: phi -; CHECK-NEXT: phi +; CHECK-NEXT: phi { i8*, i32 } ; CHECK-NEXT: br label %lpad.cont ; CHECK: lpad.cont: ; CHECK-NEXT: call void @_ZSt9terminatev() @@ -294,20 +297,27 @@ ret: ret void lpad.crit: + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + catch i8* bitcast (i8** @_ZTIi to i8*) call void @opaque() nounwind - br label %lpad + br label %terminate lpad: - %phi = phi i32 [ 0, %lpad.crit ], [ 1, %cont ] - %exn = call i8* @llvm.eh.exception() nounwind - %eh.selector = call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* %exn, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* bitcast (i8** @_ZTIi to i8*)) nounwind + %exn2 = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + catch i8* bitcast (i8** @_ZTIi to i8*) + br label %terminate + +terminate: + %phi = phi i32 [ 0, %lpad.crit ], [ 1, %lpad ] call void @use(i32 %phi) call void @_ZSt9terminatev() unreachable } ; CHECK: define void @test4_out() -; CHECK: call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* {{%.*}}, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i32 0, i8* bitcast (i8** @_ZTIi to i8*)) +; CHECK: landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0 +; CHECK-NEXT: cleanup +; CHECK-NEXT: catch i8* bitcast (i8** @_ZTIi to i8*) ; CHECK-NEXT: invoke void @_ZN1AD1Ev( ; CHECK-NEXT: to label %[[L:[^\s]+]] unwind ; CHECK: [[L]]: @@ -315,22 +325,18 @@ lpad: ; CHECK: invoke void @opaque() ; CHECK-NEXT: unwind label %lpad ; CHECK: lpad.crit: -; CHECK-NEXT: call i8* @llvm.eh.exception() -; CHECK-NEXT: call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* %4, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* bitcast (i8** @_ZTIi to i8*)) +; CHECK-NEXT: landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0 +; CHECK-NEXT: catch i8* bitcast (i8** @_ZTIi to i8*) ; CHECK-NEXT: br label %[[JOIN]] ; CHECK: [[JOIN]]: -; CHECK-NEXT: phi i8* -; CHECK-NEXT: phi i32 +; CHECK-NEXT: phi { i8*, i32 } ; CHECK-NEXT: call void @opaque() nounwind ; CHECK-NEXT: br label %[[FIX:[^\s]+]] ; CHECK: lpad: -; CHECK-NEXT: [[T0:%.*]] = phi i32 [ 1, %cont ] -; CHECK-NEXT: call i8* @llvm.eh.exception() nounwind -; CHECK-NEXT: call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* %exn, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* bitcast (i8** @_ZTIi to i8*)) +; CHECK-NEXT: landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0 +; CHECK-NEXT: catch i8* bitcast (i8** @_ZTIi to i8*) ; CHECK-NEXT: br label %[[FIX]] ; CHECK: [[FIX]]: -; CHECK-NEXT: [[T1:%.*]] = phi i32 [ [[T0]], %lpad ], [ 0, %[[JOIN]] ] -; CHECK-NEXT: phi i8* -; CHECK-NEXT: phi i32 +; CHECK-NEXT: [[T1:%.*]] = phi i32 [ 0, %[[JOIN]] ], [ 1, %lpad ] ; CHECK-NEXT: call void @use(i32 [[T1]]) ; CHECK-NEXT: call void @_ZSt9terminatev() diff --git a/test/Transforms/Inline/invoke_test-1.ll b/test/Transforms/Inline/invoke_test-1.ll index 0d27e2a7f5e4c..e0e6d600bbb36 100644 --- a/test/Transforms/Inline/invoke_test-1.ll +++ b/test/Transforms/Inline/invoke_test-1.ll @@ -20,5 +20,9 @@ cont: ; preds = %0 ret i32 0 exc: ; preds = %0 + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup ret i32 1 } + +declare i32 @__gxx_personality_v0(...) diff --git a/test/Transforms/Inline/invoke_test-2.ll b/test/Transforms/Inline/invoke_test-2.ll index bbb9ab055393d..680a5ca2542a2 100644 --- a/test/Transforms/Inline/invoke_test-2.ll +++ b/test/Transforms/Inline/invoke_test-2.ll @@ -14,6 +14,8 @@ cont: ; preds = %0 ret i32 0 exc: ; preds = %0 + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup ret i32 1 } @@ -26,5 +28,9 @@ cont: ; preds = %0 ret i32 %X UnreachableExceptionHandler: ; preds = %0 + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup ret i32 -1 } + +declare i32 @__gxx_personality_v0(...) diff --git a/test/Transforms/Inline/invoke_test-3.ll b/test/Transforms/Inline/invoke_test-3.ll index b360526fb3484..f5ce95aa516cf 100644 --- a/test/Transforms/Inline/invoke_test-3.ll +++ b/test/Transforms/Inline/invoke_test-3.ll @@ -14,7 +14,9 @@ cont: ; preds = %0 exc: ; preds = %0a ; This just rethrows the exception! - unwind + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup + resume { i8*, i32 } %exn } ; caller returns true if might_throw throws an exception... which gets @@ -28,5 +30,9 @@ cont: ; preds = %0 Handler: ; preds = %0 ; This consumes an exception thrown by might_throw + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup ret i32 1 } + +declare i32 @__gxx_personality_v0(...) diff --git a/test/Transforms/InstCombine/2003-10-29-CallSiteResolve.ll b/test/Transforms/InstCombine/2003-10-29-CallSiteResolve.ll index cfe5df6d30a36..56493e2e5e320 100644 --- a/test/Transforms/InstCombine/2003-10-29-CallSiteResolve.ll +++ b/test/Transforms/InstCombine/2003-10-29-CallSiteResolve.ll @@ -10,6 +10,9 @@ invoke_cont: ; preds = %0 ret float* %tmp.11 X: ; preds = %0 + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup ret float* null } +declare i32 @__gxx_personality_v0(...) diff --git a/test/Transforms/InstCombine/2004-01-13-InstCombineInvokePHI.ll b/test/Transforms/InstCombine/2004-01-13-InstCombineInvokePHI.ll index bec0b9e0c5733..6df30c7e7fd14 100644 --- a/test/Transforms/InstCombine/2004-01-13-InstCombineInvokePHI.ll +++ b/test/Transforms/InstCombine/2004-01-13-InstCombineInvokePHI.ll @@ -23,6 +23,9 @@ cont: ; preds = %call, %entry ret i32 %V N: ; preds = %call + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup ret i32 0 } +declare i32 @__gxx_personality_v0(...) diff --git a/test/Transforms/InstCombine/2008-01-14-VarArgTrampoline.ll b/test/Transforms/InstCombine/2008-01-14-VarArgTrampoline.ll index 9bb940893935f..aacea9df5b31e 100644 --- a/test/Transforms/InstCombine/2008-01-14-VarArgTrampoline.ll +++ b/test/Transforms/InstCombine/2008-01-14-VarArgTrampoline.ll @@ -3,7 +3,8 @@ %struct.FRAME.nest = type { i32, i32 (...)* } %struct.__builtin_trampoline = type { [10 x i8] } -declare i8* @llvm.init.trampoline(i8*, i8*, i8*) nounwind +declare void @llvm.init.trampoline(i8*, i8*, i8*) nounwind +declare i8* @llvm.adjust.trampoline(i8*) nounwind declare i32 @f(%struct.FRAME.nest* nest , ...) @@ -15,7 +16,8 @@ entry: %tmp3 = getelementptr %struct.FRAME.nest* %FRAME.0, i32 0, i32 0 ; <i32*> [#uses=1] store i32 %n, i32* %tmp3, align 8 %FRAME.06 = bitcast %struct.FRAME.nest* %FRAME.0 to i8* ; <i8*> [#uses=1] - %tramp = call i8* @llvm.init.trampoline( i8* %TRAMP.216.sub, i8* bitcast (i32 (%struct.FRAME.nest*, ...)* @f to i8*), i8* %FRAME.06 ) ; <i8*> [#uses=1] + call void @llvm.init.trampoline( i8* %TRAMP.216.sub, i8* bitcast (i32 (%struct.FRAME.nest*, ...)* @f to i8*), i8* %FRAME.06 ) ; <i8*> [#uses=1] + %tramp = call i8* @llvm.adjust.trampoline( i8* %TRAMP.216.sub) %tmp7 = getelementptr %struct.FRAME.nest* %FRAME.0, i32 0, i32 1 ; <i32 (...)**> [#uses=1] %tmp89 = bitcast i8* %tramp to i32 (...)* ; <i32 (...)*> [#uses=2] store i32 (...)* %tmp89, i32 (...)** %tmp7, align 8 diff --git a/test/Transforms/InstCombine/2008-04-28-VolatileStore.ll b/test/Transforms/InstCombine/2008-04-28-VolatileStore.ll index 626564da936a4..6847f5ed0534a 100644 --- a/test/Transforms/InstCombine/2008-04-28-VolatileStore.ll +++ b/test/Transforms/InstCombine/2008-04-28-VolatileStore.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -instcombine -S | grep {volatile store} +; RUN: opt < %s -instcombine -S | grep {store volatile} define void @test() { %votf = alloca <4 x float> ; <<4 x float>*> [#uses=1] diff --git a/test/Transforms/InstCombine/2008-04-29-VolatileLoadDontMerge.ll b/test/Transforms/InstCombine/2008-04-29-VolatileLoadDontMerge.ll index f2cc7254a3255..a24f3071c9ac7 100644 --- a/test/Transforms/InstCombine/2008-04-29-VolatileLoadDontMerge.ll +++ b/test/Transforms/InstCombine/2008-04-29-VolatileLoadDontMerge.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -instcombine -S | grep {volatile load} | count 2 +; RUN: opt < %s -instcombine -S | grep {load volatile} | 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-darwin8" @g_1 = internal global i32 0 ; <i32*> [#uses=3] diff --git a/test/Transforms/InstCombine/2008-04-29-VolatileLoadMerge.ll b/test/Transforms/InstCombine/2008-04-29-VolatileLoadMerge.ll index 176162d386363..5fb11ffb32da0 100644 --- a/test/Transforms/InstCombine/2008-04-29-VolatileLoadMerge.ll +++ b/test/Transforms/InstCombine/2008-04-29-VolatileLoadMerge.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -instcombine -S | grep {volatile load} | count 2 +; RUN: opt < %s -instcombine -S | grep {load volatile} | count 2 ; PR2262 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-darwin8" diff --git a/test/Transforms/InstCombine/2008-05-09-SinkOfInvoke.ll b/test/Transforms/InstCombine/2008-05-09-SinkOfInvoke.ll index d56a1a0b786ae..f6eb24843fb88 100644 --- a/test/Transforms/InstCombine/2008-05-09-SinkOfInvoke.ll +++ b/test/Transforms/InstCombine/2008-05-09-SinkOfInvoke.ll @@ -29,5 +29,9 @@ invcont37: ; preds = %invcont31 ret void lpad: ; preds = %invcont31, %invcont, %entry + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup unreachable } + +declare i32 @__gxx_personality_v0(...) diff --git a/test/Transforms/InstCombine/2008-07-08-VolatileLoadMerge.ll b/test/Transforms/InstCombine/2008-07-08-VolatileLoadMerge.ll index ccfb1182769f6..81044083c6026 100644 --- a/test/Transforms/InstCombine/2008-07-08-VolatileLoadMerge.ll +++ b/test/Transforms/InstCombine/2008-07-08-VolatileLoadMerge.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -instcombine -S | grep {volatile load} | count 2 +; RUN: opt < %s -instcombine -S | grep {load volatile} | count 2 ; PR2496 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-darwin8" diff --git a/test/Transforms/InstCombine/2011-09-03-Trampoline.ll b/test/Transforms/InstCombine/2011-09-03-Trampoline.ll new file mode 100644 index 0000000000000..5456e03573939 --- /dev/null +++ b/test/Transforms/InstCombine/2011-09-03-Trampoline.ll @@ -0,0 +1,87 @@ +; RUN: opt -instcombine -S < %s | FileCheck %s + +declare void @llvm.init.trampoline(i8*, i8*, i8*) +declare i8* @llvm.adjust.trampoline(i8*) +declare i32 @f(i8 * nest, i32) + +; Most common case +define i32 @test0(i32 %n) { + %alloca = alloca [10 x i8], align 16 + %gep = getelementptr [10 x i8]* %alloca, i32 0, i32 0 + call void @llvm.init.trampoline(i8* %gep, i8* bitcast (i32 (i8*, i32)* @f to i8*), + i8* null) + %tramp = call i8* @llvm.adjust.trampoline(i8* %gep) + %function = bitcast i8* %tramp to i32(i32)* + %ret = call i32 %function(i32 %n) + ret i32 %ret + +; CHECK: define i32 @test0(i32 %n) { +; CHECK: %ret = call i32 @f(i8* nest null, i32 %n) +} + +define i32 @test1(i32 %n, i8* %trampmem) { + call void @llvm.init.trampoline(i8* %trampmem, + i8* bitcast (i32 (i8*, i32)* @f to i8*), + i8* null) + %tramp = call i8* @llvm.adjust.trampoline(i8* %trampmem) + %function = bitcast i8* %tramp to i32(i32)* + %ret = call i32 %function(i32 %n) + ret i32 %ret +; CHECK: define i32 @test1(i32 %n, i8* %trampmem) { +; CHECK: %ret = call i32 @f(i8* nest null, i32 %n) +} + +define i32 @test2(i32 %n, i8* %trampmem) { + %tramp = call i8* @llvm.adjust.trampoline(i8* %trampmem) + %functiona = bitcast i8* %tramp to i32(i32)* + %ret = call i32 %functiona(i32 %n) + ret i32 %ret +; CHECK: define i32 @test2(i32 %n, i8* %trampmem) { +; CHECK: %ret = call i32 %functiona(i32 %n) +} + +define i32 @test3(i32 %n, i8* %trampmem) { + call void @llvm.init.trampoline(i8* %trampmem, + i8* bitcast (i32 (i8*, i32)* @f to i8*), + i8* null) + +; CHECK: define i32 @test3(i32 %n, i8* %trampmem) { +; CHECK: %ret0 = call i32 @f(i8* nest null, i32 %n) + %tramp0 = call i8* @llvm.adjust.trampoline(i8* %trampmem) + %function0 = bitcast i8* %tramp0 to i32(i32)* + %ret0 = call i32 %function0(i32 %n) + + ;; Not optimized since previous call could be writing. + %tramp1 = call i8* @llvm.adjust.trampoline(i8* %trampmem) + %function1 = bitcast i8* %tramp1 to i32(i32)* + %ret1 = call i32 %function1(i32 %n) +; CHECK: %ret1 = call i32 %function1(i32 %n) + + ret i32 %ret1 +} + +define i32 @test4(i32 %n) { + %alloca = alloca [10 x i8], align 16 + %gep = getelementptr [10 x i8]* %alloca, i32 0, i32 0 + call void @llvm.init.trampoline(i8* %gep, i8* bitcast (i32 (i8*, i32)* @f to i8*), + i8* null) + + %tramp0 = call i8* @llvm.adjust.trampoline(i8* %gep) + %function0 = bitcast i8* %tramp0 to i32(i32)* + %ret0 = call i32 %function0(i32 %n) + + %tramp1 = call i8* @llvm.adjust.trampoline(i8* %gep) + %function1 = bitcast i8* %tramp0 to i32(i32)* + %ret1 = call i32 %function1(i32 %n) + + %tramp2 = call i8* @llvm.adjust.trampoline(i8* %gep) + %function2 = bitcast i8* %tramp2 to i32(i32)* + %ret2 = call i32 %function2(i32 %n) + + ret i32 %ret2 + +; CHECK: define i32 @test4(i32 %n) { +; CHECK: %ret0 = call i32 @f(i8* nest null, i32 %n) +; CHECK: %ret1 = call i32 @f(i8* nest null, i32 %n) +; CHECK: %ret2 = call i32 @f(i8* nest null, i32 %n) +} diff --git a/test/Transforms/InstCombine/2011-10-07-AlignPromotion.ll b/test/Transforms/InstCombine/2011-10-07-AlignPromotion.ll new file mode 100644 index 0000000000000..22061b272a85f --- /dev/null +++ b/test/Transforms/InstCombine/2011-10-07-AlignPromotion.ll @@ -0,0 +1,20 @@ +; RUN: opt -S -instcombine < %s | FileCheck %s +; rdar://problem/10063307 +target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:32:64-v128:32:128-a0:0:32-n32-S32" +target triple = "thumbv7-apple-ios5.0.0" + +%0 = type { [2 x i32] } +%struct.CGPoint = type { float, float } + +define void @t(%struct.CGPoint* %a) nounwind { + %Point = alloca %struct.CGPoint, align 4 + %1 = bitcast %struct.CGPoint* %a to i64* + %2 = bitcast %struct.CGPoint* %Point to i64* + %3 = load i64* %1, align 4 + store i64 %3, i64* %2, align 4 + call void @foo(i64* %2) nounwind + ret void +; CHECK: %Point = alloca i64, align 4 +} + +declare void @foo(i64*) diff --git a/test/Transforms/InstCombine/LandingPadClauses.ll b/test/Transforms/InstCombine/LandingPadClauses.ll new file mode 100644 index 0000000000000..055bdcc81b564 --- /dev/null +++ b/test/Transforms/InstCombine/LandingPadClauses.ll @@ -0,0 +1,181 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +@T1 = external constant i32 +@T2 = external constant i32 +@T3 = external constant i32 + +declare i32 @generic_personality(i32, i64, i8*, i8*) +declare i32 @__gxx_personality_v0(i32, i64, i8*, i8*) + +declare void @bar() + +define void @foo_generic() { +; CHECK: @foo_generic + invoke void @bar() + to label %cont.a unwind label %lpad.a +cont.a: + invoke void @bar() + to label %cont.b unwind label %lpad.b +cont.b: + invoke void @bar() + to label %cont.c unwind label %lpad.c +cont.c: + invoke void @bar() + to label %cont.d unwind label %lpad.d +cont.d: + invoke void @bar() + to label %cont.e unwind label %lpad.e +cont.e: + invoke void @bar() + to label %cont.f unwind label %lpad.f +cont.f: + invoke void @bar() + to label %cont.g unwind label %lpad.g +cont.g: + invoke void @bar() + to label %cont.h unwind label %lpad.h +cont.h: + invoke void @bar() + to label %cont.i unwind label %lpad.i +cont.i: + ret void + +lpad.a: + %a = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @generic_personality + catch i32* @T1 + catch i32* @T2 + catch i32* @T1 + catch i32* @T2 + unreachable +; CHECK: %a = landingpad +; CHECK-NEXT: @T1 +; CHECK-NEXT: @T2 +; CHECK-NEXT: unreachable + +lpad.b: + %b = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @generic_personality + filter [0 x i32*] zeroinitializer + catch i32* @T1 + unreachable +; CHECK: %b = landingpad +; CHECK-NEXT: filter +; CHECK-NEXT: unreachable + +lpad.c: + %c = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @generic_personality + catch i32* @T1 + filter [1 x i32*] [i32* @T1] + catch i32* @T2 + unreachable +; CHECK: %c = landingpad +; CHECK-NEXT: @T1 +; CHECK-NEXT: filter [0 x i32*] +; CHECK-NEXT: unreachable + +lpad.d: + %d = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @generic_personality + filter [3 x i32*] zeroinitializer + unreachable +; CHECK: %d = landingpad +; CHECK-NEXT: filter [1 x i32*] zeroinitializer +; CHECK-NEXT: unreachable + +lpad.e: + %e = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @generic_personality + catch i32* @T1 + filter [3 x i32*] [i32* @T1, i32* @T2, i32* @T2] + unreachable +; CHECK: %e = landingpad +; CHECK-NEXT: @T1 +; CHECK-NEXT: filter [1 x i32*] [i32* @T2] +; CHECK-NEXT: unreachable + +lpad.f: + %f = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @generic_personality + filter [2 x i32*] [i32* @T2, i32* @T1] + filter [1 x i32*] [i32* @T1] + unreachable +; CHECK: %f = landingpad +; CHECK-NEXT: filter [1 x i32*] [i32* @T1] +; CHECK-NEXT: unreachable + +lpad.g: + %g = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @generic_personality + filter [1 x i32*] [i32* @T1] + catch i32* @T3 + filter [2 x i32*] [i32* @T2, i32* @T1] + unreachable +; CHECK: %g = landingpad +; CHECK-NEXT: filter [1 x i32*] [i32* @T1] +; CHECK-NEXT: catch i32* @T3 +; CHECK-NEXT: unreachable + +lpad.h: + %h = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @generic_personality + filter [2 x i32*] [i32* @T1, i32* null] + filter [1 x i32*] zeroinitializer + unreachable +; CHECK: %h = landingpad +; CHECK-NEXT: filter [1 x i32*] zeroinitializer +; CHECK-NEXT: unreachable + +lpad.i: + %i = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @generic_personality + cleanup + filter [0 x i32*] zeroinitializer + unreachable +; CHECK: %i = landingpad +; CHECK-NEXT: filter +; CHECK-NEXT: unreachable +} + +define void @foo_cxx() { +; CHECK: @foo_cxx + invoke void @bar() + to label %cont.a unwind label %lpad.a +cont.a: + invoke void @bar() + to label %cont.b unwind label %lpad.b +cont.b: + invoke void @bar() + to label %cont.c unwind label %lpad.c +cont.c: + invoke void @bar() + to label %cont.d unwind label %lpad.d +cont.d: + ret void + +lpad.a: + %a = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @__gxx_personality_v0 + catch i32* null + catch i32* @T1 + unreachable +; CHECK: %a = landingpad +; CHECK-NEXT: null +; CHECK-NEXT: unreachable + +lpad.b: + %b = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @__gxx_personality_v0 + filter [1 x i32*] zeroinitializer + unreachable +; CHECK: %b = landingpad +; CHECK-NEXT: cleanup +; CHECK-NEXT: unreachable + +lpad.c: + %c = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @__gxx_personality_v0 + filter [2 x i32*] [i32* @T1, i32* null] + unreachable +; CHECK: %c = landingpad +; CHECK-NEXT: cleanup +; CHECK-NEXT: unreachable + +lpad.d: + %d = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @__gxx_personality_v0 + cleanup + catch i32* null + unreachable +; CHECK: %d = landingpad +; CHECK-NEXT: null +; CHECK-NEXT: unreachable +} diff --git a/test/Transforms/InstCombine/and2.ll b/test/Transforms/InstCombine/and2.ll index a8881522eac4b..531aedb668a01 100644 --- a/test/Transforms/InstCombine/and2.ll +++ b/test/Transforms/InstCombine/and2.ll @@ -35,3 +35,10 @@ define i1 @test4(i32 %X) { ; CHECK: @test4 ; CHECK-NEXT: ret i1 false } + +; Make sure we don't go into an infinite loop with this test +define <4 x i32> @test5(<4 x i32> %A) { + %1 = xor <4 x i32> %A, <i32 1, i32 2, i32 3, i32 4> + %2 = and <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %1 + ret <4 x i32> %2 +} diff --git a/test/Transforms/InstCombine/atomic.ll b/test/Transforms/InstCombine/atomic.ll new file mode 100644 index 0000000000000..097cf5eafe068 --- /dev/null +++ b/test/Transforms/InstCombine/atomic.ll @@ -0,0 +1,24 @@ +; RUN: opt -S < %s -instcombine | FileCheck %s + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" +target triple = "x86_64-apple-macosx10.7.0" + +; Check transforms involving atomic operations + +define i32* @test1(i8** %p) { +; CHECK: define i32* @test1 +; CHECK: load atomic i8** %p monotonic, align 8 + %c = bitcast i8** %p to i32** + %r = load atomic i32** %c monotonic, align 8 + ret i32* %r +} + +define i32 @test2(i32* %p) { +; CHECK: define i32 @test2 +; CHECK: %x = load atomic i32* %p seq_cst, align 4 +; CHECK: shl i32 %x, 1 + %x = load atomic i32* %p seq_cst, align 4 + %y = load i32* %p, align 4 + %z = add i32 %x, %y + ret i32 %z +} diff --git a/test/Transforms/InstCombine/bitcast.ll b/test/Transforms/InstCombine/bitcast.ll index 0718b8a3aee04..8f6ae7d83527e 100644 --- a/test/Transforms/InstCombine/bitcast.ll +++ b/test/Transforms/InstCombine/bitcast.ll @@ -1,5 +1,8 @@ ; RUN: opt < %s -instcombine -S | FileCheck %s +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" +target triple = "x86_64-apple-darwin10.0.0" + ; Bitcasts between vectors and scalars are valid. ; PR4487 define i32 @test1(i64 %a) { @@ -103,3 +106,34 @@ define <2 x float> @test6(float %A){ ; CHECK-NEXT: insertelement <2 x float> <float 4.200000e+01, float undef>, float %A, i32 1 ; CHECK: ret } + +define i64 @ISPC0(i64 %in) { + %out = and i64 %in, xor (i64 bitcast (<4 x i16> <i16 -1, i16 -1, i16 -1, i16 -1> to i64), i64 -1) + ret i64 %out +; CHECK: @ISPC0 +; CHECK: ret i64 0 +} + + +define i64 @Vec2(i64 %in) { + %out = and i64 %in, xor (i64 bitcast (<4 x i16> <i16 0, i16 0, i16 0, i16 0> to i64), i64 0) + ret i64 %out +; CHECK: @Vec2 +; CHECK: ret i64 0 +} + +define i64 @All11(i64 %in) { + %out = and i64 %in, xor (i64 bitcast (<2 x float> bitcast (i64 -1 to <2 x float>) to i64), i64 -1) + ret i64 %out +; CHECK: @All11 +; CHECK: ret i64 0 +} + + +define i32 @All111(i32 %in) { + %out = and i32 %in, xor (i32 bitcast (<1 x float> bitcast (i32 -1 to <1 x float>) to i32), i32 -1) + ret i32 %out +; CHECK: @All111 +; CHECK: ret i32 0 +} + diff --git a/test/Transforms/InstCombine/call.ll b/test/Transforms/InstCombine/call.ll index d0848739cdcc2..96ec420eaa8e6 100644 --- a/test/Transforms/InstCombine/call.ll +++ b/test/Transforms/InstCombine/call.ll @@ -9,8 +9,8 @@ declare void @test1a(i8*) define void @test1(i32* %A) { call void bitcast (void (i8*)* @test1a to void (i32*)*)( i32* %A ) ret void -; CHECK: %tmp = bitcast i32* %A to i8* -; CHECK: call void @test1a(i8* %tmp) +; CHECK: %1 = bitcast i32* %A to i8* +; CHECK: call void @test1a(i8* %1) ; CHECK: ret void } @@ -24,8 +24,8 @@ define void @test2a(i8 %A) { define i32 @test2(i32 %A) { call void bitcast (void (i8)* @test2a to void (i32)*)( i32 %A ) ret i32 %A -; CHECK: %tmp = trunc i32 %A to i8 -; CHECK: call void @test2a(i8 %tmp) +; CHECK: %1 = trunc i32 %A to i8 +; CHECK: call void @test2a(i8 %1) ; CHECK: ret i32 %A } @@ -38,8 +38,8 @@ define void @test3(i8 %A, i8 %B) { call void bitcast (void (i8, ...)* @test3a to void (i8, i8)*)( i8 %A, i8 %B ) ret void -; CHECK: %tmp = zext i8 %B to i32 -; CHECK: call void (i8, ...)* @test3a(i8 %A, i32 %tmp) +; CHECK: %1 = zext i8 %B to i32 +; CHECK: call void (i8, ...)* @test3a(i8 %A, i32 %1) ; CHECK: ret void } @@ -54,8 +54,8 @@ define i32 @test4() { %X = call i32 bitcast (i8 ()* @test4a to i32 ()*)( ) ; <i32> [#uses=1] ret i32 %X ; CHECK: %X = call i8 @test4a() -; CHECK: %tmp = zext i8 %X to i32 -; CHECK: ret i32 %tmp +; CHECK: %1 = zext i8 %X to i32 +; CHECK: ret i32 %1 } @@ -107,9 +107,13 @@ invoke.cont: ; preds = %entry unreachable try.handler: ; preds = %entry + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup ret i8* null } +declare i32 @__gxx_personality_v0(...) + ; Don't turn this into "unreachable": the callee and caller don't agree in ; calling conv, but the implementation of test8a may actually end up using the ; right calling conv. diff --git a/test/Transforms/InstCombine/canonicalize_branch.ll b/test/Transforms/InstCombine/canonicalize_branch.ll index 24090abcb5acd..869546d57dcd9 100644 --- a/test/Transforms/InstCombine/canonicalize_branch.ll +++ b/test/Transforms/InstCombine/canonicalize_branch.ll @@ -1,8 +1,23 @@ ; RUN: opt < %s -instcombine -S | FileCheck %s +; Test an already canonical branch to make sure we don't flip those. +define i32 @test0(i32 %X, i32 %Y) { + %C = icmp eq i32 %X, %Y + br i1 %C, label %T, label %F, !prof !0 + +; CHECK: @test0 +; CHECK: %C = icmp eq i32 %X, %Y +; CHECK: br i1 %C, label %T, label %F + +T: + ret i32 12 +F: + ret i32 123 +} + define i32 @test1(i32 %X, i32 %Y) { %C = icmp ne i32 %X, %Y - br i1 %C, label %T, label %F + br i1 %C, label %T, label %F, !prof !1 ; CHECK: @test1 ; CHECK: %C = icmp eq i32 %X, %Y @@ -16,7 +31,7 @@ F: define i32 @test2(i32 %X, i32 %Y) { %C = icmp ule i32 %X, %Y - br i1 %C, label %T, label %F + br i1 %C, label %T, label %F, !prof !2 ; CHECK: @test2 ; CHECK: %C = icmp ugt i32 %X, %Y @@ -30,7 +45,7 @@ F: define i32 @test3(i32 %X, i32 %Y) { %C = icmp uge i32 %X, %Y - br i1 %C, label %T, label %F + br i1 %C, label %T, label %F, !prof !3 ; CHECK: @test3 ; CHECK: %C = icmp ult i32 %X, %Y @@ -42,3 +57,13 @@ F: ret i32 123 } +!0 = metadata !{metadata !"branch_weights", i32 1, i32 2} +!1 = metadata !{metadata !"branch_weights", i32 3, i32 4} +!2 = metadata !{metadata !"branch_weights", i32 5, i32 6} +!3 = metadata !{metadata !"branch_weights", i32 7, i32 8} +; Base case shouldn't change. +; CHECK: !0 = {{.*}} i32 1, i32 2} +; Ensure that the branch metadata is reversed to match the reversals above. +; CHECK: !1 = {{.*}} i32 4, i32 3} +; CHECK: !2 = {{.*}} i32 6, i32 5} +; CHECK: !3 = {{.*}} i32 8, i32 7} diff --git a/test/Transforms/InstCombine/cast.ll b/test/Transforms/InstCombine/cast.ll index f85636f8df54d..19d5a0ae772d1 100644 --- a/test/Transforms/InstCombine/cast.ll +++ b/test/Transforms/InstCombine/cast.ll @@ -630,3 +630,50 @@ entry: ; CHECK: uitofp } +define <4 x float> @test64(<4 x float> %c) nounwind { + %t0 = bitcast <4 x float> %c to <4 x i32> + %t1 = bitcast <4 x i32> %t0 to <4 x float> + ret <4 x float> %t1 +; CHECK: @test64 +; CHECK-NEXT: ret <4 x float> %c +} + +define <4 x float> @test65(<4 x float> %c) nounwind { + %t0 = bitcast <4 x float> %c to <2 x double> + %t1 = bitcast <2 x double> %t0 to <4 x float> + ret <4 x float> %t1 +; CHECK: @test65 +; CHECK-NEXT: ret <4 x float> %c +} + +define <2 x float> @test66(<2 x float> %c) nounwind { + %t0 = bitcast <2 x float> %c to double + %t1 = bitcast double %t0 to <2 x float> + ret <2 x float> %t1 +; CHECK: @test66 +; CHECK-NEXT: ret <2 x float> %c +} + +define float @test2c() { + ret float extractelement (<2 x float> bitcast (double bitcast (<2 x float> <float -1.000000e+00, float -1.000000e+00> to double) to <2 x float>), i32 0) +; CHECK: @test2c +; CHECK-NOT: extractelement +} + +define i64 @test_mmx(<2 x i32> %c) nounwind { + %A = bitcast <2 x i32> %c to x86_mmx + %B = bitcast x86_mmx %A to <2 x i32> + %C = bitcast <2 x i32> %B to i64 + ret i64 %C +; CHECK: @test_mmx +; CHECK-NOT: x86_mmx +} + +define i64 @test_mmx_const(<2 x i32> %c) nounwind { + %A = bitcast <2 x i32> zeroinitializer to x86_mmx + %B = bitcast x86_mmx %A to <2 x i32> + %C = bitcast <2 x i32> %B to i64 + ret i64 %C +; CHECK: @test_mmx_const +; CHECK-NOT: x86_mmx +} diff --git a/test/Transforms/InstCombine/crash.ll b/test/Transforms/InstCombine/crash.ll index e17774d7b0e27..1a657f53a6076 100644 --- a/test/Transforms/InstCombine/crash.ll +++ b/test/Transforms/InstCombine/crash.ll @@ -135,6 +135,8 @@ define void @test5() { store i1 true, i1* undef %1 = invoke i32 @test5a() to label %exit unwind label %exit exit: + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup ret void } @@ -219,6 +221,8 @@ invoke.cont: ; preds = %entry unreachable try.handler: ; preds = %entry + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + catch i8* null ret i8* %self } diff --git a/test/Transforms/InstCombine/deadcode.ll b/test/Transforms/InstCombine/deadcode.ll index 52af0ef4e8d4e..7c7f1abc0ca66 100644 --- a/test/Transforms/InstCombine/deadcode.ll +++ b/test/Transforms/InstCombine/deadcode.ll @@ -1,5 +1,5 @@ ; RUN: opt < %s -instcombine -S | grep {ret i32 %A} -; RUN: opt < %s -die -S | not grep call.*llvm.stacksave +; RUN: opt < %s -die -S | not grep call.*llvm define i32 @test(i32 %A) { %X = or i1 false, false @@ -22,3 +22,12 @@ define i32* @test2(i32 %width) { declare i8* @llvm.stacksave() +declare void @llvm.lifetime.start(i64, i8*) +declare void @llvm.lifetime.end(i64, i8*) + +define void @test3() { + call void @llvm.lifetime.start(i64 -1, i8* undef) + call void @llvm.lifetime.end(i64 -1, i8* undef) + ret void +} + diff --git a/test/Transforms/InstCombine/devirt.ll b/test/Transforms/InstCombine/devirt.ll new file mode 100644 index 0000000000000..6189dc2af4f94 --- /dev/null +++ b/test/Transforms/InstCombine/devirt.ll @@ -0,0 +1,39 @@ +; RUN: opt -instcombine -S -o - %s | FileCheck %s + +; CHECK-NOT: getelementptr +; CHECK-NOT: ptrtoint +; CHECK: bitcast i8* +%struct.S = type { i32 (...)** } + +@_ZL1p = internal constant { i64, i64 } { i64 1, i64 0 }, align 8 + +define void @_Z1g1S(%struct.S* %s) nounwind { +entry: + %tmp = load { i64, i64 }* @_ZL1p, align 8 + %memptr.adj = extractvalue { i64, i64 } %tmp, 1 + %0 = bitcast %struct.S* %s to i8* + %1 = getelementptr inbounds i8* %0, i64 %memptr.adj + %this.adjusted = bitcast i8* %1 to %struct.S* + %memptr.ptr = extractvalue { i64, i64 } %tmp, 0 + %2 = and i64 %memptr.ptr, 1 + %memptr.isvirtual = icmp ne i64 %2, 0 + br i1 %memptr.isvirtual, label %memptr.virtual, label %memptr.nonvirtual + +memptr.virtual: ; preds = %entry + %3 = bitcast %struct.S* %this.adjusted to i8** + %memptr.vtable = load i8** %3 + %4 = sub i64 %memptr.ptr, 1 + %5 = getelementptr i8* %memptr.vtable, i64 %4 + %6 = bitcast i8* %5 to void (%struct.S*)** + %memptr.virtualfn = load void (%struct.S*)** %6 + br label %memptr.end + +memptr.nonvirtual: ; preds = %entry + %memptr.nonvirtualfn = inttoptr i64 %memptr.ptr to void (%struct.S*)* + br label %memptr.end + +memptr.end: ; preds = %memptr.nonvirtual, %memptr.virtual + %7 = phi void (%struct.S*)* [ %memptr.virtualfn, %memptr.virtual ], [ %memptr.nonvirtualfn, %memptr.nonvirtual ] + call void %7(%struct.S* %this.adjusted) + ret void +} diff --git a/test/Transforms/InstCombine/extractvalue.ll b/test/Transforms/InstCombine/extractvalue.ll index 64edc18d45072..cf36b8f237177 100644 --- a/test/Transforms/InstCombine/extractvalue.ll +++ b/test/Transforms/InstCombine/extractvalue.ll @@ -96,7 +96,7 @@ define i32 @nogep-multiuse({i32, i32}* %pair) { } ; CHECK: define i32 @nogep-volatile -; CHECK-NEXT: volatile load {{.*}} %pair +; CHECK-NEXT: load volatile {{.*}} %pair ; CHECK-NEXT: extractvalue ; CHECK-NEXT: ret define i32 @nogep-volatile({i32, i32}* %pair) { diff --git a/test/Transforms/InstCombine/fcmp.ll b/test/Transforms/InstCombine/fcmp.ll index 2eb4f058692d9..d08cbf574a231 100644 --- a/test/Transforms/InstCombine/fcmp.ll +++ b/test/Transforms/InstCombine/fcmp.ll @@ -58,3 +58,14 @@ define i1 @test7(float %x) nounwind readnone ssp noredzone { ; CHECK: @test7 ; CHECK-NEXT: fpext float %x to ppc_fp128 } + +define float @test8(float %x) nounwind readnone optsize ssp { + %conv = fpext float %x to double + %cmp = fcmp olt double %conv, 0.000000e+00 + %conv1 = zext i1 %cmp to i32 + %conv2 = sitofp i32 %conv1 to float + ret float %conv2 +; Float comparison to zero shouldn't cast to double. +; CHECK: @test8 +; CHECK-NEXT: fcmp olt float %x, 0.000000e+00 +} diff --git a/test/Transforms/InstCombine/getelementptr.ll b/test/Transforms/InstCombine/getelementptr.ll index 26c0e47f4b14a..1c120ecbe9eb7 100644 --- a/test/Transforms/InstCombine/getelementptr.ll +++ b/test/Transforms/InstCombine/getelementptr.ll @@ -472,3 +472,23 @@ entry: ; CHECK: @pr10322_f1 ; CHECK: %tmp2 = getelementptr inbounds %pr10322_t* %arrayidx8, i64 0, i32 0 } + +; Test that we combine the last two geps in this sequence, before we +; would wait for gep1 and gep2 to be combined and never combine 2 and 3. +%three_gep_t = type {i32} +%three_gep_t2 = type {%three_gep_t} + +define void @three_gep_f(%three_gep_t2* %x) { + %gep1 = getelementptr %three_gep_t2* %x, i64 2 + call void @three_gep_h(%three_gep_t2* %gep1) + %gep2 = getelementptr %three_gep_t2* %gep1, i64 0, i32 0 + %gep3 = getelementptr %three_gep_t* %gep2, i64 0, i32 0 + call void @three_gep_g(i32* %gep3) + +; CHECK: @three_gep_f +; CHECK: %gep3 = getelementptr %three_gep_t2* %gep1, i64 0, i32 0, i32 0 + ret void +} + +declare void @three_gep_g(i32*) +declare void @three_gep_h(%three_gep_t2*) diff --git a/test/Transforms/InstCombine/intrinsics.ll b/test/Transforms/InstCombine/intrinsics.ll index 0d84ae474388e..f033e510368bd 100644 --- a/test/Transforms/InstCombine/intrinsics.ll +++ b/test/Transforms/InstCombine/intrinsics.ll @@ -152,9 +152,9 @@ entry: ret void ; CHECK: @powi ; CHECK: %A = fdiv double 1.0{{.*}}, %V -; CHECK: volatile store double %A, -; CHECK: volatile store double 1.0 -; CHECK: volatile store double %V +; CHECK: store volatile double %A, +; CHECK: store volatile double 1.0 +; CHECK: store volatile double %V } define i32 @cttz(i32 %a) { @@ -194,11 +194,11 @@ entry: ; CHECK: @cmp.simplify ; CHECK-NEXT: entry: ; CHECK-NEXT: %lz.cmp = icmp eq i32 %a, 0 -; CHECK-NEXT: volatile store i1 %lz.cmp, i1* %c +; CHECK-NEXT: store volatile i1 %lz.cmp, i1* %c ; CHECK-NEXT: %tz.cmp = icmp ne i32 %a, 0 -; CHECK-NEXT: volatile store i1 %tz.cmp, i1* %c +; CHECK-NEXT: store volatile i1 %tz.cmp, i1* %c ; CHECK-NEXT: %pop.cmp = icmp eq i32 %b, 0 -; CHECK-NEXT: volatile store i1 %pop.cmp, i1* %c +; CHECK-NEXT: store volatile i1 %pop.cmp, i1* %c } diff --git a/test/Transforms/InstCombine/malloc-free-delete.ll b/test/Transforms/InstCombine/malloc-free-delete.ll index 8455300c98cad..eae973df0a54a 100644 --- a/test/Transforms/InstCombine/malloc-free-delete.ll +++ b/test/Transforms/InstCombine/malloc-free-delete.ll @@ -12,7 +12,7 @@ define i32 @main(i32 %argc, i8** %argv) { ; CHECK: ret i32 0 } -declare i8* @malloc(i32) +declare noalias i8* @malloc(i32) declare void @free(i8*) define i1 @foo() { @@ -23,3 +23,26 @@ define i1 @foo() { call void @free(i8* %m) ret i1 %z } + +declare void @llvm.lifetime.start(i64, i8*) +declare void @llvm.lifetime.end(i64, i8*) + +define void @test3() { +; CHECK: @test3 +; CHECK-NEXT: ret void + %a = call noalias i8* @malloc(i32 10) + call void @llvm.lifetime.start(i64 10, i8* %a) + call void @llvm.lifetime.end(i64 10, i8* %a) + ret void +} + +;; This used to crash. +define void @test4() { +; CHECK: @test4 +; CHECK-NEXT: ret void + %A = call i8* @malloc(i32 16000) + %B = bitcast i8* %A to double* + %C = bitcast double* %B to i8* + call void @free(i8* %C) + ret void +} diff --git a/test/Transforms/InstCombine/nsw.ll b/test/Transforms/InstCombine/nsw.ll index 681bdc234b7d9..0140c2f801221 100644 --- a/test/Transforms/InstCombine/nsw.ll +++ b/test/Transforms/InstCombine/nsw.ll @@ -37,3 +37,47 @@ define i64 @shl1(i64 %X, i64* %P) nounwind { %B = shl i64 %A, 8 ret i64 %B } + +; CHECK: @preserve1 +; CHECK: add nsw i32 %x, 5 +define i32 @preserve1(i32 %x) nounwind { + %add = add nsw i32 %x, 2 + %add3 = add nsw i32 %add, 3 + ret i32 %add3 +} + +; CHECK: @nopreserve1 +; CHECK: add i8 %x, -126 +define i8 @nopreserve1(i8 %x) nounwind { + %add = add nsw i8 %x, 127 + %add3 = add nsw i8 %add, 3 + ret i8 %add3 +} + +; CHECK: @nopreserve2 +; CHECK: add i8 %x, 3 +define i8 @nopreserve2(i8 %x) nounwind { + %add = add i8 %x, 1 + %add3 = add nsw i8 %add, 2 + ret i8 %add3 +} + +; CHECK: @nopreserve3 +; CHECK: add i8 %A, %B +; CHECK: add i8 +define i8 @nopreserve3(i8 %A, i8 %B) nounwind { + %x = add i8 %A, 10 + %y = add i8 %B, 10 + %add = add nsw i8 %x, %y + ret i8 %add +} + +; CHECK: @nopreserve4 +; CHECK: add i8 %A, %B +; CHECK: add i8 +define i8 @nopreserve4(i8 %A, i8 %B) nounwind { + %x = add nsw i8 %A, 10 + %y = add nsw i8 %B, 10 + %add = add nsw i8 %x, %y + ret i8 %add +} diff --git a/test/Transforms/InstCombine/ptr-int-cast.ll b/test/Transforms/InstCombine/ptr-int-cast.ll index ad11e430d9a93..9524d449dd8b0 100644 --- a/test/Transforms/InstCombine/ptr-int-cast.ll +++ b/test/Transforms/InstCombine/ptr-int-cast.ll @@ -5,22 +5,22 @@ define i1 @test1(i32 *%x) nounwind { entry: ; CHECK: test1 ; CHECK: ptrtoint i32* %x to i64 - %tmp = ptrtoint i32* %x to i1 - ret i1 %tmp + %0 = ptrtoint i32* %x to i1 + ret i1 %0 } define i32* @test2(i128 %x) nounwind { entry: ; CHECK: test2 -; CHECK: inttoptr i64 %tmp1 to i32* - %tmp = inttoptr i128 %x to i32* - ret i32* %tmp +; CHECK: inttoptr i64 %0 to i32* + %0 = inttoptr i128 %x to i32* + ret i32* %0 } ; PR3574 ; CHECK: f0 -; CHECK: %tmp = zext i32 %a0 to i64 -; CHECK: ret i64 %tmp +; CHECK: %1 = zext i32 %a0 to i64 +; CHECK: ret i64 %1 define i64 @f0(i32 %a0) nounwind { %t0 = inttoptr i32 %a0 to i8* %t1 = ptrtoint i8* %t0 to i64 diff --git a/test/Transforms/InstCombine/select.ll b/test/Transforms/InstCombine/select.ll index 4ca9bd2c07c08..46615613eb9c0 100644 --- a/test/Transforms/InstCombine/select.ll +++ b/test/Transforms/InstCombine/select.ll @@ -799,3 +799,13 @@ define i1 @test60(i32 %x, i1* %y) nounwind { ; CHECK: @test60 ; CHECK: select } + +@glbl = constant i32 10 +define i32 @test61(i32* %ptr) { + %A = load i32* %ptr + %B = icmp eq i32* %ptr, @glbl + %C = select i1 %B, i32 %A, i32 10 + ret i32 %C +; CHECK: @test61 +; CHECK: ret i32 10 +} diff --git a/test/Transforms/InstCombine/shift.ll b/test/Transforms/InstCombine/shift.ll index d9ac9cbfe9ee0..132d51a660bbe 100644 --- a/test/Transforms/InstCombine/shift.ll +++ b/test/Transforms/InstCombine/shift.ll @@ -525,5 +525,20 @@ define i32 @test43(i32 %a, i32 %b) nounwind { ; CHECK-NEXT: ret } - - +define i32 @test44(i32 %a) nounwind { + %y = shl nuw i32 %a, 1 + %z = shl i32 %y, 4 + ret i32 %z +; CHECK: @test44 +; CHECK-NEXT: %y = shl i32 %a, 5 +; CHECK-NEXT: ret i32 %y +} + +define i32 @test45(i32 %a) nounwind { + %y = lshr exact i32 %a, 1 + %z = lshr i32 %y, 4 + ret i32 %z +; CHECK: @test45 +; CHECK-NEXT: %y = lshr i32 %a, 5 +; CHECK-NEXT: ret i32 %y +} diff --git a/test/Transforms/InstCombine/vec_demanded_elts.ll b/test/Transforms/InstCombine/vec_demanded_elts.ll index e0188fe91aeb2..cc63371eded67 100644 --- a/test/Transforms/InstCombine/vec_demanded_elts.ll +++ b/test/Transforms/InstCombine/vec_demanded_elts.ll @@ -152,3 +152,14 @@ entry: ret <4 x i32> %0 } declare <4 x i32> @llvm.x86.sse41.pmovzxwd(<8 x i16>) nounwind readnone + +define <4 x float> @dead_shuffle_elt(<4 x float> %x, <2 x float> %y) nounwind { +entry: +; CHECK: define <4 x float> @dead_shuffle_elt +; CHECK: shufflevector <2 x float> %y, <2 x float> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef> + %shuffle.i = shufflevector <2 x float> %y, <2 x float> %y, <4 x i32> <i32 0, i32 1, i32 0, i32 1> + %shuffle9.i = shufflevector <4 x float> %x, <4 x float> %shuffle.i, <4 x i32> <i32 4, i32 5, i32 2, i32 3> + ret <4 x float> %shuffle9.i +} + + diff --git a/test/Transforms/InstCombine/vector-casts.ll b/test/Transforms/InstCombine/vector-casts.ll index e931dc79ef413..7bbf53c270f48 100644 --- a/test/Transforms/InstCombine/vector-casts.ll +++ b/test/Transforms/InstCombine/vector-casts.ll @@ -7,7 +7,7 @@ define <2 x i1> @test1(<2 x i64> %a) { ; CHECK: @test1 ; CHECK: and <2 x i64> %a, <i64 1, i64 1> -; CHECK: icmp ne <2 x i64> %tmp, zeroinitializer +; CHECK: icmp ne <2 x i64> %1, zeroinitializer } ; The ashr turns into an lshr. diff --git a/test/Transforms/InstCombine/volatile_store.ll b/test/Transforms/InstCombine/volatile_store.ll index 5316bd772e13a..0518e5aa02629 100644 --- a/test/Transforms/InstCombine/volatile_store.ll +++ b/test/Transforms/InstCombine/volatile_store.ll @@ -1,5 +1,5 @@ -; RUN: opt < %s -instcombine -S | grep {volatile store} -; RUN: opt < %s -instcombine -S | grep {volatile load} +; RUN: opt < %s -instcombine -S | grep {store volatile} +; RUN: opt < %s -instcombine -S | grep {load volatile} @x = weak global i32 0 ; <i32*> [#uses=2] diff --git a/test/Transforms/InstSimplify/2011-09-05-InsertExtractValue.ll b/test/Transforms/InstSimplify/2011-09-05-InsertExtractValue.ll new file mode 100644 index 0000000000000..d10c61fe2cf77 --- /dev/null +++ b/test/Transforms/InstSimplify/2011-09-05-InsertExtractValue.ll @@ -0,0 +1,29 @@ +; RUN: opt < %s -instsimplify -S | FileCheck %s + +declare void @bar() + +define void @test1() { +entry: + invoke void @bar() to label %cont unwind label %lpad +cont: + ret void +lpad: + %ex = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @__gxx_personality_v0 cleanup + %exc_ptr = extractvalue { i8*, i32 } %ex, 0 + %filter = extractvalue { i8*, i32 } %ex, 1 + %exc_ptr2 = insertvalue { i8*, i32 } undef, i8* %exc_ptr, 0 + %filter2 = insertvalue { i8*, i32 } %exc_ptr2, i32 %filter, 1 + resume { i8*, i32 } %filter2 +; CHECK: @test1 +; CHECK-NOT: extractvalue +; CHECK-NOT: insertvalue +} + +declare i32 @__gxx_personality_v0(i32, i64, i8*, i8*) + +define { i8, i32 } @test2({ i8*, i32 } %x) { + %ex = extractvalue { i8*, i32 } %x, 1 + %ins = insertvalue { i8, i32 } undef, i32 %ex, 1 + ret { i8, i32 } %ins +; CHECK: @test2 +} diff --git a/test/Transforms/InstSimplify/compare.ll b/test/Transforms/InstSimplify/compare.ll index d2c564f567b44..2cbd641a7426f 100644 --- a/test/Transforms/InstSimplify/compare.ll +++ b/test/Transforms/InstSimplify/compare.ll @@ -283,17 +283,6 @@ define i1 @srem3(i16 %X, i32 %Y) { ret i1 %E } -; CHECK: @srem4 -; CHECK-NEXT: ret i1 false -define i1 @srem4(i16 %X, i32 %Y) { - %A = zext i16 %X to i32 - %B = or i32 2147483648, %A - %C = sub nsw i32 %A, %B - %D = srem i32 %C, %Y - %E = icmp slt i32 %D, 0 - ret i1 %E -} - define i1 @udiv1(i32 %X) { ; CHECK: @udiv1 %A = udiv i32 %X, 1000000 diff --git a/test/Transforms/JumpThreading/no-irreducible-loops.ll b/test/Transforms/JumpThreading/no-irreducible-loops.ll index 97276b039aaab..7c7fe3929ae02 100644 --- a/test/Transforms/JumpThreading/no-irreducible-loops.ll +++ b/test/Transforms/JumpThreading/no-irreducible-loops.ll @@ -1,5 +1,5 @@ ; RUN: opt < %s -jump-threading -loop-rotate -instcombine -indvars -loop-unroll -simplifycfg -S -verify-dom-info -verify-loop-info > %t -; RUN: grep {volatile store} %t | count 3 +; RUN: grep {store volatile} %t | count 3 ; RUN: not grep {br label} %t ; Jump threading should not prevent this loop from being unrolled. diff --git a/test/Transforms/LCSSA/invoke-dest.ll b/test/Transforms/LCSSA/invoke-dest.ll index 454715089c3b6..22b320296afd8 100644 --- a/test/Transforms/LCSSA/invoke-dest.ll +++ b/test/Transforms/LCSSA/invoke-dest.ll @@ -110,12 +110,18 @@ bb106: ; preds = %invcont105, %bb61 to label %.noexc unwind label %lpad119 ; <i8*> [#uses=1] lpad: ; preds = %_ZN7cObjectnwEj.exit + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup br label %Unwind lpad119: ; preds = %bb106, %invcont104, %invcont103, %bb102, %bb49, %bb34, %bb12, %invcont10, %invcont9, %bb8 + %exn119 = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup unreachable lpad123: ; preds = %.noexc + %exn123 = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup %tmp5 = icmp eq i8* %tmp4, null ; <i1> [#uses=1] br i1 %tmp5, label %Unwind, label %bb.i2 @@ -126,6 +132,8 @@ Unwind: ; preds = %bb.i2, %lpad123, %lpad unreachable } +declare i32 @__gxx_personality_v0(...) + declare void @_ZN8EtherBus8tokenizeEPKcRSt6vectorIdSaIdEE(i8* nocapture, i8*, i8*) declare i8* @_Znaj(i32) diff --git a/test/Transforms/LICM/2007-05-22-VolatileSink.ll b/test/Transforms/LICM/2007-05-22-VolatileSink.ll index c12e13beccf59..17383c2ebb631 100644 --- a/test/Transforms/LICM/2007-05-22-VolatileSink.ll +++ b/test/Transforms/LICM/2007-05-22-VolatileSink.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -licm -S | grep {volatile store} +; RUN: opt < %s -licm -S | grep {store volatile} ; PR1435 target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64" target triple = "i686-apple-darwin8" diff --git a/test/Transforms/LICM/2011-04-06-HoistMissedASTUpdate.ll b/test/Transforms/LICM/2011-04-06-HoistMissedASTUpdate.ll index 5774f587f1c3d..fd114f4ccc114 100644 --- a/test/Transforms/LICM/2011-04-06-HoistMissedASTUpdate.ll +++ b/test/Transforms/LICM/2011-04-06-HoistMissedASTUpdate.ll @@ -15,7 +15,7 @@ for.body4.lr.ph: br label %for.body4 ; CHECK: for.body4: -; CHECK: volatile load i16* @g_39 +; CHECK: load volatile i16* @g_39 for.body4: %l_612.11 = phi i32* [ undef, %for.body4.lr.ph ], [ %call19, %for.body4 ] diff --git a/test/Transforms/LICM/atomics.ll b/test/Transforms/LICM/atomics.ll new file mode 100644 index 0000000000000..3902152ba2e5e --- /dev/null +++ b/test/Transforms/LICM/atomics.ll @@ -0,0 +1,79 @@ +; RUN: opt < %s -S -basicaa -licm | FileCheck %s + +; Check that we can hoist unordered loads +define i32 @test1(i32* nocapture %y) nounwind uwtable ssp { +entry: + br label %loop + +loop: + %i = phi i32 [ %inc, %loop ], [ 0, %entry ] + %val = load atomic i32* %y unordered, align 4 + %inc = add nsw i32 %i, 1 + %exitcond = icmp eq i32 %inc, %val + br i1 %exitcond, label %end, label %loop + +end: + ret i32 %val +; CHECK: define i32 @test1( +; CHECK: load atomic +; CHECK-NEXT: br label %loop +} + +; Check that we don't sink/hoist monotonic loads +; (Strictly speaking, it's not forbidden, but it's supposed to be possible to +; use monotonic for spinlock-like constructs.) +define i32 @test2(i32* nocapture %y) nounwind uwtable ssp { +entry: + br label %loop + +loop: + %val = load atomic i32* %y monotonic, align 4 + %exitcond = icmp ne i32 %val, 0 + br i1 %exitcond, label %end, label %loop + +end: + ret i32 %val +; CHECK: define i32 @test2( +; CHECK: load atomic +; CHECK-NEXT: %exitcond = icmp ne +; CHECK-NEXT: br i1 %exitcond, label %end, label %loop +} + +; Check that we hoist unordered around monotonic. +; (The noalias shouldn't be necessary in theory, but LICM isn't quite that +; smart yet.) +define i32 @test3(i32* nocapture noalias %x, i32* nocapture %y) nounwind uwtable ssp { +entry: + br label %loop + +loop: + %vala = load atomic i32* %y monotonic, align 4 + %valb = load atomic i32* %x unordered, align 4 + %exitcond = icmp ne i32 %vala, %valb + br i1 %exitcond, label %end, label %loop + +end: + ret i32 %vala +; CHECK: define i32 @test3( +; CHECK: load atomic i32* %x unordered +; CHECK-NEXT: br label %loop +} + +; Don't try to "sink" unordered stores yet; it is legal, but the machinery +; isn't there. +define i32 @test4(i32* nocapture noalias %x, i32* nocapture %y) nounwind uwtable ssp { +entry: + br label %loop + +loop: + %vala = load atomic i32* %y monotonic, align 4 + store atomic i32 %vala, i32* %x unordered, align 4 + %exitcond = icmp ne i32 %vala, 0 + br i1 %exitcond, label %end, label %loop + +end: + ret i32 %vala +; CHECK: define i32 @test4( +; CHECK: load atomic i32* %y monotonic +; CHECK-NEXT: store atomic +} diff --git a/test/Transforms/LICM/scalar-promote-memmodel.ll b/test/Transforms/LICM/scalar-promote-memmodel.ll new file mode 100644 index 0000000000000..23d70f51351a5 --- /dev/null +++ b/test/Transforms/LICM/scalar-promote-memmodel.ll @@ -0,0 +1,37 @@ +; RUN: opt < %s -basicaa -licm -S | FileCheck %s + +; Make sure we don't hoist a conditionally-executed store out of the loop; +; it would violate the concurrency memory model + +@g = common global i32 0, align 4 + +define void @bar(i32 %n, i32 %b) nounwind uwtable ssp { +entry: + br label %for.cond + +for.cond: ; preds = %for.inc, %entry + %i.0 = phi i32 [ 0, %entry ], [ %inc5, %for.inc ] + %cmp = icmp slt i32 %i.0, %n + br i1 %cmp, label %for.body, label %for.end + +for.body: ; preds = %for.cond + %tobool = icmp eq i32 %b, 0 + br i1 %tobool, label %for.inc, label %if.then + +if.then: ; preds = %for.body + %tmp3 = load i32* @g, align 4 + %inc = add nsw i32 %tmp3, 1 + store i32 %inc, i32* @g, align 4 + br label %for.inc + +; CHECK: load i32* +; CHECK-NEXT: add +; CHECK-NEXT: store i32 + +for.inc: ; preds = %for.body, %if.then + %inc5 = add nsw i32 %i.0, 1 + br label %for.cond + +for.end: ; preds = %for.cond + ret void +} diff --git a/test/Transforms/LICM/scalar_promote.ll b/test/Transforms/LICM/scalar_promote.ll index d8acdc1a3ad75..9aefc4f87eac8 100644 --- a/test/Transforms/LICM/scalar_promote.ll +++ b/test/Transforms/LICM/scalar_promote.ll @@ -65,7 +65,7 @@ Loop: br i1 true, label %Out, label %Loop ; CHECK: Loop: -; CHECK-NEXT: volatile load +; CHECK-NEXT: load volatile Out: ; preds = %Loop ret void diff --git a/test/Transforms/LoopDeletion/2008-05-06-Phi.ll b/test/Transforms/LoopDeletion/2008-05-06-Phi.ll index 4fc6378ee254a..ff6a30d3a3427 100644 --- a/test/Transforms/LoopDeletion/2008-05-06-Phi.ll +++ b/test/Transforms/LoopDeletion/2008-05-06-Phi.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -inline -tailduplicate -instcombine -jump-threading -licm -loop-unswitch -instcombine -indvars -loop-deletion -gvn -simplifycfg -verify -disable-output +; RUN: opt < %s -inline -instcombine -jump-threading -licm -loop-unswitch -instcombine -indvars -loop-deletion -gvn -simplifycfg -verify -disable-output 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" diff --git a/test/Transforms/LoopIdiom/basic.ll b/test/Transforms/LoopIdiom/basic.ll index 969541813aef4..46ab7e5542b6b 100644 --- a/test/Transforms/LoopIdiom/basic.ll +++ b/test/Transforms/LoopIdiom/basic.ll @@ -62,8 +62,8 @@ for.end: ; preds = %for.body, %entry ret void ; CHECK: @test2 ; CHECK: br i1 %cmp10, -; CHECK: %tmp = mul i64 %Size, 4 -; CHECK: call void @llvm.memset.p0i8.i64(i8* %Base1, i8 1, i64 %tmp, i32 4, i1 false) +; CHECK: %0 = mul i64 %Size, 4 +; CHECK: call void @llvm.memset.p0i8.i64(i8* %Base1, i8 1, i64 %0, i32 4, i1 false) ; CHECK-NOT: store } diff --git a/test/Transforms/LoopSimplify/2003-08-15-PreheadersFail.ll b/test/Transforms/LoopSimplify/2003-08-15-PreheadersFail.ll index 11be6941d8b82..73f0813285bac 100644 --- a/test/Transforms/LoopSimplify/2003-08-15-PreheadersFail.ll +++ b/test/Transforms/LoopSimplify/2003-08-15-PreheadersFail.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -tailduplicate -instcombine -simplifycfg -licm -disable-output +; RUN: opt < %s -instcombine -simplifycfg -licm -disable-output target datalayout = "e-p:32:32" @yy_base = external global [787 x i16] ; <[787 x i16]*> [#uses=1] @yy_state_ptr = external global i32* ; <i32**> [#uses=3] diff --git a/test/Transforms/LoopSimplify/2007-10-28-InvokeCrash.ll b/test/Transforms/LoopSimplify/2007-10-28-InvokeCrash.ll index e7d0f8470ec96..e91d141cc6fff 100644 --- a/test/Transforms/LoopSimplify/2007-10-28-InvokeCrash.ll +++ b/test/Transforms/LoopSimplify/2007-10-28-InvokeCrash.ll @@ -1,892 +1,29 @@ -; RUN: opt < %s -loop-simplify -disable-output +; RUN: llvm-as < %s | opt -loop-simplify -disable-output ; PR1752 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-s0:0:64-f80:32:32" target triple = "i686-pc-mingw32" - %struct.BigInt = type { %"struct.std::vector<ulong,std::allocator<ulong> >" } - %struct.Fibonacci = type { %"struct.std::vector<BigInt,std::allocator<BigInt> >" } - %struct.__false_type = type <{ i8 }> - %"struct.__gnu_cxx::__normal_iterator<BigInt*,std::vector<BigInt, std::allocator<BigInt> > >" = type { %struct.BigInt* } - %"struct.std::_Vector_base<BigInt,std::allocator<BigInt> >" = type { %"struct.std::_Vector_base<BigInt,std::allocator<BigInt> >::_Vector_impl" } - %"struct.std::_Vector_base<BigInt,std::allocator<BigInt> >::_Vector_impl" = type { %struct.BigInt*, %struct.BigInt*, %struct.BigInt* } - %"struct.std::_Vector_base<ulong,std::allocator<ulong> >" = type { %"struct.std::_Vector_base<ulong,std::allocator<ulong> >::_Vector_impl" } - %"struct.std::_Vector_base<ulong,std::allocator<ulong> >::_Vector_impl" = type { i32*, i32*, i32* } - %"struct.std::basic_ios<char,std::char_traits<char> >" = type { %"struct.std::ios_base", %"struct.std::basic_ostream<char,std::char_traits<char> >"*, i8, i8, %"struct.std::basic_streambuf<char,std::char_traits<char> >"*, %"struct.std::ctype<char>"*, %"struct.std::num_get<char,std::istreambuf_iterator<char, std::char_traits<char> > >"*, %"struct.std::num_get<char,std::istreambuf_iterator<char, std::char_traits<char> > >"* } - %"struct.std::basic_ostream<char,std::char_traits<char> >" = type { i32 (...)**, %"struct.std::basic_ios<char,std::char_traits<char> >" } - %"struct.std::basic_streambuf<char,std::char_traits<char> >" = type { i32 (...)**, i8*, i8*, i8*, i8*, i8*, i8*, %"struct.std::locale" } - %"struct.std::basic_string<char,std::char_traits<char>,std::allocator<char> >" = type { %"struct.std::basic_string<char,std::char_traits<char>,std::allocator<char> >::_Alloc_hider" } - %"struct.std::basic_string<char,std::char_traits<char>,std::allocator<char> >::_Alloc_hider" = type { i8* } - %"struct.std::basic_stringbuf<char,std::char_traits<char>,std::allocator<char> >" = type { %"struct.std::basic_streambuf<char,std::char_traits<char> >", i32, %"struct.std::basic_string<char,std::char_traits<char>,std::allocator<char> >" } - %"struct.std::ctype<char>" = type { %"struct.std::locale::facet", i32*, i8, i32*, i32*, i16*, i8, [256 x i8], [256 x i8], i8 } - %"struct.std::ios_base" = type { i32 (...)**, i32, i32, i32, i32, i32, %"struct.std::ios_base::_Callback_list"*, %"struct.std::ios_base::_Words", [8 x %"struct.std::ios_base::_Words"], i32, %"struct.std::ios_base::_Words"*, %"struct.std::locale" } - %"struct.std::ios_base::_Callback_list" = type { %"struct.std::ios_base::_Callback_list"*, void (i32, %"struct.std::ios_base"*, i32)*, i32, i32 } - %"struct.std::ios_base::_Words" = type { i8*, i32 } - %"struct.std::locale" = type { %"struct.std::locale::_Impl"* } - %"struct.std::locale::_Impl" = type { i32, %"struct.std::locale::facet"**, i32, %"struct.std::locale::facet"**, i8** } - %"struct.std::locale::facet" = type { i32 (...)**, i32 } - %"struct.std::num_get<char,std::istreambuf_iterator<char, std::char_traits<char> > >" = type { %"struct.std::locale::facet" } - %"struct.std::ostringstream" = type { [4 x i8], %"struct.std::basic_stringbuf<char,std::char_traits<char>,std::allocator<char> >", %"struct.std::basic_ios<char,std::char_traits<char> >" } - %"struct.std::vector<BigInt,std::allocator<BigInt> >" = type { %"struct.std::_Vector_base<BigInt,std::allocator<BigInt> >" } - %"struct.std::vector<ulong,std::allocator<ulong> >" = type { %"struct.std::_Vector_base<ulong,std::allocator<ulong> >" } -@.str13 = external constant [6 x i8] ; <[6 x i8]*> [#uses=1] -@.str14 = external constant [5 x i8] ; <[5 x i8]*> [#uses=1] -@.str15 = external constant [2 x i8] ; <[2 x i8]*> [#uses=1] -@_ZSt4cout = external global %"struct.std::basic_ostream<char,std::char_traits<char> >" ; <%"struct.std::basic_ostream<char,std::char_traits<char> >"*> [#uses=1] -declare void @_ZN9Fibonacci10get_numberEj(%struct.BigInt* sret , %struct.Fibonacci*, i32) - -declare %"struct.std::basic_ostream<char,std::char_traits<char> >"* @_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc(%"struct.std::basic_ostream<char,std::char_traits<char> >"*, i8*) - -declare void @_ZNSsD1Ev(%"struct.std::basic_string<char,std::char_traits<char>,std::allocator<char> >"*) - -declare %"struct.std::basic_ostream<char,std::char_traits<char> >"* @_ZNSolsEm(%"struct.std::basic_ostream<char,std::char_traits<char> >"*, i32) - -declare void @_ZNKSt19basic_ostringstreamIcSt11char_traitsIcESaIcEE3strEv(%"struct.std::basic_string<char,std::char_traits<char>,std::allocator<char> >"* sret , %"struct.std::ostringstream"*) - -declare %"struct.std::basic_ostream<char,std::char_traits<char> >"* @_ZStlsIcSt11char_traitsIcESaIcEERSt13basic_ostreamIT_T0_ES7_RKSbIS4_S5_T1_E(%"struct.std::basic_ostream<char,std::char_traits<char> >"*, %"struct.std::basic_string<char,std::char_traits<char>,std::allocator<char> >"*) - -declare void @_ZNSt19basic_ostringstreamIcSt11char_traitsIcESaIcEED1Ev(%"struct.std::ostringstream"*) - -declare %"struct.std::basic_ostream<char,std::char_traits<char> >"* @___ZlsRSoRK6BigInt___ZN9__gnu_cxx13new_allocatorI6BigIntE10deallocateEPS1_j(i32, %"struct.std::basic_ostream<char,std::char_traits<char> >"*, %struct.BigInt*, %struct.__false_type*, i32) - -declare void @___ZNSt12_Vector_baseI6BigIntSaIS0_EE13_M_deallocateEPS0_j___ZNSt12_Vector_baseI6BigIntSaIS0_EED2Ev___ZNSt6vectorI6BigIntSaIS0_EEC1ERKS1_(%"struct.std::_Vector_base<BigInt,std::allocator<BigInt> >"*, i32, %struct.BigInt*, i32, %"struct.std::vector<BigInt,std::allocator<BigInt> >"*, %struct.__false_type*) - -declare i32 @___ZN9__gnu_cxxmiIPK6BigIntS3_St6vectorIS1_SaIS1_EEEENS_17__normal_iteratorIT_T1_E15difference_typeERKSA_RKNS7_IT0_S9_EE___ZNKSt6vectorI6BigIntSaIS0_EE4sizeEv___ZNK9Fibonacci16show_all_numbersEv___ZNKSt6vectorI6BigIntSaIS0_EE8capacityEv(%"struct.__gnu_cxx::__normal_iterator<BigInt*,std::vector<BigInt, std::allocator<BigInt> > >"*, %"struct.__gnu_cxx::__normal_iterator<BigInt*,std::vector<BigInt, std::allocator<BigInt> > >"*, %"struct.std::vector<BigInt,std::allocator<BigInt> >"*, i32, %struct.Fibonacci*) - -declare %struct.BigInt* @___ZNSt6vectorI6BigIntSaIS0_EEixEj___ZNSt6vectorI6BigIntSaIS0_EE3endEv(%"struct.std::vector<BigInt,std::allocator<BigInt> >"*, i32, i32) - -declare %"struct.__gnu_cxx::__normal_iterator<BigInt*,std::vector<BigInt, std::allocator<BigInt> > >"* @___ZN9__gnu_cxx17__normal_iteratorIP6BigIntSt6vectorIS1_SaIS1_EEEppEv___ZNSt6vectorImSaImEED1Ev___ZN6BigIntD1Ev___ZN9__gnu_cxx13new_allocatorI6BigIntE7destroyEPS1____ZSt8_DestroyIP6BigIntSaIS0_EEvT_S3_T0_(i32, %"struct.__gnu_cxx::__normal_iterator<BigInt*,std::vector<BigInt, std::allocator<BigInt> > >"*, %"struct.std::vector<ulong,std::allocator<ulong> >"*, %struct.BigInt*, %struct.__false_type*, %struct.BigInt*, %struct.__false_type* noalias ) - -declare void @___ZNSt6vectorI6BigIntSaIS0_EED1Ev___ZN9FibonacciD1Ev___ZNSt6vectorImSaImEEC1ERKS0_(i32, %"struct.std::vector<BigInt,std::allocator<BigInt> >"*, %struct.Fibonacci*, %"struct.std::vector<ulong,std::allocator<ulong> >"*, %struct.__false_type*) - -define void @___ZN9FibonacciC1Ej___ZN9Fibonacci11show_numberEm(%struct.Fibonacci* %this_this, i32 %functionID, i32 %n_i_n_i) { +define void @func() { bb_init: br label %bb_main -bb_main: ; preds = %meshBB349, %meshBB348, %meshBB347, %meshBB346, %meshBB345.unwinddest, %meshBB345, %meshBB344, %meshBB343, %meshBB342, %meshBB341, %meshBB340.normaldest, %meshBB340, %meshBB339, %invcont17.normaldest.normaldest, %invcont17.normaldest, %meshBB338.unwinddest, %meshBB338, %meshBB337.unwinddest, %meshBB337, %meshBB336.unwinddest, %meshBB336, %meshBB335, %meshBB334, %meshBB333, %meshBB332, %meshBB331, %meshBB330.normaldest, %meshBB330, %meshBB329.normaldest, %meshBB329, %meshBB328, %meshBB327, %meshBB326, %meshBB325.unwinddest, %meshBB325, %meshBB324, %meshBB323.normaldest, %meshBB323, %meshBB322.unwinddest, %meshBB322, %meshBB321, %meshBB320.unwinddest, %meshBB320, %meshBB319.unwinddest, %meshBB319, %meshBB318.unwinddest, %meshBB318, %meshBB317, %meshBB37.fragment, %meshBB37.unwinddest, %meshBB37, %meshBB36.fragment, %meshBB36, %meshBB35.fragment, %meshBB35, %meshBB34.fragment, %meshBB34, %meshBB33.fragment, %meshBB33, %meshBB32.fragment, %meshBB32, %meshBB31.fragment, %meshBB31, %meshBB30.fragment, %meshBB30.normaldest, %meshBB30, %meshBB29.fragment, %meshBB29.unwinddest, %meshBB29, %meshBB28.fragment, %meshBB28.unwinddest, %meshBB28, %meshBB27.fragment, %meshBB27, %meshBB26.fragment, %meshBB26.normaldest, %meshBB26, %meshBB25.fragment, %meshBB25, %meshBB24.fragment, %meshBB24.unwinddest, %meshBB24, %meshBB23.fragment, %meshBB23.normaldest, %meshBB23, %entry1.fragment.normaldest.normaldest, %entry1.fragment.normaldest, %meshBB22.fragment, %meshBB22.unwinddest, %meshBB22, %meshBB.fragment, %meshBB.unwinddest, %meshBB, %Unwind20, %unwind78.Unwind_crit_edge, %unwind78.fragment.fragment, %unwind78.fragment, %unwind78.fragment316, %unwind78, %invcont70, %unwind66.Unwind_crit_edge, %unwind66.fragment.fragment, %unwind66.fragment, %unwind66.fragment315, %unwind66, %unwind53.nofilter_crit_edge, %unwind53.fragment.fragment, %unwind53.fragment, %unwind53.fragment314, %unwind53, %nofilter.Unwind_crit_edge.normaldest, %nofilter.Unwind_crit_edge, %nofilter, %unwind43.nofilter_crit_edge, %unwind43.fragment.fragment, %unwind43.fragment, %unwind43.fragment313, %unwind43, %invcont41.normaldest, %invcont41, %unwind37.nofilter_crit_edge, %unwind37, %invcont36, %invcont33.unwind_crit_edge.unwinddest, %invcont33.unwind_crit_edge, %invcont30.unwind_crit_edge.unwinddest, %invcont30.unwind_crit_edge, %invcont30.normaldest, %invcont30, %invcont28.unwind_crit_edge, %invcont28.normaldest, %invcont28, %invcont25.unwind_crit_edge.unwinddest, %invcont25.unwind_crit_edge, %invcont25, %invcont22.unwind_crit_edge, %invcont22, %invcont17.unwind_crit_edge, %invcont17, %cond_next.unwind_crit_edge, %cond_next, %invcont12.cond_next_crit_edge, %invcont12.unwind_crit_edge, %invcont12, %cond_true.unwind_crit_edge.unwinddest, %cond_true.unwind_crit_edge, %invcont.cond_next_crit_edge, %invcont16.fragment, %invcont16, %unwind11.fragment, %unwind11, %entry.unwind_crit_edge, %entry1.fragment, %entry1.fragment312, %entry1, %Unwind, %unwind20.Unwind_crit_edge, %unwind20.fragment.fragment, %unwind20.fragment, %unwind20.fragment311, %unwind20, %invcont15, %invcont14.unwind10_crit_edge, %invcont14, %unwind10.Unwind_crit_edge, %unwind10.fragment, %unwind10.fragment310, %unwind10, %invcont.unwind10_crit_edge, %invcont, %unwind.fragment, %unwind, %entry.fragment, %entry.fragment309, %entry, %NewDefault, %LeafBlock, %LeafBlock914, %NodeBlock, %comb_entry.fragment, %old_entry, %bb_init - switch i32 0, label %old_entry [ - i32 2739, label %invcont28.fragment - i32 2688, label %meshBB28.fragment - i32 1318, label %meshBB32.fragment - i32 2964, label %unwind53.fragment.fragment - i32 824, label %unwind78.fragment.fragment - i32 1983, label %meshBB33.fragment - i32 2582, label %invcont30.fragment - i32 2235, label %meshBB36.fragment - i32 1275, label %meshBB343 - i32 2719, label %invcont.fragment - i32 1500, label %entry1.fragment.fragment - i32 815, label %unwind11.fragment - i32 1051, label %entry - i32 2342, label %unwind - i32 1814, label %invcont - i32 315, label %invcont.unwind10_crit_edge - i32 2422, label %unwind10 - i32 2663, label %unwind10.Unwind_crit_edge - i32 266, label %invcont14 - i32 367, label %invcont14.unwind10_crit_edge - i32 2242, label %invcont15 - i32 452, label %unwind20 - i32 419, label %invcont.cond_next_crit_edge - i32 181, label %cond_true - i32 2089, label %unwind20.Unwind_crit_edge - i32 633, label %filter - i32 455, label %Unwind - i32 2016, label %entry1 - i32 263, label %invcont33.unwind_crit_edge - i32 2498, label %invcont36 - i32 2992, label %unwind37 - i32 616, label %entry.unwind_crit_edge - i32 622, label %unwind11 - i32 875, label %invcont16 - i32 766, label %unwind53.nofilter_crit_edge - i32 668, label %filter62 - i32 2138, label %unwind66 - i32 713, label %unwind66.Unwind_crit_edge - i32 1422, label %invcont70 - i32 1976, label %cond_true.unwind_crit_edge - i32 1263, label %invcont12 - i32 2453, label %invcont12.unwind_crit_edge - i32 2876, label %invcont12.cond_next_crit_edge - i32 2271, label %cond_next - i32 2938, label %cond_next.unwind_crit_edge - i32 1082, label %invcont17 - i32 531, label %invcont17.unwind_crit_edge - i32 111, label %invcont22 - i32 1935, label %invcont22.unwind_crit_edge - i32 2004, label %invcont25 - i32 1725, label %invcont25.unwind_crit_edge - i32 1701, label %invcont28 - i32 957, label %invcont28.unwind_crit_edge - i32 165, label %invcont30 - i32 899, label %invcont30.unwind_crit_edge - i32 1092, label %invcont33 - i32 2869, label %unwind37.nofilter_crit_edge - i32 203, label %invcont41 - i32 693, label %unwind43 - i32 2895, label %unwind43.nofilter_crit_edge - i32 1174, label %invcont47 - i32 1153, label %filter19 - i32 2304, label %nofilter - i32 848, label %nofilter.Unwind_crit_edge - i32 1207, label %unwind53 - i32 2848, label %filter75 - i32 59, label %unwind78 - i32 1213, label %unwind78.Unwind_crit_edge - i32 2199, label %filter87 - i32 1268, label %Unwind20 - i32 743, label %old_entry - i32 1276, label %meshBB319 - i32 1619, label %meshBB320 - i32 2047, label %meshBB331 - i32 2828, label %meshBB23.fragment - i32 2530, label %meshBB332 - i32 1389, label %meshBB318 - i32 1450, label %meshBB317 - i32 1416, label %meshBB31.fragment - i32 82, label %meshBB322 - i32 853, label %unwind78.fragment316 - i32 107, label %meshBB24.fragment - i32 1200, label %meshBB37.fragment - i32 605, label %unwind53.fragment314 - i32 209, label %meshBB29.fragment - i32 1513, label %meshBB27.fragment - i32 1542, label %meshBB35.fragment - i32 1873, label %meshBB348 - i32 472, label %meshBB325 - i32 2615, label %meshBB22.fragment - i32 359, label %meshBB.fragment - i32 2467, label %Unwind20.fragment - i32 1671, label %unwind66.fragment.fragment - i32 1006, label %meshBB25.fragment - i32 1243, label %meshBB333 - i32 2795, label %unwind43.fragment313 - i32 1591, label %meshBB335 - i32 773, label %meshBB341 - i32 2440, label %cond_next.fragment - i32 487, label %meshBB326 - i32 394, label %meshBB324 - i32 14, label %invcont16.fragment - i32 574, label %entry1.fragment312 - i32 1453, label %meshBB35 - i32 345, label %entry1.fragment - i32 2951, label %unwind20.fragment - i32 1960, label %meshBB31 - i32 2163, label %meshBB32 - i32 1978, label %Unwind.fragment - i32 1559, label %unwind20.fragment.fragment - i32 950, label %unwind10.fragment - i32 1724, label %unwind53.fragment - i32 514, label %meshBB36 - i32 1928, label %unwind10.fragment.fragment - i32 1266, label %meshBB26 - i32 3148, label %unwind20.fragment311 - i32 1581, label %unwind43.fragment - i32 1829, label %meshBB34 - i32 1472, label %meshBB28 - i32 2657, label %unwind66.fragment - i32 2169, label %meshBB22 - i32 2619, label %meshBB - i32 1397, label %entry.fragment - i32 231, label %invcont41.fragment - i32 2557, label %meshBB338 - i32 2387, label %meshBB30.fragment - i32 2927, label %meshBB340 - i32 2331, label %meshBB321 - i32 47, label %meshBB328 - i32 1753, label %meshBB342 - i32 2074, label %meshBB323 - i32 2128, label %meshBB334 - i32 2396, label %meshBB337 - i32 1811, label %meshBB29 - i32 1113, label %meshBB27 - i32 2232, label %unwind10.fragment310 - i32 804, label %meshBB24 - i32 3099, label %meshBB30 - i32 564, label %meshBB33 - i32 1359, label %unwind.fragment - i32 1906, label %entry.fragment309 - i32 2644, label %entry.fragment.fragment - i32 134, label %entry1.fragment.normaldest - i32 2767, label %comb_entry.fragment - i32 2577, label %meshBB25 - i32 3128, label %meshBB37 - i32 2360, label %meshBB23 - i32 286, label %unwind78.fragment - i32 976, label %meshBB346 - i32 2412, label %meshBB339 - i32 876, label %meshBB345 - i32 3078, label %meshBB329 - i32 1297, label %meshBB347 - i32 3051, label %meshBB336 - i32 1342, label %meshBB344 - i32 728, label %meshBB330 - i32 1778, label %meshBB349 - i32 2784, label %meshBB327 - i32 1854, label %meshBB26.fragment - i32 1025, label %meshBB34.fragment - i32 2139, label %unwind43.fragment.fragment - i32 2217, label %nofilter.fragment - i32 665, label %invcont12.fragment - i32 316, label %invcont22.fragment - i32 1467, label %unwind66.fragment315 - i32 3018, label %unwind37.fragment - i32 1123, label %invcont17.normaldest - i32 2104, label %NewDefault - i32 1639, label %LeafBlock - i32 925, label %LeafBlock914 - i32 2880, label %NodeBlock - ] - -old_entry: ; preds = %bb_main, %bb_main - br label %bb_main - -comb_entry.fragment: ; preds = %bb_main - br label %bb_main - -NodeBlock: ; preds = %bb_main - br label %bb_main - -LeafBlock914: ; preds = %bb_main - br label %bb_main - -LeafBlock: ; preds = %bb_main - br label %bb_main - -NewDefault: ; preds = %bb_main - br label %bb_main - -entry: ; preds = %bb_main - br label %bb_main - -entry.fragment309: ; preds = %bb_main - br label %bb_main - -entry.fragment: ; preds = %bb_main - br label %bb_main - -entry.fragment.fragment: ; preds = %bb_main - invoke void @___ZNSt12_Vector_baseI6BigIntSaIS0_EE13_M_deallocateEPS0_j___ZNSt12_Vector_baseI6BigIntSaIS0_EED2Ev___ZNSt6vectorI6BigIntSaIS0_EEC1ERKS1_( %"struct.std::_Vector_base<BigInt,std::allocator<BigInt> >"* null, i32 28, %struct.BigInt* null, i32 0, %"struct.std::vector<BigInt,std::allocator<BigInt> >"* null, %struct.__false_type* null ) - to label %meshBB340 unwind label %meshBB325 - -unwind: ; preds = %bb_main - br label %bb_main - -unwind.fragment: ; preds = %bb_main - br label %bb_main - -invcont: ; preds = %bb_main - br label %bb_main - -invcont.fragment: ; preds = %bb_main - invoke void @_ZN9Fibonacci10get_numberEj( %struct.BigInt* sret null , %struct.Fibonacci* %this_this, i32 %n_i_n_i ) - to label %invcont14 unwind label %meshBB37 - -invcont.unwind10_crit_edge: ; preds = %bb_main - br label %bb_main - -unwind10: ; preds = %bb_main - br label %bb_main - -unwind10.fragment310: ; preds = %bb_main - br label %bb_main - -unwind10.fragment: ; preds = %bb_main - br label %bb_main - -unwind10.fragment.fragment: ; preds = %bb_main - invoke void @___ZNSt6vectorI6BigIntSaIS0_EED1Ev___ZN9FibonacciD1Ev___ZNSt6vectorImSaImEEC1ERKS0_( i32 57, %"struct.std::vector<BigInt,std::allocator<BigInt> >"* null, %struct.Fibonacci* null, %"struct.std::vector<ulong,std::allocator<ulong> >"* null, %struct.__false_type* null ) - to label %meshBB329 unwind label %meshBB24 - -unwind10.Unwind_crit_edge: ; preds = %bb_main - br label %bb_main - -invcont14: ; preds = %invcont.fragment, %bb_main - br label %bb_main - -invcont14.normaldest: ; No predecessors! - invoke %"struct.__gnu_cxx::__normal_iterator<BigInt*,std::vector<BigInt, std::allocator<BigInt> > >"* @___ZN9__gnu_cxx17__normal_iteratorIP6BigIntSt6vectorIS1_SaIS1_EEEppEv___ZNSt6vectorImSaImEED1Ev___ZN6BigIntD1Ev___ZN9__gnu_cxx13new_allocatorI6BigIntE7destroyEPS1____ZSt8_DestroyIP6BigIntSaIS0_EEvT_S3_T0_( i32 14, %"struct.__gnu_cxx::__normal_iterator<BigInt*,std::vector<BigInt, std::allocator<BigInt> > >"* null, %"struct.std::vector<ulong,std::allocator<ulong> >"* null, %struct.BigInt* null, %struct.__false_type* null, %struct.BigInt* null, %struct.__false_type* noalias null ) - to label %invcont15 unwind label %meshBB345 ; <%"struct.__gnu_cxx::__normal_iterator<BigInt*,std::vector<BigInt, std::allocator<BigInt> > >"*>:0 [#uses=0] - -invcont14.unwind10_crit_edge: ; preds = %bb_main - br label %bb_main - -invcont15: ; preds = %invcont14.normaldest, %bb_main - br label %bb_main - -invcont15.normaldest: ; No predecessors! - br label %UnifiedReturnBlock - -unwind20: ; preds = %bb_main - br label %bb_main - -unwind20.fragment311: ; preds = %bb_main - br label %bb_main - -unwind20.fragment: ; preds = %bb_main - br label %bb_main - -unwind20.fragment.fragment: ; preds = %bb_main - br label %bb_main - -unwind20.Unwind_crit_edge: ; preds = %bb_main - br label %bb_main - -filter: ; preds = %bb_main - br label %UnifiedUnreachableBlock - -Unwind: ; preds = %bb_main - br label %bb_main - -Unwind.fragment: ; preds = %bb_main - br label %UnifiedUnreachableBlock - -entry1: ; preds = %bb_main - br label %bb_main - -entry1.fragment312: ; preds = %bb_main - br label %bb_main - -entry1.fragment: ; preds = %bb_main - br label %bb_main - -entry1.fragment.fragment: ; preds = %bb_main - %tmp52 = invoke i32 @___ZN9__gnu_cxxmiIPK6BigIntS3_St6vectorIS1_SaIS1_EEEENS_17__normal_iteratorIT_T1_E15difference_typeERKSA_RKNS7_IT0_S9_EE___ZNKSt6vectorI6BigIntSaIS0_EE4sizeEv___ZNK9Fibonacci16show_all_numbersEv___ZNKSt6vectorI6BigIntSaIS0_EE8capacityEv( %"struct.__gnu_cxx::__normal_iterator<BigInt*,std::vector<BigInt, std::allocator<BigInt> > >"* null, %"struct.__gnu_cxx::__normal_iterator<BigInt*,std::vector<BigInt, std::allocator<BigInt> > >"* null, %"struct.std::vector<BigInt,std::allocator<BigInt> >"* null, i32 16, %struct.Fibonacci* null ) - to label %entry1.fragment.normaldest unwind label %meshBB320 ; <i32> [#uses=0] - -entry.unwind_crit_edge: ; preds = %bb_main - br label %bb_main - -unwind11: ; preds = %bb_main - br label %bb_main - -unwind11.fragment: ; preds = %bb_main - br label %bb_main - -invcont16: ; preds = %bb_main - br label %bb_main - -invcont16.fragment: ; preds = %bb_main - br label %bb_main - -invcont.cond_next_crit_edge: ; preds = %bb_main - br label %bb_main - -cond_true: ; preds = %bb_main - invoke void @_ZN9Fibonacci10get_numberEj( %struct.BigInt* sret null , %struct.Fibonacci* %this_this, i32 %n_i_n_i ) - to label %meshBB323 unwind label %cond_true.unwind_crit_edge - -cond_true.unwind_crit_edge: ; preds = %cond_true, %bb_main - br label %bb_main - -cond_true.unwind_crit_edge.unwinddest: ; No predecessors! - br label %bb_main - -invcont12: ; preds = %bb_main - br label %bb_main - -invcont12.fragment: ; preds = %bb_main - invoke %"struct.__gnu_cxx::__normal_iterator<BigInt*,std::vector<BigInt, std::allocator<BigInt> > >"* @___ZN9__gnu_cxx17__normal_iteratorIP6BigIntSt6vectorIS1_SaIS1_EEEppEv___ZNSt6vectorImSaImEED1Ev___ZN6BigIntD1Ev___ZN9__gnu_cxx13new_allocatorI6BigIntE7destroyEPS1____ZSt8_DestroyIP6BigIntSaIS0_EEvT_S3_T0_( i32 14, %"struct.__gnu_cxx::__normal_iterator<BigInt*,std::vector<BigInt, std::allocator<BigInt> > >"* null, %"struct.std::vector<ulong,std::allocator<ulong> >"* null, %struct.BigInt* null, %struct.__false_type* null, %struct.BigInt* null, %struct.__false_type* noalias null ) - to label %meshBB30 unwind label %meshBB337 ; <%"struct.__gnu_cxx::__normal_iterator<BigInt*,std::vector<BigInt, std::allocator<BigInt> > >"*>:1 [#uses=0] - -invcont12.unwind_crit_edge: ; preds = %bb_main - br label %bb_main - -invcont12.cond_next_crit_edge: ; preds = %bb_main - br label %bb_main - -cond_next: ; preds = %bb_main - br label %bb_main - -cond_next.fragment: ; preds = %bb_main - %tmp183 = invoke %struct.BigInt* @___ZNSt6vectorI6BigIntSaIS0_EEixEj___ZNSt6vectorI6BigIntSaIS0_EE3endEv( %"struct.std::vector<BigInt,std::allocator<BigInt> >"* null, i32 %n_i_n_i, i32 29 ) - to label %invcont17 unwind label %meshBB336 ; <%struct.BigInt*> [#uses=0] - -cond_next.unwind_crit_edge: ; preds = %bb_main - br label %bb_main - -invcont17: ; preds = %cond_next.fragment, %bb_main - br label %bb_main +bb_main: + br label %invcont17.normaldest invcont17.normaldest917: ; No predecessors! - %tmp23 = invoke %"struct.std::basic_ostream<char,std::char_traits<char> >"* @_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc( %"struct.std::basic_ostream<char,std::char_traits<char> >"* null, i8* getelementptr ([6 x i8]* @.str13, i32 0, i32 0) ) - to label %invcont17.normaldest unwind label %meshBB318 ; <%"struct.std::basic_ostream<char,std::char_traits<char> >"*> [#uses=1] - -invcont17.unwind_crit_edge: ; preds = %bb_main - br label %bb_main - -invcont22: ; preds = %bb_main - br label %bb_main - -invcont22.fragment: ; preds = %bb_main - %tmp26 = invoke %"struct.std::basic_ostream<char,std::char_traits<char> >"* @_ZNSolsEm( %"struct.std::basic_ostream<char,std::char_traits<char> >"* undef, i32 %n_i_n_i ) - to label %invcont25 unwind label %meshBB319 ; <%"struct.std::basic_ostream<char,std::char_traits<char> >"*> [#uses=1] - -invcont22.unwind_crit_edge: ; preds = %bb_main - br label %bb_main - -invcont25: ; preds = %invcont22.fragment, %bb_main - br label %bb_main - -invcont25.normaldest: ; No predecessors! - %tmp2918 = invoke %"struct.std::basic_ostream<char,std::char_traits<char> >"* @_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc( %"struct.std::basic_ostream<char,std::char_traits<char> >"* %tmp26, i8* getelementptr ([5 x i8]* @.str14, i32 0, i32 0) ) - to label %invcont28 unwind label %invcont25.unwind_crit_edge ; <%"struct.std::basic_ostream<char,std::char_traits<char> >"*> [#uses=0] - -invcont25.unwind_crit_edge: ; preds = %invcont25.normaldest, %bb_main - br label %bb_main - -invcont25.unwind_crit_edge.unwinddest: ; No predecessors! - br label %bb_main - -invcont28: ; preds = %invcont25.normaldest, %bb_main - br label %bb_main - -invcont28.normaldest: ; No predecessors! - br label %bb_main - -invcont28.fragment: ; preds = %bb_main - %tmp311 = invoke %"struct.std::basic_ostream<char,std::char_traits<char> >"* @___ZlsRSoRK6BigInt___ZN9__gnu_cxx13new_allocatorI6BigIntE10deallocateEPS1_j( i32 32, %"struct.std::basic_ostream<char,std::char_traits<char> >"* undef, %struct.BigInt* undef, %struct.__false_type* null, i32 0 ) - to label %invcont30 unwind label %meshBB322 ; <%"struct.std::basic_ostream<char,std::char_traits<char> >"*> [#uses=0] - -invcont28.unwind_crit_edge: ; preds = %bb_main - br label %bb_main - -invcont30: ; preds = %invcont28.fragment, %bb_main - br label %bb_main - -invcont30.normaldest: ; No predecessors! - br label %bb_main - -invcont30.fragment: ; preds = %bb_main - %tmp34 = invoke %"struct.std::basic_ostream<char,std::char_traits<char> >"* @_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc( %"struct.std::basic_ostream<char,std::char_traits<char> >"* undef, i8* getelementptr ([2 x i8]* @.str15, i32 0, i32 0) ) - to label %meshBB26 unwind label %invcont30.unwind_crit_edge ; <%"struct.std::basic_ostream<char,std::char_traits<char> >"*> [#uses=0] - -invcont30.unwind_crit_edge: ; preds = %invcont30.fragment, %bb_main - br label %bb_main - -invcont30.unwind_crit_edge.unwinddest: ; No predecessors! - br label %bb_main - -invcont33: ; preds = %bb_main - invoke void @_ZNKSt19basic_ostringstreamIcSt11char_traitsIcESaIcEE3strEv( %"struct.std::basic_string<char,std::char_traits<char>,std::allocator<char> >"* sret null , %"struct.std::ostringstream"* null ) - to label %invcont36 unwind label %invcont33.unwind_crit_edge - -invcont33.unwind_crit_edge: ; preds = %invcont33, %bb_main - br label %bb_main - -invcont33.unwind_crit_edge.unwinddest: ; No predecessors! - br label %bb_main - -invcont36: ; preds = %invcont33, %bb_main - br label %bb_main - -invcont36.normaldest: ; No predecessors! - %tmp42 = invoke %"struct.std::basic_ostream<char,std::char_traits<char> >"* @_ZStlsIcSt11char_traitsIcESaIcEERSt13basic_ostreamIT_T0_ES7_RKSbIS4_S5_T1_E( %"struct.std::basic_ostream<char,std::char_traits<char> >"* @_ZSt4cout, %"struct.std::basic_string<char,std::char_traits<char>,std::allocator<char> >"* null ) - to label %invcont41 unwind label %meshBB338 ; <%"struct.std::basic_ostream<char,std::char_traits<char> >"*> [#uses=0] - -unwind37: ; preds = %bb_main - br label %bb_main - -unwind37.fragment: ; preds = %bb_main - invoke void @_ZNSsD1Ev( %"struct.std::basic_string<char,std::char_traits<char>,std::allocator<char> >"* null ) - to label %meshBB330 unwind label %meshBB22 - -unwind37.nofilter_crit_edge: ; preds = %bb_main - br label %bb_main - -invcont41: ; preds = %invcont36.normaldest, %bb_main - br label %bb_main - -invcont41.normaldest: ; No predecessors! - br label %bb_main - -invcont41.fragment: ; preds = %bb_main - invoke void @_ZNSsD1Ev( %"struct.std::basic_string<char,std::char_traits<char>,std::allocator<char> >"* null ) - to label %meshBB23 unwind label %meshBB29 - -unwind43: ; preds = %bb_main - br label %bb_main - -unwind43.fragment313: ; preds = %bb_main - br label %bb_main - -unwind43.fragment: ; preds = %bb_main - br label %bb_main - -unwind43.fragment.fragment: ; preds = %bb_main - br label %bb_main - -unwind43.nofilter_crit_edge: ; preds = %bb_main - br label %bb_main - -invcont47: ; preds = %bb_main - invoke void @_ZNSt19basic_ostringstreamIcSt11char_traitsIcESaIcEED1Ev( %"struct.std::ostringstream"* null ) - to label %invcont70 unwind label %meshBB28 - -filter19: ; preds = %bb_main - br label %UnifiedUnreachableBlock - -nofilter: ; preds = %bb_main - br label %bb_main - -nofilter.fragment: ; preds = %bb_main - invoke void @_ZNSt19basic_ostringstreamIcSt11char_traitsIcESaIcEED1Ev( %"struct.std::ostringstream"* null ) - to label %nofilter.Unwind_crit_edge unwind label %meshBB - -nofilter.Unwind_crit_edge: ; preds = %nofilter.fragment, %bb_main - br label %bb_main - -nofilter.Unwind_crit_edge.normaldest: ; No predecessors! - br label %bb_main - -unwind53: ; preds = %bb_main - br label %bb_main - -unwind53.fragment314: ; preds = %bb_main - br label %bb_main - -unwind53.fragment: ; preds = %bb_main - br label %bb_main - -unwind53.fragment.fragment: ; preds = %bb_main - br label %bb_main - -unwind53.nofilter_crit_edge: ; preds = %bb_main - br label %bb_main - -filter62: ; preds = %bb_main - br label %UnifiedUnreachableBlock - -unwind66: ; preds = %bb_main - br label %bb_main - -unwind66.fragment315: ; preds = %bb_main - br label %bb_main - -unwind66.fragment: ; preds = %bb_main - br label %bb_main - -unwind66.fragment.fragment: ; preds = %bb_main - br label %bb_main - -unwind66.Unwind_crit_edge: ; preds = %bb_main - br label %bb_main - -invcont70: ; preds = %invcont47, %bb_main - br label %bb_main - -invcont70.normaldest: ; No predecessors! - br label %UnifiedReturnBlock - -filter75: ; preds = %bb_main - br label %UnifiedUnreachableBlock - -unwind78: ; preds = %bb_main - br label %bb_main - -unwind78.fragment316: ; preds = %bb_main - br label %bb_main - -unwind78.fragment: ; preds = %bb_main - br label %bb_main - -unwind78.fragment.fragment: ; preds = %bb_main - br label %bb_main - -unwind78.Unwind_crit_edge: ; preds = %bb_main - br label %bb_main - -filter87: ; preds = %bb_main - br label %UnifiedUnreachableBlock - -Unwind20: ; preds = %bb_main - br label %bb_main - -Unwind20.fragment: ; preds = %bb_main - br label %UnifiedUnreachableBlock - -meshBB: ; preds = %nofilter.fragment, %bb_main - br label %bb_main - -meshBB.unwinddest: ; No predecessors! - br label %bb_main - -meshBB.fragment: ; preds = %bb_main - br label %bb_main - -meshBB22: ; preds = %unwind37.fragment, %bb_main - br label %bb_main - -meshBB22.unwinddest: ; No predecessors! - br label %bb_main - -meshBB22.fragment: ; preds = %bb_main - br label %bb_main - -entry1.fragment.normaldest: ; preds = %entry1.fragment.fragment, %bb_main - br label %bb_main - -entry1.fragment.normaldest.normaldest: ; No predecessors! - br label %bb_main - -meshBB23: ; preds = %invcont41.fragment, %bb_main - br label %bb_main - -meshBB23.normaldest: ; No predecessors! - br label %bb_main - -meshBB23.fragment: ; preds = %bb_main - br label %bb_main - -meshBB24: ; preds = %unwind10.fragment.fragment, %bb_main - br label %bb_main - -meshBB24.unwinddest: ; No predecessors! - br label %bb_main - -meshBB24.fragment: ; preds = %bb_main - br label %bb_main - -meshBB25: ; preds = %bb_main - br label %bb_main - -meshBB25.fragment: ; preds = %bb_main - br label %bb_main - -meshBB26: ; preds = %invcont30.fragment, %bb_main - br label %bb_main - -meshBB26.normaldest: ; No predecessors! - br label %bb_main - -meshBB26.fragment: ; preds = %bb_main - br label %bb_main - -meshBB27: ; preds = %bb_main - br label %bb_main - -meshBB27.fragment: ; preds = %bb_main - br label %bb_main - -meshBB28: ; preds = %invcont47, %bb_main - br label %bb_main - -meshBB28.unwinddest: ; No predecessors! - br label %bb_main - -meshBB28.fragment: ; preds = %bb_main - br label %bb_main - -meshBB29: ; preds = %invcont41.fragment, %bb_main - br label %bb_main - -meshBB29.unwinddest: ; No predecessors! - br label %bb_main - -meshBB29.fragment: ; preds = %bb_main - br label %bb_main - -meshBB30: ; preds = %invcont12.fragment, %bb_main - br label %bb_main - -meshBB30.normaldest: ; No predecessors! - br label %bb_main - -meshBB30.fragment: ; preds = %bb_main - br label %bb_main - -meshBB31: ; preds = %bb_main - br label %bb_main - -meshBB31.fragment: ; preds = %bb_main - br label %bb_main - -meshBB32: ; preds = %bb_main - br label %bb_main - -meshBB32.fragment: ; preds = %bb_main - br label %bb_main - -meshBB33: ; preds = %bb_main - br label %bb_main - -meshBB33.fragment: ; preds = %bb_main - br label %bb_main - -meshBB34: ; preds = %bb_main - br label %bb_main - -meshBB34.fragment: ; preds = %bb_main - br label %bb_main - -meshBB35: ; preds = %bb_main - br label %bb_main - -meshBB35.fragment: ; preds = %bb_main - br label %bb_main - -meshBB36: ; preds = %bb_main - br label %bb_main - -meshBB36.fragment: ; preds = %bb_main - br label %bb_main - -meshBB37: ; preds = %invcont.fragment, %bb_main - br label %bb_main - -meshBB37.unwinddest: ; No predecessors! - br label %bb_main - -meshBB37.fragment: ; preds = %bb_main - br label %bb_main - -meshBB317: ; preds = %bb_main - br label %bb_main - -meshBB318: ; preds = %invcont17.normaldest917, %bb_main - br label %bb_main - -meshBB318.unwinddest: ; No predecessors! - br label %bb_main - -meshBB319: ; preds = %invcont22.fragment, %bb_main - br label %bb_main - -meshBB319.unwinddest: ; No predecessors! - br label %bb_main - -meshBB320: ; preds = %entry1.fragment.fragment, %bb_main - br label %bb_main - -meshBB320.unwinddest: ; No predecessors! - br label %bb_main - -meshBB321: ; preds = %bb_main - br label %bb_main - -meshBB322: ; preds = %invcont28.fragment, %bb_main - br label %bb_main - -meshBB322.unwinddest: ; No predecessors! - br label %bb_main - -meshBB323: ; preds = %cond_true, %bb_main - br label %bb_main - -meshBB323.normaldest: ; No predecessors! - br label %bb_main - -meshBB324: ; preds = %bb_main - br label %bb_main - -meshBB325: ; preds = %entry.fragment.fragment, %bb_main - br label %bb_main - -meshBB325.unwinddest: ; No predecessors! - br label %bb_main - -meshBB326: ; preds = %bb_main - br label %bb_main - -meshBB327: ; preds = %bb_main - br label %bb_main - -meshBB328: ; preds = %bb_main - br label %bb_main - -meshBB329: ; preds = %unwind10.fragment.fragment, %bb_main - br label %bb_main - -meshBB329.normaldest: ; No predecessors! - br label %bb_main - -meshBB330: ; preds = %unwind37.fragment, %bb_main - br label %bb_main - -meshBB330.normaldest: ; No predecessors! - br label %bb_main - -meshBB331: ; preds = %bb_main - br label %bb_main - -meshBB332: ; preds = %bb_main - br label %bb_main - -meshBB333: ; preds = %bb_main - br label %bb_main - -meshBB334: ; preds = %bb_main - br label %bb_main - -meshBB335: ; preds = %bb_main - br label %bb_main - -meshBB336: ; preds = %cond_next.fragment, %bb_main - br label %bb_main - -meshBB336.unwinddest: ; No predecessors! - br label %bb_main - -meshBB337: ; preds = %invcont12.fragment, %bb_main - br label %bb_main - -meshBB337.unwinddest: ; No predecessors! - br label %bb_main - -meshBB338: ; preds = %invcont36.normaldest, %bb_main - br label %bb_main - -meshBB338.unwinddest: ; No predecessors! - br label %bb_main + %tmp23 = invoke i32 @foo() + to label %invcont17.normaldest unwind label %invcont17.normaldest.normaldest invcont17.normaldest: ; preds = %invcont17.normaldest917, %bb_main br label %bb_main invcont17.normaldest.normaldest: ; No predecessors! - store %"struct.std::basic_ostream<char,std::char_traits<char> >"* %tmp23, %"struct.std::basic_ostream<char,std::char_traits<char> >"** undef - br label %bb_main - -meshBB339: ; preds = %bb_main - br label %bb_main - -meshBB340: ; preds = %entry.fragment.fragment, %bb_main - br label %bb_main - -meshBB340.normaldest: ; No predecessors! - br label %bb_main - -meshBB341: ; preds = %bb_main - br label %bb_main - -meshBB342: ; preds = %bb_main - br label %bb_main - -meshBB343: ; preds = %bb_main - br label %bb_main - -meshBB344: ; preds = %bb_main - br label %bb_main - -meshBB345: ; preds = %invcont14.normaldest, %bb_main - br label %bb_main - -meshBB345.unwinddest: ; No predecessors! - br label %bb_main - -meshBB346: ; preds = %bb_main - br label %bb_main - -meshBB347: ; preds = %bb_main - br label %bb_main - -meshBB348: ; preds = %bb_main - br label %bb_main - -meshBB349: ; preds = %bb_main + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + catch i8* null + store i32 %tmp23, i32* undef br label %bb_main +} -UnifiedUnreachableBlock: ; preds = %Unwind20.fragment, %filter87, %filter75, %filter62, %filter19, %Unwind.fragment, %filter - unreachable +declare i32 @foo() -UnifiedReturnBlock: ; preds = %invcont70.normaldest, %invcont15.normaldest - ret void -} +declare i32 @__gxx_personality_v0(...) diff --git a/test/Transforms/LoopSimplify/merge-exits.ll b/test/Transforms/LoopSimplify/merge-exits.ll index e5e471766b9a2..40ad2f44e717e 100644 --- a/test/Transforms/LoopSimplify/merge-exits.ll +++ b/test/Transforms/LoopSimplify/merge-exits.ll @@ -7,7 +7,7 @@ ; that indvars can promote the induction variable to i64 ; without needing casts. -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-n:32:64" +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-n32:64" define float @t(float* %pTmp1, float* %peakWeight, i32 %bandEdgeIndex) nounwind { entry: diff --git a/test/Transforms/LoopSimplify/preserve-scev.ll b/test/Transforms/LoopSimplify/preserve-scev.ll index 017a0d2108498..23ac7f257a384 100644 --- a/test/Transforms/LoopSimplify/preserve-scev.ll +++ b/test/Transforms/LoopSimplify/preserve-scev.ll @@ -48,3 +48,91 @@ return: ; preds = %for.body18, %for.bo } declare void @foo() nounwind + +; Notify SCEV when removing an ExitingBlock. +; CHECK: @mergeExit +; CHECK: while.cond191: +; CHECK: br i1 %or.cond, label %while.body197 +; CHECK-NOT: land.rhs: +; CHECK: ret +define void @mergeExit(i32 %MapAttrCount) nounwind uwtable ssp { +entry: + br i1 undef, label %if.then124, label %if.end126 + +if.then124: ; preds = %entry + unreachable + +if.end126: ; preds = %entry + br i1 undef, label %while.body.lr.ph, label %if.end591 + +while.body.lr.ph: ; preds = %if.end126 + br i1 undef, label %if.end140, label %if.then137 + +if.then137: ; preds = %while.body.lr.ph + unreachable + +if.end140: ; preds = %while.body.lr.ph + br i1 undef, label %while.cond191.outer, label %if.then148 + +if.then148: ; preds = %if.end140 + unreachable + +while.cond191.outer: ; preds = %if.then205, %if.end140 + br label %while.cond191 + +while.cond191: ; preds = %while.body197, %while.cond191.outer + %CppIndex.0 = phi i32 [ %inc, %while.body197 ], [ undef, %while.cond191.outer ] + br i1 undef, label %land.rhs, label %if.then216 + +land.rhs: ; preds = %while.cond191 + %inc = add i32 %CppIndex.0, 1 + %cmp196 = icmp ult i32 %inc, %MapAttrCount + br i1 %cmp196, label %while.body197, label %if.then216 + +while.body197: ; preds = %land.rhs + br i1 undef, label %if.then205, label %while.cond191 + +if.then205: ; preds = %while.body197 + br label %while.cond191.outer + +if.then216: ; preds = %land.rhs, %while.cond191 + br i1 undef, label %if.else, label %if.then221 + +if.then221: ; preds = %if.then216 + unreachable + +if.else: ; preds = %if.then216 + br i1 undef, label %if.then266, label %if.end340 + +if.then266: ; preds = %if.else + switch i32 undef, label %if.else329 [ + i32 17, label %if.then285 + i32 19, label %if.then285 + i32 18, label %if.then285 + i32 15, label %if.then285 + ] + +if.then285: ; preds = %if.then266, %if.then266, %if.then266, %if.then266 + br i1 undef, label %if.then317, label %if.else324 + +if.then317: ; preds = %if.then285 + br label %if.end340 + +if.else324: ; preds = %if.then285 + unreachable + +if.else329: ; preds = %if.then266 + unreachable + +if.end340: ; preds = %if.then317, %if.else + unreachable + +if.end591: ; preds = %if.end126 + br i1 undef, label %cond.end, label %cond.false + +cond.false: ; preds = %if.end591 + unreachable + +cond.end: ; preds = %if.end591 + ret void +} diff --git a/test/Transforms/LoopSimplify/single-backedge.ll b/test/Transforms/LoopSimplify/single-backedge.ll index f9567f124291e..aedd6f23091c9 100644 --- a/test/Transforms/LoopSimplify/single-backedge.ll +++ b/test/Transforms/LoopSimplify/single-backedge.ll @@ -1,8 +1,11 @@ -; The loop canonicalization pass should guarantee that there is one backedge -; for all loops. This allows the -indvars pass to recognize the %IV +; The loop canonicalization pass should guarantee that there is one backedge +; for all loops. This allows the -indvars pass to recognize the %IV ; induction variable in this testcase. -; RUN: opt < %s -indvars -S | grep indvar +; RUN: opt < %s -indvars -S | FileCheck %s +; CHECK: Loop.backedge: +; CHECK-NOT: br +; CHECK: br label %Loop define i32 @test(i1 %C) { ; <label>:0 diff --git a/test/Transforms/LoopStrengthReduce/2011-07-19-CritEdgeBreakCrash.ll b/test/Transforms/LoopStrengthReduce/2011-07-19-CritEdgeBreakCrash.ll new file mode 100644 index 0000000000000..b9bd7c9bf4a3e --- /dev/null +++ b/test/Transforms/LoopStrengthReduce/2011-07-19-CritEdgeBreakCrash.ll @@ -0,0 +1,52 @@ +; ModuleID = '<stdin>' +; RUN: opt < %s -loop-reduce -S | FileCheck %s +; PR10386 + +declare i1 @foo() +declare i8* @bar(i8*,i8*,i8*,i8*) + +define void @f(i64* %a,i64* %b,i64* %c,i64* %d,i64* %e,i64* %f,i64* %g) nounwind uwtable { +entry: + br label %b_throw.preheader + +D_BREAK_LBL: ; preds = %indirectgoto + call i1 @foo() + br label %indirectgoto + +H_CONST_LBL: ; preds = %indirectgoto + call i1 @foo() + br label %body_failed + +H_MPZ_LBL: ; preds = %indirectgoto + %boo3 = call i1 @foo() + br i1 %boo3, label %body_failed, label %while.cond.i + +while.cond.i: ; preds = %while.body.i15795, %if.then.i15791 + %phi = phi i64 [ %tmp20916, %while.body.i15795 ], [ 0, %H_MPZ_LBL ] + %tmp20916 = add i64 %phi, 1 + %incdec.ptr.i15793 = getelementptr i64* %pc.0.lcssa.i1610719352, i64 %tmp20916 + %boo2 = call i1 @foo() + br i1 %boo2, label %indirectgoto, label %while.body.i15795 + +while.body.i15795: ; preds = %while.cond.i + %tmp20.i = load i64* %incdec.ptr.i15793, align 8 + %boo1 = call i1 @foo() + br i1 %boo1, label %while.cond.i, label %body_failed + +b_throw.preheader: ; preds = %body_failed, %entry + call i1 @foo() + br label %indirectgoto + +body_failed: + %pc.0.lcssa.i1610719364 = phi i64* [ %pc.0.lcssa.i1610719352, %indirectgoto ], [ %pc.0.lcssa.i1610719352, %H_MPZ_LBL ], [ %b, %H_CONST_LBL ], [ %pc.0.lcssa.i1610719352, %while.body.i15795 ] + call i1 @foo() + br label %b_throw.preheader + +indirectgoto: + %pc.0.lcssa.i1610719352 = phi i64* [ %pc.0.lcssa.i1610719352, %D_BREAK_LBL ], [ %a, %b_throw.preheader ], [ %d, %while.cond.i ] + %p = call i8* @bar(i8* blockaddress(@f, %D_BREAK_LBL), i8* blockaddress(@f, %H_CONST_LBL), i8* blockaddress(@f, %H_MPZ_LBL), i8* blockaddress(@f, %body_failed) ) + indirectbr i8* %p, [label %D_BREAK_LBL, label %H_CONST_LBL, label %H_MPZ_LBL, label %body_failed] +} + +; CHECK: %p = call i8* @bar(i8* blockaddress(@f, %D_BREAK_LBL), i8* blockaddress(@f, %H_CONST_LBL), i8* blockaddress(@f, %H_MPZ_LBL), i8* blockaddress(@f, %body_failed)) +; CHECK: indirectbr i8* %p, [label %D_BREAK_LBL, label %H_CONST_LBL, label %H_MPZ_LBL, label %body_failed] diff --git a/test/Transforms/LoopStrengthReduce/2011-07-20-DoubleIV.ll b/test/Transforms/LoopStrengthReduce/2011-07-20-DoubleIV.ll new file mode 100644 index 0000000000000..5d9ed64ef4223 --- /dev/null +++ b/test/Transforms/LoopStrengthReduce/2011-07-20-DoubleIV.ll @@ -0,0 +1,43 @@ +; RUN: opt < %s -loop-reduce -S | FileCheck %s +; +; Test LSR's OptimizeShadowIV. Handle a floating-point IV with a +; nonzero initial value. +; rdar://9786536 + +; First, make sure LSR doesn't crash on an empty IVUsers list. +; CHECK: @dummyIV +; CHECK-NOT: phi +; CHECK-NOT: sitofp +; CHECK: br +define void @dummyIV() nounwind { +entry: + br label %loop + +loop: + %i.01 = phi i32 [ -39, %entry ], [ %inc, %loop ] + %conv = sitofp i32 %i.01 to double + %inc = add nsw i32 %i.01, 1 + br i1 undef, label %loop, label %for.end + +for.end: + unreachable +} + +; Now check that the computed double constant is correct. +; CHECK: @doubleIV +; CHECK: phi double [ -3.900000e+01, %entry ] +; CHECK: br +define void @doubleIV() nounwind { +entry: + br label %loop + +loop: + %i.01 = phi i32 [ -39, %entry ], [ %inc, %loop ] + %conv = sitofp i32 %i.01 to double + %div = fdiv double %conv, 4.000000e+01 + %inc = add nsw i32 %i.01, 1 + br i1 undef, label %loop, label %for.end + +for.end: + unreachable +} diff --git a/test/Transforms/LoopStrengthReduce/2011-10-03-CritEdgeMerge.ll b/test/Transforms/LoopStrengthReduce/2011-10-03-CritEdgeMerge.ll new file mode 100644 index 0000000000000..a6996a81fb074 --- /dev/null +++ b/test/Transforms/LoopStrengthReduce/2011-10-03-CritEdgeMerge.ll @@ -0,0 +1,43 @@ +; RUN: opt -loop-reduce -S < %s | FileCheck %s +; +; Test LSR's use of SplitCriticalEdge during phi rewriting. +; Verify that identical edges are merged. rdar://problem/6453893 + +target triple = "x86-apple-darwin" + +; CHECK: @test +; CHECK: bb89: +; CHECK: phi i8* [ %lsr.iv.next1, %bbA.bb89_crit_edge ], [ %lsr.iv.next1, %bbB.bb89_crit_edge ]{{$}} + +define i8* @test() { +entry: + br label %loop + +loop: + %rec = phi i32 [ %next, %loop ], [ 0, %entry ] + %next = add i32 %rec, 1 + %tmp75 = getelementptr i8* null, i32 %next + br i1 false, label %loop, label %loopexit + +loopexit: + br i1 false, label %bbA, label %bbB + +bbA: + switch i32 0, label %bb89 [ + i32 47, label %bb89 + i32 58, label %bb89 + ] + +bbB: + switch i8 0, label %bb89 [ + i8 47, label %bb89 + i8 58, label %bb89 + ] + +bb89: + %tmp75phi = phi i8* [ %tmp75, %bbA ], [ %tmp75, %bbA ], [ %tmp75, %bbA ], [ %tmp75, %bbB ], [ %tmp75, %bbB ], [ %tmp75, %bbB ] + br label %exit + +exit: + ret i8* %tmp75phi +} diff --git a/test/Transforms/LoopStrengthReduce/2011-10-06-ReusePhi.ll b/test/Transforms/LoopStrengthReduce/2011-10-06-ReusePhi.ll new file mode 100644 index 0000000000000..1ee9bb409d917 --- /dev/null +++ b/test/Transforms/LoopStrengthReduce/2011-10-06-ReusePhi.ll @@ -0,0 +1,53 @@ +; RUN: opt -loop-reduce -S < %s | FileCheck %s +; +; Test LSR's intelligence regarding phi reuse. +; Verify that scaled GEPs are not reused. rdar://5064068 + +target triple = "x86-apple-darwin" + +; CHECK: @test +; multiplies are hoisted out of the loop +; CHECK: while.body.lr.ph: +; CHECK: mul i64 +; CHECK: mul i64 +; GEPs are ugly +; CHECK: while.body: +; CHECK: phi +; CHECK: phi +; CHECK: phi +; CHECK: phi +; CHECK-NOT: phi +; CHECK: bitcast float* {{.*}} to i8* +; CHECK: bitcast float* {{.*}} to i8* +; CHECK: getelementptr i8* +; CHECK: getelementptr i8* + +define float @test(float* nocapture %A, float* nocapture %B, i32 %N, i32 %IA, i32 %IB) nounwind uwtable readonly ssp { +entry: + %cmp1 = icmp sgt i32 %N, 0 + br i1 %cmp1, label %while.body.lr.ph, label %while.end + +while.body.lr.ph: ; preds = %entry + %idx.ext = sext i32 %IA to i64 + %idx.ext2 = sext i32 %IB to i64 + br label %while.body + +while.body: ; preds = %while.body.lr.ph, %while.body + %A.addr.05 = phi float* [ %A, %while.body.lr.ph ], [ %add.ptr, %while.body ] + %B.addr.04 = phi float* [ %B, %while.body.lr.ph ], [ %add.ptr3, %while.body ] + %N.addr.03 = phi i32 [ %N, %while.body.lr.ph ], [ %sub, %while.body ] + %Sum0.02 = phi float [ 0.000000e+00, %while.body.lr.ph ], [ %add, %while.body ] + %0 = load float* %A.addr.05, align 4 + %1 = load float* %B.addr.04, align 4 + %mul = fmul float %0, %1 + %add = fadd float %Sum0.02, %mul + %add.ptr = getelementptr inbounds float* %A.addr.05, i64 %idx.ext + %add.ptr3 = getelementptr inbounds float* %B.addr.04, i64 %idx.ext2 + %sub = add nsw i32 %N.addr.03, -1 + %cmp = icmp sgt i32 %sub, 0 + br i1 %cmp, label %while.body, label %while.end + +while.end: ; preds = %while.body, %entry + %Sum0.0.lcssa = phi float [ 0.000000e+00, %entry ], [ %add, %while.body ] + ret float %Sum0.0.lcssa +} diff --git a/test/Transforms/LoopStrengthReduce/2011-10-13-SCEVChain.ll b/test/Transforms/LoopStrengthReduce/2011-10-13-SCEVChain.ll new file mode 100644 index 0000000000000..4718529bfd507 --- /dev/null +++ b/test/Transforms/LoopStrengthReduce/2011-10-13-SCEVChain.ll @@ -0,0 +1,111 @@ +; RUN: opt -loop-reduce -S < %s | FileCheck %s +; +; Test TransformForPostIncUse and LSR's expansion of expressions in +; post-inc form to ensure the implementation can handle expressions +; DAGs, not just trees. + +target triple = "x86_64-apple-darwin" + +; Verify that -loop-reduce runs without "hanging" and reuses post-inc +; expansions. +; CHECK: @test +; CHECK: icmp +; CHECK: icmp +; CHECK: icmp +; CHECK: icmp +; CHECK: icmp +; CHECK: icmp +; CHECK: icmp +; CHECK: icmp +; CHECK: icmp +; CHECK: icmp +; CHECK: icmp +; CHECK: icmp +; CHECK: icmp +; CHECK: icmp +; CHECK: icmp +; CHECK: icmp +; CHECK: icmp +; CHECK-NOT: icmp +define void @test(i8* %base, i32 %a0) nounwind { +entry: + br label %bb1 +bb1: + %n0 = sub i32 0, %a0 + %t0 = icmp ugt i32 %n0, -4 + %m0 = select i1 %t0, i32 %n0, i32 -4 + %a1 = add i32 %m0, %a0 + %n1 = sub i32 0, %a1 + %t1 = icmp ugt i32 %n1, -4 + %m1 = select i1 %t1, i32 %n1, i32 -4 + %a2 = add i32 %m1, %a1 + %n2 = sub i32 0, %a2 + %t2 = icmp ugt i32 %n2, -4 + %m2 = select i1 %t2, i32 %n2, i32 -4 + %a3 = add i32 %m2, %a2 + %n3 = sub i32 0, %a3 + %t3 = icmp ugt i32 %n3, -4 + %m3 = select i1 %t3, i32 %n3, i32 -4 + %a4 = add i32 %m3, %a3 + %n4 = sub i32 0, %a4 + %t4 = icmp ugt i32 %n4, -4 + %m4 = select i1 %t4, i32 %n4, i32 -4 + %a5 = add i32 %m4, %a4 + %n5 = sub i32 0, %a5 + %t5 = icmp ugt i32 %n5, -4 + %m5 = select i1 %t5, i32 %n5, i32 -4 + %a6 = add i32 %m5, %a5 + %n6 = sub i32 0, %a6 + %t6 = icmp ugt i32 %n6, -4 + %m6 = select i1 %t6, i32 %n6, i32 -4 + %a7 = add i32 %m6, %a6 + %n7 = sub i32 0, %a7 + %t7 = icmp ugt i32 %n7, -4 + %m7 = select i1 %t7, i32 %n7, i32 -4 + %a8 = add i32 %m7, %a7 + %n8 = sub i32 0, %a8 + %t8 = icmp ugt i32 %n8, -4 + %m8 = select i1 %t8, i32 %n8, i32 -4 + %a9 = add i32 %m8, %a8 + %n9 = sub i32 0, %a9 + %t9 = icmp ugt i32 %n9, -4 + %m9 = select i1 %t9, i32 %n9, i32 -4 + %a10 = add i32 %m9, %a9 + %n10 = sub i32 0, %a10 + %t10 = icmp ugt i32 %n10, -4 + %m10 = select i1 %t10, i32 %n10, i32 -4 + %a11 = add i32 %m10, %a10 + %n11 = sub i32 0, %a11 + %t11 = icmp ugt i32 %n11, -4 + %m11 = select i1 %t11, i32 %n11, i32 -4 + %a12 = add i32 %m11, %a11 + %n12 = sub i32 0, %a12 + %t12 = icmp ugt i32 %n12, -4 + %m12 = select i1 %t12, i32 %n12, i32 -4 + %a13 = add i32 %m12, %a12 + %n13 = sub i32 0, %a13 + %t13 = icmp ugt i32 %n13, -4 + %m13 = select i1 %t13, i32 %n13, i32 -4 + %a14 = add i32 %m13, %a13 + %n14 = sub i32 0, %a14 + %t14 = icmp ugt i32 %n14, -4 + %m14 = select i1 %t14, i32 %n14, i32 -4 + %a15 = add i32 %m14, %a14 + %n15 = sub i32 0, %a15 + %t15 = icmp ugt i32 %n15, -4 + %m15 = select i1 %t15, i32 %n15, i32 -4 + %a16 = add i32 %m15, %a15 + %gep = getelementptr i8* %base, i32 %a16 + %ofs = add i32 %a16, 4 + %limit = getelementptr i8* %base, i32 %ofs + br label %loop + +loop: + %iv = phi i8* [ %gep, %bb1 ], [ %inc, %loop ] + %inc = getelementptr inbounds i8* %iv, i64 1 + %exitcond = icmp eq i8* %inc, %limit + br i1 %exitcond, label %loop, label %exit + +exit: + ret void +} diff --git a/test/Transforms/LoopStrengthReduce/2011-10-14-IntPtr.ll b/test/Transforms/LoopStrengthReduce/2011-10-14-IntPtr.ll new file mode 100644 index 0000000000000..60cc7a5163268 --- /dev/null +++ b/test/Transforms/LoopStrengthReduce/2011-10-14-IntPtr.ll @@ -0,0 +1,27 @@ +; RUN: opt -loop-reduce -S < %s | FileCheck %s +; +; Test SCEVExpander reusing a phi->gep->phi IV when SCEV "wrongly" +; reports the expression as an IntegerTy. + +target triple = "x86_64-apple-darwin" + +; CHECK: @test +; CHECK: phi +; CHECK-NOT: phi +define void @test(i32 %rowStride) ssp align 2 { +entry: + %cond = select i1 undef, i32 %rowStride, i32 4 + br label %for.end + +for.end.critedge: ; preds = %for.end + br label %for.end + +for.end: ; preds = %for.end.critedge, %entry + br i1 undef, label %for.body83, label %for.end.critedge + +for.body83: ; preds = %for.body83, %for.end + %ptr.0157 = phi i8* [ %add.ptr96, %for.body83 ], [ null, %for.end ] + store i8 undef, i8* %ptr.0157, align 1 + %add.ptr96 = getelementptr inbounds i8* %ptr.0157, i32 %cond + br label %for.body83 +} diff --git a/test/Transforms/LoopStrengthReduce/invariant_value_first.ll b/test/Transforms/LoopStrengthReduce/invariant_value_first.ll index 986a55a3f6c4e..2ca678761feda 100644 --- a/test/Transforms/LoopStrengthReduce/invariant_value_first.ll +++ b/test/Transforms/LoopStrengthReduce/invariant_value_first.ll @@ -2,7 +2,7 @@ ; RUN: opt < %s -loop-reduce -S | \ ; RUN: not grep {getelementptr.*%outer.*%INDVAR} -target datalayout = "e-p:32:32:32-n:8:16:32" +target datalayout = "e-p:32:32:32-n8:16:32" declare i1 @pred() declare i32 @foo() diff --git a/test/Transforms/LoopStrengthReduce/invariant_value_first_arg.ll b/test/Transforms/LoopStrengthReduce/invariant_value_first_arg.ll index 1d43961c356e1..86c4d915a00d1 100644 --- a/test/Transforms/LoopStrengthReduce/invariant_value_first_arg.ll +++ b/test/Transforms/LoopStrengthReduce/invariant_value_first_arg.ll @@ -2,7 +2,7 @@ ; RUN: opt < %s -loop-reduce -S | \ ; RUN: not grep {getelementptr.*%outer.*%INDVAR} -target datalayout = "e-p:32:32:32-n:32" +target datalayout = "e-p:32:32:32-n32" declare i1 @pred() define void @test([10000 x i32]* %P, i32 %outer) { diff --git a/test/Transforms/LoopStrengthReduce/ops_after_indvar.ll b/test/Transforms/LoopStrengthReduce/ops_after_indvar.ll index 00bd068d0b8f0..ec55179d64953 100644 --- a/test/Transforms/LoopStrengthReduce/ops_after_indvar.ll +++ b/test/Transforms/LoopStrengthReduce/ops_after_indvar.ll @@ -3,7 +3,7 @@ ; RUN: opt < %s -loop-reduce -S | not grep INDVAR -target datalayout = "e-p:32:32:32-n:32" +target datalayout = "e-p:32:32:32-n32" declare i1 @pred() diff --git a/test/Transforms/LoopStrengthReduce/post-inc-icmpzero.ll b/test/Transforms/LoopStrengthReduce/post-inc-icmpzero.ll index 294c0904194ae..27609157ec8c5 100644 --- a/test/Transforms/LoopStrengthReduce/post-inc-icmpzero.ll +++ b/test/Transforms/LoopStrengthReduce/post-inc-icmpzero.ll @@ -4,15 +4,15 @@ ; LSR should property handle the post-inc offset when folding the ; non-IV operand of an icmp into the IV. -; CHECK: %tmp2 = sub i64 %sub.ptr.lhs.cast, %sub.ptr.rhs.cast -; CHECK: %tmp3 = lshr i64 %tmp2, 1 -; CHECK: %tmp4 = mul i64 %tmp3, 2 +; CHECK: %5 = sub i64 %sub.ptr.lhs.cast, %sub.ptr.rhs.cast +; CHECK: %6 = lshr i64 %5, 1 +; CHECK: %7 = mul i64 %6, 2 ; CHECK: br label %for.body ; CHECK: for.body: -; CHECK: %lsr.iv5 = phi i64 [ %lsr.iv.next, %for.body ], [ %tmp4, %for.body.lr.ph ] -; CHECK: %lsr.iv.next = add i64 %lsr.iv5, -2 -; CHECK: %lsr.iv.next6 = inttoptr i64 %lsr.iv.next to i16* -; CHECK: %cmp27 = icmp eq i16* %lsr.iv.next6, null +; CHECK: %lsr.iv2 = phi i64 [ %lsr.iv.next, %for.body ], [ %7, %for.body.lr.ph ] +; CHECK: %lsr.iv.next = add i64 %lsr.iv2, -2 +; CHECK: %lsr.iv.next3 = inttoptr i64 %lsr.iv.next to i16* +; CHECK: %cmp27 = icmp eq i16* %lsr.iv.next3, null target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-unknown-linux-gnu" diff --git a/test/Transforms/LoopStrengthReduce/var_stride_used_by_compare.ll b/test/Transforms/LoopStrengthReduce/var_stride_used_by_compare.ll index 7547d83629299..64ef4f951f2b1 100644 --- a/test/Transforms/LoopStrengthReduce/var_stride_used_by_compare.ll +++ b/test/Transforms/LoopStrengthReduce/var_stride_used_by_compare.ll @@ -9,7 +9,7 @@ ; mul uint %i, 3 -target datalayout = "e-p:32:32-n:32" +target datalayout = "e-p:32:32-n32" target triple = "i686-apple-darwin8" @flags2 = external global [8193 x i8], align 32 ; <[8193 x i8]*> [#uses=1] diff --git a/test/Transforms/LoopUnroll/2011-08-08-PhiUpdate.ll b/test/Transforms/LoopUnroll/2011-08-08-PhiUpdate.ll new file mode 100644 index 0000000000000..cd954c80ec37a --- /dev/null +++ b/test/Transforms/LoopUnroll/2011-08-08-PhiUpdate.ll @@ -0,0 +1,103 @@ +; RUN: opt < %s -loop-unroll -S -unroll-count=4 | FileCheck %s +; Test phi update after partial unroll. + +declare i1 @check() nounwind + +; CHECK: @test +; CHECK: if.else: +; CHECK: if.then.loopexit +; CHECK: %sub5.lcssa = phi i32 [ %sub{{.*}}, %if.else{{.*}} ], [ %sub{{.*}}, %if.else{{.*}} ], [ %sub{{.*}}, %if.else{{.*}} ], [ %sub{{.*}}, %if.else{{.*}} ] +; CHECK: if.else.3 +define void @test1(i32 %i, i32 %j) nounwind uwtable ssp { +entry: + %cond1 = call zeroext i1 @check() + br i1 %cond1, label %if.then, label %if.else.lr.ph + +if.else.lr.ph: ; preds = %entry + br label %if.else + +if.else: ; preds = %if.else, %if.else.lr.ph + %sub = phi i32 [ %i, %if.else.lr.ph ], [ %sub5, %if.else ] + %sub5 = sub i32 %sub, %j + %cond2 = call zeroext i1 @check() + br i1 %cond2, label %if.then, label %if.else + +if.then: ; preds = %if.else, %entry + %i.tr = phi i32 [ %i, %entry ], [ %sub5, %if.else ] + ret void + +} + +; PR7318: assertion failure after doing a simple loop unroll +; +; CHECK: @test2 +; CHECK: bb1.bb2_crit_edge: +; CHECK: %.lcssa = phi i32 [ %{{[2468]}}, %bb1{{.*}} ], [ %{{[2468]}}, %bb1{{.*}} ], [ %{{[2468]}}, %bb1{{.*}} ], [ %{{[2468]}}, %bb1{{.*}} ] +; CHECK: bb1.3: +define i32 @test2(i32* nocapture %p, i32 %n) nounwind readonly { +entry: + %0 = icmp sgt i32 %n, 0 ; <i1> [#uses=1] + br i1 %0, label %bb.nph, label %bb2 + +bb.nph: ; preds = %entry + %tmp = zext i32 %n to i64 ; <i64> [#uses=1] + br label %bb + +bb: ; preds = %bb.nph, %bb1 + %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %bb1 ] ; <i64> [#uses=2] + %s.01 = phi i32 [ 0, %bb.nph ], [ %2, %bb1 ] ; <i32> [#uses=1] + %scevgep = getelementptr i32* %p, i64 %indvar ; <i32*> [#uses=1] + %1 = load i32* %scevgep, align 1 ; <i32> [#uses=1] + %2 = add nsw i32 %1, %s.01 ; <i32> [#uses=2] + br label %bb1 + +bb1: ; preds = %bb + %indvar.next = add i64 %indvar, 1 ; <i64> [#uses=2] + %exitcond = icmp ne i64 %indvar.next, %tmp ; <i1> [#uses=1] + br i1 %exitcond, label %bb, label %bb1.bb2_crit_edge + +bb1.bb2_crit_edge: ; preds = %bb1 + %.lcssa = phi i32 [ %2, %bb1 ] ; <i32> [#uses=1] + br label %bb2 + +bb2: ; preds = %bb1.bb2_crit_edge, %entry + %s.0.lcssa = phi i32 [ %.lcssa, %bb1.bb2_crit_edge ], [ 0, %entry ] ; <i32> [#uses=1] + ret i32 %s.0.lcssa +} + +; Check phi update for loop with an early-exit. +; +; CHECK: @test3 +; CHECK: return.loopexit: +; CHECK: %tmp7.i.lcssa = phi i32 [ %tmp7.i{{.*}}, %land.lhs.true{{.*}} ], [ %tmp7.i{{.*}}, %land.lhs.true{{.*}} ], [ %tmp7.i{{.*}}, %land.lhs.true{{.*}} ], [ %tmp7.i{{.*}}, %land.lhs.true{{.*}} ] +; CHECK: exit.3: +define i32 @test3() nounwind uwtable ssp align 2 { +entry: + %cond1 = call zeroext i1 @check() + br i1 %cond1, label %return, label %if.end + +if.end: ; preds = %entry + br label %do.body + +do.body: ; preds = %do.cond, %if.end + %cond2 = call zeroext i1 @check() + br i1 %cond2, label %exit, label %do.cond + +exit: ; preds = %do.body + %tmp7.i = load i32* undef, align 8 + br i1 undef, label %do.cond, label %land.lhs.true + +land.lhs.true: ; preds = %exit + br i1 undef, label %return, label %do.cond + +do.cond: ; preds = %land.lhs.true, %exit, %do.body + %cond3 = call zeroext i1 @check() + br i1 %cond3, label %do.end, label %do.body + +do.end: ; preds = %do.cond + br label %return + +return: ; preds = %do.end, %land.lhs.true, %entry + %retval.0 = phi i32 [ 0, %do.end ], [ 0, %entry ], [ %tmp7.i, %land.lhs.true ] + ret i32 %retval.0 +} diff --git a/test/Transforms/LoopUnroll/2011-08-09-IVSimplify.ll b/test/Transforms/LoopUnroll/2011-08-09-IVSimplify.ll new file mode 100644 index 0000000000000..59551d5c720c7 --- /dev/null +++ b/test/Transforms/LoopUnroll/2011-08-09-IVSimplify.ll @@ -0,0 +1,41 @@ +; RUN: opt -S < %s -loop-unroll -unroll-count=4 -enable-iv-rewrite=false | FileCheck %s +; +; Test induction variable simplify after loop unrolling. It should +; expose nice opportunities for GVN. +; +; CHECK-NOT: while.body also ensures that loop unrolling (with SCEV) +; removes unrolled loop exits given that 128 is a multiple of 4. + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f80:128:128-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32" + +; PR10534: LoopUnroll not keeping canonical induction variable... +; CHECK: while.body: +; CHECK-NOT: while.body.1: +; CHECK: %shr.1 = lshr i32 %bit_addr.addr.01, 5 +; CHECK: %arrayidx.1 = getelementptr inbounds i32* %bitmap, i32 %shr.1 +; CHECK: %shr.2 = lshr i32 %bit_addr.addr.01, 5 +; CHECK: %arrayidx.2 = getelementptr inbounds i32* %bitmap, i32 %shr.2 +; CHECK: %shr.3 = lshr i32 %bit_addr.addr.01, 5 +; CHECK: %arrayidx.3 = getelementptr inbounds i32* %bitmap, i32 %shr.3 +define void @FlipBit(i32* nocapture %bitmap, i32 %bit_addr, i32 %nbits) nounwind { +entry: + br label %while.body + +while.body: + %nbits.addr.02 = phi i32 [ 128, %entry ], [ %dec, %while.body ] + %bit_addr.addr.01 = phi i32 [ 0, %entry ], [ %inc, %while.body ] + %dec = add i32 %nbits.addr.02, -1 + %shr = lshr i32 %bit_addr.addr.01, 5 + %rem = and i32 %bit_addr.addr.01, 31 + %shl = shl i32 1, %rem + %arrayidx = getelementptr inbounds i32* %bitmap, i32 %shr + %tmp6 = load i32* %arrayidx, align 4 + %xor = xor i32 %tmp6, %shl + store i32 %xor, i32* %arrayidx, align 4 + %inc = add i32 %bit_addr.addr.01, 1 + %tobool = icmp eq i32 %dec, 0 + br i1 %tobool, label %while.end, label %while.body + +while.end: + ret void +} diff --git a/test/Transforms/LoopUnroll/2011-08-09-PhiUpdate.ll b/test/Transforms/LoopUnroll/2011-08-09-PhiUpdate.ll new file mode 100644 index 0000000000000..c1221f595ac29 --- /dev/null +++ b/test/Transforms/LoopUnroll/2011-08-09-PhiUpdate.ll @@ -0,0 +1,62 @@ +; RUN: opt -S < %s -instcombine -inline -jump-threading -loop-unroll -unroll-count=4 | FileCheck %s +; +; This is a test case that required a number of setup passes because +; it depends on block order. + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" +target triple = "x86_64-apple-macosx10.6.8" + +declare i1 @check() nounwind +declare i32 @getval() nounwind + +; Check that the loop exit merges values from all the iterations. This +; could be a tad fragile, but it's a good test. +; +; CHECK: @foo +; CHECK: return: +; CHECK: %retval.0 = phi i32 [ %tmp7.i, %land.lhs.true ], [ 0, %do.cond ], [ %tmp7.i.1, %land.lhs.true.1 ], [ 0, %do.cond.1 ], [ %tmp7.i.2, %land.lhs.true.2 ], [ 0, %do.cond.2 ], [ %tmp7.i.3, %land.lhs.true.3 ], [ 0, %do.cond.3 ] +; CHECK-NOT: @bar +; CHECK: bar.exit.3 +define i32 @foo() uwtable ssp align 2 { +entry: + br i1 undef, label %return, label %if.end + +if.end: ; preds = %entry + %call2 = call i32 @getval() + br label %do.body + +do.body: ; preds = %do.cond, %if.end + %call6 = call i32 @bar() + %cmp = icmp ne i32 %call6, 0 + br i1 %cmp, label %land.lhs.true, label %do.cond + +land.lhs.true: ; preds = %do.body + %call10 = call i32 @getval() + %cmp11 = icmp eq i32 0, %call10 + br i1 %cmp11, label %return, label %do.cond + +do.cond: ; preds = %land.lhs.true, %do.body + %cmp18 = icmp sle i32 0, %call2 + br i1 %cmp18, label %do.body, label %return + +return: ; preds = %do.cond, %land.lhs.true, %entry + %retval.0 = phi i32 [ 0, %entry ], [ %call6, %land.lhs.true ], [ 0, %do.cond ] + ret i32 %retval.0 +} + +define linkonce_odr i32 @bar() nounwind uwtable ssp align 2 { +entry: + br i1 undef, label %land.lhs.true, label %cond.end + +land.lhs.true: ; preds = %entry + %cmp4 = call zeroext i1 @check() + br i1 %cmp4, label %cond.true, label %cond.end + +cond.true: ; preds = %land.lhs.true + %tmp7 = call i32 @getval() + br label %cond.end + +cond.end: ; preds = %cond.true, %land.lhs.true, %entry + %cond = phi i32 [ %tmp7, %cond.true ], [ 0, %land.lhs.true ], [ 0, %entry ] + ret i32 %cond +} diff --git a/test/Transforms/LoopUnroll/2011-10-01-NoopTrunc.ll b/test/Transforms/LoopUnroll/2011-10-01-NoopTrunc.ll new file mode 100644 index 0000000000000..7fb471ea75092 --- /dev/null +++ b/test/Transforms/LoopUnroll/2011-10-01-NoopTrunc.ll @@ -0,0 +1,36 @@ +; RUN: opt < %s -S -loop-unroll -unroll-threshold=150 | FileCheck %s +; +; Verify that trunc i64 to i32 is considered free by loop unrolling +; heuristics when i32 is a native type. +; This should result in full unrolling this loop with size=7, TC=19. +; If the trunc were not free we would have 8*19=152 > 150. + +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" + +; Check that for.body was unrolled 19 times. +; CHECK: @test +; CHECK: %0 = load +; CHECK: %conv = sext i8 %0 to i32 +; CHECK: %add.1 = add nsw i32 %conv.1, %conv +; CHECK: %add.18 = add nsw i32 %conv.18, %add.17 +; CHECK: ret i32 %add.18 +define i32 @test(i8* %arr) nounwind uwtable readnone { +entry: + br label %for.body + +for.body: ; preds = %for.body, %entry + %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] + %sum.02 = phi i32 [ 0, %entry ], [ %add, %for.body ] + %arrayidx = getelementptr inbounds i8* %arr, i64 %indvars.iv + %0 = load i8* %arrayidx, align 1 + %conv = sext i8 %0 to i32 + %add = add nsw i32 %conv, %sum.02 + %indvars.iv.next = add i64 %indvars.iv, 1 + %lftr.wideiv1 = trunc i64 %indvars.iv.next to i32 + %exitcond2 = icmp eq i32 %lftr.wideiv1, 19 + br i1 %exitcond2, label %for.end, label %for.body + +for.end: ; preds = %for.body + %add.lcssa = phi i32 [ %add, %for.body ] + ret i32 %add.lcssa +} diff --git a/test/Transforms/LoopUnroll/pr10813.ll b/test/Transforms/LoopUnroll/pr10813.ll new file mode 100644 index 0000000000000..7daefc2f788e2 --- /dev/null +++ b/test/Transforms/LoopUnroll/pr10813.ll @@ -0,0 +1,29 @@ +; RUN: opt < %s -loop-unroll -disable-output + +define void @"f_fu___REFUf[]REFUf[]Uf"() nounwind { +allocas: + br i1 undef, label %cif_mask_all, label %cif_mixed_test_all + +cif_mask_all: ; preds = %allocas + unreachable + +cif_mixed_test_all: ; preds = %allocas + br label %pl_loop.i964 + +pl_loop.i964: ; preds = %pl_loopend.i973, %cif_mixed_test_all + %0 = phi i32 [ %pl_nextlane.i971, %pl_loopend.i973 ], [ 0, %cif_mixed_test_all ] + br i1 undef, label %pl_dolane.i970, label %pl_loopend.i973 + +pl_dolane.i970: ; preds = %pl_loop.i964 + %storeval.i.i969 = extractelement <4 x i8> <i8 0, i8 1, i8 2, i8 3>, i32 %0 + store i8 %storeval.i.i969, i8* undef, align 1 + br label %pl_loopend.i973 + +pl_loopend.i973: ; preds = %pl_dolane.i970, %pl_loop.i964 + %pl_nextlane.i971 = add i32 %0, 1 + %exitcond5 = icmp ne i32 %pl_nextlane.i971, 5 + br i1 %exitcond5, label %pl_loop.i964, label %__scatter_base_offsets_i8.exit974 + +__scatter_base_offsets_i8.exit974: ; preds = %pl_loopend.i973 + unreachable +} diff --git a/test/Transforms/LoopUnroll/scevunroll.ll b/test/Transforms/LoopUnroll/scevunroll.ll new file mode 100644 index 0000000000000..99b3a7d861971 --- /dev/null +++ b/test/Transforms/LoopUnroll/scevunroll.ll @@ -0,0 +1,172 @@ +; RUN: opt < %s -S -indvars -loop-unroll -verify-loop-info | FileCheck %s +; +; Unit tests for loop unrolling using ScalarEvolution to compute trip counts. +; +; Indvars is run first to generate an "old" SCEV result. Some unit +; tests may check that SCEV is properly invalidated between passes. + +; Completely unroll loops without a canonical IV. +; +; CHECK: @sansCanonical +; CHECK-NOT: phi +; CHECK-NOT: icmp +; CHECK: ret +define i32 @sansCanonical(i32* %base) nounwind { +entry: + br label %while.body + +while.body: + %iv = phi i64 [ 10, %entry ], [ %iv.next, %while.body ] + %sum = phi i32 [ 0, %entry ], [ %sum.next, %while.body ] + %iv.next = add i64 %iv, -1 + %adr = getelementptr inbounds i32* %base, i64 %iv.next + %tmp = load i32* %adr, align 8 + %sum.next = add i32 %sum, %tmp + %iv.narrow = trunc i64 %iv.next to i32 + %cmp.i65 = icmp sgt i32 %iv.narrow, 0 + br i1 %cmp.i65, label %while.body, label %exit + +exit: + ret i32 %sum +} + +; SCEV unrolling properly handles loops with multiple exits. In this +; case, the computed trip count based on a canonical IV is *not* for a +; latch block. Canonical unrolling incorrectly unrolls it, but SCEV +; unrolling does not. +; +; CHECK: @earlyLoopTest +; CHECK: tail: +; CHECK-NOT: br +; CHECK: br i1 %cmp2, label %loop, label %exit2 +define i64 @earlyLoopTest(i64* %base) nounwind { +entry: + br label %loop + +loop: + %iv = phi i64 [ 0, %entry ], [ %inc, %tail ] + %s = phi i64 [ 0, %entry ], [ %s.next, %tail ] + %adr = getelementptr i64* %base, i64 %iv + %val = load i64* %adr + %s.next = add i64 %s, %val + %inc = add i64 %iv, 1 + %cmp = icmp ne i64 %inc, 4 + br i1 %cmp, label %tail, label %exit1 + +tail: + %cmp2 = icmp ne i64 %val, 0 + br i1 %cmp2, label %loop, label %exit2 + +exit1: + ret i64 %s + +exit2: + ret i64 %s.next +} + +; SCEV properly unrolls multi-exit loops. +; +; CHECK: @multiExit +; CHECK: getelementptr i32* %base, i32 10 +; CHECK-NEXT: load i32* +; CHECK: br i1 false, label %l2.10, label %exit1 +; CHECK: l2.10: +; CHECK-NOT: br +; CHECK: ret i32 +define i32 @multiExit(i32* %base) nounwind { +entry: + br label %l1 +l1: + %iv1 = phi i32 [ 0, %entry ], [ %inc1, %l2 ] + %iv2 = phi i32 [ 0, %entry ], [ %inc2, %l2 ] + %inc1 = add i32 %iv1, 1 + %inc2 = add i32 %iv2, 1 + %adr = getelementptr i32* %base, i32 %iv1 + %val = load i32* %adr + %cmp1 = icmp slt i32 %iv1, 5 + br i1 %cmp1, label %l2, label %exit1 +l2: + %cmp2 = icmp slt i32 %iv2, 10 + br i1 %cmp2, label %l1, label %exit2 +exit1: + ret i32 1 +exit2: + ret i32 %val +} + + +; SCEV should not unroll a multi-exit loops unless the latch block has +; a known trip count, regardless of the early exit trip counts. The +; LoopUnroll utility uses this assumption to optimize the latch +; block's branch. +; +; CHECK: @multiExit +; CHECK: l3: +; CHECK-NOT: br +; CHECK: br i1 %cmp3, label %l1, label %exit3 +define i32 @multiExitIncomplete(i32* %base) nounwind { +entry: + br label %l1 +l1: + %iv1 = phi i32 [ 0, %entry ], [ %inc1, %l3 ] + %iv2 = phi i32 [ 0, %entry ], [ %inc2, %l3 ] + %inc1 = add i32 %iv1, 1 + %inc2 = add i32 %iv2, 1 + %adr = getelementptr i32* %base, i32 %iv1 + %val = load i32* %adr + %cmp1 = icmp slt i32 %iv1, 5 + br i1 %cmp1, label %l2, label %exit1 +l2: + %cmp2 = icmp slt i32 %iv2, 10 + br i1 %cmp2, label %l3, label %exit2 +l3: + %cmp3 = icmp ne i32 %val, 0 + br i1 %cmp3, label %l1, label %exit3 + +exit1: + ret i32 1 +exit2: + ret i32 2 +exit3: + ret i32 3 +} + +; When loop unroll merges a loop exit with one of its parent loop's +; exits, SCEV must forget its ExitNotTaken info. +; +; CHECK: @nestedUnroll +; CHECK-NOT: br i1 +; CHECK: for.body87: +define void @nestedUnroll() nounwind { +entry: + br label %for.inc + +for.inc: + br i1 false, label %for.inc, label %for.body38.preheader + +for.body38.preheader: + br label %for.body38 + +for.body38: + %i.113 = phi i32 [ %inc76, %for.inc74 ], [ 0, %for.body38.preheader ] + %mul48 = mul nsw i32 %i.113, 6 + br label %for.body43 + +for.body43: + %j.011 = phi i32 [ 0, %for.body38 ], [ %inc72, %for.body43 ] + %add49 = add nsw i32 %j.011, %mul48 + %sh_prom50 = zext i32 %add49 to i64 + %inc72 = add nsw i32 %j.011, 1 + br i1 false, label %for.body43, label %for.inc74 + +for.inc74: + %inc76 = add nsw i32 %i.113, 1 + br i1 false, label %for.body38, label %for.body87.preheader + +for.body87.preheader: + br label %for.body87 + +for.body87: + br label %for.body87 +} + diff --git a/test/Transforms/LoopUnroll/unloop.ll b/test/Transforms/LoopUnroll/unloop.ll new file mode 100644 index 0000000000000..217c8cea56f7e --- /dev/null +++ b/test/Transforms/LoopUnroll/unloop.ll @@ -0,0 +1,429 @@ +; RUN: opt < %s -S -loop-unroll -verify-loop-info | FileCheck %s +; +; Unit tests for LoopInfo::updateUnloop. + +declare i1 @check() nounwind + +; Ensure that tail->inner is removed and rely on verify-loopinfo to +; check soundness. +; +; CHECK: @skiplevelexit +; CHECK: tail: +; CHECK-NOT: br +; CHECK: ret void +define void @skiplevelexit() nounwind { +entry: + br label %outer + +outer: + br label %inner + +inner: + %iv = phi i32 [ 0, %outer ], [ %inc, %tail ] + %inc = add i32 %iv, 1 + %wbucond = call zeroext i1 @check() + br i1 %wbucond, label %outer.backedge, label %tail + +tail: + br i1 false, label %inner, label %exit + +outer.backedge: + br label %outer + +exit: + ret void +} + +; Remove the middle loop of a triply nested loop tree. +; Ensure that only the middle loop is removed and rely on verify-loopinfo to +; check soundness. +; +; CHECK: @unloopNested +; Outer loop control. +; CHECK: while.body: +; CHECK: br i1 %cmp3, label %if.then, label %if.end +; Inner loop control. +; CHECK: while.end14.i: +; CHECK: br i1 %call15.i, label %if.end.i, label %exit +; Middle loop control should no longer reach %while.cond. +; Now it is the outer loop backedge. +; CHECK: exit: +; CHECK: br label %while.cond.outer +define void @unloopNested() { +entry: + br label %while.cond.outer + +while.cond.outer: + br label %while.cond + +while.cond: + %cmp = call zeroext i1 @check() + br i1 %cmp, label %while.body, label %while.end + +while.body: + %cmp3 = call zeroext i1 @check() + br i1 %cmp3, label %if.then, label %if.end + +if.then: + br label %return + +if.end: + %cmp.i48 = call zeroext i1 @check() + br i1 %cmp.i48, label %if.then.i, label %if.else20.i + +if.then.i: + %cmp8.i = call zeroext i1 @check() + br i1 %cmp8.i, label %merge, label %if.else.i + +if.else.i: + br label %merge + +if.else20.i: + %cmp25.i = call zeroext i1 @check() + br i1 %cmp25.i, label %merge, label %if.else28.i + +if.else28.i: + br label %merge + +merge: + br label %while.cond2.i + +while.cond2.i: + %cmp.i = call zeroext i1 @check() + br i1 %cmp.i, label %while.cond2.backedge.i, label %while.end.i + +while.cond2.backedge.i: + br label %while.cond2.i + +while.end.i: + %cmp1114.i = call zeroext i1 @check() + br i1 %cmp1114.i, label %while.body12.lr.ph.i, label %while.end14.i + +while.body12.lr.ph.i: + br label %while.end14.i + +while.end14.i: + %call15.i = call zeroext i1 @check() + br i1 %call15.i, label %if.end.i, label %exit + +if.end.i: + br label %while.cond2.backedge.i + +exit: + br i1 false, label %while.cond, label %if.else + +if.else: + br label %while.cond.outer + +while.end: + br label %return + +return: + ret void +} + +; Remove the middle loop of a deeply nested loop tree. +; Ensure that only the middle loop is removed and rely on verify-loopinfo to +; check soundness. +; +; CHECK: @unloopDeepNested +; Inner-inner loop control. +; CHECK: while.cond.us.i: +; CHECK: br i1 %cmp.us.i, label %next_data.exit, label %while.body.us.i +; CHECK: if.then.us.i: +; CHECK: br label %while.cond.us.i +; Inner loop tail. +; CHECK: if.else.i: +; CHECK: br label %while.cond.outer.i +; Middle loop control (removed). +; CHECK: valid_data.exit: +; CHECK-NOT: br +; CHECK: %cmp = call zeroext i1 @check() +; Outer loop control. +; CHECK: copy_data.exit: +; CHECK: br i1 %cmp38, label %if.then39, label %while.cond.outer +; Outer-outer loop tail. +; CHECK: while.cond.outer.outer.backedge: +; CHECK: br label %while.cond.outer.outer +define void @unloopDeepNested() nounwind { +for.cond8.preheader.i: + %cmp113.i = call zeroext i1 @check() + br i1 %cmp113.i, label %make_data.exit, label %for.body13.lr.ph.i + +for.body13.lr.ph.i: + br label %make_data.exit + +make_data.exit: + br label %while.cond.outer.outer + +while.cond.outer.outer: + br label %while.cond.outer + +while.cond.outer: + br label %while.cond + +while.cond: + br label %while.cond.outer.i + +while.cond.outer.i: + %tmp192.ph.i = call zeroext i1 @check() + br i1 %tmp192.ph.i, label %while.cond.outer.split.us.i, label %while.body.loopexit + +while.cond.outer.split.us.i: + br label %while.cond.us.i + +while.cond.us.i: + %cmp.us.i = call zeroext i1 @check() + br i1 %cmp.us.i, label %next_data.exit, label %while.body.us.i + +while.body.us.i: + %cmp7.us.i = call zeroext i1 @check() + br i1 %cmp7.us.i, label %if.then.us.i, label %if.else.i + +if.then.us.i: + br label %while.cond.us.i + +if.else.i: + br label %while.cond.outer.i + +next_data.exit: + %tmp192.ph.i.lcssa28 = call zeroext i1 @check() + br i1 %tmp192.ph.i.lcssa28, label %while.end, label %while.body + +while.body.loopexit: + br label %while.body + +while.body: + br label %while.cond.i + +while.cond.i: + %cmp.i = call zeroext i1 @check() + br i1 %cmp.i, label %valid_data.exit, label %while.body.i + +while.body.i: + %cmp7.i = call zeroext i1 @check() + br i1 %cmp7.i, label %valid_data.exit, label %if.end.i + +if.end.i: + br label %while.cond.i + +valid_data.exit: + br i1 true, label %if.then, label %while.cond + +if.then: + %cmp = call zeroext i1 @check() + br i1 %cmp, label %if.then12, label %if.end + +if.then12: + br label %if.end + +if.end: + %tobool3.i = call zeroext i1 @check() + br i1 %tobool3.i, label %copy_data.exit, label %while.body.lr.ph.i + +while.body.lr.ph.i: + br label %copy_data.exit + +copy_data.exit: + %cmp38 = call zeroext i1 @check() + br i1 %cmp38, label %if.then39, label %while.cond.outer + +if.then39: + %cmp5.i = call zeroext i1 @check() + br i1 %cmp5.i, label %while.cond.outer.outer.backedge, label %for.cond8.preheader.i8.thread + +for.cond8.preheader.i8.thread: + br label %while.cond.outer.outer.backedge + +while.cond.outer.outer.backedge: + br label %while.cond.outer.outer + +while.end: + ret void +} + +; Remove a nested loop with irreducible control flow. +; Ensure that only the middle loop is removed and rely on verify-loopinfo to +; check soundness. +; +; CHECK: @unloopIrreducible +; Irreducible loop. +; CHECK: for.inc117: +; CHECK: br label %for.cond103t +; Nested loop (removed). +; CHECK: for.inc159: +; CHECK: br label %for.inc163 +define void @unloopIrreducible() nounwind { + +entry: + br label %for.body + +for.body: + %cmp2113 = call zeroext i1 @check() + br i1 %cmp2113, label %for.body22.lr.ph, label %for.inc163 + +for.body22.lr.ph: + br label %for.body22 + +for.body22: + br label %for.body33 + +for.body33: + br label %for.end + +for.end: + %cmp424 = call zeroext i1 @check() + br i1 %cmp424, label %for.body43.lr.ph, label %for.end93 + +for.body43.lr.ph: + br label %for.end93 + +for.end93: + %cmp96 = call zeroext i1 @check() + br i1 %cmp96, label %if.then97, label %for.cond103 + +if.then97: + br label %for.cond103t + +for.cond103t: + br label %for.cond103 + +for.cond103: + %cmp105 = call zeroext i1 @check() + br i1 %cmp105, label %for.body106, label %for.end120 + +for.body106: + %cmp108 = call zeroext i1 @check() + br i1 %cmp108, label %if.then109, label %for.inc117 + +if.then109: + br label %for.inc117 + +for.inc117: + br label %for.cond103t + +for.end120: + br label %for.inc159 + +for.inc159: + br i1 false, label %for.body22, label %for.cond15.for.inc163_crit_edge + +for.cond15.for.inc163_crit_edge: + br label %for.inc163 + +for.inc163: + %cmp12 = call zeroext i1 @check() + br i1 %cmp12, label %for.body, label %for.end166 + +for.end166: + ret void + +} + +; Remove a loop whose exit branches into a sibling loop. +; Ensure that only the loop is removed and rely on verify-loopinfo to +; check soundness. +; +; CHECK: @unloopCriticalEdge +; CHECK: while.cond.outer.i.loopexit.split: +; CHECK: br label %while.body +; CHECK: while.body: +; CHECK: br label %for.end78 +define void @unloopCriticalEdge() nounwind { +entry: + br label %for.cond31 + +for.cond31: + br i1 undef, label %for.body35, label %for.end94 + +for.body35: + br label %while.cond.i.preheader + +while.cond.i.preheader: + br i1 undef, label %while.cond.i.preheader.split, label %while.cond.outer.i.loopexit.split + +while.cond.i.preheader.split: + br label %while.cond.i + +while.cond.i: + br i1 true, label %while.cond.i, label %while.cond.outer.i.loopexit + +while.cond.outer.i.loopexit: + br label %while.cond.outer.i.loopexit.split + +while.cond.outer.i.loopexit.split: + br i1 false, label %while.cond.i.preheader, label %Func2.exit + +Func2.exit: + br label %while.body + +while.body: + br i1 false, label %while.body, label %while.end + +while.end: + br label %for.end78 + +for.end78: + br i1 undef, label %Proc2.exit, label %for.cond.i.preheader + +for.cond.i.preheader: + br label %for.cond.i + +for.cond.i: + br label %for.cond.i + +Proc2.exit: + br label %for.cond31 + +for.end94: + ret void +} + +; Test UnloopUpdater::removeBlocksFromAncestors. +; +; Check that the loop backedge is removed from the middle loop 1699, +; but not the inner loop 1676. +; CHECK: while.body1694: +; CHECK: br label %while.cond1676 +; CHECK: while.end1699: +; CHECK: br label %sw.default1711 +define void @removeSubloopBlocks() nounwind { +entry: + br label %tryagain.outer + +tryagain.outer: ; preds = %sw.bb304, %entry + br label %tryagain + +tryagain: ; preds = %while.end1699, %tryagain.outer + br i1 undef, label %sw.bb1669, label %sw.bb304 + +sw.bb304: ; preds = %tryagain + br i1 undef, label %return, label %tryagain.outer + +sw.bb1669: ; preds = %tryagain + br i1 undef, label %sw.default1711, label %while.cond1676 + +while.cond1676: ; preds = %while.body1694, %sw.bb1669 + br i1 undef, label %while.end1699, label %while.body1694 + +while.body1694: ; preds = %while.cond1676 + br label %while.cond1676 + +while.end1699: ; preds = %while.cond1676 + br i1 false, label %tryagain, label %sw.default1711 + +sw.default1711: ; preds = %while.end1699, %sw.bb1669, %tryagain + br label %defchar + +defchar: ; preds = %sw.default1711, %sw.bb376 + br i1 undef, label %if.end2413, label %if.then2368 + +if.then2368: ; preds = %defchar + unreachable + +if.end2413: ; preds = %defchar + unreachable + +return: ; preds = %sw.bb304 + ret void +} diff --git a/test/Transforms/LoopUnswitch/2011-09-26-EHCrash.ll b/test/Transforms/LoopUnswitch/2011-09-26-EHCrash.ll new file mode 100644 index 0000000000000..0e3103dc6db71 --- /dev/null +++ b/test/Transforms/LoopUnswitch/2011-09-26-EHCrash.ll @@ -0,0 +1,67 @@ +; RUN: opt < %s -scalarrepl-ssa -loop-unswitch -disable-output +; PR11016 +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" +target triple = "x86_64-apple-macosx10.7.2" + +%class.MyContainer.1.3.19.29 = type { [6 x %class.MyMemVarClass.0.2.18.28*] } +%class.MyMemVarClass.0.2.18.28 = type { i32 } + +define void @_ZN11MyContainer1fEi(%class.MyContainer.1.3.19.29* %this, i32 %doit) uwtable ssp align 2 { +entry: + br label %for.cond + +for.cond: ; preds = %for.inc, %entry + %inc1 = phi i32 [ %inc, %for.inc ], [ 0, %entry ] + %conv = sext i32 %inc1 to i64 + %cmp = icmp ult i64 %conv, 6 + br i1 %cmp, label %for.body, label %for.end + +for.body: ; preds = %for.cond + %tobool = icmp ne i32 %doit, 0 + br i1 %tobool, label %for.inc, label %if.then + +if.then: ; preds = %for.body + %idxprom = sext i32 %inc1 to i64 + %array_ = getelementptr inbounds %class.MyContainer.1.3.19.29* %this, i32 0, i32 0 + %arrayidx = getelementptr inbounds [6 x %class.MyMemVarClass.0.2.18.28*]* %array_, i32 0, i64 %idxprom + %tmp4 = load %class.MyMemVarClass.0.2.18.28** %arrayidx, align 8, !tbaa !0 + %isnull = icmp eq %class.MyMemVarClass.0.2.18.28* %tmp4, null + br i1 %isnull, label %for.inc, label %delete.notnull + +delete.notnull: ; preds = %if.then + invoke void @_ZN13MyMemVarClassD1Ev(%class.MyMemVarClass.0.2.18.28* %tmp4) + to label %invoke.cont unwind label %lpad + +invoke.cont: ; preds = %delete.notnull + %0 = bitcast %class.MyMemVarClass.0.2.18.28* %tmp4 to i8* + call void @_ZdlPv(i8* %0) nounwind + br label %for.inc + +lpad: ; preds = %delete.notnull + %1 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + cleanup + %2 = extractvalue { i8*, i32 } %1, 0 + %3 = extractvalue { i8*, i32 } %1, 1 + %4 = bitcast %class.MyMemVarClass.0.2.18.28* %tmp4 to i8* + call void @_ZdlPv(i8* %4) nounwind + %lpad.val = insertvalue { i8*, i32 } undef, i8* %2, 0 + %lpad.val7 = insertvalue { i8*, i32 } %lpad.val, i32 %3, 1 + resume { i8*, i32 } %lpad.val7 + +for.inc: ; preds = %invoke.cont, %if.then, %for.body + %inc = add nsw i32 %inc1, 1 + br label %for.cond + +for.end: ; preds = %for.cond + ret void +} + +declare void @_ZN13MyMemVarClassD1Ev(%class.MyMemVarClass.0.2.18.28*) + +declare i32 @__gxx_personality_v0(...) + +declare void @_ZdlPv(i8*) nounwind + +!0 = metadata !{metadata !"any pointer", metadata !1} +!1 = metadata !{metadata !"omnipotent char", metadata !2} +!2 = metadata !{metadata !"Simple C/C++ TBAA", null} diff --git a/test/Transforms/LowerAtomic/atomic-load.ll b/test/Transforms/LowerAtomic/atomic-load.ll index 5b110d6b7eba4..bc04e88344ef9 100644 --- a/test/Transforms/LowerAtomic/atomic-load.ll +++ b/test/Transforms/LowerAtomic/atomic-load.ll @@ -1,13 +1,9 @@ ; RUN: opt < %s -loweratomic -S | FileCheck %s -declare i8 @llvm.atomic.load.add.i8.p0i8(i8* %ptr, i8 %delta) -declare i8 @llvm.atomic.load.nand.i8.p0i8(i8* %ptr, i8 %delta) -declare i8 @llvm.atomic.load.min.i8.p0i8(i8* %ptr, i8 %delta) - define i8 @add() { ; CHECK: @add %i = alloca i8 - %j = call i8 @llvm.atomic.load.add.i8.p0i8(i8* %i, i8 42) + %j = atomicrmw add i8* %i, i8 42 monotonic ; CHECK: [[INST:%[a-z0-9]+]] = load ; CHECK-NEXT: add ; CHECK-NEXT: store @@ -18,7 +14,7 @@ define i8 @add() { define i8 @nand() { ; CHECK: @nand %i = alloca i8 - %j = call i8 @llvm.atomic.load.nand.i8.p0i8(i8* %i, i8 42) + %j = atomicrmw nand i8* %i, i8 42 monotonic ; CHECK: [[INST:%[a-z0-9]+]] = load ; CHECK-NEXT: and ; CHECK-NEXT: xor @@ -30,7 +26,7 @@ define i8 @nand() { define i8 @min() { ; CHECK: @min %i = alloca i8 - %j = call i8 @llvm.atomic.load.min.i8.p0i8(i8* %i, i8 42) + %j = atomicrmw min i8* %i, i8 42 monotonic ; CHECK: [[INST:%[a-z0-9]+]] = load ; CHECK-NEXT: icmp ; CHECK-NEXT: select diff --git a/test/Transforms/LowerAtomic/atomic-swap.ll b/test/Transforms/LowerAtomic/atomic-swap.ll index 0a59c8595e6a0..5e2f034a5177a 100644 --- a/test/Transforms/LowerAtomic/atomic-swap.ll +++ b/test/Transforms/LowerAtomic/atomic-swap.ll @@ -1,12 +1,9 @@ ; RUN: opt < %s -loweratomic -S | FileCheck %s -declare i8 @llvm.atomic.cmp.swap.i8.p0i8(i8* %ptr, i8 %cmp, i8 %val) -declare i8 @llvm.atomic.swap.i8.p0i8(i8* %ptr, i8 %val) - define i8 @cmpswap() { ; CHECK: @cmpswap %i = alloca i8 - %j = call i8 @llvm.atomic.cmp.swap.i8.p0i8(i8* %i, i8 0, i8 42) + %j = cmpxchg i8* %i, i8 0, i8 42 monotonic ; CHECK: [[INST:%[a-z0-9]+]] = load ; CHECK-NEXT: icmp ; CHECK-NEXT: select @@ -18,7 +15,7 @@ define i8 @cmpswap() { define i8 @swap() { ; CHECK: @swap %i = alloca i8 - %j = call i8 @llvm.atomic.swap.i8.p0i8(i8* %i, i8 42) + %j = atomicrmw xchg i8* %i, i8 42 monotonic ; CHECK: [[INST:%[a-z0-9]+]] = load ; CHECK-NEXT: store ret i8 %j diff --git a/test/Transforms/LowerAtomic/barrier.ll b/test/Transforms/LowerAtomic/barrier.ll index 218c5ba8d18e8..814d7afb5ff9e 100644 --- a/test/Transforms/LowerAtomic/barrier.ll +++ b/test/Transforms/LowerAtomic/barrier.ll @@ -1,10 +1,8 @@ ; RUN: opt < %s -loweratomic -S | FileCheck %s -declare void @llvm.memory.barrier(i1 %ll, i1 %ls, i1 %sl, i1 %ss, i1 %device) - define void @barrier() { ; CHECK: @barrier - call void @llvm.memory.barrier(i1 0, i1 0, i1 0, i1 0, i1 0) + fence seq_cst ; CHECK-NEXT: ret ret void } diff --git a/test/Transforms/LowerSetJmp/2003-11-05-DominanceProperties.ll b/test/Transforms/LowerSetJmp/2003-11-05-DominanceProperties.ll deleted file mode 100644 index 9180c15b18f2b..0000000000000 --- a/test/Transforms/LowerSetJmp/2003-11-05-DominanceProperties.ll +++ /dev/null @@ -1,16 +0,0 @@ -; RUN: opt < %s -lowersetjmp -disable-output - - %struct.jmpenv = type { i32, i8 } - -declare void @Perl_sv_setpv() - -declare i32 @llvm.setjmp(i32*) - -define void @perl_call_sv() { - call void @Perl_sv_setpv( ) - %tmp.335 = getelementptr %struct.jmpenv* null, i64 0, i32 0 ; <i32*> [#uses=1] - %tmp.336 = call i32 @llvm.setjmp( i32* null ) ; <i32> [#uses=1] - store i32 %tmp.336, i32* %tmp.335 - ret void -} - diff --git a/test/Transforms/LowerSetJmp/dg.exp b/test/Transforms/LowerSetJmp/dg.exp deleted file mode 100644 index f2005891a59a8..0000000000000 --- a/test/Transforms/LowerSetJmp/dg.exp +++ /dev/null @@ -1,3 +0,0 @@ -load_lib llvm.exp - -RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll,c,cpp}]] diff --git a/test/Transforms/LowerSetJmp/simpletest.ll b/test/Transforms/LowerSetJmp/simpletest.ll deleted file mode 100644 index dece8405f28dd..0000000000000 --- a/test/Transforms/LowerSetJmp/simpletest.ll +++ /dev/null @@ -1,31 +0,0 @@ -; RUN: opt < %s -lowersetjmp -S | grep invoke - -@.str_1 = internal constant [13 x i8] c"returned %d\0A\00" ; <[13 x i8]*> [#uses=1] - -declare void @llvm.longjmp(i32*, i32) - -declare i32 @llvm.setjmp(i32*) - -declare void @foo() - -define i32 @simpletest() { - %B = alloca i32 ; <i32*> [#uses=2] - %Val = call i32 @llvm.setjmp( i32* %B ) ; <i32> [#uses=2] - %V = icmp ne i32 %Val, 0 ; <i1> [#uses=1] - br i1 %V, label %LongJumped, label %Normal -Normal: ; preds = %0 - call void @foo( ) - call void @llvm.longjmp( i32* %B, i32 42 ) - ret i32 0 -LongJumped: ; preds = %0 - ret i32 %Val -} - -declare i32 @printf(i8*, ...) - -define i32 @main() { - %V = call i32 @simpletest( ) ; <i32> [#uses=1] - call i32 (i8*, ...)* @printf( i8* getelementptr ([13 x i8]* @.str_1, i64 0, i64 0), i32 %V ) ; <i32>:1 [#uses=0] - ret i32 0 -} - diff --git a/test/Transforms/Mem2Reg/2007-08-27-VolatileLoadsStores.ll b/test/Transforms/Mem2Reg/2007-08-27-VolatileLoadsStores.ll index 50683cf8baa0d..52a8375312961 100644 --- a/test/Transforms/Mem2Reg/2007-08-27-VolatileLoadsStores.ll +++ b/test/Transforms/Mem2Reg/2007-08-27-VolatileLoadsStores.ll @@ -42,6 +42,6 @@ return: ; preds = %bb6 ret i32 %retval8 } -declare i32 @_setjmp(%struct.__jmp_buf_tag*) +declare i32 @_setjmp(%struct.__jmp_buf_tag*) returns_twice declare void @g() diff --git a/test/Transforms/Mem2Reg/atomic.ll b/test/Transforms/Mem2Reg/atomic.ll new file mode 100644 index 0000000000000..982c41318b105 --- /dev/null +++ b/test/Transforms/Mem2Reg/atomic.ll @@ -0,0 +1,12 @@ +; RUN: opt -mem2reg < %s -S | FileCheck %s + +; mem2reg is allowed with arbitrary atomic operations (although we only support +; it for atomic load and store at the moment). +define i32 @test1(i32 %x) { +; CHECK: @test1 +; CHECK: ret i32 %x + %a = alloca i32 + store atomic i32 %x, i32* %a seq_cst, align 4 + %r = load atomic i32* %a seq_cst, align 4 + ret i32 %r +} diff --git a/test/Transforms/Mem2Reg/crash.ll b/test/Transforms/Mem2Reg/crash.ll index 655549f79402c..59e2c0b3108df 100644 --- a/test/Transforms/Mem2Reg/crash.ll +++ b/test/Transforms/Mem2Reg/crash.ll @@ -18,10 +18,13 @@ bb15: ret i32 %B lpad86: + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup br label %bb15 } +declare i32 @__gxx_personality_v0(...) define i32 @test2() { diff --git a/test/Transforms/MemCpyOpt/atomic.ll b/test/Transforms/MemCpyOpt/atomic.ll new file mode 100644 index 0000000000000..f351e6792e225 --- /dev/null +++ b/test/Transforms/MemCpyOpt/atomic.ll @@ -0,0 +1,41 @@ +; RUN: opt -basicaa -memcpyopt -S < %s | FileCheck %s + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" +target triple = "x86_64-apple-macosx10.7.0" + +@x = global i32 0 + +declare void @otherf(i32*) + +declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) nounwind + +; memcpyopt should not touch atomic ops +define void @test1() nounwind uwtable ssp { +; CHECK: test1 +; CHECK: store atomic + %x = alloca [101 x i32], align 16 + %bc = bitcast [101 x i32]* %x to i8* + call void @llvm.memset.p0i8.i64(i8* %bc, i8 0, i64 400, i32 16, i1 false) + %gep1 = getelementptr inbounds [101 x i32]* %x, i32 0, i32 100 + store atomic i32 0, i32* %gep1 unordered, align 4 + %gep2 = getelementptr inbounds [101 x i32]* %x, i32 0, i32 0 + call void @otherf(i32* %gep2) + ret void +} + +; memcpyopt across unordered store +define void @test2() nounwind uwtable ssp { +; CHECK: test2 +; CHECK: call +; CHECK-NEXT: store atomic +; CHECK-NEXT: call + %old = alloca i32 + %new = alloca i32 + call void @otherf(i32* nocapture %old) + store atomic i32 0, i32* @x unordered, align 4 + %v = load i32* %old + store i32 %v, i32* %new + call void @otherf(i32* nocapture %new) + ret void +} + diff --git a/test/Transforms/ObjCARC/basic.ll b/test/Transforms/ObjCARC/basic.ll index a6bbf8674b418..575cf42d4e65b 100644 --- a/test/Transforms/ObjCARC/basic.ll +++ b/test/Transforms/ObjCARC/basic.ll @@ -353,13 +353,14 @@ entry: ; CHECK: define void @test10( ; CHECK: @objc_retain(i8* %x) +; CHECK: @callee ; CHECK: @use_pointer ; CHECK: @objc_release ; CHECK: } define void @test10(i8* %x) nounwind { entry: %0 = call i8* @objc_retain(i8* %x) nounwind - call void @use_pointer(i8* %x) + call void @callee() call void @use_pointer(i8* %x) call void @objc_release(i8* %0) nounwind ret void @@ -697,6 +698,8 @@ invoke.cont23: ; preds = %if.then12 lpad20: ; preds = %invoke.cont23, %if.then12 %tmp502 = phi double* [ undef, %invoke.cont23 ], [ %self, %if.then12 ] + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup unreachable if.end: ; preds = %invoke.cont23 @@ -768,7 +771,7 @@ entry: define void @test23b(i8* %p) { entry: %0 = call i8* @objc_retainBlock(i8* %p) nounwind - call void @use_pointer(i8* %p) + call void @callee() call void @use_pointer(i8* %p) call void @objc_release(i8* %p) nounwind ret void @@ -1569,6 +1572,107 @@ if.end: ; preds = %entry, %if.then ret void } +; When there are adjacent retain+release pairs, the first one is +; known unnecessary because the presence of the second one means that +; the first one won't be deleting the object. + +; CHECK: define void @test57( +; CHECK-NEXT: entry: +; CHECK-NEXT: call void @use_pointer(i8* %x) +; CHECK-NEXT: call void @use_pointer(i8* %x) +; CHECK-NEXT: %0 = tail call i8* @objc_retain(i8* %x) nounwind +; CHECK-NEXT: call void @use_pointer(i8* %x) +; CHECK-NEXT: call void @use_pointer(i8* %x) +; CHECK-NEXT: call void @objc_release(i8* %x) nounwind +; CHECK-NEXT: ret void +; CHECK-NEXT: } +define void @test57(i8* %x) nounwind { +entry: + call i8* @objc_retain(i8* %x) nounwind + call void @use_pointer(i8* %x) + call void @use_pointer(i8* %x) + call void @objc_release(i8* %x) nounwind + call i8* @objc_retain(i8* %x) nounwind + call void @use_pointer(i8* %x) + call void @use_pointer(i8* %x) + call void @objc_release(i8* %x) nounwind + ret void +} + +; An adjacent retain+release pair is sufficient even if it will be +; removed itself. + +; CHECK: define void @test58( +; CHECK-NEXT: entry: +; CHECK-NEXT: call void @use_pointer(i8* %x) +; CHECK-NEXT: call void @use_pointer(i8* %x) +; CHECK-NEXT: ret void +; CHECK-NEXT: } +define void @test58(i8* %x) nounwind { +entry: + call i8* @objc_retain(i8* %x) nounwind + call void @use_pointer(i8* %x) + call void @use_pointer(i8* %x) + call void @objc_release(i8* %x) nounwind + call i8* @objc_retain(i8* %x) nounwind + call void @objc_release(i8* %x) nounwind + ret void +} + +; Don't delete the second retain+release pair in an adjacent set. + +; CHECK: define void @test59( +; CHECK-NEXT: entry: +; CHECK-NEXT: %0 = tail call i8* @objc_retain(i8* %x) nounwind +; CHECK-NEXT: call void @use_pointer(i8* %x) +; CHECK-NEXT: call void @use_pointer(i8* %x) +; CHECK-NEXT: call void @objc_release(i8* %x) nounwind +; CHECK-NEXT: ret void +; CHECK-NEXT: } +define void @test59(i8* %x) nounwind { +entry: + %a = call i8* @objc_retain(i8* %x) nounwind + call void @objc_release(i8* %x) nounwind + %b = call i8* @objc_retain(i8* %x) nounwind + call void @use_pointer(i8* %x) + call void @use_pointer(i8* %x) + call void @objc_release(i8* %x) nounwind + ret void +} + +; Constant pointers to objects don't need reference counting. + +@constptr = external constant i8* +@something = external global i8* + +; CHECK: define void @test60( +; CHECK-NOT: @objc_ +; CHECK: } +define void @test60() { + %t = load i8** @constptr + %s = load i8** @something + call i8* @objc_retain(i8* %s) + call void @callee() + call void @use_pointer(i8* %t) + call void @objc_release(i8* %s) + ret void +} + +; Constant pointers to objects don't need to be considered related to other +; pointers. + +; CHECK: define void @test61( +; CHECK-NOT: @objc_ +; CHECK: } +define void @test61() { + %t = load i8** @constptr + call i8* @objc_retain(i8* %t) + call void @callee() + call void @use_pointer(i8* %t) + call void @objc_release(i8* %t) + ret void +} + declare void @bar(i32 ()*) ; A few real-world testcases. @@ -1896,3 +2000,5 @@ end: ; preds = %if.end125, %if.end1 } !0 = metadata !{} + +declare i32 @__gxx_personality_v0(...) diff --git a/test/Transforms/ObjCARC/cfg-hazards.ll b/test/Transforms/ObjCARC/cfg-hazards.ll index e3624df57be86..15194237c4c59 100644 --- a/test/Transforms/ObjCARC/cfg-hazards.ll +++ b/test/Transforms/ObjCARC/cfg-hazards.ll @@ -7,6 +7,7 @@ declare void @use_pointer(i8*) declare i8* @objc_retain(i8*) declare void @objc_release(i8*) +declare void @callee() ; CHECK: define void @test0( ; CHECK: call i8* @objc_retain( @@ -18,18 +19,18 @@ declare void @objc_release(i8*) define void @test0(i8* %digits) { entry: %tmp1 = call i8* @objc_retain(i8* %digits) nounwind - call void @use_pointer(i8* %tmp1) + call void @use_pointer(i8* %digits) br label %for.body for.body: ; preds = %for.body, %entry %upcDigitIndex.01 = phi i64 [ 2, %entry ], [ %inc, %for.body ] - call void @use_pointer(i8* %tmp1) + call void @use_pointer(i8* %digits) %inc = add i64 %upcDigitIndex.01, 1 %cmp = icmp ult i64 %inc, 12 br i1 %cmp, label %for.body, label %for.end for.end: ; preds = %for.body - call void @objc_release(i8* %tmp1) nounwind, !clang.imprecise_release !0 + call void @objc_release(i8* %digits) nounwind, !clang.imprecise_release !0 ret void } @@ -47,14 +48,14 @@ entry: for.body: ; preds = %for.body, %entry %upcDigitIndex.01 = phi i64 [ 2, %entry ], [ %inc, %for.body ] - call void @use_pointer(i8* %tmp1) - call void @use_pointer(i8* %tmp1) + call void @use_pointer(i8* %digits) + call void @use_pointer(i8* %digits) %inc = add i64 %upcDigitIndex.01, 1 %cmp = icmp ult i64 %inc, 12 br i1 %cmp, label %for.body, label %for.end for.end: ; preds = %for.body - call void @objc_release(i8* %tmp1) nounwind, !clang.imprecise_release !0 + call void @objc_release(i8* %digits) nounwind, !clang.imprecise_release !0 ret void } @@ -72,14 +73,324 @@ entry: for.body: ; preds = %for.body, %entry %upcDigitIndex.01 = phi i64 [ 2, %entry ], [ %inc, %for.body ] - call void @use_pointer(i8* %tmp1) + call void @use_pointer(i8* %digits) %inc = add i64 %upcDigitIndex.01, 1 %cmp = icmp ult i64 %inc, 12 br i1 %cmp, label %for.body, label %for.end for.end: ; preds = %for.body - call void @use_pointer(i8* %tmp1) - call void @objc_release(i8* %tmp1) nounwind, !clang.imprecise_release !0 + call void @use_pointer(i8* %digits) + call void @objc_release(i8* %digits) nounwind, !clang.imprecise_release !0 + ret void +} + +; Delete nested retain+release pairs around loops. + +; CHECK: define void @test3(i8* %a) nounwind { +; CHECK-NEXT: entry: +; CHECK-NEXT: tail call i8* @objc_retain(i8* %a) nounwind +; CHECK-NEXT: br label %loop +; CHECK-NOT: @objc_ +; CHECK: exit: +; CHECK-NEXT: call void @objc_release(i8* %a) +; CHECK-NEXT: ret void +; CHECK-NEXT: } +define void @test3(i8* %a) nounwind { +entry: + %outer = call i8* @objc_retain(i8* %a) nounwind + %inner = call i8* @objc_retain(i8* %a) nounwind + br label %loop + +loop: + call void @callee() + store i8 0, i8* %a + br i1 undef, label %loop, label %exit + +exit: + call void @objc_release(i8* %a) nounwind + call void @objc_release(i8* %a) nounwind, !clang.imprecise_release !0 + ret void +} + +; CHECK: define void @test4(i8* %a) nounwind { +; CHECK-NEXT: entry: +; CHECK-NEXT: tail call i8* @objc_retain(i8* %a) nounwind +; CHECK-NEXT: br label %loop +; CHECK-NOT: @objc_ +; CHECK: exit: +; CHECK-NEXT: call void @objc_release(i8* %a) +; CHECK-NEXT: ret void +; CHECK-NEXT: } +define void @test4(i8* %a) nounwind { +entry: + %outer = call i8* @objc_retain(i8* %a) nounwind + %inner = call i8* @objc_retain(i8* %a) nounwind + br label %loop + +loop: + br label %more + +more: + call void @callee() + call void @callee() + store i8 0, i8* %a + br i1 undef, label %loop, label %exit + +exit: + call void @objc_release(i8* %a) nounwind + call void @objc_release(i8* %a) nounwind, !clang.imprecise_release !0 + ret void +} + +; CHECK: define void @test5(i8* %a) nounwind { +; CHECK-NEXT: entry: +; CHECK-NEXT: tail call i8* @objc_retain(i8* %a) nounwind +; CHECK-NEXT: call void @callee() +; CHECK-NEXT: br label %loop +; CHECK-NOT: @objc_ +; CHECK: exit: +; CHECK-NEXT: call void @use_pointer(i8* %a) +; CHECK-NEXT: call void @objc_release(i8* %a) +; CHECK-NEXT: ret void +; CHECK-NEXT: } +define void @test5(i8* %a) nounwind { +entry: + %outer = tail call i8* @objc_retain(i8* %a) nounwind + %inner = tail call i8* @objc_retain(i8* %a) nounwind + call void @callee() + br label %loop + +loop: + br i1 undef, label %true, label %more + +true: + br label %more + +more: + br i1 undef, label %exit, label %loop + +exit: + call void @use_pointer(i8* %a) + call void @objc_release(i8* %a) nounwind + call void @objc_release(i8* %a) nounwind, !clang.imprecise_release !0 + ret void +} + +; CHECK: define void @test6(i8* %a) nounwind { +; CHECK-NEXT: entry: +; CHECK-NEXT: tail call i8* @objc_retain(i8* %a) nounwind +; CHECK-NEXT: br label %loop +; CHECK-NOT: @objc_ +; CHECK: exit: +; CHECK-NEXT: call void @use_pointer(i8* %a) +; CHECK-NEXT: call void @objc_release(i8* %a) +; CHECK-NEXT: ret void +; CHECK-NEXT: } +define void @test6(i8* %a) nounwind { +entry: + %outer = tail call i8* @objc_retain(i8* %a) nounwind + %inner = tail call i8* @objc_retain(i8* %a) nounwind + br label %loop + +loop: + br i1 undef, label %true, label %more + +true: + call void @callee() + br label %more + +more: + br i1 undef, label %exit, label %loop + +exit: + call void @use_pointer(i8* %a) + call void @objc_release(i8* %a) nounwind + call void @objc_release(i8* %a) nounwind, !clang.imprecise_release !0 + ret void +} + +; CHECK: define void @test7(i8* %a) nounwind { +; CHECK-NEXT: entry: +; CHECK-NEXT: tail call i8* @objc_retain(i8* %a) nounwind +; CHECK-NEXT: call void @callee() +; CHECK-NEXT: br label %loop +; CHECK-NOT: @objc_ +; CHECK: exit: +; CHECK-NEXT: call void @objc_release(i8* %a) +; CHECK-NEXT: ret void +; CHECK-NEXT: } +define void @test7(i8* %a) nounwind { +entry: + %outer = tail call i8* @objc_retain(i8* %a) nounwind + %inner = tail call i8* @objc_retain(i8* %a) nounwind + call void @callee() + br label %loop + +loop: + br i1 undef, label %true, label %more + +true: + call void @use_pointer(i8* %a) + br label %more + +more: + br i1 undef, label %exit, label %loop + +exit: + call void @objc_release(i8* %a) nounwind + call void @objc_release(i8* %a) nounwind, !clang.imprecise_release !0 + ret void +} + +; CHECK: define void @test8(i8* %a) nounwind { +; CHECK-NEXT: entry: +; CHECK-NEXT: tail call i8* @objc_retain(i8* %a) nounwind +; CHECK-NEXT: br label %loop +; CHECK-NOT: @objc_ +; CHECK: exit: +; CHECK-NEXT: call void @objc_release(i8* %a) +; CHECK-NEXT: ret void +; CHECK-NEXT: } +define void @test8(i8* %a) nounwind { +entry: + %outer = tail call i8* @objc_retain(i8* %a) nounwind + %inner = tail call i8* @objc_retain(i8* %a) nounwind + br label %loop + +loop: + br i1 undef, label %true, label %more + +true: + call void @callee() + call void @use_pointer(i8* %a) + br label %more + +more: + br i1 undef, label %exit, label %loop + +exit: + call void @objc_release(i8* %a) nounwind + call void @objc_release(i8* %a) nounwind, !clang.imprecise_release !0 + ret void +} + +; CHECK: define void @test9(i8* %a) nounwind { +; CHECK-NEXT: entry: +; CHECK-NEXT: br label %loop +; CHECK-NOT: @objc_ +; CHECK: exit: +; CHECK-NEXT: ret void +; CHECK-NEXT: } +define void @test9(i8* %a) nounwind { +entry: + %outer = tail call i8* @objc_retain(i8* %a) nounwind + %inner = tail call i8* @objc_retain(i8* %a) nounwind + br label %loop + +loop: + br i1 undef, label %true, label %more + +true: + call void @use_pointer(i8* %a) + br label %more + +more: + br i1 undef, label %exit, label %loop + +exit: + call void @objc_release(i8* %a) nounwind + call void @objc_release(i8* %a) nounwind, !clang.imprecise_release !0 + ret void +} + +; CHECK: define void @test10(i8* %a) nounwind { +; CHECK-NEXT: entry: +; CHECK-NEXT: br label %loop +; CHECK-NOT: @objc_ +; CHECK: exit: +; CHECK-NEXT: ret void +; CHECK-NEXT: } +define void @test10(i8* %a) nounwind { +entry: + %outer = tail call i8* @objc_retain(i8* %a) nounwind + %inner = tail call i8* @objc_retain(i8* %a) nounwind + br label %loop + +loop: + br i1 undef, label %true, label %more + +true: + call void @callee() + br label %more + +more: + br i1 undef, label %exit, label %loop + +exit: + call void @objc_release(i8* %a) nounwind + call void @objc_release(i8* %a) nounwind, !clang.imprecise_release !0 + ret void +} + +; CHECK: define void @test11(i8* %a) nounwind { +; CHECK-NEXT: entry: +; CHECK-NEXT: br label %loop +; CHECK-NOT: @objc_ +; CHECK: exit: +; CHECK-NEXT: ret void +; CHECK-NEXT: } +define void @test11(i8* %a) nounwind { +entry: + %outer = tail call i8* @objc_retain(i8* %a) nounwind + %inner = tail call i8* @objc_retain(i8* %a) nounwind + br label %loop + +loop: + br i1 undef, label %true, label %more + +true: + br label %more + +more: + br i1 undef, label %exit, label %loop + +exit: + call void @objc_release(i8* %a) nounwind + call void @objc_release(i8* %a) nounwind, !clang.imprecise_release !0 + ret void +} + +; Don't delete anything if they're not balanced. + +; CHECK: define void @test12(i8* %a) nounwind { +; CHECK-NEXT: entry: +; CHECK-NEXT: %outer = tail call i8* @objc_retain(i8* %a) nounwind +; CHECK-NEXT: %inner = tail call i8* @objc_retain(i8* %a) nounwind +; CHECK-NEXT: br label %loop +; CHECK-NOT: @objc_ +; CHECK: exit: +; CHECK-NEXT: call void @objc_release(i8* %a) nounwind +; CHECK-NEXT: call void @objc_release(i8* %a) nounwind, !clang.imprecise_release !0 +; CHECK-NEXT: ret void +; CHECK-NEXT: } +define void @test12(i8* %a) nounwind { +entry: + %outer = tail call i8* @objc_retain(i8* %a) nounwind + %inner = tail call i8* @objc_retain(i8* %a) nounwind + br label %loop + +loop: + br i1 undef, label %true, label %more + +true: + ret void + +more: + br i1 undef, label %exit, label %loop + +exit: + call void @objc_release(i8* %a) nounwind + call void @objc_release(i8* %a) nounwind, !clang.imprecise_release !0 ret void } diff --git a/test/Transforms/ObjCARC/contract-storestrong.ll b/test/Transforms/ObjCARC/contract-storestrong.ll index 50ed260eb0865..25c93f411c8db 100644 --- a/test/Transforms/ObjCARC/contract-storestrong.ll +++ b/test/Transforms/ObjCARC/contract-storestrong.ll @@ -25,7 +25,7 @@ entry: ; CHECK: define void @test1(i8* %p) { ; CHECK-NEXT: entry: ; CHECK-NEXT: %0 = tail call i8* @objc_retain(i8* %p) nounwind -; CHECK-NEXT: %tmp = volatile load i8** @x, align 8 +; CHECK-NEXT: %tmp = load volatile i8** @x, align 8 ; CHECK-NEXT: store i8* %0, i8** @x, align 8 ; CHECK-NEXT: tail call void @objc_release(i8* %tmp) nounwind ; CHECK-NEXT: ret void @@ -45,7 +45,7 @@ entry: ; CHECK-NEXT: entry: ; CHECK-NEXT: %0 = tail call i8* @objc_retain(i8* %p) nounwind ; CHECK-NEXT: %tmp = load i8** @x, align 8 -; CHECK-NEXT: volatile store i8* %0, i8** @x, align 8 +; CHECK-NEXT: store volatile i8* %0, i8** @x, align 8 ; CHECK-NEXT: tail call void @objc_release(i8* %tmp) nounwind ; CHECK-NEXT: ret void ; CHECK-NEXT: } diff --git a/test/Transforms/ObjCARC/empty-block.ll b/test/Transforms/ObjCARC/empty-block.ll new file mode 100644 index 0000000000000..ca5541365a4ec --- /dev/null +++ b/test/Transforms/ObjCARC/empty-block.ll @@ -0,0 +1,59 @@ +; RUN: opt -S -objc-arc < %s | FileCheck %s +; rdar://10210274 + +%0 = type opaque + +declare i8* @objc_retain(i8*) + +declare void @objc_release(i8*) + +declare i8* @objc_autoreleaseReturnValue(i8*) + +; Don't delete the autorelease. + +; CHECK: define %0* @test0( +; CHECK: @objc_retain +; CHECK: .lr.ph: +; CHECK-NOT: @objc_r +; CHECK: @objc_autoreleaseReturnValue +; CHECK-NOT: @objc_ +; CHECK: } +define %0* @test0(%0* %buffer) nounwind { + %1 = bitcast %0* %buffer to i8* + %2 = tail call i8* @objc_retain(i8* %1) nounwind + br i1 undef, label %.lr.ph, label %._crit_edge + +.lr.ph: ; preds = %.lr.ph, %0 + br i1 false, label %.lr.ph, label %._crit_edge + +._crit_edge: ; preds = %.lr.ph, %0 + %3 = tail call i8* @objc_retain(i8* %1) nounwind + tail call void @objc_release(i8* %1) nounwind, !clang.imprecise_release !0 + %4 = tail call i8* @objc_autoreleaseReturnValue(i8* %1) nounwind + ret %0* %buffer +} + +; Do delete the autorelease, even with the retain in a different block. + +; CHECK: define %0* @test1( +; CHECK-NOT: @objc +; CHECK: } +define %0* @test1() nounwind { + %buffer = call %0* @foo() + %1 = bitcast %0* %buffer to i8* + %2 = tail call i8* @objc_retain(i8* %1) nounwind + br i1 undef, label %.lr.ph, label %._crit_edge + +.lr.ph: ; preds = %.lr.ph, %0 + br i1 false, label %.lr.ph, label %._crit_edge + +._crit_edge: ; preds = %.lr.ph, %0 + %3 = tail call i8* @objc_retain(i8* %1) nounwind + tail call void @objc_release(i8* %1) nounwind, !clang.imprecise_release !0 + %4 = tail call i8* @objc_autoreleaseReturnValue(i8* %1) nounwind + ret %0* %buffer +} + +declare %0* @foo() + +!0 = metadata !{} diff --git a/test/Transforms/ObjCARC/invoke.ll b/test/Transforms/ObjCARC/invoke.ll index a1b87d230bd26..cf971e458aaa5 100644 --- a/test/Transforms/ObjCARC/invoke.ll +++ b/test/Transforms/ObjCARC/invoke.ll @@ -27,6 +27,8 @@ invoke.cont: ; preds = %entry ret void lpad: ; preds = %entry + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup call void @objc_release(i8* %zipFile) nounwind, !clang.imprecise_release !0 ret void } @@ -56,6 +58,8 @@ invoke.cont: ; preds = %entry br label %done lpad: ; preds = %entry + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup call void @callee() br label %done @@ -64,4 +68,6 @@ done: ret void } +declare i32 @__gxx_personality_v0(...) + !0 = metadata !{} diff --git a/test/Transforms/ObjCARC/nested.ll b/test/Transforms/ObjCARC/nested.ll new file mode 100644 index 0000000000000..9eada8a2ddbaa --- /dev/null +++ b/test/Transforms/ObjCARC/nested.ll @@ -0,0 +1,620 @@ +; RUN: opt -objc-arc -S < %s | FileCheck %s + +%struct.__objcFastEnumerationState = type { i64, i8**, i64*, [5 x i64] } + +@"\01L_OBJC_METH_VAR_NAME_" = internal global [43 x i8] c"countByEnumeratingWithState:objects:count:\00", section "__TEXT,__objc_methname,cstring_literals", align 1 +@"\01L_OBJC_SELECTOR_REFERENCES_" = internal global i8* getelementptr inbounds ([43 x i8]* @"\01L_OBJC_METH_VAR_NAME_", i64 0, i64 0), section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" +@g = common global i8* null, align 8 +@"\01L_OBJC_IMAGE_INFO" = internal constant [2 x i32] [i32 0, i32 16], section "__DATA, __objc_imageinfo, regular, no_dead_strip" + +declare void @callee() +declare i8* @returner() +declare i8* @objc_retainAutoreleasedReturnValue(i8*) +declare i8* @objc_retain(i8*) +declare void @objc_enumerationMutation(i8*) +declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) nounwind +declare i8* @objc_msgSend(i8*, i8*, ...) nonlazybind +declare void @use(i8*) +declare void @objc_release(i8*) + +!0 = metadata !{} + +; Delete a nested retain+release pair. + +; CHECK: define void @test0( +; CHECK: call i8* @objc_retain +; CHECK-NOT: @objc_retain +; CHECK: } +define void @test0(i8* %a) nounwind { +entry: + %state.ptr = alloca %struct.__objcFastEnumerationState, align 8 + %items.ptr = alloca [16 x i8*], align 8 + %0 = call i8* @objc_retain(i8* %a) nounwind + %tmp = bitcast %struct.__objcFastEnumerationState* %state.ptr to i8* + call void @llvm.memset.p0i8.i64(i8* %tmp, i8 0, i64 64, i32 8, i1 false) + %1 = call i8* @objc_retain(i8* %0) nounwind + %tmp2 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8 + %call = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp2, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16) + %iszero = icmp eq i64 %call, 0 + br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit + +forcoll.loopinit: + %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 2 + %mutationsptr = load i64** %mutationsptr.ptr, align 8 + %forcoll.initial-mutations = load i64* %mutationsptr, align 8 + %stateitems.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 1 + br label %forcoll.loopbody.outer + +forcoll.loopbody.outer: + %forcoll.count.ph = phi i64 [ %call, %forcoll.loopinit ], [ %call6, %forcoll.refetch ] + %tmp7 = icmp ugt i64 %forcoll.count.ph, 1 + %umax = select i1 %tmp7, i64 %forcoll.count.ph, i64 1 + br label %forcoll.loopbody + +forcoll.loopbody: + %forcoll.index = phi i64 [ 0, %forcoll.loopbody.outer ], [ %4, %forcoll.notmutated ] + %mutationsptr3 = load i64** %mutationsptr.ptr, align 8 + %statemutations = load i64* %mutationsptr3, align 8 + %2 = icmp eq i64 %statemutations, %forcoll.initial-mutations + br i1 %2, label %forcoll.notmutated, label %forcoll.mutated + +forcoll.mutated: + call void @objc_enumerationMutation(i8* %1) + br label %forcoll.notmutated + +forcoll.notmutated: + %stateitems = load i8*** %stateitems.ptr, align 8 + %currentitem.ptr = getelementptr i8** %stateitems, i64 %forcoll.index + %3 = load i8** %currentitem.ptr, align 8 + call void @use(i8* %3) + %4 = add i64 %forcoll.index, 1 + %exitcond = icmp eq i64 %4, %umax + br i1 %exitcond, label %forcoll.refetch, label %forcoll.loopbody + +forcoll.refetch: + %tmp5 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8 + %call6 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp5, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16) + %5 = icmp eq i64 %call6, 0 + br i1 %5, label %forcoll.empty, label %forcoll.loopbody.outer + +forcoll.empty: + call void @objc_release(i8* %1) nounwind + call void @objc_release(i8* %0) nounwind, !clang.imprecise_release !0 + ret void +} + +; Delete a nested retain+release pair. + +; CHECK: define void @test2( +; CHECK: call i8* @objc_retain +; CHECK-NOT: @objc_retain +; CHECK: } +define void @test2() nounwind { +entry: + %state.ptr = alloca %struct.__objcFastEnumerationState, align 8 + %items.ptr = alloca [16 x i8*], align 8 + %call = call i8* @returner() + %0 = call i8* @objc_retainAutoreleasedReturnValue(i8* %call) nounwind + %tmp = bitcast %struct.__objcFastEnumerationState* %state.ptr to i8* + call void @llvm.memset.p0i8.i64(i8* %tmp, i8 0, i64 64, i32 8, i1 false) + %1 = call i8* @objc_retain(i8* %0) nounwind + %tmp2 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8 + %call3 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp2, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16) + %iszero = icmp eq i64 %call3, 0 + br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit + +forcoll.loopinit: + %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 2 + %mutationsptr = load i64** %mutationsptr.ptr, align 8 + %forcoll.initial-mutations = load i64* %mutationsptr, align 8 + %stateitems.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 1 + br label %forcoll.loopbody.outer + +forcoll.loopbody.outer: + %forcoll.count.ph = phi i64 [ %call3, %forcoll.loopinit ], [ %call7, %forcoll.refetch ] + %tmp8 = icmp ugt i64 %forcoll.count.ph, 1 + %umax = select i1 %tmp8, i64 %forcoll.count.ph, i64 1 + br label %forcoll.loopbody + +forcoll.loopbody: + %forcoll.index = phi i64 [ 0, %forcoll.loopbody.outer ], [ %4, %forcoll.notmutated ] + %mutationsptr4 = load i64** %mutationsptr.ptr, align 8 + %statemutations = load i64* %mutationsptr4, align 8 + %2 = icmp eq i64 %statemutations, %forcoll.initial-mutations + br i1 %2, label %forcoll.notmutated, label %forcoll.mutated + +forcoll.mutated: + call void @objc_enumerationMutation(i8* %1) + br label %forcoll.notmutated + +forcoll.notmutated: + %stateitems = load i8*** %stateitems.ptr, align 8 + %currentitem.ptr = getelementptr i8** %stateitems, i64 %forcoll.index + %3 = load i8** %currentitem.ptr, align 8 + call void @use(i8* %3) + %4 = add i64 %forcoll.index, 1 + %exitcond = icmp eq i64 %4, %umax + br i1 %exitcond, label %forcoll.refetch, label %forcoll.loopbody + +forcoll.refetch: + %tmp6 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8 + %call7 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp6, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16) + %5 = icmp eq i64 %call7, 0 + br i1 %5, label %forcoll.empty, label %forcoll.loopbody.outer + +forcoll.empty: + call void @objc_release(i8* %1) nounwind + call void @objc_release(i8* %0) nounwind, !clang.imprecise_release !0 + ret void +} + +; Delete a nested retain+release pair. + +; CHECK: define void @test4( +; CHECK: call i8* @objc_retain +; CHECK-NOT: @objc_retain +; CHECK: } +define void @test4() nounwind { +entry: + %state.ptr = alloca %struct.__objcFastEnumerationState, align 8 + %items.ptr = alloca [16 x i8*], align 8 + %tmp = load i8** @g, align 8 + %0 = call i8* @objc_retain(i8* %tmp) nounwind + %tmp2 = bitcast %struct.__objcFastEnumerationState* %state.ptr to i8* + call void @llvm.memset.p0i8.i64(i8* %tmp2, i8 0, i64 64, i32 8, i1 false) + %1 = call i8* @objc_retain(i8* %0) nounwind + %tmp4 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8 + %call = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp4, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16) + %iszero = icmp eq i64 %call, 0 + br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit + +forcoll.loopinit: + %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 2 + %mutationsptr = load i64** %mutationsptr.ptr, align 8 + %forcoll.initial-mutations = load i64* %mutationsptr, align 8 + %stateitems.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 1 + br label %forcoll.loopbody.outer + +forcoll.loopbody.outer: + %forcoll.count.ph = phi i64 [ %call, %forcoll.loopinit ], [ %call8, %forcoll.refetch ] + %tmp9 = icmp ugt i64 %forcoll.count.ph, 1 + %umax = select i1 %tmp9, i64 %forcoll.count.ph, i64 1 + br label %forcoll.loopbody + +forcoll.loopbody: + %forcoll.index = phi i64 [ 0, %forcoll.loopbody.outer ], [ %4, %forcoll.notmutated ] + %mutationsptr5 = load i64** %mutationsptr.ptr, align 8 + %statemutations = load i64* %mutationsptr5, align 8 + %2 = icmp eq i64 %statemutations, %forcoll.initial-mutations + br i1 %2, label %forcoll.notmutated, label %forcoll.mutated + +forcoll.mutated: + call void @objc_enumerationMutation(i8* %1) + br label %forcoll.notmutated + +forcoll.notmutated: + %stateitems = load i8*** %stateitems.ptr, align 8 + %currentitem.ptr = getelementptr i8** %stateitems, i64 %forcoll.index + %3 = load i8** %currentitem.ptr, align 8 + call void @use(i8* %3) + %4 = add i64 %forcoll.index, 1 + %exitcond = icmp eq i64 %4, %umax + br i1 %exitcond, label %forcoll.refetch, label %forcoll.loopbody + +forcoll.refetch: + %tmp7 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8 + %call8 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp7, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16) + %5 = icmp eq i64 %call8, 0 + br i1 %5, label %forcoll.empty, label %forcoll.loopbody.outer + +forcoll.empty: + call void @objc_release(i8* %1) nounwind + call void @objc_release(i8* %0) nounwind, !clang.imprecise_release !0 + ret void +} + +; Delete a nested retain+release pair. + +; CHECK: define void @test5( +; CHECK: call i8* @objc_retain +; CHECK-NOT: @objc_retain +; CHECK: } +define void @test5() nounwind { +entry: + %state.ptr = alloca %struct.__objcFastEnumerationState, align 8 + %items.ptr = alloca [16 x i8*], align 8 + %call = call i8* @returner() + %0 = call i8* @objc_retainAutoreleasedReturnValue(i8* %call) nounwind + call void @callee() + %tmp = bitcast %struct.__objcFastEnumerationState* %state.ptr to i8* + call void @llvm.memset.p0i8.i64(i8* %tmp, i8 0, i64 64, i32 8, i1 false) + %1 = call i8* @objc_retain(i8* %0) nounwind + %tmp2 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8 + %call3 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp2, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16) + %iszero = icmp eq i64 %call3, 0 + br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit + +forcoll.loopinit: + %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 2 + %mutationsptr = load i64** %mutationsptr.ptr, align 8 + %forcoll.initial-mutations = load i64* %mutationsptr, align 8 + %stateitems.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 1 + br label %forcoll.loopbody.outer + +forcoll.loopbody.outer: + %forcoll.count.ph = phi i64 [ %call3, %forcoll.loopinit ], [ %call7, %forcoll.refetch ] + %tmp8 = icmp ugt i64 %forcoll.count.ph, 1 + %umax = select i1 %tmp8, i64 %forcoll.count.ph, i64 1 + br label %forcoll.loopbody + +forcoll.loopbody: + %forcoll.index = phi i64 [ 0, %forcoll.loopbody.outer ], [ %4, %forcoll.notmutated ] + %mutationsptr4 = load i64** %mutationsptr.ptr, align 8 + %statemutations = load i64* %mutationsptr4, align 8 + %2 = icmp eq i64 %statemutations, %forcoll.initial-mutations + br i1 %2, label %forcoll.notmutated, label %forcoll.mutated + +forcoll.mutated: + call void @objc_enumerationMutation(i8* %1) + br label %forcoll.notmutated + +forcoll.notmutated: + %stateitems = load i8*** %stateitems.ptr, align 8 + %currentitem.ptr = getelementptr i8** %stateitems, i64 %forcoll.index + %3 = load i8** %currentitem.ptr, align 8 + call void @use(i8* %3) + %4 = add i64 %forcoll.index, 1 + %exitcond = icmp eq i64 %4, %umax + br i1 %exitcond, label %forcoll.refetch, label %forcoll.loopbody + +forcoll.refetch: + %tmp6 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8 + %call7 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp6, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16) + %5 = icmp eq i64 %call7, 0 + br i1 %5, label %forcoll.empty, label %forcoll.loopbody.outer + +forcoll.empty: + call void @objc_release(i8* %1) nounwind + call void @objc_release(i8* %0) nounwind, !clang.imprecise_release !0 + ret void +} + +; Delete a nested retain+release pair. + +; CHECK: define void @test6( +; CHECK: call i8* @objc_retain +; CHECK-NOT: @objc_retain +; CHECK: } +define void @test6() nounwind { +entry: + %state.ptr = alloca %struct.__objcFastEnumerationState, align 8 + %items.ptr = alloca [16 x i8*], align 8 + %call = call i8* @returner() + %0 = call i8* @objc_retainAutoreleasedReturnValue(i8* %call) nounwind + %tmp = bitcast %struct.__objcFastEnumerationState* %state.ptr to i8* + call void @llvm.memset.p0i8.i64(i8* %tmp, i8 0, i64 64, i32 8, i1 false) + %1 = call i8* @objc_retain(i8* %0) nounwind + %tmp2 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8 + %call3 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp2, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16) + %iszero = icmp eq i64 %call3, 0 + br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit + +forcoll.loopinit: + %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 2 + %mutationsptr = load i64** %mutationsptr.ptr, align 8 + %forcoll.initial-mutations = load i64* %mutationsptr, align 8 + %stateitems.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 1 + br label %forcoll.loopbody.outer + +forcoll.loopbody.outer: + %forcoll.count.ph = phi i64 [ %call3, %forcoll.loopinit ], [ %call7, %forcoll.refetch ] + %tmp8 = icmp ugt i64 %forcoll.count.ph, 1 + %umax = select i1 %tmp8, i64 %forcoll.count.ph, i64 1 + br label %forcoll.loopbody + +forcoll.loopbody: + %forcoll.index = phi i64 [ 0, %forcoll.loopbody.outer ], [ %4, %forcoll.notmutated ] + %mutationsptr4 = load i64** %mutationsptr.ptr, align 8 + %statemutations = load i64* %mutationsptr4, align 8 + %2 = icmp eq i64 %statemutations, %forcoll.initial-mutations + br i1 %2, label %forcoll.notmutated, label %forcoll.mutated + +forcoll.mutated: + call void @objc_enumerationMutation(i8* %1) + br label %forcoll.notmutated + +forcoll.notmutated: + %stateitems = load i8*** %stateitems.ptr, align 8 + %currentitem.ptr = getelementptr i8** %stateitems, i64 %forcoll.index + %3 = load i8** %currentitem.ptr, align 8 + call void @use(i8* %3) + %4 = add i64 %forcoll.index, 1 + %exitcond = icmp eq i64 %4, %umax + br i1 %exitcond, label %forcoll.refetch, label %forcoll.loopbody + +forcoll.refetch: + %tmp6 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8 + %call7 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp6, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16) + %5 = icmp eq i64 %call7, 0 + br i1 %5, label %forcoll.empty, label %forcoll.loopbody.outer + +forcoll.empty: + call void @objc_release(i8* %1) nounwind + call void @callee() + call void @objc_release(i8* %0) nounwind, !clang.imprecise_release !0 + ret void +} + +; Delete a nested retain+release pair. + +; CHECK: define void @test7( +; CHECK: call i8* @objc_retain +; CHECK-NOT: @objc_retain +; CHECK: } +define void @test7() nounwind { +entry: + %state.ptr = alloca %struct.__objcFastEnumerationState, align 8 + %items.ptr = alloca [16 x i8*], align 8 + %call = call i8* @returner() + %0 = call i8* @objc_retainAutoreleasedReturnValue(i8* %call) nounwind + call void @callee() + %tmp = bitcast %struct.__objcFastEnumerationState* %state.ptr to i8* + call void @llvm.memset.p0i8.i64(i8* %tmp, i8 0, i64 64, i32 8, i1 false) + %1 = call i8* @objc_retain(i8* %0) nounwind + %tmp2 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8 + %call3 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp2, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16) + %iszero = icmp eq i64 %call3, 0 + br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit + +forcoll.loopinit: + %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 2 + %mutationsptr = load i64** %mutationsptr.ptr, align 8 + %forcoll.initial-mutations = load i64* %mutationsptr, align 8 + %stateitems.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 1 + br label %forcoll.loopbody.outer + +forcoll.loopbody.outer: + %forcoll.count.ph = phi i64 [ %call3, %forcoll.loopinit ], [ %call7, %forcoll.refetch ] + %tmp8 = icmp ugt i64 %forcoll.count.ph, 1 + %umax = select i1 %tmp8, i64 %forcoll.count.ph, i64 1 + br label %forcoll.loopbody + +forcoll.loopbody: + %forcoll.index = phi i64 [ 0, %forcoll.loopbody.outer ], [ %4, %forcoll.notmutated ] + %mutationsptr4 = load i64** %mutationsptr.ptr, align 8 + %statemutations = load i64* %mutationsptr4, align 8 + %2 = icmp eq i64 %statemutations, %forcoll.initial-mutations + br i1 %2, label %forcoll.notmutated, label %forcoll.mutated + +forcoll.mutated: + call void @objc_enumerationMutation(i8* %1) + br label %forcoll.notmutated + +forcoll.notmutated: + %stateitems = load i8*** %stateitems.ptr, align 8 + %currentitem.ptr = getelementptr i8** %stateitems, i64 %forcoll.index + %3 = load i8** %currentitem.ptr, align 8 + call void @use(i8* %3) + %4 = add i64 %forcoll.index, 1 + %exitcond = icmp eq i64 %4, %umax + br i1 %exitcond, label %forcoll.refetch, label %forcoll.loopbody + +forcoll.refetch: + %tmp6 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8 + %call7 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp6, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16) + %5 = icmp eq i64 %call7, 0 + br i1 %5, label %forcoll.empty, label %forcoll.loopbody.outer + +forcoll.empty: + call void @objc_release(i8* %1) nounwind + call void @callee() + call void @objc_release(i8* %0) nounwind, !clang.imprecise_release !0 + ret void +} + +; Delete a nested retain+release pair. + +; CHECK: define void @test8( +; CHECK: call i8* @objc_retain +; CHECK-NOT: @objc_retain +; CHECK: } +define void @test8() nounwind { +entry: + %state.ptr = alloca %struct.__objcFastEnumerationState, align 8 + %items.ptr = alloca [16 x i8*], align 8 + %call = call i8* @returner() + %0 = call i8* @objc_retainAutoreleasedReturnValue(i8* %call) nounwind + %tmp = bitcast %struct.__objcFastEnumerationState* %state.ptr to i8* + call void @llvm.memset.p0i8.i64(i8* %tmp, i8 0, i64 64, i32 8, i1 false) + %1 = call i8* @objc_retain(i8* %0) nounwind + %tmp2 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8 + %call3 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp2, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16) + %iszero = icmp eq i64 %call3, 0 + br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit + +forcoll.loopinit: + %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 2 + %mutationsptr = load i64** %mutationsptr.ptr, align 8 + %forcoll.initial-mutations = load i64* %mutationsptr, align 8 + %stateitems.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 1 + br label %forcoll.loopbody.outer + +forcoll.loopbody.outer: + %forcoll.count.ph = phi i64 [ %call3, %forcoll.loopinit ], [ %call7, %forcoll.refetch ] + %tmp8 = icmp ugt i64 %forcoll.count.ph, 1 + %umax = select i1 %tmp8, i64 %forcoll.count.ph, i64 1 + br label %forcoll.loopbody + +forcoll.loopbody: + %forcoll.index = phi i64 [ 0, %forcoll.loopbody.outer ], [ %4, %forcoll.next ] + %mutationsptr4 = load i64** %mutationsptr.ptr, align 8 + %statemutations = load i64* %mutationsptr4, align 8 + %2 = icmp eq i64 %statemutations, %forcoll.initial-mutations + br i1 %2, label %forcoll.notmutated, label %forcoll.mutated + +forcoll.mutated: + call void @objc_enumerationMutation(i8* %1) + br label %forcoll.notmutated + +forcoll.notmutated: + %stateitems = load i8*** %stateitems.ptr, align 8 + %currentitem.ptr = getelementptr i8** %stateitems, i64 %forcoll.index + %3 = load i8** %currentitem.ptr, align 8 + %tobool = icmp eq i8* %3, null + br i1 %tobool, label %forcoll.next, label %if.then + +if.then: + call void @callee() + br label %forcoll.next + +forcoll.next: + %4 = add i64 %forcoll.index, 1 + %exitcond = icmp eq i64 %4, %umax + br i1 %exitcond, label %forcoll.refetch, label %forcoll.loopbody + +forcoll.refetch: + %tmp6 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8 + %call7 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp6, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16) + %5 = icmp eq i64 %call7, 0 + br i1 %5, label %forcoll.empty, label %forcoll.loopbody.outer + +forcoll.empty: + call void @objc_release(i8* %1) nounwind + call void @objc_release(i8* %0) nounwind, !clang.imprecise_release !0 + ret void +} + +; Delete a nested retain+release pair. + +; CHECK: define void @test9( +; CHECK: call i8* @objc_retain +; CHECK: call i8* @objc_retain +; CHECK-NOT: @objc_retain +; CHECK: } +define void @test9() nounwind { +entry: + %state.ptr = alloca %struct.__objcFastEnumerationState, align 8 + %items.ptr = alloca [16 x i8*], align 8 + %call = call i8* @returner() + %0 = call i8* @objc_retainAutoreleasedReturnValue(i8* %call) nounwind + %call1 = call i8* @returner() + %1 = call i8* @objc_retainAutoreleasedReturnValue(i8* %call1) nounwind + %tmp = bitcast %struct.__objcFastEnumerationState* %state.ptr to i8* + call void @llvm.memset.p0i8.i64(i8* %tmp, i8 0, i64 64, i32 8, i1 false) + %2 = call i8* @objc_retain(i8* %0) nounwind + %tmp3 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8 + %call4 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %2, i8* %tmp3, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16) + %iszero = icmp eq i64 %call4, 0 + br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit + +forcoll.loopinit: + %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 2 + %mutationsptr = load i64** %mutationsptr.ptr, align 8 + %forcoll.initial-mutations = load i64* %mutationsptr, align 8 + br label %forcoll.loopbody.outer + +forcoll.loopbody.outer: + %forcoll.count.ph = phi i64 [ %call4, %forcoll.loopinit ], [ %call7, %forcoll.refetch ] + %tmp9 = icmp ugt i64 %forcoll.count.ph, 1 + %umax = select i1 %tmp9, i64 %forcoll.count.ph, i64 1 + br label %forcoll.loopbody + +forcoll.loopbody: + %forcoll.index = phi i64 [ %phitmp, %forcoll.notmutated.forcoll.loopbody_crit_edge ], [ 1, %forcoll.loopbody.outer ] + %mutationsptr5 = load i64** %mutationsptr.ptr, align 8 + %statemutations = load i64* %mutationsptr5, align 8 + %3 = icmp eq i64 %statemutations, %forcoll.initial-mutations + br i1 %3, label %forcoll.notmutated, label %forcoll.mutated + +forcoll.mutated: + call void @objc_enumerationMutation(i8* %2) + br label %forcoll.notmutated + +forcoll.notmutated: + %exitcond = icmp eq i64 %forcoll.index, %umax + br i1 %exitcond, label %forcoll.refetch, label %forcoll.notmutated.forcoll.loopbody_crit_edge + +forcoll.notmutated.forcoll.loopbody_crit_edge: + %phitmp = add i64 %forcoll.index, 1 + br label %forcoll.loopbody + +forcoll.refetch: + %tmp6 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8 + %call7 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %2, i8* %tmp6, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16) + %4 = icmp eq i64 %call7, 0 + br i1 %4, label %forcoll.empty, label %forcoll.loopbody.outer + +forcoll.empty: + call void @objc_release(i8* %2) nounwind + call void @objc_release(i8* %1) nounwind, !clang.imprecise_release !0 + call void @objc_release(i8* %0) nounwind, !clang.imprecise_release !0 + ret void +} + +; Delete a nested retain+release pair. + +; CHECK: define void @test10( +; CHECK: call i8* @objc_retain +; CHECK: call i8* @objc_retain +; CHECK-NOT: @objc_retain +; CHECK: } +define void @test10() nounwind { +entry: + %state.ptr = alloca %struct.__objcFastEnumerationState, align 8 + %items.ptr = alloca [16 x i8*], align 8 + %call = call i8* @returner() + %0 = call i8* @objc_retainAutoreleasedReturnValue(i8* %call) nounwind + %call1 = call i8* @returner() + %1 = call i8* @objc_retainAutoreleasedReturnValue(i8* %call1) nounwind + call void @callee() + %tmp = bitcast %struct.__objcFastEnumerationState* %state.ptr to i8* + call void @llvm.memset.p0i8.i64(i8* %tmp, i8 0, i64 64, i32 8, i1 false) + %2 = call i8* @objc_retain(i8* %0) nounwind + %tmp3 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8 + %call4 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %2, i8* %tmp3, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16) + %iszero = icmp eq i64 %call4, 0 + br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit + +forcoll.loopinit: + %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 2 + %mutationsptr = load i64** %mutationsptr.ptr, align 8 + %forcoll.initial-mutations = load i64* %mutationsptr, align 8 + br label %forcoll.loopbody.outer + +forcoll.loopbody.outer: + %forcoll.count.ph = phi i64 [ %call4, %forcoll.loopinit ], [ %call7, %forcoll.refetch ] + %tmp9 = icmp ugt i64 %forcoll.count.ph, 1 + %umax = select i1 %tmp9, i64 %forcoll.count.ph, i64 1 + br label %forcoll.loopbody + +forcoll.loopbody: + %forcoll.index = phi i64 [ %phitmp, %forcoll.notmutated.forcoll.loopbody_crit_edge ], [ 1, %forcoll.loopbody.outer ] + %mutationsptr5 = load i64** %mutationsptr.ptr, align 8 + %statemutations = load i64* %mutationsptr5, align 8 + %3 = icmp eq i64 %statemutations, %forcoll.initial-mutations + br i1 %3, label %forcoll.notmutated, label %forcoll.mutated + +forcoll.mutated: + call void @objc_enumerationMutation(i8* %2) + br label %forcoll.notmutated + +forcoll.notmutated: + %exitcond = icmp eq i64 %forcoll.index, %umax + br i1 %exitcond, label %forcoll.refetch, label %forcoll.notmutated.forcoll.loopbody_crit_edge + +forcoll.notmutated.forcoll.loopbody_crit_edge: + %phitmp = add i64 %forcoll.index, 1 + br label %forcoll.loopbody + +forcoll.refetch: + %tmp6 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8 + %call7 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %2, i8* %tmp6, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16) + %4 = icmp eq i64 %call7, 0 + br i1 %4, label %forcoll.empty, label %forcoll.loopbody.outer + +forcoll.empty: + call void @objc_release(i8* %2) nounwind + call void @objc_release(i8* %1) nounwind, !clang.imprecise_release !0 + call void @objc_release(i8* %0) nounwind, !clang.imprecise_release !0 + ret void +} diff --git a/test/Transforms/ObjCARC/retain-block-alloca.ll b/test/Transforms/ObjCARC/retain-block-alloca.ll new file mode 100644 index 0000000000000..468da9147adb4 --- /dev/null +++ b/test/Transforms/ObjCARC/retain-block-alloca.ll @@ -0,0 +1,54 @@ +; RUN: opt -S -objc-arc < %s | FileCheck %s +; rdar://10209613 + +; CHECK: define void @test +; CHECK: %3 = call i8* @objc_retainBlock(i8* %2) nounwind +; CHECK: @objc_msgSend +; CHECK-NEXT: @objc_release(i8* %3) + +%0 = type opaque +%struct.__block_descriptor = type { i64, i64 } + +@_NSConcreteStackBlock = external global i8* +@__block_descriptor_tmp = external hidden constant { i64, i64, i8*, i8*, i8*, i8* } +@"\01L_OBJC_SELECTOR_REFERENCES_" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" + +define void @test(%0* %array) uwtable { +entry: + %block = alloca <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>, align 8 + %0 = bitcast %0* %array to i8* + %1 = tail call i8* @objc_retain(i8* %0) nounwind + %block.isa = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>* %block, i64 0, i32 0 + store i8* bitcast (i8** @_NSConcreteStackBlock to i8*), i8** %block.isa, align 8 + %block.flags = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>* %block, i64 0, i32 1 + store i32 1107296256, i32* %block.flags, align 8 + %block.reserved = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>* %block, i64 0, i32 2 + store i32 0, i32* %block.reserved, align 4 + %block.invoke = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>* %block, i64 0, i32 3 + store i8* bitcast (void (i8*)* @__test_block_invoke_0 to i8*), i8** %block.invoke, align 8 + %block.descriptor = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>* %block, i64 0, i32 4 + store %struct.__block_descriptor* bitcast ({ i64, i64, i8*, i8*, i8*, i8* }* @__block_descriptor_tmp to %struct.__block_descriptor*), %struct.__block_descriptor** %block.descriptor, align 8 + %block.captured = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>* %block, i64 0, i32 5 + store %0* %array, %0** %block.captured, align 8 + %2 = bitcast <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>* %block to i8* + %3 = call i8* @objc_retainBlock(i8* %2) nounwind + %tmp2 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8 + call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i8*)*)(i8* %0, i8* %tmp2, i8* %3) + call void @objc_release(i8* %3) nounwind + %strongdestroy = load %0** %block.captured, align 8 + %4 = bitcast %0* %strongdestroy to i8* + call void @objc_release(i8* %4) nounwind, !clang.imprecise_release !0 + ret void +} + +declare i8* @objc_retain(i8*) + +declare void @__test_block_invoke_0(i8* nocapture) uwtable + +declare i8* @objc_retainBlock(i8*) + +declare i8* @objc_msgSend(i8*, i8*, ...) nonlazybind + +declare void @objc_release(i8*) + +!0 = metadata !{} diff --git a/test/Transforms/ObjCARC/retain-block-side-effects.ll b/test/Transforms/ObjCARC/retain-block-side-effects.ll new file mode 100644 index 0000000000000..e84d48f86912d --- /dev/null +++ b/test/Transforms/ObjCARC/retain-block-side-effects.ll @@ -0,0 +1,39 @@ +; RUN: opt -S -objc-arc-aa -basicaa -gvn < %s | FileCheck %s +; rdar://10050579 + +; objc_retainBlock stores into %repeater so the load from after the +; call isn't forwardable from the store before the call. + +; CHECK: %tmp16 = call i8* @objc_retainBlock(i8* %tmp15) nounwind +; CHECK: %tmp17 = bitcast i8* %tmp16 to void ()* +; CHECK: %tmp18 = load %struct.__block_byref_repeater** %byref.forwarding, align 8 +; CHECK: %repeater12 = getelementptr inbounds %struct.__block_byref_repeater* %tmp18, i64 0, i32 6 +; CHECK: store void ()* %tmp17, void ()** %repeater12, align 8 + +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" + +%0 = type opaque +%struct.__block_byref_repeater = type { i8*, %struct.__block_byref_repeater*, i32, i32, i8*, i8*, void ()* } +%struct.__block_descriptor = type { i64, i64 } + +define void @foo() noreturn { +entry: + %repeater = alloca %struct.__block_byref_repeater, align 8 + %block = alloca <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0*, i8* }>, align 8 + %byref.forwarding = getelementptr inbounds %struct.__block_byref_repeater* %repeater, i64 0, i32 1 + %tmp10 = getelementptr inbounds %struct.__block_byref_repeater* %repeater, i64 0, i32 6 + store void ()* null, void ()** %tmp10, align 8 + %block.captured11 = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0*, i8* }>* %block, i64 0, i32 6 + %tmp14 = bitcast %struct.__block_byref_repeater* %repeater to i8* + store i8* %tmp14, i8** %block.captured11, align 8 + %tmp15 = bitcast <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0*, i8* }>* %block to i8* + %tmp16 = call i8* @objc_retainBlock(i8* %tmp15) nounwind + %tmp17 = bitcast i8* %tmp16 to void ()* + %tmp18 = load %struct.__block_byref_repeater** %byref.forwarding, align 8 + %repeater12 = getelementptr inbounds %struct.__block_byref_repeater* %tmp18, i64 0, i32 6 + %tmp13 = load void ()** %repeater12, align 8 + store void ()* %tmp17, void ()** %repeater12, align 8 + ret void +} + +declare i8* @objc_retainBlock(i8*) diff --git a/test/Transforms/ObjCARC/retain-not-declared.ll b/test/Transforms/ObjCARC/retain-not-declared.ll index e1fe1170633c9..41bde017e7770 100644 --- a/test/Transforms/ObjCARC/retain-not-declared.ll +++ b/test/Transforms/ObjCARC/retain-not-declared.ll @@ -1,21 +1,23 @@ ; RUN: opt -S -objc-arc -objc-arc-contract < %s | FileCheck %s -; Test that the optimizer can create an objc_retainAutoreleaseReturnValue -; declaration even if no objc_retain declaration exists. -; rdar://9401303 - 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" declare i8* @objc_unretainedObject(i8*) declare i8* @objc_retainAutoreleasedReturnValue(i8*) declare i8* @objc_autoreleaseReturnValue(i8*) +declare i8* @objc_msgSend(i8*, i8*, ...) +declare void @objc_release(i8*) -; CHECK: define i8* @foo(i8* %p) { +; Test that the optimizer can create an objc_retainAutoreleaseReturnValue +; declaration even if no objc_retain declaration exists. +; rdar://9401303 + +; CHECK: define i8* @test0(i8* %p) { ; CHECK-NEXT: entry: ; CHECK-NEXT: %0 = tail call i8* @objc_retainAutoreleaseReturnValue(i8* %p) nounwind ; CHECK-NEXT: ret i8* %0 ; CHECK-NEXT: } -define i8* @foo(i8* %p) { +define i8* @test0(i8* %p) { entry: %call = tail call i8* @objc_unretainedObject(i8* %p) %0 = tail call i8* @objc_retainAutoreleasedReturnValue(i8* %call) nounwind @@ -23,3 +25,43 @@ entry: ret i8* %1 } +; Properly create the @objc_retain declaration when it doesn't already exist. +; rdar://9825114 + +; CHECK: @test1( +; CHECK: @objc_retain( +; CHECK: @objc_retain( +; CHECK: @objc_release( +; CHECK: @objc_release( +; CHECK: } +define void @test1(i8* %call88) nounwind { +entry: + %tmp1 = call i8* @objc_retainAutoreleasedReturnValue(i8* %call88) nounwind + %call94 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*)*)(i8* %tmp1) + to label %invoke.cont93 unwind label %lpad91 + +invoke.cont93: ; preds = %entry + %tmp2 = call i8* @objc_retainAutoreleasedReturnValue(i8* %call94) nounwind + call void @objc_release(i8* %tmp1) nounwind + invoke void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*)*)(i8* %tmp2) + to label %invoke.cont102 unwind label %lpad100 + +invoke.cont102: ; preds = %invoke.cont93 + call void @objc_release(i8* %tmp2) nounwind, !clang.imprecise_release !0 + unreachable + +lpad91: ; preds = %entry + %exn91 = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup + unreachable + +lpad100: ; preds = %invoke.cont93 + %exn100 = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup + call void @objc_release(i8* %tmp2) nounwind, !clang.imprecise_release !0 + unreachable +} + +declare i32 @__gxx_personality_v0(...) + +!0 = metadata !{} diff --git a/test/Transforms/ObjCARC/rv.ll b/test/Transforms/ObjCARC/rv.ll index da53a86b10fde..9353a19f71a44 100644 --- a/test/Transforms/ObjCARC/rv.ll +++ b/test/Transforms/ObjCARC/rv.ll @@ -329,3 +329,14 @@ define void @test23(i8* %p) { call i8* @objc_autoreleaseReturnValue(i8* %p) ret void } + +; Don't convert autoreleaseRV to autorelease if the result is returned, +; even through a bitcast. + +; CHECK: define {}* @test24( +; CHECK: tail call i8* @objc_autoreleaseReturnValue(i8* %p) +define {}* @test24(i8* %p) { + %t = call i8* @objc_autoreleaseReturnValue(i8* %p) + %s = bitcast i8* %p to {}* + ret {}* %s +} diff --git a/test/Transforms/PhaseOrdering/2010-03-22-empty-baseclass.ll b/test/Transforms/PhaseOrdering/2010-03-22-empty-baseclass.ll new file mode 100644 index 0000000000000..8859da8de106b --- /dev/null +++ b/test/Transforms/PhaseOrdering/2010-03-22-empty-baseclass.ll @@ -0,0 +1,162 @@ +; RUN: opt -O2 %s -S -o - | FileCheck %s + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" +target triple = "x86_64-apple-darwin11.1" + +%"struct.boost::compressed_pair<empty_t,int>" = type { %"struct.boost::details::compressed_pair_imp<empty_t,int,1>" } +%"struct.boost::details::compressed_pair_imp<empty_t,int,1>" = type { i32 } +%struct.empty_base_t = type <{ i8 }> +%struct.empty_t = type <{ i8 }> + +@.str = private constant [25 x i8] c"x.second() was clobbered\00", align 1 ; <[25 x i8]*> [#uses=1] + +define i32 @main(i32 %argc, i8** %argv) ssp { +entry: + %argc_addr = alloca i32, align 4 ; <i32*> [#uses=1] + %argv_addr = alloca i8**, align 8 ; <i8***> [#uses=1] + %retval = alloca i32 ; <i32*> [#uses=2] + %0 = alloca i32 ; <i32*> [#uses=2] + %retval.1 = alloca i8 ; <i8*> [#uses=2] + %1 = alloca %struct.empty_base_t ; <%struct.empty_base_t*> [#uses=1] + %2 = alloca %struct.empty_base_t* ; <%struct.empty_base_t**> [#uses=1] + %x = alloca %"struct.boost::compressed_pair<empty_t,int>" ; <%"struct.boost::compressed_pair<empty_t,int>"*> [#uses=3] + %"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0] + store i32 %argc, i32* %argc_addr + store i8** %argv, i8*** %argv_addr + %3 = call i32* @_ZN5boost15compressed_pairI7empty_tiE6secondEv(%"struct.boost::compressed_pair<empty_t,int>"* %x) ssp ; <i32*> [#uses=1] + store i32 -3, i32* %3, align 4 + %4 = call %struct.empty_base_t* @_ZN5boost15compressed_pairI7empty_tiE5firstEv(%"struct.boost::compressed_pair<empty_t,int>"* %x) ssp ; <%struct.empty_base_t*> [#uses=1] + store %struct.empty_base_t* %4, %struct.empty_base_t** %2, align 8 + call void @_ZN7empty_tC1Ev(%struct.empty_base_t* %1) nounwind + %5 = call i32* @_ZN5boost15compressed_pairI7empty_tiE6secondEv(%"struct.boost::compressed_pair<empty_t,int>"* %x) ssp ; <i32*> [#uses=1] + %6 = load i32* %5, align 4 ; <i32> [#uses=1] + %7 = icmp ne i32 %6, -3 ; <i1> [#uses=1] + %8 = zext i1 %7 to i8 ; <i8> [#uses=1] + store i8 %8, i8* %retval.1, align 1 + %9 = load i8* %retval.1, align 1 ; <i8> [#uses=1] + %toBool = icmp ne i8 %9, 0 ; <i1> [#uses=1] + br i1 %toBool, label %bb, label %bb1 + +bb: ; preds = %entry + %10 = call i32 @puts(i8* getelementptr inbounds ([25 x i8]* @.str, i64 0, i64 0)) ; <i32> [#uses=0] + call void @abort() noreturn + unreachable + +bb1: ; preds = %entry + store i32 0, i32* %0, align 4 + %11 = load i32* %0, align 4 ; <i32> [#uses=1] + store i32 %11, i32* %retval, align 4 + br label %return + +; CHECK-NOT: x.second() was clobbered +; CHECK: ret i32 +return: ; preds = %bb1 + %retval2 = load i32* %retval ; <i32> [#uses=1] + ret i32 %retval2 +} + +define linkonce_odr void @_ZN12empty_base_tC2Ev(%struct.empty_base_t* %this) nounwind ssp align 2 { +entry: + %this_addr = alloca %struct.empty_base_t*, align 8 ; <%struct.empty_base_t**> [#uses=1] + %"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0] + store %struct.empty_base_t* %this, %struct.empty_base_t** %this_addr + br label %return + +return: ; preds = %entry + ret void +} + +define linkonce_odr void @_ZN7empty_tC1Ev(%struct.empty_base_t* %this) nounwind ssp align 2 { +entry: + %this_addr = alloca %struct.empty_base_t*, align 8 ; <%struct.empty_base_t**> [#uses=2] + %"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0] + store %struct.empty_base_t* %this, %struct.empty_base_t** %this_addr + %0 = load %struct.empty_base_t** %this_addr, align 8 ; <%struct.empty_base_t*> [#uses=1] + call void @_ZN12empty_base_tC2Ev(%struct.empty_base_t* %0) nounwind + br label %return + +return: ; preds = %entry + ret void +} + +define linkonce_odr i32* @_ZN5boost7details19compressed_pair_impI7empty_tiLi1EE6secondEv(%"struct.boost::details::compressed_pair_imp<empty_t,int,1>"* %this) nounwind ssp align 2 { +entry: + %this_addr = alloca %"struct.boost::details::compressed_pair_imp<empty_t,int,1>"*, align 8 ; <%"struct.boost::details::compressed_pair_imp<empty_t,int,1>"**> [#uses=2] + %retval = alloca i32* ; <i32**> [#uses=2] + %0 = alloca i32* ; <i32**> [#uses=2] + %"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0] + store %"struct.boost::details::compressed_pair_imp<empty_t,int,1>"* %this, %"struct.boost::details::compressed_pair_imp<empty_t,int,1>"** %this_addr + %1 = load %"struct.boost::details::compressed_pair_imp<empty_t,int,1>"** %this_addr, align 8 ; <%"struct.boost::details::compressed_pair_imp<empty_t,int,1>"*> [#uses=1] + %2 = getelementptr inbounds %"struct.boost::details::compressed_pair_imp<empty_t,int,1>"* %1, i32 0, i32 0 ; <i32*> [#uses=1] + store i32* %2, i32** %0, align 8 + %3 = load i32** %0, align 8 ; <i32*> [#uses=1] + store i32* %3, i32** %retval, align 8 + br label %return + +return: ; preds = %entry + %retval1 = load i32** %retval ; <i32*> [#uses=1] + ret i32* %retval1 +} + +define linkonce_odr i32* @_ZN5boost15compressed_pairI7empty_tiE6secondEv(%"struct.boost::compressed_pair<empty_t,int>"* %this) ssp align 2 { +entry: + %this_addr = alloca %"struct.boost::compressed_pair<empty_t,int>"*, align 8 ; <%"struct.boost::compressed_pair<empty_t,int>"**> [#uses=2] + %retval = alloca i32* ; <i32**> [#uses=2] + %0 = alloca i32* ; <i32**> [#uses=2] + %"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0] + store %"struct.boost::compressed_pair<empty_t,int>"* %this, %"struct.boost::compressed_pair<empty_t,int>"** %this_addr + %1 = load %"struct.boost::compressed_pair<empty_t,int>"** %this_addr, align 8 ; <%"struct.boost::compressed_pair<empty_t,int>"*> [#uses=1] + %2 = getelementptr inbounds %"struct.boost::compressed_pair<empty_t,int>"* %1, i32 0, i32 0 ; <%"struct.boost::details::compressed_pair_imp<empty_t,int,1>"*> [#uses=1] + %3 = call i32* @_ZN5boost7details19compressed_pair_impI7empty_tiLi1EE6secondEv(%"struct.boost::details::compressed_pair_imp<empty_t,int,1>"* %2) nounwind ; <i32*> [#uses=1] + store i32* %3, i32** %0, align 8 + %4 = load i32** %0, align 8 ; <i32*> [#uses=1] + store i32* %4, i32** %retval, align 8 + br label %return + +return: ; preds = %entry + %retval1 = load i32** %retval ; <i32*> [#uses=1] + ret i32* %retval1 +} + +define linkonce_odr %struct.empty_base_t* @_ZN5boost7details19compressed_pair_impI7empty_tiLi1EE5firstEv(%"struct.boost::details::compressed_pair_imp<empty_t,int,1>"* %this) nounwind ssp align 2 { +entry: + %this_addr = alloca %"struct.boost::details::compressed_pair_imp<empty_t,int,1>"*, align 8 ; <%"struct.boost::details::compressed_pair_imp<empty_t,int,1>"**> [#uses=2] + %retval = alloca %struct.empty_base_t* ; <%struct.empty_base_t**> [#uses=2] + %0 = alloca %struct.empty_base_t* ; <%struct.empty_base_t**> [#uses=2] + %"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0] + store %"struct.boost::details::compressed_pair_imp<empty_t,int,1>"* %this, %"struct.boost::details::compressed_pair_imp<empty_t,int,1>"** %this_addr + %1 = load %"struct.boost::details::compressed_pair_imp<empty_t,int,1>"** %this_addr, align 8 ; <%"struct.boost::details::compressed_pair_imp<empty_t,int,1>"*> [#uses=1] + %2 = bitcast %"struct.boost::details::compressed_pair_imp<empty_t,int,1>"* %1 to %struct.empty_base_t* ; <%struct.empty_base_t*> [#uses=1] + store %struct.empty_base_t* %2, %struct.empty_base_t** %0, align 8 + %3 = load %struct.empty_base_t** %0, align 8 ; <%struct.empty_base_t*> [#uses=1] + store %struct.empty_base_t* %3, %struct.empty_base_t** %retval, align 8 + br label %return + +return: ; preds = %entry + %retval1 = load %struct.empty_base_t** %retval ; <%struct.empty_base_t*> [#uses=1] + ret %struct.empty_base_t* %retval1 +} + +define linkonce_odr %struct.empty_base_t* @_ZN5boost15compressed_pairI7empty_tiE5firstEv(%"struct.boost::compressed_pair<empty_t,int>"* %this) ssp align 2 { +entry: + %this_addr = alloca %"struct.boost::compressed_pair<empty_t,int>"*, align 8 ; <%"struct.boost::compressed_pair<empty_t,int>"**> [#uses=2] + %retval = alloca %struct.empty_base_t* ; <%struct.empty_base_t**> [#uses=2] + %0 = alloca %struct.empty_base_t* ; <%struct.empty_base_t**> [#uses=2] + %"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0] + store %"struct.boost::compressed_pair<empty_t,int>"* %this, %"struct.boost::compressed_pair<empty_t,int>"** %this_addr + %1 = load %"struct.boost::compressed_pair<empty_t,int>"** %this_addr, align 8 ; <%"struct.boost::compressed_pair<empty_t,int>"*> [#uses=1] + %2 = getelementptr inbounds %"struct.boost::compressed_pair<empty_t,int>"* %1, i32 0, i32 0 ; <%"struct.boost::details::compressed_pair_imp<empty_t,int,1>"*> [#uses=1] + %3 = call %struct.empty_base_t* @_ZN5boost7details19compressed_pair_impI7empty_tiLi1EE5firstEv(%"struct.boost::details::compressed_pair_imp<empty_t,int,1>"* %2) nounwind ; <%struct.empty_base_t*> [#uses=1] + store %struct.empty_base_t* %3, %struct.empty_base_t** %0, align 8 + %4 = load %struct.empty_base_t** %0, align 8 ; <%struct.empty_base_t*> [#uses=1] + store %struct.empty_base_t* %4, %struct.empty_base_t** %retval, align 8 + br label %return + +return: ; preds = %entry + %retval1 = load %struct.empty_base_t** %retval ; <%struct.empty_base_t*> [#uses=1] + ret %struct.empty_base_t* %retval1 +} + +declare i32 @puts(i8*) + +declare void @abort() noreturn diff --git a/test/Transforms/PruneEH/2003-09-14-ExternalCall.ll b/test/Transforms/PruneEH/2003-09-14-ExternalCall.ll index 679eafd593630..64aba4610167e 100644 --- a/test/Transforms/PruneEH/2003-09-14-ExternalCall.ll +++ b/test/Transforms/PruneEH/2003-09-14-ExternalCall.ll @@ -6,6 +6,9 @@ define void @foo() { invoke void @External( ) to label %Cont unwind label %Cont Cont: ; preds = %0, %0 + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + cleanup ret void } +declare i32 @__gxx_personality_v0(...) diff --git a/test/Transforms/SCCP/2003-08-26-InvokeHandling.ll b/test/Transforms/SCCP/2003-08-26-InvokeHandling.ll index 9876375ae88a7..fb1926eca25bc 100644 --- a/test/Transforms/SCCP/2003-08-26-InvokeHandling.ll +++ b/test/Transforms/SCCP/2003-08-26-InvokeHandling.ll @@ -8,11 +8,16 @@ Entry: br i1 %cond, label %Inv, label %Cont Inv: ; preds = %Entry invoke void @foo( ) - to label %Ok unwind label %Cont + to label %Ok unwind label %LPad Ok: ; preds = %Inv br label %Cont +LPad: + %val = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + catch i8* null + br label %Cont Cont: ; preds = %Ok, %Inv, %Entry - %X = phi i32 [ 0, %Entry ], [ 1, %Ok ], [ 0, %Inv ] ; <i32> [#uses=1] + %X = phi i32 [ 0, %Entry ], [ 1, %Ok ], [ 0, %LPad ] ; <i32> [#uses=1] ret i32 %X } +declare i32 @__gxx_personality_v0(...) diff --git a/test/Transforms/SCCP/2004-11-16-DeadInvoke.ll b/test/Transforms/SCCP/2004-11-16-DeadInvoke.ll index 5d2c78ef874c0..e7eb101c147aa 100644 --- a/test/Transforms/SCCP/2004-11-16-DeadInvoke.ll +++ b/test/Transforms/SCCP/2004-11-16-DeadInvoke.ll @@ -6,8 +6,13 @@ define void @caller() { br i1 true, label %T, label %F F: ; preds = %0 %X = invoke i32 @foo( ) - to label %T unwind label %T ; <i32> [#uses=0] -T: ; preds = %F, %F, %0 + to label %T unwind label %LP ; <i32> [#uses=0] +LP: + %val = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + catch i8* null + br label %T +T: ret void } +declare i32 @__gxx_personality_v0(...) diff --git a/test/Transforms/SCCP/2007-05-16-InvokeCrash.ll b/test/Transforms/SCCP/2007-05-16-InvokeCrash.ll index b84fe6db2f21d..a5a42f1b40719 100644 --- a/test/Transforms/SCCP/2007-05-16-InvokeCrash.ll +++ b/test/Transforms/SCCP/2007-05-16-InvokeCrash.ll @@ -31,7 +31,9 @@ bb149: ; preds = %bb114 bb177: ; preds = %bb149 unreachable cleanup: ; preds = %bb149, %bb114, %bb67 - unwind + %val = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + cleanup + resume { i8*, i32 } %val } declare double @sin(double) @@ -39,3 +41,5 @@ declare double @sin(double) declare double @log(double) declare double @sqrt(double) + +declare i32 @__gxx_personality_v0(...) diff --git a/test/Transforms/SCCP/2009-01-14-IPSCCP-Invoke.ll b/test/Transforms/SCCP/2009-01-14-IPSCCP-Invoke.ll index d23ee2b23d763..7546bf5cc7272 100644 --- a/test/Transforms/SCCP/2009-01-14-IPSCCP-Invoke.ll +++ b/test/Transforms/SCCP/2009-01-14-IPSCCP-Invoke.ll @@ -7,6 +7,8 @@ define i32 @main() { to label %UnifiedReturnBlock unwind label %lpad lpad: + %val = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + cleanup unreachable UnifiedReturnBlock: diff --git a/test/Transforms/SCCP/atomic-load-store.ll b/test/Transforms/SCCP/atomic-load-store.ll new file mode 100644 index 0000000000000..09061f0a6fd51 --- /dev/null +++ b/test/Transforms/SCCP/atomic-load-store.ll @@ -0,0 +1,30 @@ +; RUN: opt < %s -ipsccp -S | FileCheck %s + +; This transformation is safe for atomic loads and stores; check that it works. + +@G = internal global i32 17 +@C = internal constant i32 222 + +define i32 @test1() { + %V = load atomic i32* @G seq_cst, align 4 + %C = icmp eq i32 %V, 17 + br i1 %C, label %T, label %F +T: + store atomic i32 17, i32* @G seq_cst, align 4 + ret i32 %V +F: + store atomic i32 123, i32* @G seq_cst, align 4 + ret i32 0 +} +; CHECK: define i32 @test1 +; CHECK-NOT: store +; CHECK: ret i32 17 + +define i32 @test2() { + %V = load atomic i32* @C seq_cst, align 4 + ret i32 %V +} + +; CHECK: define i32 @test2 +; CHECK-NOT: load +; CHECK: ret i32 222 diff --git a/test/Transforms/SCCP/ipsccp-basic.ll b/test/Transforms/SCCP/ipsccp-basic.ll index b9e3f42fdbded..8340f0c1e1273 100644 --- a/test/Transforms/SCCP/ipsccp-basic.ll +++ b/test/Transforms/SCCP/ipsccp-basic.ll @@ -90,6 +90,8 @@ A: %c = call i64 @test4c(i64 %b) ret i64 %c B: + %val = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + catch i8* null ret i64 0 } ; CHECK: define i64 @test4b() @@ -121,6 +123,8 @@ A: %c = call i64 @test5c({i64,i64} %a) ret i64 %c B: + %val = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + catch i8* null ret i64 0 } @@ -204,3 +208,22 @@ entry: ret void } +declare i32 @__gxx_personality_v0(...) + +;;======================== test10 + +define i32 @test10a() nounwind { +entry: + %call = call i32 @test10b(i32 undef) + ret i32 %call +; CHECK: define i32 @test10a +; CHECK: ret i32 0 +} + +define internal i32 @test10b(i32 %x) nounwind { +entry: + %r = and i32 %x, 1 + ret i32 %r +; CHECK: define internal i32 @test10b +; CHECK: ret i32 undef +} diff --git a/test/Transforms/SCCP/switch.ll b/test/Transforms/SCCP/switch.ll new file mode 100644 index 0000000000000..9f934237e6199 --- /dev/null +++ b/test/Transforms/SCCP/switch.ll @@ -0,0 +1,13 @@ +; RUN: opt -S -sccp < %s | FileCheck %s + +; Make sure we always consider the default edge executable for a switch +; with no cases. +declare void @foo() +define void @test1() { +; CHECK: define void @test1 +; CHECK: call void @foo() + switch i32 undef, label %d [] +d: + call void @foo() + ret void +} diff --git a/test/Transforms/SCCP/undef-resolve.ll b/test/Transforms/SCCP/undef-resolve.ll index bed561c8e4f24..a3dddb799a6a0 100644 --- a/test/Transforms/SCCP/undef-resolve.ll +++ b/test/Transforms/SCCP/undef-resolve.ll @@ -104,3 +104,69 @@ bb1.us-lcssa: ; preds = %control bb1: ; preds = %bb1.us-lcssa, %bb1.us-lcssa.us ret i32 0 } + +; Make sure SCCP honors the xor "idiom" +; rdar://9956541 +define i32 @test3() { + %t = xor i32 undef, undef + ret i32 %t +; CHECK: @test3 +; CHECK: ret i32 0 +} + +; Be conservative with FP ops +define double @test4(double %x) { + %t = fadd double %x, undef + ret double %t +; CHECK: @test4 +; CHECK: fadd double %x, undef +} + +; Make sure casts produce a possible value +define i32 @test5() { + %t = sext i8 undef to i32 + ret i32 %t +; CHECK: @test5 +; CHECK: ret i32 0 +} + +; Make sure ashr produces a possible value +define i32 @test6() { + %t = ashr i32 undef, 31 + ret i32 %t +; CHECK: @test6 +; CHECK: ret i32 -1 +} + +; Make sure lshr produces a possible value +define i32 @test7() { + %t = lshr i32 undef, 31 + ret i32 %t +; CHECK: @test7 +; CHECK: ret i32 0 +} + +; icmp eq with undef simplifies to undef +define i1 @test8() { + %t = icmp eq i32 undef, -1 + ret i1 %t +; CHECK: @test8 +; CHECK: ret i1 undef +} + +; Make sure we don't conclude that relational comparisons simplify to undef +define i1 @test9() { + %t = icmp ugt i32 undef, -1 + ret i1 %t +; CHECK: @test9 +; CHECK: icmp ugt +} + +; Make sure we handle extractvalue +define i64 @test10() { +entry: + %e = extractvalue { i64, i64 } undef, 1 + ret i64 %e +; CHECK: @test10 +; CHECK: ret i64 undef +} diff --git a/test/Transforms/ScalarRepl/2003-10-29-ArrayProblem.ll b/test/Transforms/ScalarRepl/2003-10-29-ArrayProblem.ll index d75498716df01..00e43a79043d0 100644 --- a/test/Transforms/ScalarRepl/2003-10-29-ArrayProblem.ll +++ b/test/Transforms/ScalarRepl/2003-10-29-ArrayProblem.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -scalarrepl -S | grep {alloca %T} +; RUN: opt < %s -scalarrepl -S | grep {alloca %%T} %T = type { [80 x i8], i32, i32 } declare i32 @.callback_1(i8*) diff --git a/test/Transforms/ScalarRepl/2011-09-22-PHISpeculateInvoke.ll b/test/Transforms/ScalarRepl/2011-09-22-PHISpeculateInvoke.ll new file mode 100644 index 0000000000000..f98f3e8fc458f --- /dev/null +++ b/test/Transforms/ScalarRepl/2011-09-22-PHISpeculateInvoke.ll @@ -0,0 +1,40 @@ +; RUN: opt < %s -scalarrepl -S | FileCheck %s +; PR10987 + +; Make sure scalarrepl doesn't move a load across an invoke which could +; modify the loaded value. +; (The PHI could theoretically be transformed by splitting the critical +; edge, but scalarrepl doesn't modify the CFG, at least at the moment.) + +declare void @extern_fn(i32*) +declare i32 @extern_fn2(i32) +declare i32 @__gcc_personality_v0(i32, i64, i8*, i8*) + +define void @odd_fn(i1) noinline { + %retptr1 = alloca i32 + %retptr2 = alloca i32 + br i1 %0, label %then, label %else + +then: ; preds = %2 + invoke void @extern_fn(i32* %retptr1) + to label %join unwind label %unwind + +else: ; preds = %2 + store i32 3, i32* %retptr2 + br label %join + +join: ; preds = %then, %else + %storemerge.in = phi i32* [ %retptr2, %else ], [ %retptr1, %then ] + %storemerge = load i32* %storemerge.in + %x3 = call i32 @extern_fn2(i32 %storemerge) + ret void + +unwind: ; preds = %then + %info = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @__gcc_personality_v0 + cleanup + call void @extern_fn(i32* null) + unreachable +} + +; CHECK: define void @odd_fn +; CHECK: %storemerge.in = phi i32* [ %retptr2, %else ], [ %retptr1, %then ] diff --git a/test/Transforms/ScalarRepl/2011-10-11-VectorMemset.ll b/test/Transforms/ScalarRepl/2011-10-11-VectorMemset.ll new file mode 100644 index 0000000000000..9e3123149297d --- /dev/null +++ b/test/Transforms/ScalarRepl/2011-10-11-VectorMemset.ll @@ -0,0 +1,22 @@ +; RUN: opt < %s -S -scalarrepl | FileCheck %s +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" +target triple = "x86_64-apple-darwin11.0.1" + +; CHECK: test +; CHECK-NOT: alloca + +define void @test() nounwind { +entry: + %a156286 = alloca [4 x <4 x float>], align 16 + br i1 undef, label %cif_done, label %for_test158.preheader + +for_test158.preheader: ; preds = %entry + %a156286305 = bitcast [4 x <4 x float>]* %a156286 to i8* + call void @llvm.memset.p0i8.i64(i8* %a156286305, i8 -1, i64 64, i32 16, i1 false) + unreachable + +cif_done: ; preds = %entry + ret void +} + +declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) nounwind diff --git a/test/Transforms/ScalarRepl/lifetime.ll b/test/Transforms/ScalarRepl/lifetime.ll new file mode 100644 index 0000000000000..3f558a1c3737c --- /dev/null +++ b/test/Transforms/ScalarRepl/lifetime.ll @@ -0,0 +1,139 @@ +; RUN: opt -scalarrepl -S < %s | FileCheck %s + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" +target triple = "x86_64-unknown-linux-gnu" + +declare void @llvm.lifetime.start(i64, i8*) +declare void @llvm.lifetime.end(i64, i8*) + +%t1 = type {i32, i32, i32} + +define void @test1() { +; CHECK: @test1 + %A = alloca %t1 + %A1 = getelementptr %t1* %A, i32 0, i32 0 + %A2 = getelementptr %t1* %A, i32 0, i32 1 + %A3 = getelementptr %t1* %A, i32 0, i32 2 + %B = bitcast i32* %A1 to i8* + store i32 0, i32* %A1 + call void @llvm.lifetime.start(i64 -1, i8* %B) + ret void +; CHECK-NEXT: ret void +} + +define void @test2() { +; CHECK: @test2 + %A = alloca %t1 + %A1 = getelementptr %t1* %A, i32 0, i32 0 + %A2 = getelementptr %t1* %A, i32 0, i32 1 + %A3 = getelementptr %t1* %A, i32 0, i32 2 + %B = bitcast i32* %A2 to i8* + store i32 0, i32* %A2 + call void @llvm.lifetime.start(i64 -1, i8* %B) + %C = load i32* %A2 + ret void +; CHECK: ret void +} + +define void @test3() { +; CHECK: @test3 + %A = alloca %t1 + %A1 = getelementptr %t1* %A, i32 0, i32 0 + %A2 = getelementptr %t1* %A, i32 0, i32 1 + %A3 = getelementptr %t1* %A, i32 0, i32 2 + %B = bitcast i32* %A2 to i8* + store i32 0, i32* %A2 + call void @llvm.lifetime.start(i64 6, i8* %B) + %C = load i32* %A2 + ret void +; CHECK-NEXT: ret void +} + +define void @test4() { +; CHECK: @test4 + %A = alloca %t1 + %A1 = getelementptr %t1* %A, i32 0, i32 0 + %A2 = getelementptr %t1* %A, i32 0, i32 1 + %A3 = getelementptr %t1* %A, i32 0, i32 2 + %B = bitcast i32* %A2 to i8* + store i32 0, i32* %A2 + call void @llvm.lifetime.start(i64 1, i8* %B) + %C = load i32* %A2 + ret void +; CHECK-NEXT: ret void +} + +%t2 = type {i32, [4 x i8], i32} + +define void @test5() { +; CHECK: @test5 + %A = alloca %t2 +; CHECK: alloca{{.*}}i8 +; CHECK: alloca{{.*}}i8 +; CHECK: alloca{{.*}}i8 + + %A21 = getelementptr %t2* %A, i32 0, i32 1, i32 0 + %A22 = getelementptr %t2* %A, i32 0, i32 1, i32 1 + %A23 = getelementptr %t2* %A, i32 0, i32 1, i32 2 + %A24 = getelementptr %t2* %A, i32 0, i32 1, i32 3 +; CHECK-NOT: store i8 1 + store i8 1, i8* %A21 + store i8 2, i8* %A22 + store i8 3, i8* %A23 + store i8 4, i8* %A24 + + %A1 = getelementptr %t2* %A, i32 0, i32 0 + %A2 = getelementptr %t2* %A, i32 0, i32 1, i32 1 + %A3 = getelementptr %t2* %A, i32 0, i32 2 + store i8 0, i8* %A2 + call void @llvm.lifetime.start(i64 5, i8* %A2) +; CHECK: llvm.lifetime{{.*}}i64 1 +; CHECK: llvm.lifetime{{.*}}i64 1 +; CHECK: llvm.lifetime{{.*}}i64 1 + %C = load i8* %A2 + ret void +} + +%t3 = type {[4 x i16], [4 x i8]} + +define void @test6() { +; CHECK: @test6 + %A = alloca %t3 +; CHECK: alloca i8 +; CHECK: alloca i8 +; CHECK: alloca i8 + + %A11 = getelementptr %t3* %A, i32 0, i32 0, i32 0 + %A12 = getelementptr %t3* %A, i32 0, i32 0, i32 1 + %A13 = getelementptr %t3* %A, i32 0, i32 0, i32 2 + %A14 = getelementptr %t3* %A, i32 0, i32 0, i32 3 + store i16 11, i16* %A11 + store i16 12, i16* %A12 + store i16 13, i16* %A13 + store i16 14, i16* %A14 +; CHECK-NOT: store i16 11 +; CHECK-NOT: store i16 12 +; CHECK-NOT: store i16 13 +; CHECK-NOT: store i16 14 + + %A21 = getelementptr %t3* %A, i32 0, i32 1, i32 0 + %A22 = getelementptr %t3* %A, i32 0, i32 1, i32 1 + %A23 = getelementptr %t3* %A, i32 0, i32 1, i32 2 + %A24 = getelementptr %t3* %A, i32 0, i32 1, i32 3 + store i8 21, i8* %A21 + store i8 22, i8* %A22 + store i8 23, i8* %A23 + store i8 24, i8* %A24 +; CHECK: store i8 21 +; CHECK: store i8 22 +; CHECK: store i8 23 +; CHECK-NOT: store i8 24 + + %B = bitcast i16* %A13 to i8* + call void @llvm.lifetime.start(i64 7, i8* %B) +; CHECK: lifetime.start{{.*}}i64 1 +; CHECK: lifetime.start{{.*}}i64 1 +; CHECK: lifetime.start{{.*}}i64 1 + + ret void +} diff --git a/test/Transforms/ScalarRepl/vector_promote.ll b/test/Transforms/ScalarRepl/vector_promote.ll index c51ef109c0b28..5c82ae4d196db 100644 --- a/test/Transforms/ScalarRepl/vector_promote.ll +++ b/test/Transforms/ScalarRepl/vector_promote.ll @@ -86,7 +86,6 @@ define i32 @test5(float %X) { ;; should turn into bitcast. ; CHECK-NEXT: ret i32 } - define i64 @test6(<2 x float> %X) { %X_addr = alloca <2 x float> store <2 x float> %X, <2 x float>* %X_addr @@ -98,168 +97,17 @@ define i64 @test6(<2 x float> %X) { ; CHECK: ret i64 } -define float @test7(<4 x float> %x) { - %a = alloca <4 x float> - store <4 x float> %x, <4 x float>* %a - %p = bitcast <4 x float>* %a to <2 x float>* - %b = load <2 x float>* %p - %q = getelementptr <4 x float>* %a, i32 0, i32 2 - %c = load float* %q - ret float %c -; CHECK: @test7 -; CHECK-NOT: alloca -; CHECK: bitcast <4 x float> %x to <2 x double> -; CHECK-NEXT: extractelement <2 x double> -; CHECK-NEXT: bitcast double %tmp4 to <2 x float> -; CHECK-NEXT: extractelement <4 x float> -} - -define void @test8(<4 x float> %x, <2 x float> %y) { - %a = alloca <4 x float> - store <4 x float> %x, <4 x float>* %a - %p = bitcast <4 x float>* %a to <2 x float>* - store <2 x float> %y, <2 x float>* %p - ret void -; CHECK: @test8 -; CHECK-NOT: alloca -; CHECK: bitcast <4 x float> %x to <2 x double> -; CHECK-NEXT: bitcast <2 x float> %y to double -; CHECK-NEXT: insertelement <2 x double> -; CHECK-NEXT: bitcast <2 x double> %tmp2 to <4 x float> -} +%struct.test7 = type { [6 x i32] } -define i256 @test9(<4 x i256> %x) { - %a = alloca <4 x i256> - store <4 x i256> %x, <4 x i256>* %a - %p = bitcast <4 x i256>* %a to <2 x i256>* - %b = load <2 x i256>* %p - %q = getelementptr <4 x i256>* %a, i32 0, i32 2 - %c = load i256* %q - ret i256 %c -; CHECK: @test9 -; CHECK-NOT: alloca -; CHECK: bitcast <4 x i256> %x to <2 x i512> -; CHECK-NEXT: extractelement <2 x i512> -; CHECK-NEXT: bitcast i512 %tmp4 to <2 x i256> -; CHECK-NEXT: extractelement <4 x i256> -} - -define void @test10(<4 x i256> %x, <2 x i256> %y) { - %a = alloca <4 x i256> - store <4 x i256> %x, <4 x i256>* %a - %p = bitcast <4 x i256>* %a to <2 x i256>* - store <2 x i256> %y, <2 x i256>* %p - ret void -; CHECK: @test10 -; CHECK-NOT: alloca -; CHECK: bitcast <4 x i256> %x to <2 x i512> -; CHECK-NEXT: bitcast <2 x i256> %y to i512 -; CHECK-NEXT: insertelement <2 x i512> -; CHECK-NEXT: bitcast <2 x i512> %tmp2 to <4 x i256> -} - -%union.v = type { <2 x i64> } - -define void @test11(<2 x i64> %x) { - %a = alloca %union.v - %p = getelementptr inbounds %union.v* %a, i32 0, i32 0 - store <2 x i64> %x, <2 x i64>* %p, align 16 - %q = getelementptr inbounds %union.v* %a, i32 0, i32 0 - %r = bitcast <2 x i64>* %q to <4 x float>* - %b = load <4 x float>* %r, align 16 - ret void -; CHECK: @test11 -; CHECK-NOT: alloca -} - -define void @test12() { -entry: - %a = alloca <64 x i8>, align 64 - store <64 x i8> undef, <64 x i8>* %a, align 64 - %p = bitcast <64 x i8>* %a to <16 x i8>* - %0 = load <16 x i8>* %p, align 64 - store <16 x i8> undef, <16 x i8>* %p, align 64 - %q = bitcast <16 x i8>* %p to <64 x i8>* - %1 = load <64 x i8>* %q, align 64 - ret void -; CHECK: @test12 -; CHECK-NOT: alloca -; CHECK: extractelement <4 x i128> -; CHECK: insertelement <4 x i128> -} - -define float @test13(<4 x float> %x, <2 x i32> %y) { - %a = alloca <4 x float> - store <4 x float> %x, <4 x float>* %a - %p = bitcast <4 x float>* %a to <2 x float>* - %b = load <2 x float>* %p - %q = getelementptr <4 x float>* %a, i32 0, i32 2 - %c = load float* %q - %r = bitcast <4 x float>* %a to <2 x i32>* - store <2 x i32> %y, <2 x i32>* %r - ret float %c -; CHECK: @test13 -; CHECK-NOT: alloca -; CHECK: bitcast <4 x float> %x to i128 -} - -define <3 x float> @test14(<3 x float> %x) { +define void @test7() { entry: - %x.addr = alloca <3 x float>, align 16 - %r = alloca <3 x i32>, align 16 - %extractVec = shufflevector <3 x float> %x, <3 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 undef> - %storetmp = bitcast <3 x float>* %x.addr to <4 x float>* - store <4 x float> %extractVec, <4 x float>* %storetmp, align 16 - %tmp = load <3 x float>* %x.addr, align 16 - %cmp = fcmp une <3 x float> %tmp, zeroinitializer - %sext = sext <3 x i1> %cmp to <3 x i32> - %and = and <3 x i32> <i32 1065353216, i32 1065353216, i32 1065353216>, %sext - %extractVec1 = shufflevector <3 x i32> %and, <3 x i32> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 undef> - %storetmp2 = bitcast <3 x i32>* %r to <4 x i32>* - store <4 x i32> %extractVec1, <4 x i32>* %storetmp2, align 16 - %tmp3 = load <3 x i32>* %r, align 16 - %0 = bitcast <3 x i32> %tmp3 to <3 x float> - %tmp4 = load <3 x float>* %x.addr, align 16 - ret <3 x float> %tmp4 -; CHECK: @test14 -; CHECK-NOT: alloca -; CHECK: shufflevector <4 x i32> %extractVec1, <4 x i32> undef, <3 x i32> <i32 0, i32 1, i32 2> -} - -define void @test15(<3 x i64>* sret %agg.result, <3 x i64> %x, <3 x i64> %min) { -entry: - %x.addr = alloca <3 x i64>, align 32 - %min.addr = alloca <3 x i64>, align 32 - %extractVec = shufflevector <3 x i64> %x, <3 x i64> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 undef> - %storetmp = bitcast <3 x i64>* %x.addr to <4 x i64>* - store <4 x i64> %extractVec, <4 x i64>* %storetmp, align 32 - %extractVec1 = shufflevector <3 x i64> %min, <3 x i64> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 undef> - %storetmp2 = bitcast <3 x i64>* %min.addr to <4 x i64>* - store <4 x i64> %extractVec1, <4 x i64>* %storetmp2, align 32 - %tmp = load <3 x i64>* %x.addr - %tmp5 = extractelement <3 x i64> %tmp, i32 0 - %tmp11 = insertelement <3 x i64> %tmp, i64 %tmp5, i32 0 - store <3 x i64> %tmp11, <3 x i64>* %x.addr - %tmp30 = load <3 x i64>* %x.addr, align 32 - store <3 x i64> %tmp30, <3 x i64>* %agg.result + %memtmp = alloca %struct.test7, align 16 + %0 = bitcast %struct.test7* %memtmp to <4 x i32>* + store <4 x i32> zeroinitializer, <4 x i32>* %0, align 16 + %1 = getelementptr inbounds %struct.test7* %memtmp, i64 0, i32 0, i64 5 + store i32 0, i32* %1, align 4 ret void -; CHECK: @test15 -; CHECK-NOT: alloca -; CHECK: shufflevector <4 x i64> %tmpV2, <4 x i64> undef, <3 x i32> <i32 0, i32 1, i32 2> -} - -define <4 x float> @test16(<4 x float> %x, i64 %y0, i64 %y1) { -entry: - %tmp8 = bitcast <4 x float> undef to <2 x double> - %tmp9 = bitcast i64 %y0 to double - %tmp10 = insertelement <2 x double> %tmp8, double %tmp9, i32 0 - %tmp11 = bitcast <2 x double> %tmp10 to <4 x float> - %tmp3 = bitcast <4 x float> %tmp11 to <2 x double> - %tmp4 = bitcast i64 %y1 to double - %tmp5 = insertelement <2 x double> %tmp3, double %tmp4, i32 1 - %tmp6 = bitcast <2 x double> %tmp5 to <4 x float> - ret <4 x float> %tmp6 -; CHECK: @test16 +; CHECK: @test7 ; CHECK-NOT: alloca -; CHECK: bitcast <4 x float> %tmp11 to <2 x double> +; CHECK: and i192 } diff --git a/test/Transforms/ScalarRepl/vectors-with-mismatched-elements.ll b/test/Transforms/ScalarRepl/vectors-with-mismatched-elements.ll new file mode 100644 index 0000000000000..c3fbdf5f86322 --- /dev/null +++ b/test/Transforms/ScalarRepl/vectors-with-mismatched-elements.ll @@ -0,0 +1,27 @@ +; RUN: opt -scalarrepl -S < %s | FileCheck %s +; rdar://9786827 + +; SROA should be able to handle the mixed types and eliminate the allocas here. + +; TODO: Currently it does this by falling back to integer "bags of bits". +; With enough cleverness, it should be possible to convert between <3 x i32> +; and <2 x i64> by using a combination of a bitcast and a shuffle. + +; CHECK: { +; CHECK-NOT: alloca +; CHECK: } + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128-n8:16:32" +target triple = "i386-apple-darwin11.0.0" + +define <2 x i64> @foo() nounwind { +entry: + %retval = alloca <3 x i32>, align 16 + %z = alloca <4 x i32>, align 16 + %tmp = load <4 x i32>* %z + %tmp1 = shufflevector <4 x i32> %tmp, <4 x i32> undef, <3 x i32> <i32 0, i32 1, i32 2> + store <3 x i32> %tmp1, <3 x i32>* %retval + %0 = bitcast <3 x i32>* %retval to <2 x i64>* + %1 = load <2 x i64>* %0, align 1 + ret <2 x i64> %1 +} diff --git a/test/Transforms/ScalarRepl/volatile.ll b/test/Transforms/ScalarRepl/volatile.ll index 3ff322e065cbb..ab276b043e3ae 100644 --- a/test/Transforms/ScalarRepl/volatile.ll +++ b/test/Transforms/ScalarRepl/volatile.ll @@ -1,5 +1,5 @@ -; RUN: opt < %s -scalarrepl -S | grep {volatile load} -; RUN: opt < %s -scalarrepl -S | grep {volatile store} +; RUN: opt < %s -scalarrepl -S | grep {load volatile} +; RUN: opt < %s -scalarrepl -S | grep {store volatile} define i32 @voltest(i32 %T) { %A = alloca {i32, i32} diff --git a/test/Transforms/SimplifyCFG/2003-08-05-InvokeCrash.ll b/test/Transforms/SimplifyCFG/2003-08-05-InvokeCrash.ll index c019931c07e75..7551e8fb747c7 100644 --- a/test/Transforms/SimplifyCFG/2003-08-05-InvokeCrash.ll +++ b/test/Transforms/SimplifyCFG/2003-08-05-InvokeCrash.ll @@ -8,6 +8,9 @@ define i32 @test() { Ret: ; preds = %0 ret i32 %A Ret2: ; preds = %0 + %val = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + catch i8* null ret i32 undef } +declare i32 @__gxx_personality_v0(...) diff --git a/test/Transforms/SimplifyCFG/2003-08-05-MishandleInvoke.ll b/test/Transforms/SimplifyCFG/2003-08-05-MishandleInvoke.ll index 15cd7730449ee..bc61a75561d36 100644 --- a/test/Transforms/SimplifyCFG/2003-08-05-MishandleInvoke.ll +++ b/test/Transforms/SimplifyCFG/2003-08-05-MishandleInvoke.ll @@ -6,7 +6,10 @@ define i32 @test() { invoke i32 @test( ) to label %Ret unwind label %Ret ; <i32>:1 [#uses=0] Ret: ; preds = %0, %0 + %val = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + catch i8* null %A = add i32 0, 1 ; <i32> [#uses=1] ret i32 %A } +declare i32 @__gxx_personality_v0(...) diff --git a/test/Transforms/SimplifyCFG/2005-10-02-InvokeSimplify.ll b/test/Transforms/SimplifyCFG/2005-10-02-InvokeSimplify.ll index 778aa3b1f7b43..2ecdc95259cc7 100644 --- a/test/Transforms/SimplifyCFG/2005-10-02-InvokeSimplify.ll +++ b/test/Transforms/SimplifyCFG/2005-10-02-InvokeSimplify.ll @@ -4,6 +4,8 @@ define i1 @foo() { %X = invoke i1 @foo( ) to label %N unwind label %F ; <i1> [#uses=1] F: ; preds = %0 + %val = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + catch i8* null ret i1 false N: ; preds = %0 br i1 %X, label %A, label %B @@ -13,3 +15,4 @@ B: ; preds = %N ret i1 true } +declare i32 @__gxx_personality_v0(...) diff --git a/test/Transforms/SimplifyCFG/2006-10-29-InvokeCrash.ll b/test/Transforms/SimplifyCFG/2006-10-29-InvokeCrash.ll index dba41c9b111fd..27d9d8f674181 100644 --- a/test/Transforms/SimplifyCFG/2006-10-29-InvokeCrash.ll +++ b/test/Transforms/SimplifyCFG/2006-10-29-InvokeCrash.ll @@ -275,12 +275,16 @@ invcont153: ; preds = %invcont151 invoke void @_ZN12QFontMetricsD1Ev( %struct.QFontMetrics* %tmp.upgrd.2 ) to label %cleanup171 unwind label %cleanup173 cleanup168: ; preds = %invcont151, %invcont148, %invcont146 + %val168 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + cleanup invoke void @_ZN12QFontMetricsD1Ev( %struct.QFontMetrics* %tmp.upgrd.2 ) to label %cleanup173 unwind label %cleanup173 cleanup171: ; preds = %invcont153 invoke void @_ZN5QFontD1Ev( %struct.QFont* %tmp.upgrd.3 ) to label %finally170 unwind label %cleanup192 cleanup173: ; preds = %cleanup168, %cleanup168, %invcont153, %invcont144 + %val173 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + cleanup invoke void @_ZN5QFontD1Ev( %struct.QFont* %tmp.upgrd.3 ) to label %cleanup192 unwind label %cleanup192 finally170: ; preds = %cleanup171 @@ -300,12 +304,16 @@ cleanup185: ; preds = %invcont181 invoke void @_ZN5QFontD1Ev( %struct.QFont* %font ) to label %cleanup190 unwind label %cleanup192 cleanup187: ; preds = %invcont181, %invcont179, %invcont177 + %val187 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + cleanup invoke void @_ZN5QFontD1Ev( %struct.QFont* %font ) to label %cleanup192 unwind label %cleanup192 cleanup190: ; preds = %cleanup185 invoke void @_ZN16QTextFrameFormatD1Ev( %struct.QTextBlockFormat* %fmt ) to label %cond_next194 unwind label %cleanup329 cleanup192: ; preds = %cleanup187, %cleanup187, %cleanup185, %finally170, %cleanup173, %cleanup173, %cleanup171, %invcont141, %invcont124, %invcont122, %invcont120, %invcont118, %invcont117, %invcont114, %invcont111 + %val192 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + cleanup invoke void @_ZN16QTextFrameFormatD1Ev( %struct.QTextBlockFormat* %fmt ) to label %cleanup329 unwind label %cleanup329 cond_next194: ; preds = %cleanup190, %invcont83 @@ -450,8 +458,10 @@ cleanup328: ; preds = %invcont call void @_ZN8QPainterD1Ev( %struct.QPainter* %p ) ret void cleanup329: ; preds = %cond_true319, %cond_true302, %cond_next293, %cond_true277, %cond_true266, %cond_next258, %cond_next244, %cond_next225, %cond_true220, %invcont210, %cond_next208, %cond_false204, %cond_true200, %cond_next194, %cleanup192, %cleanup192, %cleanup190, %invcont106, %invcont104, %invcont103, %invcont100, %invcont98, %invcont94, %cond_false, %invcont83, %invcont79, %invcont57, %invcont51, %invcont45, %cond_next42, %invcont37, %cond_true35, %invcont29, %invcont25, %cond_true24, %cond_next, %entry + %val = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + cleanup call void @_ZN8QPainterD1Ev( %struct.QPainter* %p ) - unwind + resume { i8*, i32 } %val } declare void @_ZN6QSizeFC1Edd(%struct.QPointF*, double, double) @@ -553,3 +563,5 @@ declare i32 @_ZNK8QPrinter12printerStateEv(%struct.QPrinter*) declare i1 @_ZN8QPrinter7newPageEv(%struct.QPrinter*) declare void @_ZN8QPainterD1Ev(%struct.QPainter*) + +declare i32 @__gxx_personality_v0(...) diff --git a/test/Transforms/SimplifyCFG/2009-01-19-UnconditionalTrappingConstantExpr.ll b/test/Transforms/SimplifyCFG/2009-01-19-UnconditionalTrappingConstantExpr.ll index 33167bd5c661d..568e61c6ac6de 100644 --- a/test/Transforms/SimplifyCFG/2009-01-19-UnconditionalTrappingConstantExpr.ll +++ b/test/Transforms/SimplifyCFG/2009-01-19-UnconditionalTrappingConstantExpr.ll @@ -15,7 +15,7 @@ bb2: ret i32 42 bb6: - unwind + ret i32 927 } define i32 @test2(i32 %tmp21, i32 %tmp24, i1 %tmp34) { @@ -26,6 +26,6 @@ bb5: ; preds = %bb4 bb6: ret i32 42 bb7: - unwind + ret i32 927 } diff --git a/test/Transforms/SimplifyCFG/2009-06-15-InvokeCrash.ll b/test/Transforms/SimplifyCFG/2009-06-15-InvokeCrash.ll index f99cbe1c8b83d..abf4455d780ba 100644 --- a/test/Transforms/SimplifyCFG/2009-06-15-InvokeCrash.ll +++ b/test/Transforms/SimplifyCFG/2009-06-15-InvokeCrash.ll @@ -277,12 +277,16 @@ invcont153: ; preds = %invcont151 invoke void @_ZN12QFontMetricsD1Ev( %struct.QFontMetrics* %tmp.upgrd.2 ) to label %cleanup171 unwind label %cleanup173 cleanup168: ; preds = %invcont151, %invcont148, %invcont146 + %val168 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + cleanup invoke void @_ZN12QFontMetricsD1Ev( %struct.QFontMetrics* %tmp.upgrd.2 ) to label %cleanup173 unwind label %cleanup173 cleanup171: ; preds = %invcont153 invoke void @_ZN5QFontD1Ev( %struct.QFont* %tmp.upgrd.3 ) to label %finally170 unwind label %cleanup192 cleanup173: ; preds = %cleanup168, %cleanup168, %invcont153, %invcont144 + %val173 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + cleanup invoke void @_ZN5QFontD1Ev( %struct.QFont* %tmp.upgrd.3 ) to label %cleanup192 unwind label %cleanup192 finally170: ; preds = %cleanup171 @@ -302,12 +306,16 @@ cleanup185: ; preds = %invcont181 invoke void @_ZN5QFontD1Ev( %struct.QFont* %font ) to label %cleanup190 unwind label %cleanup192 cleanup187: ; preds = %invcont181, %invcont179, %invcont177 + %val187 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + cleanup invoke void @_ZN5QFontD1Ev( %struct.QFont* %font ) to label %cleanup192 unwind label %cleanup192 cleanup190: ; preds = %cleanup185 invoke void @_ZN16QTextFrameFormatD1Ev( %struct.QTextBlockFormat* %fmt ) to label %cond_next194 unwind label %cleanup329 cleanup192: ; preds = %cleanup187, %cleanup187, %cleanup185, %finally170, %cleanup173, %cleanup173, %cleanup171, %invcont141, %invcont124, %invcont122, %invcont120, %invcont118, %invcont117, %invcont114, %invcont111 + %val192 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + cleanup invoke void @_ZN16QTextFrameFormatD1Ev( %struct.QTextBlockFormat* %fmt ) to label %cleanup329 unwind label %cleanup329 cond_next194: ; preds = %cleanup190, %invcont83 @@ -452,8 +460,10 @@ cleanup328: ; preds = %invcont call void @_ZN8QPainterD1Ev( %struct.QPainter* %p ) ret void cleanup329: ; preds = %cond_true319, %cond_true302, %cond_next293, %cond_true277, %cond_true266, %cond_next258, %cond_next244, %cond_next225, %cond_true220, %invcont210, %cond_next208, %cond_false204, %cond_true200, %cond_next194, %cleanup192, %cleanup192, %cleanup190, %invcont106, %invcont104, %invcont103, %invcont100, %invcont98, %invcont94, %cond_false, %invcont83, %invcont79, %invcont57, %invcont51, %invcont45, %cond_next42, %invcont37, %cond_true35, %invcont29, %invcont25, %cond_true24, %cond_next, %entry + %val329 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + cleanup call void @_ZN8QPainterD1Ev( %struct.QPainter* %p ) - unwind + resume { i8*, i32 } %val329 } declare void @_ZN6QSizeFC1Edd(%struct.QPointF*, double, double) @@ -555,3 +565,5 @@ declare i32 @_ZNK8QPrinter12printerStateEv(%struct.QPrinter*) declare i1 @_ZN8QPrinter7newPageEv(%struct.QPrinter*) declare void @_ZN8QPainterD1Ev(%struct.QPainter*) + +declare i32 @__gxx_personality_v0(...) diff --git a/test/Transforms/SimplifyCFG/2010-03-30-InvokeCrash.ll b/test/Transforms/SimplifyCFG/2010-03-30-InvokeCrash.ll index ced89cf4c2b31..7bffa1a8e0e2f 100644 --- a/test/Transforms/SimplifyCFG/2010-03-30-InvokeCrash.ll +++ b/test/Transforms/SimplifyCFG/2010-03-30-InvokeCrash.ll @@ -14,5 +14,9 @@ r: ; preds = %entry ret void u: ; preds = %entry - unwind + %val = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0 + cleanup + resume { i8*, i32 } %val } + +declare i32 @__gxx_personality_v0(...) diff --git a/test/Transforms/SimplifyCFG/2011-09-05-TrivialLPad.ll b/test/Transforms/SimplifyCFG/2011-09-05-TrivialLPad.ll new file mode 100644 index 0000000000000..7558419a2ebda --- /dev/null +++ b/test/Transforms/SimplifyCFG/2011-09-05-TrivialLPad.ll @@ -0,0 +1,22 @@ +; RUN: opt < %s -simplifycfg -S | FileCheck %s + +; CHECK-NOT: invoke +; CHECK-NOT: landingpad + +declare void @bar() + +define i32 @foo() { +entry: + invoke void @bar() + to label %return unwind label %lpad + +return: + ret i32 0 + +lpad: + %lp = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @__gxx_personality_v0 + cleanup + resume { i8*, i32 } %lp +} + +declare i32 @__gxx_personality_v0(i32, i64, i8*, i8*) diff --git a/test/Transforms/SimplifyCFG/BrUnwind.ll b/test/Transforms/SimplifyCFG/BrUnwind.ll index b19a27dea048d..7ab8faa2cea98 100644 --- a/test/Transforms/SimplifyCFG/BrUnwind.ll +++ b/test/Transforms/SimplifyCFG/BrUnwind.ll @@ -10,6 +10,6 @@ B: ; preds = %0 call void @test( i1 %C ) br label %X X: ; preds = %B, %A - unwind + ret void } diff --git a/test/Transforms/SimplifyCFG/invoke_unwind.ll b/test/Transforms/SimplifyCFG/invoke_unwind.ll index 73faa952fba93..ed7ff8287f20d 100644 --- a/test/Transforms/SimplifyCFG/invoke_unwind.ll +++ b/test/Transforms/SimplifyCFG/invoke_unwind.ll @@ -12,21 +12,9 @@ define i32 @test1() { to label %1 unwind label %Rethrow ret i32 0 Rethrow: - unwind + %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 + catch i8* null + resume { i8*, i32 } %exn } - -; Verify that simplifycfg isn't duplicating 'unwind' instructions. Doing this -; is bad because it discourages commoning. -define i32 @test2(i1 %c) { -; CHECK: @test2 -; CHECK: T: -; CHECK-NEXT: call void @bar() -; CHECK-NEXT: br label %F - br i1 %c, label %T, label %F -T: - call void @bar() - br label %F -F: - unwind -} +declare i32 @__gxx_personality_v0(...) diff --git a/test/Transforms/SimplifyCFG/phi-undef-loadstore.ll b/test/Transforms/SimplifyCFG/phi-undef-loadstore.ll new file mode 100644 index 0000000000000..65d888ea01e10 --- /dev/null +++ b/test/Transforms/SimplifyCFG/phi-undef-loadstore.ll @@ -0,0 +1,87 @@ +; RUN: opt -simplifycfg -S < %s | FileCheck %s + +declare void @bar() nounwind + +define i32 @test1(i32* %a, i32 %b, i32* %c, i32 %d) nounwind { +entry: + %tobool = icmp eq i32 %b, 0 + br i1 %tobool, label %if.else, label %if.then + +if.then: ; preds = %entry + tail call void @bar() nounwind + br label %if.end7 + +if.else: ; preds = %entry + %tobool3 = icmp eq i32 %d, 0 + br i1 %tobool3, label %if.end7, label %if.then4 + +if.then4: ; preds = %if.else + tail call void @bar() nounwind + br label %if.end7 + +if.end7: ; preds = %if.else, %if.then4, %if.then + %x.0 = phi i32* [ %a, %if.then ], [ %c, %if.then4 ], [ null, %if.else ] + %tmp9 = load i32* %x.0 + ret i32 %tmp9 + +; CHECK: @test1 +; CHECK: if.else: +; CHECK: br label %if.end7 + +; CHECK: phi i32* [ %a, %if.then ], [ %c, %if.else ] +} + +define i32 @test2(i32* %a, i32 %b, i32* %c, i32 %d) nounwind { +entry: + %tobool = icmp eq i32 %b, 0 + br i1 %tobool, label %if.else, label %if.then + +if.then: ; preds = %entry + tail call void @bar() nounwind + br label %if.end7 + +if.else: ; preds = %entry + %tobool3 = icmp eq i32 %d, 0 + br i1 %tobool3, label %if.end7, label %if.then4 + +if.then4: ; preds = %if.else + tail call void @bar() nounwind + br label %if.end7 + +if.end7: ; preds = %if.else, %if.then4, %if.then + %x.0 = phi i32* [ %a, %if.then ], [ null, %if.then4 ], [ null, %if.else ] + %tmp9 = load i32* %x.0 + ret i32 %tmp9 +; CHECK: @test2 +; CHECK: if.else: +; CHECK: unreachable + +; CHECK-NOT: phi +} + +define i32 @test3(i32* %a, i32 %b, i32* %c, i32 %d) nounwind { +entry: + %tobool = icmp eq i32 %b, 0 + br i1 %tobool, label %if.else, label %if.then + +if.then: ; preds = %entry + tail call void @bar() nounwind + br label %if.end7 + +if.else: ; preds = %entry + %tobool3 = icmp eq i32 %d, 0 + br i1 %tobool3, label %if.end7, label %if.then4 + +if.then4: ; preds = %if.else + tail call void @bar() nounwind + br label %if.end7 + +if.end7: ; preds = %if.else, %if.then4, %if.then + %x.0 = phi i32* [ %a, %if.then ], [ null, %if.then4 ], [ null, %if.else ] + tail call void @bar() nounwind + %tmp9 = load i32* %x.0 + ret i32 %tmp9 +; CHECK: @test3 +; CHECK: if.end7: +; CHECK: phi i32* [ %a, %if.then ], [ null, %if.then4 ], [ null, %if.else ] +} diff --git a/test/Transforms/SimplifyCFG/trapping-load-unreachable.ll b/test/Transforms/SimplifyCFG/trapping-load-unreachable.ll index 7bca5f5afa0d6..10d6981af0e67 100644 --- a/test/Transforms/SimplifyCFG/trapping-load-unreachable.ll +++ b/test/Transforms/SimplifyCFG/trapping-load-unreachable.ll @@ -11,14 +11,14 @@ entry: br i1 %0, label %bb, label %return bb: ; preds = %entry - %1 = volatile load i32* null + %1 = load volatile i32* null unreachable br label %return return: ; preds = %entry ret void ; CHECK: @test1 -; CHECK: volatile load +; CHECK: load volatile } ; rdar://7958343 @@ -35,10 +35,53 @@ entry: ; PR7369 define void @test3() nounwind { entry: - volatile store i32 4, i32* null + store volatile i32 4, i32* null ret void ; CHECK: @test3 -; CHECK: volatile store i32 4, i32* null +; CHECK: store volatile i32 4, i32* null ; CHECK: ret } + +; Check store before unreachable. +define void @test4(i1 %C, i32* %P) { +; CHECK: @test4 +; CHECK: entry: +; CHECK-NEXT: br i1 %C +entry: + br i1 %C, label %T, label %F +T: + store volatile i32 0, i32* %P + unreachable +F: + ret void +} + +; Check cmpxchg before unreachable. +define void @test5(i1 %C, i32* %P) { +; CHECK: @test5 +; CHECK: entry: +; CHECK-NEXT: br i1 %C +entry: + br i1 %C, label %T, label %F +T: + cmpxchg volatile i32* %P, i32 0, i32 1 seq_cst + unreachable +F: + ret void +} + +; Check atomicrmw before unreachable. +define void @test6(i1 %C, i32* %P) { +; CHECK: @test6 +; CHECK: entry: +; CHECK-NEXT: br i1 %C +entry: + br i1 %C, label %T, label %F +T: + atomicrmw volatile xchg i32* %P, i32 0 seq_cst + unreachable +F: + ret void +} + diff --git a/test/Transforms/SimplifyLibCalls/StrCmp.ll b/test/Transforms/SimplifyLibCalls/StrCmp.ll index 73596351a8ccf..60854d76c97ae 100644 --- a/test/Transforms/SimplifyLibCalls/StrCmp.ll +++ b/test/Transforms/SimplifyLibCalls/StrCmp.ll @@ -1,28 +1,65 @@ ; Test that the StrCmpOptimizer works correctly -; RUN: opt < %s -simplify-libcalls -S | \ -; RUN: not grep {call.*strcmp} +; RUN: opt < %s -simplify-libcalls -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" @hello = constant [6 x i8] c"hello\00" ; <[6 x i8]*> [#uses=1] @hell = constant [5 x i8] c"hell\00" ; <[5 x i8]*> [#uses=1] +@bell = constant [5 x i8] c"bell\00" ; <[5 x i8]*> [#uses=1] @null = constant [1 x i8] zeroinitializer ; <[1 x i8]*> [#uses=1] declare i32 @strcmp(i8*, i8*) -declare i32 @puts(i8*) - -define i32 @main() { - %hello_p = getelementptr [6 x i8]* @hello, i32 0, i32 0 ; <i8*> [#uses=5] - %hell_p = getelementptr [5 x i8]* @hell, i32 0, i32 0 ; <i8*> [#uses=1] - %null_p = getelementptr [1 x i8]* @null, i32 0, i32 0 ; <i8*> [#uses=4] - %temp1 = call i32 @strcmp( i8* %hello_p, i8* %hello_p ) ; <i32> [#uses=1] - %temp2 = call i32 @strcmp( i8* %null_p, i8* %null_p ) ; <i32> [#uses=1] - %temp3 = call i32 @strcmp( i8* %hello_p, i8* %null_p ) ; <i32> [#uses=1] - %temp4 = call i32 @strcmp( i8* %null_p, i8* %hello_p ) ; <i32> [#uses=1] - %temp5 = call i32 @strcmp( i8* %hell_p, i8* %hello_p ) ; <i32> [#uses=1] - %rslt1 = add i32 %temp1, %temp2 ; <i32> [#uses=1] - %rslt2 = add i32 %rslt1, %temp3 ; <i32> [#uses=1] - %rslt3 = add i32 %rslt2, %temp4 ; <i32> [#uses=1] - %rslt4 = add i32 %rslt3, %temp5 ; <i32> [#uses=1] - ret i32 %rslt4 +; strcmp("", x) -> -*x +define i32 @test1(i8* %str) { + %temp1 = call i32 @strcmp(i8* getelementptr inbounds ([1 x i8]* @null, i32 0, i32 0), i8* %str) + ret i32 %temp1 + ; CHECK: @test1 + ; CHECK: %strcmpload = load i8* %str + ; CHECK: %1 = zext i8 %strcmpload to i32 + ; CHECK: %temp1 = sub i32 0, %1 + ; CHECK: ret i32 %temp1 +} + +; strcmp(x, "") -> *x +define i32 @test2(i8* %str) { + %temp1 = call i32 @strcmp(i8* %str, i8* getelementptr inbounds ([1 x i8]* @null, i32 0, i32 0)) + ret i32 %temp1 + ; CHECK: @test2 + ; CHECK: %strcmpload = load i8* %str + ; CHECK: %temp1 = zext i8 %strcmpload to i32 + ; CHECK: ret i32 %temp1 } +; strcmp(x, y) -> cnst +define i32 @test3() { + %temp1 = call i32 @strcmp(i8* getelementptr inbounds ([5 x i8]* @hell, i32 0, i32 0), i8* getelementptr inbounds ([6 x i8]* @hello, i32 0, i32 0)) + ret i32 %temp1 + ; CHECK: @test3 + ; CHECK: ret i32 -1 +} +define i32 @test4() { + %temp1 = call i32 @strcmp(i8* getelementptr inbounds ([5 x i8]* @hell, i32 0, i32 0), i8* getelementptr inbounds ([1 x i8]* @null, i32 0, i32 0)) + ret i32 %temp1 + ; CHECK: @test4 + ; CHECK: ret i32 1 +} + +; strcmp(x, y) -> memcmp(x, y, <known length>) +; (This transform is rather difficult to trigger in a useful manner) +define i32 @test5(i1 %b) { + %sel = select i1 %b, i8* getelementptr inbounds ([5 x i8]* @hell, i32 0, i32 0), i8* getelementptr inbounds ([5 x i8]* @bell, i32 0, i32 0) + %temp1 = call i32 @strcmp(i8* getelementptr inbounds ([6 x i8]* @hello, i32 0, i32 0), i8* %sel) + ret i32 %temp1 + ; CHECK: @test5 + ; CHECK: %memcmp = call i32 @memcmp(i8* getelementptr inbounds ([6 x i8]* @hello, i32 0, i32 0), i8* %sel, i32 5) + ; CHECK: ret i32 %memcmp +} + +; strcmp(x,x) -> 0 +define i32 @test6(i8* %str) { + %temp1 = call i32 @strcmp(i8* %str, i8* %str) + ret i32 %temp1 + ; CHECK: @test6 + ; CHECK: ret i32 0 +} diff --git a/test/Transforms/SimplifyLibCalls/StrNCmp.ll b/test/Transforms/SimplifyLibCalls/StrNCmp.ll index 8b536a5486997..0b2a501a3c8a7 100644 --- a/test/Transforms/SimplifyLibCalls/StrNCmp.ll +++ b/test/Transforms/SimplifyLibCalls/StrNCmp.ll @@ -1,35 +1,78 @@ -; Test that the StrNCmpOptimizer works correctly -; RUN: opt < %s -simplify-libcalls -S | \ -; RUN: not grep {call.*strncmp} +; Test that the StrCmpOptimizer works correctly +; RUN: opt < %s -simplify-libcalls -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-n8:16:32" -target triple = "i386-apple-darwin9.0" +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" @hello = constant [6 x i8] c"hello\00" ; <[6 x i8]*> [#uses=1] @hell = constant [5 x i8] c"hell\00" ; <[5 x i8]*> [#uses=1] +@bell = constant [5 x i8] c"bell\00" ; <[5 x i8]*> [#uses=1] @null = constant [1 x i8] zeroinitializer ; <[1 x i8]*> [#uses=1] declare i32 @strncmp(i8*, i8*, i32) -declare i32 @puts(i8*) - -define i32 @main() { - %hello_p = getelementptr [6 x i8]* @hello, i32 0, i32 0 ; <i8*> [#uses=5] - %hell_p = getelementptr [5 x i8]* @hell, i32 0, i32 0 ; <i8*> [#uses=1] - %null_p = getelementptr [1 x i8]* @null, i32 0, i32 0 ; <i8*> [#uses=4] - %temp1 = call i32 @strncmp( i8* %hello_p, i8* %hello_p, i32 5 ) ; <i32> [#uses=1] - %temp2 = call i32 @strncmp( i8* %null_p, i8* %null_p, i32 0 ) ; <i32> [#uses=1] - %temp3 = call i32 @strncmp( i8* %hello_p, i8* %null_p, i32 0 ) ; <i32> [#uses=1] - %temp4 = call i32 @strncmp( i8* %null_p, i8* %hello_p, i32 0 ) ; <i32> [#uses=1] - %temp5 = call i32 @strncmp( i8* %hell_p, i8* %hello_p, i32 4 ) ; <i32> [#uses=1] - %rslt1 = add i32 %temp1, %temp2 ; <i32> [#uses=1] - %rslt2 = add i32 %rslt1, %temp3 ; <i32> [#uses=1] - %rslt3 = add i32 %rslt2, %temp4 ; <i32> [#uses=1] - %rslt4 = add i32 %rslt3, %temp5 ; <i32> [#uses=1] - ret i32 %rslt4 -} - -define i32 @test1(i8* %P, i8* %Q) { - %cmp = call i32 @strncmp(i8* %P, i8* %Q, i32 1) - ret i32 %cmp +; strcmp("", x) -> -*x +define i32 @test1(i8* %str) { + %temp1 = call i32 @strncmp(i8* getelementptr inbounds ([1 x i8]* @null, i32 0, i32 0), i8* %str, i32 10) + ret i32 %temp1 + ; CHECK: @test1 + ; CHECK: %strcmpload = load i8* %str + ; CHECK: %1 = zext i8 %strcmpload to i32 + ; CHECK: %temp1 = sub i32 0, %1 + ; CHECK: ret i32 %temp1 +} + +; strcmp(x, "") -> *x +define i32 @test2(i8* %str) { + %temp1 = call i32 @strncmp(i8* %str, i8* getelementptr inbounds ([1 x i8]* @null, i32 0, i32 0), i32 10) + ret i32 %temp1 + ; CHECK: @test2 + ; CHECK: %strcmpload = load i8* %str + ; CHECK: %temp1 = zext i8 %strcmpload to i32 + ; CHECK: ret i32 %temp1 +} + +; strncmp(x, y, n) -> cnst +define i32 @test3() { + %temp1 = call i32 @strncmp(i8* getelementptr inbounds ([5 x i8]* @hell, i32 0, i32 0), i8* getelementptr inbounds ([6 x i8]* @hello, i32 0, i32 0), i32 10) + ret i32 %temp1 + ; CHECK: @test3 + ; CHECK: ret i32 -1 +} +define i32 @test4() { + %temp1 = call i32 @strncmp(i8* getelementptr inbounds ([5 x i8]* @hell, i32 0, i32 0), i8* getelementptr inbounds ([1 x i8]* @null, i32 0, i32 0), i32 10) + ret i32 %temp1 + ; CHECK: @test4 + ; CHECK: ret i32 1 +} +define i32 @test5() { + %temp1 = call i32 @strncmp(i8* getelementptr inbounds ([5 x i8]* @hell, i32 0, i32 0), i8* getelementptr inbounds ([6 x i8]* @hello, i32 0, i32 0), i32 4) + ret i32 %temp1 + ; CHECK: @test5 + ; CHECK: ret i32 0 +} + +; strncmp(x,y,1) -> memcmp(x,y,1) +define i32 @test6(i8* %str1, i8* %str2) { + %temp1 = call i32 @strncmp(i8* %str1, i8* %str2, i32 1) + ret i32 %temp1 + ; CHECK: @test6 + ; CHECK: load i8* + ; CHECK: load i8* + ; CHECK: sub i32 +} + +; strncmp(x,y,0) -> 0 +define i32 @test7(i8* %str1, i8* %str2) { + %temp1 = call i32 @strncmp(i8* %str1, i8* %str2, i32 0) + ret i32 %temp1 + ; CHECK: @test7 + ; CHECK: ret i32 0 +} + +; strncmp(x,x,n) -> 0 +define i32 @test8(i8* %str, i32 %n) { + %temp1 = call i32 @strncmp(i8* %str, i8* %str, i32 %n) + ret i32 %temp1 + ; CHECK: @test8 + ; CHECK: ret i32 0 } diff --git a/test/Transforms/SimplifyLibCalls/memcmp.ll b/test/Transforms/SimplifyLibCalls/memcmp.ll index ee99501bc0d83..6ca4dc97a194e 100644 --- a/test/Transforms/SimplifyLibCalls/memcmp.ll +++ b/test/Transforms/SimplifyLibCalls/memcmp.ll @@ -10,26 +10,26 @@ declare i32 @memcmp(i8*, i8*, i32) define void @test(i8* %P, i8* %Q, i32 %N, i32* %IP, i1* %BP) { %A = call i32 @memcmp( i8* %P, i8* %P, i32 %N ) ; <i32> [#uses=1] ; CHECK-NOT: call {{.*}} memcmp -; CHECK: volatile store - volatile store i32 %A, i32* %IP +; CHECK: store volatile + store volatile i32 %A, i32* %IP %B = call i32 @memcmp( i8* %P, i8* %Q, i32 0 ) ; <i32> [#uses=1] ; CHECK-NOT: call {{.*}} memcmp -; CHECK: volatile store - volatile store i32 %B, i32* %IP +; CHECK: store volatile + store volatile i32 %B, i32* %IP %C = call i32 @memcmp( i8* %P, i8* %Q, i32 1 ) ; <i32> [#uses=1] ; CHECK: load ; CHECK: zext ; CHECK: load ; CHECK: zext ; CHECK: sub -; CHECK: volatile store - volatile store i32 %C, i32* %IP - %F = call i32 @memcmp(i8* getelementptr ([4 x i8]* @hel, i32 0, i32 0), - i8* getelementptr ([8 x i8]* @hello_u, i32 0, i32 0), - i32 3) +; CHECK: store volatile + store volatile i32 %C, i32* %IP + %F = call i32 @memcmp(i8* getelementptr ([4 x i8]* @hel, i32 0, i32 0), + i8* getelementptr ([8 x i8]* @hello_u, i32 0, i32 0), + i32 3) ; CHECK-NOT: call {{.*}} memcmp -; CHECK: volatile store - volatile store i32 %F, i32* %IP +; CHECK: store volatile + store volatile i32 %F, i32* %IP ret void } diff --git a/test/Transforms/SimplifyLibCalls/pow-to-sqrt.ll b/test/Transforms/SimplifyLibCalls/pow-to-sqrt.ll index 669b414531af0..0480fdda8916b 100644 --- a/test/Transforms/SimplifyLibCalls/pow-to-sqrt.ll +++ b/test/Transforms/SimplifyLibCalls/pow-to-sqrt.ll @@ -7,9 +7,9 @@ ; CHECK: define float @foo(float %x) nounwind { ; CHECK: %sqrtf = call float @sqrtf(float %x) nounwind readonly ; CHECK: %fabsf = call float @fabsf(float %sqrtf) nounwind readonly -; CHECK: %tmp = fcmp oeq float %x, 0xFFF0000000000000 -; CHECK: %tmp1 = select i1 %tmp, float 0x7FF0000000000000, float %fabsf -; CHECK: ret float %tmp1 +; CHECK: %1 = fcmp oeq float %x, 0xFFF0000000000000 +; CHECK: %retval = select i1 %1, float 0x7FF0000000000000, float %fabsf +; CHECK: ret float %retval define float @foo(float %x) nounwind { %retval = call float @powf(float %x, float 0.5) @@ -19,9 +19,9 @@ define float @foo(float %x) nounwind { ; CHECK: define double @doo(double %x) nounwind { ; CHECK: %sqrt = call double @sqrt(double %x) nounwind readonly ; CHECK: %fabs = call double @fabs(double %sqrt) nounwind readonly -; CHECK: %tmp = fcmp oeq double %x, 0xFFF0000000000000 -; CHECK: %tmp1 = select i1 %tmp, double 0x7FF0000000000000, double %fabs -; CHECK: ret double %tmp1 +; CHECK: %1 = fcmp oeq double %x, 0xFFF0000000000000 +; CHECK: %retval = select i1 %1, double 0x7FF0000000000000, double %fabs +; CHECK: ret double %retval ; CHECK: } define double @doo(double %x) nounwind { diff --git a/test/Transforms/Sink/basic.ll b/test/Transforms/Sink/basic.ll index 54b7f1369de47..23433728c13a6 100644 --- a/test/Transforms/Sink/basic.ll +++ b/test/Transforms/Sink/basic.ll @@ -20,3 +20,19 @@ true: false: ret i32 0 } + +; But don't sink volatile loads... + +; CHECK: @foo2 +; CHECK: load volatile +; CHECK-NEXT: store i32 + +define i32 @foo2(i1 %z) { + %l = load volatile i32* @A + store i32 0, i32* @B + br i1 %z, label %true, label %false +true: + ret i32 %l +false: + ret i32 0 +} diff --git a/test/Transforms/StripSymbols/block-address.ll b/test/Transforms/StripSymbols/block-address.ll new file mode 100644 index 0000000000000..d22c6b1b157c9 --- /dev/null +++ b/test/Transforms/StripSymbols/block-address.ll @@ -0,0 +1,23 @@ +; RUN: opt %s -strip -S | FileCheck %s +; PR10286 + +@main_addrs = constant [2 x i8*] [i8* blockaddress(@f, %FOO), i8* blockaddress(@f, %BAR)] +; CHECK: @main_addrs = constant [2 x i8*] [i8* blockaddress(@f, %2), i8* blockaddress(@f, %3)] + +declare void @foo() nounwind +declare void @bar() nounwind + +define void @f(i8* %indirect.goto.dest) nounwind uwtable ssp { +entry: + indirectbr i8* %indirect.goto.dest, [label %FOO, label %BAR] + + ; CHECK: indirectbr i8* %0, [label %2, label %3] + +FOO: + call void @foo() + ret void + +BAR: + call void @bar() + ret void +} diff --git a/test/Transforms/TailCallElim/dont_reorder_load.ll b/test/Transforms/TailCallElim/dont_reorder_load.ll index cc273c3ca53db..899e115966887 100644 --- a/test/Transforms/TailCallElim/dont_reorder_load.ll +++ b/test/Transforms/TailCallElim/dont_reorder_load.ll @@ -16,7 +16,7 @@ entry: br i1 %tmp2, label %if, label %else if: ; preds = %entry - unwind + ret i32 37 else: ; preds = %entry %tmp7 = add i32 %start_arg, 1 ; <i32> [#uses=1] diff --git a/test/Transforms/TailCallElim/reorder_load.ll b/test/Transforms/TailCallElim/reorder_load.ll index 7f8af7ea14765..7f5c36e4a207b 100644 --- a/test/Transforms/TailCallElim/reorder_load.ll +++ b/test/Transforms/TailCallElim/reorder_load.ll @@ -43,7 +43,7 @@ else: ; preds = %entry br i1 %nullcheck, label %unwind, label %recurse unwind: ; preds = %else - unwind + unreachable recurse: ; preds = %else %tmp7 = add i32 %start_arg, 1 ; <i32> [#uses=1] @@ -89,7 +89,7 @@ else: ; preds = %entry br i1 %nullcheck, label %unwind, label %recurse unwind: ; preds = %else - unwind + unreachable recurse: ; preds = %else %tmp7 = add i32 %start_arg, 1 ; <i32> [#uses=1] diff --git a/test/Transforms/TailCallElim/setjmp.ll b/test/Transforms/TailCallElim/setjmp.ll index 7b7fe568259e4..7ef9cb360f53c 100644 --- a/test/Transforms/TailCallElim/setjmp.ll +++ b/test/Transforms/TailCallElim/setjmp.ll @@ -1,10 +1,14 @@ ; RUN: opt < %s -tailcallelim -S | FileCheck %s -; Test that we don't tail call in a functions that calls setjmp. +; Test that we don't tail call in a functions that calls returns_twice +; functions. +declare void @bar() + +; CHECK: foo1 ; CHECK-NOT: tail call void @bar() -define void @foo(i32* %x) { +define void @foo1(i32* %x) { bb: %tmp75 = tail call i32 @setjmp(i32* %x) call void @bar() @@ -13,4 +17,13 @@ bb: declare i32 @setjmp(i32*) -declare void @bar() +; CHECK: foo2 +; CHECK-NOT: tail call void @bar() + +define void @foo2(i32* %x) { +bb: + %tmp75 = tail call i32 @zed2(i32* %x) + call void @bar() + ret void +} +declare i32 @zed2(i32*) returns_twice diff --git a/test/Transforms/TailDup/2003-06-24-Simpleloop.ll b/test/Transforms/TailDup/2003-06-24-Simpleloop.ll deleted file mode 100644 index d7e45af5eceb7..0000000000000 --- a/test/Transforms/TailDup/2003-06-24-Simpleloop.ll +++ /dev/null @@ -1,15 +0,0 @@ -; RUN: opt < %s -tailduplicate -disable-output - -define void @motion_result7() { -entry: - br label %endif -endif: ; preds = %no_exit, %entry - %i.1 = phi i32 [ %inc, %no_exit ], [ 0, %entry ] ; <i32> [#uses=1] - %inc = add i32 %i.1, 1 ; <i32> [#uses=1] - br i1 false, label %no_exit, label %UnifiedExitNode -no_exit: ; preds = %endif - br i1 false, label %UnifiedExitNode, label %endif -UnifiedExitNode: ; preds = %no_exit, %endif - ret void -} - diff --git a/test/Transforms/TailDup/2003-07-22-InfiniteLoop.ll b/test/Transforms/TailDup/2003-07-22-InfiniteLoop.ll deleted file mode 100644 index 90f49909e5c10..0000000000000 --- a/test/Transforms/TailDup/2003-07-22-InfiniteLoop.ll +++ /dev/null @@ -1,11 +0,0 @@ -; RUN: opt < %s -tailduplicate -disable-output - -define i32 @sum() { -entry: - br label %loopentry -loopentry: ; preds = %loopentry, %entry - %i.0 = phi i32 [ 1, %entry ], [ %tmp.3, %loopentry ] ; <i32> [#uses=1] - %tmp.3 = add i32 %i.0, 1 ; <i32> [#uses=1] - br label %loopentry -} - diff --git a/test/Transforms/TailDup/2003-08-23-InvalidatedPointers.ll b/test/Transforms/TailDup/2003-08-23-InvalidatedPointers.ll deleted file mode 100644 index efe9eaed7ebdd..0000000000000 --- a/test/Transforms/TailDup/2003-08-23-InvalidatedPointers.ll +++ /dev/null @@ -1,29 +0,0 @@ -; RUN: opt < %s -tailduplicate -disable-output - -define i32 @sell_haggle() { -entry: - br i1 false, label %then.5, label %UnifiedExitNode -then.5: ; preds = %entry - br i1 false, label %loopentry.1.preheader, label %else.1 -else.1: ; preds = %then.5 - br label %loopentry.1.preheader -loopentry.1.preheader: ; preds = %else.1, %then.5 - %final_ask.0 = phi i32 [ 0, %else.1 ], [ 0, %then.5 ] ; <i32> [#uses=2] - br label %loopentry.1 -loopentry.1: ; preds = %endif.17, %loopentry.1.preheader - switch i32 0, label %UnifiedExitNode [ - i32 2, label %UnifiedExitNode - i32 1, label %endif.16 - ] -endif.16: ; preds = %loopentry.1 - br i1 false, label %then.17, label %UnifiedExitNode -then.17: ; preds = %endif.16 - br i1 false, label %then.18, label %endif.17 -then.18: ; preds = %then.17 - br i1 false, label %endif.17, label %UnifiedExitNode -endif.17: ; preds = %then.18, %then.17 - %cur_ask.3 = phi i32 [ %final_ask.0, %then.17 ], [ %final_ask.0, %then.18 ] ; <i32> [#uses=0] - br i1 false, label %loopentry.1, label %UnifiedExitNode -UnifiedExitNode: ; preds = %endif.17, %then.18, %endif.16, %loopentry.1, %loopentry.1, %entry - ret i32 0 -} diff --git a/test/Transforms/TailDup/2003-08-31-UnreachableBlocks.ll b/test/Transforms/TailDup/2003-08-31-UnreachableBlocks.ll deleted file mode 100644 index dc6492353b7ed..0000000000000 --- a/test/Transforms/TailDup/2003-08-31-UnreachableBlocks.ll +++ /dev/null @@ -1,17 +0,0 @@ -; RUN: opt < %s -tailduplicate -disable-output - -define i32 @foo() { -entry: - br label %return.i -after_ret.i: ; No predecessors! - br label %return.i -return.i: ; preds = %after_ret.i, %entry - %tmp.3 = ptrtoint i32* null to i32 ; <i32> [#uses=1] - br label %return.i1 -after_ret.i1: ; No predecessors! - br label %return.i1 -return.i1: ; preds = %after_ret.i1, %return.i - %tmp.8 = sub i32 %tmp.3, 0 ; <i32> [#uses=0] - ret i32 0 -} - diff --git a/test/Transforms/TailDup/2004-04-01-DemoteRegToStack.ll b/test/Transforms/TailDup/2004-04-01-DemoteRegToStack.ll deleted file mode 100644 index c1e5f738a7d98..0000000000000 --- a/test/Transforms/TailDup/2004-04-01-DemoteRegToStack.ll +++ /dev/null @@ -1,20 +0,0 @@ -; RUN: opt < %s -tailduplicate -disable-output - -define void @interpret() { -entry: - br label %retry -retry: ; preds = %endif.4, %entry - %tmp.8 = call i32 @interp( ) ; <i32> [#uses=3] - switch i32 0, label %endif.4 [ - i32 -25, label %return - i32 -16, label %return - ] -endif.4: ; preds = %retry - br i1 false, label %return, label %retry -return: ; preds = %endif.4, %retry, %retry - %result.0 = phi i32 [ %tmp.8, %retry ], [ %tmp.8, %retry ], [ %tmp.8, %endif.4 ] ; <i32> [#uses=0] - ret void -} - -declare i32 @interp() - diff --git a/test/Transforms/TailDup/2008-05-13-InfiniteLoop.ll b/test/Transforms/TailDup/2008-05-13-InfiniteLoop.ll deleted file mode 100644 index 3e4f0b78748c4..0000000000000 --- a/test/Transforms/TailDup/2008-05-13-InfiniteLoop.ll +++ /dev/null @@ -1,26 +0,0 @@ -; RUN: opt < %s -tailduplicate | llc -; PR2323 - -define i32 @func_27(i32 %p_28) nounwind { -entry: - %tmp125 = trunc i32 %p_28 to i8 ; <i8> [#uses=1] - %tmp5.i = icmp eq i8 %tmp125, 0 ; <i1> [#uses=1] - br i1 %tmp5.i, label %bb8.i, label %bb.i - -bb.i: ; preds = %entry - br label %bb39.i - -bb8.i: ; preds = %entry - br label %bb11.i - -bb11.i: ; preds = %bb39.i, %bb8.i - %tmp126 = trunc i32 %p_28 to i8 ; <i8> [#uses=1] - br label %bb39.i - -bb39.i: ; preds = %bb11.i, %bb.i - %tmp127 = trunc i32 %p_28 to i8 ; <i8> [#uses=1] - br label %bb11.i - -func_29.exit: ; No predecessors! - ret i32 undef -} diff --git a/test/Transforms/TailDup/2009-07-31-phicrash.ll b/test/Transforms/TailDup/2009-07-31-phicrash.ll deleted file mode 100644 index ad1a0404761a6..0000000000000 --- a/test/Transforms/TailDup/2009-07-31-phicrash.ll +++ /dev/null @@ -1,14 +0,0 @@ -; RUN: opt < %s -tailduplicate -disable-output -; PR4662 - -define void @a() { -BB: - br label %BB6 - -BB6: - %tmp9 = phi i64 [ 0, %BB ], [ 5, %BB34 ] - br label %BB34 - -BB34: - br label %BB6 -} diff --git a/test/Transforms/TailDup/MergeTest.ll b/test/Transforms/TailDup/MergeTest.ll deleted file mode 100644 index 2224283d8eec6..0000000000000 --- a/test/Transforms/TailDup/MergeTest.ll +++ /dev/null @@ -1,27 +0,0 @@ -; RUN: opt < %s -tailduplicate -taildup-threshold=2 -S | grep add | not grep uses=1 - -define i32 @test1(i1 %C, i32 %A, i32* %P) { -entry: - br i1 %C, label %L1, label %L2 -L1: ; preds = %entry - store i32 1, i32* %P - br label %L2 -L2: ; preds = %L1, %entry - %X = add i32 %A, 17 ; <i32> [#uses=1] - ret i32 %X -} - -define i32 @test2(i1 %C, i32 %A, i32* %P) { -entry: - br i1 %C, label %L1, label %L2 -L1: ; preds = %entry - store i32 1, i32* %P - br label %L3 -L2: ; preds = %entry - store i32 7, i32* %P - br label %L3 -L3: ; preds = %L2, %L1 - %X = add i32 %A, 17 ; <i32> [#uses=1] - ret i32 %X -} - diff --git a/test/Transforms/TailDup/PHIUpdateTest.ll b/test/Transforms/TailDup/PHIUpdateTest.ll deleted file mode 100644 index 38d8ebfcce565..0000000000000 --- a/test/Transforms/TailDup/PHIUpdateTest.ll +++ /dev/null @@ -1,16 +0,0 @@ -; This test checks to make sure phi nodes are updated properly -; -; RUN: opt < %s -tailduplicate -disable-output - -define i32 @test(i1 %c, i32 %X, i32 %Y) { - br label %L -L: ; preds = %F, %0 - %A = add i32 %X, %Y ; <i32> [#uses=1] - br i1 %c, label %T, label %F -F: ; preds = %L - br i1 %c, label %L, label %T -T: ; preds = %F, %L - %V = phi i32 [ %A, %L ], [ 0, %F ] ; <i32> [#uses=1] - ret i32 %V -} - diff --git a/test/Transforms/TailDup/X86/if-tail-dup.ll b/test/Transforms/TailDup/X86/if-tail-dup.ll deleted file mode 100644 index 2e4f5be38d1d2..0000000000000 --- a/test/Transforms/TailDup/X86/if-tail-dup.ll +++ /dev/null @@ -1,49 +0,0 @@ -; RUN: opt < %s -tailduplicate | \ -; RUN: llc -march=x86 -o %t -; RUN: grep {\\\<je\\\>} %t -; RUN: not grep jmp %t -; END. -; This should have no unconditional jumps in it. The C source is: - -;void foo(int c, int* P) { -; if (c & 1) P[0] = 1; -; if (c & 2) P[1] = 1; -; if (c & 4) P[2] = 1; -; if (c & 8) P[3] = 1; -;} - -define void @foo(i32 %c, i32* %P) { -entry: - %tmp1 = and i32 %c, 1 ; <i32> [#uses=1] - %tmp1.upgrd.1 = icmp eq i32 %tmp1, 0 ; <i1> [#uses=1] - br i1 %tmp1.upgrd.1, label %cond_next, label %cond_true -cond_true: ; preds = %entry - store i32 1, i32* %P - br label %cond_next -cond_next: ; preds = %cond_true, %entry - %tmp5 = and i32 %c, 2 ; <i32> [#uses=1] - %tmp5.upgrd.2 = icmp eq i32 %tmp5, 0 ; <i1> [#uses=1] - br i1 %tmp5.upgrd.2, label %cond_next10, label %cond_true6 -cond_true6: ; preds = %cond_next - %tmp8 = getelementptr i32* %P, i32 1 ; <i32*> [#uses=1] - store i32 1, i32* %tmp8 - br label %cond_next10 -cond_next10: ; preds = %cond_true6, %cond_next - %tmp13 = and i32 %c, 4 ; <i32> [#uses=1] - %tmp13.upgrd.3 = icmp eq i32 %tmp13, 0 ; <i1> [#uses=1] - br i1 %tmp13.upgrd.3, label %cond_next18, label %cond_true14 -cond_true14: ; preds = %cond_next10 - %tmp16 = getelementptr i32* %P, i32 2 ; <i32*> [#uses=1] - store i32 1, i32* %tmp16 - br label %cond_next18 -cond_next18: ; preds = %cond_true14, %cond_next10 - %tmp21 = and i32 %c, 8 ; <i32> [#uses=1] - %tmp21.upgrd.4 = icmp eq i32 %tmp21, 0 ; <i1> [#uses=1] - br i1 %tmp21.upgrd.4, label %return, label %cond_true22 -cond_true22: ; preds = %cond_next18 - %tmp24 = getelementptr i32* %P, i32 3 ; <i32*> [#uses=1] - store i32 1, i32* %tmp24 - ret void -return: ; preds = %cond_next18 - ret void -} diff --git a/test/Transforms/TailDup/basictest.ll b/test/Transforms/TailDup/basictest.ll deleted file mode 100644 index 94f5d87ad2bbc..0000000000000 --- a/test/Transforms/TailDup/basictest.ll +++ /dev/null @@ -1,20 +0,0 @@ -; RUN: opt < %s -tailduplicate -disable-output - -declare void @__main() - -define i32 @main() { -entry: - call void @__main( ) - br label %loopentry -loopentry: ; preds = %no_exit, %entry - %i.0 = phi i32 [ %inc, %no_exit ], [ 0, %entry ] ; <i32> [#uses=3] - %tmp.1 = icmp sle i32 %i.0, 99 ; <i1> [#uses=1] - br i1 %tmp.1, label %no_exit, label %return -no_exit: ; preds = %loopentry - %tmp.51 = call i32 @main( ) ; <i32> [#uses=0] - %inc = add i32 %i.0, 1 ; <i32> [#uses=1] - br label %loopentry -return: ; preds = %loopentry - ret i32 %i.0 -} - diff --git a/test/Transforms/TailDup/basictest2.ll b/test/Transforms/TailDup/basictest2.ll deleted file mode 100644 index 81a996adfee23..0000000000000 --- a/test/Transforms/TailDup/basictest2.ll +++ /dev/null @@ -1,15 +0,0 @@ -; RUN: opt < %s -tailduplicate -disable-output - -define void @ab() { -entry: - br label %loopentry.5 -loopentry.5: ; preds = %no_exit.5, %entry - %poscnt.1 = phi i64 [ 0, %entry ], [ %tmp.289, %no_exit.5 ] ; <i64> [#uses=1] - %tmp.289 = ashr i64 %poscnt.1, 1 ; <i64> [#uses=1] - br i1 false, label %no_exit.5, label %loopexit.5 -no_exit.5: ; preds = %loopentry.5 - br label %loopentry.5 -loopexit.5: ; preds = %loopentry.5 - ret void -} - |