[1/3] MATCH: Simplify (float)a - (float)b -> (float)(signed)(a - b) [PR124571]

Message ID 20260506130303.417324-1-eikansh.gupta@oss.qualcomm.com
State New
Headers
Series [1/3] MATCH: Simplify (float)a - (float)b -> (float)(signed)(a - b) [PR124571] |

Commit Message

Eikansh Gupta May 6, 2026, 1:03 p.m. UTC
  (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 <eikansh.gupta@oss.qualcomm.com>
---
 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
  

Comments

Richard Biener May 6, 2026, 1:37 p.m. UTC | #1
On Wed, May 6, 2026 at 3:10 PM Eikansh Gupta
<eikansh.gupta@oss.qualcomm.com> wrote:
>
> (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 <eikansh.gupta@oss.qualcomm.com>
> ---
>  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)))))))

Mostly OK.  Do we need to consider sfloat<stype> to be not supported but
sfloat<typeof (@0)> supported?  That said, you are building (and using)
a bit-precision integer type, I think you want to use an integer type
twice as wide for the convert and the minus?

> +
>  (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 <eikansh.gupta@oss.qualcomm.com>
> 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 <eikansh.gupta@oss.qualcomm.com>
> ---
>  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 <eikansh.gupta@oss.qualcomm.com>
> 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 <eikansh.gupta@oss.qualcomm.com>
> ---
>  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
>
  

Patch

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 <eikansh.gupta@oss.qualcomm.com>
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 <eikansh.gupta@oss.qualcomm.com>
---
 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 <eikansh.gupta@oss.qualcomm.com>
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 <eikansh.gupta@oss.qualcomm.com>
---
 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" } } */