Hello! While reviewing MPX patches, I noticed that gcc generates clobbers in the ms->sysv function call as part of the call insn pattern. The documentation recommends to generate clobbers inside the expr_list, and this is what the patch implements.
The patch further removes now unneeded specialized call patterns and related predicate. The following test: --cut here-- extern void __attribute__ ((sysv_abi)) bar (void); void foo (void) { bar (); } --cut here-- generates exactly the same register save/restore code (when compiled with -O2 -mabi=ms) as gcc-4.8.3 or gcc-4.9.1, the only difference is expected: #(call_insn:TI 5 21 40 2 (parallel [ # (call (mem:QI (symbol_ref:DI ("bar") [flags 0x41] <function_decl 0x7f3899ac9000 bar>) [0 bar S1 A8]) # (const_int 0 [0])) # (unspec [ # (const_int 0 [0]) # ] UNSPEC_MS_TO_SYSV_CALL) # (clobber (reg:TI 27 xmm6)) # (clobber (reg:TI 28 xmm7)) # (clobber (reg:TI 45 xmm8)) # (clobber (reg:TI 46 xmm9)) # (clobber (reg:TI 47 xmm10)) # (clobber (reg:TI 48 xmm11)) # (clobber (reg:TI 49 xmm12)) # (clobber (reg:TI 50 xmm13)) # (clobber (reg:TI 51 xmm14)) # (clobber (reg:TI 52 xmm15)) # (clobber (reg:DI 4 si)) # (clobber (reg:DI 5 di)) # ]) msabi.c:7 657 {*call_rex64_ms_sysv} # (nil) # (nil)) call bar # 5 *call_rex64_ms_sysv [length = 6] vs. (gcc-5.0.0): #(call_insn:TI 5 22 41 2 (call (mem:QI (symbol_ref:DI ("bar") [flags 0x41] <function_decl 0x7fd08e8f26c0 bar>) [0 bar S1 A8]) # (const_int 0 [0])) msabi.c:7 652 {*call} # (expr_list:REG_CALL_DECL (symbol_ref:DI ("bar") [flags 0x41] <function_decl 0x7fd08e8f26c0 bar>) # (nil)) # (expr_list (clobber (reg:TI 52 xmm15)) # (expr_list (clobber (reg:TI 51 xmm14)) # (expr_list (clobber (reg:TI 50 xmm13)) # (expr_list (clobber (reg:TI 49 xmm12)) # (expr_list (clobber (reg:TI 48 xmm11)) # (expr_list (clobber (reg:TI 47 xmm10)) # (expr_list (clobber (reg:TI 46 xmm9)) # (expr_list (clobber (reg:TI 45 xmm8)) # (expr_list (clobber (reg:TI 28 xmm7)) # (expr_list (clobber (reg:TI 27 xmm6)) # (expr_list (clobber (reg:DI 5 di)) # (expr_list (clobber (reg:DI 4 si)) # (nil)))))))))))))) call bar # 5 *call [length = 5] 2014-09-21 Uros Bizjak <ubiz...@gmail.com> * config/i386/i386.c (ix86_expand_call): Generate MS->SYSV extra clobbered registers using clobber_reg. Remove UNSPEC decoration. * config/i386/i386.md (unspec) <UNSPEC_MS_TO_SYSV_CALL>: Remove. (*call_rex64_ms_sysv): Remove. (*call_value_rex64_ms_sysv): Ditto. * config/i386/predicates.md (call_rex64_ms_sysv_operation): Remove. testsuite/ChangeLog: 2014-09-21 Uros Bizjak <ubiz...@gmail.com> * gcc.target/i386/avx-vzeroupper-16.c (dg-final): Remove check for call_value_rex64_ms_sysv. * gcc.target/i386/avx-vzeroupper-17.c (dg-final): Ditto. * gcc.target/i386/avx-vzeroupper-18.c (dg-final): Remove check for call_rex64_ms_sysv. The patch was bootstrapped and regression tested on x86_64-pc-linux-gnu {,-m32} and was committed to mainline SVN. Uros.
Index: config/i386/i386.c =================================================================== --- config/i386/i386.c (revision 215427) +++ config/i386/i386.c (working copy) @@ -24865,9 +24865,7 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx call rtx callarg2, rtx pop, bool sibcall) { - unsigned int const cregs_size - = ARRAY_SIZE (x86_64_ms_sysv_extra_clobbered_registers); - rtx vec[3 + cregs_size]; + rtx vec[3]; rtx use = NULL, call; unsigned int vec_len = 0; @@ -24930,18 +24928,16 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx call if (TARGET_64BIT_MS_ABI && (!callarg2 || INTVAL (callarg2) != -2)) { - unsigned i; + int const cregs_size + = ARRAY_SIZE (x86_64_ms_sysv_extra_clobbered_registers); + int i; - vec[vec_len++] = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, const0_rtx), - UNSPEC_MS_TO_SYSV_CALL); - 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)); + clobber_reg (&use, gen_rtx_REG (mode, regno)); } } Index: config/i386/i386.md =================================================================== --- config/i386/i386.md (revision 215427) +++ config/i386/i386.md (working copy) @@ -106,7 +106,6 @@ UNSPEC_LD_MPIC ; load_macho_picbase UNSPEC_TRUNC_NOOP UNSPEC_DIV_ALREADY_SPLIT - UNSPEC_MS_TO_SYSV_CALL UNSPEC_PAUSE UNSPEC_LEA_ADDR UNSPEC_XBEGIN_ABORT @@ -11477,15 +11476,6 @@ "* return ix86_output_call_insn (insn, operands[0]);" [(set_attr "type" "call")]) -(define_insn "*call_rex64_ms_sysv" - [(match_parallel 2 "call_rex64_ms_sysv_operation" - [(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rBwBz")) - (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")]) - (define_insn "*sibcall" [(call (mem:QI (match_operand:W 0 "sibcall_insn_operand" "UBsBz")) (match_operand 1))] @@ -11693,16 +11683,6 @@ (match_dup 3))) (unspec [(const_int 0)] UNSPEC_PEEPSIB)])]) -(define_insn "*call_value_rex64_ms_sysv" - [(match_parallel 3 "call_rex64_ms_sysv_operation" - [(set (match_operand 0) - (call (mem:QI (match_operand:DI 1 "call_insn_operand" "rBwBz")) - (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")]) - (define_expand "call_value_pop" [(parallel [(set (match_operand 0) (call (match_operand:QI 1) Index: config/i386/predicates.md =================================================================== --- config/i386/predicates.md (revision 215427) +++ config/i386/predicates.md (working copy) @@ -609,36 +609,6 @@ (and (not (match_test "TARGET_X32")) (match_operand 0 "sibcall_memory_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") Index: testsuite/gcc.target/i386/avx-vzeroupper-16.c =================================================================== --- testsuite/gcc.target/i386/avx-vzeroupper-16.c (revision 215427) +++ testsuite/gcc.target/i386/avx-vzeroupper-16.c (working copy) @@ -14,4 +14,3 @@ foo (void) } /* { dg-final { scan-assembler-times "avx_vzeroupper" 1 } } */ -/* { dg-final { scan-assembler-times "\\*call_value_rex64_ms_sysv" 1 } } */ Index: testsuite/gcc.target/i386/avx-vzeroupper-17.c =================================================================== --- testsuite/gcc.target/i386/avx-vzeroupper-17.c (revision 215427) +++ testsuite/gcc.target/i386/avx-vzeroupper-17.c (working copy) @@ -14,4 +14,3 @@ foo (void) } /* { dg-final { scan-assembler-times "avx_vzeroupper" 1 } } */ -/* { dg-final { scan-assembler-times "\\*call_value_rex64_ms_sysv" 1 } } */ Index: testsuite/gcc.target/i386/avx-vzeroupper-18.c =================================================================== --- testsuite/gcc.target/i386/avx-vzeroupper-18.c (revision 215427) +++ testsuite/gcc.target/i386/avx-vzeroupper-18.c (working copy) @@ -14,4 +14,3 @@ foo (void) } /* { dg-final { scan-assembler-not "avx_vzeroupper" } } */ -/* { dg-final { scan-assembler-times "\\*call_rex64_ms_sysv" 1 } } */