On Sat, Mar 10, 2012 at 5:05 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 > > I tested this patch and it passed all my x32 tests. Committed to mainline with following ChangeLog: 2012-03-11 H.J. Lu <hongjiu...@intel.com> Uros Bizjak <ubiz...@gmail.com> * 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.