32 #define DEBUG_TYPE "aarch64-vectorbyelement-opt"
35 "Number of vector by element instructions modified");
37 #define AARCH64_VECTOR_BY_ELEMENT_OPT_NAME \
38 "AArch64 vector by element instruction optimization pass"
77 bool reuseDUP(
MachineInstr &
MI,
unsigned DupOpcode,
unsigned SrcReg,
78 unsigned LaneNumber,
unsigned *DestReg)
const;
85 std::map<unsigned, bool> *VecInstElemTable)
const;
96 INITIALIZE_PASS(AArch64VectorByElementOpt,
"aarch64-vectorbyelement-opt",
105 bool AArch64VectorByElementOpt::shouldReplaceInstruction(
111 if (!VecInstElemTable.empty() &&
112 VecInstElemTable.find(InstDesc->getOpcode()) != VecInstElemTable.end())
113 return VecInstElemTable[InstDesc->getOpcode()];
115 unsigned SCIdx = InstDesc->getSchedClass();
119 SchedModel.getMCSchedModel()->getSchedClassDesc(SCIdx);
121 SchedModel.getMCSchedModel()->getSchedClassDesc(SCIdxRep1);
123 SchedModel.getMCSchedModel()->getSchedClassDesc(SCIdxRep2);
130 VecInstElemTable[InstDesc->getOpcode()] =
false;
134 if (SchedModel.computeInstrLatency(InstDesc->getOpcode()) >
135 SchedModel.computeInstrLatency(InstDescRep1->getOpcode()) +
136 SchedModel.computeInstrLatency(InstDescRep2->getOpcode())) {
137 VecInstElemTable[InstDesc->getOpcode()] =
true;
140 VecInstElemTable[InstDesc->getOpcode()] =
false;
153 bool AArch64VectorByElementOpt::earlyExitVectElement(
MachineFunction *MF) {
155 const MCInstrDesc *IndexMulMCID = &
TII->get(AArch64::FMLAv4i32_indexed);
159 if (!shouldReplaceInstruction(MF, IndexMulMCID, DupMCID, MulMCID,
169 bool AArch64VectorByElementOpt::reuseDUP(
MachineInstr &
MI,
unsigned DupOpcode,
170 unsigned SrcReg,
unsigned LaneNumber,
171 unsigned *DestReg)
const {
177 if (CurrentMI->
getOpcode() == DupOpcode &&
201 bool AArch64VectorByElementOpt::optimizeVectElement(
202 MachineInstr &MI, std::map<unsigned, bool> *VecInstElemTable)
const {
211 case AArch64::FMLAv4i32_indexed:
212 DupMCID = &
TII->get(AArch64::DUPv4i32lane);
213 MulMCID = &
TII->get(AArch64::FMLAv4f32);
215 case AArch64::FMLSv4i32_indexed:
216 DupMCID = &
TII->get(AArch64::DUPv4i32lane);
217 MulMCID = &
TII->get(AArch64::FMLSv4f32);
219 case AArch64::FMULXv4i32_indexed:
220 DupMCID = &
TII->get(AArch64::DUPv4i32lane);
221 MulMCID = &
TII->get(AArch64::FMULXv4f32);
223 case AArch64::FMULv4i32_indexed:
224 DupMCID = &
TII->get(AArch64::DUPv4i32lane);
225 MulMCID = &
TII->get(AArch64::FMULv4f32);
229 case AArch64::FMLAv2i64_indexed:
230 DupMCID = &
TII->get(AArch64::DUPv2i64lane);
231 MulMCID = &
TII->get(AArch64::FMLAv2f64);
233 case AArch64::FMLSv2i64_indexed:
234 DupMCID = &
TII->get(AArch64::DUPv2i64lane);
235 MulMCID = &
TII->get(AArch64::FMLSv2f64);
237 case AArch64::FMULXv2i64_indexed:
238 DupMCID = &
TII->get(AArch64::DUPv2i64lane);
239 MulMCID = &
TII->get(AArch64::FMULXv2f64);
241 case AArch64::FMULv2i64_indexed:
242 DupMCID = &
TII->get(AArch64::DUPv2i64lane);
243 MulMCID = &
TII->get(AArch64::FMULv2f64);
247 case AArch64::FMLAv2i32_indexed:
248 RC = &AArch64::FPR64RegClass;
249 DupMCID = &
TII->get(AArch64::DUPv2i32lane);
250 MulMCID = &
TII->get(AArch64::FMLAv2f32);
252 case AArch64::FMLSv2i32_indexed:
253 RC = &AArch64::FPR64RegClass;
254 DupMCID = &
TII->get(AArch64::DUPv2i32lane);
255 MulMCID = &
TII->get(AArch64::FMLSv2f32);
257 case AArch64::FMULXv2i32_indexed:
258 RC = &AArch64::FPR64RegClass;
259 DupMCID = &
TII->get(AArch64::DUPv2i32lane);
260 MulMCID = &
TII->get(AArch64::FMULXv2f32);
262 case AArch64::FMULv2i32_indexed:
263 RC = &AArch64::FPR64RegClass;
264 DupMCID = &
TII->get(AArch64::DUPv2i32lane);
265 MulMCID = &
TII->get(AArch64::FMULv2f32);
295 if (!reuseDUP(MI, DupMCID->
getOpcode(), SrcReg2, LaneNumber, &DupDest)) {
297 BuildMI(MBB, MI, DL, *DupMCID, DupDest)
298 .
addReg(SrcReg2, Src2IsKill)
301 BuildMI(MBB, MI, DL, *MulMCID, MulDest)
302 .
addReg(SrcReg0, Src0IsKill)
303 .
addReg(SrcReg1, Src1IsKill)
304 .
addReg(DupDest, Src2IsKill);
307 if (!reuseDUP(MI, DupMCID->
getOpcode(), SrcReg1, LaneNumber, &DupDest)) {
309 BuildMI(MBB, MI, DL, *DupMCID, DupDest)
310 .
addReg(SrcReg1, Src1IsKill)
313 BuildMI(MBB, MI, DL, *MulMCID, MulDest)
314 .
addReg(SrcReg0, Src0IsKill)
315 .
addReg(DupDest, Src1IsKill);
324 bool AArch64VectorByElementOpt::runOnMachineFunction(
MachineFunction &MF) {
336 if (!SchedModel.hasInstrSchedModel())
340 if (earlyExitVectElement(&MF))
343 bool Changed =
false;
351 if (optimizeVectElement(MI, &VecInstElemTable)) {
370 return new AArch64VectorByElementOpt();
void push_back(const T &Elt)
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
STATISTIC(NumFunctions,"Total number of functions")
unsigned createVirtualRegister(const TargetRegisterClass *RegClass)
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
#define AARCH64_VECTOR_BY_ELEMENT_OPT_NAME
Describe properties that are true of each instruction in the target description file.
const Function * getFunction() const
getFunction - Return the LLVM function that this machine code represents
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
Provide an instruction scheduling machine model to CodeGen passes.
const HexagonInstrInfo * TII
FunctionPass * createAArch64VectorByElementOptPass()
createAArch64VectorByElementOptPass - returns an instance of the vector by element optimization pass...
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
const MCSchedModel & getSchedModel() const
Get the machine model for this subtarget's CPU.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
unsigned getNumOperands() const
Access to explicit operands of the instruction.
INITIALIZE_PASS(AArch64VectorByElementOpt,"aarch64-vectorbyelement-opt", AARCH64_VECTOR_BY_ELEMENT_OPT_NAME, false, false) bool AArch64VectorByElementOpt unsigned SCIdx
Based only on latency of instructions, determine if it is cost efficient to replace the instruction I...
const MCSchedClassDesc * SCDescRep2
unsigned getKillRegState(bool B)
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
TargetInstrInfo - Interface to description of machine instruction set.
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
unsigned const MachineRegisterInfo * MRI
void initializeAArch64VectorByElementOptPass(PassRegistry &)
const MachineOperand & getOperand(unsigned i) const
Summarize the scheduling resources required for an instruction of a particular scheduling class...
FunctionPass class - This class is used to implement most global optimizations.
VecInstElemTable[InstDesc->getOpcode()]
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
unsigned getOpcode() const
Return the opcode number for this descriptor.
const MCSchedClassDesc * SCDescRep1
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
TargetSubtargetInfo - Generic base class for all target subtargets.
Representation of each machine instruction.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
unsigned getReg() const
getReg - Returns the register number.
virtual const TargetInstrInfo * getInstrInfo() const
StringRef - Represent a constant reference to a string, i.e.
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MCSchedClassDesc * SCDesc