26#define DEBUG_TYPE "si-fold-operands"
47 unsigned DefSubReg = AMDGPU::NoSubRegister;
52 FoldableDef() =
delete;
54 unsigned DefSubReg = AMDGPU::NoSubRegister)
55 : DefRC(DefRC), DefSubReg(DefSubReg), Kind(FoldOp.
getType()) {
58 ImmToFold = FoldOp.
getImm();
59 }
else if (FoldOp.
isFI()) {
60 FrameIndexToFold = FoldOp.
getIndex();
70 unsigned DefSubReg = AMDGPU::NoSubRegister)
71 : ImmToFold(FoldImm), DefRC(DefRC), DefSubReg(DefSubReg),
76 FoldableDef Copy(*
this);
77 Copy.DefSubReg =
TRI.composeSubRegIndices(DefSubReg, SubReg);
85 return OpToFold->getReg();
88 unsigned getSubReg()
const {
90 return OpToFold->getSubReg();
101 return FrameIndexToFold;
109 std::optional<int64_t> getEffectiveImmVal()
const {
117 unsigned OpIdx)
const {
120 std::optional<int64_t> ImmToFold = getEffectiveImmVal();
127 return TII.isOperandLegal(
MI, OpIdx, &TmpOp);
130 if (DefSubReg != AMDGPU::NoSubRegister)
133 return TII.isOperandLegal(
MI, OpIdx, &TmpOp);
138 if (DefSubReg != AMDGPU::NoSubRegister)
140 return TII.isOperandLegal(
MI, OpIdx, OpToFold);
147struct FoldCandidate {
155 bool Commuted =
false,
int ShrinkOp = -1)
156 :
UseMI(
MI), Def(Def), ShrinkOpcode(ShrinkOp), UseOpNo(OpNo),
157 Commuted(Commuted) {}
159 bool isFI()
const {
return Def.isFI(); }
163 return Def.FrameIndexToFold;
166 bool isImm()
const {
return Def.isImm(); }
168 bool isReg()
const {
return Def.isReg(); }
172 bool isGlobal()
const {
return Def.isGlobal(); }
174 bool needsShrink()
const {
return ShrinkOpcode != -1; }
177class SIFoldOperandsImpl {
188 const FoldableDef &OpToFold)
const;
191 unsigned convertToVALUOp(
unsigned Opc,
bool UseVOP3 =
false)
const {
193 case AMDGPU::S_ADD_I32: {
194 if (ST->hasAddNoCarryInsts())
195 return UseVOP3 ? AMDGPU::V_ADD_U32_e64 : AMDGPU::V_ADD_U32_e32;
196 return UseVOP3 ? AMDGPU::V_ADD_CO_U32_e64 : AMDGPU::V_ADD_CO_U32_e32;
198 case AMDGPU::S_OR_B32:
199 return UseVOP3 ? AMDGPU::V_OR_B32_e64 : AMDGPU::V_OR_B32_e32;
200 case AMDGPU::S_AND_B32:
201 return UseVOP3 ? AMDGPU::V_AND_B32_e64 : AMDGPU::V_AND_B32_e32;
202 case AMDGPU::S_MUL_I32:
203 return AMDGPU::V_MUL_LO_U32_e64;
205 return AMDGPU::INSTRUCTION_LIST_END;
209 bool foldCopyToVGPROfScalarAddOfFrameIndex(
Register DstReg,
Register SrcReg,
215 int64_t ImmVal)
const;
219 int64_t ImmVal)
const;
223 const FoldableDef &OpToFold)
const;
226 bool isTemporallyDivergentUse(
const FoldableDef &OpToFold,
234 getRegSeqInit(
SmallVectorImpl<std::pair<MachineOperand *, unsigned>> &Defs,
237 std::pair<int64_t, const TargetRegisterClass *>
251 struct ANDMaskResult {
257 std::optional<ANDMaskResult> getANDMaskRegOperand(
MachineInstr &AndMI)
const;
262 bool foldInstOperand(
MachineInstr &
MI,
const FoldableDef &OpToFold)
const;
264 bool foldCopyToAGPRRegSequence(
MachineInstr *CopyMI)
const;
271 std::pair<const MachineOperand *, int> isOMod(
const MachineInstr &
MI)
const;
281 SIFoldOperandsImpl() =
default;
296 &getAnalysis<MachineLoopInfoWrapperPass>().getLI();
297 return SIFoldOperandsImpl().run(MF, MLI);
300 StringRef getPassName()
const override {
return "SI Fold Operands"; }
322char SIFoldOperandsLegacy::ID = 0;
331 TRI.getSubRegisterClass(RC, MO.getSubReg()))
339 case AMDGPU::V_MAC_F32_e64:
340 return AMDGPU::V_MAD_F32_e64;
341 case AMDGPU::V_MAC_F16_e64:
342 return AMDGPU::V_MAD_F16_e64;
343 case AMDGPU::V_FMAC_F32_e64:
344 return AMDGPU::V_FMA_F32_e64;
345 case AMDGPU::V_FMAC_F16_e64:
346 return AMDGPU::V_FMA_F16_gfx9_e64;
347 case AMDGPU::V_FMAC_F16_t16_e64:
348 return AMDGPU::V_FMA_F16_gfx9_t16_e64;
349 case AMDGPU::V_FMAC_F16_fake16_e64:
350 return AMDGPU::V_FMA_F16_gfx9_fake16_e64;
351 case AMDGPU::V_FMAC_LEGACY_F32_e64:
352 return AMDGPU::V_FMA_LEGACY_F32_e64;
353 case AMDGPU::V_FMAC_F64_e64:
354 return AMDGPU::V_FMA_F64_e64;
356 return AMDGPU::INSTRUCTION_LIST_END;
362 const FoldableDef &OpToFold)
const {
363 if (!OpToFold.isFI())
366 const unsigned Opc =
UseMI.getOpcode();
368 case AMDGPU::S_ADD_I32:
369 case AMDGPU::S_ADD_U32:
370 case AMDGPU::V_ADD_U32_e32:
371 case AMDGPU::V_ADD_CO_U32_e32:
375 return UseMI.getOperand(OpNo == 1 ? 2 : 1).isImm() &&
377 case AMDGPU::V_ADD_U32_e64:
378 case AMDGPU::V_ADD_CO_U32_e64:
379 return UseMI.getOperand(OpNo == 2 ? 3 : 2).isImm() &&
386 return OpNo == AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr);
390 int SIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::saddr);
394 int VIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr);
395 return OpNo == VIdx && SIdx == -1;
401bool SIFoldOperandsImpl::foldCopyToVGPROfScalarAddOfFrameIndex(
406 if (
TRI->isVGPR(*MRI, DstReg) &&
TRI->isSGPRReg(*MRI, SrcReg) &&
409 if (!Def ||
Def->getNumOperands() != 4)
412 MachineOperand *Src0 = &
Def->getOperand(1);
413 MachineOperand *Src1 = &
Def->getOperand(2);
424 const bool UseVOP3 = !Src0->
isImm() ||
TII->isInlineConstant(*Src0);
425 unsigned NewOp = convertToVALUOp(
Def->getOpcode(), UseVOP3);
426 if (NewOp == AMDGPU::INSTRUCTION_LIST_END ||
427 !
Def->getOperand(3).isDead())
430 MachineBasicBlock *
MBB =
Def->getParent();
432 if (NewOp != AMDGPU::V_ADD_CO_U32_e32) {
433 MachineInstrBuilder
Add =
436 if (
Add->getDesc().getNumDefs() == 2) {
438 Add.addDef(CarryOutReg, RegState::Dead);
442 Add.add(*Src0).add(*Src1).setMIFlags(
Def->getFlags());
446 Def->eraseFromParent();
447 MI.eraseFromParent();
451 assert(NewOp == AMDGPU::V_ADD_CO_U32_e32);
462 Def->eraseFromParent();
463 MI.eraseFromParent();
472 return new SIFoldOperandsLegacy();
475bool SIFoldOperandsImpl::canUseImmWithOpSel(
const MachineInstr *
MI,
477 int64_t ImmVal)
const {
484 int OpNo =
MI->getOperandNo(&Old);
486 unsigned Opcode =
MI->getOpcode();
487 uint8_t OpType =
TII->get(Opcode).operands()[OpNo].OperandType;
509bool SIFoldOperandsImpl::tryFoldImmWithOpSel(MachineInstr *
MI,
unsigned UseOpNo,
510 int64_t ImmVal)
const {
511 MachineOperand &Old =
MI->getOperand(UseOpNo);
512 unsigned Opcode =
MI->getOpcode();
513 int OpNo =
MI->getOperandNo(&Old);
514 uint8_t OpType =
TII->get(Opcode).operands()[OpNo].OperandType;
526 AMDGPU::OpName ModName = AMDGPU::OpName::NUM_OPERAND_NAMES;
527 unsigned SrcIdx = ~0;
528 if (OpNo == AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0)) {
529 ModName = AMDGPU::OpName::src0_modifiers;
531 }
else if (OpNo == AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1)) {
532 ModName = AMDGPU::OpName::src1_modifiers;
534 }
else if (OpNo == AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2)) {
535 ModName = AMDGPU::OpName::src2_modifiers;
538 assert(ModName != AMDGPU::OpName::NUM_OPERAND_NAMES);
539 int ModIdx = AMDGPU::getNamedOperandIdx(Opcode, ModName);
540 MachineOperand &
Mod =
MI->getOperand(ModIdx);
541 unsigned ModVal =
Mod.getImm();
547 uint32_t
Imm = (
static_cast<uint32_t
>(ImmHi) << 16) | ImmLo;
552 auto tryFoldToInline = [&](uint32_t
Imm) ->
bool {
561 uint16_t
Lo =
static_cast<uint16_t
>(
Imm);
562 uint16_t
Hi =
static_cast<uint16_t
>(
Imm >> 16);
568 if (ST->hasBF16InlineConstFromUpperFP32() &&
572 Mod.setImm(NewModVal);
577 if (
static_cast<int16_t
>(
Lo) < 0) {
578 int32_t SExt =
static_cast<int16_t
>(
Lo);
580 Mod.setImm(NewModVal);
595 uint32_t Swapped = (
static_cast<uint32_t
>(
Lo) << 16) |
Hi;
606 if (tryFoldToInline(
Imm))
615 bool IsUAdd = Opcode == AMDGPU::V_PK_ADD_U16;
616 bool IsUSub = Opcode == AMDGPU::V_PK_SUB_U16;
617 if (SrcIdx == 1 && (IsUAdd || IsUSub)) {
619 AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::clamp);
620 bool Clamp =
MI->getOperand(ClampIdx).getImm() != 0;
623 uint16_t NegLo = -
static_cast<uint16_t
>(
Imm);
624 uint16_t NegHi = -
static_cast<uint16_t
>(
Imm >> 16);
625 uint32_t NegImm = (
static_cast<uint32_t
>(NegHi) << 16) | NegLo;
627 if (tryFoldToInline(NegImm)) {
629 IsUAdd ? AMDGPU::V_PK_SUB_U16 : AMDGPU::V_PK_ADD_U16;
630 MI->setDesc(
TII->get(NegOpcode));
639bool SIFoldOperandsImpl::updateOperand(FoldCandidate &Fold)
const {
640 MachineInstr *
MI = Fold.UseMI;
641 MachineOperand &Old =
MI->getOperand(Fold.UseOpNo);
644 std::optional<int64_t> ImmVal;
646 ImmVal = Fold.Def.getEffectiveImmVal();
648 if (ImmVal && canUseImmWithOpSel(Fold.UseMI, Fold.UseOpNo, *ImmVal)) {
649 if (tryFoldImmWithOpSel(Fold.UseMI, Fold.UseOpNo, *ImmVal))
655 int OpNo =
MI->getOperandNo(&Old);
656 if (!
TII->isOperandLegal(*
MI, OpNo, &New))
662 if ((Fold.isImm() || Fold.isFI() || Fold.isGlobal()) && Fold.needsShrink()) {
670 int Op32 = Fold.ShrinkOpcode;
671 MachineOperand &Dst0 =
MI->getOperand(0);
672 MachineOperand &Dst1 =
MI->getOperand(1);
680 MachineInstr *Inst32 =
TII->buildShrunkInst(*
MI, Op32);
682 if (HaveNonDbgCarryUse) {
685 .
addReg(AMDGPU::VCC, RegState::Kill);
695 for (
unsigned I =
MI->getNumOperands() - 1;
I > 0; --
I)
696 MI->removeOperand(
I);
697 MI->setDesc(
TII->get(AMDGPU::IMPLICIT_DEF));
700 TII->commuteInstruction(*Inst32,
false);
704 assert(!Fold.needsShrink() &&
"not handled");
709 if (NewMFMAOpc == -1)
711 MI->setDesc(
TII->get(NewMFMAOpc));
712 MI->untieRegOperand(0);
713 const MCInstrDesc &MCID =
MI->getDesc();
714 for (
unsigned I = 0;
I <
MI->getNumDefs(); ++
I)
716 MI->getOperand(
I).setIsEarlyClobber(
true);
721 int OpNo =
MI->getOperandNo(&Old);
722 if (!
TII->isOperandLegal(*
MI, OpNo, &New))
725 if (ST->hasBF16InlineConstFromUpperFP32() &&
727 AMDGPU::getNamedOperandIdx(
MI->getOpcode(), AMDGPU::OpName::src0)) {
728 unsigned Opcode =
MI->getOpcode();
729 uint8_t OpType =
TII->get(Opcode).operands()[OpNo].OperandType;
732 TII->isInlineConstant(*ImmVal, OpType)) {
735 AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0_modifiers);
738 MachineOperand &ModOp =
MI->getOperand(Mod0);
749 if (Fold.isGlobal()) {
750 Old.
ChangeToGA(Fold.Def.OpToFold->getGlobal(),
751 Fold.Def.OpToFold->getOffset(),
752 Fold.Def.OpToFold->getTargetFlags());
761 MachineOperand *
New = Fold.Def.OpToFold;
765 TII->getRegClass(
MI->getDesc(), Fold.UseOpNo)) {
767 TRI->getRegClassForReg(*MRI,
New->getReg());
770 if (
New->getSubReg()) {
772 TRI->getMatchingSuperRegClass(NewRC, OpRC,
New->getSubReg());
778 if (
New->getReg().isVirtual() &&
781 <<
TRI->getRegClassName(ConstrainRC) <<
'\n');
788 if (Old.
getSubReg() == AMDGPU::lo16 &&
TRI->isSGPRReg(*MRI,
New->getReg()))
790 if (
New->getReg().isPhysical()) {
798 if (
MI->isBundledWithPred()) {
800 for (MachineOperand &MO : Header.operands()) {
801 if (MO.getReg() == OldReg) {
802 MO.setReg(
New->getReg());
803 MO.setSubReg(
New->getSubReg());
812 FoldCandidate &&Entry) {
814 for (FoldCandidate &Fold : FoldList)
815 if (Fold.UseMI == Entry.UseMI && Fold.UseOpNo == Entry.UseOpNo)
817 LLVM_DEBUG(
dbgs() <<
"Append " << (Entry.Commuted ?
"commuted" :
"normal")
818 <<
" operand " << Entry.UseOpNo <<
"\n " << *Entry.UseMI);
824 const FoldableDef &FoldOp,
825 bool Commuted =
false,
int ShrinkOp = -1) {
827 FoldCandidate(
MI, OpNo, FoldOp, Commuted, ShrinkOp));
835 if (!ST->hasPKF32InstsReplicatingLower32BitsOfScalarInput())
845 const FoldableDef &OpToFold) {
846 assert(OpToFold.isImm() &&
"Expected immediate operand");
847 uint64_t ImmVal = OpToFold.getEffectiveImmVal().value();
853bool SIFoldOperandsImpl::tryAddToFoldList(
854 SmallVectorImpl<FoldCandidate> &FoldList, MachineInstr *
MI,
unsigned OpNo,
855 const FoldableDef &OpToFold)
const {
856 const unsigned Opc =
MI->getOpcode();
858 auto tryToFoldAsFMAAKorMK = [&]() {
859 if (!OpToFold.isImm())
862 const bool TryAK = OpNo == 3;
863 const unsigned NewOpc = TryAK ? AMDGPU::S_FMAAK_F32 : AMDGPU::S_FMAMK_F32;
864 MI->setDesc(
TII->get(NewOpc));
867 bool FoldAsFMAAKorMK =
868 tryAddToFoldList(FoldList,
MI, TryAK ? 3 : 2, OpToFold);
869 if (FoldAsFMAAKorMK) {
871 MI->untieRegOperand(3);
874 MachineOperand &Op1 =
MI->getOperand(1);
875 MachineOperand &Op2 =
MI->getOperand(2);
892 bool IsLegal = OpToFold.isOperandLegal(*
TII, *
MI, OpNo);
893 if (!IsLegal && OpToFold.isImm()) {
894 if (std::optional<int64_t> ImmVal = OpToFold.getEffectiveImmVal())
895 IsLegal = canUseImmWithOpSel(
MI, OpNo, *ImmVal);
901 if (NewOpc != AMDGPU::INSTRUCTION_LIST_END) {
904 MI->setDesc(
TII->get(NewOpc));
909 bool FoldAsMAD = tryAddToFoldList(FoldList,
MI, OpNo, OpToFold);
911 MI->untieRegOperand(OpNo);
915 MI->removeOperand(
MI->getNumExplicitOperands() - 1);
921 if (
Opc == AMDGPU::S_FMAC_F32 && OpNo == 3) {
922 if (tryToFoldAsFMAAKorMK())
927 if (OpToFold.isImm()) {
929 if (
Opc == AMDGPU::S_SETREG_B32)
930 ImmOpc = AMDGPU::S_SETREG_IMM32_B32;
931 else if (
Opc == AMDGPU::S_SETREG_B32_mode)
932 ImmOpc = AMDGPU::S_SETREG_IMM32_B32_mode;
934 MI->setDesc(
TII->get(ImmOpc));
943 bool CanCommute =
TII->findCommutedOpIndices(*
MI, OpNo, CommuteOpNo);
947 MachineOperand &
Op =
MI->getOperand(OpNo);
948 MachineOperand &CommutedOp =
MI->getOperand(CommuteOpNo);
954 if (!
Op.isReg() || !CommutedOp.
isReg())
959 if (
Op.isReg() && CommutedOp.
isReg() &&
960 (
Op.getReg() == CommutedOp.
getReg() &&
964 if (!
TII->commuteInstruction(*
MI,
false, OpNo, CommuteOpNo))
968 if (!OpToFold.isOperandLegal(*
TII, *
MI, CommuteOpNo)) {
969 if ((
Opc != AMDGPU::V_ADD_CO_U32_e64 &&
Opc != AMDGPU::V_SUB_CO_U32_e64 &&
970 Opc != AMDGPU::V_SUBREV_CO_U32_e64) ||
971 (!OpToFold.isImm() && !OpToFold.isFI() && !OpToFold.isGlobal())) {
972 TII->commuteInstruction(*
MI,
false, OpNo, CommuteOpNo);
978 MachineOperand &OtherOp =
MI->getOperand(OpNo);
979 if (!OtherOp.
isReg() ||
986 unsigned MaybeCommutedOpc =
MI->getOpcode();
1000 if (
Opc == AMDGPU::S_FMAC_F32 &&
1001 (OpNo != 1 || !
MI->getOperand(1).isIdenticalTo(
MI->getOperand(2)))) {
1002 if (tryToFoldAsFMAAKorMK())
1008 if (OpToFold.isImm() &&
1017bool SIFoldOperandsImpl::isUseSafeToFold(
const MachineInstr &
MI,
1018 const MachineOperand &UseMO)
const {
1020 return !
TII->isSDWA(
MI);
1027 if (
MI.modifiesRegister(
TRI.getExec(), &
TRI))
1035bool SIFoldOperandsImpl::isTemporallyDivergentUse(
1036 const FoldableDef &OpToFold,
const MachineInstr &
UseMI)
const {
1037 if (!OpToFold.isReg())
1039 const MachineInstr *
DefMI = OpToFold.DefMI;
1042 !
TRI->isSGPRReg(*MRI, OpToFold.getReg()))
1054 SubDef &&
TII.isFoldableCopy(*SubDef);
1056 unsigned SrcIdx =
TII.getFoldableCopySrcIdx(*SubDef);
1065 if (
SrcOp.getSubReg())
1073 MachineInstr &RegSeq,
1074 SmallVectorImpl<std::pair<MachineOperand *, unsigned>> &Defs)
const {
1090 else if (!
TRI->getCommonSubClass(RC, OpRC))
1095 Defs.emplace_back(&SrcOp, SubRegIdx);
1100 if (DefSrc && (DefSrc->
isReg() || DefSrc->
isImm())) {
1101 Defs.emplace_back(DefSrc, SubRegIdx);
1105 Defs.emplace_back(&SrcOp, SubRegIdx);
1115 SmallVectorImpl<std::pair<MachineOperand *, unsigned>> &Defs,
1118 if (!Def || !
Def->isRegSequence())
1121 return getRegSeqInit(*Def, Defs);
1124std::pair<int64_t, const TargetRegisterClass *>
1125SIFoldOperandsImpl::isRegSeqSplat(MachineInstr &RegSeq)
const {
1131 bool TryToMatchSplat64 =
false;
1133 std::optional<int64_t>
Imm;
1134 for (
unsigned I = 0,
E = Defs.
size();
I !=
E; ++
I) {
1135 const MachineOperand *
Op = Defs[
I].first;
1139 if (!Def ||
Def->isImplicitDef())
1145 int64_t SubImm =
Op->getImm();
1151 if (
Imm != SubImm) {
1152 if (
I == 1 && (
E & 1) == 0) {
1155 TryToMatchSplat64 =
true;
1163 if (!TryToMatchSplat64) {
1165 return {*
Imm, SrcRC};
1172 for (
unsigned I = 0,
E = Defs.
size();
I !=
E;
I += 2) {
1173 const MachineOperand *Op0 = Defs[
I].first;
1174 const MachineOperand *Op1 = Defs[
I + 1].first;
1179 unsigned SubReg0 = Defs[
I].second;
1180 unsigned SubReg1 = Defs[
I + 1].second;
1184 if (
TRI->getChannelFromSubReg(SubReg0) + 1 !=
1185 TRI->getChannelFromSubReg(SubReg1))
1188 if (
TRI->getSubRegIdxSize(SubReg0) != 32)
1193 SplatVal64 = MergedVal;
1194 else if (SplatVal64 != MergedVal)
1201 return {SplatVal64, RC64};
1204bool SIFoldOperandsImpl::tryFoldRegSeqSplat(
1205 MachineInstr *
UseMI,
unsigned UseOpIdx, int64_t SplatVal,
1208 if (UseOpIdx >=
Desc.getNumOperands())
1215 int16_t RCID =
TII->getOpRegClassID(
Desc.operands()[UseOpIdx]);
1224 if (SplatVal != 0 && SplatVal != -1) {
1228 uint8_t OpTy =
Desc.operands()[UseOpIdx].OperandType;
1235 OpRC =
TRI->getSubRegisterClass(OpRC, AMDGPU::sub0);
1242 OpRC =
TRI->getSubRegisterClass(OpRC, AMDGPU::sub0_sub1);
1248 if (!
TRI->getCommonSubClass(OpRC, SplatRC))
1253 if (!
TII->isOperandLegal(*
UseMI, UseOpIdx, &TmpOp))
1259bool SIFoldOperandsImpl::tryToFoldACImm(
1260 const FoldableDef &OpToFold, MachineInstr *
UseMI,
unsigned UseOpIdx,
1261 SmallVectorImpl<FoldCandidate> &FoldList)
const {
1263 if (UseOpIdx >=
Desc.getNumOperands())
1270 if (OpToFold.isImm() && OpToFold.isOperandLegal(*
TII, *
UseMI, UseOpIdx)) {
1281bool SIFoldOperandsImpl::foldOperand(
1282 FoldableDef OpToFold, MachineInstr *
UseMI,
int UseOpIdx,
1283 SmallVectorImpl<FoldCandidate> &FoldList,
1284 SmallVectorImpl<MachineInstr *> &CopiesToReplace)
const {
1288 if (!isUseSafeToFold(*
UseMI, *UseOp))
1291 if (isTemporallyDivergentUse(OpToFold, *
UseMI))
1295 if (UseOp->
isReg() && OpToFold.isReg()) {
1299 if (UseOp->
getSubReg() != AMDGPU::NoSubRegister &&
1301 !
TRI->isSGPRReg(*MRI, OpToFold.getReg())))
1314 std::tie(SplatVal, SplatRC) = isRegSeqSplat(*
UseMI);
1319 for (
unsigned I = 0;
I != UsesToProcess.size(); ++
I) {
1320 MachineOperand *RSUse = UsesToProcess[
I];
1321 MachineInstr *RSUseMI = RSUse->
getParent();
1331 if (tryFoldRegSeqSplat(RSUseMI, OpNo, SplatVal, SplatRC)) {
1332 FoldableDef SplatDef(SplatVal, SplatRC);
1340 if (RSUse->
getSubReg() != RegSeqDstSubReg)
1346 FoldList, CopiesToReplace);
1352 if (tryToFoldACImm(OpToFold,
UseMI, UseOpIdx, FoldList))
1355 if (frameIndexMayFold(*
UseMI, UseOpIdx, OpToFold)) {
1360 if (
TII->getNamedOperand(*
UseMI, AMDGPU::OpName::srsrc)->getReg() !=
1366 MachineOperand &SOff =
1367 *
TII->getNamedOperand(*
UseMI, AMDGPU::OpName::soffset);
1378 TII->getNamedOperand(*
UseMI, AMDGPU::OpName::cpol)->getImm();
1393 bool FoldingImmLike =
1394 OpToFold.isImm() || OpToFold.isFI() || OpToFold.isGlobal();
1413 for (
unsigned MovOp :
1414 {AMDGPU::S_MOV_B32, AMDGPU::V_MOV_B32_e32, AMDGPU::S_MOV_B64,
1415 AMDGPU::V_MOV_B64_PSEUDO, AMDGPU::V_MOV_B16_t16_e64,
1416 AMDGPU::V_ACCVGPR_WRITE_B32_e64, AMDGPU::AV_MOV_B32_IMM_PSEUDO,
1417 AMDGPU::AV_MOV_B64_IMM_PSEUDO}) {
1418 const MCInstrDesc &MovDesc =
TII->get(MovOp);
1428 const int SrcIdx = MovOp == AMDGPU::V_MOV_B16_t16_e64 ? 2 : 1;
1430 int16_t RegClassID =
TII->getOpRegClassID(MovDesc.
operands()[SrcIdx]);
1431 if (RegClassID != -1) {
1435 MovSrcRC =
TRI->getMatchingSuperRegClass(SrcRC, MovSrcRC, UseSubReg);
1439 if (MovOp == AMDGPU::AV_MOV_B32_IMM_PSEUDO &&
1440 (!OpToFold.isImm() ||
1441 !
TII->isImmOperandLegal(MovDesc, SrcIdx,
1442 *OpToFold.getEffectiveImmVal())))
1455 if (!OpToFold.isImm() ||
1456 !
TII->isImmOperandLegal(MovDesc, 1, *OpToFold.getEffectiveImmVal()))
1462 while (ImpOpI != ImpOpE) {
1469 if (MovOp == AMDGPU::V_MOV_B16_t16_e64) {
1471 MachineOperand NewSrcOp(SrcOp);
1493 LLVM_DEBUG(
dbgs() <<
"Folding " << *OpToFold.OpToFold <<
"\n into "
1498 unsigned SubRegIdx = OpToFold.getSubReg();
1512 static_assert(AMDGPU::sub1_hi16 == 12,
"Subregister layout has changed");
1517 if (SubRegIdx > AMDGPU::sub1) {
1518 LaneBitmask
M =
TRI->getSubRegIndexLaneMask(SubRegIdx);
1519 M |=
M.getLane(
M.getHighestLane() - 1);
1520 SmallVector<unsigned, 4> Indexes;
1521 TRI->getCoveringSubRegIndexes(
TRI->getRegClassForReg(*MRI,
UseReg), M,
1523 assert(Indexes.
size() == 1 &&
"Expected one 32-bit subreg to cover");
1524 SubRegIdx = Indexes[0];
1526 }
else if (
TII->getOpSize(*
UseMI, 1) == 4)
1529 SubRegIdx = AMDGPU::sub0;
1534 OpToFold.OpToFold->setIsKill(
false);
1539 if (foldCopyToAGPRRegSequence(
UseMI))
1544 if (UseOpc == AMDGPU::V_READFIRSTLANE_B32 ||
1545 (UseOpc == AMDGPU::V_READLANE_B32 &&
1547 AMDGPU::getNamedOperandIdx(UseOpc, AMDGPU::OpName::src0))) {
1552 if (FoldingImmLike) {
1555 *OpToFold.DefMI, *
UseMI))
1561 if (OpToFold.isImm()) {
1563 *OpToFold.getEffectiveImmVal());
1564 }
else if (OpToFold.isFI())
1567 assert(OpToFold.isGlobal());
1569 OpToFold.OpToFold->getOffset(),
1570 OpToFold.OpToFold->getTargetFlags());
1576 if (OpToFold.isReg() &&
TRI->isSGPRReg(*MRI, OpToFold.getReg())) {
1579 *OpToFold.DefMI, *
UseMI))
1601 UseDesc.
operands()[UseOpIdx].RegClass == -1)
1609 Changed |= tryAddToFoldList(FoldList,
UseMI, UseOpIdx, OpToFold);
1616 case AMDGPU::S_ADD_I32:
1617 case AMDGPU::S_ADD_U32:
1620 case AMDGPU::S_SUB_I32:
1621 case AMDGPU::S_SUB_U32:
1624 case AMDGPU::V_AND_B32_e64:
1625 case AMDGPU::V_AND_B32_e32:
1626 case AMDGPU::S_AND_B32:
1629 case AMDGPU::V_OR_B32_e64:
1630 case AMDGPU::V_OR_B32_e32:
1631 case AMDGPU::S_OR_B32:
1634 case AMDGPU::V_XOR_B32_e64:
1635 case AMDGPU::V_XOR_B32_e32:
1636 case AMDGPU::S_XOR_B32:
1639 case AMDGPU::S_XNOR_B32:
1642 case AMDGPU::S_NAND_B32:
1645 case AMDGPU::S_NOR_B32:
1648 case AMDGPU::S_ANDN2_B32:
1651 case AMDGPU::S_ORN2_B32:
1654 case AMDGPU::V_LSHL_B32_e64:
1655 case AMDGPU::V_LSHL_B32_e32:
1656 case AMDGPU::S_LSHL_B32:
1658 Result =
LHS << (
RHS & 31);
1660 case AMDGPU::V_LSHLREV_B32_e64:
1661 case AMDGPU::V_LSHLREV_B32_e32:
1662 Result =
RHS << (
LHS & 31);
1664 case AMDGPU::V_LSHR_B32_e64:
1665 case AMDGPU::V_LSHR_B32_e32:
1666 case AMDGPU::S_LSHR_B32:
1667 Result =
LHS >> (
RHS & 31);
1669 case AMDGPU::V_LSHRREV_B32_e64:
1670 case AMDGPU::V_LSHRREV_B32_e32:
1671 Result =
RHS >> (
LHS & 31);
1673 case AMDGPU::V_ASHR_I32_e64:
1674 case AMDGPU::V_ASHR_I32_e32:
1675 case AMDGPU::S_ASHR_I32:
1676 Result =
static_cast<int32_t
>(
LHS) >> (
RHS & 31);
1678 case AMDGPU::V_ASHRREV_I32_e64:
1679 case AMDGPU::V_ASHRREV_I32_e32:
1680 Result =
static_cast<int32_t
>(
RHS) >> (
LHS & 31);
1688 return IsScalar ? AMDGPU::S_MOV_B32 : AMDGPU::V_MOV_B32_e32;
1694bool SIFoldOperandsImpl::tryConstantFoldOp(MachineInstr *
MI)
const {
1695 if (!
MI->allImplicitDefsAreDead())
1698 unsigned Opc =
MI->getOpcode();
1700 int Src0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0);
1704 MachineOperand *Src0 = &
MI->getOperand(Src0Idx);
1705 std::optional<int64_t> Src0Imm =
TII->getImmOrMaterializedImm(*Src0);
1707 if ((
Opc == AMDGPU::V_NOT_B32_e64 ||
Opc == AMDGPU::V_NOT_B32_e32 ||
1708 Opc == AMDGPU::S_NOT_B32) &&
1710 MI->getOperand(1).ChangeToImmediate(~*Src0Imm);
1711 TII->mutateAndCleanupImplicit(
1716 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
1720 MachineOperand *Src1 = &
MI->getOperand(Src1Idx);
1721 std::optional<int64_t> Src1Imm =
TII->getImmOrMaterializedImm(*Src1);
1723 if (!Src0Imm && !Src1Imm)
1729 if (Src0Imm && Src1Imm) {
1734 bool IsSGPR =
TRI->isSGPRReg(*MRI,
MI->getOperand(0).getReg());
1738 MI->getOperand(Src0Idx).ChangeToImmediate(NewImm);
1739 MI->removeOperand(Src1Idx);
1746 if (
Opc == AMDGPU::S_SUB_I32 ||
Opc == AMDGPU::S_SUB_U32) {
1747 if (Src1Imm &&
static_cast<int32_t
>(*Src1Imm) == 0) {
1749 MI->removeOperand(Src1Idx);
1750 TII->mutateAndCleanupImplicit(*
MI,
TII->get(AMDGPU::COPY));
1756 if (!
MI->isCommutable())
1759 if (Src0Imm && !Src1Imm) {
1765 int32_t Src1Val =
static_cast<int32_t
>(*Src1Imm);
1766 if (
Opc == AMDGPU::S_ADD_I32 ||
Opc == AMDGPU::S_ADD_U32) {
1769 MI->removeOperand(Src1Idx);
1770 TII->mutateAndCleanupImplicit(*
MI,
TII->get(AMDGPU::COPY));
1776 if (
Opc == AMDGPU::V_OR_B32_e64 ||
1777 Opc == AMDGPU::V_OR_B32_e32 ||
1778 Opc == AMDGPU::S_OR_B32) {
1781 MI->removeOperand(Src1Idx);
1782 TII->mutateAndCleanupImplicit(*
MI,
TII->get(AMDGPU::COPY));
1783 }
else if (Src1Val == -1) {
1785 MI->removeOperand(Src0Idx);
1786 TII->mutateAndCleanupImplicit(
1794 if (
Opc == AMDGPU::V_AND_B32_e64 ||
Opc == AMDGPU::V_AND_B32_e32 ||
1795 Opc == AMDGPU::S_AND_B32) {
1798 MI->removeOperand(Src0Idx);
1799 TII->mutateAndCleanupImplicit(
1801 }
else if (Src1Val == -1) {
1803 MI->removeOperand(Src1Idx);
1804 TII->mutateAndCleanupImplicit(*
MI,
TII->get(AMDGPU::COPY));
1811 if (
Opc == AMDGPU::V_XOR_B32_e64 ||
Opc == AMDGPU::V_XOR_B32_e32 ||
1812 Opc == AMDGPU::S_XOR_B32) {
1815 MI->removeOperand(Src1Idx);
1816 TII->mutateAndCleanupImplicit(*
MI,
TII->get(AMDGPU::COPY));
1825bool SIFoldOperandsImpl::tryFoldCndMask(MachineInstr &
MI)
const {
1826 unsigned Opc =
MI.getOpcode();
1827 if (
Opc != AMDGPU::V_CNDMASK_B32_e32 &&
Opc != AMDGPU::V_CNDMASK_B32_e64 &&
1828 Opc != AMDGPU::V_CNDMASK_B64_PSEUDO)
1831 MachineOperand *Src0 =
TII->getNamedOperand(
MI, AMDGPU::OpName::src0);
1832 MachineOperand *Src1 =
TII->getNamedOperand(
MI, AMDGPU::OpName::src1);
1834 std::optional<int64_t> Src1Imm =
TII->getImmOrMaterializedImm(*Src1);
1838 std::optional<int64_t> Src0Imm =
TII->getImmOrMaterializedImm(*Src0);
1839 if (!Src0Imm || *Src0Imm != *Src1Imm)
1844 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1_modifiers);
1846 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0_modifiers);
1847 if ((Src1ModIdx != -1 &&
MI.getOperand(Src1ModIdx).getImm() != 0) ||
1848 (Src0ModIdx != -1 &&
MI.getOperand(Src0ModIdx).getImm() != 0))
1854 int Src2Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2);
1856 MI.removeOperand(Src2Idx);
1857 MI.removeOperand(AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1));
1858 if (Src1ModIdx != -1)
1859 MI.removeOperand(Src1ModIdx);
1860 if (Src0ModIdx != -1)
1861 MI.removeOperand(Src0ModIdx);
1862 TII->mutateAndCleanupImplicit(
MI, NewDesc);
1869std::optional<SIFoldOperandsImpl::ANDMaskResult>
1870SIFoldOperandsImpl::getANDMaskRegOperand(MachineInstr &AndMI)
const {
1872 if (
Opc != AMDGPU::V_AND_B32_e64 &&
Opc != AMDGPU::V_AND_B32_e32 &&
1873 Opc != AMDGPU::S_AND_B32)
1874 return std::nullopt;
1876 std::optional<int64_t> MaskImm =
1881 MaskImm =
TII->getImmOrMaterializedImm(AndMI.
getOperand(2));
1885 return std::nullopt;
1898bool SIFoldOperandsImpl::tryFoldRedundantAND(MachineInstr &ChildMI)
const {
1903 std::optional<ANDMaskResult> ChildResult = getANDMaskRegOperand(ChildMI);
1907 if (!ChildResult->Reg.isVirtual())
1910 MachineInstr *ParentMI = MRI->
getVRegDef(ChildResult->Reg);
1914 int64_t ParentMask = 0;
1915 std::optional<ANDMaskResult> ParentResult = getANDMaskRegOperand(*ParentMI);
1918 ParentMask = ParentResult->Mask;
1921 ParentMask = 0xffff;
1927 if ((ParentMask & ChildResult->Mask) != ParentMask)
1949bool SIFoldOperandsImpl::foldInstOperand(MachineInstr &
MI,
1950 const FoldableDef &OpToFold)
const {
1954 SmallVector<MachineInstr *, 4> CopiesToReplace;
1956 MachineOperand &Dst =
MI.getOperand(0);
1961 for (
auto *U : UsesToProcess) {
1962 MachineInstr *
UseMI =
U->getParent();
1964 FoldableDef SubOpToFold = OpToFold.getWithSubReg(*
TRI,
U->getSubReg());
1969 if (CopiesToReplace.
empty() && FoldList.
empty())
1973 for (MachineInstr *Copy : CopiesToReplace)
1974 Copy->addImplicitDefUseOperands(*MF);
1976 SetVector<MachineInstr *> ConstantFoldCandidates;
1977 for (FoldCandidate &Fold : FoldList) {
1978 assert(!Fold.isReg() || Fold.Def.OpToFold);
1979 if (Fold.isReg() && Fold.getReg().isVirtual()) {
1981 const MachineInstr *
DefMI = Fold.Def.DefMI;
1989 assert(Fold.Def.OpToFold && Fold.isReg());
1996 <<
static_cast<int>(Fold.UseOpNo) <<
" of "
2000 ConstantFoldCandidates.
insert(Fold.UseMI);
2002 }
else if (Fold.Commuted) {
2004 TII->commuteInstruction(*Fold.UseMI,
false);
2008 for (MachineInstr *
MI : ConstantFoldCandidates) {
2009 if (tryConstantFoldOp(
MI)) {
2019bool SIFoldOperandsImpl::foldCopyToAGPRRegSequence(MachineInstr *CopyMI)
const {
2026 if (!
TRI->isAGPRClass(DefRC))
2038 DenseMap<TargetInstrInfo::RegSubRegPair, Register> VGPRCopies;
2047 unsigned NumFoldable = 0;
2049 for (
unsigned I = 1;
I != NumRegSeqOperands;
I += 2) {
2066 DefRC, &AMDGPU::AGPR_32RegClass, SubRegIdx);
2086 TRI->getMatchingSuperRegClass(DefRC, InputRC, SubRegIdx);
2097 if (NumFoldable == 0)
2100 CopyMI->
setDesc(
TII->get(AMDGPU::REG_SEQUENCE));
2104 for (
auto [Def, DestSubIdx] : NewDefs) {
2105 if (!
Def->isReg()) {
2109 BuildMI(
MBB, CopyMI,
DL,
TII->get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), Tmp)
2114 Def->setIsKill(
false);
2116 Register &VGPRCopy = VGPRCopies[Src];
2119 TRI->getSubRegisterClass(UseRC, DestSubIdx);
2144 B.addImm(DestSubIdx);
2151bool SIFoldOperandsImpl::tryFoldFoldableCopy(
2152 MachineInstr &
MI, MachineOperand *&CurrentKnownM0Val)
const {
2156 if (DstReg == AMDGPU::M0) {
2157 MachineOperand &NewM0Val =
MI.getOperand(1);
2158 if (CurrentKnownM0Val && CurrentKnownM0Val->
isIdenticalTo(NewM0Val)) {
2159 MI.eraseFromParent();
2170 MachineOperand *OpToFoldPtr;
2171 if (
MI.getOpcode() == AMDGPU::V_MOV_B16_t16_e64) {
2173 if (
TII->hasAnyModifiersSet(
MI))
2175 OpToFoldPtr = &
MI.getOperand(2);
2177 OpToFoldPtr = &
MI.getOperand(1);
2178 MachineOperand &OpToFold = *OpToFoldPtr;
2182 if (!FoldingImm && !OpToFold.
isReg())
2187 !
TRI->isConstantPhysReg(OpToFold.
getReg()))
2216 if (
MI.getOpcode() == AMDGPU::COPY && OpToFold.
isReg() &&
2218 if (DstRC == &AMDGPU::SReg_32RegClass &&
2227 if (OpToFold.
isReg() &&
MI.isCopy() && !
MI.getOperand(1).getSubReg()) {
2228 if (foldCopyToAGPRRegSequence(&
MI))
2232 FoldableDef
Def(OpToFold, DstRC);
2233 bool Changed = foldInstOperand(
MI, Def);
2240 auto *InstToErase = &
MI;
2242 auto &SrcOp = InstToErase->getOperand(1);
2244 InstToErase->eraseFromParent();
2246 InstToErase =
nullptr;
2250 if (!InstToErase || !
TII->isFoldableCopy(*InstToErase))
2254 if (InstToErase && InstToErase->isRegSequence() &&
2256 InstToErase->eraseFromParent();
2266 return OpToFold.
isReg() &&
2267 foldCopyToVGPROfScalarAddOfFrameIndex(DstReg, OpToFold.
getReg(),
MI);
2272const MachineOperand *
2273SIFoldOperandsImpl::isClamp(
const MachineInstr &
MI)
const {
2274 unsigned Op =
MI.getOpcode();
2276 case AMDGPU::V_MAX_F32_e64:
2277 case AMDGPU::V_MAX_F16_e64:
2278 case AMDGPU::V_MAX_F16_t16_e64:
2279 case AMDGPU::V_MAX_F16_fake16_e64:
2280 case AMDGPU::V_MAX_F64_e64:
2281 case AMDGPU::V_MAX_NUM_F64_e64:
2282 case AMDGPU::V_PK_MAX_F16:
2283 case AMDGPU::V_MAX_BF16_PSEUDO_e64:
2284 case AMDGPU::V_PK_MAX_NUM_BF16: {
2285 if (
MI.mayRaiseFPException())
2288 if (!
TII->getNamedOperand(
MI, AMDGPU::OpName::clamp)->getImm())
2292 const MachineOperand *Src0 =
TII->getNamedOperand(
MI, AMDGPU::OpName::src0);
2293 const MachineOperand *Src1 =
TII->getNamedOperand(
MI, AMDGPU::OpName::src1);
2297 Src0->
getSubReg() != AMDGPU::NoSubRegister)
2301 if (
TII->hasModifiersSet(
MI, AMDGPU::OpName::omod))
2305 =
TII->getNamedOperand(
MI, AMDGPU::OpName::src0_modifiers)->getImm();
2307 =
TII->getNamedOperand(
MI, AMDGPU::OpName::src1_modifiers)->getImm();
2311 unsigned UnsetMods =
2312 (
Op == AMDGPU::V_PK_MAX_F16 ||
Op == AMDGPU::V_PK_MAX_NUM_BF16)
2315 if (Src0Mods != UnsetMods && Src1Mods != UnsetMods)
2325bool SIFoldOperandsImpl::tryFoldClamp(MachineInstr &
MI) {
2326 const MachineOperand *ClampSrc = isClamp(
MI);
2342 if (
Def->mayRaiseFPException())
2345 MachineOperand *DefClamp =
TII->getNamedOperand(*Def, AMDGPU::OpName::clamp);
2349 LLVM_DEBUG(
dbgs() <<
"Folding clamp " << *DefClamp <<
" into " << *Def);
2355 Register MIDstReg =
MI.getOperand(0).getReg();
2356 if (
TRI->isSGPRReg(*MRI, DefReg)) {
2365 MI.eraseFromParent();
2370 if (
TII->convertToThreeAddress(*Def,
nullptr,
nullptr))
2371 Def->eraseFromParent();
2378 case AMDGPU::V_MUL_F64_e64:
2379 case AMDGPU::V_MUL_F64_pseudo_e64: {
2381 case 0x3fe0000000000000:
2383 case 0x4000000000000000:
2385 case 0x4010000000000000:
2391 case AMDGPU::V_MUL_F32_e64: {
2392 switch (
static_cast<uint32_t>(Val)) {
2403 case AMDGPU::V_MUL_F16_e64:
2404 case AMDGPU::V_MUL_F16_t16_e64:
2405 case AMDGPU::V_MUL_F16_fake16_e64: {
2406 switch (
static_cast<uint16_t>(Val)) {
2425std::pair<const MachineOperand *, int>
2426SIFoldOperandsImpl::isOMod(
const MachineInstr &
MI)
const {
2427 unsigned Op =
MI.getOpcode();
2429 case AMDGPU::V_MUL_F64_e64:
2430 case AMDGPU::V_MUL_F64_pseudo_e64:
2431 case AMDGPU::V_MUL_F32_e64:
2432 case AMDGPU::V_MUL_F16_t16_e64:
2433 case AMDGPU::V_MUL_F16_fake16_e64:
2434 case AMDGPU::V_MUL_F16_e64: {
2436 if ((
Op == AMDGPU::V_MUL_F32_e64 &&
2438 ((
Op == AMDGPU::V_MUL_F64_e64 ||
Op == AMDGPU::V_MUL_F64_pseudo_e64 ||
2439 Op == AMDGPU::V_MUL_F16_e64 ||
Op == AMDGPU::V_MUL_F16_t16_e64 ||
2440 Op == AMDGPU::V_MUL_F16_fake16_e64) &&
2443 MI.mayRaiseFPException())
2446 const MachineOperand *Src0 =
TII->getNamedOperand(
MI, AMDGPU::OpName::src0);
2447 const MachineOperand *Src1 =
TII->getNamedOperand(
MI, AMDGPU::OpName::src1);
2450 std::optional<int64_t> Src1Imm =
2451 TII->getImmOrMaterializedImm(
const_cast<MachineOperand &
>(*Src1));
2457 TII->hasModifiersSet(
MI, AMDGPU::OpName::src0_modifiers) ||
2458 TII->hasModifiersSet(
MI, AMDGPU::OpName::src1_modifiers) ||
2459 TII->hasModifiersSet(
MI, AMDGPU::OpName::omod) ||
2460 TII->hasModifiersSet(
MI, AMDGPU::OpName::clamp))
2463 return {Src0, OMod};
2465 case AMDGPU::V_ADD_F64_e64:
2466 case AMDGPU::V_ADD_F64_pseudo_e64:
2467 case AMDGPU::V_ADD_F32_e64:
2468 case AMDGPU::V_ADD_F16_e64:
2469 case AMDGPU::V_ADD_F16_t16_e64:
2470 case AMDGPU::V_ADD_F16_fake16_e64: {
2472 if ((
Op == AMDGPU::V_ADD_F32_e64 &&
2474 ((
Op == AMDGPU::V_ADD_F64_e64 ||
Op == AMDGPU::V_ADD_F64_pseudo_e64 ||
2475 Op == AMDGPU::V_ADD_F16_e64 ||
Op == AMDGPU::V_ADD_F16_t16_e64 ||
2476 Op == AMDGPU::V_ADD_F16_fake16_e64) &&
2481 const MachineOperand *Src0 =
TII->getNamedOperand(
MI, AMDGPU::OpName::src0);
2482 const MachineOperand *Src1 =
TII->getNamedOperand(
MI, AMDGPU::OpName::src1);
2486 !
TII->hasModifiersSet(
MI, AMDGPU::OpName::src0_modifiers) &&
2487 !
TII->hasModifiersSet(
MI, AMDGPU::OpName::src1_modifiers) &&
2488 !
TII->hasModifiersSet(
MI, AMDGPU::OpName::clamp) &&
2489 !
TII->hasModifiersSet(
MI, AMDGPU::OpName::omod))
2500bool SIFoldOperandsImpl::tryFoldOMod(MachineInstr &
MI) {
2501 const MachineOperand *RegOp;
2503 std::tie(RegOp, OMod) = isOMod(
MI);
2505 RegOp->
getSubReg() != AMDGPU::NoSubRegister ||
2510 MachineOperand *DefOMod =
TII->getNamedOperand(*Def, AMDGPU::OpName::omod);
2514 if (
Def->mayRaiseFPException())
2519 if (
TII->hasModifiersSet(*Def, AMDGPU::OpName::clamp))
2525 Register OModSrcReg =
Def->getOperand(0).getReg();
2530 MI.eraseFromParent();
2535 if (
TII->convertToThreeAddress(*Def,
nullptr,
nullptr))
2536 Def->eraseFromParent();
2543bool SIFoldOperandsImpl::tryFoldSGPRSplatRegSequence(MachineInstr &
MI) {
2546 if (!ST->hasPackedFP64SingleSGPROps() && !ST->hasPackedU64SingleSGPROps())
2553 if (!
TRI->isSGPRClass(RegClass) ||
TRI->getRegSizeInBits(*RegClass) != 128)
2557 if (!getRegSeqInit(Defs,
Reg))
2561 if (Defs.
size() <= 1)
2564 const auto &[FirstOp,
_] = Defs.
front();
2565 if (!FirstOp->isReg())
2568 Register FirstReg = FirstOp->getReg();
2569 unsigned FirstSubReg = FirstOp->getSubReg();
2572 if (!
TRI->isSGPRClass(FirstRegClass))
2577 const auto &[
Op,
_] =
Def;
2578 return Op->isReg() &&
Op->getReg() == FirstReg &&
2579 Op->getSubReg() == FirstSubReg;
2591 MachineInstrBuilder
RS =
BuildMI(*
MI.getParent(),
MI,
MI.getDebugLoc(),
2592 TII->get(AMDGPU::REG_SEQUENCE), NewDst);
2595 FirstOp->setIsKill(
false);
2597 RS.addImm(Defs[0].second);
2602 for (
unsigned i = 1; i < Defs.
size(); ++i) {
2603 RS.addReg(UndefReg, RegState::Undef);
2604 RS.addImm(Defs[i].second);
2613 MI.eraseFromParent();
2619bool SIFoldOperandsImpl::tryFoldRegSequence(MachineInstr &
MI) {
2623 if (tryFoldSGPRSplatRegSequence(
MI))
2626 auto Reg =
MI.getOperand(0).getReg();
2628 if (!ST->hasGFX90AInsts() || !
TRI->isVGPR(*MRI,
Reg) ||
2633 if (!getRegSeqInit(Defs,
Reg))
2636 for (
auto &[
Op, SubIdx] : Defs) {
2639 if (
TRI->isAGPR(*MRI,
Op->getReg()))
2642 const MachineInstr *SubDef = MRI->
getVRegDef(
Op->getReg());
2650 MachineInstr *
UseMI =
Op->getParent();
2659 if (
Op->getSubReg())
2665 if (!OpRC || !
TRI->isVectorSuperClass(OpRC))
2671 TII->get(AMDGPU::REG_SEQUENCE), Dst);
2673 for (
auto &[Def, SubIdx] : Defs) {
2674 Def->setIsKill(
false);
2675 if (
TRI->isAGPR(*MRI,
Def->getReg())) {
2686 if (!
TII->isOperandLegal(*
UseMI, OpIdx,
Op)) {
2688 RS->eraseFromParent();
2697 MI.eraseFromParent();
2705 Register &OutReg,
unsigned &OutSubReg) {
2715 if (
TRI.isAGPR(MRI, CopySrcReg)) {
2716 OutReg = CopySrcReg;
2725 if (!CopySrcDef || !CopySrcDef->
isCopy())
2732 OtherCopySrc.
getSubReg() != AMDGPU::NoSubRegister ||
2733 !
TRI.isAGPR(MRI, OtherCopySrcReg))
2736 OutReg = OtherCopySrcReg;
2770bool SIFoldOperandsImpl::tryFoldPhiAGPR(MachineInstr &
PHI) {
2774 if (!
TRI->isVGPR(*MRI, PhiOut))
2780 for (
unsigned K = 1;
K <
PHI.getNumExplicitOperands();
K += 2) {
2781 MachineOperand &MO =
PHI.getOperand(K);
2783 if (!Copy || !
Copy->isCopy())
2787 unsigned AGPRRegMask = AMDGPU::NoSubRegister;
2792 if (
const auto *SubRC =
TRI->getSubRegisterClass(CopyInRC, AGPRRegMask))
2803 bool IsAGPR32 = (ARC == &AMDGPU::AGPR_32RegClass);
2807 for (
unsigned K = 1;
K <
PHI.getNumExplicitOperands();
K += 2) {
2808 MachineOperand &MO =
PHI.getOperand(K);
2812 MachineBasicBlock *InsertMBB =
nullptr;
2815 unsigned CopyOpc = AMDGPU::COPY;
2820 if (
Def->isCopy()) {
2822 unsigned AGPRSubReg = AMDGPU::NoSubRegister;
2835 MachineOperand &CopyIn =
Def->getOperand(1);
2838 CopyOpc = AMDGPU::V_ACCVGPR_WRITE_B32_e64;
2841 InsertMBB =
Def->getParent();
2849 MachineInstr *
MI =
BuildMI(*InsertMBB, InsertPt,
PHI.getDebugLoc(),
2850 TII->get(CopyOpc), NewReg)
2860 PHI.getOperand(0).setReg(NewReg);
2866 TII->get(AMDGPU::COPY), PhiOut)
2874bool SIFoldOperandsImpl::tryFoldLoad(MachineInstr &
MI) {
2876 if (!ST->hasGFX90AInsts() ||
MI.getNumExplicitDefs() != 1)
2879 MachineOperand &
Def =
MI.getOperand(0);
2896 while (!
Users.empty()) {
2897 const MachineInstr *
I =
Users.pop_back_val();
2898 if (!
I->isCopy() && !
I->isRegSequence())
2900 Register DstReg =
I->getOperand(0).getReg();
2904 if (
TRI->isAGPR(*MRI, DstReg))
2908 Users.push_back(&U);
2913 if (!
TII->isOperandLegal(
MI, 0, &Def)) {
2918 while (!MoveRegs.
empty()) {
2960bool SIFoldOperandsImpl::tryOptimizeAGPRPhis(MachineBasicBlock &
MBB) {
2963 if (ST->hasGFX90AInsts())
2967 DenseMap<std::pair<Register, unsigned>, std::vector<MachineOperand *>>
2970 for (
auto &
MI :
MBB) {
2974 if (!
TRI->isAGPR(*MRI,
MI.getOperand(0).getReg()))
2977 for (
unsigned K = 1;
K <
MI.getNumOperands();
K += 2) {
2978 MachineOperand &PhiMO =
MI.getOperand(K);
2988 for (
const auto &[Entry, MOs] : RegToMO) {
2989 if (MOs.size() == 1)
2994 MachineBasicBlock *DefMBB =
Def->getParent();
3001 MachineInstr *VGPRCopy =
3003 TII->get(AMDGPU::V_ACCVGPR_READ_B32_e64), TempVGPR)
3009 TII->get(AMDGPU::COPY), TempAGPR)
3013 for (MachineOperand *MO : MOs) {
3025bool SIFoldOperandsImpl::run(
MachineFunction &MF,
const MachineLoopInfo *MLI) {
3031 MFI = MF.
getInfo<SIMachineFunctionInfo>();
3042 MachineOperand *CurrentKnownM0Val =
nullptr;
3050 if (tryConstantFoldOp(&
MI)) {
3055 if (tryFoldRedundantAND(
MI)) {
3060 if (
MI.isRegSequence() && tryFoldRegSequence(
MI)) {
3065 if (
MI.isPHI() && tryFoldPhiAGPR(
MI)) {
3070 if (
MI.mayLoad() && tryFoldLoad(
MI)) {
3075 if (
TII->isFoldableCopy(
MI)) {
3076 Changed |= tryFoldFoldableCopy(
MI, CurrentKnownM0Val);
3081 if (CurrentKnownM0Val &&
MI.modifiesRegister(AMDGPU::M0,
TRI))
3082 CurrentKnownM0Val =
nullptr;
3102 bool Changed = SIFoldOperandsImpl().run(MF, MLI);
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Provides AMDGPU specific target descriptions.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static bool updateOperand(Instruction *Inst, unsigned Idx, Instruction *Mat)
Updates the operand at Idx in instruction Inst with the result of instruction Mat.
This file builds on the ADT/GraphTraits.h file to build generic depth first graph iterator.
AMD GCN specific subclass of TargetSubtarget.
static Register UseReg(const MachineOperand &MO)
const HexagonInstrInfo * TII
iv Induction Variable Users
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
static bool isReg(const MCInst &MI, unsigned OpNo)
if(auto Err=PB.parsePassPipeline(MPM, Passes)) return wrap(std MPM run * Mod
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
static bool loopModifiesExec(const MachineLoop &L, const SIRegisterInfo &TRI)
static unsigned macToMad(unsigned Opc)
static bool isAGPRCopy(const SIRegisterInfo &TRI, const MachineRegisterInfo &MRI, const MachineInstr &Copy, Register &OutReg, unsigned &OutSubReg)
Checks whether Copy is a AGPR -> VGPR copy.
static void appendFoldCandidate(SmallVectorImpl< FoldCandidate > &FoldList, FoldCandidate &&Entry)
static const TargetRegisterClass * getRegOpRC(const MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const MachineOperand &MO)
static bool evalBinaryInstruction(unsigned Opcode, int32_t &Result, uint32_t LHS, uint32_t RHS)
static int getOModValue(unsigned Opc, int64_t Val)
static unsigned getMovOpc(bool IsScalar)
static MachineOperand * lookUpCopyChain(const SIInstrInfo &TII, const MachineRegisterInfo &MRI, Register SrcReg)
static bool checkImmOpForPKF32InstrReplicatesLower32BitsOfScalarOperand(const FoldableDef &OpToFold)
static bool isPKF32InstrReplicatesLower32BitsOfScalarOperand(const GCNSubtarget *ST, MachineInstr *MI, unsigned OpNo)
Interface definition for SIInstrInfo.
Interface definition for SIRegisterInfo.
static int Lookup(ArrayRef< TableEntry > Table, unsigned Opcode)
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
Represents analyses that only rely on functions' control flow.
FunctionPass class - This class is used to implement most global optimizations.
const SIInstrInfo * getInstrInfo() const override
bool hasDOTOpSelHazard() const
bool zeroesHigh16BitsOfDest(unsigned Opcode) const
Returns if the result of this instruction with a 16-bit result returned in a 32-bit register implicit...
const HexagonRegisterInfo & getRegisterInfo() const
bool contains(const LoopT *L) const
Return true if the specified loop is contained within this loop.
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
ArrayRef< MCOperandInfo > operands() const
int getOperandConstraint(unsigned OpNum, MCOI::OperandConstraint Constraint) const
Returns the value of the specified operand constraint if it is present.
bool isVariadic() const
Return true if this instruction can have a variable number of operands.
This holds information about one operand of a machine instruction, indicating the register class for ...
uint8_t OperandType
Information about the type of the operand.
bool hasSuperClassEq(const MCRegisterClass *RC) const
Returns true if RC is a super-class of or equal to this class.
bool contains(MCRegister Reg) const
contains - Return true if the specified register is included in this register class.
bool hasSubClassEq(const MCRegisterClass *RC) const
Returns true if RC is a sub-class of or equal to this class.
An RAII based helper class to modify MachineFunctionProperties when running pass.
LLVM_ABI iterator SkipPHIsLabelsAndDebug(iterator I, Register Reg=Register(), bool SkipPseudoOp=true)
Return the first instruction in MBB after I that is not a PHI, label or debug.
LLVM_ABI LivenessQueryResult computeRegisterLiveness(const TargetRegisterInfo *TRI, MCRegister Reg, const_iterator Before, unsigned Neighborhood=10) const
Return whether (physical) register Reg has been defined and not killed as of just before Before.
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
LLVM_ABI iterator getFirstNonPHI()
Returns a pointer to the first instruction in this block that is not a PHINode instruction.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineInstrBundleIterator< MachineInstr > iterator
LivenessQueryResult
Possible outcome of a register liveness query to computeRegisterLiveness()
@ LQR_Dead
Register is known to be fully dead.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
Properties which a MachineFunction may have at a given point in time.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Register getReg(unsigned Idx) const
Get the register for the operand index.
const MachineInstrBuilder & setOperandDead(unsigned OpIdx) const
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
bool readsRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr reads the specified register.
LLVM_ABI bool allImplicitDefsAreDead() const
Return true if all the implicit defs of this instruction are dead.
unsigned getNumOperands() const
Retuns the total number of operands.
LLVM_ABI void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
unsigned getOperandNo(const_mop_iterator I) const
Returns the number of the operand iterator I points to.
LLVM_ABI unsigned getNumExplicitOperands() const
Returns the number of non-implicit operands.
mop_range implicit_operands()
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
void clearFlag(MIFlag Flag)
clearFlag - Clear a MI flag.
bool isRegSequence() const
LLVM_ABI void setDesc(const MCInstrDesc &TID)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one.
MachineOperand * mop_iterator
iterator/begin/end - Iterate over all operands of a machine instruction.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
LLVM_ABI void removeOperand(unsigned OpNo)
Erase an operand from an instruction, leaving it with one fewer operand than it started with.
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
Analysis pass that exposes the MachineLoopInfo for a machine function.
MachineOperand class - Representation of each machine instruction operand.
void setSubReg(unsigned subReg)
unsigned getSubReg() const
LLVM_ABI unsigned getOperandNo() const
Returns the index of this operand in the instruction that it belongs to.
LLVM_ABI void substVirtReg(Register Reg, unsigned SubIdx, const TargetRegisterInfo &)
substVirtReg - Substitute the current register with the virtual subregister Reg:SubReg.
LLVM_ABI void ChangeToFrameIndex(int Idx, unsigned TargetFlags=0)
Replace this operand with a frame index.
void setImm(int64_t immVal)
bool isReg() const
isReg - Tests if this is a MO_Register operand.
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
LLVM_ABI void ChangeToImmediate(int64_t ImmVal, unsigned TargetFlags=0)
ChangeToImmediate - Replace this operand with a new immediate operand of the specified value.
LLVM_ABI void ChangeToGA(const GlobalValue *GV, int64_t Offset, unsigned TargetFlags=0)
ChangeToGA - Replace this operand with a new global address operand.
void setIsKill(bool Val=true)
LLVM_ABI void ChangeToRegister(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isDebug=false)
ChangeToRegister - Replace this operand with a new register operand of the specified value.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
LLVM_ABI void substPhysReg(MCRegister Reg, const TargetRegisterInfo &)
substPhysReg - Substitute the current register with the physical register Reg, taking any existing Su...
static MachineOperand CreateImm(int64_t Val)
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
void setIsUndef(bool Val=true)
Register getReg() const
getReg - Returns the register number.
bool isFI() const
isFI - Tests if this is a MO_FrameIndex operand.
LLVM_ABI 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_GlobalAddress
Address of a global value.
@ MO_FrameIndex
Abstract Stack Frame Index.
@ MO_Register
Register operand.
static MachineOperand CreateFI(int Idx)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
use_nodbg_iterator use_nodbg_begin(Register RegNo) const
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
LLVM_ABI void clearKillFlags(Register Reg) const
clearKillFlags - Iterate over all the uses of the given register and clear the kill flag from the Mac...
LLVM_ABI LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
iterator_range< use_nodbg_iterator > use_nodbg_operands(Register Reg) const
bool use_nodbg_empty(Register RegNo) const
use_nodbg_empty - Return true if there are no non-Debug instructions using the specified register.
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLVM_ABI bool hasOneNonDBGUser(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug instruction using the specified regis...
iterator_range< use_instr_nodbg_iterator > use_nodbg_instructions(Register Reg) const
void setRegAllocationHint(Register VReg, unsigned Type, Register PrefReg)
setRegAllocationHint - Specify a register allocation hint for the specified virtual register.
LLVM_ABI void setRegClass(Register Reg, const TargetRegisterClass *RC)
setRegClass - Set the register class of the specified virtual register.
LLVM_ABI const TargetRegisterClass * constrainRegClass(Register Reg, const TargetRegisterClass *RC, unsigned MinNumRegs=0)
constrainRegClass - Constrain the register class of the specified virtual register to be a common sub...
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Wrapper class representing virtual and physical registers.
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
static bool hasSameClamp(const MachineInstr &A, const MachineInstr &B)
static std::optional< int64_t > extractSubregFromImm(int64_t ImmVal, unsigned SubRegIndex)
Return the extracted immediate value in a subregister use from a constant materialized in a super reg...
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
Register getScratchRSrcReg() const
Returns the physical register reserved for use as the resource descriptor for scratch accesses.
SIModeRegisterDefaults getMode() const
bool insert(const value_type &X)
Insert a new element into the SetVector.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
Represent a constant reference to a string, i.e.
static const unsigned CommuteAnyOperandIndex
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
bool isInlinableLiteralV216(uint32_t Literal, uint8_t OpType)
LLVM_READONLY int32_t getMFMAEarlyClobberOp(uint32_t Opcode)
LLVM_READONLY bool hasNamedOperand(uint64_t Opcode, OpName NamedIdx)
bool isPackedSingleSGPR64BitInst(unsigned Opc)
The opcode is a packed 64-bit instruction which only reads low 64 bits of a scalar operand and propag...
LLVM_READONLY int32_t getVOPe32(uint32_t Opcode)
constexpr bool isSISrcOperand(const MCOperandInfo &OpInfo)
Is this an AMDGPU specific source operand?
@ OPERAND_REG_INLINE_C_FP64
@ OPERAND_REG_INLINE_C_BF16
@ OPERAND_REG_INLINE_C_V2BF16
@ OPERAND_REG_IMM_V2INT64
@ OPERAND_REG_IMM_V2INT16
@ OPERAND_REG_INLINE_C_INT64
@ OPERAND_REG_IMM_NOINLINE_V2FP16
@ OPERAND_REG_INLINE_C_V2FP16
@ OPERAND_REG_INLINE_AC_INT32
Operands with an AccVGPR register or inline constant.
@ OPERAND_REG_INLINE_AC_FP32
@ OPERAND_REG_INLINE_C_FP32
@ OPERAND_REG_INLINE_C_INT32
@ OPERAND_REG_INLINE_C_V2INT16
@ OPERAND_REG_INLINE_AC_FP64
LLVM_READONLY int32_t getFlatScratchInstSSfromSV(uint32_t Opcode)
bool supportsScaleOffset(const MCInstrInfo &MII, unsigned Opcode)
constexpr bool isVOP3(const T &...O)
constexpr bool isMAI(const T &...O)
constexpr bool isSWMMAC(const T &...O)
constexpr bool isVOP3P(const T &...O)
constexpr bool isWMMA(const T &...O)
constexpr bool isDOT(const T &...O)
constexpr bool isPacked(const T &...O)
NodeAddr< DefNode * > Def
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.
TargetInstrInfo::RegSubRegPair getRegSubRegPair(const MachineOperand &O)
Create RegSubRegPair from a register MachineOperand.
MachineBasicBlock::instr_iterator getBundleStart(MachineBasicBlock::instr_iterator I)
Returns an iterator to the first instruction in the bundle containing I.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
bool execMayBeModifiedBeforeUse(const MachineRegisterInfo &MRI, Register VReg, const MachineInstr &DefMI, const MachineInstr &UseMI)
Return false if EXEC is not changed between the def of VReg at DefMI and the use at UseMI.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
FunctionPass * createSIFoldOperandsLegacyPass()
char & SIFoldOperandsLegacyID
constexpr uint32_t Hi_32(uint64_t Value)
Return the high 32 bits of a 64 bit value.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
constexpr uint32_t Lo_32(uint64_t Value)
Return the low 32 bits of a 64 bit value.
@ Sub
Subtraction of integers.
DWARFExpression::Operation Op
iterator_range< pointer_iterator< WrappedIteratorT > > make_pointer_range(RangeT &&Range)
iterator_range< df_iterator< T > > depth_first(const T &G)
LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
constexpr uint64_t Make_64(uint32_t High, uint32_t Low)
Make a 64-bit integer from a high / low pair of 32-bit integers.
MCRegisterClass TargetRegisterClass
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
@ PreserveSign
The sign of a flushed-to-zero number is preserved in the sign of 0.
DenormalModeKind Output
Denormal flushing mode for floating point instruction results in the default floating point environme...
DenormalMode FP64FP16Denormals
If this is set, neither input or output denormals are flushed for both f64 and f16/v2f16 instructions...
bool IEEE
Floating point opcodes that support exception flag gathering quiet and propagate signaling NaN inputs...
DenormalMode FP32Denormals
If this is set, neither input or output denormals are flushed for most f32 instructions.