[llvm] 3b4f706 - [AArch64][SVE] Asm: Fix supported immediates for DUP/CPY
Sander de Smalen via llvm-commits
llvm-commits at lists.llvm.org
Thu Feb 11 00:37:34 PST 2021
Author: Sander de Smalen
Date: 2021-02-11T08:14:15Z
New Revision: 3b4f706ae16bb12b7d925fbf428def7cb2a6f7db
URL: https://github.com/llvm/llvm-project/commit/3b4f706ae16bb12b7d925fbf428def7cb2a6f7db
DIFF: https://github.com/llvm/llvm-project/commit/3b4f706ae16bb12b7d925fbf428def7cb2a6f7db.diff
LOG: [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
Added:
Modified:
llvm/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h
llvm/test/MC/AArch64/SVE/cpy-diagnostics.s
llvm/test/MC/AArch64/SVE/cpy.s
llvm/test/MC/AArch64/SVE/dup-diagnostics.s
llvm/test/MC/AArch64/SVE/dup.s
llvm/test/MC/AArch64/SVE/mov-diagnostics.s
llvm/test/MC/AArch64/SVE/mov.s
Removed:
################################################################################
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h
index 2cbe8315bc7e..c3e74757675b 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 ac50932c81b7..8bc40d54c3da 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 d3fabef943a2..0741b4c13e93 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 f97ac83aae09..5c48444161dc 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 73e304eb331c..dd7de195f39d 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 1e92f528f561..9e2ef4adb57a 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 c896bfe1c702..92b917b4be88 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
@@ -374,6 +374,58 @@ mov z21.d, p0/z, #32512
// CHECK-UNKNOWN: f5 2f d0 05 <unknown>
+// --------------------------------------------------------------------------//
+// 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.
More information about the llvm-commits
mailing list