DFAPacketizer.cpp revision 47c144505b9be28ed22c626b3a407c11dba2fec5
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" 32using namespace llvm; 33 34DFAPacketizer::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// 49void 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. 66bool 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. 78void 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. 91bool 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. 98void DFAPacketizer::reserveResources(llvm::MachineInstr *MI) { 99 const llvm::MCInstrDesc &MID = MI->getDesc(); 100 reserveResources(&MID); 101} 102 103namespace { 104// DefaultVLIWScheduler - This class extends ScheduleDAGInstrs and overrides 105// Schedule method to build the dependence graph. 106// 107// ScheduleDAGInstrs has LLVM_LIBRARY_VISIBILITY so we have to reference it as 108// an opaque pointer in VLIWPacketizerList. 109class DefaultVLIWScheduler : public ScheduleDAGInstrs { 110public: 111 DefaultVLIWScheduler(MachineFunction &MF, MachineLoopInfo &MLI, 112 MachineDominatorTree &MDT, bool IsPostRA); 113 // Schedule - Actual scheduling work. 114 void Schedule(); 115}; 116} // end anonymous namespace 117 118DefaultVLIWScheduler::DefaultVLIWScheduler( 119 MachineFunction &MF, MachineLoopInfo &MLI, MachineDominatorTree &MDT, 120 bool IsPostRA) : 121 ScheduleDAGInstrs(MF, MLI, MDT, IsPostRA) { 122} 123 124void DefaultVLIWScheduler::Schedule() { 125 // Build the scheduling graph. 126 BuildSchedGraph(0); 127} 128 129// VLIWPacketizerList Ctor 130VLIWPacketizerList::VLIWPacketizerList( 131 MachineFunction &MF, MachineLoopInfo &MLI, MachineDominatorTree &MDT, 132 bool IsPostRA) : TM(MF.getTarget()), MF(MF) { 133 TII = TM.getInstrInfo(); 134 ResourceTracker = TII->CreateTargetScheduleState(&TM, 0); 135 SchedulerImpl = new DefaultVLIWScheduler(MF, MLI, MDT, IsPostRA); 136} 137 138// VLIWPacketizerList Dtor 139VLIWPacketizerList::~VLIWPacketizerList() { 140 delete (DefaultVLIWScheduler *)SchedulerImpl; 141 delete ResourceTracker; 142} 143 144// ignorePseudoInstruction - ignore pseudo instructions. 145bool VLIWPacketizerList::ignorePseudoInstruction(MachineInstr *MI, 146 MachineBasicBlock *MBB) { 147 if (MI->isDebugValue()) 148 return true; 149 150 if (TII->isSchedulingBoundary(MI, MBB, MF)) 151 return true; 152 153 return false; 154} 155 156// isSoloInstruction - return true if instruction I must end previous 157// packet. 158bool VLIWPacketizerList::isSoloInstruction(MachineInstr *I) { 159 if (I->isInlineAsm()) 160 return true; 161 162 return false; 163} 164 165// addToPacket - Add I to the current packet and reserve resource. 166void VLIWPacketizerList::addToPacket(MachineInstr *MI) { 167 CurrentPacketMIs.push_back(MI); 168 ResourceTracker->reserveResources(MI); 169} 170 171// endPacket - End the current packet, bundle packet instructions and reset 172// DFA state. 173void VLIWPacketizerList::endPacket(MachineBasicBlock *MBB, 174 MachineInstr *I) { 175 if (CurrentPacketMIs.size() > 1) { 176 MachineInstr *MIFirst = CurrentPacketMIs.front(); 177 finalizeBundle(*MBB, MIFirst, I); 178 } 179 CurrentPacketMIs.clear(); 180 ResourceTracker->clearResources(); 181} 182 183// PacketizeMIs - Bundle machine instructions into packets. 184void VLIWPacketizerList::PacketizeMIs(MachineBasicBlock *MBB, 185 MachineBasicBlock::iterator BeginItr, 186 MachineBasicBlock::iterator EndItr) { 187 DefaultVLIWScheduler *Scheduler = (DefaultVLIWScheduler *)SchedulerImpl; 188 Scheduler->enterRegion(MBB, BeginItr, EndItr, MBB->size()); 189 Scheduler->Schedule(); 190 Scheduler->exitRegion(); 191 192 // Remember scheduling units. 193 SUnits = Scheduler->SUnits; 194 195 // Generate MI -> SU map. 196 std::map <MachineInstr*, SUnit*> MIToSUnit; 197 for (unsigned i = 0, e = SUnits.size(); i != e; ++i) { 198 SUnit *SU = &SUnits[i]; 199 MIToSUnit[SU->getInstr()] = SU; 200 } 201 202 // The main packetizer loop. 203 for (; BeginItr != EndItr; ++BeginItr) { 204 MachineInstr *MI = BeginItr; 205 206 // Ignore pseudo instructions. 207 if (ignorePseudoInstruction(MI, MBB)) 208 continue; 209 210 // End the current packet if needed. 211 if (isSoloInstruction(MI)) { 212 endPacket(MBB, MI); 213 continue; 214 } 215 216 SUnit *SUI = MIToSUnit[MI]; 217 assert(SUI && "Missing SUnit Info!"); 218 219 // Ask DFA if machine resource is available for MI. 220 bool ResourceAvail = ResourceTracker->canReserveResources(MI); 221 if (ResourceAvail) { 222 // Dependency check for MI with instructions in CurrentPacketMIs. 223 for (std::vector<MachineInstr*>::iterator VI = CurrentPacketMIs.begin(), 224 VE = CurrentPacketMIs.end(); VI != VE; ++VI) { 225 MachineInstr *MJ = *VI; 226 SUnit *SUJ = MIToSUnit[MJ]; 227 assert(SUJ && "Missing SUnit Info!"); 228 229 // Is it legal to packetize SUI and SUJ together. 230 if (!isLegalToPacketizeTogether(SUI, SUJ)) { 231 // Allow packetization if dependency can be pruned. 232 if (!isLegalToPruneDependencies(SUI, SUJ)) { 233 // End the packet if dependency cannot be pruned. 234 endPacket(MBB, MI); 235 break; 236 } // !isLegalToPruneDependencies. 237 } // !isLegalToPacketizeTogether. 238 } // For all instructions in CurrentPacketMIs. 239 } else { 240 // End the packet if resource is not available. 241 endPacket(MBB, MI); 242 } 243 244 // Add MI to the current packet. 245 addToPacket(MI); 246 } // For all instructions in BB. 247 248 // End any packet left behind. 249 endPacket(MBB, EndItr); 250} 251