diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 27bcf010fdbdbfb14d7f6791718d1febb65044b6..d3b02002f01f54a97f375e372401d7954ff8dbc3 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 92193ba9bcb82965d66d2fd197240a740e92a273..28f8d0724380f250a9c178f9265a309cb379c584 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 95fdbf7a5d53d384d6463d4b08ad77388c028818..b717c952f4ffbc054aa274f5cbe6b0eb6b5d87b1 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 514809970d6591fe3221039e70cd47f8b0420a7d..46eb0cde84301e295ad0ca055756466b0bee2f1c 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 0000000000000000000000000000000000000000..897877aa00ddb9b67aaab16aaeb70d2477918c10 --- /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 e95cf87a75232684a3faa9a03d1f657d829d7f01..f5ba115bcfecf3bb84c4eb2103b459d9ecad7a28 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;