Re: [PATCH] MATCH: Fold `A CMP B ? A - B : B - A` to abs of difference [PR50856]

Jeffrey Law <[email protected]> Wed, 5 Aug 2026 16:52:29 -0600
Newsgroups gmane.comp.gcc.patches
Message-ID <[email protected]>

On 7/28/2026 4:31 AM, Eikansh Gupta wrote:
> Recognize the absolute-difference idiom whose selector compares the
> operands directly (a > b ? a - b : b - a), optionally widened, as
> +/- abs (A - B).
>
> The same-width case is not folded under -fsanitize=signed-integer-overflow
> so the rewrite does not move the overflow the sanitizer reports.
>
> 	PR tree-optimization/50856
>
> gcc/ChangeLog:
>
> 	* match.pd (A CMP B ? A - B : B - A -> +/- abs (A - B)): New
> 	patterns.
>
> gcc/testsuite/ChangeLog:
>
> 	* gcc.dg/tree-ssa/pr50856.c: New test.
> 	* g++.target/aarch64/pr50856.C: New test.
>
> Signed-off-by: Eikansh Gupta <[email protected]>
So a high level note.  I marked pr50856 as something that looked like 
the resulting code could be improved for RISC-V (it's a personal tag, so 
no way for you to have seen that marking when looking at the PR).  So 
you might consider looking at the RISC-V code before/after as well.  
Certainly not required though.


> ---
>   gcc/match.pd                               | 33 +++++++++++++++++
>   gcc/testsuite/g++.target/aarch64/pr50856.C | 26 ++++++++++++++
>   gcc/testsuite/gcc.dg/tree-ssa/pr50856.c    | 41 ++++++++++++++++++++++
>   3 files changed, 100 insertions(+)
>   create mode 100644 gcc/testsuite/g++.target/aarch64/pr50856.C
>   create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr50856.c
>
> diff --git a/gcc/match.pd b/gcc/match.pd
> index a7cec25dbad..7f480e43f7b 100644
> --- a/gcc/match.pd
> +++ b/gcc/match.pd
> @@ -7154,6 +7154,39 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
>         (convert (negate (absu:utype @0))))
>         (negate (abs @0)))))
>    )
> + /* A >/>= B ? A - B : B - A -> abs (A - B)
> +    with the operands optionally widened first.  */
> + (for cmp (gt ge)
> +  (simplify
> +   (cnd (cmp @0 @1)
> +	(minus@4 (convert1?@2 @0) (convert2?@3 @1))
> +	(minus @3 @2))
> +   (if (ANY_INTEGRAL_TYPE_P (type)
> +	&& !TYPE_UNSIGNED (type)
> +	&& types_match (TREE_TYPE (@0), TREE_TYPE (@1))
> +	&& (element_precision (@0) < element_precision (type)
> +	    || (types_match (TREE_TYPE (@0), type)
> +		&& TYPE_OVERFLOW_UNDEFINED (type)
> +		/* Hoisting A - B out of the selector could move the
> +		   overflow the sanitizer reports.  */
> +		&& !sanitize_flags_p (SANITIZE_SI_OVERFLOW)))
> +	&& (!VECTOR_TYPE_P (type)
> +	    || target_supports_op_p (type, ABS_EXPR, optab_vector)))
> +    (abs @4))))
> + /* A </<= B ? A - B : B - A -> -abs (A - B).  Widened operands only.  */
> + (for cmp (lt le)
> +  (simplify
> +   (cnd (cmp @0 @1)
> +	(minus@4 (convert1?@2 @0) (convert2?@3 @1))
> +	(minus @3 @2))
> +   (if (ANY_INTEGRAL_TYPE_P (type)
> +	&& !TYPE_UNSIGNED (type)
> +	&& types_match (TREE_TYPE (@0), TREE_TYPE (@1))
> +	&& element_precision (@0) < element_precision (type)
> +	&& (!VECTOR_TYPE_P (type)
> +	    || (target_supports_op_p (type, ABS_EXPR, optab_vector)
> +		&& target_supports_op_p (type, NEGATE_EXPR, optab_vector))))
> +    (negate (abs @4)))))
>   )
>   
>
So the first pattern has a more complex condition that allows when the 
precision of @0 is less than @1 *or* when certain other conditions 
hold.  But the second pattern doesn't test those additional conditions.  
Is that intentional?  If so, it would be worth a comment why.

Generally OK, so just trying to nail down the corner cases.

jeff