Hi Jeff, Sorry about that, Outlook turned the attachment into a OneDrive link. Here is the patch inline and also attached as plain file.
On the RISC-V point, thanks, that makes sense. My intent is for the middle-end transform to expose the conditional negate / ABS semantics and leave target expansion/combine to recover the preferred form where that is better. From 81b2690e383b37222954225198f8895a370e45c0 Mon Sep 17 00:00:00 2001 From: Odysseas Georgoudis <[email protected]> Date: Wed, 1 Jul 2026 02:43:49 +0100 Subject: [PATCH v1] match.pd: Recognize branchless conditional negate [PR113894] This patch teaches match.pd to recognize the branchless conditional negate idiom (x ^ -cmp) + cmp when cmp is known to be zero or one. The expression is folded to a conditional negate form. For the sign-test spelling based on x < 0, the patch exposes ABS_EXPR. PR tree-optimization/113894 gcc/ChangeLog: * match.pd: Add simplifications for branchless conditional negate and sign-test absolute value idioms. gcc/testsuite/ChangeLog: * gcc.dg/tree-ssa/pr113894.c: New test. Signed-off-by: Odysseas Georgoudis <[email protected]> --- gcc/match.pd | 15 ++++++ gcc/testsuite/gcc.dg/tree-ssa/pr113894.c | 60 ++++++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr113894.c diff --git a/gcc/match.pd b/gcc/match.pd index ddf3b61638c..70d7f3a8733 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -236,6 +236,13 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) && !TYPE_UNSIGNED (TREE_TYPE (@0))) (abs @0))) +/* (X ^ -(X < 0)) + (X < 0) -> abs (X) */ +(simplify + (plus:c (bit_xor:c @0 (negate (convert@1 (lt @0 integer_zerop)))) @1) + (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) + && !TYPE_UNSIGNED (TREE_TYPE (@0))) + (abs @0))) + /* Following match patterns are used by the match_spaceship function to detect all possible spaceship combinations. */ #if GIMPLE @@ -4793,6 +4800,14 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) && (GIMPLE || !TREE_SIDE_EFFECTS (@1))) (cond (convert:boolean_type_node @2) @1 @0))) +/* Transform (A ^ -cmp) + cmp into cmp ? -A : A. */ +(simplify + (plus:c (bit_xor:c @0 (negate zero_one_valued_p@1)) @1) + (if (INTEGRAL_TYPE_P (type) + && !TYPE_SATURATING (type) + && (GIMPLE || !TREE_SIDE_EFFECTS (@0))) + (cond (convert:boolean_type_node @1) (negate @0) @0))) + /* Transform A & (B*cmp) into (A&B)*cmp. */ (simplify (bit_and:c (mult:cs zero_one_valued_p@0 @1) @2) diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr113894.c b/gcc/testsuite/gcc.dg/tree-ssa/pr113894.c new file mode 100644 index 00000000000..04aded67582 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr113894.c @@ -0,0 +1,60 @@ +/* PR tree-optimization/113894 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +int f_cmp_lt(int x, int y) +{ + int cmp = x < y; + return (x ^ -cmp) + cmp; +} + +int f_cmp_gt_commuted(int x, int y) +{ + int cmp = x > y; + return cmp + (-cmp ^ x); +} + +unsigned f_unsigned_cmp(unsigned x, unsigned y) +{ + unsigned cmp = x < y; + return (x ^ -cmp) + cmp; +} + +int f_mask(int x, unsigned y) +{ + int cmp = y & 1; + return (x ^ -cmp) + cmp; +} + +int f_bool(int x, _Bool cmp) +{ + return (x ^ -(int) cmp) + (int) cmp; +} + +int f_abs_int(int x) +{ + int cmp = x < 0; + return (x ^ -cmp) + cmp; +} + +long f_abs_long(long x) +{ + long cmp = x < 0; + return (x ^ -cmp) + cmp; +} + +int f_signed_not_zero_one(int x, int cmp) +{ + return (x ^ -cmp) + cmp; +} + +unsigned f_unsigned_not_zero_one(unsigned x, unsigned cmp) +{ + return (x ^ -cmp) + cmp; +} + +/* The branchless conditional negate spelling should only survive when cmp is + not known to be 0 or 1. */ +/* { dg-final { scan-tree-dump-times " \\^ " 2 "optimized" } } */ +/* Sign tests should expose absolute value. */ +/* { dg-final { scan-tree-dump-times " = ABS_EXPR" 2 "optimized" } } */ -- 2.43.5 ________________________________ From: Jeffrey Law <[email protected]> Sent: 10 July 2026 02:21 To: Odysseas Georgoudis <[email protected]>; [email protected] <[email protected]> Cc: Andrew Pinski <[email protected]> Subject: Re: [PATCH] match.pd: Recognize branchless conditional negate [PR113894] On 6/30/2026 8:07 PM, Odysseas Georgoudis wrote: > This patch teaches match.pd to recognize the branchless conditional > negate idiom > > (x ^ -cmp) + cmp > > when cmp is known to be zero or one. The expression is folded to a > conditional negate form. For the sign-test spelling based on x < 0, > the patch exposes ABS_EXPR. > > I could not comment on the PR because my GCC Bugzilla account is still > pending, so I am sending the patch here. > > Bootstrapped on x86_64-pc-linux-gnu. Tested with > gcc.dg/tree-ssa/tree-ssa.exp and the new gcc.dg/tree-ssa/pr113894.c > testcase. > > I do not have commit access. > > pr113894.patch > <https://1drv.ms/u/c/5a41b3fa58bb8071/IQAXsKqhUTaaQb_gOXEu4L8RAXgQUmxYo5d_eBzRtnqcKSI> Can you include the patch in your message. It looks like the link goes to onedrive and I suspect many folks aren't going to want to do that. Interestingly enough the (x ^ -cmp) + cmp form is probably optimal on RISC-V, so hopefully even after your match.pd change we'll still be able to recover optimal form across different designs. jeff
pr113894.patch
Description: pr113894.patch
