(float)a - (float)b -> (float)((signed_wider)a - (signed_wider)b) when
a and b are the same integer type exactly representable in the float
type.  Uses a signed type one bit wider than the operand type to hold
the full mathematical difference without overflow.

        PR tree-optimization/124571

gcc/ChangeLog:

        * match.pd ((float)a - (float)b -> (float)(signed)(a - b)): New pattern.

gcc/testsuite/ChangeLog:

        * gcc.dg/tree-ssa/pr124571.c: New test.

Signed-off-by: Eikansh Gupta <[email protected]>
---
 gcc/match.pd                             | 15 +++++++++++++
 gcc/testsuite/gcc.dg/tree-ssa/pr124571.c | 28 ++++++++++++++++++++++++
 2 files changed, 43 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr124571.c

diff --git a/gcc/match.pd b/gcc/match.pd
index 7db8ce7580f..4cb0cf4bece 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -2112,6 +2112,21 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
   (if (!flag_trapping_math)
    (abs @0))))
 
+/* (float)a - (float)b -> (float)(signed)(a - b) */
+(simplify
+ (minus (float @0) (float @1))
+ (if (!DECIMAL_FLOAT_TYPE_P (type)
+      && INTEGRAL_TYPE_P (TREE_TYPE (@0))
+      && types_compatible_p (TREE_TYPE (@0), TREE_TYPE (@1)))
+  (with
+   {
+     tree stype = build_nonstandard_integer_type
+                   (TYPE_PRECISION (TREE_TYPE (@0)) + 1, 0);
+     format_helper fmt (REAL_MODE_FORMAT (TYPE_MODE (type)));
+   }
+   (if (fmt.can_represent_integral_type_p (stype))
+    (float (minus (convert:stype @0) (convert:stype @1)))))))
+
 (simplify
  (absu (negate @0))
  (absu @0))
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr124571.c 
b/gcc/testsuite/gcc.dg/tree-ssa/pr124571.c
new file mode 100644
index 00000000000..4827549bbec
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr124571.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+/* The two separate float casts must be gone; only one remains.  */
+float f1 (unsigned short a, unsigned short b)
+{
+  return (float)a - (float)b;
+}
+
+float f2 (short a, short b)
+{
+  return (float)a - (float)b;
+}
+
+double f3 (unsigned short a, unsigned short b)
+{
+  return (double)a - (double)b;
+}
+
+double f4 (int a, int b)
+{
+  return (double)a - (double)b;
+}
+
+/* { dg-final { scan-tree-dump-not "(float) a" "optimized" } } */
+/* { dg-final { scan-tree-dump-not "(float) b" "optimized" } } */
+/* { dg-final { scan-tree-dump-not "(double) a" "optimized" } } */
+/* { dg-final { scan-tree-dump-not "(double) b" "optimized" } } */
-- 
2.34.1


>From a678afce7b931a937b779a33e5f6109637d5ea96 Mon Sep 17 00:00:00 2001
From: Eikansh Gupta <[email protected]>
Date: Wed, 6 May 2026 18:21:03 +0530
Subject: [PATCH 2/3] MATCH: Simplify abs((float)a) -> (float)abs(a) [PR124571]

abs((float)a) -> (float)abs(a) when a is an integer exactly
representable in the float type.

        PR tree-optimization/124571

gcc/ChangeLog:

        * match.pd (abs((float)a) -> (float)abs(a)): New pattern.

gcc/testsuite/ChangeLog:

        * gcc.dg/tree-ssa/pr124571-1.c: New test.

Signed-off-by: Eikansh Gupta <[email protected]>
---
 gcc/match.pd                               | 14 ++++++++++++++
 gcc/testsuite/gcc.dg/tree-ssa/pr124571-1.c | 15 +++++++++++++++
 2 files changed, 29 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr124571-1.c

diff --git a/gcc/match.pd b/gcc/match.pd
index 4cb0cf4bece..02479af9dc1 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -2127,6 +2127,20 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
    (if (fmt.can_represent_integral_type_p (stype))
     (float (minus (convert:stype @0) (convert:stype @1)))))))
 
+/* abs((float)a) -> (float)abs(a) */
+(simplify
+ (abs (float @0))
+ (if (!DECIMAL_FLOAT_TYPE_P (type)
+      && INTEGRAL_TYPE_P (TREE_TYPE (@0)))
+  (with
+   {
+     tree stype = build_nonstandard_integer_type
+                   (TYPE_PRECISION (TREE_TYPE (@0)) + 1, 0);
+     format_helper fmt (REAL_MODE_FORMAT (TYPE_MODE (type)));
+   }
+   (if (fmt.can_represent_integral_type_p (stype))
+    (float (abs (convert:stype @0)))))))
+
 (simplify
  (absu (negate @0))
  (absu @0))
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr124571-1.c 
b/gcc/testsuite/gcc.dg/tree-ssa/pr124571-1.c
new file mode 100644
index 00000000000..6cc82c4faea
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr124571-1.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+/* abs((float)a) < 1.0f folds to a == 0.  */
+int f1 (short a)
+{
+  return __builtin_fabsf ((float)a) < 1.0f;
+}
+
+int f2 (short a)
+{
+  return __builtin_fabs ((double)a) < 1.0;
+}
+
+/* { dg-final { scan-tree-dump-not "ABS_EXPR" "optimized" } } */
-- 
2.34.1


>From e293f8dc88d64556bfa203a1f2e4ce34a42e3074 Mon Sep 17 00:00:00 2001
From: Eikansh Gupta <[email protected]>
Date: Wed, 6 May 2026 18:25:23 +0530
Subject: [PATCH 3/3] testsuite: Add combined minus+abs test for PR124571

        PR tree-optimization/124571

gcc/testsuite/ChangeLog:

        * gcc.dg/tree-ssa/pr124571-2.c: New test.

Signed-off-by: Eikansh Gupta <[email protected]>
---
 gcc/testsuite/gcc.dg/tree-ssa/pr124571-2.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr124571-2.c

diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr124571-2.c 
b/gcc/testsuite/gcc.dg/tree-ssa/pr124571-2.c
new file mode 100644
index 00000000000..bf75ad06424
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr124571-2.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+int f1 (unsigned short a, unsigned short b)
+{
+  float s = __builtin_fabsf ((float)a - (float)b);
+  return s < 1.0f;
+}
+
+int f2 (short a, short b)
+{
+  float s = __builtin_fabsf ((float)a - (float)b);
+  return s < 1.0f;
+}
+
+int f4 (unsigned short a, unsigned short b)
+{
+  double s = __builtin_fabs ((double)a - (double)b);
+  return s < 1.0;
+}
+
+/* { dg-final { scan-tree-dump-not "ABS_EXPR" "optimized" } } */
-- 
2.34.1

Reply via email to