From: H.J. Lu Date: Wed, 23 Dec 2015 09:49:28 +0000 (+0000) Subject: [PATCH] Allow indirect call via GOT for 64-bit Pmode x32 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=fa87d16dcf766d1754837e71d5a1abc97a9e0c8b;p=gcc.git [PATCH] Allow indirect call via GOT for 64-bit Pmode x32 From: H.J. Lu 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. From-SVN: r231923 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 032e2da5995..05c6460466d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2015-12-23 H.J. Lu + + 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. + 2015-12-22 David Malcolm PR c/68473 diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md index 2861d8dfdd2..b46d32b5728 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 96d946c63d3..17249e766ba 100644 --- a/gcc/config/i386/predicates.md +++ b/gcc/config/i386/predicates.md @@ -620,32 +620,36 @@ return false; }) +;; 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"))))) ;; Return true if OP is a 32-bit GOT symbol operand. (define_predicate "GOT32_symbol_operand" diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 1ee6af033e6..524b9b02e14 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2015-12-23 H.J. Lu + + 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. + 2015-12-22 David Malcolm PR c/68473 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 00000000000..c4e9157ac13 --- /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 00000000000..05794af83ec --- /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 00000000000..313b9e4d894 --- /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 00000000000..50a12cf91fd --- /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" } } */