On Thu, Jan 29, 2026 at 8:22 AM Andrew Pinski <[email protected]> wrote: > > The problem here is we try to use the widening type before > doing the bitwise expansion of neg/and for floating point types. > This moves the code around to try the bitwise expansion first. > > Note this mostly matters for NaNs where you widening (promotion) > would cause a NaN to be slightly different when doing the rounding > back.
So we may not try widening for FP neg/abs at all (unless maybe with -funsafe-math-optimizations), but instead should fall back to libcalls, no? > > Bootstrapped and tested on x86_64-linux-gnu. OK. Thanks, Richard. > PR middle-end/123869 > > gcc/ChangeLog: > > * optabs.cc (expand_unop): Move the NEG optab > handling before the widening code. > Move the ABS bitwise expansion from expand_abs_nojump > to before the widening code. > (expand_abs_nojump): Remove the bitwise expansion trial > since expand_unop is called right above. > > Signed-off-by: Andrew Pinski <[email protected]> > --- > gcc/optabs.cc | 65 ++++++++++++++++++++++++++------------------------- > 1 file changed, 33 insertions(+), 32 deletions(-) > > diff --git a/gcc/optabs.cc b/gcc/optabs.cc > index 5a1d4c75704..f94d2e49820 100644 > --- a/gcc/optabs.cc > +++ b/gcc/optabs.cc > @@ -3376,6 +3376,39 @@ expand_unop (machine_mode mode, optab unoptab, rtx > op0, rtx target, > goto try_libcall; > } > > + /* Neg should be tried via expand_absneg_bit before widening. */ > + if (optab_to_code (unoptab) == NEG) > + { > + /* Try negating floating point values by flipping the sign bit. */ > + if (is_a <scalar_float_mode> (GET_MODE_INNER (mode), &float_mode)) > + { > + temp = expand_absneg_bit (NEG, mode, float_mode, op0, target); > + if (temp) > + return temp; > + } > + > + /* If there is no negation pattern, and we have no negative zero, > + try subtracting from zero. */ > + if (!HONOR_SIGNED_ZEROS (mode)) > + { > + temp = expand_binop (mode, (unoptab == negv_optab > + ? subv_optab : sub_optab), > + CONST0_RTX (mode), op0, target, > + unsignedp, OPTAB_DIRECT); > + if (temp) > + return temp; > + } > + } > + > + /* ABS also needs to be handled similarly. */ > + if (optab_to_code (unoptab) == ABS > + && is_a <scalar_float_mode> (GET_MODE_INNER (mode), &float_mode)) > + { > + temp = expand_absneg_bit (ABS, mode, float_mode, op0, target); > + if (temp) > + return temp; > + } > + > if (CLASS_HAS_WIDER_MODES_P (mclass)) > FOR_EACH_WIDER_MODE (wider_mode, mode) > { > @@ -3460,29 +3493,6 @@ expand_unop (machine_mode mode, optab unoptab, rtx > op0, rtx target, > return temp; > } > > - if (optab_to_code (unoptab) == NEG) > - { > - /* Try negating floating point values by flipping the sign bit. */ > - if (is_a <scalar_float_mode> (GET_MODE_INNER (mode), &float_mode)) > - { > - temp = expand_absneg_bit (NEG, mode, float_mode, op0, target); > - if (temp) > - return temp; > - } > - > - /* If there is no negation pattern, and we have no negative zero, > - try subtracting from zero. */ > - if (!HONOR_SIGNED_ZEROS (mode)) > - { > - temp = expand_binop (mode, (unoptab == negv_optab > - ? subv_optab : sub_optab), > - CONST0_RTX (mode), op0, target, > - unsignedp, OPTAB_DIRECT); > - if (temp) > - return temp; > - } > - } > - > /* Try calculating parity (x) as popcount (x) % 2. */ > if (unoptab == parity_optab && is_a <scalar_int_mode> (mode, &int_mode)) > { > @@ -3680,15 +3690,6 @@ expand_abs_nojump (machine_mode mode, rtx op0, rtx > target, > if (temp != 0) > return temp; > > - /* For floating point modes, try clearing the sign bit. */ > - scalar_float_mode float_mode; > - if (is_a <scalar_float_mode> (GET_MODE_INNER (mode), &float_mode)) > - { > - temp = expand_absneg_bit (ABS, mode, float_mode, op0, target); > - if (temp) > - return temp; > - } > - > /* If we have a MAX insn, we can do this as MAX (x, -x). */ > if (optab_handler (smax_optab, mode) != CODE_FOR_nothing > && !HONOR_SIGNED_ZEROS (mode)) > -- > 2.43.0 >
