From 006e1abf76148626fb38de1b643c2d31de7f08a7 Mon Sep 17 00:00:00 2001 From: Andrew Trick Date: Tue, 24 Apr 2012 17:56:43 +0000 Subject: [PATCH] misched: DAG builder support for tracking register pressure within the current scheduling region. The DAG builder is a convenient place to do it. Hopefully this is more efficient than a separate traversal over the same region. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@155456 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/CodeGen/MachineScheduler.h | 6 ++- include/llvm/CodeGen/ScheduleDAGInstrs.h | 3 +- lib/CodeGen/MachineScheduler.cpp | 52 ++++++++++++++++++++++-- lib/CodeGen/ScheduleDAGInstrs.cpp | 11 ++++- 4 files changed, 65 insertions(+), 7 deletions(-) diff --git a/include/llvm/CodeGen/MachineScheduler.h b/include/llvm/CodeGen/MachineScheduler.h index 474c95dfef1..a7ed0bd7331 100644 --- a/include/llvm/CodeGen/MachineScheduler.h +++ b/include/llvm/CodeGen/MachineScheduler.h @@ -27,6 +27,7 @@ #ifndef MACHINESCHEDULER_H #define MACHINESCHEDULER_H +#include "RegisterClassInfo.h" #include "llvm/CodeGen/MachinePassRegistry.h" namespace llvm { @@ -47,7 +48,10 @@ struct MachineSchedContext { AliasAnalysis *AA; LiveIntervals *LIS; - MachineSchedContext(): MF(0), MLI(0), MDT(0), PassConfig(0), AA(0), LIS(0) {} + RegisterClassInfo RegClassInfo; + + MachineSchedContext(): + MF(0), MLI(0), MDT(0), PassConfig(0), AA(0), LIS(0) {} }; /// MachineSchedRegistry provides a selection of available machine instruction diff --git a/include/llvm/CodeGen/ScheduleDAGInstrs.h b/include/llvm/CodeGen/ScheduleDAGInstrs.h index 766c9b2f569..dcf72c79418 100644 --- a/include/llvm/CodeGen/ScheduleDAGInstrs.h +++ b/include/llvm/CodeGen/ScheduleDAGInstrs.h @@ -28,6 +28,7 @@ namespace llvm { class MachineLoopInfo; class MachineDominatorTree; class LiveIntervals; + class RegPressureTracker; /// LoopDependencies - This class analyzes loop-oriented register /// dependencies, which are used to guide scheduling decisions. @@ -275,7 +276,7 @@ namespace llvm { /// buildSchedGraph - Build SUnits from the MachineBasicBlock that we are /// input. - void buildSchedGraph(AliasAnalysis *AA); + void buildSchedGraph(AliasAnalysis *AA, RegPressureTracker *RPTracker = 0); /// addSchedBarrierDeps - Add dependencies from instructions in the current /// list of instructions being scheduled to scheduling barrier. We want to diff --git a/lib/CodeGen/MachineScheduler.cpp b/lib/CodeGen/MachineScheduler.cpp index 1d3241b8cc6..100137b38cf 100644 --- a/lib/CodeGen/MachineScheduler.cpp +++ b/lib/CodeGen/MachineScheduler.cpp @@ -14,6 +14,7 @@ #define DEBUG_TYPE "misched" +#include "RegisterPressure.h" #include "llvm/CodeGen/LiveIntervalAnalysis.h" #include "llvm/CodeGen/MachineScheduler.h" #include "llvm/CodeGen/Passes.h" @@ -149,6 +150,8 @@ bool MachineScheduler::runOnMachineFunction(MachineFunction &mf) { LIS = &getAnalysis(); const TargetInstrInfo *TII = MF->getTarget().getInstrInfo(); + RegClassInfo.runOnMachineFunction(*MF); + // Select the scheduler, or set the default. MachineSchedRegistry::ScheduleDAGCtor Ctor = MachineSchedOpt; if (Ctor == useDefaultMachineSched) { @@ -163,6 +166,9 @@ bool MachineScheduler::runOnMachineFunction(MachineFunction &mf) { OwningPtr Scheduler(Ctor(this)); // Visit all machine basic blocks. + // + // TODO: Visit blocks in global postorder or postorder within the bottom-up + // loop tree. Then we can optionally compute global RegPressure. for (MachineFunction::iterator MBB = MF->begin(), MBBEnd = MF->end(); MBB != MBBEnd; ++MBB) { @@ -181,6 +187,7 @@ bool MachineScheduler::runOnMachineFunction(MachineFunction &mf) { unsigned RemainingCount = MBB->size(); for(MachineBasicBlock::iterator RegionEnd = MBB->end(); RegionEnd != MBB->begin(); RegionEnd = Scheduler->begin()) { + // Avoid decrementing RegionEnd for blocks with no terminator. if (RegionEnd != MBB->end() || TII->isSchedulingBoundary(llvm::prior(RegionEnd), MBB, *MF)) { @@ -279,8 +286,13 @@ namespace { /// machine instructions while updating LiveIntervals. class ScheduleDAGMI : public ScheduleDAGInstrs { AliasAnalysis *AA; + RegisterClassInfo *RegClassInfo; MachineSchedStrategy *SchedImpl; + // Register pressure in this region computed by buildSchedGraph. + IntervalPressure RegPressure; + RegPressureTracker RPTracker; + /// The top of the unscheduled zone. MachineBasicBlock::iterator CurrentTop; @@ -293,7 +305,8 @@ class ScheduleDAGMI : public ScheduleDAGInstrs { public: ScheduleDAGMI(MachineSchedContext *C, MachineSchedStrategy *S): ScheduleDAGInstrs(*C->MF, *C->MLI, *C->MDT, /*IsPostRA=*/false, C->LIS), - AA(C->AA), SchedImpl(S), CurrentTop(), CurrentBottom(), + AA(C->AA), RegClassInfo(&C->RegClassInfo), SchedImpl(S), + RPTracker(RegPressure), CurrentTop(), CurrentBottom(), NumInstrsScheduled(0) {} ~ScheduleDAGMI() { @@ -303,7 +316,16 @@ public: MachineBasicBlock::iterator top() const { return CurrentTop; } MachineBasicBlock::iterator bottom() const { return CurrentBottom; } - /// Implement ScheduleDAGInstrs interface. + /// Implement the ScheduleDAGInstrs interface for handling the next scheduling + /// region. This covers all instructions in a block, while schedule() may only + /// cover a subset. + void enterRegion(MachineBasicBlock *bb, + MachineBasicBlock::iterator begin, + MachineBasicBlock::iterator end, + unsigned endcount); + + /// Implement ScheduleDAGInstrs interface for scheduling a sequence of + /// reorderable instructions. void schedule(); protected: @@ -392,10 +414,32 @@ bool ScheduleDAGMI::checkSchedLimit() { return true; } +/// enterRegion - Called back from MachineScheduler::runOnMachineFunction after +/// crossing a scheduling boundary. [begin, end) includes all instructions in +/// the region, including the boundary itself and single-instruction regions +/// that don't get scheduled. +void ScheduleDAGMI::enterRegion(MachineBasicBlock *bb, + MachineBasicBlock::iterator begin, + MachineBasicBlock::iterator end, + unsigned endcount) +{ + ScheduleDAGInstrs::enterRegion(bb, begin, end, endcount); + // Setup the register pressure tracker to begin tracking at the end of this + // region. + RPTracker.init(&MF, RegClassInfo, LIS, BB, end); +} + /// schedule - Called back from MachineScheduler::runOnMachineFunction -/// after setting up the current scheduling region. +/// after setting up the current scheduling region. [RegionBegin, RegionEnd) +/// only includes instructions that have DAG nodes, not scheduling boundaries. void ScheduleDAGMI::schedule() { - buildSchedGraph(AA); + while(RPTracker.getPos() != RegionEnd) { + bool Moved = RPTracker.recede(); + assert(Moved && "Regpressure tracker cannot find RegionEnd"); (void)Moved; + } + + // Build the DAG. + buildSchedGraph(AA, &RPTracker); DEBUG(dbgs() << "********** MI Scheduling **********\n"); DEBUG(for (unsigned su = 0, e = SUnits.size(); su != e; ++su) diff --git a/lib/CodeGen/ScheduleDAGInstrs.cpp b/lib/CodeGen/ScheduleDAGInstrs.cpp index 1b306d6990a..e2f33aa7358 100644 --- a/lib/CodeGen/ScheduleDAGInstrs.cpp +++ b/lib/CodeGen/ScheduleDAGInstrs.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "sched-instrs" +#include "RegisterPressure.h" #include "llvm/Operator.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/ValueTracking.h" @@ -504,7 +505,11 @@ void ScheduleDAGInstrs::initSUnits() { } } -void ScheduleDAGInstrs::buildSchedGraph(AliasAnalysis *AA) { +/// If RegPressure is non null, compute register pressure as a side effect. The +/// DAG builder is an efficient place to do it because it already visits +/// operands. +void ScheduleDAGInstrs::buildSchedGraph(AliasAnalysis *AA, + RegPressureTracker *RPTracker) { // Create an SUnit for each real instruction. initSUnits(); @@ -555,6 +560,10 @@ void ScheduleDAGInstrs::buildSchedGraph(AliasAnalysis *AA) { PrevMI = MI; continue; } + if (RPTracker) { + RPTracker->recede(); + assert(RPTracker->getPos() == prior(MII) && "RPTracker can't find MI"); + } assert((!MI->isTerminator() || CanHandleTerminators) && !MI->isLabel() && "Cannot schedule terminators or labels!");