diff options
author | Evgeniy Stepanov <eugeni.stepanov@gmail.com> | 2016-06-16 22:34:04 +0000 |
---|---|---|
committer | Evgeniy Stepanov <eugeni.stepanov@gmail.com> | 2016-06-16 22:34:04 +0000 |
commit | 45fa0fd758dd4eb20cca6f36d1b43dd1274c5ad7 (patch) | |
tree | f2a80a81f3e97a96b8c4e627e49f35b047603464 /llvm/lib/CodeGen/SafeStack.cpp | |
parent | 72d961a1da712ba0f50a8092ac68cde76f44cc5d (diff) | |
download | bcm5719-llvm-45fa0fd758dd4eb20cca6f36d1b43dd1274c5ad7.tar.gz bcm5719-llvm-45fa0fd758dd4eb20cca6f36d1b43dd1274c5ad7.zip |
[safestack] Sink unsafe address computation to each use.
This is a fix for PR27844.
When replacing uses of unsafe allocas, emit the new location
immediately after each use. Without this, the pointer stays live from
the function entry to the last use, while it's usually cheaper to
recalculate.
llvm-svn: 272969
Diffstat (limited to 'llvm/lib/CodeGen/SafeStack.cpp')
-rw-r--r-- | llvm/lib/CodeGen/SafeStack.cpp | 39 |
1 files changed, 31 insertions, 8 deletions
diff --git a/llvm/lib/CodeGen/SafeStack.cpp b/llvm/lib/CodeGen/SafeStack.cpp index 28f5ed861ab..457acb1503c 100644 --- a/llvm/lib/CodeGen/SafeStack.cpp +++ b/llvm/lib/CodeGen/SafeStack.cpp @@ -606,16 +606,39 @@ Value *SafeStack::moveStaticAllocasToUnsafeStack( StaticOffset += Size; StaticOffset = alignTo(StaticOffset, Align); - Value *Off = IRB.CreateGEP(BasePointer, // BasePointer is i8* - ConstantInt::get(Int32Ty, -StaticOffset)); - Value *NewAI = IRB.CreateBitCast(Off, AI->getType(), AI->getName()); - if (AI->hasName() && isa<Instruction>(NewAI)) - cast<Instruction>(NewAI)->takeName(AI); - - // Replace alloc with the new location. replaceDbgDeclareForAlloca(AI, BasePointer, DIB, /*Deref=*/true, -StaticOffset); replaceDbgValueForAlloca(AI, BasePointer, DIB, -StaticOffset); - AI->replaceAllUsesWith(NewAI); + + // Replace uses of the alloca with the new location. + // Insert address calculation close to each use to work around PR27844. + std::string Name = std::string(AI->getName()) + ".unsafe"; + while (!AI->use_empty()) { + Use &U = *AI->use_begin(); + Instruction *User = cast<Instruction>(U.getUser()); + + Instruction *InsertBefore; + if (auto *PHI = dyn_cast<PHINode>(User)) + InsertBefore = PHI->getIncomingBlock(U)->getTerminator(); + else + InsertBefore = User; + + IRBuilder<> IRBUser(InsertBefore); + Value *Off = IRBUser.CreateGEP(BasePointer, // BasePointer is i8* + ConstantInt::get(Int32Ty, -StaticOffset)); + Value *Replacement = IRBUser.CreateBitCast(Off, AI->getType(), Name); + + if (auto *PHI = dyn_cast<PHINode>(User)) { + // PHI nodes may have multiple incoming edges from the same BB (why??), + // all must be updated at once with the same incoming value. + auto *BB = PHI->getIncomingBlock(U); + for (unsigned I = 0; I < PHI->getNumIncomingValues(); ++I) + if (PHI->getIncomingBlock(I) == BB) + PHI->setIncomingValue(I, Replacement); + } else { + U.set(Replacement); + } + } + AI->eraseFromParent(); } |