OSDN Git Service

cp:
[pf3gnuchains/gcc-fork.git] / gcc / combine.c
index a155555..ea12b13 100644 (file)
@@ -192,8 +192,8 @@ static HARD_REG_SET newpat_used_regs;
 
 static rtx added_links_insn;
 
-/* Basic block number of the block in which we are performing combines.  */
-static int this_basic_block;
+/* Basic block in which we are performing combines.  */
+static basic_block this_basic_block;
 
 /* A bitmap indicating which blocks had registers go dead at entry.
    After combine, we'll need to re-do global life analysis with
@@ -578,7 +578,7 @@ combine_instructions (f, nregs)
 
   setup_incoming_promotions ();
 
-  refresh_blocks = sbitmap_alloc (n_basic_blocks);
+  refresh_blocks = sbitmap_alloc (last_basic_block);
   sbitmap_zero (refresh_blocks);
   need_refresh = 0;
 
@@ -610,143 +610,144 @@ combine_instructions (f, nregs)
 
   /* Now scan all the insns in forward order.  */
 
-  this_basic_block = -1;
   label_tick = 1;
   last_call_cuid = 0;
   mem_last_set = 0;
   init_reg_last_arrays ();
   setup_incoming_promotions ();
 
-  for (insn = f; insn; insn = next ? next : NEXT_INSN (insn))
+  FOR_EACH_BB (this_basic_block)
     {
-      next = 0;
-
-      /* If INSN starts a new basic block, update our basic block number.  */
-      if (this_basic_block + 1 < n_basic_blocks
-         && BLOCK_HEAD (this_basic_block + 1) == insn)
-       this_basic_block++;
-
-      if (GET_CODE (insn) == CODE_LABEL)
-       label_tick++;
-
-      else if (INSN_P (insn))
+      for (insn = this_basic_block->head;
+           insn != NEXT_INSN (this_basic_block->end);
+          insn = next ? next : NEXT_INSN (insn))
        {
-         /* See if we know about function return values before this
-            insn based upon SUBREG flags.  */
-         check_promoted_subreg (insn, PATTERN (insn));
+         next = 0;
 
-         /* Try this insn with each insn it links back to.  */
+         if (GET_CODE (insn) == CODE_LABEL)
+           label_tick++;
 
-         for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
-           if ((next = try_combine (insn, XEXP (links, 0),
-                                    NULL_RTX, &new_direct_jump_p)) != 0)
-             goto retry;
-
-         /* Try each sequence of three linked insns ending with this one.  */
-
-         for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
+         else if (INSN_P (insn))
            {
-             rtx link = XEXP (links, 0);
+             /* See if we know about function return values before this
+                insn based upon SUBREG flags.  */
+             check_promoted_subreg (insn, PATTERN (insn));
 
-             /* If the linked insn has been replaced by a note, then there
-                is no point in pursuing this chain any further.  */
-             if (GET_CODE (link) == NOTE)
-               continue;
+             /* Try this insn with each insn it links back to.  */
 
-             for (nextlinks = LOG_LINKS (link);
-                  nextlinks;
-                  nextlinks = XEXP (nextlinks, 1))
-               if ((next = try_combine (insn, link,
-                                        XEXP (nextlinks, 0),
-                                        &new_direct_jump_p)) != 0)
+             for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
+               if ((next = try_combine (insn, XEXP (links, 0),
+                                        NULL_RTX, &new_direct_jump_p)) != 0)
                  goto retry;
-           }
+
+             /* Try each sequence of three linked insns ending with this one.  */
+
+             for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
+               {
+                 rtx link = XEXP (links, 0);
+
+                 /* If the linked insn has been replaced by a note, then there
+                    is no point in pursuing this chain any further.  */
+                 if (GET_CODE (link) == NOTE)
+                   continue;
+
+                 for (nextlinks = LOG_LINKS (link);
+                      nextlinks;
+                      nextlinks = XEXP (nextlinks, 1))
+                   if ((next = try_combine (insn, link,
+                                            XEXP (nextlinks, 0),
+                                            &new_direct_jump_p)) != 0)
+                     goto retry;
+               }
 
 #ifdef HAVE_cc0
-         /* Try to combine a jump insn that uses CC0
-            with a preceding insn that sets CC0, and maybe with its
-            logical predecessor as well.
-            This is how we make decrement-and-branch insns.
-            We need this special code because data flow connections
-            via CC0 do not get entered in LOG_LINKS.  */
-
-         if (GET_CODE (insn) == JUMP_INSN
-             && (prev = prev_nonnote_insn (insn)) != 0
-             && GET_CODE (prev) == INSN
-             && sets_cc0_p (PATTERN (prev)))
-           {
-             if ((next = try_combine (insn, prev,
-                                      NULL_RTX, &new_direct_jump_p)) != 0)
-               goto retry;
-
-             for (nextlinks = LOG_LINKS (prev); nextlinks;
-                  nextlinks = XEXP (nextlinks, 1))
-               if ((next = try_combine (insn, prev,
-                                        XEXP (nextlinks, 0),
-                                        &new_direct_jump_p)) != 0)
-                 goto retry;
-           }
+             /* Try to combine a jump insn that uses CC0
+                with a preceding insn that sets CC0, and maybe with its
+                logical predecessor as well.
+                This is how we make decrement-and-branch insns.
+                We need this special code because data flow connections
+                via CC0 do not get entered in LOG_LINKS.  */
+
+             if (GET_CODE (insn) == JUMP_INSN
+                 && (prev = prev_nonnote_insn (insn)) != 0
+                 && GET_CODE (prev) == INSN
+                 && sets_cc0_p (PATTERN (prev)))
+               {
+                 if ((next = try_combine (insn, prev,
+                                          NULL_RTX, &new_direct_jump_p)) != 0)
+                   goto retry;
+
+                 for (nextlinks = LOG_LINKS (prev); nextlinks;
+                      nextlinks = XEXP (nextlinks, 1))
+                   if ((next = try_combine (insn, prev,
+                                            XEXP (nextlinks, 0),
+                                            &new_direct_jump_p)) != 0)
+                     goto retry;
+               }
 
-         /* Do the same for an insn that explicitly references CC0.  */
-         if (GET_CODE (insn) == INSN
-             && (prev = prev_nonnote_insn (insn)) != 0
-             && GET_CODE (prev) == INSN
-             && sets_cc0_p (PATTERN (prev))
-             && GET_CODE (PATTERN (insn)) == SET
-             && reg_mentioned_p (cc0_rtx, SET_SRC (PATTERN (insn))))
-           {
-             if ((next = try_combine (insn, prev,
-                                      NULL_RTX, &new_direct_jump_p)) != 0)
-               goto retry;
+             /* Do the same for an insn that explicitly references CC0.  */
+             if (GET_CODE (insn) == INSN
+                 && (prev = prev_nonnote_insn (insn)) != 0
+                 && GET_CODE (prev) == INSN
+                 && sets_cc0_p (PATTERN (prev))
+                 && GET_CODE (PATTERN (insn)) == SET
+                 && reg_mentioned_p (cc0_rtx, SET_SRC (PATTERN (insn))))
+               {
+                 if ((next = try_combine (insn, prev,
+                                          NULL_RTX, &new_direct_jump_p)) != 0)
+                   goto retry;
+
+                 for (nextlinks = LOG_LINKS (prev); nextlinks;
+                      nextlinks = XEXP (nextlinks, 1))
+                   if ((next = try_combine (insn, prev,
+                                            XEXP (nextlinks, 0),
+                                            &new_direct_jump_p)) != 0)
+                     goto retry;
+               }
 
-             for (nextlinks = LOG_LINKS (prev); nextlinks;
-                  nextlinks = XEXP (nextlinks, 1))
-               if ((next = try_combine (insn, prev,
-                                        XEXP (nextlinks, 0),
-                                        &new_direct_jump_p)) != 0)
+             /* Finally, see if any of the insns that this insn links to
+                explicitly references CC0.  If so, try this insn, that insn,
+                and its predecessor if it sets CC0.  */
+             for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
+               if (GET_CODE (XEXP (links, 0)) == INSN
+                   && GET_CODE (PATTERN (XEXP (links, 0))) == SET
+                   && reg_mentioned_p (cc0_rtx, SET_SRC (PATTERN (XEXP (links, 0))))
+                   && (prev = prev_nonnote_insn (XEXP (links, 0))) != 0
+                   && GET_CODE (prev) == INSN
+                   && sets_cc0_p (PATTERN (prev))
+                   && (next = try_combine (insn, XEXP (links, 0),
+                                           prev, &new_direct_jump_p)) != 0)
                  goto retry;
-           }
-
-         /* Finally, see if any of the insns that this insn links to
-            explicitly references CC0.  If so, try this insn, that insn,
-            and its predecessor if it sets CC0.  */
-         for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
-           if (GET_CODE (XEXP (links, 0)) == INSN
-               && GET_CODE (PATTERN (XEXP (links, 0))) == SET
-               && reg_mentioned_p (cc0_rtx, SET_SRC (PATTERN (XEXP (links, 0))))
-               && (prev = prev_nonnote_insn (XEXP (links, 0))) != 0
-               && GET_CODE (prev) == INSN
-               && sets_cc0_p (PATTERN (prev))
-               && (next = try_combine (insn, XEXP (links, 0),
-                                       prev, &new_direct_jump_p)) != 0)
-             goto retry;
 #endif
 
-         /* Try combining an insn with two different insns whose results it
-            uses.  */
-         for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
-           for (nextlinks = XEXP (links, 1); nextlinks;
-                nextlinks = XEXP (nextlinks, 1))
-             if ((next = try_combine (insn, XEXP (links, 0),
-                                      XEXP (nextlinks, 0),
-                                      &new_direct_jump_p)) != 0)
-               goto retry;
+             /* Try combining an insn with two different insns whose results it
+                uses.  */
+             for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
+               for (nextlinks = XEXP (links, 1); nextlinks;
+                    nextlinks = XEXP (nextlinks, 1))
+                 if ((next = try_combine (insn, XEXP (links, 0),
+                                          XEXP (nextlinks, 0),
+                                          &new_direct_jump_p)) != 0)
+                   goto retry;
 
-         if (GET_CODE (insn) != NOTE)
-           record_dead_and_set_regs (insn);
+             if (GET_CODE (insn) != NOTE)
+               record_dead_and_set_regs (insn);
 
-       retry:
-         ;
+           retry:
+             ;
+           }
        }
     }
+  clear_bb_flags ();
 
+  EXECUTE_IF_SET_IN_SBITMAP (refresh_blocks, 0, i,
+                            BASIC_BLOCK (i)->flags |= BB_DIRTY);
+  new_direct_jump_p |= purge_all_dead_edges (0);
   delete_noop_moves (f);
 
-  if (need_refresh)
-    {
-      update_life_info (refresh_blocks, UPDATE_LIFE_GLOBAL_RM_NOTES,
-                       PROP_DEATH_NOTES);
-    }
+  update_life_info_in_dirty_blocks (UPDATE_LIFE_GLOBAL_RM_NOTES,
+                                   PROP_DEATH_NOTES | PROP_SCAN_DEAD_CODE
+                                   | PROP_KILL_DEAD_CODE);
 
   /* Clean up.  */
   sbitmap_free (refresh_blocks);
@@ -858,7 +859,7 @@ set_nonzero_bits_and_sign_copies (x, set, data)
       && REGNO (x) >= FIRST_PSEUDO_REGISTER
       /* If this register is undefined at the start of the file, we can't
         say what its contents were.  */
-      && ! REGNO_REG_SET_P (BASIC_BLOCK (0)->global_live_at_start, REGNO (x))
+      && ! REGNO_REG_SET_P (ENTRY_BLOCK_PTR->next_bb->global_live_at_start, REGNO (x))
       && GET_MODE_BITSIZE (GET_MODE (x)) <= HOST_BITS_PER_WIDE_INT)
     {
       if (set == 0 || GET_CODE (set) == CLOBBER)
@@ -904,8 +905,10 @@ set_nonzero_bits_and_sign_copies (x, set, data)
                              << GET_MODE_BITSIZE (GET_MODE (x))));
 #endif
 
-         reg_nonzero_bits[REGNO (x)]
-           |= nonzero_bits (src, nonzero_bits_mode);
+         /* Don't call nonzero_bits if it cannot change anything.  */
+         if (reg_nonzero_bits[REGNO (x)] != ~(unsigned HOST_WIDE_INT) 0)
+           reg_nonzero_bits[REGNO (x)]
+             |= nonzero_bits (src, nonzero_bits_mode);
          num = num_sign_bit_copies (SET_SRC (set), GET_MODE (x));
          if (reg_sign_bit_copies[REGNO (x)] == 0
              || reg_sign_bit_copies[REGNO (x)] > num)
@@ -1752,6 +1755,7 @@ try_combine (i3, i2, i1, new_direct_jump_p)
 
          subst_prev_insn = i1
            = gen_rtx_INSN (VOIDmode, INSN_UID (i2), NULL_RTX, i2,
+                           BLOCK_FOR_INSN (i2), INSN_SCOPE (i2),
                            XVECEXP (PATTERN (i2), 0, 1), -1, NULL_RTX,
                            NULL_RTX);
 
@@ -2163,30 +2167,23 @@ try_combine (i3, i2, i1, new_direct_jump_p)
            }
        }
 
-      /* If we've split a jump pattern, we'll wind up with a sequence even
-        with one instruction.  We can handle that below, so extract it.  */
-      if (m_split && GET_CODE (m_split) == SEQUENCE
-         && XVECLEN (m_split, 0) == 1)
-       m_split = PATTERN (XVECEXP (m_split, 0, 0));
-
-      if (m_split && GET_CODE (m_split) != SEQUENCE)
+      if (m_split && NEXT_INSN (m_split) == NULL_RTX)
        {
+         m_split = PATTERN (m_split);
          insn_code_number = recog_for_combine (&m_split, i3, &new_i3_notes);
          if (insn_code_number >= 0)
            newpat = m_split;
        }
-      else if (m_split && GET_CODE (m_split) == SEQUENCE
-              && XVECLEN (m_split, 0) == 2
+      else if (m_split && NEXT_INSN (NEXT_INSN (m_split)) == NULL_RTX
               && (next_real_insn (i2) == i3
-                  || ! use_crosses_set_p (PATTERN (XVECEXP (m_split, 0, 0)),
-                                          INSN_CUID (i2))))
+                  || ! use_crosses_set_p (PATTERN (m_split), INSN_CUID (i2))))
        {
          rtx i2set, i3set;
-         rtx newi3pat = PATTERN (XVECEXP (m_split, 0, 1));
-         newi2pat = PATTERN (XVECEXP (m_split, 0, 0));
+         rtx newi3pat = PATTERN (NEXT_INSN (m_split));
+         newi2pat = PATTERN (m_split);
 
-         i3set = single_set (XVECEXP (m_split, 0, 1));
-         i2set = single_set (XVECEXP (m_split, 0, 0));
+         i3set = single_set (NEXT_INSN (m_split));
+         i2set = single_set (m_split);
 
          /* In case we changed the mode of I2DEST, replace it in the
             pseudo-register table here.  We can't do it above in case this
@@ -2384,8 +2381,8 @@ try_combine (i3, i2, i1, new_direct_jump_p)
             which we know will be a NOTE.  */
 
          for (insn = NEXT_INSN (i3);
-              insn && (this_basic_block == n_basic_blocks - 1
-                       || insn != BLOCK_HEAD (this_basic_block + 1));
+              insn && (this_basic_block->next_bb == EXIT_BLOCK_PTR
+                       || insn != this_basic_block->next_bb->head);
               insn = NEXT_INSN (insn))
            {
              if (INSN_P (insn) && reg_referenced_p (ni2dest, PATTERN (insn)))
@@ -2602,8 +2599,8 @@ try_combine (i3, i2, i1, new_direct_jump_p)
              && ! find_reg_note (i2, REG_UNUSED,
                                  SET_DEST (XVECEXP (PATTERN (i2), 0, i))))
            for (temp = NEXT_INSN (i2);
-                temp && (this_basic_block == n_basic_blocks - 1
-                         || BLOCK_HEAD (this_basic_block) != temp);
+                temp && (this_basic_block->next_bb == EXIT_BLOCK_PTR
+                         || this_basic_block->head != temp);
                 temp = NEXT_INSN (temp))
              if (temp != i3 && INSN_P (temp))
                for (link = LOG_LINKS (temp); link; link = XEXP (link, 1))
@@ -2956,20 +2953,22 @@ find_split_point (loc, insn)
             we can make put both sources together and make a split point
             in the middle.  */
 
-         if (seq && XVECLEN (seq, 0) == 2
-             && GET_CODE (XVECEXP (seq, 0, 0)) == INSN
-             && GET_CODE (PATTERN (XVECEXP (seq, 0, 0))) == SET
-             && SET_DEST (PATTERN (XVECEXP (seq, 0, 0))) == reg
+         if (seq
+             && NEXT_INSN (seq) != NULL_RTX
+             && NEXT_INSN (NEXT_INSN (seq)) == NULL_RTX
+             && GET_CODE (seq) == INSN
+             && GET_CODE (PATTERN (seq)) == SET
+             && SET_DEST (PATTERN (seq)) == reg
              && ! reg_mentioned_p (reg,
-                                   SET_SRC (PATTERN (XVECEXP (seq, 0, 0))))
-             && GET_CODE (XVECEXP (seq, 0, 1)) == INSN
-             && GET_CODE (PATTERN (XVECEXP (seq, 0, 1))) == SET
-             && SET_DEST (PATTERN (XVECEXP (seq, 0, 1))) == reg
+                                   SET_SRC (PATTERN (seq)))
+             && GET_CODE (NEXT_INSN (seq)) == INSN
+             && GET_CODE (PATTERN (NEXT_INSN (seq))) == SET
+             && SET_DEST (PATTERN (NEXT_INSN (seq))) == reg
              && memory_address_p (GET_MODE (x),
-                                  SET_SRC (PATTERN (XVECEXP (seq, 0, 1)))))
+                                  SET_SRC (PATTERN (NEXT_INSN (seq)))))
            {
-             rtx src1 = SET_SRC (PATTERN (XVECEXP (seq, 0, 0)));
-             rtx src2 = SET_SRC (PATTERN (XVECEXP (seq, 0, 1)));
+             rtx src1 = SET_SRC (PATTERN (seq));
+             rtx src2 = SET_SRC (PATTERN (NEXT_INSN (seq)));
 
              /* Replace the placeholder in SRC2 with SRC1.  If we can
                 find where in SRC2 it was placed, that can become our
@@ -3060,8 +3059,8 @@ find_split_point (loc, insn)
            SUBST (SET_SRC (x),
                   gen_binary (IOR, mode,
                               gen_binary (AND, mode, dest,
-                                          GEN_INT (~(mask << pos)
-                                                   & GET_MODE_MASK (mode))),
+                                          gen_int_mode (~(mask << pos),
+                                                        mode)),
                               GEN_INT (src << pos)));
 
          SUBST (SET_DEST (x), dest);
@@ -3534,11 +3533,13 @@ subst (x, from, to, in_dest, unique_copy)
 
              if (GET_CODE (new) == CONST_INT && GET_CODE (x) == SUBREG)
                {
+                 enum machine_mode mode = GET_MODE (x);
+
                  x = simplify_subreg (GET_MODE (x), new,
                                       GET_MODE (SUBREG_REG (x)),
                                       SUBREG_BYTE (x));
                  if (! x)
-                   abort ();
+                   x = gen_rtx_CLOBBER (mode, const0_rtx);
                }
              else if (GET_CODE (new) == CONST_INT
                       && GET_CODE (x) == ZERO_EXTEND)
@@ -3766,7 +3767,8 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
          if (temp == const0_rtx)
            temp = CONST0_RTX (mode);
          else
-           temp = immed_real_const_1 (FLOAT_STORE_FLAG_VALUE (mode), mode);
+           temp = CONST_DOUBLE_FROM_REAL_VALUE (FLOAT_STORE_FLAG_VALUE (mode),
+                                                mode);
        }
 #endif
       break;
@@ -3858,7 +3860,12 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
 
       /* simplify_subreg can't use gen_lowpart_for_combine.  */
       if (CONSTANT_P (SUBREG_REG (x))
-         && subreg_lowpart_offset (mode, op0_mode) == SUBREG_BYTE (x))
+         && subreg_lowpart_offset (mode, op0_mode) == SUBREG_BYTE (x)
+            /* Don't call gen_lowpart_for_combine if the inner mode
+               is VOIDmode and we cannot simplify it, as SUBREG without
+               inner mode is invalid.  */
+         && (GET_MODE (SUBREG_REG (x)) != VOIDmode
+             || gen_lowpart_common (mode, SUBREG_REG (x))))
        return gen_lowpart_for_combine (mode, SUBREG_REG (x));
 
       if (GET_MODE_CLASS (GET_MODE (SUBREG_REG (x))) == MODE_CC)
@@ -3871,6 +3878,13 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
          return temp;
       }
 
+      /* Don't change the mode of the MEM if that would change the meaning
+        of the address.  */
+      if (GET_CODE (SUBREG_REG (x)) == MEM
+         && (MEM_VOLATILE_P (SUBREG_REG (x))
+             || mode_dependent_address_p (XEXP (SUBREG_REG (x), 0))))
+       return gen_rtx_CLOBBER (mode, const0_rtx);
+
       /* Note that we cannot do any narrowing for non-constants since
         we might have been counting on using the fact that some bits were
         zero.  We now do this in the SET.  */
@@ -3978,12 +3992,14 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
       if (GET_CODE (XEXP (x, 0)) == NOT)
        return plus_constant (XEXP (XEXP (x, 0), 0), 1);
 
-      /* (neg (minus X Y)) can become (minus Y X).  */
+      /* (neg (minus X Y)) can become (minus Y X).  This transformation
+        isn't safe for modes with signed zeros, since if X and Y are
+        both +0, (minus Y X) is the same as (minus X Y).  If the rounding
+        mode is towards +infinity (or -infinity) then the two expressions
+        will be rounded differently.  */
       if (GET_CODE (XEXP (x, 0)) == MINUS
-         && (! FLOAT_MODE_P (mode)
-             /* x-y != -(y-x) with IEEE floating point.  */
-             || TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
-             || flag_unsafe_math_optimizations))
+         && !HONOR_SIGNED_ZEROS (mode)
+         && !HONOR_SIGN_DEPENDENT_ROUNDING (mode))
        return gen_binary (MINUS, mode, XEXP (XEXP (x, 0), 1),
                           XEXP (XEXP (x, 0), 0));
 
@@ -4145,10 +4161,11 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
       if (XEXP (x, 1) == const0_rtx)
        return XEXP (x, 0);
 
-      /* In IEEE floating point, x-0 is not the same as x.  */
-      if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
-          || ! FLOAT_MODE_P (GET_MODE (XEXP (x, 0)))
-          || flag_unsafe_math_optimizations)
+      /* x - 0 is the same as x unless x's mode has signed zeros and
+        allows rounding towards -infinity.  Under those conditions,
+        0 - 0 is -0.  */
+      if (!(HONOR_SIGNED_ZEROS (GET_MODE (XEXP (x, 0)))
+           && HONOR_SIGN_DEPENDENT_ROUNDING (GET_MODE (XEXP (x, 0))))
          && XEXP (x, 1) == CONST0_RTX (GET_MODE (XEXP (x, 0))))
        return XEXP (x, 0);
       break;
@@ -5143,6 +5160,30 @@ simplify_set (x)
       src = SET_SRC (x), dest = SET_DEST (x);
     }
 
+#ifdef HAVE_cc0
+  /* If we have (set (cc0) (subreg ...)), we try to remove the subreg
+     in SRC.  */
+  if (dest == cc0_rtx
+      && GET_CODE (src) == SUBREG
+      && subreg_lowpart_p (src)
+      && (GET_MODE_BITSIZE (GET_MODE (src))
+         < GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (src)))))
+    {
+      rtx inner = SUBREG_REG (src);
+      enum machine_mode inner_mode = GET_MODE (inner);
+
+      /* Here we make sure that we don't have a sign bit on.  */
+      if (GET_MODE_BITSIZE (inner_mode) <= HOST_BITS_PER_WIDE_INT
+         && (nonzero_bits (inner, inner_mode)
+             < ((unsigned HOST_WIDE_INT) 1
+                << (GET_MODE_BITSIZE (inner_mode) - 1))))
+       {
+         SUBST (SET_SRC (x), inner);
+         src = SET_SRC (x);
+       }
+    }
+#endif
+
 #ifdef LOAD_EXTEND_OP
   /* If we have (set FOO (subreg:M (mem:N BAR) 0)) with M wider than N, this
      would require a paradoxical subreg.  Replace the subreg with a
@@ -5583,7 +5624,7 @@ expand_compound_operation (x)
 
       len = GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0)));
       /* If the inner object has VOIDmode (the only way this can happen
-        is if it is a ASM_OPERANDS), we can't do anything since we don't
+        is if it is an ASM_OPERANDS), we can't do anything since we don't
         know how much masking to do.  */
       if (len == 0)
        return x;
@@ -5927,6 +5968,21 @@ make_extraction (mode, inner, pos, pos_rtx, len,
        is_mode = GET_MODE (SUBREG_REG (inner));
       inner = SUBREG_REG (inner);
     }
+  else if (GET_CODE (inner) == ASHIFT
+          && GET_CODE (XEXP (inner, 1)) == CONST_INT
+          && pos_rtx == 0 && pos == 0
+          && len > INTVAL (XEXP (inner, 1)))
+    {
+      /* We're extracting the least significant bits of an rtx
+        (ashift X (const_int C)), where LEN > C.  Extract the
+        least significant (LEN - C) bits of X, giving an rtx
+        whose mode is MODE, then shift it left C times.  */
+      new = make_extraction (mode, XEXP (inner, 0),
+                            0, 0, len - INTVAL (XEXP (inner, 1)),
+                            unsignedp, in_dest, in_compare);
+      if (new != 0)
+       return gen_rtx_ASHIFT (mode, new, XEXP (inner, 1));
+    }
 
   inner_mode = GET_MODE (inner);
 
@@ -6027,6 +6083,9 @@ make_extraction (mode, inner, pos, pos_rtx, len,
       if (mode == tmode)
        return new;
 
+      if (GET_CODE (new) == CONST_INT)
+       return gen_int_mode (INTVAL (new), mode);
+
       /* If we know that no extraneous bits are set, and that the high
         bit is not set, convert the extraction to the cheaper of
         sign and zero extension, that are equivalent in these cases.  */
@@ -6682,18 +6741,7 @@ force_to_mode (x, mode, mask, reg, just_select)
   /* If X is a CONST_INT, return a new one.  Do this here since the
      test below will fail.  */
   if (GET_CODE (x) == CONST_INT)
-    {
-      HOST_WIDE_INT cval = INTVAL (x) & mask;
-      int width = GET_MODE_BITSIZE (mode);
-
-      /* If MODE is narrower that HOST_WIDE_INT and CVAL is a negative
-        number, sign extend it.  */
-      if (width > 0 && width < HOST_BITS_PER_WIDE_INT
-         && (cval & ((HOST_WIDE_INT) 1 << (width - 1))) != 0)
-       cval |= (HOST_WIDE_INT) -1 << width;
-
-      return GEN_INT (cval);
-    }
+    return gen_int_mode (INTVAL (x) & mask, mode);
 
   /* If X is narrower than MODE and we want all the bits in X's mode, just
      get X in the proper mode.  */
@@ -6899,14 +6947,6 @@ force_to_mode (x, mode, mask, reg, just_select)
                                     force_to_mode (XEXP (x, 1), mode, mask,
                                                    reg, next_select));
 
-      /* If OP1 is a CONST_INT and X is an IOR or XOR, clear bits outside
-        MASK since OP1 might have been sign-extended but we never want
-        to turn on extra bits, since combine might have previously relied
-        on them being off.  */
-      if (GET_CODE (op1) == CONST_INT && (code == IOR || code == XOR)
-         && (INTVAL (op1) & mask) != 0)
-       op1 = GEN_INT (INTVAL (op1) & mask);
-
       if (op_mode != GET_MODE (x) || op0 != XEXP (x, 0) || op1 != XEXP (x, 1))
        x = gen_binary (code, op_mode, op0, op1);
       break;
@@ -7056,7 +7096,7 @@ force_to_mode (x, mode, mask, reg, just_select)
            }
        }
 
-      /* If MASK is 1, convert this to a LSHIFTRT.  This can be done
+      /* If MASK is 1, convert this to an LSHIFTRT.  This can be done
         even if the shift count isn't a constant.  */
       if (mask == 1)
        x = gen_binary (LSHIFTRT, GET_MODE (x), XEXP (x, 0), XEXP (x, 1));
@@ -7365,7 +7405,7 @@ if_then_else_cond (x, ptrue, pfalse)
           && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
           && exact_log2 (nz = nonzero_bits (x, mode)) >= 0)
     {
-      *ptrue = GEN_INT (nz), *pfalse = const0_rtx;
+      *ptrue = gen_int_mode (nz, mode), *pfalse = const0_rtx;
       return x;
     }
 
@@ -7830,14 +7870,23 @@ simplify_and_const_int (x, mode, varop, constop)
   int i;
 
   /* Simplify VAROP knowing that we will be only looking at some of the
-     bits in it.  */
+     bits in it.
+
+     Note by passing in CONSTOP, we guarantee that the bits not set in
+     CONSTOP are not significant and will never be examined.  We must
+     ensure that is the case by explicitly masking out those bits
+     before returning.  */
   varop = force_to_mode (varop, mode, constop, NULL_RTX, 0);
 
-  /* If VAROP is a CLOBBER, we will fail so return it; if it is a
-     CONST_INT, we are done.  */
-  if (GET_CODE (varop) == CLOBBER || GET_CODE (varop) == CONST_INT)
+  /* If VAROP is a CLOBBER, we will fail so return it.  */
+  if (GET_CODE (varop) == CLOBBER)
     return varop;
 
+  /* If VAROP is a CONST_INT, then we need to apply the mask in CONSTOP
+     to VAROP and return the new constant.  */
+  if (GET_CODE (varop) == CONST_INT)
+    return GEN_INT (trunc_int_for_mode (INTVAL (varop) & constop, mode));
+
   /* See what bits may be nonzero in VAROP.  Unlike the general case of
      a call to nonzero_bits, here we don't care about bits outside
      MODE.  */
@@ -7855,7 +7904,7 @@ simplify_and_const_int (x, mode, varop, constop)
     return const0_rtx;
 
   /* If VAROP is a NEG of something known to be zero or 1 and CONSTOP is
-     a power of two, we can replace this with a ASHIFT.  */
+     a power of two, we can replace this with an ASHIFT.  */
   if (GET_CODE (varop) == NEG && nonzero_bits (XEXP (varop, 0), mode) == 1
       && (i = exact_log2 (constop)) >= 0)
     return simplify_shift_const (NULL_RTX, ASHIFT, mode, XEXP (varop, 0), i);
@@ -8032,11 +8081,13 @@ nonzero_bits (x, mode)
         for this register.  */
 
       if (reg_last_set_value[REGNO (x)] != 0
-         && reg_last_set_mode[REGNO (x)] == mode
+         && (reg_last_set_mode[REGNO (x)] == mode
+             || (GET_MODE_CLASS (reg_last_set_mode[REGNO (x)]) == MODE_INT
+                 && GET_MODE_CLASS (mode) == MODE_INT))
          && (reg_last_set_label[REGNO (x)] == label_tick
              || (REGNO (x) >= FIRST_PSEUDO_REGISTER
                  && REG_N_SETS (REGNO (x)) == 1
-                 && ! REGNO_REG_SET_P (BASIC_BLOCK (0)->global_live_at_start,
+                 && ! REGNO_REG_SET_P (ENTRY_BLOCK_PTR->next_bb->global_live_at_start,
                                        REGNO (x))))
          && INSN_CUID (reg_last_set[REGNO (x)]) < subst_low_cuid)
        return reg_last_set_nonzero_bits[REGNO (x)] & nonzero;
@@ -8174,8 +8225,14 @@ nonzero_bits (x, mode)
 
     case XOR:   case IOR:
     case UMIN:  case UMAX:  case SMIN:  case SMAX:
-      nonzero &= (nonzero_bits (XEXP (x, 0), mode)
-                 | nonzero_bits (XEXP (x, 1), mode));
+      {
+       unsigned HOST_WIDE_INT nonzero0 = nonzero_bits (XEXP (x, 0), mode);
+
+       /* Don't call nonzero_bits for the second time if it cannot change
+          anything.  */
+       if ((nonzero & nonzero0) != nonzero)
+         nonzero &= (nonzero0 | nonzero_bits (XEXP (x, 1), mode));
+      }
       break;
 
     case PLUS:  case MINUS:
@@ -8445,7 +8502,7 @@ num_sign_bit_copies (x, mode)
          && (reg_last_set_label[REGNO (x)] == label_tick
              || (REGNO (x) >= FIRST_PSEUDO_REGISTER
                  && REG_N_SETS (REGNO (x)) == 1
-                 && ! REGNO_REG_SET_P (BASIC_BLOCK (0)->global_live_at_start,
+                 && ! REGNO_REG_SET_P (ENTRY_BLOCK_PTR->next_bb->global_live_at_start,
                                        REGNO (x))))
          && INSN_CUID (reg_last_set[REGNO (x)]) < subst_low_cuid)
        return reg_last_set_sign_bit_copies[REGNO (x)];
@@ -9017,8 +9074,8 @@ simplify_shift_const (x, code, result_mode, varop, orig_count)
 
       /* We simplify the tests below and elsewhere by converting
         ASHIFTRT to LSHIFTRT if we know the sign bit is clear.
-        `make_compound_operation' will convert it to a ASHIFTRT for
-        those machines (such as VAX) that don't have a LSHIFTRT.  */
+        `make_compound_operation' will convert it to an ASHIFTRT for
+        those machines (such as VAX) that don't have an LSHIFTRT.  */
       if (GET_MODE_BITSIZE (shift_mode) <= HOST_BITS_PER_WIDE_INT
          && code == ASHIFTRT
          && ((nonzero_bits (varop, shift_mode)
@@ -9191,7 +9248,7 @@ simplify_shift_const (x, code, result_mode, varop, orig_count)
 
              /* If this was (ashiftrt (ashift foo C1) C2) and FOO has more
                 than C1 high-order bits equal to the sign bit, we can convert
-                this to either an ASHIFT or a ASHIFTRT depending on the
+                this to either an ASHIFT or an ASHIFTRT depending on the
                 two counts.
 
                 We cannot do this if VAROP's mode is not SHIFT_MODE.  */
@@ -9591,7 +9648,7 @@ simplify_shift_const (x, code, result_mode, varop, orig_count)
     x = simplify_shift_const (x, code, shift_mode, XEXP (x, 0),
                              INTVAL (XEXP (x, 1)));
 
-  /* If we were doing a LSHIFTRT in a wider mode than it was originally,
+  /* If we were doing an LSHIFTRT in a wider mode than it was originally,
      turn off all the bits that the shift would have turned off.  */
   if (orig_code == LSHIFTRT && result_mode != shift_mode)
     x = simplify_and_const_int (NULL_RTX, shift_mode, x,
@@ -9766,6 +9823,12 @@ gen_lowpart_for_combine (mode, x)
            || GET_MODE_SIZE (GET_MODE (x)) == GET_MODE_SIZE (mode)))
     return gen_rtx_CLOBBER (GET_MODE (x), const0_rtx);
 
+  /* simplify_gen_subreg does not know how to handle the case where we try
+     to convert an integer constant to a vector.
+     ??? We could try to teach it to generate CONST_VECTORs.  */
+  if (GET_MODE (x) == VOIDmode && VECTOR_MODE_P (mode))
+    return gen_rtx_CLOBBER (GET_MODE (x), const0_rtx);
+
   /* X might be a paradoxical (subreg (mem)).  In that case, gen_lowpart
      won't know what to do.  So we will strip off the SUBREG here and
      process normally.  */
@@ -10784,7 +10847,7 @@ simplify_comparison (code, pop0, pop1)
              unsigned HOST_WIDE_INT temp = const_op & GET_MODE_MASK (mode);
 
              temp >>= INTVAL (XEXP (op0, 1));
-             op1 = GEN_INT (trunc_int_for_mode (temp, mode));
+             op1 = gen_int_mode (temp, mode);
              op0 = XEXP (op0, 0);
              continue;
            }
@@ -10835,9 +10898,9 @@ simplify_comparison (code, pop0, pop1)
              && XEXP (op0, 1) == XEXP (XEXP (op0, 0), 1)
              && (tmode = mode_for_size (mode_width - INTVAL (XEXP (op0, 1)),
                                         MODE_INT, 1)) != BLKmode
-             && ((unsigned HOST_WIDE_INT) const_op <= GET_MODE_MASK (tmode)
-                 || ((unsigned HOST_WIDE_INT) -const_op
-                     <= GET_MODE_MASK (tmode))))
+             && (((unsigned HOST_WIDE_INT) const_op
+                  + (GET_MODE_MASK (tmode) >> 1) + 1)
+                 <= GET_MODE_MASK (tmode)))
            {
              op0 = gen_lowpart_for_combine (tmode, XEXP (XEXP (op0, 0), 0));
              continue;
@@ -10854,9 +10917,9 @@ simplify_comparison (code, pop0, pop1)
              && XEXP (op0, 1) == XEXP (XEXP (XEXP (op0, 0), 0), 1)
              && (tmode = mode_for_size (mode_width - INTVAL (XEXP (op0, 1)),
                                         MODE_INT, 1)) != BLKmode
-             && ((unsigned HOST_WIDE_INT) const_op <= GET_MODE_MASK (tmode)
-                 || ((unsigned HOST_WIDE_INT) -const_op
-                     <= GET_MODE_MASK (tmode))))
+             && (((unsigned HOST_WIDE_INT) const_op
+                  + (GET_MODE_MASK (tmode) >> 1) + 1)
+                 <= GET_MODE_MASK (tmode)))
            {
              rtx inner = XEXP (XEXP (XEXP (op0, 0), 0), 0);
              rtx add_const = XEXP (XEXP (op0, 0), 1);
@@ -10881,9 +10944,12 @@ simplify_comparison (code, pop0, pop1)
              && mode_width <= HOST_BITS_PER_WIDE_INT
              && (nonzero_bits (XEXP (op0, 0), mode)
                  & (((HOST_WIDE_INT) 1 << INTVAL (XEXP (op0, 1))) - 1)) == 0
-             && (const_op == 0
-                 || (floor_log2 (const_op) + INTVAL (XEXP (op0, 1))
-                     < mode_width)))
+             && (((unsigned HOST_WIDE_INT) const_op
+                  + (GET_CODE (op0) != LSHIFTRT
+                     ? ((GET_MODE_MASK (mode) >> INTVAL (XEXP (op0, 1)) >> 1)
+                        + 1)
+                     : 0))
+                 <= GET_MODE_MASK (mode) >> INTVAL (XEXP (op0, 1))))
            {
              /* If the shift was logical, then we must make the condition
                 unsigned.  */
@@ -10918,38 +10984,56 @@ simplify_comparison (code, pop0, pop1)
 
   /* Now make any compound operations involved in this comparison.  Then,
      check for an outmost SUBREG on OP0 that is not doing anything or is
-     paradoxical.  The latter case can only occur when it is known that the
-     "extra" bits will be zero.  Therefore, it is safe to remove the SUBREG.
-     We can never remove a SUBREG for a non-equality comparison because the
-     sign bit is in a different place in the underlying object.  */
+     paradoxical.  The latter transformation must only be performed when
+     it is known that the "extra" bits will be the same in op0 and op1 or
+     that they don't matter.  There are three cases to consider:
+
+     1. SUBREG_REG (op0) is a register.  In this case the bits are don't
+     care bits and we can assume they have any convenient value.  So
+     making the transformation is safe.
+
+     2. SUBREG_REG (op0) is a memory and LOAD_EXTEND_OP is not defined.
+     In this case the upper bits of op0 are undefined.  We should not make
+     the simplification in that case as we do not know the contents of
+     those bits.
+
+     3. SUBREG_REG (op0) is a memory and LOAD_EXTEND_OP is defined and not
+     NIL.  In that case we know those bits are zeros or ones.  We must
+     also be sure that they are the same as the upper bits of op1.
+
+     We can never remove a SUBREG for a non-equality comparison because
+     the sign bit is in a different place in the underlying object.  */
 
   op0 = make_compound_operation (op0, op1 == const0_rtx ? COMPARE : SET);
   op1 = make_compound_operation (op1, SET);
 
   if (GET_CODE (op0) == SUBREG && subreg_lowpart_p (op0)
+      /* Case 3 above, to sometimes allow (subreg (mem x)), isn't
+        implemented.  */
+      && GET_CODE (SUBREG_REG (op0)) == REG
       && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT
       && GET_MODE_CLASS (GET_MODE (SUBREG_REG (op0))) == MODE_INT
-      && (code == NE || code == EQ)
-      && ((GET_MODE_SIZE (GET_MODE (op0))
-          > GET_MODE_SIZE (GET_MODE (SUBREG_REG (op0))))))
+      && (code == NE || code == EQ))
     {
-      op0 = SUBREG_REG (op0);
-      op1 = gen_lowpart_for_combine (GET_MODE (op0), op1);
-    }
+      if (GET_MODE_SIZE (GET_MODE (op0))
+         > GET_MODE_SIZE (GET_MODE (SUBREG_REG (op0))))
+       {
+         op0 = SUBREG_REG (op0);
+         op1 = gen_lowpart_for_combine (GET_MODE (op0), op1);
+       }
+      else if ((GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op0)))
+               <= HOST_BITS_PER_WIDE_INT)
+              && (nonzero_bits (SUBREG_REG (op0),
+                                GET_MODE (SUBREG_REG (op0)))
+                  & ~GET_MODE_MASK (GET_MODE (op0))) == 0)
+       {
+         tem = gen_lowpart_for_combine (GET_MODE (SUBREG_REG (op0)), op1);
 
-  else if (GET_CODE (op0) == SUBREG && subreg_lowpart_p (op0)
-          && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT
-          && GET_MODE_CLASS (GET_MODE (SUBREG_REG (op0))) == MODE_INT
-          && (code == NE || code == EQ)
-          && (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op0)))
-              <= HOST_BITS_PER_WIDE_INT)
-          && (nonzero_bits (SUBREG_REG (op0), GET_MODE (SUBREG_REG (op0)))
-              & ~GET_MODE_MASK (GET_MODE (op0))) == 0
-          && (tem = gen_lowpart_for_combine (GET_MODE (SUBREG_REG (op0)),
-                                             op1),
-              (nonzero_bits (tem, GET_MODE (SUBREG_REG (op0)))
-               & ~GET_MODE_MASK (GET_MODE (op0))) == 0))
-    op0 = SUBREG_REG (op0), op1 = tem;
+         if ((nonzero_bits (tem, GET_MODE (SUBREG_REG (op0)))
+              & ~GET_MODE_MASK (GET_MODE (op0))) == 0)
+           op0 = SUBREG_REG (op0), op1 = tem;
+       }
+    }
 
   /* We now do the opposite procedure: Some machines don't have compare
      insns in all modes.  If OP0's mode is an integer mode smaller than a
@@ -10967,14 +11051,22 @@ simplify_comparison (code, pop0, pop1)
         tmode = GET_MODE_WIDER_MODE (tmode))
       if (have_insn_for (COMPARE, tmode))
        {
+         int zero_extended;
+
          /* If the only nonzero bits in OP0 and OP1 are those in the
             narrower mode and this is an equality or unsigned comparison,
             we can use the wider mode.  Similarly for sign-extended
             values, in which case it is true for all comparisons.  */
-         if (((code == EQ || code == NE
-               || code == GEU || code == GTU || code == LEU || code == LTU)
-              && (nonzero_bits (op0, tmode) & ~GET_MODE_MASK (mode)) == 0
-              && (nonzero_bits (op1, tmode) & ~GET_MODE_MASK (mode)) == 0)
+         zero_extended = ((code == EQ || code == NE
+                           || code == GEU || code == GTU
+                           || code == LEU || code == LTU)
+                          && (nonzero_bits (op0, tmode)
+                              & ~GET_MODE_MASK (mode)) == 0
+                          && ((GET_CODE (op1) == CONST_INT
+                               || (nonzero_bits (op1, tmode)
+                                   & ~GET_MODE_MASK (mode)) == 0)));
+
+         if (zero_extended
              || ((num_sign_bit_copies (op0, tmode)
                   > GET_MODE_BITSIZE (tmode) - GET_MODE_BITSIZE (mode))
                  && (num_sign_bit_copies (op1, tmode)
@@ -10991,6 +11083,8 @@ simplify_comparison (code, pop0, pop1)
                                                           XEXP (op0, 1)));
 
              op0 = gen_lowpart_for_combine (tmode, op0);
+             if (zero_extended && GET_CODE (op1) == CONST_INT)
+               op1 = GEN_INT (INTVAL (op1) & GET_MODE_MASK (mode));
              op1 = gen_lowpart_for_combine (tmode, op1);
              break;
            }
@@ -11188,9 +11282,13 @@ record_value_for_reg (reg, insn, value)
 
   if (value)
     {
+      enum machine_mode mode = GET_MODE (reg);
       subst_low_cuid = INSN_CUID (insn);
-      reg_last_set_mode[regno] = GET_MODE (reg);
-      reg_last_set_nonzero_bits[regno] = nonzero_bits (value, GET_MODE (reg));
+      reg_last_set_mode[regno] = mode;
+      if (GET_MODE_CLASS (mode) == MODE_INT
+         && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
+       mode = nonzero_bits_mode;
+      reg_last_set_nonzero_bits[regno] = nonzero_bits (value, mode);
       reg_last_set_sign_bit_copies[regno]
        = num_sign_bit_copies (value, GET_MODE (reg));
     }
@@ -11413,7 +11511,7 @@ get_last_value_validate (loc, insn, tick, replace)
            || (! (regno >= FIRST_PSEUDO_REGISTER
                   && REG_N_SETS (regno) == 1
                   && (! REGNO_REG_SET_P
-                      (BASIC_BLOCK (0)->global_live_at_start, regno)))
+                      (ENTRY_BLOCK_PTR->next_bb->global_live_at_start, regno)))
                && reg_last_set_label[j] > tick))
          {
            if (replace)
@@ -11487,7 +11585,7 @@ get_last_value (x)
          && (regno < FIRST_PSEUDO_REGISTER
              || REG_N_SETS (regno) != 1
              || (REGNO_REG_SET_P
-                 (BASIC_BLOCK (0)->global_live_at_start, regno)))))
+                 (ENTRY_BLOCK_PTR->next_bb->global_live_at_start, regno)))))
     return 0;
 
   /* If the value was set in a later insn than the ones we are processing,
@@ -11606,7 +11704,7 @@ reg_dead_at_p (reg, insn)
      rtx reg;
      rtx insn;
 {
-  int block;
+  basic_block block;
   unsigned int i;
 
   /* Set variables for reg_dead_at_p_1.  */
@@ -11639,21 +11737,21 @@ reg_dead_at_p (reg, insn)
        return 1;
     }
 
-  /* Get the basic block number that we were in.  */
+  /* Get the basic block that we were in.  */
   if (insn == 0)
-    block = 0;
+    block = ENTRY_BLOCK_PTR->next_bb;
   else
     {
-      for (block = 0; block < n_basic_blocks; block++)
-       if (insn == BLOCK_HEAD (block))
+      FOR_EACH_BB (block)
+       if (insn == block->head)
          break;
 
-      if (block == n_basic_blocks)
+      if (block == EXIT_BLOCK_PTR)
        return 0;
     }
 
   for (i = reg_dead_regno; i < reg_dead_endregno; i++)
-    if (REGNO_REG_SET_P (BASIC_BLOCK (block)->global_live_at_start, i))
+    if (REGNO_REG_SET_P (block->global_live_at_start, i))
       return 0;
 
   return 1;
@@ -11860,7 +11958,7 @@ move_deaths (x, maybe_kill_insn, from_cuid, to_insn, pnotes)
                if (i < regno || i >= ourend)
                  REG_NOTES (where_dead)
                    = gen_rtx_EXPR_LIST (REG_DEAD,
-                                        gen_rtx_REG (reg_raw_mode[i], i),
+                                        regno_reg_rtx[i],
                                         REG_NOTES (where_dead));
            }
 
@@ -11887,7 +11985,7 @@ move_deaths (x, maybe_kill_insn, from_cuid, to_insn, pnotes)
                offset = 1;
 
              for (i = regno + offset; i < ourend; i++)
-               move_deaths (gen_rtx_REG (reg_raw_mode[i], i),
+               move_deaths (regno_reg_rtx[i],
                             maybe_kill_insn, from_cuid, to_insn, &oldnotes);
            }
 
@@ -12296,7 +12394,7 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
 
          if (place == 0)
            {
-             basic_block bb = BASIC_BLOCK (this_basic_block);
+             basic_block bb = this_basic_block;
 
              for (tem = PREV_INSN (i3); place == 0; tem = PREV_INSN (tem))
                {
@@ -12440,7 +12538,7 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
                  && REGNO_REG_SET_P (bb->global_live_at_start,
                                      REGNO (XEXP (note, 0))))
                {
-                 SET_BIT (refresh_blocks, this_basic_block);
+                 SET_BIT (refresh_blocks, this_basic_block->index);
                  need_refresh = 1;
                }
            }
@@ -12460,7 +12558,7 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
                 after we remove them in delete_noop_moves.  */
              if (noop_move_p (place))
                {
-                 SET_BIT (refresh_blocks, this_basic_block);
+                 SET_BIT (refresh_blocks, this_basic_block->index);
                  need_refresh = 1;
                }
 
@@ -12509,8 +12607,8 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
                      for (i = regno; i < endregno;
                           i += HARD_REGNO_NREGS (i, reg_raw_mode[i]))
                        {
-                         rtx piece = gen_rtx_REG (reg_raw_mode[i], i);
-                         basic_block bb = BASIC_BLOCK (this_basic_block);
+                         rtx piece = regno_reg_rtx[i];
+                         basic_block bb = this_basic_block;
 
                          if (! dead_or_set_p (place, piece)
                              && ! reg_bitfield_target_p (piece,
@@ -12533,7 +12631,7 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
                                    if (tem == bb->head)
                                      {
                                        SET_BIT (refresh_blocks,
-                                                this_basic_block);
+                                                this_basic_block->index);
                                        need_refresh = 1;
                                        break;
                                      }
@@ -12638,8 +12736,8 @@ distribute_links (links)
         since most links don't point very far away.  */
 
       for (insn = NEXT_INSN (XEXP (link, 0));
-          (insn && (this_basic_block == n_basic_blocks - 1
-                    || BLOCK_HEAD (this_basic_block + 1) != insn));
+          (insn && (this_basic_block->next_bb == EXIT_BLOCK_PTR
+                    || this_basic_block->next_bb->head != insn));
           insn = NEXT_INSN (insn))
        if (INSN_P (insn) && reg_overlap_mentioned_p (reg, PATTERN (insn)))
          {