|
@@ -425,14 +425,17 @@ static bool rewriteSingleStoreAlloca(AllocaInst *AI, AllocaInfo &Info,
|
|
|
/// using the Alloca.
|
|
|
///
|
|
|
/// If we cannot promote this alloca (because it is read before it is written),
|
|
|
-/// return true. This is necessary in cases where, due to control flow, the
|
|
|
-/// alloca is potentially undefined on some control flow paths. e.g. code like
|
|
|
-/// this is potentially correct:
|
|
|
-///
|
|
|
-/// for (...) { if (c) { A = undef; undef = B; } }
|
|
|
-///
|
|
|
-/// ... so long as A is not used before undef is set.
|
|
|
-static void promoteSingleBlockAlloca(AllocaInst *AI, const AllocaInfo &Info,
|
|
|
+/// return false. This is necessary in cases where, due to control flow, the
|
|
|
+/// alloca is undefined only on some control flow paths. e.g. code like
|
|
|
+/// this is correct in LLVM IR:
|
|
|
+/// // A is an alloca with no stores so far
|
|
|
+/// for (...) {
|
|
|
+/// int t = *A;
|
|
|
+/// if (!first_iteration)
|
|
|
+/// use(t);
|
|
|
+/// *A = 42;
|
|
|
+/// }
|
|
|
+static bool promoteSingleBlockAlloca(AllocaInst *AI, const AllocaInfo &Info,
|
|
|
LargeBlockInfo &LBI,
|
|
|
AliasSetTracker *AST) {
|
|
|
// The trickiest case to handle is when we have large blocks. Because of this,
|
|
@@ -468,12 +471,19 @@ static void promoteSingleBlockAlloca(AllocaInst *AI, const AllocaInfo &Info,
|
|
|
static_cast<StoreInst *>(nullptr)),
|
|
|
less_first());
|
|
|
|
|
|
- if (I == StoresByIndex.begin())
|
|
|
- // If there is no store before this load, the load takes the undef value.
|
|
|
- LI->replaceAllUsesWith(UndefValue::get(LI->getType()));
|
|
|
- else
|
|
|
+ if (I == StoresByIndex.begin()) {
|
|
|
+ if (StoresByIndex.empty())
|
|
|
+ // If there are no stores, the load takes the undef value.
|
|
|
+ LI->replaceAllUsesWith(UndefValue::get(LI->getType()));
|
|
|
+ else
|
|
|
+ // There is no store before this load, bail out (load may be affected
|
|
|
+ // by the following stores - see main comment).
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ else {
|
|
|
// Otherwise, there was a store before this load, the load takes its value.
|
|
|
LI->replaceAllUsesWith(std::prev(I)->second->getOperand(0));
|
|
|
+ }
|
|
|
|
|
|
if (AST && LI->getType()->isPointerTy())
|
|
|
AST->deleteValue(LI);
|
|
@@ -506,6 +516,7 @@ static void promoteSingleBlockAlloca(AllocaInst *AI, const AllocaInfo &Info,
|
|
|
}
|
|
|
|
|
|
++NumLocalPromoted;
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
void PromoteMem2Reg::run() {
|
|
@@ -557,9 +568,8 @@ void PromoteMem2Reg::run() {
|
|
|
|
|
|
// If the alloca is only read and written in one basic block, just perform a
|
|
|
// linear sweep over the block to eliminate it.
|
|
|
- if (Info.OnlyUsedInOneBlock) {
|
|
|
- promoteSingleBlockAlloca(AI, Info, LBI, AST);
|
|
|
-
|
|
|
+ if (Info.OnlyUsedInOneBlock &&
|
|
|
+ promoteSingleBlockAlloca(AI, Info, LBI, AST)) {
|
|
|
// The alloca has been processed, move on.
|
|
|
RemoveFromAllocasList(AllocaNum);
|
|
|
continue;
|