re PR middle-end/54921 (wrong code with -Os -fno-omit-frame-pointer -fsched2-use-superblocks -fstack-protector -ftree-slp-vectorize)

PR rtl-optimization/54921
	* cselib.h (fp_setter_insn): New prototype.
	* cselib.c (fp_setter_insn): New function.
	(cselib_process_insn): If frame_pointer_needed,
	call cselib_invalidate_rtx (stack_pointer_rtx) after
	processing a frame pointer setter.
	* var-tracking.c (fp_setter): Removed.
	(vt_initialize): Use fp_setter_insn instead of fp_setter.

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

From-SVN: r193647
This commit is contained in:
Jakub Jelinek 2012-11-20 09:34:43 +01:00 committed by Jakub Jelinek
parent 4ced1d6de8
commit 40155239d6
6 changed files with 80 additions and 36 deletions

View File

@ -1,3 +1,14 @@
2012-11-20 Jakub Jelinek <jakub@redhat.com>
PR rtl-optimization/54921
* cselib.h (fp_setter_insn): New prototype.
* cselib.c (fp_setter_insn): New function.
(cselib_process_insn): If frame_pointer_needed,
call cselib_invalidate_rtx (stack_pointer_rtx) after
processing a frame pointer setter.
* var-tracking.c (fp_setter): Removed.
(vt_initialize): Use fp_setter_insn instead of fp_setter.
2012-11-19 Michael Meissner <meissner@linux.vnet.ibm.com>
* config/rs6000/rs6000.md (movdf_hardfloat32): Reorder move

View File

@ -2593,6 +2593,28 @@ cselib_record_sets (rtx insn)
}
}
/* Return true if INSN in the prologue initializes hard_frame_pointer_rtx. */
bool
fp_setter_insn (rtx insn)
{
rtx expr, pat = NULL_RTX;
if (!RTX_FRAME_RELATED_P (insn))
return false;
expr = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX);
if (expr)
pat = XEXP (expr, 0);
if (!modified_in_p (hard_frame_pointer_rtx, pat ? pat : insn))
return false;
/* Don't return true for frame pointer restores in the epilogue. */
if (find_reg_note (insn, REG_CFA_RESTORE, hard_frame_pointer_rtx))
return false;
return true;
}
/* Record the effects of INSN. */
void
@ -2651,6 +2673,14 @@ cselib_process_insn (rtx insn)
if (GET_CODE (XEXP (x, 0)) == CLOBBER)
cselib_invalidate_rtx (XEXP (XEXP (x, 0), 0));
/* On setter of the hard frame pointer if frame_pointer_needed,
invalidate stack_pointer_rtx, so that sp and {,h}fp based
VALUEs are distinct. */
if (reload_completed
&& frame_pointer_needed
&& fp_setter_insn (insn))
cselib_invalidate_rtx (stack_pointer_rtx);
cselib_current_insn = NULL_RTX;
if (n_useless_values > MAX_USELESS_VALUES

View File

@ -78,6 +78,7 @@ extern void cselib_init (int);
extern void cselib_clear_table (void);
extern void cselib_finish (void);
extern void cselib_process_insn (rtx);
extern bool fp_setter_insn (rtx);
extern enum machine_mode cselib_reg_set_mode (const_rtx);
extern int rtx_equal_for_cselib_p (rtx, rtx);
extern int references_value_p (const_rtx, int);

View File

@ -1,3 +1,8 @@
2012-11-20 Jakub Jelinek <jakub@redhat.com>
PR rtl-optimization/54921
* gcc.dg/pr54921.c: New test.
2012-11-19 Richard Sandiford <rdsandiford@googlemail.com>
* gcc.target/i386/pr55359.c: New test.

View File

@ -0,0 +1,32 @@
/* PR rtl-optimization/54921 */
/* { dg-do run } */
/* { dg-options "-Os -fno-omit-frame-pointer -fsched2-use-superblocks -ftree-slp-vectorize" } */
/* { dg-additional-options "-fstack-protector" { target fstack_protector } } */
struct A
{
int a;
char b[32];
} a, b;
__attribute__((noinline, noclone))
struct A
bar (int x)
{
struct A r;
static int n;
r.a = ++n;
__builtin_memset (r.b, 0, sizeof (r.b));
r.b[0] = x;
return r;
}
int
main ()
{
a = bar (3);
b = bar (4);
if (a.a != 1 || a.b[0] != 3 || b.a != 2 || b.b[0] != 4)
__builtin_abort ();
return 0;
}

View File

@ -9522,40 +9522,6 @@ vt_add_function_parameters (void)
}
}
/* Return true if INSN in the prologue initializes hard_frame_pointer_rtx. */
static bool
fp_setter (rtx insn)
{
rtx pat = PATTERN (insn);
if (RTX_FRAME_RELATED_P (insn))
{
rtx expr = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX);
if (expr)
pat = XEXP (expr, 0);
}
if (GET_CODE (pat) == SET)
{
if (SET_DEST (pat) != hard_frame_pointer_rtx)
return false;
}
else if (GET_CODE (pat) == PARALLEL)
{
int i;
for (i = XVECLEN (pat, 0) - 1; i >= 0; i--)
if (GET_CODE (XVECEXP (pat, 0, i)) == SET
&& SET_DEST (XVECEXP (pat, 0, i)) == hard_frame_pointer_rtx)
break;
if (i < 0)
return false;
}
else
return false;
if (find_reg_note (insn, REG_CFA_RESTORE, hard_frame_pointer_rtx))
return false;
return true;
}
/* Initialize cfa_base_rtx, create a preserved VALUE for it and
ensure it isn't flushed during cselib_reset_table.
Can be called only if frame_pointer_rtx resp. arg_pointer_rtx
@ -9859,8 +9825,7 @@ vt_initialize (void)
if (fp_cfa_offset != -1
&& hard_frame_pointer_adjustment == -1
&& RTX_FRAME_RELATED_P (insn)
&& fp_setter (insn))
&& fp_setter_insn (insn))
{
vt_init_cfa_base ();
hard_frame_pointer_adjustment = fp_cfa_offset;