Skip to content
This repository was archived by the owner on Mar 28, 2020. It is now read-only.

Commit df60d71

Browse files
committed
[AArch64][SVE] Asm: Support for INC/DEC (scalar) instructions.
Increment/decrement scalar register by (scaled) element count given by predicate pattern, e.g. 'incw x0, all, mul #4'. Reviewers: rengolin, fhahn, SjoerdMeijer, samparker, javed.absar Reviewed By: SjoerdMeijer Differential Revision: https://reviews.llvm.org/D47713 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@334838 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent bd0b6b0 commit df60d71

21 files changed

+1663
-12
lines changed

lib/Target/AArch64/AArch64SVEInstrInfo.td

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,15 @@ let Predicates = [HasSVE] in {
477477
def ADDVL_XXI : sve_int_arith_vl<0b0, "addvl">;
478478
def ADDPL_XXI : sve_int_arith_vl<0b1, "addpl">;
479479

480+
defm INCB_XPiI : sve_int_pred_pattern_a<0b000, "incb">;
481+
defm DECB_XPiI : sve_int_pred_pattern_a<0b001, "decb">;
482+
defm INCH_XPiI : sve_int_pred_pattern_a<0b010, "inch">;
483+
defm DECH_XPiI : sve_int_pred_pattern_a<0b011, "dech">;
484+
defm INCW_XPiI : sve_int_pred_pattern_a<0b100, "incw">;
485+
defm DECW_XPiI : sve_int_pred_pattern_a<0b101, "decw">;
486+
defm INCD_XPiI : sve_int_pred_pattern_a<0b110, "incd">;
487+
defm DECD_XPiI : sve_int_pred_pattern_a<0b111, "decd">;
488+
480489
defm INDEX_RR : sve_int_index_rr<"index">;
481490
defm INDEX_IR : sve_int_index_ir<"index">;
482491
defm INDEX_RI : sve_int_index_ri<"index">;

lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ class AArch64AsmParser : public MCTargetAsmParser {
8888
bool parseRegister(OperandVector &Operands);
8989
bool parseSymbolicImmVal(const MCExpr *&ImmVal);
9090
bool parseNeonVectorList(OperandVector &Operands);
91-
bool parseOptionalMulVl(OperandVector &Operands);
91+
bool parseOptionalMulOperand(OperandVector &Operands);
9292
bool parseOperand(OperandVector &Operands, bool isCondCode,
9393
bool invertCondCode);
9494

@@ -3199,27 +3199,45 @@ AArch64AsmParser::tryParseGPROperand(OperandVector &Operands) {
31993199
return MatchOperand_Success;
32003200
}
32013201

3202-
bool AArch64AsmParser::parseOptionalMulVl(OperandVector &Operands) {
3202+
bool AArch64AsmParser::parseOptionalMulOperand(OperandVector &Operands) {
32033203
MCAsmParser &Parser = getParser();
32043204

32053205
// Some SVE instructions have a decoration after the immediate, i.e.
32063206
// "mul vl". We parse them here and add tokens, which must be present in the
32073207
// asm string in the tablegen instruction.
3208+
bool NextIsVL = Parser.getLexer().peekTok().getString().equals_lower("vl");
3209+
bool NextIsHash = Parser.getLexer().peekTok().is(AsmToken::Hash);
32083210
if (!Parser.getTok().getString().equals_lower("mul") ||
3209-
!Parser.getLexer().peekTok().getString().equals_lower("vl"))
3211+
!(NextIsVL || NextIsHash))
32103212
return true;
32113213

3212-
SMLoc S = getLoc();
32133214
Operands.push_back(
3214-
AArch64Operand::CreateToken("mul", false, S, getContext()));
3215+
AArch64Operand::CreateToken("mul", false, getLoc(), getContext()));
32153216
Parser.Lex(); // Eat the "mul"
32163217

3217-
S = getLoc();
3218-
Operands.push_back(
3219-
AArch64Operand::CreateToken("vl", false, S, getContext()));
3220-
Parser.Lex(); // Eat the "vl"
3218+
if (NextIsVL) {
3219+
Operands.push_back(
3220+
AArch64Operand::CreateToken("vl", false, getLoc(), getContext()));
3221+
Parser.Lex(); // Eat the "vl"
3222+
return false;
3223+
}
32213224

3222-
return false;
3225+
if (NextIsHash) {
3226+
Parser.Lex(); // Eat the #
3227+
SMLoc S = getLoc();
3228+
3229+
// Parse immediate operand.
3230+
const MCExpr *ImmVal;
3231+
if (!Parser.parseExpression(ImmVal))
3232+
if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal)) {
3233+
Operands.push_back(AArch64Operand::CreateImm(
3234+
MCConstantExpr::create(MCE->getValue(), getContext()), S, getLoc(),
3235+
getContext()));
3236+
return MatchOperand_Success;
3237+
}
3238+
}
3239+
3240+
return Error(getLoc(), "expected 'vl' or '#<imm>'");
32233241
}
32243242

32253243
/// parseOperand - Parse a arm instruction operand. For now this parses the
@@ -3275,8 +3293,9 @@ bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
32753293
if (!parseRegister(Operands))
32763294
return false;
32773295

3278-
// See if this is a "mul vl" decoration used by SVE instructions.
3279-
if (!parseOptionalMulVl(Operands))
3296+
// See if this is a "mul vl" decoration or "mul #<int>" operand used
3297+
// by SVE instructions.
3298+
if (!parseOptionalMulOperand(Operands))
32803299
return false;
32813300

32823301
// This could be an optional "shift" or "extend" operand.

lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,8 @@ static DecodeStatus DecodeSImm(llvm::MCInst &Inst, uint64_t Imm,
210210
template <int ElementWidth>
211211
static DecodeStatus DecodeImm8OptLsl(MCInst &Inst, unsigned Imm,
212212
uint64_t Addr, const void *Decoder);
213+
static DecodeStatus DecodeSVEIncDecImm(MCInst &Inst, unsigned Imm,
214+
uint64_t Addr, const void *Decoder);
213215

214216
static bool Check(DecodeStatus &Out, DecodeStatus In) {
215217
switch (In) {
@@ -1791,3 +1793,10 @@ static DecodeStatus DecodeImm8OptLsl(MCInst &Inst, unsigned Imm,
17911793
Inst.addOperand(MCOperand::createImm(Shift));
17921794
return Success;
17931795
}
1796+
1797+
// Decode uimm4 ranged from 1-16.
1798+
static DecodeStatus DecodeSVEIncDecImm(MCInst &Inst, unsigned Imm,
1799+
uint64_t Addr, const void *Decoder) {
1800+
Inst.addOperand(MCOperand::createImm(Imm + 1));
1801+
return Success;
1802+
}

lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,9 @@ class AArch64MCCodeEmitter : public MCCodeEmitter {
166166
uint32_t getImm8OptLsl(const MCInst &MI, unsigned OpIdx,
167167
SmallVectorImpl<MCFixup> &Fixups,
168168
const MCSubtargetInfo &STI) const;
169+
uint32_t getSVEIncDecImm(const MCInst &MI, unsigned OpIdx,
170+
SmallVectorImpl<MCFixup> &Fixups,
171+
const MCSubtargetInfo &STI) const;
169172

170173
unsigned fixMOVZ(const MCInst &MI, unsigned EncodedValue,
171174
const MCSubtargetInfo &STI) const;
@@ -531,6 +534,16 @@ AArch64MCCodeEmitter::getImm8OptLsl(const MCInst &MI, unsigned OpIdx,
531534
return (Immediate & 0xff) | (ShiftVal == 0 ? 0 : (1 << ShiftVal));
532535
}
533536

537+
uint32_t
538+
AArch64MCCodeEmitter::getSVEIncDecImm(const MCInst &MI, unsigned OpIdx,
539+
SmallVectorImpl<MCFixup> &Fixups,
540+
const MCSubtargetInfo &STI) const {
541+
const MCOperand &MO = MI.getOperand(OpIdx);
542+
assert(MO.isImm() && "Expected an immediate value!");
543+
// Normalize 1-16 range to 0-15.
544+
return MO.getImm() - 1;
545+
}
546+
534547
/// getMoveVecShifterOpValue - Return the encoded value for the vector move
535548
/// shifter (MSL).
536549
uint32_t AArch64MCCodeEmitter::getMoveVecShifterOpValue(

lib/Target/AArch64/SVEInstrFormats.td

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,14 @@ def sve_fpimm_zero_one
226226
: SVEExactFPImmOperand<"ZeroOne", "AArch64ExactFPImm::zero",
227227
"AArch64ExactFPImm::one">;
228228

229+
def sve_incdec_imm : Operand<i32>, ImmLeaf<i32, [{
230+
return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
231+
}]> {
232+
let ParserMatchClass = Imm1_16Operand;
233+
let EncoderMethod = "getSVEIncDecImm";
234+
let DecoderMethod = "DecodeSVEIncDecImm";
235+
}
236+
229237
//===----------------------------------------------------------------------===//
230238
// SVE PTrue - These are used extensively throughout the pattern matching so
231239
// it's important we define them first.
@@ -272,6 +280,41 @@ let Predicates = [HasSVE] in {
272280
defm PTRUES : sve_int_ptrue<0b001, "ptrues">;
273281
}
274282

283+
284+
//===----------------------------------------------------------------------===//
285+
// SVE Element Count Group
286+
//===----------------------------------------------------------------------===//
287+
288+
class sve_int_pred_pattern_a<bits<3> opc, string asm>
289+
: I<(outs GPR64:$Rdn), (ins GPR64:$_Rdn, sve_pred_enum:$pattern, sve_incdec_imm:$imm4),
290+
asm, "\t$Rdn, $pattern, mul $imm4",
291+
"",
292+
[]>, Sched<[]> {
293+
bits<5> Rdn;
294+
bits<5> pattern;
295+
bits<4> imm4;
296+
let Inst{31-24} = 0b00000100;
297+
let Inst{23-22} = opc{2-1};
298+
let Inst{21-20} = 0b11;
299+
let Inst{19-16} = imm4;
300+
let Inst{15-11} = 0b11100;
301+
let Inst{10} = opc{0};
302+
let Inst{9-5} = pattern;
303+
let Inst{4-0} = Rdn;
304+
305+
let Constraints = "$Rdn = $_Rdn";
306+
}
307+
308+
multiclass sve_int_pred_pattern_a<bits<3> opc, string asm> {
309+
def NAME : sve_int_pred_pattern_a<opc, asm>;
310+
311+
def : InstAlias<asm # "\t$Rdn, $pattern",
312+
(!cast<Instruction>(NAME) GPR64:$Rdn, sve_pred_enum:$pattern, 1), 1>;
313+
def : InstAlias<asm # "\t$Rdn",
314+
(!cast<Instruction>(NAME) GPR64:$Rdn, 0b11111, 1), 2>;
315+
}
316+
317+
275318
//===----------------------------------------------------------------------===//
276319
// SVE Permute - Cross Lane Group
277320
//===----------------------------------------------------------------------===//
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve 2>&1 < %s| FileCheck %s
2+
3+
// ------------------------------------------------------------------------- //
4+
// Invalid result register
5+
6+
decb w0
7+
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand
8+
// CHECK-NEXT: decb w0
9+
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
10+
11+
decb sp
12+
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand
13+
// CHECK-NEXT: decb sp
14+
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
15+
16+
17+
// ------------------------------------------------------------------------- //
18+
// Immediate not compatible with encode/decode function.
19+
20+
decb x0, all, mul #-1
21+
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16]
22+
// CHECK-NEXT: decb x0, all, mul #-1
23+
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
24+
25+
decb x0, all, mul #0
26+
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16]
27+
// CHECK-NEXT: decb x0, all, mul #0
28+
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
29+
30+
decb x0, all, mul #17
31+
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16]
32+
// CHECK-NEXT: decb x0, all, mul #17
33+
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
34+
35+
36+
// ------------------------------------------------------------------------- //
37+
// Invalid predicate patterns
38+
39+
decb x0, vl512
40+
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid predicate pattern
41+
// CHECK-NEXT: decb x0, vl512
42+
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
43+
44+
decb x0, vl9
45+
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid predicate pattern
46+
// CHECK-NEXT: decb x0, vl9
47+
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
48+
49+
decb x0, #-1
50+
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid predicate pattern
51+
// CHECK-NEXT: decb x0, #-1
52+
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
53+
54+
decb x0, #32
55+
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid predicate pattern
56+
// CHECK-NEXT: decb x0, #32
57+
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:

test/MC/AArch64/SVE/decb.s

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve < %s \
2+
// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
3+
// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \
4+
// RUN: | FileCheck %s --check-prefix=CHECK-ERROR
5+
// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve < %s \
6+
// RUN: | llvm-objdump -d -mattr=+sve - | FileCheck %s --check-prefix=CHECK-INST
7+
// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve < %s \
8+
// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN
9+
10+
decb x0
11+
// CHECK-INST: decb x0
12+
// CHECK-ENCODING: [0xe0,0xe7,0x30,0x04]
13+
// CHECK-ERROR: instruction requires: sve
14+
// CHECK-UNKNOWN: e0 e7 30 04 <unknown>
15+
16+
decb x0, all
17+
// CHECK-INST: decb x0
18+
// CHECK-ENCODING: [0xe0,0xe7,0x30,0x04]
19+
// CHECK-ERROR: instruction requires: sve
20+
// CHECK-UNKNOWN: e0 e7 30 04 <unknown>
21+
22+
decb x0, all, mul #1
23+
// CHECK-INST: decb x0
24+
// CHECK-ENCODING: [0xe0,0xe7,0x30,0x04]
25+
// CHECK-ERROR: instruction requires: sve
26+
// CHECK-UNKNOWN: e0 e7 30 04 <unknown>
27+
28+
decb x0, all, mul #16
29+
// CHECK-INST: decb x0, all, mul #16
30+
// CHECK-ENCODING: [0xe0,0xe7,0x3f,0x04]
31+
// CHECK-ERROR: instruction requires: sve
32+
// CHECK-UNKNOWN: e0 e7 3f 04 <unknown>
33+
34+
decb x0, pow2
35+
// CHECK-INST: decb x0, pow2
36+
// CHECK-ENCODING: [0x00,0xe4,0x30,0x04]
37+
// CHECK-ERROR: instruction requires: sve
38+
// CHECK-UNKNOWN: 00 e4 30 04 <unknown>
39+
40+
decb x0, vl1
41+
// CHECK-INST: decb x0, vl1
42+
// CHECK-ENCODING: [0x20,0xe4,0x30,0x04]
43+
// CHECK-ERROR: instruction requires: sve
44+
// CHECK-UNKNOWN: 20 e4 30 04 <unknown>
45+
46+
decb x0, vl2
47+
// CHECK-INST: decb x0, vl2
48+
// CHECK-ENCODING: [0x40,0xe4,0x30,0x04]
49+
// CHECK-ERROR: instruction requires: sve
50+
// CHECK-UNKNOWN: 40 e4 30 04 <unknown>
51+
52+
decb x0, vl3
53+
// CHECK-INST: decb x0, vl3
54+
// CHECK-ENCODING: [0x60,0xe4,0x30,0x04]
55+
// CHECK-ERROR: instruction requires: sve
56+
// CHECK-UNKNOWN: 60 e4 30 04 <unknown>
57+
58+
decb x0, vl4
59+
// CHECK-INST: decb x0, vl4
60+
// CHECK-ENCODING: [0x80,0xe4,0x30,0x04]
61+
// CHECK-ERROR: instruction requires: sve
62+
// CHECK-UNKNOWN: 80 e4 30 04 <unknown>
63+
64+
decb x0, vl5
65+
// CHECK-INST: decb x0, vl5
66+
// CHECK-ENCODING: [0xa0,0xe4,0x30,0x04]
67+
// CHECK-ERROR: instruction requires: sve
68+
// CHECK-UNKNOWN: a0 e4 30 04 <unknown>
69+
70+
decb x0, vl6
71+
// CHECK-INST: decb x0, vl6
72+
// CHECK-ENCODING: [0xc0,0xe4,0x30,0x04]
73+
// CHECK-ERROR: instruction requires: sve
74+
// CHECK-UNKNOWN: c0 e4 30 04 <unknown>
75+
76+
decb x0, vl7
77+
// CHECK-INST: decb x0, vl7
78+
// CHECK-ENCODING: [0xe0,0xe4,0x30,0x04]
79+
// CHECK-ERROR: instruction requires: sve
80+
// CHECK-UNKNOWN: e0 e4 30 04 <unknown>
81+
82+
decb x0, vl8
83+
// CHECK-INST: decb x0, vl8
84+
// CHECK-ENCODING: [0x00,0xe5,0x30,0x04]
85+
// CHECK-ERROR: instruction requires: sve
86+
// CHECK-UNKNOWN: 00 e5 30 04 <unknown>
87+
88+
decb x0, vl16
89+
// CHECK-INST: decb x0, vl16
90+
// CHECK-ENCODING: [0x20,0xe5,0x30,0x04]
91+
// CHECK-ERROR: instruction requires: sve
92+
// CHECK-UNKNOWN: 20 e5 30 04 <unknown>
93+
94+
decb x0, vl32
95+
// CHECK-INST: decb x0, vl32
96+
// CHECK-ENCODING: [0x40,0xe5,0x30,0x04]
97+
// CHECK-ERROR: instruction requires: sve
98+
// CHECK-UNKNOWN: 40 e5 30 04 <unknown>
99+
100+
decb x0, vl64
101+
// CHECK-INST: decb x0, vl64
102+
// CHECK-ENCODING: [0x60,0xe5,0x30,0x04]
103+
// CHECK-ERROR: instruction requires: sve
104+
// CHECK-UNKNOWN: 60 e5 30 04 <unknown>
105+
106+
decb x0, vl128
107+
// CHECK-INST: decb x0, vl128
108+
// CHECK-ENCODING: [0x80,0xe5,0x30,0x04]
109+
// CHECK-ERROR: instruction requires: sve
110+
// CHECK-UNKNOWN: 80 e5 30 04 <unknown>
111+
112+
decb x0, vl256
113+
// CHECK-INST: decb x0, vl256
114+
// CHECK-ENCODING: [0xa0,0xe5,0x30,0x04]
115+
// CHECK-ERROR: instruction requires: sve
116+
// CHECK-UNKNOWN: a0 e5 30 04 <unknown>
117+
118+
decb x0, #14
119+
// CHECK-INST: decb x0, #14
120+
// CHECK-ENCODING: [0xc0,0xe5,0x30,0x04]
121+
// CHECK-ERROR: instruction requires: sve
122+
// CHECK-UNKNOWN: c0 e5 30 04 <unknown>
123+
124+
decb x0, #28
125+
// CHECK-INST: decb x0, #28
126+
// CHECK-ENCODING: [0x80,0xe7,0x30,0x04]
127+
// CHECK-ERROR: instruction requires: sve
128+
// CHECK-UNKNOWN: 80 e7 30 04 <unknown>

0 commit comments

Comments
 (0)