OSDN Git Service

* config/xtensa/lib1funcs.asm (__udivsi3, __divsi3): Rearrange special
[pf3gnuchains/gcc-fork.git] / gcc / ifcvt.c
index b2275d0..8367316 100644 (file)
@@ -1,5 +1,6 @@
 /* If-conversion support.
-   Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005
+   Free Software Foundation, Inc.
 
    This file is part of GCC.
 
@@ -65,7 +66,6 @@
 #define MAX_CONDITIONAL_EXECUTE   (BRANCH_COST + 1)
 #endif
 
-#define NULL_EDGE      ((edge) NULL)
 #define NULL_BLOCK     ((basic_block) NULL)
 
 /* # of IF-THEN or IF-THEN-ELSE blocks we looked at  */
@@ -86,7 +86,7 @@ static bool life_data_ok;
 
 /* Forward references.  */
 static int count_bb_insns (basic_block);
-static int total_bb_rtx_cost (basic_block);
+static bool cheap_bb_rtx_cost_p (basic_block, int);
 static rtx first_active_insn (basic_block);
 static rtx last_active_insn (basic_block, int);
 static basic_block block_fallthru (basic_block);
@@ -109,38 +109,7 @@ static int dead_or_predicable (basic_block, basic_block, basic_block,
                               basic_block, int);
 static void noce_emit_move_insn (rtx, rtx);
 static rtx block_has_only_trap (basic_block);
-static void mark_loop_exit_edges (void);
 \f
-/* Sets EDGE_LOOP_EXIT flag for all loop exits.  */
-static void
-mark_loop_exit_edges (void)
-{
-  struct loops loops;
-  basic_block bb;
-  edge e;
-  
-  flow_loops_find (&loops, LOOP_TREE);
-  free_dominance_info (CDI_DOMINATORS);
-  
-  if (loops.num > 1)
-    {
-      FOR_EACH_BB (bb)
-       {
-         edge_iterator ei;
-         FOR_EACH_EDGE (e, ei, bb->succs)
-           {
-             if (find_common_loop (bb->loop_father, e->dest->loop_father)
-                 != bb->loop_father)
-               e->flags |= EDGE_LOOP_EXIT;
-             else
-               e->flags &= ~EDGE_LOOP_EXIT;
-           }
-       }
-    }
-
-  flow_loops_free (&loops);
-}
-
 /* Count the number of non-jump active insns in BB.  */
 
 static int
@@ -162,12 +131,12 @@ count_bb_insns (basic_block bb)
   return count;
 }
 
-/* Count the total insn_rtx_cost of non-jump active insns in BB.
-   This function returns -1, if the cost of any instruction could
-   not be estimated.  */
+/* Determine whether the total insn_rtx_cost on non-jump insns in
+   basic block BB is less than MAX_COST.  This function returns
+   false if the cost of any instruction could not be estimated.  */
 
-static int
-total_bb_rtx_cost (basic_block bb)
+static bool
+cheap_bb_rtx_cost_p (basic_block bb, int max_cost)
 {
   int count = 0;
   rtx insn = BB_HEAD (bb);
@@ -178,18 +147,34 @@ total_bb_rtx_cost (basic_block bb)
        {
          int cost = insn_rtx_cost (PATTERN (insn));
          if (cost == 0)
-           return -1;
+           return false;
+
+         /* If this instruction is the load or set of a "stack" register,
+            such as a floating point register on x87, then the cost of
+            speculatively executing this instruction needs to include
+            the additional cost of popping this register off of the
+            register stack.  */
+#ifdef STACK_REGS
+         {
+           rtx set = single_set (insn);
+           if (set && STACK_REG_P (SET_DEST (set)))
+             cost += COSTS_N_INSNS (1);
+         }
+#endif
+
          count += cost;
+         if (count >= max_cost)
+           return false;
        }
       else if (CALL_P (insn))
-       return -1;
+       return false;
  
       if (insn == BB_END (bb))
        break;
       insn = NEXT_INSN (insn);
     }
 
-  return count;
+  return true;
 }
 
 /* Return the first non-jump active insn in the basic block.  */
@@ -284,8 +269,7 @@ cond_exec_process_insns (ce_if_block_t *ce_info ATTRIBUTE_UNUSED,
       if (NOTE_P (insn))
        goto insn_done;
 
-      if (!NONJUMP_INSN_P (insn) && !CALL_P (insn))
-       abort ();
+      gcc_assert(NONJUMP_INSN_P (insn) || CALL_P (insn));
 
       /* Remove USE insns that get in the way.  */
       if (reload_completed && GET_CODE (PATTERN (insn)) == USE)
@@ -697,7 +681,7 @@ noce_emit_store_flag (struct noce_if_info *if_info, rtx x, int reversep,
 static void
 noce_emit_move_insn (rtx x, rtx y)
 {
-  enum machine_mode outmode, inmode;
+  enum machine_mode outmode;
   rtx outer, inner;
   int bitpos;
 
@@ -710,7 +694,6 @@ noce_emit_move_insn (rtx x, rtx y)
   outer = XEXP (x, 0);
   inner = XEXP (outer, 0);
   outmode = GET_MODE (outer);
-  inmode = GET_MODE (inner);
   bitpos = SUBREG_BYTE (outer) * BITS_PER_UNIT;
   store_bit_field (inner, GET_MODE_BITSIZE (outmode), bitpos, outmode, y);
 }
@@ -1212,6 +1195,7 @@ noce_try_cmove_arith (struct noce_if_info *if_info)
   rtx a = if_info->a;
   rtx b = if_info->b;
   rtx x = if_info->x;
+  rtx orig_a, orig_b;
   rtx insn_a, insn_b;
   rtx tmp, target;
   int is_mem = 0;
@@ -1287,6 +1271,9 @@ noce_try_cmove_arith (struct noce_if_info *if_info)
 
   start_sequence ();
 
+  orig_a = a;
+  orig_b = b;
+
   /* If either operand is complex, load it into a register first.
      The best way to do this is to copy the original insn.  In this
      way we preserve any clobbers etc that the insn may have had.
@@ -1318,7 +1305,7 @@ noce_try_cmove_arith (struct noce_if_info *if_info)
     }
   if (! general_operand (b, GET_MODE (b)))
     {
-      rtx set;
+      rtx set, last;
 
       if (no_new_pseudos)
        goto end_seq_and_fail;
@@ -1326,9 +1313,7 @@ noce_try_cmove_arith (struct noce_if_info *if_info)
       if (is_mem)
        {
           tmp = gen_reg_rtx (GET_MODE (b));
-         tmp = emit_insn (gen_rtx_SET (VOIDmode,
-                                       tmp,
-                                       b));
+         tmp = gen_rtx_SET (VOIDmode, tmp, b);
        }
       else if (! insn_b)
        goto end_seq_and_fail;
@@ -1338,8 +1323,22 @@ noce_try_cmove_arith (struct noce_if_info *if_info)
          tmp = copy_rtx (insn_b);
          set = single_set (tmp);
          SET_DEST (set) = b;
-         tmp = emit_insn (PATTERN (tmp));
+         tmp = PATTERN (tmp);
+       }
+
+      /* If insn to set up A clobbers any registers B depends on, try to
+        swap insn that sets up A with the one that sets up B.  If even
+        that doesn't help, punt.  */
+      last = get_last_insn ();
+      if (last && modified_in_p (orig_b, last))
+       {
+         tmp = emit_insn_before (tmp, get_insns ());
+         if (modified_in_p (orig_a, tmp))
+           goto end_seq_and_fail;
        }
+      else
+       tmp = emit_insn (tmp);
+
       if (recog_memoized (tmp) < 0)
        goto end_seq_and_fail;
     }
@@ -2228,30 +2227,21 @@ merge_if_block (struct ce_if_block * ce_info)
       /* The outgoing edge for the current COMBO block should already
         be correct.  Verify this.  */
       if (EDGE_COUNT (combo_bb->succs) == 0)
-       {
-         if (find_reg_note (last, REG_NORETURN, NULL))
-           ;
-         else if (NONJUMP_INSN_P (last)
-                  && GET_CODE (PATTERN (last)) == TRAP_IF
-                  && TRAP_CONDITION (PATTERN (last)) == const_true_rtx)
-           ;
-         else
-           abort ();
-       }
+       gcc_assert (find_reg_note (last, REG_NORETURN, NULL)
+                   || (NONJUMP_INSN_P (last)
+                       && GET_CODE (PATTERN (last)) == TRAP_IF
+                       && (TRAP_CONDITION (PATTERN (last))
+                           == const_true_rtx)));
 
+      else
       /* There should still be something at the end of the THEN or ELSE
          blocks taking us to our final destination.  */
-      else if (JUMP_P (last))
-       ;
-      else if (EDGE_SUCC (combo_bb, 0)->dest == EXIT_BLOCK_PTR
-              && CALL_P (last)
-              && SIBLING_CALL_P (last))
-       ;
-      else if ((EDGE_SUCC (combo_bb, 0)->flags & EDGE_EH)
-              && can_throw_internal (last))
-       ;
-      else
-       abort ();
+       gcc_assert (JUMP_P (last)
+                   || (EDGE_SUCC (combo_bb, 0)->dest == EXIT_BLOCK_PTR
+                       && CALL_P (last)
+                       && SIBLING_CALL_P (last))
+                   || ((EDGE_SUCC (combo_bb, 0)->flags & EDGE_EH)
+                       && can_throw_internal (last)));
     }
 
   /* The JOIN block may have had quite a number of other predecessors too.
@@ -2259,7 +2249,7 @@ merge_if_block (struct ce_if_block * ce_info)
      have only one remaining edge from our if-then-else diamond.  If there
      is more than one remaining edge, it must come from elsewhere.  There
      may be zero incoming edges if the THEN block didn't actually join
-     back up (as with a call to abort).  */
+     back up (as with a call to a non-return function).  */
   else if (EDGE_COUNT (join_bb->preds) < 2
           && join_bb != EXIT_BLOCK_PTR)
     {
@@ -2277,13 +2267,12 @@ merge_if_block (struct ce_if_block * ce_info)
 
       /* The outgoing edge for the current COMBO block should already
         be correct.  Verify this.  */
-      if (EDGE_COUNT (combo_bb->succs) > 1
-         || EDGE_SUCC (combo_bb, 0)->dest != join_bb)
-       abort ();
+      gcc_assert (single_succ_p (combo_bb)
+                 && single_succ (combo_bb) == join_bb);
 
       /* Remove the jump and cruft from the end of the COMBO block.  */
       if (join_bb != EXIT_BLOCK_PTR)
-       tidy_fallthru_edge (EDGE_SUCC (combo_bb, 0));
+       tidy_fallthru_edge (single_succ_edge (combo_bb));
     }
 
   num_updated_if_blocks++;
@@ -2455,10 +2444,10 @@ find_if_block (struct ce_if_block * ce_info)
      were && tests (which jump to the else block) or || tests (which jump to
      the then block).  */
   if (HAVE_conditional_execution && reload_completed
-      && EDGE_COUNT (test_bb->preds) == 1
-      && EDGE_PRED (test_bb, 0)->flags == EDGE_FALLTHRU)
+      && single_pred_p (test_bb)
+      && single_pred_edge (test_bb)->flags == EDGE_FALLTHRU)
     {
-      basic_block bb = EDGE_PRED (test_bb, 0)->src;
+      basic_block bb = single_pred (test_bb);
       basic_block target_bb;
       int max_insns = MAX_CONDITIONAL_EXECUTE;
       int n_insns;
@@ -2491,10 +2480,10 @@ find_if_block (struct ce_if_block * ce_info)
              total_insns += n_insns;
              blocks++;
 
-             if (EDGE_COUNT (bb->preds) != 1)
+             if (!single_pred_p (bb))
                break;
 
-             bb = EDGE_PRED (bb, 0)->src;
+             bb = single_pred (bb);
              n_insns = block_jumps_and_fallthru_p (bb, target_bb);
            }
          while (n_insns >= 0 && (total_insns + n_insns) <= max_insns);
@@ -2529,8 +2518,8 @@ find_if_block (struct ce_if_block * ce_info)
 
   /* The THEN block of an IF-THEN combo must have zero or one successors.  */
   if (EDGE_COUNT (then_bb->succs) > 0
-      && (EDGE_COUNT (then_bb->succs) > 1
-          || (EDGE_SUCC (then_bb, 0)->flags & EDGE_COMPLEX)
+      && (!single_succ_p (then_bb)
+          || (single_succ_edge (then_bb)->flags & EDGE_COMPLEX)
          || (flow2_completed && tablejump_p (BB_END (then_bb), NULL, NULL))))
     return FALSE;
 
@@ -2542,7 +2531,7 @@ find_if_block (struct ce_if_block * ce_info)
      code processing.  ??? we should fix this in the future.  */
   if (EDGE_COUNT (then_bb->succs) == 0)
     {
-      if (EDGE_COUNT (else_bb->preds) == 1)
+      if (single_pred_p (else_bb))
        {
          rtx last_insn = BB_END (then_bb);
 
@@ -2565,7 +2554,7 @@ find_if_block (struct ce_if_block * ce_info)
 
   /* If the THEN block's successor is the other edge out of the TEST block,
      then we have an IF-THEN combo without an ELSE.  */
-  else if (EDGE_SUCC (then_bb, 0)->dest == else_bb)
+  else if (single_succ (then_bb) == else_bb)
     {
       join_bb = else_bb;
       else_bb = NULL_BLOCK;
@@ -2574,12 +2563,12 @@ find_if_block (struct ce_if_block * ce_info)
   /* If the THEN and ELSE block meet in a subsequent block, and the ELSE
      has exactly one predecessor and one successor, and the outgoing edge
      is not complex, then we have an IF-THEN-ELSE combo.  */
-  else if (EDGE_COUNT (else_bb->succs) == 1
-          && EDGE_SUCC (then_bb, 0)->dest == EDGE_SUCC (else_bb, 0)->dest
-          && EDGE_COUNT (else_bb->preds) == 1
-          && ! (EDGE_SUCC (else_bb, 0)->flags & EDGE_COMPLEX)
+  else if (single_succ_p (else_bb)
+          && single_succ (then_bb) == single_succ (else_bb)
+          && single_pred_p (else_bb)
+          && ! (single_succ_edge (else_bb)->flags & EDGE_COMPLEX)
           && ! (flow2_completed && tablejump_p (BB_END (else_bb), NULL, NULL)))
-    join_bb = EDGE_SUCC (else_bb, 0)->dest;
+    join_bb = single_succ (else_bb);
 
   /* Otherwise it is not an IF-THEN or IF-THEN-ELSE combination.  */
   else
@@ -2627,7 +2616,7 @@ find_if_block (struct ce_if_block * ce_info)
      we checked the FALLTHRU flag, those are already adjacent to the last IF
      block.  */
   /* ??? As an enhancement, move the ELSE block.  Have to deal with
-     BLOCK notes, if by no other means than aborting the merge if they
+     BLOCK notes, if by no other means than backing out the merge if they
      exist.  Sticky enough I don't want to think about it now.  */
   next = then_bb;
   if (else_bb && (next = next->next_bb) != else_bb)
@@ -2853,7 +2842,7 @@ find_if_case_1 (basic_block test_bb, edge then_edge, edge else_edge)
 {
   basic_block then_bb = then_edge->dest;
   basic_block else_bb = else_edge->dest, new_bb;
-  int then_bb_index, bb_cost;
+  int then_bb_index;
 
   /* If we are partitioning hot/cold basic blocks, we don't want to
      mess up unconditional or indirect jumps that cross between hot
@@ -2865,24 +2854,25 @@ find_if_case_1 (basic_block test_bb, edge then_edge, edge else_edge)
      partition boundaries).  See  the comments at the top of 
      bb-reorder.c:partition_hot_cold_basic_blocks for complete details.  */
 
-  if (flag_reorder_blocks_and_partition
-      && ((BB_END (then_bb) 
-          && find_reg_note (BB_END (then_bb), REG_CROSSING_JUMP, NULL_RTX))
-         || (BB_END (else_bb)
-             && find_reg_note (BB_END (else_bb), REG_CROSSING_JUMP, 
-                               NULL_RTX))))
+  if ((BB_END (then_bb) 
+       && find_reg_note (BB_END (then_bb), REG_CROSSING_JUMP, NULL_RTX))
+      || (BB_END (test_bb)
+         && find_reg_note (BB_END (test_bb), REG_CROSSING_JUMP, NULL_RTX))
+      || (BB_END (else_bb)
+         && find_reg_note (BB_END (else_bb), REG_CROSSING_JUMP, 
+                           NULL_RTX)))
     return FALSE;
 
   /* THEN has one successor.  */
-  if (EDGE_COUNT (then_bb->succs) != 1)
+  if (!single_succ_p (then_bb))
     return FALSE;
 
   /* THEN does not fall through, but is not strange either.  */
-  if (EDGE_SUCC (then_bb, 0)->flags & (EDGE_COMPLEX | EDGE_FALLTHRU))
+  if (single_succ_edge (then_bb)->flags & (EDGE_COMPLEX | EDGE_FALLTHRU))
     return FALSE;
 
   /* THEN has one predecessor.  */
-  if (EDGE_COUNT (then_bb->preds) != 1)
+  if (!single_pred_p (then_bb))
     return FALSE;
 
   /* THEN must do something.  */
@@ -2896,13 +2886,12 @@ find_if_case_1 (basic_block test_bb, edge then_edge, edge else_edge)
             test_bb->index, then_bb->index);
 
   /* THEN is small.  */
-  bb_cost = total_bb_rtx_cost (then_bb);
-  if (bb_cost < 0 || bb_cost >= COSTS_N_INSNS (BRANCH_COST))
+  if (! cheap_bb_rtx_cost_p (then_bb, COSTS_N_INSNS (BRANCH_COST)))
     return FALSE;
 
   /* Registers set are dead, or are predicable.  */
   if (! dead_or_predicable (test_bb, then_bb, else_bb,
-                           EDGE_SUCC (then_bb, 0)->dest, 1))
+                           single_succ (then_bb), 1))
     return FALSE;
 
   /* Conversion went ok, including moving the insns and fixing up the
@@ -2912,7 +2901,22 @@ find_if_case_1 (basic_block test_bb, edge then_edge, edge else_edge)
              else_bb->global_live_at_start,
              then_bb->global_live_at_end);
 
-  new_bb = redirect_edge_and_branch_force (FALLTHRU_EDGE (test_bb), else_bb);
+
+  /* We can avoid creating a new basic block if then_bb is immediately
+     followed by else_bb, i.e. deleting then_bb allows test_bb to fall
+     thru to else_bb.  */
+
+  if (then_bb->next_bb == else_bb
+      && then_bb->prev_bb == test_bb
+      && else_bb != EXIT_BLOCK_PTR)
+    {
+      redirect_edge_succ (FALLTHRU_EDGE (test_bb), else_bb);
+      new_bb = 0;
+    }
+  else
+    new_bb = redirect_edge_and_branch_force (FALLTHRU_EDGE (test_bb),
+                                             else_bb);
+
   then_bb_index = then_bb->index;
   delete_basic_block (then_bb);
 
@@ -2944,7 +2948,6 @@ find_if_case_2 (basic_block test_bb, edge then_edge, edge else_edge)
   basic_block then_bb = then_edge->dest;
   basic_block else_bb = else_edge->dest;
   edge else_succ;
-  int bb_cost;
   rtx note;
 
   /* If we are partitioning hot/cold basic blocks, we don't want to
@@ -2957,26 +2960,27 @@ find_if_case_2 (basic_block test_bb, edge then_edge, edge else_edge)
      partition boundaries).  See  the comments at the top of 
      bb-reorder.c:partition_hot_cold_basic_blocks for complete details.  */
 
-  if (flag_reorder_blocks_and_partition
-      && ((BB_END (then_bb)
-          && find_reg_note (BB_END (then_bb), REG_CROSSING_JUMP, NULL_RTX))
-         || (BB_END (else_bb) 
-             && find_reg_note (BB_END (else_bb), REG_CROSSING_JUMP, 
-                               NULL_RTX))))
+  if ((BB_END (then_bb)
+       && find_reg_note (BB_END (then_bb), REG_CROSSING_JUMP, NULL_RTX))
+      || (BB_END (test_bb)
+         && find_reg_note (BB_END (test_bb), REG_CROSSING_JUMP, NULL_RTX))
+      || (BB_END (else_bb) 
+         && find_reg_note (BB_END (else_bb), REG_CROSSING_JUMP, 
+                           NULL_RTX)))
     return FALSE;
 
   /* ELSE has one successor.  */
-  if (EDGE_COUNT (else_bb->succs) != 1)
+  if (!single_succ_p (else_bb))
     return FALSE;
   else
-    else_succ = EDGE_SUCC (else_bb, 0);
+    else_succ = single_succ_edge (else_bb);
 
   /* ELSE outgoing edge is not complex.  */
   if (else_succ->flags & EDGE_COMPLEX)
     return FALSE;
 
   /* ELSE has one predecessor.  */
-  if (EDGE_COUNT (else_bb->preds) != 1)
+  if (!single_pred_p (else_bb))
     return FALSE;
 
   /* THEN is not EXIT.  */
@@ -3001,8 +3005,7 @@ find_if_case_2 (basic_block test_bb, edge then_edge, edge else_edge)
             test_bb->index, else_bb->index);
 
   /* ELSE is small.  */
-  bb_cost = total_bb_rtx_cost (else_bb);
-  if (bb_cost < 0 || bb_cost >= COSTS_N_INSNS (BRANCH_COST))
+  if (! cheap_bb_rtx_cost_p (else_bb, COSTS_N_INSNS (BRANCH_COST)))
     return FALSE;
 
   /* Registers set are dead, or are predicable.  */
@@ -3124,7 +3127,6 @@ dead_or_predicable (basic_block test_bb, basic_block merge_bb,
         that any registers modified are dead at the branch site.  */
 
       rtx insn, cond, prev;
-      regset_head merge_set_head, tmp_head, test_live_head, test_set_head;
       regset merge_set, tmp, test_live, test_set;
       struct propagate_block_info *pbi;
       unsigned i, fail = 0;
@@ -3166,10 +3168,10 @@ dead_or_predicable (basic_block test_bb, basic_block merge_bb,
           TEST_SET  = set of registers set between EARLIEST and the
                       end of the block.  */
 
-      tmp = INITIALIZE_REG_SET (tmp_head);
-      merge_set = INITIALIZE_REG_SET (merge_set_head);
-      test_live = INITIALIZE_REG_SET (test_live_head);
-      test_set = INITIALIZE_REG_SET (test_set_head);
+      tmp = ALLOC_REG_SET (&reg_obstack);
+      merge_set = ALLOC_REG_SET (&reg_obstack);
+      test_live = ALLOC_REG_SET (&reg_obstack);
+      test_set = ALLOC_REG_SET (&reg_obstack);
 
       /* ??? bb->local_set is only valid during calculate_global_regs_live,
         so we must recompute usage for MERGE_BB.  Not so bad, I suppose,
@@ -3245,13 +3247,7 @@ dead_or_predicable (basic_block test_bb, basic_block merge_bb,
 
   if (other_bb != new_dest)
     {
-      if (old_dest)
-       LABEL_NUSES (old_dest) -= 1;
-      if (new_label)
-       LABEL_NUSES (new_label) += 1;
-      JUMP_LABEL (jump) = new_label;
-      if (reversep)
-       invert_br_probabilities (jump);
+      redirect_jump_2 (jump, old_dest, new_label, -1, reversep);
 
       redirect_edge_succ (BRANCH_EDGE (test_bb), new_dest);
       if (reversep)
@@ -3312,7 +3308,14 @@ if_convert (int x_life_data_ok)
   if ((! targetm.cannot_modify_jumps_p ())
       && (!flag_reorder_blocks_and_partition || !no_new_pseudos
          || !targetm.have_named_sections))
-    mark_loop_exit_edges ();
+    {
+      struct loops loops;
+
+      flow_loops_find (&loops);
+      mark_loop_exit_edges (&loops);
+      flow_loops_free (&loops);
+      free_dominance_info (CDI_DOMINATORS);
+    }
 
   /* Compute postdominators if we think we'll use them.  */
   if (HAVE_conditional_execution || life_data_ok)