OSDN Git Service

Add file forgotten in commit Rev. 162500
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-dom.c
index 25eb306..4715592 100644 (file)
@@ -51,6 +51,7 @@ enum expr_kind
   EXPR_SINGLE,
   EXPR_UNARY,
   EXPR_BINARY,
+  EXPR_TERNARY,
   EXPR_CALL
 };
 
@@ -61,7 +62,8 @@ struct hashable_expr
   union {
     struct { tree rhs; } single;
     struct { enum tree_code op;  tree opnd; } unary;
-    struct { enum tree_code op;  tree opnd0; tree opnd1; } binary;
+    struct { enum tree_code op;  tree opnd0, opnd1; } binary;
+    struct { enum tree_code op;  tree opnd0, opnd1, opnd2; } ternary;
     struct { tree fn; bool pure; size_t nargs; tree *args; } call;
   } ops;
 };
@@ -211,22 +213,30 @@ initialize_hash_element (gimple stmt, tree lhs,
       switch (get_gimple_rhs_class (subcode))
         {
         case GIMPLE_SINGLE_RHS:
-          expr->kind = EXPR_SINGLE;
-          expr->ops.single.rhs = gimple_assign_rhs1 (stmt);
-          break;
+         expr->kind = EXPR_SINGLE;
+         expr->ops.single.rhs = gimple_assign_rhs1 (stmt);
+         break;
         case GIMPLE_UNARY_RHS:
-          expr->kind = EXPR_UNARY;
+         expr->kind = EXPR_UNARY;
          expr->type = TREE_TYPE (gimple_assign_lhs (stmt));
-          expr->ops.unary.op = subcode;
-          expr->ops.unary.opnd = gimple_assign_rhs1 (stmt);
-          break;
+         expr->ops.unary.op = subcode;
+         expr->ops.unary.opnd = gimple_assign_rhs1 (stmt);
+         break;
         case GIMPLE_BINARY_RHS:
-          expr->kind = EXPR_BINARY;
+         expr->kind = EXPR_BINARY;
          expr->type = TREE_TYPE (gimple_assign_lhs (stmt));
-          expr->ops.binary.op = subcode;
-          expr->ops.binary.opnd0 = gimple_assign_rhs1 (stmt);
-          expr->ops.binary.opnd1 = gimple_assign_rhs2 (stmt);
-          break;
+         expr->ops.binary.op = subcode;
+         expr->ops.binary.opnd0 = gimple_assign_rhs1 (stmt);
+         expr->ops.binary.opnd1 = gimple_assign_rhs2 (stmt);
+         break;
+        case GIMPLE_TERNARY_RHS:
+         expr->kind = EXPR_TERNARY;
+         expr->type = TREE_TYPE (gimple_assign_lhs (stmt));
+         expr->ops.ternary.op = subcode;
+         expr->ops.ternary.opnd0 = gimple_assign_rhs1 (stmt);
+         expr->ops.ternary.opnd1 = gimple_assign_rhs2 (stmt);
+         expr->ops.ternary.opnd2 = gimple_assign_rhs3 (stmt);
+         break;
         default:
           gcc_unreachable ();
         }
@@ -371,23 +381,40 @@ hashable_expr_equal_p (const struct hashable_expr *expr0,
                               expr1->ops.unary.opnd, 0);
 
     case EXPR_BINARY:
-      {
-        if (expr0->ops.binary.op != expr1->ops.binary.op)
-          return false;
-
-        if (operand_equal_p (expr0->ops.binary.opnd0,
-                             expr1->ops.binary.opnd0, 0)
-            && operand_equal_p (expr0->ops.binary.opnd1,
-                                expr1->ops.binary.opnd1, 0))
-          return true;
-
-        /* For commutative ops, allow the other order.  */
-        return (commutative_tree_code (expr0->ops.binary.op)
-                && operand_equal_p (expr0->ops.binary.opnd0,
-                                    expr1->ops.binary.opnd1, 0)
-                && operand_equal_p (expr0->ops.binary.opnd1,
-                                    expr1->ops.binary.opnd0, 0));
-      }
+      if (expr0->ops.binary.op != expr1->ops.binary.op)
+       return false;
+
+      if (operand_equal_p (expr0->ops.binary.opnd0,
+                          expr1->ops.binary.opnd0, 0)
+         && operand_equal_p (expr0->ops.binary.opnd1,
+                             expr1->ops.binary.opnd1, 0))
+       return true;
+
+      /* For commutative ops, allow the other order.  */
+      return (commutative_tree_code (expr0->ops.binary.op)
+             && operand_equal_p (expr0->ops.binary.opnd0,
+                                 expr1->ops.binary.opnd1, 0)
+             && operand_equal_p (expr0->ops.binary.opnd1,
+                                 expr1->ops.binary.opnd0, 0));
+
+    case EXPR_TERNARY:
+      if (expr0->ops.ternary.op != expr1->ops.ternary.op
+         || !operand_equal_p (expr0->ops.ternary.opnd2,
+                              expr1->ops.ternary.opnd2, 0))
+       return false;
+
+      if (operand_equal_p (expr0->ops.ternary.opnd0,
+                          expr1->ops.ternary.opnd0, 0)
+         && operand_equal_p (expr0->ops.ternary.opnd1,
+                             expr1->ops.ternary.opnd1, 0))
+       return true;
+
+      /* For commutative ops, allow the other order.  */
+      return (commutative_ternary_tree_code (expr0->ops.ternary.op)
+             && operand_equal_p (expr0->ops.ternary.opnd0,
+                                 expr1->ops.ternary.opnd1, 0)
+             && operand_equal_p (expr0->ops.ternary.opnd1,
+                                 expr1->ops.ternary.opnd0, 0));
 
     case EXPR_CALL:
       {
@@ -450,8 +477,8 @@ iterative_hash_hashable_expr (const struct hashable_expr *expr, hashval_t val)
     case EXPR_BINARY:
       val = iterative_hash_object (expr->ops.binary.op, val);
       if (commutative_tree_code (expr->ops.binary.op))
-          val = iterative_hash_exprs_commutative (expr->ops.binary.opnd0,
-                                                  expr->ops.binary.opnd1, val);
+       val = iterative_hash_exprs_commutative (expr->ops.binary.opnd0,
+                                               expr->ops.binary.opnd1, val);
       else
         {
           val = iterative_hash_expr (expr->ops.binary.opnd0, val);
@@ -459,6 +486,19 @@ iterative_hash_hashable_expr (const struct hashable_expr *expr, hashval_t val)
         }
       break;
 
+    case EXPR_TERNARY:
+      val = iterative_hash_object (expr->ops.ternary.op, val);
+      if (commutative_ternary_tree_code (expr->ops.ternary.op))
+       val = iterative_hash_exprs_commutative (expr->ops.ternary.opnd0,
+                                               expr->ops.ternary.opnd1, val);
+      else
+        {
+          val = iterative_hash_expr (expr->ops.ternary.opnd0, val);
+          val = iterative_hash_expr (expr->ops.ternary.opnd1, val);
+        }
+      val = iterative_hash_expr (expr->ops.ternary.opnd2, val);
+      break;
+
     case EXPR_CALL:
       {
         size_t i;
@@ -511,6 +551,16 @@ print_expr_hash_elt (FILE * stream, const struct expr_hash_elt *element)
         print_generic_expr (stream, element->expr.ops.binary.opnd1, 0);
         break;
 
+      case EXPR_TERNARY:
+        fprintf (stream, " %s <", tree_code_name[element->expr.ops.ternary.op]);
+        print_generic_expr (stream, element->expr.ops.ternary.opnd0, 0);
+       fputs (", ", stream);
+        print_generic_expr (stream, element->expr.ops.ternary.opnd1, 0);
+       fputs (", ", stream);
+        print_generic_expr (stream, element->expr.ops.ternary.opnd2, 0);
+       fputs (">", stream);
+        break;
+
       case EXPR_CALL:
         {
           size_t i;
@@ -1585,7 +1635,7 @@ record_edge_info (basic_block bb)
               edge_info = allocate_edge_info (false_edge);
               record_conditions (edge_info, inverted, cond);
 
-              if (code == NE_EXPR)
+              if (TREE_CODE (inverted) == EQ_EXPR)
                 {
                   edge_info->lhs = op1;
                   edge_info->rhs = op0;
@@ -1612,7 +1662,7 @@ record_edge_info (basic_block bb)
               edge_info = allocate_edge_info (false_edge);
               record_conditions (edge_info, inverted, cond);
 
-              if (TREE_CODE (cond) == NE_EXPR)
+              if (TREE_CODE (inverted) == EQ_EXPR)
                 {
                   edge_info->lhs = op0;
                   edge_info->rhs = op1;
@@ -2509,6 +2559,20 @@ propagate_rhs_into_lhs (gimple stmt, tree lhs, tree rhs, bitmap interesting_name
              continue;
            }
 
+         /* It's not ok to propagate into the definition stmt of RHS.
+               <bb 9>:
+                 # prephitmp.12_36 = PHI <g_67.1_6(9)>
+                 g_67.1_6 = prephitmp.12_36;
+                 goto <bb 9>;
+            While this is strictly all dead code we do not want to
+            deal with this here.  */
+         if (TREE_CODE (rhs) == SSA_NAME
+             && SSA_NAME_DEF_STMT (rhs) == use_stmt)
+           {
+             all = false;
+             continue;
+           }
+
          /* Dump details.  */
          if (dump_file && (dump_flags & TDF_DETAILS))
            {