1*0b57cec5SDimitry Andric //===---- ScheduleDAGSDNodes.h - SDNode Scheduling --------------*- C++ -*-===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric // This file implements the ScheduleDAGSDNodes class, which implements 10*0b57cec5SDimitry Andric // scheduling for an SDNode-based dependency graph. 11*0b57cec5SDimitry Andric // 12*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 13*0b57cec5SDimitry Andric 14*0b57cec5SDimitry Andric #ifndef LLVM_LIB_CODEGEN_SELECTIONDAG_SCHEDULEDAGSDNODES_H 15*0b57cec5SDimitry Andric #define LLVM_LIB_CODEGEN_SELECTIONDAG_SCHEDULEDAGSDNODES_H 16*0b57cec5SDimitry Andric 17*0b57cec5SDimitry Andric #include "llvm/CodeGen/ISDOpcodes.h" 18*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 19*0b57cec5SDimitry Andric #include "llvm/CodeGen/ScheduleDAG.h" 20*0b57cec5SDimitry Andric #include "llvm/CodeGen/SelectionDAGNodes.h" 21*0b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 22*0b57cec5SDimitry Andric #include "llvm/Support/MachineValueType.h" 23*0b57cec5SDimitry Andric #include <cassert> 24*0b57cec5SDimitry Andric #include <string> 25*0b57cec5SDimitry Andric #include <vector> 26*0b57cec5SDimitry Andric 27*0b57cec5SDimitry Andric namespace llvm { 28*0b57cec5SDimitry Andric 29*0b57cec5SDimitry Andric class InstrItineraryData; 30*0b57cec5SDimitry Andric 31*0b57cec5SDimitry Andric /// ScheduleDAGSDNodes - A ScheduleDAG for scheduling SDNode-based DAGs. 32*0b57cec5SDimitry Andric /// 33*0b57cec5SDimitry Andric /// Edges between SUnits are initially based on edges in the SelectionDAG, 34*0b57cec5SDimitry Andric /// and additional edges can be added by the schedulers as heuristics. 35*0b57cec5SDimitry Andric /// SDNodes such as Constants, Registers, and a few others that are not 36*0b57cec5SDimitry Andric /// interesting to schedulers are not allocated SUnits. 37*0b57cec5SDimitry Andric /// 38*0b57cec5SDimitry Andric /// SDNodes with MVT::Glue operands are grouped along with the flagged 39*0b57cec5SDimitry Andric /// nodes into a single SUnit so that they are scheduled together. 40*0b57cec5SDimitry Andric /// 41*0b57cec5SDimitry Andric /// SDNode-based scheduling graphs do not use SDep::Anti or SDep::Output 42*0b57cec5SDimitry Andric /// edges. Physical register dependence information is not carried in 43*0b57cec5SDimitry Andric /// the DAG and must be handled explicitly by schedulers. 44*0b57cec5SDimitry Andric /// 45*0b57cec5SDimitry Andric class ScheduleDAGSDNodes : public ScheduleDAG { 46*0b57cec5SDimitry Andric public: 47*0b57cec5SDimitry Andric MachineBasicBlock *BB; 48*0b57cec5SDimitry Andric SelectionDAG *DAG; // DAG of the current basic block 49*0b57cec5SDimitry Andric const InstrItineraryData *InstrItins; 50*0b57cec5SDimitry Andric 51*0b57cec5SDimitry Andric /// The schedule. Null SUnit*'s represent noop instructions. 52*0b57cec5SDimitry Andric std::vector<SUnit*> Sequence; 53*0b57cec5SDimitry Andric 54*0b57cec5SDimitry Andric explicit ScheduleDAGSDNodes(MachineFunction &mf); 55*0b57cec5SDimitry Andric 56*0b57cec5SDimitry Andric ~ScheduleDAGSDNodes() override = default; 57*0b57cec5SDimitry Andric 58*0b57cec5SDimitry Andric /// Run - perform scheduling. 59*0b57cec5SDimitry Andric /// 60*0b57cec5SDimitry Andric void Run(SelectionDAG *dag, MachineBasicBlock *bb); 61*0b57cec5SDimitry Andric 62*0b57cec5SDimitry Andric /// isPassiveNode - Return true if the node is a non-scheduled leaf. 63*0b57cec5SDimitry Andric /// 64*0b57cec5SDimitry Andric static bool isPassiveNode(SDNode *Node) { 65*0b57cec5SDimitry Andric if (isa<ConstantSDNode>(Node)) return true; 66*0b57cec5SDimitry Andric if (isa<ConstantFPSDNode>(Node)) return true; 67*0b57cec5SDimitry Andric if (isa<RegisterSDNode>(Node)) return true; 68*0b57cec5SDimitry Andric if (isa<RegisterMaskSDNode>(Node)) return true; 69*0b57cec5SDimitry Andric if (isa<GlobalAddressSDNode>(Node)) return true; 70*0b57cec5SDimitry Andric if (isa<BasicBlockSDNode>(Node)) return true; 71*0b57cec5SDimitry Andric if (isa<FrameIndexSDNode>(Node)) return true; 72*0b57cec5SDimitry Andric if (isa<ConstantPoolSDNode>(Node)) return true; 73*0b57cec5SDimitry Andric if (isa<TargetIndexSDNode>(Node)) return true; 74*0b57cec5SDimitry Andric if (isa<JumpTableSDNode>(Node)) return true; 75*0b57cec5SDimitry Andric if (isa<ExternalSymbolSDNode>(Node)) return true; 76*0b57cec5SDimitry Andric if (isa<MCSymbolSDNode>(Node)) return true; 77*0b57cec5SDimitry Andric if (isa<BlockAddressSDNode>(Node)) return true; 78*0b57cec5SDimitry Andric if (Node->getOpcode() == ISD::EntryToken || 79*0b57cec5SDimitry Andric isa<MDNodeSDNode>(Node)) return true; 80*0b57cec5SDimitry Andric return false; 81*0b57cec5SDimitry Andric } 82*0b57cec5SDimitry Andric 83*0b57cec5SDimitry Andric /// NewSUnit - Creates a new SUnit and return a ptr to it. 84*0b57cec5SDimitry Andric /// 85*0b57cec5SDimitry Andric SUnit *newSUnit(SDNode *N); 86*0b57cec5SDimitry Andric 87*0b57cec5SDimitry Andric /// Clone - Creates a clone of the specified SUnit. It does not copy the 88*0b57cec5SDimitry Andric /// predecessors / successors info nor the temporary scheduling states. 89*0b57cec5SDimitry Andric /// 90*0b57cec5SDimitry Andric SUnit *Clone(SUnit *Old); 91*0b57cec5SDimitry Andric 92*0b57cec5SDimitry Andric /// BuildSchedGraph - Build the SUnit graph from the selection dag that we 93*0b57cec5SDimitry Andric /// are input. This SUnit graph is similar to the SelectionDAG, but 94*0b57cec5SDimitry Andric /// excludes nodes that aren't interesting to scheduling, and represents 95*0b57cec5SDimitry Andric /// flagged together nodes with a single SUnit. 96*0b57cec5SDimitry Andric void BuildSchedGraph(AliasAnalysis *AA); 97*0b57cec5SDimitry Andric 98*0b57cec5SDimitry Andric /// InitNumRegDefsLeft - Determine the # of regs defined by this node. 99*0b57cec5SDimitry Andric /// 100*0b57cec5SDimitry Andric void InitNumRegDefsLeft(SUnit *SU); 101*0b57cec5SDimitry Andric 102*0b57cec5SDimitry Andric /// computeLatency - Compute node latency. 103*0b57cec5SDimitry Andric /// 104*0b57cec5SDimitry Andric virtual void computeLatency(SUnit *SU); 105*0b57cec5SDimitry Andric 106*0b57cec5SDimitry Andric virtual void computeOperandLatency(SDNode *Def, SDNode *Use, 107*0b57cec5SDimitry Andric unsigned OpIdx, SDep& dep) const; 108*0b57cec5SDimitry Andric 109*0b57cec5SDimitry Andric /// Schedule - Order nodes according to selected style, filling 110*0b57cec5SDimitry Andric /// in the Sequence member. 111*0b57cec5SDimitry Andric /// 112*0b57cec5SDimitry Andric virtual void Schedule() = 0; 113*0b57cec5SDimitry Andric 114*0b57cec5SDimitry Andric /// VerifyScheduledSequence - Verify that all SUnits are scheduled and 115*0b57cec5SDimitry Andric /// consistent with the Sequence of scheduled instructions. 116*0b57cec5SDimitry Andric void VerifyScheduledSequence(bool isBottomUp); 117*0b57cec5SDimitry Andric 118*0b57cec5SDimitry Andric /// EmitSchedule - Insert MachineInstrs into the MachineBasicBlock 119*0b57cec5SDimitry Andric /// according to the order specified in Sequence. 120*0b57cec5SDimitry Andric /// 121*0b57cec5SDimitry Andric virtual MachineBasicBlock* 122*0b57cec5SDimitry Andric EmitSchedule(MachineBasicBlock::iterator &InsertPos); 123*0b57cec5SDimitry Andric 124*0b57cec5SDimitry Andric void dumpNode(const SUnit &SU) const override; 125*0b57cec5SDimitry Andric void dump() const override; 126*0b57cec5SDimitry Andric void dumpSchedule() const; 127*0b57cec5SDimitry Andric 128*0b57cec5SDimitry Andric std::string getGraphNodeLabel(const SUnit *SU) const override; 129*0b57cec5SDimitry Andric 130*0b57cec5SDimitry Andric std::string getDAGName() const override; 131*0b57cec5SDimitry Andric 132*0b57cec5SDimitry Andric virtual void getCustomGraphFeatures(GraphWriter<ScheduleDAG*> &GW) const; 133*0b57cec5SDimitry Andric 134*0b57cec5SDimitry Andric /// RegDefIter - In place iteration over the values defined by an 135*0b57cec5SDimitry Andric /// SUnit. This does not need copies of the iterator or any other STLisms. 136*0b57cec5SDimitry Andric /// The iterator creates itself, rather than being provided by the SchedDAG. 137*0b57cec5SDimitry Andric class RegDefIter { 138*0b57cec5SDimitry Andric const ScheduleDAGSDNodes *SchedDAG; 139*0b57cec5SDimitry Andric const SDNode *Node; 140*0b57cec5SDimitry Andric unsigned DefIdx; 141*0b57cec5SDimitry Andric unsigned NodeNumDefs; 142*0b57cec5SDimitry Andric MVT ValueType; 143*0b57cec5SDimitry Andric 144*0b57cec5SDimitry Andric public: 145*0b57cec5SDimitry Andric RegDefIter(const SUnit *SU, const ScheduleDAGSDNodes *SD); 146*0b57cec5SDimitry Andric 147*0b57cec5SDimitry Andric bool IsValid() const { return Node != nullptr; } 148*0b57cec5SDimitry Andric 149*0b57cec5SDimitry Andric MVT GetValue() const { 150*0b57cec5SDimitry Andric assert(IsValid() && "bad iterator"); 151*0b57cec5SDimitry Andric return ValueType; 152*0b57cec5SDimitry Andric } 153*0b57cec5SDimitry Andric 154*0b57cec5SDimitry Andric const SDNode *GetNode() const { 155*0b57cec5SDimitry Andric return Node; 156*0b57cec5SDimitry Andric } 157*0b57cec5SDimitry Andric 158*0b57cec5SDimitry Andric unsigned GetIdx() const { 159*0b57cec5SDimitry Andric return DefIdx-1; 160*0b57cec5SDimitry Andric } 161*0b57cec5SDimitry Andric 162*0b57cec5SDimitry Andric void Advance(); 163*0b57cec5SDimitry Andric 164*0b57cec5SDimitry Andric private: 165*0b57cec5SDimitry Andric void InitNodeNumDefs(); 166*0b57cec5SDimitry Andric }; 167*0b57cec5SDimitry Andric 168*0b57cec5SDimitry Andric protected: 169*0b57cec5SDimitry Andric /// ForceUnitLatencies - Return true if all scheduling edges should be given 170*0b57cec5SDimitry Andric /// a latency value of one. The default is to return false; schedulers may 171*0b57cec5SDimitry Andric /// override this as needed. 172*0b57cec5SDimitry Andric virtual bool forceUnitLatencies() const { return false; } 173*0b57cec5SDimitry Andric 174*0b57cec5SDimitry Andric private: 175*0b57cec5SDimitry Andric /// ClusterNeighboringLoads - Cluster loads from "near" addresses into 176*0b57cec5SDimitry Andric /// combined SUnits. 177*0b57cec5SDimitry Andric void ClusterNeighboringLoads(SDNode *Node); 178*0b57cec5SDimitry Andric /// ClusterNodes - Cluster certain nodes which should be scheduled together. 179*0b57cec5SDimitry Andric /// 180*0b57cec5SDimitry Andric void ClusterNodes(); 181*0b57cec5SDimitry Andric 182*0b57cec5SDimitry Andric /// BuildSchedUnits, AddSchedEdges - Helper functions for BuildSchedGraph. 183*0b57cec5SDimitry Andric void BuildSchedUnits(); 184*0b57cec5SDimitry Andric void AddSchedEdges(); 185*0b57cec5SDimitry Andric 186*0b57cec5SDimitry Andric void EmitPhysRegCopy(SUnit *SU, DenseMap<SUnit*, unsigned> &VRBaseMap, 187*0b57cec5SDimitry Andric MachineBasicBlock::iterator InsertPos); 188*0b57cec5SDimitry Andric }; 189*0b57cec5SDimitry Andric 190*0b57cec5SDimitry Andric } // end namespace llvm 191*0b57cec5SDimitry Andric 192*0b57cec5SDimitry Andric #endif // LLVM_LIB_CODEGEN_SELECTIONDAG_SCHEDULEDAGSDNODES_H 193