------- Comment #12 from rguenth at gcc dot gnu dot org 2009-06-03 14:00 ------- The problem seems to be the asymmetry wrt handling of NAMEs vs. SSA_NAME operands in NARYs and REFERENCEs. We happily translate NAMEs and do not clean them if they are in AVAIL_OUT, but we only can translate SSA_NAME operands if they have a leader in the set we are currently translating (wtf?) and we clean the NARYs and REFERENCEs that do not have their SSA_NAME operands in ANTIC_IN itself.
Huh. Fixing both "fixes" the problem, but obviously results in larger ANTIC_IN sets. @@ -1466,13 +1499,15 @@ phi_translate_1 (pre_expr expr, bitmap_s { unsigned int op_val_id = VN_INFO (newnary.op[i])->value_id; pre_expr leader = find_leader_in_sets (op_val_id, set1, set2); - pre_expr result = phi_translate_1 (leader, set1, set2, + pre_expr result; + if (!leader) + leader = get_or_alloc_expr_for_name (newnary.op[i]); + result = phi_translate_1 (leader, set1, set2, pred, phiblock, seen); if (result && result != leader) { tree name = get_representative_for (result); - if (!name) - return NULL; + gcc_assert (name != NULL_TREE); newnary.op[i] = name; } else if (!result) @@ -1569,13 +1604,14 @@ phi_translate_1 (pre_expr expr, bitmap_s { unsigned int op_val_id = VN_INFO (op0)->value_id; leader = find_leader_in_sets (op_val_id, set1, set2); + if (!leader) + leader = get_or_alloc_expr_for_name (op0); opresult = phi_translate_1 (leader, set1, set2, pred, phiblock, seen); if (opresult && opresult != leader) { tree name = get_representative_for (opresult); - if (!name) - break; + gcc_assert (name != NULL_TREE); op0 = name; } else if (!opresult) @@ -1587,13 +1623,14 @@ phi_translate_1 (pre_expr expr, bitmap_s { unsigned int op_val_id = VN_INFO (op1)->value_id; leader = find_leader_in_sets (op_val_id, set1, set2); + if (!leader) + leader = get_or_alloc_expr_for_name (op1); opresult = phi_translate_1 (leader, set1, set2, pred, phiblock, seen); if (opresult && opresult != leader) { tree name = get_representative_for (opresult); - if (!name) - break; + gcc_assert (name != NULL_TREE); op1 = name; } else if (!opresult) @@ -1604,13 +1641,14 @@ phi_translate_1 (pre_expr expr, bitmap_s { unsigned int op_val_id = VN_INFO (op2)->value_id; leader = find_leader_in_sets (op_val_id, set1, set2); + if (!leader) + leader = get_or_alloc_expr_for_name (op2); opresult = phi_translate_1 (leader, set1, set2, pred, phiblock, seen); if (opresult && opresult != leader) { tree name = get_representative_for (opresult); - if (!name) - break; + gcc_assert (name != NULL_TREE); op2 = name; } else if (!opresult) @@ -2091,7 +2129,7 @@ clean (bitmap_set_t set, basic_block blo for (i = 0; VEC_iterate (pre_expr, exprs, i, expr); i++) { - if (!valid_in_sets (set, NULL, expr, block)) + if (!valid_in_sets (set, AVAIL_OUT (block), expr, block)) bitmap_remove_from_set (set, expr); } VEC_free (pre_expr, heap, exprs); the fix results in some ICEs because we cannot insert though. A fix the other way around is be possible as well, but it doesn't fix the problem: Index: tree-ssa-pre.c =================================================================== --- tree-ssa-pre.c (revision 148119) +++ tree-ssa-pre.c (working copy) @@ -1717,6 +1717,10 @@ phi_translate_1 (pre_expr expr, bitmap_s edge e; gimple def_stmt; tree name = PRE_EXPR_NAME (expr); + unsigned int name_val_id = VN_INFO (name)->value_id; + pre_expr leader = find_leader_in_sets (name_val_id, set1, set2); + if (!leader) + return NULL; def_stmt = SSA_NAME_DEF_STMT (name); if (gimple_code (def_stmt) == GIMPLE_PHI @@ -2006,7 +2010,7 @@ valid_in_sets (bitmap_set_t set1, bitmap switch (expr->kind) { case NAME: - return bitmap_set_contains_expr (AVAIL_OUT (block), expr); + return union_contains_value (set1, set2, get_expr_value_id (expr)); case NARY: { unsigned int i; Note that what is odd is that during clean () we use ANTIC_IN to clean expressions but we change it at the same time. How are we sure that clean (); clean () is a no-op? -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40321