This moves handling of trapping ops to prune_clobbered_mems and compute_avail, similar to how I moved handling of clobbered mems earlier. It fixes one existing testcase even.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied. Richard. 2012-05-03 Richard Guenther <rguent...@suse.de> * tree-ssa-pre.c (valid_in_sets): Remove checking of trapping operations. (prune_clobbered_mems): Do it here. Do not uselessly sort expressions. (compute_avail): Do not add possibly trapping operations to EXP_GEN if they might not be executed in the block. * gcc.dg/tree-ssa/ssa-pre-27.c: Remove XFAIL. Index: gcc/tree-ssa-pre.c =================================================================== *** gcc/tree-ssa-pre.c (revision 187092) --- gcc/tree-ssa-pre.c (working copy) *************** valid_in_sets (bitmap_set_t set1, bitmap *** 2069,2081 **** for (i = 0; i < nary->length; i++) if (!op_valid_in_sets (set1, set2, nary->op[i])) return false; - /* If the NARY may trap make sure the block does not contain - a possible exit point. - ??? This is overly conservative if we translate AVAIL_OUT - as the available expression might be after the exit point. */ - if (BB_MAY_NOTRETURN (block) - && vn_nary_may_trap (nary)) - return false; return true; } break; --- 2069,2074 ---- *************** clean (bitmap_set_t set, basic_block blo *** 2140,2174 **** } /* Clean the set of expressions that are no longer valid in SET because ! they are clobbered in BLOCK. */ static void prune_clobbered_mems (bitmap_set_t set, basic_block block) { ! VEC (pre_expr, heap) *exprs = sorted_array_from_bitmap_set (set); ! pre_expr expr; ! int i; ! FOR_EACH_VEC_ELT (pre_expr, exprs, i, expr) { ! vn_reference_t ref; ! if (expr->kind != REFERENCE) ! continue; ! ! ref = PRE_EXPR_REFERENCE (expr); ! if (ref->vuse) { ! gimple def_stmt = SSA_NAME_DEF_STMT (ref->vuse); ! if (!gimple_nop_p (def_stmt) ! && ((gimple_bb (def_stmt) != block ! && !dominated_by_p (CDI_DOMINATORS, ! block, gimple_bb (def_stmt))) ! || (gimple_bb (def_stmt) == block ! && value_dies_in_block_x (expr, block)))) bitmap_remove_from_set (set, expr); } } - VEC_free (pre_expr, heap, exprs); } static sbitmap has_abnormal_preds; --- 2133,2176 ---- } /* Clean the set of expressions that are no longer valid in SET because ! they are clobbered in BLOCK or because they trap and may not be executed. */ static void prune_clobbered_mems (bitmap_set_t set, basic_block block) { ! bitmap_iterator bi; ! unsigned i; ! FOR_EACH_EXPR_ID_IN_SET (set, i, bi) { ! pre_expr expr = expression_for_id (i); ! if (expr->kind == REFERENCE) ! { ! vn_reference_t ref = PRE_EXPR_REFERENCE (expr); ! if (ref->vuse) ! { ! gimple def_stmt = SSA_NAME_DEF_STMT (ref->vuse); ! if (!gimple_nop_p (def_stmt) ! && ((gimple_bb (def_stmt) != block ! && !dominated_by_p (CDI_DOMINATORS, ! block, gimple_bb (def_stmt))) ! || (gimple_bb (def_stmt) == block ! && value_dies_in_block_x (expr, block)))) ! bitmap_remove_from_set (set, expr); ! } ! } ! else if (expr->kind == NARY) { ! vn_nary_op_t nary = PRE_EXPR_NARY (expr); ! /* If the NARY may trap make sure the block does not contain ! a possible exit point. ! ??? This is overly conservative if we translate AVAIL_OUT ! as the available expression might be after the exit point. */ ! if (BB_MAY_NOTRETURN (block) ! && vn_nary_may_trap (nary)) bitmap_remove_from_set (set, expr); } } } static sbitmap has_abnormal_preds; *************** compute_avail (void) *** 4119,4124 **** --- 4121,4133 ---- if (TREE_CODE (nary->op[i]) == SSA_NAME) add_to_exp_gen (block, nary->op[i]); + /* If the NARY traps and there was a preceeding + point in the block that might not return avoid + adding the nary to EXP_GEN. */ + if (BB_MAY_NOTRETURN (block) + && vn_nary_may_trap (nary)) + continue; + result = (pre_expr) pool_alloc (pre_expr_pool); result->kind = NARY; result->id = 0; Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-27.c =================================================================== *** gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-27.c (revision 187091) --- gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-27.c (working copy) *************** int foo2 (int i, int j, int b) *** 17,29 **** int res = 0; if (b) res = i/j; ! /* But we fail so here because of the possibly not returning ! call in the same basic-block. */ res += i/j; bar (); return res; } ! /* { dg-final { scan-tree-dump-times "# prephitmp" 1 "pre" } } */ ! /* { dg-final { scan-tree-dump-times "# prephitmp" 2 "pre" { xfail *-*-* } } } */ /* { dg-final { cleanup-tree-dump "pre" } } */ --- 17,28 ---- int res = 0; if (b) res = i/j; ! /* And here, the possibly not returning call in the same basic-block ! comes after the trapping i/j. */ res += i/j; bar (); return res; } ! /* { dg-final { scan-tree-dump-times "# prephitmp" 2 "pre" } } */ /* { dg-final { cleanup-tree-dump "pre" } } */