From e2da79543b4fa0aaeb885410d1a328468fe5b138 Mon Sep 17 00:00:00 2001 From: Sander de Smalen Date: Tue, 6 Feb 2018 13:13:21 +0000 Subject: [PATCH] [AArch64][SVE] Asm: Add AND_ZI instructions and aliases 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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@324343 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/AArch64/AArch64SVEInstrInfo.td | 2 + .../AArch64/Disassembler/AArch64Disassembler.cpp | 20 ++++ .../AArch64/MCTargetDesc/AArch64AddressingModes.h | 11 +++ lib/Target/AArch64/SVEInstrFormats.td | 103 +++++++++++++++++++++ test/MC/AArch64/SVE/and-diagnostics.s | 52 +++++++++++ test/MC/AArch64/SVE/and.s | 56 +++++++++++ 6 files changed, 244 insertions(+) create mode 100644 test/MC/AArch64/SVE/and-diagnostics.s create mode 100644 test/MC/AArch64/SVE/and.s diff --git a/lib/Target/AArch64/AArch64SVEInstrInfo.td b/lib/Target/AArch64/AArch64SVEInstrInfo.td index c2f46cae978..07cd15485a4 100644 --- a/lib/Target/AArch64/AArch64SVEInstrInfo.td +++ b/lib/Target/AArch64/AArch64SVEInstrInfo.td @@ -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">; diff --git a/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp b/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp index 583a07f6a7b..b4a554e0658 100644 --- a/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp +++ b/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp @@ -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 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 static DecodeStatus DecodeSImm(llvm::MCInst &Inst, uint64_t Imm, uint64_t Address, const void *Decoder) { diff --git a/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h b/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h index fdd9c960dab..637aa4a9e6f 100644 --- a/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h +++ b/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h @@ -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 +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) diff --git a/lib/Target/AArch64/SVEInstrFormats.td b/lib/Target/AArch64/SVEInstrFormats.td index 078ae683110..c7d6628de44 100644 --- a/lib/Target/AArch64/SVEInstrFormats.td +++ b/lib/Target/AArch64/SVEInstrFormats.td @@ -27,6 +27,69 @@ def sve_pred_enum : Operand, ImmLeaf : AsmOperandClass { + let Name = "SVELogicalImm" # Width; + let DiagnosticType = "LogicalSecondSource"; + let PredicateMethod = "isLogicalImm"; + let RenderMethod = "addLogicalImmOperands"; +} + +def sve_logical_imm8 : Operand { + let ParserMatchClass = SVELogicalImmOperand<8>; + let PrintMethod = "printLogicalImm"; + + let MCOperandPredicate = [{ + if (!MCOp.isImm()) + return false; + int64_t Val = AArch64_AM::decodeLogicalImmediate(MCOp.getImm(), 64); + return AArch64_AM::isSVEMaskOfIdenticalElements(Val); + }]; +} + +def sve_logical_imm16 : Operand { + let ParserMatchClass = SVELogicalImmOperand<16>; + let PrintMethod = "printLogicalImm"; + + let MCOperandPredicate = [{ + if (!MCOp.isImm()) + return false; + int64_t Val = AArch64_AM::decodeLogicalImmediate(MCOp.getImm(), 64); + return AArch64_AM::isSVEMaskOfIdenticalElements(Val); + }]; +} + +def sve_logical_imm32 : Operand { + let ParserMatchClass = SVELogicalImmOperand<32>; + let PrintMethod = "printLogicalImm"; + + let MCOperandPredicate = [{ + if (!MCOp.isImm()) + return false; + int64_t Val = AArch64_AM::decodeLogicalImmediate(MCOp.getImm(), 64); + return AArch64_AM::isSVEMaskOfIdenticalElements(Val); + }]; +} + +//===----------------------------------------------------------------------===// +class SVELogicalImmNotOperand : AsmOperandClass { + let Name = "SVELogicalImm" # Width # "Not"; + let DiagnosticType = "LogicalSecondSource"; + let PredicateMethod = "isLogicalImm"; + let RenderMethod = "addLogicalImmNotOperands"; +} + +def sve_logical_imm8_not : Operand { + let ParserMatchClass = SVELogicalImmNotOperand<8>; +} + +def sve_logical_imm16_not : Operand { + let ParserMatchClass = SVELogicalImmNotOperand<16>; +} + +def sve_logical_imm32_not : Operand { + 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 { } //===----------------------------------------------------------------------===// +// SVE Logical Mask Immediate Group +//===----------------------------------------------------------------------===// + +class sve_int_log_imm 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 opc, string asm, string alias> { + def NAME : sve_int_log_imm; + + def : InstAlias(NAME) ZPR8:$Zdn, sve_logical_imm8:$imm), 4>; + def : InstAlias(NAME) ZPR16:$Zdn, sve_logical_imm16:$imm), 3>; + def : InstAlias(NAME) ZPR32:$Zdn, sve_logical_imm32:$imm), 2>; + + def : InstAlias(NAME) ZPR8:$Zdn, sve_logical_imm8_not:$imm), 0>; + def : InstAlias(NAME) ZPR16:$Zdn, sve_logical_imm16_not:$imm), 0>; + def : InstAlias(NAME) ZPR32:$Zdn, sve_logical_imm32_not:$imm), 0>; + def : InstAlias(NAME) ZPR64:$Zdn, logical_imm64_not:$imm), 0>; +} + +//===----------------------------------------------------------------------===// // SVE Integer Arithmetic - Unpredicated Group. //===----------------------------------------------------------------------===// diff --git a/test/MC/AArch64/SVE/and-diagnostics.s b/test/MC/AArch64/SVE/and-diagnostics.s new file mode 100644 index 00000000000..f2a5ced66b5 --- /dev/null +++ b/test/MC/AArch64/SVE/and-diagnostics.s @@ -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/test/MC/AArch64/SVE/and.s b/test/MC/AArch64/SVE/and.s new file mode 100644 index 00000000000..b40c6b6928a --- /dev/null +++ b/test/MC/AArch64/SVE/and.s @@ -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 + +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 + +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 + +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 + +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 + +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 + +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 + +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 -- 2.11.0