Commit 90588a10 by Jakub Jelinek Committed by Jakub Jelinek

re PR bootstrap/41241 (bootstrap comparison failure)

	PR bootstrap/41241
	* combine-stack-adj.c (struct csa_memlist): Rename to...
	(struct csa_reflist): ... this.  Rename mem field to ref.
	(free_csa_memlist): Rename to...
	(free_csa_reflist): ... this.
	(record_one_stack_memref): Rename to...
	(record_one_stack_ref): ... this.  Handle also REG_P.
	(try_apply_stack_adjustment): Handle also REG_P.
	(struct record_stack_memrefs_data): Rename to...
	(struct record_stack_refs_data): ... this.  Rename memlist field to
	reflist.
	(record_stack_memrefs): Rename to...
	(record_stack_refs): ... this.  For DEBUG_INSNs keep traversing
	subexpressions instead of failing when a MEM contains SP references.
	For SP itself in DEBUG_INSNs queue it also onto reflist chain.
	(combine_stack_adjustments_for_block): Adjust for mem to ref renaming.

	* gcc.dg/pr41241.c: New test.

From-SVN: r151462
parent 3797a0ff
2009-09-06 Jakub Jelinek <jakub@redhat.com>
PR bootstrap/41241
* combine-stack-adj.c (struct csa_memlist): Rename to...
(struct csa_reflist): ... this. Rename mem field to ref.
(free_csa_memlist): Rename to...
(free_csa_reflist): ... this.
(record_one_stack_memref): Rename to...
(record_one_stack_ref): ... this. Handle also REG_P.
(try_apply_stack_adjustment): Handle also REG_P.
(struct record_stack_memrefs_data): Rename to...
(struct record_stack_refs_data): ... this. Rename memlist field to
reflist.
(record_stack_memrefs): Rename to...
(record_stack_refs): ... this. For DEBUG_INSNs keep traversing
subexpressions instead of failing when a MEM contains SP references.
For SP itself in DEBUG_INSNs queue it also onto reflist chain.
(combine_stack_adjustments_for_block): Adjust for mem to ref renaming.
2009-09-06 Richard Guenther <rguenther@suse.de>
PR middle-end/41144
......
......@@ -71,25 +71,26 @@ along with GCC; see the file COPYING3. If not see
#define STACK_GROWS_DOWNWARD 0
#endif
/* This structure records stack memory references between stack adjusting
instructions. */
/* This structure records two kinds of stack references between stack
adjusting instructions: stack references in memory addresses for
regular insns and all stack references for debug insns. */
struct csa_memlist
struct csa_reflist
{
HOST_WIDE_INT sp_offset;
rtx insn, *mem;
struct csa_memlist *next;
rtx insn, *ref;
struct csa_reflist *next;
};
static int stack_memref_p (rtx);
static rtx single_set_for_csa (rtx);
static void free_csa_memlist (struct csa_memlist *);
static struct csa_memlist *record_one_stack_memref (rtx, rtx *,
struct csa_memlist *);
static int try_apply_stack_adjustment (rtx, struct csa_memlist *,
static void free_csa_reflist (struct csa_reflist *);
static struct csa_reflist *record_one_stack_ref (rtx, rtx *,
struct csa_reflist *);
static int try_apply_stack_adjustment (rtx, struct csa_reflist *,
HOST_WIDE_INT, HOST_WIDE_INT);
static void combine_stack_adjustments_for_block (basic_block);
static int record_stack_memrefs (rtx *, void *);
static int record_stack_refs (rtx *, void *);
/* Main entry point for stack adjustment combination. */
......@@ -157,65 +158,75 @@ single_set_for_csa (rtx insn)
return XVECEXP (tmp, 0, 0);
}
/* Free the list of csa_memlist nodes. */
/* Free the list of csa_reflist nodes. */
static void
free_csa_memlist (struct csa_memlist *memlist)
free_csa_reflist (struct csa_reflist *reflist)
{
struct csa_memlist *next;
for (; memlist ; memlist = next)
struct csa_reflist *next;
for (; reflist ; reflist = next)
{
next = memlist->next;
free (memlist);
next = reflist->next;
free (reflist);
}
}
/* Create a new csa_memlist node from the given memory reference.
It is already known that the memory is stack_memref_p. */
/* Create a new csa_reflist node from the given stack reference.
It is already known that the reference is either a MEM satisfying the
predicate stack_memref_p or a REG representing the stack pointer. */
static struct csa_memlist *
record_one_stack_memref (rtx insn, rtx *mem, struct csa_memlist *next_memlist)
static struct csa_reflist *
record_one_stack_ref (rtx insn, rtx *ref, struct csa_reflist *next_reflist)
{
struct csa_memlist *ml;
struct csa_reflist *ml;
ml = XNEW (struct csa_memlist);
ml = XNEW (struct csa_reflist);
if (XEXP (*mem, 0) == stack_pointer_rtx)
if (REG_P (*ref) || XEXP (*ref, 0) == stack_pointer_rtx)
ml->sp_offset = 0;
else
ml->sp_offset = INTVAL (XEXP (XEXP (*mem, 0), 1));
ml->sp_offset = INTVAL (XEXP (XEXP (*ref, 0), 1));
ml->insn = insn;
ml->mem = mem;
ml->next = next_memlist;
ml->ref = ref;
ml->next = next_reflist;
return ml;
}
/* Attempt to apply ADJUST to the stack adjusting insn INSN, as well
as each of the memories in MEMLIST. Return true on success. */
as each of the memories and stack references in REFLIST. Return true
on success. */
static int
try_apply_stack_adjustment (rtx insn, struct csa_memlist *memlist, HOST_WIDE_INT new_adjust,
HOST_WIDE_INT delta)
try_apply_stack_adjustment (rtx insn, struct csa_reflist *reflist,
HOST_WIDE_INT new_adjust, HOST_WIDE_INT delta)
{
struct csa_memlist *ml;
struct csa_reflist *ml;
rtx set;
set = single_set_for_csa (insn);
validate_change (insn, &XEXP (SET_SRC (set), 1), GEN_INT (new_adjust), 1);
for (ml = memlist; ml ; ml = ml->next)
validate_change
(ml->insn, ml->mem,
replace_equiv_address_nv (*ml->mem,
plus_constant (stack_pointer_rtx,
ml->sp_offset - delta)), 1);
for (ml = reflist; ml ; ml = ml->next)
{
rtx new_addr = plus_constant (stack_pointer_rtx, ml->sp_offset - delta);
rtx new_val;
if (MEM_P (*ml->ref))
new_val = replace_equiv_address_nv (*ml->ref, new_addr);
else if (GET_MODE (*ml->ref) == GET_MODE (stack_pointer_rtx))
new_val = new_addr;
else
new_val = lowpart_subreg (GET_MODE (*ml->ref), new_addr,
GET_MODE (new_addr));
validate_change (ml->insn, ml->ref, new_val, 1);
}
if (apply_change_group ())
{
/* Succeeded. Update our knowledge of the memory references. */
for (ml = memlist; ml ; ml = ml->next)
/* Succeeded. Update our knowledge of the stack references. */
for (ml = reflist; ml ; ml = ml->next)
ml->sp_offset -= delta;
return 1;
......@@ -224,20 +235,20 @@ try_apply_stack_adjustment (rtx insn, struct csa_memlist *memlist, HOST_WIDE_INT
return 0;
}
/* Called via for_each_rtx and used to record all stack memory references in
the insn and discard all other stack pointer references. */
struct record_stack_memrefs_data
/* Called via for_each_rtx and used to record all stack memory and other
references in the insn and discard all other stack pointer references. */
struct record_stack_refs_data
{
rtx insn;
struct csa_memlist *memlist;
struct csa_reflist *reflist;
};
static int
record_stack_memrefs (rtx *xp, void *data)
record_stack_refs (rtx *xp, void *data)
{
rtx x = *xp;
struct record_stack_memrefs_data *d =
(struct record_stack_memrefs_data *) data;
struct record_stack_refs_data *d =
(struct record_stack_refs_data *) data;
if (!x)
return 0;
switch (GET_CODE (x))
......@@ -249,10 +260,11 @@ record_stack_memrefs (rtx *xp, void *data)
stack pointer, so this check is necessary. */
if (stack_memref_p (x))
{
d->memlist = record_one_stack_memref (d->insn, xp, d->memlist);
d->reflist = record_one_stack_ref (d->insn, xp, d->reflist);
return -1;
}
return 1;
/* Try harder for DEBUG_INSNs, handle e.g. (mem (mem (sp + 16) + 4). */
return !DEBUG_INSN_P (d->insn);
case REG:
/* ??? We want be able to handle non-memory stack pointer
references later. For now just discard all insns referring to
......@@ -262,9 +274,17 @@ record_stack_memrefs (rtx *xp, void *data)
We can't just compare with STACK_POINTER_RTX because the
reference to the stack pointer might be in some other mode.
In particular, an explicit clobber in an asm statement will
result in a QImode clobber. */
result in a QImode clobber.
In DEBUG_INSNs, we want to replace all occurrences, otherwise
they will cause -fcompare-debug failures. */
if (REGNO (x) == STACK_POINTER_REGNUM)
{
if (!DEBUG_INSN_P (d->insn))
return 1;
d->reflist = record_one_stack_ref (d->insn, xp, d->reflist);
return -1;
}
break;
default:
break;
......@@ -343,9 +363,9 @@ combine_stack_adjustments_for_block (basic_block bb)
{
HOST_WIDE_INT last_sp_adjust = 0;
rtx last_sp_set = NULL_RTX;
struct csa_memlist *memlist = NULL;
struct csa_reflist *reflist = NULL;
rtx insn, next, set;
struct record_stack_memrefs_data data;
struct record_stack_refs_data data;
bool end_of_block = false;
for (insn = BB_HEAD (bb); !end_of_block ; insn = next)
......@@ -379,7 +399,7 @@ combine_stack_adjustments_for_block (basic_block bb)
continue;
}
/* If not all recorded memrefs can be adjusted, or the
/* If not all recorded refs can be adjusted, or the
adjustment is now too large for a constant addition,
we cannot merge the two stack adjustments.
......@@ -403,7 +423,7 @@ combine_stack_adjustments_for_block (basic_block bb)
/* Combine an allocation into the first instruction. */
if (STACK_GROWS_DOWNWARD ? this_adjust <= 0 : this_adjust >= 0)
{
if (try_apply_stack_adjustment (last_sp_set, memlist,
if (try_apply_stack_adjustment (last_sp_set, reflist,
last_sp_adjust + this_adjust,
this_adjust))
{
......@@ -422,7 +442,7 @@ combine_stack_adjustments_for_block (basic_block bb)
else if (STACK_GROWS_DOWNWARD
? last_sp_adjust >= 0 : last_sp_adjust <= 0)
{
if (try_apply_stack_adjustment (insn, memlist,
if (try_apply_stack_adjustment (insn, reflist,
last_sp_adjust + this_adjust,
-last_sp_adjust))
{
......@@ -430,8 +450,8 @@ combine_stack_adjustments_for_block (basic_block bb)
delete_insn (last_sp_set);
last_sp_set = insn;
last_sp_adjust += this_adjust;
free_csa_memlist (memlist);
memlist = NULL;
free_csa_reflist (reflist);
reflist = NULL;
continue;
}
}
......@@ -441,8 +461,8 @@ combine_stack_adjustments_for_block (basic_block bb)
delete the old deallocation insn. */
if (last_sp_set && last_sp_adjust == 0)
delete_insn (last_sp_set);
free_csa_memlist (memlist);
memlist = NULL;
free_csa_reflist (reflist);
reflist = NULL;
last_sp_set = insn;
last_sp_adjust = this_adjust;
continue;
......@@ -451,7 +471,7 @@ combine_stack_adjustments_for_block (basic_block bb)
/* Find a predecrement of exactly the previous adjustment and
turn it into a direct store. Obviously we can't do this if
there were any intervening uses of the stack pointer. */
if (memlist == NULL
if (reflist == NULL
&& MEM_P (dest)
&& ((GET_CODE (XEXP (dest, 0)) == PRE_DEC
&& (last_sp_adjust
......@@ -472,8 +492,8 @@ combine_stack_adjustments_for_block (basic_block bb)
0))
{
delete_insn (last_sp_set);
free_csa_memlist (memlist);
memlist = NULL;
free_csa_reflist (reflist);
reflist = NULL;
last_sp_set = NULL_RTX;
last_sp_adjust = 0;
continue;
......@@ -481,14 +501,14 @@ combine_stack_adjustments_for_block (basic_block bb)
}
data.insn = insn;
data.memlist = memlist;
data.reflist = reflist;
if (!CALL_P (insn) && last_sp_set
&& !for_each_rtx (&PATTERN (insn), record_stack_memrefs, &data))
&& !for_each_rtx (&PATTERN (insn), record_stack_refs, &data))
{
memlist = data.memlist;
reflist = data.reflist;
continue;
}
memlist = data.memlist;
reflist = data.reflist;
/* Otherwise, we were not able to process the instruction.
Do not continue collecting data across such a one. */
......@@ -498,8 +518,8 @@ combine_stack_adjustments_for_block (basic_block bb)
{
if (last_sp_set && last_sp_adjust == 0)
delete_insn (last_sp_set);
free_csa_memlist (memlist);
memlist = NULL;
free_csa_reflist (reflist);
reflist = NULL;
last_sp_set = NULL_RTX;
last_sp_adjust = 0;
}
......@@ -508,8 +528,8 @@ combine_stack_adjustments_for_block (basic_block bb)
if (last_sp_set && last_sp_adjust == 0)
delete_insn (last_sp_set);
if (memlist)
free_csa_memlist (memlist);
if (reflist)
free_csa_reflist (reflist);
}
......
2009-09-06 Jakub Jelinek <jakub@redhat.com>
PR bootstrap/41241
* gcc.dg/pr41241.c: New test.
2009-09-06 Richard Guenther <rguenther@suse.de>
PR middle-end/41144
......
/* PR bootstrap/41241 */
/* { dg-do compile } */
/* { dg-options "-O2 -fcompare-debug -g" } */
/* { dg-options "-O2 -fcompare-debug -g -march=i586 -mtune=i586 -fomit-frame-pointer" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */
typedef struct { int t1; int t2; int t3; } *T;
typedef struct { int s; } S;
int fn1 (int);
int fn2 (int, int, int);
int fn3 (void);
static S
bar ()
{
S s = { 0 };
return s;
}
void
foo (T x)
{
int a, b, c, d, e;
T f, g;
S h;
a = x->t2;
fn1 (x->t1);
h = bar (b);
c = fn1 (e);
d = fn3 ();
f->t3 &= g->t3 |= fn2 (0, b, x->t1);
fn2 (0, c, d);
fn2 (0, e, 0);
}
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