LLVM  8.0.1
DFAPacketizer.cpp
Go to the documentation of this file.
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 
34 #include "llvm/MC/MCInstrDesc.h"
37 #include "llvm/Support/Debug.h"
39 #include <algorithm>
40 #include <cassert>
41 #include <iterator>
42 #include <memory>
43 #include <vector>
44 
45 using namespace llvm;
46 
47 #define DEBUG_TYPE "packets"
48 
49 static cl::opt<unsigned> InstrLimit("dfa-instr-limit", cl::Hidden,
50  cl::init(0), cl::desc("If present, stops packetizing after N instructions"));
51 
52 static unsigned InstrCount = 0;
53 
54 // --------------------------------------------------------------------
55 // Definitions shared between DFAPacketizer.cpp and DFAPacketizerEmitter.cpp
56 
57 static DFAInput addDFAFuncUnits(DFAInput Inp, unsigned FuncUnits) {
58  return (Inp << DFA_MAX_RESOURCES) | FuncUnits;
59 }
60 
61 /// Return the DFAInput for an instruction class input vector.
62 /// This function is used in both DFAPacketizer.cpp and in
63 /// DFAPacketizerEmitter.cpp.
64 static DFAInput getDFAInsnInput(const std::vector<unsigned> &InsnClass) {
65  DFAInput InsnInput = 0;
66  assert((InsnClass.size() <= DFA_MAX_RESTERMS) &&
67  "Exceeded maximum number of DFA terms");
68  for (auto U : InsnClass)
69  InsnInput = addDFAFuncUnits(InsnInput, U);
70  return InsnInput;
71 }
72 
73 // --------------------------------------------------------------------
74 
76  const DFAStateInput (*SIT)[2],
77  const unsigned *SET):
78  InstrItins(I), DFAStateInputTable(SIT), DFAStateEntryTable(SET) {
79  // Make sure DFA types are large enough for the number of terms & resources.
80  static_assert((DFA_MAX_RESTERMS * DFA_MAX_RESOURCES) <=
81  (8 * sizeof(DFAInput)),
82  "(DFA_MAX_RESTERMS * DFA_MAX_RESOURCES) too big for DFAInput");
83  static_assert(
84  (DFA_MAX_RESTERMS * DFA_MAX_RESOURCES) <= (8 * sizeof(DFAStateInput)),
85  "(DFA_MAX_RESTERMS * DFA_MAX_RESOURCES) too big for DFAStateInput");
86 }
87 
88 // Read the DFA transition table and update CachedTable.
89 //
90 // Format of the transition tables:
91 // DFAStateInputTable[][2] = pairs of <Input, Transition> for all valid
92 // transitions
93 // DFAStateEntryTable[i] = Index of the first entry in DFAStateInputTable
94 // for the ith state
95 //
96 void DFAPacketizer::ReadTable(unsigned int state) {
97  unsigned ThisState = DFAStateEntryTable[state];
98  unsigned NextStateInTable = DFAStateEntryTable[state+1];
99  // Early exit in case CachedTable has already contains this
100  // state's transitions.
101  if (CachedTable.count(UnsignPair(state, DFAStateInputTable[ThisState][0])))
102  return;
103 
104  for (unsigned i = ThisState; i < NextStateInTable; i++)
105  CachedTable[UnsignPair(state, DFAStateInputTable[i][0])] =
106  DFAStateInputTable[i][1];
107 }
108 
109 // Return the DFAInput for an instruction class.
111  // Note: this logic must match that in DFAPacketizerDefs.h for input vectors.
112  DFAInput InsnInput = 0;
113  unsigned i = 0;
114  (void)i;
115  for (const InstrStage *IS = InstrItins->beginStage(InsnClass),
116  *IE = InstrItins->endStage(InsnClass); IS != IE; ++IS) {
117  InsnInput = addDFAFuncUnits(InsnInput, IS->getUnits());
118  assert((i++ < DFA_MAX_RESTERMS) && "Exceeded maximum number of DFA inputs");
119  }
120  return InsnInput;
121 }
122 
123 // Return the DFAInput for an instruction class input vector.
124 DFAInput DFAPacketizer::getInsnInput(const std::vector<unsigned> &InsnClass) {
125  return getDFAInsnInput(InsnClass);
126 }
127 
128 // Check if the resources occupied by a MCInstrDesc are available in the
129 // current state.
131  unsigned InsnClass = MID->getSchedClass();
132  DFAInput InsnInput = getInsnInput(InsnClass);
133  UnsignPair StateTrans = UnsignPair(CurrentState, InsnInput);
134  ReadTable(CurrentState);
135  return CachedTable.count(StateTrans) != 0;
136 }
137 
138 // Reserve the resources occupied by a MCInstrDesc and change the current
139 // state to reflect that change.
141  unsigned InsnClass = MID->getSchedClass();
142  DFAInput InsnInput = getInsnInput(InsnClass);
143  UnsignPair StateTrans = UnsignPair(CurrentState, InsnInput);
144  ReadTable(CurrentState);
145  assert(CachedTable.count(StateTrans) != 0);
146  CurrentState = CachedTable[StateTrans];
147 }
148 
149 // Check if the resources occupied by a machine instruction are available
150 // in the current state.
152  const MCInstrDesc &MID = MI.getDesc();
153  return canReserveResources(&MID);
154 }
155 
156 // Reserve the resources occupied by a machine instruction and change the
157 // current state to reflect that change.
159  const MCInstrDesc &MID = MI.getDesc();
160  reserveResources(&MID);
161 }
162 
163 namespace llvm {
164 
165 // This class extends ScheduleDAGInstrs and overrides the schedule method
166 // to build the dependence graph.
168 private:
169  AliasAnalysis *AA;
170  /// Ordered list of DAG postprocessing steps.
171  std::vector<std::unique_ptr<ScheduleDAGMutation>> Mutations;
172 
173 public:
175  AliasAnalysis *AA);
176 
177  // Actual scheduling work.
178  void schedule() override;
179 
180  /// DefaultVLIWScheduler takes ownership of the Mutation object.
181  void addMutation(std::unique_ptr<ScheduleDAGMutation> Mutation) {
182  Mutations.push_back(std::move(Mutation));
183  }
184 
185 protected:
186  void postprocessDAG();
187 };
188 
189 } // end namespace llvm
190 
192  MachineLoopInfo &MLI,
193  AliasAnalysis *AA)
194  : ScheduleDAGInstrs(MF, &MLI), AA(AA) {
195  CanHandleTerminators = true;
196 }
197 
198 /// Apply each ScheduleDAGMutation step in order.
200  for (auto &M : Mutations)
201  M->apply(this);
202 }
203 
205  // Build the scheduling graph.
206  buildSchedGraph(AA);
207  postprocessDAG();
208 }
209 
212  : MF(mf), TII(mf.getSubtarget().getInstrInfo()), AA(aa) {
215 }
216 
218  delete VLIWScheduler;
219  delete ResourceTracker;
220 }
221 
222 // End the current packet, bundle packet instructions and reset DFA state.
225  LLVM_DEBUG({
226  if (!CurrentPacketMIs.empty()) {
227  dbgs() << "Finalizing packet:\n";
228  for (MachineInstr *MI : CurrentPacketMIs)
229  dbgs() << " * " << *MI;
230  }
231  });
232  if (CurrentPacketMIs.size() > 1) {
233  MachineInstr &MIFirst = *CurrentPacketMIs.front();
234  finalizeBundle(*MBB, MIFirst.getIterator(), MI.getInstrIterator());
235  }
236  CurrentPacketMIs.clear();
238  LLVM_DEBUG(dbgs() << "End packet\n");
239 }
240 
241 // Bundle machine instructions into packets.
245  assert(VLIWScheduler && "VLIW Scheduler is not initialized!");
247  VLIWScheduler->enterRegion(MBB, BeginItr, EndItr,
248  std::distance(BeginItr, EndItr));
250 
251  LLVM_DEBUG({
252  dbgs() << "Scheduling DAG of the packetize region\n";
253  VLIWScheduler->dump();
254  });
255 
256  // Generate MI -> SU map.
257  MIToSUnit.clear();
258  for (SUnit &SU : VLIWScheduler->SUnits)
259  MIToSUnit[SU.getInstr()] = &SU;
260 
261  bool LimitPresent = InstrLimit.getPosition();
262 
263  // The main packetizer loop.
264  for (; BeginItr != EndItr; ++BeginItr) {
265  if (LimitPresent) {
266  if (InstrCount >= InstrLimit) {
267  EndItr = BeginItr;
268  break;
269  }
270  InstrCount++;
271  }
272  MachineInstr &MI = *BeginItr;
274 
275  // End the current packet if needed.
276  if (isSoloInstruction(MI)) {
277  endPacket(MBB, MI);
278  continue;
279  }
280 
281  // Ignore pseudo instructions.
282  if (ignorePseudoInstruction(MI, MBB))
283  continue;
284 
285  SUnit *SUI = MIToSUnit[&MI];
286  assert(SUI && "Missing SUnit Info!");
287 
288  // Ask DFA if machine resource is available for MI.
289  LLVM_DEBUG(dbgs() << "Checking resources for adding MI to packet " << MI);
290 
291  bool ResourceAvail = ResourceTracker->canReserveResources(MI);
292  LLVM_DEBUG({
293  if (ResourceAvail)
294  dbgs() << " Resources are available for adding MI to packet\n";
295  else
296  dbgs() << " Resources NOT available\n";
297  });
298  if (ResourceAvail && shouldAddToPacket(MI)) {
299  // Dependency check for MI with instructions in CurrentPacketMIs.
300  for (auto MJ : CurrentPacketMIs) {
301  SUnit *SUJ = MIToSUnit[MJ];
302  assert(SUJ && "Missing SUnit Info!");
303 
304  LLVM_DEBUG(dbgs() << " Checking against MJ " << *MJ);
305  // Is it legal to packetize SUI and SUJ together.
306  if (!isLegalToPacketizeTogether(SUI, SUJ)) {
307  LLVM_DEBUG(dbgs() << " Not legal to add MI, try to prune\n");
308  // Allow packetization if dependency can be pruned.
309  if (!isLegalToPruneDependencies(SUI, SUJ)) {
310  // End the packet if dependency cannot be pruned.
311  LLVM_DEBUG(dbgs()
312  << " Could not prune dependencies for adding MI\n");
313  endPacket(MBB, MI);
314  break;
315  }
316  LLVM_DEBUG(dbgs() << " Pruned dependence for adding MI\n");
317  }
318  }
319  } else {
320  LLVM_DEBUG(if (ResourceAvail) dbgs()
321  << "Resources are available, but instruction should not be "
322  "added to packet\n "
323  << MI);
324  // End the packet if resource is not available, or if the instruction
325  // shoud not be added to the current packet.
326  endPacket(MBB, MI);
327  }
328 
329  // Add MI to the current packet.
330  LLVM_DEBUG(dbgs() << "* Adding MI to packet " << MI << '\n');
331  BeginItr = addToPacket(MI);
332  } // For all instructions in the packetization range.
333 
334  // End any packet left behind.
335  endPacket(MBB, EndItr);
338 }
339 
341  const MachineMemOperand &Op2,
342  bool UseTBAA) const {
343  if (!Op1.getValue() || !Op2.getValue())
344  return true;
345 
346  int64_t MinOffset = std::min(Op1.getOffset(), Op2.getOffset());
347  int64_t Overlapa = Op1.getSize() + Op1.getOffset() - MinOffset;
348  int64_t Overlapb = Op2.getSize() + Op2.getOffset() - MinOffset;
349 
350  AliasResult AAResult =
351  AA->alias(MemoryLocation(Op1.getValue(), Overlapa,
352  UseTBAA ? Op1.getAAInfo() : AAMDNodes()),
353  MemoryLocation(Op2.getValue(), Overlapb,
354  UseTBAA ? Op2.getAAInfo() : AAMDNodes()));
355 
356  return AAResult != NoAlias;
357 }
358 
360  const MachineInstr &MI2,
361  bool UseTBAA) const {
362  if (MI1.memoperands_empty() || MI2.memoperands_empty())
363  return true;
364 
365  for (const MachineMemOperand *Op1 : MI1.memoperands())
366  for (const MachineMemOperand *Op2 : MI2.memoperands())
367  if (alias(*Op1, *Op2, UseTBAA))
368  return true;
369  return false;
370 }
371 
372 // Add a DAG mutation object to the ordered list.
374  std::unique_ptr<ScheduleDAGMutation> Mutation) {
375  VLIWScheduler->addMutation(std::move(Mutation));
376 }
std::vector< MachineInstr * > CurrentPacketMIs
void addMutation(std::unique_ptr< ScheduleDAGMutation > Mutation)
virtual void finishBlock()
Cleans up after scheduling in the given block.
virtual void initPacketizerState()
static DFAInput addDFAFuncUnits(DFAInput Inp, unsigned FuncUnits)
void dump() const override
This class represents lattice values for constants.
Definition: AllocatorList.h:24
const InstrStage * beginStage(unsigned ItinClassIndx) const
Return the first stage of the itinerary.
DFAInput getInsnInput(unsigned InsnClass)
Describe properties that are true of each instruction in the target description file.
Definition: MCInstrDesc.h:164
The two locations do not alias at all.
Definition: AliasAnalysis.h:84
bool CanHandleTerminators
The standard DAG builder does not normally include terminators as DAG nodes because it does not creat...
uint64_t getSize() const
Return the size in bytes of the memory reference.
virtual bool isLegalToPruneDependencies(SUnit *SUI, SUnit *SUJ)
virtual bool ignorePseudoInstruction(const MachineInstr &I, const MachineBasicBlock *MBB)
static unsigned InstrCount
virtual void startBlock(MachineBasicBlock *BB)
Prepares to perform scheduling in the given block.
int64_t DFAStateInput
Definition: DFAPacketizer.h:73
void schedule() override
Orders nodes according to selected style.
MachineFunction & MF
Machine function.
Definition: ScheduleDAG.h:564
AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB)
The main low level interface to the alias analysis implementation.
AAMDNodes getAAInfo() const
Return the AA tags for the memory reference.
void buildSchedGraph(AliasAnalysis *AA, RegPressureTracker *RPTracker=nullptr, PressureDiffs *PDiffs=nullptr, LiveIntervals *LIS=nullptr, bool TrackLaneMasks=false)
Builds SUnits for the current region.
std::map< MachineInstr *, SUnit * > MIToSUnit
A description of a memory reference used in the backend.
bool alias(const MachineInstr &MI1, const MachineInstr &MI2, bool UseTBAA=true) const
void postprocessDAG()
Apply each ScheduleDAGMutation step in order.
virtual DFAPacketizer * CreateTargetScheduleState(const TargetSubtargetInfo &) const
Create machine specific model for scheduling.
virtual void endPacket(MachineBasicBlock *MBB, MachineBasicBlock::iterator MI)
uint64_t DFAInput
Definition: DFAPacketizer.h:72
MachineFunction & MF
PowerPC VSX FMA Mutation
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
Definition: MachineInstr.h:406
DFAPacketizer * ResourceTracker
virtual MachineBasicBlock::iterator addToPacket(MachineInstr &MI)
void addMutation(std::unique_ptr< ScheduleDAGMutation > Mutation)
DefaultVLIWScheduler takes ownership of the Mutation object.
Itinerary data supplied by a subtarget to be used by a target.
virtual void enterRegion(MachineBasicBlock *bb, MachineBasicBlock::iterator begin, MachineBasicBlock::iterator end, unsigned regioninstrs)
Initialize the DAG and common scheduler state for a new scheduling region.
DefaultVLIWScheduler(MachineFunction &MF, MachineLoopInfo &MLI, AliasAnalysis *AA)
AliasResult
The possible results of an alias query.
Definition: AliasAnalysis.h:78
const Value * getValue() const
Return the base address of the memory access.
unsigned getSchedClass() const
Return the scheduling class for this instruction.
Definition: MCInstrDesc.h:577
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:423
MachineInstr * getInstr() const
Returns the representative MachineInstr for this SUnit.
Definition: ScheduleDAG.h:377
#define SET(n)
Definition: MD5.cpp:68
ArrayRef< MachineMemOperand * > memoperands() const
Access to memory operands of the instruction.
Definition: MachineInstr.h:516
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
#define DFA_MAX_RESOURCES
Definition: DFAPacketizer.h:70
virtual bool shouldAddToPacket(const MachineInstr &MI)
virtual bool isSoloInstruction(const MachineInstr &MI)
virtual void exitRegion()
Called when the scheduler has finished scheduling the current region.
self_iterator getIterator()
Definition: ilist_node.h:82
Representation for a specific memory location.
const TargetInstrInfo * TII
bool canReserveResources(const MCInstrDesc *MID)
A collection of metadata nodes that might be associated with a memory access used by the alias-analys...
Definition: Metadata.h:644
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:133
static DFAInput getDFAInsnInput(const std::vector< unsigned > &InsnClass)
Return the DFAInput for an instruction class input vector.
virtual bool isLegalToPacketizeTogether(SUnit *SUI, SUnit *SUJ)
A ScheduleDAG for scheduling lists of MachineInstr.
Representation of each machine instruction.
Definition: MachineInstr.h:64
static cl::opt< bool > UseTBAA("use-tbaa-in-sched-mi", cl::Hidden, cl::init(true), cl::desc("Enable use of TBAA during MI DAG construction"))
These values represent a non-pipelined step in the execution of an instruction.
const InstrStage * endStage(unsigned ItinClassIndx) const
Return the last+1 stage of the itinerary.
#define I(x, y, z)
Definition: MD5.cpp:58
const TargetInstrInfo * TII
Target instruction information.
Definition: ScheduleDAG.h:562
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Definition: DenseMap.h:171
static cl::opt< unsigned > InstrLimit("dfa-instr-limit", cl::Hidden, cl::init(0), cl::desc("If present, stops packetizing after N instructions"))
#define DFA_MAX_RESTERMS
Definition: DFAPacketizer.h:69
bool memoperands_empty() const
Return true if we don&#39;t have any memory operands which described the memory access done by this instr...
Definition: MachineInstr.h:546
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
int64_t getOffset() const
For normal values, this is a byte offset added to the base address.
VLIWPacketizerList(MachineFunction &MF, MachineLoopInfo &MLI, AliasAnalysis *AA)
IRTranslator LLVM IR MI
DFAPacketizer(const InstrItineraryData *I, const DFAStateInput(*SIT)[2], const unsigned *SET)
std::vector< SUnit > SUnits
The scheduling units.
Definition: ScheduleDAG.h:566
#define LLVM_DEBUG(X)
Definition: Debug.h:123
void finalizeBundle(MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
finalizeBundle - Finalize a machine instruction bundle which includes a sequence of instructions star...
void PacketizeMIs(MachineBasicBlock *MBB, MachineBasicBlock::iterator BeginItr, MachineBasicBlock::iterator EndItr)
DefaultVLIWScheduler * VLIWScheduler
Scheduling unit. This is a node in the scheduling DAG.
Definition: ScheduleDAG.h:246
void reserveResources(const MCInstrDesc *MID)