df-scan.c (df_get_call_refs): Mark global registers as both a DF_REF_REG_USE and a non-clobber DF_REF_REG_DEF.

gcc/:

2007-10-22  Seongbae Park <seongbae.park@gmail.com>
	David S. Miller  <davem@davemloft.net>

	* df-scan.c (df_get_call_refs): Mark global registers as both a
	DF_REF_REG_USE and a non-clobber DF_REF_REG_DEF.


gcc/testsuite/:

2007-10-22  David S. Miller  <davem@davemloft.net>

	* gcc.dg/globalreg-1.c: New test.

From-SVN: r129572
This commit is contained in:
David S. Miller 2007-10-22 21:33:26 -07:00
parent 7de5c6a447
commit f168817602
4 changed files with 72 additions and 4 deletions

View File

@ -1,3 +1,9 @@
2007-10-22 Seongbae Park <seongbae.park@gmail.com>
David S. Miller <davem@davemloft.net>
* df-scan.c (df_get_call_refs): Mark global registers as both a
DF_REF_REG_USE and a non-clobber DF_REF_REG_DEF.
2007-10-22 Dorit Nuzman <dorit@il.ibm.com> 2007-10-22 Dorit Nuzman <dorit@il.ibm.com>
PR tree-optimization/33834 PR tree-optimization/33834

View File

@ -3109,18 +3109,22 @@ df_get_call_refs (struct df_collection_rec * collection_rec,
so they are recorded as used. */ so they are recorded as used. */
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (global_regs[i]) if (global_regs[i])
df_ref_record (collection_rec, regno_reg_rtx[i], {
NULL, bb, insn, DF_REF_REG_USE, flags); df_ref_record (collection_rec, regno_reg_rtx[i],
NULL, bb, insn, DF_REF_REG_USE, flags);
df_ref_record (collection_rec, regno_reg_rtx[i],
NULL, bb, insn, DF_REF_REG_DEF, flags);
}
is_sibling_call = SIBLING_CALL_P (insn); is_sibling_call = SIBLING_CALL_P (insn);
EXECUTE_IF_SET_IN_BITMAP (df_invalidated_by_call, 0, ui, bi) EXECUTE_IF_SET_IN_BITMAP (df_invalidated_by_call, 0, ui, bi)
{ {
if ((!bitmap_bit_p (defs_generated, ui)) if (!global_regs[ui]
&& (!bitmap_bit_p (defs_generated, ui))
&& (!is_sibling_call && (!is_sibling_call
|| !bitmap_bit_p (df->exit_block_uses, ui) || !bitmap_bit_p (df->exit_block_uses, ui)
|| refers_to_regno_p (ui, ui+1, || refers_to_regno_p (ui, ui+1,
current_function_return_rtx, NULL))) current_function_return_rtx, NULL)))
df_ref_record (collection_rec, regno_reg_rtx[ui], df_ref_record (collection_rec, regno_reg_rtx[ui],
NULL, bb, insn, DF_REF_REG_DEF, DF_REF_MAY_CLOBBER | flags); NULL, bb, insn, DF_REF_REG_DEF, DF_REF_MAY_CLOBBER | flags);
} }

View File

@ -1,3 +1,7 @@
2007-10-22 David S. Miller <davem@davemloft.net>
* gcc.dg/globalreg-1.c: New test.
2007-10-22 Martin Michlmayr <tbm@cyrius.com> 2007-10-22 Martin Michlmayr <tbm@cyrius.com>
Dorit Nuzman <dorit@il.ibm.com> Dorit Nuzman <dorit@il.ibm.com>

View File

@ -0,0 +1,54 @@
/* { dg-do run { target sparc*-*-* } } */
/* { dg-options "-std=gnu99 -Os" } */
/* This is a massively distilled test case based upon
mm/memory.c:unmap_vmas() in the Linux kernel when compiled
on sparc64 for SMP which uses a global register as the
base of the per-cpu variable area.
Because of a bug in global register handling in the dataflow
code, the loop-invariant pass would move 'expression(regval)'
outside of the loop. */
extern void exit(int);
extern void abort(void);
register unsigned long regval __asm__("g6");
extern void cond_resched(void);
unsigned int var;
static unsigned long expression(unsigned long v)
{
unsigned long ret;
__asm__("" : "=r" (ret) : "0" (0));
return ret + v;
}
void func(unsigned long *pp)
{
int i;
for (i = 0; i < 56; i++) {
cond_resched();
*pp = expression(regval);
}
}
void __attribute__((noinline)) cond_resched(void)
{
regval++;
}
int main(void)
{
unsigned long val;
regval = 100;
func(&val);
if (val != 156)
abort();
exit(0);
}