This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix __builtin_apply_args on i386 with -fpic (PR middle-end/38338)


Hi!

My recent patch broke the attached testcase on i386.  When
the apply args sequence is emitted right before NOTE_FUNCTION_BEG
instead of beginning of function, if the apply args sequence uses
hard registers, they are live over the initially emitted insns.
On i386 one such insn wanted to store a 8 bit value into memory,
but as eax, edx and ecx were live across this and ebx reserved
for PIC pointer, there were no QImode registers for reload available.

The fix is either revert the PR middle-end/37323 change for targets
that don't need it (i.e. where internal_arg_pointer is a virtual
register, not copied into another pseudo; implemented in the patch below),
or alternatively it could walk insns from entry_of_function ()
till parm_birth_insn and using note_stores check which function
writes to the crtl->args.internal_arg_pointer register and
emit apply args sequence after such an insn.

The following patch has been bootstrapped/regtested on x86_64-linux,
the testcase checked also with -m32.  Ok for trunk, or should I implement
the longer variant using note_stores?

2008-12-01  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/38338
	* builtins.c (expand_builtin_apply_args): Put before parm_birth_insn
	only if internal_arg_pointer is a non-virtual pseudo.

	* gcc.dg/pr38338.c: New test.

--- gcc/builtins.c.jj	2008-11-25 11:25:52.000000000 +0100
+++ gcc/builtins.c	2008-12-01 18:52:04.000000000 +0100
@@ -1434,9 +1434,15 @@ expand_builtin_apply_args (void)
     /* Put the insns after the NOTE that starts the function.
        If this is inside a start_sequence, make the outer-level insn
        chain current, so the code is placed at the start of the
-       function.  */
+       function.  If internal_arg_pointer is a non-virtual pseudo,
+       it needs to be placed after the function that initializes
+       that pseudo.  */
     push_topmost_sequence ();
-    emit_insn_before (seq, parm_birth_insn);
+    if (REG_P (crtl->args.internal_arg_pointer)
+	&& REGNO (crtl->args.internal_arg_pointer) > LAST_VIRTUAL_REGISTER)
+      emit_insn_before (seq, parm_birth_insn);
+    else
+      emit_insn_before (seq, NEXT_INSN (entry_of_function ()));
     pop_topmost_sequence ();
     return temp;
   }
--- gcc/testsuite/gcc.dg/pr38338.c.jj	2008-12-01 18:58:22.000000000 +0100
+++ gcc/testsuite/gcc.dg/pr38338.c	2008-12-01 18:58:03.000000000 +0100
@@ -0,0 +1,18 @@
+/* PR middle-end/38338 */
+/* { dg-options "-O0" } */
+/* { dg-options "-O0 -fPIC" { target fpic } } */
+
+typedef void (*fnp) (void);
+
+static char
+foo (char x)
+{
+  return x;
+}
+
+static void *
+bar (char x)
+{
+  void *args = __builtin_apply_args ();
+  return __builtin_apply ((fnp) foo, args, sizeof (void *));
+}

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]