On Thu, May 21, 2015 at 7:01 PM, H.J. Lu <hjl.to...@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"