https://gcc.gnu.org/g:c59bee6acb24a0d580f4c98a14e879452096220e

commit r17-3190-gc59bee6acb24a0d580f4c98a14e879452096220e
Author: Tudor-Stefan Magirescu <[email protected]>
Date:   Mon Aug 10 18:11:45 2026 +0200

    tree-optimization: Simplify ((X CMP1 Y) - (X CMP2 Y)) REL 0
    
    Add a new match.pd pattern to fold sign-of-difference expressions into
    a single comparison.  The pattern matches differences of two comparisons
    of the same operands, where the comparison pair is one of {gt,lt} or
    {ge,le}.
    
    The pattern cannot be merged into the generic (X - Y) CMP 0 rule
    above it, which is restricted to eq/ne.  Extending that rule to
    lt/le/gt/ge would defeat ABS_EXPR synthesis in
    fold_cond_expr_with_comparison for expressions of the form
    (X - Y) < 0 ? (Y - X) : (X - Y).  Matching the full comparison
    structure avoids this regression.
    
    Bootstrapped and tested on x86_64-linux-gnu.
    
    gcc/ChangeLog:
    
            * match.pd (((X CMP1 Y) - (X CMP2 Y)) REL 0): New pattern.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.c-torture/execute/subcmp-1.c: New test.
            * gcc.dg/tree-ssa/subcmp-1.c: New test.
    
    Signed-off-by: Tudor-Stefan Magirescu <[email protected]>

Diff:
---
 gcc/match.pd                                   |  15 +++
 gcc/testsuite/gcc.c-torture/execute/subcmp-1.c |  55 +++++++++++
 gcc/testsuite/gcc.dg/tree-ssa/subcmp-1.c       | 131 +++++++++++++++++++++++++
 3 files changed, 201 insertions(+)

diff --git a/gcc/match.pd b/gcc/match.pd
index 0ba97b32cb13..50e731770228 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -7599,6 +7599,21 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
    (if (single_use (@2))
     (cmp @0 @1)))))
 
+/* Fold ((X CMP1 Y) - (X CMP2 Y)) REL 0 into a single comparison of X and Y,
+   e.g., ((X > Y) - (X < Y)) < 0 to X < Y.  This cannot be merged into the
+   generic X - Y CMP 0 rule above as it would prevent ABS_EXPR synthesis in
+   fold_cond_expr_with_comparison.  */
+(for rel (lt le gt ge)
+ (for cmp1 (gt ge)
+      cmp2 (lt le)
+  (simplify
+   (rel (minus@2 (convert? (cmp1:c @0 @1))
+                (convert? (cmp2:c @0 @1))) integer_zerop)
+    (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+        && !TYPE_UNSIGNED (TREE_TYPE (@2))
+        && TYPE_PRECISION (TREE_TYPE (@2)) > 1)
+     (rel @0 @1)))))
+
 /* Simplify (x < 0) ^ (y < 0) to (x ^ y) < 0 and
    (x >= 0) ^ (y >= 0) to (x ^ y) < 0.  */
 (for cmp (lt ge)
diff --git a/gcc/testsuite/gcc.c-torture/execute/subcmp-1.c 
b/gcc/testsuite/gcc.c-torture/execute/subcmp-1.c
new file mode 100644
index 000000000000..4682246c3552
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/subcmp-1.c
@@ -0,0 +1,55 @@
+#define func(vol, op1, op2, op3)       \
+_Bool op1##_##op2##_##op3##_##vol (int a, int b)       \
+{                                      \
+ vol _Bool x = op_##op1(a, b);         \
+ vol _Bool y = op_##op2(a, b);         \
+ return op_##op3(x - y, 0);            \
+}
+
+#define op_lt(a, b) ((a) < (b))
+#define op_le(a, b) ((a) <= (b))
+#define op_gt(a, b) ((a) > (b))
+#define op_ge(a, b) ((a) >= (b))
+
+#define funcs(a) \
+ a(gt,lt,lt) \
+ a(gt,lt,le) \
+ a(gt,lt,gt) \
+ a(gt,lt,ge) \
+  \
+ a(ge,le,lt) \
+ a(ge,le,le) \
+ a(ge,le,gt) \
+ a(ge,le,ge) \
+  \
+ a(lt,gt,lt) \
+ a(lt,gt,le) \
+ a(lt,gt,gt) \
+ a(lt,gt,ge) \
+  \
+ a(le,ge,lt) \
+ a(le,ge,le) \
+ a(le,ge,gt) \
+ a(le,ge,ge) \
+
+#define funcs1(a,b,c) \
+func(,a,b,c) \
+func(volatile,a,b,c)
+
+funcs(funcs1)
+
+#define test(op1,op2,op3)                      \
+do {                                           \
+  if (op1##_##op2##_##op3##_(x,y)              \
+      != op1##_##op2##_##op3##_volatile(x,y))  \
+    __builtin_abort();                         \
+} while(0);
+
+int main()
+{
+  for(int x = -10; x < 10; x++)
+    for(int y = -10; y < 10; y++)
+    {
+        funcs(test)
+    }
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/subcmp-1.c 
b/gcc/testsuite/gcc.dg/tree-ssa/subcmp-1.c
new file mode 100644
index 000000000000..489cf4c1f406
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/subcmp-1.c
@@ -0,0 +1,131 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+_Bool subgtlt_lt(int a00, int b00)
+{
+  _Bool x00 = a00 > b00;
+  _Bool y00 = a00 < b00;
+  return x00 - y00 < 0;
+}
+/* { dg-final { scan-tree-dump "a00_\[0-9\]+.D. < 
b00_\[0-9\]+.D.|b00_\[0-9\]+.D. > a00_\[0-9\]+.D." "optimized" } } */
+
+_Bool subgtlt_le(int a01, int b01)
+{
+  _Bool x01 = a01 > b01;
+  _Bool y01 = a01 < b01;
+  return x01 - y01 <= 0;
+}
+/* { dg-final { scan-tree-dump "a01_\[0-9\]+.D. <= 
b01_\[0-9\]+.D.|b01_\[0-9\]+.D. >= a01_\[0-9\]+.D." "optimized" } } */
+
+_Bool subgtlt_gt(int a02, int b02)
+{
+  _Bool x02 = a02 > b02;
+  _Bool y02 = a02 < b02;
+  return x02 - y02 > 0;
+}
+/* { dg-final { scan-tree-dump "a02_\[0-9\]+.D. > 
b02_\[0-9\]+.D.|b02_\[0-9\]+.D. < a02_\[0-9\]+.D." "optimized" } } */
+
+_Bool subgtlt_ge(int a03, int b03)
+{
+  _Bool x03 = a03 > b03;
+  _Bool y03 = a03 < b03;
+  return x03 - y03 >= 0;
+}
+/* { dg-final { scan-tree-dump "a03_\[0-9\]+.D. >= 
b03_\[0-9\]+.D.|b03_\[0-9\]+.D. <= a03_\[0-9\]+.D." "optimized" } } */
+
+_Bool subgele_lt(int a04, int b04)
+{
+  _Bool x04 = a04 >= b04;
+  _Bool y04 = a04 <= b04;
+  return x04 - y04 < 0;
+}
+/* { dg-final { scan-tree-dump "a04_\[0-9\]+.D. < 
b04_\[0-9\]+.D.|b04_\[0-9\]+.D. > a04_\[0-9\]+.D." "optimized" } } */
+
+_Bool subgele_le(int a05, int b05)
+{
+  _Bool x05 = a05 >= b05;
+  _Bool y05 = a05 <= b05;
+  return x05 - y05 <= 0;
+}
+/* { dg-final { scan-tree-dump "a05_\[0-9\]+.D. <= 
b05_\[0-9\]+.D.|b05_\[0-9\]+.D. >= a05_\[0-9\]+.D." "optimized" } } */
+
+_Bool subgele_gt(int a06, int b06)
+{
+  _Bool x06 = a06 >= b06;
+  _Bool y06 = a06 <= b06;
+  return x06 - y06 > 0;
+}
+/* { dg-final { scan-tree-dump "a06_\[0-9\]+.D. > 
b06_\[0-9\]+.D.|b06_\[0-9\]+.D. < a06_\[0-9\]+.D." "optimized" } } */
+
+_Bool subgele_ge(int a07, int b07)
+{
+  _Bool x07 = a07 >= b07;
+  _Bool y07 = a07 <= b07;
+  return x07 - y07 >= 0;
+}
+/* { dg-final { scan-tree-dump "a07_\[0-9\]+.D. >= 
b07_\[0-9\]+.D.|b07_\[0-9\]+.D. <= a07_\[0-9\]+.D." "optimized" } } */
+
+_Bool subltgt_lt(int a08, int b08)
+{
+  _Bool x08 = a08 < b08;
+  _Bool y08 = a08 > b08;
+  return x08 - y08 < 0;
+}
+/* { dg-final { scan-tree-dump "a08_\[0-9\]+.D. > 
b08_\[0-9\]+.D.|b08_\[0-9\]+.D. < a08_\[0-9\]+.D." "optimized" } } */
+
+_Bool subltgt_le(int a09, int b09)
+{
+  _Bool x09 = a09 < b09;
+  _Bool y09 = a09 > b09;
+  return x09 - y09 <= 0;
+}
+/* { dg-final { scan-tree-dump "a09_\[0-9\]+.D. >= 
b09_\[0-9\]+.D.|b09_\[0-9\]+.D. <= a09_\[0-9\]+.D." "optimized" } } */
+
+_Bool subltgt_gt(int a10, int b10)
+{
+  _Bool x10 = a10 < b10;
+  _Bool y10 = a10 > b10;
+  return x10 - y10 > 0;
+}
+/* { dg-final { scan-tree-dump "a10_\[0-9\]+.D. < 
b10_\[0-9\]+.D.|b10_\[0-9\]+.D. > a10_\[0-9\]+.D." "optimized" } } */
+
+_Bool subltgt_ge(int a11, int b11)
+{
+  _Bool x11 = a11 < b11;
+  _Bool y11 = a11 > b11;
+  return x11 - y11 >= 0;
+}
+/* { dg-final { scan-tree-dump "a11_\[0-9\]+.D. <= 
b11_\[0-9\]+.D.|b11_\[0-9\]+.D. >= a11_\[0-9\]+.D." "optimized" } } */
+
+_Bool sublege_lt(int a12, int b12)
+{
+  _Bool x12 = a12 <= b12;
+  _Bool y12 = a12 >= b12;
+  return x12 - y12 < 0;
+}
+/* { dg-final { scan-tree-dump "a12_\[0-9\]+.D. > 
b12_\[0-9\]+.D.|b12_\[0-9\]+.D. < a12_\[0-9\]+.D." "optimized" } } */
+
+_Bool sublege_le(int a13, int b13)
+{
+  _Bool x13 = a13 <= b13;
+  _Bool y13 = a13 >= b13;
+  return x13 - y13 <= 0;
+}
+/* { dg-final { scan-tree-dump "a13_\[0-9\]+.D. >= 
b13_\[0-9\]+.D.|b13_\[0-9\]+.D. <= a13_\[0-9\]+.D." "optimized" } } */
+
+_Bool sublege_gt(int a14, int b14)
+{
+  _Bool x14 = a14 <= b14;
+  _Bool y14 = a14 >= b14;
+  return x14 - y14 > 0;
+}
+/* { dg-final { scan-tree-dump "a14_\[0-9\]+.D. < 
b14_\[0-9\]+.D.|b14_\[0-9\]+.D. > a14_\[0-9\]+.D." "optimized" } } */
+
+_Bool sublege_ge(int a15, int b15)
+{
+  _Bool x15 = a15 <= b15;
+  _Bool y15 = a15 >= b15;
+  return x15 - y15 >= 0;
+}
+/* { dg-final { scan-tree-dump "a15_\[0-9\]+.D. <= 
b15_\[0-9\]+.D.|b15_\[0-9\]+.D. >= a15_\[0-9\]+.D." "optimized" } } */
+/* { dg-final { scan-tree-dump-not "_\[0-9\]+ - _\[0-9\]+" "optimized" } } */

Reply via email to