bool ARM64PromoteConstant::isDominated(Instruction *NewPt, Value::use_iterator &UseIt, InsertionPoints &InsertPts) { DominatorTree &DT = getAnalysis<DominatorTree>(*NewPt->getParent()->getParent()); // Traverse all the existing insertion point and check if one is dominating // NewPt for (InsertionPoints::iterator IPI = InsertPts.begin(), EndIPI = InsertPts.end(); IPI != EndIPI; ++IPI) { if (NewPt == IPI->first || DT.dominates(IPI->first, NewPt) || // When IPI->first is a terminator instruction, DT may think that // the result is defined on the edge. // Here we are testing the insertion point, not the definition. (IPI->first->getParent() != NewPt->getParent() && DT.dominates(IPI->first->getParent(), NewPt->getParent()))) { // No need to insert this point // Record the dominated use DEBUG(dbgs() << "Insertion point dominated by:\n"); DEBUG(IPI->first->print(dbgs())); DEBUG(dbgs() << '\n'); IPI->second.push_back(UseIt); return true; } } return false; }
bool AArch64PromoteConstant::tryAndMerge(Instruction *NewPt, Instruction *User, unsigned OpNo, InsertionPoints &InsertPts) { DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>( *NewPt->getParent()->getParent()).getDomTree(); BasicBlock *NewBB = NewPt->getParent(); // Traverse all the existing insertion point and check if one is dominated by // NewPt and thus useless or can be combined with NewPt into a common // dominator. for (InsertionPoints::iterator IPI = InsertPts.begin(), EndIPI = InsertPts.end(); IPI != EndIPI; ++IPI) { BasicBlock *CurBB = IPI->first->getParent(); if (NewBB == CurBB) { // Instructions are in the same block. // By construction, NewPt is dominating the other. // Indeed, isDominated returned false with the exact same arguments. DEBUG(dbgs() << "Merge insertion point with:\n"); DEBUG(IPI->first->print(dbgs())); DEBUG(dbgs() << "\nat considered insertion point.\n"); appendAndTransferDominatedUses(NewPt, User, OpNo, IPI, InsertPts); return true; } // Look for a common dominator BasicBlock *CommonDominator = DT.findNearestCommonDominator(NewBB, CurBB); // If none exists, we cannot merge these two points. if (!CommonDominator) continue; if (CommonDominator != NewBB) { // By construction, the CommonDominator cannot be CurBB. assert(CommonDominator != CurBB && "Instruction has not been rejected during isDominated check!"); // Take the last instruction of the CommonDominator as insertion point NewPt = CommonDominator->getTerminator(); } // else, CommonDominator is the block of NewBB, hence NewBB is the last // possible insertion point in that block. DEBUG(dbgs() << "Merge insertion point with:\n"); DEBUG(IPI->first->print(dbgs())); DEBUG(dbgs() << '\n'); DEBUG(NewPt->print(dbgs())); DEBUG(dbgs() << '\n'); appendAndTransferDominatedUses(NewPt, User, OpNo, IPI, InsertPts); return true; } return false; }
void AArch64PromoteConstant::insertDefinitions(Function &F, GlobalVariable &PromotedGV, InsertionPoints &InsertPts) { #ifndef NDEBUG // Do more checking for debug purposes. DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>(F).getDomTree(); #endif assert(!InsertPts.empty() && "Empty uses does not need a definition"); for (const auto &IPI : InsertPts) { // Create the load of the global variable. IRBuilder<> Builder(IPI.first); LoadInst *LoadedCst = Builder.CreateLoad(&PromotedGV); DEBUG(dbgs() << "**********\n"); DEBUG(dbgs() << "New def: "); DEBUG(LoadedCst->print(dbgs())); DEBUG(dbgs() << '\n'); // Update the dominated uses. for (auto Use : IPI.second) { #ifndef NDEBUG assert(DT.dominates(LoadedCst, findInsertionPoint(*Use.first, Use.second)) && "Inserted definition does not dominate all its uses!"); #endif DEBUG({ dbgs() << "Use to update " << Use.second << ":"; Use.first->print(dbgs()); dbgs() << '\n'; }); Use.first->setOperand(Use.second, LoadedCst); ++NumPromotedUses; } }