[arm] PR target/83687: Fix invalid combination of VSUB + VABS into VABD
authorKyrylo Tkachov <kyrylo.tkachov@arm.com>
Mon, 15 Jan 2018 11:56:03 +0000 (11:56 +0000)
committerKyrylo Tkachov <ktkachov@gcc.gnu.org>
Mon, 15 Jan 2018 11:56:03 +0000 (11:56 +0000)
In this wrong-code bug we combine a VSUB.I8 and a VABS.S8
into a VABD.S8 instruction . This combination is not valid
for integer operands because in the VABD instruction the semantics
are that the difference is computed in notionally infinite precision
and the absolute difference is computed on that, whereas for a
VSUB.I8 + VABS.S8 sequence the VSUB operation will perform any
wrapping that's needed for the 8-bit signed type before the VABS
gets its hands on it.

This leads to the wrong-code in the PR where the expected
sequence from the intrinsics:
VSUB + VABS of two vectors {-100, -100, -100...}, {100, 100, 100...}
gives a result of {56, 56, 56...} (-100 - 100)

but GCC optimises it into a single
VABD of {-100, -100, -100...}, {100, 100, 100...}
which produces a result of {200, 200, 200...}

The transformation is still valid for floating-point operands,
which is why it was added in the first place I believe (r178817)
but this patch disables it for integer operands.
The HFmode variants though only exist for TARGET_NEON_FP16INST, so
this patch adds the appropriate guards to the new mode iterator

Bootstrapped and tested on arm-none-linux-gnueabihf.

PR target/83687
* config/arm/iterators.md (VF): New mode iterator.
* config/arm/neon.md (neon_vabd<mode>_2): Use the above.
Remove integer-related logic from pattern.
(neon_vabd<mode>_3): Likewise.

* gcc.target/arm/neon-combine-sub-abs-into-vabd.c: Delete integer
tests.
* gcc.target/arm/pr83687.c: New test.

From-SVN: r256696

gcc/ChangeLog
gcc/config/arm/iterators.md
gcc/config/arm/neon.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/arm/neon-combine-sub-abs-into-vabd.c
gcc/testsuite/gcc.target/arm/pr83687.c [new file with mode: 0644]

index 76977e0d053556e6ffbf3c2f198ee2c80283a035..980573ff3c6bdacb7417476c5679b3da149b3f7d 100644 (file)
@@ -1,3 +1,11 @@
+2018-01-15  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
+
+       PR target/83687
+       * config/arm/iterators.md (VF): New mode iterator.
+       * config/arm/neon.md (neon_vabd<mode>_2): Use the above.
+       Remove integer-related logic from pattern.
+       (neon_vabd<mode>_3): Likewise.
+
 2018-01-15  Jakub Jelinek  <jakub@redhat.com>
 
        PR middle-end/82694
index 5772aa99cc92de66ef4438b76632e86325a96ef2..0b2d42399d22ba89a976e39bef6182d31173c1ef 100644 (file)
 ;; All supported vector modes (except singleton DImode).
 (define_mode_iterator VDQ [V8QI V16QI V4HI V8HI V2SI V4SI V4HF V8HF V2SF V4SF V2DI])
 
+;; All supported floating-point vector modes (except V2DF).
+(define_mode_iterator VF [(V4HF "TARGET_NEON_FP16INST")
+                          (V8HF "TARGET_NEON_FP16INST") V2SF V4SF])
+
 ;; All supported vector modes (except those with 64-bit integer elements).
 (define_mode_iterator VDQW [V8QI V16QI V4HI V8HI V2SI V4SI V2SF V4SF])
 
index 59fb6435da8abfe46254558e8646cd4606acb4fa..6a6f5d737715e4100adee8fb7de1d6211da3d85c 100644 (file)
@@ -6706,28 +6706,22 @@ if (BYTES_BIG_ENDIAN)
 })
 
 (define_insn "neon_vabd<mode>_2"
- [(set (match_operand:VDQ 0 "s_register_operand" "=w")
-       (abs:VDQ (minus:VDQ (match_operand:VDQ 1 "s_register_operand" "w")
-                           (match_operand:VDQ 2 "s_register_operand" "w"))))]
- "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)"
+ [(set (match_operand:VF 0 "s_register_operand" "=w")
+       (abs:VF (minus:VF (match_operand:VF 1 "s_register_operand" "w")
+                        (match_operand:VF 2 "s_register_operand" "w"))))]
+ "TARGET_NEON && flag_unsafe_math_optimizations"
  "vabd.<V_s_elem> %<V_reg>0, %<V_reg>1, %<V_reg>2"
- [(set (attr "type")
-       (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
-                     (const_string "neon_fp_abd_s<q>")
-                     (const_string "neon_abd<q>")))]
+ [(set_attr "type" "neon_fp_abd_s<q>")]
 )
 
 (define_insn "neon_vabd<mode>_3"
- [(set (match_operand:VDQ 0 "s_register_operand" "=w")
-       (abs:VDQ (unspec:VDQ [(match_operand:VDQ 1 "s_register_operand" "w")
-                             (match_operand:VDQ 2 "s_register_operand" "w")]
-                 UNSPEC_VSUB)))]
- "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)"
+ [(set (match_operand:VF 0 "s_register_operand" "=w")
+       (abs:VF (unspec:VF [(match_operand:VF 1 "s_register_operand" "w")
+                           (match_operand:VF 2 "s_register_operand" "w")]
+               UNSPEC_VSUB)))]
+ "TARGET_NEON && flag_unsafe_math_optimizations"
  "vabd.<V_if_elem> %<V_reg>0, %<V_reg>1, %<V_reg>2"
- [(set (attr "type")
-       (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
-                     (const_string "neon_fp_abd_s<q>")
-                     (const_string "neon_abd<q>")))]
+ [(set_attr "type" "neon_fp_abd_s<q>")]
 )
 
 ;; Copy from core-to-neon regs, then extend, not vice-versa
index 748fdf3c7c5cdbb6dc59649670c0982e6874f5af..9d0aeb02e7872194b9ff211ea350cf7e6a4decf5 100644 (file)
@@ -1,3 +1,10 @@
+2018-01-15  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
+
+       PR target/83687
+       * gcc.target/arm/neon-combine-sub-abs-into-vabd.c: Delete integer
+       tests.
+       * gcc.target/arm/pr83687.c: New test.
+
 2018-01-15  Georg-Johann Lay  <avr@gjlay.de>
 
        Adjust tests to AVR_TINY.
index fe3d78b308cde0338300785cf7cb6ca77a831e3d..784714f0e87d8cd1216af948c61cdb87319e02cd 100644 (file)
@@ -12,31 +12,3 @@ float32x2_t f_sub_abs_to_vabd_32(float32x2_t val1, float32x2_t val2)
   return res;
 }
 /* { dg-final { scan-assembler "vabd\.f32" } }*/
-
-#include <arm_neon.h>
-int8x8_t sub_abs_to_vabd_8(int8x8_t val1, int8x8_t val2)
-{
-  int8x8_t sres = vsub_s8(val1, val2);
-  int8x8_t res = vabs_s8 (sres);
-
-  return res;
-}
-/* { dg-final { scan-assembler "vabd\.s8" } }*/
-
-int16x4_t sub_abs_to_vabd_16(int16x4_t val1, int16x4_t val2)
-{
-  int16x4_t sres = vsub_s16(val1, val2);
-  int16x4_t res = vabs_s16 (sres);
-
-  return res;
-}
-/* { dg-final { scan-assembler "vabd\.s16" } }*/
-
-int32x2_t sub_abs_to_vabd_32(int32x2_t val1, int32x2_t val2)
-{
-  int32x2_t sres = vsub_s32(val1, val2);
-  int32x2_t res = vabs_s32 (sres);
-
-   return res;
-}
-/* { dg-final { scan-assembler "vabd\.s32" } }*/
diff --git a/gcc/testsuite/gcc.target/arm/pr83687.c b/gcc/testsuite/gcc.target/arm/pr83687.c
new file mode 100644 (file)
index 0000000..4275413
--- /dev/null
@@ -0,0 +1,31 @@
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_hw } */
+/* { dg-options "-O2" } */
+/* { dg-add-options arm_neon } */
+
+#include <arm_neon.h>
+
+__attribute__ ((noinline)) int8_t
+testFunction1 (int8_t a, int8_t b)
+{
+  volatile int8x16_t sub = vsubq_s8 (vdupq_n_s8 (a), vdupq_n_s8 (b));
+  int8x16_t abs = vabsq_s8 (sub);
+  return vgetq_lane_s8 (abs, 0);
+}
+
+__attribute__ ((noinline)) int8_t
+testFunction2 (int8_t a, int8_t b)
+{
+  int8x16_t sub = vsubq_s8 (vdupq_n_s8 (a), vdupq_n_s8 (b));
+  int8x16_t abs = vabsq_s8 (sub);
+  return vgetq_lane_s8 (abs, 0);
+}
+
+int
+main (void)
+{
+  if (testFunction1 (-100, 100) != testFunction2 (-100, 100))
+    __builtin_abort ();
+
+  return 0;
+}