OSDN Git Service

* tree-data-ref.c (dr_analyze_innermost): Add new argument.
[pf3gnuchains/gcc-fork.git] / gcc / ifcvt.c
index eee5cc7..0fcacb6 100644 (file)
@@ -1,5 +1,6 @@
 /* If-conversion support.
-   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010
+   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010,
+   2011
    Free Software Foundation, Inc.
 
    This file is part of GCC.
@@ -103,7 +104,7 @@ static int cond_exec_find_if_block (ce_if_block_t *);
 static int find_if_case_1 (basic_block, edge, edge);
 static int find_if_case_2 (basic_block, edge, edge);
 static int dead_or_predicable (basic_block, basic_block, basic_block,
-                              basic_block, int);
+                              edge, int);
 static void noce_emit_move_insn (rtx, rtx);
 static rtx block_has_only_trap (basic_block);
 \f
@@ -304,6 +305,10 @@ cond_exec_process_insns (ce_if_block_t *ce_info ATTRIBUTE_UNUSED,
 
   for (insn = start; ; insn = NEXT_INSN (insn))
     {
+      /* dwarf2out can't cope with conditional prologues.  */
+      if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_PROLOGUE_END)
+       return FALSE;
+
       if (NOTE_P (insn) || DEBUG_INSN_P (insn))
        goto insn_done;
 
@@ -476,7 +481,8 @@ cond_exec_process_if_block (ce_if_block_t * ce_info,
       /* Look for matching sequences at the head and tail of the two blocks,
         and limit the range of insns to be converted if possible.  */
       n_matching = flow_find_cross_jump (then_bb, else_bb,
-                                        &then_first_tail, &else_first_tail);
+                                        &then_first_tail, &else_first_tail,
+                                        NULL);
       if (then_first_tail == BB_HEAD (then_bb))
        then_start = then_end = NULL_RTX;
       if (else_first_tail == BB_HEAD (else_bb))
@@ -879,7 +885,7 @@ noce_emit_move_insn (rtx x, rtx y)
                }
 
              gcc_assert (start < (MEM_P (op) ? BITS_PER_UNIT : BITS_PER_WORD));
-             store_bit_field (op, size, start, GET_MODE (x), y);
+             store_bit_field (op, size, start, 0, 0, GET_MODE (x), y);
              return;
            }
 
@@ -933,7 +939,8 @@ noce_emit_move_insn (rtx x, rtx y)
   inner = XEXP (outer, 0);
   outmode = GET_MODE (outer);
   bitpos = SUBREG_BYTE (outer) * BITS_PER_UNIT;
-  store_bit_field (inner, GET_MODE_BITSIZE (outmode), bitpos, outmode, y);
+  store_bit_field (inner, GET_MODE_BITSIZE (outmode), bitpos,
+                  0, 0, outmode, y);
 }
 
 /* Return sequence of instructions generated by if conversion.  This
@@ -2119,7 +2126,7 @@ noce_try_sign_mask (struct noce_if_info *if_info)
      && (if_info->insn_b == NULL_RTX
         || BLOCK_FOR_INSN (if_info->insn_b) == if_info->test_bb));
   if (!(t_unconditional
-       || (rtx_cost (t, SET, optimize_bb_for_speed_p (if_info->test_bb))
+       || (set_src_cost (t, optimize_bb_for_speed_p (if_info->test_bb))
            < COSTS_N_INSNS (2))))
     return FALSE;
 
@@ -3789,6 +3796,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;
   basic_block new_bb;
+  rtx else_target = NULL_RTX;
   int then_bb_index;
 
   /* If we are partitioning hot/cold basic blocks, we don't want to
@@ -3838,9 +3846,16 @@ find_if_case_1 (basic_block test_bb, edge then_edge, edge else_edge)
                                    predictable_edge_p (then_edge)))))
     return FALSE;
 
+  if (else_bb == EXIT_BLOCK_PTR)
+    {
+      rtx jump = BB_END (else_edge->src);
+      gcc_assert (JUMP_P (jump));
+      else_target = JUMP_LABEL (jump);
+    }
+
   /* Registers set are dead, or are predicable.  */
   if (! dead_or_predicable (test_bb, then_bb, else_bb,
-                           single_succ (then_bb), 1))
+                           single_succ_edge (then_bb), 1))
     return FALSE;
 
   /* Conversion went ok, including moving the insns and fixing up the
@@ -3857,6 +3872,9 @@ find_if_case_1 (basic_block test_bb, edge then_edge, edge else_edge)
       redirect_edge_succ (FALLTHRU_EDGE (test_bb), else_bb);
       new_bb = 0;
     }
+  else if (else_bb == EXIT_BLOCK_PTR)
+    new_bb = force_nonfallthru_and_redirect (FALLTHRU_EDGE (test_bb),
+                                            else_bb, else_target);
   else
     new_bb = redirect_edge_and_branch_force (FALLTHRU_EDGE (test_bb),
                                             else_bb);
@@ -3955,7 +3973,7 @@ find_if_case_2 (basic_block test_bb, edge then_edge, edge else_edge)
     return FALSE;
 
   /* Registers set are dead, or are predicable.  */
-  if (! dead_or_predicable (test_bb, else_bb, then_bb, else_succ->dest, 0))
+  if (! dead_or_predicable (test_bb, else_bb, then_bb, else_succ, 0))
     return FALSE;
 
   /* Conversion went ok, including moving the insns and fixing up the
@@ -3978,18 +3996,21 @@ find_if_case_2 (basic_block test_bb, edge then_edge, edge else_edge)
    Return TRUE if successful.
 
    TEST_BB is the block containing the conditional branch.  MERGE_BB
-   is the block containing the code to manipulate.  NEW_DEST is the
-   label TEST_BB should be branching to after the conversion.
+   is the block containing the code to manipulate.  DEST_EDGE is an
+   edge representing a jump to the join block; after the conversion,
+   TEST_BB should be branching to its destination.
    REVERSEP is true if the sense of the branch should be reversed.  */
 
 static int
 dead_or_predicable (basic_block test_bb, basic_block merge_bb,
-                   basic_block other_bb, basic_block new_dest, int reversep)
+                   basic_block other_bb, edge dest_edge, int reversep)
 {
-  rtx head, end, jump, earliest = NULL_RTX, old_dest, new_label = NULL_RTX;
+  basic_block new_dest = dest_edge->dest;
+  rtx head, end, jump, earliest = NULL_RTX, old_dest;
   bitmap merge_set = NULL;
   /* Number of pending changes.  */
   int n_validated_changes = 0;
+  rtx new_dest_label = NULL_RTX;
 
   jump = BB_END (test_bb);
 
@@ -4127,10 +4148,16 @@ dead_or_predicable (basic_block test_bb, basic_block merge_bb,
   old_dest = JUMP_LABEL (jump);
   if (other_bb != new_dest)
     {
-      new_label = block_label (new_dest);
+      if (JUMP_P (BB_END (dest_edge->src)))
+       new_dest_label = JUMP_LABEL (BB_END (dest_edge->src));
+      else if (new_dest == EXIT_BLOCK_PTR)
+       new_dest_label = ret_rtx;
+      else
+       new_dest_label = block_label (new_dest);
+
       if (reversep
-         ? ! invert_jump_1 (jump, new_label)
-         : ! redirect_jump_1 (jump, new_label))
+         ? ! invert_jump_1 (jump, new_dest_label)
+         : ! redirect_jump_1 (jump, new_dest_label))
        goto cancel;
     }
 
@@ -4141,7 +4168,7 @@ dead_or_predicable (basic_block test_bb, basic_block merge_bb,
 
   if (other_bb != new_dest)
     {
-      redirect_jump_2 (jump, old_dest, new_label, 0, reversep);
+      redirect_jump_2 (jump, old_dest, new_dest_label, 0, reversep);
 
       redirect_edge_succ (BRANCH_EDGE (test_bb), new_dest);
       if (reversep)
@@ -4362,7 +4389,7 @@ struct rtl_opt_pass pass_rtl_ifcvt =
   0,                                    /* properties_destroyed */
   0,                                    /* todo_flags_start */
   TODO_df_finish | TODO_verify_rtl_sharing |
-  TODO_dump_func                        /* todo_flags_finish */
+  0                                     /* todo_flags_finish */
  }
 };
 
@@ -4399,7 +4426,6 @@ struct rtl_opt_pass pass_if_after_combine =
   0,                                    /* properties_destroyed */
   0,                                    /* todo_flags_start */
   TODO_df_finish | TODO_verify_rtl_sharing |
-  TODO_dump_func |
   TODO_ggc_collect                      /* todo_flags_finish */
  }
 };
@@ -4436,7 +4462,6 @@ struct rtl_opt_pass pass_if_after_reload =
   0,                                    /* properties_destroyed */
   0,                                    /* todo_flags_start */
   TODO_df_finish | TODO_verify_rtl_sharing |
-  TODO_dump_func |
   TODO_ggc_collect                      /* todo_flags_finish */
  }
 };