This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Patch: treat sibling calls as non-const
- From: Dale Johannesen <dalej at apple dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Dale Johannesen <dalej at apple dot com>
- Date: Thu, 11 Sep 2003 12:54:27 -0700
- Subject: Patch: treat sibling calls as non-const
For the reason explained in the comment. The testcase demonstrates the
problem
on ppc, and probably on other machines that pass args in registers.
Bootstrapped and tested on Darwin to the extent currently possible
(no diffs before & after).
2003-09-11 Dale Johannesen <dalej@apple.com>
* loop.c (prescan_loop): Treat sibling calls as non-const.
Index: loop.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/loop.c,v
retrieving revision 1.470
diff -u -d -b -w -c -3 -p -r1.470 loop.c
*** loop.c 7 Sep 2003 05:21:35 -0000 1.470
--- loop.c 11 Sep 2003 19:48:20 -0000
*************** prescan_loop (struct loop *loop)
*** 2511,2522 ****
break;
case CALL_INSN:
if (! CONST_OR_PURE_CALL_P (insn))
{
loop_info->unknown_address_altered = 1;
loop_info->has_nonconst_call = 1;
}
! else if (pure_call_p (insn))
loop_info->has_nonconst_call = 1;
loop_info->has_call = 1;
if (can_throw_internal (insn))
--- 2511,2539 ----
break;
case CALL_INSN:
+ /* The loop optimizer attempts to hoist invariant stores
+ out of the loop. Stores into memory locations that are
+ actual parameters for a call within the loop
+ can be invariant, and can be hoisted; however,
+ they then appear dead and are removed, as the call
+ insn doesn't have any info about memory parameters
+ attached. So we don't want to do this. This is
+ prevented in the case of non-const calls by not
+ hoisting any stores, and in the case of const non-sibcalls
+ by enclosing the parameters in LIBCALL...RETVAL notes,
+ which prevents individual stores from being considered
+ separately. To fix the remaining case, const sibcalls,
+ we treat them as non-const.
+ FIXME: A better, but much more invasive, way to fix this
+ is to establish a connection between the call and the
+ parameters, so hoisted stores don't get deleted. There
+ is no good reason they shouldn't get hoisted. */
if (! CONST_OR_PURE_CALL_P (insn))
{
loop_info->unknown_address_altered = 1;
loop_info->has_nonconst_call = 1;
}
! else if (pure_call_p (insn) || SIBLING_CALL_P (insn))
loop_info->has_nonconst_call = 1;
loop_info->has_call = 1;
if (can_throw_internal (insn))
/* { dg-do run } */
/* { dg-options "-O2" } */
static int a (int i1, int i2, int i3, int i4, int i5, int i6, int i7,
int i8, int i9, int i10)
{ return i10; }
int b (int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8,
int i9, int i10)
{
for(;;)
if (i1)
return a (i1, i2, i3, i4, i5, i6, i7, i8, i9, i10 + 1);
}
main() {
int val = b(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
if (val != 11)
{
printf ("failure: got %d, expected 11\n", val);
abort() ;
}
else
printf ("O.K.\n");
exit(0);
}