1 //=- llvm/CodeGen/DFAPacketizer.cpp - DFA Packetizer for VLIW -*- C++ -*-=====// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // This class implements a deterministic finite automaton (DFA) based 10 // packetizing mechanism for VLIW architectures. It provides APIs to 11 // determine whether there exists a legal mapping of instructions to 12 // functional unit assignments in a packet. The DFA is auto-generated from 13 // the target's Schedule.td file. 14 // 15 // A DFA consists of 3 major elements: states, inputs, and transitions. For 16 // the packetizing mechanism, the input is the set of instruction classes for 17 // a target. The state models all possible combinations of functional unit 18 // consumption for a given set of instructions in a packet. A transition 19 // models the addition of an instruction to a packet. In the DFA constructed 20 // by this class, if an instruction can be added to a packet, then a valid 21 // transition exists from the corresponding state. Invalid transitions 22 // indicate that the instruction cannot be added to the current packet. 23 // 24 //===----------------------------------------------------------------------===// 25 26 #include "ScheduleDAGInstrs.h" 27 #include "llvm/CodeGen/DFAPacketizer.h" 28 #include "llvm/CodeGen/MachineInstr.h" 29 #include "llvm/CodeGen/MachineInstrBundle.h" 30 #include "llvm/Target/TargetInstrInfo.h" 31 #include "llvm/MC/MCInstrItineraries.h" 32 using namespace llvm; 33 34 DFAPacketizer::DFAPacketizer(const InstrItineraryData *I, const int (*SIT)[2], 35 const unsigned *SET): 36 InstrItins(I), CurrentState(0), DFAStateInputTable(SIT), 37 DFAStateEntryTable(SET) {} 38 39 40 // 41 // ReadTable - Read the DFA transition table and update CachedTable. 42 // 43 // Format of the transition tables: 44 // DFAStateInputTable[][2] = pairs of <Input, Transition> for all valid 45 // transitions 46 // DFAStateEntryTable[i] = Index of the first entry in DFAStateInputTable 47 // for the ith state 48 // 49 void DFAPacketizer::ReadTable(unsigned int state) { 50 unsigned ThisState = DFAStateEntryTable[state]; 51 unsigned NextStateInTable = DFAStateEntryTable[state+1]; 52 // Early exit in case CachedTable has already contains this 53 // state's transitions. 54 if (CachedTable.count(UnsignPair(state, 55 DFAStateInputTable[ThisState][0]))) 56 return; 57 58 for (unsigned i = ThisState; i < NextStateInTable; i++) 59 CachedTable[UnsignPair(state, DFAStateInputTable[i][0])] = 60 DFAStateInputTable[i][1]; 61 } 62 63 64 // canReserveResources - Check if the resources occupied by a MCInstrDesc 65 // are available in the current state. 66 bool DFAPacketizer::canReserveResources(const llvm::MCInstrDesc *MID) { 67 unsigned InsnClass = MID->getSchedClass(); 68 const llvm::InstrStage *IS = InstrItins->beginStage(InsnClass); 69 unsigned FuncUnits = IS->getUnits(); 70 UnsignPair StateTrans = UnsignPair(CurrentState, FuncUnits); 71 ReadTable(CurrentState); 72 return (CachedTable.count(StateTrans) != 0); 73 } 74 75 76 // reserveResources - Reserve the resources occupied by a MCInstrDesc and 77 // change the current state to reflect that change. 78 void DFAPacketizer::reserveResources(const llvm::MCInstrDesc *MID) { 79 unsigned InsnClass = MID->getSchedClass(); 80 const llvm::InstrStage *IS = InstrItins->beginStage(InsnClass); 81 unsigned FuncUnits = IS->getUnits(); 82 UnsignPair StateTrans = UnsignPair(CurrentState, FuncUnits); 83 ReadTable(CurrentState); 84 assert(CachedTable.count(StateTrans) != 0); 85 CurrentState = CachedTable[StateTrans]; 86 } 87 88 89 // canReserveResources - Check if the resources occupied by a machine 90 // instruction are available in the current state. 91 bool DFAPacketizer::canReserveResources(llvm::MachineInstr *MI) { 92 const llvm::MCInstrDesc &MID = MI->getDesc(); 93 return canReserveResources(&MID); 94 } 95 96 // reserveResources - Reserve the resources occupied by a machine 97 // instruction and change the current state to reflect that change. 98 void DFAPacketizer::reserveResources(llvm::MachineInstr *MI) { 99 const llvm::MCInstrDesc &MID = MI->getDesc(); 100 reserveResources(&MID); 101 } 102 103 namespace { 104 // DefaultVLIWScheduler - This class extends ScheduleDAGInstrs and overrides 105 // Schedule method to build the dependence graph. 106 // 107 // ScheduleDAGInstrs has LLVM_LIBRARY_VISIBILITY so cannot be exposed to the 108 // VLIWPacketizerImpl interface, even as an undefined pointer. 109 class DefaultVLIWScheduler : public ScheduleDAGInstrs { 110 public: 111 DefaultVLIWScheduler(MachineFunction &MF, MachineLoopInfo &MLI, 112 MachineDominatorTree &MDT, bool IsPostRA); 113 // Schedule - Actual scheduling work. 114 void Schedule(); 115 }; 116 } 117 118 namespace llvm { 119 // Wrapper for holding library-local data types. 120 class VLIWPacketizerImpl { 121 public: 122 DefaultVLIWScheduler DAGBuilder; 123 VLIWPacketizerImpl(MachineFunction &MF, MachineLoopInfo &MLI, 124 MachineDominatorTree &MDT, bool IsPostRA) 125 : DAGBuilder(MF, MLI, MDT, IsPostRA) {} 126 }; 127 } 128 129 DefaultVLIWScheduler::DefaultVLIWScheduler( 130 MachineFunction &MF, MachineLoopInfo &MLI, MachineDominatorTree &MDT, 131 bool IsPostRA) : 132 ScheduleDAGInstrs(MF, MLI, MDT, IsPostRA) { 133 } 134 135 void DefaultVLIWScheduler::Schedule() { 136 // Build the scheduling graph. 137 BuildSchedGraph(0); 138 } 139 140 // VLIWPacketizerList Ctor 141 VLIWPacketizerList::VLIWPacketizerList( 142 MachineFunction &MF, MachineLoopInfo &MLI, MachineDominatorTree &MDT, 143 bool IsPostRA) : TM(MF.getTarget()), MF(MF) { 144 TII = TM.getInstrInfo(); 145 ResourceTracker = TII->CreateTargetScheduleState(&TM, 0); 146 Impl = new VLIWPacketizerImpl(MF, MLI, MDT, IsPostRA); 147 } 148 149 // VLIWPacketizerList Dtor 150 VLIWPacketizerList::~VLIWPacketizerList() { 151 delete Impl; 152 delete ResourceTracker; 153 } 154 155 // ignorePseudoInstruction - ignore pseudo instructions. 156 bool VLIWPacketizerList::ignorePseudoInstruction(MachineInstr *MI, 157 MachineBasicBlock *MBB) { 158 if (MI->isDebugValue()) 159 return true; 160 161 if (TII->isSchedulingBoundary(MI, MBB, MF)) 162 return true; 163 164 return false; 165 } 166 167 // isSoloInstruction - return true if instruction I must end previous 168 // packet. 169 bool VLIWPacketizerList::isSoloInstruction(MachineInstr *I) { 170 if (I->isInlineAsm()) 171 return true; 172 173 return false; 174 } 175 176 // addToPacket - Add I to the current packet and reserve resource. 177 void VLIWPacketizerList::addToPacket(MachineInstr *MI) { 178 CurrentPacketMIs.push_back(MI); 179 ResourceTracker->reserveResources(MI); 180 } 181 182 // endPacket - End the current packet, bundle packet instructions and reset 183 // DFA state. 184 void VLIWPacketizerList::endPacket(MachineBasicBlock *MBB, 185 MachineInstr *I) { 186 if (CurrentPacketMIs.size() > 1) { 187 MachineInstr *MIFirst = CurrentPacketMIs.front(); 188 finalizeBundle(*MBB, MIFirst, I); 189 } 190 CurrentPacketMIs.clear(); 191 ResourceTracker->clearResources(); 192 } 193 194 // PacketizeMIs - Bundle machine instructions into packets. 195 void VLIWPacketizerList::PacketizeMIs(MachineBasicBlock *MBB, 196 MachineBasicBlock::iterator BeginItr, 197 MachineBasicBlock::iterator EndItr) { 198 Impl->DAGBuilder.Run(MBB, BeginItr, EndItr, MBB->size()); 199 200 // Remember scheduling units. 201 SUnits = Impl->DAGBuilder.SUnits; 202 203 // Generate MI -> SU map. 204 std::map <MachineInstr*, SUnit*> MIToSUnit; 205 for (unsigned i = 0, e = SUnits.size(); i != e; ++i) { 206 SUnit *SU = &SUnits[i]; 207 MIToSUnit[SU->getInstr()] = SU; 208 } 209 210 // The main packetizer loop. 211 for (; BeginItr != EndItr; ++BeginItr) { 212 MachineInstr *MI = BeginItr; 213 214 // Ignore pseudo instructions. 215 if (ignorePseudoInstruction(MI, MBB)) 216 continue; 217 218 // End the current packet if needed. 219 if (isSoloInstruction(MI)) { 220 endPacket(MBB, MI); 221 continue; 222 } 223 224 SUnit *SUI = MIToSUnit[MI]; 225 assert(SUI && "Missing SUnit Info!"); 226 227 // Ask DFA if machine resource is available for MI. 228 bool ResourceAvail = ResourceTracker->canReserveResources(MI); 229 if (ResourceAvail) { 230 // Dependency check for MI with instructions in CurrentPacketMIs. 231 for (std::vector<MachineInstr*>::iterator VI = CurrentPacketMIs.begin(), 232 VE = CurrentPacketMIs.end(); VI != VE; ++VI) { 233 MachineInstr *MJ = *VI; 234 SUnit *SUJ = MIToSUnit[MJ]; 235 assert(SUJ && "Missing SUnit Info!"); 236 237 // Is it legal to packetize SUI and SUJ together. 238 if (!isLegalToPacketizeTogether(SUI, SUJ)) { 239 // Allow packetization if dependency can be pruned. 240 if (!isLegalToPruneDependencies(SUI, SUJ)) { 241 // End the packet if dependency cannot be pruned. 242 endPacket(MBB, MI); 243 break; 244 } // !isLegalToPruneDependencies. 245 } // !isLegalToPacketizeTogether. 246 } // For all instructions in CurrentPacketMIs. 247 } else { 248 // End the packet if resource is not available. 249 endPacket(MBB, MI); 250 } 251 252 // Add MI to the current packet. 253 addToPacket(MI); 254 } // For all instructions in BB. 255 256 // End any packet left behind. 257 endPacket(MBB, EndItr); 258 } 259