Index: llvm/trunk/include/llvm/CodeGen/MachineScheduler.h =================================================================== --- llvm/trunk/include/llvm/CodeGen/MachineScheduler.h +++ llvm/trunk/include/llvm/CodeGen/MachineScheduler.h @@ -779,6 +779,15 @@ unsigned DemandResIdx; CandPolicy(): ReduceLatency(false), ReduceResIdx(0), DemandResIdx(0) {} + + bool operator==(const CandPolicy &RHS) const { + return ReduceLatency == RHS.ReduceLatency && + ReduceResIdx == RHS.ReduceResIdx && + DemandResIdx == RHS.DemandResIdx; + } + bool operator!=(const CandPolicy &RHS) const { + return !(*this == RHS); + } }; /// Status of an instruction's critical resource consumption. @@ -820,8 +829,17 @@ // Critical resource consumption of the best candidate. SchedResourceDelta ResDelta; - SchedCandidate(const CandPolicy &policy) - : Policy(policy), SU(nullptr), Reason(NoCand), AtTop(false) {} + SchedCandidate() { reset(CandPolicy()); } + SchedCandidate(const CandPolicy &Policy) { reset(Policy); } + + void reset(const CandPolicy &NewPolicy) { + Policy = NewPolicy; + SU = nullptr; + Reason = NoCand; + AtTop = false; + RPDelta = RegPressureDelta(); + ResDelta = SchedResourceDelta(); + } bool isValid() const { return SU; } @@ -866,6 +884,11 @@ SchedBoundary Top; SchedBoundary Bot; + /// Candidate last picked from Top boundary. + SchedCandidate TopCand; + /// Candidate last picked from Bot boundary. + SchedCandidate BotCand; + MachineSchedPolicy RegionPolicy; public: GenericScheduler(const MachineSchedContext *C): @@ -894,10 +917,12 @@ void releaseTopNode(SUnit *SU) override { Top.releaseTopNode(SU); + TopCand.SU = nullptr; } void releaseBottomNode(SUnit *SU) override { Bot.releaseBottomNode(SU); + BotCand.SU = nullptr; } void registerRoots() override; Index: llvm/trunk/lib/CodeGen/MachineScheduler.cpp =================================================================== --- llvm/trunk/lib/CodeGen/MachineScheduler.cpp +++ llvm/trunk/lib/CodeGen/MachineScheduler.cpp @@ -2557,6 +2557,8 @@ DAG->MF.getSubtarget().getInstrInfo()->CreateTargetMIHazardRecognizer( Itin, DAG); } + TopCand.SU = nullptr; + BotCand.SU = nullptr; } /// Initialize the per-region scheduling policy. @@ -2954,17 +2956,56 @@ CandPolicy TopPolicy; setPolicy(TopPolicy, /*IsPostRA=*/false, Top, &Bot); - // Prefer bottom scheduling when heuristics are silent. - CandPolicy NoPolicy; - SchedCandidate Cand(NoPolicy); + // See if BotCand is still valid (because we previously scheduled from Top). DEBUG(dbgs() << "Picking from Bot:\n"); - pickNodeFromQueue(Bot, BotPolicy, DAG->getBotRPTracker(), Cand); - assert(Cand.Reason != NoCand && "failed to find the first candidate"); + if (!BotCand.isValid() || BotCand.SU->isScheduled || + BotCand.Policy != BotPolicy) { + BotCand.reset(CandPolicy()); + pickNodeFromQueue(Bot, BotPolicy, DAG->getBotRPTracker(), BotCand); + assert(BotCand.Reason != NoCand && "failed to find the first candidate"); + } else { + DEBUG(traceCandidate(BotCand)); +#ifndef NDEBUG + if (VerifyScheduling) { + SchedCandidate TCand; + TCand.reset(CandPolicy()); + pickNodeFromQueue(Bot, BotPolicy, DAG->getBotRPTracker(), TCand); + assert(TCand.SU == BotCand.SU && + "Last pick result should correspond to re-picking right now"); + } +#endif + } // Check if the top Q has a better candidate. DEBUG(dbgs() << "Picking from Top:\n"); - pickNodeFromQueue(Top, TopPolicy, DAG->getTopRPTracker(), Cand); - assert(Cand.Reason != NoCand && "failed to find the first candidate"); + if (!TopCand.isValid() || TopCand.SU->isScheduled || + TopCand.Policy != TopPolicy) { + TopCand.reset(CandPolicy()); + pickNodeFromQueue(Top, TopPolicy, DAG->getTopRPTracker(), TopCand); + assert(TopCand.Reason != NoCand && "failed to find the first candidate"); + } else { + DEBUG(traceCandidate(TopCand)); +#ifndef NDEBUG + if (VerifyScheduling) { + SchedCandidate TCand; + TCand.reset(CandPolicy()); + pickNodeFromQueue(Top, TopPolicy, DAG->getTopRPTracker(), TCand); + assert(TCand.SU == TopCand.SU && + "Last pick result should correspond to re-picking right now"); + } +#endif + } + + // Pick best from BotCand and TopCand. + assert(BotCand.isValid()); + assert(TopCand.isValid()); + SchedCandidate Cand = BotCand; + TopCand.Reason = NoCand; + tryCandidate(Cand, TopCand, nullptr); + if (TopCand.Reason != NoCand) { + Cand.setBest(TopCand); + DEBUG(traceCandidate(Cand)); + } IsTopNode = Cand.AtTop; tracePick(Cand); @@ -2984,7 +3025,7 @@ SU = Top.pickOnlyChoice(); if (!SU) { CandPolicy NoPolicy; - SchedCandidate TopCand(NoPolicy); + TopCand.reset(NoPolicy); pickNodeFromQueue(Top, NoPolicy, DAG->getTopRPTracker(), TopCand); assert(TopCand.Reason != NoCand && "failed to find a candidate"); tracePick(TopCand); @@ -2995,7 +3036,7 @@ SU = Bot.pickOnlyChoice(); if (!SU) { CandPolicy NoPolicy; - SchedCandidate BotCand(NoPolicy); + BotCand.reset(NoPolicy); pickNodeFromQueue(Bot, NoPolicy, DAG->getBotRPTracker(), BotCand); assert(BotCand.Reason != NoCand && "failed to find a candidate"); tracePick(BotCand);