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