diff --git a/llvm/include/llvm/Analysis/InstructionSimplify.h b/llvm/include/llvm/Analysis/InstructionSimplify.h --- a/llvm/include/llvm/Analysis/InstructionSimplify.h +++ b/llvm/include/llvm/Analysis/InstructionSimplify.h @@ -157,23 +157,34 @@ const SimplifyQuery &Q); /// Given operands for an FAdd, fold the result or return null. -Value *SimplifyFAddInst(Value *LHS, Value *RHS, FastMathFlags FMF, - const SimplifyQuery &Q); +Value * +SimplifyFAddInst(Value *LHS, Value *RHS, FastMathFlags FMF, + const SimplifyQuery &Q, + fp::ExceptionBehavior ExBehavior = fp::ebIgnore, + RoundingMode Rounding = RoundingMode::NearestTiesToEven); /// Given operands for an FSub, fold the result or return null. -Value *SimplifyFSubInst(Value *LHS, Value *RHS, FastMathFlags FMF, - const SimplifyQuery &Q); +Value * +SimplifyFSubInst(Value *LHS, Value *RHS, FastMathFlags FMF, + const SimplifyQuery &Q, + fp::ExceptionBehavior ExBehavior = fp::ebIgnore, + RoundingMode Rounding = RoundingMode::NearestTiesToEven); /// Given operands for an FMul, fold the result or return null. -Value *SimplifyFMulInst(Value *LHS, Value *RHS, FastMathFlags FMF, - const SimplifyQuery &Q); +Value * +SimplifyFMulInst(Value *LHS, Value *RHS, FastMathFlags FMF, + const SimplifyQuery &Q, + fp::ExceptionBehavior ExBehavior = fp::ebIgnore, + RoundingMode Rounding = RoundingMode::NearestTiesToEven); /// Given operands for the multiplication of a FMA, fold the result or return /// null. In contrast to SimplifyFMulInst, this function will not perform /// simplifications whose unrounded results differ when rounded to the argument /// type. Value *SimplifyFMAFMul(Value *LHS, Value *RHS, FastMathFlags FMF, - const SimplifyQuery &Q); + const SimplifyQuery &Q, + fp::ExceptionBehavior ExBehavior = fp::ebIgnore, + RoundingMode Rounding = RoundingMode::NearestTiesToEven); /// Given operands for a Mul, fold the result or return null. Value *SimplifyMulInst(Value *LHS, Value *RHS, const SimplifyQuery &Q); @@ -185,8 +196,11 @@ Value *SimplifyUDivInst(Value *LHS, Value *RHS, const SimplifyQuery &Q); /// Given operands for an FDiv, fold the result or return null. -Value *SimplifyFDivInst(Value *LHS, Value *RHS, FastMathFlags FMF, - const SimplifyQuery &Q); +Value * +SimplifyFDivInst(Value *LHS, Value *RHS, FastMathFlags FMF, + const SimplifyQuery &Q, + fp::ExceptionBehavior ExBehavior = fp::ebIgnore, + RoundingMode Rounding = RoundingMode::NearestTiesToEven); /// Given operands for an SRem, fold the result or return null. Value *SimplifySRemInst(Value *LHS, Value *RHS, const SimplifyQuery &Q); @@ -195,8 +209,11 @@ Value *SimplifyURemInst(Value *LHS, Value *RHS, const SimplifyQuery &Q); /// Given operands for an FRem, fold the result or return null. -Value *SimplifyFRemInst(Value *LHS, Value *RHS, FastMathFlags FMF, - const SimplifyQuery &Q); +Value * +SimplifyFRemInst(Value *LHS, Value *RHS, FastMathFlags FMF, + const SimplifyQuery &Q, + fp::ExceptionBehavior ExBehavior = fp::ebIgnore, + RoundingMode Rounding = RoundingMode::NearestTiesToEven); /// Given operands for a Shl, fold the result or return null. Value *SimplifyShlInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW, diff --git a/llvm/include/llvm/IR/FPEnv.h b/llvm/include/llvm/IR/FPEnv.h --- a/llvm/include/llvm/IR/FPEnv.h +++ b/llvm/include/llvm/IR/FPEnv.h @@ -52,5 +52,11 @@ /// For any ExceptionBehavior enumerator, returns a string valid as /// input in constrained intrinsic exception behavior metadata. Optional ExceptionBehaviorToStr(fp::ExceptionBehavior); + +/// Returns true if the exception handling behavior and rounding mode +/// match what is used in the default floating point environment. +inline bool isDefaultFPEnvironment(fp::ExceptionBehavior EB, RoundingMode RM) { + return EB == fp::ebIgnore && RM == RoundingMode::NearestTiesToEven; +} } #endif diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -4856,7 +4856,9 @@ /// transforms based on poison/undef/NaN because the operation itself makes no /// difference to the result. static Constant *simplifyFPOp(ArrayRef Ops, FastMathFlags FMF, - const SimplifyQuery &Q) { + const SimplifyQuery &Q, + fp::ExceptionBehavior ExBehavior, + RoundingMode Rounding) { // Poison is independent of anything else. It always propagates from an // operand to a math result. if (any_of(Ops, [](Value *V) { return match(V, m_Poison()); })) @@ -4875,22 +4877,34 @@ if (FMF.noInfs() && (IsInf || IsUndef)) return PoisonValue::get(V->getType()); - if (IsUndef || IsNan) - return propagateNaN(cast(V)); + if (isDefaultFPEnvironment(ExBehavior, Rounding)) { + if (IsUndef || IsNan) + return propagateNaN(cast(V)); + } else if (ExBehavior != fp::ebStrict) { + if (IsNan) + return propagateNaN(cast(V)); + } } return nullptr; } /// Given operands for an FAdd, see if we can fold the result. If not, this /// returns null. -static Value *SimplifyFAddInst(Value *Op0, Value *Op1, FastMathFlags FMF, - const SimplifyQuery &Q, unsigned MaxRecurse) { - if (Constant *C = foldOrCommuteConstant(Instruction::FAdd, Op0, Op1, Q)) - return C; +static Value * +SimplifyFAddInst(Value *Op0, Value *Op1, FastMathFlags FMF, + const SimplifyQuery &Q, unsigned MaxRecurse, + fp::ExceptionBehavior ExBehavior = fp::ebIgnore, + RoundingMode Rounding = RoundingMode::NearestTiesToEven) { + if (isDefaultFPEnvironment(ExBehavior, Rounding)) + if (Constant *C = foldOrCommuteConstant(Instruction::FAdd, Op0, Op1, Q)) + return C; - if (Constant *C = simplifyFPOp({Op0, Op1}, FMF, Q)) + if (Constant *C = simplifyFPOp({Op0, Op1}, FMF, Q, ExBehavior, Rounding)) return C; + if (!isDefaultFPEnvironment(ExBehavior, Rounding)) + return nullptr; + // fadd X, -0 ==> X if (match(Op1, m_NegZeroFP())) return Op0; @@ -4930,14 +4944,21 @@ /// Given operands for an FSub, see if we can fold the result. If not, this /// returns null. -static Value *SimplifyFSubInst(Value *Op0, Value *Op1, FastMathFlags FMF, - const SimplifyQuery &Q, unsigned MaxRecurse) { - if (Constant *C = foldOrCommuteConstant(Instruction::FSub, Op0, Op1, Q)) - return C; +static Value * +SimplifyFSubInst(Value *Op0, Value *Op1, FastMathFlags FMF, + const SimplifyQuery &Q, unsigned MaxRecurse, + fp::ExceptionBehavior ExBehavior = fp::ebIgnore, + RoundingMode Rounding = RoundingMode::NearestTiesToEven) { + if (isDefaultFPEnvironment(ExBehavior, Rounding)) + if (Constant *C = foldOrCommuteConstant(Instruction::FSub, Op0, Op1, Q)) + return C; - if (Constant *C = simplifyFPOp({Op0, Op1}, FMF, Q)) + if (Constant *C = simplifyFPOp({Op0, Op1}, FMF, Q, ExBehavior, Rounding)) return C; + if (!isDefaultFPEnvironment(ExBehavior, Rounding)) + return nullptr; + // fsub X, +0 ==> X if (match(Op1, m_PosZeroFP())) return Op0; @@ -4976,10 +4997,15 @@ } static Value *SimplifyFMAFMul(Value *Op0, Value *Op1, FastMathFlags FMF, - const SimplifyQuery &Q, unsigned MaxRecurse) { - if (Constant *C = simplifyFPOp({Op0, Op1}, FMF, Q)) + const SimplifyQuery &Q, unsigned MaxRecurse, + fp::ExceptionBehavior ExBehavior, + RoundingMode Rounding) { + if (Constant *C = simplifyFPOp({Op0, Op1}, FMF, Q, ExBehavior, Rounding)) return C; + if (!isDefaultFPEnvironment(ExBehavior, Rounding)) + return nullptr; + // fmul X, 1.0 ==> X if (match(Op1, m_FPOne())) return Op0; @@ -5009,43 +5035,65 @@ } /// Given the operands for an FMul, see if we can fold the result -static Value *SimplifyFMulInst(Value *Op0, Value *Op1, FastMathFlags FMF, - const SimplifyQuery &Q, unsigned MaxRecurse) { - if (Constant *C = foldOrCommuteConstant(Instruction::FMul, Op0, Op1, Q)) - return C; +static Value * +SimplifyFMulInst(Value *Op0, Value *Op1, FastMathFlags FMF, + const SimplifyQuery &Q, unsigned MaxRecurse, + fp::ExceptionBehavior ExBehavior = fp::ebIgnore, + RoundingMode Rounding = RoundingMode::NearestTiesToEven) { + if (isDefaultFPEnvironment(ExBehavior, Rounding)) + if (Constant *C = foldOrCommuteConstant(Instruction::FMul, Op0, Op1, Q)) + return C; // Now apply simplifications that do not require rounding. - return SimplifyFMAFMul(Op0, Op1, FMF, Q, MaxRecurse); + return SimplifyFMAFMul(Op0, Op1, FMF, Q, MaxRecurse, ExBehavior, Rounding); } Value *llvm::SimplifyFAddInst(Value *Op0, Value *Op1, FastMathFlags FMF, - const SimplifyQuery &Q) { - return ::SimplifyFAddInst(Op0, Op1, FMF, Q, RecursionLimit); + const SimplifyQuery &Q, + fp::ExceptionBehavior ExBehavior, + RoundingMode Rounding) { + return ::SimplifyFAddInst(Op0, Op1, FMF, Q, RecursionLimit, ExBehavior, + Rounding); } - Value *llvm::SimplifyFSubInst(Value *Op0, Value *Op1, FastMathFlags FMF, - const SimplifyQuery &Q) { - return ::SimplifyFSubInst(Op0, Op1, FMF, Q, RecursionLimit); + const SimplifyQuery &Q, + fp::ExceptionBehavior ExBehavior, + RoundingMode Rounding) { + return ::SimplifyFSubInst(Op0, Op1, FMF, Q, RecursionLimit, ExBehavior, + Rounding); } Value *llvm::SimplifyFMulInst(Value *Op0, Value *Op1, FastMathFlags FMF, - const SimplifyQuery &Q) { - return ::SimplifyFMulInst(Op0, Op1, FMF, Q, RecursionLimit); + const SimplifyQuery &Q, + fp::ExceptionBehavior ExBehavior, + RoundingMode Rounding) { + return ::SimplifyFMulInst(Op0, Op1, FMF, Q, RecursionLimit, ExBehavior, + Rounding); } Value *llvm::SimplifyFMAFMul(Value *Op0, Value *Op1, FastMathFlags FMF, - const SimplifyQuery &Q) { - return ::SimplifyFMAFMul(Op0, Op1, FMF, Q, RecursionLimit); -} + const SimplifyQuery &Q, + fp::ExceptionBehavior ExBehavior, + RoundingMode Rounding) { + return ::SimplifyFMAFMul(Op0, Op1, FMF, Q, RecursionLimit, ExBehavior, + Rounding); +} + +static Value * +SimplifyFDivInst(Value *Op0, Value *Op1, FastMathFlags FMF, + const SimplifyQuery &Q, unsigned, + fp::ExceptionBehavior ExBehavior = fp::ebIgnore, + RoundingMode Rounding = RoundingMode::NearestTiesToEven) { + if (isDefaultFPEnvironment(ExBehavior, Rounding)) + if (Constant *C = foldOrCommuteConstant(Instruction::FDiv, Op0, Op1, Q)) + return C; -static Value *SimplifyFDivInst(Value *Op0, Value *Op1, FastMathFlags FMF, - const SimplifyQuery &Q, unsigned) { - if (Constant *C = foldOrCommuteConstant(Instruction::FDiv, Op0, Op1, Q)) + if (Constant *C = simplifyFPOp({Op0, Op1}, FMF, Q, ExBehavior, Rounding)) return C; - if (Constant *C = simplifyFPOp({Op0, Op1}, FMF, Q)) - return C; + if (!isDefaultFPEnvironment(ExBehavior, Rounding)) + return nullptr; // X / 1.0 -> X if (match(Op1, m_FPOne())) @@ -5080,17 +5128,27 @@ } Value *llvm::SimplifyFDivInst(Value *Op0, Value *Op1, FastMathFlags FMF, - const SimplifyQuery &Q) { - return ::SimplifyFDivInst(Op0, Op1, FMF, Q, RecursionLimit); -} + const SimplifyQuery &Q, + fp::ExceptionBehavior ExBehavior, + RoundingMode Rounding) { + return ::SimplifyFDivInst(Op0, Op1, FMF, Q, RecursionLimit, ExBehavior, + Rounding); +} + +static Value * +SimplifyFRemInst(Value *Op0, Value *Op1, FastMathFlags FMF, + const SimplifyQuery &Q, unsigned, + fp::ExceptionBehavior ExBehavior = fp::ebIgnore, + RoundingMode Rounding = RoundingMode::NearestTiesToEven) { + if (isDefaultFPEnvironment(ExBehavior, Rounding)) + if (Constant *C = foldOrCommuteConstant(Instruction::FRem, Op0, Op1, Q)) + return C; -static Value *SimplifyFRemInst(Value *Op0, Value *Op1, FastMathFlags FMF, - const SimplifyQuery &Q, unsigned) { - if (Constant *C = foldOrCommuteConstant(Instruction::FRem, Op0, Op1, Q)) + if (Constant *C = simplifyFPOp({Op0, Op1}, FMF, Q, ExBehavior, Rounding)) return C; - if (Constant *C = simplifyFPOp({Op0, Op1}, FMF, Q)) - return C; + if (!isDefaultFPEnvironment(ExBehavior, Rounding)) + return nullptr; // Unlike fdiv, the result of frem always matches the sign of the dividend. // The constant match may include undef elements in a vector, so return a full @@ -5108,8 +5166,11 @@ } Value *llvm::SimplifyFRemInst(Value *Op0, Value *Op1, FastMathFlags FMF, - const SimplifyQuery &Q) { - return ::SimplifyFRemInst(Op0, Op1, FMF, Q, RecursionLimit); + const SimplifyQuery &Q, + fp::ExceptionBehavior ExBehavior, + RoundingMode Rounding) { + return ::SimplifyFRemInst(Op0, Op1, FMF, Q, RecursionLimit, ExBehavior, + Rounding); } //=== Helper functions for higher up the class hierarchy. @@ -5755,12 +5816,24 @@ } return nullptr; } + case Intrinsic::experimental_constrained_fma: { + Value *Op0 = Call->getArgOperand(0); + Value *Op1 = Call->getArgOperand(1); + Value *Op2 = Call->getArgOperand(2); + auto *FPI = cast(Call); + if (Value *V = simplifyFPOp({Op0, Op1, Op2}, {}, Q, + FPI->getExceptionBehavior().getValue(), + FPI->getRoundingMode().getValue())) + return V; + return nullptr; + } case Intrinsic::fma: case Intrinsic::fmuladd: { Value *Op0 = Call->getArgOperand(0); Value *Op1 = Call->getArgOperand(1); Value *Op2 = Call->getArgOperand(2); - if (Value *V = simplifyFPOp({ Op0, Op1, Op2 }, {}, Q)) + if (Value *V = simplifyFPOp({Op0, Op1, Op2}, {}, Q, fp::ebIgnore, + RoundingMode::NearestTiesToEven)) return V; return nullptr; } @@ -5812,6 +5885,46 @@ return nullptr; } + case Intrinsic::experimental_constrained_fadd: { + auto *FPI = cast(Call); + return SimplifyFAddInst(FPI->getArgOperand(0), FPI->getArgOperand(1), + FPI->getFastMathFlags(), Q, + FPI->getExceptionBehavior().getValue(), + FPI->getRoundingMode().getValue()); + break; + } + case Intrinsic::experimental_constrained_fsub: { + auto *FPI = cast(Call); + return SimplifyFSubInst(FPI->getArgOperand(0), FPI->getArgOperand(1), + FPI->getFastMathFlags(), Q, + FPI->getExceptionBehavior().getValue(), + FPI->getRoundingMode().getValue()); + break; + } + case Intrinsic::experimental_constrained_fmul: { + auto *FPI = cast(Call); + return SimplifyFMulInst(FPI->getArgOperand(0), FPI->getArgOperand(1), + FPI->getFastMathFlags(), Q, + FPI->getExceptionBehavior().getValue(), + FPI->getRoundingMode().getValue()); + break; + } + case Intrinsic::experimental_constrained_fdiv: { + auto *FPI = cast(Call); + return SimplifyFDivInst(FPI->getArgOperand(0), FPI->getArgOperand(1), + FPI->getFastMathFlags(), Q, + FPI->getExceptionBehavior().getValue(), + FPI->getRoundingMode().getValue()); + break; + } + case Intrinsic::experimental_constrained_frem: { + auto *FPI = cast(Call); + return SimplifyFRemInst(FPI->getArgOperand(0), FPI->getArgOperand(1), + FPI->getFastMathFlags(), Q, + FPI->getExceptionBehavior().getValue(), + FPI->getRoundingMode().getValue()); + break; + } default: return nullptr; } diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp --- a/llvm/lib/Transforms/Utils/Local.cpp +++ b/llvm/lib/Transforms/Utils/Local.cpp @@ -473,6 +473,11 @@ return false; } + + if (auto *FPI = dyn_cast(I)) { + Optional ExBehavior = FPI->getExceptionBehavior(); + return ExBehavior.getValue() != fp::ebStrict; + } } if (isAllocLikeFn(I, TLI)) diff --git a/llvm/test/Transforms/InstSimplify/X86/fp-nan-strictfp.ll b/llvm/test/Transforms/InstSimplify/X86/fp-nan-strictfp.ll --- a/llvm/test/Transforms/InstSimplify/X86/fp-nan-strictfp.ll +++ b/llvm/test/Transforms/InstSimplify/X86/fp-nan-strictfp.ll @@ -16,8 +16,7 @@ define float @fadd_nan_op0_maytrap(float %x) #0 { ; CHECK-LABEL: @fadd_nan_op0_maytrap( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float 0x7FF8000000000000, float [[X:%.*]], metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.fadd.f32(float 0x7FF8000000000000, float %x, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0 ret float %r @@ -25,8 +24,7 @@ define float @fadd_nan_op0_upward(float %x) #0 { ; CHECK-LABEL: @fadd_nan_op0_upward( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float 0x7FF8000000000000, float [[X:%.*]], metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.fadd.f32(float 0x7FF8000000000000, float %x, metadata !"round.upward", metadata !"fpexcept.ignore") #0 ret float %r @@ -34,8 +32,7 @@ define float @fadd_nan_op0_defaultfp(float %x) #0 { ; CHECK-LABEL: @fadd_nan_op0_defaultfp( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float 0x7FF8000000000000, float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.fadd.f32(float 0x7FF8000000000000, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 ret float %r @@ -52,8 +49,7 @@ define float @fadd_nan_op1_maytrap(float %x) #0 { ; CHECK-LABEL: @fadd_nan_op1_maytrap( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[X:%.*]], float 0x7FF8000000000000, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.fadd.f32(float %x, float 0x7FF8000000000000, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0 ret float %r @@ -61,8 +57,7 @@ define float @fadd_nan_op1_upward(float %x) #0 { ; CHECK-LABEL: @fadd_nan_op1_upward( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[X:%.*]], float 0x7FF8000000000000, metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.fadd.f32(float %x, float 0x7FF8000000000000, metadata !"round.upward", metadata !"fpexcept.ignore") #0 ret float %r @@ -70,8 +65,7 @@ define float @fadd_nan_op1_defaultfp(float %x) #0 { ; CHECK-LABEL: @fadd_nan_op1_defaultfp( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[X:%.*]], float 0x7FF8000000000000, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.fadd.f32(float %x, float 0x7FF8000000000000, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 ret float %r @@ -92,8 +86,7 @@ define float @fsub_nan_op0_maytrap(float %x) { ; CHECK-LABEL: @fsub_nan_op0_maytrap( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float 0x7FF8000000000000, float [[X:%.*]], metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.fsub.f32(float 0x7FF8000000000000, float %x, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0 ret float %r @@ -101,8 +94,7 @@ define float @fsub_nan_op0_upward(float %x) { ; CHECK-LABEL: @fsub_nan_op0_upward( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float 0x7FF8000000000000, float [[X:%.*]], metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.fsub.f32(float 0x7FF8000000000000, float %x, metadata !"round.upward", metadata !"fpexcept.ignore") #0 ret float %r @@ -110,8 +102,7 @@ define float @fsub_nan_op0_defaultfp(float %x) { ; CHECK-LABEL: @fsub_nan_op0_defaultfp( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float 0x7FF8000000000000, float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.fsub.f32(float 0x7FF8000000000000, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 ret float %r @@ -128,8 +119,7 @@ define float @fsub_nan_op1_maytrap(float %x) { ; CHECK-LABEL: @fsub_nan_op1_maytrap( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[X:%.*]], float 0x7FF8000000000000, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.fsub.f32(float %x, float 0x7FF8000000000000, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0 ret float %r @@ -137,8 +127,7 @@ define float @fsub_nan_op1_upward(float %x) { ; CHECK-LABEL: @fsub_nan_op1_upward( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[X:%.*]], float 0x7FF8000000000000, metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.fsub.f32(float %x, float 0x7FF8000000000000, metadata !"round.upward", metadata !"fpexcept.ignore") #0 ret float %r @@ -146,8 +135,7 @@ define float @fsub_nan_op1_defaultfp(float %x) { ; CHECK-LABEL: @fsub_nan_op1_defaultfp( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[X:%.*]], float 0x7FF8000000000000, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.fsub.f32(float %x, float 0x7FF8000000000000, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 ret float %r @@ -168,8 +156,7 @@ define float @fmul_nan_op0_maytrap(float %x) { ; CHECK-LABEL: @fmul_nan_op0_maytrap( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fmul.f32(float 0x7FF8000000000000, float [[X:%.*]], metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.fmul.f32(float 0x7FF8000000000000, float %x, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0 ret float %r @@ -177,8 +164,7 @@ define float @fmul_nan_op0_upward(float %x) { ; CHECK-LABEL: @fmul_nan_op0_upward( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fmul.f32(float 0x7FF8000000000000, float [[X:%.*]], metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.fmul.f32(float 0x7FF8000000000000, float %x, metadata !"round.upward", metadata !"fpexcept.ignore") #0 ret float %r @@ -186,8 +172,7 @@ define float @fmul_nan_op0_defaultfp(float %x) { ; CHECK-LABEL: @fmul_nan_op0_defaultfp( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fmul.f32(float 0x7FF8000000000000, float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.fmul.f32(float 0x7FF8000000000000, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 ret float %r @@ -204,8 +189,7 @@ define float @fmul_nan_op1_maytrap(float %x) { ; CHECK-LABEL: @fmul_nan_op1_maytrap( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fmul.f32(float [[X:%.*]], float 0x7FF8000000000000, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.fmul.f32(float %x, float 0x7FF8000000000000, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0 ret float %r @@ -213,8 +197,7 @@ define float @fmul_nan_op1_upward(float %x) { ; CHECK-LABEL: @fmul_nan_op1_upward( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fmul.f32(float [[X:%.*]], float 0x7FF8000000000000, metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.fmul.f32(float %x, float 0x7FF8000000000000, metadata !"round.upward", metadata !"fpexcept.ignore") #0 ret float %r @@ -222,8 +205,7 @@ define float @fmul_nan_op1_defaultfp(float %x) { ; CHECK-LABEL: @fmul_nan_op1_defaultfp( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fmul.f32(float [[X:%.*]], float 0x7FF8000000000000, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.fmul.f32(float %x, float 0x7FF8000000000000, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 ret float %r @@ -244,8 +226,7 @@ define float @fdiv_nan_op0_maytrap(float %x) { ; CHECK-LABEL: @fdiv_nan_op0_maytrap( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fdiv.f32(float 0x7FF8000000000000, float [[X:%.*]], metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.fdiv.f32(float 0x7FF8000000000000, float %x, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0 ret float %r @@ -253,8 +234,7 @@ define float @fdiv_nan_op0_upward(float %x) { ; CHECK-LABEL: @fdiv_nan_op0_upward( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fdiv.f32(float 0x7FF8000000000000, float [[X:%.*]], metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.fdiv.f32(float 0x7FF8000000000000, float %x, metadata !"round.upward", metadata !"fpexcept.ignore") #0 ret float %r @@ -262,8 +242,7 @@ define float @fdiv_nan_op0_defaultfp(float %x) { ; CHECK-LABEL: @fdiv_nan_op0_defaultfp( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fdiv.f32(float 0x7FF8000000000000, float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.fdiv.f32(float 0x7FF8000000000000, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 ret float %r @@ -280,8 +259,7 @@ define float @fdiv_nan_op1_maytrap(float %x) { ; CHECK-LABEL: @fdiv_nan_op1_maytrap( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fdiv.f32(float [[X:%.*]], float 0x7FF8000000000000, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.fdiv.f32(float %x, float 0x7FF8000000000000, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0 ret float %r @@ -289,8 +267,7 @@ define float @fdiv_nan_op1_upward(float %x) { ; CHECK-LABEL: @fdiv_nan_op1_upward( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fdiv.f32(float [[X:%.*]], float 0x7FF8000000000000, metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.fdiv.f32(float %x, float 0x7FF8000000000000, metadata !"round.upward", metadata !"fpexcept.ignore") #0 ret float %r @@ -298,8 +275,7 @@ define float @fdiv_nan_op1_defaultfp(float %x) { ; CHECK-LABEL: @fdiv_nan_op1_defaultfp( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fdiv.f32(float [[X:%.*]], float 0x7FF8000000000000, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.fdiv.f32(float %x, float 0x7FF8000000000000, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 ret float %r @@ -320,8 +296,7 @@ define float @frem_nan_op0_maytrap(float %x) { ; CHECK-LABEL: @frem_nan_op0_maytrap( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.frem.f32(float 0x7FF8000000000000, float [[X:%.*]], metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.frem.f32(float 0x7FF8000000000000, float %x, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0 ret float %r @@ -329,8 +304,7 @@ define float @frem_nan_op0_upward(float %x) { ; CHECK-LABEL: @frem_nan_op0_upward( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.frem.f32(float 0x7FF8000000000000, float [[X:%.*]], metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.frem.f32(float 0x7FF8000000000000, float %x, metadata !"round.upward", metadata !"fpexcept.ignore") #0 ret float %r @@ -338,8 +312,7 @@ define float @frem_nan_op0_defaultfp(float %x) { ; CHECK-LABEL: @frem_nan_op0_defaultfp( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.frem.f32(float 0x7FF8000000000000, float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.frem.f32(float 0x7FF8000000000000, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 ret float %r @@ -356,8 +329,7 @@ define float @frem_nan_op1_maytrap(float %x) { ; CHECK-LABEL: @frem_nan_op1_maytrap( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.frem.f32(float [[X:%.*]], float 0x7FF8000000000000, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.frem.f32(float %x, float 0x7FF8000000000000, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0 ret float %r @@ -365,8 +337,7 @@ define float @frem_nan_op1_upward(float %x) { ; CHECK-LABEL: @frem_nan_op1_upward( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.frem.f32(float [[X:%.*]], float 0x7FF8000000000000, metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.frem.f32(float %x, float 0x7FF8000000000000, metadata !"round.upward", metadata !"fpexcept.ignore") #0 ret float %r @@ -374,8 +345,7 @@ define float @frem_nan_op1_defaultfp(float %x) { ; CHECK-LABEL: @frem_nan_op1_defaultfp( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.frem.f32(float [[X:%.*]], float 0x7FF8000000000000, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.frem.f32(float %x, float 0x7FF8000000000000, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 ret float %r @@ -396,8 +366,7 @@ define float @fma_nan_op0_maytrap(float %x, float %y) { ; CHECK-LABEL: @fma_nan_op0_maytrap( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float 0x7FF8000000000000, float [[X:%.*]], float [[Y:%.*]], metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.fma.f32(float 0x7FF8000000000000, float %x, float %y, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0 ret float %r @@ -405,8 +374,7 @@ define float @fma_nan_op0_upward(float %x, float %y) { ; CHECK-LABEL: @fma_nan_op0_upward( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float 0x7FF8000000000000, float [[X:%.*]], float [[Y:%.*]], metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.fma.f32(float 0x7FF8000000000000, float %x, float %y, metadata !"round.upward", metadata !"fpexcept.ignore") #0 ret float %r @@ -414,8 +382,7 @@ define float @fma_nan_op0_defaultfp(float %x, float %y) { ; CHECK-LABEL: @fma_nan_op0_defaultfp( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float 0x7FF8000000000000, float [[X:%.*]], float [[Y:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.fma.f32(float 0x7FF8000000000000, float %x, float %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 ret float %r @@ -432,8 +399,7 @@ define float @fma_nan_op1_maytrap(float %x, float %y) { ; CHECK-LABEL: @fma_nan_op1_maytrap( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float [[X:%.*]], float 0x7FF8000000000000, float [[Y:%.*]], metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.fma.f32(float %x, float 0x7FF8000000000000, float %y, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0 ret float %r @@ -441,8 +407,7 @@ define float @fma_nan_op1_upward(float %x, float %y) { ; CHECK-LABEL: @fma_nan_op1_upward( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float [[X:%.*]], float 0x7FF8000000000000, float [[Y:%.*]], metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.fma.f32(float %x, float 0x7FF8000000000000, float %y, metadata !"round.upward", metadata !"fpexcept.ignore") #0 ret float %r @@ -450,8 +415,7 @@ define float @fma_nan_op1_defaultfp(float %x, float %y) { ; CHECK-LABEL: @fma_nan_op1_defaultfp( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float [[X:%.*]], float 0x7FF8000000000000, float [[Y:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.fma.f32(float %x, float 0x7FF8000000000000, float %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 ret float %r @@ -468,8 +432,7 @@ define float @fma_nan_op2_maytrap(float %x, float %y) { ; CHECK-LABEL: @fma_nan_op2_maytrap( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float [[X:%.*]], float [[Y:%.*]], float 0x7FF8000000000000, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.fma.f32(float %x, float %y, float 0x7FF8000000000000, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0 ret float %r @@ -477,8 +440,7 @@ define float @fma_nan_op2_upward(float %x, float %y) { ; CHECK-LABEL: @fma_nan_op2_upward( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float [[X:%.*]], float [[Y:%.*]], float 0x7FF8000000000000, metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.fma.f32(float %x, float %y, float 0x7FF8000000000000, metadata !"round.upward", metadata !"fpexcept.ignore") #0 ret float %r @@ -486,8 +448,7 @@ define float @fma_nan_op2_defaultfp(float %x, float %y) { ; CHECK-LABEL: @fma_nan_op2_defaultfp( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float [[X:%.*]], float [[Y:%.*]], float 0x7FF8000000000000, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.fma.f32(float %x, float %y, float 0x7FF8000000000000, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 ret float %r diff --git a/llvm/test/Transforms/InstSimplify/fast-math-strictfp.ll b/llvm/test/Transforms/InstSimplify/fast-math-strictfp.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/InstSimplify/fast-math-strictfp.ll @@ -0,0 +1,582 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -instsimplify -S | FileCheck %s + +;; x * 0 ==> 0 when no-nans and no-signed-zero +define float @mul_zero_1(float %a) #0 { +; CHECK-LABEL: @mul_zero_1( +; CHECK-NEXT: ret float 0.000000e+00 +; + %b = call nsz nnan float @llvm.experimental.constrained.fmul.f32(float %a, float 0.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret float %b +} + +define float @mul_zero_2(float %a) #0 { +; CHECK-LABEL: @mul_zero_2( +; CHECK-NEXT: ret float 0.000000e+00 +; + %b = call fast float @llvm.experimental.constrained.fmul.f32(float 0.0, float %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret float %b +} + +define <2 x float> @mul_zero_nsz_nnan_vec_undef(<2 x float> %a) #0 { +; CHECK-LABEL: @mul_zero_nsz_nnan_vec_undef( +; CHECK-NEXT: ret <2 x float> zeroinitializer +; + %b = call nsz nnan <2 x float> @llvm.experimental.constrained.fmul.v2f32(<2 x float> %a, <2 x float>, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret <2 x float> %b +} + +;; x * 0 =/=> 0 when there could be nans or -0 +define float @no_mul_zero_1(float %a) #0 { +; CHECK-LABEL: @no_mul_zero_1( +; CHECK-NEXT: [[B:%.*]] = call nsz float @llvm.experimental.constrained.fmul.f32(float [[A:%.*]], float 0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0:[0-9]+]] +; CHECK-NEXT: ret float [[B]] +; + %b = call nsz float @llvm.experimental.constrained.fmul.f32(float %a, float 0.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret float %b +} + +define float @no_mul_zero_2(float %a) #0 { +; CHECK-LABEL: @no_mul_zero_2( +; CHECK-NEXT: [[B:%.*]] = call nnan float @llvm.experimental.constrained.fmul.f32(float [[A:%.*]], float 0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret float [[B]] +; + %b = call nnan float @llvm.experimental.constrained.fmul.f32(float %a, float 0.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret float %b +} + +define float @no_mul_zero_3(float %a) #0 { +; CHECK-LABEL: @no_mul_zero_3( +; CHECK-NEXT: [[B:%.*]] = call float @llvm.experimental.constrained.fmul.f32(float [[A:%.*]], float 0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret float [[B]] +; + %b = call float @llvm.experimental.constrained.fmul.f32(float %a, float 0.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret float %b +} + +; -X + X --> 0.0 (with nnan on the fadd) + +define float @fadd_binary_fnegx(float %x) #0 { +; CHECK-LABEL: @fadd_binary_fnegx( +; CHECK-NEXT: [[NEGX:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[R:%.*]] = call nnan float @llvm.experimental.constrained.fadd.f32(float [[NEGX]], float [[X]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret float [[R]] +; + %negx = call float @llvm.experimental.constrained.fsub.f32(float -0.0, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %r = call nnan float @llvm.experimental.constrained.fadd.f32(float %negx, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret float %r +} + +define float @fadd_unary_fnegx(float %x) #0 { +; CHECK-LABEL: @fadd_unary_fnegx( +; CHECK-NEXT: ret float 0.000000e+00 +; + %negx = fneg float %x + %r = call nnan float @llvm.experimental.constrained.fadd.f32(float %negx, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret float %r +} + +; X + -X --> 0.0 (with nnan on the fadd) + +define <2 x float> @fadd_binary_fnegx_commute_vec(<2 x float> %x) #0 { +; CHECK-LABEL: @fadd_binary_fnegx_commute_vec( +; CHECK-NEXT: [[NEGX:%.*]] = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> , <2 x float> [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[R:%.*]] = call nnan <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float> [[X]], <2 x float> [[NEGX]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret <2 x float> [[R]] +; + %negx = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> , <2 x float> %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %r = call nnan <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float> %x, <2 x float> %negx, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret <2 x float> %r +} + +define <2 x float> @fadd_unary_fnegx_commute_vec(<2 x float> %x) #0 { +; CHECK-LABEL: @fadd_unary_fnegx_commute_vec( +; CHECK-NEXT: ret <2 x float> zeroinitializer +; + %negx = fneg <2 x float> %x + %r = call nnan <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float> %x, <2 x float> %negx, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret <2 x float> %r +} + +define <2 x float> @fadd_fnegx_commute_vec_undef(<2 x float> %x) #0 { +; CHECK-LABEL: @fadd_fnegx_commute_vec_undef( +; CHECK-NEXT: [[NEGX:%.*]] = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> , <2 x float> [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[R:%.*]] = call nnan <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float> [[X]], <2 x float> [[NEGX]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret <2 x float> [[R]] +; + %negx = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> , <2 x float> %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %r = call nnan <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float> %x, <2 x float> %negx, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret <2 x float> %r +} + +; https://bugs.llvm.org/show_bug.cgi?id=26958 +; https://bugs.llvm.org/show_bug.cgi?id=27151 + +define float @fadd_binary_fneg_nan(float %x) #0 { +; CHECK-LABEL: @fadd_binary_fneg_nan( +; CHECK-NEXT: [[T:%.*]] = call nnan float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[COULD_BE_NAN:%.*]] = call ninf float @llvm.experimental.constrained.fadd.f32(float [[T]], float [[X]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret float [[COULD_BE_NAN]] +; + %t = call nnan float @llvm.experimental.constrained.fsub.f32(float -0.0, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %could_be_nan = call ninf float @llvm.experimental.constrained.fadd.f32(float %t, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret float %could_be_nan +} + +define float @fadd_unary_fneg_nan(float %x) #0 { +; CHECK-LABEL: @fadd_unary_fneg_nan( +; CHECK-NEXT: [[T:%.*]] = fneg nnan float [[X:%.*]] +; CHECK-NEXT: [[COULD_BE_NAN:%.*]] = call ninf float @llvm.experimental.constrained.fadd.f32(float [[T]], float [[X]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret float [[COULD_BE_NAN]] +; + %t = fneg nnan float %x + %could_be_nan = call ninf float @llvm.experimental.constrained.fadd.f32(float %t, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret float %could_be_nan +} + +define float @fadd_binary_fneg_nan_commute(float %x) #0 { +; CHECK-LABEL: @fadd_binary_fneg_nan_commute( +; CHECK-NEXT: [[T:%.*]] = call nnan ninf float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[COULD_BE_NAN:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[X]], float [[T]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret float [[COULD_BE_NAN]] +; + %t = call nnan ninf float @llvm.experimental.constrained.fsub.f32(float -0.0, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %could_be_nan = call float @llvm.experimental.constrained.fadd.f32(float %x, float %t, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret float %could_be_nan +} + +define float @fadd_unary_fneg_nan_commute(float %x) #0 { +; CHECK-LABEL: @fadd_unary_fneg_nan_commute( +; CHECK-NEXT: [[T:%.*]] = fneg nnan ninf float [[X:%.*]] +; CHECK-NEXT: [[COULD_BE_NAN:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[X]], float [[T]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret float [[COULD_BE_NAN]] +; + %t = fneg nnan ninf float %x + %could_be_nan = call float @llvm.experimental.constrained.fadd.f32(float %x, float %t, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret float %could_be_nan +} + +; X + (0.0 - X) --> 0.0 (with nnan on the fadd) + +define float @fadd_fsub_nnan_ninf(float %x) #0 { +; CHECK-LABEL: @fadd_fsub_nnan_ninf( +; CHECK-NEXT: [[SUB:%.*]] = call nnan ninf float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[ZERO:%.*]] = call nnan ninf float @llvm.experimental.constrained.fadd.f32(float [[X]], float [[SUB]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret float [[ZERO]] +; + %sub = call nnan ninf float @llvm.experimental.constrained.fsub.f32(float 0.0, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %zero = call nnan ninf float @llvm.experimental.constrained.fadd.f32(float %x, float %sub, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret float %zero +} + +; (0.0 - X) + X --> 0.0 (with nnan on the fadd) + +define <2 x float> @fadd_fsub_nnan_ninf_commute_vec(<2 x float> %x) #0 { +; CHECK-LABEL: @fadd_fsub_nnan_ninf_commute_vec( +; CHECK-NEXT: [[SUB:%.*]] = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> zeroinitializer, <2 x float> [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[ZERO:%.*]] = call nnan ninf <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float> [[SUB]], <2 x float> [[X]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret <2 x float> [[ZERO]] +; + %sub = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> zeroinitializer, <2 x float> %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %zero = call nnan ninf <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float> %sub, <2 x float> %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret <2 x float> %zero +} + +; 'ninf' is not required because 'nnan' allows us to assume +; that X is not INF or -INF (adding opposite INFs would be NaN). + +define float @fadd_fsub_nnan(float %x) #0 { +; CHECK-LABEL: @fadd_fsub_nnan( +; CHECK-NEXT: [[SUB:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[ZERO:%.*]] = call nnan float @llvm.experimental.constrained.fadd.f32(float [[SUB]], float [[X]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret float [[ZERO]] +; + %sub = call float @llvm.experimental.constrained.fsub.f32(float 0.0, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %zero = call nnan float @llvm.experimental.constrained.fadd.f32(float %sub, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret float %zero +} + +; fsub nnan x, x ==> 0.0 +define float @fsub_x_x(float %a) #0 { +; X - X ==> 0 +; CHECK-LABEL: @fsub_x_x( +; CHECK-NEXT: [[NO_ZERO1:%.*]] = call ninf float @llvm.experimental.constrained.fsub.f32(float [[A:%.*]], float [[A]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[NO_ZERO2:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[A]], float [[A]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[NO_ZERO:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[NO_ZERO1]], float [[NO_ZERO2]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret float [[NO_ZERO]] +; + %zero1 = call nnan float @llvm.experimental.constrained.fsub.f32(float %a, float %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + +; Dont fold + %no_zero1 = call ninf float @llvm.experimental.constrained.fsub.f32(float %a, float %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %no_zero2 = call float @llvm.experimental.constrained.fsub.f32(float %a, float %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %no_zero = call float @llvm.experimental.constrained.fadd.f32(float %no_zero1, float %no_zero2, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + +; Should get folded + %ret = call nsz float @llvm.experimental.constrained.fadd.f32(float %no_zero, float %zero1, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + + ret float %ret +} + +; fsub nsz 0.0, (fsub 0.0, X) ==> X +define float @fsub_0_0_x(float %a) #0 { +; CHECK-LABEL: @fsub_0_0_x( +; CHECK-NEXT: [[T1:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[RET:%.*]] = call nsz float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float [[T1]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret float [[RET]] +; + %t1 = call float @llvm.experimental.constrained.fsub.f32(float 0.0, float %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %ret = call nsz float @llvm.experimental.constrained.fsub.f32(float 0.0, float %t1, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret float %ret +} + +; fsub nsz 0.0, (fneg X) ==> X +define float @fneg_x(float %a) #0 { +; CHECK-LABEL: @fneg_x( +; CHECK-NEXT: ret float [[A:%.*]] +; + %t1 = fneg float %a + %ret = call nsz float @llvm.experimental.constrained.fsub.f32(float 0.0, float %t1, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret float %ret +} + +define <2 x float> @fsub_0_0_x_vec_undef1(<2 x float> %a) #0 { +; CHECK-LABEL: @fsub_0_0_x_vec_undef1( +; CHECK-NEXT: [[T1:%.*]] = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> , <2 x float> [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[RET:%.*]] = call nsz <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> zeroinitializer, <2 x float> [[T1]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret <2 x float> [[RET]] +; + %t1 = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> , <2 x float> %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %ret = call nsz <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> zeroinitializer, <2 x float> %t1, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret <2 x float> %ret +} + +define <2 x float> @fneg_x_vec_undef1(<2 x float> %a) #0 { +; CHECK-LABEL: @fneg_x_vec_undef1( +; CHECK-NEXT: ret <2 x float> [[A:%.*]] +; + %t1 = fneg <2 x float> %a + %ret = call nsz <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> , <2 x float> %t1, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret <2 x float> %ret +} + +define <2 x float> @fsub_0_0_x_vec_undef2(<2 x float> %a) #0 { +; CHECK-LABEL: @fsub_0_0_x_vec_undef2( +; CHECK-NEXT: [[T1:%.*]] = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> zeroinitializer, <2 x float> [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[RET:%.*]] = call nsz <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> , <2 x float> [[T1]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret <2 x float> [[RET]] +; + %t1 = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> zeroinitializer, <2 x float> %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %ret = call nsz <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> , <2 x float> %t1, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret <2 x float> %ret +} + +; fadd nsz X, 0 ==> X + +define <2 x float> @fadd_zero_nsz_vec(<2 x float> %x) #0 { +; CHECK-LABEL: @fadd_zero_nsz_vec( +; CHECK-NEXT: ret <2 x float> [[X:%.*]] +; + %r = call nsz <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float> %x, <2 x float> zeroinitializer, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret <2 x float> %r +} + +define <2 x float> @fadd_zero_nsz_vec_undef(<2 x float> %x) #0 { +; CHECK-LABEL: @fadd_zero_nsz_vec_undef( +; CHECK-NEXT: ret <2 x float> [[X:%.*]] +; + %r = call nsz <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float> %x, <2 x float> , metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret <2 x float> %r +} + +define float @nofold_fadd_x_0(float %a) #0 { +; Dont fold +; CHECK-LABEL: @nofold_fadd_x_0( +; CHECK-NEXT: [[NO_ZERO1:%.*]] = call ninf float @llvm.experimental.constrained.fadd.f32(float [[A:%.*]], float 0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[NO_ZERO2:%.*]] = call nnan float @llvm.experimental.constrained.fadd.f32(float [[A]], float 0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[NO_ZERO:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[NO_ZERO1]], float [[NO_ZERO2]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret float [[NO_ZERO]] +; + %no_zero1 = call ninf float @llvm.experimental.constrained.fadd.f32(float %a, float 0.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %no_zero2 = call nnan float @llvm.experimental.constrained.fadd.f32(float %a, float 0.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %no_zero = call float @llvm.experimental.constrained.fadd.f32(float %no_zero1, float %no_zero2, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret float %no_zero +} + +define float @fold_fadd_nsz_x_0(float %a) #0 { +; CHECK-LABEL: @fold_fadd_nsz_x_0( +; CHECK-NEXT: ret float [[A:%.*]] +; + %add = call nsz float @llvm.experimental.constrained.fadd.f32(float %a, float 0.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret float %add +} + +; 'nsz' does not guarantee that -0.0 does not occur, so this does not simplify. + +define float @fold_fadd_cannot_be_neg0_nsz_src_x_0(float %a, float %b) #0 { +; CHECK-LABEL: @fold_fadd_cannot_be_neg0_nsz_src_x_0( +; CHECK-NEXT: [[NSZ:%.*]] = call nsz float @llvm.experimental.constrained.fmul.f32(float [[A:%.*]], float [[B:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[ADD:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[NSZ]], float 0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret float [[ADD]] +; + %nsz = call nsz float @llvm.experimental.constrained.fmul.f32(float %a, float %b, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %add = call float @llvm.experimental.constrained.fadd.f32(float %nsz, float 0.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret float %add +} + +define float @fold_fadd_cannot_be_neg0_fabs_src_x_0(float %a) #0 { +; CHECK-LABEL: @fold_fadd_cannot_be_neg0_fabs_src_x_0( +; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[A:%.*]]) +; CHECK-NEXT: ret float [[FABS]] +; + %fabs = call float @llvm.fabs.f32(float %a) + %add = call float @llvm.experimental.constrained.fadd.f32(float %fabs, float 0.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret float %add +} + +; 'nsz' does not guarantee that -0.0 does not occur, so this does not simplify. + +define float @fold_fadd_cannot_be_neg0_sqrt_nsz_src_x_0(float %a, float %b) #0 { +; CHECK-LABEL: @fold_fadd_cannot_be_neg0_sqrt_nsz_src_x_0( +; CHECK-NEXT: [[NSZ:%.*]] = call nsz float @llvm.experimental.constrained.fmul.f32(float [[A:%.*]], float [[B:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[SQRT:%.*]] = call float @llvm.experimental.constrained.sqrt.f32(float [[NSZ]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[ADD:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[SQRT]], float 0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret float [[ADD]] +; + %nsz = call nsz float @llvm.experimental.constrained.fmul.f32(float %a, float %b, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %sqrt = call float @llvm.experimental.constrained.sqrt.f32(float %nsz, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %add = call float @llvm.experimental.constrained.fadd.f32(float %sqrt, float 0.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret float %add +} + +; 'nsz' does not guarantee that -0.0 does not occur, so this does not simplify. + +define float @fold_fadd_cannot_be_neg0_canonicalize_nsz_src_x_0(float %a, float %b) #0 { +; CHECK-LABEL: @fold_fadd_cannot_be_neg0_canonicalize_nsz_src_x_0( +; CHECK-NEXT: [[NSZ:%.*]] = call nsz float @llvm.experimental.constrained.fmul.f32(float [[A:%.*]], float [[B:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[CANON:%.*]] = call float @llvm.canonicalize.f32(float [[NSZ]]) +; CHECK-NEXT: [[ADD:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[CANON]], float 0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret float [[ADD]] +; + %nsz = call nsz float @llvm.experimental.constrained.fmul.f32(float %a, float %b, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %canon = call float @llvm.canonicalize.f32(float %nsz) + %add = call float @llvm.experimental.constrained.fadd.f32(float %canon, float 0.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret float %add +} + +; fdiv nsz nnan 0, X ==> 0 +; 0 / X -> 0 + +define double @fdiv_zero_by_x(double %x) #0 { +; CHECK-LABEL: @fdiv_zero_by_x( +; CHECK-NEXT: ret double 0.000000e+00 +; + %r = call nnan nsz double @llvm.experimental.constrained.fdiv.f64(double 0.0, double %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret double %r +} + +define <2 x double> @fdiv_zero_by_x_vec_undef(<2 x double> %x) #0 { +; CHECK-LABEL: @fdiv_zero_by_x_vec_undef( +; CHECK-NEXT: ret <2 x double> zeroinitializer +; + %r = call nnan nsz <2 x double> @llvm.experimental.constrained.fdiv.v2f64(<2 x double> , <2 x double> %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret <2 x double> %r +} + +; 0 % X -> 0 +; nsz is not necessary - frem result always has the sign of the dividend + +define double @frem_zero_by_x(double %x) #0 { +; CHECK-LABEL: @frem_zero_by_x( +; CHECK-NEXT: ret double 0.000000e+00 +; + %r = call nnan double @llvm.experimental.constrained.frem.f64(double 0.0, double %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret double %r +} + +define <2 x double> @frem_poszero_by_x_vec_undef(<2 x double> %x) #0 { +; CHECK-LABEL: @frem_poszero_by_x_vec_undef( +; CHECK-NEXT: ret <2 x double> zeroinitializer +; + %r = call nnan <2 x double> @llvm.experimental.constrained.frem.v2f64(<2 x double> , <2 x double> %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret <2 x double> %r +} + +; -0 % X -> -0 +; nsz is not necessary - frem result always has the sign of the dividend + +define double @frem_negzero_by_x(double %x) #0 { +; CHECK-LABEL: @frem_negzero_by_x( +; CHECK-NEXT: ret double -0.000000e+00 +; + %r = call nnan double @llvm.experimental.constrained.frem.f64(double -0.0, double %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret double %r +} + +define <2 x double> @frem_negzero_by_x_vec_undef(<2 x double> %x) #0 { +; CHECK-LABEL: @frem_negzero_by_x_vec_undef( +; CHECK-NEXT: ret <2 x double> +; + %r = call nnan <2 x double> @llvm.experimental.constrained.frem.v2f64(<2 x double> , <2 x double> %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret <2 x double> %r +} + +define float @fdiv_self(float %f) #0 { +; CHECK-LABEL: @fdiv_self( +; CHECK-NEXT: ret float 1.000000e+00 +; + %div = call nnan float @llvm.experimental.constrained.fdiv.f32(float %f, float %f, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret float %div +} + +define float @fdiv_self_invalid(float %f) #0 { +; CHECK-LABEL: @fdiv_self_invalid( +; CHECK-NEXT: [[DIV:%.*]] = call float @llvm.experimental.constrained.fdiv.f32(float [[F:%.*]], float [[F]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret float [[DIV]] +; + %div = call float @llvm.experimental.constrained.fdiv.f32(float %f, float %f, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret float %div +} + +define float @fdiv_neg1(float %f) #0 { +; CHECK-LABEL: @fdiv_neg1( +; CHECK-NEXT: [[NEG:%.*]] = call fast float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[F:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[DIV:%.*]] = call nnan float @llvm.experimental.constrained.fdiv.f32(float [[NEG]], float [[F]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret float [[DIV]] +; + %neg = call fast float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float %f, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %div = call nnan float @llvm.experimental.constrained.fdiv.f32(float %neg, float %f, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret float %div +} + +define float @fdiv_neg2(float %f) #0 { +; CHECK-LABEL: @fdiv_neg2( +; CHECK-NEXT: [[NEG:%.*]] = call fast float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float [[F:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[DIV:%.*]] = call nnan float @llvm.experimental.constrained.fdiv.f32(float [[NEG]], float [[F]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret float [[DIV]] +; + %neg = call fast float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float %f, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %div = call nnan float @llvm.experimental.constrained.fdiv.f32(float %neg, float %f, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret float %div +} + +define float @fdiv_neg_invalid(float %f) #0 { +; CHECK-LABEL: @fdiv_neg_invalid( +; CHECK-NEXT: [[NEG:%.*]] = call fast float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[F:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[DIV:%.*]] = call float @llvm.experimental.constrained.fdiv.f32(float [[NEG]], float [[F]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret float [[DIV]] +; + %neg = call fast float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float %f, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %div = call float @llvm.experimental.constrained.fdiv.f32(float %neg, float %f, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret float %div +} + +define float @fdiv_neg_swapped1(float %f) #0 { +; CHECK-LABEL: @fdiv_neg_swapped1( +; CHECK-NEXT: [[NEG:%.*]] = call fast float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[F:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[DIV:%.*]] = call nnan float @llvm.experimental.constrained.fdiv.f32(float [[F]], float [[NEG]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret float [[DIV]] +; + %neg = call fast float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float %f, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %div = call nnan float @llvm.experimental.constrained.fdiv.f32(float %f, float %neg, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret float %div +} + +define float @fdiv_neg_swapped2(float %f) #0 { +; CHECK-LABEL: @fdiv_neg_swapped2( +; CHECK-NEXT: [[NEG:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float [[F:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[DIV:%.*]] = call nnan float @llvm.experimental.constrained.fdiv.f32(float [[F]], float [[NEG]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret float [[DIV]] +; + %neg = call float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float %f, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %div = call nnan float @llvm.experimental.constrained.fdiv.f32(float %f, float %neg, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret float %div +} + +define <2 x float> @fdiv_neg_vec_undef_elt(<2 x float> %f) #0 { +; CHECK-LABEL: @fdiv_neg_vec_undef_elt( +; CHECK-NEXT: [[NEG:%.*]] = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> , <2 x float> [[F:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[DIV:%.*]] = call nnan <2 x float> @llvm.experimental.constrained.fdiv.v2f32(<2 x float> [[F]], <2 x float> [[NEG]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret <2 x float> [[DIV]] +; + %neg = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> , <2 x float> %f, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %div = call nnan <2 x float> @llvm.experimental.constrained.fdiv.v2f32(<2 x float> %f, <2 x float> %neg, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret <2 x float> %div +} + +; PR21126: http://llvm.org/bugs/show_bug.cgi?id=21126 +; With loose math, sqrt(X) * sqrt(X) is just X. + +declare double @llvm.sqrt.f64(double) + +define double @sqrt_squared(double %f) #0 { +; CHECK-LABEL: @sqrt_squared( +; CHECK-NEXT: [[SQRT:%.*]] = call double @llvm.experimental.constrained.sqrt.f64(double [[F:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") +; CHECK-NEXT: [[MUL:%.*]] = call reassoc nnan nsz double @llvm.experimental.constrained.fmul.f64(double [[SQRT]], double [[SQRT]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret double [[MUL]] +; + %sqrt = call double @llvm.experimental.constrained.sqrt.f64(double %f, metadata !"round.tonearest", metadata !"fpexcept.ignore") + %mul = call reassoc nnan nsz double @llvm.experimental.constrained.fmul.f64(double %sqrt, double %sqrt, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret double %mul +} + +; Negative tests for the above transform: we need all 3 of those flags. + +define double @sqrt_squared_not_fast_enough1(double %f) #0 { +; CHECK-LABEL: @sqrt_squared_not_fast_enough1( +; CHECK-NEXT: [[SQRT:%.*]] = call double @llvm.experimental.constrained.sqrt.f64(double [[F:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") +; CHECK-NEXT: [[MUL:%.*]] = call nnan nsz double @llvm.experimental.constrained.fmul.f64(double [[SQRT]], double [[SQRT]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret double [[MUL]] +; + %sqrt = call double @llvm.experimental.constrained.sqrt.f64(double %f, metadata !"round.tonearest", metadata !"fpexcept.ignore") + %mul = call nnan nsz double @llvm.experimental.constrained.fmul.f64(double %sqrt, double %sqrt, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret double %mul +} + +define double @sqrt_squared_not_fast_enough2(double %f) #0 { +; CHECK-LABEL: @sqrt_squared_not_fast_enough2( +; CHECK-NEXT: [[SQRT:%.*]] = call double @llvm.experimental.constrained.sqrt.f64(double [[F:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") +; CHECK-NEXT: [[MUL:%.*]] = call reassoc nnan double @llvm.experimental.constrained.fmul.f64(double [[SQRT]], double [[SQRT]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret double [[MUL]] +; + %sqrt = call double @llvm.experimental.constrained.sqrt.f64(double %f, metadata !"round.tonearest", metadata !"fpexcept.ignore") + %mul = call reassoc nnan double @llvm.experimental.constrained.fmul.f64(double %sqrt, double %sqrt, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret double %mul +} + +define double @sqrt_squared_not_fast_enough3(double %f) #0 { +; CHECK-LABEL: @sqrt_squared_not_fast_enough3( +; CHECK-NEXT: [[SQRT:%.*]] = call double @llvm.experimental.constrained.sqrt.f64(double [[F:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") +; CHECK-NEXT: [[MUL:%.*]] = call reassoc nsz double @llvm.experimental.constrained.fmul.f64(double [[SQRT]], double [[SQRT]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret double [[MUL]] +; + %sqrt = call double @llvm.experimental.constrained.sqrt.f64(double %f, metadata !"round.tonearest", metadata !"fpexcept.ignore") + %mul = call reassoc nsz double @llvm.experimental.constrained.fmul.f64(double %sqrt, double %sqrt, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret double %mul +} + +declare float @llvm.fabs.f32(float) +declare float @llvm.experimental.constrained.sqrt.f32(float, metadata, metadata) #0 +declare double @llvm.experimental.constrained.sqrt.f64(double, metadata, metadata) #0 +declare float @llvm.canonicalize.f32(float) + +declare float @llvm.experimental.constrained.fadd.f32(float, float, metadata, metadata) #0 +declare <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float>, <2 x float>, metadata, metadata) #0 + +declare float @llvm.experimental.constrained.fsub.f32(float, float, metadata, metadata) #0 +declare <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float>, <2 x float>, metadata, metadata) #0 + +declare float @llvm.experimental.constrained.fmul.f32(float, float, metadata, metadata) #0 +declare double @llvm.experimental.constrained.fmul.f64(double, double, metadata, metadata) #0 +declare <2 x float> @llvm.experimental.constrained.fmul.v2f32(<2 x float>, <2 x float>, metadata, metadata) #0 + +declare float @llvm.experimental.constrained.fdiv.f32(float, float, metadata, metadata) #0 +declare double @llvm.experimental.constrained.fdiv.f64(double, double, metadata, metadata) #0 +declare <2 x float> @llvm.experimental.constrained.fdiv.v2f32(<2 x float>, <2 x float>, metadata, metadata) #0 +declare <2 x double> @llvm.experimental.constrained.fdiv.v2f64(<2 x double>, <2 x double>, metadata, metadata) #0 + +declare double @llvm.experimental.constrained.frem.f64(double, double, metadata, metadata) #0 +declare <2 x double> @llvm.experimental.constrained.frem.v2f64(<2 x double>, <2 x double>, metadata, metadata) #0 + +attributes #0 = { strictfp } + diff --git a/llvm/test/Transforms/InstSimplify/fdiv-strictfp.ll b/llvm/test/Transforms/InstSimplify/fdiv-strictfp.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/InstSimplify/fdiv-strictfp.ll @@ -0,0 +1,87 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -instsimplify -S | FileCheck %s + +define float @fdiv_constant_fold() #0 { +; CHECK-LABEL: @fdiv_constant_fold( +; CHECK-NEXT: ret float 1.500000e+00 +; + %f = call float @llvm.experimental.constrained.fdiv.f32(float 3.0, float 2.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + + ret float %f +} + +define float @fdiv_constant_fold_strict() #0 { +; CHECK-LABEL: @fdiv_constant_fold_strict( +; CHECK-NEXT: [[F:%.*]] = call float @llvm.experimental.constrained.fdiv.f32(float 3.000000e+00, float 2.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR0:[0-9]+]] +; CHECK-NEXT: ret float [[F]] +; + %f = call float @llvm.experimental.constrained.fdiv.f32(float 3.0, float 2.0, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 + + ret float %f +} + +define float @frem_constant_fold() #0 { +; CHECK-LABEL: @frem_constant_fold( +; CHECK-NEXT: ret float 1.500000e+00 +; + %f = call float @llvm.experimental.constrained.fdiv.f32(float 3.0, float 2.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret float %f +} + +define float @frem_constant_fold_strict() #0 { +; CHECK-LABEL: @frem_constant_fold_strict( +; CHECK-NEXT: [[F:%.*]] = call float @llvm.experimental.constrained.fdiv.f32(float 3.000000e+00, float 2.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR0]] +; CHECK-NEXT: ret float [[F]] +; + %f = call float @llvm.experimental.constrained.fdiv.f32(float 3.0, float 2.0, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 + ret float %f +} + +define double @fmul_fdiv_common_operand(double %x, double %y) #0 { +; CHECK-LABEL: @fmul_fdiv_common_operand( +; CHECK-NEXT: [[M:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[X:%.*]], double [[Y:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[D:%.*]] = call reassoc nnan double @llvm.experimental.constrained.fdiv.f64(double [[M]], double [[Y]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret double [[D]] +; + %m = call double @llvm.experimental.constrained.fmul.f64(double %x, double %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %d = call reassoc nnan double @llvm.experimental.constrained.fdiv.f64(double %m, double %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret double %d +} + +; Negative test - the fdiv must be reassociative and not allow NaNs. + +define double @fmul_fdiv_common_operand_too_strict(double %x, double %y) #0 { +; CHECK-LABEL: @fmul_fdiv_common_operand_too_strict( +; CHECK-NEXT: [[M:%.*]] = call fast double @llvm.experimental.constrained.fmul.f64(double [[X:%.*]], double [[Y:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[D:%.*]] = call reassoc double @llvm.experimental.constrained.fdiv.f64(double [[M]], double [[Y]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret double [[D]] +; + %m = call fast double @llvm.experimental.constrained.fmul.f64(double %x, double %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %d = call reassoc double @llvm.experimental.constrained.fdiv.f64(double %m, double %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret double %d +} + +; Commute the fmul operands. Use a vector type to verify that works too. + +define <2 x float> @fmul_fdiv_common_operand_commute_vec(<2 x float> %x, <2 x float> %y) #0 { +; CHECK-LABEL: @fmul_fdiv_common_operand_commute_vec( +; CHECK-NEXT: [[M:%.*]] = call <2 x float> @llvm.experimental.constrained.fmul.v2f32(<2 x float> [[Y:%.*]], <2 x float> [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[D:%.*]] = call fast <2 x float> @llvm.experimental.constrained.fdiv.v2f32(<2 x float> [[M]], <2 x float> [[Y]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret <2 x float> [[D]] +; + %m = call <2 x float> @llvm.experimental.constrained.fmul.v2f32(<2 x float> %y, <2 x float> %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %d = call fast <2 x float> @llvm.experimental.constrained.fdiv.v2f32(<2 x float> %m, <2 x float> %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret <2 x float> %d +} + +declare double @llvm.experimental.constrained.fmul.f64(double, double, metadata, metadata) #0 +declare <2 x float> @llvm.experimental.constrained.fmul.v2f32(<2 x float>, <2 x float>, metadata, metadata) #0 + +declare float @llvm.experimental.constrained.fdiv.f32(float, float, metadata, metadata) #0 +declare double @llvm.experimental.constrained.fdiv.f64(double, double, metadata, metadata) #0 +declare <2 x float> @llvm.experimental.constrained.fdiv.v2f32(<2 x float>, <2 x float>, metadata, metadata) #0 + +declare float @llvm.experimental.constrained.frem.f32(float, float, metadata, metadata) #0 + +attributes #0 = { strictfp } + diff --git a/llvm/test/Transforms/InstSimplify/floating-point-arithmetic-strictfp.ll b/llvm/test/Transforms/InstSimplify/floating-point-arithmetic-strictfp.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/InstSimplify/floating-point-arithmetic-strictfp.ll @@ -0,0 +1,538 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -instsimplify -S | FileCheck %s + +; fneg (fsub -0.0, X) ==> X +define float @fsub_-0_x(float %a) #0 { +; CHECK-LABEL: @fsub_-0_x( +; CHECK-NEXT: [[T1:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0:[0-9]+]] +; CHECK-NEXT: [[RET:%.*]] = fneg float [[T1]] +; CHECK-NEXT: ret float [[RET]] +; + %t1 = call float @llvm.experimental.constrained.fsub.f32(float -0.0, float %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %ret = fneg float %t1 + ret float %ret +} + +define <2 x float> @fsub_-0_x_vec(<2 x float> %a) #0 { +; CHECK-LABEL: @fsub_-0_x_vec( +; CHECK-NEXT: [[T1:%.*]] = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> , <2 x float> [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[RET:%.*]] = fneg <2 x float> [[T1]] +; CHECK-NEXT: ret <2 x float> [[RET]] +; + %t1 = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float>, <2 x float> %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %ret = fneg <2 x float> %t1 + ret <2 x float> %ret +} + +define <2 x float> @fsub_-0_x_vec_undef_elts(<2 x float> %a) #0 { +; CHECK-LABEL: @fsub_-0_x_vec_undef_elts( +; CHECK-NEXT: [[T1:%.*]] = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> , <2 x float> [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[RET:%.*]] = fneg <2 x float> [[T1]] +; CHECK-NEXT: ret <2 x float> [[RET]] +; + %t1 = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float>, <2 x float> %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %ret = fneg <2 x float> %t1 + ret <2 x float> %ret +} + +define <2 x float> @fsub_negzero_vec_undef_elts(<2 x float> %x) #0 { +; CHECK-LABEL: @fsub_negzero_vec_undef_elts( +; CHECK-NEXT: [[R:%.*]] = call nsz <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> , <2 x float> [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret <2 x float> [[R]] +; + %r = call nsz <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float>, <2 x float> %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret <2 x float> %r +} + +; fsub -0.0, (fsub -0.0, X) ==> X +define float @fsub_-0_-0_x(float %a) #0 { +; CHECK-LABEL: @fsub_-0_-0_x( +; CHECK-NEXT: [[T1:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[RET:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[T1]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret float [[RET]] +; + %t1 = call float @llvm.experimental.constrained.fsub.f32(float -0.0, float %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %ret = call float @llvm.experimental.constrained.fsub.f32(float -0.0, float %t1, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret float %ret +} + +; fsub -0.0, (fneg X) ==> X +define float @fneg_x(float %a) #0 { +; CHECK-LABEL: @fneg_x( +; CHECK-NEXT: ret float [[A:%.*]] +; + %t1 = fneg float %a + %ret = call float @llvm.experimental.constrained.fsub.f32(float -0.0, float %t1, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret float %ret +} + +define <2 x float> @fsub_-0_-0_x_vec(<2 x float> %a) #0 { +; CHECK-LABEL: @fsub_-0_-0_x_vec( +; CHECK-NEXT: [[T1:%.*]] = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> , <2 x float> [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[RET:%.*]] = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> , <2 x float> [[T1]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret <2 x float> [[RET]] +; + %t1 = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float>, <2 x float> %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %ret = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float>, <2 x float> %t1, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret <2 x float> %ret +} + +define <2 x float> @fneg_x_vec(<2 x float> %a) #0 { +; CHECK-LABEL: @fneg_x_vec( +; CHECK-NEXT: ret <2 x float> [[A:%.*]] +; + %t1 = fneg <2 x float> %a + %ret = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float>, <2 x float> %t1, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret <2 x float> %ret +} + +define <2 x float> @fsub_-0_-0_x_vec_undef_elts(<2 x float> %a) #0 { +; CHECK-LABEL: @fsub_-0_-0_x_vec_undef_elts( +; CHECK-NEXT: [[T1:%.*]] = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> , <2 x float> [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[RET:%.*]] = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> , <2 x float> [[T1]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret <2 x float> [[RET]] +; + %t1 = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float>, <2 x float> %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %ret = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float>, <2 x float> %t1, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret <2 x float> %ret +} + +define <2 x float> @fneg_x_vec_undef_elts(<2 x float> %a) #0 { +; CHECK-LABEL: @fneg_x_vec_undef_elts( +; CHECK-NEXT: ret <2 x float> [[A:%.*]] +; + %t1 = fneg <2 x float> %a + %ret = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float>, <2 x float> %t1, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret <2 x float> %ret +} + +; fsub -0.0, (fsub 0.0, X) != X +define float @fsub_-0_0_x(float %a) #0 { +; CHECK-LABEL: @fsub_-0_0_x( +; CHECK-NEXT: [[T1:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[RET:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[T1]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret float [[RET]] +; + %t1 = call float @llvm.experimental.constrained.fsub.f32(float 0.0, float %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %ret = call float @llvm.experimental.constrained.fsub.f32(float -0.0, float %t1, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret float %ret +} + +; fsub 0.0, (fsub -0.0, X) != X +define float @fsub_0_-0_x(float %a) #0 { +; CHECK-LABEL: @fsub_0_-0_x( +; CHECK-NEXT: [[T1:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[RET:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float [[T1]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret float [[RET]] +; + %t1 = call float @llvm.experimental.constrained.fsub.f32(float -0.0, float %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %ret = call float @llvm.experimental.constrained.fsub.f32(float 0.0, float %t1, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret float %ret +} + +; fsub X, 0 ==> X +define float @fsub_x_0(float %x) #0 { +; CHECK-LABEL: @fsub_x_0( +; CHECK-NEXT: ret float [[X:%.*]] +; + %r = call float @llvm.experimental.constrained.fsub.f32(float %x, float 0.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret float %r +} + +define <2 x float> @fsub_x_0_vec_undef(<2 x float> %x) #0 { +; CHECK-LABEL: @fsub_x_0_vec_undef( +; CHECK-NEXT: ret <2 x float> [[X:%.*]] +; + %r = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> %x, <2 x float>, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret <2 x float> %r +} + +; fadd X, -0 ==> X +define float @fadd_x_n0(float %a) #0 { +; CHECK-LABEL: @fadd_x_n0( +; CHECK-NEXT: ret float [[A:%.*]] +; + %ret = call float @llvm.experimental.constrained.fadd.f32(float %a, float -0.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret float %ret +} + +define <2 x float> @fadd_x_n0_vec_undef_elt(<2 x float> %a) #0 { +; CHECK-LABEL: @fadd_x_n0_vec_undef_elt( +; CHECK-NEXT: ret <2 x float> [[A:%.*]] +; + %ret = call <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float> %a, <2 x float> , metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret <2 x float> %ret +} + +; fadd X, 0 ==> X +define float @fadd_x_p0(float %a) #0 { +; CHECK-LABEL: @fadd_x_p0( +; CHECK-NEXT: [[RET:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[A:%.*]], float 0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret float [[RET]] +; + %ret = call float @llvm.experimental.constrained.fadd.f32(float %a, float 0.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret float %ret +} + +define <2 x float> @fadd_x_p0_vec_undef_elt(<2 x float> %a) #0 { +; CHECK-LABEL: @fadd_x_p0_vec_undef_elt( +; CHECK-NEXT: [[RET:%.*]] = call <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float> [[A:%.*]], <2 x float> , metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret <2 x float> [[RET]] +; + %ret = call <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float> %a, <2 x float> , metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret <2 x float> %ret +} + +; fmul X, 1.0 ==> X +define double @fmul_X_1(double %a) #0 { +; CHECK-LABEL: @fmul_X_1( +; CHECK-NEXT: ret double [[A:%.*]] +; + %b = call double @llvm.experimental.constrained.fmul.f64(double 1.0, double %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret double %b +} + +; Originally PR2642 +define <4 x float> @fmul_X_1_vec(<4 x float> %x) { +; CHECK-LABEL: @fmul_X_1_vec( +; CHECK-NEXT: ret <4 x float> [[X:%.*]] +; + %m = call <4 x float> @llvm.experimental.constrained.fmul.v4f32(<4 x float> %x, <4 x float> , metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret <4 x float> %m +} + +; fdiv X, 1.0 ==> X +define float @fdiv_x_1(float %a) #0 { +; CHECK-LABEL: @fdiv_x_1( +; CHECK-NEXT: ret float [[A:%.*]] +; + %ret = call float @llvm.experimental.constrained.fdiv.f32(float %a, float 1.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + + ret float %ret +} + + +; The fabs can't be eliminated because llvm.experimental.constrained.sqrt.f32 may return -0 or NaN with +; an arbitrary sign bit. +define float @fabs_sqrt(float %a) #0 { +; CHECK-LABEL: @fabs_sqrt( +; CHECK-NEXT: [[SQRT:%.*]] = call float @llvm.experimental.constrained.sqrt.f32(float [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SQRT]]) +; CHECK-NEXT: ret float [[FABS]] +; + %sqrt = call float @llvm.experimental.constrained.sqrt.f32(float %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %fabs = call float @llvm.fabs.f32(float %sqrt) + ret float %fabs +} + +; The fabs can't be eliminated because the nnan sqrt may still return -0. +define float @fabs_sqrt_nnan(float %a) #0 { +; CHECK-LABEL: @fabs_sqrt_nnan( +; CHECK-NEXT: [[SQRT:%.*]] = call nnan float @llvm.experimental.constrained.sqrt.f32(float [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SQRT]]) +; CHECK-NEXT: ret float [[FABS]] +; + %sqrt = call nnan float @llvm.experimental.constrained.sqrt.f32(float %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %fabs = call float @llvm.fabs.f32(float %sqrt) + ret float %fabs +} + +; The fabs can't be eliminated because the nsz sqrt may still return NaN. +define float @fabs_sqrt_nsz(float %a) #0 { +; CHECK-LABEL: @fabs_sqrt_nsz( +; CHECK-NEXT: [[SQRT:%.*]] = call nsz float @llvm.experimental.constrained.sqrt.f32(float [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SQRT]]) +; CHECK-NEXT: ret float [[FABS]] +; + %sqrt = call nsz float @llvm.experimental.constrained.sqrt.f32(float %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %fabs = call float @llvm.fabs.f32(float %sqrt) + ret float %fabs +} + +; The fabs can be eliminated because we're nsz and nnan. +define float @fabs_sqrt_nnan_nsz(float %a) #0 { +; CHECK-LABEL: @fabs_sqrt_nnan_nsz( +; CHECK-NEXT: [[SQRT:%.*]] = call nnan nsz float @llvm.experimental.constrained.sqrt.f32(float [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SQRT]]) +; CHECK-NEXT: ret float [[FABS]] +; + %sqrt = call nnan nsz float @llvm.experimental.constrained.sqrt.f32(float %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %fabs = call float @llvm.fabs.f32(float %sqrt) + ret float %fabs +} + +; The second fabs can be eliminated because the operand to sqrt cannot be -0. +define float @fabs_sqrt_nnan_fabs(float %a) #0 { +; CHECK-LABEL: @fabs_sqrt_nnan_fabs( +; CHECK-NEXT: [[B:%.*]] = call float @llvm.fabs.f32(float [[A:%.*]]) +; CHECK-NEXT: [[SQRT:%.*]] = call nnan float @llvm.experimental.constrained.sqrt.f32(float [[B]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SQRT]]) +; CHECK-NEXT: ret float [[FABS]] +; + %b = call float @llvm.fabs.f32(float %a) + %sqrt = call nnan float @llvm.experimental.constrained.sqrt.f32(float %b, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %fabs = call float @llvm.fabs.f32(float %sqrt) + ret float %fabs +} + +; Y - (Y - X) --> X + +define float @fsub_fsub_common_op(float %x, float %y) #0 { +; CHECK-LABEL: @fsub_fsub_common_op( +; CHECK-NEXT: [[S:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[Y:%.*]], float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[R:%.*]] = call reassoc nsz float @llvm.experimental.constrained.fsub.f32(float [[Y]], float [[S]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret float [[R]] +; + %s = call float @llvm.experimental.constrained.fsub.f32(float %y, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %r = call reassoc nsz float @llvm.experimental.constrained.fsub.f32(float %y, float %s, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret float %r +} + +define <2 x float> @fsub_fsub_common_op_vec(<2 x float> %x, <2 x float> %y) #0 { +; CHECK-LABEL: @fsub_fsub_common_op_vec( +; CHECK-NEXT: [[S:%.*]] = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> [[Y:%.*]], <2 x float> [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[R:%.*]] = call reassoc nsz <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> [[Y]], <2 x float> [[S]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret <2 x float> [[R]] +; + %s = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> %y, <2 x float> %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %r = call reassoc nsz <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> %y, <2 x float> %s, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret <2 x float> %r +} + +; Negative test - fsub is not commutative. +; Y - (X - Y) --> (Y - X) + Y (canonicalized) + +define float @fsub_fsub_wrong_common_op(float %x, float %y) #0 { +; CHECK-LABEL: @fsub_fsub_wrong_common_op( +; CHECK-NEXT: [[S:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[X:%.*]], float [[Y:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[R:%.*]] = call reassoc nsz float @llvm.experimental.constrained.fsub.f32(float [[Y]], float [[S]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret float [[R]] +; + %s = call float @llvm.experimental.constrained.fsub.f32(float %x, float %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %r = call reassoc nsz float @llvm.experimental.constrained.fsub.f32(float %y, float %s, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret float %r +} + +; Negative test - negated operand needed. +; (Y - X) - Y --> -X + +define float @fsub_fsub_common_op_wrong_commute(float %x, float %y) #0 { +; CHECK-LABEL: @fsub_fsub_common_op_wrong_commute( +; CHECK-NEXT: [[S:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[Y:%.*]], float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[R:%.*]] = call reassoc nsz float @llvm.experimental.constrained.fsub.f32(float [[S]], float [[Y]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret float [[R]] +; + %s = call float @llvm.experimental.constrained.fsub.f32(float %y, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %r = call reassoc nsz float @llvm.experimental.constrained.fsub.f32(float %s, float %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret float %r +} + +; Negative test - fsub is not commutative. +; (X - Y) - Y --> ? + +define float @fsub_fsub_wrong_common_op_wrong_commute(float %x, float %y) #0 { +; CHECK-LABEL: @fsub_fsub_wrong_common_op_wrong_commute( +; CHECK-NEXT: [[S:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[X:%.*]], float [[Y:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[R:%.*]] = call reassoc nsz float @llvm.experimental.constrained.fsub.f32(float [[S]], float [[Y]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret float [[R]] +; + %s = call float @llvm.experimental.constrained.fsub.f32(float %x, float %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %r = call reassoc nsz float @llvm.experimental.constrained.fsub.f32(float %s, float %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret float %r +} + +; (Y + X) - Y --> X + +define float @fadd_fsub_common_op(float %x, float %y) #0 { +; CHECK-LABEL: @fadd_fsub_common_op( +; CHECK-NEXT: [[A:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[Y:%.*]], float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[R:%.*]] = call reassoc nsz float @llvm.experimental.constrained.fsub.f32(float [[A]], float [[Y]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret float [[R]] +; + %a = call float @llvm.experimental.constrained.fadd.f32(float %y, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %r = call reassoc nsz float @llvm.experimental.constrained.fsub.f32(float %a, float %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret float %r +} + +; (X + Y) - Y --> X + +define <2 x float> @fadd_fsub_common_op_commute_vec(<2 x float> %x, <2 x float> %y) #0 { +; CHECK-LABEL: @fadd_fsub_common_op_commute_vec( +; CHECK-NEXT: [[A:%.*]] = call <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float> [[X:%.*]], <2 x float> [[Y:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[R:%.*]] = call reassoc nsz <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> [[A]], <2 x float> [[Y]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret <2 x float> [[R]] +; + %a = call <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float> %x, <2 x float> %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %r = call reassoc nsz <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> %a, <2 x float> %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret <2 x float> %r +} + +; Negative test - negated operand needed. +; Y - (Y + X) --> -X + +define float @fadd_fsub_common_op_wrong_commute(float %x, float %y) #0 { +; CHECK-LABEL: @fadd_fsub_common_op_wrong_commute( +; CHECK-NEXT: [[A:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[Y:%.*]], float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[R:%.*]] = call reassoc nsz float @llvm.experimental.constrained.fsub.f32(float [[Y]], float [[A]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret float [[R]] +; + %a = call float @llvm.experimental.constrained.fadd.f32(float %y, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %r = call reassoc nsz float @llvm.experimental.constrained.fsub.f32(float %y, float %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret float %r +} + +; Negative test - negated operand needed. +; Y - (X + Y) --> -X + +define float @fadd_fsub_common_op_wrong_commute_commute(float %x, float %y) #0 { +; CHECK-LABEL: @fadd_fsub_common_op_wrong_commute_commute( +; CHECK-NEXT: [[A:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[X:%.*]], float [[Y:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[R:%.*]] = call reassoc nsz float @llvm.experimental.constrained.fsub.f32(float [[Y]], float [[A]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret float [[R]] +; + %a = call float @llvm.experimental.constrained.fadd.f32(float %x, float %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %r = call reassoc nsz float @llvm.experimental.constrained.fsub.f32(float %y, float %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret float %r +} + +; Y + (X - Y) --> X + +define <2 x float> @fsub_fadd_common_op_vec(<2 x float> %x, <2 x float> %y) #0 { +; CHECK-LABEL: @fsub_fadd_common_op_vec( +; CHECK-NEXT: [[S:%.*]] = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> [[X:%.*]], <2 x float> [[Y:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[R:%.*]] = call reassoc nsz <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float> [[Y]], <2 x float> [[S]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret <2 x float> [[R]] +; + %s = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> %x, <2 x float> %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %r = call reassoc nsz <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float> %y, <2 x float> %s, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret <2 x float> %r +} + +; (X - Y) + Y --> X + +define float @fsub_fadd_common_op_commute(float %x, float %y) #0 { +; CHECK-LABEL: @fsub_fadd_common_op_commute( +; CHECK-NEXT: [[S:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[X:%.*]], float [[Y:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[R:%.*]] = call reassoc nsz float @llvm.experimental.constrained.fadd.f32(float [[S]], float [[Y]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret float [[R]] +; + %s = call float @llvm.experimental.constrained.fsub.f32(float %x, float %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %r = call reassoc nsz float @llvm.experimental.constrained.fadd.f32(float %s, float %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret float %r +} + +; Negative test. +; Y + (Y - X) --> ? + +define float @fsub_fadd_common_op_wrong_commute(float %x, float %y) #0 { +; CHECK-LABEL: @fsub_fadd_common_op_wrong_commute( +; CHECK-NEXT: [[S:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[Y:%.*]], float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[R:%.*]] = call reassoc nsz float @llvm.experimental.constrained.fadd.f32(float [[Y]], float [[S]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret float [[R]] +; + %s = call float @llvm.experimental.constrained.fsub.f32(float %y, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %r = call reassoc nsz float @llvm.experimental.constrained.fadd.f32(float %y, float %s, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret float %r +} + +; Negative test. +; (Y - X) + Y --> ? + +define float @fsub_fadd_common_op_wrong_commute_commute(float %x, float %y) #0 { +; CHECK-LABEL: @fsub_fadd_common_op_wrong_commute_commute( +; CHECK-NEXT: [[S:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[Y:%.*]], float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[R:%.*]] = call reassoc nsz float @llvm.experimental.constrained.fadd.f32(float [[S]], float [[Y]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: ret float [[R]] +; + %s = call float @llvm.experimental.constrained.fsub.f32(float %y, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %r = call reassoc nsz float @llvm.experimental.constrained.fadd.f32(float %s, float %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + ret float %r +} + +; Originally PR46627 - https://bugs.llvm.org/show_bug.cgi?id=46627 + +define float @maxnum_with_poszero_op(float %a) #0 { +; CHECK-LABEL: @maxnum_with_poszero_op( +; CHECK-NEXT: [[MAX:%.*]] = call float @llvm.experimental.constrained.maxnum.f32(float [[A:%.*]], float 0.000000e+00, metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[MAX]]) +; CHECK-NEXT: ret float [[FABS]] +; + %max = call float @llvm.experimental.constrained.maxnum.f32(float %a, float 0.0, metadata !"fpexcept.ignore") #0 + %fabs = call float @llvm.fabs.f32(float %max) + ret float %fabs +} + +define float @maxnum_with_poszero_op_commute(float %a) #0 { +; CHECK-LABEL: @maxnum_with_poszero_op_commute( +; CHECK-NEXT: [[SQRT:%.*]] = call float @llvm.experimental.constrained.sqrt.f32(float [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[MAX:%.*]] = call float @llvm.experimental.constrained.maxnum.f32(float 0.000000e+00, float [[SQRT]], metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[MAX]]) +; CHECK-NEXT: ret float [[FABS]] +; + %sqrt = call float @llvm.experimental.constrained.sqrt.f32(float %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %max = call float @llvm.experimental.constrained.maxnum.f32(float 0.0, float %sqrt, metadata !"fpexcept.ignore") #0 + %fabs = call float @llvm.fabs.f32(float %max) + ret float %fabs +} + +define float @maxnum_with_negzero_op(float %a) #0 { +; CHECK-LABEL: @maxnum_with_negzero_op( +; CHECK-NEXT: [[NNAN:%.*]] = call nnan float @llvm.experimental.constrained.sqrt.f32(float [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[FABSA:%.*]] = call float @llvm.fabs.f32(float [[NNAN]]) +; CHECK-NEXT: [[MAX:%.*]] = call float @llvm.experimental.constrained.maxnum.f32(float -0.000000e+00, float [[FABSA]], metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[MAX]]) +; CHECK-NEXT: ret float [[FABS]] +; + %nnan = call nnan float @llvm.experimental.constrained.sqrt.f32(float %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %fabsa = call float @llvm.fabs.f32(float %nnan) + %max = call float @llvm.experimental.constrained.maxnum.f32(float -0.0, float %fabsa, metadata !"fpexcept.ignore") #0 + %fabs = call float @llvm.fabs.f32(float %max) + ret float %fabs +} + +define float @maxnum_with_negzero_op_commute(float %a) #0 { +; CHECK-LABEL: @maxnum_with_negzero_op_commute( +; CHECK-NEXT: [[NNAN:%.*]] = call nnan float @llvm.experimental.constrained.sqrt.f32(float [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[FABSA:%.*]] = call float @llvm.fabs.f32(float [[NNAN]]) +; CHECK-NEXT: [[MAX:%.*]] = call float @llvm.experimental.constrained.maxnum.f32(float [[FABSA]], float -0.000000e+00, metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[MAX]]) +; CHECK-NEXT: ret float [[FABS]] +; + %nnan = call nnan float @llvm.experimental.constrained.sqrt.f32(float %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 + %fabsa = call float @llvm.fabs.f32(float %nnan) + %max = call float @llvm.experimental.constrained.maxnum.f32(float %fabsa, float -0.0, metadata !"fpexcept.ignore") #0 + %fabs = call float @llvm.fabs.f32(float %max) + ret float %fabs +} + +; If an operand is strictly greater than 0.0, we know the sign of the result of maxnum. + +define float @maxnum_with_pos_one_op(float %a) #0 { +; CHECK-LABEL: @maxnum_with_pos_one_op( +; CHECK-NEXT: [[MAX:%.*]] = call float @llvm.experimental.constrained.maxnum.f32(float [[A:%.*]], float 1.000000e+00, metadata !"fpexcept.ignore") #[[ATTR0]] +; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[MAX]]) +; CHECK-NEXT: ret float [[FABS]] +; + %max = call float @llvm.experimental.constrained.maxnum.f32(float %a, float 1.0, metadata !"fpexcept.ignore") #0 + %fabs = call float @llvm.fabs.f32(float %max) + ret float %fabs +} + +declare float @llvm.fabs.f32(float) +declare <2 x float> @llvm.fabs.v2f32(<2 x float>) + +declare float @llvm.experimental.constrained.fadd.f32(float, float, metadata, metadata) #0 +declare <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float>, <2 x float>, metadata, metadata) #0 + +declare float @llvm.experimental.constrained.fsub.f32(float, float, metadata, metadata) #0 +declare <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float>, <2 x float>, metadata, metadata) #0 + +declare double @llvm.experimental.constrained.fmul.f64(double, double, metadata, metadata) #0 +declare <4 x float> @llvm.experimental.constrained.fmul.v4f32(<4 x float>, <4 x float>, metadata, metadata) #0 + +declare float @llvm.experimental.constrained.fdiv.f32(float, float, metadata, metadata) #0 + +declare float @llvm.experimental.constrained.maxnum.f32(float, float, metadata) #0 +declare float @llvm.experimental.constrained.sqrt.f32(float, metadata, metadata) #0 + +attributes #0 = { strictfp } diff --git a/llvm/test/Transforms/InstSimplify/fp-undef-poison-strictfp.ll b/llvm/test/Transforms/InstSimplify/fp-undef-poison-strictfp.ll --- a/llvm/test/Transforms/InstSimplify/fp-undef-poison-strictfp.ll +++ b/llvm/test/Transforms/InstSimplify/fp-undef-poison-strictfp.ll @@ -36,8 +36,7 @@ define float @fadd_undef_op0_defaultfp(float %x) #0 { ; CHECK-LABEL: @fadd_undef_op0_defaultfp( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float undef, float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.fadd.f32(float undef, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 ret float %r @@ -46,7 +45,7 @@ define float @fadd_poison_op0_strict(float %x) #0 { ; CHECK-LABEL: @fadd_poison_op0_strict( ; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float poison, float [[X:%.*]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fadd.f32(float poison, float %x, metadata !"round.dynamic", metadata !"fpexcept.strict") #0 ret float %r @@ -54,8 +53,7 @@ define float @fadd_poison_op0_maytrap(float %x) #0 { ; CHECK-LABEL: @fadd_poison_op0_maytrap( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float poison, float [[X:%.*]], metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fadd.f32(float poison, float %x, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0 ret float %r @@ -63,8 +61,7 @@ define float @fadd_poison_op0_upward(float %x) #0 { ; CHECK-LABEL: @fadd_poison_op0_upward( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float poison, float [[X:%.*]], metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fadd.f32(float poison, float %x, metadata !"round.upward", metadata !"fpexcept.ignore") #0 ret float %r @@ -72,8 +69,7 @@ define float @fadd_poison_op0_defaultfp(float %x) #0 { ; CHECK-LABEL: @fadd_poison_op0_defaultfp( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float poison, float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fadd.f32(float poison, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 ret float %r @@ -108,8 +104,7 @@ define float @fadd_undef_op1_defaultfp(float %x) #0 { ; CHECK-LABEL: @fadd_undef_op1_defaultfp( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[X:%.*]], float undef, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.fadd.f32(float %x, float undef, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 ret float %r @@ -118,7 +113,7 @@ define float @fadd_poison_op1_strict(float %x) #0 { ; CHECK-LABEL: @fadd_poison_op1_strict( ; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[X:%.*]], float poison, metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fadd.f32(float %x, float poison, metadata !"round.dynamic", metadata !"fpexcept.strict") #0 ret float %r @@ -126,8 +121,7 @@ define float @fadd_poison_op1_maytrap(float %x) #0 { ; CHECK-LABEL: @fadd_poison_op1_maytrap( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[X:%.*]], float poison, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fadd.f32(float %x, float poison, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0 ret float %r @@ -135,8 +129,7 @@ define float @fadd_poison_op1_upward(float %x) #0 { ; CHECK-LABEL: @fadd_poison_op1_upward( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[X:%.*]], float poison, metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fadd.f32(float %x, float poison, metadata !"round.upward", metadata !"fpexcept.ignore") #0 ret float %r @@ -144,8 +137,7 @@ define float @fadd_poison_op1_defaultfp(float %x) #0 { ; CHECK-LABEL: @fadd_poison_op1_defaultfp( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[X:%.*]], float poison, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fadd.f32(float %x, float poison, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 ret float %r @@ -184,8 +176,7 @@ define float @fsub_undef_op0_defaultfp(float %x) { ; CHECK-LABEL: @fsub_undef_op0_defaultfp( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float undef, float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.fsub.f32(float undef, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 ret float %r @@ -194,7 +185,7 @@ define float @fsub_poison_op0_strict(float %x) { ; CHECK-LABEL: @fsub_poison_op0_strict( ; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float poison, float [[X:%.*]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fsub.f32(float poison, float %x, metadata !"round.dynamic", metadata !"fpexcept.strict") #0 ret float %r @@ -202,8 +193,7 @@ define float @fsub_poison_op0_maytrap(float %x) { ; CHECK-LABEL: @fsub_poison_op0_maytrap( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float poison, float [[X:%.*]], metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fsub.f32(float poison, float %x, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0 ret float %r @@ -211,8 +201,7 @@ define float @fsub_poison_op0_upward(float %x) { ; CHECK-LABEL: @fsub_poison_op0_upward( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float poison, float [[X:%.*]], metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fsub.f32(float poison, float %x, metadata !"round.upward", metadata !"fpexcept.ignore") #0 ret float %r @@ -220,8 +209,7 @@ define float @fsub_poison_op0_defaultfp(float %x) { ; CHECK-LABEL: @fsub_poison_op0_defaultfp( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float poison, float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fsub.f32(float poison, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 ret float %r @@ -256,8 +244,7 @@ define float @fsub_undef_op1_defaultfp(float %x) { ; CHECK-LABEL: @fsub_undef_op1_defaultfp( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[X:%.*]], float undef, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.fsub.f32(float %x, float undef, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 ret float %r @@ -266,7 +253,7 @@ define float @fsub_poison_op1_strict(float %x) { ; CHECK-LABEL: @fsub_poison_op1_strict( ; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[X:%.*]], float poison, metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fsub.f32(float %x, float poison, metadata !"round.dynamic", metadata !"fpexcept.strict") #0 ret float %r @@ -274,8 +261,7 @@ define float @fsub_poison_op1_maytrap(float %x) { ; CHECK-LABEL: @fsub_poison_op1_maytrap( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[X:%.*]], float poison, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fsub.f32(float %x, float poison, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0 ret float %r @@ -283,8 +269,7 @@ define float @fsub_poison_op1_upward(float %x) { ; CHECK-LABEL: @fsub_poison_op1_upward( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[X:%.*]], float poison, metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fsub.f32(float %x, float poison, metadata !"round.upward", metadata !"fpexcept.ignore") #0 ret float %r @@ -292,8 +277,7 @@ define float @fsub_poison_op1_defaultfp(float %x) { ; CHECK-LABEL: @fsub_poison_op1_defaultfp( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[X:%.*]], float poison, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fsub.f32(float %x, float poison, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 ret float %r @@ -332,8 +316,7 @@ define float @fmul_undef_op0_defaultfp(float %x) { ; CHECK-LABEL: @fmul_undef_op0_defaultfp( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fmul.f32(float undef, float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.fmul.f32(float undef, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 ret float %r @@ -342,7 +325,7 @@ define float @fmul_poison_op0_strict(float %x) { ; CHECK-LABEL: @fmul_poison_op0_strict( ; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fmul.f32(float poison, float [[X:%.*]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fmul.f32(float poison, float %x, metadata !"round.dynamic", metadata !"fpexcept.strict") #0 ret float %r @@ -350,8 +333,7 @@ define float @fmul_poison_op0_maytrap(float %x) { ; CHECK-LABEL: @fmul_poison_op0_maytrap( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fmul.f32(float poison, float [[X:%.*]], metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fmul.f32(float poison, float %x, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0 ret float %r @@ -359,8 +341,7 @@ define float @fmul_poison_op0_upward(float %x) { ; CHECK-LABEL: @fmul_poison_op0_upward( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fmul.f32(float poison, float [[X:%.*]], metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fmul.f32(float poison, float %x, metadata !"round.upward", metadata !"fpexcept.ignore") #0 ret float %r @@ -368,8 +349,7 @@ define float @fmul_poison_op0_defaultfp(float %x) { ; CHECK-LABEL: @fmul_poison_op0_defaultfp( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fmul.f32(float poison, float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fmul.f32(float poison, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 ret float %r @@ -404,8 +384,7 @@ define float @fmul_undef_op1_defaultfp(float %x) { ; CHECK-LABEL: @fmul_undef_op1_defaultfp( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fmul.f32(float [[X:%.*]], float undef, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.fmul.f32(float %x, float undef, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 ret float %r @@ -414,7 +393,7 @@ define float @fmul_poison_op1_strict(float %x) { ; CHECK-LABEL: @fmul_poison_op1_strict( ; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fmul.f32(float [[X:%.*]], float poison, metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fmul.f32(float %x, float poison, metadata !"round.dynamic", metadata !"fpexcept.strict") #0 ret float %r @@ -422,8 +401,7 @@ define float @fmul_poison_op1_maytrap(float %x) { ; CHECK-LABEL: @fmul_poison_op1_maytrap( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fmul.f32(float [[X:%.*]], float poison, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fmul.f32(float %x, float poison, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0 ret float %r @@ -431,8 +409,7 @@ define float @fmul_poison_op1_upward(float %x) { ; CHECK-LABEL: @fmul_poison_op1_upward( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fmul.f32(float [[X:%.*]], float poison, metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fmul.f32(float %x, float poison, metadata !"round.upward", metadata !"fpexcept.ignore") #0 ret float %r @@ -440,8 +417,7 @@ define float @fmul_poison_op1_defaultfp(float %x) { ; CHECK-LABEL: @fmul_poison_op1_defaultfp( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fmul.f32(float [[X:%.*]], float poison, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fmul.f32(float %x, float poison, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 ret float %r @@ -480,8 +456,7 @@ define float @fdiv_undef_op0_defaultfp(float %x) { ; CHECK-LABEL: @fdiv_undef_op0_defaultfp( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fdiv.f32(float undef, float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.fdiv.f32(float undef, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 ret float %r @@ -490,7 +465,7 @@ define float @fdiv_poison_op0_strict(float %x) { ; CHECK-LABEL: @fdiv_poison_op0_strict( ; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fdiv.f32(float poison, float [[X:%.*]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fdiv.f32(float poison, float %x, metadata !"round.dynamic", metadata !"fpexcept.strict") #0 ret float %r @@ -498,8 +473,7 @@ define float @fdiv_poison_op0_maytrap(float %x) { ; CHECK-LABEL: @fdiv_poison_op0_maytrap( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fdiv.f32(float poison, float [[X:%.*]], metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fdiv.f32(float poison, float %x, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0 ret float %r @@ -507,8 +481,7 @@ define float @fdiv_poison_op0_upward(float %x) { ; CHECK-LABEL: @fdiv_poison_op0_upward( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fdiv.f32(float poison, float [[X:%.*]], metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fdiv.f32(float poison, float %x, metadata !"round.upward", metadata !"fpexcept.ignore") #0 ret float %r @@ -516,8 +489,7 @@ define float @fdiv_poison_op0_defaultfp(float %x) { ; CHECK-LABEL: @fdiv_poison_op0_defaultfp( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fdiv.f32(float poison, float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fdiv.f32(float poison, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 ret float %r @@ -552,8 +524,7 @@ define float @fdiv_undef_op1_defaultfp(float %x) { ; CHECK-LABEL: @fdiv_undef_op1_defaultfp( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fdiv.f32(float [[X:%.*]], float undef, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.fdiv.f32(float %x, float undef, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 ret float %r @@ -562,7 +533,7 @@ define float @fdiv_poison_op1_strict(float %x) { ; CHECK-LABEL: @fdiv_poison_op1_strict( ; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fdiv.f32(float [[X:%.*]], float poison, metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fdiv.f32(float %x, float poison, metadata !"round.dynamic", metadata !"fpexcept.strict") #0 ret float %r @@ -570,8 +541,7 @@ define float @fdiv_poison_op1_maytrap(float %x) { ; CHECK-LABEL: @fdiv_poison_op1_maytrap( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fdiv.f32(float [[X:%.*]], float poison, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fdiv.f32(float %x, float poison, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0 ret float %r @@ -579,8 +549,7 @@ define float @fdiv_poison_op1_upward(float %x) { ; CHECK-LABEL: @fdiv_poison_op1_upward( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fdiv.f32(float [[X:%.*]], float poison, metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fdiv.f32(float %x, float poison, metadata !"round.upward", metadata !"fpexcept.ignore") #0 ret float %r @@ -588,8 +557,7 @@ define float @fdiv_poison_op1_defaultfp(float %x) { ; CHECK-LABEL: @fdiv_poison_op1_defaultfp( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fdiv.f32(float [[X:%.*]], float poison, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fdiv.f32(float %x, float poison, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 ret float %r @@ -628,8 +596,7 @@ define float @frem_undef_op0_defaultfp(float %x) { ; CHECK-LABEL: @frem_undef_op0_defaultfp( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.frem.f32(float undef, float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.frem.f32(float undef, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 ret float %r @@ -638,7 +605,7 @@ define float @frem_poison_op0_strict(float %x) { ; CHECK-LABEL: @frem_poison_op0_strict( ; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.frem.f32(float poison, float [[X:%.*]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.frem.f32(float poison, float %x, metadata !"round.dynamic", metadata !"fpexcept.strict") #0 ret float %r @@ -646,8 +613,7 @@ define float @frem_poison_op0_maytrap(float %x) { ; CHECK-LABEL: @frem_poison_op0_maytrap( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.frem.f32(float poison, float [[X:%.*]], metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.frem.f32(float poison, float %x, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0 ret float %r @@ -655,8 +621,7 @@ define float @frem_poison_op0_upward(float %x) { ; CHECK-LABEL: @frem_poison_op0_upward( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.frem.f32(float poison, float [[X:%.*]], metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.frem.f32(float poison, float %x, metadata !"round.upward", metadata !"fpexcept.ignore") #0 ret float %r @@ -664,8 +629,7 @@ define float @frem_poison_op0_defaultfp(float %x) { ; CHECK-LABEL: @frem_poison_op0_defaultfp( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.frem.f32(float poison, float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.frem.f32(float poison, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 ret float %r @@ -700,8 +664,7 @@ define float @frem_undef_op1_defaultfp(float %x) { ; CHECK-LABEL: @frem_undef_op1_defaultfp( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.frem.f32(float [[X:%.*]], float undef, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.frem.f32(float %x, float undef, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 ret float %r @@ -710,7 +673,7 @@ define float @frem_poison_op1_strict(float %x) { ; CHECK-LABEL: @frem_poison_op1_strict( ; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.frem.f32(float [[X:%.*]], float poison, metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.frem.f32(float %x, float poison, metadata !"round.dynamic", metadata !"fpexcept.strict") #0 ret float %r @@ -718,8 +681,7 @@ define float @frem_poison_op1_maytrap(float %x) { ; CHECK-LABEL: @frem_poison_op1_maytrap( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.frem.f32(float [[X:%.*]], float poison, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.frem.f32(float %x, float poison, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0 ret float %r @@ -727,8 +689,7 @@ define float @frem_poison_op1_upward(float %x) { ; CHECK-LABEL: @frem_poison_op1_upward( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.frem.f32(float [[X:%.*]], float poison, metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.frem.f32(float %x, float poison, metadata !"round.upward", metadata !"fpexcept.ignore") #0 ret float %r @@ -736,8 +697,7 @@ define float @frem_poison_op1_defaultfp(float %x) { ; CHECK-LABEL: @frem_poison_op1_defaultfp( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.frem.f32(float [[X:%.*]], float poison, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.frem.f32(float %x, float poison, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 ret float %r @@ -776,8 +736,7 @@ define float @fma_undef_op0_defaultfp(float %x, float %y) { ; CHECK-LABEL: @fma_undef_op0_defaultfp( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float undef, float [[X:%.*]], float [[Y:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.fma.f32(float undef, float %x, float %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 ret float %r @@ -786,7 +745,7 @@ define float @fma_poison_op0_strict(float %x, float %y) { ; CHECK-LABEL: @fma_poison_op0_strict( ; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float poison, float [[X:%.*]], float [[Y:%.*]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fma.f32(float poison, float %x, float %y, metadata !"round.dynamic", metadata !"fpexcept.strict") #0 ret float %r @@ -794,8 +753,7 @@ define float @fma_poison_op0_maytrap(float %x, float %y) { ; CHECK-LABEL: @fma_poison_op0_maytrap( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float poison, float [[X:%.*]], float [[Y:%.*]], metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fma.f32(float poison, float %x, float %y, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0 ret float %r @@ -803,8 +761,7 @@ define float @fma_poison_op0_upward(float %x, float %y) { ; CHECK-LABEL: @fma_poison_op0_upward( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float poison, float [[X:%.*]], float [[Y:%.*]], metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fma.f32(float poison, float %x, float %y, metadata !"round.upward", metadata !"fpexcept.ignore") #0 ret float %r @@ -812,8 +769,7 @@ define float @fma_poison_op0_defaultfp(float %x, float %y) { ; CHECK-LABEL: @fma_poison_op0_defaultfp( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float poison, float [[X:%.*]], float [[Y:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fma.f32(float poison, float %x, float %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 ret float %r @@ -848,8 +804,7 @@ define float @fma_undef_op1_defaultfp(float %x, float %y) { ; CHECK-LABEL: @fma_undef_op1_defaultfp( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float [[X:%.*]], float undef, float [[Y:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.fma.f32(float %x, float undef, float %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 ret float %r @@ -858,7 +813,7 @@ define float @fma_poison_op1_strict(float %x, float %y) { ; CHECK-LABEL: @fma_poison_op1_strict( ; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float [[X:%.*]], float poison, float [[Y:%.*]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fma.f32(float %x, float poison, float %y, metadata !"round.dynamic", metadata !"fpexcept.strict") #0 ret float %r @@ -866,8 +821,7 @@ define float @fma_poison_op1_maytrap(float %x, float %y) { ; CHECK-LABEL: @fma_poison_op1_maytrap( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float [[X:%.*]], float poison, float [[Y:%.*]], metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fma.f32(float %x, float poison, float %y, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0 ret float %r @@ -875,8 +829,7 @@ define float @fma_poison_op1_upward(float %x, float %y) { ; CHECK-LABEL: @fma_poison_op1_upward( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float [[X:%.*]], float poison, float [[Y:%.*]], metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fma.f32(float %x, float poison, float %y, metadata !"round.upward", metadata !"fpexcept.ignore") #0 ret float %r @@ -884,8 +837,7 @@ define float @fma_poison_op1_defaultfp(float %x, float %y) { ; CHECK-LABEL: @fma_poison_op1_defaultfp( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float [[X:%.*]], float poison, float [[Y:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fma.f32(float %x, float poison, float %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 ret float %r @@ -920,8 +872,7 @@ define float @fma_undef_op2_defaultfp(float %x, float %y) { ; CHECK-LABEL: @fma_undef_op2_defaultfp( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float [[X:%.*]], float [[Y:%.*]], float undef, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %r = call float @llvm.experimental.constrained.fma.f32(float %x, float %y, float undef, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 ret float %r @@ -930,7 +881,7 @@ define float @fma_poison_op2_strict(float %x, float %y) { ; CHECK-LABEL: @fma_poison_op2_strict( ; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float [[X:%.*]], float [[Y:%.*]], float poison, metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fma.f32(float %x, float %y, float poison, metadata !"round.dynamic", metadata !"fpexcept.strict") #0 ret float %r @@ -938,8 +889,7 @@ define float @fma_poison_op2_maytrap(float %x, float %y) { ; CHECK-LABEL: @fma_poison_op2_maytrap( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float [[X:%.*]], float [[Y:%.*]], float poison, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fma.f32(float %x, float %y, float poison, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0 ret float %r @@ -947,8 +897,7 @@ define float @fma_poison_op2_upward(float %x, float %y) { ; CHECK-LABEL: @fma_poison_op2_upward( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float [[X:%.*]], float [[Y:%.*]], float poison, metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fma.f32(float %x, float %y, float poison, metadata !"round.upward", metadata !"fpexcept.ignore") #0 ret float %r @@ -956,8 +905,7 @@ define float @fma_poison_op2_defaultfp(float %x, float %y) { ; CHECK-LABEL: @fma_poison_op2_defaultfp( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float [[X:%.*]], float [[Y:%.*]], float poison, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]] -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fma.f32(float %x, float %y, float poison, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0 ret float %r