When looking at the code we produce from if-conversion and vectorization I noticed several things. For one, we are not handling TARGET_MEM_REF in operand_equal_p which means that DOM does not clean up loads/stores of that form (to the extent DOM can do that anyway). Also we never simplify the conditions in VEC_COND_EXPRs because the combining in forwprop does not handle them. And we do not combine the inverted COND_EXPRs if-conversion can create - but it's easy to do that in forwprop.
The following addresses this two issues. Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk. Richard. 2012-04-16 Richard Guenther <rguent...@suse.de> PR tree-optimization/52975 * tree-ssa-forwprop.c (combine_cond_exprs): New function. (ssa_forward_propagate_and_combine): Call it for COND_EXPRs and VEC_COND_EXPRs. Also combine into VEC_COND_EXPRs condition. * fold-const.c (operand_equal_p): Handle TARGET_MEM_REF. Index: gcc/tree-ssa-forwprop.c =================================================================== *** gcc/tree-ssa-forwprop.c (revision 186417) --- gcc/tree-ssa-forwprop.c (working copy) *************** forward_propagate_into_cond (gimple_stmt *** 632,637 **** --- 632,689 ---- return 0; } + /* Propagate from the ssa name definition statements of COND_EXPR + values in the rhs of statement STMT into the conditional arms + if that simplifies it. + Returns true if the stmt was changed. */ + + static bool + combine_cond_exprs (gimple_stmt_iterator *gsi_p) + { + gimple stmt = gsi_stmt (*gsi_p); + tree cond, val1, val2; + bool changed = false; + + cond = gimple_assign_rhs1 (stmt); + val1 = gimple_assign_rhs2 (stmt); + if (TREE_CODE (val1) == SSA_NAME) + { + gimple def_stmt = SSA_NAME_DEF_STMT (val1); + if (is_gimple_assign (def_stmt) + && gimple_assign_rhs_code (def_stmt) == gimple_assign_rhs_code (stmt) + && operand_equal_p (gimple_assign_rhs1 (def_stmt), cond, 0)) + { + val1 = unshare_expr (gimple_assign_rhs2 (def_stmt)); + gimple_assign_set_rhs2 (stmt, val1); + changed = true; + } + } + val2 = gimple_assign_rhs3 (stmt); + if (TREE_CODE (val2) == SSA_NAME) + { + gimple def_stmt = SSA_NAME_DEF_STMT (val2); + if (is_gimple_assign (def_stmt) + && gimple_assign_rhs_code (def_stmt) == gimple_assign_rhs_code (stmt) + && operand_equal_p (gimple_assign_rhs1 (def_stmt), cond, 0)) + { + val2 = unshare_expr (gimple_assign_rhs3 (def_stmt)); + gimple_assign_set_rhs3 (stmt, val2); + changed = true; + } + } + if (operand_equal_p (val1, val2, 0)) + { + gimple_assign_set_rhs_from_tree (gsi_p, val1); + stmt = gsi_stmt (*gsi_p); + changed = true; + } + + if (changed) + update_stmt (stmt); + + return changed; + } + /* We've just substituted an ADDR_EXPR into stmt. Update all the relevant data structures to match. */ *************** ssa_forward_propagate_and_combine (void) *** 2480,2489 **** || code == NEGATE_EXPR) && TREE_CODE (rhs1) == SSA_NAME) changed = simplify_not_neg_expr (&gsi); ! else if (code == COND_EXPR) { /* In this case the entire COND_EXPR is in rhs1. */ changed |= forward_propagate_into_cond (&gsi); stmt = gsi_stmt (gsi); } else if (TREE_CODE_CLASS (code) == tcc_comparison) --- 2532,2543 ---- || code == NEGATE_EXPR) && TREE_CODE (rhs1) == SSA_NAME) changed = simplify_not_neg_expr (&gsi); ! else if (code == COND_EXPR ! || code == VEC_COND_EXPR) { /* In this case the entire COND_EXPR is in rhs1. */ changed |= forward_propagate_into_cond (&gsi); + changed |= combine_cond_exprs (&gsi); stmt = gsi_stmt (gsi); } else if (TREE_CODE_CLASS (code) == tcc_comparison) Index: gcc/fold-const.c =================================================================== *** gcc/fold-const.c (revision 186417) --- gcc/fold-const.c (working copy) *************** operand_equal_p (const_tree arg0, const_ *** 2562,2567 **** --- 2562,2575 ---- case IMAGPART_EXPR: return OP_SAME (0); + case TARGET_MEM_REF: + /* Require equal extra operands and then fall thru to MEM_REF + handling of the two common operands. */ + if (!OP_SAME_WITH_NULL (2) + || !OP_SAME_WITH_NULL (3) + || !OP_SAME_WITH_NULL (4)) + return 0; + /* Fallthru. */ case MEM_REF: /* Require equal access sizes, and similar pointer types. We can have incomplete types for array references of