[llvm] [InstCombine] Optimize fcmp ord/uno logical select operations using freeze (PR #205076)

SUBASH BOOPATHI via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 22 21:46:38 PDT 2026


https://github.com/SubashBoopathi1605 updated https://github.com/llvm/llvm-project/pull/205076

>From 0f8dd78635eed64dec611d6de32ea1a8abd4eddf Mon Sep 17 00:00:00 2001
From: Subash Boopathi <subashofficial7 at gmail.com>
Date: Mon, 22 Jun 2026 15:56:02 +0530
Subject: [PATCH] [InstCombine] Optimize fcmp ord/uno logical select operations
 using freeze

---
 .../InstCombine/InstCombineAndOrXor.cpp        | 11 ++++++-----
 llvm/test/Transforms/InstCombine/and-fcmp.ll   | 18 ++++++------------
 llvm/test/Transforms/InstCombine/or-fcmp.ll    | 12 ++++--------
 3 files changed, 16 insertions(+), 25 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index b4686a6a63e86..8a98f2a479c0d 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -1472,11 +1472,9 @@ Value *InstCombinerImpl::foldLogicOfFCmps(FCmpInst *LHS, FCmpInst *RHS,
                         FMFSource::intersect(LHS, RHS));
   }
 
-  // This transform is not valid for a logical select.
-  if (!IsLogicalSelect &&
-      ((PredL == FCmpInst::FCMP_ORD && PredR == FCmpInst::FCMP_ORD && IsAnd) ||
+  if ((PredL == FCmpInst::FCMP_ORD && PredR == FCmpInst::FCMP_ORD && IsAnd) ||
        (PredL == FCmpInst::FCMP_UNO && PredR == FCmpInst::FCMP_UNO &&
-        !IsAnd))) {
+        !IsAnd)) {
     if (LHS0->getType() != RHS0->getType())
       return nullptr;
 
@@ -1486,7 +1484,10 @@ Value *InstCombinerImpl::foldLogicOfFCmps(FCmpInst *LHS, FCmpInst *RHS,
       // Ignore the constants because they are obviously not NANs:
       // (fcmp ord x, 0.0) & (fcmp ord y, 0.0)  -> (fcmp ord x, y)
       // (fcmp uno x, 0.0) | (fcmp uno y, 0.0)  -> (fcmp uno x, y)
-      return Builder.CreateFCmpFMF(PredL, LHS0, RHS0,
+      Value *Y = RHS0;
+      if (IsLogicalSelect)
+        Y = Builder.CreateFreeze(Y, Y->getName() + ".fr");
+      return Builder.CreateFCmpFMF(PredL, LHS0, Y,
                                    FMFSource::intersect(LHS, RHS));
     }
   }
diff --git a/llvm/test/Transforms/InstCombine/and-fcmp.ll b/llvm/test/Transforms/InstCombine/and-fcmp.ll
index 99adb49a579ec..64b12bada377d 100644
--- a/llvm/test/Transforms/InstCombine/and-fcmp.ll
+++ b/llvm/test/Transforms/InstCombine/and-fcmp.ll
@@ -12,12 +12,10 @@ define i1 @PR1738(double %x, double %y) {
   ret i1 %and
 }
 
-; TODO: this can be supported by freezing %y
 define i1 @PR1738_logical(double %x, double %y) {
 ; CHECK-LABEL: @PR1738_logical(
-; CHECK-NEXT:    [[CMP1:%.*]] = fcmp ord double [[X:%.*]], 0.000000e+00
-; CHECK-NEXT:    [[CMP2:%.*]] = fcmp ord double [[Y:%.*]], 0.000000e+00
-; CHECK-NEXT:    [[AND:%.*]] = select i1 [[CMP1]], i1 [[CMP2]], i1 false
+; CHECK-NEXT:    [[Y_FR:%.*]] = freeze double [[Y:%.*]]
+; CHECK-NEXT:    [[AND:%.*]] = fcmp ord double [[X:%.*]], [[Y_FR]]
 ; CHECK-NEXT:    ret i1 [[AND]]
 ;
   %cmp1 = fcmp ord double %x, 0.0
@@ -103,12 +101,10 @@ define i1 @PR41069_commute(i1 %z, float %c, float %d) {
   ret i1 %r
 }
 
-; TODO: this should be fixed using freeze
 define i1 @PR41069_commute_logical(i1 %z, float %c, float %d) {
 ; CHECK-LABEL: @PR41069_commute_logical(
-; CHECK-NEXT:    [[ORD1:%.*]] = fcmp ninf ord float [[C:%.*]], 0.000000e+00
-; CHECK-NEXT:    [[ORD2:%.*]] = fcmp reassoc ninf ord float [[D:%.*]], 0.000000e+00
-; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[ORD2]], i1 [[ORD1]], i1 false
+; CHECK-NEXT:    [[C_FR:%.*]] = freeze float [[C:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fcmp ninf ord float [[D:%.*]], [[C_FR]]
 ; CHECK-NEXT:    [[R:%.*]] = select i1 [[TMP1]], i1 [[Z:%.*]], i1 false
 ; CHECK-NEXT:    ret i1 [[R]]
 ;
@@ -205,12 +201,10 @@ define i1 @fcmp_ord_nonzero(float %x, float %y) {
   ret i1 %and
 }
 
-; TODO: this can be supported by freezing %y
 define i1 @fcmp_ord_nonzero_logical(float %x, float %y) {
 ; CHECK-LABEL: @fcmp_ord_nonzero_logical(
-; CHECK-NEXT:    [[CMP1:%.*]] = fcmp ord float [[X:%.*]], 0.000000e+00
-; CHECK-NEXT:    [[CMP2:%.*]] = fcmp ord float [[Y:%.*]], 0.000000e+00
-; CHECK-NEXT:    [[AND:%.*]] = select i1 [[CMP1]], i1 [[CMP2]], i1 false
+; CHECK-NEXT:    [[Y_FR:%.*]] = freeze float [[Y:%.*]]
+; CHECK-NEXT:    [[AND:%.*]] = fcmp ord float [[X:%.*]], [[Y_FR]]
 ; CHECK-NEXT:    ret i1 [[AND]]
 ;
   %cmp1 = fcmp ord float %x, 1.0
diff --git a/llvm/test/Transforms/InstCombine/or-fcmp.ll b/llvm/test/Transforms/InstCombine/or-fcmp.ll
index 193fe4b5cc722..99f8b687fd603 100644
--- a/llvm/test/Transforms/InstCombine/or-fcmp.ll
+++ b/llvm/test/Transforms/InstCombine/or-fcmp.ll
@@ -12,12 +12,10 @@ define i1 @PR1738(double %x, double %y) {
   ret i1 %or
 }
 
-; TODO: this can be fixed by freezing %y
 define i1 @PR1738_logical(double %x, double %y) {
 ; CHECK-LABEL: @PR1738_logical(
-; CHECK-NEXT:    [[CMP1:%.*]] = fcmp uno double [[X:%.*]], 0.000000e+00
-; CHECK-NEXT:    [[CMP2:%.*]] = fcmp uno double [[Y:%.*]], 0.000000e+00
-; CHECK-NEXT:    [[OR:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP2]]
+; CHECK-NEXT:    [[Y_FR:%.*]] = freeze double [[Y:%.*]]
+; CHECK-NEXT:    [[OR:%.*]] = fcmp uno double [[X:%.*]], [[Y_FR]]
 ; CHECK-NEXT:    ret i1 [[OR]]
 ;
   %cmp1 = fcmp uno double %x, 0.0
@@ -183,12 +181,10 @@ define i1 @fcmp_uno_nonzero(float %x, float %y) {
   ret i1 %or
 }
 
-; TODO: this can be fixed by freezing %y
 define i1 @fcmp_uno_nonzero_logical(float %x, float %y) {
 ; CHECK-LABEL: @fcmp_uno_nonzero_logical(
-; CHECK-NEXT:    [[CMP1:%.*]] = fcmp uno float [[X:%.*]], 0.000000e+00
-; CHECK-NEXT:    [[CMP2:%.*]] = fcmp uno float [[Y:%.*]], 0.000000e+00
-; CHECK-NEXT:    [[OR:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP2]]
+; CHECK-NEXT:    [[Y_FR:%.*]] = freeze float [[Y:%.*]]
+; CHECK-NEXT:    [[OR:%.*]] = fcmp uno float [[X:%.*]], [[Y_FR]]
 ; CHECK-NEXT:    ret i1 [[OR]]
 ;
   %cmp1 = fcmp uno float %x, 1.0



More information about the llvm-commits mailing list