aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/calls.cc29
-rw-r--r--gcc/testsuite/gcc.dg/pr122947.c45
2 files changed, 73 insertions, 1 deletions
diff --git a/gcc/calls.cc b/gcc/calls.cc
index bb8a6d0..85d6ea4 100644
--- a/gcc/calls.cc
+++ b/gcc/calls.cc
@@ -3579,7 +3579,8 @@ expand_call (tree exp, rtx target, int ignore)
&& check_sibcall_argument_overlap (before_arg,
&args[i], true)))
sibcall_failure = true;
- }
+ gcc_checking_assert (!args[i].stack || argblock);
+ }
if (args[i].stack)
call_fusage
@@ -3676,6 +3677,32 @@ expand_call (tree exp, rtx target, int ignore)
&& !must_preallocate && reg_parm_stack_space > 0)
anti_adjust_stack (GEN_INT (reg_parm_stack_space));
+ /* Cover pushed arguments with call usage, so that cselib knows to
+ invalidate the stores in them at the call insn. */
+ if (pass == 1 && !argblock
+ && (maybe_ne (adjusted_args_size.constant, 0)
+ || adjusted_args_size.var))
+ {
+ rtx addr = virtual_outgoing_args_rtx;
+ poly_int64 size = adjusted_args_size.constant;
+ if (!STACK_GROWS_DOWNWARD)
+ {
+ if (adjusted_args_size.var)
+ /* ??? We can't compute the exact base address. */
+ addr = gen_rtx_PLUS (GET_MODE (addr), addr,
+ gen_rtx_SCRATCH (GET_MODE (addr)));
+ else
+ addr = plus_constant (GET_MODE (addr), addr, -size);
+ }
+ rtx fu = gen_rtx_MEM (BLKmode, addr);
+ if (adjusted_args_size.var == 0)
+ set_mem_size (fu, size);
+ call_fusage
+ = gen_rtx_EXPR_LIST (BLKmode,
+ gen_rtx_USE (VOIDmode, fu),
+ call_fusage);
+ }
+
/* Pass the function the address in which to return a
structure value. */
if (pass != 0 && structure_value_addr && ! structure_value_addr_parm)
diff --git a/gcc/testsuite/gcc.dg/pr122947.c b/gcc/testsuite/gcc.dg/pr122947.c
new file mode 100644
index 0000000..945a61a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr122947.c
@@ -0,0 +1,45 @@
+/* PR rtl-optimization/122947 based on PR 117239 */
+/* { dg-do run } */
+/* { dg-options "-fno-inline -O2" } */
+/* { dg-additional-options "-fschedule-insns -mno-accumulate-outgoing-args" { target x86 } } */
+
+int c = 1;
+
+struct A {
+ int e, f, g, h;
+ short i;
+ int j;
+};
+
+void
+bar (int x, struct A y)
+{
+ if (y.j == 1)
+ c = 0;
+}
+
+/* Simplest pure way to force baz's x.j back to memory.
+ So simple that IPA "inlines" it, so we disable IPA and mark as pure. */
+int __attribute__ ((noipa, pure))
+bad (struct A const *x)
+{
+ return x->j;
+}
+
+int
+baz (struct A x)
+{
+ x.j = 0;
+ return bad (&x);
+}
+
+int
+main ()
+{
+ struct A k = { 0, 0, 0, 0, 0, 1 };
+ int d = baz (k);
+ bar (0, k);
+ if (c + d != 0)
+ __builtin_abort ();
+ return 0;
+}