aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2002-03-27 02:34:14 -0800
committerRichard Henderson <rth@gcc.gnu.org>2002-03-27 02:34:14 -0800
commit6dad5a56316443a832b581d384e1596fad690be1 (patch)
treed54d94353c2c82dd02ebc94714b3af184e829fe3
parent59f968797461e667478c4858837fb00883c1bfb2 (diff)
downloadgcc-6dad5a56316443a832b581d384e1596fad690be1.zip
gcc-6dad5a56316443a832b581d384e1596fad690be1.tar.gz
gcc-6dad5a56316443a832b581d384e1596fad690be1.tar.bz2
re PR target/6054 (GCC 3.1 for ia64 fails to restore gp after indirect call in Linux kernel)
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
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/config/ia64/ia64.c62
-rw-r--r--gcc/testsuite/gcc.dg/20020326-1.c11
3 files changed, 36 insertions, 43 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 80df83c..79b9d50 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,11 @@
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,
config/sparc/netbsd-elf.h, config/sparc/pbd.h, config/sparc/sol2.h,
config/sparc/vxsim.h (LOCAL_LABEL_PREFIX): Define.
diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
index de0c1c9..c78d631 100644
--- a/gcc/config/ia64/ia64.c
+++ b/gcc/config/ia64/ia64.c
@@ -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);
}
/* 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
index 0000000..4a903bc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/20020326-1.c
@@ -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 ();
+}