[PATCH] middle-end: fix de-optimizations with bitclear patterns on signed values

Jakub Jelinek jakub@redhat.com
Wed Nov 3 14:20:45 GMT 2021


On Wed, Nov 03, 2021 at 10:56:30AM +0000, Tamar Christina wrote:
> The spaceship operator is looking for (res & 1) == res which was previously folded to (res & ~1) == 0.
> This is now being folded further to ((unsigned) res) <= 1.

Is that match.pd change already in the tree (which commit) or not yet?
> --- a/gcc/tree-ssa-phiopt.c
> +++ b/gcc/tree-ssa-phiopt.c
> @@ -2038,6 +2038,26 @@ spaceship_replacement (basic_block cond_bb, basic_block middle_bb,
>    gimple *orig_use_stmt = use_stmt;
>    tree orig_use_lhs = NULL_TREE;
>    int prec = TYPE_PRECISION (TREE_TYPE (phires));
> +
> +  /* Deal with if match.pd has rewritten the (res & ~1) == 0
> +     into res <= 1 and has left a type-cast for signed types.  */

The above sentence doesn't make sense gramatically.  Either
Deal with match.pd rewriting ... and leaving ... or
Deal with the case when match.pd ...
or something similar?

> +  if (gimple_assign_cast_p (use_stmt))
> +    {
> +      orig_use_lhs = gimple_assign_lhs (use_stmt);
> +      /* Match.pd would have only done this for a signed type,
> +	 so the conversion must be to an unsigned one.  */

Even at the start of sentence it should be match.pd, the file isn't
called Match.pd.

> +      if (!TYPE_UNSIGNED (TREE_TYPE (orig_use_lhs)))
> +	return false;
> +      if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (orig_use_lhs))
> +	return false;
> +      if (EDGE_COUNT (phi_bb->preds) != 4)
> +	return false;
> +      if (!TYPE_UNSIGNED (TREE_TYPE (orig_use_lhs)))
> +	return false;

You are testing !TYPE_UNSIGNED (TREE_TYPE (orig_use_lhs)) twice, did you
mean to instead test that it is a conversion from signed to unsigned
(i.e. test
      if (TYPE_UNSIGNED (TREE_TYPE (gimple_assign_rhs1 (use_stmt))))
	return false;
?  Also, shouldn't it also test that both types are integral and have the
same precision?

> +      if (!single_imm_use (orig_use_lhs, &use_p, &use_stmt))
> +	return false;
> +    }
> +
>    if (is_gimple_assign (use_stmt)
>        && gimple_assign_rhs_code (use_stmt) == BIT_AND_EXPR
>        && TREE_CODE (gimple_assign_rhs2 (use_stmt)) == INTEGER_CST
> @@ -2099,7 +2119,7 @@ spaceship_replacement (basic_block cond_bb, basic_block middle_bb,
>        || !tree_fits_shwi_p (rhs)
>        || !IN_RANGE (tree_to_shwi (rhs), -1, 1))
>      return false;
> -  if (orig_use_lhs)
> +  if (orig_use_lhs && !integer_onep (rhs))

This doesn't look safe.  orig_use_lhs in this case means
either that there was just a cast, or that there was BIT_AND_EXPR,
or that were both, and you don't know which one it is.
The decision shouldn't be done based on whether rhs is or isn't 1, but on
whether there was the BIT_AND or not.

>      {
>        if ((cmp != EQ_EXPR && cmp != NE_EXPR) || !integer_zerop (rhs))
>  	return false;
> @@ -2345,6 +2365,8 @@ spaceship_replacement (basic_block cond_bb, basic_block middle_bb,
>  	res_cmp = one_cmp == LT_EXPR ? GE_EXPR : LE_EXPR;
>        else if (integer_minus_onep (rhs))
>  	res_cmp = one_cmp == LT_EXPR ? GT_EXPR : LT_EXPR;
> +      else if (integer_onep (rhs))
> +	res_cmp = GE_EXPR;

And this one should be guarded on either the cast present or the comparison
done unsigned (so probably TYPE_UNSIGNED (TREE_TYPE (rhs)) && integer_onep (rhs))?

>        else
>  	return false;
>        break;
> @@ -2353,6 +2375,8 @@ spaceship_replacement (basic_block cond_bb, basic_block middle_bb,
>  	res_cmp = one_cmp == LT_EXPR ? LE_EXPR : GE_EXPR;
>        else if (integer_zerop (rhs))
>  	res_cmp = one_cmp;
> +      else if (integer_onep (rhs))
> +	res_cmp = one_cmp;
>        else
>  	return false;
>        break;

Likewise.

> @@ -2360,7 +2384,7 @@ spaceship_replacement (basic_block cond_bb, basic_block middle_bb,
>        if (integer_zerop (rhs))
>  	res_cmp = one_cmp == LT_EXPR ? LE_EXPR : GE_EXPR;
>        else if (integer_onep (rhs))
> -	res_cmp = one_cmp;
> +	res_cmp = LE_EXPR;
>        else
>  	return false;
>        break;

Are you sure?

	Jakub



More information about the Gcc-patches mailing list