On Tue, Mar 6, 2012 at 9:57 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.
Index: predicates.md
===================================================================
--- predicates.md (revision 184992)
+++ predicates.md (working copy)
@@ -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.
@@ -557,22 +565,27 @@
(match_operand 0 "immediate_operand")))
;; Test for a valid operand for indirect branch.
+;; Allow register operands in word mode only.
(define_predicate "indirect_branch_operand"
- (if_then_else (match_test "TARGET_X32")
- (match_operand 0 "register_operand")
- (match_operand 0 "nonimmediate_operand")))
+ (ior (match_test "register_operand
+ (op, mode == VOIDmode ? mode : word_mode)")
+ (and (match_test "Pmode == word_mode")
+ (match_operand 0 "memory_operand"))))
;; Test for a valid operand for a call instruction.
+;; Allow register operands in word mode only.
(define_predicate "call_insn_operand"
(ior (match_operand 0 "constant_call_address_operand")
- (match_operand 0 "call_register_no_elim_operand")
- (and (not (match_test "TARGET_X32"))
+ (match_test "call_register_no_elim_operand
+ (op, mode == VOIDmode ? mode : word_mode)")
+ (and (match_test "Pmode == word_mode")
(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")
- (match_operand 0 "register_no_elim_operand")))
+ (match_test "register_no_elim_operand
+ (op, mode == VOIDmode ? mode : word_mode)")))
;; Match exactly zero.
(define_predicate "const0_operand"