diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index 49e597171b1c6..55207a8343d0e 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -7286,8 +7286,9 @@ Instruction *InstCombinerImpl::visitICmpInst(ICmpInst &I) { Instruction *InstCombinerImpl::foldFCmpIntToFPConst(FCmpInst &I, Instruction *LHSI, Constant *RHSC) { - if (!isa(RHSC)) return nullptr; - const APFloat &RHS = cast(RHSC)->getValueAPF(); + const APFloat *RHS; + if (!match(RHSC, m_APFloat(RHS))) + return nullptr; // Get the width of the mantissa. We don't want to hack on conversions that // might lose information from the integer, e.g. "i64 -> float" @@ -7302,20 +7303,20 @@ Instruction *InstCombinerImpl::foldFCmpIntToFPConst(FCmpInst &I, FCmpInst::Predicate P = I.getPredicate(); bool IsExact = false; APSInt RHSCvt(IntWidth, LHSUnsigned); - RHS.convertToInteger(RHSCvt, APFloat::rmNearestTiesToEven, &IsExact); + RHS->convertToInteger(RHSCvt, APFloat::rmNearestTiesToEven, &IsExact); // If the floating point constant isn't an integer value, we know if we will // ever compare equal / not equal to it. if (!IsExact) { // TODO: Can never be -0.0 and other non-representable values - APFloat RHSRoundInt(RHS); + APFloat RHSRoundInt(*RHS); RHSRoundInt.roundToIntegral(APFloat::rmNearestTiesToEven); - if (RHS != RHSRoundInt) { + if (*RHS != RHSRoundInt) { if (P == FCmpInst::FCMP_OEQ || P == FCmpInst::FCMP_UEQ) - return replaceInstUsesWith(I, Builder.getFalse()); + return replaceInstUsesWith(I, ConstantInt::getFalse(I.getType())); assert(P == FCmpInst::FCMP_ONE || P == FCmpInst::FCMP_UNE); - return replaceInstUsesWith(I, Builder.getTrue()); + return replaceInstUsesWith(I, ConstantInt::getTrue(I.getType())); } } @@ -7332,9 +7333,9 @@ Instruction *InstCombinerImpl::foldFCmpIntToFPConst(FCmpInst &I, // to distinguish it from one less than that value. if ((int)IntWidth > MantissaWidth) { // Conversion would lose accuracy. Check if loss can impact comparison. - int Exp = ilogb(RHS); + int Exp = ilogb(*RHS); if (Exp == APFloat::IEK_Inf) { - int MaxExponent = ilogb(APFloat::getLargest(RHS.getSemantics())); + int MaxExponent = ilogb(APFloat::getLargest(RHS->getSemantics())); if (MaxExponent < (int)IntWidth - !LHSUnsigned) // Conversion could create infinity. return nullptr; @@ -7350,7 +7351,7 @@ Instruction *InstCombinerImpl::foldFCmpIntToFPConst(FCmpInst &I, // Otherwise, we can potentially simplify the comparison. We know that it // will always come through as an integer value and we know the constant is // not a NAN (it would have been previously simplified). - assert(!RHS.isNaN() && "NaN comparison not already folded!"); + assert(!RHS->isNaN() && "NaN comparison not already folded!"); ICmpInst::Predicate Pred; switch (I.getPredicate()) { @@ -7380,9 +7381,9 @@ Instruction *InstCombinerImpl::foldFCmpIntToFPConst(FCmpInst &I, Pred = ICmpInst::ICMP_NE; break; case FCmpInst::FCMP_ORD: - return replaceInstUsesWith(I, Builder.getTrue()); + return replaceInstUsesWith(I, ConstantInt::getTrue(I.getType())); case FCmpInst::FCMP_UNO: - return replaceInstUsesWith(I, Builder.getFalse()); + return replaceInstUsesWith(I, ConstantInt::getFalse(I.getType())); } // Now we know that the APFloat is a normal number, zero or inf. @@ -7392,50 +7393,50 @@ Instruction *InstCombinerImpl::foldFCmpIntToFPConst(FCmpInst &I, if (!LHSUnsigned) { // If the RHS value is > SignedMax, fold the comparison. This handles +INF // and large values. - APFloat SMax(RHS.getSemantics()); + APFloat SMax(RHS->getSemantics()); SMax.convertFromAPInt(APInt::getSignedMaxValue(IntWidth), true, APFloat::rmNearestTiesToEven); - if (SMax < RHS) { // smax < 13123.0 + if (SMax < *RHS) { // smax < 13123.0 if (Pred == ICmpInst::ICMP_NE || Pred == ICmpInst::ICMP_SLT || Pred == ICmpInst::ICMP_SLE) - return replaceInstUsesWith(I, Builder.getTrue()); - return replaceInstUsesWith(I, Builder.getFalse()); + return replaceInstUsesWith(I, ConstantInt::getTrue(I.getType())); + return replaceInstUsesWith(I, ConstantInt::getFalse(I.getType())); } } else { // If the RHS value is > UnsignedMax, fold the comparison. This handles // +INF and large values. - APFloat UMax(RHS.getSemantics()); + APFloat UMax(RHS->getSemantics()); UMax.convertFromAPInt(APInt::getMaxValue(IntWidth), false, APFloat::rmNearestTiesToEven); - if (UMax < RHS) { // umax < 13123.0 + if (UMax < *RHS) { // umax < 13123.0 if (Pred == ICmpInst::ICMP_NE || Pred == ICmpInst::ICMP_ULT || Pred == ICmpInst::ICMP_ULE) - return replaceInstUsesWith(I, Builder.getTrue()); - return replaceInstUsesWith(I, Builder.getFalse()); + return replaceInstUsesWith(I, ConstantInt::getTrue(I.getType())); + return replaceInstUsesWith(I, ConstantInt::getFalse(I.getType())); } } if (!LHSUnsigned) { // See if the RHS value is < SignedMin. - APFloat SMin(RHS.getSemantics()); + APFloat SMin(RHS->getSemantics()); SMin.convertFromAPInt(APInt::getSignedMinValue(IntWidth), true, APFloat::rmNearestTiesToEven); - if (SMin > RHS) { // smin > 12312.0 + if (SMin > *RHS) { // smin > 12312.0 if (Pred == ICmpInst::ICMP_NE || Pred == ICmpInst::ICMP_SGT || Pred == ICmpInst::ICMP_SGE) - return replaceInstUsesWith(I, Builder.getTrue()); - return replaceInstUsesWith(I, Builder.getFalse()); + return replaceInstUsesWith(I, ConstantInt::getTrue(I.getType())); + return replaceInstUsesWith(I, ConstantInt::getFalse(I.getType())); } } else { // See if the RHS value is < UnsignedMin. - APFloat UMin(RHS.getSemantics()); + APFloat UMin(RHS->getSemantics()); UMin.convertFromAPInt(APInt::getMinValue(IntWidth), false, APFloat::rmNearestTiesToEven); - if (UMin > RHS) { // umin > 12312.0 + if (UMin > *RHS) { // umin > 12312.0 if (Pred == ICmpInst::ICMP_NE || Pred == ICmpInst::ICMP_UGT || Pred == ICmpInst::ICMP_UGE) - return replaceInstUsesWith(I, Builder.getTrue()); - return replaceInstUsesWith(I, Builder.getFalse()); + return replaceInstUsesWith(I, ConstantInt::getTrue(I.getType())); + return replaceInstUsesWith(I, ConstantInt::getFalse(I.getType())); } } @@ -7445,8 +7446,8 @@ Instruction *InstCombinerImpl::foldFCmpIntToFPConst(FCmpInst &I, // Don't do this for zero, because -0.0 is not fractional. APSInt RHSInt(IntWidth, LHSUnsigned); bool IsExact; - RHS.convertToInteger(RHSInt, APFloat::rmTowardZero, &IsExact); - if (!RHS.isZero()) { + RHS->convertToInteger(RHSInt, APFloat::rmTowardZero, &IsExact); + if (!RHS->isZero()) { if (!IsExact) { // If we had a comparison against a fractional value, we have to adjust // the compare predicate and sometimes the value. RHSC is rounded towards @@ -7454,57 +7455,57 @@ Instruction *InstCombinerImpl::foldFCmpIntToFPConst(FCmpInst &I, switch (Pred) { default: llvm_unreachable("Unexpected integer comparison!"); case ICmpInst::ICMP_NE: // (float)int != 4.4 --> true - return replaceInstUsesWith(I, Builder.getTrue()); + return replaceInstUsesWith(I, ConstantInt::getTrue(I.getType())); case ICmpInst::ICMP_EQ: // (float)int == 4.4 --> false - return replaceInstUsesWith(I, Builder.getFalse()); + return replaceInstUsesWith(I, ConstantInt::getFalse(I.getType())); case ICmpInst::ICMP_ULE: // (float)int <= 4.4 --> int <= 4 // (float)int <= -4.4 --> false - if (RHS.isNegative()) - return replaceInstUsesWith(I, Builder.getFalse()); + if (RHS->isNegative()) + return replaceInstUsesWith(I, ConstantInt::getFalse(I.getType())); break; case ICmpInst::ICMP_SLE: // (float)int <= 4.4 --> int <= 4 // (float)int <= -4.4 --> int < -4 - if (RHS.isNegative()) + if (RHS->isNegative()) Pred = ICmpInst::ICMP_SLT; break; case ICmpInst::ICMP_ULT: // (float)int < -4.4 --> false // (float)int < 4.4 --> int <= 4 - if (RHS.isNegative()) - return replaceInstUsesWith(I, Builder.getFalse()); + if (RHS->isNegative()) + return replaceInstUsesWith(I, ConstantInt::getFalse(I.getType())); Pred = ICmpInst::ICMP_ULE; break; case ICmpInst::ICMP_SLT: // (float)int < -4.4 --> int < -4 // (float)int < 4.4 --> int <= 4 - if (!RHS.isNegative()) + if (!RHS->isNegative()) Pred = ICmpInst::ICMP_SLE; break; case ICmpInst::ICMP_UGT: // (float)int > 4.4 --> int > 4 // (float)int > -4.4 --> true - if (RHS.isNegative()) - return replaceInstUsesWith(I, Builder.getTrue()); + if (RHS->isNegative()) + return replaceInstUsesWith(I, ConstantInt::getTrue(I.getType())); break; case ICmpInst::ICMP_SGT: // (float)int > 4.4 --> int > 4 // (float)int > -4.4 --> int >= -4 - if (RHS.isNegative()) + if (RHS->isNegative()) Pred = ICmpInst::ICMP_SGE; break; case ICmpInst::ICMP_UGE: // (float)int >= -4.4 --> true // (float)int >= 4.4 --> int > 4 - if (RHS.isNegative()) - return replaceInstUsesWith(I, Builder.getTrue()); + if (RHS->isNegative()) + return replaceInstUsesWith(I, ConstantInt::getTrue(I.getType())); Pred = ICmpInst::ICMP_UGT; break; case ICmpInst::ICMP_SGE: // (float)int >= -4.4 --> int >= -4 // (float)int >= 4.4 --> int > 4 - if (!RHS.isNegative()) + if (!RHS->isNegative()) Pred = ICmpInst::ICMP_SGT; break; } @@ -7513,7 +7514,8 @@ Instruction *InstCombinerImpl::foldFCmpIntToFPConst(FCmpInst &I, // Lower this FP comparison into an appropriate integer version of the // comparison. - return new ICmpInst(Pred, LHSI->getOperand(0), Builder.getInt(RHSInt)); + return new ICmpInst(Pred, LHSI->getOperand(0), + ConstantInt::get(LHSI->getOperand(0)->getType(), RHSInt)); } /// Fold (C / X) < 0.0 --> X < 0.0 if possible. Swap predicate if necessary. diff --git a/llvm/test/Transforms/InstCombine/cast-int-fcmp-eq-0.ll b/llvm/test/Transforms/InstCombine/cast-int-fcmp-eq-0.ll index b04033d94a26f..68a386ec00423 100644 --- a/llvm/test/Transforms/InstCombine/cast-int-fcmp-eq-0.ll +++ b/llvm/test/Transforms/InstCombine/cast-int-fcmp-eq-0.ll @@ -509,3 +509,61 @@ define i1 @i128_cast_cmp_oeq_int_inf_uitofp(i128 %i) { %cmp = fcmp oeq float %f, 0x7FF0000000000000 ret i1 %cmp } + +define <2 x i1> @i32_vec_cast_cmp_oeq_vec_int_0_sitofp(<2 x i32> %i) { +; CHECK-LABEL: @i32_vec_cast_cmp_oeq_vec_int_0_sitofp( +; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i32> [[I:%.*]], zeroinitializer +; CHECK-NEXT: ret <2 x i1> [[CMP]] +; + %f = sitofp <2 x i32> %i to <2 x float> + %cmp = fcmp oeq <2 x float> %f, + ret <2 x i1> %cmp +} + +define <2 x i1> @i32_vec_cast_cmp_oeq_vec_int_n0_sitofp(<2 x i32> %i) { +; CHECK-LABEL: @i32_vec_cast_cmp_oeq_vec_int_n0_sitofp( +; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i32> [[I:%.*]], zeroinitializer +; CHECK-NEXT: ret <2 x i1> [[CMP]] +; + %f = sitofp <2 x i32> %i to <2 x float> + %cmp = fcmp oeq <2 x float> %f, + ret <2 x i1> %cmp +} + +define <2 x i1> @i32_vec_cast_cmp_oeq_vec_int_i32imax_sitofp(<2 x i32> %i) { +; CHECK-LABEL: @i32_vec_cast_cmp_oeq_vec_int_i32imax_sitofp( +; CHECK-NEXT: [[F:%.*]] = sitofp <2 x i32> [[I:%.*]] to <2 x float> +; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq <2 x float> [[F]], +; CHECK-NEXT: ret <2 x i1> [[CMP]] +; + %f = sitofp <2 x i32> %i to <2 x float> + %cmp = fcmp oeq <2 x float> %f, + ret <2 x i1> %cmp +} + +define <2 x i1> @i32_vec_cast_cmp_oeq_vec_int_negi32umax_sitofp(<2 x i32> %i) { +; CHECK-LABEL: @i32_vec_cast_cmp_oeq_vec_int_negi32umax_sitofp( +; CHECK-NEXT: ret <2 x i1> zeroinitializer +; + %f = sitofp <2 x i32> %i to <2 x float> + %cmp = fcmp oeq <2 x float> %f, + ret <2 x i1> %cmp +} + +define <2 x i1> @i32_vec_cast_cmp_oeq_vec_half_sitofp(<2 x i32> %i) { +; CHECK-LABEL: @i32_vec_cast_cmp_oeq_vec_half_sitofp( +; CHECK-NEXT: ret <2 x i1> zeroinitializer +; + %f = sitofp <2 x i32> %i to <2 x float> + %cmp = fcmp oeq <2 x float> %f, + ret <2 x i1> %cmp +} + +define <2 x i1> @i32_vec_cast_cmp_oeq_vec_int_inf_sitofp(<2 x i32> %i) { +; CHECK-LABEL: @i32_vec_cast_cmp_oeq_vec_int_inf_sitofp( +; CHECK-NEXT: ret <2 x i1> zeroinitializer +; + %f = sitofp <2 x i32> %i to <2 x float> + %cmp = fcmp oeq <2 x float> %f, + ret <2 x i1> %cmp +} diff --git a/llvm/test/Transforms/InstCombine/clamp-to-minmax.ll b/llvm/test/Transforms/InstCombine/clamp-to-minmax.ll index fad1176cc18fa..9da9eb36d381f 100644 --- a/llvm/test/Transforms/InstCombine/clamp-to-minmax.ll +++ b/llvm/test/Transforms/InstCombine/clamp-to-minmax.ll @@ -566,3 +566,20 @@ define i32 @mixed_clamp_to_i32_2(float %x) { %r = select i1 %lo_cmp, i32 1, i32 %i32_min ret i32 %r } + + +define <2 x float> @mixed_clamp_to_float_vec(<2 x i32> %x) { +; CHECK-LABEL: @mixed_clamp_to_float_vec( +; CHECK-NEXT: [[SI_MIN:%.*]] = call <2 x i32> @llvm.smin.v2i32(<2 x i32> [[X:%.*]], <2 x i32> ) +; CHECK-NEXT: [[R1:%.*]] = call <2 x i32> @llvm.smax.v2i32(<2 x i32> [[SI_MIN]], <2 x i32> ) +; CHECK-NEXT: [[R:%.*]] = sitofp <2 x i32> [[R1]] to <2 x float> +; CHECK-NEXT: ret <2 x float> [[R]] +; + %si_min_cmp = icmp sgt <2 x i32> %x, + %si_min = select <2 x i1> %si_min_cmp, <2 x i32> , <2 x i32> %x + %f_min = sitofp <2 x i32> %si_min to <2 x float> + %f_x = sitofp <2 x i32> %x to <2 x float> + %lo_cmp = fcmp ult <2 x float> %f_x, + %r = select <2 x i1> %lo_cmp, <2 x float> , <2 x float> %f_min + ret <2 x float> %r +} diff --git a/llvm/test/Transforms/InstCombine/sitofp.ll b/llvm/test/Transforms/InstCombine/sitofp.ll index 5e0cf94488007..cc6b6425eb03c 100644 --- a/llvm/test/Transforms/InstCombine/sitofp.ll +++ b/llvm/test/Transforms/InstCombine/sitofp.ll @@ -378,3 +378,40 @@ define i12 @u32_half_u12(i32 %x) { %r = fptoui half %h to i12 ret i12 %r } + +define <2 x i1> @i8_vec_sitofp_test1(<2 x i8> %A) { +; CHECK-LABEL: @i8_vec_sitofp_test1( +; CHECK-NEXT: ret <2 x i1> +; + %B = sitofp <2 x i8> %A to <2 x double> + %C = fcmp ult <2 x double> %B, + ret <2 x i1> %C +} + +define <2 x i1> @i8_vec_sitofp_test2(<2 x i8> %A) { +; CHECK-LABEL: @i8_vec_sitofp_test2( +; CHECK-NEXT: ret <2 x i1> +; + %B = sitofp <2 x i8> %A to <2 x double> + %C = fcmp ugt <2 x double> %B, + ret <2 x i1> %C +} + +define <2 x i1> @i8_vec_sitofp_test3(<2 x i8> %A) { +; CHECK-LABEL: @i8_vec_sitofp_test3( +; CHECK-NEXT: ret <2 x i1> +; + %B = sitofp <2 x i8> %A to <2 x double> + %C = fcmp ule <2 x double> %B, + ret <2 x i1> %C +} + +define <2 x i1> @i8_vec_sitofp_test4(<2 x i8> %A) { +; CHECK-LABEL: @i8_vec_sitofp_test4( +; CHECK-NEXT: [[C:%.*]] = icmp ne <2 x i8> [[A:%.*]], +; CHECK-NEXT: ret <2 x i1> [[C]] +; + %B = sitofp <2 x i8> %A to <2 x double> + %C = fcmp ult <2 x double> %B, + ret <2 x i1> %C +}