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; } }
bool AArch64PromoteConstant::insertDefinitions( Constant *Cst, InsertionPointsPerFunc &InsPtsPerFunc) { // We will create one global variable per Module. DenseMap<Module *, GlobalVariable *> ModuleToMergedGV; bool HasChanged = false; // Traverse all insertion points in all the function. for (const auto &FctToInstPtsIt : InsPtsPerFunc) { const InsertionPoints &InsertPts = FctToInstPtsIt.second; // Do more checking for debug purposes. #ifndef NDEBUG DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>( *FctToInstPtsIt.first).getDomTree(); #endif assert(!InsertPts.empty() && "Empty uses does not need a definition"); Module *M = FctToInstPtsIt.first->getParent(); GlobalVariable *&PromotedGV = ModuleToMergedGV[M]; if (!PromotedGV) { PromotedGV = new GlobalVariable( *M, Cst->getType(), true, GlobalValue::InternalLinkage, nullptr, "_PromotedConst", nullptr, GlobalVariable::NotThreadLocal); PromotedGV->setInitializer(Cst); DEBUG(dbgs() << "Global replacement: "); DEBUG(PromotedGV->print(dbgs())); DEBUG(dbgs() << '\n'); ++NumPromoted; HasChanged = true; } for (const auto &IPI : InsertPts) { // Create the load of the global variable. IRBuilder<> Builder(IPI.first->getParent(), 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 (Use *Use : IPI.second) { #ifndef NDEBUG assert(DT.dominates(LoadedCst, findInsertionPoint(*Use)) && "Inserted definition does not dominate all its uses!"); #endif DEBUG(dbgs() << "Use to update " << Use->getOperandNo() << ":"); DEBUG(Use->getUser()->print(dbgs())); DEBUG(dbgs() << '\n'); Use->set(LoadedCst); ++NumPromotedUses; } } } return HasChanged; }
bool AArch64PromoteConstant::insertDefinitions( Constant *Cst, InsertionPointsPerFunc &InsPtsPerFunc) { // We will create one global variable per Module. DenseMap<Module *, GlobalVariable *> ModuleToMergedGV; bool HasChanged = false; // Traverse all insertion points in all the function. for (InsertionPointsPerFunc::iterator FctToInstPtsIt = InsPtsPerFunc.begin(), EndIt = InsPtsPerFunc.end(); FctToInstPtsIt != EndIt; ++FctToInstPtsIt) { InsertionPoints &InsertPts = FctToInstPtsIt->second; // Do more checking for debug purposes. #ifndef NDEBUG DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>( *FctToInstPtsIt->first).getDomTree(); #endif GlobalVariable *PromotedGV; assert(!InsertPts.empty() && "Empty uses does not need a definition"); Module *M = FctToInstPtsIt->first->getParent(); DenseMap<Module *, GlobalVariable *>::iterator MapIt = ModuleToMergedGV.find(M); if (MapIt == ModuleToMergedGV.end()) { PromotedGV = new GlobalVariable( *M, Cst->getType(), true, GlobalValue::InternalLinkage, nullptr, "_PromotedConst", nullptr, GlobalVariable::NotThreadLocal); PromotedGV->setInitializer(Cst); ModuleToMergedGV[M] = PromotedGV; DEBUG(dbgs() << "Global replacement: "); DEBUG(PromotedGV->print(dbgs())); DEBUG(dbgs() << '\n'); ++NumPromoted; HasChanged = true; } else { PromotedGV = MapIt->second; } for (InsertionPoints::iterator IPI = InsertPts.begin(), EndIPI = InsertPts.end(); IPI != EndIPI; ++IPI) { // Create the load of the global variable. IRBuilder<> Builder(IPI->first->getParent(), 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. Users &DominatedUsers = IPI->second; for (Value::user_iterator Use : DominatedUsers) { #ifndef NDEBUG assert((DT.dominates(LoadedCst, cast<Instruction>(*Use)) || (isa<PHINode>(*Use) && DT.dominates(LoadedCst, findInsertionPoint(Use)))) && "Inserted definition does not dominate all its uses!"); #endif DEBUG(dbgs() << "Use to update " << Use.getOperandNo() << ":"); DEBUG(Use->print(dbgs())); DEBUG(dbgs() << '\n'); Use->setOperand(Use.getOperandNo(), LoadedCst); ++NumPromotedUses; } } } return HasChanged; }