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 #define DEBUG_TYPE "mlx-expansion" 1662c7b5bfSEvan Cheng #include "ARM.h" 1762c7b5bfSEvan Cheng #include "ARMBaseInstrInfo.h" 180858c3aaSBob Wilson #include "ARMSubtarget.h" 190858c3aaSBob Wilson #include "llvm/ADT/SmallPtrSet.h" 2062c7b5bfSEvan Cheng #include "llvm/ADT/Statistic.h" 21ed0881b2SChandler Carruth #include "llvm/CodeGen/MachineFunctionPass.h" 22ed0881b2SChandler Carruth #include "llvm/CodeGen/MachineInstr.h" 23ed0881b2SChandler Carruth #include "llvm/CodeGen/MachineInstrBuilder.h" 24ed0881b2SChandler Carruth #include "llvm/CodeGen/MachineRegisterInfo.h" 2562c7b5bfSEvan Cheng #include "llvm/Support/CommandLine.h" 2662c7b5bfSEvan Cheng #include "llvm/Support/Debug.h" 2762c7b5bfSEvan Cheng #include "llvm/Support/raw_ostream.h" 28ed0881b2SChandler Carruth #include "llvm/Target/TargetRegisterInfo.h" 2962c7b5bfSEvan Cheng using namespace llvm; 3062c7b5bfSEvan Cheng 3162c7b5bfSEvan Cheng static cl::opt<bool> 3262c7b5bfSEvan Cheng ForceExapnd("expand-all-fp-mlx", cl::init(false), cl::Hidden); 3362c7b5bfSEvan Cheng static cl::opt<unsigned> 3462c7b5bfSEvan Cheng ExpandLimit("expand-limit", cl::init(~0U), cl::Hidden); 3562c7b5bfSEvan Cheng 3662c7b5bfSEvan Cheng STATISTIC(NumExpand, "Number of fp MLA / MLS instructions expanded"); 3762c7b5bfSEvan Cheng 3862c7b5bfSEvan Cheng namespace { 3962c7b5bfSEvan Cheng struct MLxExpansion : public MachineFunctionPass { 4062c7b5bfSEvan Cheng static char ID; 4162c7b5bfSEvan Cheng MLxExpansion() : MachineFunctionPass(ID) {} 4262c7b5bfSEvan Cheng 4362c7b5bfSEvan Cheng virtual bool runOnMachineFunction(MachineFunction &Fn); 4462c7b5bfSEvan Cheng 4562c7b5bfSEvan Cheng virtual const char *getPassName() const { 4662c7b5bfSEvan Cheng return "ARM MLA / MLS expansion pass"; 4762c7b5bfSEvan Cheng } 4862c7b5bfSEvan Cheng 4962c7b5bfSEvan Cheng private: 5062c7b5bfSEvan Cheng const ARMBaseInstrInfo *TII; 5162c7b5bfSEvan Cheng const TargetRegisterInfo *TRI; 5262c7b5bfSEvan Cheng MachineRegisterInfo *MRI; 5362c7b5bfSEvan Cheng 54b47bb94fSSilviu Baranga bool isLikeA9; 55e8a549cdSBob Wilson bool isSwift; 5662c7b5bfSEvan Cheng unsigned MIIdx; 5762c7b5bfSEvan Cheng MachineInstr* LastMIs[4]; 580858c3aaSBob Wilson SmallPtrSet<MachineInstr*, 4> IgnoreStall; 5962c7b5bfSEvan Cheng 6062c7b5bfSEvan Cheng void clearStack(); 6162c7b5bfSEvan Cheng void pushStack(MachineInstr *MI); 6262c7b5bfSEvan Cheng MachineInstr *getAccDefMI(MachineInstr *MI) const; 6362c7b5bfSEvan Cheng unsigned getDefReg(MachineInstr *MI) const; 64e8a549cdSBob Wilson bool hasLoopHazard(MachineInstr *MI) const; 6562c7b5bfSEvan Cheng bool hasRAWHazard(unsigned Reg, MachineInstr *MI) const; 660858c3aaSBob Wilson bool FindMLxHazard(MachineInstr *MI); 6762c7b5bfSEvan Cheng void ExpandFPMLxInstruction(MachineBasicBlock &MBB, MachineInstr *MI, 6862c7b5bfSEvan Cheng unsigned MulOpc, unsigned AddSubOpc, 6962c7b5bfSEvan Cheng bool NegAcc, bool HasLane); 7062c7b5bfSEvan Cheng bool ExpandFPMLxInstructions(MachineBasicBlock &MBB); 7162c7b5bfSEvan Cheng }; 7262c7b5bfSEvan Cheng char MLxExpansion::ID = 0; 7362c7b5bfSEvan Cheng } 7462c7b5bfSEvan Cheng 7562c7b5bfSEvan Cheng void MLxExpansion::clearStack() { 7662c7b5bfSEvan Cheng std::fill(LastMIs, LastMIs + 4, (MachineInstr*)0); 7762c7b5bfSEvan Cheng MIIdx = 0; 7862c7b5bfSEvan Cheng } 7962c7b5bfSEvan Cheng 8062c7b5bfSEvan Cheng void MLxExpansion::pushStack(MachineInstr *MI) { 8162c7b5bfSEvan Cheng LastMIs[MIIdx] = MI; 8262c7b5bfSEvan Cheng if (++MIIdx == 4) 8362c7b5bfSEvan Cheng MIIdx = 0; 8462c7b5bfSEvan Cheng } 8562c7b5bfSEvan Cheng 8662c7b5bfSEvan Cheng MachineInstr *MLxExpansion::getAccDefMI(MachineInstr *MI) const { 8762c7b5bfSEvan Cheng // Look past COPY and INSERT_SUBREG instructions to find the 8862c7b5bfSEvan Cheng // real definition MI. This is important for _sfp instructions. 8962c7b5bfSEvan Cheng unsigned Reg = MI->getOperand(1).getReg(); 9062c7b5bfSEvan Cheng if (TargetRegisterInfo::isPhysicalRegister(Reg)) 9162c7b5bfSEvan Cheng return 0; 9262c7b5bfSEvan Cheng 9362c7b5bfSEvan Cheng MachineBasicBlock *MBB = MI->getParent(); 9462c7b5bfSEvan Cheng MachineInstr *DefMI = MRI->getVRegDef(Reg); 9562c7b5bfSEvan Cheng while (true) { 9662c7b5bfSEvan Cheng if (DefMI->getParent() != MBB) 9762c7b5bfSEvan Cheng break; 9862c7b5bfSEvan Cheng if (DefMI->isCopyLike()) { 9962c7b5bfSEvan Cheng Reg = DefMI->getOperand(1).getReg(); 10062c7b5bfSEvan Cheng if (TargetRegisterInfo::isVirtualRegister(Reg)) { 10162c7b5bfSEvan Cheng DefMI = MRI->getVRegDef(Reg); 10262c7b5bfSEvan Cheng continue; 10362c7b5bfSEvan Cheng } 10462c7b5bfSEvan Cheng } else if (DefMI->isInsertSubreg()) { 10562c7b5bfSEvan Cheng Reg = DefMI->getOperand(2).getReg(); 10662c7b5bfSEvan Cheng if (TargetRegisterInfo::isVirtualRegister(Reg)) { 10762c7b5bfSEvan Cheng DefMI = MRI->getVRegDef(Reg); 10862c7b5bfSEvan Cheng continue; 10962c7b5bfSEvan Cheng } 11062c7b5bfSEvan Cheng } 11162c7b5bfSEvan Cheng break; 11262c7b5bfSEvan Cheng } 11362c7b5bfSEvan Cheng return DefMI; 11462c7b5bfSEvan Cheng } 11562c7b5bfSEvan Cheng 11662c7b5bfSEvan Cheng unsigned MLxExpansion::getDefReg(MachineInstr *MI) const { 11762c7b5bfSEvan Cheng unsigned Reg = MI->getOperand(0).getReg(); 11862c7b5bfSEvan Cheng if (TargetRegisterInfo::isPhysicalRegister(Reg) || 11962c7b5bfSEvan Cheng !MRI->hasOneNonDBGUse(Reg)) 12062c7b5bfSEvan Cheng return Reg; 12162c7b5bfSEvan Cheng 12262c7b5bfSEvan Cheng MachineBasicBlock *MBB = MI->getParent(); 12362c7b5bfSEvan Cheng MachineInstr *UseMI = &*MRI->use_nodbg_begin(Reg); 12462c7b5bfSEvan Cheng if (UseMI->getParent() != MBB) 12562c7b5bfSEvan Cheng return Reg; 12662c7b5bfSEvan Cheng 12762c7b5bfSEvan Cheng while (UseMI->isCopy() || UseMI->isInsertSubreg()) { 12862c7b5bfSEvan Cheng Reg = UseMI->getOperand(0).getReg(); 12962c7b5bfSEvan Cheng if (TargetRegisterInfo::isPhysicalRegister(Reg) || 13062c7b5bfSEvan Cheng !MRI->hasOneNonDBGUse(Reg)) 13162c7b5bfSEvan Cheng return Reg; 13262c7b5bfSEvan Cheng UseMI = &*MRI->use_nodbg_begin(Reg); 13362c7b5bfSEvan Cheng if (UseMI->getParent() != MBB) 13462c7b5bfSEvan Cheng return Reg; 13562c7b5bfSEvan Cheng } 13662c7b5bfSEvan Cheng 13762c7b5bfSEvan Cheng return Reg; 13862c7b5bfSEvan Cheng } 13962c7b5bfSEvan Cheng 140e8a549cdSBob Wilson /// hasLoopHazard - Check whether an MLx instruction is chained to itself across 141e8a549cdSBob Wilson /// a single-MBB loop. 142e8a549cdSBob Wilson bool MLxExpansion::hasLoopHazard(MachineInstr *MI) const { 143e8a549cdSBob Wilson unsigned Reg = MI->getOperand(1).getReg(); 144e8a549cdSBob Wilson if (TargetRegisterInfo::isPhysicalRegister(Reg)) 145e8a549cdSBob Wilson return false; 146e8a549cdSBob Wilson 147e8a549cdSBob Wilson MachineBasicBlock *MBB = MI->getParent(); 148e8a549cdSBob Wilson MachineInstr *DefMI = MRI->getVRegDef(Reg); 149e8a549cdSBob Wilson while (true) { 150e8a549cdSBob Wilson outer_continue: 151e8a549cdSBob Wilson if (DefMI->getParent() != MBB) 152e8a549cdSBob Wilson break; 153e8a549cdSBob Wilson 154e8a549cdSBob Wilson if (DefMI->isPHI()) { 155e8a549cdSBob Wilson for (unsigned i = 1, e = DefMI->getNumOperands(); i < e; i += 2) { 156e8a549cdSBob Wilson if (DefMI->getOperand(i + 1).getMBB() == MBB) { 157e8a549cdSBob Wilson unsigned SrcReg = DefMI->getOperand(i).getReg(); 158e8a549cdSBob Wilson if (TargetRegisterInfo::isVirtualRegister(SrcReg)) { 159e8a549cdSBob Wilson DefMI = MRI->getVRegDef(SrcReg); 160e8a549cdSBob Wilson goto outer_continue; 161e8a549cdSBob Wilson } 162e8a549cdSBob Wilson } 163e8a549cdSBob Wilson } 164e8a549cdSBob Wilson } else if (DefMI->isCopyLike()) { 165e8a549cdSBob Wilson Reg = DefMI->getOperand(1).getReg(); 166e8a549cdSBob Wilson if (TargetRegisterInfo::isVirtualRegister(Reg)) { 167e8a549cdSBob Wilson DefMI = MRI->getVRegDef(Reg); 168e8a549cdSBob Wilson continue; 169e8a549cdSBob Wilson } 170e8a549cdSBob Wilson } else if (DefMI->isInsertSubreg()) { 171e8a549cdSBob Wilson Reg = DefMI->getOperand(2).getReg(); 172e8a549cdSBob Wilson if (TargetRegisterInfo::isVirtualRegister(Reg)) { 173e8a549cdSBob Wilson DefMI = MRI->getVRegDef(Reg); 174e8a549cdSBob Wilson continue; 175e8a549cdSBob Wilson } 176e8a549cdSBob Wilson } 177e8a549cdSBob Wilson 178e8a549cdSBob Wilson break; 179e8a549cdSBob Wilson } 180e8a549cdSBob Wilson 181e8a549cdSBob Wilson return DefMI == MI; 182e8a549cdSBob Wilson } 183e8a549cdSBob Wilson 18462c7b5bfSEvan Cheng bool MLxExpansion::hasRAWHazard(unsigned Reg, MachineInstr *MI) const { 18562c7b5bfSEvan Cheng // FIXME: Detect integer instructions properly. 1866cc775f9SEvan Cheng const MCInstrDesc &MCID = MI->getDesc(); 1876cc775f9SEvan Cheng unsigned Domain = MCID.TSFlags & ARMII::DomainMask; 1887f8e563aSEvan Cheng if (MI->mayStore()) 18904ad35b5SEvan Cheng return false; 1906cc775f9SEvan Cheng unsigned Opcode = MCID.getOpcode(); 19104ad35b5SEvan Cheng if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD) 19262c7b5bfSEvan Cheng return false; 19304ad35b5SEvan Cheng if ((Domain & ARMII::DomainVFP) || (Domain & ARMII::DomainNEON)) 19462c7b5bfSEvan Cheng return MI->readsRegister(Reg, TRI); 19562c7b5bfSEvan Cheng return false; 19662c7b5bfSEvan Cheng } 19762c7b5bfSEvan Cheng 198e8a549cdSBob Wilson static bool isFpMulInstruction(unsigned Opcode) { 199e8a549cdSBob Wilson switch (Opcode) { 200e8a549cdSBob Wilson case ARM::VMULS: 201e8a549cdSBob Wilson case ARM::VMULfd: 202e8a549cdSBob Wilson case ARM::VMULfq: 203e8a549cdSBob Wilson case ARM::VMULD: 204e8a549cdSBob Wilson case ARM::VMULslfd: 205e8a549cdSBob Wilson case ARM::VMULslfq: 206e8a549cdSBob Wilson return true; 207e8a549cdSBob Wilson default: 208e8a549cdSBob Wilson return false; 209e8a549cdSBob Wilson } 210e8a549cdSBob Wilson } 21162c7b5bfSEvan Cheng 2120858c3aaSBob Wilson bool MLxExpansion::FindMLxHazard(MachineInstr *MI) { 21362c7b5bfSEvan Cheng if (NumExpand >= ExpandLimit) 21462c7b5bfSEvan Cheng return false; 21562c7b5bfSEvan Cheng 21662c7b5bfSEvan Cheng if (ForceExapnd) 21762c7b5bfSEvan Cheng return true; 21862c7b5bfSEvan Cheng 21962c7b5bfSEvan Cheng MachineInstr *DefMI = getAccDefMI(MI); 2200858c3aaSBob Wilson if (TII->isFpMLxInstruction(DefMI->getOpcode())) { 22162c7b5bfSEvan Cheng // r0 = vmla 22262c7b5bfSEvan Cheng // r3 = vmla r0, r1, r2 22362c7b5bfSEvan Cheng // takes 16 - 17 cycles 22462c7b5bfSEvan Cheng // 22562c7b5bfSEvan Cheng // r0 = vmla 22662c7b5bfSEvan Cheng // r4 = vmul r1, r2 22762c7b5bfSEvan Cheng // r3 = vadd r0, r4 22862c7b5bfSEvan Cheng // takes about 14 - 15 cycles even with vmul stalling for 4 cycles. 2290858c3aaSBob Wilson IgnoreStall.insert(DefMI); 23062c7b5bfSEvan Cheng return true; 2310858c3aaSBob Wilson } 2320858c3aaSBob Wilson 233e8a549cdSBob Wilson // On Swift, we mostly care about hazards from multiplication instructions 234e8a549cdSBob Wilson // writing the accumulator and the pipelining of loop iterations by out-of- 235e8a549cdSBob Wilson // order execution. 236e8a549cdSBob Wilson if (isSwift) 237e8a549cdSBob Wilson return isFpMulInstruction(DefMI->getOpcode()) || hasLoopHazard(MI); 238e8a549cdSBob Wilson 2390858c3aaSBob Wilson if (IgnoreStall.count(MI)) 2400858c3aaSBob Wilson return false; 24162c7b5bfSEvan Cheng 24262c7b5bfSEvan Cheng // If a VMLA.F is followed by an VADD.F or VMUL.F with no RAW hazard, the 24362c7b5bfSEvan Cheng // VADD.F or VMUL.F will stall 4 cycles before issue. The 4 cycle stall 24462c7b5bfSEvan Cheng // preserves the in-order retirement of the instructions. 24562c7b5bfSEvan Cheng // Look at the next few instructions, if *most* of them can cause hazards, 24662c7b5bfSEvan Cheng // then the scheduler can't *fix* this, we'd better break up the VMLA. 247b47bb94fSSilviu Baranga unsigned Limit1 = isLikeA9 ? 1 : 4; 248b47bb94fSSilviu Baranga unsigned Limit2 = isLikeA9 ? 1 : 4; 24962c7b5bfSEvan Cheng for (unsigned i = 1; i <= 4; ++i) { 25062c7b5bfSEvan Cheng int Idx = ((int)MIIdx - i + 4) % 4; 25162c7b5bfSEvan Cheng MachineInstr *NextMI = LastMIs[Idx]; 25262c7b5bfSEvan Cheng if (!NextMI) 25362c7b5bfSEvan Cheng continue; 25462c7b5bfSEvan Cheng 2550858c3aaSBob Wilson if (TII->canCauseFpMLxStall(NextMI->getOpcode())) { 2560858c3aaSBob Wilson if (i <= Limit1) 25762c7b5bfSEvan Cheng return true; 2580858c3aaSBob Wilson } 25962c7b5bfSEvan Cheng 26062c7b5bfSEvan Cheng // Look for VMLx RAW hazard. 2610858c3aaSBob Wilson if (i <= Limit2 && hasRAWHazard(getDefReg(MI), NextMI)) 26262c7b5bfSEvan Cheng return true; 26362c7b5bfSEvan Cheng } 26462c7b5bfSEvan Cheng 26562c7b5bfSEvan Cheng return false; 26662c7b5bfSEvan Cheng } 26762c7b5bfSEvan Cheng 26862c7b5bfSEvan Cheng /// ExpandFPMLxInstructions - Expand a MLA / MLS instruction into a pair 26962c7b5bfSEvan Cheng /// of MUL + ADD / SUB instructions. 27062c7b5bfSEvan Cheng void 27162c7b5bfSEvan Cheng MLxExpansion::ExpandFPMLxInstruction(MachineBasicBlock &MBB, MachineInstr *MI, 27262c7b5bfSEvan Cheng unsigned MulOpc, unsigned AddSubOpc, 27362c7b5bfSEvan Cheng bool NegAcc, bool HasLane) { 27462c7b5bfSEvan Cheng unsigned DstReg = MI->getOperand(0).getReg(); 27562c7b5bfSEvan Cheng bool DstDead = MI->getOperand(0).isDead(); 27662c7b5bfSEvan Cheng unsigned AccReg = MI->getOperand(1).getReg(); 27762c7b5bfSEvan Cheng unsigned Src1Reg = MI->getOperand(2).getReg(); 27862c7b5bfSEvan Cheng unsigned Src2Reg = MI->getOperand(3).getReg(); 27962c7b5bfSEvan Cheng bool Src1Kill = MI->getOperand(2).isKill(); 28062c7b5bfSEvan Cheng bool Src2Kill = MI->getOperand(3).isKill(); 28162c7b5bfSEvan Cheng unsigned LaneImm = HasLane ? MI->getOperand(4).getImm() : 0; 28262c7b5bfSEvan Cheng unsigned NextOp = HasLane ? 5 : 4; 28362c7b5bfSEvan Cheng ARMCC::CondCodes Pred = (ARMCC::CondCodes)MI->getOperand(NextOp).getImm(); 28462c7b5bfSEvan Cheng unsigned PredReg = MI->getOperand(++NextOp).getReg(); 28562c7b5bfSEvan Cheng 2866cc775f9SEvan Cheng const MCInstrDesc &MCID1 = TII->get(MulOpc); 2876cc775f9SEvan Cheng const MCInstrDesc &MCID2 = TII->get(AddSubOpc); 2883c52f028SJakob Stoklund Olesen const MachineFunction &MF = *MI->getParent()->getParent(); 2893c52f028SJakob Stoklund Olesen unsigned TmpReg = MRI->createVirtualRegister( 2903c52f028SJakob Stoklund Olesen TII->getRegClass(MCID1, 0, TRI, MF)); 29162c7b5bfSEvan Cheng 2927fae11b2SEvan Cheng MachineInstrBuilder MIB = BuildMI(MBB, MI, MI->getDebugLoc(), MCID1, TmpReg) 29362c7b5bfSEvan Cheng .addReg(Src1Reg, getKillRegState(Src1Kill)) 29462c7b5bfSEvan Cheng .addReg(Src2Reg, getKillRegState(Src2Kill)); 29562c7b5bfSEvan Cheng if (HasLane) 29662c7b5bfSEvan Cheng MIB.addImm(LaneImm); 29762c7b5bfSEvan Cheng MIB.addImm(Pred).addReg(PredReg); 29862c7b5bfSEvan Cheng 2997fae11b2SEvan Cheng MIB = BuildMI(MBB, MI, MI->getDebugLoc(), MCID2) 30062c7b5bfSEvan Cheng .addReg(DstReg, getDefRegState(true) | getDeadRegState(DstDead)); 30162c7b5bfSEvan Cheng 30262c7b5bfSEvan Cheng if (NegAcc) { 30362c7b5bfSEvan Cheng bool AccKill = MRI->hasOneNonDBGUse(AccReg); 30462c7b5bfSEvan Cheng MIB.addReg(TmpReg, getKillRegState(true)) 30562c7b5bfSEvan Cheng .addReg(AccReg, getKillRegState(AccKill)); 30662c7b5bfSEvan Cheng } else { 30762c7b5bfSEvan Cheng MIB.addReg(AccReg).addReg(TmpReg, getKillRegState(true)); 30862c7b5bfSEvan Cheng } 30962c7b5bfSEvan Cheng MIB.addImm(Pred).addReg(PredReg); 31062c7b5bfSEvan Cheng 31162c7b5bfSEvan Cheng DEBUG({ 31262c7b5bfSEvan Cheng dbgs() << "Expanding: " << *MI; 31362c7b5bfSEvan Cheng dbgs() << " to:\n"; 31462c7b5bfSEvan Cheng MachineBasicBlock::iterator MII = MI; 315*b6d0bd48SBenjamin Kramer MII = std::prev(MII); 31662c7b5bfSEvan Cheng MachineInstr &MI2 = *MII; 317*b6d0bd48SBenjamin Kramer MII = std::prev(MII); 31862c7b5bfSEvan Cheng MachineInstr &MI1 = *MII; 31962c7b5bfSEvan Cheng dbgs() << " " << MI1; 32062c7b5bfSEvan Cheng dbgs() << " " << MI2; 32162c7b5bfSEvan Cheng }); 32262c7b5bfSEvan Cheng 32362c7b5bfSEvan Cheng MI->eraseFromParent(); 32462c7b5bfSEvan Cheng ++NumExpand; 32562c7b5bfSEvan Cheng } 32662c7b5bfSEvan Cheng 32762c7b5bfSEvan Cheng bool MLxExpansion::ExpandFPMLxInstructions(MachineBasicBlock &MBB) { 32862c7b5bfSEvan Cheng bool Changed = false; 32962c7b5bfSEvan Cheng 33062c7b5bfSEvan Cheng clearStack(); 3310858c3aaSBob Wilson IgnoreStall.clear(); 33262c7b5bfSEvan Cheng 33362c7b5bfSEvan Cheng unsigned Skip = 0; 33462c7b5bfSEvan Cheng MachineBasicBlock::reverse_iterator MII = MBB.rbegin(), E = MBB.rend(); 33562c7b5bfSEvan Cheng while (MII != E) { 33662c7b5bfSEvan Cheng MachineInstr *MI = &*MII; 33762c7b5bfSEvan Cheng 33862c7b5bfSEvan Cheng if (MI->isLabel() || MI->isImplicitDef() || MI->isCopy()) { 33962c7b5bfSEvan Cheng ++MII; 34062c7b5bfSEvan Cheng continue; 34162c7b5bfSEvan Cheng } 34262c7b5bfSEvan Cheng 3436cc775f9SEvan Cheng const MCInstrDesc &MCID = MI->getDesc(); 3447f8e563aSEvan Cheng if (MI->isBarrier()) { 34562c7b5bfSEvan Cheng clearStack(); 34662c7b5bfSEvan Cheng Skip = 0; 34762c7b5bfSEvan Cheng ++MII; 34862c7b5bfSEvan Cheng continue; 34962c7b5bfSEvan Cheng } 35062c7b5bfSEvan Cheng 3516cc775f9SEvan Cheng unsigned Domain = MCID.TSFlags & ARMII::DomainMask; 35262c7b5bfSEvan Cheng if (Domain == ARMII::DomainGeneral) { 35362c7b5bfSEvan Cheng if (++Skip == 2) 35462c7b5bfSEvan Cheng // Assume dual issues of non-VFP / NEON instructions. 35562c7b5bfSEvan Cheng pushStack(0); 35662c7b5bfSEvan Cheng } else { 35762c7b5bfSEvan Cheng Skip = 0; 35862c7b5bfSEvan Cheng 35962c7b5bfSEvan Cheng unsigned MulOpc, AddSubOpc; 36062c7b5bfSEvan Cheng bool NegAcc, HasLane; 3616cc775f9SEvan Cheng if (!TII->isFpMLxInstruction(MCID.getOpcode(), 36262c7b5bfSEvan Cheng MulOpc, AddSubOpc, NegAcc, HasLane) || 36362c7b5bfSEvan Cheng !FindMLxHazard(MI)) 36462c7b5bfSEvan Cheng pushStack(MI); 36562c7b5bfSEvan Cheng else { 36662c7b5bfSEvan Cheng ExpandFPMLxInstruction(MBB, MI, MulOpc, AddSubOpc, NegAcc, HasLane); 36762c7b5bfSEvan Cheng E = MBB.rend(); // May have changed if MI was the 1st instruction. 36862c7b5bfSEvan Cheng Changed = true; 36962c7b5bfSEvan Cheng continue; 37062c7b5bfSEvan Cheng } 37162c7b5bfSEvan Cheng } 37262c7b5bfSEvan Cheng 37362c7b5bfSEvan Cheng ++MII; 37462c7b5bfSEvan Cheng } 37562c7b5bfSEvan Cheng 37662c7b5bfSEvan Cheng return Changed; 37762c7b5bfSEvan Cheng } 37862c7b5bfSEvan Cheng 37962c7b5bfSEvan Cheng bool MLxExpansion::runOnMachineFunction(MachineFunction &Fn) { 38062c7b5bfSEvan Cheng TII = static_cast<const ARMBaseInstrInfo*>(Fn.getTarget().getInstrInfo()); 38162c7b5bfSEvan Cheng TRI = Fn.getTarget().getRegisterInfo(); 38262c7b5bfSEvan Cheng MRI = &Fn.getRegInfo(); 3830858c3aaSBob Wilson const ARMSubtarget *STI = &Fn.getTarget().getSubtarget<ARMSubtarget>(); 384e8a549cdSBob Wilson isLikeA9 = STI->isLikeA9() || STI->isSwift(); 385e8a549cdSBob Wilson isSwift = STI->isSwift(); 38662c7b5bfSEvan Cheng 38762c7b5bfSEvan Cheng bool Modified = false; 38862c7b5bfSEvan Cheng for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E; 38962c7b5bfSEvan Cheng ++MFI) { 39062c7b5bfSEvan Cheng MachineBasicBlock &MBB = *MFI; 39162c7b5bfSEvan Cheng Modified |= ExpandFPMLxInstructions(MBB); 39262c7b5bfSEvan Cheng } 39362c7b5bfSEvan Cheng 39462c7b5bfSEvan Cheng return Modified; 39562c7b5bfSEvan Cheng } 39662c7b5bfSEvan Cheng 39762c7b5bfSEvan Cheng FunctionPass *llvm::createMLxExpansionPass() { 39862c7b5bfSEvan Cheng return new MLxExpansion(); 39962c7b5bfSEvan Cheng } 400