From 1d95725d60ca1c77a202a78a62f552ff8a1b116a Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sat, 7 Nov 2009 17:59:32 +0000 Subject: [PATCH] Revert r86359, it is breaking the self host on the llvm-gcc-i386-darwin9 build bot. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@86391 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Scalar/DeadStoreElimination.cpp | 179 ++++++------------ .../DeadStoreElimination/lifetime.ll | 19 -- .../DeadStoreElimination/memintrinsics.ll | 47 ----- 3 files changed, 62 insertions(+), 183 deletions(-) diff --git a/lib/Transforms/Scalar/DeadStoreElimination.cpp b/lib/Transforms/Scalar/DeadStoreElimination.cpp index f8a7d9f0274..90436f40661 100644 --- a/lib/Transforms/Scalar/DeadStoreElimination.cpp +++ b/lib/Transforms/Scalar/DeadStoreElimination.cpp @@ -78,84 +78,19 @@ static RegisterPass X("dse", "Dead Store Elimination"); FunctionPass *llvm::createDeadStoreEliminationPass() { return new DSE(); } -/// doesClobberMemory - Does this instruction clobber (write without reading) -/// some memory? -static bool doesClobberMemory(Instruction *I) { - if (isa(I)) - return true; - if (IntrinsicInst *II = dyn_cast(I)) { - switch (II->getIntrinsicID()) { - default: return false; - case Intrinsic::memset: case Intrinsic::memmove: case Intrinsic::memcpy: - case Intrinsic::lifetime_end: return true; - } - } - return false; -} - -/// isElidable - If the memory this instruction and the memory it writes to is -/// unused, may we delete this instrtction? -static bool isElidable(Instruction *I) { - assert(doesClobberMemory(I)); - if (IntrinsicInst *II = dyn_cast(I)) - return II->getIntrinsicID() != Intrinsic::lifetime_end; - if (StoreInst *SI = dyn_cast(I)) - return !SI->isVolatile(); - return true; -} - -/// getPointerOperand - Return the pointer that is being clobbered. -static Value *getPointerOperand(Instruction *I) { - assert(doesClobberMemory(I)); - if (StoreInst *SI = dyn_cast(I)) - return SI->getPointerOperand(); - if (MemIntrinsic *MI = dyn_cast(I)) - return MI->getOperand(1); - assert(cast(I)->getIntrinsicID() == Intrinsic::lifetime_end); - return cast(I)->getOperand(2); -} - -/// getStoreSize - Return the length in bytes of the write by the clobbering -/// instruction. If variable or unknown, returns -1. -static unsigned getStoreSize(Instruction *I, const TargetData *TD = 0) { - assert(doesClobberMemory(I)); - if (StoreInst *SI = dyn_cast(I)) { - if (!TD) return -1u; - const PointerType *PTy = - cast(SI->getPointerOperand()->getType()); - return TD->getTypeStoreSize(PTy); - } - - Value *Len; - if (MemIntrinsic *MI = dyn_cast(I)) { - Len = MI->getLength(); - } else { - assert(cast(I)->getIntrinsicID() == - Intrinsic::lifetime_end); - Len = cast(I)->getOperand(0); - } - if (ConstantInt *LenCI = dyn_cast(Len)) - if (!LenCI->isAllOnesValue()) - return LenCI->getZExtValue(); - return -1u; -} - -/// isStoreAtLeastAsWideAs - Return true if the size of the store in I1 is -/// greater than or equal to the store in I2. This returns false if we don't -/// know. +/// isValueAtLeastAsBigAs - Return true if V1 is greater than or equal to the +/// stored size of V2. This returns false if we don't know. /// -static bool isStoreAtLeastAsWideAs(Instruction *I1, Instruction *I2, - const TargetData *TD) { - const Type *I1Ty = getPointerOperand(I1)->getType(); - const Type *I2Ty = getPointerOperand(I2)->getType(); +static bool isValueAtLeastAsBigAs(Value *V1, Value *V2, const TargetData *TD) { + const Type *V1Ty = V1->getType(), *V2Ty = V2->getType(); // Exactly the same type, must have exactly the same size. - if (I1Ty == I2Ty) return true; + if (V1Ty == V2Ty) return true; - int I1Size = getStoreSize(I1, TD); - int I2Size = getStoreSize(I2, TD); + // If we don't have target data, we don't know. + if (TD == 0) return false; - return I1Size != -1 && I2Size != -1 && I1Size >= I2Size; + return TD->getTypeStoreSize(V1Ty) >= TD->getTypeStoreSize(V2Ty); } bool DSE::runOnBasicBlock(BasicBlock &BB) { @@ -169,9 +104,14 @@ bool DSE::runOnBasicBlock(BasicBlock &BB) { Instruction *Inst = BBI++; // If we find a store or a free, get its memory dependence. - if (!doesClobberMemory(Inst) && !isFreeCall(Inst)) + if (!isa(Inst) && !isFreeCall(Inst)) continue; + // Don't molest volatile stores or do queries that will return "clobber". + if (StoreInst *SI = dyn_cast(Inst)) + if (SI->isVolatile()) + continue; + MemDepResult InstDep = MD.getDependency(Inst); // Ignore non-local stores. @@ -184,16 +124,16 @@ bool DSE::runOnBasicBlock(BasicBlock &BB) { continue; } + StoreInst *SI = cast(Inst); + // If not a definite must-alias dependency, ignore it. if (!InstDep.isDef()) continue; // If this is a store-store dependence, then the previous store is dead so // long as this store is at least as big as it. - if (doesClobberMemory(InstDep.getInst())) { - Instruction *DepStore = InstDep.getInst(); - if (isStoreAtLeastAsWideAs(Inst, DepStore, TD) && - isElidable(DepStore)){ + if (StoreInst *DepStore = dyn_cast(InstDep.getInst())) + if (isValueAtLeastAsBigAs(SI->getOperand(0), DepStore->getOperand(0),TD)){ // Delete the store and now-dead instructions that feed it. DeleteDeadInstruction(DepStore); NumFastStores++; @@ -206,31 +146,25 @@ bool DSE::runOnBasicBlock(BasicBlock &BB) { --BBI; continue; } - } - - if (!isElidable(Inst)) - continue; // If we're storing the same value back to a pointer that we just // loaded from, then the store can be removed. - if (StoreInst *SI = dyn_cast(Inst)) { - if (LoadInst *DepLoad = dyn_cast(InstDep.getInst())) { - if (SI->getPointerOperand() == DepLoad->getPointerOperand() && - SI->getOperand(0) == DepLoad) { - // DeleteDeadInstruction can delete the current instruction. Save BBI - // in case we need it. - WeakVH NextInst(BBI); - - DeleteDeadInstruction(SI); - - if (NextInst == 0) // Next instruction deleted. - BBI = BB.begin(); - else if (BBI != BB.begin()) // Revisit this instruction if possible. - --BBI; - NumFastStores++; - MadeChange = true; - continue; - } + if (LoadInst *DepLoad = dyn_cast(InstDep.getInst())) { + if (SI->getPointerOperand() == DepLoad->getPointerOperand() && + SI->getOperand(0) == DepLoad) { + // DeleteDeadInstruction can delete the current instruction. Save BBI + // in case we need it. + WeakVH NextInst(BBI); + + DeleteDeadInstruction(SI); + + if (NextInst == 0) // Next instruction deleted. + BBI = BB.begin(); + else if (BBI != BB.begin()) // Revisit this instruction if possible. + --BBI; + NumFastStores++; + MadeChange = true; + continue; } } @@ -242,7 +176,7 @@ bool DSE::runOnBasicBlock(BasicBlock &BB) { // in case we need it. WeakVH NextInst(BBI); - DeleteDeadInstruction(Inst); + DeleteDeadInstruction(SI); if (NextInst == 0) // Next instruction deleted. BBI = BB.begin(); @@ -268,11 +202,11 @@ bool DSE::runOnBasicBlock(BasicBlock &BB) { bool DSE::handleFreeWithNonTrivialDependency(Instruction *F, MemDepResult Dep) { AliasAnalysis &AA = getAnalysis(); - Instruction *Dependency = Dep.getInst(); - if (!Dependency || !doesClobberMemory(Dependency) || !isElidable(Dependency)) + StoreInst *Dependency = dyn_cast_or_null(Dep.getInst()); + if (!Dependency || Dependency->isVolatile()) return false; - Value *DepPointer = getPointerOperand(Dependency)->getUnderlyingObject(); + Value *DepPointer = Dependency->getPointerOperand()->getUnderlyingObject(); // Check for aliasing. if (AA.alias(F->getOperand(1), 1, DepPointer, 1) != @@ -317,28 +251,39 @@ bool DSE::handleEndBlock(BasicBlock &BB) { --BBI; // If we find a store whose pointer is dead. - if (doesClobberMemory(BBI)) { - if (isElidable(BBI)) { + if (StoreInst* S = dyn_cast(BBI)) { + if (!S->isVolatile()) { // See through pointer-to-pointer bitcasts - Value *pointerOperand = getPointerOperand(BBI)->getUnderlyingObject(); + Value* pointerOperand = S->getPointerOperand()->getUnderlyingObject(); // Alloca'd pointers or byval arguments (which are functionally like // alloca's) are valid candidates for removal. if (deadPointers.count(pointerOperand)) { // DCE instructions only used to calculate that store. - Instruction *Dead = BBI; BBI++; - DeleteDeadInstruction(Dead, &deadPointers); + DeleteDeadInstruction(S, &deadPointers); NumFastStores++; MadeChange = true; - continue; } } - // Because a memcpy or memmove is also a load, we can't skip it if we - // didn't remove it. - if (!isa(BBI)) + continue; + } + + // We can also remove memcpy's to local variables at the end of a function. + if (MemCpyInst *M = dyn_cast(BBI)) { + Value *dest = M->getDest()->getUnderlyingObject(); + + if (deadPointers.count(dest)) { + BBI++; + DeleteDeadInstruction(M, &deadPointers); + NumFastOther++; + MadeChange = true; continue; + } + + // Because a memcpy is also a load, we can't skip it if we didn't remove + // it. } Value* killPointer = 0; @@ -359,11 +304,11 @@ bool DSE::handleEndBlock(BasicBlock &BB) { killPointer = L->getPointerOperand(); } else if (VAArgInst* V = dyn_cast(BBI)) { killPointer = V->getOperand(0); - } else if (isa(BBI) && - isa(cast(BBI)->getLength())) { - killPointer = cast(BBI)->getSource(); + } else if (isa(BBI) && + isa(cast(BBI)->getLength())) { + killPointer = cast(BBI)->getSource(); killPointerSize = cast( - cast(BBI)->getLength())->getZExtValue(); + cast(BBI)->getLength())->getZExtValue(); } else if (AllocaInst* A = dyn_cast(BBI)) { deadPointers.erase(A); diff --git a/test/Transforms/DeadStoreElimination/lifetime.ll b/test/Transforms/DeadStoreElimination/lifetime.ll index b2da790db27..e69de29bb2d 100644 --- a/test/Transforms/DeadStoreElimination/lifetime.ll +++ b/test/Transforms/DeadStoreElimination/lifetime.ll @@ -1,19 +0,0 @@ -; RUN: opt -S -dse < %s | FileCheck %s - -declare void @llvm.lifetime.end(i64, i8*) -declare void @llvm.memset.i8(i8*, i8, i8, i32) - -define void @test1() { -; CHECK: @test1 - %A = alloca i8 - - store i8 0, i8* %A ;; Written to by memset - call void @llvm.lifetime.end(i64 1, i8* %A) -; CHECK: lifetime.end - - call void @llvm.memset.i8(i8* %A, i8 0, i8 -1, i32 0) -; CHECK-NOT: memset - - ret void -; CHECK: ret void -} diff --git a/test/Transforms/DeadStoreElimination/memintrinsics.ll b/test/Transforms/DeadStoreElimination/memintrinsics.ll index e31e9fa3ca6..e69de29bb2d 100644 --- a/test/Transforms/DeadStoreElimination/memintrinsics.ll +++ b/test/Transforms/DeadStoreElimination/memintrinsics.ll @@ -1,47 +0,0 @@ -; RUN: opt -S -dse < %s | FileCheck %s - -declare void @llvm.memcpy.i8(i8*, i8*, i8, i32) -declare void @llvm.memmove.i8(i8*, i8*, i8, i32) -declare void @llvm.memset.i8(i8*, i8, i8, i32) - -define void @test1() { -; CHECK: @test1 - %A = alloca i8 - %B = alloca i8 - - store i8 0, i8* %A ;; Written to by memcpy -; CHECK-NOT: store - - call void @llvm.memcpy.i8(i8* %A, i8* %B, i8 -1, i32 0) - - ret void -; CHECK: ret void -} - -define void @test2() { -; CHECK: @test2 - %A = alloca i8 - %B = alloca i8 - - store i8 0, i8* %A ;; Written to by memmove -; CHECK-NOT: store - - call void @llvm.memmove.i8(i8* %A, i8* %B, i8 -1, i32 0) - - ret void -; CHECK: ret void -} - -define void @test3() { -; CHECK: @test3 - %A = alloca i8 - %B = alloca i8 - - store i8 0, i8* %A ;; Written to by memset -; CHECK-NOT: store - - call void @llvm.memset.i8(i8* %A, i8 0, i8 -1, i32 0) - - ret void -; CHECK: ret void -}