On Wed, Mar 7, 2012 at 1:58 PM, Uros Bizjak <ubiz...@gmail.com> wrote:
> On Wed, Mar 7, 2012 at 5:03 PM, H.J. Lu <hjl.to...@gmail.com> 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.
>>>>
>>>> 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?
>>>
>>> Please do not complicate matters that much. Just stick word_mode
>>> overrides for register operands in predicates.md, like in attached
>>> patch. These changed predicates now allow registers only in word_mode
>>> (and VOIDmode).
>>>
>>> You can now remove all new mode iterators and leave call patterns untouched.
>>>
>>> @@ -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;
>>>
>>> Please update the above part. It looks you don't even have to change
>>> condition with new predicates. Basically, you should only convert the
>>> address to word_mode instead of Pmode.
>>>
>>> +  if (TARGET_X32)
>>> +    operands[0] = convert_memory_address (word_mode, operands[0]);
>>>
>>> This addition to indirect_jump and tablejump should be the only
>>> change, needed in i386.md now. Please write the condition
>>>
>>> if (Pmode != word_mode)
>>>
>>> for consistency.
>>>
>>> BTW: The attached patch was bootstrapped and regression tested on
>>> x86_64-pc-linux-gnu {,-m32}.
>>>
>>> Uros.
>>
>> It doesn't work:
>>
>> x.i:7:1: error: unrecognizable insn:
>> (call_insn/j 8 7 9 3 (call (mem:QI (reg:DI 62) [0 *foo.0_1 S1 A8])
>>        (const_int 0 [0])) x.i:6 -1
>>     (nil)
>>    (nil))
>> x.i:7:1: internal compiler error: in extract_insn, at recog.c:2123
>> Please submit a full bug report,
>> with preprocessed source if appropriate.
>> See <http://gcc.gnu.org/bugs.html> for instructions.
>> make: *** [x.s] Error 1
>>
>> I will investigate it.
>
> For reference, attached is the complete patch that uses
> define_special_predicate. This patch works OK with the current
> mainline, with additional patch to i386.h, where
>
> Index: i386.h
> ===================================================================
> --- i386.h      (revision 185079)
> +++ i386.h      (working copy)
> @@ -1744,7 +1744,7 @@
>  /* Specify the machine mode that pointers have.
>    After generation of rtl, the compiler makes no further distinction
>    between pointers and any other objects of this machine mode.  */
> -#define Pmode (TARGET_64BIT ? DImode : SImode)
> +#define Pmode (TARGET_LP64 ? DImode : SImode)
>
>  /* A C expression whose value is zero if pointers that need to be extended
>    from being `POINTER_SIZE' bits wide to `Pmode' are sign-extended and
>
> Uros.

I tested this patch and it passed all my x32 tests.

Thanks.

-- 
H.J.
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index c2cad5a..33ef330 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -23032,13 +23031,13 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx 
callarg1,
       && !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))
+          ? !sibcall_insn_operand (XEXP (fnaddr, 0), word_mode)
+          : !call_insn_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 e3b5bd2..3994b1e 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -11091,10 +11091,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")
@@ -11136,12 +11141,13 @@
       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"
@@ -11228,7 +11234,7 @@
 })
 
 (define_insn_and_split "*call_vzeroupper"
-  [(call (mem:QI (match_operand:P 0 "call_insn_operand" "<c>zw"))
+  [(call (mem:QI (match_operand:W 0 "call_insn_operand" "<c>zw"))
         (match_operand 1 "" ""))
    (unspec [(match_operand 2 "const_int_operand" "")]
           UNSPEC_CALL_NEEDS_VZEROUPPER)]
@@ -11240,7 +11246,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:W 0 "call_insn_operand" "<c>zw"))
         (match_operand 1 "" ""))]
   "!SIBLING_CALL_P (insn)"
   "* return ix86_output_call_insn (insn, operands[0]);"
@@ -11292,7 +11298,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:W 0 "sibcall_insn_operand" "Uz"))
         (match_operand 1 "" ""))
    (unspec [(match_operand 2 "const_int_operand" "")]
           UNSPEC_CALL_NEEDS_VZEROUPPER)]
@@ -11304,7 +11310,7 @@
   [(set_attr "type" "call")])
 
 (define_insn "*sibcall"
-  [(call (mem:QI (match_operand:P 0 "sibcall_insn_operand" "Uz"))
+  [(call (mem:QI (match_operand:W 0 "sibcall_insn_operand" "Uz"))
         (match_operand 1 "" ""))]
   "SIBLING_CALL_P (insn)"
   "* return ix86_output_call_insn (insn, operands[0]);"
@@ -11401,7 +11407,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:W 1 "call_insn_operand" "<c>zw"))
              (match_operand 2 "" "")))
    (unspec [(match_operand 3 "const_int_operand" "")]
           UNSPEC_CALL_NEEDS_VZEROUPPER)]
@@ -11414,7 +11420,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:W 1 "call_insn_operand" "<c>zw"))
              (match_operand 2 "" "")))]
   "!SIBLING_CALL_P (insn)"
   "* return ix86_output_call_insn (insn, operands[1]);"
@@ -11422,7 +11428,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:W 1 "sibcall_insn_operand" "Uz"))
              (match_operand 2 "" "")))
    (unspec [(match_operand 3 "const_int_operand" "")]
           UNSPEC_CALL_NEEDS_VZEROUPPER)]
@@ -11435,7 +11441,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:W 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 dad8bf3..7e0e1ef 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -1,5 +1,5 @@
 ;; Predicate definitions for IA-32 and x86-64.
-;; Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
+;; Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
 ;; Free Software Foundation, Inc.
 ;;
 ;; This file is part of GCC.
@@ -571,15 +571,18 @@
            (match_operand 0 "memory_operand"))))
 
 ;; Test for a valid operand for a call instruction.
-(define_predicate "call_insn_operand"
-  (ior (match_operand 0 "constant_call_address_operand")
+;; Allow constant call address operands in Pmode only.
+(define_special_predicate "call_insn_operand"
+  (ior (match_test "constant_call_address_operand
+                    (op, mode == VOIDmode ? mode : Pmode)")
        (match_operand 0 "call_register_no_elim_operand")
        (and (not (match_test "TARGET_X32"))
            (match_operand 0 "memory_operand"))))
 
 ;; Similarly, but for tail calls, in which we cannot allow memory references.
-(define_predicate "sibcall_insn_operand"
-  (ior (match_operand 0 "constant_call_address_operand")
+(define_special_predicate "sibcall_insn_operand"
+  (ior (match_test "constant_call_address_operand
+                    (op, mode == VOIDmode ? mode : Pmode)")
        (match_operand 0 "register_no_elim_operand")))
 
 ;; Match exactly zero.

Reply via email to