62#define HEXAGON_QFP_OPTIMIZER "QFP optimizer pass"
81#define DEBUG_TYPE "hexagon-qfp-optimizer"
87 cl::desc(
"Disable optimization of Qfloat operations."));
89 "disable-qfp-opt-mul",
cl::init(
true),
90 cl::desc(
"Disable optimization of Qfloat operations for multiply."));
93const std::map<unsigned short, unsigned short> QFPInstMap{
94 {Hexagon::V6_vadd_hf, Hexagon::V6_vadd_qf16_mix},
95 {Hexagon::V6_vadd_qf16_mix, Hexagon::V6_vadd_qf16},
96 {Hexagon::V6_vadd_sf, Hexagon::V6_vadd_qf32_mix},
97 {Hexagon::V6_vadd_qf32_mix, Hexagon::V6_vadd_qf32},
98 {Hexagon::V6_vsub_hf, Hexagon::V6_vsub_qf16_mix},
99 {Hexagon::V6_vsub_qf16_mix, Hexagon::V6_vsub_qf16},
100 {Hexagon::V6_vsub_sf, Hexagon::V6_vsub_qf32_mix},
101 {Hexagon::V6_vsub_qf32_mix, Hexagon::V6_vsub_qf32},
102 {Hexagon::V6_vmpy_qf16_hf, Hexagon::V6_vmpy_qf16_mix_hf},
103 {Hexagon::V6_vmpy_qf16_mix_hf, Hexagon::V6_vmpy_qf16},
104 {Hexagon::V6_vmpy_qf32_hf, Hexagon::V6_vmpy_qf32_mix_hf},
105 {Hexagon::V6_vmpy_qf32_mix_hf, Hexagon::V6_vmpy_qf32_qf16},
106 {Hexagon::V6_vmpy_qf32_sf, Hexagon::V6_vmpy_qf32},
107 {Hexagon::V6_vilog2_sf, Hexagon::V6_vilog2_qf32},
108 {Hexagon::V6_vilog2_hf, Hexagon::V6_vilog2_qf16},
109 {Hexagon::V6_vabs_qf32_sf, Hexagon::V6_vabs_qf32_qf32},
110 {Hexagon::V6_vabs_qf16_hf, Hexagon::V6_vabs_qf16_qf16},
111 {Hexagon::V6_vneg_qf32_sf, Hexagon::V6_vneg_qf32_qf32},
112 {Hexagon::V6_vneg_qf16_hf, Hexagon::V6_vneg_qf16_qf16}};
120 HexagonQFPOptimizer() : MachineFunctionPass(ID) {}
122 bool runOnMachineFunction(MachineFunction &MF)
override;
124 bool optimizeQfp(MachineInstr *
MI, MachineBasicBlock *
MBB);
126 bool optimizeQfpTwoOp(MachineInstr *
MI, MachineBasicBlock *
MBB);
128 bool optimizeQfpOneOp(MachineInstr *
MI, MachineBasicBlock *
MBB);
132 void getAnalysisUsage(AnalysisUsage &AU)
const override {
138 const HexagonSubtarget *HST =
nullptr;
139 const HexagonInstrInfo *HII =
nullptr;
140 const MachineRegisterInfo *MRI =
nullptr;
143char HexagonQFPOptimizer::ID = 0;
150 return new HexagonQFPOptimizer();
156 if (
MI->getNumOperands() == 2)
157 return optimizeQfpOneOp(
MI,
MBB);
158 else if (
MI->getNumOperands() == 3)
159 return optimizeQfpTwoOp(
MI,
MBB);
164bool HexagonQFPOptimizer::optimizeQfpOneOp(MachineInstr *
MI,
165 MachineBasicBlock *
MBB) {
168 auto It = QFPInstMap.find(
MI->getOpcode());
169 if (It == QFPInstMap.end())
172 unsigned short InstTy = It->second;
174 MachineInstr *
DefMI =
MRI->getVRegDef(
MI->getOperand(1).getReg());
175 MachineOperand &Res =
MI->getOperand(0);
180 MachineInstr *ReachDefDef =
nullptr;
187 MachineInstrBuilder MIB;
190 if (ReachDefOp == Hexagon::V6_vconv_sf_qf32 ||
191 ReachDefOp == Hexagon::V6_vconv_hf_qf16) {
195 &Hexagon::HvxWRRegClass)
210bool HexagonQFPOptimizer::optimizeQfpTwoOp(MachineInstr *
MI,
211 MachineBasicBlock *
MBB) {
215 auto It = QFPInstMap.find(
MI->getOpcode());
216 if (It == QFPInstMap.end())
218 unsigned short InstTy = It->second;
220 MachineInstr *DefMI1 =
nullptr;
221 MachineInstr *DefMI2 =
nullptr;
223 if (
MI->getOperand(1).isReg())
224 DefMI1 =
MRI->getVRegDef(
MI->getOperand(1).getReg());
225 if (
MI->getOperand(2).isReg())
226 DefMI2 =
MRI->getVRegDef(
MI->getOperand(2).getReg());
227 if (!DefMI1 || !DefMI2)
230 MachineOperand &Res =
MI->getOperand(0);
234 MachineInstr *Inst1 =
nullptr;
235 MachineInstr *Inst2 =
nullptr;
251 MachineInstrBuilder MIB;
254 if ((Def1OP == Hexagon::V6_vconv_sf_qf32 &&
255 Def2OP == Hexagon::V6_vconv_sf_qf32) ||
256 (Def1OP == Hexagon::V6_vconv_hf_qf16 &&
257 Def2OP == Hexagon::V6_vconv_hf_qf16)) {
262 &Hexagon::HvxWRRegClass) ||
265 &Hexagon::HvxWRRegClass))
278 if (
MI->getOpcode() != Hexagon::V6_vmpy_qf32_sf) {
279 auto OuterIt = QFPInstMap.find(
MI->getOpcode());
280 if (OuterIt == QFPInstMap.end())
282 auto InnerIt = QFPInstMap.find(OuterIt->second);
283 if (InnerIt == QFPInstMap.end())
285 InstTy = InnerIt->second;
295 }
else if (((Def1OP == Hexagon::V6_vconv_sf_qf32 &&
296 Def2OP != Hexagon::V6_vconv_sf_qf32) ||
297 (Def1OP == Hexagon::V6_vconv_hf_qf16 &&
298 Def2OP != Hexagon::V6_vconv_hf_qf16)) &&
300 (
MI->getOpcode() != Hexagon::V6_vmpy_qf32_sf)) {
303 &Hexagon::HvxWRRegClass)
307 MachineOperand &Src2 =
MI->getOperand(2);
319 }
else if (((Def1OP != Hexagon::V6_vconv_sf_qf32 &&
320 Def2OP == Hexagon::V6_vconv_sf_qf32) ||
321 (Def1OP != Hexagon::V6_vconv_hf_qf16 &&
322 Def2OP == Hexagon::V6_vconv_hf_qf16)) &&
324 (
MI->getOpcode() != Hexagon::V6_vmpy_qf32_sf)) {
327 &Hexagon::HvxWRRegClass)
330 MachineOperand &Src1 =
MI->getOperand(1);
336 if (InstTy == Hexagon::V6_vsub_qf16_mix ||
337 InstTy == Hexagon::V6_vsub_qf32_mix) {
343 if (Def2OP == Hexagon::V6_vconv_sf_qf32)
344 InstTy = Hexagon::V6_vsub_sf_mix;
345 else if (Def2OP == Hexagon::V6_vconv_hf_qf16)
346 InstTy = Hexagon::V6_vsub_hf_mix;
363bool HexagonQFPOptimizer::runOnMachineFunction(MachineFunction &MF) {
379 <<
" Optimize intermediate conversions ===\n");
381 MachineBasicBlock *
MBB = &*
MBBI;
384 MachineInstr *
MI = &*MII;
386 if (QFPInstMap.count(
MI->getOpcode())) {
387 auto OpC =
MI->getOpcode();
390 if (OpC != Hexagon::V6_vconv_sf_qf32 &&
391 OpC != Hexagon::V6_vconv_hf_qf16) {
393 if (optimizeQfp(
MI,
MBB)) {
394 MI->eraseFromParent();
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder MachineInstrBuilder & DefMI
MachineBasicBlock MachineBasicBlock::iterator MBBI
cl::opt< bool > DisableQFOptimizer("disable-qfp-opt", cl::init(false), cl::desc("Disable optimization of Qfloat operations."))
cl::opt< bool > DisableQFOptForMul("disable-qfp-opt-mul", cl::init(true), cl::desc("Disable optimization of Qfloat operations for multiply."))
#define HEXAGON_QFP_OPTIMIZER
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
This file defines the SmallVector class.
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
FunctionPass class - This class is used to implement most global optimizations.
bool isQFPMul(const MachineInstr *MF) const
const HexagonInstrInfo * getInstrInfo() const override
bool useHVXV81Ops() const
bool useHVXV68Ops() const
instr_iterator instr_begin()
instr_iterator instr_end()
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.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
unsigned getNumOperands() const
Retuns the total number of operands.
LLVM_ABI void dump() const
const MachineOperand & getOperand(unsigned i) const
unsigned getSubReg() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
void setIsKill(bool Val=true)
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.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
FunctionPass * createHexagonQFPOptimizer()
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
unsigned getKillRegState(bool B)