29#define DEBUG_TYPE "mlx-expansion"
36STATISTIC(NumExpand,
"Number of fp MLA / MLS instructions expanded");
43 bool runOnMachineFunction(MachineFunction &Fn)
override;
45 StringRef getPassName()
const override {
46 return "ARM MLA / MLS expansion pass";
50 const ARMBaseInstrInfo *TII;
51 const TargetRegisterInfo *TRI;
52 MachineRegisterInfo *MRI;
57 MachineInstr* LastMIs[4];
58 SmallPtrSet<MachineInstr*, 4> IgnoreStall;
61 void pushStack(MachineInstr *
MI);
62 MachineInstr *getAccDefMI(MachineInstr *
MI)
const;
63 unsigned getDefReg(MachineInstr *
MI)
const;
64 bool hasLoopHazard(MachineInstr *
MI)
const;
66 bool FindMLxHazard(MachineInstr *
MI);
67 void ExpandFPMLxInstruction(MachineBasicBlock &
MBB, MachineInstr *
MI,
68 unsigned MulOpc,
unsigned AddSubOpc,
69 bool NegAcc,
bool HasLane);
70 bool ExpandFPMLxInstructions(MachineBasicBlock &
MBB);
72 char MLxExpansion::ID = 0;
75void MLxExpansion::clearStack() {
76 std::fill(LastMIs, LastMIs + 4,
nullptr);
80void MLxExpansion::pushStack(MachineInstr *
MI) {
86MachineInstr *MLxExpansion::getAccDefMI(MachineInstr *
MI)
const {
93 MachineBasicBlock *
MBB =
MI->getParent();
116unsigned MLxExpansion::getDefReg(MachineInstr *
MI)
const {
121 MachineBasicBlock *
MBB =
MI->getParent();
122 MachineInstr *
UseMI = &*
MRI->use_instr_nodbg_begin(
Reg);
140bool MLxExpansion::hasLoopHazard(MachineInstr *
MI)
const {
145 MachineBasicBlock *
MBB =
MI->getParent();
182bool MLxExpansion::hasRAWHazard(
unsigned Reg, MachineInstr *
MI)
const {
184 const MCInstrDesc &MCID =
MI->getDesc();
189 if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD)
210bool MLxExpansion::FindMLxHazard(MachineInstr *
MI) {
217 MachineInstr *
DefMI = getAccDefMI(
MI);
227 IgnoreStall.insert(
DefMI);
237 if (IgnoreStall.count(
MI))
245 unsigned Limit1 = isLikeA9 ? 1 : 4;
246 unsigned Limit2 = isLikeA9 ? 1 : 4;
247 for (
unsigned i = 1; i <= 4; ++i) {
248 int Idx = ((int)MIIdx - i + 4) % 4;
249 MachineInstr *NextMI = LastMIs[Idx];
269MLxExpansion::ExpandFPMLxInstruction(MachineBasicBlock &
MBB, MachineInstr *
MI,
270 unsigned MulOpc,
unsigned AddSubOpc,
271 bool NegAcc,
bool HasLane) {
273 bool DstDead =
MI->getOperand(0).isDead();
275 Register Src1Reg =
MI->getOperand(2).getReg();
276 Register Src2Reg =
MI->getOperand(3).getReg();
277 bool Src1Kill =
MI->getOperand(2).isKill();
278 bool Src2Kill =
MI->getOperand(3).isKill();
279 unsigned LaneImm = HasLane ?
MI->getOperand(4).getImm() : 0;
280 unsigned NextOp = HasLane ? 5 : 4;
282 Register PredReg =
MI->getOperand(++NextOp).getReg();
284 const MCInstrDesc &MCID1 =
TII->get(MulOpc);
285 const MCInstrDesc &MCID2 =
TII->get(AddSubOpc);
288 MachineInstrBuilder MIB =
BuildMI(
MBB,
MI,
MI->getDebugLoc(), MCID1, TmpReg)
299 bool AccKill =
MRI->hasOneNonDBGUse(AccReg);
308 dbgs() <<
"Expanding: " << *
MI;
311 MII = std::prev(MII);
312 MachineInstr &MI2 = *MII;
313 MII = std::prev(MII);
314 MachineInstr &MI1 = *MII;
315 dbgs() <<
" " << MI1;
316 dbgs() <<
" " << MI2;
319 MI->eraseFromParent();
323bool MLxExpansion::ExpandFPMLxInstructions(MachineBasicBlock &
MBB) {
332 MachineInstr *
MI = &*MII++;
334 if (
MI->isPosition() ||
MI->isImplicitDef() ||
MI->isCopy())
337 const MCInstrDesc &MCID =
MI->getDesc();
338 if (
MI->isBarrier()) {
352 unsigned MulOpc, AddSubOpc;
353 bool NegAcc, HasLane;
355 MulOpc, AddSubOpc, NegAcc, HasLane) ||
359 ExpandFPMLxInstruction(
MBB,
MI, MulOpc, AddSubOpc, NegAcc, HasLane);
368bool MLxExpansion::runOnMachineFunction(MachineFunction &Fn) {
372 TII =
static_cast<const ARMBaseInstrInfo *
>(Fn.
getSubtarget().getInstrInfo());
375 const ARMSubtarget *STI = &Fn.
getSubtarget<ARMSubtarget>();
376 if (!STI->expandMLx())
382 for (MachineBasicBlock &
MBB : Fn)
389 return new MLxExpansion();
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
static bool hasRAWHazard(MachineInstr *DefMI, MachineInstr *MI, const TargetRegisterInfo &TRI)
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
const HexagonInstrInfo * TII
static cl::opt< unsigned > ExpandLimit("expand-limit", cl::init(~0U), cl::Hidden)
static bool isFpMulInstruction(unsigned Opcode)
static cl::opt< bool > ForceExapnd("expand-all-fp-mlx", cl::init(false), cl::Hidden)
Register const TargetRegisterInfo * TRI
Promote Memory to Register
This file defines the SmallPtrSet class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
FunctionPass class - This class is used to implement most global optimizations.
unsigned getOpcode() const
Return the opcode number for this descriptor.
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
reverse_iterator rbegin()
MachineInstrBundleIterator< MachineInstr > iterator
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
bool isCopyLike() const
Return true if the instruction behaves like a copy.
unsigned getNumOperands() const
Retuns the total number of operands.
bool isInsertSubreg() const
const MachineOperand & getOperand(unsigned i) const
MachineBasicBlock * getMBB() const
Register getReg() const
getReg - Returns the register number.
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
unsigned getDeadRegState(bool B)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
unsigned getDefRegState(bool B)
unsigned getKillRegState(bool B)
FunctionPass * createMLxExpansionPass()