unsigned DWARFVerifier::verifyDebugNamesCULists(const DWARFDebugNames &AccelTable) { // A map from CU offset to the (first) Name Index offset which claims to index // this CU. DenseMap<uint32_t, uint32_t> CUMap; const uint32_t NotIndexed = std::numeric_limits<uint32_t>::max(); CUMap.reserve(DCtx.getNumCompileUnits()); for (const auto &CU : DCtx.compile_units()) CUMap[CU->getOffset()] = NotIndexed; unsigned NumErrors = 0; for (const DWARFDebugNames::NameIndex &NI : AccelTable) { if (NI.getCUCount() == 0) { error() << formatv("Name Index @ {0:x} does not index any CU\n", NI.getUnitOffset()); ++NumErrors; continue; } for (uint32_t CU = 0, End = NI.getCUCount(); CU < End; ++CU) { uint32_t Offset = NI.getCUOffset(CU); auto Iter = CUMap.find(Offset); if (Iter == CUMap.end()) { error() << formatv( "Name Index @ {0:x} references a non-existing CU @ {1:x}\n", NI.getUnitOffset(), Offset); ++NumErrors; continue; } if (Iter->second != NotIndexed) { error() << formatv("Name Index @ {0:x} references a CU @ {1:x}, but " "this CU is already indexed by Name Index @ {2:x}\n", NI.getUnitOffset(), Offset, Iter->second); continue; } Iter->second = NI.getUnitOffset(); } } for (const auto &KV : CUMap) { if (KV.second == NotIndexed) warn() << formatv("CU @ {0:x} not covered by any Name Index\n", KV.first); } return NumErrors; }
// Builds the graph + StratifiedSets for a function. CFLAAResult::FunctionInfo CFLAAResult::buildSetsFrom(Function *Fn) { NodeMapT Map; GraphT Graph; SmallVector<Value *, 4> ReturnedValues; buildGraphFrom(*this, Fn, ReturnedValues, Map, Graph); DenseMap<GraphT::Node, Value *> NodeValueMap; NodeValueMap.reserve(Map.size()); for (const auto &Pair : Map) NodeValueMap.insert(std::make_pair(Pair.second, Pair.first)); const auto findValueOrDie = [&NodeValueMap](GraphT::Node Node) { auto ValIter = NodeValueMap.find(Node); assert(ValIter != NodeValueMap.end()); return ValIter->second; }; StratifiedSetsBuilder<Value *> Builder; SmallVector<GraphT::Node, 16> Worklist; for (auto &Pair : Map) { Worklist.clear(); auto *Value = Pair.first; Builder.add(Value); auto InitialNode = Pair.second; Worklist.push_back(InitialNode); while (!Worklist.empty()) { auto Node = Worklist.pop_back_val(); auto *CurValue = findValueOrDie(Node); if (canSkipAddingToSets(CurValue)) continue; Optional<StratifiedAttr> MaybeCurIndex = valueToAttrIndex(CurValue); if (MaybeCurIndex) Builder.noteAttributes(CurValue, *MaybeCurIndex); for (const auto &EdgeTuple : Graph.edgesFor(Node)) { auto Weight = std::get<0>(EdgeTuple); auto Label = Weight.first; auto &OtherNode = std::get<1>(EdgeTuple); auto *OtherValue = findValueOrDie(OtherNode); if (canSkipAddingToSets(OtherValue)) continue; bool Added; switch (directionOfEdgeType(Label)) { case Level::Above: Added = Builder.addAbove(CurValue, OtherValue); break; case Level::Below: Added = Builder.addBelow(CurValue, OtherValue); break; case Level::Same: Added = Builder.addWith(CurValue, OtherValue); break; } auto Aliasing = Weight.second; if (MaybeCurIndex) Aliasing.set(*MaybeCurIndex); if (auto MaybeOtherIndex = valueToAttrIndex(OtherValue)) Aliasing.set(*MaybeOtherIndex); Builder.noteAttributes(CurValue, Aliasing); Builder.noteAttributes(OtherValue, Aliasing); if (Added) Worklist.push_back(OtherNode); } } } // There are times when we end up with parameters not in our graph (i.e. if // it's only used as the condition of a branch). Other bits of code depend on // things that were present during construction being present in the graph. // So, we add all present arguments here. for (auto &Arg : Fn->args()) { if (!Builder.add(&Arg)) continue; auto Attrs = valueToAttrIndex(&Arg); if (Attrs.hasValue()) Builder.noteAttributes(&Arg, *Attrs); } return FunctionInfo(Builder.build(), std::move(ReturnedValues)); }
/// Given \p BBs as input, find another set of BBs which collectively /// dominates \p BBs and have the minimal sum of frequencies. Return the BB /// set found in \p BBs. static void findBestInsertionSet(DominatorTree &DT, BlockFrequencyInfo &BFI, BasicBlock *Entry, SmallPtrSet<BasicBlock *, 8> &BBs) { assert(!BBs.count(Entry) && "Assume Entry is not in BBs"); // Nodes on the current path to the root. SmallPtrSet<BasicBlock *, 8> Path; // Candidates includes any block 'BB' in set 'BBs' that is not strictly // dominated by any other blocks in set 'BBs', and all nodes in the path // in the dominator tree from Entry to 'BB'. SmallPtrSet<BasicBlock *, 16> Candidates; for (auto BB : BBs) { // Ignore unreachable basic blocks. if (!DT.isReachableFromEntry(BB)) continue; Path.clear(); // Walk up the dominator tree until Entry or another BB in BBs // is reached. Insert the nodes on the way to the Path. BasicBlock *Node = BB; // The "Path" is a candidate path to be added into Candidates set. bool isCandidate = false; do { Path.insert(Node); if (Node == Entry || Candidates.count(Node)) { isCandidate = true; break; } assert(DT.getNode(Node)->getIDom() && "Entry doens't dominate current Node"); Node = DT.getNode(Node)->getIDom()->getBlock(); } while (!BBs.count(Node)); // If isCandidate is false, Node is another Block in BBs dominating // current 'BB'. Drop the nodes on the Path. if (!isCandidate) continue; // Add nodes on the Path into Candidates. Candidates.insert(Path.begin(), Path.end()); } // Sort the nodes in Candidates in top-down order and save the nodes // in Orders. unsigned Idx = 0; SmallVector<BasicBlock *, 16> Orders; Orders.push_back(Entry); while (Idx != Orders.size()) { BasicBlock *Node = Orders[Idx++]; for (auto ChildDomNode : DT.getNode(Node)->getChildren()) { if (Candidates.count(ChildDomNode->getBlock())) Orders.push_back(ChildDomNode->getBlock()); } } // Visit Orders in bottom-up order. using InsertPtsCostPair = std::pair<SmallPtrSet<BasicBlock *, 16>, BlockFrequency>; // InsertPtsMap is a map from a BB to the best insertion points for the // subtree of BB (subtree not including the BB itself). DenseMap<BasicBlock *, InsertPtsCostPair> InsertPtsMap; InsertPtsMap.reserve(Orders.size() + 1); for (auto RIt = Orders.rbegin(); RIt != Orders.rend(); RIt++) { BasicBlock *Node = *RIt; bool NodeInBBs = BBs.count(Node); SmallPtrSet<BasicBlock *, 16> &InsertPts = InsertPtsMap[Node].first; BlockFrequency &InsertPtsFreq = InsertPtsMap[Node].second; // Return the optimal insert points in BBs. if (Node == Entry) { BBs.clear(); if (InsertPtsFreq > BFI.getBlockFreq(Node) || (InsertPtsFreq == BFI.getBlockFreq(Node) && InsertPts.size() > 1)) BBs.insert(Entry); else BBs.insert(InsertPts.begin(), InsertPts.end()); break; } BasicBlock *Parent = DT.getNode(Node)->getIDom()->getBlock(); // Initially, ParentInsertPts is empty and ParentPtsFreq is 0. Every child // will update its parent's ParentInsertPts and ParentPtsFreq. SmallPtrSet<BasicBlock *, 16> &ParentInsertPts = InsertPtsMap[Parent].first; BlockFrequency &ParentPtsFreq = InsertPtsMap[Parent].second; // Choose to insert in Node or in subtree of Node. // Don't hoist to EHPad because we may not find a proper place to insert // in EHPad. // If the total frequency of InsertPts is the same as the frequency of the // target Node, and InsertPts contains more than one nodes, choose hoisting // to reduce code size. if (NodeInBBs || (!Node->isEHPad() && (InsertPtsFreq > BFI.getBlockFreq(Node) || (InsertPtsFreq == BFI.getBlockFreq(Node) && InsertPts.size() > 1)))) { ParentInsertPts.insert(Node); ParentPtsFreq += BFI.getBlockFreq(Node); } else { ParentInsertPts.insert(InsertPts.begin(), InsertPts.end()); ParentPtsFreq += InsertPtsFreq; } } }