Hi! This is an attempt to hopefully end the endless stream of aliasing miscompilations where alias.c assumes that hfp based accesses can't alias sp based accesses, but both sp and fp can appear in VALUEs pretty much randomly. As detailed in the PR, we have the r variable at rbp - 48 and rsp is also rbp - 48, some stores use direct rbp - 44 based addresses which then have find_base_term of the value equal to (address:DI -4), other stores use rdi == r9 based address, where r9 is r8 + 4 and r8 is rbp - 48, but value for r8 has r8 as well as rsp registers in its locs and therefore find_base_term returns (address:DI -1) - i.e. sp based term, and alias.c says those two can't alias even when they actually do.
The fix is what I've done recently in var-tracking.c, invalidate sp if frame_pointer_needed right after the fp setter insn, so we then have a set of VALUEs which are based on rbp and a different set of values which are based on rsp, but those two sets are now disjoint. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2012-10-23 Jakub Jelinek <ja...@redhat.com> PR rtl-optimization/54921 * cselib.c (cselib_process_insn): If frame_pointer_needed, call cselib_invalidate_rtx (stack_pointer_rtx) after processing a frame pointer setter in the prologue. * gcc.dg/pr54921.c: New test. --- gcc/cselib.c.jj 2012-10-16 13:20:25.000000000 +0200 +++ gcc/cselib.c 2012-10-23 14:22:17.694861625 +0200 @@ -2655,6 +2655,34 @@ 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 + && RTX_FRAME_RELATED_P (insn) + && BLOCK_FOR_INSN (insn) == single_succ (ENTRY_BLOCK_PTR)) + { + rtx pat = PATTERN (insn); + rtx expr = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX); + if (expr) + pat = XEXP (expr, 0); + if (GET_CODE (pat) == SET + && SET_DEST (pat) == hard_frame_pointer_rtx) + cselib_invalidate_rtx (stack_pointer_rtx); + 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) + { + cselib_invalidate_rtx (stack_pointer_rtx); + break; + } + } + } + cselib_current_insn = NULL_RTX; if (n_useless_values > MAX_USELESS_VALUES --- gcc/testsuite/gcc.dg/pr54921.c.jj 2012-10-23 14:17:49.811466882 +0200 +++ gcc/testsuite/gcc.dg/pr54921.c 2012-10-23 14:17:32.000000000 +0200 @@ -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; +} Jakub