diff options
Diffstat (limited to 'test/Transforms/DeadStoreElimination')
4 files changed, 223 insertions, 4 deletions
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 0000000..c5cc101 --- /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 0000000..22b8786 --- /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 0000000..2e84298 --- /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 5f143fc..ec2f157 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 } |