OSDN Git Service

* configure.in (all_headers, all_lib2funcs): Remove.
[pf3gnuchains/gcc-fork.git] / gcc / flow.c
index b5a6e37..17f8277 100644 (file)
@@ -296,7 +296,7 @@ static void mark_regs_live_at_end   PARAMS ((regset));
 static int set_phi_alternative_reg      PARAMS ((rtx, int, int, void *));
 static void calculate_global_regs_live PARAMS ((sbitmap, sbitmap, int));
 static void propagate_block_delete_insn PARAMS ((basic_block, rtx));
-static rtx propagate_block_delete_libcall PARAMS ((basic_block, rtx, rtx));
+static rtx propagate_block_delete_libcall PARAMS ((rtx, rtx));
 static int insn_dead_p                 PARAMS ((struct propagate_block_info *,
                                                 rtx, int, rtx));
 static int libcall_dead_p              PARAMS ((struct propagate_block_info *,
@@ -306,6 +306,8 @@ static void mark_set_regs           PARAMS ((struct propagate_block_info *,
 static void mark_set_1                 PARAMS ((struct propagate_block_info *,
                                                 enum rtx_code, rtx, rtx,
                                                 rtx, int));
+static int find_regno_partial          PARAMS ((rtx *, void *));
+
 #ifdef HAVE_conditional_execution
 static int mark_regno_cond_dead                PARAMS ((struct propagate_block_info *,
                                                 int, rtx));
@@ -344,6 +346,7 @@ static void invalidate_mems_from_autoinc PARAMS ((struct propagate_block_info *,
 static void invalidate_mems_from_set   PARAMS ((struct propagate_block_info *,
                                                 rtx));
 static void delete_dead_jumptables     PARAMS ((void));
+static void clear_log_links            PARAMS ((sbitmap));
 \f
 
 void
@@ -377,8 +380,6 @@ check_function_return_warnings ()
        {
          /* Recompute insn->block mapping, since the initial mapping is
             set before we delete unreachable blocks.  */
-         compute_bb_for_insn (max_uid);
-
          if (BLOCK_FOR_INSN (cfun->x_clobber_return_insn) != NULL)
            warning ("control reaches end of non-void function");
        }
@@ -418,8 +419,8 @@ life_analysis (f, file, flags)
      int flags;
 {
 #ifdef ELIMINABLE_REGS
-  register int i;
-  static struct {int from, to; } eliminables[] = ELIMINABLE_REGS;
+  int i;
+  static const struct {const int from, to; } eliminables[] = ELIMINABLE_REGS;
 #endif
 
   /* Record which registers will be eliminated.  We use this in
@@ -457,6 +458,7 @@ life_analysis (f, file, flags)
   /* Always remove no-op moves.  Do this before other processing so
      that we don't have to keep re-scanning them.  */
   delete_noop_moves (f);
+  purge_all_dead_edges (false);
 
   /* Some targets can emit simpler epilogues if they know that sp was
      not ever modified during the function.  After reload, of course,
@@ -630,12 +632,19 @@ update_life_info (blocks, extent, prop_flags)
 
   tmp = INITIALIZE_REG_SET (tmp_head);
 
+  timevar_push ((extent == UPDATE_LIFE_LOCAL || blocks)
+               ? TV_LIFE_UPDATE : TV_LIFE);
+
   /* Changes to the CFG are only allowed when
      doing a global update for the entire CFG.  */
   if ((prop_flags & PROP_ALLOW_CFG_CHANGES)
       && (extent == UPDATE_LIFE_LOCAL || blocks))
     abort ();
 
+  /* Clear log links in case we are asked to (re)compute them.  */
+  if (prop_flags & PROP_LOG_LINKS)
+    clear_log_links (blocks);
+
   /* For a global update, we go through the relaxation process again.  */
   if (extent != UPDATE_LIFE_LOCAL)
     {
@@ -729,6 +738,8 @@ update_life_info (blocks, extent, prop_flags)
                                     }
                                 });
     }
+  timevar_pop ((extent == UPDATE_LIFE_LOCAL || blocks)
+              ? TV_LIFE_UPDATE : TV_LIFE);
 }
 
 /* Free the variables allocated by find_basic_blocks.
@@ -739,12 +750,6 @@ void
 free_basic_block_vars (keep_head_end_p)
      int keep_head_end_p;
 {
-  if (basic_block_for_insn)
-    {
-      VARRAY_FREE (basic_block_for_insn);
-      basic_block_for_insn = NULL;
-    }
-
   if (! keep_head_end_p)
     {
       if (basic_block_info)
@@ -779,20 +784,35 @@ delete_noop_moves (f)
          next = NEXT_INSN (insn);
          if (INSN_P (insn) && noop_move_p (insn))
            {
-             /* Do not call flow_delete_insn here to not confuse backward
-                pointers of LIBCALL block.  */
+             rtx note;
+
+             /* If we're about to remove the first insn of a libcall
+                then move the libcall note to the next real insn and
+                update the retval note.  */
+             if ((note = find_reg_note (insn, REG_LIBCALL, NULL_RTX))
+                      && XEXP (note, 0) != insn)
+               {
+                 rtx new_libcall_insn = next_real_insn (insn);
+                 rtx retval_note = find_reg_note (XEXP (note, 0),
+                                                  REG_RETVAL, NULL_RTX);
+                 REG_NOTES (new_libcall_insn)
+                   = gen_rtx_INSN_LIST (REG_LIBCALL, XEXP (note, 0),
+                                        REG_NOTES (new_libcall_insn));
+                 XEXP (retval_note, 0) = new_libcall_insn;
+               }
+
+             /* Do not call delete_insn here since that may change
+                the basic block boundaries which upsets some callers.  */
              PUT_CODE (insn, NOTE);
              NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
              NOTE_SOURCE_FILE (insn) = 0;
-             if (insn == bb->end)
-               purge_dead_edges (bb);
            }
        }
     }
 }
 
 /* Delete any jump tables never referenced.  We can't delete them at the
-   time of removing tablejump insn as they are referenced by the preceeding
+   time of removing tablejump insn as they are referenced by the preceding
    insns computing the destination, so we delay deleting and garbagecollect
    them once life information is computed.  */
 static void
@@ -803,15 +823,15 @@ delete_dead_jumptables ()
     {
       next = NEXT_INSN (insn);
       if (GET_CODE (insn) == CODE_LABEL
-         && LABEL_NUSES (insn) == 0
+         && LABEL_NUSES (insn) == LABEL_PRESERVE_P (insn)
          && GET_CODE (next) == JUMP_INSN
          && (GET_CODE (PATTERN (next)) == ADDR_VEC
              || GET_CODE (PATTERN (next)) == ADDR_DIFF_VEC))
        {
          if (rtl_dump_file)
            fprintf (rtl_dump_file, "Dead jumptable %i removed\n", INSN_UID (insn));
-         flow_delete_insn (NEXT_INSN (insn));
-         flow_delete_insn (insn);
+         delete_insn (NEXT_INSN (insn));
+         delete_insn (insn);
          next = NEXT_INSN (next);
        }
     }
@@ -1015,7 +1035,7 @@ calculate_global_regs_live (blocks_in, blocks_out, flags)
   new_live_at_end = INITIALIZE_REG_SET (new_live_at_end_head);
   call_used = INITIALIZE_REG_SET (call_used_head);
 
-  /* Inconveniently, this is only redily available in hard reg set form.  */
+  /* Inconveniently, this is only readily available in hard reg set form.  */
   for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
     if (call_used_regs[i])
       SET_REGNO_REG_SET (call_used, i);
@@ -1272,6 +1292,115 @@ calculate_global_regs_live (blocks_in, blocks_out, flags)
 
   free (queue);
 }
+
+\f
+/* This structure is used to pass parameters to an from the
+   the function find_regno_partial(). It is used to pass in the 
+   register number we are looking, as well as to return any rtx 
+   we find.  */
+
+typedef struct {
+  unsigned regno_to_find;
+  rtx retval;
+} find_regno_partial_param;
+
+
+/* Find the rtx for the reg numbers specified in 'data' if it is
+   part of an expression which only uses part of the register.  Return
+   it in the structure passed in.  */
+static int 
+find_regno_partial (ptr, data)
+     rtx *ptr;
+     void *data;
+{
+  find_regno_partial_param *param = (find_regno_partial_param *)data;
+  unsigned reg = param->regno_to_find;
+  param->retval = NULL_RTX;
+
+  if (*ptr == NULL_RTX)
+    return 0;
+
+  switch (GET_CODE (*ptr)) 
+    {
+    case ZERO_EXTRACT:
+    case SIGN_EXTRACT:
+    case STRICT_LOW_PART:
+      if (GET_CODE (XEXP (*ptr, 0)) == REG && REGNO (XEXP (*ptr, 0)) == reg)
+       {
+         param->retval = XEXP (*ptr, 0);
+         return 1;
+       }
+      break;
+
+    case SUBREG:
+      if (GET_CODE (SUBREG_REG (*ptr)) == REG 
+         && REGNO (SUBREG_REG (*ptr)) == reg)
+       {
+         param->retval = SUBREG_REG (*ptr);
+         return 1;
+       }
+      break;
+
+    default:
+      break;
+    }
+
+  return 0;
+}
+
+/* Process all immediate successors of the entry block looking for pseudo
+   registers which are live on entry. Find all of those whose first 
+   instance is a partial register reference of some kind, and initialize 
+   them to 0 after the entry block.  This will prevent bit sets within
+   registers whose value is unknown, and may contain some kind of sticky 
+   bits we don't want.  */
+
+int
+initialize_uninitialized_subregs () 
+{
+  rtx insn;
+  edge e;
+  int reg, did_something = 0;
+  find_regno_partial_param param;
+
+  for (e = ENTRY_BLOCK_PTR->succ; e; e = e->succ_next)
+    {
+      basic_block bb = e->dest;
+      regset map = bb->global_live_at_start;
+      EXECUTE_IF_SET_IN_REG_SET (map,
+                                FIRST_PSEUDO_REGISTER, reg,
+       {
+         int uid = REGNO_FIRST_UID (reg);
+         rtx i;
+
+         /* Find an insn which mentions the register we are looking for.
+            Its preferable to have an instance of the register's rtl since
+            there may be various flags set which we need to duplicate.  
+            If we can't find it, its probably an automatic whose initial
+            value doesn't matter, or hopefully something we don't care about. */
+         for (i = get_insns (); i && INSN_UID (i) != uid; i = NEXT_INSN (i))
+           ;
+         if (i != NULL_RTX)
+           {
+             /* Found the insn, now get the REG rtx, if we can.  */
+             param.regno_to_find = reg;
+             for_each_rtx (&i, find_regno_partial, &param);
+             if (param.retval != NULL_RTX)
+               {
+                 insn = gen_move_insn (param.retval, 
+                                       CONST0_RTX (GET_MODE (param.retval)));
+                 insert_insn_on_edge (insn, e);
+                 did_something = 1;
+               }
+           }
+       });
+    }
+
+  if (did_something)
+    commit_edge_insertions ();
+  return did_something;
+}
+
 \f
 /* Subroutines of life analysis.  */
 
@@ -1281,7 +1410,7 @@ calculate_global_regs_live (blocks_in, blocks_out, flags)
 void
 allocate_bb_life_data ()
 {
-  register int i;
+  int i;
 
   for (i = 0; i < n_basic_blocks; i++)
     {
@@ -1331,6 +1460,7 @@ propagate_block_delete_insn (bb, insn)
      rtx insn;
 {
   rtx inote = find_reg_note (insn, REG_LABEL, NULL_RTX);
+  bool purge = false;
 
   /* If the insn referred to a label, and that label was attached to
      an ADDR_VEC, it's safe to delete the ADDR_VEC.  In fact, it's
@@ -1368,33 +1498,28 @@ propagate_block_delete_insn (bb, insn)
          for (i = 0; i < len; i++)
            LABEL_NUSES (XEXP (XVECEXP (pat, diff_vec_p, i), 0))--;
 
-         flow_delete_insn (next);
+         delete_insn (next);
        }
     }
 
   if (bb->end == insn)
-    {
-      bb->end = PREV_INSN (insn);
-      purge_dead_edges (bb);
-    }
-  flow_delete_insn (insn);
+    purge = true;
+  delete_insn (insn);
+  if (purge)
+    purge_dead_edges (bb);
 }
 
 /* Delete dead libcalls for propagate_block.  Return the insn
    before the libcall.  */
 
 static rtx
-propagate_block_delete_libcall (bb, insn, note)
-     basic_block bb;
+propagate_block_delete_libcall ( insn, note)
      rtx insn, note;
 {
   rtx first = XEXP (note, 0);
   rtx before = PREV_INSN (first);
 
-  if (insn == bb->end)
-    bb->end = before;
-
-  flow_delete_insn_chain (first, insn);
+  delete_insn_chain (first, insn);
   return before;
 }
 
@@ -1453,7 +1578,7 @@ propagate_one_insn (pbi, insn)
       pbi->cc0_live = 0;
 
       if (libcall_is_dead)
-       prev = propagate_block_delete_libcall (pbi->bb, insn, note);
+       prev = propagate_block_delete_libcall ( insn, note);
       else
        propagate_block_delete_insn (pbi->bb, insn);
 
@@ -1464,7 +1589,7 @@ propagate_one_insn (pbi, insn)
      a following memory address.  */
 #ifdef AUTO_INC_DEC
   {
-    register rtx x = single_set (insn);
+    rtx x = single_set (insn);
 
     /* Does this instruction increment or decrement a register?  */
     if ((flags & PROP_AUTOINC)
@@ -1522,7 +1647,7 @@ propagate_one_insn (pbi, insn)
 
       if (GET_CODE (insn) == CALL_INSN)
        {
-         register int i;
+         int i;
          rtx note, cond;
 
          cond = NULL_RTX;
@@ -1572,7 +1697,7 @@ propagate_one_insn (pbi, insn)
 
       if (! insn_is_dead && GET_CODE (insn) == CALL_INSN)
        {
-         register int i;
+         int i;
          rtx note, cond;
 
          cond = NULL_RTX;
@@ -1827,7 +1952,7 @@ propagate_block (bb, live, local_set, cond_local_set, flags)
 
   if (flags & PROP_REG_INFO)
     {
-      register int i;
+      int i;
 
       /* Process the regs live at the end of the block.
         Mark them as not local to any one basic block.  */
@@ -1878,21 +2003,18 @@ insn_dead_p (pbi, x, call_ok, notes)
   enum rtx_code code = GET_CODE (x);
 
 #ifdef AUTO_INC_DEC
-  /* If flow is invoked after reload, we must take existing AUTO_INC
-     expresions into account.  */
-  if (reload_completed)
+  /* As flow is invoked after combine, we must take existing AUTO_INC
+     expressions into account.  */
+  for (; notes; notes = XEXP (notes, 1))
     {
-      for (; notes; notes = XEXP (notes, 1))
+      if (REG_NOTE_KIND (notes) == REG_INC)
        {
-         if (REG_NOTE_KIND (notes) == REG_INC)
-           {
-             int regno = REGNO (XEXP (notes, 0));
-
-             /* Don't delete insns to set global regs.  */
-             if ((regno < FIRST_PSEUDO_REGISTER && global_regs[regno])
-                 || REGNO_REG_SET_P (pbi->reg_live, regno))
-               return 0;
-           }
+         int regno = REGNO (XEXP (notes, 0));
+         
+         /* Don't delete insns to set global regs.  */
+         if ((regno < FIRST_PSEUDO_REGISTER && global_regs[regno])
+             || REGNO_REG_SET_P (pbi->reg_live, regno))
+           return 0;
        }
     }
 #endif
@@ -2074,13 +2196,13 @@ libcall_dead_p (pbi, note, insn)
 
   if (x)
     {
-      register rtx r = SET_SRC (x);
+      rtx r = SET_SRC (x);
 
       if (GET_CODE (r) == REG)
        {
          rtx call = XEXP (note, 0);
          rtx call_pat;
-         register int i;
+         int i;
 
          /* Find the call insn.  */
          while (call != insn && GET_CODE (call) != CALL_INSN)
@@ -2123,7 +2245,7 @@ libcall_dead_p (pbi, note, insn)
 
 int
 regno_uninitialized (regno)
-     int regno;
+     unsigned int regno;
 {
   if (n_basic_blocks == 0
       || (regno < FIRST_PSEUDO_REGISTER
@@ -2213,7 +2335,7 @@ invalidate_mems_from_autoinc (pbi, insn)
       invalidate_mems_from_set (pbi, XEXP (note, 0));
 }
 
-/* EXP is a REG.  Remove any dependant entries from pbi->mem_set_list.  */
+/* EXP is a REG.  Remove any dependent entries from pbi->mem_set_list.  */
 
 static void
 invalidate_mems_from_set (pbi, exp)
@@ -2283,7 +2405,8 @@ mark_set_regs (pbi, x, insn)
 
     case PARALLEL:
       {
-       register int i;
+       int i;
+
        for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
          {
            rtx sub = XVECEXP (x, 0, i);
@@ -2498,8 +2621,8 @@ mark_set_1 (pbi, code, reg, cond, insn, flags)
       if (flags & (PROP_LOG_LINKS | PROP_REG_INFO
                   | PROP_DEATH_NOTES | PROP_AUTOINC))
        {
-         register rtx y;
-         register int blocknum = pbi->bb->index;
+         rtx y;
+         int blocknum = pbi->bb->index;
 
          y = NULL_RTX;
          if (flags & (PROP_LOG_LINKS | PROP_AUTOINC))
@@ -2677,7 +2800,7 @@ mark_regno_cond_dead (pbi, regno, cond)
 
          SET_REGNO_REG_SET (pbi->reg_cond_reg, REGNO (XEXP (cond, 0)));
 
-         /* Not unconditionaly dead.  */
+         /* Not unconditionally dead.  */
          return 0;
        }
       else
@@ -2709,7 +2832,7 @@ mark_regno_cond_dead (pbi, regno, cond)
 
              SET_REGNO_REG_SET (pbi->reg_cond_reg, REGNO (XEXP (cond, 0)));
 
-             /* Not unconditionaly dead.  */
+             /* Not unconditionally dead.  */
              return 0;
            }
        }
@@ -2784,7 +2907,7 @@ flush_reg_cond_reg (pbi, regno)
    For ior/and, the ADD flag determines whether we want to add the new
    condition X to the old one unconditionally.  If it is zero, we will
    only return a new expression if X allows us to simplify part of
-   OLD, otherwise we return OLD unchanged to the caller.
+   OLD, otherwise we return NULL to the caller.
    If ADD is nonzero, we will return a new condition in all cases.  The
    toplevel caller of one of these functions should always pass 1 for
    ADD.  */
@@ -2806,7 +2929,7 @@ ior_reg_cond (old, x, add)
          && REGNO (XEXP (x, 0)) == REGNO (XEXP (old, 0)))
        return old;
       if (! add)
-       return old;
+       return NULL;
       return gen_rtx_IOR (0, old, x);
     }
 
@@ -2815,51 +2938,63 @@ ior_reg_cond (old, x, add)
     case IOR:
       op0 = ior_reg_cond (XEXP (old, 0), x, 0);
       op1 = ior_reg_cond (XEXP (old, 1), x, 0);
-      if (op0 != XEXP (old, 0) || op1 != XEXP (old, 1))
+      if (op0 != NULL || op1 != NULL)
        {
          if (op0 == const0_rtx)
-           return op1;
+           return op1 ? op1 : gen_rtx_IOR (0, XEXP (old, 1), x);
          if (op1 == const0_rtx)
-           return op0;
+           return op0 ? op0 : gen_rtx_IOR (0, XEXP (old, 0), x);
          if (op0 == const1_rtx || op1 == const1_rtx)
            return const1_rtx;
-         if (op0 == XEXP (old, 0))
-           op0 = gen_rtx_IOR (0, op0, x);
-         else
-           op1 = gen_rtx_IOR (0, op1, x);
+         if (op0 == NULL)
+           op0 = gen_rtx_IOR (0, XEXP (old, 0), x);
+         else if (rtx_equal_p (x, op0))
+           /* (x | A) | x ~ (x | A).  */
+           return old;
+         if (op1 == NULL)
+           op1 = gen_rtx_IOR (0, XEXP (old, 1), x);
+         else if (rtx_equal_p (x, op1))
+           /* (A | x) | x ~ (A | x).  */
+           return old;
          return gen_rtx_IOR (0, op0, op1);
        }
       if (! add)
-       return old;
+       return NULL;
       return gen_rtx_IOR (0, old, x);
 
     case AND:
       op0 = ior_reg_cond (XEXP (old, 0), x, 0);
       op1 = ior_reg_cond (XEXP (old, 1), x, 0);
-      if (op0 != XEXP (old, 0) || op1 != XEXP (old, 1))
+      if (op0 != NULL || op1 != NULL)
        {
          if (op0 == const1_rtx)
-           return op1;
+           return op1 ? op1 : gen_rtx_IOR (0, XEXP (old, 1), x);
          if (op1 == const1_rtx)
-           return op0;
+           return op0 ? op0 : gen_rtx_IOR (0, XEXP (old, 0), x);
          if (op0 == const0_rtx || op1 == const0_rtx)
            return const0_rtx;
-         if (op0 == XEXP (old, 0))
-           op0 = gen_rtx_IOR (0, op0, x);
-         else
-           op1 = gen_rtx_IOR (0, op1, x);
+         if (op0 == NULL)
+           op0 = gen_rtx_IOR (0, XEXP (old, 0), x);
+         else if (rtx_equal_p (x, op0))
+           /* (x & A) | x ~ x.  */
+           return op0;
+         if (op1 == NULL)
+           op1 = gen_rtx_IOR (0, XEXP (old, 1), x);
+         else if (rtx_equal_p (x, op1))
+           /* (A & x) | x ~ x.  */
+           return op1;
          return gen_rtx_AND (0, op0, op1);
        }
       if (! add)
-       return old;
+       return NULL;
       return gen_rtx_IOR (0, old, x);
 
     case NOT:
       op0 = and_reg_cond (XEXP (old, 0), not_reg_cond (x), 0);
-      if (op0 != XEXP (old, 0))
+      if (op0 != NULL)
        return not_reg_cond (op0);
       if (! add)
-       return old;
+       return NULL;
       return gen_rtx_IOR (0, old, x);
 
     default:
@@ -2909,7 +3044,7 @@ and_reg_cond (old, x, add)
          && REGNO (XEXP (x, 0)) == REGNO (XEXP (old, 0)))
        return old;
       if (! add)
-       return old;
+       return NULL;
       return gen_rtx_AND (0, old, x);
     }
 
@@ -2918,62 +3053,63 @@ and_reg_cond (old, x, add)
     case IOR:
       op0 = and_reg_cond (XEXP (old, 0), x, 0);
       op1 = and_reg_cond (XEXP (old, 1), x, 0);
-      if (op0 != XEXP (old, 0) || op1 != XEXP (old, 1))
+      if (op0 != NULL || op1 != NULL)
        {
          if (op0 == const0_rtx)
-           return op1;
+           return op1 ? op1 : gen_rtx_AND (0, XEXP (old, 1), x);
          if (op1 == const0_rtx)
-           return op0;
+           return op0 ? op0 : gen_rtx_AND (0, XEXP (old, 0), x);
          if (op0 == const1_rtx || op1 == const1_rtx)
            return const1_rtx;
-         if (op0 == XEXP (old, 0))
-           op0 = gen_rtx_AND (0, op0, x);
-         else
-           op1 = gen_rtx_AND (0, op1, x);
+         if (op0 == NULL)
+           op0 = gen_rtx_AND (0, XEXP (old, 0), x);
+         else if (rtx_equal_p (x, op0))
+           /* (x | A) & x ~ x.  */
+           return op0;
+         if (op1 == NULL)
+           op1 = gen_rtx_AND (0, XEXP (old, 1), x);
+         else if (rtx_equal_p (x, op1))
+           /* (A | x) & x ~ x.  */
+           return op1;
          return gen_rtx_IOR (0, op0, op1);
        }
       if (! add)
-       return old;
+       return NULL;
       return gen_rtx_AND (0, old, x);
 
     case AND:
       op0 = and_reg_cond (XEXP (old, 0), x, 0);
       op1 = and_reg_cond (XEXP (old, 1), x, 0);
-      if (op0 != XEXP (old, 0) || op1 != XEXP (old, 1))
+      if (op0 != NULL || op1 != NULL)
        {
          if (op0 == const1_rtx)
-           return op1;
+           return op1 ? op1 : gen_rtx_AND (0, XEXP (old, 1), x);
          if (op1 == const1_rtx)
-           return op0;
+           return op0 ? op0 : gen_rtx_AND (0, XEXP (old, 0), x);
          if (op0 == const0_rtx || op1 == const0_rtx)
            return const0_rtx;
-         if (op0 == XEXP (old, 0))
-           op0 = gen_rtx_AND (0, op0, x);
-         else
-           op1 = gen_rtx_AND (0, op1, x);
+         if (op0 == NULL)
+           op0 = gen_rtx_AND (0, XEXP (old, 0), x);
+         else if (rtx_equal_p (x, op0))
+           /* (x & A) & x ~ (x & A).  */
+           return old;
+         if (op1 == NULL)
+           op1 = gen_rtx_AND (0, XEXP (old, 1), x);
+         else if (rtx_equal_p (x, op1))
+           /* (A & x) & x ~ (A & x).  */
+           return old;
          return gen_rtx_AND (0, op0, op1);
        }
       if (! add)
-       return old;
-
-      /* If X is identical to one of the existing terms of the AND,
-        then just return what we already have.  */
-      /* ??? There really should be some sort of recursive check here in
-        case there are nested ANDs.  */
-      if ((GET_CODE (XEXP (old, 0)) == GET_CODE (x)
-          && REGNO (XEXP (XEXP (old, 0), 0)) == REGNO (XEXP (x, 0)))
-         || (GET_CODE (XEXP (old, 1)) == GET_CODE (x)
-             && REGNO (XEXP (XEXP (old, 1), 0)) == REGNO (XEXP (x, 0))))
-       return old;
-
+       return NULL;
       return gen_rtx_AND (0, old, x);
 
     case NOT:
       op0 = ior_reg_cond (XEXP (old, 0), not_reg_cond (x), 0);
-      if (op0 != XEXP (old, 0))
+      if (op0 != NULL)
        return not_reg_cond (op0);
       if (! add)
-       return old;
+       return NULL;
       return gen_rtx_AND (0, old, x);
 
     default:
@@ -3099,10 +3235,6 @@ attempt_auto_inc (pbi, inc, insn, mem, incr, incr_reg)
       insns = get_insns ();
       end_sequence ();
 
-      if (basic_block_for_insn)
-       for (temp = insns; temp; temp = NEXT_INSN (temp))
-         set_block_for_insn (temp, pbi->bb);
-
       /* If we can't make the auto-inc, or can't make the
         replacement into Y, exit.  There's no point in making
         the change below if we can't do the auto-inc and doing
@@ -3347,7 +3479,7 @@ mark_used_reg (pbi, reg, cond, insn)
        {
          /* Keep track of which basic block each reg appears in.  */
 
-         register int blocknum = pbi->bb->index;
+         int blocknum = pbi->bb->index;
          if (REG_BASIC_BLOCK (regno_first) == REG_BLOCK_UNKNOWN)
            REG_BASIC_BLOCK (regno_first) = blocknum;
          else if (REG_BASIC_BLOCK (regno_first) != blocknum)
@@ -3479,8 +3611,8 @@ mark_used_regs (pbi, x, cond, insn)
      struct propagate_block_info *pbi;
      rtx x, cond, insn;
 {
-  register RTX_CODE code;
-  register int regno;
+  RTX_CODE code;
+  int regno;
   int flags = pbi->flags;
 
  retry:
@@ -3581,7 +3713,7 @@ mark_used_regs (pbi, x, cond, insn)
 
     case SET:
       {
-       register rtx testreg = SET_DEST (x);
+       rtx testreg = SET_DEST (x);
        int mark_dest = 0;
 
        /* If storing into MEM, don't show it as being used.  But do
@@ -3622,7 +3754,10 @@ mark_used_regs (pbi, x, cond, insn)
               does not use any of the old value.  But these other
               ways of storing in a register do use the old value.  */
            if (GET_CODE (testreg) == SUBREG
-               && !(REG_SIZE (SUBREG_REG (testreg)) > REG_SIZE (testreg)))
+               && !((REG_BYTES (SUBREG_REG (testreg))
+                     + UNITS_PER_WORD - 1) / UNITS_PER_WORD
+                    > (REG_BYTES (testreg)
+                       + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
              ;
            else
              mark_dest = 1;
@@ -3720,8 +3855,8 @@ mark_used_regs (pbi, x, cond, insn)
   /* Recursively scan the operands of this expression.  */
 
   {
-    register const char * const fmt = GET_RTX_FORMAT (code);
-    register int i;
+    const char * const fmt = GET_RTX_FORMAT (code);
+    int i;
 
     for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
       {
@@ -3737,7 +3872,7 @@ mark_used_regs (pbi, x, cond, insn)
          }
        else if (fmt[i] == 'E')
          {
-           register int j;
+           int j;
            for (j = 0; j < XVECLEN (x, i); j++)
              mark_used_regs (pbi, XVECEXP (x, i, j), cond, insn);
          }
@@ -3800,7 +3935,7 @@ try_pre_increment (insn, reg, amount)
      rtx insn, reg;
      HOST_WIDE_INT amount;
 {
-  register rtx use;
+  rtx use;
 
   /* Nonzero if we can try to make a pre-increment or pre-decrement.
      For example, addl $4,r1; movl (r1),... can become movl +(r1),...  */
@@ -3877,15 +4012,15 @@ try_pre_increment (insn, reg, amount)
 
 rtx
 find_use_as_address (x, reg, plusconst)
-     register rtx x;
+     rtx x;
      rtx reg;
      HOST_WIDE_INT plusconst;
 {
   enum rtx_code code = GET_CODE (x);
   const char * const fmt = GET_RTX_FORMAT (code);
-  register int i;
-  register rtx value = 0;
-  register rtx tem;
+  int i;
+  rtx value = 0;
+  rtx tem;
 
   if (code == MEM && XEXP (x, 0) == reg && plusconst == 0)
     return x;
@@ -3919,7 +4054,7 @@ find_use_as_address (x, reg, plusconst)
        }
       else if (fmt[i] == 'E')
        {
-         register int j;
+         int j;
          for (j = XVECLEN (x, i) - 1; j >= 0; j--)
            {
              tem = find_use_as_address (XVECEXP (x, i, j), reg, plusconst);
@@ -4086,31 +4221,32 @@ count_or_remove_death_notes (blocks, kill)
 
   return count;
 }
-/* Clear LOG_LINKS fields of insns in a chain.
-   Also clear the global_live_at_{start,end} fields of the basic block
-   structures.  */
+/* Clear LOG_LINKS fields of insns in a selected blocks or whole chain
+   if blocks is NULL.  */
 
-void
-clear_log_links (insns)
-     rtx insns;
+static void
+clear_log_links (blocks)
+     sbitmap blocks;
 {
-  rtx i;
-  int b;
-
-  for (i = insns; i; i = NEXT_INSN (i))
-    if (INSN_P (i))
-      LOG_LINKS (i) = 0;
+  rtx insn;
+  int i;
 
-  for (b = 0; b < n_basic_blocks; b++)
+  if (!blocks)
     {
-      basic_block bb = BASIC_BLOCK (b);
-
-      bb->global_live_at_start = NULL;
-      bb->global_live_at_end = NULL;
+      for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+       if (INSN_P (insn))
+         free_INSN_LIST_list (&LOG_LINKS (insn));
     }
+  else
+    EXECUTE_IF_SET_IN_SBITMAP (blocks, 0, i,
+      {
+       basic_block bb = BASIC_BLOCK (i);
 
-  ENTRY_BLOCK_PTR->global_live_at_end = NULL;
-  EXIT_BLOCK_PTR->global_live_at_start = NULL;
+       for (insn = bb->head; insn != NEXT_INSN (bb->end);
+            insn = NEXT_INSN (insn))
+         if (INSN_P (insn))
+           free_INSN_LIST_list (&LOG_LINKS (insn));
+      });
 }
 
 /* Given a register bitmap, turn on the bits in a HARD_REG_SET that