Tamar Christina <tamar.christ...@arm.com> writes:
> 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.

Yeah, agreed that that's the most robust fix.

> 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.

LGTM.  OK if there are no objections in 24 hours.

Thanks,
Richard

>
> ---
>
> 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