===================================================================
@@ -363,7 +363,8 @@
consider CALL_INSN_FUNCTION_USAGE when processing call insns.
Moreover, we need to distinguish two cases:
1. Before reload (register elimination), the stores related to
- outgoing arguments are stack pointer based and thus deemed
+ outgoing arguments are stack pointer based, except for sibling
+ calls which use incoming arguments, and thus they are deemed
of non-constant base in this pass. This requires special
handling but also means that the frame pointer based stores
need not be killed upon encountering a const function call.
@@ -2516,7 +2517,7 @@
const_call ? "const" : "memset", INSN_UID (insn));
/* See the head comment of the frame_read field. */
- if (reload_completed)
+ if (reload_completed || SIBLING_CALL_P (insn))
insn_info->frame_read = true;
/* Loop over the active stores and remove those which are
@@ -2525,8 +2526,11 @@
{
bool remove_store = false;
- /* The stack pointer based stores are always killed. */
- if (i_ptr->stack_pointer_based)
+ /* The stack pointer based stores are always killed for
+ non sibling calls. Before reload, the arguments of a
+ sibling call are frame pointer based. */
+ if (i_ptr->stack_pointer_based
+ && (reload_completed || !SIBLING_CALL_P (insn)))
remove_store = true;
/* If the frame is read, the frame related stores are killed. */
@@ -0,0 +1,33 @@
+/* PR rtl-optimization/55023 */
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-inline" } */
+
+extern void abort (void);
+typedef long long int64_t;
+
+struct foo {
+ int x;
+ int y;
+};
+
+int64_t foo(int64_t a, int64_t b, int64_t c)
+{
+ return a + b + c;
+}
+
+int64_t bar(int64_t a, struct foo bq, struct foo cq)
+{
+ int64_t b = bq.x + bq.y;
+ int64_t c = cq.x + cq.y;
+ return foo(a, b, c);
+}
+
+int main(void)
+{
+ int64_t a = 1;
+ struct foo b = { 2, 3 };
+ struct foo c = { 4, 5 };
+ if (bar (a, b, c) != 15)
+ abort ();
+ return 0;
+}