1*9880d681SAndroid Build Coastguard Worker //===----- HexagonPacketizer.cpp - vliw packetizer ---------------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This implements a simple VLIW packetizer using DFA. The packetizer works on
11*9880d681SAndroid Build Coastguard Worker // machine basic blocks. For each instruction I in BB, the packetizer consults
12*9880d681SAndroid Build Coastguard Worker // the DFA to see if machine resources are available to execute I. If so, the
13*9880d681SAndroid Build Coastguard Worker // packetizer checks if I depends on any instruction J in the current packet.
14*9880d681SAndroid Build Coastguard Worker // If no dependency is found, I is added to current packet and machine resource
15*9880d681SAndroid Build Coastguard Worker // is marked as taken. If any dependency is found, a target API call is made to
16*9880d681SAndroid Build Coastguard Worker // prune the dependence.
17*9880d681SAndroid Build Coastguard Worker //
18*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
19*9880d681SAndroid Build Coastguard Worker #include "HexagonRegisterInfo.h"
20*9880d681SAndroid Build Coastguard Worker #include "HexagonSubtarget.h"
21*9880d681SAndroid Build Coastguard Worker #include "HexagonTargetMachine.h"
22*9880d681SAndroid Build Coastguard Worker #include "HexagonVLIWPacketizer.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/AliasAnalysis.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineDominators.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFunctionAnalysis.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFunctionPass.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineLoopInfo.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineRegisterInfo.h"
29*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/Passes.h"
30*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/CommandLine.h"
31*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
32*9880d681SAndroid Build Coastguard Worker
33*9880d681SAndroid Build Coastguard Worker using namespace llvm;
34*9880d681SAndroid Build Coastguard Worker
35*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "packets"
36*9880d681SAndroid Build Coastguard Worker
37*9880d681SAndroid Build Coastguard Worker static cl::opt<bool> DisablePacketizer("disable-packetizer", cl::Hidden,
38*9880d681SAndroid Build Coastguard Worker cl::ZeroOrMore, cl::init(false),
39*9880d681SAndroid Build Coastguard Worker cl::desc("Disable Hexagon packetizer pass"));
40*9880d681SAndroid Build Coastguard Worker
41*9880d681SAndroid Build Coastguard Worker static cl::opt<bool> PacketizeVolatiles("hexagon-packetize-volatiles",
42*9880d681SAndroid Build Coastguard Worker cl::ZeroOrMore, cl::Hidden, cl::init(true),
43*9880d681SAndroid Build Coastguard Worker cl::desc("Allow non-solo packetization of volatile memory references"));
44*9880d681SAndroid Build Coastguard Worker
45*9880d681SAndroid Build Coastguard Worker static cl::opt<bool> EnableGenAllInsnClass("enable-gen-insn", cl::init(false),
46*9880d681SAndroid Build Coastguard Worker cl::Hidden, cl::ZeroOrMore, cl::desc("Generate all instruction with TC"));
47*9880d681SAndroid Build Coastguard Worker
48*9880d681SAndroid Build Coastguard Worker static cl::opt<bool> DisableVecDblNVStores("disable-vecdbl-nv-stores",
49*9880d681SAndroid Build Coastguard Worker cl::init(false), cl::Hidden, cl::ZeroOrMore,
50*9880d681SAndroid Build Coastguard Worker cl::desc("Disable vector double new-value-stores"));
51*9880d681SAndroid Build Coastguard Worker
52*9880d681SAndroid Build Coastguard Worker extern cl::opt<bool> ScheduleInlineAsm;
53*9880d681SAndroid Build Coastguard Worker
54*9880d681SAndroid Build Coastguard Worker namespace llvm {
55*9880d681SAndroid Build Coastguard Worker FunctionPass *createHexagonPacketizer();
56*9880d681SAndroid Build Coastguard Worker void initializeHexagonPacketizerPass(PassRegistry&);
57*9880d681SAndroid Build Coastguard Worker }
58*9880d681SAndroid Build Coastguard Worker
59*9880d681SAndroid Build Coastguard Worker
60*9880d681SAndroid Build Coastguard Worker namespace {
61*9880d681SAndroid Build Coastguard Worker class HexagonPacketizer : public MachineFunctionPass {
62*9880d681SAndroid Build Coastguard Worker public:
63*9880d681SAndroid Build Coastguard Worker static char ID;
HexagonPacketizer()64*9880d681SAndroid Build Coastguard Worker HexagonPacketizer() : MachineFunctionPass(ID) {
65*9880d681SAndroid Build Coastguard Worker initializeHexagonPacketizerPass(*PassRegistry::getPassRegistry());
66*9880d681SAndroid Build Coastguard Worker }
67*9880d681SAndroid Build Coastguard Worker
getAnalysisUsage(AnalysisUsage & AU) const68*9880d681SAndroid Build Coastguard Worker void getAnalysisUsage(AnalysisUsage &AU) const override {
69*9880d681SAndroid Build Coastguard Worker AU.setPreservesCFG();
70*9880d681SAndroid Build Coastguard Worker AU.addRequired<AAResultsWrapperPass>();
71*9880d681SAndroid Build Coastguard Worker AU.addRequired<MachineBranchProbabilityInfo>();
72*9880d681SAndroid Build Coastguard Worker AU.addRequired<MachineDominatorTree>();
73*9880d681SAndroid Build Coastguard Worker AU.addRequired<MachineLoopInfo>();
74*9880d681SAndroid Build Coastguard Worker AU.addPreserved<MachineDominatorTree>();
75*9880d681SAndroid Build Coastguard Worker AU.addPreserved<MachineLoopInfo>();
76*9880d681SAndroid Build Coastguard Worker MachineFunctionPass::getAnalysisUsage(AU);
77*9880d681SAndroid Build Coastguard Worker }
getPassName() const78*9880d681SAndroid Build Coastguard Worker const char *getPassName() const override {
79*9880d681SAndroid Build Coastguard Worker return "Hexagon Packetizer";
80*9880d681SAndroid Build Coastguard Worker }
81*9880d681SAndroid Build Coastguard Worker bool runOnMachineFunction(MachineFunction &Fn) override;
getRequiredProperties() const82*9880d681SAndroid Build Coastguard Worker MachineFunctionProperties getRequiredProperties() const override {
83*9880d681SAndroid Build Coastguard Worker return MachineFunctionProperties().set(
84*9880d681SAndroid Build Coastguard Worker MachineFunctionProperties::Property::AllVRegsAllocated);
85*9880d681SAndroid Build Coastguard Worker }
86*9880d681SAndroid Build Coastguard Worker
87*9880d681SAndroid Build Coastguard Worker private:
88*9880d681SAndroid Build Coastguard Worker const HexagonInstrInfo *HII;
89*9880d681SAndroid Build Coastguard Worker const HexagonRegisterInfo *HRI;
90*9880d681SAndroid Build Coastguard Worker };
91*9880d681SAndroid Build Coastguard Worker
92*9880d681SAndroid Build Coastguard Worker char HexagonPacketizer::ID = 0;
93*9880d681SAndroid Build Coastguard Worker }
94*9880d681SAndroid Build Coastguard Worker
95*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_BEGIN(HexagonPacketizer, "packets", "Hexagon Packetizer",
96*9880d681SAndroid Build Coastguard Worker false, false)
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)97*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
98*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfo)
99*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo)
100*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
101*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_END(HexagonPacketizer, "packets", "Hexagon Packetizer",
102*9880d681SAndroid Build Coastguard Worker false, false)
103*9880d681SAndroid Build Coastguard Worker
104*9880d681SAndroid Build Coastguard Worker
105*9880d681SAndroid Build Coastguard Worker HexagonPacketizerList::HexagonPacketizerList(MachineFunction &MF,
106*9880d681SAndroid Build Coastguard Worker MachineLoopInfo &MLI, AliasAnalysis *AA,
107*9880d681SAndroid Build Coastguard Worker const MachineBranchProbabilityInfo *MBPI)
108*9880d681SAndroid Build Coastguard Worker : VLIWPacketizerList(MF, MLI, AA), MBPI(MBPI), MLI(&MLI) {
109*9880d681SAndroid Build Coastguard Worker HII = MF.getSubtarget<HexagonSubtarget>().getInstrInfo();
110*9880d681SAndroid Build Coastguard Worker HRI = MF.getSubtarget<HexagonSubtarget>().getRegisterInfo();
111*9880d681SAndroid Build Coastguard Worker }
112*9880d681SAndroid Build Coastguard Worker
113*9880d681SAndroid Build Coastguard Worker // Check if FirstI modifies a register that SecondI reads.
hasWriteToReadDep(const MachineInstr & FirstI,const MachineInstr & SecondI,const TargetRegisterInfo * TRI)114*9880d681SAndroid Build Coastguard Worker static bool hasWriteToReadDep(const MachineInstr &FirstI,
115*9880d681SAndroid Build Coastguard Worker const MachineInstr &SecondI,
116*9880d681SAndroid Build Coastguard Worker const TargetRegisterInfo *TRI) {
117*9880d681SAndroid Build Coastguard Worker for (auto &MO : FirstI.operands()) {
118*9880d681SAndroid Build Coastguard Worker if (!MO.isReg() || !MO.isDef())
119*9880d681SAndroid Build Coastguard Worker continue;
120*9880d681SAndroid Build Coastguard Worker unsigned R = MO.getReg();
121*9880d681SAndroid Build Coastguard Worker if (SecondI.readsRegister(R, TRI))
122*9880d681SAndroid Build Coastguard Worker return true;
123*9880d681SAndroid Build Coastguard Worker }
124*9880d681SAndroid Build Coastguard Worker return false;
125*9880d681SAndroid Build Coastguard Worker }
126*9880d681SAndroid Build Coastguard Worker
127*9880d681SAndroid Build Coastguard Worker
moveInstrOut(MachineInstr * MI,MachineBasicBlock::iterator BundleIt,bool Before)128*9880d681SAndroid Build Coastguard Worker static MachineBasicBlock::iterator moveInstrOut(MachineInstr *MI,
129*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator BundleIt, bool Before) {
130*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::instr_iterator InsertPt;
131*9880d681SAndroid Build Coastguard Worker if (Before)
132*9880d681SAndroid Build Coastguard Worker InsertPt = BundleIt.getInstrIterator();
133*9880d681SAndroid Build Coastguard Worker else
134*9880d681SAndroid Build Coastguard Worker InsertPt = std::next(BundleIt).getInstrIterator();
135*9880d681SAndroid Build Coastguard Worker
136*9880d681SAndroid Build Coastguard Worker MachineBasicBlock &B = *MI->getParent();
137*9880d681SAndroid Build Coastguard Worker // The instruction should at least be bundled with the preceding instruction
138*9880d681SAndroid Build Coastguard Worker // (there will always be one, i.e. BUNDLE, if nothing else).
139*9880d681SAndroid Build Coastguard Worker assert(MI->isBundledWithPred());
140*9880d681SAndroid Build Coastguard Worker if (MI->isBundledWithSucc()) {
141*9880d681SAndroid Build Coastguard Worker MI->clearFlag(MachineInstr::BundledSucc);
142*9880d681SAndroid Build Coastguard Worker MI->clearFlag(MachineInstr::BundledPred);
143*9880d681SAndroid Build Coastguard Worker } else {
144*9880d681SAndroid Build Coastguard Worker // If it's not bundled with the successor (i.e. it is the last one
145*9880d681SAndroid Build Coastguard Worker // in the bundle), then we can simply unbundle it from the predecessor,
146*9880d681SAndroid Build Coastguard Worker // which will take care of updating the predecessor's flag.
147*9880d681SAndroid Build Coastguard Worker MI->unbundleFromPred();
148*9880d681SAndroid Build Coastguard Worker }
149*9880d681SAndroid Build Coastguard Worker B.splice(InsertPt, &B, MI);
150*9880d681SAndroid Build Coastguard Worker
151*9880d681SAndroid Build Coastguard Worker // Get the size of the bundle without asserting.
152*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::const_instr_iterator I = BundleIt.getInstrIterator();
153*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::const_instr_iterator E = B.instr_end();
154*9880d681SAndroid Build Coastguard Worker unsigned Size = 0;
155*9880d681SAndroid Build Coastguard Worker for (++I; I != E && I->isBundledWithPred(); ++I)
156*9880d681SAndroid Build Coastguard Worker ++Size;
157*9880d681SAndroid Build Coastguard Worker
158*9880d681SAndroid Build Coastguard Worker // If there are still two or more instructions, then there is nothing
159*9880d681SAndroid Build Coastguard Worker // else to be done.
160*9880d681SAndroid Build Coastguard Worker if (Size > 1)
161*9880d681SAndroid Build Coastguard Worker return BundleIt;
162*9880d681SAndroid Build Coastguard Worker
163*9880d681SAndroid Build Coastguard Worker // Otherwise, extract the single instruction out and delete the bundle.
164*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator NextIt = std::next(BundleIt);
165*9880d681SAndroid Build Coastguard Worker MachineInstr *SingleI = BundleIt->getNextNode();
166*9880d681SAndroid Build Coastguard Worker SingleI->unbundleFromPred();
167*9880d681SAndroid Build Coastguard Worker assert(!SingleI->isBundledWithSucc());
168*9880d681SAndroid Build Coastguard Worker BundleIt->eraseFromParent();
169*9880d681SAndroid Build Coastguard Worker return NextIt;
170*9880d681SAndroid Build Coastguard Worker }
171*9880d681SAndroid Build Coastguard Worker
172*9880d681SAndroid Build Coastguard Worker
runOnMachineFunction(MachineFunction & MF)173*9880d681SAndroid Build Coastguard Worker bool HexagonPacketizer::runOnMachineFunction(MachineFunction &MF) {
174*9880d681SAndroid Build Coastguard Worker if (DisablePacketizer || skipFunction(*MF.getFunction()))
175*9880d681SAndroid Build Coastguard Worker return false;
176*9880d681SAndroid Build Coastguard Worker
177*9880d681SAndroid Build Coastguard Worker HII = MF.getSubtarget<HexagonSubtarget>().getInstrInfo();
178*9880d681SAndroid Build Coastguard Worker HRI = MF.getSubtarget<HexagonSubtarget>().getRegisterInfo();
179*9880d681SAndroid Build Coastguard Worker auto &MLI = getAnalysis<MachineLoopInfo>();
180*9880d681SAndroid Build Coastguard Worker auto *AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
181*9880d681SAndroid Build Coastguard Worker auto *MBPI = &getAnalysis<MachineBranchProbabilityInfo>();
182*9880d681SAndroid Build Coastguard Worker
183*9880d681SAndroid Build Coastguard Worker if (EnableGenAllInsnClass)
184*9880d681SAndroid Build Coastguard Worker HII->genAllInsnTimingClasses(MF);
185*9880d681SAndroid Build Coastguard Worker
186*9880d681SAndroid Build Coastguard Worker // Instantiate the packetizer.
187*9880d681SAndroid Build Coastguard Worker HexagonPacketizerList Packetizer(MF, MLI, AA, MBPI);
188*9880d681SAndroid Build Coastguard Worker
189*9880d681SAndroid Build Coastguard Worker // DFA state table should not be empty.
190*9880d681SAndroid Build Coastguard Worker assert(Packetizer.getResourceTracker() && "Empty DFA table!");
191*9880d681SAndroid Build Coastguard Worker
192*9880d681SAndroid Build Coastguard Worker //
193*9880d681SAndroid Build Coastguard Worker // Loop over all basic blocks and remove KILL pseudo-instructions
194*9880d681SAndroid Build Coastguard Worker // These instructions confuse the dependence analysis. Consider:
195*9880d681SAndroid Build Coastguard Worker // D0 = ... (Insn 0)
196*9880d681SAndroid Build Coastguard Worker // R0 = KILL R0, D0 (Insn 1)
197*9880d681SAndroid Build Coastguard Worker // R0 = ... (Insn 2)
198*9880d681SAndroid Build Coastguard Worker // Here, Insn 1 will result in the dependence graph not emitting an output
199*9880d681SAndroid Build Coastguard Worker // dependence between Insn 0 and Insn 2. This can lead to incorrect
200*9880d681SAndroid Build Coastguard Worker // packetization
201*9880d681SAndroid Build Coastguard Worker //
202*9880d681SAndroid Build Coastguard Worker for (auto &MB : MF) {
203*9880d681SAndroid Build Coastguard Worker auto End = MB.end();
204*9880d681SAndroid Build Coastguard Worker auto MI = MB.begin();
205*9880d681SAndroid Build Coastguard Worker while (MI != End) {
206*9880d681SAndroid Build Coastguard Worker auto NextI = std::next(MI);
207*9880d681SAndroid Build Coastguard Worker if (MI->isKill()) {
208*9880d681SAndroid Build Coastguard Worker MB.erase(MI);
209*9880d681SAndroid Build Coastguard Worker End = MB.end();
210*9880d681SAndroid Build Coastguard Worker }
211*9880d681SAndroid Build Coastguard Worker MI = NextI;
212*9880d681SAndroid Build Coastguard Worker }
213*9880d681SAndroid Build Coastguard Worker }
214*9880d681SAndroid Build Coastguard Worker
215*9880d681SAndroid Build Coastguard Worker // Loop over all of the basic blocks.
216*9880d681SAndroid Build Coastguard Worker for (auto &MB : MF) {
217*9880d681SAndroid Build Coastguard Worker auto Begin = MB.begin(), End = MB.end();
218*9880d681SAndroid Build Coastguard Worker while (Begin != End) {
219*9880d681SAndroid Build Coastguard Worker // First the first non-boundary starting from the end of the last
220*9880d681SAndroid Build Coastguard Worker // scheduling region.
221*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator RB = Begin;
222*9880d681SAndroid Build Coastguard Worker while (RB != End && HII->isSchedulingBoundary(*RB, &MB, MF))
223*9880d681SAndroid Build Coastguard Worker ++RB;
224*9880d681SAndroid Build Coastguard Worker // First the first boundary starting from the beginning of the new
225*9880d681SAndroid Build Coastguard Worker // region.
226*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator RE = RB;
227*9880d681SAndroid Build Coastguard Worker while (RE != End && !HII->isSchedulingBoundary(*RE, &MB, MF))
228*9880d681SAndroid Build Coastguard Worker ++RE;
229*9880d681SAndroid Build Coastguard Worker // Add the scheduling boundary if it's not block end.
230*9880d681SAndroid Build Coastguard Worker if (RE != End)
231*9880d681SAndroid Build Coastguard Worker ++RE;
232*9880d681SAndroid Build Coastguard Worker // If RB == End, then RE == End.
233*9880d681SAndroid Build Coastguard Worker if (RB != End)
234*9880d681SAndroid Build Coastguard Worker Packetizer.PacketizeMIs(&MB, RB, RE);
235*9880d681SAndroid Build Coastguard Worker
236*9880d681SAndroid Build Coastguard Worker Begin = RE;
237*9880d681SAndroid Build Coastguard Worker }
238*9880d681SAndroid Build Coastguard Worker }
239*9880d681SAndroid Build Coastguard Worker
240*9880d681SAndroid Build Coastguard Worker Packetizer.unpacketizeSoloInstrs(MF);
241*9880d681SAndroid Build Coastguard Worker return true;
242*9880d681SAndroid Build Coastguard Worker }
243*9880d681SAndroid Build Coastguard Worker
244*9880d681SAndroid Build Coastguard Worker
245*9880d681SAndroid Build Coastguard Worker // Reserve resources for a constant extender. Trigger an assertion if the
246*9880d681SAndroid Build Coastguard Worker // reservation fails.
reserveResourcesForConstExt()247*9880d681SAndroid Build Coastguard Worker void HexagonPacketizerList::reserveResourcesForConstExt() {
248*9880d681SAndroid Build Coastguard Worker if (!tryAllocateResourcesForConstExt(true))
249*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Resources not available");
250*9880d681SAndroid Build Coastguard Worker }
251*9880d681SAndroid Build Coastguard Worker
canReserveResourcesForConstExt()252*9880d681SAndroid Build Coastguard Worker bool HexagonPacketizerList::canReserveResourcesForConstExt() {
253*9880d681SAndroid Build Coastguard Worker return tryAllocateResourcesForConstExt(false);
254*9880d681SAndroid Build Coastguard Worker }
255*9880d681SAndroid Build Coastguard Worker
256*9880d681SAndroid Build Coastguard Worker // Allocate resources (i.e. 4 bytes) for constant extender. If succeeded,
257*9880d681SAndroid Build Coastguard Worker // return true, otherwise, return false.
tryAllocateResourcesForConstExt(bool Reserve)258*9880d681SAndroid Build Coastguard Worker bool HexagonPacketizerList::tryAllocateResourcesForConstExt(bool Reserve) {
259*9880d681SAndroid Build Coastguard Worker auto *ExtMI = MF.CreateMachineInstr(HII->get(Hexagon::A4_ext), DebugLoc());
260*9880d681SAndroid Build Coastguard Worker bool Avail = ResourceTracker->canReserveResources(*ExtMI);
261*9880d681SAndroid Build Coastguard Worker if (Reserve && Avail)
262*9880d681SAndroid Build Coastguard Worker ResourceTracker->reserveResources(*ExtMI);
263*9880d681SAndroid Build Coastguard Worker MF.DeleteMachineInstr(ExtMI);
264*9880d681SAndroid Build Coastguard Worker return Avail;
265*9880d681SAndroid Build Coastguard Worker }
266*9880d681SAndroid Build Coastguard Worker
267*9880d681SAndroid Build Coastguard Worker
isCallDependent(const MachineInstr * MI,SDep::Kind DepType,unsigned DepReg)268*9880d681SAndroid Build Coastguard Worker bool HexagonPacketizerList::isCallDependent(const MachineInstr* MI,
269*9880d681SAndroid Build Coastguard Worker SDep::Kind DepType, unsigned DepReg) {
270*9880d681SAndroid Build Coastguard Worker // Check for LR dependence.
271*9880d681SAndroid Build Coastguard Worker if (DepReg == HRI->getRARegister())
272*9880d681SAndroid Build Coastguard Worker return true;
273*9880d681SAndroid Build Coastguard Worker
274*9880d681SAndroid Build Coastguard Worker if (HII->isDeallocRet(MI))
275*9880d681SAndroid Build Coastguard Worker if (DepReg == HRI->getFrameRegister() || DepReg == HRI->getStackRegister())
276*9880d681SAndroid Build Coastguard Worker return true;
277*9880d681SAndroid Build Coastguard Worker
278*9880d681SAndroid Build Coastguard Worker // Check if this is a predicate dependence.
279*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass* RC = HRI->getMinimalPhysRegClass(DepReg);
280*9880d681SAndroid Build Coastguard Worker if (RC == &Hexagon::PredRegsRegClass)
281*9880d681SAndroid Build Coastguard Worker return true;
282*9880d681SAndroid Build Coastguard Worker
283*9880d681SAndroid Build Coastguard Worker // Assumes that the first operand of the CALLr is the function address.
284*9880d681SAndroid Build Coastguard Worker if (HII->isIndirectCall(MI) && (DepType == SDep::Data)) {
285*9880d681SAndroid Build Coastguard Worker MachineOperand MO = MI->getOperand(0);
286*9880d681SAndroid Build Coastguard Worker if (MO.isReg() && MO.isUse() && (MO.getReg() == DepReg))
287*9880d681SAndroid Build Coastguard Worker return true;
288*9880d681SAndroid Build Coastguard Worker }
289*9880d681SAndroid Build Coastguard Worker
290*9880d681SAndroid Build Coastguard Worker return false;
291*9880d681SAndroid Build Coastguard Worker }
292*9880d681SAndroid Build Coastguard Worker
isRegDependence(const SDep::Kind DepType)293*9880d681SAndroid Build Coastguard Worker static bool isRegDependence(const SDep::Kind DepType) {
294*9880d681SAndroid Build Coastguard Worker return DepType == SDep::Data || DepType == SDep::Anti ||
295*9880d681SAndroid Build Coastguard Worker DepType == SDep::Output;
296*9880d681SAndroid Build Coastguard Worker }
297*9880d681SAndroid Build Coastguard Worker
isDirectJump(const MachineInstr * MI)298*9880d681SAndroid Build Coastguard Worker static bool isDirectJump(const MachineInstr* MI) {
299*9880d681SAndroid Build Coastguard Worker return MI->getOpcode() == Hexagon::J2_jump;
300*9880d681SAndroid Build Coastguard Worker }
301*9880d681SAndroid Build Coastguard Worker
isSchedBarrier(const MachineInstr * MI)302*9880d681SAndroid Build Coastguard Worker static bool isSchedBarrier(const MachineInstr* MI) {
303*9880d681SAndroid Build Coastguard Worker switch (MI->getOpcode()) {
304*9880d681SAndroid Build Coastguard Worker case Hexagon::Y2_barrier:
305*9880d681SAndroid Build Coastguard Worker return true;
306*9880d681SAndroid Build Coastguard Worker }
307*9880d681SAndroid Build Coastguard Worker return false;
308*9880d681SAndroid Build Coastguard Worker }
309*9880d681SAndroid Build Coastguard Worker
isControlFlow(const MachineInstr * MI)310*9880d681SAndroid Build Coastguard Worker static bool isControlFlow(const MachineInstr* MI) {
311*9880d681SAndroid Build Coastguard Worker return (MI->getDesc().isTerminator() || MI->getDesc().isCall());
312*9880d681SAndroid Build Coastguard Worker }
313*9880d681SAndroid Build Coastguard Worker
314*9880d681SAndroid Build Coastguard Worker
315*9880d681SAndroid Build Coastguard Worker /// Returns true if the instruction modifies a callee-saved register.
doesModifyCalleeSavedReg(const MachineInstr * MI,const TargetRegisterInfo * TRI)316*9880d681SAndroid Build Coastguard Worker static bool doesModifyCalleeSavedReg(const MachineInstr *MI,
317*9880d681SAndroid Build Coastguard Worker const TargetRegisterInfo *TRI) {
318*9880d681SAndroid Build Coastguard Worker const MachineFunction &MF = *MI->getParent()->getParent();
319*9880d681SAndroid Build Coastguard Worker for (auto *CSR = TRI->getCalleeSavedRegs(&MF); CSR && *CSR; ++CSR)
320*9880d681SAndroid Build Coastguard Worker if (MI->modifiesRegister(*CSR, TRI))
321*9880d681SAndroid Build Coastguard Worker return true;
322*9880d681SAndroid Build Coastguard Worker return false;
323*9880d681SAndroid Build Coastguard Worker }
324*9880d681SAndroid Build Coastguard Worker
325*9880d681SAndroid Build Coastguard Worker // TODO: MI->isIndirectBranch() and IsRegisterJump(MI)
326*9880d681SAndroid Build Coastguard Worker // Returns true if an instruction can be promoted to .new predicate or
327*9880d681SAndroid Build Coastguard Worker // new-value store.
isNewifiable(const MachineInstr * MI)328*9880d681SAndroid Build Coastguard Worker bool HexagonPacketizerList::isNewifiable(const MachineInstr* MI) {
329*9880d681SAndroid Build Coastguard Worker return HII->isCondInst(MI) || MI->isReturn() || HII->mayBeNewStore(MI);
330*9880d681SAndroid Build Coastguard Worker }
331*9880d681SAndroid Build Coastguard Worker
332*9880d681SAndroid Build Coastguard Worker // Promote an instructiont to its .cur form.
333*9880d681SAndroid Build Coastguard Worker // At this time, we have already made a call to canPromoteToDotCur and made
334*9880d681SAndroid Build Coastguard Worker // sure that it can *indeed* be promoted.
promoteToDotCur(MachineInstr * MI,SDep::Kind DepType,MachineBasicBlock::iterator & MII,const TargetRegisterClass * RC)335*9880d681SAndroid Build Coastguard Worker bool HexagonPacketizerList::promoteToDotCur(MachineInstr* MI,
336*9880d681SAndroid Build Coastguard Worker SDep::Kind DepType, MachineBasicBlock::iterator &MII,
337*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass* RC) {
338*9880d681SAndroid Build Coastguard Worker assert(DepType == SDep::Data);
339*9880d681SAndroid Build Coastguard Worker int CurOpcode = HII->getDotCurOp(MI);
340*9880d681SAndroid Build Coastguard Worker MI->setDesc(HII->get(CurOpcode));
341*9880d681SAndroid Build Coastguard Worker return true;
342*9880d681SAndroid Build Coastguard Worker }
343*9880d681SAndroid Build Coastguard Worker
cleanUpDotCur()344*9880d681SAndroid Build Coastguard Worker void HexagonPacketizerList::cleanUpDotCur() {
345*9880d681SAndroid Build Coastguard Worker MachineInstr *MI = NULL;
346*9880d681SAndroid Build Coastguard Worker for (auto BI : CurrentPacketMIs) {
347*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Cleanup packet has "; BI->dump(););
348*9880d681SAndroid Build Coastguard Worker if (BI->getOpcode() == Hexagon::V6_vL32b_cur_ai) {
349*9880d681SAndroid Build Coastguard Worker MI = BI;
350*9880d681SAndroid Build Coastguard Worker continue;
351*9880d681SAndroid Build Coastguard Worker }
352*9880d681SAndroid Build Coastguard Worker if (MI) {
353*9880d681SAndroid Build Coastguard Worker for (auto &MO : BI->operands())
354*9880d681SAndroid Build Coastguard Worker if (MO.isReg() && MO.getReg() == MI->getOperand(0).getReg())
355*9880d681SAndroid Build Coastguard Worker return;
356*9880d681SAndroid Build Coastguard Worker }
357*9880d681SAndroid Build Coastguard Worker }
358*9880d681SAndroid Build Coastguard Worker if (!MI)
359*9880d681SAndroid Build Coastguard Worker return;
360*9880d681SAndroid Build Coastguard Worker // We did not find a use of the CUR, so de-cur it.
361*9880d681SAndroid Build Coastguard Worker MI->setDesc(HII->get(Hexagon::V6_vL32b_ai));
362*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Demoted CUR "; MI->dump(););
363*9880d681SAndroid Build Coastguard Worker }
364*9880d681SAndroid Build Coastguard Worker
365*9880d681SAndroid Build Coastguard Worker // Check to see if an instruction can be dot cur.
canPromoteToDotCur(const MachineInstr * MI,const SUnit * PacketSU,unsigned DepReg,MachineBasicBlock::iterator & MII,const TargetRegisterClass * RC)366*9880d681SAndroid Build Coastguard Worker bool HexagonPacketizerList::canPromoteToDotCur(const MachineInstr *MI,
367*9880d681SAndroid Build Coastguard Worker const SUnit *PacketSU, unsigned DepReg, MachineBasicBlock::iterator &MII,
368*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RC) {
369*9880d681SAndroid Build Coastguard Worker if (!HII->isV60VectorInstruction(MI))
370*9880d681SAndroid Build Coastguard Worker return false;
371*9880d681SAndroid Build Coastguard Worker if (!HII->isV60VectorInstruction(&*MII))
372*9880d681SAndroid Build Coastguard Worker return false;
373*9880d681SAndroid Build Coastguard Worker
374*9880d681SAndroid Build Coastguard Worker // Already a dot new instruction.
375*9880d681SAndroid Build Coastguard Worker if (HII->isDotCurInst(MI) && !HII->mayBeCurLoad(MI))
376*9880d681SAndroid Build Coastguard Worker return false;
377*9880d681SAndroid Build Coastguard Worker
378*9880d681SAndroid Build Coastguard Worker if (!HII->mayBeCurLoad(MI))
379*9880d681SAndroid Build Coastguard Worker return false;
380*9880d681SAndroid Build Coastguard Worker
381*9880d681SAndroid Build Coastguard Worker // The "cur value" cannot come from inline asm.
382*9880d681SAndroid Build Coastguard Worker if (PacketSU->getInstr()->isInlineAsm())
383*9880d681SAndroid Build Coastguard Worker return false;
384*9880d681SAndroid Build Coastguard Worker
385*9880d681SAndroid Build Coastguard Worker // Make sure candidate instruction uses cur.
386*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Can we DOT Cur Vector MI\n";
387*9880d681SAndroid Build Coastguard Worker MI->dump();
388*9880d681SAndroid Build Coastguard Worker dbgs() << "in packet\n";);
389*9880d681SAndroid Build Coastguard Worker MachineInstr &MJ = *MII;
390*9880d681SAndroid Build Coastguard Worker DEBUG({
391*9880d681SAndroid Build Coastguard Worker dbgs() << "Checking CUR against ";
392*9880d681SAndroid Build Coastguard Worker MJ.dump();
393*9880d681SAndroid Build Coastguard Worker });
394*9880d681SAndroid Build Coastguard Worker unsigned DestReg = MI->getOperand(0).getReg();
395*9880d681SAndroid Build Coastguard Worker bool FoundMatch = false;
396*9880d681SAndroid Build Coastguard Worker for (auto &MO : MJ.operands())
397*9880d681SAndroid Build Coastguard Worker if (MO.isReg() && MO.getReg() == DestReg)
398*9880d681SAndroid Build Coastguard Worker FoundMatch = true;
399*9880d681SAndroid Build Coastguard Worker if (!FoundMatch)
400*9880d681SAndroid Build Coastguard Worker return false;
401*9880d681SAndroid Build Coastguard Worker
402*9880d681SAndroid Build Coastguard Worker // Check for existing uses of a vector register within the packet which
403*9880d681SAndroid Build Coastguard Worker // would be affected by converting a vector load into .cur formt.
404*9880d681SAndroid Build Coastguard Worker for (auto BI : CurrentPacketMIs) {
405*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "packet has "; BI->dump(););
406*9880d681SAndroid Build Coastguard Worker if (BI->readsRegister(DepReg, MF.getSubtarget().getRegisterInfo()))
407*9880d681SAndroid Build Coastguard Worker return false;
408*9880d681SAndroid Build Coastguard Worker }
409*9880d681SAndroid Build Coastguard Worker
410*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Can Dot CUR MI\n"; MI->dump(););
411*9880d681SAndroid Build Coastguard Worker // We can convert the opcode into a .cur.
412*9880d681SAndroid Build Coastguard Worker return true;
413*9880d681SAndroid Build Coastguard Worker }
414*9880d681SAndroid Build Coastguard Worker
415*9880d681SAndroid Build Coastguard Worker // Promote an instruction to its .new form. At this time, we have already
416*9880d681SAndroid Build Coastguard Worker // made a call to canPromoteToDotNew and made sure that it can *indeed* be
417*9880d681SAndroid Build Coastguard Worker // promoted.
promoteToDotNew(MachineInstr * MI,SDep::Kind DepType,MachineBasicBlock::iterator & MII,const TargetRegisterClass * RC)418*9880d681SAndroid Build Coastguard Worker bool HexagonPacketizerList::promoteToDotNew(MachineInstr* MI,
419*9880d681SAndroid Build Coastguard Worker SDep::Kind DepType, MachineBasicBlock::iterator &MII,
420*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass* RC) {
421*9880d681SAndroid Build Coastguard Worker assert (DepType == SDep::Data);
422*9880d681SAndroid Build Coastguard Worker int NewOpcode;
423*9880d681SAndroid Build Coastguard Worker if (RC == &Hexagon::PredRegsRegClass)
424*9880d681SAndroid Build Coastguard Worker NewOpcode = HII->getDotNewPredOp(MI, MBPI);
425*9880d681SAndroid Build Coastguard Worker else
426*9880d681SAndroid Build Coastguard Worker NewOpcode = HII->getDotNewOp(MI);
427*9880d681SAndroid Build Coastguard Worker MI->setDesc(HII->get(NewOpcode));
428*9880d681SAndroid Build Coastguard Worker return true;
429*9880d681SAndroid Build Coastguard Worker }
430*9880d681SAndroid Build Coastguard Worker
demoteToDotOld(MachineInstr * MI)431*9880d681SAndroid Build Coastguard Worker bool HexagonPacketizerList::demoteToDotOld(MachineInstr* MI) {
432*9880d681SAndroid Build Coastguard Worker int NewOpcode = HII->getDotOldOp(MI->getOpcode());
433*9880d681SAndroid Build Coastguard Worker MI->setDesc(HII->get(NewOpcode));
434*9880d681SAndroid Build Coastguard Worker return true;
435*9880d681SAndroid Build Coastguard Worker }
436*9880d681SAndroid Build Coastguard Worker
437*9880d681SAndroid Build Coastguard Worker enum PredicateKind {
438*9880d681SAndroid Build Coastguard Worker PK_False,
439*9880d681SAndroid Build Coastguard Worker PK_True,
440*9880d681SAndroid Build Coastguard Worker PK_Unknown
441*9880d681SAndroid Build Coastguard Worker };
442*9880d681SAndroid Build Coastguard Worker
443*9880d681SAndroid Build Coastguard Worker /// Returns true if an instruction is predicated on p0 and false if it's
444*9880d681SAndroid Build Coastguard Worker /// predicated on !p0.
getPredicateSense(const MachineInstr & MI,const HexagonInstrInfo * HII)445*9880d681SAndroid Build Coastguard Worker static PredicateKind getPredicateSense(const MachineInstr &MI,
446*9880d681SAndroid Build Coastguard Worker const HexagonInstrInfo *HII) {
447*9880d681SAndroid Build Coastguard Worker if (!HII->isPredicated(MI))
448*9880d681SAndroid Build Coastguard Worker return PK_Unknown;
449*9880d681SAndroid Build Coastguard Worker if (HII->isPredicatedTrue(MI))
450*9880d681SAndroid Build Coastguard Worker return PK_True;
451*9880d681SAndroid Build Coastguard Worker return PK_False;
452*9880d681SAndroid Build Coastguard Worker }
453*9880d681SAndroid Build Coastguard Worker
getPostIncrementOperand(const MachineInstr * MI,const HexagonInstrInfo * HII)454*9880d681SAndroid Build Coastguard Worker static const MachineOperand &getPostIncrementOperand(const MachineInstr *MI,
455*9880d681SAndroid Build Coastguard Worker const HexagonInstrInfo *HII) {
456*9880d681SAndroid Build Coastguard Worker assert(HII->isPostIncrement(MI) && "Not a post increment operation.");
457*9880d681SAndroid Build Coastguard Worker #ifndef NDEBUG
458*9880d681SAndroid Build Coastguard Worker // Post Increment means duplicates. Use dense map to find duplicates in the
459*9880d681SAndroid Build Coastguard Worker // list. Caution: Densemap initializes with the minimum of 64 buckets,
460*9880d681SAndroid Build Coastguard Worker // whereas there are at most 5 operands in the post increment.
461*9880d681SAndroid Build Coastguard Worker DenseSet<unsigned> DefRegsSet;
462*9880d681SAndroid Build Coastguard Worker for (auto &MO : MI->operands())
463*9880d681SAndroid Build Coastguard Worker if (MO.isReg() && MO.isDef())
464*9880d681SAndroid Build Coastguard Worker DefRegsSet.insert(MO.getReg());
465*9880d681SAndroid Build Coastguard Worker
466*9880d681SAndroid Build Coastguard Worker for (auto &MO : MI->operands())
467*9880d681SAndroid Build Coastguard Worker if (MO.isReg() && MO.isUse() && DefRegsSet.count(MO.getReg()))
468*9880d681SAndroid Build Coastguard Worker return MO;
469*9880d681SAndroid Build Coastguard Worker #else
470*9880d681SAndroid Build Coastguard Worker if (MI->mayLoad()) {
471*9880d681SAndroid Build Coastguard Worker const MachineOperand &Op1 = MI->getOperand(1);
472*9880d681SAndroid Build Coastguard Worker // The 2nd operand is always the post increment operand in load.
473*9880d681SAndroid Build Coastguard Worker assert(Op1.isReg() && "Post increment operand has be to a register.");
474*9880d681SAndroid Build Coastguard Worker return Op1;
475*9880d681SAndroid Build Coastguard Worker }
476*9880d681SAndroid Build Coastguard Worker if (MI->getDesc().mayStore()) {
477*9880d681SAndroid Build Coastguard Worker const MachineOperand &Op0 = MI->getOperand(0);
478*9880d681SAndroid Build Coastguard Worker // The 1st operand is always the post increment operand in store.
479*9880d681SAndroid Build Coastguard Worker assert(Op0.isReg() && "Post increment operand has be to a register.");
480*9880d681SAndroid Build Coastguard Worker return Op0;
481*9880d681SAndroid Build Coastguard Worker }
482*9880d681SAndroid Build Coastguard Worker #endif
483*9880d681SAndroid Build Coastguard Worker // we should never come here.
484*9880d681SAndroid Build Coastguard Worker llvm_unreachable("mayLoad or mayStore not set for Post Increment operation");
485*9880d681SAndroid Build Coastguard Worker }
486*9880d681SAndroid Build Coastguard Worker
487*9880d681SAndroid Build Coastguard Worker // Get the value being stored.
getStoreValueOperand(const MachineInstr * MI)488*9880d681SAndroid Build Coastguard Worker static const MachineOperand& getStoreValueOperand(const MachineInstr *MI) {
489*9880d681SAndroid Build Coastguard Worker // value being stored is always the last operand.
490*9880d681SAndroid Build Coastguard Worker return MI->getOperand(MI->getNumOperands()-1);
491*9880d681SAndroid Build Coastguard Worker }
492*9880d681SAndroid Build Coastguard Worker
isLoadAbsSet(const MachineInstr * MI)493*9880d681SAndroid Build Coastguard Worker static bool isLoadAbsSet(const MachineInstr *MI) {
494*9880d681SAndroid Build Coastguard Worker unsigned Opc = MI->getOpcode();
495*9880d681SAndroid Build Coastguard Worker switch (Opc) {
496*9880d681SAndroid Build Coastguard Worker case Hexagon::L4_loadrd_ap:
497*9880d681SAndroid Build Coastguard Worker case Hexagon::L4_loadrb_ap:
498*9880d681SAndroid Build Coastguard Worker case Hexagon::L4_loadrh_ap:
499*9880d681SAndroid Build Coastguard Worker case Hexagon::L4_loadrub_ap:
500*9880d681SAndroid Build Coastguard Worker case Hexagon::L4_loadruh_ap:
501*9880d681SAndroid Build Coastguard Worker case Hexagon::L4_loadri_ap:
502*9880d681SAndroid Build Coastguard Worker return true;
503*9880d681SAndroid Build Coastguard Worker }
504*9880d681SAndroid Build Coastguard Worker return false;
505*9880d681SAndroid Build Coastguard Worker }
506*9880d681SAndroid Build Coastguard Worker
getAbsSetOperand(const MachineInstr * MI)507*9880d681SAndroid Build Coastguard Worker static const MachineOperand &getAbsSetOperand(const MachineInstr *MI) {
508*9880d681SAndroid Build Coastguard Worker assert(isLoadAbsSet(MI));
509*9880d681SAndroid Build Coastguard Worker return MI->getOperand(1);
510*9880d681SAndroid Build Coastguard Worker }
511*9880d681SAndroid Build Coastguard Worker
512*9880d681SAndroid Build Coastguard Worker
513*9880d681SAndroid Build Coastguard Worker // Can be new value store?
514*9880d681SAndroid Build Coastguard Worker // Following restrictions are to be respected in convert a store into
515*9880d681SAndroid Build Coastguard Worker // a new value store.
516*9880d681SAndroid Build Coastguard Worker // 1. If an instruction uses auto-increment, its address register cannot
517*9880d681SAndroid Build Coastguard Worker // be a new-value register. Arch Spec 5.4.2.1
518*9880d681SAndroid Build Coastguard Worker // 2. If an instruction uses absolute-set addressing mode, its address
519*9880d681SAndroid Build Coastguard Worker // register cannot be a new-value register. Arch Spec 5.4.2.1.
520*9880d681SAndroid Build Coastguard Worker // 3. If an instruction produces a 64-bit result, its registers cannot be used
521*9880d681SAndroid Build Coastguard Worker // as new-value registers. Arch Spec 5.4.2.2.
522*9880d681SAndroid Build Coastguard Worker // 4. If the instruction that sets the new-value register is conditional, then
523*9880d681SAndroid Build Coastguard Worker // the instruction that uses the new-value register must also be conditional,
524*9880d681SAndroid Build Coastguard Worker // and both must always have their predicates evaluate identically.
525*9880d681SAndroid Build Coastguard Worker // Arch Spec 5.4.2.3.
526*9880d681SAndroid Build Coastguard Worker // 5. There is an implied restriction that a packet cannot have another store,
527*9880d681SAndroid Build Coastguard Worker // if there is a new value store in the packet. Corollary: if there is
528*9880d681SAndroid Build Coastguard Worker // already a store in a packet, there can not be a new value store.
529*9880d681SAndroid Build Coastguard Worker // Arch Spec: 3.4.4.2
canPromoteToNewValueStore(const MachineInstr * MI,const MachineInstr * PacketMI,unsigned DepReg)530*9880d681SAndroid Build Coastguard Worker bool HexagonPacketizerList::canPromoteToNewValueStore(const MachineInstr *MI,
531*9880d681SAndroid Build Coastguard Worker const MachineInstr *PacketMI, unsigned DepReg) {
532*9880d681SAndroid Build Coastguard Worker // Make sure we are looking at the store, that can be promoted.
533*9880d681SAndroid Build Coastguard Worker if (!HII->mayBeNewStore(MI))
534*9880d681SAndroid Build Coastguard Worker return false;
535*9880d681SAndroid Build Coastguard Worker
536*9880d681SAndroid Build Coastguard Worker // Make sure there is dependency and can be new value'd.
537*9880d681SAndroid Build Coastguard Worker const MachineOperand &Val = getStoreValueOperand(MI);
538*9880d681SAndroid Build Coastguard Worker if (Val.isReg() && Val.getReg() != DepReg)
539*9880d681SAndroid Build Coastguard Worker return false;
540*9880d681SAndroid Build Coastguard Worker
541*9880d681SAndroid Build Coastguard Worker const MCInstrDesc& MCID = PacketMI->getDesc();
542*9880d681SAndroid Build Coastguard Worker
543*9880d681SAndroid Build Coastguard Worker // First operand is always the result.
544*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *PacketRC = HII->getRegClass(MCID, 0, HRI, MF);
545*9880d681SAndroid Build Coastguard Worker // Double regs can not feed into new value store: PRM section: 5.4.2.2.
546*9880d681SAndroid Build Coastguard Worker if (PacketRC == &Hexagon::DoubleRegsRegClass)
547*9880d681SAndroid Build Coastguard Worker return false;
548*9880d681SAndroid Build Coastguard Worker
549*9880d681SAndroid Build Coastguard Worker // New-value stores are of class NV (slot 0), dual stores require class ST
550*9880d681SAndroid Build Coastguard Worker // in slot 0 (PRM 5.5).
551*9880d681SAndroid Build Coastguard Worker for (auto I : CurrentPacketMIs) {
552*9880d681SAndroid Build Coastguard Worker SUnit *PacketSU = MIToSUnit.find(I)->second;
553*9880d681SAndroid Build Coastguard Worker if (PacketSU->getInstr()->mayStore())
554*9880d681SAndroid Build Coastguard Worker return false;
555*9880d681SAndroid Build Coastguard Worker }
556*9880d681SAndroid Build Coastguard Worker
557*9880d681SAndroid Build Coastguard Worker // Make sure it's NOT the post increment register that we are going to
558*9880d681SAndroid Build Coastguard Worker // new value.
559*9880d681SAndroid Build Coastguard Worker if (HII->isPostIncrement(MI) &&
560*9880d681SAndroid Build Coastguard Worker getPostIncrementOperand(MI, HII).getReg() == DepReg) {
561*9880d681SAndroid Build Coastguard Worker return false;
562*9880d681SAndroid Build Coastguard Worker }
563*9880d681SAndroid Build Coastguard Worker
564*9880d681SAndroid Build Coastguard Worker if (HII->isPostIncrement(PacketMI) && PacketMI->mayLoad() &&
565*9880d681SAndroid Build Coastguard Worker getPostIncrementOperand(PacketMI, HII).getReg() == DepReg) {
566*9880d681SAndroid Build Coastguard Worker // If source is post_inc, or absolute-set addressing, it can not feed
567*9880d681SAndroid Build Coastguard Worker // into new value store
568*9880d681SAndroid Build Coastguard Worker // r3 = memw(r2++#4)
569*9880d681SAndroid Build Coastguard Worker // memw(r30 + #-1404) = r2.new -> can not be new value store
570*9880d681SAndroid Build Coastguard Worker // arch spec section: 5.4.2.1.
571*9880d681SAndroid Build Coastguard Worker return false;
572*9880d681SAndroid Build Coastguard Worker }
573*9880d681SAndroid Build Coastguard Worker
574*9880d681SAndroid Build Coastguard Worker if (isLoadAbsSet(PacketMI) && getAbsSetOperand(PacketMI).getReg() == DepReg)
575*9880d681SAndroid Build Coastguard Worker return false;
576*9880d681SAndroid Build Coastguard Worker
577*9880d681SAndroid Build Coastguard Worker // If the source that feeds the store is predicated, new value store must
578*9880d681SAndroid Build Coastguard Worker // also be predicated.
579*9880d681SAndroid Build Coastguard Worker if (HII->isPredicated(*PacketMI)) {
580*9880d681SAndroid Build Coastguard Worker if (!HII->isPredicated(*MI))
581*9880d681SAndroid Build Coastguard Worker return false;
582*9880d681SAndroid Build Coastguard Worker
583*9880d681SAndroid Build Coastguard Worker // Check to make sure that they both will have their predicates
584*9880d681SAndroid Build Coastguard Worker // evaluate identically.
585*9880d681SAndroid Build Coastguard Worker unsigned predRegNumSrc = 0;
586*9880d681SAndroid Build Coastguard Worker unsigned predRegNumDst = 0;
587*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass* predRegClass = nullptr;
588*9880d681SAndroid Build Coastguard Worker
589*9880d681SAndroid Build Coastguard Worker // Get predicate register used in the source instruction.
590*9880d681SAndroid Build Coastguard Worker for (auto &MO : PacketMI->operands()) {
591*9880d681SAndroid Build Coastguard Worker if (!MO.isReg())
592*9880d681SAndroid Build Coastguard Worker continue;
593*9880d681SAndroid Build Coastguard Worker predRegNumSrc = MO.getReg();
594*9880d681SAndroid Build Coastguard Worker predRegClass = HRI->getMinimalPhysRegClass(predRegNumSrc);
595*9880d681SAndroid Build Coastguard Worker if (predRegClass == &Hexagon::PredRegsRegClass)
596*9880d681SAndroid Build Coastguard Worker break;
597*9880d681SAndroid Build Coastguard Worker }
598*9880d681SAndroid Build Coastguard Worker assert((predRegClass == &Hexagon::PredRegsRegClass) &&
599*9880d681SAndroid Build Coastguard Worker "predicate register not found in a predicated PacketMI instruction");
600*9880d681SAndroid Build Coastguard Worker
601*9880d681SAndroid Build Coastguard Worker // Get predicate register used in new-value store instruction.
602*9880d681SAndroid Build Coastguard Worker for (auto &MO : MI->operands()) {
603*9880d681SAndroid Build Coastguard Worker if (!MO.isReg())
604*9880d681SAndroid Build Coastguard Worker continue;
605*9880d681SAndroid Build Coastguard Worker predRegNumDst = MO.getReg();
606*9880d681SAndroid Build Coastguard Worker predRegClass = HRI->getMinimalPhysRegClass(predRegNumDst);
607*9880d681SAndroid Build Coastguard Worker if (predRegClass == &Hexagon::PredRegsRegClass)
608*9880d681SAndroid Build Coastguard Worker break;
609*9880d681SAndroid Build Coastguard Worker }
610*9880d681SAndroid Build Coastguard Worker assert((predRegClass == &Hexagon::PredRegsRegClass) &&
611*9880d681SAndroid Build Coastguard Worker "predicate register not found in a predicated MI instruction");
612*9880d681SAndroid Build Coastguard Worker
613*9880d681SAndroid Build Coastguard Worker // New-value register producer and user (store) need to satisfy these
614*9880d681SAndroid Build Coastguard Worker // constraints:
615*9880d681SAndroid Build Coastguard Worker // 1) Both instructions should be predicated on the same register.
616*9880d681SAndroid Build Coastguard Worker // 2) If producer of the new-value register is .new predicated then store
617*9880d681SAndroid Build Coastguard Worker // should also be .new predicated and if producer is not .new predicated
618*9880d681SAndroid Build Coastguard Worker // then store should not be .new predicated.
619*9880d681SAndroid Build Coastguard Worker // 3) Both new-value register producer and user should have same predicate
620*9880d681SAndroid Build Coastguard Worker // sense, i.e, either both should be negated or both should be non-negated.
621*9880d681SAndroid Build Coastguard Worker if (predRegNumDst != predRegNumSrc ||
622*9880d681SAndroid Build Coastguard Worker HII->isDotNewInst(PacketMI) != HII->isDotNewInst(MI) ||
623*9880d681SAndroid Build Coastguard Worker getPredicateSense(*MI, HII) != getPredicateSense(*PacketMI, HII))
624*9880d681SAndroid Build Coastguard Worker return false;
625*9880d681SAndroid Build Coastguard Worker }
626*9880d681SAndroid Build Coastguard Worker
627*9880d681SAndroid Build Coastguard Worker // Make sure that other than the new-value register no other store instruction
628*9880d681SAndroid Build Coastguard Worker // register has been modified in the same packet. Predicate registers can be
629*9880d681SAndroid Build Coastguard Worker // modified by they should not be modified between the producer and the store
630*9880d681SAndroid Build Coastguard Worker // instruction as it will make them both conditional on different values.
631*9880d681SAndroid Build Coastguard Worker // We already know this to be true for all the instructions before and
632*9880d681SAndroid Build Coastguard Worker // including PacketMI. Howerver, we need to perform the check for the
633*9880d681SAndroid Build Coastguard Worker // remaining instructions in the packet.
634*9880d681SAndroid Build Coastguard Worker
635*9880d681SAndroid Build Coastguard Worker unsigned StartCheck = 0;
636*9880d681SAndroid Build Coastguard Worker
637*9880d681SAndroid Build Coastguard Worker for (auto I : CurrentPacketMIs) {
638*9880d681SAndroid Build Coastguard Worker SUnit *TempSU = MIToSUnit.find(I)->second;
639*9880d681SAndroid Build Coastguard Worker MachineInstr* TempMI = TempSU->getInstr();
640*9880d681SAndroid Build Coastguard Worker
641*9880d681SAndroid Build Coastguard Worker // Following condition is true for all the instructions until PacketMI is
642*9880d681SAndroid Build Coastguard Worker // reached (StartCheck is set to 0 before the for loop).
643*9880d681SAndroid Build Coastguard Worker // StartCheck flag is 1 for all the instructions after PacketMI.
644*9880d681SAndroid Build Coastguard Worker if (TempMI != PacketMI && !StartCheck) // Start processing only after
645*9880d681SAndroid Build Coastguard Worker continue; // encountering PacketMI.
646*9880d681SAndroid Build Coastguard Worker
647*9880d681SAndroid Build Coastguard Worker StartCheck = 1;
648*9880d681SAndroid Build Coastguard Worker if (TempMI == PacketMI) // We don't want to check PacketMI for dependence.
649*9880d681SAndroid Build Coastguard Worker continue;
650*9880d681SAndroid Build Coastguard Worker
651*9880d681SAndroid Build Coastguard Worker for (auto &MO : MI->operands())
652*9880d681SAndroid Build Coastguard Worker if (MO.isReg() && TempSU->getInstr()->modifiesRegister(MO.getReg(), HRI))
653*9880d681SAndroid Build Coastguard Worker return false;
654*9880d681SAndroid Build Coastguard Worker }
655*9880d681SAndroid Build Coastguard Worker
656*9880d681SAndroid Build Coastguard Worker // Make sure that for non-POST_INC stores:
657*9880d681SAndroid Build Coastguard Worker // 1. The only use of reg is DepReg and no other registers.
658*9880d681SAndroid Build Coastguard Worker // This handles V4 base+index registers.
659*9880d681SAndroid Build Coastguard Worker // The following store can not be dot new.
660*9880d681SAndroid Build Coastguard Worker // Eg. r0 = add(r0, #3)
661*9880d681SAndroid Build Coastguard Worker // memw(r1+r0<<#2) = r0
662*9880d681SAndroid Build Coastguard Worker if (!HII->isPostIncrement(MI)) {
663*9880d681SAndroid Build Coastguard Worker for (unsigned opNum = 0; opNum < MI->getNumOperands()-1; opNum++) {
664*9880d681SAndroid Build Coastguard Worker const MachineOperand &MO = MI->getOperand(opNum);
665*9880d681SAndroid Build Coastguard Worker if (MO.isReg() && MO.getReg() == DepReg)
666*9880d681SAndroid Build Coastguard Worker return false;
667*9880d681SAndroid Build Coastguard Worker }
668*9880d681SAndroid Build Coastguard Worker }
669*9880d681SAndroid Build Coastguard Worker
670*9880d681SAndroid Build Coastguard Worker // If data definition is because of implicit definition of the register,
671*9880d681SAndroid Build Coastguard Worker // do not newify the store. Eg.
672*9880d681SAndroid Build Coastguard Worker // %R9<def> = ZXTH %R12, %D6<imp-use>, %R12<imp-def>
673*9880d681SAndroid Build Coastguard Worker // S2_storerh_io %R8, 2, %R12<kill>; mem:ST2[%scevgep343]
674*9880d681SAndroid Build Coastguard Worker for (auto &MO : PacketMI->operands()) {
675*9880d681SAndroid Build Coastguard Worker if (!MO.isReg() || !MO.isDef() || !MO.isImplicit())
676*9880d681SAndroid Build Coastguard Worker continue;
677*9880d681SAndroid Build Coastguard Worker unsigned R = MO.getReg();
678*9880d681SAndroid Build Coastguard Worker if (R == DepReg || HRI->isSuperRegister(DepReg, R))
679*9880d681SAndroid Build Coastguard Worker return false;
680*9880d681SAndroid Build Coastguard Worker }
681*9880d681SAndroid Build Coastguard Worker
682*9880d681SAndroid Build Coastguard Worker // Handle imp-use of super reg case. There is a target independent side
683*9880d681SAndroid Build Coastguard Worker // change that should prevent this situation but I am handling it for
684*9880d681SAndroid Build Coastguard Worker // just-in-case. For example, we cannot newify R2 in the following case:
685*9880d681SAndroid Build Coastguard Worker // %R3<def> = A2_tfrsi 0;
686*9880d681SAndroid Build Coastguard Worker // S2_storeri_io %R0<kill>, 0, %R2<kill>, %D1<imp-use,kill>;
687*9880d681SAndroid Build Coastguard Worker for (auto &MO : MI->operands()) {
688*9880d681SAndroid Build Coastguard Worker if (MO.isReg() && MO.isUse() && MO.isImplicit() && MO.getReg() == DepReg)
689*9880d681SAndroid Build Coastguard Worker return false;
690*9880d681SAndroid Build Coastguard Worker }
691*9880d681SAndroid Build Coastguard Worker
692*9880d681SAndroid Build Coastguard Worker // Can be dot new store.
693*9880d681SAndroid Build Coastguard Worker return true;
694*9880d681SAndroid Build Coastguard Worker }
695*9880d681SAndroid Build Coastguard Worker
696*9880d681SAndroid Build Coastguard Worker // Can this MI to promoted to either new value store or new value jump.
canPromoteToNewValue(const MachineInstr * MI,const SUnit * PacketSU,unsigned DepReg,MachineBasicBlock::iterator & MII)697*9880d681SAndroid Build Coastguard Worker bool HexagonPacketizerList::canPromoteToNewValue(const MachineInstr *MI,
698*9880d681SAndroid Build Coastguard Worker const SUnit *PacketSU, unsigned DepReg,
699*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator &MII) {
700*9880d681SAndroid Build Coastguard Worker if (!HII->mayBeNewStore(MI))
701*9880d681SAndroid Build Coastguard Worker return false;
702*9880d681SAndroid Build Coastguard Worker
703*9880d681SAndroid Build Coastguard Worker // Check to see the store can be new value'ed.
704*9880d681SAndroid Build Coastguard Worker MachineInstr *PacketMI = PacketSU->getInstr();
705*9880d681SAndroid Build Coastguard Worker if (canPromoteToNewValueStore(MI, PacketMI, DepReg))
706*9880d681SAndroid Build Coastguard Worker return true;
707*9880d681SAndroid Build Coastguard Worker
708*9880d681SAndroid Build Coastguard Worker // Check to see the compare/jump can be new value'ed.
709*9880d681SAndroid Build Coastguard Worker // This is done as a pass on its own. Don't need to check it here.
710*9880d681SAndroid Build Coastguard Worker return false;
711*9880d681SAndroid Build Coastguard Worker }
712*9880d681SAndroid Build Coastguard Worker
isImplicitDependency(const MachineInstr * I,unsigned DepReg)713*9880d681SAndroid Build Coastguard Worker static bool isImplicitDependency(const MachineInstr *I, unsigned DepReg) {
714*9880d681SAndroid Build Coastguard Worker for (auto &MO : I->operands())
715*9880d681SAndroid Build Coastguard Worker if (MO.isReg() && MO.isDef() && (MO.getReg() == DepReg) && MO.isImplicit())
716*9880d681SAndroid Build Coastguard Worker return true;
717*9880d681SAndroid Build Coastguard Worker return false;
718*9880d681SAndroid Build Coastguard Worker }
719*9880d681SAndroid Build Coastguard Worker
720*9880d681SAndroid Build Coastguard Worker // Check to see if an instruction can be dot new
721*9880d681SAndroid Build Coastguard Worker // There are three kinds.
722*9880d681SAndroid Build Coastguard Worker // 1. dot new on predicate - V2/V3/V4
723*9880d681SAndroid Build Coastguard Worker // 2. dot new on stores NV/ST - V4
724*9880d681SAndroid Build Coastguard Worker // 3. dot new on jump NV/J - V4 -- This is generated in a pass.
canPromoteToDotNew(const MachineInstr * MI,const SUnit * PacketSU,unsigned DepReg,MachineBasicBlock::iterator & MII,const TargetRegisterClass * RC)725*9880d681SAndroid Build Coastguard Worker bool HexagonPacketizerList::canPromoteToDotNew(const MachineInstr *MI,
726*9880d681SAndroid Build Coastguard Worker const SUnit *PacketSU, unsigned DepReg, MachineBasicBlock::iterator &MII,
727*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass* RC) {
728*9880d681SAndroid Build Coastguard Worker // Already a dot new instruction.
729*9880d681SAndroid Build Coastguard Worker if (HII->isDotNewInst(MI) && !HII->mayBeNewStore(MI))
730*9880d681SAndroid Build Coastguard Worker return false;
731*9880d681SAndroid Build Coastguard Worker
732*9880d681SAndroid Build Coastguard Worker if (!isNewifiable(MI))
733*9880d681SAndroid Build Coastguard Worker return false;
734*9880d681SAndroid Build Coastguard Worker
735*9880d681SAndroid Build Coastguard Worker const MachineInstr *PI = PacketSU->getInstr();
736*9880d681SAndroid Build Coastguard Worker
737*9880d681SAndroid Build Coastguard Worker // The "new value" cannot come from inline asm.
738*9880d681SAndroid Build Coastguard Worker if (PI->isInlineAsm())
739*9880d681SAndroid Build Coastguard Worker return false;
740*9880d681SAndroid Build Coastguard Worker
741*9880d681SAndroid Build Coastguard Worker // IMPLICIT_DEFs won't materialize as real instructions, so .new makes no
742*9880d681SAndroid Build Coastguard Worker // sense.
743*9880d681SAndroid Build Coastguard Worker if (PI->isImplicitDef())
744*9880d681SAndroid Build Coastguard Worker return false;
745*9880d681SAndroid Build Coastguard Worker
746*9880d681SAndroid Build Coastguard Worker // If dependency is trough an implicitly defined register, we should not
747*9880d681SAndroid Build Coastguard Worker // newify the use.
748*9880d681SAndroid Build Coastguard Worker if (isImplicitDependency(PI, DepReg))
749*9880d681SAndroid Build Coastguard Worker return false;
750*9880d681SAndroid Build Coastguard Worker
751*9880d681SAndroid Build Coastguard Worker const MCInstrDesc& MCID = PI->getDesc();
752*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *VecRC = HII->getRegClass(MCID, 0, HRI, MF);
753*9880d681SAndroid Build Coastguard Worker if (DisableVecDblNVStores && VecRC == &Hexagon::VecDblRegsRegClass)
754*9880d681SAndroid Build Coastguard Worker return false;
755*9880d681SAndroid Build Coastguard Worker
756*9880d681SAndroid Build Coastguard Worker // predicate .new
757*9880d681SAndroid Build Coastguard Worker // bug 5670: until that is fixed
758*9880d681SAndroid Build Coastguard Worker // TODO: MI->isIndirectBranch() and IsRegisterJump(MI)
759*9880d681SAndroid Build Coastguard Worker if (RC == &Hexagon::PredRegsRegClass)
760*9880d681SAndroid Build Coastguard Worker if (HII->isCondInst(MI) || MI->isReturn())
761*9880d681SAndroid Build Coastguard Worker return HII->predCanBeUsedAsDotNew(PI, DepReg);
762*9880d681SAndroid Build Coastguard Worker
763*9880d681SAndroid Build Coastguard Worker if (RC != &Hexagon::PredRegsRegClass && !HII->mayBeNewStore(MI))
764*9880d681SAndroid Build Coastguard Worker return false;
765*9880d681SAndroid Build Coastguard Worker
766*9880d681SAndroid Build Coastguard Worker // Create a dot new machine instruction to see if resources can be
767*9880d681SAndroid Build Coastguard Worker // allocated. If not, bail out now.
768*9880d681SAndroid Build Coastguard Worker int NewOpcode = HII->getDotNewOp(MI);
769*9880d681SAndroid Build Coastguard Worker const MCInstrDesc &D = HII->get(NewOpcode);
770*9880d681SAndroid Build Coastguard Worker MachineInstr *NewMI = MF.CreateMachineInstr(D, DebugLoc());
771*9880d681SAndroid Build Coastguard Worker bool ResourcesAvailable = ResourceTracker->canReserveResources(*NewMI);
772*9880d681SAndroid Build Coastguard Worker MF.DeleteMachineInstr(NewMI);
773*9880d681SAndroid Build Coastguard Worker if (!ResourcesAvailable)
774*9880d681SAndroid Build Coastguard Worker return false;
775*9880d681SAndroid Build Coastguard Worker
776*9880d681SAndroid Build Coastguard Worker // New Value Store only. New Value Jump generated as a separate pass.
777*9880d681SAndroid Build Coastguard Worker if (!canPromoteToNewValue(MI, PacketSU, DepReg, MII))
778*9880d681SAndroid Build Coastguard Worker return false;
779*9880d681SAndroid Build Coastguard Worker
780*9880d681SAndroid Build Coastguard Worker return true;
781*9880d681SAndroid Build Coastguard Worker }
782*9880d681SAndroid Build Coastguard Worker
783*9880d681SAndroid Build Coastguard Worker // Go through the packet instructions and search for an anti dependency between
784*9880d681SAndroid Build Coastguard Worker // them and DepReg from MI. Consider this case:
785*9880d681SAndroid Build Coastguard Worker // Trying to add
786*9880d681SAndroid Build Coastguard Worker // a) %R1<def> = TFRI_cdNotPt %P3, 2
787*9880d681SAndroid Build Coastguard Worker // to this packet:
788*9880d681SAndroid Build Coastguard Worker // {
789*9880d681SAndroid Build Coastguard Worker // b) %P0<def> = C2_or %P3<kill>, %P0<kill>
790*9880d681SAndroid Build Coastguard Worker // c) %P3<def> = C2_tfrrp %R23
791*9880d681SAndroid Build Coastguard Worker // d) %R1<def> = C2_cmovenewit %P3, 4
792*9880d681SAndroid Build Coastguard Worker // }
793*9880d681SAndroid Build Coastguard Worker // The P3 from a) and d) will be complements after
794*9880d681SAndroid Build Coastguard Worker // a)'s P3 is converted to .new form
795*9880d681SAndroid Build Coastguard Worker // Anti-dep between c) and b) is irrelevant for this case
restrictingDepExistInPacket(MachineInstr * MI,unsigned DepReg)796*9880d681SAndroid Build Coastguard Worker bool HexagonPacketizerList::restrictingDepExistInPacket(MachineInstr* MI,
797*9880d681SAndroid Build Coastguard Worker unsigned DepReg) {
798*9880d681SAndroid Build Coastguard Worker SUnit *PacketSUDep = MIToSUnit.find(MI)->second;
799*9880d681SAndroid Build Coastguard Worker
800*9880d681SAndroid Build Coastguard Worker for (auto I : CurrentPacketMIs) {
801*9880d681SAndroid Build Coastguard Worker // We only care for dependencies to predicated instructions
802*9880d681SAndroid Build Coastguard Worker if (!HII->isPredicated(*I))
803*9880d681SAndroid Build Coastguard Worker continue;
804*9880d681SAndroid Build Coastguard Worker
805*9880d681SAndroid Build Coastguard Worker // Scheduling Unit for current insn in the packet
806*9880d681SAndroid Build Coastguard Worker SUnit *PacketSU = MIToSUnit.find(I)->second;
807*9880d681SAndroid Build Coastguard Worker
808*9880d681SAndroid Build Coastguard Worker // Look at dependencies between current members of the packet and
809*9880d681SAndroid Build Coastguard Worker // predicate defining instruction MI. Make sure that dependency is
810*9880d681SAndroid Build Coastguard Worker // on the exact register we care about.
811*9880d681SAndroid Build Coastguard Worker if (PacketSU->isSucc(PacketSUDep)) {
812*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0; i < PacketSU->Succs.size(); ++i) {
813*9880d681SAndroid Build Coastguard Worker auto &Dep = PacketSU->Succs[i];
814*9880d681SAndroid Build Coastguard Worker if (Dep.getSUnit() == PacketSUDep && Dep.getKind() == SDep::Anti &&
815*9880d681SAndroid Build Coastguard Worker Dep.getReg() == DepReg)
816*9880d681SAndroid Build Coastguard Worker return true;
817*9880d681SAndroid Build Coastguard Worker }
818*9880d681SAndroid Build Coastguard Worker }
819*9880d681SAndroid Build Coastguard Worker }
820*9880d681SAndroid Build Coastguard Worker
821*9880d681SAndroid Build Coastguard Worker return false;
822*9880d681SAndroid Build Coastguard Worker }
823*9880d681SAndroid Build Coastguard Worker
824*9880d681SAndroid Build Coastguard Worker
825*9880d681SAndroid Build Coastguard Worker /// Gets the predicate register of a predicated instruction.
getPredicatedRegister(MachineInstr & MI,const HexagonInstrInfo * QII)826*9880d681SAndroid Build Coastguard Worker static unsigned getPredicatedRegister(MachineInstr &MI,
827*9880d681SAndroid Build Coastguard Worker const HexagonInstrInfo *QII) {
828*9880d681SAndroid Build Coastguard Worker /// We use the following rule: The first predicate register that is a use is
829*9880d681SAndroid Build Coastguard Worker /// the predicate register of a predicated instruction.
830*9880d681SAndroid Build Coastguard Worker assert(QII->isPredicated(MI) && "Must be predicated instruction");
831*9880d681SAndroid Build Coastguard Worker
832*9880d681SAndroid Build Coastguard Worker for (auto &Op : MI.operands()) {
833*9880d681SAndroid Build Coastguard Worker if (Op.isReg() && Op.getReg() && Op.isUse() &&
834*9880d681SAndroid Build Coastguard Worker Hexagon::PredRegsRegClass.contains(Op.getReg()))
835*9880d681SAndroid Build Coastguard Worker return Op.getReg();
836*9880d681SAndroid Build Coastguard Worker }
837*9880d681SAndroid Build Coastguard Worker
838*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unknown instruction operand layout");
839*9880d681SAndroid Build Coastguard Worker return 0;
840*9880d681SAndroid Build Coastguard Worker }
841*9880d681SAndroid Build Coastguard Worker
842*9880d681SAndroid Build Coastguard Worker // Given two predicated instructions, this function detects whether
843*9880d681SAndroid Build Coastguard Worker // the predicates are complements.
arePredicatesComplements(MachineInstr & MI1,MachineInstr & MI2)844*9880d681SAndroid Build Coastguard Worker bool HexagonPacketizerList::arePredicatesComplements(MachineInstr &MI1,
845*9880d681SAndroid Build Coastguard Worker MachineInstr &MI2) {
846*9880d681SAndroid Build Coastguard Worker // If we don't know the predicate sense of the instructions bail out early, we
847*9880d681SAndroid Build Coastguard Worker // need it later.
848*9880d681SAndroid Build Coastguard Worker if (getPredicateSense(MI1, HII) == PK_Unknown ||
849*9880d681SAndroid Build Coastguard Worker getPredicateSense(MI2, HII) == PK_Unknown)
850*9880d681SAndroid Build Coastguard Worker return false;
851*9880d681SAndroid Build Coastguard Worker
852*9880d681SAndroid Build Coastguard Worker // Scheduling unit for candidate.
853*9880d681SAndroid Build Coastguard Worker SUnit *SU = MIToSUnit[&MI1];
854*9880d681SAndroid Build Coastguard Worker
855*9880d681SAndroid Build Coastguard Worker // One corner case deals with the following scenario:
856*9880d681SAndroid Build Coastguard Worker // Trying to add
857*9880d681SAndroid Build Coastguard Worker // a) %R24<def> = A2_tfrt %P0, %R25
858*9880d681SAndroid Build Coastguard Worker // to this packet:
859*9880d681SAndroid Build Coastguard Worker // {
860*9880d681SAndroid Build Coastguard Worker // b) %R25<def> = A2_tfrf %P0, %R24
861*9880d681SAndroid Build Coastguard Worker // c) %P0<def> = C2_cmpeqi %R26, 1
862*9880d681SAndroid Build Coastguard Worker // }
863*9880d681SAndroid Build Coastguard Worker //
864*9880d681SAndroid Build Coastguard Worker // On general check a) and b) are complements, but presence of c) will
865*9880d681SAndroid Build Coastguard Worker // convert a) to .new form, and then it is not a complement.
866*9880d681SAndroid Build Coastguard Worker // We attempt to detect it by analyzing existing dependencies in the packet.
867*9880d681SAndroid Build Coastguard Worker
868*9880d681SAndroid Build Coastguard Worker // Analyze relationships between all existing members of the packet.
869*9880d681SAndroid Build Coastguard Worker // Look for Anti dependecy on the same predicate reg as used in the
870*9880d681SAndroid Build Coastguard Worker // candidate.
871*9880d681SAndroid Build Coastguard Worker for (auto I : CurrentPacketMIs) {
872*9880d681SAndroid Build Coastguard Worker // Scheduling Unit for current insn in the packet.
873*9880d681SAndroid Build Coastguard Worker SUnit *PacketSU = MIToSUnit.find(I)->second;
874*9880d681SAndroid Build Coastguard Worker
875*9880d681SAndroid Build Coastguard Worker // If this instruction in the packet is succeeded by the candidate...
876*9880d681SAndroid Build Coastguard Worker if (PacketSU->isSucc(SU)) {
877*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0; i < PacketSU->Succs.size(); ++i) {
878*9880d681SAndroid Build Coastguard Worker auto Dep = PacketSU->Succs[i];
879*9880d681SAndroid Build Coastguard Worker // The corner case exist when there is true data dependency between
880*9880d681SAndroid Build Coastguard Worker // candidate and one of current packet members, this dep is on
881*9880d681SAndroid Build Coastguard Worker // predicate reg, and there already exist anti dep on the same pred in
882*9880d681SAndroid Build Coastguard Worker // the packet.
883*9880d681SAndroid Build Coastguard Worker if (Dep.getSUnit() == SU && Dep.getKind() == SDep::Data &&
884*9880d681SAndroid Build Coastguard Worker Hexagon::PredRegsRegClass.contains(Dep.getReg())) {
885*9880d681SAndroid Build Coastguard Worker // Here I know that I is predicate setting instruction with true
886*9880d681SAndroid Build Coastguard Worker // data dep to candidate on the register we care about - c) in the
887*9880d681SAndroid Build Coastguard Worker // above example. Now I need to see if there is an anti dependency
888*9880d681SAndroid Build Coastguard Worker // from c) to any other instruction in the same packet on the pred
889*9880d681SAndroid Build Coastguard Worker // reg of interest.
890*9880d681SAndroid Build Coastguard Worker if (restrictingDepExistInPacket(I, Dep.getReg()))
891*9880d681SAndroid Build Coastguard Worker return false;
892*9880d681SAndroid Build Coastguard Worker }
893*9880d681SAndroid Build Coastguard Worker }
894*9880d681SAndroid Build Coastguard Worker }
895*9880d681SAndroid Build Coastguard Worker }
896*9880d681SAndroid Build Coastguard Worker
897*9880d681SAndroid Build Coastguard Worker // If the above case does not apply, check regular complement condition.
898*9880d681SAndroid Build Coastguard Worker // Check that the predicate register is the same and that the predicate
899*9880d681SAndroid Build Coastguard Worker // sense is different We also need to differentiate .old vs. .new: !p0
900*9880d681SAndroid Build Coastguard Worker // is not complementary to p0.new.
901*9880d681SAndroid Build Coastguard Worker unsigned PReg1 = getPredicatedRegister(MI1, HII);
902*9880d681SAndroid Build Coastguard Worker unsigned PReg2 = getPredicatedRegister(MI2, HII);
903*9880d681SAndroid Build Coastguard Worker return PReg1 == PReg2 &&
904*9880d681SAndroid Build Coastguard Worker Hexagon::PredRegsRegClass.contains(PReg1) &&
905*9880d681SAndroid Build Coastguard Worker Hexagon::PredRegsRegClass.contains(PReg2) &&
906*9880d681SAndroid Build Coastguard Worker getPredicateSense(MI1, HII) != getPredicateSense(MI2, HII) &&
907*9880d681SAndroid Build Coastguard Worker HII->isDotNewInst(&MI1) == HII->isDotNewInst(&MI2);
908*9880d681SAndroid Build Coastguard Worker }
909*9880d681SAndroid Build Coastguard Worker
910*9880d681SAndroid Build Coastguard Worker // Initialize packetizer flags.
initPacketizerState()911*9880d681SAndroid Build Coastguard Worker void HexagonPacketizerList::initPacketizerState() {
912*9880d681SAndroid Build Coastguard Worker Dependence = false;
913*9880d681SAndroid Build Coastguard Worker PromotedToDotNew = false;
914*9880d681SAndroid Build Coastguard Worker GlueToNewValueJump = false;
915*9880d681SAndroid Build Coastguard Worker GlueAllocframeStore = false;
916*9880d681SAndroid Build Coastguard Worker FoundSequentialDependence = false;
917*9880d681SAndroid Build Coastguard Worker }
918*9880d681SAndroid Build Coastguard Worker
919*9880d681SAndroid Build Coastguard Worker // Ignore bundling of pseudo instructions.
ignorePseudoInstruction(const MachineInstr & MI,const MachineBasicBlock *)920*9880d681SAndroid Build Coastguard Worker bool HexagonPacketizerList::ignorePseudoInstruction(const MachineInstr &MI,
921*9880d681SAndroid Build Coastguard Worker const MachineBasicBlock *) {
922*9880d681SAndroid Build Coastguard Worker if (MI.isDebugValue())
923*9880d681SAndroid Build Coastguard Worker return true;
924*9880d681SAndroid Build Coastguard Worker
925*9880d681SAndroid Build Coastguard Worker if (MI.isCFIInstruction())
926*9880d681SAndroid Build Coastguard Worker return false;
927*9880d681SAndroid Build Coastguard Worker
928*9880d681SAndroid Build Coastguard Worker // We must print out inline assembly.
929*9880d681SAndroid Build Coastguard Worker if (MI.isInlineAsm())
930*9880d681SAndroid Build Coastguard Worker return false;
931*9880d681SAndroid Build Coastguard Worker
932*9880d681SAndroid Build Coastguard Worker if (MI.isImplicitDef())
933*9880d681SAndroid Build Coastguard Worker return false;
934*9880d681SAndroid Build Coastguard Worker
935*9880d681SAndroid Build Coastguard Worker // We check if MI has any functional units mapped to it. If it doesn't,
936*9880d681SAndroid Build Coastguard Worker // we ignore the instruction.
937*9880d681SAndroid Build Coastguard Worker const MCInstrDesc& TID = MI.getDesc();
938*9880d681SAndroid Build Coastguard Worker auto *IS = ResourceTracker->getInstrItins()->beginStage(TID.getSchedClass());
939*9880d681SAndroid Build Coastguard Worker unsigned FuncUnits = IS->getUnits();
940*9880d681SAndroid Build Coastguard Worker return !FuncUnits;
941*9880d681SAndroid Build Coastguard Worker }
942*9880d681SAndroid Build Coastguard Worker
isSoloInstruction(const MachineInstr & MI)943*9880d681SAndroid Build Coastguard Worker bool HexagonPacketizerList::isSoloInstruction(const MachineInstr &MI) {
944*9880d681SAndroid Build Coastguard Worker if (MI.isEHLabel() || MI.isCFIInstruction())
945*9880d681SAndroid Build Coastguard Worker return true;
946*9880d681SAndroid Build Coastguard Worker
947*9880d681SAndroid Build Coastguard Worker // Consider inline asm to not be a solo instruction by default.
948*9880d681SAndroid Build Coastguard Worker // Inline asm will be put in a packet temporarily, but then it will be
949*9880d681SAndroid Build Coastguard Worker // removed, and placed outside of the packet (before or after, depending
950*9880d681SAndroid Build Coastguard Worker // on dependencies). This is to reduce the impact of inline asm as a
951*9880d681SAndroid Build Coastguard Worker // "packet splitting" instruction.
952*9880d681SAndroid Build Coastguard Worker if (MI.isInlineAsm() && !ScheduleInlineAsm)
953*9880d681SAndroid Build Coastguard Worker return true;
954*9880d681SAndroid Build Coastguard Worker
955*9880d681SAndroid Build Coastguard Worker // From Hexagon V4 Programmer's Reference Manual 3.4.4 Grouping constraints:
956*9880d681SAndroid Build Coastguard Worker // trap, pause, barrier, icinva, isync, and syncht are solo instructions.
957*9880d681SAndroid Build Coastguard Worker // They must not be grouped with other instructions in a packet.
958*9880d681SAndroid Build Coastguard Worker if (isSchedBarrier(&MI))
959*9880d681SAndroid Build Coastguard Worker return true;
960*9880d681SAndroid Build Coastguard Worker
961*9880d681SAndroid Build Coastguard Worker if (HII->isSolo(&MI))
962*9880d681SAndroid Build Coastguard Worker return true;
963*9880d681SAndroid Build Coastguard Worker
964*9880d681SAndroid Build Coastguard Worker if (MI.getOpcode() == Hexagon::A2_nop)
965*9880d681SAndroid Build Coastguard Worker return true;
966*9880d681SAndroid Build Coastguard Worker
967*9880d681SAndroid Build Coastguard Worker return false;
968*9880d681SAndroid Build Coastguard Worker }
969*9880d681SAndroid Build Coastguard Worker
970*9880d681SAndroid Build Coastguard Worker
971*9880d681SAndroid Build Coastguard Worker // Quick check if instructions MI and MJ cannot coexist in the same packet.
972*9880d681SAndroid Build Coastguard Worker // Limit the tests to be "one-way", e.g. "if MI->isBranch and MJ->isInlineAsm",
973*9880d681SAndroid Build Coastguard Worker // but not the symmetric case: "if MJ->isBranch and MI->isInlineAsm".
974*9880d681SAndroid Build Coastguard Worker // For full test call this function twice:
975*9880d681SAndroid Build Coastguard Worker // cannotCoexistAsymm(MI, MJ) || cannotCoexistAsymm(MJ, MI)
976*9880d681SAndroid Build Coastguard Worker // Doing the test only one way saves the amount of code in this function,
977*9880d681SAndroid Build Coastguard Worker // since every test would need to be repeated with the MI and MJ reversed.
cannotCoexistAsymm(const MachineInstr * MI,const MachineInstr * MJ,const HexagonInstrInfo & HII)978*9880d681SAndroid Build Coastguard Worker static bool cannotCoexistAsymm(const MachineInstr *MI, const MachineInstr *MJ,
979*9880d681SAndroid Build Coastguard Worker const HexagonInstrInfo &HII) {
980*9880d681SAndroid Build Coastguard Worker const MachineFunction *MF = MI->getParent()->getParent();
981*9880d681SAndroid Build Coastguard Worker if (MF->getSubtarget<HexagonSubtarget>().hasV60TOpsOnly() &&
982*9880d681SAndroid Build Coastguard Worker HII.isHVXMemWithAIndirect(MI, MJ))
983*9880d681SAndroid Build Coastguard Worker return true;
984*9880d681SAndroid Build Coastguard Worker
985*9880d681SAndroid Build Coastguard Worker // An inline asm cannot be together with a branch, because we may not be
986*9880d681SAndroid Build Coastguard Worker // able to remove the asm out after packetizing (i.e. if the asm must be
987*9880d681SAndroid Build Coastguard Worker // moved past the bundle). Similarly, two asms cannot be together to avoid
988*9880d681SAndroid Build Coastguard Worker // complications when determining their relative order outside of a bundle.
989*9880d681SAndroid Build Coastguard Worker if (MI->isInlineAsm())
990*9880d681SAndroid Build Coastguard Worker return MJ->isInlineAsm() || MJ->isBranch() || MJ->isBarrier() ||
991*9880d681SAndroid Build Coastguard Worker MJ->isCall() || MJ->isTerminator();
992*9880d681SAndroid Build Coastguard Worker
993*9880d681SAndroid Build Coastguard Worker // "False" really means that the quick check failed to determine if
994*9880d681SAndroid Build Coastguard Worker // I and J cannot coexist.
995*9880d681SAndroid Build Coastguard Worker return false;
996*9880d681SAndroid Build Coastguard Worker }
997*9880d681SAndroid Build Coastguard Worker
998*9880d681SAndroid Build Coastguard Worker
999*9880d681SAndroid Build Coastguard Worker // Full, symmetric check.
cannotCoexist(const MachineInstr * MI,const MachineInstr * MJ)1000*9880d681SAndroid Build Coastguard Worker bool HexagonPacketizerList::cannotCoexist(const MachineInstr *MI,
1001*9880d681SAndroid Build Coastguard Worker const MachineInstr *MJ) {
1002*9880d681SAndroid Build Coastguard Worker return cannotCoexistAsymm(MI, MJ, *HII) || cannotCoexistAsymm(MJ, MI, *HII);
1003*9880d681SAndroid Build Coastguard Worker }
1004*9880d681SAndroid Build Coastguard Worker
unpacketizeSoloInstrs(MachineFunction & MF)1005*9880d681SAndroid Build Coastguard Worker void HexagonPacketizerList::unpacketizeSoloInstrs(MachineFunction &MF) {
1006*9880d681SAndroid Build Coastguard Worker for (auto &B : MF) {
1007*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator BundleIt;
1008*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::instr_iterator NextI;
1009*9880d681SAndroid Build Coastguard Worker for (auto I = B.instr_begin(), E = B.instr_end(); I != E; I = NextI) {
1010*9880d681SAndroid Build Coastguard Worker NextI = std::next(I);
1011*9880d681SAndroid Build Coastguard Worker MachineInstr *MI = &*I;
1012*9880d681SAndroid Build Coastguard Worker if (MI->isBundle())
1013*9880d681SAndroid Build Coastguard Worker BundleIt = I;
1014*9880d681SAndroid Build Coastguard Worker if (!MI->isInsideBundle())
1015*9880d681SAndroid Build Coastguard Worker continue;
1016*9880d681SAndroid Build Coastguard Worker
1017*9880d681SAndroid Build Coastguard Worker // Decide on where to insert the instruction that we are pulling out.
1018*9880d681SAndroid Build Coastguard Worker // Debug instructions always go before the bundle, but the placement of
1019*9880d681SAndroid Build Coastguard Worker // INLINE_ASM depends on potential dependencies. By default, try to
1020*9880d681SAndroid Build Coastguard Worker // put it before the bundle, but if the asm writes to a register that
1021*9880d681SAndroid Build Coastguard Worker // other instructions in the bundle read, then we need to place it
1022*9880d681SAndroid Build Coastguard Worker // after the bundle (to preserve the bundle semantics).
1023*9880d681SAndroid Build Coastguard Worker bool InsertBeforeBundle;
1024*9880d681SAndroid Build Coastguard Worker if (MI->isInlineAsm())
1025*9880d681SAndroid Build Coastguard Worker InsertBeforeBundle = !hasWriteToReadDep(*MI, *BundleIt, HRI);
1026*9880d681SAndroid Build Coastguard Worker else if (MI->isDebugValue())
1027*9880d681SAndroid Build Coastguard Worker InsertBeforeBundle = true;
1028*9880d681SAndroid Build Coastguard Worker else
1029*9880d681SAndroid Build Coastguard Worker continue;
1030*9880d681SAndroid Build Coastguard Worker
1031*9880d681SAndroid Build Coastguard Worker BundleIt = moveInstrOut(MI, BundleIt, InsertBeforeBundle);
1032*9880d681SAndroid Build Coastguard Worker }
1033*9880d681SAndroid Build Coastguard Worker }
1034*9880d681SAndroid Build Coastguard Worker }
1035*9880d681SAndroid Build Coastguard Worker
1036*9880d681SAndroid Build Coastguard Worker // Check if a given instruction is of class "system".
isSystemInstr(const MachineInstr * MI)1037*9880d681SAndroid Build Coastguard Worker static bool isSystemInstr(const MachineInstr *MI) {
1038*9880d681SAndroid Build Coastguard Worker unsigned Opc = MI->getOpcode();
1039*9880d681SAndroid Build Coastguard Worker switch (Opc) {
1040*9880d681SAndroid Build Coastguard Worker case Hexagon::Y2_barrier:
1041*9880d681SAndroid Build Coastguard Worker case Hexagon::Y2_dcfetchbo:
1042*9880d681SAndroid Build Coastguard Worker return true;
1043*9880d681SAndroid Build Coastguard Worker }
1044*9880d681SAndroid Build Coastguard Worker return false;
1045*9880d681SAndroid Build Coastguard Worker }
1046*9880d681SAndroid Build Coastguard Worker
hasDeadDependence(const MachineInstr * I,const MachineInstr * J)1047*9880d681SAndroid Build Coastguard Worker bool HexagonPacketizerList::hasDeadDependence(const MachineInstr *I,
1048*9880d681SAndroid Build Coastguard Worker const MachineInstr *J) {
1049*9880d681SAndroid Build Coastguard Worker // The dependence graph may not include edges between dead definitions,
1050*9880d681SAndroid Build Coastguard Worker // so without extra checks, we could end up packetizing two instruction
1051*9880d681SAndroid Build Coastguard Worker // defining the same (dead) register.
1052*9880d681SAndroid Build Coastguard Worker if (I->isCall() || J->isCall())
1053*9880d681SAndroid Build Coastguard Worker return false;
1054*9880d681SAndroid Build Coastguard Worker if (HII->isPredicated(*I) || HII->isPredicated(*J))
1055*9880d681SAndroid Build Coastguard Worker return false;
1056*9880d681SAndroid Build Coastguard Worker
1057*9880d681SAndroid Build Coastguard Worker BitVector DeadDefs(Hexagon::NUM_TARGET_REGS);
1058*9880d681SAndroid Build Coastguard Worker for (auto &MO : I->operands()) {
1059*9880d681SAndroid Build Coastguard Worker if (!MO.isReg() || !MO.isDef() || !MO.isDead())
1060*9880d681SAndroid Build Coastguard Worker continue;
1061*9880d681SAndroid Build Coastguard Worker DeadDefs[MO.getReg()] = true;
1062*9880d681SAndroid Build Coastguard Worker }
1063*9880d681SAndroid Build Coastguard Worker
1064*9880d681SAndroid Build Coastguard Worker for (auto &MO : J->operands()) {
1065*9880d681SAndroid Build Coastguard Worker if (!MO.isReg() || !MO.isDef() || !MO.isDead())
1066*9880d681SAndroid Build Coastguard Worker continue;
1067*9880d681SAndroid Build Coastguard Worker unsigned R = MO.getReg();
1068*9880d681SAndroid Build Coastguard Worker if (R != Hexagon::USR_OVF && DeadDefs[R])
1069*9880d681SAndroid Build Coastguard Worker return true;
1070*9880d681SAndroid Build Coastguard Worker }
1071*9880d681SAndroid Build Coastguard Worker return false;
1072*9880d681SAndroid Build Coastguard Worker }
1073*9880d681SAndroid Build Coastguard Worker
hasControlDependence(const MachineInstr * I,const MachineInstr * J)1074*9880d681SAndroid Build Coastguard Worker bool HexagonPacketizerList::hasControlDependence(const MachineInstr *I,
1075*9880d681SAndroid Build Coastguard Worker const MachineInstr *J) {
1076*9880d681SAndroid Build Coastguard Worker // A save callee-save register function call can only be in a packet
1077*9880d681SAndroid Build Coastguard Worker // with instructions that don't write to the callee-save registers.
1078*9880d681SAndroid Build Coastguard Worker if ((HII->isSaveCalleeSavedRegsCall(I) &&
1079*9880d681SAndroid Build Coastguard Worker doesModifyCalleeSavedReg(J, HRI)) ||
1080*9880d681SAndroid Build Coastguard Worker (HII->isSaveCalleeSavedRegsCall(J) &&
1081*9880d681SAndroid Build Coastguard Worker doesModifyCalleeSavedReg(I, HRI)))
1082*9880d681SAndroid Build Coastguard Worker return true;
1083*9880d681SAndroid Build Coastguard Worker
1084*9880d681SAndroid Build Coastguard Worker // Two control flow instructions cannot go in the same packet.
1085*9880d681SAndroid Build Coastguard Worker if (isControlFlow(I) && isControlFlow(J))
1086*9880d681SAndroid Build Coastguard Worker return true;
1087*9880d681SAndroid Build Coastguard Worker
1088*9880d681SAndroid Build Coastguard Worker // \ref-manual (7.3.4) A loop setup packet in loopN or spNloop0 cannot
1089*9880d681SAndroid Build Coastguard Worker // contain a speculative indirect jump,
1090*9880d681SAndroid Build Coastguard Worker // a new-value compare jump or a dealloc_return.
1091*9880d681SAndroid Build Coastguard Worker auto isBadForLoopN = [this] (const MachineInstr *MI) -> bool {
1092*9880d681SAndroid Build Coastguard Worker if (MI->isCall() || HII->isDeallocRet(MI) || HII->isNewValueJump(MI))
1093*9880d681SAndroid Build Coastguard Worker return true;
1094*9880d681SAndroid Build Coastguard Worker if (HII->isPredicated(*MI) && HII->isPredicatedNew(*MI) && HII->isJumpR(MI))
1095*9880d681SAndroid Build Coastguard Worker return true;
1096*9880d681SAndroid Build Coastguard Worker return false;
1097*9880d681SAndroid Build Coastguard Worker };
1098*9880d681SAndroid Build Coastguard Worker
1099*9880d681SAndroid Build Coastguard Worker if (HII->isLoopN(I) && isBadForLoopN(J))
1100*9880d681SAndroid Build Coastguard Worker return true;
1101*9880d681SAndroid Build Coastguard Worker if (HII->isLoopN(J) && isBadForLoopN(I))
1102*9880d681SAndroid Build Coastguard Worker return true;
1103*9880d681SAndroid Build Coastguard Worker
1104*9880d681SAndroid Build Coastguard Worker // dealloc_return cannot appear in the same packet as a conditional or
1105*9880d681SAndroid Build Coastguard Worker // unconditional jump.
1106*9880d681SAndroid Build Coastguard Worker return HII->isDeallocRet(I) &&
1107*9880d681SAndroid Build Coastguard Worker (J->isBranch() || J->isCall() || J->isBarrier());
1108*9880d681SAndroid Build Coastguard Worker }
1109*9880d681SAndroid Build Coastguard Worker
hasV4SpecificDependence(const MachineInstr * I,const MachineInstr * J)1110*9880d681SAndroid Build Coastguard Worker bool HexagonPacketizerList::hasV4SpecificDependence(const MachineInstr *I,
1111*9880d681SAndroid Build Coastguard Worker const MachineInstr *J) {
1112*9880d681SAndroid Build Coastguard Worker bool SysI = isSystemInstr(I), SysJ = isSystemInstr(J);
1113*9880d681SAndroid Build Coastguard Worker bool StoreI = I->mayStore(), StoreJ = J->mayStore();
1114*9880d681SAndroid Build Coastguard Worker if ((SysI && StoreJ) || (SysJ && StoreI))
1115*9880d681SAndroid Build Coastguard Worker return true;
1116*9880d681SAndroid Build Coastguard Worker
1117*9880d681SAndroid Build Coastguard Worker if (StoreI && StoreJ) {
1118*9880d681SAndroid Build Coastguard Worker if (HII->isNewValueInst(J) || HII->isMemOp(J) || HII->isMemOp(I))
1119*9880d681SAndroid Build Coastguard Worker return true;
1120*9880d681SAndroid Build Coastguard Worker } else {
1121*9880d681SAndroid Build Coastguard Worker // A memop cannot be in the same packet with another memop or a store.
1122*9880d681SAndroid Build Coastguard Worker // Two stores can be together, but here I and J cannot both be stores.
1123*9880d681SAndroid Build Coastguard Worker bool MopStI = HII->isMemOp(I) || StoreI;
1124*9880d681SAndroid Build Coastguard Worker bool MopStJ = HII->isMemOp(J) || StoreJ;
1125*9880d681SAndroid Build Coastguard Worker if (MopStI && MopStJ)
1126*9880d681SAndroid Build Coastguard Worker return true;
1127*9880d681SAndroid Build Coastguard Worker }
1128*9880d681SAndroid Build Coastguard Worker
1129*9880d681SAndroid Build Coastguard Worker return (StoreJ && HII->isDeallocRet(I)) || (StoreI && HII->isDeallocRet(J));
1130*9880d681SAndroid Build Coastguard Worker }
1131*9880d681SAndroid Build Coastguard Worker
1132*9880d681SAndroid Build Coastguard Worker // SUI is the current instruction that is out side of the current packet.
1133*9880d681SAndroid Build Coastguard Worker // SUJ is the current instruction inside the current packet against which that
1134*9880d681SAndroid Build Coastguard Worker // SUI will be packetized.
isLegalToPacketizeTogether(SUnit * SUI,SUnit * SUJ)1135*9880d681SAndroid Build Coastguard Worker bool HexagonPacketizerList::isLegalToPacketizeTogether(SUnit *SUI, SUnit *SUJ) {
1136*9880d681SAndroid Build Coastguard Worker MachineInstr *I = SUI->getInstr();
1137*9880d681SAndroid Build Coastguard Worker MachineInstr *J = SUJ->getInstr();
1138*9880d681SAndroid Build Coastguard Worker assert(I && J && "Unable to packetize null instruction!");
1139*9880d681SAndroid Build Coastguard Worker
1140*9880d681SAndroid Build Coastguard Worker // Clear IgnoreDepMIs when Packet starts.
1141*9880d681SAndroid Build Coastguard Worker if (CurrentPacketMIs.size() == 1)
1142*9880d681SAndroid Build Coastguard Worker IgnoreDepMIs.clear();
1143*9880d681SAndroid Build Coastguard Worker
1144*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator II = I;
1145*9880d681SAndroid Build Coastguard Worker const unsigned FrameSize = MF.getFrameInfo()->getStackSize();
1146*9880d681SAndroid Build Coastguard Worker
1147*9880d681SAndroid Build Coastguard Worker // Solo instructions cannot go in the packet.
1148*9880d681SAndroid Build Coastguard Worker assert(!isSoloInstruction(*I) && "Unexpected solo instr!");
1149*9880d681SAndroid Build Coastguard Worker
1150*9880d681SAndroid Build Coastguard Worker if (cannotCoexist(I, J))
1151*9880d681SAndroid Build Coastguard Worker return false;
1152*9880d681SAndroid Build Coastguard Worker
1153*9880d681SAndroid Build Coastguard Worker Dependence = hasDeadDependence(I, J) || hasControlDependence(I, J);
1154*9880d681SAndroid Build Coastguard Worker if (Dependence)
1155*9880d681SAndroid Build Coastguard Worker return false;
1156*9880d681SAndroid Build Coastguard Worker
1157*9880d681SAndroid Build Coastguard Worker // V4 allows dual stores. It does not allow second store, if the first
1158*9880d681SAndroid Build Coastguard Worker // store is not in SLOT0. New value store, new value jump, dealloc_return
1159*9880d681SAndroid Build Coastguard Worker // and memop always take SLOT0. Arch spec 3.4.4.2.
1160*9880d681SAndroid Build Coastguard Worker Dependence = hasV4SpecificDependence(I, J);
1161*9880d681SAndroid Build Coastguard Worker if (Dependence)
1162*9880d681SAndroid Build Coastguard Worker return false;
1163*9880d681SAndroid Build Coastguard Worker
1164*9880d681SAndroid Build Coastguard Worker // If an instruction feeds new value jump, glue it.
1165*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator NextMII = I;
1166*9880d681SAndroid Build Coastguard Worker ++NextMII;
1167*9880d681SAndroid Build Coastguard Worker if (NextMII != I->getParent()->end() && HII->isNewValueJump(&*NextMII)) {
1168*9880d681SAndroid Build Coastguard Worker MachineInstr &NextMI = *NextMII;
1169*9880d681SAndroid Build Coastguard Worker
1170*9880d681SAndroid Build Coastguard Worker bool secondRegMatch = false;
1171*9880d681SAndroid Build Coastguard Worker const MachineOperand &NOp0 = NextMI.getOperand(0);
1172*9880d681SAndroid Build Coastguard Worker const MachineOperand &NOp1 = NextMI.getOperand(1);
1173*9880d681SAndroid Build Coastguard Worker
1174*9880d681SAndroid Build Coastguard Worker if (NOp1.isReg() && I->getOperand(0).getReg() == NOp1.getReg())
1175*9880d681SAndroid Build Coastguard Worker secondRegMatch = true;
1176*9880d681SAndroid Build Coastguard Worker
1177*9880d681SAndroid Build Coastguard Worker for (auto I : CurrentPacketMIs) {
1178*9880d681SAndroid Build Coastguard Worker SUnit *PacketSU = MIToSUnit.find(I)->second;
1179*9880d681SAndroid Build Coastguard Worker MachineInstr *PI = PacketSU->getInstr();
1180*9880d681SAndroid Build Coastguard Worker // NVJ can not be part of the dual jump - Arch Spec: section 7.8.
1181*9880d681SAndroid Build Coastguard Worker if (PI->isCall()) {
1182*9880d681SAndroid Build Coastguard Worker Dependence = true;
1183*9880d681SAndroid Build Coastguard Worker break;
1184*9880d681SAndroid Build Coastguard Worker }
1185*9880d681SAndroid Build Coastguard Worker // Validate:
1186*9880d681SAndroid Build Coastguard Worker // 1. Packet does not have a store in it.
1187*9880d681SAndroid Build Coastguard Worker // 2. If the first operand of the nvj is newified, and the second
1188*9880d681SAndroid Build Coastguard Worker // operand is also a reg, it (second reg) is not defined in
1189*9880d681SAndroid Build Coastguard Worker // the same packet.
1190*9880d681SAndroid Build Coastguard Worker // 3. If the second operand of the nvj is newified, (which means
1191*9880d681SAndroid Build Coastguard Worker // first operand is also a reg), first reg is not defined in
1192*9880d681SAndroid Build Coastguard Worker // the same packet.
1193*9880d681SAndroid Build Coastguard Worker if (PI->getOpcode() == Hexagon::S2_allocframe || PI->mayStore() ||
1194*9880d681SAndroid Build Coastguard Worker HII->isLoopN(PI)) {
1195*9880d681SAndroid Build Coastguard Worker Dependence = true;
1196*9880d681SAndroid Build Coastguard Worker break;
1197*9880d681SAndroid Build Coastguard Worker }
1198*9880d681SAndroid Build Coastguard Worker // Check #2/#3.
1199*9880d681SAndroid Build Coastguard Worker const MachineOperand &OpR = secondRegMatch ? NOp0 : NOp1;
1200*9880d681SAndroid Build Coastguard Worker if (OpR.isReg() && PI->modifiesRegister(OpR.getReg(), HRI)) {
1201*9880d681SAndroid Build Coastguard Worker Dependence = true;
1202*9880d681SAndroid Build Coastguard Worker break;
1203*9880d681SAndroid Build Coastguard Worker }
1204*9880d681SAndroid Build Coastguard Worker }
1205*9880d681SAndroid Build Coastguard Worker
1206*9880d681SAndroid Build Coastguard Worker if (Dependence)
1207*9880d681SAndroid Build Coastguard Worker return false;
1208*9880d681SAndroid Build Coastguard Worker GlueToNewValueJump = true;
1209*9880d681SAndroid Build Coastguard Worker }
1210*9880d681SAndroid Build Coastguard Worker
1211*9880d681SAndroid Build Coastguard Worker // There no dependency between a prolog instruction and its successor.
1212*9880d681SAndroid Build Coastguard Worker if (!SUJ->isSucc(SUI))
1213*9880d681SAndroid Build Coastguard Worker return true;
1214*9880d681SAndroid Build Coastguard Worker
1215*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0; i < SUJ->Succs.size(); ++i) {
1216*9880d681SAndroid Build Coastguard Worker if (FoundSequentialDependence)
1217*9880d681SAndroid Build Coastguard Worker break;
1218*9880d681SAndroid Build Coastguard Worker
1219*9880d681SAndroid Build Coastguard Worker if (SUJ->Succs[i].getSUnit() != SUI)
1220*9880d681SAndroid Build Coastguard Worker continue;
1221*9880d681SAndroid Build Coastguard Worker
1222*9880d681SAndroid Build Coastguard Worker SDep::Kind DepType = SUJ->Succs[i].getKind();
1223*9880d681SAndroid Build Coastguard Worker // For direct calls:
1224*9880d681SAndroid Build Coastguard Worker // Ignore register dependences for call instructions for packetization
1225*9880d681SAndroid Build Coastguard Worker // purposes except for those due to r31 and predicate registers.
1226*9880d681SAndroid Build Coastguard Worker //
1227*9880d681SAndroid Build Coastguard Worker // For indirect calls:
1228*9880d681SAndroid Build Coastguard Worker // Same as direct calls + check for true dependences to the register
1229*9880d681SAndroid Build Coastguard Worker // used in the indirect call.
1230*9880d681SAndroid Build Coastguard Worker //
1231*9880d681SAndroid Build Coastguard Worker // We completely ignore Order dependences for call instructions.
1232*9880d681SAndroid Build Coastguard Worker //
1233*9880d681SAndroid Build Coastguard Worker // For returns:
1234*9880d681SAndroid Build Coastguard Worker // Ignore register dependences for return instructions like jumpr,
1235*9880d681SAndroid Build Coastguard Worker // dealloc return unless we have dependencies on the explicit uses
1236*9880d681SAndroid Build Coastguard Worker // of the registers used by jumpr (like r31) or dealloc return
1237*9880d681SAndroid Build Coastguard Worker // (like r29 or r30).
1238*9880d681SAndroid Build Coastguard Worker //
1239*9880d681SAndroid Build Coastguard Worker // TODO: Currently, jumpr is handling only return of r31. So, the
1240*9880d681SAndroid Build Coastguard Worker // following logic (specificaly isCallDependent) is working fine.
1241*9880d681SAndroid Build Coastguard Worker // We need to enable jumpr for register other than r31 and then,
1242*9880d681SAndroid Build Coastguard Worker // we need to rework the last part, where it handles indirect call
1243*9880d681SAndroid Build Coastguard Worker // of that (isCallDependent) function. Bug 6216 is opened for this.
1244*9880d681SAndroid Build Coastguard Worker unsigned DepReg = 0;
1245*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RC = nullptr;
1246*9880d681SAndroid Build Coastguard Worker if (DepType == SDep::Data) {
1247*9880d681SAndroid Build Coastguard Worker DepReg = SUJ->Succs[i].getReg();
1248*9880d681SAndroid Build Coastguard Worker RC = HRI->getMinimalPhysRegClass(DepReg);
1249*9880d681SAndroid Build Coastguard Worker }
1250*9880d681SAndroid Build Coastguard Worker
1251*9880d681SAndroid Build Coastguard Worker if (I->isCall() || I->isReturn() || HII->isTailCall(I)) {
1252*9880d681SAndroid Build Coastguard Worker if (!isRegDependence(DepType))
1253*9880d681SAndroid Build Coastguard Worker continue;
1254*9880d681SAndroid Build Coastguard Worker if (!isCallDependent(I, DepType, SUJ->Succs[i].getReg()))
1255*9880d681SAndroid Build Coastguard Worker continue;
1256*9880d681SAndroid Build Coastguard Worker }
1257*9880d681SAndroid Build Coastguard Worker
1258*9880d681SAndroid Build Coastguard Worker if (DepType == SDep::Data) {
1259*9880d681SAndroid Build Coastguard Worker if (canPromoteToDotCur(J, SUJ, DepReg, II, RC))
1260*9880d681SAndroid Build Coastguard Worker if (promoteToDotCur(J, DepType, II, RC))
1261*9880d681SAndroid Build Coastguard Worker continue;
1262*9880d681SAndroid Build Coastguard Worker }
1263*9880d681SAndroid Build Coastguard Worker
1264*9880d681SAndroid Build Coastguard Worker // Data dpendence ok if we have load.cur.
1265*9880d681SAndroid Build Coastguard Worker if (DepType == SDep::Data && HII->isDotCurInst(J)) {
1266*9880d681SAndroid Build Coastguard Worker if (HII->isV60VectorInstruction(I))
1267*9880d681SAndroid Build Coastguard Worker continue;
1268*9880d681SAndroid Build Coastguard Worker }
1269*9880d681SAndroid Build Coastguard Worker
1270*9880d681SAndroid Build Coastguard Worker // For instructions that can be promoted to dot-new, try to promote.
1271*9880d681SAndroid Build Coastguard Worker if (DepType == SDep::Data) {
1272*9880d681SAndroid Build Coastguard Worker if (canPromoteToDotNew(I, SUJ, DepReg, II, RC)) {
1273*9880d681SAndroid Build Coastguard Worker if (promoteToDotNew(I, DepType, II, RC)) {
1274*9880d681SAndroid Build Coastguard Worker PromotedToDotNew = true;
1275*9880d681SAndroid Build Coastguard Worker continue;
1276*9880d681SAndroid Build Coastguard Worker }
1277*9880d681SAndroid Build Coastguard Worker }
1278*9880d681SAndroid Build Coastguard Worker if (HII->isNewValueJump(I))
1279*9880d681SAndroid Build Coastguard Worker continue;
1280*9880d681SAndroid Build Coastguard Worker }
1281*9880d681SAndroid Build Coastguard Worker
1282*9880d681SAndroid Build Coastguard Worker // For predicated instructions, if the predicates are complements then
1283*9880d681SAndroid Build Coastguard Worker // there can be no dependence.
1284*9880d681SAndroid Build Coastguard Worker if (HII->isPredicated(*I) && HII->isPredicated(*J) &&
1285*9880d681SAndroid Build Coastguard Worker arePredicatesComplements(*I, *J)) {
1286*9880d681SAndroid Build Coastguard Worker // Not always safe to do this translation.
1287*9880d681SAndroid Build Coastguard Worker // DAG Builder attempts to reduce dependence edges using transitive
1288*9880d681SAndroid Build Coastguard Worker // nature of dependencies. Here is an example:
1289*9880d681SAndroid Build Coastguard Worker //
1290*9880d681SAndroid Build Coastguard Worker // r0 = tfr_pt ... (1)
1291*9880d681SAndroid Build Coastguard Worker // r0 = tfr_pf ... (2)
1292*9880d681SAndroid Build Coastguard Worker // r0 = tfr_pt ... (3)
1293*9880d681SAndroid Build Coastguard Worker //
1294*9880d681SAndroid Build Coastguard Worker // There will be an output dependence between (1)->(2) and (2)->(3).
1295*9880d681SAndroid Build Coastguard Worker // However, there is no dependence edge between (1)->(3). This results
1296*9880d681SAndroid Build Coastguard Worker // in all 3 instructions going in the same packet. We ignore dependce
1297*9880d681SAndroid Build Coastguard Worker // only once to avoid this situation.
1298*9880d681SAndroid Build Coastguard Worker auto Itr = std::find(IgnoreDepMIs.begin(), IgnoreDepMIs.end(), J);
1299*9880d681SAndroid Build Coastguard Worker if (Itr != IgnoreDepMIs.end()) {
1300*9880d681SAndroid Build Coastguard Worker Dependence = true;
1301*9880d681SAndroid Build Coastguard Worker return false;
1302*9880d681SAndroid Build Coastguard Worker }
1303*9880d681SAndroid Build Coastguard Worker IgnoreDepMIs.push_back(I);
1304*9880d681SAndroid Build Coastguard Worker continue;
1305*9880d681SAndroid Build Coastguard Worker }
1306*9880d681SAndroid Build Coastguard Worker
1307*9880d681SAndroid Build Coastguard Worker // Ignore Order dependences between unconditional direct branches
1308*9880d681SAndroid Build Coastguard Worker // and non-control-flow instructions.
1309*9880d681SAndroid Build Coastguard Worker if (isDirectJump(I) && !J->isBranch() && !J->isCall() &&
1310*9880d681SAndroid Build Coastguard Worker DepType == SDep::Order)
1311*9880d681SAndroid Build Coastguard Worker continue;
1312*9880d681SAndroid Build Coastguard Worker
1313*9880d681SAndroid Build Coastguard Worker // Ignore all dependences for jumps except for true and output
1314*9880d681SAndroid Build Coastguard Worker // dependences.
1315*9880d681SAndroid Build Coastguard Worker if (I->isConditionalBranch() && DepType != SDep::Data &&
1316*9880d681SAndroid Build Coastguard Worker DepType != SDep::Output)
1317*9880d681SAndroid Build Coastguard Worker continue;
1318*9880d681SAndroid Build Coastguard Worker
1319*9880d681SAndroid Build Coastguard Worker // Ignore output dependences due to superregs. We can write to two
1320*9880d681SAndroid Build Coastguard Worker // different subregisters of R1:0 for instance in the same cycle.
1321*9880d681SAndroid Build Coastguard Worker
1322*9880d681SAndroid Build Coastguard Worker // If neither I nor J defines DepReg, then this is a superfluous output
1323*9880d681SAndroid Build Coastguard Worker // dependence. The dependence must be of the form:
1324*9880d681SAndroid Build Coastguard Worker // R0 = ...
1325*9880d681SAndroid Build Coastguard Worker // R1 = ...
1326*9880d681SAndroid Build Coastguard Worker // and there is an output dependence between the two instructions with
1327*9880d681SAndroid Build Coastguard Worker // DepReg = D0.
1328*9880d681SAndroid Build Coastguard Worker // We want to ignore these dependences. Ideally, the dependence
1329*9880d681SAndroid Build Coastguard Worker // constructor should annotate such dependences. We can then avoid this
1330*9880d681SAndroid Build Coastguard Worker // relatively expensive check.
1331*9880d681SAndroid Build Coastguard Worker //
1332*9880d681SAndroid Build Coastguard Worker if (DepType == SDep::Output) {
1333*9880d681SAndroid Build Coastguard Worker // DepReg is the register that's responsible for the dependence.
1334*9880d681SAndroid Build Coastguard Worker unsigned DepReg = SUJ->Succs[i].getReg();
1335*9880d681SAndroid Build Coastguard Worker
1336*9880d681SAndroid Build Coastguard Worker // Check if I and J really defines DepReg.
1337*9880d681SAndroid Build Coastguard Worker if (!I->definesRegister(DepReg) && !J->definesRegister(DepReg))
1338*9880d681SAndroid Build Coastguard Worker continue;
1339*9880d681SAndroid Build Coastguard Worker FoundSequentialDependence = true;
1340*9880d681SAndroid Build Coastguard Worker break;
1341*9880d681SAndroid Build Coastguard Worker }
1342*9880d681SAndroid Build Coastguard Worker
1343*9880d681SAndroid Build Coastguard Worker // For Order dependences:
1344*9880d681SAndroid Build Coastguard Worker // 1. On V4 or later, volatile loads/stores can be packetized together,
1345*9880d681SAndroid Build Coastguard Worker // unless other rules prevent is.
1346*9880d681SAndroid Build Coastguard Worker // 2. Store followed by a load is not allowed.
1347*9880d681SAndroid Build Coastguard Worker // 3. Store followed by a store is only valid on V4 or later.
1348*9880d681SAndroid Build Coastguard Worker // 4. Load followed by any memory operation is allowed.
1349*9880d681SAndroid Build Coastguard Worker if (DepType == SDep::Order) {
1350*9880d681SAndroid Build Coastguard Worker if (!PacketizeVolatiles) {
1351*9880d681SAndroid Build Coastguard Worker bool OrdRefs = I->hasOrderedMemoryRef() || J->hasOrderedMemoryRef();
1352*9880d681SAndroid Build Coastguard Worker if (OrdRefs) {
1353*9880d681SAndroid Build Coastguard Worker FoundSequentialDependence = true;
1354*9880d681SAndroid Build Coastguard Worker break;
1355*9880d681SAndroid Build Coastguard Worker }
1356*9880d681SAndroid Build Coastguard Worker }
1357*9880d681SAndroid Build Coastguard Worker // J is first, I is second.
1358*9880d681SAndroid Build Coastguard Worker bool LoadJ = J->mayLoad(), StoreJ = J->mayStore();
1359*9880d681SAndroid Build Coastguard Worker bool LoadI = I->mayLoad(), StoreI = I->mayStore();
1360*9880d681SAndroid Build Coastguard Worker if (StoreJ) {
1361*9880d681SAndroid Build Coastguard Worker // Two stores are only allowed on V4+. Load following store is never
1362*9880d681SAndroid Build Coastguard Worker // allowed.
1363*9880d681SAndroid Build Coastguard Worker if (LoadI) {
1364*9880d681SAndroid Build Coastguard Worker FoundSequentialDependence = true;
1365*9880d681SAndroid Build Coastguard Worker break;
1366*9880d681SAndroid Build Coastguard Worker }
1367*9880d681SAndroid Build Coastguard Worker } else if (!LoadJ || (!LoadI && !StoreI)) {
1368*9880d681SAndroid Build Coastguard Worker // If J is neither load nor store, assume a dependency.
1369*9880d681SAndroid Build Coastguard Worker // If J is a load, but I is neither, also assume a dependency.
1370*9880d681SAndroid Build Coastguard Worker FoundSequentialDependence = true;
1371*9880d681SAndroid Build Coastguard Worker break;
1372*9880d681SAndroid Build Coastguard Worker }
1373*9880d681SAndroid Build Coastguard Worker // Store followed by store: not OK on V2.
1374*9880d681SAndroid Build Coastguard Worker // Store followed by load: not OK on all.
1375*9880d681SAndroid Build Coastguard Worker // Load followed by store: OK on all.
1376*9880d681SAndroid Build Coastguard Worker // Load followed by load: OK on all.
1377*9880d681SAndroid Build Coastguard Worker continue;
1378*9880d681SAndroid Build Coastguard Worker }
1379*9880d681SAndroid Build Coastguard Worker
1380*9880d681SAndroid Build Coastguard Worker // For V4, special case ALLOCFRAME. Even though there is dependency
1381*9880d681SAndroid Build Coastguard Worker // between ALLOCFRAME and subsequent store, allow it to be packetized
1382*9880d681SAndroid Build Coastguard Worker // in a same packet. This implies that the store is using the caller's
1383*9880d681SAndroid Build Coastguard Worker // SP. Hence, offset needs to be updated accordingly.
1384*9880d681SAndroid Build Coastguard Worker if (DepType == SDep::Data && J->getOpcode() == Hexagon::S2_allocframe) {
1385*9880d681SAndroid Build Coastguard Worker unsigned Opc = I->getOpcode();
1386*9880d681SAndroid Build Coastguard Worker switch (Opc) {
1387*9880d681SAndroid Build Coastguard Worker case Hexagon::S2_storerd_io:
1388*9880d681SAndroid Build Coastguard Worker case Hexagon::S2_storeri_io:
1389*9880d681SAndroid Build Coastguard Worker case Hexagon::S2_storerh_io:
1390*9880d681SAndroid Build Coastguard Worker case Hexagon::S2_storerb_io:
1391*9880d681SAndroid Build Coastguard Worker if (I->getOperand(0).getReg() == HRI->getStackRegister()) {
1392*9880d681SAndroid Build Coastguard Worker int64_t Imm = I->getOperand(1).getImm();
1393*9880d681SAndroid Build Coastguard Worker int64_t NewOff = Imm - (FrameSize + HEXAGON_LRFP_SIZE);
1394*9880d681SAndroid Build Coastguard Worker if (HII->isValidOffset(Opc, NewOff)) {
1395*9880d681SAndroid Build Coastguard Worker GlueAllocframeStore = true;
1396*9880d681SAndroid Build Coastguard Worker // Since this store is to be glued with allocframe in the same
1397*9880d681SAndroid Build Coastguard Worker // packet, it will use SP of the previous stack frame, i.e.
1398*9880d681SAndroid Build Coastguard Worker // caller's SP. Therefore, we need to recalculate offset
1399*9880d681SAndroid Build Coastguard Worker // according to this change.
1400*9880d681SAndroid Build Coastguard Worker I->getOperand(1).setImm(NewOff);
1401*9880d681SAndroid Build Coastguard Worker continue;
1402*9880d681SAndroid Build Coastguard Worker }
1403*9880d681SAndroid Build Coastguard Worker }
1404*9880d681SAndroid Build Coastguard Worker default:
1405*9880d681SAndroid Build Coastguard Worker break;
1406*9880d681SAndroid Build Coastguard Worker }
1407*9880d681SAndroid Build Coastguard Worker }
1408*9880d681SAndroid Build Coastguard Worker
1409*9880d681SAndroid Build Coastguard Worker // There are certain anti-dependencies that cannot be ignored.
1410*9880d681SAndroid Build Coastguard Worker // Specifically:
1411*9880d681SAndroid Build Coastguard Worker // J2_call ... %R0<imp-def> ; SUJ
1412*9880d681SAndroid Build Coastguard Worker // R0 = ... ; SUI
1413*9880d681SAndroid Build Coastguard Worker // Those cannot be packetized together, since the call will observe
1414*9880d681SAndroid Build Coastguard Worker // the effect of the assignment to R0.
1415*9880d681SAndroid Build Coastguard Worker if (DepType == SDep::Anti && J->isCall()) {
1416*9880d681SAndroid Build Coastguard Worker // Check if I defines any volatile register. We should also check
1417*9880d681SAndroid Build Coastguard Worker // registers that the call may read, but these happen to be a
1418*9880d681SAndroid Build Coastguard Worker // subset of the volatile register set.
1419*9880d681SAndroid Build Coastguard Worker for (const MCPhysReg *P = J->getDesc().ImplicitDefs; P && *P; ++P) {
1420*9880d681SAndroid Build Coastguard Worker if (!I->modifiesRegister(*P, HRI))
1421*9880d681SAndroid Build Coastguard Worker continue;
1422*9880d681SAndroid Build Coastguard Worker FoundSequentialDependence = true;
1423*9880d681SAndroid Build Coastguard Worker break;
1424*9880d681SAndroid Build Coastguard Worker }
1425*9880d681SAndroid Build Coastguard Worker }
1426*9880d681SAndroid Build Coastguard Worker
1427*9880d681SAndroid Build Coastguard Worker // Skip over remaining anti-dependences. Two instructions that are
1428*9880d681SAndroid Build Coastguard Worker // anti-dependent can share a packet, since in most such cases all
1429*9880d681SAndroid Build Coastguard Worker // operands are read before any modifications take place.
1430*9880d681SAndroid Build Coastguard Worker // The exceptions are branch and call instructions, since they are
1431*9880d681SAndroid Build Coastguard Worker // executed after all other instructions have completed (at least
1432*9880d681SAndroid Build Coastguard Worker // conceptually).
1433*9880d681SAndroid Build Coastguard Worker if (DepType != SDep::Anti) {
1434*9880d681SAndroid Build Coastguard Worker FoundSequentialDependence = true;
1435*9880d681SAndroid Build Coastguard Worker break;
1436*9880d681SAndroid Build Coastguard Worker }
1437*9880d681SAndroid Build Coastguard Worker }
1438*9880d681SAndroid Build Coastguard Worker
1439*9880d681SAndroid Build Coastguard Worker if (FoundSequentialDependence) {
1440*9880d681SAndroid Build Coastguard Worker Dependence = true;
1441*9880d681SAndroid Build Coastguard Worker return false;
1442*9880d681SAndroid Build Coastguard Worker }
1443*9880d681SAndroid Build Coastguard Worker
1444*9880d681SAndroid Build Coastguard Worker return true;
1445*9880d681SAndroid Build Coastguard Worker }
1446*9880d681SAndroid Build Coastguard Worker
isLegalToPruneDependencies(SUnit * SUI,SUnit * SUJ)1447*9880d681SAndroid Build Coastguard Worker bool HexagonPacketizerList::isLegalToPruneDependencies(SUnit *SUI, SUnit *SUJ) {
1448*9880d681SAndroid Build Coastguard Worker MachineInstr *I = SUI->getInstr();
1449*9880d681SAndroid Build Coastguard Worker MachineInstr *J = SUJ->getInstr();
1450*9880d681SAndroid Build Coastguard Worker assert(I && J && "Unable to packetize null instruction!");
1451*9880d681SAndroid Build Coastguard Worker
1452*9880d681SAndroid Build Coastguard Worker if (cannotCoexist(I, J))
1453*9880d681SAndroid Build Coastguard Worker return false;
1454*9880d681SAndroid Build Coastguard Worker
1455*9880d681SAndroid Build Coastguard Worker if (!Dependence)
1456*9880d681SAndroid Build Coastguard Worker return true;
1457*9880d681SAndroid Build Coastguard Worker
1458*9880d681SAndroid Build Coastguard Worker // Check if the instruction was promoted to a dot-new. If so, demote it
1459*9880d681SAndroid Build Coastguard Worker // back into a dot-old.
1460*9880d681SAndroid Build Coastguard Worker if (PromotedToDotNew)
1461*9880d681SAndroid Build Coastguard Worker demoteToDotOld(I);
1462*9880d681SAndroid Build Coastguard Worker
1463*9880d681SAndroid Build Coastguard Worker cleanUpDotCur();
1464*9880d681SAndroid Build Coastguard Worker // Check if the instruction (must be a store) was glued with an allocframe
1465*9880d681SAndroid Build Coastguard Worker // instruction. If so, restore its offset to its original value, i.e. use
1466*9880d681SAndroid Build Coastguard Worker // current SP instead of caller's SP.
1467*9880d681SAndroid Build Coastguard Worker if (GlueAllocframeStore) {
1468*9880d681SAndroid Build Coastguard Worker unsigned FrameSize = MF.getFrameInfo()->getStackSize();
1469*9880d681SAndroid Build Coastguard Worker MachineOperand &MOff = I->getOperand(1);
1470*9880d681SAndroid Build Coastguard Worker MOff.setImm(MOff.getImm() + FrameSize + HEXAGON_LRFP_SIZE);
1471*9880d681SAndroid Build Coastguard Worker }
1472*9880d681SAndroid Build Coastguard Worker return false;
1473*9880d681SAndroid Build Coastguard Worker }
1474*9880d681SAndroid Build Coastguard Worker
1475*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator
addToPacket(MachineInstr & MI)1476*9880d681SAndroid Build Coastguard Worker HexagonPacketizerList::addToPacket(MachineInstr &MI) {
1477*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator MII = MI;
1478*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *MBB = MI.getParent();
1479*9880d681SAndroid Build Coastguard Worker if (MI.isImplicitDef()) {
1480*9880d681SAndroid Build Coastguard Worker unsigned R = MI.getOperand(0).getReg();
1481*9880d681SAndroid Build Coastguard Worker if (Hexagon::IntRegsRegClass.contains(R)) {
1482*9880d681SAndroid Build Coastguard Worker MCSuperRegIterator S(R, HRI, false);
1483*9880d681SAndroid Build Coastguard Worker MI.addOperand(MachineOperand::CreateReg(*S, true, true));
1484*9880d681SAndroid Build Coastguard Worker }
1485*9880d681SAndroid Build Coastguard Worker return MII;
1486*9880d681SAndroid Build Coastguard Worker }
1487*9880d681SAndroid Build Coastguard Worker assert(ResourceTracker->canReserveResources(MI));
1488*9880d681SAndroid Build Coastguard Worker
1489*9880d681SAndroid Build Coastguard Worker bool ExtMI = HII->isExtended(&MI) || HII->isConstExtended(&MI);
1490*9880d681SAndroid Build Coastguard Worker bool Good = true;
1491*9880d681SAndroid Build Coastguard Worker
1492*9880d681SAndroid Build Coastguard Worker if (GlueToNewValueJump) {
1493*9880d681SAndroid Build Coastguard Worker MachineInstr &NvjMI = *++MII;
1494*9880d681SAndroid Build Coastguard Worker // We need to put both instructions in the same packet: MI and NvjMI.
1495*9880d681SAndroid Build Coastguard Worker // Either of them can require a constant extender. Try to add both to
1496*9880d681SAndroid Build Coastguard Worker // the current packet, and if that fails, end the packet and start a
1497*9880d681SAndroid Build Coastguard Worker // new one.
1498*9880d681SAndroid Build Coastguard Worker ResourceTracker->reserveResources(MI);
1499*9880d681SAndroid Build Coastguard Worker if (ExtMI)
1500*9880d681SAndroid Build Coastguard Worker Good = tryAllocateResourcesForConstExt(true);
1501*9880d681SAndroid Build Coastguard Worker
1502*9880d681SAndroid Build Coastguard Worker bool ExtNvjMI = HII->isExtended(&NvjMI) || HII->isConstExtended(&NvjMI);
1503*9880d681SAndroid Build Coastguard Worker if (Good) {
1504*9880d681SAndroid Build Coastguard Worker if (ResourceTracker->canReserveResources(NvjMI))
1505*9880d681SAndroid Build Coastguard Worker ResourceTracker->reserveResources(NvjMI);
1506*9880d681SAndroid Build Coastguard Worker else
1507*9880d681SAndroid Build Coastguard Worker Good = false;
1508*9880d681SAndroid Build Coastguard Worker }
1509*9880d681SAndroid Build Coastguard Worker if (Good && ExtNvjMI)
1510*9880d681SAndroid Build Coastguard Worker Good = tryAllocateResourcesForConstExt(true);
1511*9880d681SAndroid Build Coastguard Worker
1512*9880d681SAndroid Build Coastguard Worker if (!Good) {
1513*9880d681SAndroid Build Coastguard Worker endPacket(MBB, MI);
1514*9880d681SAndroid Build Coastguard Worker assert(ResourceTracker->canReserveResources(MI));
1515*9880d681SAndroid Build Coastguard Worker ResourceTracker->reserveResources(MI);
1516*9880d681SAndroid Build Coastguard Worker if (ExtMI) {
1517*9880d681SAndroid Build Coastguard Worker assert(canReserveResourcesForConstExt());
1518*9880d681SAndroid Build Coastguard Worker tryAllocateResourcesForConstExt(true);
1519*9880d681SAndroid Build Coastguard Worker }
1520*9880d681SAndroid Build Coastguard Worker assert(ResourceTracker->canReserveResources(NvjMI));
1521*9880d681SAndroid Build Coastguard Worker ResourceTracker->reserveResources(NvjMI);
1522*9880d681SAndroid Build Coastguard Worker if (ExtNvjMI) {
1523*9880d681SAndroid Build Coastguard Worker assert(canReserveResourcesForConstExt());
1524*9880d681SAndroid Build Coastguard Worker reserveResourcesForConstExt();
1525*9880d681SAndroid Build Coastguard Worker }
1526*9880d681SAndroid Build Coastguard Worker }
1527*9880d681SAndroid Build Coastguard Worker CurrentPacketMIs.push_back(&MI);
1528*9880d681SAndroid Build Coastguard Worker CurrentPacketMIs.push_back(&NvjMI);
1529*9880d681SAndroid Build Coastguard Worker return MII;
1530*9880d681SAndroid Build Coastguard Worker }
1531*9880d681SAndroid Build Coastguard Worker
1532*9880d681SAndroid Build Coastguard Worker ResourceTracker->reserveResources(MI);
1533*9880d681SAndroid Build Coastguard Worker if (ExtMI && !tryAllocateResourcesForConstExt(true)) {
1534*9880d681SAndroid Build Coastguard Worker endPacket(MBB, MI);
1535*9880d681SAndroid Build Coastguard Worker if (PromotedToDotNew)
1536*9880d681SAndroid Build Coastguard Worker demoteToDotOld(&MI);
1537*9880d681SAndroid Build Coastguard Worker ResourceTracker->reserveResources(MI);
1538*9880d681SAndroid Build Coastguard Worker reserveResourcesForConstExt();
1539*9880d681SAndroid Build Coastguard Worker }
1540*9880d681SAndroid Build Coastguard Worker
1541*9880d681SAndroid Build Coastguard Worker CurrentPacketMIs.push_back(&MI);
1542*9880d681SAndroid Build Coastguard Worker return MII;
1543*9880d681SAndroid Build Coastguard Worker }
1544*9880d681SAndroid Build Coastguard Worker
endPacket(MachineBasicBlock * MBB,MachineBasicBlock::iterator MI)1545*9880d681SAndroid Build Coastguard Worker void HexagonPacketizerList::endPacket(MachineBasicBlock *MBB,
1546*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator MI) {
1547*9880d681SAndroid Build Coastguard Worker OldPacketMIs = CurrentPacketMIs;
1548*9880d681SAndroid Build Coastguard Worker VLIWPacketizerList::endPacket(MBB, MI);
1549*9880d681SAndroid Build Coastguard Worker }
1550*9880d681SAndroid Build Coastguard Worker
shouldAddToPacket(const MachineInstr & MI)1551*9880d681SAndroid Build Coastguard Worker bool HexagonPacketizerList::shouldAddToPacket(const MachineInstr &MI) {
1552*9880d681SAndroid Build Coastguard Worker return !producesStall(&MI);
1553*9880d681SAndroid Build Coastguard Worker }
1554*9880d681SAndroid Build Coastguard Worker
1555*9880d681SAndroid Build Coastguard Worker
1556*9880d681SAndroid Build Coastguard Worker // Return true when ConsMI uses a register defined by ProdMI.
isDependent(const MachineInstr * ProdMI,const MachineInstr * ConsMI)1557*9880d681SAndroid Build Coastguard Worker static bool isDependent(const MachineInstr *ProdMI,
1558*9880d681SAndroid Build Coastguard Worker const MachineInstr *ConsMI) {
1559*9880d681SAndroid Build Coastguard Worker if (!ProdMI->getOperand(0).isReg())
1560*9880d681SAndroid Build Coastguard Worker return false;
1561*9880d681SAndroid Build Coastguard Worker unsigned DstReg = ProdMI->getOperand(0).getReg();
1562*9880d681SAndroid Build Coastguard Worker
1563*9880d681SAndroid Build Coastguard Worker for (auto &Op : ConsMI->operands())
1564*9880d681SAndroid Build Coastguard Worker if (Op.isReg() && Op.isUse() && Op.getReg() == DstReg)
1565*9880d681SAndroid Build Coastguard Worker // The MIs depend on each other.
1566*9880d681SAndroid Build Coastguard Worker return true;
1567*9880d681SAndroid Build Coastguard Worker
1568*9880d681SAndroid Build Coastguard Worker return false;
1569*9880d681SAndroid Build Coastguard Worker }
1570*9880d681SAndroid Build Coastguard Worker
1571*9880d681SAndroid Build Coastguard Worker // V60 forward scheduling.
producesStall(const MachineInstr * I)1572*9880d681SAndroid Build Coastguard Worker bool HexagonPacketizerList::producesStall(const MachineInstr *I) {
1573*9880d681SAndroid Build Coastguard Worker // Check whether the previous packet is in a different loop. If this is the
1574*9880d681SAndroid Build Coastguard Worker // case, there is little point in trying to avoid a stall because that would
1575*9880d681SAndroid Build Coastguard Worker // favor the rare case (loop entry) over the common case (loop iteration).
1576*9880d681SAndroid Build Coastguard Worker //
1577*9880d681SAndroid Build Coastguard Worker // TODO: We should really be able to check all the incoming edges if this is
1578*9880d681SAndroid Build Coastguard Worker // the first packet in a basic block, so we can avoid stalls from the loop
1579*9880d681SAndroid Build Coastguard Worker // backedge.
1580*9880d681SAndroid Build Coastguard Worker if (!OldPacketMIs.empty()) {
1581*9880d681SAndroid Build Coastguard Worker auto *OldBB = OldPacketMIs.front()->getParent();
1582*9880d681SAndroid Build Coastguard Worker auto *ThisBB = I->getParent();
1583*9880d681SAndroid Build Coastguard Worker if (MLI->getLoopFor(OldBB) != MLI->getLoopFor(ThisBB))
1584*9880d681SAndroid Build Coastguard Worker return false;
1585*9880d681SAndroid Build Coastguard Worker }
1586*9880d681SAndroid Build Coastguard Worker
1587*9880d681SAndroid Build Coastguard Worker // Check for stall between two vector instructions.
1588*9880d681SAndroid Build Coastguard Worker if (HII->isV60VectorInstruction(I)) {
1589*9880d681SAndroid Build Coastguard Worker for (auto J : OldPacketMIs) {
1590*9880d681SAndroid Build Coastguard Worker if (!HII->isV60VectorInstruction(J))
1591*9880d681SAndroid Build Coastguard Worker continue;
1592*9880d681SAndroid Build Coastguard Worker if (isDependent(J, I) && !HII->isVecUsableNextPacket(J, I))
1593*9880d681SAndroid Build Coastguard Worker return true;
1594*9880d681SAndroid Build Coastguard Worker }
1595*9880d681SAndroid Build Coastguard Worker return false;
1596*9880d681SAndroid Build Coastguard Worker }
1597*9880d681SAndroid Build Coastguard Worker
1598*9880d681SAndroid Build Coastguard Worker // Check for stall between two scalar instructions. First, check that
1599*9880d681SAndroid Build Coastguard Worker // there is no definition of a use in the current packet, because it
1600*9880d681SAndroid Build Coastguard Worker // may be a candidate for .new.
1601*9880d681SAndroid Build Coastguard Worker for (auto J : CurrentPacketMIs)
1602*9880d681SAndroid Build Coastguard Worker if (!HII->isV60VectorInstruction(J) && isDependent(J, I))
1603*9880d681SAndroid Build Coastguard Worker return false;
1604*9880d681SAndroid Build Coastguard Worker
1605*9880d681SAndroid Build Coastguard Worker // Check for stall between I and instructions in the previous packet.
1606*9880d681SAndroid Build Coastguard Worker if (MF.getSubtarget<HexagonSubtarget>().useBSBScheduling()) {
1607*9880d681SAndroid Build Coastguard Worker for (auto J : OldPacketMIs) {
1608*9880d681SAndroid Build Coastguard Worker if (HII->isV60VectorInstruction(J))
1609*9880d681SAndroid Build Coastguard Worker continue;
1610*9880d681SAndroid Build Coastguard Worker if (!HII->isLateInstrFeedsEarlyInstr(J, I))
1611*9880d681SAndroid Build Coastguard Worker continue;
1612*9880d681SAndroid Build Coastguard Worker if (isDependent(J, I) && !HII->canExecuteInBundle(J, I))
1613*9880d681SAndroid Build Coastguard Worker return true;
1614*9880d681SAndroid Build Coastguard Worker }
1615*9880d681SAndroid Build Coastguard Worker }
1616*9880d681SAndroid Build Coastguard Worker
1617*9880d681SAndroid Build Coastguard Worker return false;
1618*9880d681SAndroid Build Coastguard Worker }
1619*9880d681SAndroid Build Coastguard Worker
1620*9880d681SAndroid Build Coastguard Worker
1621*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
1622*9880d681SAndroid Build Coastguard Worker // Public Constructor Functions
1623*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
1624*9880d681SAndroid Build Coastguard Worker
createHexagonPacketizer()1625*9880d681SAndroid Build Coastguard Worker FunctionPass *llvm::createHexagonPacketizer() {
1626*9880d681SAndroid Build Coastguard Worker return new HexagonPacketizer();
1627*9880d681SAndroid Build Coastguard Worker }
1628