i386.h (enum ix86_enitity): Add X86_DIRFLAG.
authorUros Bizjak <uros@gcc.gnu.org>
Mon, 6 Jun 2016 22:35:18 +0000 (00:35 +0200)
committerUros Bizjak <uros@gcc.gnu.org>
Mon, 6 Jun 2016 22:35:18 +0000 (00:35 +0200)
* config/i386/i386.h (enum ix86_enitity): Add X86_DIRFLAG.
(enum x86_dirflag_state): New enum.
(NUM_MODES_FOR_MODE_SWITCHING): Add X86_DIRFLAG_ANY.
(machine_function): Remove needs_cld.
(ix86_current_function_needs_cld): Remove.
* config/i386/i386.c (ix86_set_func_type): Set
ix86_optimize_mode_switching[X86_DIRFLAG] to 1.
(ix86_expand_prologue): Do not emit CLD here.
(ix86_dirflag_mode_needed): New function.
(ix86_dirflag_mode_entry): Ditto.
(ix86_mode_needed): Handle X86_DIRFLAG entity.
(ix86_mode_after): Ditto.
(ix86_mode_entry): Ditto.
(ix86_mode_exit): Ditto.
(ix86_emit_mode_set): Ditto.
* config/i386/i386.md (strmov_singleop): Set
ix86_optimize_mode_switching[X86_DIRFLAG] to 1 for TARGET_CLD.
Do not set ix86_current_function_needs_cld.
(rep_mov): Ditto.
(strset_singleop): Ditto.
(rep_stos): Ditto.
(cmpstrnqi_nz_1): Ditto.
(cmpstrnqi_1): Ditto.
(strlenqi_1): Ditto.

From-SVN: r237156

gcc/ChangeLog
gcc/config/i386/i386.c
gcc/config/i386/i386.h
gcc/config/i386/i386.md

index ccabd6f6f42ef9c6335c7be7d2721f297fbab0c6..18f491a6dcbecadb436fd45860ba0ac73ad92413 100644 (file)
@@ -1,3 +1,30 @@
+2016-06-07  Uros Bizjak  <ubizjak@gmail.com>
+
+       * config/i386/i386.h (enum ix86_enitity): Add X86_DIRFLAG.
+       (enum x86_dirflag_state): New enum.
+       (NUM_MODES_FOR_MODE_SWITCHING): Add X86_DIRFLAG_ANY.
+       (machine_function): Remove needs_cld.
+       (ix86_current_function_needs_cld): Remove.
+       * config/i386/i386.c (ix86_set_func_type): Set
+       ix86_optimize_mode_switching[X86_DIRFLAG] to 1.
+       (ix86_expand_prologue): Do not emit CLD here.
+       (ix86_dirflag_mode_needed): New function.
+       (ix86_dirflag_mode_entry): Ditto.
+       (ix86_mode_needed): Handle X86_DIRFLAG entity.
+       (ix86_mode_after): Ditto.
+       (ix86_mode_entry): Ditto.
+       (ix86_mode_exit): Ditto.
+       (ix86_emit_mode_set): Ditto.
+       * config/i386/i386.md (strmov_singleop): Set
+       ix86_optimize_mode_switching[X86_DIRFLAG] to 1 for TARGET_CLD.
+       Do not set ix86_current_function_needs_cld.
+       (rep_mov): Ditto.
+       (strset_singleop): Ditto.
+       (rep_stos): Ditto.
+       (cmpstrnqi_nz_1): Ditto.
+       (cmpstrnqi_1): Ditto.
+       (strlenqi_1): Ditto.
+
 2016-06-06  Jakub Jelinek  <jakub@redhat.com>
 
        PR tree-optimization/71259
 
        * config/ft32/ft32.c (ft32_setup_incoming_varargs,
        ft32_expand_prolog, ft32_expand_epilogue):
-        Handle pretend_args.
+       Handle pretend_args.
        * config/ft32/ft32.h: Remove OUTGOING_REG_PARM_STACK_SPACE.
        * config/ft32/ft32.md: Add pretend_returner.
 
index c191eebc09d12cbf3a3033574bc616ecc3404645..b807a9a00041eb6009261819fcd253bb147f2b52 100644 (file)
@@ -6823,6 +6823,8 @@ ix86_set_func_type (tree fndecl)
          cfun->machine->func_type
            = nargs == 2 ? TYPE_EXCEPTION : TYPE_INTERRUPT;
 
+         ix86_optimize_mode_switching[X86_DIRFLAG] = 1;
+
          /* Only dwarf2out.c can handle -WORD(AP) as a pointer argument.  */
          if (write_symbols != NO_DEBUG && write_symbols != DWARF2_DEBUG)
            sorry ("Only DWARF debug format is supported for interrupt "
@@ -13817,16 +13819,6 @@ ix86_expand_prologue (void)
   if (frame_pointer_needed && frame.red_zone_size)
     emit_insn (gen_memory_blockage ());
 
-  /* Emit cld instruction if stringops are used in the function.  Since
-     we can't assume the direction flag in interrupt handler, we must
-     emit cld instruction if stringops are used in interrupt handler or
-     interrupt handler isn't a leaf function.  */
-  if ((TARGET_CLD && ix86_current_function_needs_cld)
-      || (!TARGET_CLD
-         && cfun->machine->func_type != TYPE_NORMAL
-         && (ix86_current_function_needs_cld || !crtl->is_leaf)))
-    emit_insn (gen_cld ());
-
   /* SEH requires that the prologue end within 256 bytes of the start of
      the function.  Prevent instruction schedules that would extend that.
      Further, prevent alloca modifications to the stack pointer from being
@@ -18600,6 +18592,35 @@ output_387_binary_op (rtx insn, rtx *operands)
   return buf;
 }
 
+/* Return needed mode for entity in optimize_mode_switching pass.  */
+
+static int
+ix86_dirflag_mode_needed (rtx_insn *insn)
+{
+  if (CALL_P (insn))
+    {
+      if (cfun->machine->func_type == TYPE_NORMAL)
+       return X86_DIRFLAG_ANY;
+      else
+       /* No need to emit CLD in interrupt handler for TARGET_CLD.  */
+       return TARGET_CLD ? X86_DIRFLAG_ANY : X86_DIRFLAG_RESET;
+    }
+
+  if (recog_memoized (insn) < 0)
+    return X86_DIRFLAG_ANY;
+
+  if (get_attr_type (insn) == TYPE_STR)
+    {
+      /* Emit cld instruction if stringops are used in the function.  */
+      if (cfun->machine->func_type == TYPE_NORMAL)
+       return TARGET_CLD ? X86_DIRFLAG_RESET : X86_DIRFLAG_ANY;
+      else
+       return X86_DIRFLAG_RESET;
+    }
+
+  return X86_DIRFLAG_ANY;
+}
+
 /* Check if a 256bit AVX register is referenced inside of EXP.   */
 
 static bool
@@ -18712,6 +18733,8 @@ ix86_mode_needed (int entity, rtx_insn *insn)
 {
   switch (entity)
     {
+    case X86_DIRFLAG:
+      return ix86_dirflag_mode_needed (insn);
     case AVX_U128:
       return ix86_avx_u128_mode_needed (insn);
     case I387_TRUNC:
@@ -18771,6 +18794,8 @@ ix86_mode_after (int entity, int mode, rtx_insn *insn)
 {
   switch (entity)
     {
+    case X86_DIRFLAG:
+      return mode;
     case AVX_U128:
       return ix86_avx_u128_mode_after (mode, insn);
     case I387_TRUNC:
@@ -18783,6 +18808,18 @@ ix86_mode_after (int entity, int mode, rtx_insn *insn)
     }
 }
 
+static int
+ix86_dirflag_mode_entry (void)
+{
+  /* For TARGET_CLD or in the interrupt handler we can't assume
+     direction flag state at function entry.  */
+  if (TARGET_CLD
+      || cfun->machine->func_type != TYPE_NORMAL)
+    return X86_DIRFLAG_ANY;
+
+  return X86_DIRFLAG_RESET;
+}
+
 static int
 ix86_avx_u128_mode_entry (void)
 {
@@ -18810,6 +18847,8 @@ ix86_mode_entry (int entity)
 {
   switch (entity)
     {
+    case X86_DIRFLAG:
+      return ix86_dirflag_mode_entry ();
     case AVX_U128:
       return ix86_avx_u128_mode_entry ();
     case I387_TRUNC:
@@ -18843,6 +18882,8 @@ ix86_mode_exit (int entity)
 {
   switch (entity)
     {
+    case X86_DIRFLAG:
+      return X86_DIRFLAG_ANY;
     case AVX_U128:
       return ix86_avx_u128_mode_exit ();
     case I387_TRUNC:
@@ -18986,6 +19027,10 @@ ix86_emit_mode_set (int entity, int mode, int prev_mode ATTRIBUTE_UNUSED,
 {
   switch (entity)
     {
+    case X86_DIRFLAG:
+      if (mode == X86_DIRFLAG_RESET)
+       emit_insn (gen_cld ());
+      break;
     case AVX_U128:
       if (mode == AVX_U128_CLEAN)
        ix86_avx_emit_vzeroupper (regs_live);
index f1fa02c3302831ac2dcc650895d43ff0dd319033..cab0a5d013bad4520fa017a220a2b5764eb5f3a2 100644 (file)
@@ -2376,9 +2376,21 @@ enum ix86_fpcmp_strategy {
    Post-reload pass may be later used to eliminate the redundant fildcw if
    needed.  */
 
+enum ix86_stack_slot
+{
+  SLOT_TEMP = 0,
+  SLOT_CW_STORED,
+  SLOT_CW_TRUNC,
+  SLOT_CW_FLOOR,
+  SLOT_CW_CEIL,
+  SLOT_CW_MASK_PM,
+  MAX_386_STACK_LOCALS
+};
+
 enum ix86_entity
 {
-  AVX_U128 = 0,
+  X86_DIRFLAG = 0,
+  AVX_U128,
   I387_TRUNC,
   I387_FLOOR,
   I387_CEIL,
@@ -2386,15 +2398,10 @@ enum ix86_entity
   MAX_386_ENTITIES
 };
 
-enum ix86_stack_slot
+enum x86_dirflag_state
 {
-  SLOT_TEMP = 0,
-  SLOT_CW_STORED,
-  SLOT_CW_TRUNC,
-  SLOT_CW_FLOOR,
-  SLOT_CW_CEIL,
-  SLOT_CW_MASK_PM,
-  MAX_386_STACK_LOCALS
+  X86_DIRFLAG_RESET,
+  X86_DIRFLAG_ANY
 };
 
 enum avx_u128_state
@@ -2418,8 +2425,9 @@ enum avx_u128_state
    starting counting at zero - determines the integer that is used to
    refer to the mode-switched entity in question.  */
 
-#define NUM_MODES_FOR_MODE_SWITCHING \
-  { AVX_U128_ANY, I387_CW_ANY, I387_CW_ANY, I387_CW_ANY, I387_CW_ANY }
+#define NUM_MODES_FOR_MODE_SWITCHING                   \
+  { X86_DIRFLAG_ANY, AVX_U128_ANY,                     \
+    I387_CW_ANY, I387_CW_ANY, I387_CW_ANY, I387_CW_ANY }
 
 \f
 /* Avoid renaming of stack registers, as doing so in combination with
@@ -2516,9 +2524,6 @@ struct GTY(()) machine_function {
   /* Nonzero if the function accesses a previous frame.  */
   BOOL_BITFIELD accesses_prev_frame : 1;
 
-  /* Nonzero if the function requires a CLD in the prologue.  */
-  BOOL_BITFIELD needs_cld : 1;
-
   /* Set by ix86_compute_frame_layout and used by prologue/epilogue
      expander to determine the style used.  */
   BOOL_BITFIELD use_fast_prologue_epilogue : 1;
@@ -2572,7 +2577,6 @@ struct GTY(()) machine_function {
 #define ix86_varargs_gpr_size (cfun->machine->varargs_gpr_size)
 #define ix86_varargs_fpr_size (cfun->machine->varargs_fpr_size)
 #define ix86_optimize_mode_switching (cfun->machine->optimize_mode_switching)
-#define ix86_current_function_needs_cld (cfun->machine->needs_cld)
 #define ix86_pc_thunk_call_expanded (cfun->machine->pc_thunk_call_expanded)
 #define ix86_tls_descriptor_calls_expanded_in_cfun \
   (cfun->machine->tls_descriptor_call_expanded_p)
index a32c4e204ce317dbf9cc40bb452d3e7b559db9a8..416cdcd91296147c6e91eeed8bc82f61a2889bc3 100644 (file)
              (set (match_operand 2 "register_operand")
                   (match_operand 5))])]
   ""
-  "ix86_current_function_needs_cld = 1;")
+{
+  if (TARGET_CLD)
+    ix86_optimize_mode_switching[X86_DIRFLAG] = 1;
+})
 
 (define_insn "*strmovdi_rex_1"
   [(set (mem:DI (match_operand:P 2 "register_operand" "0"))
                   (match_operand 3 "memory_operand"))
              (use (match_dup 4))])]
   ""
-  "ix86_current_function_needs_cld = 1;")
+{
+  if (TARGET_CLD)
+    ix86_optimize_mode_switching[X86_DIRFLAG] = 1;
+})
 
 (define_insn "*rep_movdi_rex64"
   [(set (match_operand:P 2 "register_operand" "=c") (const_int 0))
                   (match_operand 3))
              (unspec [(const_int 0)] UNSPEC_STOS)])]
   ""
-  "ix86_current_function_needs_cld = 1;")
+{
+  if (TARGET_CLD)
+    ix86_optimize_mode_switching[X86_DIRFLAG] = 1;
+})
 
 (define_insn "*strsetdi_rex_1"
   [(set (mem:DI (match_operand:P 1 "register_operand" "0"))
              (use (match_operand 3 "register_operand"))
              (use (match_dup 1))])]
   ""
-  "ix86_current_function_needs_cld = 1;")
+{
+  if (TARGET_CLD)
+    ix86_optimize_mode_switching[X86_DIRFLAG] = 1;
+})
 
 (define_insn "*rep_stosdi_rex64"
   [(set (match_operand:P 1 "register_operand" "=c") (const_int 0))
              (clobber (match_operand 1 "register_operand"))
              (clobber (match_dup 2))])]
   ""
-  "ix86_current_function_needs_cld = 1;")
+{
+  if (TARGET_CLD)
+    ix86_optimize_mode_switching[X86_DIRFLAG] = 1;
+})
 
 (define_insn "*cmpstrnqi_nz_1"
   [(set (reg:CC FLAGS_REG)
              (clobber (match_operand 1 "register_operand"))
              (clobber (match_dup 2))])]
   ""
-  "ix86_current_function_needs_cld = 1;")
+{
+  if (TARGET_CLD)
+    ix86_optimize_mode_switching[X86_DIRFLAG] = 1;
+})
 
 (define_insn "*cmpstrnqi_1"
   [(set (reg:CC FLAGS_REG)
              (clobber (match_operand 1 "register_operand"))
              (clobber (reg:CC FLAGS_REG))])]
   ""
-  "ix86_current_function_needs_cld = 1;")
+{
+  if (TARGET_CLD)
+    ix86_optimize_mode_switching[X86_DIRFLAG] = 1;
+})
 
 (define_insn "*strlenqi_1"
   [(set (match_operand:P 0 "register_operand" "=&c")