Index: llvm/include/llvm/Transforms/IPO/IROutliner.h =================================================================== --- llvm/include/llvm/Transforms/IPO/IROutliner.h +++ llvm/include/llvm/Transforms/IPO/IROutliner.h @@ -156,6 +156,16 @@ /// containing the called function. void reattachCandidate(); + /// Find a corresponding value for \p V in similar OutlinableRegion \p Other. + /// + /// \param Other [in] - The OutlinableRegion to find the corresponding Value + /// in. + /// \param V [in] - The Value to look for in the other region. + /// \return An optional that contains the corresponding Value to \p V if it + /// exists, otherwise None. + Optional findCorrespondingValueIn(const OutlinableRegion &Other, + Value *V); + /// Get the size of the code removed from the region. /// /// \param [in] TTI - The TargetTransformInfo for the parent function. Index: llvm/lib/Transforms/IPO/IROutliner.cpp =================================================================== --- llvm/lib/Transforms/IPO/IROutliner.cpp +++ llvm/lib/Transforms/IPO/IROutliner.cpp @@ -164,6 +164,16 @@ }); } +Optional +OutlinableRegion::findCorrespondingValueIn(const OutlinableRegion &Other, + Value *V) { + Optional GVN = Candidate->getGVN(V); + assert(GVN.hasValue() && "No GVN for incoming value"); + Optional CanonNum = Candidate->getCanonicalNum(*GVN); + Optional FirstGVN = Other.Candidate->fromCanonicalNum(*CanonNum); + return Other.Candidate->fromGVN(*FirstGVN); +} + void OutlinableRegion::splitCandidate() { assert(!CandidateSplit && "Candidate already split!"); @@ -1151,12 +1161,27 @@ VBBIt = OutputBBs.find(RetVal); assert(VBBIt != OutputBBs.end() && "Could not find output value!"); + // If this is storing a PHINode, we must make sure it is included in the + // overall function. + StoreInst *SI = dyn_cast(I); + assert(SI && "Is not a store instrution"); + + Value *ValueOperand = SI->getValueOperand(); + Instruction *NewI = I->clone(); NewI->setDebugLoc(DebugLoc()); BasicBlock *OutputBB = VBBIt->second; OutputBB->getInstList().push_back(NewI); LLVM_DEBUG(dbgs() << "Move store for instruction " << *I << " to " << *OutputBB << "\n"); + + StoreInst *NewSI = dyn_cast(NewI); + if (FirstFunction) + continue; + Optional CorrVal = + Region.findCorrespondingValueIn(*Group.Regions[0], ValueOperand); + assert(CorrVal.hasValue() && "Value is none?"); + NewSI->setOperand(0, *CorrVal); } // If we added an edge for basic blocks without a predecessor, we remove it @@ -1203,34 +1228,6 @@ } } -/// For the given function, find all the nondebug or lifetime instructions, -/// and return them as a vector. Exclude any blocks in \p ExludeBlocks. -/// -/// \param [in] F - The function we collect the instructions from. -/// \param [in] ExcludeBlocks - BasicBlocks to ignore. -/// \returns the list of instructions extracted. -static std::vector -collectRelevantInstructions(Function &F, - DenseSet &ExcludeBlocks) { - std::vector RelevantInstructions; - - for (BasicBlock &BB : F) { - if (ExcludeBlocks.contains(&BB)) - continue; - - for (Instruction &Inst : BB) { - if (Inst.isLifetimeStartOrEnd()) - continue; - if (isa(Inst)) - continue; - - RelevantInstructions.push_back(&Inst); - } - } - - return RelevantInstructions; -} - /// It is possible that there is a basic block that already performs the same /// stores. This returns a duplicate block, if it exists /// @@ -1306,51 +1303,6 @@ DenseMap &EndBBs, const DenseMap &OutputMappings, std::vector> &OutputStoreBBs) { - DenseSet ValuesToFind(Region.GVNStores.begin(), - Region.GVNStores.end()); - - // We iterate over the instructions in the extracted function, and find the - // global value number of the instructions. If we find a value that should - // be contained in a store, we replace the uses of the value with the value - // from the overall function, so that the store is storing the correct - // value from the overall function. - DenseSet ExcludeBBs; - for (DenseMap &BBMap : OutputStoreBBs) - for (std::pair &VBPair : BBMap) - ExcludeBBs.insert(VBPair.second); - for (std::pair &VBPair : OutputBBs) - ExcludeBBs.insert(VBPair.second); - - std::vector ExtractedFunctionInsts = - collectRelevantInstructions(*(Region.ExtractedFunction), ExcludeBBs); - std::vector OverallFunctionInsts = - collectRelevantInstructions(*OG.OutlinedFunction, ExcludeBBs); - - assert(ExtractedFunctionInsts.size() == OverallFunctionInsts.size() && - "Number of relevant instructions not equal!"); - - unsigned NumInstructions = ExtractedFunctionInsts.size(); - for (unsigned Idx = 0; Idx < NumInstructions; Idx++) { - Value *V = ExtractedFunctionInsts[Idx]; - - if (OutputMappings.find(V) != OutputMappings.end()) - V = OutputMappings.find(V)->second; - Optional GVN = Region.Candidate->getGVN(V); - - // If we have found one of the stored values for output, replace the value - // with the corresponding one from the overall function. - if (GVN.hasValue() && ValuesToFind.erase(GVN.getValue())) { - V->replaceAllUsesWith(OverallFunctionInsts[Idx]); - if (ValuesToFind.size() == 0) - break; - } - - if (ValuesToFind.size() == 0) - break; - } - - assert(ValuesToFind.size() == 0 && "Not all store values were handled!"); - // If the size of the block is 0, then there are no stores, and we do not // need to save this block. bool AllRemoved = true;