GCC eliminates an integer-to-floating-point-to-integer conversion when the
intermediate floating-point type can represent every value of the input
integer type. This misses cases where it can represent every value of the
final integer type.
Extend the existing PR66211 folding pattern to use the final integer precision
as an alternative condition when -fno-trapping-math is enabled. Values in
range are represented exactly while out-of-range conversions are already
undefined or invalid, so removing the intermediate conversion is safe.
gcc/ChangeLog:
PR tree-optimization/98984
* match.pd: Fold integer-float-integer conversions when the
intermediate floating-point significand covers the final integer
precision under -fno-trapping-math.
gcc/testsuite/ChangeLog:
PR tree-optimization/98984
* gcc.dg/tree-ssa/pr98984.c: New test.
* gcc.dg/tree-ssa/pr98984-2.c: New test.
Signed-off-by: Naveen <[email protected]>
---
gcc/match.pd | 11 ++++---
gcc/testsuite/gcc.dg/tree-ssa/pr98984-2.c | 12 ++++++++
gcc/testsuite/gcc.dg/tree-ssa/pr98984.c | 37 +++++++++++++++++++++++
3 files changed, 56 insertions(+), 4 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr98984-2.c
create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr98984.c
diff --git a/gcc/match.pd b/gcc/match.pd
index 032f29dcbc2..35714360063 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -6045,12 +6045,15 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
/* If we are converting an integer to a floating-point that can
represent it exactly and back to an integer, we can skip the
- floating-point conversion. */
- (if (GIMPLE /* PR66211 */
+ floating-point conversion. PR66211, PR98984. */
+ (if (GIMPLE
&& inside_int && inter_float && final_int
&& ! is_vec
- && ((unsigned) significand_size (TYPE_MODE (inter_type))
- >= inside_prec - !inside_unsignedp))
+ && (((unsigned) significand_size (TYPE_MODE (inter_type))
+ >= inside_prec - !inside_unsignedp)
+ || (! flag_trapping_math
+ && ((unsigned) significand_size (TYPE_MODE (inter_type))
+ >= final_prec))))
(convert @0)))))))
/* (float_type)(integer_type) x -> trunc (x) if the type of x matches
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr98984-2.c
b/gcc/testsuite/gcc.dg/tree-ssa/pr98984-2.c
new file mode 100644
index 00000000000..caf882d11c1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr98984-2.c
@@ -0,0 +1,12 @@
+/* PR tree-optimization/98984 */
+/* { dg-do compile { target bitint } } */
+/* { dg-require-effective-target float32 } */
+/* { dg-options "-O2 -std=c23 -fno-trapping-math -fdump-tree-optimized" } */
+/* { dg-add-options float32 } */
+
+signed _BitInt(25)
+f (long long n)
+{
+ return (_Float32) n;
+}
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr98984.c
b/gcc/testsuite/gcc.dg/tree-ssa/pr98984.c
new file mode 100644
index 00000000000..51f84c9669b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr98984.c
@@ -0,0 +1,37 @@
+/* PR tree-optimization/98984 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-trapping-math -fdump-tree-optimized" } */
+
+
+signed char
+f1 (unsigned long long n)
+{
+ return (float)n;
+}
+
+signed char
+f2 (long long n)
+{
+ return (float)n;
+}
+
+unsigned char
+f3 (unsigned int n)
+{
+ return (float)n;
+}
+
+short
+f4 (unsigned long long n)
+{
+ return (float)n;
+}
+
+unsigned short
+f5 (unsigned long long n)
+{
+ return (double)n;
+}
+
+/* { dg-final { scan-tree-dump-not "\\(float\\)" "optimized" } } */
+/* { dg-final { scan-tree-dump-not "\\(double\\)" "optimized" } } */
--
2.34.1