On 7/10/2026 6:44 AM, Richard Biener wrote:
On Fri, Jul 10, 2026 at 8:32 AM Odysseas Georgoudis <[email protected]> wrote:
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)))
Both forms invoke UB for -INT_MIN, so OK I guess. But does this not
also require !TYPE_SATURATING?
I thought so too (it's on my mind due to Kael's patches) and the LLM
evaluation flagged it as-well. But I haven't come up with a value where
the transformation doesn't hold. The most interesting value would be
INT_MIN, but the original and converted both produce INT_MAX for that on
saturating types.
Given this pattern can match in the GENERIC context, do we have to worry
about dropping side effects? The original would reference X 3 times
whereas the result only references once for that abs pattern.
Kind of like Kael's recent patches, testing an earlier dump would
potentially make the test more robust.
So I think we need a V2.
Jeff