OSDN Git Service

PR middle-end/19068
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-ccp.c
index 144a8bf..c530ede 100644 (file)
@@ -454,16 +454,21 @@ replace_uses_in (tree stmt, bool *replaced_addresses_p)
 
   FOR_EACH_SSA_USE_OPERAND (use, stmt, iter, SSA_OP_USE)
     {
-      value *val = get_value (USE_FROM_PTR (use));
+      tree tuse = USE_FROM_PTR (use);
+      value *val = get_value (tuse);
 
-      if (val->lattice_val == CONSTANT)
-       {
-         SET_USE (use, val->const_val);
-         replaced = true;
-         if (POINTER_TYPE_P (TREE_TYPE (USE_FROM_PTR (use))) 
-             && replaced_addresses_p)
-           *replaced_addresses_p = true;
-       }
+      if (val->lattice_val != CONSTANT)
+       continue;
+
+      if (TREE_CODE (stmt) == ASM_EXPR
+         && !may_propagate_copy_into_asm (tuse))
+       continue;
+
+      SET_USE (use, val->const_val);
+
+      replaced = true;
+      if (POINTER_TYPE_P (TREE_TYPE (tuse)) && replaced_addresses_p)
+       *replaced_addresses_p = true;
     }
 
   return replaced;
@@ -574,16 +579,18 @@ substitute_and_fold (void)
            {
              bool changed = fold_stmt (bsi_stmt_ptr (i));
              stmt = bsi_stmt(i);
+
              /* If we folded a builtin function, we'll likely
                 need to rename VDEFs.  */
              if (replaced_address || changed)
-               {
-                 mark_new_vars_to_rename (stmt, vars_to_rename);
-                 if (maybe_clean_eh_stmt (stmt))
-                   tree_purge_dead_eh_edges (bb);
-               }
-             else
-               modify_stmt (stmt);
+               mark_new_vars_to_rename (stmt, vars_to_rename);
+
+              /* If we cleaned up EH information from the statement,
+                 remove EH edges.  */
+             if (maybe_clean_eh_stmt (stmt))
+               tree_purge_dead_eh_edges (bb);
+
+             modify_stmt (stmt);
            }
 
          if (dump_file && (dump_flags & TDF_DETAILS))
@@ -624,9 +631,6 @@ ccp_finalize (void)
   /* Perform substitutions based on the known constant values.  */
   substitute_and_fold ();
 
-  /* Now cleanup any unreachable code.  */
-  cleanup_tree_cfg ();
-
   free (value_vector);
 }
 
@@ -845,9 +849,7 @@ ccp_fold (tree stmt)
            op0 = get_value (op0)->const_val;
        }
 
-      retval = nondestructive_fold_unary_to_constant (code,
-                                                     TREE_TYPE (rhs),
-                                                     op0);
+      retval = fold_unary_to_constant (code, TREE_TYPE (rhs), op0);
 
       /* If we folded, but did not create an invariant, then we can not
         use this expression.  */
@@ -898,9 +900,7 @@ ccp_fold (tree stmt)
            op1 = val->const_val;
        }
 
-      retval = nondestructive_fold_binary_to_constant (code,
-                                                      TREE_TYPE (rhs),
-                                                      op0, op1);
+      retval = fold_binary_to_constant (code, TREE_TYPE (rhs), op0, op1);
 
       /* If we folded, but did not create an invariant, then we can not
         use this expression.  */
@@ -1036,7 +1036,7 @@ visit_assignment (tree stmt, tree *output_p)
     {
       /* If we make it here, then stmt only has one definition:
          a V_MUST_DEF.  */
-      lhs = V_MUST_DEF_OP (v_must_defs, 0);
+      lhs = V_MUST_DEF_RESULT (v_must_defs, 0);
     }
 
   if (TREE_CODE (rhs) == SSA_NAME)
@@ -1055,21 +1055,35 @@ visit_assignment (tree stmt, tree *output_p)
       val = *nval;
     }
   else
-    {
-      /* Evaluate the statement.  */
+    /* Evaluate the statement.  */
       val = evaluate_stmt (stmt);
-    }
 
-  /* FIXME: Hack.  If this was a definition of a bitfield, we need to widen
+  /* If the original LHS was a VIEW_CONVERT_EXPR, modify the constant
+     value to be a VIEW_CONVERT_EXPR of the old constant value.  This is
+     valid because a VIEW_CONVERT_EXPR is valid everywhere an operand of
+     aggregate type is valid.
+
+     ??? Also, if this was a definition of a bitfield, we need to widen
      the constant value into the type of the destination variable.  This
      should not be necessary if GCC represented bitfields properly.  */
   {
-    tree lhs = TREE_OPERAND (stmt, 0);
+    tree orig_lhs = TREE_OPERAND (stmt, 0);
+
+    if (TREE_CODE (orig_lhs) == VIEW_CONVERT_EXPR
+       && val.lattice_val == CONSTANT)
+      {
+       val.const_val = build1 (VIEW_CONVERT_EXPR,
+                               TREE_TYPE (TREE_OPERAND (orig_lhs, 0)),
+                               val.const_val);
+       orig_lhs = TREE_OPERAND (orig_lhs, 1);
+      }
+
     if (val.lattice_val == CONSTANT
-       && TREE_CODE (lhs) == COMPONENT_REF
-       && DECL_BIT_FIELD (TREE_OPERAND (lhs, 1)))
+       && TREE_CODE (orig_lhs) == COMPONENT_REF
+       && DECL_BIT_FIELD (TREE_OPERAND (orig_lhs, 1)))
       {
-       tree w = widen_bitfield (val.const_val, TREE_OPERAND (lhs, 1), lhs);
+       tree w = widen_bitfield (val.const_val, TREE_OPERAND (orig_lhs, 1),
+                                orig_lhs);
 
        if (w && is_gimple_min_invariant (w))
          val.const_val = w;
@@ -1118,7 +1132,7 @@ visit_cond_stmt (tree stmt, edge *taken_edge_p)
      to the worklist.  If no single edge can be determined statically,
      return SSA_PROP_VARYING to feed all the outgoing edges to the
      propagation engine.  */
-  *taken_edge_p = find_taken_edge (block, val.const_val);
+  *taken_edge_p = val.const_val ? find_taken_edge (block, val.const_val) : 0;
   if (*taken_edge_p)
     return SSA_PROP_INTERESTING;
   else
@@ -1224,7 +1238,7 @@ struct tree_opt_pass pass_ccp =
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
-  TODO_dump_func | TODO_rename_vars
+  TODO_cleanup_cfg | TODO_dump_func | TODO_rename_vars
     | TODO_ggc_collect | TODO_verify_ssa
     | TODO_verify_stmts,               /* todo_flags_finish */
   0                                    /* letter */
@@ -2138,6 +2152,7 @@ convert_to_gimple_builtin (block_stmt_iterator *si_p, tree expr)
 static void
 execute_fold_all_builtins (void)
 {
+  bool cfg_changed = false;
   basic_block bb;
   FOR_EACH_BB (bb)
     {
@@ -2182,6 +2197,9 @@ execute_fold_all_builtins (void)
                abort ();
            }
          modify_stmt (*stmtp);
+         if (maybe_clean_eh_stmt (*stmtp)
+             && tree_purge_dead_eh_edges (bb))
+           cfg_changed = true;
 
          if (dump_file && (dump_flags & TDF_DETAILS))
            {
@@ -2191,6 +2209,10 @@ execute_fold_all_builtins (void)
            }
        }
     }
+
+  /* Delete unreachable blocks.  */
+  if (cfg_changed)
+    cleanup_tree_cfg ();
 }