re PR target/65697 (__atomic memory barriers not strong enough for __sync builtins)
[gcc.git] / gcc / df-problems.c
index 305ed5d9da4cfd828b49101d48421f3dcf04fb71..a34578157ae13c4811a9d7a71f07f65e4bda30f1 100644 (file)
@@ -1,5 +1,5 @@
 /* Standard problems for dataflow support routines.
-   Copyright (C) 1999-2014 Free Software Foundation, Inc.
+   Copyright (C) 1999-2015 Free Software Foundation, Inc.
    Originally contributed by Michael P. Hayes
              (m.hayes@elec.canterbury.ac.nz, mhayes@redhat.com)
    Major rewrite contributed by Danny Berlin (dberlin@dberlin.org)
@@ -29,11 +29,15 @@ along with GCC; see the file COPYING3.  If not see
 #include "tm_p.h"
 #include "insn-config.h"
 #include "recog.h"
+#include "hard-reg-set.h"
 #include "function.h"
 #include "regs.h"
 #include "alloc-pool.h"
 #include "flags.h"
-#include "hard-reg-set.h"
+#include "predict.h"
+#include "dominance.h"
+#include "cfg.h"
+#include "cfganal.h"
 #include "basic-block.h"
 #include "sbitmap.h"
 #include "bitmap.h"
@@ -44,6 +48,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "dce.h"
 #include "valtrack.h"
 #include "dumpfile.h"
+#include "rtl-iter.h"
 
 /* Note that turning REG_DEAD_DEBUGGING on will cause
    gcc.c-torture/unsorted/dump-noaddr.c to fail because it prints
@@ -262,7 +267,7 @@ df_rd_simulate_artificial_defs_at_top (basic_block bb, bitmap local_rd)
    LOCAL_RD.  */
 
 void
-df_rd_simulate_one_insn (basic_block bb ATTRIBUTE_UNUSED, rtx insn,
+df_rd_simulate_one_insn (basic_block bb ATTRIBUTE_UNUSED, rtx_insn *insn,
                         bitmap local_rd)
 {
   df_ref def;
@@ -923,12 +928,11 @@ df_lr_local_compute (bitmap all_blocks ATTRIBUTE_UNUSED)
         reference of the frame pointer.  */
       bitmap_set_bit (&df->hardware_regs_used, FRAME_POINTER_REGNUM);
 
-#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
       /* Pseudos with argument area equivalences may require
         reloading via the argument pointer.  */
-      if (fixed_regs[ARG_POINTER_REGNUM])
+      if (FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
+         && fixed_regs[ARG_POINTER_REGNUM])
        bitmap_set_bit (&df->hardware_regs_used, ARG_POINTER_REGNUM);
-#endif
 
       /* Any constant, or pseudo with constant equivalences, may
         require reloading from memory using the pic register.  */
@@ -1870,7 +1874,7 @@ struct df_link *
 df_chain_create (df_ref src, df_ref dst)
 {
   struct df_link *head = DF_REF_CHAIN (src);
-  struct df_link *link = (struct df_link *) pool_alloc (df_chain->block_pool);
+  struct df_link *link = df_chain->block_pool->allocate ();
 
   DF_REF_CHAIN (src) = link;
   link->next = head;
@@ -1895,7 +1899,7 @@ df_chain_unlink_1 (df_ref ref, df_ref target)
            prev->next = chain->next;
          else
            DF_REF_CHAIN (ref) = chain->next;
-         pool_free (df_chain->block_pool, chain);
+         df_chain->block_pool->remove (chain);
          return;
        }
       prev = chain;
@@ -1915,7 +1919,7 @@ df_chain_unlink (df_ref ref)
       struct df_link *next = chain->next;
       /* Delete the other side if it exists.  */
       df_chain_unlink_1 (chain->ref, ref);
-      pool_free (df_chain->block_pool, chain);
+      df_chain->block_pool->remove (chain);
       chain = next;
     }
   DF_REF_CHAIN (ref) = NULL;
@@ -1947,7 +1951,7 @@ df_chain_remove_problem (void)
 
   /* Wholesale destruction of the old chains.  */
   if (df_chain->block_pool)
-    free_alloc_pool (df_chain->block_pool);
+    delete df_chain->block_pool;
 
   EXECUTE_IF_SET_IN_BITMAP (df_chain->out_of_date_transfer_functions, 0, bb_index, bi)
     {
@@ -2001,8 +2005,8 @@ static void
 df_chain_alloc (bitmap all_blocks ATTRIBUTE_UNUSED)
 {
   df_chain_remove_problem ();
-  df_chain->block_pool = create_alloc_pool ("df_chain_block pool",
-                                        sizeof (struct df_link), 50);
+  df_chain->block_pool = new pool_allocator<df_link> ("df_chain_block pool",
+                                                     50);
   df_chain->optional_p = true;
 }
 
@@ -2137,7 +2141,7 @@ df_chain_finalize (bitmap all_blocks)
 static void
 df_chain_free (void)
 {
-  free_alloc_pool (df_chain->block_pool);
+  delete df_chain->block_pool;
   BITMAP_FREE (df_chain->out_of_date_transfer_functions);
   free (df_chain);
 }
@@ -2198,7 +2202,7 @@ df_chain_bottom_dump (basic_block bb, FILE *file)
 }
 
 static void
-df_chain_insn_top_dump (const_rtx insn, FILE *file)
+df_chain_insn_top_dump (const rtx_insn *insn, FILE *file)
 {
   if (df_chain_problem_p (DF_UD_CHAIN) && INSN_P (insn))
     {
@@ -2229,7 +2233,7 @@ df_chain_insn_top_dump (const_rtx insn, FILE *file)
 }
 
 static void
-df_chain_insn_bottom_dump (const_rtx insn, FILE *file)
+df_chain_insn_bottom_dump (const rtx_insn *insn, FILE *file)
 {
   if (df_chain_problem_p (DF_DU_CHAIN) && INSN_P (insn))
     {
@@ -2415,7 +2419,7 @@ df_word_lr_mark_ref (df_ref ref, bool is_set, regset live)
 {
   rtx orig_reg = DF_REF_REG (ref);
   rtx reg = orig_reg;
-  enum machine_mode reg_mode;
+  machine_mode reg_mode;
   unsigned regno;
   /* Left at -1 for whole accesses.  */
   int which_subword = -1;
@@ -2668,7 +2672,7 @@ df_word_lr_add_problem (void)
    an insn.  */
 
 bool
-df_word_lr_simulate_defs (rtx insn, bitmap live)
+df_word_lr_simulate_defs (rtx_insn *insn, bitmap live)
 {
   bool changed = false;
   df_ref def;
@@ -2685,7 +2689,7 @@ df_word_lr_simulate_defs (rtx insn, bitmap live)
 /* Simulate the effects of the uses of INSN on LIVE.  */
 
 void
-df_word_lr_simulate_uses (rtx insn, bitmap live)
+df_word_lr_simulate_uses (rtx_insn *insn, bitmap live)
 {
   df_ref use;
 
@@ -2705,7 +2709,7 @@ df_note_alloc (bitmap all_blocks ATTRIBUTE_UNUSED)
 
 /* This is only used if REG_DEAD_DEBUGGING is in effect.  */
 static void
-df_print_note (const char *prefix, rtx insn, rtx note)
+df_print_note (const char *prefix, rtx_insn *insn, rtx note)
 {
   if (dump_file)
     {
@@ -2739,7 +2743,7 @@ df_ignore_stack_reg (int regno ATTRIBUTE_UNUSED)
 /* Remove all of the REG_DEAD or REG_UNUSED notes from INSN.  */
 
 static void
-df_remove_dead_and_unused_notes (rtx insn)
+df_remove_dead_and_unused_notes (rtx_insn *insn)
 {
   rtx *pprev = &REG_NOTES (insn);
   rtx link = *pprev;
@@ -2854,7 +2858,7 @@ df_remove_dead_eq_notes (rtx_insn *insn, bitmap live)
 /* Set a NOTE_TYPE note for REG in INSN.  */
 
 static inline void
-df_set_note (enum reg_note note_type, rtx insn, rtx reg)
+df_set_note (enum reg_note note_type, rtx_insn *insn, rtx reg)
 {
   gcc_checking_assert (!DEBUG_INSN_P (insn));
   add_reg_note (insn, note_type, reg);
@@ -2895,7 +2899,7 @@ df_whole_mw_reg_unused_p (struct df_mw_hardreg *mws,
 */
 
 static void
-df_set_unused_notes_for_mw (rtx insn, struct df_mw_hardreg *mws,
+df_set_unused_notes_for_mw (rtx_insn *insn, struct df_mw_hardreg *mws,
                            bitmap live, bitmap do_not_gen,
                            bitmap artificial_uses,
                            struct dead_debug_local *debug)
@@ -2968,7 +2972,7 @@ df_whole_mw_reg_dead_p (struct df_mw_hardreg *mws,
    register.  */
 
 static void
-df_set_dead_notes_for_mw (rtx insn, struct df_mw_hardreg *mws,
+df_set_dead_notes_for_mw (rtx_insn *insn, struct df_mw_hardreg *mws,
                          bitmap live, bitmap do_not_gen,
                          bitmap artificial_uses, bool *added_notes_p)
 {
@@ -3025,7 +3029,7 @@ df_set_dead_notes_for_mw (rtx insn, struct df_mw_hardreg *mws,
    LIVE.  Do not generate notes for registers in ARTIFICIAL_USES.  */
 
 static void
-df_create_unused_note (rtx insn, df_ref def,
+df_create_unused_note (rtx_insn *insn, df_ref def,
                       bitmap live, bitmap artificial_uses,
                       struct dead_debug_local *debug)
 {
@@ -3357,7 +3361,7 @@ df_note_add_problem (void)
 /* Find the set of DEFs for INSN.  */
 
 void
-df_simulate_find_defs (rtx insn, bitmap defs)
+df_simulate_find_defs (rtx_insn *insn, bitmap defs)
 {
   df_ref def;
 
@@ -3368,7 +3372,7 @@ df_simulate_find_defs (rtx insn, bitmap defs)
 /* Find the set of uses for INSN.  This includes partial defs.  */
 
 static void
-df_simulate_find_uses (rtx insn, bitmap uses)
+df_simulate_find_uses (rtx_insn *insn, bitmap uses)
 {
   df_ref def, use;
   struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
@@ -3383,7 +3387,7 @@ df_simulate_find_uses (rtx insn, bitmap uses)
 /* Find the set of real DEFs, which are not clobbers, for INSN.  */
 
 void
-df_simulate_find_noclobber_defs (rtx insn, bitmap defs)
+df_simulate_find_noclobber_defs (rtx_insn *insn, bitmap defs)
 {
   df_ref def;
 
@@ -3396,7 +3400,7 @@ df_simulate_find_noclobber_defs (rtx insn, bitmap defs)
 /* Simulate the effects of the defs of INSN on LIVE.  */
 
 void
-df_simulate_defs (rtx insn, bitmap live)
+df_simulate_defs (rtx_insn *insn, bitmap live)
 {
   df_ref def;
 
@@ -3415,7 +3419,7 @@ df_simulate_defs (rtx insn, bitmap live)
 /* Simulate the effects of the uses of INSN on LIVE.  */
 
 void
-df_simulate_uses (rtx insn, bitmap live)
+df_simulate_uses (rtx_insn *insn, bitmap live)
 {
   df_ref use;
 
@@ -3476,7 +3480,7 @@ df_simulate_initialize_backwards (basic_block bb, bitmap live)
 /* Simulate the backwards effects of INSN on the bitmap LIVE.  */
 
 void
-df_simulate_one_insn_backwards (basic_block bb, rtx insn, bitmap live)
+df_simulate_one_insn_backwards (basic_block bb, rtx_insn *insn, bitmap live)
 {
   if (!NONDEBUG_INSN_P (insn))
     return;
@@ -3539,7 +3543,7 @@ df_simulate_initialize_forwards (basic_block bb, bitmap live)
 /* Simulate the forwards effects of INSN on the bitmap LIVE.  */
 
 void
-df_simulate_one_insn_forwards (basic_block bb, rtx insn, bitmap live)
+df_simulate_one_insn_forwards (basic_block bb, rtx_insn *insn, bitmap live)
 {
   rtx link;
   if (! INSN_P (insn))
@@ -3564,12 +3568,7 @@ df_simulate_one_insn_forwards (basic_block bb, rtx insn, bitmap live)
        case REG_UNUSED:
          {
            rtx reg = XEXP (link, 0);
-           int regno = REGNO (reg);
-           if (HARD_REGISTER_NUM_P (regno))
-             bitmap_clear_range (live, regno,
-                                 hard_regno_nregs[regno][GET_MODE (reg)]);
-           else
-             bitmap_clear_bit (live, regno);
+           bitmap_clear_range (live, REGNO (reg), REG_NREGS (reg));
          }
          break;
        default:
@@ -3584,25 +3583,27 @@ df_simulate_one_insn_forwards (basic_block bb, rtx insn, bitmap live)
 #define MEMREF_NORMAL 1
 #define MEMREF_VOLATILE 2
 
-/* A subroutine of can_move_insns_across_p called through for_each_rtx.
-   Return either MEMREF_NORMAL or MEMREF_VOLATILE if a memory is found.  */
+/* Return an OR of MEMREF_NORMAL or MEMREF_VOLATILE for the MEMs in X.  */
 
 static int
-find_memory (rtx *px, void *data ATTRIBUTE_UNUSED)
+find_memory (rtx_insn *insn)
 {
-  rtx x = *px;
-
-  if (GET_CODE (x) == ASM_OPERANDS && MEM_VOLATILE_P (x))
-    return MEMREF_VOLATILE;
-
-  if (!MEM_P (x))
-    return 0;
-  if (MEM_VOLATILE_P (x))
-    return MEMREF_VOLATILE;
-  if (MEM_READONLY_P (x))
-    return 0;
-
-  return MEMREF_NORMAL;
+  int flags = 0;
+  subrtx_iterator::array_type array;
+  FOR_EACH_SUBRTX (iter, array, PATTERN (insn), NONCONST)
+    {
+      const_rtx x = *iter;
+      if (GET_CODE (x) == ASM_OPERANDS && MEM_VOLATILE_P (x))
+       flags |= MEMREF_VOLATILE;
+      else if (MEM_P (x))
+       {
+         if (MEM_VOLATILE_P (x))
+           flags |= MEMREF_VOLATILE;
+         else if (!MEM_READONLY_P (x))
+           flags |= MEMREF_NORMAL;
+       }
+    }
+  return flags;
 }
 
 /* A subroutine of can_move_insns_across_p called through note_stores.
@@ -3706,8 +3707,7 @@ can_move_insns_across (rtx_insn *from, rtx_insn *to,
        {
          if (volatile_insn_p (PATTERN (insn)))
            return false;
-         memrefs_in_across |= for_each_rtx (&PATTERN (insn), find_memory,
-                                            NULL);
+         memrefs_in_across |= find_memory (insn);
          note_stores (PATTERN (insn), find_memory_stores,
                       &mem_sets_in_across);
          /* This is used just to find sets of the stack pointer.  */
@@ -3789,8 +3789,7 @@ can_move_insns_across (rtx_insn *from, rtx_insn *to,
              int mem_ref_flags = 0;
              int mem_set_flags = 0;
              note_stores (PATTERN (insn), find_memory_stores, &mem_set_flags);
-             mem_ref_flags = for_each_rtx (&PATTERN (insn), find_memory,
-                                           NULL);
+             mem_ref_flags = find_memory (insn);
              /* Catch sets of the stack pointer.  */
              mem_ref_flags |= mem_set_flags;
 
@@ -3810,9 +3809,7 @@ can_move_insns_across (rtx_insn *from, rtx_insn *to,
          if (bitmap_intersect_p (merge_set, test_use)
              || bitmap_intersect_p (merge_use, test_set))
            break;
-#ifdef HAVE_cc0
-         if (!sets_cc0_p (insn))
-#endif
+         if (!HAVE_cc0 || !sets_cc0_p (insn))
            max_to = insn;
        }
       next = NEXT_INSN (insn);
@@ -3851,10 +3848,7 @@ can_move_insns_across (rtx_insn *from, rtx_insn *to,
       if (NONDEBUG_INSN_P (insn))
        {
          if (!bitmap_intersect_p (test_set, local_merge_live)
-#ifdef HAVE_cc0
-             && !sets_cc0_p (insn)
-#endif
-             )
+             && (!HAVE_cc0 || !sets_cc0_p (insn)))
            {
              max_to = insn;
              break;
@@ -4051,7 +4045,7 @@ df_md_simulate_artificial_defs_at_top (basic_block bb, bitmap local_md)
    LOCAL_MD.  */
 
 void
-df_md_simulate_one_insn (basic_block bb ATTRIBUTE_UNUSED, rtx insn,
+df_md_simulate_one_insn (basic_block bb ATTRIBUTE_UNUSED, rtx_insn *insn,
                         bitmap local_md)
 {
   df_ref def;