public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] PR target/66232: -fPIC -fno-plt -mx32 fails to generate indirect branch via GOT
@ 2015-05-21 13:05 H.J. Lu
  2015-05-21 13:19 ` Uros Bizjak
  2015-05-21 19:13 ` Richard Henderson
  0 siblings, 2 replies; 16+ messages in thread
From: H.J. Lu @ 2015-05-21 13:05 UTC (permalink / raw)
  To: gcc-patches; +Cc: Uros Bizjak

X32 doesn't support indirect branch via 32-bit memory slot since
indirect branch will load 64-bit address from 64-bit memory slot.
Since x32 GOT slot is 64-bit, we should allow indirect branch via GOT
slot for x32.

I am testing it on x32.  OK for master if there is no regression?

Thanks.


H.J.
--
gcc/

	PR target/66232
	* config/i386/constraints.md (Bg): Add a constraint for x32
	call and sibcall memory operand.
	* config/i386/i386.md (*call_x32): New pattern.
	(*sibcall_x32): Likewise.
	(*call_value_x32): Likewise.
	(*sibcall_value_x32): Likewise.
	* config/i386/predicates.md (x32_sibcall_memory_operand): New
	predicate.
	(x32_call_insn_operand): Likewise.
	(x32_sibcall_insn_operand): Likewise.

gcc/testsuite/

	PR target/66232
	* gcc.target/i386/pr66232-1.c: New test.
	* gcc.target/i386/pr66232-2.c: Likewise.
	* gcc.target/i386/pr66232-3.c: Likewise.
	* gcc.target/i386/pr66232-4.c: Likewise.
---
 gcc/config/i386/constraints.md            |  6 ++++++
 gcc/config/i386/i386.md                   | 36 +++++++++++++++++++++++++++++++
 gcc/config/i386/predicates.md             | 26 ++++++++++++++++++++++
 gcc/testsuite/gcc.target/i386/pr66232-1.c | 13 +++++++++++
 gcc/testsuite/gcc.target/i386/pr66232-2.c | 14 ++++++++++++
 gcc/testsuite/gcc.target/i386/pr66232-3.c | 13 +++++++++++
 gcc/testsuite/gcc.target/i386/pr66232-4.c | 13 +++++++++++
 7 files changed, 121 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-1.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-2.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-3.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-4.c

diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md
index 2271bd1..7be8917 100644
--- a/gcc/config/i386/constraints.md
+++ b/gcc/config/i386/constraints.md
@@ -146,10 +146,16 @@
  "@internal Lower SSE register when avoiding REX prefix and all SSE registers otherwise.")
 
 ;; We use the B prefix to denote any number of internal operands:
+;;  g  Call and sibcall memory operand, valid for TARGET_X32
 ;;  s  Sibcall memory operand, not valid for TARGET_X32
 ;;  w  Call memory operand, not valid for TARGET_X32
 ;;  z  Constant call address operand.
 
+(define_constraint "Bg"
+  "@internal Call/sibcall memory operand for x32."
+  (and (match_test "TARGET_X32")
+       (match_operand 0 "x32_sibcall_memory_operand")))
+
 (define_constraint "Bs"
   "@internal Sibcall memory operand."
   (and (not (match_test "TARGET_X32"))
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index aefca43..a1ae05a 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -11659,6 +11659,14 @@
   "* return ix86_output_call_insn (insn, operands[0]);"
   [(set_attr "type" "call")])
 
+(define_insn "*call_x32"
+  [(call (mem:QI (zero_extend:DI
+		   (match_operand:SI 0 "x32_call_insn_operand" "Bg")))
+	 (match_operand 1))]
+  "TARGET_X32 && !SIBLING_CALL_P (insn)"
+  "* return ix86_output_call_insn (insn, operands[0]);"
+  [(set_attr "type" "call")])
+
 (define_insn "*sibcall"
   [(call (mem:QI (match_operand:W 0 "sibcall_insn_operand" "UBsBz"))
 	 (match_operand 1))]
@@ -11666,6 +11674,14 @@
   "* return ix86_output_call_insn (insn, operands[0]);"
   [(set_attr "type" "call")])
 
+(define_insn "*sibcall_x32"
+  [(call (mem:QI (zero_extend:DI
+		   (match_operand:SI 0 "x32_sibcall_insn_operand" "Bg")))
+	 (match_operand 1))]
+  "TARGET_X32 && SIBLING_CALL_P (insn)"
+  "* return ix86_output_call_insn (insn, operands[0]);"
+  [(set_attr "type" "call")])
+
 (define_insn "*sibcall_memory"
   [(call (mem:QI (match_operand:W 0 "memory_operand" "m"))
 	 (match_operand 1))
@@ -11825,6 +11841,16 @@
   "* return ix86_output_call_insn (insn, operands[1]);"
   [(set_attr "type" "callv")])
 
+(define_insn "*call_value_x32"
+  [(set (match_operand 0)
+	(call (mem:QI
+		(zero_extend:DI
+		  (match_operand:SI 1 "x32_call_insn_operand" "Bg")))
+	      (match_operand 2)))]
+  "TARGET_X32 && !SIBLING_CALL_P (insn)"
+  "* return ix86_output_call_insn (insn, operands[1]);"
+  [(set_attr "type" "callv")])
+
 (define_insn "*sibcall_value"
   [(set (match_operand 0)
 	(call (mem:QI (match_operand:W 1 "sibcall_insn_operand" "UBsBz"))
@@ -11833,6 +11859,16 @@
   "* return ix86_output_call_insn (insn, operands[1]);"
   [(set_attr "type" "callv")])
 
+(define_insn "*sibcall_value_x32"
+  [(set (match_operand 0)
+	(call (mem:QI
+		(zero_extend:DI
+		  (match_operand:SI 1 "x32_sibcall_insn_operand" "Bg")))
+	      (match_operand 2)))]
+  "TARGET_X32 && SIBLING_CALL_P (insn)"
+  "* return ix86_output_call_insn (insn, operands[1]);"
+  [(set_attr "type" "callv")])
+
 (define_insn "*sibcall_value_memory"
   [(set (match_operand 0)
  	(call (mem:QI (match_operand:W 1 "memory_operand" "m"))
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index 26dd3e1..40fdd20 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -606,6 +606,32 @@
        (and (not (match_test "TARGET_X32"))
 	    (match_operand 0 "sibcall_memory_operand"))))
 
+;; Return true if OP is a memory operand that can be used in x32 calls
+;; and sibcalls.  Only th 64-bit GOT slot is allowed.
+(define_predicate "x32_sibcall_memory_operand"
+  (and (match_operand 0 "memory_operand")
+       (match_test "CONSTANT_P (XEXP (op, 0))")
+       (match_test "GET_CODE (XEXP (XEXP (op, 0), 0)) == UNSPEC")
+       (match_test "XINT (XEXP (XEXP (op, 0), 0), 1) == UNSPEC_GOTPCREL")))
+
+;; Test for a valid operand for an x32 call instruction.
+;; Allow constant call address operands in Pmode only.
+(define_special_predicate "x32_call_insn_operand"
+  (ior (match_test "constant_call_address_operand
+		     (op, mode == VOIDmode ? mode : Pmode)")
+       (match_operand 0 "call_register_no_elim_operand")
+       (and (match_test "TARGET_X32")
+	    (match_operand 0 "x32_sibcall_memory_operand"))))
+
+;; Similarly, but for tail x32 calls, in which we cannot allow memory
+;; references.
+(define_special_predicate "x32_sibcall_insn_operand"
+  (ior (match_test "constant_call_address_operand
+		     (op, mode == VOIDmode ? mode : Pmode)")
+       (match_operand 0 "register_no_elim_operand")
+       (and (match_test "TARGET_X32")
+	    (match_operand 0 "x32_sibcall_memory_operand"))))
+
 ;; Match exactly zero.
 (define_predicate "const0_operand"
   (match_code "const_int,const_wide_int,const_double,const_vector")
diff --git a/gcc/testsuite/gcc.target/i386/pr66232-1.c b/gcc/testsuite/gcc.target/i386/pr66232-1.c
new file mode 100644
index 0000000..ba4a5ef
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr66232-1.c
@@ -0,0 +1,13 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpic -fno-plt" } */
+
+extern void bar (void);
+
+void
+foo (void)
+{
+  bar ();
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]*.bar@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOT\\(" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr66232-2.c b/gcc/testsuite/gcc.target/i386/pr66232-2.c
new file mode 100644
index 0000000..f05d7c5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr66232-2.c
@@ -0,0 +1,14 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpic -fno-plt" } */
+
+extern void bar (void);
+
+int
+foo (void)
+{
+  bar ();
+  return 0;
+}
+
+/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOT\\(" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr66232-3.c b/gcc/testsuite/gcc.target/i386/pr66232-3.c
new file mode 100644
index 0000000..ee3176c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr66232-3.c
@@ -0,0 +1,13 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpic -fno-plt" } */
+
+extern int bar (void);
+
+int
+foo (void)
+{
+  return bar ();
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]*.bar@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOT\\(" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr66232-4.c b/gcc/testsuite/gcc.target/i386/pr66232-4.c
new file mode 100644
index 0000000..5fa0ded
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr66232-4.c
@@ -0,0 +1,13 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpic -fno-plt" } */
+
+extern int bar (void);
+
+int
+foo (void)
+{
+  return bar () + 1;
+}
+
+/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOT\\(" { target ia32 } } } */
-- 
2.1.0

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] PR target/66232: -fPIC -fno-plt -mx32 fails to generate indirect branch via GOT
  2015-05-21 13:05 [PATCH] PR target/66232: -fPIC -fno-plt -mx32 fails to generate indirect branch via GOT H.J. Lu
@ 2015-05-21 13:19 ` Uros Bizjak
  2015-05-21 13:40   ` H.J. Lu
  2015-05-21 19:13 ` Richard Henderson
  1 sibling, 1 reply; 16+ messages in thread
From: Uros Bizjak @ 2015-05-21 13:19 UTC (permalink / raw)
  To: H.J. Lu; +Cc: gcc-patches

On Thu, May 21, 2015 at 2:59 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
> X32 doesn't support indirect branch via 32-bit memory slot since
> indirect branch will load 64-bit address from 64-bit memory slot.
> Since x32 GOT slot is 64-bit, we should allow indirect branch via GOT
> slot for x32.
>
> I am testing it on x32.  OK for master if there is no regression?
>
> Thanks.
>
>
> H.J.
> --
> gcc/
>
>         PR target/66232
>         * config/i386/constraints.md (Bg): Add a constraint for x32
>         call and sibcall memory operand.
>         * config/i386/i386.md (*call_x32): New pattern.
>         (*sibcall_x32): Likewise.
>         (*call_value_x32): Likewise.
>         (*sibcall_value_x32): Likewise.
>         * config/i386/predicates.md (x32_sibcall_memory_operand): New
>         predicate.
>         (x32_call_insn_operand): Likewise.
>         (x32_sibcall_insn_operand): Likewise.
>
> gcc/testsuite/
>
>         PR target/66232
>         * gcc.target/i386/pr66232-1.c: New test.
>         * gcc.target/i386/pr66232-2.c: Likewise.
>         * gcc.target/i386/pr66232-3.c: Likewise.
>         * gcc.target/i386/pr66232-4.c: Likewise.

OK.

maybe you should use match_code some more in x32_sibcall_memory_operand, e.g.

(match_code "constant" "0")
(match_code "unspec" "00")

But it is up to you, since XINT doesn't fit in this scheme...

Thanks,
Uros.

>  gcc/config/i386/constraints.md            |  6 ++++++
>  gcc/config/i386/i386.md                   | 36 +++++++++++++++++++++++++++++++
>  gcc/config/i386/predicates.md             | 26 ++++++++++++++++++++++
>  gcc/testsuite/gcc.target/i386/pr66232-1.c | 13 +++++++++++
>  gcc/testsuite/gcc.target/i386/pr66232-2.c | 14 ++++++++++++
>  gcc/testsuite/gcc.target/i386/pr66232-3.c | 13 +++++++++++
>  gcc/testsuite/gcc.target/i386/pr66232-4.c | 13 +++++++++++
>  7 files changed, 121 insertions(+)
>  create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-1.c
>  create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-2.c
>  create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-3.c
>  create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-4.c
>
> diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md
> index 2271bd1..7be8917 100644
> --- a/gcc/config/i386/constraints.md
> +++ b/gcc/config/i386/constraints.md
> @@ -146,10 +146,16 @@
>   "@internal Lower SSE register when avoiding REX prefix and all SSE registers otherwise.")
>
>  ;; We use the B prefix to denote any number of internal operands:
> +;;  g  Call and sibcall memory operand, valid for TARGET_X32
>  ;;  s  Sibcall memory operand, not valid for TARGET_X32
>  ;;  w  Call memory operand, not valid for TARGET_X32
>  ;;  z  Constant call address operand.
>
> +(define_constraint "Bg"
> +  "@internal Call/sibcall memory operand for x32."
> +  (and (match_test "TARGET_X32")
> +       (match_operand 0 "x32_sibcall_memory_operand")))
> +
>  (define_constraint "Bs"
>    "@internal Sibcall memory operand."
>    (and (not (match_test "TARGET_X32"))
> diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
> index aefca43..a1ae05a 100644
> --- a/gcc/config/i386/i386.md
> +++ b/gcc/config/i386/i386.md
> @@ -11659,6 +11659,14 @@
>    "* return ix86_output_call_insn (insn, operands[0]);"
>    [(set_attr "type" "call")])
>
> +(define_insn "*call_x32"
> +  [(call (mem:QI (zero_extend:DI
> +                  (match_operand:SI 0 "x32_call_insn_operand" "Bg")))
> +        (match_operand 1))]
> +  "TARGET_X32 && !SIBLING_CALL_P (insn)"
> +  "* return ix86_output_call_insn (insn, operands[0]);"
> +  [(set_attr "type" "call")])
> +
>  (define_insn "*sibcall"
>    [(call (mem:QI (match_operand:W 0 "sibcall_insn_operand" "UBsBz"))
>          (match_operand 1))]
> @@ -11666,6 +11674,14 @@
>    "* return ix86_output_call_insn (insn, operands[0]);"
>    [(set_attr "type" "call")])
>
> +(define_insn "*sibcall_x32"
> +  [(call (mem:QI (zero_extend:DI
> +                  (match_operand:SI 0 "x32_sibcall_insn_operand" "Bg")))
> +        (match_operand 1))]
> +  "TARGET_X32 && SIBLING_CALL_P (insn)"
> +  "* return ix86_output_call_insn (insn, operands[0]);"
> +  [(set_attr "type" "call")])
> +
>  (define_insn "*sibcall_memory"
>    [(call (mem:QI (match_operand:W 0 "memory_operand" "m"))
>          (match_operand 1))
> @@ -11825,6 +11841,16 @@
>    "* return ix86_output_call_insn (insn, operands[1]);"
>    [(set_attr "type" "callv")])
>
> +(define_insn "*call_value_x32"
> +  [(set (match_operand 0)
> +       (call (mem:QI
> +               (zero_extend:DI
> +                 (match_operand:SI 1 "x32_call_insn_operand" "Bg")))
> +             (match_operand 2)))]
> +  "TARGET_X32 && !SIBLING_CALL_P (insn)"
> +  "* return ix86_output_call_insn (insn, operands[1]);"
> +  [(set_attr "type" "callv")])
> +
>  (define_insn "*sibcall_value"
>    [(set (match_operand 0)
>         (call (mem:QI (match_operand:W 1 "sibcall_insn_operand" "UBsBz"))
> @@ -11833,6 +11859,16 @@
>    "* return ix86_output_call_insn (insn, operands[1]);"
>    [(set_attr "type" "callv")])
>
> +(define_insn "*sibcall_value_x32"
> +  [(set (match_operand 0)
> +       (call (mem:QI
> +               (zero_extend:DI
> +                 (match_operand:SI 1 "x32_sibcall_insn_operand" "Bg")))
> +             (match_operand 2)))]
> +  "TARGET_X32 && SIBLING_CALL_P (insn)"
> +  "* return ix86_output_call_insn (insn, operands[1]);"
> +  [(set_attr "type" "callv")])
> +
>  (define_insn "*sibcall_value_memory"
>    [(set (match_operand 0)
>         (call (mem:QI (match_operand:W 1 "memory_operand" "m"))
> diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
> index 26dd3e1..40fdd20 100644
> --- a/gcc/config/i386/predicates.md
> +++ b/gcc/config/i386/predicates.md
> @@ -606,6 +606,32 @@
>         (and (not (match_test "TARGET_X32"))
>             (match_operand 0 "sibcall_memory_operand"))))
>
> +;; Return true if OP is a memory operand that can be used in x32 calls
> +;; and sibcalls.  Only th 64-bit GOT slot is allowed.
> +(define_predicate "x32_sibcall_memory_operand"
> +  (and (match_operand 0 "memory_operand")
> +       (match_test "CONSTANT_P (XEXP (op, 0))")
> +       (match_test "GET_CODE (XEXP (XEXP (op, 0), 0)) == UNSPEC")
> +       (match_test "XINT (XEXP (XEXP (op, 0), 0), 1) == UNSPEC_GOTPCREL")))
> +
> +;; Test for a valid operand for an x32 call instruction.
> +;; Allow constant call address operands in Pmode only.
> +(define_special_predicate "x32_call_insn_operand"
> +  (ior (match_test "constant_call_address_operand
> +                    (op, mode == VOIDmode ? mode : Pmode)")
> +       (match_operand 0 "call_register_no_elim_operand")
> +       (and (match_test "TARGET_X32")
> +           (match_operand 0 "x32_sibcall_memory_operand"))))
> +
> +;; Similarly, but for tail x32 calls, in which we cannot allow memory
> +;; references.
> +(define_special_predicate "x32_sibcall_insn_operand"
> +  (ior (match_test "constant_call_address_operand
> +                    (op, mode == VOIDmode ? mode : Pmode)")
> +       (match_operand 0 "register_no_elim_operand")
> +       (and (match_test "TARGET_X32")
> +           (match_operand 0 "x32_sibcall_memory_operand"))))
> +
>  ;; Match exactly zero.
>  (define_predicate "const0_operand"
>    (match_code "const_int,const_wide_int,const_double,const_vector")
> diff --git a/gcc/testsuite/gcc.target/i386/pr66232-1.c b/gcc/testsuite/gcc.target/i386/pr66232-1.c
> new file mode 100644
> index 0000000..ba4a5ef
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr66232-1.c
> @@ -0,0 +1,13 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-options "-O2 -fpic -fno-plt" } */
> +
> +extern void bar (void);
> +
> +void
> +foo (void)
> +{
> +  bar ();
> +}
> +
> +/* { dg-final { scan-assembler "jmp\[ \t\]*.bar@GOTPCREL" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOT\\(" { target ia32 } } } */
> diff --git a/gcc/testsuite/gcc.target/i386/pr66232-2.c b/gcc/testsuite/gcc.target/i386/pr66232-2.c
> new file mode 100644
> index 0000000..f05d7c5
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr66232-2.c
> @@ -0,0 +1,14 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-options "-O2 -fpic -fno-plt" } */
> +
> +extern void bar (void);
> +
> +int
> +foo (void)
> +{
> +  bar ();
> +  return 0;
> +}
> +
> +/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOTPCREL" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOT\\(" { target ia32 } } } */
> diff --git a/gcc/testsuite/gcc.target/i386/pr66232-3.c b/gcc/testsuite/gcc.target/i386/pr66232-3.c
> new file mode 100644
> index 0000000..ee3176c
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr66232-3.c
> @@ -0,0 +1,13 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-options "-O2 -fpic -fno-plt" } */
> +
> +extern int bar (void);
> +
> +int
> +foo (void)
> +{
> +  return bar ();
> +}
> +
> +/* { dg-final { scan-assembler "jmp\[ \t\]*.bar@GOTPCREL" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOT\\(" { target ia32 } } } */
> diff --git a/gcc/testsuite/gcc.target/i386/pr66232-4.c b/gcc/testsuite/gcc.target/i386/pr66232-4.c
> new file mode 100644
> index 0000000..5fa0ded
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr66232-4.c
> @@ -0,0 +1,13 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-options "-O2 -fpic -fno-plt" } */
> +
> +extern int bar (void);
> +
> +int
> +foo (void)
> +{
> +  return bar () + 1;
> +}
> +
> +/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOTPCREL" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOT\\(" { target ia32 } } } */
> --
> 2.1.0
>

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] PR target/66232: -fPIC -fno-plt -mx32 fails to generate indirect branch via GOT
  2015-05-21 13:19 ` Uros Bizjak
@ 2015-05-21 13:40   ` H.J. Lu
  2015-05-21 17:16     ` H.J. Lu
  0 siblings, 1 reply; 16+ messages in thread
From: H.J. Lu @ 2015-05-21 13:40 UTC (permalink / raw)
  To: Uros Bizjak; +Cc: gcc-patches

On Thu, May 21, 2015 at 6:11 AM, Uros Bizjak <ubizjak@gmail.com> wrote:
> On Thu, May 21, 2015 at 2:59 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
>> X32 doesn't support indirect branch via 32-bit memory slot since
>> indirect branch will load 64-bit address from 64-bit memory slot.
>> Since x32 GOT slot is 64-bit, we should allow indirect branch via GOT
>> slot for x32.
>>
>> I am testing it on x32.  OK for master if there is no regression?
>>
>> Thanks.
>>
>>
>> H.J.
>> --
>> gcc/
>>
>>         PR target/66232
>>         * config/i386/constraints.md (Bg): Add a constraint for x32
>>         call and sibcall memory operand.
>>         * config/i386/i386.md (*call_x32): New pattern.
>>         (*sibcall_x32): Likewise.
>>         (*call_value_x32): Likewise.
>>         (*sibcall_value_x32): Likewise.
>>         * config/i386/predicates.md (x32_sibcall_memory_operand): New
>>         predicate.
>>         (x32_call_insn_operand): Likewise.
>>         (x32_sibcall_insn_operand): Likewise.
>>
>> gcc/testsuite/
>>
>>         PR target/66232
>>         * gcc.target/i386/pr66232-1.c: New test.
>>         * gcc.target/i386/pr66232-2.c: Likewise.
>>         * gcc.target/i386/pr66232-3.c: Likewise.
>>         * gcc.target/i386/pr66232-4.c: Likewise.
>
> OK.
>
> maybe you should use match_code some more in x32_sibcall_memory_operand, e.g.
>
> (match_code "constant" "0")
> (match_code "unspec" "00")
>
> But it is up to you, since XINT doesn't fit in this scheme...
>

>>
>> +;; Return true if OP is a memory operand that can be used in x32 calls
>> +;; and sibcalls.  Only th 64-bit GOT slot is allowed.
>> +(define_predicate "x32_sibcall_memory_operand"
>> +  (and (match_operand 0 "memory_operand")
>> +       (match_test "CONSTANT_P (XEXP (op, 0))")
>> +       (match_test "GET_CODE (XEXP (XEXP (op, 0), 0)) == UNSPEC")
>> +       (match_test "XINT (XEXP (XEXP (op, 0), 0), 1) == UNSPEC_GOTPCREL")))
>> +

Since "match_code" doesn't support "constant" neither

#define CONSTANT_P(X)   \
  (GET_RTX_CLASS (GET_CODE (X)) == RTX_CONST_OBJ)

I will keep it asis.

Thanks.

-- 
H.J.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] PR target/66232: -fPIC -fno-plt -mx32 fails to generate indirect branch via GOT
  2015-05-21 13:40   ` H.J. Lu
@ 2015-05-21 17:16     ` H.J. Lu
  2015-05-21 18:36       ` Uros Bizjak
  0 siblings, 1 reply; 16+ messages in thread
From: H.J. Lu @ 2015-05-21 17:16 UTC (permalink / raw)
  To: Uros Bizjak; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 3204 bytes --]

On Thu, May 21, 2015 at 6:33 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Thu, May 21, 2015 at 6:11 AM, Uros Bizjak <ubizjak@gmail.com> wrote:
>> On Thu, May 21, 2015 at 2:59 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
>>> X32 doesn't support indirect branch via 32-bit memory slot since
>>> indirect branch will load 64-bit address from 64-bit memory slot.
>>> Since x32 GOT slot is 64-bit, we should allow indirect branch via GOT
>>> slot for x32.
>>>
>>> I am testing it on x32.  OK for master if there is no regression?
>>>
>>> Thanks.
>>>
>>>
>>> H.J.
>>> --
>>> gcc/
>>>
>>>         PR target/66232
>>>         * config/i386/constraints.md (Bg): Add a constraint for x32
>>>         call and sibcall memory operand.
>>>         * config/i386/i386.md (*call_x32): New pattern.
>>>         (*sibcall_x32): Likewise.
>>>         (*call_value_x32): Likewise.
>>>         (*sibcall_value_x32): Likewise.
>>>         * config/i386/predicates.md (x32_sibcall_memory_operand): New
>>>         predicate.
>>>         (x32_call_insn_operand): Likewise.
>>>         (x32_sibcall_insn_operand): Likewise.
>>>
>>> gcc/testsuite/
>>>
>>>         PR target/66232
>>>         * gcc.target/i386/pr66232-1.c: New test.
>>>         * gcc.target/i386/pr66232-2.c: Likewise.
>>>         * gcc.target/i386/pr66232-3.c: Likewise.
>>>         * gcc.target/i386/pr66232-4.c: Likewise.
>>
>> OK.
>>
>> maybe you should use match_code some more in x32_sibcall_memory_operand, e.g.
>>
>> (match_code "constant" "0")
>> (match_code "unspec" "00")
>>
>> But it is up to you, since XINT doesn't fit in this scheme...
>>
>
>>>
>>> +;; Return true if OP is a memory operand that can be used in x32 calls
>>> +;; and sibcalls.  Only th 64-bit GOT slot is allowed.
>>> +(define_predicate "x32_sibcall_memory_operand"
>>> +  (and (match_operand 0 "memory_operand")
>>> +       (match_test "CONSTANT_P (XEXP (op, 0))")
>>> +       (match_test "GET_CODE (XEXP (XEXP (op, 0), 0)) == UNSPEC")
>>> +       (match_test "XINT (XEXP (XEXP (op, 0), 0), 1) == UNSPEC_GOTPCREL")))
>>> +
>
> Since "match_code" doesn't support "constant" neither
>
> #define CONSTANT_P(X)   \
>   (GET_RTX_CLASS (GET_CODE (X)) == RTX_CONST_OBJ)
>
> I will keep it asis.

Here is the updated patch.  It limited memory operand to
GOT slot only.  It used a single pattern to cover both call
and sibcall since only GOT slot is allowed.

OK for master if there is no regression?

Thanks.


-- 
H.J.
---
X32 doesn't support indirect branch via 32-bit memory slot since
indirect branch will load 64-bit address from 64-bit memory slot.
Since x32 GOT slot is 64-bit, we should allow indirect branch via GOT
slot for x32.

gcc/

PR target/66232
* config/i386/constraints.md (Bg): Add a constraint for x32
call and sibcall memory operand.
* config/i386/i386.md (*call_got_x32): New pattern.
(*call_value_got_x32): Likewise.
* config/i386/predicates.md (x32_call_got_memory_operand): New
predicate.
(x32_call_insn_got_operand): Likewise.

gcc/testsuite/

PR target/66232
* gcc.target/i386/pr66232-1.c: New test.
* gcc.target/i386/pr66232-2.c: Likewise.
* gcc.target/i386/pr66232-3.c: Likewise.
* gcc.target/i386/pr66232-4.c: Likewise.
* gcc.target/i386/pr66232-5.c: Likewise.

[-- Attachment #2: 0001-Allow-indirect-branch-via-GOT-slot-for-x32.patch --]
[-- Type: text/x-patch, Size: 7833 bytes --]

From 8eb3d88948e95b25ae889fcec5502a2a8dba6347 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Thu, 21 May 2015 05:50:14 -0700
Subject: [PATCH] Allow indirect branch via GOT slot for x32

X32 doesn't support indirect branch via 32-bit memory slot since
indirect branch will load 64-bit address from 64-bit memory slot.
Since x32 GOT slot is 64-bit, we should allow indirect branch via GOT
slot for x32.

gcc/

	PR target/66232
	* config/i386/constraints.md (Bg): Add a constraint for x32
	call and sibcall memory operand.
	* config/i386/i386.md (*call_got_x32): New pattern.
	(*call_value_got_x32): Likewise.
	* config/i386/predicates.md (x32_call_got_memory_operand): New
	predicate.
	(x32_call_insn_got_operand): Likewise.

gcc/testsuite/

	PR target/66232
	* gcc.target/i386/pr66232-1.c: New test.
	* gcc.target/i386/pr66232-2.c: Likewise.
	* gcc.target/i386/pr66232-3.c: Likewise.
	* gcc.target/i386/pr66232-4.c: Likewise.
	* gcc.target/i386/pr66232-5.c: Likewise.
---
 gcc/config/i386/constraints.md            |  6 ++++++
 gcc/config/i386/i386.md                   | 20 ++++++++++++++++++++
 gcc/config/i386/predicates.md             | 14 ++++++++++++++
 gcc/testsuite/gcc.target/i386/pr66232-1.c | 13 +++++++++++++
 gcc/testsuite/gcc.target/i386/pr66232-2.c | 14 ++++++++++++++
 gcc/testsuite/gcc.target/i386/pr66232-3.c | 13 +++++++++++++
 gcc/testsuite/gcc.target/i386/pr66232-4.c | 13 +++++++++++++
 gcc/testsuite/gcc.target/i386/pr66232-5.c | 16 ++++++++++++++++
 8 files changed, 109 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-1.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-2.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-3.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-4.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-5.c

diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md
index 2271bd1..4ec9821 100644
--- a/gcc/config/i386/constraints.md
+++ b/gcc/config/i386/constraints.md
@@ -146,10 +146,16 @@
  "@internal Lower SSE register when avoiding REX prefix and all SSE registers otherwise.")
 
 ;; We use the B prefix to denote any number of internal operands:
+;;  g  Call and sibcall memory operand, valid for TARGET_X32
 ;;  s  Sibcall memory operand, not valid for TARGET_X32
 ;;  w  Call memory operand, not valid for TARGET_X32
 ;;  z  Constant call address operand.
 
+(define_constraint "Bg"
+  "@internal Call/sibcall GOT memory operand for x32."
+  (and (match_test "TARGET_X32")
+       (match_operand 0 "x32_call_got_memory_operand")))
+
 (define_constraint "Bs"
   "@internal Sibcall memory operand."
   (and (not (match_test "TARGET_X32"))
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index aefca43..158a3ed 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -11659,6 +11659,15 @@
   "* return ix86_output_call_insn (insn, operands[0]);"
   [(set_attr "type" "call")])
 
+;; This covers both call and sibcall since only GOT slot is allowed.
+(define_insn "*call_got_x32"
+  [(call (mem:QI (zero_extend:DI
+		   (match_operand:SI 0 "x32_call_insn_got_operand" "Bg")))
+	 (match_operand 1))]
+  "TARGET_X32"
+  "* return ix86_output_call_insn (insn, operands[0]);"
+  [(set_attr "type" "call")])
+
 (define_insn "*sibcall"
   [(call (mem:QI (match_operand:W 0 "sibcall_insn_operand" "UBsBz"))
 	 (match_operand 1))]
@@ -11825,6 +11834,17 @@
   "* return ix86_output_call_insn (insn, operands[1]);"
   [(set_attr "type" "callv")])
 
+;; This covers both call and sibcall since only GOT slot is allowed.
+(define_insn "*call_value_got_x32"
+  [(set (match_operand 0)
+	(call (mem:QI
+		(zero_extend:DI
+		  (match_operand:SI 1 "x32_call_insn_got_operand" "Bg")))
+	      (match_operand 2)))]
+  "TARGET_X32"
+  "* return ix86_output_call_insn (insn, operands[1]);"
+  [(set_attr "type" "callv")])
+
 (define_insn "*sibcall_value"
   [(set (match_operand 0)
 	(call (mem:QI (match_operand:W 1 "sibcall_insn_operand" "UBsBz"))
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index 26dd3e1..166893e 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -606,6 +606,20 @@
        (and (not (match_test "TARGET_X32"))
 	    (match_operand 0 "sibcall_memory_operand"))))
 
+;; Return true if OP is a GOT memory operand that can be used in x32 calls
+;; and sibcalls.
+(define_predicate "x32_call_got_memory_operand"
+  (and (match_operand 0 "memory_operand")
+       (match_test "CONSTANT_P (XEXP (op, 0))")
+       (match_test "GET_CODE (XEXP (XEXP (op, 0), 0)) == UNSPEC")
+       (match_test "XINT (XEXP (XEXP (op, 0), 0), 1) == UNSPEC_GOTPCREL")))
+
+;; Test for a valid operand for an x32 call/sibcall instruction via
+;; memory.  Only the 64-bit GOT slot is allowed.
+(define_special_predicate "x32_call_insn_got_operand"
+  (and (match_test "TARGET_X32")
+       (match_operand 0 "x32_call_got_memory_operand")))
+
 ;; Match exactly zero.
 (define_predicate "const0_operand"
   (match_code "const_int,const_wide_int,const_double,const_vector")
diff --git a/gcc/testsuite/gcc.target/i386/pr66232-1.c b/gcc/testsuite/gcc.target/i386/pr66232-1.c
new file mode 100644
index 0000000..ba4a5ef
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr66232-1.c
@@ -0,0 +1,13 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpic -fno-plt" } */
+
+extern void bar (void);
+
+void
+foo (void)
+{
+  bar ();
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]*.bar@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOT\\(" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr66232-2.c b/gcc/testsuite/gcc.target/i386/pr66232-2.c
new file mode 100644
index 0000000..f05d7c5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr66232-2.c
@@ -0,0 +1,14 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpic -fno-plt" } */
+
+extern void bar (void);
+
+int
+foo (void)
+{
+  bar ();
+  return 0;
+}
+
+/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOT\\(" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr66232-3.c b/gcc/testsuite/gcc.target/i386/pr66232-3.c
new file mode 100644
index 0000000..ee3176c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr66232-3.c
@@ -0,0 +1,13 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpic -fno-plt" } */
+
+extern int bar (void);
+
+int
+foo (void)
+{
+  return bar ();
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]*.bar@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOT\\(" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr66232-4.c b/gcc/testsuite/gcc.target/i386/pr66232-4.c
new file mode 100644
index 0000000..5fa0ded
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr66232-4.c
@@ -0,0 +1,13 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpic -fno-plt" } */
+
+extern int bar (void);
+
+int
+foo (void)
+{
+  return bar () + 1;
+}
+
+/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOT\\(" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr66232-5.c b/gcc/testsuite/gcc.target/i386/pr66232-5.c
new file mode 100644
index 0000000..c016717
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr66232-5.c
@@ -0,0 +1,16 @@
+/* { dg-do compile { target { ! { ia32 } } } } */
+/* { dg-require-effective-target maybe_x32 } */
+/* { dg-options "-O2 -fpic -mx32" } */
+
+extern void (*bar) (void);
+void
+foo (int n)
+{
+  int i;
+  for (i = 0; i < n; i++)
+    {
+      if (!bar)
+	continue;
+      (*bar) ();
+    }
+}
-- 
1.9.3


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] PR target/66232: -fPIC -fno-plt -mx32 fails to generate indirect branch via GOT
  2015-05-21 17:16     ` H.J. Lu
@ 2015-05-21 18:36       ` Uros Bizjak
  2015-05-21 19:01         ` H.J. Lu
  0 siblings, 1 reply; 16+ messages in thread
From: Uros Bizjak @ 2015-05-21 18:36 UTC (permalink / raw)
  To: H.J. Lu; +Cc: gcc-patches

On Thu, May 21, 2015 at 7:01 PM, H.J. Lu <hjl.tools@gmail.com> wrote:

> Here is the updated patch.  It limited memory operand to
> GOT slot only.  It used a single pattern to cover both call
> and sibcall since only GOT slot is allowed.
>
> OK for master if there is no regression?
>
> Thanks.
>
>
> --
> H.J.
> ---
> X32 doesn't support indirect branch via 32-bit memory slot since
> indirect branch will load 64-bit address from 64-bit memory slot.
> Since x32 GOT slot is 64-bit, we should allow indirect branch via GOT
> slot for x32.
>
> gcc/
>
> PR target/66232
> * config/i386/constraints.md (Bg): Add a constraint for x32
> call and sibcall memory operand.
> * config/i386/i386.md (*call_got_x32): New pattern.
> (*call_value_got_x32): Likewise.
> * config/i386/predicates.md (x32_call_got_memory_operand): New
> predicate.
> (x32_call_insn_got_operand): Likewise.
>
> gcc/testsuite/
>
> PR target/66232
> * gcc.target/i386/pr66232-1.c: New test.
> * gcc.target/i386/pr66232-2.c: Likewise.
> * gcc.target/i386/pr66232-3.c: Likewise.
> * gcc.target/i386/pr66232-4.c: Likewise.
> * gcc.target/i386/pr66232-5.c: Likewise.

diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md
index 2271bd1..4ec9821 100644
--- a/gcc/config/i386/constraints.md
+++ b/gcc/config/i386/constraints.md
@@ -146,10 +146,16 @@
  "@internal Lower SSE register when avoiding REX prefix and all SSE
registers otherwise.")

 ;; We use the B prefix to denote any number of internal operands:
+;;  g  Call and sibcall memory operand, valid for TARGET_X32
 ;;  s  Sibcall memory operand, not valid for TARGET_X32
 ;;  w  Call memory operand, not valid for TARGET_X32
 ;;  z  Constant call address operand.

+(define_constraint "Bg"
+  "@internal Call/sibcall GOT memory operand for x32."
+  (and (match_test "TARGET_X32")
+       (match_operand 0 "x32_call_got_memory_operand")))

No need for TARGET_X32, when all insn patterns are protected by it.
And the predicate is not x32 specific. And not call specific, so
"@internal GOT memory operand". Please use "GOT_memory_operand"
predicate, see below.

 (define_constraint "Bs"
   "@internal Sibcall memory operand."
   (and (not (match_test "TARGET_X32"))
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index aefca43..158a3ed 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -11659,6 +11659,15 @@
   "* return ix86_output_call_insn (insn, operands[0]);"
   [(set_attr "type" "call")])

+;; This covers both call and sibcall since only GOT slot is allowed.
+(define_insn "*call_got_x32"
+  [(call (mem:QI (zero_extend:DI
+           (match_operand:SI 0 "x32_call_insn_got_operand" "Bg")))
+     (match_operand 1))]
+  "TARGET_X32"
+  "* return ix86_output_call_insn (insn, operands[0]);"
+  [(set_attr "type" "call")])

"GOT_memory_operand" in the above pattern and all other call patterns.

 (define_insn "*sibcall"
   [(call (mem:QI (match_operand:W 0 "sibcall_insn_operand" "UBsBz"))
      (match_operand 1))]
@@ -11825,6 +11834,17 @@
   "* return ix86_output_call_insn (insn, operands[1]);"
   [(set_attr "type" "callv")])

+;; This covers both call and sibcall since only GOT slot is allowed.
+(define_insn "*call_value_got_x32"
+  [(set (match_operand 0)
+    (call (mem:QI
+        (zero_extend:DI
+          (match_operand:SI 1 "x32_call_insn_got_operand" "Bg")))
+          (match_operand 2)))]
+  "TARGET_X32"
+  "* return ix86_output_call_insn (insn, operands[1]);"
+  [(set_attr "type" "callv")])
+
 (define_insn "*sibcall_value"
   [(set (match_operand 0)
     (call (mem:QI (match_operand:W 1 "sibcall_insn_operand" "UBsBz"))
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index 26dd3e1..166893e 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -606,6 +606,20 @@
        (and (not (match_test "TARGET_X32"))
         (match_operand 0 "sibcall_memory_operand"))))

+;; Return true if OP is a GOT memory operand that can be used in x32 calls
+;; and sibcalls.
+(define_predicate "x32_call_got_memory_operand"
+  (and (match_operand 0 "memory_operand")
+       (match_test "CONSTANT_P (XEXP (op, 0))")
+       (match_test "GET_CODE (XEXP (XEXP (op, 0), 0)) == UNSPEC")
+       (match_test "XINT (XEXP (XEXP (op, 0), 0), 1) == UNSPEC_GOTPCREL")))

There is nothing x32 specific, it is just a GOT memory operand, so
let's name it "GOT_memory_operand".

+;; Test for a valid operand for an x32 call/sibcall instruction via
+;; memory.  Only the 64-bit GOT slot is allowed.
+(define_special_predicate "x32_call_insn_got_operand"
+  (and (match_test "TARGET_X32")
+       (match_operand 0 "x32_call_got_memory_operand")))

The above predicate is not needed, all insns are protected by TARGET_X32.

 ;; Match exactly zero.
 (define_predicate "const0_operand"

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] PR target/66232: -fPIC -fno-plt -mx32 fails to generate indirect branch via GOT
  2015-05-21 18:36       ` Uros Bizjak
@ 2015-05-21 19:01         ` H.J. Lu
  2015-05-21 19:06           ` Uros Bizjak
  0 siblings, 1 reply; 16+ messages in thread
From: H.J. Lu @ 2015-05-21 19:01 UTC (permalink / raw)
  To: Uros Bizjak; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 5898 bytes --]

On Thu, May 21, 2015 at 11:19 AM, Uros Bizjak <ubizjak@gmail.com> wrote:
> On Thu, May 21, 2015 at 7:01 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
>
>> Here is the updated patch.  It limited memory operand to
>> GOT slot only.  It used a single pattern to cover both call
>> and sibcall since only GOT slot is allowed.
>>
>> OK for master if there is no regression?
>>
>> Thanks.
>>
>>
>> --
>> H.J.
>> ---
>> X32 doesn't support indirect branch via 32-bit memory slot since
>> indirect branch will load 64-bit address from 64-bit memory slot.
>> Since x32 GOT slot is 64-bit, we should allow indirect branch via GOT
>> slot for x32.
>>
>> gcc/
>>
>> PR target/66232
>> * config/i386/constraints.md (Bg): Add a constraint for x32
>> call and sibcall memory operand.
>> * config/i386/i386.md (*call_got_x32): New pattern.
>> (*call_value_got_x32): Likewise.
>> * config/i386/predicates.md (x32_call_got_memory_operand): New
>> predicate.
>> (x32_call_insn_got_operand): Likewise.
>>
>> gcc/testsuite/
>>
>> PR target/66232
>> * gcc.target/i386/pr66232-1.c: New test.
>> * gcc.target/i386/pr66232-2.c: Likewise.
>> * gcc.target/i386/pr66232-3.c: Likewise.
>> * gcc.target/i386/pr66232-4.c: Likewise.
>> * gcc.target/i386/pr66232-5.c: Likewise.
>
> diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md
> index 2271bd1..4ec9821 100644
> --- a/gcc/config/i386/constraints.md
> +++ b/gcc/config/i386/constraints.md
> @@ -146,10 +146,16 @@
>   "@internal Lower SSE register when avoiding REX prefix and all SSE
> registers otherwise.")
>
>  ;; We use the B prefix to denote any number of internal operands:
> +;;  g  Call and sibcall memory operand, valid for TARGET_X32
>  ;;  s  Sibcall memory operand, not valid for TARGET_X32
>  ;;  w  Call memory operand, not valid for TARGET_X32
>  ;;  z  Constant call address operand.
>
> +(define_constraint "Bg"
> +  "@internal Call/sibcall GOT memory operand for x32."
> +  (and (match_test "TARGET_X32")
> +       (match_operand 0 "x32_call_got_memory_operand")))
>
> No need for TARGET_X32, when all insn patterns are protected by it.
> And the predicate is not x32 specific. And not call specific, so
> "@internal GOT memory operand". Please use "GOT_memory_operand"
> predicate, see below.
>
>  (define_constraint "Bs"
>    "@internal Sibcall memory operand."
>    (and (not (match_test "TARGET_X32"))
> diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
> index aefca43..158a3ed 100644
> --- a/gcc/config/i386/i386.md
> +++ b/gcc/config/i386/i386.md
> @@ -11659,6 +11659,15 @@
>    "* return ix86_output_call_insn (insn, operands[0]);"
>    [(set_attr "type" "call")])
>
> +;; This covers both call and sibcall since only GOT slot is allowed.
> +(define_insn "*call_got_x32"
> +  [(call (mem:QI (zero_extend:DI
> +           (match_operand:SI 0 "x32_call_insn_got_operand" "Bg")))
> +     (match_operand 1))]
> +  "TARGET_X32"
> +  "* return ix86_output_call_insn (insn, operands[0]);"
> +  [(set_attr "type" "call")])
>
> "GOT_memory_operand" in the above pattern and all other call patterns.
>
>  (define_insn "*sibcall"
>    [(call (mem:QI (match_operand:W 0 "sibcall_insn_operand" "UBsBz"))
>       (match_operand 1))]
> @@ -11825,6 +11834,17 @@
>    "* return ix86_output_call_insn (insn, operands[1]);"
>    [(set_attr "type" "callv")])
>
> +;; This covers both call and sibcall since only GOT slot is allowed.
> +(define_insn "*call_value_got_x32"
> +  [(set (match_operand 0)
> +    (call (mem:QI
> +        (zero_extend:DI
> +          (match_operand:SI 1 "x32_call_insn_got_operand" "Bg")))
> +          (match_operand 2)))]
> +  "TARGET_X32"
> +  "* return ix86_output_call_insn (insn, operands[1]);"
> +  [(set_attr "type" "callv")])
> +
>  (define_insn "*sibcall_value"
>    [(set (match_operand 0)
>      (call (mem:QI (match_operand:W 1 "sibcall_insn_operand" "UBsBz"))
> diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
> index 26dd3e1..166893e 100644
> --- a/gcc/config/i386/predicates.md
> +++ b/gcc/config/i386/predicates.md
> @@ -606,6 +606,20 @@
>         (and (not (match_test "TARGET_X32"))
>          (match_operand 0 "sibcall_memory_operand"))))
>
> +;; Return true if OP is a GOT memory operand that can be used in x32 calls
> +;; and sibcalls.
> +(define_predicate "x32_call_got_memory_operand"
> +  (and (match_operand 0 "memory_operand")
> +       (match_test "CONSTANT_P (XEXP (op, 0))")
> +       (match_test "GET_CODE (XEXP (XEXP (op, 0), 0)) == UNSPEC")
> +       (match_test "XINT (XEXP (XEXP (op, 0), 0), 1) == UNSPEC_GOTPCREL")))
>
> There is nothing x32 specific, it is just a GOT memory operand, so
> let's name it "GOT_memory_operand".
>
> +;; Test for a valid operand for an x32 call/sibcall instruction via
> +;; memory.  Only the 64-bit GOT slot is allowed.
> +(define_special_predicate "x32_call_insn_got_operand"
> +  (and (match_test "TARGET_X32")
> +       (match_operand 0 "x32_call_got_memory_operand")))
>
> The above predicate is not needed, all insns are protected by TARGET_X32.
>
>  ;; Match exactly zero.
>  (define_predicate "const0_operand"

I am testing this now.  I will check it in if there is no regression.

Thanks.

-- 
H.J.
---
X32 doesn't support indirect branch via 32-bit memory slot since
indirect branch will load 64-bit address from 64-bit memory slot.
Since x32 GOT slot is 64-bit, we should allow indirect branch via GOT
slot for x32.

gcc/

PR target/66232
* config/i386/constraints.md (Bg): New.  A constraint for GOT
memory operand.
* config/i386/i386.md (*call_got_x32): New pattern.
(*call_value_got_x32): Likewise.
* config/i386/predicates.md (GOT_memory_operand): New predicate.

gcc/testsuite/

PR target/66232
* gcc.target/i386/pr66232-1.c: New test.
* gcc.target/i386/pr66232-2.c: Likewise.
* gcc.target/i386/pr66232-3.c: Likewise.
* gcc.target/i386/pr66232-4.c: Likewise.
* gcc.target/i386/pr66232-5.c: Likewise.

[-- Attachment #2: 0001-Allow-indirect-branch-via-GOT-slot-for-x32.patch --]
[-- Type: text/x-patch, Size: 7318 bytes --]

From da4bc478e87481b02152d23ce154ba28a0e52300 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Thu, 21 May 2015 05:50:14 -0700
Subject: [PATCH] Allow indirect branch via GOT slot for x32

X32 doesn't support indirect branch via 32-bit memory slot since
indirect branch will load 64-bit address from 64-bit memory slot.
Since x32 GOT slot is 64-bit, we should allow indirect branch via GOT
slot for x32.

gcc/

	PR target/66232
	* config/i386/constraints.md (Bg): New.  A constraint for GOT
	memory operand.
	* config/i386/i386.md (*call_got_x32): New pattern.
	(*call_value_got_x32): Likewise.
	* config/i386/predicates.md (GOT_memory_operand): New predicate.

gcc/testsuite/

	PR target/66232
	* gcc.target/i386/pr66232-1.c: New test.
	* gcc.target/i386/pr66232-2.c: Likewise.
	* gcc.target/i386/pr66232-3.c: Likewise.
	* gcc.target/i386/pr66232-4.c: Likewise.
	* gcc.target/i386/pr66232-5.c: Likewise.
---
 gcc/config/i386/constraints.md            |  5 +++++
 gcc/config/i386/i386.md                   | 20 ++++++++++++++++++++
 gcc/config/i386/predicates.md             |  7 +++++++
 gcc/testsuite/gcc.target/i386/pr66232-1.c | 13 +++++++++++++
 gcc/testsuite/gcc.target/i386/pr66232-2.c | 14 ++++++++++++++
 gcc/testsuite/gcc.target/i386/pr66232-3.c | 13 +++++++++++++
 gcc/testsuite/gcc.target/i386/pr66232-4.c | 13 +++++++++++++
 gcc/testsuite/gcc.target/i386/pr66232-5.c | 16 ++++++++++++++++
 8 files changed, 101 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-1.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-2.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-3.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-4.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-5.c

diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md
index 2271bd1..c718bc1 100644
--- a/gcc/config/i386/constraints.md
+++ b/gcc/config/i386/constraints.md
@@ -146,10 +146,15 @@
  "@internal Lower SSE register when avoiding REX prefix and all SSE registers otherwise.")
 
 ;; We use the B prefix to denote any number of internal operands:
+;;  g  GOT memory operand.
 ;;  s  Sibcall memory operand, not valid for TARGET_X32
 ;;  w  Call memory operand, not valid for TARGET_X32
 ;;  z  Constant call address operand.
 
+(define_constraint "Bg"
+  "@internal GOT memory operand."
+  (match_operand 0 "GOT_memory_operand"))
+
 (define_constraint "Bs"
   "@internal Sibcall memory operand."
   (and (not (match_test "TARGET_X32"))
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index aefca43..3819dfd 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -11659,6 +11659,15 @@
   "* return ix86_output_call_insn (insn, operands[0]);"
   [(set_attr "type" "call")])
 
+;; This covers both call and sibcall since only GOT slot is allowed.
+(define_insn "*call_got_x32"
+  [(call (mem:QI (zero_extend:DI
+		   (match_operand:SI 0 "GOT_memory_operand" "Bg")))
+	 (match_operand 1))]
+  "TARGET_X32"
+  "* return ix86_output_call_insn (insn, operands[0]);"
+  [(set_attr "type" "call")])
+
 (define_insn "*sibcall"
   [(call (mem:QI (match_operand:W 0 "sibcall_insn_operand" "UBsBz"))
 	 (match_operand 1))]
@@ -11825,6 +11834,17 @@
   "* return ix86_output_call_insn (insn, operands[1]);"
   [(set_attr "type" "callv")])
 
+;; This covers both call and sibcall since only GOT slot is allowed.
+(define_insn "*call_value_got_x32"
+  [(set (match_operand 0)
+	(call (mem:QI
+		(zero_extend:DI
+		  (match_operand:SI 1 "GOT_memory_operand" "Bg")))
+	      (match_operand 2)))]
+  "TARGET_X32"
+  "* return ix86_output_call_insn (insn, operands[1]);"
+  [(set_attr "type" "callv")])
+
 (define_insn "*sibcall_value"
   [(set (match_operand 0)
 	(call (mem:QI (match_operand:W 1 "sibcall_insn_operand" "UBsBz"))
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index 26dd3e1..009aa24 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -606,6 +606,13 @@
        (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"
+  (and (match_operand 0 "memory_operand")
+       (match_test "CONSTANT_P (XEXP (op, 0))")
+       (match_test "GET_CODE (XEXP (XEXP (op, 0), 0)) == UNSPEC")
+       (match_test "XINT (XEXP (XEXP (op, 0), 0), 1) == UNSPEC_GOTPCREL")))
+
 ;; Match exactly zero.
 (define_predicate "const0_operand"
   (match_code "const_int,const_wide_int,const_double,const_vector")
diff --git a/gcc/testsuite/gcc.target/i386/pr66232-1.c b/gcc/testsuite/gcc.target/i386/pr66232-1.c
new file mode 100644
index 0000000..ba4a5ef
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr66232-1.c
@@ -0,0 +1,13 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpic -fno-plt" } */
+
+extern void bar (void);
+
+void
+foo (void)
+{
+  bar ();
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]*.bar@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOT\\(" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr66232-2.c b/gcc/testsuite/gcc.target/i386/pr66232-2.c
new file mode 100644
index 0000000..f05d7c5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr66232-2.c
@@ -0,0 +1,14 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpic -fno-plt" } */
+
+extern void bar (void);
+
+int
+foo (void)
+{
+  bar ();
+  return 0;
+}
+
+/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOT\\(" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr66232-3.c b/gcc/testsuite/gcc.target/i386/pr66232-3.c
new file mode 100644
index 0000000..ee3176c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr66232-3.c
@@ -0,0 +1,13 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpic -fno-plt" } */
+
+extern int bar (void);
+
+int
+foo (void)
+{
+  return bar ();
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]*.bar@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOT\\(" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr66232-4.c b/gcc/testsuite/gcc.target/i386/pr66232-4.c
new file mode 100644
index 0000000..5fa0ded
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr66232-4.c
@@ -0,0 +1,13 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpic -fno-plt" } */
+
+extern int bar (void);
+
+int
+foo (void)
+{
+  return bar () + 1;
+}
+
+/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOT\\(" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr66232-5.c b/gcc/testsuite/gcc.target/i386/pr66232-5.c
new file mode 100644
index 0000000..c016717
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr66232-5.c
@@ -0,0 +1,16 @@
+/* { dg-do compile { target { ! { ia32 } } } } */
+/* { dg-require-effective-target maybe_x32 } */
+/* { dg-options "-O2 -fpic -mx32" } */
+
+extern void (*bar) (void);
+void
+foo (int n)
+{
+  int i;
+  for (i = 0; i < n; i++)
+    {
+      if (!bar)
+	continue;
+      (*bar) ();
+    }
+}
-- 
1.9.3


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] PR target/66232: -fPIC -fno-plt -mx32 fails to generate indirect branch via GOT
  2015-05-21 19:01         ` H.J. Lu
@ 2015-05-21 19:06           ` Uros Bizjak
  0 siblings, 0 replies; 16+ messages in thread
From: Uros Bizjak @ 2015-05-21 19:06 UTC (permalink / raw)
  To: H.J. Lu; +Cc: gcc-patches

On Thu, May 21, 2015 at 8:36 PM, H.J. Lu <hjl.tools@gmail.com> wrote:

> I am testing this now.  I will check it in if there is no regression.

OK.

Maybe just :

;; Return true if OP is a GOT memory operand.
(define_predicate "GOT_memory_operand"
  (match_operand 0 "memory_operand")
{
  return CONSTANT_P ...
            && GET_CODE (...) == UNSPEC
            && XINT (...)
}

No point in using match_test in the above pattern.

Uros.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] PR target/66232: -fPIC -fno-plt -mx32 fails to generate indirect branch via GOT
  2015-05-21 13:05 [PATCH] PR target/66232: -fPIC -fno-plt -mx32 fails to generate indirect branch via GOT H.J. Lu
  2015-05-21 13:19 ` Uros Bizjak
@ 2015-05-21 19:13 ` Richard Henderson
  2015-05-21 19:19   ` H.J. Lu
  1 sibling, 1 reply; 16+ messages in thread
From: Richard Henderson @ 2015-05-21 19:13 UTC (permalink / raw)
  To: H.J. Lu, gcc-patches; +Cc: Uros Bizjak

On 05/21/2015 05:59 AM, H.J. Lu wrote:
> +(define_predicate "x32_sibcall_memory_operand"
> +  (and (match_operand 0 "memory_operand")
> +       (match_test "CONSTANT_P (XEXP (op, 0))")
> +       (match_test "GET_CODE (XEXP (XEXP (op, 0), 0)) == UNSPEC")
> +       (match_test "XINT (XEXP (XEXP (op, 0), 0), 1) == UNSPEC_GOTPCREL")))

CONSTANT_P doesn't do what you think it does.  That accepts all constants, not
the CONST rtx code, which is the only thing you want to be looking into its XEXP.


r~

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] PR target/66232: -fPIC -fno-plt -mx32 fails to generate indirect branch via GOT
  2015-05-21 19:13 ` Richard Henderson
@ 2015-05-21 19:19   ` H.J. Lu
  2015-05-21 19:21     ` Richard Henderson
  2015-05-21 22:20     ` H.J. Lu
  0 siblings, 2 replies; 16+ messages in thread
From: H.J. Lu @ 2015-05-21 19:19 UTC (permalink / raw)
  To: Richard Henderson; +Cc: GCC Patches, Uros Bizjak

[-- Attachment #1: Type: text/plain, Size: 641 bytes --]

On Thu, May 21, 2015 at 11:41 AM, Richard Henderson <rth@redhat.com> wrote:
> On 05/21/2015 05:59 AM, H.J. Lu wrote:
>> +(define_predicate "x32_sibcall_memory_operand"
>> +  (and (match_operand 0 "memory_operand")
>> +       (match_test "CONSTANT_P (XEXP (op, 0))")
>> +       (match_test "GET_CODE (XEXP (XEXP (op, 0), 0)) == UNSPEC")
>> +       (match_test "XINT (XEXP (XEXP (op, 0), 0), 1) == UNSPEC_GOTPCREL")))
>
> CONSTANT_P doesn't do what you think it does.  That accepts all constants, not
> the CONST rtx code, which is the only thing you want to be looking into its XEXP.
>

Hope this is the final one :-).

Thanks.

-- 
H.J.
---

[-- Attachment #2: 0001-Allow-indirect-branch-via-GOT-slot-for-x32.patch --]
[-- Type: text/x-patch, Size: 7276 bytes --]

From 66ca08e9fb7456d7be7d48825f2a1c40b777f657 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Thu, 21 May 2015 05:50:14 -0700
Subject: [PATCH] Allow indirect branch via GOT slot for x32

X32 doesn't support indirect branch via 32-bit memory slot since
indirect branch will load 64-bit address from 64-bit memory slot.
Since x32 GOT slot is 64-bit, we should allow indirect branch via GOT
slot for x32.

gcc/

	PR target/66232
	* config/i386/constraints.md (Bg): New constraint for GOT memory
	operand.
	* config/i386/i386.md (*call_got_x32): New pattern.
	(*call_value_got_x32): Likewise.
	* config/i386/predicates.md (GOT_memory_operand): New predicate.

gcc/testsuite/

	PR target/66232
	* gcc.target/i386/pr66232-1.c: New test.
	* gcc.target/i386/pr66232-2.c: Likewise.
	* gcc.target/i386/pr66232-3.c: Likewise.
	* gcc.target/i386/pr66232-4.c: Likewise.
	* gcc.target/i386/pr66232-5.c: Likewise.
---
 gcc/config/i386/constraints.md            |  5 +++++
 gcc/config/i386/i386.md                   | 20 ++++++++++++++++++++
 gcc/config/i386/predicates.md             | 10 ++++++++++
 gcc/testsuite/gcc.target/i386/pr66232-1.c | 13 +++++++++++++
 gcc/testsuite/gcc.target/i386/pr66232-2.c | 14 ++++++++++++++
 gcc/testsuite/gcc.target/i386/pr66232-3.c | 13 +++++++++++++
 gcc/testsuite/gcc.target/i386/pr66232-4.c | 13 +++++++++++++
 gcc/testsuite/gcc.target/i386/pr66232-5.c | 16 ++++++++++++++++
 8 files changed, 104 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-1.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-2.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-3.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-4.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-5.c

diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md
index 2271bd1..c718bc1 100644
--- a/gcc/config/i386/constraints.md
+++ b/gcc/config/i386/constraints.md
@@ -146,10 +146,15 @@
  "@internal Lower SSE register when avoiding REX prefix and all SSE registers otherwise.")
 
 ;; We use the B prefix to denote any number of internal operands:
+;;  g  GOT memory operand.
 ;;  s  Sibcall memory operand, not valid for TARGET_X32
 ;;  w  Call memory operand, not valid for TARGET_X32
 ;;  z  Constant call address operand.
 
+(define_constraint "Bg"
+  "@internal GOT memory operand."
+  (match_operand 0 "GOT_memory_operand"))
+
 (define_constraint "Bs"
   "@internal Sibcall memory operand."
   (and (not (match_test "TARGET_X32"))
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index aefca43..3819dfd 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -11659,6 +11659,15 @@
   "* return ix86_output_call_insn (insn, operands[0]);"
   [(set_attr "type" "call")])
 
+;; This covers both call and sibcall since only GOT slot is allowed.
+(define_insn "*call_got_x32"
+  [(call (mem:QI (zero_extend:DI
+		   (match_operand:SI 0 "GOT_memory_operand" "Bg")))
+	 (match_operand 1))]
+  "TARGET_X32"
+  "* return ix86_output_call_insn (insn, operands[0]);"
+  [(set_attr "type" "call")])
+
 (define_insn "*sibcall"
   [(call (mem:QI (match_operand:W 0 "sibcall_insn_operand" "UBsBz"))
 	 (match_operand 1))]
@@ -11825,6 +11834,17 @@
   "* return ix86_output_call_insn (insn, operands[1]);"
   [(set_attr "type" "callv")])
 
+;; This covers both call and sibcall since only GOT slot is allowed.
+(define_insn "*call_value_got_x32"
+  [(set (match_operand 0)
+	(call (mem:QI
+		(zero_extend:DI
+		  (match_operand:SI 1 "GOT_memory_operand" "Bg")))
+	      (match_operand 2)))]
+  "TARGET_X32"
+  "* return ix86_output_call_insn (insn, operands[1]);"
+  [(set_attr "type" "callv")])
+
 (define_insn "*sibcall_value"
   [(set (match_operand 0)
 	(call (mem:QI (match_operand:W 1 "sibcall_insn_operand" "UBsBz"))
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index 26dd3e1..6d6c6c4 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -606,6 +606,16 @@
        (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);
+})
+
 ;; Match exactly zero.
 (define_predicate "const0_operand"
   (match_code "const_int,const_wide_int,const_double,const_vector")
diff --git a/gcc/testsuite/gcc.target/i386/pr66232-1.c b/gcc/testsuite/gcc.target/i386/pr66232-1.c
new file mode 100644
index 0000000..ba4a5ef
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr66232-1.c
@@ -0,0 +1,13 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpic -fno-plt" } */
+
+extern void bar (void);
+
+void
+foo (void)
+{
+  bar ();
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]*.bar@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOT\\(" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr66232-2.c b/gcc/testsuite/gcc.target/i386/pr66232-2.c
new file mode 100644
index 0000000..f05d7c5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr66232-2.c
@@ -0,0 +1,14 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpic -fno-plt" } */
+
+extern void bar (void);
+
+int
+foo (void)
+{
+  bar ();
+  return 0;
+}
+
+/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOT\\(" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr66232-3.c b/gcc/testsuite/gcc.target/i386/pr66232-3.c
new file mode 100644
index 0000000..ee3176c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr66232-3.c
@@ -0,0 +1,13 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpic -fno-plt" } */
+
+extern int bar (void);
+
+int
+foo (void)
+{
+  return bar ();
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]*.bar@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOT\\(" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr66232-4.c b/gcc/testsuite/gcc.target/i386/pr66232-4.c
new file mode 100644
index 0000000..5fa0ded
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr66232-4.c
@@ -0,0 +1,13 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpic -fno-plt" } */
+
+extern int bar (void);
+
+int
+foo (void)
+{
+  return bar () + 1;
+}
+
+/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOT\\(" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr66232-5.c b/gcc/testsuite/gcc.target/i386/pr66232-5.c
new file mode 100644
index 0000000..c016717
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr66232-5.c
@@ -0,0 +1,16 @@
+/* { dg-do compile { target { ! { ia32 } } } } */
+/* { dg-require-effective-target maybe_x32 } */
+/* { dg-options "-O2 -fpic -mx32" } */
+
+extern void (*bar) (void);
+void
+foo (int n)
+{
+  int i;
+  for (i = 0; i < n; i++)
+    {
+      if (!bar)
+	continue;
+      (*bar) ();
+    }
+}
-- 
1.9.3


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] PR target/66232: -fPIC -fno-plt -mx32 fails to generate indirect branch via GOT
  2015-05-21 19:19   ` H.J. Lu
@ 2015-05-21 19:21     ` Richard Henderson
  2015-05-21 19:37       ` H.J. Lu
  2015-05-21 22:20     ` H.J. Lu
  1 sibling, 1 reply; 16+ messages in thread
From: Richard Henderson @ 2015-05-21 19:21 UTC (permalink / raw)
  To: H.J. Lu; +Cc: GCC Patches, Uros Bizjak

On 05/21/2015 12:01 PM, H.J. Lu wrote:
> +++ b/gcc/testsuite/gcc.target/i386/pr66232-1.c
> @@ -0,0 +1,13 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-options "-O2 -fpic -fno-plt" } */
> +
> +extern void bar (void);
> +
> +void
> +foo (void)
> +{
> +  bar ();
> +}
> +
> +/* { dg-final { scan-assembler "jmp\[ \t\]*.bar@GOTPCREL" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOT\\(" { target ia32 } } } */

Do you really want to check for no tail call for ia32 here?
That's really just a missed optimization, surely.


r~

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] PR target/66232: -fPIC -fno-plt -mx32 fails to generate indirect branch via GOT
  2015-05-21 19:21     ` Richard Henderson
@ 2015-05-21 19:37       ` H.J. Lu
  2015-05-21 19:43         ` Alexander Monakov
  0 siblings, 1 reply; 16+ messages in thread
From: H.J. Lu @ 2015-05-21 19:37 UTC (permalink / raw)
  To: Richard Henderson; +Cc: GCC Patches, Uros Bizjak

On Thu, May 21, 2015 at 12:06 PM, Richard Henderson <rth@redhat.com> wrote:
> On 05/21/2015 12:01 PM, H.J. Lu wrote:
>> +++ b/gcc/testsuite/gcc.target/i386/pr66232-1.c
>> @@ -0,0 +1,13 @@
>> +/* { dg-do compile { target *-*-linux* } } */
>> +/* { dg-options "-O2 -fpic -fno-plt" } */
>> +
>> +extern void bar (void);
>> +
>> +void
>> +foo (void)
>> +{
>> +  bar ();
>> +}
>> +
>> +/* { dg-final { scan-assembler "jmp\[ \t\]*.bar@GOTPCREL" { target { ! ia32 } } } } */
>> +/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOT\\(" { target ia32 } } } */
>
> Do you really want to check for no tail call for ia32 here?
> That's really just a missed optimization, surely.
>
>

I'd like to keep it.  When it is fixed, we can update it.  I tried:

https://gcc.gnu.org/ml/gcc-patches/2015-05/msg00230.html

and got

call __x86.get_pc_thunk.ax
addl $_GLOBAL_OFFSET_TABLE_, %eax
subl $28, %esp
.cfi_def_cfa_offset 32
movl bar@GOT(%eax), %eax
movl %eax, 12(%esp)
addl $28, %esp
.cfi_def_cfa_offset 4
jmp *%eax

This is very odd code, comparing against

call __x86.get_pc_thunk.ax
addl $_GLOBAL_OFFSET_TABLE_, %eax
subl $12, %esp
.cfi_def_cfa_offset 16
call *bar@GOT(%eax)
addl $12, %esp
.cfi_def_cfa_offset 4
ret


-- 
H.J.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] PR target/66232: -fPIC -fno-plt -mx32 fails to generate indirect branch via GOT
  2015-05-21 19:37       ` H.J. Lu
@ 2015-05-21 19:43         ` Alexander Monakov
  2015-05-21 20:06           ` H.J. Lu
  0 siblings, 1 reply; 16+ messages in thread
From: Alexander Monakov @ 2015-05-21 19:43 UTC (permalink / raw)
  To: H.J. Lu; +Cc: Richard Henderson, GCC Patches, Uros Bizjak

On Thu, 21 May 2015, H.J. Lu wrote:
> On Thu, May 21, 2015 at 12:06 PM, Richard Henderson <rth@redhat.com> wrote:
> > On 05/21/2015 12:01 PM, H.J. Lu wrote:
> >> +++ b/gcc/testsuite/gcc.target/i386/pr66232-1.c
> >> @@ -0,0 +1,13 @@
> >> +/* { dg-do compile { target *-*-linux* } } */
> >> +/* { dg-options "-O2 -fpic -fno-plt" } */
> >> +
> >> +extern void bar (void);
> >> +
> >> +void
> >> +foo (void)
> >> +{
> >> +  bar ();
> >> +}
> >> +
> >> +/* { dg-final { scan-assembler "jmp\[ \t\]*.bar@GOTPCREL" { target { ! ia32 } } } } */
> >> +/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOT\\(" { target ia32 } } } */
> >
> > Do you really want to check for no tail call for ia32 here?
> > That's really just a missed optimization, surely.
> >
> >
> 
> I'd like to keep it.  When it is fixed, we can update it.  I tried:
> 
> https://gcc.gnu.org/ml/gcc-patches/2015-05/msg00230.html
> 
> and got
> 
> call __x86.get_pc_thunk.ax
> addl $_GLOBAL_OFFSET_TABLE_, %eax
> subl $28, %esp
> .cfi_def_cfa_offset 32
> movl bar@GOT(%eax), %eax
> movl %eax, 12(%esp)
> addl $28, %esp
> .cfi_def_cfa_offset 4
> jmp *%eax
> 
> This is very odd code, comparing against

To avoid that, you need the CLOBBERED_REGS patch too:
https://gcc.gnu.org/ml/gcc-patches/2015-05/msg00227.html

Alexander

> call __x86.get_pc_thunk.ax
> addl $_GLOBAL_OFFSET_TABLE_, %eax
> subl $12, %esp
> .cfi_def_cfa_offset 16
> call *bar@GOT(%eax)
> addl $12, %esp
> .cfi_def_cfa_offset 4
> ret

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] PR target/66232: -fPIC -fno-plt -mx32 fails to generate indirect branch via GOT
  2015-05-21 19:43         ` Alexander Monakov
@ 2015-05-21 20:06           ` H.J. Lu
  2015-05-21 20:32             ` Alexander Monakov
  0 siblings, 1 reply; 16+ messages in thread
From: H.J. Lu @ 2015-05-21 20:06 UTC (permalink / raw)
  To: Alexander Monakov; +Cc: Richard Henderson, GCC Patches, Uros Bizjak

On Thu, May 21, 2015 at 12:32 PM, Alexander Monakov <amonakov@ispras.ru> wrote:
> On Thu, 21 May 2015, H.J. Lu wrote:
>> On Thu, May 21, 2015 at 12:06 PM, Richard Henderson <rth@redhat.com> wrote:
>> > On 05/21/2015 12:01 PM, H.J. Lu wrote:
>> >> +++ b/gcc/testsuite/gcc.target/i386/pr66232-1.c
>> >> @@ -0,0 +1,13 @@
>> >> +/* { dg-do compile { target *-*-linux* } } */
>> >> +/* { dg-options "-O2 -fpic -fno-plt" } */
>> >> +
>> >> +extern void bar (void);
>> >> +
>> >> +void
>> >> +foo (void)
>> >> +{
>> >> +  bar ();
>> >> +}
>> >> +
>> >> +/* { dg-final { scan-assembler "jmp\[ \t\]*.bar@GOTPCREL" { target { ! ia32 } } } } */
>> >> +/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOT\\(" { target ia32 } } } */
>> >
>> > Do you really want to check for no tail call for ia32 here?
>> > That's really just a missed optimization, surely.
>> >
>> >
>>
>> I'd like to keep it.  When it is fixed, we can update it.  I tried:
>>
>> https://gcc.gnu.org/ml/gcc-patches/2015-05/msg00230.html
>>
>> and got
>>
>> call __x86.get_pc_thunk.ax
>> addl $_GLOBAL_OFFSET_TABLE_, %eax
>> subl $28, %esp
>> .cfi_def_cfa_offset 32
>> movl bar@GOT(%eax), %eax
>> movl %eax, 12(%esp)
>> addl $28, %esp
>> .cfi_def_cfa_offset 4
>> jmp *%eax
>>
>> This is very odd code, comparing against
>
> To avoid that, you need the CLOBBERED_REGS patch too:
> https://gcc.gnu.org/ml/gcc-patches/2015-05/msg00227.html
>

Should both patches be needed for ia32 tail call?

-- 
H.J.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] PR target/66232: -fPIC -fno-plt -mx32 fails to generate indirect branch via GOT
  2015-05-21 20:06           ` H.J. Lu
@ 2015-05-21 20:32             ` Alexander Monakov
  2015-05-25 19:30               ` Alexander Monakov
  0 siblings, 1 reply; 16+ messages in thread
From: Alexander Monakov @ 2015-05-21 20:32 UTC (permalink / raw)
  To: H.J. Lu; +Cc: Richard Henderson, GCC Patches, Uros Bizjak



On Thu, 21 May 2015, H.J. Lu wrote:

> On Thu, May 21, 2015 at 12:32 PM, Alexander Monakov <amonakov@ispras.ru> wrote:
> > On Thu, 21 May 2015, H.J. Lu wrote:
> >> On Thu, May 21, 2015 at 12:06 PM, Richard Henderson <rth@redhat.com> wrote:
> >> > On 05/21/2015 12:01 PM, H.J. Lu wrote:
> >> >> +++ b/gcc/testsuite/gcc.target/i386/pr66232-1.c
> >> >> @@ -0,0 +1,13 @@
> >> >> +/* { dg-do compile { target *-*-linux* } } */
> >> >> +/* { dg-options "-O2 -fpic -fno-plt" } */
> >> >> +
> >> >> +extern void bar (void);
> >> >> +
> >> >> +void
> >> >> +foo (void)
> >> >> +{
> >> >> +  bar ();
> >> >> +}
> >> >> +
> >> >> +/* { dg-final { scan-assembler "jmp\[ \t\]*.bar@GOTPCREL" { target { ! ia32 } } } } */
> >> >> +/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOT\\(" { target ia32 } } } */
> >> >
> >> > Do you really want to check for no tail call for ia32 here?
> >> > That's really just a missed optimization, surely.
> >> >
> >> >
> >>
> >> I'd like to keep it.  When it is fixed, we can update it.  I tried:
> >>
> >> https://gcc.gnu.org/ml/gcc-patches/2015-05/msg00230.html
> >>
> >> and got
> >>
> >> call __x86.get_pc_thunk.ax
> >> addl $_GLOBAL_OFFSET_TABLE_, %eax
> >> subl $28, %esp
> >> .cfi_def_cfa_offset 32
> >> movl bar@GOT(%eax), %eax
> >> movl %eax, 12(%esp)
> >> addl $28, %esp
> >> .cfi_def_cfa_offset 4
> >> jmp *%eax
> >>
> >> This is very odd code, comparing against
> >
> > To avoid that, you need the CLOBBERED_REGS patch too:
> > https://gcc.gnu.org/ml/gcc-patches/2015-05/msg00227.html
> >
> 
> Should both patches be needed for ia32 tail call?

I don't really understand the question.  The first patch (that you've linked)
is required to produce a tail call, the second patch (that I've linked) helps
to produce clean code.  To match the scan-assembler test as written in your
testcase, both patches are needed.

Alexander

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] PR target/66232: -fPIC -fno-plt -mx32 fails to generate indirect branch via GOT
  2015-05-21 19:19   ` H.J. Lu
  2015-05-21 19:21     ` Richard Henderson
@ 2015-05-21 22:20     ` H.J. Lu
  1 sibling, 0 replies; 16+ messages in thread
From: H.J. Lu @ 2015-05-21 22:20 UTC (permalink / raw)
  To: Richard Henderson; +Cc: GCC Patches, Uros Bizjak

[-- Attachment #1: Type: text/plain, Size: 753 bytes --]

On Thu, May 21, 2015 at 12:01 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Thu, May 21, 2015 at 11:41 AM, Richard Henderson <rth@redhat.com> wrote:
>> On 05/21/2015 05:59 AM, H.J. Lu wrote:
>>> +(define_predicate "x32_sibcall_memory_operand"
>>> +  (and (match_operand 0 "memory_operand")
>>> +       (match_test "CONSTANT_P (XEXP (op, 0))")
>>> +       (match_test "GET_CODE (XEXP (XEXP (op, 0), 0)) == UNSPEC")
>>> +       (match_test "XINT (XEXP (XEXP (op, 0), 0), 1) == UNSPEC_GOTPCREL")))
>>
>> CONSTANT_P doesn't do what you think it does.  That accepts all constants, not
>> the CONST rtx code, which is the only thing you want to be looking into its XEXP.
>>
>
> Hope this is the final one :-).
>

This is what I checked in.

Thanks.

-- 
H.J.

[-- Attachment #2: 0001-Allow-indirect-branch-via-GOT-slot-for-x32.patch --]
[-- Type: text/x-patch, Size: 7274 bytes --]

From b7134fccde8be4343f37c450379b81f890014f6b Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Thu, 21 May 2015 05:50:14 -0700
Subject: [PATCH] Allow indirect branch via GOT slot for x32

X32 doesn't support indirect branch via 32-bit memory slot since
indirect branch will load 64-bit address from 64-bit memory slot.
Since x32 GOT slot is 64-bit, we should allow indirect branch via GOT
slot for x32.

gcc/

	PR target/66232
	* config/i386/constraints.md (Bg): New constraint for GOT memory
	operand.
	* config/i386/i386.md (*call_got_x32): New pattern.
	(*call_value_got_x32): Likewise.
	* config/i386/predicates.md (GOT_memory_operand): New predicate.

gcc/testsuite/

	PR target/66232
	* gcc.target/i386/pr66232-1.c: New test.
	* gcc.target/i386/pr66232-2.c: Likewise.
	* gcc.target/i386/pr66232-3.c: Likewise.
	* gcc.target/i386/pr66232-4.c: Likewise.
	* gcc.target/i386/pr66232-5.c: Likewise.
---
 gcc/config/i386/constraints.md            |  5 +++++
 gcc/config/i386/i386.md                   | 20 ++++++++++++++++++++
 gcc/config/i386/predicates.md             | 10 ++++++++++
 gcc/testsuite/gcc.target/i386/pr66232-1.c | 13 +++++++++++++
 gcc/testsuite/gcc.target/i386/pr66232-2.c | 14 ++++++++++++++
 gcc/testsuite/gcc.target/i386/pr66232-3.c | 13 +++++++++++++
 gcc/testsuite/gcc.target/i386/pr66232-4.c | 13 +++++++++++++
 gcc/testsuite/gcc.target/i386/pr66232-5.c | 16 ++++++++++++++++
 8 files changed, 104 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-1.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-2.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-3.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-4.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-5.c

diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md
index 2271bd1..c718bc1 100644
--- a/gcc/config/i386/constraints.md
+++ b/gcc/config/i386/constraints.md
@@ -146,10 +146,15 @@
  "@internal Lower SSE register when avoiding REX prefix and all SSE registers otherwise.")
 
 ;; We use the B prefix to denote any number of internal operands:
+;;  g  GOT memory operand.
 ;;  s  Sibcall memory operand, not valid for TARGET_X32
 ;;  w  Call memory operand, not valid for TARGET_X32
 ;;  z  Constant call address operand.
 
+(define_constraint "Bg"
+  "@internal GOT memory operand."
+  (match_operand 0 "GOT_memory_operand"))
+
 (define_constraint "Bs"
   "@internal Sibcall memory operand."
   (and (not (match_test "TARGET_X32"))
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index aefca43..3819dfd 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -11659,6 +11659,15 @@
   "* return ix86_output_call_insn (insn, operands[0]);"
   [(set_attr "type" "call")])
 
+;; This covers both call and sibcall since only GOT slot is allowed.
+(define_insn "*call_got_x32"
+  [(call (mem:QI (zero_extend:DI
+		   (match_operand:SI 0 "GOT_memory_operand" "Bg")))
+	 (match_operand 1))]
+  "TARGET_X32"
+  "* return ix86_output_call_insn (insn, operands[0]);"
+  [(set_attr "type" "call")])
+
 (define_insn "*sibcall"
   [(call (mem:QI (match_operand:W 0 "sibcall_insn_operand" "UBsBz"))
 	 (match_operand 1))]
@@ -11825,6 +11834,17 @@
   "* return ix86_output_call_insn (insn, operands[1]);"
   [(set_attr "type" "callv")])
 
+;; This covers both call and sibcall since only GOT slot is allowed.
+(define_insn "*call_value_got_x32"
+  [(set (match_operand 0)
+	(call (mem:QI
+		(zero_extend:DI
+		  (match_operand:SI 1 "GOT_memory_operand" "Bg")))
+	      (match_operand 2)))]
+  "TARGET_X32"
+  "* return ix86_output_call_insn (insn, operands[1]);"
+  [(set_attr "type" "callv")])
+
 (define_insn "*sibcall_value"
   [(set (match_operand 0)
 	(call (mem:QI (match_operand:W 1 "sibcall_insn_operand" "UBsBz"))
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index 26dd3e1..b7bb84f 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -606,6 +606,16 @@
        (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);
+})
+
 ;; Match exactly zero.
 (define_predicate "const0_operand"
   (match_code "const_int,const_wide_int,const_double,const_vector")
diff --git a/gcc/testsuite/gcc.target/i386/pr66232-1.c b/gcc/testsuite/gcc.target/i386/pr66232-1.c
new file mode 100644
index 0000000..ba4a5ef
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr66232-1.c
@@ -0,0 +1,13 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpic -fno-plt" } */
+
+extern void bar (void);
+
+void
+foo (void)
+{
+  bar ();
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]*.bar@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOT\\(" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr66232-2.c b/gcc/testsuite/gcc.target/i386/pr66232-2.c
new file mode 100644
index 0000000..f05d7c5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr66232-2.c
@@ -0,0 +1,14 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpic -fno-plt" } */
+
+extern void bar (void);
+
+int
+foo (void)
+{
+  bar ();
+  return 0;
+}
+
+/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOT\\(" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr66232-3.c b/gcc/testsuite/gcc.target/i386/pr66232-3.c
new file mode 100644
index 0000000..ee3176c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr66232-3.c
@@ -0,0 +1,13 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpic -fno-plt" } */
+
+extern int bar (void);
+
+int
+foo (void)
+{
+  return bar ();
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]*.bar@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOT\\(" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr66232-4.c b/gcc/testsuite/gcc.target/i386/pr66232-4.c
new file mode 100644
index 0000000..5fa0ded
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr66232-4.c
@@ -0,0 +1,13 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpic -fno-plt" } */
+
+extern int bar (void);
+
+int
+foo (void)
+{
+  return bar () + 1;
+}
+
+/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOT\\(" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr66232-5.c b/gcc/testsuite/gcc.target/i386/pr66232-5.c
new file mode 100644
index 0000000..c016717
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr66232-5.c
@@ -0,0 +1,16 @@
+/* { dg-do compile { target { ! { ia32 } } } } */
+/* { dg-require-effective-target maybe_x32 } */
+/* { dg-options "-O2 -fpic -mx32" } */
+
+extern void (*bar) (void);
+void
+foo (int n)
+{
+  int i;
+  for (i = 0; i < n; i++)
+    {
+      if (!bar)
+	continue;
+      (*bar) ();
+    }
+}
-- 
1.9.3


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] PR target/66232: -fPIC -fno-plt -mx32 fails to generate indirect branch via GOT
  2015-05-21 20:32             ` Alexander Monakov
@ 2015-05-25 19:30               ` Alexander Monakov
  0 siblings, 0 replies; 16+ messages in thread
From: Alexander Monakov @ 2015-05-25 19:30 UTC (permalink / raw)
  To: H.J. Lu; +Cc: Richard Henderson, GCC Patches, Uros Bizjak

> On Thu, 21 May 2015, H.J. Lu wrote:
> 
> > On Thu, May 21, 2015 at 12:32 PM, Alexander Monakov <amonakov@ispras.ru> wrote:
> > > On Thu, 21 May 2015, H.J. Lu wrote:
> > >> On Thu, May 21, 2015 at 12:06 PM, Richard Henderson <rth@redhat.com> wrote:
> > >> > On 05/21/2015 12:01 PM, H.J. Lu wrote:
> > >> >> +++ b/gcc/testsuite/gcc.target/i386/pr66232-1.c
> > >> >> @@ -0,0 +1,13 @@
> > >> >> +/* { dg-do compile { target *-*-linux* } } */
> > >> >> +/* { dg-options "-O2 -fpic -fno-plt" } */
> > >> >> +
> > >> >> +extern void bar (void);
> > >> >> +
> > >> >> +void
> > >> >> +foo (void)
> > >> >> +{
> > >> >> +  bar ();
> > >> >> +}
> > >> >> +
> > >> >> +/* { dg-final { scan-assembler "jmp\[ \t\]*.bar@GOTPCREL" { target { ! ia32 } } } } */
> > >> >> +/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOT\\(" { target ia32 } } } */
> > >> >
> > >> > Do you really want to check for no tail call for ia32 here?
> > >> > That's really just a missed optimization, surely.
> > >> >
> > >> >
> > >>
> > >> I'd like to keep it.  When it is fixed, we can update it.  I tried:
> > >>
> > >> https://gcc.gnu.org/ml/gcc-patches/2015-05/msg00230.html
> > >>
> > >> and got
> > >>
> > >> call __x86.get_pc_thunk.ax
> > >> addl $_GLOBAL_OFFSET_TABLE_, %eax
> > >> subl $28, %esp
> > >> .cfi_def_cfa_offset 32
> > >> movl bar@GOT(%eax), %eax
> > >> movl %eax, 12(%esp)
> > >> addl $28, %esp
> > >> .cfi_def_cfa_offset 4
> > >> jmp *%eax
> > >>
> > >> This is very odd code, comparing against
> > >
> > > To avoid that, you need the CLOBBERED_REGS patch too:
> > > https://gcc.gnu.org/ml/gcc-patches/2015-05/msg00227.html
> > >
> > 
> > Should both patches be needed for ia32 tail call?
> 
> I don't really understand the question.  The first patch (that you've linked)
> is required to produce a tail call, the second patch (that I've linked) helps
> to produce clean code.  To match the scan-assembler test as written in your
> testcase, both patches are needed.

I have pushed those patches and updated the scan patterns to match
memory-indirect jump rather than call.

Alexander

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2015-05-25 18:09 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-05-21 13:05 [PATCH] PR target/66232: -fPIC -fno-plt -mx32 fails to generate indirect branch via GOT H.J. Lu
2015-05-21 13:19 ` Uros Bizjak
2015-05-21 13:40   ` H.J. Lu
2015-05-21 17:16     ` H.J. Lu
2015-05-21 18:36       ` Uros Bizjak
2015-05-21 19:01         ` H.J. Lu
2015-05-21 19:06           ` Uros Bizjak
2015-05-21 19:13 ` Richard Henderson
2015-05-21 19:19   ` H.J. Lu
2015-05-21 19:21     ` Richard Henderson
2015-05-21 19:37       ` H.J. Lu
2015-05-21 19:43         ` Alexander Monakov
2015-05-21 20:06           ` H.J. Lu
2015-05-21 20:32             ` Alexander Monakov
2015-05-25 19:30               ` Alexander Monakov
2015-05-21 22:20     ` H.J. Lu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).