Re: [PATCH 1/2] emit-rtl, lra: Move lra's emit_inc to emit-rtl.cc

2023-12-14 Thread Vladimir Makarov



On 12/13/23 16:00, Alex Coplan wrote:

Hi,

In PR112906 we ICE because we try to use force_reg to reload an
auto-increment address, but force_reg can't do this.

With the aim of fixing the PR by supporting reloading arbitrary
addresses in pre-RA splitters, this patch generalizes
lra-constraints.cc:emit_inc and makes it available to the rest of the
compiler by moving the generalized version to emit-rtl.cc.

We observe that the separate IN parameter to LRA's emit_inc is
redundant, since the function is static and is only (statically) called
once in lra-constraints.cc, with in == value.  As such, we drop the IN
parameter and simplify the code accordingly.

The function was initially adopted from reload1.cc:inc_for_reload.

We wrap the emit_inc code in a virtual class to allow LRA to override
how reload pseudos are created, thereby preserving the existing LRA
behaviour as much as possible.

We then add a second (higher-level) routine to emit-rtl.cc,
force_reload_address, which can reload arbitrary addresses.  This uses
the generalized emit_inc code to handle the RTX_AUTOINC case.  The
second patch in this series uses force_reload_address to fix PR112906.

Since we intend to call address_reload_context::emit_autoinc from within
splitters, and the code lifted from LRA calls recog, we have to avoid
clobbering recog_data.  We do this by introducing a new RAII class for
saving/restoring recog_data on the stack.

Bootstrapped/regtested on aarch64-linux-gnu, bootstrapped on
x86_64-linux-gnu, OK for trunk?

OK for me.  Thank you.

gcc/ChangeLog:

PR target/112906
* emit-rtl.cc (address_reload_context::emit_autoinc): New.
(force_reload_address): New.
* emit-rtl.h (struct address_reload_context): Declare.
(force_reload_address): Declare.
* lra-constraints.cc (class lra_autoinc_reload_context): New.
(emit_inc): Drop IN parameter, invoke
code moved to emit-rtl.cc:address_reload_context::emit_autoinc.
(curr_insn_transform): Drop redundant IN parameter in call to
emit_inc.
* recog.h (class recog_data_saver): New.




Re: [PATCH 1/2] emit-rtl, lra: Move lra's emit_inc to emit-rtl.cc

2023-12-13 Thread Richard Sandiford
Alex Coplan  writes:
> Hi,
>
> In PR112906 we ICE because we try to use force_reg to reload an
> auto-increment address, but force_reg can't do this.
>
> With the aim of fixing the PR by supporting reloading arbitrary
> addresses in pre-RA splitters, this patch generalizes
> lra-constraints.cc:emit_inc and makes it available to the rest of the
> compiler by moving the generalized version to emit-rtl.cc.
>
> We observe that the separate IN parameter to LRA's emit_inc is
> redundant, since the function is static and is only (statically) called
> once in lra-constraints.cc, with in == value.  As such, we drop the IN
> parameter and simplify the code accordingly.
>
> We wrap the emit_inc code in a virtual class to allow LRA to override
> how reload pseudos are created, thereby preserving the existing LRA
> behaviour as much as possible.
>
> We then add a second (higher-level) routine to emit-rtl.cc,
> force_reload_address, which can reload arbitrary addresses.  This uses
> the generalized emit_inc code to handle the RTX_AUTOINC case.  The
> second patch in this series uses force_reload_address to fix PR112906.
>
> Since we intend to call address_reload_context::emit_autoinc from within
> splitters, and the code lifted from LRA calls recog, we have to avoid
> clobbering recog_data.  We do this by introducing a new RAII class for
> saving/restoring recog_data on the stack.
>
> Bootstrapped/regtested on aarch64-linux-gnu, bootstrapped on
> x86_64-linux-gnu, OK for trunk?
>
> Thanks,
> Alex
>
> gcc/ChangeLog:
>
>   PR target/112906
>   * emit-rtl.cc (address_reload_context::emit_autoinc): New.
>   (force_reload_address): New.
>   * emit-rtl.h (struct address_reload_context): Declare.
>   (force_reload_address): Declare.
>   * lra-constraints.cc (class lra_autoinc_reload_context): New.
>   (emit_inc): Drop IN parameter, invoke
>   code moved to emit-rtl.cc:address_reload_context::emit_autoinc.
>   (curr_insn_transform): Drop redundant IN parameter in call to
>   emit_inc.
>   * recog.h (class recog_data_saver): New.

LGTM, and looks like it should functionally be a no-op for LRA.

So OK, but please give Vlad 24 hours to comment, or to ask for more time.

Thanks,
Richard

>
> diff --git a/gcc/emit-rtl.cc b/gcc/emit-rtl.cc
> index 4a7e420e7c0..ce7b98bf006 100644
> --- a/gcc/emit-rtl.cc
> +++ b/gcc/emit-rtl.cc
> @@ -58,6 +58,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "rtl-iter.h"
>  #include "stor-layout.h"
>  #include "opts.h"
> +#include "optabs.h"
>  #include "predict.h"
>  #include "rtx-vector-builder.h"
>  #include "gimple.h"
> @@ -2576,6 +2577,140 @@ replace_equiv_address_nv (rtx memref, rtx addr, bool 
> inplace)
>return change_address_1 (memref, VOIDmode, addr, 0, inplace);
>  }
>  
> +
> +/* Emit insns to reload VALUE into a new register.  VALUE is an
> +   auto-increment or auto-decrement RTX whose operand is a register or
> +   memory location; so reloading involves incrementing that location.
> +
> +   INC_AMOUNT is the number to increment or decrement by (always
> +   positive and ignored for POST_MODIFY/PRE_MODIFY).
> +
> +   Return a pseudo containing the result.  */
> +rtx
> +address_reload_context::emit_autoinc (rtx value, poly_int64 inc_amount)
> +{
> +  /* Since we're going to call recog, and might be called within recog,
> + we need to ensure we save and restore recog_data.  */
> +  recog_data_saver recog_save;
> +
> +  /* REG or MEM to be copied and incremented.  */
> +  rtx incloc = XEXP (value, 0);
> +
> +  const rtx_code code = GET_CODE (value);
> +  const bool post_p
> += code == POST_DEC || code == POST_INC || code == POST_MODIFY;
> +
> +  bool plus_p = true;
> +  rtx inc;
> +  if (code == PRE_MODIFY || code == POST_MODIFY)
> +{
> +  gcc_assert (GET_CODE (XEXP (value, 1)) == PLUS
> +   || GET_CODE (XEXP (value, 1)) == MINUS);
> +  gcc_assert (rtx_equal_p (XEXP (XEXP (value, 1), 0), XEXP (value, 0)));
> +  plus_p = GET_CODE (XEXP (value, 1)) == PLUS;
> +  inc = XEXP (XEXP (value, 1), 1);
> +}
> +  else
> +{
> +  if (code == PRE_DEC || code == POST_DEC)
> + inc_amount = -inc_amount;
> +
> +  inc = gen_int_mode (inc_amount, GET_MODE (value));
> +}
> +
> +  rtx result;
> +  if (!post_p && REG_P (incloc))
> +result = incloc;
> +  else
> +{
> +  result = get_reload_reg ();
> +  /* First copy the location to the result register.  */
> +  emit_insn (gen_move_insn (result, incloc));
> +}
> +
> +  /* See if we can directly increment INCLOC.  */
> +  rtx_insn *last = get_last_insn ();
> +  rtx_insn *add_insn = emit_insn (plus_p
> +   ? gen_add2_insn (incloc, inc)
> +   : gen_sub2_insn (incloc, inc));
> +  const int icode = recog_memoized (add_insn);
> +  if (icode >= 0)
> +{
> +  if (!post_p && result != incloc)
> + emit_insn (gen_move_insn (result, incloc));
> +  return res