https://gcc.gnu.org/bugzilla/show_bug.cgi?id=123027
Hongtao Liu <liuhongt at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |liuhongt at gcc dot gnu.org
--- Comment #3 from Hongtao Liu <liuhongt at gcc dot gnu.org> ---
(In reply to Richard Biener from comment #2)
> For "reasons" RTL expansion differs here, using a jumpy sequence w/o
> -ffinite-math-only, but an if-converted variant if not. IIRC this is the x86
> expander which likely fails to recognize equal compare args and thus
> min/max. IIRC there's another PR for this already.
>
> TER should come to the rescue here. The x86 backend gets
>
> (ge (reg/v:SF 100 [ a ])
> (reg/v:SF 101 [ b ])) ? (reg/v:SF 101 [ b ]) : (reg/v:SF 100 [ a ])
>
> then decides to turn this into (le ...) ? : instead of inverting the compare
> (which should be valid with -ffinite-math-only) and ix86_expand_sse_fp_minmax
> does not recognize the LE min():
>
> static bool
> ix86_expand_sse_fp_minmax (rtx dest, enum rtx_code code, rtx cmp_op0,
> rtx cmp_op1, rtx if_true, rtx if_false)
> {
> machine_mode mode;
> bool is_min;
> rtx tmp;
>
> if (code == LT)
> ;
> else if (code == UNGE)
> std::swap (if_true, if_false);
> else
> return false;
>
> this could add
>
> else if (code == LE && !HONOR_NANS (mode))
> ;
>
> I'll note that we end up with GE only because of prepare_cmp_insn not
> accepting LT for cbranch but GE is and what reversed_comparison_code_parts
> does depends on HONOR_NANS.
>
> The following works for me:
>
> diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc
> index fd9bcaa8541..da96454a73a 100644
> --- a/gcc/config/i386/i386-expand.cc
> +++ b/gcc/config/i386/i386-expand.cc
> @@ -4163,7 +4163,8 @@ ix86_expand_sse_fp_minmax (rtx dest, enum rtx_code
> code, rtx cmp_op0,
> bool is_min;
> rtx tmp;
>
> - if (code == LT)
> + mode = GET_MODE (dest);
> + if (code == LT || (code == LE && !HONOR_NANS (mode)))
> ;
Yes, please also add UNGT if !HONOR_NANS (mode)
else if (code == UNGE || (code == UNGT && !HONOR_NANS (mode)))
std::swap (if_true, if_false);