On Sat, Mar 10, 2012 at 5:05 PM, H.J. Lu <[email protected]> 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
>
> I tested this patch and it passed all my x32 tests.
Committed to mainline with following ChangeLog:
2012-03-11 H.J. Lu <[email protected]>
Uros Bizjak <[email protected]>
* config/i386/predicates.md (call_insn_operand): Allow
constant_call_address_operand in Pmode only.
(sibcall_insn_operand): Ditto.
* config/i386/i386.md (*call): Use W mode iterator instead of P mode.
(*call_vzeroupper): Ditto.
(*sibcall): Ditto.
(*sibcall_vzeroupper): Ditto.
(*call_value): Ditto.
(*call_value_vzeroupper): Ditto.
(*sibcall_value): Ditto.
(*sibcall_value_vzeroupper): Ditto.
(*indirect_jump): Ditto.
(*tablejump_1): Ditto.
(indirect_jump): Convert memory address to word mode for TARGET_X32.
(tablejump): Ditto.
* config/i386/i386.c (ix86_expand_call): Convert indirect operands
to word mode.
Uros.