diff options
author | David Majnemer <david.majnemer@gmail.com> | 2016-05-26 19:24:24 +0000 |
---|---|---|
committer | David Majnemer <david.majnemer@gmail.com> | 2016-05-26 19:24:24 +0000 |
commit | d99068d26db69f2cdaba0ad02a6bd92512f04b60 (patch) | |
tree | ef3d5a5ff2988cdfe75cbc90f0cb34972aea0a9a /llvm/lib/Transforms | |
parent | 23c12ca9226c297771ba5fefa0f047e9e2450d7b (diff) | |
download | bcm5719-llvm-d99068d26db69f2cdaba0ad02a6bd92512f04b60.tar.gz bcm5719-llvm-d99068d26db69f2cdaba0ad02a6bd92512f04b60.zip |
[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
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r-- | llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp | 14 |
1 files changed, 13 insertions, 1 deletions
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<AllocaInst>(CpyDest); AliasAnalysis &AA = getAnalysis<AAResultsWrapperPass>().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<Argument>(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. |