From d239eb3ce375b238ac2793152417754795b371ba Mon Sep 17 00:00:00 2001 From: Sander de Smalen Date: Mon, 16 Apr 2018 10:10:48 +0000 Subject: [PATCH] [AArch64][SVE] Asm: Support for structured LD3 (scalar+imm) load instructions. Reviewers: fhahn, rengolin, javed.absar, huntergr, SjoerdMeijer, t.p.northover, echristo, evandro Reviewed By: rengolin Subscribers: tschuett, kristof.beyls, llvm-commits Differential Revision: https://reviews.llvm.org/D45623 llvm-svn: 330116 --- .../lib/Target/AArch64/AArch64RegisterInfo.td | 21 ++++++ .../lib/Target/AArch64/AArch64SVEInstrInfo.td | 4 ++ .../AArch64/AsmParser/AArch64AsmParser.cpp | 10 ++- .../Disassembler/AArch64Disassembler.cpp | 27 ++++++++ .../InstPrinter/AArch64InstPrinter.cpp | 1 + llvm/lib/Target/AArch64/SVEInstrFormats.td | 9 +++ llvm/test/MC/AArch64/SVE/ld3b-diagnostics.s | 67 +++++++++++++++++++ llvm/test/MC/AArch64/SVE/ld3b.s | 26 +++++++ llvm/test/MC/AArch64/SVE/ld3d-diagnostics.s | 67 +++++++++++++++++++ llvm/test/MC/AArch64/SVE/ld3d.s | 26 +++++++ llvm/test/MC/AArch64/SVE/ld3h-diagnostics.s | 67 +++++++++++++++++++ llvm/test/MC/AArch64/SVE/ld3h.s | 26 +++++++ llvm/test/MC/AArch64/SVE/ld3w-diagnostics.s | 67 +++++++++++++++++++ llvm/test/MC/AArch64/SVE/ld3w.s | 26 +++++++ 14 files changed, 441 insertions(+), 3 deletions(-) create mode 100644 llvm/test/MC/AArch64/SVE/ld3b-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE/ld3b.s create mode 100644 llvm/test/MC/AArch64/SVE/ld3d-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE/ld3d.s create mode 100644 llvm/test/MC/AArch64/SVE/ld3h-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE/ld3h.s create mode 100644 llvm/test/MC/AArch64/SVE/ld3w-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE/ld3w.s diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.td b/llvm/lib/Target/AArch64/AArch64RegisterInfo.td index 1e320be16d47..8022b104da9f 100644 --- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.td +++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.td @@ -842,14 +842,19 @@ def ZPR128 : ZPRRegOp<"q", ZPRAsmOp128, ZPR>; let Namespace = "AArch64" in { def zsub0 : SubRegIndex<128, -1>; def zsub1 : SubRegIndex<128, -1>; + def zsub2 : SubRegIndex<128, -1>; } // Pairs, triples, and quads of SVE vector registers. def ZSeqPairs : RegisterTuples<[zsub0, zsub1], [(rotl ZPR, 0), (rotl ZPR, 1)]>; +def ZSeqTriples : RegisterTuples<[zsub0, zsub1, zsub2], [(rotl ZPR, 0), (rotl ZPR, 1), (rotl ZPR, 2)]>; def ZPR2 : RegisterClass<"AArch64", [untyped], 128, (add ZSeqPairs)> { let Size = 256; } +def ZPR3 : RegisterClass<"AArch64", [untyped], 128, (add ZSeqTriples)> { + let Size = 384; +} class ZPRVectorList : AsmOperandClass { let Name = "SVEVectorList" # NumRegs # ElementWidth; @@ -890,3 +895,19 @@ def ZZ_s : RegisterOperand"> { def ZZ_d : RegisterOperand"> { let ParserMatchClass = ZPRVectorList<64, 2>; } + +def ZZZ_b : RegisterOperand"> { + let ParserMatchClass = ZPRVectorList<8, 3>; +} + +def ZZZ_h : RegisterOperand"> { + let ParserMatchClass = ZPRVectorList<16, 3>; +} + +def ZZZ_s : RegisterOperand"> { + let ParserMatchClass = ZPRVectorList<32, 3>; +} + +def ZZZ_d : RegisterOperand"> { + let ParserMatchClass = ZPRVectorList<64, 3>; +} diff --git a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td index 0406c52e872c..eae76ac937e1 100644 --- a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td @@ -40,9 +40,13 @@ let Predicates = [HasSVE] in { // LD(2|3|4) structured loads with reg+immediate defm LD2B_IMM : sve_mem_eld_si<0b00, 0b01, ZZ_b, "ld2b", simm4Scale2MulVl>; + defm LD3B_IMM : sve_mem_eld_si<0b00, 0b10, ZZZ_b, "ld3b", simm4Scale3MulVl>; defm LD2H_IMM : sve_mem_eld_si<0b01, 0b01, ZZ_h, "ld2h", simm4Scale2MulVl>; + defm LD3H_IMM : sve_mem_eld_si<0b01, 0b10, ZZZ_h, "ld3h", simm4Scale3MulVl>; defm LD2W_IMM : sve_mem_eld_si<0b10, 0b01, ZZ_s, "ld2w", simm4Scale2MulVl>; + defm LD3W_IMM : sve_mem_eld_si<0b10, 0b10, ZZZ_s, "ld3w", simm4Scale3MulVl>; defm LD2D_IMM : sve_mem_eld_si<0b11, 0b01, ZZ_d, "ld2d", simm4Scale2MulVl>; + defm LD3D_IMM : sve_mem_eld_si<0b11, 0b10, ZZZ_d, "ld3d", simm4Scale3MulVl>; // continuous store with immediates defm ST1B_IMM : sve_mem_cst_si<0b00, 0b00, "st1b", Z_b, ZPR8>; diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp index b3b3f0672bf4..82a3e49ca443 100644 --- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -1154,11 +1154,12 @@ public: AArch64::Q0, AArch64::Q0_Q1, AArch64::Q0_Q1_Q2, AArch64::Q0_Q1_Q2_Q3 }, /* ZReg */ { AArch64::Z0, - AArch64::Z0, AArch64::Z0_Z1 } + AArch64::Z0, AArch64::Z0_Z1, + AArch64::Z0_Z1_Z2 } }; - assert((RegTy != VecListIdx_ZReg || NumRegs <= 2) && - " NumRegs must be <= 2 for ZRegs"); + assert((RegTy != VecListIdx_ZReg || NumRegs <= 3) && + " NumRegs must be <= 3 for ZRegs"); unsigned FirstReg = FirstRegs[(unsigned)RegTy][NumRegs]; Inst.addOperand(MCOperand::createReg(FirstReg + getVectorListStart() - @@ -3649,6 +3650,8 @@ bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode, return Error(Loc, "index must be an integer in range [-8, 7]."); case Match_InvalidMemoryIndexed2SImm4: return Error(Loc, "index must be a multiple of 2 in range [-16, 14]."); + case Match_InvalidMemoryIndexed3SImm4: + return Error(Loc, "index must be a multiple of 3 in range [-24, 21]."); case Match_InvalidMemoryIndexedSImm9: return Error(Loc, "index must be an integer in range [-256, 255]."); case Match_InvalidMemoryIndexedSImm10: @@ -4165,6 +4168,7 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, case Match_InvalidMemoryXExtend128: case Match_InvalidMemoryIndexed1SImm4: case Match_InvalidMemoryIndexed2SImm4: + case Match_InvalidMemoryIndexed3SImm4: case Match_InvalidMemoryIndexed4SImm7: case Match_InvalidMemoryIndexed8SImm7: case Match_InvalidMemoryIndexed16SImm7: diff --git a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp index 19783d3f9d3e..ff1904cec78d 100644 --- a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp +++ b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp @@ -91,6 +91,9 @@ static DecodeStatus DecodeZPRRegisterClass(MCInst &Inst, unsigned RegNo, static DecodeStatus DecodeZPR2RegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decode); +static DecodeStatus DecodeZPR3RegisterClass(MCInst &Inst, unsigned RegNo, + uint64_t Address, + const void *Decode); static DecodeStatus DecodePPRRegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decode); @@ -495,6 +498,30 @@ static DecodeStatus DecodeZPR2RegisterClass(MCInst &Inst, unsigned RegNo, return Success; } +static const unsigned ZZZDecoderTable[] = { + AArch64::Z0_Z1_Z2, AArch64::Z1_Z2_Z3, AArch64::Z2_Z3_Z4, + AArch64::Z3_Z4_Z5, AArch64::Z4_Z5_Z6, AArch64::Z5_Z6_Z7, + AArch64::Z6_Z7_Z8, AArch64::Z7_Z8_Z9, AArch64::Z8_Z9_Z10, + AArch64::Z9_Z10_Z11, AArch64::Z10_Z11_Z12, AArch64::Z11_Z12_Z13, + AArch64::Z12_Z13_Z14, AArch64::Z13_Z14_Z15, AArch64::Z14_Z15_Z16, + AArch64::Z15_Z16_Z17, AArch64::Z16_Z17_Z18, AArch64::Z17_Z18_Z19, + AArch64::Z18_Z19_Z20, AArch64::Z19_Z20_Z21, AArch64::Z20_Z21_Z22, + AArch64::Z21_Z22_Z23, AArch64::Z22_Z23_Z24, AArch64::Z23_Z24_Z25, + AArch64::Z24_Z25_Z26, AArch64::Z25_Z26_Z27, AArch64::Z26_Z27_Z28, + AArch64::Z27_Z28_Z29, AArch64::Z28_Z29_Z30, AArch64::Z29_Z30_Z31, + AArch64::Z30_Z31_Z0, AArch64::Z31_Z0_Z1 +}; + +static DecodeStatus DecodeZPR3RegisterClass(MCInst &Inst, unsigned RegNo, + uint64_t Address, + const void* Decoder) { + if (RegNo > 31) + return Fail; + unsigned Register = ZZZDecoderTable[RegNo]; + Inst.addOperand(MCOperand::createReg(Register)); + return Success; +} + static const unsigned PPRDecoderTable[] = { AArch64::P0, AArch64::P1, AArch64::P2, AArch64::P3, AArch64::P4, AArch64::P5, AArch64::P6, AArch64::P7, diff --git a/llvm/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp b/llvm/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp index b36ce3ad2e93..abea344355cd 100644 --- a/llvm/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp +++ b/llvm/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp @@ -1184,6 +1184,7 @@ void AArch64InstPrinter::printVectorList(const MCInst *MI, unsigned OpNum, MRI.getRegClass(AArch64::QQRegClassID).contains(Reg)) NumRegs = 2; else if (MRI.getRegClass(AArch64::DDDRegClassID).contains(Reg) || + MRI.getRegClass(AArch64::ZPR3RegClassID).contains(Reg) || MRI.getRegClass(AArch64::QQQRegClassID).contains(Reg)) NumRegs = 3; else if (MRI.getRegClass(AArch64::DDDDRegClassID).contains(Reg) || diff --git a/llvm/lib/Target/AArch64/SVEInstrFormats.td b/llvm/lib/Target/AArch64/SVEInstrFormats.td index a21a7dc090cf..0874f236a755 100644 --- a/llvm/lib/Target/AArch64/SVEInstrFormats.td +++ b/llvm/lib/Target/AArch64/SVEInstrFormats.td @@ -37,6 +37,7 @@ class SImmMulVlOperand : AsmOperandClass { def SImm4MulVlOperand : SImmMulVlOperand<4,1>; def SImm4Scale2MulVlOperand : SImmMulVlOperand<4,2>; +def SImm4Scale3MulVlOperand : SImmMulVlOperand<4,3>; def simm4MulVl : Operand, ImmLeaf= -8 && Imm < 8; }]> { let DecoderMethod = "DecodeSImm<4>"; @@ -51,6 +52,14 @@ def simm4Scale2MulVl : Operand, ImmLeaf, ImmLeaf= -24 && Imm <= 21) && ((Imm % 3) == 0x0); + }]> { + let DecoderMethod = "DecodeSImm<4>"; + let PrintMethod = "printImmScale<3>"; + let ParserMatchClass = SImm4Scale3MulVlOperand; +} + class SVELogicalImmOperand : AsmOperandClass { let Name = "SVELogicalImm" # Width; let DiagnosticType = "LogicalSecondSource"; diff --git a/llvm/test/MC/AArch64/SVE/ld3b-diagnostics.s b/llvm/test/MC/AArch64/SVE/ld3b-diagnostics.s new file mode 100644 index 000000000000..d07dafad5e1f --- /dev/null +++ b/llvm/test/MC/AArch64/SVE/ld3b-diagnostics.s @@ -0,0 +1,67 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve 2>&1 < %s| FileCheck %s + + +// --------------------------------------------------------------------------// +// Immediate out of lower bound [-24, 21]. + +ld3b {z12.b, z13.b, z14.b}, p4/z, [x12, #-27, MUL VL] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 3 in range [-24, 21]. +// CHECK-NEXT: ld3b {z12.b, z13.b, z14.b}, p4/z, [x12, #-27, MUL VL] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld3b {z7.b, z8.b, z9.b}, p3/z, [x1, #24, MUL VL] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 3 in range [-24, 21]. +// CHECK-NEXT: ld3b {z7.b, z8.b, z9.b}, p3/z, [x1, #24, MUL VL] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Immediate not a multiple of three. + +ld3b {z12.b, z13.b, z14.b}, p4/z, [x12, #-7, MUL VL] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 3 in range [-24, 21]. +// CHECK-NEXT: ld3b {z12.b, z13.b, z14.b}, p4/z, [x12, #-7, MUL VL] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld3b {z7.b, z8.b, z9.b}, p3/z, [x1, #5, MUL VL] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 3 in range [-24, 21]. +// CHECK-NEXT: ld3b {z7.b, z8.b, z9.b}, p3/z, [x1, #5, MUL VL] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// error: restricted predicate has range [0, 7]. + +ld3b {z2.b, z3.b, z4.b}, p8/z, [x15, #10, MUL VL] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: restricted predicate has range [0, 7]. +// CHECK-NEXT: ld3b {z2.b, z3.b, z4.b}, p8/z, [x15, #10, MUL VL] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid vector list. + +ld3b { }, p0/z, [x0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector register expected +// CHECK-NEXT: ld3b { }, p0/z, [x0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld3b { z0.b, z1.b, z2.b, z3.b }, p0/z, [x0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand +// CHECK-NEXT: ld3b { z0.b, z1.b, z2.b, z3.b }, p0/z, [x0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld3b { z0.b, z1.b, z2.h }, p0/z, [x0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: mismatched register size suffix +// CHECK-NEXT: ld3b { z0.b, z1.b, z2.h }, p0/z, [x0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld3b { z0.b, z1.b, z3.b }, p0/z, [x0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: registers must be sequential +// CHECK-NEXT: ld3b { z0.b, z1.b, z3.b }, p0/z, [x0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld3b { v0.16b, v1.16b, v2.16b }, p0/z, [x0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand +// CHECK-NEXT: ld3b { v0.16b, v1.16b, v2.16b }, p0/z, [x0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE/ld3b.s b/llvm/test/MC/AArch64/SVE/ld3b.s new file mode 100644 index 000000000000..748f59cad83a --- /dev/null +++ b/llvm/test/MC/AArch64/SVE/ld3b.s @@ -0,0 +1,26 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve < %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=+sve < %s \ +// RUN: | llvm-objdump -d -mattr=+sve - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +ld3b { z0.b, z1.b, z2.b }, p0/z, [x0] +// CHECK-INST: ld3b { z0.b, z1.b, z2.b }, p0/z, [x0] +// CHECK-ENCODING: [0x00,0xe0,0x40,0xa4] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 e0 40 a4 + +ld3b { z23.b, z24.b, z25.b }, p3/z, [x13, #-24, mul vl] +// CHECK-INST: ld3b { z23.b, z24.b, z25.b }, p3/z, [x13, #-24, mul vl] +// CHECK-ENCODING: [0xb7,0xed,0x48,0xa4] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: b7 ed 48 a4 + +ld3b { z21.b, z22.b, z23.b }, p5/z, [x10, #15, mul vl] +// CHECK-INST: ld3b { z21.b, z22.b, z23.b }, p5/z, [x10, #15, mul vl] +// CHECK-ENCODING: [0x55,0xf5,0x45,0xa4] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 55 f5 45 a4 diff --git a/llvm/test/MC/AArch64/SVE/ld3d-diagnostics.s b/llvm/test/MC/AArch64/SVE/ld3d-diagnostics.s new file mode 100644 index 000000000000..96f17217de2c --- /dev/null +++ b/llvm/test/MC/AArch64/SVE/ld3d-diagnostics.s @@ -0,0 +1,67 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve 2>&1 < %s| FileCheck %s + + +// --------------------------------------------------------------------------// +// Immediate out of lower bound [-24, 21]. + +ld3d {z12.d, z13.d, z14.d}, p4/z, [x12, #-27, MUL VL] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 3 in range [-24, 21]. +// CHECK-NEXT: ld3d {z12.d, z13.d, z14.d}, p4/z, [x12, #-27, MUL VL] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld3d {z7.d, z8.d, z9.d}, p3/z, [x1, #24, MUL VL] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 3 in range [-24, 21]. +// CHECK-NEXT: ld3d {z7.d, z8.d, z9.d}, p3/z, [x1, #24, MUL VL] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Immediate not a multiple of three. + +ld3d {z12.d, z13.d, z14.d}, p4/z, [x12, #-7, MUL VL] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 3 in range [-24, 21]. +// CHECK-NEXT: ld3d {z12.d, z13.d, z14.d}, p4/z, [x12, #-7, MUL VL] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld3d {z7.d, z8.d, z9.d}, p3/z, [x1, #5, MUL VL] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 3 in range [-24, 21]. +// CHECK-NEXT: ld3d {z7.d, z8.d, z9.d}, p3/z, [x1, #5, MUL VL] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// error: restricted predicate has range [0, 7]. + +ld3d {z2.d, z3.d, z4.d}, p8/z, [x15, #10, MUL VL] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: restricted predicate has range [0, 7]. +// CHECK-NEXT: ld3d {z2.d, z3.d, z4.d}, p8/z, [x15, #10, MUL VL] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid vector list. + +ld3d { }, p0/z, [x0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector register expected +// CHECK-NEXT: ld3d { }, p0/z, [x0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld3d { z0.d, z1.d, z2.d, z3.d }, p0/z, [x0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand +// CHECK-NEXT: ld3d { z0.d, z1.d, z2.d, z3.d }, p0/z, [x0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld3d { z0.d, z1.d, z2.b }, p0/z, [x0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: mismatched register size suffix +// CHECK-NEXT: ld3d { z0.d, z1.d, z2.b }, p0/z, [x0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld3d { z0.d, z1.d, z3.d }, p0/z, [x0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: registers must be sequential +// CHECK-NEXT: ld3d { z0.d, z1.d, z3.d }, p0/z, [x0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld3d { v0.2d, v1.2d, v2.2d }, p0/z, [x0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand +// CHECK-NEXT: ld3d { v0.2d, v1.2d, v2.2d }, p0/z, [x0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE/ld3d.s b/llvm/test/MC/AArch64/SVE/ld3d.s new file mode 100644 index 000000000000..332c0ddaf8c0 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE/ld3d.s @@ -0,0 +1,26 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve < %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=+sve < %s \ +// RUN: | llvm-objdump -d -mattr=+sve - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +ld3d { z0.d, z1.d, z2.d }, p0/z, [x0] +// CHECK-INST: ld3d { z0.d, z1.d, z2.d }, p0/z, [x0] +// CHECK-ENCODING: [0x00,0xe0,0xc0,0xa5] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 e0 c0 a5 + +ld3d { z23.d, z24.d, z25.d }, p3/z, [x13, #-24, mul vl] +// CHECK-INST: ld3d { z23.d, z24.d, z25.d }, p3/z, [x13, #-24, mul vl] +// CHECK-ENCODING: [0xb7,0xed,0xc8,0xa5] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: b7 ed c8 a5 + +ld3d { z21.d, z22.d, z23.d }, p5/z, [x10, #15, mul vl] +// CHECK-INST: ld3d { z21.d, z22.d, z23.d }, p5/z, [x10, #15, mul vl] +// CHECK-ENCODING: [0x55,0xf5,0xc5,0xa5] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 55 f5 c5 a5 diff --git a/llvm/test/MC/AArch64/SVE/ld3h-diagnostics.s b/llvm/test/MC/AArch64/SVE/ld3h-diagnostics.s new file mode 100644 index 000000000000..545a96dac41a --- /dev/null +++ b/llvm/test/MC/AArch64/SVE/ld3h-diagnostics.s @@ -0,0 +1,67 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve 2>&1 < %s| FileCheck %s + + +// --------------------------------------------------------------------------// +// Immediate out of lower bound [-24, 21]. + +ld3h {z12.h, z13.h, z14.h}, p4/z, [x12, #-27, MUL VL] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 3 in range [-24, 21]. +// CHECK-NEXT: ld3h {z12.h, z13.h, z14.h}, p4/z, [x12, #-27, MUL VL] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld3h {z7.h, z8.h, z9.h}, p3/z, [x1, #24, MUL VL] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 3 in range [-24, 21]. +// CHECK-NEXT: ld3h {z7.h, z8.h, z9.h}, p3/z, [x1, #24, MUL VL] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Immediate not a multiple of three. + +ld3h {z12.h, z13.h, z14.h}, p4/z, [x12, #-7, MUL VL] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 3 in range [-24, 21]. +// CHECK-NEXT: ld3h {z12.h, z13.h, z14.h}, p4/z, [x12, #-7, MUL VL] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld3h {z7.h, z8.h, z9.h}, p3/z, [x1, #5, MUL VL] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 3 in range [-24, 21]. +// CHECK-NEXT: ld3h {z7.h, z8.h, z9.h}, p3/z, [x1, #5, MUL VL] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// error: restricted predicate has range [0, 7]. + +ld3h {z2.h, z3.h, z4.h}, p8/z, [x15, #10, MUL VL] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: restricted predicate has range [0, 7]. +// CHECK-NEXT: ld3h {z2.h, z3.h, z4.h}, p8/z, [x15, #10, MUL VL] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid vector list. + +ld3h { }, p0/z, [x0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector register expected +// CHECK-NEXT: ld3h { }, p0/z, [x0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld3h { z0.h, z1.h, z2.h, z3.h }, p0/z, [x0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand +// CHECK-NEXT: ld3h { z0.h, z1.h, z2.h, z3.h }, p0/z, [x0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld3h { z0.h, z1.h, z2.s }, p0/z, [x0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: mismatched register size suffix +// CHECK-NEXT: ld3h { z0.h, z1.h, z2.s }, p0/z, [x0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld3h { z0.h, z1.h, z3.h }, p0/z, [x0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: registers must be sequential +// CHECK-NEXT: ld3h { z0.h, z1.h, z3.h }, p0/z, [x0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld3h { v0.8h, v1.8h, v2.8h }, p0/z, [x0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand +// CHECK-NEXT: ld3h { v0.8h, v1.8h, v2.8h }, p0/z, [x0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE/ld3h.s b/llvm/test/MC/AArch64/SVE/ld3h.s new file mode 100644 index 000000000000..3de35f6ba336 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE/ld3h.s @@ -0,0 +1,26 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve < %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=+sve < %s \ +// RUN: | llvm-objdump -d -mattr=+sve - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +ld3h { z0.h, z1.h, z2.h }, p0/z, [x0] +// CHECK-INST: ld3h { z0.h, z1.h, z2.h }, p0/z, [x0] +// CHECK-ENCODING: [0x00,0xe0,0xc0,0xa4] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 e0 c0 a4 + +ld3h { z23.h, z24.h, z25.h }, p3/z, [x13, #-24, mul vl] +// CHECK-INST: ld3h { z23.h, z24.h, z25.h }, p3/z, [x13, #-24, mul vl] +// CHECK-ENCODING: [0xb7,0xed,0xc8,0xa4] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: b7 ed c8 a4 + +ld3h { z21.h, z22.h, z23.h }, p5/z, [x10, #15, mul vl] +// CHECK-INST: ld3h { z21.h, z22.h, z23.h }, p5/z, [x10, #15, mul vl] +// CHECK-ENCODING: [0x55,0xf5,0xc5,0xa4] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 55 f5 c5 a4 diff --git a/llvm/test/MC/AArch64/SVE/ld3w-diagnostics.s b/llvm/test/MC/AArch64/SVE/ld3w-diagnostics.s new file mode 100644 index 000000000000..6bca3761d459 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE/ld3w-diagnostics.s @@ -0,0 +1,67 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve 2>&1 < %s| FileCheck %s + + +// --------------------------------------------------------------------------// +// Immediate out of lower bound [-24, 21]. + +ld3w {z12.s, z13.s, z14.s}, p4/z, [x12, #-27, MUL VL] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 3 in range [-24, 21]. +// CHECK-NEXT: ld3w {z12.s, z13.s, z14.s}, p4/z, [x12, #-27, MUL VL] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld3w {z7.s, z8.s, z9.s}, p3/z, [x1, #24, MUL VL] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 3 in range [-24, 21]. +// CHECK-NEXT: ld3w {z7.s, z8.s, z9.s}, p3/z, [x1, #24, MUL VL] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Immediate not a multiple of three. + +ld3w {z12.s, z13.s, z14.s}, p4/z, [x12, #-7, MUL VL] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 3 in range [-24, 21]. +// CHECK-NEXT: ld3w {z12.s, z13.s, z14.s}, p4/z, [x12, #-7, MUL VL] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld3w {z7.s, z8.s, z9.s}, p3/z, [x1, #5, MUL VL] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 3 in range [-24, 21]. +// CHECK-NEXT: ld3w {z7.s, z8.s, z9.s}, p3/z, [x1, #5, MUL VL] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// error: restricted predicate has range [0, 7]. + +ld3w {z2.s, z3.s, z4.s}, p8/z, [x15, #10, MUL VL] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: restricted predicate has range [0, 7]. +// CHECK-NEXT: ld3w {z2.s, z3.s, z4.s}, p8/z, [x15, #10, MUL VL] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid vector list. + +ld3w { }, p0/z, [x0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector register expected +// CHECK-NEXT: ld3w { }, p0/z, [x0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld3w { z0.s, z1.s, z2.s, z3.s }, p0/z, [x0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand +// CHECK-NEXT: ld3w { z0.s, z1.s, z2.s, z3.s }, p0/z, [x0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld3w { z0.s, z1.s, z2.d }, p0/z, [x0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: mismatched register size suffix +// CHECK-NEXT: ld3w { z0.s, z1.s, z2.d }, p0/z, [x0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld3w { z0.s, z1.s, z3.s }, p0/z, [x0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: registers must be sequential +// CHECK-NEXT: ld3w { z0.s, z1.s, z3.s }, p0/z, [x0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld3w { v0.4s, v1.4s, v2.4s }, p0/z, [x0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand +// CHECK-NEXT: ld3w { v0.4s, v1.4s, v2.4s }, p0/z, [x0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE/ld3w.s b/llvm/test/MC/AArch64/SVE/ld3w.s new file mode 100644 index 000000000000..9b3cc0a07b00 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE/ld3w.s @@ -0,0 +1,26 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve < %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=+sve < %s \ +// RUN: | llvm-objdump -d -mattr=+sve - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +ld3w { z0.s, z1.s, z2.s }, p0/z, [x0] +// CHECK-INST: ld3w { z0.s, z1.s, z2.s }, p0/z, [x0] +// CHECK-ENCODING: [0x00,0xe0,0x40,0xa5] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 e0 40 a5 + +ld3w { z23.s, z24.s, z25.s }, p3/z, [x13, #-24, mul vl] +// CHECK-INST: ld3w { z23.s, z24.s, z25.s }, p3/z, [x13, #-24, mul vl] +// CHECK-ENCODING: [0xb7,0xed,0x48,0xa5] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: b7 ed 48 a5 + +ld3w { z21.s, z22.s, z23.s }, p5/z, [x10, #15, mul vl] +// CHECK-INST: ld3w { z21.s, z22.s, z23.s }, p5/z, [x10, #15, mul vl] +// CHECK-ENCODING: [0x55,0xf5,0x45,0xa5] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 55 f5 45 a5