Index: include/llvm/Transforms/Scalar/GVN.h =================================================================== --- include/llvm/Transforms/Scalar/GVN.h +++ include/llvm/Transforms/Scalar/GVN.h @@ -27,6 +27,7 @@ #include "llvm/IR/Dominators.h" #include "llvm/IR/InstrTypes.h" #include "llvm/IR/PassManager.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Compiler.h" #include @@ -180,7 +181,12 @@ // Map the block to reversed postorder traversal number. It is used to // find back edge easily. - DenseMap BlockRPONumber; + DenseMap, uint32_t> BlockRPONumber; + + // This is set 'true' initially and also when new blocks have been added to + // the function being analyzed. This boolean is used to control the updating + // of BlockRPONumber prior to accessing the contents of BlockRPONumber. + bool InvalidBlockRPONumbers = true; using LoadDepVect = SmallVector; using AvailValInBlkVect = SmallVector; Index: lib/Transforms/Scalar/GVN.cpp =================================================================== --- lib/Transforms/Scalar/GVN.cpp +++ lib/Transforms/Scalar/GVN.cpp @@ -1328,12 +1328,14 @@ } // If this load follows a GEP, see if we can PRE the indices before analyzing. - if (GetElementPtrInst *GEP = dyn_cast(LI->getOperand(0))) { - for (GetElementPtrInst::op_iterator OI = GEP->idx_begin(), - OE = GEP->idx_end(); - OI != OE; ++OI) - if (Instruction *I = dyn_cast(OI->get())) - performScalarPRE(I); + if (EnablePRE) { + if (auto GEP = dyn_cast(LI->getOperand(0))) { + for (GetElementPtrInst::op_iterator OI = GEP->idx_begin(), + OE = GEP->idx_end(); + OI != OE; ++OI) + if (Instruction *I = dyn_cast(OI->get())) + performScalarPRE(I); + } } // Step 2: Analyze the availability of the load @@ -1645,10 +1647,12 @@ } void GVN::assignBlockRPONumber(Function &F) { + BlockRPONumber.clear(); uint32_t NextBlockNumber = 1; ReversePostOrderTraversal RPOT(&F); for (BasicBlock *BB : RPOT) BlockRPONumber[BB] = NextBlockNumber++; + InvalidBlockRPONumbers = false; } // Tries to replace instruction with const, using information from @@ -1992,6 +1996,7 @@ ICF = &ImplicitCFT; VN.setMemDep(MD); ORE = RunORE; + InvalidBlockRPONumbers = true; bool Changed = false; bool ShouldContinue = true; @@ -2021,7 +2026,6 @@ // Fabricate val-num for dead-code in order to suppress assertion in // performPRE(). assignValNumForDeadCode(); - assignBlockRPONumber(F); bool PREChanged = true; while (PREChanged) { PREChanged = performPRE(F); @@ -2143,6 +2147,7 @@ } bool GVN::performScalarPRE(Instruction *CurInst) { + assert(EnablePRE && "GVN: Calling performScalarPRE with -enable-pre=false."); if (isa(CurInst) || CurInst->isTerminator() || isa(CurInst) || CurInst->getType()->isVoidTy() || CurInst->mayReadFromMemory() || CurInst->mayHaveSideEffects() || @@ -2184,6 +2189,10 @@ BasicBlock *PREPred = nullptr; BasicBlock *CurrentBlock = CurInst->getParent(); + // Update the RPO numbers for this function. + if (InvalidBlockRPONumbers) + assignBlockRPONumber(*CurrentBlock->getParent()); + SmallVector, 8> predMap; for (BasicBlock *P : predecessors(CurrentBlock)) { // We're not interested in PRE where blocks with predecessors that are @@ -2342,6 +2351,7 @@ SplitCriticalEdge(Pred, Succ, CriticalEdgeSplittingOptions(DT)); if (MD) MD->invalidateCachedPredecessors(); + InvalidBlockRPONumbers = true; return BB; } @@ -2356,6 +2366,7 @@ CriticalEdgeSplittingOptions(DT)); } while (!toSplit.empty()); if (MD) MD->invalidateCachedPredecessors(); + InvalidBlockRPONumbers = true; return true; } Index: test/Transforms/GVN/nonescaping-malloc.ll =================================================================== --- test/Transforms/GVN/nonescaping-malloc.ll +++ test/Transforms/GVN/nonescaping-malloc.ll @@ -2,6 +2,10 @@ ; RUN: opt < %s -basicaa -gvn -stats -disable-output 2>&1 | FileCheck %s ; rdar://7363102 +; Sanity check that GVN::performScalarPRE is not called with +; enable-pre=false (asserts) +; RUN: opt < %s -basicaa -gvn -enable-pre=false -disable-output 2>&1 + ; CHECK: Number of loads deleted ; GVN should be able to eliminate load %tmp22.i, because it is redundant with