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"
83 int &FrameIndex)
const {
90 unsigned &MemBytes)
const {
91 switch (
MI.getOpcode()) {
114 if (
MI.getOperand(1).isFI() &&
MI.getOperand(2).isImm() &&
115 MI.getOperand(2).getImm() == 0) {
116 FrameIndex =
MI.getOperand(1).getIndex();
117 return MI.getOperand(0).getReg();
124 int &FrameIndex)
const {
131 unsigned &MemBytes)
const {
132 switch (
MI.getOpcode()) {
152 if (
MI.getOperand(1).isFI() &&
MI.getOperand(2).isImm() &&
153 MI.getOperand(2).getImm() == 0) {
154 FrameIndex =
MI.getOperand(1).getIndex();
155 return MI.getOperand(0).getReg();
163 return DstReg > SrcReg && (DstReg - SrcReg) < NumRegs;
174 assert(
MBBI->getOpcode() == TargetOpcode::COPY &&
175 "Unexpected COPY instruction.");
179 bool FoundDef =
false;
180 bool FirstVSetVLI =
false;
181 unsigned FirstSEW = 0;
184 if (
MBBI->isMetaInstruction())
187 if (
MBBI->getOpcode() == RISCV::PseudoVSETVLI ||
188 MBBI->getOpcode() == RISCV::PseudoVSETVLIX0 ||
189 MBBI->getOpcode() == RISCV::PseudoVSETIVLI) {
199 unsigned FirstVType =
MBBI->getOperand(2).getImm();
204 if (FirstLMul != LMul)
209 if (
MBBI->getOperand(0).getReg() != RISCV::X0)
211 if (
MBBI->getOperand(1).isImm())
213 if (
MBBI->getOperand(1).getReg() != RISCV::X0)
219 unsigned VType =
MBBI->getOperand(2).getImm();
237 }
else if (
MBBI->isInlineAsm() ||
MBBI->isCall()) {
239 }
else if (
MBBI->getNumDefs()) {
242 if (
MBBI->modifiesRegister(RISCV::VL))
248 if (!MO.isReg() || !MO.isDef())
250 if (!FoundDef &&
TRI->regsOverlap(MO.getReg(), SrcReg)) {
265 if (MO.getReg() != SrcReg)
307 unsigned VVOpc, VIOpc;
312 Opc = RISCV::VMV1R_V;
313 SubRegIdx = RISCV::sub_vrm1_0;
314 VVOpc = RISCV::PseudoVMV_V_V_M1;
315 VIOpc = RISCV::PseudoVMV_V_I_M1;
318 Opc = RISCV::VMV2R_V;
319 SubRegIdx = RISCV::sub_vrm2_0;
320 VVOpc = RISCV::PseudoVMV_V_V_M2;
321 VIOpc = RISCV::PseudoVMV_V_I_M2;
324 Opc = RISCV::VMV4R_V;
325 SubRegIdx = RISCV::sub_vrm4_0;
326 VVOpc = RISCV::PseudoVMV_V_V_M4;
327 VIOpc = RISCV::PseudoVMV_V_I_M4;
331 Opc = RISCV::VMV8R_V;
332 SubRegIdx = RISCV::sub_vrm1_0;
333 VVOpc = RISCV::PseudoVMV_V_V_M8;
334 VIOpc = RISCV::PseudoVMV_V_I_M8;
338 bool UseVMV_V_V =
false;
339 bool UseVMV_V_I =
false;
345 if (DefMBBI->getOpcode() == VIOpc) {
356 MIB = MIB.add(DefMBBI->getOperand(2));
370 int I = 0,
End = NF, Incr = 1;
371 unsigned SrcEncoding =
TRI->getEncodingValue(SrcReg);
372 unsigned DstEncoding =
TRI->getEncodingValue(DstReg);
376 assert(!Fractional &&
"It is impossible be fractional lmul here.");
383 for (;
I !=
End;
I += Incr) {
389 MIB = MIB.add(DefMBBI->getOperand(2));
391 MIB = MIB.addReg(
TRI->getSubReg(SrcReg, SubRegIdx +
I),
410 if (RISCV::GPRRegClass.
contains(DstReg, SrcReg)) {
417 if (RISCV::GPRPairRegClass.
contains(DstReg, SrcReg)) {
420 TRI->getSubReg(DstReg, RISCV::sub_gpr_even))
421 .
addReg(
TRI->getSubReg(SrcReg, RISCV::sub_gpr_even),
425 TRI->getSubReg(DstReg, RISCV::sub_gpr_odd))
426 .
addReg(
TRI->getSubReg(SrcReg, RISCV::sub_gpr_odd),
433 if (RISCV::VCSRRegClass.
contains(SrcReg) &&
434 RISCV::GPRRegClass.
contains(DstReg)) {
436 .
addImm(RISCVSysReg::lookupSysRegByName(
TRI->getName(SrcReg))->Encoding)
441 if (RISCV::FPR16RegClass.
contains(DstReg, SrcReg)) {
443 if (
STI.hasStdExtZfh()) {
444 Opc = RISCV::FSGNJ_H;
447 (
STI.hasStdExtZfhmin() ||
STI.hasStdExtZfbfmin()) &&
448 "Unexpected extensions");
450 DstReg =
TRI->getMatchingSuperReg(DstReg, RISCV::sub_16,
451 &RISCV::FPR32RegClass);
452 SrcReg =
TRI->getMatchingSuperReg(SrcReg, RISCV::sub_16,
453 &RISCV::FPR32RegClass);
454 Opc = RISCV::FSGNJ_S;
462 if (RISCV::FPR32RegClass.
contains(DstReg, SrcReg)) {
469 if (RISCV::FPR64RegClass.
contains(DstReg, SrcReg)) {
476 if (RISCV::FPR32RegClass.
contains(DstReg) &&
477 RISCV::GPRRegClass.
contains(SrcReg)) {
483 if (RISCV::GPRRegClass.
contains(DstReg) &&
484 RISCV::FPR32RegClass.
contains(SrcReg)) {
490 if (RISCV::FPR64RegClass.
contains(DstReg) &&
491 RISCV::GPRRegClass.
contains(SrcReg)) {
498 if (RISCV::GPRRegClass.
contains(DstReg) &&
499 RISCV::FPR64RegClass.
contains(SrcReg)) {
507 if (RISCV::VRRegClass.
contains(DstReg, SrcReg)) {
512 if (RISCV::VRM2RegClass.
contains(DstReg, SrcReg)) {
517 if (RISCV::VRM4RegClass.
contains(DstReg, SrcReg)) {
522 if (RISCV::VRM8RegClass.
contains(DstReg, SrcReg)) {
527 if (RISCV::VRN2M1RegClass.
contains(DstReg, SrcReg)) {
533 if (RISCV::VRN2M2RegClass.
contains(DstReg, SrcReg)) {
539 if (RISCV::VRN2M4RegClass.
contains(DstReg, SrcReg)) {
545 if (RISCV::VRN3M1RegClass.
contains(DstReg, SrcReg)) {
551 if (RISCV::VRN3M2RegClass.
contains(DstReg, SrcReg)) {
557 if (RISCV::VRN4M1RegClass.
contains(DstReg, SrcReg)) {
563 if (RISCV::VRN4M2RegClass.
contains(DstReg, SrcReg)) {
569 if (RISCV::VRN5M1RegClass.
contains(DstReg, SrcReg)) {
575 if (RISCV::VRN6M1RegClass.
contains(DstReg, SrcReg)) {
581 if (RISCV::VRN7M1RegClass.
contains(DstReg, SrcReg)) {
587 if (RISCV::VRN8M1RegClass.
contains(DstReg, SrcReg)) {
598 Register SrcReg,
bool IsKill,
int FI,
606 bool IsScalableVector =
true;
607 if (RISCV::GPRRegClass.hasSubClassEq(RC)) {
608 Opcode =
TRI->getRegSizeInBits(RISCV::GPRRegClass) == 32 ?
609 RISCV::SW : RISCV::SD;
610 IsScalableVector =
false;
611 }
else if (RISCV::GPRPairRegClass.hasSubClassEq(RC)) {
612 Opcode = RISCV::PseudoRV32ZdinxSD;
613 IsScalableVector =
false;
614 }
else if (RISCV::FPR16RegClass.hasSubClassEq(RC)) {
616 IsScalableVector =
false;
617 }
else if (RISCV::FPR32RegClass.hasSubClassEq(RC)) {
619 IsScalableVector =
false;
620 }
else if (RISCV::FPR64RegClass.hasSubClassEq(RC)) {
622 IsScalableVector =
false;
623 }
else if (RISCV::VRRegClass.hasSubClassEq(RC)) {
624 Opcode = RISCV::VS1R_V;
625 }
else if (RISCV::VRM2RegClass.hasSubClassEq(RC)) {
626 Opcode = RISCV::VS2R_V;
627 }
else if (RISCV::VRM4RegClass.hasSubClassEq(RC)) {
628 Opcode = RISCV::VS4R_V;
629 }
else if (RISCV::VRM8RegClass.hasSubClassEq(RC)) {
630 Opcode = RISCV::VS8R_V;
631 }
else if (RISCV::VRN2M1RegClass.hasSubClassEq(RC))
632 Opcode = RISCV::PseudoVSPILL2_M1;
633 else if (RISCV::VRN2M2RegClass.hasSubClassEq(RC))
634 Opcode = RISCV::PseudoVSPILL2_M2;
635 else if (RISCV::VRN2M4RegClass.hasSubClassEq(RC))
636 Opcode = RISCV::PseudoVSPILL2_M4;
637 else if (RISCV::VRN3M1RegClass.hasSubClassEq(RC))
638 Opcode = RISCV::PseudoVSPILL3_M1;
639 else if (RISCV::VRN3M2RegClass.hasSubClassEq(RC))
640 Opcode = RISCV::PseudoVSPILL3_M2;
641 else if (RISCV::VRN4M1RegClass.hasSubClassEq(RC))
642 Opcode = RISCV::PseudoVSPILL4_M1;
643 else if (RISCV::VRN4M2RegClass.hasSubClassEq(RC))
644 Opcode = RISCV::PseudoVSPILL4_M2;
645 else if (RISCV::VRN5M1RegClass.hasSubClassEq(RC))
646 Opcode = RISCV::PseudoVSPILL5_M1;
647 else if (RISCV::VRN6M1RegClass.hasSubClassEq(RC))
648 Opcode = RISCV::PseudoVSPILL6_M1;
649 else if (RISCV::VRN7M1RegClass.hasSubClassEq(RC))
650 Opcode = RISCV::PseudoVSPILL7_M1;
651 else if (RISCV::VRN8M1RegClass.hasSubClassEq(RC))
652 Opcode = RISCV::PseudoVSPILL8_M1;
656 if (IsScalableVector) {
689 bool IsScalableVector =
true;
690 if (RISCV::GPRRegClass.hasSubClassEq(RC)) {
691 Opcode =
TRI->getRegSizeInBits(RISCV::GPRRegClass) == 32 ?
692 RISCV::LW : RISCV::LD;
693 IsScalableVector =
false;
694 }
else if (RISCV::GPRPairRegClass.hasSubClassEq(RC)) {
695 Opcode = RISCV::PseudoRV32ZdinxLD;
696 IsScalableVector =
false;
697 }
else if (RISCV::FPR16RegClass.hasSubClassEq(RC)) {
699 IsScalableVector =
false;
700 }
else if (RISCV::FPR32RegClass.hasSubClassEq(RC)) {
702 IsScalableVector =
false;
703 }
else if (RISCV::FPR64RegClass.hasSubClassEq(RC)) {
705 IsScalableVector =
false;
706 }
else if (RISCV::VRRegClass.hasSubClassEq(RC)) {
707 Opcode = RISCV::VL1RE8_V;
708 }
else if (RISCV::VRM2RegClass.hasSubClassEq(RC)) {
709 Opcode = RISCV::VL2RE8_V;
710 }
else if (RISCV::VRM4RegClass.hasSubClassEq(RC)) {
711 Opcode = RISCV::VL4RE8_V;
712 }
else if (RISCV::VRM8RegClass.hasSubClassEq(RC)) {
713 Opcode = RISCV::VL8RE8_V;
714 }
else if (RISCV::VRN2M1RegClass.hasSubClassEq(RC))
715 Opcode = RISCV::PseudoVRELOAD2_M1;
716 else if (RISCV::VRN2M2RegClass.hasSubClassEq(RC))
717 Opcode = RISCV::PseudoVRELOAD2_M2;
718 else if (RISCV::VRN2M4RegClass.hasSubClassEq(RC))
719 Opcode = RISCV::PseudoVRELOAD2_M4;
720 else if (RISCV::VRN3M1RegClass.hasSubClassEq(RC))
721 Opcode = RISCV::PseudoVRELOAD3_M1;
722 else if (RISCV::VRN3M2RegClass.hasSubClassEq(RC))
723 Opcode = RISCV::PseudoVRELOAD3_M2;
724 else if (RISCV::VRN4M1RegClass.hasSubClassEq(RC))
725 Opcode = RISCV::PseudoVRELOAD4_M1;
726 else if (RISCV::VRN4M2RegClass.hasSubClassEq(RC))
727 Opcode = RISCV::PseudoVRELOAD4_M2;
728 else if (RISCV::VRN5M1RegClass.hasSubClassEq(RC))
729 Opcode = RISCV::PseudoVRELOAD5_M1;
730 else if (RISCV::VRN6M1RegClass.hasSubClassEq(RC))
731 Opcode = RISCV::PseudoVRELOAD6_M1;
732 else if (RISCV::VRN7M1RegClass.hasSubClassEq(RC))
733 Opcode = RISCV::PseudoVRELOAD7_M1;
734 else if (RISCV::VRN8M1RegClass.hasSubClassEq(RC))
735 Opcode = RISCV::PseudoVRELOAD8_M1;
739 if (IsScalableVector) {
773 if (Ops.
size() != 1 || Ops[0] != 1)
777 switch (
MI.getOpcode()) {
784 LoadOpc = RISCV::LWU;
788 LoadOpc = RISCV::LBU;
798 case RISCV::ZEXT_H_RV32:
799 case RISCV::ZEXT_H_RV64:
800 LoadOpc = RISCV::LHU;
810 return BuildMI(*
MI.getParent(), InsertPt,
MI.getDebugLoc(),
get(LoadOpc),
821 bool DstIsDead)
const {
830 bool SrcRenamable =
false;
834 bool LastItem = ++Num == Seq.
size();
839 switch (Inst.getOpndKind()) {
849 .
addReg(SrcReg, SrcRegState)
856 .
addReg(SrcReg, SrcRegState)
857 .
addReg(SrcReg, SrcRegState)
863 .
addReg(SrcReg, SrcRegState)
871 SrcRenamable = DstRenamable;
901 "Unknown conditional branch");
955 bool AllowModify)
const {
961 if (
I ==
MBB.
end() || !isUnpredicatedTerminator(*
I))
967 int NumTerminators = 0;
968 for (
auto J =
I.getReverse(); J !=
MBB.
rend() && isUnpredicatedTerminator(*J);
971 if (J->getDesc().isUnconditionalBranch() ||
972 J->getDesc().isIndirectBranch()) {
979 if (AllowModify && FirstUncondOrIndirectBr !=
MBB.
end()) {
980 while (std::next(FirstUncondOrIndirectBr) !=
MBB.
end()) {
981 std::next(FirstUncondOrIndirectBr)->eraseFromParent();
984 I = FirstUncondOrIndirectBr;
988 if (
I->getDesc().isIndirectBranch())
992 if (
I->isPreISelOpcode())
996 if (NumTerminators > 2)
1000 if (NumTerminators == 1 &&
I->getDesc().isUnconditionalBranch()) {
1006 if (NumTerminators == 1 &&
I->getDesc().isConditionalBranch()) {
1012 if (NumTerminators == 2 && std::prev(
I)->getDesc().isConditionalBranch() &&
1013 I->getDesc().isUnconditionalBranch()) {
1024 int *BytesRemoved)
const {
1031 if (!
I->getDesc().isUnconditionalBranch() &&
1032 !
I->getDesc().isConditionalBranch())
1038 I->eraseFromParent();
1045 if (!
I->getDesc().isConditionalBranch())
1051 I->eraseFromParent();
1064 assert(
TBB &&
"insertBranch must not be told to insert a fallthrough");
1066 "RISC-V branch conditions have two components!");
1099 assert(RS &&
"RegScavenger required for long branching");
1101 "new block should be inserted for expanding unconditional branch");
1104 "restore block should be inserted for restoring clobbered registers");
1111 if (!isInt<32>(BrOffset))
1113 "Branch offsets outside of the signed 32-bit range not supported");
1118 Register ScratchReg =
MRI.createVirtualRegister(&RISCV::GPRJALRRegClass);
1130 if (TmpGPR != RISCV::NoRegister)
1136 TmpGPR = RISCV::X27;
1139 if (FrameIndex == -1)
1144 TRI->eliminateFrameIndex(std::prev(
MI.getIterator()),
1147 MI.getOperand(1).setMBB(&RestoreBB);
1151 TRI->eliminateFrameIndex(RestoreBB.
back(),
1155 MRI.replaceRegWith(ScratchReg, TmpGPR);
1156 MRI.clearVirtRegs();
1161 assert((
Cond.size() == 3) &&
"Invalid branch condition!");
1201 auto isLoadImm = [](
const MachineInstr *
MI, int64_t &Imm) ->
bool {
1202 if (
MI->getOpcode() == RISCV::ADDI &&
MI->getOperand(1).isReg() &&
1203 MI->getOperand(1).getReg() == RISCV::X0) {
1204 Imm =
MI->getOperand(2).getImm();
1214 return Reg.isVirtual() && isLoadImm(
MRI.getVRegDef(Reg), Imm);
1221 auto searchConst = [&](int64_t C1) ->
Register {
1223 auto DefC1 = std::find_if(++II, E, [&](
const MachineInstr &
I) ->
bool {
1225 return isLoadImm(&
I, Imm) && Imm == C1 &&
1226 I.getOperand(0).getReg().isVirtual();
1229 return DefC1->getOperand(0).getReg();
1234 bool Modify =
false;
1236 if (isFromLoadImm(
LHS, C0) &&
MRI.hasOneUse(
LHS.getReg())) {
1241 if (
Register RegZ = searchConst(C0 + 1)) {
1247 MRI.clearKillFlags(RegZ);
1250 }
else if (isFromLoadImm(
RHS, C0) &&
MRI.hasOneUse(
RHS.getReg())) {
1255 if (
Register RegZ = searchConst(C0 - 1)) {
1261 MRI.clearKillFlags(RegZ);
1275 MI.eraseFromParent();
1282 assert(
MI.getDesc().isBranch() &&
"Unexpected opcode!");
1284 int NumOp =
MI.getNumExplicitOperands();
1285 return MI.getOperand(NumOp - 1).getMBB();
1289 int64_t BrOffset)
const {
1303 return isIntN(13, BrOffset);
1305 case RISCV::PseudoBR:
1306 return isIntN(21, BrOffset);
1307 case RISCV::PseudoJump:
1317 case RISCV::ADD:
return RISCV::PseudoCCADD;
break;
1318 case RISCV::SUB:
return RISCV::PseudoCCSUB;
break;
1319 case RISCV::SLL:
return RISCV::PseudoCCSLL;
break;
1320 case RISCV::SRL:
return RISCV::PseudoCCSRL;
break;
1321 case RISCV::SRA:
return RISCV::PseudoCCSRA;
break;
1322 case RISCV::AND:
return RISCV::PseudoCCAND;
break;
1323 case RISCV::OR:
return RISCV::PseudoCCOR;
break;
1324 case RISCV::XOR:
return RISCV::PseudoCCXOR;
break;
1326 case RISCV::ADDI:
return RISCV::PseudoCCADDI;
break;
1327 case RISCV::SLLI:
return RISCV::PseudoCCSLLI;
break;
1328 case RISCV::SRLI:
return RISCV::PseudoCCSRLI;
break;
1329 case RISCV::SRAI:
return RISCV::PseudoCCSRAI;
break;
1330 case RISCV::ANDI:
return RISCV::PseudoCCANDI;
break;
1331 case RISCV::ORI:
return RISCV::PseudoCCORI;
break;
1332 case RISCV::XORI:
return RISCV::PseudoCCXORI;
break;
1334 case RISCV::ADDW:
return RISCV::PseudoCCADDW;
break;
1335 case RISCV::SUBW:
return RISCV::PseudoCCSUBW;
break;
1336 case RISCV::SLLW:
return RISCV::PseudoCCSLLW;
break;
1337 case RISCV::SRLW:
return RISCV::PseudoCCSRLW;
break;
1338 case RISCV::SRAW:
return RISCV::PseudoCCSRAW;
break;
1340 case RISCV::ADDIW:
return RISCV::PseudoCCADDIW;
break;
1341 case RISCV::SLLIW:
return RISCV::PseudoCCSLLIW;
break;
1342 case RISCV::SRLIW:
return RISCV::PseudoCCSRLIW;
break;
1343 case RISCV::SRAIW:
return RISCV::PseudoCCSRAIW;
break;
1345 case RISCV::ANDN:
return RISCV::PseudoCCANDN;
break;
1346 case RISCV::ORN:
return RISCV::PseudoCCORN;
break;
1347 case RISCV::XNOR:
return RISCV::PseudoCCXNOR;
break;
1350 return RISCV::INSTRUCTION_LIST_END;
1358 if (!Reg.isVirtual())
1360 if (!
MRI.hasOneNonDBGUse(Reg))
1369 if (
MI->getOpcode() == RISCV::ADDI &&
MI->getOperand(1).isReg() &&
1370 MI->getOperand(1).getReg() == RISCV::X0)
1375 if (MO.isFI() || MO.isCPI() || MO.isJTI())
1385 if (MO.getReg().isPhysical() && !
MRI.isConstantPhysReg(MO.getReg()))
1388 bool DontMoveAcrossStores =
true;
1389 if (!
MI->isSafeToMove(
nullptr, DontMoveAcrossStores))
1396 unsigned &TrueOp,
unsigned &FalseOp,
1397 bool &Optimizable)
const {
1398 assert(
MI.getOpcode() == RISCV::PseudoCCMOVGPR &&
1399 "Unknown select instruction");
1409 Cond.push_back(
MI.getOperand(1));
1410 Cond.push_back(
MI.getOperand(2));
1411 Cond.push_back(
MI.getOperand(3));
1413 Optimizable =
STI.hasShortForwardBranchOpt();
1420 bool PreferFalse)
const {
1421 assert(
MI.getOpcode() == RISCV::PseudoCCMOVGPR &&
1422 "Unknown select instruction");
1423 if (!
STI.hasShortForwardBranchOpt())
1429 bool Invert = !
DefMI;
1437 Register DestReg =
MI.getOperand(0).getReg();
1439 if (!
MRI.constrainRegClass(DestReg, PreviousClass))
1443 assert(PredOpc != RISCV::INSTRUCTION_LIST_END &&
"Unexpected opcode!");
1450 NewMI.
add(
MI.getOperand(1));
1451 NewMI.
add(
MI.getOperand(2));
1460 NewMI.
add(FalseReg);
1484 if (
MI.isMetaInstruction())
1487 unsigned Opcode =
MI.getOpcode();
1489 if (Opcode == TargetOpcode::INLINEASM ||
1490 Opcode == TargetOpcode::INLINEASM_BR) {
1493 return getInlineAsmLength(
MI.getOperand(0).getSymbolName(),
1494 *
TM.getMCAsmInfo());
1497 if (!
MI.memoperands_empty()) {
1502 if (ST.hasStdExtCOrZca() && ST.enableRVCHintInstrs()) {
1503 if (isCompressibleInst(
MI,
STI))
1511 if (Opcode == TargetOpcode::BUNDLE)
1512 return getInstBundleLength(
MI);
1514 if (
MI.getParent() &&
MI.getParent()->getParent()) {
1515 if (isCompressibleInst(
MI,
STI))
1520 case TargetOpcode::STACKMAP:
1523 case TargetOpcode::PATCHPOINT:
1526 case TargetOpcode::STATEPOINT:
1530 return get(Opcode).getSize();
1534unsigned RISCVInstrInfo::getInstBundleLength(
const MachineInstr &
MI)
const {
1538 while (++
I != E &&
I->isInsideBundle()) {
1539 assert(!
I->isBundle() &&
"No nested bundle!");
1546 const unsigned Opcode =
MI.getOpcode();
1550 case RISCV::FSGNJ_D:
1551 case RISCV::FSGNJ_S:
1552 case RISCV::FSGNJ_H:
1553 case RISCV::FSGNJ_D_INX:
1554 case RISCV::FSGNJ_D_IN32X:
1555 case RISCV::FSGNJ_S_INX:
1556 case RISCV::FSGNJ_H_INX:
1558 return MI.getOperand(1).isReg() &&
MI.getOperand(2).isReg() &&
1559 MI.getOperand(1).getReg() ==
MI.getOperand(2).getReg();
1563 return (
MI.getOperand(1).isReg() &&
1564 MI.getOperand(1).getReg() == RISCV::X0) ||
1565 (
MI.getOperand(2).isImm() &&
MI.getOperand(2).getImm() == 0);
1567 return MI.isAsCheapAsAMove();
1570std::optional<DestSourcePair>
1574 switch (
MI.getOpcode()) {
1579 if (
MI.getOperand(1).isReg() &&
MI.getOperand(2).isImm() &&
1580 MI.getOperand(2).getImm() == 0)
1583 case RISCV::FSGNJ_D:
1584 case RISCV::FSGNJ_S:
1585 case RISCV::FSGNJ_H:
1586 case RISCV::FSGNJ_D_INX:
1587 case RISCV::FSGNJ_D_IN32X:
1588 case RISCV::FSGNJ_S_INX:
1589 case RISCV::FSGNJ_H_INX:
1591 if (
MI.getOperand(1).isReg() &&
MI.getOperand(2).isReg() &&
1592 MI.getOperand(1).getReg() ==
MI.getOperand(2).getReg())
1596 return std::nullopt;
1604 const auto &SchedModel =
STI.getSchedModel();
1605 return (!SchedModel.hasInstrSchedModel() || SchedModel.isOutOfOrder())
1622 RISCV::OpName::frm) < 0;
1624 "New instructions require FRM whereas the old one does not have it");
1631 for (
auto *NewMI : InsInstrs) {
1633 NewMI->getOpcode(), RISCV::OpName::frm)) ==
1634 NewMI->getNumOperands() &&
1635 "Instruction has unexpected number of operands");
1677 bool &Commuted)
const {
1682 unsigned OperandIdx = Commuted ? 2 : 1;
1686 int16_t InstFrmOpIdx =
1688 int16_t SiblingFrmOpIdx =
1691 return (InstFrmOpIdx < 0 && SiblingFrmOpIdx < 0) ||
1696 bool Invert)
const {
1702 Opc = *InverseOpcode;
1747std::optional<unsigned>
1751 return std::nullopt;
1753 return RISCV::FSUB_H;
1755 return RISCV::FSUB_S;
1757 return RISCV::FSUB_D;
1759 return RISCV::FADD_H;
1761 return RISCV::FADD_S;
1763 return RISCV::FADD_D;
1777 bool DoRegPressureReduce) {
1793 if (DoRegPressureReduce && !
MRI.hasOneNonDBGUse(
MI->getOperand(0).getReg()))
1805 bool DoRegPressureReduce) {
1807 bool IsFAdd =
isFADD(Opc);
1808 if (!IsFAdd && !
isFSUB(Opc))
1812 DoRegPressureReduce)) {
1818 DoRegPressureReduce)) {
1828 bool DoRegPressureReduce) {
1834 bool DoRegPressureReduce)
const {
1840 DoRegPressureReduce);
1849 return RISCV::FMADD_H;
1851 return RISCV::FMADD_S;
1853 return RISCV::FMADD_D;
1898 bool Mul1IsKill = Mul1.
isKill();
1899 bool Mul2IsKill = Mul2.
isKill();
1900 bool AddendIsKill = Addend.
isKill();
1909 BuildMI(*MF, MergedLoc,
TII->get(FusedOpc), DstReg)
1930 DelInstrs, InstrIdxForVirtReg);
1952 unsigned OpType = Operand.OperandType;
1957 int64_t Imm = MO.
getImm();
1964#define CASE_OPERAND_UIMM(NUM) \
1965 case RISCVOp::OPERAND_UIMM##NUM: \
1966 Ok = isUInt<NUM>(Imm); \
1980 Ok = isShiftedUInt<1, 1>(Imm);
1983 Ok = isShiftedUInt<5, 2>(Imm);
1986 Ok = isShiftedUInt<6, 2>(Imm);
1989 Ok = isShiftedUInt<5, 3>(Imm);
1992 Ok = isUInt<8>(Imm) && Imm >= 32;
1995 Ok = isShiftedUInt<6, 3>(Imm);
1998 Ok = isShiftedInt<6, 4>(Imm) && (Imm != 0);
2001 Ok = isShiftedUInt<8, 2>(Imm) && (Imm != 0);
2010 Ok = (isInt<5>(Imm) && Imm != -16) || Imm == 16;
2016 Ok = Imm != 0 && isInt<6>(Imm);
2019 Ok = isUInt<10>(Imm);
2022 Ok = isUInt<11>(Imm);
2025 Ok = isInt<12>(Imm);
2028 Ok = isShiftedInt<7, 5>(Imm);
2031 Ok =
STI.
is64Bit() ? isUInt<6>(Imm) : isUInt<5>(Imm);
2034 Ok =
STI.
is64Bit() ? isUInt<6>(Imm) : isUInt<5>(Imm);
2035 Ok = Ok && Imm != 0;
2038 Ok = (isUInt<5>(Imm) && Imm != 0) ||
2039 (Imm >= 0xfffe0 && Imm <= 0xfffff);
2042 Ok = Imm >= 0 && Imm <= 10;
2045 Ok = Imm >= 0 && Imm <= 7;
2048 Ok = Imm >= 1 && Imm <= 10;
2051 Ok = Imm >= 2 && Imm <= 14;
2055 ErrInfo =
"Invalid immediate";
2065 if (!
Op.isImm() && !
Op.isReg()) {
2066 ErrInfo =
"Invalid operand type for VL operand";
2069 if (
Op.isReg() &&
Op.getReg() != RISCV::NoRegister) {
2071 auto *RC =
MRI.getRegClass(
Op.getReg());
2072 if (!RISCV::GPRRegClass.hasSubClassEq(RC)) {
2073 ErrInfo =
"Invalid register class for VL operand";
2078 ErrInfo =
"VL operand w/o SEW operand?";
2084 if (!
MI.getOperand(OpIdx).isImm()) {
2085 ErrInfo =
"SEW value expected to be an immediate";
2088 uint64_t Log2SEW =
MI.getOperand(OpIdx).getImm();
2090 ErrInfo =
"Unexpected SEW value";
2093 unsigned SEW = Log2SEW ? 1 << Log2SEW : 8;
2095 ErrInfo =
"Unexpected SEW value";
2101 if (!
MI.getOperand(OpIdx).isImm()) {
2102 ErrInfo =
"Policy operand expected to be an immediate";
2105 uint64_t Policy =
MI.getOperand(OpIdx).getImm();
2107 ErrInfo =
"Invalid Policy Value";
2111 ErrInfo =
"policy operand w/o VL operand?";
2119 if (!
MI.isRegTiedToUseOperand(0, &UseOpIdx)) {
2120 ErrInfo =
"policy operand w/o tied operand?";
2163 int64_t NewOffset = OldOffset + Disp;
2165 NewOffset = SignExtend64<32>(NewOffset);
2167 if (!isInt<12>(NewOffset))
2185 "Addressing mode not supported for folding");
2227 OffsetIsScalable =
false;
2243 if (BaseOps1.
front()->isIdenticalTo(*BaseOps2.
front()))
2251 if (MO1->getAddrSpace() != MO2->getAddrSpace())
2254 auto Base1 = MO1->getValue();
2255 auto Base2 = MO2->getValue();
2256 if (!Base1 || !Base2)
2261 if (isa<UndefValue>(Base1) || isa<UndefValue>(Base2))
2264 return Base1 == Base2;
2270 int64_t Offset2,
bool OffsetIsScalable2,
unsigned ClusterSize,
2271 unsigned NumBytes)
const {
2274 if (!BaseOps1.
empty() && !BaseOps2.
empty()) {
2279 }
else if (!BaseOps1.
empty() || !BaseOps2.
empty()) {
2285 BaseOps1.
front()->getParent()->getMF()->getSubtarget().getCacheLineSize();
2291 return ClusterSize <= 4 && std::abs(Offset1 - Offset2) <
CacheLineSize;
2341 int64_t OffsetA = 0, OffsetB = 0;
2346 int LowOffset = std::min(OffsetA, OffsetB);
2347 int HighOffset = std::max(OffsetA, OffsetB);
2348 LocationSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
2350 LowOffset + (int)LowWidth.
getValue() <= HighOffset)
2357std::pair<unsigned, unsigned>
2360 return std::make_pair(TF & Mask, TF & ~Mask);
2365 using namespace RISCVII;
2366 static const std::pair<unsigned, const char *> TargetFlags[] = {
2367 {MO_CALL,
"riscv-call"},
2368 {MO_LO,
"riscv-lo"},
2369 {MO_HI,
"riscv-hi"},
2370 {MO_PCREL_LO,
"riscv-pcrel-lo"},
2371 {MO_PCREL_HI,
"riscv-pcrel-hi"},
2372 {MO_GOT_HI,
"riscv-got-hi"},
2373 {MO_TPREL_LO,
"riscv-tprel-lo"},
2374 {MO_TPREL_HI,
"riscv-tprel-hi"},
2375 {MO_TPREL_ADD,
"riscv-tprel-add"},
2376 {MO_TLS_GOT_HI,
"riscv-tls-got-hi"},
2377 {MO_TLS_GD_HI,
"riscv-tls-gd-hi"},
2378 {MO_TLSDESC_HI,
"riscv-tlsdesc-hi"},
2379 {MO_TLSDESC_LOAD_LO,
"riscv-tlsdesc-load-lo"},
2380 {MO_TLSDESC_ADD_LO,
"riscv-tlsdesc-add-lo"},
2381 {MO_TLSDESC_CALL,
"riscv-tlsdesc-call"}};
2389 if (!OutlineFromLinkOnceODRs &&
F.hasLinkOnceODRLinkage())
2402 unsigned &Flags)
const {
2417std::optional<outliner::OutlinedFunction>
2419 std::vector<outliner::Candidate> &RepeatedSequenceLocs)
const {
2425 return !
C.isAvailableAcrossAndOutOfSeq(RISCV::X5, *
TRI);
2431 if (RepeatedSequenceLocs.size() < 2)
2432 return std::nullopt;
2434 unsigned SequenceSize = 0;
2436 for (
auto &
MI : RepeatedSequenceLocs[0])
2440 unsigned CallOverhead = 8;
2441 for (
auto &
C : RepeatedSequenceLocs)
2445 unsigned FrameOverhead = 4;
2446 if (RepeatedSequenceLocs[0]
2448 ->getSubtarget<RISCVSubtarget>()
2458 unsigned Flags)
const {
2463 const auto &
F =
MI.getMF()->getFunction();
2466 if (
MI.isCFIInstruction())
2480 if (
MI.modifiesRegister(RISCV::X5,
TRI) ||
2481 MI.getDesc().hasImplicitDefOfPhysReg(RISCV::X5))
2485 for (
const auto &MO :
MI.operands()) {
2490 (
MI.getMF()->getTarget().getFunctionSections() ||
F.hasComdat() ||
2503 bool Changed =
true;
2508 for (;
I != E; ++
I) {
2509 if (
I->isCFIInstruction()) {
2510 I->removeFromParent();
2533 .addGlobalAddress(M.getNamedValue(MF.
getName()), 0,
2544 return std::nullopt;
2548 if (
MI.getOpcode() == RISCV::ADDI &&
MI.getOperand(1).isReg() &&
2549 MI.getOperand(2).isImm())
2550 return RegImmPair{
MI.getOperand(1).getReg(),
MI.getOperand(2).getImm()};
2552 return std::nullopt;
2560 std::string GenericComment =
2562 if (!GenericComment.empty())
2563 return GenericComment;
2567 return std::string();
2569 std::string Comment;
2576 if ((
MI.getOpcode() == RISCV::VSETVLI ||
MI.getOpcode() == RISCV::VSETIVLI ||
2577 MI.getOpcode() == RISCV::PseudoVSETVLI ||
2578 MI.getOpcode() == RISCV::PseudoVSETIVLI ||
2579 MI.getOpcode() == RISCV::PseudoVSETVLIX0) &&
2581 unsigned Imm =
MI.getOperand(OpIdx).getImm();
2585 unsigned Log2SEW =
MI.getOperand(OpIdx).getImm();
2586 unsigned SEW = Log2SEW ? 1 << Log2SEW : 8;
2591 unsigned Policy =
MI.getOperand(OpIdx).getImm();
2593 "Invalid Policy Value");
2603#define CASE_VFMA_OPCODE_COMMON(OP, TYPE, LMUL) \
2604 RISCV::PseudoV##OP##_##TYPE##_##LMUL
2606#define CASE_VFMA_OPCODE_LMULS_M1(OP, TYPE) \
2607 CASE_VFMA_OPCODE_COMMON(OP, TYPE, M1): \
2608 case CASE_VFMA_OPCODE_COMMON(OP, TYPE, M2): \
2609 case CASE_VFMA_OPCODE_COMMON(OP, TYPE, M4): \
2610 case CASE_VFMA_OPCODE_COMMON(OP, TYPE, M8)
2612#define CASE_VFMA_OPCODE_LMULS_MF2(OP, TYPE) \
2613 CASE_VFMA_OPCODE_COMMON(OP, TYPE, MF2): \
2614 case CASE_VFMA_OPCODE_LMULS_M1(OP, TYPE)
2616#define CASE_VFMA_OPCODE_LMULS_MF4(OP, TYPE) \
2617 CASE_VFMA_OPCODE_COMMON(OP, TYPE, MF4): \
2618 case CASE_VFMA_OPCODE_LMULS_MF2(OP, TYPE)
2620#define CASE_VFMA_OPCODE_LMULS(OP, TYPE) \
2621 CASE_VFMA_OPCODE_COMMON(OP, TYPE, MF8): \
2622 case CASE_VFMA_OPCODE_LMULS_MF4(OP, TYPE)
2624#define CASE_VFMA_SPLATS(OP) \
2625 CASE_VFMA_OPCODE_LMULS_MF4(OP, VFPR16): \
2626 case CASE_VFMA_OPCODE_LMULS_MF2(OP, VFPR32): \
2627 case CASE_VFMA_OPCODE_LMULS_M1(OP, VFPR64)
2631 unsigned &SrcOpIdx1,
2632 unsigned &SrcOpIdx2)
const {
2634 if (!
Desc.isCommutable())
2637 switch (
MI.getOpcode()) {
2638 case RISCV::TH_MVEQZ:
2639 case RISCV::TH_MVNEZ:
2643 if (
MI.getOperand(2).getReg() == RISCV::X0)
2646 return fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 1, 2);
2647 case RISCV::TH_MULA:
2648 case RISCV::TH_MULAW:
2649 case RISCV::TH_MULAH:
2650 case RISCV::TH_MULS:
2651 case RISCV::TH_MULSW:
2652 case RISCV::TH_MULSH:
2654 return fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 2, 3);
2655 case RISCV::PseudoCCMOVGPRNoX0:
2656 case RISCV::PseudoCCMOVGPR:
2658 return fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 4, 5);
2679 if ((
MI.getOperand(
MI.getNumExplicitOperands() - 1).getImm() & 1) == 0)
2684 unsigned CommutableOpIdx1 = 1;
2685 unsigned CommutableOpIdx2 = 3;
2686 if (!fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, CommutableOpIdx1,
2699 if ((
MI.getOperand(
MI.getNumExplicitOperands() - 1).getImm() & 1) == 0)
2706 if (SrcOpIdx1 != CommuteAnyOperandIndex && SrcOpIdx1 > 3)
2708 if (SrcOpIdx2 != CommuteAnyOperandIndex && SrcOpIdx2 > 3)
2712 if (SrcOpIdx1 != CommuteAnyOperandIndex &&
2713 SrcOpIdx2 != CommuteAnyOperandIndex && SrcOpIdx1 != 1 && SrcOpIdx2 != 1)
2719 if (SrcOpIdx1 == CommuteAnyOperandIndex ||
2720 SrcOpIdx2 == CommuteAnyOperandIndex) {
2723 unsigned CommutableOpIdx1 = SrcOpIdx1;
2724 if (SrcOpIdx1 == SrcOpIdx2) {
2727 CommutableOpIdx1 = 1;
2728 }
else if (SrcOpIdx1 == CommuteAnyOperandIndex) {
2730 CommutableOpIdx1 = SrcOpIdx2;
2735 unsigned CommutableOpIdx2;
2736 if (CommutableOpIdx1 != 1) {
2738 CommutableOpIdx2 = 1;
2740 Register Op1Reg =
MI.getOperand(CommutableOpIdx1).getReg();
2745 if (Op1Reg !=
MI.getOperand(2).getReg())
2746 CommutableOpIdx2 = 2;
2748 CommutableOpIdx2 = 3;
2753 if (!fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, CommutableOpIdx1,
2765#define CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, LMUL) \
2766 case RISCV::PseudoV##OLDOP##_##TYPE##_##LMUL: \
2767 Opc = RISCV::PseudoV##NEWOP##_##TYPE##_##LMUL; \
2770#define CASE_VFMA_CHANGE_OPCODE_LMULS_M1(OLDOP, NEWOP, TYPE) \
2771 CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M1) \
2772 CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M2) \
2773 CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M4) \
2774 CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M8)
2776#define CASE_VFMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, TYPE) \
2777 CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF2) \
2778 CASE_VFMA_CHANGE_OPCODE_LMULS_M1(OLDOP, NEWOP, TYPE)
2780#define CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(OLDOP, NEWOP, TYPE) \
2781 CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF4) \
2782 CASE_VFMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, TYPE)
2784#define CASE_VFMA_CHANGE_OPCODE_LMULS(OLDOP, NEWOP, TYPE) \
2785 CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF8) \
2786 CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(OLDOP, NEWOP, TYPE)
2788#define CASE_VFMA_CHANGE_OPCODE_SPLATS(OLDOP, NEWOP) \
2789 CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(OLDOP, NEWOP, VFPR16) \
2790 CASE_VFMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, VFPR32) \
2791 CASE_VFMA_CHANGE_OPCODE_LMULS_M1(OLDOP, NEWOP, VFPR64)
2796 unsigned OpIdx2)
const {
2799 return *
MI.getParent()->getParent()->CloneMachineInstr(&
MI);
2803 switch (
MI.getOpcode()) {
2804 case RISCV::TH_MVEQZ:
2805 case RISCV::TH_MVNEZ: {
2806 auto &WorkingMI = cloneIfNew(
MI);
2807 WorkingMI.setDesc(
get(
MI.getOpcode() == RISCV::TH_MVEQZ ? RISCV::TH_MVNEZ
2808 : RISCV::TH_MVEQZ));
2812 case RISCV::PseudoCCMOVGPRNoX0:
2813 case RISCV::PseudoCCMOVGPR: {
2817 auto &WorkingMI = cloneIfNew(
MI);
2818 WorkingMI.getOperand(3).setImm(
CC);
2842 assert((OpIdx1 == 1 || OpIdx2 == 1) &&
"Unexpected opcode index");
2843 assert((OpIdx1 == 3 || OpIdx2 == 3) &&
"Unexpected opcode index");
2845 switch (
MI.getOpcode()) {
2868 auto &WorkingMI = cloneIfNew(
MI);
2869 WorkingMI.setDesc(
get(Opc));
2879 assert((OpIdx1 == 1 || OpIdx2 == 1) &&
"Unexpected opcode index");
2882 if (OpIdx1 == 3 || OpIdx2 == 3) {
2884 switch (
MI.getOpcode()) {
2895 auto &WorkingMI = cloneIfNew(
MI);
2896 WorkingMI.setDesc(
get(Opc));
2908#undef CASE_VFMA_CHANGE_OPCODE_SPLATS
2909#undef CASE_VFMA_CHANGE_OPCODE_LMULS
2910#undef CASE_VFMA_CHANGE_OPCODE_COMMON
2911#undef CASE_VFMA_SPLATS
2912#undef CASE_VFMA_OPCODE_LMULS
2913#undef CASE_VFMA_OPCODE_COMMON
2916#define CASE_WIDEOP_OPCODE_COMMON(OP, LMUL) \
2917 RISCV::PseudoV##OP##_##LMUL##_TIED
2919#define CASE_WIDEOP_OPCODE_LMULS_MF4(OP) \
2920 CASE_WIDEOP_OPCODE_COMMON(OP, MF4): \
2921 case CASE_WIDEOP_OPCODE_COMMON(OP, MF2): \
2922 case CASE_WIDEOP_OPCODE_COMMON(OP, M1): \
2923 case CASE_WIDEOP_OPCODE_COMMON(OP, M2): \
2924 case CASE_WIDEOP_OPCODE_COMMON(OP, M4)
2926#define CASE_WIDEOP_OPCODE_LMULS(OP) \
2927 CASE_WIDEOP_OPCODE_COMMON(OP, MF8): \
2928 case CASE_WIDEOP_OPCODE_LMULS_MF4(OP)
2931#define CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, LMUL) \
2932 case RISCV::PseudoV##OP##_##LMUL##_TIED: \
2933 NewOpc = RISCV::PseudoV##OP##_##LMUL; \
2936#define CASE_WIDEOP_CHANGE_OPCODE_LMULS_MF4(OP) \
2937 CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF4) \
2938 CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF2) \
2939 CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, M1) \
2940 CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, M2) \
2941 CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, M4)
2943#define CASE_WIDEOP_CHANGE_OPCODE_LMULS(OP) \
2944 CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF8) \
2945 CASE_WIDEOP_CHANGE_OPCODE_LMULS_MF4(OP)
2951 switch (
MI.getOpcode()) {
2957 MI.getNumExplicitOperands() == 7 &&
2958 "Expect 7 explicit operands rd, rs2, rs1, rm, vl, sew, policy");
2965 switch (
MI.getOpcode()) {
2975 .
add(
MI.getOperand(0))
2977 .
add(
MI.getOperand(1))
2978 .
add(
MI.getOperand(2))
2979 .
add(
MI.getOperand(3))
2980 .
add(
MI.getOperand(4))
2981 .
add(
MI.getOperand(5))
2982 .
add(
MI.getOperand(6));
2991 MI.getNumExplicitOperands() == 6);
2992 if ((
MI.getOperand(5).getImm() & 1) == 0)
2997 switch (
MI.getOpcode()) {
3009 .
add(
MI.getOperand(0))
3011 .
add(
MI.getOperand(1))
3012 .
add(
MI.getOperand(2))
3013 .
add(
MI.getOperand(3))
3014 .
add(
MI.getOperand(4))
3015 .
add(
MI.getOperand(5));
3022 unsigned NumOps =
MI.getNumOperands();
3023 for (
unsigned I = 1;
I < NumOps; ++
I) {
3025 if (
Op.isReg() &&
Op.isKill())
3033 if (
MI.getOperand(0).isEarlyClobber()) {
3039 if (S->
end ==
Idx.getRegSlot(
true))
3040 S->
end =
Idx.getRegSlot();
3047#undef CASE_WIDEOP_CHANGE_OPCODE_LMULS
3048#undef CASE_WIDEOP_CHANGE_OPCODE_COMMON
3049#undef CASE_WIDEOP_OPCODE_LMULS
3050#undef CASE_WIDEOP_OPCODE_COMMON
3058 assert(Amount > 0 &&
"There is no need to get VLEN scaled value.");
3059 assert(Amount % 8 == 0 &&
3060 "Reserve the stack by the multiple of one vector size.");
3063 assert(isInt<32>(Amount / 8) &&
3064 "Expect the number of vector registers within 32-bits.");
3068 if (llvm::has_single_bit<uint32_t>(NumOfVReg)) {
3070 if (ShiftAmount == 0)
3076 }
else if (
STI.hasStdExtZba() &&
3083 if (NumOfVReg % 9 == 0) {
3084 Opc = RISCV::SH3ADD;
3085 ShiftAmount =
Log2_64(NumOfVReg / 9);
3086 }
else if (NumOfVReg % 5 == 0) {
3087 Opc = RISCV::SH2ADD;
3088 ShiftAmount =
Log2_64(NumOfVReg / 5);
3089 }
else if (NumOfVReg % 3 == 0) {
3090 Opc = RISCV::SH1ADD;
3091 ShiftAmount =
Log2_64(NumOfVReg / 3);
3104 }
else if (llvm::has_single_bit<uint32_t>(NumOfVReg - 1)) {
3105 Register ScaledRegister =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
3115 }
else if (llvm::has_single_bit<uint32_t>(NumOfVReg + 1)) {
3116 Register ScaledRegister =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
3126 }
else if (
STI.hasStdExtM() ||
STI.hasStdExtZmmul()) {
3127 Register N =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
3136 for (
uint32_t ShiftAmount = 0; NumOfVReg >> ShiftAmount; ShiftAmount++) {
3137 if (NumOfVReg & (1U << ShiftAmount)) {
3141 .
addImm(ShiftAmount - PrevShiftAmount)
3143 if (NumOfVReg >> (ShiftAmount + 1)) {
3146 Acc =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
3157 PrevShiftAmount = ShiftAmount;
3160 assert(Acc &&
"Expected valid accumulator");
3170 static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
3178 return MI.getOpcode() == RISCV::ADDIW &&
MI.getOperand(1).isReg() &&
3179 MI.getOperand(2).isImm() &&
MI.getOperand(2).getImm() == 0;
3184 return MI.getOpcode() == RISCV::ADD_UW &&
MI.getOperand(1).isReg() &&
3185 MI.getOperand(2).isReg() &&
MI.getOperand(2).getReg() == RISCV::X0;
3190 return MI.getOpcode() == RISCV::ANDI &&
MI.getOperand(1).isReg() &&
3191 MI.getOperand(2).isImm() &&
MI.getOperand(2).getImm() == 255;
3202 case RISCV::VL1RE8_V:
3203 case RISCV::VL2RE8_V:
3204 case RISCV::VL4RE8_V:
3205 case RISCV::VL8RE8_V:
3206 case RISCV::VL1RE16_V:
3207 case RISCV::VL2RE16_V:
3208 case RISCV::VL4RE16_V:
3209 case RISCV::VL8RE16_V:
3210 case RISCV::VL1RE32_V:
3211 case RISCV::VL2RE32_V:
3212 case RISCV::VL4RE32_V:
3213 case RISCV::VL8RE32_V:
3214 case RISCV::VL1RE64_V:
3215 case RISCV::VL2RE64_V:
3216 case RISCV::VL4RE64_V:
3217 case RISCV::VL8RE64_V:
3225 unsigned Opcode =
MI.getOpcode();
3226 if (!RISCVVPseudosTable::getPseudoInfo(Opcode) &&
3232std::optional<std::pair<unsigned, unsigned>>
3236 return std::nullopt;
3237 case RISCV::PseudoVSPILL2_M1:
3238 case RISCV::PseudoVRELOAD2_M1:
3239 return std::make_pair(2u, 1u);
3240 case RISCV::PseudoVSPILL2_M2:
3241 case RISCV::PseudoVRELOAD2_M2:
3242 return std::make_pair(2u, 2u);
3243 case RISCV::PseudoVSPILL2_M4:
3244 case RISCV::PseudoVRELOAD2_M4:
3245 return std::make_pair(2u, 4u);
3246 case RISCV::PseudoVSPILL3_M1:
3247 case RISCV::PseudoVRELOAD3_M1:
3248 return std::make_pair(3u, 1u);
3249 case RISCV::PseudoVSPILL3_M2:
3250 case RISCV::PseudoVRELOAD3_M2:
3251 return std::make_pair(3u, 2u);
3252 case RISCV::PseudoVSPILL4_M1:
3253 case RISCV::PseudoVRELOAD4_M1:
3254 return std::make_pair(4u, 1u);
3255 case RISCV::PseudoVSPILL4_M2:
3256 case RISCV::PseudoVRELOAD4_M2:
3257 return std::make_pair(4u, 2u);
3258 case RISCV::PseudoVSPILL5_M1:
3259 case RISCV::PseudoVRELOAD5_M1:
3260 return std::make_pair(5u, 1u);
3261 case RISCV::PseudoVSPILL6_M1:
3262 case RISCV::PseudoVRELOAD6_M1:
3263 return std::make_pair(6u, 1u);
3264 case RISCV::PseudoVSPILL7_M1:
3265 case RISCV::PseudoVRELOAD7_M1:
3266 return std::make_pair(7u, 1u);
3267 case RISCV::PseudoVSPILL8_M1:
3268 case RISCV::PseudoVRELOAD8_M1:
3269 return std::make_pair(8u, 1u);
3274 return MI.getNumExplicitDefs() == 2 &&
MI.modifiesRegister(RISCV::VL) &&
3279 int16_t MI1FrmOpIdx =
3281 int16_t MI2FrmOpIdx =
3283 if (MI1FrmOpIdx < 0 || MI2FrmOpIdx < 0)
3290std::optional<unsigned>
3295 return std::nullopt;
3298 case RISCV::VSLL_VX:
3299 case RISCV::VSRL_VX:
3300 case RISCV::VSRA_VX:
3302 case RISCV::VSSRL_VX:
3303 case RISCV::VSSRA_VX:
3308 case RISCV::VNSRL_WX:
3309 case RISCV::VNSRA_WX:
3311 case RISCV::VNCLIPU_WX:
3312 case RISCV::VNCLIP_WX:
3317 case RISCV::VADD_VX:
3318 case RISCV::VSUB_VX:
3319 case RISCV::VRSUB_VX:
3321 case RISCV::VWADDU_VX:
3322 case RISCV::VWSUBU_VX:
3323 case RISCV::VWADD_VX:
3324 case RISCV::VWSUB_VX:
3325 case RISCV::VWADDU_WX:
3326 case RISCV::VWSUBU_WX:
3327 case RISCV::VWADD_WX:
3328 case RISCV::VWSUB_WX:
3330 case RISCV::VADC_VXM:
3331 case RISCV::VADC_VIM:
3332 case RISCV::VMADC_VXM:
3333 case RISCV::VMADC_VIM:
3334 case RISCV::VMADC_VX:
3335 case RISCV::VSBC_VXM:
3336 case RISCV::VMSBC_VXM:
3337 case RISCV::VMSBC_VX:
3339 case RISCV::VAND_VX:
3341 case RISCV::VXOR_VX:
3343 case RISCV::VMSEQ_VX:
3344 case RISCV::VMSNE_VX:
3345 case RISCV::VMSLTU_VX:
3346 case RISCV::VMSLT_VX:
3347 case RISCV::VMSLEU_VX:
3348 case RISCV::VMSLE_VX:
3349 case RISCV::VMSGTU_VX:
3350 case RISCV::VMSGT_VX:
3352 case RISCV::VMINU_VX:
3353 case RISCV::VMIN_VX:
3354 case RISCV::VMAXU_VX:
3355 case RISCV::VMAX_VX:
3357 case RISCV::VMUL_VX:
3358 case RISCV::VMULH_VX:
3359 case RISCV::VMULHU_VX:
3360 case RISCV::VMULHSU_VX:
3362 case RISCV::VDIVU_VX:
3363 case RISCV::VDIV_VX:
3364 case RISCV::VREMU_VX:
3365 case RISCV::VREM_VX:
3367 case RISCV::VWMUL_VX:
3368 case RISCV::VWMULU_VX:
3369 case RISCV::VWMULSU_VX:
3371 case RISCV::VMACC_VX:
3372 case RISCV::VNMSAC_VX:
3373 case RISCV::VMADD_VX:
3374 case RISCV::VNMSUB_VX:
3376 case RISCV::VWMACCU_VX:
3377 case RISCV::VWMACC_VX:
3378 case RISCV::VWMACCSU_VX:
3379 case RISCV::VWMACCUS_VX:
3381 case RISCV::VMERGE_VXM:
3383 case RISCV::VMV_V_X:
3385 case RISCV::VSADDU_VX:
3386 case RISCV::VSADD_VX:
3387 case RISCV::VSSUBU_VX:
3388 case RISCV::VSSUB_VX:
3390 case RISCV::VAADDU_VX:
3391 case RISCV::VAADD_VX:
3392 case RISCV::VASUBU_VX:
3393 case RISCV::VASUB_VX:
3395 case RISCV::VSMUL_VX:
3397 case RISCV::VMV_S_X:
3398 return 1U << Log2SEW;
3404 RISCVVPseudosTable::getPseudoInfo(RVVPseudoOpcode);
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder MachineInstrBuilder & DefMI
static bool forwardCopyWillClobberTuple(unsigned DestReg, unsigned SrcReg, unsigned NumRegs)
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
const HexagonInstrInfo * TII
static M68k::CondCode getCondFromBranchOpc(unsigned BrOpc)
unsigned const TargetRegisterInfo * TRI
This file provides utility analysis objects describing memory locations.
const char LLVMTargetMachineRef TM
#define CASE_VFMA_CHANGE_OPCODE_SPLATS(OLDOP, NEWOP)
static bool isRVVWholeLoadStore(unsigned Opcode)
static void combineFPFusedMultiply(MachineInstr &Root, MachineInstr &Prev, MachineCombinerPattern Pattern, SmallVectorImpl< MachineInstr * > &InsInstrs, SmallVectorImpl< MachineInstr * > &DelInstrs)
static bool getFPFusedMultiplyPatterns(MachineInstr &Root, SmallVectorImpl< MachineCombinerPattern > &Patterns, bool DoRegPressureReduce)
#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 unsigned getFPFusedMultiplyOpcode(unsigned RootOpc, MachineCombinerPattern Pattern)
#define CASE_WIDEOP_OPCODE_LMULS(OP)
static bool isFSUB(unsigned Opc)
MachineOutlinerConstructionID
static bool isFMUL(unsigned Opc)
#define CASE_WIDEOP_CHANGE_OPCODE_LMULS_MF4(OP)
#define CASE_OPERAND_UIMM(NUM)
#define CASE_VFMA_CHANGE_OPCODE_LMULS(OLDOP, NEWOP, TYPE)
static bool isFADD(unsigned Opc)
#define CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(OLDOP, NEWOP, TYPE)
#define CASE_WIDEOP_OPCODE_LMULS_MF4(OP)
static unsigned getAddendOperandIdx(MachineCombinerPattern Pattern)
static bool isConvertibleToVMV_V_V(const RISCVSubtarget &STI, const MachineBasicBlock &MBB, MachineBasicBlock::const_iterator MBBI, MachineBasicBlock::const_iterator &DefMBBI, RISCVII::VLMUL LMul)
#define CASE_VFMA_OPCODE_LMULS(OP, TYPE)
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 getFPPatterns(MachineInstr &Root, SmallVectorImpl< MachineCombinerPattern > &Patterns, bool DoRegPressureReduce)
static bool canCombineFPFusedMultiply(const MachineInstr &Root, const MachineOperand &MO, 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.")))
#define CASE_VFMA_OPCODE_LMULS_MF4(OP, TYPE)
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.
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)
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 ...
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
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 genAlternativeCodeSequence(MachineInstr &Root, MachineCombinerPattern 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 copyPhysRegVector(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, MCRegister DstReg, MCRegister SrcReg, bool KillSrc, RISCVII::VLMUL LMul, unsigned NF=1) const
const RISCVSubtarget & STI
bool getMachineCombinerPatterns(MachineInstr &Root, SmallVectorImpl< MachineCombinerPattern > &Patterns, bool DoRegPressureReduce) const override
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
void finalizeInsInstrs(MachineInstr &Root, MachineCombinerPattern &P, SmallVectorImpl< MachineInstr * > &InsInstrs) 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
std::pair< unsigned, unsigned > decomposeMachineOperandsTargetFlags(unsigned TF) const override
MachineInstr * commuteInstructionImpl(MachineInstr &MI, bool NewMI, unsigned OpIdx1, unsigned OpIdx2) const override
void getVLENFactoredAmount(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator II, const DebugLoc &DL, Register DestReg, int64_t Amount, MachineInstr::MIFlag Flag=MachineInstr::NoFlags) const
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
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 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 getMachineCombinerPatterns(MachineInstr &Root, SmallVectorImpl< MachineCombinerPattern > &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 genAlternativeCodeSequence(MachineInstr &Root, MachineCombinerPattern Pattern, SmallVectorImpl< MachineInstr * > &InsInstrs, SmallVectorImpl< MachineInstr * > &DelInstrs, DenseMap< unsigned, unsigned > &InstIdxForVirtReg) const
When getMachineCombinerPatterns() finds patterns, this function generates the instructions that could...
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
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 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)
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 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 and pointer casts from the specified value,...
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.
MachineCombinerPattern
These are instruction patterns matched by the machine combiner pass.
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.
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.