diff options
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp | 38 | 
1 files changed, 23 insertions, 15 deletions
diff --git a/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp b/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp index a87f8504bfb..828d6a173bb 100644 --- a/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp +++ b/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp @@ -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, @@ -467,10 +470,15 @@ static void promoteSingleBlockAlloca(AllocaInst *AI, const AllocaInfo &Info,                           std::make_pair(LoadIdx,                                          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())); +    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)); @@ -506,6 +514,7 @@ static void promoteSingleBlockAlloca(AllocaInst *AI, const AllocaInfo &Info,    }    ++NumLocalPromoted; +  return true;  }  void PromoteMem2Reg::run() { @@ -557,9 +566,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;  | 

