This is bug that triggers on m68k. The loop unroller creates a MULT expression and tries to force it into a register, which causes a libcall to be generated. Since args are pushed we create a (use (mem (plus virtual_outgoing_args scratch))) in CALL_INSN_FUNCTION_USAGE. Since we're past vregs, the virtual_outgoing_args rtx survives to reload, which blows up.
Fixed by just using stack_pointer_rtx, since we use a scratch anyway rather than a known offset. I also noticed that we actually add two of these USEs, so I've fixed that as well. Bootstrapped and tested on x86_64-linux, ok? Bernd
diff --git a/gcc/calls.c b/gcc/calls.c index cdab8e0..db38b73 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -3603,6 +3603,7 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value, int reg_parm_stack_space = 0; int needed; rtx before_call; + bool have_push_fusage; tree tfom; /* type_for_mode (outmode, 0) */ #ifdef REG_PARM_STACK_SPACE @@ -3956,6 +3957,8 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value, /* Push the args that need to be pushed. */ + have_push_fusage = false; + /* ARGNUM indexes the ARGVEC array in the order in which the arguments are to be pushed. */ for (count = 0; count < nargs; count++, argnum += inc) @@ -4046,14 +4049,19 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value, if (argblock) use = plus_constant (Pmode, argblock, argvec[argnum].locate.offset.constant); + else if (have_push_fusage) + continue; else - /* When arguments are pushed, trying to tell alias.c where - exactly this argument is won't work, because the - auto-increment causes confusion. So we merely indicate - that we access something with a known mode somewhere on - the stack. */ - use = gen_rtx_PLUS (Pmode, virtual_outgoing_args_rtx, - gen_rtx_SCRATCH (Pmode)); + { + /* When arguments are pushed, trying to tell alias.c where + exactly this argument is won't work, because the + auto-increment causes confusion. So we merely indicate + that we access something with a known mode somewhere on + the stack. */ + use = gen_rtx_PLUS (Pmode, stack_pointer_rtx, + gen_rtx_SCRATCH (Pmode)); + have_push_fusage = true; + } use = gen_rtx_MEM (argvec[argnum].mode, use); use = gen_rtx_USE (VOIDmode, use); call_fusage = gen_rtx_EXPR_LIST (VOIDmode, use, call_fusage); diff --git a/gcc/testsuite/gcc.c-torture/compile/pr52773.c b/gcc/testsuite/gcc.c-torture/compile/pr52773.c new file mode 100644 index 0000000..8daa5ee --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr52773.c @@ -0,0 +1,16 @@ +/* pr52773.c */ + +struct s { + short x; + short _pad[2]; +}; + +static short mat_a_x; + +void transform(const struct s *src, struct s *dst, int n) +{ + int i; + + for (i = 0; i < n; ++i) + dst[i].x = (src[i].x * mat_a_x) >> 6; +}