* [PATCH] Handle __builtin_unreachable () using assertions in VRP @ 2013-10-25 9:13 Jakub Jelinek 2013-10-29 12:05 ` Richard Biener 0 siblings, 1 reply; 6+ messages in thread From: Jakub Jelinek @ 2013-10-25 9:13 UTC (permalink / raw) To: Richard Biener; +Cc: gcc-patches Hi! As discussed on IRC, this patch attempts to preserve VRP computed range info for some simple __builtin_unreachable () using assertions. If there are no immediate uses of some SSA_NAME except for those in a condition guarding __builtin_unreachable () and in ASSERT_EXPR in the following basic block, we can copy the range info from the assert lhs (which is lost during remove_range_assertions) and thus preserve it. Eventually we might then remove the __builtin_unreachable () in that case and still benefit from user annotating the source. In the testcase below in bar we have even without this patch the expected range info on the SSA_NAME set to x + 1, but in foo there was no range info preserved. As we have just one user of get_range_info right now, not creating a testcase. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? int foo (int x) { if (x < 26 || x > 37) __builtin_unreachable (); return x; } int bar (int x) { if (x < 26 || x > 37) __builtin_unreachable (); return x + 1; } 2013-10-25 Jakub Jelinek <jakub@redhat.com> * tree-vrp.c (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-vrp.c.jj 2013-10-24 10:19:21.000000000 +0200 +++ gcc/tree-vrp.c 2013-10-24 14:32:29.065878208 +0200 @@ -6488,12 +6488,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,30 +6505,96 @@ 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)); - use_operand_p use_p; + use_operand_p use_p, use2_p; imm_use_iterator iter; 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)) + { + basic_block pred_bb = single_pred (bb); + 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 == bb) + other_bb = EDGE_SUCC (pred_bb, 1)->dest; + if (EDGE_COUNT (other_bb->succs) == 0) + { + gimple_stmt_iterator gsi + = gsi_after_labels (other_bb); + if (!gsi_end_p (gsi) + && gimple_call_builtin_p + (gsi_stmt (gsi), + BUILT_IN_UNREACHABLE)) + 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) + { + bool ok = true; + FOR_EACH_IMM_USE_FAST (use_p, iter, var) + if (USE_STMT (use_p) != stmt) + { + 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) != single_pred (bb)) + { + ok = false; + break; + } + } + if (ok) + 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; + } } } Jakub ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] Handle __builtin_unreachable () using assertions in VRP 2013-10-25 9:13 [PATCH] Handle __builtin_unreachable () using assertions in VRP Jakub Jelinek @ 2013-10-29 12:05 ` Richard Biener 2013-10-29 14:15 ` Jakub Jelinek 0 siblings, 1 reply; 6+ messages in thread From: Richard Biener @ 2013-10-29 12:05 UTC (permalink / raw) To: Jakub Jelinek; +Cc: gcc-patches On Fri, 25 Oct 2013, Jakub Jelinek wrote: > Hi! > > As discussed on IRC, this patch attempts to preserve VRP computed > range info for some simple __builtin_unreachable () using assertions. > If there are no immediate uses of some SSA_NAME except for those in > a condition guarding __builtin_unreachable () and in ASSERT_EXPR > in the following basic block, we can copy the range info from the assert > lhs (which is lost during remove_range_assertions) and thus preserve it. > Eventually we might then remove the __builtin_unreachable () in that case > and still benefit from user annotating the source. > In the testcase below in bar we have even without this patch the expected > range info on the SSA_NAME set to x + 1, but in foo there was no range > info preserved. As we have just one user of get_range_info right now, > not creating a testcase. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? > > int > foo (int x) > { > if (x < 26 || x > 37) > __builtin_unreachable (); > return x; > } > > int > bar (int x) > { > if (x < 26 || x > 37) > __builtin_unreachable (); > return x + 1; > } > > 2013-10-25 Jakub Jelinek <jakub@redhat.com> > > * tree-vrp.c (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-vrp.c.jj 2013-10-24 10:19:21.000000000 +0200 > +++ gcc/tree-vrp.c 2013-10-24 14:32:29.065878208 +0200 > @@ -6488,12 +6488,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,30 +6505,96 @@ 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)); > - use_operand_p use_p; > + use_operand_p use_p, use2_p; > imm_use_iterator iter; > > 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)) > + { > + basic_block pred_bb = single_pred (bb); > + 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 == bb) > + other_bb = EDGE_SUCC (pred_bb, 1)->dest; > + if (EDGE_COUNT (other_bb->succs) == 0) > + { > + gimple_stmt_iterator gsi > + = gsi_after_labels (other_bb); > + if (!gsi_end_p (gsi) > + && gimple_call_builtin_p > + (gsi_stmt (gsi), > + BUILT_IN_UNREACHABLE)) > + is_unreachable = 1; > + } > + } Please factor this out into a separate function. Like obfuscated_fallthru_edge_p () (better name?). Best somewhere in tree-cfg.c. Also you want to skip debug stmts ... (not sure if we reliably enough remove them, but I can envision a compare-debug fail with some DCE disabled at least). > + } > + } > + /* 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) > + { > + bool ok = true; > + FOR_EACH_IMM_USE_FAST (use_p, iter, var) > + if (USE_STMT (use_p) != stmt) > + { > + 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) != single_pred (bb)) > + { > + ok = false; > + break; > + } > + } This also should be split out. Otherwise ok. Thanks, Richard. > + if (ok) > + 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; > + } > } > } > > > Jakub ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] Handle __builtin_unreachable () using assertions in VRP 2013-10-29 12:05 ` Richard Biener @ 2013-10-29 14:15 ` Jakub Jelinek 2013-10-29 14:41 ` Richard Biener 2013-11-04 1:00 ` Tom de Vries 0 siblings, 2 replies; 6+ messages in thread From: Jakub Jelinek @ 2013-10-29 14:15 UTC (permalink / raw) To: Richard Biener; +Cc: gcc-patches On Tue, Oct 29, 2013 at 12:28:49PM +0100, Richard Biener wrote: > Otherwise ok. So like this? 2013-10-29 Jakub Jelinek <jakub@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 ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] Handle __builtin_unreachable () using assertions in VRP 2013-10-29 14:15 ` Jakub Jelinek @ 2013-10-29 14:41 ` Richard Biener 2013-11-04 1:00 ` Tom de Vries 1 sibling, 0 replies; 6+ messages in thread From: Richard Biener @ 2013-10-29 14:41 UTC (permalink / raw) To: Jakub Jelinek; +Cc: gcc-patches 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 <jakub@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 <rguenther@suse.de> SUSE / SUSE Labs SUSE LINUX Products GmbH - Nuernberg - AG Nuernberg - HRB 16746 GF: Jeff Hawn, Jennifer Guild, Felix Imend ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] Handle __builtin_unreachable () using assertions in VRP 2013-10-29 14:15 ` Jakub Jelinek 2013-10-29 14:41 ` Richard Biener @ 2013-11-04 1:00 ` Tom de Vries 2013-11-04 10:46 ` Tom de Vries 1 sibling, 1 reply; 6+ messages in thread From: Tom de Vries @ 2013-11-04 1:00 UTC (permalink / raw) To: Jakub Jelinek; +Cc: Richard Biener, gcc-patches On 29/10/13 14:54, Jakub Jelinek wrote: > +/* 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; > +} > + Jakub, with g++.dg/torture/pr54684.C and -fno-tree-tail-merge, I run into a sigsegv because of gimple_code (use_stmt) being called with use_stmt == NULL. Thanks, - Tom ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] Handle __builtin_unreachable () using assertions in VRP 2013-11-04 1:00 ` Tom de Vries @ 2013-11-04 10:46 ` Tom de Vries 0 siblings, 0 replies; 6+ messages in thread From: Tom de Vries @ 2013-11-04 10:46 UTC (permalink / raw) To: Jakub Jelinek; +Cc: Richard Biener, gcc-patches On 04/11/13 01:59, Tom de Vries wrote: > On 29/10/13 14:54, Jakub Jelinek wrote: >> +/* 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; >> +} >> + > > Jakub, > > with g++.dg/torture/pr54684.C and -fno-tree-tail-merge, I run into a sigsegv > because of gimple_code (use_stmt) being called with use_stmt == NULL. > It's a duplicate of PR58978 - '[4.9 Regression] ICE: Segmentation fault' http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58978 Thanks, - Tom ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2013-11-04 10:46 UTC | newest] Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2013-10-25 9:13 [PATCH] Handle __builtin_unreachable () using assertions in VRP Jakub Jelinek 2013-10-29 12:05 ` Richard Biener 2013-10-29 14:15 ` Jakub Jelinek 2013-10-29 14:41 ` Richard Biener 2013-11-04 1:00 ` Tom de Vries 2013-11-04 10:46 ` Tom de Vries
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).