40#define DEBUG_TYPE "riscv-vl-optimizer"
41#define PASS_NAME "RISC-V VL Optimizer"
50 static DemandedVL vlmax() {
62 return DemandedVL::vlmax();
66class RISCVVLOptimizerImpl {
77 DemandedVL getMinimumVLForUser(
const MachineInstr &UserMI,
78 unsigned OpIdx)
const;
94 return MO.isReg() && MO.getReg().isVirtual() &&
95 RISCVRegisterInfo::isRVVRegClass(MRI->getRegClass(MO.getReg()));
102 return MO.getReg().isVirtual() &&
103 RISCVRegisterInfo::isRVVRegClass(MRI->getRegClass(MO.getReg()));
132 std::optional<std::pair<unsigned, bool>> EMUL;
139 OperandInfo(std::pair<unsigned, bool> EMUL,
unsigned Log2EEW)
140 : EMUL(EMUL), Log2EEW(Log2EEW) {}
142 OperandInfo(
unsigned Log2EEW) : Log2EEW(Log2EEW) {}
144 OperandInfo() =
delete;
148 static bool areCompatible(
const OperandInfo &Def,
const OperandInfo &
User) {
149 if (Def.Log2EEW !=
User.Log2EEW)
151 if (
User.EMUL && Def.EMUL !=
User.EMUL)
163 OS <<
"EMUL: none\n";
164 OS <<
", EEW: " << (1 << Log2EEW);
170char RISCVVLOptimizerLegacy::ID = 0;
177 return new RISCVVLOptimizerLegacy();
188 const std::optional<OperandInfo> &OI) {
198static std::pair<unsigned, bool>
210 unsigned MISEW = 1 << MILog2SEW;
212 unsigned EEW = 1 << Log2EEW;
215 unsigned Num = EEW, Denom = MISEW;
216 int GCD = MILMULIsFractional ? std::gcd(Num, Denom * MILMUL)
217 : std::gcd(Num * MILMUL, Denom);
218 Num = MILMULIsFractional ? Num / GCD : Num * MILMUL / GCD;
219 Denom = MILMULIsFractional ? Denom * MILMUL / GCD : Denom / GCD;
220 return std::make_pair(Num > Denom ? Num : Denom, Denom > Num);
224 if (!MinimumVL.VL.
isImm())
225 return DemandedVL::vlmax();
227 int64_t VL = MinimumVL.VL.
getImm();
229 return DemandedVL::vlmax();
233static DemandedVL
halfVL(DemandedVL MinimumVL,
bool Ceil =
false) {
234 if (!MinimumVL.VL.
isImm())
235 return DemandedVL::vlmax();
237 int64_t VL = MinimumVL.VL.
getImm();
239 return DemandedVL::vlmax();
243static std::pair<unsigned, bool>
doubleEMUL(std::pair<unsigned, bool> EMUL) {
244 auto [Num, IsFractional] = EMUL;
246 return std::make_pair(Num / 2, Num > 2);
247 return std::make_pair(Num * 2,
false);
250static std::pair<unsigned, bool>
halfEMUL(std::pair<unsigned, bool> EMUL) {
251 auto [Num, IsFractional] = EMUL;
252 if (IsFractional || Num == 1)
253 return std::make_pair(Num * 2,
true);
254 return std::make_pair(Num / 2,
false);
268 unsigned MISEW = 1 << MILog2SEW;
269 unsigned EEW = MISEW / Factor;
270 unsigned Log2EEW =
Log2_32(EEW);
275#define VSEG_CASES(Prefix, EEW) \
276 RISCV::Prefix##SEG2E##EEW##_V: \
277 case RISCV::Prefix##SEG3E##EEW##_V: \
278 case RISCV::Prefix##SEG4E##EEW##_V: \
279 case RISCV::Prefix##SEG5E##EEW##_V: \
280 case RISCV::Prefix##SEG6E##EEW##_V: \
281 case RISCV::Prefix##SEG7E##EEW##_V: \
282 case RISCV::Prefix##SEG8E##EEW##_V
283#define VSSEG_CASES(EEW) VSEG_CASES(VS, EEW)
284#define VSSSEG_CASES(EEW) VSEG_CASES(VSS, EEW)
285#define VSUXSEG_CASES(EEW) VSEG_CASES(VSUX, I##EEW)
286#define VSOXSEG_CASES(EEW) VSEG_CASES(VSOX, I##EEW)
292 RISCVVPseudosTable::getPseudoInfo(
MI.getOpcode());
293 assert(
RVV &&
"Could not find MI in PseudoTable");
303 OpIdx == 0 || (HasPassthru && OpIdx ==
MI.getNumExplicitDefs());
308 Info.RegClass == RISCV::VMV0RegClassID)
313 switch (
RVV->BaseInstr) {
317 case RISCV::VSETIVLI:
339 case RISCV::VLSE16_V:
340 case RISCV::VSSE16_V:
346 case RISCV::VLSE32_V:
347 case RISCV::VSSE32_V:
353 case RISCV::VLSE64_V:
354 case RISCV::VSSE64_V:
362 case RISCV::VLUXEI8_V:
363 case RISCV::VLOXEI8_V:
364 case RISCV::VSUXEI8_V:
365 case RISCV::VSOXEI8_V:
372 case RISCV::VLUXEI16_V:
373 case RISCV::VLOXEI16_V:
374 case RISCV::VSUXEI16_V:
375 case RISCV::VSOXEI16_V:
382 case RISCV::VLUXEI32_V:
383 case RISCV::VLOXEI32_V:
384 case RISCV::VSUXEI32_V:
385 case RISCV::VSOXEI32_V:
392 case RISCV::VLUXEI64_V:
393 case RISCV::VLOXEI64_V:
394 case RISCV::VSUXEI64_V:
395 case RISCV::VSOXEI64_V:
410 case RISCV::VRSUB_VI:
411 case RISCV::VRSUB_VX:
435 case RISCV::VMINU_VV:
436 case RISCV::VMINU_VX:
439 case RISCV::VMAXU_VV:
440 case RISCV::VMAXU_VX:
447 case RISCV::VMULH_VV:
448 case RISCV::VMULH_VX:
449 case RISCV::VMULHU_VV:
450 case RISCV::VMULHU_VX:
451 case RISCV::VMULHSU_VV:
452 case RISCV::VMULHSU_VX:
455 case RISCV::VDIVU_VV:
456 case RISCV::VDIVU_VX:
459 case RISCV::VREMU_VV:
460 case RISCV::VREMU_VX:
465 case RISCV::VMACC_VV:
466 case RISCV::VMACC_VX:
467 case RISCV::VNMSAC_VV:
468 case RISCV::VNMSAC_VX:
469 case RISCV::VMADD_VV:
470 case RISCV::VMADD_VX:
471 case RISCV::VNMSUB_VV:
472 case RISCV::VNMSUB_VX:
477 case RISCV::VMERGE_VIM:
478 case RISCV::VMERGE_VVM:
479 case RISCV::VMERGE_VXM:
480 case RISCV::VADC_VIM:
481 case RISCV::VADC_VVM:
482 case RISCV::VADC_VXM:
483 case RISCV::VSBC_VVM:
484 case RISCV::VSBC_VXM:
493 case RISCV::VSADDU_VI:
494 case RISCV::VSADDU_VV:
495 case RISCV::VSADDU_VX:
496 case RISCV::VSADD_VI:
497 case RISCV::VSADD_VV:
498 case RISCV::VSADD_VX:
499 case RISCV::VSSUBU_VV:
500 case RISCV::VSSUBU_VX:
501 case RISCV::VSSUB_VV:
502 case RISCV::VSSUB_VX:
503 case RISCV::VAADDU_VV:
504 case RISCV::VAADDU_VX:
505 case RISCV::VAADD_VV:
506 case RISCV::VAADD_VX:
507 case RISCV::VASUBU_VV:
508 case RISCV::VASUBU_VX:
509 case RISCV::VASUB_VV:
510 case RISCV::VASUB_VX:
514 case RISCV::VSMUL_VV:
515 case RISCV::VSMUL_VX:
518 case RISCV::VSSRL_VI:
519 case RISCV::VSSRL_VV:
520 case RISCV::VSSRL_VX:
521 case RISCV::VSSRA_VI:
522 case RISCV::VSSRA_VV:
523 case RISCV::VSSRA_VX:
530 case RISCV::VFMV_F_S:
531 case RISCV::VFMV_S_F:
534 case RISCV::VSLIDEUP_VI:
535 case RISCV::VSLIDEUP_VX:
536 case RISCV::VSLIDEDOWN_VI:
537 case RISCV::VSLIDEDOWN_VX:
538 case RISCV::VSLIDE1UP_VX:
539 case RISCV::VFSLIDE1UP_VF:
540 case RISCV::VSLIDE1DOWN_VX:
541 case RISCV::VFSLIDE1DOWN_VF:
544 case RISCV::VRGATHER_VI:
545 case RISCV::VRGATHER_VV:
546 case RISCV::VRGATHER_VX:
550 case RISCV::VFADD_VF:
551 case RISCV::VFADD_VV:
552 case RISCV::VFSUB_VF:
553 case RISCV::VFSUB_VV:
554 case RISCV::VFRSUB_VF:
556 case RISCV::VFMUL_VF:
557 case RISCV::VFMUL_VV:
558 case RISCV::VFDIV_VF:
559 case RISCV::VFDIV_VV:
560 case RISCV::VFRDIV_VF:
562 case RISCV::VFMACC_VV:
563 case RISCV::VFMACC_VF:
564 case RISCV::VFNMACC_VV:
565 case RISCV::VFNMACC_VF:
566 case RISCV::VFMSAC_VV:
567 case RISCV::VFMSAC_VF:
568 case RISCV::VFNMSAC_VV:
569 case RISCV::VFNMSAC_VF:
570 case RISCV::VFMADD_VV:
571 case RISCV::VFMADD_VF:
572 case RISCV::VFNMADD_VV:
573 case RISCV::VFNMADD_VF:
574 case RISCV::VFMSUB_VV:
575 case RISCV::VFMSUB_VF:
576 case RISCV::VFNMSUB_VV:
577 case RISCV::VFNMSUB_VF:
579 case RISCV::VFSQRT_V:
581 case RISCV::VFRSQRT7_V:
583 case RISCV::VFREC7_V:
585 case RISCV::VFMIN_VF:
586 case RISCV::VFMIN_VV:
587 case RISCV::VFMAX_VF:
588 case RISCV::VFMAX_VV:
590 case RISCV::VFSGNJ_VF:
591 case RISCV::VFSGNJ_VV:
592 case RISCV::VFSGNJN_VV:
593 case RISCV::VFSGNJN_VF:
594 case RISCV::VFSGNJX_VF:
595 case RISCV::VFSGNJX_VV:
597 case RISCV::VFCLASS_V:
599 case RISCV::VFMV_V_F:
601 case RISCV::VFCVT_XU_F_V:
602 case RISCV::VFCVT_X_F_V:
603 case RISCV::VFCVT_RTZ_XU_F_V:
604 case RISCV::VFCVT_RTZ_X_F_V:
605 case RISCV::VFCVT_F_XU_V:
606 case RISCV::VFCVT_F_X_V:
608 case RISCV::VFMERGE_VFM:
612 case RISCV::VFIRST_M:
615 case RISCV::VANDN_VV:
616 case RISCV::VANDN_VX:
620 case RISCV::VBREV8_V:
638 case RISCV::VCLMUL_VV:
639 case RISCV::VCLMUL_VX:
641 case RISCV::VCLMULH_VV:
642 case RISCV::VCLMULH_VX:
647 case RISCV::VABDU_VV:
648 case RISCV::VABDU_VX:
652 case RISCV::VUNZIPE_V:
653 case RISCV::VUNZIPO_V:
654 case RISCV::VPAIRE_VV:
655 case RISCV::VPAIRO_VV:
659 case RISCV::VWSLL_VI:
660 case RISCV::VWSLL_VX:
661 case RISCV::VWSLL_VV:
664 case RISCV::VWADDU_VV:
665 case RISCV::VWADDU_VX:
666 case RISCV::VWSUBU_VV:
667 case RISCV::VWSUBU_VX:
668 case RISCV::VWADD_VV:
669 case RISCV::VWADD_VX:
670 case RISCV::VWSUB_VV:
671 case RISCV::VWSUB_VX:
674 case RISCV::VWMUL_VV:
675 case RISCV::VWMUL_VX:
676 case RISCV::VWMULSU_VV:
677 case RISCV::VWMULSU_VX:
678 case RISCV::VWMULU_VV:
679 case RISCV::VWMULU_VX:
685 case RISCV::VWMACCU_VV:
686 case RISCV::VWMACCU_VX:
687 case RISCV::VWMACC_VV:
688 case RISCV::VWMACC_VX:
689 case RISCV::VWMACCSU_VV:
690 case RISCV::VWMACCSU_VX:
691 case RISCV::VWMACCUS_VX:
693 case RISCV::VFWMACC_VF:
694 case RISCV::VFWMACC_VV:
695 case RISCV::VFWNMACC_VF:
696 case RISCV::VFWNMACC_VV:
697 case RISCV::VFWMSAC_VF:
698 case RISCV::VFWMSAC_VV:
699 case RISCV::VFWNMSAC_VF:
700 case RISCV::VFWNMSAC_VV:
701 case RISCV::VFWMACCBF16_VV:
702 case RISCV::VFWMACCBF16_VF:
705 case RISCV::VFWADD_VV:
706 case RISCV::VFWADD_VF:
707 case RISCV::VFWSUB_VV:
708 case RISCV::VFWSUB_VF:
710 case RISCV::VFWMUL_VF:
711 case RISCV::VFWMUL_VV:
713 case RISCV::VFWCVT_XU_F_V:
714 case RISCV::VFWCVT_X_F_V:
715 case RISCV::VFWCVT_RTZ_XU_F_V:
716 case RISCV::VFWCVT_RTZ_X_F_V:
717 case RISCV::VFWCVT_F_XU_V:
718 case RISCV::VFWCVT_F_X_V:
719 case RISCV::VFWCVT_F_F_V:
720 case RISCV::VFWCVTBF16_F_F_V:
722 case RISCV::VWABDA_VV:
723 case RISCV::VWABDA_VX:
724 case RISCV::VWABDAU_VV:
725 case RISCV::VWABDAU_VX:
726 return IsMODef ? MILog2SEW + 1 : MILog2SEW;
729 case RISCV::VWADDU_WV:
730 case RISCV::VWADDU_WX:
731 case RISCV::VWSUBU_WV:
732 case RISCV::VWSUBU_WX:
733 case RISCV::VWADD_WV:
734 case RISCV::VWADD_WX:
735 case RISCV::VWSUB_WV:
736 case RISCV::VWSUB_WX:
738 case RISCV::VFWADD_WF:
739 case RISCV::VFWADD_WV:
740 case RISCV::VFWSUB_WF:
741 case RISCV::VFWSUB_WV: {
742 bool IsOp1 = (HasPassthru && !IsTied) ? OpIdx == 2 : OpIdx == 1;
743 bool TwoTimes = IsMODef || IsOp1;
744 return TwoTimes ? MILog2SEW + 1 : MILog2SEW;
748 case RISCV::VZEXT_VF2:
749 case RISCV::VSEXT_VF2:
751 case RISCV::VZEXT_VF4:
752 case RISCV::VSEXT_VF4:
754 case RISCV::VZEXT_VF8:
755 case RISCV::VSEXT_VF8:
760 case RISCV::VNSRL_WX:
761 case RISCV::VNSRL_WI:
762 case RISCV::VNSRL_WV:
763 case RISCV::VNSRA_WI:
764 case RISCV::VNSRA_WV:
765 case RISCV::VNSRA_WX:
768 case RISCV::VNCLIPU_WI:
769 case RISCV::VNCLIPU_WV:
770 case RISCV::VNCLIPU_WX:
771 case RISCV::VNCLIP_WI:
772 case RISCV::VNCLIP_WV:
773 case RISCV::VNCLIP_WX:
775 case RISCV::VFNCVT_XU_F_W:
776 case RISCV::VFNCVT_X_F_W:
777 case RISCV::VFNCVT_RTZ_XU_F_W:
778 case RISCV::VFNCVT_RTZ_X_F_W:
779 case RISCV::VFNCVT_F_XU_W:
780 case RISCV::VFNCVT_F_X_W:
781 case RISCV::VFNCVT_F_F_W:
782 case RISCV::VFNCVT_ROD_F_F_W:
783 case RISCV::VFNCVTBF16_F_F_W: {
785 bool IsOp1 = HasPassthru ? OpIdx == 2 : OpIdx == 1;
786 bool TwoTimes = IsOp1;
787 return TwoTimes ? MILog2SEW + 1 : MILog2SEW;
799 case RISCV::VMAND_MM:
800 case RISCV::VMNAND_MM:
801 case RISCV::VMANDN_MM:
802 case RISCV::VMXOR_MM:
804 case RISCV::VMNOR_MM:
805 case RISCV::VMORN_MM:
806 case RISCV::VMXNOR_MM:
809 case RISCV::VMSOF_M: {
816 case RISCV::VCOMPRESS_VM:
817 return OpIdx == 3 ? 0 : MILog2SEW;
822 case RISCV::VIOTA_M: {
823 if (IsMODef || OpIdx == 1)
830 case RISCV::VMSEQ_VI:
831 case RISCV::VMSEQ_VV:
832 case RISCV::VMSEQ_VX:
833 case RISCV::VMSNE_VI:
834 case RISCV::VMSNE_VV:
835 case RISCV::VMSNE_VX:
836 case RISCV::VMSLTU_VV:
837 case RISCV::VMSLTU_VX:
838 case RISCV::VMSLT_VV:
839 case RISCV::VMSLT_VX:
840 case RISCV::VMSLEU_VV:
841 case RISCV::VMSLEU_VI:
842 case RISCV::VMSLEU_VX:
843 case RISCV::VMSLE_VV:
844 case RISCV::VMSLE_VI:
845 case RISCV::VMSLE_VX:
846 case RISCV::VMSGTU_VI:
847 case RISCV::VMSGTU_VX:
848 case RISCV::VMSGT_VI:
849 case RISCV::VMSGT_VX:
852 case RISCV::VMADC_VIM:
853 case RISCV::VMADC_VVM:
854 case RISCV::VMADC_VXM:
855 case RISCV::VMSBC_VVM:
856 case RISCV::VMSBC_VXM:
858 case RISCV::VMADC_VV:
859 case RISCV::VMADC_VI:
860 case RISCV::VMADC_VX:
861 case RISCV::VMSBC_VV:
862 case RISCV::VMSBC_VX:
865 case RISCV::VMFEQ_VF:
866 case RISCV::VMFEQ_VV:
867 case RISCV::VMFNE_VF:
868 case RISCV::VMFNE_VV:
869 case RISCV::VMFLT_VF:
870 case RISCV::VMFLT_VV:
871 case RISCV::VMFLE_VF:
872 case RISCV::VMFLE_VV:
873 case RISCV::VMFGT_VF:
874 case RISCV::VMFGE_VF: {
882 case RISCV::VREDAND_VS:
883 case RISCV::VREDMAX_VS:
884 case RISCV::VREDMAXU_VS:
885 case RISCV::VREDMIN_VS:
886 case RISCV::VREDMINU_VS:
887 case RISCV::VREDOR_VS:
888 case RISCV::VREDSUM_VS:
889 case RISCV::VREDXOR_VS:
891 case RISCV::VFREDMAX_VS:
892 case RISCV::VFREDMIN_VS:
893 case RISCV::VFREDOSUM_VS:
894 case RISCV::VFREDUSUM_VS: {
901 case RISCV::VWREDSUM_VS:
902 case RISCV::VWREDSUMU_VS:
904 case RISCV::VFWREDOSUM_VS:
905 case RISCV::VFWREDUSUM_VS: {
906 bool TwoTimes = IsMODef || OpIdx == 3;
907 return TwoTimes ? MILog2SEW + 1 : MILog2SEW;
912 case RISCV::VRGATHEREI16_VV: {
926 RISCVVPseudosTable::getPseudoInfo(
MI.getOpcode());
927 assert(
RVV &&
"Could not find MI in PseudoTable");
933 switch (
RVV->BaseInstr) {
940 case RISCV::VREDAND_VS:
941 case RISCV::VREDMAX_VS:
942 case RISCV::VREDMAXU_VS:
943 case RISCV::VREDMIN_VS:
944 case RISCV::VREDMINU_VS:
945 case RISCV::VREDOR_VS:
946 case RISCV::VREDSUM_VS:
947 case RISCV::VREDXOR_VS:
948 case RISCV::VWREDSUM_VS:
949 case RISCV::VWREDSUMU_VS:
950 case RISCV::VFWREDOSUM_VS:
951 case RISCV::VFWREDUSUM_VS:
953 return OperandInfo(*Log2EEW);
959 case RISCV::VZIP_VV: {
961 if (OpIdx == 2 || OpIdx == 3)
963 return OperandInfo(EMUL, *Log2EEW);
968 case RISCV::VUNZIPE_V:
969 case RISCV::VUNZIPO_V: {
973 return OperandInfo(EMUL, *Log2EEW);
984bool RISCVVLOptimizerImpl::isSupportedInstr(
const MachineInstr &
MI)
const {
992 assert(!(
MI.getNumExplicitDefs() == 0 && !
MI.mayStore() &&
994 "No defs but elements don't depend on VL?");
998 if (RVVOpc == RISCV::VMV_S_X || RVVOpc == RISCV::VFMV_S_F)
1014 RISCVVPseudosTable::getPseudoInfo(
MI.getOpcode());
1019 switch (
RVV->BaseInstr) {
1021 case RISCV::VREDAND_VS:
1022 case RISCV::VREDMAX_VS:
1023 case RISCV::VREDMAXU_VS:
1024 case RISCV::VREDMIN_VS:
1025 case RISCV::VREDMINU_VS:
1026 case RISCV::VREDOR_VS:
1027 case RISCV::VREDSUM_VS:
1028 case RISCV::VREDXOR_VS:
1029 case RISCV::VWREDSUM_VS:
1030 case RISCV::VWREDSUMU_VS:
1031 case RISCV::VFREDMAX_VS:
1032 case RISCV::VFREDMIN_VS:
1033 case RISCV::VFREDOSUM_VS:
1034 case RISCV::VFREDUSUM_VS:
1035 case RISCV::VFWREDOSUM_VS:
1036 case RISCV::VFWREDUSUM_VS:
1038 case RISCV::VMV_X_S:
1039 case RISCV::VFMV_F_S:
1046bool RISCVVLOptimizerImpl::isCandidate(
const MachineInstr &
MI)
const {
1047 const MCInstrDesc &
Desc =
MI.getDesc();
1051 if (
MI.getNumExplicitDefs() != 1)
1056 if (!
MI.allImplicitDefsAreDead()) {
1057 LLVM_DEBUG(
dbgs() <<
"Not a candidate because has non-dead implicit def\n");
1061 if (
MI.mayRaiseFPException()) {
1062 LLVM_DEBUG(
dbgs() <<
"Not a candidate because may raise FP exception\n");
1066 for (
const MachineMemOperand *MMO :
MI.memoperands()) {
1067 if (MMO->isVolatile()) {
1068 LLVM_DEBUG(
dbgs() <<
"Not a candidate because contains volatile MMO\n");
1073 if (!isSupportedInstr(
MI)) {
1074 LLVM_DEBUG(
dbgs() <<
"Not a candidate due to unsupported instruction: "
1081 "Instruction shouldn't be supported if elements depend on VL");
1085 "All supported instructions produce a vector register result");
1087 LLVM_DEBUG(
dbgs() <<
"Found a candidate for VL reduction: " <<
MI <<
"\n");
1102static std::optional<DemandedVL>
1106 return std::nullopt;
1109 return std::nullopt;
1113 return std::nullopt;
1117 return std::nullopt;
1119 if (!SlideAmtDef || SlideAmtDef->
getOpcode() != RISCV::ADDI ||
1122 return std::nullopt;
1126DemandedVL RISCVVLOptimizerImpl::getMinimumVLForUser(
const MachineInstr &UserMI,
1127 unsigned OpIdx)
const {
1128 const MachineOperand &UserOp = UserMI.
getOperand(OpIdx);
1132 return DemandedVLs.lookup(&UserMI);
1137 return DemandedVL::vlmax();
1144 bool IsVUNZIP = RVVOpc == RISCV::VUNZIPE_V || RVVOpc == RISCV::VUNZIPO_V;
1145 bool IsVZIP = RVVOpc == RISCV::VZIP_VV;
1147 LLVM_DEBUG(
dbgs() <<
" Abort because used by unsafe instruction\n");
1148 return DemandedVL::vlmax();
1152 const MachineOperand &VLOp = UserMI.
getOperand(VLOpNum);
1155 "Did not expect X0 VL");
1164 "instruction with demanded tail\n");
1165 return DemandedVL::vlmax();
1172 LLVM_DEBUG(
dbgs() <<
" Used this operand as a scalar operand\n");
1178 DemandedVL MinimumVL = VLOp;
1180 MinimumVL = DemandedVLs.lookup(&UserMI);
1182 if (IsVUNZIP && OpIdx == 2)
1184 if (IsVZIP && (OpIdx == 2 || OpIdx == 3))
1185 MinimumVL =
halfVL(MinimumVL, OpIdx == 2);
1194 if (!
MI.isInsertSubreg())
1208 unsigned SubRegIdx =
MI.getOperand(3).getImm();
1210 assert(!IsFractional &&
"unexpected LMUL for tuple register classes");
1238bool RISCVVLOptimizerImpl::checkUsers(
const MachineInstr &
MI)
const {
1242 SmallSetVector<MachineOperand *, 8> OpWorklist;
1243 SmallPtrSet<const MachineInstr *, 4> PHISeen;
1244 for (
auto &UserOp : MRI->
use_operands(
MI.getOperand(0).getReg()))
1245 OpWorklist.
insert(&UserOp);
1247 while (!OpWorklist.
empty()) {
1249 const MachineInstr &UserMI = *UserOp.
getParent();
1260 LLVM_DEBUG(
dbgs().indent(4) <<
"Peeking through uses of INSERT_SUBREG\n");
1261 for (MachineOperand &UseOp :
1263 const MachineInstr &CandidateMI = *UseOp.getParent();
1271 OpWorklist.
insert(&UseOp);
1276 if (UserMI.
isPHI()) {
1278 if (!PHISeen.
insert(&UserMI).second)
1291 std::optional<OperandInfo> ConsumerInfo =
1294 if (!ConsumerInfo || !ProducerInfo) {
1295 LLVM_DEBUG(
dbgs() <<
" Abort due to unknown operand information.\n");
1296 LLVM_DEBUG(
dbgs() <<
" ConsumerInfo is: " << ConsumerInfo <<
"\n");
1297 LLVM_DEBUG(
dbgs() <<
" ProducerInfo is: " << ProducerInfo <<
"\n");
1301 if (!OperandInfo::areCompatible(*ProducerInfo, *ConsumerInfo)) {
1304 <<
" Abort due to incompatible information for EMUL or EEW.\n");
1305 LLVM_DEBUG(
dbgs() <<
" ConsumerInfo is: " << ConsumerInfo <<
"\n");
1306 LLVM_DEBUG(
dbgs() <<
" ProducerInfo is: " << ProducerInfo <<
"\n");
1314bool RISCVVLOptimizerImpl::tryReduceVL(MachineInstr &
MI,
1315 MachineOperand CommonVL)
const {
1319 MachineOperand &VLOp =
MI.getOperand(VLOpNum);
1322 "Expected VL to be an Imm or virtual Reg");
1326 if (CommonVL.
isReg()) {
1328 if (VLMI && RISCVInstrInfo::isFaultOnlyFirstLoad(*VLMI) &&
1340 dbgs() <<
" Abort due to CommonVL == VLOp, no point in reducing.\n");
1344 if (CommonVL.
isImm()) {
1346 << CommonVL.
getImm() <<
" for " <<
MI <<
"\n");
1354 auto VLDominates = [
this, &VLMI](
const MachineInstr &
MI) {
1357 if (!VLDominates(
MI)) {
1358 assert(
MI.getNumExplicitDefs() == 1);
1361 return Use.getParent() ==
MI.getParent();
1364 all_of(UsesSameBB, VLDominates) &&
1375 <<
" for " <<
MI <<
"\n");
1388void RISCVVLOptimizerImpl::transfer(
const MachineInstr &
MI) {
1390 DemandedVLs[&
MI] = DemandedVL::vlmax();
1392 for (
const MachineOperand &MO : virtual_vec_uses(
MI)) {
1394 DemandedVL Prev = DemandedVLs[
Def];
1395 DemandedVLs[
Def] = DemandedVLs[
Def].max(
1396 *MRI, getMinimumVLForUser(
MI,
MI.getOperandNo(&MO)));
1397 if (DemandedVLs[Def] != Prev)
1398 Worklist.insert(Def);
1406 if (!
ST.hasVInstructions())
1409 TII =
ST.getInstrInfo();
1411 assert(DemandedVLs.empty());
1418 if (
MI.isDebugInstr())
1420 if (virtual_vec_defs(
MI).
empty() && virtual_vec_uses(
MI).
empty())
1422 Worklist.insert(&
MI);
1426 while (!Worklist.empty()) {
1427 const MachineInstr *
MI = Worklist.front();
1428 Worklist.remove(
MI);
1434 bool MadeChange =
false;
1435 for (
auto &[
MI, VL] : DemandedVLs) {
1439 if (!tryReduceVL(*
const_cast<MachineInstr *
>(
MI), VL.VL))
1444 DemandedVLs.clear();
1448bool RISCVVLOptimizerLegacy::runOnMachineFunction(
MachineFunction &MF) {
1452 auto *MDT = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
1453 return RISCVVLOptimizerImpl(MDT).run(MF);
1460 bool Changed = RISCVVLOptimizerImpl(MDT).run(MF);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
const HexagonInstrInfo * TII
static bool isCandidate(const MachineInstr *MI, Register &DefedReg, Register FrameReg)
Register const TargetRegisterInfo * TRI
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
static DemandedVL halfVL(DemandedVL MinimumVL, bool Ceil=false)
#define VSOXSEG_CASES(EEW)
static unsigned getIntegerExtensionOperandEEW(unsigned Factor, const MachineInstr &MI, unsigned OpIdx)
Dest has EEW=SEW.
static std::pair< unsigned, bool > halfEMUL(std::pair< unsigned, bool > EMUL)
static bool isSegmentedStoreInstr(const MachineInstr &MI)
static std::optional< DemandedVL > getMinimumVLForVSLIDEDOWN_VX(const MachineInstr &MI, unsigned OpIdx, const MachineRegisterInfo *MRI)
Given a vslidedown.vx like:
static bool isVectorOpUsedAsScalarOp(const MachineInstr &MI, unsigned OpIdx)
Return true if operand OpIdx of MI is a vector operand but is used as a scalar operand.
static std::optional< OperandInfo > getOperandInfo(const MachineInstr &MI, unsigned OpIdx)
static DemandedVL doubleVL(DemandedVL MinimumVL)
static std::pair< unsigned, bool > getEMULEqualsEEWDivSEWTimesLMUL(unsigned Log2EEW, const MachineInstr &MI)
Return EMUL = (EEW / SEW) * LMUL where EEW comes from Log2EEW and LMUL and SEW are from the TSFlags o...
#define VSUXSEG_CASES(EEW)
static bool isPhysical(const MachineOperand &MO)
static std::optional< unsigned > getOperandLog2EEW(const MachineInstr &MI, unsigned OpIdx)
static std::pair< unsigned, bool > doubleEMUL(std::pair< unsigned, bool > EMUL)
#define VSSSEG_CASES(EEW)
static bool isTupleInsertInstr(const MachineInstr &MI)
Return true if MI is an instruction used for assembling registers for segmented store instructions,...
Remove Loads Into Fake Uses
This file implements a set that has insertion order iteration characteristics.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
Represents analyses that only rely on functions' control flow.
bool isReachableFromEntry(const NodeT *A) const
isReachableFromEntry - Return true if A is dominated by the entry block of the function containing it...
FunctionPass class - This class is used to implement most global optimizations.
Describe properties that are true of each instruction in the target description file.
This holds information about one operand of a machine instruction, indicating the register class for ...
const uint8_t TSFlags
Configurable target specific flags.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
Analysis pass which computes a MachineDominatorTree.
Analysis pass which computes a MachineDominatorTree.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
bool dominates(const MachineInstr *A, const MachineInstr *B) 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.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
unsigned getOperandNo(const_mop_iterator I) const
Returns the number of the operand iterator I points to.
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
LLVM_ABI unsigned getNumExplicitDefs() const
Returns the number of non-implicit definitions.
const MachineOperand & getOperand(unsigned i) const
MachineOperand class - Representation of each machine instruction operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
LLVM_ABI void ChangeToImmediate(int64_t ImmVal, unsigned TargetFlags=0)
ChangeToImmediate - Replace this operand with a new immediate operand of the specified value.
LLVM_ABI void ChangeToRegister(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isDebug=false)
ChangeToRegister - Replace this operand with a new register operand of the specified value.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
static MachineOperand CreateImm(int64_t Val)
Register getReg() const
getReg - Returns the register number.
LLVM_ABI bool isIdenticalTo(const MachineOperand &Other) const
Returns true if this operand is identical to the specified operand except for liveness related flags ...
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
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 ...
iterator_range< use_instr_iterator > use_instructions(Register Reg) const
const TargetRegisterInfo * getTargetRegisterInfo() const
LLVM_ABI const TargetRegisterClass * constrainRegClass(Register Reg, const TargetRegisterClass *RC, unsigned MinNumRegs=0)
constrainRegClass - Constrain the register class of the specified virtual register to be a common sub...
iterator_range< use_iterator > use_operands(Register Reg) const
This class implements a map that also provides access to all stored values in a deterministic order.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
static bool isSafeToMove(const MachineInstr &From, const MachineBasicBlock::iterator &To)
Return true if moving From down to To won't cause any physical register reads or writes to be clobber...
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
A vector that has set insertion semantics.
void insert_range(Range &&R)
bool empty() const
Determine if the SetVector is empty or not.
bool insert(const value_type &X)
Insert a new element into the SetVector.
value_type pop_back_val()
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
Represent a constant reference to a string, i.e.
TargetInstrInfo - Interface to description of machine instruction set.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
self_iterator getIterator()
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static bool readsPastVL(uint64_t TSFlags)
static bool isTiedPseudo(uint64_t TSFlags)
static RISCVVType::VLMUL getLMul(uint64_t TSFlags)
static unsigned getVLOpNum(const MCInstrDesc &Desc)
static bool hasVLOp(uint64_t TSFlags)
static unsigned getSEWOpNum(const MCInstrDesc &Desc)
static bool elementsDependOnVL(uint64_t TSFlags)
static bool hasSEWOp(uint64_t TSFlags)
static bool isFirstDefTiedToFirstUse(const MCInstrDesc &Desc)
static unsigned getNF(uint8_t TSFlags)
static bool isVRegClass(uint8_t TSFlags)
static RISCVVType::VLMUL getLMul(uint8_t TSFlags)
LLVM_ABI std::pair< unsigned, bool > decodeVLMUL(VLMUL VLMul)
unsigned getRVVMCOpcode(unsigned RVVPseudoOpcode)
static constexpr unsigned RVVBitsPerBlock
static constexpr int64_t VLMaxSentinel
bool isVLKnownLE(const MachineRegisterInfo &MRI, const MachineOperand &LHS, const MachineOperand &RHS)
Given two VL operands, do we know that LHS <= RHS?
NodeAddr< DefNode * > Def
NodeAddr< UseNode * > Use
This is an optimization pass for GlobalISel generic memory operations.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
bool operator!=(uint64_t V1, const APInt &V2)
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
auto reverse(ContainerTy &&C)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
iterator_range< filter_iterator< detail::IterOfRange< RangeT >, PredicateT > > make_filter_range(RangeT &&Range, PredicateT Pred)
Convenience function that takes a range of elements and a predicate, and return a new filter_iterator...
auto post_order(const T &G)
Post-order traversal of a graph.
constexpr NextUseDistance max(NextUseDistance A, NextUseDistance B)
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
iterator_range< pointer_iterator< WrappedIteratorT > > make_pointer_range(RangeT &&Range)
FunctionPass * createRISCVVLOptimizerLegacyPass()
LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
MCRegisterClass TargetRegisterClass