[AArch64][SVE] Asm: Support for structured LD2 (scalar+imm) load instructions.
authorSander de Smalen <sander.desmalen@arm.com>
Mon, 16 Apr 2018 07:09:29 +0000 (07:09 +0000)
committerSander de Smalen <sander.desmalen@arm.com>
Mon, 16 Apr 2018 07:09:29 +0000 (07:09 +0000)
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/D45622

llvm-svn: 330108

14 files changed:
llvm/lib/Target/AArch64/AArch64RegisterInfo.td
llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
llvm/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp
llvm/lib/Target/AArch64/SVEInstrFormats.td
llvm/test/MC/AArch64/SVE/ld2b-diagnostics.s [new file with mode: 0644]
llvm/test/MC/AArch64/SVE/ld2b.s [new file with mode: 0644]
llvm/test/MC/AArch64/SVE/ld2d-diagnostics.s [new file with mode: 0644]
llvm/test/MC/AArch64/SVE/ld2d.s [new file with mode: 0644]
llvm/test/MC/AArch64/SVE/ld2h-diagnostics.s [new file with mode: 0644]
llvm/test/MC/AArch64/SVE/ld2h.s [new file with mode: 0644]
llvm/test/MC/AArch64/SVE/ld2w-diagnostics.s [new file with mode: 0644]
llvm/test/MC/AArch64/SVE/ld2w.s [new file with mode: 0644]

index a4e9b44..1e320be 100644 (file)
@@ -841,6 +841,14 @@ def ZPR128  : ZPRRegOp<"q", ZPRAsmOp128, ZPR>;
 
 let Namespace = "AArch64" in {
   def zsub0 : SubRegIndex<128, -1>;
+  def zsub1 : SubRegIndex<128, -1>;
+}
+
+// Pairs, triples, and quads of SVE vector registers.
+def ZSeqPairs   : RegisterTuples<[zsub0, zsub1], [(rotl ZPR, 0), (rotl ZPR, 1)]>;
+
+def ZPR2   : RegisterClass<"AArch64", [untyped], 128, (add ZSeqPairs)>  {
+  let Size = 256;
 }
 
 class ZPRVectorList<int ElementWidth, int NumRegs> : AsmOperandClass {
@@ -866,3 +874,19 @@ def Z_s  : RegisterOperand<ZPR,  "printTypedVectorList<0,'s'>"> {
 def Z_d  : RegisterOperand<ZPR,  "printTypedVectorList<0,'d'>"> {
   let ParserMatchClass = ZPRVectorList<64, 1>;
 }
+
+def ZZ_b  : RegisterOperand<ZPR2, "printTypedVectorList<0,'b'>"> {
+  let ParserMatchClass = ZPRVectorList<8, 2>;
+}
+
+def ZZ_h  : RegisterOperand<ZPR2, "printTypedVectorList<0,'h'>"> {
+  let ParserMatchClass = ZPRVectorList<16, 2>;
+}
+
+def ZZ_s  : RegisterOperand<ZPR2, "printTypedVectorList<0,'s'>"> {
+  let ParserMatchClass = ZPRVectorList<32, 2>;
+}
+
+def ZZ_d  : RegisterOperand<ZPR2, "printTypedVectorList<0,'d'>"> {
+  let ParserMatchClass = ZPRVectorList<64, 2>;
+}
index b3bed53..0406c52 100644 (file)
@@ -38,6 +38,12 @@ let Predicates = [HasSVE] in {
   defm LD1SB_H_IMM : sve_mem_cld_si<0b1110, "ld1sb", Z_h, ZPR16>;
   defm LD1D_IMM    : sve_mem_cld_si<0b1111, "ld1d",  Z_d, ZPR64>;
 
+  // LD(2|3|4) structured loads with reg+immediate
+  defm LD2B_IMM : sve_mem_eld_si<0b00, 0b01, ZZ_b,   "ld2b", simm4Scale2MulVl>;
+  defm LD2H_IMM : sve_mem_eld_si<0b01, 0b01, ZZ_h,   "ld2h", simm4Scale2MulVl>;
+  defm LD2W_IMM : sve_mem_eld_si<0b10, 0b01, ZZ_s,   "ld2w", simm4Scale2MulVl>;
+  defm LD2D_IMM : sve_mem_eld_si<0b11, 0b01, ZZ_d,   "ld2d", simm4Scale2MulVl>;
+
   // continuous store with immediates
   defm ST1B_IMM   : sve_mem_cst_si<0b00, 0b00, "st1b", Z_b, ZPR8>;
   defm ST1B_H_IMM : sve_mem_cst_si<0b00, 0b01, "st1b", Z_h, ZPR16>;
index 787c035..b3b3f06 100644 (file)
@@ -1154,11 +1154,11 @@ public:
                    AArch64::Q0,       AArch64::Q0_Q1,
                    AArch64::Q0_Q1_Q2, AArch64::Q0_Q1_Q2_Q3 },
       /* ZReg */ { AArch64::Z0,
-                   AArch64::Z0 }
+                   AArch64::Z0,       AArch64::Z0_Z1 }
     };
 
-    assert((RegTy != VecListIdx_ZReg || NumRegs <= 1) &&
-           " NumRegs must be 0 or 1 for ZRegs");
+    assert((RegTy != VecListIdx_ZReg || NumRegs <= 2) &&
+           " NumRegs must be <= 2 for ZRegs");
 
     unsigned FirstReg = FirstRegs[(unsigned)RegTy][NumRegs];
     Inst.addOperand(MCOperand::createReg(FirstReg + getVectorListStart() -
@@ -3647,6 +3647,8 @@ bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
     return Error(Loc, "index must be an integer in range [-16, 15].");
   case Match_InvalidMemoryIndexed1SImm4:
     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_InvalidMemoryIndexedSImm9:
     return Error(Loc, "index must be an integer in range [-256, 255].");
   case Match_InvalidMemoryIndexedSImm10:
@@ -4162,6 +4164,7 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
   case Match_InvalidMemoryXExtend64:
   case Match_InvalidMemoryXExtend128:
   case Match_InvalidMemoryIndexed1SImm4:
+  case Match_InvalidMemoryIndexed2SImm4:
   case Match_InvalidMemoryIndexed4SImm7:
   case Match_InvalidMemoryIndexed8SImm7:
   case Match_InvalidMemoryIndexed16SImm7:
index b4a554e..19783d3 100644 (file)
@@ -88,6 +88,9 @@ static DecodeStatus DecodeDDDDRegisterClass(MCInst &Inst, unsigned RegNo,
 static DecodeStatus DecodeZPRRegisterClass(MCInst &Inst, unsigned RegNo,
                                            uint64_t Address,
                                            const void *Decode);
+static DecodeStatus DecodeZPR2RegisterClass(MCInst &Inst, unsigned RegNo,
+                                            uint64_t Address,
+                                            const void *Decode);
 static DecodeStatus DecodePPRRegisterClass(MCInst &Inst, unsigned RegNo,
                                            uint64_t Address,
                                            const void *Decode);
@@ -471,6 +474,27 @@ static DecodeStatus DecodeZPRRegisterClass(MCInst &Inst, unsigned RegNo,
   return Success;
 }
 
+static const unsigned ZZDecoderTable[] = {
+  AArch64::Z0_Z1,   AArch64::Z1_Z2,   AArch64::Z2_Z3,   AArch64::Z3_Z4,
+  AArch64::Z4_Z5,   AArch64::Z5_Z6,   AArch64::Z6_Z7,   AArch64::Z7_Z8,
+  AArch64::Z8_Z9,   AArch64::Z9_Z10,  AArch64::Z10_Z11, AArch64::Z11_Z12,
+  AArch64::Z12_Z13, AArch64::Z13_Z14, AArch64::Z14_Z15, AArch64::Z15_Z16,
+  AArch64::Z16_Z17, AArch64::Z17_Z18, AArch64::Z18_Z19, AArch64::Z19_Z20,
+  AArch64::Z20_Z21, AArch64::Z21_Z22, AArch64::Z22_Z23, AArch64::Z23_Z24,
+  AArch64::Z24_Z25, AArch64::Z25_Z26, AArch64::Z26_Z27, AArch64::Z27_Z28,
+  AArch64::Z28_Z29, AArch64::Z29_Z30, AArch64::Z30_Z31, AArch64::Z31_Z0
+};
+
+static DecodeStatus DecodeZPR2RegisterClass(MCInst &Inst, unsigned RegNo,
+                                            uint64_t Address,
+                                            const void* Decoder) {
+  if (RegNo > 31)
+    return Fail;
+  unsigned Register = ZZDecoderTable[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,
index 4e39b96..b36ce3a 100644 (file)
@@ -1180,6 +1180,7 @@ void AArch64InstPrinter::printVectorList(const MCInst *MI, unsigned OpNum,
   // list).
   unsigned NumRegs = 1;
   if (MRI.getRegClass(AArch64::DDRegClassID).contains(Reg) ||
+      MRI.getRegClass(AArch64::ZPR2RegClassID).contains(Reg) ||
       MRI.getRegClass(AArch64::QQRegClassID).contains(Reg))
     NumRegs = 2;
   else if (MRI.getRegClass(AArch64::DDDRegClassID).contains(Reg) ||
index 95af668..a21a7dc 100644 (file)
@@ -36,12 +36,21 @@ class SImmMulVlOperand<int Bits, int Scale> : AsmOperandClass {
 }
 
 def SImm4MulVlOperand : SImmMulVlOperand<4,1>;
+def SImm4Scale2MulVlOperand : SImmMulVlOperand<4,2>;
 
 def simm4MulVl : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -8 && Imm < 8; }]> {
   let DecoderMethod = "DecodeSImm<4>";
   let ParserMatchClass = SImm4MulVlOperand;
 }
 
+def simm4Scale2MulVl : Operand<i64>, ImmLeaf<i64, [{
+    return (Imm >= -16 && Imm <= 14) && ((Imm % 2) == 0x0);
+  }]> {
+  let DecoderMethod = "DecodeSImm<4>";
+  let PrintMethod = "printImmScale<2>";
+  let ParserMatchClass = SImm4Scale2MulVlOperand;
+}
+
 class SVELogicalImmOperand<int Width> : AsmOperandClass {
   let Name = "SVELogicalImm" # Width;
   let DiagnosticType = "LogicalSecondSource";
@@ -618,4 +627,35 @@ multiclass sve_mem_cld_si_base<bits<4> dtype, bit nf, string asm,
 
 multiclass sve_mem_cld_si<bits<4> dtype, string asm, RegisterOperand listty,
                           ZPRRegOp zprty>
-: sve_mem_cld_si_base<dtype, 0, asm, listty, zprty>;
\ No newline at end of file
+: sve_mem_cld_si_base<dtype, 0, asm, listty, zprty>;
+
+class sve_mem_eld_si<bits<2> sz, bits<2> nregs, RegisterOperand VecList,
+                     string asm, Operand immtype>
+: I<(outs VecList:$Zt), (ins PPR3bAny:$Pg, GPR64sp:$Rn, immtype:$imm4),
+  asm, "\t$Zt, $Pg/z, [$Rn, $imm4, mul vl]",
+  "",
+  []>, Sched<[]> {
+  bits<5> Zt;
+  bits<3> Pg;
+  bits<5> Rn;
+  bits<4> imm4;
+  let Inst{31-25} = 0b1010010;
+  let Inst{24-23} = sz;
+  let Inst{22-21} = nregs;
+  let Inst{20}    = 0;
+  let Inst{19-16} = imm4;
+  let Inst{15-13} = 0b111;
+  let Inst{12-10} = Pg;
+  let Inst{9-5}   = Rn;
+  let Inst{4-0}   = Zt;
+
+  let mayLoad = 1;
+}
+
+multiclass sve_mem_eld_si<bits<2> sz, bits<2> nregs, RegisterOperand VecList,
+                          string asm, Operand immtype> {
+  def NAME : sve_mem_eld_si<sz, nregs, VecList, asm, immtype>;
+
+  def : InstAlias<asm # "\t$Zt, $Pg/z, [$Rn]",
+                  (!cast<Instruction>(NAME) VecList:$Zt, PPR3bAny:$Pg, GPR64sp:$Rn, 0), 1>;
+}
diff --git a/llvm/test/MC/AArch64/SVE/ld2b-diagnostics.s b/llvm/test/MC/AArch64/SVE/ld2b-diagnostics.s
new file mode 100644 (file)
index 0000000..a63c1b0
--- /dev/null
@@ -0,0 +1,67 @@
+// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve  2>&1 < %s| FileCheck %s
+
+
+// --------------------------------------------------------------------------//
+// Immediate out of lower bound [-16, 14].
+
+ld2b {z12.b, z13.b}, p4/z, [x12, #-18, MUL VL]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 2 in range [-16, 14].
+// CHECK-NEXT: ld2b {z12.b, z13.b}, p4/z, [x12, #-18, MUL VL]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+ld2b {z7.b, z8.b}, p3/z, [x1, #16, MUL VL]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 2 in range [-16, 14].
+// CHECK-NEXT: ld2b {z7.b, z8.b}, p3/z, [x1, #16, MUL VL]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+
+// --------------------------------------------------------------------------//
+// Immediate not a multiple of two.
+
+ld2b {z12.b, z13.b}, p4/z, [x12, #-7, MUL VL]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 2 in range [-16, 14].
+// CHECK-NEXT: ld2b {z12.b, z13.b}, p4/z, [x12, #-7, MUL VL]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+ld2b {z7.b, z8.b}, p3/z, [x1, #5, MUL VL]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 2 in range [-16, 14].
+// CHECK-NEXT: ld2b {z7.b, z8.b}, p3/z, [x1, #5, MUL VL]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+
+// --------------------------------------------------------------------------//
+// error: restricted predicate has range [0, 7].
+
+ld2b {z2.b, z3.b}, p8/z, [x15, #10, MUL VL]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: restricted predicate has range [0, 7].
+// CHECK-NEXT: ld2b {z2.b, z3.b}, p8/z, [x15, #10, MUL VL]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+
+// --------------------------------------------------------------------------//
+// Invalid vector list.
+
+ld2b { }, p0/z, [x0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector register expected
+// CHECK-NEXT: ld2b { }, p0/z, [x0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+ld2b { z0.b, z1.b, z2.b }, p0/z, [x0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand
+// CHECK-NEXT: ld2b { z0.b, z1.b, z2.b }, p0/z, [x0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+ld2b { z0.b, z1.h }, p0/z, [x0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: mismatched register size suffix
+// CHECK-NEXT: ld2b { z0.b, z1.h }, p0/z, [x0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+ld2b { z0.b, z2.b }, p0/z, [x0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: registers must be sequential
+// CHECK-NEXT: ld2b { z0.b, z2.b }, p0/z, [x0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+ld2b { v0.2d, v1.2d }, p0/z, [x0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand
+// CHECK-NEXT: ld2b { v0.2d, v1.2d }, p0/z, [x0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
diff --git a/llvm/test/MC/AArch64/SVE/ld2b.s b/llvm/test/MC/AArch64/SVE/ld2b.s
new file mode 100644 (file)
index 0000000..626a0a5
--- /dev/null
@@ -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
+
+ld2b    { z0.b, z1.b }, p0/z, [x0]
+// CHECK-INST: ld2b    { z0.b, z1.b }, p0/z, [x0]
+// CHECK-ENCODING: [0x00,0xe0,0x20,0xa4]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: 00 e0 20 a4 <unknown>
+
+ld2b    { z23.b, z24.b }, p3/z, [x13, #-16, mul vl]
+// CHECK-INST: ld2b    { z23.b, z24.b }, p3/z, [x13, #-16, mul vl]
+// CHECK-ENCODING: [0xb7,0xed,0x28,0xa4]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: b7 ed 28 a4 <unknown>
+
+ld2b    { z21.b, z22.b }, p5/z, [x10, #10, mul vl]
+// CHECK-INST: ld2b    { z21.b, z22.b }, p5/z, [x10, #10, mul vl]
+// CHECK-ENCODING: [0x55,0xf5,0x25,0xa4]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: 55 f5 25 a4 <unknown>
diff --git a/llvm/test/MC/AArch64/SVE/ld2d-diagnostics.s b/llvm/test/MC/AArch64/SVE/ld2d-diagnostics.s
new file mode 100644 (file)
index 0000000..a77070e
--- /dev/null
@@ -0,0 +1,67 @@
+// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve  2>&1 < %s| FileCheck %s
+
+
+// --------------------------------------------------------------------------//
+// Immediate out of lower bound [-16, 14].
+
+ld2d {z12.d, z13.d}, p4/z, [x12, #-18, MUL VL]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 2 in range [-16, 14].
+// CHECK-NEXT: ld2d {z12.d, z13.d}, p4/z, [x12, #-18, MUL VL]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+ld2d {z7.d, z8.d}, p3/z, [x1, #16, MUL VL]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 2 in range [-16, 14].
+// CHECK-NEXT: ld2d {z7.d, z8.d}, p3/z, [x1, #16, MUL VL]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+
+// --------------------------------------------------------------------------//
+// Immediate not a multiple of two.
+
+ld2d {z12.d, z13.d}, p4/z, [x12, #-7, MUL VL]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 2 in range [-16, 14].
+// CHECK-NEXT: ld2d {z12.d, z13.d}, p4/z, [x12, #-7, MUL VL]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+ld2d {z7.d, z8.d}, p3/z, [x1, #5, MUL VL]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 2 in range [-16, 14].
+// CHECK-NEXT: ld2d {z7.d, z8.d}, p3/z, [x1, #5, MUL VL]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+
+// --------------------------------------------------------------------------//
+// error: restricted predicate has range [0, 7].
+
+ld2d {z2.d, z3.d}, p8/z, [x15, #10, MUL VL]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: restricted predicate has range [0, 7].
+// CHECK-NEXT: ld2d {z2.d, z3.d}, p8/z, [x15, #10, MUL VL]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+
+// --------------------------------------------------------------------------//
+// Invalid vector list.
+
+ld2d { }, p0/z, [x0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector register expected
+// CHECK-NEXT: ld2d { }, p0/z, [x0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+ld2d { z0.d, z1.d, z2.d }, p0/z, [x0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand
+// CHECK-NEXT: ld2d { z0.d, z1.d, z2.d }, p0/z, [x0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+ld2d { z0.d, z1.b }, p0/z, [x0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: mismatched register size suffix
+// CHECK-NEXT: ld2d { z0.d, z1.b }, p0/z, [x0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+ld2d { z0.d, z2.d }, p0/z, [x0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: registers must be sequential
+// CHECK-NEXT: ld2d { z0.d, z2.d }, p0/z, [x0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+ld2d { v0.2d, v1.2d }, p0/z, [x0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand
+// CHECK-NEXT: ld2d { v0.2d, v1.2d }, p0/z, [x0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
diff --git a/llvm/test/MC/AArch64/SVE/ld2d.s b/llvm/test/MC/AArch64/SVE/ld2d.s
new file mode 100644 (file)
index 0000000..2544a69
--- /dev/null
@@ -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
+
+ld2d    { z0.d, z1.d }, p0/z, [x0]
+// CHECK-INST: ld2d    { z0.d, z1.d }, p0/z, [x0]
+// CHECK-ENCODING: [0x00,0xe0,0xa0,0xa5]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: 00 e0 a0 a5 <unknown>
+
+ld2d    { z23.d, z24.d }, p3/z, [x13, #-16, mul vl]
+// CHECK-INST: ld2d    { z23.d, z24.d }, p3/z, [x13, #-16, mul vl]
+// CHECK-ENCODING: [0xb7,0xed,0xa8,0xa5]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: b7 ed a8 a5 <unknown>
+
+ld2d    { z21.d, z22.d }, p5/z, [x10, #10, mul vl]
+// CHECK-INST: ld2d    { z21.d, z22.d }, p5/z, [x10, #10, mul vl]
+// CHECK-ENCODING: [0x55,0xf5,0xa5,0xa5]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: 55 f5 a5 a5 <unknown>
diff --git a/llvm/test/MC/AArch64/SVE/ld2h-diagnostics.s b/llvm/test/MC/AArch64/SVE/ld2h-diagnostics.s
new file mode 100644 (file)
index 0000000..35ae363
--- /dev/null
@@ -0,0 +1,67 @@
+// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve  2>&1 < %s| FileCheck %s
+
+
+// --------------------------------------------------------------------------//
+// Immediate out of lower bound [-16, 14].
+
+ld2h {z12.h, z13.h}, p4/z, [x12, #-18, MUL VL]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 2 in range [-16, 14].
+// CHECK-NEXT: ld2h {z12.h, z13.h}, p4/z, [x12, #-18, MUL VL]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+ld2h {z7.h, z8.h}, p3/z, [x1, #16, MUL VL]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 2 in range [-16, 14].
+// CHECK-NEXT: ld2h {z7.h, z8.h}, p3/z, [x1, #16, MUL VL]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+
+// --------------------------------------------------------------------------//
+// Immediate not a multiple of two.
+
+ld2h {z12.h, z13.h}, p4/z, [x12, #-7, MUL VL]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 2 in range [-16, 14].
+// CHECK-NEXT: ld2h {z12.h, z13.h}, p4/z, [x12, #-7, MUL VL]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+ld2h {z7.h, z8.h}, p3/z, [x1, #5, MUL VL]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 2 in range [-16, 14].
+// CHECK-NEXT: ld2h {z7.h, z8.h}, p3/z, [x1, #5, MUL VL]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+
+// --------------------------------------------------------------------------//
+// error: restricted predicate has range [0, 7].
+
+ld2h {z2.h, z3.h}, p8/z, [x15, #10, MUL VL]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: restricted predicate has range [0, 7].
+// CHECK-NEXT: ld2h {z2.h, z3.h}, p8/z, [x15, #10, MUL VL]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+
+// --------------------------------------------------------------------------//
+// Invalid vector list.
+
+ld2h { }, p0/z, [x0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector register expected
+// CHECK-NEXT: ld2h { }, p0/z, [x0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+ld2h { z0.h, z1.h, z2.h }, p0/z, [x0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand
+// CHECK-NEXT: ld2h { z0.h, z1.h, z2.h }, p0/z, [x0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+ld2h { z0.h, z1.s }, p0/z, [x0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: mismatched register size suffix
+// CHECK-NEXT: ld2h { z0.h, z1.s }, p0/z, [x0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+ld2h { z0.h, z2.h }, p0/z, [x0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: registers must be sequential
+// CHECK-NEXT: ld2h { z0.h, z2.h }, p0/z, [x0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+ld2h { v0.2d, v1.2d }, p0/z, [x0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand
+// CHECK-NEXT: ld2h { v0.2d, v1.2d }, p0/z, [x0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
diff --git a/llvm/test/MC/AArch64/SVE/ld2h.s b/llvm/test/MC/AArch64/SVE/ld2h.s
new file mode 100644 (file)
index 0000000..68eda33
--- /dev/null
@@ -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
+
+ld2h    { z0.h, z1.h }, p0/z, [x0]
+// CHECK-INST: ld2h    { z0.h, z1.h }, p0/z, [x0]
+// CHECK-ENCODING: [0x00,0xe0,0xa0,0xa4]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: 00 e0 a0 a4 <unknown>
+
+ld2h    { z23.h, z24.h }, p3/z, [x13, #-16, mul vl]
+// CHECK-INST: ld2h    { z23.h, z24.h }, p3/z, [x13, #-16, mul vl]
+// CHECK-ENCODING: [0xb7,0xed,0xa8,0xa4]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: b7 ed a8 a4 <unknown>
+
+ld2h    { z21.h, z22.h }, p5/z, [x10, #10, mul vl]
+// CHECK-INST: ld2h    { z21.h, z22.h }, p5/z, [x10, #10, mul vl]
+// CHECK-ENCODING: [0x55,0xf5,0xa5,0xa4]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: 55 f5 a5 a4 <unknown>
diff --git a/llvm/test/MC/AArch64/SVE/ld2w-diagnostics.s b/llvm/test/MC/AArch64/SVE/ld2w-diagnostics.s
new file mode 100644 (file)
index 0000000..d701040
--- /dev/null
@@ -0,0 +1,67 @@
+// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve  2>&1 < %s| FileCheck %s
+
+
+// --------------------------------------------------------------------------//
+// Immediate out of lower bound [-16, 14].
+
+ld2w {z12.s, z13.s}, p4/z, [x12, #-18, MUL VL]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 2 in range [-16, 14].
+// CHECK-NEXT: ld2w {z12.s, z13.s}, p4/z, [x12, #-18, MUL VL]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+ld2w {z7.s, z8.s}, p3/z, [x1, #16, MUL VL]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 2 in range [-16, 14].
+// CHECK-NEXT: ld2w {z7.s, z8.s}, p3/z, [x1, #16, MUL VL]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+
+// --------------------------------------------------------------------------//
+// Immediate not a multiple of two.
+
+ld2w {z12.s, z13.s}, p4/z, [x12, #-7, MUL VL]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 2 in range [-16, 14].
+// CHECK-NEXT: ld2w {z12.s, z13.s}, p4/z, [x12, #-7, MUL VL]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+ld2w {z7.s, z8.s}, p3/z, [x1, #5, MUL VL]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 2 in range [-16, 14].
+// CHECK-NEXT: ld2w {z7.s, z8.s}, p3/z, [x1, #5, MUL VL]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+
+// --------------------------------------------------------------------------//
+// error: restricted predicate has range [0, 7].
+
+ld2w {z2.s, z3.s}, p8/z, [x15, #10, MUL VL]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: restricted predicate has range [0, 7].
+// CHECK-NEXT: ld2w {z2.s, z3.s}, p8/z, [x15, #10, MUL VL]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+
+// --------------------------------------------------------------------------//
+// Invalid vector list.
+
+ld2w { }, p0/z, [x0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector register expected
+// CHECK-NEXT: ld2w { }, p0/z, [x0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+ld2w { z0.s, z1.s, z2.s }, p0/z, [x0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand
+// CHECK-NEXT: ld2w { z0.s, z1.s, z2.s }, p0/z, [x0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+ld2w { z0.s, z1.d }, p0/z, [x0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: mismatched register size suffix
+// CHECK-NEXT: ld2w { z0.s, z1.d }, p0/z, [x0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+ld2w { z0.s, z2.s }, p0/z, [x0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: registers must be sequential
+// CHECK-NEXT: ld2w { z0.s, z2.s }, p0/z, [x0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+ld2w { v0.2d, v1.2d }, p0/z, [x0]
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand
+// CHECK-NEXT: ld2w { v0.2d, v1.2d }, p0/z, [x0]
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
diff --git a/llvm/test/MC/AArch64/SVE/ld2w.s b/llvm/test/MC/AArch64/SVE/ld2w.s
new file mode 100644 (file)
index 0000000..99ccc25
--- /dev/null
@@ -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
+
+ld2w    { z0.s, z1.s }, p0/z, [x0]
+// CHECK-INST: ld2w    { z0.s, z1.s }, p0/z, [x0]
+// CHECK-ENCODING: [0x00,0xe0,0x20,0xa5]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: 00 e0 20 a5 <unknown>
+
+ld2w    { z23.s, z24.s }, p3/z, [x13, #-16, mul vl]
+// CHECK-INST: ld2w    { z23.s, z24.s }, p3/z, [x13, #-16, mul vl]
+// CHECK-ENCODING: [0xb7,0xed,0x28,0xa5]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: b7 ed 28 a5 <unknown>
+
+ld2w    { z21.s, z22.s }, p5/z, [x10, #10, mul vl]
+// CHECK-INST: ld2w    { z21.s, z22.s }, p5/z, [x10, #10, mul vl]
+// CHECK-ENCODING: [0x55,0xf5,0x25,0xa5]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: 55 f5 25 a5 <unknown>