@@ -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
@@ -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;
+}