[Bug tree-optimization/59660] We fail to optimize common boolean checks pre-inlining

rguenth at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Thu Jan 9 09:52:00 GMT 2014


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59660

--- Comment #10 from Richard Biener <rguenth at gcc dot gnu.org> ---
(In reply to Jan Hubicka from comment #9)
> Hi,
> this patch solves the testcase.
> The first hunk gets rid of the redundant NOP_EXPR converting TRUTH_EXPR from
> INT to BOOL.  The second improves gimplifier to not introduce unnecesary
> control flow.
> 
> If this approach seems to make sense, I will extend it to other booleans and
> prepare less hackish patch.
> 
> Honza
> 
> Index: fold-const.c
> ===================================================================
> --- fold-const.c	(revision 206346)
> +++ fold-const.c	(working copy)
> @@ -1977,6 +1977,8 @@ fold_convert_loc (location_t loc, tree t
>  
>      case INTEGER_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE:
>      case OFFSET_TYPE:
> +      if (TREE_CODE (arg) == TRUTH_ORIF_EXPR)
> +	return fold_build2_loc (loc, TRUTH_ORIF_EXPR, type, TREE_OPERAND (arg, 0),
> TREE_OPERAND (arg, 1));
>        if (TREE_CODE (arg) == INTEGER_CST)
>  	{
>  	  tem = fold_convert_const (NOP_EXPR, type, arg);

This looks bogus.  See where we do this folding and instead handle it
there (I suspect gimple_boolify?)

> Index: gimplify.c
> ===================================================================
> --- gimplify.c	(revision 206346)
> +++ gimplify.c	(working copy)
> @@ -2931,14 +2931,37 @@ gimplify_cond_expr (tree *expr_p, gimple
>  	  result = build_simple_mem_ref_loc (loc, tmp);
>  	}
>  
> -      /* Build the new then clause, `tmp = then_;'.  But don't build the
> -	 assignment if the value is void; in C++ it can be if it's a throw.  */
> -      if (!VOID_TYPE_P (TREE_TYPE (then_)))
> -	TREE_OPERAND (expr, 1) = build2 (MODIFY_EXPR, type, tmp, then_);
> +      /* Convert (A||B) ? true : false
> +	 as A ? tmp = true : tmp = B != 0.  */

So does it end up working for if (a || b || c)?  Otherwise this looks
sensible to me.  (A&&B) ? true : false -> A ? tmp = B != 0 : tmp = false
then?

> -      /* Similarly, build the new else clause, `tmp = else_;'.  */
> -      if (!VOID_TYPE_P (TREE_TYPE (else_)))
> -	TREE_OPERAND (expr, 2) = build2 (MODIFY_EXPR, type, tmp, else_);
> +      if (integer_zerop (else_) && integer_onep (then_)
> +	  && TREE_CODE (TREE_OPERAND (expr, 0)) == TRUTH_ORIF_EXPR)
> +	{
> +	  tree pred = TREE_OPERAND (expr, 0);
> +	  location_t loc = EXPR_LOCATION (*expr_p);
> +	  TREE_OPERAND (expr, 0) = TREE_OPERAND (pred, 0);
> +	  /* Build the new then clause, `tmp = then_;'.  But don't build the
> +	     assignment if the value is void; in C++ it can be if it's a throw.  */
> +	  TREE_OPERAND (expr, 1) = build2 (MODIFY_EXPR, type, tmp,
> +					   fold_convert (type, boolean_true_node));
> +
> +	  /* Similarly, build the new else clause, `tmp = else_;'.  */
> +	  TREE_OPERAND (expr, 2) = build2 (MODIFY_EXPR, type, tmp,
> +					   fold_build2_loc (loc, NE_EXPR, type, TREE_OPERAND (pred, 1),
> +							    fold_convert (TREE_TYPE (TREE_OPERAND (pred, 1)),
> +									  integer_zero_node)));
> +	}
> +      else
> +	{
> +	  /* Build the new then clause, `tmp = then_;'.  But don't build the
> +	     assignment if the value is void; in C++ it can be if it's a throw.  */
> +	  if (!VOID_TYPE_P (TREE_TYPE (then_)))
> +	    TREE_OPERAND (expr, 1) = build2 (MODIFY_EXPR, type, tmp, then_);
> +
> +	  /* Similarly, build the new else clause, `tmp = else_;'.  */
> +	  if (!VOID_TYPE_P (TREE_TYPE (else_)))
> +	    TREE_OPERAND (expr, 2) = build2 (MODIFY_EXPR, type, tmp, else_);
> +	}
>  
>        TREE_TYPE (expr) = void_type_node;
>        recalculate_side_effects (expr);


More information about the Gcc-bugs mailing list