Skip to content

Commit 3b4f706

Browse files
committed
[AArch64][SVE] Asm: Fix supported immediates for DUP/CPY
This patch fixes an issue in the implementation of DUP/CPY where certain immediates were not accepted. Immediates should be interpreted as a two's complement encoding of a value that fits the number of bits of the element type. mov z0.b, p0/z, #127 <=> mov z0.b, p0/z, #-129 <=> mov z0.b, p0/z, #0xffffffffffffff7f This behaviour is in line with the GNU assembler. Reviewed By: c-rhodes Differential Revision: https://reviews.llvm.org/D94776
1 parent 9325b8d commit 3b4f706

File tree

7 files changed

+114
-76
lines changed

7 files changed

+114
-76
lines changed

llvm/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -760,17 +760,24 @@ static inline bool isSVEMaskOfIdenticalElements(int64_t Imm) {
760760
/// Returns true if Imm is valid for CPY/DUP.
761761
template <typename T>
762762
static inline bool isSVECpyImm(int64_t Imm) {
763-
bool IsImm8 = int8_t(Imm) == Imm;
764-
bool IsImm16 = int16_t(Imm & ~0xff) == Imm;
763+
// Imm is interpreted as a signed value, which means top bits must be all ones
764+
// (sign bits if the immediate value is negative and passed in a larger
765+
// container), or all zeroes.
766+
int64_t Mask = ~int64_t(std::numeric_limits<std::make_unsigned_t<T>>::max());
767+
if ((Imm & Mask) != 0 && (Imm & Mask) != Mask)
768+
return false;
765769

766-
if (std::is_same<int8_t, std::make_signed_t<T>>::value ||
767-
std::is_same<int8_t, T>::value)
768-
return IsImm8 || uint8_t(Imm) == Imm;
770+
// Imm is a signed 8-bit value.
771+
// Top bits must be zeroes or sign bits.
772+
if (Imm & 0xff)
773+
return int8_t(Imm) == T(Imm);
769774

770-
if (std::is_same<int16_t, std::make_signed_t<T>>::value)
771-
return IsImm8 || IsImm16 || uint16_t(Imm & ~0xff) == Imm;
775+
// Imm is a signed 16-bit value and multiple of 256.
776+
// Top bits must be zeroes or sign bits.
777+
if (Imm & 0xff00)
778+
return int16_t(Imm) == T(Imm);
772779

773-
return IsImm8 || IsImm16;
780+
return Imm == 0;
774781
}
775782

776783
/// Returns true if Imm is valid for ADD/SUB.

llvm/test/MC/AArch64/SVE/cpy-diagnostics.s

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -92,11 +92,6 @@ cpy z0.b, p0/z, #0, lsl #8 // #0, lsl #8 is not valid for .b
9292
// CHECK-NEXT: cpy z0.b, p0/z, #0, lsl #8
9393
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
9494

95-
cpy z0.b, p0/z, #-129
96-
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 255]
97-
// CHECK-NEXT: cpy z0.b, p0/z, #-129
98-
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
99-
10095
cpy z0.b, p0/z, #-1, lsl #8
10196
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 255]
10297
// CHECK-NEXT: cpy z0.b, p0/z, #-1, lsl #8
@@ -112,21 +107,11 @@ cpy z0.b, p0/z, #1, lsl #8
112107
// CHECK-NEXT: cpy z0.b, p0/z, #1, lsl #8
113108
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
114109

115-
cpy z0.h, p0/z, #-33024
116-
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 65280]
117-
// CHECK-NEXT: cpy z0.h, p0/z, #-33024
118-
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
119-
120110
cpy z0.h, p0/z, #-32769
121111
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 65280]
122112
// CHECK-NEXT: cpy z0.h, p0/z, #-32769
123113
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
124114

125-
cpy z0.h, p0/z, #-129, lsl #8
126-
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 65280]
127-
// CHECK-NEXT: cpy z0.h, p0/z, #-129, lsl #8
128-
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
129-
130115
cpy z0.h, p0/z, #32513
131116
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 65280]
132117
// CHECK-NEXT: cpy z0.h, p0/z, #32513

llvm/test/MC/AArch64/SVE/cpy.s

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,28 @@ cpy z21.d, p0/z, #32512
229229
// CHECK-ERROR: instruction requires: sve
230230
// CHECK-UNKNOWN: f5 2f d0 05 <unknown>
231231

232+
// --------------------------------------------------------------------------//
233+
// Tests where the negative immediate is in bounds when interpreted
234+
// as the element type.
235+
236+
cpy z0.b, p0/z, #-129
237+
// CHECK-INST: mov z0.b, p0/z, #127
238+
// CHECK-ENCODING: [0xe0,0x0f,0x10,0x05]
239+
// CHECK-ERROR: instruction requires: sve
240+
// CHECK-UNKNOWN: e0 0f 10 05 <unknown>
241+
242+
cpy z0.h, p0/z, #-33024
243+
// CHECK-INST: mov z0.h, p0/z, #32512
244+
// CHECK-ENCODING: [0xe0,0x2f,0x50,0x05]
245+
// CHECK-ERROR: instruction requires: sve
246+
// CHECK-UNKNOWN: e0 2f 50 05 <unknown>
247+
248+
cpy z0.h, p0/z, #-129, lsl #8
249+
// CHECK-INST: mov z0.h, p0/z, #32512
250+
// CHECK-ENCODING: [0xe0,0x2f,0x50,0x05]
251+
// CHECK-ERROR: instruction requires: sve
252+
// CHECK-UNKNOWN: e0 2f 50 05 <unknown>
253+
232254

233255
// --------------------------------------------------------------------------//
234256
// Tests for merging variant (/m) and testing the range of predicate (> 7)

llvm/test/MC/AArch64/SVE/dup-diagnostics.s

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,6 @@ dup z0.b, #0, lsl #8 // #0, lsl #8 is not valid for .b
2727
// CHECK-NEXT: dup z0.b, #0, lsl #8
2828
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
2929

30-
dup z0.b, #-129
31-
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 255]
32-
// CHECK-NEXT: dup z0.b, #-129
33-
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
34-
3530
dup z0.b, #-1, lsl #8
3631
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 255]
3732
// CHECK-NEXT: dup z0.b, #-1, lsl #8
@@ -47,21 +42,11 @@ dup z0.b, #1, lsl #8
4742
// CHECK-NEXT: dup z0.b, #1, lsl #8
4843
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
4944

50-
dup z0.h, #-33024
51-
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 65280]
52-
// CHECK-NEXT: dup z0.h, #-33024
53-
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
54-
5545
dup z0.h, #-32769
5646
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 65280]
5747
// CHECK-NEXT: dup z0.h, #-32769
5848
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
5949

60-
dup z0.h, #-129, lsl #8
61-
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 65280]
62-
// CHECK-NEXT: dup z0.h, #-129, lsl #8
63-
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
64-
6550
dup z0.h, #65281
6651
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 65280]
6752
// CHECK-NEXT: dup z0.h, #65281

llvm/test/MC/AArch64/SVE/dup.s

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,3 +240,25 @@ dup z5.q, z17.q[3]
240240
// CHECK-ENCODING: [0x25,0x22,0xf0,0x05]
241241
// CHECK-ERROR: instruction requires: sve
242242
// CHECK-UNKNOWN: 25 22 f0 05 <unknown>
243+
244+
// --------------------------------------------------------------------------//
245+
// Tests where the negative immediate is in bounds when interpreted
246+
// as the element type.
247+
248+
dup z0.b, #-129
249+
// CHECK-INST: mov z0.b, #127
250+
// CHECK-ENCODING: [0xe0,0xcf,0x38,0x25]
251+
// CHECK-ERROR: instruction requires: sve
252+
// CHECK-UNKNOWN: e0 cf 38 25 <unknown>
253+
254+
dup z0.h, #-33024
255+
// CHECK-INST: mov z0.h, #32512
256+
// CHECK-ENCODING: [0xe0,0xef,0x78,0x25]
257+
// CHECK-ERROR: instruction requires: sve
258+
// CHECK-UNKNOWN: e0 ef 78 25 <unknown>
259+
260+
dup z0.h, #-129, lsl #8
261+
// CHECK-INST: mov z0.h, #32512
262+
// CHECK-ENCODING: [0xe0,0xef,0x78,0x25]
263+
// CHECK-ERROR: instruction requires: sve
264+
// CHECK-UNKNOWN: e0 ef 78 25 <unknown>

llvm/test/MC/AArch64/SVE/mov-diagnostics.s

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -133,11 +133,6 @@ mov z0.b, #0, lsl #8 // #0, lsl #8 is not valid for .b
133133
// CHECK-NEXT: mov z0.b, #0, lsl #8
134134
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
135135

136-
mov z0.b, #-129
137-
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 255]
138-
// CHECK-NEXT: mov z0.b, #-129
139-
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
140-
141136
mov z0.b, #-1, lsl #8
142137
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 255]
143138
// CHECK-NEXT: mov z0.b, #-1, lsl #8
@@ -153,11 +148,6 @@ mov z0.b, #1, lsl #8
153148
// CHECK-NEXT: mov z0.b, #1, lsl #8
154149
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
155150

156-
mov z0.h, #-129, lsl #8
157-
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 65280]
158-
// CHECK-NEXT: mov z0.h, #-129, lsl #8
159-
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
160-
161151
// Note: 65281 is a valid logical immediate.
162152
mov z0.h, #65282
163153
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 65280]
@@ -214,21 +204,11 @@ mov z5.b, #0xfff9
214204
// CHECK-NEXT: mov z5.b, #0xfff9
215205
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
216206

217-
mov z5.h, #0xfffa
218-
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 65280]
219-
// CHECK-NEXT: mov z5.h, #0xfffa
220-
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
221-
222207
mov z5.h, #0xfffffff9
223208
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 65280]
224209
// CHECK-NEXT: mov z5.h, #0xfffffff9
225210
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
226211

227-
mov z5.s, #0xfffffffa
228-
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 32512]
229-
// CHECK-NEXT: mov z5.s, #0xfffffffa
230-
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
231-
232212
mov z5.s, #0xffffffffffffff9
233213
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 32512]
234214
// CHECK-NEXT: mov z5.s, #0xffffffffffffff9
@@ -239,11 +219,6 @@ mov z0.b, p0/z, #0, lsl #8 // #0, lsl #8 is not valid for .b
239219
// CHECK-NEXT: mov z0.b, p0/z, #0, lsl #8
240220
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
241221

242-
mov z0.b, p0/z, #-129
243-
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 255]
244-
// CHECK-NEXT: mov z0.b, p0/z, #-129
245-
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
246-
247222
mov z0.b, p0/z, #-1, lsl #8
248223
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 255]
249224
// CHECK-NEXT: mov z0.b, p0/z, #-1, lsl #8
@@ -259,21 +234,11 @@ mov z0.b, p0/z, #1, lsl #8
259234
// CHECK-NEXT: mov z0.b, p0/z, #1, lsl #8
260235
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
261236

262-
mov z0.h, p0/z, #-33024
263-
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 65280]
264-
// CHECK-NEXT: mov z0.h, p0/z, #-33024
265-
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
266-
267237
mov z0.h, p0/z, #-32769
268238
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 65280]
269239
// CHECK-NEXT: mov z0.h, p0/z, #-32769
270240
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
271241

272-
mov z0.h, p0/z, #-129, lsl #8
273-
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 65280]
274-
// CHECK-NEXT: mov z0.h, p0/z, #-129, lsl #8
275-
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
276-
277242
mov z0.h, p0/z, #32513
278243
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 65280]
279244
// CHECK-NEXT: mov z0.h, p0/z, #32513

llvm/test/MC/AArch64/SVE/mov.s

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -206,10 +206,10 @@ mov z0.h, #65280
206206
// CHECK-UNKNOWN: e0 ff 78 25 <unknown>
207207

208208
mov z0.h, #-33024
209-
// CHECK-INST: dupm z0.h, #0x7f00
210-
// CHECK-ENCODING: [0xc0,0x44,0xc0,0x05]
209+
// CHECK-INST: mov z0.h, #32512
210+
// CHECK-ENCODING: [0xe0,0xef,0x78,0x25]
211211
// CHECK-ERROR: instruction requires: sve
212-
// CHECK-UNKNOWN: c0 44 c0 05 <unknown>
212+
// CHECK-UNKNOWN: e0 ef 78 25 <unknown>
213213

214214
mov z0.h, #-32769
215215
// CHECK-INST: mov z0.h, #32767
@@ -374,6 +374,58 @@ mov z21.d, p0/z, #32512
374374
// CHECK-UNKNOWN: f5 2f d0 05 <unknown>
375375

376376

377+
// --------------------------------------------------------------------------//
378+
// Tests where the negative immediate is in bounds when interpreted
379+
// as the element type.
380+
381+
mov z0.b, #-129
382+
// CHECK-INST: mov z0.b, #127
383+
// CHECK-ENCODING: [0xe0,0xcf,0x38,0x25]
384+
// CHECK-ERROR: instruction requires: sve
385+
// CHECK-UNKNOWN: e0 cf 38 25 <unknown>
386+
387+
mov z0.h, #-129, lsl #8
388+
// CHECK-INST: mov z0.h, #32512
389+
// CHECK-ENCODING: [0xe0,0xef,0x78,0x25]
390+
// CHECK-ERROR: instruction requires: sve
391+
// CHECK-UNKNOWN: e0 ef 78 25 <unknown>
392+
393+
mov z5.h, #0xfffa
394+
// CHECK-INST: mov z5.h, #-6
395+
// CHECK-ENCODING: [0x45,0xdf,0x78,0x25]
396+
// CHECK-ERROR: instruction requires: sve
397+
// CHECK-UNKNOWN: 45 df 78 25 <unknown>
398+
399+
mov z5.s, #0xfffffffa
400+
// CHECK-INST: mov z5.s, #-6
401+
// CHECK-ENCODING: [0x45,0xdf,0xb8,0x25]
402+
// CHECK-ERROR: instruction requires: sve
403+
// CHECK-UNKNOWN: 45 df b8 25 <unknown>
404+
405+
mov z5.d, #0xfffffffffffffffa
406+
// CHECK-INST: mov z5.d, #-6
407+
// CHECK-ENCODING: [0x45,0xdf,0xf8,0x25]
408+
// CHECK-ERROR: instruction requires: sve
409+
// CHECK-UNKNOWN: 45 df f8 25 <unknown>
410+
411+
mov z0.b, p0/z, #-129
412+
// CHECK-INST: mov z0.b, p0/z, #127
413+
// CHECK-ENCODING: [0xe0,0x0f,0x10,0x05]
414+
// CHECK-ERROR: instruction requires: sve
415+
// CHECK-UNKNOWN: e0 0f 10 05 <unknown>
416+
417+
mov z0.h, p0/z, #-33024
418+
// CHECK-INST: mov z0.h, p0/z, #32512
419+
// CHECK-ENCODING: [0xe0,0x2f,0x50,0x05]
420+
// CHECK-ERROR: instruction requires: sve
421+
// CHECK-UNKNOWN: e0 2f 50 05 <unknown>
422+
423+
mov z0.h, p0/z, #-129, lsl #8
424+
// CHECK-INST: mov z0.h, p0/z, #32512
425+
// CHECK-ENCODING: [0xe0,0x2f,0x50,0x05]
426+
// CHECK-ERROR: instruction requires: sve
427+
// CHECK-UNKNOWN: e0 2f 50 05 <unknown>
428+
377429
// --------------------------------------------------------------------------//
378430
// Tests for merging variant (/m) and testing the range of predicate (> 7)
379431
// is allowed.

0 commit comments

Comments
 (0)