62#define HEXAGON_QFP_OPTIMIZER "QFP optimizer pass"
82#define DEBUG_TYPE "hexagon-qfp-optimizer"
88 cl::desc(
"Disable optimization of Qfloat operations."));
90 "disable-qfp-opt-mul",
cl::init(
true),
91 cl::desc(
"Disable optimization of Qfloat operations for multiply."));
94const std::map<unsigned short, unsigned short> QFPInstMap{
95 {Hexagon::V6_vadd_hf, Hexagon::V6_vadd_qf16_mix},
96 {Hexagon::V6_vadd_qf16_mix, Hexagon::V6_vadd_qf16},
97 {Hexagon::V6_vadd_sf, Hexagon::V6_vadd_qf32_mix},
98 {Hexagon::V6_vadd_qf32_mix, Hexagon::V6_vadd_qf32},
99 {Hexagon::V6_vsub_hf, Hexagon::V6_vsub_qf16_mix},
100 {Hexagon::V6_vsub_qf16_mix, Hexagon::V6_vsub_qf16},
101 {Hexagon::V6_vsub_sf, Hexagon::V6_vsub_qf32_mix},
102 {Hexagon::V6_vsub_qf32_mix, Hexagon::V6_vsub_qf32},
103 {Hexagon::V6_vmpy_qf16_hf, Hexagon::V6_vmpy_qf16_mix_hf},
104 {Hexagon::V6_vmpy_qf16_mix_hf, Hexagon::V6_vmpy_qf16},
105 {Hexagon::V6_vmpy_qf32_hf, Hexagon::V6_vmpy_qf32_mix_hf},
106 {Hexagon::V6_vmpy_qf32_mix_hf, Hexagon::V6_vmpy_qf32_qf16},
107 {Hexagon::V6_vmpy_qf32_sf, Hexagon::V6_vmpy_qf32},
108 {Hexagon::V6_vilog2_sf, Hexagon::V6_vilog2_qf32},
109 {Hexagon::V6_vilog2_hf, Hexagon::V6_vilog2_qf16},
110 {Hexagon::V6_vabs_qf32_sf, Hexagon::V6_vabs_qf32_qf32},
111 {Hexagon::V6_vabs_qf16_hf, Hexagon::V6_vabs_qf16_qf16},
112 {Hexagon::V6_vneg_qf32_sf, Hexagon::V6_vneg_qf32_qf32},
113 {Hexagon::V6_vneg_qf16_hf, Hexagon::V6_vneg_qf16_qf16}};
126 HexagonQFPOptimizer() : MachineFunctionPass(ID) {}
128 bool runOnMachineFunction(MachineFunction &MF)
override;
130 bool optimizeQfp(MachineInstr *
MI, MachineBasicBlock *
MBB);
132 bool optimizeQfpTwoOp(MachineInstr *
MI, MachineBasicBlock *
MBB);
134 bool optimizeQfpOneOp(MachineInstr *
MI, MachineBasicBlock *
MBB);
138 void getAnalysisUsage(AnalysisUsage &AU)
const override {
144 const HexagonSubtarget *HST =
nullptr;
145 const HexagonInstrInfo *HII =
nullptr;
146 const MachineRegisterInfo *MRI =
nullptr;
149char HexagonQFPOptimizer::ID = 0;
156 return new HexagonQFPOptimizer();
162 if (
MI->getNumOperands() == 2)
163 return optimizeQfpOneOp(
MI,
MBB);
164 else if (
MI->getNumOperands() == 3)
165 return optimizeQfpTwoOp(
MI,
MBB);
170bool HexagonQFPOptimizer::optimizeQfpOneOp(MachineInstr *
MI,
171 MachineBasicBlock *
MBB) {
174 auto It = QFPInstMap.find(
MI->getOpcode());
175 if (It == QFPInstMap.end())
178 unsigned short InstTy = It->second;
180 MachineInstr *
DefMI =
MRI->getVRegDef(
MI->getOperand(1).getReg());
181 MachineOperand &Res =
MI->getOperand(0);
186 MachineInstr *ReachDefDef =
nullptr;
193 MachineInstrBuilder MIB;
196 if (ReachDefOp == Hexagon::V6_vconv_sf_qf32 ||
197 ReachDefOp == Hexagon::V6_vconv_hf_qf16) {
201 &Hexagon::HvxWRRegClass)
216bool HexagonQFPOptimizer::optimizeQfpTwoOp(MachineInstr *
MI,
217 MachineBasicBlock *
MBB) {
221 auto It = QFPInstMap.find(
MI->getOpcode());
222 if (It == QFPInstMap.end())
224 unsigned short InstTy = It->second;
226 MachineInstr *DefMI1 =
nullptr;
227 MachineInstr *DefMI2 =
nullptr;
229 if (
MI->getOperand(1).isReg())
230 DefMI1 =
MRI->getVRegDef(
MI->getOperand(1).getReg());
231 if (
MI->getOperand(2).isReg())
232 DefMI2 =
MRI->getVRegDef(
MI->getOperand(2).getReg());
233 if (!DefMI1 || !DefMI2)
236 MachineOperand &Res =
MI->getOperand(0);
240 MachineInstr *Inst1 =
nullptr;
241 MachineInstr *Inst2 =
nullptr;
257 MachineInstrBuilder MIB;
260 if ((Def1OP == Hexagon::V6_vconv_sf_qf32 &&
261 Def2OP == Hexagon::V6_vconv_sf_qf32) ||
262 (Def1OP == Hexagon::V6_vconv_hf_qf16 &&
263 Def2OP == Hexagon::V6_vconv_hf_qf16)) {
268 &Hexagon::HvxWRRegClass) ||
271 &Hexagon::HvxWRRegClass))
284 if (
MI->getOpcode() != Hexagon::V6_vmpy_qf32_sf) {
285 auto OuterIt = QFPInstMap.find(
MI->getOpcode());
286 if (OuterIt == QFPInstMap.end())
288 auto InnerIt = QFPInstMap.find(OuterIt->second);
289 if (InnerIt == QFPInstMap.end())
291 InstTy = InnerIt->second;
301 }
else if (((Def1OP == Hexagon::V6_vconv_sf_qf32 &&
302 Def2OP != Hexagon::V6_vconv_sf_qf32) ||
303 (Def1OP == Hexagon::V6_vconv_hf_qf16 &&
304 Def2OP != Hexagon::V6_vconv_hf_qf16)) &&
306 (
MI->getOpcode() != Hexagon::V6_vmpy_qf32_sf)) {
309 &Hexagon::HvxWRRegClass)
313 MachineOperand &Src2 =
MI->getOperand(2);
325 }
else if (((Def1OP != Hexagon::V6_vconv_sf_qf32 &&
326 Def2OP == Hexagon::V6_vconv_sf_qf32) ||
327 (Def1OP != Hexagon::V6_vconv_hf_qf16 &&
328 Def2OP == Hexagon::V6_vconv_hf_qf16)) &&
330 (
MI->getOpcode() != Hexagon::V6_vmpy_qf32_sf)) {
333 &Hexagon::HvxWRRegClass)
336 MachineOperand &Src1 =
MI->getOperand(1);
342 if (InstTy == Hexagon::V6_vsub_qf16_mix ||
343 InstTy == Hexagon::V6_vsub_qf32_mix) {
349 if (Def2OP == Hexagon::V6_vconv_sf_qf32)
350 InstTy = Hexagon::V6_vsub_sf_mix;
351 else if (Def2OP == Hexagon::V6_vconv_hf_qf16)
352 InstTy = Hexagon::V6_vsub_hf_mix;
369bool HexagonQFPOptimizer::runOnMachineFunction(MachineFunction &MF) {
385 <<
" Optimize intermediate conversions ===\n");
387 MachineBasicBlock *
MBB = &*
MBBI;
390 MachineInstr *
MI = &*MII;
392 if (QFPInstMap.count(
MI->getOpcode())) {
393 auto OpC =
MI->getOpcode();
396 if (OpC != Hexagon::V6_vconv_sf_qf32 &&
397 OpC != Hexagon::V6_vconv_hf_qf16) {
399 if (optimizeQfp(
MI,
MBB)) {
400 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.
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
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)
void initializeHexagonQFPOptimizerPass(PassRegistry &)