LLVM API Documentation

DFAPacketizer.cpp
Go to the documentation of this file.
00001 //=- llvm/CodeGen/DFAPacketizer.cpp - DFA Packetizer for VLIW -*- C++ -*-=====//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 // This class implements a deterministic finite automaton (DFA) based
00010 // packetizing mechanism for VLIW architectures. It provides APIs to
00011 // determine whether there exists a legal mapping of instructions to
00012 // functional unit assignments in a packet. The DFA is auto-generated from
00013 // the target's Schedule.td file.
00014 //
00015 // A DFA consists of 3 major elements: states, inputs, and transitions. For
00016 // the packetizing mechanism, the input is the set of instruction classes for
00017 // a target. The state models all possible combinations of functional unit
00018 // consumption for a given set of instructions in a packet. A transition
00019 // models the addition of an instruction to a packet. In the DFA constructed
00020 // by this class, if an instruction can be added to a packet, then a valid
00021 // transition exists from the corresponding state. Invalid transitions
00022 // indicate that the instruction cannot be added to the current packet.
00023 //
00024 //===----------------------------------------------------------------------===//
00025 
00026 #include "llvm/CodeGen/DFAPacketizer.h"
00027 #include "llvm/CodeGen/MachineInstr.h"
00028 #include "llvm/CodeGen/MachineInstrBundle.h"
00029 #include "llvm/CodeGen/ScheduleDAGInstrs.h"
00030 #include "llvm/MC/MCInstrItineraries.h"
00031 #include "llvm/Target/TargetInstrInfo.h"
00032 using namespace llvm;
00033 
00034 DFAPacketizer::DFAPacketizer(const InstrItineraryData *I, const int (*SIT)[2],
00035                              const unsigned *SET):
00036   InstrItins(I), CurrentState(0), DFAStateInputTable(SIT),
00037   DFAStateEntryTable(SET) {}
00038 
00039 
00040 //
00041 // ReadTable - Read the DFA transition table and update CachedTable.
00042 //
00043 // Format of the transition tables:
00044 // DFAStateInputTable[][2] = pairs of <Input, Transition> for all valid
00045 //                           transitions
00046 // DFAStateEntryTable[i] = Index of the first entry in DFAStateInputTable
00047 //                         for the ith state
00048 //
00049 void DFAPacketizer::ReadTable(unsigned int state) {
00050   unsigned ThisState = DFAStateEntryTable[state];
00051   unsigned NextStateInTable = DFAStateEntryTable[state+1];
00052   // Early exit in case CachedTable has already contains this
00053   // state's transitions.
00054   if (CachedTable.count(UnsignPair(state,
00055                                    DFAStateInputTable[ThisState][0])))
00056     return;
00057 
00058   for (unsigned i = ThisState; i < NextStateInTable; i++)
00059     CachedTable[UnsignPair(state, DFAStateInputTable[i][0])] =
00060       DFAStateInputTable[i][1];
00061 }
00062 
00063 
00064 // canReserveResources - Check if the resources occupied by a MCInstrDesc
00065 // are available in the current state.
00066 bool DFAPacketizer::canReserveResources(const llvm::MCInstrDesc *MID) {
00067   unsigned InsnClass = MID->getSchedClass();
00068   const llvm::InstrStage *IS = InstrItins->beginStage(InsnClass);
00069   unsigned FuncUnits = IS->getUnits();
00070   UnsignPair StateTrans = UnsignPair(CurrentState, FuncUnits);
00071   ReadTable(CurrentState);
00072   return (CachedTable.count(StateTrans) != 0);
00073 }
00074 
00075 
00076 // reserveResources - Reserve the resources occupied by a MCInstrDesc and
00077 // change the current state to reflect that change.
00078 void DFAPacketizer::reserveResources(const llvm::MCInstrDesc *MID) {
00079   unsigned InsnClass = MID->getSchedClass();
00080   const llvm::InstrStage *IS = InstrItins->beginStage(InsnClass);
00081   unsigned FuncUnits = IS->getUnits();
00082   UnsignPair StateTrans = UnsignPair(CurrentState, FuncUnits);
00083   ReadTable(CurrentState);
00084   assert(CachedTable.count(StateTrans) != 0);
00085   CurrentState = CachedTable[StateTrans];
00086 }
00087 
00088 
00089 // canReserveResources - Check if the resources occupied by a machine
00090 // instruction are available in the current state.
00091 bool DFAPacketizer::canReserveResources(llvm::MachineInstr *MI) {
00092   const llvm::MCInstrDesc &MID = MI->getDesc();
00093   return canReserveResources(&MID);
00094 }
00095 
00096 // reserveResources - Reserve the resources occupied by a machine
00097 // instruction and change the current state to reflect that change.
00098 void DFAPacketizer::reserveResources(llvm::MachineInstr *MI) {
00099   const llvm::MCInstrDesc &MID = MI->getDesc();
00100   reserveResources(&MID);
00101 }
00102 
00103 namespace llvm {
00104 // DefaultVLIWScheduler - This class extends ScheduleDAGInstrs and overrides
00105 // Schedule method to build the dependence graph.
00106 class DefaultVLIWScheduler : public ScheduleDAGInstrs {
00107 public:
00108   DefaultVLIWScheduler(MachineFunction &MF, MachineLoopInfo &MLI,
00109                        bool IsPostRA);
00110   // Schedule - Actual scheduling work.
00111   void schedule() override;
00112 };
00113 }
00114 
00115 DefaultVLIWScheduler::DefaultVLIWScheduler(MachineFunction &MF,
00116                                            MachineLoopInfo &MLI, bool IsPostRA)
00117     : ScheduleDAGInstrs(MF, &MLI, IsPostRA) {
00118   CanHandleTerminators = true;
00119 }
00120 
00121 void DefaultVLIWScheduler::schedule() {
00122   // Build the scheduling graph.
00123   buildSchedGraph(nullptr);
00124 }
00125 
00126 // VLIWPacketizerList Ctor
00127 VLIWPacketizerList::VLIWPacketizerList(MachineFunction &MF,
00128                                        MachineLoopInfo &MLI, bool IsPostRA)
00129     : TM(MF.getTarget()), MF(MF) {
00130   TII = TM.getSubtargetImpl()->getInstrInfo();
00131   ResourceTracker = TII->CreateTargetScheduleState(&TM, nullptr);
00132   VLIWScheduler = new DefaultVLIWScheduler(MF, MLI, IsPostRA);
00133 }
00134 
00135 // VLIWPacketizerList Dtor
00136 VLIWPacketizerList::~VLIWPacketizerList() {
00137   if (VLIWScheduler)
00138     delete VLIWScheduler;
00139 
00140   if (ResourceTracker)
00141     delete ResourceTracker;
00142 }
00143 
00144 // endPacket - End the current packet, bundle packet instructions and reset
00145 // DFA state.
00146 void VLIWPacketizerList::endPacket(MachineBasicBlock *MBB,
00147                                          MachineInstr *MI) {
00148   if (CurrentPacketMIs.size() > 1) {
00149     MachineInstr *MIFirst = CurrentPacketMIs.front();
00150     finalizeBundle(*MBB, MIFirst, MI);
00151   }
00152   CurrentPacketMIs.clear();
00153   ResourceTracker->clearResources();
00154 }
00155 
00156 // PacketizeMIs - Bundle machine instructions into packets.
00157 void VLIWPacketizerList::PacketizeMIs(MachineBasicBlock *MBB,
00158                                       MachineBasicBlock::iterator BeginItr,
00159                                       MachineBasicBlock::iterator EndItr) {
00160   assert(VLIWScheduler && "VLIW Scheduler is not initialized!");
00161   VLIWScheduler->startBlock(MBB);
00162   VLIWScheduler->enterRegion(MBB, BeginItr, EndItr,
00163                              std::distance(BeginItr, EndItr));
00164   VLIWScheduler->schedule();
00165 
00166   // Generate MI -> SU map.
00167   MIToSUnit.clear();
00168   for (unsigned i = 0, e = VLIWScheduler->SUnits.size(); i != e; ++i) {
00169     SUnit *SU = &VLIWScheduler->SUnits[i];
00170     MIToSUnit[SU->getInstr()] = SU;
00171   }
00172 
00173   // The main packetizer loop.
00174   for (; BeginItr != EndItr; ++BeginItr) {
00175     MachineInstr *MI = BeginItr;
00176 
00177     this->initPacketizerState();
00178 
00179     // End the current packet if needed.
00180     if (this->isSoloInstruction(MI)) {
00181       endPacket(MBB, MI);
00182       continue;
00183     }
00184 
00185     // Ignore pseudo instructions.
00186     if (this->ignorePseudoInstruction(MI, MBB))
00187       continue;
00188 
00189     SUnit *SUI = MIToSUnit[MI];
00190     assert(SUI && "Missing SUnit Info!");
00191 
00192     // Ask DFA if machine resource is available for MI.
00193     bool ResourceAvail = ResourceTracker->canReserveResources(MI);
00194     if (ResourceAvail) {
00195       // Dependency check for MI with instructions in CurrentPacketMIs.
00196       for (std::vector<MachineInstr*>::iterator VI = CurrentPacketMIs.begin(),
00197            VE = CurrentPacketMIs.end(); VI != VE; ++VI) {
00198         MachineInstr *MJ = *VI;
00199         SUnit *SUJ = MIToSUnit[MJ];
00200         assert(SUJ && "Missing SUnit Info!");
00201 
00202         // Is it legal to packetize SUI and SUJ together.
00203         if (!this->isLegalToPacketizeTogether(SUI, SUJ)) {
00204           // Allow packetization if dependency can be pruned.
00205           if (!this->isLegalToPruneDependencies(SUI, SUJ)) {
00206             // End the packet if dependency cannot be pruned.
00207             endPacket(MBB, MI);
00208             break;
00209           } // !isLegalToPruneDependencies.
00210         } // !isLegalToPacketizeTogether.
00211       } // For all instructions in CurrentPacketMIs.
00212     } else {
00213       // End the packet if resource is not available.
00214       endPacket(MBB, MI);
00215     }
00216 
00217     // Add MI to the current packet.
00218     BeginItr = this->addToPacket(MI);
00219   } // For all instructions in BB.
00220 
00221   // End any packet left behind.
00222   endPacket(MBB, EndItr);
00223   VLIWScheduler->exitRegion();
00224   VLIWScheduler->finishBlock();
00225 }