OSDN Git Service

* config/avr/avr.h (PREFERRED_RELOAD_CLASS): Remove.
[pf3gnuchains/gcc-fork.git] / gcc / tree-if-conv.c
index 55e2a11..642dbda 100644 (file)
@@ -446,6 +446,21 @@ if_convertible_phi_p (struct loop *loop, basic_block bb, gimple phi)
   return true;
 }
 
+/* Records the status of a data reference.  This struct is attached to
+   each DR->aux field.  */
+
+struct ifc_dr {
+  /* -1 when not initialized, 0 when false, 1 when true.  */
+  int written_at_least_once;
+
+  /* -1 when not initialized, 0 when false, 1 when true.  */
+  int rw_unconditionally;
+};
+
+#define IFC_DR(DR) ((struct ifc_dr *) (DR)->aux)
+#define DR_WRITTEN_AT_LEAST_ONCE(DR) (IFC_DR (DR)->written_at_least_once)
+#define DR_RW_UNCONDITIONALLY(DR) (IFC_DR (DR)->rw_unconditionally)
+
 /* Returns true when the memory references of STMT are read or written
    unconditionally.  In other words, this function returns true when
    for every data reference A in STMT there exist other accesses to
@@ -465,6 +480,13 @@ memrefs_read_or_written_unconditionally (gimple stmt,
     if (DR_STMT (a) == stmt)
       {
        bool found = false;
+       int x = DR_RW_UNCONDITIONALLY (a);
+
+       if (x == 0)
+         return false;
+
+       if (x == 1)
+         continue;
 
        for (j = 0; VEC_iterate (data_reference_p, drs, j, b); j++)
          if (DR_STMT (b) != stmt
@@ -472,17 +494,23 @@ memrefs_read_or_written_unconditionally (gimple stmt,
            {
              tree cb = bb_predicate (gimple_bb (DR_STMT (b)));
 
-             if (is_true_predicate (cb)
+             if (DR_RW_UNCONDITIONALLY (b) == 1
+                 || is_true_predicate (cb)
                  || is_true_predicate (ca = fold_or_predicates (EXPR_LOCATION (cb),
                                                                 ca, cb)))
                {
+                 DR_RW_UNCONDITIONALLY (a) = 1;
+                 DR_RW_UNCONDITIONALLY (b) = 1;
                  found = true;
                  break;
                }
            }
 
        if (!found)
-         return false;
+         {
+           DR_RW_UNCONDITIONALLY (a) = 0;
+           return false;
+         }
       }
 
   return true;
@@ -505,28 +533,41 @@ write_memrefs_written_at_least_once (gimple stmt,
 
   for (i = 0; VEC_iterate (data_reference_p, drs, i, a); i++)
     if (DR_STMT (a) == stmt
-       && !DR_IS_READ (a))
+       && DR_IS_WRITE (a))
       {
        bool found = false;
+       int x = DR_WRITTEN_AT_LEAST_ONCE (a);
+
+       if (x == 0)
+         return false;
+
+       if (x == 1)
+         continue;
 
        for (j = 0; VEC_iterate (data_reference_p, drs, j, b); j++)
          if (DR_STMT (b) != stmt
-             && !DR_IS_READ (b)
+             && DR_IS_WRITE (b)
              && same_data_refs_base_objects (a, b))
            {
              tree cb = bb_predicate (gimple_bb (DR_STMT (b)));
 
-             if (is_true_predicate (cb)
+             if (DR_WRITTEN_AT_LEAST_ONCE (b) == 1
+                 || is_true_predicate (cb)
                  || is_true_predicate (ca = fold_or_predicates (EXPR_LOCATION (cb),
                                                                 ca, cb)))
                {
+                 DR_WRITTEN_AT_LEAST_ONCE (a) = 1;
+                 DR_WRITTEN_AT_LEAST_ONCE (b) = 1;
                  found = true;
                  break;
                }
            }
 
        if (!found)
-         return false;
+         {
+           DR_WRITTEN_AT_LEAST_ONCE (a) = 0;
+           return false;
+         }
       }
 
   return true;
@@ -874,7 +915,7 @@ predicate_bbs (loop_p loop)
 
            case GIMPLE_COND:
              {
-               tree c2;
+               tree c2, tem;
                edge true_edge, false_edge;
                location_t loc = gimple_location (stmt);
                tree c = fold_build2_loc (loc, gimple_cond_code (stmt),
@@ -891,6 +932,9 @@ predicate_bbs (loop_p loop)
 
                /* If C is false, then FALSE_EDGE is taken.  */
                c2 = invert_truthvalue_loc (loc, unshare_expr (c));
+               tem = canonicalize_cond_expr_cond (c2);
+               if (tem)
+                 c2 = tem;
                add_to_dst_predicate_list (loop, false_edge, cond, c2);
 
                cond = NULL_TREE;
@@ -972,6 +1016,18 @@ if_convertible_loop_p_1 (struct loop *loop,
   if (!res)
     return false;
 
+  if (flag_tree_loop_if_convert_stores)
+    {
+      data_reference_p dr;
+
+      for (i = 0; VEC_iterate (data_reference_p, *refs, i, dr); i++)
+       {
+         dr->aux = XNEW (struct ifc_dr);
+         DR_WRITTEN_AT_LEAST_ONCE (dr) = -1;
+         DR_RW_UNCONDITIONALLY (dr) = -1;
+       }
+    }
+
   for (i = 0; i < loop->num_nodes; i++)
     {
       basic_block bb = ifc_bbs[i];
@@ -1045,6 +1101,15 @@ if_convertible_loop_p (struct loop *loop)
   ddrs = VEC_alloc (ddr_p, heap, 25);
   res = if_convertible_loop_p_1 (loop, &refs, &ddrs);
 
+  if (flag_tree_loop_if_convert_stores)
+    {
+      data_reference_p dr;
+      unsigned int i;
+
+      for (i = 0; VEC_iterate (data_reference_p, refs, i, dr); i++)
+       free (dr->aux);
+    }
+
   free_data_refs (refs);
   free_dependence_relations (ddrs);
   return res;