Hi! The attached testcase is miscompiled on arm*, by doing a sibcall when setup of one argument overwrites incoming arguments used to setup parameters in later insns. The reason why mem_overlaps_already_clobbered_arg_p/check_sibcall_argument_overlap fails to detect is that the caller has non-zero crtl->args.pretend_args_size, and in that case the base: /* The argument block when performing a sibling call is the incoming argument block. */ if (pass == 0) { argblock = crtl->args.internal_arg_pointer; argblock #ifdef STACK_GROWS_DOWNWARD = plus_constant (argblock, crtl->args.pretend_args_size); #else = plus_constant (argblock, -crtl->args.pretend_args_size); #endif stored_args_map = sbitmap_alloc (args_size.constant); sbitmap_zero (stored_args_map); } apparently isn't virtual-incoming-rtx, but that plus pretend_args_size (8 in this case). When we store bits into stored_args_map sbitmap, we use arg->locate.slot_offset.constant based values (or something different for ARGS_GROW_DOWNWARD, but when mem_overlaps_already_clobbered_arg_p is testing those bits, it uses just virtual-incoming-rtx offsets (or something different for ARGS_GROW_DOWNWARD). This patch fixes it by adjusting the virtual-incoming-rtx relative offset to be actually argblock relative offset.
Bootstrapped/regtested on x86_64-linux and i686-linux and tested on the testcase on arm cross. Ok for trunk? 2012-02-06 Jakub Jelinek <ja...@redhat.com> PR target/52129 * calls.c (mem_overlaps_already_clobbered_arg_p): If val is CONST_INT_P, subtract resp. add crtl->args.pretend_args_size to it. * gcc.c-torture/execute/pr52129.c: New test. --- gcc/calls.c.jj 2012-02-01 14:44:27.000000000 +0100 +++ gcc/calls.c 2012-02-06 10:19:12.112132905 +0100 @@ -1808,6 +1808,11 @@ mem_overlaps_already_clobbered_arg_p (rt return true; else i = INTVAL (val); +#ifdef STACK_GROWS_DOWNWARD + i -= crtl->args.pretend_args_size; +#else + i += crtl->args.pretend_args_size; +#endif #ifdef ARGS_GROW_DOWNWARD i = -i - size; --- gcc/testsuite/gcc.c-torture/execute/pr52129.c.jj 2012-02-06 10:27:50.988876791 +0100 +++ gcc/testsuite/gcc.c-torture/execute/pr52129.c 2012-02-06 10:25:26.000000000 +0100 @@ -0,0 +1,28 @@ +/* PR target/52129 */ + +extern void abort (void); +struct S { void *p; unsigned int q; }; +struct T { char a[64]; char b[64]; } t; + +__attribute__((noinline, noclone)) int +foo (void *x, struct S s, void *y, void *z) +{ + if (x != &t.a[2] || s.p != &t.b[5] || s.q != 27 || y != &t.a[17] || z != &t.b[17]) + abort (); + return 29; +} + +__attribute__((noinline, noclone)) int +bar (void *x, void *y, void *z, struct S s, int t, struct T *u) +{ + return foo (x, s, &u->a[t], &u->b[t]); +} + +int +main () +{ + struct S s = { &t.b[5], 27 }; + if (bar (&t.a[2], (void *) 0, (void *) 0, s, 17, &t) != 29) + abort (); + return 0; +} Jakub