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; }
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())); }
/// \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; }
// Traverse the DFG and collect the set dead RefNodes and the set of // dead instructions. Return "true" if any of these sets is non-empty, // "false" otherwise. bool DeadCodeElimination::collect() { // This function works by first finding all live nodes. The dead nodes // are then the complement of the set of live nodes. // // Assume that all nodes are dead. Identify instructions which must be // considered live, i.e. instructions with observable side-effects, such // as calls and stores. All arguments of such instructions are considered // live. For each live def, all operands used in the corresponding // instruction are considered live. For each live use, all its reaching // defs are considered live. LiveNodes.clear(); SetVector<NodeId> WorkQ; for (NodeAddr<BlockNode*> BA : DFG.getFunc().Addr->members(DFG)) for (NodeAddr<InstrNode*> IA : BA.Addr->members(DFG)) scanInstr(IA, WorkQ); while (!WorkQ.empty()) { NodeId N = *WorkQ.begin(); WorkQ.remove(N); LiveNodes.insert(N); auto RA = DFG.addr<RefNode*>(N); if (DFG.IsDef(RA)) processDef(RA, WorkQ); else processUse(RA, WorkQ); } if (trace()) { dbgs() << "Live nodes:\n"; for (NodeId N : LiveNodes) { auto RA = DFG.addr<RefNode*>(N); dbgs() << PrintNode<RefNode*>(RA, DFG) << "\n"; } } auto IsDead = [this] (NodeAddr<InstrNode*> IA) -> bool { for (NodeAddr<DefNode*> DA : IA.Addr->members_if(DFG.IsDef, DFG)) if (LiveNodes.count(DA.Id)) return false; return true; }; for (NodeAddr<BlockNode*> BA : DFG.getFunc().Addr->members(DFG)) { for (NodeAddr<InstrNode*> IA : BA.Addr->members(DFG)) { for (NodeAddr<RefNode*> RA : IA.Addr->members(DFG)) if (!LiveNodes.count(RA.Id)) DeadNodes.insert(RA.Id); if (DFG.IsCode<NodeAttrs::Stmt>(IA)) if (isLiveInstr(NodeAddr<StmtNode*>(IA).Addr->getCode())) continue; if (IsDead(IA)) { DeadInstrs.insert(IA.Id); if (trace()) dbgs() << "Dead instr: " << PrintNode<InstrNode*>(IA, DFG) << "\n"; } } } return !DeadNodes.empty(); }
SetVector<Value*> qdp_jit_vec::get_stores( SetVector<Value*> Vec ) { SetVector<Value*> stores; for (Value* V : Vec) { SetVector<Value*> tmp = get_stores( V ); stores.insert( tmp.begin() , tmp.end() ); } return stores; }
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; }
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; }
// // 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 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; }
// // 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; // Differentially encoded lists. SequenceToOffsetTable<DiffVec> DiffSeqs; SmallVector<DiffVec, 4> SubRegLists(Regs.size()); SmallVector<DiffVec, 4> SuperRegLists(Regs.size()); SmallVector<DiffVec, 4> OverlapLists(Regs.size()); SmallVector<DiffVec, 4> RegUnitLists(Regs.size()); SmallVector<unsigned, 4> RegUnitInitScale(Regs.size()); // Keep track of sub-register names as well. These are not differentially // encoded. typedef SmallVector<const CodeGenSubRegIndex*, 4> SubRegIdxVec; SequenceToOffsetTable<SubRegIdxVec> SubRegIdxSeqs; SmallVector<SubRegIdxVec, 4> SubRegIdxLists(Regs.size()); SequenceToOffsetTable<std::string> RegStrings; // Precompute register lists for the SequenceToOffsetTable. for (unsigned i = 0, e = Regs.size(); i != e; ++i) { const CodeGenRegister *Reg = Regs[i]; RegStrings.add(Reg->getName()); // Compute the ordered sub-register list. SetVector<const CodeGenRegister*> SR; Reg->addSubRegsPreOrder(SR, RegBank); diffEncode(SubRegLists[i], Reg->EnumValue, SR.begin(), SR.end()); DiffSeqs.add(SubRegLists[i]); // Compute the corresponding sub-register indexes. SubRegIdxVec &SRIs = SubRegIdxLists[i]; for (unsigned j = 0, je = SR.size(); j != je; ++j) SRIs.push_back(Reg->getSubRegIndex(SR[j])); SubRegIdxSeqs.add(SRIs); // Super-registers are already computed. const RegVec &SuperRegList = Reg->getSuperRegs(); diffEncode(SuperRegLists[i], Reg->EnumValue, SuperRegList.begin(), SuperRegList.end()); DiffSeqs.add(SuperRegLists[i]); // The list of overlaps doesn't need to have any particular order, and Reg // itself must be omitted. DiffVec &OverlapList = OverlapLists[i]; CodeGenRegister::Set OSet; Reg->computeOverlaps(OSet, RegBank); OSet.erase(Reg); diffEncode(OverlapList, Reg->EnumValue, OSet.begin(), OSet.end()); DiffSeqs.add(OverlapList); // Differentially encode the register unit list, seeded by register number. // First compute a scale factor that allows more diff-lists to be reused: // // D0 -> (S0, S1) // D1 -> (S2, S3) // // A scale factor of 2 allows D0 and D1 to share a diff-list. The initial // value for the differential decoder is the register number multiplied by // the scale. // // Check the neighboring registers for arithmetic progressions. unsigned ScaleA = ~0u, ScaleB = ~0u; ArrayRef<unsigned> RUs = Reg->getNativeRegUnits(); if (i > 0 && Regs[i-1]->getNativeRegUnits().size() == RUs.size()) ScaleB = RUs.front() - Regs[i-1]->getNativeRegUnits().front(); if (i+1 != Regs.size() && Regs[i+1]->getNativeRegUnits().size() == RUs.size()) ScaleA = Regs[i+1]->getNativeRegUnits().front() - RUs.front(); unsigned Scale = std::min(ScaleB, ScaleA); // Default the scale to 0 if it can't be encoded in 4 bits. if (Scale >= 16) Scale = 0; RegUnitInitScale[i] = Scale; DiffSeqs.add(diffEncode(RegUnitLists[i], Scale * Reg->EnumValue, RUs)); } // Compute the final layout of the sequence table. DiffSeqs.layout(); SubRegIdxSeqs.layout(); OS << "namespace llvm {\n\n"; const std::string &TargetName = Target.getName(); // Emit the shared table of differential lists. OS << "extern const uint16_t " << TargetName << "RegDiffLists[] = {\n"; DiffSeqs.emit(OS, printDiff16); OS << "};\n\n"; // Emit the table of sub-register indexes. OS << "extern const uint16_t " << TargetName << "SubRegIdxLists[] = {\n"; SubRegIdxSeqs.emit(OS, printSubRegIndex); OS << "};\n\n"; // Emit the string table. RegStrings.layout(); OS << "extern const char " << TargetName << "RegStrings[] = {\n"; RegStrings.emit(OS, printChar); OS << "};\n\n"; OS << "extern const MCRegisterDesc " << TargetName << "RegDesc[] = { // Descriptors\n"; OS << " { " << RegStrings.get("") << ", 0, 0, 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 << " { " << RegStrings.get(Reg->getName()) << ", " << DiffSeqs.get(OverlapLists[i]) << ", " << DiffSeqs.get(SubRegLists[i]) << ", " << DiffSeqs.get(SuperRegLists[i]) << ", " << SubRegIdxSeqs.get(SubRegIdxLists[i]) << ", " << (DiffSeqs.get(RegUnitLists[i])*16 + RegUnitInitScale[i]) << " },\n"; } OS << "};\n\n"; // End of register descriptors... // Emit the table of register unit roots. Each regunit has one or two root // registers. OS << "extern const uint16_t " << TargetName << "RegUnitRoots[][2] = {\n"; for (unsigned i = 0, e = RegBank.getNumNativeRegUnits(); i != e; ++i) { ArrayRef<const CodeGenRegister*> Roots = RegBank.getRegUnit(i).getRoots(); assert(!Roots.empty() && "All regunits must have a root register."); assert(Roots.size() <= 2 && "More than two roots not supported yet."); OS << " { " << getQualifiedName(Roots.front()->TheDef); for (unsigned r = 1; r != Roots.size(); ++r) OS << ", " << getQualifiedName(Roots[r]->TheDef); OS << " },\n"; } OS << "};\n\n"; 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"; ArrayRef<CodeGenSubRegIndex*> SubRegIndices = RegBank.getSubRegIndices(); 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" << " RI->InitMCRegisterInfo(" << TargetName << "RegDesc, " << Regs.size()+1 << ", RA, " << TargetName << "MCRegisterClasses, " << RegisterClasses.size() << ", " << TargetName << "RegUnitRoots, " << RegBank.getNumNativeRegUnits() << ", " << TargetName << "RegDiffLists, " << TargetName << "RegStrings, " << TargetName << "SubRegIdxLists, " << SubRegIndices.size() << ",\n" << " " << TargetName << "RegEncodingTable);\n\n"; EmitRegMapping(OS, Regs, false); OS << "}\n\n"; OS << "} // End llvm namespace \n"; OS << "#endif // GET_REGINFO_MC_DESC\n\n"; }
NodeList Liveness::getAllReachingDefs(RegisterRef RefRR, NodeAddr<RefNode*> RefA, bool FullChain, const RegisterSet &DefRRs) { SetVector<NodeId> DefQ; SetVector<NodeId> Owners; // The initial queue should not have reaching defs for shadows. The // whole point of a shadow is that it will have a reaching def that // is not aliased to the reaching defs of the related shadows. NodeId Start = RefA.Id; auto SNA = DFG.addr<RefNode*>(Start); if (NodeId RD = SNA.Addr->getReachingDef()) DefQ.insert(RD); // Collect all the reaching defs, going up until a phi node is encountered, // or there are no more reaching defs. From this set, the actual set of // reaching defs will be selected. // The traversal upwards must go on until a covering def is encountered. // It is possible that a collection of non-covering (individually) defs // will be sufficient, but keep going until a covering one is found. for (unsigned i = 0; i < DefQ.size(); ++i) { auto TA = DFG.addr<DefNode*>(DefQ[i]); if (TA.Addr->getFlags() & NodeAttrs::PhiRef) continue; // Stop at the covering/overwriting def of the initial register reference. RegisterRef RR = TA.Addr->getRegRef(); if (RAI.covers(RR, RefRR)) { uint16_t Flags = TA.Addr->getFlags(); if (!(Flags & NodeAttrs::Preserving)) continue; } // Get the next level of reaching defs. This will include multiple // reaching defs for shadows. for (auto S : DFG.getRelatedRefs(TA.Addr->getOwner(DFG), TA)) if (auto RD = NodeAddr<RefNode*>(S).Addr->getReachingDef()) DefQ.insert(RD); } // Remove all non-phi defs that are not aliased to RefRR, and collect // the owners of the remaining defs. SetVector<NodeId> Defs; for (auto N : DefQ) { auto TA = DFG.addr<DefNode*>(N); bool IsPhi = TA.Addr->getFlags() & NodeAttrs::PhiRef; if (!IsPhi && !RAI.alias(RefRR, TA.Addr->getRegRef())) continue; Defs.insert(TA.Id); Owners.insert(TA.Addr->getOwner(DFG).Id); } // Return the MachineBasicBlock containing a given instruction. auto Block = [this] (NodeAddr<InstrNode*> IA) -> MachineBasicBlock* { if (IA.Addr->getKind() == NodeAttrs::Stmt) return NodeAddr<StmtNode*>(IA).Addr->getCode()->getParent(); assert(IA.Addr->getKind() == NodeAttrs::Phi); NodeAddr<PhiNode*> PA = IA; NodeAddr<BlockNode*> BA = PA.Addr->getOwner(DFG); return BA.Addr->getCode(); }; // Less(A,B) iff instruction A is further down in the dominator tree than B. auto Less = [&Block,this] (NodeId A, NodeId B) -> bool { if (A == B) return false; auto OA = DFG.addr<InstrNode*>(A), OB = DFG.addr<InstrNode*>(B); MachineBasicBlock *BA = Block(OA), *BB = Block(OB); if (BA != BB) return MDT.dominates(BB, BA); // They are in the same block. bool StmtA = OA.Addr->getKind() == NodeAttrs::Stmt; bool StmtB = OB.Addr->getKind() == NodeAttrs::Stmt; if (StmtA) { if (!StmtB) // OB is a phi and phis dominate statements. return true; auto CA = NodeAddr<StmtNode*>(OA).Addr->getCode(); auto CB = NodeAddr<StmtNode*>(OB).Addr->getCode(); // The order must be linear, so tie-break such equalities. if (CA == CB) return A < B; return MDT.dominates(CB, CA); } else { // OA is a phi. if (StmtB) return false; // Both are phis. There is no ordering between phis (in terms of // the data-flow), so tie-break this via node id comparison. return A < B; } }; std::vector<NodeId> Tmp(Owners.begin(), Owners.end()); std::sort(Tmp.begin(), Tmp.end(), Less); // The vector is a list of instructions, so that defs coming from // the same instruction don't need to be artificially ordered. // Then, when computing the initial segment, and iterating over an // instruction, pick the defs that contribute to the covering (i.e. is // not covered by previously added defs). Check the defs individually, // i.e. first check each def if is covered or not (without adding them // to the tracking set), and then add all the selected ones. // The reason for this is this example: // *d1<A>, *d2<B>, ... Assume A and B are aliased (can happen in phi nodes). // *d3<C> If A \incl BuC, and B \incl AuC, then *d2 would be // covered if we added A first, and A would be covered // if we added B first. NodeList RDefs; RegisterSet RRs = DefRRs; auto DefInSet = [&Defs] (NodeAddr<RefNode*> TA) -> bool { return TA.Addr->getKind() == NodeAttrs::Def && Defs.count(TA.Id); }; for (auto T : Tmp) { if (!FullChain && RAI.covers(RRs, RefRR)) break; auto TA = DFG.addr<InstrNode*>(T); bool IsPhi = DFG.IsCode<NodeAttrs::Phi>(TA); NodeList Ds; for (NodeAddr<DefNode*> DA : TA.Addr->members_if(DefInSet, DFG)) { auto QR = DA.Addr->getRegRef(); // Add phi defs even if they are covered by subsequent defs. This is // for cases where the reached use is not covered by any of the defs // encountered so far: the phi def is needed to expose the liveness // of that use to the entry of the block. // Example: // phi d1<R3>(,d2,), ... Phi def d1 is covered by d2. // d2<R3>(d1,,u3), ... // ..., u3<D1>(d2) This use needs to be live on entry. if (FullChain || IsPhi || !RAI.covers(RRs, QR)) Ds.push_back(DA); } RDefs.insert(RDefs.end(), Ds.begin(), Ds.end()); for (NodeAddr<DefNode*> DA : Ds) { // When collecting a full chain of definitions, do not consider phi // defs to actually define a register. uint16_t Flags = DA.Addr->getFlags(); if (!FullChain || !(Flags & NodeAttrs::PhiRef)) if (!(Flags & NodeAttrs::Preserving)) RRs.insert(DA.Addr->getRegRef()); } } return RDefs; }
bool WebAssemblyFixIrreducibleControlFlow::VisitLoop(MachineFunction &MF, MachineLoopInfo &MLI, MachineLoop *Loop) { MachineBasicBlock *Header = Loop ? Loop->getHeader() : &*MF.begin(); SetVector<MachineBasicBlock *> RewriteSuccs; // DFS through Loop's body, looking for for irreducible control flow. Loop is // natural, and we stay in its body, and we treat any nested loops // monolithically, so any cycles we encounter indicate irreducibility. SmallPtrSet<MachineBasicBlock *, 8> OnStack; SmallPtrSet<MachineBasicBlock *, 8> Visited; SmallVector<SuccessorList, 4> LoopWorklist; LoopWorklist.push_back(SuccessorList(Header)); OnStack.insert(Header); Visited.insert(Header); while (!LoopWorklist.empty()) { SuccessorList &Top = LoopWorklist.back(); if (Top.HasNext()) { MachineBasicBlock *Next = Top.Next(); if (Next == Header || (Loop && !Loop->contains(Next))) continue; if (LLVM_LIKELY(OnStack.insert(Next).second)) { if (!Visited.insert(Next).second) { OnStack.erase(Next); continue; } MachineLoop *InnerLoop = MLI.getLoopFor(Next); if (InnerLoop != Loop) LoopWorklist.push_back(SuccessorList(InnerLoop)); else LoopWorklist.push_back(SuccessorList(Next)); } else { RewriteSuccs.insert(Top.getBlock()); } continue; } OnStack.erase(Top.getBlock()); LoopWorklist.pop_back(); } // Most likely, we didn't find any irreducible control flow. if (LLVM_LIKELY(RewriteSuccs.empty())) return false; DEBUG(dbgs() << "Irreducible control flow detected!\n"); // Ok. We have irreducible control flow! Create a dispatch block which will // contains a jump table to any block in the problematic set of blocks. MachineBasicBlock *Dispatch = MF.CreateMachineBasicBlock(); MF.insert(MF.end(), Dispatch); MLI.changeLoopFor(Dispatch, Loop); // Add the jump table. const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo(); MachineInstrBuilder MIB = BuildMI(*Dispatch, Dispatch->end(), DebugLoc(), TII.get(WebAssembly::BR_TABLE_I32)); // Add the register which will be used to tell the jump table which block to // jump to. MachineRegisterInfo &MRI = MF.getRegInfo(); unsigned Reg = MRI.createVirtualRegister(&WebAssembly::I32RegClass); MIB.addReg(Reg); // Collect all the blocks which need to have their successors rewritten, // add the successors to the jump table, and remember their index. DenseMap<MachineBasicBlock *, unsigned> Indices; SmallVector<MachineBasicBlock *, 4> SuccWorklist(RewriteSuccs.begin(), RewriteSuccs.end()); while (!SuccWorklist.empty()) { MachineBasicBlock *MBB = SuccWorklist.pop_back_val(); auto Pair = Indices.insert(std::make_pair(MBB, 0)); if (!Pair.second) continue; unsigned Index = MIB.getInstr()->getNumExplicitOperands() - 1; DEBUG(dbgs() << printMBBReference(*MBB) << " has index " << Index << "\n"); Pair.first->second = Index; for (auto Pred : MBB->predecessors()) RewriteSuccs.insert(Pred); MIB.addMBB(MBB); Dispatch->addSuccessor(MBB); MetaBlock Meta(MBB); for (auto *Succ : Meta.successors()) if (Succ != Header && (!Loop || Loop->contains(Succ))) SuccWorklist.push_back(Succ); } // Rewrite the problematic successors for every block in RewriteSuccs. // For simplicity, we just introduce a new block for every edge we need to // rewrite. Fancier things are possible. for (MachineBasicBlock *MBB : RewriteSuccs) { DenseMap<MachineBasicBlock *, MachineBasicBlock *> Map; for (auto *Succ : MBB->successors()) { if (!Indices.count(Succ)) continue; MachineBasicBlock *Split = MF.CreateMachineBasicBlock(); MF.insert(MBB->isLayoutSuccessor(Succ) ? MachineFunction::iterator(Succ) : MF.end(), Split); MLI.changeLoopFor(Split, Loop); // Set the jump table's register of the index of the block we wish to // jump to, and jump to the jump table. BuildMI(*Split, Split->end(), DebugLoc(), TII.get(WebAssembly::CONST_I32), Reg) .addImm(Indices[Succ]); BuildMI(*Split, Split->end(), DebugLoc(), TII.get(WebAssembly::BR)) .addMBB(Dispatch); Split->addSuccessor(Dispatch); Map[Succ] = Split; } // Remap the terminator operands and the successor list. for (MachineInstr &Term : MBB->terminators()) for (auto &Op : Term.explicit_uses()) if (Op.isMBB() && Indices.count(Op.getMBB())) Op.setMBB(Map[Op.getMBB()]); for (auto Rewrite : Map) MBB->replaceSuccessor(Rewrite.first, Rewrite.second); } // Create a fake default label, because br_table requires one. MIB.addMBB(MIB.getInstr() ->getOperand(MIB.getInstr()->getNumExplicitOperands() - 1) .getMBB()); return true; }
int main(int argc, char **argv) { // Print a stack trace if we signal out. sys::PrintStackTraceOnErrorSignal(argv[0]); PrettyStackTraceProgram X(argc, argv); LLVMContext Context; llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. cl::ParseCommandLineOptions(argc, argv, "llvm extractor\n"); // Use lazy loading, since we only care about selected global values. SMDiagnostic Err; std::unique_ptr<Module> M = getLazyIRFileModule(InputFilename, Err, Context); if (!M.get()) { Err.print(argv[0], errs()); return 1; } // Use SetVector to avoid duplicates. SetVector<GlobalValue *> GVs; // Figure out which aliases we should extract. for (size_t i = 0, e = ExtractAliases.size(); i != e; ++i) { GlobalAlias *GA = M->getNamedAlias(ExtractAliases[i]); if (!GA) { errs() << argv[0] << ": program doesn't contain alias named '" << ExtractAliases[i] << "'!\n"; return 1; } GVs.insert(GA); } // Extract aliases via regular expression matching. for (size_t i = 0, e = ExtractRegExpAliases.size(); i != e; ++i) { std::string Error; Regex RegEx(ExtractRegExpAliases[i]); if (!RegEx.isValid(Error)) { errs() << argv[0] << ": '" << ExtractRegExpAliases[i] << "' " "invalid regex: " << Error; } bool match = false; for (Module::alias_iterator GA = M->alias_begin(), E = M->alias_end(); GA != E; GA++) { if (RegEx.match(GA->getName())) { GVs.insert(&*GA); match = true; } } if (!match) { errs() << argv[0] << ": program doesn't contain global named '" << ExtractRegExpAliases[i] << "'!\n"; return 1; } } // Figure out which globals we should extract. for (size_t i = 0, e = ExtractGlobals.size(); i != e; ++i) { GlobalValue *GV = M->getNamedGlobal(ExtractGlobals[i]); if (!GV) { errs() << argv[0] << ": program doesn't contain global named '" << ExtractGlobals[i] << "'!\n"; return 1; } GVs.insert(GV); } // Extract globals via regular expression matching. for (size_t i = 0, e = ExtractRegExpGlobals.size(); i != e; ++i) { std::string Error; Regex RegEx(ExtractRegExpGlobals[i]); if (!RegEx.isValid(Error)) { errs() << argv[0] << ": '" << ExtractRegExpGlobals[i] << "' " "invalid regex: " << Error; } bool match = false; for (auto &GV : M->globals()) { if (RegEx.match(GV.getName())) { GVs.insert(&GV); match = true; } } if (!match) { errs() << argv[0] << ": program doesn't contain global named '" << ExtractRegExpGlobals[i] << "'!\n"; return 1; } } // Figure out which functions we should extract. for (size_t i = 0, e = ExtractFuncs.size(); i != e; ++i) { GlobalValue *GV = M->getFunction(ExtractFuncs[i]); if (!GV) { errs() << argv[0] << ": program doesn't contain function named '" << ExtractFuncs[i] << "'!\n"; return 1; } GVs.insert(GV); } // Extract functions via regular expression matching. for (size_t i = 0, e = ExtractRegExpFuncs.size(); i != e; ++i) { std::string Error; StringRef RegExStr = ExtractRegExpFuncs[i]; Regex RegEx(RegExStr); if (!RegEx.isValid(Error)) { errs() << argv[0] << ": '" << ExtractRegExpFuncs[i] << "' " "invalid regex: " << Error; } bool match = false; for (Module::iterator F = M->begin(), E = M->end(); F != E; F++) { if (RegEx.match(F->getName())) { GVs.insert(&*F); match = true; } } if (!match) { errs() << argv[0] << ": program doesn't contain global named '" << ExtractRegExpFuncs[i] << "'!\n"; return 1; } } auto Materialize = [&](GlobalValue &GV) { if (std::error_code EC = GV.materialize()) { errs() << argv[0] << ": error reading input: " << EC.message() << "\n"; exit(1); } }; // Materialize requisite global values. if (!DeleteFn) { for (size_t i = 0, e = GVs.size(); i != e; ++i) Materialize(*GVs[i]); } else { // Deleting. Materialize every GV that's *not* in GVs. SmallPtrSet<GlobalValue *, 8> GVSet(GVs.begin(), GVs.end()); for (auto &F : *M) { if (!GVSet.count(&F)) Materialize(F); } } { std::vector<GlobalValue *> Gvs(GVs.begin(), GVs.end()); legacy::PassManager Extract; Extract.add(createGVExtractionPass(Gvs, DeleteFn)); Extract.run(*M); // Now that we have all the GVs we want, mark the module as fully // materialized. // FIXME: should the GVExtractionPass handle this? M->materializeAll(); } // In addition to deleting all other functions, we also want to spiff it // up a little bit. Do this now. legacy::PassManager Passes; if (!DeleteFn) Passes.add(createGlobalDCEPass()); // Delete unreachable globals Passes.add(createStripDeadDebugInfoPass()); // Remove dead debug info Passes.add(createStripDeadPrototypesPass()); // Remove dead func decls std::error_code EC; tool_output_file Out(OutputFilename, EC, sys::fs::F_None); if (EC) { errs() << EC.message() << '\n'; return 1; } if (OutputAssembly) Passes.add( createPrintModulePass(Out.os(), "", PreserveAssemblyUseListOrder)); else if (Force || !CheckBitcodeOutputToConsole(Out.os(), true)) Passes.add(createBitcodeWriterPass(Out.os(), PreserveBitcodeUseListOrder)); Passes.run(*M.get()); // Declare success. Out.keep(); return 0; }
int main(int argc, char **argv) { InitLLVM X(argc, argv); LLVMContext Context; cl::ParseCommandLineOptions(argc, argv, "llvm extractor\n"); // Use lazy loading, since we only care about selected global values. SMDiagnostic Err; std::unique_ptr<Module> M = getLazyIRFileModule(InputFilename, Err, Context); if (!M.get()) { Err.print(argv[0], errs()); return 1; } // Use SetVector to avoid duplicates. SetVector<GlobalValue *> GVs; // Figure out which aliases we should extract. for (size_t i = 0, e = ExtractAliases.size(); i != e; ++i) { GlobalAlias *GA = M->getNamedAlias(ExtractAliases[i]); if (!GA) { errs() << argv[0] << ": program doesn't contain alias named '" << ExtractAliases[i] << "'!\n"; return 1; } GVs.insert(GA); } // Extract aliases via regular expression matching. for (size_t i = 0, e = ExtractRegExpAliases.size(); i != e; ++i) { std::string Error; Regex RegEx(ExtractRegExpAliases[i]); if (!RegEx.isValid(Error)) { errs() << argv[0] << ": '" << ExtractRegExpAliases[i] << "' " "invalid regex: " << Error; } bool match = false; for (Module::alias_iterator GA = M->alias_begin(), E = M->alias_end(); GA != E; GA++) { if (RegEx.match(GA->getName())) { GVs.insert(&*GA); match = true; } } if (!match) { errs() << argv[0] << ": program doesn't contain global named '" << ExtractRegExpAliases[i] << "'!\n"; return 1; } } // Figure out which globals we should extract. for (size_t i = 0, e = ExtractGlobals.size(); i != e; ++i) { GlobalValue *GV = M->getNamedGlobal(ExtractGlobals[i]); if (!GV) { errs() << argv[0] << ": program doesn't contain global named '" << ExtractGlobals[i] << "'!\n"; return 1; } GVs.insert(GV); } // Extract globals via regular expression matching. for (size_t i = 0, e = ExtractRegExpGlobals.size(); i != e; ++i) { std::string Error; Regex RegEx(ExtractRegExpGlobals[i]); if (!RegEx.isValid(Error)) { errs() << argv[0] << ": '" << ExtractRegExpGlobals[i] << "' " "invalid regex: " << Error; } bool match = false; for (auto &GV : M->globals()) { if (RegEx.match(GV.getName())) { GVs.insert(&GV); match = true; } } if (!match) { errs() << argv[0] << ": program doesn't contain global named '" << ExtractRegExpGlobals[i] << "'!\n"; return 1; } } // Figure out which functions we should extract. for (size_t i = 0, e = ExtractFuncs.size(); i != e; ++i) { GlobalValue *GV = M->getFunction(ExtractFuncs[i]); if (!GV) { errs() << argv[0] << ": program doesn't contain function named '" << ExtractFuncs[i] << "'!\n"; return 1; } GVs.insert(GV); } // Extract functions via regular expression matching. for (size_t i = 0, e = ExtractRegExpFuncs.size(); i != e; ++i) { std::string Error; StringRef RegExStr = ExtractRegExpFuncs[i]; Regex RegEx(RegExStr); if (!RegEx.isValid(Error)) { errs() << argv[0] << ": '" << ExtractRegExpFuncs[i] << "' " "invalid regex: " << Error; } bool match = false; for (Module::iterator F = M->begin(), E = M->end(); F != E; F++) { if (RegEx.match(F->getName())) { GVs.insert(&*F); match = true; } } if (!match) { errs() << argv[0] << ": program doesn't contain global named '" << ExtractRegExpFuncs[i] << "'!\n"; return 1; } } // Figure out which BasicBlocks we should extract. SmallVector<BasicBlock *, 4> BBs; for (StringRef StrPair : ExtractBlocks) { auto BBInfo = StrPair.split(':'); // Get the function. Function *F = M->getFunction(BBInfo.first); if (!F) { errs() << argv[0] << ": program doesn't contain a function named '" << BBInfo.first << "'!\n"; return 1; } // Do not materialize this function. GVs.insert(F); // Get the basic block. auto Res = llvm::find_if(*F, [&](const BasicBlock &BB) { return BB.getName().equals(BBInfo.second); }); if (Res == F->end()) { errs() << argv[0] << ": function " << F->getName() << " doesn't contain a basic block named '" << BBInfo.second << "'!\n"; return 1; } BBs.push_back(&*Res); } // Use *argv instead of argv[0] to work around a wrong GCC warning. ExitOnError ExitOnErr(std::string(*argv) + ": error reading input: "); if (Recursive) { std::vector<llvm::Function *> Workqueue; for (GlobalValue *GV : GVs) { if (auto *F = dyn_cast<Function>(GV)) { Workqueue.push_back(F); } } while (!Workqueue.empty()) { Function *F = &*Workqueue.back(); Workqueue.pop_back(); ExitOnErr(F->materialize()); for (auto &BB : *F) { for (auto &I : BB) { auto *CI = dyn_cast<CallInst>(&I); if (!CI) continue; Function *CF = CI->getCalledFunction(); if (!CF) continue; if (CF->isDeclaration() || GVs.count(CF)) continue; GVs.insert(CF); Workqueue.push_back(CF); } } } } auto Materialize = [&](GlobalValue &GV) { ExitOnErr(GV.materialize()); }; // Materialize requisite global values. if (!DeleteFn) { for (size_t i = 0, e = GVs.size(); i != e; ++i) Materialize(*GVs[i]); } else { // Deleting. Materialize every GV that's *not* in GVs. SmallPtrSet<GlobalValue *, 8> GVSet(GVs.begin(), GVs.end()); for (auto &F : *M) { if (!GVSet.count(&F)) Materialize(F); } } { std::vector<GlobalValue *> Gvs(GVs.begin(), GVs.end()); legacy::PassManager Extract; Extract.add(createGVExtractionPass(Gvs, DeleteFn)); Extract.run(*M); // Now that we have all the GVs we want, mark the module as fully // materialized. // FIXME: should the GVExtractionPass handle this? ExitOnErr(M->materializeAll()); } // Extract the specified basic blocks from the module and erase the existing // functions. if (!ExtractBlocks.empty()) { legacy::PassManager PM; PM.add(createBlockExtractorPass(BBs, true)); PM.run(*M); } // In addition to deleting all other functions, we also want to spiff it // up a little bit. Do this now. legacy::PassManager Passes; if (!DeleteFn) Passes.add(createGlobalDCEPass()); // Delete unreachable globals Passes.add(createStripDeadDebugInfoPass()); // Remove dead debug info Passes.add(createStripDeadPrototypesPass()); // Remove dead func decls std::error_code EC; ToolOutputFile Out(OutputFilename, EC, sys::fs::F_None); if (EC) { errs() << EC.message() << '\n'; return 1; } if (OutputAssembly) Passes.add( createPrintModulePass(Out.os(), "", PreserveAssemblyUseListOrder)); else if (Force || !CheckBitcodeOutputToConsole(Out.os(), true)) Passes.add(createBitcodeWriterPass(Out.os(), PreserveBitcodeUseListOrder)); Passes.run(*M.get()); // Declare success. Out.keep(); return 0; }
int main(int argc, char **argv) { // Print a stack trace if we signal out. sys::PrintStackTraceOnErrorSignal(); PrettyStackTraceProgram X(argc, argv); LLVMContext &Context = getGlobalContext(); llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. cl::ParseCommandLineOptions(argc, argv, "llvm extractor\n"); // Use lazy loading, since we only care about selected global values. SMDiagnostic Err; std::auto_ptr<Module> M; M.reset(getLazyIRFileModule(InputFilename, Err, Context)); if (M.get() == 0) { Err.print(argv[0], errs()); return 1; } // Use SetVector to avoid duplicates. SetVector<GlobalValue *> GVs; // Figure out which globals we should extract. for (size_t i = 0, e = ExtractGlobals.size(); i != e; ++i) { GlobalValue *GV = M.get()->getNamedGlobal(ExtractGlobals[i]); if (!GV) { errs() << argv[0] << ": program doesn't contain global named '" << ExtractGlobals[i] << "'!\n"; return 1; } GVs.insert(GV); } // Extract globals via regular expression matching. for (size_t i = 0, e = ExtractRegExpGlobals.size(); i != e; ++i) { std::string Error; Regex RegEx(ExtractRegExpGlobals[i]); if (!RegEx.isValid(Error)) { errs() << argv[0] << ": '" << ExtractRegExpGlobals[i] << "' " "invalid regex: " << Error; } bool match = false; for (Module::global_iterator GV = M.get()->global_begin(), E = M.get()->global_end(); GV != E; GV++) { if (RegEx.match(GV->getName())) { GVs.insert(&*GV); match = true; } } if (!match) { errs() << argv[0] << ": program doesn't contain global named '" << ExtractRegExpGlobals[i] << "'!\n"; return 1; } } // Figure out which functions we should extract. for (size_t i = 0, e = ExtractFuncs.size(); i != e; ++i) { GlobalValue *GV = M.get()->getFunction(ExtractFuncs[i]); if (!GV) { errs() << argv[0] << ": program doesn't contain function named '" << ExtractFuncs[i] << "'!\n"; return 1; } GVs.insert(GV); } // Extract functions via regular expression matching. for (size_t i = 0, e = ExtractRegExpFuncs.size(); i != e; ++i) { std::string Error; StringRef RegExStr = ExtractRegExpFuncs[i]; Regex RegEx(RegExStr); if (!RegEx.isValid(Error)) { errs() << argv[0] << ": '" << ExtractRegExpFuncs[i] << "' " "invalid regex: " << Error; } bool match = false; for (Module::iterator F = M.get()->begin(), E = M.get()->end(); F != E; F++) { if (RegEx.match(F->getName())) { GVs.insert(&*F); match = true; } } if (!match) { errs() << argv[0] << ": program doesn't contain global named '" << ExtractRegExpFuncs[i] << "'!\n"; return 1; } } // Materialize requisite global values. if (!DeleteFn) for (size_t i = 0, e = GVs.size(); i != e; ++i) { GlobalValue *GV = GVs[i]; if (GV->isMaterializable()) { std::string ErrInfo; if (GV->Materialize(&ErrInfo)) { errs() << argv[0] << ": error reading input: " << ErrInfo << "\n"; return 1; } } } else { // Deleting. Materialize every GV that's *not* in GVs. SmallPtrSet<GlobalValue *, 8> GVSet(GVs.begin(), GVs.end()); for (Module::global_iterator I = M->global_begin(), E = M->global_end(); I != E; ++I) { GlobalVariable *G = I; if (!GVSet.count(G) && G->isMaterializable()) { std::string ErrInfo; if (G->Materialize(&ErrInfo)) { errs() << argv[0] << ": error reading input: " << ErrInfo << "\n"; return 1; } } } for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) { Function *F = I; if (!GVSet.count(F) && F->isMaterializable()) { std::string ErrInfo; if (F->Materialize(&ErrInfo)) { errs() << argv[0] << ": error reading input: " << ErrInfo << "\n"; return 1; } } } } // In addition to deleting all other functions, we also want to spiff it // up a little bit. Do this now. PassManager Passes; Passes.add(new TargetData(M.get())); // Use correct TargetData std::vector<GlobalValue*> Gvs(GVs.begin(), GVs.end()); Passes.add(createGVExtractionPass(Gvs, DeleteFn)); if (!DeleteFn) Passes.add(createGlobalDCEPass()); // Delete unreachable globals Passes.add(createStripDeadDebugInfoPass()); // Remove dead debug info Passes.add(createStripDeadPrototypesPass()); // Remove dead func decls std::string ErrorInfo; tool_output_file Out(OutputFilename.c_str(), ErrorInfo, raw_fd_ostream::F_Binary); if (!ErrorInfo.empty()) { errs() << ErrorInfo << '\n'; return 1; } if (OutputAssembly) Passes.add(createPrintModulePass(&Out.os())); else if (Force || !CheckBitcodeOutputToConsole(Out.os(), true)) Passes.add(createBitcodeWriterPass(Out.os())); Passes.run(*M.get()); // Declare success. Out.keep(); return 0; }
void AAEvaluator::runInternal(Function &F, AAResults &AA) { const DataLayout &DL = F.getParent()->getDataLayout(); ++FunctionCount; SetVector<Value *> Pointers; SmallSetVector<CallBase *, 16> Calls; SetVector<Value *> Loads; SetVector<Value *> Stores; for (auto &I : F.args()) 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 (EvalAAMD && isa<LoadInst>(&*I)) Loads.insert(&*I); if (EvalAAMD && isa<StoreInst>(&*I)) Stores.insert(&*I); Instruction &Inst = *I; if (auto *Call = dyn_cast<CallBase>(&Inst)) { Value *Callee = Call->getCalledValue(); // Skip actual functions for direct function calls. if (!isa<Function>(Callee) && isInterestingPointer(Callee)) Pointers.insert(Callee); // Consider formals. for (Use &DataOp : Call->data_ops()) if (isInterestingPointer(DataOp)) Pointers.insert(DataOp); Calls.insert(Call); } 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 (PrintAll || PrintNoAlias || PrintMayAlias || PrintPartialAlias || PrintMustAlias || PrintNoModRef || PrintMod || PrintRef || PrintModRef) errs() << "Function: " << F.getName() << ": " << Pointers.size() << " pointers, " << Calls.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) { auto I1Size = LocationSize::unknown(); Type *I1ElTy = cast<PointerType>((*I1)->getType())->getElementType(); if (I1ElTy->isSized()) I1Size = LocationSize::precise(DL.getTypeStoreSize(I1ElTy)); for (SetVector<Value *>::iterator I2 = Pointers.begin(); I2 != I1; ++I2) { auto I2Size = LocationSize::unknown(); Type *I2ElTy = cast<PointerType>((*I2)->getType())->getElementType(); if (I2ElTy->isSized()) I2Size = LocationSize::precise(DL.getTypeStoreSize(I2ElTy)); AliasResult AR = AA.alias(*I1, I1Size, *I2, I2Size); switch (AR) { case NoAlias: PrintResults(AR, PrintNoAlias, *I1, *I2, F.getParent()); ++NoAliasCount; break; case MayAlias: PrintResults(AR, PrintMayAlias, *I1, *I2, F.getParent()); ++MayAliasCount; break; case PartialAlias: PrintResults(AR, PrintPartialAlias, *I1, *I2, F.getParent()); ++PartialAliasCount; break; case MustAlias: PrintResults(AR, PrintMustAlias, *I1, *I2, F.getParent()); ++MustAliasCount; break; } } } if (EvalAAMD) { // iterate over all pairs of load, store for (Value *Load : Loads) { for (Value *Store : Stores) { AliasResult AR = AA.alias(MemoryLocation::get(cast<LoadInst>(Load)), MemoryLocation::get(cast<StoreInst>(Store))); switch (AR) { case NoAlias: PrintLoadStoreResults(AR, PrintNoAlias, Load, Store, F.getParent()); ++NoAliasCount; break; case MayAlias: PrintLoadStoreResults(AR, PrintMayAlias, Load, Store, F.getParent()); ++MayAliasCount; break; case PartialAlias: PrintLoadStoreResults(AR, PrintPartialAlias, Load, Store, F.getParent()); ++PartialAliasCount; break; case MustAlias: PrintLoadStoreResults(AR, PrintMustAlias, Load, Store, F.getParent()); ++MustAliasCount; 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) { AliasResult AR = AA.alias(MemoryLocation::get(cast<StoreInst>(*I1)), MemoryLocation::get(cast<StoreInst>(*I2))); switch (AR) { case NoAlias: PrintLoadStoreResults(AR, PrintNoAlias, *I1, *I2, F.getParent()); ++NoAliasCount; break; case MayAlias: PrintLoadStoreResults(AR, PrintMayAlias, *I1, *I2, F.getParent()); ++MayAliasCount; break; case PartialAlias: PrintLoadStoreResults(AR, PrintPartialAlias, *I1, *I2, F.getParent()); ++PartialAliasCount; break; case MustAlias: PrintLoadStoreResults(AR, PrintMustAlias, *I1, *I2, F.getParent()); ++MustAliasCount; break; } } } } // Mod/ref alias analysis: compare all pairs of calls and values for (CallBase *Call : Calls) { for (auto Pointer : Pointers) { auto Size = LocationSize::unknown(); Type *ElTy = cast<PointerType>(Pointer->getType())->getElementType(); if (ElTy->isSized()) Size = LocationSize::precise(DL.getTypeStoreSize(ElTy)); switch (AA.getModRefInfo(Call, Pointer, Size)) { case ModRefInfo::NoModRef: PrintModRefResults("NoModRef", PrintNoModRef, Call, Pointer, F.getParent()); ++NoModRefCount; break; case ModRefInfo::Mod: PrintModRefResults("Just Mod", PrintMod, Call, Pointer, F.getParent()); ++ModCount; break; case ModRefInfo::Ref: PrintModRefResults("Just Ref", PrintRef, Call, Pointer, F.getParent()); ++RefCount; break; case ModRefInfo::ModRef: PrintModRefResults("Both ModRef", PrintModRef, Call, Pointer, F.getParent()); ++ModRefCount; break; case ModRefInfo::Must: PrintModRefResults("Must", PrintMust, Call, Pointer, F.getParent()); ++MustCount; break; case ModRefInfo::MustMod: PrintModRefResults("Just Mod (MustAlias)", PrintMustMod, Call, Pointer, F.getParent()); ++MustModCount; break; case ModRefInfo::MustRef: PrintModRefResults("Just Ref (MustAlias)", PrintMustRef, Call, Pointer, F.getParent()); ++MustRefCount; break; case ModRefInfo::MustModRef: PrintModRefResults("Both ModRef (MustAlias)", PrintMustModRef, Call, Pointer, F.getParent()); ++MustModRefCount; break; } } } // Mod/ref alias analysis: compare all pairs of calls for (CallBase *CallA : Calls) { for (CallBase *CallB : Calls) { if (CallA == CallB) continue; switch (AA.getModRefInfo(CallA, CallB)) { case ModRefInfo::NoModRef: PrintModRefResults("NoModRef", PrintNoModRef, CallA, CallB, F.getParent()); ++NoModRefCount; break; case ModRefInfo::Mod: PrintModRefResults("Just Mod", PrintMod, CallA, CallB, F.getParent()); ++ModCount; break; case ModRefInfo::Ref: PrintModRefResults("Just Ref", PrintRef, CallA, CallB, F.getParent()); ++RefCount; break; case ModRefInfo::ModRef: PrintModRefResults("Both ModRef", PrintModRef, CallA, CallB, F.getParent()); ++ModRefCount; break; case ModRefInfo::Must: PrintModRefResults("Must", PrintMust, CallA, CallB, F.getParent()); ++MustCount; break; case ModRefInfo::MustMod: PrintModRefResults("Just Mod (MustAlias)", PrintMustMod, CallA, CallB, F.getParent()); ++MustModCount; break; case ModRefInfo::MustRef: PrintModRefResults("Just Ref (MustAlias)", PrintMustRef, CallA, CallB, F.getParent()); ++MustRefCount; break; case ModRefInfo::MustModRef: PrintModRefResults("Both ModRef (MustAlias)", PrintMustModRef, CallA, CallB, F.getParent()); ++MustModRefCount; break; } } } }