Skip to content

Commit

Permalink
[AARCH64] Add assembly/disassmbly for FIRST,LASTP instr. (llvm#114049)
Browse files Browse the repository at this point in the history
This patch adds assembly/disassembly and tests for new FIRSTP
and LASTP instructions introduced in
https://developer.arm.com/documentation/ddi0602/2024-09

---------

Co-authored-by: SpencerAbson <Spencer.Abson@arm.com>
  • Loading branch information
Lukacma and SpencerAbson authored Oct 30, 2024
1 parent 85f3d5c commit 15f63ec
Show file tree
Hide file tree
Showing 6 changed files with 252 additions and 5 deletions.
5 changes: 4 additions & 1 deletion llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -2129,7 +2129,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),
Expand Down Expand Up @@ -4304,6 +4304,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

//===----------------------------------------------------------------------===//
Expand Down
14 changes: 10 additions & 4 deletions llvm/lib/Target/AArch64/SVEInstrFormats.td
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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>;
Expand All @@ -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
//===----------------------------------------------------------------------===//
Expand Down
32 changes: 32 additions & 0 deletions llvm/test/MC/AArch64/SVE2p2/firstp-diagnostics.s
Original file line number Diff line number Diff line change
@@ -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, p0.h
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
// CHECK-NEXT: firstp sp, p15, p0.h
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:

firstp w0, p15, p0.h
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
// CHECK-NEXT: firstp w0, p15, p0.h
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
87 changes: 87 additions & 0 deletions llvm/test/MC/AArch64/SVE2p2/firstp.s
Original file line number Diff line number Diff line change
@@ -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>
32 changes: 32 additions & 0 deletions llvm/test/MC/AArch64/SVE2p2/lastp-diagnostics.s
Original file line number Diff line number Diff line change
@@ -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, p0.h
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
// CHECK-NEXT: lastp sp, p15, p0.h
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:

lastp w0, p15, p0.h
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
// CHECK-NEXT: lastp w0, p15, p0.h
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
87 changes: 87 additions & 0 deletions llvm/test/MC/AArch64/SVE2p2/lastp.s
Original file line number Diff line number Diff line change
@@ -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>

0 comments on commit 15f63ec

Please sign in to comment.