This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
CALL_INSN_FUNCTION_USAGE fix, PR52773
- From: Bernd Schmidt <bernds at codesourcery dot com>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Wed, 19 Jun 2013 19:39:03 +0200
- 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
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;
+}