blob: 5c8feb14668906307e34d3af3bdc9b1afa17030b [file] [log] [blame]
Anshuman Dasguptadc81e5d2011-12-01 21:10:21 +00001//=- 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
Andrew Trickebafa0c2012-02-15 18:55:14 +000026#include "ScheduleDAGInstrs.h"
Anshuman Dasguptadc81e5d2011-12-01 21:10:21 +000027#include "llvm/CodeGen/DFAPacketizer.h"
28#include "llvm/CodeGen/MachineInstr.h"
Andrew Trickebafa0c2012-02-15 18:55:14 +000029#include "llvm/CodeGen/MachineInstrBundle.h"
30#include "llvm/Target/TargetInstrInfo.h"
Anshuman Dasguptadc81e5d2011-12-01 21:10:21 +000031#include "llvm/MC/MCInstrItineraries.h"
32using namespace llvm;
33
34DFAPacketizer::DFAPacketizer(const InstrItineraryData *I, const int (*SIT)[2],
Sebastian Pop464f3a32011-12-06 17:34:16 +000035 const unsigned *SET):
Anshuman Dasguptadc81e5d2011-12-01 21:10:21 +000036 InstrItins(I), CurrentState(0), DFAStateInputTable(SIT),
37 DFAStateEntryTable(SET) {}
38
39
40//
Sebastian Popf6f77e92011-12-06 17:34:11 +000041// ReadTable - Read the DFA transition table and update CachedTable.
Anshuman Dasguptadc81e5d2011-12-01 21:10:21 +000042//
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
Sebastian Popf6f77e92011-12-06 17:34:11 +000053 // state's transitions.
Anshuman Dasguptadc81e5d2011-12-01 21:10:21 +000054 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
Sebastian Popf6f77e92011-12-06 17:34:11 +000065// are available in the current state.
Sebastian Pop464f3a32011-12-06 17:34:16 +000066bool DFAPacketizer::canReserveResources(const llvm::MCInstrDesc *MID) {
Anshuman Dasguptadc81e5d2011-12-01 21:10:21 +000067 unsigned InsnClass = MID->getSchedClass();
Sebastian Pop464f3a32011-12-06 17:34:16 +000068 const llvm::InstrStage *IS = InstrItins->beginStage(InsnClass);
Anshuman Dasguptadc81e5d2011-12-01 21:10:21 +000069 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
Sebastian Popf6f77e92011-12-06 17:34:11 +000077// change the current state to reflect that change.
Sebastian Pop464f3a32011-12-06 17:34:16 +000078void DFAPacketizer::reserveResources(const llvm::MCInstrDesc *MID) {
Anshuman Dasguptadc81e5d2011-12-01 21:10:21 +000079 unsigned InsnClass = MID->getSchedClass();
Sebastian Pop464f3a32011-12-06 17:34:16 +000080 const llvm::InstrStage *IS = InstrItins->beginStage(InsnClass);
Anshuman Dasguptadc81e5d2011-12-01 21:10:21 +000081 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
Sebastian Popf6f77e92011-12-06 17:34:11 +000090// instruction are available in the current state.
Sebastian Pop464f3a32011-12-06 17:34:16 +000091bool DFAPacketizer::canReserveResources(llvm::MachineInstr *MI) {
92 const llvm::MCInstrDesc &MID = MI->getDesc();
Anshuman Dasguptadc81e5d2011-12-01 21:10:21 +000093 return canReserveResources(&MID);
94}
95
96// reserveResources - Reserve the resources occupied by a machine
Sebastian Popf6f77e92011-12-06 17:34:11 +000097// instruction and change the current state to reflect that change.
Sebastian Pop464f3a32011-12-06 17:34:16 +000098void DFAPacketizer::reserveResources(llvm::MachineInstr *MI) {
99 const llvm::MCInstrDesc &MID = MI->getDesc();
Anshuman Dasguptadc81e5d2011-12-01 21:10:21 +0000100 reserveResources(&MID);
101}
Andrew Trickebafa0c2012-02-15 18:55:14 +0000102
Andrew Trick68c36e02012-02-15 22:06:21 +0000103namespace {
Andrew Trickebafa0c2012-02-15 18:55:14 +0000104// DefaultVLIWScheduler - This class extends ScheduleDAGInstrs and overrides
105// Schedule method to build the dependence graph.
Andrew Tricke7461862012-02-15 23:34:15 +0000106//
107// ScheduleDAGInstrs has LLVM_LIBRARY_VISIBILITY so cannot be exposed to the
108// VLIWPacketizerImpl interface, even as an undefined pointer.
Andrew Trickebafa0c2012-02-15 18:55:14 +0000109class DefaultVLIWScheduler : public ScheduleDAGInstrs {
110public:
111 DefaultVLIWScheduler(MachineFunction &MF, MachineLoopInfo &MLI,
Andrew Tricke7461862012-02-15 23:34:15 +0000112 MachineDominatorTree &MDT, bool IsPostRA);
Andrew Trickebafa0c2012-02-15 18:55:14 +0000113 // Schedule - Actual scheduling work.
114 void Schedule();
115};
116}
117
Andrew Tricke7461862012-02-15 23:34:15 +0000118namespace llvm {
119// Wrapper for holding library-local data types.
120class VLIWPacketizerImpl {
121public:
122 DefaultVLIWScheduler DAGBuilder;
123 VLIWPacketizerImpl(MachineFunction &MF, MachineLoopInfo &MLI,
124 MachineDominatorTree &MDT, bool IsPostRA)
125 : DAGBuilder(MF, MLI, MDT, IsPostRA) {}
126};
127}
128
Andrew Trickebafa0c2012-02-15 18:55:14 +0000129DefaultVLIWScheduler::DefaultVLIWScheduler(
130 MachineFunction &MF, MachineLoopInfo &MLI, MachineDominatorTree &MDT,
131 bool IsPostRA) :
132 ScheduleDAGInstrs(MF, MLI, MDT, IsPostRA) {
133}
134
135void DefaultVLIWScheduler::Schedule() {
136 // Build the scheduling graph.
137 BuildSchedGraph(0);
138}
139
140// VLIWPacketizerList Ctor
141VLIWPacketizerList::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);
Andrew Tricke7461862012-02-15 23:34:15 +0000146 Impl = new VLIWPacketizerImpl(MF, MLI, MDT, IsPostRA);
Andrew Trickebafa0c2012-02-15 18:55:14 +0000147}
148
149// VLIWPacketizerList Dtor
150VLIWPacketizerList::~VLIWPacketizerList() {
Andrew Tricke7461862012-02-15 23:34:15 +0000151 delete Impl;
Andrew Trickebafa0c2012-02-15 18:55:14 +0000152 delete ResourceTracker;
153}
154
155// ignorePseudoInstruction - ignore pseudo instructions.
156bool 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.
169bool 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.
177void 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.
184void 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.
195void VLIWPacketizerList::PacketizeMIs(MachineBasicBlock *MBB,
196 MachineBasicBlock::iterator BeginItr,
197 MachineBasicBlock::iterator EndItr) {
Andrew Tricke7461862012-02-15 23:34:15 +0000198 Impl->DAGBuilder.Run(MBB, BeginItr, EndItr, MBB->size());
Andrew Trickebafa0c2012-02-15 18:55:14 +0000199
200 // Remember scheduling units.
Andrew Tricke7461862012-02-15 23:34:15 +0000201 SUnits = Impl->DAGBuilder.SUnits;
Andrew Trickebafa0c2012-02-15 18:55:14 +0000202
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}