}
static bool getFoldableImm(Register Reg, const MachineRegisterInfo &MRI,
- int64_t &Imm) {
+ int64_t &Imm, MachineInstr **DefMI = nullptr) {
if (Reg.isPhysical())
return false;
auto *Def = MRI.getUniqueVRegDef(Reg);
if (Def && SIInstrInfo::isFoldableCopy(*Def) && Def->getOperand(1).isImm()) {
Imm = Def->getOperand(1).getImm();
+ if (DefMI)
+ *DefMI = Def;
return true;
}
return false;
}
-static bool getFoldableImm(const MachineOperand *MO, int64_t &Imm) {
+static bool getFoldableImm(const MachineOperand *MO, int64_t &Imm,
+ MachineInstr **DefMI = nullptr) {
if (!MO->isReg())
return false;
const MachineFunction *MF = MO->getParent()->getParent()->getParent();
const MachineRegisterInfo &MRI = MF->getRegInfo();
- return getFoldableImm(MO->getReg(), MRI, Imm);
+ return getFoldableImm(MO->getReg(), MRI, Imm, DefMI);
}
static void updateLiveVariables(LiveVariables *LV, MachineInstr &MI,
// If we have an SGPR input, we will violate the constant bus restriction.
(ST.getConstantBusLimit(Opc) > 1 || !Src0->isReg() ||
!RI.isSGPRReg(MBB.getParent()->getRegInfo(), Src0->getReg()))) {
+ MachineInstr *DefMI;
+ const auto killDef = [&DefMI, &MBB, this]() -> void {
+ const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
+ // The only user is the instruction which will be killed.
+ if (!MRI.hasOneNonDBGUse(DefMI->getOperand(0).getReg()))
+ return;
+ // We cannot just remove the DefMI here, calling pass will crash.
+ DefMI->setDesc(get(AMDGPU::IMPLICIT_DEF));
+ for (unsigned I = DefMI->getNumOperands() - 1; I != 0; --I)
+ DefMI->RemoveOperand(I);
+ };
+
int64_t Imm;
- if (getFoldableImm(Src2, Imm)) {
+ if (getFoldableImm(Src2, Imm, &DefMI)) {
unsigned NewOpc =
IsFMA ? (IsF16 ? AMDGPU::V_FMAAK_F16 : AMDGPU::V_FMAAK_F32)
: (IsF16 ? AMDGPU::V_MADAK_F16 : AMDGPU::V_MADAK_F32);
updateLiveVariables(LV, MI, *MIB);
if (LIS)
LIS->ReplaceMachineInstrInMaps(MI, *MIB);
+ killDef();
return MIB;
}
}
unsigned NewOpc = IsFMA
? (IsF16 ? AMDGPU::V_FMAMK_F16 : AMDGPU::V_FMAMK_F32)
: (IsF16 ? AMDGPU::V_MADMK_F16 : AMDGPU::V_MADMK_F32);
- if (getFoldableImm(Src1, Imm)) {
+ if (getFoldableImm(Src1, Imm, &DefMI)) {
if (pseudoToMCOpcode(NewOpc) != -1) {
MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
.add(*Dst)
updateLiveVariables(LV, MI, *MIB);
if (LIS)
LIS->ReplaceMachineInstrInMaps(MI, *MIB);
+ killDef();
return MIB;
}
}
- if (getFoldableImm(Src0, Imm)) {
+ if (getFoldableImm(Src0, Imm, &DefMI)) {
if (pseudoToMCOpcode(NewOpc) != -1 &&
isOperandLegal(
MI, AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::src0),
updateLiveVariables(LV, MI, *MIB);
if (LIS)
LIS->ReplaceMachineInstrInMaps(MI, *MIB);
+ killDef();
return MIB;
}
}
# RUN: llc -march=amdgcn -mcpu=gfx1010 %s -run-pass twoaddressinstruction -verify-machineinstrs -o - | FileCheck -check-prefix=GCN %s
# GCN-LABEL: name: test_fmamk_reg_imm_f32
+# GCN: %2:vgpr_32 = IMPLICIT_DEF
+# GCN-NOT: V_MOV_B32
# GCN: V_FMAMK_F32 killed %0.sub0, 1078523331, killed %1, implicit $mode, implicit $exec
---
name: test_fmamk_reg_imm_f32
...
# GCN-LABEL: name: test_fmamk_imm_reg_f32
+# GCN: %2:vgpr_32 = IMPLICIT_DEF
+# GCN-NOT: V_MOV_B32
# GCN: V_FMAMK_F32 killed %0.sub0, 1078523331, killed %1, implicit $mode, implicit $exec
---
name: test_fmamk_imm_reg_f32
...
# GCN-LABEL: name: test_fmaak_f32
+# GCN: %1:vgpr_32 = IMPLICIT_DEF
+# GCN-NOT: V_MOV_B32
# GCN: V_FMAAK_F32 killed %0.sub0, %0.sub1, 1078523331, implicit $mode, implicit $exec
---
name: test_fmaak_f32
...
# GCN-LABEL: name: test_fmamk_reg_imm_f16
+# GCN: %2:vgpr_32 = IMPLICIT_DEF
+# GCN-NOT: V_MOV_B32
# GCN: V_FMAMK_F16 killed %0.sub0, 1078523331, killed %1, implicit $mode, implicit $exec
---
name: test_fmamk_reg_imm_f16
...
# GCN-LABEL: name: test_fmamk_imm_reg_f16
+# GCN: %2:vgpr_32 = IMPLICIT_DEF
+# GCN-NOT: V_MOV_B32
# GCN: V_FMAMK_F16 killed %0.sub0, 1078523331, killed %1, implicit $mode, implicit $exec
---
name: test_fmamk_imm_reg_f16
...
# GCN-LABEL: name: test_fmaak_f16
+# GCN: %1:vgpr_32 = IMPLICIT_DEF
+# GCN-NOT: V_MOV_B32
# GCN: V_FMAAK_F16 killed %0.sub0, %0.sub1, 1078523331, implicit $mode, implicit $exec
---
name: test_fmaak_f16
...
# GCN-LABEL: name: test_fmaak_sgpr_src0_f32
+# GCN: %1:vgpr_32 = IMPLICIT_DEF
+# GCN-NOT: V_MOV_B32
# GCN: %2:vgpr_32 = V_FMAMK_F32 killed %0, 1078523331, %3:vgpr_32, implicit $mode, implicit $exec
---
...
# GCN-LABEL: name: test_fmaak_inlineimm_src0_f32
+# GCN: %0:vgpr_32 = IMPLICIT_DEF
+# GCN-NOT: V_MOV_B32
# GCN: %1:vgpr_32 = V_FMAMK_F32 1073741824, 1078523331, %2:vgpr_32, implicit $mode, implicit $exec
---
...
# GCN-LABEL: name: test_fmaak_inline_literal_f16
+# GCN: %1:vgpr_32 = IMPLICIT_DEF
+# GCN-NOT: V_MOV_B32
# GCN: %2:vgpr_32 = V_FMAAK_F16 16384, killed %0, 49664, implicit $mode, implicit $exec
---
...
+# GCN-LABEL: name: test_fmamk_reg_imm_f32_2_folds
+# GCN: %2:vgpr_32 = IMPLICIT_DEF
+# GCN-NOT: V_MOV_B32
+# GCN: V_FMAMK_F32 %0.sub0, 1078523331, %1, implicit $mode, implicit $exec
+# GCN: V_FMAMK_F32 killed %0.sub0, 1078523331, killed %1, implicit $mode, implicit $exec
+---
+name: test_fmamk_reg_imm_f32_2_folds
+registers:
+ - { id: 0, class: vreg_64 }
+ - { id: 1, class: vgpr_32 }
+ - { id: 2, class: vgpr_32 }
+ - { id: 3, class: vgpr_32 }
+ - { id: 4, class: vgpr_32 }
+body: |
+ bb.0:
+
+ %0 = IMPLICIT_DEF
+ %1 = COPY %0.sub1
+ %2 = V_MOV_B32_e32 1078523331, implicit $exec
+ %3 = V_FMAC_F32_e32 %0.sub0, %2, %1, implicit $mode, implicit $exec
+ %4 = V_FMAC_F32_e32 killed %0.sub0, %2, killed %1, implicit $mode, implicit $exec
+
+...
+
+# GCN-LABEL: name: test_fmamk_reg_imm_f32_used_imm
+# GCN: %2:vgpr_32 = V_MOV_B32_e32 1078523331, implicit $exec
+# GCN: V_FMAMK_F32 killed %0.sub0, 1078523331, killed %1, implicit $mode, implicit $exec
+---
+name: test_fmamk_reg_imm_f32_used_imm
+registers:
+ - { id: 0, class: vreg_64 }
+ - { id: 1, class: vgpr_32 }
+ - { id: 2, class: vgpr_32 }
+ - { id: 3, class: vgpr_32 }
+body: |
+ bb.0:
+
+ %0 = IMPLICIT_DEF
+ %1 = COPY %0.sub1
+ %2 = V_MOV_B32_e32 1078523331, implicit $exec
+ %3 = V_FMAC_F32_e32 killed %0.sub0, %2, killed %1, implicit $mode, implicit $exec
+ S_NOP 0, implicit %2
+
+...