diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp index da32542cf7870..4bdca4266308a 100755 --- a/llvm/lib/Analysis/ConstantFolding.cpp +++ b/llvm/lib/Analysis/ConstantFolding.cpp @@ -2315,6 +2315,11 @@ static bool mayFoldConstrained(ConstrainedFPIntrinsic *CI, if (ORM == RoundingMode::Dynamic) return false; + // If NaN is produced, do not fold such call. In runtime it can be trapped + // and properly handled. + if (St == APFloat::opStatus::opInvalidOp) + return false; + // If FP exceptions are ignored, fold the call, even if such exception is // raised. if (EB && *EB != fp::ExceptionBehavior::ebStrict) @@ -2441,17 +2446,22 @@ static Constant *ConstantFoldScalarCall1(StringRef Name, } if (auto *Op = dyn_cast(Operands[0])) { + APFloat U = Op->getValueAPF(); + if (IntrinsicID == Intrinsic::convert_to_fp16) { - APFloat Val(Op->getValueAPF()); + APFloat Val(U); + if (Val.isNaN()) + return nullptr; bool lost = false; - Val.convert(APFloat::IEEEhalf(), APFloat::rmNearestTiesToEven, &lost); + APFloat::opStatus Status = + Val.convert(APFloat::IEEEhalf(), APFloat::rmNearestTiesToEven, &lost); + if (Status == APFloat::opInvalidOp) + return nullptr; return ConstantInt::get(Ty->getContext(), Val.bitcastToAPInt()); } - APFloat U = Op->getValueAPF(); - if (IntrinsicID == Intrinsic::wasm_trunc_signed || IntrinsicID == Intrinsic::wasm_trunc_unsigned) { bool Signed = IntrinsicID == Intrinsic::wasm_trunc_signed; @@ -2473,6 +2483,8 @@ static Constant *ConstantFoldScalarCall1(StringRef Name, if (IntrinsicID == Intrinsic::fptoui_sat || IntrinsicID == Intrinsic::fptosi_sat) { + if (U.isNaN()) + return nullptr; // convertToInteger() already has the desired saturation semantics. APSInt Int(Ty->getIntegerBitWidth(), IntrinsicID == Intrinsic::fptoui_sat); @@ -2502,38 +2514,6 @@ static Constant *ConstantFoldScalarCall1(StringRef Name, !Ty->isIntegerTy()) return nullptr; - // Use internal versions of these intrinsics. - - if (IntrinsicID == Intrinsic::nearbyint || IntrinsicID == Intrinsic::rint) { - U.roundToIntegral(APFloat::rmNearestTiesToEven); - return ConstantFP::get(Ty->getContext(), U); - } - - if (IntrinsicID == Intrinsic::round) { - U.roundToIntegral(APFloat::rmNearestTiesToAway); - return ConstantFP::get(Ty->getContext(), U); - } - - if (IntrinsicID == Intrinsic::roundeven) { - U.roundToIntegral(APFloat::rmNearestTiesToEven); - return ConstantFP::get(Ty->getContext(), U); - } - - if (IntrinsicID == Intrinsic::ceil) { - U.roundToIntegral(APFloat::rmTowardPositive); - return ConstantFP::get(Ty->getContext(), U); - } - - if (IntrinsicID == Intrinsic::floor) { - U.roundToIntegral(APFloat::rmTowardNegative); - return ConstantFP::get(Ty->getContext(), U); - } - - if (IntrinsicID == Intrinsic::trunc) { - U.roundToIntegral(APFloat::rmTowardZero); - return ConstantFP::get(Ty->getContext(), U); - } - if (IntrinsicID == Intrinsic::fabs) { U.clearSign(); return ConstantFP::get(Ty->getContext(), U); @@ -2552,53 +2532,6 @@ static Constant *ConstantFoldScalarCall1(StringRef Name, return ConstantFP::get(Ty->getContext(), minimum(FractU, AlmostOne)); } - // Rounding operations (floor, trunc, ceil, round and nearbyint) do not - // raise FP exceptions, unless the argument is signaling NaN. - - std::optional RM; - switch (IntrinsicID) { - default: - break; - case Intrinsic::experimental_constrained_nearbyint: - case Intrinsic::experimental_constrained_rint: { - auto CI = cast(Call); - RM = CI->getRoundingMode(); - if (!RM || *RM == RoundingMode::Dynamic) - return nullptr; - break; - } - case Intrinsic::experimental_constrained_round: - RM = APFloat::rmNearestTiesToAway; - break; - case Intrinsic::experimental_constrained_ceil: - RM = APFloat::rmTowardPositive; - break; - case Intrinsic::experimental_constrained_floor: - RM = APFloat::rmTowardNegative; - break; - case Intrinsic::experimental_constrained_trunc: - RM = APFloat::rmTowardZero; - break; - } - if (RM) { - auto CI = cast(Call); - if (U.isFinite()) { - APFloat::opStatus St = U.roundToIntegral(*RM); - if (IntrinsicID == Intrinsic::experimental_constrained_rint && - St == APFloat::opInexact) { - std::optional EB = CI->getExceptionBehavior(); - if (EB == fp::ebStrict) - return nullptr; - } - } else if (U.isSignaling()) { - std::optional EB = CI->getExceptionBehavior(); - if (EB && *EB != fp::ebIgnore) - return nullptr; - U = APFloat::getQNaN(U.getSemantics()); - } - return ConstantFP::get(Ty->getContext(), U); - } - // NVVM float/double to signed/unsigned int32/int64 conversions: switch (IntrinsicID) { // f2i @@ -2686,6 +2619,84 @@ static Constant *ConstantFoldScalarCall1(StringRef Name, } } + // NaN is not a value, it represents an error, don't constfold it. + if (U.isNaN()) + return nullptr; + + // Use internal versions of these intrinsics. + + if (IntrinsicID == Intrinsic::nearbyint || IntrinsicID == Intrinsic::rint) { + U.roundToIntegral(APFloat::rmNearestTiesToEven); + return ConstantFP::get(Ty->getContext(), U); + } + + if (IntrinsicID == Intrinsic::round) { + U.roundToIntegral(APFloat::rmNearestTiesToAway); + return ConstantFP::get(Ty->getContext(), U); + } + + if (IntrinsicID == Intrinsic::roundeven) { + U.roundToIntegral(APFloat::rmNearestTiesToEven); + return ConstantFP::get(Ty->getContext(), U); + } + + if (IntrinsicID == Intrinsic::ceil) { + U.roundToIntegral(APFloat::rmTowardPositive); + return ConstantFP::get(Ty->getContext(), U); + } + + if (IntrinsicID == Intrinsic::floor) { + U.roundToIntegral(APFloat::rmTowardNegative); + return ConstantFP::get(Ty->getContext(), U); + } + + if (IntrinsicID == Intrinsic::trunc) { + U.roundToIntegral(APFloat::rmTowardZero); + return ConstantFP::get(Ty->getContext(), U); + } + + // Rounding operations (floor, trunc, ceil, round and nearbyint) do not + // raise FP exceptions, unless the argument is signaling NaN. + + std::optional RM; + switch (IntrinsicID) { + default: + break; + case Intrinsic::experimental_constrained_nearbyint: + case Intrinsic::experimental_constrained_rint: { + auto CI = cast(Call); + RM = CI->getRoundingMode(); + if (!RM || *RM == RoundingMode::Dynamic) + return nullptr; + break; + } + case Intrinsic::experimental_constrained_round: + RM = APFloat::rmNearestTiesToAway; + break; + case Intrinsic::experimental_constrained_ceil: + RM = APFloat::rmTowardPositive; + break; + case Intrinsic::experimental_constrained_floor: + RM = APFloat::rmTowardNegative; + break; + case Intrinsic::experimental_constrained_trunc: + RM = APFloat::rmTowardZero; + break; + } + if (RM) { + auto CI = cast(Call); + if (U.isFinite()) { + APFloat::opStatus St = U.roundToIntegral(*RM); + if (IntrinsicID == Intrinsic::experimental_constrained_rint && + St == APFloat::opInexact) { + std::optional EB = CI->getExceptionBehavior(); + if (EB == fp::ebStrict) + return nullptr; + } + } + return ConstantFP::get(Ty->getContext(), U); + } + /// We only fold functions with finite arguments. Folding NaN and inf is /// likely to be aborted with an exception anyway, and some host libms /// have known errors raising exceptions. @@ -3182,6 +3193,8 @@ static Constant *ConstantFoldLibCall2(StringRef Name, Type *Ty, const APFloat &Op1V = Op1->getValueAPF(); const APFloat &Op2V = Op2->getValueAPF(); + if (Op1V.isNaN() || Op2V.isNaN()) + return nullptr; switch (Func) { default: @@ -3196,16 +3209,16 @@ static Constant *ConstantFoldLibCall2(StringRef Name, Type *Ty, case LibFunc_fmod: case LibFunc_fmodf: if (TLI->has(Func)) { - APFloat V = Op1->getValueAPF(); - if (APFloat::opStatus::opOK == V.mod(Op2->getValueAPF())) + APFloat V = Op1V; + if (APFloat::opStatus::opOK == V.mod(Op2V)) return ConstantFP::get(Ty->getContext(), V); } break; case LibFunc_remainder: case LibFunc_remainderf: if (TLI->has(Func)) { - APFloat V = Op1->getValueAPF(); - if (APFloat::opStatus::opOK == V.remainder(Op2->getValueAPF())) + APFloat V = Op1V; + if (APFloat::opStatus::opOK == V.remainder(Op2V)) return ConstantFP::get(Ty->getContext(), V); } break; @@ -3299,6 +3312,8 @@ static Constant *ConstantFoldIntrinsicCall2(Intrinsic::ID IntrinsicID, Type *Ty, if (const auto *ConstrIntr = dyn_cast_if_present(Call)) { + if (Op1V.isNaN() || Op2V.isNaN()) + return nullptr; RoundingMode RM = getEvaluationRoundingMode(ConstrIntr); APFloat Res = Op1V; APFloat::opStatus St; @@ -3519,6 +3534,8 @@ static Constant *ConstantFoldIntrinsicCall2(Intrinsic::ID IntrinsicID, Type *Ty, default: break; case Intrinsic::pow: + if (Op1V.isNaN() || Op2V.isNaN()) + return nullptr; return ConstantFoldBinaryFP(pow, Op1V, Op2V, Ty); case Intrinsic::amdgcn_fmul_legacy: // The legacy behaviour is that multiplying +/- 0.0 by anything, even @@ -3531,6 +3548,8 @@ static Constant *ConstantFoldIntrinsicCall2(Intrinsic::ID IntrinsicID, Type *Ty, } else if (auto *Op2C = dyn_cast(Operands[1])) { switch (IntrinsicID) { case Intrinsic::ldexp: { + if (Op1V.isNaN()) + return nullptr; return ConstantFP::get( Ty->getContext(), scalbn(Op1V, Op2C->getSExtValue(), APFloat::rmNearestTiesToEven)); @@ -3551,6 +3570,8 @@ static Constant *ConstantFoldIntrinsicCall2(Intrinsic::ID IntrinsicID, Type *Ty, return ConstantInt::get(Ty, Result); } case Intrinsic::powi: { + if (Op1V.isNaN()) + return nullptr; int Exp = static_cast(Op2C->getSExtValue()); switch (Ty->getTypeID()) { case Type::HalfTyID: @@ -3893,6 +3914,9 @@ static Constant *ConstantFoldScalarCall3(StringRef Name, const APFloat &C3 = Op3->getValueAPF(); if (const auto *ConstrIntr = dyn_cast(Call)) { + if (C1.isNaN() || C2.isNaN() || C3.isNaN()) + return nullptr; + RoundingMode RM = getEvaluationRoundingMode(ConstrIntr); APFloat Res = C1; APFloat::opStatus St; @@ -3924,6 +3948,8 @@ static Constant *ConstantFoldScalarCall3(StringRef Name, } case Intrinsic::fma: case Intrinsic::fmuladd: { + if (C1.isNaN() || C2.isNaN() || C3.isNaN()) + return nullptr; APFloat V = C1; V.fusedMultiplyAdd(C2, C3, APFloat::rmNearestTiesToEven); return ConstantFP::get(Ty->getContext(), V); @@ -4333,6 +4359,9 @@ ConstantFoldScalarFrexpCall(Constant *Op, Type *IntTy) { return {}; const APFloat &U = ConstFP->getValueAPF(); + if (U.isNaN()) + return {}; + int FrexpExp; APFloat FrexpMant = frexp(U, FrexpExp, APFloat::rmNearestTiesToEven); Constant *Result0 = ConstantFP::get(ConstFP->getType(), FrexpMant); diff --git a/llvm/lib/IR/ConstantFold.cpp b/llvm/lib/IR/ConstantFold.cpp index 6a9ef2efa321f..8783029b120fa 100644 --- a/llvm/lib/IR/ConstantFold.cpp +++ b/llvm/lib/IR/ConstantFold.cpp @@ -845,6 +845,8 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode, Constant *C1, if (ConstantFP *CFP2 = dyn_cast(C2)) { const APFloat &C1V = CFP1->getValueAPF(); const APFloat &C2V = CFP2->getValueAPF(); + if (C1V.isNaN() || C2V.isNaN()) + return nullptr; APFloat C3V = C1V; // copy for modification switch (Opcode) { default: diff --git a/llvm/test/Transforms/EarlyCSE/atan.ll b/llvm/test/Transforms/EarlyCSE/atan.ll index 2b7206c0a6aab..18a7bb5ebff90 100644 --- a/llvm/test/Transforms/EarlyCSE/atan.ll +++ b/llvm/test/Transforms/EarlyCSE/atan.ll @@ -136,8 +136,9 @@ define float @callatan2_flush_to_zero() { define float @callatan2_NaN() { ; CHECK-LABEL: @callatan2_NaN( -; CHECK-NEXT: ret float 0x7FF8000000000000 -; +; CHECK-NEXT: [[CALL:%.*]] = call float @atan2f(float 0x7FF8000000000000, float 0x7FF8000000000000) +; CHECK-NEXT: ret float [[CALL]] + %call = call float @atan2f(float 0x7FF8000000000000, float 0x7FF8000000000000) ret float %call } diff --git a/llvm/test/Transforms/InstCombine/frexp.ll b/llvm/test/Transforms/InstCombine/frexp.ll index 6541f0d77a093..6feff85b5d8ba 100644 --- a/llvm/test/Transforms/InstCombine/frexp.ll +++ b/llvm/test/Transforms/InstCombine/frexp.ll @@ -199,7 +199,8 @@ define { float, i32 } @frexp_neginf() { define { float, i32 } @frexp_qnan() { ; CHECK-LABEL: define { float, i32 } @frexp_qnan() { -; CHECK-NEXT: ret { float, i32 } { float 0x7FF8000000000000, i32 0 } +; CHECK-NEXT: [[RET:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float 0x7FF8000000000000) +; CHECK-NEXT: ret { float, i32 } [[RET]] ; %ret = call { float, i32 } @llvm.frexp.f32.i32(float 0x7FF8000000000000) ret { float, i32 } %ret @@ -207,7 +208,8 @@ define { float, i32 } @frexp_qnan() { define { float, i32 } @frexp_snan() { ; CHECK-LABEL: define { float, i32 } @frexp_snan() { -; CHECK-NEXT: ret { float, i32 } { float 0x7FF8000020000000, i32 0 } +; CHECK-NEXT: [[RET:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float 0x7FF0000020000000) +; CHECK-NEXT: ret { float, i32 } [[RET]] ; %ret = call { float, i32 } @llvm.frexp.f32.i32(float bitcast (i32 2139095041 to float)) ret { float, i32 } %ret @@ -263,7 +265,8 @@ define { <2 x float>, <2 x i32> } @frexp_splat_4() { define { <2 x float>, <2 x i32> } @frexp_splat_qnan() { ; CHECK-LABEL: define { <2 x float>, <2 x i32> } @frexp_splat_qnan() { -; CHECK-NEXT: ret { <2 x float>, <2 x i32> } { <2 x float> splat (float 0x7FF8000000000000), <2 x i32> zeroinitializer } +; CHECK-NEXT: [[RET:%.*]] = call { <2 x float>, <2 x i32> } @llvm.frexp.v2f32.v2i32(<2 x float> splat (float 0x7FF8000000000000)) +; CHECK-NEXT: ret { <2 x float>, <2 x i32> } [[RET]] ; %ret = call { <2 x float>, <2 x i32> } @llvm.frexp.v2f32.v2i32(<2 x float> ) ret { <2 x float>, <2 x i32> } %ret diff --git a/llvm/test/Transforms/InstSimplify/constfold-constrained.ll b/llvm/test/Transforms/InstSimplify/constfold-constrained.ll index a9ef7f6a765d1..342acf872ae57 100644 --- a/llvm/test/Transforms/InstSimplify/constfold-constrained.ll +++ b/llvm/test/Transforms/InstSimplify/constfold-constrained.ll @@ -164,23 +164,24 @@ entry: ret double %result } -; Verify that trunc(SNAN) is folded to QNAN if the exception behavior mode is 'ignore'. +; Verify that trunc(SNAN) is not folded if the exception behavior mode is 'ignore'. define double @nonfinite_02() #0 { ; CHECK-LABEL: @nonfinite_02( ; CHECK-NEXT: entry: -; CHECK-NEXT: ret double 0x7FF8000000000000 +; CHECK-NEXT: [[RESULT:%.*]] = call double @llvm.experimental.constrained.trunc.f64(double 0x7FF4000000000000, metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret double [[RESULT]] ; entry: %result = call double @llvm.experimental.constrained.trunc.f64(double 0x7ff4000000000000, metadata !"fpexcept.ignore") #0 ret double %result } -; Verify that trunc(QNAN) is folded even if the exception behavior mode is not 'ignore'. +; Verify that trunc(QNAN) is not folded if the exception behavior mode is not 'ignore'. define double @nonfinite_03() #0 { ; CHECK-LABEL: @nonfinite_03( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[RESULT:%.*]] = call double @llvm.experimental.constrained.trunc.f64(double 0x7FF8000000000000, metadata !"fpexcept.strict") #[[ATTR0]] -; CHECK-NEXT: ret double 0x7FF8000000000000 +; CHECK-NEXT: ret double [[RESULT]] ; entry: %result = call double @llvm.experimental.constrained.trunc.f64(double 0x7ff8000000000000, metadata !"fpexcept.strict") #0 @@ -451,7 +452,8 @@ entry: define i1 @cmp_eq_03() #0 { ; CHECK-LABEL: @cmp_eq_03( ; CHECK-NEXT: entry: -; CHECK-NEXT: ret i1 false +; CHECK-NEXT: [[RESULT:%.*]] = call i1 @llvm.experimental.constrained.fcmp.f64(double 2.000000e+00, double 0x7FF8000000000000, metadata !"oeq", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret i1 [[RESULT]] ; entry: %result = call i1 @llvm.experimental.constrained.fcmp.f64(double 2.0, double 0x7ff8000000000000, metadata !"oeq", metadata !"fpexcept.ignore") #0 @@ -461,7 +463,8 @@ entry: define i1 @cmp_eq_04() #0 { ; CHECK-LABEL: @cmp_eq_04( ; CHECK-NEXT: entry: -; CHECK-NEXT: ret i1 false +; CHECK-NEXT: [[RESULT:%.*]] = call i1 @llvm.experimental.constrained.fcmp.f64(double 2.000000e+00, double 0x7FF4000000000000, metadata !"oeq", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret i1 [[RESULT]] ; entry: %result = call i1 @llvm.experimental.constrained.fcmp.f64(double 2.0, double 0x7ff4000000000000, metadata !"oeq", metadata !"fpexcept.ignore") #0 @@ -471,7 +474,8 @@ entry: define i1 @cmp_eq_05() #0 { ; CHECK-LABEL: @cmp_eq_05( ; CHECK-NEXT: entry: -; CHECK-NEXT: ret i1 false +; CHECK-NEXT: [[RESULT:%.*]] = call i1 @llvm.experimental.constrained.fcmps.f64(double 2.000000e+00, double 0x7FF8000000000000, metadata !"oeq", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret i1 [[RESULT]] ; entry: %result = call i1 @llvm.experimental.constrained.fcmps.f64(double 2.0, double 0x7ff8000000000000, metadata !"oeq", metadata !"fpexcept.ignore") #0 @@ -481,7 +485,8 @@ entry: define i1 @cmp_eq_06() #0 { ; CHECK-LABEL: @cmp_eq_06( ; CHECK-NEXT: entry: -; CHECK-NEXT: ret i1 false +; CHECK-NEXT: [[RESULT:%.*]] = call i1 @llvm.experimental.constrained.fcmps.f64(double 2.000000e+00, double 0x7FF4000000000000, metadata !"oeq", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret i1 [[RESULT]] ; entry: %result = call i1 @llvm.experimental.constrained.fcmps.f64(double 2.0, double 0x7ff4000000000000, metadata !"oeq", metadata !"fpexcept.ignore") #0 @@ -516,7 +521,7 @@ define i1 @cmp_eq_nan_03() #0 { ; CHECK-LABEL: @cmp_eq_nan_03( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[RESULT:%.*]] = call i1 @llvm.experimental.constrained.fcmp.f64(double 0x7FF8000000000000, double 1.000000e+00, metadata !"oeq", metadata !"fpexcept.strict") #[[ATTR0]] -; CHECK-NEXT: ret i1 false +; CHECK-NEXT: ret i1 [[RESULT]] ; entry: %result = call i1 @llvm.experimental.constrained.fcmp.f64(double 0x7ff8000000000000, double 1.0, metadata !"oeq", metadata !"fpexcept.strict") #0 diff --git a/llvm/test/Transforms/InstSimplify/fptoi-sat.ll b/llvm/test/Transforms/InstSimplify/fptoi-sat.ll index ef15b1ee7a33a..3f7b982baf935 100644 --- a/llvm/test/Transforms/InstSimplify/fptoi-sat.ll +++ b/llvm/test/Transforms/InstSimplify/fptoi-sat.ll @@ -139,7 +139,8 @@ define i32 @fptosi_f64_to_i32_neg_inf() { define i32 @fptosi_f64_to_i32_nan1() { ; CHECK-LABEL: @fptosi_f64_to_i32_nan1( -; CHECK-NEXT: ret i32 0 +; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.fptosi.sat.i32.f64(double 0x7FF8000000000000) +; CHECK-NEXT: ret i32 [[R]] ; %r = call i32 @llvm.fptosi.sat.i32.f64(double 0x7ff8000000000000) ret i32 %r @@ -147,7 +148,8 @@ define i32 @fptosi_f64_to_i32_nan1() { define i32 @fptosi_f64_to_i32_nan2() { ; CHECK-LABEL: @fptosi_f64_to_i32_nan2( -; CHECK-NEXT: ret i32 0 +; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.fptosi.sat.i32.f64(double 0x7FF4000000000000) +; CHECK-NEXT: ret i32 [[R]] ; %r = call i32 @llvm.fptosi.sat.i32.f64(double 0x7ff4000000000000) ret i32 %r @@ -155,7 +157,8 @@ define i32 @fptosi_f64_to_i32_nan2() { define i32 @fptosi_f64_to_i32_nan3() { ; CHECK-LABEL: @fptosi_f64_to_i32_nan3( -; CHECK-NEXT: ret i32 0 +; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.fptosi.sat.i32.f64(double 0xFFF8000000000000) +; CHECK-NEXT: ret i32 [[R]] ; %r = call i32 @llvm.fptosi.sat.i32.f64(double 0xfff8000000000000) ret i32 %r @@ -163,7 +166,8 @@ define i32 @fptosi_f64_to_i32_nan3() { define i32 @fptosi_f64_to_i32_nan4() { ; CHECK-LABEL: @fptosi_f64_to_i32_nan4( -; CHECK-NEXT: ret i32 0 +; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.fptosi.sat.i32.f64(double 0xFFF4000000000000) +; CHECK-NEXT: ret i32 [[R]] ; %r = call i32 @llvm.fptosi.sat.i32.f64(double 0xfff4000000000000) ret i32 %r @@ -281,7 +285,8 @@ define i32 @fptoui_f64_to_i32_neg_inf() { define i32 @fptoui_f64_to_i32_nan1() { ; CHECK-LABEL: @fptoui_f64_to_i32_nan1( -; CHECK-NEXT: ret i32 0 +; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.fptoui.sat.i32.f64(double 0x7FF8000000000000) +; CHECK-NEXT: ret i32 [[R]] ; %r = call i32 @llvm.fptoui.sat.i32.f64(double 0x7ff8000000000000) ret i32 %r @@ -289,7 +294,8 @@ define i32 @fptoui_f64_to_i32_nan1() { define i32 @fptoui_f64_to_i32_nan2() { ; CHECK-LABEL: @fptoui_f64_to_i32_nan2( -; CHECK-NEXT: ret i32 0 +; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.fptoui.sat.i32.f64(double 0x7FF4000000000000) +; CHECK-NEXT: ret i32 [[R]] ; %r = call i32 @llvm.fptoui.sat.i32.f64(double 0x7ff4000000000000) ret i32 %r @@ -297,7 +303,8 @@ define i32 @fptoui_f64_to_i32_nan2() { define i32 @fptoui_f64_to_i32_nan3() { ; CHECK-LABEL: @fptoui_f64_to_i32_nan3( -; CHECK-NEXT: ret i32 0 +; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.fptoui.sat.i32.f64(double 0xFFF8000000000000) +; CHECK-NEXT: ret i32 [[R]] ; %r = call i32 @llvm.fptoui.sat.i32.f64(double 0xfff8000000000000) ret i32 %r @@ -305,7 +312,8 @@ define i32 @fptoui_f64_to_i32_nan3() { define i32 @fptoui_f64_to_i32_nan4() { ; CHECK-LABEL: @fptoui_f64_to_i32_nan4( -; CHECK-NEXT: ret i32 0 +; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.fptoui.sat.i32.f64(double 0xFFF4000000000000) +; CHECK-NEXT: ret i32 [[R]] ; %r = call i32 @llvm.fptoui.sat.i32.f64(double 0xfff4000000000000) ret i32 %r @@ -439,7 +447,8 @@ define i32 @fptosi_f32_to_i32_neg_inf() { define i32 @fptosi_f32_to_i32_nan1() { ; CHECK-LABEL: @fptosi_f32_to_i32_nan1( -; CHECK-NEXT: ret i32 0 +; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.fptosi.sat.i32.f32(float 0x7FF8000000000000) +; CHECK-NEXT: ret i32 [[R]] ; %r = call i32 @llvm.fptosi.sat.i32.f32(float 0x7ff8000000000000) ret i32 %r @@ -447,7 +456,8 @@ define i32 @fptosi_f32_to_i32_nan1() { define i32 @fptosi_f32_to_i32_nan2() { ; CHECK-LABEL: @fptosi_f32_to_i32_nan2( -; CHECK-NEXT: ret i32 0 +; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.fptosi.sat.i32.f32(float 0x7FF4000000000000) +; CHECK-NEXT: ret i32 [[R]] ; %r = call i32 @llvm.fptosi.sat.i32.f32(float 0x7ff4000000000000) ret i32 %r @@ -455,7 +465,8 @@ define i32 @fptosi_f32_to_i32_nan2() { define i32 @fptosi_f32_to_i32_nan3() { ; CHECK-LABEL: @fptosi_f32_to_i32_nan3( -; CHECK-NEXT: ret i32 0 +; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.fptosi.sat.i32.f32(float 0xFFF8000000000000) +; CHECK-NEXT: ret i32 [[R]] ; %r = call i32 @llvm.fptosi.sat.i32.f32(float 0xfff8000000000000) ret i32 %r @@ -463,7 +474,8 @@ define i32 @fptosi_f32_to_i32_nan3() { define i32 @fptosi_f32_to_i32_nan4() { ; CHECK-LABEL: @fptosi_f32_to_i32_nan4( -; CHECK-NEXT: ret i32 0 +; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.fptosi.sat.i32.f32(float 0xFFF4000000000000) +; CHECK-NEXT: ret i32 [[R]] ; %r = call i32 @llvm.fptosi.sat.i32.f32(float 0xfff4000000000000) ret i32 %r @@ -573,7 +585,8 @@ define i32 @fptoui_f32_to_i32_neg_inf() { define i32 @fptoui_f32_to_i32_nan1() { ; CHECK-LABEL: @fptoui_f32_to_i32_nan1( -; CHECK-NEXT: ret i32 0 +; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.fptoui.sat.i32.f32(float 0x7FF8000000000000) +; CHECK-NEXT: ret i32 [[R]] ; %r = call i32 @llvm.fptoui.sat.i32.f32(float 0x7ff8000000000000) ret i32 %r @@ -581,7 +594,8 @@ define i32 @fptoui_f32_to_i32_nan1() { define i32 @fptoui_f32_to_i32_nan2() { ; CHECK-LABEL: @fptoui_f32_to_i32_nan2( -; CHECK-NEXT: ret i32 0 +; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.fptoui.sat.i32.f32(float 0x7FF4000000000000) +; CHECK-NEXT: ret i32 [[R]] ; %r = call i32 @llvm.fptoui.sat.i32.f32(float 0x7ff4000000000000) ret i32 %r @@ -589,7 +603,8 @@ define i32 @fptoui_f32_to_i32_nan2() { define i32 @fptoui_f32_to_i32_nan3() { ; CHECK-LABEL: @fptoui_f32_to_i32_nan3( -; CHECK-NEXT: ret i32 0 +; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.fptoui.sat.i32.f32(float 0xFFF8000000000000) +; CHECK-NEXT: ret i32 [[R]] ; %r = call i32 @llvm.fptoui.sat.i32.f32(float 0xfff8000000000000) ret i32 %r @@ -597,7 +612,8 @@ define i32 @fptoui_f32_to_i32_nan3() { define i32 @fptoui_f32_to_i32_nan4() { ; CHECK-LABEL: @fptoui_f32_to_i32_nan4( -; CHECK-NEXT: ret i32 0 +; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.fptoui.sat.i32.f32(float 0xFFF4000000000000) +; CHECK-NEXT: ret i32 [[R]] ; %r = call i32 @llvm.fptoui.sat.i32.f32(float 0xfff4000000000000) ret i32 %r diff --git a/llvm/test/Transforms/InstSimplify/strictfp-fadd.ll b/llvm/test/Transforms/InstSimplify/strictfp-fadd.ll index d75c00e04c4eb..ef2728a8412a5 100644 --- a/llvm/test/Transforms/InstSimplify/strictfp-fadd.ll +++ b/llvm/test/Transforms/InstSimplify/strictfp-fadd.ll @@ -364,7 +364,7 @@ define float @fold_fadd_qnan_qnan_ebmaytrap() #0 { define float @fold_fadd_qnan_qnan_ebstrict() #0 { ; CHECK-LABEL: @fold_fadd_qnan_qnan_ebstrict( ; CHECK-NEXT: [[ADD:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float 0x7FF8000000000000, float 0x7FF8000000000000, metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR0]] -; CHECK-NEXT: ret float 0x7FF8000000000000 +; CHECK-NEXT: ret float [[ADD]] ; %add = call float @llvm.experimental.constrained.fadd.f32(float 0x7ff8000000000000, float 0x7ff8000000000000, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 ret float %add diff --git a/llvm/test/Transforms/SLPVectorizer/RISCV/revec.ll b/llvm/test/Transforms/SLPVectorizer/RISCV/revec.ll index e13dfce8c29f3..bdb0c801b4783 100644 --- a/llvm/test/Transforms/SLPVectorizer/RISCV/revec.ll +++ b/llvm/test/Transforms/SLPVectorizer/RISCV/revec.ll @@ -227,9 +227,10 @@ define ptr @test4() { define i32 @test5() { ; CHECK-LABEL: @test5( ; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = fadd <8 x double> zeroinitializer, ; CHECK-NEXT: br label [[FOR_END47:%.*]] ; CHECK: for.end47: -; CHECK-NEXT: [[TMP0:%.*]] = phi <8 x double> [ , [[ENTRY:%.*]] ] +; CHECK-NEXT: [[TMP1:%.*]] = phi <8 x double> [ [[TMP0]], [[ENTRY:%.*]] ] ; CHECK-NEXT: ret i32 0 ; entry: diff --git a/llvm/test/Transforms/SLPVectorizer/X86/split-node-full-match.ll b/llvm/test/Transforms/SLPVectorizer/X86/split-node-full-match.ll index f6bf138944749..e96f94f363dd0 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/split-node-full-match.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/split-node-full-match.ll @@ -24,15 +24,17 @@ define void @test(double %0) { ; CHECK: [[_LR_PH272_PREHEADER:.*:]] ; CHECK-NEXT: br i1 false, [[DOT_CRIT_EDGE]], label %[[BB14:.*]] ; CHECK: [[BB14]]: +; CHECK-NEXT: [[TMP16:%.*]] = fsub <2 x double> zeroinitializer, splat (double 0x7FF8000000000000) ; CHECK-NEXT: [[TMP14:%.*]] = shufflevector <6 x double> [[TMP12]], <6 x double> poison, <4 x i32> ; CHECK-NEXT: [[TMP15:%.*]] = shufflevector <4 x double> [[TMP14]], <4 x double> poison, <6 x i32> -; CHECK-NEXT: [[TMP17:%.*]] = shufflevector <6 x double> [[TMP15]], <6 x double> , <6 x i32> -; CHECK-NEXT: br i1 false, label %[[BB18:.*]], [[DOT_CRIT_EDGE]] -; CHECK: [[BB18]]: +; CHECK-NEXT: [[TMP20:%.*]] = shufflevector <2 x double> [[TMP16]], <2 x double> poison, <6 x i32> +; CHECK-NEXT: [[TMP19:%.*]] = shufflevector <6 x double> [[TMP15]], <6 x double> [[TMP20]], <6 x i32> +; CHECK-NEXT: br i1 false, label %[[BB20:.*]], [[DOT_CRIT_EDGE]] +; CHECK: [[BB20]]: ; CHECK-NEXT: [[TMP18:%.*]] = insertelement <6 x double> , double [[TMP0]], i32 3 ; CHECK-NEXT: br [[DOT_CRIT_EDGE]] ; CHECK: [[__CRIT_EDGE:.*:]] -; CHECK-NEXT: [[TMP20:%.*]] = phi <6 x double> [ [[TMP12]], %[[BB7]] ], [ [[TMP18]], %[[BB18]] ], [ [[TMP17]], %[[BB14]] ], [ [[TMP12]], %[[DOTLR_PH272_PREHEADER]] ] +; CHECK-NEXT: [[TMP22:%.*]] = phi <6 x double> [ [[TMP12]], %[[BB7]] ], [ [[TMP18]], %[[BB20]] ], [ [[TMP19]], %[[BB14]] ], [ [[TMP12]], %[[DOTLR_PH272_PREHEADER]] ] ; CHECK-NEXT: ret void ; .thread: