The following fixes the remaining ICEs I see when testing all languages (but ada and go).
The tree-cfg.c hunk highlights one change in the behavior of fold_stmt, namely that it now follows SSA edges by default. Maybe that's undesired? On a related note, fold_stmt_inplace preserves the actual statement object gsi_stmt points to, but in reality callers use it to avoid creating new SSA names thus would it be ok if fold_stmt_inplace made sure to preserve the number of statements (and only change what gsi points to) only? Bootstrapped / tested on x86_64-unknown-linux-gnu, applied. Richard. 2014-08-16 Richard Biener <rguent...@suse.de> * tree-cfg.c (no_follow_ssa_edges): New function. (replace_uses_by): Do not follow SSA edges when folding the stmt. * gimple-match-head.c (maybe_push_res_to_seq): Disallow stmts that mention SSA names occuring in abnormal PHIs. (gimple_simplify): Likewise. Index: gcc/tree-cfg.c =================================================================== --- gcc/tree-cfg.c (revision 213651) +++ gcc/tree-cfg.c (working copy) @@ -1681,6 +1681,14 @@ gimple_can_merge_blocks_p (basic_block a return true; } +/* ??? Maybe this should be a generic overload of fold_stmt. */ + +static tree +no_follow_ssa_edges (tree) +{ + return NULL_TREE; +} + /* Replaces all uses of NAME by VAL. */ void @@ -1737,7 +1745,16 @@ replace_uses_by (tree name, tree val) recompute_tree_invariant_for_addr_expr (op); } - if (fold_stmt (&gsi)) + /* If we have sth like + neighbor_29 = <name> + -1; + _33 = <name> + neighbor_29; + and end up visiting _33 first then folding will + simplify the stmt to _33 = <name>; and the new + immediate use will be inserted before the stmt + iterator marker and thus we fail to visit it + again, ICEing within the has_zero_uses assert. + Avoid that by never following SSA edges. */ + if (fold_stmt (&gsi, no_follow_ssa_edges)) stmt = gsi_stmt (gsi); if (maybe_clean_or_replace_eh_stmt (orig_stmt, stmt)) Index: gcc/gimple-match-head.c =================================================================== --- gcc/gimple-match-head.c (revision 213651) +++ gcc/gimple-match-head.c (working copy) @@ -305,6 +305,17 @@ maybe_push_res_to_seq (code_helper rcode return NULL_TREE; if (!res) res = make_ssa_name (type, NULL); + /* Play safe and do not allow abnormals to be mentioned in + newly created statements. */ + if ((TREE_CODE (ops[0]) == SSA_NAME + && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ops[0])) + || (ops[1] + && TREE_CODE (ops[1]) == SSA_NAME + && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ops[1])) + || (ops[2] + && TREE_CODE (ops[2]) == SSA_NAME + && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ops[2]))) + return NULL_TREE; gimple new_stmt = gimple_build_assign_with_ops (rcode, res, ops[0], ops[1], ops[2]); gimple_seq_add_stmt_without_update (seq, new_stmt); @@ -321,6 +332,17 @@ maybe_push_res_to_seq (code_helper rcode res = make_ssa_name (type, NULL); unsigned nargs = type_num_arguments (TREE_TYPE (decl)); gcc_assert (nargs <= 3); + /* Play safe and do not allow abnormals to be mentioned in + newly created statements. */ + if ((TREE_CODE (ops[0]) == SSA_NAME + && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ops[0])) + || (nargs >= 2 + && TREE_CODE (ops[1]) == SSA_NAME + && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ops[1])) + || (nargs == 3 + && TREE_CODE (ops[2]) == SSA_NAME + && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ops[2]))) + return NULL_TREE; gimple new_stmt = gimple_build_call (decl, nargs, ops[0], ops[1], ops[2]); gimple_call_set_lhs (new_stmt, res); gimple_seq_add_stmt_without_update (seq, new_stmt); @@ -414,8 +436,8 @@ gimple_simplify (enum tree_code code, tr tree gimple_simplify (enum built_in_function fn, tree type, - tree arg0, - gimple_seq *seq, tree (*valueize)(tree)) + tree arg0, + gimple_seq *seq, tree (*valueize)(tree)) { if (constant_for_folding (arg0)) { @@ -683,6 +705,17 @@ gimple_simplify (gimple_stmt_iterator *g if (is_gimple_assign (stmt) && rcode.is_tree_code ()) { + /* Play safe and do not allow abnormals to be mentioned in + newly created statements. */ + if ((TREE_CODE (ops[0]) == SSA_NAME + && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ops[0])) + || (ops[1] + && TREE_CODE (ops[1]) == SSA_NAME + && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ops[1])) + || (ops[2] + && TREE_CODE (ops[2]) == SSA_NAME + && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ops[2]))) + return false; gimple_assign_set_rhs_with_ops_1 (gsi, rcode, ops[0], ops[1], ops[2]); update_stmt (gsi_stmt (*gsi)); }