(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