]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
AArch64: Fix signbit mask creation after late combine [PR116229]
authorTamar Christina <tamar.christina@arm.com>
Thu, 8 Aug 2024 17:51:30 +0000 (18:51 +0100)
committerTamar Christina <tamar.christina@arm.com>
Thu, 8 Aug 2024 17:51:30 +0000 (18:51 +0100)
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
thus producing incorrect code.

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

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.

gcc/config/aarch64/aarch64-simd.md
gcc/config/aarch64/aarch64.cc
gcc/config/aarch64/iterators.md
gcc/testsuite/gcc.target/aarch64/pr116229.c [new file with mode: 0644]

index 816f499e9634989c41da13ab7ca8a6294bb09f08..cc612ec2ca0e3d84df410242c48ff60211ae7613 100644 (file)
   [(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")))]
index 2ac5a22c848e0c694e08cea80237545736961c2e..bfd7bcdef7cb9baee33b5ae1c8054e3bcd907c60 100644 (file)
@@ -11808,8 +11808,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;
     }
 
index aaa4afefe2ce95b92dc2a3cff51ad4bdd1ee33b7..20a318e023b6b91547b1e52926a6144b02543c71 100644 (file)
     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 (file)
index 0000000..cc42078
--- /dev/null
@@ -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();
+}