[llvm] [InstCombine] Fold `fcmp ord/uno (fptrunc X), C` to `fcmp ord/uno X, C` (PR #185848)

Tirthankar Mazumder via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 11 06:13:39 PDT 2026


https://github.com/wermos updated https://github.com/llvm/llvm-project/pull/185848

>From a30fd37f4b5cc6ed49ff55c396547be43339da39 Mon Sep 17 00:00:00 2001
From: Tirthankar Mazumder <tmazumder.github at gmail.com>
Date: Wed, 11 Mar 2026 13:18:38 +0530
Subject: [PATCH 1/4] Pre-commit tests

---
 .../Transforms/InstCombine/fold-fcmp-trunc.ll | 49 ++++++++++++++++++-
 1 file changed, 48 insertions(+), 1 deletion(-)

diff --git a/llvm/test/Transforms/InstCombine/fold-fcmp-trunc.ll b/llvm/test/Transforms/InstCombine/fold-fcmp-trunc.ll
index 371f9b6807fe4..7bc5d7fb7a1c6 100644
--- a/llvm/test/Transforms/InstCombine/fold-fcmp-trunc.ll
+++ b/llvm/test/Transforms/InstCombine/fold-fcmp-trunc.ll
@@ -104,7 +104,7 @@ define i1 @fcmp_trunc_with_reassoc(double %0) {
 define i1 @fcmp_trunc_with_fast(double %0) {
 ; CHECK-LABEL: define i1 @fcmp_trunc_with_fast(
 ; CHECK-SAME: double [[TMP0:%.*]]) {
-; CHECK-NEXT:    [[RESULT:%.*]] = fcmp fast oge double [[TMP0]], 0x4058FFFFF0000000 
+; CHECK-NEXT:    [[RESULT:%.*]] = fcmp fast oge double [[TMP0]], 0x4058FFFFF0000000
 ; CHECK-NEXT:    ret i1 [[RESULT]]
 ;
   %trunc = fptrunc double %0 to float
@@ -672,3 +672,50 @@ define i1 @fcmp_trunc_mn_ppc_fp128(ppc_fp128 %0) {
   ret i1 %result
 }
 
+define i1 @fptrunc_uno_fcmp(double %arg0) {
+; CHECK-LABEL: define i1 @fptrunc_uno_fcmp(
+; CHECK-SAME: double [[ARG0:%.*]]) {
+; CHECK-NEXT:    [[V0:%.*]] = fptrunc double [[ARG0]] to float
+; CHECK-NEXT:    [[V1:%.*]] = fcmp uno float [[V0]], 0.000000e+00
+; CHECK-NEXT:    ret i1 [[V1]]
+;
+  %v0 = fptrunc double %arg0 to float
+  %v1 = fcmp uno float %v0, 0.000000e+00
+  ret i1 %v1
+}
+
+define i1 @fptrunc_uno_fcmp_commuted(double %arg0) {
+; CHECK-LABEL: define i1 @fptrunc_uno_fcmp_commuted(
+; CHECK-SAME: double [[ARG0:%.*]]) {
+; CHECK-NEXT:    [[V0:%.*]] = fptrunc double [[ARG0]] to float
+; CHECK-NEXT:    [[V1:%.*]] = fcmp uno float [[V0]], 0.000000e+00
+; CHECK-NEXT:    ret i1 [[V1]]
+;
+  %v0 = fptrunc double %arg0 to float
+  %v1 = fcmp uno float 7.000000e+00, %v0
+  ret i1 %v1
+}
+
+define i1 @fptrunc_ord_fcmp(double %arg0) {
+; CHECK-LABEL: define i1 @fptrunc_ord_fcmp(
+; CHECK-SAME: double [[ARG0:%.*]]) {
+; CHECK-NEXT:    [[V0:%.*]] = fptrunc double [[ARG0]] to float
+; CHECK-NEXT:    [[V1:%.*]] = fcmp ord float [[V0]], 0.000000e+00
+; CHECK-NEXT:    ret i1 [[V1]]
+;
+  %v0 = fptrunc double %arg0 to float
+  %v1 = fcmp ord float %v0, 0.000000e+00
+  ret i1 %v1
+}
+
+define i1 @fptrunc_ord_fcmp_commuted(double %arg0) {
+; CHECK-LABEL: define i1 @fptrunc_ord_fcmp_commuted(
+; CHECK-SAME: double [[ARG0:%.*]]) {
+; CHECK-NEXT:    [[V0:%.*]] = fptrunc double [[ARG0]] to float
+; CHECK-NEXT:    [[V1:%.*]] = fcmp ord float [[V0]], 0.000000e+00
+; CHECK-NEXT:    ret i1 [[V1]]
+;
+  %v0 = fptrunc double %arg0 to float
+  %v1 = fcmp ord float 7.000000e+00, %v0
+  ret i1 %v1
+}

>From 0b45b755eb6afb7c7e179ffd5d401ae3505611d6 Mon Sep 17 00:00:00 2001
From: Tirthankar Mazumder <tmazumder.github at gmail.com>
Date: Wed, 11 Mar 2026 15:28:26 +0530
Subject: [PATCH 2/4] Fold fcmp ord/uno (fptrunc X), C to fcmp ord/uno X, C.

---
 .../InstCombine/InstCombineCompares.cpp       | 52 +++++++++++--------
 .../Transforms/InstCombine/fold-fcmp-trunc.ll | 15 ++----
 2 files changed, 35 insertions(+), 32 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 10caf4ab78a5a..90e9fbb4ab583 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -8359,26 +8359,15 @@ static Instruction *foldFCmpReciprocalAndZero(FCmpInst &I, Instruction *LHSI,
 
 // Transform 'fptrunc(x) cmp C' to 'x cmp ext(C)' if possible.
 // Patterns include:
-//    fptrunc(x) <  C  -->  x <  ext(C)
-//    fptrunc(x) <= C  -->  x <= ext(C)
-//    fptrunc(x) >  C  -->  x >  ext(C)
-//    fptrunc(x) >= C  -->  x >= ext(C)
+//    fptrunc(x) <  C      -->  x <  ext(C)
+//    fptrunc(x) <= C      -->  x <= ext(C)
+//    fptrunc(x) >  C      -->  x >  ext(C)
+//    fptrunc(x) >= C      -->  x >= ext(C)
+//    fptrunc(x) ord/uno C --> x ord/uno C
 // where 'ext(C)' is the extension of 'C' to the type of 'x' with a small bias
 // due to precision loss.
 static Instruction *foldFCmpFpTrunc(FCmpInst &I, const Instruction &FPTrunc,
                                     const Constant &C) {
-  FCmpInst::Predicate Pred = I.getPredicate();
-  bool RoundDown = false;
-
-  if (Pred == FCmpInst::FCMP_OGE || Pred == FCmpInst::FCMP_UGE ||
-      Pred == FCmpInst::FCMP_OLT || Pred == FCmpInst::FCMP_ULT)
-    RoundDown = true;
-  else if (Pred == FCmpInst::FCMP_OGT || Pred == FCmpInst::FCMP_UGT ||
-           Pred == FCmpInst::FCMP_OLE || Pred == FCmpInst::FCMP_ULE)
-    RoundDown = false;
-  else
-    return nullptr;
-
   const APFloat *CValue;
   if (!match(&C, m_APFloat(CValue)))
     return nullptr;
@@ -8393,6 +8382,31 @@ static Instruction *foldFCmpFpTrunc(FCmpInst &I, const Instruction &FPTrunc,
     return Dest;
   };
 
+  Type *DestType = FPTrunc.getOperand(0)->getType();
+  const fltSemantics &DestFltSema =
+      DestType->getScalarType()->getFltSemantics();
+
+  APFloat ExtCValue = ConvertFltSema(*CValue, DestFltSema);
+
+  FCmpInst::Predicate Pred = I.getPredicate();
+
+  // Fold fcmp ord/uno fptrunc X, C -> fcmp ord/uno X, C
+  if (Pred == FCmpInst::FCMP_ORD || Pred == FCmpInst::FCMP_UNO) {
+    return new FCmpInst(Pred, FPTrunc.getOperand(0),
+                        ConstantFP::get(DestType, ExtCValue), "", &I);
+  }
+
+  bool RoundDown = false;
+
+  if (Pred == FCmpInst::FCMP_OGE || Pred == FCmpInst::FCMP_UGE ||
+      Pred == FCmpInst::FCMP_OLT || Pred == FCmpInst::FCMP_ULT)
+    RoundDown = true;
+  else if (Pred == FCmpInst::FCMP_OGT || Pred == FCmpInst::FCMP_UGT ||
+           Pred == FCmpInst::FCMP_OLE || Pred == FCmpInst::FCMP_ULE)
+    RoundDown = false;
+  else
+    return nullptr;
+
   auto NextValue = [](const APFloat &Value, bool RoundDown) {
     APFloat NextValue = Value;
     NextValue.next(RoundDown);
@@ -8400,12 +8414,6 @@ static Instruction *foldFCmpFpTrunc(FCmpInst &I, const Instruction &FPTrunc,
   };
 
   APFloat NextCValue = NextValue(*CValue, RoundDown);
-
-  Type *DestType = FPTrunc.getOperand(0)->getType();
-  const fltSemantics &DestFltSema =
-      DestType->getScalarType()->getFltSemantics();
-
-  APFloat ExtCValue = ConvertFltSema(*CValue, DestFltSema);
   APFloat ExtNextCValue = ConvertFltSema(NextCValue, DestFltSema);
 
   // When 'NextCValue' is infinity, use an imaged 'NextCValue' that equals
diff --git a/llvm/test/Transforms/InstCombine/fold-fcmp-trunc.ll b/llvm/test/Transforms/InstCombine/fold-fcmp-trunc.ll
index 7bc5d7fb7a1c6..bca9be81dca16 100644
--- a/llvm/test/Transforms/InstCombine/fold-fcmp-trunc.ll
+++ b/llvm/test/Transforms/InstCombine/fold-fcmp-trunc.ll
@@ -327,8 +327,7 @@ define i1 @fcmp_trunc_literal_positive_inf(double %0) {
 define i1 @fcmp_trunc_literal_negative_inf(double %0) {
 ; CHECK-LABEL: define i1 @fcmp_trunc_literal_negative_inf(
 ; CHECK-SAME: double [[TMP0:%.*]]) {
-; CHECK-NEXT:    [[TRUNC:%.*]] = fptrunc double [[TMP0]] to float
-; CHECK-NEXT:    [[RESULT:%.*]] = fcmp uno float [[TRUNC]], 0.000000e+00
+; CHECK-NEXT:    [[RESULT:%.*]] = fcmp uno double [[TMP0]], 0.000000e+00
 ; CHECK-NEXT:    ret i1 [[RESULT]]
 ;
   %trunc = fptrunc double %0 to float
@@ -675,8 +674,7 @@ define i1 @fcmp_trunc_mn_ppc_fp128(ppc_fp128 %0) {
 define i1 @fptrunc_uno_fcmp(double %arg0) {
 ; CHECK-LABEL: define i1 @fptrunc_uno_fcmp(
 ; CHECK-SAME: double [[ARG0:%.*]]) {
-; CHECK-NEXT:    [[V0:%.*]] = fptrunc double [[ARG0]] to float
-; CHECK-NEXT:    [[V1:%.*]] = fcmp uno float [[V0]], 0.000000e+00
+; CHECK-NEXT:    [[V1:%.*]] = fcmp uno double [[ARG0]], 0.000000e+00
 ; CHECK-NEXT:    ret i1 [[V1]]
 ;
   %v0 = fptrunc double %arg0 to float
@@ -687,8 +685,7 @@ define i1 @fptrunc_uno_fcmp(double %arg0) {
 define i1 @fptrunc_uno_fcmp_commuted(double %arg0) {
 ; CHECK-LABEL: define i1 @fptrunc_uno_fcmp_commuted(
 ; CHECK-SAME: double [[ARG0:%.*]]) {
-; CHECK-NEXT:    [[V0:%.*]] = fptrunc double [[ARG0]] to float
-; CHECK-NEXT:    [[V1:%.*]] = fcmp uno float [[V0]], 0.000000e+00
+; CHECK-NEXT:    [[V1:%.*]] = fcmp uno double [[ARG0]], 0.000000e+00
 ; CHECK-NEXT:    ret i1 [[V1]]
 ;
   %v0 = fptrunc double %arg0 to float
@@ -699,8 +696,7 @@ define i1 @fptrunc_uno_fcmp_commuted(double %arg0) {
 define i1 @fptrunc_ord_fcmp(double %arg0) {
 ; CHECK-LABEL: define i1 @fptrunc_ord_fcmp(
 ; CHECK-SAME: double [[ARG0:%.*]]) {
-; CHECK-NEXT:    [[V0:%.*]] = fptrunc double [[ARG0]] to float
-; CHECK-NEXT:    [[V1:%.*]] = fcmp ord float [[V0]], 0.000000e+00
+; CHECK-NEXT:    [[V1:%.*]] = fcmp ord double [[ARG0]], 0.000000e+00
 ; CHECK-NEXT:    ret i1 [[V1]]
 ;
   %v0 = fptrunc double %arg0 to float
@@ -711,8 +707,7 @@ define i1 @fptrunc_ord_fcmp(double %arg0) {
 define i1 @fptrunc_ord_fcmp_commuted(double %arg0) {
 ; CHECK-LABEL: define i1 @fptrunc_ord_fcmp_commuted(
 ; CHECK-SAME: double [[ARG0:%.*]]) {
-; CHECK-NEXT:    [[V0:%.*]] = fptrunc double [[ARG0]] to float
-; CHECK-NEXT:    [[V1:%.*]] = fcmp ord float [[V0]], 0.000000e+00
+; CHECK-NEXT:    [[V1:%.*]] = fcmp ord double [[ARG0]], 0.000000e+00
 ; CHECK-NEXT:    ret i1 [[V1]]
 ;
   %v0 = fptrunc double %arg0 to float

>From 8720d1f4ab0cb503e3aa608e0a9fb53335092726 Mon Sep 17 00:00:00 2001
From: Tirthankar Mazumder <tmazumder.github at gmail.com>
Date: Wed, 11 Mar 2026 18:42:28 +0530
Subject: [PATCH 3/4] Update another test.

---
 llvm/test/Transforms/InstCombine/known-never-nan.ll | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/llvm/test/Transforms/InstCombine/known-never-nan.ll b/llvm/test/Transforms/InstCombine/known-never-nan.ll
index c4ce874029647..759cabae3d72f 100644
--- a/llvm/test/Transforms/InstCombine/known-never-nan.ll
+++ b/llvm/test/Transforms/InstCombine/known-never-nan.ll
@@ -150,8 +150,7 @@ define i1 @fpext_maybe_nan(float %arg0) {
 
 define i1 @fptrunc_maybe_nan(double %arg0) {
 ; CHECK-LABEL: @fptrunc_maybe_nan(
-; CHECK-NEXT:    [[OP:%.*]] = fptrunc double [[ARG0:%.*]] to float
-; CHECK-NEXT:    [[TMP:%.*]] = fcmp ord float [[OP]], 0.000000e+00
+; CHECK-NEXT:    [[TMP:%.*]] = fcmp ord double [[ARG0:%.*]], 0.000000e+00
 ; CHECK-NEXT:    ret i1 [[TMP]]
 ;
   %op = fptrunc double %arg0 to float

>From 0b282d9d85ff9bc4dc329ab800b11338473f8293 Mon Sep 17 00:00:00 2001
From: Tirthankar Mazumder <tmazumder.github at gmail.com>
Date: Wed, 11 Mar 2026 18:43:23 +0530
Subject: [PATCH 4/4] Fix comment formatting.

---
 llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 90e9fbb4ab583..7716f6c190e3c 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -8363,7 +8363,7 @@ static Instruction *foldFCmpReciprocalAndZero(FCmpInst &I, Instruction *LHSI,
 //    fptrunc(x) <= C      -->  x <= ext(C)
 //    fptrunc(x) >  C      -->  x >  ext(C)
 //    fptrunc(x) >= C      -->  x >= ext(C)
-//    fptrunc(x) ord/uno C --> x ord/uno C
+//    fptrunc(x) ord/uno C -->  x ord/uno C
 // where 'ext(C)' is the extension of 'C' to the type of 'x' with a small bias
 // due to precision loss.
 static Instruction *foldFCmpFpTrunc(FCmpInst &I, const Instruction &FPTrunc,



More information about the llvm-commits mailing list