[llvm] [GlobalISel] Avoid constant folding of different FP types in FCMP (PR #171878)

Joel Fuentes via llvm-commits llvm-commits at lists.llvm.org
Mon Dec 15 10:51:13 PST 2025


https://github.com/jfuentes updated https://github.com/llvm/llvm-project/pull/171878

>From 920654b9059cc3fbb30f9e64882afab80c7d40c3 Mon Sep 17 00:00:00 2001
From: Joel Fuentes <joel.fuentes at intel.com>
Date: Thu, 11 Dec 2025 09:41:49 -0800
Subject: [PATCH 1/2] [InstCombine] Avoid constant folding of different FP
 types in FCMP

The instruction combine ``canonicalize_fcmp`` tries to fold constant
values in fcmp, however, it fails when the source defs have different
FP types. This occurs because it uses
``getFConstantVRegValWithLookThrough`` to get the constants value def, even
through trunc, zext, or sext.

This fix avoids the compiler to crash while a final solution is
implemented, e.g. use the constant value after trunc/zext/sext for
the constant folding.

Related to #171856
---
 .../GlobalISel/CombinerHelperCompares.cpp       |  3 +++
 .../GlobalISel/combine-cannonicalize-fcmp.mir   | 17 +++++++++++++++++
 2 files changed, 20 insertions(+)

diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelperCompares.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelperCompares.cpp
index fc40533cf3dc9..764199ee4a27f 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelperCompares.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelperCompares.cpp
@@ -74,6 +74,9 @@ bool CombinerHelper::constantFoldFCmp(const GFCmp &FCmp,
   APFloat LHS = LHSCst.getScalarValue();
   APFloat RHS = RHSCst.getScalarValue();
 
+  if (&LHS.getSemantics() != &RHS.getSemantics())
+    return false;
+
   bool Result = FCmpInst::compare(LHS, RHS, Pred);
 
   MatchInfo = [=](MachineIRBuilder &B) {
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-cannonicalize-fcmp.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-cannonicalize-fcmp.mir
index 94204611095db..d68eda67d2b80 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-cannonicalize-fcmp.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-cannonicalize-fcmp.mir
@@ -117,3 +117,20 @@ body:             |
     %res:_(s32) = afn G_FCMP floatpred(oge), %lhs(s64), %rhs
     $w0 = COPY %res(s32)
 ...
+---
+name:            test_fcmp_no_same_semantics
+body:             |
+  bb.1:
+    ; CHECK-LABEL: name: test_fcmp_no_same_semantics
+    ; CHECK: %lhs:_(s64) = G_FCONSTANT double 0x5D3B0B8040DF92C9
+    ; CHECK-NEXT: %trunc:_(s32) = G_TRUNC %lhs(s64)
+    ; CHECK-NEXT: %rhs:_(s32) = G_FCONSTANT float 0x3E6BBDE420000000
+    ; CHECK-NEXT: %res:_(s32) = G_FCMP floatpred(oge), %trunc(s32), %rhs
+    ; CHECK-NEXT: $w0 = COPY %res(s32)
+    %lhs:_(s64) = G_FCONSTANT double 0x5D3B0B8040DF92C9
+    %fabs:_(s64) = G_FABS %lhs
+    %trunc:_(s32) = G_TRUNC %fabs(s64)
+    %rhs:_(s32) = G_FCONSTANT float 0x3E6BBDE420000000
+    %res:_(s32) = G_FCMP floatpred(oge), %trunc(s32), %rhs
+    $w0 = COPY %res(s32)
+...

>From c1236bcf15ca9c2a8e878479df938906b95dac89 Mon Sep 17 00:00:00 2001
From: Joel Fuentes <joel.fuentes at intel.com>
Date: Mon, 15 Dec 2025 10:49:19 -0800
Subject: [PATCH 2/2] Re-create float after interpret bits for constant folding

---
 llvm/lib/CodeGen/GlobalISel/Utils.cpp         | 20 +++++++++++++++++--
 .../GlobalISel/combine-cannonicalize-fcmp.mir |  9 +++------
 2 files changed, 21 insertions(+), 8 deletions(-)

diff --git a/llvm/lib/CodeGen/GlobalISel/Utils.cpp b/llvm/lib/CodeGen/GlobalISel/Utils.cpp
index 15e81f5773b69..df438a79fd5e6 100644
--- a/llvm/lib/CodeGen/GlobalISel/Utils.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/Utils.cpp
@@ -452,8 +452,24 @@ std::optional<FPValueAndVReg> llvm::getFConstantVRegValWithLookThrough(
           VReg, MRI, LookThroughInstrs);
   if (!Reg)
     return std::nullopt;
-  return FPValueAndVReg{getConstantFPVRegVal(Reg->VReg, MRI)->getValueAPF(),
-                        Reg->VReg};
+
+  auto getFloatSemantics = [](unsigned BitWidth) -> const llvm::fltSemantics & {
+    switch (BitWidth) {
+    default:
+      llvm_unreachable("Unsupported floating-point semantics!");
+    case 16:
+      return APFloat::IEEEhalf();
+    case 32:
+      return APFloat::IEEEsingle();
+    case 64:
+      return APFloat::IEEEdouble();
+    case 128:
+      return APFloat::IEEEquad();
+    }
+  };
+
+  APFloat FloatVal(getFloatSemantics(Reg->Value.getBitWidth()), Reg->Value);
+  return FPValueAndVReg{FloatVal, Reg->VReg};
 }
 
 const ConstantFP *
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-cannonicalize-fcmp.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-cannonicalize-fcmp.mir
index d68eda67d2b80..8c9885ef37934 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-cannonicalize-fcmp.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-cannonicalize-fcmp.mir
@@ -122,15 +122,12 @@ name:            test_fcmp_no_same_semantics
 body:             |
   bb.1:
     ; CHECK-LABEL: name: test_fcmp_no_same_semantics
-    ; CHECK: %lhs:_(s64) = G_FCONSTANT double 0x5D3B0B8040DF92C9
-    ; CHECK-NEXT: %trunc:_(s32) = G_TRUNC %lhs(s64)
-    ; CHECK-NEXT: %rhs:_(s32) = G_FCONSTANT float 0x3E6BBDE420000000
-    ; CHECK-NEXT: %res:_(s32) = G_FCMP floatpred(oge), %trunc(s32), %rhs
+    ; CHECK: %res:_(s32) = G_CONSTANT i32 0
     ; CHECK-NEXT: $w0 = COPY %res(s32)
-    %lhs:_(s64) = G_FCONSTANT double 0x5D3B0B8040DF92C9
+    %lhs:_(s64) = G_FCONSTANT double 2.0
     %fabs:_(s64) = G_FABS %lhs
     %trunc:_(s32) = G_TRUNC %fabs(s64)
-    %rhs:_(s32) = G_FCONSTANT float 0x3E6BBDE420000000
+    %rhs:_(s32) = G_FCONSTANT float 1.0
     %res:_(s32) = G_FCMP floatpred(oge), %trunc(s32), %rhs
     $w0 = COPY %res(s32)
 ...



More information about the llvm-commits mailing list