[backport proposed fix for PR52773 on M68K ] List-Archive: Date: Wed, 19 Jun 2013 19:39:03 +0200 From: Bernd Schmidt Subject: CALL_INSN_FUNCTION_USAGE fix, PR52773 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 --- gcc-4.8.1/gcc/calls.c.~1~ 2013-01-12 00:39:18.000000000 +0100 +++ gcc-4.8.1/gcc/calls.c 2013-06-21 13:03:26.365529168 +0200 @@ -3601,6 +3601,7 @@ emit_library_call_value_1 (int retval, r 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 @@ -3954,6 +3955,8 @@ emit_library_call_value_1 (int retval, r /* 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) @@ -4044,14 +4047,19 @@ emit_library_call_value_1 (int retval, r 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); --- gcc-4.8.1/gcc/testsuite/gcc.c-torture/compile/pr52773.c.~1~ 1970-01-01 01:00:00.000000000 +0100 +++ gcc-4.8.1/gcc/testsuite/gcc.c-torture/compile/pr52773.c 2013-06-21 13:03:26.365529168 +0200 @@ -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; +}