SetVector<Value*> qdp_jit_vec::get_loads( SetVector<Value*> Vec ) { SetVector<Value*> loads; for (Value* V : Vec) { SetVector<Value*> tmp = get_loads( V ); loads.insert( tmp.begin() , tmp.end() ); } return loads; }
bool Linker::linkInMetadata(Module &Src, DenseMap<unsigned, MDNode *> *ValIDToTempMDMap) { SetVector<GlobalValue *> ValuesToLink; if (Mover.move( Src, ValuesToLink.getArrayRef(), [this](GlobalValue &GV, IRMover::ValueAdder Add) { assert(false); }, ValIDToTempMDMap, true)) return true; return false; }
ScopStmt::ScopStmt(Scop &parent, SmallVectorImpl<unsigned> &Scatter) : Parent(parent), BB(NULL), IVS(0) { BaseName = "FinalRead"; // Build iteration domain. std::string IterationDomainString = "{[i0] : i0 = 0}"; Domain = isl_set_read_from_str(Parent.getCtx(), IterationDomainString.c_str(), -1); Domain = isl_set_add_dims(Domain, isl_dim_param, Parent.getNumParams()); Domain = isl_set_set_tuple_name(Domain, getBaseName()); // Build scattering. unsigned ScatDim = Parent.getMaxLoopDepth() * 2 + 1; isl_dim *dim = isl_dim_alloc(Parent.getCtx(), Parent.getNumParams(), 1, ScatDim); dim = isl_dim_set_tuple_name(dim, isl_dim_out, "scattering"); dim = isl_dim_set_tuple_name(dim, isl_dim_in, getBaseName()); isl_basic_map *bmap = isl_basic_map_universe(isl_dim_copy(dim)); isl_int v; isl_int_init(v); isl_constraint *c = isl_equality_alloc(dim); isl_int_set_si(v, -1); isl_constraint_set_coefficient(c, isl_dim_out, 0, v); // TODO: This is incorrect. We should not use a very large number to ensure // that this statement is executed last. isl_int_set_si(v, 200000000); isl_constraint_set_constant(c, v); bmap = isl_basic_map_add_constraint(bmap, c); isl_int_clear(v); Scattering = isl_map_from_basic_map(bmap); // Build memory accesses, use SetVector to keep the order of memory accesses // and prevent the same memory access inserted more than once. SetVector<const Value*> BaseAddressSet; for (Scop::const_iterator SI = Parent.begin(), SE = Parent.end(); SI != SE; ++SI) { ScopStmt *Stmt = *SI; for (MemoryAccessVec::const_iterator I = Stmt->memacc_begin(), E = Stmt->memacc_end(); I != E; ++I) BaseAddressSet.insert((*I)->getBaseAddr()); } for (SetVector<const Value*>::iterator BI = BaseAddressSet.begin(), BE = BaseAddressSet.end(); BI != BE; ++BI) MemAccs.push_back(new MemoryAccess(*BI, this)); IsReduction = false; }
SetVector<Value*> qdp_jit_vec::get_all_linked_stores_from_store( Value* V ) { bool all=false; SetVector<Value*> stores; stores.insert(V); while(!all) { SetVector<Value*> new_stores; new_stores = get_stores( get_loads( stores ) ); all = (new_stores.size() == stores.size()); stores = new_stores; } return stores; }
static void computeVariableSummary(ModuleSummaryIndex &Index, const GlobalVariable &V, DenseSet<GlobalValue::GUID> &CantBePromoted) { SetVector<ValueInfo> RefEdges; SmallPtrSet<const User *, 8> Visited; findRefEdges(&V, RefEdges, Visited); bool NonRenamableLocal = isNonRenamableLocal(V); GlobalValueSummary::GVFlags Flags(V.getLinkage(), NonRenamableLocal, /* LiveRoot = */ false); auto GVarSummary = llvm::make_unique<GlobalVarSummary>(Flags, RefEdges.takeVector()); if (NonRenamableLocal) CantBePromoted.insert(V.getGUID()); Index.addGlobalValueSummary(V.getName(), std::move(GVarSummary)); }
/// Determine whether this call has all constant integer arguments (excluding /// "this") and summarize it to VCalls or ConstVCalls as appropriate. static void addVCallToSet(DevirtCallSite Call, GlobalValue::GUID Guid, SetVector<FunctionSummary::VFuncId> &VCalls, SetVector<FunctionSummary::ConstVCall> &ConstVCalls) { std::vector<uint64_t> Args; // Start from the second argument to skip the "this" pointer. for (auto &Arg : make_range(Call.CS.arg_begin() + 1, Call.CS.arg_end())) { auto *CI = dyn_cast<ConstantInt>(Arg); if (!CI || CI->getBitWidth() > 64) { VCalls.insert({Guid, Call.Offset}); return; } Args.push_back(CI->getZExtValue()); } ConstVCalls.insert({{Guid, Call.Offset}, std::move(Args)}); }
void DeadCodeElimination::processUse(NodeAddr<UseNode*> UA, SetVector<NodeId> &WorkQ) { for (NodeAddr<DefNode*> DA : LV.getAllReachingDefs(UA)) { if (!LiveNodes.count(DA.Id)) WorkQ.insert(DA.Id); } }
/// definedInCaller - Return true if the specified value is defined in the /// function being code extracted, but not in the region being extracted. /// These values must be passed in as live-ins to the function. static bool definedInCaller(const SetVector<BasicBlock *> &Blocks, Value *V) { if (isa<Argument>(V)) return true; if (Instruction *I = dyn_cast<Instruction>(V)) if (!Blocks.count(I->getParent())) return true; return false; }
// Walk through the operands of a given User via worklist iteration and populate // the set of GlobalValue references encountered. Invoked either on an // Instruction or a GlobalVariable (which walks its initializer). static void findRefEdges(const User *CurUser, SetVector<ValueInfo> &RefEdges, SmallPtrSet<const User *, 8> &Visited) { SmallVector<const User *, 32> Worklist; Worklist.push_back(CurUser); while (!Worklist.empty()) { const User *U = Worklist.pop_back_val(); if (!Visited.insert(U).second) continue; ImmutableCallSite CS(U); for (const auto &OI : U->operands()) { const User *Operand = dyn_cast<User>(OI); if (!Operand) continue; if (isa<BlockAddress>(Operand)) continue; if (auto *GV = dyn_cast<GlobalValue>(Operand)) { // We have a reference to a global value. This should be added to // the reference set unless it is a callee. Callees are handled // specially by WriteFunction and are added to a separate list. if (!(CS && CS.isCallee(&OI))) RefEdges.insert(GV); continue; } Worklist.push_back(Operand); } } }
static SetVector<BasicBlock *> buildExtractionBlockSet(IteratorT BBBegin, IteratorT BBEnd) { SetVector<BasicBlock *> Result; assert(BBBegin != BBEnd); // Loop over the blocks, adding them to our set-vector, and aborting with an // empty set if we encounter invalid blocks. for (IteratorT I = BBBegin, E = BBEnd; I != E; ++I) { if (!Result.insert(*I)) llvm_unreachable("Repeated basic blocks in extraction input"); if (!isBlockValidForExtraction(**I)) { Result.clear(); return Result; } } #ifndef NDEBUG #if LLVM_VERSION_MINOR == 5 for (SetVector<BasicBlock *>::iterator I = std::next(Result.begin()), #else for (SetVector<BasicBlock *>::iterator I = llvm::next(Result.begin()), #endif E = Result.end(); I != E; ++I) for (pred_iterator PI = pred_begin(*I), PE = pred_end(*I); PI != PE; ++PI) assert(Result.count(*PI) && "No blocks in this region may have entries from outside the region" " except for the first block!"); #endif return Result; }
void OMPGenerator::extractValuesFromStruct(SetVector<Value *> OldValues, Value *Struct, ValueToValueMapTy &Map) { for (unsigned i = 0; i < OldValues.size(); i++) { Value *Address = Builder.CreateStructGEP(Struct, i); Value *NewValue = Builder.CreateLoad(Address); Map.insert(std::make_pair(OldValues[i], NewValue)); } }
void ParallelLoopGenerator::extractValuesFromStruct( SetVector<Value *> OldValues, Type *Ty, Value *Struct, ValueMapT &Map) { for (unsigned i = 0; i < OldValues.size(); i++) { Value *Address = Builder.CreateStructGEP(Ty, Struct, i); Value *NewValue = Builder.CreateLoad(Address); NewValue->setName("polly.subfunc.arg." + OldValues[i]->getName()); Map[OldValues[i]] = NewValue; } }
void ParallelLoopGenerator::extractValuesFromStruct( SetVector<Value *> OldValues, Type *Ty, Value *Struct, ValueToValueMapTy &Map) { for (unsigned i = 0; i < OldValues.size(); i++) { Value *Address = Builder.CreateStructGEP(Ty, Struct, i); Value *NewValue = Builder.CreateLoad(Address); Map[OldValues[i]] = NewValue; } }
TEST(SetVector, EraseTest) { SetVector<int> S; S.insert(0); S.insert(1); S.insert(2); auto I = S.erase(std::next(S.begin())); // Test that the returned iterator is the expected one-after-erase // and the size/contents is the expected sequence {0, 2}. EXPECT_EQ(std::next(S.begin()), I); EXPECT_EQ(2u, S.size()); EXPECT_EQ(0, *S.begin()); EXPECT_EQ(2, *std::next(S.begin())); }
void DeadCodeElimination::processDef(NodeAddr<DefNode*> DA, SetVector<NodeId> &WorkQ) { NodeAddr<InstrNode*> IA = DA.Addr->getOwner(DFG); for (NodeAddr<UseNode*> UA : IA.Addr->members_if(DFG.IsUse, DFG)) { if (!LiveNodes.count(UA.Id)) WorkQ.insert(UA.Id); } for (NodeAddr<DefNode*> TA : DFG.getRelatedRefs(IA, DA)) LiveNodes.insert(TA.Id); }
void CodeGenRegister::addSubRegsPreOrder(SetVector<CodeGenRegister*> &OSet) const { assert(SubRegsComplete && "Must precompute sub-registers"); std::vector<Record*> Indices = TheDef->getValueAsListOfDefs("SubRegIndices"); for (unsigned i = 0, e = Indices.size(); i != e; ++i) { CodeGenRegister *SR = SubRegs.find(Indices[i])->second; if (OSet.insert(SR)) SR->addSubRegsPreOrder(OSet); } }
APInt GraphNode::findShortestPath(GraphNode *Dest, SetVector<GraphNode*> Visited) { if (Dest == this) { DEBUG(dbgs() << "IneqGraph: Reached: " << *Dest->getValue() << "\n"); return APInt(64, 0, true); } DEBUG(dbgs() << "IneqGraph: Node: " << *V << "\n"); if (Visited.count(this)) { DEBUG(dbgs() << "IneqGraph: Visited\n"); return APInt::getSignedMaxValue(64); //(64, , true); } Visited.insert(this); APInt MayMin = APInt::getSignedMaxValue(64); for (may_iterator It = may_begin(), E = may_end(); It != E; ++It) { APInt Total = It->getToEdge()->findShortestPath(Dest, Visited); if (Total.slt(MayMin)) MayMin = Total + It->getWeight(); } //DEBUG(dbgs() << "IneqGraph: Node: " << *V << ", MayMin: " << MayMin << "\n"); APInt MustMax = APInt::getSignedMinValue(64); for (must_iterator It = must_begin(), E = must_end(); It != E; ++It) { APInt Total = It->getToEdge()->findShortestPath(Dest, Visited); if (MustMax.slt(Total)) MustMax = Total; } // DEBUG(dbgs() << "IneqGraph: Node: " << *V << ", MustMax: " << MustMax << "\n"); if (MustMax.isMinSignedValue()) { //DEBUG(dbgs() << "IneqGraph: Node: " << *V << ", Distance: " << MayMin << "\n"); DEBUG(dbgs() << "IneqGraph: Ret: " << MayMin << "\n"); return MayMin; } else { APInt Min = MustMax.slt(MayMin) ? MustMax : MayMin; //DEBUG(dbgs() << "IneqGraph: Node: " << *V << ", Distance: " << Min << "\n"); DEBUG(dbgs() << "IneqGraph: Ret: " << Min << "\n"); return Min; } }
void DeadCodeElimination::scanInstr(NodeAddr<InstrNode*> IA, SetVector<NodeId> &WorkQ) { if (!DFG.IsCode<NodeAttrs::Stmt>(IA)) return; if (!isLiveInstr(NodeAddr<StmtNode*>(IA).Addr->getCode())) return; for (NodeAddr<RefNode*> RA : IA.Addr->members(DFG)) { if (!LiveNodes.count(RA.Id)) WorkQ.insert(RA.Id); } }
bool LiveRangeCalc::isJointlyDominated(const MachineBasicBlock *MBB, ArrayRef<SlotIndex> Defs, const SlotIndexes &Indexes) { const MachineFunction &MF = *MBB->getParent(); BitVector DefBlocks(MF.getNumBlockIDs()); for (SlotIndex I : Defs) DefBlocks.set(Indexes.getMBBFromIndex(I)->getNumber()); SetVector<unsigned> PredQueue; PredQueue.insert(MBB->getNumber()); for (unsigned i = 0; i != PredQueue.size(); ++i) { unsigned BN = PredQueue[i]; if (DefBlocks[BN]) return true; const MachineBasicBlock *B = MF.getBlockNumbered(BN); for (const MachineBasicBlock *P : B->predecessors()) PredQueue.insert(P->getNumber()); } return false; }
/// \brief Build a set of blocks to extract if the input blocks are viable. static SetVector<BasicBlock *> buildExtractionBlockSet(ArrayRef<BasicBlock *> BBs, DominatorTree *DT) { assert(!BBs.empty() && "The set of blocks to extract must be non-empty"); SetVector<BasicBlock *> Result; // Loop over the blocks, adding them to our set-vector, and aborting with an // empty set if we encounter invalid blocks. for (BasicBlock *BB : BBs) { // If this block is dead, don't process it. if (DT && !DT->isReachableFromEntry(BB)) continue; if (!Result.insert(BB)) llvm_unreachable("Repeated basic blocks in extraction input"); if (!CodeExtractor::isBlockValidForExtraction(*BB)) { Result.clear(); return Result; } } #ifndef NDEBUG for (SetVector<BasicBlock *>::iterator I = std::next(Result.begin()), E = Result.end(); I != E; ++I) for (pred_iterator PI = pred_begin(*I), PE = pred_end(*I); PI != PE; ++PI) assert(Result.count(*PI) && "No blocks in this region may have entries from outside the region" " except for the first block!"); #endif return Result; }
bool HexagonDCE::run() { bool Collected = collect(); if (!Collected) return false; const SetVector<NodeId> &DeadNodes = getDeadNodes(); const SetVector<NodeId> &DeadInstrs = getDeadInstrs(); typedef DenseMap<NodeId,NodeId> RefToInstrMap; RefToInstrMap R2I; SetVector<NodeId> PartlyDead; DataFlowGraph &DFG = getDFG(); for (NodeAddr<BlockNode*> BA : DFG.getFunc().Addr->members(DFG)) { for (auto TA : BA.Addr->members_if(DFG.IsCode<NodeAttrs::Stmt>, DFG)) { NodeAddr<StmtNode*> SA = TA; for (NodeAddr<RefNode*> RA : SA.Addr->members(DFG)) { R2I.insert(std::make_pair(RA.Id, SA.Id)); if (DFG.IsDef(RA) && DeadNodes.count(RA.Id)) if (!DeadInstrs.count(SA.Id)) PartlyDead.insert(SA.Id); } } } // Nodes to remove. SetVector<NodeId> Remove = DeadInstrs; bool Changed = false; for (NodeId N : PartlyDead) { auto SA = DFG.addr<StmtNode*>(N); if (trace()) dbgs() << "Partly dead: " << *SA.Addr->getCode(); Changed |= rewrite(SA, Remove); } return erase(Remove) || Changed; }
SetVector<Value*> qdp_jit_vec::get_stores( Value* V ) { SetVector<Value*> stores; SetVector<Value*> to_visit; to_visit.insert(V); while (!to_visit.empty()) { Value* v = to_visit.back(); to_visit.pop_back(); Instruction* vi; if ((vi = dyn_cast<Instruction>(v))) { for (Use& U : vi->uses()) { if (isa<StoreInst>(U.getUser())) { stores.insert(U.getUser()); } else if (isa<Instruction>(U.getUser())) { to_visit.insert(U.getUser()); } } } } return stores; }
SetVector<Value*> qdp_jit_vec::get_loads( Value* V ) { SetVector<Value*> loads; SetVector<Value*> to_visit; to_visit.insert(V); while (!to_visit.empty()) { Value* v = to_visit.back(); to_visit.pop_back(); Instruction* vi; if ((vi = dyn_cast<Instruction>(v))) { for (Use& U : vi->operands()) { if (isa<LoadInst>(U.get())) { loads.insert(U.get()); } else if (isa<Instruction>(U.get())) { to_visit.insert(U.get()); } } } } return loads; }
SetVector<Value *> ClastStmtCodeGen::getOMPValues(const clast_stmt *Body) { SetVector<Value *> Values; // The clast variables for (CharMapT::iterator I = ClastVars.begin(), E = ClastVars.end(); I != E; I++) Values.insert(I->second); // Find the temporaries that are referenced in the clast statements' // basic blocks but are not defined by these blocks (e.g., references // to function arguments or temporaries defined before the start of // the SCoP). ParameterVisitor Params; Params.visit(Body); for (ParameterVisitor::const_iterator PI = Params.begin(), PE = Params.end(); PI != PE; ++PI) { Value *V = *PI; Values.insert(V); DEBUG(dbgs() << "Adding temporary for OMP copy-in: " << *V << "\n"); } return Values; }
// If a linkonce global is present in the MustPreserveSymbols, we need to make // sure we honor this. To force the compiler to not drop it, we add it to the // "llvm.compiler.used" global. void LTOCodeGenerator::preserveDiscardableGVs( Module &TheModule, llvm::function_ref<bool(const GlobalValue &)> mustPreserveGV) { SetVector<Constant *> UsedValuesSet; if (GlobalVariable *LLVMUsed = TheModule.getGlobalVariable("llvm.compiler.used")) { ConstantArray *Inits = cast<ConstantArray>(LLVMUsed->getInitializer()); for (auto &V : Inits->operands()) UsedValuesSet.insert(cast<Constant>(&V)); LLVMUsed->eraseFromParent(); } llvm::Type *i8PTy = llvm::Type::getInt8PtrTy(TheModule.getContext()); auto mayPreserveGlobal = [&](GlobalValue &GV) { if (!GV.isDiscardableIfUnused() || GV.isDeclaration()) return; if (!mustPreserveGV(GV)) return; if (GV.hasAvailableExternallyLinkage()) { emitWarning( (Twine("Linker asked to preserve available_externally global: '") + GV.getName() + "'").str()); return; } if (GV.hasInternalLinkage()) { emitWarning((Twine("Linker asked to preserve internal global: '") + GV.getName() + "'").str()); return; } UsedValuesSet.insert(ConstantExpr::getBitCast(&GV, i8PTy)); }; for (auto &GV : TheModule) mayPreserveGlobal(GV); for (auto &GV : TheModule.globals()) mayPreserveGlobal(GV); for (auto &GV : TheModule.aliases()) mayPreserveGlobal(GV); if (UsedValuesSet.empty()) return; llvm::ArrayType *ATy = llvm::ArrayType::get(i8PTy, UsedValuesSet.size()); auto *LLVMUsed = new llvm::GlobalVariable( TheModule, ATy, false, llvm::GlobalValue::AppendingLinkage, llvm::ConstantArray::get(ATy, UsedValuesSet.getArrayRef()), "llvm.compiler.used"); LLVMUsed->setSection("llvm.metadata"); }
BitVector CodeGenRegBank::computeCoveredRegisters(ArrayRef<Record*> Regs) { SetVector<const CodeGenRegister*> Set; // First add Regs with all sub-registers. for (unsigned i = 0, e = Regs.size(); i != e; ++i) { CodeGenRegister *Reg = getReg(Regs[i]); if (Set.insert(Reg)) // Reg is new, add all sub-registers. // The pre-ordering is not important here. Reg->addSubRegsPreOrder(Set, *this); } // Second, find all super-registers that are completely covered by the set. for (unsigned i = 0; i != Set.size(); ++i) { const CodeGenRegister::SuperRegList &SR = Set[i]->getSuperRegs(); for (unsigned j = 0, e = SR.size(); j != e; ++j) { const CodeGenRegister *Super = SR[j]; if (!Super->CoveredBySubRegs || Set.count(Super)) continue; // This new super-register is covered by its sub-registers. bool AllSubsInSet = true; const CodeGenRegister::SubRegMap &SRM = Super->getSubRegs(); for (CodeGenRegister::SubRegMap::const_iterator I = SRM.begin(), E = SRM.end(); I != E; ++I) if (!Set.count(I->second)) { AllSubsInSet = false; break; } // All sub-registers in Set, add Super as well. // We will visit Super later to recheck its super-registers. if (AllSubsInSet) Set.insert(Super); } } // Convert to BitVector. BitVector BV(Registers.size() + 1); for (unsigned i = 0, e = Set.size(); i != e; ++i) BV.set(Set[i]->EnumValue); return BV; }
bool HexagonDCE::rewrite(NodeAddr<InstrNode*> IA, SetVector<NodeId> &Remove) { if (!getDFG().IsCode<NodeAttrs::Stmt>(IA)) return false; DataFlowGraph &DFG = getDFG(); MachineInstr *MI = NodeAddr<StmtNode*>(IA).Addr->getCode(); auto &HII = static_cast<const HexagonInstrInfo&>(DFG.getTII()); if (HII.getAddrMode(MI) != HexagonII::PostInc) return false; unsigned Opc = MI->getOpcode(); unsigned OpNum, NewOpc; switch (Opc) { case Hexagon::L2_loadri_pi: NewOpc = Hexagon::L2_loadri_io; OpNum = 1; break; case Hexagon::L2_loadrd_pi: NewOpc = Hexagon::L2_loadrd_io; OpNum = 1; break; case Hexagon::V6_vL32b_pi: NewOpc = Hexagon::V6_vL32b_ai; OpNum = 1; break; case Hexagon::S2_storeri_pi: NewOpc = Hexagon::S2_storeri_io; OpNum = 0; break; case Hexagon::S2_storerd_pi: NewOpc = Hexagon::S2_storerd_io; OpNum = 0; break; case Hexagon::V6_vS32b_pi: NewOpc = Hexagon::V6_vS32b_ai; OpNum = 0; break; default: return false; } auto IsDead = [this] (NodeAddr<DefNode*> DA) -> bool { return getDeadNodes().count(DA.Id); }; NodeList Defs; MachineOperand &Op = MI->getOperand(OpNum); for (NodeAddr<DefNode*> DA : IA.Addr->members_if(DFG.IsDef, DFG)) { if (&DA.Addr->getOp() != &Op) continue; Defs = DFG.getRelatedRefs(IA, DA); if (!std::all_of(Defs.begin(), Defs.end(), IsDead)) return false; break; } // Mark all nodes in Defs for removal. for (auto D : Defs) Remove.insert(D.Id); if (trace()) dbgs() << "Rewriting: " << *MI; MI->setDesc(HII.get(NewOpc)); MI->getOperand(OpNum+2).setImm(0); removeOperand(IA, OpNum); if (trace()) dbgs() << " to: " << *MI; return true; }
// // runMCDesc - Print out MC register descriptions. // void RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, CodeGenRegBank &RegBank) { EmitSourceFileHeader("MC Register Information", OS); OS << "\n#ifdef GET_REGINFO_MC_DESC\n"; OS << "#undef GET_REGINFO_MC_DESC\n"; const std::vector<CodeGenRegister*> &Regs = RegBank.getRegisters(); // The lists of sub-registers, super-registers, and overlaps all go in the // same array. That allows us to share suffixes. typedef std::vector<const CodeGenRegister*> RegVec; SmallVector<RegVec, 4> SubRegLists(Regs.size()); SmallVector<RegVec, 4> OverlapLists(Regs.size()); SequenceToOffsetTable<RegVec, CodeGenRegister::Less> RegSeqs; // Precompute register lists for the SequenceToOffsetTable. for (unsigned i = 0, e = Regs.size(); i != e; ++i) { const CodeGenRegister *Reg = Regs[i]; // Compute the ordered sub-register list. SetVector<const CodeGenRegister*> SR; Reg->addSubRegsPreOrder(SR, RegBank); RegVec &SubRegList = SubRegLists[i]; SubRegList.assign(SR.begin(), SR.end()); RegSeqs.add(SubRegList); // Super-registers are already computed. const RegVec &SuperRegList = Reg->getSuperRegs(); RegSeqs.add(SuperRegList); // The list of overlaps doesn't need to have any particular order, except // Reg itself must be the first element. Pick an ordering that has one of // the other lists as a suffix. RegVec &OverlapList = OverlapLists[i]; const RegVec &Suffix = SubRegList.size() > SuperRegList.size() ? SubRegList : SuperRegList; CodeGenRegister::Set Omit(Suffix.begin(), Suffix.end()); // First element is Reg itself. OverlapList.push_back(Reg); Omit.insert(Reg); // Any elements not in Suffix. CodeGenRegister::Set OSet; Reg->computeOverlaps(OSet, RegBank); std::set_difference(OSet.begin(), OSet.end(), Omit.begin(), Omit.end(), std::back_inserter(OverlapList), CodeGenRegister::Less()); // Finally, Suffix itself. OverlapList.insert(OverlapList.end(), Suffix.begin(), Suffix.end()); RegSeqs.add(OverlapList); } // Compute the final layout of the sequence table. RegSeqs.layout(); OS << "namespace llvm {\n\n"; const std::string &TargetName = Target.getName(); // Emit the shared table of register lists. OS << "extern const uint16_t " << TargetName << "RegLists[] = {\n"; RegSeqs.emit(OS, printRegister); OS << "};\n\n"; OS << "extern const MCRegisterDesc " << TargetName << "RegDesc[] = { // Descriptors\n"; OS << " { \"NOREG\", 0, 0, 0 },\n"; // Emit the register descriptors now. for (unsigned i = 0, e = Regs.size(); i != e; ++i) { const CodeGenRegister *Reg = Regs[i]; OS << " { \"" << Reg->getName() << "\", " << RegSeqs.get(OverlapLists[i]) << ", " << RegSeqs.get(SubRegLists[i]) << ", " << RegSeqs.get(Reg->getSuperRegs()) << " },\n"; } OS << "};\n\n"; // End of register descriptors... ArrayRef<CodeGenRegisterClass*> RegisterClasses = RegBank.getRegClasses(); // Loop over all of the register classes... emitting each one. OS << "namespace { // Register classes...\n"; // Emit the register enum value arrays for each RegisterClass for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { const CodeGenRegisterClass &RC = *RegisterClasses[rc]; ArrayRef<Record*> Order = RC.getOrder(); // Give the register class a legal C name if it's anonymous. std::string Name = RC.getName(); // Emit the register list now. OS << " // " << Name << " Register Class...\n" << " const uint16_t " << Name << "[] = {\n "; for (unsigned i = 0, e = Order.size(); i != e; ++i) { Record *Reg = Order[i]; OS << getQualifiedName(Reg) << ", "; } OS << "\n };\n\n"; OS << " // " << Name << " Bit set.\n" << " const uint8_t " << Name << "Bits[] = {\n "; BitVectorEmitter BVE; for (unsigned i = 0, e = Order.size(); i != e; ++i) { Record *Reg = Order[i]; BVE.add(Target.getRegBank().getReg(Reg)->EnumValue); } BVE.print(OS); OS << "\n };\n\n"; } OS << "}\n\n"; OS << "extern const MCRegisterClass " << TargetName << "MCRegisterClasses[] = {\n"; for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { const CodeGenRegisterClass &RC = *RegisterClasses[rc]; // Asserts to make sure values will fit in table assuming types from // MCRegisterInfo.h assert((RC.SpillSize/8) <= 0xffff && "SpillSize too large."); assert((RC.SpillAlignment/8) <= 0xffff && "SpillAlignment too large."); assert(RC.CopyCost >= -128 && RC.CopyCost <= 127 && "Copy cost too large."); OS << " { " << '\"' << RC.getName() << "\", " << RC.getName() << ", " << RC.getName() << "Bits, " << RC.getOrder().size() << ", sizeof(" << RC.getName() << "Bits), " << RC.getQualifiedName() + "RegClassID" << ", " << RC.SpillSize/8 << ", " << RC.SpillAlignment/8 << ", " << RC.CopyCost << ", " << RC.Allocatable << " },\n"; } OS << "};\n\n"; // Emit the data table for getSubReg(). ArrayRef<CodeGenSubRegIndex*> SubRegIndices = RegBank.getSubRegIndices(); if (SubRegIndices.size()) { OS << "const uint16_t " << TargetName << "SubRegTable[][" << SubRegIndices.size() << "] = {\n"; for (unsigned i = 0, e = Regs.size(); i != e; ++i) { const CodeGenRegister::SubRegMap &SRM = Regs[i]->getSubRegs(); OS << " /* " << Regs[i]->TheDef->getName() << " */\n"; if (SRM.empty()) { OS << " {0},\n"; continue; } OS << " {"; for (unsigned j = 0, je = SubRegIndices.size(); j != je; ++j) { // FIXME: We really should keep this to 80 columns... CodeGenRegister::SubRegMap::const_iterator SubReg = SRM.find(SubRegIndices[j]); if (SubReg != SRM.end()) OS << getQualifiedName(SubReg->second->TheDef); else OS << "0"; if (j != je - 1) OS << ", "; } OS << "}" << (i != e ? "," : "") << "\n"; } OS << "};\n\n"; OS << "const uint16_t *get" << TargetName << "SubRegTable() {\n return (const uint16_t *)" << TargetName << "SubRegTable;\n}\n\n"; } EmitRegMappingTables(OS, Regs, false); // Emit Reg encoding table OS << "extern const uint16_t " << TargetName; OS << "RegEncodingTable[] = {\n"; // Add entry for NoRegister OS << " 0,\n"; for (unsigned i = 0, e = Regs.size(); i != e; ++i) { Record *Reg = Regs[i]->TheDef; BitsInit *BI = Reg->getValueAsBitsInit("HWEncoding"); uint64_t Value = 0; for (unsigned b = 0, be = BI->getNumBits(); b != be; ++b) { if (BitInit *B = dynamic_cast<BitInit*>(BI->getBit(b))) Value |= (uint64_t)B->getValue() << b; } OS << " " << Value << ",\n"; } OS << "};\n"; // End of HW encoding table // MCRegisterInfo initialization routine. OS << "static inline void Init" << TargetName << "MCRegisterInfo(MCRegisterInfo *RI, unsigned RA, " << "unsigned DwarfFlavour = 0, unsigned EHFlavour = 0) {\n"; OS << " RI->InitMCRegisterInfo(" << TargetName << "RegDesc, " << Regs.size()+1 << ", RA, " << TargetName << "MCRegisterClasses, " << RegisterClasses.size() << ", " << TargetName << "RegLists, "; if (SubRegIndices.size() != 0) OS << "(uint16_t*)" << TargetName << "SubRegTable, " << SubRegIndices.size() << ",\n"; else OS << "NULL, 0,\n"; OS << " " << TargetName << "RegEncodingTable);\n\n"; EmitRegMapping(OS, Regs, false); OS << "}\n\n"; OS << "} // End llvm namespace \n"; OS << "#endif // GET_REGINFO_MC_DESC\n\n"; }
bool PlaceSafepoints::runOnFunction(Function &F) { if (F.isDeclaration() || F.empty()) { // This is a declaration, nothing to do. Must exit early to avoid crash in // dom tree calculation return false; } if (isGCSafepointPoll(F)) { // Given we're inlining this inside of safepoint poll insertion, this // doesn't make any sense. Note that we do make any contained calls // parseable after we inline a poll. return false; } if (!shouldRewriteFunction(F)) return false; bool modified = false; // In various bits below, we rely on the fact that uses are reachable from // defs. When there are basic blocks unreachable from the entry, dominance // and reachablity queries return non-sensical results. Thus, we preprocess // the function to ensure these properties hold. modified |= removeUnreachableBlocks(F); // STEP 1 - Insert the safepoint polling locations. We do not need to // actually insert parse points yet. That will be done for all polls and // calls in a single pass. DominatorTree DT; DT.recalculate(F); SmallVector<Instruction *, 16> PollsNeeded; std::vector<CallSite> ParsePointNeeded; if (enableBackedgeSafepoints(F)) { // Construct a pass manager to run the LoopPass backedge logic. We // need the pass manager to handle scheduling all the loop passes // appropriately. Doing this by hand is painful and just not worth messing // with for the moment. legacy::FunctionPassManager FPM(F.getParent()); bool CanAssumeCallSafepoints = enableCallSafepoints(F); PlaceBackedgeSafepointsImpl *PBS = new PlaceBackedgeSafepointsImpl(CanAssumeCallSafepoints); FPM.add(PBS); FPM.run(F); // We preserve dominance information when inserting the poll, otherwise // we'd have to recalculate this on every insert DT.recalculate(F); auto &PollLocations = PBS->PollLocations; auto OrderByBBName = [](Instruction *a, Instruction *b) { return a->getParent()->getName() < b->getParent()->getName(); }; // We need the order of list to be stable so that naming ends up stable // when we split edges. This makes test cases much easier to write. std::sort(PollLocations.begin(), PollLocations.end(), OrderByBBName); // We can sometimes end up with duplicate poll locations. This happens if // a single loop is visited more than once. The fact this happens seems // wrong, but it does happen for the split-backedge.ll test case. PollLocations.erase(std::unique(PollLocations.begin(), PollLocations.end()), PollLocations.end()); // Insert a poll at each point the analysis pass identified // The poll location must be the terminator of a loop latch block. for (TerminatorInst *Term : PollLocations) { // We are inserting a poll, the function is modified modified = true; if (SplitBackedge) { // Split the backedge of the loop and insert the poll within that new // basic block. This creates a loop with two latches per original // latch (which is non-ideal), but this appears to be easier to // optimize in practice than inserting the poll immediately before the // latch test. // Since this is a latch, at least one of the successors must dominate // it. Its possible that we have a) duplicate edges to the same header // and b) edges to distinct loop headers. We need to insert pools on // each. SetVector<BasicBlock *> Headers; for (unsigned i = 0; i < Term->getNumSuccessors(); i++) { BasicBlock *Succ = Term->getSuccessor(i); if (DT.dominates(Succ, Term->getParent())) { Headers.insert(Succ); } } assert(!Headers.empty() && "poll location is not a loop latch?"); // The split loop structure here is so that we only need to recalculate // the dominator tree once. Alternatively, we could just keep it up to // date and use a more natural merged loop. SetVector<BasicBlock *> SplitBackedges; for (BasicBlock *Header : Headers) { BasicBlock *NewBB = SplitEdge(Term->getParent(), Header, &DT); PollsNeeded.push_back(NewBB->getTerminator()); NumBackedgeSafepoints++; } } else { // Split the latch block itself, right before the terminator. PollsNeeded.push_back(Term); NumBackedgeSafepoints++; } } } if (enableEntrySafepoints(F)) { Instruction *Location = findLocationForEntrySafepoint(F, DT); if (!Location) { // policy choice not to insert? } else { PollsNeeded.push_back(Location); modified = true; NumEntrySafepoints++; } } // Now that we've identified all the needed safepoint poll locations, insert // safepoint polls themselves. for (Instruction *PollLocation : PollsNeeded) { std::vector<CallSite> RuntimeCalls; InsertSafepointPoll(PollLocation, RuntimeCalls); ParsePointNeeded.insert(ParsePointNeeded.end(), RuntimeCalls.begin(), RuntimeCalls.end()); } // If we've been asked to not wrap the calls with gc.statepoint, then we're // done. In the near future, this option will be "constant folded" to true, // and the code below that deals with insert gc.statepoint calls will be // removed. Wrapping potentially safepointing calls in gc.statepoint will // then become the responsibility of the RewriteStatepointsForGC pass. if (NoStatepoints) return modified; PollsNeeded.clear(); // make sure we don't accidentally use // The dominator tree has been invalidated by the inlining performed in the // above loop. TODO: Teach the inliner how to update the dom tree? DT.recalculate(F); if (enableCallSafepoints(F)) { std::vector<CallSite> Calls; findCallSafepoints(F, Calls); NumCallSafepoints += Calls.size(); ParsePointNeeded.insert(ParsePointNeeded.end(), Calls.begin(), Calls.end()); } // Unique the vectors since we can end up with duplicates if we scan the call // site for call safepoints after we add it for entry or backedge. The // only reason we need tracking at all is that some functions might have // polls but not call safepoints and thus we might miss marking the runtime // calls for the polls. (This is useful in test cases!) unique_unsorted(ParsePointNeeded); // Any parse point (no matter what source) will be handled here // We're about to start modifying the function if (!ParsePointNeeded.empty()) modified = true; // Now run through and insert the safepoints, but do _NOT_ update or remove // any existing uses. We have references to live variables that need to // survive to the last iteration of this loop. std::vector<Value *> Results; Results.reserve(ParsePointNeeded.size()); for (size_t i = 0; i < ParsePointNeeded.size(); i++) { CallSite &CS = ParsePointNeeded[i]; // For invoke statepoints we need to remove all phi nodes at the normal // destination block. // Reason for this is that we can place gc_result only after last phi node // in basic block. We will get malformed code after RAUW for the // gc_result if one of this phi nodes uses result from the invoke. if (InvokeInst *Invoke = dyn_cast<InvokeInst>(CS.getInstruction())) { normalizeForInvokeSafepoint(Invoke->getNormalDest(), Invoke->getParent()); } Value *GCResult = ReplaceWithStatepoint(CS); Results.push_back(GCResult); } assert(Results.size() == ParsePointNeeded.size()); // Adjust all users of the old call sites to use the new ones instead for (size_t i = 0; i < ParsePointNeeded.size(); i++) { CallSite &CS = ParsePointNeeded[i]; Value *GCResult = Results[i]; if (GCResult) { // Can not RAUW for the invoke gc result in case of phi nodes preset. assert(CS.isCall() || !isa<PHINode>(cast<Instruction>(GCResult)->getParent()->begin())); // Replace all uses with the new call CS.getInstruction()->replaceAllUsesWith(GCResult); } // Now that we've handled all uses, remove the original call itself // Note: The insert point can't be the deleted instruction! CS.getInstruction()->eraseFromParent(); } return modified; }
bool AAEval::runOnFunction(Function &F) { AliasAnalysis &AA = getAnalysis<AliasAnalysis>(); SetVector<Value *> Pointers; SetVector<CallSite> CallSites; SetVector<Value *> Loads; SetVector<Value *> Stores; for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I) if (I->getType()->isPointerTy()) // Add all pointer arguments. Pointers.insert(I); for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) { if (I->getType()->isPointerTy()) // Add all pointer instructions. Pointers.insert(&*I); if (EvalTBAA && isa<LoadInst>(&*I)) Loads.insert(&*I); if (EvalTBAA && isa<StoreInst>(&*I)) Stores.insert(&*I); Instruction &Inst = *I; if (CallSite CS = cast<Value>(&Inst)) { Value *Callee = CS.getCalledValue(); // Skip actual functions for direct function calls. if (!isa<Function>(Callee) && isInterestingPointer(Callee)) Pointers.insert(Callee); // Consider formals. for (CallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end(); AI != AE; ++AI) if (isInterestingPointer(*AI)) Pointers.insert(*AI); CallSites.insert(CS); } else { // Consider all operands. for (Instruction::op_iterator OI = Inst.op_begin(), OE = Inst.op_end(); OI != OE; ++OI) if (isInterestingPointer(*OI)) Pointers.insert(*OI); } } if (PrintNoAlias || PrintMayAlias || PrintPartialAlias || PrintMustAlias || PrintNoModRef || PrintMod || PrintRef || PrintModRef) errs() << "Function: " << F.getName() << ": " << Pointers.size() << " pointers, " << CallSites.size() << " call sites\n"; // iterate over the worklist, and run the full (n^2)/2 disambiguations for (SetVector<Value *>::iterator I1 = Pointers.begin(), E = Pointers.end(); I1 != E; ++I1) { uint64_t I1Size = AliasAnalysis::UnknownSize; Type *I1ElTy = cast<PointerType>((*I1)->getType())->getElementType(); if (I1ElTy->isSized()) I1Size = AA.getTypeStoreSize(I1ElTy); for (SetVector<Value *>::iterator I2 = Pointers.begin(); I2 != I1; ++I2) { uint64_t I2Size = AliasAnalysis::UnknownSize; Type *I2ElTy =cast<PointerType>((*I2)->getType())->getElementType(); if (I2ElTy->isSized()) I2Size = AA.getTypeStoreSize(I2ElTy); switch (AA.alias(*I1, I1Size, *I2, I2Size)) { case AliasAnalysis::NoAlias: PrintResults("NoAlias", PrintNoAlias, *I1, *I2, F.getParent()); ++NoAlias; break; case AliasAnalysis::MayAlias: PrintResults("MayAlias", PrintMayAlias, *I1, *I2, F.getParent()); ++MayAlias; break; case AliasAnalysis::PartialAlias: PrintResults("PartialAlias", PrintPartialAlias, *I1, *I2, F.getParent()); ++PartialAlias; break; case AliasAnalysis::MustAlias: PrintResults("MustAlias", PrintMustAlias, *I1, *I2, F.getParent()); ++MustAlias; break; } } } if (EvalTBAA) { // iterate over all pairs of load, store for (SetVector<Value *>::iterator I1 = Loads.begin(), E = Loads.end(); I1 != E; ++I1) { for (SetVector<Value *>::iterator I2 = Stores.begin(), E2 = Stores.end(); I2 != E2; ++I2) { switch (AA.alias(AA.getLocation(cast<LoadInst>(*I1)), AA.getLocation(cast<StoreInst>(*I2)))) { case AliasAnalysis::NoAlias: PrintLoadStoreResults("NoAlias", PrintNoAlias, *I1, *I2, F.getParent()); ++NoAlias; break; case AliasAnalysis::MayAlias: PrintLoadStoreResults("MayAlias", PrintMayAlias, *I1, *I2, F.getParent()); ++MayAlias; break; case AliasAnalysis::PartialAlias: PrintLoadStoreResults("PartialAlias", PrintPartialAlias, *I1, *I2, F.getParent()); ++PartialAlias; break; case AliasAnalysis::MustAlias: PrintLoadStoreResults("MustAlias", PrintMustAlias, *I1, *I2, F.getParent()); ++MustAlias; break; } } } // iterate over all pairs of store, store for (SetVector<Value *>::iterator I1 = Stores.begin(), E = Stores.end(); I1 != E; ++I1) { for (SetVector<Value *>::iterator I2 = Stores.begin(); I2 != I1; ++I2) { switch (AA.alias(AA.getLocation(cast<StoreInst>(*I1)), AA.getLocation(cast<StoreInst>(*I2)))) { case AliasAnalysis::NoAlias: PrintLoadStoreResults("NoAlias", PrintNoAlias, *I1, *I2, F.getParent()); ++NoAlias; break; case AliasAnalysis::MayAlias: PrintLoadStoreResults("MayAlias", PrintMayAlias, *I1, *I2, F.getParent()); ++MayAlias; break; case AliasAnalysis::PartialAlias: PrintLoadStoreResults("PartialAlias", PrintPartialAlias, *I1, *I2, F.getParent()); ++PartialAlias; break; case AliasAnalysis::MustAlias: PrintLoadStoreResults("MustAlias", PrintMustAlias, *I1, *I2, F.getParent()); ++MustAlias; break; } } } } // Mod/ref alias analysis: compare all pairs of calls and values for (SetVector<CallSite>::iterator C = CallSites.begin(), Ce = CallSites.end(); C != Ce; ++C) { Instruction *I = C->getInstruction(); for (SetVector<Value *>::iterator V = Pointers.begin(), Ve = Pointers.end(); V != Ve; ++V) { uint64_t Size = AliasAnalysis::UnknownSize; Type *ElTy = cast<PointerType>((*V)->getType())->getElementType(); if (ElTy->isSized()) Size = AA.getTypeStoreSize(ElTy); switch (AA.getModRefInfo(*C, *V, Size)) { case AliasAnalysis::NoModRef: PrintModRefResults("NoModRef", PrintNoModRef, I, *V, F.getParent()); ++NoModRef; break; case AliasAnalysis::Mod: PrintModRefResults("Just Mod", PrintMod, I, *V, F.getParent()); ++Mod; break; case AliasAnalysis::Ref: PrintModRefResults("Just Ref", PrintRef, I, *V, F.getParent()); ++Ref; break; case AliasAnalysis::ModRef: PrintModRefResults("Both ModRef", PrintModRef, I, *V, F.getParent()); ++ModRef; break; } } } // Mod/ref alias analysis: compare all pairs of calls for (SetVector<CallSite>::iterator C = CallSites.begin(), Ce = CallSites.end(); C != Ce; ++C) { for (SetVector<CallSite>::iterator D = CallSites.begin(); D != Ce; ++D) { if (D == C) continue; switch (AA.getModRefInfo(*C, *D)) { case AliasAnalysis::NoModRef: PrintModRefResults("NoModRef", PrintNoModRef, *C, *D, F.getParent()); ++NoModRef; break; case AliasAnalysis::Mod: PrintModRefResults("Just Mod", PrintMod, *C, *D, F.getParent()); ++Mod; break; case AliasAnalysis::Ref: PrintModRefResults("Just Ref", PrintRef, *C, *D, F.getParent()); ++Ref; break; case AliasAnalysis::ModRef: PrintModRefResults("Both ModRef", PrintModRef, *C, *D, F.getParent()); ++ModRef; break; } } } return false; }