Skip to content

[AMDGPU][MC] Separate VOPC MnemonicAlias from Instruction #89105

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 18, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
222 changes: 117 additions & 105 deletions llvm/lib/Target/AMDGPU/VOPCInstructions.td
Original file line number Diff line number Diff line change
Expand Up @@ -1386,75 +1386,81 @@ multiclass VOPC_Real_Base<GFXGen Gen, bits<9> op> {

multiclass VOPC_Real_with_name<GFXGen Gen, bits<9> op, string OpName,
string asm_name, string pseudo_mnemonic = ""> {
let AssemblerPredicate = Gen.AssemblerPredicate, DecoderNamespace = Gen.DecoderNamespace in {
defvar ps32 = !cast<VOPC_Pseudo>(OpName#"_e32");
defvar ps64 = !cast<VOP3_Pseudo>(OpName#"_e64");
def _e32#Gen.Suffix :
// 32 and 64 bit forms of the instruction have _e32 and _e64
// respectively appended to their assembly mnemonic.
// _e64 is printed as part of the VOPDstS64orS32 operand, whereas
// the destination-less 32bit forms add it to the asmString here.
VOPC_Real<ps32, Gen.Subtarget, asm_name#"_e32">,
VOPCe<op{7-0}>,
MnemonicAlias<!if(!empty(pseudo_mnemonic), ps32.Mnemonic,
pseudo_mnemonic),
asm_name, ps32.AsmVariantName>,
Requires<[Gen.AssemblerPredicate]>;
def _e64#Gen.Suffix :
VOP3_Real<ps64, Gen.Subtarget, asm_name>,
VOP3a_gfx11_gfx12<{0, op}, ps64.Pfl>,
MnemonicAlias<!if(!empty(pseudo_mnemonic), ps64.Mnemonic,
pseudo_mnemonic),
defvar ps32 = !cast<VOPC_Pseudo>(OpName#"_e32");
defvar ps64 = !cast<VOP3_Pseudo>(OpName#"_e64");
let AssemblerPredicate = Gen.AssemblerPredicate in {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just FYI an alternative to splitting this let into two would be to add LetDummies to the defs for the aliases. But this way is fine too.

// MnemonicAlias and GCNPredicateControl both define the field Predicates,
// so GCNPredicateControl must come after MnemonicAlias because it contains
// the predicates we actually want.
def : MnemonicAlias<!if(!empty(pseudo_mnemonic), ps32.Mnemonic,
pseudo_mnemonic),
asm_name, ps32.AsmVariantName>,
GCNPredicateControl;
def : MnemonicAlias<!if(!empty(pseudo_mnemonic), ps64.Mnemonic,
pseudo_mnemonic),
asm_name, ps64.AsmVariantName>,
Requires<[Gen.AssemblerPredicate]> {
// Encoding used for VOPC instructions encoded as VOP3 differs from
// VOP3e by destination name (sdst) as VOPC doesn't have vector dst.
bits<8> sdst;
let Inst{7-0} = sdst;
}

defm : VOPCInstAliases<OpName, !substr(Gen.Suffix, 1), NAME, asm_name>;

if ps32.Pfl.HasExtDPP then {
defvar psDPP = !cast<VOP_DPP_Pseudo>(OpName #"_e32" #"_dpp");
defvar AsmDPP = ps32.Pfl.AsmDPP16;
def _e32_dpp#Gen.Suffix : VOPC_DPP16_SIMC<op{7-0}, psDPP,
Gen.Subtarget, asm_name>;
def _e32_dpp_w32#Gen.Suffix
: VOPC_DPP16<op{7-0}, psDPP, asm_name> {
let AsmString = asm_name # " vcc_lo, " # AsmDPP;
let isAsmParserOnly = 1;
let WaveSizePredicate = isWave32;
}
def _e32_dpp_w64#Gen.Suffix
: VOPC_DPP16<op{7-0}, psDPP, asm_name> {
let AsmString = asm_name # " vcc, " # AsmDPP;
let isAsmParserOnly = 1;
let WaveSizePredicate = isWave64;
GCNPredicateControl;

let DecoderNamespace = Gen.DecoderNamespace in {
def _e32#Gen.Suffix :
// 32 and 64 bit forms of the instruction have _e32 and _e64
// respectively appended to their assembly mnemonic.
// _e64 is printed as part of the VOPDstS64orS32 operand, whereas
// the destination-less 32bit forms add it to the asmString here.
VOPC_Real<ps32, Gen.Subtarget, asm_name#"_e32">,
VOPCe<op{7-0}>;
def _e64#Gen.Suffix :
VOP3_Real_Gen<ps64, Gen, asm_name>,
VOP3a_gfx11_gfx12<{0, op}, ps64.Pfl> {
// Encoding used for VOPC instructions encoded as VOP3 differs from
// VOP3e by destination name (sdst) as VOPC doesn't have vector dst.
bits<8> sdst;
let Inst{7-0} = sdst;
}
defvar AsmDPP8 = ps32.Pfl.AsmDPP8;
def _e32_dpp8#Gen.Suffix : VOPC_DPP8<op{7-0}, ps32, asm_name>;
def _e32_dpp8_w32#Gen.Suffix
: VOPC_DPP8<op{7-0}, ps32, asm_name> {
let AsmString = asm_name # " vcc_lo, " # AsmDPP8;
let isAsmParserOnly = 1;
let WaveSizePredicate = isWave32;
}
def _e32_dpp8_w64#Gen.Suffix
: VOPC_DPP8<op{7-0}, ps32, asm_name> {
let AsmString = asm_name # " vcc, " # AsmDPP8;
let isAsmParserOnly = 1;
let WaveSizePredicate = isWave64;

defm : VOPCInstAliases<OpName, !substr(Gen.Suffix, 1), NAME, asm_name>;

if ps32.Pfl.HasExtDPP then {
defvar psDPP = !cast<VOP_DPP_Pseudo>(OpName #"_e32" #"_dpp");
defvar AsmDPP = ps32.Pfl.AsmDPP16;
def _e32_dpp#Gen.Suffix : VOPC_DPP16_SIMC<op{7-0}, psDPP,
Gen.Subtarget, asm_name>;
def _e32_dpp_w32#Gen.Suffix
: VOPC_DPP16<op{7-0}, psDPP, asm_name> {
let AsmString = asm_name # " vcc_lo, " # AsmDPP;
let isAsmParserOnly = 1;
let WaveSizePredicate = isWave32;
}
def _e32_dpp_w64#Gen.Suffix
: VOPC_DPP16<op{7-0}, psDPP, asm_name> {
let AsmString = asm_name # " vcc, " # AsmDPP;
let isAsmParserOnly = 1;
let WaveSizePredicate = isWave64;
}
defvar AsmDPP8 = ps32.Pfl.AsmDPP8;
def _e32_dpp8#Gen.Suffix : VOPC_DPP8<op{7-0}, ps32, asm_name>;
def _e32_dpp8_w32#Gen.Suffix
: VOPC_DPP8<op{7-0}, ps32, asm_name> {
let AsmString = asm_name # " vcc_lo, " # AsmDPP8;
let isAsmParserOnly = 1;
let WaveSizePredicate = isWave32;
}
def _e32_dpp8_w64#Gen.Suffix
: VOPC_DPP8<op{7-0}, ps32, asm_name> {
let AsmString = asm_name # " vcc, " # AsmDPP8;
let isAsmParserOnly = 1;
let WaveSizePredicate = isWave64;
}
}
}

if ps64.Pfl.HasExtVOP3DPP then {
defvar psDPP = !cast<VOP_DPP_Pseudo>(OpName #"_e64" #"_dpp");
def _e64_dpp#Gen.Suffix : VOPC64_DPP16_Dst<{0, op}, psDPP, asm_name>,
SIMCInstr<psDPP.PseudoInstr, Gen.Subtarget>;
def _e64_dpp8#Gen.Suffix : VOPC64_DPP8_Dst<{0, op}, ps64, asm_name>;
}
} // End AssemblerPredicate = Gen.AssemblerPredicate, DecoderNamespace = Gen.DecoderNamespace
if ps64.Pfl.HasExtVOP3DPP then {
defvar psDPP = !cast<VOP_DPP_Pseudo>(OpName #"_e64" #"_dpp");
def _e64_dpp#Gen.Suffix : VOPC64_DPP16_Dst<{0, op}, psDPP, asm_name>,
SIMCInstr<psDPP.PseudoInstr, Gen.Subtarget>;
def _e64_dpp8#Gen.Suffix : VOPC64_DPP8_Dst<{0, op}, ps64, asm_name>;
} // end if ps64.Pfl.HasExtVOP3DPP
} // End DecoderNamespace
} // End AssemblerPredicate
}

multiclass VOPC_Real_t16<GFXGen Gen, bits<9> op, string asm_name,
Expand Down Expand Up @@ -1514,51 +1520,57 @@ multiclass VOPCX_Real<GFXGen Gen, bits<9> op> {

multiclass VOPCX_Real_with_name<GFXGen Gen, bits<9> op, string OpName,
string asm_name, string pseudo_mnemonic = ""> {
let AssemblerPredicate = Gen.AssemblerPredicate, DecoderNamespace = Gen.DecoderNamespace in {
defvar ps32 = !cast<VOPC_Pseudo>(OpName#"_nosdst_e32");
defvar ps64 = !cast<VOP3_Pseudo>(OpName#"_nosdst_e64");
def _e32#Gen.Suffix
: VOPC_Real<ps32, Gen.Subtarget, asm_name>,
MnemonicAlias<!if(!empty(pseudo_mnemonic), !subst("_nosdst", "", ps32.Mnemonic),
pseudo_mnemonic),
defvar ps32 = !cast<VOPC_Pseudo>(OpName#"_nosdst_e32");
defvar ps64 = !cast<VOP3_Pseudo>(OpName#"_nosdst_e64");
let AssemblerPredicate = Gen.AssemblerPredicate in {
// MnemonicAlias and GCNPredicateControl both define the field Predicates,
// so GCNPredicateControl must come after MnemonicAlias because it contains
// the predicates we actually want.
def : MnemonicAlias<!if(!empty(pseudo_mnemonic), !subst("_nosdst", "", ps32.Mnemonic),
pseudo_mnemonic),
asm_name, ps32.AsmVariantName>,
Requires<[Gen.AssemblerPredicate]>,
VOPCe<op{7-0}> {
let AsmString = asm_name # "{_e32} " # ps32.AsmOperands;
}
def _e64#Gen.Suffix
: VOP3_Real<ps64, Gen.Subtarget, asm_name>,
MnemonicAlias<!if(!empty(pseudo_mnemonic), !subst("_nosdst", "", ps64.Mnemonic),
pseudo_mnemonic),
GCNPredicateControl;
def : MnemonicAlias<!if(!empty(pseudo_mnemonic), !subst("_nosdst", "", ps64.Mnemonic),
pseudo_mnemonic),
asm_name, ps64.AsmVariantName>,
Requires<[Gen.AssemblerPredicate]>,
VOP3a_gfx11_gfx12<{0, op}, ps64.Pfl> {
let Inst{7-0} = ? ; // sdst
let AsmString = asm_name # "{_e64} " # ps64.AsmOperands;
}

defm : VOPCXInstAliases<OpName, !substr(Gen.Suffix, 1), NAME, asm_name>;
GCNPredicateControl;

if ps32.Pfl.HasExtDPP then {
defvar psDPP = !cast<VOP_DPP_Pseudo>(OpName#"_nosdst_e32"#"_dpp");
def _e32_dpp#Gen.Suffix : VOPC_DPP16_SIMC<op{7-0}, psDPP,
Gen.Subtarget, asm_name>;
def _e32_dpp8#Gen.Suffix : VOPC_DPP8<op{7-0}, ps32, asm_name>;
}
if ps64.Pfl.HasExtVOP3DPP then {
defvar psDPP = !cast<VOP_DPP_Pseudo>(OpName#"_nosdst_e64"#"_dpp");
defvar AsmDPP = ps64.Pfl.AsmVOP3DPP16;
def _e64_dpp#Gen.Suffix
: VOPC64_DPP16_NoDst<{0, op}, psDPP, asm_name>,
SIMCInstr<psDPP.PseudoInstr, Gen.Subtarget> {
let AsmString = asm_name # "{_e64_dpp} " # AsmDPP;
let DecoderNamespace = Gen.DecoderNamespace in {
def _e32#Gen.Suffix
: VOPC_Real<ps32, Gen.Subtarget, asm_name>,
VOPCe<op{7-0}> {
let AsmString = asm_name # "{_e32} " # ps32.AsmOperands;
}
defvar AsmDPP8 = ps64.Pfl.AsmVOP3DPP8;
def _e64_dpp8#Gen.Suffix : VOPC64_DPP8_NoDst<{0, op}, ps64, asm_name> {
let AsmString = asm_name # "{_e64_dpp} " # AsmDPP8;
def _e64#Gen.Suffix
: VOP3_Real_Gen<ps64, Gen, asm_name>,
VOP3a_gfx11_gfx12<{0, op}, ps64.Pfl> {
let Inst{7-0} = ? ; // sdst
let AsmString = asm_name # "{_e64} " # ps64.AsmOperands;
}
}
} // End AssemblerPredicate = Gen.AssemblerPredicate, DecoderNamespace = Gen.DecoderNamespace

defm : VOPCXInstAliases<OpName, !substr(Gen.Suffix, 1), NAME, asm_name>;

if ps32.Pfl.HasExtDPP then {
defvar psDPP = !cast<VOP_DPP_Pseudo>(OpName#"_nosdst_e32"#"_dpp");
def _e32_dpp#Gen.Suffix : VOPC_DPP16_SIMC<op{7-0}, psDPP,
Gen.Subtarget, asm_name>;
def _e32_dpp8#Gen.Suffix : VOPC_DPP8<op{7-0}, ps32, asm_name>;
}
if ps64.Pfl.HasExtVOP3DPP then {
defvar psDPP = !cast<VOP_DPP_Pseudo>(OpName#"_nosdst_e64"#"_dpp");
defvar AsmDPP = ps64.Pfl.AsmVOP3DPP16;
def _e64_dpp#Gen.Suffix
: VOPC64_DPP16_NoDst<{0, op}, psDPP, asm_name>,
SIMCInstr<psDPP.PseudoInstr, Gen.Subtarget> {
let AsmString = asm_name # "{_e64_dpp} " # AsmDPP;
}
defvar AsmDPP8 = ps64.Pfl.AsmVOP3DPP8;
def _e64_dpp8#Gen.Suffix : VOPC64_DPP8_NoDst<{0, op}, ps64, asm_name> {
let AsmString = asm_name # "{_e64_dpp} " # AsmDPP8;
}
} // End if ps64.Pfl.HasExtVOP3DPP
} // End DecoderNamespace
} // End AssemblerPredicate
}

multiclass VOPCX_Real_t16<GFXGen Gen, bits<9> op, string asm_name,
Expand Down