re PR target/6054 (GCC 3.1 for ia64 fails to restore gp after indirect call in Linux...
authorRichard Henderson <rth@redhat.com>
Wed, 27 Mar 2002 10:34:14 +0000 (02:34 -0800)
committerRichard Henderson <rth@gcc.gnu.org>
Wed, 27 Mar 2002 10:34:14 +0000 (02:34 -0800)
        PR target/6054
        * config/ia64/ia64.c (ia64_expand_call): Use pic patterns for
        TARGET_CONST_GP.  Simplify conditions.

* gcc.dg/20020326-1.c: New.

From-SVN: r51444

gcc/ChangeLog
gcc/config/ia64/ia64.c
gcc/testsuite/gcc.dg/20020326-1.c [new file with mode: 0644]

index 80df83c3e2239e2edd1ba5b52f0275df40893532..79b9d5020431bd12d555361edd9d7c047bc62022 100644 (file)
@@ -1,3 +1,9 @@
+2002-03-27  Richard Henderson  <rth@redhat.com>
+
+       PR target/6054
+       * config/ia64/ia64.c (ia64_expand_call): Use pic patterns for
+       TARGET_CONST_GP.  Simplify conditions.
+
 2002-03-27  Richard Henderson  <rth@redhat.com>
 
        * config/sparc/freebsd.h, config/sparc/linux.h, config/sparc/linux64.h,
index de0c1c941415a8f696e6ecce193429a64914abe8..c78d6319d82f841d0c4de8d9a5b83d67d268da12 100644 (file)
@@ -1144,7 +1144,8 @@ ia64_expand_call (retval, addr, nextarg, sibcall_p)
      rtx nextarg;
      int sibcall_p;
 {
-  rtx insn, b0, pfs, gp_save, narg_rtx;
+  rtx insn, b0, pfs, gp_save, narg_rtx, dest;
+  bool indirect_p;
   int narg;
 
   addr = XEXP (addr, 0);
@@ -1171,61 +1172,36 @@ ia64_expand_call (retval, addr, nextarg, sibcall_p)
       return;
     }
 
-  if (sibcall_p)
+  indirect_p = ! symbolic_operand (addr, VOIDmode);
+
+  if (sibcall_p || (TARGET_CONST_GP && !indirect_p))
     gp_save = NULL_RTX;
   else
     gp_save = ia64_gp_save_reg (setjmp_operand (addr, VOIDmode));
 
+  if (gp_save)
+    emit_move_insn (gp_save, pic_offset_table_rtx);
+
   /* If this is an indirect call, then we have the address of a descriptor.  */
-  if (! symbolic_operand (addr, VOIDmode))
+  if (indirect_p)
     {
-      rtx dest;
-
-      if (! sibcall_p)
-       emit_move_insn (gp_save, pic_offset_table_rtx);
-
       dest = force_reg (DImode, gen_rtx_MEM (DImode, addr));
       emit_move_insn (pic_offset_table_rtx,
                      gen_rtx_MEM (DImode, plus_constant (addr, 8)));
-
-      if (sibcall_p)
-       insn = gen_sibcall_pic (dest, narg_rtx, b0, pfs);
-      else if (! retval)
-       insn = gen_call_pic (dest, narg_rtx, b0);
-      else
-       insn = gen_call_value_pic (retval, dest, narg_rtx, b0);
-      emit_call_insn (insn);
-
-      if (! sibcall_p)
-       emit_move_insn (pic_offset_table_rtx, gp_save);
-    }
-  else if (TARGET_CONST_GP)
-    {
-      if (sibcall_p)
-       insn = gen_sibcall_nopic (addr, narg_rtx, b0, pfs);
-      else if (! retval)
-       insn = gen_call_nopic (addr, narg_rtx, b0);
-      else
-       insn = gen_call_value_nopic (retval, addr, narg_rtx, b0);
-      emit_call_insn (insn);
     }
   else
-    {
-      if (sibcall_p)
-       emit_call_insn (gen_sibcall_pic (addr, narg_rtx, b0, pfs));
-      else
-       {
-         emit_move_insn (gp_save, pic_offset_table_rtx);
+    dest = addr;
 
-         if (! retval)
-           insn = gen_call_pic (addr, narg_rtx, b0);
-         else
-           insn = gen_call_value_pic (retval, addr, narg_rtx, b0);
-         emit_call_insn (insn);
+  if (sibcall_p)
+    insn = gen_sibcall_pic (dest, narg_rtx, b0, pfs);
+  else if (! retval)
+    insn = gen_call_pic (dest, narg_rtx, b0);
+  else
+    insn = gen_call_value_pic (retval, dest, narg_rtx, b0);
+  emit_call_insn (insn);
 
-         emit_move_insn (pic_offset_table_rtx, gp_save);
-       }
-    }
+  if (gp_save)
+    emit_move_insn (pic_offset_table_rtx, gp_save);
 }
 \f
 /* Begin the assembly file.  */
diff --git a/gcc/testsuite/gcc.dg/20020326-1.c b/gcc/testsuite/gcc.dg/20020326-1.c
new file mode 100644 (file)
index 0000000..4a903bc
--- /dev/null
@@ -0,0 +1,11 @@
+/* PR target/6054 */
+/* { dg-do compile { target ia64-*-* } } */
+/* { dg-options "-O -mconstant-gp" } */
+/* { dg-final { scan-assembler "mov r1 =" } } */
+
+extern void direct (void);
+void foo(void (*indirect) (void))
+{
+  indirect ();
+  direct ();
+}