/// \brief Find an insertion point that dominates all uses. Instruction *ConstantHoisting:: FindConstantInsertionPoint(Function &F, const ConstantInfo &CI) const { BasicBlock *Entry = &F.getEntryBlock(); // Collect all basic blocks. SmallPtrSet<BasicBlock *, 4> BBs; ConstantInfo::RebasedConstantListType::const_iterator RCI, RCE; for (RCI = CI.RebasedConstants.begin(), RCE = CI.RebasedConstants.end(); RCI != RCE; ++RCI) for (SmallVectorImpl<User *>::const_iterator U = RCI->Uses.begin(), E = RCI->Uses.end(); U != E; ++U) CollectBasicBlocks(BBs, F, *U); if (BBs.count(Entry)) return Entry->getFirstInsertionPt(); while (BBs.size() >= 2) { BasicBlock *BB, *BB1, *BB2; BB1 = *BBs.begin(); BB2 = *llvm::next(BBs.begin()); BB = DT->findNearestCommonDominator(BB1, BB2); if (BB == Entry) return Entry->getFirstInsertionPt(); BBs.erase(BB1); BBs.erase(BB2); BBs.insert(BB); } assert((BBs.size() == 1) && "Expected only one element."); return (*BBs.begin())->getFirstInsertionPt(); }
/// RemoveUnreachableBlocksFromFn - Remove blocks that are not reachable, even /// if they are in a dead cycle. Return true if a change was made, false /// otherwise. static bool RemoveUnreachableBlocksFromFn(Function &F) { SmallPtrSet<BasicBlock*, 128> Reachable; bool Changed = MarkAliveBlocks(F.begin(), Reachable); // If there are unreachable blocks in the CFG... if (Reachable.size() == F.size()) return Changed; assert(Reachable.size() < F.size()); NumSimpl += F.size()-Reachable.size(); // Loop over all of the basic blocks that are not reachable, dropping all of // their internal references... for (Function::iterator BB = ++F.begin(), E = F.end(); BB != E; ++BB) { if (Reachable.count(BB)) continue; for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB); SI != SE; ++SI) if (Reachable.count(*SI)) (*SI)->removePredecessor(BB); BB->dropAllReferences(); } for (Function::iterator I = ++F.begin(); I != F.end();) if (!Reachable.count(I)) I = F.getBasicBlockList().erase(I); else ++I; return true; }
/// \brief Find an insertion point that dominates all uses. Instruction *ConstantHoistingPass::findConstantInsertionPoint( const ConstantInfo &ConstInfo) const { assert(!ConstInfo.RebasedConstants.empty() && "Invalid constant info entry."); // Collect all basic blocks. SmallPtrSet<BasicBlock *, 8> BBs; for (auto const &RCI : ConstInfo.RebasedConstants) for (auto const &U : RCI.Uses) BBs.insert(findMatInsertPt(U.Inst, U.OpndIdx)->getParent()); if (BBs.count(Entry)) return &Entry->front(); while (BBs.size() >= 2) { BasicBlock *BB, *BB1, *BB2; BB1 = *BBs.begin(); BB2 = *std::next(BBs.begin()); BB = DT->findNearestCommonDominator(BB1, BB2); if (BB == Entry) return &Entry->front(); BBs.erase(BB1); BBs.erase(BB2); BBs.insert(BB); } assert((BBs.size() == 1) && "Expected only one element."); Instruction &FirstInst = (*BBs.begin())->front(); return findMatInsertPt(&FirstInst); }
// Calculate Edge Weights using "Loop Branch Heuristics". Predict backedges // as taken, exiting edges as not-taken. bool BranchProbabilityInfo::calcLoopBranchHeuristics(BasicBlock *BB) { Loop *L = LI->getLoopFor(BB); if (!L) return false; SmallPtrSet<BasicBlock *, 8> BackEdges; SmallPtrSet<BasicBlock *, 8> ExitingEdges; SmallPtrSet<BasicBlock *, 8> InEdges; // Edges from header to the loop. for (succ_iterator I = succ_begin(BB), E = succ_end(BB); I != E; ++I) { if (!L->contains(*I)) ExitingEdges.insert(*I); else if (L->getHeader() == *I) BackEdges.insert(*I); else InEdges.insert(*I); } if (uint32_t numBackEdges = BackEdges.size()) { uint32_t backWeight = LBH_TAKEN_WEIGHT / numBackEdges; if (backWeight < NORMAL_WEIGHT) backWeight = NORMAL_WEIGHT; for (SmallPtrSet<BasicBlock *, 8>::iterator EI = BackEdges.begin(), EE = BackEdges.end(); EI != EE; ++EI) { BasicBlock *Back = *EI; setEdgeWeight(BB, Back, backWeight); } } if (uint32_t numInEdges = InEdges.size()) { uint32_t inWeight = LBH_TAKEN_WEIGHT / numInEdges; if (inWeight < NORMAL_WEIGHT) inWeight = NORMAL_WEIGHT; for (SmallPtrSet<BasicBlock *, 8>::iterator EI = InEdges.begin(), EE = InEdges.end(); EI != EE; ++EI) { BasicBlock *Back = *EI; setEdgeWeight(BB, Back, inWeight); } } if (uint32_t numExitingEdges = ExitingEdges.size()) { uint32_t exitWeight = LBH_NONTAKEN_WEIGHT / numExitingEdges; if (exitWeight < MIN_WEIGHT) exitWeight = MIN_WEIGHT; for (SmallPtrSet<BasicBlock *, 8>::iterator EI = ExitingEdges.begin(), EE = ExitingEdges.end(); EI != EE; ++EI) { BasicBlock *Exiting = *EI; setEdgeWeight(BB, Exiting, exitWeight); } } return true; }
TEST(SmallPtrSetTest, GrowthTest) { int i; int buf[8]; for(i=0; i<8; ++i) buf[i]=0; SmallPtrSet<int *, 4> s; typedef SmallPtrSet<int *, 4>::iterator iter; s.insert(&buf[0]); s.insert(&buf[1]); s.insert(&buf[2]); s.insert(&buf[3]); EXPECT_EQ(4U, s.size()); i = 0; for(iter I=s.begin(), E=s.end(); I!=E; ++I, ++i) (**I)++; EXPECT_EQ(4, i); for(i=0; i<8; ++i) EXPECT_EQ(i<4?1:0,buf[i]); s.insert(&buf[4]); s.insert(&buf[5]); s.insert(&buf[6]); s.insert(&buf[7]); i = 0; for(iter I=s.begin(), E=s.end(); I!=E; ++I, ++i) (**I)++; EXPECT_EQ(8, i); s.erase(&buf[4]); s.erase(&buf[5]); s.erase(&buf[6]); s.erase(&buf[7]); EXPECT_EQ(4U, s.size()); i = 0; for(iter I=s.begin(), E=s.end(); I!=E; ++I, ++i) (**I)++; EXPECT_EQ(4, i); for(i=0; i<8; ++i) EXPECT_EQ(i<4?3:1,buf[i]); s.clear(); for(i=0; i<8; ++i) buf[i]=0; for(i=0; i<128; ++i) s.insert(&buf[i%8]); // test repeated entires EXPECT_EQ(8U, s.size()); for(iter I=s.begin(), E=s.end(); I!=E; ++I, ++i) (**I)++; for(i=0; i<8; ++i) EXPECT_EQ(1,buf[i]); }
bool ReduceCrashingInstructions::TestInsts(std::vector<const Instruction*> &Insts) { // Clone the program to try hacking it apart... ValueToValueMapTy VMap; Module *M = CloneModule(BD.getProgram(), VMap); // Convert list to set for fast lookup... SmallPtrSet<Instruction*, 64> Instructions; for (unsigned i = 0, e = Insts.size(); i != e; ++i) { assert(!isa<TerminatorInst>(Insts[i])); Instructions.insert(cast<Instruction>(VMap[Insts[i]])); } outs() << "Checking for crash with only " << Instructions.size(); if (Instructions.size() == 1) outs() << " instruction: "; else outs() << " instructions: "; for (Module::iterator MI = M->begin(), ME = M->end(); MI != ME; ++MI) for (Function::iterator FI = MI->begin(), FE = MI->end(); FI != FE; ++FI) for (BasicBlock::iterator I = FI->begin(), E = FI->end(); I != E;) { Instruction *Inst = I++; if (!Instructions.count(Inst) && !isa<TerminatorInst>(Inst) && !isa<LandingPadInst>(Inst)) { if (!Inst->getType()->isVoidTy()) Inst->replaceAllUsesWith(UndefValue::get(Inst->getType())); Inst->eraseFromParent(); } } // Verify that this is still valid. PassManager Passes; Passes.add(createVerifierPass()); Passes.add(createDebugInfoVerifierPass()); Passes.run(*M); // Try running on the hacked up program... if (TestFn(BD, M)) { BD.setNewProgram(M); // It crashed, keep the trimmed version... // Make sure to use instruction pointers that point into the now-current // module, and that they don't include any deleted blocks. Insts.clear(); for (SmallPtrSet<Instruction*, 64>::const_iterator I = Instructions.begin(), E = Instructions.end(); I != E; ++I) Insts.push_back(*I); return true; } delete M; // It didn't crash, try something else. return false; }
bool ReduceCrashingNamedMDOps::TestNamedMDOps( std::vector<const MDNode *> &NamedMDOps) { // Convert list to set for fast lookup... SmallPtrSet<const MDNode *, 32> OldMDNodeOps; for (unsigned i = 0, e = NamedMDOps.size(); i != e; ++i) { OldMDNodeOps.insert(NamedMDOps[i]); } outs() << "Checking for crash with only " << OldMDNodeOps.size(); if (OldMDNodeOps.size() == 1) outs() << " named metadata operand: "; else outs() << " named metadata operands: "; ValueToValueMapTy VMap; Module *M = CloneModule(BD.getProgram(), VMap).release(); // This is a little wasteful. In the future it might be good if we could have // these dropped during cloning. for (auto &NamedMD : BD.getProgram()->named_metadata()) { // Drop the old one and create a new one M->eraseNamedMetadata(M->getNamedMetadata(NamedMD.getName())); NamedMDNode *NewNamedMDNode = M->getOrInsertNamedMetadata(NamedMD.getName()); for (MDNode *op : NamedMD.operands()) if (OldMDNodeOps.count(op)) NewNamedMDNode->addOperand(cast<MDNode>(MapMetadata(op, VMap))); } // Verify that this is still valid. legacy::PassManager Passes; Passes.add(createVerifierPass(/*FatalErrors=*/false)); Passes.run(*M); // Try running on the hacked up program... if (TestFn(BD, M)) { // Make sure to use instruction pointers that point into the now-current // module, and that they don't include any deleted blocks. NamedMDOps.clear(); for (const MDNode *Node : OldMDNodeOps) NamedMDOps.push_back(cast<MDNode>(*VMap.getMappedMD(Node))); BD.setNewProgram(M); // It crashed, keep the trimmed version... return true; } delete M; // It didn't crash, try something else. return false; }
bool CallAnalyzer::visitSwitchInst(SwitchInst &SI) { // We model unconditional switches as free, see the comments on handling // branches. if (isa<ConstantInt>(SI.getCondition())) return true; if (Value *V = SimplifiedValues.lookup(SI.getCondition())) if (isa<ConstantInt>(V)) return true; // Otherwise, we need to accumulate a cost proportional to the number of // distinct successor blocks. This fan-out in the CFG cannot be represented // for free even if we can represent the core switch as a jumptable that // takes a single instruction. // // NB: We convert large switches which are just used to initialize large phi // nodes to lookup tables instead in simplify-cfg, so this shouldn't prevent // inlining those. It will prevent inlining in cases where the optimization // does not (yet) fire. SmallPtrSet<BasicBlock *, 8> SuccessorBlocks; SuccessorBlocks.insert(SI.getDefaultDest()); for (auto I = SI.case_begin(), E = SI.case_end(); I != E; ++I) SuccessorBlocks.insert(I.getCaseSuccessor()); // Add cost corresponding to the number of distinct destinations. The first // we model as free because of fallthrough. Cost += (SuccessorBlocks.size() - 1) * InlineConstants::InstrCost; return false; }
bool Lowerer::shouldElide() const { // If no CoroAllocs, we cannot suppress allocation, so elision is not // possible. if (CoroAllocs.empty()) return false; // Check that for every coro.begin there is a coro.destroy directly // referencing the SSA value of that coro.begin. If the value escaped, then // coro.destroy would have been referencing a memory location storing that // value and not the virtual register. SmallPtrSet<CoroBeginInst *, 8> ReferencedCoroBegins; for (CoroSubFnInst *DA : DestroyAddr) { if (auto *CB = dyn_cast<CoroBeginInst>(DA->getFrame())) ReferencedCoroBegins.insert(CB); else return false; } // If size of the set is the same as total number of CoroBegins, means we // found a coro.free or coro.destroy mentioning a coro.begin and we can // perform heap elision. return ReferencedCoroBegins.size() == CoroBegins.size(); }
/// Iteratively perform simplification on a worklist of users /// of the specified induction variable. Each successive simplification may push /// more users which may themselves be candidates for simplification. /// /// This algorithm does not require IVUsers analysis. Instead, it simplifies /// instructions in-place during analysis. Rather than rewriting induction /// variables bottom-up from their users, it transforms a chain of IVUsers /// top-down, updating the IR only when it encounters a clear optimization /// opportunity. /// /// Once DisableIVRewrite is default, LSR will be the only client of IVUsers. /// void SimplifyIndvar::simplifyUsers(PHINode *CurrIV, IVVisitor *V) { if (!SE->isSCEVable(CurrIV->getType())) return; // Instructions processed by SimplifyIndvar for CurrIV. SmallPtrSet<Instruction*,16> Simplified; // Use-def pairs if IV users waiting to be processed for CurrIV. SmallVector<std::pair<Instruction*, Instruction*>, 8> SimpleIVUsers; // Push users of the current LoopPhi. In rare cases, pushIVUsers may be // called multiple times for the same LoopPhi. This is the proper thing to // do for loop header phis that use each other. pushIVUsers(CurrIV, Simplified, SimpleIVUsers); while (!SimpleIVUsers.empty()) { std::pair<Instruction*, Instruction*> UseOper = SimpleIVUsers.pop_back_val(); Instruction *UseInst = UseOper.first; // Bypass back edges to avoid extra work. if (UseInst == CurrIV) continue; Instruction *IVOperand = UseOper.second; for (unsigned N = 0; IVOperand; ++N) { assert(N <= Simplified.size() && "runaway iteration"); Value *NewOper = foldIVUser(UseOper.first, IVOperand); if (!NewOper) break; // done folding IVOperand = dyn_cast<Instruction>(NewOper); } if (!IVOperand) continue; if (eliminateIVUser(UseOper.first, IVOperand)) { pushIVUsers(IVOperand, Simplified, SimpleIVUsers); continue; } if (BinaryOperator *BO = dyn_cast<BinaryOperator>(UseOper.first)) { if (isa<OverflowingBinaryOperator>(BO) && strengthenOverflowingOperation(BO, IVOperand)) { // re-queue uses of the now modified binary operator and fall // through to the checks that remain. pushIVUsers(IVOperand, Simplified, SimpleIVUsers); } } CastInst *Cast = dyn_cast<CastInst>(UseOper.first); if (V && Cast) { V->visitCast(Cast); continue; } if (isSimpleIVUser(UseOper.first, L, SE)) { pushIVUsers(UseOper.first, Simplified, SimpleIVUsers); } } }
/// \brief Calculate edge weights for successors lead to unreachable. /// /// Predict that a successor which leads necessarily to an /// unreachable-terminated block as extremely unlikely. bool BranchProbabilityInfo::calcUnreachableHeuristics(BasicBlock *BB) { TerminatorInst *TI = BB->getTerminator(); if (TI->getNumSuccessors() == 0) { if (isa<UnreachableInst>(TI)) PostDominatedByUnreachable.insert(BB); return false; } SmallPtrSet<BasicBlock *, 4> UnreachableEdges; SmallPtrSet<BasicBlock *, 4> ReachableEdges; for (succ_iterator I = succ_begin(BB), E = succ_end(BB); I != E; ++I) { if (PostDominatedByUnreachable.count(*I)) UnreachableEdges.insert(*I); else ReachableEdges.insert(*I); } // If all successors are in the set of blocks post-dominated by unreachable, // this block is too. if (UnreachableEdges.size() == TI->getNumSuccessors()) PostDominatedByUnreachable.insert(BB); // Skip probabilities if this block has a single successor or if all were // reachable. if (TI->getNumSuccessors() == 1 || UnreachableEdges.empty()) return false; uint32_t UnreachableWeight = std::max(UR_TAKEN_WEIGHT / UnreachableEdges.size(), MIN_WEIGHT); for (SmallPtrSet<BasicBlock *, 4>::iterator I = UnreachableEdges.begin(), E = UnreachableEdges.end(); I != E; ++I) setEdgeWeight(BB, *I, UnreachableWeight); if (ReachableEdges.empty()) return true; uint32_t ReachableWeight = std::max(UR_NONTAKEN_WEIGHT / ReachableEdges.size(), NORMAL_WEIGHT); for (SmallPtrSet<BasicBlock *, 4>::iterator I = ReachableEdges.begin(), E = ReachableEdges.end(); I != E; ++I) setEdgeWeight(BB, *I, ReachableWeight); return true; }
/// Find an insertion point that dominates all uses. SmallPtrSet<Instruction *, 8> ConstantHoistingPass::findConstantInsertionPoint( const ConstantInfo &ConstInfo) const { assert(!ConstInfo.RebasedConstants.empty() && "Invalid constant info entry."); // Collect all basic blocks. SmallPtrSet<BasicBlock *, 8> BBs; SmallPtrSet<Instruction *, 8> InsertPts; for (auto const &RCI : ConstInfo.RebasedConstants) for (auto const &U : RCI.Uses) BBs.insert(findMatInsertPt(U.Inst, U.OpndIdx)->getParent()); if (BBs.count(Entry)) { InsertPts.insert(&Entry->front()); return InsertPts; } if (BFI) { findBestInsertionSet(*DT, *BFI, Entry, BBs); for (auto BB : BBs) { BasicBlock::iterator InsertPt = BB->begin(); for (; isa<PHINode>(InsertPt) || InsertPt->isEHPad(); ++InsertPt) ; InsertPts.insert(&*InsertPt); } return InsertPts; } while (BBs.size() >= 2) { BasicBlock *BB, *BB1, *BB2; BB1 = *BBs.begin(); BB2 = *std::next(BBs.begin()); BB = DT->findNearestCommonDominator(BB1, BB2); if (BB == Entry) { InsertPts.insert(&Entry->front()); return InsertPts; } BBs.erase(BB1); BBs.erase(BB2); BBs.insert(BB); } assert((BBs.size() == 1) && "Expected only one element."); Instruction &FirstInst = (*BBs.begin())->front(); InsertPts.insert(findMatInsertPt(&FirstInst)); return InsertPts; }
/// Merge an autorelease with a retain into a fused call. bool ObjCARCContract::ContractAutorelease(Function &F, Instruction *Autorelease, InstructionClass Class, SmallPtrSet<Instruction *, 4> &DependingInstructions, SmallPtrSet<const BasicBlock *, 4> &Visited) { const Value *Arg = GetObjCArg(Autorelease); // Check that there are no instructions between the retain and the autorelease // (such as an autorelease_pop) which may change the count. CallInst *Retain = 0; if (Class == IC_AutoreleaseRV) FindDependencies(RetainAutoreleaseRVDep, Arg, Autorelease->getParent(), Autorelease, DependingInstructions, Visited, PA); else FindDependencies(RetainAutoreleaseDep, Arg, Autorelease->getParent(), Autorelease, DependingInstructions, Visited, PA); Visited.clear(); if (DependingInstructions.size() != 1) { DependingInstructions.clear(); return false; } Retain = dyn_cast_or_null<CallInst>(*DependingInstructions.begin()); DependingInstructions.clear(); if (!Retain || GetBasicInstructionClass(Retain) != IC_Retain || GetObjCArg(Retain) != Arg) return false; Changed = true; ++NumPeeps; DEBUG(dbgs() << "ObjCARCContract::ContractAutorelease: Fusing " "retain/autorelease. Erasing: " << *Autorelease << "\n" " Old Retain: " << *Retain << "\n"); if (Class == IC_AutoreleaseRV) Retain->setCalledFunction(getRetainAutoreleaseRVCallee(F.getParent())); else Retain->setCalledFunction(getRetainAutoreleaseCallee(F.getParent())); DEBUG(dbgs() << " New Retain: " << *Retain << "\n"); EraseInstruction(Autorelease); return true; }
void LowerEmAsyncify::FindContextVariables(AsyncCallEntry & Entry) { BasicBlock *AfterCallBlock = Entry.AfterCallBlock; Function & F = *AfterCallBlock->getParent(); // Create a new entry block as if in the callback function // theck check variables that no longer properly dominate their uses BasicBlock *EntryBlock = BasicBlock::Create(TheModule->getContext(), "", &F, &F.getEntryBlock()); BranchInst::Create(AfterCallBlock, EntryBlock); DominatorTreeWrapperPass DTW; DTW.runOnFunction(F); DominatorTree& DT = DTW.getDomTree(); // These blocks may be using some values defined at or before AsyncCallBlock BasicBlockSet Ramifications = FindReachableBlocksFrom(AfterCallBlock); SmallPtrSet<Value*, 256> ContextVariables; Values Pending; // Examine the instructions, find all variables that we need to store in the context for (BasicBlockSet::iterator RI = Ramifications.begin(), RE = Ramifications.end(); RI != RE; ++RI) { for (BasicBlock::iterator I = (*RI)->begin(), E = (*RI)->end(); I != E; ++I) { for (unsigned i = 0, NumOperands = I->getNumOperands(); i < NumOperands; ++i) { Value *O = I->getOperand(i); if (Instruction *Inst = dyn_cast<Instruction>(O)) { if (Inst == Entry.AsyncCallInst) continue; // for the original async call, we will load directly from async return value if (ContextVariables.count(Inst) != 0) continue; // already examined if (!DT.dominates(Inst, I->getOperandUse(i))) { // `I` is using `Inst`, yet `Inst` does not dominate `I` if we arrive directly at AfterCallBlock // so we need to save `Inst` in the context ContextVariables.insert(Inst); Pending.push_back(Inst); } } else if (Argument *Arg = dyn_cast<Argument>(O)) { // count() should be as fast/slow as insert, so just insert here ContextVariables.insert(Arg); } } } } // restore F EntryBlock->eraseFromParent(); Entry.ContextVariables.clear(); Entry.ContextVariables.reserve(ContextVariables.size()); for (SmallPtrSet<Value*, 256>::iterator I = ContextVariables.begin(), E = ContextVariables.end(); I != E; ++I) { Entry.ContextVariables.push_back(*I); } }
/// Check if the root value for Value that comes /// along the path from DomBB is equivalent to the /// DomCondition. SILValue CheckedCastBrJumpThreading::isArgValueEquivalentToCondition( SILValue Value, SILBasicBlock *DomBB, SILValue DomValue, DominanceInfo *DT) { SmallPtrSet<ValueBase *, 16> SeenValues; DomValue = DomValue.stripClassCasts(); while (true) { Value = Value.stripClassCasts(); if (Value == DomValue) return Value; // We know how to propagate through BBArgs only. auto *V = dyn_cast<SILArgument>(Value); if (!V) return SILValue(); // Have we visited this BB already? if (!SeenValues.insert(Value.getDef()).second) return SILValue(); if (SeenValues.size() > 10) return SILValue(); SmallVector<SILValue, 4> IncomingValues; if (!V->getIncomingValues(IncomingValues) || IncomingValues.empty()) return SILValue(); ValueBase *Def = nullptr; for (auto IncomingValue : IncomingValues) { // Each incoming value should be either from a block // dominated by DomBB or it should be the value used in // condition in DomBB Value = IncomingValue.stripClassCasts(); if (Value == DomValue) continue; // Values should be the same if (!Def) Def = Value.getDef(); if (Def != Value.getDef()) return SILValue(); if (!DT->dominates(DomBB, Value.getDef()->getParentBB())) return SILValue(); // OK, this value is a potential candidate } Value = IncomingValues[0]; } }
// Calculate Edge Weights using "Return Heuristics". Predict a successor which // leads directly to Return Instruction will not be taken. bool BranchProbabilityAnalysis::calcReturnHeuristics(BasicBlock *BB){ if (BB->getTerminator()->getNumSuccessors() == 1) return false; SmallPtrSet<BasicBlock *, 4> ReturningEdges; SmallPtrSet<BasicBlock *, 4> StayEdges; for (succ_iterator I = succ_begin(BB), E = succ_end(BB); I != E; ++I) { BasicBlock *Succ = *I; if (isReturningBlock(Succ)) ReturningEdges.insert(Succ); else StayEdges.insert(Succ); } if (uint32_t numStayEdges = StayEdges.size()) { uint32_t stayWeight = RH_TAKEN_WEIGHT / numStayEdges; if (stayWeight < NORMAL_WEIGHT) stayWeight = NORMAL_WEIGHT; for (SmallPtrSet<BasicBlock *, 4>::iterator I = StayEdges.begin(), E = StayEdges.end(); I != E; ++I) BP->setEdgeWeight(BB, *I, stayWeight); } if (uint32_t numRetEdges = ReturningEdges.size()) { uint32_t retWeight = RH_NONTAKEN_WEIGHT / numRetEdges; if (retWeight < MIN_WEIGHT) retWeight = MIN_WEIGHT; for (SmallPtrSet<BasicBlock *, 4>::iterator I = ReturningEdges.begin(), E = ReturningEdges.end(); I != E; ++I) { BP->setEdgeWeight(BB, *I, retWeight); } } return ReturningEdges.size() > 0; }
std::unique_ptr<CompilerInvocation> swift::driver::createCompilerInvocation(ArrayRef<const char *> ArgList, DiagnosticEngine &Diags) { SmallVector<const char *, 16> Args; Args.push_back("<swiftc>"); // FIXME: Remove dummy argument. Args.insert(Args.end(), ArgList.begin(), ArgList.end()); // When creating a CompilerInvocation, ensure that the driver creates a single // frontend command. Args.push_back("-force-single-frontend-invocation"); // Force the driver into batch mode by specifying "swiftc" as the name. Driver TheDriver("swiftc", "swiftc", Args, Diags); // Don't check for the existence of input files, since the user of the // CompilerInvocation may wish to remap inputs to source buffers. TheDriver.setCheckInputFilesExist(false); std::unique_ptr<Compilation> C = TheDriver.buildCompilation(Args); if (!C || C->getJobs().empty()) return nullptr; // Don't emit an error; one should already have been emitted SmallPtrSet<const Job *, 4> CompileCommands; for (const Job *Cmd : C->getJobs()) if (isa<CompileJobAction>(Cmd->getSource())) CompileCommands.insert(Cmd); if (CompileCommands.size() != 1) { // TODO: include Jobs in the diagnostic. Diags.diagnose(SourceLoc(), diag::error_expected_one_frontend_job); return nullptr; } const Job *Cmd = *CompileCommands.begin(); if (StringRef("-frontend") != Cmd->getArguments().front()) { Diags.diagnose(SourceLoc(), diag::error_expected_frontend_command); return nullptr; } std::unique_ptr<CompilerInvocation> Invocation(new CompilerInvocation()); const llvm::opt::ArgStringList &BaseFrontendArgs = Cmd->getArguments(); ArrayRef<const char *> FrontendArgs = llvm::makeArrayRef(BaseFrontendArgs.data() + 1, BaseFrontendArgs.data() + BaseFrontendArgs.size()); if (Invocation->parseArgs(FrontendArgs, Diags)) return nullptr; // Don't emit an error; one should already have been emitted return Invocation; }
/// \brief Find nearest common dominator of all uses. /// FIXME: Replace this with NearestCommonDominator once it is in common code. BasicBlock * ConstantHoisting::findIDomOfAllUses(const ConstantUseListType &Uses) const { // Collect all basic blocks. SmallPtrSet<BasicBlock *, 8> BBs; for (auto const &U : Uses) BBs.insert(findMatInsertPt(U.Inst, U.OpndIdx)->getParent()); if (BBs.count(Entry)) return Entry; while (BBs.size() >= 2) { BasicBlock *BB, *BB1, *BB2; BB1 = *BBs.begin(); BB2 = *std::next(BBs.begin()); BB = DT->findNearestCommonDominator(BB1, BB2); if (BB == Entry) return Entry; BBs.erase(BB1); BBs.erase(BB2); BBs.insert(BB); } assert((BBs.size() == 1) && "Expected only one element."); return *BBs.begin(); }
/// 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; }
// FindCopyInsertPoint - Find a safe place in MBB to insert a copy from SrcReg // when following the CFG edge to SuccMBB. This needs to be after any def of // SrcReg, but before any subsequent point where control flow might jump out of // the basic block. MachineBasicBlock::iterator llvm::PHIElimination::FindCopyInsertPoint(MachineBasicBlock &MBB, MachineBasicBlock &SuccMBB, unsigned SrcReg) { // Handle the trivial case trivially. if (MBB.empty()) return MBB.begin(); // Usually, we just want to insert the copy before the first terminator // instruction. However, for the edge going to a landing pad, we must insert // the copy before the call/invoke instruction. if (!SuccMBB.isLandingPad()) return MBB.getFirstTerminator(); // Discover any defs/uses in this basic block. SmallPtrSet<MachineInstr*, 8> DefUsesInMBB; for (MachineRegisterInfo::reg_iterator RI = MRI->reg_begin(SrcReg), RE = MRI->reg_end(); RI != RE; ++RI) { MachineInstr *DefUseMI = &*RI; if (DefUseMI->getParent() == &MBB) DefUsesInMBB.insert(DefUseMI); } MachineBasicBlock::iterator InsertPoint; if (DefUsesInMBB.empty()) { // No defs. Insert the copy at the start of the basic block. InsertPoint = MBB.begin(); } else if (DefUsesInMBB.size() == 1) { // Insert the copy immediately after the def/use. InsertPoint = *DefUsesInMBB.begin(); ++InsertPoint; } else { // Insert the copy immediately after the last def/use. InsertPoint = MBB.end(); while (!DefUsesInMBB.count(&*--InsertPoint)) {} ++InsertPoint; } // Make sure the copy goes after any phi nodes however. return SkipPHIsAndLabels(MBB, InsertPoint); }
// FindCopyInsertPoint - Find a safe place in MBB to insert a copy from SrcReg. // This needs to be after any def or uses of SrcReg, but before any subsequent // point where control flow might jump out of the basic block. MachineBasicBlock::iterator llvm::PHIElimination::FindCopyInsertPoint(MachineBasicBlock &MBB, unsigned SrcReg) { // Handle the trivial case trivially. if (MBB.empty()) return MBB.begin(); // If this basic block does not contain an invoke, then control flow always // reaches the end of it, so place the copy there. The logic below works in // this case too, but is more expensive. if (!isa<InvokeInst>(MBB.getBasicBlock()->getTerminator())) return MBB.getFirstTerminator(); // Discover any definition/uses in this basic block. SmallPtrSet<MachineInstr*, 8> DefUsesInMBB; for (MachineRegisterInfo::reg_iterator RI = MRI->reg_begin(SrcReg), RE = MRI->reg_end(); RI != RE; ++RI) { MachineInstr *DefUseMI = &*RI; if (DefUseMI->getParent() == &MBB) DefUsesInMBB.insert(DefUseMI); } MachineBasicBlock::iterator InsertPoint; if (DefUsesInMBB.empty()) { // No def/uses. Insert the copy at the start of the basic block. InsertPoint = MBB.begin(); } else if (DefUsesInMBB.size() == 1) { // Insert the copy immediately after the definition/use. InsertPoint = *DefUsesInMBB.begin(); ++InsertPoint; } else { // Insert the copy immediately after the last definition/use. InsertPoint = MBB.end(); while (!DefUsesInMBB.count(&*--InsertPoint)) {} ++InsertPoint; } // Make sure the copy goes after any phi nodes however. return SkipPHIsAndLabels(MBB, InsertPoint); }
// findCopyInsertPoint - Find a safe place in MBB to insert a copy from SrcReg // when following the CFG edge to SuccMBB. This needs to be after any def of // SrcReg, but before any subsequent point where control flow might jump out of // the basic block. MachineBasicBlock::iterator llvm::findPHICopyInsertPoint(MachineBasicBlock* MBB, MachineBasicBlock* SuccMBB, unsigned SrcReg) { // Handle the trivial case trivially. if (MBB->empty()) return MBB->begin(); // Usually, we just want to insert the copy before the first terminator // instruction. However, for the edge going to a landing pad, we must insert // the copy before the call/invoke instruction. if (!SuccMBB->isLandingPad()) return MBB->getFirstTerminator(); // Discover any defs/uses in this basic block. SmallPtrSet<MachineInstr*, 8> DefUsesInMBB; MachineRegisterInfo& MRI = MBB->getParent()->getRegInfo(); for (MachineInstr &RI : MRI.reg_instructions(SrcReg)) { if (RI.getParent() == MBB) DefUsesInMBB.insert(&RI); } MachineBasicBlock::iterator InsertPoint; if (DefUsesInMBB.empty()) { // No defs. Insert the copy at the start of the basic block. InsertPoint = MBB->begin(); } else if (DefUsesInMBB.size() == 1) { // Insert the copy immediately after the def/use. InsertPoint = *DefUsesInMBB.begin(); ++InsertPoint; } else { // Insert the copy immediately after the last def/use. InsertPoint = MBB->end(); while (!DefUsesInMBB.count(&*--InsertPoint)) {} ++InsertPoint; } // Make sure the copy goes after any phi nodes however. return MBB->SkipPHIsAndLabels(InsertPoint); }
void MachineVerifier::visitMachineBasicBlockBefore(const MachineBasicBlock *MBB) { FirstTerminator = 0; // Count the number of landing pad successors. SmallPtrSet<MachineBasicBlock*, 4> LandingPadSuccs; for (MachineBasicBlock::const_succ_iterator I = MBB->succ_begin(), E = MBB->succ_end(); I != E; ++I) { if ((*I)->isLandingPad()) LandingPadSuccs.insert(*I); } const MCAsmInfo *AsmInfo = TM->getMCAsmInfo(); const BasicBlock *BB = MBB->getBasicBlock(); if (LandingPadSuccs.size() > 1 && !(AsmInfo && AsmInfo->getExceptionHandlingType() == ExceptionHandling::SjLj && BB && isa<SwitchInst>(BB->getTerminator()))) report("MBB has more than one landing pad successor", MBB); // Call AnalyzeBranch. If it succeeds, there several more conditions to check. MachineBasicBlock *TBB = 0, *FBB = 0; SmallVector<MachineOperand, 4> Cond; if (!TII->AnalyzeBranch(*const_cast<MachineBasicBlock *>(MBB), TBB, FBB, Cond)) { // Ok, AnalyzeBranch thinks it knows what's going on with this block. Let's // check whether its answers match up with reality. if (!TBB && !FBB) { // Block falls through to its successor. MachineFunction::const_iterator MBBI = MBB; ++MBBI; if (MBBI == MF->end()) { // It's possible that the block legitimately ends with a noreturn // call or an unreachable, in which case it won't actually fall // out the bottom of the function. } else if (MBB->succ_size() == LandingPadSuccs.size()) { // It's possible that the block legitimately ends with a noreturn // call or an unreachable, in which case it won't actuall fall // out of the block. } else if (MBB->succ_size() != 1+LandingPadSuccs.size()) { report("MBB exits via unconditional fall-through but doesn't have " "exactly one CFG successor!", MBB); } else if (!MBB->isSuccessor(MBBI)) { report("MBB exits via unconditional fall-through but its successor " "differs from its CFG successor!", MBB); } if (!MBB->empty() && MBB->back().getDesc().isBarrier() && !TII->isPredicated(&MBB->back())) { report("MBB exits via unconditional fall-through but ends with a " "barrier instruction!", MBB); } if (!Cond.empty()) { report("MBB exits via unconditional fall-through but has a condition!", MBB); } } else if (TBB && !FBB && Cond.empty()) { // Block unconditionally branches somewhere. if (MBB->succ_size() != 1+LandingPadSuccs.size()) { report("MBB exits via unconditional branch but doesn't have " "exactly one CFG successor!", MBB); } else if (!MBB->isSuccessor(TBB)) { report("MBB exits via unconditional branch but the CFG " "successor doesn't match the actual successor!", MBB); } if (MBB->empty()) { report("MBB exits via unconditional branch but doesn't contain " "any instructions!", MBB); } else if (!MBB->back().getDesc().isBarrier()) { report("MBB exits via unconditional branch but doesn't end with a " "barrier instruction!", MBB); } else if (!MBB->back().getDesc().isTerminator()) { report("MBB exits via unconditional branch but the branch isn't a " "terminator instruction!", MBB); } } else if (TBB && !FBB && !Cond.empty()) { // Block conditionally branches somewhere, otherwise falls through. MachineFunction::const_iterator MBBI = MBB; ++MBBI; if (MBBI == MF->end()) { report("MBB conditionally falls through out of function!", MBB); } if (MBB->succ_size() != 2) { report("MBB exits via conditional branch/fall-through but doesn't have " "exactly two CFG successors!", MBB); } else if (!matchPair(MBB->succ_begin(), TBB, MBBI)) { report("MBB exits via conditional branch/fall-through but the CFG " "successors don't match the actual successors!", MBB); } if (MBB->empty()) { report("MBB exits via conditional branch/fall-through but doesn't " "contain any instructions!", MBB); } else if (MBB->back().getDesc().isBarrier()) { report("MBB exits via conditional branch/fall-through but ends with a " "barrier instruction!", MBB); } else if (!MBB->back().getDesc().isTerminator()) { report("MBB exits via conditional branch/fall-through but the branch " "isn't a terminator instruction!", MBB); } } else if (TBB && FBB) { // Block conditionally branches somewhere, otherwise branches // somewhere else. if (MBB->succ_size() != 2) { report("MBB exits via conditional branch/branch but doesn't have " "exactly two CFG successors!", MBB); } else if (!matchPair(MBB->succ_begin(), TBB, FBB)) { report("MBB exits via conditional branch/branch but the CFG " "successors don't match the actual successors!", MBB); } if (MBB->empty()) { report("MBB exits via conditional branch/branch but doesn't " "contain any instructions!", MBB); } else if (!MBB->back().getDesc().isBarrier()) { report("MBB exits via conditional branch/branch but doesn't end with a " "barrier instruction!", MBB); } else if (!MBB->back().getDesc().isTerminator()) { report("MBB exits via conditional branch/branch but the branch " "isn't a terminator instruction!", MBB); } if (Cond.empty()) { report("MBB exits via conditinal branch/branch but there's no " "condition!", MBB); } } else { report("AnalyzeBranch returned invalid data!", MBB); } } regsLive.clear(); for (MachineBasicBlock::livein_iterator I = MBB->livein_begin(), E = MBB->livein_end(); I != E; ++I) { if (!TargetRegisterInfo::isPhysicalRegister(*I)) { report("MBB live-in list contains non-physical register", MBB); continue; } regsLive.insert(*I); for (const unsigned *R = TRI->getSubRegisters(*I); *R; R++) regsLive.insert(*R); } regsLiveInButUnused = regsLive; const MachineFrameInfo *MFI = MF->getFrameInfo(); assert(MFI && "Function has no frame info"); BitVector PR = MFI->getPristineRegs(MBB); for (int I = PR.find_first(); I>0; I = PR.find_next(I)) { regsLive.insert(I); for (const unsigned *R = TRI->getSubRegisters(I); *R; R++) regsLive.insert(*R); } regsKilled.clear(); regsDefined.clear(); if (Indexes) lastIndex = Indexes->getMBBStartIdx(MBB); }
bool ReduceCrashingBlocks::TestBlocks(std::vector<const BasicBlock*> &BBs) { // Clone the program to try hacking it apart... ValueToValueMapTy VMap; Module *M = CloneModule(BD.getProgram(), VMap); // Convert list to set for fast lookup... SmallPtrSet<BasicBlock*, 8> Blocks; for (unsigned i = 0, e = BBs.size(); i != e; ++i) Blocks.insert(cast<BasicBlock>(VMap[BBs[i]])); outs() << "Checking for crash with only these blocks:"; unsigned NumPrint = Blocks.size(); if (NumPrint > 10) NumPrint = 10; for (unsigned i = 0, e = NumPrint; i != e; ++i) outs() << " " << BBs[i]->getName(); if (NumPrint < Blocks.size()) outs() << "... <" << Blocks.size() << " total>"; outs() << ": "; // Loop over and delete any hack up any blocks that are not listed... for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) for (Function::iterator BB = I->begin(), E = I->end(); BB != E; ++BB) if (!Blocks.count(&*BB) && BB->getTerminator()->getNumSuccessors()) { // Loop over all of the successors of this block, deleting any PHI nodes // that might include it. for (succ_iterator SI = succ_begin(&*BB), E = succ_end(&*BB); SI != E; ++SI) (*SI)->removePredecessor(&*BB); TerminatorInst *BBTerm = BB->getTerminator(); if (!BB->getTerminator()->getType()->isVoidTy()) BBTerm->replaceAllUsesWith(Constant::getNullValue(BBTerm->getType())); // Replace the old terminator instruction. BB->getInstList().pop_back(); new UnreachableInst(BB->getContext(), &*BB); } // The CFG Simplifier pass may delete one of the basic blocks we are // interested in. If it does we need to take the block out of the list. Make // a "persistent mapping" by turning basic blocks into <function, name> pairs. // This won't work well if blocks are unnamed, but that is just the risk we // have to take. std::vector<std::pair<std::string, std::string> > BlockInfo; for (BasicBlock *BB : Blocks) BlockInfo.emplace_back(BB->getParent()->getName(), BB->getName()); // Now run the CFG simplify pass on the function... std::vector<std::string> Passes; Passes.push_back("simplifycfg"); Passes.push_back("verify"); std::unique_ptr<Module> New = BD.runPassesOn(M, Passes); delete M; if (!New) { errs() << "simplifycfg failed!\n"; exit(1); } M = New.release(); // Try running on the hacked up program... if (TestFn(BD, M)) { BD.setNewProgram(M); // It crashed, keep the trimmed version... // Make sure to use basic block pointers that point into the now-current // module, and that they don't include any deleted blocks. BBs.clear(); const ValueSymbolTable &GST = M->getValueSymbolTable(); for (unsigned i = 0, e = BlockInfo.size(); i != e; ++i) { Function *F = cast<Function>(GST.lookup(BlockInfo[i].first)); ValueSymbolTable &ST = F->getValueSymbolTable(); Value* V = ST.lookup(BlockInfo[i].second); if (V && V->getType() == Type::getLabelTy(V->getContext())) BBs.push_back(cast<BasicBlock>(V)); } return true; } delete M; // It didn't crash, try something else. return false; }
// Calculate Edge Weights using "Loop Branch Heuristics". Predict backedges // as taken, exiting edges as not-taken. bool BranchProbabilityAnalysis::calcLoopBranchHeuristics(BasicBlock *BB) { uint32_t numSuccs = BB->getTerminator()->getNumSuccessors(); Loop *L = LI->getLoopFor(BB); if (!L) return false; SmallPtrSet<BasicBlock *, 8> BackEdges; SmallPtrSet<BasicBlock *, 8> ExitingEdges; SmallPtrSet<BasicBlock *, 8> InEdges; // Edges from header to the loop. bool isHeader = BB == L->getHeader(); for (succ_iterator I = succ_begin(BB), E = succ_end(BB); I != E; ++I) { BasicBlock *Succ = *I; Loop *SuccL = LI->getLoopFor(Succ); if (SuccL != L) ExitingEdges.insert(Succ); else if (Succ == L->getHeader()) BackEdges.insert(Succ); else if (isHeader) InEdges.insert(Succ); } if (uint32_t numBackEdges = BackEdges.size()) { uint32_t backWeight = LBH_TAKEN_WEIGHT / numBackEdges; if (backWeight < NORMAL_WEIGHT) backWeight = NORMAL_WEIGHT; for (SmallPtrSet<BasicBlock *, 8>::iterator EI = BackEdges.begin(), EE = BackEdges.end(); EI != EE; ++EI) { BasicBlock *Back = *EI; BP->setEdgeWeight(BB, Back, backWeight); } } if (uint32_t numInEdges = InEdges.size()) { uint32_t inWeight = LBH_TAKEN_WEIGHT / numInEdges; if (inWeight < NORMAL_WEIGHT) inWeight = NORMAL_WEIGHT; for (SmallPtrSet<BasicBlock *, 8>::iterator EI = InEdges.begin(), EE = InEdges.end(); EI != EE; ++EI) { BasicBlock *Back = *EI; BP->setEdgeWeight(BB, Back, inWeight); } } uint32_t numExitingEdges = ExitingEdges.size(); if (uint32_t numNonExitingEdges = numSuccs - numExitingEdges) { uint32_t exitWeight = LBH_NONTAKEN_WEIGHT / numNonExitingEdges; if (exitWeight < MIN_WEIGHT) exitWeight = MIN_WEIGHT; for (SmallPtrSet<BasicBlock *, 8>::iterator EI = ExitingEdges.begin(), EE = ExitingEdges.end(); EI != EE; ++EI) { BasicBlock *Exiting = *EI; BP->setEdgeWeight(BB, Exiting, exitWeight); } } return true; }
/// \brief Retrieve the set of potential type bindings for the given /// representative type variable, along with flags indicating whether /// those types should be opened. ConstraintSystem::PotentialBindings ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) { assert(typeVar->getImpl().getRepresentative(nullptr) == typeVar && "not a representative"); assert(!typeVar->getImpl().getFixedType(nullptr) && "has a fixed type"); // Gather the constraints associated with this type variable. SmallVector<Constraint *, 8> constraints; llvm::SmallPtrSet<Constraint *, 4> visitedConstraints; getConstraintGraph().gatherConstraints( typeVar, constraints, ConstraintGraph::GatheringKind::EquivalenceClass); PotentialBindings result(typeVar); // Consider each of the constraints related to this type variable. llvm::SmallPtrSet<CanType, 4> exactTypes; llvm::SmallPtrSet<ProtocolDecl *, 4> literalProtocols; SmallVector<Constraint *, 2> defaultableConstraints; bool addOptionalSupertypeBindings = false; auto &tc = getTypeChecker(); bool hasNonDependentMemberRelationalConstraints = false; bool hasDependentMemberRelationalConstraints = false; for (auto constraint : constraints) { // Only visit each constraint once. if (!visitedConstraints.insert(constraint).second) continue; switch (constraint->getKind()) { case ConstraintKind::Bind: case ConstraintKind::Equal: case ConstraintKind::BindParam: case ConstraintKind::BindToPointerType: case ConstraintKind::Subtype: case ConstraintKind::Conversion: case ConstraintKind::ArgumentConversion: case ConstraintKind::ArgumentTupleConversion: case ConstraintKind::OperatorArgumentTupleConversion: case ConstraintKind::OperatorArgumentConversion: case ConstraintKind::OptionalObject: // Relational constraints: break out to look for types above/below. break; case ConstraintKind::BridgingConversion: case ConstraintKind::CheckedCast: case ConstraintKind::EscapableFunctionOf: case ConstraintKind::OpenedExistentialOf: case ConstraintKind::KeyPath: case ConstraintKind::KeyPathApplication: // Constraints from which we can't do anything. continue; case ConstraintKind::DynamicTypeOf: { // Direct binding of the left-hand side could result // in `DynamicTypeOf` failure if right-hand side is // bound (because 'Bind' requires equal types to // succeed), or left is bound to Any which is not an // [existential] metatype. auto dynamicType = constraint->getFirstType(); if (auto *tv = dynamicType->getAs<TypeVariableType>()) { if (tv->getImpl().getRepresentative(nullptr) == typeVar) return {typeVar}; } // This is right-hand side, let's continue. continue; } case ConstraintKind::Defaultable: // Do these in a separate pass. if (getFixedTypeRecursive(constraint->getFirstType(), true) ->getAs<TypeVariableType>() == typeVar) { defaultableConstraints.push_back(constraint); hasNonDependentMemberRelationalConstraints = true; } continue; case ConstraintKind::Disjunction: // FIXME: Recurse into these constraints to see whether this // type variable is fully bound by any of them. result.InvolvesTypeVariables = true; continue; case ConstraintKind::ConformsTo: case ConstraintKind::SelfObjectOfProtocol: // Swift 3 allowed the use of default types for normal conformances // to expressible-by-literal protocols. if (tc.Context.LangOpts.EffectiveLanguageVersion[0] >= 4) continue; if (!constraint->getSecondType()->is<ProtocolType>()) continue; LLVM_FALLTHROUGH; case ConstraintKind::LiteralConformsTo: { // If there is a 'nil' literal constraint, we might need optional // supertype bindings. if (constraint->getProtocol()->isSpecificProtocol( KnownProtocolKind::ExpressibleByNilLiteral)) addOptionalSupertypeBindings = true; // If there is a default literal type for this protocol, it's a // potential binding. auto defaultType = tc.getDefaultType(constraint->getProtocol(), DC); if (!defaultType) continue; // Note that we have a literal constraint with this protocol. literalProtocols.insert(constraint->getProtocol()); hasNonDependentMemberRelationalConstraints = true; // Handle unspecialized types directly. if (!defaultType->hasUnboundGenericType()) { if (!exactTypes.insert(defaultType->getCanonicalType()).second) continue; result.foundLiteralBinding(constraint->getProtocol()); result.addPotentialBinding({defaultType, AllowedBindingKind::Subtypes, constraint->getKind(), constraint->getProtocol()}); continue; } // For generic literal types, check whether we already have a // specialization of this generic within our list. // FIXME: This assumes that, e.g., the default literal // int/float/char/string types are never generic. auto nominal = defaultType->getAnyNominal(); if (!nominal) continue; bool matched = false; for (auto exactType : exactTypes) { if (auto exactNominal = exactType->getAnyNominal()) { // FIXME: Check parents? if (nominal == exactNominal) { matched = true; break; } } } if (!matched) { result.foundLiteralBinding(constraint->getProtocol()); exactTypes.insert(defaultType->getCanonicalType()); result.addPotentialBinding({defaultType, AllowedBindingKind::Subtypes, constraint->getKind(), constraint->getProtocol()}); } continue; } case ConstraintKind::ApplicableFunction: case ConstraintKind::BindOverload: { if (result.FullyBound && result.InvolvesTypeVariables) continue; // If this variable is in the left-hand side, it is fully bound. SmallPtrSet<TypeVariableType *, 4> typeVars; findInferableTypeVars(simplifyType(constraint->getFirstType()), typeVars); if (typeVars.count(typeVar)) result.FullyBound = true; if (result.InvolvesTypeVariables) continue; // If this and another type variable occur, this result involves // type variables. findInferableTypeVars(simplifyType(constraint->getSecondType()), typeVars); if (typeVars.size() > 1 && typeVars.count(typeVar)) result.InvolvesTypeVariables = true; continue; } case ConstraintKind::ValueMember: case ConstraintKind::UnresolvedValueMember: // If our type variable shows up in the base type, there's // nothing to do. // FIXME: Can we avoid simplification here? if (ConstraintSystem::typeVarOccursInType( typeVar, simplifyType(constraint->getFirstType()), &result.InvolvesTypeVariables)) { continue; } // If the type variable is in the list of member type // variables, it is fully bound. // FIXME: Can we avoid simplification here? if (ConstraintSystem::typeVarOccursInType( typeVar, simplifyType(constraint->getSecondType()), &result.InvolvesTypeVariables)) { result.FullyBound = true; } continue; } // Handle relational constraints. assert(constraint->getClassification() == ConstraintClassification::Relational && "only relational constraints handled here"); // Record constraint which contributes to the // finding of pontential bindings. result.Sources.insert(constraint); auto first = simplifyType(constraint->getFirstType()); auto second = simplifyType(constraint->getSecondType()); if (first->is<TypeVariableType>() && first->isEqual(second)) continue; Type type; AllowedBindingKind kind; if (first->getAs<TypeVariableType>() == typeVar) { // Upper bound for this type variable. type = second; kind = AllowedBindingKind::Subtypes; } else if (second->getAs<TypeVariableType>() == typeVar) { // Lower bound for this type variable. type = first; kind = AllowedBindingKind::Supertypes; } else { // Can't infer anything. if (result.InvolvesTypeVariables) continue; // Check whether both this type and another type variable are // inferable. SmallPtrSet<TypeVariableType *, 4> typeVars; findInferableTypeVars(first, typeVars); findInferableTypeVars(second, typeVars); if (typeVars.size() > 1 && typeVars.count(typeVar)) result.InvolvesTypeVariables = true; continue; } // Do not attempt to bind to ErrorType. if (type->hasError()) continue; // If the type we'd be binding to is a dependent member, don't try to // resolve this type variable yet. if (type->is<DependentMemberType>()) { if (!ConstraintSystem::typeVarOccursInType( typeVar, type, &result.InvolvesTypeVariables)) { hasDependentMemberRelationalConstraints = true; } continue; } hasNonDependentMemberRelationalConstraints = true; // Check whether we can perform this binding. // FIXME: this has a super-inefficient extraneous simplifyType() in it. bool isNilLiteral = false; bool *isNilLiteralPtr = nullptr; if (!addOptionalSupertypeBindings && kind == AllowedBindingKind::Supertypes) isNilLiteralPtr = &isNilLiteral; if (auto boundType = checkTypeOfBinding(typeVar, type, isNilLiteralPtr)) { type = *boundType; if (type->hasTypeVariable()) result.InvolvesTypeVariables = true; } else { // If the bound is a 'nil' literal type, add optional supertype bindings. if (isNilLiteral) { addOptionalSupertypeBindings = true; continue; } result.InvolvesTypeVariables = true; continue; } // Don't deduce autoclosure types or single-element, non-variadic // tuples. if (shouldBindToValueType(constraint)) { if (auto funcTy = type->getAs<FunctionType>()) { if (funcTy->isAutoClosure()) type = funcTy->getResult(); } type = type->getWithoutImmediateLabel(); } // Make sure we aren't trying to equate type variables with different // lvalue-binding rules. if (auto otherTypeVar = type->lookThroughAllOptionalTypes()->getAs<TypeVariableType>()) { if (typeVar->getImpl().canBindToLValue() != otherTypeVar->getImpl().canBindToLValue()) continue; } // BindParam constraints are not reflexive and must be treated specially. if (constraint->getKind() == ConstraintKind::BindParam) { if (kind == AllowedBindingKind::Subtypes) { if (auto *lvt = type->getAs<LValueType>()) { type = InOutType::get(lvt->getObjectType()); } } else if (kind == AllowedBindingKind::Supertypes) { if (auto *iot = type->getAs<InOutType>()) { type = LValueType::get(iot->getObjectType()); } } kind = AllowedBindingKind::Exact; } if (exactTypes.insert(type->getCanonicalType()).second) result.addPotentialBinding({type, kind, constraint->getKind()}); } // If we have any literal constraints, check whether there is already a // binding that provides a type that conforms to that literal protocol. In // such cases, remove the default binding suggestion because the existing // suggestion is better. if (!literalProtocols.empty()) { SmallPtrSet<ProtocolDecl *, 5> coveredLiteralProtocols; for (auto &binding : result.Bindings) { // Skip defaulted-protocol constraints. if (binding.DefaultedProtocol) continue; Type testType; switch (binding.Kind) { case AllowedBindingKind::Exact: testType = binding.BindingType; break; case AllowedBindingKind::Subtypes: case AllowedBindingKind::Supertypes: testType = binding.BindingType->getRValueType(); break; } // Check each non-covered literal protocol to determine which ones bool updatedBindingType = false; for (auto proto : literalProtocols) { do { // If the type conforms to this protocol, we're covered. if (tc.conformsToProtocol( testType, proto, DC, (ConformanceCheckFlags::InExpression| ConformanceCheckFlags::SkipConditionalRequirements))) { coveredLiteralProtocols.insert(proto); break; } // If we're allowed to bind to subtypes, look through optionals. // FIXME: This is really crappy special case of computing a reasonable // result based on the given constraints. if (binding.Kind == AllowedBindingKind::Subtypes) { if (auto objTy = testType->getOptionalObjectType()) { updatedBindingType = true; testType = objTy; continue; } } updatedBindingType = false; break; } while (true); } if (updatedBindingType) binding.BindingType = testType; } // For any literal type that has been covered, remove the default literal // type. if (!coveredLiteralProtocols.empty()) { result.Bindings.erase( std::remove_if(result.Bindings.begin(), result.Bindings.end(), [&](PotentialBinding &binding) { return binding.DefaultedProtocol && coveredLiteralProtocols.count( *binding.DefaultedProtocol) > 0; }), result.Bindings.end()); } } /// Add defaultable constraints last. for (auto constraint : defaultableConstraints) { Type type = constraint->getSecondType(); if (!exactTypes.insert(type->getCanonicalType()).second) continue; ++result.NumDefaultableBindings; result.addPotentialBinding({type, AllowedBindingKind::Exact, constraint->getKind(), None, constraint->getLocator()}); } // Determine if the bindings only constrain the type variable from above with // an existential type; such a binding is not very helpful because it's // impossible to enumerate the existential type's subtypes. result.SubtypeOfExistentialType = std::all_of(result.Bindings.begin(), result.Bindings.end(), [](const PotentialBinding &binding) { return binding.BindingType->isExistentialType() && binding.Kind == AllowedBindingKind::Subtypes; }); // If we're supposed to add optional supertype bindings, do so now. if (addOptionalSupertypeBindings) { for (unsigned i : indices(result.Bindings)) { auto &binding = result.Bindings[i]; bool wrapInOptional = false; if (binding.Kind == AllowedBindingKind::Supertypes) { // If the type doesn't conform to ExpressibleByNilLiteral, // produce an optional of that type as a potential binding. We // overwrite the binding in place because the non-optional type // will fail to type-check against the nil-literal conformance. auto nominalBindingDecl = binding.BindingType->getRValueType()->getAnyNominal(); bool conformsToExprByNilLiteral = false; if (nominalBindingDecl) { SmallVector<ProtocolConformance *, 2> conformances; conformsToExprByNilLiteral = nominalBindingDecl->lookupConformance( DC->getParentModule(), getASTContext().getProtocol( KnownProtocolKind::ExpressibleByNilLiteral), conformances); } wrapInOptional = !conformsToExprByNilLiteral; } else if (binding.isDefaultableBinding() && binding.BindingType->isAny()) { wrapInOptional = true; } if (wrapInOptional) { binding.BindingType = OptionalType::get(binding.BindingType); } } } // If there were both dependent-member and non-dependent-member relational // constraints, consider this "fully bound"; we don't want to touch it. if (hasDependentMemberRelationalConstraints) { if (hasNonDependentMemberRelationalConstraints) result.FullyBound = true; else result.Bindings.clear(); } return result; }
bool ReduceSimplifyCFG::TestBlocks(std::vector<const BasicBlock *> &BBs) { // Clone the program to try hacking it apart... ValueToValueMapTy VMap; Module *M = CloneModule(BD.getProgram(), VMap).release(); // Convert list to set for fast lookup... SmallPtrSet<const BasicBlock *, 8> Blocks; for (const auto *BB : BBs) Blocks.insert(cast<BasicBlock>(VMap[BB])); outs() << "Checking for crash with CFG simplifying:"; unsigned NumPrint = Blocks.size(); if (NumPrint > 10) NumPrint = 10; for (unsigned i = 0, e = NumPrint; i != e; ++i) outs() << " " << BBs[i]->getName(); if (NumPrint < Blocks.size()) outs() << "... <" << Blocks.size() << " total>"; outs() << ": "; // The following may destroy some blocks, so we save them first std::vector<std::pair<std::string, std::string>> BlockInfo; for (const BasicBlock *BB : Blocks) BlockInfo.emplace_back(BB->getParent()->getName(), BB->getName()); // Loop over and delete any hack up any blocks that are not listed... for (auto &F : *M) // Loop over all of the basic blocks and remove them if they are unneeded. for (Function::iterator BBIt = F.begin(); BBIt != F.end();) { if (!Blocks.count(&*BBIt)) { ++BBIt; continue; } SimplifyCFG(&*BBIt++, TTI, 1); } // Verify we didn't break anything std::vector<std::string> Passes; Passes.push_back("verify"); std::unique_ptr<Module> New = BD.runPassesOn(M, Passes); delete M; if (!New) { errs() << "verify failed!\n"; exit(1); } M = New.release(); // Try running on the hacked up program... if (TestFn(BD, M)) { BD.setNewProgram(M); // It crashed, keep the trimmed version... // Make sure to use basic block pointers that point into the now-current // module, and that they don't include any deleted blocks. BBs.clear(); const ValueSymbolTable &GST = M->getValueSymbolTable(); for (auto &BI : BlockInfo) { auto *F = cast<Function>(GST.lookup(BI.first)); Value *V = F->getValueSymbolTable()->lookup(BI.second); if (V && V->getType() == Type::getLabelTy(V->getContext())) BBs.push_back(cast<BasicBlock>(V)); } return true; } delete M; // It didn't crash, try something else. return false; }
// Sinks \p I from the loop \p L's preheader to its uses. Returns true if // sinking is successful. // \p LoopBlockNumber is used to sort the insertion blocks to ensure // determinism. static bool sinkInstruction(Loop &L, Instruction &I, const SmallVectorImpl<BasicBlock *> &ColdLoopBBs, const SmallDenseMap<BasicBlock *, int, 16> &LoopBlockNumber, LoopInfo &LI, DominatorTree &DT, BlockFrequencyInfo &BFI) { // Compute the set of blocks in loop L which contain a use of I. SmallPtrSet<BasicBlock *, 2> BBs; for (auto &U : I.uses()) { Instruction *UI = cast<Instruction>(U.getUser()); // We cannot sink I to PHI-uses. if (dyn_cast<PHINode>(UI)) return false; // We cannot sink I if it has uses outside of the loop. if (!L.contains(LI.getLoopFor(UI->getParent()))) return false; BBs.insert(UI->getParent()); } // findBBsToSinkInto is O(BBs.size() * ColdLoopBBs.size()). We cap the max // BBs.size() to avoid expensive computation. // FIXME: Handle code size growth for min_size and opt_size. if (BBs.size() > MaxNumberOfUseBBsForSinking) return false; // Find the set of BBs that we should insert a copy of I. SmallPtrSet<BasicBlock *, 2> BBsToSinkInto = findBBsToSinkInto(L, BBs, ColdLoopBBs, DT, BFI); if (BBsToSinkInto.empty()) return false; // Copy the final BBs into a vector and sort them using the total ordering // of the loop block numbers as iterating the set doesn't give a useful // order. No need to stable sort as the block numbers are a total ordering. SmallVector<BasicBlock *, 2> SortedBBsToSinkInto; SortedBBsToSinkInto.insert(SortedBBsToSinkInto.begin(), BBsToSinkInto.begin(), BBsToSinkInto.end()); std::sort(SortedBBsToSinkInto.begin(), SortedBBsToSinkInto.end(), [&](BasicBlock *A, BasicBlock *B) { return *LoopBlockNumber.find(A) < *LoopBlockNumber.find(B); }); BasicBlock *MoveBB = *SortedBBsToSinkInto.begin(); // FIXME: Optimize the efficiency for cloned value replacement. The current // implementation is O(SortedBBsToSinkInto.size() * I.num_uses()). for (BasicBlock *N : SortedBBsToSinkInto) { if (N == MoveBB) continue; // Clone I and replace its uses. Instruction *IC = I.clone(); IC->setName(I.getName()); IC->insertBefore(&*N->getFirstInsertionPt()); // Replaces uses of I with IC in N for (Value::use_iterator UI = I.use_begin(), UE = I.use_end(); UI != UE;) { Use &U = *UI++; auto *I = cast<Instruction>(U.getUser()); if (I->getParent() == N) U.set(IC); } // Replaces uses of I with IC in blocks dominated by N replaceDominatedUsesWith(&I, IC, DT, N); DEBUG(dbgs() << "Sinking a clone of " << I << " To: " << N->getName() << '\n'); NumLoopSunkCloned++; } DEBUG(dbgs() << "Sinking " << I << " To: " << MoveBB->getName() << '\n'); NumLoopSunk++; I.moveBefore(&*MoveBB->getFirstInsertionPt()); return true; }
void RealizeRMC::findActions() { // First, collect all calls to register actions SmallPtrSet<CallInst *, 8> registrations; for (inst_iterator is = inst_begin(func_), ie = inst_end(func_); is != ie; is++) { if (CallInst *call = dyn_cast<CallInst>(&*is)) { if (Function *target = call->getCalledFunction()) { if (target->getName() == "__rmc_action_register") { registrations.insert(call); } } } } // Now, make the vector of actions and a mapping from BasicBlock *. // We, somewhat tastelessly, reserve space for 3x the number of // actions we actually have so that we have space for new pre/post // actions that we might need to dummy up. // We need to have all the space reserved in advance so that our // pointers don't get invalidated when a resize happens. actions_.reserve(3 * registrations.size()); numNormalActions_ = registrations.size(); for (auto reg : registrations) { // FIXME: this scheme only works if we've run mem2reg. Otherwise we // need to chase through the alloca... assert(reg->hasOneUse()); Instruction *close = cast<Instruction>(*reg->user_begin()); StringRef name = getStringArg(reg->getOperand(0)); // Now that we have found the start and the end of the action, // split the action into its own (group of) basic blocks so that // we can work with it more easily. // Split once to make a start block BasicBlock *start = splitBlock(reg->getParent(), reg); start->setName("_rmc_start_" + name); // Split it again so the start block is empty and we have our main block BasicBlock *main = splitBlock(start, reg); main->setName("_rmc_" + name); // Now split the end to get our tail block BasicBlock *end = splitBlock(close->getParent(), close); // Every action needs to have a well-defined single "out block" // that is the last block of the action that doesn't contain any // code from after the action (like the end block does). If there // isn't such a block, we shave off an empty one from the end // block. Note that we can use an existing out block even in // multi-block actions as long as there is a unique one. BasicBlock *out = end->getSinglePredecessor(); if (!out) { out = end; end = splitBlock(close->getParent(), close); out->setName("_rmc_out_" + name); } end->setName("_rmc_end_" + name); // There is a subtly here: further processing of actions can cause // the out block to get split, leaving our pointer to it wrong // (since if it gets split we want the *later* block). // We work around this in a hacky way by storing the *end* block // instead and then patching them up once we have processed all // the actions. actions_.emplace_back(main, end, name); bb2action_[main] = &actions_.back(); deleteRegisterCall(reg); deleteRegisterCall(close); } // Now we need to go fix up our out blocks. for (auto & action : actions_) { BasicBlock *out = action.outBlock->getSinglePredecessor(); assert(out); action.outBlock = out; } }
bool ReduceCrashingConditionals::TestBlocks( std::vector<const BasicBlock *> &BBs) { // Clone the program to try hacking it apart... ValueToValueMapTy VMap; Module *M = CloneModule(BD.getProgram(), VMap).release(); // Convert list to set for fast lookup... SmallPtrSet<const BasicBlock *, 8> Blocks; for (const auto *BB : BBs) Blocks.insert(cast<BasicBlock>(VMap[BB])); outs() << "Checking for crash with changing conditionals to always jump to " << (Direction ? "true" : "false") << ":"; unsigned NumPrint = Blocks.size(); if (NumPrint > 10) NumPrint = 10; for (unsigned i = 0, e = NumPrint; i != e; ++i) outs() << " " << BBs[i]->getName(); if (NumPrint < Blocks.size()) outs() << "... <" << Blocks.size() << " total>"; outs() << ": "; // Loop over and delete any hack up any blocks that are not listed... for (auto &F : *M) for (auto &BB : F) if (!Blocks.count(&BB)) { auto *BR = dyn_cast<BranchInst>(BB.getTerminator()); if (!BR || !BR->isConditional()) continue; if (Direction) BR->setCondition(ConstantInt::getTrue(BR->getContext())); else BR->setCondition(ConstantInt::getFalse(BR->getContext())); } // The following may destroy some blocks, so we save them first std::vector<std::pair<std::string, std::string>> BlockInfo; for (const BasicBlock *BB : Blocks) BlockInfo.emplace_back(BB->getParent()->getName(), BB->getName()); SmallVector<BasicBlock *, 16> ToProcess; for (auto &F : *M) { for (auto &BB : F) if (!Blocks.count(&BB)) ToProcess.push_back(&BB); simpleSimplifyCfg(F, ToProcess); ToProcess.clear(); } // Verify we didn't break anything std::vector<std::string> Passes; Passes.push_back("verify"); std::unique_ptr<Module> New = BD.runPassesOn(M, Passes); delete M; if (!New) { errs() << "verify failed!\n"; exit(1); } M = New.release(); // Try running on the hacked up program... if (TestFn(BD, M)) { BD.setNewProgram(M); // It crashed, keep the trimmed version... // Make sure to use basic block pointers that point into the now-current // module, and that they don't include any deleted blocks. BBs.clear(); const ValueSymbolTable &GST = M->getValueSymbolTable(); for (auto &BI : BlockInfo) { auto *F = cast<Function>(GST.lookup(BI.first)); Value *V = F->getValueSymbolTable()->lookup(BI.second); if (V && V->getType() == Type::getLabelTy(V->getContext())) BBs.push_back(cast<BasicBlock>(V)); } return true; } delete M; // It didn't crash, try something else. return false; }