1*9880d681SAndroid Build Coastguard Worker //===-- MLxExpansionPass.cpp - Expand MLx instrs to avoid hazards ---------===//
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 // Expand VFP / NEON floating point MLA / MLS instructions (each to a pair of
11*9880d681SAndroid Build Coastguard Worker // multiple and add / sub instructions) when special VMLx hazards are detected.
12*9880d681SAndroid Build Coastguard Worker //
13*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
14*9880d681SAndroid Build Coastguard Worker
15*9880d681SAndroid Build Coastguard Worker #include "ARM.h"
16*9880d681SAndroid Build Coastguard Worker #include "ARMBaseInstrInfo.h"
17*9880d681SAndroid Build Coastguard Worker #include "ARMSubtarget.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SmallPtrSet.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Statistic.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFunctionPass.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineInstr.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineInstrBuilder.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineRegisterInfo.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/CommandLine.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetRegisterInfo.h"
28*9880d681SAndroid Build Coastguard Worker using namespace llvm;
29*9880d681SAndroid Build Coastguard Worker
30*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "mlx-expansion"
31*9880d681SAndroid Build Coastguard Worker
32*9880d681SAndroid Build Coastguard Worker static cl::opt<bool>
33*9880d681SAndroid Build Coastguard Worker ForceExapnd("expand-all-fp-mlx", cl::init(false), cl::Hidden);
34*9880d681SAndroid Build Coastguard Worker static cl::opt<unsigned>
35*9880d681SAndroid Build Coastguard Worker ExpandLimit("expand-limit", cl::init(~0U), cl::Hidden);
36*9880d681SAndroid Build Coastguard Worker
37*9880d681SAndroid Build Coastguard Worker STATISTIC(NumExpand, "Number of fp MLA / MLS instructions expanded");
38*9880d681SAndroid Build Coastguard Worker
39*9880d681SAndroid Build Coastguard Worker namespace {
40*9880d681SAndroid Build Coastguard Worker struct MLxExpansion : public MachineFunctionPass {
41*9880d681SAndroid Build Coastguard Worker static char ID;
MLxExpansion__anone0effe0a0111::MLxExpansion42*9880d681SAndroid Build Coastguard Worker MLxExpansion() : MachineFunctionPass(ID) {}
43*9880d681SAndroid Build Coastguard Worker
44*9880d681SAndroid Build Coastguard Worker bool runOnMachineFunction(MachineFunction &Fn) override;
45*9880d681SAndroid Build Coastguard Worker
getPassName__anone0effe0a0111::MLxExpansion46*9880d681SAndroid Build Coastguard Worker const char *getPassName() const override {
47*9880d681SAndroid Build Coastguard Worker return "ARM MLA / MLS expansion pass";
48*9880d681SAndroid Build Coastguard Worker }
49*9880d681SAndroid Build Coastguard Worker
50*9880d681SAndroid Build Coastguard Worker private:
51*9880d681SAndroid Build Coastguard Worker const ARMBaseInstrInfo *TII;
52*9880d681SAndroid Build Coastguard Worker const TargetRegisterInfo *TRI;
53*9880d681SAndroid Build Coastguard Worker MachineRegisterInfo *MRI;
54*9880d681SAndroid Build Coastguard Worker
55*9880d681SAndroid Build Coastguard Worker bool isLikeA9;
56*9880d681SAndroid Build Coastguard Worker bool isSwift;
57*9880d681SAndroid Build Coastguard Worker unsigned MIIdx;
58*9880d681SAndroid Build Coastguard Worker MachineInstr* LastMIs[4];
59*9880d681SAndroid Build Coastguard Worker SmallPtrSet<MachineInstr*, 4> IgnoreStall;
60*9880d681SAndroid Build Coastguard Worker
61*9880d681SAndroid Build Coastguard Worker void clearStack();
62*9880d681SAndroid Build Coastguard Worker void pushStack(MachineInstr *MI);
63*9880d681SAndroid Build Coastguard Worker MachineInstr *getAccDefMI(MachineInstr *MI) const;
64*9880d681SAndroid Build Coastguard Worker unsigned getDefReg(MachineInstr *MI) const;
65*9880d681SAndroid Build Coastguard Worker bool hasLoopHazard(MachineInstr *MI) const;
66*9880d681SAndroid Build Coastguard Worker bool hasRAWHazard(unsigned Reg, MachineInstr *MI) const;
67*9880d681SAndroid Build Coastguard Worker bool FindMLxHazard(MachineInstr *MI);
68*9880d681SAndroid Build Coastguard Worker void ExpandFPMLxInstruction(MachineBasicBlock &MBB, MachineInstr *MI,
69*9880d681SAndroid Build Coastguard Worker unsigned MulOpc, unsigned AddSubOpc,
70*9880d681SAndroid Build Coastguard Worker bool NegAcc, bool HasLane);
71*9880d681SAndroid Build Coastguard Worker bool ExpandFPMLxInstructions(MachineBasicBlock &MBB);
72*9880d681SAndroid Build Coastguard Worker };
73*9880d681SAndroid Build Coastguard Worker char MLxExpansion::ID = 0;
74*9880d681SAndroid Build Coastguard Worker }
75*9880d681SAndroid Build Coastguard Worker
clearStack()76*9880d681SAndroid Build Coastguard Worker void MLxExpansion::clearStack() {
77*9880d681SAndroid Build Coastguard Worker std::fill(LastMIs, LastMIs + 4, nullptr);
78*9880d681SAndroid Build Coastguard Worker MIIdx = 0;
79*9880d681SAndroid Build Coastguard Worker }
80*9880d681SAndroid Build Coastguard Worker
pushStack(MachineInstr * MI)81*9880d681SAndroid Build Coastguard Worker void MLxExpansion::pushStack(MachineInstr *MI) {
82*9880d681SAndroid Build Coastguard Worker LastMIs[MIIdx] = MI;
83*9880d681SAndroid Build Coastguard Worker if (++MIIdx == 4)
84*9880d681SAndroid Build Coastguard Worker MIIdx = 0;
85*9880d681SAndroid Build Coastguard Worker }
86*9880d681SAndroid Build Coastguard Worker
getAccDefMI(MachineInstr * MI) const87*9880d681SAndroid Build Coastguard Worker MachineInstr *MLxExpansion::getAccDefMI(MachineInstr *MI) const {
88*9880d681SAndroid Build Coastguard Worker // Look past COPY and INSERT_SUBREG instructions to find the
89*9880d681SAndroid Build Coastguard Worker // real definition MI. This is important for _sfp instructions.
90*9880d681SAndroid Build Coastguard Worker unsigned Reg = MI->getOperand(1).getReg();
91*9880d681SAndroid Build Coastguard Worker if (TargetRegisterInfo::isPhysicalRegister(Reg))
92*9880d681SAndroid Build Coastguard Worker return nullptr;
93*9880d681SAndroid Build Coastguard Worker
94*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *MBB = MI->getParent();
95*9880d681SAndroid Build Coastguard Worker MachineInstr *DefMI = MRI->getVRegDef(Reg);
96*9880d681SAndroid Build Coastguard Worker while (true) {
97*9880d681SAndroid Build Coastguard Worker if (DefMI->getParent() != MBB)
98*9880d681SAndroid Build Coastguard Worker break;
99*9880d681SAndroid Build Coastguard Worker if (DefMI->isCopyLike()) {
100*9880d681SAndroid Build Coastguard Worker Reg = DefMI->getOperand(1).getReg();
101*9880d681SAndroid Build Coastguard Worker if (TargetRegisterInfo::isVirtualRegister(Reg)) {
102*9880d681SAndroid Build Coastguard Worker DefMI = MRI->getVRegDef(Reg);
103*9880d681SAndroid Build Coastguard Worker continue;
104*9880d681SAndroid Build Coastguard Worker }
105*9880d681SAndroid Build Coastguard Worker } else if (DefMI->isInsertSubreg()) {
106*9880d681SAndroid Build Coastguard Worker Reg = DefMI->getOperand(2).getReg();
107*9880d681SAndroid Build Coastguard Worker if (TargetRegisterInfo::isVirtualRegister(Reg)) {
108*9880d681SAndroid Build Coastguard Worker DefMI = MRI->getVRegDef(Reg);
109*9880d681SAndroid Build Coastguard Worker continue;
110*9880d681SAndroid Build Coastguard Worker }
111*9880d681SAndroid Build Coastguard Worker }
112*9880d681SAndroid Build Coastguard Worker break;
113*9880d681SAndroid Build Coastguard Worker }
114*9880d681SAndroid Build Coastguard Worker return DefMI;
115*9880d681SAndroid Build Coastguard Worker }
116*9880d681SAndroid Build Coastguard Worker
getDefReg(MachineInstr * MI) const117*9880d681SAndroid Build Coastguard Worker unsigned MLxExpansion::getDefReg(MachineInstr *MI) const {
118*9880d681SAndroid Build Coastguard Worker unsigned Reg = MI->getOperand(0).getReg();
119*9880d681SAndroid Build Coastguard Worker if (TargetRegisterInfo::isPhysicalRegister(Reg) ||
120*9880d681SAndroid Build Coastguard Worker !MRI->hasOneNonDBGUse(Reg))
121*9880d681SAndroid Build Coastguard Worker return Reg;
122*9880d681SAndroid Build Coastguard Worker
123*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *MBB = MI->getParent();
124*9880d681SAndroid Build Coastguard Worker MachineInstr *UseMI = &*MRI->use_instr_nodbg_begin(Reg);
125*9880d681SAndroid Build Coastguard Worker if (UseMI->getParent() != MBB)
126*9880d681SAndroid Build Coastguard Worker return Reg;
127*9880d681SAndroid Build Coastguard Worker
128*9880d681SAndroid Build Coastguard Worker while (UseMI->isCopy() || UseMI->isInsertSubreg()) {
129*9880d681SAndroid Build Coastguard Worker Reg = UseMI->getOperand(0).getReg();
130*9880d681SAndroid Build Coastguard Worker if (TargetRegisterInfo::isPhysicalRegister(Reg) ||
131*9880d681SAndroid Build Coastguard Worker !MRI->hasOneNonDBGUse(Reg))
132*9880d681SAndroid Build Coastguard Worker return Reg;
133*9880d681SAndroid Build Coastguard Worker UseMI = &*MRI->use_instr_nodbg_begin(Reg);
134*9880d681SAndroid Build Coastguard Worker if (UseMI->getParent() != MBB)
135*9880d681SAndroid Build Coastguard Worker return Reg;
136*9880d681SAndroid Build Coastguard Worker }
137*9880d681SAndroid Build Coastguard Worker
138*9880d681SAndroid Build Coastguard Worker return Reg;
139*9880d681SAndroid Build Coastguard Worker }
140*9880d681SAndroid Build Coastguard Worker
141*9880d681SAndroid Build Coastguard Worker /// hasLoopHazard - Check whether an MLx instruction is chained to itself across
142*9880d681SAndroid Build Coastguard Worker /// a single-MBB loop.
hasLoopHazard(MachineInstr * MI) const143*9880d681SAndroid Build Coastguard Worker bool MLxExpansion::hasLoopHazard(MachineInstr *MI) const {
144*9880d681SAndroid Build Coastguard Worker unsigned Reg = MI->getOperand(1).getReg();
145*9880d681SAndroid Build Coastguard Worker if (TargetRegisterInfo::isPhysicalRegister(Reg))
146*9880d681SAndroid Build Coastguard Worker return false;
147*9880d681SAndroid Build Coastguard Worker
148*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *MBB = MI->getParent();
149*9880d681SAndroid Build Coastguard Worker MachineInstr *DefMI = MRI->getVRegDef(Reg);
150*9880d681SAndroid Build Coastguard Worker while (true) {
151*9880d681SAndroid Build Coastguard Worker outer_continue:
152*9880d681SAndroid Build Coastguard Worker if (DefMI->getParent() != MBB)
153*9880d681SAndroid Build Coastguard Worker break;
154*9880d681SAndroid Build Coastguard Worker
155*9880d681SAndroid Build Coastguard Worker if (DefMI->isPHI()) {
156*9880d681SAndroid Build Coastguard Worker for (unsigned i = 1, e = DefMI->getNumOperands(); i < e; i += 2) {
157*9880d681SAndroid Build Coastguard Worker if (DefMI->getOperand(i + 1).getMBB() == MBB) {
158*9880d681SAndroid Build Coastguard Worker unsigned SrcReg = DefMI->getOperand(i).getReg();
159*9880d681SAndroid Build Coastguard Worker if (TargetRegisterInfo::isVirtualRegister(SrcReg)) {
160*9880d681SAndroid Build Coastguard Worker DefMI = MRI->getVRegDef(SrcReg);
161*9880d681SAndroid Build Coastguard Worker goto outer_continue;
162*9880d681SAndroid Build Coastguard Worker }
163*9880d681SAndroid Build Coastguard Worker }
164*9880d681SAndroid Build Coastguard Worker }
165*9880d681SAndroid Build Coastguard Worker } else if (DefMI->isCopyLike()) {
166*9880d681SAndroid Build Coastguard Worker Reg = DefMI->getOperand(1).getReg();
167*9880d681SAndroid Build Coastguard Worker if (TargetRegisterInfo::isVirtualRegister(Reg)) {
168*9880d681SAndroid Build Coastguard Worker DefMI = MRI->getVRegDef(Reg);
169*9880d681SAndroid Build Coastguard Worker continue;
170*9880d681SAndroid Build Coastguard Worker }
171*9880d681SAndroid Build Coastguard Worker } else if (DefMI->isInsertSubreg()) {
172*9880d681SAndroid Build Coastguard Worker Reg = DefMI->getOperand(2).getReg();
173*9880d681SAndroid Build Coastguard Worker if (TargetRegisterInfo::isVirtualRegister(Reg)) {
174*9880d681SAndroid Build Coastguard Worker DefMI = MRI->getVRegDef(Reg);
175*9880d681SAndroid Build Coastguard Worker continue;
176*9880d681SAndroid Build Coastguard Worker }
177*9880d681SAndroid Build Coastguard Worker }
178*9880d681SAndroid Build Coastguard Worker
179*9880d681SAndroid Build Coastguard Worker break;
180*9880d681SAndroid Build Coastguard Worker }
181*9880d681SAndroid Build Coastguard Worker
182*9880d681SAndroid Build Coastguard Worker return DefMI == MI;
183*9880d681SAndroid Build Coastguard Worker }
184*9880d681SAndroid Build Coastguard Worker
hasRAWHazard(unsigned Reg,MachineInstr * MI) const185*9880d681SAndroid Build Coastguard Worker bool MLxExpansion::hasRAWHazard(unsigned Reg, MachineInstr *MI) const {
186*9880d681SAndroid Build Coastguard Worker // FIXME: Detect integer instructions properly.
187*9880d681SAndroid Build Coastguard Worker const MCInstrDesc &MCID = MI->getDesc();
188*9880d681SAndroid Build Coastguard Worker unsigned Domain = MCID.TSFlags & ARMII::DomainMask;
189*9880d681SAndroid Build Coastguard Worker if (MI->mayStore())
190*9880d681SAndroid Build Coastguard Worker return false;
191*9880d681SAndroid Build Coastguard Worker unsigned Opcode = MCID.getOpcode();
192*9880d681SAndroid Build Coastguard Worker if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD)
193*9880d681SAndroid Build Coastguard Worker return false;
194*9880d681SAndroid Build Coastguard Worker if ((Domain & ARMII::DomainVFP) || (Domain & ARMII::DomainNEON))
195*9880d681SAndroid Build Coastguard Worker return MI->readsRegister(Reg, TRI);
196*9880d681SAndroid Build Coastguard Worker return false;
197*9880d681SAndroid Build Coastguard Worker }
198*9880d681SAndroid Build Coastguard Worker
isFpMulInstruction(unsigned Opcode)199*9880d681SAndroid Build Coastguard Worker static bool isFpMulInstruction(unsigned Opcode) {
200*9880d681SAndroid Build Coastguard Worker switch (Opcode) {
201*9880d681SAndroid Build Coastguard Worker case ARM::VMULS:
202*9880d681SAndroid Build Coastguard Worker case ARM::VMULfd:
203*9880d681SAndroid Build Coastguard Worker case ARM::VMULfq:
204*9880d681SAndroid Build Coastguard Worker case ARM::VMULD:
205*9880d681SAndroid Build Coastguard Worker case ARM::VMULslfd:
206*9880d681SAndroid Build Coastguard Worker case ARM::VMULslfq:
207*9880d681SAndroid Build Coastguard Worker return true;
208*9880d681SAndroid Build Coastguard Worker default:
209*9880d681SAndroid Build Coastguard Worker return false;
210*9880d681SAndroid Build Coastguard Worker }
211*9880d681SAndroid Build Coastguard Worker }
212*9880d681SAndroid Build Coastguard Worker
FindMLxHazard(MachineInstr * MI)213*9880d681SAndroid Build Coastguard Worker bool MLxExpansion::FindMLxHazard(MachineInstr *MI) {
214*9880d681SAndroid Build Coastguard Worker if (NumExpand >= ExpandLimit)
215*9880d681SAndroid Build Coastguard Worker return false;
216*9880d681SAndroid Build Coastguard Worker
217*9880d681SAndroid Build Coastguard Worker if (ForceExapnd)
218*9880d681SAndroid Build Coastguard Worker return true;
219*9880d681SAndroid Build Coastguard Worker
220*9880d681SAndroid Build Coastguard Worker MachineInstr *DefMI = getAccDefMI(MI);
221*9880d681SAndroid Build Coastguard Worker if (TII->isFpMLxInstruction(DefMI->getOpcode())) {
222*9880d681SAndroid Build Coastguard Worker // r0 = vmla
223*9880d681SAndroid Build Coastguard Worker // r3 = vmla r0, r1, r2
224*9880d681SAndroid Build Coastguard Worker // takes 16 - 17 cycles
225*9880d681SAndroid Build Coastguard Worker //
226*9880d681SAndroid Build Coastguard Worker // r0 = vmla
227*9880d681SAndroid Build Coastguard Worker // r4 = vmul r1, r2
228*9880d681SAndroid Build Coastguard Worker // r3 = vadd r0, r4
229*9880d681SAndroid Build Coastguard Worker // takes about 14 - 15 cycles even with vmul stalling for 4 cycles.
230*9880d681SAndroid Build Coastguard Worker IgnoreStall.insert(DefMI);
231*9880d681SAndroid Build Coastguard Worker return true;
232*9880d681SAndroid Build Coastguard Worker }
233*9880d681SAndroid Build Coastguard Worker
234*9880d681SAndroid Build Coastguard Worker // On Swift, we mostly care about hazards from multiplication instructions
235*9880d681SAndroid Build Coastguard Worker // writing the accumulator and the pipelining of loop iterations by out-of-
236*9880d681SAndroid Build Coastguard Worker // order execution.
237*9880d681SAndroid Build Coastguard Worker if (isSwift)
238*9880d681SAndroid Build Coastguard Worker return isFpMulInstruction(DefMI->getOpcode()) || hasLoopHazard(MI);
239*9880d681SAndroid Build Coastguard Worker
240*9880d681SAndroid Build Coastguard Worker if (IgnoreStall.count(MI))
241*9880d681SAndroid Build Coastguard Worker return false;
242*9880d681SAndroid Build Coastguard Worker
243*9880d681SAndroid Build Coastguard Worker // If a VMLA.F is followed by an VADD.F or VMUL.F with no RAW hazard, the
244*9880d681SAndroid Build Coastguard Worker // VADD.F or VMUL.F will stall 4 cycles before issue. The 4 cycle stall
245*9880d681SAndroid Build Coastguard Worker // preserves the in-order retirement of the instructions.
246*9880d681SAndroid Build Coastguard Worker // Look at the next few instructions, if *most* of them can cause hazards,
247*9880d681SAndroid Build Coastguard Worker // then the scheduler can't *fix* this, we'd better break up the VMLA.
248*9880d681SAndroid Build Coastguard Worker unsigned Limit1 = isLikeA9 ? 1 : 4;
249*9880d681SAndroid Build Coastguard Worker unsigned Limit2 = isLikeA9 ? 1 : 4;
250*9880d681SAndroid Build Coastguard Worker for (unsigned i = 1; i <= 4; ++i) {
251*9880d681SAndroid Build Coastguard Worker int Idx = ((int)MIIdx - i + 4) % 4;
252*9880d681SAndroid Build Coastguard Worker MachineInstr *NextMI = LastMIs[Idx];
253*9880d681SAndroid Build Coastguard Worker if (!NextMI)
254*9880d681SAndroid Build Coastguard Worker continue;
255*9880d681SAndroid Build Coastguard Worker
256*9880d681SAndroid Build Coastguard Worker if (TII->canCauseFpMLxStall(NextMI->getOpcode())) {
257*9880d681SAndroid Build Coastguard Worker if (i <= Limit1)
258*9880d681SAndroid Build Coastguard Worker return true;
259*9880d681SAndroid Build Coastguard Worker }
260*9880d681SAndroid Build Coastguard Worker
261*9880d681SAndroid Build Coastguard Worker // Look for VMLx RAW hazard.
262*9880d681SAndroid Build Coastguard Worker if (i <= Limit2 && hasRAWHazard(getDefReg(MI), NextMI))
263*9880d681SAndroid Build Coastguard Worker return true;
264*9880d681SAndroid Build Coastguard Worker }
265*9880d681SAndroid Build Coastguard Worker
266*9880d681SAndroid Build Coastguard Worker return false;
267*9880d681SAndroid Build Coastguard Worker }
268*9880d681SAndroid Build Coastguard Worker
269*9880d681SAndroid Build Coastguard Worker /// ExpandFPMLxInstructions - Expand a MLA / MLS instruction into a pair
270*9880d681SAndroid Build Coastguard Worker /// of MUL + ADD / SUB instructions.
271*9880d681SAndroid Build Coastguard Worker void
ExpandFPMLxInstruction(MachineBasicBlock & MBB,MachineInstr * MI,unsigned MulOpc,unsigned AddSubOpc,bool NegAcc,bool HasLane)272*9880d681SAndroid Build Coastguard Worker MLxExpansion::ExpandFPMLxInstruction(MachineBasicBlock &MBB, MachineInstr *MI,
273*9880d681SAndroid Build Coastguard Worker unsigned MulOpc, unsigned AddSubOpc,
274*9880d681SAndroid Build Coastguard Worker bool NegAcc, bool HasLane) {
275*9880d681SAndroid Build Coastguard Worker unsigned DstReg = MI->getOperand(0).getReg();
276*9880d681SAndroid Build Coastguard Worker bool DstDead = MI->getOperand(0).isDead();
277*9880d681SAndroid Build Coastguard Worker unsigned AccReg = MI->getOperand(1).getReg();
278*9880d681SAndroid Build Coastguard Worker unsigned Src1Reg = MI->getOperand(2).getReg();
279*9880d681SAndroid Build Coastguard Worker unsigned Src2Reg = MI->getOperand(3).getReg();
280*9880d681SAndroid Build Coastguard Worker bool Src1Kill = MI->getOperand(2).isKill();
281*9880d681SAndroid Build Coastguard Worker bool Src2Kill = MI->getOperand(3).isKill();
282*9880d681SAndroid Build Coastguard Worker unsigned LaneImm = HasLane ? MI->getOperand(4).getImm() : 0;
283*9880d681SAndroid Build Coastguard Worker unsigned NextOp = HasLane ? 5 : 4;
284*9880d681SAndroid Build Coastguard Worker ARMCC::CondCodes Pred = (ARMCC::CondCodes)MI->getOperand(NextOp).getImm();
285*9880d681SAndroid Build Coastguard Worker unsigned PredReg = MI->getOperand(++NextOp).getReg();
286*9880d681SAndroid Build Coastguard Worker
287*9880d681SAndroid Build Coastguard Worker const MCInstrDesc &MCID1 = TII->get(MulOpc);
288*9880d681SAndroid Build Coastguard Worker const MCInstrDesc &MCID2 = TII->get(AddSubOpc);
289*9880d681SAndroid Build Coastguard Worker const MachineFunction &MF = *MI->getParent()->getParent();
290*9880d681SAndroid Build Coastguard Worker unsigned TmpReg = MRI->createVirtualRegister(
291*9880d681SAndroid Build Coastguard Worker TII->getRegClass(MCID1, 0, TRI, MF));
292*9880d681SAndroid Build Coastguard Worker
293*9880d681SAndroid Build Coastguard Worker MachineInstrBuilder MIB = BuildMI(MBB, MI, MI->getDebugLoc(), MCID1, TmpReg)
294*9880d681SAndroid Build Coastguard Worker .addReg(Src1Reg, getKillRegState(Src1Kill))
295*9880d681SAndroid Build Coastguard Worker .addReg(Src2Reg, getKillRegState(Src2Kill));
296*9880d681SAndroid Build Coastguard Worker if (HasLane)
297*9880d681SAndroid Build Coastguard Worker MIB.addImm(LaneImm);
298*9880d681SAndroid Build Coastguard Worker MIB.addImm(Pred).addReg(PredReg);
299*9880d681SAndroid Build Coastguard Worker
300*9880d681SAndroid Build Coastguard Worker MIB = BuildMI(MBB, MI, MI->getDebugLoc(), MCID2)
301*9880d681SAndroid Build Coastguard Worker .addReg(DstReg, getDefRegState(true) | getDeadRegState(DstDead));
302*9880d681SAndroid Build Coastguard Worker
303*9880d681SAndroid Build Coastguard Worker if (NegAcc) {
304*9880d681SAndroid Build Coastguard Worker bool AccKill = MRI->hasOneNonDBGUse(AccReg);
305*9880d681SAndroid Build Coastguard Worker MIB.addReg(TmpReg, getKillRegState(true))
306*9880d681SAndroid Build Coastguard Worker .addReg(AccReg, getKillRegState(AccKill));
307*9880d681SAndroid Build Coastguard Worker } else {
308*9880d681SAndroid Build Coastguard Worker MIB.addReg(AccReg).addReg(TmpReg, getKillRegState(true));
309*9880d681SAndroid Build Coastguard Worker }
310*9880d681SAndroid Build Coastguard Worker MIB.addImm(Pred).addReg(PredReg);
311*9880d681SAndroid Build Coastguard Worker
312*9880d681SAndroid Build Coastguard Worker DEBUG({
313*9880d681SAndroid Build Coastguard Worker dbgs() << "Expanding: " << *MI;
314*9880d681SAndroid Build Coastguard Worker dbgs() << " to:\n";
315*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator MII = MI;
316*9880d681SAndroid Build Coastguard Worker MII = std::prev(MII);
317*9880d681SAndroid Build Coastguard Worker MachineInstr &MI2 = *MII;
318*9880d681SAndroid Build Coastguard Worker MII = std::prev(MII);
319*9880d681SAndroid Build Coastguard Worker MachineInstr &MI1 = *MII;
320*9880d681SAndroid Build Coastguard Worker dbgs() << " " << MI1;
321*9880d681SAndroid Build Coastguard Worker dbgs() << " " << MI2;
322*9880d681SAndroid Build Coastguard Worker });
323*9880d681SAndroid Build Coastguard Worker
324*9880d681SAndroid Build Coastguard Worker MI->eraseFromParent();
325*9880d681SAndroid Build Coastguard Worker ++NumExpand;
326*9880d681SAndroid Build Coastguard Worker }
327*9880d681SAndroid Build Coastguard Worker
ExpandFPMLxInstructions(MachineBasicBlock & MBB)328*9880d681SAndroid Build Coastguard Worker bool MLxExpansion::ExpandFPMLxInstructions(MachineBasicBlock &MBB) {
329*9880d681SAndroid Build Coastguard Worker bool Changed = false;
330*9880d681SAndroid Build Coastguard Worker
331*9880d681SAndroid Build Coastguard Worker clearStack();
332*9880d681SAndroid Build Coastguard Worker IgnoreStall.clear();
333*9880d681SAndroid Build Coastguard Worker
334*9880d681SAndroid Build Coastguard Worker unsigned Skip = 0;
335*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::reverse_iterator MII = MBB.rbegin(), E = MBB.rend();
336*9880d681SAndroid Build Coastguard Worker while (MII != E) {
337*9880d681SAndroid Build Coastguard Worker MachineInstr *MI = &*MII;
338*9880d681SAndroid Build Coastguard Worker
339*9880d681SAndroid Build Coastguard Worker if (MI->isPosition() || MI->isImplicitDef() || MI->isCopy()) {
340*9880d681SAndroid Build Coastguard Worker ++MII;
341*9880d681SAndroid Build Coastguard Worker continue;
342*9880d681SAndroid Build Coastguard Worker }
343*9880d681SAndroid Build Coastguard Worker
344*9880d681SAndroid Build Coastguard Worker const MCInstrDesc &MCID = MI->getDesc();
345*9880d681SAndroid Build Coastguard Worker if (MI->isBarrier()) {
346*9880d681SAndroid Build Coastguard Worker clearStack();
347*9880d681SAndroid Build Coastguard Worker Skip = 0;
348*9880d681SAndroid Build Coastguard Worker ++MII;
349*9880d681SAndroid Build Coastguard Worker continue;
350*9880d681SAndroid Build Coastguard Worker }
351*9880d681SAndroid Build Coastguard Worker
352*9880d681SAndroid Build Coastguard Worker unsigned Domain = MCID.TSFlags & ARMII::DomainMask;
353*9880d681SAndroid Build Coastguard Worker if (Domain == ARMII::DomainGeneral) {
354*9880d681SAndroid Build Coastguard Worker if (++Skip == 2)
355*9880d681SAndroid Build Coastguard Worker // Assume dual issues of non-VFP / NEON instructions.
356*9880d681SAndroid Build Coastguard Worker pushStack(nullptr);
357*9880d681SAndroid Build Coastguard Worker } else {
358*9880d681SAndroid Build Coastguard Worker Skip = 0;
359*9880d681SAndroid Build Coastguard Worker
360*9880d681SAndroid Build Coastguard Worker unsigned MulOpc, AddSubOpc;
361*9880d681SAndroid Build Coastguard Worker bool NegAcc, HasLane;
362*9880d681SAndroid Build Coastguard Worker if (!TII->isFpMLxInstruction(MCID.getOpcode(),
363*9880d681SAndroid Build Coastguard Worker MulOpc, AddSubOpc, NegAcc, HasLane) ||
364*9880d681SAndroid Build Coastguard Worker !FindMLxHazard(MI))
365*9880d681SAndroid Build Coastguard Worker pushStack(MI);
366*9880d681SAndroid Build Coastguard Worker else {
367*9880d681SAndroid Build Coastguard Worker ExpandFPMLxInstruction(MBB, MI, MulOpc, AddSubOpc, NegAcc, HasLane);
368*9880d681SAndroid Build Coastguard Worker E = MBB.rend(); // May have changed if MI was the 1st instruction.
369*9880d681SAndroid Build Coastguard Worker Changed = true;
370*9880d681SAndroid Build Coastguard Worker continue;
371*9880d681SAndroid Build Coastguard Worker }
372*9880d681SAndroid Build Coastguard Worker }
373*9880d681SAndroid Build Coastguard Worker
374*9880d681SAndroid Build Coastguard Worker ++MII;
375*9880d681SAndroid Build Coastguard Worker }
376*9880d681SAndroid Build Coastguard Worker
377*9880d681SAndroid Build Coastguard Worker return Changed;
378*9880d681SAndroid Build Coastguard Worker }
379*9880d681SAndroid Build Coastguard Worker
runOnMachineFunction(MachineFunction & Fn)380*9880d681SAndroid Build Coastguard Worker bool MLxExpansion::runOnMachineFunction(MachineFunction &Fn) {
381*9880d681SAndroid Build Coastguard Worker if (skipFunction(*Fn.getFunction()))
382*9880d681SAndroid Build Coastguard Worker return false;
383*9880d681SAndroid Build Coastguard Worker
384*9880d681SAndroid Build Coastguard Worker TII = static_cast<const ARMBaseInstrInfo *>(Fn.getSubtarget().getInstrInfo());
385*9880d681SAndroid Build Coastguard Worker TRI = Fn.getSubtarget().getRegisterInfo();
386*9880d681SAndroid Build Coastguard Worker MRI = &Fn.getRegInfo();
387*9880d681SAndroid Build Coastguard Worker const ARMSubtarget *STI = &Fn.getSubtarget<ARMSubtarget>();
388*9880d681SAndroid Build Coastguard Worker if (!STI->expandMLx())
389*9880d681SAndroid Build Coastguard Worker return false;
390*9880d681SAndroid Build Coastguard Worker isLikeA9 = STI->isLikeA9() || STI->isSwift();
391*9880d681SAndroid Build Coastguard Worker isSwift = STI->isSwift();
392*9880d681SAndroid Build Coastguard Worker
393*9880d681SAndroid Build Coastguard Worker bool Modified = false;
394*9880d681SAndroid Build Coastguard Worker for (MachineBasicBlock &MBB : Fn)
395*9880d681SAndroid Build Coastguard Worker Modified |= ExpandFPMLxInstructions(MBB);
396*9880d681SAndroid Build Coastguard Worker
397*9880d681SAndroid Build Coastguard Worker return Modified;
398*9880d681SAndroid Build Coastguard Worker }
399*9880d681SAndroid Build Coastguard Worker
createMLxExpansionPass()400*9880d681SAndroid Build Coastguard Worker FunctionPass *llvm::createMLxExpansionPass() {
401*9880d681SAndroid Build Coastguard Worker return new MLxExpansion();
402*9880d681SAndroid Build Coastguard Worker }
403