On Thu, Jan 29, 2026 at 12:59 AM Richard Biener <[email protected]> wrote: > > 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?
Yes but I am not sure that will ever happen in practice with the movement of doing the bitwise beforehand. As the only time bitwise fails is `REAL_MODE_FORMAT does not have a simple sign bit` or `GET_MODE_SIZE (mode) <= UNITS_PER_WORD && the mode does not exist` So most smaller floating point types (<=32) bitwise will never fail on most (if not all) targets and floating point modes. The only floating point mode which has more than a simple sign bit is IBM `double double` long double and 128bit floating point on 32bit targets might have issues too BUT there is no fp type to widen those types too so it won't cause an issue. Also there is https://gcc.gnu.org/bugzilla/show_bug.cgi?id=29253 which is about IBM double double long double on 32bit powerpc were abs goes wrong; it might also go wrong for NEG but I didn't look when I write a new patch for it. I will look at that again but for GCC 17. > > > > > Bootstrapped and tested on x86_64-linux-gnu. > > OK. Thanks pushed with the small comment formatting fixes that Jakub pointed out. Thanks, Andrew > > 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 > >
