/// Like ValueIsPHI but also check if the PHI has no source /// operands, i.e., it was just added. static SILPhiArgument *ValueIsNewPHI(SILValue Val, SILSSAUpdater *Updater) { SILPhiArgument *PHI = ValueIsPHI(Val, Updater); if (PHI) { auto *PhiBB = PHI->getParent(); size_t PhiIdx = PHI->getIndex(); // If all predecessor edges are 'not set' this is a new phi. for (auto *PredBB : PhiBB->getPredecessorBlocks()) { OperandValueArrayRef Edges = getEdgeValuesForTerminator(PredBB->getTerminator(), PhiBB); assert(PhiIdx < Edges.size() && "Not enough edges!"); SILValue V = Edges[PhiIdx]; // Check for the 'not set' sentinel. if (V != Updater->PHISentinel.get()) return nullptr; } return PHI; } return nullptr; }
/// 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->getSinglePredecessorBlock())) 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. auto *Cmp = dyn_cast<BuiltinInst>(CondBr->getCondition()); if (!Cmp) return None; unsigned Adjust = 0; SILBasicBlock *Exit = CondBr->getTrueBB(); switch (Cmp->getBuiltinInfo().ID) { case BuiltinValueKind::ICMP_EQ: case BuiltinValueKind::ICMP_SGE: break; case BuiltinValueKind::ICMP_SGT: Adjust = 1; break; case BuiltinValueKind::ICMP_SLE: Exit = CondBr->getFalseBB(); Adjust = 1; break; case BuiltinValueKind::ICMP_NE: case BuiltinValueKind::ICMP_SLT: Exit = CondBr->getFalseBB(); break; default: return None; } if (Loop->contains(Exit)) return None; auto *End = dyn_cast<IntegerLiteralInst>(Cmp->getArguments()[1]); if (!End) return None; SILValue RecNext = Cmp->getArguments()[0]; SILPhiArgument *RecArg; if (!match(RecNext, m_TupleExtractInst(m_ApplyInst(BuiltinValueKind::SAddOver, m_SILPhiArgument(RecArg), m_One()), 0))) return None; if (RecArg->getParent() != Header) return None; auto *Start = dyn_cast_or_null<IntegerLiteralInst>( RecArg->getIncomingPhiValue(Preheader)); if (!Start) return None; if (RecNext != RecArg->getIncomingPhiValue(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() + Adjust; }