From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 12824 invoked by alias); 29 Oct 2013 14:12:24 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 12805 invoked by uid 89); 29 Oct 2013 14:12:22 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-3.7 required=5.0 tests=AWL,BAYES_00,RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: mx2.suse.de Received: from cantor2.suse.de (HELO mx2.suse.de) (195.135.220.15) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 29 Oct 2013 14:12:21 +0000 Received: from relay2.suse.de (unknown [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 4CE46A5E9C; Tue, 29 Oct 2013 15:12:19 +0100 (CET) Date: Tue, 29 Oct 2013 14:41:00 -0000 From: Richard Biener To: Jakub Jelinek Cc: gcc-patches@gcc.gnu.org Subject: Re: [PATCH] Handle __builtin_unreachable () using assertions in VRP In-Reply-To: <20131029135401.GC30970@tucnak.zalov.cz> Message-ID: References: <20131025090640.GF30970@tucnak.zalov.cz> <20131029135401.GC30970@tucnak.zalov.cz> User-Agent: Alpine 2.00 (LNX 1167 2008-08-23) MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII X-SW-Source: 2013-10/txt/msg02414.txt.bz2 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 > > * 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: > + : > + ... > + if (something) > + goto ; > + else > + goto ; > + : > + __builtin_unreachable (); > + : */ > + > +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 ; > + 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 SUSE / SUSE Labs SUSE LINUX Products GmbH - Nuernberg - AG Nuernberg - HRB 16746 GF: Jeff Hawn, Jennifer Guild, Felix Imend