lcm.c (optimize_mode_switching): Do not rebuild liveness information when no changes...
authorJan Hubicka <jh@suse.cz>
Tue, 30 Oct 2001 11:13:49 +0000 (12:13 +0100)
committerJan Hubicka <hubicka@gcc.gnu.org>
Tue, 30 Oct 2001 11:13:49 +0000 (11:13 +0000)
* lcm.c (optimize_mode_switching):  Do not rebuild liveness information
when no changes has been made.

* gcse.c (reg_set_bitmap): Turn into reg_set.
(modify_mem_list_set, canon_modify_mem_list_set)
(clear_modify_mem_tables, free_modify_mem_tables): New.
(gcse_main); Use free_modify_mem_tables.
(free_gcse_mem): Likewise; free the bitmaps.
(alloc_gcse_main): Initialize the bitmaps.
(canon_list_insert): Set canon_modify_mem_list_set.
(record_last_mem_set_info): Likewise; set modify_mem_list_set.
(compute_hash_table): Use clear_modify_mem_tables.
(reset_opr_set_tables): Likewise.
(oprs_not_set_p): reg_set_bitmap is regset.
(mark_set, mark_clobber): Likewise.

* df.h (DF_EQUIV_NOTES): New constant.
(df_insn_refs_record): Record uses inside or REG_EQUIV/EQUAL notes
when asked for.

* sched-rgn.c (CHECK_DEAD_NOTES): New constant.
(init_regions, schedule_insns): Conditionalize the checking
code by CHECK_DEAD_NOTES; avoid multiple calls to update_life_info.

From-SVN: r46634

gcc/ChangeLog
gcc/df.c
gcc/df.h
gcc/gcse.c
gcc/lcm.c
gcc/reg-stack.c
gcc/sched-rgn.c

index f0659d2..a7e6c7a 100644 (file)
@@ -1,3 +1,29 @@
+Tue Oct 30 11:08:11 CET 2001  Jan Hubicka  <jh@suse.cz>
+
+       * lcm.c (optimize_mode_switching):  Do not rebuild liveness information
+       when no changes has been made.
+
+       * gcse.c (reg_set_bitmap): Turn into reg_set.
+       (modify_mem_list_set, canon_modify_mem_list_set)
+       (clear_modify_mem_tables, free_modify_mem_tables): New.
+       (gcse_main); Use free_modify_mem_tables.
+       (free_gcse_mem): Likewise; free the bitmaps.
+       (alloc_gcse_main): Initialize the bitmaps.
+       (canon_list_insert): Set canon_modify_mem_list_set.
+       (record_last_mem_set_info): Likewise; set modify_mem_list_set.
+       (compute_hash_table): Use clear_modify_mem_tables.
+       (reset_opr_set_tables): Likewise.
+       (oprs_not_set_p): reg_set_bitmap is regset.
+       (mark_set, mark_clobber): Likewise.
+
+       * df.h (DF_EQUIV_NOTES): New constant.
+       (df_insn_refs_record): Record uses inside or REG_EQUIV/EQUAL notes
+       when asked for.
+
+       * sched-rgn.c (CHECK_DEAD_NOTES): New constant.
+       (init_regions, schedule_insns): Conditionalize the checking
+       code by CHECK_DEAD_NOTES; avoid multiple calls to update_life_info.
+
 Tue Oct 30 11:02:31 CET 2001  Jan Hubicka  <jh@suse.cz>
 
        * i386.md (movti_rex64 splitter): Fix condition.
index 7514873..3318d45 100644 (file)
--- a/gcc/df.c
+++ b/gcc/df.c
@@ -1224,8 +1224,25 @@ df_insn_refs_record (df, bb, insn)
 
   if (INSN_P (insn))
     {
+      rtx note;
+
       /* Record register defs */
       df_defs_record (df, PATTERN (insn), bb, insn);
+
+      if (df->flags & DF_EQUIV_NOTES)
+       for (note = REG_NOTES (insn); note;
+            note = XEXP (note, 1))
+         {
+           switch (REG_NOTE_KIND (note))
+             {
+               case REG_EQUIV:
+               case REG_EQUAL:
+                 df_uses_record (df, &XEXP (note, 0), DF_REF_REG_USE,
+                                 bb, insn);
+               default:
+                 break;
+             }
+         }
       
       if (GET_CODE (insn) == CALL_INSN)
        {
index 068461d..395b325 100644 (file)
--- a/gcc/df.h
+++ b/gcc/df.h
@@ -31,6 +31,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #define DF_RU_CHAIN    128     /* Reg-use chain.  */
 #define DF_ALL        255
 #define DF_HARD_REGS  1024
+#define DF_EQUIV_NOTES 2048    /* Mark uses present in EQUIV/EQUAL notes.  */
 
 enum df_ref_type {DF_REF_REG_DEF, DF_REF_REG_USE, DF_REF_REG_MEM_LOAD,
                  DF_REF_REG_MEM_STORE};
index a6cd29e..a91cfd6 100644 (file)
@@ -481,7 +481,7 @@ static struct ls_expr * pre_ldst_mems = NULL;
 /* Bitmap containing one bit for each register in the program.
    Used when performing GCSE to track which registers have been set since
    the start of the basic block.  */
-static sbitmap reg_set_bitmap;
+static regset reg_set_bitmap;
 
 /* For each block, a bitmap of registers set in the block.
    This is used by expr_killed_p and compute_transp.
@@ -493,9 +493,11 @@ static sbitmap *reg_set_in_block;
 /* Array, indexed by basic block number for a list of insns which modify
    memory within that block.  */
 static rtx * modify_mem_list;
+bitmap modify_mem_list_set;
 
 /* This array parallels modify_mem_list, but is kept canonicalized.  */
 static rtx * canon_modify_mem_list;
+bitmap canon_modify_mem_list_set;
 /* Various variables for statistics gathering.  */
 
 /* Memory used in a pass.
@@ -693,6 +695,8 @@ static void delete_store            PARAMS ((struct ls_expr *,
                                                 basic_block));
 static void free_store_memory          PARAMS ((void));
 static void store_motion               PARAMS ((void));
+static void clear_modify_mem_tables    PARAMS ((void));
+static void free_modify_mem_tables     PARAMS ((void));
 \f
 /* Entry point for global common subexpression elimination.
    F is the first instruction in the function.  */
@@ -825,15 +829,7 @@ gcse_main (f, file)
             basic blocks.  */
          if (changed)
            {
-             int i;
-
-             for (i = 0; i < orig_bb_count; i++)
-               {
-                 if (modify_mem_list[i])
-                   free_INSN_LIST_list (modify_mem_list + i);
-                 if (canon_modify_mem_list[i])
-                   free_INSN_LIST_list (canon_modify_mem_list + i); 
-               }
+             free_modify_mem_tables ();
              modify_mem_list
                = (rtx *) gmalloc (n_basic_blocks * sizeof (rtx *));
              canon_modify_mem_list
@@ -1016,7 +1012,7 @@ alloc_gcse_mem (f)
       CUID_INSN (i++) = insn;
 
   /* Allocate vars to track sets of regs.  */
-  reg_set_bitmap = (sbitmap) sbitmap_alloc (max_gcse_regno);
+  reg_set_bitmap = BITMAP_XMALLOC ();
 
   /* Allocate vars to track sets of regs, memory per block.  */
   reg_set_in_block = (sbitmap *) sbitmap_vector_alloc (n_basic_blocks,
@@ -1027,6 +1023,8 @@ alloc_gcse_mem (f)
   canon_modify_mem_list = (rtx *) gmalloc (n_basic_blocks * sizeof (rtx *));
   memset ((char *) modify_mem_list, 0, n_basic_blocks * sizeof (rtx *));
   memset ((char *) canon_modify_mem_list, 0, n_basic_blocks * sizeof (rtx *));
+  modify_mem_list_set = BITMAP_XMALLOC ();
+  canon_modify_mem_list_set = BITMAP_XMALLOC ();
 }
 
 /* Free memory allocated by alloc_gcse_mem.  */
@@ -1037,26 +1035,12 @@ free_gcse_mem ()
   free (uid_cuid);
   free (cuid_insn);
 
-  free (reg_set_bitmap);
+  BITMAP_XFREE (reg_set_bitmap);
 
   sbitmap_vector_free (reg_set_in_block);
-  /* re-Cache any INSN_LIST nodes we have allocated.  */
-  {
-    int i;
-
-    for (i = 0; i < n_basic_blocks; i++)
-      {
-        if (modify_mem_list[i])
-          free_INSN_LIST_list (modify_mem_list + i);
-        if (canon_modify_mem_list[i])
-          free_INSN_LIST_list (canon_modify_mem_list + i);
-      }
-
-    free (modify_mem_list);
-    free (canon_modify_mem_list);
-    modify_mem_list = 0;
-    canon_modify_mem_list = 0;
-  }
+  free_modify_mem_tables ();
+  BITMAP_XFREE (modify_mem_list_set);
+  BITMAP_XFREE (canon_modify_mem_list_set);
 }
 
 /* Many of the global optimization algorithms work by solving dataflow
@@ -2403,6 +2387,7 @@ canon_list_insert (dest, unused1, v_insn)
     alloc_INSN_LIST (dest_addr, canon_modify_mem_list[BLOCK_NUM (insn)]);
   canon_modify_mem_list[BLOCK_NUM (insn)] = 
     alloc_INSN_LIST (dest, canon_modify_mem_list[BLOCK_NUM (insn)]);
+  bitmap_set_bit (canon_modify_mem_list_set, BLOCK_NUM (insn));
 }
 
 /* Record memory modification information for INSN.  We do not actually care
@@ -2417,6 +2402,7 @@ record_last_mem_set_info (insn)
      everything.  */
   modify_mem_list[BLOCK_NUM (insn)] = 
     alloc_INSN_LIST (insn, modify_mem_list[BLOCK_NUM (insn)]);
+  bitmap_set_bit (modify_mem_list_set, BLOCK_NUM (insn));
 
   if (GET_CODE (insn) == CALL_INSN)
     {
@@ -2425,6 +2411,7 @@ record_last_mem_set_info (insn)
         need to insert a pair of items, as canon_list_insert does.  */
       canon_modify_mem_list[BLOCK_NUM (insn)] = 
         alloc_INSN_LIST (insn, canon_modify_mem_list[BLOCK_NUM (insn)]);
+      bitmap_set_bit (canon_modify_mem_list_set, BLOCK_NUM (insn));
     }
   else
     note_stores (PATTERN (insn), canon_list_insert, (void*)insn );
@@ -2482,16 +2469,7 @@ compute_hash_table (set_p)
   sbitmap_vector_zero (reg_set_in_block, n_basic_blocks);
 
   /* re-Cache any INSN_LIST nodes we have allocated.  */
-  {
-    int i;
-    for (i = 0; i < n_basic_blocks; i++)
-      {
-        if (modify_mem_list[i])
-         free_INSN_LIST_list (modify_mem_list + i);
-        if (canon_modify_mem_list[i])
-         free_INSN_LIST_list (canon_modify_mem_list + i);
-      }
-  }
+  clear_modify_mem_tables ();
   /* Some working arrays used to track first and last set in each block.  */
   reg_avail_info = (struct reg_avail_info*)
     gmalloc (max_gcse_regno * sizeof (struct reg_avail_info));
@@ -2712,6 +2690,35 @@ next_set (regno, expr)
   return expr;
 }
 
+/* Clear canon_modify_mem_list and modify_mem_list tables.  */
+static void
+clear_modify_mem_tables ()
+{
+  int i;
+
+  EXECUTE_IF_SET_IN_BITMAP
+    (canon_modify_mem_list_set, 0, i,
+     free_INSN_LIST_list (modify_mem_list + i));
+  bitmap_clear (canon_modify_mem_list_set);
+
+  EXECUTE_IF_SET_IN_BITMAP
+    (canon_modify_mem_list_set, 0, i,
+     free_INSN_LIST_list (canon_modify_mem_list + i));
+  bitmap_clear (modify_mem_list_set);
+}
+
+/* Release memory used by modify_mem_list_set and canon_modify_mem_list_set.  */
+
+static void
+free_modify_mem_tables ()
+{
+  clear_modify_mem_tables ();
+  free (modify_mem_list);
+  free (canon_modify_mem_list);
+  modify_mem_list = 0;
+  canon_modify_mem_list = 0;
+}
+
 /* Reset tables used to keep track of what's still available [since the
    start of the block].  */
 
@@ -2720,23 +2727,12 @@ reset_opr_set_tables ()
 {
   /* Maintain a bitmap of which regs have been set since beginning of
      the block.  */
-  sbitmap_zero (reg_set_bitmap);
+  CLEAR_REG_SET (reg_set_bitmap);
 
   /* Also keep a record of the last instruction to modify memory.
      For now this is very trivial, we only record whether any memory
      location has been modified.  */
-  {
-    int i;
-
-    /* re-Cache any INSN_LIST nodes we have allocated.  */
-    for (i = 0; i < n_basic_blocks; i++)
-      {
-        if (modify_mem_list[i]) 
-         free_INSN_LIST_list (modify_mem_list + i);
-        if (canon_modify_mem_list[i]) 
-         free_INSN_LIST_list (canon_modify_mem_list + i);
-      }
-  }
+  clear_modify_mem_tables ();
 }
 
 /* Return non-zero if the operands of X are not set before INSN in
@@ -2775,7 +2771,7 @@ oprs_not_set_p (x, insn)
        return oprs_not_set_p (XEXP (x, 0), insn);
 
     case REG:
-      return ! TEST_BIT (reg_set_bitmap, REGNO (x));
+      return ! REGNO_REG_SET_P (reg_set_bitmap, REGNO (x));
 
     default:
       break;
@@ -2828,7 +2824,7 @@ mark_set (pat, insn)
     dest = XEXP (dest, 0);
 
   if (GET_CODE (dest) == REG)
-    SET_BIT (reg_set_bitmap, REGNO (dest));
+    SET_REGNO_REG_SET (reg_set_bitmap, REGNO (dest));
   else if (GET_CODE (dest) == MEM)
     record_last_mem_set_info (insn);
 
@@ -2848,7 +2844,7 @@ mark_clobber (pat, insn)
     clob = XEXP (clob, 0);
 
   if (GET_CODE (clob) == REG)
-    SET_BIT (reg_set_bitmap, REGNO (clob));
+    SET_REGNO_REG_SET (reg_set_bitmap, REGNO (clob));
   else
     record_last_mem_set_info (insn);
 }
index 4f5d692..88e5841 100644 (file)
--- a/gcc/lcm.c
+++ b/gcc/lcm.c
@@ -1029,6 +1029,7 @@ optimize_mode_switching (file)
   int i, j;
   int n_entities;
   int max_num_modes = 0;
+  bool emited = false;
 
 #ifdef NORMAL_MODE
   /* Increment n_basic_blocks before allocating bb_info.  */
@@ -1239,10 +1240,16 @@ optimize_mode_switching (file)
              mode_set = gen_sequence ();
              end_sequence ();
 
+             /* Do not bother to insert empty sequence.  */
+             if (GET_CODE (mode_set) == SEQUENCE
+                 && !XVECLEN (mode_set, 0))
+               continue;
+
              /* If this is an abnormal edge, we'll insert at the end
                 of the previous block.  */
              if (eg->flags & EDGE_ABNORMAL)
                {
+                 emited = true;
                  if (GET_CODE (src_bb->end) == JUMP_INSN)
                    emit_insn_before (mode_set, src_bb->end);
                  /* It doesn't make sense to switch to normal mode
@@ -1313,10 +1320,16 @@ optimize_mode_switching (file)
              mode_set = gen_sequence ();
              end_sequence ();
 
+             /* Do not bother to insert empty sequence.  */
+             if (GET_CODE (mode_set) == SEQUENCE
+                 && !XVECLEN (mode_set, 0))
+               continue;
+
              /* If this is an abnormal edge, we'll insert at the end of the
                 previous block.  */
              if (eg->flags & EDGE_ABNORMAL)
                {
+                 emited = true;
                  if (GET_CODE (eg->src->end) == JUMP_INSN)
                    emit_insn_before (mode_set, eg->src->end);
                  else if (GET_CODE (eg->src->end) == INSN)
@@ -1349,6 +1362,12 @@ optimize_mode_switching (file)
                  mode_set = gen_sequence ();
                  end_sequence ();
 
+                 /* Do not bother to insert empty sequence.  */
+                 if (GET_CODE (mode_set) == SEQUENCE
+                     && !XVECLEN (mode_set, 0))
+                   continue;
+
+                 emited = true;
                  if (GET_CODE (ptr->insn_ptr) == NOTE
                      && (NOTE_LINE_NUMBER (ptr->insn_ptr)
                          == NOTE_INSN_BASIC_BLOCK))
@@ -1376,6 +1395,9 @@ optimize_mode_switching (file)
   if (need_commit)
     commit_edge_insertions ();
 
+  if (!need_commit && !emited)
+    return 0;
+
   /* Ideally we'd figure out what blocks were affected and start from
      there, but this is enormously complicated by commit_edge_insertions,
      which would screw up any indicies we'd collected, and also need to
index 006f063..56f4751 100644 (file)
@@ -442,9 +442,11 @@ reg_to_stack (first, file)
   /* Ok, floating point instructions exist.  If not optimizing, 
      build the CFG and run life analysis.  */
   if (!optimize)
-    find_basic_blocks (first, max_reg_num (), file);
-  count_or_remove_death_notes (NULL, 1);
-  life_analysis (first, file, PROP_DEATH_NOTES);
+    {
+      find_basic_blocks (first, max_reg_num (), file);
+      count_or_remove_death_notes (NULL, 1);
+      life_analysis (first, file, PROP_DEATH_NOTES);
+    }
   mark_dfs_back_edges ();
 
   /* Set up block info for each basic block.  */
index 3cd89e9..c443cd7 100644 (file)
@@ -62,6 +62,17 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "recog.h"
 #include "sched-int.h"
 
+/* Define when we want to do count REG_DEAD notes before and after scheduling
+   for sanity checking.  We can't do that when conditional execution is used,
+   as REG_DEAD exist only for unconditional deaths.  */
+
+#if !defined (HAVE_conditional_execution) && defined (ENABLE_CHECKING)
+#define CHECK_DEAD_NOTES 1
+#else
+#define CHECK_DEAD_NOTES 0
+#endif
+
+
 #ifdef INSN_SCHEDULING
 /* Some accessor macros for h_i_d members only used within this file.  */
 #define INSN_REF_COUNT(INSN)   (h_i_d[INSN_UID (INSN)].ref_count)
@@ -2790,8 +2801,6 @@ init_regions ()
   block_to_bb = (int *) xmalloc ((n_basic_blocks) * sizeof (int));
   containing_rgn = (int *) xmalloc ((n_basic_blocks) * sizeof (int));
 
-  blocks = sbitmap_alloc (n_basic_blocks);
-
   /* Compute regions for scheduling.  */
   if (reload_completed
       || n_basic_blocks == 1
@@ -2849,21 +2858,26 @@ init_regions ()
        }
     }
 
-  deaths_in_region = (int *) xmalloc (sizeof (int) * nr_regions);
 
-  /* Remove all death notes from the subroutine.  */
-  for (rgn = 0; rgn < nr_regions; rgn++)
+  if (CHECK_DEAD_NOTES)
     {
-      int b;
+      blocks = sbitmap_alloc (n_basic_blocks);
+      deaths_in_region = (int *) xmalloc (sizeof (int) * nr_regions);
+      /* Remove all death notes from the subroutine.  */
+      for (rgn = 0; rgn < nr_regions; rgn++)
+       {
+         int b;
 
-      sbitmap_zero (blocks);
-      for (b = RGN_NR_BLOCKS (rgn) - 1; b >= 0; --b)
-       SET_BIT (blocks, rgn_bb_table[RGN_BLOCKS (rgn) + b]);
+         sbitmap_zero (blocks);
+         for (b = RGN_NR_BLOCKS (rgn) - 1; b >= 0; --b)
+           SET_BIT (blocks, rgn_bb_table[RGN_BLOCKS (rgn) + b]);
 
-      deaths_in_region[rgn] = count_or_remove_death_notes (blocks, 1);
+         deaths_in_region[rgn] = count_or_remove_death_notes (blocks, 1);
+       }
+      sbitmap_free (blocks);
     }
-
-  sbitmap_free (blocks);
+  else
+    count_or_remove_death_notes (NULL, 1);
 }
 
 /* The one entry point in this file.  DUMP_FILE is the dump file for
@@ -2916,39 +2930,50 @@ schedule_insns (dump_file)
   sbitmap_ones (large_region_blocks);
 
   blocks = sbitmap_alloc (n_basic_blocks);
+  sbitmap_zero (blocks);
 
+  /* Update life information.  For regions consisting of multiple blocks
+     we've possibly done interblock scheduling that affects global liveness.
+     For regions consisting of single blocks we need to do only local
+     liveness.  */
   for (rgn = 0; rgn < nr_regions; rgn++)
     if (RGN_NR_BLOCKS (rgn) > 1)
       any_large_regions = 1;
     else
       {
-       sbitmap_zero (blocks);
        SET_BIT (blocks, rgn_bb_table[RGN_BLOCKS (rgn)]);
        RESET_BIT (large_region_blocks, rgn_bb_table[RGN_BLOCKS (rgn)]);
-
-       /* Don't update reg info after reload, since that affects
-          regs_ever_live, which should not change after reload.  */
-       update_life_info (blocks, UPDATE_LIFE_LOCAL,
-                         (reload_completed ? PROP_DEATH_NOTES
-                          : PROP_DEATH_NOTES | PROP_REG_INFO));
-
-#ifndef HAVE_conditional_execution
-       /* ??? REG_DEAD notes only exist for unconditional deaths.  We need
-          a count of the conditional plus unconditional deaths for this to
-          work out.  */
-       /* In the single block case, the count of registers that died should
-          not have changed during the schedule.  */
-       if (count_or_remove_death_notes (blocks, 0) != deaths_in_region[rgn])
-         abort ();
-#endif
       }
 
+  /* Don't update reg info after reload, since that affects
+     regs_ever_live, which should not change after reload.  */
+  update_life_info (blocks, UPDATE_LIFE_LOCAL,
+                   (reload_completed ? PROP_DEATH_NOTES
+                    : PROP_DEATH_NOTES | PROP_REG_INFO));
   if (any_large_regions)
     {
       update_life_info (large_region_blocks, UPDATE_LIFE_GLOBAL,
                        PROP_DEATH_NOTES | PROP_REG_INFO);
     }
 
+  if (CHECK_DEAD_NOTES)
+    {
+      /* Remove all death notes from the subroutine.  */
+      for (rgn = 0; rgn < nr_regions; rgn++)
+       if (RGN_NR_BLOCKS (rgn) == 1)
+         {
+           int b;
+
+           sbitmap_zero (blocks);
+           SET_BIT (blocks, rgn_bb_table[RGN_BLOCKS (rgn)]);
+
+           if (deaths_in_region[rgn]
+               != count_or_remove_death_notes (blocks, 0))
+             abort ();
+         }
+      free (deaths_in_region);
+    }
+
   /* Reposition the prologue and epilogue notes in case we moved the
      prologue/epilogue insns.  */
   if (reload_completed)
@@ -3001,7 +3026,5 @@ schedule_insns (dump_file)
 
   sbitmap_free (blocks);
   sbitmap_free (large_region_blocks);
-
-  free (deaths_in_region);
 }
 #endif