OSDN Git Service

* optabs.c, doc/c-tree.texi, doc/install.texi, doc/md.texi,
[pf3gnuchains/gcc-fork.git] / gcc / loop-unswitch.c
index a056841..f307dc1 100644 (file)
@@ -24,6 +24,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "tm.h"
 #include "rtl.h"
 #include "hard-reg-set.h"
+#include "obstack.h"
 #include "basic-block.h"
 #include "cfgloop.h"
 #include "cfglayout.h"
@@ -174,20 +175,20 @@ unswitch_loops (struct loops *loops)
 static rtx
 may_unswitch_on (basic_block bb, struct loop *loop, rtx *cinsn)
 {
-  rtx test, at, insn, op[2];
+  rtx test, at, insn, op[2], stest;
   struct rtx_iv iv;
   unsigned i;
   enum machine_mode mode;
 
   /* BB must end in a simple conditional jump.  */
-  if (!bb->succ || !bb->succ->succ_next || bb->succ->succ_next->succ_next)
+  if (EDGE_COUNT (bb->succs) != 2)
     return NULL_RTX;
   if (!any_condjump_p (BB_END (bb)))
     return NULL_RTX;
 
   /* With branches inside loop.  */
-  if (!flow_bb_inside_loop_p (loop, bb->succ->dest)
-      || !flow_bb_inside_loop_p (loop, bb->succ->succ_next->dest))
+  if (!flow_bb_inside_loop_p (loop, EDGE_SUCC (bb, 0)->dest)
+      || !flow_bb_inside_loop_p (loop, EDGE_SUCC (bb, 1)->dest))
     return NULL_RTX;
 
   /* It must be executed just once each iteration (because otherwise we
@@ -196,7 +197,7 @@ may_unswitch_on (basic_block bb, struct loop *loop, rtx *cinsn)
     return NULL_RTX;
 
   /* Condition must be invariant.  */
-  test = get_condition (BB_END (bb), &at, true);
+  test = get_condition (BB_END (bb), &at, true, false);
   if (!test)
     return NULL_RTX;
 
@@ -233,6 +234,12 @@ may_unswitch_on (basic_block bb, struct loop *loop, rtx *cinsn)
       return test;
     }
 
+  stest = simplify_gen_relational (GET_CODE (test), SImode,
+                                  mode, op[0], op[1]);
+  if (stest == const0_rtx
+      || stest == const_true_rtx)
+    return stest;
+
   return canon_condition (gen_rtx_fmt_ee (GET_CODE (test), SImode,
                                          op[0], op[1]));
 }
@@ -262,7 +269,7 @@ unswitch_single_loop (struct loops *loops, struct loop *loop,
   basic_block *bbs;
   struct loop *nloop;
   unsigned i;
-  rtx cond, rcond, conds, rconds, acond, cinsn = NULL_RTX;
+  rtx cond, rcond = NULL_RTX, conds, rconds, acond, cinsn = NULL_RTX;
   int repeat;
   edge e;
 
@@ -331,13 +338,17 @@ unswitch_single_loop (struct loops *loops, struct loop *loop,
          return;
        }
 
-      rcond = reversed_condition (cond);
-      if (rcond)
-       rcond = canon_condition (rcond);
+      if (cond != const0_rtx
+         && cond != const_true_rtx)
+       {
+         rcond = reversed_condition (cond);
+         if (rcond)
+           rcond = canon_condition (rcond);
 
-      /* Check whether the result can be predicted.  */
-      for (acond = cond_checked; acond; acond = XEXP (acond, 1))
-       simplify_using_condition (XEXP (acond, 0), &cond, NULL);
+         /* Check whether the result can be predicted.  */
+         for (acond = cond_checked; acond; acond = XEXP (acond, 1))
+           simplify_using_condition (XEXP (acond, 0), &cond, NULL);
+       }
 
       if (cond == const_true_rtx)
        {
@@ -379,6 +390,8 @@ unswitch_single_loop (struct loops *loops, struct loop *loop,
   free_EXPR_LIST_node (conds);
   if (rcond)
     free_EXPR_LIST_node (rconds);
+
+  free (bbs);
 }
 
 /* Unswitch a LOOP w.r. to given basic block UNSWITCH_ON.  We only support
@@ -402,16 +415,15 @@ unswitch_loop (struct loops *loops, struct loop *loop, basic_block unswitch_on,
   /* Some sanity checking.  */
   if (!flow_bb_inside_loop_p (loop, unswitch_on))
     abort ();
-  if (!unswitch_on->succ || !unswitch_on->succ->succ_next ||
-      unswitch_on->succ->succ_next->succ_next)
+  if (EDGE_COUNT (unswitch_on->succs) != 2)
     abort ();
   if (!just_once_each_iteration_p (loop, unswitch_on))
     abort ();
   if (loop->inner)
     abort ();
-  if (!flow_bb_inside_loop_p (loop, unswitch_on->succ->dest))
+  if (!flow_bb_inside_loop_p (loop, EDGE_SUCC (unswitch_on, 0)->dest))
     abort ();
-  if (!flow_bb_inside_loop_p (loop, unswitch_on->succ->succ_next->dest))
+  if (!flow_bb_inside_loop_p (loop, EDGE_SUCC (unswitch_on, 1)->dest))
     abort ();
 
   entry = loop_preheader_edge (loop);
@@ -432,7 +444,7 @@ unswitch_loop (struct loops *loops, struct loop *loop, basic_block unswitch_on,
   unswitch_on_alt = unswitch_on->rbi->copy;
   true_edge = BRANCH_EDGE (unswitch_on_alt);
   false_edge = FALLTHRU_EDGE (unswitch_on);
-  latch_edge = loop->latch->rbi->copy->succ;
+  latch_edge = EDGE_SUCC (loop->latch->rbi->copy, 0);
 
   /* Create a block with the condition.  */
   prob = true_edge->probability;
@@ -451,19 +463,20 @@ unswitch_loop (struct loops *loops, struct loop *loop, basic_block unswitch_on,
   if (irred_flag)
     {
       switch_bb->flags |= BB_IRREDUCIBLE_LOOP;
-      switch_bb->succ->flags |= EDGE_IRREDUCIBLE_LOOP;
-      switch_bb->succ->succ_next->flags |= EDGE_IRREDUCIBLE_LOOP;
+      EDGE_SUCC (switch_bb, 0)->flags |= EDGE_IRREDUCIBLE_LOOP;
+      EDGE_SUCC (switch_bb, 1)->flags |= EDGE_IRREDUCIBLE_LOOP;
     }
   else
     {
       switch_bb->flags &= ~BB_IRREDUCIBLE_LOOP;
-      switch_bb->succ->flags &= ~EDGE_IRREDUCIBLE_LOOP;
-      switch_bb->succ->succ_next->flags &= ~EDGE_IRREDUCIBLE_LOOP;
+      EDGE_SUCC (switch_bb, 0)->flags &= ~EDGE_IRREDUCIBLE_LOOP;
+      EDGE_SUCC (switch_bb, 1)->flags &= ~EDGE_IRREDUCIBLE_LOOP;
     }
 
   /* Loopify from the copy of LOOP body, constructing the new loop.  */
   nloop = loopify (loops, latch_edge,
-                  loop->header->rbi->copy->pred, switch_bb);
+                  EDGE_PRED (loop->header->rbi->copy, 0), switch_bb,
+                  BRANCH_EDGE (switch_bb), FALLTHRU_EDGE (switch_bb), true);
 
   /* Remove branches that are now unreachable in new loops.  */
   remove_path (loops, true_edge);