37#define DEBUG_TYPE "riscv-insert-vsetvli"
38#define RISCV_INSERT_VSETVLI_NAME "RISC-V Insert VSETVLI pass"
40STATISTIC(NumInsertedVSETVL,
"Number of VSETVL inst inserted");
41STATISTIC(NumCoalescedVSETVL,
"Number of VSETVL inst coalesced");
45 cl::desc(
"Insert vsetvlis before vmvNr.vs to ensure vtype is valid and "
61 return LI.getVNInfoBefore(SI);
73 return MI.getOpcode() == RISCV::PseudoVSETVLI ||
74 MI.getOpcode() == RISCV::PseudoVSETVLIX0 ||
75 MI.getOpcode() == RISCV::PseudoVSETIVLI;
81 if (
MI.getOpcode() != RISCV::PseudoVSETVLIX0)
83 assert(RISCV::X0 ==
MI.getOperand(1).getReg());
84 return RISCV::X0 ==
MI.getOperand(0).getReg();
87static bool isFloatScalarMoveOrScalarSplatInstr(
const MachineInstr &
MI) {
102 case RISCV::VFMV_F_S:
112 case RISCV::VFMV_S_F:
123 case RISCV::VFMV_V_F:
132 case RISCV::VSLIDEDOWN_VX:
133 case RISCV::VSLIDEDOWN_VI:
134 case RISCV::VSLIDEUP_VX:
135 case RISCV::VSLIDEUP_VI:
142static std::optional<unsigned> getEEWForLoadStore(
const MachineInstr &
MI) {
152 case RISCV::VLSE16_V:
154 case RISCV::VSSE16_V:
157 case RISCV::VLSE32_V:
159 case RISCV::VSSE32_V:
162 case RISCV::VLSE64_V:
164 case RISCV::VSSE64_V:
170 return MI.getOpcode() == RISCV::ADDI &&
171 MI.getOperand(1).isReg() &&
MI.getOperand(2).isImm() &&
172 MI.getOperand(1).getReg() == RISCV::X0 &&
173 MI.getOperand(2).getImm() != 0;
181 const unsigned Log2SEW =
MI.getOperand(getSEWOpNum(
MI)).getImm();
193 if (!
MI.isRegTiedToUseOperand(0, &UseOpIdx))
201 return UseMO.
getReg() == RISCV::NoRegister || UseMO.
isUndef();
207 return MI.isCopy() &&
MI.getOperand(0).getReg().isPhysical() &&
209 TRI->getMinimalPhysRegClass(
MI.getOperand(0).getReg()));
213struct DemandedFields {
218 bool VLZeroness =
false;
222 SEWGreaterThanOrEqual = 2,
224 SEWGreaterThanOrEqualAndLessThan64 =
232 LMULLessThanOrEqualToM1 = 1,
235 bool SEWLMULRatio =
false;
236 bool TailPolicy =
false;
237 bool MaskPolicy =
false;
243 bool usedVTYPE()
const {
244 return SEW ||
LMUL || SEWLMULRatio || TailPolicy || MaskPolicy || VILL;
249 return VLAny || VLZeroness;
268 static DemandedFields
all() {
276 void doUnion(
const DemandedFields &
B) {
278 VLZeroness |=
B.VLZeroness;
279 SEW = std::max(SEW,
B.SEW);
280 LMUL = std::max(LMUL,
B.LMUL);
281 SEWLMULRatio |=
B.SEWLMULRatio;
282 TailPolicy |=
B.TailPolicy;
283 MaskPolicy |=
B.MaskPolicy;
287#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
297 OS <<
"VLAny=" << VLAny <<
", ";
298 OS <<
"VLZeroness=" << VLZeroness <<
", ";
304 case SEWGreaterThanOrEqual:
305 OS <<
"SEWGreaterThanOrEqual";
307 case SEWGreaterThanOrEqualAndLessThan64:
308 OS <<
"SEWGreaterThanOrEqualAndLessThan64";
320 case LMULLessThanOrEqualToM1:
321 OS <<
"LMULLessThanOrEqualToM1";
328 OS <<
"SEWLMULRatio=" << SEWLMULRatio <<
", ";
329 OS <<
"TailPolicy=" << TailPolicy <<
", ";
330 OS <<
"MaskPolicy=" << MaskPolicy <<
", ";
331 OS <<
"VILL=" << VILL;
337#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
347 return Fractional || LMul == 1;
354 const DemandedFields &Used) {
356 case DemandedFields::SEWNone:
358 case DemandedFields::SEWEqual:
362 case DemandedFields::SEWGreaterThanOrEqual:
366 case DemandedFields::SEWGreaterThanOrEqualAndLessThan64:
374 case DemandedFields::LMULNone:
376 case DemandedFields::LMULEqual:
380 case DemandedFields::LMULLessThanOrEqualToM1:
386 if (
Used.SEWLMULRatio) {
391 if (Ratio1 != Ratio2)
414 if (
MI.isCall() ||
MI.isInlineAsm() ||
415 MI.readsRegister(RISCV::VL,
nullptr))
417 if (
MI.isCall() ||
MI.isInlineAsm() ||
418 MI.readsRegister(RISCV::VTYPE,
nullptr))
426 !VLOp.isReg() || !VLOp.isUndef())
431 Res.MaskPolicy =
false;
440 if (getEEWForLoadStore(
MI)) {
441 Res.SEW = DemandedFields::SEWNone;
442 Res.LMUL = DemandedFields::LMULNone;
447 Res.TailPolicy =
false;
448 Res.MaskPolicy =
false;
455 if (isMaskRegOp(
MI)) {
456 Res.SEW = DemandedFields::SEWNone;
457 Res.LMUL = DemandedFields::LMULNone;
461 if (isScalarInsertInstr(
MI)) {
462 Res.LMUL = DemandedFields::LMULNone;
463 Res.SEWLMULRatio =
false;
471 if (hasUndefinedPassthru(
MI)) {
472 if (isFloatScalarMoveOrScalarSplatInstr(
MI) && !
ST->hasVInstructionsF64())
473 Res.SEW = DemandedFields::SEWGreaterThanOrEqualAndLessThan64;
475 Res.SEW = DemandedFields::SEWGreaterThanOrEqual;
476 Res.TailPolicy =
false;
481 if (isScalarExtractInstr(
MI)) {
483 Res.LMUL = DemandedFields::LMULNone;
484 Res.SEWLMULRatio =
false;
485 Res.TailPolicy =
false;
486 Res.MaskPolicy =
false;
499 if (isVSlideInstr(
MI) && VLOp.
isImm() && VLOp.
getImm() == 1 &&
500 hasUndefinedPassthru(
MI)) {
502 Res.VLZeroness =
true;
503 Res.LMUL = DemandedFields::LMULLessThanOrEqualToM1;
504 Res.TailPolicy =
false;
513 if (isScalarSplatInstr(
MI) && VLOp.
isImm() && VLOp.
getImm() == 1 &&
514 hasUndefinedPassthru(
MI)) {
515 Res.LMUL = DemandedFields::LMULLessThanOrEqualToM1;
516 Res.SEWLMULRatio =
false;
518 if (isFloatScalarMoveOrScalarSplatInstr(
MI) && !
ST->hasVInstructionsF64())
519 Res.SEW = DemandedFields::SEWGreaterThanOrEqualAndLessThan64;
521 Res.SEW = DemandedFields::SEWGreaterThanOrEqual;
522 Res.TailPolicy =
false;
533 if (isVectorCopy(
ST->getRegisterInfo(),
MI)) {
534 Res.LMUL = DemandedFields::LMULNone;
535 Res.SEW = DemandedFields::SEWNone;
536 Res.SEWLMULRatio =
false;
537 Res.TailPolicy =
false;
538 Res.MaskPolicy =
false;
575 : AVLImm(0), TailAgnostic(
false), MaskAgnostic(
false),
576 SEWLMULRatioOnly(
false) {}
578 static VSETVLIInfo getUnknown() {
585 void setUnknown() { State =
Unknown; }
586 bool isUnknown()
const {
return State ==
Unknown; }
591 AVLRegDef.DefReg = AVLReg;
595 void setAVLImm(
unsigned Imm) {
600 void setAVLVLMAX() { State = AVLIsVLMAX; }
602 bool hasAVLImm()
const {
return State == AVLIsImm; }
603 bool hasAVLReg()
const {
return State == AVLIsReg; }
604 bool hasAVLVLMAX()
const {
return State == AVLIsVLMAX; }
606 assert(hasAVLReg() && AVLRegDef.DefReg.isVirtual());
607 return AVLRegDef.DefReg;
609 unsigned getAVLImm()
const {
613 const VNInfo *getAVLVNInfo()
const {
615 return AVLRegDef.ValNo;
623 if (!LIS || getAVLVNInfo()->isPHIDef())
630 void setAVL(VSETVLIInfo Info) {
632 if (
Info.isUnknown())
634 else if (
Info.hasAVLReg())
635 setAVLRegDef(
Info.getAVLVNInfo(),
Info.getAVLReg());
636 else if (
Info.hasAVLVLMAX())
640 setAVLImm(
Info.getAVLImm());
644 unsigned getSEW()
const {
return SEW; }
646 bool getTailAgnostic()
const {
return TailAgnostic; }
647 bool getMaskAgnostic()
const {
return MaskAgnostic; }
651 return getAVLImm() > 0;
653 if (
auto *
DefMI = getAVLDefMI(LIS))
654 return isNonZeroLoadImmediate(*
DefMI);
661 bool hasEquallyZeroAVL(
const VSETVLIInfo &
Other,
663 if (hasSameAVL(
Other))
665 return (hasNonZeroAVL(LIS) &&
Other.hasNonZeroAVL(LIS));
668 bool hasSameAVLLatticeValue(
const VSETVLIInfo &
Other)
const {
669 if (hasAVLReg() &&
Other.hasAVLReg()) {
671 "we either have intervals or we don't");
673 return getAVLReg() ==
Other.getAVLReg();
674 return getAVLVNInfo()->id ==
Other.getAVLVNInfo()->id &&
675 getAVLReg() ==
Other.getAVLReg();
678 if (hasAVLImm() &&
Other.hasAVLImm())
679 return getAVLImm() ==
Other.getAVLImm();
682 return Other.hasAVLVLMAX() && hasSameVLMAX(
Other);
689 bool hasSameAVL(
const VSETVLIInfo &
Other)
const {
693 if (hasAVLReg() &&
Other.hasAVLReg()) {
695 "we either have intervals or we don't");
699 return hasSameAVLLatticeValue(
Other);
702 void setVTYPE(
unsigned VType) {
704 "Can't set VTYPE for uninitialized or unknown");
712 "Can't set VTYPE for uninitialized or unknown");
723 "Can't encode VTYPE for uninitialized or unknown");
727 bool hasSEWLMULRatioOnly()
const {
return SEWLMULRatioOnly; }
729 bool hasSameVTYPE(
const VSETVLIInfo &
Other)
const {
731 "Can't compare invalid VSETVLIInfos");
733 "Can't compare VTYPE in unknown state");
734 assert(!SEWLMULRatioOnly && !
Other.SEWLMULRatioOnly &&
735 "Can't compare when only LMUL/SEW ratio is valid.");
736 return std::tie(VLMul, SEW, TailAgnostic, MaskAgnostic) ==
743 "Can't use VTYPE for uninitialized or unknown");
751 bool hasSameVLMAX(
const VSETVLIInfo &
Other)
const {
753 "Can't compare invalid VSETVLIInfos");
755 "Can't compare VTYPE in unknown state");
759 bool hasCompatibleVTYPE(
const DemandedFields &Used,
760 const VSETVLIInfo &Require)
const {
761 return areCompatibleVTYPEs(Require.encodeVTYPE(),
encodeVTYPE(), Used);
767 bool isCompatible(
const DemandedFields &Used,
const VSETVLIInfo &Require,
770 "Can't compare invalid VSETVLIInfos");
772 if (isUnknown() || Require.isUnknown())
776 if (SEWLMULRatioOnly || Require.SEWLMULRatioOnly)
779 if (
Used.VLAny && !(hasSameAVL(Require) && hasSameVLMAX(Require)))
782 if (
Used.VLZeroness && !hasEquallyZeroAVL(Require, LIS))
785 return hasCompatibleVTYPE(Used, Require);
791 return !
Other.isValid();
792 if (!
Other.isValid())
797 return Other.isUnknown();
798 if (
Other.isUnknown())
801 if (!hasSameAVLLatticeValue(
Other))
805 if (SEWLMULRatioOnly !=
Other.SEWLMULRatioOnly)
809 if (SEWLMULRatioOnly)
810 return hasSameVLMAX(
Other);
813 return hasSameVTYPE(
Other);
817 return !(*
this ==
Other);
824 if (!
Other.isValid())
832 if (isUnknown() ||
Other.isUnknown())
833 return VSETVLIInfo::getUnknown();
841 if (hasSameAVL(
Other) && hasSameVLMAX(
Other)) {
842 VSETVLIInfo MergeInfo = *
this;
843 MergeInfo.SEWLMULRatioOnly =
true;
848 return VSETVLIInfo::getUnknown();
851#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
863 OS <<
"Uninitialized";
873 <<
"VLMul=" << (
unsigned)VLMul <<
", "
874 <<
"SEW=" << (
unsigned)SEW <<
", "
875 <<
"TailAgnostic=" << (
bool)TailAgnostic <<
", "
876 <<
"MaskAgnostic=" << (
bool)MaskAgnostic <<
", "
877 <<
"SEWLMULRatioOnly=" << (
bool)SEWLMULRatioOnly <<
"}";
882#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
900 bool InQueue =
false;
912 std::vector<BlockData> BlockInfo;
913 std::queue<const MachineBasicBlock *> WorkList;
936 bool needVSETVLI(
const DemandedFields &Used,
const VSETVLIInfo &Require,
937 const VSETVLIInfo &CurInfo)
const;
938 bool needVSETVLIPHI(
const VSETVLIInfo &Require,
942 const VSETVLIInfo &Info,
const VSETVLIInfo &PrevInfo);
944 void transferBefore(VSETVLIInfo &Info,
const MachineInstr &
MI)
const;
945 void transferAfter(VSETVLIInfo &Info,
const MachineInstr &
MI)
const;
947 VSETVLIInfo &Info)
const;
954 const DemandedFields &Used)
const;
959 void forwardVSETVLIAVL(VSETVLIInfo &Info)
const;
964char RISCVInsertVSETVLI::ID = 0;
978void RISCVInsertVSETVLI::forwardVSETVLIAVL(VSETVLIInfo &Info)
const {
979 if (!
Info.hasAVLReg())
984 VSETVLIInfo DefInstrInfo = getInfoForVSETVLI(*
DefMI);
985 if (!DefInstrInfo.hasSameVLMAX(
Info))
987 Info.setAVL(DefInstrInfo);
993RISCVInsertVSETVLI::getInfoForVSETVLI(
const MachineInstr &
MI)
const {
995 if (
MI.getOpcode() == RISCV::PseudoVSETIVLI) {
996 NewInfo.setAVLImm(
MI.getOperand(1).getImm());
998 assert(
MI.getOpcode() == RISCV::PseudoVSETVLI ||
999 MI.getOpcode() == RISCV::PseudoVSETVLIX0);
1001 assert((AVLReg != RISCV::X0 ||
MI.getOperand(0).getReg() != RISCV::X0) &&
1002 "Can't handle X0, X0 vsetvli yet");
1003 if (AVLReg == RISCV::X0)
1004 NewInfo.setAVLVLMAX();
1005 else if (
MI.getOperand(1).isUndef())
1007 NewInfo.setAVLImm(1);
1009 VNInfo *VNI = getVNInfoFromReg(AVLReg,
MI, LIS);
1010 NewInfo.setAVLRegDef(VNI, AVLReg);
1013 NewInfo.setVTYPE(
MI.getOperand(2).getImm());
1015 forwardVSETVLIAVL(NewInfo);
1020static unsigned computeVLMAX(
unsigned VLEN,
unsigned SEW,
1031RISCVInsertVSETVLI::computeInfoForInstr(
const MachineInstr &
MI)
const {
1032 VSETVLIInfo InstrInfo;
1033 const uint64_t TSFlags =
MI.getDesc().TSFlags;
1035 bool TailAgnostic =
true;
1036 bool MaskAgnostic =
true;
1037 if (!hasUndefinedPassthru(
MI)) {
1039 TailAgnostic =
false;
1040 MaskAgnostic =
false;
1047 "Invalid Policy Value");
1055 TailAgnostic =
true;
1058 MaskAgnostic =
true;
1063 unsigned Log2SEW =
MI.getOperand(getSEWOpNum(
MI)).getImm();
1065 unsigned SEW = Log2SEW ? 1 << Log2SEW : 8;
1076 const unsigned VLMAX = computeVLMAX(
ST->getRealMaxVLen(), SEW, VLMul);
1077 if (
ST->getRealMinVLen() ==
ST->getRealMaxVLen() && VLMAX <= 31)
1078 InstrInfo.setAVLImm(VLMAX);
1080 InstrInfo.setAVLVLMAX();
1083 InstrInfo.setAVLImm(Imm);
1086 InstrInfo.setAVLImm(1);
1089 InstrInfo.setAVLRegDef(VNI, VLOp.
getReg());
1095 InstrInfo.setAVLImm(1);
1098 if (std::optional<unsigned> EEW = getEEWForLoadStore(
MI)) {
1099 assert(SEW == EEW &&
"Initial SEW doesn't match expected EEW");
1102 InstrInfo.setVTYPE(VLMul, SEW, TailAgnostic, MaskAgnostic);
1104 forwardVSETVLIAVL(InstrInfo);
1111 const VSETVLIInfo &Info,
const VSETVLIInfo &PrevInfo) {
1113 ++NumInsertedVSETVL;
1114 if (PrevInfo.isValid() && !PrevInfo.isUnknown()) {
1117 if (
Info.hasSameAVL(PrevInfo) &&
Info.hasSameVLMAX(PrevInfo)) {
1131 if (
Info.hasSameVLMAX(PrevInfo) &&
Info.hasAVLReg()) {
1134 VSETVLIInfo DefInfo = getInfoForVSETVLI(*
DefMI);
1135 if (DefInfo.hasSameAVL(PrevInfo) && DefInfo.hasSameVLMAX(PrevInfo)) {
1149 if (
Info.hasAVLImm()) {
1159 if (
Info.hasAVLVLMAX()) {
1160 Register DestReg =
MRI->createVirtualRegister(&RISCV::GPRRegClass);
1173 MRI->constrainRegClass(AVLReg, &RISCV::GPRNoX0RegClass);
1189 MRI->createVirtualRegister(&RISCV::GPRNoX0RegClass);
1191 if (
Info.getAVLVNInfo()->isPHIDef())
1202 MI->getOperand(1).setReg(AVLCopyReg);
1211bool RISCVInsertVSETVLI::needVSETVLI(
const DemandedFields &Used,
1212 const VSETVLIInfo &Require,
1213 const VSETVLIInfo &CurInfo)
const {
1214 if (!CurInfo.isValid() || CurInfo.isUnknown() || CurInfo.hasSEWLMULRatioOnly())
1217 if (CurInfo.isCompatible(Used, Require, LIS))
1227 DemandedFields &Demanded) {
1228 VSETVLIInfo
Info = NewInfo;
1230 if (!Demanded.LMUL && !Demanded.SEWLMULRatio && PrevInfo.isValid() &&
1231 !PrevInfo.isUnknown()) {
1233 PrevInfo.getSEW(), PrevInfo.getVLMUL(),
Info.getSEW()))
1234 Info.setVLMul(*NewVLMul);
1235 Demanded.LMUL = DemandedFields::LMULEqual;
1244void RISCVInsertVSETVLI::transferBefore(VSETVLIInfo &Info,
1246 if (isVectorCopy(
ST->getRegisterInfo(),
MI) &&
1247 (
Info.isUnknown() || !
Info.isValid() ||
Info.hasSEWLMULRatioOnly())) {
1250 VSETVLIInfo NewInfo;
1251 NewInfo.setAVLImm(1);
1252 NewInfo.setVTYPE(RISCVII::VLMUL::LMUL_1, 8,
true,
1261 DemandedFields Demanded = getDemanded(
MI, ST);
1263 const VSETVLIInfo NewInfo = computeInfoForInstr(
MI);
1264 assert(NewInfo.isValid() && !NewInfo.isUnknown());
1265 if (
Info.isValid() && !needVSETVLI(Demanded, NewInfo, Info))
1268 const VSETVLIInfo PrevInfo =
Info;
1269 if (!
Info.isValid() ||
Info.isUnknown())
1272 const VSETVLIInfo IncomingInfo =
adjustIncoming(PrevInfo, NewInfo, Demanded);
1281 bool EquallyZero = IncomingInfo.hasEquallyZeroAVL(PrevInfo, LIS) &&
1282 IncomingInfo.hasSameVLMAX(PrevInfo);
1283 if (Demanded.VLAny || (Demanded.VLZeroness && !EquallyZero))
1284 Info.setAVL(IncomingInfo);
1287 ((Demanded.LMUL || Demanded.SEWLMULRatio) ? IncomingInfo : Info)
1289 ((Demanded.SEW || Demanded.SEWLMULRatio) ? IncomingInfo : Info).getSEW(),
1292 (Demanded.TailPolicy ? IncomingInfo : Info).getTailAgnostic() ||
1293 IncomingInfo.getTailAgnostic(),
1294 (Demanded.MaskPolicy ? IncomingInfo : Info).getMaskAgnostic() ||
1295 IncomingInfo.getMaskAgnostic());
1299 if (
Info.hasSEWLMULRatioOnly()) {
1300 VSETVLIInfo RatiolessInfo = IncomingInfo;
1301 RatiolessInfo.setAVL(Info);
1302 Info = RatiolessInfo;
1309void RISCVInsertVSETVLI::transferAfter(VSETVLIInfo &Info,
1311 if (isVectorConfigInstr(
MI)) {
1312 Info = getInfoForVSETVLI(
MI);
1318 assert(
MI.getOperand(1).getReg().isVirtual());
1324 Info.setAVLRegDef(VNI,
MI.getOperand(1).getReg());
1326 Info.setAVLRegDef(
nullptr,
MI.getOperand(1).getReg());
1332 if (
MI.isCall() ||
MI.isInlineAsm() ||
1333 MI.modifiesRegister(RISCV::VL,
nullptr) ||
1334 MI.modifiesRegister(RISCV::VTYPE,
nullptr))
1335 Info = VSETVLIInfo::getUnknown();
1339 VSETVLIInfo &Info)
const {
1340 bool HadVectorOp =
false;
1344 transferBefore(Info,
MI);
1347 isVectorCopy(
ST->getRegisterInfo(),
MI))
1350 transferAfter(Info,
MI);
1360 BBInfo.InQueue =
false;
1364 VSETVLIInfo InInfo = BBInfo.
Pred;
1367 InInfo.setUnknown();
1370 InInfo = InInfo.
intersect(BlockInfo[
P->getNumber()].Exit);
1374 if (!InInfo.isValid())
1378 if (InInfo == BBInfo.
Pred)
1381 BBInfo.
Pred = InInfo;
1383 <<
" changed to " << BBInfo.
Pred <<
"\n");
1389 VSETVLIInfo TmpStatus;
1390 computeVLVTYPEChanges(
MBB, TmpStatus);
1394 if (BBInfo.
Exit == TmpStatus)
1397 BBInfo.
Exit = TmpStatus;
1399 <<
" changed to " << BBInfo.
Exit <<
"\n");
1404 if (!BlockInfo[S->getNumber()].InQueue) {
1405 BlockInfo[S->getNumber()].InQueue =
true;
1413bool RISCVInsertVSETVLI::needVSETVLIPHI(
const VSETVLIInfo &Require,
1415 if (!Require.hasAVLReg())
1422 const VNInfo *Valno = Require.getAVLVNInfo();
1429 const VSETVLIInfo &PBBExit = BlockInfo[PBB->getNumber()].Exit;
1441 VSETVLIInfo DefInfo = getInfoForVSETVLI(*
DefMI);
1442 if (DefInfo != PBBExit)
1448 if (PBBExit.isUnknown() || !PBBExit.hasSameVTYPE(Require))
1461 bool PrefixTransparent =
true;
1463 const VSETVLIInfo PrevInfo = CurInfo;
1464 transferBefore(CurInfo,
MI);
1467 if (isVectorConfigInstr(
MI)) {
1469 assert(
MI.getOperand(3).getReg() == RISCV::VL &&
1470 MI.getOperand(4).getReg() == RISCV::VTYPE &&
1471 "Unexpected operands where VL and VTYPE should be");
1472 MI.getOperand(3).setIsDead(
false);
1473 MI.getOperand(4).setIsDead(
false);
1474 PrefixTransparent =
false;
1478 isVectorCopy(
ST->getRegisterInfo(),
MI)) {
1479 if (!PrevInfo.isCompatible(DemandedFields::all(), CurInfo, LIS)) {
1480 insertVSETVLI(
MBB,
MI,
MI.getDebugLoc(), CurInfo, PrevInfo);
1481 PrefixTransparent =
false;
1489 if (!PrevInfo.isCompatible(DemandedFields::all(), CurInfo, LIS)) {
1497 if (!PrefixTransparent || needVSETVLIPHI(CurInfo,
MBB))
1498 insertVSETVLI(
MBB,
MI,
MI.getDebugLoc(), CurInfo, PrevInfo);
1499 PrefixTransparent =
false;
1508 VLOp.
setReg(RISCV::NoRegister);
1524 if (!
TII->isAddImmediate(*DeadMI, Reg))
1527 DeadMI->eraseFromParent();
1538 if (
MI.isCall() ||
MI.isInlineAsm() ||
1539 MI.modifiesRegister(RISCV::VL,
nullptr) ||
1540 MI.modifiesRegister(RISCV::VTYPE,
nullptr))
1541 PrefixTransparent =
false;
1543 transferAfter(CurInfo,
MI);
1547 if (CurInfo !=
Info.Exit) {
1553 assert(CurInfo ==
Info.Exit &&
"InsertVSETVLI dataflow invariant violated");
1566 VSETVLIInfo AvailableInfo;
1568 const VSETVLIInfo &PredInfo = BlockInfo[
P->getNumber()].Exit;
1569 if (PredInfo.isUnknown()) {
1570 if (UnavailablePred)
1572 UnavailablePred =
P;
1573 }
else if (!AvailableInfo.isValid()) {
1574 AvailableInfo = PredInfo;
1575 }
else if (AvailableInfo != PredInfo) {
1582 if (!UnavailablePred || !AvailableInfo.isValid())
1590 if (AvailableInfo.hasSEWLMULRatioOnly())
1600 if (AvailableInfo.hasAVLReg()) {
1620 VSETVLIInfo CurInfo = AvailableInfo;
1621 int TransitionsRemoved = 0;
1623 const VSETVLIInfo LastInfo = CurInfo;
1624 const VSETVLIInfo LastOldInfo = OldInfo;
1625 transferBefore(CurInfo,
MI);
1626 transferBefore(OldInfo,
MI);
1627 if (CurInfo == LastInfo)
1628 TransitionsRemoved++;
1629 if (LastOldInfo == OldInfo)
1630 TransitionsRemoved--;
1631 transferAfter(CurInfo,
MI);
1632 transferAfter(OldInfo,
MI);
1633 if (CurInfo == OldInfo)
1637 if (CurInfo != OldInfo || TransitionsRemoved <= 0)
1644 auto OldExit = BlockInfo[UnavailablePred->
getNumber()].Exit;
1646 << UnavailablePred->
getName() <<
" with state "
1647 << AvailableInfo <<
"\n");
1648 BlockInfo[UnavailablePred->
getNumber()].Exit = AvailableInfo;
1654 insertVSETVLI(*UnavailablePred, InsertPt,
1656 AvailableInfo, OldExit);
1661bool RISCVInsertVSETVLI::canMutatePriorConfig(
1663 const DemandedFields &Used)
const {
1667 if (!isVLPreservingConfig(
MI)) {
1671 if (
Used.VLZeroness) {
1672 if (isVLPreservingConfig(PrevMI))
1674 if (!getInfoForVSETVLI(PrevMI).hasEquallyZeroAVL(getInfoForVSETVLI(
MI),
1679 auto &AVL =
MI.getOperand(1);
1683 if (AVL.isReg() && AVL.getReg() != RISCV::X0) {
1684 VNInfo *VNI = getVNInfoFromReg(AVL.getReg(),
MI, LIS);
1685 VNInfo *PrevVNI = getVNInfoFromReg(AVL.getReg(), PrevMI, LIS);
1686 if (!VNI || !PrevVNI || VNI != PrevVNI)
1693 auto VType =
MI.getOperand(2).getImm();
1694 return areCompatibleVTYPEs(PriorVType, VType, Used);
1701 DemandedFields
Used;
1707 if (!MO.isReg() || !MO.getReg().isVirtual())
1710 MO.setReg(RISCV::NoRegister);
1716 if (VLOpDef &&
TII->isAddImmediate(*VLOpDef, OldVLReg) &&
1717 MRI->use_nodbg_empty(OldVLReg))
1724 if (!isVectorConfigInstr(
MI)) {
1725 Used.doUnion(getDemanded(
MI, ST));
1726 if (
MI.isCall() ||
MI.isInlineAsm() ||
1727 MI.modifiesRegister(RISCV::VL,
nullptr) ||
1728 MI.modifiesRegister(RISCV::VTYPE,
nullptr))
1733 if (!
MI.getOperand(0).isDead())
1737 if (!
Used.usedVL() && !
Used.usedVTYPE()) {
1738 dropAVLUse(
MI.getOperand(1));
1741 MI.eraseFromParent();
1742 NumCoalescedVSETVL++;
1747 if (canMutatePriorConfig(
MI, *NextMI, Used)) {
1748 if (!isVLPreservingConfig(*NextMI)) {
1751 MI.getOperand(0).setReg(DefReg);
1752 MI.getOperand(0).setIsDead(
false);
1762 DefVNI->
def = MISlot;
1771 dropAVLUse(
MI.getOperand(1));
1786 NumCoalescedVSETVL++;
1791 Used = getDemanded(
MI, ST);
1796 for (
auto *
MI : ToDelete) {
1801 MI->eraseFromParent();
1809 Register VLOutput =
MI.getOperand(1).getReg();
1811 if (!
MI.getOperand(1).isDead()) {
1813 TII->get(RISCV::PseudoReadVL), VLOutput);
1821 DefVNI->
def = NewDefSI;
1825 MI.getOperand(1).setReg(RISCV::X0);
1833 if (!
ST->hasVInstructions())
1838 TII =
ST->getInstrInfo();
1840 auto *LISWrapper = getAnalysisIfAvailable<LiveIntervalsWrapperPass>();
1841 LIS = LISWrapper ? &LISWrapper->getLIS() :
nullptr;
1843 assert(BlockInfo.empty() &&
"Expect empty block infos");
1846 bool HaveVectorOp =
false;
1850 VSETVLIInfo TmpStatus;
1851 HaveVectorOp |= computeVLVTYPEChanges(
MBB, TmpStatus);
1854 BBInfo.
Exit = TmpStatus;
1856 <<
" is " << BBInfo.
Exit <<
"\n");
1861 if (!HaveVectorOp) {
1870 WorkList.push(&
MBB);
1873 while (!WorkList.empty()) {
1876 computeIncomingVLVTYPE(
MBB);
1897 coalesceVSETVLIs(
MBB);
1905 return HaveVectorOp;
1910 return new RISCVInsertVSETVLI();
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder MachineInstrBuilder & DefMI
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Analysis containing CSE Info
#define LLVM_ATTRIBUTE_USED
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
static RegisterPass< DebugifyFunctionPass > DF("debugify-function", "Attach debug info to a function")
std::optional< std::vector< StOtherPiece > > Other
const HexagonInstrInfo * TII
unsigned const TargetRegisterInfo * TRI
static Interval intersect(const Interval &I1, const Interval &I2)
uint64_t IntrinsicInst * II
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
static cl::opt< bool > EnsureWholeVectorRegisterMoveValidVTYPE(DEBUG_TYPE "-whole-vector-register-move-valid-vtype", cl::Hidden, cl::desc("Insert vsetvlis before vmvNr.vs to ensure vtype is valid and " "vill is cleared"), cl::init(true))
#define RISCV_INSERT_VSETVLI_NAME
static VSETVLIInfo adjustIncoming(VSETVLIInfo PrevInfo, VSETVLIInfo NewInfo, DemandedFields &Demanded)
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Represent the analysis usage information of a pass.
AnalysisUsage & addUsedIfAvailable()
Add the specified Pass class to the set of analyses used by this pass.
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
void setPreservesCFG()
This function should be called by the pass, iff they do not:
This class represents an Operation in the Expression.
FunctionPass class - This class is used to implement most global optimizations.
LiveInterval - This class represents the liveness of a register, or stack slot.
void setWeight(float Value)
MachineInstr * getInstructionFromIndex(SlotIndex index) const
Returns the instruction associated with the given index.
SlotIndex InsertMachineInstrInMaps(MachineInstr &MI)
SlotIndexes * getSlotIndexes() const
SlotIndex getInstructionIndex(const MachineInstr &Instr) const
Returns the base index of the given instruction.
void RemoveMachineInstrFromMaps(MachineInstr &MI)
SlotIndex getMBBEndIdx(const MachineBasicBlock *mbb) const
Return the last index in the given basic block.
LiveInterval & getInterval(Register Reg)
void removeInterval(Register Reg)
Interval removal.
bool shrinkToUses(LiveInterval *li, SmallVectorImpl< MachineInstr * > *dead=nullptr)
After removing some uses of a register, shrink its live range to just the remaining uses.
void extendToIndices(LiveRange &LR, ArrayRef< SlotIndex > Indices, ArrayRef< SlotIndex > Undefs)
Extend the live range LR to reach all points in Indices.
void splitSeparateComponents(LiveInterval &LI, SmallVectorImpl< LiveInterval * > &SplitLIs)
Split separate components in LiveInterval LI into separate intervals.
MachineBasicBlock * getMBBFromIndex(SlotIndex index) const
LiveInterval & createAndComputeVirtRegInterval(Register Reg)
This class represents the liveness of a register, stack slot, etc.
iterator addSegment(Segment S)
Add the specified Segment to this range, merging segments as appropriate.
bool liveAt(SlotIndex index) const
VNInfo * getVNInfoBefore(SlotIndex Idx) const
getVNInfoBefore - Return the VNInfo that is live up to but not necessarily including Idx,...
SlotIndex beginIndex() const
beginIndex - Return the lowest numbered slot covered.
bool containsOneValue() const
void removeSegment(SlotIndex Start, SlotIndex End, bool RemoveDeadValNo=false)
Remove the specified interval from this live range.
VNInfo * getVNInfoAt(SlotIndex Idx) const
getVNInfoAt - Return the VNInfo that is live at Idx, or NULL.
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
unsigned succ_size() const
iterator getFirstNonPHI()
Returns a pointer to the first instruction in this block that is not a PHINode instruction.
DebugLoc findDebugLoc(instr_iterator MBBI)
Find the next valid DebugLoc starting at MBBI, skipping any debug instructions.
iterator_range< iterator > terminators()
iterator_range< succ_iterator > successors()
instr_iterator getFirstInstrTerminator()
Same getFirstTerminator but it ignores bundles and return an instr_iterator instead.
reverse_iterator rbegin()
iterator_range< pred_iterator > predecessors()
StringRef getName() const
Return the name of the corresponding LLVM basic block, or an empty string.
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.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
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.
unsigned getNumBlockIDs() const
getNumBlockIDs - Return the number of MBB ID's allocated.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
Representation of each machine instruction.
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
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.
void setReg(Register Reg)
Change the register this operand corresponds to.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
void setIsKill(bool Val=true)
Register getReg() const
getReg - Returns the register number.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Wrapper class representing virtual and physical registers.
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
SlotIndex - An opaque wrapper around machine indexes.
SlotIndex getRegSlot(bool EC=false) const
Returns the register use/def slot in the current instruction for a normal or early-clobber def.
SlotIndex getInstructionIndex(const MachineInstr &MI, bool IgnoreBundle=false) const
Returns the base index for the given instruction.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - 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...
VNInfo - Value Number Information.
SlotIndex def
The index of the defining instruction.
bool isPHIDef() const
Returns true if this value is defined by a PHI instruction (or was, PHI instructions may have been el...
LLVM Value Representation.
This class implements an extremely fast bulk output stream that can only output to a stream.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Predicate all(Predicate P0, Predicate P1)
True iff P0 and P1 are true.
static bool usesMaskPolicy(uint64_t TSFlags)
static unsigned getVLOpNum(const MCInstrDesc &Desc)
static bool doesForceTailAgnostic(uint64_t TSFlags)
static VLMUL getLMul(uint64_t TSFlags)
static bool hasVLOp(uint64_t TSFlags)
static bool hasVecPolicyOp(uint64_t TSFlags)
static unsigned getSEWOpNum(const MCInstrDesc &Desc)
static bool hasSEWOp(uint64_t TSFlags)
static bool isTailAgnostic(unsigned VType)
static RISCVII::VLMUL getVLMUL(unsigned VType)
std::pair< unsigned, bool > decodeVLMUL(RISCVII::VLMUL VLMUL)
unsigned getSEWLMULRatio(unsigned SEW, RISCVII::VLMUL VLMul)
static bool isMaskAgnostic(unsigned VType)
static bool isValidSEW(unsigned SEW)
unsigned encodeVTYPE(RISCVII::VLMUL VLMUL, unsigned SEW, bool TailAgnostic, bool MaskAgnostic)
static unsigned getSEW(unsigned VType)
std::optional< RISCVII::VLMUL > getSameRatioLMUL(unsigned SEW, RISCVII::VLMUL VLMUL, unsigned EEW)
unsigned getRVVMCOpcode(unsigned RVVPseudoOpcode)
bool isFaultFirstLoad(const MachineInstr &MI)
static constexpr int64_t VLMaxSentinel
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Define
Register definition.
@ Kill
The last use of a register.
Reg
All possible values of the reg field in the ModR/M byte.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
bool operator!=(uint64_t V1, const APInt &V2)
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionPass * createRISCVInsertVSETVLIPass()
Returns an instance of the Insert VSETVLI pass.
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
char & RISCVInsertVSETVLIID
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.
Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.
Status intersect(const Status &S) const
This represents a simple continuous liveness interval for a value.
static bool isRVVRegClass(const TargetRegisterClass *RC)