> -----Original Message----- > From: Richard Biener <richard.guent...@gmail.com> > Sent: Thursday, December 14, 2023 5:23 AM > To: Andrew Pinski (QUIC) <quic_apin...@quicinc.com> > Cc: gcc-patches@gcc.gnu.org > Subject: Re: [PATCH] middle-end: Fix up constant handling in > emit_conditional_move [PR111260] > > 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).
I was originally deciding between that patch and what this one. I decided to go with this one in the end as I was trying to keep the extra optimization. Anyways I test and commit the one with just the checking of the modes to be equal. Also it is not that rtx_equal_p is lazy on mode mismatches but rather all CONST_INT don't have a mode (all have VOIDmode); this is why you have to pass around the cmpmode and the outer mode of the conditional. Thanks, Andrew > > 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 > >