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
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion llvm/lib/Target/AArch64/AArch64.td
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
7 changes: 6 additions & 1 deletion llvm/lib/Target/AArch64/AArch64InstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -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'.
Expand Down
17 changes: 14 additions & 3 deletions llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -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>;
Expand Down Expand Up @@ -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
//===----------------------------------------------------------------------===//
Expand Down
43 changes: 37 additions & 6 deletions llvm/lib/Target/AArch64/SVEInstrFormats.td
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -7413,16 +7439,16 @@ 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",
"",
[]>, Sched<[]> {
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;
Expand All @@ -7431,16 +7457,21 @@ 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)>;
def : SVE_2_Op_Pat<nxv2i64, op, nxv2i1, nxv2i64, !cast<Instruction>(NAME # _D)>;
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
//===----------------------------------------------------------------------===//
Expand Down
4 changes: 2 additions & 2 deletions llvm/test/MC/AArch64/SVE/compact-diagnostics.s
Original file line number Diff line number Diff line change
Expand Up @@ -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]+}}:

Expand Down
4 changes: 2 additions & 2 deletions llvm/test/MC/AArch64/SVE/compact.s
Original file line number Diff line number Diff line change
Expand Up @@ -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>
65 changes: 65 additions & 0 deletions llvm/test/MC/AArch64/SVE2p2/compact-diagnostics.s
Original file line number Diff line number Diff line change
@@ -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]+}}:
33 changes: 33 additions & 0 deletions llvm/test/MC/AArch64/SVE2p2/compact.s
Original file line number Diff line number Diff line change
@@ -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>
120 changes: 120 additions & 0 deletions llvm/test/MC/AArch64/SVE2p2/expand-diagnostics.s
Original file line number Diff line number Diff line change
@@ -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]+}}:
Loading
Loading