127#define HEXAGON_XQFLOAT_GENERATOR "XQFloat Generator pass"
149#define DEBUG_TYPE "hexagon-xqf-gen"
157 cl::desc(
"Enable XQFloat generations"));
161 cl::desc(
"Enable extraneous conversions removal"));
165 cl::desc(
"Print function mir after transformation"));
169 Hexagon::V6_vadd_sf, Hexagon::V6_vadd_qf32, Hexagon::V6_vadd_qf32_mix,
172 Hexagon::V6_vsub_qf32, Hexagon::V6_vsub_qf32_mix, Hexagon::V6_vsub_sf,
173 Hexagon::V6_vsub_sf_mix};
178 Hexagon::V6_vadd_hf, Hexagon::V6_vadd_qf16, Hexagon::V6_vadd_qf16_mix,
181 Hexagon::V6_vsub_hf, Hexagon::V6_vsub_qf16, Hexagon::V6_vsub_qf16_mix,
182 Hexagon::V6_vsub_hf_mix};
186 Hexagon::V6_vmpy_qf32, Hexagon::V6_vmpy_qf32_qf16, Hexagon::V6_vmpy_qf32_hf,
187 Hexagon::V6_vmpy_qf32_sf, Hexagon::V6_vmpy_qf32_mix_hf};
189static constexpr unsigned XQFPMult16[] = {Hexagon::V6_vmpy_qf16,
190 Hexagon::V6_vmpy_qf16_hf,
191 Hexagon::V6_vmpy_qf16_mix_hf};
203 HexagonXQFloatGenerator() : MachineFunctionPass(ID) {}
209 void getAnalysisUsage(AnalysisUsage &AU)
const override {
233 bool normalizeMultiplicationInputF32(MachineInstr &,
Register &,
Register &,
243 void createPrologInstructions(MachineInstr &,
Register &);
249 bool convertIfInputToNonHVX(MachineInstr &,
bool);
256 const HexagonSubtarget *HST =
nullptr;
257 const HexagonInstrInfo *HII =
nullptr;
258 MachineRegisterInfo *MRI =
nullptr;
266 dbgs() <<
"\n=== Printing function ===\n";
277class VectorConvertRemove {
281 const HexagonSubtarget *_HST)
282 : MF(_MF), MRI(_MRI), HST(_HST) {
283 HII = HST->getInstrInfo();
290 MachineRegisterInfo *MRI;
291 const HexagonSubtarget *HST;
292 const HexagonInstrInfo *HII;
294 enum Operation { Add16, Add32, Sub16, Sub32, Mul16, Mul32 };
306 bool checkHVXUses32(MachineInstr *, MachineInstr *);
307 bool checkHVXUses16(MachineInstr *, MachineInstr *);
308 unsigned getOperation(Operation,
bool,
bool);
311 SmallPtrSet<MachineInstr *, 16> ConvInstrList;
313 std::vector<MachineInstr *> SfHfInstrList;
317unsigned VectorConvertRemove::getOperation(
Operation Op,
bool firstOpQf,
319 if (firstOpQf && secOpQf) {
322 return Hexagon::V6_vadd_qf16;
324 return Hexagon::V6_vadd_qf32;
326 return Hexagon::V6_vsub_qf16;
328 return Hexagon::V6_vsub_qf32;
330 return Hexagon::V6_vmpy_qf16;
332 return Hexagon::V6_vmpy_qf32_qf16;
334 }
else if (firstOpQf) {
337 return Hexagon::V6_vadd_qf16_mix;
339 return Hexagon::V6_vadd_qf32_mix;
341 return Hexagon::V6_vsub_qf16_mix;
343 return Hexagon::V6_vsub_qf32_mix;
345 return Hexagon::V6_vmpy_qf16_mix_hf;
347 return Hexagon::V6_vmpy_qf32_mix_hf;
349 }
else if (secOpQf) {
352 return Hexagon::V6_vsub_hf_mix;
354 return Hexagon::V6_vsub_sf_mix;
365bool VectorConvertRemove::checkHVXUses32(MachineInstr *
MI,
366 MachineInstr *
UseMI) {
367 Register convReg =
MI->getOperand(0).getReg();
373 MI->getOperand(1).setIsKill(
false);
381bool VectorConvertRemove::checkHVXUses16(MachineInstr *
MI,
382 MachineInstr *
UseMI) {
383 Register convReg =
MI->getOperand(0).getReg();
389 MI->getOperand(1).setIsKill(
false);
396void VectorConvertRemove::handle_addsub_sf_sf(MachineInstr &
MI,
Register &Reg1,
403 bool firstConv =
false, secConv =
false;
404 bool DefOp1_del =
false, DefOp2_del =
false;
410 if (DefOp1->
getOpcode() == Hexagon::V6_vconv_sf_qf32) {
411 if (checkHVXUses32(DefOp1, &
MI))
418 if (DefOp2->
getOpcode() == Hexagon::V6_vconv_sf_qf32) {
419 if (checkHVXUses32(DefOp2, &
MI))
425 if (firstConv && secConv) {
427 HII->get(getOperation(isAdd ? Operation::Add32 : Operation::Sub32,
432 SfHfInstrList.push_back(&
MI);
433 }
else if (firstConv) {
435 HII->get(getOperation(isAdd ? Operation::Add32 : Operation::Sub32,
440 SfHfInstrList.push_back(&
MI);
441 }
else if (secConv) {
452 SfHfInstrList.push_back(&
MI);
461 SfHfInstrList.push_back(&
MI);
468 ConvInstrList.
insert(DefOp1);
470 ConvInstrList.
insert(DefOp2);
474void VectorConvertRemove::handle_addsubmul_hf_hf(MachineInstr &
MI,
481 bool firstConv =
false, secConv =
false;
482 bool DefOp1_del =
false, DefOp2_del =
false;
483 bool isSub =
Op == Operation::Sub16;
489 if (DefOp1->
getOpcode() == Hexagon::V6_vconv_hf_qf16) {
490 if (checkHVXUses16(DefOp1, &
MI))
497 if (DefOp2->
getOpcode() == Hexagon::V6_vconv_hf_qf16) {
498 if (checkHVXUses16(DefOp2, &
MI))
504 if (firstConv && secConv) {
508 SfHfInstrList.push_back(&
MI);
509 }
else if (firstConv) {
513 SfHfInstrList.push_back(&
MI);
514 }
else if (secConv) {
526 SfHfInstrList.push_back(&
MI);
533 SfHfInstrList.push_back(&
MI);
540 ConvInstrList.
insert(DefOp1);
542 ConvInstrList.
insert(DefOp2);
546void VectorConvertRemove::handle_addsub_qf_sf(MachineInstr &
MI,
Register &Reg1,
556 if (DefOp->
getOpcode() == Hexagon::V6_vconv_sf_qf32) {
557 if (checkHVXUses32(DefOp, &
MI))
558 ConvInstrList.
insert(DefOp);
565 HII->get(isAdd ? Hexagon::V6_vadd_qf32 : Hexagon::V6_vsub_qf32),
569 SfHfInstrList.push_back(&
MI);
574void VectorConvertRemove::handle_addsubmul_qf_hf(MachineInstr &
MI,
584 if (DefOp->
getOpcode() == Hexagon::V6_vconv_hf_qf16) {
585 if (checkHVXUses16(DefOp, &
MI))
586 ConvInstrList.
insert(DefOp);
595 SfHfInstrList.push_back(&
MI);
600void VectorConvertRemove::handle_qf32_mul_sf_sf(MachineInstr &
MI,
606 bool firstConv =
false, secConv =
false;
611 if (DefOp1->
getOpcode() == Hexagon::V6_vconv_sf_qf32 &&
612 DefOp2->
getOpcode() == Hexagon::V6_vconv_sf_qf32) {
614 if (checkHVXUses32(DefOp1, &
MI) && checkHVXUses32(DefOp2, &
MI)) {
615 ConvInstrList.
insert(DefOp1);
616 ConvInstrList.
insert(DefOp2);
625 if (firstConv && secConv) {
629 SfHfInstrList.push_back(&
MI);
633void VectorConvertRemove::run() {
634 for (
auto &
MBB : MF) {
635 for (
auto &
MI :
MBB) {
639 if (
MI.getNumOperands() != 3 ||
MI.isDebugInstr())
642 auto Op1 =
MI.getOperand(1);
645 auto Op2 =
MI.getOperand(2);
648 auto Op0 =
MI.getOperand(0);
655 switch (
MI.getOpcode()) {
658 case Hexagon::V6_vadd_sf:
659 handle_addsub_sf_sf(
MI, Reg1, Reg2, Dest,
true);
662 case Hexagon::V6_vsub_sf:
663 handle_addsub_sf_sf(
MI, Reg1, Reg2, Dest,
false);
666 case Hexagon::V6_vadd_qf32_mix:
667 handle_addsub_qf_sf(
MI, Reg1, Reg2, Dest,
true);
670 case Hexagon::V6_vsub_qf32_mix:
671 handle_addsub_qf_sf(
MI, Reg1, Reg2, Dest,
false);
674 case Hexagon::V6_vadd_hf:
675 handle_addsubmul_hf_hf(
MI, Reg1, Reg2, Dest, Operation::Add16);
678 case Hexagon::V6_vsub_hf:
679 handle_addsubmul_hf_hf(
MI, Reg1, Reg2, Dest, Operation::Sub16);
682 case Hexagon::V6_vadd_qf16_mix:
683 handle_addsubmul_qf_hf(
MI, Reg1, Reg2, Dest, Operation::Add16);
686 case Hexagon::V6_vsub_qf16_mix:
687 handle_addsubmul_qf_hf(
MI, Reg1, Reg2, Dest, Operation::Sub16);
690 case Hexagon::V6_vmpy_qf32_sf:
691 handle_qf32_mul_sf_sf(
MI, Reg1, Reg2, Dest);
694 case Hexagon::V6_vmpy_qf32_hf:
695 handle_addsubmul_hf_hf(
MI, Reg1, Reg2, Dest, Operation::Mul32);
698 case Hexagon::V6_vmpy_qf32_mix_hf:
699 handle_addsubmul_qf_hf(
MI, Reg1, Reg2, Dest, Operation::Mul32);
702 case Hexagon::V6_vmpy_qf16_hf:
703 handle_addsubmul_hf_hf(
MI, Reg1, Reg2, Dest, Operation::Mul16);
706 case Hexagon::V6_vmpy_qf16_mix_hf:
707 handle_addsubmul_qf_hf(
MI, Reg1, Reg2, Dest, Operation::Mul16);
716 for (MachineInstr *sfhfMI : SfHfInstrList) {
719 sfhfMI->eraseFromParent();
722 for (MachineInstr *convMI : ConvInstrList) {
725 convMI->eraseFromParent();
729char HexagonXQFloatGenerator::ID = 0;
737 return new HexagonXQFloatGenerator();
741bool HexagonXQFloatGenerator::checkIfInputFromAdder32(
Register Reg) {
747 if (
Def->getOpcode() == TargetOpcode::COPY) {
750 return checkIfInputFromAdder32(SrcReg);
752 }
else if (
Def->getOpcode() == TargetOpcode::REG_SEQUENCE) {
757 isTrue = checkIfInputFromAdder32(SrcReg1);
759 isTrue |= checkIfInputFromAdder32(SrcReg2);
766bool HexagonXQFloatGenerator::checkIfInputFromAdder16(
Register Reg) {
772 if (
Def->getOpcode() == TargetOpcode::COPY) {
775 return checkIfInputFromAdder16(SrcReg);
782bool HexagonXQFloatGenerator::checkIfInputFromMult32(
Register Reg) {
788 if (
Def->getOpcode() == TargetOpcode::COPY) {
791 return checkIfInputFromMult32(SrcReg);
793 }
else if (
Def->getOpcode() == TargetOpcode::REG_SEQUENCE) {
798 isTrue |= checkIfInputFromMult32(SrcReg1);
800 isTrue |= checkIfInputFromMult32(SrcReg2);
807bool HexagonXQFloatGenerator::checkIfInputFromMult16(
Register Reg) {
813 if (
Def->getOpcode() == TargetOpcode::COPY) {
816 return checkIfInputFromMult16(SrcReg);
823void HexagonXQFloatGenerator::createConvertInstr(MachineInstr *
UseMI,
838bool HexagonXQFloatGenerator::convertIfInputToNonHVX(MachineInstr &
MI,
847 MachineInstr *
UseMI = MO.getParent();
863 return convertIfInputToNonHVX(*
UseMI,
true);
865 createConvertInstr(
UseMI, NewR, Dest,
true);
873 return convertIfInputToNonHVX(*
UseMI,
false);
875 createConvertInstr(
UseMI, NewR, Dest,
false);
888void HexagonXQFloatGenerator::generateQF16FromQF32(MachineInstr &
MI,
896 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vconv_hf_qf32), convertReg)
907void HexagonXQFloatGenerator::widenMultiplyInputHF(MachineInstr &
MI,
915 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vmpy_qf32_hf), output_mpy)
918 generateQF16FromQF32(
MI, Dest, output_mpy);
922bool HexagonXQFloatGenerator::widenMultiplicationInputF16(MachineInstr &
MI,
927 bool firstconvert =
false, secondconvert =
false;
932 if (checkIfInputFromAdder16(Reg1))
935 if (twoOps && checkIfInputFromAdder16(Reg2))
936 secondconvert =
true;
941 if (firstconvert || secondconvert) {
943 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vmpy_qf32_qf16), widenReg)
952 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vmpy_qf32_mix_hf), widenReg)
961 generateQF16FromQF32(
MI, Dest, widenReg);
968bool HexagonXQFloatGenerator::widenMultiplicationInputF16Rt(MachineInstr &
MI,
974 if (!checkIfInputFromAdder16(Reg1)) {
976 if (!checkIfInputFromMult16(Reg1))
992 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vmpy_qf32_hf), widenReg)
996 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vmpy_qf32_mix_hf), widenReg)
1002 generateQF16FromQF32(
MI, Dest, widenReg);
1011bool HexagonXQFloatGenerator::convertAddOpToIEEE32(
1013 bool isAdd,
bool isFirstOpQf,
bool isSecOpQf) {
1017 bool firstconvert =
false, secondconvert =
false;
1025 if (checkIfInputFromAdder32(Reg1) || checkIfInputFromMult32(Reg1)) {
1029 firstconvert =
true;
1037 if (checkIfInputFromAdder32(Reg2) || checkIfInputFromMult32(Reg2)) {
1041 secondconvert =
true;
1048 if (isFirstOpQf && isSecOpQf) {
1049 if (firstconvert && secondconvert) {
1051 HII->get(isAdd ? Hexagon::V6_vadd_sf : Hexagon::V6_vsub_sf), Dest)
1054 }
else if (firstconvert) {
1075 }
else if (secondconvert) {
1077 HII->get(isAdd ? Hexagon::V6_vadd_qf32_mix
1078 : Hexagon::V6_vsub_qf32_mix),
1086 }
else if (isFirstOpQf) {
1089 HII->get(isAdd ? Hexagon::V6_vadd_sf : Hexagon::V6_vsub_sf), Dest)
1095 }
else if (isSecOpQf) {
1098 HII->get(isAdd ? Hexagon::V6_vadd_sf : Hexagon::V6_vsub_sf), Dest)
1113bool HexagonXQFloatGenerator::convertAddOpToIEEE16(
1115 bool isAdd,
bool isFirstOpQf,
bool isSecOpQf) {
1121 bool firstconvert =
false, secondconvert =
false;
1126 if (checkIfInputFromAdder16(Reg1) || checkIfInputFromMult16(Reg1)) {
1130 firstconvert =
true;
1136 if (checkIfInputFromAdder16(Reg2) || checkIfInputFromMult16(Reg2)) {
1140 secondconvert =
true;
1147 if (isFirstOpQf && isSecOpQf) {
1148 if (firstconvert && secondconvert) {
1150 HII->get(isAdd ? Hexagon::V6_vadd_hf : Hexagon::V6_vsub_hf), Dest)
1153 }
else if (firstconvert) {
1174 }
else if (secondconvert) {
1176 HII->get(isAdd ? Hexagon::V6_vadd_qf16_mix
1177 : Hexagon::V6_vsub_qf16_mix),
1185 }
else if (isFirstOpQf) {
1188 HII->get(isAdd ? Hexagon::V6_vadd_hf : Hexagon::V6_vsub_hf), Dest)
1194 }
else if (isSecOpQf) {
1197 HII->get(isAdd ? Hexagon::V6_vadd_hf : Hexagon::V6_vsub_hf), Dest)
1212void HexagonXQFloatGenerator::createPrologInstructions(MachineInstr &
MI,
1233bool HexagonXQFloatGenerator::V81normalizeMultF32(
1235 bool firstconvert,
bool secondconvert,
bool strictieee) {
1241 strictieee ? Hexagon::V6_vconv_qf32_sf : Hexagon::V6_vconv_qf32_qf32;
1244 if (firstconvert && secondconvert) {
1255 else if (firstconvert) {
1263 else if (secondconvert) {
1277void HexagonXQFloatGenerator::normalizeMultiplicationInputSF(
1279 Register &R_mpy,
bool &PrologCreated) {
1289 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vconv_qf32_sf), input_mpy1)
1291 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vconv_qf32_sf), input_mpy2)
1300 if (!PrologCreated) {
1301 createPrologInstructions(
MI, R_mpy);
1302 PrologCreated =
true;
1308 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vadd_qf32_mix), input_mpy1)
1311 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vadd_qf32_mix), input_mpy2)
1321bool HexagonXQFloatGenerator::convertNormalizeMultOp32(
1323 Register &R_mpy,
bool &PrologCreated) {
1326 bool firstconvert =
false, secondconvert =
false;
1332 if (checkIfInputFromAdder32(Reg1) || checkIfInputFromMult32(Reg1)) {
1335 firstconvert =
true;
1338 if (checkIfInputFromAdder32(Reg2) || checkIfInputFromMult32(Reg2)) {
1341 secondconvert =
true;
1345 if (firstconvert && secondconvert)
1346 return V81normalizeMultF32(
MI, VR1, VR2, Dest,
true,
true,
true);
1347 else if (firstconvert)
1348 return V81normalizeMultF32(
MI, VR1, Reg2, Dest,
true,
false,
true);
1349 else if (secondconvert)
1350 return V81normalizeMultF32(
MI, Reg1, VR2, Dest,
false,
true,
true);
1356 if (!PrologCreated && (firstconvert || secondconvert)) {
1357 createPrologInstructions(
MI, R_mpy);
1358 PrologCreated =
true;
1364 if (firstconvert && secondconvert) {
1368 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vadd_qf32_mix), input_mpy1)
1371 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vadd_qf32_mix), input_mpy2)
1378 }
else if (firstconvert) {
1381 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vadd_qf32_mix), input_mpy1)
1388 }
else if (secondconvert) {
1391 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vadd_qf32_mix), input_mpy2)
1407bool HexagonXQFloatGenerator::convertWidenMultOp16(MachineInstr &
MI,
1414 bool firstconvert =
false,
1415 secondconvert =
false;
1421 if (checkIfInputFromAdder16(Reg1) || checkIfInputFromMult16(Reg1)) {
1424 firstconvert =
true;
1428 if (checkIfInputFromAdder16(Reg2) || checkIfInputFromMult16(Reg2)) {
1432 secondconvert =
true;
1438 if (firstconvert && secondconvert) {
1440 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vmpy_qf32_hf), output_mpy)
1444 }
else if (firstconvert) {
1446 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vmpy_qf32_mix_hf), output_mpy)
1449 }
else if (secondconvert) {
1451 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vmpy_qf32_mix_hf), output_mpy)
1461 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vmpy_qf32_hf), output_mpy)
1469 generateQF16FromQF32(
MI, Dest, output_mpy);
1476bool HexagonXQFloatGenerator::convertWidenMultOp32(MachineInstr &
MI,
1482 bool firstconvert =
false,
1483 secondconvert =
false;
1489 if (checkIfInputFromAdder16(Reg1) || checkIfInputFromMult16(Reg1)) {
1492 firstconvert =
true;
1496 if (checkIfInputFromAdder16(Reg2) || checkIfInputFromMult16(Reg2)) {
1500 secondconvert =
true;
1506 if (firstconvert && secondconvert) {
1511 }
else if (firstconvert) {
1512 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vmpy_qf32_mix_hf), Dest)
1515 }
else if (secondconvert) {
1516 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vmpy_qf32_mix_hf), Dest)
1535bool HexagonXQFloatGenerator::normalizeMultiplicationInputF32(
1537 Register &R_mpy,
bool &PrologCreated) {
1538 bool firstconvert =
false, secondconvert =
false;
1543 if (checkIfInputFromAdder32(Reg1))
1544 firstconvert =
true;
1545 if (checkIfInputFromAdder32(Reg2))
1546 secondconvert =
true;
1550 return V81normalizeMultF32(
MI, Reg1, Reg2, Dest, firstconvert,
1551 secondconvert,
false);
1554 if ((!PrologCreated && (firstconvert || secondconvert))) {
1555 createPrologInstructions(
MI, R_mpy);
1556 PrologCreated =
true;
1562 if (firstconvert && secondconvert) {
1566 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vadd_qf32), input_mpy1)
1569 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vadd_qf32), input_mpy2)
1576 }
else if (firstconvert) {
1579 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vadd_qf32), input_mpy1)
1586 }
else if (secondconvert) {
1589 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vadd_qf32), input_mpy2)
1603bool HexagonXQFloatGenerator::deleteList() {
1604 if (OriginalMI.empty())
1607 for (MachineInstr *origMI : OriginalMI) {
1610 origMI->eraseFromParent();
1618bool HexagonXQFloatGenerator::HandleLossySubnormals(
MachineFunction &MF) {
1621 for (
auto &
MBB : MF) {
1622 bool PrologCreated =
false;
1623 for (
auto &
MI :
MBB) {
1628 if (
MI.getNumOperands() != 3 ||
MI.isDebugInstr())
1630 auto Op1 =
MI.getOperand(1);
1633 auto Op2 =
MI.getOperand(2);
1636 auto Op0 =
MI.getOperand(0);
1647 switch (
MI.getOpcode()) {
1651 case Hexagon::V6_vmpy_qf32:
1652 if (normalizeMultiplicationInputF32(
MI, Reg1, Reg2, Dest, R_mpy,
1654 OriginalMI.push_back(&
MI);
1655 Changed |= convertIfInputToNonHVX(
MI,
true);
1661 case Hexagon::V6_vmpy_qf16:
1662 if (widenMultiplicationInputF16(
MI, Reg1, Reg2, Dest,
true))
1663 OriginalMI.push_back(&
MI);
1664 Changed |= convertIfInputToNonHVX(
MI,
false);
1671 case Hexagon::V6_vmpy_rt_qf16:
1672 if (widenMultiplicationInputF16Rt(
MI, Reg1, Reg2, Dest))
1673 OriginalMI.push_back(&
MI);
1674 Changed |= convertIfInputToNonHVX(
MI,
false);
1680 case Hexagon::V6_vmpy_qf16_mix_hf:
1681 if (widenMultiplicationInputF16(
MI, Reg1, Reg2, Dest,
false))
1682 OriginalMI.push_back(&
MI);
1683 Changed |= convertIfInputToNonHVX(
MI,
false);
1688 case Hexagon::V6_vadd_sf:
1689 case Hexagon::V6_vadd_qf32:
1690 case Hexagon::V6_vadd_qf32_mix:
1691 case Hexagon::V6_vsub_sf:
1692 case Hexagon::V6_vsub_qf32:
1693 case Hexagon::V6_vsub_qf32_mix:
1694 case Hexagon::V6_vsub_sf_mix:
1695 case Hexagon::V6_vmpy_qf32_qf16:
1696 case Hexagon::V6_vmpy_qf32_hf:
1697 case Hexagon::V6_vmpy_qf32_mix_hf:
1698 case Hexagon::V6_vmpy_rt_sf:
1699 case Hexagon::V6_vmpy_qf32_sf:
1700 Changed |= convertIfInputToNonHVX(
MI,
true);
1705 case Hexagon::V6_vadd_hf:
1706 case Hexagon::V6_vsub_hf:
1707 case Hexagon::V6_vadd_qf16:
1708 case Hexagon::V6_vsub_qf16:
1709 case Hexagon::V6_vadd_qf16_mix:
1710 case Hexagon::V6_vsub_qf16_mix:
1711 case Hexagon::V6_vsub_hf_mix:
1712 case Hexagon::V6_vmpy_qf16_hf:
1713 case Hexagon::V6_vmpy_rt_hf:
1714 Changed |= convertIfInputToNonHVX(
MI,
false);
1721 if (OriginalMI.empty() || !
Changed)
1727bool HexagonXQFloatGenerator::HandleCompliantIEEE(
MachineFunction &MF) {
1730 for (
auto &
MBB : MF) {
1731 bool PrologCreated =
false;
1732 for (
auto &
MI :
MBB) {
1737 if (
MI.getNumOperands() != 3 ||
MI.isDebugInstr())
1740 auto Op1 =
MI.getOperand(1);
1743 auto Op2 =
MI.getOperand(2);
1746 auto Op0 =
MI.getOperand(0);
1758 switch (
MI.getOpcode()) {
1765 case Hexagon::V6_vmpy_rt_sf:
1767 BuildMI(
MBB,
MI,
MI.getDebugLoc(), HII->get(Hexagon::V6_lvsplatw),
1770 normalizeMultiplicationInputSF(
MI, Reg1, VRtSplat, Dest, R_mpy,
1772 OriginalMI.push_back(&
MI);
1773 Changed |= convertIfInputToNonHVX(
MI,
true);
1778 case Hexagon::V6_vmpy_qf32_sf:
1779 normalizeMultiplicationInputSF(
MI, Reg1, Reg2, Dest, R_mpy,
1781 OriginalMI.push_back(&
MI);
1782 Changed |= convertIfInputToNonHVX(
MI,
true);
1788 case Hexagon::V6_vmpy_qf32:
1789 if (normalizeMultiplicationInputF32(
MI, Reg1, Reg2, Dest, R_mpy,
1791 OriginalMI.push_back(&
MI);
1792 Changed |= convertIfInputToNonHVX(
MI,
true);
1797 case Hexagon::V6_vmpy_rt_hf:
1799 BuildMI(
MBB,
MI,
MI.getDebugLoc(), HII->get(Hexagon::V6_lvsplatw),
1802 widenMultiplyInputHF(
MI, Reg1, VRtSplat, Dest);
1803 OriginalMI.push_back(&
MI);
1804 Changed |= convertIfInputToNonHVX(
MI,
false);
1809 case Hexagon::V6_vmpy_qf16_hf:
1810 widenMultiplyInputHF(
MI, Reg1, Reg2, Dest);
1811 OriginalMI.push_back(&
MI);
1812 Changed |= convertIfInputToNonHVX(
MI,
false);
1818 case Hexagon::V6_vmpy_qf16:
1819 if (widenMultiplicationInputF16(
MI, Reg1, Reg2, Dest,
true))
1820 OriginalMI.push_back(&
MI);
1821 Changed |= convertIfInputToNonHVX(
MI,
false);
1828 case Hexagon::V6_vmpy_rt_qf16:
1829 if (widenMultiplicationInputF16Rt(
MI, Reg1, Reg2, Dest))
1830 OriginalMI.push_back(&
MI);
1831 Changed |= convertIfInputToNonHVX(
MI,
false);
1837 case Hexagon::V6_vmpy_qf16_mix_hf:
1838 if (widenMultiplicationInputF16(
MI, Reg1, Reg2, Dest,
false))
1839 OriginalMI.push_back(&
MI);
1840 Changed |= convertIfInputToNonHVX(
MI,
false);
1846 case Hexagon::V6_vadd_sf:
1847 case Hexagon::V6_vadd_qf32:
1848 case Hexagon::V6_vadd_qf32_mix:
1849 case Hexagon::V6_vsub_sf:
1850 case Hexagon::V6_vsub_qf32:
1851 case Hexagon::V6_vsub_qf32_mix:
1852 case Hexagon::V6_vsub_sf_mix:
1853 case Hexagon::V6_vmpy_qf32_qf16:
1854 case Hexagon::V6_vmpy_qf32_hf:
1855 case Hexagon::V6_vmpy_qf32_mix_hf:
1856 Changed |= convertIfInputToNonHVX(
MI,
true);
1858 case Hexagon::V6_vadd_hf:
1859 case Hexagon::V6_vsub_hf:
1860 case Hexagon::V6_vadd_qf16:
1861 case Hexagon::V6_vsub_qf16:
1862 case Hexagon::V6_vadd_qf16_mix:
1863 case Hexagon::V6_vsub_qf16_mix:
1864 case Hexagon::V6_vsub_hf_mix:
1865 Changed |= convertIfInputToNonHVX(
MI,
false);
1872 if (OriginalMI.empty() || !
Changed)
1882 for (
auto &
MBB : MF) {
1883 bool PrologCreated =
false;
1884 for (
auto &
MI :
MBB) {
1889 if (
MI.getNumOperands() != 3 ||
MI.isDebugInstr())
1892 auto Op1 =
MI.getOperand(1);
1895 auto Op2 =
MI.getOperand(2);
1898 auto Op0 =
MI.getOperand(0);
1910 switch (
MI.getOpcode()) {
1915 case Hexagon::V6_vadd_qf32:
1916 if (convertAddOpToIEEE32(
MI, Reg1, Reg2, Dest,
true,
true,
true))
1917 OriginalMI.push_back(&
MI);
1918 Changed |= convertIfInputToNonHVX(
MI,
true);
1921 case Hexagon::V6_vsub_qf32:
1922 if (convertAddOpToIEEE32(
MI, Reg1, Reg2, Dest,
false,
true,
true))
1923 OriginalMI.push_back(&
MI);
1924 Changed |= convertIfInputToNonHVX(
MI,
true);
1929 case Hexagon::V6_vadd_qf32_mix:
1930 if (convertAddOpToIEEE32(
MI, Reg1, Reg2, Dest,
true,
true,
false))
1931 OriginalMI.push_back(&
MI);
1932 Changed |= convertIfInputToNonHVX(
MI,
true);
1935 case Hexagon::V6_vsub_qf32_mix:
1936 if (convertAddOpToIEEE32(
MI, Reg1, Reg2, Dest,
false,
true,
false))
1937 OriginalMI.push_back(&
MI);
1938 Changed |= convertIfInputToNonHVX(
MI,
true);
1941 case Hexagon::V6_vsub_sf_mix:
1942 if (convertAddOpToIEEE32(
MI, Reg1, Reg2, Dest,
false,
false,
true))
1943 OriginalMI.push_back(&
MI);
1944 Changed |= convertIfInputToNonHVX(
MI,
true);
1951 case Hexagon::V6_vadd_qf16:
1952 if (convertAddOpToIEEE16(
MI, Reg1, Reg2, Dest,
true,
true,
true))
1953 OriginalMI.push_back(&
MI);
1954 Changed |= convertIfInputToNonHVX(
MI,
false);
1957 case Hexagon::V6_vsub_qf16:
1958 if (convertAddOpToIEEE16(
MI, Reg1, Reg2, Dest,
false,
true,
true))
1959 OriginalMI.push_back(&
MI);
1960 Changed |= convertIfInputToNonHVX(
MI,
false);
1965 case Hexagon::V6_vadd_qf16_mix:
1966 if (convertAddOpToIEEE16(
MI, Reg1, Reg2, Dest,
true,
true,
false))
1967 OriginalMI.push_back(&
MI);
1968 Changed |= convertIfInputToNonHVX(
MI,
false);
1971 case Hexagon::V6_vsub_qf16_mix:
1972 if (convertAddOpToIEEE16(
MI, Reg1, Reg2, Dest,
false,
true,
false))
1973 OriginalMI.push_back(&
MI);
1974 Changed |= convertIfInputToNonHVX(
MI,
false);
1977 case Hexagon::V6_vsub_hf_mix:
1978 if (convertAddOpToIEEE16(
MI, Reg1, Reg2, Dest,
false,
false,
true))
1979 OriginalMI.push_back(&
MI);
1980 Changed |= convertIfInputToNonHVX(
MI,
false);
1988 case Hexagon::V6_vmpy_rt_sf:
1990 BuildMI(
MBB,
MI,
MI.getDebugLoc(), HII->get(Hexagon::V6_lvsplatw),
1993 normalizeMultiplicationInputSF(
MI, Reg1, VRtSplat, Dest, R_mpy,
1995 OriginalMI.push_back(&
MI);
1996 Changed |= convertIfInputToNonHVX(
MI,
true);
2001 case Hexagon::V6_vmpy_qf32_sf:
2002 normalizeMultiplicationInputSF(
MI, Reg1, Reg2, Dest, R_mpy,
2004 Changed |= convertIfInputToNonHVX(
MI,
true);
2005 OriginalMI.push_back(&
MI);
2011 case Hexagon::V6_vmpy_qf32:
2012 if (convertNormalizeMultOp32(
MI, Reg1, Reg2, Dest, R_mpy,
2014 OriginalMI.push_back(&
MI);
2015 Changed |= convertIfInputToNonHVX(
MI,
true);
2023 case Hexagon::V6_vmpy_qf16:
2024 if (convertWidenMultOp16(
MI, Reg1, Reg2, Dest,
true))
2025 OriginalMI.push_back(&
MI);
2026 Changed |= convertIfInputToNonHVX(
MI,
false);
2033 case Hexagon::V6_vmpy_qf32_qf16:
2034 if (convertWidenMultOp32(
MI, Reg1, Reg2, Dest,
true))
2035 OriginalMI.push_back(&
MI);
2036 Changed |= convertIfInputToNonHVX(
MI,
true);
2041 case Hexagon::V6_vmpy_rt_hf:
2043 BuildMI(
MBB,
MI,
MI.getDebugLoc(), HII->get(Hexagon::V6_lvsplatw),
2046 widenMultiplyInputHF(
MI, Reg1, VRtSplat, Dest);
2047 OriginalMI.push_back(&
MI);
2048 Changed |= convertIfInputToNonHVX(
MI,
false);
2053 case Hexagon::V6_vmpy_qf16_hf:
2054 widenMultiplyInputHF(
MI, Reg1, Reg2, Dest);
2055 OriginalMI.push_back(&
MI);
2056 Changed |= convertIfInputToNonHVX(
MI,
false);
2063 case Hexagon::V6_vmpy_rt_qf16:
2064 if (widenMultiplicationInputF16Rt(
MI, Reg1, Reg2, Dest))
2065 OriginalMI.push_back(&
MI);
2066 Changed |= convertIfInputToNonHVX(
MI,
false);
2074 case Hexagon::V6_vmpy_qf16_mix_hf:
2075 if (convertWidenMultOp16(
MI, Reg1, Reg2, Dest,
false))
2076 OriginalMI.push_back(&
MI);
2077 Changed |= convertIfInputToNonHVX(
MI,
false);
2084 case Hexagon::V6_vmpy_qf32_mix_hf:
2085 if (convertWidenMultOp32(
MI, Reg1, Reg2, Dest,
false))
2086 OriginalMI.push_back(&
MI);
2087 Changed |= convertIfInputToNonHVX(
MI,
true);
2092 case Hexagon::V6_vadd_sf:
2093 case Hexagon::V6_vsub_sf:
2094 Changed |= convertIfInputToNonHVX(
MI,
true);
2096 case Hexagon::V6_vadd_hf:
2097 case Hexagon::V6_vsub_hf:
2098 Changed |= convertIfInputToNonHVX(
MI,
false);
2105 if (OriginalMI.empty() || !
Changed)
2115bool HexagonXQFloatGenerator::runOnMachineFunction(
MachineFunction &MF) {
2126 VectorConvertRemove VCR(MF, MRI, HST);
2128 LLVM_DEBUG(
dbgs() <<
"\nExtraneous conversion instructions removed for "
2135 case QFloatMode::StrictIEEE:
2136 LLVM_DEBUG(
dbgs() <<
"\nGenerating code for STRICT-IEEE mode.\n");
2137 Changed = HandleStrictIEEE(MF);
2139 case QFloatMode::IEEE:
2141 Changed = HandleCompliantIEEE(MF);
2143 case QFloatMode::Lossy:
2145 Changed = HandleLossySubnormals(MF);
2147 case QFloatMode::Legacy:
2149 Changed = HandleLossyLegacy(MF);
2155 for (MachineInstr *origMI : OriginalMI) {
2157 origMI->eraseFromParent();
MachineInstrBuilder & UseMI
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
cl::opt< QFloatMode > QFloatModeValue
static constexpr unsigned XQFPMult32[]
cl::opt< bool > EnableHVXXQFloat("enable-xqf-gen", cl::init(false), cl::desc("Enable XQFloat generations"))
cl::opt< bool > EnableConversionsRemoval("enable-rem-conv", cl::init(false), cl::desc("Enable extraneous conversions removal"))
cl::opt< bool > PrintDebug("debug-print", cl::init(false), cl::desc("Print function mir after transformation"))
static constexpr unsigned XQFPAdd16[]
static constexpr unsigned XQFPAdd32[]
#define HEXAGON_XQFLOAT_GENERATOR
static constexpr unsigned XQFPMult16[]
Promote Memory to Register
PowerPC Reduce CR logical Operation
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
FunctionPass class - This class is used to implement most global optimizations.
bool usesQFOperand(MachineInstr *MI, unsigned Index=0) const
const HexagonInstrInfo * getInstrInfo() const override
bool useHVXV79Ops() const
bool useHVXV81Ops() const
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
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.
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
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
const MachineOperand & getOperand(unsigned i) const
Register getReg() const
getReg - Returns the register number.
LLVM_ABI LLVM_READONLY 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...
iterator_range< use_instr_iterator > use_instructions(Register Reg) const
use_iterator use_begin(Register RegNo) const
static use_iterator use_end()
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
constexpr bool isValid() const
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
initializer< Ty > init(const Ty &Val)
DXILDebugInfoMap run(Module &M)
NodeAddr< DefNode * > Def
This is an optimization pass for GlobalISel generic memory operations.
FunctionPass * createHexagonXQFloatGenerator()
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
void initializeHexagonXQFloatGeneratorPass(PassRegistry &)
DWARFExpression::Operation Op
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.