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) {}
205 bool runOnMachineFunction(MachineFunction &MF)
override;
209 void getAnalysisUsage(AnalysisUsage &AU)
const override {
215 bool HandleStrictIEEE(MachineFunction &);
216 bool HandleCompliantIEEE(MachineFunction &);
217 bool HandleLossySubnormals(MachineFunction &);
218 bool HandleLossyLegacy(MachineFunction &);
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 {
280 VectorConvertRemove(MachineFunction &_MF, MachineRegisterInfo *_MRI,
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();
370 MachineInstr *UMI = MO.getParent();
374 MI->getOperand(1).setIsKill(
false);
382bool VectorConvertRemove::checkHVXUses16(MachineInstr *
MI,
383 MachineInstr *
UseMI) {
384 Register convReg =
MI->getOperand(0).getReg();
391 MI->getOperand(1).setIsKill(
false);
398void VectorConvertRemove::handle_addsub_sf_sf(MachineInstr &
MI,
Register &Reg1,
402 MachineBasicBlock &
MBB = *
MI.getParent();
405 bool firstConv =
false, secConv =
false;
406 bool DefOp1_del =
false, DefOp2_del =
false;
412 if (DefOp1->
getOpcode() == Hexagon::V6_vconv_sf_qf32) {
413 if (checkHVXUses32(DefOp1, &
MI))
420 if (DefOp2->
getOpcode() == Hexagon::V6_vconv_sf_qf32) {
421 if (checkHVXUses32(DefOp2, &
MI))
427 if (firstConv && secConv) {
429 HII->get(getOperation(isAdd ? Operation::Add32 : Operation::Sub32,
434 SfHfInstrList.push_back(&
MI);
435 }
else if (firstConv) {
437 HII->get(getOperation(isAdd ? Operation::Add32 : Operation::Sub32,
442 SfHfInstrList.push_back(&
MI);
443 }
else if (secConv) {
454 SfHfInstrList.push_back(&
MI);
463 SfHfInstrList.push_back(&
MI);
470 ConvInstrList.
insert(DefOp1);
472 ConvInstrList.
insert(DefOp2);
476void VectorConvertRemove::handle_addsubmul_hf_hf(MachineInstr &
MI,
480 MachineBasicBlock &
MBB = *
MI.getParent();
483 bool firstConv =
false, secConv =
false;
484 bool DefOp1_del =
false, DefOp2_del =
false;
485 bool isSub =
Op == Operation::Sub16;
491 if (DefOp1->
getOpcode() == Hexagon::V6_vconv_hf_qf16) {
492 if (checkHVXUses16(DefOp1, &
MI))
499 if (DefOp2->
getOpcode() == Hexagon::V6_vconv_hf_qf16) {
500 if (checkHVXUses16(DefOp2, &
MI))
506 if (firstConv && secConv) {
510 SfHfInstrList.push_back(&
MI);
511 }
else if (firstConv) {
515 SfHfInstrList.push_back(&
MI);
516 }
else if (secConv) {
528 SfHfInstrList.push_back(&
MI);
535 SfHfInstrList.push_back(&
MI);
542 ConvInstrList.
insert(DefOp1);
544 ConvInstrList.
insert(DefOp2);
548void VectorConvertRemove::handle_addsub_qf_sf(MachineInstr &
MI,
Register &Reg1,
551 MachineBasicBlock &
MBB = *
MI.getParent();
558 if (DefOp->
getOpcode() == Hexagon::V6_vconv_sf_qf32) {
559 if (checkHVXUses32(DefOp, &
MI))
560 ConvInstrList.
insert(DefOp);
567 HII->get(isAdd ? Hexagon::V6_vadd_qf32 : Hexagon::V6_vsub_qf32),
571 SfHfInstrList.push_back(&
MI);
576void VectorConvertRemove::handle_addsubmul_qf_hf(MachineInstr &
MI,
579 MachineBasicBlock &
MBB = *
MI.getParent();
586 if (DefOp->
getOpcode() == Hexagon::V6_vconv_hf_qf16) {
587 if (checkHVXUses16(DefOp, &
MI))
588 ConvInstrList.
insert(DefOp);
597 SfHfInstrList.push_back(&
MI);
602void VectorConvertRemove::handle_qf32_mul_sf_sf(MachineInstr &
MI,
605 MachineBasicBlock &
MBB = *
MI.getParent();
608 bool firstConv =
false, secConv =
false;
613 if (DefOp1->
getOpcode() == Hexagon::V6_vconv_sf_qf32 &&
614 DefOp2->
getOpcode() == Hexagon::V6_vconv_sf_qf32) {
616 if (checkHVXUses32(DefOp1, &
MI) && checkHVXUses32(DefOp2, &
MI)) {
617 ConvInstrList.
insert(DefOp1);
618 ConvInstrList.
insert(DefOp2);
627 if (firstConv && secConv) {
631 SfHfInstrList.push_back(&
MI);
635void VectorConvertRemove::run() {
636 for (
auto &
MBB : MF) {
637 for (
auto &
MI :
MBB) {
641 if (
MI.getNumOperands() != 3 ||
MI.isDebugInstr())
644 auto Op1 =
MI.getOperand(1);
647 auto Op2 =
MI.getOperand(2);
650 auto Op0 =
MI.getOperand(0);
657 switch (
MI.getOpcode()) {
660 case Hexagon::V6_vadd_sf:
661 handle_addsub_sf_sf(
MI, Reg1, Reg2, Dest,
true);
664 case Hexagon::V6_vsub_sf:
665 handle_addsub_sf_sf(
MI, Reg1, Reg2, Dest,
false);
668 case Hexagon::V6_vadd_qf32_mix:
669 handle_addsub_qf_sf(
MI, Reg1, Reg2, Dest,
true);
672 case Hexagon::V6_vsub_qf32_mix:
673 handle_addsub_qf_sf(
MI, Reg1, Reg2, Dest,
false);
676 case Hexagon::V6_vadd_hf:
677 handle_addsubmul_hf_hf(
MI, Reg1, Reg2, Dest, Operation::Add16);
680 case Hexagon::V6_vsub_hf:
681 handle_addsubmul_hf_hf(
MI, Reg1, Reg2, Dest, Operation::Sub16);
684 case Hexagon::V6_vadd_qf16_mix:
685 handle_addsubmul_qf_hf(
MI, Reg1, Reg2, Dest, Operation::Add16);
688 case Hexagon::V6_vsub_qf16_mix:
689 handle_addsubmul_qf_hf(
MI, Reg1, Reg2, Dest, Operation::Sub16);
692 case Hexagon::V6_vmpy_qf32_sf:
693 handle_qf32_mul_sf_sf(
MI, Reg1, Reg2, Dest);
696 case Hexagon::V6_vmpy_qf32_hf:
697 handle_addsubmul_hf_hf(
MI, Reg1, Reg2, Dest, Operation::Mul32);
700 case Hexagon::V6_vmpy_qf32_mix_hf:
701 handle_addsubmul_qf_hf(
MI, Reg1, Reg2, Dest, Operation::Mul32);
704 case Hexagon::V6_vmpy_qf16_hf:
705 handle_addsubmul_hf_hf(
MI, Reg1, Reg2, Dest, Operation::Mul16);
708 case Hexagon::V6_vmpy_qf16_mix_hf:
709 handle_addsubmul_qf_hf(
MI, Reg1, Reg2, Dest, Operation::Mul16);
718 for (MachineInstr *sfhfMI : SfHfInstrList) {
721 sfhfMI->eraseFromParent();
724 for (MachineInstr *convMI : ConvInstrList) {
727 convMI->eraseFromParent();
731char HexagonXQFloatGenerator::ID = 0;
739 return new HexagonXQFloatGenerator();
743bool HexagonXQFloatGenerator::checkIfInputFromAdder32(
Register Reg) {
749 if (
Def->getOpcode() == TargetOpcode::COPY) {
752 return checkIfInputFromAdder32(SrcReg);
754 }
else if (
Def->getOpcode() == TargetOpcode::REG_SEQUENCE) {
759 isTrue = checkIfInputFromAdder32(SrcReg1);
761 isTrue |= checkIfInputFromAdder32(SrcReg2);
768bool HexagonXQFloatGenerator::checkIfInputFromAdder16(
Register Reg) {
774 if (
Def->getOpcode() == TargetOpcode::COPY) {
777 return checkIfInputFromAdder16(SrcReg);
784bool HexagonXQFloatGenerator::checkIfInputFromMult32(
Register Reg) {
790 if (
Def->getOpcode() == TargetOpcode::COPY) {
793 return checkIfInputFromMult32(SrcReg);
795 }
else if (
Def->getOpcode() == TargetOpcode::REG_SEQUENCE) {
800 isTrue |= checkIfInputFromMult32(SrcReg1);
802 isTrue |= checkIfInputFromMult32(SrcReg2);
809bool HexagonXQFloatGenerator::checkIfInputFromMult16(
Register Reg) {
815 if (
Def->getOpcode() == TargetOpcode::COPY) {
818 return checkIfInputFromMult16(SrcReg);
825void HexagonXQFloatGenerator::createConvertInstr(MachineInstr *
UseMI,
840bool HexagonXQFloatGenerator::convertIfInputToNonHVX(MachineInstr &
MI,
849 MachineInstr *
UseMI = MO.getParent();
865 return convertIfInputToNonHVX(*
UseMI,
true);
867 createConvertInstr(
UseMI, NewR, Dest,
true);
875 return convertIfInputToNonHVX(*
UseMI,
false);
877 createConvertInstr(
UseMI, NewR, Dest,
false);
890void HexagonXQFloatGenerator::generateQF16FromQF32(MachineInstr &
MI,
894 MachineBasicBlock &
MBB = *
MI.getParent();
898 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vconv_hf_qf32), convertReg)
909void HexagonXQFloatGenerator::widenMultiplyInputHF(MachineInstr &
MI,
914 MachineBasicBlock &
MBB = *
MI.getParent();
917 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vmpy_qf32_hf), output_mpy)
920 generateQF16FromQF32(
MI, Dest, output_mpy);
924bool HexagonXQFloatGenerator::widenMultiplicationInputF16(MachineInstr &
MI,
929 bool firstconvert =
false, secondconvert =
false;
930 MachineBasicBlock &
MBB = *
MI.getParent();
934 if (checkIfInputFromAdder16(Reg1))
937 if (twoOps && checkIfInputFromAdder16(Reg2))
938 secondconvert =
true;
943 if (firstconvert || secondconvert) {
945 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vmpy_qf32_qf16), widenReg)
954 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vmpy_qf32_mix_hf), widenReg)
963 generateQF16FromQF32(
MI, Dest, widenReg);
970bool HexagonXQFloatGenerator::widenMultiplicationInputF16Rt(MachineInstr &
MI,
976 if (!checkIfInputFromAdder16(Reg1)) {
978 if (!checkIfInputFromMult16(Reg1))
984 MachineBasicBlock &
MBB = *
MI.getParent();
994 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vmpy_qf32_hf), widenReg)
998 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vmpy_qf32_mix_hf), widenReg)
1004 generateQF16FromQF32(
MI, Dest, widenReg);
1013bool HexagonXQFloatGenerator::convertAddOpToIEEE32(
1015 bool isAdd,
bool isFirstOpQf,
bool isSecOpQf) {
1019 bool firstconvert =
false, secondconvert =
false;
1020 MachineBasicBlock &
MBB = *
MI.getParent();
1027 if (checkIfInputFromAdder32(Reg1) || checkIfInputFromMult32(Reg1)) {
1031 firstconvert =
true;
1039 if (checkIfInputFromAdder32(Reg2) || checkIfInputFromMult32(Reg2)) {
1043 secondconvert =
true;
1050 if (isFirstOpQf && isSecOpQf) {
1051 if (firstconvert && secondconvert) {
1053 HII->get(isAdd ? Hexagon::V6_vadd_sf : Hexagon::V6_vsub_sf), Dest)
1056 }
else if (firstconvert) {
1077 }
else if (secondconvert) {
1079 HII->get(isAdd ? Hexagon::V6_vadd_qf32_mix
1080 : Hexagon::V6_vsub_qf32_mix),
1088 }
else if (isFirstOpQf) {
1091 HII->get(isAdd ? Hexagon::V6_vadd_sf : Hexagon::V6_vsub_sf), Dest)
1097 }
else if (isSecOpQf) {
1100 HII->get(isAdd ? Hexagon::V6_vadd_sf : Hexagon::V6_vsub_sf), Dest)
1115bool HexagonXQFloatGenerator::convertAddOpToIEEE16(
1117 bool isAdd,
bool isFirstOpQf,
bool isSecOpQf) {
1119 MachineBasicBlock &
MBB = *
MI.getParent();
1123 bool firstconvert =
false, secondconvert =
false;
1128 if (checkIfInputFromAdder16(Reg1) || checkIfInputFromMult16(Reg1)) {
1132 firstconvert =
true;
1138 if (checkIfInputFromAdder16(Reg2) || checkIfInputFromMult16(Reg2)) {
1142 secondconvert =
true;
1149 if (isFirstOpQf && isSecOpQf) {
1150 if (firstconvert && secondconvert) {
1152 HII->get(isAdd ? Hexagon::V6_vadd_hf : Hexagon::V6_vsub_hf), Dest)
1155 }
else if (firstconvert) {
1176 }
else if (secondconvert) {
1178 HII->get(isAdd ? Hexagon::V6_vadd_qf16_mix
1179 : Hexagon::V6_vsub_qf16_mix),
1187 }
else if (isFirstOpQf) {
1190 HII->get(isAdd ? Hexagon::V6_vadd_hf : Hexagon::V6_vsub_hf), Dest)
1196 }
else if (isSecOpQf) {
1199 HII->get(isAdd ? Hexagon::V6_vadd_hf : Hexagon::V6_vsub_hf), Dest)
1214void HexagonXQFloatGenerator::createPrologInstructions(MachineInstr &
MI,
1217 MachineBasicBlock &
MBB = *
MI.getParent();
1235bool HexagonXQFloatGenerator::V81normalizeMultF32(
1237 bool firstconvert,
bool secondconvert,
bool strictieee) {
1238 MachineBasicBlock &
MBB = *
MI.getParent();
1243 strictieee ? Hexagon::V6_vconv_qf32_sf : Hexagon::V6_vconv_qf32_qf32;
1246 if (firstconvert && secondconvert) {
1257 else if (firstconvert) {
1265 else if (secondconvert) {
1279void HexagonXQFloatGenerator::normalizeMultiplicationInputSF(
1281 Register &R_mpy,
bool &PrologCreated) {
1283 MachineBasicBlock &
MBB = *
MI.getParent();
1291 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vconv_qf32_sf), input_mpy1)
1293 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vconv_qf32_sf), input_mpy2)
1302 if (!PrologCreated) {
1303 createPrologInstructions(
MI, R_mpy);
1304 PrologCreated =
true;
1310 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vadd_qf32_mix), input_mpy1)
1313 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vadd_qf32_mix), input_mpy2)
1323bool HexagonXQFloatGenerator::convertNormalizeMultOp32(
1325 Register &R_mpy,
bool &PrologCreated) {
1328 bool firstconvert =
false, secondconvert =
false;
1329 MachineBasicBlock &
MBB = *
MI.getParent();
1334 if (checkIfInputFromAdder32(Reg1) || checkIfInputFromMult32(Reg1)) {
1337 firstconvert =
true;
1340 if (checkIfInputFromAdder32(Reg2) || checkIfInputFromMult32(Reg2)) {
1343 secondconvert =
true;
1347 if (firstconvert && secondconvert)
1348 return V81normalizeMultF32(
MI, VR1, VR2, Dest,
true,
true,
true);
1349 else if (firstconvert)
1350 return V81normalizeMultF32(
MI, VR1, Reg2, Dest,
true,
false,
true);
1351 else if (secondconvert)
1352 return V81normalizeMultF32(
MI, Reg1, VR2, Dest,
false,
true,
true);
1358 if (!PrologCreated && (firstconvert || secondconvert)) {
1359 createPrologInstructions(
MI, R_mpy);
1360 PrologCreated =
true;
1366 if (firstconvert && secondconvert) {
1370 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vadd_qf32_mix), input_mpy1)
1373 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vadd_qf32_mix), input_mpy2)
1380 }
else if (firstconvert) {
1383 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vadd_qf32_mix), input_mpy1)
1390 }
else if (secondconvert) {
1393 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vadd_qf32_mix), input_mpy2)
1409bool HexagonXQFloatGenerator::convertWidenMultOp16(MachineInstr &
MI,
1416 bool firstconvert =
false,
1417 secondconvert =
false;
1418 MachineBasicBlock &
MBB = *
MI.getParent();
1423 if (checkIfInputFromAdder16(Reg1) || checkIfInputFromMult16(Reg1)) {
1426 firstconvert =
true;
1430 if (checkIfInputFromAdder16(Reg2) || checkIfInputFromMult16(Reg2)) {
1434 secondconvert =
true;
1440 if (firstconvert && secondconvert) {
1442 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vmpy_qf32_hf), output_mpy)
1446 }
else if (firstconvert) {
1448 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vmpy_qf32_mix_hf), output_mpy)
1451 }
else if (secondconvert) {
1453 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vmpy_qf32_mix_hf), output_mpy)
1463 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vmpy_qf32_hf), output_mpy)
1471 generateQF16FromQF32(
MI, Dest, output_mpy);
1478bool HexagonXQFloatGenerator::convertWidenMultOp32(MachineInstr &
MI,
1484 bool firstconvert =
false,
1485 secondconvert =
false;
1486 MachineBasicBlock &
MBB = *
MI.getParent();
1491 if (checkIfInputFromAdder16(Reg1) || checkIfInputFromMult16(Reg1)) {
1494 firstconvert =
true;
1498 if (checkIfInputFromAdder16(Reg2) || checkIfInputFromMult16(Reg2)) {
1502 secondconvert =
true;
1508 if (firstconvert && secondconvert) {
1513 }
else if (firstconvert) {
1514 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vmpy_qf32_mix_hf), Dest)
1517 }
else if (secondconvert) {
1518 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vmpy_qf32_mix_hf), Dest)
1537bool HexagonXQFloatGenerator::normalizeMultiplicationInputF32(
1539 Register &R_mpy,
bool &PrologCreated) {
1540 bool firstconvert =
false, secondconvert =
false;
1541 MachineBasicBlock &
MBB = *
MI.getParent();
1545 if (checkIfInputFromAdder32(Reg1))
1546 firstconvert =
true;
1547 if (checkIfInputFromAdder32(Reg2))
1548 secondconvert =
true;
1552 return V81normalizeMultF32(
MI, Reg1, Reg2, Dest, firstconvert,
1553 secondconvert,
false);
1556 if ((!PrologCreated && (firstconvert || secondconvert))) {
1557 createPrologInstructions(
MI, R_mpy);
1558 PrologCreated =
true;
1564 if (firstconvert && secondconvert) {
1568 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vadd_qf32), input_mpy1)
1571 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vadd_qf32), input_mpy2)
1578 }
else if (firstconvert) {
1581 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vadd_qf32), input_mpy1)
1588 }
else if (secondconvert) {
1591 BuildMI(
MBB,
MI,
DL, HII->get(Hexagon::V6_vadd_qf32), input_mpy2)
1605bool HexagonXQFloatGenerator::deleteList() {
1606 if (OriginalMI.empty())
1609 for (MachineInstr *origMI : OriginalMI) {
1612 origMI->eraseFromParent();
1620bool HexagonXQFloatGenerator::HandleLossySubnormals(MachineFunction &MF) {
1623 for (
auto &
MBB : MF) {
1624 bool PrologCreated =
false;
1625 for (
auto &
MI :
MBB) {
1630 if (
MI.getNumOperands() != 3 ||
MI.isDebugInstr())
1632 auto Op1 =
MI.getOperand(1);
1635 auto Op2 =
MI.getOperand(2);
1638 auto Op0 =
MI.getOperand(0);
1649 switch (
MI.getOpcode()) {
1653 case Hexagon::V6_vmpy_qf32:
1654 if (normalizeMultiplicationInputF32(
MI, Reg1, Reg2, Dest, R_mpy,
1656 OriginalMI.push_back(&
MI);
1657 Changed |= convertIfInputToNonHVX(
MI,
true);
1663 case Hexagon::V6_vmpy_qf16:
1664 if (widenMultiplicationInputF16(
MI, Reg1, Reg2, Dest,
true))
1665 OriginalMI.push_back(&
MI);
1666 Changed |= convertIfInputToNonHVX(
MI,
false);
1673 case Hexagon::V6_vmpy_rt_qf16:
1674 if (widenMultiplicationInputF16Rt(
MI, Reg1, Reg2, Dest))
1675 OriginalMI.push_back(&
MI);
1676 Changed |= convertIfInputToNonHVX(
MI,
false);
1682 case Hexagon::V6_vmpy_qf16_mix_hf:
1683 if (widenMultiplicationInputF16(
MI, Reg1, Reg2, Dest,
false))
1684 OriginalMI.push_back(&
MI);
1685 Changed |= convertIfInputToNonHVX(
MI,
false);
1690 case Hexagon::V6_vadd_sf:
1691 case Hexagon::V6_vadd_qf32:
1692 case Hexagon::V6_vadd_qf32_mix:
1693 case Hexagon::V6_vsub_sf:
1694 case Hexagon::V6_vsub_qf32:
1695 case Hexagon::V6_vsub_qf32_mix:
1696 case Hexagon::V6_vsub_sf_mix:
1697 case Hexagon::V6_vmpy_qf32_qf16:
1698 case Hexagon::V6_vmpy_qf32_hf:
1699 case Hexagon::V6_vmpy_qf32_mix_hf:
1700 case Hexagon::V6_vmpy_rt_sf:
1701 case Hexagon::V6_vmpy_qf32_sf:
1702 Changed |= convertIfInputToNonHVX(
MI,
true);
1707 case Hexagon::V6_vadd_hf:
1708 case Hexagon::V6_vsub_hf:
1709 case Hexagon::V6_vadd_qf16:
1710 case Hexagon::V6_vsub_qf16:
1711 case Hexagon::V6_vadd_qf16_mix:
1712 case Hexagon::V6_vsub_qf16_mix:
1713 case Hexagon::V6_vsub_hf_mix:
1714 case Hexagon::V6_vmpy_qf16_hf:
1715 case Hexagon::V6_vmpy_rt_hf:
1716 Changed |= convertIfInputToNonHVX(
MI,
false);
1723 if (OriginalMI.empty() || !
Changed)
1729bool HexagonXQFloatGenerator::HandleCompliantIEEE(MachineFunction &MF) {
1732 for (
auto &
MBB : MF) {
1733 bool PrologCreated =
false;
1734 for (
auto &
MI :
MBB) {
1739 if (
MI.getNumOperands() != 3 ||
MI.isDebugInstr())
1742 auto Op1 =
MI.getOperand(1);
1745 auto Op2 =
MI.getOperand(2);
1748 auto Op0 =
MI.getOperand(0);
1760 switch (
MI.getOpcode()) {
1767 case Hexagon::V6_vmpy_rt_sf:
1769 BuildMI(
MBB,
MI,
MI.getDebugLoc(), HII->get(Hexagon::V6_lvsplatw),
1772 normalizeMultiplicationInputSF(
MI, Reg1, VRtSplat, Dest, R_mpy,
1774 OriginalMI.push_back(&
MI);
1775 Changed |= convertIfInputToNonHVX(
MI,
true);
1780 case Hexagon::V6_vmpy_qf32_sf:
1781 normalizeMultiplicationInputSF(
MI, Reg1, Reg2, Dest, R_mpy,
1783 OriginalMI.push_back(&
MI);
1784 Changed |= convertIfInputToNonHVX(
MI,
true);
1790 case Hexagon::V6_vmpy_qf32:
1791 if (normalizeMultiplicationInputF32(
MI, Reg1, Reg2, Dest, R_mpy,
1793 OriginalMI.push_back(&
MI);
1794 Changed |= convertIfInputToNonHVX(
MI,
true);
1799 case Hexagon::V6_vmpy_rt_hf:
1801 BuildMI(
MBB,
MI,
MI.getDebugLoc(), HII->get(Hexagon::V6_lvsplatw),
1804 widenMultiplyInputHF(
MI, Reg1, VRtSplat, Dest);
1805 OriginalMI.push_back(&
MI);
1806 Changed |= convertIfInputToNonHVX(
MI,
false);
1811 case Hexagon::V6_vmpy_qf16_hf:
1812 widenMultiplyInputHF(
MI, Reg1, Reg2, Dest);
1813 OriginalMI.push_back(&
MI);
1814 Changed |= convertIfInputToNonHVX(
MI,
false);
1820 case Hexagon::V6_vmpy_qf16:
1821 if (widenMultiplicationInputF16(
MI, Reg1, Reg2, Dest,
true))
1822 OriginalMI.push_back(&
MI);
1823 Changed |= convertIfInputToNonHVX(
MI,
false);
1830 case Hexagon::V6_vmpy_rt_qf16:
1831 if (widenMultiplicationInputF16Rt(
MI, Reg1, Reg2, Dest))
1832 OriginalMI.push_back(&
MI);
1833 Changed |= convertIfInputToNonHVX(
MI,
false);
1839 case Hexagon::V6_vmpy_qf16_mix_hf:
1840 if (widenMultiplicationInputF16(
MI, Reg1, Reg2, Dest,
false))
1841 OriginalMI.push_back(&
MI);
1842 Changed |= convertIfInputToNonHVX(
MI,
false);
1848 case Hexagon::V6_vadd_sf:
1849 case Hexagon::V6_vadd_qf32:
1850 case Hexagon::V6_vadd_qf32_mix:
1851 case Hexagon::V6_vsub_sf:
1852 case Hexagon::V6_vsub_qf32:
1853 case Hexagon::V6_vsub_qf32_mix:
1854 case Hexagon::V6_vsub_sf_mix:
1855 case Hexagon::V6_vmpy_qf32_qf16:
1856 case Hexagon::V6_vmpy_qf32_hf:
1857 case Hexagon::V6_vmpy_qf32_mix_hf:
1858 Changed |= convertIfInputToNonHVX(
MI,
true);
1860 case Hexagon::V6_vadd_hf:
1861 case Hexagon::V6_vsub_hf:
1862 case Hexagon::V6_vadd_qf16:
1863 case Hexagon::V6_vsub_qf16:
1864 case Hexagon::V6_vadd_qf16_mix:
1865 case Hexagon::V6_vsub_qf16_mix:
1866 case Hexagon::V6_vsub_hf_mix:
1867 Changed |= convertIfInputToNonHVX(
MI,
false);
1874 if (OriginalMI.empty() || !
Changed)
1880bool HexagonXQFloatGenerator::HandleStrictIEEE(MachineFunction &MF) {
1884 for (
auto &
MBB : MF) {
1885 bool PrologCreated =
false;
1886 for (
auto &
MI :
MBB) {
1891 if (
MI.getNumOperands() != 3 ||
MI.isDebugInstr())
1894 auto Op1 =
MI.getOperand(1);
1897 auto Op2 =
MI.getOperand(2);
1900 auto Op0 =
MI.getOperand(0);
1912 switch (
MI.getOpcode()) {
1917 case Hexagon::V6_vadd_qf32:
1918 if (convertAddOpToIEEE32(
MI, Reg1, Reg2, Dest,
true,
true,
true))
1919 OriginalMI.push_back(&
MI);
1920 Changed |= convertIfInputToNonHVX(
MI,
true);
1923 case Hexagon::V6_vsub_qf32:
1924 if (convertAddOpToIEEE32(
MI, Reg1, Reg2, Dest,
false,
true,
true))
1925 OriginalMI.push_back(&
MI);
1926 Changed |= convertIfInputToNonHVX(
MI,
true);
1931 case Hexagon::V6_vadd_qf32_mix:
1932 if (convertAddOpToIEEE32(
MI, Reg1, Reg2, Dest,
true,
true,
false))
1933 OriginalMI.push_back(&
MI);
1934 Changed |= convertIfInputToNonHVX(
MI,
true);
1937 case Hexagon::V6_vsub_qf32_mix:
1938 if (convertAddOpToIEEE32(
MI, Reg1, Reg2, Dest,
false,
true,
false))
1939 OriginalMI.push_back(&
MI);
1940 Changed |= convertIfInputToNonHVX(
MI,
true);
1943 case Hexagon::V6_vsub_sf_mix:
1944 if (convertAddOpToIEEE32(
MI, Reg1, Reg2, Dest,
false,
false,
true))
1945 OriginalMI.push_back(&
MI);
1946 Changed |= convertIfInputToNonHVX(
MI,
true);
1953 case Hexagon::V6_vadd_qf16:
1954 if (convertAddOpToIEEE16(
MI, Reg1, Reg2, Dest,
true,
true,
true))
1955 OriginalMI.push_back(&
MI);
1956 Changed |= convertIfInputToNonHVX(
MI,
false);
1959 case Hexagon::V6_vsub_qf16:
1960 if (convertAddOpToIEEE16(
MI, Reg1, Reg2, Dest,
false,
true,
true))
1961 OriginalMI.push_back(&
MI);
1962 Changed |= convertIfInputToNonHVX(
MI,
false);
1967 case Hexagon::V6_vadd_qf16_mix:
1968 if (convertAddOpToIEEE16(
MI, Reg1, Reg2, Dest,
true,
true,
false))
1969 OriginalMI.push_back(&
MI);
1970 Changed |= convertIfInputToNonHVX(
MI,
false);
1973 case Hexagon::V6_vsub_qf16_mix:
1974 if (convertAddOpToIEEE16(
MI, Reg1, Reg2, Dest,
false,
true,
false))
1975 OriginalMI.push_back(&
MI);
1976 Changed |= convertIfInputToNonHVX(
MI,
false);
1979 case Hexagon::V6_vsub_hf_mix:
1980 if (convertAddOpToIEEE16(
MI, Reg1, Reg2, Dest,
false,
false,
true))
1981 OriginalMI.push_back(&
MI);
1982 Changed |= convertIfInputToNonHVX(
MI,
false);
1990 case Hexagon::V6_vmpy_rt_sf:
1992 BuildMI(
MBB,
MI,
MI.getDebugLoc(), HII->get(Hexagon::V6_lvsplatw),
1995 normalizeMultiplicationInputSF(
MI, Reg1, VRtSplat, Dest, R_mpy,
1997 OriginalMI.push_back(&
MI);
1998 Changed |= convertIfInputToNonHVX(
MI,
true);
2003 case Hexagon::V6_vmpy_qf32_sf:
2004 normalizeMultiplicationInputSF(
MI, Reg1, Reg2, Dest, R_mpy,
2006 Changed |= convertIfInputToNonHVX(
MI,
true);
2007 OriginalMI.push_back(&
MI);
2013 case Hexagon::V6_vmpy_qf32:
2014 if (convertNormalizeMultOp32(
MI, Reg1, Reg2, Dest, R_mpy,
2016 OriginalMI.push_back(&
MI);
2017 Changed |= convertIfInputToNonHVX(
MI,
true);
2025 case Hexagon::V6_vmpy_qf16:
2026 if (convertWidenMultOp16(
MI, Reg1, Reg2, Dest,
true))
2027 OriginalMI.push_back(&
MI);
2028 Changed |= convertIfInputToNonHVX(
MI,
false);
2035 case Hexagon::V6_vmpy_qf32_qf16:
2036 if (convertWidenMultOp32(
MI, Reg1, Reg2, Dest,
true))
2037 OriginalMI.push_back(&
MI);
2038 Changed |= convertIfInputToNonHVX(
MI,
true);
2043 case Hexagon::V6_vmpy_rt_hf:
2045 BuildMI(
MBB,
MI,
MI.getDebugLoc(), HII->get(Hexagon::V6_lvsplatw),
2048 widenMultiplyInputHF(
MI, Reg1, VRtSplat, Dest);
2049 OriginalMI.push_back(&
MI);
2050 Changed |= convertIfInputToNonHVX(
MI,
false);
2055 case Hexagon::V6_vmpy_qf16_hf:
2056 widenMultiplyInputHF(
MI, Reg1, Reg2, Dest);
2057 OriginalMI.push_back(&
MI);
2058 Changed |= convertIfInputToNonHVX(
MI,
false);
2065 case Hexagon::V6_vmpy_rt_qf16:
2066 if (widenMultiplicationInputF16Rt(
MI, Reg1, Reg2, Dest))
2067 OriginalMI.push_back(&
MI);
2068 Changed |= convertIfInputToNonHVX(
MI,
false);
2076 case Hexagon::V6_vmpy_qf16_mix_hf:
2077 if (convertWidenMultOp16(
MI, Reg1, Reg2, Dest,
false))
2078 OriginalMI.push_back(&
MI);
2079 Changed |= convertIfInputToNonHVX(
MI,
false);
2086 case Hexagon::V6_vmpy_qf32_mix_hf:
2087 if (convertWidenMultOp32(
MI, Reg1, Reg2, Dest,
false))
2088 OriginalMI.push_back(&
MI);
2089 Changed |= convertIfInputToNonHVX(
MI,
true);
2094 case Hexagon::V6_vadd_sf:
2095 case Hexagon::V6_vsub_sf:
2096 Changed |= convertIfInputToNonHVX(
MI,
true);
2098 case Hexagon::V6_vadd_hf:
2099 case Hexagon::V6_vsub_hf:
2100 Changed |= convertIfInputToNonHVX(
MI,
false);
2107 if (OriginalMI.empty() || !
Changed)
2113bool HexagonXQFloatGenerator::HandleLossyLegacy(MachineFunction &MF) {
2117bool HexagonXQFloatGenerator::runOnMachineFunction(MachineFunction &MF) {
2128 VectorConvertRemove VCR(MF, MRI, HST);
2130 LLVM_DEBUG(
dbgs() <<
"\nExtraneous conversion instructions removed for "
2137 case QFloatMode::StrictIEEE:
2138 LLVM_DEBUG(
dbgs() <<
"\nGenerating code for STRICT-IEEE mode.\n");
2139 Changed = HandleStrictIEEE(MF);
2141 case QFloatMode::IEEE:
2143 Changed = HandleCompliantIEEE(MF);
2145 case QFloatMode::Lossy:
2147 Changed = HandleLossySubnormals(MF);
2149 case QFloatMode::Legacy:
2151 Changed = HandleLossyLegacy(MF);
2157 for (MachineInstr *origMI : OriginalMI) {
2159 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
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 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_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.