From 118cf4c2c928608f7ad7edd0812d6f2f880dbd55 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@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
@@ -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."
@@ -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"
new file mode 100644
@@ -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" } } */
new file mode 100644
@@ -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" } } */
new file mode 100644
@@ -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" } } */
new file mode 100644
@@ -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