diff options
author | Sander de Smalen <sander.desmalen@arm.com> | 2021-02-11 08:14:15 +0000 |
---|---|---|
committer | Sander de Smalen <sander.desmalen@arm.com> | 2021-02-11 08:14:15 +0000 |
commit | 3b4f706ae16bb12b7d925fbf428def7cb2a6f7db (patch) | |
tree | c369f6bdebfcc741914044689d9f8c314376e8e1 | |
parent | 9325b8da1702238f15f837b6e07f099baf4dcd94 (diff) | |
download | llvm-3b4f706ae16bb12b7d925fbf428def7cb2a6f7db.zip llvm-3b4f706ae16bb12b7d925fbf428def7cb2a6f7db.tar.gz llvm-3b4f706ae16bb12b7d925fbf428def7cb2a6f7db.tar.bz2 |
[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
-rw-r--r-- | llvm/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h | 23 | ||||
-rw-r--r-- | llvm/test/MC/AArch64/SVE/cpy-diagnostics.s | 15 | ||||
-rw-r--r-- | llvm/test/MC/AArch64/SVE/cpy.s | 22 | ||||
-rw-r--r-- | llvm/test/MC/AArch64/SVE/dup-diagnostics.s | 15 | ||||
-rw-r--r-- | llvm/test/MC/AArch64/SVE/dup.s | 22 | ||||
-rw-r--r-- | llvm/test/MC/AArch64/SVE/mov-diagnostics.s | 35 | ||||
-rw-r--r-- | llvm/test/MC/AArch64/SVE/mov.s | 58 |
7 files changed, 114 insertions, 76 deletions
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h index 2cbe831..c3e74757 100644 --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h @@ -760,17 +760,24 @@ static inline bool isSVEMaskOfIdenticalElements(int64_t Imm) { /// Returns true if Imm is valid for CPY/DUP. template <typename T> static inline bool isSVECpyImm(int64_t Imm) { - bool IsImm8 = int8_t(Imm) == Imm; - bool IsImm16 = int16_t(Imm & ~0xff) == Imm; + // Imm is interpreted as a signed value, which means top bits must be all ones + // (sign bits if the immediate value is negative and passed in a larger + // container), or all zeroes. + int64_t Mask = ~int64_t(std::numeric_limits<std::make_unsigned_t<T>>::max()); + if ((Imm & Mask) != 0 && (Imm & Mask) != Mask) + return false; - if (std::is_same<int8_t, std::make_signed_t<T>>::value || - std::is_same<int8_t, T>::value) - return IsImm8 || uint8_t(Imm) == Imm; + // Imm is a signed 8-bit value. + // Top bits must be zeroes or sign bits. + if (Imm & 0xff) + return int8_t(Imm) == T(Imm); - if (std::is_same<int16_t, std::make_signed_t<T>>::value) - return IsImm8 || IsImm16 || uint16_t(Imm & ~0xff) == Imm; + // Imm is a signed 16-bit value and multiple of 256. + // Top bits must be zeroes or sign bits. + if (Imm & 0xff00) + return int16_t(Imm) == T(Imm); - return IsImm8 || IsImm16; + return Imm == 0; } /// Returns true if Imm is valid for ADD/SUB. diff --git a/llvm/test/MC/AArch64/SVE/cpy-diagnostics.s b/llvm/test/MC/AArch64/SVE/cpy-diagnostics.s index ac50932..8bc40d5 100644 --- a/llvm/test/MC/AArch64/SVE/cpy-diagnostics.s +++ b/llvm/test/MC/AArch64/SVE/cpy-diagnostics.s @@ -92,11 +92,6 @@ cpy z0.b, p0/z, #0, lsl #8 // #0, lsl #8 is not valid for .b // CHECK-NEXT: cpy z0.b, p0/z, #0, lsl #8 // CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: -cpy z0.b, p0/z, #-129 -// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 255] -// CHECK-NEXT: cpy z0.b, p0/z, #-129 -// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: - cpy z0.b, p0/z, #-1, lsl #8 // CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 255] // CHECK-NEXT: cpy z0.b, p0/z, #-1, lsl #8 @@ -112,21 +107,11 @@ cpy z0.b, p0/z, #1, lsl #8 // CHECK-NEXT: cpy z0.b, p0/z, #1, lsl #8 // CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: -cpy z0.h, p0/z, #-33024 -// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 65280] -// CHECK-NEXT: cpy z0.h, p0/z, #-33024 -// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: - cpy z0.h, p0/z, #-32769 // CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 65280] // CHECK-NEXT: cpy z0.h, p0/z, #-32769 // CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: -cpy z0.h, p0/z, #-129, lsl #8 -// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 65280] -// CHECK-NEXT: cpy z0.h, p0/z, #-129, lsl #8 -// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: - cpy z0.h, p0/z, #32513 // CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 65280] // CHECK-NEXT: cpy z0.h, p0/z, #32513 diff --git a/llvm/test/MC/AArch64/SVE/cpy.s b/llvm/test/MC/AArch64/SVE/cpy.s index d3fabef..0741b4c 100644 --- a/llvm/test/MC/AArch64/SVE/cpy.s +++ b/llvm/test/MC/AArch64/SVE/cpy.s @@ -229,6 +229,28 @@ cpy z21.d, p0/z, #32512 // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: f5 2f d0 05 <unknown> +// --------------------------------------------------------------------------// +// Tests where the negative immediate is in bounds when interpreted +// as the element type. + +cpy z0.b, p0/z, #-129 +// CHECK-INST: mov z0.b, p0/z, #127 +// CHECK-ENCODING: [0xe0,0x0f,0x10,0x05] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: e0 0f 10 05 <unknown> + +cpy z0.h, p0/z, #-33024 +// CHECK-INST: mov z0.h, p0/z, #32512 +// CHECK-ENCODING: [0xe0,0x2f,0x50,0x05] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: e0 2f 50 05 <unknown> + +cpy z0.h, p0/z, #-129, lsl #8 +// CHECK-INST: mov z0.h, p0/z, #32512 +// CHECK-ENCODING: [0xe0,0x2f,0x50,0x05] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: e0 2f 50 05 <unknown> + // --------------------------------------------------------------------------// // Tests for merging variant (/m) and testing the range of predicate (> 7) diff --git a/llvm/test/MC/AArch64/SVE/dup-diagnostics.s b/llvm/test/MC/AArch64/SVE/dup-diagnostics.s index f97ac83..5c48444 100644 --- a/llvm/test/MC/AArch64/SVE/dup-diagnostics.s +++ b/llvm/test/MC/AArch64/SVE/dup-diagnostics.s @@ -27,11 +27,6 @@ dup z0.b, #0, lsl #8 // #0, lsl #8 is not valid for .b // CHECK-NEXT: dup z0.b, #0, lsl #8 // CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: -dup z0.b, #-129 -// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 255] -// CHECK-NEXT: dup z0.b, #-129 -// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: - dup z0.b, #-1, lsl #8 // CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 255] // CHECK-NEXT: dup z0.b, #-1, lsl #8 @@ -47,21 +42,11 @@ dup z0.b, #1, lsl #8 // CHECK-NEXT: dup z0.b, #1, lsl #8 // CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: -dup z0.h, #-33024 -// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 65280] -// CHECK-NEXT: dup z0.h, #-33024 -// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: - dup z0.h, #-32769 // CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 65280] // CHECK-NEXT: dup z0.h, #-32769 // CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: -dup z0.h, #-129, lsl #8 -// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 65280] -// CHECK-NEXT: dup z0.h, #-129, lsl #8 -// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: - dup z0.h, #65281 // CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 65280] // CHECK-NEXT: dup z0.h, #65281 diff --git a/llvm/test/MC/AArch64/SVE/dup.s b/llvm/test/MC/AArch64/SVE/dup.s index 73e304e..dd7de19 100644 --- a/llvm/test/MC/AArch64/SVE/dup.s +++ b/llvm/test/MC/AArch64/SVE/dup.s @@ -240,3 +240,25 @@ dup z5.q, z17.q[3] // CHECK-ENCODING: [0x25,0x22,0xf0,0x05] // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: 25 22 f0 05 <unknown> + +// --------------------------------------------------------------------------// +// Tests where the negative immediate is in bounds when interpreted +// as the element type. + +dup z0.b, #-129 +// CHECK-INST: mov z0.b, #127 +// CHECK-ENCODING: [0xe0,0xcf,0x38,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: e0 cf 38 25 <unknown> + +dup z0.h, #-33024 +// CHECK-INST: mov z0.h, #32512 +// CHECK-ENCODING: [0xe0,0xef,0x78,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: e0 ef 78 25 <unknown> + +dup z0.h, #-129, lsl #8 +// CHECK-INST: mov z0.h, #32512 +// CHECK-ENCODING: [0xe0,0xef,0x78,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: e0 ef 78 25 <unknown> diff --git a/llvm/test/MC/AArch64/SVE/mov-diagnostics.s b/llvm/test/MC/AArch64/SVE/mov-diagnostics.s index 1e92f52..9e2ef4a 100644 --- a/llvm/test/MC/AArch64/SVE/mov-diagnostics.s +++ b/llvm/test/MC/AArch64/SVE/mov-diagnostics.s @@ -133,11 +133,6 @@ mov z0.b, #0, lsl #8 // #0, lsl #8 is not valid for .b // CHECK-NEXT: mov z0.b, #0, lsl #8 // CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: -mov z0.b, #-129 -// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 255] -// CHECK-NEXT: mov z0.b, #-129 -// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: - mov z0.b, #-1, lsl #8 // CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 255] // CHECK-NEXT: mov z0.b, #-1, lsl #8 @@ -153,11 +148,6 @@ mov z0.b, #1, lsl #8 // CHECK-NEXT: mov z0.b, #1, lsl #8 // CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: -mov z0.h, #-129, lsl #8 -// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 65280] -// CHECK-NEXT: mov z0.h, #-129, lsl #8 -// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: - // Note: 65281 is a valid logical immediate. mov z0.h, #65282 // 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 // CHECK-NEXT: mov z5.b, #0xfff9 // CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: -mov z5.h, #0xfffa -// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 65280] -// CHECK-NEXT: mov z5.h, #0xfffa -// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: - mov z5.h, #0xfffffff9 // CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 65280] // CHECK-NEXT: mov z5.h, #0xfffffff9 // CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: -mov z5.s, #0xfffffffa -// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 32512] -// CHECK-NEXT: mov z5.s, #0xfffffffa -// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: - mov z5.s, #0xffffffffffffff9 // CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 32512] // 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 // CHECK-NEXT: mov z0.b, p0/z, #0, lsl #8 // CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: -mov z0.b, p0/z, #-129 -// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 255] -// CHECK-NEXT: mov z0.b, p0/z, #-129 -// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: - mov z0.b, p0/z, #-1, lsl #8 // CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 255] // CHECK-NEXT: mov z0.b, p0/z, #-1, lsl #8 @@ -259,21 +234,11 @@ mov z0.b, p0/z, #1, lsl #8 // CHECK-NEXT: mov z0.b, p0/z, #1, lsl #8 // CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: -mov z0.h, p0/z, #-33024 -// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 65280] -// CHECK-NEXT: mov z0.h, p0/z, #-33024 -// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: - mov z0.h, p0/z, #-32769 // CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 65280] // CHECK-NEXT: mov z0.h, p0/z, #-32769 // CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: -mov z0.h, p0/z, #-129, lsl #8 -// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 65280] -// CHECK-NEXT: mov z0.h, p0/z, #-129, lsl #8 -// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: - mov z0.h, p0/z, #32513 // CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 65280] // CHECK-NEXT: mov z0.h, p0/z, #32513 diff --git a/llvm/test/MC/AArch64/SVE/mov.s b/llvm/test/MC/AArch64/SVE/mov.s index c896bfe1..92b917b 100644 --- a/llvm/test/MC/AArch64/SVE/mov.s +++ b/llvm/test/MC/AArch64/SVE/mov.s @@ -206,10 +206,10 @@ mov z0.h, #65280 // CHECK-UNKNOWN: e0 ff 78 25 <unknown> mov z0.h, #-33024 -// CHECK-INST: dupm z0.h, #0x7f00 -// CHECK-ENCODING: [0xc0,0x44,0xc0,0x05] +// CHECK-INST: mov z0.h, #32512 +// CHECK-ENCODING: [0xe0,0xef,0x78,0x25] // CHECK-ERROR: instruction requires: sve -// CHECK-UNKNOWN: c0 44 c0 05 <unknown> +// CHECK-UNKNOWN: e0 ef 78 25 <unknown> mov z0.h, #-32769 // CHECK-INST: mov z0.h, #32767 @@ -375,6 +375,58 @@ mov z21.d, p0/z, #32512 // --------------------------------------------------------------------------// +// Tests where the negative immediate is in bounds when interpreted +// as the element type. + +mov z0.b, #-129 +// CHECK-INST: mov z0.b, #127 +// CHECK-ENCODING: [0xe0,0xcf,0x38,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: e0 cf 38 25 <unknown> + +mov z0.h, #-129, lsl #8 +// CHECK-INST: mov z0.h, #32512 +// CHECK-ENCODING: [0xe0,0xef,0x78,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: e0 ef 78 25 <unknown> + +mov z5.h, #0xfffa +// CHECK-INST: mov z5.h, #-6 +// CHECK-ENCODING: [0x45,0xdf,0x78,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 45 df 78 25 <unknown> + +mov z5.s, #0xfffffffa +// CHECK-INST: mov z5.s, #-6 +// CHECK-ENCODING: [0x45,0xdf,0xb8,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 45 df b8 25 <unknown> + +mov z5.d, #0xfffffffffffffffa +// CHECK-INST: mov z5.d, #-6 +// CHECK-ENCODING: [0x45,0xdf,0xf8,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 45 df f8 25 <unknown> + +mov z0.b, p0/z, #-129 +// CHECK-INST: mov z0.b, p0/z, #127 +// CHECK-ENCODING: [0xe0,0x0f,0x10,0x05] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: e0 0f 10 05 <unknown> + +mov z0.h, p0/z, #-33024 +// CHECK-INST: mov z0.h, p0/z, #32512 +// CHECK-ENCODING: [0xe0,0x2f,0x50,0x05] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: e0 2f 50 05 <unknown> + +mov z0.h, p0/z, #-129, lsl #8 +// CHECK-INST: mov z0.h, p0/z, #32512 +// CHECK-ENCODING: [0xe0,0x2f,0x50,0x05] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: e0 2f 50 05 <unknown> + +// --------------------------------------------------------------------------// // Tests for merging variant (/m) and testing the range of predicate (> 7) // is allowed. |