+ /* Statements other than MODIFY_EXPR, COND_EXPR and
+ SWITCH_EXPR are not interesting for constant propagation.
+ Mark them VARYING. */
+ if (TREE_CODE (stmt) != MODIFY_EXPR
+ && TREE_CODE (stmt) != COND_EXPR
+ && TREE_CODE (stmt) != SWITCH_EXPR)
+ is_varying = true;
+
+ DONT_SIMULATE_AGAIN (stmt) = is_varying;
+ }
+ }
+
+ /* Now process PHI nodes. */
+ FOR_EACH_BB (bb)
+ {
+ tree phi, var;
+ int x;
+
+ for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
+ {
+ value *val = get_value (PHI_RESULT (phi));
+
+ for (x = 0; x < PHI_NUM_ARGS (phi); x++)
+ {
+ var = PHI_ARG_DEF (phi, x);
+
+ /* If one argument has a V_MAY_DEF, the result is
+ VARYING. */
+ if (TREE_CODE (var) == SSA_NAME)
+ {
+ if (TEST_BIT (is_may_def, SSA_NAME_VERSION (var)))
+ {
+ val->lattice_val = VARYING;
+ SET_BIT (is_may_def, SSA_NAME_VERSION (PHI_RESULT (phi)));
+ break;
+ }
+ }
+ }
+
+ DONT_SIMULATE_AGAIN (phi) = (val->lattice_val == VARYING);
+ }
+ }
+
+ sbitmap_free (is_may_def);
+
+ /* Compute immediate uses for variables we care about. */
+ compute_immediate_uses (TDFA_USE_OPS | TDFA_USE_VOPS, need_imm_uses_for);
+}
+
+
+/* Replace USE references in statement STMT with their immediate reaching
+ definition. Return true if at least one reference was replaced. If
+ REPLACED_ADDRESSES_P is given, it will be set to true if an address
+ constant was replaced. */
+
+static bool
+replace_uses_in (tree stmt, bool *replaced_addresses_p)
+{
+ bool replaced = false;
+ use_operand_p use;
+ ssa_op_iter iter;
+
+ if (replaced_addresses_p)
+ *replaced_addresses_p = false;
+
+ get_stmt_operands (stmt);
+
+ FOR_EACH_SSA_USE_OPERAND (use, stmt, iter, SSA_OP_USE)
+ {
+ tree tuse = USE_FROM_PTR (use);
+ value *val = get_value (tuse);
+
+ 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;
+}
+
+
+/* Replace the VUSE references in statement STMT with its immediate reaching
+ definition. Return true if the reference was replaced. If
+ REPLACED_ADDRESSES_P is given, it will be set to true if an address
+ constant was replaced. */
+
+static bool
+replace_vuse_in (tree stmt, bool *replaced_addresses_p)
+{
+ bool replaced = false;
+ vuse_optype vuses;
+ use_operand_p vuse;
+ value *val;
+
+ if (replaced_addresses_p)
+ *replaced_addresses_p = false;
+
+ get_stmt_operands (stmt);
+
+ vuses = STMT_VUSE_OPS (stmt);
+
+ if (NUM_VUSES (vuses) != 1)
+ return false;
+
+ vuse = VUSE_OP_PTR (vuses, 0);
+ val = get_value (USE_FROM_PTR (vuse));
+
+ if (val->lattice_val == CONSTANT
+ && TREE_CODE (stmt) == MODIFY_EXPR
+ && DECL_P (TREE_OPERAND (stmt, 1))
+ && TREE_OPERAND (stmt, 1) == SSA_NAME_VAR (USE_FROM_PTR (vuse)))
+ {
+ TREE_OPERAND (stmt, 1) = val->const_val;
+ replaced = true;
+ if (POINTER_TYPE_P (TREE_TYPE (USE_FROM_PTR (vuse)))
+ && replaced_addresses_p)
+ *replaced_addresses_p = true;
+ }
+
+ return replaced;
+}
+
+
+/* Perform final substitution and folding. After this pass the program
+ should still be in SSA form. */
+
+static void
+substitute_and_fold (void)
+{
+ basic_block bb;
+ unsigned int i;
+
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file,
+ "\nSubstituing constants and folding statements\n\n");
+
+ /* Substitute constants in every statement of every basic block. */
+ FOR_EACH_BB (bb)
+ {
+ block_stmt_iterator i;
+ tree phi;
+
+ /* Propagate our known constants into PHI nodes. */
+ for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
+ {
+ int i;
+
+ for (i = 0; i < PHI_NUM_ARGS (phi); i++)
+ {
+ value *new_val;
+ use_operand_p orig_p = PHI_ARG_DEF_PTR (phi, i);
+ tree orig = USE_FROM_PTR (orig_p);
+
+ if (! SSA_VAR_P (orig))
+ break;
+
+ new_val = get_value (orig);
+ if (new_val->lattice_val == CONSTANT
+ && may_propagate_copy (orig, new_val->const_val))
+ SET_USE (orig_p, new_val->const_val);
+ }
+ }
+
+ for (i = bsi_start (bb); !bsi_end_p (i); bsi_next (&i))