30#define DEBUG_TYPE "mlx-expansion"
37STATISTIC(NumExpand,
"Number of fp MLA / MLS instructions expanded");
44 bool runOnMachineFunction(MachineFunction &Fn)
override;
46 StringRef getPassName()
const override {
47 return "ARM MLA / MLS expansion pass";
50 void getAnalysisUsage(AnalysisUsage &AU)
const override {
56 const ARMBaseInstrInfo *TII;
57 const TargetRegisterInfo *TRI;
58 MachineRegisterInfo *MRI;
63 MachineInstr* LastMIs[4];
64 SmallPtrSet<MachineInstr*, 4> IgnoreStall;
67 void pushStack(MachineInstr *
MI);
68 MachineInstr *getAccDefMI(MachineInstr *
MI)
const;
69 unsigned getDefReg(MachineInstr *
MI)
const;
70 bool hasLoopHazard(MachineInstr *
MI)
const;
72 bool FindMLxHazard(MachineInstr *
MI);
73 void ExpandFPMLxInstruction(MachineBasicBlock &
MBB, MachineInstr *
MI,
74 unsigned MulOpc,
unsigned AddSubOpc,
75 bool NegAcc,
bool HasLane);
76 bool ExpandFPMLxInstructions(MachineBasicBlock &
MBB);
78 char MLxExpansion::ID = 0;
81void MLxExpansion::clearStack() {
82 std::fill(LastMIs, LastMIs + 4,
nullptr);
86void MLxExpansion::pushStack(MachineInstr *
MI) {
92MachineInstr *MLxExpansion::getAccDefMI(MachineInstr *
MI)
const {
99 MachineBasicBlock *
MBB =
MI->getParent();
122unsigned MLxExpansion::getDefReg(MachineInstr *
MI)
const {
127 MachineBasicBlock *
MBB =
MI->getParent();
146bool MLxExpansion::hasLoopHazard(MachineInstr *
MI)
const {
151 MachineBasicBlock *
MBB =
MI->getParent();
188bool MLxExpansion::hasRAWHazard(
unsigned Reg, MachineInstr *
MI)
const {
190 const MCInstrDesc &MCID =
MI->getDesc();
195 if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD)
216bool MLxExpansion::FindMLxHazard(MachineInstr *
MI) {
223 MachineInstr *
DefMI = getAccDefMI(
MI);
233 IgnoreStall.insert(
DefMI);
243 if (IgnoreStall.count(
MI))
251 unsigned Limit1 = isLikeA9 ? 1 : 4;
252 unsigned Limit2 = isLikeA9 ? 1 : 4;
253 for (
unsigned i = 1; i <= 4; ++i) {
254 int Idx = ((int)MIIdx - i + 4) % 4;
255 MachineInstr *NextMI = LastMIs[Idx];
275MLxExpansion::ExpandFPMLxInstruction(MachineBasicBlock &
MBB, MachineInstr *
MI,
276 unsigned MulOpc,
unsigned AddSubOpc,
277 bool NegAcc,
bool HasLane) {
279 bool DstDead =
MI->getOperand(0).isDead();
281 Register Src1Reg =
MI->getOperand(2).getReg();
282 Register Src2Reg =
MI->getOperand(3).getReg();
283 bool Src1Kill =
MI->getOperand(2).isKill();
284 bool Src2Kill =
MI->getOperand(3).isKill();
285 unsigned LaneImm = HasLane ?
MI->getOperand(4).getImm() : 0;
286 unsigned NextOp = HasLane ? 5 : 4;
288 Register PredReg =
MI->getOperand(++NextOp).getReg();
290 const MCInstrDesc &MCID1 =
TII->get(MulOpc);
291 const MCInstrDesc &MCID2 =
TII->get(AddSubOpc);
294 MachineInstrBuilder MIB =
BuildMI(
MBB,
MI,
MI->getDebugLoc(), MCID1, TmpReg)
314 dbgs() <<
"Expanding: " << *
MI;
317 MII = std::prev(MII);
318 MachineInstr &MI2 = *MII;
319 MII = std::prev(MII);
320 MachineInstr &MI1 = *MII;
321 dbgs() <<
" " << MI1;
322 dbgs() <<
" " << MI2;
325 MI->eraseFromParent();
329bool MLxExpansion::ExpandFPMLxInstructions(MachineBasicBlock &
MBB) {
338 MachineInstr *
MI = &*MII++;
340 if (
MI->isPosition() ||
MI->isImplicitDef() ||
MI->isCopy())
343 const MCInstrDesc &MCID =
MI->getDesc();
344 if (
MI->isBarrier()) {
358 unsigned MulOpc, AddSubOpc;
359 bool NegAcc, HasLane;
361 MulOpc, AddSubOpc, NegAcc, HasLane) ||
365 ExpandFPMLxInstruction(
MBB,
MI, MulOpc, AddSubOpc, NegAcc, HasLane);
374bool MLxExpansion::runOnMachineFunction(MachineFunction &Fn) {
378 TII =
static_cast<const ARMBaseInstrInfo *
>(Fn.
getSubtarget().getInstrInfo());
381 const ARMSubtarget *STI = &Fn.
getSubtarget<ARMSubtarget>();
382 if (!STI->expandMLx())
388 for (MachineBasicBlock &
MBB : Fn)
395 return new MLxExpansion();
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 > ForceExpand("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)
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
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...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
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 & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate 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.
LLVM_ABI bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
LLVM_ABI MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
use_instr_nodbg_iterator use_instr_nodbg_begin(Register RegNo) const
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.
constexpr RegState getKillRegState(bool B)
constexpr RegState getDeadRegState(bool B)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
constexpr RegState getDefRegState(bool B)
FunctionPass * createMLxExpansionPass()