| //==- ScheduleDAGInstrs.h - MachineInstr Scheduling --------------*- C++ -*-==// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file implements the ScheduleDAGInstrs class, which implements |
| // scheduling for a MachineInstr-based dependency graph. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef SCHEDULEDAGINSTRS_H |
| #define SCHEDULEDAGINSTRS_H |
| |
| #include "llvm/CodeGen/MachineDominators.h" |
| #include "llvm/CodeGen/MachineLoopInfo.h" |
| #include "llvm/CodeGen/ScheduleDAG.h" |
| #include "llvm/Support/Compiler.h" |
| #include "llvm/Target/TargetRegisterInfo.h" |
| #include "llvm/ADT/SmallSet.h" |
| #include <map> |
| |
| namespace llvm { |
| class MachineLoopInfo; |
| class MachineDominatorTree; |
| |
| /// LoopDependencies - This class analyzes loop-oriented register |
| /// dependencies, which are used to guide scheduling decisions. |
| /// For example, loop induction variable increments should be |
| /// scheduled as soon as possible after the variable's last use. |
| /// |
| class LLVM_LIBRARY_VISIBILITY LoopDependencies { |
| const MachineLoopInfo &MLI; |
| const MachineDominatorTree &MDT; |
| |
| public: |
| typedef std::map<unsigned, std::pair<const MachineOperand *, unsigned> > |
| LoopDeps; |
| LoopDeps Deps; |
| |
| LoopDependencies(const MachineLoopInfo &mli, |
| const MachineDominatorTree &mdt) : |
| MLI(mli), MDT(mdt) {} |
| |
| /// VisitLoop - Clear out any previous state and analyze the given loop. |
| /// |
| void VisitLoop(const MachineLoop *Loop) { |
| assert(Deps.empty() && "stale loop dependencies"); |
| |
| MachineBasicBlock *Header = Loop->getHeader(); |
| SmallSet<unsigned, 8> LoopLiveIns; |
| for (MachineBasicBlock::livein_iterator LI = Header->livein_begin(), |
| LE = Header->livein_end(); LI != LE; ++LI) |
| LoopLiveIns.insert(*LI); |
| |
| const MachineDomTreeNode *Node = MDT.getNode(Header); |
| const MachineBasicBlock *MBB = Node->getBlock(); |
| assert(Loop->contains(MBB) && |
| "Loop does not contain header!"); |
| VisitRegion(Node, MBB, Loop, LoopLiveIns); |
| } |
| |
| private: |
| void VisitRegion(const MachineDomTreeNode *Node, |
| const MachineBasicBlock *MBB, |
| const MachineLoop *Loop, |
| const SmallSet<unsigned, 8> &LoopLiveIns) { |
| unsigned Count = 0; |
| for (MachineBasicBlock::const_iterator I = MBB->begin(), E = MBB->end(); |
| I != E; ++I) { |
| const MachineInstr *MI = I; |
| if (MI->isDebugValue()) |
| continue; |
| for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { |
| const MachineOperand &MO = MI->getOperand(i); |
| if (!MO.isReg() || !MO.isUse()) |
| continue; |
| unsigned MOReg = MO.getReg(); |
| if (LoopLiveIns.count(MOReg)) |
| Deps.insert(std::make_pair(MOReg, std::make_pair(&MO, Count))); |
| } |
| ++Count; // Not every iteration due to dbg_value above. |
| } |
| |
| const std::vector<MachineDomTreeNode*> &Children = Node->getChildren(); |
| for (std::vector<MachineDomTreeNode*>::const_iterator I = |
| Children.begin(), E = Children.end(); I != E; ++I) { |
| const MachineDomTreeNode *ChildNode = *I; |
| MachineBasicBlock *ChildBlock = ChildNode->getBlock(); |
| if (Loop->contains(ChildBlock)) |
| VisitRegion(ChildNode, ChildBlock, Loop, LoopLiveIns); |
| } |
| } |
| }; |
| |
| /// ScheduleDAGInstrs - A ScheduleDAG subclass for scheduling lists of |
| /// MachineInstrs. |
| class LLVM_LIBRARY_VISIBILITY ScheduleDAGInstrs : public ScheduleDAG { |
| const MachineLoopInfo &MLI; |
| const MachineDominatorTree &MDT; |
| const MachineFrameInfo *MFI; |
| const InstrItineraryData *InstrItins; |
| |
| /// Defs, Uses - Remember where defs and uses of each physical register |
| /// are as we iterate upward through the instructions. This is allocated |
| /// here instead of inside BuildSchedGraph to avoid the need for it to be |
| /// initialized and destructed for each block. |
| std::vector<std::vector<SUnit *> > Defs; |
| std::vector<std::vector<SUnit *> > Uses; |
| |
| /// PendingLoads - Remember where unknown loads are after the most recent |
| /// unknown store, as we iterate. As with Defs and Uses, this is here |
| /// to minimize construction/destruction. |
| std::vector<SUnit *> PendingLoads; |
| |
| /// LoopRegs - Track which registers are used for loop-carried dependencies. |
| /// |
| LoopDependencies LoopRegs; |
| |
| /// LoopLiveInRegs - Track which regs are live into a loop, to help guide |
| /// back-edge-aware scheduling. |
| /// |
| SmallSet<unsigned, 8> LoopLiveInRegs; |
| |
| protected: |
| |
| /// DbgValues - Remember instruction that preceeds DBG_VALUE. |
| typedef std::vector<std::pair<MachineInstr *, MachineInstr *> > |
| DbgValueVector; |
| DbgValueVector DbgValues; |
| MachineInstr *FirstDbgValue; |
| |
| public: |
| MachineBasicBlock::iterator Begin; // The beginning of the range to |
| // be scheduled. The range extends |
| // to InsertPos. |
| unsigned InsertPosIndex; // The index in BB of InsertPos. |
| |
| explicit ScheduleDAGInstrs(MachineFunction &mf, |
| const MachineLoopInfo &mli, |
| const MachineDominatorTree &mdt); |
| |
| virtual ~ScheduleDAGInstrs() {} |
| |
| /// NewSUnit - Creates a new SUnit and return a ptr to it. |
| /// |
| SUnit *NewSUnit(MachineInstr *MI) { |
| #ifndef NDEBUG |
| const SUnit *Addr = SUnits.empty() ? 0 : &SUnits[0]; |
| #endif |
| SUnits.push_back(SUnit(MI, (unsigned)SUnits.size())); |
| assert((Addr == 0 || Addr == &SUnits[0]) && |
| "SUnits std::vector reallocated on the fly!"); |
| SUnits.back().OrigNode = &SUnits.back(); |
| return &SUnits.back(); |
| } |
| |
| /// Run - perform scheduling. |
| /// |
| void Run(MachineBasicBlock *bb, |
| MachineBasicBlock::iterator begin, |
| MachineBasicBlock::iterator end, |
| unsigned endindex); |
| |
| /// BuildSchedGraph - Build SUnits from the MachineBasicBlock that we are |
| /// input. |
| virtual void BuildSchedGraph(AliasAnalysis *AA); |
| |
| /// AddSchedBarrierDeps - Add dependencies from instructions in the current |
| /// list of instructions being scheduled to scheduling barrier. We want to |
| /// make sure instructions which define registers that are either used by |
| /// the terminator or are live-out are properly scheduled. This is |
| /// especially important when the definition latency of the return value(s) |
| /// are too high to be hidden by the branch or when the liveout registers |
| /// used by instructions in the fallthrough block. |
| void AddSchedBarrierDeps(); |
| |
| /// ComputeLatency - Compute node latency. |
| /// |
| virtual void ComputeLatency(SUnit *SU); |
| |
| /// ComputeOperandLatency - Override dependence edge latency using |
| /// operand use/def information |
| /// |
| virtual void ComputeOperandLatency(SUnit *Def, SUnit *Use, |
| SDep& dep) const; |
| |
| virtual MachineBasicBlock *EmitSchedule(); |
| |
| /// StartBlock - Prepare to perform scheduling in the given block. |
| /// |
| virtual void StartBlock(MachineBasicBlock *BB); |
| |
| /// Schedule - Order nodes according to selected style, filling |
| /// in the Sequence member. |
| /// |
| virtual void Schedule() = 0; |
| |
| /// FinishBlock - Clean up after scheduling in the given block. |
| /// |
| virtual void FinishBlock(); |
| |
| virtual void dumpNode(const SUnit *SU) const; |
| |
| virtual std::string getGraphNodeLabel(const SUnit *SU) const; |
| }; |
| } |
| |
| #endif |