[PATCH, i386]: Properly generate clobbered regs in ms->sysv function call

Uros Bizjak ubizjak@gmail.com
Sun Sep 21 15:23:00 GMT 2014


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  <ubizjak@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  <ubizjak@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.
-------------- next part --------------
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 } } */


More information about the Gcc-patches mailing list