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

Reply via email to