Hi all, This is a backport to GCC 4.9 and 5 of the patch at https://gcc.gnu.org/ml/gcc-patches/2015-11/msg03082.html The only difference with the trunk version is that we perform #ifdef checks on STACK_GROWS_DOWNWARD because on these branches we have not moved away from conditional compilation of those bits.
Bernd approved the backports at https://gcc.gnu.org/ml/gcc-patches/2015-11/msg03090.html so I'll be committing this to the branches. Bootstrapped and tested on arm, aarch64, x86_64. Confirmed that the testcase fails on all the branches before this patch and passes with it. Thanks, Kyrill 2015-11-26 Kyrylo Tkachov <kyrylo.tkac...@arm.com> Bernd Schmidt <bschm...@redhat.com> PR rtl-optimization/67226 * calls.c (store_one_arg): Take into account crtl->args.pretend_args_size when checking for overlap between arg->value and argblock + arg->locate.offset during sibcall optimization. 2015-11-26 Kyrylo Tkachov <kyrylo.tkac...@arm.com> PR rtl-optimization/67226 * gcc.c-torture/execute/pr67226.c: New test.
diff --git a/gcc/calls.c b/gcc/calls.c index 0987dd0..ee8ea5f 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -4959,6 +4959,13 @@ store_one_arg (struct arg_data *arg, rtx argblock, int flags, if (XEXP (x, 0) != crtl->args.internal_arg_pointer) i = INTVAL (XEXP (XEXP (x, 0), 1)); + /* arg.locate doesn't contain the pretend_args_size offset, + it's part of argblock. Ensure we don't count it in I. */ +#ifdef STACK_GROWS_DOWNWARD + i -= crtl->args.pretend_args_size; +#else + i += crtl->args.pretend_args_size; +#endif /* expand_call should ensure this. */ gcc_assert (!arg->locate.offset.var && arg->locate.size.var == 0 diff --git a/gcc/testsuite/gcc.c-torture/execute/pr67226.c b/gcc/testsuite/gcc.c-torture/execute/pr67226.c new file mode 100644 index 0000000..c533496 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr67226.c @@ -0,0 +1,42 @@ +struct assembly_operand +{ + int type, value, symtype, symflags, marker; +}; + +struct assembly_operand to_input, from_input; + +void __attribute__ ((__noinline__, __noclone__)) +assemblez_1 (int internal_number, struct assembly_operand o1) +{ + if (o1.type != from_input.type) + __builtin_abort (); +} + +void __attribute__ ((__noinline__, __noclone__)) +t0 (struct assembly_operand to, struct assembly_operand from) +{ + if (to.value == 0) + assemblez_1 (32, from); + else + __builtin_abort (); +} + +int +main (void) +{ + to_input.value = 0; + to_input.type = 1; + to_input.symtype = 2; + to_input.symflags = 3; + to_input.marker = 4; + + from_input.value = 5; + from_input.type = 6; + from_input.symtype = 7; + from_input.symflags = 8; + from_input.marker = 9; + + t0 (to_input, from_input); + + return 0; +}