This PR shows an issue with ifcombine which ends up executing stmts producing range info under a different condition than before (always true). With a twisted enough maze we end up miscompiling the testcase for this reason.
Thus the following patch which resets all flow-sensitive info on defs in the affected block. I chose this over disabling ifcombine on blocks with flow-sensitive info and I didn't see an easy way to preserve some of it by analyzing the condition we replace with true/false. Bootstrap & regtest running on x86_64-unknown-linux-gnu. Richard. 2015-07-22 Richard Biener <rguent...@suse.de> PR tree-optimization/66952 * tree-ssa-ifcombine.c (pass_tree_ifcombine::execute): For blocks we end up executing unconditionally reset all SSA info such as range and alignment. * tree-ssanames.h (reset_flow_sensitive_info): Declare. * tree-ssanames.c (reset_flow_sensitive_info): New function. * gcc.dg/torture/pr66952.c: New testcase. Index: gcc/tree-ssa-ifcombine.c =================================================================== --- gcc/tree-ssa-ifcombine.c (revision 226042) +++ gcc/tree-ssa-ifcombine.c (working copy) @@ -765,7 +765,22 @@ pass_tree_ifcombine::execute (function * if (stmt && gimple_code (stmt) == GIMPLE_COND) - cfg_changed |= tree_ssa_ifcombine_bb (bb); + if (tree_ssa_ifcombine_bb (bb)) + { + /* Clear range info from all stmts in BB which is now executed + conditional on a always true/false condition. */ + for (gimple_stmt_iterator gsi = gsi_start_bb (bb); + !gsi_end_p (gsi); gsi_next (&gsi)) + { + gimple stmt = gsi_stmt (gsi); + ssa_op_iter i; + tree op; + FOR_EACH_SSA_TREE_OPERAND (op, stmt, i, SSA_OP_DEF) + reset_flow_sensitive_info (op); + } + + cfg_changed |= true; + } } free (bbs); Index: gcc/tree-ssanames.c =================================================================== --- gcc/tree-ssanames.c (revision 226042) +++ gcc/tree-ssanames.c (working copy) @@ -528,6 +528,23 @@ duplicate_ssa_name_fn (struct function * } +/* Reset all flow sensitive data on NAME such as range-info, nonzero + bits and alignment. */ + +void +reset_flow_sensitive_info (tree name) +{ + if (POINTER_TYPE_P (TREE_TYPE (name))) + { + /* points-to info is not flow-sensitive. */ + if (SSA_NAME_PTR_INFO (name)) + mark_ptr_info_alignment_unknown (SSA_NAME_PTR_INFO (name)); + } + else + SSA_NAME_RANGE_INFO (name) = NULL; +} + + /* Release all the SSA_NAMEs created by STMT. */ void Index: gcc/tree-ssanames.h =================================================================== --- gcc/tree-ssanames.h (revision 226042) +++ gcc/tree-ssanames.h (working copy) @@ -94,6 +94,7 @@ extern void duplicate_ssa_name_ptr_info extern tree duplicate_ssa_name_fn (struct function *, tree, gimple); extern void duplicate_ssa_name_range_info (tree, enum value_range_type, struct range_info_def *); +extern void reset_flow_sensitive_info (tree); extern void release_defs (gimple); extern void replace_ssa_name_symbol (tree, tree); Index: gcc/testsuite/gcc.dg/torture/pr66952.c =================================================================== --- gcc/testsuite/gcc.dg/torture/pr66952.c (revision 0) +++ gcc/testsuite/gcc.dg/torture/pr66952.c (working copy) @@ -0,0 +1,28 @@ +/* { dg-do run } */ + +int a = 128, b; + +static int +fn1 (char p1, int p2) +{ + return p1 < 0 || p1 > 1 >> p2 ? 0 : p1 << 1; +} + +static int +fn2 () +{ + char c = a; + b = fn1 (c, 1); + if ((128 | c) < 0 ? 1 : 0) + return 1; + return 0; +} + +int +main () +{ + if (fn2 () != 1) + __builtin_abort (); + + return 0; +}