10b57cec5SDimitry Andric //===- ScheduleDAGRRList.cpp - Reg pressure reduction list scheduler ------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This implements bottom-up and top-down register pressure reduction list 100b57cec5SDimitry Andric // schedulers, using standard algorithms. The basic approach uses a priority 110b57cec5SDimitry Andric // queue of available nodes to schedule. One at a time, nodes are taken from 120b57cec5SDimitry Andric // the priority queue (thus in priority order), checked for legality to 130b57cec5SDimitry Andric // schedule, and emitted if legal. 140b57cec5SDimitry Andric // 150b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 160b57cec5SDimitry Andric 170b57cec5SDimitry Andric #include "ScheduleDAGSDNodes.h" 180b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 190b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h" 200b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 210b57cec5SDimitry Andric #include "llvm/ADT/SmallSet.h" 220b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 230b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h" 240b57cec5SDimitry Andric #include "llvm/CodeGen/ISDOpcodes.h" 250b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 260b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOperand.h" 27bdd1243dSDimitry Andric #include "llvm/CodeGen/Register.h" 280b57cec5SDimitry Andric #include "llvm/CodeGen/ScheduleDAG.h" 290b57cec5SDimitry Andric #include "llvm/CodeGen/ScheduleHazardRecognizer.h" 300b57cec5SDimitry Andric #include "llvm/CodeGen/SchedulerRegistry.h" 310b57cec5SDimitry Andric #include "llvm/CodeGen/SelectionDAGISel.h" 320b57cec5SDimitry Andric #include "llvm/CodeGen/SelectionDAGNodes.h" 330b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h" 340b57cec5SDimitry Andric #include "llvm/CodeGen/TargetLowering.h" 350b57cec5SDimitry Andric #include "llvm/CodeGen/TargetOpcodes.h" 360b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h" 370b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h" 38*0fca6ea1SDimitry Andric #include "llvm/CodeGenTypes/MachineValueType.h" 390b57cec5SDimitry Andric #include "llvm/Config/llvm-config.h" 400b57cec5SDimitry Andric #include "llvm/IR/InlineAsm.h" 410b57cec5SDimitry Andric #include "llvm/MC/MCInstrDesc.h" 420b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 430b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 440b57cec5SDimitry Andric #include "llvm/Support/CodeGen.h" 450b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h" 460b57cec5SDimitry Andric #include "llvm/Support/Compiler.h" 470b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 480b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 490b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 500b57cec5SDimitry Andric #include <algorithm> 510b57cec5SDimitry Andric #include <cassert> 520b57cec5SDimitry Andric #include <cstdint> 530b57cec5SDimitry Andric #include <cstdlib> 540b57cec5SDimitry Andric #include <iterator> 550b57cec5SDimitry Andric #include <limits> 560b57cec5SDimitry Andric #include <memory> 570b57cec5SDimitry Andric #include <utility> 580b57cec5SDimitry Andric #include <vector> 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric using namespace llvm; 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric #define DEBUG_TYPE "pre-RA-sched" 630b57cec5SDimitry Andric 640b57cec5SDimitry Andric STATISTIC(NumBacktracks, "Number of times scheduler backtracked"); 650b57cec5SDimitry Andric STATISTIC(NumUnfolds, "Number of nodes unfolded"); 660b57cec5SDimitry Andric STATISTIC(NumDups, "Number of duplicated nodes"); 670b57cec5SDimitry Andric STATISTIC(NumPRCopies, "Number of physical register copies"); 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric static RegisterScheduler 700b57cec5SDimitry Andric burrListDAGScheduler("list-burr", 710b57cec5SDimitry Andric "Bottom-up register reduction list scheduling", 720b57cec5SDimitry Andric createBURRListDAGScheduler); 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric static RegisterScheduler 750b57cec5SDimitry Andric sourceListDAGScheduler("source", 760b57cec5SDimitry Andric "Similar to list-burr but schedules in source " 770b57cec5SDimitry Andric "order when possible", 780b57cec5SDimitry Andric createSourceListDAGScheduler); 790b57cec5SDimitry Andric 800b57cec5SDimitry Andric static RegisterScheduler 810b57cec5SDimitry Andric hybridListDAGScheduler("list-hybrid", 820b57cec5SDimitry Andric "Bottom-up register pressure aware list scheduling " 830b57cec5SDimitry Andric "which tries to balance latency and register pressure", 840b57cec5SDimitry Andric createHybridListDAGScheduler); 850b57cec5SDimitry Andric 860b57cec5SDimitry Andric static RegisterScheduler 870b57cec5SDimitry Andric ILPListDAGScheduler("list-ilp", 880b57cec5SDimitry Andric "Bottom-up register pressure aware list scheduling " 890b57cec5SDimitry Andric "which tries to balance ILP and register pressure", 900b57cec5SDimitry Andric createILPListDAGScheduler); 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric static cl::opt<bool> DisableSchedCycles( 930b57cec5SDimitry Andric "disable-sched-cycles", cl::Hidden, cl::init(false), 940b57cec5SDimitry Andric cl::desc("Disable cycle-level precision during preRA scheduling")); 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric // Temporary sched=list-ilp flags until the heuristics are robust. 970b57cec5SDimitry Andric // Some options are also available under sched=list-hybrid. 980b57cec5SDimitry Andric static cl::opt<bool> DisableSchedRegPressure( 990b57cec5SDimitry Andric "disable-sched-reg-pressure", cl::Hidden, cl::init(false), 1000b57cec5SDimitry Andric cl::desc("Disable regpressure priority in sched=list-ilp")); 1010b57cec5SDimitry Andric static cl::opt<bool> DisableSchedLiveUses( 1020b57cec5SDimitry Andric "disable-sched-live-uses", cl::Hidden, cl::init(true), 1030b57cec5SDimitry Andric cl::desc("Disable live use priority in sched=list-ilp")); 1040b57cec5SDimitry Andric static cl::opt<bool> DisableSchedVRegCycle( 1050b57cec5SDimitry Andric "disable-sched-vrcycle", cl::Hidden, cl::init(false), 1060b57cec5SDimitry Andric cl::desc("Disable virtual register cycle interference checks")); 1070b57cec5SDimitry Andric static cl::opt<bool> DisableSchedPhysRegJoin( 1080b57cec5SDimitry Andric "disable-sched-physreg-join", cl::Hidden, cl::init(false), 1090b57cec5SDimitry Andric cl::desc("Disable physreg def-use affinity")); 1100b57cec5SDimitry Andric static cl::opt<bool> DisableSchedStalls( 1110b57cec5SDimitry Andric "disable-sched-stalls", cl::Hidden, cl::init(true), 1120b57cec5SDimitry Andric cl::desc("Disable no-stall priority in sched=list-ilp")); 1130b57cec5SDimitry Andric static cl::opt<bool> DisableSchedCriticalPath( 1140b57cec5SDimitry Andric "disable-sched-critical-path", cl::Hidden, cl::init(false), 1150b57cec5SDimitry Andric cl::desc("Disable critical path priority in sched=list-ilp")); 1160b57cec5SDimitry Andric static cl::opt<bool> DisableSchedHeight( 1170b57cec5SDimitry Andric "disable-sched-height", cl::Hidden, cl::init(false), 1180b57cec5SDimitry Andric cl::desc("Disable scheduled-height priority in sched=list-ilp")); 1190b57cec5SDimitry Andric static cl::opt<bool> Disable2AddrHack( 1200b57cec5SDimitry Andric "disable-2addr-hack", cl::Hidden, cl::init(true), 1210b57cec5SDimitry Andric cl::desc("Disable scheduler's two-address hack")); 1220b57cec5SDimitry Andric 1230b57cec5SDimitry Andric static cl::opt<int> MaxReorderWindow( 1240b57cec5SDimitry Andric "max-sched-reorder", cl::Hidden, cl::init(6), 1250b57cec5SDimitry Andric cl::desc("Number of instructions to allow ahead of the critical path " 1260b57cec5SDimitry Andric "in sched=list-ilp")); 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric static cl::opt<unsigned> AvgIPC( 1290b57cec5SDimitry Andric "sched-avg-ipc", cl::Hidden, cl::init(1), 1300b57cec5SDimitry Andric cl::desc("Average inst/cycle whan no target itinerary exists.")); 1310b57cec5SDimitry Andric 1320b57cec5SDimitry Andric namespace { 1330b57cec5SDimitry Andric 1340b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 1350b57cec5SDimitry Andric /// ScheduleDAGRRList - The actual register reduction list scheduler 1360b57cec5SDimitry Andric /// implementation. This supports both top-down and bottom-up scheduling. 1370b57cec5SDimitry Andric /// 1380b57cec5SDimitry Andric class ScheduleDAGRRList : public ScheduleDAGSDNodes { 1390b57cec5SDimitry Andric private: 1400b57cec5SDimitry Andric /// NeedLatency - True if the scheduler will make use of latency information. 1410b57cec5SDimitry Andric bool NeedLatency; 1420b57cec5SDimitry Andric 1430b57cec5SDimitry Andric /// AvailableQueue - The priority queue to use for the available SUnits. 1440b57cec5SDimitry Andric SchedulingPriorityQueue *AvailableQueue; 1450b57cec5SDimitry Andric 1460b57cec5SDimitry Andric /// PendingQueue - This contains all of the instructions whose operands have 1470b57cec5SDimitry Andric /// been issued, but their results are not ready yet (due to the latency of 1480b57cec5SDimitry Andric /// the operation). Once the operands becomes available, the instruction is 1490b57cec5SDimitry Andric /// added to the AvailableQueue. 1500b57cec5SDimitry Andric std::vector<SUnit *> PendingQueue; 1510b57cec5SDimitry Andric 1520b57cec5SDimitry Andric /// HazardRec - The hazard recognizer to use. 1530b57cec5SDimitry Andric ScheduleHazardRecognizer *HazardRec; 1540b57cec5SDimitry Andric 1550b57cec5SDimitry Andric /// CurCycle - The current scheduler state corresponds to this cycle. 1560b57cec5SDimitry Andric unsigned CurCycle = 0; 1570b57cec5SDimitry Andric 1580b57cec5SDimitry Andric /// MinAvailableCycle - Cycle of the soonest available instruction. 15906c3fb27SDimitry Andric unsigned MinAvailableCycle = ~0u; 1600b57cec5SDimitry Andric 1610b57cec5SDimitry Andric /// IssueCount - Count instructions issued in this cycle 1620b57cec5SDimitry Andric /// Currently valid only for bottom-up scheduling. 16306c3fb27SDimitry Andric unsigned IssueCount = 0u; 1640b57cec5SDimitry Andric 1650b57cec5SDimitry Andric /// LiveRegDefs - A set of physical registers and their definition 1660b57cec5SDimitry Andric /// that are "live". These nodes must be scheduled before any other nodes that 1670b57cec5SDimitry Andric /// modifies the registers can be scheduled. 16806c3fb27SDimitry Andric unsigned NumLiveRegs = 0u; 1690b57cec5SDimitry Andric std::unique_ptr<SUnit*[]> LiveRegDefs; 1700b57cec5SDimitry Andric std::unique_ptr<SUnit*[]> LiveRegGens; 1710b57cec5SDimitry Andric 1720b57cec5SDimitry Andric // Collect interferences between physical register use/defs. 1730b57cec5SDimitry Andric // Each interference is an SUnit and set of physical registers. 1740b57cec5SDimitry Andric SmallVector<SUnit*, 4> Interferences; 1750b57cec5SDimitry Andric 1760b57cec5SDimitry Andric using LRegsMapT = DenseMap<SUnit *, SmallVector<unsigned, 4>>; 1770b57cec5SDimitry Andric 1780b57cec5SDimitry Andric LRegsMapT LRegsMap; 1790b57cec5SDimitry Andric 1800b57cec5SDimitry Andric /// Topo - A topological ordering for SUnits which permits fast IsReachable 1810b57cec5SDimitry Andric /// and similar queries. 1820b57cec5SDimitry Andric ScheduleDAGTopologicalSort Topo; 1830b57cec5SDimitry Andric 1840b57cec5SDimitry Andric // Hack to keep track of the inverse of FindCallSeqStart without more crazy 1850b57cec5SDimitry Andric // DAG crawling. 1860b57cec5SDimitry Andric DenseMap<SUnit*, SUnit*> CallSeqEndForStart; 1870b57cec5SDimitry Andric 1880b57cec5SDimitry Andric public: 1890b57cec5SDimitry Andric ScheduleDAGRRList(MachineFunction &mf, bool needlatency, 1900b57cec5SDimitry Andric SchedulingPriorityQueue *availqueue, 1915f757f3fSDimitry Andric CodeGenOptLevel OptLevel) 1925f757f3fSDimitry Andric : ScheduleDAGSDNodes(mf), NeedLatency(needlatency), 1935f757f3fSDimitry Andric AvailableQueue(availqueue), Topo(SUnits, nullptr) { 1940b57cec5SDimitry Andric const TargetSubtargetInfo &STI = mf.getSubtarget(); 1950b57cec5SDimitry Andric if (DisableSchedCycles || !NeedLatency) 1960b57cec5SDimitry Andric HazardRec = new ScheduleHazardRecognizer(); 1970b57cec5SDimitry Andric else 1980b57cec5SDimitry Andric HazardRec = STI.getInstrInfo()->CreateTargetHazardRecognizer(&STI, this); 1990b57cec5SDimitry Andric } 2000b57cec5SDimitry Andric 2010b57cec5SDimitry Andric ~ScheduleDAGRRList() override { 2020b57cec5SDimitry Andric delete HazardRec; 2030b57cec5SDimitry Andric delete AvailableQueue; 2040b57cec5SDimitry Andric } 2050b57cec5SDimitry Andric 2060b57cec5SDimitry Andric void Schedule() override; 2070b57cec5SDimitry Andric 2080b57cec5SDimitry Andric ScheduleHazardRecognizer *getHazardRec() { return HazardRec; } 2090b57cec5SDimitry Andric 2100b57cec5SDimitry Andric /// IsReachable - Checks if SU is reachable from TargetSU. 2110b57cec5SDimitry Andric bool IsReachable(const SUnit *SU, const SUnit *TargetSU) { 2120b57cec5SDimitry Andric return Topo.IsReachable(SU, TargetSU); 2130b57cec5SDimitry Andric } 2140b57cec5SDimitry Andric 2150b57cec5SDimitry Andric /// WillCreateCycle - Returns true if adding an edge from SU to TargetSU will 2160b57cec5SDimitry Andric /// create a cycle. 2170b57cec5SDimitry Andric bool WillCreateCycle(SUnit *SU, SUnit *TargetSU) { 2180b57cec5SDimitry Andric return Topo.WillCreateCycle(SU, TargetSU); 2190b57cec5SDimitry Andric } 2200b57cec5SDimitry Andric 2210b57cec5SDimitry Andric /// AddPredQueued - Queues and update to add a predecessor edge to SUnit SU. 2220b57cec5SDimitry Andric /// This returns true if this is a new predecessor. 2230b57cec5SDimitry Andric /// Does *NOT* update the topological ordering! It just queues an update. 2240b57cec5SDimitry Andric void AddPredQueued(SUnit *SU, const SDep &D) { 2250b57cec5SDimitry Andric Topo.AddPredQueued(SU, D.getSUnit()); 2260b57cec5SDimitry Andric SU->addPred(D); 2270b57cec5SDimitry Andric } 2280b57cec5SDimitry Andric 2290b57cec5SDimitry Andric /// AddPred - adds a predecessor edge to SUnit SU. 2300b57cec5SDimitry Andric /// This returns true if this is a new predecessor. 2310b57cec5SDimitry Andric /// Updates the topological ordering if required. 2320b57cec5SDimitry Andric void AddPred(SUnit *SU, const SDep &D) { 2330b57cec5SDimitry Andric Topo.AddPred(SU, D.getSUnit()); 2340b57cec5SDimitry Andric SU->addPred(D); 2350b57cec5SDimitry Andric } 2360b57cec5SDimitry Andric 2370b57cec5SDimitry Andric /// RemovePred - removes a predecessor edge from SUnit SU. 2380b57cec5SDimitry Andric /// This returns true if an edge was removed. 2390b57cec5SDimitry Andric /// Updates the topological ordering if required. 2400b57cec5SDimitry Andric void RemovePred(SUnit *SU, const SDep &D) { 2410b57cec5SDimitry Andric Topo.RemovePred(SU, D.getSUnit()); 2420b57cec5SDimitry Andric SU->removePred(D); 2430b57cec5SDimitry Andric } 2440b57cec5SDimitry Andric 2450b57cec5SDimitry Andric private: 2460b57cec5SDimitry Andric bool isReady(SUnit *SU) { 2470b57cec5SDimitry Andric return DisableSchedCycles || !AvailableQueue->hasReadyFilter() || 2480b57cec5SDimitry Andric AvailableQueue->isReady(SU); 2490b57cec5SDimitry Andric } 2500b57cec5SDimitry Andric 2510b57cec5SDimitry Andric void ReleasePred(SUnit *SU, const SDep *PredEdge); 2520b57cec5SDimitry Andric void ReleasePredecessors(SUnit *SU); 2530b57cec5SDimitry Andric void ReleasePending(); 2540b57cec5SDimitry Andric void AdvanceToCycle(unsigned NextCycle); 2550b57cec5SDimitry Andric void AdvancePastStalls(SUnit *SU); 2560b57cec5SDimitry Andric void EmitNode(SUnit *SU); 2570b57cec5SDimitry Andric void ScheduleNodeBottomUp(SUnit*); 2580b57cec5SDimitry Andric void CapturePred(SDep *PredEdge); 2590b57cec5SDimitry Andric void UnscheduleNodeBottomUp(SUnit*); 2600b57cec5SDimitry Andric void RestoreHazardCheckerBottomUp(); 2610b57cec5SDimitry Andric void BacktrackBottomUp(SUnit*, SUnit*); 2620b57cec5SDimitry Andric SUnit *TryUnfoldSU(SUnit *); 2630b57cec5SDimitry Andric SUnit *CopyAndMoveSuccessors(SUnit*); 2640b57cec5SDimitry Andric void InsertCopiesAndMoveSuccs(SUnit*, unsigned, 2650b57cec5SDimitry Andric const TargetRegisterClass*, 2660b57cec5SDimitry Andric const TargetRegisterClass*, 2670b57cec5SDimitry Andric SmallVectorImpl<SUnit*>&); 2680b57cec5SDimitry Andric bool DelayForLiveRegsBottomUp(SUnit*, SmallVectorImpl<unsigned>&); 2690b57cec5SDimitry Andric 2700b57cec5SDimitry Andric void releaseInterferences(unsigned Reg = 0); 2710b57cec5SDimitry Andric 2720b57cec5SDimitry Andric SUnit *PickNodeToScheduleBottomUp(); 2730b57cec5SDimitry Andric void ListScheduleBottomUp(); 2740b57cec5SDimitry Andric 2750b57cec5SDimitry Andric /// CreateNewSUnit - Creates a new SUnit and returns a pointer to it. 2760b57cec5SDimitry Andric SUnit *CreateNewSUnit(SDNode *N) { 2770b57cec5SDimitry Andric unsigned NumSUnits = SUnits.size(); 2780b57cec5SDimitry Andric SUnit *NewNode = newSUnit(N); 2790b57cec5SDimitry Andric // Update the topological ordering. 2800b57cec5SDimitry Andric if (NewNode->NodeNum >= NumSUnits) 2815ffd83dbSDimitry Andric Topo.AddSUnitWithoutPredecessors(NewNode); 2820b57cec5SDimitry Andric return NewNode; 2830b57cec5SDimitry Andric } 2840b57cec5SDimitry Andric 2850b57cec5SDimitry Andric /// CreateClone - Creates a new SUnit from an existing one. 2860b57cec5SDimitry Andric SUnit *CreateClone(SUnit *N) { 2870b57cec5SDimitry Andric unsigned NumSUnits = SUnits.size(); 2880b57cec5SDimitry Andric SUnit *NewNode = Clone(N); 2890b57cec5SDimitry Andric // Update the topological ordering. 2900b57cec5SDimitry Andric if (NewNode->NodeNum >= NumSUnits) 2915ffd83dbSDimitry Andric Topo.AddSUnitWithoutPredecessors(NewNode); 2920b57cec5SDimitry Andric return NewNode; 2930b57cec5SDimitry Andric } 2940b57cec5SDimitry Andric 2950b57cec5SDimitry Andric /// forceUnitLatencies - Register-pressure-reducing scheduling doesn't 2960b57cec5SDimitry Andric /// need actual latency information but the hybrid scheduler does. 2970b57cec5SDimitry Andric bool forceUnitLatencies() const override { 2980b57cec5SDimitry Andric return !NeedLatency; 2990b57cec5SDimitry Andric } 3000b57cec5SDimitry Andric }; 3010b57cec5SDimitry Andric 3020b57cec5SDimitry Andric } // end anonymous namespace 3030b57cec5SDimitry Andric 304bdd1243dSDimitry Andric static constexpr unsigned RegSequenceCost = 1; 305bdd1243dSDimitry Andric 3060b57cec5SDimitry Andric /// GetCostForDef - Looks up the register class and cost for a given definition. 3070b57cec5SDimitry Andric /// Typically this just means looking up the representative register class, 3080b57cec5SDimitry Andric /// but for untyped values (MVT::Untyped) it means inspecting the node's 3090b57cec5SDimitry Andric /// opcode to determine what register class is being generated. 3100b57cec5SDimitry Andric static void GetCostForDef(const ScheduleDAGSDNodes::RegDefIter &RegDefPos, 3110b57cec5SDimitry Andric const TargetLowering *TLI, 3120b57cec5SDimitry Andric const TargetInstrInfo *TII, 3130b57cec5SDimitry Andric const TargetRegisterInfo *TRI, 3140b57cec5SDimitry Andric unsigned &RegClass, unsigned &Cost, 3150b57cec5SDimitry Andric const MachineFunction &MF) { 3160b57cec5SDimitry Andric MVT VT = RegDefPos.GetValue(); 3170b57cec5SDimitry Andric 3180b57cec5SDimitry Andric // Special handling for untyped values. These values can only come from 3190b57cec5SDimitry Andric // the expansion of custom DAG-to-DAG patterns. 3200b57cec5SDimitry Andric if (VT == MVT::Untyped) { 3210b57cec5SDimitry Andric const SDNode *Node = RegDefPos.GetNode(); 3220b57cec5SDimitry Andric 3230b57cec5SDimitry Andric // Special handling for CopyFromReg of untyped values. 3240b57cec5SDimitry Andric if (!Node->isMachineOpcode() && Node->getOpcode() == ISD::CopyFromReg) { 325bdd1243dSDimitry Andric Register Reg = cast<RegisterSDNode>(Node->getOperand(1))->getReg(); 3260b57cec5SDimitry Andric const TargetRegisterClass *RC = MF.getRegInfo().getRegClass(Reg); 3270b57cec5SDimitry Andric RegClass = RC->getID(); 3280b57cec5SDimitry Andric Cost = 1; 3290b57cec5SDimitry Andric return; 3300b57cec5SDimitry Andric } 3310b57cec5SDimitry Andric 3320b57cec5SDimitry Andric unsigned Opcode = Node->getMachineOpcode(); 3330b57cec5SDimitry Andric if (Opcode == TargetOpcode::REG_SEQUENCE) { 334647cbc5dSDimitry Andric unsigned DstRCIdx = Node->getConstantOperandVal(0); 3350b57cec5SDimitry Andric const TargetRegisterClass *RC = TRI->getRegClass(DstRCIdx); 3360b57cec5SDimitry Andric RegClass = RC->getID(); 337bdd1243dSDimitry Andric Cost = RegSequenceCost; 3380b57cec5SDimitry Andric return; 3390b57cec5SDimitry Andric } 3400b57cec5SDimitry Andric 3410b57cec5SDimitry Andric unsigned Idx = RegDefPos.GetIdx(); 342bdd1243dSDimitry Andric const MCInstrDesc &Desc = TII->get(Opcode); 3430b57cec5SDimitry Andric const TargetRegisterClass *RC = TII->getRegClass(Desc, Idx, TRI, MF); 344bdd1243dSDimitry Andric assert(RC && "Not a valid register class"); 3450b57cec5SDimitry Andric RegClass = RC->getID(); 3460b57cec5SDimitry Andric // FIXME: Cost arbitrarily set to 1 because there doesn't seem to be a 3470b57cec5SDimitry Andric // better way to determine it. 3480b57cec5SDimitry Andric Cost = 1; 3490b57cec5SDimitry Andric } else { 3500b57cec5SDimitry Andric RegClass = TLI->getRepRegClassFor(VT)->getID(); 3510b57cec5SDimitry Andric Cost = TLI->getRepRegClassCostFor(VT); 3520b57cec5SDimitry Andric } 3530b57cec5SDimitry Andric } 3540b57cec5SDimitry Andric 3550b57cec5SDimitry Andric /// Schedule - Schedule the DAG using list scheduling. 3560b57cec5SDimitry Andric void ScheduleDAGRRList::Schedule() { 3570b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "********** List Scheduling " << printMBBReference(*BB) 3580b57cec5SDimitry Andric << " '" << BB->getName() << "' **********\n"); 3590b57cec5SDimitry Andric 3600b57cec5SDimitry Andric CurCycle = 0; 3610b57cec5SDimitry Andric IssueCount = 0; 3620b57cec5SDimitry Andric MinAvailableCycle = 3630b57cec5SDimitry Andric DisableSchedCycles ? 0 : std::numeric_limits<unsigned>::max(); 3640b57cec5SDimitry Andric NumLiveRegs = 0; 3650b57cec5SDimitry Andric // Allocate slots for each physical register, plus one for a special register 3660b57cec5SDimitry Andric // to track the virtual resource of a calling sequence. 3670b57cec5SDimitry Andric LiveRegDefs.reset(new SUnit*[TRI->getNumRegs() + 1]()); 3680b57cec5SDimitry Andric LiveRegGens.reset(new SUnit*[TRI->getNumRegs() + 1]()); 3690b57cec5SDimitry Andric CallSeqEndForStart.clear(); 3700b57cec5SDimitry Andric assert(Interferences.empty() && LRegsMap.empty() && "stale Interferences"); 3710b57cec5SDimitry Andric 3720b57cec5SDimitry Andric // Build the scheduling graph. 3730b57cec5SDimitry Andric BuildSchedGraph(nullptr); 3740b57cec5SDimitry Andric 3750b57cec5SDimitry Andric LLVM_DEBUG(dump()); 3760b57cec5SDimitry Andric Topo.MarkDirty(); 3770b57cec5SDimitry Andric 3780b57cec5SDimitry Andric AvailableQueue->initNodes(SUnits); 3790b57cec5SDimitry Andric 3800b57cec5SDimitry Andric HazardRec->Reset(); 3810b57cec5SDimitry Andric 3820b57cec5SDimitry Andric // Execute the actual scheduling loop. 3830b57cec5SDimitry Andric ListScheduleBottomUp(); 3840b57cec5SDimitry Andric 3850b57cec5SDimitry Andric AvailableQueue->releaseState(); 3860b57cec5SDimitry Andric 3870b57cec5SDimitry Andric LLVM_DEBUG({ 3880b57cec5SDimitry Andric dbgs() << "*** Final schedule ***\n"; 3890b57cec5SDimitry Andric dumpSchedule(); 3900b57cec5SDimitry Andric dbgs() << '\n'; 3910b57cec5SDimitry Andric }); 3920b57cec5SDimitry Andric } 3930b57cec5SDimitry Andric 3940b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 3950b57cec5SDimitry Andric // Bottom-Up Scheduling 3960b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 3970b57cec5SDimitry Andric 3980b57cec5SDimitry Andric /// ReleasePred - Decrement the NumSuccsLeft count of a predecessor. Add it to 3990b57cec5SDimitry Andric /// the AvailableQueue if the count reaches zero. Also update its cycle bound. 4000b57cec5SDimitry Andric void ScheduleDAGRRList::ReleasePred(SUnit *SU, const SDep *PredEdge) { 4010b57cec5SDimitry Andric SUnit *PredSU = PredEdge->getSUnit(); 4020b57cec5SDimitry Andric 4030b57cec5SDimitry Andric #ifndef NDEBUG 4040b57cec5SDimitry Andric if (PredSU->NumSuccsLeft == 0) { 4050b57cec5SDimitry Andric dbgs() << "*** Scheduling failed! ***\n"; 4060b57cec5SDimitry Andric dumpNode(*PredSU); 4070b57cec5SDimitry Andric dbgs() << " has been released too many times!\n"; 4080b57cec5SDimitry Andric llvm_unreachable(nullptr); 4090b57cec5SDimitry Andric } 4100b57cec5SDimitry Andric #endif 4110b57cec5SDimitry Andric --PredSU->NumSuccsLeft; 4120b57cec5SDimitry Andric 4130b57cec5SDimitry Andric if (!forceUnitLatencies()) { 4140b57cec5SDimitry Andric // Updating predecessor's height. This is now the cycle when the 4150b57cec5SDimitry Andric // predecessor can be scheduled without causing a pipeline stall. 4160b57cec5SDimitry Andric PredSU->setHeightToAtLeast(SU->getHeight() + PredEdge->getLatency()); 4170b57cec5SDimitry Andric } 4180b57cec5SDimitry Andric 4190b57cec5SDimitry Andric // If all the node's successors are scheduled, this node is ready 4200b57cec5SDimitry Andric // to be scheduled. Ignore the special EntrySU node. 4210b57cec5SDimitry Andric if (PredSU->NumSuccsLeft == 0 && PredSU != &EntrySU) { 4220b57cec5SDimitry Andric PredSU->isAvailable = true; 4230b57cec5SDimitry Andric 4240b57cec5SDimitry Andric unsigned Height = PredSU->getHeight(); 4250b57cec5SDimitry Andric if (Height < MinAvailableCycle) 4260b57cec5SDimitry Andric MinAvailableCycle = Height; 4270b57cec5SDimitry Andric 4280b57cec5SDimitry Andric if (isReady(PredSU)) { 4290b57cec5SDimitry Andric AvailableQueue->push(PredSU); 4300b57cec5SDimitry Andric } 4310b57cec5SDimitry Andric // CapturePred and others may have left the node in the pending queue, avoid 4320b57cec5SDimitry Andric // adding it twice. 4330b57cec5SDimitry Andric else if (!PredSU->isPending) { 4340b57cec5SDimitry Andric PredSU->isPending = true; 4350b57cec5SDimitry Andric PendingQueue.push_back(PredSU); 4360b57cec5SDimitry Andric } 4370b57cec5SDimitry Andric } 4380b57cec5SDimitry Andric } 4390b57cec5SDimitry Andric 4400b57cec5SDimitry Andric /// IsChainDependent - Test if Outer is reachable from Inner through 4410b57cec5SDimitry Andric /// chain dependencies. 4420b57cec5SDimitry Andric static bool IsChainDependent(SDNode *Outer, SDNode *Inner, 4430b57cec5SDimitry Andric unsigned NestLevel, 4440b57cec5SDimitry Andric const TargetInstrInfo *TII) { 4450b57cec5SDimitry Andric SDNode *N = Outer; 4460b57cec5SDimitry Andric while (true) { 4470b57cec5SDimitry Andric if (N == Inner) 4480b57cec5SDimitry Andric return true; 4490b57cec5SDimitry Andric // For a TokenFactor, examine each operand. There may be multiple ways 4500b57cec5SDimitry Andric // to get to the CALLSEQ_BEGIN, but we need to find the path with the 4510b57cec5SDimitry Andric // most nesting in order to ensure that we find the corresponding match. 4520b57cec5SDimitry Andric if (N->getOpcode() == ISD::TokenFactor) { 4530b57cec5SDimitry Andric for (const SDValue &Op : N->op_values()) 4540b57cec5SDimitry Andric if (IsChainDependent(Op.getNode(), Inner, NestLevel, TII)) 4550b57cec5SDimitry Andric return true; 4560b57cec5SDimitry Andric return false; 4570b57cec5SDimitry Andric } 4580b57cec5SDimitry Andric // Check for a lowered CALLSEQ_BEGIN or CALLSEQ_END. 4590b57cec5SDimitry Andric if (N->isMachineOpcode()) { 4600b57cec5SDimitry Andric if (N->getMachineOpcode() == TII->getCallFrameDestroyOpcode()) { 4610b57cec5SDimitry Andric ++NestLevel; 4620b57cec5SDimitry Andric } else if (N->getMachineOpcode() == TII->getCallFrameSetupOpcode()) { 4630b57cec5SDimitry Andric if (NestLevel == 0) 4640b57cec5SDimitry Andric return false; 4650b57cec5SDimitry Andric --NestLevel; 4660b57cec5SDimitry Andric } 4670b57cec5SDimitry Andric } 4680b57cec5SDimitry Andric // Otherwise, find the chain and continue climbing. 4690b57cec5SDimitry Andric for (const SDValue &Op : N->op_values()) 4700b57cec5SDimitry Andric if (Op.getValueType() == MVT::Other) { 4710b57cec5SDimitry Andric N = Op.getNode(); 4720b57cec5SDimitry Andric goto found_chain_operand; 4730b57cec5SDimitry Andric } 4740b57cec5SDimitry Andric return false; 4750b57cec5SDimitry Andric found_chain_operand:; 4760b57cec5SDimitry Andric if (N->getOpcode() == ISD::EntryToken) 4770b57cec5SDimitry Andric return false; 4780b57cec5SDimitry Andric } 4790b57cec5SDimitry Andric } 4800b57cec5SDimitry Andric 4810b57cec5SDimitry Andric /// FindCallSeqStart - Starting from the (lowered) CALLSEQ_END node, locate 4820b57cec5SDimitry Andric /// the corresponding (lowered) CALLSEQ_BEGIN node. 4830b57cec5SDimitry Andric /// 4840b57cec5SDimitry Andric /// NestLevel and MaxNested are used in recursion to indcate the current level 4850b57cec5SDimitry Andric /// of nesting of CALLSEQ_BEGIN and CALLSEQ_END pairs, as well as the maximum 4860b57cec5SDimitry Andric /// level seen so far. 4870b57cec5SDimitry Andric /// 4880b57cec5SDimitry Andric /// TODO: It would be better to give CALLSEQ_END an explicit operand to point 4890b57cec5SDimitry Andric /// to the corresponding CALLSEQ_BEGIN to avoid needing to search for it. 4900b57cec5SDimitry Andric static SDNode * 4910b57cec5SDimitry Andric FindCallSeqStart(SDNode *N, unsigned &NestLevel, unsigned &MaxNest, 4920b57cec5SDimitry Andric const TargetInstrInfo *TII) { 4930b57cec5SDimitry Andric while (true) { 4940b57cec5SDimitry Andric // For a TokenFactor, examine each operand. There may be multiple ways 4950b57cec5SDimitry Andric // to get to the CALLSEQ_BEGIN, but we need to find the path with the 4960b57cec5SDimitry Andric // most nesting in order to ensure that we find the corresponding match. 4970b57cec5SDimitry Andric if (N->getOpcode() == ISD::TokenFactor) { 4980b57cec5SDimitry Andric SDNode *Best = nullptr; 4990b57cec5SDimitry Andric unsigned BestMaxNest = MaxNest; 5000b57cec5SDimitry Andric for (const SDValue &Op : N->op_values()) { 5010b57cec5SDimitry Andric unsigned MyNestLevel = NestLevel; 5020b57cec5SDimitry Andric unsigned MyMaxNest = MaxNest; 5030b57cec5SDimitry Andric if (SDNode *New = FindCallSeqStart(Op.getNode(), 5040b57cec5SDimitry Andric MyNestLevel, MyMaxNest, TII)) 5050b57cec5SDimitry Andric if (!Best || (MyMaxNest > BestMaxNest)) { 5060b57cec5SDimitry Andric Best = New; 5070b57cec5SDimitry Andric BestMaxNest = MyMaxNest; 5080b57cec5SDimitry Andric } 5090b57cec5SDimitry Andric } 5100b57cec5SDimitry Andric assert(Best); 5110b57cec5SDimitry Andric MaxNest = BestMaxNest; 5120b57cec5SDimitry Andric return Best; 5130b57cec5SDimitry Andric } 5140b57cec5SDimitry Andric // Check for a lowered CALLSEQ_BEGIN or CALLSEQ_END. 5150b57cec5SDimitry Andric if (N->isMachineOpcode()) { 5160b57cec5SDimitry Andric if (N->getMachineOpcode() == TII->getCallFrameDestroyOpcode()) { 5170b57cec5SDimitry Andric ++NestLevel; 5180b57cec5SDimitry Andric MaxNest = std::max(MaxNest, NestLevel); 5190b57cec5SDimitry Andric } else if (N->getMachineOpcode() == TII->getCallFrameSetupOpcode()) { 5200b57cec5SDimitry Andric assert(NestLevel != 0); 5210b57cec5SDimitry Andric --NestLevel; 5220b57cec5SDimitry Andric if (NestLevel == 0) 5230b57cec5SDimitry Andric return N; 5240b57cec5SDimitry Andric } 5250b57cec5SDimitry Andric } 5260b57cec5SDimitry Andric // Otherwise, find the chain and continue climbing. 5270b57cec5SDimitry Andric for (const SDValue &Op : N->op_values()) 5280b57cec5SDimitry Andric if (Op.getValueType() == MVT::Other) { 5290b57cec5SDimitry Andric N = Op.getNode(); 5300b57cec5SDimitry Andric goto found_chain_operand; 5310b57cec5SDimitry Andric } 5320b57cec5SDimitry Andric return nullptr; 5330b57cec5SDimitry Andric found_chain_operand:; 5340b57cec5SDimitry Andric if (N->getOpcode() == ISD::EntryToken) 5350b57cec5SDimitry Andric return nullptr; 5360b57cec5SDimitry Andric } 5370b57cec5SDimitry Andric } 5380b57cec5SDimitry Andric 5390b57cec5SDimitry Andric /// Call ReleasePred for each predecessor, then update register live def/gen. 5400b57cec5SDimitry Andric /// Always update LiveRegDefs for a register dependence even if the current SU 5410b57cec5SDimitry Andric /// also defines the register. This effectively create one large live range 5420b57cec5SDimitry Andric /// across a sequence of two-address node. This is important because the 5430b57cec5SDimitry Andric /// entire chain must be scheduled together. Example: 5440b57cec5SDimitry Andric /// 5450b57cec5SDimitry Andric /// flags = (3) add 5460b57cec5SDimitry Andric /// flags = (2) addc flags 5470b57cec5SDimitry Andric /// flags = (1) addc flags 5480b57cec5SDimitry Andric /// 5490b57cec5SDimitry Andric /// results in 5500b57cec5SDimitry Andric /// 5510b57cec5SDimitry Andric /// LiveRegDefs[flags] = 3 5520b57cec5SDimitry Andric /// LiveRegGens[flags] = 1 5530b57cec5SDimitry Andric /// 5540b57cec5SDimitry Andric /// If (2) addc is unscheduled, then (1) addc must also be unscheduled to avoid 5550b57cec5SDimitry Andric /// interference on flags. 5560b57cec5SDimitry Andric void ScheduleDAGRRList::ReleasePredecessors(SUnit *SU) { 5570b57cec5SDimitry Andric // Bottom up: release predecessors 5580b57cec5SDimitry Andric for (SDep &Pred : SU->Preds) { 5590b57cec5SDimitry Andric ReleasePred(SU, &Pred); 5600b57cec5SDimitry Andric if (Pred.isAssignedRegDep()) { 5610b57cec5SDimitry Andric // This is a physical register dependency and it's impossible or 5620b57cec5SDimitry Andric // expensive to copy the register. Make sure nothing that can 5630b57cec5SDimitry Andric // clobber the register is scheduled between the predecessor and 5640b57cec5SDimitry Andric // this node. 5650b57cec5SDimitry Andric SUnit *RegDef = LiveRegDefs[Pred.getReg()]; (void)RegDef; 5660b57cec5SDimitry Andric assert((!RegDef || RegDef == SU || RegDef == Pred.getSUnit()) && 5670b57cec5SDimitry Andric "interference on register dependence"); 5680b57cec5SDimitry Andric LiveRegDefs[Pred.getReg()] = Pred.getSUnit(); 5690b57cec5SDimitry Andric if (!LiveRegGens[Pred.getReg()]) { 5700b57cec5SDimitry Andric ++NumLiveRegs; 5710b57cec5SDimitry Andric LiveRegGens[Pred.getReg()] = SU; 5720b57cec5SDimitry Andric } 5730b57cec5SDimitry Andric } 5740b57cec5SDimitry Andric } 5750b57cec5SDimitry Andric 5760b57cec5SDimitry Andric // If we're scheduling a lowered CALLSEQ_END, find the corresponding 5770b57cec5SDimitry Andric // CALLSEQ_BEGIN. Inject an artificial physical register dependence between 5780b57cec5SDimitry Andric // these nodes, to prevent other calls from being interscheduled with them. 5790b57cec5SDimitry Andric unsigned CallResource = TRI->getNumRegs(); 5800b57cec5SDimitry Andric if (!LiveRegDefs[CallResource]) 5810b57cec5SDimitry Andric for (SDNode *Node = SU->getNode(); Node; Node = Node->getGluedNode()) 5820b57cec5SDimitry Andric if (Node->isMachineOpcode() && 5830b57cec5SDimitry Andric Node->getMachineOpcode() == TII->getCallFrameDestroyOpcode()) { 5840b57cec5SDimitry Andric unsigned NestLevel = 0; 5850b57cec5SDimitry Andric unsigned MaxNest = 0; 5860b57cec5SDimitry Andric SDNode *N = FindCallSeqStart(Node, NestLevel, MaxNest, TII); 5870b57cec5SDimitry Andric assert(N && "Must find call sequence start"); 5880b57cec5SDimitry Andric 5890b57cec5SDimitry Andric SUnit *Def = &SUnits[N->getNodeId()]; 5900b57cec5SDimitry Andric CallSeqEndForStart[Def] = SU; 5910b57cec5SDimitry Andric 5920b57cec5SDimitry Andric ++NumLiveRegs; 5930b57cec5SDimitry Andric LiveRegDefs[CallResource] = Def; 5940b57cec5SDimitry Andric LiveRegGens[CallResource] = SU; 5950b57cec5SDimitry Andric break; 5960b57cec5SDimitry Andric } 5970b57cec5SDimitry Andric } 5980b57cec5SDimitry Andric 5990b57cec5SDimitry Andric /// Check to see if any of the pending instructions are ready to issue. If 6000b57cec5SDimitry Andric /// so, add them to the available queue. 6010b57cec5SDimitry Andric void ScheduleDAGRRList::ReleasePending() { 6020b57cec5SDimitry Andric if (DisableSchedCycles) { 6030b57cec5SDimitry Andric assert(PendingQueue.empty() && "pending instrs not allowed in this mode"); 6040b57cec5SDimitry Andric return; 6050b57cec5SDimitry Andric } 6060b57cec5SDimitry Andric 6070b57cec5SDimitry Andric // If the available queue is empty, it is safe to reset MinAvailableCycle. 6080b57cec5SDimitry Andric if (AvailableQueue->empty()) 6090b57cec5SDimitry Andric MinAvailableCycle = std::numeric_limits<unsigned>::max(); 6100b57cec5SDimitry Andric 6110b57cec5SDimitry Andric // Check to see if any of the pending instructions are ready to issue. If 6120b57cec5SDimitry Andric // so, add them to the available queue. 6130b57cec5SDimitry Andric for (unsigned i = 0, e = PendingQueue.size(); i != e; ++i) { 6140b57cec5SDimitry Andric unsigned ReadyCycle = PendingQueue[i]->getHeight(); 6150b57cec5SDimitry Andric if (ReadyCycle < MinAvailableCycle) 6160b57cec5SDimitry Andric MinAvailableCycle = ReadyCycle; 6170b57cec5SDimitry Andric 6180b57cec5SDimitry Andric if (PendingQueue[i]->isAvailable) { 6190b57cec5SDimitry Andric if (!isReady(PendingQueue[i])) 6200b57cec5SDimitry Andric continue; 6210b57cec5SDimitry Andric AvailableQueue->push(PendingQueue[i]); 6220b57cec5SDimitry Andric } 6230b57cec5SDimitry Andric PendingQueue[i]->isPending = false; 6240b57cec5SDimitry Andric PendingQueue[i] = PendingQueue.back(); 6250b57cec5SDimitry Andric PendingQueue.pop_back(); 6260b57cec5SDimitry Andric --i; --e; 6270b57cec5SDimitry Andric } 6280b57cec5SDimitry Andric } 6290b57cec5SDimitry Andric 6300b57cec5SDimitry Andric /// Move the scheduler state forward by the specified number of Cycles. 6310b57cec5SDimitry Andric void ScheduleDAGRRList::AdvanceToCycle(unsigned NextCycle) { 6320b57cec5SDimitry Andric if (NextCycle <= CurCycle) 6330b57cec5SDimitry Andric return; 6340b57cec5SDimitry Andric 6350b57cec5SDimitry Andric IssueCount = 0; 6360b57cec5SDimitry Andric AvailableQueue->setCurCycle(NextCycle); 6370b57cec5SDimitry Andric if (!HazardRec->isEnabled()) { 6380b57cec5SDimitry Andric // Bypass lots of virtual calls in case of long latency. 6390b57cec5SDimitry Andric CurCycle = NextCycle; 6400b57cec5SDimitry Andric } 6410b57cec5SDimitry Andric else { 6420b57cec5SDimitry Andric for (; CurCycle != NextCycle; ++CurCycle) { 6430b57cec5SDimitry Andric HazardRec->RecedeCycle(); 6440b57cec5SDimitry Andric } 6450b57cec5SDimitry Andric } 6460b57cec5SDimitry Andric // FIXME: Instead of visiting the pending Q each time, set a dirty flag on the 6470b57cec5SDimitry Andric // available Q to release pending nodes at least once before popping. 6480b57cec5SDimitry Andric ReleasePending(); 6490b57cec5SDimitry Andric } 6500b57cec5SDimitry Andric 6510b57cec5SDimitry Andric /// Move the scheduler state forward until the specified node's dependents are 6520b57cec5SDimitry Andric /// ready and can be scheduled with no resource conflicts. 6530b57cec5SDimitry Andric void ScheduleDAGRRList::AdvancePastStalls(SUnit *SU) { 6540b57cec5SDimitry Andric if (DisableSchedCycles) 6550b57cec5SDimitry Andric return; 6560b57cec5SDimitry Andric 6570b57cec5SDimitry Andric // FIXME: Nodes such as CopyFromReg probably should not advance the current 6580b57cec5SDimitry Andric // cycle. Otherwise, we can wrongly mask real stalls. If the non-machine node 6590b57cec5SDimitry Andric // has predecessors the cycle will be advanced when they are scheduled. 6600b57cec5SDimitry Andric // But given the crude nature of modeling latency though such nodes, we 6610b57cec5SDimitry Andric // currently need to treat these nodes like real instructions. 6620b57cec5SDimitry Andric // if (!SU->getNode() || !SU->getNode()->isMachineOpcode()) return; 6630b57cec5SDimitry Andric 6640b57cec5SDimitry Andric unsigned ReadyCycle = SU->getHeight(); 6650b57cec5SDimitry Andric 6660b57cec5SDimitry Andric // Bump CurCycle to account for latency. We assume the latency of other 6670b57cec5SDimitry Andric // available instructions may be hidden by the stall (not a full pipe stall). 6680b57cec5SDimitry Andric // This updates the hazard recognizer's cycle before reserving resources for 6690b57cec5SDimitry Andric // this instruction. 6700b57cec5SDimitry Andric AdvanceToCycle(ReadyCycle); 6710b57cec5SDimitry Andric 6720b57cec5SDimitry Andric // Calls are scheduled in their preceding cycle, so don't conflict with 6730b57cec5SDimitry Andric // hazards from instructions after the call. EmitNode will reset the 6740b57cec5SDimitry Andric // scoreboard state before emitting the call. 6750b57cec5SDimitry Andric if (SU->isCall) 6760b57cec5SDimitry Andric return; 6770b57cec5SDimitry Andric 6780b57cec5SDimitry Andric // FIXME: For resource conflicts in very long non-pipelined stages, we 6790b57cec5SDimitry Andric // should probably skip ahead here to avoid useless scoreboard checks. 6800b57cec5SDimitry Andric int Stalls = 0; 6810b57cec5SDimitry Andric while (true) { 6820b57cec5SDimitry Andric ScheduleHazardRecognizer::HazardType HT = 6830b57cec5SDimitry Andric HazardRec->getHazardType(SU, -Stalls); 6840b57cec5SDimitry Andric 6850b57cec5SDimitry Andric if (HT == ScheduleHazardRecognizer::NoHazard) 6860b57cec5SDimitry Andric break; 6870b57cec5SDimitry Andric 6880b57cec5SDimitry Andric ++Stalls; 6890b57cec5SDimitry Andric } 6900b57cec5SDimitry Andric AdvanceToCycle(CurCycle + Stalls); 6910b57cec5SDimitry Andric } 6920b57cec5SDimitry Andric 6930b57cec5SDimitry Andric /// Record this SUnit in the HazardRecognizer. 6940b57cec5SDimitry Andric /// Does not update CurCycle. 6950b57cec5SDimitry Andric void ScheduleDAGRRList::EmitNode(SUnit *SU) { 6960b57cec5SDimitry Andric if (!HazardRec->isEnabled()) 6970b57cec5SDimitry Andric return; 6980b57cec5SDimitry Andric 6990b57cec5SDimitry Andric // Check for phys reg copy. 7000b57cec5SDimitry Andric if (!SU->getNode()) 7010b57cec5SDimitry Andric return; 7020b57cec5SDimitry Andric 7030b57cec5SDimitry Andric switch (SU->getNode()->getOpcode()) { 7040b57cec5SDimitry Andric default: 7050b57cec5SDimitry Andric assert(SU->getNode()->isMachineOpcode() && 7060b57cec5SDimitry Andric "This target-independent node should not be scheduled."); 7070b57cec5SDimitry Andric break; 7080b57cec5SDimitry Andric case ISD::MERGE_VALUES: 7090b57cec5SDimitry Andric case ISD::TokenFactor: 7100b57cec5SDimitry Andric case ISD::LIFETIME_START: 7110b57cec5SDimitry Andric case ISD::LIFETIME_END: 7120b57cec5SDimitry Andric case ISD::CopyToReg: 7130b57cec5SDimitry Andric case ISD::CopyFromReg: 7140b57cec5SDimitry Andric case ISD::EH_LABEL: 7150b57cec5SDimitry Andric // Noops don't affect the scoreboard state. Copies are likely to be 7160b57cec5SDimitry Andric // removed. 7170b57cec5SDimitry Andric return; 7180b57cec5SDimitry Andric case ISD::INLINEASM: 7190b57cec5SDimitry Andric case ISD::INLINEASM_BR: 7200b57cec5SDimitry Andric // For inline asm, clear the pipeline state. 7210b57cec5SDimitry Andric HazardRec->Reset(); 7220b57cec5SDimitry Andric return; 7230b57cec5SDimitry Andric } 7240b57cec5SDimitry Andric if (SU->isCall) { 7250b57cec5SDimitry Andric // Calls are scheduled with their preceding instructions. For bottom-up 7260b57cec5SDimitry Andric // scheduling, clear the pipeline state before emitting. 7270b57cec5SDimitry Andric HazardRec->Reset(); 7280b57cec5SDimitry Andric } 7290b57cec5SDimitry Andric 7300b57cec5SDimitry Andric HazardRec->EmitInstruction(SU); 7310b57cec5SDimitry Andric } 7320b57cec5SDimitry Andric 7330b57cec5SDimitry Andric static void resetVRegCycle(SUnit *SU); 7340b57cec5SDimitry Andric 7350b57cec5SDimitry Andric /// ScheduleNodeBottomUp - Add the node to the schedule. Decrement the pending 7360b57cec5SDimitry Andric /// count of its predecessors. If a predecessor pending count is zero, add it to 7370b57cec5SDimitry Andric /// the Available queue. 7380b57cec5SDimitry Andric void ScheduleDAGRRList::ScheduleNodeBottomUp(SUnit *SU) { 7390b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\n*** Scheduling [" << CurCycle << "]: "); 7400b57cec5SDimitry Andric LLVM_DEBUG(dumpNode(*SU)); 7410b57cec5SDimitry Andric 7420b57cec5SDimitry Andric #ifndef NDEBUG 7430b57cec5SDimitry Andric if (CurCycle < SU->getHeight()) 7440b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " Height [" << SU->getHeight() 7450b57cec5SDimitry Andric << "] pipeline stall!\n"); 7460b57cec5SDimitry Andric #endif 7470b57cec5SDimitry Andric 7480b57cec5SDimitry Andric // FIXME: Do not modify node height. It may interfere with 7490b57cec5SDimitry Andric // backtracking. Instead add a "ready cycle" to SUnit. Before scheduling the 7500b57cec5SDimitry Andric // node its ready cycle can aid heuristics, and after scheduling it can 7510b57cec5SDimitry Andric // indicate the scheduled cycle. 7520b57cec5SDimitry Andric SU->setHeightToAtLeast(CurCycle); 7530b57cec5SDimitry Andric 7540b57cec5SDimitry Andric // Reserve resources for the scheduled instruction. 7550b57cec5SDimitry Andric EmitNode(SU); 7560b57cec5SDimitry Andric 7570b57cec5SDimitry Andric Sequence.push_back(SU); 7580b57cec5SDimitry Andric 7590b57cec5SDimitry Andric AvailableQueue->scheduledNode(SU); 7600b57cec5SDimitry Andric 7610b57cec5SDimitry Andric // If HazardRec is disabled, and each inst counts as one cycle, then 7620b57cec5SDimitry Andric // advance CurCycle before ReleasePredecessors to avoid useless pushes to 7630b57cec5SDimitry Andric // PendingQueue for schedulers that implement HasReadyFilter. 7640b57cec5SDimitry Andric if (!HazardRec->isEnabled() && AvgIPC < 2) 7650b57cec5SDimitry Andric AdvanceToCycle(CurCycle + 1); 7660b57cec5SDimitry Andric 7670b57cec5SDimitry Andric // Update liveness of predecessors before successors to avoid treating a 7680b57cec5SDimitry Andric // two-address node as a live range def. 7690b57cec5SDimitry Andric ReleasePredecessors(SU); 7700b57cec5SDimitry Andric 7710b57cec5SDimitry Andric // Release all the implicit physical register defs that are live. 7720b57cec5SDimitry Andric for (SDep &Succ : SU->Succs) { 7730b57cec5SDimitry Andric // LiveRegDegs[Succ.getReg()] != SU when SU is a two-address node. 7740b57cec5SDimitry Andric if (Succ.isAssignedRegDep() && LiveRegDefs[Succ.getReg()] == SU) { 7750b57cec5SDimitry Andric assert(NumLiveRegs > 0 && "NumLiveRegs is already zero!"); 7760b57cec5SDimitry Andric --NumLiveRegs; 7770b57cec5SDimitry Andric LiveRegDefs[Succ.getReg()] = nullptr; 7780b57cec5SDimitry Andric LiveRegGens[Succ.getReg()] = nullptr; 7790b57cec5SDimitry Andric releaseInterferences(Succ.getReg()); 7800b57cec5SDimitry Andric } 7810b57cec5SDimitry Andric } 7820b57cec5SDimitry Andric // Release the special call resource dependence, if this is the beginning 7830b57cec5SDimitry Andric // of a call. 7840b57cec5SDimitry Andric unsigned CallResource = TRI->getNumRegs(); 7850b57cec5SDimitry Andric if (LiveRegDefs[CallResource] == SU) 7860b57cec5SDimitry Andric for (const SDNode *SUNode = SU->getNode(); SUNode; 7870b57cec5SDimitry Andric SUNode = SUNode->getGluedNode()) { 7880b57cec5SDimitry Andric if (SUNode->isMachineOpcode() && 7890b57cec5SDimitry Andric SUNode->getMachineOpcode() == TII->getCallFrameSetupOpcode()) { 7900b57cec5SDimitry Andric assert(NumLiveRegs > 0 && "NumLiveRegs is already zero!"); 7910b57cec5SDimitry Andric --NumLiveRegs; 7920b57cec5SDimitry Andric LiveRegDefs[CallResource] = nullptr; 7930b57cec5SDimitry Andric LiveRegGens[CallResource] = nullptr; 7940b57cec5SDimitry Andric releaseInterferences(CallResource); 7950b57cec5SDimitry Andric } 7960b57cec5SDimitry Andric } 7970b57cec5SDimitry Andric 7980b57cec5SDimitry Andric resetVRegCycle(SU); 7990b57cec5SDimitry Andric 8000b57cec5SDimitry Andric SU->isScheduled = true; 8010b57cec5SDimitry Andric 8020b57cec5SDimitry Andric // Conditions under which the scheduler should eagerly advance the cycle: 8030b57cec5SDimitry Andric // (1) No available instructions 8040b57cec5SDimitry Andric // (2) All pipelines full, so available instructions must have hazards. 8050b57cec5SDimitry Andric // 8060b57cec5SDimitry Andric // If HazardRec is disabled, the cycle was pre-advanced before calling 8070b57cec5SDimitry Andric // ReleasePredecessors. In that case, IssueCount should remain 0. 8080b57cec5SDimitry Andric // 8090b57cec5SDimitry Andric // Check AvailableQueue after ReleasePredecessors in case of zero latency. 8100b57cec5SDimitry Andric if (HazardRec->isEnabled() || AvgIPC > 1) { 8110b57cec5SDimitry Andric if (SU->getNode() && SU->getNode()->isMachineOpcode()) 8120b57cec5SDimitry Andric ++IssueCount; 8130b57cec5SDimitry Andric if ((HazardRec->isEnabled() && HazardRec->atIssueLimit()) 8140b57cec5SDimitry Andric || (!HazardRec->isEnabled() && IssueCount == AvgIPC)) 8150b57cec5SDimitry Andric AdvanceToCycle(CurCycle + 1); 8160b57cec5SDimitry Andric } 8170b57cec5SDimitry Andric } 8180b57cec5SDimitry Andric 8190b57cec5SDimitry Andric /// CapturePred - This does the opposite of ReleasePred. Since SU is being 8200b57cec5SDimitry Andric /// unscheduled, increase the succ left count of its predecessors. Remove 8210b57cec5SDimitry Andric /// them from AvailableQueue if necessary. 8220b57cec5SDimitry Andric void ScheduleDAGRRList::CapturePred(SDep *PredEdge) { 8230b57cec5SDimitry Andric SUnit *PredSU = PredEdge->getSUnit(); 8240b57cec5SDimitry Andric if (PredSU->isAvailable) { 8250b57cec5SDimitry Andric PredSU->isAvailable = false; 8260b57cec5SDimitry Andric if (!PredSU->isPending) 8270b57cec5SDimitry Andric AvailableQueue->remove(PredSU); 8280b57cec5SDimitry Andric } 8290b57cec5SDimitry Andric 8300b57cec5SDimitry Andric assert(PredSU->NumSuccsLeft < std::numeric_limits<unsigned>::max() && 8310b57cec5SDimitry Andric "NumSuccsLeft will overflow!"); 8320b57cec5SDimitry Andric ++PredSU->NumSuccsLeft; 8330b57cec5SDimitry Andric } 8340b57cec5SDimitry Andric 8350b57cec5SDimitry Andric /// UnscheduleNodeBottomUp - Remove the node from the schedule, update its and 8360b57cec5SDimitry Andric /// its predecessor states to reflect the change. 8370b57cec5SDimitry Andric void ScheduleDAGRRList::UnscheduleNodeBottomUp(SUnit *SU) { 8380b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "*** Unscheduling [" << SU->getHeight() << "]: "); 8390b57cec5SDimitry Andric LLVM_DEBUG(dumpNode(*SU)); 8400b57cec5SDimitry Andric 8410b57cec5SDimitry Andric for (SDep &Pred : SU->Preds) { 8420b57cec5SDimitry Andric CapturePred(&Pred); 8430b57cec5SDimitry Andric if (Pred.isAssignedRegDep() && SU == LiveRegGens[Pred.getReg()]){ 8440b57cec5SDimitry Andric assert(NumLiveRegs > 0 && "NumLiveRegs is already zero!"); 8450b57cec5SDimitry Andric assert(LiveRegDefs[Pred.getReg()] == Pred.getSUnit() && 8460b57cec5SDimitry Andric "Physical register dependency violated?"); 8470b57cec5SDimitry Andric --NumLiveRegs; 8480b57cec5SDimitry Andric LiveRegDefs[Pred.getReg()] = nullptr; 8490b57cec5SDimitry Andric LiveRegGens[Pred.getReg()] = nullptr; 8500b57cec5SDimitry Andric releaseInterferences(Pred.getReg()); 8510b57cec5SDimitry Andric } 8520b57cec5SDimitry Andric } 8530b57cec5SDimitry Andric 8540b57cec5SDimitry Andric // Reclaim the special call resource dependence, if this is the beginning 8550b57cec5SDimitry Andric // of a call. 8560b57cec5SDimitry Andric unsigned CallResource = TRI->getNumRegs(); 8570b57cec5SDimitry Andric for (const SDNode *SUNode = SU->getNode(); SUNode; 8580b57cec5SDimitry Andric SUNode = SUNode->getGluedNode()) { 8590b57cec5SDimitry Andric if (SUNode->isMachineOpcode() && 8600b57cec5SDimitry Andric SUNode->getMachineOpcode() == TII->getCallFrameSetupOpcode()) { 8610b57cec5SDimitry Andric SUnit *SeqEnd = CallSeqEndForStart[SU]; 8620b57cec5SDimitry Andric assert(SeqEnd && "Call sequence start/end must be known"); 8630b57cec5SDimitry Andric assert(!LiveRegDefs[CallResource]); 8640b57cec5SDimitry Andric assert(!LiveRegGens[CallResource]); 8650b57cec5SDimitry Andric ++NumLiveRegs; 8660b57cec5SDimitry Andric LiveRegDefs[CallResource] = SU; 8670b57cec5SDimitry Andric LiveRegGens[CallResource] = SeqEnd; 8680b57cec5SDimitry Andric } 8690b57cec5SDimitry Andric } 8700b57cec5SDimitry Andric 8710b57cec5SDimitry Andric // Release the special call resource dependence, if this is the end 8720b57cec5SDimitry Andric // of a call. 8730b57cec5SDimitry Andric if (LiveRegGens[CallResource] == SU) 8740b57cec5SDimitry Andric for (const SDNode *SUNode = SU->getNode(); SUNode; 8750b57cec5SDimitry Andric SUNode = SUNode->getGluedNode()) { 8760b57cec5SDimitry Andric if (SUNode->isMachineOpcode() && 8770b57cec5SDimitry Andric SUNode->getMachineOpcode() == TII->getCallFrameDestroyOpcode()) { 8780b57cec5SDimitry Andric assert(NumLiveRegs > 0 && "NumLiveRegs is already zero!"); 8790b57cec5SDimitry Andric assert(LiveRegDefs[CallResource]); 8800b57cec5SDimitry Andric assert(LiveRegGens[CallResource]); 8810b57cec5SDimitry Andric --NumLiveRegs; 8820b57cec5SDimitry Andric LiveRegDefs[CallResource] = nullptr; 8830b57cec5SDimitry Andric LiveRegGens[CallResource] = nullptr; 8840b57cec5SDimitry Andric releaseInterferences(CallResource); 8850b57cec5SDimitry Andric } 8860b57cec5SDimitry Andric } 8870b57cec5SDimitry Andric 8880b57cec5SDimitry Andric for (auto &Succ : SU->Succs) { 8890b57cec5SDimitry Andric if (Succ.isAssignedRegDep()) { 8900b57cec5SDimitry Andric auto Reg = Succ.getReg(); 8910b57cec5SDimitry Andric if (!LiveRegDefs[Reg]) 8920b57cec5SDimitry Andric ++NumLiveRegs; 8930b57cec5SDimitry Andric // This becomes the nearest def. Note that an earlier def may still be 8940b57cec5SDimitry Andric // pending if this is a two-address node. 8950b57cec5SDimitry Andric LiveRegDefs[Reg] = SU; 8960b57cec5SDimitry Andric 8970b57cec5SDimitry Andric // Update LiveRegGen only if was empty before this unscheduling. 8980b57cec5SDimitry Andric // This is to avoid incorrect updating LiveRegGen set in previous run. 8990b57cec5SDimitry Andric if (!LiveRegGens[Reg]) { 9000b57cec5SDimitry Andric // Find the successor with the lowest height. 9010b57cec5SDimitry Andric LiveRegGens[Reg] = Succ.getSUnit(); 9020b57cec5SDimitry Andric for (auto &Succ2 : SU->Succs) { 9030b57cec5SDimitry Andric if (Succ2.isAssignedRegDep() && Succ2.getReg() == Reg && 9040b57cec5SDimitry Andric Succ2.getSUnit()->getHeight() < LiveRegGens[Reg]->getHeight()) 9050b57cec5SDimitry Andric LiveRegGens[Reg] = Succ2.getSUnit(); 9060b57cec5SDimitry Andric } 9070b57cec5SDimitry Andric } 9080b57cec5SDimitry Andric } 9090b57cec5SDimitry Andric } 9100b57cec5SDimitry Andric if (SU->getHeight() < MinAvailableCycle) 9110b57cec5SDimitry Andric MinAvailableCycle = SU->getHeight(); 9120b57cec5SDimitry Andric 9130b57cec5SDimitry Andric SU->setHeightDirty(); 9140b57cec5SDimitry Andric SU->isScheduled = false; 9150b57cec5SDimitry Andric SU->isAvailable = true; 9160b57cec5SDimitry Andric if (!DisableSchedCycles && AvailableQueue->hasReadyFilter()) { 9170b57cec5SDimitry Andric // Don't make available until backtracking is complete. 9180b57cec5SDimitry Andric SU->isPending = true; 9190b57cec5SDimitry Andric PendingQueue.push_back(SU); 9200b57cec5SDimitry Andric } 9210b57cec5SDimitry Andric else { 9220b57cec5SDimitry Andric AvailableQueue->push(SU); 9230b57cec5SDimitry Andric } 9240b57cec5SDimitry Andric AvailableQueue->unscheduledNode(SU); 9250b57cec5SDimitry Andric } 9260b57cec5SDimitry Andric 9270b57cec5SDimitry Andric /// After backtracking, the hazard checker needs to be restored to a state 9280b57cec5SDimitry Andric /// corresponding the current cycle. 9290b57cec5SDimitry Andric void ScheduleDAGRRList::RestoreHazardCheckerBottomUp() { 9300b57cec5SDimitry Andric HazardRec->Reset(); 9310b57cec5SDimitry Andric 9320b57cec5SDimitry Andric unsigned LookAhead = std::min((unsigned)Sequence.size(), 9330b57cec5SDimitry Andric HazardRec->getMaxLookAhead()); 9340b57cec5SDimitry Andric if (LookAhead == 0) 9350b57cec5SDimitry Andric return; 9360b57cec5SDimitry Andric 9370b57cec5SDimitry Andric std::vector<SUnit *>::const_iterator I = (Sequence.end() - LookAhead); 9380b57cec5SDimitry Andric unsigned HazardCycle = (*I)->getHeight(); 9390b57cec5SDimitry Andric for (auto E = Sequence.end(); I != E; ++I) { 9400b57cec5SDimitry Andric SUnit *SU = *I; 9410b57cec5SDimitry Andric for (; SU->getHeight() > HazardCycle; ++HazardCycle) { 9420b57cec5SDimitry Andric HazardRec->RecedeCycle(); 9430b57cec5SDimitry Andric } 9440b57cec5SDimitry Andric EmitNode(SU); 9450b57cec5SDimitry Andric } 9460b57cec5SDimitry Andric } 9470b57cec5SDimitry Andric 9480b57cec5SDimitry Andric /// BacktrackBottomUp - Backtrack scheduling to a previous cycle specified in 9490b57cec5SDimitry Andric /// BTCycle in order to schedule a specific node. 9500b57cec5SDimitry Andric void ScheduleDAGRRList::BacktrackBottomUp(SUnit *SU, SUnit *BtSU) { 9510b57cec5SDimitry Andric SUnit *OldSU = Sequence.back(); 9520b57cec5SDimitry Andric while (true) { 9530b57cec5SDimitry Andric Sequence.pop_back(); 9540b57cec5SDimitry Andric // FIXME: use ready cycle instead of height 9550b57cec5SDimitry Andric CurCycle = OldSU->getHeight(); 9560b57cec5SDimitry Andric UnscheduleNodeBottomUp(OldSU); 9570b57cec5SDimitry Andric AvailableQueue->setCurCycle(CurCycle); 9580b57cec5SDimitry Andric if (OldSU == BtSU) 9590b57cec5SDimitry Andric break; 9600b57cec5SDimitry Andric OldSU = Sequence.back(); 9610b57cec5SDimitry Andric } 9620b57cec5SDimitry Andric 9630b57cec5SDimitry Andric assert(!SU->isSucc(OldSU) && "Something is wrong!"); 9640b57cec5SDimitry Andric 9650b57cec5SDimitry Andric RestoreHazardCheckerBottomUp(); 9660b57cec5SDimitry Andric 9670b57cec5SDimitry Andric ReleasePending(); 9680b57cec5SDimitry Andric 9690b57cec5SDimitry Andric ++NumBacktracks; 9700b57cec5SDimitry Andric } 9710b57cec5SDimitry Andric 9720b57cec5SDimitry Andric static bool isOperandOf(const SUnit *SU, SDNode *N) { 9730b57cec5SDimitry Andric for (const SDNode *SUNode = SU->getNode(); SUNode; 9740b57cec5SDimitry Andric SUNode = SUNode->getGluedNode()) { 9750b57cec5SDimitry Andric if (SUNode->isOperandOf(N)) 9760b57cec5SDimitry Andric return true; 9770b57cec5SDimitry Andric } 9780b57cec5SDimitry Andric return false; 9790b57cec5SDimitry Andric } 9800b57cec5SDimitry Andric 9810b57cec5SDimitry Andric /// TryUnfold - Attempt to unfold 9820b57cec5SDimitry Andric SUnit *ScheduleDAGRRList::TryUnfoldSU(SUnit *SU) { 9830b57cec5SDimitry Andric SDNode *N = SU->getNode(); 9840b57cec5SDimitry Andric // Use while over if to ease fall through. 9850b57cec5SDimitry Andric SmallVector<SDNode *, 2> NewNodes; 9860b57cec5SDimitry Andric if (!TII->unfoldMemoryOperand(*DAG, N, NewNodes)) 9870b57cec5SDimitry Andric return nullptr; 9880b57cec5SDimitry Andric 9890b57cec5SDimitry Andric assert(NewNodes.size() == 2 && "Expected a load folding node!"); 9900b57cec5SDimitry Andric 9910b57cec5SDimitry Andric N = NewNodes[1]; 9920b57cec5SDimitry Andric SDNode *LoadNode = NewNodes[0]; 9930b57cec5SDimitry Andric unsigned NumVals = N->getNumValues(); 9940b57cec5SDimitry Andric unsigned OldNumVals = SU->getNode()->getNumValues(); 9950b57cec5SDimitry Andric 9960b57cec5SDimitry Andric // LoadNode may already exist. This can happen when there is another 9970b57cec5SDimitry Andric // load from the same location and producing the same type of value 9980b57cec5SDimitry Andric // but it has different alignment or volatileness. 9990b57cec5SDimitry Andric bool isNewLoad = true; 10000b57cec5SDimitry Andric SUnit *LoadSU; 10010b57cec5SDimitry Andric if (LoadNode->getNodeId() != -1) { 10020b57cec5SDimitry Andric LoadSU = &SUnits[LoadNode->getNodeId()]; 10030b57cec5SDimitry Andric // If LoadSU has already been scheduled, we should clone it but 10040b57cec5SDimitry Andric // this would negate the benefit to unfolding so just return SU. 10050b57cec5SDimitry Andric if (LoadSU->isScheduled) 10060b57cec5SDimitry Andric return SU; 10070b57cec5SDimitry Andric isNewLoad = false; 10080b57cec5SDimitry Andric } else { 10090b57cec5SDimitry Andric LoadSU = CreateNewSUnit(LoadNode); 10100b57cec5SDimitry Andric LoadNode->setNodeId(LoadSU->NodeNum); 10110b57cec5SDimitry Andric 10120b57cec5SDimitry Andric InitNumRegDefsLeft(LoadSU); 10130b57cec5SDimitry Andric computeLatency(LoadSU); 10140b57cec5SDimitry Andric } 10150b57cec5SDimitry Andric 10160b57cec5SDimitry Andric bool isNewN = true; 10170b57cec5SDimitry Andric SUnit *NewSU; 10180b57cec5SDimitry Andric // This can only happen when isNewLoad is false. 10190b57cec5SDimitry Andric if (N->getNodeId() != -1) { 10200b57cec5SDimitry Andric NewSU = &SUnits[N->getNodeId()]; 10210b57cec5SDimitry Andric // If NewSU has already been scheduled, we need to clone it, but this 10220b57cec5SDimitry Andric // negates the benefit to unfolding so just return SU. 10230b57cec5SDimitry Andric if (NewSU->isScheduled) { 10240b57cec5SDimitry Andric return SU; 10250b57cec5SDimitry Andric } 10260b57cec5SDimitry Andric isNewN = false; 10270b57cec5SDimitry Andric } else { 10280b57cec5SDimitry Andric NewSU = CreateNewSUnit(N); 10290b57cec5SDimitry Andric N->setNodeId(NewSU->NodeNum); 10300b57cec5SDimitry Andric 10310b57cec5SDimitry Andric const MCInstrDesc &MCID = TII->get(N->getMachineOpcode()); 10320b57cec5SDimitry Andric for (unsigned i = 0; i != MCID.getNumOperands(); ++i) { 10330b57cec5SDimitry Andric if (MCID.getOperandConstraint(i, MCOI::TIED_TO) != -1) { 10340b57cec5SDimitry Andric NewSU->isTwoAddress = true; 10350b57cec5SDimitry Andric break; 10360b57cec5SDimitry Andric } 10370b57cec5SDimitry Andric } 10380b57cec5SDimitry Andric if (MCID.isCommutable()) 10390b57cec5SDimitry Andric NewSU->isCommutable = true; 10400b57cec5SDimitry Andric 10410b57cec5SDimitry Andric InitNumRegDefsLeft(NewSU); 10420b57cec5SDimitry Andric computeLatency(NewSU); 10430b57cec5SDimitry Andric } 10440b57cec5SDimitry Andric 10450b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Unfolding SU #" << SU->NodeNum << "\n"); 10460b57cec5SDimitry Andric 10470b57cec5SDimitry Andric // Now that we are committed to unfolding replace DAG Uses. 10480b57cec5SDimitry Andric for (unsigned i = 0; i != NumVals; ++i) 10490b57cec5SDimitry Andric DAG->ReplaceAllUsesOfValueWith(SDValue(SU->getNode(), i), SDValue(N, i)); 10500b57cec5SDimitry Andric DAG->ReplaceAllUsesOfValueWith(SDValue(SU->getNode(), OldNumVals - 1), 10510b57cec5SDimitry Andric SDValue(LoadNode, 1)); 10520b57cec5SDimitry Andric 10530b57cec5SDimitry Andric // Record all the edges to and from the old SU, by category. 10540b57cec5SDimitry Andric SmallVector<SDep, 4> ChainPreds; 10550b57cec5SDimitry Andric SmallVector<SDep, 4> ChainSuccs; 10560b57cec5SDimitry Andric SmallVector<SDep, 4> LoadPreds; 10570b57cec5SDimitry Andric SmallVector<SDep, 4> NodePreds; 10580b57cec5SDimitry Andric SmallVector<SDep, 4> NodeSuccs; 10590b57cec5SDimitry Andric for (SDep &Pred : SU->Preds) { 10600b57cec5SDimitry Andric if (Pred.isCtrl()) 10610b57cec5SDimitry Andric ChainPreds.push_back(Pred); 10620b57cec5SDimitry Andric else if (isOperandOf(Pred.getSUnit(), LoadNode)) 10630b57cec5SDimitry Andric LoadPreds.push_back(Pred); 10640b57cec5SDimitry Andric else 10650b57cec5SDimitry Andric NodePreds.push_back(Pred); 10660b57cec5SDimitry Andric } 10670b57cec5SDimitry Andric for (SDep &Succ : SU->Succs) { 10680b57cec5SDimitry Andric if (Succ.isCtrl()) 10690b57cec5SDimitry Andric ChainSuccs.push_back(Succ); 10700b57cec5SDimitry Andric else 10710b57cec5SDimitry Andric NodeSuccs.push_back(Succ); 10720b57cec5SDimitry Andric } 10730b57cec5SDimitry Andric 10740b57cec5SDimitry Andric // Now assign edges to the newly-created nodes. 10750b57cec5SDimitry Andric for (const SDep &Pred : ChainPreds) { 10760b57cec5SDimitry Andric RemovePred(SU, Pred); 10770b57cec5SDimitry Andric if (isNewLoad) 10780b57cec5SDimitry Andric AddPredQueued(LoadSU, Pred); 10790b57cec5SDimitry Andric } 10800b57cec5SDimitry Andric for (const SDep &Pred : LoadPreds) { 10810b57cec5SDimitry Andric RemovePred(SU, Pred); 10820b57cec5SDimitry Andric if (isNewLoad) 10830b57cec5SDimitry Andric AddPredQueued(LoadSU, Pred); 10840b57cec5SDimitry Andric } 10850b57cec5SDimitry Andric for (const SDep &Pred : NodePreds) { 10860b57cec5SDimitry Andric RemovePred(SU, Pred); 10870b57cec5SDimitry Andric AddPredQueued(NewSU, Pred); 10880b57cec5SDimitry Andric } 1089bdd1243dSDimitry Andric for (SDep &D : NodeSuccs) { 10900b57cec5SDimitry Andric SUnit *SuccDep = D.getSUnit(); 10910b57cec5SDimitry Andric D.setSUnit(SU); 10920b57cec5SDimitry Andric RemovePred(SuccDep, D); 10930b57cec5SDimitry Andric D.setSUnit(NewSU); 10940b57cec5SDimitry Andric AddPredQueued(SuccDep, D); 10950b57cec5SDimitry Andric // Balance register pressure. 10960b57cec5SDimitry Andric if (AvailableQueue->tracksRegPressure() && SuccDep->isScheduled && 10970b57cec5SDimitry Andric !D.isCtrl() && NewSU->NumRegDefsLeft > 0) 10980b57cec5SDimitry Andric --NewSU->NumRegDefsLeft; 10990b57cec5SDimitry Andric } 1100bdd1243dSDimitry Andric for (SDep &D : ChainSuccs) { 11010b57cec5SDimitry Andric SUnit *SuccDep = D.getSUnit(); 11020b57cec5SDimitry Andric D.setSUnit(SU); 11030b57cec5SDimitry Andric RemovePred(SuccDep, D); 11040b57cec5SDimitry Andric if (isNewLoad) { 11050b57cec5SDimitry Andric D.setSUnit(LoadSU); 11060b57cec5SDimitry Andric AddPredQueued(SuccDep, D); 11070b57cec5SDimitry Andric } 11080b57cec5SDimitry Andric } 11090b57cec5SDimitry Andric 11100b57cec5SDimitry Andric // Add a data dependency to reflect that NewSU reads the value defined 11110b57cec5SDimitry Andric // by LoadSU. 11120b57cec5SDimitry Andric SDep D(LoadSU, SDep::Data, 0); 11130b57cec5SDimitry Andric D.setLatency(LoadSU->Latency); 11140b57cec5SDimitry Andric AddPredQueued(NewSU, D); 11150b57cec5SDimitry Andric 11160b57cec5SDimitry Andric if (isNewLoad) 11170b57cec5SDimitry Andric AvailableQueue->addNode(LoadSU); 11180b57cec5SDimitry Andric if (isNewN) 11190b57cec5SDimitry Andric AvailableQueue->addNode(NewSU); 11200b57cec5SDimitry Andric 11210b57cec5SDimitry Andric ++NumUnfolds; 11220b57cec5SDimitry Andric 11230b57cec5SDimitry Andric if (NewSU->NumSuccsLeft == 0) 11240b57cec5SDimitry Andric NewSU->isAvailable = true; 11250b57cec5SDimitry Andric 11260b57cec5SDimitry Andric return NewSU; 11270b57cec5SDimitry Andric } 11280b57cec5SDimitry Andric 11290b57cec5SDimitry Andric /// CopyAndMoveSuccessors - Clone the specified node and move its scheduled 11300b57cec5SDimitry Andric /// successors to the newly created node. 11310b57cec5SDimitry Andric SUnit *ScheduleDAGRRList::CopyAndMoveSuccessors(SUnit *SU) { 11320b57cec5SDimitry Andric SDNode *N = SU->getNode(); 11330b57cec5SDimitry Andric if (!N) 11340b57cec5SDimitry Andric return nullptr; 11350b57cec5SDimitry Andric 11360b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Considering duplicating the SU\n"); 11370b57cec5SDimitry Andric LLVM_DEBUG(dumpNode(*SU)); 11380b57cec5SDimitry Andric 11390b57cec5SDimitry Andric if (N->getGluedNode() && 11400b57cec5SDimitry Andric !TII->canCopyGluedNodeDuringSchedule(N)) { 11410b57cec5SDimitry Andric LLVM_DEBUG( 11420b57cec5SDimitry Andric dbgs() 11430b57cec5SDimitry Andric << "Giving up because it has incoming glue and the target does not " 11440b57cec5SDimitry Andric "want to copy it\n"); 11450b57cec5SDimitry Andric return nullptr; 11460b57cec5SDimitry Andric } 11470b57cec5SDimitry Andric 11480b57cec5SDimitry Andric SUnit *NewSU; 11490b57cec5SDimitry Andric bool TryUnfold = false; 11500b57cec5SDimitry Andric for (unsigned i = 0, e = N->getNumValues(); i != e; ++i) { 11510b57cec5SDimitry Andric MVT VT = N->getSimpleValueType(i); 11520b57cec5SDimitry Andric if (VT == MVT::Glue) { 11530b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Giving up because it has outgoing glue\n"); 11540b57cec5SDimitry Andric return nullptr; 11550b57cec5SDimitry Andric } else if (VT == MVT::Other) 11560b57cec5SDimitry Andric TryUnfold = true; 11570b57cec5SDimitry Andric } 11580b57cec5SDimitry Andric for (const SDValue &Op : N->op_values()) { 11590b57cec5SDimitry Andric MVT VT = Op.getNode()->getSimpleValueType(Op.getResNo()); 11600b57cec5SDimitry Andric if (VT == MVT::Glue && !TII->canCopyGluedNodeDuringSchedule(N)) { 11610b57cec5SDimitry Andric LLVM_DEBUG( 11620b57cec5SDimitry Andric dbgs() << "Giving up because it one of the operands is glue and " 11630b57cec5SDimitry Andric "the target does not want to copy it\n"); 11640b57cec5SDimitry Andric return nullptr; 11650b57cec5SDimitry Andric } 11660b57cec5SDimitry Andric } 11670b57cec5SDimitry Andric 11680b57cec5SDimitry Andric // If possible unfold instruction. 11690b57cec5SDimitry Andric if (TryUnfold) { 11700b57cec5SDimitry Andric SUnit *UnfoldSU = TryUnfoldSU(SU); 11710b57cec5SDimitry Andric if (!UnfoldSU) 11720b57cec5SDimitry Andric return nullptr; 11730b57cec5SDimitry Andric SU = UnfoldSU; 11740b57cec5SDimitry Andric N = SU->getNode(); 11750b57cec5SDimitry Andric // If this can be scheduled don't bother duplicating and just return 11760b57cec5SDimitry Andric if (SU->NumSuccsLeft == 0) 11770b57cec5SDimitry Andric return SU; 11780b57cec5SDimitry Andric } 11790b57cec5SDimitry Andric 11800b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " Duplicating SU #" << SU->NodeNum << "\n"); 11810b57cec5SDimitry Andric NewSU = CreateClone(SU); 11820b57cec5SDimitry Andric 11830b57cec5SDimitry Andric // New SUnit has the exact same predecessors. 11840b57cec5SDimitry Andric for (SDep &Pred : SU->Preds) 11850b57cec5SDimitry Andric if (!Pred.isArtificial()) 11860b57cec5SDimitry Andric AddPredQueued(NewSU, Pred); 11870b57cec5SDimitry Andric 11888bcb0991SDimitry Andric // Make sure the clone comes after the original. (InstrEmitter assumes 11898bcb0991SDimitry Andric // this ordering.) 11908bcb0991SDimitry Andric AddPredQueued(NewSU, SDep(SU, SDep::Artificial)); 11918bcb0991SDimitry Andric 11920b57cec5SDimitry Andric // Only copy scheduled successors. Cut them from old node's successor 11930b57cec5SDimitry Andric // list and move them over. 11940b57cec5SDimitry Andric SmallVector<std::pair<SUnit *, SDep>, 4> DelDeps; 11950b57cec5SDimitry Andric for (SDep &Succ : SU->Succs) { 11960b57cec5SDimitry Andric if (Succ.isArtificial()) 11970b57cec5SDimitry Andric continue; 11980b57cec5SDimitry Andric SUnit *SuccSU = Succ.getSUnit(); 11990b57cec5SDimitry Andric if (SuccSU->isScheduled) { 12000b57cec5SDimitry Andric SDep D = Succ; 12010b57cec5SDimitry Andric D.setSUnit(NewSU); 12020b57cec5SDimitry Andric AddPredQueued(SuccSU, D); 12030b57cec5SDimitry Andric D.setSUnit(SU); 1204bdd1243dSDimitry Andric DelDeps.emplace_back(SuccSU, D); 12050b57cec5SDimitry Andric } 12060b57cec5SDimitry Andric } 1207bdd1243dSDimitry Andric for (const auto &[DelSU, DelD] : DelDeps) 1208bdd1243dSDimitry Andric RemovePred(DelSU, DelD); 12090b57cec5SDimitry Andric 12100b57cec5SDimitry Andric AvailableQueue->updateNode(SU); 12110b57cec5SDimitry Andric AvailableQueue->addNode(NewSU); 12120b57cec5SDimitry Andric 12130b57cec5SDimitry Andric ++NumDups; 12140b57cec5SDimitry Andric return NewSU; 12150b57cec5SDimitry Andric } 12160b57cec5SDimitry Andric 12170b57cec5SDimitry Andric /// InsertCopiesAndMoveSuccs - Insert register copies and move all 12180b57cec5SDimitry Andric /// scheduled successors of the given SUnit to the last copy. 12190b57cec5SDimitry Andric void ScheduleDAGRRList::InsertCopiesAndMoveSuccs(SUnit *SU, unsigned Reg, 12200b57cec5SDimitry Andric const TargetRegisterClass *DestRC, 12210b57cec5SDimitry Andric const TargetRegisterClass *SrcRC, 12220b57cec5SDimitry Andric SmallVectorImpl<SUnit*> &Copies) { 12230b57cec5SDimitry Andric SUnit *CopyFromSU = CreateNewSUnit(nullptr); 12240b57cec5SDimitry Andric CopyFromSU->CopySrcRC = SrcRC; 12250b57cec5SDimitry Andric CopyFromSU->CopyDstRC = DestRC; 12260b57cec5SDimitry Andric 12270b57cec5SDimitry Andric SUnit *CopyToSU = CreateNewSUnit(nullptr); 12280b57cec5SDimitry Andric CopyToSU->CopySrcRC = DestRC; 12290b57cec5SDimitry Andric CopyToSU->CopyDstRC = SrcRC; 12300b57cec5SDimitry Andric 12310b57cec5SDimitry Andric // Only copy scheduled successors. Cut them from old node's successor 12320b57cec5SDimitry Andric // list and move them over. 12330b57cec5SDimitry Andric SmallVector<std::pair<SUnit *, SDep>, 4> DelDeps; 12340b57cec5SDimitry Andric for (SDep &Succ : SU->Succs) { 12350b57cec5SDimitry Andric if (Succ.isArtificial()) 12360b57cec5SDimitry Andric continue; 12370b57cec5SDimitry Andric SUnit *SuccSU = Succ.getSUnit(); 12380b57cec5SDimitry Andric if (SuccSU->isScheduled) { 12390b57cec5SDimitry Andric SDep D = Succ; 12400b57cec5SDimitry Andric D.setSUnit(CopyToSU); 12410b57cec5SDimitry Andric AddPredQueued(SuccSU, D); 1242bdd1243dSDimitry Andric DelDeps.emplace_back(SuccSU, Succ); 12430b57cec5SDimitry Andric } 12440b57cec5SDimitry Andric else { 1245bdd1243dSDimitry Andric // Avoid scheduling the def-side copy before other successors. Otherwise, 12460b57cec5SDimitry Andric // we could introduce another physreg interference on the copy and 12470b57cec5SDimitry Andric // continue inserting copies indefinitely. 12480b57cec5SDimitry Andric AddPredQueued(SuccSU, SDep(CopyFromSU, SDep::Artificial)); 12490b57cec5SDimitry Andric } 12500b57cec5SDimitry Andric } 1251bdd1243dSDimitry Andric for (const auto &[DelSU, DelD] : DelDeps) 1252bdd1243dSDimitry Andric RemovePred(DelSU, DelD); 12530b57cec5SDimitry Andric 12540b57cec5SDimitry Andric SDep FromDep(SU, SDep::Data, Reg); 12550b57cec5SDimitry Andric FromDep.setLatency(SU->Latency); 12560b57cec5SDimitry Andric AddPredQueued(CopyFromSU, FromDep); 12570b57cec5SDimitry Andric SDep ToDep(CopyFromSU, SDep::Data, 0); 12580b57cec5SDimitry Andric ToDep.setLatency(CopyFromSU->Latency); 12590b57cec5SDimitry Andric AddPredQueued(CopyToSU, ToDep); 12600b57cec5SDimitry Andric 12610b57cec5SDimitry Andric AvailableQueue->updateNode(SU); 12620b57cec5SDimitry Andric AvailableQueue->addNode(CopyFromSU); 12630b57cec5SDimitry Andric AvailableQueue->addNode(CopyToSU); 12640b57cec5SDimitry Andric Copies.push_back(CopyFromSU); 12650b57cec5SDimitry Andric Copies.push_back(CopyToSU); 12660b57cec5SDimitry Andric 12670b57cec5SDimitry Andric ++NumPRCopies; 12680b57cec5SDimitry Andric } 12690b57cec5SDimitry Andric 12700b57cec5SDimitry Andric /// getPhysicalRegisterVT - Returns the ValueType of the physical register 12710b57cec5SDimitry Andric /// definition of the specified node. 12720b57cec5SDimitry Andric /// FIXME: Move to SelectionDAG? 12730b57cec5SDimitry Andric static MVT getPhysicalRegisterVT(SDNode *N, unsigned Reg, 12740b57cec5SDimitry Andric const TargetInstrInfo *TII) { 12750b57cec5SDimitry Andric unsigned NumRes; 12760b57cec5SDimitry Andric if (N->getOpcode() == ISD::CopyFromReg) { 12770b57cec5SDimitry Andric // CopyFromReg has: "chain, Val, glue" so operand 1 gives the type. 12780b57cec5SDimitry Andric NumRes = 1; 12790b57cec5SDimitry Andric } else { 12800b57cec5SDimitry Andric const MCInstrDesc &MCID = TII->get(N->getMachineOpcode()); 1281bdd1243dSDimitry Andric assert(!MCID.implicit_defs().empty() && 1282bdd1243dSDimitry Andric "Physical reg def must be in implicit def list!"); 12830b57cec5SDimitry Andric NumRes = MCID.getNumDefs(); 1284bdd1243dSDimitry Andric for (MCPhysReg ImpDef : MCID.implicit_defs()) { 1285bdd1243dSDimitry Andric if (Reg == ImpDef) 12860b57cec5SDimitry Andric break; 12870b57cec5SDimitry Andric ++NumRes; 12880b57cec5SDimitry Andric } 12890b57cec5SDimitry Andric } 12900b57cec5SDimitry Andric return N->getSimpleValueType(NumRes); 12910b57cec5SDimitry Andric } 12920b57cec5SDimitry Andric 12930b57cec5SDimitry Andric /// CheckForLiveRegDef - Return true and update live register vector if the 12940b57cec5SDimitry Andric /// specified register def of the specified SUnit clobbers any "live" registers. 129581ad6265SDimitry Andric static void CheckForLiveRegDef(SUnit *SU, unsigned Reg, SUnit **LiveRegDefs, 12960b57cec5SDimitry Andric SmallSet<unsigned, 4> &RegAdded, 12970b57cec5SDimitry Andric SmallVectorImpl<unsigned> &LRegs, 129881ad6265SDimitry Andric const TargetRegisterInfo *TRI, 129981ad6265SDimitry Andric const SDNode *Node = nullptr) { 13000b57cec5SDimitry Andric for (MCRegAliasIterator AliasI(Reg, TRI, true); AliasI.isValid(); ++AliasI) { 13010b57cec5SDimitry Andric 13020b57cec5SDimitry Andric // Check if Ref is live. 13030b57cec5SDimitry Andric if (!LiveRegDefs[*AliasI]) continue; 13040b57cec5SDimitry Andric 13050b57cec5SDimitry Andric // Allow multiple uses of the same def. 13060b57cec5SDimitry Andric if (LiveRegDefs[*AliasI] == SU) continue; 13070b57cec5SDimitry Andric 130881ad6265SDimitry Andric // Allow multiple uses of same def 130981ad6265SDimitry Andric if (Node && LiveRegDefs[*AliasI]->getNode() == Node) 131081ad6265SDimitry Andric continue; 131181ad6265SDimitry Andric 13120b57cec5SDimitry Andric // Add Reg to the set of interfering live regs. 13130b57cec5SDimitry Andric if (RegAdded.insert(*AliasI).second) { 13140b57cec5SDimitry Andric LRegs.push_back(*AliasI); 13150b57cec5SDimitry Andric } 13160b57cec5SDimitry Andric } 13170b57cec5SDimitry Andric } 13180b57cec5SDimitry Andric 13190b57cec5SDimitry Andric /// CheckForLiveRegDefMasked - Check for any live physregs that are clobbered 13200b57cec5SDimitry Andric /// by RegMask, and add them to LRegs. 13210b57cec5SDimitry Andric static void CheckForLiveRegDefMasked(SUnit *SU, const uint32_t *RegMask, 13220b57cec5SDimitry Andric ArrayRef<SUnit*> LiveRegDefs, 13230b57cec5SDimitry Andric SmallSet<unsigned, 4> &RegAdded, 13240b57cec5SDimitry Andric SmallVectorImpl<unsigned> &LRegs) { 13250b57cec5SDimitry Andric // Look at all live registers. Skip Reg0 and the special CallResource. 13260b57cec5SDimitry Andric for (unsigned i = 1, e = LiveRegDefs.size()-1; i != e; ++i) { 13270b57cec5SDimitry Andric if (!LiveRegDefs[i]) continue; 13280b57cec5SDimitry Andric if (LiveRegDefs[i] == SU) continue; 13290b57cec5SDimitry Andric if (!MachineOperand::clobbersPhysReg(RegMask, i)) continue; 13300b57cec5SDimitry Andric if (RegAdded.insert(i).second) 13310b57cec5SDimitry Andric LRegs.push_back(i); 13320b57cec5SDimitry Andric } 13330b57cec5SDimitry Andric } 13340b57cec5SDimitry Andric 13350b57cec5SDimitry Andric /// getNodeRegMask - Returns the register mask attached to an SDNode, if any. 13360b57cec5SDimitry Andric static const uint32_t *getNodeRegMask(const SDNode *N) { 13370b57cec5SDimitry Andric for (const SDValue &Op : N->op_values()) 13380b57cec5SDimitry Andric if (const auto *RegOp = dyn_cast<RegisterMaskSDNode>(Op.getNode())) 13390b57cec5SDimitry Andric return RegOp->getRegMask(); 13400b57cec5SDimitry Andric return nullptr; 13410b57cec5SDimitry Andric } 13420b57cec5SDimitry Andric 13430b57cec5SDimitry Andric /// DelayForLiveRegsBottomUp - Returns true if it is necessary to delay 13440b57cec5SDimitry Andric /// scheduling of the given node to satisfy live physical register dependencies. 13450b57cec5SDimitry Andric /// If the specific node is the last one that's available to schedule, do 13460b57cec5SDimitry Andric /// whatever is necessary (i.e. backtracking or cloning) to make it possible. 13470b57cec5SDimitry Andric bool ScheduleDAGRRList:: 13480b57cec5SDimitry Andric DelayForLiveRegsBottomUp(SUnit *SU, SmallVectorImpl<unsigned> &LRegs) { 13490b57cec5SDimitry Andric if (NumLiveRegs == 0) 13500b57cec5SDimitry Andric return false; 13510b57cec5SDimitry Andric 13520b57cec5SDimitry Andric SmallSet<unsigned, 4> RegAdded; 13530b57cec5SDimitry Andric // If this node would clobber any "live" register, then it's not ready. 13540b57cec5SDimitry Andric // 13550b57cec5SDimitry Andric // If SU is the currently live definition of the same register that it uses, 13560b57cec5SDimitry Andric // then we are free to schedule it. 13570b57cec5SDimitry Andric for (SDep &Pred : SU->Preds) { 13580b57cec5SDimitry Andric if (Pred.isAssignedRegDep() && LiveRegDefs[Pred.getReg()] != SU) 13590b57cec5SDimitry Andric CheckForLiveRegDef(Pred.getSUnit(), Pred.getReg(), LiveRegDefs.get(), 13600b57cec5SDimitry Andric RegAdded, LRegs, TRI); 13610b57cec5SDimitry Andric } 13620b57cec5SDimitry Andric 13630b57cec5SDimitry Andric for (SDNode *Node = SU->getNode(); Node; Node = Node->getGluedNode()) { 13640b57cec5SDimitry Andric if (Node->getOpcode() == ISD::INLINEASM || 13650b57cec5SDimitry Andric Node->getOpcode() == ISD::INLINEASM_BR) { 13660b57cec5SDimitry Andric // Inline asm can clobber physical defs. 13670b57cec5SDimitry Andric unsigned NumOps = Node->getNumOperands(); 13680b57cec5SDimitry Andric if (Node->getOperand(NumOps-1).getValueType() == MVT::Glue) 13690b57cec5SDimitry Andric --NumOps; // Ignore the glue operand. 13700b57cec5SDimitry Andric 13710b57cec5SDimitry Andric for (unsigned i = InlineAsm::Op_FirstOperand; i != NumOps;) { 1372647cbc5dSDimitry Andric unsigned Flags = Node->getConstantOperandVal(i); 13735f757f3fSDimitry Andric const InlineAsm::Flag F(Flags); 13745f757f3fSDimitry Andric unsigned NumVals = F.getNumOperandRegisters(); 13750b57cec5SDimitry Andric 13760b57cec5SDimitry Andric ++i; // Skip the ID value. 13775f757f3fSDimitry Andric if (F.isRegDefKind() || F.isRegDefEarlyClobberKind() || 13785f757f3fSDimitry Andric F.isClobberKind()) { 13790b57cec5SDimitry Andric // Check for def of register or earlyclobber register. 13800b57cec5SDimitry Andric for (; NumVals; --NumVals, ++i) { 1381bdd1243dSDimitry Andric Register Reg = cast<RegisterSDNode>(Node->getOperand(i))->getReg(); 1382bdd1243dSDimitry Andric if (Reg.isPhysical()) 13830b57cec5SDimitry Andric CheckForLiveRegDef(SU, Reg, LiveRegDefs.get(), RegAdded, LRegs, TRI); 13840b57cec5SDimitry Andric } 13850b57cec5SDimitry Andric } else 13860b57cec5SDimitry Andric i += NumVals; 13870b57cec5SDimitry Andric } 13880b57cec5SDimitry Andric continue; 13890b57cec5SDimitry Andric } 13900b57cec5SDimitry Andric 139181ad6265SDimitry Andric if (Node->getOpcode() == ISD::CopyToReg) { 139281ad6265SDimitry Andric Register Reg = cast<RegisterSDNode>(Node->getOperand(1))->getReg(); 139381ad6265SDimitry Andric if (Reg.isPhysical()) { 139481ad6265SDimitry Andric SDNode *SrcNode = Node->getOperand(2).getNode(); 139581ad6265SDimitry Andric CheckForLiveRegDef(SU, Reg, LiveRegDefs.get(), RegAdded, LRegs, TRI, 139681ad6265SDimitry Andric SrcNode); 139781ad6265SDimitry Andric } 139881ad6265SDimitry Andric } 139981ad6265SDimitry Andric 14000b57cec5SDimitry Andric if (!Node->isMachineOpcode()) 14010b57cec5SDimitry Andric continue; 14020b57cec5SDimitry Andric // If we're in the middle of scheduling a call, don't begin scheduling 14030b57cec5SDimitry Andric // another call. Also, don't allow any physical registers to be live across 14040b57cec5SDimitry Andric // the call. 14050b57cec5SDimitry Andric if (Node->getMachineOpcode() == TII->getCallFrameDestroyOpcode()) { 14060b57cec5SDimitry Andric // Check the special calling-sequence resource. 14070b57cec5SDimitry Andric unsigned CallResource = TRI->getNumRegs(); 14080b57cec5SDimitry Andric if (LiveRegDefs[CallResource]) { 14090b57cec5SDimitry Andric SDNode *Gen = LiveRegGens[CallResource]->getNode(); 14100b57cec5SDimitry Andric while (SDNode *Glued = Gen->getGluedNode()) 14110b57cec5SDimitry Andric Gen = Glued; 14120b57cec5SDimitry Andric if (!IsChainDependent(Gen, Node, 0, TII) && 14130b57cec5SDimitry Andric RegAdded.insert(CallResource).second) 14140b57cec5SDimitry Andric LRegs.push_back(CallResource); 14150b57cec5SDimitry Andric } 14160b57cec5SDimitry Andric } 14170b57cec5SDimitry Andric if (const uint32_t *RegMask = getNodeRegMask(Node)) 14180b57cec5SDimitry Andric CheckForLiveRegDefMasked(SU, RegMask, 1419bdd1243dSDimitry Andric ArrayRef(LiveRegDefs.get(), TRI->getNumRegs()), 14200b57cec5SDimitry Andric RegAdded, LRegs); 14210b57cec5SDimitry Andric 14220b57cec5SDimitry Andric const MCInstrDesc &MCID = TII->get(Node->getMachineOpcode()); 14230b57cec5SDimitry Andric if (MCID.hasOptionalDef()) { 14240b57cec5SDimitry Andric // Most ARM instructions have an OptionalDef for CPSR, to model the S-bit. 14250b57cec5SDimitry Andric // This operand can be either a def of CPSR, if the S bit is set; or a use 14260b57cec5SDimitry Andric // of %noreg. When the OptionalDef is set to a valid register, we need to 14270b57cec5SDimitry Andric // handle it in the same way as an ImplicitDef. 14280b57cec5SDimitry Andric for (unsigned i = 0; i < MCID.getNumDefs(); ++i) 1429bdd1243dSDimitry Andric if (MCID.operands()[i].isOptionalDef()) { 14300b57cec5SDimitry Andric const SDValue &OptionalDef = Node->getOperand(i - Node->getNumValues()); 1431bdd1243dSDimitry Andric Register Reg = cast<RegisterSDNode>(OptionalDef)->getReg(); 14320b57cec5SDimitry Andric CheckForLiveRegDef(SU, Reg, LiveRegDefs.get(), RegAdded, LRegs, TRI); 14330b57cec5SDimitry Andric } 14340b57cec5SDimitry Andric } 1435bdd1243dSDimitry Andric for (MCPhysReg Reg : MCID.implicit_defs()) 1436bdd1243dSDimitry Andric CheckForLiveRegDef(SU, Reg, LiveRegDefs.get(), RegAdded, LRegs, TRI); 14370b57cec5SDimitry Andric } 14380b57cec5SDimitry Andric 14390b57cec5SDimitry Andric return !LRegs.empty(); 14400b57cec5SDimitry Andric } 14410b57cec5SDimitry Andric 14420b57cec5SDimitry Andric void ScheduleDAGRRList::releaseInterferences(unsigned Reg) { 14430b57cec5SDimitry Andric // Add the nodes that aren't ready back onto the available list. 14440b57cec5SDimitry Andric for (unsigned i = Interferences.size(); i > 0; --i) { 14450b57cec5SDimitry Andric SUnit *SU = Interferences[i-1]; 14460b57cec5SDimitry Andric LRegsMapT::iterator LRegsPos = LRegsMap.find(SU); 14470b57cec5SDimitry Andric if (Reg) { 14480b57cec5SDimitry Andric SmallVectorImpl<unsigned> &LRegs = LRegsPos->second; 14490b57cec5SDimitry Andric if (!is_contained(LRegs, Reg)) 14500b57cec5SDimitry Andric continue; 14510b57cec5SDimitry Andric } 14520b57cec5SDimitry Andric SU->isPending = false; 14530b57cec5SDimitry Andric // The interfering node may no longer be available due to backtracking. 14540b57cec5SDimitry Andric // Furthermore, it may have been made available again, in which case it is 14550b57cec5SDimitry Andric // now already in the AvailableQueue. 14560b57cec5SDimitry Andric if (SU->isAvailable && !SU->NodeQueueId) { 14570b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " Repushing SU #" << SU->NodeNum << '\n'); 14580b57cec5SDimitry Andric AvailableQueue->push(SU); 14590b57cec5SDimitry Andric } 14600b57cec5SDimitry Andric if (i < Interferences.size()) 14610b57cec5SDimitry Andric Interferences[i-1] = Interferences.back(); 14620b57cec5SDimitry Andric Interferences.pop_back(); 14630b57cec5SDimitry Andric LRegsMap.erase(LRegsPos); 14640b57cec5SDimitry Andric } 14650b57cec5SDimitry Andric } 14660b57cec5SDimitry Andric 14670b57cec5SDimitry Andric /// Return a node that can be scheduled in this cycle. Requirements: 14680b57cec5SDimitry Andric /// (1) Ready: latency has been satisfied 14690b57cec5SDimitry Andric /// (2) No Hazards: resources are available 14700b57cec5SDimitry Andric /// (3) No Interferences: may unschedule to break register interferences. 14710b57cec5SDimitry Andric SUnit *ScheduleDAGRRList::PickNodeToScheduleBottomUp() { 14720b57cec5SDimitry Andric SUnit *CurSU = AvailableQueue->empty() ? nullptr : AvailableQueue->pop(); 14730b57cec5SDimitry Andric auto FindAvailableNode = [&]() { 14740b57cec5SDimitry Andric while (CurSU) { 14750b57cec5SDimitry Andric SmallVector<unsigned, 4> LRegs; 14760b57cec5SDimitry Andric if (!DelayForLiveRegsBottomUp(CurSU, LRegs)) 14770b57cec5SDimitry Andric break; 14780b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " Interfering reg "; 14790b57cec5SDimitry Andric if (LRegs[0] == TRI->getNumRegs()) dbgs() << "CallResource"; 14800b57cec5SDimitry Andric else dbgs() << printReg(LRegs[0], TRI); 14810b57cec5SDimitry Andric dbgs() << " SU #" << CurSU->NodeNum << '\n'); 1482bdd1243dSDimitry Andric auto [LRegsIter, LRegsInserted] = LRegsMap.try_emplace(CurSU, LRegs); 1483bdd1243dSDimitry Andric if (LRegsInserted) { 14840b57cec5SDimitry Andric CurSU->isPending = true; // This SU is not in AvailableQueue right now. 14850b57cec5SDimitry Andric Interferences.push_back(CurSU); 14860b57cec5SDimitry Andric } 14870b57cec5SDimitry Andric else { 14880b57cec5SDimitry Andric assert(CurSU->isPending && "Interferences are pending"); 14890b57cec5SDimitry Andric // Update the interference with current live regs. 1490bdd1243dSDimitry Andric LRegsIter->second = LRegs; 14910b57cec5SDimitry Andric } 14920b57cec5SDimitry Andric CurSU = AvailableQueue->pop(); 14930b57cec5SDimitry Andric } 14940b57cec5SDimitry Andric }; 14950b57cec5SDimitry Andric FindAvailableNode(); 14960b57cec5SDimitry Andric if (CurSU) 14970b57cec5SDimitry Andric return CurSU; 14980b57cec5SDimitry Andric 14990b57cec5SDimitry Andric // We query the topological order in the loop body, so make sure outstanding 15000b57cec5SDimitry Andric // updates are applied before entering it (we only enter the loop if there 15010b57cec5SDimitry Andric // are some interferences). If we make changes to the ordering, we exit 15020b57cec5SDimitry Andric // the loop. 15030b57cec5SDimitry Andric 15040b57cec5SDimitry Andric // All candidates are delayed due to live physical reg dependencies. 15050b57cec5SDimitry Andric // Try backtracking, code duplication, or inserting cross class copies 15060b57cec5SDimitry Andric // to resolve it. 15070b57cec5SDimitry Andric for (SUnit *TrySU : Interferences) { 15080b57cec5SDimitry Andric SmallVectorImpl<unsigned> &LRegs = LRegsMap[TrySU]; 15090b57cec5SDimitry Andric 15100b57cec5SDimitry Andric // Try unscheduling up to the point where it's safe to schedule 15110b57cec5SDimitry Andric // this node. 15120b57cec5SDimitry Andric SUnit *BtSU = nullptr; 15130b57cec5SDimitry Andric unsigned LiveCycle = std::numeric_limits<unsigned>::max(); 15140b57cec5SDimitry Andric for (unsigned Reg : LRegs) { 15150b57cec5SDimitry Andric if (LiveRegGens[Reg]->getHeight() < LiveCycle) { 15160b57cec5SDimitry Andric BtSU = LiveRegGens[Reg]; 15170b57cec5SDimitry Andric LiveCycle = BtSU->getHeight(); 15180b57cec5SDimitry Andric } 15190b57cec5SDimitry Andric } 15200b57cec5SDimitry Andric if (!WillCreateCycle(TrySU, BtSU)) { 15210b57cec5SDimitry Andric // BacktrackBottomUp mutates Interferences! 15220b57cec5SDimitry Andric BacktrackBottomUp(TrySU, BtSU); 15230b57cec5SDimitry Andric 15240b57cec5SDimitry Andric // Force the current node to be scheduled before the node that 15250b57cec5SDimitry Andric // requires the physical reg dep. 15260b57cec5SDimitry Andric if (BtSU->isAvailable) { 15270b57cec5SDimitry Andric BtSU->isAvailable = false; 15280b57cec5SDimitry Andric if (!BtSU->isPending) 15290b57cec5SDimitry Andric AvailableQueue->remove(BtSU); 15300b57cec5SDimitry Andric } 15310b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "ARTIFICIAL edge from SU(" << BtSU->NodeNum 15320b57cec5SDimitry Andric << ") to SU(" << TrySU->NodeNum << ")\n"); 15330b57cec5SDimitry Andric AddPredQueued(TrySU, SDep(BtSU, SDep::Artificial)); 15340b57cec5SDimitry Andric 15350b57cec5SDimitry Andric // If one or more successors has been unscheduled, then the current 15360b57cec5SDimitry Andric // node is no longer available. 15370b57cec5SDimitry Andric if (!TrySU->isAvailable || !TrySU->NodeQueueId) { 15380b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "TrySU not available; choosing node from queue\n"); 15390b57cec5SDimitry Andric CurSU = AvailableQueue->pop(); 15400b57cec5SDimitry Andric } else { 15410b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "TrySU available\n"); 15420b57cec5SDimitry Andric // Available and in AvailableQueue 15430b57cec5SDimitry Andric AvailableQueue->remove(TrySU); 15440b57cec5SDimitry Andric CurSU = TrySU; 15450b57cec5SDimitry Andric } 15460b57cec5SDimitry Andric FindAvailableNode(); 15470b57cec5SDimitry Andric // Interferences has been mutated. We must break. 15480b57cec5SDimitry Andric break; 15490b57cec5SDimitry Andric } 15500b57cec5SDimitry Andric } 15510b57cec5SDimitry Andric 15520b57cec5SDimitry Andric if (!CurSU) { 15530b57cec5SDimitry Andric // Can't backtrack. If it's too expensive to copy the value, then try 15540b57cec5SDimitry Andric // duplicate the nodes that produces these "too expensive to copy" 15550b57cec5SDimitry Andric // values to break the dependency. In case even that doesn't work, 15560b57cec5SDimitry Andric // insert cross class copies. 15570b57cec5SDimitry Andric // If it's not too expensive, i.e. cost != -1, issue copies. 15580b57cec5SDimitry Andric SUnit *TrySU = Interferences[0]; 15590b57cec5SDimitry Andric SmallVectorImpl<unsigned> &LRegs = LRegsMap[TrySU]; 15600b57cec5SDimitry Andric assert(LRegs.size() == 1 && "Can't handle this yet!"); 15610b57cec5SDimitry Andric unsigned Reg = LRegs[0]; 15620b57cec5SDimitry Andric SUnit *LRDef = LiveRegDefs[Reg]; 15630b57cec5SDimitry Andric MVT VT = getPhysicalRegisterVT(LRDef->getNode(), Reg, TII); 15640b57cec5SDimitry Andric const TargetRegisterClass *RC = 15650b57cec5SDimitry Andric TRI->getMinimalPhysRegClass(Reg, VT); 15660b57cec5SDimitry Andric const TargetRegisterClass *DestRC = TRI->getCrossCopyRegClass(RC); 15670b57cec5SDimitry Andric 15680b57cec5SDimitry Andric // If cross copy register class is the same as RC, then it must be possible 15690b57cec5SDimitry Andric // copy the value directly. Do not try duplicate the def. 15700b57cec5SDimitry Andric // If cross copy register class is not the same as RC, then it's possible to 15710b57cec5SDimitry Andric // copy the value but it require cross register class copies and it is 15720b57cec5SDimitry Andric // expensive. 15730b57cec5SDimitry Andric // If cross copy register class is null, then it's not possible to copy 15740b57cec5SDimitry Andric // the value at all. 15750b57cec5SDimitry Andric SUnit *NewDef = nullptr; 15760b57cec5SDimitry Andric if (DestRC != RC) { 15770b57cec5SDimitry Andric NewDef = CopyAndMoveSuccessors(LRDef); 15780b57cec5SDimitry Andric if (!DestRC && !NewDef) 15790b57cec5SDimitry Andric report_fatal_error("Can't handle live physical register dependency!"); 15800b57cec5SDimitry Andric } 15810b57cec5SDimitry Andric if (!NewDef) { 15820b57cec5SDimitry Andric // Issue copies, these can be expensive cross register class copies. 15830b57cec5SDimitry Andric SmallVector<SUnit*, 2> Copies; 15840b57cec5SDimitry Andric InsertCopiesAndMoveSuccs(LRDef, Reg, DestRC, RC, Copies); 15850b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " Adding an edge from SU #" << TrySU->NodeNum 15860b57cec5SDimitry Andric << " to SU #" << Copies.front()->NodeNum << "\n"); 15870b57cec5SDimitry Andric AddPredQueued(TrySU, SDep(Copies.front(), SDep::Artificial)); 15880b57cec5SDimitry Andric NewDef = Copies.back(); 15890b57cec5SDimitry Andric } 15900b57cec5SDimitry Andric 15910b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " Adding an edge from SU #" << NewDef->NodeNum 15920b57cec5SDimitry Andric << " to SU #" << TrySU->NodeNum << "\n"); 15930b57cec5SDimitry Andric LiveRegDefs[Reg] = NewDef; 15940b57cec5SDimitry Andric AddPredQueued(NewDef, SDep(TrySU, SDep::Artificial)); 15950b57cec5SDimitry Andric TrySU->isAvailable = false; 15960b57cec5SDimitry Andric CurSU = NewDef; 15970b57cec5SDimitry Andric } 15980b57cec5SDimitry Andric assert(CurSU && "Unable to resolve live physical register dependencies!"); 15990b57cec5SDimitry Andric return CurSU; 16000b57cec5SDimitry Andric } 16010b57cec5SDimitry Andric 16020b57cec5SDimitry Andric /// ListScheduleBottomUp - The main loop of list scheduling for bottom-up 16030b57cec5SDimitry Andric /// schedulers. 16040b57cec5SDimitry Andric void ScheduleDAGRRList::ListScheduleBottomUp() { 16050b57cec5SDimitry Andric // Release any predecessors of the special Exit node. 16060b57cec5SDimitry Andric ReleasePredecessors(&ExitSU); 16070b57cec5SDimitry Andric 16080b57cec5SDimitry Andric // Add root to Available queue. 16090b57cec5SDimitry Andric if (!SUnits.empty()) { 16100b57cec5SDimitry Andric SUnit *RootSU = &SUnits[DAG->getRoot().getNode()->getNodeId()]; 16110b57cec5SDimitry Andric assert(RootSU->Succs.empty() && "Graph root shouldn't have successors!"); 16120b57cec5SDimitry Andric RootSU->isAvailable = true; 16130b57cec5SDimitry Andric AvailableQueue->push(RootSU); 16140b57cec5SDimitry Andric } 16150b57cec5SDimitry Andric 16160b57cec5SDimitry Andric // While Available queue is not empty, grab the node with the highest 16170b57cec5SDimitry Andric // priority. If it is not ready put it back. Schedule the node. 16180b57cec5SDimitry Andric Sequence.reserve(SUnits.size()); 16190b57cec5SDimitry Andric while (!AvailableQueue->empty() || !Interferences.empty()) { 16200b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\nExamining Available:\n"; 16210b57cec5SDimitry Andric AvailableQueue->dump(this)); 16220b57cec5SDimitry Andric 16230b57cec5SDimitry Andric // Pick the best node to schedule taking all constraints into 16240b57cec5SDimitry Andric // consideration. 16250b57cec5SDimitry Andric SUnit *SU = PickNodeToScheduleBottomUp(); 16260b57cec5SDimitry Andric 16270b57cec5SDimitry Andric AdvancePastStalls(SU); 16280b57cec5SDimitry Andric 16290b57cec5SDimitry Andric ScheduleNodeBottomUp(SU); 16300b57cec5SDimitry Andric 16310b57cec5SDimitry Andric while (AvailableQueue->empty() && !PendingQueue.empty()) { 16320b57cec5SDimitry Andric // Advance the cycle to free resources. Skip ahead to the next ready SU. 16330b57cec5SDimitry Andric assert(MinAvailableCycle < std::numeric_limits<unsigned>::max() && 16340b57cec5SDimitry Andric "MinAvailableCycle uninitialized"); 16350b57cec5SDimitry Andric AdvanceToCycle(std::max(CurCycle + 1, MinAvailableCycle)); 16360b57cec5SDimitry Andric } 16370b57cec5SDimitry Andric } 16380b57cec5SDimitry Andric 16390b57cec5SDimitry Andric // Reverse the order if it is bottom up. 16400b57cec5SDimitry Andric std::reverse(Sequence.begin(), Sequence.end()); 16410b57cec5SDimitry Andric 16420b57cec5SDimitry Andric #ifndef NDEBUG 16430b57cec5SDimitry Andric VerifyScheduledSequence(/*isBottomUp=*/true); 16440b57cec5SDimitry Andric #endif 16450b57cec5SDimitry Andric } 16460b57cec5SDimitry Andric 16470b57cec5SDimitry Andric namespace { 16480b57cec5SDimitry Andric 16490b57cec5SDimitry Andric class RegReductionPQBase; 16500b57cec5SDimitry Andric 16510b57cec5SDimitry Andric struct queue_sort { 16520b57cec5SDimitry Andric bool isReady(SUnit* SU, unsigned CurCycle) const { return true; } 16530b57cec5SDimitry Andric }; 16540b57cec5SDimitry Andric 16550b57cec5SDimitry Andric #ifndef NDEBUG 16560b57cec5SDimitry Andric template<class SF> 16570b57cec5SDimitry Andric struct reverse_sort : public queue_sort { 16580b57cec5SDimitry Andric SF &SortFunc; 16590b57cec5SDimitry Andric 16600b57cec5SDimitry Andric reverse_sort(SF &sf) : SortFunc(sf) {} 16610b57cec5SDimitry Andric 16620b57cec5SDimitry Andric bool operator()(SUnit* left, SUnit* right) const { 16630b57cec5SDimitry Andric // reverse left/right rather than simply !SortFunc(left, right) 16640b57cec5SDimitry Andric // to expose different paths in the comparison logic. 16650b57cec5SDimitry Andric return SortFunc(right, left); 16660b57cec5SDimitry Andric } 16670b57cec5SDimitry Andric }; 16680b57cec5SDimitry Andric #endif // NDEBUG 16690b57cec5SDimitry Andric 16700b57cec5SDimitry Andric /// bu_ls_rr_sort - Priority function for bottom up register pressure 16710b57cec5SDimitry Andric // reduction scheduler. 16720b57cec5SDimitry Andric struct bu_ls_rr_sort : public queue_sort { 16730b57cec5SDimitry Andric enum { 16740b57cec5SDimitry Andric IsBottomUp = true, 16750b57cec5SDimitry Andric HasReadyFilter = false 16760b57cec5SDimitry Andric }; 16770b57cec5SDimitry Andric 16780b57cec5SDimitry Andric RegReductionPQBase *SPQ; 16790b57cec5SDimitry Andric 16800b57cec5SDimitry Andric bu_ls_rr_sort(RegReductionPQBase *spq) : SPQ(spq) {} 16810b57cec5SDimitry Andric 16820b57cec5SDimitry Andric bool operator()(SUnit* left, SUnit* right) const; 16830b57cec5SDimitry Andric }; 16840b57cec5SDimitry Andric 16850b57cec5SDimitry Andric // src_ls_rr_sort - Priority function for source order scheduler. 16860b57cec5SDimitry Andric struct src_ls_rr_sort : public queue_sort { 16870b57cec5SDimitry Andric enum { 16880b57cec5SDimitry Andric IsBottomUp = true, 16890b57cec5SDimitry Andric HasReadyFilter = false 16900b57cec5SDimitry Andric }; 16910b57cec5SDimitry Andric 16920b57cec5SDimitry Andric RegReductionPQBase *SPQ; 16930b57cec5SDimitry Andric 16940b57cec5SDimitry Andric src_ls_rr_sort(RegReductionPQBase *spq) : SPQ(spq) {} 16950b57cec5SDimitry Andric 16960b57cec5SDimitry Andric bool operator()(SUnit* left, SUnit* right) const; 16970b57cec5SDimitry Andric }; 16980b57cec5SDimitry Andric 16990b57cec5SDimitry Andric // hybrid_ls_rr_sort - Priority function for hybrid scheduler. 17000b57cec5SDimitry Andric struct hybrid_ls_rr_sort : public queue_sort { 17010b57cec5SDimitry Andric enum { 17020b57cec5SDimitry Andric IsBottomUp = true, 17030b57cec5SDimitry Andric HasReadyFilter = false 17040b57cec5SDimitry Andric }; 17050b57cec5SDimitry Andric 17060b57cec5SDimitry Andric RegReductionPQBase *SPQ; 17070b57cec5SDimitry Andric 17080b57cec5SDimitry Andric hybrid_ls_rr_sort(RegReductionPQBase *spq) : SPQ(spq) {} 17090b57cec5SDimitry Andric 17100b57cec5SDimitry Andric bool isReady(SUnit *SU, unsigned CurCycle) const; 17110b57cec5SDimitry Andric 17120b57cec5SDimitry Andric bool operator()(SUnit* left, SUnit* right) const; 17130b57cec5SDimitry Andric }; 17140b57cec5SDimitry Andric 17150b57cec5SDimitry Andric // ilp_ls_rr_sort - Priority function for ILP (instruction level parallelism) 17160b57cec5SDimitry Andric // scheduler. 17170b57cec5SDimitry Andric struct ilp_ls_rr_sort : public queue_sort { 17180b57cec5SDimitry Andric enum { 17190b57cec5SDimitry Andric IsBottomUp = true, 17200b57cec5SDimitry Andric HasReadyFilter = false 17210b57cec5SDimitry Andric }; 17220b57cec5SDimitry Andric 17230b57cec5SDimitry Andric RegReductionPQBase *SPQ; 17240b57cec5SDimitry Andric 17250b57cec5SDimitry Andric ilp_ls_rr_sort(RegReductionPQBase *spq) : SPQ(spq) {} 17260b57cec5SDimitry Andric 17270b57cec5SDimitry Andric bool isReady(SUnit *SU, unsigned CurCycle) const; 17280b57cec5SDimitry Andric 17290b57cec5SDimitry Andric bool operator()(SUnit* left, SUnit* right) const; 17300b57cec5SDimitry Andric }; 17310b57cec5SDimitry Andric 17320b57cec5SDimitry Andric class RegReductionPQBase : public SchedulingPriorityQueue { 17330b57cec5SDimitry Andric protected: 17340b57cec5SDimitry Andric std::vector<SUnit *> Queue; 17350b57cec5SDimitry Andric unsigned CurQueueId = 0; 17360b57cec5SDimitry Andric bool TracksRegPressure; 17370b57cec5SDimitry Andric bool SrcOrder; 17380b57cec5SDimitry Andric 17390b57cec5SDimitry Andric // SUnits - The SUnits for the current graph. 174006c3fb27SDimitry Andric std::vector<SUnit> *SUnits = nullptr; 17410b57cec5SDimitry Andric 17420b57cec5SDimitry Andric MachineFunction &MF; 174306c3fb27SDimitry Andric const TargetInstrInfo *TII = nullptr; 174406c3fb27SDimitry Andric const TargetRegisterInfo *TRI = nullptr; 174506c3fb27SDimitry Andric const TargetLowering *TLI = nullptr; 17460b57cec5SDimitry Andric ScheduleDAGRRList *scheduleDAG = nullptr; 17470b57cec5SDimitry Andric 17480b57cec5SDimitry Andric // SethiUllmanNumbers - The SethiUllman number for each node. 17490b57cec5SDimitry Andric std::vector<unsigned> SethiUllmanNumbers; 17500b57cec5SDimitry Andric 17510b57cec5SDimitry Andric /// RegPressure - Tracking current reg pressure per register class. 17520b57cec5SDimitry Andric std::vector<unsigned> RegPressure; 17530b57cec5SDimitry Andric 17540b57cec5SDimitry Andric /// RegLimit - Tracking the number of allocatable registers per register 17550b57cec5SDimitry Andric /// class. 17560b57cec5SDimitry Andric std::vector<unsigned> RegLimit; 17570b57cec5SDimitry Andric 17580b57cec5SDimitry Andric public: 17590b57cec5SDimitry Andric RegReductionPQBase(MachineFunction &mf, 17600b57cec5SDimitry Andric bool hasReadyFilter, 17610b57cec5SDimitry Andric bool tracksrp, 17620b57cec5SDimitry Andric bool srcorder, 17630b57cec5SDimitry Andric const TargetInstrInfo *tii, 17640b57cec5SDimitry Andric const TargetRegisterInfo *tri, 17650b57cec5SDimitry Andric const TargetLowering *tli) 17660b57cec5SDimitry Andric : SchedulingPriorityQueue(hasReadyFilter), TracksRegPressure(tracksrp), 17670b57cec5SDimitry Andric SrcOrder(srcorder), MF(mf), TII(tii), TRI(tri), TLI(tli) { 17680b57cec5SDimitry Andric if (TracksRegPressure) { 17690b57cec5SDimitry Andric unsigned NumRC = TRI->getNumRegClasses(); 17700b57cec5SDimitry Andric RegLimit.resize(NumRC); 17710b57cec5SDimitry Andric RegPressure.resize(NumRC); 17720b57cec5SDimitry Andric std::fill(RegLimit.begin(), RegLimit.end(), 0); 17730b57cec5SDimitry Andric std::fill(RegPressure.begin(), RegPressure.end(), 0); 17740b57cec5SDimitry Andric for (const TargetRegisterClass *RC : TRI->regclasses()) 17750b57cec5SDimitry Andric RegLimit[RC->getID()] = tri->getRegPressureLimit(RC, MF); 17760b57cec5SDimitry Andric } 17770b57cec5SDimitry Andric } 17780b57cec5SDimitry Andric 17790b57cec5SDimitry Andric void setScheduleDAG(ScheduleDAGRRList *scheduleDag) { 17800b57cec5SDimitry Andric scheduleDAG = scheduleDag; 17810b57cec5SDimitry Andric } 17820b57cec5SDimitry Andric 17830b57cec5SDimitry Andric ScheduleHazardRecognizer* getHazardRec() { 17840b57cec5SDimitry Andric return scheduleDAG->getHazardRec(); 17850b57cec5SDimitry Andric } 17860b57cec5SDimitry Andric 17870b57cec5SDimitry Andric void initNodes(std::vector<SUnit> &sunits) override; 17880b57cec5SDimitry Andric 17890b57cec5SDimitry Andric void addNode(const SUnit *SU) override; 17900b57cec5SDimitry Andric 17910b57cec5SDimitry Andric void updateNode(const SUnit *SU) override; 17920b57cec5SDimitry Andric 17930b57cec5SDimitry Andric void releaseState() override { 17940b57cec5SDimitry Andric SUnits = nullptr; 17950b57cec5SDimitry Andric SethiUllmanNumbers.clear(); 17960b57cec5SDimitry Andric std::fill(RegPressure.begin(), RegPressure.end(), 0); 17970b57cec5SDimitry Andric } 17980b57cec5SDimitry Andric 17990b57cec5SDimitry Andric unsigned getNodePriority(const SUnit *SU) const; 18000b57cec5SDimitry Andric 18010b57cec5SDimitry Andric unsigned getNodeOrdering(const SUnit *SU) const { 18020b57cec5SDimitry Andric if (!SU->getNode()) return 0; 18030b57cec5SDimitry Andric 18040b57cec5SDimitry Andric return SU->getNode()->getIROrder(); 18050b57cec5SDimitry Andric } 18060b57cec5SDimitry Andric 18070b57cec5SDimitry Andric bool empty() const override { return Queue.empty(); } 18080b57cec5SDimitry Andric 18090b57cec5SDimitry Andric void push(SUnit *U) override { 18100b57cec5SDimitry Andric assert(!U->NodeQueueId && "Node in the queue already"); 18110b57cec5SDimitry Andric U->NodeQueueId = ++CurQueueId; 18120b57cec5SDimitry Andric Queue.push_back(U); 18130b57cec5SDimitry Andric } 18140b57cec5SDimitry Andric 18150b57cec5SDimitry Andric void remove(SUnit *SU) override { 18160b57cec5SDimitry Andric assert(!Queue.empty() && "Queue is empty!"); 18170b57cec5SDimitry Andric assert(SU->NodeQueueId != 0 && "Not in queue!"); 18180b57cec5SDimitry Andric std::vector<SUnit *>::iterator I = llvm::find(Queue, SU); 18190b57cec5SDimitry Andric if (I != std::prev(Queue.end())) 18200b57cec5SDimitry Andric std::swap(*I, Queue.back()); 18210b57cec5SDimitry Andric Queue.pop_back(); 18220b57cec5SDimitry Andric SU->NodeQueueId = 0; 18230b57cec5SDimitry Andric } 18240b57cec5SDimitry Andric 18250b57cec5SDimitry Andric bool tracksRegPressure() const override { return TracksRegPressure; } 18260b57cec5SDimitry Andric 18270b57cec5SDimitry Andric void dumpRegPressure() const; 18280b57cec5SDimitry Andric 18290b57cec5SDimitry Andric bool HighRegPressure(const SUnit *SU) const; 18300b57cec5SDimitry Andric 18310b57cec5SDimitry Andric bool MayReduceRegPressure(SUnit *SU) const; 18320b57cec5SDimitry Andric 18330b57cec5SDimitry Andric int RegPressureDiff(SUnit *SU, unsigned &LiveUses) const; 18340b57cec5SDimitry Andric 18350b57cec5SDimitry Andric void scheduledNode(SUnit *SU) override; 18360b57cec5SDimitry Andric 18370b57cec5SDimitry Andric void unscheduledNode(SUnit *SU) override; 18380b57cec5SDimitry Andric 18390b57cec5SDimitry Andric protected: 18400b57cec5SDimitry Andric bool canClobber(const SUnit *SU, const SUnit *Op); 18410b57cec5SDimitry Andric void AddPseudoTwoAddrDeps(); 18420b57cec5SDimitry Andric void PrescheduleNodesWithMultipleUses(); 18430b57cec5SDimitry Andric void CalculateSethiUllmanNumbers(); 18440b57cec5SDimitry Andric }; 18450b57cec5SDimitry Andric 18460b57cec5SDimitry Andric template<class SF> 18470b57cec5SDimitry Andric static SUnit *popFromQueueImpl(std::vector<SUnit *> &Q, SF &Picker) { 1848e8d8bef9SDimitry Andric unsigned BestIdx = 0; 1849e8d8bef9SDimitry Andric // Only compute the cost for the first 1000 items in the queue, to avoid 1850e8d8bef9SDimitry Andric // excessive compile-times for very large queues. 1851e8d8bef9SDimitry Andric for (unsigned I = 1, E = std::min(Q.size(), (decltype(Q.size()))1000); I != E; 1852e8d8bef9SDimitry Andric I++) 1853e8d8bef9SDimitry Andric if (Picker(Q[BestIdx], Q[I])) 1854e8d8bef9SDimitry Andric BestIdx = I; 1855e8d8bef9SDimitry Andric SUnit *V = Q[BestIdx]; 1856e8d8bef9SDimitry Andric if (BestIdx + 1 != Q.size()) 1857e8d8bef9SDimitry Andric std::swap(Q[BestIdx], Q.back()); 18580b57cec5SDimitry Andric Q.pop_back(); 18590b57cec5SDimitry Andric return V; 18600b57cec5SDimitry Andric } 18610b57cec5SDimitry Andric 18620b57cec5SDimitry Andric template<class SF> 18630b57cec5SDimitry Andric SUnit *popFromQueue(std::vector<SUnit *> &Q, SF &Picker, ScheduleDAG *DAG) { 18640b57cec5SDimitry Andric #ifndef NDEBUG 18650b57cec5SDimitry Andric if (DAG->StressSched) { 18660b57cec5SDimitry Andric reverse_sort<SF> RPicker(Picker); 18670b57cec5SDimitry Andric return popFromQueueImpl(Q, RPicker); 18680b57cec5SDimitry Andric } 18690b57cec5SDimitry Andric #endif 18700b57cec5SDimitry Andric (void)DAG; 18710b57cec5SDimitry Andric return popFromQueueImpl(Q, Picker); 18720b57cec5SDimitry Andric } 18730b57cec5SDimitry Andric 18740b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 18750b57cec5SDimitry Andric // RegReductionPriorityQueue Definition 18760b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 18770b57cec5SDimitry Andric // 18780b57cec5SDimitry Andric // This is a SchedulingPriorityQueue that schedules using Sethi Ullman numbers 18790b57cec5SDimitry Andric // to reduce register pressure. 18800b57cec5SDimitry Andric // 18810b57cec5SDimitry Andric template<class SF> 18820b57cec5SDimitry Andric class RegReductionPriorityQueue : public RegReductionPQBase { 18830b57cec5SDimitry Andric SF Picker; 18840b57cec5SDimitry Andric 18850b57cec5SDimitry Andric public: 18860b57cec5SDimitry Andric RegReductionPriorityQueue(MachineFunction &mf, 18870b57cec5SDimitry Andric bool tracksrp, 18880b57cec5SDimitry Andric bool srcorder, 18890b57cec5SDimitry Andric const TargetInstrInfo *tii, 18900b57cec5SDimitry Andric const TargetRegisterInfo *tri, 18910b57cec5SDimitry Andric const TargetLowering *tli) 18920b57cec5SDimitry Andric : RegReductionPQBase(mf, SF::HasReadyFilter, tracksrp, srcorder, 18930b57cec5SDimitry Andric tii, tri, tli), 18940b57cec5SDimitry Andric Picker(this) {} 18950b57cec5SDimitry Andric 18960b57cec5SDimitry Andric bool isBottomUp() const override { return SF::IsBottomUp; } 18970b57cec5SDimitry Andric 18980b57cec5SDimitry Andric bool isReady(SUnit *U) const override { 18990b57cec5SDimitry Andric return Picker.HasReadyFilter && Picker.isReady(U, getCurCycle()); 19000b57cec5SDimitry Andric } 19010b57cec5SDimitry Andric 19020b57cec5SDimitry Andric SUnit *pop() override { 19030b57cec5SDimitry Andric if (Queue.empty()) return nullptr; 19040b57cec5SDimitry Andric 19050b57cec5SDimitry Andric SUnit *V = popFromQueue(Queue, Picker, scheduleDAG); 19060b57cec5SDimitry Andric V->NodeQueueId = 0; 19070b57cec5SDimitry Andric return V; 19080b57cec5SDimitry Andric } 19090b57cec5SDimitry Andric 19100b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 19110b57cec5SDimitry Andric LLVM_DUMP_METHOD void dump(ScheduleDAG *DAG) const override { 19120b57cec5SDimitry Andric // Emulate pop() without clobbering NodeQueueIds. 19130b57cec5SDimitry Andric std::vector<SUnit *> DumpQueue = Queue; 19140b57cec5SDimitry Andric SF DumpPicker = Picker; 19150b57cec5SDimitry Andric while (!DumpQueue.empty()) { 19160b57cec5SDimitry Andric SUnit *SU = popFromQueue(DumpQueue, DumpPicker, scheduleDAG); 19170b57cec5SDimitry Andric dbgs() << "Height " << SU->getHeight() << ": "; 19180b57cec5SDimitry Andric DAG->dumpNode(*SU); 19190b57cec5SDimitry Andric } 19200b57cec5SDimitry Andric } 19210b57cec5SDimitry Andric #endif 19220b57cec5SDimitry Andric }; 19230b57cec5SDimitry Andric 19240b57cec5SDimitry Andric using BURegReductionPriorityQueue = RegReductionPriorityQueue<bu_ls_rr_sort>; 19250b57cec5SDimitry Andric using SrcRegReductionPriorityQueue = RegReductionPriorityQueue<src_ls_rr_sort>; 19260b57cec5SDimitry Andric using HybridBURRPriorityQueue = RegReductionPriorityQueue<hybrid_ls_rr_sort>; 19270b57cec5SDimitry Andric using ILPBURRPriorityQueue = RegReductionPriorityQueue<ilp_ls_rr_sort>; 19280b57cec5SDimitry Andric 19290b57cec5SDimitry Andric } // end anonymous namespace 19300b57cec5SDimitry Andric 19310b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 19320b57cec5SDimitry Andric // Static Node Priority for Register Pressure Reduction 19330b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 19340b57cec5SDimitry Andric 19350b57cec5SDimitry Andric // Check for special nodes that bypass scheduling heuristics. 19360b57cec5SDimitry Andric // Currently this pushes TokenFactor nodes down, but may be used for other 19370b57cec5SDimitry Andric // pseudo-ops as well. 19380b57cec5SDimitry Andric // 19390b57cec5SDimitry Andric // Return -1 to schedule right above left, 1 for left above right. 19400b57cec5SDimitry Andric // Return 0 if no bias exists. 19410b57cec5SDimitry Andric static int checkSpecialNodes(const SUnit *left, const SUnit *right) { 19420b57cec5SDimitry Andric bool LSchedLow = left->isScheduleLow; 19430b57cec5SDimitry Andric bool RSchedLow = right->isScheduleLow; 19440b57cec5SDimitry Andric if (LSchedLow != RSchedLow) 19450b57cec5SDimitry Andric return LSchedLow < RSchedLow ? 1 : -1; 19460b57cec5SDimitry Andric return 0; 19470b57cec5SDimitry Andric } 19480b57cec5SDimitry Andric 19490b57cec5SDimitry Andric /// CalcNodeSethiUllmanNumber - Compute Sethi Ullman number. 19500b57cec5SDimitry Andric /// Smaller number is the higher priority. 19510b57cec5SDimitry Andric static unsigned 19520b57cec5SDimitry Andric CalcNodeSethiUllmanNumber(const SUnit *SU, std::vector<unsigned> &SUNumbers) { 19530b57cec5SDimitry Andric if (SUNumbers[SU->NodeNum] != 0) 19540b57cec5SDimitry Andric return SUNumbers[SU->NodeNum]; 19550b57cec5SDimitry Andric 19560b57cec5SDimitry Andric // Use WorkList to avoid stack overflow on excessively large IRs. 19570b57cec5SDimitry Andric struct WorkState { 19580b57cec5SDimitry Andric WorkState(const SUnit *SU) : SU(SU) {} 19590b57cec5SDimitry Andric const SUnit *SU; 19600b57cec5SDimitry Andric unsigned PredsProcessed = 0; 19610b57cec5SDimitry Andric }; 19620b57cec5SDimitry Andric 19630b57cec5SDimitry Andric SmallVector<WorkState, 16> WorkList; 19640b57cec5SDimitry Andric WorkList.push_back(SU); 19650b57cec5SDimitry Andric while (!WorkList.empty()) { 19660b57cec5SDimitry Andric auto &Temp = WorkList.back(); 19670b57cec5SDimitry Andric auto *TempSU = Temp.SU; 19680b57cec5SDimitry Andric bool AllPredsKnown = true; 19690b57cec5SDimitry Andric // Try to find a non-evaluated pred and push it into the processing stack. 19700b57cec5SDimitry Andric for (unsigned P = Temp.PredsProcessed; P < TempSU->Preds.size(); ++P) { 19710b57cec5SDimitry Andric auto &Pred = TempSU->Preds[P]; 19720b57cec5SDimitry Andric if (Pred.isCtrl()) continue; // ignore chain preds 19730b57cec5SDimitry Andric SUnit *PredSU = Pred.getSUnit(); 19740b57cec5SDimitry Andric if (SUNumbers[PredSU->NodeNum] == 0) { 19750b57cec5SDimitry Andric #ifndef NDEBUG 19760b57cec5SDimitry Andric // In debug mode, check that we don't have such element in the stack. 19770b57cec5SDimitry Andric for (auto It : WorkList) 19780b57cec5SDimitry Andric assert(It.SU != PredSU && "Trying to push an element twice?"); 19790b57cec5SDimitry Andric #endif 19800b57cec5SDimitry Andric // Next time start processing this one starting from the next pred. 19810b57cec5SDimitry Andric Temp.PredsProcessed = P + 1; 19820b57cec5SDimitry Andric WorkList.push_back(PredSU); 19830b57cec5SDimitry Andric AllPredsKnown = false; 19840b57cec5SDimitry Andric break; 19850b57cec5SDimitry Andric } 19860b57cec5SDimitry Andric } 19870b57cec5SDimitry Andric 19880b57cec5SDimitry Andric if (!AllPredsKnown) 19890b57cec5SDimitry Andric continue; 19900b57cec5SDimitry Andric 19910b57cec5SDimitry Andric // Once all preds are known, we can calculate the answer for this one. 19920b57cec5SDimitry Andric unsigned SethiUllmanNumber = 0; 19930b57cec5SDimitry Andric unsigned Extra = 0; 19940b57cec5SDimitry Andric for (const SDep &Pred : TempSU->Preds) { 19950b57cec5SDimitry Andric if (Pred.isCtrl()) continue; // ignore chain preds 19960b57cec5SDimitry Andric SUnit *PredSU = Pred.getSUnit(); 19970b57cec5SDimitry Andric unsigned PredSethiUllman = SUNumbers[PredSU->NodeNum]; 19980b57cec5SDimitry Andric assert(PredSethiUllman > 0 && "We should have evaluated this pred!"); 19990b57cec5SDimitry Andric if (PredSethiUllman > SethiUllmanNumber) { 20000b57cec5SDimitry Andric SethiUllmanNumber = PredSethiUllman; 20010b57cec5SDimitry Andric Extra = 0; 20020b57cec5SDimitry Andric } else if (PredSethiUllman == SethiUllmanNumber) 20030b57cec5SDimitry Andric ++Extra; 20040b57cec5SDimitry Andric } 20050b57cec5SDimitry Andric 20060b57cec5SDimitry Andric SethiUllmanNumber += Extra; 20070b57cec5SDimitry Andric if (SethiUllmanNumber == 0) 20080b57cec5SDimitry Andric SethiUllmanNumber = 1; 20090b57cec5SDimitry Andric SUNumbers[TempSU->NodeNum] = SethiUllmanNumber; 20100b57cec5SDimitry Andric WorkList.pop_back(); 20110b57cec5SDimitry Andric } 20120b57cec5SDimitry Andric 20130b57cec5SDimitry Andric assert(SUNumbers[SU->NodeNum] > 0 && "SethiUllman should never be zero!"); 20140b57cec5SDimitry Andric return SUNumbers[SU->NodeNum]; 20150b57cec5SDimitry Andric } 20160b57cec5SDimitry Andric 20170b57cec5SDimitry Andric /// CalculateSethiUllmanNumbers - Calculate Sethi-Ullman numbers of all 20180b57cec5SDimitry Andric /// scheduling units. 20190b57cec5SDimitry Andric void RegReductionPQBase::CalculateSethiUllmanNumbers() { 20200b57cec5SDimitry Andric SethiUllmanNumbers.assign(SUnits->size(), 0); 20210b57cec5SDimitry Andric 20220b57cec5SDimitry Andric for (const SUnit &SU : *SUnits) 20230b57cec5SDimitry Andric CalcNodeSethiUllmanNumber(&SU, SethiUllmanNumbers); 20240b57cec5SDimitry Andric } 20250b57cec5SDimitry Andric 20260b57cec5SDimitry Andric void RegReductionPQBase::addNode(const SUnit *SU) { 20270b57cec5SDimitry Andric unsigned SUSize = SethiUllmanNumbers.size(); 20280b57cec5SDimitry Andric if (SUnits->size() > SUSize) 20290b57cec5SDimitry Andric SethiUllmanNumbers.resize(SUSize*2, 0); 20300b57cec5SDimitry Andric CalcNodeSethiUllmanNumber(SU, SethiUllmanNumbers); 20310b57cec5SDimitry Andric } 20320b57cec5SDimitry Andric 20330b57cec5SDimitry Andric void RegReductionPQBase::updateNode(const SUnit *SU) { 20340b57cec5SDimitry Andric SethiUllmanNumbers[SU->NodeNum] = 0; 20350b57cec5SDimitry Andric CalcNodeSethiUllmanNumber(SU, SethiUllmanNumbers); 20360b57cec5SDimitry Andric } 20370b57cec5SDimitry Andric 20380b57cec5SDimitry Andric // Lower priority means schedule further down. For bottom-up scheduling, lower 20390b57cec5SDimitry Andric // priority SUs are scheduled before higher priority SUs. 20400b57cec5SDimitry Andric unsigned RegReductionPQBase::getNodePriority(const SUnit *SU) const { 20410b57cec5SDimitry Andric assert(SU->NodeNum < SethiUllmanNumbers.size()); 20420b57cec5SDimitry Andric unsigned Opc = SU->getNode() ? SU->getNode()->getOpcode() : 0; 20430b57cec5SDimitry Andric if (Opc == ISD::TokenFactor || Opc == ISD::CopyToReg) 20440b57cec5SDimitry Andric // CopyToReg should be close to its uses to facilitate coalescing and 20450b57cec5SDimitry Andric // avoid spilling. 20460b57cec5SDimitry Andric return 0; 20470b57cec5SDimitry Andric if (Opc == TargetOpcode::EXTRACT_SUBREG || 20480b57cec5SDimitry Andric Opc == TargetOpcode::SUBREG_TO_REG || 20490b57cec5SDimitry Andric Opc == TargetOpcode::INSERT_SUBREG) 20500b57cec5SDimitry Andric // EXTRACT_SUBREG, INSERT_SUBREG, and SUBREG_TO_REG nodes should be 20510b57cec5SDimitry Andric // close to their uses to facilitate coalescing. 20520b57cec5SDimitry Andric return 0; 20530b57cec5SDimitry Andric if (SU->NumSuccs == 0 && SU->NumPreds != 0) 20540b57cec5SDimitry Andric // If SU does not have a register use, i.e. it doesn't produce a value 20550b57cec5SDimitry Andric // that would be consumed (e.g. store), then it terminates a chain of 20560b57cec5SDimitry Andric // computation. Give it a large SethiUllman number so it will be 20570b57cec5SDimitry Andric // scheduled right before its predecessors that it doesn't lengthen 20580b57cec5SDimitry Andric // their live ranges. 20590b57cec5SDimitry Andric return 0xffff; 20600b57cec5SDimitry Andric if (SU->NumPreds == 0 && SU->NumSuccs != 0) 20610b57cec5SDimitry Andric // If SU does not have a register def, schedule it close to its uses 20620b57cec5SDimitry Andric // because it does not lengthen any live ranges. 20630b57cec5SDimitry Andric return 0; 20640b57cec5SDimitry Andric #if 1 20650b57cec5SDimitry Andric return SethiUllmanNumbers[SU->NodeNum]; 20660b57cec5SDimitry Andric #else 20670b57cec5SDimitry Andric unsigned Priority = SethiUllmanNumbers[SU->NodeNum]; 20680b57cec5SDimitry Andric if (SU->isCallOp) { 20690b57cec5SDimitry Andric // FIXME: This assumes all of the defs are used as call operands. 20700b57cec5SDimitry Andric int NP = (int)Priority - SU->getNode()->getNumValues(); 20710b57cec5SDimitry Andric return (NP > 0) ? NP : 0; 20720b57cec5SDimitry Andric } 20730b57cec5SDimitry Andric return Priority; 20740b57cec5SDimitry Andric #endif 20750b57cec5SDimitry Andric } 20760b57cec5SDimitry Andric 20770b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 20780b57cec5SDimitry Andric // Register Pressure Tracking 20790b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 20800b57cec5SDimitry Andric 20810b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 20820b57cec5SDimitry Andric LLVM_DUMP_METHOD void RegReductionPQBase::dumpRegPressure() const { 20830b57cec5SDimitry Andric for (const TargetRegisterClass *RC : TRI->regclasses()) { 20840b57cec5SDimitry Andric unsigned Id = RC->getID(); 20850b57cec5SDimitry Andric unsigned RP = RegPressure[Id]; 20860b57cec5SDimitry Andric if (!RP) continue; 20870b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << TRI->getRegClassName(RC) << ": " << RP << " / " 20880b57cec5SDimitry Andric << RegLimit[Id] << '\n'); 20890b57cec5SDimitry Andric } 20900b57cec5SDimitry Andric } 20910b57cec5SDimitry Andric #endif 20920b57cec5SDimitry Andric 20930b57cec5SDimitry Andric bool RegReductionPQBase::HighRegPressure(const SUnit *SU) const { 20940b57cec5SDimitry Andric if (!TLI) 20950b57cec5SDimitry Andric return false; 20960b57cec5SDimitry Andric 20970b57cec5SDimitry Andric for (const SDep &Pred : SU->Preds) { 20980b57cec5SDimitry Andric if (Pred.isCtrl()) 20990b57cec5SDimitry Andric continue; 21000b57cec5SDimitry Andric SUnit *PredSU = Pred.getSUnit(); 21010b57cec5SDimitry Andric // NumRegDefsLeft is zero when enough uses of this node have been scheduled 21020b57cec5SDimitry Andric // to cover the number of registers defined (they are all live). 21030b57cec5SDimitry Andric if (PredSU->NumRegDefsLeft == 0) { 21040b57cec5SDimitry Andric continue; 21050b57cec5SDimitry Andric } 21060b57cec5SDimitry Andric for (ScheduleDAGSDNodes::RegDefIter RegDefPos(PredSU, scheduleDAG); 21070b57cec5SDimitry Andric RegDefPos.IsValid(); RegDefPos.Advance()) { 21080b57cec5SDimitry Andric unsigned RCId, Cost; 21090b57cec5SDimitry Andric GetCostForDef(RegDefPos, TLI, TII, TRI, RCId, Cost, MF); 21100b57cec5SDimitry Andric 21110b57cec5SDimitry Andric if ((RegPressure[RCId] + Cost) >= RegLimit[RCId]) 21120b57cec5SDimitry Andric return true; 21130b57cec5SDimitry Andric } 21140b57cec5SDimitry Andric } 21150b57cec5SDimitry Andric return false; 21160b57cec5SDimitry Andric } 21170b57cec5SDimitry Andric 21180b57cec5SDimitry Andric bool RegReductionPQBase::MayReduceRegPressure(SUnit *SU) const { 21190b57cec5SDimitry Andric const SDNode *N = SU->getNode(); 21200b57cec5SDimitry Andric 21210b57cec5SDimitry Andric if (!N->isMachineOpcode() || !SU->NumSuccs) 21220b57cec5SDimitry Andric return false; 21230b57cec5SDimitry Andric 21240b57cec5SDimitry Andric unsigned NumDefs = TII->get(N->getMachineOpcode()).getNumDefs(); 21250b57cec5SDimitry Andric for (unsigned i = 0; i != NumDefs; ++i) { 21260b57cec5SDimitry Andric MVT VT = N->getSimpleValueType(i); 21270b57cec5SDimitry Andric if (!N->hasAnyUseOfValue(i)) 21280b57cec5SDimitry Andric continue; 21290b57cec5SDimitry Andric unsigned RCId = TLI->getRepRegClassFor(VT)->getID(); 21300b57cec5SDimitry Andric if (RegPressure[RCId] >= RegLimit[RCId]) 21310b57cec5SDimitry Andric return true; 21320b57cec5SDimitry Andric } 21330b57cec5SDimitry Andric return false; 21340b57cec5SDimitry Andric } 21350b57cec5SDimitry Andric 21360b57cec5SDimitry Andric // Compute the register pressure contribution by this instruction by count up 21370b57cec5SDimitry Andric // for uses that are not live and down for defs. Only count register classes 21380b57cec5SDimitry Andric // that are already under high pressure. As a side effect, compute the number of 21390b57cec5SDimitry Andric // uses of registers that are already live. 21400b57cec5SDimitry Andric // 21410b57cec5SDimitry Andric // FIXME: This encompasses the logic in HighRegPressure and MayReduceRegPressure 21420b57cec5SDimitry Andric // so could probably be factored. 21430b57cec5SDimitry Andric int RegReductionPQBase::RegPressureDiff(SUnit *SU, unsigned &LiveUses) const { 21440b57cec5SDimitry Andric LiveUses = 0; 21450b57cec5SDimitry Andric int PDiff = 0; 21460b57cec5SDimitry Andric for (const SDep &Pred : SU->Preds) { 21470b57cec5SDimitry Andric if (Pred.isCtrl()) 21480b57cec5SDimitry Andric continue; 21490b57cec5SDimitry Andric SUnit *PredSU = Pred.getSUnit(); 21500b57cec5SDimitry Andric // NumRegDefsLeft is zero when enough uses of this node have been scheduled 21510b57cec5SDimitry Andric // to cover the number of registers defined (they are all live). 21520b57cec5SDimitry Andric if (PredSU->NumRegDefsLeft == 0) { 21530b57cec5SDimitry Andric if (PredSU->getNode()->isMachineOpcode()) 21540b57cec5SDimitry Andric ++LiveUses; 21550b57cec5SDimitry Andric continue; 21560b57cec5SDimitry Andric } 21570b57cec5SDimitry Andric for (ScheduleDAGSDNodes::RegDefIter RegDefPos(PredSU, scheduleDAG); 21580b57cec5SDimitry Andric RegDefPos.IsValid(); RegDefPos.Advance()) { 21590b57cec5SDimitry Andric MVT VT = RegDefPos.GetValue(); 21600b57cec5SDimitry Andric unsigned RCId = TLI->getRepRegClassFor(VT)->getID(); 21610b57cec5SDimitry Andric if (RegPressure[RCId] >= RegLimit[RCId]) 21620b57cec5SDimitry Andric ++PDiff; 21630b57cec5SDimitry Andric } 21640b57cec5SDimitry Andric } 21650b57cec5SDimitry Andric const SDNode *N = SU->getNode(); 21660b57cec5SDimitry Andric 21670b57cec5SDimitry Andric if (!N || !N->isMachineOpcode() || !SU->NumSuccs) 21680b57cec5SDimitry Andric return PDiff; 21690b57cec5SDimitry Andric 21700b57cec5SDimitry Andric unsigned NumDefs = TII->get(N->getMachineOpcode()).getNumDefs(); 21710b57cec5SDimitry Andric for (unsigned i = 0; i != NumDefs; ++i) { 21720b57cec5SDimitry Andric MVT VT = N->getSimpleValueType(i); 21730b57cec5SDimitry Andric if (!N->hasAnyUseOfValue(i)) 21740b57cec5SDimitry Andric continue; 21750b57cec5SDimitry Andric unsigned RCId = TLI->getRepRegClassFor(VT)->getID(); 21760b57cec5SDimitry Andric if (RegPressure[RCId] >= RegLimit[RCId]) 21770b57cec5SDimitry Andric --PDiff; 21780b57cec5SDimitry Andric } 21790b57cec5SDimitry Andric return PDiff; 21800b57cec5SDimitry Andric } 21810b57cec5SDimitry Andric 21820b57cec5SDimitry Andric void RegReductionPQBase::scheduledNode(SUnit *SU) { 21830b57cec5SDimitry Andric if (!TracksRegPressure) 21840b57cec5SDimitry Andric return; 21850b57cec5SDimitry Andric 21860b57cec5SDimitry Andric if (!SU->getNode()) 21870b57cec5SDimitry Andric return; 21880b57cec5SDimitry Andric 21890b57cec5SDimitry Andric for (const SDep &Pred : SU->Preds) { 21900b57cec5SDimitry Andric if (Pred.isCtrl()) 21910b57cec5SDimitry Andric continue; 21920b57cec5SDimitry Andric SUnit *PredSU = Pred.getSUnit(); 21930b57cec5SDimitry Andric // NumRegDefsLeft is zero when enough uses of this node have been scheduled 21940b57cec5SDimitry Andric // to cover the number of registers defined (they are all live). 21950b57cec5SDimitry Andric if (PredSU->NumRegDefsLeft == 0) { 21960b57cec5SDimitry Andric continue; 21970b57cec5SDimitry Andric } 21980b57cec5SDimitry Andric // FIXME: The ScheduleDAG currently loses information about which of a 21990b57cec5SDimitry Andric // node's values is consumed by each dependence. Consequently, if the node 22000b57cec5SDimitry Andric // defines multiple register classes, we don't know which to pressurize 22010b57cec5SDimitry Andric // here. Instead the following loop consumes the register defs in an 22020b57cec5SDimitry Andric // arbitrary order. At least it handles the common case of clustered loads 22030b57cec5SDimitry Andric // to the same class. For precise liveness, each SDep needs to indicate the 22040b57cec5SDimitry Andric // result number. But that tightly couples the ScheduleDAG with the 22050b57cec5SDimitry Andric // SelectionDAG making updates tricky. A simpler hack would be to attach a 22060b57cec5SDimitry Andric // value type or register class to SDep. 22070b57cec5SDimitry Andric // 22080b57cec5SDimitry Andric // The most important aspect of register tracking is balancing the increase 22090b57cec5SDimitry Andric // here with the reduction further below. Note that this SU may use multiple 22100b57cec5SDimitry Andric // defs in PredSU. The can't be determined here, but we've already 22110b57cec5SDimitry Andric // compensated by reducing NumRegDefsLeft in PredSU during 22120b57cec5SDimitry Andric // ScheduleDAGSDNodes::AddSchedEdges. 22130b57cec5SDimitry Andric --PredSU->NumRegDefsLeft; 22140b57cec5SDimitry Andric unsigned SkipRegDefs = PredSU->NumRegDefsLeft; 22150b57cec5SDimitry Andric for (ScheduleDAGSDNodes::RegDefIter RegDefPos(PredSU, scheduleDAG); 22160b57cec5SDimitry Andric RegDefPos.IsValid(); RegDefPos.Advance(), --SkipRegDefs) { 22170b57cec5SDimitry Andric if (SkipRegDefs) 22180b57cec5SDimitry Andric continue; 22190b57cec5SDimitry Andric 22200b57cec5SDimitry Andric unsigned RCId, Cost; 22210b57cec5SDimitry Andric GetCostForDef(RegDefPos, TLI, TII, TRI, RCId, Cost, MF); 22220b57cec5SDimitry Andric RegPressure[RCId] += Cost; 22230b57cec5SDimitry Andric break; 22240b57cec5SDimitry Andric } 22250b57cec5SDimitry Andric } 22260b57cec5SDimitry Andric 22270b57cec5SDimitry Andric // We should have this assert, but there may be dead SDNodes that never 22280b57cec5SDimitry Andric // materialize as SUnits, so they don't appear to generate liveness. 22290b57cec5SDimitry Andric //assert(SU->NumRegDefsLeft == 0 && "not all regdefs have scheduled uses"); 22300b57cec5SDimitry Andric int SkipRegDefs = (int)SU->NumRegDefsLeft; 22310b57cec5SDimitry Andric for (ScheduleDAGSDNodes::RegDefIter RegDefPos(SU, scheduleDAG); 22320b57cec5SDimitry Andric RegDefPos.IsValid(); RegDefPos.Advance(), --SkipRegDefs) { 22330b57cec5SDimitry Andric if (SkipRegDefs > 0) 22340b57cec5SDimitry Andric continue; 22350b57cec5SDimitry Andric unsigned RCId, Cost; 22360b57cec5SDimitry Andric GetCostForDef(RegDefPos, TLI, TII, TRI, RCId, Cost, MF); 22370b57cec5SDimitry Andric if (RegPressure[RCId] < Cost) { 22380b57cec5SDimitry Andric // Register pressure tracking is imprecise. This can happen. But we try 22390b57cec5SDimitry Andric // hard not to let it happen because it likely results in poor scheduling. 22400b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " SU(" << SU->NodeNum 22410b57cec5SDimitry Andric << ") has too many regdefs\n"); 22420b57cec5SDimitry Andric RegPressure[RCId] = 0; 22430b57cec5SDimitry Andric } 22440b57cec5SDimitry Andric else { 22450b57cec5SDimitry Andric RegPressure[RCId] -= Cost; 22460b57cec5SDimitry Andric } 22470b57cec5SDimitry Andric } 22480b57cec5SDimitry Andric LLVM_DEBUG(dumpRegPressure()); 22490b57cec5SDimitry Andric } 22500b57cec5SDimitry Andric 22510b57cec5SDimitry Andric void RegReductionPQBase::unscheduledNode(SUnit *SU) { 22520b57cec5SDimitry Andric if (!TracksRegPressure) 22530b57cec5SDimitry Andric return; 22540b57cec5SDimitry Andric 22550b57cec5SDimitry Andric const SDNode *N = SU->getNode(); 22560b57cec5SDimitry Andric if (!N) return; 22570b57cec5SDimitry Andric 22580b57cec5SDimitry Andric if (!N->isMachineOpcode()) { 22590b57cec5SDimitry Andric if (N->getOpcode() != ISD::CopyToReg) 22600b57cec5SDimitry Andric return; 22610b57cec5SDimitry Andric } else { 22620b57cec5SDimitry Andric unsigned Opc = N->getMachineOpcode(); 22630b57cec5SDimitry Andric if (Opc == TargetOpcode::EXTRACT_SUBREG || 22640b57cec5SDimitry Andric Opc == TargetOpcode::INSERT_SUBREG || 22650b57cec5SDimitry Andric Opc == TargetOpcode::SUBREG_TO_REG || 22660b57cec5SDimitry Andric Opc == TargetOpcode::REG_SEQUENCE || 22670b57cec5SDimitry Andric Opc == TargetOpcode::IMPLICIT_DEF) 22680b57cec5SDimitry Andric return; 22690b57cec5SDimitry Andric } 22700b57cec5SDimitry Andric 22710b57cec5SDimitry Andric for (const SDep &Pred : SU->Preds) { 22720b57cec5SDimitry Andric if (Pred.isCtrl()) 22730b57cec5SDimitry Andric continue; 22740b57cec5SDimitry Andric SUnit *PredSU = Pred.getSUnit(); 22750b57cec5SDimitry Andric // NumSuccsLeft counts all deps. Don't compare it with NumSuccs which only 22760b57cec5SDimitry Andric // counts data deps. 22770b57cec5SDimitry Andric if (PredSU->NumSuccsLeft != PredSU->Succs.size()) 22780b57cec5SDimitry Andric continue; 22790b57cec5SDimitry Andric const SDNode *PN = PredSU->getNode(); 22800b57cec5SDimitry Andric if (!PN->isMachineOpcode()) { 22810b57cec5SDimitry Andric if (PN->getOpcode() == ISD::CopyFromReg) { 22820b57cec5SDimitry Andric MVT VT = PN->getSimpleValueType(0); 22830b57cec5SDimitry Andric unsigned RCId = TLI->getRepRegClassFor(VT)->getID(); 22840b57cec5SDimitry Andric RegPressure[RCId] += TLI->getRepRegClassCostFor(VT); 22850b57cec5SDimitry Andric } 22860b57cec5SDimitry Andric continue; 22870b57cec5SDimitry Andric } 22880b57cec5SDimitry Andric unsigned POpc = PN->getMachineOpcode(); 22890b57cec5SDimitry Andric if (POpc == TargetOpcode::IMPLICIT_DEF) 22900b57cec5SDimitry Andric continue; 22910b57cec5SDimitry Andric if (POpc == TargetOpcode::EXTRACT_SUBREG || 22920b57cec5SDimitry Andric POpc == TargetOpcode::INSERT_SUBREG || 22930b57cec5SDimitry Andric POpc == TargetOpcode::SUBREG_TO_REG) { 22940b57cec5SDimitry Andric MVT VT = PN->getSimpleValueType(0); 22950b57cec5SDimitry Andric unsigned RCId = TLI->getRepRegClassFor(VT)->getID(); 22960b57cec5SDimitry Andric RegPressure[RCId] += TLI->getRepRegClassCostFor(VT); 22970b57cec5SDimitry Andric continue; 22980b57cec5SDimitry Andric } 2299bdd1243dSDimitry Andric if (POpc == TargetOpcode::REG_SEQUENCE) { 2300647cbc5dSDimitry Andric unsigned DstRCIdx = PN->getConstantOperandVal(0); 2301bdd1243dSDimitry Andric const TargetRegisterClass *RC = TRI->getRegClass(DstRCIdx); 2302bdd1243dSDimitry Andric unsigned RCId = RC->getID(); 2303bdd1243dSDimitry Andric // REG_SEQUENCE is untyped, so getRepRegClassCostFor could not be used 2304bdd1243dSDimitry Andric // here. Instead use the same constant as in GetCostForDef. 2305bdd1243dSDimitry Andric RegPressure[RCId] += RegSequenceCost; 2306bdd1243dSDimitry Andric continue; 2307bdd1243dSDimitry Andric } 23080b57cec5SDimitry Andric unsigned NumDefs = TII->get(PN->getMachineOpcode()).getNumDefs(); 23090b57cec5SDimitry Andric for (unsigned i = 0; i != NumDefs; ++i) { 23100b57cec5SDimitry Andric MVT VT = PN->getSimpleValueType(i); 23110b57cec5SDimitry Andric if (!PN->hasAnyUseOfValue(i)) 23120b57cec5SDimitry Andric continue; 23130b57cec5SDimitry Andric unsigned RCId = TLI->getRepRegClassFor(VT)->getID(); 23140b57cec5SDimitry Andric if (RegPressure[RCId] < TLI->getRepRegClassCostFor(VT)) 23150b57cec5SDimitry Andric // Register pressure tracking is imprecise. This can happen. 23160b57cec5SDimitry Andric RegPressure[RCId] = 0; 23170b57cec5SDimitry Andric else 23180b57cec5SDimitry Andric RegPressure[RCId] -= TLI->getRepRegClassCostFor(VT); 23190b57cec5SDimitry Andric } 23200b57cec5SDimitry Andric } 23210b57cec5SDimitry Andric 23220b57cec5SDimitry Andric // Check for isMachineOpcode() as PrescheduleNodesWithMultipleUses() 23230b57cec5SDimitry Andric // may transfer data dependencies to CopyToReg. 23240b57cec5SDimitry Andric if (SU->NumSuccs && N->isMachineOpcode()) { 23250b57cec5SDimitry Andric unsigned NumDefs = TII->get(N->getMachineOpcode()).getNumDefs(); 23260b57cec5SDimitry Andric for (unsigned i = NumDefs, e = N->getNumValues(); i != e; ++i) { 23270b57cec5SDimitry Andric MVT VT = N->getSimpleValueType(i); 23280b57cec5SDimitry Andric if (VT == MVT::Glue || VT == MVT::Other) 23290b57cec5SDimitry Andric continue; 23300b57cec5SDimitry Andric if (!N->hasAnyUseOfValue(i)) 23310b57cec5SDimitry Andric continue; 23320b57cec5SDimitry Andric unsigned RCId = TLI->getRepRegClassFor(VT)->getID(); 23330b57cec5SDimitry Andric RegPressure[RCId] += TLI->getRepRegClassCostFor(VT); 23340b57cec5SDimitry Andric } 23350b57cec5SDimitry Andric } 23360b57cec5SDimitry Andric 23370b57cec5SDimitry Andric LLVM_DEBUG(dumpRegPressure()); 23380b57cec5SDimitry Andric } 23390b57cec5SDimitry Andric 23400b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 23410b57cec5SDimitry Andric // Dynamic Node Priority for Register Pressure Reduction 23420b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 23430b57cec5SDimitry Andric 23440b57cec5SDimitry Andric /// closestSucc - Returns the scheduled cycle of the successor which is 23450b57cec5SDimitry Andric /// closest to the current cycle. 23460b57cec5SDimitry Andric static unsigned closestSucc(const SUnit *SU) { 23470b57cec5SDimitry Andric unsigned MaxHeight = 0; 23480b57cec5SDimitry Andric for (const SDep &Succ : SU->Succs) { 23490b57cec5SDimitry Andric if (Succ.isCtrl()) continue; // ignore chain succs 23500b57cec5SDimitry Andric unsigned Height = Succ.getSUnit()->getHeight(); 23510b57cec5SDimitry Andric // If there are bunch of CopyToRegs stacked up, they should be considered 23520b57cec5SDimitry Andric // to be at the same position. 23530b57cec5SDimitry Andric if (Succ.getSUnit()->getNode() && 23540b57cec5SDimitry Andric Succ.getSUnit()->getNode()->getOpcode() == ISD::CopyToReg) 23550b57cec5SDimitry Andric Height = closestSucc(Succ.getSUnit())+1; 23560b57cec5SDimitry Andric if (Height > MaxHeight) 23570b57cec5SDimitry Andric MaxHeight = Height; 23580b57cec5SDimitry Andric } 23590b57cec5SDimitry Andric return MaxHeight; 23600b57cec5SDimitry Andric } 23610b57cec5SDimitry Andric 23620b57cec5SDimitry Andric /// calcMaxScratches - Returns an cost estimate of the worse case requirement 23630b57cec5SDimitry Andric /// for scratch registers, i.e. number of data dependencies. 23640b57cec5SDimitry Andric static unsigned calcMaxScratches(const SUnit *SU) { 23650b57cec5SDimitry Andric unsigned Scratches = 0; 23660b57cec5SDimitry Andric for (const SDep &Pred : SU->Preds) { 23670b57cec5SDimitry Andric if (Pred.isCtrl()) continue; // ignore chain preds 23680b57cec5SDimitry Andric Scratches++; 23690b57cec5SDimitry Andric } 23700b57cec5SDimitry Andric return Scratches; 23710b57cec5SDimitry Andric } 23720b57cec5SDimitry Andric 23730b57cec5SDimitry Andric /// hasOnlyLiveInOpers - Return true if SU has only value predecessors that are 23740b57cec5SDimitry Andric /// CopyFromReg from a virtual register. 23750b57cec5SDimitry Andric static bool hasOnlyLiveInOpers(const SUnit *SU) { 23760b57cec5SDimitry Andric bool RetVal = false; 23770b57cec5SDimitry Andric for (const SDep &Pred : SU->Preds) { 23780b57cec5SDimitry Andric if (Pred.isCtrl()) continue; 23790b57cec5SDimitry Andric const SUnit *PredSU = Pred.getSUnit(); 23800b57cec5SDimitry Andric if (PredSU->getNode() && 23810b57cec5SDimitry Andric PredSU->getNode()->getOpcode() == ISD::CopyFromReg) { 2382bdd1243dSDimitry Andric Register Reg = 23830b57cec5SDimitry Andric cast<RegisterSDNode>(PredSU->getNode()->getOperand(1))->getReg(); 2384bdd1243dSDimitry Andric if (Reg.isVirtual()) { 23850b57cec5SDimitry Andric RetVal = true; 23860b57cec5SDimitry Andric continue; 23870b57cec5SDimitry Andric } 23880b57cec5SDimitry Andric } 23890b57cec5SDimitry Andric return false; 23900b57cec5SDimitry Andric } 23910b57cec5SDimitry Andric return RetVal; 23920b57cec5SDimitry Andric } 23930b57cec5SDimitry Andric 23940b57cec5SDimitry Andric /// hasOnlyLiveOutUses - Return true if SU has only value successors that are 23950b57cec5SDimitry Andric /// CopyToReg to a virtual register. This SU def is probably a liveout and 23960b57cec5SDimitry Andric /// it has no other use. It should be scheduled closer to the terminator. 23970b57cec5SDimitry Andric static bool hasOnlyLiveOutUses(const SUnit *SU) { 23980b57cec5SDimitry Andric bool RetVal = false; 23990b57cec5SDimitry Andric for (const SDep &Succ : SU->Succs) { 24000b57cec5SDimitry Andric if (Succ.isCtrl()) continue; 24010b57cec5SDimitry Andric const SUnit *SuccSU = Succ.getSUnit(); 24020b57cec5SDimitry Andric if (SuccSU->getNode() && SuccSU->getNode()->getOpcode() == ISD::CopyToReg) { 2403bdd1243dSDimitry Andric Register Reg = 24040b57cec5SDimitry Andric cast<RegisterSDNode>(SuccSU->getNode()->getOperand(1))->getReg(); 2405bdd1243dSDimitry Andric if (Reg.isVirtual()) { 24060b57cec5SDimitry Andric RetVal = true; 24070b57cec5SDimitry Andric continue; 24080b57cec5SDimitry Andric } 24090b57cec5SDimitry Andric } 24100b57cec5SDimitry Andric return false; 24110b57cec5SDimitry Andric } 24120b57cec5SDimitry Andric return RetVal; 24130b57cec5SDimitry Andric } 24140b57cec5SDimitry Andric 24150b57cec5SDimitry Andric // Set isVRegCycle for a node with only live in opers and live out uses. Also 24160b57cec5SDimitry Andric // set isVRegCycle for its CopyFromReg operands. 24170b57cec5SDimitry Andric // 24180b57cec5SDimitry Andric // This is only relevant for single-block loops, in which case the VRegCycle 24190b57cec5SDimitry Andric // node is likely an induction variable in which the operand and target virtual 24200b57cec5SDimitry Andric // registers should be coalesced (e.g. pre/post increment values). Setting the 24210b57cec5SDimitry Andric // isVRegCycle flag helps the scheduler prioritize other uses of the same 24220b57cec5SDimitry Andric // CopyFromReg so that this node becomes the virtual register "kill". This 24230b57cec5SDimitry Andric // avoids interference between the values live in and out of the block and 24240b57cec5SDimitry Andric // eliminates a copy inside the loop. 24250b57cec5SDimitry Andric static void initVRegCycle(SUnit *SU) { 24260b57cec5SDimitry Andric if (DisableSchedVRegCycle) 24270b57cec5SDimitry Andric return; 24280b57cec5SDimitry Andric 24290b57cec5SDimitry Andric if (!hasOnlyLiveInOpers(SU) || !hasOnlyLiveOutUses(SU)) 24300b57cec5SDimitry Andric return; 24310b57cec5SDimitry Andric 24320b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "VRegCycle: SU(" << SU->NodeNum << ")\n"); 24330b57cec5SDimitry Andric 24340b57cec5SDimitry Andric SU->isVRegCycle = true; 24350b57cec5SDimitry Andric 24360b57cec5SDimitry Andric for (const SDep &Pred : SU->Preds) { 24370b57cec5SDimitry Andric if (Pred.isCtrl()) continue; 24380b57cec5SDimitry Andric Pred.getSUnit()->isVRegCycle = true; 24390b57cec5SDimitry Andric } 24400b57cec5SDimitry Andric } 24410b57cec5SDimitry Andric 24420b57cec5SDimitry Andric // After scheduling the definition of a VRegCycle, clear the isVRegCycle flag of 24430b57cec5SDimitry Andric // CopyFromReg operands. We should no longer penalize other uses of this VReg. 24440b57cec5SDimitry Andric static void resetVRegCycle(SUnit *SU) { 24450b57cec5SDimitry Andric if (!SU->isVRegCycle) 24460b57cec5SDimitry Andric return; 24470b57cec5SDimitry Andric 24480b57cec5SDimitry Andric for (const SDep &Pred : SU->Preds) { 24490b57cec5SDimitry Andric if (Pred.isCtrl()) continue; // ignore chain preds 24500b57cec5SDimitry Andric SUnit *PredSU = Pred.getSUnit(); 24510b57cec5SDimitry Andric if (PredSU->isVRegCycle) { 24520b57cec5SDimitry Andric assert(PredSU->getNode()->getOpcode() == ISD::CopyFromReg && 24530b57cec5SDimitry Andric "VRegCycle def must be CopyFromReg"); 24540b57cec5SDimitry Andric Pred.getSUnit()->isVRegCycle = false; 24550b57cec5SDimitry Andric } 24560b57cec5SDimitry Andric } 24570b57cec5SDimitry Andric } 24580b57cec5SDimitry Andric 24590b57cec5SDimitry Andric // Return true if this SUnit uses a CopyFromReg node marked as a VRegCycle. This 24600b57cec5SDimitry Andric // means a node that defines the VRegCycle has not been scheduled yet. 24610b57cec5SDimitry Andric static bool hasVRegCycleUse(const SUnit *SU) { 24620b57cec5SDimitry Andric // If this SU also defines the VReg, don't hoist it as a "use". 24630b57cec5SDimitry Andric if (SU->isVRegCycle) 24640b57cec5SDimitry Andric return false; 24650b57cec5SDimitry Andric 24660b57cec5SDimitry Andric for (const SDep &Pred : SU->Preds) { 24670b57cec5SDimitry Andric if (Pred.isCtrl()) continue; // ignore chain preds 24680b57cec5SDimitry Andric if (Pred.getSUnit()->isVRegCycle && 24690b57cec5SDimitry Andric Pred.getSUnit()->getNode()->getOpcode() == ISD::CopyFromReg) { 24700b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " VReg cycle use: SU (" << SU->NodeNum << ")\n"); 24710b57cec5SDimitry Andric return true; 24720b57cec5SDimitry Andric } 24730b57cec5SDimitry Andric } 24740b57cec5SDimitry Andric return false; 24750b57cec5SDimitry Andric } 24760b57cec5SDimitry Andric 24770b57cec5SDimitry Andric // Check for either a dependence (latency) or resource (hazard) stall. 24780b57cec5SDimitry Andric // 24790b57cec5SDimitry Andric // Note: The ScheduleHazardRecognizer interface requires a non-const SU. 24800b57cec5SDimitry Andric static bool BUHasStall(SUnit *SU, int Height, RegReductionPQBase *SPQ) { 24810b57cec5SDimitry Andric if ((int)SPQ->getCurCycle() < Height) return true; 24820b57cec5SDimitry Andric if (SPQ->getHazardRec()->getHazardType(SU, 0) 24830b57cec5SDimitry Andric != ScheduleHazardRecognizer::NoHazard) 24840b57cec5SDimitry Andric return true; 24850b57cec5SDimitry Andric return false; 24860b57cec5SDimitry Andric } 24870b57cec5SDimitry Andric 24880b57cec5SDimitry Andric // Return -1 if left has higher priority, 1 if right has higher priority. 24890b57cec5SDimitry Andric // Return 0 if latency-based priority is equivalent. 24900b57cec5SDimitry Andric static int BUCompareLatency(SUnit *left, SUnit *right, bool checkPref, 24910b57cec5SDimitry Andric RegReductionPQBase *SPQ) { 24920b57cec5SDimitry Andric // Scheduling an instruction that uses a VReg whose postincrement has not yet 24930b57cec5SDimitry Andric // been scheduled will induce a copy. Model this as an extra cycle of latency. 24940b57cec5SDimitry Andric int LPenalty = hasVRegCycleUse(left) ? 1 : 0; 24950b57cec5SDimitry Andric int RPenalty = hasVRegCycleUse(right) ? 1 : 0; 24960b57cec5SDimitry Andric int LHeight = (int)left->getHeight() + LPenalty; 24970b57cec5SDimitry Andric int RHeight = (int)right->getHeight() + RPenalty; 24980b57cec5SDimitry Andric 24990b57cec5SDimitry Andric bool LStall = (!checkPref || left->SchedulingPref == Sched::ILP) && 25000b57cec5SDimitry Andric BUHasStall(left, LHeight, SPQ); 25010b57cec5SDimitry Andric bool RStall = (!checkPref || right->SchedulingPref == Sched::ILP) && 25020b57cec5SDimitry Andric BUHasStall(right, RHeight, SPQ); 25030b57cec5SDimitry Andric 25040b57cec5SDimitry Andric // If scheduling one of the node will cause a pipeline stall, delay it. 25050b57cec5SDimitry Andric // If scheduling either one of the node will cause a pipeline stall, sort 25060b57cec5SDimitry Andric // them according to their height. 25070b57cec5SDimitry Andric if (LStall) { 25080b57cec5SDimitry Andric if (!RStall) 25090b57cec5SDimitry Andric return 1; 25100b57cec5SDimitry Andric if (LHeight != RHeight) 25110b57cec5SDimitry Andric return LHeight > RHeight ? 1 : -1; 25120b57cec5SDimitry Andric } else if (RStall) 25130b57cec5SDimitry Andric return -1; 25140b57cec5SDimitry Andric 25150b57cec5SDimitry Andric // If either node is scheduling for latency, sort them by height/depth 25160b57cec5SDimitry Andric // and latency. 25170b57cec5SDimitry Andric if (!checkPref || (left->SchedulingPref == Sched::ILP || 25180b57cec5SDimitry Andric right->SchedulingPref == Sched::ILP)) { 25190b57cec5SDimitry Andric // If neither instruction stalls (!LStall && !RStall) and HazardRecognizer 25200b57cec5SDimitry Andric // is enabled, grouping instructions by cycle, then its height is already 25210b57cec5SDimitry Andric // covered so only its depth matters. We also reach this point if both stall 25220b57cec5SDimitry Andric // but have the same height. 25230b57cec5SDimitry Andric if (!SPQ->getHazardRec()->isEnabled()) { 25240b57cec5SDimitry Andric if (LHeight != RHeight) 25250b57cec5SDimitry Andric return LHeight > RHeight ? 1 : -1; 25260b57cec5SDimitry Andric } 25270b57cec5SDimitry Andric int LDepth = left->getDepth() - LPenalty; 25280b57cec5SDimitry Andric int RDepth = right->getDepth() - RPenalty; 25290b57cec5SDimitry Andric if (LDepth != RDepth) { 25300b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " Comparing latency of SU (" << left->NodeNum 25310b57cec5SDimitry Andric << ") depth " << LDepth << " vs SU (" << right->NodeNum 25320b57cec5SDimitry Andric << ") depth " << RDepth << "\n"); 25330b57cec5SDimitry Andric return LDepth < RDepth ? 1 : -1; 25340b57cec5SDimitry Andric } 25350b57cec5SDimitry Andric if (left->Latency != right->Latency) 25360b57cec5SDimitry Andric return left->Latency > right->Latency ? 1 : -1; 25370b57cec5SDimitry Andric } 25380b57cec5SDimitry Andric return 0; 25390b57cec5SDimitry Andric } 25400b57cec5SDimitry Andric 25410b57cec5SDimitry Andric static bool BURRSort(SUnit *left, SUnit *right, RegReductionPQBase *SPQ) { 25420b57cec5SDimitry Andric // Schedule physical register definitions close to their use. This is 25430b57cec5SDimitry Andric // motivated by microarchitectures that can fuse cmp+jump macro-ops. But as 25440b57cec5SDimitry Andric // long as shortening physreg live ranges is generally good, we can defer 25450b57cec5SDimitry Andric // creating a subtarget hook. 25460b57cec5SDimitry Andric if (!DisableSchedPhysRegJoin) { 25470b57cec5SDimitry Andric bool LHasPhysReg = left->hasPhysRegDefs; 25480b57cec5SDimitry Andric bool RHasPhysReg = right->hasPhysRegDefs; 25490b57cec5SDimitry Andric if (LHasPhysReg != RHasPhysReg) { 25500b57cec5SDimitry Andric #ifndef NDEBUG 25510b57cec5SDimitry Andric static const char *const PhysRegMsg[] = { " has no physreg", 25520b57cec5SDimitry Andric " defines a physreg" }; 25530b57cec5SDimitry Andric #endif 25540b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " SU (" << left->NodeNum << ") " 25550b57cec5SDimitry Andric << PhysRegMsg[LHasPhysReg] << " SU(" << right->NodeNum 25560b57cec5SDimitry Andric << ") " << PhysRegMsg[RHasPhysReg] << "\n"); 25570b57cec5SDimitry Andric return LHasPhysReg < RHasPhysReg; 25580b57cec5SDimitry Andric } 25590b57cec5SDimitry Andric } 25600b57cec5SDimitry Andric 25610b57cec5SDimitry Andric // Prioritize by Sethi-Ulmann number and push CopyToReg nodes down. 25620b57cec5SDimitry Andric unsigned LPriority = SPQ->getNodePriority(left); 25630b57cec5SDimitry Andric unsigned RPriority = SPQ->getNodePriority(right); 25640b57cec5SDimitry Andric 25650b57cec5SDimitry Andric // Be really careful about hoisting call operands above previous calls. 25660b57cec5SDimitry Andric // Only allows it if it would reduce register pressure. 25670b57cec5SDimitry Andric if (left->isCall && right->isCallOp) { 25680b57cec5SDimitry Andric unsigned RNumVals = right->getNode()->getNumValues(); 25690b57cec5SDimitry Andric RPriority = (RPriority > RNumVals) ? (RPriority - RNumVals) : 0; 25700b57cec5SDimitry Andric } 25710b57cec5SDimitry Andric if (right->isCall && left->isCallOp) { 25720b57cec5SDimitry Andric unsigned LNumVals = left->getNode()->getNumValues(); 25730b57cec5SDimitry Andric LPriority = (LPriority > LNumVals) ? (LPriority - LNumVals) : 0; 25740b57cec5SDimitry Andric } 25750b57cec5SDimitry Andric 25760b57cec5SDimitry Andric if (LPriority != RPriority) 25770b57cec5SDimitry Andric return LPriority > RPriority; 25780b57cec5SDimitry Andric 25790b57cec5SDimitry Andric // One or both of the nodes are calls and their sethi-ullman numbers are the 25800b57cec5SDimitry Andric // same, then keep source order. 25810b57cec5SDimitry Andric if (left->isCall || right->isCall) { 25820b57cec5SDimitry Andric unsigned LOrder = SPQ->getNodeOrdering(left); 25830b57cec5SDimitry Andric unsigned ROrder = SPQ->getNodeOrdering(right); 25840b57cec5SDimitry Andric 25850b57cec5SDimitry Andric // Prefer an ordering where the lower the non-zero order number, the higher 25860b57cec5SDimitry Andric // the preference. 25870b57cec5SDimitry Andric if ((LOrder || ROrder) && LOrder != ROrder) 25880b57cec5SDimitry Andric return LOrder != 0 && (LOrder < ROrder || ROrder == 0); 25890b57cec5SDimitry Andric } 25900b57cec5SDimitry Andric 25910b57cec5SDimitry Andric // Try schedule def + use closer when Sethi-Ullman numbers are the same. 25920b57cec5SDimitry Andric // e.g. 25930b57cec5SDimitry Andric // t1 = op t2, c1 25940b57cec5SDimitry Andric // t3 = op t4, c2 25950b57cec5SDimitry Andric // 25960b57cec5SDimitry Andric // and the following instructions are both ready. 25970b57cec5SDimitry Andric // t2 = op c3 25980b57cec5SDimitry Andric // t4 = op c4 25990b57cec5SDimitry Andric // 26000b57cec5SDimitry Andric // Then schedule t2 = op first. 26010b57cec5SDimitry Andric // i.e. 26020b57cec5SDimitry Andric // t4 = op c4 26030b57cec5SDimitry Andric // t2 = op c3 26040b57cec5SDimitry Andric // t1 = op t2, c1 26050b57cec5SDimitry Andric // t3 = op t4, c2 26060b57cec5SDimitry Andric // 26070b57cec5SDimitry Andric // This creates more short live intervals. 26080b57cec5SDimitry Andric unsigned LDist = closestSucc(left); 26090b57cec5SDimitry Andric unsigned RDist = closestSucc(right); 26100b57cec5SDimitry Andric if (LDist != RDist) 26110b57cec5SDimitry Andric return LDist < RDist; 26120b57cec5SDimitry Andric 26130b57cec5SDimitry Andric // How many registers becomes live when the node is scheduled. 26140b57cec5SDimitry Andric unsigned LScratch = calcMaxScratches(left); 26150b57cec5SDimitry Andric unsigned RScratch = calcMaxScratches(right); 26160b57cec5SDimitry Andric if (LScratch != RScratch) 26170b57cec5SDimitry Andric return LScratch > RScratch; 26180b57cec5SDimitry Andric 26190b57cec5SDimitry Andric // Comparing latency against a call makes little sense unless the node 26200b57cec5SDimitry Andric // is register pressure-neutral. 26210b57cec5SDimitry Andric if ((left->isCall && RPriority > 0) || (right->isCall && LPriority > 0)) 26220b57cec5SDimitry Andric return (left->NodeQueueId > right->NodeQueueId); 26230b57cec5SDimitry Andric 26240b57cec5SDimitry Andric // Do not compare latencies when one or both of the nodes are calls. 26250b57cec5SDimitry Andric if (!DisableSchedCycles && 26260b57cec5SDimitry Andric !(left->isCall || right->isCall)) { 26270b57cec5SDimitry Andric int result = BUCompareLatency(left, right, false /*checkPref*/, SPQ); 26280b57cec5SDimitry Andric if (result != 0) 26290b57cec5SDimitry Andric return result > 0; 26300b57cec5SDimitry Andric } 26310b57cec5SDimitry Andric else { 26320b57cec5SDimitry Andric if (left->getHeight() != right->getHeight()) 26330b57cec5SDimitry Andric return left->getHeight() > right->getHeight(); 26340b57cec5SDimitry Andric 26350b57cec5SDimitry Andric if (left->getDepth() != right->getDepth()) 26360b57cec5SDimitry Andric return left->getDepth() < right->getDepth(); 26370b57cec5SDimitry Andric } 26380b57cec5SDimitry Andric 26390b57cec5SDimitry Andric assert(left->NodeQueueId && right->NodeQueueId && 26400b57cec5SDimitry Andric "NodeQueueId cannot be zero"); 26410b57cec5SDimitry Andric return (left->NodeQueueId > right->NodeQueueId); 26420b57cec5SDimitry Andric } 26430b57cec5SDimitry Andric 26440b57cec5SDimitry Andric // Bottom up 26450b57cec5SDimitry Andric bool bu_ls_rr_sort::operator()(SUnit *left, SUnit *right) const { 26460b57cec5SDimitry Andric if (int res = checkSpecialNodes(left, right)) 26470b57cec5SDimitry Andric return res > 0; 26480b57cec5SDimitry Andric 26490b57cec5SDimitry Andric return BURRSort(left, right, SPQ); 26500b57cec5SDimitry Andric } 26510b57cec5SDimitry Andric 26520b57cec5SDimitry Andric // Source order, otherwise bottom up. 26530b57cec5SDimitry Andric bool src_ls_rr_sort::operator()(SUnit *left, SUnit *right) const { 26540b57cec5SDimitry Andric if (int res = checkSpecialNodes(left, right)) 26550b57cec5SDimitry Andric return res > 0; 26560b57cec5SDimitry Andric 26570b57cec5SDimitry Andric unsigned LOrder = SPQ->getNodeOrdering(left); 26580b57cec5SDimitry Andric unsigned ROrder = SPQ->getNodeOrdering(right); 26590b57cec5SDimitry Andric 26600b57cec5SDimitry Andric // Prefer an ordering where the lower the non-zero order number, the higher 26610b57cec5SDimitry Andric // the preference. 26620b57cec5SDimitry Andric if ((LOrder || ROrder) && LOrder != ROrder) 26630b57cec5SDimitry Andric return LOrder != 0 && (LOrder < ROrder || ROrder == 0); 26640b57cec5SDimitry Andric 26650b57cec5SDimitry Andric return BURRSort(left, right, SPQ); 26660b57cec5SDimitry Andric } 26670b57cec5SDimitry Andric 26680b57cec5SDimitry Andric // If the time between now and when the instruction will be ready can cover 26690b57cec5SDimitry Andric // the spill code, then avoid adding it to the ready queue. This gives long 26700b57cec5SDimitry Andric // stalls highest priority and allows hoisting across calls. It should also 26710b57cec5SDimitry Andric // speed up processing the available queue. 26720b57cec5SDimitry Andric bool hybrid_ls_rr_sort::isReady(SUnit *SU, unsigned CurCycle) const { 26730b57cec5SDimitry Andric static const unsigned ReadyDelay = 3; 26740b57cec5SDimitry Andric 26750b57cec5SDimitry Andric if (SPQ->MayReduceRegPressure(SU)) return true; 26760b57cec5SDimitry Andric 26770b57cec5SDimitry Andric if (SU->getHeight() > (CurCycle + ReadyDelay)) return false; 26780b57cec5SDimitry Andric 26790b57cec5SDimitry Andric if (SPQ->getHazardRec()->getHazardType(SU, -ReadyDelay) 26800b57cec5SDimitry Andric != ScheduleHazardRecognizer::NoHazard) 26810b57cec5SDimitry Andric return false; 26820b57cec5SDimitry Andric 26830b57cec5SDimitry Andric return true; 26840b57cec5SDimitry Andric } 26850b57cec5SDimitry Andric 26860b57cec5SDimitry Andric // Return true if right should be scheduled with higher priority than left. 26870b57cec5SDimitry Andric bool hybrid_ls_rr_sort::operator()(SUnit *left, SUnit *right) const { 26880b57cec5SDimitry Andric if (int res = checkSpecialNodes(left, right)) 26890b57cec5SDimitry Andric return res > 0; 26900b57cec5SDimitry Andric 26910b57cec5SDimitry Andric if (left->isCall || right->isCall) 26920b57cec5SDimitry Andric // No way to compute latency of calls. 26930b57cec5SDimitry Andric return BURRSort(left, right, SPQ); 26940b57cec5SDimitry Andric 26950b57cec5SDimitry Andric bool LHigh = SPQ->HighRegPressure(left); 26960b57cec5SDimitry Andric bool RHigh = SPQ->HighRegPressure(right); 26970b57cec5SDimitry Andric // Avoid causing spills. If register pressure is high, schedule for 26980b57cec5SDimitry Andric // register pressure reduction. 26990b57cec5SDimitry Andric if (LHigh && !RHigh) { 27000b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " pressure SU(" << left->NodeNum << ") > SU(" 27010b57cec5SDimitry Andric << right->NodeNum << ")\n"); 27020b57cec5SDimitry Andric return true; 27030b57cec5SDimitry Andric } 27040b57cec5SDimitry Andric else if (!LHigh && RHigh) { 27050b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " pressure SU(" << right->NodeNum << ") > SU(" 27060b57cec5SDimitry Andric << left->NodeNum << ")\n"); 27070b57cec5SDimitry Andric return false; 27080b57cec5SDimitry Andric } 27090b57cec5SDimitry Andric if (!LHigh && !RHigh) { 27100b57cec5SDimitry Andric int result = BUCompareLatency(left, right, true /*checkPref*/, SPQ); 27110b57cec5SDimitry Andric if (result != 0) 27120b57cec5SDimitry Andric return result > 0; 27130b57cec5SDimitry Andric } 27140b57cec5SDimitry Andric return BURRSort(left, right, SPQ); 27150b57cec5SDimitry Andric } 27160b57cec5SDimitry Andric 27170b57cec5SDimitry Andric // Schedule as many instructions in each cycle as possible. So don't make an 27180b57cec5SDimitry Andric // instruction available unless it is ready in the current cycle. 27190b57cec5SDimitry Andric bool ilp_ls_rr_sort::isReady(SUnit *SU, unsigned CurCycle) const { 27200b57cec5SDimitry Andric if (SU->getHeight() > CurCycle) return false; 27210b57cec5SDimitry Andric 27220b57cec5SDimitry Andric if (SPQ->getHazardRec()->getHazardType(SU, 0) 27230b57cec5SDimitry Andric != ScheduleHazardRecognizer::NoHazard) 27240b57cec5SDimitry Andric return false; 27250b57cec5SDimitry Andric 27260b57cec5SDimitry Andric return true; 27270b57cec5SDimitry Andric } 27280b57cec5SDimitry Andric 27290b57cec5SDimitry Andric static bool canEnableCoalescing(SUnit *SU) { 27300b57cec5SDimitry Andric unsigned Opc = SU->getNode() ? SU->getNode()->getOpcode() : 0; 27310b57cec5SDimitry Andric if (Opc == ISD::TokenFactor || Opc == ISD::CopyToReg) 27320b57cec5SDimitry Andric // CopyToReg should be close to its uses to facilitate coalescing and 27330b57cec5SDimitry Andric // avoid spilling. 27340b57cec5SDimitry Andric return true; 27350b57cec5SDimitry Andric 27360b57cec5SDimitry Andric if (Opc == TargetOpcode::EXTRACT_SUBREG || 27370b57cec5SDimitry Andric Opc == TargetOpcode::SUBREG_TO_REG || 27380b57cec5SDimitry Andric Opc == TargetOpcode::INSERT_SUBREG) 27390b57cec5SDimitry Andric // EXTRACT_SUBREG, INSERT_SUBREG, and SUBREG_TO_REG nodes should be 27400b57cec5SDimitry Andric // close to their uses to facilitate coalescing. 27410b57cec5SDimitry Andric return true; 27420b57cec5SDimitry Andric 27430b57cec5SDimitry Andric if (SU->NumPreds == 0 && SU->NumSuccs != 0) 27440b57cec5SDimitry Andric // If SU does not have a register def, schedule it close to its uses 27450b57cec5SDimitry Andric // because it does not lengthen any live ranges. 27460b57cec5SDimitry Andric return true; 27470b57cec5SDimitry Andric 27480b57cec5SDimitry Andric return false; 27490b57cec5SDimitry Andric } 27500b57cec5SDimitry Andric 27510b57cec5SDimitry Andric // list-ilp is currently an experimental scheduler that allows various 27520b57cec5SDimitry Andric // heuristics to be enabled prior to the normal register reduction logic. 27530b57cec5SDimitry Andric bool ilp_ls_rr_sort::operator()(SUnit *left, SUnit *right) const { 27540b57cec5SDimitry Andric if (int res = checkSpecialNodes(left, right)) 27550b57cec5SDimitry Andric return res > 0; 27560b57cec5SDimitry Andric 27570b57cec5SDimitry Andric if (left->isCall || right->isCall) 27580b57cec5SDimitry Andric // No way to compute latency of calls. 27590b57cec5SDimitry Andric return BURRSort(left, right, SPQ); 27600b57cec5SDimitry Andric 27610b57cec5SDimitry Andric unsigned LLiveUses = 0, RLiveUses = 0; 27620b57cec5SDimitry Andric int LPDiff = 0, RPDiff = 0; 27630b57cec5SDimitry Andric if (!DisableSchedRegPressure || !DisableSchedLiveUses) { 27640b57cec5SDimitry Andric LPDiff = SPQ->RegPressureDiff(left, LLiveUses); 27650b57cec5SDimitry Andric RPDiff = SPQ->RegPressureDiff(right, RLiveUses); 27660b57cec5SDimitry Andric } 27670b57cec5SDimitry Andric if (!DisableSchedRegPressure && LPDiff != RPDiff) { 27680b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "RegPressureDiff SU(" << left->NodeNum 27690b57cec5SDimitry Andric << "): " << LPDiff << " != SU(" << right->NodeNum 27700b57cec5SDimitry Andric << "): " << RPDiff << "\n"); 27710b57cec5SDimitry Andric return LPDiff > RPDiff; 27720b57cec5SDimitry Andric } 27730b57cec5SDimitry Andric 27740b57cec5SDimitry Andric if (!DisableSchedRegPressure && (LPDiff > 0 || RPDiff > 0)) { 27750b57cec5SDimitry Andric bool LReduce = canEnableCoalescing(left); 27760b57cec5SDimitry Andric bool RReduce = canEnableCoalescing(right); 27770b57cec5SDimitry Andric if (LReduce && !RReduce) return false; 27780b57cec5SDimitry Andric if (RReduce && !LReduce) return true; 27790b57cec5SDimitry Andric } 27800b57cec5SDimitry Andric 27810b57cec5SDimitry Andric if (!DisableSchedLiveUses && (LLiveUses != RLiveUses)) { 27820b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Live uses SU(" << left->NodeNum << "): " << LLiveUses 27830b57cec5SDimitry Andric << " != SU(" << right->NodeNum << "): " << RLiveUses 27840b57cec5SDimitry Andric << "\n"); 27850b57cec5SDimitry Andric return LLiveUses < RLiveUses; 27860b57cec5SDimitry Andric } 27870b57cec5SDimitry Andric 27880b57cec5SDimitry Andric if (!DisableSchedStalls) { 27890b57cec5SDimitry Andric bool LStall = BUHasStall(left, left->getHeight(), SPQ); 27900b57cec5SDimitry Andric bool RStall = BUHasStall(right, right->getHeight(), SPQ); 27910b57cec5SDimitry Andric if (LStall != RStall) 27920b57cec5SDimitry Andric return left->getHeight() > right->getHeight(); 27930b57cec5SDimitry Andric } 27940b57cec5SDimitry Andric 27950b57cec5SDimitry Andric if (!DisableSchedCriticalPath) { 27960b57cec5SDimitry Andric int spread = (int)left->getDepth() - (int)right->getDepth(); 27970b57cec5SDimitry Andric if (std::abs(spread) > MaxReorderWindow) { 27980b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Depth of SU(" << left->NodeNum << "): " 27990b57cec5SDimitry Andric << left->getDepth() << " != SU(" << right->NodeNum 28000b57cec5SDimitry Andric << "): " << right->getDepth() << "\n"); 28010b57cec5SDimitry Andric return left->getDepth() < right->getDepth(); 28020b57cec5SDimitry Andric } 28030b57cec5SDimitry Andric } 28040b57cec5SDimitry Andric 28050b57cec5SDimitry Andric if (!DisableSchedHeight && left->getHeight() != right->getHeight()) { 28060b57cec5SDimitry Andric int spread = (int)left->getHeight() - (int)right->getHeight(); 28070b57cec5SDimitry Andric if (std::abs(spread) > MaxReorderWindow) 28080b57cec5SDimitry Andric return left->getHeight() > right->getHeight(); 28090b57cec5SDimitry Andric } 28100b57cec5SDimitry Andric 28110b57cec5SDimitry Andric return BURRSort(left, right, SPQ); 28120b57cec5SDimitry Andric } 28130b57cec5SDimitry Andric 28140b57cec5SDimitry Andric void RegReductionPQBase::initNodes(std::vector<SUnit> &sunits) { 28150b57cec5SDimitry Andric SUnits = &sunits; 28160b57cec5SDimitry Andric // Add pseudo dependency edges for two-address nodes. 28170b57cec5SDimitry Andric if (!Disable2AddrHack) 28180b57cec5SDimitry Andric AddPseudoTwoAddrDeps(); 28190b57cec5SDimitry Andric // Reroute edges to nodes with multiple uses. 28200b57cec5SDimitry Andric if (!TracksRegPressure && !SrcOrder) 28210b57cec5SDimitry Andric PrescheduleNodesWithMultipleUses(); 28220b57cec5SDimitry Andric // Calculate node priorities. 28230b57cec5SDimitry Andric CalculateSethiUllmanNumbers(); 28240b57cec5SDimitry Andric 28250b57cec5SDimitry Andric // For single block loops, mark nodes that look like canonical IV increments. 28260b57cec5SDimitry Andric if (scheduleDAG->BB->isSuccessor(scheduleDAG->BB)) 28270b57cec5SDimitry Andric for (SUnit &SU : sunits) 28280b57cec5SDimitry Andric initVRegCycle(&SU); 28290b57cec5SDimitry Andric } 28300b57cec5SDimitry Andric 28310b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 28320b57cec5SDimitry Andric // Preschedule for Register Pressure 28330b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 28340b57cec5SDimitry Andric 28350b57cec5SDimitry Andric bool RegReductionPQBase::canClobber(const SUnit *SU, const SUnit *Op) { 28360b57cec5SDimitry Andric if (SU->isTwoAddress) { 28370b57cec5SDimitry Andric unsigned Opc = SU->getNode()->getMachineOpcode(); 28380b57cec5SDimitry Andric const MCInstrDesc &MCID = TII->get(Opc); 28390b57cec5SDimitry Andric unsigned NumRes = MCID.getNumDefs(); 28400b57cec5SDimitry Andric unsigned NumOps = MCID.getNumOperands() - NumRes; 28410b57cec5SDimitry Andric for (unsigned i = 0; i != NumOps; ++i) { 28420b57cec5SDimitry Andric if (MCID.getOperandConstraint(i+NumRes, MCOI::TIED_TO) != -1) { 28430b57cec5SDimitry Andric SDNode *DU = SU->getNode()->getOperand(i).getNode(); 28440b57cec5SDimitry Andric if (DU->getNodeId() != -1 && 28450b57cec5SDimitry Andric Op->OrigNode == &(*SUnits)[DU->getNodeId()]) 28460b57cec5SDimitry Andric return true; 28470b57cec5SDimitry Andric } 28480b57cec5SDimitry Andric } 28490b57cec5SDimitry Andric } 28500b57cec5SDimitry Andric return false; 28510b57cec5SDimitry Andric } 28520b57cec5SDimitry Andric 28530b57cec5SDimitry Andric /// canClobberReachingPhysRegUse - True if SU would clobber one of it's 28540b57cec5SDimitry Andric /// successor's explicit physregs whose definition can reach DepSU. 28550b57cec5SDimitry Andric /// i.e. DepSU should not be scheduled above SU. 28560b57cec5SDimitry Andric static bool canClobberReachingPhysRegUse(const SUnit *DepSU, const SUnit *SU, 28570b57cec5SDimitry Andric ScheduleDAGRRList *scheduleDAG, 28580b57cec5SDimitry Andric const TargetInstrInfo *TII, 28590b57cec5SDimitry Andric const TargetRegisterInfo *TRI) { 2860bdd1243dSDimitry Andric ArrayRef<MCPhysReg> ImpDefs = 2861bdd1243dSDimitry Andric TII->get(SU->getNode()->getMachineOpcode()).implicit_defs(); 28620b57cec5SDimitry Andric const uint32_t *RegMask = getNodeRegMask(SU->getNode()); 2863bdd1243dSDimitry Andric if (ImpDefs.empty() && !RegMask) 28640b57cec5SDimitry Andric return false; 28650b57cec5SDimitry Andric 28660b57cec5SDimitry Andric for (const SDep &Succ : SU->Succs) { 28670b57cec5SDimitry Andric SUnit *SuccSU = Succ.getSUnit(); 28680b57cec5SDimitry Andric for (const SDep &SuccPred : SuccSU->Preds) { 28690b57cec5SDimitry Andric if (!SuccPred.isAssignedRegDep()) 28700b57cec5SDimitry Andric continue; 28710b57cec5SDimitry Andric 28720b57cec5SDimitry Andric if (RegMask && 28730b57cec5SDimitry Andric MachineOperand::clobbersPhysReg(RegMask, SuccPred.getReg()) && 28740b57cec5SDimitry Andric scheduleDAG->IsReachable(DepSU, SuccPred.getSUnit())) 28750b57cec5SDimitry Andric return true; 28760b57cec5SDimitry Andric 2877bdd1243dSDimitry Andric for (MCPhysReg ImpDef : ImpDefs) { 28780b57cec5SDimitry Andric // Return true if SU clobbers this physical register use and the 28790b57cec5SDimitry Andric // definition of the register reaches from DepSU. IsReachable queries 28800b57cec5SDimitry Andric // a topological forward sort of the DAG (following the successors). 2881bdd1243dSDimitry Andric if (TRI->regsOverlap(ImpDef, SuccPred.getReg()) && 28820b57cec5SDimitry Andric scheduleDAG->IsReachable(DepSU, SuccPred.getSUnit())) 28830b57cec5SDimitry Andric return true; 28840b57cec5SDimitry Andric } 28850b57cec5SDimitry Andric } 2886bdd1243dSDimitry Andric } 28870b57cec5SDimitry Andric return false; 28880b57cec5SDimitry Andric } 28890b57cec5SDimitry Andric 28900b57cec5SDimitry Andric /// canClobberPhysRegDefs - True if SU would clobber one of SuccSU's 28910b57cec5SDimitry Andric /// physical register defs. 28920b57cec5SDimitry Andric static bool canClobberPhysRegDefs(const SUnit *SuccSU, const SUnit *SU, 28930b57cec5SDimitry Andric const TargetInstrInfo *TII, 28940b57cec5SDimitry Andric const TargetRegisterInfo *TRI) { 28950b57cec5SDimitry Andric SDNode *N = SuccSU->getNode(); 28960b57cec5SDimitry Andric unsigned NumDefs = TII->get(N->getMachineOpcode()).getNumDefs(); 2897bdd1243dSDimitry Andric ArrayRef<MCPhysReg> ImpDefs = TII->get(N->getMachineOpcode()).implicit_defs(); 2898bdd1243dSDimitry Andric assert(!ImpDefs.empty() && "Caller should check hasPhysRegDefs"); 28990b57cec5SDimitry Andric for (const SDNode *SUNode = SU->getNode(); SUNode; 29000b57cec5SDimitry Andric SUNode = SUNode->getGluedNode()) { 29010b57cec5SDimitry Andric if (!SUNode->isMachineOpcode()) 29020b57cec5SDimitry Andric continue; 2903bdd1243dSDimitry Andric ArrayRef<MCPhysReg> SUImpDefs = 2904bdd1243dSDimitry Andric TII->get(SUNode->getMachineOpcode()).implicit_defs(); 29050b57cec5SDimitry Andric const uint32_t *SURegMask = getNodeRegMask(SUNode); 2906bdd1243dSDimitry Andric if (SUImpDefs.empty() && !SURegMask) 29070b57cec5SDimitry Andric continue; 29080b57cec5SDimitry Andric for (unsigned i = NumDefs, e = N->getNumValues(); i != e; ++i) { 29090b57cec5SDimitry Andric MVT VT = N->getSimpleValueType(i); 29100b57cec5SDimitry Andric if (VT == MVT::Glue || VT == MVT::Other) 29110b57cec5SDimitry Andric continue; 29120b57cec5SDimitry Andric if (!N->hasAnyUseOfValue(i)) 29130b57cec5SDimitry Andric continue; 2914bdd1243dSDimitry Andric MCPhysReg Reg = ImpDefs[i - NumDefs]; 29150b57cec5SDimitry Andric if (SURegMask && MachineOperand::clobbersPhysReg(SURegMask, Reg)) 29160b57cec5SDimitry Andric return true; 2917bdd1243dSDimitry Andric for (MCPhysReg SUReg : SUImpDefs) { 29180b57cec5SDimitry Andric if (TRI->regsOverlap(Reg, SUReg)) 29190b57cec5SDimitry Andric return true; 29200b57cec5SDimitry Andric } 29210b57cec5SDimitry Andric } 29220b57cec5SDimitry Andric } 29230b57cec5SDimitry Andric return false; 29240b57cec5SDimitry Andric } 29250b57cec5SDimitry Andric 29260b57cec5SDimitry Andric /// PrescheduleNodesWithMultipleUses - Nodes with multiple uses 29270b57cec5SDimitry Andric /// are not handled well by the general register pressure reduction 29280b57cec5SDimitry Andric /// heuristics. When presented with code like this: 29290b57cec5SDimitry Andric /// 29300b57cec5SDimitry Andric /// N 29310b57cec5SDimitry Andric /// / | 29320b57cec5SDimitry Andric /// / | 29330b57cec5SDimitry Andric /// U store 29340b57cec5SDimitry Andric /// | 29350b57cec5SDimitry Andric /// ... 29360b57cec5SDimitry Andric /// 29370b57cec5SDimitry Andric /// the heuristics tend to push the store up, but since the 29380b57cec5SDimitry Andric /// operand of the store has another use (U), this would increase 29390b57cec5SDimitry Andric /// the length of that other use (the U->N edge). 29400b57cec5SDimitry Andric /// 29410b57cec5SDimitry Andric /// This function transforms code like the above to route U's 29420b57cec5SDimitry Andric /// dependence through the store when possible, like this: 29430b57cec5SDimitry Andric /// 29440b57cec5SDimitry Andric /// N 29450b57cec5SDimitry Andric /// || 29460b57cec5SDimitry Andric /// || 29470b57cec5SDimitry Andric /// store 29480b57cec5SDimitry Andric /// | 29490b57cec5SDimitry Andric /// U 29500b57cec5SDimitry Andric /// | 29510b57cec5SDimitry Andric /// ... 29520b57cec5SDimitry Andric /// 29530b57cec5SDimitry Andric /// This results in the store being scheduled immediately 29540b57cec5SDimitry Andric /// after N, which shortens the U->N live range, reducing 29550b57cec5SDimitry Andric /// register pressure. 29560b57cec5SDimitry Andric void RegReductionPQBase::PrescheduleNodesWithMultipleUses() { 29570b57cec5SDimitry Andric // Visit all the nodes in topological order, working top-down. 29580b57cec5SDimitry Andric for (SUnit &SU : *SUnits) { 29590b57cec5SDimitry Andric // For now, only look at nodes with no data successors, such as stores. 29600b57cec5SDimitry Andric // These are especially important, due to the heuristics in 29610b57cec5SDimitry Andric // getNodePriority for nodes with no data successors. 29620b57cec5SDimitry Andric if (SU.NumSuccs != 0) 29630b57cec5SDimitry Andric continue; 29640b57cec5SDimitry Andric // For now, only look at nodes with exactly one data predecessor. 29650b57cec5SDimitry Andric if (SU.NumPreds != 1) 29660b57cec5SDimitry Andric continue; 29670b57cec5SDimitry Andric // Avoid prescheduling copies to virtual registers, which don't behave 29680b57cec5SDimitry Andric // like other nodes from the perspective of scheduling heuristics. 29690b57cec5SDimitry Andric if (SDNode *N = SU.getNode()) 29700b57cec5SDimitry Andric if (N->getOpcode() == ISD::CopyToReg && 2971bdd1243dSDimitry Andric cast<RegisterSDNode>(N->getOperand(1))->getReg().isVirtual()) 29720b57cec5SDimitry Andric continue; 29730b57cec5SDimitry Andric 29740b57cec5SDimitry Andric SDNode *PredFrameSetup = nullptr; 29750b57cec5SDimitry Andric for (const SDep &Pred : SU.Preds) 29760b57cec5SDimitry Andric if (Pred.isCtrl() && Pred.getSUnit()) { 29770b57cec5SDimitry Andric // Find the predecessor which is not data dependence. 29780b57cec5SDimitry Andric SDNode *PredND = Pred.getSUnit()->getNode(); 29790b57cec5SDimitry Andric 29800b57cec5SDimitry Andric // If PredND is FrameSetup, we should not pre-scheduled the node, 29810b57cec5SDimitry Andric // or else, when bottom up scheduling, ADJCALLSTACKDOWN and 29820b57cec5SDimitry Andric // ADJCALLSTACKUP may hold CallResource too long and make other 29830b57cec5SDimitry Andric // calls can't be scheduled. If there's no other available node 29840b57cec5SDimitry Andric // to schedule, the schedular will try to rename the register by 29850b57cec5SDimitry Andric // creating copy to avoid the conflict which will fail because 29860b57cec5SDimitry Andric // CallResource is not a real physical register. 29870b57cec5SDimitry Andric if (PredND && PredND->isMachineOpcode() && 29880b57cec5SDimitry Andric (PredND->getMachineOpcode() == TII->getCallFrameSetupOpcode())) { 29890b57cec5SDimitry Andric PredFrameSetup = PredND; 29900b57cec5SDimitry Andric break; 29910b57cec5SDimitry Andric } 29920b57cec5SDimitry Andric } 29930b57cec5SDimitry Andric // Skip the node has FrameSetup parent. 29940b57cec5SDimitry Andric if (PredFrameSetup != nullptr) 29950b57cec5SDimitry Andric continue; 29960b57cec5SDimitry Andric 29970b57cec5SDimitry Andric // Locate the single data predecessor. 29980b57cec5SDimitry Andric SUnit *PredSU = nullptr; 29990b57cec5SDimitry Andric for (const SDep &Pred : SU.Preds) 30000b57cec5SDimitry Andric if (!Pred.isCtrl()) { 30010b57cec5SDimitry Andric PredSU = Pred.getSUnit(); 30020b57cec5SDimitry Andric break; 30030b57cec5SDimitry Andric } 30040b57cec5SDimitry Andric assert(PredSU); 30050b57cec5SDimitry Andric 30060b57cec5SDimitry Andric // Don't rewrite edges that carry physregs, because that requires additional 30070b57cec5SDimitry Andric // support infrastructure. 30080b57cec5SDimitry Andric if (PredSU->hasPhysRegDefs) 30090b57cec5SDimitry Andric continue; 30100b57cec5SDimitry Andric // Short-circuit the case where SU is PredSU's only data successor. 30110b57cec5SDimitry Andric if (PredSU->NumSuccs == 1) 30120b57cec5SDimitry Andric continue; 30130b57cec5SDimitry Andric // Avoid prescheduling to copies from virtual registers, which don't behave 30140b57cec5SDimitry Andric // like other nodes from the perspective of scheduling heuristics. 30150b57cec5SDimitry Andric if (SDNode *N = SU.getNode()) 30160b57cec5SDimitry Andric if (N->getOpcode() == ISD::CopyFromReg && 3017bdd1243dSDimitry Andric cast<RegisterSDNode>(N->getOperand(1))->getReg().isVirtual()) 30180b57cec5SDimitry Andric continue; 30190b57cec5SDimitry Andric 30200b57cec5SDimitry Andric // Perform checks on the successors of PredSU. 30210b57cec5SDimitry Andric for (const SDep &PredSucc : PredSU->Succs) { 30220b57cec5SDimitry Andric SUnit *PredSuccSU = PredSucc.getSUnit(); 30230b57cec5SDimitry Andric if (PredSuccSU == &SU) continue; 30240b57cec5SDimitry Andric // If PredSU has another successor with no data successors, for 30250b57cec5SDimitry Andric // now don't attempt to choose either over the other. 30260b57cec5SDimitry Andric if (PredSuccSU->NumSuccs == 0) 30270b57cec5SDimitry Andric goto outer_loop_continue; 30280b57cec5SDimitry Andric // Don't break physical register dependencies. 30290b57cec5SDimitry Andric if (SU.hasPhysRegClobbers && PredSuccSU->hasPhysRegDefs) 30300b57cec5SDimitry Andric if (canClobberPhysRegDefs(PredSuccSU, &SU, TII, TRI)) 30310b57cec5SDimitry Andric goto outer_loop_continue; 30320b57cec5SDimitry Andric // Don't introduce graph cycles. 30330b57cec5SDimitry Andric if (scheduleDAG->IsReachable(&SU, PredSuccSU)) 30340b57cec5SDimitry Andric goto outer_loop_continue; 30350b57cec5SDimitry Andric } 30360b57cec5SDimitry Andric 30370b57cec5SDimitry Andric // Ok, the transformation is safe and the heuristics suggest it is 30380b57cec5SDimitry Andric // profitable. Update the graph. 30390b57cec5SDimitry Andric LLVM_DEBUG( 30400b57cec5SDimitry Andric dbgs() << " Prescheduling SU #" << SU.NodeNum << " next to PredSU #" 30410b57cec5SDimitry Andric << PredSU->NodeNum 30420b57cec5SDimitry Andric << " to guide scheduling in the presence of multiple uses\n"); 30430b57cec5SDimitry Andric for (unsigned i = 0; i != PredSU->Succs.size(); ++i) { 30440b57cec5SDimitry Andric SDep Edge = PredSU->Succs[i]; 30450b57cec5SDimitry Andric assert(!Edge.isAssignedRegDep()); 30460b57cec5SDimitry Andric SUnit *SuccSU = Edge.getSUnit(); 30470b57cec5SDimitry Andric if (SuccSU != &SU) { 30480b57cec5SDimitry Andric Edge.setSUnit(PredSU); 30490b57cec5SDimitry Andric scheduleDAG->RemovePred(SuccSU, Edge); 30500b57cec5SDimitry Andric scheduleDAG->AddPredQueued(&SU, Edge); 30510b57cec5SDimitry Andric Edge.setSUnit(&SU); 30520b57cec5SDimitry Andric scheduleDAG->AddPredQueued(SuccSU, Edge); 30530b57cec5SDimitry Andric --i; 30540b57cec5SDimitry Andric } 30550b57cec5SDimitry Andric } 30560b57cec5SDimitry Andric outer_loop_continue:; 30570b57cec5SDimitry Andric } 30580b57cec5SDimitry Andric } 30590b57cec5SDimitry Andric 30600b57cec5SDimitry Andric /// AddPseudoTwoAddrDeps - If two nodes share an operand and one of them uses 30610b57cec5SDimitry Andric /// it as a def&use operand. Add a pseudo control edge from it to the other 30620b57cec5SDimitry Andric /// node (if it won't create a cycle) so the two-address one will be scheduled 30630b57cec5SDimitry Andric /// first (lower in the schedule). If both nodes are two-address, favor the 30640b57cec5SDimitry Andric /// one that has a CopyToReg use (more likely to be a loop induction update). 30650b57cec5SDimitry Andric /// If both are two-address, but one is commutable while the other is not 30660b57cec5SDimitry Andric /// commutable, favor the one that's not commutable. 30670b57cec5SDimitry Andric void RegReductionPQBase::AddPseudoTwoAddrDeps() { 30680b57cec5SDimitry Andric for (SUnit &SU : *SUnits) { 30690b57cec5SDimitry Andric if (!SU.isTwoAddress) 30700b57cec5SDimitry Andric continue; 30710b57cec5SDimitry Andric 30720b57cec5SDimitry Andric SDNode *Node = SU.getNode(); 30730b57cec5SDimitry Andric if (!Node || !Node->isMachineOpcode() || SU.getNode()->getGluedNode()) 30740b57cec5SDimitry Andric continue; 30750b57cec5SDimitry Andric 30760b57cec5SDimitry Andric bool isLiveOut = hasOnlyLiveOutUses(&SU); 30770b57cec5SDimitry Andric unsigned Opc = Node->getMachineOpcode(); 30780b57cec5SDimitry Andric const MCInstrDesc &MCID = TII->get(Opc); 30790b57cec5SDimitry Andric unsigned NumRes = MCID.getNumDefs(); 30800b57cec5SDimitry Andric unsigned NumOps = MCID.getNumOperands() - NumRes; 30810b57cec5SDimitry Andric for (unsigned j = 0; j != NumOps; ++j) { 30820b57cec5SDimitry Andric if (MCID.getOperandConstraint(j+NumRes, MCOI::TIED_TO) == -1) 30830b57cec5SDimitry Andric continue; 30840b57cec5SDimitry Andric SDNode *DU = SU.getNode()->getOperand(j).getNode(); 30850b57cec5SDimitry Andric if (DU->getNodeId() == -1) 30860b57cec5SDimitry Andric continue; 30870b57cec5SDimitry Andric const SUnit *DUSU = &(*SUnits)[DU->getNodeId()]; 30880b57cec5SDimitry Andric if (!DUSU) 30890b57cec5SDimitry Andric continue; 30900b57cec5SDimitry Andric for (const SDep &Succ : DUSU->Succs) { 30910b57cec5SDimitry Andric if (Succ.isCtrl()) 30920b57cec5SDimitry Andric continue; 30930b57cec5SDimitry Andric SUnit *SuccSU = Succ.getSUnit(); 30940b57cec5SDimitry Andric if (SuccSU == &SU) 30950b57cec5SDimitry Andric continue; 30960b57cec5SDimitry Andric // Be conservative. Ignore if nodes aren't at roughly the same 30970b57cec5SDimitry Andric // depth and height. 30980b57cec5SDimitry Andric if (SuccSU->getHeight() < SU.getHeight() && 30990b57cec5SDimitry Andric (SU.getHeight() - SuccSU->getHeight()) > 1) 31000b57cec5SDimitry Andric continue; 31010b57cec5SDimitry Andric // Skip past COPY_TO_REGCLASS nodes, so that the pseudo edge 31020b57cec5SDimitry Andric // constrains whatever is using the copy, instead of the copy 31030b57cec5SDimitry Andric // itself. In the case that the copy is coalesced, this 31040b57cec5SDimitry Andric // preserves the intent of the pseudo two-address heurietics. 31050b57cec5SDimitry Andric while (SuccSU->Succs.size() == 1 && 31060b57cec5SDimitry Andric SuccSU->getNode()->isMachineOpcode() && 31070b57cec5SDimitry Andric SuccSU->getNode()->getMachineOpcode() == 31080b57cec5SDimitry Andric TargetOpcode::COPY_TO_REGCLASS) 31090b57cec5SDimitry Andric SuccSU = SuccSU->Succs.front().getSUnit(); 31100b57cec5SDimitry Andric // Don't constrain non-instruction nodes. 31110b57cec5SDimitry Andric if (!SuccSU->getNode() || !SuccSU->getNode()->isMachineOpcode()) 31120b57cec5SDimitry Andric continue; 31130b57cec5SDimitry Andric // Don't constrain nodes with physical register defs if the 31140b57cec5SDimitry Andric // predecessor can clobber them. 31150b57cec5SDimitry Andric if (SuccSU->hasPhysRegDefs && SU.hasPhysRegClobbers) { 31160b57cec5SDimitry Andric if (canClobberPhysRegDefs(SuccSU, &SU, TII, TRI)) 31170b57cec5SDimitry Andric continue; 31180b57cec5SDimitry Andric } 31190b57cec5SDimitry Andric // Don't constrain EXTRACT_SUBREG, INSERT_SUBREG, and SUBREG_TO_REG; 31200b57cec5SDimitry Andric // these may be coalesced away. We want them close to their uses. 31210b57cec5SDimitry Andric unsigned SuccOpc = SuccSU->getNode()->getMachineOpcode(); 31220b57cec5SDimitry Andric if (SuccOpc == TargetOpcode::EXTRACT_SUBREG || 31230b57cec5SDimitry Andric SuccOpc == TargetOpcode::INSERT_SUBREG || 31240b57cec5SDimitry Andric SuccOpc == TargetOpcode::SUBREG_TO_REG) 31250b57cec5SDimitry Andric continue; 31260b57cec5SDimitry Andric if (!canClobberReachingPhysRegUse(SuccSU, &SU, scheduleDAG, TII, TRI) && 31270b57cec5SDimitry Andric (!canClobber(SuccSU, DUSU) || 31280b57cec5SDimitry Andric (isLiveOut && !hasOnlyLiveOutUses(SuccSU)) || 31290b57cec5SDimitry Andric (!SU.isCommutable && SuccSU->isCommutable)) && 31300b57cec5SDimitry Andric !scheduleDAG->IsReachable(SuccSU, &SU)) { 31310b57cec5SDimitry Andric LLVM_DEBUG(dbgs() 31320b57cec5SDimitry Andric << " Adding a pseudo-two-addr edge from SU #" 31330b57cec5SDimitry Andric << SU.NodeNum << " to SU #" << SuccSU->NodeNum << "\n"); 31340b57cec5SDimitry Andric scheduleDAG->AddPredQueued(&SU, SDep(SuccSU, SDep::Artificial)); 31350b57cec5SDimitry Andric } 31360b57cec5SDimitry Andric } 31370b57cec5SDimitry Andric } 31380b57cec5SDimitry Andric } 31390b57cec5SDimitry Andric } 31400b57cec5SDimitry Andric 31410b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 31420b57cec5SDimitry Andric // Public Constructor Functions 31430b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 31440b57cec5SDimitry Andric 31455f757f3fSDimitry Andric ScheduleDAGSDNodes *llvm::createBURRListDAGScheduler(SelectionDAGISel *IS, 31465f757f3fSDimitry Andric CodeGenOptLevel OptLevel) { 31470b57cec5SDimitry Andric const TargetSubtargetInfo &STI = IS->MF->getSubtarget(); 31480b57cec5SDimitry Andric const TargetInstrInfo *TII = STI.getInstrInfo(); 31490b57cec5SDimitry Andric const TargetRegisterInfo *TRI = STI.getRegisterInfo(); 31500b57cec5SDimitry Andric 31510b57cec5SDimitry Andric BURegReductionPriorityQueue *PQ = 31520b57cec5SDimitry Andric new BURegReductionPriorityQueue(*IS->MF, false, false, TII, TRI, nullptr); 31530b57cec5SDimitry Andric ScheduleDAGRRList *SD = new ScheduleDAGRRList(*IS->MF, false, PQ, OptLevel); 31540b57cec5SDimitry Andric PQ->setScheduleDAG(SD); 31550b57cec5SDimitry Andric return SD; 31560b57cec5SDimitry Andric } 31570b57cec5SDimitry Andric 31580b57cec5SDimitry Andric ScheduleDAGSDNodes * 31590b57cec5SDimitry Andric llvm::createSourceListDAGScheduler(SelectionDAGISel *IS, 31605f757f3fSDimitry Andric CodeGenOptLevel OptLevel) { 31610b57cec5SDimitry Andric const TargetSubtargetInfo &STI = IS->MF->getSubtarget(); 31620b57cec5SDimitry Andric const TargetInstrInfo *TII = STI.getInstrInfo(); 31630b57cec5SDimitry Andric const TargetRegisterInfo *TRI = STI.getRegisterInfo(); 31640b57cec5SDimitry Andric 31650b57cec5SDimitry Andric SrcRegReductionPriorityQueue *PQ = 31660b57cec5SDimitry Andric new SrcRegReductionPriorityQueue(*IS->MF, false, true, TII, TRI, nullptr); 31670b57cec5SDimitry Andric ScheduleDAGRRList *SD = new ScheduleDAGRRList(*IS->MF, false, PQ, OptLevel); 31680b57cec5SDimitry Andric PQ->setScheduleDAG(SD); 31690b57cec5SDimitry Andric return SD; 31700b57cec5SDimitry Andric } 31710b57cec5SDimitry Andric 31720b57cec5SDimitry Andric ScheduleDAGSDNodes * 31730b57cec5SDimitry Andric llvm::createHybridListDAGScheduler(SelectionDAGISel *IS, 31745f757f3fSDimitry Andric CodeGenOptLevel OptLevel) { 31750b57cec5SDimitry Andric const TargetSubtargetInfo &STI = IS->MF->getSubtarget(); 31760b57cec5SDimitry Andric const TargetInstrInfo *TII = STI.getInstrInfo(); 31770b57cec5SDimitry Andric const TargetRegisterInfo *TRI = STI.getRegisterInfo(); 31780b57cec5SDimitry Andric const TargetLowering *TLI = IS->TLI; 31790b57cec5SDimitry Andric 31800b57cec5SDimitry Andric HybridBURRPriorityQueue *PQ = 31810b57cec5SDimitry Andric new HybridBURRPriorityQueue(*IS->MF, true, false, TII, TRI, TLI); 31820b57cec5SDimitry Andric 31830b57cec5SDimitry Andric ScheduleDAGRRList *SD = new ScheduleDAGRRList(*IS->MF, true, PQ, OptLevel); 31840b57cec5SDimitry Andric PQ->setScheduleDAG(SD); 31850b57cec5SDimitry Andric return SD; 31860b57cec5SDimitry Andric } 31870b57cec5SDimitry Andric 31885f757f3fSDimitry Andric ScheduleDAGSDNodes *llvm::createILPListDAGScheduler(SelectionDAGISel *IS, 31895f757f3fSDimitry Andric CodeGenOptLevel OptLevel) { 31900b57cec5SDimitry Andric const TargetSubtargetInfo &STI = IS->MF->getSubtarget(); 31910b57cec5SDimitry Andric const TargetInstrInfo *TII = STI.getInstrInfo(); 31920b57cec5SDimitry Andric const TargetRegisterInfo *TRI = STI.getRegisterInfo(); 31930b57cec5SDimitry Andric const TargetLowering *TLI = IS->TLI; 31940b57cec5SDimitry Andric 31950b57cec5SDimitry Andric ILPBURRPriorityQueue *PQ = 31960b57cec5SDimitry Andric new ILPBURRPriorityQueue(*IS->MF, true, false, TII, TRI, TLI); 31970b57cec5SDimitry Andric ScheduleDAGRRList *SD = new ScheduleDAGRRList(*IS->MF, true, PQ, OptLevel); 31980b57cec5SDimitry Andric PQ->setScheduleDAG(SD); 31990b57cec5SDimitry Andric return SD; 32000b57cec5SDimitry Andric } 3201