From: Chris Lattner Date: Thu, 13 Sep 2007 18:00:31 +0000 (+0000) Subject: be tolerant of PHI nodes when rewriting heap SROA code. This is a step X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=a637a8b1e7ecc9ce06e0463b64be0721bf52255d;p=oota-llvm.git be tolerant of PHI nodes when rewriting heap SROA code. This is a step along the way of PR1639 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@41930 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Transforms/IPO/GlobalOpt.cpp b/lib/Transforms/IPO/GlobalOpt.cpp index 4c046c261c8..9240fb0e3d9 100644 --- a/lib/Transforms/IPO/GlobalOpt.cpp +++ b/lib/Transforms/IPO/GlobalOpt.cpp @@ -844,17 +844,23 @@ static bool ValueIsOnlyUsedLocallyOrStoredToOneGlobal(Instruction *V, static void ReplaceUsesOfMallocWithGlobal(Instruction *Alloc, GlobalVariable *GV) { while (!Alloc->use_empty()) { - Instruction *U = Alloc->use_back(); + Instruction *U = cast(*Alloc->use_begin()); + Instruction *InsertPt = U; if (StoreInst *SI = dyn_cast(U)) { // If this is the store of the allocation into the global, remove it. if (SI->getOperand(1) == GV) { SI->eraseFromParent(); continue; } + } else if (PHINode *PN = dyn_cast(U)) { + // Insert the load in the corresponding predecessor, not right before the + // PHI. + unsigned PredNo = Alloc->use_begin().getOperandNo()/2; + InsertPt = PN->getIncomingBlock(PredNo)->getTerminator(); } // Insert a load from the global, and use it instead of the malloc. - Value *NL = new LoadInst(GV, GV->getName()+".val", U); + Value *NL = new LoadInst(GV, GV->getName()+".val", InsertPt); U->replaceUsesOfWith(Alloc, NL); } } @@ -891,6 +897,20 @@ static bool GlobalLoadUsesSimpleEnoughForHeapSRA(GlobalVariable *GV) { return true; } +/// GetHeapSROALoad - Return the load for the specified field of the HeapSROA'd +/// value, lazily creating it on demand. +static Value *GetHeapSROALoad(LoadInst *Load, unsigned FieldNo, + const std::vector &FieldGlobals, + std::vector &InsertedLoadsForPtr) { + if (InsertedLoadsForPtr.size() <= FieldNo) + InsertedLoadsForPtr.resize(FieldNo+1); + if (InsertedLoadsForPtr[FieldNo] == 0) + InsertedLoadsForPtr[FieldNo] = new LoadInst(FieldGlobals[FieldNo], + Load->getName()+".f" + + utostr(FieldNo), Load); + return InsertedLoadsForPtr[FieldNo]; +} + /// RewriteHeapSROALoadUser - Given a load instruction and a value derived from /// the load, rewrite the derived value to use the HeapSRoA'd load. static void RewriteHeapSROALoadUser(LoadInst *Load, Instruction *LoadUser, @@ -903,8 +923,7 @@ static void RewriteHeapSROALoadUser(LoadInst *Load, Instruction *LoadUser, // field. Value *NPtr; if (InsertedLoadsForPtr.empty()) { - NPtr = new LoadInst(FieldGlobals[0], Load->getName()+".f0", Load); - InsertedLoadsForPtr.push_back(Load); + NPtr = GetHeapSROALoad(Load, 0, FieldGlobals, InsertedLoadsForPtr); } else { NPtr = InsertedLoadsForPtr.back(); } @@ -917,30 +936,35 @@ static void RewriteHeapSROALoadUser(LoadInst *Load, Instruction *LoadUser, return; } - // Otherwise, this should be: 'getelementptr Ptr, Idx, uint FieldNo ...' - GetElementPtrInst *GEPI = cast(LoadUser); - assert(GEPI->getNumOperands() >= 3 && isa(GEPI->getOperand(2)) - && "Unexpected GEPI!"); - - // Load the pointer for this field. - unsigned FieldNo = cast(GEPI->getOperand(2))->getZExtValue(); - if (InsertedLoadsForPtr.size() <= FieldNo) - InsertedLoadsForPtr.resize(FieldNo+1); - if (InsertedLoadsForPtr[FieldNo] == 0) - InsertedLoadsForPtr[FieldNo] = new LoadInst(FieldGlobals[FieldNo], - Load->getName()+".f" + - utostr(FieldNo), Load); - Value *NewPtr = InsertedLoadsForPtr[FieldNo]; + // Handle 'getelementptr Ptr, Idx, uint FieldNo ...' + if (GetElementPtrInst *GEPI = dyn_cast(LoadUser)) { + assert(GEPI->getNumOperands() >= 3 && isa(GEPI->getOperand(2)) + && "Unexpected GEPI!"); - // Create the new GEP idx vector. - SmallVector GEPIdx; - GEPIdx.push_back(GEPI->getOperand(1)); - GEPIdx.append(GEPI->op_begin()+3, GEPI->op_end()); + // Load the pointer for this field. + unsigned FieldNo = cast(GEPI->getOperand(2))->getZExtValue(); + Value *NewPtr = GetHeapSROALoad(Load, FieldNo, + FieldGlobals, InsertedLoadsForPtr); + + // Create the new GEP idx vector. + SmallVector GEPIdx; + GEPIdx.push_back(GEPI->getOperand(1)); + GEPIdx.append(GEPI->op_begin()+3, GEPI->op_end()); + + Value *NGEPI = new GetElementPtrInst(NewPtr, GEPIdx.begin(), GEPIdx.end(), + GEPI->getName(), GEPI); + GEPI->replaceAllUsesWith(NGEPI); + GEPI->eraseFromParent(); + return; + } - Value *NGEPI = new GetElementPtrInst(NewPtr, GEPIdx.begin(), GEPIdx.end(), - GEPI->getName(), GEPI); - GEPI->replaceAllUsesWith(NGEPI); - GEPI->eraseFromParent(); + // Handle PHI nodes. All PHI nodes must be merging in the same values, so + // just treat them like a copy. + PHINode *PN = cast(LoadUser); + while (!PN->use_empty()) + RewriteHeapSROALoadUser(Load, PN->use_back(), + FieldGlobals, InsertedLoadsForPtr); + PN->eraseFromParent(); } /// RewriteUsesOfLoadForHeapSRoA - We are performing Heap SRoA on a global. Ptr