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