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 _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
