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

Attachment: pr113894.patch
Description: pr113894.patch

Reply via email to