On Tue, 29 Oct 2013, Jakub Jelinek wrote: > On Tue, Oct 29, 2013 at 12:28:49PM +0100, Richard Biener wrote: > > Otherwise ok. > > So like this?
Yes, Thanks. Richard. > 2013-10-29 Jakub Jelinek <ja...@redhat.com> > > * tree-cfg.c (assert_unreachable_fallthru_edge_p): New function. > * tree-cfg.h (assert_unreachable_fallthru_edge_p): New prototype. > * tree-vrp.c (all_imm_uses_in_stmt_or_feed_cond): New function. > (remove_range_assertions): If ASSERT_EXPR_VAR has no other immediate > uses but in the condition and ASSERT_EXPR and the other successor of > the predecessor bb is __builtin_unreachable (), set_range_info of the > ASSERT_EXPR_VAR to the range info of the ASSERT_EXPR's lhs. > > --- gcc/tree-cfg.c.jj 2013-10-29 09:25:55.000000000 +0100 > +++ gcc/tree-cfg.c 2013-10-29 14:32:53.235150267 +0100 > @@ -380,6 +380,50 @@ computed_goto_p (gimple t) > && TREE_CODE (gimple_goto_dest (t)) != LABEL_DECL); > } > > +/* Returns true for edge E where e->src ends with a GIMPLE_COND and > + the other edge points to a bb with just __builtin_unreachable (). > + I.e. return true for C->M edge in: > + <bb C>: > + ... > + if (something) > + goto <bb N>; > + else > + goto <bb M>; > + <bb N>: > + __builtin_unreachable (); > + <bb M>: */ > + > +bool > +assert_unreachable_fallthru_edge_p (edge e) > +{ > + basic_block pred_bb = e->src; > + gimple last = last_stmt (pred_bb); > + if (last && gimple_code (last) == GIMPLE_COND) > + { > + basic_block other_bb = EDGE_SUCC (pred_bb, 0)->dest; > + if (other_bb == e->dest) > + other_bb = EDGE_SUCC (pred_bb, 1)->dest; > + if (EDGE_COUNT (other_bb->succs) == 0) > + { > + gimple_stmt_iterator gsi = gsi_after_labels (other_bb); > + gimple stmt; > + > + if (gsi_end_p (gsi)) > + return false; > + stmt = gsi_stmt (gsi); > + if (is_gimple_debug (stmt)) > + { > + gsi_next_nondebug (&gsi); > + if (gsi_end_p (gsi)) > + return false; > + stmt = gsi_stmt (gsi); > + } > + return gimple_call_builtin_p (stmt, BUILT_IN_UNREACHABLE); > + } > + } > + return false; > +} > + > > /* Search the CFG for any computed gotos. If found, factor them to a > common computed goto site. Also record the location of that site so > --- gcc/tree-vrp.c.jj 2013-10-29 09:25:38.382477963 +0100 > +++ gcc/tree-vrp.c 2013-10-29 14:36:23.695060600 +0100 > @@ -6459,6 +6459,33 @@ check_all_array_refs (void) > } > } > > +/* Return true if all imm uses of VAR are either in STMT, or > + feed (optionally through a chain of single imm uses) GIMPLE_COND > + in basic block COND_BB. */ > + > +static bool > +all_imm_uses_in_stmt_or_feed_cond (tree var, gimple stmt, basic_block > cond_bb) > +{ > + use_operand_p use_p, use2_p; > + imm_use_iterator iter; > + > + FOR_EACH_IMM_USE_FAST (use_p, iter, var) > + if (USE_STMT (use_p) != stmt) > + { > + gimple use_stmt = USE_STMT (use_p); > + if (is_gimple_debug (use_stmt)) > + continue; > + while (is_gimple_assign (use_stmt) > + && single_imm_use (gimple_assign_lhs (use_stmt), > + &use2_p, &use_stmt)) > + ; > + if (gimple_code (use_stmt) != GIMPLE_COND > + || gimple_bb (use_stmt) != cond_bb) > + return false; > + } > + return true; > +} > + > /* Convert range assertion expressions into the implied copies and > copy propagate away the copies. Doing the trivial copy propagation > here avoids the need to run the full copy propagation pass after > @@ -6488,12 +6515,16 @@ remove_range_assertions (void) > { > basic_block bb; > gimple_stmt_iterator si; > + /* 1 if looking at ASSERT_EXPRs immediately at the beginning of > + a basic block preceeded by GIMPLE_COND branching to it and > + __builtin_trap, -1 if not yet checked, 0 otherwise. */ > + int is_unreachable; > > /* Note that the BSI iterator bump happens at the bottom of the > loop and no bump is necessary if we're removing the statement > referenced by the current BSI. */ > FOR_EACH_BB (bb) > - for (si = gsi_start_bb (bb); !gsi_end_p (si);) > + for (si = gsi_after_labels (bb), is_unreachable = -1; !gsi_end_p (si);) > { > gimple stmt = gsi_stmt (si); > gimple use_stmt; > @@ -6501,6 +6532,7 @@ remove_range_assertions (void) > if (is_gimple_assign (stmt) > && gimple_assign_rhs_code (stmt) == ASSERT_EXPR) > { > + tree lhs = gimple_assign_lhs (stmt); > tree rhs = gimple_assign_rhs1 (stmt); > tree var; > tree cond = fold (ASSERT_EXPR_COND (rhs)); > @@ -6509,22 +6541,49 @@ remove_range_assertions (void) > > gcc_assert (cond != boolean_false_node); > > - /* Propagate the RHS into every use of the LHS. */ > var = ASSERT_EXPR_VAR (rhs); > - FOR_EACH_IMM_USE_STMT (use_stmt, iter, > - gimple_assign_lhs (stmt)) > + gcc_assert (TREE_CODE (var) == SSA_NAME); > + > + if (!POINTER_TYPE_P (TREE_TYPE (lhs)) > + && SSA_NAME_RANGE_INFO (lhs)) > + { > + if (is_unreachable == -1) > + { > + is_unreachable = 0; > + if (single_pred_p (bb) > + && assert_unreachable_fallthru_edge_p > + (single_pred_edge (bb))) > + is_unreachable = 1; > + } > + /* Handle > + if (x_7 >= 10 && x_7 < 20) > + __builtin_unreachable (); > + x_8 = ASSERT_EXPR <x_7, ...>; > + if the only uses of x_7 are in the ASSERT_EXPR and > + in the condition. In that case, we can copy the > + range info from x_8 computed in this pass also > + for x_7. */ > + if (is_unreachable > + && all_imm_uses_in_stmt_or_feed_cond (var, stmt, > + single_pred (bb))) > + set_range_info (var, SSA_NAME_RANGE_INFO (lhs)->min, > + SSA_NAME_RANGE_INFO (lhs)->max); > + } > + > + /* Propagate the RHS into every use of the LHS. */ > + FOR_EACH_IMM_USE_STMT (use_stmt, iter, lhs) > FOR_EACH_IMM_USE_ON_STMT (use_p, iter) > - { > - SET_USE (use_p, var); > - gcc_assert (TREE_CODE (var) == SSA_NAME); > - } > + SET_USE (use_p, var); > > /* And finally, remove the copy, it is not needed. */ > gsi_remove (&si, true); > release_defs (stmt); > } > else > - gsi_next (&si); > + { > + gsi_next (&si); > + is_unreachable = 0; > + } > } > } > > --- gcc/tree-cfg.h.jj 2013-10-21 09:00:52.000000000 +0200 > +++ gcc/tree-cfg.h 2013-10-29 14:17:52.927812547 +0100 > @@ -51,6 +51,7 @@ extern bool is_ctrl_stmt (gimple); > extern bool is_ctrl_altering_stmt (gimple); > extern bool simple_goto_p (gimple); > extern bool stmt_ends_bb_p (gimple); > +extern bool assert_unreachable_fallthru_edge_p (edge); > extern void delete_tree_cfg_annotations (void); > extern gimple first_stmt (basic_block); > extern gimple last_stmt (basic_block); > > > Jakub > > -- Richard Biener <rguent...@suse.de> SUSE / SUSE Labs SUSE LINUX Products GmbH - Nuernberg - AG Nuernberg - HRB 16746 GF: Jeff Hawn, Jennifer Guild, Felix Imend