summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen/SafeStack.cpp
diff options
context:
space:
mode:
authorEvgeniy Stepanov <eugeni.stepanov@gmail.com>2016-06-16 22:34:04 +0000
committerEvgeniy Stepanov <eugeni.stepanov@gmail.com>2016-06-16 22:34:04 +0000
commit45fa0fd758dd4eb20cca6f36d1b43dd1274c5ad7 (patch)
treef2a80a81f3e97a96b8c4e627e49f35b047603464 /llvm/lib/CodeGen/SafeStack.cpp
parent72d961a1da712ba0f50a8092ac68cde76f44cc5d (diff)
downloadbcm5719-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.cpp39
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();
}
OpenPOWER on IntegriCloud