[PATCH] Allow indirect call via GOT for 64-bit Pmode x32
authorH.J. Lu <hongjiu.lu@intel.com>
Wed, 23 Dec 2015 09:49:28 +0000 (09:49 +0000)
committerUros Bizjak <uros@gcc.gnu.org>
Wed, 23 Dec 2015 09:49:28 +0000 (10:49 +0100)
From: H.J. Lu  <hongjiu.lu@intel.com>

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

gcc/ChangeLog
gcc/config/i386/constraints.md
gcc/config/i386/predicates.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/pr66232-10.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr66232-11.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr66232-12.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr66232-13.c [new file with mode: 0644]

index 032e2da59951a2eb4a25118c457f1d7da4a01311..05c6460466d55c27ed75619ec5ad3cbfedc0cb64 100644 (file)
@@ -1,3 +1,13 @@
+2015-12-23  H.J. Lu  <hongjiu.lu@intel.com>
+
+       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  <dmalcolm@redhat.com>
 
        PR c/68473
index 2861d8dfdd2af189f94fbf36320709bf3007c9f0..b46d32b57281f8519b9d794b41104d7f5e110af8 100644 (file)
 
 (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."
index 96d946c63d36f30a1e30c7357b66c76927fc80aa..17249e766badff51e7bf1765ca67671e61bc8666 100644 (file)
   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"
index 1ee6af033e6d449512c76652c8e5076cd3cc7570..524b9b02e14604520c092bd6769fe8110c3361aa 100644 (file)
@@ -1,3 +1,11 @@
+2015-12-23  H.J. Lu  <hongjiu.lu@intel.com>
+
+       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  <dmalcolm@redhat.com>
 
        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 (file)
index 0000000..c4e9157
--- /dev/null
@@ -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 (file)
index 0000000..05794af
--- /dev/null
@@ -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 (file)
index 0000000..313b9e4
--- /dev/null
@@ -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 (file)
index 0000000..50a12cf
--- /dev/null
@@ -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" } } */