diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h @@ -760,17 +760,24 @@ /// Returns true if Imm is valid for CPY/DUP. template 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>::max()); + if ((Imm & Mask) != 0 && (Imm & Mask) != Mask) + return false; - if (std::is_same>::value || - std::is_same::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>::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 --- a/llvm/test/MC/AArch64/SVE/cpy-diagnostics.s +++ b/llvm/test/MC/AArch64/SVE/cpy-diagnostics.s @@ -92,11 +92,6 @@ // 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 @@ // 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 --- a/llvm/test/MC/AArch64/SVE/cpy.s +++ b/llvm/test/MC/AArch64/SVE/cpy.s @@ -229,6 +229,28 @@ // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: f5 2f d0 05 +// --------------------------------------------------------------------------// +// 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 + +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 + +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 + // --------------------------------------------------------------------------// // 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 --- a/llvm/test/MC/AArch64/SVE/dup-diagnostics.s +++ b/llvm/test/MC/AArch64/SVE/dup-diagnostics.s @@ -27,11 +27,6 @@ // 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 @@ // 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 --- a/llvm/test/MC/AArch64/SVE/dup.s +++ b/llvm/test/MC/AArch64/SVE/dup.s @@ -240,3 +240,25 @@ // CHECK-ENCODING: [0x25,0x22,0xf0,0x05] // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: 25 22 f0 05 + +// --------------------------------------------------------------------------// +// 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 + +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 + +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 diff --git a/llvm/test/MC/AArch64/SVE/mov-diagnostics.s b/llvm/test/MC/AArch64/SVE/mov-diagnostics.s --- a/llvm/test/MC/AArch64/SVE/mov-diagnostics.s +++ b/llvm/test/MC/AArch64/SVE/mov-diagnostics.s @@ -133,11 +133,6 @@ // 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 @@ // 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 @@ // 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 @@ // 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 @@ // 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 --- a/llvm/test/MC/AArch64/SVE/mov.s +++ b/llvm/test/MC/AArch64/SVE/mov.s @@ -206,10 +206,10 @@ // CHECK-UNKNOWN: e0 ff 78 25 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 +// CHECK-UNKNOWN: e0 ef 78 25 mov z0.h, #-32769 // CHECK-INST: mov z0.h, #32767 @@ -374,6 +374,58 @@ // CHECK-UNKNOWN: f5 2f d0 05 +// --------------------------------------------------------------------------// +// 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 + +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 + +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 + +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 + +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 + +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 + +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 + +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 + // --------------------------------------------------------------------------// // Tests for merging variant (/m) and testing the range of predicate (> 7) // is allowed.