On Tue, Mar 6, 2012 at 11:47 AM, Richard Henderson <r...@redhat.com> wrote:
> On 03/06/12 11:10, H.J. Lu wrote:
>>  (define_insn "*call"
>> -  [(call (mem:QI (match_operand:P 0 "call_insn_operand" "<c>zw"))
>> +  [(call (mem:QI (match_operand:C 0 "call_insn_operand" "<c>zw"))
>>        (match_operand 1 "" ""))]
>> -  "!SIBLING_CALL_P (insn)"
>> +  "!SIBLING_CALL_P (insn)
>> +   && (GET_CODE (operands[0]) == SYMBOL_REF
>> +       || GET_MODE (operands[0]) == word_mode)"
>
> There are enough copies of this extra constraint that I wonder
> if it simply ought to be folded into call_insn_operand.
>
> Which would need to be changed to define_special_predicate,
> since you'd be doing your own mode checking.
>
> Probably similar changes to sibcall_insn_operand.
>
>
> r~

Here is the updated patch.  I changed constant_call_address_operand
and call_register_no_elim_operand to use define_special_predicate.
OK for trunk?

Thanks.


-- 
H.J
---
2012-03-06  H.J. Lu  <hongjiu...@intel.com>

        * config/i386/i386.c (ix86_expand_call): Call
        constant_call_address_operand with Pmode and call
        call_register_no_elim_operand/memory_operand with word_mode.
        Convert the address to word_mode instead of Pmode.

        * config/i386/i386.md (W): New.
        (C): Likewise.
        (indirect_jump): Convert address to word_mode for x32.
        (tablejump): Likewise.
        (*indirect_jump): Replace :P with :W.
        (*tablejump_1): Likewise.
        (*call_vzeroupper): Replace :P with :C.
        (*call): Likewise.
        (*sibcall_vzeroupper): Likewise.
        (*sibcall): Likewise.
        (*call_value_vzeroupper): Likewise.
        (*call_value): Likewise.
        (*sibcall_value_vzeroupper): Likewise.
        (*sibcall_value): Likewise.

        * config/i386/predicates.md (constant_call_address_operand):
        Defined with define_special_predicate.  Return false if mode
        isn't Pmode.
        (call_register_no_elim_operand): Defined with
        define_special_predicate.  Return false if mode isn't word_mode.
2012-03-06  H.J. Lu  <hongjiu...@intel.com>

        * config/i386/i386.c (ix86_expand_call): Call
        constant_call_address_operand with Pmode and call
        call_register_no_elim_operand/memory_operand with word_mode.
        Convert the address to word_mode instead of Pmode.

        * config/i386/i386.md (W): New.
        (C): Likewise.
        (indirect_jump): Convert address to word_mode for x32.
        (tablejump): Likewise.
        (*indirect_jump): Replace :P with :W.
        (*tablejump_1): Likewise.
        (*call_vzeroupper): Replace :P with :C.
        (*call): Likewise.
        (*sibcall_vzeroupper): Likewise.
        (*sibcall): Likewise.
        (*call_value_vzeroupper): Likewise.
        (*call_value): Likewise.
        (*sibcall_value_vzeroupper): Likewise.
        (*sibcall_value): Likewise.

        * config/i386/predicates.md (constant_call_address_operand):
        Defined with define_special_predicate.  Return false if mode
        isn't Pmode.
        (call_register_no_elim_operand): Defined with
        define_special_predicate.  Return false if mode isn't word_mode.

diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 973bbeb..7ee71fa 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -22940,14 +22940,18 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx 
callarg1,
       && GET_CODE (XEXP (fnaddr, 0)) == SYMBOL_REF
       && !local_symbolic_operand (XEXP (fnaddr, 0), VOIDmode))
     fnaddr = gen_rtx_MEM (QImode, construct_plt_address (XEXP (fnaddr, 0)));
-  else if (sibcall
-          ? !sibcall_insn_operand (XEXP (fnaddr, 0), Pmode)
-          : !call_insn_operand (XEXP (fnaddr, 0), Pmode))
+  else if (!(constant_call_address_operand (XEXP (fnaddr, 0), Pmode)
+            || call_register_no_elim_operand (XEXP (fnaddr, 0),
+                                              word_mode)
+            || (!sibcall
+                && !TARGET_X32
+                && memory_operand (XEXP (fnaddr, 0), word_mode))))
     {
       fnaddr = XEXP (fnaddr, 0);
-      if (GET_MODE (fnaddr) != Pmode)
-       fnaddr = convert_to_mode (Pmode, fnaddr, 1);
-      fnaddr = gen_rtx_MEM (QImode, copy_to_mode_reg (Pmode, fnaddr));
+      if (GET_MODE (fnaddr) != word_mode)
+       fnaddr = convert_to_mode (word_mode, fnaddr, 1);
+      fnaddr = gen_rtx_MEM (QImode,
+                           copy_to_mode_reg (word_mode, fnaddr));
     }
 
   vec_len = 0;
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index bfbf5bf..801ffa2 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -896,6 +896,16 @@
 ;; ptr_mode sized quantities.
 (define_mode_iterator PTR
   [(SI "ptr_mode == SImode") (DI "ptr_mode == DImode")])
+
+;; This mode iterator allows :W to be used for patterns that operate on
+;; word_mode sized quantities.
+(define_mode_iterator W
+  [(SI "word_mode == SImode") (DI "word_mode == DImode")])
+
+;; This mode iterator allows :C to be used for patterns that operate on
+;; pointer-sized and word_mode sized quantities.
+(define_mode_iterator C
+  [(SI "Pmode == SImode") (DI "word_mode == DImode")])
 
 ;; Scheduling descriptions
 
@@ -11076,10 +11086,15 @@
    (set_attr "modrm" "0")])
 
 (define_expand "indirect_jump"
-  [(set (pc) (match_operand 0 "indirect_branch_operand" ""))])
+  [(set (pc) (match_operand 0 "indirect_branch_operand" ""))]
+  ""
+{
+  if (TARGET_X32)
+    operands[0] = convert_memory_address (word_mode, operands[0]);
+})
 
 (define_insn "*indirect_jump"
-  [(set (pc) (match_operand:P 0 "indirect_branch_operand" "rw"))]
+  [(set (pc) (match_operand:W 0 "indirect_branch_operand" "rw"))]
   ""
   "jmp\t%A0"
   [(set_attr "type" "ibr")
@@ -11121,12 +11136,12 @@
       operands[0] = expand_simple_binop (Pmode, code, op0, op1, NULL_RTX, 0,
                                         OPTAB_DIRECT);
     }
-  else if (TARGET_X32)
-    operands[0] = convert_memory_address (Pmode, operands[0]);
+  if (TARGET_X32)
+    operands[0] = convert_memory_address (word_mode, operands[0]);
 })
 
 (define_insn "*tablejump_1"
-  [(set (pc) (match_operand:P 0 "indirect_branch_operand" "rw"))
+  [(set (pc) (match_operand:W 0 "indirect_branch_operand" "rw"))
    (use (label_ref (match_operand 1 "" "")))]
   ""
   "jmp\t%A0"
@@ -11213,7 +11228,7 @@
 })
 
 (define_insn_and_split "*call_vzeroupper"
-  [(call (mem:QI (match_operand:P 0 "call_insn_operand" "<c>zw"))
+  [(call (mem:QI (match_operand:C 0 "call_insn_operand" "<c>zw"))
         (match_operand 1 "" ""))
    (unspec [(match_operand 2 "const_int_operand" "")]
           UNSPEC_CALL_NEEDS_VZEROUPPER)]
@@ -11225,7 +11240,7 @@
   [(set_attr "type" "call")])
 
 (define_insn "*call"
-  [(call (mem:QI (match_operand:P 0 "call_insn_operand" "<c>zw"))
+  [(call (mem:QI (match_operand:C 0 "call_insn_operand" "<c>zw"))
         (match_operand 1 "" ""))]
   "!SIBLING_CALL_P (insn)"
   "* return ix86_output_call_insn (insn, operands[0]);"
@@ -11277,7 +11292,7 @@
   [(set_attr "type" "call")])
 
 (define_insn_and_split "*sibcall_vzeroupper"
-  [(call (mem:QI (match_operand:P 0 "sibcall_insn_operand" "Uz"))
+  [(call (mem:QI (match_operand:C 0 "sibcall_insn_operand" "Uz"))
         (match_operand 1 "" ""))
    (unspec [(match_operand 2 "const_int_operand" "")]
           UNSPEC_CALL_NEEDS_VZEROUPPER)]
@@ -11289,7 +11304,7 @@
   [(set_attr "type" "call")])
 
 (define_insn "*sibcall"
-  [(call (mem:QI (match_operand:P 0 "sibcall_insn_operand" "Uz"))
+  [(call (mem:QI (match_operand:C 0 "sibcall_insn_operand" "Uz"))
         (match_operand 1 "" ""))]
   "SIBLING_CALL_P (insn)"
   "* return ix86_output_call_insn (insn, operands[0]);"
@@ -11386,7 +11401,7 @@
 
 (define_insn_and_split "*call_value_vzeroupper"
   [(set (match_operand 0 "" "")
-       (call (mem:QI (match_operand:P 1 "call_insn_operand" "<c>zw"))
+       (call (mem:QI (match_operand:C 1 "call_insn_operand" "<c>zw"))
              (match_operand 2 "" "")))
    (unspec [(match_operand 3 "const_int_operand" "")]
           UNSPEC_CALL_NEEDS_VZEROUPPER)]
@@ -11399,7 +11414,7 @@
 
 (define_insn "*call_value"
   [(set (match_operand 0 "" "")
-       (call (mem:QI (match_operand:P 1 "call_insn_operand" "<c>zw"))
+       (call (mem:QI (match_operand:C 1 "call_insn_operand" "<c>zw"))
              (match_operand 2 "" "")))]
   "!SIBLING_CALL_P (insn)"
   "* return ix86_output_call_insn (insn, operands[1]);"
@@ -11407,7 +11422,7 @@
 
 (define_insn_and_split "*sibcall_value_vzeroupper"
   [(set (match_operand 0 "" "")
-       (call (mem:QI (match_operand:P 1 "sibcall_insn_operand" "Uz"))
+       (call (mem:QI (match_operand:C 1 "sibcall_insn_operand" "Uz"))
              (match_operand 2 "" "")))
    (unspec [(match_operand 3 "const_int_operand" "")]
           UNSPEC_CALL_NEEDS_VZEROUPPER)]
@@ -11420,7 +11435,7 @@
 
 (define_insn "*sibcall_value"
   [(set (match_operand 0 "" "")
-       (call (mem:QI (match_operand:P 1 "sibcall_insn_operand" "Uz"))
+       (call (mem:QI (match_operand:C 1 "sibcall_insn_operand" "Uz"))
              (match_operand 2 "" "")))]
   "SIBLING_CALL_P (insn)"
   "* return ix86_output_call_insn (insn, operands[1]);"
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index 32f73da..4853bff 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -492,9 +492,11 @@
        (match_test "op == ix86_tls_module_base ()")))
 
 ;; Test for a pc-relative call operand
-(define_predicate "constant_call_address_operand"
+(define_special_predicate "constant_call_address_operand"
   (match_code "symbol_ref")
 {
+  if (mode != Pmode)
+    return false;
   if (ix86_cmodel == CM_LARGE || ix86_cmodel == CM_LARGE_PIC)
     return false;
   if (TARGET_DLLIMPORT_DECL_ATTRIBUTES && SYMBOL_REF_DLLIMPORT_P (op))
@@ -506,9 +508,12 @@
 ;; is used as a call operand, so they will execute return address as a code.
 ;; See Pentium Pro errata 70, Pentium 2 errata A33 and Pentium 3 errata E17.
 
-(define_predicate "call_register_no_elim_operand"
+(define_special_predicate "call_register_no_elim_operand"
   (match_operand 0 "register_operand")
 {
+  if (mode != word_mode)
+    return false;
+
   if (GET_CODE (op) == SUBREG)
     op = SUBREG_REG (op);
 

Reply via email to