1b22310fdSJia Liu //===-- MLxExpansionPass.cpp - Expand MLx instrs to avoid hazards ---------===// 262c7b5bfSEvan Cheng // 362c7b5bfSEvan Cheng // The LLVM Compiler Infrastructure 462c7b5bfSEvan Cheng // 562c7b5bfSEvan Cheng // This file is distributed under the University of Illinois Open Source 662c7b5bfSEvan Cheng // License. See LICENSE.TXT for details. 762c7b5bfSEvan Cheng // 862c7b5bfSEvan Cheng //===----------------------------------------------------------------------===// 962c7b5bfSEvan Cheng // 1062c7b5bfSEvan Cheng // Expand VFP / NEON floating point MLA / MLS instructions (each to a pair of 1162c7b5bfSEvan Cheng // multiple and add / sub instructions) when special VMLx hazards are detected. 1262c7b5bfSEvan Cheng // 1362c7b5bfSEvan Cheng //===----------------------------------------------------------------------===// 1462c7b5bfSEvan Cheng 1562c7b5bfSEvan Cheng #include "ARM.h" 1662c7b5bfSEvan Cheng #include "ARMBaseInstrInfo.h" 170858c3aaSBob Wilson #include "ARMSubtarget.h" 180858c3aaSBob Wilson #include "llvm/ADT/SmallPtrSet.h" 1962c7b5bfSEvan Cheng #include "llvm/ADT/Statistic.h" 20ed0881b2SChandler Carruth #include "llvm/CodeGen/MachineFunctionPass.h" 21ed0881b2SChandler Carruth #include "llvm/CodeGen/MachineInstr.h" 22ed0881b2SChandler Carruth #include "llvm/CodeGen/MachineInstrBuilder.h" 23ed0881b2SChandler Carruth #include "llvm/CodeGen/MachineRegisterInfo.h" 2462c7b5bfSEvan Cheng #include "llvm/Support/CommandLine.h" 2562c7b5bfSEvan Cheng #include "llvm/Support/Debug.h" 2662c7b5bfSEvan Cheng #include "llvm/Support/raw_ostream.h" 27ed0881b2SChandler Carruth #include "llvm/Target/TargetRegisterInfo.h" 2862c7b5bfSEvan Cheng using namespace llvm; 2962c7b5bfSEvan Cheng 3084e68b29SChandler Carruth #define DEBUG_TYPE "mlx-expansion" 3184e68b29SChandler Carruth 3262c7b5bfSEvan Cheng static cl::opt<bool> 3362c7b5bfSEvan Cheng ForceExapnd("expand-all-fp-mlx", cl::init(false), cl::Hidden); 3462c7b5bfSEvan Cheng static cl::opt<unsigned> 3562c7b5bfSEvan Cheng ExpandLimit("expand-limit", cl::init(~0U), cl::Hidden); 3662c7b5bfSEvan Cheng 3762c7b5bfSEvan Cheng STATISTIC(NumExpand, "Number of fp MLA / MLS instructions expanded"); 3862c7b5bfSEvan Cheng 3962c7b5bfSEvan Cheng namespace { 4062c7b5bfSEvan Cheng struct MLxExpansion : public MachineFunctionPass { 4162c7b5bfSEvan Cheng static char ID; 4262c7b5bfSEvan Cheng MLxExpansion() : MachineFunctionPass(ID) {} 4362c7b5bfSEvan Cheng 446bc27bf3SCraig Topper bool runOnMachineFunction(MachineFunction &Fn) override; 4562c7b5bfSEvan Cheng 46*117296c0SMehdi Amini StringRef getPassName() const override { 4762c7b5bfSEvan Cheng return "ARM MLA / MLS expansion pass"; 4862c7b5bfSEvan Cheng } 4962c7b5bfSEvan Cheng 5062c7b5bfSEvan Cheng private: 5162c7b5bfSEvan Cheng const ARMBaseInstrInfo *TII; 5262c7b5bfSEvan Cheng const TargetRegisterInfo *TRI; 5362c7b5bfSEvan Cheng MachineRegisterInfo *MRI; 5462c7b5bfSEvan Cheng 55b47bb94fSSilviu Baranga bool isLikeA9; 56e8a549cdSBob Wilson bool isSwift; 5762c7b5bfSEvan Cheng unsigned MIIdx; 5862c7b5bfSEvan Cheng MachineInstr* LastMIs[4]; 590858c3aaSBob Wilson SmallPtrSet<MachineInstr*, 4> IgnoreStall; 6062c7b5bfSEvan Cheng 6162c7b5bfSEvan Cheng void clearStack(); 6262c7b5bfSEvan Cheng void pushStack(MachineInstr *MI); 6362c7b5bfSEvan Cheng MachineInstr *getAccDefMI(MachineInstr *MI) const; 6462c7b5bfSEvan Cheng unsigned getDefReg(MachineInstr *MI) const; 65e8a549cdSBob Wilson bool hasLoopHazard(MachineInstr *MI) const; 6662c7b5bfSEvan Cheng bool hasRAWHazard(unsigned Reg, MachineInstr *MI) const; 670858c3aaSBob Wilson bool FindMLxHazard(MachineInstr *MI); 6862c7b5bfSEvan Cheng void ExpandFPMLxInstruction(MachineBasicBlock &MBB, MachineInstr *MI, 6962c7b5bfSEvan Cheng unsigned MulOpc, unsigned AddSubOpc, 7062c7b5bfSEvan Cheng bool NegAcc, bool HasLane); 7162c7b5bfSEvan Cheng bool ExpandFPMLxInstructions(MachineBasicBlock &MBB); 7262c7b5bfSEvan Cheng }; 7362c7b5bfSEvan Cheng char MLxExpansion::ID = 0; 74f00654e3SAlexander Kornienko } 7562c7b5bfSEvan Cheng 7662c7b5bfSEvan Cheng void MLxExpansion::clearStack() { 77062a2baeSCraig Topper std::fill(LastMIs, LastMIs + 4, nullptr); 7862c7b5bfSEvan Cheng MIIdx = 0; 7962c7b5bfSEvan Cheng } 8062c7b5bfSEvan Cheng 8162c7b5bfSEvan Cheng void MLxExpansion::pushStack(MachineInstr *MI) { 8262c7b5bfSEvan Cheng LastMIs[MIIdx] = MI; 8362c7b5bfSEvan Cheng if (++MIIdx == 4) 8462c7b5bfSEvan Cheng MIIdx = 0; 8562c7b5bfSEvan Cheng } 8662c7b5bfSEvan Cheng 8762c7b5bfSEvan Cheng MachineInstr *MLxExpansion::getAccDefMI(MachineInstr *MI) const { 8862c7b5bfSEvan Cheng // Look past COPY and INSERT_SUBREG instructions to find the 8962c7b5bfSEvan Cheng // real definition MI. This is important for _sfp instructions. 9062c7b5bfSEvan Cheng unsigned Reg = MI->getOperand(1).getReg(); 9162c7b5bfSEvan Cheng if (TargetRegisterInfo::isPhysicalRegister(Reg)) 92062a2baeSCraig Topper return nullptr; 9362c7b5bfSEvan Cheng 9462c7b5bfSEvan Cheng MachineBasicBlock *MBB = MI->getParent(); 9562c7b5bfSEvan Cheng MachineInstr *DefMI = MRI->getVRegDef(Reg); 9662c7b5bfSEvan Cheng while (true) { 9762c7b5bfSEvan Cheng if (DefMI->getParent() != MBB) 9862c7b5bfSEvan Cheng break; 9962c7b5bfSEvan Cheng if (DefMI->isCopyLike()) { 10062c7b5bfSEvan Cheng Reg = DefMI->getOperand(1).getReg(); 10162c7b5bfSEvan Cheng if (TargetRegisterInfo::isVirtualRegister(Reg)) { 10262c7b5bfSEvan Cheng DefMI = MRI->getVRegDef(Reg); 10362c7b5bfSEvan Cheng continue; 10462c7b5bfSEvan Cheng } 10562c7b5bfSEvan Cheng } else if (DefMI->isInsertSubreg()) { 10662c7b5bfSEvan Cheng Reg = DefMI->getOperand(2).getReg(); 10762c7b5bfSEvan Cheng if (TargetRegisterInfo::isVirtualRegister(Reg)) { 10862c7b5bfSEvan Cheng DefMI = MRI->getVRegDef(Reg); 10962c7b5bfSEvan Cheng continue; 11062c7b5bfSEvan Cheng } 11162c7b5bfSEvan Cheng } 11262c7b5bfSEvan Cheng break; 11362c7b5bfSEvan Cheng } 11462c7b5bfSEvan Cheng return DefMI; 11562c7b5bfSEvan Cheng } 11662c7b5bfSEvan Cheng 11762c7b5bfSEvan Cheng unsigned MLxExpansion::getDefReg(MachineInstr *MI) const { 11862c7b5bfSEvan Cheng unsigned Reg = MI->getOperand(0).getReg(); 11962c7b5bfSEvan Cheng if (TargetRegisterInfo::isPhysicalRegister(Reg) || 12062c7b5bfSEvan Cheng !MRI->hasOneNonDBGUse(Reg)) 12162c7b5bfSEvan Cheng return Reg; 12262c7b5bfSEvan Cheng 12362c7b5bfSEvan Cheng MachineBasicBlock *MBB = MI->getParent(); 12416c6bf49SOwen Anderson MachineInstr *UseMI = &*MRI->use_instr_nodbg_begin(Reg); 12562c7b5bfSEvan Cheng if (UseMI->getParent() != MBB) 12662c7b5bfSEvan Cheng return Reg; 12762c7b5bfSEvan Cheng 12862c7b5bfSEvan Cheng while (UseMI->isCopy() || UseMI->isInsertSubreg()) { 12962c7b5bfSEvan Cheng Reg = UseMI->getOperand(0).getReg(); 13062c7b5bfSEvan Cheng if (TargetRegisterInfo::isPhysicalRegister(Reg) || 13162c7b5bfSEvan Cheng !MRI->hasOneNonDBGUse(Reg)) 13262c7b5bfSEvan Cheng return Reg; 13316c6bf49SOwen Anderson UseMI = &*MRI->use_instr_nodbg_begin(Reg); 13462c7b5bfSEvan Cheng if (UseMI->getParent() != MBB) 13562c7b5bfSEvan Cheng return Reg; 13662c7b5bfSEvan Cheng } 13762c7b5bfSEvan Cheng 13862c7b5bfSEvan Cheng return Reg; 13962c7b5bfSEvan Cheng } 14062c7b5bfSEvan Cheng 141e8a549cdSBob Wilson /// hasLoopHazard - Check whether an MLx instruction is chained to itself across 142e8a549cdSBob Wilson /// a single-MBB loop. 143e8a549cdSBob Wilson bool MLxExpansion::hasLoopHazard(MachineInstr *MI) const { 144e8a549cdSBob Wilson unsigned Reg = MI->getOperand(1).getReg(); 145e8a549cdSBob Wilson if (TargetRegisterInfo::isPhysicalRegister(Reg)) 146e8a549cdSBob Wilson return false; 147e8a549cdSBob Wilson 148e8a549cdSBob Wilson MachineBasicBlock *MBB = MI->getParent(); 149e8a549cdSBob Wilson MachineInstr *DefMI = MRI->getVRegDef(Reg); 150e8a549cdSBob Wilson while (true) { 151e8a549cdSBob Wilson outer_continue: 152e8a549cdSBob Wilson if (DefMI->getParent() != MBB) 153e8a549cdSBob Wilson break; 154e8a549cdSBob Wilson 155e8a549cdSBob Wilson if (DefMI->isPHI()) { 156e8a549cdSBob Wilson for (unsigned i = 1, e = DefMI->getNumOperands(); i < e; i += 2) { 157e8a549cdSBob Wilson if (DefMI->getOperand(i + 1).getMBB() == MBB) { 158e8a549cdSBob Wilson unsigned SrcReg = DefMI->getOperand(i).getReg(); 159e8a549cdSBob Wilson if (TargetRegisterInfo::isVirtualRegister(SrcReg)) { 160e8a549cdSBob Wilson DefMI = MRI->getVRegDef(SrcReg); 161e8a549cdSBob Wilson goto outer_continue; 162e8a549cdSBob Wilson } 163e8a549cdSBob Wilson } 164e8a549cdSBob Wilson } 165e8a549cdSBob Wilson } else if (DefMI->isCopyLike()) { 166e8a549cdSBob Wilson Reg = DefMI->getOperand(1).getReg(); 167e8a549cdSBob Wilson if (TargetRegisterInfo::isVirtualRegister(Reg)) { 168e8a549cdSBob Wilson DefMI = MRI->getVRegDef(Reg); 169e8a549cdSBob Wilson continue; 170e8a549cdSBob Wilson } 171e8a549cdSBob Wilson } else if (DefMI->isInsertSubreg()) { 172e8a549cdSBob Wilson Reg = DefMI->getOperand(2).getReg(); 173e8a549cdSBob Wilson if (TargetRegisterInfo::isVirtualRegister(Reg)) { 174e8a549cdSBob Wilson DefMI = MRI->getVRegDef(Reg); 175e8a549cdSBob Wilson continue; 176e8a549cdSBob Wilson } 177e8a549cdSBob Wilson } 178e8a549cdSBob Wilson 179e8a549cdSBob Wilson break; 180e8a549cdSBob Wilson } 181e8a549cdSBob Wilson 182e8a549cdSBob Wilson return DefMI == MI; 183e8a549cdSBob Wilson } 184e8a549cdSBob Wilson 18562c7b5bfSEvan Cheng bool MLxExpansion::hasRAWHazard(unsigned Reg, MachineInstr *MI) const { 18662c7b5bfSEvan Cheng // FIXME: Detect integer instructions properly. 1876cc775f9SEvan Cheng const MCInstrDesc &MCID = MI->getDesc(); 1886cc775f9SEvan Cheng unsigned Domain = MCID.TSFlags & ARMII::DomainMask; 1897f8e563aSEvan Cheng if (MI->mayStore()) 19004ad35b5SEvan Cheng return false; 1916cc775f9SEvan Cheng unsigned Opcode = MCID.getOpcode(); 19204ad35b5SEvan Cheng if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD) 19362c7b5bfSEvan Cheng return false; 19404ad35b5SEvan Cheng if ((Domain & ARMII::DomainVFP) || (Domain & ARMII::DomainNEON)) 19562c7b5bfSEvan Cheng return MI->readsRegister(Reg, TRI); 19662c7b5bfSEvan Cheng return false; 19762c7b5bfSEvan Cheng } 19862c7b5bfSEvan Cheng 199e8a549cdSBob Wilson static bool isFpMulInstruction(unsigned Opcode) { 200e8a549cdSBob Wilson switch (Opcode) { 201e8a549cdSBob Wilson case ARM::VMULS: 202e8a549cdSBob Wilson case ARM::VMULfd: 203e8a549cdSBob Wilson case ARM::VMULfq: 204e8a549cdSBob Wilson case ARM::VMULD: 205e8a549cdSBob Wilson case ARM::VMULslfd: 206e8a549cdSBob Wilson case ARM::VMULslfq: 207e8a549cdSBob Wilson return true; 208e8a549cdSBob Wilson default: 209e8a549cdSBob Wilson return false; 210e8a549cdSBob Wilson } 211e8a549cdSBob Wilson } 21262c7b5bfSEvan Cheng 2130858c3aaSBob Wilson bool MLxExpansion::FindMLxHazard(MachineInstr *MI) { 21462c7b5bfSEvan Cheng if (NumExpand >= ExpandLimit) 21562c7b5bfSEvan Cheng return false; 21662c7b5bfSEvan Cheng 21762c7b5bfSEvan Cheng if (ForceExapnd) 21862c7b5bfSEvan Cheng return true; 21962c7b5bfSEvan Cheng 22062c7b5bfSEvan Cheng MachineInstr *DefMI = getAccDefMI(MI); 2210858c3aaSBob Wilson if (TII->isFpMLxInstruction(DefMI->getOpcode())) { 22262c7b5bfSEvan Cheng // r0 = vmla 22362c7b5bfSEvan Cheng // r3 = vmla r0, r1, r2 22462c7b5bfSEvan Cheng // takes 16 - 17 cycles 22562c7b5bfSEvan Cheng // 22662c7b5bfSEvan Cheng // r0 = vmla 22762c7b5bfSEvan Cheng // r4 = vmul r1, r2 22862c7b5bfSEvan Cheng // r3 = vadd r0, r4 22962c7b5bfSEvan Cheng // takes about 14 - 15 cycles even with vmul stalling for 4 cycles. 2300858c3aaSBob Wilson IgnoreStall.insert(DefMI); 23162c7b5bfSEvan Cheng return true; 2320858c3aaSBob Wilson } 2330858c3aaSBob Wilson 234e8a549cdSBob Wilson // On Swift, we mostly care about hazards from multiplication instructions 235e8a549cdSBob Wilson // writing the accumulator and the pipelining of loop iterations by out-of- 236e8a549cdSBob Wilson // order execution. 237e8a549cdSBob Wilson if (isSwift) 238e8a549cdSBob Wilson return isFpMulInstruction(DefMI->getOpcode()) || hasLoopHazard(MI); 239e8a549cdSBob Wilson 2400858c3aaSBob Wilson if (IgnoreStall.count(MI)) 2410858c3aaSBob Wilson return false; 24262c7b5bfSEvan Cheng 24362c7b5bfSEvan Cheng // If a VMLA.F is followed by an VADD.F or VMUL.F with no RAW hazard, the 24462c7b5bfSEvan Cheng // VADD.F or VMUL.F will stall 4 cycles before issue. The 4 cycle stall 24562c7b5bfSEvan Cheng // preserves the in-order retirement of the instructions. 24662c7b5bfSEvan Cheng // Look at the next few instructions, if *most* of them can cause hazards, 24762c7b5bfSEvan Cheng // then the scheduler can't *fix* this, we'd better break up the VMLA. 248b47bb94fSSilviu Baranga unsigned Limit1 = isLikeA9 ? 1 : 4; 249b47bb94fSSilviu Baranga unsigned Limit2 = isLikeA9 ? 1 : 4; 25062c7b5bfSEvan Cheng for (unsigned i = 1; i <= 4; ++i) { 25162c7b5bfSEvan Cheng int Idx = ((int)MIIdx - i + 4) % 4; 25262c7b5bfSEvan Cheng MachineInstr *NextMI = LastMIs[Idx]; 25362c7b5bfSEvan Cheng if (!NextMI) 25462c7b5bfSEvan Cheng continue; 25562c7b5bfSEvan Cheng 2560858c3aaSBob Wilson if (TII->canCauseFpMLxStall(NextMI->getOpcode())) { 2570858c3aaSBob Wilson if (i <= Limit1) 25862c7b5bfSEvan Cheng return true; 2590858c3aaSBob Wilson } 26062c7b5bfSEvan Cheng 26162c7b5bfSEvan Cheng // Look for VMLx RAW hazard. 2620858c3aaSBob Wilson if (i <= Limit2 && hasRAWHazard(getDefReg(MI), NextMI)) 26362c7b5bfSEvan Cheng return true; 26462c7b5bfSEvan Cheng } 26562c7b5bfSEvan Cheng 26662c7b5bfSEvan Cheng return false; 26762c7b5bfSEvan Cheng } 26862c7b5bfSEvan Cheng 26962c7b5bfSEvan Cheng /// ExpandFPMLxInstructions - Expand a MLA / MLS instruction into a pair 27062c7b5bfSEvan Cheng /// of MUL + ADD / SUB instructions. 27162c7b5bfSEvan Cheng void 27262c7b5bfSEvan Cheng MLxExpansion::ExpandFPMLxInstruction(MachineBasicBlock &MBB, MachineInstr *MI, 27362c7b5bfSEvan Cheng unsigned MulOpc, unsigned AddSubOpc, 27462c7b5bfSEvan Cheng bool NegAcc, bool HasLane) { 27562c7b5bfSEvan Cheng unsigned DstReg = MI->getOperand(0).getReg(); 27662c7b5bfSEvan Cheng bool DstDead = MI->getOperand(0).isDead(); 27762c7b5bfSEvan Cheng unsigned AccReg = MI->getOperand(1).getReg(); 27862c7b5bfSEvan Cheng unsigned Src1Reg = MI->getOperand(2).getReg(); 27962c7b5bfSEvan Cheng unsigned Src2Reg = MI->getOperand(3).getReg(); 28062c7b5bfSEvan Cheng bool Src1Kill = MI->getOperand(2).isKill(); 28162c7b5bfSEvan Cheng bool Src2Kill = MI->getOperand(3).isKill(); 28262c7b5bfSEvan Cheng unsigned LaneImm = HasLane ? MI->getOperand(4).getImm() : 0; 28362c7b5bfSEvan Cheng unsigned NextOp = HasLane ? 5 : 4; 28462c7b5bfSEvan Cheng ARMCC::CondCodes Pred = (ARMCC::CondCodes)MI->getOperand(NextOp).getImm(); 28562c7b5bfSEvan Cheng unsigned PredReg = MI->getOperand(++NextOp).getReg(); 28662c7b5bfSEvan Cheng 2876cc775f9SEvan Cheng const MCInstrDesc &MCID1 = TII->get(MulOpc); 2886cc775f9SEvan Cheng const MCInstrDesc &MCID2 = TII->get(AddSubOpc); 2893c52f028SJakob Stoklund Olesen const MachineFunction &MF = *MI->getParent()->getParent(); 2903c52f028SJakob Stoklund Olesen unsigned TmpReg = MRI->createVirtualRegister( 2913c52f028SJakob Stoklund Olesen TII->getRegClass(MCID1, 0, TRI, MF)); 29262c7b5bfSEvan Cheng 2937fae11b2SEvan Cheng MachineInstrBuilder MIB = BuildMI(MBB, MI, MI->getDebugLoc(), MCID1, TmpReg) 29462c7b5bfSEvan Cheng .addReg(Src1Reg, getKillRegState(Src1Kill)) 29562c7b5bfSEvan Cheng .addReg(Src2Reg, getKillRegState(Src2Kill)); 29662c7b5bfSEvan Cheng if (HasLane) 29762c7b5bfSEvan Cheng MIB.addImm(LaneImm); 29862c7b5bfSEvan Cheng MIB.addImm(Pred).addReg(PredReg); 29962c7b5bfSEvan Cheng 3007fae11b2SEvan Cheng MIB = BuildMI(MBB, MI, MI->getDebugLoc(), MCID2) 30162c7b5bfSEvan Cheng .addReg(DstReg, getDefRegState(true) | getDeadRegState(DstDead)); 30262c7b5bfSEvan Cheng 30362c7b5bfSEvan Cheng if (NegAcc) { 30462c7b5bfSEvan Cheng bool AccKill = MRI->hasOneNonDBGUse(AccReg); 30562c7b5bfSEvan Cheng MIB.addReg(TmpReg, getKillRegState(true)) 30662c7b5bfSEvan Cheng .addReg(AccReg, getKillRegState(AccKill)); 30762c7b5bfSEvan Cheng } else { 30862c7b5bfSEvan Cheng MIB.addReg(AccReg).addReg(TmpReg, getKillRegState(true)); 30962c7b5bfSEvan Cheng } 31062c7b5bfSEvan Cheng MIB.addImm(Pred).addReg(PredReg); 31162c7b5bfSEvan Cheng 31262c7b5bfSEvan Cheng DEBUG({ 31362c7b5bfSEvan Cheng dbgs() << "Expanding: " << *MI; 31462c7b5bfSEvan Cheng dbgs() << " to:\n"; 31562c7b5bfSEvan Cheng MachineBasicBlock::iterator MII = MI; 316b6d0bd48SBenjamin Kramer MII = std::prev(MII); 31762c7b5bfSEvan Cheng MachineInstr &MI2 = *MII; 318b6d0bd48SBenjamin Kramer MII = std::prev(MII); 31962c7b5bfSEvan Cheng MachineInstr &MI1 = *MII; 32062c7b5bfSEvan Cheng dbgs() << " " << MI1; 32162c7b5bfSEvan Cheng dbgs() << " " << MI2; 32262c7b5bfSEvan Cheng }); 32362c7b5bfSEvan Cheng 32462c7b5bfSEvan Cheng MI->eraseFromParent(); 32562c7b5bfSEvan Cheng ++NumExpand; 32662c7b5bfSEvan Cheng } 32762c7b5bfSEvan Cheng 32862c7b5bfSEvan Cheng bool MLxExpansion::ExpandFPMLxInstructions(MachineBasicBlock &MBB) { 32962c7b5bfSEvan Cheng bool Changed = false; 33062c7b5bfSEvan Cheng 33162c7b5bfSEvan Cheng clearStack(); 3320858c3aaSBob Wilson IgnoreStall.clear(); 33362c7b5bfSEvan Cheng 33462c7b5bfSEvan Cheng unsigned Skip = 0; 33562c7b5bfSEvan Cheng MachineBasicBlock::reverse_iterator MII = MBB.rbegin(), E = MBB.rend(); 33662c7b5bfSEvan Cheng while (MII != E) { 3371872096fSDuncan P. N. Exon Smith MachineInstr *MI = &*MII++; 33862c7b5bfSEvan Cheng 3391872096fSDuncan P. N. Exon Smith if (MI->isPosition() || MI->isImplicitDef() || MI->isCopy()) 34062c7b5bfSEvan Cheng continue; 34162c7b5bfSEvan Cheng 3426cc775f9SEvan Cheng const MCInstrDesc &MCID = MI->getDesc(); 3437f8e563aSEvan Cheng if (MI->isBarrier()) { 34462c7b5bfSEvan Cheng clearStack(); 34562c7b5bfSEvan Cheng Skip = 0; 34662c7b5bfSEvan Cheng continue; 34762c7b5bfSEvan Cheng } 34862c7b5bfSEvan Cheng 3496cc775f9SEvan Cheng unsigned Domain = MCID.TSFlags & ARMII::DomainMask; 35062c7b5bfSEvan Cheng if (Domain == ARMII::DomainGeneral) { 35162c7b5bfSEvan Cheng if (++Skip == 2) 35262c7b5bfSEvan Cheng // Assume dual issues of non-VFP / NEON instructions. 353062a2baeSCraig Topper pushStack(nullptr); 35462c7b5bfSEvan Cheng } else { 35562c7b5bfSEvan Cheng Skip = 0; 35662c7b5bfSEvan Cheng 35762c7b5bfSEvan Cheng unsigned MulOpc, AddSubOpc; 35862c7b5bfSEvan Cheng bool NegAcc, HasLane; 3596cc775f9SEvan Cheng if (!TII->isFpMLxInstruction(MCID.getOpcode(), 36062c7b5bfSEvan Cheng MulOpc, AddSubOpc, NegAcc, HasLane) || 36162c7b5bfSEvan Cheng !FindMLxHazard(MI)) 36262c7b5bfSEvan Cheng pushStack(MI); 36362c7b5bfSEvan Cheng else { 36462c7b5bfSEvan Cheng ExpandFPMLxInstruction(MBB, MI, MulOpc, AddSubOpc, NegAcc, HasLane); 36562c7b5bfSEvan Cheng Changed = true; 36662c7b5bfSEvan Cheng } 36762c7b5bfSEvan Cheng } 36862c7b5bfSEvan Cheng } 36962c7b5bfSEvan Cheng 37062c7b5bfSEvan Cheng return Changed; 37162c7b5bfSEvan Cheng } 37262c7b5bfSEvan Cheng 37362c7b5bfSEvan Cheng bool MLxExpansion::runOnMachineFunction(MachineFunction &Fn) { 374a2b9111eSAndrew Kaylor if (skipFunction(*Fn.getFunction())) 375a2b9111eSAndrew Kaylor return false; 376a2b9111eSAndrew Kaylor 377fc6de428SEric Christopher TII = static_cast<const ARMBaseInstrInfo *>(Fn.getSubtarget().getInstrInfo()); 378fc6de428SEric Christopher TRI = Fn.getSubtarget().getRegisterInfo(); 37962c7b5bfSEvan Cheng MRI = &Fn.getRegInfo(); 38022b2ad26SEric Christopher const ARMSubtarget *STI = &Fn.getSubtarget<ARMSubtarget>(); 381575f2bb2SDiana Picus if (!STI->expandMLx()) 38263b44882SEric Christopher return false; 383e8a549cdSBob Wilson isLikeA9 = STI->isLikeA9() || STI->isSwift(); 384e8a549cdSBob Wilson isSwift = STI->isSwift(); 38562c7b5bfSEvan Cheng 38662c7b5bfSEvan Cheng bool Modified = false; 38756112b99SOwen Anderson for (MachineBasicBlock &MBB : Fn) 38862c7b5bfSEvan Cheng Modified |= ExpandFPMLxInstructions(MBB); 38962c7b5bfSEvan Cheng 39062c7b5bfSEvan Cheng return Modified; 39162c7b5bfSEvan Cheng } 39262c7b5bfSEvan Cheng 39362c7b5bfSEvan Cheng FunctionPass *llvm::createMLxExpansionPass() { 39462c7b5bfSEvan Cheng return new MLxExpansion(); 39562c7b5bfSEvan Cheng } 396