diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 861320b612b..7b796775588 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2011-08-04 Richard Henderson + + PR target/49964 + * config/i386/i386.c (ix86_expand_call): Don't create nested + PARALLELs for TARGET_VZEROUPPER. + (ix86_split_call_vzeroupper): Fix extraction of the original call. + * config/i386/i386.md (*call_rex64_ms_sysv_vzeroupper): Don't + recognize nested PARALLELs. + (*call_pop_vzeroupper, *sibcall_pop_vzeroupper, + *call_value_rex64_ms_sysv_vzeroupper, *call_value_pop_vzeroupper, + *sibcall_value_pop_vzeroupper): Likewise. + 2011-08-04 Richard Henderson PR middle-end/49968 diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 0e4f3f46de6..a7f8ee5bdf3 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -21501,7 +21501,17 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1, 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]; rtx use = NULL, call; + unsigned int vec_len; if (pop == const0_rtx) pop = NULL; @@ -21545,52 +21555,40 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1, fnaddr = gen_rtx_MEM (QImode, copy_to_mode_reg (Pmode, fnaddr)); } + vec_len = 0; call = gen_rtx_CALL (VOIDmode, fnaddr, callarg1); if (retval) call = gen_rtx_SET (VOIDmode, retval, call); + vec[vec_len++] = call; + if (pop) { pop = gen_rtx_PLUS (Pmode, stack_pointer_rtx, pop); pop = gen_rtx_SET (VOIDmode, stack_pointer_rtx, pop); - call = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, call, pop)); + vec[vec_len++] = pop; } + if (TARGET_64BIT_MS_ABI && (!callarg2 || INTVAL (callarg2) != -2)) { - /* 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 - }; - unsigned int i; - rtx vec[ARRAY_SIZE (clobbered_registers) + 2]; - rtx unspec = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, const0_rtx), - UNSPEC_MS_TO_SYSV_CALL); + unsigned i; + + vec[vec_len++] = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, const0_rtx), + UNSPEC_MS_TO_SYSV_CALL); - vec[0] = call; - vec[1] = unspec; for (i = 0; i < ARRAY_SIZE (clobbered_registers); i++) - vec[i + 2] = gen_rtx_CLOBBER (SSE_REGNO_P (clobbered_registers[i]) - ? TImode : DImode, - gen_rtx_REG - (SSE_REGNO_P (clobbered_registers[i]) - ? TImode : DImode, - clobbered_registers[i])); - - call = gen_rtx_PARALLEL (VOIDmode, - gen_rtvec_v (ARRAY_SIZE (clobbered_registers) - + 2, vec)); + vec[vec_len++] + = gen_rtx_CLOBBER (SSE_REGNO_P (clobbered_registers[i]) + ? TImode : DImode, + gen_rtx_REG (SSE_REGNO_P (clobbered_registers[i]) + ? TImode : DImode, + clobbered_registers[i])); } /* Add UNSPEC_CALL_NEEDS_VZEROUPPER decoration. */ if (TARGET_VZEROUPPER) { - rtx unspec; int avx256; - if (cfun->machine->callee_pass_avx256_p) { if (cfun->machine->callee_return_avx256_p) @@ -21606,15 +21604,13 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1, if (reload_completed) emit_insn (gen_avx_vzeroupper (GEN_INT (avx256))); else - { - unspec = gen_rtx_UNSPEC (VOIDmode, - gen_rtvec (1, GEN_INT (avx256)), - UNSPEC_CALL_NEEDS_VZEROUPPER); - call = gen_rtx_PARALLEL (VOIDmode, - gen_rtvec (2, call, unspec)); - } + vec[vec_len++] = gen_rtx_UNSPEC (VOIDmode, + gen_rtvec (1, GEN_INT (avx256)), + UNSPEC_CALL_NEEDS_VZEROUPPER); } + if (vec_len > 1) + call = gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (vec_len, vec)); call = emit_call_insn (call); if (use) CALL_INSN_FUNCTION_USAGE (call) = use; @@ -21625,9 +21621,20 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1, void ix86_split_call_vzeroupper (rtx insn, rtx vzeroupper) { - rtx call = XVECEXP (PATTERN (insn), 0, 0); + rtx pat = PATTERN (insn); + rtvec vec = XVEC (pat, 0); + int len = GET_NUM_ELEM (vec) - 1; + + /* Strip off the last entry of the parallel. */ + gcc_assert (GET_CODE (RTVEC_ELT (vec, len)) == UNSPEC); + gcc_assert (XINT (RTVEC_ELT (vec, len), 1) == UNSPEC_CALL_NEEDS_VZEROUPPER); + if (len == 1) + pat = RTVEC_ELT (vec, 0); + else + pat = gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (len, &RTVEC_ELT (vec, 0))); + emit_insn (gen_avx_vzeroupper (vzeroupper)); - emit_call_insn (call); + emit_call_insn (pat); } /* Output the assembly for a call instruction. */ diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 3a07d4e3c00..245ee54785c 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -11050,22 +11050,21 @@ [(set_attr "type" "call")]) (define_insn_and_split "*call_rex64_ms_sysv_vzeroupper" - [(parallel - [(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))]) + [(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)) (unspec [(match_operand 2 "const_int_operand" "")] UNSPEC_CALL_NEEDS_VZEROUPPER)] "TARGET_VZEROUPPER && TARGET_64BIT && !SIBLING_CALL_P (insn)" @@ -11128,12 +11127,11 @@ }) (define_insn_and_split "*call_pop_vzeroupper" - [(parallel - [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "lzm")) - (match_operand:SI 1 "" "")) - (set (reg:SI SP_REG) - (plus:SI (reg:SI SP_REG) - (match_operand:SI 2 "immediate_operand" "i")))]) + [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "lzm")) + (match_operand:SI 1 "" "")) + (set (reg:SI SP_REG) + (plus:SI (reg:SI SP_REG) + (match_operand:SI 2 "immediate_operand" "i"))) (unspec [(match_operand 3 "const_int_operand" "")] UNSPEC_CALL_NEEDS_VZEROUPPER)] "TARGET_VZEROUPPER && !TARGET_64BIT && !SIBLING_CALL_P (insn)" @@ -11154,12 +11152,11 @@ [(set_attr "type" "call")]) (define_insn_and_split "*sibcall_pop_vzeroupper" - [(parallel - [(call (mem:QI (match_operand:SI 0 "sibcall_insn_operand" "Uz")) - (match_operand 1 "" "")) - (set (reg:SI SP_REG) - (plus:SI (reg:SI SP_REG) - (match_operand:SI 2 "immediate_operand" "i")))]) + [(call (mem:QI (match_operand:SI 0 "sibcall_insn_operand" "Uz")) + (match_operand 1 "" "")) + (set (reg:SI SP_REG) + (plus:SI (reg:SI SP_REG) + (match_operand:SI 2 "immediate_operand" "i"))) (unspec [(match_operand 3 "const_int_operand" "")] UNSPEC_CALL_NEEDS_VZEROUPPER)] "TARGET_VZEROUPPER && !TARGET_64BIT && SIBLING_CALL_P (insn)" @@ -11248,23 +11245,22 @@ [(set_attr "type" "callv")]) (define_insn_and_split "*call_value_rex64_ms_sysv_vzeroupper" - [(parallel - [(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))]) + [(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)) (unspec [(match_operand 3 "const_int_operand" "")] UNSPEC_CALL_NEEDS_VZEROUPPER)] "TARGET_VZEROUPPER && TARGET_64BIT && !SIBLING_CALL_P (insn)" @@ -11310,13 +11306,12 @@ }) (define_insn_and_split "*call_value_pop_vzeroupper" - [(parallel - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:SI 1 "call_insn_operand" "lzm")) - (match_operand 2 "" ""))) - (set (reg:SI SP_REG) - (plus:SI (reg:SI SP_REG) - (match_operand:SI 3 "immediate_operand" "i")))]) + [(set (match_operand 0 "" "") + (call (mem:QI (match_operand:SI 1 "call_insn_operand" "lzm")) + (match_operand 2 "" ""))) + (set (reg:SI SP_REG) + (plus:SI (reg:SI SP_REG) + (match_operand:SI 3 "immediate_operand" "i"))) (unspec [(match_operand 4 "const_int_operand" "")] UNSPEC_CALL_NEEDS_VZEROUPPER)] "TARGET_VZEROUPPER && !TARGET_64BIT && !SIBLING_CALL_P (insn)" @@ -11338,13 +11333,12 @@ [(set_attr "type" "callv")]) (define_insn_and_split "*sibcall_value_pop_vzeroupper" - [(parallel - [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:SI 1 "sibcall_insn_operand" "Uz")) - (match_operand 2 "" ""))) - (set (reg:SI SP_REG) - (plus:SI (reg:SI SP_REG) - (match_operand:SI 3 "immediate_operand" "i")))]) + [(set (match_operand 0 "" "") + (call (mem:QI (match_operand:SI 1 "sibcall_insn_operand" "Uz")) + (match_operand 2 "" ""))) + (set (reg:SI SP_REG) + (plus:SI (reg:SI SP_REG) + (match_operand:SI 3 "immediate_operand" "i"))) (unspec [(match_operand 4 "const_int_operand" "")] UNSPEC_CALL_NEEDS_VZEROUPPER)] "TARGET_VZEROUPPER && !TARGET_64BIT && SIBLING_CALL_P (insn)"