[llvm-branch-commits] [llvm] b23ba29 - [InstCombine] Optimize fcmp ord/uno logical select operations using freeze (#205076)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Sat Jun 27 08:58:13 PDT 2026


Author: SUBASH BOOPATHI
Date: 2026-06-27T13:51:03Z
New Revision: b23ba298af84d56be149350bf617dc869c1fb42c

URL: https://github.com/llvm/llvm-project/commit/b23ba298af84d56be149350bf617dc869c1fb42c
DIFF: https://github.com/llvm/llvm-project/commit/b23ba298af84d56be149350bf617dc869c1fb42c.diff

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

This pull request optimizes logical select sequences checking ordered or
unordered floating point operations.

Currently, InstCombine canonicalizes:

fcmp ord x, 0.0 AND fcmp ord y, 0.0 to fcmp ord x, y
fcmp uno x, 0.0 OR fcmp uno y, 0.0 to fcmp uno x, y
However, this canonicalization is blocked for logical selects because it
is not poison safe if the second operand evaluates to poison when the
first evaluates to NaN.

This patch enables the transformation for logical selects by inserting a
freeze on the second evaluated operand to guarantee poison safety.

Fixes #49175

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
    llvm/test/Transforms/InstCombine/and-fcmp.ll
    llvm/test/Transforms/InstCombine/or-fcmp.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 50496065b8dfa..b6f4a55c07e8a 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -1472,11 +1472,8 @@ 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) ||
-       (PredL == FCmpInst::FCMP_UNO && PredR == FCmpInst::FCMP_UNO &&
-        !IsAnd))) {
+  if ((PredL == FCmpInst::FCMP_ORD && PredR == FCmpInst::FCMP_ORD && IsAnd) ||
+      (PredL == FCmpInst::FCMP_UNO && PredR == FCmpInst::FCMP_UNO && !IsAnd)) {
     if (LHS0->getType() != RHS0->getType())
       return nullptr;
 
@@ -1486,8 +1483,14 @@ 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,
-                                   FMFSource::intersect(LHS, RHS));
+      Value *Y = RHS0;
+      FastMathFlags FMF = LHS->getFastMathFlags() & RHS->getFastMathFlags();
+      if (IsLogicalSelect) {
+        Y = Builder.CreateFreeze(Y, Y->getName() + ".fr");
+        FMF.setNoNaNs(false);
+        FMF.setNoInfs(false);
+      }
+      return Builder.CreateFCmpFMF(PredL, LHS0, Y, FMF);
     }
   }
 

diff  --git a/llvm/test/Transforms/InstCombine/and-fcmp.ll b/llvm/test/Transforms/InstCombine/and-fcmp.ll
index 99adb49a579ec..c6f1e635ce5ce 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 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-branch-commits mailing list