AArch64: Fix signbit mask creation after late combine [PR116229]
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.
This commit is contained in:
parent
c4d3dba253
commit
2c24e05683
4 changed files with 32 additions and 2 deletions
|
@ -2629,6 +2629,15 @@
|
|||
[(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")))]
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -689,6 +689,7 @@
|
|||
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.
|
||||
|
|
20
gcc/testsuite/gcc.target/aarch64/pr116229.c
Normal file
20
gcc/testsuite/gcc.target/aarch64/pr116229.c
Normal file
|
@ -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();
|
||||
}
|
Loading…
Add table
Reference in a new issue