37#define DEBUG_TYPE "riscv-insert-vsetvli"
38#define RISCV_INSERT_VSETVLI_NAME "RISC-V Insert VSETVLI pass"
39#define RISCV_COALESCE_VSETVLI_NAME "RISC-V Coalesce VSETVLI pass"
41STATISTIC(NumInsertedVSETVL,
"Number of VSETVL inst inserted");
42STATISTIC(NumCoalescedVSETVL,
"Number of VSETVL inst coalesced");
56 return LI.getVNInfoBefore(SI);
68 return MI.getOpcode() == RISCV::PseudoVSETVLI ||
69 MI.getOpcode() == RISCV::PseudoVSETVLIX0 ||
70 MI.getOpcode() == RISCV::PseudoVSETIVLI;
76 if (
MI.getOpcode() != RISCV::PseudoVSETVLIX0)
78 assert(RISCV::X0 ==
MI.getOperand(1).getReg());
79 return RISCV::X0 ==
MI.getOperand(0).getReg();
82static bool isFloatScalarMoveOrScalarSplatInstr(
const MachineInstr &
MI) {
107 case RISCV::VFMV_S_F:
118 case RISCV::VFMV_V_F:
127 case RISCV::VSLIDEDOWN_VX:
128 case RISCV::VSLIDEDOWN_VI:
129 case RISCV::VSLIDEUP_VX:
130 case RISCV::VSLIDEUP_VI:
137static std::optional<unsigned> getEEWForLoadStore(
const MachineInstr &
MI) {
147 case RISCV::VLSE16_V:
149 case RISCV::VSSE16_V:
152 case RISCV::VLSE32_V:
154 case RISCV::VSSE32_V:
157 case RISCV::VLSE64_V:
159 case RISCV::VSSE64_V:
165 return MI.getOpcode() == RISCV::ADDI &&
166 MI.getOperand(1).isReg() &&
MI.getOperand(2).isImm() &&
167 MI.getOperand(1).getReg() == RISCV::X0 &&
168 MI.getOperand(2).getImm() != 0;
176 const unsigned Log2SEW =
MI.getOperand(getSEWOpNum(
MI)).getImm();
188 if (!
MI.isRegTiedToUseOperand(0, &UseOpIdx))
196 return UseMO.
getReg() == RISCV::NoRegister || UseMO.
isUndef();
200struct DemandedFields {
205 bool VLZeroness =
false;
209 SEWGreaterThanOrEqual = 2,
211 SEWGreaterThanOrEqualAndLessThan64 =
219 LMULLessThanOrEqualToM1 = 1,
222 bool SEWLMULRatio =
false;
223 bool TailPolicy =
false;
224 bool MaskPolicy =
false;
227 bool usedVTYPE()
const {
228 return SEW ||
LMUL || SEWLMULRatio || TailPolicy || MaskPolicy;
233 return VLAny || VLZeroness;
251 static DemandedFields
all() {
259 void doUnion(
const DemandedFields &
B) {
261 VLZeroness |=
B.VLZeroness;
262 SEW = std::max(SEW,
B.SEW);
263 LMUL = std::max(LMUL,
B.LMUL);
264 SEWLMULRatio |=
B.SEWLMULRatio;
265 TailPolicy |=
B.TailPolicy;
266 MaskPolicy |=
B.MaskPolicy;
269#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
279 OS <<
"VLAny=" << VLAny <<
", ";
280 OS <<
"VLZeroness=" << VLZeroness <<
", ";
286 case SEWGreaterThanOrEqual:
287 OS <<
"SEWGreaterThanOrEqual";
289 case SEWGreaterThanOrEqualAndLessThan64:
290 OS <<
"SEWGreaterThanOrEqualAndLessThan64";
302 case LMULLessThanOrEqualToM1:
303 OS <<
"LMULLessThanOrEqualToM1";
310 OS <<
"SEWLMULRatio=" << SEWLMULRatio <<
", ";
311 OS <<
"TailPolicy=" << TailPolicy <<
", ";
312 OS <<
"MaskPolicy=" << MaskPolicy;
318#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
328 return Fractional || LMul == 1;
335 const DemandedFields &Used) {
337 case DemandedFields::SEWNone:
339 case DemandedFields::SEWEqual:
343 case DemandedFields::SEWGreaterThanOrEqual:
347 case DemandedFields::SEWGreaterThanOrEqualAndLessThan64:
355 case DemandedFields::LMULNone:
357 case DemandedFields::LMULEqual:
361 case DemandedFields::LMULLessThanOrEqualToM1:
367 if (
Used.SEWLMULRatio) {
372 if (Ratio1 != Ratio2)
395 if (
MI.isCall() ||
MI.isInlineAsm() ||
396 MI.readsRegister(RISCV::VL,
nullptr))
398 if (
MI.isCall() ||
MI.isInlineAsm() ||
399 MI.readsRegister(RISCV::VTYPE,
nullptr))
407 !VLOp.isReg() || !VLOp.isUndef())
412 Res.MaskPolicy =
false;
421 if (getEEWForLoadStore(
MI)) {
422 Res.SEW = DemandedFields::SEWNone;
423 Res.LMUL = DemandedFields::LMULNone;
428 Res.TailPolicy =
false;
429 Res.MaskPolicy =
false;
436 if (isMaskRegOp(
MI)) {
437 Res.SEW = DemandedFields::SEWNone;
438 Res.LMUL = DemandedFields::LMULNone;
442 if (isScalarInsertInstr(
MI)) {
443 Res.LMUL = DemandedFields::LMULNone;
444 Res.SEWLMULRatio =
false;
452 if (hasUndefinedPassthru(
MI)) {
453 if (isFloatScalarMoveOrScalarSplatInstr(
MI) && !
ST->hasVInstructionsF64())
454 Res.SEW = DemandedFields::SEWGreaterThanOrEqualAndLessThan64;
456 Res.SEW = DemandedFields::SEWGreaterThanOrEqual;
457 Res.TailPolicy =
false;
462 if (isScalarExtractInstr(
MI)) {
464 Res.LMUL = DemandedFields::LMULNone;
465 Res.SEWLMULRatio =
false;
466 Res.TailPolicy =
false;
467 Res.MaskPolicy =
false;
480 if (isVSlideInstr(
MI) && VLOp.
isImm() && VLOp.
getImm() == 1 &&
481 hasUndefinedPassthru(
MI)) {
483 Res.VLZeroness =
true;
484 Res.LMUL = DemandedFields::LMULLessThanOrEqualToM1;
485 Res.TailPolicy =
false;
494 if (isScalarSplatInstr(
MI) && VLOp.
isImm() && VLOp.
getImm() == 1 &&
495 hasUndefinedPassthru(
MI)) {
496 Res.LMUL = DemandedFields::LMULLessThanOrEqualToM1;
497 Res.SEWLMULRatio =
false;
499 if (isFloatScalarMoveOrScalarSplatInstr(
MI) && !
ST->hasVInstructionsF64())
500 Res.SEW = DemandedFields::SEWGreaterThanOrEqualAndLessThan64;
502 Res.SEW = DemandedFields::SEWGreaterThanOrEqual;
503 Res.TailPolicy =
false;
535 uint8_t TailAgnostic : 1;
536 uint8_t MaskAgnostic : 1;
537 uint8_t SEWLMULRatioOnly : 1;
541 : AVLImm(0), TailAgnostic(
false), MaskAgnostic(
false),
542 SEWLMULRatioOnly(
false) {}
544 static VSETVLIInfo getUnknown() {
551 void setUnknown() { State =
Unknown; }
552 bool isUnknown()
const {
return State ==
Unknown; }
557 AVLRegDef.DefReg = AVLReg;
561 void setAVLImm(
unsigned Imm) {
566 void setAVLVLMAX() { State = AVLIsVLMAX; }
568 bool hasAVLImm()
const {
return State == AVLIsImm; }
569 bool hasAVLReg()
const {
return State == AVLIsReg; }
570 bool hasAVLVLMAX()
const {
return State == AVLIsVLMAX; }
572 assert(hasAVLReg() && AVLRegDef.DefReg.isVirtual());
573 return AVLRegDef.DefReg;
575 unsigned getAVLImm()
const {
579 const VNInfo *getAVLVNInfo()
const {
581 return AVLRegDef.ValNo;
589 if (!LIS || getAVLVNInfo()->isPHIDef())
596 void setAVL(VSETVLIInfo Info) {
598 if (
Info.isUnknown())
600 else if (
Info.hasAVLReg())
601 setAVLRegDef(
Info.getAVLVNInfo(),
Info.getAVLReg());
602 else if (
Info.hasAVLVLMAX())
606 setAVLImm(
Info.getAVLImm());
610 unsigned getSEW()
const {
return SEW; }
612 bool getTailAgnostic()
const {
return TailAgnostic; }
613 bool getMaskAgnostic()
const {
return MaskAgnostic; }
617 return getAVLImm() > 0;
619 if (
auto *
DefMI = getAVLDefMI(LIS))
620 return isNonZeroLoadImmediate(*
DefMI);
627 bool hasEquallyZeroAVL(
const VSETVLIInfo &
Other,
629 if (hasSameAVL(
Other))
631 return (hasNonZeroAVL(LIS) &&
Other.hasNonZeroAVL(LIS));
634 bool hasSameAVLLatticeValue(
const VSETVLIInfo &
Other)
const {
635 if (hasAVLReg() &&
Other.hasAVLReg()) {
637 "we either have intervals or we don't");
639 return getAVLReg() ==
Other.getAVLReg();
640 return getAVLVNInfo()->id ==
Other.getAVLVNInfo()->id &&
641 getAVLReg() ==
Other.getAVLReg();
644 if (hasAVLImm() &&
Other.hasAVLImm())
645 return getAVLImm() ==
Other.getAVLImm();
648 return Other.hasAVLVLMAX() && hasSameVLMAX(
Other);
655 bool hasSameAVL(
const VSETVLIInfo &
Other)
const {
659 if (hasAVLReg() &&
Other.hasAVLReg()) {
661 "we either have intervals or we don't");
665 return hasSameAVLLatticeValue(
Other);
668 void setVTYPE(
unsigned VType) {
670 "Can't set VTYPE for uninitialized or unknown");
678 "Can't set VTYPE for uninitialized or unknown");
689 "Can't encode VTYPE for uninitialized or unknown");
693 bool hasSEWLMULRatioOnly()
const {
return SEWLMULRatioOnly; }
695 bool hasSameVTYPE(
const VSETVLIInfo &
Other)
const {
697 "Can't compare invalid VSETVLIInfos");
699 "Can't compare VTYPE in unknown state");
700 assert(!SEWLMULRatioOnly && !
Other.SEWLMULRatioOnly &&
701 "Can't compare when only LMUL/SEW ratio is valid.");
702 return std::tie(VLMul, SEW, TailAgnostic, MaskAgnostic) ==
709 "Can't use VTYPE for uninitialized or unknown");
717 bool hasSameVLMAX(
const VSETVLIInfo &
Other)
const {
719 "Can't compare invalid VSETVLIInfos");
721 "Can't compare VTYPE in unknown state");
725 bool hasCompatibleVTYPE(
const DemandedFields &Used,
726 const VSETVLIInfo &Require)
const {
727 return areCompatibleVTYPEs(Require.encodeVTYPE(),
encodeVTYPE(), Used);
733 bool isCompatible(
const DemandedFields &Used,
const VSETVLIInfo &Require,
736 "Can't compare invalid VSETVLIInfos");
738 if (isUnknown() || Require.isUnknown())
742 if (SEWLMULRatioOnly || Require.SEWLMULRatioOnly)
745 if (
Used.VLAny && !(hasSameAVL(Require) && hasSameVLMAX(Require)))
748 if (
Used.VLZeroness && !hasEquallyZeroAVL(Require, LIS))
751 return hasCompatibleVTYPE(Used, Require);
757 return !
Other.isValid();
758 if (!
Other.isValid())
763 return Other.isUnknown();
764 if (
Other.isUnknown())
767 if (!hasSameAVLLatticeValue(
Other))
771 if (SEWLMULRatioOnly !=
Other.SEWLMULRatioOnly)
775 if (SEWLMULRatioOnly)
776 return hasSameVLMAX(
Other);
779 return hasSameVTYPE(
Other);
783 return !(*
this ==
Other);
790 if (!
Other.isValid())
798 if (isUnknown() ||
Other.isUnknown())
799 return VSETVLIInfo::getUnknown();
807 if (hasSameAVL(
Other) && hasSameVLMAX(
Other)) {
808 VSETVLIInfo MergeInfo = *
this;
809 MergeInfo.SEWLMULRatioOnly =
true;
814 return VSETVLIInfo::getUnknown();
817#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
829 OS <<
"Uninitialized";
839 <<
"VLMul=" << (
unsigned)VLMul <<
", "
840 <<
"SEW=" << (
unsigned)SEW <<
", "
841 <<
"TailAgnostic=" << (
bool)TailAgnostic <<
", "
842 <<
"MaskAgnostic=" << (
bool)MaskAgnostic <<
", "
843 <<
"SEWLMULRatioOnly=" << (
bool)SEWLMULRatioOnly <<
"}";
848#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
866 bool InQueue =
false;
878 std::vector<BlockData> BlockInfo;
879 std::queue<const MachineBasicBlock *> WorkList;
902 bool needVSETVLI(
const DemandedFields &Used,
const VSETVLIInfo &Require,
903 const VSETVLIInfo &CurInfo)
const;
904 bool needVSETVLIPHI(
const VSETVLIInfo &Require,
908 const VSETVLIInfo &Info,
const VSETVLIInfo &PrevInfo);
910 void transferBefore(VSETVLIInfo &Info,
const MachineInstr &
MI)
const;
911 void transferAfter(VSETVLIInfo &Info,
const MachineInstr &
MI)
const;
913 VSETVLIInfo &Info)
const;
920 const DemandedFields &Used)
const;
925 void forwardVSETVLIAVL(VSETVLIInfo &Info)
const;
930char RISCVInsertVSETVLI::ID = 0;
944void RISCVInsertVSETVLI::forwardVSETVLIAVL(VSETVLIInfo &Info)
const {
945 if (!
Info.hasAVLReg())
950 VSETVLIInfo DefInstrInfo = getInfoForVSETVLI(*
DefMI);
951 if (!DefInstrInfo.hasSameVLMAX(
Info))
953 Info.setAVL(DefInstrInfo);
959RISCVInsertVSETVLI::getInfoForVSETVLI(
const MachineInstr &
MI)
const {
961 if (
MI.getOpcode() == RISCV::PseudoVSETIVLI) {
962 NewInfo.setAVLImm(
MI.getOperand(1).getImm());
964 assert(
MI.getOpcode() == RISCV::PseudoVSETVLI ||
965 MI.getOpcode() == RISCV::PseudoVSETVLIX0);
967 assert((AVLReg != RISCV::X0 ||
MI.getOperand(0).getReg() != RISCV::X0) &&
968 "Can't handle X0, X0 vsetvli yet");
969 if (AVLReg == RISCV::X0)
970 NewInfo.setAVLVLMAX();
971 else if (
MI.getOperand(1).isUndef())
973 NewInfo.setAVLImm(1);
975 VNInfo *VNI = getVNInfoFromReg(AVLReg,
MI, LIS);
976 NewInfo.setAVLRegDef(VNI, AVLReg);
979 NewInfo.setVTYPE(
MI.getOperand(2).getImm());
981 forwardVSETVLIAVL(NewInfo);
986static unsigned computeVLMAX(
unsigned VLEN,
unsigned SEW,
997RISCVInsertVSETVLI::computeInfoForInstr(
const MachineInstr &
MI)
const {
998 VSETVLIInfo InstrInfo;
999 const uint64_t TSFlags =
MI.getDesc().TSFlags;
1001 bool TailAgnostic =
true;
1002 bool MaskAgnostic =
true;
1003 if (!hasUndefinedPassthru(
MI)) {
1005 TailAgnostic =
false;
1006 MaskAgnostic =
false;
1013 "Invalid Policy Value");
1021 TailAgnostic =
true;
1024 MaskAgnostic =
true;
1029 unsigned Log2SEW =
MI.getOperand(getSEWOpNum(
MI)).getImm();
1031 unsigned SEW = Log2SEW ? 1 << Log2SEW : 8;
1042 const unsigned VLMAX = computeVLMAX(
ST->getRealMaxVLen(), SEW, VLMul);
1043 if (
ST->getRealMinVLen() ==
ST->getRealMaxVLen() && VLMAX <= 31)
1044 InstrInfo.setAVLImm(VLMAX);
1046 InstrInfo.setAVLVLMAX();
1049 InstrInfo.setAVLImm(Imm);
1052 InstrInfo.setAVLImm(1);
1055 InstrInfo.setAVLRegDef(VNI, VLOp.
getReg());
1061 InstrInfo.setAVLImm(1);
1064 if (std::optional<unsigned> EEW = getEEWForLoadStore(
MI)) {
1065 assert(SEW == EEW &&
"Initial SEW doesn't match expected EEW");
1068 InstrInfo.setVTYPE(VLMul, SEW, TailAgnostic, MaskAgnostic);
1070 forwardVSETVLIAVL(InstrInfo);
1077 const VSETVLIInfo &Info,
const VSETVLIInfo &PrevInfo) {
1079 ++NumInsertedVSETVL;
1080 if (PrevInfo.isValid() && !PrevInfo.isUnknown()) {
1083 if (
Info.hasSameAVL(PrevInfo) &&
Info.hasSameVLMAX(PrevInfo)) {
1097 if (
Info.hasSameVLMAX(PrevInfo) &&
Info.hasAVLReg()) {
1100 VSETVLIInfo DefInfo = getInfoForVSETVLI(*
DefMI);
1101 if (DefInfo.hasSameAVL(PrevInfo) && DefInfo.hasSameVLMAX(PrevInfo)) {
1115 if (
Info.hasAVLImm()) {
1125 if (
Info.hasAVLVLMAX()) {
1126 Register DestReg =
MRI->createVirtualRegister(&RISCV::GPRRegClass);
1139 MRI->constrainRegClass(AVLReg, &RISCV::GPRNoX0RegClass);
1155 MRI->createVirtualRegister(&RISCV::GPRNoX0RegClass);
1157 if (
Info.getAVLVNInfo()->isPHIDef())
1168 MI->getOperand(1).setReg(AVLCopyReg);
1177bool RISCVInsertVSETVLI::needVSETVLI(
const DemandedFields &Used,
1178 const VSETVLIInfo &Require,
1179 const VSETVLIInfo &CurInfo)
const {
1180 if (!CurInfo.isValid() || CurInfo.isUnknown() || CurInfo.hasSEWLMULRatioOnly())
1183 if (CurInfo.isCompatible(Used, Require, LIS))
1193 DemandedFields &Demanded) {
1194 VSETVLIInfo
Info = NewInfo;
1196 if (!Demanded.LMUL && !Demanded.SEWLMULRatio && PrevInfo.isValid() &&
1197 !PrevInfo.isUnknown()) {
1199 PrevInfo.getSEW(), PrevInfo.getVLMUL(),
Info.getSEW()))
1200 Info.setVLMul(*NewVLMul);
1201 Demanded.LMUL = DemandedFields::LMULEqual;
1210void RISCVInsertVSETVLI::transferBefore(VSETVLIInfo &Info,
1215 DemandedFields Demanded = getDemanded(
MI, ST);
1217 const VSETVLIInfo NewInfo = computeInfoForInstr(
MI);
1218 assert(NewInfo.isValid() && !NewInfo.isUnknown());
1219 if (
Info.isValid() && !needVSETVLI(Demanded, NewInfo, Info))
1222 const VSETVLIInfo PrevInfo =
Info;
1223 if (!
Info.isValid() ||
Info.isUnknown())
1226 const VSETVLIInfo IncomingInfo =
adjustIncoming(PrevInfo, NewInfo, Demanded);
1235 bool EquallyZero = IncomingInfo.hasEquallyZeroAVL(PrevInfo, LIS) &&
1236 IncomingInfo.hasSameVLMAX(PrevInfo);
1237 if (Demanded.VLAny || (Demanded.VLZeroness && !EquallyZero))
1238 Info.setAVL(IncomingInfo);
1241 ((Demanded.LMUL || Demanded.SEWLMULRatio) ? IncomingInfo : Info)
1243 ((Demanded.SEW || Demanded.SEWLMULRatio) ? IncomingInfo : Info).getSEW(),
1246 (Demanded.TailPolicy ? IncomingInfo : Info).getTailAgnostic() ||
1247 IncomingInfo.getTailAgnostic(),
1248 (Demanded.MaskPolicy ? IncomingInfo : Info).getMaskAgnostic() ||
1249 IncomingInfo.getMaskAgnostic());
1253 if (
Info.hasSEWLMULRatioOnly()) {
1254 VSETVLIInfo RatiolessInfo = IncomingInfo;
1255 RatiolessInfo.setAVL(Info);
1256 Info = RatiolessInfo;
1263void RISCVInsertVSETVLI::transferAfter(VSETVLIInfo &Info,
1265 if (isVectorConfigInstr(
MI)) {
1266 Info = getInfoForVSETVLI(
MI);
1272 assert(
MI.getOperand(1).getReg().isVirtual());
1278 Info.setAVLRegDef(VNI,
MI.getOperand(1).getReg());
1280 Info.setAVLRegDef(
nullptr,
MI.getOperand(1).getReg());
1286 if (
MI.isCall() ||
MI.isInlineAsm() ||
1287 MI.modifiesRegister(RISCV::VL,
nullptr) ||
1288 MI.modifiesRegister(RISCV::VTYPE,
nullptr))
1289 Info = VSETVLIInfo::getUnknown();
1293 VSETVLIInfo &Info)
const {
1294 bool HadVectorOp =
false;
1298 transferBefore(Info,
MI);
1303 transferAfter(Info,
MI);
1313 BBInfo.InQueue =
false;
1317 VSETVLIInfo InInfo = BBInfo.
Pred;
1320 InInfo.setUnknown();
1323 InInfo = InInfo.
intersect(BlockInfo[
P->getNumber()].Exit);
1327 if (!InInfo.isValid())
1331 if (InInfo == BBInfo.
Pred)
1334 BBInfo.
Pred = InInfo;
1336 <<
" changed to " << BBInfo.
Pred <<
"\n");
1342 VSETVLIInfo TmpStatus;
1343 computeVLVTYPEChanges(
MBB, TmpStatus);
1347 if (BBInfo.
Exit == TmpStatus)
1350 BBInfo.
Exit = TmpStatus;
1352 <<
" changed to " << BBInfo.
Exit <<
"\n");
1357 if (!BlockInfo[S->getNumber()].InQueue) {
1358 BlockInfo[S->getNumber()].InQueue =
true;
1366bool RISCVInsertVSETVLI::needVSETVLIPHI(
const VSETVLIInfo &Require,
1368 if (!Require.hasAVLReg())
1375 const VNInfo *Valno = Require.getAVLVNInfo();
1382 const VSETVLIInfo &PBBExit = BlockInfo[PBB->getNumber()].Exit;
1394 VSETVLIInfo DefInfo = getInfoForVSETVLI(*
DefMI);
1395 if (DefInfo != PBBExit)
1401 if (PBBExit.isUnknown() || !PBBExit.hasSameVTYPE(Require))
1414 bool PrefixTransparent =
true;
1416 const VSETVLIInfo PrevInfo = CurInfo;
1417 transferBefore(CurInfo,
MI);
1420 if (isVectorConfigInstr(
MI)) {
1422 assert(
MI.getOperand(3).getReg() == RISCV::VL &&
1423 MI.getOperand(4).getReg() == RISCV::VTYPE &&
1424 "Unexpected operands where VL and VTYPE should be");
1425 MI.getOperand(3).setIsDead(
false);
1426 MI.getOperand(4).setIsDead(
false);
1427 PrefixTransparent =
false;
1432 if (!PrevInfo.isCompatible(DemandedFields::all(), CurInfo, LIS)) {
1440 if (!PrefixTransparent || needVSETVLIPHI(CurInfo,
MBB))
1441 insertVSETVLI(
MBB,
MI,
MI.getDebugLoc(), CurInfo, PrevInfo);
1442 PrefixTransparent =
false;
1451 VLOp.
setReg(RISCV::NoRegister);
1467 if (!
TII->isAddImmediate(*DeadMI, Reg))
1470 DeadMI->eraseFromParent();
1481 if (
MI.isCall() ||
MI.isInlineAsm() ||
1482 MI.modifiesRegister(RISCV::VL,
nullptr) ||
1483 MI.modifiesRegister(RISCV::VTYPE,
nullptr))
1484 PrefixTransparent =
false;
1486 transferAfter(CurInfo,
MI);
1490 if (CurInfo !=
Info.Exit) {
1496 assert(CurInfo ==
Info.Exit &&
"InsertVSETVLI dataflow invariant violated");
1509 VSETVLIInfo AvailableInfo;
1511 const VSETVLIInfo &PredInfo = BlockInfo[
P->getNumber()].Exit;
1512 if (PredInfo.isUnknown()) {
1513 if (UnavailablePred)
1515 UnavailablePred =
P;
1516 }
else if (!AvailableInfo.isValid()) {
1517 AvailableInfo = PredInfo;
1518 }
else if (AvailableInfo != PredInfo) {
1525 if (!UnavailablePred || !AvailableInfo.isValid())
1533 if (AvailableInfo.hasSEWLMULRatioOnly())
1543 if (AvailableInfo.hasAVLReg()) {
1563 VSETVLIInfo CurInfo = AvailableInfo;
1564 int TransitionsRemoved = 0;
1566 const VSETVLIInfo LastInfo = CurInfo;
1567 const VSETVLIInfo LastOldInfo = OldInfo;
1568 transferBefore(CurInfo,
MI);
1569 transferBefore(OldInfo,
MI);
1570 if (CurInfo == LastInfo)
1571 TransitionsRemoved++;
1572 if (LastOldInfo == OldInfo)
1573 TransitionsRemoved--;
1574 transferAfter(CurInfo,
MI);
1575 transferAfter(OldInfo,
MI);
1576 if (CurInfo == OldInfo)
1580 if (CurInfo != OldInfo || TransitionsRemoved <= 0)
1587 auto OldExit = BlockInfo[UnavailablePred->
getNumber()].Exit;
1589 << UnavailablePred->
getName() <<
" with state "
1590 << AvailableInfo <<
"\n");
1591 BlockInfo[UnavailablePred->
getNumber()].Exit = AvailableInfo;
1597 insertVSETVLI(*UnavailablePred, InsertPt,
1599 AvailableInfo, OldExit);
1604bool RISCVInsertVSETVLI::canMutatePriorConfig(
1606 const DemandedFields &Used)
const {
1610 if (!isVLPreservingConfig(
MI)) {
1614 if (
Used.VLZeroness) {
1615 if (isVLPreservingConfig(PrevMI))
1617 if (!getInfoForVSETVLI(PrevMI).hasEquallyZeroAVL(getInfoForVSETVLI(
MI),
1622 auto &AVL =
MI.getOperand(1);
1627 if (AVL.isReg() && AVL.getReg() != RISCV::X0 &&
1628 (!
MRI->hasOneDef(AVL.getReg()) || !PrevAVL.isReg() ||
1629 PrevAVL.getReg() != AVL.getReg()))
1635 auto VType =
MI.getOperand(2).getImm();
1636 return areCompatibleVTYPEs(PriorVType, VType, Used);
1643 DemandedFields
Used;
1649 if (!MO.isReg() || !MO.getReg().isVirtual())
1652 MO.setReg(RISCV::NoRegister);
1658 if (VLOpDef &&
TII->isAddImmediate(*VLOpDef, OldVLReg) &&
1659 MRI->use_nodbg_empty(OldVLReg))
1666 if (!isVectorConfigInstr(
MI)) {
1667 Used.doUnion(getDemanded(
MI, ST));
1668 if (
MI.isCall() ||
MI.isInlineAsm() ||
1669 MI.modifiesRegister(RISCV::VL,
nullptr) ||
1670 MI.modifiesRegister(RISCV::VTYPE,
nullptr))
1675 if (!
MI.getOperand(0).isDead())
1679 if (!
Used.usedVL() && !
Used.usedVTYPE()) {
1680 dropAVLUse(
MI.getOperand(1));
1683 MI.eraseFromParent();
1684 NumCoalescedVSETVL++;
1689 if (canMutatePriorConfig(
MI, *NextMI, Used)) {
1690 if (!isVLPreservingConfig(*NextMI)) {
1693 MI.getOperand(0).setReg(DefReg);
1694 MI.getOperand(0).setIsDead(
false);
1704 DefVNI->
def = MISlot;
1713 dropAVLUse(
MI.getOperand(1));
1728 NumCoalescedVSETVL++;
1733 Used = getDemanded(
MI, ST);
1738 for (
auto *
MI : ToDelete) {
1743 MI->eraseFromParent();
1751 Register VLOutput =
MI.getOperand(1).getReg();
1753 if (!
MI.getOperand(1).isDead()) {
1755 TII->get(RISCV::PseudoReadVL), VLOutput);
1763 DefVNI->
def = NewDefSI;
1767 MI.getOperand(1).setReg(RISCV::X0);
1775 if (!
ST->hasVInstructions())
1780 TII =
ST->getInstrInfo();
1782 auto *LISWrapper = getAnalysisIfAvailable<LiveIntervalsWrapperPass>();
1783 LIS = LISWrapper ? &LISWrapper->getLIS() :
nullptr;
1785 assert(BlockInfo.empty() &&
"Expect empty block infos");
1788 bool HaveVectorOp =
false;
1792 VSETVLIInfo TmpStatus;
1793 HaveVectorOp |= computeVLVTYPEChanges(
MBB, TmpStatus);
1796 BBInfo.
Exit = TmpStatus;
1798 <<
" is " << BBInfo.
Exit <<
"\n");
1803 if (!HaveVectorOp) {
1812 WorkList.push(&
MBB);
1815 while (!WorkList.empty()) {
1818 computeIncomingVLVTYPE(
MBB);
1839 coalesceVSETVLIs(
MBB);
1847 return HaveVectorOp;
1852 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
static ValueLatticeElement intersect(const ValueLatticeElement &A, const ValueLatticeElement &B)
Combine two sets of facts about the same value into a single set of facts.
uint64_t IntrinsicInst * II
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
#define RISCV_INSERT_VSETVLI_NAME
static VSETVLIInfo adjustIncoming(VSETVLIInfo PrevInfo, VSETVLIInfo NewInfo, DemandedFields &Demanded)
static unsigned getSEWLMULRatio(const MachineInstr &MI)
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 necessarilly 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.
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.
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.