summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td2
-rw-r--r--llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp20
-rw-r--r--llvm/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h11
-rw-r--r--llvm/lib/Target/AArch64/SVEInstrFormats.td103
4 files changed, 136 insertions, 0 deletions
diff --git a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
index c2f46cae978..07cd15485a4 100644
--- a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
+++ b/llvm/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/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
index 583a07f6a7b..b4a554e0658 100644
--- a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
+++ b/llvm/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<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) {
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h
index fdd9c960dab..637aa4a9e6f 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h
+++ b/llvm/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 <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)
diff --git a/llvm/lib/Target/AArch64/SVEInstrFormats.td b/llvm/lib/Target/AArch64/SVEInstrFormats.td
index 078ae683110..c7d6628de44 100644
--- a/llvm/lib/Target/AArch64/SVEInstrFormats.td
+++ b/llvm/lib/Target/AArch64/SVEInstrFormats.td
@@ -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.
//===----------------------------------------------------------------------===//
OpenPOWER on IntegriCloud