Skip to content

[llvm][AArch64][Assembly]: Add FP8 instructions assembly and disassembly. #69632

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
Oct 26, 2023
Merged
Show file tree
Hide file tree
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
2 changes: 2 additions & 0 deletions llvm/include/llvm/TargetParser/AArch64TargetParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ enum ArchExtKind : unsigned {
AEK_ITE = 56, // FEAT_ITE
AEK_GCS = 57, // FEAT_GCS
AEK_FPMR = 58, // FEAT_FPMR
AEK_FP8 = 59, // FEAT_FP8
AEK_NUM_EXTENSIONS
};
using ExtensionBitset = Bitset<AEK_NUM_EXTENSIONS>;
Expand Down Expand Up @@ -269,6 +270,7 @@ inline constexpr ExtensionInfo Extensions[] = {
{"wfxt", AArch64::AEK_NONE, {}, {}, FEAT_WFXT, "+wfxt", 550},
{"gcs", AArch64::AEK_GCS, "+gcs", "-gcs", FEAT_INIT, "", 0},
{"fpmr", AArch64::AEK_FPMR, "+fpmr", "-fpmr", FEAT_INIT, "", 0},
{"fp8", AArch64::AEK_FP8, "+fp8", "-fp8", FEAT_INIT, "+fpmr", 0},
// Special cases
{"none", AArch64::AEK_NONE, {}, {}, FEAT_INIT, "", ExtensionInfo::MaxFMVPriority},
};
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Target/AArch64/AArch64.td
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,9 @@ def FeatureSVE : SubtargetFeature<"sve", "HasSVE", "true",
def FeatureFPMR : SubtargetFeature<"fpmr", "HasFPMR", "true",
"Enable FPMR Register (FEAT_FPMR)">;

def FeatureFP8 : SubtargetFeature<"fp8", "HasFP8", "true",
"Enable FP8 instructions (FEAT_FP8)">;

// This flag is currently still labeled as Experimental, but when fully
// implemented this should tell the compiler to use the zeroing pseudos to
// benefit from the reverse instructions (e.g. SUB vs SUBR) if the inactive
Expand Down
53 changes: 53 additions & 0 deletions llvm/lib/Target/AArch64/AArch64InstrFormats.td
Original file line number Diff line number Diff line change
Expand Up @@ -6056,6 +6056,49 @@ multiclass SIMDThreeSameVectorFML<bit U, bit b13, bits<3> size, string asm,
}


// FP8 assembly/disassembly classes

//----------------------------------------------------------------------------
// FP8 Advanced SIMD three-register extension
//----------------------------------------------------------------------------
class BaseSIMDThreeVectors<bit Q, bit U, bits<2> size, bits<4> op,
RegisterOperand regtype1,
RegisterOperand regtype2, string asm,
string kind1, string kind2>
: I<(outs regtype1:$Rd), (ins regtype2:$Rn, regtype2:$Rm), asm,
"\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2, "", []>, Sched<[]> {
bits<5> Rd;
bits<5> Rn;
bits<5> Rm;
let Inst{31} = 0;
let Inst{30} = Q;
let Inst{29} = U;
let Inst{28-24} = 0b01110;
let Inst{23-22} = size;
let Inst{21} = 0b0;
let Inst{20-16} = Rm;
let Inst{15} = 0b1;
let Inst{14-11} = op;
let Inst{10} = 0b1;
let Inst{9-5} = Rn;
let Inst{4-0} = Rd;
}


// FCVTN (FP16 to FP8)
multiclass SIMDThreeSameSizeVectorCvt<string asm> {
def v8f8 : BaseSIMDThreeVectors<0b0, 0b0, 0b01, 0b1110, V64, V64, asm, ".8b",".4h">;
def v16f8 : BaseSIMDThreeVectors<0b1, 0b0, 0b01, 0b1110, V128, V128, asm, ".16b", ".8h">;
}

// TODO : Create v16f8 value type
// FCVTN, FCVTN2 (FP32 to FP8)
multiclass SIMDThreeVectorCvt<string asm> {
def v8f8 : BaseSIMDThreeVectors<0b0, 0b0, 0b00, 0b1110, V64, V128, asm, ".8b", ".4s">;
def 2v16f8 : BaseSIMDThreeSameVectorDot<0b1, 0b0, 0b00, 0b1110, asm#2, ".16b", ".4s",
V128, v16i8, v4f32, null_frag>;
}

//----------------------------------------------------------------------------
// AdvSIMD two register vector instructions.
//----------------------------------------------------------------------------
Expand Down Expand Up @@ -6479,6 +6522,16 @@ multiclass SIMDMixedTwoVector<bit U, bits<5> opc, string asm,
(INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
}

//----------------------------------------------------------------------------
// FP8 Advanced SIMD two-register miscellaneous
//----------------------------------------------------------------------------
multiclass SIMDMixedTwoVectorFP8<bits<2>sz, string asm> {
def v8f16 : BaseSIMDMixedTwoVector<0b0, 0b1, sz, 0b10111, V64, V128,
asm, ".8h", ".8b", []>;
def 2v8f16 : BaseSIMDMixedTwoVector<0b1, 0b1, sz, 0b10111, V128, V128,
asm#2, ".8h", ".16b", []>;
}

class BaseSIMDCmpTwoVector<bit Q, bit U, bits<2> size, bits<2> size2,
bits<5> opcode, RegisterOperand regtype, string asm,
string kind, string zero, ValueType dty,
Expand Down
15 changes: 15 additions & 0 deletions llvm/lib/Target/AArch64/AArch64InstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,8 @@ def HasSME2p1 : Predicate<"Subtarget->hasSME2p1()">,
AssemblerPredicateWithAll<(all_of FeatureSME2p1), "sme2p1">;
def HasFPMR : Predicate<"Subtarget->hasFPMR()">,
AssemblerPredicateWithAll<(all_of FeatureFPMR), "fpmr">;
def HasFP8 : Predicate<"Subtarget->hasFP8()">,
AssemblerPredicateWithAll<(all_of FeatureFP8), "fp8">;

// A subset of SVE(2) instructions are legal in Streaming SVE execution mode,
// they should be enabled if either has been specified.
Expand All @@ -173,6 +175,10 @@ def HasSVE2orSME
: Predicate<"Subtarget->hasSVE2() || Subtarget->hasSME()">,
AssemblerPredicateWithAll<(any_of FeatureSVE2, FeatureSME),
"sve2 or sme">;
def HasSVE2orSME2
: Predicate<"Subtarget->hasSVE2() || Subtarget->hasSME2()">,
AssemblerPredicateWithAll<(any_of FeatureSVE2, FeatureSME2),
"sve2 or sme2">;
def HasSVE2p1_or_HasSME
: Predicate<"Subtarget->hasSVE2p1() || Subtarget->hasSME()">,
AssemblerPredicateWithAll<(any_of FeatureSME, FeatureSVE2p1), "sme or sve2p1">;
Expand Down Expand Up @@ -9249,6 +9255,15 @@ let Predicates = [HasD128] in {
}
}

let Predicates = [HasFP8] in {
defm F1CVTL : SIMDMixedTwoVectorFP8<0b00, "f1cvtl">;
defm F2CVTL : SIMDMixedTwoVectorFP8<0b01, "f2cvtl">;
defm BF1CVTL : SIMDMixedTwoVectorFP8<0b10, "bf1cvtl">;
defm BF2CVTL : SIMDMixedTwoVectorFP8<0b11, "bf2cvtl">;
defm FCVTN_F16_F8 : SIMDThreeSameSizeVectorCvt<"fcvtn">;
defm FCVTN_F32_F8 : SIMDThreeVectorCvt<"fcvtn">;
defm FSCALE : SIMDThreeSameVectorFP<0b1, 0b1, 0b111, "fscale", null_frag>;
} // End let Predicates = [HasFP8]

include "AArch64InstrAtomics.td"
include "AArch64SVEInstrInfo.td"
Expand Down
39 changes: 31 additions & 8 deletions llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -330,14 +330,14 @@ defm UMLSL_VG4_M4ZZ : sme2_int_mla_long_array_vg4_single<"umlsl", 0b11, int_aar
defm UMLSL_VG2_M2Z2Z : sme2_int_mla_long_array_vg2_multi<"umlsl", 0b11, int_aarch64_sme_umlsl_vg2x2>;
defm UMLSL_VG4_M4Z4Z : sme2_int_mla_long_array_vg4_multi<"umlsl", 0b11, int_aarch64_sme_umlsl_vg2x4>;

defm FCVT_Z2Z_StoH : sme2_cvt_vg2_single<"fcvt", 0b0000, nxv8f16, nxv4f32, int_aarch64_sve_fcvt_x2>;
defm FCVTN_Z2Z_StoH : sme2_cvt_vg2_single<"fcvtn", 0b0001, nxv8f16, nxv4f32, int_aarch64_sve_fcvtn_x2>;
defm BFCVT_Z2Z_StoH : sme2_cvt_vg2_single<"bfcvt", 0b1000, nxv8bf16, nxv4f32, int_aarch64_sve_bfcvt_x2>;
defm BFCVTN_Z2Z_StoH : sme2_cvt_vg2_single<"bfcvtn", 0b1001, nxv8bf16, nxv4f32, int_aarch64_sve_bfcvtn_x2>;

defm SQCVT_Z2Z_StoH : sme2_cvt_vg2_single<"sqcvt", 0b0110, nxv8i16, nxv4i32, int_aarch64_sve_sqcvt_x2>;
defm UQCVT_Z2Z_StoH : sme2_cvt_vg2_single<"uqcvt", 0b0111, nxv8i16, nxv4i32, int_aarch64_sve_uqcvt_x2>;
defm SQCVTU_Z2Z_StoH : sme2_cvt_vg2_single<"sqcvtu", 0b1110, nxv8i16, nxv4i32, int_aarch64_sve_sqcvtu_x2>;
defm FCVT_Z2Z_StoH : sme2_cvt_vg2_single<"fcvt", 0b00000, nxv8f16, nxv4f32, int_aarch64_sve_fcvt_x2>;
defm FCVTN_Z2Z_StoH : sme2_cvt_vg2_single<"fcvtn", 0b00001, nxv8f16, nxv4f32, int_aarch64_sve_fcvtn_x2>;
defm BFCVT_Z2Z_StoH : sme2_cvt_vg2_single<"bfcvt", 0b10000, nxv8bf16, nxv4f32, int_aarch64_sve_bfcvt_x2>;
defm BFCVTN_Z2Z_StoH : sme2_cvt_vg2_single<"bfcvtn", 0b10001, nxv8bf16, nxv4f32, int_aarch64_sve_bfcvtn_x2>;

defm SQCVT_Z2Z_StoH : sme2_cvt_vg2_single<"sqcvt", 0b00110, nxv8i16, nxv4i32, int_aarch64_sve_sqcvt_x2>;
defm UQCVT_Z2Z_StoH : sme2_cvt_vg2_single<"uqcvt", 0b00111, nxv8i16, nxv4i32, int_aarch64_sve_uqcvt_x2>;
defm SQCVTU_Z2Z_StoH : sme2_cvt_vg2_single<"sqcvtu", 0b10110, nxv8i16, nxv4i32, int_aarch64_sve_sqcvtu_x2>;
defm SQCVT_Z4Z : sme2_int_cvt_vg4_single<"sqcvt", 0b000, int_aarch64_sve_sqcvt_x4>;
defm UQCVT_Z4Z : sme2_int_cvt_vg4_single<"uqcvt", 0b001, int_aarch64_sve_uqcvt_x4>;
defm SQCVTU_Z4Z : sme2_int_cvt_vg4_single<"sqcvtu", 0b100, int_aarch64_sve_sqcvtu_x4>;
Expand Down Expand Up @@ -855,3 +855,26 @@ defm BFCLAMP_VG4_4ZZZ: sme2p1_bfclamp_vector_vg4_multi<"bfclamp">;
defm BFMOPA_MPPZZ_H : sme2p1_fmop_tile_fp16<"bfmopa", 0b1, 0b0, 0b11, ZPR16>;
defm BFMOPS_MPPZZ_H : sme2p1_fmop_tile_fp16<"bfmops", 0b1, 0b1, 0b11, ZPR16>;
}

let Predicates = [HasSME2, HasFP8] in {
defm F1CVT_2ZZ_BtoH : sme2p1_fp8_cvt_vector_vg2_single<"f1cvt", 0b00, 0b0>;
defm F1CVTL_2ZZ_BtoH : sme2p1_fp8_cvt_vector_vg2_single<"f1cvtl", 0b00, 0b1>;
defm BF1CVT_2ZZ_BtoH : sme2p1_fp8_cvt_vector_vg2_single<"bf1cvt", 0b01, 0b0>;
defm BF1CVTL_2ZZ_BtoH : sme2p1_fp8_cvt_vector_vg2_single<"bf1cvtl", 0b01, 0b1>;
defm F2CVT_2ZZ_BtoH : sme2p1_fp8_cvt_vector_vg2_single<"f2cvt", 0b10, 0b0>;
defm F2CVTL_2ZZ_BtoH : sme2p1_fp8_cvt_vector_vg2_single<"f2cvtl", 0b10, 0b1>;
defm BF2CVT_2ZZ_BtoH : sme2p1_fp8_cvt_vector_vg2_single<"bf2cvt", 0b11, 0b0>;
defm BF2CVTL_2ZZ_BtoH : sme2p1_fp8_cvt_vector_vg2_single<"bf2cvtl", 0b11, 0b1>;

defm FCVT_Z2Z_HtoB : sme2_fp8_cvt_vg2_single<"fcvt", 0b0>;
defm BFCVT_Z2Z_HtoB : sme2_fp8_cvt_vg2_single<"bfcvt", 0b1>;
defm FCVT_Z4Z_StoB : sme2_fp8_cvt_vg4_single<"fcvt", 0b0>;
defm FCVTN_Z4Z_StoB : sme2_fp8_cvt_vg4_single<"fcvtn", 0b1>;

defm FSCALE_2ZZ : sme2_fp_sve_destructive_vector_vg2_single<"fscale", 0b0011000>;
defm FSCALE_4ZZ : sme2_fp_sve_destructive_vector_vg4_single<"fscale", 0b0011000>;
defm FSCALE_2Z2Z : sme2_fp_sve_destructive_vector_vg2_multi<"fscale", 0b0011000>;
defm FSCALE_4Z4Z : sme2_fp_sve_destructive_vector_vg4_multi<"fscale", 0b0011000>;

} // [HasSME2, HasFP8]

21 changes: 21 additions & 0 deletions llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -4002,3 +4002,24 @@ defm UZPQ1_ZZZ : sve2p1_permute_vec_elems_q<0b010, "uzpq1">;
defm UZPQ2_ZZZ : sve2p1_permute_vec_elems_q<0b011, "uzpq2">;
defm TBLQ_ZZZ : sve2p1_tblq<"tblq">;
} // End HasSVE2p1_or_HasSME2p1

//===----------------------------------------------------------------------===//
// SVE2 FP8 instructions
//===----------------------------------------------------------------------===//
let Predicates = [HasSVE2orSME2, HasFP8] in {
// FP8 upconvert
defm F1CVT_ZZ : sve2_fp8_cvt_single<0b0, 0b00, "f1cvt">;
defm F2CVT_ZZ : sve2_fp8_cvt_single<0b0, 0b01, "f2cvt">;
defm BF1CVT_ZZ : sve2_fp8_cvt_single<0b0, 0b10, "bf1cvt">;
defm BF2CVT_ZZ : sve2_fp8_cvt_single<0b0, 0b11, "bf2cvt">;
defm F1CVTLT_ZZ : sve2_fp8_cvt_single<0b1, 0b00, "f1cvtlt">;
defm F2CVTLT_ZZ : sve2_fp8_cvt_single<0b1, 0b01, "f2cvtlt">;
defm BF1CVTLT_ZZ : sve2_fp8_cvt_single<0b1, 0b10, "bf1cvtlt">;
defm BF2CVTLT_ZZ : sve2_fp8_cvt_single<0b1, 0b11, "bf2cvtlt">;

// FP8 downconvert
defm FCVTN_Z2Z_HtoB : sve2_fp8_down_cvt_single<0b00, "fcvtn", ZZ_h_mul_r>;
defm FCVTNB_Z2Z_StoB : sve2_fp8_down_cvt_single<0b01, "fcvtnb", ZZ_s_mul_r>;
defm BFCVTN_Z2Z_HtoB : sve2_fp8_down_cvt_single<0b10, "bfcvtn", ZZ_h_mul_r>;
defm FCVTNT_Z2Z_StoB : sve2_fp8_down_cvt_single<0b11, "fcvtnt", ZZ_s_mul_r>;
} // End HasSVE2orSME2, HasFP8
1 change: 1 addition & 0 deletions llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3639,6 +3639,7 @@ static const struct Extension {
{"ssbs", {AArch64::FeatureSSBS}},
{"tme", {AArch64::FeatureTME}},
{"fpmr", {AArch64::FeatureFPMR}},
{"fp8", {AArch64::FeatureFP8}},
};

static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
Expand Down
41 changes: 30 additions & 11 deletions llvm/lib/Target/AArch64/SMEInstrFormats.td
Original file line number Diff line number Diff line change
Expand Up @@ -2161,15 +2161,16 @@ multiclass sme2_frint_vector_vg4_multi<string mnemonic, bits<7> op> {
mnemonic>;
}

class sme2_cvt_vg2_single<string mnemonic, bits<4> op>
: I<(outs ZPR16:$Zd), (ins ZZ_s_mul_r:$Zn),
class sme2_cvt_vg2_single<string mnemonic, bits<5> op,
RegisterOperand first_ty, RegisterOperand second_ty>
: I<(outs first_ty:$Zd), (ins second_ty:$Zn),
mnemonic, "\t$Zd, $Zn", "", []>, Sched<[]> {
bits<4> Zn;
bits<5> Zd;
let Inst{31-23} = 0b110000010;
let Inst{22} = op{3};
let Inst{21-18} = 0b1000;
let Inst{17-16} = op{2-1};
let Inst{22} = op{4};
let Inst{21-19} = 0b100;
let Inst{18-16} = op{3-1};
let Inst{15-10} = 0b111000;
let Inst{9-6} = Zn;
let Inst{5} = op{0};
Expand All @@ -2178,12 +2179,17 @@ class sme2_cvt_vg2_single<string mnemonic, bits<4> op>

// SME2 multi-vec FP down convert two registers
// SME2 multi-vec int down convert two registers
multiclass sme2_cvt_vg2_single<string mnemonic, bits<4> op, ValueType out_vt,
multiclass sme2_cvt_vg2_single<string mnemonic, bits<5> op, ValueType out_vt,
ValueType in_vt, SDPatternOperator intrinsic> {
def NAME : sme2_cvt_vg2_single<mnemonic, op>;
def NAME : sme2_cvt_vg2_single<mnemonic, op, ZPR16, ZZ_s_mul_r>;
def : SVE2p1_Cvt_VG2_Pat<NAME, intrinsic, out_vt, in_vt>;
}

// SME2 multi-vec FP8 down convert two registers
multiclass sme2_fp8_cvt_vg2_single<string mnemonic, bit op> {
def NAME : sme2_cvt_vg2_single<mnemonic, {op, 0b1000}, ZPR8, ZZ_h_mul_r>;
}

class sme2_cvt_unpk_vector_vg2<bits<2>sz, bits<3> op, bit u, RegisterOperand first_ty,
RegisterOperand second_ty, string mnemonic>
: I<(outs first_ty:$Zd), (ins second_ty:$Zn),
Expand Down Expand Up @@ -2212,7 +2218,13 @@ multiclass sme2p1_fp_cvt_vector_vg2_single<string mnemonic, bit l> {
def _S : sme2_cvt_unpk_vector_vg2<0b10, 0b000, l, ZZ_s_mul_r, ZPR16, mnemonic>;
}

class sme2_cvt_vg4_single<bit sz, bits<3> op, RegisterOperand first_ty,
// SME2 multi-vec FP8 up convert two registers
multiclass sme2p1_fp8_cvt_vector_vg2_single<string mnemonic, bits<2> opc, bit L> {
def _NAME : sme2_cvt_unpk_vector_vg2<opc, 0b110, L, ZZ_h_mul_r, ZPR8, mnemonic>;
}


class sme2_cvt_vg4_single<bit sz, bits<3> op, bits<4>op2, RegisterOperand first_ty,
RegisterOperand second_ty, string mnemonic>
: I<(outs first_ty:$Zd), (ins second_ty:$Zn),
mnemonic, "\t$Zd, $Zn", "", []>, Sched<[]> {
Expand All @@ -2221,21 +2233,28 @@ class sme2_cvt_vg4_single<bit sz, bits<3> op, RegisterOperand first_ty,
let Inst{31-24} = 0b11000001;
let Inst{23} = sz;
let Inst{22} = op{2};
let Inst{21-10} = 0b110011111000;
let Inst{21-20} = 0b11;
let Inst{19-16} = op2;
let Inst{15-10} = 0b111000;
let Inst{9-7} = Zn;
let Inst{6-5} = op{1-0};
let Inst{4-0} = Zd;
}

// SME2 multi-vec int down convert four registers
multiclass sme2_int_cvt_vg4_single<string mnemonic, bits<3> op, SDPatternOperator intrinsic> {
def _StoB : sme2_cvt_vg4_single<0, op, ZPR8, ZZZZ_s_mul_r, mnemonic>;
def _DtoH : sme2_cvt_vg4_single<1, op, ZPR16, ZZZZ_d_mul_r, mnemonic>;
def _StoB : sme2_cvt_vg4_single<0, op, 0b0011, ZPR8, ZZZZ_s_mul_r, mnemonic>;
def _DtoH : sme2_cvt_vg4_single<1, op, 0b0011, ZPR16, ZZZZ_d_mul_r, mnemonic>;

def : SME2_Cvt_VG4_Pat<NAME # _StoB, intrinsic, nxv16i8, nxv4i32>;
def : SME2_Cvt_VG4_Pat<NAME # _DtoH, intrinsic, nxv8i16, nxv2i64>;
}

//SME2 multi-vec FP8 down convert four registers
multiclass sme2_fp8_cvt_vg4_single<string mnemonic, bit N> {
def _NAME : sme2_cvt_vg4_single<0b0, {0b00, N}, 0b0100, ZPR8, ZZZZ_s_mul_r, mnemonic>;
}

class sme2_unpk_vector_vg4<bits<2>sz, bit u, RegisterOperand first_ty,
RegisterOperand second_ty, string mnemonic>
: I<(outs first_ty:$Zd), (ins second_ty:$Zn),
Expand Down
43 changes: 43 additions & 0 deletions llvm/lib/Target/AArch64/SVEInstrFormats.td
Original file line number Diff line number Diff line change
Expand Up @@ -10078,3 +10078,46 @@ multiclass sve2p1_tblq<string mnemonic> {
def _S : sve2p1_permute_vec_elems_q<0b10, 0b110, mnemonic, ZPR32, Z_s>;
def _D : sve2p1_permute_vec_elems_q<0b11, 0b110, mnemonic, ZPR64, Z_d>;
}

//===----------------------------------------------------------------------===//
// SVE2 FP8 Instructions
//===----------------------------------------------------------------------===//

// FP8 upconvert
class sve2_fp8_cvt_single<bit L, bits<2> opc, string mnemonic,
ZPRRegOp dst_ty, ZPRRegOp src_ty>
: I<(outs dst_ty:$Zd), (ins src_ty:$Zn),
mnemonic, "\t$Zd, $Zn",
"", []>, Sched<[]>{
bits<5> Zd;
bits<5> Zn;
let Inst{31-17} = 0b011001010000100;
let Inst{16} = L;
let Inst{15-12} = 0b0011;
let Inst{11-10} = opc;
let Inst{9-5} = Zn;
let Inst{4-0} = Zd;
}

multiclass sve2_fp8_cvt_single<bit L, bits<2> opc, string mnemonic> {
def _BtoH : sve2_fp8_cvt_single<L, opc, mnemonic, ZPR16, ZPR8>;
}

// FP8 downconvert
class sve2_fp8_down_cvt_single<bits<2> opc, string mnemonic,
ZPRRegOp dst_ty, RegisterOperand src_ty>
: I<(outs dst_ty:$Zd), (ins src_ty:$Zn),
mnemonic, "\t$Zd, $Zn",
"", []>, Sched<[]>{
bits<5> Zd;
bits<4> Zn;
let Inst{31-12} = 0b01100101000010100011;
let Inst{11-10} = opc;
let Inst{9-6} = Zn;
let Inst{5} = 0b0;
let Inst{4-0} = Zd;
}

multiclass sve2_fp8_down_cvt_single<bits<2> opc, string mnemonic, RegisterOperand src> {
def NAME : sve2_fp8_down_cvt_single<opc, mnemonic, ZPR8, src>;
}
7 changes: 7 additions & 0 deletions llvm/test/MC/AArch64/FP8/directive-arch-negative.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// RUN: not llvm-mc -triple aarch64 -filetype asm -o - %s 2>&1 | FileCheck %s

.arch armv9-a+fp8
.arch armv9-a+nofp8
bf1cvtl v0.8h, v0.8b
// CHECK: error: instruction requires: fp8
// CHECK: bf1cvtl v0.8h, v0.8b
7 changes: 7 additions & 0 deletions llvm/test/MC/AArch64/FP8/directive-arch.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// RUN: llvm-mc -triple aarch64 -o - %s 2>&1 | FileCheck %s

.arch armv9-a+fp8
bf1cvtl v0.8h, v0.8b
// CHECK: bf1cvtl v0.8h, v0.8b

.arch armv9-a+nofp8
Loading