From d99068d26db69f2cdaba0ad02a6bd92512f04b60 Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Thu, 26 May 2016 19:24:24 +0000 Subject: [MemCpyOpt] Don't perform callslot optimization across may-throw calls An exception could prevent a store from occurring but MemCpyOpt's callslot optimization would fire anyway, causing the store to occur. This fixes PR27849. llvm-svn: 270892 --- llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'llvm/lib/Transforms') diff --git a/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp b/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp index 8976742be40..3c421d2365d 100644 --- a/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp +++ b/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp @@ -496,7 +496,7 @@ static unsigned findCommonAlignment(const DataLayout &DL, const StoreInst *SI, // This method try to lift a store instruction before position P. // It will lift the store and its argument + that anything that -// lay alias with these. +// may alias with these. // The method returns true if it was successful. static bool moveUp(AliasAnalysis &AA, StoreInst *SI, Instruction *P) { // If the store alias this position, early bail out. @@ -675,6 +675,8 @@ bool MemCpyOpt::processStore(StoreInst *SI, BasicBlock::iterator &BBI) { if (C) { // Check that nothing touches the dest of the "copy" between // the call and the store. + Value *CpyDest = SI->getPointerOperand()->stripPointerCasts(); + bool CpyDestIsLocal = isa(CpyDest); AliasAnalysis &AA = getAnalysis().getAAResults(); MemoryLocation StoreLoc = MemoryLocation::get(SI); for (BasicBlock::iterator I = --SI->getIterator(), E = C->getIterator(); @@ -683,6 +685,12 @@ bool MemCpyOpt::processStore(StoreInst *SI, BasicBlock::iterator &BBI) { C = nullptr; break; } + // The store to dest may never happen if an exception can be thrown + // between the load and the store. + if (I->mayThrow() && !CpyDestIsLocal) { + C = nullptr; + break; + } } } @@ -815,6 +823,10 @@ bool MemCpyOpt::performCallSlotOptzn(Instruction *cpy, if (destSize < srcSize) return false; } else if (Argument *A = dyn_cast(cpyDest)) { + // The store to dest may never happen if the call can throw. + if (C->mayThrow()) + return false; + if (A->getDereferenceableBytes() < srcSize) { // If the destination is an sret parameter then only accesses that are // outside of the returned struct type can trap. -- cgit v1.2.3