Skip to content
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

[AArch64] Add assembly/disassembly for SVE COMPACT (b/h) and EXPAND #114053

Merged
merged 1 commit into from
Oct 30, 2024

Conversation

SpencerAbson
Copy link
Contributor

This patch adds assembly/disassembly support for the following SVE2.2 instructions

  - COMPACT (byte, halfword)
  - EXPAND

- Add assembler support for the following SVE2p2 instructions
	- COMPACT (byte, halfword)
	- EXPAND
- Rename predicates guarding instructions that are illegal in streaming SVE mode without FEAT_SME2p2

Co-authored-by: Marian Lukac [email protected]
@llvmbot
Copy link
Member

llvmbot commented Oct 29, 2024

@llvm/pr-subscribers-mc

@llvm/pr-subscribers-backend-aarch64

Author: None (SpencerAbson)

Changes

This patch adds assembly/disassembly support for the following SVE2.2 instructions

  - COMPACT (byte, halfword)
  - EXPAND

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

10 Files Affected:

  • (modified) llvm/lib/Target/AArch64/AArch64.td (+2-1)
  • (modified) llvm/lib/Target/AArch64/AArch64InstrInfo.td (+6-1)
  • (modified) llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td (+14-3)
  • (modified) llvm/lib/Target/AArch64/SVEInstrFormats.td (+37-6)
  • (modified) llvm/test/MC/AArch64/SVE/compact-diagnostics.s (+2-2)
  • (modified) llvm/test/MC/AArch64/SVE/compact.s (+2-2)
  • (added) llvm/test/MC/AArch64/SVE2p2/compact-diagnostics.s (+65)
  • (added) llvm/test/MC/AArch64/SVE2p2/compact.s (+33)
  • (added) llvm/test/MC/AArch64/SVE2p2/expand-diagnostics.s (+120)
  • (added) llvm/test/MC/AArch64/SVE2p2/expand.s (+39)
diff --git a/llvm/lib/Target/AArch64/AArch64.td b/llvm/lib/Target/AArch64/AArch64.td
index 9bb508b783c36a..6854cccaafa1d7 100644
--- a/llvm/lib/Target/AArch64/AArch64.td
+++ b/llvm/lib/Target/AArch64/AArch64.td
@@ -73,7 +73,8 @@ def SVEUnsupported : AArch64Unsupported {
                       SVE2Unsupported.F);
 }
 
-let F = [HasSME2p2, HasSVE2p2orSME2p2] in
+let F = [HasSME2p2, HasSVE2p2orSME2p2, HasNonStreamingSVEorSME2p2,
+         HasNonStreamingSVE2p2orSME2p2] in
 def SME2p2Unsupported : AArch64Unsupported;
 
 def SME2p1Unsupported : AArch64Unsupported {
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index fe3c8578b52aa4..f64f520b57ad1f 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -244,7 +244,7 @@ def HasSVEorSME
     : Predicate<"Subtarget->hasSVE() || (Subtarget->isStreaming() && Subtarget->hasSME())">,
                 AssemblerPredicateWithAll<(any_of FeatureSVE, FeatureSME),
                 "sve or sme">;
-def HasSVEorSME2p2
+def HasNonStreamingSVEorSME2p2
     : Predicate<"(Subtarget->isSVEAvailable() && Subtarget->hasSVE()) ||"
                 "(Subtarget->isSVEorStreamingSVEAvailable() && Subtarget->hasSME2p2())">,
                 AssemblerPredicateWithAll<(any_of FeatureSVE, FeatureSME2p2),
@@ -281,6 +281,11 @@ def HasSMEF16F16orSMEF8F16
     : Predicate<"Subtarget->isStreaming() && (Subtarget->hasSMEF16F16() || Subtarget->hasSMEF8F16())">,
                 AssemblerPredicateWithAll<(any_of FeatureSMEF16F16, FeatureSMEF8F16),
                 "sme-f16f16 or sme-f8f16">;
+def HasNonStreamingSVE2p2orSME2p2
+    : Predicate<"(Subtarget->isSVEAvailable() && Subtarget->hasSVE2p2()) ||"
+                "(Subtarget->isSVEorStreamingSVEAvailable() && Subtarget->hasSME2p2())">,
+                AssemblerPredicateWithAll<(any_of FeatureSVE2p2, FeatureSME2p2),
+                "sme2p2 or sve2p2">;
 
 // A subset of NEON instructions are legal in Streaming SVE execution mode,
 // so don't need the additional check for 'isNeonAvailable'.
diff --git a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
index dc96b249c4e40c..05b4c62993f5d0 100644
--- a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
@@ -928,9 +928,10 @@ let Predicates = [HasSVEorSME] in {
   defm SPLICE_ZPZ : sve_int_perm_splice<"splice", AArch64splice>;
 } // End HasSVEorSME
 
-let Predicates = [HasSVE] in {
-  defm COMPACT_ZPZ : sve_int_perm_compact<"compact", int_aarch64_sve_compact>;
-} // End HasSVE
+// COMPACT - word and doubleword
+let Predicates = [HasNonStreamingSVEorSME2p2] in {
+  defm COMPACT_ZPZ : sve_int_perm_compact_sd<"compact", int_aarch64_sve_compact>;
+}
 
 let Predicates = [HasSVEorSME] in {
   defm INSR_ZR : sve_int_perm_insrs<"insr", AArch64insr>;
@@ -4269,6 +4270,16 @@ let Predicates = [HasSVE2p2orSME2p2] in {
 
 } // End HasSME2p2orSVE2p2
 
+//===----------------------------------------------------------------------===//
+// SME2.2 or SVE2.2 instructions - Legal in streaming mode iff target has SME2p2
+//===----------------------------------------------------------------------===//
+let Predicates = [HasNonStreamingSVE2p2orSME2p2] in {
+  // SVE2 EXPAND
+  defm EXPAND_ZPZ : sve2_int_perm_expand<"expand">;
+  // SVE COMPACT - byte and halfword
+  defm COMPACT_ZPZ : sve_int_perm_compact_bh<"compact">;
+}
+
 //===----------------------------------------------------------------------===//
 // SVE2 FP8 instructions
 //===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/AArch64/SVEInstrFormats.td b/llvm/lib/Target/AArch64/SVEInstrFormats.td
index 02ee0fe9244572..80d3b471f6eea0 100644
--- a/llvm/lib/Target/AArch64/SVEInstrFormats.td
+++ b/llvm/lib/Target/AArch64/SVEInstrFormats.td
@@ -7252,6 +7252,32 @@ multiclass sve2_int_perm_splice_cons<string asm> {
   def _D : sve2_int_perm_splice_cons<0b11, asm, ZPR64, ZZ_d>;
 }
 
+class sve2_int_perm_expand<bits<2> sz, string asm,
+                           ZPRRegOp zprty>
+: I<(outs zprty:$Zd), (ins PPR3bAny:$Pg, zprty:$Zn),
+  asm, "\t$Zd, $Pg, $Zn",
+  "",
+  []>, Sched<[]> {
+  bits<3> Pg;
+  bits<5> Zn;
+  bits<5> Zd;
+  let Inst{31-24} = 0b00000101;
+  let Inst{23-22} = sz;
+  let Inst{21-13} = 0b110001100;
+  let Inst{12-10} = Pg;
+  let Inst{9-5}   = Zn;
+  let Inst{4-0}   = Zd;
+
+  let hasSideEffects = 0;
+}
+
+multiclass sve2_int_perm_expand<string asm> {
+  def _B : sve2_int_perm_expand<0b00, asm, ZPR8>;
+  def _H : sve2_int_perm_expand<0b01, asm, ZPR16>;
+  def _S : sve2_int_perm_expand<0b10, asm, ZPR32>;
+  def _D : sve2_int_perm_expand<0b11, asm, ZPR64>;
+}
+
 class sve_int_perm_rev<bits<2> sz8_64, bits<2> opc, string asm,
                        ZPRRegOp zprty>
 : I<(outs zprty:$Zd), (ins zprty:$_Zd, PPR3bAny:$Pg, zprty:$Zn),
@@ -7413,7 +7439,7 @@ multiclass sve_int_perm_cpy_v<string asm, SDPatternOperator op> {
             (!cast<Instruction>(NAME # _H) $passthru, $pg, $splat)>;
 }
 
-class sve_int_perm_compact<bit sz, string asm, ZPRRegOp zprty>
+class sve_int_perm_compact<bits<2> sz, string asm, ZPRRegOp zprty>
 : I<(outs zprty:$Zd), (ins PPR3bAny:$Pg, zprty:$Zn),
   asm, "\t$Zd, $Pg, $Zn",
   "",
@@ -7421,8 +7447,8 @@ class sve_int_perm_compact<bit sz, string asm, ZPRRegOp zprty>
   bits<3> Pg;
   bits<5> Zd;
   bits<5> Zn;
-  let Inst{31-23} = 0b000001011;
-  let Inst{22}    = sz;
+  let Inst{31-24} = 0b00000101;
+  let Inst{23-22} = sz;
   let Inst{21-13} = 0b100001100;
   let Inst{12-10} = Pg;
   let Inst{9-5}   = Zn;
@@ -7431,9 +7457,9 @@ class sve_int_perm_compact<bit sz, string asm, ZPRRegOp zprty>
   let hasSideEffects = 0;
 }
 
-multiclass sve_int_perm_compact<string asm, SDPatternOperator op> {
-  def _S : sve_int_perm_compact<0b0, asm, ZPR32>;
-  def _D : sve_int_perm_compact<0b1, asm, ZPR64>;
+multiclass sve_int_perm_compact_sd<string asm, SDPatternOperator op> {
+  def _S : sve_int_perm_compact<0b10, asm, ZPR32>;
+  def _D : sve_int_perm_compact<0b11, asm, ZPR64>;
 
   def : SVE_2_Op_Pat<nxv4i32, op, nxv4i1, nxv4i32, !cast<Instruction>(NAME # _S)>;
   def : SVE_2_Op_Pat<nxv4f32, op, nxv4i1, nxv4f32, !cast<Instruction>(NAME # _S)>;
@@ -7441,6 +7467,11 @@ multiclass sve_int_perm_compact<string asm, SDPatternOperator op> {
   def : SVE_2_Op_Pat<nxv2f64, op, nxv2i1, nxv2f64, !cast<Instruction>(NAME # _D)>;
 }
 
+multiclass sve_int_perm_compact_bh<string asm> {
+  def _B : sve_int_perm_compact<0b00, asm, ZPR8>;
+  def _H : sve_int_perm_compact<0b01, asm, ZPR16>;
+}
+
 //===----------------------------------------------------------------------===//
 // SVE Memory - Contiguous Load Group
 //===----------------------------------------------------------------------===//
diff --git a/llvm/test/MC/AArch64/SVE/compact-diagnostics.s b/llvm/test/MC/AArch64/SVE/compact-diagnostics.s
index a3d86267d917b5..b8ff8cc46201f2 100644
--- a/llvm/test/MC/AArch64/SVE/compact-diagnostics.s
+++ b/llvm/test/MC/AArch64/SVE/compact-diagnostics.s
@@ -28,12 +28,12 @@ compact z31.s, p7, z31.d
 // CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
 
 compact z31.b, p7, z31.b
-// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction requires: sme2p2 or sve2p2
 // CHECK-NEXT: compact z31.b, p7, z31.b
 // CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
 
 compact z31.h, p7, z31.h
-// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction requires: sme2p2 or sve2p2
 // CHECK-NEXT: compact z31.h, p7, z31.h
 // CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
 
diff --git a/llvm/test/MC/AArch64/SVE/compact.s b/llvm/test/MC/AArch64/SVE/compact.s
index ff815980781d79..a9b47dea246bee 100644
--- a/llvm/test/MC/AArch64/SVE/compact.s
+++ b/llvm/test/MC/AArch64/SVE/compact.s
@@ -12,11 +12,11 @@
 compact z31.s, p7, z31.s
 // CHECK-INST: compact z31.s, p7, z31.s
 // CHECK-ENCODING: [0xff,0x9f,0xa1,0x05]
-// CHECK-ERROR: instruction requires: sve
+// CHECK-ERROR: instruction requires: sve or sme2p2
 // CHECK-UNKNOWN: 05a19fff <unknown>
 
 compact z31.d, p7, z31.d
 // CHECK-INST: compact z31.d, p7, z31.d
 // CHECK-ENCODING: [0xff,0x9f,0xe1,0x05]
-// CHECK-ERROR: instruction requires: sve
+// CHECK-ERROR: instruction requires: sve or sme2p2
 // CHECK-UNKNOWN: 05e19fff <unknown>
diff --git a/llvm/test/MC/AArch64/SVE2p2/compact-diagnostics.s b/llvm/test/MC/AArch64/SVE2p2/compact-diagnostics.s
new file mode 100644
index 00000000000000..acf00e7f7a600f
--- /dev/null
+++ b/llvm/test/MC/AArch64/SVE2p2/compact-diagnostics.s
@@ -0,0 +1,65 @@
+// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2p2  2>&1 < %s| FileCheck %s
+
+// --------------------------------------------------------------------------//
+// Invalid element widths
+
+compact z31.h, p7, z31.b
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width
+// CHECK-NEXT: compact z31.h, p7, z31.b
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+compact z31.b, p7, z31.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width
+// CHECK-NEXT: compact z31.b, p7, z31.h
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+// --------------------------------------------------------------------------//
+// Invalid predicate operation
+
+compact z23.b, p7/m, z13.b
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: compact z23.b, p7/m, z13.b
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+compact z23.b, p7.b, z13.b
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid restricted predicate register, expected p0..p7 (without element suffix)
+// CHECK-NEXT: compact z23.b, p7.b, z13.b
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+compact z23.h, p7/z, z13.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: compact z23.h, p7/z, z13.h
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+compact z23.h, p7.h, z13.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid restricted predicate register, expected p0..p7 (without element suffix)
+// CHECK-NEXT: compact z23.h, p7.h, z13.h
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+// --------------------------------------------------------------------------//
+// Predicate not in restricted predicate range
+
+compact z23.b, p8, z13.b
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid restricted predicate register, expected p0..p7 (without element suffix)
+// CHECK-NEXT: compact z23.b, p8, z13.b
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+compact z23.h, p8, z13.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid restricted predicate register, expected p0..p7 (without element suffix)
+// CHECK-NEXT: compact z23.h, p8, z13.h
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+// --------------------------------------------------------------------------//
+// Negative tests for instructions that are incompatible with movprfx
+
+movprfx z31.b, p7/z, z6.b
+compact z31.b, p7, z31.b
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov
+// CHECK-NEXT: compact z31.b, p7, z31.b
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+movprfx z31, z6
+compact z31.h, p7, z31.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov
+// CHECK-NEXT: compact z31.h, p7, z31.h
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
diff --git a/llvm/test/MC/AArch64/SVE2p2/compact.s b/llvm/test/MC/AArch64/SVE2p2/compact.s
new file mode 100644
index 00000000000000..0170b3832bea67
--- /dev/null
+++ b/llvm/test/MC/AArch64/SVE2p2/compact.s
@@ -0,0 +1,33 @@
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2p2 < %s \
+// RUN:        | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sme2p2 < %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=+sve2p2 < %s \
+// RUN:        | llvm-objdump -d --mattr=+sve2p2 - | FileCheck %s --check-prefix=CHECK-INST
+// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2p2 < %s \
+// RUN:        | llvm-objdump -d --mattr=-sve2p2 - | FileCheck %s --check-prefix=CHECK-UNKNOWN
+// Disassemble encoding and check the re-encoding (-show-encoding) matches.
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2p2 < %s \
+// RUN:        | sed '/.text/d' | sed 's/.*encoding: //g' \
+// RUN:        | llvm-mc -triple=aarch64 -mattr=+sve2p2 -disassemble -show-encoding \
+// RUN:        | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+
+compact z0.b, p0, z0.b  // 00000101-00100001-10000000-00000000
+// CHECK-INST: compact z0.b, p0, z0.b
+// CHECK-ENCODING: [0x00,0x80,0x21,0x05]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 05218000 <unknown>
+
+compact z21.b, p5, z10.b  // 00000101-00100001-10010101-01010101
+// CHECK-INST: compact z21.b, p5, z10.b
+// CHECK-ENCODING: [0x55,0x95,0x21,0x05]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 05219555 <unknown>
+
+compact z31.h, p7, z31.h  // 00000101-01100001-10011111-11111111
+// CHECK-INST: compact z31.h, p7, z31.h
+// CHECK-ENCODING: [0xff,0x9f,0x61,0x05]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 05619fff <unknown>
\ No newline at end of file
diff --git a/llvm/test/MC/AArch64/SVE2p2/expand-diagnostics.s b/llvm/test/MC/AArch64/SVE2p2/expand-diagnostics.s
new file mode 100644
index 00000000000000..b9a95f399a168a
--- /dev/null
+++ b/llvm/test/MC/AArch64/SVE2p2/expand-diagnostics.s
@@ -0,0 +1,120 @@
+// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2p2  2>&1 < %s| FileCheck %s
+
+// ------------------------------------------------------------------------- //
+// Invalid element widths.
+
+expand  z23.b, p3, z13.d
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width
+// CHECK-NEXT: expand  z23.b, p3, z13.d
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+expand  z23.h, p3, z13.b
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width
+// CHECK-NEXT: expand  z23.h, p3, z13.b
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+expand  z23.s, p3, z13.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width
+// CHECK-NEXT: expand  z23.s, p3, z13.h
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+expand  z23.d, p3, z13.s
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width
+// CHECK-NEXT: expand  z23.d, p3, z13.s
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+expand  z23.q, p3, z13.q
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width
+// CHECK-NEXT: expand  z23.q, p3, z13.q
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+// --------------------------------------------------------------------------//
+// Invalid predicate operation
+
+expand  z23.b, p3/z, z13.b
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: expand  z23.b, p3/z, z13.b
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+expand  z23.b, p3.b, z13.b
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid restricted predicate register, expected p0..p7 (without element suffix)
+// CHECK-NEXT: expand  z23.b, p3.b, z13.b
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+expand  z23.h, p3/m, z13.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: expand  z23.h, p3/m, z13.h
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+expand  z23.h, p3.h, z13.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid restricted predicate register, expected p0..p7 (without element suffix)
+// CHECK-NEXT: expand  z23.h, p3.h, z13.h
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+expand  z23.s, p3/z, z13.s
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: expand  z23.s, p3/z, z13.s
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+expand  z23.s, p3.s, z13.s
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid restricted predicate register, expected p0..p7 (without element suffix)
+// CHECK-NEXT: expand  z23.s, p3.s, z13.s
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+expand  z23.d, p3/m, z13.d
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: expand  z23.d, p3/m, z13.d
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+expand  z23.d, p3.d, z13.d
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid restricted predicate register, expected p0..p7 (without element suffix)
+// CHECK-NEXT: expand  z23.d, p3.d, z13.d
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+// --------------------------------------------------------------------------//
+// Predicate not in restricted predicate range
+
+expand  z23.b, p8, z13.b
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid restricted predicate register, expected p0..p7 (without element suffix)
+// CHECK-NEXT: expand  z23.b, p8, z13.b
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+expand  z23.b, p3.b, z13.b
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid restricted predicate register, expected p0..p7 (without element suffix)
+// CHECK-NEXT: expand  z23.b, p3.b, z13.b
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+expand  z23.h, p8, z13.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid restricted predicate register, expected p0..p7 (without element suffix)
+// CHECK-NEXT: expand  z23.h, p8, z13.h
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+expand  z23.h, p3.h, z13.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid restricted predicate register, expected p0..p7 (without element suffix)
+// CHECK-NEXT: expand  z23.h, p3.h, z13.h
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}
+
+expand  z23.s, p8, z13.s
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid restricted predicate register, expected p0..p7 (without element suffix)
+// CHECK-NEXT: expand  z23.s, p8, z13.s
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+expand  z23.d, p8, z13.d
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid restricted predicate register, expected p0..p7 (without element suffix)
+// CHECK-NEXT: expand  z23.d, p8, z13.d
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+// --------------------------------------------------------------------------//
+// Negative tests for instructions that are incompatible with movprfx
+
+movprfx z31, z6
+expand  z31.b, p7, z31.b
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov
+// CHECK-NEXT: expand  z31.b, p7, z31.b
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+movprfx z31.b, p0/z, z6.b
+expand  z31.b, p0, z31.b
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov
+// CHECK-NEXT: expand  z31.b, p0, z31.b
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
diff --git a/llvm/test/MC/AArch64/SVE2p2/expand.s b/llvm/test/MC/AArch64/SVE2p2/expand.s
new file mode 100644
index 00000000000000..7523978380fbd7
--- /dev/null
+++ b/llvm/test/MC/AArch64/SVE2p2/expand.s
@@ -0,0 +1,39 @@
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2p2 < %s \
+// RUN:        | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sme2p2 < %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=+sve2p2 < %s \
+// RUN:        | llvm-objdump -d --mattr=+sve2p2 - | FileCheck %s --check-prefix=CHECK-INST
+// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2p2 < %s \
+// RUN:        | llvm-objdump -d --mattr=-sve2p2 - | FileCheck %s --check-prefix=CHECK-UNKNOWN
+// Disassemble encoding and check the re-encoding (-show-encoding) matches.
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2p2 < %s \
+// RUN:        | sed '/.text/d' | sed 's/.*encoding: //g' \
+// RUN:        | llvm-mc -triple=aarch64 -mattr=+sve2p2 -disassemble -show-encoding \
+// RUN:        | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+
+expand  z0.b, p0, z0.b  // 00000101-00110001-10000000-00000000
+// CHECK-INST: expand  z0.b, p0, z0.b
+// CHECK-ENCODING: [0x00,0x80,0x31,0x05]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 05318000 <unknown>
+
+expand  z21.h, p5, z10.h  // 00000101-01110001-10010101-01010101
+// CHECK-INST: expand  ...
[truncated]

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

@SpencerAbson SpencerAbson merged commit 85f3d5c into llvm:main Oct 30, 2024
11 checks passed
NoumanAmir657 pushed a commit to NoumanAmir657/llvm-project that referenced this pull request Nov 4, 2024
…lvm#114053)

This patch adds assembly/disassembly support for the following SVE2.2
instructions

      - COMPACT (byte, halfword)
      - EXPAND

- Allow selection of `COMPACT` (word/halfword) in streaming mode if the
target has FEAT_SME2p2 (see [COMPACT ](
https://developer.arm.com/documentation/ddi0602/2024-09/SVE-Instructions/COMPACT--Copy-active-vector-elements-to-lower-numbered-elements-))
- Rename predicates guarding instructions that are illegal in streaming
SVE mode without FEAT_SME2p2
- In accordance with
https://developer.arm.com/documentation/ddi0602/2024-09/SVE-Instructions
Co-authored-by: Marian Lukac [email protected]
qiaojbao pushed a commit to GPUOpen-Drivers/llvm-project that referenced this pull request Dec 4, 2024
…1ca85ec98

Local branch amd-gfx 7a21ca8 Merged main:03948882d3bac33cf71a47df1c7ee0f87aad9fc2 into amd-gfx:d2b54d8b4b44
Remote branch main 85f3d5c [AArch64] Add assembly/disassembly for SVE COMPACT (b/h) and EXPAND (llvm#114053)
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.

3 participants