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> 2009-09-06 Richard Guenther <rguenther@suse.de>
PR middle-end/41144 PR middle-end/41144
......
...@@ -71,25 +71,26 @@ along with GCC; see the file COPYING3. If not see ...@@ -71,25 +71,26 @@ along with GCC; see the file COPYING3. If not see
#define STACK_GROWS_DOWNWARD 0 #define STACK_GROWS_DOWNWARD 0
#endif #endif
/* This structure records stack memory references between stack adjusting /* This structure records two kinds of stack references between stack
instructions. */ 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; HOST_WIDE_INT sp_offset;
rtx insn, *mem; rtx insn, *ref;
struct csa_memlist *next; struct csa_reflist *next;
}; };
static int stack_memref_p (rtx); static int stack_memref_p (rtx);
static rtx single_set_for_csa (rtx); static rtx single_set_for_csa (rtx);
static void free_csa_memlist (struct csa_memlist *); static void free_csa_reflist (struct csa_reflist *);
static struct csa_memlist *record_one_stack_memref (rtx, rtx *, static struct csa_reflist *record_one_stack_ref (rtx, rtx *,
struct csa_memlist *); struct csa_reflist *);
static int try_apply_stack_adjustment (rtx, struct csa_memlist *, static int try_apply_stack_adjustment (rtx, struct csa_reflist *,
HOST_WIDE_INT, HOST_WIDE_INT); HOST_WIDE_INT, HOST_WIDE_INT);
static void combine_stack_adjustments_for_block (basic_block); 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. */ /* Main entry point for stack adjustment combination. */
...@@ -157,65 +158,75 @@ single_set_for_csa (rtx insn) ...@@ -157,65 +158,75 @@ single_set_for_csa (rtx insn)
return XVECEXP (tmp, 0, 0); return XVECEXP (tmp, 0, 0);
} }
/* Free the list of csa_memlist nodes. */ /* Free the list of csa_reflist nodes. */
static void static void
free_csa_memlist (struct csa_memlist *memlist) free_csa_reflist (struct csa_reflist *reflist)
{ {
struct csa_memlist *next; struct csa_reflist *next;
for (; memlist ; memlist = next) for (; reflist ; reflist = next)
{ {
next = memlist->next; next = reflist->next;
free (memlist); free (reflist);
} }
} }
/* Create a new csa_memlist node from the given memory reference. /* Create a new csa_reflist node from the given stack reference.
It is already known that the memory is stack_memref_p. */ 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 * static struct csa_reflist *
record_one_stack_memref (rtx insn, rtx *mem, struct csa_memlist *next_memlist) 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; ml->sp_offset = 0;
else else
ml->sp_offset = INTVAL (XEXP (XEXP (*mem, 0), 1)); ml->sp_offset = INTVAL (XEXP (XEXP (*ref, 0), 1));
ml->insn = insn; ml->insn = insn;
ml->mem = mem; ml->ref = ref;
ml->next = next_memlist; ml->next = next_reflist;
return ml; return ml;
} }
/* Attempt to apply ADJUST to the stack adjusting insn INSN, as well /* 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 static int
try_apply_stack_adjustment (rtx insn, struct csa_memlist *memlist, HOST_WIDE_INT new_adjust, try_apply_stack_adjustment (rtx insn, struct csa_reflist *reflist,
HOST_WIDE_INT delta) HOST_WIDE_INT new_adjust, HOST_WIDE_INT delta)
{ {
struct csa_memlist *ml; struct csa_reflist *ml;
rtx set; rtx set;
set = single_set_for_csa (insn); set = single_set_for_csa (insn);
validate_change (insn, &XEXP (SET_SRC (set), 1), GEN_INT (new_adjust), 1); validate_change (insn, &XEXP (SET_SRC (set), 1), GEN_INT (new_adjust), 1);
for (ml = memlist; ml ; ml = ml->next) for (ml = reflist; ml ; ml = ml->next)
validate_change {
(ml->insn, ml->mem, rtx new_addr = plus_constant (stack_pointer_rtx, ml->sp_offset - delta);
replace_equiv_address_nv (*ml->mem, rtx new_val;
plus_constant (stack_pointer_rtx,
ml->sp_offset - delta)), 1); 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 ()) if (apply_change_group ())
{ {
/* Succeeded. Update our knowledge of the memory references. */ /* Succeeded. Update our knowledge of the stack references. */
for (ml = memlist; ml ; ml = ml->next) for (ml = reflist; ml ; ml = ml->next)
ml->sp_offset -= delta; ml->sp_offset -= delta;
return 1; return 1;
...@@ -224,20 +235,20 @@ try_apply_stack_adjustment (rtx insn, struct csa_memlist *memlist, HOST_WIDE_INT ...@@ -224,20 +235,20 @@ try_apply_stack_adjustment (rtx insn, struct csa_memlist *memlist, HOST_WIDE_INT
return 0; return 0;
} }
/* Called via for_each_rtx and used to record all stack memory references in /* Called via for_each_rtx and used to record all stack memory and other
the insn and discard all other stack pointer references. */ references in the insn and discard all other stack pointer references. */
struct record_stack_memrefs_data struct record_stack_refs_data
{ {
rtx insn; rtx insn;
struct csa_memlist *memlist; struct csa_reflist *reflist;
}; };
static int static int
record_stack_memrefs (rtx *xp, void *data) record_stack_refs (rtx *xp, void *data)
{ {
rtx x = *xp; rtx x = *xp;
struct record_stack_memrefs_data *d = struct record_stack_refs_data *d =
(struct record_stack_memrefs_data *) data; (struct record_stack_refs_data *) data;
if (!x) if (!x)
return 0; return 0;
switch (GET_CODE (x)) switch (GET_CODE (x))
...@@ -249,10 +260,11 @@ record_stack_memrefs (rtx *xp, void *data) ...@@ -249,10 +260,11 @@ record_stack_memrefs (rtx *xp, void *data)
stack pointer, so this check is necessary. */ stack pointer, so this check is necessary. */
if (stack_memref_p (x)) 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;
} }
return 1; /* Try harder for DEBUG_INSNs, handle e.g. (mem (mem (sp + 16) + 4). */
return !DEBUG_INSN_P (d->insn);
case REG: case REG:
/* ??? We want be able to handle non-memory stack pointer /* ??? We want be able to handle non-memory stack pointer
references later. For now just discard all insns referring to references later. For now just discard all insns referring to
...@@ -262,9 +274,17 @@ record_stack_memrefs (rtx *xp, void *data) ...@@ -262,9 +274,17 @@ record_stack_memrefs (rtx *xp, void *data)
We can't just compare with STACK_POINTER_RTX because the We can't just compare with STACK_POINTER_RTX because the
reference to the stack pointer might be in some other mode. reference to the stack pointer might be in some other mode.
In particular, an explicit clobber in an asm statement will 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 (REGNO (x) == STACK_POINTER_REGNUM)
return 1; {
if (!DEBUG_INSN_P (d->insn))
return 1;
d->reflist = record_one_stack_ref (d->insn, xp, d->reflist);
return -1;
}
break; break;
default: default:
break; break;
...@@ -343,9 +363,9 @@ combine_stack_adjustments_for_block (basic_block bb) ...@@ -343,9 +363,9 @@ combine_stack_adjustments_for_block (basic_block bb)
{ {
HOST_WIDE_INT last_sp_adjust = 0; HOST_WIDE_INT last_sp_adjust = 0;
rtx last_sp_set = NULL_RTX; rtx last_sp_set = NULL_RTX;
struct csa_memlist *memlist = NULL; struct csa_reflist *reflist = NULL;
rtx insn, next, set; rtx insn, next, set;
struct record_stack_memrefs_data data; struct record_stack_refs_data data;
bool end_of_block = false; bool end_of_block = false;
for (insn = BB_HEAD (bb); !end_of_block ; insn = next) for (insn = BB_HEAD (bb); !end_of_block ; insn = next)
...@@ -379,7 +399,7 @@ combine_stack_adjustments_for_block (basic_block bb) ...@@ -379,7 +399,7 @@ combine_stack_adjustments_for_block (basic_block bb)
continue; 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, adjustment is now too large for a constant addition,
we cannot merge the two stack adjustments. we cannot merge the two stack adjustments.
...@@ -403,7 +423,7 @@ combine_stack_adjustments_for_block (basic_block bb) ...@@ -403,7 +423,7 @@ combine_stack_adjustments_for_block (basic_block bb)
/* Combine an allocation into the first instruction. */ /* Combine an allocation into the first instruction. */
if (STACK_GROWS_DOWNWARD ? this_adjust <= 0 : this_adjust >= 0) 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, last_sp_adjust + this_adjust,
this_adjust)) this_adjust))
{ {
...@@ -422,7 +442,7 @@ combine_stack_adjustments_for_block (basic_block bb) ...@@ -422,7 +442,7 @@ combine_stack_adjustments_for_block (basic_block bb)
else if (STACK_GROWS_DOWNWARD else if (STACK_GROWS_DOWNWARD
? last_sp_adjust >= 0 : last_sp_adjust <= 0) ? 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 + this_adjust,
-last_sp_adjust)) -last_sp_adjust))
{ {
...@@ -430,8 +450,8 @@ combine_stack_adjustments_for_block (basic_block bb) ...@@ -430,8 +450,8 @@ combine_stack_adjustments_for_block (basic_block bb)
delete_insn (last_sp_set); delete_insn (last_sp_set);
last_sp_set = insn; last_sp_set = insn;
last_sp_adjust += this_adjust; last_sp_adjust += this_adjust;
free_csa_memlist (memlist); free_csa_reflist (reflist);
memlist = NULL; reflist = NULL;
continue; continue;
} }
} }
...@@ -441,8 +461,8 @@ combine_stack_adjustments_for_block (basic_block bb) ...@@ -441,8 +461,8 @@ combine_stack_adjustments_for_block (basic_block bb)
delete the old deallocation insn. */ delete the old deallocation insn. */
if (last_sp_set && last_sp_adjust == 0) if (last_sp_set && last_sp_adjust == 0)
delete_insn (last_sp_set); delete_insn (last_sp_set);
free_csa_memlist (memlist); free_csa_reflist (reflist);
memlist = NULL; reflist = NULL;
last_sp_set = insn; last_sp_set = insn;
last_sp_adjust = this_adjust; last_sp_adjust = this_adjust;
continue; continue;
...@@ -451,7 +471,7 @@ combine_stack_adjustments_for_block (basic_block bb) ...@@ -451,7 +471,7 @@ combine_stack_adjustments_for_block (basic_block bb)
/* Find a predecrement of exactly the previous adjustment and /* Find a predecrement of exactly the previous adjustment and
turn it into a direct store. Obviously we can't do this if turn it into a direct store. Obviously we can't do this if
there were any intervening uses of the stack pointer. */ there were any intervening uses of the stack pointer. */
if (memlist == NULL if (reflist == NULL
&& MEM_P (dest) && MEM_P (dest)
&& ((GET_CODE (XEXP (dest, 0)) == PRE_DEC && ((GET_CODE (XEXP (dest, 0)) == PRE_DEC
&& (last_sp_adjust && (last_sp_adjust
...@@ -472,8 +492,8 @@ combine_stack_adjustments_for_block (basic_block bb) ...@@ -472,8 +492,8 @@ combine_stack_adjustments_for_block (basic_block bb)
0)) 0))
{ {
delete_insn (last_sp_set); delete_insn (last_sp_set);
free_csa_memlist (memlist); free_csa_reflist (reflist);
memlist = NULL; reflist = NULL;
last_sp_set = NULL_RTX; last_sp_set = NULL_RTX;
last_sp_adjust = 0; last_sp_adjust = 0;
continue; continue;
...@@ -481,14 +501,14 @@ combine_stack_adjustments_for_block (basic_block bb) ...@@ -481,14 +501,14 @@ combine_stack_adjustments_for_block (basic_block bb)
} }
data.insn = insn; data.insn = insn;
data.memlist = memlist; data.reflist = reflist;
if (!CALL_P (insn) && last_sp_set 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; continue;
} }
memlist = data.memlist; reflist = data.reflist;
/* Otherwise, we were not able to process the instruction. /* Otherwise, we were not able to process the instruction.
Do not continue collecting data across such a one. */ Do not continue collecting data across such a one. */
...@@ -498,8 +518,8 @@ combine_stack_adjustments_for_block (basic_block bb) ...@@ -498,8 +518,8 @@ combine_stack_adjustments_for_block (basic_block bb)
{ {
if (last_sp_set && last_sp_adjust == 0) if (last_sp_set && last_sp_adjust == 0)
delete_insn (last_sp_set); delete_insn (last_sp_set);
free_csa_memlist (memlist); free_csa_reflist (reflist);
memlist = NULL; reflist = NULL;
last_sp_set = NULL_RTX; last_sp_set = NULL_RTX;
last_sp_adjust = 0; last_sp_adjust = 0;
} }
...@@ -508,8 +528,8 @@ combine_stack_adjustments_for_block (basic_block bb) ...@@ -508,8 +528,8 @@ combine_stack_adjustments_for_block (basic_block bb)
if (last_sp_set && last_sp_adjust == 0) if (last_sp_set && last_sp_adjust == 0)
delete_insn (last_sp_set); delete_insn (last_sp_set);
if (memlist) if (reflist)
free_csa_memlist (memlist); 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> 2009-09-06 Richard Guenther <rguenther@suse.de>
PR middle-end/41144 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