The following removes GENERIC folding from cleanup_control_expr_graph in favor of GIMPLE one. This likely doesn't solve the underlying issue of PR67915 fully but using const_binop as I originally wanted doesn't catch all cases fold_binary did because stmts that were previously folded get non-folded as the cgraph state changes (and thus we can start simplifying aliases and weaks).
I've adjusted match.pd to handle &"ab" < &"ab"[2] and gimplification to fold the conditions it builds (the C++ FE leaves us with unfolded COND_EXPR_CONDs). Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk. Richard. 2015-10-14 Richard Biener <rguent...@suse.de> PR tree-optimization/67915 * match.pd: Handle comparisons of addresses of STRING_CSTs. * gimplify.c (gimplify_cond_expr): Fold the GIMPLE conds we build. * tree-cfgcleanup.c (cleanup_control_expr_graph): Remove GENERIC stmt folding in favor of GIMPLE one. * gcc.dg/torture/pr67915.c: New testcase. Index: gcc/testsuite/gcc.dg/torture/pr67915.c =================================================================== *** gcc/testsuite/gcc.dg/torture/pr67915.c (revision 0) --- gcc/testsuite/gcc.dg/torture/pr67915.c (revision 0) *************** *** 0 **** --- 1,23 ---- + /* { dg-do compile } */ + + int a, b, c, d, e, f, g; + + int + fn1 (int p1) + { + return p1; + } + + void + fn2 () + { + lbl: + g = b; + if (fn1 (c && e)) + { + f = a ? 0 : 1 << 1; + short h = b; + d = h < 0 || f ? 0 : 1; + } + goto lbl; + } Index: gcc/match.pd =================================================================== *** gcc/match.pd (revision 228804) --- gcc/match.pd (working copy) *************** (define_operator_list CEXPI BUILT_IN_CEX *** 1998,2005 **** && decl_in_symtab_p (base1)) equal = symtab_node::get_create (base0) ->equal_address_to (symtab_node::get_create (base1)); ! else if ((DECL_P (base0) || TREE_CODE (base0) == SSA_NAME) ! && (DECL_P (base1) || TREE_CODE (base1) == SSA_NAME)) equal = (base0 == base1); } (if (equal == 1 --- 1998,2009 ---- && decl_in_symtab_p (base1)) equal = symtab_node::get_create (base0) ->equal_address_to (symtab_node::get_create (base1)); ! else if ((DECL_P (base0) ! || TREE_CODE (base0) == SSA_NAME ! || TREE_CODE (base0) == STRING_CST) ! && (DECL_P (base1) ! || TREE_CODE (base1) == SSA_NAME ! || TREE_CODE (base1) == STRING_CST)) equal = (base0 == base1); } (if (equal == 1 *************** (define_operator_list CEXPI BUILT_IN_CEX *** 2007,2015 **** /* If the offsets are equal we can ignore overflow. */ || off0 == off1 || POINTER_TYPE_OVERFLOW_UNDEFINED ! /* Or if we compare using pointers to decls. */ || (POINTER_TYPE_P (TREE_TYPE (@2)) ! && DECL_P (base0)))) (switch (if (cmp == EQ_EXPR) { constant_boolean_node (off0 == off1, type); }) --- 2011,2019 ---- /* If the offsets are equal we can ignore overflow. */ || off0 == off1 || POINTER_TYPE_OVERFLOW_UNDEFINED ! /* Or if we compare using pointers to decls or strings. */ || (POINTER_TYPE_P (TREE_TYPE (@2)) ! && (DECL_P (base0) || TREE_CODE (base0) == STRING_CST)))) (switch (if (cmp == EQ_EXPR) { constant_boolean_node (off0 == off1, type); }) Index: gcc/gimplify.c =================================================================== *** gcc/gimplify.c (revision 228804) --- gcc/gimplify.c (working copy) *************** gimplify_cond_expr (tree *expr_p, gimple *** 3152,3162 **** gimple_cond_get_ops_from_tree (COND_EXPR_COND (expr), &pred_code, &arm1, &arm2); - cond_stmt = gimple_build_cond (pred_code, arm1, arm2, label_true, ! label_false); ! gimplify_seq_add_stmt (&seq, cond_stmt); label_cont = NULL_TREE; if (!have_then_clause_p) { --- 3152,3163 ---- gimple_cond_get_ops_from_tree (COND_EXPR_COND (expr), &pred_code, &arm1, &arm2); cond_stmt = gimple_build_cond (pred_code, arm1, arm2, label_true, ! label_false); gimplify_seq_add_stmt (&seq, cond_stmt); + gimple_stmt_iterator gsi = gsi_last (seq); + maybe_fold_stmt (&gsi); + label_cont = NULL_TREE; if (!have_then_clause_p) { Index: gcc/tree-cfgcleanup.c =================================================================== *** gcc/tree-cfgcleanup.c (revision 228804) --- gcc/tree-cfgcleanup.c (working copy) *************** along with GCC; see the file COPYING3. *** 56,61 **** --- 56,64 ---- #include "cfgloop.h" #include "tree-ssa-propagate.h" #include "tree-scalar-evolution.h" + #include "gimple-match.h" + #include "gimple-fold.h" + /* The set of blocks in that at least one of the following changes happened: -- the statement at the end of the block was changed *************** cleanup_control_expr_graph (basic_block *** 96,127 **** edge taken_edge; bool retval = false; gimple *stmt = gsi_stmt (gsi); - tree val; if (!single_succ_p (bb)) { edge e; edge_iterator ei; bool warned; ! location_t loc; fold_defer_overflow_warnings (); - loc = gimple_location (stmt); switch (gimple_code (stmt)) { case GIMPLE_COND: ! val = fold_binary_loc (loc, gimple_cond_code (stmt), ! boolean_type_node, ! gimple_cond_lhs (stmt), ! gimple_cond_rhs (stmt)); ! break; case GIMPLE_SWITCH: val = gimple_switch_index (as_a <gswitch *> (stmt)); break; default: ! val = NULL_TREE; } taken_edge = find_taken_edge (bb, val); if (!taken_edge) --- 99,132 ---- edge taken_edge; bool retval = false; gimple *stmt = gsi_stmt (gsi); if (!single_succ_p (bb)) { edge e; edge_iterator ei; bool warned; ! tree val = NULL_TREE; fold_defer_overflow_warnings (); switch (gimple_code (stmt)) { case GIMPLE_COND: ! { ! code_helper rcode; ! tree ops[3] = {}; ! if (gimple_simplify (stmt, &rcode, ops, NULL, no_follow_ssa_edges, ! no_follow_ssa_edges) ! && rcode == INTEGER_CST) ! val = ops[0]; ! break; ! } case GIMPLE_SWITCH: val = gimple_switch_index (as_a <gswitch *> (stmt)); break; default: ! ; } taken_edge = find_taken_edge (bb, val); if (!taken_edge)