[AArch64] PR target/85512: Tighten SIMD right shift immediate constraints
authorKyrylo Tkachov <kyrylo.tkachov@arm.com>
Tue, 24 Apr 2018 16:58:49 +0000 (16:58 +0000)
committerKyrylo Tkachov <ktkachov@gcc.gnu.org>
Tue, 24 Apr 2018 16:58:49 +0000 (16:58 +0000)
In this testcase it is possible to generate an invalid SISD shift of zero:
Error: immediate value out of range 1 to 64 at operand 3 -- `sshr v9.2s,v0.2s,0'

The SSHR and USHR instructions require a shift from 1 up to the element size.
However our constraints on the scalar shifts that generate these patterns
allow a shift amount of zero as well. The pure GP-reg ASR and LSR instructions allow a shift amount of zero.

It is unlikely that a shift of zero will survive till the end of compilation, but it's not impossible, as this PR shows.

The patch tightens up the constraints in the offending patterns by adding two new constraints
that allow shift amounts [1,32] and [1,64] and using them in *aarch64_ashr_sisd_or_int_<mode>3
and *aarch64_lshr_sisd_or_int_<mode>3.
The left-shift SISD instructions SHL and USHL allow a shift amount of zero so don't need adjustment
The vector shift patterns that map down to SSHR and USHR already enforce the correct immediate range.

        PR target/85512
        * config/aarch64/constraints.md (Usg, Usj): New constraints.
        * config/aarch64/iterators.md (cmode_simd): New mode attribute.
        * config/aarch64/aarch64.md (*aarch64_ashr_sisd_or_int_<mode>3):
        Use the above on operand 2.  Reindent.
        (*aarch64_lshr_sisd_or_int_<mode>3): Likewise.

        * gcc.dg/pr85512.c: New test.

From-SVN: r259614

gcc/ChangeLog
gcc/config/aarch64/aarch64.md
gcc/config/aarch64/constraints.md
gcc/config/aarch64/iterators.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr85512.c [new file with mode: 0644]

index 4421420979610b221db4027a0c6846d3222626ef..1837b2621898056bb63642b896886fd33850455b 100644 (file)
@@ -1,3 +1,12 @@
+2018-04-24  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
+
+       PR target/85512
+       * config/aarch64/constraints.md (Usg, Usj): New constraints.
+       * config/aarch64/iterators.md (cmode_simd): New mode attribute.
+       * config/aarch64/aarch64.md (*aarch64_ashr_sisd_or_int_<mode>3):
+       Use the above on operand 2.  Reindent.
+       (*aarch64_lshr_sisd_or_int_<mode>3): Likewise.
+
 2018-04-24  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR target/85485
index 10fcde6a1b6a5251857f2dd623d61c0dbff06993..32a0e1f3685746b9a7d70239745586d0f0fa7ee1 100644 (file)
   [(set (match_operand:GPI 0 "register_operand" "=r,r,w,&w,&w")
        (lshiftrt:GPI
         (match_operand:GPI 1 "register_operand" "r,r,w,w,w")
-        (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r,Us<cmode>,w,0")))]
+        (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>"
+                             "Us<cmode>,r,Us<cmode_simd>,w,0")))]
   ""
   "@
    lsr\t%<w>0, %<w>1, %2
 ;; Arithmetic right shift using SISD or Integer instruction
 (define_insn "*aarch64_ashr_sisd_or_int_<mode>3"
   [(set (match_operand:GPI 0 "register_operand" "=r,r,w,&w,&w")
-        (ashiftrt:GPI
-          (match_operand:GPI 1 "register_operand" "r,r,w,w,w")
-          (match_operand:QI 2 "aarch64_reg_or_shift_imm_di" "Us<cmode>,r,Us<cmode>,w,0")))]
+       (ashiftrt:GPI
+         (match_operand:GPI 1 "register_operand" "r,r,w,w,w")
+         (match_operand:QI 2 "aarch64_reg_or_shift_imm_di"
+                              "Us<cmode>,r,Us<cmode_simd>,w,0")))]
   ""
   "@
    asr\t%<w>0, %<w>1, %2
index f052103e859ebc0c8707d54561216794e0dd3d59..b5da997e7bab1541ed1401a94a3b94a0cde8017f 100644 (file)
        (match_test "!(aarch64_is_noplt_call_p (op)
                      || aarch64_is_long_call_p (op))")))
 
+(define_constraint "Usg"
+  "@internal
+  A constraint that matches an immediate right shift constant in SImode
+  suitable for a SISD instruction."
+  (and (match_code "const_int")
+       (match_test "IN_RANGE (ival, 1, 32)")))
+
+(define_constraint "Usj"
+  "@internal
+  A constraint that matches an immediate right shift constant in DImode
+  suitable for a SISD instruction."
+  (and (match_code "const_int")
+       (match_test "IN_RANGE (ival, 1, 64)")))
+
 (define_constraint "UsM"
   "@internal
   A constraint that matches the immediate constant -1."
index fa181794392d4dc48e9a6df5cf5db14a9824cd2d..25991d97836498f48ca30b8757ed7963217da417 100644 (file)
 ;; Map a mode to a specific constraint character.
 (define_mode_attr cmode [(QI "q") (HI "h") (SI "s") (DI "d")])
 
+;; Map modes to Usg and Usj constraints for SISD right shifts
+(define_mode_attr cmode_simd [(SI "g") (DI "j")])
+
 (define_mode_attr Vtype [(V8QI "8b") (V16QI "16b")
                         (V4HI "4h") (V8HI  "8h")
                          (V2SI "2s") (V4SI  "4s")
index 7d551408cdb8fcea60865f84c5a64b1359fc335e..ff4b5fbe28384717d6b94e62e4fbffccb181325f 100644 (file)
@@ -1,3 +1,8 @@
+2018-04-24  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
+
+       PR target/85512
+       * gcc.dg/pr85512.c: New test.
+
 
        PR target/85485
        * g++.dg/cet-notrack-1.C (dg-options): Remove -mcet.
diff --git a/gcc/testsuite/gcc.dg/pr85512.c b/gcc/testsuite/gcc.dg/pr85512.c
new file mode 100644 (file)
index 0000000..b581f83
--- /dev/null
@@ -0,0 +1,47 @@
+/* { dg-do assemble } */
+/* { dg-options "-O -fno-if-conversion" } */
+
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned int u32;
+typedef unsigned long long u64;
+u64
+bar0(u8 u8_0, u16 u16_0, u32 u32_0, u64 u64_0, u8 u8_1, u16 u16_1, u32 u32_1, u64 u64_1, u8 u8_2, u16 u16_2, u32 u32_2, u64 u64_2, u8 u8_3, u16 u16_3, u32 u32_3, u64 u64_3);
+u64
+bar1(u8 u8_0, u16 u16_0, u32 u32_0, u64 u64_0, u8 u8_1, u16 u16_1, u32 u32_1, u64 u64_1, u8 u8_2, u16 u16_2, u32 u32_2, u64 u64_2, u8 u8_3, u16 u16_3, u32 u32_3, u64 u64_3);
+u64
+bar2(u8 u8_0, u16 u16_0, u32 u32_0, u64 u64_0, u8 u8_1, u16 u16_1, u32 u32_1, u64 u64_1, u8 u8_2, u16 u16_2, u32 u32_2, u64 u64_2, u8 u8_3, u16 u16_3, u32 u32_3, u64 u64_3);
+u64
+bar0(u8 u8_0, u16 u16_0, u32 u32_0, u64 u64_0, u8 u8_1, u16 u16_1, u32 u32_1, u64 u64_1, u8 u8_2, u16 u16_2, u32 u32_2, u64 u64_2, u8 u8_3, u16 u16_3, u32 u32_3, u64 u64_3)
+{
+l0:     u32_2 += __builtin_add_overflow_p((u32)(u64)u32_0, (u16)-(u32)u64_2, (u64)-(u64)(unsigned)__builtin_parityll((u16)(u16)(((u64)0x1a6cb5b10 << 0))));
+        u8_3 <<= __builtin_add_overflow((u16)~(u32)u64_2, (u16)(u8)(unsigned)__builtin_popcountll((u16)-(u8)(((u64)0x725582 << 0))), &u32_1);
+        u64_1 -= (u8)~(u8)(0);
+        u16_3 = (u16_3 >> ((u32)~(u8)(1) & 15)) | (u16_3 << ((16 - ((u32)~(u8)(1) & 15)) & 15));
+        u8_2 = __builtin_mul_overflow((u64)(u8)__builtin_bswap32((u32)-(u32)u16_0), (u64)(u16)u16_2, &u8_3) ? (u64)~(u8)u8_3 : (u16)(u16)(((u64)0x7ffffff << 0));
+        u32_0 *= (u8)(u8)(((u64)0x1ffffffffffffff << 0));
+        u32_1 >>= (u64)~(u64)(((u64)0x61bf860d09fb3a << 0)) >= (u8)(u16)(unsigned)__builtin_parityll((u16)(u8)(((u64)0x6 << 0)));
+        u16_0 >>= __builtin_add_overflow_p((u64)-(u8)(((u64)0x68b4dda55e3 << 0)), (u16)(u64)__builtin_bswap64((u16)~(u32)__builtin_bswap32((u32)(u32)u8_3)), (u64)(u16)u16_1);
+        u64_0 += (u8)-(u64)(((u64)0xcc88a5c0292b6ba0 << 0));
+        u32_0 += __builtin_mul_overflow((u8)-(u64)(((u64)0xc89172ea72a << 0)), (u64)(u64)u8_2, &u8_3);
+        u64_0 >>= __builtin_add_overflow((u32)-(u64)(0), (u32)-(u16)u8_1, &u8_2);
+        u16_1 >>= (u32)(u64)u16_1 & 15;
+        u16_3 ^= (u16)~(u16)(1);
+        u32_2 &= (u16)-(u32)(0);
+l1:     u32_3 = (u32_3 >> ((u64)(u32)u32_1 & 31)) | (u32_3 << ((32 - ((u64)(u32)u32_1 & 31)) & 31));
+        u64_1 |= (u64)~(u64)(unsigned)__builtin_parityll((u8)-(u32)u32_1);
+        u8_3 *= __builtin_add_overflow((u64)-(u32)(((u64)0xffff << 0)), (u32)~(u64)(((u64)0x117e3e << 0)), &u32_2);
+        u16_3 = (u16_3 << ((u64)~(u8)(((u64)0xf78e81 << 0)) & 15)) | (u16_3 >> ((16 - ((u64)~(u8)(((u64)0xf78e81 << 0)) & 15)) & 15));
+        u64_1 = (u64)(u16)bar1((u8)((u32)(u64)(((u64)0x3ffffff << 0))), (u16)((u8)(u16)(((u64)0x5b << 0))), (u32)((u32)~(u8)(1)), (u64)((u8)(u16)(unsigned)__builtin_clrsb((u32)~(u32)(unsigned)__builtin_clrsbll((u8)(u16)(((u64)0xffffffff << 0))))), (u8)((u8)-(u64)(((u64)0x3e43180756484 << 0))), (u16)((u8)(u16)(((u64)0x7 << 0))), (u32)((u64)(u32)(((u64)0x285fa35c89 << 0))), (u64)((u32)(u8)(((u64)0x3ffff << 0))), (u8)((u16)-(u32)(((u64)0x73d01 << 0))), (u16)((u16)-(u16)(((u64)0x1fffffffffffff << 0))), (u32)((u16)(u64)(0)), (u64)((u16)(u32)(((u64)0x4c << 0))), (u8)((u64)-(u64)(((u64)0x3fffffffffffff << 0))), (u16)((u16)~(u16)(((u64)0xfffffffff << 0))), (u32)((u64)(u16)(((u64)0x7edb0cc1c << 0))), (u64)((u32)(u64)(((u64)0x1ffffffffff << 0)))) > (u16)-(u64)(((u64)0x7 << 0)) ? (u16)(u8)u64_2 : (u64)(u16)u32_2;
+        u32_0 >>= (u8)(u16)(((u64)0x32 << 0)) != (u16)-(u64)u16_3;
+        u16_1 *= __builtin_mul_overflow_p((u64)(u32)u32_1, (u16)(u8)(((u64)0x4ad149d89bf0be6 << 0)), (u64)(u32)(((u64)0x1bd7589 << 0)));
+        u8_1 &= (u64)-(u64)u8_0;
+        u16_3 %= (u16)(u16)(unsigned)__builtin_clrsbll((u32)~(u32)(((u64)0x3db8721fd79 << 0)));
+        u8_3 >>= (u32)(u8)u8_1 & 7;
+        u64_1 |= (u8)-(u64)(unsigned)__builtin_ffsll((u32)-(u64)bar2((u8)((u16)(u16)(((u64)0x3 << 0))), (u16)((u32)-(u8)(((u64)0x86af5 << 0))), (u32)((u16)-(u64)__builtin_bswap64((u64)-(u64)(0))), (u64)((u16)(u16)(((u64)0x75138426ec84c6 << 0))), (u8)((u64)(u32)(((u64)0x7fffffffff << 0))), (u16)((u32)~(u8)(((u64)0x71aa939dbdf3 << 0))), (u32)((u16)(u32)(((u64)0x8776ee7dbb651a2d << 0))), (u64)((u8)(u64)(0)), (u8)((u16)(u8)(unsigned)__builtin_clrsbll((u16)~(u32)(((u64)0x8df94655ec8430 << 0)))), (u16)((u16)-(u64)(unsigned)__builtin_clrsbll((u32)(u64)(((u64)0x3090a532 << 0)))), (u32)((u16)~(u16)(1)), (u64)((u8)(u32)(((u64)0x7fffffffffff << 0))), (u8)((u32)~(u64)(0)), (u16)((u8)~(u8)(unsigned)__builtin_ffs((u64)(u64)(0))), (u32)((u16)-(u8)(((u64)0x5dfe702 << 0))), (u64)((u8)(u64)(((u64)0x68f2a584e0 << 0)))));
+        u32_3 >>= (u32)-(u32)u32_2 & 31;
+        u8_3 = (u8_3 >> ((u32)-(u8)u8_1 & 7)) | (u8_3 << ((8 - ((u32)-(u8)u8_1 & 7)) & 7));
+        u8_2 >>= (u16)-(u64)u64_3 & 7;
+        u32_1 = (u32_1 >> ((u16)(u16)(1) & 31)) | (u32_1 << ((32 - ((u16)(u16)(1) & 31)) & 31));
+        return u8_0 + u16_0 + u32_0 + u64_0 + u8_1 + u16_1 + u32_1 + u64_1 + u8_2 + u16_2 + u32_2 + u64_2 + u8_3 + u16_3 + u32_3 + u64_3;
+}