https://github.com/harrisonGPU updated https://github.com/llvm/llvm-project/pull/230188
>From bd737a9551a1df002b769a0e7cb55d203dd87762 Mon Sep 17 00:00:00 2001 From: Harrison Hao <[email protected]> Date: Thu, 8 Oct 2026 23:08:24 +0800 Subject: [PATCH 1/2] [InstCombine] Fold fpto[su]i.sat of NaN guarded select fpto[su]i.sat returns 0 for both NaN and $\pm 0.0$, so a select that replaces a NaN input with zero does not change the result, and the call can take X directly. ```llvm %not.nan = fcmp ord float %x, 0.0 %sel = select i1 %not.nan, float %x, float 0.0 %r = call i32 @llvm.fptosi.sat.i32.f32(float %sel) --> %r = call i32 @llvm.fptosi.sat.i32.f32(float %x) ``` The inverted form `select (fcmp uno X, 0.0), 0.0, X` is folded too. Only the canonical `fcmp ord/uno X, 0.0` is matched, which also covers `oeq/une X, X` after fcmp canonicalization. --- .../Transforms/InstCombine/InstCombineCalls.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp index 6fb5f50244a46..8a1b23eb0b5b2 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -4523,10 +4523,25 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) { break; } case Intrinsic::fptoui_sat: - case Intrinsic::fptosi_sat: + case Intrinsic::fptosi_sat: { if (Instruction *I = foldItoFPtoI(*II)) return I; + + Value *Src = II->getArgOperand(0); + Value *X; + // select (fcmp ord X, 0.0), X, +-0.0 --> X + if (match(Src, m_Select(m_SpecificFCmp(FCmpInst::FCMP_ORD, m_Value(X), + m_AnyZeroFP()), + m_Deferred(X), m_AnyZeroFP()))) + return replaceOperand(*II, 0, X); + + // select (fcmp uno X, 0.0), +-0.0, X --> X + if (match(Src, m_Select(m_SpecificFCmp(FCmpInst::FCMP_UNO, m_Value(X), + m_AnyZeroFP()), + m_AnyZeroFP(), m_Deferred(X)))) + return replaceOperand(*II, 0, X); break; + } case Intrinsic::frexp: { // frexp(frexp(x).fract) -> { frexp(x).fract, 0 }: the fraction operand is // already normalized, so the first result is idempotent and the second is >From 8e02f08f60ee463fa97951143634b473efce1e30 Mon Sep 17 00:00:00 2001 From: Harrison Hao <[email protected]> Date: Mon, 12 Oct 2026 15:53:36 +0800 Subject: [PATCH 2/2] Implement in Simplify --- llvm/lib/Analysis/InstructionSimplify.cpp | 17 +++++++++++ .../InstCombine/InstCombineCalls.cpp | 14 --------- .../test/Transforms/InstSimplify/fptoi-sat.ll | 30 +++++++------------ 3 files changed, 27 insertions(+), 34 deletions(-) diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index 74a266660b234..d1fb62e77fcba 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -4982,6 +4982,23 @@ static Value *simplifySelectWithFCmp(Value *Cond, Value *T, Value *F, return nullptr; FCmpInst *I = cast<FCmpInst>(Cond); + Value *X = nullptr; + auto FPToISat = + m_AnyIntrinsic<Intrinsic::fptosi_sat, Intrinsic::fptoui_sat>(); + // select (fcmp ord X, 0.0), fpto[su]i.sat(X), 0 --> fpto[su]i.sat(X) + if (match(Cond, + m_SpecificFCmp(FCmpInst::FCMP_ORD, m_Value(X), m_AnyZeroFP())) && + match(T, m_CombineAnd(FPToISat, m_Argument<0>(m_Specific(X)))) && + match(F, m_Zero())) + return T; + + // select (fcmp uno X, 0.0), 0, fpto[su]i.sat(X) --> fpto[su]i.sat(X) + if (match(Cond, + m_SpecificFCmp(FCmpInst::FCMP_UNO, m_Value(X), m_AnyZeroFP())) && + match(F, m_CombineAnd(FPToISat, m_Argument<0>(m_Specific(X)))) && + match(T, m_Zero())) + return F; + bool IsEquiv = I->isEquivalence(); if (I->isEquivalence(/*Invert=*/true)) { std::swap(T, F); diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp index 8a1b23eb0b5b2..8cae13805b3b3 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -4526,20 +4526,6 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) { case Intrinsic::fptosi_sat: { if (Instruction *I = foldItoFPtoI(*II)) return I; - - Value *Src = II->getArgOperand(0); - Value *X; - // select (fcmp ord X, 0.0), X, +-0.0 --> X - if (match(Src, m_Select(m_SpecificFCmp(FCmpInst::FCMP_ORD, m_Value(X), - m_AnyZeroFP()), - m_Deferred(X), m_AnyZeroFP()))) - return replaceOperand(*II, 0, X); - - // select (fcmp uno X, 0.0), +-0.0, X --> X - if (match(Src, m_Select(m_SpecificFCmp(FCmpInst::FCMP_UNO, m_Value(X), - m_AnyZeroFP()), - m_AnyZeroFP(), m_Deferred(X)))) - return replaceOperand(*II, 0, X); break; } case Intrinsic::frexp: { diff --git a/llvm/test/Transforms/InstSimplify/fptoi-sat.ll b/llvm/test/Transforms/InstSimplify/fptoi-sat.ll index bfd5f083cb2c7..56bcc94010ce5 100644 --- a/llvm/test/Transforms/InstSimplify/fptoi-sat.ll +++ b/llvm/test/Transforms/InstSimplify/fptoi-sat.ll @@ -613,10 +613,8 @@ define <2 x i32> @fptoui_f32_to_i32_vec() { define i32 @fptosi_sat_select_ord(float %a) { ; CHECK-LABEL: @fptosi_sat_select_ord( -; CHECK-NEXT: [[NOT_NAN:%.*]] = fcmp ord float [[A:%.*]], 0.000000e+00 -; CHECK-NEXT: [[CVT:%.*]] = call i32 @llvm.fptosi.sat.i32.f32(float [[A]]) -; CHECK-NEXT: [[R:%.*]] = select i1 [[NOT_NAN]], i32 [[CVT]], i32 0 -; CHECK-NEXT: ret i32 [[R]] +; CHECK-NEXT: [[CVT:%.*]] = call i32 @llvm.fptosi.sat.i32.f32(float [[A:%.*]]) +; CHECK-NEXT: ret i32 [[CVT]] ; %not.nan = fcmp ord float %a, 0.000000e+00 %cvt = call i32 @llvm.fptosi.sat.i32.f32(float %a) @@ -626,10 +624,8 @@ define i32 @fptosi_sat_select_ord(float %a) { define i32 @fptoui_sat_select_uno(float %a) { ; CHECK-LABEL: @fptoui_sat_select_uno( -; CHECK-NEXT: [[IS_NAN:%.*]] = fcmp uno float [[A:%.*]], 0.000000e+00 -; CHECK-NEXT: [[CVT:%.*]] = call i32 @llvm.fptoui.sat.i32.f32(float [[A]]) -; CHECK-NEXT: [[R:%.*]] = select i1 [[IS_NAN]], i32 0, i32 [[CVT]] -; CHECK-NEXT: ret i32 [[R]] +; CHECK-NEXT: [[CVT:%.*]] = call i32 @llvm.fptoui.sat.i32.f32(float [[A:%.*]]) +; CHECK-NEXT: ret i32 [[CVT]] ; %is.nan = fcmp uno float %a, 0.000000e+00 %cvt = call i32 @llvm.fptoui.sat.i32.f32(float %a) @@ -639,10 +635,8 @@ define i32 @fptoui_sat_select_uno(float %a) { define i32 @fptoui_sat_select_ord_negzero(float %a) { ; CHECK-LABEL: @fptoui_sat_select_ord_negzero( -; CHECK-NEXT: [[NOT_NAN:%.*]] = fcmp ord float [[A:%.*]], -0.000000e+00 -; CHECK-NEXT: [[CVT:%.*]] = call i32 @llvm.fptoui.sat.i32.f32(float [[A]]) -; CHECK-NEXT: [[R:%.*]] = select i1 [[NOT_NAN]], i32 [[CVT]], i32 0 -; CHECK-NEXT: ret i32 [[R]] +; CHECK-NEXT: [[CVT:%.*]] = call i32 @llvm.fptoui.sat.i32.f32(float [[A:%.*]]) +; CHECK-NEXT: ret i32 [[CVT]] ; %not.nan = fcmp ord float %a, -0.000000e+00 %cvt = call i32 @llvm.fptoui.sat.i32.f32(float %a) @@ -652,10 +646,8 @@ define i32 @fptoui_sat_select_ord_negzero(float %a) { define <2 x i32> @fptosi_sat_select_uno_vec(<2 x float> %a) { ; CHECK-LABEL: @fptosi_sat_select_uno_vec( -; CHECK-NEXT: [[IS_NAN:%.*]] = fcmp uno <2 x float> [[A:%.*]], zeroinitializer -; CHECK-NEXT: [[CVT:%.*]] = call <2 x i32> @llvm.fptosi.sat.v2i32.v2f32(<2 x float> [[A]]) -; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[IS_NAN]], <2 x i32> zeroinitializer, <2 x i32> [[CVT]] -; CHECK-NEXT: ret <2 x i32> [[R]] +; CHECK-NEXT: [[CVT:%.*]] = call <2 x i32> @llvm.fptosi.sat.v2i32.v2f32(<2 x float> [[A:%.*]]) +; CHECK-NEXT: ret <2 x i32> [[CVT]] ; %is.nan = fcmp uno <2 x float> %a, zeroinitializer %cvt = call <2 x i32> @llvm.fptosi.sat.v2i32.v2f32(<2 x float> %a) @@ -665,10 +657,8 @@ define <2 x i32> @fptosi_sat_select_uno_vec(<2 x float> %a) { define <2 x i32> @fptoui_sat_select_ord_vec_poison(<2 x float> %a) { ; CHECK-LABEL: @fptoui_sat_select_ord_vec_poison( -; CHECK-NEXT: [[NOT_NAN:%.*]] = fcmp ord <2 x float> [[A:%.*]], zeroinitializer -; CHECK-NEXT: [[CVT:%.*]] = call <2 x i32> @llvm.fptoui.sat.v2i32.v2f32(<2 x float> [[A]]) -; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[NOT_NAN]], <2 x i32> [[CVT]], <2 x i32> <i32 0, i32 poison> -; CHECK-NEXT: ret <2 x i32> [[R]] +; CHECK-NEXT: [[CVT:%.*]] = call <2 x i32> @llvm.fptoui.sat.v2i32.v2f32(<2 x float> [[A:%.*]]) +; CHECK-NEXT: ret <2 x i32> [[CVT]] ; %not.nan = fcmp ord <2 x float> %a, zeroinitializer %cvt = call <2 x i32> @llvm.fptoui.sat.v2i32.v2f32(<2 x float> %a) _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
