[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