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"
27db17bf38SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
28dff0c46cSDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
29dff0c46cSDimitry Andric #include "llvm/CodeGen/MachineInstrBundle.h"
30db17bf38SDimitry Andric #include "llvm/CodeGen/ScheduleDAG.h"
31139f7f9bSDimitry Andric #include "llvm/CodeGen/ScheduleDAGInstrs.h"
322cab237bSDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
332cab237bSDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
34db17bf38SDimitry Andric #include "llvm/MC/MCInstrDesc.h"
35dff0c46cSDimitry Andric #include "llvm/MC/MCInstrItineraries.h"
36d88c1a5aSDimitry Andric #include "llvm/Support/CommandLine.h"
37db17bf38SDimitry Andric #include "llvm/Support/Debug.h"
38db17bf38SDimitry Andric #include "llvm/Support/raw_ostream.h"
39db17bf38SDimitry Andric #include <algorithm>
40db17bf38SDimitry Andric #include <cassert>
41db17bf38SDimitry Andric #include <iterator>
42db17bf38SDimitry Andric #include <memory>
43db17bf38SDimitry Andric #include <vector>
443ca95b02SDimitry Andric 
45dff0c46cSDimitry Andric using namespace llvm;
46dff0c46cSDimitry Andric 
47db17bf38SDimitry Andric #define DEBUG_TYPE "packets"
48db17bf38SDimitry Andric 
49d88c1a5aSDimitry Andric static cl::opt<unsigned> InstrLimit("dfa-instr-limit", cl::Hidden,
50d88c1a5aSDimitry Andric   cl::init(0), cl::desc("If present, stops packetizing after N instructions"));
51db17bf38SDimitry Andric 
52d88c1a5aSDimitry Andric static unsigned InstrCount = 0;
53d88c1a5aSDimitry Andric 
547d523365SDimitry Andric // --------------------------------------------------------------------
557d523365SDimitry Andric // Definitions shared between DFAPacketizer.cpp and DFAPacketizerEmitter.cpp
567d523365SDimitry Andric 
addDFAFuncUnits(DFAInput Inp,unsigned FuncUnits)57db17bf38SDimitry Andric static DFAInput addDFAFuncUnits(DFAInput Inp, unsigned FuncUnits) {
587d523365SDimitry Andric   return (Inp << DFA_MAX_RESOURCES) | FuncUnits;
597d523365SDimitry Andric }
607d523365SDimitry Andric 
617d523365SDimitry Andric /// Return the DFAInput for an instruction class input vector.
627d523365SDimitry Andric /// This function is used in both DFAPacketizer.cpp and in
637d523365SDimitry Andric /// DFAPacketizerEmitter.cpp.
getDFAInsnInput(const std::vector<unsigned> & InsnClass)64db17bf38SDimitry Andric static DFAInput getDFAInsnInput(const std::vector<unsigned> &InsnClass) {
657d523365SDimitry Andric   DFAInput InsnInput = 0;
667d523365SDimitry Andric   assert((InsnClass.size() <= DFA_MAX_RESTERMS) &&
677d523365SDimitry Andric          "Exceeded maximum number of DFA terms");
687d523365SDimitry Andric   for (auto U : InsnClass)
697d523365SDimitry Andric     InsnInput = addDFAFuncUnits(InsnInput, U);
707d523365SDimitry Andric   return InsnInput;
717d523365SDimitry Andric }
72db17bf38SDimitry Andric 
737d523365SDimitry Andric // --------------------------------------------------------------------
747d523365SDimitry Andric 
DFAPacketizer(const InstrItineraryData * I,const DFAStateInput (* SIT)[2],const unsigned * SET)757d523365SDimitry Andric DFAPacketizer::DFAPacketizer(const InstrItineraryData *I,
767d523365SDimitry Andric                              const DFAStateInput (*SIT)[2],
77dff0c46cSDimitry Andric                              const unsigned *SET):
78db17bf38SDimitry Andric   InstrItins(I), DFAStateInputTable(SIT), DFAStateEntryTable(SET) {
797d523365SDimitry Andric   // Make sure DFA types are large enough for the number of terms & resources.
803ca95b02SDimitry Andric   static_assert((DFA_MAX_RESTERMS * DFA_MAX_RESOURCES) <=
813ca95b02SDimitry Andric                     (8 * sizeof(DFAInput)),
823ca95b02SDimitry Andric                 "(DFA_MAX_RESTERMS * DFA_MAX_RESOURCES) too big for DFAInput");
833ca95b02SDimitry Andric   static_assert(
843ca95b02SDimitry Andric       (DFA_MAX_RESTERMS * DFA_MAX_RESOURCES) <= (8 * sizeof(DFAStateInput)),
853ca95b02SDimitry Andric       "(DFA_MAX_RESTERMS * DFA_MAX_RESOURCES) too big for DFAStateInput");
867d523365SDimitry Andric }
87dff0c46cSDimitry Andric 
883ca95b02SDimitry Andric // Read the DFA transition table and update CachedTable.
89dff0c46cSDimitry Andric //
90dff0c46cSDimitry Andric // Format of the transition tables:
91dff0c46cSDimitry Andric // DFAStateInputTable[][2] = pairs of <Input, Transition> for all valid
92dff0c46cSDimitry Andric //                           transitions
93dff0c46cSDimitry Andric // DFAStateEntryTable[i] = Index of the first entry in DFAStateInputTable
94dff0c46cSDimitry Andric //                         for the ith state
95dff0c46cSDimitry Andric //
ReadTable(unsigned int state)96dff0c46cSDimitry Andric void DFAPacketizer::ReadTable(unsigned int state) {
97dff0c46cSDimitry Andric   unsigned ThisState = DFAStateEntryTable[state];
98dff0c46cSDimitry Andric   unsigned NextStateInTable = DFAStateEntryTable[state+1];
99dff0c46cSDimitry Andric   // Early exit in case CachedTable has already contains this
100dff0c46cSDimitry Andric   // state's transitions.
1013ca95b02SDimitry Andric   if (CachedTable.count(UnsignPair(state, DFAStateInputTable[ThisState][0])))
102dff0c46cSDimitry Andric     return;
103dff0c46cSDimitry Andric 
104dff0c46cSDimitry Andric   for (unsigned i = ThisState; i < NextStateInTable; i++)
105dff0c46cSDimitry Andric     CachedTable[UnsignPair(state, DFAStateInputTable[i][0])] =
106dff0c46cSDimitry Andric       DFAStateInputTable[i][1];
107dff0c46cSDimitry Andric }
108dff0c46cSDimitry Andric 
1093ca95b02SDimitry Andric // Return the DFAInput for an instruction class.
getInsnInput(unsigned InsnClass)1107d523365SDimitry Andric DFAInput DFAPacketizer::getInsnInput(unsigned InsnClass) {
1117d523365SDimitry Andric   // Note: this logic must match that in DFAPacketizerDefs.h for input vectors.
1127d523365SDimitry Andric   DFAInput InsnInput = 0;
1137d523365SDimitry Andric   unsigned i = 0;
1143ca95b02SDimitry Andric   (void)i;
1157d523365SDimitry Andric   for (const InstrStage *IS = InstrItins->beginStage(InsnClass),
1163ca95b02SDimitry Andric        *IE = InstrItins->endStage(InsnClass); IS != IE; ++IS) {
1177d523365SDimitry Andric     InsnInput = addDFAFuncUnits(InsnInput, IS->getUnits());
1183ca95b02SDimitry Andric     assert((i++ < DFA_MAX_RESTERMS) && "Exceeded maximum number of DFA inputs");
1197d523365SDimitry Andric   }
1207d523365SDimitry Andric   return InsnInput;
1217d523365SDimitry Andric }
1227d523365SDimitry Andric 
1233ca95b02SDimitry Andric // Return the DFAInput for an instruction class input vector.
getInsnInput(const std::vector<unsigned> & InsnClass)1247d523365SDimitry Andric DFAInput DFAPacketizer::getInsnInput(const std::vector<unsigned> &InsnClass) {
1257d523365SDimitry Andric   return getDFAInsnInput(InsnClass);
1267d523365SDimitry Andric }
127dff0c46cSDimitry Andric 
1283ca95b02SDimitry Andric // Check if the resources occupied by a MCInstrDesc are available in the
1293ca95b02SDimitry Andric // current state.
canReserveResources(const MCInstrDesc * MID)130db17bf38SDimitry Andric bool DFAPacketizer::canReserveResources(const MCInstrDesc *MID) {
131dff0c46cSDimitry Andric   unsigned InsnClass = MID->getSchedClass();
1327d523365SDimitry Andric   DFAInput InsnInput = getInsnInput(InsnClass);
1337d523365SDimitry Andric   UnsignPair StateTrans = UnsignPair(CurrentState, InsnInput);
134dff0c46cSDimitry Andric   ReadTable(CurrentState);
1353ca95b02SDimitry Andric   return CachedTable.count(StateTrans) != 0;
136dff0c46cSDimitry Andric }
137dff0c46cSDimitry Andric 
1383ca95b02SDimitry Andric // Reserve the resources occupied by a MCInstrDesc and change the current
1393ca95b02SDimitry Andric // state to reflect that change.
reserveResources(const MCInstrDesc * MID)140db17bf38SDimitry Andric void DFAPacketizer::reserveResources(const MCInstrDesc *MID) {
141dff0c46cSDimitry Andric   unsigned InsnClass = MID->getSchedClass();
1427d523365SDimitry Andric   DFAInput InsnInput = getInsnInput(InsnClass);
1437d523365SDimitry Andric   UnsignPair StateTrans = UnsignPair(CurrentState, InsnInput);
144dff0c46cSDimitry Andric   ReadTable(CurrentState);
145dff0c46cSDimitry Andric   assert(CachedTable.count(StateTrans) != 0);
146dff0c46cSDimitry Andric   CurrentState = CachedTable[StateTrans];
147dff0c46cSDimitry Andric }
148dff0c46cSDimitry Andric 
1493ca95b02SDimitry Andric // Check if the resources occupied by a machine instruction are available
1503ca95b02SDimitry Andric // in the current state.
canReserveResources(MachineInstr & MI)151db17bf38SDimitry Andric bool DFAPacketizer::canReserveResources(MachineInstr &MI) {
152db17bf38SDimitry Andric   const MCInstrDesc &MID = MI.getDesc();
153dff0c46cSDimitry Andric   return canReserveResources(&MID);
154dff0c46cSDimitry Andric }
155dff0c46cSDimitry Andric 
1563ca95b02SDimitry Andric // Reserve the resources occupied by a machine instruction and change the
1573ca95b02SDimitry Andric // current state to reflect that change.
reserveResources(MachineInstr & MI)158db17bf38SDimitry Andric void DFAPacketizer::reserveResources(MachineInstr &MI) {
159db17bf38SDimitry Andric   const MCInstrDesc &MID = MI.getDesc();
160dff0c46cSDimitry Andric   reserveResources(&MID);
161dff0c46cSDimitry Andric }
162dff0c46cSDimitry Andric 
1637ae0e2c9SDimitry Andric namespace llvm {
164db17bf38SDimitry Andric 
1653ca95b02SDimitry Andric // This class extends ScheduleDAGInstrs and overrides the schedule method
1663ca95b02SDimitry Andric // to build the dependence graph.
167dff0c46cSDimitry Andric class DefaultVLIWScheduler : public ScheduleDAGInstrs {
1687d523365SDimitry Andric private:
1697d523365SDimitry Andric   AliasAnalysis *AA;
1703ca95b02SDimitry Andric   /// Ordered list of DAG postprocessing steps.
1713ca95b02SDimitry Andric   std::vector<std::unique_ptr<ScheduleDAGMutation>> Mutations;
172db17bf38SDimitry Andric 
173dff0c46cSDimitry Andric public:
174dff0c46cSDimitry Andric   DefaultVLIWScheduler(MachineFunction &MF, MachineLoopInfo &MLI,
1757d523365SDimitry Andric                        AliasAnalysis *AA);
176db17bf38SDimitry Andric 
1773ca95b02SDimitry Andric   // Actual scheduling work.
17891bc56edSDimitry Andric   void schedule() override;
1793ca95b02SDimitry Andric 
1803ca95b02SDimitry Andric   /// DefaultVLIWScheduler takes ownership of the Mutation object.
addMutation(std::unique_ptr<ScheduleDAGMutation> Mutation)1813ca95b02SDimitry Andric   void addMutation(std::unique_ptr<ScheduleDAGMutation> Mutation) {
1823ca95b02SDimitry Andric     Mutations.push_back(std::move(Mutation));
1833ca95b02SDimitry Andric   }
184db17bf38SDimitry Andric 
1853ca95b02SDimitry Andric protected:
1863ca95b02SDimitry Andric   void postprocessDAG();
187dff0c46cSDimitry Andric };
188dff0c46cSDimitry Andric 
189db17bf38SDimitry Andric } // end namespace llvm
1903ca95b02SDimitry Andric 
DefaultVLIWScheduler(MachineFunction & MF,MachineLoopInfo & MLI,AliasAnalysis * AA)19139d628a0SDimitry Andric DefaultVLIWScheduler::DefaultVLIWScheduler(MachineFunction &MF,
1927d523365SDimitry Andric                                            MachineLoopInfo &MLI,
1937d523365SDimitry Andric                                            AliasAnalysis *AA)
1947d523365SDimitry Andric     : ScheduleDAGInstrs(MF, &MLI), AA(AA) {
1957ae0e2c9SDimitry Andric   CanHandleTerminators = true;
196dff0c46cSDimitry Andric }
197dff0c46cSDimitry Andric 
1983ca95b02SDimitry Andric /// Apply each ScheduleDAGMutation step in order.
postprocessDAG()1993ca95b02SDimitry Andric void DefaultVLIWScheduler::postprocessDAG() {
2003ca95b02SDimitry Andric   for (auto &M : Mutations)
2013ca95b02SDimitry Andric     M->apply(this);
2023ca95b02SDimitry Andric }
2033ca95b02SDimitry Andric 
schedule()204dff0c46cSDimitry Andric void DefaultVLIWScheduler::schedule() {
205dff0c46cSDimitry Andric   // Build the scheduling graph.
2067d523365SDimitry Andric   buildSchedGraph(AA);
2073ca95b02SDimitry Andric   postprocessDAG();
208dff0c46cSDimitry Andric }
209dff0c46cSDimitry Andric 
VLIWPacketizerList(MachineFunction & mf,MachineLoopInfo & mli,AliasAnalysis * aa)2103ca95b02SDimitry Andric VLIWPacketizerList::VLIWPacketizerList(MachineFunction &mf,
2113ca95b02SDimitry Andric                                        MachineLoopInfo &mli, AliasAnalysis *aa)
2123ca95b02SDimitry Andric     : MF(mf), TII(mf.getSubtarget().getInstrInfo()), AA(aa) {
21339d628a0SDimitry Andric   ResourceTracker = TII->CreateTargetScheduleState(MF.getSubtarget());
2143ca95b02SDimitry Andric   VLIWScheduler = new DefaultVLIWScheduler(MF, mli, AA);
215dff0c46cSDimitry Andric }
216dff0c46cSDimitry Andric 
~VLIWPacketizerList()217dff0c46cSDimitry Andric VLIWPacketizerList::~VLIWPacketizerList() {
2187ae0e2c9SDimitry Andric   delete VLIWScheduler;
219dff0c46cSDimitry Andric   delete ResourceTracker;
220dff0c46cSDimitry Andric }
221dff0c46cSDimitry Andric 
2223ca95b02SDimitry Andric // End the current packet, bundle packet instructions and reset DFA state.
endPacket(MachineBasicBlock * MBB,MachineBasicBlock::iterator MI)223dff0c46cSDimitry Andric void VLIWPacketizerList::endPacket(MachineBasicBlock *MBB,
2243ca95b02SDimitry Andric                                    MachineBasicBlock::iterator MI) {
2254ba319b5SDimitry Andric   LLVM_DEBUG({
226d88c1a5aSDimitry Andric     if (!CurrentPacketMIs.empty()) {
227d88c1a5aSDimitry Andric       dbgs() << "Finalizing packet:\n";
228d88c1a5aSDimitry Andric       for (MachineInstr *MI : CurrentPacketMIs)
229d88c1a5aSDimitry Andric         dbgs() << " * " << *MI;
230d88c1a5aSDimitry Andric     }
231d88c1a5aSDimitry Andric   });
232dff0c46cSDimitry Andric   if (CurrentPacketMIs.size() > 1) {
2333ca95b02SDimitry Andric     MachineInstr &MIFirst = *CurrentPacketMIs.front();
2343ca95b02SDimitry Andric     finalizeBundle(*MBB, MIFirst.getIterator(), MI.getInstrIterator());
235dff0c46cSDimitry Andric   }
236dff0c46cSDimitry Andric   CurrentPacketMIs.clear();
237dff0c46cSDimitry Andric   ResourceTracker->clearResources();
2384ba319b5SDimitry Andric   LLVM_DEBUG(dbgs() << "End packet\n");
239dff0c46cSDimitry Andric }
240dff0c46cSDimitry Andric 
2413ca95b02SDimitry Andric // Bundle machine instructions into packets.
PacketizeMIs(MachineBasicBlock * MBB,MachineBasicBlock::iterator BeginItr,MachineBasicBlock::iterator EndItr)242dff0c46cSDimitry Andric void VLIWPacketizerList::PacketizeMIs(MachineBasicBlock *MBB,
243dff0c46cSDimitry Andric                                       MachineBasicBlock::iterator BeginItr,
244dff0c46cSDimitry Andric                                       MachineBasicBlock::iterator EndItr) {
2457ae0e2c9SDimitry Andric   assert(VLIWScheduler && "VLIW Scheduler is not initialized!");
2467ae0e2c9SDimitry Andric   VLIWScheduler->startBlock(MBB);
247f785676fSDimitry Andric   VLIWScheduler->enterRegion(MBB, BeginItr, EndItr,
248f785676fSDimitry Andric                              std::distance(BeginItr, EndItr));
2497ae0e2c9SDimitry Andric   VLIWScheduler->schedule();
250dff0c46cSDimitry Andric 
2514ba319b5SDimitry Andric   LLVM_DEBUG({
2523ca95b02SDimitry Andric     dbgs() << "Scheduling DAG of the packetize region\n";
253*b5893f02SDimitry Andric     VLIWScheduler->dump();
2543ca95b02SDimitry Andric   });
2553ca95b02SDimitry Andric 
2567ae0e2c9SDimitry Andric   // Generate MI -> SU map.
2577ae0e2c9SDimitry Andric   MIToSUnit.clear();
2583ca95b02SDimitry Andric   for (SUnit &SU : VLIWScheduler->SUnits)
2593ca95b02SDimitry Andric     MIToSUnit[SU.getInstr()] = &SU;
260dff0c46cSDimitry Andric 
261d88c1a5aSDimitry Andric   bool LimitPresent = InstrLimit.getPosition();
262d88c1a5aSDimitry Andric 
263dff0c46cSDimitry Andric   // The main packetizer loop.
264dff0c46cSDimitry Andric   for (; BeginItr != EndItr; ++BeginItr) {
265d88c1a5aSDimitry Andric     if (LimitPresent) {
266d88c1a5aSDimitry Andric       if (InstrCount >= InstrLimit) {
267d88c1a5aSDimitry Andric         EndItr = BeginItr;
268d88c1a5aSDimitry Andric         break;
269d88c1a5aSDimitry Andric       }
270d88c1a5aSDimitry Andric       InstrCount++;
271d88c1a5aSDimitry Andric     }
2723ca95b02SDimitry Andric     MachineInstr &MI = *BeginItr;
2733ca95b02SDimitry Andric     initPacketizerState();
274dff0c46cSDimitry Andric 
275dff0c46cSDimitry Andric     // End the current packet if needed.
2763ca95b02SDimitry Andric     if (isSoloInstruction(MI)) {
277dff0c46cSDimitry Andric       endPacket(MBB, MI);
278dff0c46cSDimitry Andric       continue;
279dff0c46cSDimitry Andric     }
280dff0c46cSDimitry Andric 
2817ae0e2c9SDimitry Andric     // Ignore pseudo instructions.
2823ca95b02SDimitry Andric     if (ignorePseudoInstruction(MI, MBB))
2837ae0e2c9SDimitry Andric       continue;
2847ae0e2c9SDimitry Andric 
2853ca95b02SDimitry Andric     SUnit *SUI = MIToSUnit[&MI];
286dff0c46cSDimitry Andric     assert(SUI && "Missing SUnit Info!");
287dff0c46cSDimitry Andric 
288dff0c46cSDimitry Andric     // Ask DFA if machine resource is available for MI.
2894ba319b5SDimitry Andric     LLVM_DEBUG(dbgs() << "Checking resources for adding MI to packet " << MI);
2903ca95b02SDimitry Andric 
291dff0c46cSDimitry Andric     bool ResourceAvail = ResourceTracker->canReserveResources(MI);
2924ba319b5SDimitry Andric     LLVM_DEBUG({
2933ca95b02SDimitry Andric       if (ResourceAvail)
2943ca95b02SDimitry Andric         dbgs() << "  Resources are available for adding MI to packet\n";
2953ca95b02SDimitry Andric       else
2963ca95b02SDimitry Andric         dbgs() << "  Resources NOT available\n";
2973ca95b02SDimitry Andric     });
2987d523365SDimitry Andric     if (ResourceAvail && shouldAddToPacket(MI)) {
299dff0c46cSDimitry Andric       // Dependency check for MI with instructions in CurrentPacketMIs.
3003ca95b02SDimitry Andric       for (auto MJ : CurrentPacketMIs) {
3017ae0e2c9SDimitry Andric         SUnit *SUJ = MIToSUnit[MJ];
302dff0c46cSDimitry Andric         assert(SUJ && "Missing SUnit Info!");
303dff0c46cSDimitry Andric 
3044ba319b5SDimitry Andric         LLVM_DEBUG(dbgs() << "  Checking against MJ " << *MJ);
305dff0c46cSDimitry Andric         // Is it legal to packetize SUI and SUJ together.
3063ca95b02SDimitry Andric         if (!isLegalToPacketizeTogether(SUI, SUJ)) {
3074ba319b5SDimitry Andric           LLVM_DEBUG(dbgs() << "  Not legal to add MI, try to prune\n");
308dff0c46cSDimitry Andric           // Allow packetization if dependency can be pruned.
3093ca95b02SDimitry Andric           if (!isLegalToPruneDependencies(SUI, SUJ)) {
310dff0c46cSDimitry Andric             // End the packet if dependency cannot be pruned.
3114ba319b5SDimitry Andric             LLVM_DEBUG(dbgs()
3124ba319b5SDimitry Andric                        << "  Could not prune dependencies for adding MI\n");
313dff0c46cSDimitry Andric             endPacket(MBB, MI);
314dff0c46cSDimitry Andric             break;
3153ca95b02SDimitry Andric           }
3164ba319b5SDimitry Andric           LLVM_DEBUG(dbgs() << "  Pruned dependence for adding MI\n");
3173ca95b02SDimitry Andric         }
3183ca95b02SDimitry Andric       }
319dff0c46cSDimitry Andric     } else {
3204ba319b5SDimitry Andric       LLVM_DEBUG(if (ResourceAvail) dbgs()
3214ba319b5SDimitry Andric                  << "Resources are available, but instruction should not be "
3224ba319b5SDimitry Andric                     "added to packet\n  "
3234ba319b5SDimitry Andric                  << MI);
3247d523365SDimitry Andric       // End the packet if resource is not available, or if the instruction
3257d523365SDimitry Andric       // shoud not be added to the current packet.
326dff0c46cSDimitry Andric       endPacket(MBB, MI);
327dff0c46cSDimitry Andric     }
328dff0c46cSDimitry Andric 
329dff0c46cSDimitry Andric     // Add MI to the current packet.
3304ba319b5SDimitry Andric     LLVM_DEBUG(dbgs() << "* Adding MI to packet " << MI << '\n');
3313ca95b02SDimitry Andric     BeginItr = addToPacket(MI);
3323ca95b02SDimitry Andric   } // For all instructions in the packetization range.
333dff0c46cSDimitry Andric 
334dff0c46cSDimitry Andric   // End any packet left behind.
335dff0c46cSDimitry Andric   endPacket(MBB, EndItr);
3367ae0e2c9SDimitry Andric   VLIWScheduler->exitRegion();
3377ae0e2c9SDimitry Andric   VLIWScheduler->finishBlock();
338dff0c46cSDimitry Andric }
3393ca95b02SDimitry Andric 
alias(const MachineMemOperand & Op1,const MachineMemOperand & Op2,bool UseTBAA) const3402cab237bSDimitry Andric bool VLIWPacketizerList::alias(const MachineMemOperand &Op1,
3412cab237bSDimitry Andric                                const MachineMemOperand &Op2,
3422cab237bSDimitry Andric                                bool UseTBAA) const {
3432cab237bSDimitry Andric   if (!Op1.getValue() || !Op2.getValue())
3442cab237bSDimitry Andric     return true;
3452cab237bSDimitry Andric 
3462cab237bSDimitry Andric   int64_t MinOffset = std::min(Op1.getOffset(), Op2.getOffset());
3472cab237bSDimitry Andric   int64_t Overlapa = Op1.getSize() + Op1.getOffset() - MinOffset;
3482cab237bSDimitry Andric   int64_t Overlapb = Op2.getSize() + Op2.getOffset() - MinOffset;
3492cab237bSDimitry Andric 
3502cab237bSDimitry Andric   AliasResult AAResult =
3512cab237bSDimitry Andric       AA->alias(MemoryLocation(Op1.getValue(), Overlapa,
3522cab237bSDimitry Andric                                UseTBAA ? Op1.getAAInfo() : AAMDNodes()),
3532cab237bSDimitry Andric                 MemoryLocation(Op2.getValue(), Overlapb,
3542cab237bSDimitry Andric                                UseTBAA ? Op2.getAAInfo() : AAMDNodes()));
3552cab237bSDimitry Andric 
3562cab237bSDimitry Andric   return AAResult != NoAlias;
3572cab237bSDimitry Andric }
3582cab237bSDimitry Andric 
alias(const MachineInstr & MI1,const MachineInstr & MI2,bool UseTBAA) const3592cab237bSDimitry Andric bool VLIWPacketizerList::alias(const MachineInstr &MI1,
3602cab237bSDimitry Andric                                const MachineInstr &MI2,
3612cab237bSDimitry Andric                                bool UseTBAA) const {
3622cab237bSDimitry Andric   if (MI1.memoperands_empty() || MI2.memoperands_empty())
3632cab237bSDimitry Andric     return true;
3642cab237bSDimitry Andric 
3652cab237bSDimitry Andric   for (const MachineMemOperand *Op1 : MI1.memoperands())
3662cab237bSDimitry Andric     for (const MachineMemOperand *Op2 : MI2.memoperands())
3672cab237bSDimitry Andric       if (alias(*Op1, *Op2, UseTBAA))
3682cab237bSDimitry Andric         return true;
3692cab237bSDimitry Andric   return false;
3702cab237bSDimitry Andric }
3712cab237bSDimitry Andric 
3723ca95b02SDimitry Andric // Add a DAG mutation object to the ordered list.
addMutation(std::unique_ptr<ScheduleDAGMutation> Mutation)3733ca95b02SDimitry Andric void VLIWPacketizerList::addMutation(
3743ca95b02SDimitry Andric       std::unique_ptr<ScheduleDAGMutation> Mutation) {
3753ca95b02SDimitry Andric   VLIWScheduler->addMutation(std::move(Mutation));
3763ca95b02SDimitry Andric }
377