/// Determine the number of iterations the loop is at most executed. The loop /// might contain early exits so this is the maximum if no early exits are /// taken. static Optional<uint64_t> getMaxLoopTripCount(SILLoop *Loop, SILBasicBlock *Preheader, SILBasicBlock *Header, SILBasicBlock *Latch) { // Skip a split backedge. SILBasicBlock *OrigLatch = Latch; if (!Loop->isLoopExiting(Latch) && !(Latch = Latch->getSinglePredecessor())) return None; if (!Loop->isLoopExiting(Latch)) return None; // Get the loop exit condition. auto *CondBr = dyn_cast<CondBranchInst>(Latch->getTerminator()); if (!CondBr) return None; // Match an add 1 recurrence. SILArgument *RecArg; IntegerLiteralInst *End; SILValue RecNext; if (!match(CondBr->getCondition(), m_BuiltinInst(BuiltinValueKind::ICMP_EQ, m_SILValue(RecNext), m_IntegerLiteralInst(End)))) return None; if (!match(RecNext, m_TupleExtractInst(m_ApplyInst(BuiltinValueKind::SAddOver, m_SILArgument(RecArg), m_One()), 0))) return None; if (RecArg->getParent() != Header) return None; auto *Start = dyn_cast_or_null<IntegerLiteralInst>( RecArg->getIncomingValue(Preheader).getDef()); if (!Start) return None; if (RecNext != RecArg->getIncomingValue(OrigLatch)) return None; auto StartVal = Start->getValue(); auto EndVal = End->getValue(); if (StartVal.sgt(EndVal)) return None; auto Dist = EndVal - StartVal; if (Dist.getBitWidth() > 64) return None; if (Dist == 0) return None; return Dist.getZExtValue(); }
/// \brief Issue diagnostics whenever we see Builtin.static_report(1, ...). static void diagnoseStaticReports(const SILInstruction *I, SILModule &M) { // Find out if we are dealing with Builtin.staticReport(). if (auto *BI = dyn_cast<BuiltinInst>(I)) { const BuiltinInfo &B = BI->getBuiltinInfo(); if (B.ID == BuiltinValueKind::StaticReport) { // Report diagnostic if the first argument has been folded to '1'. OperandValueArrayRef Args = BI->getArguments(); IntegerLiteralInst *V = dyn_cast<IntegerLiteralInst>(Args[0]); if (!V || V->getValue() != 1) return; diagnose(M.getASTContext(), I->getLoc().getSourceLoc(), diag::static_report_error); } } }