1dff0c46cSDimitry Andric //=- llvm/CodeGen/DFAPacketizer.cpp - DFA Packetizer for VLIW -*- C++ -*-=====// 2dff0c46cSDimitry Andric // 3dff0c46cSDimitry Andric // The LLVM Compiler Infrastructure 4dff0c46cSDimitry Andric // 5dff0c46cSDimitry Andric // This file is distributed under the University of Illinois Open Source 6dff0c46cSDimitry Andric // License. See LICENSE.TXT for details. 7dff0c46cSDimitry Andric // 8dff0c46cSDimitry Andric //===----------------------------------------------------------------------===// 9dff0c46cSDimitry Andric // This class implements a deterministic finite automaton (DFA) based 10dff0c46cSDimitry Andric // packetizing mechanism for VLIW architectures. It provides APIs to 11dff0c46cSDimitry Andric // determine whether there exists a legal mapping of instructions to 12dff0c46cSDimitry Andric // functional unit assignments in a packet. The DFA is auto-generated from 13dff0c46cSDimitry Andric // the target's Schedule.td file. 14dff0c46cSDimitry Andric // 15dff0c46cSDimitry Andric // A DFA consists of 3 major elements: states, inputs, and transitions. For 16dff0c46cSDimitry Andric // the packetizing mechanism, the input is the set of instruction classes for 17dff0c46cSDimitry Andric // a target. The state models all possible combinations of functional unit 18dff0c46cSDimitry Andric // consumption for a given set of instructions in a packet. A transition 19dff0c46cSDimitry Andric // models the addition of an instruction to a packet. In the DFA constructed 20dff0c46cSDimitry Andric // by this class, if an instruction can be added to a packet, then a valid 21dff0c46cSDimitry Andric // transition exists from the corresponding state. Invalid transitions 22dff0c46cSDimitry Andric // indicate that the instruction cannot be added to the current packet. 23dff0c46cSDimitry Andric // 24dff0c46cSDimitry Andric //===----------------------------------------------------------------------===// 25dff0c46cSDimitry Andric 26dff0c46cSDimitry Andric #include "llvm/CodeGen/DFAPacketizer.h" 27dff0c46cSDimitry Andric #include "llvm/CodeGen/MachineInstr.h" 28dff0c46cSDimitry Andric #include "llvm/CodeGen/MachineInstrBundle.h" 29139f7f9bSDimitry Andric #include "llvm/CodeGen/ScheduleDAGInstrs.h" 30dff0c46cSDimitry Andric #include "llvm/MC/MCInstrItineraries.h" 31139f7f9bSDimitry Andric #include "llvm/Target/TargetInstrInfo.h" 32dff0c46cSDimitry Andric using namespace llvm; 33dff0c46cSDimitry Andric 34dff0c46cSDimitry Andric DFAPacketizer::DFAPacketizer(const InstrItineraryData *I, const int (*SIT)[2], 35dff0c46cSDimitry Andric const unsigned *SET): 36dff0c46cSDimitry Andric InstrItins(I), CurrentState(0), DFAStateInputTable(SIT), 37dff0c46cSDimitry Andric DFAStateEntryTable(SET) {} 38dff0c46cSDimitry Andric 39dff0c46cSDimitry Andric 40dff0c46cSDimitry Andric // 41dff0c46cSDimitry Andric // ReadTable - Read the DFA transition table and update CachedTable. 42dff0c46cSDimitry Andric // 43dff0c46cSDimitry Andric // Format of the transition tables: 44dff0c46cSDimitry Andric // DFAStateInputTable[][2] = pairs of <Input, Transition> for all valid 45dff0c46cSDimitry Andric // transitions 46dff0c46cSDimitry Andric // DFAStateEntryTable[i] = Index of the first entry in DFAStateInputTable 47dff0c46cSDimitry Andric // for the ith state 48dff0c46cSDimitry Andric // 49dff0c46cSDimitry Andric void DFAPacketizer::ReadTable(unsigned int state) { 50dff0c46cSDimitry Andric unsigned ThisState = DFAStateEntryTable[state]; 51dff0c46cSDimitry Andric unsigned NextStateInTable = DFAStateEntryTable[state+1]; 52dff0c46cSDimitry Andric // Early exit in case CachedTable has already contains this 53dff0c46cSDimitry Andric // state's transitions. 54dff0c46cSDimitry Andric if (CachedTable.count(UnsignPair(state, 55dff0c46cSDimitry Andric DFAStateInputTable[ThisState][0]))) 56dff0c46cSDimitry Andric return; 57dff0c46cSDimitry Andric 58dff0c46cSDimitry Andric for (unsigned i = ThisState; i < NextStateInTable; i++) 59dff0c46cSDimitry Andric CachedTable[UnsignPair(state, DFAStateInputTable[i][0])] = 60dff0c46cSDimitry Andric DFAStateInputTable[i][1]; 61dff0c46cSDimitry Andric } 62dff0c46cSDimitry Andric 63dff0c46cSDimitry Andric 64dff0c46cSDimitry Andric // canReserveResources - Check if the resources occupied by a MCInstrDesc 65dff0c46cSDimitry Andric // are available in the current state. 66dff0c46cSDimitry Andric bool DFAPacketizer::canReserveResources(const llvm::MCInstrDesc *MID) { 67dff0c46cSDimitry Andric unsigned InsnClass = MID->getSchedClass(); 68dff0c46cSDimitry Andric const llvm::InstrStage *IS = InstrItins->beginStage(InsnClass); 69dff0c46cSDimitry Andric unsigned FuncUnits = IS->getUnits(); 70dff0c46cSDimitry Andric UnsignPair StateTrans = UnsignPair(CurrentState, FuncUnits); 71dff0c46cSDimitry Andric ReadTable(CurrentState); 72dff0c46cSDimitry Andric return (CachedTable.count(StateTrans) != 0); 73dff0c46cSDimitry Andric } 74dff0c46cSDimitry Andric 75dff0c46cSDimitry Andric 76dff0c46cSDimitry Andric // reserveResources - Reserve the resources occupied by a MCInstrDesc and 77dff0c46cSDimitry Andric // change the current state to reflect that change. 78dff0c46cSDimitry Andric void DFAPacketizer::reserveResources(const llvm::MCInstrDesc *MID) { 79dff0c46cSDimitry Andric unsigned InsnClass = MID->getSchedClass(); 80dff0c46cSDimitry Andric const llvm::InstrStage *IS = InstrItins->beginStage(InsnClass); 81dff0c46cSDimitry Andric unsigned FuncUnits = IS->getUnits(); 82dff0c46cSDimitry Andric UnsignPair StateTrans = UnsignPair(CurrentState, FuncUnits); 83dff0c46cSDimitry Andric ReadTable(CurrentState); 84dff0c46cSDimitry Andric assert(CachedTable.count(StateTrans) != 0); 85dff0c46cSDimitry Andric CurrentState = CachedTable[StateTrans]; 86dff0c46cSDimitry Andric } 87dff0c46cSDimitry Andric 88dff0c46cSDimitry Andric 89dff0c46cSDimitry Andric // canReserveResources - Check if the resources occupied by a machine 90dff0c46cSDimitry Andric // instruction are available in the current state. 91dff0c46cSDimitry Andric bool DFAPacketizer::canReserveResources(llvm::MachineInstr *MI) { 92dff0c46cSDimitry Andric const llvm::MCInstrDesc &MID = MI->getDesc(); 93dff0c46cSDimitry Andric return canReserveResources(&MID); 94dff0c46cSDimitry Andric } 95dff0c46cSDimitry Andric 96dff0c46cSDimitry Andric // reserveResources - Reserve the resources occupied by a machine 97dff0c46cSDimitry Andric // instruction and change the current state to reflect that change. 98dff0c46cSDimitry Andric void DFAPacketizer::reserveResources(llvm::MachineInstr *MI) { 99dff0c46cSDimitry Andric const llvm::MCInstrDesc &MID = MI->getDesc(); 100dff0c46cSDimitry Andric reserveResources(&MID); 101dff0c46cSDimitry Andric } 102dff0c46cSDimitry Andric 1037ae0e2c9SDimitry Andric namespace llvm { 104dff0c46cSDimitry Andric // DefaultVLIWScheduler - This class extends ScheduleDAGInstrs and overrides 105dff0c46cSDimitry Andric // Schedule method to build the dependence graph. 106dff0c46cSDimitry Andric class DefaultVLIWScheduler : public ScheduleDAGInstrs { 107dff0c46cSDimitry Andric public: 108dff0c46cSDimitry Andric DefaultVLIWScheduler(MachineFunction &MF, MachineLoopInfo &MLI, 109dff0c46cSDimitry Andric MachineDominatorTree &MDT, bool IsPostRA); 110dff0c46cSDimitry Andric // Schedule - Actual scheduling work. 11191bc56edSDimitry Andric void schedule() override; 112dff0c46cSDimitry Andric }; 1137ae0e2c9SDimitry Andric } 114dff0c46cSDimitry Andric 115dff0c46cSDimitry Andric DefaultVLIWScheduler::DefaultVLIWScheduler( 116dff0c46cSDimitry Andric MachineFunction &MF, MachineLoopInfo &MLI, MachineDominatorTree &MDT, 117dff0c46cSDimitry Andric bool IsPostRA) : 118dff0c46cSDimitry Andric ScheduleDAGInstrs(MF, MLI, MDT, IsPostRA) { 1197ae0e2c9SDimitry Andric CanHandleTerminators = true; 120dff0c46cSDimitry Andric } 121dff0c46cSDimitry Andric 122dff0c46cSDimitry Andric void DefaultVLIWScheduler::schedule() { 123dff0c46cSDimitry Andric // Build the scheduling graph. 12491bc56edSDimitry Andric buildSchedGraph(nullptr); 125dff0c46cSDimitry Andric } 126dff0c46cSDimitry Andric 127dff0c46cSDimitry Andric // VLIWPacketizerList Ctor 128dff0c46cSDimitry Andric VLIWPacketizerList::VLIWPacketizerList( 129dff0c46cSDimitry Andric MachineFunction &MF, MachineLoopInfo &MLI, MachineDominatorTree &MDT, 130dff0c46cSDimitry Andric bool IsPostRA) : TM(MF.getTarget()), MF(MF) { 131dff0c46cSDimitry Andric TII = TM.getInstrInfo(); 13291bc56edSDimitry Andric ResourceTracker = TII->CreateTargetScheduleState(&TM, nullptr); 1337ae0e2c9SDimitry Andric VLIWScheduler = new DefaultVLIWScheduler(MF, MLI, MDT, IsPostRA); 134dff0c46cSDimitry Andric } 135dff0c46cSDimitry Andric 136dff0c46cSDimitry Andric // VLIWPacketizerList Dtor 137dff0c46cSDimitry Andric VLIWPacketizerList::~VLIWPacketizerList() { 1387ae0e2c9SDimitry Andric if (VLIWScheduler) 1397ae0e2c9SDimitry Andric delete VLIWScheduler; 1407ae0e2c9SDimitry Andric 1417ae0e2c9SDimitry Andric if (ResourceTracker) 142dff0c46cSDimitry Andric delete ResourceTracker; 143dff0c46cSDimitry Andric } 144dff0c46cSDimitry Andric 145dff0c46cSDimitry Andric // endPacket - End the current packet, bundle packet instructions and reset 146dff0c46cSDimitry Andric // DFA state. 147dff0c46cSDimitry Andric void VLIWPacketizerList::endPacket(MachineBasicBlock *MBB, 1487ae0e2c9SDimitry Andric MachineInstr *MI) { 149dff0c46cSDimitry Andric if (CurrentPacketMIs.size() > 1) { 150dff0c46cSDimitry Andric MachineInstr *MIFirst = CurrentPacketMIs.front(); 1517ae0e2c9SDimitry Andric finalizeBundle(*MBB, MIFirst, MI); 152dff0c46cSDimitry Andric } 153dff0c46cSDimitry Andric CurrentPacketMIs.clear(); 154dff0c46cSDimitry Andric ResourceTracker->clearResources(); 155dff0c46cSDimitry Andric } 156dff0c46cSDimitry Andric 157dff0c46cSDimitry Andric // PacketizeMIs - Bundle machine instructions into packets. 158dff0c46cSDimitry Andric void VLIWPacketizerList::PacketizeMIs(MachineBasicBlock *MBB, 159dff0c46cSDimitry Andric MachineBasicBlock::iterator BeginItr, 160dff0c46cSDimitry Andric MachineBasicBlock::iterator EndItr) { 1617ae0e2c9SDimitry Andric assert(VLIWScheduler && "VLIW Scheduler is not initialized!"); 1627ae0e2c9SDimitry Andric VLIWScheduler->startBlock(MBB); 163f785676fSDimitry Andric VLIWScheduler->enterRegion(MBB, BeginItr, EndItr, 164f785676fSDimitry Andric std::distance(BeginItr, EndItr)); 1657ae0e2c9SDimitry Andric VLIWScheduler->schedule(); 166dff0c46cSDimitry Andric 1677ae0e2c9SDimitry Andric // Generate MI -> SU map. 1687ae0e2c9SDimitry Andric MIToSUnit.clear(); 1697ae0e2c9SDimitry Andric for (unsigned i = 0, e = VLIWScheduler->SUnits.size(); i != e; ++i) { 1707ae0e2c9SDimitry Andric SUnit *SU = &VLIWScheduler->SUnits[i]; 1717ae0e2c9SDimitry Andric MIToSUnit[SU->getInstr()] = SU; 1727ae0e2c9SDimitry Andric } 173dff0c46cSDimitry Andric 174dff0c46cSDimitry Andric // The main packetizer loop. 175dff0c46cSDimitry Andric for (; BeginItr != EndItr; ++BeginItr) { 176dff0c46cSDimitry Andric MachineInstr *MI = BeginItr; 177dff0c46cSDimitry Andric 1787ae0e2c9SDimitry Andric this->initPacketizerState(); 179dff0c46cSDimitry Andric 180dff0c46cSDimitry Andric // End the current packet if needed. 1817ae0e2c9SDimitry Andric if (this->isSoloInstruction(MI)) { 182dff0c46cSDimitry Andric endPacket(MBB, MI); 183dff0c46cSDimitry Andric continue; 184dff0c46cSDimitry Andric } 185dff0c46cSDimitry Andric 1867ae0e2c9SDimitry Andric // Ignore pseudo instructions. 1877ae0e2c9SDimitry Andric if (this->ignorePseudoInstruction(MI, MBB)) 1887ae0e2c9SDimitry Andric continue; 1897ae0e2c9SDimitry Andric 1907ae0e2c9SDimitry Andric SUnit *SUI = MIToSUnit[MI]; 191dff0c46cSDimitry Andric assert(SUI && "Missing SUnit Info!"); 192dff0c46cSDimitry Andric 193dff0c46cSDimitry Andric // Ask DFA if machine resource is available for MI. 194dff0c46cSDimitry Andric bool ResourceAvail = ResourceTracker->canReserveResources(MI); 195dff0c46cSDimitry Andric if (ResourceAvail) { 196dff0c46cSDimitry Andric // Dependency check for MI with instructions in CurrentPacketMIs. 197dff0c46cSDimitry Andric for (std::vector<MachineInstr*>::iterator VI = CurrentPacketMIs.begin(), 198dff0c46cSDimitry Andric VE = CurrentPacketMIs.end(); VI != VE; ++VI) { 199dff0c46cSDimitry Andric MachineInstr *MJ = *VI; 2007ae0e2c9SDimitry Andric SUnit *SUJ = MIToSUnit[MJ]; 201dff0c46cSDimitry Andric assert(SUJ && "Missing SUnit Info!"); 202dff0c46cSDimitry Andric 203dff0c46cSDimitry Andric // Is it legal to packetize SUI and SUJ together. 2047ae0e2c9SDimitry Andric if (!this->isLegalToPacketizeTogether(SUI, SUJ)) { 205dff0c46cSDimitry Andric // Allow packetization if dependency can be pruned. 2067ae0e2c9SDimitry Andric if (!this->isLegalToPruneDependencies(SUI, SUJ)) { 207dff0c46cSDimitry Andric // End the packet if dependency cannot be pruned. 208dff0c46cSDimitry Andric endPacket(MBB, MI); 209dff0c46cSDimitry Andric break; 210dff0c46cSDimitry Andric } // !isLegalToPruneDependencies. 211dff0c46cSDimitry Andric } // !isLegalToPacketizeTogether. 212dff0c46cSDimitry Andric } // For all instructions in CurrentPacketMIs. 213dff0c46cSDimitry Andric } else { 214dff0c46cSDimitry Andric // End the packet if resource is not available. 215dff0c46cSDimitry Andric endPacket(MBB, MI); 216dff0c46cSDimitry Andric } 217dff0c46cSDimitry Andric 218dff0c46cSDimitry Andric // Add MI to the current packet. 2197ae0e2c9SDimitry Andric BeginItr = this->addToPacket(MI); 220dff0c46cSDimitry Andric } // For all instructions in BB. 221dff0c46cSDimitry Andric 222dff0c46cSDimitry Andric // End any packet left behind. 223dff0c46cSDimitry Andric endPacket(MBB, EndItr); 2247ae0e2c9SDimitry Andric VLIWScheduler->exitRegion(); 2257ae0e2c9SDimitry Andric VLIWScheduler->finishBlock(); 226dff0c46cSDimitry Andric } 227