Hi All,

The optimization to generate a DI signbit constant by using fneg was relying
on nothing being able to push the constant into the negate.  It's run quite
late for this reason.

However late combine now runs after it and triggers RTL simplification based on
the neg.  When -fno-signed-zeros this ends up dropping the - from the -0.0 and
this producing incorrect code.

This change adds a new unspec FNEG on DI mode which prevents this simplication.

Bootstrapped Regtested on aarch64-none-linux-gnu and no issues.

Ok for master?

Thanks,
Tamar

gcc/ChangeLog:

        PR target/116229
        * config/aarch64/aarch64-simd.md (aarch64_fnegv2di2<vczle><vczbe>): New.
        * config/aarch64/aarch64.cc (aarch64_maybe_generate_simd_constant):
        Update call to gen_aarch64_fnegv2di2.
        * config/aarch64/iterators.md: New UNSPEC_FNEG.

gcc/testsuite/ChangeLog:

        PR target/116229
        * gcc.target/aarch64/pr116229.c: New test.

---
diff --git a/gcc/config/aarch64/aarch64-simd.md 
b/gcc/config/aarch64/aarch64-simd.md
index 
459e11b09a19cdc97a5153cfd8c4e0e07a7ffb0c..75b2d6cf3ea0902cfe89c2f54a7e60e041fba536
 100644
--- a/gcc/config/aarch64/aarch64-simd.md
+++ b/gcc/config/aarch64/aarch64-simd.md
@@ -2629,6 +2629,15 @@ (define_insn "neg<mode>2<vczle><vczbe>"
   [(set_attr "type" "neon_fp_neg_<stype><q>")]
 )
 
+(define_insn "aarch64_fnegv2di2<vczle><vczbe>"
+ [(set (match_operand:V2DI 0 "register_operand" "=w")
+       (unspec:V2DI [(match_operand:V2DI 1 "register_operand" "w")]
+                     UNSPEC_FNEG))]
+ "TARGET_SIMD"
+ "fneg\\t%0.2d, %1.2d"
+  [(set_attr "type" "neon_fp_neg_d")]
+)
+
 (define_insn "abs<mode>2<vczle><vczbe>"
  [(set (match_operand:VHSDF 0 "register_operand" "=w")
        (abs:VHSDF (match_operand:VHSDF 1 "register_operand" "w")))]
diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index 
9810f2c039004cae4df37d07b5dcac948745011a..04fa4e71ae1ed2047f304a7a0e9607c7dc790652
 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -11804,8 +11804,8 @@ aarch64_maybe_generate_simd_constant (rtx target, rtx 
val, machine_mode mode)
       /* Use the same base type as aarch64_gen_shareable_zero.  */
       rtx zero = CONST0_RTX (V4SImode);
       emit_move_insn (lowpart_subreg (V4SImode, target, mode), zero);
-      rtx neg = lowpart_subreg (V2DFmode, target, mode);
-      emit_insn (gen_negv2df2 (neg, copy_rtx (neg)));
+      rtx neg = lowpart_subreg (V2DImode, target, mode);
+      emit_insn (gen_aarch64_fnegv2di2 (neg, copy_rtx (neg)));
       return true;
     }
 
diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
index 
95fe8f070f4c3f5770e4424162bf13b712adedf3..92bebcf48b1e4462537e8ca2b97df46de5e73cb5
 100644
--- a/gcc/config/aarch64/iterators.md
+++ b/gcc/config/aarch64/iterators.md
@@ -686,6 +686,7 @@ (define_c_enum "unspec"
     UNSPEC_FMINNMV     ; Used in aarch64-simd.md.
     UNSPEC_FMINV       ; Used in aarch64-simd.md.
     UNSPEC_FADDV       ; Used in aarch64-simd.md.
+    UNSPEC_FNEG                ; Used in aarch64-simd.md.
     UNSPEC_ADDV                ; Used in aarch64-simd.md.
     UNSPEC_SMAXV       ; Used in aarch64-simd.md.
     UNSPEC_SMINV       ; Used in aarch64-simd.md.
diff --git a/gcc/testsuite/gcc.target/aarch64/pr116229.c 
b/gcc/testsuite/gcc.target/aarch64/pr116229.c
new file mode 100644
index 
0000000000000000000000000000000000000000..cc42078478f77b3ee96de3e7fe853088d0c57c1c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/pr116229.c
@@ -0,0 +1,20 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-signed-zeros" } */
+
+typedef __attribute__((__vector_size__ (8))) unsigned long V;
+
+V __attribute__((__noipa__))
+foo (void)
+{
+  return (V){ 0x8000000000000000 };
+}
+
+V ref = (V){ 0x8000000000000000 };
+
+int
+main ()
+{
+  V v = foo ();
+  if (v[0] != ref[0])
+    __builtin_abort();
+}




-- 
diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md
index 459e11b09a19cdc97a5153cfd8c4e0e07a7ffb0c..75b2d6cf3ea0902cfe89c2f54a7e60e041fba536 100644
--- a/gcc/config/aarch64/aarch64-simd.md
+++ b/gcc/config/aarch64/aarch64-simd.md
@@ -2629,6 +2629,15 @@ (define_insn "neg<mode>2<vczle><vczbe>"
   [(set_attr "type" "neon_fp_neg_<stype><q>")]
 )
 
+(define_insn "aarch64_fnegv2di2<vczle><vczbe>"
+ [(set (match_operand:V2DI 0 "register_operand" "=w")
+       (unspec:V2DI [(match_operand:V2DI 1 "register_operand" "w")]
+		      UNSPEC_FNEG))]
+ "TARGET_SIMD"
+ "fneg\\t%0.2d, %1.2d"
+  [(set_attr "type" "neon_fp_neg_d")]
+)
+
 (define_insn "abs<mode>2<vczle><vczbe>"
  [(set (match_operand:VHSDF 0 "register_operand" "=w")
        (abs:VHSDF (match_operand:VHSDF 1 "register_operand" "w")))]
diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index 9810f2c039004cae4df37d07b5dcac948745011a..04fa4e71ae1ed2047f304a7a0e9607c7dc790652 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -11804,8 +11804,8 @@ aarch64_maybe_generate_simd_constant (rtx target, rtx val, machine_mode mode)
       /* Use the same base type as aarch64_gen_shareable_zero.  */
       rtx zero = CONST0_RTX (V4SImode);
       emit_move_insn (lowpart_subreg (V4SImode, target, mode), zero);
-      rtx neg = lowpart_subreg (V2DFmode, target, mode);
-      emit_insn (gen_negv2df2 (neg, copy_rtx (neg)));
+      rtx neg = lowpart_subreg (V2DImode, target, mode);
+      emit_insn (gen_aarch64_fnegv2di2 (neg, copy_rtx (neg)));
       return true;
     }
 
diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
index 95fe8f070f4c3f5770e4424162bf13b712adedf3..92bebcf48b1e4462537e8ca2b97df46de5e73cb5 100644
--- a/gcc/config/aarch64/iterators.md
+++ b/gcc/config/aarch64/iterators.md
@@ -686,6 +686,7 @@ (define_c_enum "unspec"
     UNSPEC_FMINNMV	; Used in aarch64-simd.md.
     UNSPEC_FMINV	; Used in aarch64-simd.md.
     UNSPEC_FADDV	; Used in aarch64-simd.md.
+    UNSPEC_FNEG		; Used in aarch64-simd.md.
     UNSPEC_ADDV		; Used in aarch64-simd.md.
     UNSPEC_SMAXV	; Used in aarch64-simd.md.
     UNSPEC_SMINV	; Used in aarch64-simd.md.
diff --git a/gcc/testsuite/gcc.target/aarch64/pr116229.c b/gcc/testsuite/gcc.target/aarch64/pr116229.c
new file mode 100644
index 0000000000000000000000000000000000000000..cc42078478f77b3ee96de3e7fe853088d0c57c1c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/pr116229.c
@@ -0,0 +1,20 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-signed-zeros" } */
+
+typedef __attribute__((__vector_size__ (8))) unsigned long V;
+
+V __attribute__((__noipa__))
+foo (void)
+{
+  return (V){ 0x8000000000000000 };
+}
+
+V ref = (V){ 0x8000000000000000 };
+
+int
+main ()
+{
+  V v = foo ();
+  if (v[0] != ref[0])
+    __builtin_abort();
+}



Reply via email to