Skip to content

[LLVM][AArch64] Add assembly/disassembly for MUL/BFMUL SME instructions #113535

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 2 commits into from
Oct 29, 2024

Conversation

CarolineConcatto
Copy link
Contributor

According to https://developer.arm.com/documentation/ddi0602

Co-authored-by: Momchil-Velikov [email protected]

@llvmbot llvmbot added backend:AArch64 mc Machine (object) code labels Oct 24, 2024
@llvmbot
Copy link
Member

llvmbot commented Oct 24, 2024

@llvm/pr-subscribers-backend-aarch64

Author: None (CarolineConcatto)

Changes

According to https://developer.arm.com/documentation/ddi0602

Co-authored-by: Momchil-Velikov [email protected]


Patch is 32.76 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/113535.diff

7 Files Affected:

  • (modified) llvm/lib/Target/AArch64/AArch64.td (+7-2)
  • (modified) llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td (+10)
  • (modified) llvm/lib/Target/AArch64/SMEInstrFormats.td (+110)
  • (added) llvm/test/MC/AArch64/SME2/bfmul-diagnostics.s (+111)
  • (added) llvm/test/MC/AArch64/SME2/bfmul.s (+92)
  • (added) llvm/test/MC/AArch64/SME2/fmul-diagnostics.s (+112)
  • (added) llvm/test/MC/AArch64/SME2/fmul.s (+261)
diff --git a/llvm/lib/Target/AArch64/AArch64.td b/llvm/lib/Target/AArch64/AArch64.td
index 2262ad1dfd0cc9..56ffa10774047f 100644
--- a/llvm/lib/Target/AArch64/AArch64.td
+++ b/llvm/lib/Target/AArch64/AArch64.td
@@ -73,8 +73,13 @@ def SVEUnsupported : AArch64Unsupported {
                       SVE2Unsupported.F);
 }
 
-let F = [HasSME2p1, HasSVE2p1_or_HasSME2p1, HasSVE2p1orSSVE_AES] in
-def SME2p1Unsupported : AArch64Unsupported;
+let F = [HasSME2p2] in
+def SME2p2Unsupported : AArch64Unsupported;
+
+def SME2p1Unsupported : AArch64Unsupported {
+  let F = !listconcat([HasSME2p1, HasSVE2p1_or_HasSME2p1, HasSVE2p1orSSVE_AES],
+                      SME2p2Unsupported.F);
+}
 
 def SME2Unsupported : AArch64Unsupported {
   let F = !listconcat([HasSME2, HasSVE2orSME2, HasSVE2p1_or_HasSME2, HasSSVE_FP8FMA,
diff --git a/llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td
index 6044b5bb7d8151..5c20f23160ea36 100644
--- a/llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td
@@ -1004,6 +1004,11 @@ let Predicates = [HasSME2p2] in {
   def FTMOPA_M2ZZZI_HtoS  : sme_tmopa_32b<0b11000, ZZ_h_mul_r, ZPR16, "ftmopa">;
   def FTMOPA_M2ZZZI_StoS  : sme_tmopa_32b<0b00000, ZZ_s_mul_r, ZPR32, "ftmopa">;
   def BFTMOPA_M2ZZZI_HtoS : sme_tmopa_32b<0b10000, ZZ_h_mul_r, ZPR16, "bftmopa">;
+
+  defm FMUL_2ZZ  : sme2_multi2_fmul_sm<"fmul">;
+  defm FMUL_2Z2Z : sme2_multi2_fmul_mm< "fmul">;
+  defm FMUL_4ZZ  : sme2_multi4_fmul_sm<"fmul">;
+  defm FMUL_4Z4Z : sme2_multi4_fmul_mm< "fmul">;
 } // [HasSME2p2]
 
 let Predicates = [HasSME2p2, HasSMEB16B16] in {
@@ -1021,3 +1026,8 @@ let Predicates = [HasSME2p2, HasSMEF8F16], Uses = [FPMR, FPCR] in {
 let Predicates = [HasSME2p2, HasSMEF16F16] in {
   def FTMOPA_M2ZZZI_HtoH : sme_tmopa_16b<0b10001, ZZ_h_mul_r, ZPR16, "ftmopa">;
 } // [HasSME2p2, HasSMEF16F16]
+
+let Predicates = [HasSME2, HasSVEBFSCALE] in {
+  defm BFMUL : sme2_bfmul_single<"bfmul">;
+  defm BFMUL : sme2_bfmul_multi<"bfmul">;
+} //[HasSME2, HasSVEBFSCALE]
diff --git a/llvm/lib/Target/AArch64/SMEInstrFormats.td b/llvm/lib/Target/AArch64/SMEInstrFormats.td
index 08929ed5616b2c..febb956e06982c 100644
--- a/llvm/lib/Target/AArch64/SMEInstrFormats.td
+++ b/llvm/lib/Target/AArch64/SMEInstrFormats.td
@@ -5188,3 +5188,113 @@ class sme2_luti4_vector_vg4_strided<bits<2> sz, bits<2> op, string mnemonic>
   let Inst{3-2}   = 0b00;
   let Inst{1-0}   = Zd{1-0};
 }
+
+class sme2_multi2_fmul_sm<bits<2> size, string mnemonic, RegisterOperand vector_ty, RegisterOperand zpr_ty>
+    : I<(outs vector_ty:$Zd), (ins vector_ty:$Zn, zpr_ty:$Zm),
+        mnemonic, "\t$Zd, $Zn, $Zm",
+        "", []>, Sched<[]> {
+  bits<4> Zd;
+  bits<4> Zn;
+  bits<4> Zm;
+
+  let Inst{31-24} = 0b11000001;
+  let Inst{23-22} = size;
+  let Inst{21}    = 0b1;
+  let Inst{20-17} = Zm;
+  let Inst{16-10} = 0b0111010;
+  let Inst{9-6}   = Zn;
+  let Inst{5}     = 0b0;
+  let Inst{4-1}   = Zd;
+  let Inst{0}     = 0b0;
+}
+
+multiclass sme2_multi2_fmul_sm<string mnemonic> {
+  def _H : sme2_multi2_fmul_sm<0b01, mnemonic, ZZ_h_mul_r, ZPR4b16>;
+  def _S : sme2_multi2_fmul_sm<0b10, mnemonic, ZZ_s_mul_r, ZPR4b32>;
+  def _D : sme2_multi2_fmul_sm<0b11, mnemonic, ZZ_d_mul_r, ZPR4b64>;
+}
+
+class sme2_multi4_fmul_sm<bits<2> size, string mnemonic, RegisterOperand vector_ty, RegisterOperand zpr_ty>
+    : I<(outs vector_ty:$Zd), (ins vector_ty:$Zn, zpr_ty:$Zm),
+        mnemonic, "\t$Zd, $Zn, $Zm",
+        "", []>, Sched<[]> {
+  bits<3> Zd;
+  bits<3> Zn;
+  bits<4> Zm;
+
+  let Inst{31-24} = 0b11000001;
+  let Inst{23-22} = size;
+  let Inst{21}    = 0b1;
+  let Inst{20-17} = Zm;
+  let Inst{16-10} = 0b1111010;
+  let Inst{9-7}   = Zn;
+  let Inst{6-5}   = 0b00;
+  let Inst{4-2}   = Zd;
+  let Inst{1-0}   = 0b00;
+}
+
+multiclass sme2_multi4_fmul_sm<string mnemonic> {
+  def _H : sme2_multi4_fmul_sm<0b01, mnemonic, ZZZZ_h_mul_r, ZPR4b16>;
+  def _S : sme2_multi4_fmul_sm<0b10, mnemonic, ZZZZ_s_mul_r, ZPR4b32>;
+  def _D : sme2_multi4_fmul_sm<0b11, mnemonic, ZZZZ_d_mul_r, ZPR4b64>;
+}
+
+multiclass sme2_bfmul_single<string mnemonic> {
+  def _2ZZ  : sme2_multi2_fmul_sm<0b00, mnemonic, ZZ_h_mul_r,   ZPR4b16>;
+  def _4ZZ  : sme2_multi4_fmul_sm<0b00, mnemonic, ZZZZ_h_mul_r, ZPR4b16>;
+}
+
+class sme2_multi2_fmul_mm<bits<2> size, string mnemonic, RegisterOperand vector_ty>
+    : I<(outs vector_ty:$Zd), (ins vector_ty:$Zn, vector_ty:$Zm),
+        mnemonic, "\t$Zd, $Zn, $Zm",
+        "", []>, Sched<[]> {
+  bits<4> Zd;
+  bits<4> Zn;
+  bits<4> Zm;
+
+  let Inst{31-24} = 0b11000001;
+  let Inst{23-22} = size;
+  let Inst{21}    = 0b1;
+  let Inst{20-17} = Zm;
+  let Inst{16-10} = 0b0111001;
+  let Inst{9-6}   = Zn;
+  let Inst{5}     = 0b0;
+  let Inst{4-1}   = Zd;
+  let Inst{0}     = 0b0;
+}
+
+multiclass sme2_multi2_fmul_mm<string mnemonic> {
+  def _H : sme2_multi2_fmul_mm<0b01, mnemonic, ZZ_h_mul_r>;
+  def _S : sme2_multi2_fmul_mm<0b10, mnemonic, ZZ_s_mul_r>;
+  def _D : sme2_multi2_fmul_mm<0b11, mnemonic, ZZ_d_mul_r>;
+}
+
+class sme2_multi4_fmul_mm<bits<2> size, string mnemonic, RegisterOperand vector_ty>
+    : I<(outs vector_ty:$Zd), (ins vector_ty:$Zn, vector_ty:$Zm),
+        mnemonic, "\t$Zd, $Zn, $Zm",
+        "", []>, Sched<[]> {
+  bits<3> Zd;
+  bits<3> Zn;
+  bits<3> Zm;
+
+  let Inst{31-24} = 0b11000001;
+  let Inst{23-22} = size;
+  let Inst{21}    = 0b1;
+  let Inst{20-18} = Zm;
+  let Inst{17-10} = 0b01111001;
+  let Inst{9-7}   = Zn;
+  let Inst{6-5}   = 0b00;
+  let Inst{4-2}   = Zd;
+  let Inst{1-0}   = 0b00;
+}
+
+multiclass sme2_multi4_fmul_mm<string mnemonic> {
+  def _H : sme2_multi4_fmul_mm<0b01, mnemonic, ZZZZ_h_mul_r>;
+  def _S : sme2_multi4_fmul_mm<0b10, mnemonic, ZZZZ_s_mul_r>;
+  def _D : sme2_multi4_fmul_mm<0b11, mnemonic, ZZZZ_d_mul_r>;
+}
+
+multiclass sme2_bfmul_multi<string mnemonic> {
+  def _2Z2Z : sme2_multi2_fmul_mm<0b00, mnemonic, ZZ_h_mul_r>;
+  def _4Z4Z : sme2_multi4_fmul_mm<0b00, mnemonic, ZZZZ_h_mul_r>;
+}
diff --git a/llvm/test/MC/AArch64/SME2/bfmul-diagnostics.s b/llvm/test/MC/AArch64/SME2/bfmul-diagnostics.s
new file mode 100644
index 00000000000000..c28cc5cd426dda
--- /dev/null
+++ b/llvm/test/MC/AArch64/SME2/bfmul-diagnostics.s
@@ -0,0 +1,111 @@
+// RUN: not llvm-mc -triple=aarch64 -mattr=+sme2,+sve-bfscale 2>&1 < %s| FileCheck %s
+
+// Multiple and single, 2 regs
+
+bfmul   {z0.s-z1.s}, {z0.h-z1.h}, z0.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+bfmul   {z1.h-z2.h}, {z0.h-z1.h}, z0.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid vector list, expected list with 2 consecutive SVE vectors, where the first vector is a multiple of 2 and with matching element types
+
+bfmul   {z0.h-z2.h}, {z0.h-z1.h}, z0.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+bfmul   {z0.h-z1.h}, {z0.s-z1.s}, z0.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+bfmul   {z0.h-z1.h}, {z1.h-z2.h}, z0.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid vector list, expected list with 2 consecutive SVE vectors, where the first vector is a multiple of 2 and with matching element types
+
+bfmul   {z0.h-z1.h}, {z0.h-z2.h}, z0.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+bfmul   {z0.h-z1.h}, {z0.h-z1.h}, z0.s
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid restricted vector register, expected z0.h..z15.h
+
+bfmul   {z0.h-z1.h}, {z0.h-z1.h}, z16.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid restricted vector register, expected z0.h..z15.h
+
+// Multiple and single, 4 regs
+
+bfmul   {z0.s-z3.s}, {z0.h-z3.h}, z0.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+bfmul   {z1.h-z4.h}, {z0.h-z3.h}, z0.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid vector list, expected list with 4 consecutive SVE vectors, where the first vector is a multiple of 4 and with matching element types
+
+bfmul   {z0.h-z4.h}, {z0.h-z3.h}, z0.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid number of vectors
+
+bfmul   {z0.h-z3.h}, {z0.s-z3.s}, z0.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+bfmul   {z0.h-z3.h}, {z1.h-z4.h}, z0.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid vector list, expected list with 4 consecutive SVE vectors, where the first vector is a multiple of 4 and with matching element types
+
+bfmul   {z0.h-z3.h}, {z0.h-z4.h}, z0.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid number of vectors
+
+bfmul   {z0.h-z3.h}, {z0.h-z3.h}, z0.s
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid restricted vector register, expected z0.h..z15.h
+
+bfmul   {z0.h-z3.h}, {z0.h-z3.h}, z16.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid restricted vector register, expected z0.h..z15.h
+
+// Multiple, 2 regs
+
+bfmul   {z0.s-z1.s}, {z0.h-z1.h}, {z0.h-z1.h}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+bfmul   {z1.h-z2.h}, {z0.h-z1.h}, {z0.h-z1.h}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid vector list, expected list with 2 consecutive SVE vectors, where the first vector is a multiple of 2 and with matching element types
+
+bfmul   {z0.h-z2.h}, {z0.h-z1.h}, {z0.h-z1.h}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+bfmul   {z0.h-z1.h}, {z0.s-z1.s}, {z0.h-z1.h}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+bfmul   {z0.h-z1.h}, {z1.h-z2.h}, {z0.h-z1.h}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid vector list, expected list with 2 consecutive SVE vectors, where the first vector is a multiple of 2 and with matching element types
+
+bfmul   {z0.h-z1.h}, {z0.h-z2.h}, {z0.h-z1.h}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+bfmul   {z0.h-z1.h}, {z0.h-z1.h}, {z0.s-z1.s}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+bfmul   {z0.h-z1.h}, {z0.h-z1.h}, {z1.h-z2.h}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid vector list, expected list with 2 consecutive SVE vectors, where the first vector is a multiple of 2 and with matching element types
+
+bfmul   {z0.h-z1.h}, {z0.h-z1.h}, {z0.h-z2.h}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+// Multiple, 4 regs
+
+bfmul   {z0.s-z3.s}, {z0.h-z3.h}, {z0.h-z3.h}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+bfmul   {z1.h-z4.h}, {z0.h-z3.h}, {z0.h-z3.h}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid vector list, expected list with 4 consecutive SVE vectors, where the first vector is a multiple of 4 and with matching element types
+
+bfmul   {z0.h-z4.h}, {z0.h-z3.h}, {z0.h-z3.h}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid number of vectors
+
+bfmul   {z0.h-z3.h}, {z0.s-z3.s}, {z0.h-z3.h}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+bfmul   {z0.h-z3.h}, {z1.h-z4.h}, {z0.h-z3.h}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid vector list, expected list with 4 consecutive SVE vectors, where the first vector is a multiple of 4 and with matching element types
+
+bfmul   {z0.h-z3.h}, {z0.h-z4.h}, {z0.h-z3.h}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid number of vectors
+
+bfmul   {z0.h-z3.h}, {z0.h-z3.h}, {z0.s-z3.s}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+bfmul   {z0.h-z3.h}, {z0.h-z3.h}, {z1.h-z4.h}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid vector list, expected list with 4 consecutive SVE vectors, where the first vector is a multiple of 4 and with matching element types
+
+bfmul   {z0.h-z3.h}, {z0.h-z3.h}, {z0.h-z4.h}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid number of vectors
diff --git a/llvm/test/MC/AArch64/SME2/bfmul.s b/llvm/test/MC/AArch64/SME2/bfmul.s
new file mode 100644
index 00000000000000..10a43848c73819
--- /dev/null
+++ b/llvm/test/MC/AArch64/SME2/bfmul.s
@@ -0,0 +1,92 @@
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sme2,+sve-bfscale < %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=+sme2,+sve-bfscale < %s \
+// RUN:        | llvm-objdump -d --mattr=+sme2,+sve-bfscale - | FileCheck %s --check-prefix=CHECK-INST
+// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sme2,+sve-bfscale < %s \
+// RUN:        | llvm-objdump -d --mattr=-sme2 - | FileCheck %s --check-prefix=CHECK-UNKNOWN
+// Disassemble encoding and check the re-encoding (-show-encoding) matches.
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sme2,+sve-bfscale < %s \
+// RUN:        | sed '/.text/d' | sed 's/.*encoding: //g' \
+// RUN:        | llvm-mc -triple=aarch64 -mattr=+sme2,+sve-bfscale -disassemble -show-encoding \
+// RUN:        | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+
+// Multiple and single, 2 regs
+
+bfmul   {z0.h-z1.h}, {z0.h-z1.h}, z0.h  // 11000001-00100000-11101000-00000000
+// CHECK-INST: bfmul   { z0.h, z1.h }, { z0.h, z1.h }, z0.h
+// CHECK-ENCODING: [0x00,0xe8,0x20,0xc1]
+// CHECK-ERROR: instruction requires: sme2 sve-bfscale
+// CHECK-UNKNOWN: c120e800 <unknown>
+
+bfmul   {z20.h-z21.h}, {z10.h-z11.h}, z10.h  // 11000001-00110100-11101001-01010100
+// CHECK-INST: bfmul   { z20.h, z21.h }, { z10.h, z11.h }, z10.h
+// CHECK-ENCODING: [0x54,0xe9,0x34,0xc1]
+// CHECK-ERROR: instruction requires: sme2 sve-bfscale
+// CHECK-UNKNOWN: c134e954 <unknown>
+
+bfmul   {z30.h-z31.h}, {z30.h-z31.h}, z15.h  // 11000001-00111110-11101011-11011110
+// CHECK-INST: bfmul   { z30.h, z31.h }, { z30.h, z31.h }, z15.h
+// CHECK-ENCODING: [0xde,0xeb,0x3e,0xc1]
+// CHECK-ERROR: instruction requires: sme2 sve-bfscale
+// CHECK-UNKNOWN: c13eebde <unknown>
+
+// Multiple and single, 4 regs
+
+bfmul   {z0.h-z3.h}, {z0.h-z3.h}, z0.h  // 11000001-00100001-11101000-00000000
+// CHECK-INST: bfmul   { z0.h - z3.h }, { z0.h - z3.h }, z0.h
+// CHECK-ENCODING: [0x00,0xe8,0x21,0xc1]
+// CHECK-ERROR: instruction requires: sme2 sve-bfscale
+// CHECK-UNKNOWN: c121e800 <unknown>
+
+bfmul   {z20.h-z23.h}, {z8.h-z11.h}, z10.h  // 11000001-00110101-11101001-00010100
+// CHECK-INST: bfmul   { z20.h - z23.h }, { z8.h - z11.h }, z10.h
+// CHECK-ENCODING: [0x14,0xe9,0x35,0xc1]
+// CHECK-ERROR: instruction requires: sme2 sve-bfscale
+// CHECK-UNKNOWN: c135e914 <unknown>
+
+bfmul   {z28.h-z31.h}, {z28.h-z31.h}, z15.h  // 11000001-00111111-11101011-10011100
+// CHECK-INST: bfmul   { z28.h - z31.h }, { z28.h - z31.h }, z15.h
+// CHECK-ENCODING: [0x9c,0xeb,0x3f,0xc1]
+// CHECK-ERROR: instruction requires: sme2 sve-bfscale
+// CHECK-UNKNOWN: c13feb9c <unknown>
+
+// Multiple, 2 regs
+bfmul   {z0.h-z1.h}, {z0.h-z1.h}, {z0.h-z1.h}  // 11000001-00100000-11100100-00000000
+// CHECK-INST: bfmul   { z0.h, z1.h }, { z0.h, z1.h }, { z0.h, z1.h }
+// CHECK-ENCODING: [0x00,0xe4,0x20,0xc1]
+// CHECK-ERROR: instruction requires: sme2 sve-bfscale
+// CHECK-UNKNOWN: c120e400 <unknown>
+
+bfmul   {z20.h-z21.h}, {z10.h-z11.h}, {z20.h-z21.h}  // 11000001-00110100-11100101-01010100
+// CHECK-INST: bfmul   { z20.h, z21.h }, { z10.h, z11.h }, { z20.h, z21.h }
+// CHECK-ENCODING: [0x54,0xe5,0x34,0xc1]
+// CHECK-ERROR: instruction requires: sme2 sve-bfscale
+// CHECK-UNKNOWN: c134e554 <unknown>
+
+bfmul   {z30.h-z31.h}, {z30.h-z31.h}, {z30.h-z31.h}  // 11000001-00111110-11100111-11011110
+// CHECK-INST: bfmul   { z30.h, z31.h }, { z30.h, z31.h }, { z30.h, z31.h }
+// CHECK-ENCODING: [0xde,0xe7,0x3e,0xc1]
+// CHECK-ERROR: instruction requires: sme2 sve-bfscale
+// CHECK-UNKNOWN: c13ee7de <unknown>
+
+// Multiple, 4 regs
+
+bfmul   {z0.h-z3.h}, {z0.h-z3.h}, {z0.h-z3.h}  // 11000001-00100001-11100100-00000000
+// CHECK-INST: bfmul   { z0.h - z3.h }, { z0.h - z3.h }, { z0.h - z3.h }
+// CHECK-ENCODING: [0x00,0xe4,0x21,0xc1]
+// CHECK-ERROR: instruction requires: sme2 sve-bfscale
+// CHECK-UNKNOWN: c121e400 <unknown>
+
+bfmul   {z20.h-z23.h}, {z8.h-z11.h}, {z20.h-z23.h}  // 11000001-00110101-11100101-00010100
+// CHECK-INST: bfmul   { z20.h - z23.h }, { z8.h - z11.h }, { z20.h - z23.h }
+// CHECK-ENCODING: [0x14,0xe5,0x35,0xc1]
+// CHECK-ERROR: instruction requires: sme2 sve-bfscale
+// CHECK-UNKNOWN: c135e514 <unknown>
+
+bfmul   {z28.h-z31.h}, {z28.h-z31.h}, {z28.h-z31.h}  // 11000001-00111101-11100111-10011100
+// CHECK-INST: bfmul   { z28.h - z31.h }, { z28.h - z31.h }, { z28.h - z31.h }
+// CHECK-ENCODING: [0x9c,0xe7,0x3d,0xc1]
+// CHECK-ERROR: instruction requires: sme2 sve-bfscale
+// CHECK-UNKNOWN: c13de79c <unknown>
diff --git a/llvm/test/MC/AArch64/SME2/fmul-diagnostics.s b/llvm/test/MC/AArch64/SME2/fmul-diagnostics.s
new file mode 100644
index 00000000000000..2fdd3f82adc1dd
--- /dev/null
+++ b/llvm/test/MC/AArch64/SME2/fmul-diagnostics.s
@@ -0,0 +1,112 @@
+
+// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sme2p2 2>&1 < %s| FileCheck %s
+
+// Multiple and single, 2 regs
+
+fmul    {z0.b-z1.b}, {z0.h-z1.h}, z0.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+fmul    {z1.s-z2.s}, {z0.s-z1.s}, z0.s
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid vector list, expected list with 2 consecutive SVE vectors, where the first vector is a multiple of 2 and with matching element types
+
+fmul    {z0.d-z2.d}, {z0.d-z1.d}, z0.d
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+fmul    {z0.h-z1.h}, {z0.b-z1.b}, z0.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+fmul    {z0.s-z1.s}, {z1.s-z2.s}, z0.s
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid vector list, expected list with 2 consecutive SVE vectors, where the first vector is a multiple of 2 and with matching element types
+
+fmul    {z0.d-z1.d}, {z0.d-z2.d}, z0.d
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+fmul    {z0.h-z1.h}, {z0.h-z1.h}, z0.b
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid restricted vector register, expected z0.h..z15.h
+
+fmul    {z0.s-z1.s}, {z0.s-z1.s}, z16.s
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid restricted vector register, expected z0.s..z15.s
+
+// Multiple and single, 4 regs
+
+fmul    {z0.b-z3.b}, {z0.h-z3.h}, z0.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+fmul    {z1.s-z3.s}, {z0.h-z3.h}, z0.s
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+fmul    {z0.d-z4.d}, {z0.d-z3.d}, z0.d
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid number of vectors
+
+fmul    {z0.h-z3.h}, {z0.b-z3.b}, z0.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+fmul    {z0.s-z3.s}, {z1.s-z3.s}, z0.s
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+fmul    {z0.d-z3.d}, {z0.d-z4.d}, z0.d
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid number of vectors
+
+fmul    {z0.h-z3.h}, {z0.h-z3.h}, z0.b
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid restricted vector register, expected z0.h..z15.h
+
+fmul    {z0.s-z3.s}, {z0.s-z3.s}, z16.s
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid restricted vector register, expected z0.s..z15.s
+
+// Multiple, 2 regs
+
+fmul    {z0.b-z1.b}, {z0.h-z1.h}, {z0.h-z1.h}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+fmul    {z1.s-z2.s}, {z0.s-z1.s}, {z0.s-z1.s}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid vector list, expected list with 2 consecutive SVE vectors, where the first vector is a multiple of 2 and with matching element types
+
+fmul    {z0.d-z2.d}, {z0.d-z1.d}, {z0.d-z1.d}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+fmul    {z0.h-z1.h}, {z0.b-z1.b}, {z0.h-z1.h}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+fmul    {z0.s-z1.s}, {z1.s-z2.s}, {z0.s-z1.s}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid vector list, expected list with 2 consecutive SVE vectors, where the first vector is a multiple of 2 and with matching element types
+
+fmul    {z0.d-z1.d}, {z0.d-z2.d}, {z0.d-z1.d}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+fmul    {z0.h-z1.h}, {z0.h-z1.h}, {z0.b-z1.b}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+fmul    {z0.s-z1.s}, {z0.s-z1.s}, {z1.s-z2.s}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid vector list, expected list with 2 consecutive SVE vectors, where the first vector is a multiple of 2 and with matching element types
+
+...
[truncated]

@llvmbot
Copy link
Member

llvmbot commented Oct 24, 2024

@llvm/pr-subscribers-mc

Author: None (CarolineConcatto)

Changes

According to https://developer.arm.com/documentation/ddi0602

Co-authored-by: Momchil-Velikov [email protected]


Patch is 32.76 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/113535.diff

7 Files Affected:

  • (modified) llvm/lib/Target/AArch64/AArch64.td (+7-2)
  • (modified) llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td (+10)
  • (modified) llvm/lib/Target/AArch64/SMEInstrFormats.td (+110)
  • (added) llvm/test/MC/AArch64/SME2/bfmul-diagnostics.s (+111)
  • (added) llvm/test/MC/AArch64/SME2/bfmul.s (+92)
  • (added) llvm/test/MC/AArch64/SME2/fmul-diagnostics.s (+112)
  • (added) llvm/test/MC/AArch64/SME2/fmul.s (+261)
diff --git a/llvm/lib/Target/AArch64/AArch64.td b/llvm/lib/Target/AArch64/AArch64.td
index 2262ad1dfd0cc9..56ffa10774047f 100644
--- a/llvm/lib/Target/AArch64/AArch64.td
+++ b/llvm/lib/Target/AArch64/AArch64.td
@@ -73,8 +73,13 @@ def SVEUnsupported : AArch64Unsupported {
                       SVE2Unsupported.F);
 }
 
-let F = [HasSME2p1, HasSVE2p1_or_HasSME2p1, HasSVE2p1orSSVE_AES] in
-def SME2p1Unsupported : AArch64Unsupported;
+let F = [HasSME2p2] in
+def SME2p2Unsupported : AArch64Unsupported;
+
+def SME2p1Unsupported : AArch64Unsupported {
+  let F = !listconcat([HasSME2p1, HasSVE2p1_or_HasSME2p1, HasSVE2p1orSSVE_AES],
+                      SME2p2Unsupported.F);
+}
 
 def SME2Unsupported : AArch64Unsupported {
   let F = !listconcat([HasSME2, HasSVE2orSME2, HasSVE2p1_or_HasSME2, HasSSVE_FP8FMA,
diff --git a/llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td
index 6044b5bb7d8151..5c20f23160ea36 100644
--- a/llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td
@@ -1004,6 +1004,11 @@ let Predicates = [HasSME2p2] in {
   def FTMOPA_M2ZZZI_HtoS  : sme_tmopa_32b<0b11000, ZZ_h_mul_r, ZPR16, "ftmopa">;
   def FTMOPA_M2ZZZI_StoS  : sme_tmopa_32b<0b00000, ZZ_s_mul_r, ZPR32, "ftmopa">;
   def BFTMOPA_M2ZZZI_HtoS : sme_tmopa_32b<0b10000, ZZ_h_mul_r, ZPR16, "bftmopa">;
+
+  defm FMUL_2ZZ  : sme2_multi2_fmul_sm<"fmul">;
+  defm FMUL_2Z2Z : sme2_multi2_fmul_mm< "fmul">;
+  defm FMUL_4ZZ  : sme2_multi4_fmul_sm<"fmul">;
+  defm FMUL_4Z4Z : sme2_multi4_fmul_mm< "fmul">;
 } // [HasSME2p2]
 
 let Predicates = [HasSME2p2, HasSMEB16B16] in {
@@ -1021,3 +1026,8 @@ let Predicates = [HasSME2p2, HasSMEF8F16], Uses = [FPMR, FPCR] in {
 let Predicates = [HasSME2p2, HasSMEF16F16] in {
   def FTMOPA_M2ZZZI_HtoH : sme_tmopa_16b<0b10001, ZZ_h_mul_r, ZPR16, "ftmopa">;
 } // [HasSME2p2, HasSMEF16F16]
+
+let Predicates = [HasSME2, HasSVEBFSCALE] in {
+  defm BFMUL : sme2_bfmul_single<"bfmul">;
+  defm BFMUL : sme2_bfmul_multi<"bfmul">;
+} //[HasSME2, HasSVEBFSCALE]
diff --git a/llvm/lib/Target/AArch64/SMEInstrFormats.td b/llvm/lib/Target/AArch64/SMEInstrFormats.td
index 08929ed5616b2c..febb956e06982c 100644
--- a/llvm/lib/Target/AArch64/SMEInstrFormats.td
+++ b/llvm/lib/Target/AArch64/SMEInstrFormats.td
@@ -5188,3 +5188,113 @@ class sme2_luti4_vector_vg4_strided<bits<2> sz, bits<2> op, string mnemonic>
   let Inst{3-2}   = 0b00;
   let Inst{1-0}   = Zd{1-0};
 }
+
+class sme2_multi2_fmul_sm<bits<2> size, string mnemonic, RegisterOperand vector_ty, RegisterOperand zpr_ty>
+    : I<(outs vector_ty:$Zd), (ins vector_ty:$Zn, zpr_ty:$Zm),
+        mnemonic, "\t$Zd, $Zn, $Zm",
+        "", []>, Sched<[]> {
+  bits<4> Zd;
+  bits<4> Zn;
+  bits<4> Zm;
+
+  let Inst{31-24} = 0b11000001;
+  let Inst{23-22} = size;
+  let Inst{21}    = 0b1;
+  let Inst{20-17} = Zm;
+  let Inst{16-10} = 0b0111010;
+  let Inst{9-6}   = Zn;
+  let Inst{5}     = 0b0;
+  let Inst{4-1}   = Zd;
+  let Inst{0}     = 0b0;
+}
+
+multiclass sme2_multi2_fmul_sm<string mnemonic> {
+  def _H : sme2_multi2_fmul_sm<0b01, mnemonic, ZZ_h_mul_r, ZPR4b16>;
+  def _S : sme2_multi2_fmul_sm<0b10, mnemonic, ZZ_s_mul_r, ZPR4b32>;
+  def _D : sme2_multi2_fmul_sm<0b11, mnemonic, ZZ_d_mul_r, ZPR4b64>;
+}
+
+class sme2_multi4_fmul_sm<bits<2> size, string mnemonic, RegisterOperand vector_ty, RegisterOperand zpr_ty>
+    : I<(outs vector_ty:$Zd), (ins vector_ty:$Zn, zpr_ty:$Zm),
+        mnemonic, "\t$Zd, $Zn, $Zm",
+        "", []>, Sched<[]> {
+  bits<3> Zd;
+  bits<3> Zn;
+  bits<4> Zm;
+
+  let Inst{31-24} = 0b11000001;
+  let Inst{23-22} = size;
+  let Inst{21}    = 0b1;
+  let Inst{20-17} = Zm;
+  let Inst{16-10} = 0b1111010;
+  let Inst{9-7}   = Zn;
+  let Inst{6-5}   = 0b00;
+  let Inst{4-2}   = Zd;
+  let Inst{1-0}   = 0b00;
+}
+
+multiclass sme2_multi4_fmul_sm<string mnemonic> {
+  def _H : sme2_multi4_fmul_sm<0b01, mnemonic, ZZZZ_h_mul_r, ZPR4b16>;
+  def _S : sme2_multi4_fmul_sm<0b10, mnemonic, ZZZZ_s_mul_r, ZPR4b32>;
+  def _D : sme2_multi4_fmul_sm<0b11, mnemonic, ZZZZ_d_mul_r, ZPR4b64>;
+}
+
+multiclass sme2_bfmul_single<string mnemonic> {
+  def _2ZZ  : sme2_multi2_fmul_sm<0b00, mnemonic, ZZ_h_mul_r,   ZPR4b16>;
+  def _4ZZ  : sme2_multi4_fmul_sm<0b00, mnemonic, ZZZZ_h_mul_r, ZPR4b16>;
+}
+
+class sme2_multi2_fmul_mm<bits<2> size, string mnemonic, RegisterOperand vector_ty>
+    : I<(outs vector_ty:$Zd), (ins vector_ty:$Zn, vector_ty:$Zm),
+        mnemonic, "\t$Zd, $Zn, $Zm",
+        "", []>, Sched<[]> {
+  bits<4> Zd;
+  bits<4> Zn;
+  bits<4> Zm;
+
+  let Inst{31-24} = 0b11000001;
+  let Inst{23-22} = size;
+  let Inst{21}    = 0b1;
+  let Inst{20-17} = Zm;
+  let Inst{16-10} = 0b0111001;
+  let Inst{9-6}   = Zn;
+  let Inst{5}     = 0b0;
+  let Inst{4-1}   = Zd;
+  let Inst{0}     = 0b0;
+}
+
+multiclass sme2_multi2_fmul_mm<string mnemonic> {
+  def _H : sme2_multi2_fmul_mm<0b01, mnemonic, ZZ_h_mul_r>;
+  def _S : sme2_multi2_fmul_mm<0b10, mnemonic, ZZ_s_mul_r>;
+  def _D : sme2_multi2_fmul_mm<0b11, mnemonic, ZZ_d_mul_r>;
+}
+
+class sme2_multi4_fmul_mm<bits<2> size, string mnemonic, RegisterOperand vector_ty>
+    : I<(outs vector_ty:$Zd), (ins vector_ty:$Zn, vector_ty:$Zm),
+        mnemonic, "\t$Zd, $Zn, $Zm",
+        "", []>, Sched<[]> {
+  bits<3> Zd;
+  bits<3> Zn;
+  bits<3> Zm;
+
+  let Inst{31-24} = 0b11000001;
+  let Inst{23-22} = size;
+  let Inst{21}    = 0b1;
+  let Inst{20-18} = Zm;
+  let Inst{17-10} = 0b01111001;
+  let Inst{9-7}   = Zn;
+  let Inst{6-5}   = 0b00;
+  let Inst{4-2}   = Zd;
+  let Inst{1-0}   = 0b00;
+}
+
+multiclass sme2_multi4_fmul_mm<string mnemonic> {
+  def _H : sme2_multi4_fmul_mm<0b01, mnemonic, ZZZZ_h_mul_r>;
+  def _S : sme2_multi4_fmul_mm<0b10, mnemonic, ZZZZ_s_mul_r>;
+  def _D : sme2_multi4_fmul_mm<0b11, mnemonic, ZZZZ_d_mul_r>;
+}
+
+multiclass sme2_bfmul_multi<string mnemonic> {
+  def _2Z2Z : sme2_multi2_fmul_mm<0b00, mnemonic, ZZ_h_mul_r>;
+  def _4Z4Z : sme2_multi4_fmul_mm<0b00, mnemonic, ZZZZ_h_mul_r>;
+}
diff --git a/llvm/test/MC/AArch64/SME2/bfmul-diagnostics.s b/llvm/test/MC/AArch64/SME2/bfmul-diagnostics.s
new file mode 100644
index 00000000000000..c28cc5cd426dda
--- /dev/null
+++ b/llvm/test/MC/AArch64/SME2/bfmul-diagnostics.s
@@ -0,0 +1,111 @@
+// RUN: not llvm-mc -triple=aarch64 -mattr=+sme2,+sve-bfscale 2>&1 < %s| FileCheck %s
+
+// Multiple and single, 2 regs
+
+bfmul   {z0.s-z1.s}, {z0.h-z1.h}, z0.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+bfmul   {z1.h-z2.h}, {z0.h-z1.h}, z0.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid vector list, expected list with 2 consecutive SVE vectors, where the first vector is a multiple of 2 and with matching element types
+
+bfmul   {z0.h-z2.h}, {z0.h-z1.h}, z0.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+bfmul   {z0.h-z1.h}, {z0.s-z1.s}, z0.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+bfmul   {z0.h-z1.h}, {z1.h-z2.h}, z0.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid vector list, expected list with 2 consecutive SVE vectors, where the first vector is a multiple of 2 and with matching element types
+
+bfmul   {z0.h-z1.h}, {z0.h-z2.h}, z0.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+bfmul   {z0.h-z1.h}, {z0.h-z1.h}, z0.s
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid restricted vector register, expected z0.h..z15.h
+
+bfmul   {z0.h-z1.h}, {z0.h-z1.h}, z16.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid restricted vector register, expected z0.h..z15.h
+
+// Multiple and single, 4 regs
+
+bfmul   {z0.s-z3.s}, {z0.h-z3.h}, z0.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+bfmul   {z1.h-z4.h}, {z0.h-z3.h}, z0.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid vector list, expected list with 4 consecutive SVE vectors, where the first vector is a multiple of 4 and with matching element types
+
+bfmul   {z0.h-z4.h}, {z0.h-z3.h}, z0.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid number of vectors
+
+bfmul   {z0.h-z3.h}, {z0.s-z3.s}, z0.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+bfmul   {z0.h-z3.h}, {z1.h-z4.h}, z0.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid vector list, expected list with 4 consecutive SVE vectors, where the first vector is a multiple of 4 and with matching element types
+
+bfmul   {z0.h-z3.h}, {z0.h-z4.h}, z0.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid number of vectors
+
+bfmul   {z0.h-z3.h}, {z0.h-z3.h}, z0.s
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid restricted vector register, expected z0.h..z15.h
+
+bfmul   {z0.h-z3.h}, {z0.h-z3.h}, z16.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid restricted vector register, expected z0.h..z15.h
+
+// Multiple, 2 regs
+
+bfmul   {z0.s-z1.s}, {z0.h-z1.h}, {z0.h-z1.h}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+bfmul   {z1.h-z2.h}, {z0.h-z1.h}, {z0.h-z1.h}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid vector list, expected list with 2 consecutive SVE vectors, where the first vector is a multiple of 2 and with matching element types
+
+bfmul   {z0.h-z2.h}, {z0.h-z1.h}, {z0.h-z1.h}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+bfmul   {z0.h-z1.h}, {z0.s-z1.s}, {z0.h-z1.h}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+bfmul   {z0.h-z1.h}, {z1.h-z2.h}, {z0.h-z1.h}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid vector list, expected list with 2 consecutive SVE vectors, where the first vector is a multiple of 2 and with matching element types
+
+bfmul   {z0.h-z1.h}, {z0.h-z2.h}, {z0.h-z1.h}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+bfmul   {z0.h-z1.h}, {z0.h-z1.h}, {z0.s-z1.s}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+bfmul   {z0.h-z1.h}, {z0.h-z1.h}, {z1.h-z2.h}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid vector list, expected list with 2 consecutive SVE vectors, where the first vector is a multiple of 2 and with matching element types
+
+bfmul   {z0.h-z1.h}, {z0.h-z1.h}, {z0.h-z2.h}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+// Multiple, 4 regs
+
+bfmul   {z0.s-z3.s}, {z0.h-z3.h}, {z0.h-z3.h}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+bfmul   {z1.h-z4.h}, {z0.h-z3.h}, {z0.h-z3.h}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid vector list, expected list with 4 consecutive SVE vectors, where the first vector is a multiple of 4 and with matching element types
+
+bfmul   {z0.h-z4.h}, {z0.h-z3.h}, {z0.h-z3.h}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid number of vectors
+
+bfmul   {z0.h-z3.h}, {z0.s-z3.s}, {z0.h-z3.h}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+bfmul   {z0.h-z3.h}, {z1.h-z4.h}, {z0.h-z3.h}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid vector list, expected list with 4 consecutive SVE vectors, where the first vector is a multiple of 4 and with matching element types
+
+bfmul   {z0.h-z3.h}, {z0.h-z4.h}, {z0.h-z3.h}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid number of vectors
+
+bfmul   {z0.h-z3.h}, {z0.h-z3.h}, {z0.s-z3.s}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+bfmul   {z0.h-z3.h}, {z0.h-z3.h}, {z1.h-z4.h}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid vector list, expected list with 4 consecutive SVE vectors, where the first vector is a multiple of 4 and with matching element types
+
+bfmul   {z0.h-z3.h}, {z0.h-z3.h}, {z0.h-z4.h}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid number of vectors
diff --git a/llvm/test/MC/AArch64/SME2/bfmul.s b/llvm/test/MC/AArch64/SME2/bfmul.s
new file mode 100644
index 00000000000000..10a43848c73819
--- /dev/null
+++ b/llvm/test/MC/AArch64/SME2/bfmul.s
@@ -0,0 +1,92 @@
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sme2,+sve-bfscale < %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=+sme2,+sve-bfscale < %s \
+// RUN:        | llvm-objdump -d --mattr=+sme2,+sve-bfscale - | FileCheck %s --check-prefix=CHECK-INST
+// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sme2,+sve-bfscale < %s \
+// RUN:        | llvm-objdump -d --mattr=-sme2 - | FileCheck %s --check-prefix=CHECK-UNKNOWN
+// Disassemble encoding and check the re-encoding (-show-encoding) matches.
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sme2,+sve-bfscale < %s \
+// RUN:        | sed '/.text/d' | sed 's/.*encoding: //g' \
+// RUN:        | llvm-mc -triple=aarch64 -mattr=+sme2,+sve-bfscale -disassemble -show-encoding \
+// RUN:        | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+
+// Multiple and single, 2 regs
+
+bfmul   {z0.h-z1.h}, {z0.h-z1.h}, z0.h  // 11000001-00100000-11101000-00000000
+// CHECK-INST: bfmul   { z0.h, z1.h }, { z0.h, z1.h }, z0.h
+// CHECK-ENCODING: [0x00,0xe8,0x20,0xc1]
+// CHECK-ERROR: instruction requires: sme2 sve-bfscale
+// CHECK-UNKNOWN: c120e800 <unknown>
+
+bfmul   {z20.h-z21.h}, {z10.h-z11.h}, z10.h  // 11000001-00110100-11101001-01010100
+// CHECK-INST: bfmul   { z20.h, z21.h }, { z10.h, z11.h }, z10.h
+// CHECK-ENCODING: [0x54,0xe9,0x34,0xc1]
+// CHECK-ERROR: instruction requires: sme2 sve-bfscale
+// CHECK-UNKNOWN: c134e954 <unknown>
+
+bfmul   {z30.h-z31.h}, {z30.h-z31.h}, z15.h  // 11000001-00111110-11101011-11011110
+// CHECK-INST: bfmul   { z30.h, z31.h }, { z30.h, z31.h }, z15.h
+// CHECK-ENCODING: [0xde,0xeb,0x3e,0xc1]
+// CHECK-ERROR: instruction requires: sme2 sve-bfscale
+// CHECK-UNKNOWN: c13eebde <unknown>
+
+// Multiple and single, 4 regs
+
+bfmul   {z0.h-z3.h}, {z0.h-z3.h}, z0.h  // 11000001-00100001-11101000-00000000
+// CHECK-INST: bfmul   { z0.h - z3.h }, { z0.h - z3.h }, z0.h
+// CHECK-ENCODING: [0x00,0xe8,0x21,0xc1]
+// CHECK-ERROR: instruction requires: sme2 sve-bfscale
+// CHECK-UNKNOWN: c121e800 <unknown>
+
+bfmul   {z20.h-z23.h}, {z8.h-z11.h}, z10.h  // 11000001-00110101-11101001-00010100
+// CHECK-INST: bfmul   { z20.h - z23.h }, { z8.h - z11.h }, z10.h
+// CHECK-ENCODING: [0x14,0xe9,0x35,0xc1]
+// CHECK-ERROR: instruction requires: sme2 sve-bfscale
+// CHECK-UNKNOWN: c135e914 <unknown>
+
+bfmul   {z28.h-z31.h}, {z28.h-z31.h}, z15.h  // 11000001-00111111-11101011-10011100
+// CHECK-INST: bfmul   { z28.h - z31.h }, { z28.h - z31.h }, z15.h
+// CHECK-ENCODING: [0x9c,0xeb,0x3f,0xc1]
+// CHECK-ERROR: instruction requires: sme2 sve-bfscale
+// CHECK-UNKNOWN: c13feb9c <unknown>
+
+// Multiple, 2 regs
+bfmul   {z0.h-z1.h}, {z0.h-z1.h}, {z0.h-z1.h}  // 11000001-00100000-11100100-00000000
+// CHECK-INST: bfmul   { z0.h, z1.h }, { z0.h, z1.h }, { z0.h, z1.h }
+// CHECK-ENCODING: [0x00,0xe4,0x20,0xc1]
+// CHECK-ERROR: instruction requires: sme2 sve-bfscale
+// CHECK-UNKNOWN: c120e400 <unknown>
+
+bfmul   {z20.h-z21.h}, {z10.h-z11.h}, {z20.h-z21.h}  // 11000001-00110100-11100101-01010100
+// CHECK-INST: bfmul   { z20.h, z21.h }, { z10.h, z11.h }, { z20.h, z21.h }
+// CHECK-ENCODING: [0x54,0xe5,0x34,0xc1]
+// CHECK-ERROR: instruction requires: sme2 sve-bfscale
+// CHECK-UNKNOWN: c134e554 <unknown>
+
+bfmul   {z30.h-z31.h}, {z30.h-z31.h}, {z30.h-z31.h}  // 11000001-00111110-11100111-11011110
+// CHECK-INST: bfmul   { z30.h, z31.h }, { z30.h, z31.h }, { z30.h, z31.h }
+// CHECK-ENCODING: [0xde,0xe7,0x3e,0xc1]
+// CHECK-ERROR: instruction requires: sme2 sve-bfscale
+// CHECK-UNKNOWN: c13ee7de <unknown>
+
+// Multiple, 4 regs
+
+bfmul   {z0.h-z3.h}, {z0.h-z3.h}, {z0.h-z3.h}  // 11000001-00100001-11100100-00000000
+// CHECK-INST: bfmul   { z0.h - z3.h }, { z0.h - z3.h }, { z0.h - z3.h }
+// CHECK-ENCODING: [0x00,0xe4,0x21,0xc1]
+// CHECK-ERROR: instruction requires: sme2 sve-bfscale
+// CHECK-UNKNOWN: c121e400 <unknown>
+
+bfmul   {z20.h-z23.h}, {z8.h-z11.h}, {z20.h-z23.h}  // 11000001-00110101-11100101-00010100
+// CHECK-INST: bfmul   { z20.h - z23.h }, { z8.h - z11.h }, { z20.h - z23.h }
+// CHECK-ENCODING: [0x14,0xe5,0x35,0xc1]
+// CHECK-ERROR: instruction requires: sme2 sve-bfscale
+// CHECK-UNKNOWN: c135e514 <unknown>
+
+bfmul   {z28.h-z31.h}, {z28.h-z31.h}, {z28.h-z31.h}  // 11000001-00111101-11100111-10011100
+// CHECK-INST: bfmul   { z28.h - z31.h }, { z28.h - z31.h }, { z28.h - z31.h }
+// CHECK-ENCODING: [0x9c,0xe7,0x3d,0xc1]
+// CHECK-ERROR: instruction requires: sme2 sve-bfscale
+// CHECK-UNKNOWN: c13de79c <unknown>
diff --git a/llvm/test/MC/AArch64/SME2/fmul-diagnostics.s b/llvm/test/MC/AArch64/SME2/fmul-diagnostics.s
new file mode 100644
index 00000000000000..2fdd3f82adc1dd
--- /dev/null
+++ b/llvm/test/MC/AArch64/SME2/fmul-diagnostics.s
@@ -0,0 +1,112 @@
+
+// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sme2p2 2>&1 < %s| FileCheck %s
+
+// Multiple and single, 2 regs
+
+fmul    {z0.b-z1.b}, {z0.h-z1.h}, z0.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+fmul    {z1.s-z2.s}, {z0.s-z1.s}, z0.s
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid vector list, expected list with 2 consecutive SVE vectors, where the first vector is a multiple of 2 and with matching element types
+
+fmul    {z0.d-z2.d}, {z0.d-z1.d}, z0.d
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+fmul    {z0.h-z1.h}, {z0.b-z1.b}, z0.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+fmul    {z0.s-z1.s}, {z1.s-z2.s}, z0.s
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid vector list, expected list with 2 consecutive SVE vectors, where the first vector is a multiple of 2 and with matching element types
+
+fmul    {z0.d-z1.d}, {z0.d-z2.d}, z0.d
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+fmul    {z0.h-z1.h}, {z0.h-z1.h}, z0.b
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid restricted vector register, expected z0.h..z15.h
+
+fmul    {z0.s-z1.s}, {z0.s-z1.s}, z16.s
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid restricted vector register, expected z0.s..z15.s
+
+// Multiple and single, 4 regs
+
+fmul    {z0.b-z3.b}, {z0.h-z3.h}, z0.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+fmul    {z1.s-z3.s}, {z0.h-z3.h}, z0.s
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+fmul    {z0.d-z4.d}, {z0.d-z3.d}, z0.d
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid number of vectors
+
+fmul    {z0.h-z3.h}, {z0.b-z3.b}, z0.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+fmul    {z0.s-z3.s}, {z1.s-z3.s}, z0.s
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+fmul    {z0.d-z3.d}, {z0.d-z4.d}, z0.d
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid number of vectors
+
+fmul    {z0.h-z3.h}, {z0.h-z3.h}, z0.b
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid restricted vector register, expected z0.h..z15.h
+
+fmul    {z0.s-z3.s}, {z0.s-z3.s}, z16.s
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid restricted vector register, expected z0.s..z15.s
+
+// Multiple, 2 regs
+
+fmul    {z0.b-z1.b}, {z0.h-z1.h}, {z0.h-z1.h}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+fmul    {z1.s-z2.s}, {z0.s-z1.s}, {z0.s-z1.s}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid vector list, expected list with 2 consecutive SVE vectors, where the first vector is a multiple of 2 and with matching element types
+
+fmul    {z0.d-z2.d}, {z0.d-z1.d}, {z0.d-z1.d}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+fmul    {z0.h-z1.h}, {z0.b-z1.b}, {z0.h-z1.h}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+fmul    {z0.s-z1.s}, {z1.s-z2.s}, {z0.s-z1.s}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid vector list, expected list with 2 consecutive SVE vectors, where the first vector is a multiple of 2 and with matching element types
+
+fmul    {z0.d-z1.d}, {z0.d-z2.d}, {z0.d-z1.d}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+fmul    {z0.h-z1.h}, {z0.h-z1.h}, {z0.b-z1.b}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+
+fmul    {z0.s-z1.s}, {z0.s-z1.s}, {z1.s-z2.s}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid vector list, expected list with 2 consecutive SVE vectors, where the first vector is a multiple of 2 and with matching element types
+
+...
[truncated]

Copy link
Contributor

@SpencerAbson SpencerAbson left a comment

Choose a reason for hiding this comment

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

LGTM, just a nit.

Copy link
Contributor

@jthackray jthackray left a comment

Choose a reason for hiding this comment

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

LGTM

@CarolineConcatto CarolineConcatto merged commit d4197f3 into llvm:main Oct 29, 2024
8 checks passed
@CarolineConcatto CarolineConcatto deleted the sve_mul_2024 branch October 29, 2024 09:09
NoumanAmir657 pushed a commit to NoumanAmir657/llvm-project that referenced this pull request Nov 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:AArch64 mc Machine (object) code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants