Commit 4456525c by Richard Earnshaw Committed by Richard Earnshaw

[arm] PR target/90405 fix regression for thumb1 with -mtpcs-leaf-frame

-mtpcs-leaf-frame causes an APCS-style backtrace frame to be created
on the stack.  This should probably be deprecated, but it did reveal
an issue with the patch I committed previously to improve the code
generation when pushing high registers, in that
thumb_find_work_register had a different idea as to which registers
were available as scratch registers.

The new code actually does a better job of finding a viable work
register and doesn't rely so much on assumptions about the ABI, so it
seems better to adapt thumb_find_work_register to the new approach.
This way we can eliminate some rather crufty code.

gcc:
	PR target/90405
	* config/arm/arm.c (callee_saved_reg_p): Move before
	thumb_find_work_register.
	(thumb1_prologue_unused_call_clobbered_lo_regs): Move before
	thumb_find_work_register.  Only call df_get_live_out once.
	(thumb1_epilogue_unused_call_clobbered_lo_regs): Likewise.
	(thumb_find_work_register): Use
	thumb1_prologue_unused_call_clobbered_lo_regs instead of ad hoc
	algorithms to locate a spare call clobbered reg.

gcc/testsuite:
	PR target/90405
	* gcc.target/arm/pr90405.c: New test.

From-SVN: r271036
parent fd4485aa
2019-05-09 Richard Earnshaw <rearnsha@arm.com>
PR target/90405
* config/arm/arm.c (callee_saved_reg_p): Move before
thumb_find_work_register.
(thumb1_prologue_unused_call_clobbered_lo_regs): Move before
thumb_find_work_register. Only call df_get_live_out once.
(thumb1_epilogue_unused_call_clobbered_lo_regs): Likewise.
(thumb_find_work_register): Use
thumb1_prologue_unused_call_clobbered_lo_regs instead of ad hoc
algorithms to locate a spare call clobbered reg.
2019-05-09 Martin Liska <mliska@suse.cz> 2019-05-09 Martin Liska <mliska@suse.cz>
* gimple-pretty-print.c (dump_binary_rhs): Dump MIN_EXPR * gimple-pretty-print.c (dump_binary_rhs): Dump MIN_EXPR
......
...@@ -7638,6 +7638,41 @@ legitimize_pic_address (rtx orig, machine_mode mode, rtx reg, rtx pic_reg, ...@@ -7638,6 +7638,41 @@ legitimize_pic_address (rtx orig, machine_mode mode, rtx reg, rtx pic_reg,
} }
/* Whether a register is callee saved or not. This is necessary because high
registers are marked as caller saved when optimizing for size on Thumb-1
targets despite being callee saved in order to avoid using them. */
#define callee_saved_reg_p(reg) \
(!call_used_regs[reg] \
|| (TARGET_THUMB1 && optimize_size \
&& reg >= FIRST_HI_REGNUM && reg <= LAST_HI_REGNUM))
/* Return a mask for the call-clobbered low registers that are unused
at the end of the prologue. */
static unsigned long
thumb1_prologue_unused_call_clobbered_lo_regs (void)
{
unsigned long mask = 0;
bitmap prologue_live_out = df_get_live_out (ENTRY_BLOCK_PTR_FOR_FN (cfun));
for (int reg = FIRST_LO_REGNUM; reg <= LAST_LO_REGNUM; reg++)
if (!callee_saved_reg_p (reg) && !REGNO_REG_SET_P (prologue_live_out, reg))
mask |= 1 << (reg - FIRST_LO_REGNUM);
return mask;
}
/* Similarly for the start of the epilogue. */
static unsigned long
thumb1_epilogue_unused_call_clobbered_lo_regs (void)
{
unsigned long mask = 0;
bitmap epilogue_live_in = df_get_live_in (EXIT_BLOCK_PTR_FOR_FN (cfun));
for (int reg = FIRST_LO_REGNUM; reg <= LAST_LO_REGNUM; reg++)
if (!callee_saved_reg_p (reg) && !REGNO_REG_SET_P (epilogue_live_in, reg))
mask |= 1 << (reg - FIRST_LO_REGNUM);
return mask;
}
/* Find a spare register to use during the prolog of a function. */ /* Find a spare register to use during the prolog of a function. */
static int static int
...@@ -7645,45 +7680,16 @@ thumb_find_work_register (unsigned long pushed_regs_mask) ...@@ -7645,45 +7680,16 @@ thumb_find_work_register (unsigned long pushed_regs_mask)
{ {
int reg; int reg;
unsigned long unused_regs
= thumb1_prologue_unused_call_clobbered_lo_regs ();
/* Check the argument registers first as these are call-used. The /* Check the argument registers first as these are call-used. The
register allocation order means that sometimes r3 might be used register allocation order means that sometimes r3 might be used
but earlier argument registers might not, so check them all. */ but earlier argument registers might not, so check them all. */
for (reg = LAST_ARG_REGNUM; reg >= 0; reg --) for (reg = LAST_LO_REGNUM; reg >= FIRST_LO_REGNUM; reg--)
if (!df_regs_ever_live_p (reg)) if (unused_regs & (1 << (reg - FIRST_LO_REGNUM)))
return reg; return reg;
/* Before going on to check the call-saved registers we can try a couple
more ways of deducing that r3 is available. The first is when we are
pushing anonymous arguments onto the stack and we have less than 4
registers worth of fixed arguments(*). In this case r3 will be part of
the variable argument list and so we can be sure that it will be
pushed right at the start of the function. Hence it will be available
for the rest of the prologue.
(*): ie crtl->args.pretend_args_size is greater than 0. */
if (cfun->machine->uses_anonymous_args
&& crtl->args.pretend_args_size > 0)
return LAST_ARG_REGNUM;
/* The other case is when we have fixed arguments but less than 4 registers
worth. In this case r3 might be used in the body of the function, but
it is not being used to convey an argument into the function. In theory
we could just check crtl->args.size to see how many bytes are
being passed in argument registers, but it seems that it is unreliable.
Sometimes it will have the value 0 when in fact arguments are being
passed. (See testcase execute/20021111-1.c for an example). So we also
check the args_info.nregs field as well. The problem with this field is
that it makes no allowances for arguments that are passed to the
function but which are not used. Hence we could miss an opportunity
when a function has an unused argument in r3. But it is better to be
safe than to be sorry. */
if (! cfun->machine->uses_anonymous_args
&& crtl->args.size >= 0
&& crtl->args.size <= (LAST_ARG_REGNUM * UNITS_PER_WORD)
&& (TARGET_AAPCS_BASED
? crtl->args.info.aapcs_ncrn < 4
: crtl->args.info.nregs < 4))
return LAST_ARG_REGNUM;
/* Otherwise look for a call-saved register that is going to be pushed. */ /* Otherwise look for a call-saved register that is going to be pushed. */
for (reg = LAST_LO_REGNUM; reg > LAST_ARG_REGNUM; reg --) for (reg = LAST_LO_REGNUM; reg > LAST_ARG_REGNUM; reg --)
if (pushed_regs_mask & (1 << reg)) if (pushed_regs_mask & (1 << reg))
...@@ -19441,13 +19447,6 @@ output_ascii_pseudo_op (FILE *stream, const unsigned char *p, int len) ...@@ -19441,13 +19447,6 @@ output_ascii_pseudo_op (FILE *stream, const unsigned char *p, int len)
fputs ("\"\n", stream); fputs ("\"\n", stream);
} }
/* Whether a register is callee saved or not. This is necessary because high
registers are marked as caller saved when optimizing for size on Thumb-1
targets despite being callee saved in order to avoid using them. */
#define callee_saved_reg_p(reg) \
(!call_used_regs[reg] \
|| (TARGET_THUMB1 && optimize_size \
&& reg >= FIRST_HI_REGNUM && reg <= LAST_HI_REGNUM))
/* Compute the register save mask for registers 0 through 12 /* Compute the register save mask for registers 0 through 12
inclusive. This code is used by arm_compute_save_core_reg_mask (). */ inclusive. This code is used by arm_compute_save_core_reg_mask (). */
...@@ -19670,35 +19669,6 @@ arm_compute_save_core_reg_mask (void) ...@@ -19670,35 +19669,6 @@ arm_compute_save_core_reg_mask (void)
return save_reg_mask; return save_reg_mask;
} }
/* Return a mask for the call-clobbered low registers that are unused
at the end of the prologue. */
static unsigned long
thumb1_prologue_unused_call_clobbered_lo_regs (void)
{
unsigned long mask = 0;
for (int reg = 0; reg <= LAST_LO_REGNUM; reg++)
if (!callee_saved_reg_p (reg)
&& !REGNO_REG_SET_P (df_get_live_out (ENTRY_BLOCK_PTR_FOR_FN (cfun)),
reg))
mask |= 1 << reg;
return mask;
}
/* Similarly for the start of the epilogue. */
static unsigned long
thumb1_epilogue_unused_call_clobbered_lo_regs (void)
{
unsigned long mask = 0;
for (int reg = 0; reg <= LAST_LO_REGNUM; reg++)
if (!callee_saved_reg_p (reg)
&& !REGNO_REG_SET_P (df_get_live_in (EXIT_BLOCK_PTR_FOR_FN (cfun)),
reg))
mask |= 1 << reg;
return mask;
}
/* Compute a bit mask of which core registers need to be /* Compute a bit mask of which core registers need to be
saved on the stack for the current function. */ saved on the stack for the current function. */
static unsigned long static unsigned long
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment