40#define DEBUG_TYPE "riscv-vl-optimizer"
41#define PASS_NAME "RISC-V VL Optimizer"
50 static DemandedVL vlmax() {
57 DemandedVL
max(
const DemandedVL &
X)
const {
62 return DemandedVL::vlmax();
88 DemandedVL getMinimumVLForUser(
const MachineOperand &UserOp)
const;
104 return MO.isReg() && MO.getReg().isVirtual() &&
105 RISCVRegisterInfo::isRVVRegClass(MRI->getRegClass(MO.getReg()));
116 std::optional<std::pair<unsigned, bool>> EMUL;
123 OperandInfo(std::pair<unsigned, bool> EMUL,
unsigned Log2EEW)
124 : EMUL(EMUL), Log2EEW(Log2EEW) {}
126 OperandInfo(
unsigned Log2EEW) : Log2EEW(Log2EEW) {}
128 OperandInfo() =
delete;
132 static bool areCompatible(
const OperandInfo &Def,
const OperandInfo &
User) {
133 if (Def.Log2EEW !=
User.Log2EEW)
135 if (
User.EMUL && Def.EMUL !=
User.EMUL)
147 OS <<
"EMUL: none\n";
148 OS <<
", EEW: " << (1 << Log2EEW);
154char RISCVVLOptimizer::ID = 0;
160 return new RISCVVLOptimizer();
171 const std::optional<OperandInfo> &OI) {
181static std::pair<unsigned, bool>
193 unsigned MISEW = 1 << MILog2SEW;
195 unsigned EEW = 1 << Log2EEW;
198 unsigned Num = EEW, Denom = MISEW;
199 int GCD = MILMULIsFractional ? std::gcd(Num, Denom * MILMUL)
200 : std::gcd(Num * MILMUL, Denom);
201 Num = MILMULIsFractional ? Num / GCD : Num * MILMUL / GCD;
202 Denom = MILMULIsFractional ? Denom * MILMUL / GCD : Denom / GCD;
203 return std::make_pair(Num > Denom ? Num : Denom, Denom > Num);
217 unsigned MISEW = 1 << MILog2SEW;
218 unsigned EEW = MISEW / Factor;
219 unsigned Log2EEW =
Log2_32(EEW);
224#define VSEG_CASES(Prefix, EEW) \
225 RISCV::Prefix##SEG2E##EEW##_V: \
226 case RISCV::Prefix##SEG3E##EEW##_V: \
227 case RISCV::Prefix##SEG4E##EEW##_V: \
228 case RISCV::Prefix##SEG5E##EEW##_V: \
229 case RISCV::Prefix##SEG6E##EEW##_V: \
230 case RISCV::Prefix##SEG7E##EEW##_V: \
231 case RISCV::Prefix##SEG8E##EEW##_V
232#define VSSEG_CASES(EEW) VSEG_CASES(VS, EEW)
233#define VSSSEG_CASES(EEW) VSEG_CASES(VSS, EEW)
234#define VSUXSEG_CASES(EEW) VSEG_CASES(VSUX, I##EEW)
235#define VSOXSEG_CASES(EEW) VSEG_CASES(VSOX, I##EEW)
241 RISCVVPseudosTable::getPseudoInfo(
MI.getOpcode());
242 assert(
RVV &&
"Could not find MI in PseudoTable");
257 Info.RegClass == RISCV::VMV0RegClassID)
262 switch (
RVV->BaseInstr) {
266 case RISCV::VSETIVLI:
288 case RISCV::VLSE16_V:
289 case RISCV::VSSE16_V:
295 case RISCV::VLSE32_V:
296 case RISCV::VSSE32_V:
302 case RISCV::VLSE64_V:
303 case RISCV::VSSE64_V:
311 case RISCV::VLUXEI8_V:
312 case RISCV::VLOXEI8_V:
313 case RISCV::VSUXEI8_V:
314 case RISCV::VSOXEI8_V:
321 case RISCV::VLUXEI16_V:
322 case RISCV::VLOXEI16_V:
323 case RISCV::VSUXEI16_V:
324 case RISCV::VSOXEI16_V:
331 case RISCV::VLUXEI32_V:
332 case RISCV::VLOXEI32_V:
333 case RISCV::VSUXEI32_V:
334 case RISCV::VSOXEI32_V:
341 case RISCV::VLUXEI64_V:
342 case RISCV::VLOXEI64_V:
343 case RISCV::VSUXEI64_V:
344 case RISCV::VSOXEI64_V:
359 case RISCV::VRSUB_VI:
360 case RISCV::VRSUB_VX:
384 case RISCV::VMINU_VV:
385 case RISCV::VMINU_VX:
388 case RISCV::VMAXU_VV:
389 case RISCV::VMAXU_VX:
396 case RISCV::VMULH_VV:
397 case RISCV::VMULH_VX:
398 case RISCV::VMULHU_VV:
399 case RISCV::VMULHU_VX:
400 case RISCV::VMULHSU_VV:
401 case RISCV::VMULHSU_VX:
404 case RISCV::VDIVU_VV:
405 case RISCV::VDIVU_VX:
408 case RISCV::VREMU_VV:
409 case RISCV::VREMU_VX:
414 case RISCV::VMACC_VV:
415 case RISCV::VMACC_VX:
416 case RISCV::VNMSAC_VV:
417 case RISCV::VNMSAC_VX:
418 case RISCV::VMADD_VV:
419 case RISCV::VMADD_VX:
420 case RISCV::VNMSUB_VV:
421 case RISCV::VNMSUB_VX:
426 case RISCV::VMERGE_VIM:
427 case RISCV::VMERGE_VVM:
428 case RISCV::VMERGE_VXM:
429 case RISCV::VADC_VIM:
430 case RISCV::VADC_VVM:
431 case RISCV::VADC_VXM:
432 case RISCV::VSBC_VVM:
433 case RISCV::VSBC_VXM:
442 case RISCV::VSADDU_VI:
443 case RISCV::VSADDU_VV:
444 case RISCV::VSADDU_VX:
445 case RISCV::VSADD_VI:
446 case RISCV::VSADD_VV:
447 case RISCV::VSADD_VX:
448 case RISCV::VSSUBU_VV:
449 case RISCV::VSSUBU_VX:
450 case RISCV::VSSUB_VV:
451 case RISCV::VSSUB_VX:
452 case RISCV::VAADDU_VV:
453 case RISCV::VAADDU_VX:
454 case RISCV::VAADD_VV:
455 case RISCV::VAADD_VX:
456 case RISCV::VASUBU_VV:
457 case RISCV::VASUBU_VX:
458 case RISCV::VASUB_VV:
459 case RISCV::VASUB_VX:
463 case RISCV::VSMUL_VV:
464 case RISCV::VSMUL_VX:
467 case RISCV::VSSRL_VI:
468 case RISCV::VSSRL_VV:
469 case RISCV::VSSRL_VX:
470 case RISCV::VSSRA_VI:
471 case RISCV::VSSRA_VV:
472 case RISCV::VSSRA_VX:
479 case RISCV::VFMV_F_S:
480 case RISCV::VFMV_S_F:
483 case RISCV::VSLIDEUP_VI:
484 case RISCV::VSLIDEUP_VX:
485 case RISCV::VSLIDEDOWN_VI:
486 case RISCV::VSLIDEDOWN_VX:
487 case RISCV::VSLIDE1UP_VX:
488 case RISCV::VFSLIDE1UP_VF:
489 case RISCV::VSLIDE1DOWN_VX:
490 case RISCV::VFSLIDE1DOWN_VF:
493 case RISCV::VRGATHER_VI:
494 case RISCV::VRGATHER_VV:
495 case RISCV::VRGATHER_VX:
499 case RISCV::VFADD_VF:
500 case RISCV::VFADD_VV:
501 case RISCV::VFSUB_VF:
502 case RISCV::VFSUB_VV:
503 case RISCV::VFRSUB_VF:
505 case RISCV::VFMUL_VF:
506 case RISCV::VFMUL_VV:
507 case RISCV::VFDIV_VF:
508 case RISCV::VFDIV_VV:
509 case RISCV::VFRDIV_VF:
511 case RISCV::VFMACC_VV:
512 case RISCV::VFMACC_VF:
513 case RISCV::VFNMACC_VV:
514 case RISCV::VFNMACC_VF:
515 case RISCV::VFMSAC_VV:
516 case RISCV::VFMSAC_VF:
517 case RISCV::VFNMSAC_VV:
518 case RISCV::VFNMSAC_VF:
519 case RISCV::VFMADD_VV:
520 case RISCV::VFMADD_VF:
521 case RISCV::VFNMADD_VV:
522 case RISCV::VFNMADD_VF:
523 case RISCV::VFMSUB_VV:
524 case RISCV::VFMSUB_VF:
525 case RISCV::VFNMSUB_VV:
526 case RISCV::VFNMSUB_VF:
528 case RISCV::VFSQRT_V:
530 case RISCV::VFRSQRT7_V:
532 case RISCV::VFREC7_V:
534 case RISCV::VFMIN_VF:
535 case RISCV::VFMIN_VV:
536 case RISCV::VFMAX_VF:
537 case RISCV::VFMAX_VV:
539 case RISCV::VFSGNJ_VF:
540 case RISCV::VFSGNJ_VV:
541 case RISCV::VFSGNJN_VV:
542 case RISCV::VFSGNJN_VF:
543 case RISCV::VFSGNJX_VF:
544 case RISCV::VFSGNJX_VV:
546 case RISCV::VFCLASS_V:
548 case RISCV::VFMV_V_F:
550 case RISCV::VFCVT_XU_F_V:
551 case RISCV::VFCVT_X_F_V:
552 case RISCV::VFCVT_RTZ_XU_F_V:
553 case RISCV::VFCVT_RTZ_X_F_V:
554 case RISCV::VFCVT_F_XU_V:
555 case RISCV::VFCVT_F_X_V:
557 case RISCV::VFMERGE_VFM:
561 case RISCV::VFIRST_M:
564 case RISCV::VANDN_VV:
565 case RISCV::VANDN_VX:
569 case RISCV::VBREV8_V:
587 case RISCV::VCLMUL_VV:
588 case RISCV::VCLMUL_VX:
590 case RISCV::VCLMULH_VV:
591 case RISCV::VCLMULH_VX:
596 case RISCV::VABDU_VV:
600 case RISCV::VWSLL_VI:
601 case RISCV::VWSLL_VX:
602 case RISCV::VWSLL_VV:
605 case RISCV::VWADDU_VV:
606 case RISCV::VWADDU_VX:
607 case RISCV::VWSUBU_VV:
608 case RISCV::VWSUBU_VX:
609 case RISCV::VWADD_VV:
610 case RISCV::VWADD_VX:
611 case RISCV::VWSUB_VV:
612 case RISCV::VWSUB_VX:
615 case RISCV::VWMUL_VV:
616 case RISCV::VWMUL_VX:
617 case RISCV::VWMULSU_VV:
618 case RISCV::VWMULSU_VX:
619 case RISCV::VWMULU_VV:
620 case RISCV::VWMULU_VX:
626 case RISCV::VWMACCU_VV:
627 case RISCV::VWMACCU_VX:
628 case RISCV::VWMACC_VV:
629 case RISCV::VWMACC_VX:
630 case RISCV::VWMACCSU_VV:
631 case RISCV::VWMACCSU_VX:
632 case RISCV::VWMACCUS_VX:
634 case RISCV::VFWMACC_VF:
635 case RISCV::VFWMACC_VV:
636 case RISCV::VFWNMACC_VF:
637 case RISCV::VFWNMACC_VV:
638 case RISCV::VFWMSAC_VF:
639 case RISCV::VFWMSAC_VV:
640 case RISCV::VFWNMSAC_VF:
641 case RISCV::VFWNMSAC_VV:
642 case RISCV::VFWMACCBF16_VV:
643 case RISCV::VFWMACCBF16_VF:
646 case RISCV::VFWADD_VV:
647 case RISCV::VFWADD_VF:
648 case RISCV::VFWSUB_VV:
649 case RISCV::VFWSUB_VF:
651 case RISCV::VFWMUL_VF:
652 case RISCV::VFWMUL_VV:
654 case RISCV::VFWCVT_XU_F_V:
655 case RISCV::VFWCVT_X_F_V:
656 case RISCV::VFWCVT_RTZ_XU_F_V:
657 case RISCV::VFWCVT_RTZ_X_F_V:
658 case RISCV::VFWCVT_F_XU_V:
659 case RISCV::VFWCVT_F_X_V:
660 case RISCV::VFWCVT_F_F_V:
661 case RISCV::VFWCVTBF16_F_F_V:
663 case RISCV::VWABDA_VV:
664 case RISCV::VWABDAU_VV:
665 return IsMODef ? MILog2SEW + 1 : MILog2SEW;
668 case RISCV::VWADDU_WV:
669 case RISCV::VWADDU_WX:
670 case RISCV::VWSUBU_WV:
671 case RISCV::VWSUBU_WX:
672 case RISCV::VWADD_WV:
673 case RISCV::VWADD_WX:
674 case RISCV::VWSUB_WV:
675 case RISCV::VWSUB_WX:
677 case RISCV::VFWADD_WF:
678 case RISCV::VFWADD_WV:
679 case RISCV::VFWSUB_WF:
680 case RISCV::VFWSUB_WV: {
681 bool IsOp1 = (HasPassthru && !IsTied) ? MO.
getOperandNo() == 2
683 bool TwoTimes = IsMODef || IsOp1;
684 return TwoTimes ? MILog2SEW + 1 : MILog2SEW;
688 case RISCV::VZEXT_VF2:
689 case RISCV::VSEXT_VF2:
691 case RISCV::VZEXT_VF4:
692 case RISCV::VSEXT_VF4:
694 case RISCV::VZEXT_VF8:
695 case RISCV::VSEXT_VF8:
700 case RISCV::VNSRL_WX:
701 case RISCV::VNSRL_WI:
702 case RISCV::VNSRL_WV:
703 case RISCV::VNSRA_WI:
704 case RISCV::VNSRA_WV:
705 case RISCV::VNSRA_WX:
708 case RISCV::VNCLIPU_WI:
709 case RISCV::VNCLIPU_WV:
710 case RISCV::VNCLIPU_WX:
711 case RISCV::VNCLIP_WI:
712 case RISCV::VNCLIP_WV:
713 case RISCV::VNCLIP_WX:
715 case RISCV::VFNCVT_XU_F_W:
716 case RISCV::VFNCVT_X_F_W:
717 case RISCV::VFNCVT_RTZ_XU_F_W:
718 case RISCV::VFNCVT_RTZ_X_F_W:
719 case RISCV::VFNCVT_F_XU_W:
720 case RISCV::VFNCVT_F_X_W:
721 case RISCV::VFNCVT_F_F_W:
722 case RISCV::VFNCVT_ROD_F_F_W:
723 case RISCV::VFNCVTBF16_F_F_W: {
726 bool TwoTimes = IsOp1;
727 return TwoTimes ? MILog2SEW + 1 : MILog2SEW;
739 case RISCV::VMAND_MM:
740 case RISCV::VMNAND_MM:
741 case RISCV::VMANDN_MM:
742 case RISCV::VMXOR_MM:
744 case RISCV::VMNOR_MM:
745 case RISCV::VMORN_MM:
746 case RISCV::VMXNOR_MM:
749 case RISCV::VMSOF_M: {
756 case RISCV::VCOMPRESS_VM:
762 case RISCV::VIOTA_M: {
770 case RISCV::VMSEQ_VI:
771 case RISCV::VMSEQ_VV:
772 case RISCV::VMSEQ_VX:
773 case RISCV::VMSNE_VI:
774 case RISCV::VMSNE_VV:
775 case RISCV::VMSNE_VX:
776 case RISCV::VMSLTU_VV:
777 case RISCV::VMSLTU_VX:
778 case RISCV::VMSLT_VV:
779 case RISCV::VMSLT_VX:
780 case RISCV::VMSLEU_VV:
781 case RISCV::VMSLEU_VI:
782 case RISCV::VMSLEU_VX:
783 case RISCV::VMSLE_VV:
784 case RISCV::VMSLE_VI:
785 case RISCV::VMSLE_VX:
786 case RISCV::VMSGTU_VI:
787 case RISCV::VMSGTU_VX:
788 case RISCV::VMSGT_VI:
789 case RISCV::VMSGT_VX:
792 case RISCV::VMADC_VIM:
793 case RISCV::VMADC_VVM:
794 case RISCV::VMADC_VXM:
795 case RISCV::VMSBC_VVM:
796 case RISCV::VMSBC_VXM:
798 case RISCV::VMADC_VV:
799 case RISCV::VMADC_VI:
800 case RISCV::VMADC_VX:
801 case RISCV::VMSBC_VV:
802 case RISCV::VMSBC_VX:
805 case RISCV::VMFEQ_VF:
806 case RISCV::VMFEQ_VV:
807 case RISCV::VMFNE_VF:
808 case RISCV::VMFNE_VV:
809 case RISCV::VMFLT_VF:
810 case RISCV::VMFLT_VV:
811 case RISCV::VMFLE_VF:
812 case RISCV::VMFLE_VV:
813 case RISCV::VMFGT_VF:
814 case RISCV::VMFGE_VF: {
822 case RISCV::VREDAND_VS:
823 case RISCV::VREDMAX_VS:
824 case RISCV::VREDMAXU_VS:
825 case RISCV::VREDMIN_VS:
826 case RISCV::VREDMINU_VS:
827 case RISCV::VREDOR_VS:
828 case RISCV::VREDSUM_VS:
829 case RISCV::VREDXOR_VS:
831 case RISCV::VFREDMAX_VS:
832 case RISCV::VFREDMIN_VS:
833 case RISCV::VFREDOSUM_VS:
834 case RISCV::VFREDUSUM_VS: {
841 case RISCV::VWREDSUM_VS:
842 case RISCV::VWREDSUMU_VS:
844 case RISCV::VFWREDOSUM_VS:
845 case RISCV::VFWREDUSUM_VS: {
847 return TwoTimes ? MILog2SEW + 1 : MILog2SEW;
852 case RISCV::VRGATHEREI16_VV: {
866 RISCVVPseudosTable::getPseudoInfo(
MI.getOpcode());
867 assert(
RVV &&
"Could not find MI in PseudoTable");
873 switch (
RVV->BaseInstr) {
880 case RISCV::VREDAND_VS:
881 case RISCV::VREDMAX_VS:
882 case RISCV::VREDMAXU_VS:
883 case RISCV::VREDMIN_VS:
884 case RISCV::VREDMINU_VS:
885 case RISCV::VREDOR_VS:
886 case RISCV::VREDSUM_VS:
887 case RISCV::VREDXOR_VS:
888 case RISCV::VWREDSUM_VS:
889 case RISCV::VWREDSUMU_VS:
890 case RISCV::VFWREDOSUM_VS:
891 case RISCV::VFWREDUSUM_VS:
893 return OperandInfo(*Log2EEW);
904bool RISCVVLOptimizer::isSupportedInstr(
const MachineInstr &
MI)
const {
912 assert(!(
MI.getNumExplicitDefs() == 0 && !
MI.mayStore() &&
914 "No defs but elements don't depend on VL?");
918 if (RVVOpc == RISCV::VMV_S_X || RVVOpc == RISCV::VFMV_S_F)
934 RISCVVPseudosTable::getPseudoInfo(
MI->getOpcode());
939 switch (
RVV->BaseInstr) {
941 case RISCV::VREDAND_VS:
942 case RISCV::VREDMAX_VS:
943 case RISCV::VREDMAXU_VS:
944 case RISCV::VREDMIN_VS:
945 case RISCV::VREDMINU_VS:
946 case RISCV::VREDOR_VS:
947 case RISCV::VREDSUM_VS:
948 case RISCV::VREDXOR_VS:
949 case RISCV::VWREDSUM_VS:
950 case RISCV::VWREDSUMU_VS:
951 case RISCV::VFREDMAX_VS:
952 case RISCV::VFREDMIN_VS:
953 case RISCV::VFREDOSUM_VS:
954 case RISCV::VFREDUSUM_VS:
955 case RISCV::VFWREDOSUM_VS:
956 case RISCV::VFWREDUSUM_VS:
959 case RISCV::VFMV_F_S:
966bool RISCVVLOptimizer::isCandidate(
const MachineInstr &
MI)
const {
967 const MCInstrDesc &
Desc =
MI.getDesc();
971 if (
MI.getNumExplicitDefs() != 1)
976 if (!
MI.allImplicitDefsAreDead()) {
977 LLVM_DEBUG(
dbgs() <<
"Not a candidate because has non-dead implicit def\n");
981 if (
MI.mayRaiseFPException()) {
982 LLVM_DEBUG(
dbgs() <<
"Not a candidate because may raise FP exception\n");
986 for (
const MachineMemOperand *MMO :
MI.memoperands()) {
987 if (MMO->isVolatile()) {
988 LLVM_DEBUG(
dbgs() <<
"Not a candidate because contains volatile MMO\n");
993 if (!isSupportedInstr(
MI)) {
994 LLVM_DEBUG(
dbgs() <<
"Not a candidate due to unsupported instruction: "
1001 "Instruction shouldn't be supported if elements depend on VL");
1005 "All supported instructions produce a vector register result");
1007 LLVM_DEBUG(
dbgs() <<
"Found a candidate for VL reduction: " <<
MI <<
"\n");
1022static std::optional<DemandedVL>
1027 return std::nullopt;
1030 return std::nullopt;
1034 return std::nullopt;
1038 return std::nullopt;
1040 if (SlideAmtDef->
getOpcode() != RISCV::ADDI ||
1043 return std::nullopt;
1048RISCVVLOptimizer::getMinimumVLForUser(
const MachineOperand &UserOp)
const {
1049 const MachineInstr &UserMI = *UserOp.
getParent();
1053 return DemandedVLs.lookup(&UserMI);
1058 return DemandedVL::vlmax();
1066 LLVM_DEBUG(
dbgs() <<
" Abort because used by unsafe instruction\n");
1067 return DemandedVL::vlmax();
1071 const MachineOperand &VLOp = UserMI.
getOperand(VLOpNum);
1074 "Did not expect X0 VL");
1083 "instruction with demanded tail\n");
1084 return DemandedVL::vlmax();
1091 LLVM_DEBUG(
dbgs() <<
" Used this operand as a scalar operand\n");
1098 return DemandedVLs.lookup(&UserMI);
1107 if (!
MI.isInsertSubreg())
1121 unsigned SubRegIdx =
MI.getOperand(3).getImm();
1123 assert(!IsFractional &&
"unexpected LMUL for tuple register classes");
1151bool RISCVVLOptimizer::checkUsers(
const MachineInstr &
MI)
const {
1155 SmallSetVector<MachineOperand *, 8> OpWorklist;
1156 SmallPtrSet<const MachineInstr *, 4> PHISeen;
1157 for (
auto &UserOp : MRI->
use_operands(
MI.getOperand(0).getReg()))
1158 OpWorklist.
insert(&UserOp);
1160 while (!OpWorklist.
empty()) {
1162 const MachineInstr &UserMI = *UserOp.
getParent();
1173 LLVM_DEBUG(
dbgs().indent(4) <<
"Peeking through uses of INSERT_SUBREG\n");
1174 for (MachineOperand &UseOp :
1176 const MachineInstr &CandidateMI = *UseOp.getParent();
1184 OpWorklist.
insert(&UseOp);
1189 if (UserMI.
isPHI()) {
1191 if (!PHISeen.
insert(&UserMI).second)
1204 std::optional<OperandInfo> ConsumerInfo =
getOperandInfo(UserOp);
1205 std::optional<OperandInfo> ProducerInfo =
getOperandInfo(
MI.getOperand(0));
1206 if (!ConsumerInfo || !ProducerInfo) {
1207 LLVM_DEBUG(
dbgs() <<
" Abort due to unknown operand information.\n");
1208 LLVM_DEBUG(
dbgs() <<
" ConsumerInfo is: " << ConsumerInfo <<
"\n");
1209 LLVM_DEBUG(
dbgs() <<
" ProducerInfo is: " << ProducerInfo <<
"\n");
1213 if (!OperandInfo::areCompatible(*ProducerInfo, *ConsumerInfo)) {
1216 <<
" Abort due to incompatible information for EMUL or EEW.\n");
1217 LLVM_DEBUG(
dbgs() <<
" ConsumerInfo is: " << ConsumerInfo <<
"\n");
1218 LLVM_DEBUG(
dbgs() <<
" ProducerInfo is: " << ProducerInfo <<
"\n");
1226bool RISCVVLOptimizer::tryReduceVL(MachineInstr &
MI,
1227 MachineOperand CommonVL)
const {
1231 MachineOperand &VLOp =
MI.getOperand(VLOpNum);
1234 "Expected VL to be an Imm or virtual Reg");
1238 if (CommonVL.
isReg()) {
1240 if (RISCVInstrInfo::isFaultOnlyFirstLoad(*VLMI) &&
1252 dbgs() <<
" Abort due to CommonVL == VLOp, no point in reducing.\n");
1256 if (CommonVL.
isImm()) {
1258 << CommonVL.
getImm() <<
" for " <<
MI <<
"\n");
1263 auto VLDominates = [
this, &VLMI](
const MachineInstr &
MI) {
1266 if (!VLDominates(
MI)) {
1267 assert(
MI.getNumExplicitDefs() == 1);
1270 return Use.getParent() ==
MI.getParent();
1273 all_of(UsesSameBB, VLDominates) &&
1284 <<
" for " <<
MI <<
"\n");
1297void RISCVVLOptimizer::transfer(
const MachineInstr &
MI) {
1299 DemandedVLs[&
MI] = DemandedVL::vlmax();
1301 for (
const MachineOperand &MO : virtual_vec_uses(
MI)) {
1303 DemandedVL Prev = DemandedVLs[
Def];
1304 DemandedVLs[
Def] = DemandedVLs[
Def].max(getMinimumVLForUser(MO));
1305 if (DemandedVLs[Def] != Prev)
1306 Worklist.insert(Def);
1310bool RISCVVLOptimizer::runOnMachineFunction(MachineFunction &MF) {
1315 MDT = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
1318 if (!
ST.hasVInstructions())
1321 TII =
ST.getInstrInfo();
1323 assert(DemandedVLs.empty());
1330 if (!
MI.isDebugInstr())
1331 Worklist.insert(&
MI);
1334 while (!Worklist.empty()) {
1335 const MachineInstr *
MI = Worklist.front();
1336 Worklist.remove(
MI);
1342 bool MadeChange =
false;
1343 for (
auto &[
MI, VL] : DemandedVLs) {
1347 if (!tryReduceVL(*
const_cast<MachineInstr *
>(
MI), VL.VL))
1352 DemandedVLs.clear();
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 std::optional< DemandedVL > getMinimumVLForVSLIDEDOWN_VX(const MachineOperand &UserOp, const MachineRegisterInfo *MRI)
Given a vslidedown.vx like:
static unsigned getIntegerExtensionOperandEEW(unsigned Factor, const MachineInstr &MI, const MachineOperand &MO)
Dest has EEW=SEW.
static std::optional< OperandInfo > getOperandInfo(const MachineOperand &MO)
#define VSOXSEG_CASES(EEW)
static bool isSegmentedStoreInstr(const MachineInstr &MI)
static bool isVectorOpUsedAsScalarOp(const MachineOperand &MO)
Return true if MO is a vector operand but is used as a scalar operand.
static std::optional< unsigned > getOperandLog2EEW(const MachineOperand &MO)
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)
#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.
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:
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.
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.
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
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.
LLVM_ABI unsigned getOperandNo() const
Returns the index of this operand in the instruction that it belongs to.
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 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
LLVM_ABI MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
This class implements a map that also provides access to all stored values in a deterministic order.
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...
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)
bool isVLKnownLE(const MachineOperand &LHS, const MachineOperand &RHS)
Given two VL operands, do we know that LHS <= RHS?
unsigned getRVVMCOpcode(unsigned RVVPseudoOpcode)
static constexpr unsigned RVVBitsPerBlock
static constexpr int64_t VLMaxSentinel
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)
FunctionPass * createRISCVVLOptimizerPass()
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.
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)
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