39#define GEN_CHECK_COMPRESS_INSTR
40#include "RISCVGenCompressInstEmitter.inc"
42#define GET_INSTRINFO_CTOR_DTOR
43#define GET_INSTRINFO_NAMED_OPS
44#include "RISCVGenInstrInfo.inc"
48 cl::desc(
"Prefer whole register move for vector registers."));
51 "riscv-force-machine-combiner-strategy",
cl::Hidden,
52 cl::desc(
"Force machine combiner to use a specific strategy for machine "
53 "trace metrics evaluation."),
54 cl::init(MachineTraceStrategy::TS_NumStrategies),
57 clEnumValN(MachineTraceStrategy::TS_MinInstrCount,
"min-instr",
58 "MinInstrCount strategy.")));
64#define GET_RISCVVPseudosTable_IMPL
65#include "RISCVGenSearchableTables.inc"
71#define GET_RISCVMaskedPseudosTable_IMPL
72#include "RISCVGenSearchableTables.inc"
90 int &FrameIndex)
const {
97 unsigned &MemBytes)
const {
98 switch (
MI.getOpcode()) {
121 if (
MI.getOperand(1).isFI() &&
MI.getOperand(2).isImm() &&
122 MI.getOperand(2).getImm() == 0) {
123 FrameIndex =
MI.getOperand(1).getIndex();
124 return MI.getOperand(0).getReg();
131 int &FrameIndex)
const {
138 unsigned &MemBytes)
const {
139 switch (
MI.getOpcode()) {
159 if (
MI.getOperand(1).isFI() &&
MI.getOperand(2).isImm() &&
160 MI.getOperand(2).getImm() == 0) {
161 FrameIndex =
MI.getOperand(1).getIndex();
162 return MI.getOperand(0).getReg();
170 return DstReg > SrcReg && (DstReg - SrcReg) < NumRegs;
181 assert(
MBBI->getOpcode() == TargetOpcode::COPY &&
182 "Unexpected COPY instruction.");
186 bool FoundDef =
false;
187 bool FirstVSetVLI =
false;
188 unsigned FirstSEW = 0;
191 if (
MBBI->isMetaInstruction())
194 if (
MBBI->getOpcode() == RISCV::PseudoVSETVLI ||
195 MBBI->getOpcode() == RISCV::PseudoVSETVLIX0 ||
196 MBBI->getOpcode() == RISCV::PseudoVSETIVLI) {
206 unsigned FirstVType =
MBBI->getOperand(2).getImm();
211 if (FirstLMul != LMul)
216 if (
MBBI->getOperand(0).getReg() != RISCV::X0)
218 if (
MBBI->getOperand(1).isImm())
220 if (
MBBI->getOperand(1).getReg() != RISCV::X0)
226 unsigned VType =
MBBI->getOperand(2).getImm();
244 }
else if (
MBBI->isInlineAsm() ||
MBBI->isCall()) {
246 }
else if (
MBBI->getNumDefs()) {
249 if (
MBBI->modifiesRegister(RISCV::VL,
nullptr))
255 if (!MO.isReg() || !MO.isDef())
257 if (!FoundDef &&
TRI->regsOverlap(MO.getReg(), SrcReg)) {
272 if (MO.getReg() != SrcReg)
313 uint16_t SrcEncoding =
TRI->getEncodingValue(SrcReg);
314 uint16_t DstEncoding =
TRI->getEncodingValue(DstReg);
316 assert(!Fractional &&
"It is impossible be fractional lmul here.");
317 unsigned NumRegs = NF * LMulVal;
323 SrcEncoding += NumRegs - 1;
324 DstEncoding += NumRegs - 1;
330 unsigned,
unsigned> {
338 uint16_t Diff = DstEncoding - SrcEncoding;
339 if (
I + 8 <= NumRegs && Diff >= 8 && SrcEncoding % 8 == 7 &&
340 DstEncoding % 8 == 7)
342 RISCV::PseudoVMV_V_V_M8, RISCV::PseudoVMV_V_I_M8};
343 if (
I + 4 <= NumRegs && Diff >= 4 && SrcEncoding % 4 == 3 &&
344 DstEncoding % 4 == 3)
346 RISCV::PseudoVMV_V_V_M4, RISCV::PseudoVMV_V_I_M4};
347 if (
I + 2 <= NumRegs && Diff >= 2 && SrcEncoding % 2 == 1 &&
348 DstEncoding % 2 == 1)
350 RISCV::PseudoVMV_V_V_M2, RISCV::PseudoVMV_V_I_M2};
353 RISCV::PseudoVMV_V_V_M1, RISCV::PseudoVMV_V_I_M1};
358 if (
I + 8 <= NumRegs && SrcEncoding % 8 == 0 && DstEncoding % 8 == 0)
360 RISCV::PseudoVMV_V_V_M8, RISCV::PseudoVMV_V_I_M8};
361 if (
I + 4 <= NumRegs && SrcEncoding % 4 == 0 && DstEncoding % 4 == 0)
363 RISCV::PseudoVMV_V_V_M4, RISCV::PseudoVMV_V_I_M4};
364 if (
I + 2 <= NumRegs && SrcEncoding % 2 == 0 && DstEncoding % 2 == 0)
366 RISCV::PseudoVMV_V_V_M2, RISCV::PseudoVMV_V_I_M2};
369 RISCV::PseudoVMV_V_V_M1, RISCV::PseudoVMV_V_I_M1};
374 if (&RegClass == &RISCV::VRRegClass)
376 return TRI->getMatchingSuperReg(Reg, RISCV::sub_vrm1_0, &RegClass);
378 while (
I != NumRegs) {
383 auto [LMulCopied, RegClass, Opc, VVOpc, VIOpc] =
384 GetCopyInfo(SrcEncoding, DstEncoding);
388 if (LMul == LMulCopied &&
391 if (DefMBBI->getOpcode() == VIOpc)
397 MCRegister ActualSrcReg = FindRegWithEncoding(
398 RegClass, ReversedCopy ? (SrcEncoding - NumCopied + 1) : SrcEncoding);
399 MCRegister ActualDstReg = FindRegWithEncoding(
400 RegClass, ReversedCopy ? (DstEncoding - NumCopied + 1) : DstEncoding);
408 MIB = MIB.add(DefMBBI->getOperand(2));
421 SrcEncoding += (ReversedCopy ? -NumCopied : NumCopied);
422 DstEncoding += (ReversedCopy ? -NumCopied : NumCopied);
433 if (RISCV::GPRRegClass.
contains(DstReg, SrcReg)) {
440 if (RISCV::GPRPairRegClass.
contains(DstReg, SrcReg)) {
443 TRI->getSubReg(DstReg, RISCV::sub_gpr_even))
444 .
addReg(
TRI->getSubReg(SrcReg, RISCV::sub_gpr_even),
448 TRI->getSubReg(DstReg, RISCV::sub_gpr_odd))
449 .
addReg(
TRI->getSubReg(SrcReg, RISCV::sub_gpr_odd),
456 if (RISCV::VCSRRegClass.
contains(SrcReg) &&
457 RISCV::GPRRegClass.
contains(DstReg)) {
459 .
addImm(RISCVSysReg::lookupSysRegByName(
TRI->getName(SrcReg))->Encoding)
464 if (RISCV::FPR16RegClass.
contains(DstReg, SrcReg)) {
466 if (
STI.hasStdExtZfh()) {
467 Opc = RISCV::FSGNJ_H;
470 (
STI.hasStdExtZfhmin() ||
STI.hasStdExtZfbfmin()) &&
471 "Unexpected extensions");
473 DstReg =
TRI->getMatchingSuperReg(DstReg, RISCV::sub_16,
474 &RISCV::FPR32RegClass);
475 SrcReg =
TRI->getMatchingSuperReg(SrcReg, RISCV::sub_16,
476 &RISCV::FPR32RegClass);
477 Opc = RISCV::FSGNJ_S;
485 if (RISCV::FPR32RegClass.
contains(DstReg, SrcReg)) {
492 if (RISCV::FPR64RegClass.
contains(DstReg, SrcReg)) {
499 if (RISCV::FPR32RegClass.
contains(DstReg) &&
500 RISCV::GPRRegClass.
contains(SrcReg)) {
506 if (RISCV::GPRRegClass.
contains(DstReg) &&
507 RISCV::FPR32RegClass.
contains(SrcReg)) {
513 if (RISCV::FPR64RegClass.
contains(DstReg) &&
514 RISCV::GPRRegClass.
contains(SrcReg)) {
521 if (RISCV::GPRRegClass.
contains(DstReg) &&
522 RISCV::FPR64RegClass.
contains(SrcReg)) {
531 &RISCV::VRRegClass, &RISCV::VRM2RegClass, &RISCV::VRM4RegClass,
532 &RISCV::VRM8RegClass, &RISCV::VRN2M1RegClass, &RISCV::VRN2M2RegClass,
533 &RISCV::VRN2M4RegClass, &RISCV::VRN3M1RegClass, &RISCV::VRN3M2RegClass,
534 &RISCV::VRN4M1RegClass, &RISCV::VRN4M2RegClass, &RISCV::VRN5M1RegClass,
535 &RISCV::VRN6M1RegClass, &RISCV::VRN7M1RegClass, &RISCV::VRN8M1RegClass};
536 for (
const auto &RegClass : RVVRegClasses) {
537 if (RegClass->contains(DstReg, SrcReg)) {
548 Register SrcReg,
bool IsKill,
int FI,
556 bool IsScalableVector =
true;
557 if (RISCV::GPRRegClass.hasSubClassEq(RC)) {
558 Opcode =
TRI->getRegSizeInBits(RISCV::GPRRegClass) == 32 ?
559 RISCV::SW : RISCV::SD;
560 IsScalableVector =
false;
561 }
else if (RISCV::GPRPairRegClass.hasSubClassEq(RC)) {
562 Opcode = RISCV::PseudoRV32ZdinxSD;
563 IsScalableVector =
false;
564 }
else if (RISCV::FPR16RegClass.hasSubClassEq(RC)) {
566 IsScalableVector =
false;
567 }
else if (RISCV::FPR32RegClass.hasSubClassEq(RC)) {
569 IsScalableVector =
false;
570 }
else if (RISCV::FPR64RegClass.hasSubClassEq(RC)) {
572 IsScalableVector =
false;
573 }
else if (RISCV::VRRegClass.hasSubClassEq(RC)) {
574 Opcode = RISCV::VS1R_V;
575 }
else if (RISCV::VRM2RegClass.hasSubClassEq(RC)) {
576 Opcode = RISCV::VS2R_V;
577 }
else if (RISCV::VRM4RegClass.hasSubClassEq(RC)) {
578 Opcode = RISCV::VS4R_V;
579 }
else if (RISCV::VRM8RegClass.hasSubClassEq(RC)) {
580 Opcode = RISCV::VS8R_V;
581 }
else if (RISCV::VRN2M1RegClass.hasSubClassEq(RC))
582 Opcode = RISCV::PseudoVSPILL2_M1;
583 else if (RISCV::VRN2M2RegClass.hasSubClassEq(RC))
584 Opcode = RISCV::PseudoVSPILL2_M2;
585 else if (RISCV::VRN2M4RegClass.hasSubClassEq(RC))
586 Opcode = RISCV::PseudoVSPILL2_M4;
587 else if (RISCV::VRN3M1RegClass.hasSubClassEq(RC))
588 Opcode = RISCV::PseudoVSPILL3_M1;
589 else if (RISCV::VRN3M2RegClass.hasSubClassEq(RC))
590 Opcode = RISCV::PseudoVSPILL3_M2;
591 else if (RISCV::VRN4M1RegClass.hasSubClassEq(RC))
592 Opcode = RISCV::PseudoVSPILL4_M1;
593 else if (RISCV::VRN4M2RegClass.hasSubClassEq(RC))
594 Opcode = RISCV::PseudoVSPILL4_M2;
595 else if (RISCV::VRN5M1RegClass.hasSubClassEq(RC))
596 Opcode = RISCV::PseudoVSPILL5_M1;
597 else if (RISCV::VRN6M1RegClass.hasSubClassEq(RC))
598 Opcode = RISCV::PseudoVSPILL6_M1;
599 else if (RISCV::VRN7M1RegClass.hasSubClassEq(RC))
600 Opcode = RISCV::PseudoVSPILL7_M1;
601 else if (RISCV::VRN8M1RegClass.hasSubClassEq(RC))
602 Opcode = RISCV::PseudoVSPILL8_M1;
606 if (IsScalableVector) {
639 bool IsScalableVector =
true;
640 if (RISCV::GPRRegClass.hasSubClassEq(RC)) {
641 Opcode =
TRI->getRegSizeInBits(RISCV::GPRRegClass) == 32 ?
642 RISCV::LW : RISCV::LD;
643 IsScalableVector =
false;
644 }
else if (RISCV::GPRPairRegClass.hasSubClassEq(RC)) {
645 Opcode = RISCV::PseudoRV32ZdinxLD;
646 IsScalableVector =
false;
647 }
else if (RISCV::FPR16RegClass.hasSubClassEq(RC)) {
649 IsScalableVector =
false;
650 }
else if (RISCV::FPR32RegClass.hasSubClassEq(RC)) {
652 IsScalableVector =
false;
653 }
else if (RISCV::FPR64RegClass.hasSubClassEq(RC)) {
655 IsScalableVector =
false;
656 }
else if (RISCV::VRRegClass.hasSubClassEq(RC)) {
657 Opcode = RISCV::VL1RE8_V;
658 }
else if (RISCV::VRM2RegClass.hasSubClassEq(RC)) {
659 Opcode = RISCV::VL2RE8_V;
660 }
else if (RISCV::VRM4RegClass.hasSubClassEq(RC)) {
661 Opcode = RISCV::VL4RE8_V;
662 }
else if (RISCV::VRM8RegClass.hasSubClassEq(RC)) {
663 Opcode = RISCV::VL8RE8_V;
664 }
else if (RISCV::VRN2M1RegClass.hasSubClassEq(RC))
665 Opcode = RISCV::PseudoVRELOAD2_M1;
666 else if (RISCV::VRN2M2RegClass.hasSubClassEq(RC))
667 Opcode = RISCV::PseudoVRELOAD2_M2;
668 else if (RISCV::VRN2M4RegClass.hasSubClassEq(RC))
669 Opcode = RISCV::PseudoVRELOAD2_M4;
670 else if (RISCV::VRN3M1RegClass.hasSubClassEq(RC))
671 Opcode = RISCV::PseudoVRELOAD3_M1;
672 else if (RISCV::VRN3M2RegClass.hasSubClassEq(RC))
673 Opcode = RISCV::PseudoVRELOAD3_M2;
674 else if (RISCV::VRN4M1RegClass.hasSubClassEq(RC))
675 Opcode = RISCV::PseudoVRELOAD4_M1;
676 else if (RISCV::VRN4M2RegClass.hasSubClassEq(RC))
677 Opcode = RISCV::PseudoVRELOAD4_M2;
678 else if (RISCV::VRN5M1RegClass.hasSubClassEq(RC))
679 Opcode = RISCV::PseudoVRELOAD5_M1;
680 else if (RISCV::VRN6M1RegClass.hasSubClassEq(RC))
681 Opcode = RISCV::PseudoVRELOAD6_M1;
682 else if (RISCV::VRN7M1RegClass.hasSubClassEq(RC))
683 Opcode = RISCV::PseudoVRELOAD7_M1;
684 else if (RISCV::VRN8M1RegClass.hasSubClassEq(RC))
685 Opcode = RISCV::PseudoVRELOAD8_M1;
689 if (IsScalableVector) {
723 if (Ops.
size() != 1 || Ops[0] != 1)
727 switch (
MI.getOpcode()) {
734 LoadOpc = RISCV::LWU;
738 LoadOpc = RISCV::LBU;
748 case RISCV::ZEXT_H_RV32:
749 case RISCV::ZEXT_H_RV64:
750 LoadOpc = RISCV::LHU;
760 return BuildMI(*
MI.getParent(), InsertPt,
MI.getDebugLoc(),
get(LoadOpc),
771 bool DstIsDead)
const {
777 if (!isUInt<32>(Val))
781 Val = SignExtend64<32>(Val);
787 bool SrcRenamable =
false;
791 bool LastItem = ++Num == Seq.
size();
796 switch (Inst.getOpndKind()) {
806 .
addReg(SrcReg, SrcRegState)
813 .
addReg(SrcReg, SrcRegState)
814 .
addReg(SrcReg, SrcRegState)
820 .
addReg(SrcReg, SrcRegState)
828 SrcRenamable = DstRenamable;
858 "Unknown conditional branch");
912 bool AllowModify)
const {
918 if (
I ==
MBB.
end() || !isUnpredicatedTerminator(*
I))
924 int NumTerminators = 0;
925 for (
auto J =
I.getReverse(); J !=
MBB.
rend() && isUnpredicatedTerminator(*J);
928 if (J->getDesc().isUnconditionalBranch() ||
929 J->getDesc().isIndirectBranch()) {
936 if (AllowModify && FirstUncondOrIndirectBr !=
MBB.
end()) {
937 while (std::next(FirstUncondOrIndirectBr) !=
MBB.
end()) {
938 std::next(FirstUncondOrIndirectBr)->eraseFromParent();
941 I = FirstUncondOrIndirectBr;
945 if (
I->getDesc().isIndirectBranch())
949 if (
I->isPreISelOpcode())
953 if (NumTerminators > 2)
957 if (NumTerminators == 1 &&
I->getDesc().isUnconditionalBranch()) {
963 if (NumTerminators == 1 &&
I->getDesc().isConditionalBranch()) {
969 if (NumTerminators == 2 && std::prev(
I)->getDesc().isConditionalBranch() &&
970 I->getDesc().isUnconditionalBranch()) {
981 int *BytesRemoved)
const {
988 if (!
I->getDesc().isUnconditionalBranch() &&
989 !
I->getDesc().isConditionalBranch())
995 I->eraseFromParent();
1002 if (!
I->getDesc().isConditionalBranch())
1008 I->eraseFromParent();
1021 assert(
TBB &&
"insertBranch must not be told to insert a fallthrough");
1023 "RISC-V branch conditions have two components!");
1056 assert(RS &&
"RegScavenger required for long branching");
1058 "new block should be inserted for expanding unconditional branch");
1061 "restore block should be inserted for restoring clobbered registers");
1068 if (!isInt<32>(BrOffset))
1070 "Branch offsets outside of the signed 32-bit range not supported");
1075 Register ScratchReg =
MRI.createVirtualRegister(&RISCV::GPRJALRRegClass);
1087 if (TmpGPR != RISCV::NoRegister)
1093 TmpGPR = RISCV::X27;
1096 if (FrameIndex == -1)
1101 TRI->eliminateFrameIndex(std::prev(
MI.getIterator()),
1104 MI.getOperand(1).setMBB(&RestoreBB);
1108 TRI->eliminateFrameIndex(RestoreBB.
back(),
1112 MRI.replaceRegWith(ScratchReg, TmpGPR);
1113 MRI.clearVirtRegs();
1118 assert((
Cond.size() == 3) &&
"Invalid branch condition!");
1158 auto isLoadImm = [](
const MachineInstr *
MI, int64_t &Imm) ->
bool {
1159 if (
MI->getOpcode() == RISCV::ADDI &&
MI->getOperand(1).isReg() &&
1160 MI->getOperand(1).getReg() == RISCV::X0) {
1161 Imm =
MI->getOperand(2).getImm();
1171 return Reg.isVirtual() && isLoadImm(
MRI.getVRegDef(Reg), Imm);
1178 auto searchConst = [&](int64_t C1) ->
Register {
1180 auto DefC1 = std::find_if(++II, E, [&](
const MachineInstr &
I) ->
bool {
1182 return isLoadImm(&
I, Imm) && Imm == C1 &&
1183 I.getOperand(0).getReg().isVirtual();
1186 return DefC1->getOperand(0).getReg();
1191 bool Modify =
false;
1193 if (isFromLoadImm(
LHS, C0) &&
MRI.hasOneUse(
LHS.getReg())) {
1198 if (
Register RegZ = searchConst(C0 + 1)) {
1204 MRI.clearKillFlags(RegZ);
1207 }
else if (isFromLoadImm(
RHS, C0) &&
MRI.hasOneUse(
RHS.getReg())) {
1212 if (
Register RegZ = searchConst(C0 - 1)) {
1218 MRI.clearKillFlags(RegZ);
1232 MI.eraseFromParent();
1239 assert(
MI.getDesc().isBranch() &&
"Unexpected opcode!");
1241 int NumOp =
MI.getNumExplicitOperands();
1242 return MI.getOperand(NumOp - 1).getMBB();
1246 int64_t BrOffset)
const {
1260 return isIntN(13, BrOffset);
1262 case RISCV::PseudoBR:
1263 return isIntN(21, BrOffset);
1264 case RISCV::PseudoJump:
1274 case RISCV::ADD:
return RISCV::PseudoCCADD;
break;
1275 case RISCV::SUB:
return RISCV::PseudoCCSUB;
break;
1276 case RISCV::SLL:
return RISCV::PseudoCCSLL;
break;
1277 case RISCV::SRL:
return RISCV::PseudoCCSRL;
break;
1278 case RISCV::SRA:
return RISCV::PseudoCCSRA;
break;
1279 case RISCV::AND:
return RISCV::PseudoCCAND;
break;
1280 case RISCV::OR:
return RISCV::PseudoCCOR;
break;
1281 case RISCV::XOR:
return RISCV::PseudoCCXOR;
break;
1283 case RISCV::ADDI:
return RISCV::PseudoCCADDI;
break;
1284 case RISCV::SLLI:
return RISCV::PseudoCCSLLI;
break;
1285 case RISCV::SRLI:
return RISCV::PseudoCCSRLI;
break;
1286 case RISCV::SRAI:
return RISCV::PseudoCCSRAI;
break;
1287 case RISCV::ANDI:
return RISCV::PseudoCCANDI;
break;
1288 case RISCV::ORI:
return RISCV::PseudoCCORI;
break;
1289 case RISCV::XORI:
return RISCV::PseudoCCXORI;
break;
1291 case RISCV::ADDW:
return RISCV::PseudoCCADDW;
break;
1292 case RISCV::SUBW:
return RISCV::PseudoCCSUBW;
break;
1293 case RISCV::SLLW:
return RISCV::PseudoCCSLLW;
break;
1294 case RISCV::SRLW:
return RISCV::PseudoCCSRLW;
break;
1295 case RISCV::SRAW:
return RISCV::PseudoCCSRAW;
break;
1297 case RISCV::ADDIW:
return RISCV::PseudoCCADDIW;
break;
1298 case RISCV::SLLIW:
return RISCV::PseudoCCSLLIW;
break;
1299 case RISCV::SRLIW:
return RISCV::PseudoCCSRLIW;
break;
1300 case RISCV::SRAIW:
return RISCV::PseudoCCSRAIW;
break;
1302 case RISCV::ANDN:
return RISCV::PseudoCCANDN;
break;
1303 case RISCV::ORN:
return RISCV::PseudoCCORN;
break;
1304 case RISCV::XNOR:
return RISCV::PseudoCCXNOR;
break;
1307 return RISCV::INSTRUCTION_LIST_END;
1315 if (!Reg.isVirtual())
1317 if (!
MRI.hasOneNonDBGUse(Reg))
1326 if (
MI->getOpcode() == RISCV::ADDI &&
MI->getOperand(1).isReg() &&
1327 MI->getOperand(1).getReg() == RISCV::X0)
1332 if (MO.isFI() || MO.isCPI() || MO.isJTI())
1342 if (MO.getReg().isPhysical() && !
MRI.isConstantPhysReg(MO.getReg()))
1345 bool DontMoveAcrossStores =
true;
1346 if (!
MI->isSafeToMove(
nullptr, DontMoveAcrossStores))
1353 unsigned &TrueOp,
unsigned &FalseOp,
1354 bool &Optimizable)
const {
1355 assert(
MI.getOpcode() == RISCV::PseudoCCMOVGPR &&
1356 "Unknown select instruction");
1366 Cond.push_back(
MI.getOperand(1));
1367 Cond.push_back(
MI.getOperand(2));
1368 Cond.push_back(
MI.getOperand(3));
1370 Optimizable =
STI.hasShortForwardBranchOpt();
1377 bool PreferFalse)
const {
1378 assert(
MI.getOpcode() == RISCV::PseudoCCMOVGPR &&
1379 "Unknown select instruction");
1380 if (!
STI.hasShortForwardBranchOpt())
1386 bool Invert = !
DefMI;
1394 Register DestReg =
MI.getOperand(0).getReg();
1396 if (!
MRI.constrainRegClass(DestReg, PreviousClass))
1400 assert(PredOpc != RISCV::INSTRUCTION_LIST_END &&
"Unexpected opcode!");
1407 NewMI.
add(
MI.getOperand(1));
1408 NewMI.
add(
MI.getOperand(2));
1417 NewMI.
add(FalseReg);
1441 if (
MI.isMetaInstruction())
1444 unsigned Opcode =
MI.getOpcode();
1446 if (Opcode == TargetOpcode::INLINEASM ||
1447 Opcode == TargetOpcode::INLINEASM_BR) {
1450 return getInlineAsmLength(
MI.getOperand(0).getSymbolName(),
1451 *
TM.getMCAsmInfo());
1454 if (!
MI.memoperands_empty()) {
1459 if (ST.hasStdExtCOrZca() && ST.enableRVCHintInstrs()) {
1460 if (isCompressibleInst(
MI,
STI))
1468 if (Opcode == TargetOpcode::BUNDLE)
1469 return getInstBundleLength(
MI);
1471 if (
MI.getParent() &&
MI.getParent()->getParent()) {
1472 if (isCompressibleInst(
MI,
STI))
1477 case TargetOpcode::STACKMAP:
1480 case TargetOpcode::PATCHPOINT:
1483 case TargetOpcode::STATEPOINT: {
1487 return std::max(NumBytes, 8U);
1490 return get(Opcode).getSize();
1494unsigned RISCVInstrInfo::getInstBundleLength(
const MachineInstr &
MI)
const {
1498 while (++
I != E &&
I->isInsideBundle()) {
1499 assert(!
I->isBundle() &&
"No nested bundle!");
1506 const unsigned Opcode =
MI.getOpcode();
1510 case RISCV::FSGNJ_D:
1511 case RISCV::FSGNJ_S:
1512 case RISCV::FSGNJ_H:
1513 case RISCV::FSGNJ_D_INX:
1514 case RISCV::FSGNJ_D_IN32X:
1515 case RISCV::FSGNJ_S_INX:
1516 case RISCV::FSGNJ_H_INX:
1518 return MI.getOperand(1).isReg() &&
MI.getOperand(2).isReg() &&
1519 MI.getOperand(1).getReg() ==
MI.getOperand(2).getReg();
1523 return (
MI.getOperand(1).isReg() &&
1524 MI.getOperand(1).getReg() == RISCV::X0) ||
1525 (
MI.getOperand(2).isImm() &&
MI.getOperand(2).getImm() == 0);
1527 return MI.isAsCheapAsAMove();
1530std::optional<DestSourcePair>
1534 switch (
MI.getOpcode()) {
1539 if (
MI.getOperand(1).isReg() &&
MI.getOperand(2).isImm() &&
1540 MI.getOperand(2).getImm() == 0)
1543 case RISCV::FSGNJ_D:
1544 case RISCV::FSGNJ_S:
1545 case RISCV::FSGNJ_H:
1546 case RISCV::FSGNJ_D_INX:
1547 case RISCV::FSGNJ_D_IN32X:
1548 case RISCV::FSGNJ_S_INX:
1549 case RISCV::FSGNJ_H_INX:
1551 if (
MI.getOperand(1).isReg() &&
MI.getOperand(2).isReg() &&
1552 MI.getOperand(1).getReg() ==
MI.getOperand(2).getReg())
1556 return std::nullopt;
1564 const auto &SchedModel =
STI.getSchedModel();
1565 return (!SchedModel.hasInstrSchedModel() || SchedModel.isOutOfOrder())
1582 RISCV::OpName::frm) < 0;
1584 "New instructions require FRM whereas the old one does not have it");
1591 for (
auto *NewMI : InsInstrs) {
1594 NewMI->getOpcode(), RISCV::OpName::frm)) != NewMI->getNumOperands())
1636bool RISCVInstrInfo::isVectorAssociativeAndCommutative(
const MachineInstr &Inst,
1637 bool Invert)
const {
1638#define OPCODE_LMUL_CASE(OPC) \
1639 case RISCV::OPC##_M1: \
1640 case RISCV::OPC##_M2: \
1641 case RISCV::OPC##_M4: \
1642 case RISCV::OPC##_M8: \
1643 case RISCV::OPC##_MF2: \
1644 case RISCV::OPC##_MF4: \
1645 case RISCV::OPC##_MF8
1647#define OPCODE_LMUL_MASK_CASE(OPC) \
1648 case RISCV::OPC##_M1_MASK: \
1649 case RISCV::OPC##_M2_MASK: \
1650 case RISCV::OPC##_M4_MASK: \
1651 case RISCV::OPC##_M8_MASK: \
1652 case RISCV::OPC##_MF2_MASK: \
1653 case RISCV::OPC##_MF4_MASK: \
1654 case RISCV::OPC##_MF8_MASK
1659 Opcode = *InvOpcode;
1676#undef OPCODE_LMUL_MASK_CASE
1677#undef OPCODE_LMUL_CASE
1680bool RISCVInstrInfo::areRVVInstsReassociable(
const MachineInstr &Root,
1693 auto checkImmOperand = [&](
unsigned OpIdx) {
1697 auto checkRegOperand = [&](
unsigned OpIdx) {
1705 if (!checkRegOperand(1))
1720 bool SeenMI2 =
false;
1730 if (It->modifiesRegister(RISCV::V0,
TRI)) {
1731 Register SrcReg = It->getOperand(1).getReg();
1749 if (MI1VReg != SrcReg)
1758 assert(SeenMI2 &&
"Prev is expected to appear before Root");
1797bool RISCVInstrInfo::hasReassociableVectorSibling(
const MachineInstr &Inst,
1798 bool &Commuted)
const {
1802 "Expect the present of passthrough operand.");
1808 Commuted = !areRVVInstsReassociable(Inst, *MI1) &&
1809 areRVVInstsReassociable(Inst, *MI2);
1813 return areRVVInstsReassociable(Inst, *MI1) &&
1814 (isVectorAssociativeAndCommutative(*MI1) ||
1815 isVectorAssociativeAndCommutative(*MI1,
true)) &&
1822 if (!isVectorAssociativeAndCommutative(Inst) &&
1823 !isVectorAssociativeAndCommutative(Inst,
true))
1835 MI1 =
MRI.getUniqueVRegDef(Op1.
getReg());
1837 MI2 =
MRI.getUniqueVRegDef(Op2.
getReg());
1849 for (
unsigned I = 0;
I < 5; ++
I)
1855 bool &Commuted)
const {
1856 if (isVectorAssociativeAndCommutative(Inst) ||
1857 isVectorAssociativeAndCommutative(Inst,
true))
1858 return hasReassociableVectorSibling(Inst, Commuted);
1864 unsigned OperandIdx = Commuted ? 2 : 1;
1868 int16_t InstFrmOpIdx =
1870 int16_t SiblingFrmOpIdx =
1873 return (InstFrmOpIdx < 0 && SiblingFrmOpIdx < 0) ||
1878 bool Invert)
const {
1879 if (isVectorAssociativeAndCommutative(Inst, Invert))
1887 Opc = *InverseOpcode;
1932std::optional<unsigned>
1934#define RVV_OPC_LMUL_CASE(OPC, INV) \
1935 case RISCV::OPC##_M1: \
1936 return RISCV::INV##_M1; \
1937 case RISCV::OPC##_M2: \
1938 return RISCV::INV##_M2; \
1939 case RISCV::OPC##_M4: \
1940 return RISCV::INV##_M4; \
1941 case RISCV::OPC##_M8: \
1942 return RISCV::INV##_M8; \
1943 case RISCV::OPC##_MF2: \
1944 return RISCV::INV##_MF2; \
1945 case RISCV::OPC##_MF4: \
1946 return RISCV::INV##_MF4; \
1947 case RISCV::OPC##_MF8: \
1948 return RISCV::INV##_MF8
1950#define RVV_OPC_LMUL_MASK_CASE(OPC, INV) \
1951 case RISCV::OPC##_M1_MASK: \
1952 return RISCV::INV##_M1_MASK; \
1953 case RISCV::OPC##_M2_MASK: \
1954 return RISCV::INV##_M2_MASK; \
1955 case RISCV::OPC##_M4_MASK: \
1956 return RISCV::INV##_M4_MASK; \
1957 case RISCV::OPC##_M8_MASK: \
1958 return RISCV::INV##_M8_MASK; \
1959 case RISCV::OPC##_MF2_MASK: \
1960 return RISCV::INV##_MF2_MASK; \
1961 case RISCV::OPC##_MF4_MASK: \
1962 return RISCV::INV##_MF4_MASK; \
1963 case RISCV::OPC##_MF8_MASK: \
1964 return RISCV::INV##_MF8_MASK
1968 return std::nullopt;
1970 return RISCV::FSUB_H;
1972 return RISCV::FSUB_S;
1974 return RISCV::FSUB_D;
1976 return RISCV::FADD_H;
1978 return RISCV::FADD_S;
1980 return RISCV::FADD_D;
1997#undef RVV_OPC_LMUL_MASK_CASE
1998#undef RVV_OPC_LMUL_CASE
2003 bool DoRegPressureReduce) {
2019 if (DoRegPressureReduce && !
MRI.hasOneNonDBGUse(
MI->getOperand(0).getReg()))
2030 bool DoRegPressureReduce) {
2032 bool IsFAdd =
isFADD(Opc);
2033 if (!IsFAdd && !
isFSUB(Opc))
2037 DoRegPressureReduce)) {
2043 DoRegPressureReduce)) {
2053 bool DoRegPressureReduce) {
2061 unsigned CombineOpc) {
2068 if (!
MI ||
MI->getParent() != &
MBB ||
MI->getOpcode() != CombineOpc)
2071 if (!
MRI.hasOneNonDBGUse(
MI->getOperand(0).getReg()))
2082 unsigned OuterShiftAmt) {
2088 if (InnerShiftAmt < OuterShiftAmt || (InnerShiftAmt - OuterShiftAmt) > 3)
2150 bool DoRegPressureReduce)
const {
2159 DoRegPressureReduce);
2167 return RISCV::FMADD_H;
2169 return RISCV::FMADD_S;
2171 return RISCV::FMADD_D;
2216 bool Mul1IsKill = Mul1.
isKill();
2217 bool Mul2IsKill = Mul2.
isKill();
2218 bool AddendIsKill = Addend.
isKill();
2227 BuildMI(*MF, MergedLoc,
TII->get(FusedOpc), DstReg)
2252 assert(OuterShiftAmt != 0 &&
"Unexpected opcode");
2259 assert(InnerShiftAmt >= OuterShiftAmt &&
"Unexpected shift amount");
2262 switch (InnerShiftAmt - OuterShiftAmt) {
2266 InnerOpc = RISCV::ADD;
2269 InnerOpc = RISCV::SH1ADD;
2272 InnerOpc = RISCV::SH2ADD;
2275 InnerOpc = RISCV::SH3ADD;
2283 Register NewVR =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
2293 InstrIdxForVirtReg.
insert(std::make_pair(NewVR, 0));
2310 DelInstrs, InstrIdxForVirtReg);
2338 unsigned OpType = Operand.OperandType;
2343 int64_t Imm = MO.
getImm();
2350#define CASE_OPERAND_UIMM(NUM) \
2351 case RISCVOp::OPERAND_UIMM##NUM: \
2352 Ok = isUInt<NUM>(Imm); \
2366 Ok = isShiftedUInt<1, 1>(Imm);
2369 Ok = isShiftedUInt<5, 2>(Imm);
2372 Ok = isShiftedUInt<6, 2>(Imm);
2375 Ok = isShiftedUInt<5, 3>(Imm);
2378 Ok = isUInt<8>(Imm) && Imm >= 32;
2381 Ok = isShiftedUInt<6, 3>(Imm);
2384 Ok = isShiftedInt<6, 4>(Imm) && (Imm != 0);
2387 Ok = isShiftedUInt<8, 2>(Imm) && (Imm != 0);
2396 Ok = (isInt<5>(Imm) && Imm != -16) || Imm == 16;
2402 Ok = Imm != 0 && isInt<6>(Imm);
2405 Ok = isUInt<10>(Imm);
2408 Ok = isUInt<11>(Imm);
2411 Ok = isInt<12>(Imm);
2414 Ok = isShiftedInt<7, 5>(Imm);
2417 Ok =
STI.
is64Bit() ? isUInt<6>(Imm) : isUInt<5>(Imm);
2420 Ok =
STI.
is64Bit() ? isUInt<6>(Imm) : isUInt<5>(Imm);
2421 Ok = Ok && Imm != 0;
2424 Ok = (isUInt<5>(Imm) && Imm != 0) ||
2425 (Imm >= 0xfffe0 && Imm <= 0xfffff);
2428 Ok = Imm >= 0 && Imm <= 10;
2431 Ok = Imm >= 0 && Imm <= 7;
2434 Ok = Imm >= 1 && Imm <= 10;
2437 Ok = Imm >= 2 && Imm <= 14;
2440 Ok = (Imm & 0xf) == 0;
2444 ErrInfo =
"Invalid immediate";
2454 if (!
Op.isImm() && !
Op.isReg()) {
2455 ErrInfo =
"Invalid operand type for VL operand";
2458 if (
Op.isReg() &&
Op.getReg() != RISCV::NoRegister) {
2460 auto *RC =
MRI.getRegClass(
Op.getReg());
2461 if (!RISCV::GPRRegClass.hasSubClassEq(RC)) {
2462 ErrInfo =
"Invalid register class for VL operand";
2467 ErrInfo =
"VL operand w/o SEW operand?";
2473 if (!
MI.getOperand(OpIdx).isImm()) {
2474 ErrInfo =
"SEW value expected to be an immediate";
2477 uint64_t Log2SEW =
MI.getOperand(OpIdx).getImm();
2479 ErrInfo =
"Unexpected SEW value";
2482 unsigned SEW = Log2SEW ? 1 << Log2SEW : 8;
2484 ErrInfo =
"Unexpected SEW value";
2490 if (!
MI.getOperand(OpIdx).isImm()) {
2491 ErrInfo =
"Policy operand expected to be an immediate";
2494 uint64_t Policy =
MI.getOperand(OpIdx).getImm();
2496 ErrInfo =
"Invalid Policy Value";
2500 ErrInfo =
"policy operand w/o VL operand?";
2508 if (!
MI.isRegTiedToUseOperand(0, &UseOpIdx)) {
2509 ErrInfo =
"policy operand w/o tied operand?";
2552 int64_t NewOffset = OldOffset + Disp;
2554 NewOffset = SignExtend64<32>(NewOffset);
2556 if (!isInt<12>(NewOffset))
2574 "Addressing mode not supported for folding");
2616 OffsetIsScalable =
false;
2632 if (BaseOps1.
front()->isIdenticalTo(*BaseOps2.
front()))
2640 if (MO1->getAddrSpace() != MO2->getAddrSpace())
2643 auto Base1 = MO1->getValue();
2644 auto Base2 = MO2->getValue();
2645 if (!Base1 || !Base2)
2650 if (isa<UndefValue>(Base1) || isa<UndefValue>(Base2))
2653 return Base1 == Base2;
2659 int64_t Offset2,
bool OffsetIsScalable2,
unsigned ClusterSize,
2660 unsigned NumBytes)
const {
2663 if (!BaseOps1.
empty() && !BaseOps2.
empty()) {
2668 }
else if (!BaseOps1.
empty() || !BaseOps2.
empty()) {
2674 BaseOps1.
front()->getParent()->getMF()->getSubtarget().getCacheLineSize();
2680 return ClusterSize <= 4 && std::abs(Offset1 - Offset2) <
CacheLineSize;
2730 int64_t OffsetA = 0, OffsetB = 0;
2735 int LowOffset = std::min(OffsetA, OffsetB);
2736 int HighOffset = std::max(OffsetA, OffsetB);
2737 LocationSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
2739 LowOffset + (int)LowWidth.
getValue() <= HighOffset)
2746std::pair<unsigned, unsigned>
2749 return std::make_pair(TF & Mask, TF & ~Mask);
2754 using namespace RISCVII;
2755 static const std::pair<unsigned, const char *> TargetFlags[] = {
2756 {MO_CALL,
"riscv-call"},
2757 {MO_LO,
"riscv-lo"},
2758 {MO_HI,
"riscv-hi"},
2759 {MO_PCREL_LO,
"riscv-pcrel-lo"},
2760 {MO_PCREL_HI,
"riscv-pcrel-hi"},
2761 {MO_GOT_HI,
"riscv-got-hi"},
2762 {MO_TPREL_LO,
"riscv-tprel-lo"},
2763 {MO_TPREL_HI,
"riscv-tprel-hi"},
2764 {MO_TPREL_ADD,
"riscv-tprel-add"},
2765 {MO_TLS_GOT_HI,
"riscv-tls-got-hi"},
2766 {MO_TLS_GD_HI,
"riscv-tls-gd-hi"},
2767 {MO_TLSDESC_HI,
"riscv-tlsdesc-hi"},
2768 {MO_TLSDESC_LOAD_LO,
"riscv-tlsdesc-load-lo"},
2769 {MO_TLSDESC_ADD_LO,
"riscv-tlsdesc-add-lo"},
2770 {MO_TLSDESC_CALL,
"riscv-tlsdesc-call"}};
2778 if (!OutlineFromLinkOnceODRs &&
F.hasLinkOnceODRLinkage())
2791 unsigned &Flags)
const {
2806std::optional<outliner::OutlinedFunction>
2808 std::vector<outliner::Candidate> &RepeatedSequenceLocs)
const {
2814 return !
C.isAvailableAcrossAndOutOfSeq(RISCV::X5, *
TRI);
2820 if (RepeatedSequenceLocs.size() < 2)
2821 return std::nullopt;
2823 unsigned SequenceSize = 0;
2825 for (
auto &
MI : RepeatedSequenceLocs[0])
2829 unsigned CallOverhead = 8;
2830 for (
auto &
C : RepeatedSequenceLocs)
2834 unsigned FrameOverhead = 4;
2835 if (RepeatedSequenceLocs[0]
2837 ->getSubtarget<RISCVSubtarget>()
2847 unsigned Flags)
const {
2852 const auto &
F =
MI.getMF()->getFunction();
2855 if (
MI.isCFIInstruction())
2869 if (
MI.modifiesRegister(RISCV::X5,
TRI) ||
2870 MI.getDesc().hasImplicitDefOfPhysReg(RISCV::X5))
2874 for (
const auto &MO :
MI.operands()) {
2879 (
MI.getMF()->getTarget().getFunctionSections() ||
F.hasComdat() ||
2892 bool Changed =
true;
2897 for (;
I != E; ++
I) {
2898 if (
I->isCFIInstruction()) {
2899 I->removeFromParent();
2922 .addGlobalAddress(M.getNamedValue(MF.
getName()), 0,
2933 return std::nullopt;
2937 if (
MI.getOpcode() == RISCV::ADDI &&
MI.getOperand(1).isReg() &&
2938 MI.getOperand(2).isImm())
2939 return RegImmPair{
MI.getOperand(1).getReg(),
MI.getOperand(2).getImm()};
2941 return std::nullopt;
2949 std::string GenericComment =
2951 if (!GenericComment.empty())
2952 return GenericComment;
2956 return std::string();
2958 std::string Comment;
2965 if ((
MI.getOpcode() == RISCV::VSETVLI ||
MI.getOpcode() == RISCV::VSETIVLI ||
2966 MI.getOpcode() == RISCV::PseudoVSETVLI ||
2967 MI.getOpcode() == RISCV::PseudoVSETIVLI ||
2968 MI.getOpcode() == RISCV::PseudoVSETVLIX0) &&
2970 unsigned Imm =
MI.getOperand(OpIdx).getImm();
2974 unsigned Log2SEW =
MI.getOperand(OpIdx).getImm();
2975 unsigned SEW = Log2SEW ? 1 << Log2SEW : 8;
2980 unsigned Policy =
MI.getOperand(OpIdx).getImm();
2982 "Invalid Policy Value");
2992#define CASE_RVV_OPCODE_UNMASK_LMUL(OP, LMUL) \
2993 RISCV::Pseudo##OP##_##LMUL
2995#define CASE_RVV_OPCODE_MASK_LMUL(OP, LMUL) \
2996 RISCV::Pseudo##OP##_##LMUL##_MASK
2998#define CASE_RVV_OPCODE_LMUL(OP, LMUL) \
2999 CASE_RVV_OPCODE_UNMASK_LMUL(OP, LMUL): \
3000 case CASE_RVV_OPCODE_MASK_LMUL(OP, LMUL)
3002#define CASE_RVV_OPCODE_UNMASK_WIDEN(OP) \
3003 CASE_RVV_OPCODE_UNMASK_LMUL(OP, MF8): \
3004 case CASE_RVV_OPCODE_UNMASK_LMUL(OP, MF4): \
3005 case CASE_RVV_OPCODE_UNMASK_LMUL(OP, MF2): \
3006 case CASE_RVV_OPCODE_UNMASK_LMUL(OP, M1): \
3007 case CASE_RVV_OPCODE_UNMASK_LMUL(OP, M2): \
3008 case CASE_RVV_OPCODE_UNMASK_LMUL(OP, M4)
3010#define CASE_RVV_OPCODE_UNMASK(OP) \
3011 CASE_RVV_OPCODE_UNMASK_WIDEN(OP): \
3012 case CASE_RVV_OPCODE_UNMASK_LMUL(OP, M8)
3014#define CASE_RVV_OPCODE_MASK_WIDEN(OP) \
3015 CASE_RVV_OPCODE_MASK_LMUL(OP, MF8): \
3016 case CASE_RVV_OPCODE_MASK_LMUL(OP, MF4): \
3017 case CASE_RVV_OPCODE_MASK_LMUL(OP, MF2): \
3018 case CASE_RVV_OPCODE_MASK_LMUL(OP, M1): \
3019 case CASE_RVV_OPCODE_MASK_LMUL(OP, M2): \
3020 case CASE_RVV_OPCODE_MASK_LMUL(OP, M4)
3022#define CASE_RVV_OPCODE_MASK(OP) \
3023 CASE_RVV_OPCODE_MASK_WIDEN(OP): \
3024 case CASE_RVV_OPCODE_MASK_LMUL(OP, M8)
3026#define CASE_RVV_OPCODE_WIDEN(OP) \
3027 CASE_RVV_OPCODE_UNMASK_WIDEN(OP): \
3028 case CASE_RVV_OPCODE_MASK_WIDEN(OP)
3030#define CASE_RVV_OPCODE(OP) \
3031 CASE_RVV_OPCODE_UNMASK(OP): \
3032 case CASE_RVV_OPCODE_MASK(OP)
3036#define CASE_VMA_OPCODE_COMMON(OP, TYPE, LMUL) \
3037 RISCV::PseudoV##OP##_##TYPE##_##LMUL
3039#define CASE_VMA_OPCODE_LMULS_M1(OP, TYPE) \
3040 CASE_VMA_OPCODE_COMMON(OP, TYPE, M1): \
3041 case CASE_VMA_OPCODE_COMMON(OP, TYPE, M2): \
3042 case CASE_VMA_OPCODE_COMMON(OP, TYPE, M4): \
3043 case CASE_VMA_OPCODE_COMMON(OP, TYPE, M8)
3045#define CASE_VMA_OPCODE_LMULS_MF2(OP, TYPE) \
3046 CASE_VMA_OPCODE_COMMON(OP, TYPE, MF2): \
3047 case CASE_VMA_OPCODE_LMULS_M1(OP, TYPE)
3049#define CASE_VMA_OPCODE_LMULS_MF4(OP, TYPE) \
3050 CASE_VMA_OPCODE_COMMON(OP, TYPE, MF4): \
3051 case CASE_VMA_OPCODE_LMULS_MF2(OP, TYPE)
3053#define CASE_VMA_OPCODE_LMULS(OP, TYPE) \
3054 CASE_VMA_OPCODE_COMMON(OP, TYPE, MF8): \
3055 case CASE_VMA_OPCODE_LMULS_MF4(OP, TYPE)
3058#define CASE_VFMA_OPCODE_COMMON(OP, TYPE, LMUL, SEW) \
3059 RISCV::PseudoV##OP##_##TYPE##_##LMUL##_##SEW
3061#define CASE_VFMA_OPCODE_LMULS_M1(OP, TYPE, SEW) \
3062 CASE_VFMA_OPCODE_COMMON(OP, TYPE, M1, SEW): \
3063 case CASE_VFMA_OPCODE_COMMON(OP, TYPE, M2, SEW): \
3064 case CASE_VFMA_OPCODE_COMMON(OP, TYPE, M4, SEW): \
3065 case CASE_VFMA_OPCODE_COMMON(OP, TYPE, M8, SEW)
3067#define CASE_VFMA_OPCODE_LMULS_MF2(OP, TYPE, SEW) \
3068 CASE_VFMA_OPCODE_COMMON(OP, TYPE, MF2, SEW): \
3069 case CASE_VFMA_OPCODE_LMULS_M1(OP, TYPE, SEW)
3071#define CASE_VFMA_OPCODE_LMULS_MF4(OP, TYPE, SEW) \
3072 CASE_VFMA_OPCODE_COMMON(OP, TYPE, MF4, SEW): \
3073 case CASE_VFMA_OPCODE_LMULS_MF2(OP, TYPE, SEW)
3075#define CASE_VFMA_OPCODE_VV(OP) \
3076 CASE_VFMA_OPCODE_LMULS_MF4(OP, VV, E16): \
3077 case CASE_VFMA_OPCODE_LMULS_MF2(OP, VV, E32): \
3078 case CASE_VFMA_OPCODE_LMULS_M1(OP, VV, E64)
3080#define CASE_VFMA_SPLATS(OP) \
3081 CASE_VFMA_OPCODE_LMULS_MF4(OP, VFPR16, E16): \
3082 case CASE_VFMA_OPCODE_LMULS_MF2(OP, VFPR32, E32): \
3083 case CASE_VFMA_OPCODE_LMULS_M1(OP, VFPR64, E64)
3087 unsigned &SrcOpIdx1,
3088 unsigned &SrcOpIdx2)
const {
3090 if (!
Desc.isCommutable())
3093 switch (
MI.getOpcode()) {
3094 case RISCV::TH_MVEQZ:
3095 case RISCV::TH_MVNEZ:
3099 if (
MI.getOperand(2).getReg() == RISCV::X0)
3102 return fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 1, 2);
3103 case RISCV::TH_MULA:
3104 case RISCV::TH_MULAW:
3105 case RISCV::TH_MULAH:
3106 case RISCV::TH_MULS:
3107 case RISCV::TH_MULSW:
3108 case RISCV::TH_MULSH:
3110 return fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 2, 3);
3111 case RISCV::PseudoCCMOVGPRNoX0:
3112 case RISCV::PseudoCCMOVGPR:
3114 return fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 4, 5);
3136 return fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 2, 3);
3157 if ((
MI.getOperand(
MI.getNumExplicitOperands() - 1).getImm() & 1) == 0)
3162 unsigned CommutableOpIdx1 = 1;
3163 unsigned CommutableOpIdx2 = 3;
3164 if (!fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, CommutableOpIdx1,
3177 if ((
MI.getOperand(
MI.getNumExplicitOperands() - 1).getImm() & 1) == 0)
3184 if (SrcOpIdx1 != CommuteAnyOperandIndex && SrcOpIdx1 > 3)
3186 if (SrcOpIdx2 != CommuteAnyOperandIndex && SrcOpIdx2 > 3)
3190 if (SrcOpIdx1 != CommuteAnyOperandIndex &&
3191 SrcOpIdx2 != CommuteAnyOperandIndex && SrcOpIdx1 != 1 && SrcOpIdx2 != 1)
3197 if (SrcOpIdx1 == CommuteAnyOperandIndex ||
3198 SrcOpIdx2 == CommuteAnyOperandIndex) {
3201 unsigned CommutableOpIdx1 = SrcOpIdx1;
3202 if (SrcOpIdx1 == SrcOpIdx2) {
3205 CommutableOpIdx1 = 1;
3206 }
else if (SrcOpIdx1 == CommuteAnyOperandIndex) {
3208 CommutableOpIdx1 = SrcOpIdx2;
3213 unsigned CommutableOpIdx2;
3214 if (CommutableOpIdx1 != 1) {
3216 CommutableOpIdx2 = 1;
3218 Register Op1Reg =
MI.getOperand(CommutableOpIdx1).getReg();
3223 if (Op1Reg !=
MI.getOperand(2).getReg())
3224 CommutableOpIdx2 = 2;
3226 CommutableOpIdx2 = 3;
3231 if (!fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, CommutableOpIdx1,
3244#define CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, LMUL) \
3245 case RISCV::PseudoV##OLDOP##_##TYPE##_##LMUL: \
3246 Opc = RISCV::PseudoV##NEWOP##_##TYPE##_##LMUL; \
3249#define CASE_VMA_CHANGE_OPCODE_LMULS_M1(OLDOP, NEWOP, TYPE) \
3250 CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M1) \
3251 CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M2) \
3252 CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M4) \
3253 CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M8)
3255#define CASE_VMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, TYPE) \
3256 CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF2) \
3257 CASE_VMA_CHANGE_OPCODE_LMULS_M1(OLDOP, NEWOP, TYPE)
3259#define CASE_VMA_CHANGE_OPCODE_LMULS_MF4(OLDOP, NEWOP, TYPE) \
3260 CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF4) \
3261 CASE_VMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, TYPE)
3263#define CASE_VMA_CHANGE_OPCODE_LMULS(OLDOP, NEWOP, TYPE) \
3264 CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF8) \
3265 CASE_VMA_CHANGE_OPCODE_LMULS_MF4(OLDOP, NEWOP, TYPE)
3267#define CASE_VMA_CHANGE_OPCODE_SPLATS(OLDOP, NEWOP) \
3268 CASE_VMA_CHANGE_OPCODE_LMULS_MF4(OLDOP, NEWOP, VFPR16) \
3269 CASE_VMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, VFPR32) \
3270 CASE_VMA_CHANGE_OPCODE_LMULS_M1(OLDOP, NEWOP, VFPR64)
3273#define CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, LMUL, SEW) \
3274 case RISCV::PseudoV##OLDOP##_##TYPE##_##LMUL##_##SEW: \
3275 Opc = RISCV::PseudoV##NEWOP##_##TYPE##_##LMUL##_##SEW; \
3278#define CASE_VFMA_CHANGE_OPCODE_LMULS_M1(OLDOP, NEWOP, TYPE, SEW) \
3279 CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M1, SEW) \
3280 CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M2, SEW) \
3281 CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M4, SEW) \
3282 CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M8, SEW)
3284#define CASE_VFMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, TYPE, SEW) \
3285 CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF2, SEW) \
3286 CASE_VFMA_CHANGE_OPCODE_LMULS_M1(OLDOP, NEWOP, TYPE, SEW)
3288#define CASE_VFMA_CHANGE_OPCODE_VV(OLDOP, NEWOP) \
3289 CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(OLDOP, NEWOP, VV, E16) \
3290 CASE_VFMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, VV, E32) \
3291 CASE_VFMA_CHANGE_OPCODE_LMULS_M1(OLDOP, NEWOP, VV, E64)
3293#define CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(OLDOP, NEWOP, TYPE, SEW) \
3294 CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF4, SEW) \
3295 CASE_VFMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, TYPE, SEW)
3297#define CASE_VFMA_CHANGE_OPCODE_LMULS(OLDOP, NEWOP, TYPE, SEW) \
3298 CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF8, SEW) \
3299 CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(OLDOP, NEWOP, TYPE, SEW)
3301#define CASE_VFMA_CHANGE_OPCODE_SPLATS(OLDOP, NEWOP) \
3302 CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(OLDOP, NEWOP, VFPR16, E16) \
3303 CASE_VFMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, VFPR32, E32) \
3304 CASE_VFMA_CHANGE_OPCODE_LMULS_M1(OLDOP, NEWOP, VFPR64, E64)
3309 unsigned OpIdx2)
const {
3312 return *
MI.getParent()->getParent()->CloneMachineInstr(&
MI);
3316 switch (
MI.getOpcode()) {
3317 case RISCV::TH_MVEQZ:
3318 case RISCV::TH_MVNEZ: {
3319 auto &WorkingMI = cloneIfNew(
MI);
3320 WorkingMI.setDesc(
get(
MI.getOpcode() == RISCV::TH_MVEQZ ? RISCV::TH_MVNEZ
3321 : RISCV::TH_MVEQZ));
3325 case RISCV::PseudoCCMOVGPRNoX0:
3326 case RISCV::PseudoCCMOVGPR: {
3330 auto &WorkingMI = cloneIfNew(
MI);
3331 WorkingMI.getOperand(3).setImm(
CC);
3355 assert((OpIdx1 == 1 || OpIdx2 == 1) &&
"Unexpected opcode index");
3356 assert((OpIdx1 == 3 || OpIdx2 == 3) &&
"Unexpected opcode index");
3358 switch (
MI.getOpcode()) {
3381 auto &WorkingMI = cloneIfNew(
MI);
3382 WorkingMI.setDesc(
get(Opc));
3392 assert((OpIdx1 == 1 || OpIdx2 == 1) &&
"Unexpected opcode index");
3395 if (OpIdx1 == 3 || OpIdx2 == 3) {
3397 switch (
MI.getOpcode()) {
3408 auto &WorkingMI = cloneIfNew(
MI);
3409 WorkingMI.setDesc(
get(Opc));
3421#undef CASE_RVV_OPCODE_UNMASK_LMUL
3422#undef CASE_RVV_OPCODE_MASK_LMUL
3423#undef CASE_RVV_OPCODE_LMUL
3424#undef CASE_RVV_OPCODE_UNMASK_WIDEN
3425#undef CASE_RVV_OPCODE_UNMASK
3426#undef CASE_RVV_OPCODE_MASK_WIDEN
3427#undef CASE_RVV_OPCODE_MASK
3428#undef CASE_RVV_OPCODE_WIDEN
3429#undef CASE_RVV_OPCODE
3431#undef CASE_VMA_OPCODE_COMMON
3432#undef CASE_VMA_OPCODE_LMULS_M1
3433#undef CASE_VMA_OPCODE_LMULS_MF2
3434#undef CASE_VMA_OPCODE_LMULS_MF4
3435#undef CASE_VMA_OPCODE_LMULS
3436#undef CASE_VFMA_OPCODE_COMMON
3437#undef CASE_VFMA_OPCODE_LMULS_M1
3438#undef CASE_VFMA_OPCODE_LMULS_MF2
3439#undef CASE_VFMA_OPCODE_LMULS_MF4
3440#undef CASE_VFMA_OPCODE_VV
3441#undef CASE_VFMA_SPLATS
3444#define CASE_WIDEOP_OPCODE_COMMON(OP, LMUL) \
3445 RISCV::PseudoV##OP##_##LMUL##_TIED
3447#define CASE_WIDEOP_OPCODE_LMULS_MF4(OP) \
3448 CASE_WIDEOP_OPCODE_COMMON(OP, MF4): \
3449 case CASE_WIDEOP_OPCODE_COMMON(OP, MF2): \
3450 case CASE_WIDEOP_OPCODE_COMMON(OP, M1): \
3451 case CASE_WIDEOP_OPCODE_COMMON(OP, M2): \
3452 case CASE_WIDEOP_OPCODE_COMMON(OP, M4)
3454#define CASE_WIDEOP_OPCODE_LMULS(OP) \
3455 CASE_WIDEOP_OPCODE_COMMON(OP, MF8): \
3456 case CASE_WIDEOP_OPCODE_LMULS_MF4(OP)
3458#define CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, LMUL) \
3459 case RISCV::PseudoV##OP##_##LMUL##_TIED: \
3460 NewOpc = RISCV::PseudoV##OP##_##LMUL; \
3463#define CASE_WIDEOP_CHANGE_OPCODE_LMULS_MF4(OP) \
3464 CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF4) \
3465 CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF2) \
3466 CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, M1) \
3467 CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, M2) \
3468 CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, M4)
3470#define CASE_WIDEOP_CHANGE_OPCODE_LMULS(OP) \
3471 CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF8) \
3472 CASE_WIDEOP_CHANGE_OPCODE_LMULS_MF4(OP)
3475#define CASE_FP_WIDEOP_OPCODE_COMMON(OP, LMUL, SEW) \
3476 RISCV::PseudoV##OP##_##LMUL##_##SEW##_TIED
3478#define CASE_FP_WIDEOP_OPCODE_LMULS_MF4(OP) \
3479 CASE_FP_WIDEOP_OPCODE_COMMON(OP, MF4, E16): \
3480 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, MF2, E16): \
3481 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, MF2, E32): \
3482 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M1, E16): \
3483 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M1, E32): \
3484 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M2, E16): \
3485 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M2, E32): \
3486 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M4, E16): \
3487 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M4, E32) \
3489#define CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, LMUL, SEW) \
3490 case RISCV::PseudoV##OP##_##LMUL##_##SEW##_TIED: \
3491 NewOpc = RISCV::PseudoV##OP##_##LMUL##_##SEW; \
3494#define CASE_FP_WIDEOP_CHANGE_OPCODE_LMULS_MF4(OP) \
3495 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF4, E16) \
3496 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF2, E16) \
3497 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF2, E32) \
3498 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M1, E16) \
3499 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M1, E32) \
3500 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M2, E16) \
3501 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M2, E32) \
3502 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M4, E16) \
3503 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M4, E32) \
3505#define CASE_FP_WIDEOP_CHANGE_OPCODE_LMULS(OP) \
3506 CASE_FP_WIDEOP_CHANGE_OPCODE_LMULS_MF4(OP)
3513 switch (
MI.getOpcode()) {
3519 MI.getNumExplicitOperands() == 7 &&
3520 "Expect 7 explicit operands rd, rs2, rs1, rm, vl, sew, policy");
3527 switch (
MI.getOpcode()) {
3537 .
add(
MI.getOperand(0))
3539 .
add(
MI.getOperand(1))
3540 .
add(
MI.getOperand(2))
3541 .
add(
MI.getOperand(3))
3542 .
add(
MI.getOperand(4))
3543 .
add(
MI.getOperand(5))
3544 .
add(
MI.getOperand(6));
3553 MI.getNumExplicitOperands() == 6);
3554 if ((
MI.getOperand(5).getImm() & 1) == 0)
3559 switch (
MI.getOpcode()) {
3571 .
add(
MI.getOperand(0))
3573 .
add(
MI.getOperand(1))
3574 .
add(
MI.getOperand(2))
3575 .
add(
MI.getOperand(3))
3576 .
add(
MI.getOperand(4))
3577 .
add(
MI.getOperand(5));
3584 unsigned NumOps =
MI.getNumOperands();
3585 for (
unsigned I = 1;
I < NumOps; ++
I) {
3587 if (
Op.isReg() &&
Op.isKill())
3595 if (
MI.getOperand(0).isEarlyClobber()) {
3601 if (S->
end ==
Idx.getRegSlot(
true))
3602 S->
end =
Idx.getRegSlot();
3609#undef CASE_WIDEOP_OPCODE_COMMON
3610#undef CASE_WIDEOP_OPCODE_LMULS_MF4
3611#undef CASE_WIDEOP_OPCODE_LMULS
3612#undef CASE_WIDEOP_CHANGE_OPCODE_COMMON
3613#undef CASE_WIDEOP_CHANGE_OPCODE_LMULS_MF4
3614#undef CASE_WIDEOP_CHANGE_OPCODE_LMULS
3615#undef CASE_FP_WIDEOP_OPCODE_COMMON
3616#undef CASE_FP_WIDEOP_OPCODE_LMULS_MF4
3617#undef CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON
3618#undef CASE_FP_WIDEOP_CHANGE_OPCODE_LMULS_MF4
3619#undef CASE_FP_WIDEOP_CHANGE_OPCODE_LMULS
3626 if (llvm::has_single_bit<uint32_t>(Amount)) {
3628 if (ShiftAmount == 0)
3634 }
else if (
STI.hasStdExtZba() &&
3641 if (Amount % 9 == 0) {
3642 Opc = RISCV::SH3ADD;
3643 ShiftAmount =
Log2_64(Amount / 9);
3644 }
else if (Amount % 5 == 0) {
3645 Opc = RISCV::SH2ADD;
3646 ShiftAmount =
Log2_64(Amount / 5);
3647 }
else if (Amount % 3 == 0) {
3648 Opc = RISCV::SH1ADD;
3649 ShiftAmount =
Log2_64(Amount / 3);
3662 }
else if (llvm::has_single_bit<uint32_t>(Amount - 1)) {
3663 Register ScaledRegister =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
3673 }
else if (llvm::has_single_bit<uint32_t>(Amount + 1)) {
3674 Register ScaledRegister =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
3684 }
else if (
STI.hasStdExtM() ||
STI.hasStdExtZmmul()) {
3685 Register N =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
3694 for (
uint32_t ShiftAmount = 0; Amount >> ShiftAmount; ShiftAmount++) {
3695 if (Amount & (1U << ShiftAmount)) {
3699 .
addImm(ShiftAmount - PrevShiftAmount)
3701 if (Amount >> (ShiftAmount + 1)) {
3704 Acc =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
3715 PrevShiftAmount = ShiftAmount;
3718 assert(Acc &&
"Expected valid accumulator");
3728 static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
3736 return MI.getOpcode() == RISCV::ADDIW &&
MI.getOperand(1).isReg() &&
3737 MI.getOperand(2).isImm() &&
MI.getOperand(2).getImm() == 0;
3742 return MI.getOpcode() == RISCV::ADD_UW &&
MI.getOperand(1).isReg() &&
3743 MI.getOperand(2).isReg() &&
MI.getOperand(2).getReg() == RISCV::X0;
3748 return MI.getOpcode() == RISCV::ANDI &&
MI.getOperand(1).isReg() &&
3749 MI.getOperand(2).isImm() &&
MI.getOperand(2).getImm() == 255;
3760 case RISCV::VL1RE8_V:
3761 case RISCV::VL2RE8_V:
3762 case RISCV::VL4RE8_V:
3763 case RISCV::VL8RE8_V:
3764 case RISCV::VL1RE16_V:
3765 case RISCV::VL2RE16_V:
3766 case RISCV::VL4RE16_V:
3767 case RISCV::VL8RE16_V:
3768 case RISCV::VL1RE32_V:
3769 case RISCV::VL2RE32_V:
3770 case RISCV::VL4RE32_V:
3771 case RISCV::VL8RE32_V:
3772 case RISCV::VL1RE64_V:
3773 case RISCV::VL2RE64_V:
3774 case RISCV::VL4RE64_V:
3775 case RISCV::VL8RE64_V:
3783 unsigned Opcode =
MI.getOpcode();
3784 if (!RISCVVPseudosTable::getPseudoInfo(Opcode) &&
3790std::optional<std::pair<unsigned, unsigned>>
3794 return std::nullopt;
3795 case RISCV::PseudoVSPILL2_M1:
3796 case RISCV::PseudoVRELOAD2_M1:
3797 return std::make_pair(2u, 1u);
3798 case RISCV::PseudoVSPILL2_M2:
3799 case RISCV::PseudoVRELOAD2_M2:
3800 return std::make_pair(2u, 2u);
3801 case RISCV::PseudoVSPILL2_M4:
3802 case RISCV::PseudoVRELOAD2_M4:
3803 return std::make_pair(2u, 4u);
3804 case RISCV::PseudoVSPILL3_M1:
3805 case RISCV::PseudoVRELOAD3_M1:
3806 return std::make_pair(3u, 1u);
3807 case RISCV::PseudoVSPILL3_M2:
3808 case RISCV::PseudoVRELOAD3_M2:
3809 return std::make_pair(3u, 2u);
3810 case RISCV::PseudoVSPILL4_M1:
3811 case RISCV::PseudoVRELOAD4_M1:
3812 return std::make_pair(4u, 1u);
3813 case RISCV::PseudoVSPILL4_M2:
3814 case RISCV::PseudoVRELOAD4_M2:
3815 return std::make_pair(4u, 2u);
3816 case RISCV::PseudoVSPILL5_M1:
3817 case RISCV::PseudoVRELOAD5_M1:
3818 return std::make_pair(5u, 1u);
3819 case RISCV::PseudoVSPILL6_M1:
3820 case RISCV::PseudoVRELOAD6_M1:
3821 return std::make_pair(6u, 1u);
3822 case RISCV::PseudoVSPILL7_M1:
3823 case RISCV::PseudoVRELOAD7_M1:
3824 return std::make_pair(7u, 1u);
3825 case RISCV::PseudoVSPILL8_M1:
3826 case RISCV::PseudoVRELOAD8_M1:
3827 return std::make_pair(8u, 1u);
3832 return MI.getNumExplicitDefs() == 2 &&
3833 MI.modifiesRegister(RISCV::VL,
nullptr) && !
MI.isInlineAsm();
3837 int16_t MI1FrmOpIdx =
3839 int16_t MI2FrmOpIdx =
3841 if (MI1FrmOpIdx < 0 || MI2FrmOpIdx < 0)
3848std::optional<unsigned>
3853 return std::nullopt;
3856 case RISCV::VSLL_VX:
3857 case RISCV::VSRL_VX:
3858 case RISCV::VSRA_VX:
3860 case RISCV::VSSRL_VX:
3861 case RISCV::VSSRA_VX:
3866 case RISCV::VNSRL_WX:
3867 case RISCV::VNSRA_WX:
3869 case RISCV::VNCLIPU_WX:
3870 case RISCV::VNCLIP_WX:
3875 case RISCV::VADD_VX:
3876 case RISCV::VSUB_VX:
3877 case RISCV::VRSUB_VX:
3879 case RISCV::VWADDU_VX:
3880 case RISCV::VWSUBU_VX:
3881 case RISCV::VWADD_VX:
3882 case RISCV::VWSUB_VX:
3883 case RISCV::VWADDU_WX:
3884 case RISCV::VWSUBU_WX:
3885 case RISCV::VWADD_WX:
3886 case RISCV::VWSUB_WX:
3888 case RISCV::VADC_VXM:
3889 case RISCV::VADC_VIM:
3890 case RISCV::VMADC_VXM:
3891 case RISCV::VMADC_VIM:
3892 case RISCV::VMADC_VX:
3893 case RISCV::VSBC_VXM:
3894 case RISCV::VMSBC_VXM:
3895 case RISCV::VMSBC_VX:
3897 case RISCV::VAND_VX:
3899 case RISCV::VXOR_VX:
3901 case RISCV::VMSEQ_VX:
3902 case RISCV::VMSNE_VX:
3903 case RISCV::VMSLTU_VX:
3904 case RISCV::VMSLT_VX:
3905 case RISCV::VMSLEU_VX:
3906 case RISCV::VMSLE_VX:
3907 case RISCV::VMSGTU_VX:
3908 case RISCV::VMSGT_VX:
3910 case RISCV::VMINU_VX:
3911 case RISCV::VMIN_VX:
3912 case RISCV::VMAXU_VX:
3913 case RISCV::VMAX_VX:
3915 case RISCV::VMUL_VX:
3916 case RISCV::VMULH_VX:
3917 case RISCV::VMULHU_VX:
3918 case RISCV::VMULHSU_VX:
3920 case RISCV::VDIVU_VX:
3921 case RISCV::VDIV_VX:
3922 case RISCV::VREMU_VX:
3923 case RISCV::VREM_VX:
3925 case RISCV::VWMUL_VX:
3926 case RISCV::VWMULU_VX:
3927 case RISCV::VWMULSU_VX:
3929 case RISCV::VMACC_VX:
3930 case RISCV::VNMSAC_VX:
3931 case RISCV::VMADD_VX:
3932 case RISCV::VNMSUB_VX:
3934 case RISCV::VWMACCU_VX:
3935 case RISCV::VWMACC_VX:
3936 case RISCV::VWMACCSU_VX:
3937 case RISCV::VWMACCUS_VX:
3939 case RISCV::VMERGE_VXM:
3941 case RISCV::VMV_V_X:
3943 case RISCV::VSADDU_VX:
3944 case RISCV::VSADD_VX:
3945 case RISCV::VSSUBU_VX:
3946 case RISCV::VSSUB_VX:
3948 case RISCV::VAADDU_VX:
3949 case RISCV::VAADD_VX:
3950 case RISCV::VASUBU_VX:
3951 case RISCV::VASUB_VX:
3953 case RISCV::VSMUL_VX:
3955 case RISCV::VMV_S_X:
3956 return 1U << Log2SEW;
3962 RISCVVPseudosTable::getPseudoInfo(RVVPseudoOpcode);
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder MachineInstrBuilder & DefMI
static bool forwardCopyWillClobberTuple(unsigned DestReg, unsigned SrcReg, unsigned NumRegs)
static bool canCombine(MachineBasicBlock &MBB, MachineOperand &MO, unsigned CombineOpc, unsigned ZeroReg=0, bool CheckZeroReg=false)
static void parseCondBranch(MachineInstr *LastInst, MachineBasicBlock *&Target, SmallVectorImpl< MachineOperand > &Cond)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static ARCCC::CondCode getOppositeBranchCondition(ARCCC::CondCode CC)
Return the inverse of passed condition, i.e. turning COND_E to COND_NE.
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
const HexagonInstrInfo * TII
static M68k::CondCode getCondFromBranchOpc(unsigned BrOpc)
unsigned const TargetRegisterInfo * TRI
This file provides utility analysis objects describing memory locations.
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
const char LLVMTargetMachineRef TM
#define CASE_VFMA_CHANGE_OPCODE_SPLATS(OLDOP, NEWOP)
static bool isRVVWholeLoadStore(unsigned Opcode)
#define CASE_VFMA_CHANGE_OPCODE_VV(OLDOP, NEWOP)
static unsigned getFPFusedMultiplyOpcode(unsigned RootOpc, unsigned Pattern)
#define RVV_OPC_LMUL_CASE(OPC, INV)
static void combineFPFusedMultiply(MachineInstr &Root, MachineInstr &Prev, unsigned Pattern, SmallVectorImpl< MachineInstr * > &InsInstrs, SmallVectorImpl< MachineInstr * > &DelInstrs)
static unsigned getAddendOperandIdx(unsigned Pattern)
#define CASE_RVV_OPCODE_UNMASK(OP)
#define CASE_WIDEOP_CHANGE_OPCODE_LMULS(OP)
static cl::opt< bool > PreferWholeRegisterMove("riscv-prefer-whole-register-move", cl::init(false), cl::Hidden, cl::desc("Prefer whole register move for vector registers."))
#define CASE_VFMA_SPLATS(OP)
unsigned getPredicatedOpcode(unsigned Opcode)
static void genShXAddAddShift(MachineInstr &Root, unsigned AddOpIdx, SmallVectorImpl< MachineInstr * > &InsInstrs, SmallVectorImpl< MachineInstr * > &DelInstrs, DenseMap< unsigned, unsigned > &InstrIdxForVirtReg)
#define CASE_WIDEOP_OPCODE_LMULS(OP)
#define OPCODE_LMUL_MASK_CASE(OPC)
static bool isFSUB(unsigned Opc)
#define CASE_VMA_CHANGE_OPCODE_LMULS(OLDOP, NEWOP, TYPE)
#define CASE_RVV_OPCODE(OP)
#define CASE_VFMA_OPCODE_VV(OP)
MachineOutlinerConstructionID
#define CASE_RVV_OPCODE_WIDEN(OP)
#define CASE_VMA_OPCODE_LMULS(OP, TYPE)
static bool isFMUL(unsigned Opc)
static bool getFPPatterns(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns, bool DoRegPressureReduce)
#define OPCODE_LMUL_CASE(OPC)
#define CASE_OPERAND_UIMM(NUM)
static bool canCombineShiftIntoShXAdd(const MachineBasicBlock &MBB, const MachineOperand &MO, unsigned OuterShiftAmt)
Utility routine that checks if.
static bool isFADD(unsigned Opc)
#define CASE_FP_WIDEOP_OPCODE_LMULS_MF4(OP)
static bool isConvertibleToVMV_V_V(const RISCVSubtarget &STI, const MachineBasicBlock &MBB, MachineBasicBlock::const_iterator MBBI, MachineBasicBlock::const_iterator &DefMBBI, RISCVII::VLMUL LMul)
static MachineInstr * canFoldAsPredicatedOp(Register Reg, const MachineRegisterInfo &MRI, const TargetInstrInfo *TII)
Identify instructions that can be folded into a CCMOV instruction, and return the defining instructio...
static bool canCombineFPFusedMultiply(const MachineInstr &Root, const MachineOperand &MO, bool DoRegPressureReduce)
static bool getSHXADDPatterns(const MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns)
static bool getFPFusedMultiplyPatterns(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns, bool DoRegPressureReduce)
static cl::opt< MachineTraceStrategy > ForceMachineCombinerStrategy("riscv-force-machine-combiner-strategy", cl::Hidden, cl::desc("Force machine combiner to use a specific strategy for machine " "trace metrics evaluation."), cl::init(MachineTraceStrategy::TS_NumStrategies), cl::values(clEnumValN(MachineTraceStrategy::TS_Local, "local", "Local strategy."), clEnumValN(MachineTraceStrategy::TS_MinInstrCount, "min-instr", "MinInstrCount strategy.")))
static unsigned getSHXADDShiftAmount(unsigned Opc)
#define CASE_RVV_OPCODE_MASK(OP)
#define RVV_OPC_LMUL_MASK_CASE(OPC, INV)
#define CASE_FP_WIDEOP_CHANGE_OPCODE_LMULS_MF4(OP)
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
const SmallVectorImpl< MachineOperand > & Cond
This file declares the machine register scavenger class.
static bool memOpsHaveSameBasePtr(const MachineInstr &MI1, ArrayRef< const MachineOperand * > BaseOps1, const MachineInstr &MI2, ArrayRef< const MachineOperand * > BaseOps2)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallVector class.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
static unsigned getSize(unsigned Kind)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
const T & front() const
front - Get the first element.
size_t size() const
size - Get the array size.
bool empty() const
empty - Check if the array is empty.
static DILocation * getMergedLocation(DILocation *LocA, DILocation *LocB)
When two instructions are combined into a single instruction we also need to combine the original loc...
This class represents an Operation in the Expression.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
bool hasMinSize() const
Optimize this function for minimum size (-Oz).
LiveInterval - This class represents the liveness of a register, or stack slot.
LiveInterval & getInterval(Register Reg)
SlotIndex ReplaceMachineInstrInMaps(MachineInstr &MI, MachineInstr &NewMI)
const Segment * getSegmentContaining(SlotIndex Idx) const
Return the segment that contains the specified index, or null if there is none.
void replaceKillInstruction(Register Reg, MachineInstr &OldMI, MachineInstr &NewMI)
replaceKillInstruction - Update register kill info by replacing a kill instruction with a new one.
static constexpr LocationSize beforeOrAfterPointer()
Any location before or after the base pointer (but still within the underlying object).
TypeSize getValue() const
MCInstBuilder & addReg(unsigned Reg)
Add a new register operand.
MCInstBuilder & addImm(int64_t Val)
Add a new integer immediate operand.
Instances of this class represent a single low-level machine instruction.
Describe properties that are true of each instruction in the target description file.
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
bool isConditionalBranch() const
Return true if this is a branch which may fall through to the next instruction or may transfer contro...
Wrapper class representing physical registers. Should be passed by value.
unsigned pred_size() const
instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
iterator getLastNonDebugInstr(bool SkipPseudoOp=true)
Returns an iterator to the last non-debug instruction in the basic block, or end().
Instructions::const_iterator const_instr_iterator
void addLiveIn(MCRegister PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
void setStackID(int ObjectIdx, uint8_t ID)
Align getObjectAlign(int ObjectIdx) const
Return the alignment of the specified stack object.
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
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.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
const LLVMTargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineInstrBuilder & setMemRefs(ArrayRef< MachineMemOperand * > MMOs) const
const MachineInstrBuilder & setMIFlag(MachineInstr::MIFlag Flag) const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & copyImplicitOps(const MachineInstr &OtherMI) const
Copy all the implicit operands from OtherMI onto this one.
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
reverse_iterator getReverse() const
Get a reverse iterator to the same node.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
bool mayLoadOrStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read or modify memory.
const MachineBasicBlock * getParent() const
bool getFlag(MIFlag Flag) const
Return whether an MI flag is set.
unsigned getNumExplicitOperands() const
Returns the number of non-implicit operands.
bool mayLoad(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read memory.
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
bool hasUnmodeledSideEffects() const
Return true if this instruction has side effects that are not modeled by mayLoad / mayStore,...
bool hasOneMemOperand() const
Return true if this instruction has exactly one MachineMemOperand.
mmo_iterator memoperands_begin() const
Access to memory operands of the instruction.
bool hasOrderedMemoryRef() const
Return true if this instruction may have an ordered or volatile memory reference, or if the informati...
const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
ArrayRef< MachineMemOperand * > memoperands() const
Access to memory operands of the instruction.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
const MachineOperand & getOperand(unsigned i) const
uint32_t getFlags() const
Return the MI flags bitvector.
void clearKillInfo()
Clears kill flags on all operands.
A description of a memory reference used in the backend.
bool isNonTemporal() const
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
MachineOperand class - Representation of each machine instruction operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
MachineBasicBlock * getMBB() const
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
static MachineOperand CreateImm(int64_t Val)
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
Register getReg() const
getReg - Returns the register number.
bool isFI() const
isFI - Tests if this is a MO_FrameIndex operand.
bool isIdenticalTo(const MachineOperand &Other) const
Returns true if this operand is identical to the specified operand except for liveness related flags ...
@ MO_Immediate
Immediate operand.
@ MO_Register
Register operand.
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,...
A Module instance is used to store all the information related to an LLVM module.
MI-level patchpoint operands.
uint32_t getNumPatchBytes() const
Return the number of patchable bytes the given patchpoint should emit.
MachineInstr * convertToThreeAddress(MachineInstr &MI, LiveVariables *LV, LiveIntervals *LIS) const override
Register isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const override
unsigned removeBranch(MachineBasicBlock &MBB, int *BytesRemoved=nullptr) const override
std::optional< outliner::OutlinedFunction > getOutliningCandidateInfo(std::vector< outliner::Candidate > &RepeatedSequenceLocs) const override
void movImm(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, Register DstReg, uint64_t Val, MachineInstr::MIFlag Flag=MachineInstr::NoFlags, bool DstRenamable=false, bool DstIsDead=false) const
MachineInstr * emitLdStWithAddr(MachineInstr &MemI, const ExtAddrMode &AM) const override
void mulImm(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator II, const DebugLoc &DL, Register DestReg, uint32_t Amt, MachineInstr::MIFlag Flag) const
Generate code to multiply the value in DestReg by Amt - handles all the common optimizations for this...
const MCInstrDesc & getBrCond(RISCVCC::CondCode CC) const
bool isFunctionSafeToOutlineFrom(MachineFunction &MF, bool OutlineFromLinkOnceODRs) const override
unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, ArrayRef< MachineOperand > Cond, const DebugLoc &dl, int *BytesAdded=nullptr) const override
bool hasReassociableSibling(const MachineInstr &Inst, bool &Commuted) const override
RISCVInstrInfo(RISCVSubtarget &STI)
void copyPhysRegVector(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, MCRegister DstReg, MCRegister SrcReg, bool KillSrc, const TargetRegisterClass *RegClass) const
void genAlternativeCodeSequence(MachineInstr &Root, unsigned Pattern, SmallVectorImpl< MachineInstr * > &InsInstrs, SmallVectorImpl< MachineInstr * > &DelInstrs, DenseMap< unsigned, unsigned > &InstrIdxForVirtReg) const override
MachineInstr * optimizeSelect(MachineInstr &MI, SmallPtrSetImpl< MachineInstr * > &SeenMIs, bool) const override
bool canFoldIntoAddrMode(const MachineInstr &MemI, Register Reg, const MachineInstr &AddrI, ExtAddrMode &AM) const override
void insertIndirectBranch(MachineBasicBlock &MBB, MachineBasicBlock &NewDestBB, MachineBasicBlock &RestoreBB, const DebugLoc &DL, int64_t BrOffset, RegScavenger *RS) const override
bool isAsCheapAsAMove(const MachineInstr &MI) const override
bool verifyInstruction(const MachineInstr &MI, StringRef &ErrInfo) const override
bool getMemOperandWithOffsetWidth(const MachineInstr &LdSt, const MachineOperand *&BaseOp, int64_t &Offset, LocationSize &Width, const TargetRegisterInfo *TRI) const
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, MCRegister DstReg, MCRegister SrcReg, bool KillSrc) const override
void getReassociateOperandIndices(const MachineInstr &Root, unsigned Pattern, std::array< unsigned, 5 > &OperandIndices) const override
const RISCVSubtarget & STI
Register isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const override
std::optional< unsigned > getInverseOpcode(unsigned Opcode) const override
ArrayRef< std::pair< unsigned, const char * > > getSerializableDirectMachineOperandTargetFlags() const override
MachineTraceStrategy getMachineCombinerTraceStrategy() const override
unsigned getInstSizeInBytes(const MachineInstr &MI) const override
virtual outliner::InstrType getOutliningTypeImpl(MachineBasicBlock::iterator &MBBI, unsigned Flags) const override
std::optional< RegImmPair > isAddImmediate(const MachineInstr &MI, Register Reg) const override
bool reverseBranchCondition(SmallVectorImpl< MachineOperand > &Cond) const override
ArrayRef< std::pair< MachineMemOperand::Flags, const char * > > getSerializableMachineMemOperandTargetFlags() const override
MCInst getNop() const override
MachineInstr * foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI, ArrayRef< unsigned > Ops, MachineBasicBlock::iterator InsertPt, int FrameIndex, LiveIntervals *LIS=nullptr, VirtRegMap *VRM=nullptr) const override
bool isMBBSafeToOutlineFrom(MachineBasicBlock &MBB, unsigned &Flags) const override
bool getMemOperandsWithOffsetWidth(const MachineInstr &MI, SmallVectorImpl< const MachineOperand * > &BaseOps, int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width, const TargetRegisterInfo *TRI) const override
void buildOutlinedFrame(MachineBasicBlock &MBB, MachineFunction &MF, const outliner::OutlinedFunction &OF) const override
void finalizeInsInstrs(MachineInstr &Root, unsigned &Pattern, SmallVectorImpl< MachineInstr * > &InsInstrs) const override
std::pair< unsigned, unsigned > decomposeMachineOperandsTargetFlags(unsigned TF) const override
MachineInstr * commuteInstructionImpl(MachineInstr &MI, bool NewMI, unsigned OpIdx1, unsigned OpIdx2) const override
bool hasReassociableOperands(const MachineInstr &Inst, const MachineBasicBlock *MBB) const override
MachineBasicBlock * getBranchDestBlock(const MachineInstr &MI) const override
std::string createMIROperandComment(const MachineInstr &MI, const MachineOperand &Op, unsigned OpIdx, const TargetRegisterInfo *TRI) const override
bool shouldOutlineFromFunctionByDefault(MachineFunction &MF) const override
bool findCommutedOpIndices(const MachineInstr &MI, unsigned &SrcOpIdx1, unsigned &SrcOpIdx2) const override
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify) const override
MachineBasicBlock::iterator insertOutlinedCall(Module &M, MachineBasicBlock &MBB, MachineBasicBlock::iterator &It, MachineFunction &MF, outliner::Candidate &C) const override
bool isBranchOffsetInRange(unsigned BranchOpc, int64_t BrOffset) const override
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register DstReg, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, Register VReg) const override
bool isAssociativeAndCommutative(const MachineInstr &Inst, bool Invert) const override
CombinerObjective getCombinerObjective(unsigned Pattern) const override
bool getMachineCombinerPatterns(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns, bool DoRegPressureReduce) const override
bool optimizeCondBranch(MachineInstr &MI) const override
std::optional< DestSourcePair > isCopyInstrImpl(const MachineInstr &MI) const override
bool analyzeSelect(const MachineInstr &MI, SmallVectorImpl< MachineOperand > &Cond, unsigned &TrueOp, unsigned &FalseOp, bool &Optimizable) const override
bool shouldClusterMemOps(ArrayRef< const MachineOperand * > BaseOps1, int64_t Offset1, bool OffsetIsScalable1, ArrayRef< const MachineOperand * > BaseOps2, int64_t Offset2, bool OffsetIsScalable2, unsigned ClusterSize, unsigned NumBytes) const override
bool areMemAccessesTriviallyDisjoint(const MachineInstr &MIa, const MachineInstr &MIb) const override
void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register SrcReg, bool IsKill, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, Register VReg) const override
RISCVMachineFunctionInfo - This class is derived from MachineFunctionInfo and contains private RISCV-...
int getBranchRelaxationScratchFrameIndex() const
bool hasStdExtCOrZca() const
const RISCVRegisterInfo * getRegisterInfo() const override
void enterBasicBlockEnd(MachineBasicBlock &MBB)
Start tracking liveness from the end of basic block MBB.
void setRegUsed(Register Reg, LaneBitmask LaneMask=LaneBitmask::getAll())
Tell the scavenger a register is used.
Register scavengeRegisterBackwards(const TargetRegisterClass &RC, MachineBasicBlock::iterator To, bool RestoreAfter, int SPAdj, bool AllowSpill=true)
Make a register of the specific register class available from the current position backwards to the p...
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
SlotIndex - An opaque wrapper around machine indexes.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
bool erase(PtrType Ptr)
erase - If the set contains the specified pointer, remove it and return true, otherwise return false.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
MI-level stackmap operands.
uint32_t getNumPatchBytes() const
Return the number of patchable bytes the given stackmap should emit.
MI-level Statepoint operands.
uint32_t getNumPatchBytes() const
Return the number of patchable bytes the given statepoint should emit.
StringRef - Represent a constant reference to a string, i.e.
TargetInstrInfo - Interface to description of machine instruction set.
virtual bool findCommutedOpIndices(const MachineInstr &MI, unsigned &SrcOpIdx1, unsigned &SrcOpIdx2) const
Returns true iff the routine could find two commutable operands in the given machine instruction.
virtual bool hasReassociableOperands(const MachineInstr &Inst, const MachineBasicBlock *MBB) const
Return true when \P Inst has reassociable operands in the same \P MBB.
virtual void genAlternativeCodeSequence(MachineInstr &Root, unsigned Pattern, SmallVectorImpl< MachineInstr * > &InsInstrs, SmallVectorImpl< MachineInstr * > &DelInstrs, DenseMap< unsigned, unsigned > &InstIdxForVirtReg) const
When getMachineCombinerPatterns() finds patterns, this function generates the instructions that could...
virtual bool getMachineCombinerPatterns(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns, bool DoRegPressureReduce) const
Return true when there is potentially a faster code sequence for an instruction chain ending in Root.
virtual bool isMBBSafeToOutlineFrom(MachineBasicBlock &MBB, unsigned &Flags) const
Optional target hook that returns true if MBB is safe to outline from, and returns any target-specifi...
virtual void getReassociateOperandIndices(const MachineInstr &Root, unsigned Pattern, std::array< unsigned, 5 > &OperandIndices) const
The returned array encodes the operand index for each parameter because the operands may be commuted;...
virtual CombinerObjective getCombinerObjective(unsigned Pattern) const
Return the objective of a combiner pattern.
virtual MachineInstr * commuteInstructionImpl(MachineInstr &MI, bool NewMI, unsigned OpIdx1, unsigned OpIdx2) const
This method commutes the operands of the given machine instruction MI.
virtual bool hasReassociableSibling(const MachineInstr &Inst, bool &Commuted) const
Return true when \P Inst has reassociable sibling.
virtual std::string createMIROperandComment(const MachineInstr &MI, const MachineOperand &Op, unsigned OpIdx, const TargetRegisterInfo *TRI) const
const uint8_t TSFlags
Configurable target specific flags.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
virtual const TargetInstrInfo * getInstrInfo() const
Target - Wrapper for Target specific information.
A raw_ostream that writes to an std::string.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
CondCode getOppositeBranchCondition(CondCode)
unsigned getBrCond(CondCode CC)
static unsigned getVecPolicyOpNum(const MCInstrDesc &Desc)
static bool usesMaskPolicy(uint64_t TSFlags)
static bool hasRoundModeOp(uint64_t TSFlags)
static unsigned getVLOpNum(const MCInstrDesc &Desc)
static bool hasVLOp(uint64_t TSFlags)
static bool hasVecPolicyOp(uint64_t TSFlags)
static bool isRVVWideningReduction(uint64_t TSFlags)
static unsigned getSEWOpNum(const MCInstrDesc &Desc)
static bool hasSEWOp(uint64_t TSFlags)
static bool isFirstDefTiedToFirstUse(const MCInstrDesc &Desc)
InstSeq generateInstSeq(int64_t Val, const MCSubtargetInfo &STI)
@ OPERAND_UIMMLOG2XLEN_NONZERO
@ OPERAND_SIMM12_LSB00000
@ OPERAND_FIRST_RISCV_IMM
@ OPERAND_UIMM10_LSB00_NONZERO
@ OPERAND_SIMM10_LSB0000_NONZERO
static RISCVII::VLMUL getLMul(uint64_t TSFlags)
static unsigned getNF(uint64_t TSFlags)
static bool isTailAgnostic(unsigned VType)
static RISCVII::VLMUL getVLMUL(unsigned VType)
std::pair< unsigned, bool > decodeVLMUL(RISCVII::VLMUL VLMUL)
static bool isValidSEW(unsigned SEW)
void printVType(unsigned VType, raw_ostream &OS)
static unsigned getSEW(unsigned VType)
bool hasEqualFRM(const MachineInstr &MI1, const MachineInstr &MI2)
std::optional< unsigned > getVectorLowDemandedScalarBits(uint16_t Opcode, unsigned Log2SEW)
int16_t getNamedOperandIdx(uint16_t Opcode, uint16_t NamedIndex)
unsigned getRVVMCOpcode(unsigned RVVPseudoOpcode)
bool isSEXT_W(const MachineInstr &MI)
bool isFaultFirstLoad(const MachineInstr &MI)
std::optional< std::pair< unsigned, unsigned > > isRVVSpillForZvlsseg(unsigned Opcode)
bool isZEXT_B(const MachineInstr &MI)
bool isRVVSpill(const MachineInstr &MI)
bool isZEXT_W(const MachineInstr &MI)
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Define
Register definition.
@ Kill
The last use of a register.
@ Undef
Value of the register doesn't matter.
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
InstrType
Represents how an instruction should be mapped by the outliner.
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
MachineTraceStrategy
Strategies for selecting traces.
@ TS_MinInstrCount
Select the trace through a block that has the fewest instructions.
@ TS_Local
Select the trace that contains only the current basic block.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
static const MachineMemOperand::Flags MONontemporalBit1
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are are tuples (A,...
static const MachineMemOperand::Flags MONontemporalBit0
const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=6)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
unsigned getDeadRegState(bool B)
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
CombinerObjective
The combiner's goal may differ based on which pattern it is attempting to optimize.
unsigned getKillRegState(bool B)
bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
unsigned getRenamableRegState(bool B)
DWARFExpression::Operation Op
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Description of the encoding of one expression Op.
Used to describe addressing mode similar to ExtAddrMode in CodeGenPrepare.
This represents a simple continuous liveness interval for a value.
static MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
Used to describe a register and immediate addition.
An individual sequence of instructions to be replaced with a call to an outlined function.
The information necessary to create an outlined function for some class of candidate.