On Wed, Dec 13, 2023 at 5:51 PM Andrew Pinski <quic_apin...@quicinc.com> wrote:
>
> After r14-2667-gceae1400cf24f329393e96dd9720, we force a constant to a 
> register
> if it is shared with one of the other operands. The problem is used the 
> comparison
> mode for the register but that could be different from the operand mode. This
> causes some issues on some targets.
> To fix it, we either need to have the modes match or if it is an integer mode,
> then we can use the lower part for the smaller mode.
>
> Bootstrapped and tested on both aarch64-linux-gnu and x86_64-linux.

I think to fulfil the original purpose requiring matching modes is enough,
the x86 backend checks for equality here, a subreg wouldn't be enough.
In fact the whole point preserving equality doesn't work then.

So please just check the modes are equal (I also see I used
'mode' for the cost check - I've really split out the check done
by prepare_cmp_insn here btw).  This seemed to be the simplest
solution at the time, rather than for example trying to postpone
legitimizing the constants (so rtx_equal_p could continue to be
lazy with slight mode mismatches).

Richard.

>         PR middle-end/111260
>
> gcc/ChangeLog:
>
>         * optabs.cc (emit_conditional_move): Fix up mode handling for
>         forcing the constant to a register.
>
> gcc/testsuite/ChangeLog:
>
>         * gcc.c-torture/compile/condmove-1.c: New test.
>
> Signed-off-by: Andrew Pinski <quic_apin...@quicinc.com>
> ---
>  gcc/optabs.cc                                 | 40 +++++++++++++++++--
>  .../gcc.c-torture/compile/condmove-1.c        |  9 +++++
>  2 files changed, 45 insertions(+), 4 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.c-torture/compile/condmove-1.c
>
> diff --git a/gcc/optabs.cc b/gcc/optabs.cc
> index f0a048a6bdb..573cf22760e 100644
> --- a/gcc/optabs.cc
> +++ b/gcc/optabs.cc
> @@ -5131,26 +5131,58 @@ emit_conditional_move (rtx target, struct 
> rtx_comparison comp,
>           /* If we are optimizing, force expensive constants into a register
>              but preserve an eventual equality with op2/op3.  */
>           if (CONSTANT_P (orig_op0) && optimize
> +             && (cmpmode == mode
> +                 || (GET_MODE_CLASS (cmpmode) == MODE_INT
> +                     && GET_MODE_CLASS (mode) == MODE_INT))
>               && (rtx_cost (orig_op0, mode, COMPARE, 0,
>                             optimize_insn_for_speed_p ())
>                   > COSTS_N_INSNS (1))
>               && can_create_pseudo_p ())
>             {
> +             machine_mode new_mode;
> +             if (known_le (GET_MODE_PRECISION (cmpmode), GET_MODE_PRECISION 
> (mode)))
> +               new_mode = mode;
> +             else
> +               new_mode = cmpmode;
>               if (rtx_equal_p (orig_op0, op2))
> -               op2p = XEXP (comparison, 0) = force_reg (cmpmode, orig_op0);
> +               {
> +                 rtx r = force_reg (new_mode, orig_op0);
> +                 op2p = gen_lowpart (mode, r);
> +                 XEXP (comparison, 0) = gen_lowpart (cmpmode, r);
> +               }
>               else if (rtx_equal_p (orig_op0, op3))
> -               op3p = XEXP (comparison, 0) = force_reg (cmpmode, orig_op0);
> +               {
> +                 rtx r = force_reg (new_mode, orig_op0);
> +                 op3p = gen_lowpart (mode, r);
> +                 XEXP (comparison, 0) = gen_lowpart (cmpmode, r);
> +               }
>             }
>           if (CONSTANT_P (orig_op1) && optimize
> +             && (cmpmode == mode
> +                 || (GET_MODE_CLASS (cmpmode) == MODE_INT
> +                     && GET_MODE_CLASS (mode) == MODE_INT))
>               && (rtx_cost (orig_op1, mode, COMPARE, 0,
>                             optimize_insn_for_speed_p ())
>                   > COSTS_N_INSNS (1))
>               && can_create_pseudo_p ())
>             {
> +             machine_mode new_mode;
> +             if (known_le (GET_MODE_PRECISION (cmpmode), GET_MODE_PRECISION 
> (mode)))
> +               new_mode = mode;
> +             else
> +               new_mode = cmpmode;
>               if (rtx_equal_p (orig_op1, op2))
> -               op2p = XEXP (comparison, 1) = force_reg (cmpmode, orig_op1);
> +               {
> +                 rtx r = force_reg (new_mode, orig_op1);
> +                 op2p = gen_lowpart (mode, r);
> +                 XEXP (comparison, 1) = gen_lowpart (cmpmode, r);
> +               }
>               else if (rtx_equal_p (orig_op1, op3))
> -               op3p = XEXP (comparison, 1) = force_reg (cmpmode, orig_op1);
> +               {
> +                 rtx r = force_reg (new_mode, orig_op1);
> +                 op3p = gen_lowpart (mode, r);
> +                 XEXP (comparison, 1) = gen_lowpart (cmpmode, r);
> +               }
>             }
>           prepare_cmp_insn (XEXP (comparison, 0), XEXP (comparison, 1),
>                             GET_CODE (comparison), NULL_RTX, unsignedp,
> diff --git a/gcc/testsuite/gcc.c-torture/compile/condmove-1.c 
> b/gcc/testsuite/gcc.c-torture/compile/condmove-1.c
> new file mode 100644
> index 00000000000..3fcc591af00
> --- /dev/null
> +++ b/gcc/testsuite/gcc.c-torture/compile/condmove-1.c
> @@ -0,0 +1,9 @@
> +/* PR middle-end/111260 */
> +
> +/* Used to ICE while expansion of the `(a == b) ? b : 0;` */
> +int f1(long long a)
> +{
> +  int b = 822920;
> +  int t = a == b;
> +  return t * (int)b;
> +}
> --
> 2.39.3
>

Reply via email to