On Thu, Dec 17, 2015 at 8:49 AM, H.J. Lu <hongjiu...@intel.com> wrote: > Since Pmode is 64-bit with -maddress-mode=long for x32, indirect call > via GOT slot doesn't need zero_extend. This patch limits *call_got_x32 > and *call_value_got_x32 patterns to 32-bit Pmode, adds *call_got_x32_long > and *call_value_got_x32_long for 64-bit Pmode. > > OK for trunk if there is no regression? > > > H.J. > --- > gcc/ > > PR target/66232 > * config/i386/i386.md (*call_got_x32): Limited to 32-bit Pmode. > (*call_value_got_x32): Likewise. > (*call_got_x32_long): New pattern. > (call_value_got_x32_long): Likewise. >
Here is a different approach without adding new patterns. Either one works. -- H.J.
From 118cf4c2c928608f7ad7edd0812d6f2f880dbd55 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" <hjl.to...@gmail.com> Date: Thu, 17 Dec 2015 08:42:06 -0800 Subject: [PATCH] Allow indirect call via GOT for 64-bit Pmode x32 Since Pmode is 64-bit with -maddress-mode=long for x32, indirect call via GOT slot doesn't need zero_extend. This patch enables indirect call via GOT for x32 with 64-bit Pmode. gcc/ PR target/66232 * config/i386/constraints.md (Bs): Allow GOT slot for x32 with 64-bit Pmode. (Bw): Likewise. (Bz): Likewise. * config/i386/predicates.md (call_insn_operand): Likewise. (sibcall_insn_operand): Likewise. gcc/testsuite/ PR target/66232 * gcc.target/i386/pr66232-10.c: New test. * gcc.target/i386/pr66232-11.c: Likewise. * gcc.target/i386/pr66232-12.c: Likewise. * gcc.target/i386/pr66232-13.c: Likewise. --- gcc/config/i386/constraints.md | 12 +++++++---- gcc/config/i386/predicates.md | 32 +++++++++++++++++------------- gcc/testsuite/gcc.target/i386/pr66232-10.c | 13 ++++++++++++ gcc/testsuite/gcc.target/i386/pr66232-11.c | 14 +++++++++++++ gcc/testsuite/gcc.target/i386/pr66232-12.c | 13 ++++++++++++ gcc/testsuite/gcc.target/i386/pr66232-13.c | 13 ++++++++++++ 6 files changed, 79 insertions(+), 18 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-10.c create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-11.c create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-12.c create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-13.c diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md index 2861d8d..b46d32b 100644 --- a/gcc/config/i386/constraints.md +++ b/gcc/config/i386/constraints.md @@ -162,13 +162,17 @@ (define_constraint "Bs" "@internal Sibcall memory operand." - (and (not (match_test "TARGET_X32")) - (match_operand 0 "sibcall_memory_operand"))) + (ior (and (not (match_test "TARGET_X32")) + (match_operand 0 "sibcall_memory_operand")) + (and (match_test "TARGET_X32 && Pmode == DImode") + (match_operand 0 "GOT_memory_operand")))) (define_constraint "Bw" "@internal Call memory operand." - (and (not (match_test "TARGET_X32")) - (match_operand 0 "memory_operand"))) + (ior (and (not (match_test "TARGET_X32")) + (match_operand 0 "memory_operand")) + (and (match_test "TARGET_X32 && Pmode == DImode") + (match_operand 0 "GOT_memory_operand")))) (define_constraint "Bz" "@internal Constant call address operand." diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md index 8bdd5d8..ab8ef06 100644 --- a/gcc/config/i386/predicates.md +++ b/gcc/config/i386/predicates.md @@ -606,32 +606,36 @@ && GET_CODE (XEXP (XEXP (XEXP (op, 0), 1), 0)) == UNSPEC && XINT (XEXP (XEXP (XEXP (op, 0), 1), 0), 1) == UNSPEC_GOT)"))) +;; Return true if OP is a GOT memory operand. +(define_predicate "GOT_memory_operand" + (match_operand 0 "memory_operand") +{ + op = XEXP (op, 0); + return (GET_CODE (op) == CONST + && GET_CODE (XEXP (op, 0)) == UNSPEC + && XINT (XEXP (op, 0), 1) == UNSPEC_GOTPCREL); +}) + ;; Test for a valid operand for a call instruction. ;; Allow constant call address operands in Pmode only. (define_special_predicate "call_insn_operand" (ior (match_test "constant_call_address_operand (op, mode == VOIDmode ? mode : Pmode)") (match_operand 0 "call_register_no_elim_operand") - (and (not (match_test "TARGET_X32")) - (match_operand 0 "memory_operand")))) + (ior (and (not (match_test "TARGET_X32")) + (match_operand 0 "sibcall_memory_operand")) + (and (match_test "TARGET_X32 && Pmode == DImode") + (match_operand 0 "GOT_memory_operand"))))) ;; Similarly, but for tail calls, in which we cannot allow memory references. (define_special_predicate "sibcall_insn_operand" (ior (match_test "constant_call_address_operand (op, mode == VOIDmode ? mode : Pmode)") (match_operand 0 "register_no_elim_operand") - (and (not (match_test "TARGET_X32")) - (match_operand 0 "sibcall_memory_operand")))) - -;; Return true if OP is a GOT memory operand. -(define_predicate "GOT_memory_operand" - (match_operand 0 "memory_operand") -{ - op = XEXP (op, 0); - return (GET_CODE (op) == CONST - && GET_CODE (XEXP (op, 0)) == UNSPEC - && XINT (XEXP (op, 0), 1) == UNSPEC_GOTPCREL); -}) + (ior (and (not (match_test "TARGET_X32")) + (match_operand 0 "sibcall_memory_operand")) + (and (match_test "TARGET_X32 && Pmode == DImode") + (match_operand 0 "GOT_memory_operand"))))) ;; Match exactly zero. (define_predicate "const0_operand" diff --git a/gcc/testsuite/gcc.target/i386/pr66232-10.c b/gcc/testsuite/gcc.target/i386/pr66232-10.c new file mode 100644 index 0000000..c4e9157 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr66232-10.c @@ -0,0 +1,13 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-require-effective-target maybe_x32 } */ +/* { dg-options "-O2 -mx32 -fpic -fno-plt -maddress-mode=long" } */ + +extern void bar (void); + +void +foo (void) +{ + bar (); +} + +/* { dg-final { scan-assembler "jmp\[ \t\]*.bar@GOTPCREL" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr66232-11.c b/gcc/testsuite/gcc.target/i386/pr66232-11.c new file mode 100644 index 0000000..05794af --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr66232-11.c @@ -0,0 +1,14 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-require-effective-target maybe_x32 } */ +/* { dg-options "-O2 -mx32 -fpic -fno-plt -maddress-mode=long" } */ + +extern void bar (void); + +int +foo (void) +{ + bar (); + return 0; +} + +/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOTPCREL" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr66232-12.c b/gcc/testsuite/gcc.target/i386/pr66232-12.c new file mode 100644 index 0000000..313b9e4 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr66232-12.c @@ -0,0 +1,13 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-require-effective-target maybe_x32 } */ +/* { dg-options "-O2 -mx32 -fpic -fno-plt -maddress-mode=long" } */ + +extern int bar (void); + +int +foo (void) +{ + return bar (); +} + +/* { dg-final { scan-assembler "jmp\[ \t\]*.bar@GOTPCREL" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr66232-13.c b/gcc/testsuite/gcc.target/i386/pr66232-13.c new file mode 100644 index 0000000..50a12cf --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr66232-13.c @@ -0,0 +1,13 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-require-effective-target maybe_x32 } */ +/* { dg-options "-O2 -mx32 -fpic -fno-plt -maddress-mode=long" } */ + +extern int bar (void); + +int +foo (void) +{ + return bar () + 1; +} + +/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOTPCREL" } } */ -- 2.5.0