https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88717

--- Comment #4 from 刘袋鼠 <crazylht at gmail dot com> ---
(In reply to H.J. Lu from comment #3)
> Like this
> 
> diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
> index d01278d866f..9b49a2c1d9c 100644
> --- a/gcc/config/i386/i386.c
> +++ b/gcc/config/i386/i386.c
> @@ -19100,7 +19100,11 @@ ix86_avx_u128_mode_entry (void)
>        rtx incoming = DECL_INCOMING_RTL (arg);
>  
>        if (incoming && ix86_check_avx_upper_register (incoming))
> -     return AVX_U128_DIRTY;
> +     {
> +       /* Caller is AVX_U128_DIRTY.  */
> +       cfun->machine->caller_avx_u128_dirty = true;
> +       return AVX_U128_DIRTY;
> +     }
>      }
>  
>    return AVX_U128_CLEAN;
> @@ -19130,6 +19134,10 @@ ix86_mode_entry (int entity)
>  static int
>  ix86_avx_u128_mode_exit (void)
>  {
> +  /* Exit mode is set to AVX_U128_DIRTY if caller is AVX_U128_DIRTY.  */
> +  if (cfun->machine->caller_avx_u128_dirty)
> +    return AVX_U128_DIRTY;
> +
>    rtx reg = crtl->return_rtx;
>  
>    /* Exit mode is set to AVX_U128_DIRTY if there are 256bit
> diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
> index 83b025e0cf5..c053b657a55 100644
> --- a/gcc/config/i386/i386.h
> +++ b/gcc/config/i386/i386.h
> @@ -2747,6 +2747,9 @@ struct GTY(()) machine_function {
>    /* If true, ENDBR is queued at function entrance.  */
>    BOOL_BITFIELD endbr_queued_at_entrance : 1;
>  
> +  /* If true, caller is AVX_U128_DIRTY.  */
> +  BOOL_BITFIELD caller_avx_u128_dirty : 1;
> +
>    /* The largest alignment, in bytes, of stack slot actually used.  */
>    unsigned int max_used_stack_alignment;


My thought is AVX_U128_DIRTY would be set when ymm/zmm appeared, and
AVX_U128_CLEAN for xmm, AVX_U128_ANY for other situations. This also works for
this case.

diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 61dbc95c086..233f46c116b 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -18912,6 +18912,12 @@ ix86_check_avx_upper_register (const_rtx exp)
   return SSE_REG_P (exp) && GET_MODE_BITSIZE (GET_MODE (exp)) > 128;
 }

+/* Check if a 128bit SSE register is referenced inside of EXP. */
+static bool
+ix86_check_sse_register (const_rtx exp)
+{
+  return SSE_REG_P (exp) && GET_MODE_BITSIZE (GET_MODE (exp)) == 128;
+}
 /* Return needed mode for entity in optimize_mode_switching pass.  */

 static int
@@ -18920,6 +18926,7 @@ ix86_avx_u128_mode_needed (rtx_insn *insn)
   if (CALL_P (insn))
     {
       rtx link;
+      bool flag_clean = 0;

       /* Needed mode is set to AVX_U128_CLEAN if there are
         no 256bit or 512bit modes used in function arguments. */
@@ -18933,10 +18940,14 @@ ix86_avx_u128_mode_needed (rtx_insn *insn)

              if (ix86_check_avx_upper_register (arg))
                return AVX_U128_DIRTY;
+             if (ix86_check_sse_register (arg))
+               flag_clean = true;
            }
        }

-      return AVX_U128_CLEAN;
+      if(flag_clean)
+       return AVX_U128_CLEAN;
+      return AVX_U128_ANY;
     }

   /* Require DIRTY mode if a 256bit or 512bit AVX register is referenced.
@@ -19033,6 +19044,15 @@ ix86_check_avx_upper_stores (rtx dest, const_rtx, void
*data)
     }
  } 

+static void
+ix86_check_sse_stores (rtx dest, const_rtx, void *data)
+{
+  if (ix86_check_sse_register (dest))
+  {
+    bool *used = (bool *)data;
+    *used = true;
+  }
+}
 /* Calculate mode of upper 128bit AVX registers after the insn.  */

 static int
@@ -19049,9 +19069,10 @@ ix86_avx_u128_mode_after (int mode, rtx_insn *insn)
   if (CALL_P (insn))
     {
       bool avx_upper_reg_found = false;
+      bool sse_reg_found = false;
       note_stores (pat, ix86_check_avx_upper_stores, &avx_upper_reg_found);
-
-      return avx_upper_reg_found ? AVX_U128_DIRTY : AVX_U128_CLEAN;
+      note_stores (pat, ix86_check_sse_stores, &sse_reg_found);
+      return avx_upper_reg_found ? AVX_U128_DIRTY : sse_reg_found ?
AVX_U128_CLEAN : AVX_U128_ANY;
     }

   /* Otherwise, return current mode.  Remember that if insn
@@ -19096,7 +19117,7 @@ static int
 ix86_avx_u128_mode_entry (void)
 {
   tree arg;
-
+  bool flag_clean = false;
   /* Entry mode is set to AVX_U128_DIRTY if there are
      256bit or 512bit modes used in function arguments.  */
   for (arg = DECL_ARGUMENTS (current_function_decl); arg;
@@ -19106,9 +19127,14 @@ ix86_avx_u128_mode_entry (void)

       if (incoming && ix86_check_avx_upper_register (incoming))
        return AVX_U128_DIRTY;
+
+      if (incoming && ix86_check_sse_register (incoming))
+       flag_clean = true;
     }

-  return AVX_U128_CLEAN;
+  if (flag_clean)
+    return AVX_U128_CLEAN;
+  return AVX_U128_ANY;
 }

 /* Return a mode that ENTITY is assumed to be
@@ -19142,7 +19168,9 @@ ix86_avx_u128_mode_exit (void)
   if (reg && ix86_check_avx_upper_register (reg))
     return AVX_U128_DIRTY;

-  return AVX_U128_CLEAN;
+  if (reg && ix86_check_sse_register (reg))
+    return AVX_U128_CLEAN;
+  return AVX_U128_ANY;
 }

 /* Return a mode that ENTITY is assumed to be

Reply via email to