[AArch64][SVE] Asm: Add AND_ZI instructions and aliases
authorSander de Smalen <sander.desmalen@arm.com>
Tue, 6 Feb 2018 13:13:21 +0000 (13:13 +0000)
committerSander de Smalen <sander.desmalen@arm.com>
Tue, 6 Feb 2018 13:13:21 +0000 (13:13 +0000)
Summary: Adds support for the SVE AND instruction with vector and logical-immediate operands, and their corresponding aliases.

Reviewers: fhahn, rengolin, samparker, echristo, aadg, kristof.beyls

Reviewed By: fhahn

Subscribers: aemerson, javed.absar, tschuett, llvm-commits

Differential Revision: https://reviews.llvm.org/D42295

llvm-svn: 324343

llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
llvm/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h
llvm/lib/Target/AArch64/SVEInstrFormats.td
llvm/test/MC/AArch64/SVE/and-diagnostics.s [new file with mode: 0644]
llvm/test/MC/AArch64/SVE/and.s [new file with mode: 0644]

index c2f46ca..07cd154 100644 (file)
@@ -15,6 +15,8 @@ let Predicates = [HasSVE] in {
   defm ADD_ZZZ   : sve_int_bin_cons_arit_0<0b000, "add">;
   defm SUB_ZZZ   : sve_int_bin_cons_arit_0<0b001, "sub">;
 
+  defm AND_ZI    : sve_int_log_imm<0b10, "and", "bic">;
+
   defm ADD_ZPmZ  : sve_int_bin_pred_arit_0<0b000, "add">;
   defm SUB_ZPmZ  : sve_int_bin_pred_arit_0<0b001, "sub">;
 
index 583a07f..b4a554e 100644 (file)
@@ -188,6 +188,10 @@ static DecodeStatus DecodeXSeqPairsClassRegisterClass(MCInst &Inst,
                                                       unsigned RegNo,
                                                       uint64_t Addr,
                                                       const void *Decoder);
+static DecodeStatus DecodeSVELogicalImmInstruction(llvm::MCInst &Inst,
+                                                   uint32_t insn,
+                                                   uint64_t Address,
+                                                   const void *Decoder);
 template<int Bits>
 static DecodeStatus DecodeSImm(llvm::MCInst &Inst, uint64_t Imm,
                                uint64_t Address, const void *Decoder);
@@ -1649,6 +1653,22 @@ static DecodeStatus DecodeXSeqPairsClassRegisterClass(MCInst &Inst,
                                              RegNo, Addr, Decoder);
 }
 
+static DecodeStatus DecodeSVELogicalImmInstruction(llvm::MCInst &Inst,
+                                                   uint32_t insn,
+                                                   uint64_t Addr,
+                                                   const void *Decoder) {
+  unsigned Zdn = fieldFromInstruction(insn, 0, 5);
+  unsigned imm = fieldFromInstruction(insn, 5, 13);
+  if (!AArch64_AM::isValidDecodeLogicalImmediate(imm, 64))
+    return Fail;
+
+  // The same (tied) operand is added twice to the instruction.
+  DecodeZPRRegisterClass(Inst, Zdn, Addr, Decoder);
+  DecodeZPRRegisterClass(Inst, Zdn, Addr, Decoder);
+  Inst.addOperand(MCOperand::createImm(imm));
+  return Success;
+}
+
 template<int Bits>
 static DecodeStatus DecodeSImm(llvm::MCInst &Inst, uint64_t Imm,
                                uint64_t Address, const void *Decoder) {
index fdd9c96..637aa4a 100644 (file)
@@ -754,6 +754,17 @@ static inline uint64_t decodeAdvSIMDModImmType12(uint8_t Imm) {
   return (EncVal << 32) | EncVal;
 }
 
+/// Returns true if Imm is the concatenation of a repeating pattern of type T.
+template <typename T>
+static inline bool isSVEMaskOfIdenticalElements(int64_t Imm) {
+  union {
+    int64_t Whole;
+    T Parts[sizeof(int64_t)/sizeof(T)];
+  } Vec { Imm };
+
+  return all_of(Vec.Parts, [Vec](T Elem) { return Elem == Vec.Parts[0]; });
+}
+
 inline static bool isAnyMOVZMovAlias(uint64_t Value, int RegWidth) {
   for (int Shift = 0; Shift <= RegWidth - 16; Shift += 16)
     if ((Value & ~(0xffffULL << Shift)) == 0)
index 078ae68..c7d6628 100644 (file)
@@ -27,6 +27,69 @@ def sve_pred_enum : Operand<i32>, ImmLeaf<i32, [{
   let ParserMatchClass = SVEPatternOperand;
 }
 
+class SVELogicalImmOperand<int Width> : AsmOperandClass {
+  let Name = "SVELogicalImm" # Width;
+  let DiagnosticType = "LogicalSecondSource";
+  let PredicateMethod = "isLogicalImm<int" # Width # "_t>";
+  let RenderMethod = "addLogicalImmOperands<int" # Width # "_t>";
+}
+
+def sve_logical_imm8 : Operand<i64> {
+  let ParserMatchClass = SVELogicalImmOperand<8>;
+  let PrintMethod = "printLogicalImm<int8_t>";
+
+  let MCOperandPredicate = [{
+    if (!MCOp.isImm())
+      return false;
+    int64_t Val = AArch64_AM::decodeLogicalImmediate(MCOp.getImm(), 64);
+    return AArch64_AM::isSVEMaskOfIdenticalElements<int8_t>(Val);
+  }];
+}
+
+def sve_logical_imm16 : Operand<i64> {
+  let ParserMatchClass = SVELogicalImmOperand<16>;
+  let PrintMethod = "printLogicalImm<int16_t>";
+
+  let MCOperandPredicate = [{
+    if (!MCOp.isImm())
+      return false;
+    int64_t Val = AArch64_AM::decodeLogicalImmediate(MCOp.getImm(), 64);
+    return AArch64_AM::isSVEMaskOfIdenticalElements<int16_t>(Val);
+  }];
+}
+
+def sve_logical_imm32 : Operand<i64> {
+  let ParserMatchClass = SVELogicalImmOperand<32>;
+  let PrintMethod = "printLogicalImm<int32_t>";
+
+  let MCOperandPredicate = [{
+    if (!MCOp.isImm())
+      return false;
+    int64_t Val = AArch64_AM::decodeLogicalImmediate(MCOp.getImm(), 64);
+    return AArch64_AM::isSVEMaskOfIdenticalElements<int32_t>(Val);
+  }];
+}
+
+//===----------------------------------------------------------------------===//
+class SVELogicalImmNotOperand<int Width> : AsmOperandClass {
+  let Name = "SVELogicalImm" # Width # "Not";
+  let DiagnosticType = "LogicalSecondSource";
+  let PredicateMethod = "isLogicalImm<int" # Width # "_t>";
+  let RenderMethod = "addLogicalImmNotOperands<int" # Width # "_t>";
+}
+
+def sve_logical_imm8_not : Operand<i64> {
+  let ParserMatchClass = SVELogicalImmNotOperand<8>;
+}
+
+def sve_logical_imm16_not : Operand<i64> {
+  let ParserMatchClass = SVELogicalImmNotOperand<16>;
+}
+
+def sve_logical_imm32_not : Operand<i64> {
+  let ParserMatchClass = SVELogicalImmNotOperand<32>;
+}
+
 //===----------------------------------------------------------------------===//
 // SVE PTrue - These are used extensively throughout the pattern matching so
 //             it's important we define them first.
@@ -109,6 +172,46 @@ multiclass sve_int_perm_dup_r<string asm> {
 }
 
 //===----------------------------------------------------------------------===//
+// SVE Logical Mask Immediate Group
+//===----------------------------------------------------------------------===//
+
+class sve_int_log_imm<bits<2> opc, string asm>
+: I<(outs ZPR64:$Zdn), (ins ZPR64:$_Zdn, logical_imm64:$imms13),
+  asm, "\t$Zdn, $_Zdn, $imms13",
+  "", []>, Sched<[]> {
+  bits<5> Zdn;
+  bits<13> imms13;
+  let Inst{31-24} = 0b00000101;
+  let Inst{23-22} = opc;
+  let Inst{21-18} = 0b0000;
+  let Inst{17-5}  = imms13;
+  let Inst{4-0}   = Zdn;
+
+  let Constraints = "$Zdn = $_Zdn";
+  let DecoderMethod = "DecodeSVELogicalImmInstruction";
+}
+
+multiclass sve_int_log_imm<bits<2> opc, string asm, string alias> {
+  def NAME : sve_int_log_imm<opc, asm>;
+
+  def : InstAlias<asm # "\t$Zdn, $Zdn, $imm",
+                  (!cast<Instruction>(NAME) ZPR8:$Zdn, sve_logical_imm8:$imm), 4>;
+  def : InstAlias<asm # "\t$Zdn, $Zdn, $imm",
+                  (!cast<Instruction>(NAME) ZPR16:$Zdn, sve_logical_imm16:$imm), 3>;
+  def : InstAlias<asm # "\t$Zdn, $Zdn, $imm",
+                  (!cast<Instruction>(NAME) ZPR32:$Zdn, sve_logical_imm32:$imm), 2>;
+
+  def : InstAlias<alias # "\t$Zdn, $Zdn, $imm",
+                  (!cast<Instruction>(NAME) ZPR8:$Zdn, sve_logical_imm8_not:$imm), 0>;
+  def : InstAlias<alias # "\t$Zdn, $Zdn, $imm",
+                  (!cast<Instruction>(NAME) ZPR16:$Zdn, sve_logical_imm16_not:$imm), 0>;
+  def : InstAlias<alias # "\t$Zdn, $Zdn, $imm",
+                  (!cast<Instruction>(NAME) ZPR32:$Zdn, sve_logical_imm32_not:$imm), 0>;
+  def : InstAlias<alias # "\t$Zdn, $Zdn, $imm",
+                  (!cast<Instruction>(NAME) ZPR64:$Zdn, logical_imm64_not:$imm), 0>;
+}
+
+//===----------------------------------------------------------------------===//
 // SVE Integer Arithmetic -  Unpredicated Group.
 //===----------------------------------------------------------------------===//
 
diff --git a/llvm/test/MC/AArch64/SVE/and-diagnostics.s b/llvm/test/MC/AArch64/SVE/and-diagnostics.s
new file mode 100644 (file)
index 0000000..f2a5ced
--- /dev/null
@@ -0,0 +1,52 @@
+// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve  2>&1 < %s| FileCheck %s
+
+// --------------------------------------------------------------------------//
+// Immediate not compatible with encode/decode function.
+
+and z5.b, z5.b, #0xfa
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: expected compatible register or logical immediate
+// CHECK-NEXT: and z5.b, z5.b, #0xfa
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+and z5.b, z5.b, #0xfff9
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: expected compatible register or logical immediate
+// CHECK-NEXT: and z5.b, z5.b, #0xfff9
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+and z5.h, z5.h, #0xfffa
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: expected compatible register or logical immediate
+// CHECK-NEXT: and z5.h, z5.h, #0xfffa
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+and z5.h, z5.h, #0xfffffff9
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: expected compatible register or logical immediate
+// CHECK-NEXT: and z5.h, z5.h, #0xfffffff9
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+and z5.s, z5.s, #0xfffffffa
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: expected compatible register or logical immediate
+// CHECK-NEXT: and z5.s, z5.s, #0xfffffffa
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+and z5.s, z5.s, #0xffffffffffffff9
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: expected compatible register or logical immediate
+// CHECK-NEXT: and z5.s, z5.s, #0xffffffffffffff9
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+and z15.d, z15.d, #0xfffffffffffffffa
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: expected compatible register or logical immediate
+// CHECK-NEXT: and z15.d, z15.d, #0xfffffffffffffffa
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+// --------------------------------------------------------------------------//
+// Source and Destination Registers must match
+
+and z7.d, z8.d, #254
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: operand must match destination register
+// CHECK-NEXT: and z7.d, z8.d, #254
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+bic z7.d, z8.d, #254
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: operand must match destination register
+// CHECK-NEXT: bic z7.d, z8.d, #254
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
diff --git a/llvm/test/MC/AArch64/SVE/and.s b/llvm/test/MC/AArch64/SVE/and.s
new file mode 100644 (file)
index 0000000..b40c6b6
--- /dev/null
@@ -0,0 +1,56 @@
+// 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
+
+and     z5.b, z5.b, #0xf9
+// CHECK-INST: and     z5.b, z5.b, #0xf9
+// CHECK-ENCODING: [0xa5,0x2e,0x80,0x05]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: a5 2e 80 05 <unknown>
+
+bic     z5.b, z5.b, #0x06
+// CHECK-INST: and     z5.b, z5.b, #0xf9
+// CHECK-ENCODING: [0xa5,0x2e,0x80,0x05]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: a5 2e 80 05 <unknown>
+
+and     z23.h, z23.h, #0xfff9
+// CHECK-INST: and     z23.h, z23.h, #0xfff9
+// CHECK-ENCODING: [0xb7,0x6d,0x80,0x05]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: b7 6d 80 05 <unknown>
+
+bic     z23.h, z23.h, #0x0006
+// CHECK-INST: and     z23.h, z23.h, #0xfff9
+// CHECK-ENCODING: [0xb7,0x6d,0x80,0x05]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: b7 6d 80 05 <unknown>
+
+and     z0.s, z0.s, #0xfffffff9
+// CHECK-INST: and     z0.s, z0.s, #0xfffffff9
+// CHECK-ENCODING: [0xa0,0xeb,0x80,0x05]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: a0 eb 80 05 <unknown>
+
+bic     z0.s, z0.s, #0x00000006
+// CHECK-INST: and     z0.s, z0.s, #0xfffffff9
+// CHECK-ENCODING: [0xa0,0xeb,0x80,0x05]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: a0 eb 80 05 <unknown>
+
+and     z0.d, z0.d, #0xfffffffffffffff9
+// CHECK-INST: and     z0.d, z0.d, #0xfffffffffffffff9
+// CHECK-ENCODING: [0xa0,0xef,0x83,0x05]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: a0 ef 83 05 <unknown>
+
+bic     z0.d, z0.d, #0x0000000000000006
+// CHECK-INST: and     z0.d, z0.d, #0xfffffffffffffff9
+// CHECK-ENCODING: [0xa0,0xef,0x83,0x05]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: a0 ef 83 05 <unknown>