OSDN Git Service

2004-10-04 Jose Ruiz <ruiz@act-europe.fr>
[pf3gnuchains/gcc-fork.git] / gcc / df.c
index cd66fe3..ee10362 100644 (file)
--- a/gcc/df.c
+++ b/gcc/df.c
@@ -192,8 +192,12 @@ and again mark them read/write.
   do                                                   \
     {                                                  \
       unsigned int node_;                              \
-      EXECUTE_IF_SET_IN_BITMAP (BITMAP, MIN, node_,    \
-      {(BB) = BASIC_BLOCK (node_); CODE;});            \
+      bitmap_iterator bi;                              \
+      EXECUTE_IF_SET_IN_BITMAP (BITMAP, MIN, node_, bi)        \
+       {                                               \
+         (BB) = BASIC_BLOCK (node_);                   \
+         CODE;                                         \
+       }                                               \
     }                                                  \
   while (0)
 
@@ -243,7 +247,7 @@ static void df_bb_du_chain_create (struct df *, basic_block, bitmap);
 static void df_du_chain_create (struct df *, bitmap);
 static void df_bb_ud_chain_create (struct df *, basic_block);
 static void df_ud_chain_create (struct df *, bitmap);
-static void df_bb_rd_local_compute (struct df *, basic_block);
+static void df_bb_rd_local_compute (struct df *, basic_block, bitmap);
 static void df_rd_local_compute (struct df *, bitmap);
 static void df_bb_ru_local_compute (struct df *, basic_block);
 static void df_ru_local_compute (struct df *, bitmap);
@@ -604,19 +608,6 @@ static rtx df_reg_use_gen (unsigned int regno)
   use = gen_rtx_USE (GET_MODE (reg), reg);
   return use;
 }
-
-
-/* Return a CLOBBER for register REGNO.  */
-static rtx df_reg_clobber_gen (unsigned int regno)
-{
-  rtx reg;
-  rtx use;
-
-  reg = regno_reg_rtx[regno];
-
-  use = gen_rtx_CLOBBER (GET_MODE (reg), reg);
-  return use;
-}
 \f
 /* Local chain manipulation routines.  */
 
@@ -661,8 +652,8 @@ df_ref_unlink (struct df_link **phead, struct ref *ref)
          /* Only a single ref.  It must be the one we want.
             If not, the def-use and use-def chains are likely to
             be inconsistent.  */
-         if (link->ref != ref)
-           abort ();
+         gcc_assert (link->ref == ref);
+         
          /* Now have an empty chain.  */
          *phead = NULL;
        }
@@ -821,8 +812,7 @@ df_ref_record (struct df *df, rtx reg, rtx *loc, rtx insn,
 {
   unsigned int regno;
 
-  if (!REG_P (reg) && GET_CODE (reg) != SUBREG)
-    abort ();
+  gcc_assert (REG_P (reg) || GET_CODE (reg) == SUBREG);
 
   /* For the reg allocator we are interested in some SUBREG rtx's, but not
      all.  Notably only those representing a word extraction from a multi-word
@@ -998,7 +988,7 @@ df_uses_record (struct df *df, rtx *loc, enum df_ref_type ref_type,
     case CLOBBER:
       /* If we are clobbering a MEM, mark any registers inside the address
         as being used.  */
-      if (GET_CODE (XEXP (x, 0)) == MEM)
+      if (MEM_P (XEXP (x, 0)))
        df_uses_record (df, &XEXP (XEXP (x, 0), 0),
                        DF_REF_REG_MEM_STORE, bb, insn, flags);
 
@@ -1053,10 +1043,10 @@ df_uses_record (struct df *df, rtx *loc, enum df_ref_type ref_type,
                              bb, insn, 0);
              break;
            case STRICT_LOW_PART:
-             /* A strict_low_part uses the whole REG and not just the SUBREG.  */
+             /* A strict_low_part uses the whole REG and not just the
+                SUBREG.  */
              dst = XEXP (dst, 0);
-             if (GET_CODE (dst) != SUBREG)
-               abort ();
+             gcc_assert (GET_CODE (dst) == SUBREG);
              df_uses_record (df, &SUBREG_REG (dst), DF_REF_REG_USE, bb,
                             insn, DF_REF_READ_WRITE);
              break;
@@ -1069,7 +1059,7 @@ df_uses_record (struct df *df, rtx *loc, enum df_ref_type ref_type,
              dst = XEXP (dst, 0);
              break;
            default:
-             abort ();
+             gcc_unreachable ();
          }
        return;
       }
@@ -1181,7 +1171,7 @@ df_insn_refs_record (struct df *df, basic_block bb, rtx insn)
              }
          }
 
-      if (GET_CODE (insn) == CALL_INSN)
+      if (CALL_P (insn))
        {
          rtx note;
          rtx x;
@@ -1217,20 +1207,15 @@ df_insn_refs_record (struct df *df, basic_block bb, rtx insn)
       df_uses_record (df, &PATTERN (insn),
                      DF_REF_REG_USE, bb, insn, 0);
 
-      if (GET_CODE (insn) == CALL_INSN)
+      if (CALL_P (insn))
        {
          rtx note;
 
-         if (df->flags & DF_HARD_REGS)
-           {
-             /* Kill all registers invalidated by a call.  */
-             for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-               if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i))
-                 {
-                   rtx reg_clob = df_reg_clobber_gen (i);
-                   df_defs_record (df, reg_clob, bb, insn);
-                 }
-           }
+         /* We do not record hard registers clobbered by the call,
+            since there are awfully many of them and "defs" created
+            through them are not interesting (since no use can be legally
+            reached by them).  So we must just make sure we include them when
+            computing kill bitmaps.  */
 
          /* There may be extra registers to be clobbered.  */
          for (note = CALL_INSN_FUNCTION_USAGE (insn);
@@ -1329,8 +1314,7 @@ df_reg_def_chain_create (struct df *df, bitmap blocks, bool redo)
     {
 #ifdef ENABLE_CHECKING
       for (regno = 0; regno < df->n_regs; regno++)
-       if (df->regs[regno].defs)
-         abort ();
+       gcc_assert (!df->regs[regno].defs);
 #endif
 
       /* Pretend that all defs are new.  */
@@ -1411,8 +1395,7 @@ df_reg_use_chain_create (struct df *df, bitmap blocks, bool redo)
     {
 #ifdef ENABLE_CHECKING
       for (regno = 0; regno < df->n_regs; regno++)
-       if (df->regs[regno].uses)
-         abort ();
+       gcc_assert (!df->regs[regno].uses);
 #endif
 
       /* Pretend that all uses are new.  */
@@ -1629,13 +1612,14 @@ df_lr_transfer_function (int bb ATTRIBUTE_UNUSED, int *changed, void *in,
 
 /* Compute local reaching def info for basic block BB.  */
 static void
-df_bb_rd_local_compute (struct df *df, basic_block bb)
+df_bb_rd_local_compute (struct df *df, basic_block bb, bitmap call_killed_defs)
 {
   struct bb_info *bb_info = DF_BB_INFO (df, bb);
   rtx insn;
+  bitmap seen = BITMAP_XMALLOC ();
+  bool call_seen = false;
 
-  for (insn = BB_HEAD (bb); insn && insn != NEXT_INSN (BB_END (bb));
-       insn = NEXT_INSN (insn))
+  FOR_BB_INSNS_REVERSE (bb, insn)
     {
       unsigned int uid = INSN_UID (insn);
       struct df_link *def_link;
@@ -1649,6 +1633,12 @@ df_bb_rd_local_compute (struct df *df, basic_block bb)
          unsigned int regno = DF_REF_REGNO (def);
          struct df_link *def2_link;
 
+         if (bitmap_bit_p (seen, regno)
+             || (call_seen
+                 && regno < FIRST_PSEUDO_REGISTER
+                 && TEST_HARD_REG_BIT (regs_invalidated_by_call, regno)))
+           continue;
+
          for (def2_link = df->regs[regno].defs; def2_link;
               def2_link = def2_link->next)
            {
@@ -1659,16 +1649,21 @@ df_bb_rd_local_compute (struct df *df, basic_block bb)
                 be killed by this BB but it keeps things a lot
                 simpler.  */
              bitmap_set_bit (bb_info->rd_kill, DF_REF_ID (def2));
-
-             /* Zap from the set of gens for this BB.  */
-             bitmap_clear_bit (bb_info->rd_gen, DF_REF_ID (def2));
            }
 
          bitmap_set_bit (bb_info->rd_gen, DF_REF_ID (def));
+         bitmap_set_bit (seen, regno);
+       }
+
+      if (CALL_P (insn) && (df->flags & DF_HARD_REGS))
+       {
+         bitmap_operation (bb_info->rd_kill, bb_info->rd_kill,
+                           call_killed_defs, BITMAP_IOR);
+         call_seen = 1;
        }
     }
 
-  bb_info->rd_valid = 1;
+  BITMAP_XFREE (seen);
 }
 
 
@@ -1677,11 +1672,32 @@ static void
 df_rd_local_compute (struct df *df, bitmap blocks)
 {
   basic_block bb;
+  bitmap killed_by_call = NULL;
+  unsigned regno;
+  struct df_link *def_link;
+
+  if (df->flags & DF_HARD_REGS)
+    {
+      killed_by_call = BITMAP_XMALLOC ();
+      for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+       {
+         if (!TEST_HARD_REG_BIT (regs_invalidated_by_call, regno))
+           continue;
+         
+         for (def_link = df->regs[regno].defs;
+              def_link;
+              def_link = def_link->next)
+           bitmap_set_bit (killed_by_call, DF_REF_ID (def_link->ref));
+       }
+    }
 
   FOR_EACH_BB_IN_BITMAP (blocks, 0, bb,
   {
-    df_bb_rd_local_compute (df, bb);
+    df_bb_rd_local_compute (df, bb, killed_by_call);
   });
+
+  if (df->flags & DF_HARD_REGS)
+    BITMAP_XFREE (killed_by_call);
 }
 
 
@@ -1817,6 +1833,7 @@ df_bb_reg_info_compute (struct df *df, basic_block bb, bitmap live)
       unsigned int uid = INSN_UID (insn);
       unsigned int regno;
       struct df_link *link;
+      bitmap_iterator bi;
 
       if (! INSN_P (insn))
        continue;
@@ -1842,10 +1859,10 @@ df_bb_reg_info_compute (struct df *df, basic_block bb, bitmap live)
        }
 
       /* Increment lifetimes of all live registers.  */
-      EXECUTE_IF_SET_IN_BITMAP (live, 0, regno,
-      {
-       reg_info[regno].lifetime++;
-      });
+      EXECUTE_IF_SET_IN_BITMAP (live, 0, regno, bi)
+       {
+         reg_info[regno].lifetime++;
+       }
     }
 }
 
@@ -2239,10 +2256,12 @@ df_refs_update (struct df *df, bitmap blocks)
     }
   else
     {
-      EXECUTE_IF_AND_IN_BITMAP (df->bbs_modified, blocks, 0, bbno,
+      bitmap_iterator bi;
+
+      EXECUTE_IF_AND_IN_BITMAP (df->bbs_modified, blocks, 0, bbno, bi)
        {
          count += df_bb_refs_update (df, BASIC_BLOCK (bbno));
-       });
+       }
     }
 
   df_refs_process (df);
@@ -2283,8 +2302,7 @@ df_analyze (struct df *df, bitmap blocks, int flags)
 
   /* We could deal with additional basic blocks being created by
      rescanning everything again.  */
-  if (df->n_bbs && df->n_bbs != (unsigned int) last_basic_block)
-    abort ();
+  gcc_assert (!df->n_bbs || df->n_bbs == (unsigned int) last_basic_block);
 
   update = df_modified_p (df, blocks);
   if (update || (flags != df->flags))
@@ -2306,8 +2324,7 @@ df_analyze (struct df *df, bitmap blocks, int flags)
          if (blocks == (bitmap) -1)
            blocks = df->bbs_modified;
 
-         if (! df->n_bbs)
-           abort ();
+         gcc_assert (df->n_bbs);
 
          df_analyze_1 (df, blocks, flags, 1);
          bitmap_zero (df->bbs_modified);
@@ -2333,7 +2350,7 @@ prune_to_subcfg (int list[], unsigned len, bitmap blocks)
   return last;
 }
 
-/* Alternative entry point to the analysis.  Analyse just the part of the cfg
+/* Alternative entry point to the analysis.  Analyze just the part of the cfg
    graph induced by BLOCKS.
    
    TODO I am not quite sure how to avoid code duplication with df_analyze_1
@@ -2616,8 +2633,7 @@ df_insn_delete (struct df *df, basic_block bb ATTRIBUTE_UNUSED, rtx insn)
      handle the JUMP_LABEL?  */
 
   /* We should not be deleting the NOTE_INSN_BASIC_BLOCK or label.  */
-  if (insn == BB_HEAD (bb))
-    abort ();
+  gcc_assert (insn != BB_HEAD (bb));
 
   /* Delete the insn.  */
   delete_insn (insn);
@@ -2781,24 +2797,17 @@ df_refs_reg_replace (struct df *df, bitmap blocks, struct df_link *chain, rtx ol
       if (! INSN_P (insn))
        continue;
 
-      if (bitmap_bit_p (blocks, DF_REF_BBNO (ref)))
-       {
-         df_ref_reg_replace (df, ref, oldreg, newreg);
+      gcc_assert (bitmap_bit_p (blocks, DF_REF_BBNO (ref)));
+      
+      df_ref_reg_replace (df, ref, oldreg, newreg);
 
-         /* Replace occurrences of the reg within the REG_NOTES.  */
-         if ((! link->next || DF_REF_INSN (ref)
-             != DF_REF_INSN (link->next->ref))
-             && REG_NOTES (insn))
-           {
-             args.insn = insn;
-             for_each_rtx (&REG_NOTES (insn), df_rtx_reg_replace, &args);
-           }
-       }
-      else
+      /* Replace occurrences of the reg within the REG_NOTES.  */
+      if ((! link->next || DF_REF_INSN (ref)
+          != DF_REF_INSN (link->next->ref))
+         && REG_NOTES (insn))
        {
-         /* Temporary check to ensure that we have a grip on which
-            regs should be replaced.  */
-         abort ();
+         args.insn = insn;
+         for_each_rtx (&REG_NOTES (insn), df_rtx_reg_replace, &args);
        }
     }
 }
@@ -2829,8 +2838,7 @@ df_ref_reg_replace (struct df *df, struct ref *ref, rtx oldreg, rtx newreg)
   if (! INSN_P (DF_REF_INSN (ref)))
     return 0;
 
-  if (oldreg && oldreg != DF_REF_REG (ref))
-    abort ();
+  gcc_assert (!oldreg || oldreg == DF_REF_REG (ref));
 
   if (! validate_change (DF_REF_INSN (ref), DF_REF_LOC (ref), newreg, 1))
     return 0;
@@ -2896,10 +2904,8 @@ df_insns_modify (struct df *df, basic_block bb, rtx first_insn, rtx last_insn)
       /* A non-const call should not have slipped through the net.  If
         it does, we need to create a new basic block.  Ouch.  The
         same applies for a label.  */
-      if ((GET_CODE (insn) == CALL_INSN
-          && ! CONST_OR_PURE_CALL_P (insn))
-         || GET_CODE (insn) == CODE_LABEL)
-       abort ();
+      gcc_assert ((!CALL_P (insn) || CONST_OR_PURE_CALL_P (insn))
+                 && !LABEL_P (insn));
 
       uid = INSN_UID (insn);
 
@@ -2922,8 +2928,7 @@ df_pattern_emit_before (struct df *df, rtx pattern, basic_block bb, rtx insn)
   rtx prev_insn = PREV_INSN (insn);
 
   /* We should not be inserting before the start of the block.  */
-  if (insn == BB_HEAD (bb))
-    abort ();
+  gcc_assert (insn != BB_HEAD (bb));
   ret_insn = emit_insn_before (pattern, insn);
   if (ret_insn == insn)
     return ret_insn;
@@ -3181,10 +3186,7 @@ df_bb_reg_live_start_p (struct df *df, basic_block bb, rtx reg)
 {
   struct bb_info *bb_info = DF_BB_INFO (df, bb);
 
-#ifdef ENABLE_CHECKING
-  if (! bb_info->lr_in)
-    abort ();
-#endif
+  gcc_assert (bb_info->lr_in);
 
   return bitmap_bit_p (bb_info->lr_in, REGNO (reg));
 }
@@ -3196,10 +3198,7 @@ df_bb_reg_live_end_p (struct df *df, basic_block bb, rtx reg)
 {
   struct bb_info *bb_info = DF_BB_INFO (df, bb);
 
-#ifdef ENABLE_CHECKING
-  if (! bb_info->lr_in)
-    abort ();
-#endif
+  gcc_assert (bb_info->lr_in);
 
   return bitmap_bit_p (bb_info->lr_out, REGNO (reg));
 }
@@ -3219,9 +3218,8 @@ df_bb_regs_lives_compare (struct df *df, basic_block bb, rtx reg1, rtx reg2)
 
 
   /* The regs must be local to BB.  */
-  if (df_regno_bb (df, regno1) != bb
-      || df_regno_bb (df, regno2) != bb)
-    abort ();
+  gcc_assert (df_regno_bb (df, regno1) == bb
+             && df_regno_bb (df, regno2) == bb);
 
   def2 = df_bb_regno_first_def_find (df, bb, regno2);
   use1 = df_bb_regno_last_use_find (df, bb, regno1);
@@ -3365,8 +3363,7 @@ df_bb_single_def_use_insn_find (struct df *df, basic_block bb, rtx insn, rtx reg
 
   def = df_bb_insn_regno_first_def_find (df, bb, insn, REGNO (reg));
 
-  if (! def)
-    abort ();
+  gcc_assert (def);
 
   du_link = DF_REF_CHAIN (def);
 
@@ -3746,7 +3743,7 @@ dataflow_set_a_op_b (enum set_representation repr,
          break;
 
        default:
-         abort ();
+         gcc_unreachable ();
        }
       break;
 
@@ -3762,12 +3759,12 @@ dataflow_set_a_op_b (enum set_representation repr,
          break;
 
        default:
-         abort ();
+         gcc_unreachable ();
        }
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -3785,7 +3782,7 @@ dataflow_set_copy (enum set_representation repr, void *dest, void *src)
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -3799,19 +3796,19 @@ hybrid_search (basic_block bb, struct dataflow *dataflow,
   int changed;
   int i = bb->index;
   edge e;
+  edge_iterator ei;
 
   SET_BIT (visited, bb->index);
-  if (!TEST_BIT (pending, bb->index))
-    abort ();
+  gcc_assert (TEST_BIT (pending, bb->index));
   RESET_BIT (pending, i);
 
-#define HS(E_ANTI, E_ANTI_NEXT, E_ANTI_BB, E_ANTI_START_BB, IN_SET,    \
-          E, E_NEXT, E_BB, E_START_BB, OUT_SET)                        \
+#define HS(E_ANTI, E_ANTI_BB, E_ANTI_START_BB, IN_SET,                 \
+          E, E_BB, E_START_BB, OUT_SET)                                \
   do                                                                   \
     {                                                                  \
       /*  Calculate <conf_op> of predecessor_outs.  */                 \
       bitmap_zero (IN_SET[i]);                                         \
-      for (e = bb->E_ANTI; e; e = e->E_ANTI_NEXT)                      \
+      FOR_EACH_EDGE (e, ei, bb->E_ANTI)                                        \
        {                                                               \
          if (e->E_ANTI_BB == E_ANTI_START_BB)                          \
            continue;                                                   \
@@ -3831,7 +3828,7 @@ hybrid_search (basic_block bb, struct dataflow *dataflow,
       if (!changed)                                                    \
        break;                                                          \
                                                                        \
-      for (e = bb->E; e; e = e->E_NEXT)                                        \
+      FOR_EACH_EDGE (e, ei, bb->E)                                             \
        {                                                               \
          if (e->E_BB == E_START_BB || e->E_BB->index == i)             \
            continue;                                                   \
@@ -3842,7 +3839,7 @@ hybrid_search (basic_block bb, struct dataflow *dataflow,
          SET_BIT (pending, e->E_BB->index);                            \
        }                                                               \
                                                                        \
-      for (e = bb->E; e; e = e->E_NEXT)                                        \
+      FOR_EACH_EDGE (e, ei, bb->E)                                             \
        {                                                               \
          if (e->E_BB == E_START_BB || e->E_BB->index == i)             \
            continue;                                                   \
@@ -3856,11 +3853,11 @@ hybrid_search (basic_block bb, struct dataflow *dataflow,
     } while (0)
 
   if (dataflow->dir == DF_FORWARD)
-    HS (pred, pred_next, src, ENTRY_BLOCK_PTR, dataflow->in,
-       succ, succ_next, dest, EXIT_BLOCK_PTR, dataflow->out);
+    HS (preds, src, ENTRY_BLOCK_PTR, dataflow->in,
+       succs, dest, EXIT_BLOCK_PTR, dataflow->out);
   else
-    HS (succ, succ_next, dest, EXIT_BLOCK_PTR, dataflow->out,
-       pred, pred_next, src, ENTRY_BLOCK_PTR, dataflow->in);
+    HS (succs, dest, EXIT_BLOCK_PTR, dataflow->out,
+       preds, src, ENTRY_BLOCK_PTR, dataflow->in);
 }
 
 /* This function will perform iterative bitvector dataflow described by