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/disassmbly for FIRST,LASTP instr. #114049

Merged
merged 3 commits into from
Oct 30, 2024

Conversation

Lukacma
Copy link
Contributor

@Lukacma Lukacma commented Oct 29, 2024

This patch adds assembly/disassembly and tests for new FIRSTP
and LASTP instructions introduced in https://developer.arm.com/documentation/ddi0602/2024-09

@llvmbot
Copy link
Collaborator

llvmbot commented Oct 29, 2024

@llvm/pr-subscribers-mc

Author: None (Lukacma)

Changes

This patch adds assembly/disassembly and tests for new FIRSTP
and LASTP instructions introduced in https://developer.arm.com/documentation/ddi0602/2024-09


Full diff: https://github.com/llvm/llvm-project/pull/114049.diff

6 Files Affected:

  • (modified) llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td (+4-1)
  • (modified) llvm/lib/Target/AArch64/SVEInstrFormats.td (+10-4)
  • (added) llvm/test/MC/AArch64/SVE2p2/firstp-diagnostics.s (+32)
  • (added) llvm/test/MC/AArch64/SVE2p2/firstp.s (+87)
  • (added) llvm/test/MC/AArch64/SVE2p2/lastp-diagnostics.s (+32)
  • (added) llvm/test/MC/AArch64/SVE2p2/lastp.s (+87)
diff --git a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
index 2b69903b133fe3..9dc55c2b508229 100644
--- a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
@@ -2128,7 +2128,7 @@ let Predicates = [HasSVEorSME] in {
   defm CNTH_XPiI : sve_int_count<0b010, "cnth", int_aarch64_sve_cnth>;
   defm CNTW_XPiI : sve_int_count<0b100, "cntw", int_aarch64_sve_cntw>;
   defm CNTD_XPiI : sve_int_count<0b110, "cntd", int_aarch64_sve_cntd>;
-  defm CNTP_XPP : sve_int_pcount_pred<0b0000, "cntp", int_aarch64_sve_cntp>;
+  defm CNTP_XPP : sve_int_pcount_pred<0b000, "cntp", int_aarch64_sve_cntp>;
 
   def : Pat<(i64 (AArch64CttzElts nxv16i1:$Op1)),
             (CNTP_XPP_B (BRKB_PPzP (PTRUE_B 31), PPR:$Op1),
@@ -4292,6 +4292,9 @@ let Predicates = [HasSVE2p2orSME2p2] in {
   def SXTW_ZPzZ_D : sve_int_un_pred_arit_z<0b11, 0b1000, "sxtw", ZPR64>;
   def UXTW_ZPzZ_D : sve_int_un_pred_arit_z<0b11, 0b1010, "uxtw", ZPR64>;
 
+  // SVE predicate count
+  defm FIRSTP_XPP : sve_int_pcount_pred_tmp<0b001, "firstp">;
+  defm LASTP_XPP  : sve_int_pcount_pred_tmp<0b010, "lastp">;
 } // End HasSME2p2orSVE2p2
 
 //===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/AArch64/SVEInstrFormats.td b/llvm/lib/Target/AArch64/SVEInstrFormats.td
index 31312e00b919e2..bcb92e65729010 100644
--- a/llvm/lib/Target/AArch64/SVEInstrFormats.td
+++ b/llvm/lib/Target/AArch64/SVEInstrFormats.td
@@ -1046,7 +1046,7 @@ multiclass sve_int_count_v<bits<5> opc, string asm,
                   (!cast<Instruction>(NAME # "_D") ZPR64:$Zdn, PPRAny:$Pm), 0>;
 }
 
-class sve_int_pcount_pred<bits<2> sz8_64, bits<4> opc, string asm,
+class sve_int_pcount_pred<bits<2> sz8_64, bits<3> opc, string asm,
                           PPRRegOp pprty>
 : I<(outs GPR64:$Rd), (ins PPRAny:$Pg, pprty:$Pn),
   asm, "\t$Rd, $Pg, $Pn",
@@ -1058,17 +1058,17 @@ class sve_int_pcount_pred<bits<2> sz8_64, bits<4> opc, string asm,
   let Inst{31-24} = 0b00100101;
   let Inst{23-22} = sz8_64;
   let Inst{21-19} = 0b100;
-  let Inst{18-16} = opc{3-1};
+  let Inst{18-16} = opc{2-0};
   let Inst{15-14} = 0b10;
   let Inst{13-10} = Pg;
-  let Inst{9}     = opc{0};
+  let Inst{9}     = 0b0;
   let Inst{8-5}   = Pn;
   let Inst{4-0}   = Rd;
 
   let hasSideEffects = 0;
 }
 
-multiclass sve_int_pcount_pred<bits<4> opc, string asm,
+multiclass sve_int_pcount_pred<bits<3> opc, string asm,
                                SDPatternOperator int_op> {
   def _B : sve_int_pcount_pred<0b00, opc, asm, PPR8>;
   def _H : sve_int_pcount_pred<0b01, opc, asm, PPR16>;
@@ -1081,6 +1081,12 @@ multiclass sve_int_pcount_pred<bits<4> opc, string asm,
   def : SVE_2_Op_Pat<i64, int_op, nxv2i1,  nxv2i1,  !cast<Instruction>(NAME # _D)>;
 }
 
+multiclass sve_int_pcount_pred_tmp<bits<3> opc, string asm> {
+  def _B : sve_int_pcount_pred<0b00, opc, asm, PPR8>;
+  def _H : sve_int_pcount_pred<0b01, opc, asm, PPR16>;
+  def _S : sve_int_pcount_pred<0b10, opc, asm, PPR32>;
+  def _D : sve_int_pcount_pred<0b11, opc, asm, PPR64>;
+}
 //===----------------------------------------------------------------------===//
 // SVE Element Count Group
 //===----------------------------------------------------------------------===//
diff --git a/llvm/test/MC/AArch64/SVE2p2/firstp-diagnostics.s b/llvm/test/MC/AArch64/SVE2p2/firstp-diagnostics.s
new file mode 100644
index 00000000000000..942b277f68c154
--- /dev/null
+++ b/llvm/test/MC/AArch64/SVE2p2/firstp-diagnostics.s
@@ -0,0 +1,32 @@
+// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2p2 2>&1 < %s| FileCheck %s
+
+// ------------------------------------------------------------------------- //
+// Invalid predicate operand
+
+firstp  x0, p15, p0
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid predicate register.
+// CHECK-NEXT: firstp  x0, p15, p0
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+firstp  x0, p15.b, p0.b
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid predicate register.
+// CHECK-NEXT: firstp  x0, p15.b, p0.b
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+firstp  x0, p15.q, p0.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid predicate register.
+// CHECK-NEXT: firstp  x0, p15.q, p0.h
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+// ------------------------------------------------------------------------- //
+// Invalid register types
+
+firstp  sp, p15.q, p0.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: firstp  sp, p15.q, p0.h
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+firstp  w0, p15.q, p0.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: firstp  w0, p15.q, p0.h
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
diff --git a/llvm/test/MC/AArch64/SVE2p2/firstp.s b/llvm/test/MC/AArch64/SVE2p2/firstp.s
new file mode 100644
index 00000000000000..629bee5576fc7d
--- /dev/null
+++ b/llvm/test/MC/AArch64/SVE2p2/firstp.s
@@ -0,0 +1,87 @@
+// 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=-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=+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
+
+firstp  x0, p0, p0.b  // 00100101-00100001-10000000-00000000
+// CHECK-INST: firstp  x0, p0, p0.b
+// CHECK-ENCODING: [0x00,0x80,0x21,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 25218000 <unknown>
+
+firstp  x23, p11, p13.b  // 00100101-00100001-10101101-10110111
+// CHECK-INST: firstp  x23, p11, p13.b
+// CHECK-ENCODING: [0xb7,0xad,0x21,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 2521adb7 <unknown>
+
+firstp  xzr, p15, p15.b  // 00100101-00100001-10111101-11111111
+// CHECK-INST: firstp  xzr, p15, p15.b
+// CHECK-ENCODING: [0xff,0xbd,0x21,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 2521bdff <unknown>
+
+firstp  x0, p0, p0.h  // 00100101-01100001-10000000-00000000
+// CHECK-INST: firstp  x0, p0, p0.h
+// CHECK-ENCODING: [0x00,0x80,0x61,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 25618000 <unknown>
+
+firstp  x23, p11, p13.h  // 00100101-01100001-10101101-10110111
+// CHECK-INST: firstp  x23, p11, p13.h
+// CHECK-ENCODING: [0xb7,0xad,0x61,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 2561adb7 <unknown>
+
+firstp  xzr, p15, p15.h  // 00100101-01100001-10111101-11111111
+// CHECK-INST: firstp  xzr, p15, p15.h
+// CHECK-ENCODING: [0xff,0xbd,0x61,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 2561bdff <unknown>
+
+firstp  x0, p0, p0.s  // 00100101-10100001-10000000-00000000
+// CHECK-INST: firstp  x0, p0, p0.s
+// CHECK-ENCODING: [0x00,0x80,0xa1,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 25a18000 <unknown>
+
+firstp  x23, p11, p13.s  // 00100101-10100001-10101101-10110111
+// CHECK-INST: firstp  x23, p11, p13.s
+// CHECK-ENCODING: [0xb7,0xad,0xa1,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 25a1adb7 <unknown>
+
+firstp  xzr, p15, p15.s  // 00100101-10100001-10111101-11111111
+// CHECK-INST: firstp  xzr, p15, p15.s
+// CHECK-ENCODING: [0xff,0xbd,0xa1,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 25a1bdff <unknown>
+
+firstp  x0, p0, p0.d  // 00100101-11100001-10000000-00000000
+// CHECK-INST: firstp  x0, p0, p0.d
+// CHECK-ENCODING: [0x00,0x80,0xe1,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 25e18000 <unknown>
+
+firstp  x23, p11, p13.d  // 00100101-11100001-10101101-10110111
+// CHECK-INST: firstp  x23, p11, p13.d
+// CHECK-ENCODING: [0xb7,0xad,0xe1,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 25e1adb7 <unknown>
+
+firstp  xzr, p15, p15.d  // 00100101-11100001-10111101-11111111
+// CHECK-INST: firstp  xzr, p15, p15.d
+// CHECK-ENCODING: [0xff,0xbd,0xe1,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 25e1bdff <unknown>
\ No newline at end of file
diff --git a/llvm/test/MC/AArch64/SVE2p2/lastp-diagnostics.s b/llvm/test/MC/AArch64/SVE2p2/lastp-diagnostics.s
new file mode 100644
index 00000000000000..fecb52c6006b55
--- /dev/null
+++ b/llvm/test/MC/AArch64/SVE2p2/lastp-diagnostics.s
@@ -0,0 +1,32 @@
+// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2p2 2>&1 < %s| FileCheck %s
+
+// ------------------------------------------------------------------------- //
+// Invalid predicate operand
+
+lastp  x0, p15, p0
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid predicate register.
+// CHECK-NEXT: lastp  x0, p15, p0
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+lastp  x0, p15.b, p0.b
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid predicate register.
+// CHECK-NEXT: lastp  x0, p15.b, p0.b
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+lastp  x0, p15.q, p0.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid predicate register.
+// CHECK-NEXT: lastp  x0, p15.q, p0.h
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+// ------------------------------------------------------------------------- //
+// Invalid register types
+
+lastp  sp, p15.q, p0.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: lastp  sp, p15.q, p0.h
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+lastp  w0, p15.q, p0.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: lastp  w0, p15.q, p0.h
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
\ No newline at end of file
diff --git a/llvm/test/MC/AArch64/SVE2p2/lastp.s b/llvm/test/MC/AArch64/SVE2p2/lastp.s
new file mode 100644
index 00000000000000..1ffa0a7d1fcc19
--- /dev/null
+++ b/llvm/test/MC/AArch64/SVE2p2/lastp.s
@@ -0,0 +1,87 @@
+// 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=-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=+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
+
+lastp   x0, p0, p0.b  // 00100101-00100010-10000000-00000000
+// CHECK-INST: lastp   x0, p0, p0.b
+// CHECK-ENCODING: [0x00,0x80,0x22,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 25228000 <unknown>
+
+lastp   x23, p11, p13.b  // 00100101-00100010-10101101-10110111
+// CHECK-INST: lastp   x23, p11, p13.b
+// CHECK-ENCODING: [0xb7,0xad,0x22,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 2522adb7 <unknown>
+
+lastp   xzr, p15, p15.b  // 00100101-00100010-10111101-11111111
+// CHECK-INST: lastp   xzr, p15, p15.b
+// CHECK-ENCODING: [0xff,0xbd,0x22,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 2522bdff <unknown>
+
+lastp   x0, p0, p0.h  // 00100101-01100010-10000000-00000000
+// CHECK-INST: lastp   x0, p0, p0.h
+// CHECK-ENCODING: [0x00,0x80,0x62,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 25628000 <unknown>
+
+lastp   x23, p11, p13.h  // 00100101-01100010-10101101-10110111
+// CHECK-INST: lastp   x23, p11, p13.h
+// CHECK-ENCODING: [0xb7,0xad,0x62,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 2562adb7 <unknown>
+
+lastp   xzr, p15, p15.h  // 00100101-01100010-10111101-11111111
+// CHECK-INST: lastp   xzr, p15, p15.h
+// CHECK-ENCODING: [0xff,0xbd,0x62,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 2562bdff <unknown>
+
+lastp   x0, p0, p0.s  // 00100101-10100010-10000000-00000000
+// CHECK-INST: lastp   x0, p0, p0.s
+// CHECK-ENCODING: [0x00,0x80,0xa2,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 25a28000 <unknown>
+
+lastp   x23, p11, p13.s  // 00100101-10100010-10101101-10110111
+// CHECK-INST: lastp   x23, p11, p13.s
+// CHECK-ENCODING: [0xb7,0xad,0xa2,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 25a2adb7 <unknown>
+
+lastp   xzr, p15, p15.s  // 00100101-10100010-10111101-11111111
+// CHECK-INST: lastp   xzr, p15, p15.s
+// CHECK-ENCODING: [0xff,0xbd,0xa2,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 25a2bdff <unknown>
+
+lastp   x0, p0, p0.d  // 00100101-11100010-10000000-00000000
+// CHECK-INST: lastp   x0, p0, p0.d
+// CHECK-ENCODING: [0x00,0x80,0xe2,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 25e28000 <unknown>
+
+lastp   x23, p11, p13.d  // 00100101-11100010-10101101-10110111
+// CHECK-INST: lastp   x23, p11, p13.d
+// CHECK-ENCODING: [0xb7,0xad,0xe2,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 25e2adb7 <unknown>
+
+lastp   xzr, p15, p15.d  // 00100101-11100010-10111101-11111111
+// CHECK-INST: lastp   xzr, p15, p15.d
+// CHECK-ENCODING: [0xff,0xbd,0xe2,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 25e2bdff <unknown>
\ No newline at end of file

@llvmbot
Copy link
Collaborator

llvmbot commented Oct 29, 2024

@llvm/pr-subscribers-backend-aarch64

Author: None (Lukacma)

Changes

This patch adds assembly/disassembly and tests for new FIRSTP
and LASTP instructions introduced in https://developer.arm.com/documentation/ddi0602/2024-09


Full diff: https://github.com/llvm/llvm-project/pull/114049.diff

6 Files Affected:

  • (modified) llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td (+4-1)
  • (modified) llvm/lib/Target/AArch64/SVEInstrFormats.td (+10-4)
  • (added) llvm/test/MC/AArch64/SVE2p2/firstp-diagnostics.s (+32)
  • (added) llvm/test/MC/AArch64/SVE2p2/firstp.s (+87)
  • (added) llvm/test/MC/AArch64/SVE2p2/lastp-diagnostics.s (+32)
  • (added) llvm/test/MC/AArch64/SVE2p2/lastp.s (+87)
diff --git a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
index 2b69903b133fe3..9dc55c2b508229 100644
--- a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
@@ -2128,7 +2128,7 @@ let Predicates = [HasSVEorSME] in {
   defm CNTH_XPiI : sve_int_count<0b010, "cnth", int_aarch64_sve_cnth>;
   defm CNTW_XPiI : sve_int_count<0b100, "cntw", int_aarch64_sve_cntw>;
   defm CNTD_XPiI : sve_int_count<0b110, "cntd", int_aarch64_sve_cntd>;
-  defm CNTP_XPP : sve_int_pcount_pred<0b0000, "cntp", int_aarch64_sve_cntp>;
+  defm CNTP_XPP : sve_int_pcount_pred<0b000, "cntp", int_aarch64_sve_cntp>;
 
   def : Pat<(i64 (AArch64CttzElts nxv16i1:$Op1)),
             (CNTP_XPP_B (BRKB_PPzP (PTRUE_B 31), PPR:$Op1),
@@ -4292,6 +4292,9 @@ let Predicates = [HasSVE2p2orSME2p2] in {
   def SXTW_ZPzZ_D : sve_int_un_pred_arit_z<0b11, 0b1000, "sxtw", ZPR64>;
   def UXTW_ZPzZ_D : sve_int_un_pred_arit_z<0b11, 0b1010, "uxtw", ZPR64>;
 
+  // SVE predicate count
+  defm FIRSTP_XPP : sve_int_pcount_pred_tmp<0b001, "firstp">;
+  defm LASTP_XPP  : sve_int_pcount_pred_tmp<0b010, "lastp">;
 } // End HasSME2p2orSVE2p2
 
 //===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/AArch64/SVEInstrFormats.td b/llvm/lib/Target/AArch64/SVEInstrFormats.td
index 31312e00b919e2..bcb92e65729010 100644
--- a/llvm/lib/Target/AArch64/SVEInstrFormats.td
+++ b/llvm/lib/Target/AArch64/SVEInstrFormats.td
@@ -1046,7 +1046,7 @@ multiclass sve_int_count_v<bits<5> opc, string asm,
                   (!cast<Instruction>(NAME # "_D") ZPR64:$Zdn, PPRAny:$Pm), 0>;
 }
 
-class sve_int_pcount_pred<bits<2> sz8_64, bits<4> opc, string asm,
+class sve_int_pcount_pred<bits<2> sz8_64, bits<3> opc, string asm,
                           PPRRegOp pprty>
 : I<(outs GPR64:$Rd), (ins PPRAny:$Pg, pprty:$Pn),
   asm, "\t$Rd, $Pg, $Pn",
@@ -1058,17 +1058,17 @@ class sve_int_pcount_pred<bits<2> sz8_64, bits<4> opc, string asm,
   let Inst{31-24} = 0b00100101;
   let Inst{23-22} = sz8_64;
   let Inst{21-19} = 0b100;
-  let Inst{18-16} = opc{3-1};
+  let Inst{18-16} = opc{2-0};
   let Inst{15-14} = 0b10;
   let Inst{13-10} = Pg;
-  let Inst{9}     = opc{0};
+  let Inst{9}     = 0b0;
   let Inst{8-5}   = Pn;
   let Inst{4-0}   = Rd;
 
   let hasSideEffects = 0;
 }
 
-multiclass sve_int_pcount_pred<bits<4> opc, string asm,
+multiclass sve_int_pcount_pred<bits<3> opc, string asm,
                                SDPatternOperator int_op> {
   def _B : sve_int_pcount_pred<0b00, opc, asm, PPR8>;
   def _H : sve_int_pcount_pred<0b01, opc, asm, PPR16>;
@@ -1081,6 +1081,12 @@ multiclass sve_int_pcount_pred<bits<4> opc, string asm,
   def : SVE_2_Op_Pat<i64, int_op, nxv2i1,  nxv2i1,  !cast<Instruction>(NAME # _D)>;
 }
 
+multiclass sve_int_pcount_pred_tmp<bits<3> opc, string asm> {
+  def _B : sve_int_pcount_pred<0b00, opc, asm, PPR8>;
+  def _H : sve_int_pcount_pred<0b01, opc, asm, PPR16>;
+  def _S : sve_int_pcount_pred<0b10, opc, asm, PPR32>;
+  def _D : sve_int_pcount_pred<0b11, opc, asm, PPR64>;
+}
 //===----------------------------------------------------------------------===//
 // SVE Element Count Group
 //===----------------------------------------------------------------------===//
diff --git a/llvm/test/MC/AArch64/SVE2p2/firstp-diagnostics.s b/llvm/test/MC/AArch64/SVE2p2/firstp-diagnostics.s
new file mode 100644
index 00000000000000..942b277f68c154
--- /dev/null
+++ b/llvm/test/MC/AArch64/SVE2p2/firstp-diagnostics.s
@@ -0,0 +1,32 @@
+// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2p2 2>&1 < %s| FileCheck %s
+
+// ------------------------------------------------------------------------- //
+// Invalid predicate operand
+
+firstp  x0, p15, p0
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid predicate register.
+// CHECK-NEXT: firstp  x0, p15, p0
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+firstp  x0, p15.b, p0.b
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid predicate register.
+// CHECK-NEXT: firstp  x0, p15.b, p0.b
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+firstp  x0, p15.q, p0.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid predicate register.
+// CHECK-NEXT: firstp  x0, p15.q, p0.h
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+// ------------------------------------------------------------------------- //
+// Invalid register types
+
+firstp  sp, p15.q, p0.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: firstp  sp, p15.q, p0.h
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+firstp  w0, p15.q, p0.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: firstp  w0, p15.q, p0.h
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
diff --git a/llvm/test/MC/AArch64/SVE2p2/firstp.s b/llvm/test/MC/AArch64/SVE2p2/firstp.s
new file mode 100644
index 00000000000000..629bee5576fc7d
--- /dev/null
+++ b/llvm/test/MC/AArch64/SVE2p2/firstp.s
@@ -0,0 +1,87 @@
+// 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=-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=+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
+
+firstp  x0, p0, p0.b  // 00100101-00100001-10000000-00000000
+// CHECK-INST: firstp  x0, p0, p0.b
+// CHECK-ENCODING: [0x00,0x80,0x21,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 25218000 <unknown>
+
+firstp  x23, p11, p13.b  // 00100101-00100001-10101101-10110111
+// CHECK-INST: firstp  x23, p11, p13.b
+// CHECK-ENCODING: [0xb7,0xad,0x21,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 2521adb7 <unknown>
+
+firstp  xzr, p15, p15.b  // 00100101-00100001-10111101-11111111
+// CHECK-INST: firstp  xzr, p15, p15.b
+// CHECK-ENCODING: [0xff,0xbd,0x21,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 2521bdff <unknown>
+
+firstp  x0, p0, p0.h  // 00100101-01100001-10000000-00000000
+// CHECK-INST: firstp  x0, p0, p0.h
+// CHECK-ENCODING: [0x00,0x80,0x61,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 25618000 <unknown>
+
+firstp  x23, p11, p13.h  // 00100101-01100001-10101101-10110111
+// CHECK-INST: firstp  x23, p11, p13.h
+// CHECK-ENCODING: [0xb7,0xad,0x61,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 2561adb7 <unknown>
+
+firstp  xzr, p15, p15.h  // 00100101-01100001-10111101-11111111
+// CHECK-INST: firstp  xzr, p15, p15.h
+// CHECK-ENCODING: [0xff,0xbd,0x61,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 2561bdff <unknown>
+
+firstp  x0, p0, p0.s  // 00100101-10100001-10000000-00000000
+// CHECK-INST: firstp  x0, p0, p0.s
+// CHECK-ENCODING: [0x00,0x80,0xa1,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 25a18000 <unknown>
+
+firstp  x23, p11, p13.s  // 00100101-10100001-10101101-10110111
+// CHECK-INST: firstp  x23, p11, p13.s
+// CHECK-ENCODING: [0xb7,0xad,0xa1,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 25a1adb7 <unknown>
+
+firstp  xzr, p15, p15.s  // 00100101-10100001-10111101-11111111
+// CHECK-INST: firstp  xzr, p15, p15.s
+// CHECK-ENCODING: [0xff,0xbd,0xa1,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 25a1bdff <unknown>
+
+firstp  x0, p0, p0.d  // 00100101-11100001-10000000-00000000
+// CHECK-INST: firstp  x0, p0, p0.d
+// CHECK-ENCODING: [0x00,0x80,0xe1,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 25e18000 <unknown>
+
+firstp  x23, p11, p13.d  // 00100101-11100001-10101101-10110111
+// CHECK-INST: firstp  x23, p11, p13.d
+// CHECK-ENCODING: [0xb7,0xad,0xe1,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 25e1adb7 <unknown>
+
+firstp  xzr, p15, p15.d  // 00100101-11100001-10111101-11111111
+// CHECK-INST: firstp  xzr, p15, p15.d
+// CHECK-ENCODING: [0xff,0xbd,0xe1,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 25e1bdff <unknown>
\ No newline at end of file
diff --git a/llvm/test/MC/AArch64/SVE2p2/lastp-diagnostics.s b/llvm/test/MC/AArch64/SVE2p2/lastp-diagnostics.s
new file mode 100644
index 00000000000000..fecb52c6006b55
--- /dev/null
+++ b/llvm/test/MC/AArch64/SVE2p2/lastp-diagnostics.s
@@ -0,0 +1,32 @@
+// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2p2 2>&1 < %s| FileCheck %s
+
+// ------------------------------------------------------------------------- //
+// Invalid predicate operand
+
+lastp  x0, p15, p0
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid predicate register.
+// CHECK-NEXT: lastp  x0, p15, p0
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+lastp  x0, p15.b, p0.b
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid predicate register.
+// CHECK-NEXT: lastp  x0, p15.b, p0.b
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+lastp  x0, p15.q, p0.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid predicate register.
+// CHECK-NEXT: lastp  x0, p15.q, p0.h
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+// ------------------------------------------------------------------------- //
+// Invalid register types
+
+lastp  sp, p15.q, p0.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: lastp  sp, p15.q, p0.h
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+lastp  w0, p15.q, p0.h
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: lastp  w0, p15.q, p0.h
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
\ No newline at end of file
diff --git a/llvm/test/MC/AArch64/SVE2p2/lastp.s b/llvm/test/MC/AArch64/SVE2p2/lastp.s
new file mode 100644
index 00000000000000..1ffa0a7d1fcc19
--- /dev/null
+++ b/llvm/test/MC/AArch64/SVE2p2/lastp.s
@@ -0,0 +1,87 @@
+// 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=-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=+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
+
+lastp   x0, p0, p0.b  // 00100101-00100010-10000000-00000000
+// CHECK-INST: lastp   x0, p0, p0.b
+// CHECK-ENCODING: [0x00,0x80,0x22,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 25228000 <unknown>
+
+lastp   x23, p11, p13.b  // 00100101-00100010-10101101-10110111
+// CHECK-INST: lastp   x23, p11, p13.b
+// CHECK-ENCODING: [0xb7,0xad,0x22,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 2522adb7 <unknown>
+
+lastp   xzr, p15, p15.b  // 00100101-00100010-10111101-11111111
+// CHECK-INST: lastp   xzr, p15, p15.b
+// CHECK-ENCODING: [0xff,0xbd,0x22,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 2522bdff <unknown>
+
+lastp   x0, p0, p0.h  // 00100101-01100010-10000000-00000000
+// CHECK-INST: lastp   x0, p0, p0.h
+// CHECK-ENCODING: [0x00,0x80,0x62,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 25628000 <unknown>
+
+lastp   x23, p11, p13.h  // 00100101-01100010-10101101-10110111
+// CHECK-INST: lastp   x23, p11, p13.h
+// CHECK-ENCODING: [0xb7,0xad,0x62,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 2562adb7 <unknown>
+
+lastp   xzr, p15, p15.h  // 00100101-01100010-10111101-11111111
+// CHECK-INST: lastp   xzr, p15, p15.h
+// CHECK-ENCODING: [0xff,0xbd,0x62,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 2562bdff <unknown>
+
+lastp   x0, p0, p0.s  // 00100101-10100010-10000000-00000000
+// CHECK-INST: lastp   x0, p0, p0.s
+// CHECK-ENCODING: [0x00,0x80,0xa2,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 25a28000 <unknown>
+
+lastp   x23, p11, p13.s  // 00100101-10100010-10101101-10110111
+// CHECK-INST: lastp   x23, p11, p13.s
+// CHECK-ENCODING: [0xb7,0xad,0xa2,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 25a2adb7 <unknown>
+
+lastp   xzr, p15, p15.s  // 00100101-10100010-10111101-11111111
+// CHECK-INST: lastp   xzr, p15, p15.s
+// CHECK-ENCODING: [0xff,0xbd,0xa2,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 25a2bdff <unknown>
+
+lastp   x0, p0, p0.d  // 00100101-11100010-10000000-00000000
+// CHECK-INST: lastp   x0, p0, p0.d
+// CHECK-ENCODING: [0x00,0x80,0xe2,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 25e28000 <unknown>
+
+lastp   x23, p11, p13.d  // 00100101-11100010-10101101-10110111
+// CHECK-INST: lastp   x23, p11, p13.d
+// CHECK-ENCODING: [0xb7,0xad,0xe2,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 25e2adb7 <unknown>
+
+lastp   xzr, p15, p15.d  // 00100101-11100010-10111101-11111111
+// CHECK-INST: lastp   xzr, p15, p15.d
+// CHECK-ENCODING: [0xff,0xbd,0xe2,0x25]
+// CHECK-ERROR: instruction requires: sme2p2 or sve2p2
+// CHECK-UNKNOWN: 25e2bdff <unknown>
\ No newline at end of file

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

llvm/test/MC/AArch64/SVE2p2/firstp-diagnostics.s Outdated Show resolved Hide resolved
llvm/test/MC/AArch64/SVE2p2/firstp-diagnostics.s Outdated Show resolved Hide resolved
llvm/test/MC/AArch64/SVE2p2/lastp-diagnostics.s Outdated Show resolved Hide resolved
llvm/test/MC/AArch64/SVE2p2/lastp-diagnostics.s Outdated Show resolved Hide resolved
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, thanks.

@Lukacma Lukacma merged commit 15f63ec into llvm:main Oct 30, 2024
8 checks passed
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