"H.J. Lu via Gcc-patches" <gcc-patches@gcc.gnu.org> writes: > On Fri, Apr 30, 2021 at 2:06 AM Richard Sandiford > <richard.sandif...@arm.com> wrote: >> >> "H.J. Lu via Gcc-patches" <gcc-patches@gcc.gnu.org> writes: >> > gen_reg_rtx tracks stack alignment needed for pseudo registers so that >> > associated hard registers can be properly spilled onto stack. But there >> > are cases where associated hard registers will never be spilled onto >> > stack. gen_reg_rtx is changed to take an argument for register alignment >> > so that stack realignment can be avoided when not needed. >> >> How is it guaranteed that they will never be spilled though? >> I don't think that that guarantee exists for any kind of pseudo, >> except perhaps for the temporary pseudos that the RA creates to >> replace (match_scratch …)es. >> > > The caller of creating pseudo registers with specific alignment must > guarantee that they will never be spilled. I am only using it in > > /* Make operand1 a register if it isn't already. */ > if (can_create_pseudo_p () > && !register_operand (op0, mode) > && !register_operand (op1, mode)) > { > /* NB: Don't increase stack alignment requirement when forcing > operand1 into a pseudo register to copy data from one memory > location to another since it doesn't require a spill. */ > emit_move_insn (op0, > force_reg (GET_MODE (op0), op1, > (UNITS_PER_WORD * BITS_PER_UNIT))); > return; > } > > for vector moves. RA shouldn't spill it.
But this is the point: it's a case of hoping that the RA won't spill it, rather than having a guarantee that it won't. Even if the moves start out adjacent, they could be separated by later RTL optimisations, particularly scheduling. (I realise pre-RA scheduling isn't enabled by default for x86, but it can still be enabled explicitly.) Or if the same data is being copied to two locations, we might reuse values loaded by the first copy for the second copy as well. The only way to guarantee that the temporary won't be spilled is to hide it until after RA. Thanks, Richard > >> Thanks, >> Richard >> >> > * emit-rtl.c (gen_reg_rtx): Add an argument for register >> > alignment and use it if it isn't zero. >> > * explow.c (force_reg): Add an argument for register alignment >> > and pass it to gen_reg_rtx. >> > * explow.h (force_reg): Add an argument for register alignment >> > and default it to 0. >> > * expr.h (convert_to_mode): Likewise. >> > (convert_modes): Likewise. >> > * expr.c (convert_to_mode): Add an argument for register >> > alignment and pass it to convert_modes. >> > (convert_modes): Add an argument for register alignment and >> > pass it to gen_reg_rtx. >> > --- >> > gcc/emit-rtl.c | 5 +++-- >> > gcc/explow.c | 6 +++--- >> > gcc/explow.h | 2 +- >> > gcc/expr.c | 10 ++++++---- >> > gcc/expr.h | 6 ++++-- >> > gcc/rtl.h | 2 +- >> > 6 files changed, 18 insertions(+), 13 deletions(-) >> > >> > diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c >> > index 07e908624a0..4accf851d23 100644 >> > --- a/gcc/emit-rtl.c >> > +++ b/gcc/emit-rtl.c >> > @@ -1160,10 +1160,11 @@ subreg_memory_offset (const_rtx x) >> > This pseudo is assigned the next sequential register number. */ >> > >> > rtx >> > -gen_reg_rtx (machine_mode mode) >> > +gen_reg_rtx (machine_mode mode, unsigned int align) >> > { >> > rtx val; >> > - unsigned int align = GET_MODE_ALIGNMENT (mode); >> > + if (align == 0) >> > + align = GET_MODE_ALIGNMENT (mode); >> > >> > gcc_assert (can_create_pseudo_p ()); >> > >> > diff --git a/gcc/explow.c b/gcc/explow.c >> > index b6da277f689..c8673ce512d 100644 >> > --- a/gcc/explow.c >> > +++ b/gcc/explow.c >> > @@ -663,7 +663,7 @@ copy_to_mode_reg (machine_mode mode, rtx x) >> > since we mark it as a "constant" register. */ >> > >> > rtx >> > -force_reg (machine_mode mode, rtx x) >> > +force_reg (machine_mode mode, rtx x, unsigned int reg_align) >> > { >> > rtx temp, set; >> > rtx_insn *insn; >> > @@ -673,7 +673,7 @@ force_reg (machine_mode mode, rtx x) >> > >> > if (general_operand (x, mode)) >> > { >> > - temp = gen_reg_rtx (mode); >> > + temp = gen_reg_rtx (mode, reg_align); >> > insn = emit_move_insn (temp, x); >> > } >> > else >> > @@ -683,7 +683,7 @@ force_reg (machine_mode mode, rtx x) >> > insn = get_last_insn (); >> > else >> > { >> > - rtx temp2 = gen_reg_rtx (mode); >> > + rtx temp2 = gen_reg_rtx (mode, reg_align); >> > insn = emit_move_insn (temp2, temp); >> > temp = temp2; >> > } >> > diff --git a/gcc/explow.h b/gcc/explow.h >> > index 698f2a2a21c..621cdd7d356 100644 >> > --- a/gcc/explow.h >> > +++ b/gcc/explow.h >> > @@ -40,7 +40,7 @@ extern rtx copy_to_suggested_reg (rtx, rtx, >> > machine_mode); >> > >> > /* Copy a value to a register if it isn't already a register. >> > Args are mode (in case value is a constant) and the value. */ >> > -extern rtx force_reg (machine_mode, rtx); >> > +extern rtx force_reg (machine_mode, rtx, unsigned int reg_align = 0); >> > >> > /* Return given rtx, copied into a new temp reg if it was in memory. */ >> > extern rtx force_not_mem (rtx); >> > diff --git a/gcc/expr.c b/gcc/expr.c >> > index b4c110f8c17..42db4ddbe0a 100644 >> > --- a/gcc/expr.c >> > +++ b/gcc/expr.c >> > @@ -658,9 +658,10 @@ convert_mode_scalar (rtx to, rtx from, int unsignedp) >> > or by copying to a new temporary with conversion. */ >> > >> > rtx >> > -convert_to_mode (machine_mode mode, rtx x, int unsignedp) >> > +convert_to_mode (machine_mode mode, rtx x, int unsignedp, >> > + unsigned int reg_align) >> > { >> > - return convert_modes (mode, VOIDmode, x, unsignedp); >> > + return convert_modes (mode, VOIDmode, x, unsignedp, reg_align); >> > } >> > >> > /* Return an rtx for a value that would result >> > @@ -674,7 +675,8 @@ convert_to_mode (machine_mode mode, rtx x, int >> > unsignedp) >> > You can give VOIDmode for OLDMODE, if you are sure X has a nonvoid >> > mode. */ >> > >> > rtx >> > -convert_modes (machine_mode mode, machine_mode oldmode, rtx x, int >> > unsignedp) >> > +convert_modes (machine_mode mode, machine_mode oldmode, rtx x, >> > + int unsignedp, unsigned int reg_align) >> > { >> > rtx temp; >> > scalar_int_mode int_mode; >> > @@ -734,7 +736,7 @@ convert_modes (machine_mode mode, machine_mode >> > oldmode, rtx x, int unsignedp) >> > return simplify_gen_subreg (mode, x, oldmode, 0); >> > } >> > >> > - temp = gen_reg_rtx (mode); >> > + temp = gen_reg_rtx (mode, reg_align); >> > convert_move (temp, x, unsignedp); >> > return temp; >> > } >> > diff --git a/gcc/expr.h b/gcc/expr.h >> > index 9a2736f69fa..2b06da1a889 100644 >> > --- a/gcc/expr.h >> > +++ b/gcc/expr.h >> > @@ -66,10 +66,12 @@ extern void init_expr (void); >> > extern void convert_move (rtx, rtx, int); >> > >> > /* Convert an rtx to specified machine mode and return the result. */ >> > -extern rtx convert_to_mode (machine_mode, rtx, int); >> > +extern rtx convert_to_mode (machine_mode, rtx, int, >> > + unsigned int reg_align = 0); >> > >> > /* Convert an rtx to MODE from OLDMODE and return the result. */ >> > -extern rtx convert_modes (machine_mode, machine_mode, rtx, int); >> > +extern rtx convert_modes (machine_mode, machine_mode, rtx, int, >> > + unsigned int reg_align = 0); >> > >> > /* Expand a call to memcpy or memmove or memcmp, and return the result. >> > */ >> > extern rtx emit_block_op_via_libcall (enum built_in_function, rtx, rtx, >> > rtx, >> > diff --git a/gcc/rtl.h b/gcc/rtl.h >> > index 398d745aff5..c72f7fd59b9 100644 >> > --- a/gcc/rtl.h >> > +++ b/gcc/rtl.h >> > @@ -3125,7 +3125,7 @@ subreg_promoted_mode (rtx x) >> > /* In emit-rtl.c */ >> > extern rtvec gen_rtvec_v (int, rtx *); >> > extern rtvec gen_rtvec_v (int, rtx_insn **); >> > -extern rtx gen_reg_rtx (machine_mode); >> > +extern rtx gen_reg_rtx (machine_mode, unsigned int align = 0); >> > extern rtx gen_rtx_REG_offset (rtx, machine_mode, unsigned int, >> > poly_int64); >> > extern rtx gen_reg_rtx_offset (rtx, machine_mode, int); >> > extern rtx gen_reg_rtx_and_attrs (rtx);