On Fri, Apr 16, 2021 at 12:01 PM Richard Sandiford via Gcc-patches <gcc-patches@gcc.gnu.org> wrote: > > This patch is a GCC 11 regression caused by the rtl-ssa code. > Normally we treat calls as containing a potential set of a global > register, but DF makes a sensible exception for the stack pointer: > > if (i == STACK_POINTER_REGNUM) > /* The stack ptr is used (honorarily) by a CALL insn. */ > df_ref_record (DF_REF_BASE, collection_rec, regno_reg_rtx[i], > NULL, bb, insn_info, DF_REF_REG_USE, > DF_REF_CALL_STACK_USAGE | flags); > else if (global_regs[i]) > { > /* Calls to const functions cannot access any global registers and > calls to pure functions cannot set them. All other calls may > reference any of the global registers, so they are recorded as > used. */ > > The only DF definition of SP was therefore the one in the entry block. > However, the rtlanal.c rtx_properties code (wrongly) assumed that calls > also clobbered the global SP. This led to multiple definitions of SP > when we only expected one. > > This patch tightens the rtlanal.c handling of global registers > to match the DF approach. > > Tested on aarch64-linux-gnu, arm-linux-gnueabihf, armeb-eabi and > x86_64-linux-gnu. OK to install?
Makes sense for the stack pointer handling and also for the const/pure call adjustment. I assume the latter wasn't necessary to fix the testcase though? Still OK. Thanks, Richard. > Richard > > > gcc/ > PR rtl-optimization/99596 > * rtlanal.c (rtx_properties::try_to_add_insn): Don't add global > register accesses for const calls. Assume that pure functions > can only read from global registers. Ignore cases in which > the stack pointer has been marked global. > > gcc/testsuite/ > PR rtl-optimization/99596 > * gcc.target/arm/pr99596.c: New test. > --- > gcc/rtlanal.c | 20 +++++++++++++++----- > gcc/testsuite/gcc.target/arm/pr99596.c | 18 ++++++++++++++++++ > 2 files changed, 33 insertions(+), 5 deletions(-) > create mode 100644 gcc/testsuite/gcc.target/arm/pr99596.c > > diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c > index c35386bccbd..170420a610b 100644 > --- a/gcc/rtlanal.c > +++ b/gcc/rtlanal.c > @@ -2311,15 +2311,25 @@ rtx_properties::try_to_add_insn (const rtx_insn > *insn, bool include_notes) > { > if (CALL_P (insn)) > { > - /* Adding the global registers first removes a situation in which > + /* Non-const functions can read from global registers. Impure > + functions can also set them. > + > + Adding the global registers first removes a situation in which > a fixed-form clobber of register R could come before a real set > of register R. */ > - if (!hard_reg_set_empty_p (global_reg_set)) > + if (!hard_reg_set_empty_p (global_reg_set) > + && !RTL_CONST_CALL_P (insn)) > { > - unsigned int flags = (rtx_obj_flags::IS_READ > - | rtx_obj_flags::IS_WRITE); > + unsigned int flags = rtx_obj_flags::IS_READ; > + if (!RTL_PURE_CALL_P (insn)) > + flags |= rtx_obj_flags::IS_WRITE; > for (unsigned int regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno) > - if (global_regs[regno] && ref_iter != ref_end) > + /* As a special case, the stack pointer is invariant across calls > + even if it has been marked global; see the corresponding > + handling in df_get_call_refs. */ > + if (regno != STACK_POINTER_REGNUM > + && global_regs[regno] > + && ref_iter != ref_end) > *ref_iter++ = rtx_obj_reference (regno, flags, > reg_raw_mode[regno], 0); > } > diff --git a/gcc/testsuite/gcc.target/arm/pr99596.c > b/gcc/testsuite/gcc.target/arm/pr99596.c > new file mode 100644 > index 00000000000..2b8b4c87e96 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/arm/pr99596.c > @@ -0,0 +1,18 @@ > +/* { dg-options "-Os -mtune=xscale" } */ > + > +register int a asm("sp"); > +extern int b; > +typedef struct { > + long c[16 * 8 / 32]; > +} d; > +int e; > +int f; > +int g; > +d h; > +int j(int, int, int, d); > +int i(void) { > + for (;;) { > + b &&j(e, f, g, h); > + j(e, f, g, h); > + } > +}