@@ -1578,7 +1578,9 @@ rtx_for_function_call (tree fndecl, tree addr)
sibcall. */
static bool
-mem_overlaps_already_clobbered_arg_p (rtx addr, unsigned HOST_WIDE_INT size)
+mem_overlaps_already_clobbered_arg_p (rtx addr,
+ unsigned HOST_WIDE_INT size,
+ bool check_addr_reg)
{
HOST_WIDE_INT i;
@@ -1595,7 +1597,7 @@ mem_overlaps_already_clobbered_arg_p (rtx addr, unsigned HOST_WIDE_INT size)
return true;
/* If the address comes in a register, we have no idea of its origin so
give up and conservatively return true. */
- else if (REG_P(addr))
+ else if (check_addr_reg && REG_P(addr))
return true;
else
return false;
@@ -1716,7 +1718,8 @@ load_register_parameters (struct arg_data *args, int num_actuals,
if (is_sibcall
&& (size == 0
|| mem_overlaps_already_clobbered_arg_p
- (XEXP (args[i].value, 0), size)))
+ (XEXP (args[i].value, 0), size,
+ false)))
*sibcall_failure = 1;
/* Handle a BLKmode that needs shifting. */
@@ -1843,7 +1846,8 @@ check_sibcall_argument_overlap_1 (rtx x)
if (code == MEM)
return mem_overlaps_already_clobbered_arg_p (XEXP (x, 0),
- GET_MODE_SIZE (GET_MODE (x)));
+ GET_MODE_SIZE (GET_MODE (x)),
+ false);
/* Scan all subexpressions. */
fmt = GET_RTX_FORMAT (code);
@@ -4256,7 +4260,8 @@ store_one_arg (struct arg_data *arg, rtx argblock, int flags,
if ((flags & ECF_SIBCALL)
&& MEM_P (arg->value)
&& mem_overlaps_already_clobbered_arg_p (XEXP (arg->value, 0),
- arg->locate.size.constant))
+ arg->locate.size.constant,
+ true))
sibcall_failure = 1;
/* Don't allow anything left on stack from computation
new file mode 100644
@@ -0,0 +1,38 @@
+/* { dg-do run { target { { i?86-*-* x86_64-*-* s390*-*-* } && fpic } } } */
+/* { dg-skip-if "" { { i?86-*-* x86_64-*-* } && ia32 } { "*" } { "" } } */
+/* { dg-options "-O2 -foptimize-sibling-calls -fno-ipa-cp -fPIC" } */
+
+extern void abort (void);
+extern void exit (int);
+
+int foo (int);
+int bar (int);
+
+int (*ptr) (int);
+int *f_addr;
+
+int
+main ()
+{
+ ptr = bar;
+ foo (7);
+ exit (0);
+}
+
+int __attribute__ ((noinline))
+bar (b)
+ int b;
+{
+ if (f_addr == (int*) __builtin_return_address (0))
+ return b;
+ else
+ abort ();
+}
+
+int __attribute__ ((noinline))
+foo (f)
+ int f;
+{
+ f_addr = (int*) __builtin_return_address (0);
+ return (*ptr)(f);
+}