[llvm] [llvm][AArch64][Assembly]: Add FP8FMA assembly and disassembly. (PR #70134)

via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 24 15:38:22 PDT 2023


https://github.com/hassnaaHamdi updated https://github.com/llvm/llvm-project/pull/70134

>From ac5830e259f0cc35b0c9101427424a1c7f50c6ce Mon Sep 17 00:00:00 2001
From: Hassnaa Hamdi <hassnaa.hamdi at arm.com>
Date: Tue, 24 Oct 2023 21:42:22 +0000
Subject: [PATCH] [llvm][AArch64][Assembly]: Add FP8FMA  assembly and
 disassembly.

This patch adds the feature flag FP8FMA and the assembly/disassembly
for the following instructions of NEON and SVE2:
  * NEON:
    - FMLALBlane
    - FMLALTlane
    - FMLALLBBlane
    - FMLALLBTlane
    - FMLALLTBlane
    - FMLALLTTlane
    - FMLALB
    - FMLALT
    - FMLALLB
    - FMLALLBT
    - FMLALLTB
    - FMLALLTT
  * SVE2:
    - FMLALB_ZZZI
    - FMLALT_ZZZI
    - FMLALB_ZZZ
    - FMLALT_ZZZ
    - FMLALLBB_ZZZI
    - FMLALLBT_ZZZI
    - FMLALLTB_ZZZI
    - FMLALLTT_ZZZI
    - FMLALLBB_ZZZ
    - FMLALLBT_ZZZ
    - FMLALLTB_ZZZ
    - FMLALLTT_ZZZ

That is according to this documentation:
https://developer.arm.com/documentation/ddi0602/2023-09

Change-Id: Ie7527ecd3be9de04a1176f41761986bb2e679fab
---
 .../llvm/TargetParser/AArch64TargetParser.h   |   4 +
 llvm/lib/Target/AArch64/AArch64.td            |  10 +-
 .../lib/Target/AArch64/AArch64InstrFormats.td |  34 +++
 llvm/lib/Target/AArch64/AArch64InstrInfo.td   |  22 ++
 .../Target/AArch64/AArch64RegisterInfo.cpp    |   2 +
 .../lib/Target/AArch64/AArch64RegisterInfo.td |  16 ++
 .../lib/Target/AArch64/AArch64SVEInstrInfo.td |  20 ++
 llvm/lib/Target/AArch64/AArch64SchedA64FX.td  |   2 +-
 .../AArch64/AsmParser/AArch64AsmParser.cpp    |  63 +++--
 .../Disassembler/AArch64Disassembler.cpp      |  11 +
 .../AArch64/GISel/AArch64RegisterBankInfo.cpp |   3 +-
 llvm/lib/Target/AArch64/SVEInstrFormats.td    |  90 +++++++
 .../MC/AArch64/FP8/directive-arch-negative.s  |  13 +
 llvm/test/MC/AArch64/FP8/directive-arch.s     |  13 +
 llvm/test/MC/AArch64/FP8/mla-diagnostic.s     |  85 +++++++
 llvm/test/MC/AArch64/FP8/mla.s                |  98 ++++++++
 .../MC/AArch64/FP8_SVE2/fmlal-diagnostics.s   |  64 +++++
 llvm/test/MC/AArch64/FP8_SVE2/fmlal.s         | 114 +++++++++
 .../MC/AArch64/FP8_SVE2/fmlall-diagnostics.s  |  85 +++++++
 llvm/test/MC/AArch64/FP8_SVE2/fmlall.s        | 222 ++++++++++++++++++
 .../TargetParser/TargetParserTest.cpp         |  44 ++--
 21 files changed, 966 insertions(+), 49 deletions(-)
 create mode 100644 llvm/test/MC/AArch64/FP8/directive-arch-negative.s
 create mode 100644 llvm/test/MC/AArch64/FP8/directive-arch.s
 create mode 100644 llvm/test/MC/AArch64/FP8/mla-diagnostic.s
 create mode 100644 llvm/test/MC/AArch64/FP8/mla.s
 create mode 100644 llvm/test/MC/AArch64/FP8_SVE2/fmlal-diagnostics.s
 create mode 100644 llvm/test/MC/AArch64/FP8_SVE2/fmlal.s
 create mode 100644 llvm/test/MC/AArch64/FP8_SVE2/fmlall-diagnostics.s
 create mode 100644 llvm/test/MC/AArch64/FP8_SVE2/fmlall.s

diff --git a/llvm/include/llvm/TargetParser/AArch64TargetParser.h b/llvm/include/llvm/TargetParser/AArch64TargetParser.h
index bf14473f133fab7..9a3185d3ed38e56 100644
--- a/llvm/include/llvm/TargetParser/AArch64TargetParser.h
+++ b/llvm/include/llvm/TargetParser/AArch64TargetParser.h
@@ -160,6 +160,8 @@ enum ArchExtKind : unsigned {
   AEK_ITE =           56, // FEAT_ITE
   AEK_GCS =           57, // FEAT_GCS
   AEK_FPMR =          58, // FEAT_FPMR
+  AEK_FP8FMA =        59, // FEAT_FP8FMA
+  AEK_SSVE_FP8FMA =   60, // FEAT_SSVE_FP8FMA
   AEK_NUM_EXTENSIONS
 };
 using ExtensionBitset = Bitset<AEK_NUM_EXTENSIONS>;
@@ -269,6 +271,8 @@ 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},
+    {"fp8fma", AArch64::AEK_FP8FMA, "+fp8fma", "-fp8fma", FEAT_INIT, "+fpmr", 0},
+    {"ssve-fp8fma", AArch64::AEK_SSVE_FP8FMA, "+ssve-fp8fma", "-ssve-fp8fma", FEAT_INIT, "+sme2", 0},
     // Special cases
     {"none", AArch64::AEK_NONE, {}, {}, FEAT_INIT, "", ExtensionInfo::MaxFMVPriority},
 };
diff --git a/llvm/lib/Target/AArch64/AArch64.td b/llvm/lib/Target/AArch64/AArch64.td
index ced1d4389203653..64f619de4fe9b1a 100644
--- a/llvm/lib/Target/AArch64/AArch64.td
+++ b/llvm/lib/Target/AArch64/AArch64.td
@@ -511,6 +511,12 @@ def FeatureSME2 : SubtargetFeature<"sme2", "HasSME2", "true",
 def FeatureSME2p1 : SubtargetFeature<"sme2p1", "HasSME2p1", "true",
   "Enable Scalable Matrix Extension 2.1 (FEAT_SME2p1) instructions", [FeatureSME2]>;
 
+def FeatureFP8FMA : SubtargetFeature<"fp8fma", "HasFP8FMA", "true",
+  "Enable fp8 multiply-add instructions (FEAT_FP8FMA)">;
+
+def FeatureSSVE_FP8FMA : SubtargetFeature<"ssve-fp8fma", "HasSSVE_FP8FMA", "true",
+  "Enable SVE2 fp8 multiply-add instructions (FEAT_SSVE_FP8FMA)", [FeatureSME2]>;
+
 def FeatureAppleA7SysReg  : SubtargetFeature<"apple-a7-sysreg", "HasAppleA7SysReg", "true",
   "Apple A7 (the CPU formerly known as Cyclone)">;
 
@@ -741,7 +747,7 @@ let F = [HasSVE2p1, HasSVE2p1_or_HasSME2, HasSVE2p1_or_HasSME2p1] in
 def SVE2p1Unsupported : AArch64Unsupported;
 
 def SVE2Unsupported : AArch64Unsupported {
-  let F = !listconcat([HasSVE2, HasSVE2orSME,
+  let F = !listconcat([HasSVE2, HasSVE2orSME, HasSSVE_FP8FMA,
                        HasSVE2AES, HasSVE2SHA3, HasSVE2SM4, HasSVE2BitPerm],
                        SVE2p1Unsupported.F);
 }
@@ -755,7 +761,7 @@ let F = [HasSME2p1, HasSVE2p1_or_HasSME2p1] in
 def SME2p1Unsupported : AArch64Unsupported;
 
 def SME2Unsupported : AArch64Unsupported {
-  let F = !listconcat([HasSME2, HasSVE2p1_or_HasSME2],
+  let F = !listconcat([HasSME2, HasSVE2p1_or_HasSME2, HasSSVE_FP8FMA],
                       SME2p1Unsupported.F);
 }
 
diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
index e5dbfa404b3c6bf..25f6f04acd475a8 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
@@ -6055,6 +6055,15 @@ multiclass SIMDThreeSameVectorFML<bit U, bit b13, bits<3> size, string asm,
                                          v4f32, v8f16, OpNode>;
 }
 
+multiclass SIMDThreeSameVectorMLA<bit Q, string asm>{
+  def v8f16 : BaseSIMDThreeSameVectorDot<Q, 0b0, 0b11, 0b1111, asm, ".8h", ".16b",
+                                         V128, v8f16, v16i8, null_frag>;
+}
+
+multiclass SIMDThreeSameVectorMLAL<bit Q, bits<2> sz, string asm>{
+  def v4f32 : BaseSIMDThreeSameVectorDot<Q, 0b0, sz, 0b1000, asm, ".4s", ".16b",
+                                         V128, v4f32, v16i8, null_frag>;
+}
 
 //----------------------------------------------------------------------------
 // AdvSIMD two register vector instructions.
@@ -8468,6 +8477,31 @@ class BF16ToSinglePrecision<string asm>
 }
 } // End of let mayStore = 0, mayLoad = 0, hasSideEffects = 0
 
+//----------------------------------------------------------------------------
+class BaseSIMDThreeSameVectorIndexB<bit Q, bit U, bits<2> sz, bits<4> opc,
+                                    string asm, string dst_kind,
+                                    RegisterOperand RegType,
+                                    RegisterOperand RegType_lo>
+  : BaseSIMDIndexedTied<Q, U, 0b0, sz, opc,
+                        RegType, RegType, RegType_lo, VectorIndexB,
+                        asm, "", dst_kind, ".16b", ".b", []> {
+
+  // idx = H:L:M
+  bits<4> idx;
+  let Inst{11} = idx{3};
+  let Inst{21-19} = idx{2-0};
+}
+
+multiclass SIMDThreeSameVectorMLAIndex<bit Q, string asm> {
+  def v8f16 : BaseSIMDThreeSameVectorIndexB<Q, 0b0, 0b11, 0b0000, asm, ".8h",
+                                            V128, V128_0to7>;
+}
+
+multiclass SIMDThreeSameVectorMLALIndex<bit Q, bits<2> sz, string asm> {
+  def v4f32 : BaseSIMDThreeSameVectorIndexB<Q, 0b1, sz, 0b1000, asm, ".4s",
+                                            V128, V128_0to7>;
+}
+
 //----------------------------------------------------------------------------
 // Armv8.6 Matrix Multiply Extension
 //----------------------------------------------------------------------------
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index 382d3956f105f8c..664fea4d73f4631 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -162,6 +162,13 @@ def HasSME2p1        : Predicate<"Subtarget->hasSME2p1()">,
                                  AssemblerPredicateWithAll<(all_of FeatureSME2p1), "sme2p1">;
 def HasFPMR          : Predicate<"Subtarget->hasFPMR()">,
                                  AssemblerPredicateWithAll<(all_of FeatureFPMR), "fpmr">;
+def HasFP8FMA        : Predicate<"Subtarget->hasFP8FMA()">,
+                                 AssemblerPredicateWithAll<(all_of FeatureFP8FMA), "fp8fma">;
+def HasSSVE_FP8FMA   : Predicate<"Subtarget->SSVE_FP8FMA() || "
+                                 "(Subtarget->hasSVE2() && Subtarget->hasFP8FMA())">,
+                                 AssemblerPredicateWithAll<(any_of FeatureSSVE_FP8FMA,
+                                                          (all_of FeatureSVE2, FeatureFP8FMA)),
+                                 "ssve-fp8fma or (sve2 and fp8fma)">;
 
 // A subset of SVE(2) instructions are legal in Streaming SVE execution mode,
 // they should be enabled if either has been specified.
@@ -9249,6 +9256,21 @@ let Predicates = [HasD128] in {
   }
 }
 
+let Predicates = [HasFP8FMA] in {
+ defm FMLALBlane : SIMDThreeSameVectorMLAIndex<0b0, "fmlalb">;
+ defm FMLALTlane : SIMDThreeSameVectorMLAIndex<0b1, "fmlalt">;
+ defm FMLALLBBlane : SIMDThreeSameVectorMLALIndex<0b0, 0b00, "fmlallbb">;
+ defm FMLALLBTlane : SIMDThreeSameVectorMLALIndex<0b0, 0b01, "fmlallbt">;
+ defm FMLALLTBlane : SIMDThreeSameVectorMLALIndex<0b1, 0b00, "fmlalltb">;
+ defm FMLALLTTlane : SIMDThreeSameVectorMLALIndex<0b1, 0b01, "fmlalltt">;
+
+ defm FMLALB : SIMDThreeSameVectorMLA<0b0, "fmlalb">;
+ defm FMLALT : SIMDThreeSameVectorMLA<0b1, "fmlalt">;
+ defm FMLALLBB : SIMDThreeSameVectorMLAL<0b0, 0b00, "fmlallbb">;
+ defm FMLALLBT : SIMDThreeSameVectorMLAL<0b0, 0b01, "fmlallbt">;
+ defm FMLALLTB : SIMDThreeSameVectorMLAL<0b1, 0b00, "fmlalltb">;
+ defm FMLALLTT : SIMDThreeSameVectorMLAL<0b1, 0b01, "fmlalltt">;
+} // End let Predicates = [HasFP8FMA]
 
 include "AArch64InstrAtomics.td"
 include "AArch64SVEInstrInfo.td"
diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
index cc5384613f1ab38..1a730a0b955d3d1 100644
--- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
@@ -981,6 +981,8 @@ unsigned AArch64RegisterInfo::getRegPressureLimit(const TargetRegisterClass *RC,
   case AArch64::FPR64_loRegClassID:
   case AArch64::FPR16_loRegClassID:
     return 16;
+  case AArch64::FPR128_0to7RegClassID:
+    return 8;
   }
 }
 
diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.td b/llvm/lib/Target/AArch64/AArch64RegisterInfo.td
index eb26591908fd79c..497c143584d48d4 100644
--- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.td
@@ -467,6 +467,13 @@ def FPR128_lo : RegisterClass<"AArch64",
                                v8bf16],
                               128, (trunc FPR128, 16)>;
 
+// The lower 8 vector registers.  Some instructions can only take registers
+// in this range.
+def FPR128_0to7 : RegisterClass<"AArch64",
+                                [v16i8, v8i16, v4i32, v2i64, v4f32, v2f64, v8f16,
+                                 v8bf16],
+                                128, (trunc FPR128, 8)>;
+
 // Pairs, triples, and quads of 64-bit vector registers.
 def DSeqPairs : RegisterTuples<[dsub0, dsub1], [(rotl FPR64, 0), (rotl FPR64, 1)]>;
 def DSeqTriples : RegisterTuples<[dsub0, dsub1, dsub2],
@@ -534,6 +541,15 @@ def V128_lo : RegisterOperand<FPR128_lo, "printVRegOperand"> {
   let ParserMatchClass = VectorRegLoAsmOperand;
 }
 
+def VectorReg0to7AsmOperand : AsmOperandClass {
+  let Name = "VectorReg0to7";
+  let PredicateMethod = "isNeonVectorReg0to7";
+}
+
+def V128_0to7 : RegisterOperand<FPR128_0to7, "printVRegOperand"> {
+  let ParserMatchClass = VectorReg0to7AsmOperand;
+}
+
 class TypedVecListAsmOperand<int count, string vecty, int lanes, int eltsize>
     : AsmOperandClass {
   let Name = "TypedVectorList" # count # "_" # lanes # eltsize;
diff --git a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
index d599ac4689e5cb3..4fbbd33a3cdfdb0 100644
--- a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
@@ -4002,3 +4002,23 @@ 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
+
+let Predicates = [HasSSVE_FP8FMA] in {
+// FP8 Widening Multiply-Add Long - Indexed Group
+def FMLALB_ZZZI : sve2_fp8_mla_long_by_indexed_elem<0b0, "fmlalb">;
+def FMLALT_ZZZI : sve2_fp8_mla_long_by_indexed_elem<0b1, "fmlalt">;
+// FP8 Widening Multiply-Add Long Group
+def FMLALB_ZZZ : sve2_fp8_mla_long<0b0, "fmlalb">;
+def FMLALT_ZZZ : sve2_fp8_mla_long<0b1, "fmlalt">;
+
+// FP8 Widening Multiply-Add Long Long - Indexed Group
+def FMLALLBB_ZZZI : sve2_fp8_mla_long_long_by_indexed_elem<0b00, "fmlallbb">;
+def FMLALLBT_ZZZI : sve2_fp8_mla_long_long_by_indexed_elem<0b01, "fmlallbt">;
+def FMLALLTB_ZZZI : sve2_fp8_mla_long_long_by_indexed_elem<0b10, "fmlalltb">;
+def FMLALLTT_ZZZI : sve2_fp8_mla_long_long_by_indexed_elem<0b11, "fmlalltt">;
+// FP8 Widening Multiply-Add Long Long Group
+def FMLALLBB_ZZZ : sve2_fp8_mla_long_long<0b00, "fmlallbb">;
+def FMLALLBT_ZZZ : sve2_fp8_mla_long_long<0b01, "fmlallbt">;
+def FMLALLTB_ZZZ : sve2_fp8_mla_long_long<0b10, "fmlalltb">;
+def FMLALLTT_ZZZ : sve2_fp8_mla_long_long<0b11, "fmlalltt">;
+} // End HasSSVE_FP8FMA
diff --git a/llvm/lib/Target/AArch64/AArch64SchedA64FX.td b/llvm/lib/Target/AArch64/AArch64SchedA64FX.td
index f3e844dc5b270d1..1de0e8291ef12d9 100644
--- a/llvm/lib/Target/AArch64/AArch64SchedA64FX.td
+++ b/llvm/lib/Target/AArch64/AArch64SchedA64FX.td
@@ -23,7 +23,7 @@ def A64FXModel : SchedMachineModel {
   list<Predicate> UnsupportedFeatures =
     [HasSVE2, HasSVE2AES, HasSVE2SM4, HasSVE2SHA3, HasSVE2BitPerm, HasPAuth,
      HasSVE2orSME, HasMTE, HasMatMulInt8, HasBF16, HasSME2, HasSME2p1, HasSVE2p1,
-     HasSVE2p1_or_HasSME2p1, HasSMEF16F16];
+     HasSVE2p1_or_HasSME2p1, HasSMEF16F16, HasSSVE_FP8FMA];
 
   let FullInstRWOverlapCheck = 0;
 }
diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index 6e70deec3f89092..321e12b9ea87605 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -1223,6 +1223,12 @@ class AArch64Operand : public MCParsedAsmOperand {
                 Reg.RegNum));
   }
 
+  bool isNeonVectorReg0to7() const {
+    return Kind == k_Register && Reg.Kind == RegKind::NeonVector &&
+           (AArch64MCRegisterClasses[AArch64::FPR128_0to7RegClassID].contains(
+               Reg.RegNum));
+  }
+
   bool isMatrix() const { return Kind == k_MatrixRegister; }
   bool isMatrixTileList() const { return Kind == k_MatrixTileList; }
 
@@ -1766,6 +1772,11 @@ class AArch64Operand : public MCParsedAsmOperand {
     Inst.addOperand(MCOperand::createReg(getReg()));
   }
 
+  void addVectorReg0to7Operands(MCInst &Inst, unsigned N) const {
+    assert(N == 1 && "Invalid number of operands!");
+    Inst.addOperand(MCOperand::createReg(getReg()));
+  }
+
   enum VecListIndexType {
     VecListIdx_DReg = 0,
     VecListIdx_QReg = 1,
@@ -2598,31 +2609,31 @@ static std::optional<std::pair<int, int>> parseVectorKind(StringRef Suffix,
 
   switch (VectorKind) {
   case RegKind::NeonVector:
-    Res =
-        StringSwitch<std::pair<int, int>>(Suffix.lower())
-            .Case("", {0, 0})
-            .Case(".1d", {1, 64})
-            .Case(".1q", {1, 128})
-            // '.2h' needed for fp16 scalar pairwise reductions
-            .Case(".2h", {2, 16})
-            .Case(".2s", {2, 32})
-            .Case(".2d", {2, 64})
-            // '.4b' is another special case for the ARMv8.2a dot product
-            // operand
-            .Case(".4b", {4, 8})
-            .Case(".4h", {4, 16})
-            .Case(".4s", {4, 32})
-            .Case(".8b", {8, 8})
-            .Case(".8h", {8, 16})
-            .Case(".16b", {16, 8})
-            // Accept the width neutral ones, too, for verbose syntax. If those
-            // aren't used in the right places, the token operand won't match so
-            // all will work out.
-            .Case(".b", {0, 8})
-            .Case(".h", {0, 16})
-            .Case(".s", {0, 32})
-            .Case(".d", {0, 64})
-            .Default({-1, -1});
+    Res = StringSwitch<std::pair<int, int>>(Suffix.lower())
+              .Case("", {0, 0})
+              .Case(".1d", {1, 64})
+              .Case(".1q", {1, 128})
+              // '.2h' needed for fp16 scalar pairwise reductions
+              .Case(".2h", {2, 16})
+              .Case(".2b", {2, 8})
+              .Case(".2s", {2, 32})
+              .Case(".2d", {2, 64})
+              // '.4b' is another special case for the ARMv8.2a dot product
+              // operand
+              .Case(".4b", {4, 8})
+              .Case(".4h", {4, 16})
+              .Case(".4s", {4, 32})
+              .Case(".8b", {8, 8})
+              .Case(".8h", {8, 16})
+              .Case(".16b", {16, 8})
+              // Accept the width neutral ones, too, for verbose syntax. If
+              // those aren't used in the right places, the token operand won't
+              // match so all will work out.
+              .Case(".b", {0, 8})
+              .Case(".h", {0, 16})
+              .Case(".s", {0, 32})
+              .Case(".d", {0, 64})
+              .Default({-1, -1});
     break;
   case RegKind::SVEPredicateAsCounter:
   case RegKind::SVEPredicateVector:
@@ -3639,6 +3650,8 @@ static const struct Extension {
     {"ssbs", {AArch64::FeatureSSBS}},
     {"tme", {AArch64::FeatureTME}},
     {"fpmr", {AArch64::FeatureFPMR}},
+    {"fp8fma", {AArch64::FeatureFP8FMA}},
+    {"ssve-fp8fma", {AArch64::FeatureFP8FMA}},
 };
 
 static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
diff --git a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
index df817f62f99fbf7..cf2d3879292d196 100644
--- a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
+++ b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
@@ -44,6 +44,9 @@ static DecodeStatus DecodeFPR128RegisterClass(MCInst &Inst, unsigned RegNo,
 static DecodeStatus DecodeFPR128_loRegisterClass(MCInst &Inst, unsigned RegNo,
                                                  uint64_t Address,
                                                  const MCDisassembler *Decoder);
+static DecodeStatus
+DecodeFPR128_0to7RegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address,
+                               const MCDisassembler *Decoder);
 static DecodeStatus DecodeFPR64RegisterClass(MCInst &Inst, unsigned RegNo,
                                              uint64_t Address,
                                              const MCDisassembler *Decoder);
@@ -437,6 +440,14 @@ DecodeFPR128_loRegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Addr,
   return DecodeFPR128RegisterClass(Inst, RegNo, Addr, Decoder);
 }
 
+static DecodeStatus
+DecodeFPR128_0to7RegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Addr,
+                               const MCDisassembler *Decoder) {
+  if (RegNo > 7)
+    return Fail;
+  return DecodeFPR128RegisterClass(Inst, RegNo, Addr, Decoder);
+}
+
 static DecodeStatus DecodeFPR64RegisterClass(MCInst &Inst, unsigned RegNo,
                                              uint64_t Addr,
                                              const MCDisassembler *Decoder) {
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp b/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp
index 26954c62e03f1fc..6266152bca48f1f 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp
@@ -245,9 +245,10 @@ AArch64RegisterBankInfo::getRegBankFromRegClass(const TargetRegisterClass &RC,
   case AArch64::FPR32_with_hsub_in_FPR16_loRegClassID:
   case AArch64::FPR32RegClassID:
   case AArch64::FPR64RegClassID:
-  case AArch64::FPR64_loRegClassID:
   case AArch64::FPR128RegClassID:
+  case AArch64::FPR64_loRegClassID:
   case AArch64::FPR128_loRegClassID:
+  case AArch64::FPR128_0to7RegClassID:
   case AArch64::DDRegClassID:
   case AArch64::DDDRegClassID:
   case AArch64::DDDDRegClassID:
diff --git a/llvm/lib/Target/AArch64/SVEInstrFormats.td b/llvm/lib/Target/AArch64/SVEInstrFormats.td
index 7bb457d9188210c..284cf6f7ef22ebc 100644
--- a/llvm/lib/Target/AArch64/SVEInstrFormats.td
+++ b/llvm/lib/Target/AArch64/SVEInstrFormats.td
@@ -10078,3 +10078,93 @@ 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>;
 }
+
+// FP8 Widening Multiply-Add Long - Indexed Group
+class sve2_fp8_mla_long_by_indexed_elem<bit T, string mnemonic>
+    : I<(outs ZPR16:$Zda),
+      (ins ZPR16:$_Zda, ZPR8:$Zn, ZPR3b8:$Zm, VectorIndexB:$imm4),
+      mnemonic, "\t$Zda, $Zn, $Zm$imm4",
+      "", []>, Sched<[]>{
+  bits<5> Zda;
+  bits<5> Zn;
+  bits<3> Zm;
+  bits<4> imm4;
+  let Inst{31-24} = 0b01100100;
+  let Inst{23} = T;
+  let Inst{22-21} = 0b01;
+  let Inst{20-19} = imm4{3-2};
+  let Inst{18-16} = Zm;
+  let Inst{15-12} = 0b0101;
+  let Inst{11-10} = imm4{1-0};
+  let Inst{9-5} = Zn;
+  let Inst{4-0} = Zda;
+  let Constraints = "$Zda = $_Zda";
+  let DestructiveInstType = DestructiveOther;
+  let ElementSize = ZPR16.ElementSize;
+}
+
+// FP8 Widening Multiply-Add Long Group
+class sve2_fp8_mla_long<bit T, string mnemonic>
+    : I<(outs ZPR16:$Zda),
+      (ins ZPR16:$_Zda, ZPR8:$Zn, ZPR8:$Zm),
+      mnemonic, "\t$Zda, $Zn, $Zm",
+      "", []>, Sched<[]>{
+  bits<5> Zda;
+  bits<5> Zn;
+  bits<5> Zm;
+  let Inst{31-21} = 0b01100100101;
+  let Inst{20-16} = Zm;
+  let Inst{15-13} = 0b100;
+  let Inst{12} = T;
+  let Inst{11-10} = 0b10;
+  let Inst{9-5} = Zn;
+  let Inst{4-0} = Zda;
+  let Constraints = "$Zda = $_Zda";
+  let DestructiveInstType = DestructiveOther;
+  let ElementSize = ZPR16.ElementSize;
+}
+
+// FP8 Widening Multiply-Add Long Long - Indexed Group
+class sve2_fp8_mla_long_long_by_indexed_elem<bits<2> TT, string mnemonic>
+    : I<(outs ZPR32:$Zda),
+      (ins ZPR32:$_Zda, ZPR8:$Zn, ZPR3b8:$Zm, VectorIndexB:$imm4),
+      mnemonic, "\t$Zda, $Zn, $Zm$imm4",
+      "", []>, Sched<[]>{
+  bits<5> Zda;
+  bits<5> Zn;
+  bits<3> Zm;
+  bits<4> imm4;
+  let Inst{31-24} = 0b01100100;
+  let Inst{23-22} = TT;
+  let Inst{21} = 0b1;
+  let Inst{20-19} = imm4{3-2};
+  let Inst{18-16} = Zm;
+  let Inst{15-12} = 0b1100;
+  let Inst{11-10} = imm4{1-0};
+  let Inst{9-5} = Zn;
+  let Inst{4-0} = Zda;
+  let Constraints = "$Zda = $_Zda";
+  let DestructiveInstType = DestructiveOther;
+  let ElementSize = ZPR32.ElementSize;
+}
+
+// FP8 Widening Multiply-Add Long Long Group
+class sve2_fp8_mla_long_long<bits<2> TT, string mnemonic>
+    : I<(outs ZPR32:$Zda),
+      (ins ZPR32:$_Zda, ZPR8:$Zn, ZPR8:$Zm),
+      mnemonic, "\t$Zda, $Zn, $Zm",
+      "", []>, Sched<[]>{
+  bits<5> Zda;
+  bits<5> Zn;
+  bits<5> Zm;
+  let Inst{31-21} = 0b01100100001;
+  let Inst{20-16} = Zm;
+  let Inst{15-14} = 0b10;
+  let Inst{13-12} = TT;
+  let Inst{11-10} = 0b10;
+  let Inst{9-5} = Zn;
+  let Inst{4-0} = Zda;
+  let Constraints = "$Zda = $_Zda";
+  let DestructiveInstType = DestructiveOther;
+  let ElementSize = ZPR32.ElementSize;
+}
diff --git a/llvm/test/MC/AArch64/FP8/directive-arch-negative.s b/llvm/test/MC/AArch64/FP8/directive-arch-negative.s
new file mode 100644
index 000000000000000..3a1a5837a9eea3c
--- /dev/null
+++ b/llvm/test/MC/AArch64/FP8/directive-arch-negative.s
@@ -0,0 +1,13 @@
+// RUN: not llvm-mc -triple aarch64 -filetype asm -o - %s 2>&1 | FileCheck %s
+
+.arch armv9-a+fp8fma
+.arch armv9-a+nofp8fma
+fmlalb  v0.8h, v0.16b, v0.16b
+// CHECK: error: instruction requires: fp8fma
+// CHECK: fmlalb  v0.8h, v0.16b, v0.16b
+
+.arch armv9-a+ssve-fp8fma
+.arch armv9-a+nossve-fp8fma
+fmlalb  v0.8h, v0.16b, v0.16b
+// CHECK: error: instruction requires: ssve-fp8fma
+// CHECK: fmlalb  v0.8h, v0.16b, v0.16b
\ No newline at end of file
diff --git a/llvm/test/MC/AArch64/FP8/directive-arch.s b/llvm/test/MC/AArch64/FP8/directive-arch.s
new file mode 100644
index 000000000000000..f8bf1c42d6448b2
--- /dev/null
+++ b/llvm/test/MC/AArch64/FP8/directive-arch.s
@@ -0,0 +1,13 @@
+// RUN: llvm-mc -triple aarch64 -o - %s 2>&1 | FileCheck %s
+
+.arch armv9-a+fp8fma
+fmlalb  v0.8h, v0.16b, v0.16b
+// CHECK: fmlalb  v0.8h, v0.16b, v0.16b
+
+.arch armv9-a+nofp8fma
+
+.arch armv9-a+ssve-fp8fma
+fmlalb  v0.8h, v0.16b, v0.16b
+// CHECK: fmlalb  v0.8h, v0.16b, v0.16b
+
+.arch armv9-a+nossve-fp8fma
\ No newline at end of file
diff --git a/llvm/test/MC/AArch64/FP8/mla-diagnostic.s b/llvm/test/MC/AArch64/FP8/mla-diagnostic.s
new file mode 100644
index 000000000000000..91a23a3d73e0caf
--- /dev/null
+++ b/llvm/test/MC/AArch64/FP8/mla-diagnostic.s
@@ -0,0 +1,85 @@
+// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=fp8fma 2>&1 < %s| FileCheck %s
+
+// --------------------------------------------------------------------------//
+// Element size extension incorrect
+fmlalb  v0.8h, v0.8b, v0.8b
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: fmlalb  v0.8h, v0.8b, v0.8b
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+fmlalt  v31.8h, v31.16b, v31.16h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid vector kind qualifier
+// CHECK-NEXT: fmlalt  v31.8h, v31.16b, v31.16h
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+fmlallbb  v0.4s, v0, v31
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: fmlallbb  v0.4s, v0, v31
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+fmlallbt  v31.4b, v31.16b, v0.16b
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: fmlallbt  v31.4b, v31.16b, v0.16b
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+fmlalltb  v31.b, v31.16b, v0.16b
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: fmlalltb  v31.b, v31.16b, v0.16b
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+fmlalltt  v0.4s, v0.16b, v31.b
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: fmlalltt  v0.4s, v0.16b, v31.b
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+fmlalt  v31.8s, v31.16b, v31.16b
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid vector kind qualifier
+// CHECK-NEXT: fmlalt  v31.8s, v31.16b, v31.16b
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+
+//--------------------------------------------------------------------------//
+// Last Register range is between 0-7
+
+fmlalltb  v0.4s, v31.16b, v8.b[0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: fmlalltb  v0.4s, v31.16b, v8.b[0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}$
+
+fmlalt  v31.8h, v0.16b, v8.b[15]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: fmlalt  v31.8h, v0.16b, v8.b[15]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:$
+
+
+// --------------------------------------------------------------------------//
+// Out of range index
+fmlalb  v31.8h, v0.16b, v0.b[-1]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 15].
+// CHECK-NEXT: fmlalb  v31.8h, v0.16b, v0.b[-1]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+fmlalt  v31.8h, v0.16b, v0.b[16]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 15].
+// CHECK-NEXT: fmlalt  v31.8h, v0.16b, v0.b[16]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+fmlallbb  v31.4s, v0.16b, v7.b[-1]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 15].
+// CHECK-NEXT: fmlallbb  v31.4s, v0.16b, v7.b[-1]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+fmlalltt  v31.4s, v0.16b, v7.b[16]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 15].
+// CHECK-NEXT: fmlalltt  v31.4s, v0.16b, v7.b[16]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+fmlalltb  v0.4s, v31.16b, v7.b[-1]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 15].
+// CHECK-NEXT: fmlalltb  v0.4s, v31.16b, v7.b[-1]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}
+
+fmlallbt  v0.4s, v31.16b, v0.b[16]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 15].
+// CHECK-NEXT: fmlallbt  v0.4s, v31.16b, v0.b[16]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
diff --git a/llvm/test/MC/AArch64/FP8/mla.s b/llvm/test/MC/AArch64/FP8/mla.s
new file mode 100644
index 000000000000000..b3b6f1eb1806211
--- /dev/null
+++ b/llvm/test/MC/AArch64/FP8/mla.s
@@ -0,0 +1,98 @@
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+fp8fma < %s \
+// RUN:        | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \
+// RUN:        | FileCheck %s --check-prefix=CHECK-ERROR
+// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+fp8fma < %s \
+// RUN:        | llvm-objdump -d --mattr=+fp8fma - | FileCheck %s --check-prefix=CHECK-INST
+// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+fp8fma < %s \
+// RUN:        | llvm-objdump -d --mattr=-fp8fma - | FileCheck %s --check-prefix=CHECK-UNKNOWN
+// Disassemble encoding and check the re-encoding (-show-encoding) matches.
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+fp8fma < %s \
+// RUN:        | sed '/.text/d' | sed 's/.*encoding: //g' \
+// RUN:        | llvm-mc -triple=aarch64 -mattr=+fp8fma -disassemble -show-encoding \
+// RUN:        | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+
+/// VECTOR
+// MLA
+fmlalb  v0.8h, v0.16b, v0.16b
+// CHECK-INST: fmlalb  v0.8h, v0.16b, v0.16b
+// CHECK-ENCODING: [0x00,0xfc,0xc0,0x0e]
+// CHECK-ERROR: instruction requires: fp8fma
+// CHECK-UNKNOWN: 0ec0fc00 <unknown>
+
+fmlalt  v31.8h, v31.16b, v31.16b
+// CHECK-INST: fmlalt  v31.8h, v31.16b, v31.16b
+// CHECK-ENCODING: [0xff,0xff,0xdf,0x4e]
+// CHECK-ERROR: instruction requires: fp8fma
+// CHECK-UNKNOWN: 4edfffff <unknown>
+
+
+// MLALL
+fmlallbb  v0.4s, v0.16b, v31.16b
+// CHECK-INST: fmlallbb  v0.4s, v0.16b, v31.16b
+// CHECK-ENCODING: [0x00,0xc4,0x1f,0x0e]
+// CHECK-ERROR: instruction requires: fp8fma
+// CHECK-UNKNOWN: 0e1fc400 <unknown>
+
+fmlallbt  v31.4s, v31.16b, v0.16b
+// CHECK-INST: fmlallbt  v31.4s, v31.16b, v0.16b
+// CHECK-ENCODING: [0xff,0xc7,0x40,0x0e]
+// CHECK-ERROR: instruction requires: fp8fma
+// CHECK-UNKNOWN: 0e40c7ff <unknown>
+
+fmlalltb  v31.4s, v31.16b, v0.16b
+// CHECK-INST: fmlalltb  v31.4s, v31.16b, v0.16b
+// CHECK-ENCODING: [0xff,0xc7,0x00,0x4e]
+// CHECK-ERROR: instruction requires: fp8fma
+// CHECK-UNKNOWN: 4e00c7ff <unknown>
+
+fmlalltt  v0.4s, v0.16b, v31.16b
+// CHECK-INST: fmlalltt  v0.4s, v0.16b, v31.16b
+// CHECK-ENCODING: [0x00,0xc4,0x5f,0x4e]
+// CHECK-ERROR: instruction requires: fp8fma
+// CHECK-UNKNOWN: 4e5fc400 <unknown>
+
+fmlalltt v31.4s, v31.16b, v31.16b  // 01001110-01011111-11000111-11111111
+// CHECK-INST: fmlalltt v31.4s, v31.16b, v31.16b
+// CHECK-ENCODING: [0xff,0xc7,0x5f,0x4e]
+// CHECK-ERROR: instruction requires: fp8
+// CHECK-UNKNOWN: 4e5fc7ff <unknown>
+
+//INDEXED
+// MLA
+fmlalb  v31.8h, v0.16b, v0.b[0]
+// CHECK-INST: fmlalb  v31.8h, v0.16b, v0.b[0]
+// CHECK-ENCODING: [0x1f,0x00,0xc0,0x0f]
+// CHECK-ERROR: instruction requires: fp8fma
+// CHECK-UNKNOWN: 0fc0001f <unknown>
+
+fmlalt  v31.8h, v0.16b, v0.b[15]
+// CHECK-INST: fmlalt  v31.8h, v0.16b, v0.b[15]
+// CHECK-ENCODING: [0x1f,0x08,0xf8,0x4f]
+// CHECK-ERROR: instruction requires: fp8fma
+// CHECK-UNKNOWN: 4ff8081f <unknown>
+
+// MLALL
+fmlallbb  v31.4s, v0.16b, v7.b[0]
+// CHECK-INST: fmlallbb  v31.4s, v0.16b, v7.b[0]
+// CHECK-ENCODING: [0x1f,0x80,0x07,0x2f]
+// CHECK-ERROR: instruction requires: fp8fma
+// CHECK-UNKNOWN: 2f07801f <unknown>
+
+fmlalltt  v31.4s, v0.16b, v7.b[0]
+// CHECK-INST: fmlalltt  v31.4s, v0.16b, v7.b[0]
+// CHECK-ENCODING: [0x1f,0x80,0x47,0x6f]
+// CHECK-ERROR: instruction requires: fp8fma
+// CHECK-UNKNOWN: 6f47801f <unknown>
+
+fmlalltb  v0.4s, v31.16b, v7.b[15]
+// CHECK-INST: fmlalltb  v0.4s, v31.16b, v7.b[15]
+// CHECK-ENCODING: [0xe0,0x8b,0x3f,0x6f]
+// CHECK-ERROR: instruction requires: fp8fma
+// CHECK-UNKNOWN: 6f3f8be0 <unknown>
+
+fmlallbt  v0.4s, v31.16b, v0.b[15]
+// CHECK-INST: fmlallbt  v0.4s, v31.16b, v0.b[15]
+// CHECK-ENCODING: [0xe0,0x8b,0x78,0x2f]
+// CHECK-ERROR: instruction requires: fp8fma
+// CHECK-UNKNOWN: 2f788be0 <unknown>
diff --git a/llvm/test/MC/AArch64/FP8_SVE2/fmlal-diagnostics.s b/llvm/test/MC/AArch64/FP8_SVE2/fmlal-diagnostics.s
new file mode 100644
index 000000000000000..627ec0f044bb999
--- /dev/null
+++ b/llvm/test/MC/AArch64/FP8_SVE2/fmlal-diagnostics.s
@@ -0,0 +1,64 @@
+// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+ssve-fp8fma  2>&1 < %s| FileCheck %s
+
+// ------------------------------------------------------------------------- //
+// z register out of range for index
+fmlalb z0.h, z1.b, z8.b[0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: fmlalb z0.h, z1.b, z8.b[0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+fmlalt z0.h, z1.b, z8.b[0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: fmlalt z0.h, z1.b, z8.b[0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+// ------------------------------------------------------------------------- //
+// Index out of bounds
+
+fmlalb z0.h, z1.b, z7.b[-1]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 15].
+// CHECK-NEXT: fmlalb z0.h, z1.b, z7.b[-1]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+fmlalt z0.h, z1.b, z7.b[16]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 15].
+// CHECK-NEXT: fmlalt z0.h, z1.b, z7.b[16]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+// ------------------------------------------------------------------------- //
+// Invalid element width
+
+fmlalb z0.h, z1.h, z2.h[0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width
+// CHECK-NEXT: fmlalb z0.h, z1.h, z2.h[0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+fmlalb z0.h, z1.h, z2.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width
+// CHECK-NEXT: fmlalb  z0.h, z1.h, z2.h
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+fmlalt z0.s, z1.b, z2.b[0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width
+// CHECK-NEXT: fmlalt z0.s, z1.b, z2.b[0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+fmlalt z0.s, z1.b, z2.b
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width
+// CHECK-NEXT: fmlalt  z0.s, z1.b, z2.b
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+// --------------------------------------------------------------------------//
+// Negative tests for instructions that are incompatible with movprfx
+
+movprfx z0.b, p0/z, z0.b
+fmlalb  z0.h, z1.b, z7.b[0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a predicated movprfx, suggest using unpredicated movprfx
+// CHECK-NEXT: fmlalb  z0.h, z1.b, z7.b[0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+movprfx z29.b, p0/z, z7.b
+fmlalt  z29.h, z30.b, z31.b
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a predicated movprfx, suggest using unpredicated movprfx
+// CHECK-NEXT: fmlalt  z29.h, z30.b, z31.b
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
diff --git a/llvm/test/MC/AArch64/FP8_SVE2/fmlal.s b/llvm/test/MC/AArch64/FP8_SVE2/fmlal.s
new file mode 100644
index 000000000000000..b567364b0788563
--- /dev/null
+++ b/llvm/test/MC/AArch64/FP8_SVE2/fmlal.s
@@ -0,0 +1,114 @@
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+ssve-fp8fma < %s \
+// RUN:        | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+
+// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \
+// RUN:        | FileCheck %s --check-prefix=CHECK-ERROR
+
+// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2,+fp8fma < %s \
+// RUN:        | llvm-objdump -d --mattr=+sve2,+fp8fma --no-print-imm-hex - | FileCheck %s --check-prefix=CHECK-INST
+
+// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2,+fp8fma < %s \
+// RUN:        | llvm-objdump -d --mattr=-fp8fma --no-print-imm-hex - | FileCheck %s --check-prefix=CHECK-UNKNOWN
+
+// Disassemble encoding and check the re-encoding (-show-encoding) matches.
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2,+fp8fma < %s \
+// RUN:        | sed '/.text/d' | sed 's/.*encoding: //g' \
+// RUN:        | llvm-mc -triple=aarch64 -mattr=+sve2,+fp8fma -disassemble -show-encoding \
+// RUN:        | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+
+//
+// FMLALB instructions
+//
+// fmlalb - indexed
+
+fmlalb  z0.h, z0.b, z0.b[0]  // 01100100-00100000-01010000-00000000
+// CHECK-INST: fmlalb  z0.h, z0.b, z0.b[0]
+// CHECK-ENCODING: [0x00,0x50,0x20,0x64]
+// CHECK-ERROR: instruction requires: ssve-fp8fma or (sve2 and fp8fma)
+// CHECK-UNKNOWN: 64205000 <unknown>
+
+movprfx z23, z31
+fmlalb  z23.h, z13.b, z0.b[7]  // 01100100-00101000-01011101-10110111
+// CHECK-INST:  movprfx z23, z31
+// CHECK-INST: fmlalb  z23.h, z13.b, z0.b[7]
+// CHECK-ENCODING: [0xb7,0x5d,0x28,0x64]
+// CHECK-ERROR: instruction requires: ssve-fp8fma or (sve2 and fp8fma)
+// CHECK-UNKNOWN: 64285db7 <unknown>
+
+fmlalb  z31.h, z31.b, z7.b[15]  // 01100100-00111111-01011111-11111111
+// CHECK-INST: fmlalb  z31.h, z31.b, z7.b[15]
+// CHECK-ENCODING: [0xff,0x5f,0x3f,0x64]
+// CHECK-ERROR: instruction requires: ssve-fp8fma or (sve2 and fp8fma)
+// CHECK-UNKNOWN: 643f5fff <unknown>
+
+
+// fmlalb - group
+
+fmlalb  z0.h, z0.b, z0.b  // 01100100-10100000-10001000-00000000
+// CHECK-INST: fmlalb  z0.h, z0.b, z0.b
+// CHECK-ENCODING: [0x00,0x88,0xa0,0x64]
+// CHECK-ERROR: instruction requires: ssve-fp8fma or (sve2 and fp8fma)
+// CHECK-UNKNOWN: 64a08800 <unknown>
+
+movprfx z23, z31
+fmlalb  z23.h, z13.b, z8.b  // 01100100-10101000-10001001-10110111
+// CHECK-INST:  movprfx z23, z31
+// CHECK-INST: fmlalb  z23.h, z13.b, z8.b
+// CHECK-ENCODING: [0xb7,0x89,0xa8,0x64]
+// CHECK-ERROR: instruction requires: ssve-fp8fma or (sve2 and fp8fma)
+// CHECK-UNKNOWN: 64a889b7 <unknown>
+
+fmlalb  z31.h, z31.b, z31.b  // 01100100-10111111-10001011-11111111
+// CHECK-INST: fmlalb  z31.h, z31.b, z31.b
+// CHECK-ENCODING: [0xff,0x8b,0xbf,0x64]
+// CHECK-ERROR: instruction requires: ssve-fp8fma or (sve2 and fp8fma)
+// CHECK-UNKNOWN: 64bf8bff <unknown>
+
+
+//
+// FMLALT instructions
+//
+// fmlalt - indexed
+
+fmlalt  z0.h, z0.b, z0.b[0]  // 01100100-10100000-01010000-00000000
+// CHECK-INST: fmlalt  z0.h, z0.b, z0.b[0]
+// CHECK-ENCODING: [0x00,0x50,0xa0,0x64]
+// CHECK-ERROR: instruction requires: ssve-fp8fma or (sve2 and fp8fma)
+// CHECK-UNKNOWN: 64a05000 <unknown>
+
+movprfx z23, z31
+fmlalt  z23.h, z13.b, z0.b[7]  // 01100100-10101000-01011101-10110111
+// CHECK-INST:  movprfx z23, z31
+// CHECK-INST: fmlalt  z23.h, z13.b, z0.b[7]
+// CHECK-ENCODING: [0xb7,0x5d,0xa8,0x64]
+// CHECK-ERROR: instruction requires: ssve-fp8fma or (sve2 and fp8fma)
+// CHECK-UNKNOWN: 64a85db7 <unknown>
+
+fmlalt  z31.h, z31.b, z7.b[15]  // 01100100-10111111-01011111-11111111
+// CHECK-INST: fmlalt  z31.h, z31.b, z7.b[15]
+// CHECK-ENCODING: [0xff,0x5f,0xbf,0x64]
+// CHECK-ERROR: instruction requires: ssve-fp8fma or (sve2 and fp8fma)
+// CHECK-UNKNOWN: 64bf5fff <unknown>
+
+
+// fmlalt - group
+
+fmlalt  z0.h, z0.b, z0.b  // 01100100-10100000-10011000-00000000
+// CHECK-INST: fmlalt  z0.h, z0.b, z0.b
+// CHECK-ENCODING: [0x00,0x98,0xa0,0x64]
+// CHECK-ERROR: instruction requires: ssve-fp8fma or (sve2 and fp8fma)
+// CHECK-UNKNOWN: 64a09800 <unknown>
+
+movprfx z23, z31
+fmlalt  z23.h, z13.b, z8.b  // 01100100-10101000-10011001-10110111
+// CHECK-INST:  movprfx z23, z31
+// CHECK-INST: fmlalt  z23.h, z13.b, z8.b
+// CHECK-ENCODING: [0xb7,0x99,0xa8,0x64]
+// CHECK-ERROR: instruction requires: ssve-fp8fma or (sve2 and fp8fma)
+// CHECK-UNKNOWN: 64a899b7 <unknown>
+
+fmlalt  z31.h, z31.b, z31.b  // 01100100-10111111-10011011-11111111
+// CHECK-INST: fmlalt  z31.h, z31.b, z31.b
+// CHECK-ENCODING: [0xff,0x9b,0xbf,0x64]
+// CHECK-ERROR: instruction requires: ssve-fp8fma or (sve2 and fp8fma)
+// CHECK-UNKNOWN: 64bf9bff <unknown>
diff --git a/llvm/test/MC/AArch64/FP8_SVE2/fmlall-diagnostics.s b/llvm/test/MC/AArch64/FP8_SVE2/fmlall-diagnostics.s
new file mode 100644
index 000000000000000..7a8a299b8756daf
--- /dev/null
+++ b/llvm/test/MC/AArch64/FP8_SVE2/fmlall-diagnostics.s
@@ -0,0 +1,85 @@
+// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+ssve-fp8fma  2>&1 < %s| FileCheck %s
+
+// ------------------------------------------------------------------------- //
+// z register out of range for index
+
+fmlallbb z0.s, z1.b, z8.b[0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: fmlallbb z0.s, z1.b, z8.b[0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+fmlallbt z0.s, z1.b, z8.b[0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: fmlallbt z0.s, z1.b, z8.b[0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+fmlalltb z0.s, z1.b, z8.b[0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: fmlalltb z0.s, z1.b, z8.b[0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+fmlalltt z0.s, z1.b, z8.b[0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: fmlalltt z0.s, z1.b, z8.b[0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+// ------------------------------------------------------------------------- //
+// Index out of bounds
+
+fmlallbb z0.s, z1.b, z7.b[-1]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 15].
+// CHECK-NEXT: fmlallbb z0.s, z1.b, z7.b[-1]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+fmlallbt z0.s, z1.b, z7.b[16]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 15].
+// CHECK-NEXT: fmlallbt z0.s, z1.b, z7.b[16]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+fmlalltb z0.s, z1.b, z7.b[-1]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 15].
+// CHECK-NEXT: fmlalltb z0.s, z1.b, z7.b[-1]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+fmlalltt z0.s, z1.b, z7.b[16]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 15].
+// CHECK-NEXT: fmlalltt z0.s, z1.b, z7.b[16]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+// ------------------------------------------------------------------------- //
+// Invalid element width
+
+fmlallbb z0.h, z1.b, z2.b[0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width
+// CHECK-NEXT: fmlallbb z0.h, z1.b, z2.b[0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+fmlallbt z0.h, z1.b, z2.b
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width
+// CHECK-NEXT: fmlallbt  z0.h, z1.b, z2.b
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+fmlalltb z0.s, z1.h, z2.h[0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width
+// CHECK-NEXT: fmlalltb z0.s, z1.h, z2.h[0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+fmlalltt z0.s, z1.h, z2.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width
+// CHECK-NEXT: fmlalltt  z0.s, z1.h, z2.h
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+// --------------------------------------------------------------------------//
+// Negative tests for instructions that are incompatible with movprfx
+
+movprfx z0.s, p0/z, z0.s
+fmlallbb  z0.s, z1.b, z7.b[0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a predicated movprfx, suggest using unpredicated movprfx
+// CHECK-NEXT: fmlallbb  z0.s, z1.b, z7.b[0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+movprfx z29.s, p0/z, z7.s
+fmlalltt  z29.s, z30.b, z31.b
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a predicated movprfx, suggest using unpredicated movprfx
+// CHECK-NEXT: fmlalltt  z29.s, z30.b, z31.b
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
diff --git a/llvm/test/MC/AArch64/FP8_SVE2/fmlall.s b/llvm/test/MC/AArch64/FP8_SVE2/fmlall.s
new file mode 100644
index 000000000000000..319e664172da658
--- /dev/null
+++ b/llvm/test/MC/AArch64/FP8_SVE2/fmlall.s
@@ -0,0 +1,222 @@
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+ssve-fp8fma < %s \
+// RUN:        | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+
+// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \
+// RUN:        | FileCheck %s --check-prefix=CHECK-ERROR
+
+// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2,+fp8fma < %s \
+// RUN:        | llvm-objdump -d --mattr=+sve2,+fp8fma --no-print-imm-hex - | FileCheck %s --check-prefix=CHECK-INST
+
+// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2,+fp8fma < %s \
+// RUN:        | llvm-objdump -d --mattr=-sve2 --no-print-imm-hex - | FileCheck %s --check-prefix=CHECK-UNKNOWN
+
+// Disassemble encoding and check the re-encoding (-show-encoding) matches.
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2,+fp8fma < %s \
+// RUN:        | sed '/.text/d' | sed 's/.*encoding: //g' \
+// RUN:        | llvm-mc -triple=aarch64 -mattr=+sve2,+fp8fma -disassemble -show-encoding \
+// RUN:        | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+
+//
+// FMLALLBB instructions
+//
+// fmlallbb - indexed
+
+fmlallbb z0.s, z0.b, z0.b[0]  // 01100100-00100000-11000000-00000000
+// CHECK-INST: fmlallbb z0.s, z0.b, z0.b[0]
+// CHECK-ENCODING: [0x00,0xc0,0x20,0x64]
+// CHECK-ERROR: instruction requires: ssve-fp8fma or (sve2 and fp8fma)
+// CHECK-UNKNOWN: 6420c000 <unknown>
+
+movprfx z23, z31
+fmlallbb z23.s, z13.b, z0.b[7]  // 01100100-00101000-11001101-10110111
+// CHECK-INST:  movprfx z23, z31
+// CHECK-INST: fmlallbb z23.s, z13.b, z0.b[7]
+// CHECK-ENCODING: [0xb7,0xcd,0x28,0x64]
+// CHECK-ERROR: instruction requires: ssve-fp8fma or (sve2 and fp8fma)
+// CHECK-UNKNOWN: 6428cdb7 <unknown>
+
+fmlallbb z31.s, z31.b, z7.b[15]  // 01100100-00111111-11001111-11111111
+// CHECK-INST: fmlallbb z31.s, z31.b, z7.b[15]
+// CHECK-ENCODING: [0xff,0xcf,0x3f,0x64]
+// CHECK-ERROR: instruction requires: ssve-fp8fma or (sve2 and fp8fma)
+// CHECK-UNKNOWN: 643fcfff <unknown>
+
+//
+// FMLALLBB instructions
+//
+// fmlallbb - group
+
+fmlallbb z0.s, z0.b, z0.b  // 01100100-00100000-10001000-00000000
+// CHECK-INST: fmlallbb z0.s, z0.b, z0.b
+// CHECK-ENCODING: [0x00,0x88,0x20,0x64]
+// CHECK-ERROR: instruction requires: ssve-fp8fma or (sve2 and fp8fma)
+// CHECK-UNKNOWN: 64208800 <unknown>
+
+movprfx z23, z31
+fmlallbb z23.s, z13.b, z8.b  // 01100100-00101000-10001001-10110111
+// CHECK-INST:  movprfx z23, z31
+// CHECK-INST: fmlallbb z23.s, z13.b, z8.b
+// CHECK-ENCODING: [0xb7,0x89,0x28,0x64]
+// CHECK-ERROR: instruction requires: ssve-fp8fma or (sve2 and fp8fma)
+// CHECK-UNKNOWN: 642889b7 <unknown>
+
+fmlallbb z31.s, z31.b, z31.b  // 01100100-00111111-10001011-11111111
+// CHECK-INST: fmlallbb z31.s, z31.b, z31.b
+// CHECK-ENCODING: [0xff,0x8b,0x3f,0x64]
+// CHECK-ERROR: instruction requires: ssve-fp8fma or (sve2 and fp8fma)
+// CHECK-UNKNOWN: 643f8bff <unknown>
+
+//--------------------------------------------//
+//
+// FMLALLBT instructions
+//
+// fmlallbt - indexed
+
+fmlallbt z0.s, z0.b, z0.b[0]  // 01100100-01100000-11000000-00000000
+// CHECK-INST: fmlallbt z0.s, z0.b, z0.b[0]
+// CHECK-ENCODING: [0x00,0xc0,0x60,0x64]
+// CHECK-ERROR: instruction requires: ssve-fp8fma or (sve2 and fp8fma)
+// CHECK-UNKNOWN: 6460c000 <unknown>
+
+movprfx z23, z31
+fmlallbt z23.s, z13.b, z0.b[7]  // 01100100-01101000-11001101-10110111
+// CHECK-INST:  movprfx z23, z31
+// CHECK-INST: fmlallbt z23.s, z13.b, z0.b[7]
+// CHECK-ENCODING: [0xb7,0xcd,0x68,0x64]
+// CHECK-ERROR: instruction requires: ssve-fp8fma or (sve2 and fp8fma)
+// CHECK-UNKNOWN: 6468cdb7 <unknown>
+
+fmlallbt z31.s, z31.b, z7.b[15]  // 01100100-01111111-11001111-11111111
+// CHECK-INST: fmlallbt z31.s, z31.b, z7.b[15]
+// CHECK-ENCODING: [0xff,0xcf,0x7f,0x64]
+// CHECK-ERROR: instruction requires: ssve-fp8fma or (sve2 and fp8fma)
+// CHECK-UNKNOWN: 647fcfff <unknown>
+
+//
+// FMLALLBT instructions
+//
+// fmlallbt - group
+
+fmlallbt z0.s, z0.b, z0.b  // 01100100-00100000-10011000-00000000
+// CHECK-INST: fmlallbt z0.s, z0.b, z0.b
+// CHECK-ENCODING: [0x00,0x98,0x20,0x64]
+// CHECK-ERROR: instruction requires: ssve-fp8fma or (sve2 and fp8fma)
+// CHECK-UNKNOWN: 64209800 <unknown>
+
+movprfx z23, z31
+fmlallbt z23.s, z13.b, z8.b  // 01100100-00101000-10011001-10110111
+// CHECK-INST:  movprfx z23, z31
+// CHECK-INST: fmlallbt z23.s, z13.b, z8.b
+// CHECK-ENCODING: [0xb7,0x99,0x28,0x64]
+// CHECK-ERROR: instruction requires: ssve-fp8fma or (sve2 and fp8fma)
+// CHECK-UNKNOWN: 642899b7 <unknown>
+
+fmlallbt z31.s, z31.b, z31.b  // 01100100-00111111-10011011-11111111
+// CHECK-INST: fmlallbt z31.s, z31.b, z31.b
+// CHECK-ENCODING: [0xff,0x9b,0x3f,0x64]
+// CHECK-ERROR: instruction requires: ssve-fp8fma or (sve2 and fp8fma)
+// CHECK-UNKNOWN: 643f9bff <unknown>
+
+//--------------------------------------------//
+//
+// FMLALLTB instructions
+//
+// fmlalltb - indexed
+
+fmlalltb z0.s, z0.b, z0.b[0]  // 01100100-10100000-11000000-00000000
+// CHECK-INST: fmlalltb z0.s, z0.b, z0.b[0]
+// CHECK-ENCODING: [0x00,0xc0,0xa0,0x64]
+// CHECK-ERROR: instruction requires: ssve-fp8fma or (sve2 and fp8fma)
+// CHECK-UNKNOWN: 64a0c000 <unknown>
+
+movprfx z23, z31
+fmlalltb z23.s, z13.b, z0.b[7]  // 01100100-10101000-11001101-10110111
+// CHECK-INST:  movprfx z23, z31
+// CHECK-INST: fmlalltb z23.s, z13.b, z0.b[7]
+// CHECK-ENCODING: [0xb7,0xcd,0xa8,0x64]
+// CHECK-ERROR: instruction requires: ssve-fp8fma or (sve2 and fp8fma)
+// CHECK-UNKNOWN: 64a8cdb7 <unknown>
+
+fmlalltb z31.s, z31.b, z7.b[15]  // 01100100-10111111-11001111-11111111
+// CHECK-INST: fmlalltb z31.s, z31.b, z7.b[15]
+// CHECK-ENCODING: [0xff,0xcf,0xbf,0x64]
+// CHECK-ERROR: instruction requires: ssve-fp8fma or (sve2 and fp8fma)
+// CHECK-UNKNOWN: 64bfcfff <unknown>
+
+//
+// FMLALLTB instructions
+//
+// fmlalltb - group
+
+fmlalltb z0.s, z0.b, z0.b  // 01100100-00100000-10101000-00000000
+// CHECK-INST: fmlalltb z0.s, z0.b, z0.b
+// CHECK-ENCODING: [0x00,0xa8,0x20,0x64]
+// CHECK-ERROR: instruction requires: ssve-fp8fma or (sve2 and fp8fma)
+// CHECK-UNKNOWN: 6420a800 <unknown>
+
+movprfx z23, z31
+fmlalltb z23.s, z13.b, z8.b  // 01100100-00101000-10101001-10110111
+// CHECK-INST:  movprfx z23, z31
+// CHECK-INST: fmlalltb z23.s, z13.b, z8.b
+// CHECK-ENCODING: [0xb7,0xa9,0x28,0x64]
+// CHECK-ERROR: instruction requires: ssve-fp8fma or (sve2 and fp8fma)
+// CHECK-UNKNOWN: 6428a9b7 <unknown>
+
+fmlalltb z31.s, z31.b, z31.b  // 01100100-00111111-10101011-11111111
+// CHECK-INST: fmlalltb z31.s, z31.b, z31.b
+// CHECK-ENCODING: [0xff,0xab,0x3f,0x64]
+// CHECK-ERROR: instruction requires: ssve-fp8fma or (sve2 and fp8fma)
+// CHECK-UNKNOWN: 643fabff <unknown>
+
+
+//--------------------------------------------//
+//
+// FMLALLTT instructions
+//
+// fmlalltt - indexed
+
+fmlalltt z0.s, z0.b, z0.b[0]  // 01100100-11100000-11000000-00000000
+// CHECK-INST: fmlalltt z0.s, z0.b, z0.b[0]
+// CHECK-ENCODING: [0x00,0xc0,0xe0,0x64]
+// CHECK-ERROR: instruction requires: ssve-fp8fma or (sve2 and fp8fma)
+// CHECK-UNKNOWN: 64e0c000 <unknown>
+
+movprfx z23, z31
+fmlalltt z23.s, z13.b, z0.b[7]  // 01100100-11101000-11001101-10110111
+// CHECK-INST:  movprfx z23, z31
+// CHECK-INST: fmlalltt z23.s, z13.b, z0.b[7]
+// CHECK-ENCODING: [0xb7,0xcd,0xe8,0x64]
+// CHECK-ERROR: instruction requires: ssve-fp8fma or (sve2 and fp8fma)
+// CHECK-UNKNOWN: 64e8cdb7 <unknown>
+
+fmlalltt z31.s, z31.b, z7.b[15]  // 01100100-11111111-11001111-11111111
+// CHECK-INST: fmlalltt z31.s, z31.b, z7.b[15]
+// CHECK-ENCODING: [0xff,0xcf,0xff,0x64]
+// CHECK-ERROR: instruction requires: ssve-fp8fma or (sve2 and fp8fma)
+// CHECK-UNKNOWN: 64ffcfff <unknown>
+
+
+//
+// FMLALLTT instructions
+//
+// fmlalltt - group
+
+fmlalltt z0.s, z0.b, z0.b  // 01100100-00100000-10111000-00000000
+// CHECK-INST: fmlalltt z0.s, z0.b, z0.b
+// CHECK-ENCODING: [0x00,0xb8,0x20,0x64]
+// CHECK-ERROR: instruction requires: ssve-fp8fma or (sve2 and fp8fma)
+// CHECK-UNKNOWN: 6420b800 <unknown>
+
+movprfx z23, z31
+fmlalltt z23.s, z13.b, z8.b  // 01100100-00101000-10111001-10110111
+// CHECK-INST:  movprfx z23, z31
+// CHECK-INST: fmlalltt z23.s, z13.b, z8.b
+// CHECK-ENCODING: [0xb7,0xb9,0x28,0x64]
+// CHECK-ERROR: instruction requires: ssve-fp8fma or (sve2 and fp8fma)
+// CHECK-UNKNOWN: 6428b9b7 <unknown>
+
+fmlalltt z31.s, z31.b, z31.b  // 01100100-00111111-10111011-11111111
+// CHECK-INST: fmlalltt z31.s, z31.b, z31.b
+// CHECK-ENCODING: [0xff,0xbb,0x3f,0x64]
+// CHECK-ERROR: instruction requires: ssve-fp8fma or (sve2 and fp8fma)
+// CHECK-UNKNOWN: 643fbbff <unknown>
diff --git a/llvm/unittests/TargetParser/TargetParserTest.cpp b/llvm/unittests/TargetParser/TargetParserTest.cpp
index b432e7ac2d86871..732c68190bb39b9 100644
--- a/llvm/unittests/TargetParser/TargetParserTest.cpp
+++ b/llvm/unittests/TargetParser/TargetParserTest.cpp
@@ -1713,26 +1713,26 @@ TEST(TargetParserTest, testAArch64Extension) {
 
 TEST(TargetParserTest, AArch64ExtensionFeatures) {
   std::vector<uint64_t> Extensions = {
-      AArch64::AEK_CRC,     AArch64::AEK_LSE,       AArch64::AEK_RDM,
-      AArch64::AEK_CRYPTO,  AArch64::AEK_SM4,       AArch64::AEK_SHA3,
-      AArch64::AEK_SHA2,    AArch64::AEK_AES,       AArch64::AEK_DOTPROD,
-      AArch64::AEK_FP,      AArch64::AEK_SIMD,      AArch64::AEK_FP16,
-      AArch64::AEK_FP16FML, AArch64::AEK_PROFILE,   AArch64::AEK_RAS,
-      AArch64::AEK_SVE,     AArch64::AEK_SVE2,      AArch64::AEK_SVE2AES,
-      AArch64::AEK_SVE2SM4, AArch64::AEK_SVE2SHA3,  AArch64::AEK_SVE2BITPERM,
-      AArch64::AEK_RCPC,    AArch64::AEK_RAND,      AArch64::AEK_MTE,
-      AArch64::AEK_SSBS,    AArch64::AEK_SB,        AArch64::AEK_PREDRES,
-      AArch64::AEK_BF16,    AArch64::AEK_I8MM,      AArch64::AEK_F32MM,
-      AArch64::AEK_F64MM,   AArch64::AEK_TME,       AArch64::AEK_LS64,
-      AArch64::AEK_BRBE,    AArch64::AEK_PAUTH,     AArch64::AEK_FLAGM,
-      AArch64::AEK_SME,     AArch64::AEK_SMEF64F64, AArch64::AEK_SMEI16I64,
-      AArch64::AEK_SME2,    AArch64::AEK_HBC,       AArch64::AEK_MOPS,
-      AArch64::AEK_PERFMON, AArch64::AEK_SVE2p1,    AArch64::AEK_SME2p1,
-      AArch64::AEK_B16B16,  AArch64::AEK_SMEF16F16, AArch64::AEK_CSSC,
-      AArch64::AEK_RCPC3,   AArch64::AEK_THE,       AArch64::AEK_D128,
-      AArch64::AEK_LSE128,  AArch64::AEK_SPECRES2,  AArch64::AEK_RASv2,
-      AArch64::AEK_ITE,     AArch64::AEK_GCS,       AArch64::AEK_FPMR,
-  };
+      AArch64::AEK_CRC,     AArch64::AEK_LSE,        AArch64::AEK_RDM,
+      AArch64::AEK_CRYPTO,  AArch64::AEK_SM4,        AArch64::AEK_SHA3,
+      AArch64::AEK_SHA2,    AArch64::AEK_AES,        AArch64::AEK_DOTPROD,
+      AArch64::AEK_FP,      AArch64::AEK_SIMD,       AArch64::AEK_FP16,
+      AArch64::AEK_FP16FML, AArch64::AEK_PROFILE,    AArch64::AEK_RAS,
+      AArch64::AEK_SVE,     AArch64::AEK_SVE2,       AArch64::AEK_SVE2AES,
+      AArch64::AEK_SVE2SM4, AArch64::AEK_SVE2SHA3,   AArch64::AEK_SVE2BITPERM,
+      AArch64::AEK_RCPC,    AArch64::AEK_RAND,       AArch64::AEK_MTE,
+      AArch64::AEK_SSBS,    AArch64::AEK_SB,         AArch64::AEK_PREDRES,
+      AArch64::AEK_BF16,    AArch64::AEK_I8MM,       AArch64::AEK_F32MM,
+      AArch64::AEK_F64MM,   AArch64::AEK_TME,        AArch64::AEK_LS64,
+      AArch64::AEK_BRBE,    AArch64::AEK_PAUTH,      AArch64::AEK_FLAGM,
+      AArch64::AEK_SME,     AArch64::AEK_SMEF64F64,  AArch64::AEK_SMEI16I64,
+      AArch64::AEK_SME2,    AArch64::AEK_HBC,        AArch64::AEK_MOPS,
+      AArch64::AEK_PERFMON, AArch64::AEK_SVE2p1,     AArch64::AEK_SME2p1,
+      AArch64::AEK_B16B16,  AArch64::AEK_SMEF16F16,  AArch64::AEK_CSSC,
+      AArch64::AEK_RCPC3,   AArch64::AEK_THE,        AArch64::AEK_D128,
+      AArch64::AEK_LSE128,  AArch64::AEK_SPECRES2,   AArch64::AEK_RASv2,
+      AArch64::AEK_ITE,     AArch64::AEK_GCS,        AArch64::AEK_FPMR,
+      AArch64::AEK_FP8FMA,  AArch64::AEK_SSVE_FP8FMA};
 
   std::vector<StringRef> Features;
 
@@ -1805,6 +1805,8 @@ TEST(TargetParserTest, AArch64ExtensionFeatures) {
   EXPECT_TRUE(llvm::is_contained(Features, "+ite"));
   EXPECT_TRUE(llvm::is_contained(Features, "+gcs"));
   EXPECT_TRUE(llvm::is_contained(Features, "+fpmr"));
+  EXPECT_TRUE(llvm::is_contained(Features, "+fp8fma"));
+  EXPECT_TRUE(llvm::is_contained(Features, "+ssve-fp8fma"));
 
   // Assuming we listed every extension above, this should produce the same
   // result. (note that AEK_NONE doesn't have a name so it won't be in the
@@ -1929,6 +1931,8 @@ TEST(TargetParserTest, AArch64ArchExtFeature) {
       {"rasv2", "norasv2", "+rasv2", "-rasv2"},
       {"gcs", "nogcs", "+gcs", "-gcs"},
       {"fpmr", "nofpmr", "+fpmr", "-fpmr"},
+      {"fp8fma", "nofp8fma", "+fp8fma", "-fp8fma"},
+      {"ssve-fp8fma", "nossve-fp8fma", "+ssve-fp8fma", "-ssve-fp8fma"},
   };
 
   for (unsigned i = 0; i < std::size(ArchExt); i++) {



More information about the llvm-commits mailing list