From 8e6daa19e69791e3d541912e9fb878242d8f78b2 Mon Sep 17 00:00:00 2001 From: Artem Trokhymchuk Date: Tue, 26 Aug 2025 00:28:10 +0300 Subject: [PATCH 1/3] [InstCombint] add icmp (fptosi %x) -> fcmp %y optimization tests Add optimization test reducing unneded float-to-int cast when comparing numbers: * icmp sgt (fptosi %x), -> fcmp ogt %x, * icmp sgt (fptosi %x), -> fcmp oge %x, * icmp slt (fptosi %x), -> fcmp olt %x, * icmp slt (fptosi %x), -> fcmp ole %x, --- llvm/test/Transforms/InstCombine/icmp.ll | 305 +++++++++++++++++++++++ 1 file changed, 305 insertions(+) diff --git a/llvm/test/Transforms/InstCombine/icmp.ll b/llvm/test/Transforms/InstCombine/icmp.ll index 0faa7da482ef2..eccf9ec39da61 100644 --- a/llvm/test/Transforms/InstCombine/icmp.ll +++ b/llvm/test/Transforms/InstCombine/icmp.ll @@ -6054,3 +6054,308 @@ define i1 @icmp_samesign_logical_or(i32 %In) { %V = select i1 %c1, i1 true, i1 %c2 ret i1 %V } + +; https://alive2.llvm.org/ce/z/XtQS6H +define i1 @float_to_int_comparing_constant1_positive1(float %arg0) { +; CHECK-LABEL: define i1 @float_to_int_comparing_constant1_positive1( +; CHECK-SAME: float [[ARG0:%.*]]) { +; CHECK-NEXT: [[V0:%.*]] = fptosi float [[ARG0]] to i32 +; CHECK-NEXT: [[V1:%.*]] = icmp sgt i32 [[V0]], -1 +; CHECK-NEXT: ret i1 [[V1]] +; + %v0 = fptosi float %arg0 to i32 + %v1 = icmp sgt i32 %v0, -1 + ret i1 %v1 +} + +; https://alive2.llvm.org/ce/z/ZycBgc +define i1 @float_to_int_comparing_constant1_positive2(float %arg0) { +; CHECK-LABEL: define i1 @float_to_int_comparing_constant1_positive2( +; CHECK-SAME: float [[ARG0:%.*]]) { +; CHECK-NEXT: [[V0:%.*]] = fptosi float [[ARG0]] to i32 +; CHECK-NEXT: [[V1:%.*]] = icmp sgt i32 [[V0]], 1 +; CHECK-NEXT: ret i1 [[V1]] +; + %v0 = fptosi float %arg0 to i32 + %v1 = icmp sgt i32 %v0, 1 + ret i1 %v1 +} + +; https://alive2.llvm.org/ce/z/5VRWXi +define i1 @float_to_int_comparing_constant2_positive1(float %arg0) { +; CHECK-LABEL: define i1 @float_to_int_comparing_constant2_positive1( +; CHECK-SAME: float [[ARG0:%.*]]) { +; CHECK-NEXT: [[V0:%.*]] = fptosi float [[ARG0]] to i32 +; CHECK-NEXT: [[V1:%.*]] = icmp slt i32 [[V0]], 1 +; CHECK-NEXT: ret i1 [[V1]] +; + %v0 = fptosi float %arg0 to i32 + %v1 = icmp slt i32 %v0, 1 + ret i1 %v1 +} + +; https://alive2.llvm.org/ce/z/9bejWa +define i1 @float_to_int_comparing_constant2_positive2(float %arg0) { +; CHECK-LABEL: define i1 @float_to_int_comparing_constant2_positive2( +; CHECK-SAME: float [[ARG0:%.*]]) { +; CHECK-NEXT: [[V0:%.*]] = fptosi float [[ARG0]] to i32 +; CHECK-NEXT: [[V1:%.*]] = icmp slt i32 [[V0]], 0 +; CHECK-NEXT: ret i1 [[V1]] +; + %v0 = fptosi float %arg0 to i32 + %v1 = icmp slt i32 %v0, 0 + ret i1 %v1 +} + +define i1 @double_to_int_comparing_constant1_positive1(double %arg0) { +; CHECK-LABEL: define i1 @double_to_int_comparing_constant1_positive1( +; CHECK-SAME: double [[ARG0:%.*]]) { +; CHECK-NEXT: [[V0:%.*]] = fptosi double [[ARG0]] to i32 +; CHECK-NEXT: [[V1:%.*]] = icmp sgt i32 [[V0]], -1 +; CHECK-NEXT: ret i1 [[V1]] +; + %v0 = fptosi double %arg0 to i32 + %v1 = icmp sgt i32 %v0, -1 + ret i1 %v1 +} + +define i1 @double_to_int_comparing_constant1_positive2(double %arg0) { +; CHECK-LABEL: define i1 @double_to_int_comparing_constant1_positive2( +; CHECK-SAME: double [[ARG0:%.*]]) { +; CHECK-NEXT: [[V0:%.*]] = fptosi double [[ARG0]] to i32 +; CHECK-NEXT: [[V1:%.*]] = icmp sgt i32 [[V0]], 1 +; CHECK-NEXT: ret i1 [[V1]] +; + %v0 = fptosi double %arg0 to i32 + %v1 = icmp sgt i32 %v0, 1 + ret i1 %v1 +} + +define i1 @fp16_to_int_comparing_constant2_positive1(half %arg0) { +; CHECK-LABEL: define i1 @fp16_to_int_comparing_constant2_positive1( +; CHECK-SAME: half [[ARG0:%.*]]) { +; CHECK-NEXT: [[V0:%.*]] = fptosi half [[ARG0]] to i32 +; CHECK-NEXT: [[V1:%.*]] = icmp slt i32 [[V0]], 1 +; CHECK-NEXT: ret i1 [[V1]] +; + %v0 = fptosi half %arg0 to i32 + %v1 = icmp slt i32 %v0, 1 + ret i1 %v1 +} + +define i1 @fp16_to_int_comparing_constant2_positive2(half %arg0) { +; CHECK-LABEL: define i1 @fp16_to_int_comparing_constant2_positive2( +; CHECK-SAME: half [[ARG0:%.*]]) { +; CHECK-NEXT: [[V0:%.*]] = fptosi half [[ARG0]] to i32 +; CHECK-NEXT: [[V1:%.*]] = icmp slt i32 [[V0]], 0 +; CHECK-NEXT: ret i1 [[V1]] +; + %v0 = fptosi half %arg0 to i32 + %v1 = icmp slt i32 %v0, 0 + ret i1 %v1 +} + +define i1 @fp16_to_int_comparing_constant2_negative1(half %arg0) { +; CHECK-LABEL: define i1 @fp16_to_int_comparing_constant2_negative1( +; CHECK-SAME: half [[ARG0:%.*]]) { +; CHECK-NEXT: ret i1 false +; + %v0 = fptosi half %arg0 to i32 + %v1 = icmp slt i32 %v0, -65535 + ret i1 %v1 +} + +define i1 @fp16_to_int_comparing_constant2_negativee2(half %arg0) { +; CHECK-LABEL: define i1 @fp16_to_int_comparing_constant2_negativee2( +; CHECK-SAME: half [[ARG0:%.*]]) { +; CHECK-NEXT: ret i1 true +; + %v0 = fptosi half %arg0 to i32 + %v1 = icmp slt i32 %v0, 65535 + ret i1 %v1 +} + +define i1 @float_to_int_comparing_constant1_negative1(float %arg0) { +; CHECK-LABEL: define i1 @float_to_int_comparing_constant1_negative1( +; CHECK-SAME: float [[ARG0:%.*]]) { +; CHECK-NEXT: ret i1 false +; + %v0 = fptosi float %arg0 to i8 + %v1 = icmp sgt i8 %v0, 127 + ret i1 %v1 +} + +define i1 @float_to_int_comparing_constant1_negative2(float %arg0) { +; CHECK-LABEL: define i1 @float_to_int_comparing_constant1_negative2( +; CHECK-SAME: float [[ARG0:%.*]]) { +; CHECK-NEXT: [[V0:%.*]] = fptosi float [[ARG0]] to i8 +; CHECK-NEXT: [[V1:%.*]] = icmp eq i8 [[V0]], 127 +; CHECK-NEXT: ret i1 [[V1]] +; + %v0 = fptosi float %arg0 to i8 + %v1 = icmp sge i8 %v0, 127 + ret i1 %v1 +} + +define i1 @float_to_int_comparing_constant2_negative1(float %arg0) { +; CHECK-LABEL: define i1 @float_to_int_comparing_constant2_negative1( +; CHECK-SAME: float [[ARG0:%.*]]) { +; CHECK-NEXT: ret i1 false +; + %v0 = fptosi float %arg0 to i8 + %v1 = icmp slt i8 %v0, -128 + ret i1 %v1 +} + +define i1 @float_to_int_comparing_constant2_negative2(float %arg0) { +; CHECK-LABEL: define i1 @float_to_int_comparing_constant2_negative2( +; CHECK-SAME: float [[ARG0:%.*]]) { +; CHECK-NEXT: [[V0:%.*]] = fptosi float [[ARG0]] to i8 +; CHECK-NEXT: [[V1:%.*]] = icmp eq i8 [[V0]], -128 +; CHECK-NEXT: ret i1 [[V1]] +; + %v0 = fptosi float %arg0 to i8 + %v1 = icmp sle i8 %v0, -128 + ret i1 %v1 +} + +define <2 x i1> @float_to_int_comparing_constant_vec_positive1(<2 x float> %arg0) { +; CHECK-LABEL: define <2 x i1> @float_to_int_comparing_constant_vec_positive1( +; CHECK-SAME: <2 x float> [[ARG0:%.*]]) { +; CHECK-NEXT: [[V0:%.*]] = fptosi <2 x float> [[ARG0]] to <2 x i32> +; CHECK-NEXT: [[V1:%.*]] = icmp sgt <2 x i32> [[V0]], splat (i32 -1) +; CHECK-NEXT: ret <2 x i1> [[V1]] +; + %v0 = fptosi <2 x float> %arg0 to <2 x i32> + %v1 = icmp sgt <2 x i32> %v0, + ret <2 x i1> %v1 +} + +define <2 x i1> @float_to_int_comparing_constant_vec_positive2(<2 x float> %arg0) { +; CHECK-LABEL: define <2 x i1> @float_to_int_comparing_constant_vec_positive2( +; CHECK-SAME: <2 x float> [[ARG0:%.*]]) { +; CHECK-NEXT: [[V0:%.*]] = fptosi <2 x float> [[ARG0]] to <2 x i32> +; CHECK-NEXT: [[V1:%.*]] = icmp sgt <2 x i32> [[V0]], +; CHECK-NEXT: ret <2 x i1> [[V1]] +; + %v0 = fptosi <2 x float> %arg0 to <2 x i32> + %v1 = icmp sgt <2 x i32> %v0, + ret <2 x i1> %v1 +} + + +define <2 x i1> @float_to_int_comparing_constant_vec_positive3(<2 x float> %arg0) { +; CHECK-LABEL: define <2 x i1> @float_to_int_comparing_constant_vec_positive3( +; CHECK-SAME: <2 x float> [[ARG0:%.*]]) { +; CHECK-NEXT: [[V0:%.*]] = fptosi <2 x float> [[ARG0]] to <2 x i32> +; CHECK-NEXT: [[V1:%.*]] = icmp slt <2 x i32> [[V0]], splat (i32 1) +; CHECK-NEXT: ret <2 x i1> [[V1]] +; + %v0 = fptosi <2 x float> %arg0 to <2 x i32> + %v1 = icmp slt <2 x i32> %v0, + ret <2 x i1> %v1 +} + +define <2 x i1> @float_to_int_comparing_constant_vec_positive4(<2 x float> %arg0) { +; CHECK-LABEL: define <2 x i1> @float_to_int_comparing_constant_vec_positive4( +; CHECK-SAME: <2 x float> [[ARG0:%.*]]) { +; CHECK-NEXT: [[V0:%.*]] = fptosi <2 x float> [[ARG0]] to <2 x i32> +; CHECK-NEXT: [[V1:%.*]] = icmp slt <2 x i32> [[V0]], +; CHECK-NEXT: ret <2 x i1> [[V1]] +; + %v0 = fptosi <2 x float> %arg0 to <2 x i32> + %v1 = icmp slt <2 x i32> %v0, + ret <2 x i1> %v1 +} + +define <2 x i1> @half_to_int_comparing_constant_vec_positive1(<2 x half> %arg0) { +; CHECK-LABEL: define <2 x i1> @half_to_int_comparing_constant_vec_positive1( +; CHECK-SAME: <2 x half> [[ARG0:%.*]]) { +; CHECK-NEXT: [[V0:%.*]] = fptosi <2 x half> [[ARG0]] to <2 x i32> +; CHECK-NEXT: [[V1:%.*]] = icmp sgt <2 x i32> [[V0]], splat (i32 -1) +; CHECK-NEXT: ret <2 x i1> [[V1]] +; + %v0 = fptosi <2 x half> %arg0 to <2 x i32> + %v1 = icmp sgt <2 x i32> %v0, + ret <2 x i1> %v1 +} + +define <2 x i1> @half_to_int_comparing_constant_vec_positive2(<2 x half> %arg0) { +; CHECK-LABEL: define <2 x i1> @half_to_int_comparing_constant_vec_positive2( +; CHECK-SAME: <2 x half> [[ARG0:%.*]]) { +; CHECK-NEXT: [[V0:%.*]] = fptosi <2 x half> [[ARG0]] to <2 x i32> +; CHECK-NEXT: [[V1:%.*]] = icmp sgt <2 x i32> [[V0]], +; CHECK-NEXT: ret <2 x i1> [[V1]] +; + %v0 = fptosi <2 x half> %arg0 to <2 x i32> + %v1 = icmp sgt <2 x i32> %v0, + ret <2 x i1> %v1 +} + +define <2 x i1> @double_to_int_comparing_constant_vec_positive3(<2 x double> %arg0) { +; CHECK-LABEL: define <2 x i1> @double_to_int_comparing_constant_vec_positive3( +; CHECK-SAME: <2 x double> [[ARG0:%.*]]) { +; CHECK-NEXT: [[V0:%.*]] = fptosi <2 x double> [[ARG0]] to <2 x i32> +; CHECK-NEXT: [[V1:%.*]] = icmp slt <2 x i32> [[V0]], splat (i32 1) +; CHECK-NEXT: ret <2 x i1> [[V1]] +; + %v0 = fptosi <2 x double> %arg0 to <2 x i32> + %v1 = icmp slt <2 x i32> %v0, + ret <2 x i1> %v1 +} + +define <2 x i1> @double_to_int_comparing_constant_vec_positive4(<2 x double> %arg0) { +; CHECK-LABEL: define <2 x i1> @double_to_int_comparing_constant_vec_positive4( +; CHECK-SAME: <2 x double> [[ARG0:%.*]]) { +; CHECK-NEXT: [[V0:%.*]] = fptosi <2 x double> [[ARG0]] to <2 x i32> +; CHECK-NEXT: [[V1:%.*]] = icmp slt <2 x i32> [[V0]], +; CHECK-NEXT: ret <2 x i1> [[V1]] +; + %v0 = fptosi <2 x double> %arg0 to <2 x i32> + %v1 = icmp slt <2 x i32> %v0, + ret <2 x i1> %v1 +} + +define <2 x i1> @float_to_int_comparing_constant_vec_negative1(<2 x float> %arg0) { +; CHECK-LABEL: define <2 x i1> @float_to_int_comparing_constant_vec_negative1( +; CHECK-SAME: <2 x float> [[ARG0:%.*]]) { +; CHECK-NEXT: [[V0:%.*]] = fptosi <2 x float> [[ARG0]] to <2 x i32> +; CHECK-NEXT: [[V1:%.*]] = icmp sgt <2 x i32> [[V0]], +; CHECK-NEXT: ret <2 x i1> [[V1]] +; + %v0 = fptosi <2 x float> %arg0 to <2 x i32> + %v1 = icmp sgt <2 x i32> %v0, + ret <2 x i1> %v1 +} + +define <2 x i1> @float_to_int_comparing_constant_vec_negative2(<2 x float> %arg0) { +; CHECK-LABEL: define <2 x i1> @float_to_int_comparing_constant_vec_negative2( +; CHECK-SAME: <2 x float> [[ARG0:%.*]]) { +; CHECK-NEXT: [[V0:%.*]] = fptosi <2 x float> [[ARG0]] to <2 x i32> +; CHECK-NEXT: [[V1:%.*]] = icmp slt <2 x i32> [[V0]], +; CHECK-NEXT: ret <2 x i1> [[V1]] +; + %v0 = fptosi <2 x float> %arg0 to <2 x i32> + %v1 = icmp slt <2 x i32> %v0, + ret <2 x i1> %v1 +} + +define <2 x i1> @float_to_int_comparing_constant_vec_negative3(<2 x float> %arg0) { +; CHECK-LABEL: define <2 x i1> @float_to_int_comparing_constant_vec_negative3( +; CHECK-SAME: <2 x float> [[ARG0:%.*]]) { +; CHECK-NEXT: ret <2 x i1> zeroinitializer +; + %v0 = fptosi <2 x float> %arg0 to <2 x i8> + %v1 = icmp sgt <2 x i8> %v0, + ret <2 x i1> %v1 +} + +define <2 x i1> @float_to_int_comparing_constant_vec_negative4(<2 x float> %arg0) { +; CHECK-LABEL: define <2 x i1> @float_to_int_comparing_constant_vec_negative4( +; CHECK-SAME: <2 x float> [[ARG0:%.*]]) { +; CHECK-NEXT: ret <2 x i1> zeroinitializer +; + %v0 = fptosi <2 x float> %arg0 to <2 x i8> + %v1 = icmp slt <2 x i8> %v0, + ret <2 x i1> %v1 +} From 09d9caa80e8ac8f75558fe9f5f6f0ed6d799f847 Mon Sep 17 00:00:00 2001 From: Artem Trokhymchuk Date: Tue, 26 Aug 2025 22:58:27 +0300 Subject: [PATCH 2/3] [InstCombine] add icmp (fptosi %x) -> fcmp %y optimization implementation Add optimization test reducing unneded float-to-int cast when comparing numbers: * icmp sgt (fptosi %x), -> fcmp ogt %x, * icmp sgt (fptosi %x), -> fcmp oge %x, * icmp slt (fptosi %x), -> fcmp olt %x, * icmp slt (fptosi %x), -> fcmp ole %x, --- llvm/include/llvm/IR/PatternMatch.h | 13 +++ .../InstCombine/InstCombineCompares.cpp | 85 +++++++++++++++++++ llvm/test/Transforms/InstCombine/icmp.ll | 48 ++++------- 3 files changed, 114 insertions(+), 32 deletions(-) diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h index 2cb78904dd799..4c833421a2448 100644 --- a/llvm/include/llvm/IR/PatternMatch.h +++ b/llvm/include/llvm/IR/PatternMatch.h @@ -542,6 +542,19 @@ inline api_pred_ty m_MaxSignedValue(const APInt *&V) { return V; } +struct is_minsignedvalue { + bool isValue(const APInt &C) const { return C.isMinSignedValue(); } +}; +/// Match an integer or vector with values having only high bit set +/// (0x80...). +/// For vectors, this includes constants with undefined elements. +inline cst_pred_ty m_MinSignedValue() { + return cst_pred_ty(); +} +inline api_pred_ty m_MinSignedValue(const APInt *&V) { + return V; +} + struct is_negative { bool isValue(const APInt &C) const { return C.isNegative(); } }; diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index 90feddf6dcfe1..1a12db869f837 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -12,6 +12,7 @@ #include "InstCombineInternal.h" #include "llvm/ADT/APFloat.h" +#include "llvm/ADT/APInt.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/Statistic.h" @@ -21,6 +22,7 @@ #include "llvm/Analysis/InstructionSimplify.h" #include "llvm/Analysis/Utils/Local.h" #include "llvm/Analysis/VectorUtils.h" +#include "llvm/IR/CmpPredicate.h" #include "llvm/IR/ConstantRange.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" @@ -7611,6 +7613,87 @@ Instruction *InstCombinerImpl::foldICmpCommutative(CmpPredicate Pred, return nullptr; } +/// Cast integral constant (either scalar or vector) to an appropriate vector +/// one +/// +/// \param C integral contsant to cast +/// \param FPType floating point type to cast to +/// \param Addend addend to add before casting +/// \param DL target data layout +/// +/// \return result constant +static Constant *castIntegralConstantToFloat(Constant *C, Type *FPType, + int Addend, const DataLayout &DL) { + assert(FPType->isFPOrFPVectorTy() && + "fptosi operand must have floating point type"); + + Constant *CWithAddend = ConstantFoldBinaryOpOperands( + Instruction::Add, C, ConstantInt::getSigned(C->getType(), Addend), DL); + if (!CWithAddend) + return nullptr; + return ConstantFoldCastOperand(Instruction::SIToFP, CWithAddend, FPType, DL); +} + +/// Fold icmp (fptosi %arg) C -> fcmp $arg +/// Folds: +/// - icmp sgt %arg -> fcmp ogt %arg +/// - icmp sgt %arg -> fcmp oge %arg ( + 1) +/// - icmp slt %arg -> fcmp olt %arg +/// - icmp slt %arg -> fcmp ole %arg ( - 1) +/// +/// \param ICmp icmp instruction +/// \param IC InstCombiner isntance +/// \param DL target data layout +/// +/// \return folded instruction or nullptr, if failed to combine instructions +static Instruction *foldICmpFToSIToFCmp(ICmpInst &ICmp, InstCombiner &IC, + const DataLayout &DL) { + // Expect that canonical form: first argument is fptosi, second is constant + CmpPredicate Pred; + Value *FloatOp; + Constant *C; + if (!match(&ICmp, m_ICmp(Pred, m_OneUse(m_FPToSI(m_Value(FloatOp))), + m_ImmConstant(C)))) + return nullptr; + + if (Pred != ICmpInst::ICMP_SGT && Pred != ICmpInst::ICMP_SLT) + return nullptr; + + FCmpInst::Predicate FCmpPredicate; + Constant *FCmpConstant{}; + + switch (ICmp.getPredicate()) { + case ICmpInst::ICMP_SGT: + if (match(C, m_Negative())) { + // icmp sgt %arg -> fcmp ogt %arg + FCmpPredicate = FCmpInst::FCMP_OGT; + FCmpConstant = castIntegralConstantToFloat(C, FloatOp->getType(), 0, DL); + } else if (match(C, m_NonNegative()) && !match(C, m_MaxSignedValue())) { + // icmp sgt %arg -> fcmp oge %arg ( + 1) + FCmpPredicate = FCmpInst::FCMP_OGE; + FCmpConstant = castIntegralConstantToFloat(C, FloatOp->getType(), 1, DL); + } + break; + case ICmpInst::ICMP_SLT: + if (match(C, m_StrictlyPositive())) { + // icmp slt %arg -> fcmp olt %arg + FCmpPredicate = FCmpInst::FCMP_OLT; + FCmpConstant = castIntegralConstantToFloat(C, FloatOp->getType(), 0, DL); + } else if (match(C, m_NonPositive()) && !match(C, m_MinSignedValue())) { + // icmp slt %arg -> fcmp ole %arg ( - 1) + FCmpPredicate = FCmpInst::FCMP_OLE; + FCmpConstant = castIntegralConstantToFloat(C, FloatOp->getType(), -1, DL); + } + break; + default: + llvm_unreachable("Unknown icmp comparator"); + } + if (!FCmpConstant) + return nullptr; + + return new FCmpInst(FCmpPredicate, FloatOp, FCmpConstant); +} + Instruction *InstCombinerImpl::visitICmpInst(ICmpInst &I) { bool Changed = false; const SimplifyQuery Q = SQ.getWithInstruction(&I); @@ -7748,6 +7831,8 @@ Instruction *InstCombinerImpl::visitICmpInst(ICmpInst &I) { if (Instruction *Res = foldICmpCommutative(I.getSwappedCmpPredicate(), Op1, Op0, I)) return Res; + if (Instruction *Res = foldICmpFToSIToFCmp(I, *this, DL)) + return Res; if (I.isCommutative()) { if (auto Pair = matchSymmetricPair(I.getOperand(0), I.getOperand(1))) { diff --git a/llvm/test/Transforms/InstCombine/icmp.ll b/llvm/test/Transforms/InstCombine/icmp.ll index eccf9ec39da61..79da4af93e9d5 100644 --- a/llvm/test/Transforms/InstCombine/icmp.ll +++ b/llvm/test/Transforms/InstCombine/icmp.ll @@ -6059,8 +6059,7 @@ define i1 @icmp_samesign_logical_or(i32 %In) { define i1 @float_to_int_comparing_constant1_positive1(float %arg0) { ; CHECK-LABEL: define i1 @float_to_int_comparing_constant1_positive1( ; CHECK-SAME: float [[ARG0:%.*]]) { -; CHECK-NEXT: [[V0:%.*]] = fptosi float [[ARG0]] to i32 -; CHECK-NEXT: [[V1:%.*]] = icmp sgt i32 [[V0]], -1 +; CHECK-NEXT: [[V1:%.*]] = fcmp ogt float [[ARG0]], -1.000000e+00 ; CHECK-NEXT: ret i1 [[V1]] ; %v0 = fptosi float %arg0 to i32 @@ -6072,8 +6071,7 @@ define i1 @float_to_int_comparing_constant1_positive1(float %arg0) { define i1 @float_to_int_comparing_constant1_positive2(float %arg0) { ; CHECK-LABEL: define i1 @float_to_int_comparing_constant1_positive2( ; CHECK-SAME: float [[ARG0:%.*]]) { -; CHECK-NEXT: [[V0:%.*]] = fptosi float [[ARG0]] to i32 -; CHECK-NEXT: [[V1:%.*]] = icmp sgt i32 [[V0]], 1 +; CHECK-NEXT: [[V1:%.*]] = fcmp oge float [[ARG0]], 2.000000e+00 ; CHECK-NEXT: ret i1 [[V1]] ; %v0 = fptosi float %arg0 to i32 @@ -6085,8 +6083,7 @@ define i1 @float_to_int_comparing_constant1_positive2(float %arg0) { define i1 @float_to_int_comparing_constant2_positive1(float %arg0) { ; CHECK-LABEL: define i1 @float_to_int_comparing_constant2_positive1( ; CHECK-SAME: float [[ARG0:%.*]]) { -; CHECK-NEXT: [[V0:%.*]] = fptosi float [[ARG0]] to i32 -; CHECK-NEXT: [[V1:%.*]] = icmp slt i32 [[V0]], 1 +; CHECK-NEXT: [[V1:%.*]] = fcmp olt float [[ARG0]], 1.000000e+00 ; CHECK-NEXT: ret i1 [[V1]] ; %v0 = fptosi float %arg0 to i32 @@ -6098,8 +6095,7 @@ define i1 @float_to_int_comparing_constant2_positive1(float %arg0) { define i1 @float_to_int_comparing_constant2_positive2(float %arg0) { ; CHECK-LABEL: define i1 @float_to_int_comparing_constant2_positive2( ; CHECK-SAME: float [[ARG0:%.*]]) { -; CHECK-NEXT: [[V0:%.*]] = fptosi float [[ARG0]] to i32 -; CHECK-NEXT: [[V1:%.*]] = icmp slt i32 [[V0]], 0 +; CHECK-NEXT: [[V1:%.*]] = fcmp ole float [[ARG0]], -1.000000e+00 ; CHECK-NEXT: ret i1 [[V1]] ; %v0 = fptosi float %arg0 to i32 @@ -6110,8 +6106,7 @@ define i1 @float_to_int_comparing_constant2_positive2(float %arg0) { define i1 @double_to_int_comparing_constant1_positive1(double %arg0) { ; CHECK-LABEL: define i1 @double_to_int_comparing_constant1_positive1( ; CHECK-SAME: double [[ARG0:%.*]]) { -; CHECK-NEXT: [[V0:%.*]] = fptosi double [[ARG0]] to i32 -; CHECK-NEXT: [[V1:%.*]] = icmp sgt i32 [[V0]], -1 +; CHECK-NEXT: [[V1:%.*]] = fcmp ogt double [[ARG0]], -1.000000e+00 ; CHECK-NEXT: ret i1 [[V1]] ; %v0 = fptosi double %arg0 to i32 @@ -6122,8 +6117,7 @@ define i1 @double_to_int_comparing_constant1_positive1(double %arg0) { define i1 @double_to_int_comparing_constant1_positive2(double %arg0) { ; CHECK-LABEL: define i1 @double_to_int_comparing_constant1_positive2( ; CHECK-SAME: double [[ARG0:%.*]]) { -; CHECK-NEXT: [[V0:%.*]] = fptosi double [[ARG0]] to i32 -; CHECK-NEXT: [[V1:%.*]] = icmp sgt i32 [[V0]], 1 +; CHECK-NEXT: [[V1:%.*]] = fcmp oge double [[ARG0]], 2.000000e+00 ; CHECK-NEXT: ret i1 [[V1]] ; %v0 = fptosi double %arg0 to i32 @@ -6134,8 +6128,7 @@ define i1 @double_to_int_comparing_constant1_positive2(double %arg0) { define i1 @fp16_to_int_comparing_constant2_positive1(half %arg0) { ; CHECK-LABEL: define i1 @fp16_to_int_comparing_constant2_positive1( ; CHECK-SAME: half [[ARG0:%.*]]) { -; CHECK-NEXT: [[V0:%.*]] = fptosi half [[ARG0]] to i32 -; CHECK-NEXT: [[V1:%.*]] = icmp slt i32 [[V0]], 1 +; CHECK-NEXT: [[V1:%.*]] = fcmp olt half [[ARG0]], 0xH3C00 ; CHECK-NEXT: ret i1 [[V1]] ; %v0 = fptosi half %arg0 to i32 @@ -6146,8 +6139,7 @@ define i1 @fp16_to_int_comparing_constant2_positive1(half %arg0) { define i1 @fp16_to_int_comparing_constant2_positive2(half %arg0) { ; CHECK-LABEL: define i1 @fp16_to_int_comparing_constant2_positive2( ; CHECK-SAME: half [[ARG0:%.*]]) { -; CHECK-NEXT: [[V0:%.*]] = fptosi half [[ARG0]] to i32 -; CHECK-NEXT: [[V1:%.*]] = icmp slt i32 [[V0]], 0 +; CHECK-NEXT: [[V1:%.*]] = fcmp ole half [[ARG0]], 0xHBC00 ; CHECK-NEXT: ret i1 [[V1]] ; %v0 = fptosi half %arg0 to i32 @@ -6222,8 +6214,7 @@ define i1 @float_to_int_comparing_constant2_negative2(float %arg0) { define <2 x i1> @float_to_int_comparing_constant_vec_positive1(<2 x float> %arg0) { ; CHECK-LABEL: define <2 x i1> @float_to_int_comparing_constant_vec_positive1( ; CHECK-SAME: <2 x float> [[ARG0:%.*]]) { -; CHECK-NEXT: [[V0:%.*]] = fptosi <2 x float> [[ARG0]] to <2 x i32> -; CHECK-NEXT: [[V1:%.*]] = icmp sgt <2 x i32> [[V0]], splat (i32 -1) +; CHECK-NEXT: [[V1:%.*]] = fcmp ogt <2 x float> [[ARG0]], splat (float -1.000000e+00) ; CHECK-NEXT: ret <2 x i1> [[V1]] ; %v0 = fptosi <2 x float> %arg0 to <2 x i32> @@ -6234,8 +6225,7 @@ define <2 x i1> @float_to_int_comparing_constant_vec_positive1(<2 x float> %arg0 define <2 x i1> @float_to_int_comparing_constant_vec_positive2(<2 x float> %arg0) { ; CHECK-LABEL: define <2 x i1> @float_to_int_comparing_constant_vec_positive2( ; CHECK-SAME: <2 x float> [[ARG0:%.*]]) { -; CHECK-NEXT: [[V0:%.*]] = fptosi <2 x float> [[ARG0]] to <2 x i32> -; CHECK-NEXT: [[V1:%.*]] = icmp sgt <2 x i32> [[V0]], +; CHECK-NEXT: [[V1:%.*]] = fcmp oge <2 x float> [[ARG0]], ; CHECK-NEXT: ret <2 x i1> [[V1]] ; %v0 = fptosi <2 x float> %arg0 to <2 x i32> @@ -6247,8 +6237,7 @@ define <2 x i1> @float_to_int_comparing_constant_vec_positive2(<2 x float> %arg0 define <2 x i1> @float_to_int_comparing_constant_vec_positive3(<2 x float> %arg0) { ; CHECK-LABEL: define <2 x i1> @float_to_int_comparing_constant_vec_positive3( ; CHECK-SAME: <2 x float> [[ARG0:%.*]]) { -; CHECK-NEXT: [[V0:%.*]] = fptosi <2 x float> [[ARG0]] to <2 x i32> -; CHECK-NEXT: [[V1:%.*]] = icmp slt <2 x i32> [[V0]], splat (i32 1) +; CHECK-NEXT: [[V1:%.*]] = fcmp olt <2 x float> [[ARG0]], splat (float 1.000000e+00) ; CHECK-NEXT: ret <2 x i1> [[V1]] ; %v0 = fptosi <2 x float> %arg0 to <2 x i32> @@ -6259,8 +6248,7 @@ define <2 x i1> @float_to_int_comparing_constant_vec_positive3(<2 x float> %arg0 define <2 x i1> @float_to_int_comparing_constant_vec_positive4(<2 x float> %arg0) { ; CHECK-LABEL: define <2 x i1> @float_to_int_comparing_constant_vec_positive4( ; CHECK-SAME: <2 x float> [[ARG0:%.*]]) { -; CHECK-NEXT: [[V0:%.*]] = fptosi <2 x float> [[ARG0]] to <2 x i32> -; CHECK-NEXT: [[V1:%.*]] = icmp slt <2 x i32> [[V0]], +; CHECK-NEXT: [[V1:%.*]] = fcmp ole <2 x float> [[ARG0]], ; CHECK-NEXT: ret <2 x i1> [[V1]] ; %v0 = fptosi <2 x float> %arg0 to <2 x i32> @@ -6271,8 +6259,7 @@ define <2 x i1> @float_to_int_comparing_constant_vec_positive4(<2 x float> %arg0 define <2 x i1> @half_to_int_comparing_constant_vec_positive1(<2 x half> %arg0) { ; CHECK-LABEL: define <2 x i1> @half_to_int_comparing_constant_vec_positive1( ; CHECK-SAME: <2 x half> [[ARG0:%.*]]) { -; CHECK-NEXT: [[V0:%.*]] = fptosi <2 x half> [[ARG0]] to <2 x i32> -; CHECK-NEXT: [[V1:%.*]] = icmp sgt <2 x i32> [[V0]], splat (i32 -1) +; CHECK-NEXT: [[V1:%.*]] = fcmp ogt <2 x half> [[ARG0]], splat (half 0xHBC00) ; CHECK-NEXT: ret <2 x i1> [[V1]] ; %v0 = fptosi <2 x half> %arg0 to <2 x i32> @@ -6283,8 +6270,7 @@ define <2 x i1> @half_to_int_comparing_constant_vec_positive1(<2 x half> %arg0) define <2 x i1> @half_to_int_comparing_constant_vec_positive2(<2 x half> %arg0) { ; CHECK-LABEL: define <2 x i1> @half_to_int_comparing_constant_vec_positive2( ; CHECK-SAME: <2 x half> [[ARG0:%.*]]) { -; CHECK-NEXT: [[V0:%.*]] = fptosi <2 x half> [[ARG0]] to <2 x i32> -; CHECK-NEXT: [[V1:%.*]] = icmp sgt <2 x i32> [[V0]], +; CHECK-NEXT: [[V1:%.*]] = fcmp oge <2 x half> [[ARG0]], ; CHECK-NEXT: ret <2 x i1> [[V1]] ; %v0 = fptosi <2 x half> %arg0 to <2 x i32> @@ -6295,8 +6281,7 @@ define <2 x i1> @half_to_int_comparing_constant_vec_positive2(<2 x half> %arg0) define <2 x i1> @double_to_int_comparing_constant_vec_positive3(<2 x double> %arg0) { ; CHECK-LABEL: define <2 x i1> @double_to_int_comparing_constant_vec_positive3( ; CHECK-SAME: <2 x double> [[ARG0:%.*]]) { -; CHECK-NEXT: [[V0:%.*]] = fptosi <2 x double> [[ARG0]] to <2 x i32> -; CHECK-NEXT: [[V1:%.*]] = icmp slt <2 x i32> [[V0]], splat (i32 1) +; CHECK-NEXT: [[V1:%.*]] = fcmp olt <2 x double> [[ARG0]], splat (double 1.000000e+00) ; CHECK-NEXT: ret <2 x i1> [[V1]] ; %v0 = fptosi <2 x double> %arg0 to <2 x i32> @@ -6307,8 +6292,7 @@ define <2 x i1> @double_to_int_comparing_constant_vec_positive3(<2 x double> %ar define <2 x i1> @double_to_int_comparing_constant_vec_positive4(<2 x double> %arg0) { ; CHECK-LABEL: define <2 x i1> @double_to_int_comparing_constant_vec_positive4( ; CHECK-SAME: <2 x double> [[ARG0:%.*]]) { -; CHECK-NEXT: [[V0:%.*]] = fptosi <2 x double> [[ARG0]] to <2 x i32> -; CHECK-NEXT: [[V1:%.*]] = icmp slt <2 x i32> [[V0]], +; CHECK-NEXT: [[V1:%.*]] = fcmp ole <2 x double> [[ARG0]], ; CHECK-NEXT: ret <2 x i1> [[V1]] ; %v0 = fptosi <2 x double> %arg0 to <2 x i32> From bf38c1bdd526967990cd626182516e76a566ddab Mon Sep 17 00:00:00 2001 From: Artem Trokhymchuk Date: Sun, 7 Sep 2025 15:12:53 +0300 Subject: [PATCH 3/3] [InstCombine] add icmp (fptosi %x) -> fcmp %y fix regression tests Fix regression in the llvm/test/Transforms/PGOProfile/chr.ll after optimizing fptosi cast in icmp. --- llvm/test/Transforms/PGOProfile/chr.ll | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/llvm/test/Transforms/PGOProfile/chr.ll b/llvm/test/Transforms/PGOProfile/chr.ll index f0a1574c5f209..4133f56f9a630 100644 --- a/llvm/test/Transforms/PGOProfile/chr.ll +++ b/llvm/test/Transforms/PGOProfile/chr.ll @@ -1128,9 +1128,7 @@ define void @test_chr_11(ptr %i, i32 %x) !prof !14 { ; CHECK-NEXT: [[CONV:%.*]] = sitofp i32 [[DOTFR1]] to double ; CHECK-NEXT: [[DIV:%.*]] = fdiv double 1.000000e+00, [[CONV]] ; CHECK-NEXT: [[MUL16:%.*]] = fmul double [[DIV]], [[CONV]] -; CHECK-NEXT: [[CONV717:%.*]] = fptosi double [[MUL16]] to i32 -; CHECK-NEXT: [[CONV717_FR:%.*]] = freeze i32 [[CONV717]] -; CHECK-NEXT: [[CMP18:%.*]] = icmp sgt i32 [[CONV717_FR]], 0 +; CHECK-NEXT: [[CMP18:%.*]] = fcmp oge double [[MUL16]], 1.000000e+00 ; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[CMP18]] ; CHECK-NEXT: br i1 [[TMP3]], label [[BB0:%.*]], label [[ENTRY_SPLIT_NONCHR:%.*]], !prof [[PROF15]] ; CHECK: bb0: @@ -1146,8 +1144,7 @@ define void @test_chr_11(ptr %i, i32 %x) !prof !14 { ; CHECK-NEXT: [[CONV_NONCHR:%.*]] = sitofp i32 [[DOTFR1]] to double ; CHECK-NEXT: [[DIV_NONCHR:%.*]] = fdiv double 1.000000e+00, [[CONV_NONCHR]] ; CHECK-NEXT: [[MUL16_NONCHR:%.*]] = fmul double [[DIV_NONCHR]], [[CONV_NONCHR]] -; CHECK-NEXT: [[CONV717_NONCHR:%.*]] = fptosi double [[MUL16_NONCHR]] to i32 -; CHECK-NEXT: [[CMP18_NONCHR:%.*]] = icmp slt i32 [[CONV717_NONCHR]], 1 +; CHECK-NEXT: [[CMP18_NONCHR:%.*]] = fcmp olt double [[MUL16_NONCHR]], 1.000000e+00 ; CHECK-NEXT: br i1 [[CMP18_NONCHR]], label [[BB3]], label [[BB2_NONCHR:%.*]], !prof [[PROF16]] ; CHECK: bb2.nonchr: ; CHECK-NEXT: call void @foo()