I have queued the following patch for stage1 which improves the ability to utilize the match-and-simplify combiner during SSA propagation (by CCP and VRP). It makes sure to mark stmts as not-simulate-again when possible so that the valueization hooks know when it is safe to combine multiple statements. I had to prevent CCP from prematurely deciding that simplifying isn't worth it as well.
Bootstrapped and tested on x86_64-unknown-linux-gnu. I have applied the changes to valueize_op_1 and vrp_valueize_1 now, as requested by Jakub. Thanks, Richard. 2015-02-02 Richard Biener <rguent...@suse.de> * tree-ssa-ccp.c (likely_value): See if we have operands that are marked as never simulate again and return CONSTANT in this case. (valueize_op_1): Always allow valueizing default-defs. * tree-vrp.c (vrp_valueize_1): Likewise. * tree-ssa-propagate.c (simulate_stmt): Mark stmts that do not have any operands that will be simulated again as not being simulated again. * gcc.dg/tree-ssa/ssa-ccp-35.c: New testcase. * gcc.dg/tree-ssa/pr37508.c: Adjust. * gfortran.dg/reassoc_6.f: Remove XFAIL. Index: gcc/tree-ssa-ccp.c =================================================================== *** gcc/tree-ssa-ccp.c.orig 2015-01-30 13:20:25.794134935 +0100 --- gcc/tree-ssa-ccp.c 2015-02-02 15:48:47.810028364 +0100 *************** static ccp_lattice_t *** 645,650 **** --- 645,651 ---- likely_value (gimple stmt) { bool has_constant_operand, has_undefined_operand, all_undefined_operands; + bool has_nsa_operand; tree use; ssa_op_iter iter; unsigned i; *************** likely_value (gimple stmt) *** 667,672 **** --- 668,674 ---- has_constant_operand = false; has_undefined_operand = false; all_undefined_operands = true; + has_nsa_operand = false; FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE) { ccp_prop_value_t *val = get_value (use); *************** likely_value (gimple stmt) *** 678,683 **** --- 680,689 ---- if (val->lattice_val == CONSTANT) has_constant_operand = true; + + if (SSA_NAME_IS_DEFAULT_DEF (use) + || !prop_simulate_again_p (SSA_NAME_DEF_STMT (use))) + has_nsa_operand = true; } /* There may be constants in regular rhs operands. For calls we *************** likely_value (gimple stmt) *** 750,757 **** /* We do not consider virtual operands here -- load from read-only memory may have only VARYING virtual operands, but still be ! constant. */ if (has_constant_operand || gimple_references_memory_p (stmt)) return CONSTANT; --- 756,765 ---- /* We do not consider virtual operands here -- load from read-only memory may have only VARYING virtual operands, but still be ! constant. Also we can combine the stmt with definitions from ! operands whose definitions are not simulated again. */ if (has_constant_operand + || has_nsa_operand || gimple_references_memory_p (stmt)) return CONSTANT; *************** valueize_op_1 (tree op) *** 1145,1151 **** this SSA edge as the SSA propagator does not necessarily re-visit the use. */ gimple def_stmt = SSA_NAME_DEF_STMT (op); ! if (prop_simulate_again_p (def_stmt)) return NULL_TREE; tree tem = get_constant_value (op); if (tem) --- 1153,1160 ---- this SSA edge as the SSA propagator does not necessarily re-visit the use. */ gimple def_stmt = SSA_NAME_DEF_STMT (op); ! if (!gimple_nop_p (def_stmt) ! && prop_simulate_again_p (def_stmt)) return NULL_TREE; tree tem = get_constant_value (op); if (tem) Index: gcc/tree-vrp.c =================================================================== *** gcc/tree-vrp.c.orig 2015-01-30 13:20:25.816135225 +0100 --- gcc/tree-vrp.c 2015-02-02 15:48:47.825028438 +0100 *************** vrp_valueize_1 (tree name) *** 7096,7102 **** this SSA edge as the SSA propagator does not necessarily re-visit the use. */ gimple def_stmt = SSA_NAME_DEF_STMT (name); ! if (prop_simulate_again_p (def_stmt)) return NULL_TREE; value_range_t *vr = get_value_range (name); if (range_int_cst_singleton_p (vr)) --- 7096,7103 ---- this SSA edge as the SSA propagator does not necessarily re-visit the use. */ gimple def_stmt = SSA_NAME_DEF_STMT (name); ! if (!gimple_nop_p (def_stmt) ! && prop_simulate_again_p (def_stmt)) return NULL_TREE; value_range_t *vr = get_value_range (name); if (range_int_cst_singleton_p (vr)) Index: gcc/tree-ssa-propagate.c =================================================================== *** gcc/tree-ssa-propagate.c.orig 2015-01-30 13:20:25.817135239 +0100 --- gcc/tree-ssa-propagate.c 2015-02-02 15:48:47.825028438 +0100 *************** simulate_stmt (gimple stmt) *** 364,369 **** --- 364,370 ---- FOR_EACH_EDGE (e, ei, bb->succs) add_control_edge (e); } + return; } else if (val == SSA_PROP_INTERESTING) { *************** simulate_stmt (gimple stmt) *** 377,382 **** --- 378,422 ---- if (taken_edge) add_control_edge (taken_edge); } + + /* If there are no SSA uses on the stmt whose defs are simulated + again then this stmt will be never visited again. */ + bool has_simulate_again_uses = false; + use_operand_p use_p; + ssa_op_iter iter; + if (gimple_code (stmt) == GIMPLE_PHI) + { + edge_iterator ei; + edge e; + tree arg; + FOR_EACH_EDGE (e, ei, gimple_bb (stmt)->preds) + if (!(e->flags & EDGE_EXECUTABLE) + || ((arg = PHI_ARG_DEF_FROM_EDGE (stmt, e)) + && TREE_CODE (arg) == SSA_NAME + && !SSA_NAME_IS_DEFAULT_DEF (arg) + && prop_simulate_again_p (SSA_NAME_DEF_STMT (arg)))) + { + has_simulate_again_uses = true; + break; + } + } + else + FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE) + { + gimple def_stmt = SSA_NAME_DEF_STMT (USE_FROM_PTR (use_p)); + if (!gimple_nop_p (def_stmt) + && prop_simulate_again_p (def_stmt)) + { + has_simulate_again_uses = true; + break; + } + } + if (!has_simulate_again_uses) + { + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, "marking stmt to be not simulated again\n"); + prop_set_simulate_again (stmt, false); + } } /* Process an SSA edge worklist. WORKLIST is the SSA edge worklist to Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-35.c =================================================================== *** /dev/null 1970-01-01 00:00:00.000000000 +0000 --- gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-35.c 2015-02-02 15:48:47.840028513 +0100 *************** *** 0 **** --- 1,15 ---- + /* { dg-do compile } */ + /* { dg-options "-O -fdump-tree-ccp1" } */ + + int foo (int i, int j) + { + int x = 1; + int y = i + x; + int z = y - i; + if (z == 1) + return 1; + return 2; + } + + /* { dg-final { scan-tree-dump "return 1;" "ccp1" } } */ + /* { dg-final { cleanup-tree-dump "ccp1" } } */ Index: gcc/testsuite/gcc.dg/tree-ssa/pr37508.c =================================================================== *** gcc/testsuite/gcc.dg/tree-ssa/pr37508.c.orig 2012-06-29 15:52:56.055720744 +0200 --- gcc/testsuite/gcc.dg/tree-ssa/pr37508.c 2015-02-02 15:51:32.621918788 +0100 *************** int test2 (struct foo2 *x) *** 21,27 **** { if (x->i == 0) return 1; ! else if (x->i == -1) return 1; return 0; } --- 21,27 ---- { if (x->i == 0) return 1; ! else if (x->i == -1) /* This test is already folded to false by ccp1. */ return 1; return 0; } *************** int test4 (struct foo2 *x) *** 44,48 **** return 0; } ! /* { dg-final { scan-tree-dump-times "Folding" 3 "vrp1" } } */ /* { dg-final { cleanup-tree-dump "vrp1" } } */ --- 44,48 ---- return 0; } ! /* { dg-final { scan-tree-dump-times "Folding" 2 "vrp1" } } */ /* { dg-final { cleanup-tree-dump "vrp1" } } */ Index: gcc/testsuite/gfortran.dg/reassoc_6.f =================================================================== *** gcc/testsuite/gfortran.dg/reassoc_6.f.orig 2010-08-12 12:38:56.000000000 +0200 --- gcc/testsuite/gfortran.dg/reassoc_6.f 2015-02-02 15:54:45.217118028 +0100 *************** *** 16,22 **** return end ! Verify that offset of the first element is simplified ! ! While we understand to combine x + ~x IVOPTs now messes things ! ! up by hiding that operation in casts to unsigned. ! ! { dg-final { scan-tree-dump-not "~" "optimized" { xfail *-*-* } } } ! { dg-final { cleanup-tree-dump "optimized" } } --- 16,20 ---- return end ! Verify that offset of the first element is simplified ! ! { dg-final { scan-tree-dump-not "~" "optimized" } } ! { dg-final { cleanup-tree-dump "optimized" } }