+/* Propagate from the ssa name definition statements of COND_EXPR
+ in statement STMT into the conditional if that simplifies it.
+ Returns zero if no statement was changed, one if there were
+ changes and two if cfg_cleanup needs to run. */
+
+static int
+forward_propagate_into_cond (tree cond_expr, tree stmt)
+{
+ int did_something = 0;
+
+ do {
+ tree tmp = NULL_TREE;
+ tree cond = COND_EXPR_COND (cond_expr);
+ tree name, def_stmt, rhs;
+ bool single_use_p;
+
+ /* We can do tree combining on SSA_NAME and comparison expressions. */
+ if (COMPARISON_CLASS_P (cond)
+ && TREE_CODE (TREE_OPERAND (cond, 0)) == SSA_NAME)
+ {
+ /* For comparisons use the first operand, that is likely to
+ simplify comparisons against constants. */
+ name = TREE_OPERAND (cond, 0);
+ def_stmt = get_prop_source_stmt (name, false, &single_use_p);
+ if (def_stmt != NULL_TREE
+ && can_propagate_from (def_stmt))
+ {
+ tree op1 = TREE_OPERAND (cond, 1);
+ rhs = GIMPLE_STMT_OPERAND (def_stmt, 1);
+ tmp = combine_cond_expr_cond (TREE_CODE (cond), boolean_type_node,
+ fold_convert (TREE_TYPE (op1), rhs),
+ op1, !single_use_p);
+ }
+ /* If that wasn't successful, try the second operand. */
+ if (tmp == NULL_TREE
+ && TREE_CODE (TREE_OPERAND (cond, 1)) == SSA_NAME)
+ {
+ tree op0 = TREE_OPERAND (cond, 0);
+ name = TREE_OPERAND (cond, 1);
+ def_stmt = get_prop_source_stmt (name, false, &single_use_p);
+ if (def_stmt == NULL_TREE
+ || !can_propagate_from (def_stmt))
+ return did_something;
+
+ rhs = GIMPLE_STMT_OPERAND (def_stmt, 1);
+ tmp = combine_cond_expr_cond (TREE_CODE (cond), boolean_type_node,
+ op0,
+ fold_convert (TREE_TYPE (op0), rhs),
+ !single_use_p);
+ }
+ }
+ else if (TREE_CODE (cond) == SSA_NAME)
+ {
+ name = cond;
+ def_stmt = get_prop_source_stmt (name, true, NULL);
+ if (def_stmt == NULL_TREE
+ || !can_propagate_from (def_stmt))
+ return did_something;
+
+ rhs = GIMPLE_STMT_OPERAND (def_stmt, 1);
+ tmp = combine_cond_expr_cond (NE_EXPR, boolean_type_node, rhs,
+ build_int_cst (TREE_TYPE (rhs), 0),
+ false);
+ }
+
+ if (tmp)
+ {
+ if (dump_file && tmp)
+ {
+ fprintf (dump_file, " Replaced '");
+ print_generic_expr (dump_file, cond, 0);
+ fprintf (dump_file, "' with '");
+ print_generic_expr (dump_file, tmp, 0);
+ fprintf (dump_file, "'\n");
+ }
+
+ COND_EXPR_COND (cond_expr) = unshare_expr (tmp);
+ update_stmt (stmt);