void checkEraseAndIterators(SmallPtrSetImpl<int*> &S) { int buf[3]; S.insert(&buf[0]); S.insert(&buf[1]); S.insert(&buf[2]); // Iterators must still be valid after erase() calls; auto B = S.begin(); auto M = std::next(B); auto E = S.end(); EXPECT_TRUE(*B == &buf[0] || *B == &buf[1] || *B == &buf[2]); EXPECT_TRUE(*M == &buf[0] || *M == &buf[1] || *M == &buf[2]); EXPECT_TRUE(*B != *M); int *Removable = *std::next(M); // No iterator points to Removable now. EXPECT_TRUE(Removable == &buf[0] || Removable == &buf[1] || Removable == &buf[2]); EXPECT_TRUE(Removable != *B && Removable != *M); S.erase(Removable); // B,M,E iterators should still be valid EXPECT_EQ(B, S.begin()); EXPECT_EQ(M, std::next(B)); EXPECT_EQ(E, S.end()); EXPECT_EQ(std::next(M), E); }
/// Walk up the CFG from StartPos (which is in StartBB) and find local and /// non-local dependencies on Arg. /// /// TODO: Cache results? void llvm::objcarc::FindDependencies(DependenceKind Flavor, const Value *Arg, BasicBlock *StartBB, Instruction *StartInst, SmallPtrSetImpl<Instruction *> &DependingInsts, SmallPtrSetImpl<const BasicBlock *> &Visited, ProvenanceAnalysis &PA) { BasicBlock::iterator StartPos = StartInst; SmallVector<std::pair<BasicBlock *, BasicBlock::iterator>, 4> Worklist; Worklist.push_back(std::make_pair(StartBB, StartPos)); do { std::pair<BasicBlock *, BasicBlock::iterator> Pair = Worklist.pop_back_val(); BasicBlock *LocalStartBB = Pair.first; BasicBlock::iterator LocalStartPos = Pair.second; BasicBlock::iterator StartBBBegin = LocalStartBB->begin(); for (;;) { if (LocalStartPos == StartBBBegin) { pred_iterator PI(LocalStartBB), PE(LocalStartBB, false); if (PI == PE) // If we've reached the function entry, produce a null dependence. DependingInsts.insert(nullptr); else // Add the predecessors to the worklist. do { BasicBlock *PredBB = *PI; if (Visited.insert(PredBB)) Worklist.push_back(std::make_pair(PredBB, PredBB->end())); } while (++PI != PE); break; } Instruction *Inst = --LocalStartPos; if (Depends(Flavor, Inst, Arg, PA)) { DependingInsts.insert(Inst); break; } } } while (!Worklist.empty()); // Determine whether the original StartBB post-dominates all of the blocks we // visited. If not, insert a sentinal indicating that most optimizations are // not safe. for (SmallPtrSet<const BasicBlock *, 4>::const_iterator I = Visited.begin(), E = Visited.end(); I != E; ++I) { const BasicBlock *BB = *I; if (BB == StartBB) continue; const TerminatorInst *TI = cast<TerminatorInst>(&BB->back()); for (succ_const_iterator SI(TI), SE(TI, false); SI != SE; ++SI) { const BasicBlock *Succ = *SI; if (Succ != StartBB && !Visited.count(Succ)) { DependingInsts.insert(reinterpret_cast<Instruction *>(-1)); return; } } } }
// Breadth-first walk of the use-def graph; determine the set of nodes // we care about and eagerly determine if some of them are poisonous. void Float2IntPass::walkBackwards(const SmallPtrSetImpl<Instruction*> &Roots) { std::deque<Instruction*> Worklist(Roots.begin(), Roots.end()); while (!Worklist.empty()) { Instruction *I = Worklist.back(); Worklist.pop_back(); if (SeenInsts.find(I) != SeenInsts.end()) // Seen already. continue; switch (I->getOpcode()) { // FIXME: Handle select and phi nodes. default: // Path terminated uncleanly. seen(I, badRange()); break; case Instruction::UIToFP: case Instruction::SIToFP: { // Path terminated cleanly - use the type of the integer input to seed // the analysis. unsigned BW = I->getOperand(0)->getType()->getPrimitiveSizeInBits(); auto Input = ConstantRange(BW, true); auto CastOp = (Instruction::CastOps)I->getOpcode(); seen(I, validateRange(Input.castOp(CastOp, MaxIntegerBW+1))); continue; } case Instruction::FAdd: case Instruction::FSub: case Instruction::FMul: case Instruction::FPToUI: case Instruction::FPToSI: case Instruction::FCmp: seen(I, unknownRange()); break; } for (Value *O : I->operands()) { if (Instruction *OI = dyn_cast<Instruction>(O)) { // Unify def-use chains if they interfere. ECs.unionSets(I, OI); if (SeenInsts.find(I)->second != badRange()) Worklist.push_back(OI); } else if (!isa<ConstantFP>(O)) { // Not an instruction or ConstantFP? we can't do anything. seen(I, badRange()); } } } }
/// Return a set of basic blocks to insert sinked instructions. /// /// The returned set of basic blocks (BBsToSinkInto) should satisfy: /// /// * Inside the loop \p L /// * For each UseBB in \p UseBBs, there is at least one BB in BBsToSinkInto /// that domintates the UseBB /// * Has minimum total frequency that is no greater than preheader frequency /// /// The purpose of the function is to find the optimal sinking points to /// minimize execution cost, which is defined as "sum of frequency of /// BBsToSinkInto". /// As a result, the returned BBsToSinkInto needs to have minimum total /// frequency. /// Additionally, if the total frequency of BBsToSinkInto exceeds preheader /// frequency, the optimal solution is not sinking (return empty set). /// /// \p ColdLoopBBs is used to help find the optimal sinking locations. /// It stores a list of BBs that is: /// /// * Inside the loop \p L /// * Has a frequency no larger than the loop's preheader /// * Sorted by BB frequency /// /// The complexity of the function is O(UseBBs.size() * ColdLoopBBs.size()). /// To avoid expensive computation, we cap the maximum UseBBs.size() in its /// caller. static SmallPtrSet<BasicBlock *, 2> findBBsToSinkInto(const Loop &L, const SmallPtrSetImpl<BasicBlock *> &UseBBs, const SmallVectorImpl<BasicBlock *> &ColdLoopBBs, DominatorTree &DT, BlockFrequencyInfo &BFI) { SmallPtrSet<BasicBlock *, 2> BBsToSinkInto; if (UseBBs.size() == 0) return BBsToSinkInto; BBsToSinkInto.insert(UseBBs.begin(), UseBBs.end()); SmallPtrSet<BasicBlock *, 2> BBsDominatedByColdestBB; // For every iteration: // * Pick the ColdestBB from ColdLoopBBs // * Find the set BBsDominatedByColdestBB that satisfy: // - BBsDominatedByColdestBB is a subset of BBsToSinkInto // - Every BB in BBsDominatedByColdestBB is dominated by ColdestBB // * If Freq(ColdestBB) < Freq(BBsDominatedByColdestBB), remove // BBsDominatedByColdestBB from BBsToSinkInto, add ColdestBB to // BBsToSinkInto for (BasicBlock *ColdestBB : ColdLoopBBs) { BBsDominatedByColdestBB.clear(); for (BasicBlock *SinkedBB : BBsToSinkInto) if (DT.dominates(ColdestBB, SinkedBB)) BBsDominatedByColdestBB.insert(SinkedBB); if (BBsDominatedByColdestBB.size() == 0) continue; if (adjustedSumFreq(BBsDominatedByColdestBB, BFI) > BFI.getBlockFreq(ColdestBB)) { for (BasicBlock *DominatedBB : BBsDominatedByColdestBB) { BBsToSinkInto.erase(DominatedBB); } BBsToSinkInto.insert(ColdestBB); } } // If the total frequency of BBsToSinkInto is larger than preheader frequency, // do not sink. if (adjustedSumFreq(BBsToSinkInto, BFI) > BFI.getBlockFreq(L.getLoopPreheader())) BBsToSinkInto.clear(); return BBsToSinkInto; }