OSDN Git Service

* config/rs6000/rs6000.c (build_opaque_vector_type): Set
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-phiopt.c
index a8376cf..93b82d9 100644 (file)
@@ -1,5 +1,6 @@
 /* Optimization of PHI nodes by converting them into straightline code.
-   Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+   Copyright (C) 2004, 2005, 2006, 2007, 2008 Free Software Foundation,
+   Inc.
 
 This file is part of GCC.
 
@@ -463,6 +464,11 @@ conditional_replacement (basic_block cond_bb, basic_block middle_bb,
   tree new_var = NULL;
   tree new_var1;
 
+  /* FIXME: Gimplification of complex type is too hard for now.  */
+  if (TREE_CODE (TREE_TYPE (arg0)) == COMPLEX_TYPE
+      || TREE_CODE (TREE_TYPE (arg1)) == COMPLEX_TYPE)
+    return false;
+
   /* The PHI arguments have the constants 0 and 1, then convert
      it to the conditional.  */
   if ((integer_zerop (arg0) && integer_onep (arg1))
@@ -587,8 +593,7 @@ conditional_replacement (basic_block cond_bb, basic_block middle_bb,
          /* Only "real" casts are OK here, not everything that is
             acceptable to is_gimple_cast.  Make sure we don't do
             anything stupid here.  */
-         gcc_assert (TREE_CODE (cond) == NOP_EXPR
-                     || TREE_CODE (cond) == CONVERT_EXPR);
+         gcc_assert (CONVERT_EXPR_P (cond));
 
          op0 = TREE_OPERAND (cond, 0);
          tmp = create_tmp_var (TREE_TYPE (op0), NULL);
@@ -1078,9 +1083,17 @@ abs_replacement (basic_block cond_bb, basic_block middle_bb,
    simply is a walk over all instructions in dominator order.  When
    we see an INDIRECT_REF we determine if we've already seen a same
    ref anywhere up to the root of the dominator tree.  If we do the
-   current access can't trap.  If we don't see any dominator access
+   current access can't trap.  If we don't see any dominating access
    the current access might trap, but might also make later accesses
-   non-trapping, so we remember it.  */
+   non-trapping, so we remember it.  We need to be careful with loads
+   or stores, for instance a load might not trap, while a store would,
+   so if we see a dominating read access this doesn't mean that a later
+   write access would not trap.  Hence we also need to differentiate the
+   type of access(es) seen.
+
+   ??? We currently are very conservative and assume that a load might
+   trap even if a store doesn't (write-only memory).  This probably is
+   overly conservative.  */
 
 /* A hash-table of SSA_NAMEs, and in which basic block an INDIRECT_REF
    through it was seen, which would constitute a no-trap region for
@@ -1089,6 +1102,7 @@ struct name_to_bb
 {
   tree ssa_name;
   basic_block bb;
+  unsigned store : 1;
 };
 
 /* The hash table for remembering what we've seen.  */
@@ -1102,7 +1116,7 @@ static hashval_t
 name_to_bb_hash (const void *p)
 {
   tree n = ((struct name_to_bb *)p)->ssa_name;
-  return htab_hash_pointer (n);
+  return htab_hash_pointer (n) ^ ((struct name_to_bb *)p)->store;
 }
 
 /* The equality function of *P1 and *P2.  SSA_NAMEs are shared, so
@@ -1110,17 +1124,20 @@ name_to_bb_hash (const void *p)
 static int
 name_to_bb_eq (const void *p1, const void *p2)
 {
-  tree n1 = ((struct name_to_bb *)p1)->ssa_name;
-  tree n2 = ((struct name_to_bb *)p2)->ssa_name;
+  const struct name_to_bb *n1 = (const struct name_to_bb *)p1;
+  const struct name_to_bb *n2 = (const struct name_to_bb *)p2;
 
-  return n1 == n2;
+  return n1->ssa_name == n2->ssa_name && n1->store == n2->store;
 }
 
-/* We see the expression EXP in basic block BB.  If it's an interesting
+/* We see the expression EXP in basic block BB.  If it's an interesting
    expression (an INDIRECT_REF through an SSA_NAME) possibly insert the
-   expression into the set NONTRAP or the hash table of seen expressions.  */
+   expression into the set NONTRAP or the hash table of seen expressions.
+   STORE is true if this expression is on the LHS, otherwise it's on
+   the RHS.  */
 static void
-add_or_mark_expr (basic_block bb, tree exp, struct pointer_set_t *nontrap)
+add_or_mark_expr (basic_block bb, tree exp,
+                 struct pointer_set_t *nontrap, bool store)
 {
   if (INDIRECT_REF_P (exp)
       && TREE_CODE (TREE_OPERAND (exp, 0)) == SSA_NAME)
@@ -1128,15 +1145,18 @@ add_or_mark_expr (basic_block bb, tree exp, struct pointer_set_t *nontrap)
       tree name = TREE_OPERAND (exp, 0);
       struct name_to_bb map;
       void **slot;
+      struct name_to_bb *n2bb;
       basic_block found_bb = 0;
 
       /* Try to find the last seen INDIRECT_REF through the same
          SSA_NAME, which can trap.  */
       map.ssa_name = name;
       map.bb = 0;
+      map.store = store;
       slot = htab_find_slot (seen_ssa_names, &map, INSERT);
-      if (*slot)
-        found_bb = ((struct name_to_bb *)*slot)->bb;
+      n2bb = (struct name_to_bb *) *slot;
+      if (n2bb)
+        found_bb = n2bb->bb;
 
       /* If we've found a trapping INDIRECT_REF, _and_ it dominates EXP
          (it's in a basic block on the path from us to the dominator root)
@@ -1148,16 +1168,17 @@ add_or_mark_expr (basic_block bb, tree exp, struct pointer_set_t *nontrap)
       else
         {
          /* EXP might trap, so insert it into the hash table.  */
-         if (*slot)
+         if (n2bb)
            {
-              ((struct name_to_bb *)*slot)->bb = bb;
+             n2bb->bb = bb;
            }
          else
            {
-             struct name_to_bb *nmap = XNEW (struct name_to_bb);
-             nmap->ssa_name = name;
-             nmap->bb = bb;
-             *slot = nmap;
+             n2bb = XNEW (struct name_to_bb);
+             n2bb->ssa_name = name;
+             n2bb->bb = bb;
+             n2bb->store = store;
+             *slot = n2bb;
            }
        }
     }
@@ -1180,8 +1201,8 @@ nt_init_block (struct dom_walk_data *data ATTRIBUTE_UNUSED, basic_block bb)
        {
          tree lhs = GIMPLE_STMT_OPERAND (stmt, 0);
          tree rhs = GIMPLE_STMT_OPERAND (stmt, 1);
-         add_or_mark_expr (bb, rhs, nontrap_set);
-         add_or_mark_expr (bb, lhs, nontrap_set);
+         add_or_mark_expr (bb, rhs, nontrap_set, false);
+         add_or_mark_expr (bb, lhs, nontrap_set, true);
        }
     }
 }
@@ -1287,6 +1308,9 @@ cond_store_replacement (basic_block middle_bb, basic_block join_bb,
     {
       condstoretemp = create_tmp_var (TREE_TYPE (lhs), "cstore");
       get_var_ann (condstoretemp);
+      if (TREE_CODE (TREE_TYPE (lhs)) == COMPLEX_TYPE
+          || TREE_CODE (TREE_TYPE (lhs)) == VECTOR_TYPE)
+       DECL_GIMPLE_REG_P (condstoretemp) = 1;
     }
   add_referenced_var (condstoretemp);
 
@@ -1333,8 +1357,10 @@ gate_phiopt (void)
   return 1;
 }
 
-struct tree_opt_pass pass_phiopt =
+struct gimple_opt_pass pass_phiopt =
 {
+ {
+  GIMPLE_PASS,
   "phiopt",                            /* name */
   gate_phiopt,                         /* gate */
   tree_ssa_phiopt,                     /* execute */
@@ -1350,8 +1376,8 @@ struct tree_opt_pass pass_phiopt =
     | TODO_ggc_collect
     | TODO_verify_ssa
     | TODO_verify_flow
-    | TODO_verify_stmts,               /* todo_flags_finish */
-  0                                    /* letter */
+    | TODO_verify_stmts                        /* todo_flags_finish */
+ }
 };
 
 static bool
@@ -1360,8 +1386,10 @@ gate_cselim (void)
   return flag_tree_cselim;
 }
 
-struct tree_opt_pass pass_cselim =
+struct gimple_opt_pass pass_cselim =
 {
+ {
+  GIMPLE_PASS,
   "cselim",                            /* name */
   gate_cselim,                         /* gate */
   tree_ssa_cs_elim,                    /* execute */
@@ -1377,6 +1405,6 @@ struct tree_opt_pass pass_cselim =
     | TODO_ggc_collect
     | TODO_verify_ssa
     | TODO_verify_flow
-    | TODO_verify_stmts,               /* todo_flags_finish */
-  0                                    /* letter */
+    | TODO_verify_stmts                        /* todo_flags_finish */
+ }
 };