OSDN Git Service

Fix misapplied patch.
[pf3gnuchains/gcc-fork.git] / gcc / combine.c
index 6b507c2..129cd4d 100644 (file)
@@ -321,7 +321,7 @@ static rtx *uid_log_links;
 
 static int label_tick;
 
-/* Reset to label_tick for each label.  */
+/* Reset to label_tick for each extended basic block in scanning order.  */
 
 static int label_tick_ebb_start;
 
@@ -1010,9 +1010,6 @@ clear_log_links (void)
     if (INSN_P (insn))
       free_INSN_LIST_list (&LOG_LINKS (insn));
 }
-
-
-
 \f
 /* Main entry point for combiner.  F is the first insn of the function.
    NREGS is the first unused pseudo-reg number.
@@ -1028,6 +1025,7 @@ combine_instructions (rtx f, unsigned int nregs)
 #endif
   rtx links, nextlinks;
   rtx first;
+  basic_block last_bb;
 
   int new_direct_jump_p = 0;
 
@@ -1058,6 +1056,7 @@ combine_instructions (rtx f, unsigned int nregs)
      problems when, for example, we have j <<= 1 in a loop.  */
 
   nonzero_sign_valid = 0;
+  label_tick = label_tick_ebb_start = 1;
 
   /* Scan all SETs and see if we can deduce anything about what
      bits are known to be zero for some registers and how many copies
@@ -1067,18 +1066,23 @@ combine_instructions (rtx f, unsigned int nregs)
      for what bits are known to be set.  */
 
   setup_incoming_promotions (first);
+  /* Allow the entry block and the first block to fall into the same EBB.
+     Conceptually the incoming promotions are assigned to the entry block.  */
+  last_bb = ENTRY_BLOCK_PTR;
 
   create_log_links ();
-  label_tick_ebb_start = ENTRY_BLOCK_PTR->index;
   FOR_EACH_BB (this_basic_block)
     {
       optimize_this_for_speed_p = optimize_bb_for_speed_p (this_basic_block);
       last_call_luid = 0;
       mem_last_set = -1;
-      label_tick = this_basic_block->index;
+
+      label_tick++;
       if (!single_pred_p (this_basic_block)
-         || single_pred (this_basic_block)->index != label_tick - 1)
+         || single_pred (this_basic_block) != last_bb)
        label_tick_ebb_start = label_tick;
+      last_bb = this_basic_block;
+
       FOR_BB_INSNS (this_basic_block, insn)
         if (INSN_P (insn) && BLOCK_FOR_INSN (insn))
          {
@@ -1109,20 +1113,23 @@ combine_instructions (rtx f, unsigned int nregs)
   nonzero_sign_valid = 1;
 
   /* Now scan all the insns in forward order.  */
-
-  label_tick_ebb_start = ENTRY_BLOCK_PTR->index;
+  label_tick = label_tick_ebb_start = 1;
   init_reg_last ();
   setup_incoming_promotions (first);
+  last_bb = ENTRY_BLOCK_PTR;
 
   FOR_EACH_BB (this_basic_block)
     {
       optimize_this_for_speed_p = optimize_bb_for_speed_p (this_basic_block);
       last_call_luid = 0;
       mem_last_set = -1;
-      label_tick = this_basic_block->index;
+
+      label_tick++;
       if (!single_pred_p (this_basic_block)
-         || single_pred (this_basic_block)->index != label_tick - 1)
+         || single_pred (this_basic_block) != last_bb)
        label_tick_ebb_start = label_tick;
+      last_bb = this_basic_block;
+
       rtl_profile_for_bb (this_basic_block);
       for (insn = BB_HEAD (this_basic_block);
           insn != NEXT_INSN (BB_END (this_basic_block));
@@ -2257,68 +2264,33 @@ cleanup_auto_inc_dec (rtx src, bool after, enum machine_mode mem_mode)
 
   return x;
 }
-#endif
 
 /* Auxiliary data structure for propagate_for_debug_stmt.  */
 
 struct rtx_subst_pair
 {
-  rtx from, to;
-  bool changed;
-#ifdef AUTO_INC_DEC
+  rtx to;
   bool adjusted;
   bool after;
-#endif
 };
 
-/* Clean up any auto-updates in PAIR->to the first time it is called
-   for a PAIR.  PAIR->adjusted is used to tell whether we've cleaned
-   up before.  */
+/* DATA points to an rtx_subst_pair.  Return the value that should be
+   substituted.  */
 
-static void
-auto_adjust_pair (struct rtx_subst_pair *pair ATTRIBUTE_UNUSED)
+static rtx
+propagate_for_debug_subst (rtx from ATTRIBUTE_UNUSED, void *data)
 {
-#ifdef AUTO_INC_DEC
+  struct rtx_subst_pair *pair = (struct rtx_subst_pair *)data;
+
   if (!pair->adjusted)
     {
       pair->adjusted = true;
       pair->to = cleanup_auto_inc_dec (pair->to, pair->after, VOIDmode);
+      return pair->to;
     }
-#endif
-}
-
-/* If *LOC is the same as FROM in the struct rtx_subst_pair passed as
-   DATA, replace it with a copy of TO.  Handle SUBREGs of *LOC as
-   well.  */
-
-static int
-propagate_for_debug_subst (rtx *loc, void *data)
-{
-  struct rtx_subst_pair *pair = (struct rtx_subst_pair *)data;
-  rtx from = pair->from, to = pair->to;
-  rtx x = *loc, s = x;
-
-  if (rtx_equal_p (x, from)
-      || (GET_CODE (x) == SUBREG && rtx_equal_p ((s = SUBREG_REG (x)), from)))
-    {
-      auto_adjust_pair (pair);
-      if (pair->to != to)
-       to = pair->to;
-      else
-       to = copy_rtx (to);
-      if (s != x)
-       {
-         gcc_assert (GET_CODE (x) == SUBREG && SUBREG_REG (x) == s);
-         to = simplify_gen_subreg (GET_MODE (x), to,
-                                   GET_MODE (from), SUBREG_BYTE (x));
-       }
-      *loc = wrap_constant (GET_MODE (x), to);
-      pair->changed = true;
-      return -1;
-    }
-
-  return 0;
+  return copy_rtx (pair->to);
 }
+#endif
 
 /* Replace occurrences of DEST with SRC in DEBUG_INSNs between INSN
    and LAST.  If MOVE holds, debug insns must also be moved past
@@ -2327,14 +2299,11 @@ propagate_for_debug_subst (rtx *loc, void *data)
 static void
 propagate_for_debug (rtx insn, rtx last, rtx dest, rtx src, bool move)
 {
-  struct rtx_subst_pair p;
-  rtx next, move_pos = move ? last : NULL_RTX;
-
-  p.from = dest;
-  p.to = src;
-  p.changed = false;
+  rtx next, move_pos = move ? last : NULL_RTX, loc;
 
 #ifdef AUTO_INC_DEC
+  struct rtx_subst_pair p;
+  p.to = src;
   p.adjusted = false;
   p.after = move;
 #endif
@@ -2346,11 +2315,15 @@ propagate_for_debug (rtx insn, rtx last, rtx dest, rtx src, bool move)
       next = NEXT_INSN (insn);
       if (DEBUG_INSN_P (insn))
        {
-         for_each_rtx (&INSN_VAR_LOCATION_LOC (insn),
-                       propagate_for_debug_subst, &p);
-         if (!p.changed)
+#ifdef AUTO_INC_DEC
+         loc = simplify_replace_fn_rtx (INSN_VAR_LOCATION_LOC (insn),
+                                        dest, propagate_for_debug_subst, &p);
+#else
+         loc = simplify_replace_rtx (INSN_VAR_LOCATION_LOC (insn), dest, src);
+#endif
+         if (loc == INSN_VAR_LOCATION_LOC (insn))
            continue;
-         p.changed = false;
+         INSN_VAR_LOCATION_LOC (insn) = loc;
          if (move_pos)
            {
              remove_insn (insn);
@@ -2363,7 +2336,7 @@ propagate_for_debug (rtx insn, rtx last, rtx dest, rtx src, bool move)
     }
 }
 
-/* Delete the conditional jump INSN and adjust the CFG correspondingly.
+/* Delete the unconditional jump INSN and adjust the CFG correspondingly.
    Note that the INSN should be deleted *after* removing dead edges, so
    that the kept edge is the fallthrough edge for a (set (pc) (pc))
    but not for a (set (pc) (label_ref FOO)).  */
@@ -2372,12 +2345,13 @@ static void
 update_cfg_for_uncondjump (rtx insn)
 {
   basic_block bb = BLOCK_FOR_INSN (insn);
+  bool at_end = (BB_END (bb) == insn);
 
-  if (BB_END (bb) == insn)
+  if (at_end)
     purge_dead_edges (bb);
 
   delete_insn (insn);
-  if (EDGE_COUNT (bb->succs) == 1)
+  if (at_end && EDGE_COUNT (bb->succs) == 1)
     single_succ_edge (bb)->flags |= EDGE_FALLTHRU;
 }
 
@@ -8810,6 +8784,12 @@ distribute_and_simplify_rtx (rtx x, int n)
   enum rtx_code outer_code, inner_code;
   rtx decomposed, distributed, inner_op0, inner_op1, new_op0, new_op1, tmp;
 
+  /* Distributivity is not true for floating point as it can change the
+     value.  So we don't do it unless -funsafe-math-optimizations.  */
+  if (FLOAT_MODE_P (GET_MODE (x))
+      && ! flag_unsafe_math_optimizations)
+    return NULL_RTX;
+
   decomposed = XEXP (x, n);
   if (!ARITHMETIC_P (decomposed))
     return NULL_RTX;
@@ -11751,12 +11731,10 @@ record_value_for_reg (rtx reg, rtx insn, rtx value)
      case, we must replace it with (clobber (const_int 0)) to prevent
      infinite loops.  */
   rsp = VEC_index (reg_stat_type, reg_stat, regno);
-  if (value && ! get_last_value_validate (&value, insn,
-                                         rsp->last_set_label, 0))
+  if (value && !get_last_value_validate (&value, insn, label_tick, 0))
     {
       value = copy_rtx (value);
-      if (! get_last_value_validate (&value, insn,
-                                    rsp->last_set_label, 1))
+      if (!get_last_value_validate (&value, insn, label_tick, 1))
        value = 0;
     }
 
@@ -12048,15 +12026,14 @@ check_promoted_subreg (rtx insn, rtx x)
     }
 }
 \f
-/* Utility routine for the following function.  Verify that all the registers
-   mentioned in *LOC are valid when *LOC was part of a value set when
-   label_tick == TICK.  Return 0 if some are not.
-
-   If REPLACE is nonzero, replace the invalid reference with
-   (clobber (const_int 0)) and return 1.  This replacement is useful because
-   we often can get useful information about the form of a value (e.g., if
-   it was produced by a shift that always produces -1 or 0) even though
-   we don't know exactly what registers it was produced from.  */
+/* Verify that all the registers and memory references mentioned in *LOC are
+   still valid.  *LOC was part of a value set in INSN when label_tick was
+   equal to TICK.  Return 0 if some are not.  If REPLACE is nonzero, replace
+   the invalid references with (clobber (const_int 0)) and return 1.  This
+   replacement is useful because we often can get useful information about
+   the form of a value (e.g., if it was produced by a shift that always
+   produces -1 or 0) even though we don't know exactly what registers it
+   was produced from.  */
 
 static int
 get_last_value_validate (rtx *loc, rtx insn, int tick, int replace)
@@ -12092,11 +12069,12 @@ get_last_value_validate (rtx *loc, rtx insn, int tick, int replace)
 
       return 1;
     }
-  /* If this is a memory reference, make sure that there were
-     no stores after it that might have clobbered the value.  We don't
-     have alias info, so we assume any store invalidates it.  */
+  /* If this is a memory reference, make sure that there were no stores after
+     it that might have clobbered the value.  We don't have alias info, so we
+     assume any store invalidates it.  Moreover, we only have local UIDs, so
+     we also assume that there were stores in the intervening basic blocks.  */
   else if (MEM_P (x) && !MEM_READONLY_P (x)
-          && DF_INSN_LUID (insn) <= mem_last_set)
+          && (tick != label_tick || DF_INSN_LUID (insn) <= mem_last_set))
     {
       if (replace)
        *loc = gen_rtx_CLOBBER (GET_MODE (x), const0_rtx);
@@ -12206,16 +12184,14 @@ get_last_value (const_rtx x)
     return 0;
 
   /* If the value has all its registers valid, return it.  */
-  if (get_last_value_validate (&value, rsp->last_set,
-                              rsp->last_set_label, 0))
+  if (get_last_value_validate (&value, rsp->last_set, rsp->last_set_label, 0))
     return value;
 
   /* Otherwise, make a copy and replace any invalid register with
      (clobber (const_int 0)).  If that fails for some reason, return 0.  */
 
   value = copy_rtx (value);
-  if (get_last_value_validate (&value, rsp->last_set,
-                              rsp->last_set_label, 1))
+  if (get_last_value_validate (&value, rsp->last_set, rsp->last_set_label, 1))
     return value;
 
   return 0;