Hello! Attached patch avoids explicit clobbers in *call_value_rex64_ms_sysv and *call_rex64_ms_sysv by introducing call_rex64_ms_sysv_operation predicate. In addition to simplified pattern, the insn RTX pattern is now constructed from the same array as it is generated from.
2013-04-18 Uros Bizjak <ubiz...@gmail.com> * config/i386/i386.c (x86_64_ms_sysv_extra_clobbered_registers): New array. (ix86_expand_call): Remove clobbered_registers array and use x86_64_ms_sysv_extra_clobbered_registers instead. * config/i386/i386.h (x86_64_ms_sysv_extra_clobbered_registers): Declare here. * config/i386/predicates.md (call_rex64_ms_sysv_operation): New predicate. * config/i386/i386.md (*call_rex64_ms_sysv): Use call_rex64_ms_sysv_operation predicate. Remove explicit clobbers. (*call_value_rex64_ms_sysv): Ditto. Tested on x86_64-pc-linux-gnu {,-m32} and committed to mainline SVN. Uros.
Index: config/i386/i386.c =================================================================== --- config/i386/i386.c (revision 198056) +++ config/i386/i386.c (working copy) @@ -2216,6 +2216,16 @@ static int const x86_64_int_return_registers[4] = AX_REG, DX_REG, DI_REG, SI_REG }; +/* Additional registers that are clobbered by SYSV calls. */ + +int const x86_64_ms_sysv_extra_clobbered_registers[12] = +{ + SI_REG, DI_REG, + XMM6_REG, XMM7_REG, + XMM8_REG, XMM9_REG, XMM10_REG, XMM11_REG, + XMM12_REG, XMM13_REG, XMM14_REG, XMM15_REG +}; + /* Define the structure for the machine field in struct function. */ struct GTY(()) stack_local_entry { @@ -23704,17 +23714,10 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx call rtx callarg2, rtx pop, bool sibcall) { - /* We need to represent that SI and DI registers are clobbered - by SYSV calls. */ - static int clobbered_registers[] = { - XMM6_REG, XMM7_REG, XMM8_REG, - XMM9_REG, XMM10_REG, XMM11_REG, - XMM12_REG, XMM13_REG, XMM14_REG, - XMM15_REG, SI_REG, DI_REG - }; - rtx vec[ARRAY_SIZE (clobbered_registers) + 3]; + int const cregs_size = ARRAY_SIZE (x86_64_ms_sysv_extra_clobbered_registers); + rtx vec[3 + cregs_size]; rtx use = NULL, call; - unsigned int vec_len; + unsigned int vec_len = 0; if (pop == const0_rtx) pop = NULL; @@ -23730,8 +23733,10 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx call else { /* Static functions and indirect calls don't need the pic register. */ - if (flag_pic && (!TARGET_64BIT - || (ix86_cmodel == CM_LARGE_PIC && DEFAULT_ABI != MS_ABI)) + if (flag_pic + && (!TARGET_64BIT + || (ix86_cmodel == CM_LARGE_PIC + && DEFAULT_ABI != MS_ABI)) && GET_CODE (XEXP (fnaddr, 0)) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (XEXP (fnaddr, 0))) use_reg (&use, pic_offset_table_rtx); @@ -23758,7 +23763,6 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx call fnaddr = gen_rtx_MEM (QImode, copy_to_mode_reg (word_mode, fnaddr)); } - vec_len = 0; call = gen_rtx_CALL (VOIDmode, fnaddr, callarg1); if (retval) call = gen_rtx_SET (VOIDmode, retval, call); @@ -23779,12 +23783,14 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx call vec[vec_len++] = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, const0_rtx), UNSPEC_MS_TO_SYSV_CALL); - for (i = 0; i < ARRAY_SIZE (clobbered_registers); i++) - vec[vec_len++] - = gen_rtx_CLOBBER (VOIDmode, - gen_rtx_REG (SSE_REGNO_P (clobbered_registers[i]) - ? TImode : DImode, - clobbered_registers[i])); + for (i = 0; i < cregs_size; i++) + { + int regno = x86_64_ms_sysv_extra_clobbered_registers[i]; + enum machine_mode mode = SSE_REGNO_P (regno) ? TImode : DImode; + + vec[vec_len++] + = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (mode, regno)); + } } if (vec_len > 1) Index: config/i386/i386.h =================================================================== --- config/i386/i386.h (revision 198056) +++ config/i386/i386.h (working copy) @@ -1963,6 +1963,8 @@ extern int const dbx_register_map[FIRST_PSEUDO_REG extern int const dbx64_register_map[FIRST_PSEUDO_REGISTER]; extern int const svr4_dbx_register_map[FIRST_PSEUDO_REGISTER]; +extern int const x86_64_ms_sysv_extra_clobbered_registers[12]; + /* Before the prologue, RA is at 0(%esp). */ #define INCOMING_RETURN_ADDR_RTX \ gen_rtx_MEM (VOIDmode, gen_rtx_REG (VOIDmode, STACK_POINTER_REGNUM)) Index: config/i386/i386.md =================================================================== --- config/i386/i386.md (revision 198056) +++ config/i386/i386.md (working copy) @@ -10903,21 +10903,10 @@ [(set_attr "type" "call")]) (define_insn "*call_rex64_ms_sysv" - [(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rzw")) - (match_operand 1)) - (unspec [(const_int 0)] UNSPEC_MS_TO_SYSV_CALL) - (clobber (reg:TI XMM6_REG)) - (clobber (reg:TI XMM7_REG)) - (clobber (reg:TI XMM8_REG)) - (clobber (reg:TI XMM9_REG)) - (clobber (reg:TI XMM10_REG)) - (clobber (reg:TI XMM11_REG)) - (clobber (reg:TI XMM12_REG)) - (clobber (reg:TI XMM13_REG)) - (clobber (reg:TI XMM14_REG)) - (clobber (reg:TI XMM15_REG)) - (clobber (reg:DI SI_REG)) - (clobber (reg:DI DI_REG))] + [(match_parallel 2 "call_rex64_ms_sysv_operation" + [(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rzw")) + (match_operand 1)) + (unspec [(const_int 0)] UNSPEC_MS_TO_SYSV_CALL)])] "TARGET_64BIT && !SIBLING_CALL_P (insn)" "* return ix86_output_call_insn (insn, operands[0]);" [(set_attr "type" "call")]) @@ -11005,23 +10994,12 @@ [(set_attr "type" "callv")]) (define_insn "*call_value_rex64_ms_sysv" - [(set (match_operand 0) - (call (mem:QI (match_operand:DI 1 "call_insn_operand" "rzw")) - (match_operand 2))) - (unspec [(const_int 0)] UNSPEC_MS_TO_SYSV_CALL) - (clobber (reg:TI XMM6_REG)) - (clobber (reg:TI XMM7_REG)) - (clobber (reg:TI XMM8_REG)) - (clobber (reg:TI XMM9_REG)) - (clobber (reg:TI XMM10_REG)) - (clobber (reg:TI XMM11_REG)) - (clobber (reg:TI XMM12_REG)) - (clobber (reg:TI XMM13_REG)) - (clobber (reg:TI XMM14_REG)) - (clobber (reg:TI XMM15_REG)) - (clobber (reg:DI SI_REG)) - (clobber (reg:DI DI_REG))] - "TARGET_64BIT && !SIBLING_CALL_P (insn)" + [(match_parallel 3 "call_rex64_ms_sysv_operation" + [(set (match_operand 0) + (call (mem:QI (match_operand:DI 1 "call_insn_operand" "rzw")) + (match_operand 2))) + (unspec [(const_int 0)] UNSPEC_MS_TO_SYSV_CALL)])] + "TARGET_64BIT && !SIBLING_CALL_P (insn)" "* return ix86_output_call_insn (insn, operands[1]);" [(set_attr "type" "callv")]) Index: config/i386/predicates.md =================================================================== --- config/i386/predicates.md (revision 198056) +++ config/i386/predicates.md (working copy) @@ -573,6 +573,36 @@ (op, mode == VOIDmode ? mode : Pmode)") (match_operand 0 "register_no_elim_operand"))) +;; Return true if OP is a call from MS ABI to SYSV ABI function. +(define_predicate "call_rex64_ms_sysv_operation" + (match_code "parallel") +{ + unsigned creg_size = ARRAY_SIZE (x86_64_ms_sysv_extra_clobbered_registers); + unsigned i; + + if ((unsigned) XVECLEN (op, 0) != creg_size + 2) + return false; + + for (i = 0; i < creg_size; i++) + { + rtx elt = XVECEXP (op, 0, i+2); + enum machine_mode mode; + unsigned regno; + + if (GET_CODE (elt) != CLOBBER + || GET_CODE (SET_DEST (elt)) != REG) + return false; + + regno = x86_64_ms_sysv_extra_clobbered_registers[i]; + mode = SSE_REGNO_P (regno) ? TImode : DImode; + + if (GET_MODE (SET_DEST (elt)) != mode + || REGNO (SET_DEST (elt)) != regno) + return false; + } + return true; +}) + ;; Match exactly zero. (define_predicate "const0_operand" (match_code "const_int,const_double,const_vector")