https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/173872
>From f2f9302f7895cad143af8b5c0b70dac0072851de Mon Sep 17 00:00:00 2001 From: Matt Arsenault <[email protected]> Date: Sun, 21 Dec 2025 16:11:38 +0100 Subject: [PATCH] InstCombine: Handle fmul in SimplifyDemandedFPClass --- llvm/include/llvm/Support/KnownFPClass.h | 29 ++++ llvm/lib/Analysis/ValueTracking.cpp | 81 +++-------- llvm/lib/Support/KnownFPClass.cpp | 59 ++++++++ .../InstCombineSimplifyDemanded.cpp | 137 +++++++++++++++++- .../simplify-demanded-fpclass-fmul.ll | 109 +++++++------- .../InstCombine/simplify-demanded-fpclass.ll | 3 +- 6 files changed, 300 insertions(+), 118 deletions(-) diff --git a/llvm/include/llvm/Support/KnownFPClass.h b/llvm/include/llvm/Support/KnownFPClass.h index bf70ddb272e29..62df87ad8a67e 100644 --- a/llvm/include/llvm/Support/KnownFPClass.h +++ b/llvm/include/llvm/Support/KnownFPClass.h @@ -54,6 +54,9 @@ struct KnownFPClass { /// Return true if it's known this can never be an infinity. bool isKnownNeverInfinity() const { return isKnownNever(fcInf); } + /// Return true if it's known this can never be an infinity or nan + bool isKnownNeverInfOrNaN() const { return isKnownNever(fcInf | fcNan); } + /// Return true if it's known this can never be +infinity. bool isKnownNeverPosInfinity() const { return isKnownNever(fcPosInf); } @@ -119,6 +122,17 @@ struct KnownFPClass { return isKnownNever(OrderedGreaterThanZeroMask); } + /// Return true if it's know this can never be a negative value or a logical + /// 0. + /// + /// NaN --> true + /// x >= -0 --> false + /// nsub --> true if mode is ieee, false otherwise. + /// x < -0 --> true + bool cannotBeOrderedGreaterEqZero(DenormalMode Mode) const { + return isKnownNever(fcPositive) && isKnownNeverLogicalNegZero(Mode); + } + KnownFPClass &operator|=(const KnownFPClass &RHS) { KnownFPClasses = KnownFPClasses | RHS.KnownFPClasses; @@ -165,6 +179,21 @@ struct KnownFPClass { canonicalize(const KnownFPClass &Src, DenormalMode DenormMode = DenormalMode::getDynamic()); + /// Report known values for fmul + LLVM_ABI static KnownFPClass + fmul(const KnownFPClass &LHS, const KnownFPClass &RHS, + DenormalMode Mode = DenormalMode::getDynamic()); + + // Special case of fmul x, x. + static KnownFPClass square(const KnownFPClass &Src, + DenormalMode Mode = DenormalMode::getDynamic()) { + KnownFPClass Known = fmul(Src, Src, Mode); + + // X, * X is always non-negative or a NaN. + Known.knownNot(fcNegative); + return Known; + } + /// Report known values for exp, exp2 and exp10. LLVM_ABI static KnownFPClass exp(const KnownFPClass &Src); diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index cf7c6796f76c7..cddd6f9c25074 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -5673,12 +5673,24 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts, break; } case Instruction::FMul: { + const Function *F = cast<Instruction>(Op)->getFunction(); + DenormalMode Mode = + F ? F->getDenormalMode( + Op->getType()->getScalarType()->getFltSemantics()) + : DenormalMode::getDynamic(); + // X * X is always non-negative or a NaN. - if (Op->getOperand(0) == Op->getOperand(1)) - Known.knownNot(fcNegative); + if (Op->getOperand(0) == Op->getOperand(1)) { + KnownFPClass KnownSrc; + computeKnownFPClass(Op->getOperand(0), DemandedElts, fcAllFlags, KnownSrc, + Q, Depth + 1); + Known = KnownFPClass::square(KnownSrc, Mode); + break; + } KnownFPClass KnownLHS, KnownRHS; + bool CannotBeSubnormal = false; const APFloat *CRHS; if (match(Op->getOperand(1), m_APFloat(CRHS))) { // Match denormal scaling pattern, similar to the case in ldexp. If the @@ -5693,7 +5705,7 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts, int MinKnownExponent = ilogb(*CRHS); if (MinKnownExponent >= MantissaBits) - Known.knownNot(fcSubnormal); + CannotBeSubnormal = true; KnownRHS = KnownFPClass(*CRHS); } else { @@ -5704,66 +5716,9 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts, computeKnownFPClass(Op->getOperand(0), DemandedElts, fcAllFlags, KnownLHS, Q, Depth + 1); - // xor sign bit. - if ((KnownLHS.isKnownNever(fcNegative) && - KnownRHS.isKnownNever(fcNegative)) || - (KnownLHS.isKnownNever(fcPositive) && - KnownRHS.isKnownNever(fcPositive))) - Known.knownNot(fcNegative); - - if ((KnownLHS.isKnownAlways(fcNegative | fcNan) && - KnownRHS.isKnownNever(fcNegative)) || - (KnownLHS.isKnownNever(fcNegative) && - KnownRHS.isKnownAlways(fcNegative | fcNan))) - Known.knownNot(fcPositive); - - // inf * anything => inf or nan - if (KnownLHS.isKnownAlways(fcInf | fcNan) || - KnownRHS.isKnownAlways(fcInf | fcNan)) - Known.knownNot(fcNormal | fcSubnormal | fcZero); - - // 0 * anything => 0 or nan - if (KnownRHS.isKnownAlways(fcZero | fcNan) || - KnownLHS.isKnownAlways(fcZero | fcNan)) - Known.knownNot(fcNormal | fcSubnormal | fcInf); - - // +/-0 * +/-inf = nan - if ((KnownLHS.isKnownAlways(fcZero | fcNan) && - KnownRHS.isKnownAlways(fcInf | fcNan)) || - (KnownLHS.isKnownAlways(fcInf | fcNan) && - KnownRHS.isKnownAlways(fcZero | fcNan))) - Known.knownNot(~fcNan); - - if (!KnownLHS.isKnownNeverNaN() || !KnownRHS.isKnownNeverNaN()) - break; - - if (KnownLHS.SignBit && KnownRHS.SignBit) { - if (*KnownLHS.SignBit == *KnownRHS.SignBit) - Known.signBitMustBeZero(); - else - Known.signBitMustBeOne(); - } - - // If 0 * +/-inf produces NaN. - if (KnownLHS.isKnownNeverInfinity() && KnownRHS.isKnownNeverInfinity()) { - Known.knownNot(fcNan); - break; - } - - const Function *F = cast<Instruction>(Op)->getFunction(); - if (!F) - break; - - Type *OpTy = Op->getType()->getScalarType(); - const fltSemantics &FltSem = OpTy->getFltSemantics(); - DenormalMode Mode = F->getDenormalMode(FltSem); - - if ((KnownRHS.isKnownNeverInfinity() || - KnownLHS.isKnownNeverLogicalZero(Mode)) && - (KnownLHS.isKnownNeverInfinity() || - KnownRHS.isKnownNeverLogicalZero(Mode))) - Known.knownNot(fcNan); - + Known = KnownFPClass::fmul(KnownLHS, KnownRHS, Mode); + if (CannotBeSubnormal) + Known.knownNot(fcSubnormal); break; } case Instruction::FDiv: diff --git a/llvm/lib/Support/KnownFPClass.cpp b/llvm/lib/Support/KnownFPClass.cpp index 9ca040366b611..125bee00c38ff 100644 --- a/llvm/lib/Support/KnownFPClass.cpp +++ b/llvm/lib/Support/KnownFPClass.cpp @@ -141,6 +141,65 @@ KnownFPClass KnownFPClass::canonicalize(const KnownFPClass &KnownSrc, return Known; } +KnownFPClass KnownFPClass::fmul(const KnownFPClass &KnownLHS, + const KnownFPClass &KnownRHS, + DenormalMode Mode) { + KnownFPClass Known; + + // xor sign bit. + if ((KnownLHS.isKnownNever(fcNegative) && + KnownRHS.isKnownNever(fcNegative)) || + (KnownLHS.isKnownNever(fcPositive) && KnownRHS.isKnownNever(fcPositive))) + Known.knownNot(fcNegative); + + if ((KnownLHS.isKnownAlways(fcNegative | fcNan) && + KnownRHS.isKnownNever(fcNegative)) || + (KnownLHS.isKnownNever(fcNegative) && + KnownRHS.isKnownAlways(fcNegative | fcNan))) + Known.knownNot(fcPositive); + + // inf * anything => inf or nan + if (KnownLHS.isKnownAlways(fcInf | fcNan) || + KnownRHS.isKnownAlways(fcInf | fcNan)) + Known.knownNot(fcNormal | fcSubnormal | fcZero); + + // 0 * anything => 0 or nan + if (KnownRHS.isKnownAlways(fcZero | fcNan) || + KnownLHS.isKnownAlways(fcZero | fcNan)) + Known.knownNot(fcNormal | fcSubnormal | fcInf); + + // +/-0 * +/-inf = nan + if ((KnownLHS.isKnownAlways(fcZero | fcNan) && + KnownRHS.isKnownAlways(fcInf | fcNan)) || + (KnownLHS.isKnownAlways(fcInf | fcNan) && + KnownRHS.isKnownAlways(fcZero | fcNan))) + Known.knownNot(~fcNan); + + if (!KnownLHS.isKnownNeverNaN() || !KnownRHS.isKnownNeverNaN()) + return Known; + + if (KnownLHS.SignBit && KnownRHS.SignBit) { + if (*KnownLHS.SignBit == *KnownRHS.SignBit) + Known.signBitMustBeZero(); + else + Known.signBitMustBeOne(); + } + + // If 0 * +/-inf produces NaN. + if (KnownLHS.isKnownNeverInfinity() && KnownRHS.isKnownNeverInfinity()) { + Known.knownNot(fcNan); + return Known; + } + + if ((KnownRHS.isKnownNeverInfinity() || + KnownLHS.isKnownNeverLogicalZero(Mode)) && + (KnownLHS.isKnownNeverInfinity() || + KnownRHS.isKnownNeverLogicalZero(Mode))) + Known.knownNot(fcNan); + + return Known; +} + KnownFPClass KnownFPClass::exp(const KnownFPClass &KnownSrc) { KnownFPClass Known; Known.knownNot(fcNegative); diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp index 85672cdfe1377..3a695ea35ae56 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp @@ -2005,13 +2005,18 @@ Value *InstCombinerImpl::SimplifyDemandedVectorElts(Value *V, /// For floating-point classes that resolve to a single bit pattern, return that /// value. -static Constant *getFPClassConstant(Type *Ty, FPClassTest Mask) { +static Constant *getFPClassConstant(Type *Ty, FPClassTest Mask, + bool IsCanonicalizing = false) { if (Mask == fcNone) return PoisonValue::get(Ty); if (Mask == fcPosZero) return Constant::getNullValue(Ty); + // Turn any possible snans into quiet if we can. + if (Mask == fcNan && IsCanonicalizing) + return ConstantFP::getQNaN(Ty); + // TODO: Support aggregate types that are allowed by FPMathOperator. if (Ty->isAggregateType()) return nullptr; @@ -2056,12 +2061,17 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Value *V, if (!I->hasOneUse()) return nullptr; + FastMathFlags FMF; + if (auto *FPOp = dyn_cast<FPMathOperator>(I)) { - if (FPOp->hasNoNaNs()) + FMF = FPOp->getFastMathFlags(); + if (FMF.noNaNs()) DemandedMask &= ~fcNan; - if (FPOp->hasNoInfs()) + + if (FMF.noInfs()) DemandedMask &= ~fcInf; } + switch (I->getOpcode()) { case Instruction::FNeg: { if (SimplifyDemandedFPClass(I, 0, llvm::fneg(DemandedMask), Known, @@ -2280,6 +2290,127 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Value *V, Known = KnownLHS | KnownRHS; break; } + case Instruction::FMul: { + KnownFPClass KnownLHS, KnownRHS; + + Value *X = I->getOperand(0); + Value *Y = I->getOperand(1); + + FPClassTest SrcDemandedMask = + DemandedMask & (fcNan | fcZero | fcSubnormal | fcNormal); + + if (DemandedMask & fcInf) { + // mul x, inf = inf + // mul large_x, large_y = inf + SrcDemandedMask |= fcSubnormal | fcNormal | fcInf; + } + + if (DemandedMask & fcNan) { + // mul +/-inf, 0 => nan + SrcDemandedMask |= fcZero | fcInf; + + // TODO: Mode check + // mul +/-inf, sub => nan if daz + SrcDemandedMask |= fcSubnormal; + } + + if (X == Y) { + if (SimplifyDemandedFPClass(I, 0, SrcDemandedMask, KnownLHS, Depth + 1)) + return I; + Type *EltTy = VTy->getScalarType(); + + DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics()); + Known = KnownFPClass::square(KnownLHS, Mode); + + // Propagate known result to simplify edge case checks. + if ((DemandedMask & fcNan) == fcNone) + Known.knownNot(fcNan); + if ((DemandedMask & fcPosInf) == fcNone) + Known.knownNot(fcInf); + + FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses; + if (Constant *Folded = + getFPClassConstant(VTy, ValidResults, /*IsCanonicalizing=*/true)) + return Folded; + + if (Known.isKnownAlways(fcPosZero | fcPosInf | fcNan)) { + // We can skip the fabs if the source was already known positive. + if (KnownLHS.isKnownAlways(fcPositive)) + return X; + + // => fabs(x), in case this was a -inf or -0. + // Note: Dropping canonicalize. + IRBuilderBase::InsertPointGuard Guard(Builder); + Builder.SetInsertPoint(I); + Value *Fabs = Builder.CreateUnaryIntrinsic(Intrinsic::fabs, X, FMF); + Fabs->takeName(I); + return Fabs; + } + + return nullptr; + } + + if (SimplifyDemandedFPClass(I, 1, SrcDemandedMask, KnownRHS, Depth + 1) || + SimplifyDemandedFPClass(I, 0, SrcDemandedMask, KnownLHS, Depth + 1)) + return I; + + // Propagate nnan-ness to sources to simplify source checks. + if ((DemandedMask & fcNan) == fcNone) { + KnownLHS.knownNot(fcNan); + KnownRHS.knownNot(fcNan); + } + + // With no-nans/no-infs: + // X * 0.0 --> copysign(0.0, X) + // X * -0.0 --> copysign(0.0, -X) + + // TODO: Apply knowledge of no-infinity returns to sources. + + // TODO: Known -0, turn into copysign(y, fneg(x)) like visitFMul. + if (KnownLHS.isKnownNeverInfOrNaN() && + KnownRHS.isKnownAlways(fcPosZero | fcNan)) { + // => copysign(+0, lhs) + // Note: Dropping canonicalize + Value *Copysign = Builder.CreateCopySign(Y, X, FMF); + Copysign->takeName(I); + return Copysign; + } + + if (KnownLHS.isKnownAlways(fcPosZero | fcNan) && + KnownRHS.isKnownNeverInfOrNaN()) { + // => copysign(+0, rhs) + // Note: Dropping canonicalize + Value *Copysign = Builder.CreateCopySign(X, Y, FMF); + Copysign->takeName(I); + return Copysign; + } + + Type *EltTy = VTy->getScalarType(); + DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics()); + + if (KnownLHS.isKnownAlways(fcInf | fcNan) && + (KnownRHS.isKnownNeverNaN() && + KnownRHS.cannotBeOrderedGreaterEqZero(Mode))) { + // Note: Dropping canonicalize + Value *Neg = Builder.CreateFNegFMF(X, FMF); + Neg->takeName(I); + return Neg; + } + + if (KnownRHS.isKnownAlways(fcInf | fcNan) && + (KnownLHS.isKnownNeverNaN() && + KnownLHS.cannotBeOrderedGreaterEqZero(Mode))) { + // Note: Dropping canonicalize + Value *Neg = Builder.CreateFNegFMF(Y, FMF); + Neg->takeName(I); + return Neg; + } + + Known = KnownFPClass::fmul(KnownLHS, KnownRHS, Mode); + + FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses; + return getFPClassConstant(VTy, ValidResults, /*IsCanonicalizing=*/true); + } default: Known = computeKnownFPClass(I, DemandedMask, CxtI, Depth + 1); break; diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-fmul.ll b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-fmul.ll index 88f6e31f86f83..53ae101762ca5 100644 --- a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-fmul.ll +++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-fmul.ll @@ -50,8 +50,7 @@ define nofpclass(inf) float @ret_nofpclass_inf__fmul_unknown_or_pinf(i1 %cond, f define nofpclass(pinf pnorm psub pzero) float @ret_only_negative_results_or_nan_square(float %x) { ; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_only_negative_results_or_nan_square( ; CHECK-SAME: float [[X:%.*]]) { -; CHECK-NEXT: [[MUL:%.*]] = fmul float [[X]], [[X]] -; CHECK-NEXT: ret float [[MUL]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %mul = fmul float %x, %x ret float %mul @@ -89,8 +88,7 @@ define nofpclass(inf norm sub nan) float @ret_only_zero_results_square(float %x) define nofpclass(inf norm sub zero) float @ret_only_nan_results_square(float %x) { ; CHECK-LABEL: define nofpclass(inf zero sub norm) float @ret_only_nan_results_square( ; CHECK-SAME: float [[X:%.*]]) { -; CHECK-NEXT: [[MUL:%.*]] = fmul float [[X]], [[X]] -; CHECK-NEXT: ret float [[MUL]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %mul = fmul float %x, %x ret float %mul @@ -167,8 +165,7 @@ define nofpclass(pinf norm sub zero nan) float @ret_only_ninf_results_square(flo define nofpclass(inf) float @ret_src_must_be_zero_square(float nofpclass(nan inf norm sub) %x) { ; CHECK-LABEL: define nofpclass(inf) float @ret_src_must_be_zero_square( ; CHECK-SAME: float nofpclass(nan inf sub norm) [[X:%.*]]) { -; CHECK-NEXT: [[MUL:%.*]] = fmul float [[X]], [[X]] -; CHECK-NEXT: ret float [[MUL]] +; CHECK-NEXT: ret float 0.000000e+00 ; %mul = fmul float %x, %x ret float %mul @@ -177,8 +174,7 @@ define nofpclass(inf) float @ret_src_must_be_zero_square(float nofpclass(nan inf define nofpclass(inf) float @ret_src_must_be_pzero(float nofpclass(nan inf norm sub nzero) %x) { ; CHECK-LABEL: define nofpclass(inf) float @ret_src_must_be_pzero( ; CHECK-SAME: float nofpclass(nan inf nzero sub norm) [[X:%.*]]) { -; CHECK-NEXT: [[MUL:%.*]] = fmul float [[X]], [[X]] -; CHECK-NEXT: ret float [[MUL]] +; CHECK-NEXT: ret float 0.000000e+00 ; %mul = fmul float %x, %x ret float %mul @@ -187,8 +183,7 @@ define nofpclass(inf) float @ret_src_must_be_pzero(float nofpclass(nan inf norm define nofpclass(inf) float @ret_src_must_be_nzero(float nofpclass(nan inf norm sub pzero) %x) { ; CHECK-LABEL: define nofpclass(inf) float @ret_src_must_be_nzero( ; CHECK-SAME: float nofpclass(nan inf pzero sub norm) [[X:%.*]]) { -; CHECK-NEXT: [[MUL:%.*]] = fmul float [[X]], [[X]] -; CHECK-NEXT: ret float [[MUL]] +; CHECK-NEXT: ret float 0.000000e+00 ; %mul = fmul float %x, %x ret float %mul @@ -197,7 +192,7 @@ define nofpclass(inf) float @ret_src_must_be_nzero(float nofpclass(nan inf norm define nofpclass(inf) float @ret_src_must_be_zero_or_nan_square(float nofpclass(inf norm sub) %x) { ; CHECK-LABEL: define nofpclass(inf) float @ret_src_must_be_zero_or_nan_square( ; CHECK-SAME: float nofpclass(inf sub norm) [[X:%.*]]) { -; CHECK-NEXT: [[MUL:%.*]] = fmul float [[X]], [[X]] +; CHECK-NEXT: [[MUL:%.*]] = call float @llvm.fabs.f32(float [[X]]) ; CHECK-NEXT: ret float [[MUL]] ; %mul = fmul float %x, %x @@ -207,7 +202,7 @@ define nofpclass(inf) float @ret_src_must_be_zero_or_nan_square(float nofpclass( define nofpclass(inf) float @ret_src_must_be_zero_or_nan_square__preserve_flags(float nofpclass(inf norm sub) %x) { ; CHECK-LABEL: define nofpclass(inf) float @ret_src_must_be_zero_or_nan_square__preserve_flags( ; CHECK-SAME: float nofpclass(inf sub norm) [[X:%.*]]) { -; CHECK-NEXT: [[MUL:%.*]] = fmul contract float [[X]], [[X]] +; CHECK-NEXT: [[MUL:%.*]] = call contract float @llvm.fabs.f32(float [[X]]) ; CHECK-NEXT: ret float [[MUL]] ; %mul = fmul contract float %x, %x @@ -218,6 +213,27 @@ define nofpclass(inf) float @ret_src_must_be_zero_or_nan_square__preserve_flags( define nofpclass(nzero) float @ret_src_must_be_nan_square(float nofpclass(inf norm sub zero) %x) { ; CHECK-LABEL: define nofpclass(nzero) float @ret_src_must_be_nan_square( ; CHECK-SAME: float nofpclass(inf zero sub norm) [[X:%.*]]) { +; CHECK-NEXT: ret float 0x7FF8000000000000 +; + %mul = fmul float %x, %x + ret float %mul +} + +; Make sure this doesn't get dropped as a no-op +define nofpclass(nzero) float @ret_src_must_be_positive_square(float nofpclass(ninf nnorm nsub nzero) %x) { +; CHECK-LABEL: define nofpclass(nzero) float @ret_src_must_be_positive_square( +; CHECK-SAME: float nofpclass(ninf nzero nsub nnorm) [[X:%.*]]) { +; CHECK-NEXT: [[MUL:%.*]] = fmul float [[X]], [[X]] +; CHECK-NEXT: ret float [[MUL]] +; + %mul = fmul float %x, %x + ret float %mul +} + +; Make sure this doesn't get dropped as a no-op +define nofpclass(nzero) float @ret_src_must_be_negative_square(float nofpclass(pinf pnorm psub pzero) %x) { +; CHECK-LABEL: define nofpclass(nzero) float @ret_src_must_be_negative_square( +; CHECK-SAME: float nofpclass(pinf pzero psub pnorm) [[X:%.*]]) { ; CHECK-NEXT: [[MUL:%.*]] = fmul float [[X]], [[X]] ; CHECK-NEXT: ret float [[MUL]] ; @@ -229,9 +245,7 @@ define nofpclass(nzero) float @ret_src_must_be_nan_square(float nofpclass(inf no define nofpclass(pinf pnorm psub pzero) float @ret_only_negative_results_or_nan_fabs_xy(float %x, float nofpclass(ninf nnorm nsub nzero) %y.pos.or.nan) { ; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_only_negative_results_or_nan_fabs_xy( ; CHECK-SAME: float [[X:%.*]], float nofpclass(ninf nzero nsub nnorm) [[Y_POS_OR_NAN:%.*]]) { -; CHECK-NEXT: [[X_FABS:%.*]] = call float @llvm.fabs.f32(float [[X]]) -; CHECK-NEXT: [[MUL:%.*]] = fmul float [[X_FABS]], [[Y_POS_OR_NAN]] -; CHECK-NEXT: ret float [[MUL]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %x.fabs = call float @llvm.fabs.f32(float %x) %mul = fmul float %x.fabs, %y.pos.or.nan @@ -242,9 +256,7 @@ define nofpclass(pinf pnorm psub pzero) float @ret_only_negative_results_or_nan_ define nofpclass(pinf pnorm psub pzero nan) float @ret_only_negative_results_fabs_xy(float %x,float nofpclass(ninf nnorm nsub nzero) %y.pos.or.nan) { ; CHECK-LABEL: define nofpclass(nan pinf pzero psub pnorm) float @ret_only_negative_results_fabs_xy( ; CHECK-SAME: float [[X:%.*]], float nofpclass(ninf nzero nsub nnorm) [[Y_POS_OR_NAN:%.*]]) { -; CHECK-NEXT: [[X_FABS:%.*]] = call float @llvm.fabs.f32(float [[X]]) -; CHECK-NEXT: [[MUL:%.*]] = fmul float [[X_FABS]], [[Y_POS_OR_NAN]] -; CHECK-NEXT: ret float [[MUL]] +; CHECK-NEXT: ret float poison ; %x.fabs = call float @llvm.fabs.f32(float %x) %mul = fmul float %x.fabs, %y.pos.or.nan @@ -365,8 +377,7 @@ define nofpclass(pinf nan) float @ret_no_pinf_or_nan_results__lhs_known_non_inf( define nofpclass(inf nan) float @ret_no_inf_or_nan_results__lhs_known_non_inf(i1 %cond, float %x, float nofpclass(inf) %y) { ; CHECK-LABEL: define nofpclass(nan inf) float @ret_no_inf_or_nan_results__lhs_known_non_inf( ; CHECK-SAME: i1 [[COND:%.*]], float [[X:%.*]], float nofpclass(inf) [[Y:%.*]]) { -; CHECK-NEXT: [[X_OR_PINF:%.*]] = select i1 [[COND]], float [[X]], float 0x7FF0000000000000 -; CHECK-NEXT: [[MUL:%.*]] = fmul float [[X_OR_PINF]], [[Y]] +; CHECK-NEXT: [[MUL:%.*]] = fmul float [[X]], [[Y]] ; CHECK-NEXT: ret float [[MUL]] ; %x.or.pinf = select i1 %cond, float %x, float 0x7FF0000000000000 @@ -378,8 +389,7 @@ define nofpclass(inf nan) float @ret_no_inf_or_nan_results__lhs_known_non_inf(i1 define nofpclass(inf nan) float @ret_no_inf_or_nan_results__rhs_known_non_inf(i1 %cond, float %x, float nofpclass(inf) %y) { ; CHECK-LABEL: define nofpclass(nan inf) float @ret_no_inf_or_nan_results__rhs_known_non_inf( ; CHECK-SAME: i1 [[COND:%.*]], float [[X:%.*]], float nofpclass(inf) [[Y:%.*]]) { -; CHECK-NEXT: [[Y_OR_PINF:%.*]] = select i1 [[COND]], float [[Y]], float 0x7FF0000000000000 -; CHECK-NEXT: [[MUL:%.*]] = fmul float [[X]], [[Y_OR_PINF]] +; CHECK-NEXT: [[MUL:%.*]] = fmul float [[X]], [[Y]] ; CHECK-NEXT: ret float [[MUL]] ; %y.or.pinf = select i1 %cond, float %y, float 0x7FF0000000000000 @@ -391,8 +401,7 @@ define nofpclass(inf nan) float @ret_no_inf_or_nan_results__rhs_known_non_inf(i1 define nofpclass(ninf nnorm nsub nzero) float @ret_only_positive_results_or_nan_known_negative_fmul(float nofpclass(ninf nnorm nsub nzero) %only.positive.or.nan, float nofpclass(pinf pnorm psub pzero) %only.negative.or.nan) { ; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_only_positive_results_or_nan_known_negative_fmul( ; CHECK-SAME: float nofpclass(ninf nzero nsub nnorm) [[ONLY_POSITIVE_OR_NAN:%.*]], float nofpclass(pinf pzero psub pnorm) [[ONLY_NEGATIVE_OR_NAN:%.*]]) { -; CHECK-NEXT: [[MUL:%.*]] = fmul float [[ONLY_NEGATIVE_OR_NAN]], [[ONLY_POSITIVE_OR_NAN]] -; CHECK-NEXT: ret float [[MUL]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %mul = fmul float %only.negative.or.nan, %only.positive.or.nan ret float %mul @@ -402,8 +411,7 @@ define nofpclass(ninf nnorm nsub nzero) float @ret_only_positive_results_or_nan_ define nofpclass(ninf nnorm nsub nzero nan) float @ret_only_positive_results_known_negative_fmul(float nofpclass(ninf nnorm nsub nzero) %only.positive.or.nan, float nofpclass(pinf pnorm psub pzero) %only.negative.or.nan) { ; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @ret_only_positive_results_known_negative_fmul( ; CHECK-SAME: float nofpclass(ninf nzero nsub nnorm) [[ONLY_POSITIVE_OR_NAN:%.*]], float nofpclass(pinf pzero psub pnorm) [[ONLY_NEGATIVE_OR_NAN:%.*]]) { -; CHECK-NEXT: [[MUL:%.*]] = fmul float [[ONLY_NEGATIVE_OR_NAN]], [[ONLY_POSITIVE_OR_NAN]] -; CHECK-NEXT: ret float [[MUL]] +; CHECK-NEXT: ret float poison ; %mul = fmul float %only.negative.or.nan, %only.positive.or.nan ret float %mul @@ -446,7 +454,7 @@ define nofpclass(nsub) float @ret__not_inf_or_nan__fmul__known_zero_or_nan(float define nofpclass(nsub) float @ret__known_pzero_or_nan__fmul__not_inf_or_nan(float nofpclass(inf sub norm nzero) %pzero.or.nan, float nofpclass(inf nan) %not.inf.or.nan) { ; CHECK-LABEL: define nofpclass(nsub) float @ret__known_pzero_or_nan__fmul__not_inf_or_nan( ; CHECK-SAME: float nofpclass(inf nzero sub norm) [[PZERO_OR_NAN:%.*]], float nofpclass(nan inf) [[NOT_INF_OR_NAN:%.*]]) { -; CHECK-NEXT: [[MUL:%.*]] = fmul float [[PZERO_OR_NAN]], [[NOT_INF_OR_NAN]] +; CHECK-NEXT: [[MUL:%.*]] = call float @llvm.copysign.f32(float [[PZERO_OR_NAN]], float [[NOT_INF_OR_NAN]]) ; CHECK-NEXT: ret float [[MUL]] ; %mul = fmul float %pzero.or.nan, %not.inf.or.nan @@ -468,7 +476,7 @@ define nofpclass(nsub) float @ret__not_inf__fmul__known_pzero_or_nan(float nofpc define nofpclass(nsub) float @ret__not_inf_or_nan__fmul__known_pzero_or_nan(float nofpclass(inf nan) %not.inf.or.nan, float nofpclass(inf sub norm nzero) %pzero.or.nan) { ; CHECK-LABEL: define nofpclass(nsub) float @ret__not_inf_or_nan__fmul__known_pzero_or_nan( ; CHECK-SAME: float nofpclass(nan inf) [[NOT_INF_OR_NAN:%.*]], float nofpclass(inf nzero sub norm) [[PZERO_OR_NAN:%.*]]) { -; CHECK-NEXT: [[MUL:%.*]] = fmul float [[NOT_INF_OR_NAN]], [[PZERO_OR_NAN]] +; CHECK-NEXT: [[MUL:%.*]] = call float @llvm.copysign.f32(float [[PZERO_OR_NAN]], float [[NOT_INF_OR_NAN]]) ; CHECK-NEXT: ret float [[MUL]] ; %mul = fmul float %not.inf.or.nan, %pzero.or.nan @@ -501,7 +509,7 @@ define nofpclass(nsub) float @ret__known_negative_non0_or_nan__fmul__known_inf_o define nofpclass(nsub) float @ret__known_inf_or_nan__fmul__known_negative_non0(float nofpclass(zero sub norm) %inf.or.nan, float nofpclass(nan zero pinf pnorm psub) %negative.non0) { ; CHECK-LABEL: define nofpclass(nsub) float @ret__known_inf_or_nan__fmul__known_negative_non0( ; CHECK-SAME: float nofpclass(zero sub norm) [[INF_OR_NAN:%.*]], float nofpclass(nan pinf zero psub pnorm) [[NEGATIVE_NON0:%.*]]) { -; CHECK-NEXT: [[MUL:%.*]] = fmul float [[INF_OR_NAN]], [[NEGATIVE_NON0]] +; CHECK-NEXT: [[MUL:%.*]] = fneg float [[INF_OR_NAN]] ; CHECK-NEXT: ret float [[MUL]] ; %mul = fmul float %inf.or.nan, %negative.non0 @@ -512,7 +520,7 @@ define nofpclass(nsub) float @ret__known_inf_or_nan__fmul__known_negative_non0(f define nofpclass(nsub) float @ret__known_negative_non0__fmul__known_inf_or_nan(float nofpclass(nan zero pinf pnorm psub) %negative.non0, float nofpclass(zero sub norm) %inf.or.nan) { ; CHECK-LABEL: define nofpclass(nsub) float @ret__known_negative_non0__fmul__known_inf_or_nan( ; CHECK-SAME: float nofpclass(nan pinf zero psub pnorm) [[NEGATIVE_NON0:%.*]], float nofpclass(zero sub norm) [[INF_OR_NAN:%.*]]) { -; CHECK-NEXT: [[MUL:%.*]] = fmul float [[NEGATIVE_NON0]], [[INF_OR_NAN]] +; CHECK-NEXT: [[MUL:%.*]] = fneg float [[INF_OR_NAN]] ; CHECK-NEXT: ret float [[MUL]] ; %mul = fmul float %negative.non0, %inf.or.nan @@ -545,7 +553,7 @@ define nofpclass(nsub) float @ret__known_negative_non0__fmul__known_inf_or_nan__ define nofpclass(nsub) float @ret__known_inf_or_nan__fmul__known_negative_nonlogical0__daz(float nofpclass(zero sub norm) %inf.or.nan, float nofpclass(nan zero pinf pnorm sub) %negative.nonlogical0) #1 { ; CHECK-LABEL: define nofpclass(nsub) float @ret__known_inf_or_nan__fmul__known_negative_nonlogical0__daz( ; CHECK-SAME: float nofpclass(zero sub norm) [[INF_OR_NAN:%.*]], float nofpclass(nan pinf zero sub pnorm) [[NEGATIVE_NONLOGICAL0:%.*]]) #[[ATTR1]] { -; CHECK-NEXT: [[MUL:%.*]] = fmul float [[INF_OR_NAN]], [[NEGATIVE_NONLOGICAL0]] +; CHECK-NEXT: [[MUL:%.*]] = fneg float [[INF_OR_NAN]] ; CHECK-NEXT: ret float [[MUL]] ; %mul = fmul float %inf.or.nan, %negative.nonlogical0 @@ -556,7 +564,7 @@ define nofpclass(nsub) float @ret__known_inf_or_nan__fmul__known_negative_nonlog define nofpclass(nsub) float @ret__known_negative_nonlogical0__fmul__known_inf_or_nan__daz(float nofpclass(nan zero pinf pnorm sub) %negative.nonlogical0, float nofpclass(zero sub norm) %inf.or.nan) #1 { ; CHECK-LABEL: define nofpclass(nsub) float @ret__known_negative_nonlogical0__fmul__known_inf_or_nan__daz( ; CHECK-SAME: float nofpclass(nan pinf zero sub pnorm) [[NEGATIVE_NONLOGICAL0:%.*]], float nofpclass(zero sub norm) [[INF_OR_NAN:%.*]]) #[[ATTR1]] { -; CHECK-NEXT: [[MUL:%.*]] = fmul float [[NEGATIVE_NONLOGICAL0]], [[INF_OR_NAN]] +; CHECK-NEXT: [[MUL:%.*]] = fneg float [[INF_OR_NAN]] ; CHECK-NEXT: ret float [[MUL]] ; %mul = fmul float %negative.nonlogical0, %inf.or.nan @@ -567,7 +575,7 @@ define nofpclass(nsub) float @ret__known_negative_nonlogical0__fmul__known_inf_o define nofpclass(nan) float @ret_no_nan_result__known_pzero__fmul__not_inf(float nofpclass(inf sub norm nzero) %pzero.or.nan, float nofpclass(inf nan) %not.inf.or.nan) { ; CHECK-LABEL: define nofpclass(nan) float @ret_no_nan_result__known_pzero__fmul__not_inf( ; CHECK-SAME: float nofpclass(inf nzero sub norm) [[PZERO_OR_NAN:%.*]], float nofpclass(nan inf) [[NOT_INF_OR_NAN:%.*]]) { -; CHECK-NEXT: [[MUL:%.*]] = fmul float [[PZERO_OR_NAN]], [[NOT_INF_OR_NAN]] +; CHECK-NEXT: [[MUL:%.*]] = call float @llvm.copysign.f32(float 0.000000e+00, float [[NOT_INF_OR_NAN]]) ; CHECK-NEXT: ret float [[MUL]] ; %mul = fmul float %pzero.or.nan, %not.inf.or.nan @@ -578,7 +586,7 @@ define nofpclass(nan) float @ret_no_nan_result__known_pzero__fmul__not_inf(float define nofpclass(nan) float @ret_no_nan_result__not_inf_or_nan__fmul__known_pzero_or_nan(float nofpclass(inf) %not.inf.or.nan, float nofpclass(inf sub norm nzero) %pzero.or.nan) { ; CHECK-LABEL: define nofpclass(nan) float @ret_no_nan_result__not_inf_or_nan__fmul__known_pzero_or_nan( ; CHECK-SAME: float nofpclass(inf) [[NOT_INF_OR_NAN:%.*]], float nofpclass(inf nzero sub norm) [[PZERO_OR_NAN:%.*]]) { -; CHECK-NEXT: [[MUL:%.*]] = fmul float [[NOT_INF_OR_NAN]], [[PZERO_OR_NAN]] +; CHECK-NEXT: [[MUL:%.*]] = call float @llvm.copysign.f32(float 0.000000e+00, float [[NOT_INF_OR_NAN]]) ; CHECK-NEXT: ret float [[MUL]] ; %mul = fmul float %not.inf.or.nan, %pzero.or.nan @@ -589,7 +597,7 @@ define nofpclass(nan) float @ret_no_nan_result__not_inf_or_nan__fmul__known_pzer define nofpclass(nan) float @ret_no_nan_result__known_inf_or_nan__fmul__known_negative_non0(float nofpclass(zero sub norm) %inf.or.nan, float nofpclass(zero pinf pnorm psub) %negative.non0) { ; CHECK-LABEL: define nofpclass(nan) float @ret_no_nan_result__known_inf_or_nan__fmul__known_negative_non0( ; CHECK-SAME: float nofpclass(zero sub norm) [[INF_OR_NAN:%.*]], float nofpclass(pinf zero psub pnorm) [[NEGATIVE_NON0:%.*]]) { -; CHECK-NEXT: [[MUL:%.*]] = fmul float [[INF_OR_NAN]], [[NEGATIVE_NON0]] +; CHECK-NEXT: [[MUL:%.*]] = fneg float [[INF_OR_NAN]] ; CHECK-NEXT: ret float [[MUL]] ; %mul = fmul float %inf.or.nan, %negative.non0 @@ -600,7 +608,7 @@ define nofpclass(nan) float @ret_no_nan_result__known_inf_or_nan__fmul__known_ne define nofpclass(nan) float @ret_no_nan_result__known_negative_non0__fmul__known_inf_or_nan(float nofpclass(zero pinf pnorm psub) %negative.non0, float nofpclass(zero sub norm) %inf.or.nan) { ; CHECK-LABEL: define nofpclass(nan) float @ret_no_nan_result__known_negative_non0__fmul__known_inf_or_nan( ; CHECK-SAME: float nofpclass(pinf zero psub pnorm) [[NEGATIVE_NON0:%.*]], float nofpclass(zero sub norm) [[INF_OR_NAN:%.*]]) { -; CHECK-NEXT: [[MUL:%.*]] = fmul float [[NEGATIVE_NON0]], [[INF_OR_NAN]] +; CHECK-NEXT: [[MUL:%.*]] = fneg float [[INF_OR_NAN]] ; CHECK-NEXT: ret float [[MUL]] ; %mul = fmul float %negative.non0, %inf.or.nan @@ -611,7 +619,7 @@ define nofpclass(nan) float @ret_no_nan_result__known_negative_non0__fmul__known define nofpclass(inf nan) float @ret_noinf_nonan__known_pzero_or_nan__fmul__not_inf_or_nan(float nofpclass(inf sub norm nzero) %pzero.or.nan, float %unknown) { ; CHECK-LABEL: define nofpclass(nan inf) float @ret_noinf_nonan__known_pzero_or_nan__fmul__not_inf_or_nan( ; CHECK-SAME: float nofpclass(inf nzero sub norm) [[PZERO_OR_NAN:%.*]], float [[UNKNOWN:%.*]]) { -; CHECK-NEXT: [[MUL:%.*]] = fmul float [[PZERO_OR_NAN]], [[UNKNOWN]] +; CHECK-NEXT: [[MUL:%.*]] = fmul float [[UNKNOWN]], 0.000000e+00 ; CHECK-NEXT: ret float [[MUL]] ; %mul = fmul float %pzero.or.nan, %unknown @@ -622,7 +630,7 @@ define nofpclass(inf nan) float @ret_noinf_nonan__known_pzero_or_nan__fmul__not_ define nofpclass(inf nan) float @ret_noinf_nonan__not_inf_or_nan__fmul__known_pzero_or_nan(float nofpclass(inf sub norm nzero) %pzero.or.nan, float %unknown) { ; CHECK-LABEL: define nofpclass(nan inf) float @ret_noinf_nonan__not_inf_or_nan__fmul__known_pzero_or_nan( ; CHECK-SAME: float nofpclass(inf nzero sub norm) [[PZERO_OR_NAN:%.*]], float [[UNKNOWN:%.*]]) { -; CHECK-NEXT: [[MUL:%.*]] = fmul float [[PZERO_OR_NAN]], [[UNKNOWN]] +; CHECK-NEXT: [[MUL:%.*]] = fmul float [[UNKNOWN]], 0.000000e+00 ; CHECK-NEXT: ret float [[MUL]] ; %mul = fmul float %pzero.or.nan, %unknown @@ -797,8 +805,7 @@ define nofpclass(ninf) float @ret_noninf__not_nan_neg__fmul__known_zero_or_pos_n define nofpclass(inf norm sub zero) float @ret_only_nan_results_fmul(float %x, float %y) { ; CHECK-LABEL: define nofpclass(inf zero sub norm) float @ret_only_nan_results_fmul( ; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) { -; CHECK-NEXT: [[MUL:%.*]] = fmul float [[X]], [[Y]] -; CHECK-NEXT: ret float [[MUL]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %mul = fmul float %x, %y ret float %mul @@ -872,7 +879,7 @@ define nofpclass(nan) float @ret_no_nan__fmul_pzero__unknown(float %unknown) { ; CHECK-LABEL: define nofpclass(nan) float @ret_no_nan__fmul_pzero__unknown( ; CHECK-SAME: float [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[PZERO:%.*]] = call float @returns_pzero() -; CHECK-NEXT: [[FMUL:%.*]] = fmul float [[PZERO]], [[UNKNOWN]] +; CHECK-NEXT: [[FMUL:%.*]] = fmul float [[UNKNOWN]], 0.000000e+00 ; CHECK-NEXT: ret float [[FMUL]] ; %pzero = call float @returns_pzero() @@ -884,7 +891,7 @@ define nofpclass(nan) float @ret_no_nan__fmul_unknown__pzero(float %unknown) { ; CHECK-LABEL: define nofpclass(nan) float @ret_no_nan__fmul_unknown__pzero( ; CHECK-SAME: float [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[PZERO:%.*]] = call float @returns_pzero() -; CHECK-NEXT: [[FMUL:%.*]] = fmul float [[UNKNOWN]], [[PZERO]] +; CHECK-NEXT: [[FMUL:%.*]] = fmul float [[UNKNOWN]], 0.000000e+00 ; CHECK-NEXT: ret float [[FMUL]] ; %pzero = call float @returns_pzero() @@ -896,7 +903,7 @@ define nofpclass(nan) float @ret_no_nan__fmul_nzero__unknown(float %unknown) { ; CHECK-LABEL: define nofpclass(nan) float @ret_no_nan__fmul_nzero__unknown( ; CHECK-SAME: float [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[NZERO:%.*]] = call float @returns_nzero() -; CHECK-NEXT: [[FMUL:%.*]] = fmul float [[NZERO]], [[UNKNOWN]] +; CHECK-NEXT: [[FMUL:%.*]] = fmul float [[UNKNOWN]], -0.000000e+00 ; CHECK-NEXT: ret float [[FMUL]] ; %nzero = call float @returns_nzero() @@ -908,7 +915,7 @@ define nofpclass(nan) float @ret_no_nan__fmul_unknown__nzero(float %unknown) { ; CHECK-LABEL: define nofpclass(nan) float @ret_no_nan__fmul_unknown__nzero( ; CHECK-SAME: float [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[NZERO:%.*]] = call float @returns_nzero() -; CHECK-NEXT: [[FMUL:%.*]] = fmul float [[UNKNOWN]], [[NZERO]] +; CHECK-NEXT: [[FMUL:%.*]] = fmul float [[UNKNOWN]], -0.000000e+00 ; CHECK-NEXT: ret float [[FMUL]] ; %nzero = call float @returns_nzero() @@ -1032,7 +1039,7 @@ define nofpclass(inf) float @ret_noinf__not_inf_or_nan__fmul__nzero_or_nan(float define nofpclass(nan) float @ret_nonan__nzero_or_nan__fmul__not_inf_or_nan(float nofpclass(inf sub norm pzero) %nzero.or.nan, float nofpclass(nan) %not.nan) { ; CHECK-LABEL: define nofpclass(nan) float @ret_nonan__nzero_or_nan__fmul__not_inf_or_nan( ; CHECK-SAME: float nofpclass(inf pzero sub norm) [[NZERO_OR_NAN:%.*]], float nofpclass(nan) [[NOT_NAN:%.*]]) { -; CHECK-NEXT: [[MUL:%.*]] = fmul float [[NZERO_OR_NAN]], [[NOT_NAN]] +; CHECK-NEXT: [[MUL:%.*]] = fmul float [[NOT_NAN]], -0.000000e+00 ; CHECK-NEXT: ret float [[MUL]] ; %mul = fmul float %nzero.or.nan, %not.nan @@ -1043,7 +1050,7 @@ define nofpclass(nan) float @ret_nonan__nzero_or_nan__fmul__not_inf_or_nan(float define nofpclass(nan) float @ret_nonan__not_inf_or_nan__fmul__nzero_or_nan(float nofpclass(nan) %not.nan, float nofpclass(inf sub norm pzero) %nzero.or.nan) { ; CHECK-LABEL: define nofpclass(nan) float @ret_nonan__not_inf_or_nan__fmul__nzero_or_nan( ; CHECK-SAME: float nofpclass(nan) [[NOT_NAN:%.*]], float nofpclass(inf pzero sub norm) [[NZERO_OR_NAN:%.*]]) { -; CHECK-NEXT: [[MUL:%.*]] = fmul float [[NOT_NAN]], [[NZERO_OR_NAN]] +; CHECK-NEXT: [[MUL:%.*]] = fmul float [[NOT_NAN]], -0.000000e+00 ; CHECK-NEXT: ret float [[MUL]] ; %mul = fmul float %not.nan, %nzero.or.nan @@ -1076,7 +1083,8 @@ define nofpclass(snan) float @ret_not_inf_or_nan__fmul_ninf__nzero_or_nan(float define nofpclass(snan) float @ret__nzero_or_nan__fmul_nnan__not_inf_or_nan(float nofpclass(inf sub norm pzero) %nzero.or.nan, float %unknown) { ; CHECK-LABEL: define nofpclass(snan) float @ret__nzero_or_nan__fmul_nnan__not_inf_or_nan( ; CHECK-SAME: float nofpclass(inf pzero sub norm) [[NZERO_OR_NAN:%.*]], float [[UNKNOWN:%.*]]) { -; CHECK-NEXT: [[MUL:%.*]] = fmul nnan float [[NZERO_OR_NAN]], [[UNKNOWN]] +; CHECK-NEXT: [[TMP1:%.*]] = fneg nnan float [[UNKNOWN]] +; CHECK-NEXT: [[MUL:%.*]] = call nnan float @llvm.copysign.f32(float 0.000000e+00, float [[TMP1]]) ; CHECK-NEXT: ret float [[MUL]] ; %mul = fmul nnan float %nzero.or.nan, %unknown @@ -1087,7 +1095,8 @@ define nofpclass(snan) float @ret__nzero_or_nan__fmul_nnan__not_inf_or_nan(float define nofpclass(snan) float @not_inf_or_nan__fmul_nnan__nzero_or_nan(float %unknown, float nofpclass(inf sub norm pzero) %nzero.or.nan) { ; CHECK-LABEL: define nofpclass(snan) float @not_inf_or_nan__fmul_nnan__nzero_or_nan( ; CHECK-SAME: float [[UNKNOWN:%.*]], float nofpclass(inf pzero sub norm) [[NZERO_OR_NAN:%.*]]) { -; CHECK-NEXT: [[MUL:%.*]] = fmul nnan float [[UNKNOWN]], [[NZERO_OR_NAN]] +; CHECK-NEXT: [[TMP1:%.*]] = fneg nnan float [[UNKNOWN]] +; CHECK-NEXT: [[MUL:%.*]] = call nnan float @llvm.copysign.f32(float 0.000000e+00, float [[TMP1]]) ; CHECK-NEXT: ret float [[MUL]] ; %mul = fmul nnan float %unknown, %nzero.or.nan @@ -1098,7 +1107,7 @@ define nofpclass(snan) float @not_inf_or_nan__fmul_nnan__nzero_or_nan(float %unk define nofpclass(snan) float @known__pzero_or_nan__fmul__not_inf_or_nan(float nofpclass(inf sub norm nzero) %pzero.or.nan, float nofpclass(inf nan) %not.inf.or.nan) { ; CHECK-LABEL: define nofpclass(snan) float @known__pzero_or_nan__fmul__not_inf_or_nan( ; CHECK-SAME: float nofpclass(inf nzero sub norm) [[PZERO_OR_NAN:%.*]], float nofpclass(nan inf) [[NOT_INF_OR_NAN:%.*]]) { -; CHECK-NEXT: [[MUL:%.*]] = fmul contract float [[PZERO_OR_NAN]], [[NOT_INF_OR_NAN]] +; CHECK-NEXT: [[MUL:%.*]] = call contract float @llvm.copysign.f32(float [[PZERO_OR_NAN]], float [[NOT_INF_OR_NAN]]) ; CHECK-NEXT: ret float [[MUL]] ; %mul = fmul contract float %pzero.or.nan, %not.inf.or.nan @@ -1109,7 +1118,7 @@ define nofpclass(snan) float @known__pzero_or_nan__fmul__not_inf_or_nan(float no define nofpclass(snan) float @known__not_inf_or_nan__fmul__pzero_or_nan(float nofpclass(inf nan) %not.inf.or.nan, float nofpclass(inf sub norm nzero) %pzero.or.nan) { ; CHECK-LABEL: define nofpclass(snan) float @known__not_inf_or_nan__fmul__pzero_or_nan( ; CHECK-SAME: float nofpclass(nan inf) [[NOT_INF_OR_NAN:%.*]], float nofpclass(inf nzero sub norm) [[PZERO_OR_NAN:%.*]]) { -; CHECK-NEXT: [[MUL:%.*]] = fmul contract float [[NOT_INF_OR_NAN]], [[PZERO_OR_NAN]] +; CHECK-NEXT: [[MUL:%.*]] = call contract float @llvm.copysign.f32(float [[PZERO_OR_NAN]], float [[NOT_INF_OR_NAN]]) ; CHECK-NEXT: ret float [[MUL]] ; %mul = fmul contract float %not.inf.or.nan, %pzero.or.nan diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass.ll b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass.ll index a7ff967d3123b..667f7191385e4 100644 --- a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass.ll +++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass.ll @@ -970,8 +970,7 @@ define nofpclass(nan inf nzero nsub nnorm) float @test_powr_issue64870_2(float n ; CHECK-NEXT: [[I:%.*]] = fcmp olt float [[ARG]], 0.000000e+00 ; CHECK-NEXT: [[I2:%.*]] = select i1 [[I]], float 0x7FF8000000000000, float [[ARG]] ; CHECK-NEXT: [[I3:%.*]] = tail call float @llvm.log2.f32(float noundef [[I2]]) -; CHECK-NEXT: [[I4:%.*]] = select i1 [[I]], float 0x7FF8000000000000, float [[ARG1]] -; CHECK-NEXT: [[I5:%.*]] = fmul float [[I4]], [[I3]] +; CHECK-NEXT: [[I5:%.*]] = fmul float [[ARG1]], [[I3]] ; CHECK-NEXT: [[I6:%.*]] = tail call noundef nofpclass(ninf nzero nsub nnorm) float @llvm.exp2.f32(float noundef [[I5]]) ; CHECK-NEXT: [[I10:%.*]] = fcmp oeq float [[I2]], 0.000000e+00 ; CHECK-NEXT: [[I12:%.*]] = select i1 [[I10]], float 0.000000e+00, float [[I6]] _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
