diff options
author | Jakub Jelinek <jakub@redhat.com> | 2012-11-20 09:34:43 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2012-11-20 09:34:43 +0100 |
commit | 40155239d684ae96712d34f3f4dcc88eef4fc99d (patch) | |
tree | b8e399f48378d1d27ec4ce799592476990e6187c | |
parent | 4ced1d6de8b7ad914c4ea6fdb3121487d298c9e0 (diff) | |
download | gcc-40155239d684ae96712d34f3f4dcc88eef4fc99d.zip gcc-40155239d684ae96712d34f3f4dcc88eef4fc99d.tar.gz gcc-40155239d684ae96712d34f3f4dcc88eef4fc99d.tar.bz2 |
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
-rw-r--r-- | gcc/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/cselib.c | 30 | ||||
-rw-r--r-- | gcc/cselib.h | 1 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr54921.c | 32 | ||||
-rw-r--r-- | gcc/var-tracking.c | 37 |
6 files changed, 80 insertions, 36 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 27bcf01..d3b0200 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 diff --git a/gcc/cselib.c b/gcc/cselib.c index 92193ba..28f8d07 100644 --- a/gcc/cselib.c +++ b/gcc/cselib.c @@ -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 diff --git a/gcc/cselib.h b/gcc/cselib.h index 95fdbf7..b717c95 100644 --- a/gcc/cselib.h +++ b/gcc/cselib.h @@ -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); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5148099..46eb0cd 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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. diff --git a/gcc/testsuite/gcc.dg/pr54921.c b/gcc/testsuite/gcc.dg/pr54921.c new file mode 100644 index 0000000..897877a --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr54921.c @@ -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; +} diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c index e95cf87..f5ba115 100644 --- a/gcc/var-tracking.c +++ b/gcc/var-tracking.c @@ -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; |