[llvm-branch-commits] [llvm] Prevent optimizations of math intrinsics in strictfp functions (PR #201433)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Wed Jun 3 12:07:25 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-analysis
Author: Serge Pavlov (spavloff)
<details>
<summary>Changes</summary>
Previously, the non-constrained forms of math intrinsics were allowed in strictfp functions. They are treated as the corresponding constrained functions with the assumed rounding mode 'dynamic' and the exception handling mode 'strict'. However, their calls are subject to optimizations, because they look identical to regular intrinsic calls, the only difference lies in the enclosing function attribute. Many of these optimizations are inconsistent with the semantics of strictfp functions.
This change attempts to prevent from unwanted optimizations that involve math intrinsics in strictfp functions. The partition into allowed and unwanted optimizations depends on the criteria used for control modes and exceptions. The criteria used for exception behavior are taken to be the same as those used in the current implementation based on the constrained functions. It requires that exceptions must be raised in the same order and in the same places as they would be when executing the function on an abstract machine. This is a rather restrictive model, and many optimizations are inconsistent with it. Using other exception models could allow more optimizations.
---
Patch is 24.59 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/201433.diff
10 Files Affected:
- (modified) llvm/include/llvm/Analysis/SimplifyQuery.h (+9)
- (modified) llvm/include/llvm/Transforms/InstCombine/InstCombiner.h (+6-1)
- (modified) llvm/lib/Analysis/InstructionSimplify.cpp (+25-14)
- (modified) llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp (+2-1)
- (modified) llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp (+10-4)
- (modified) llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp (+2)
- (modified) llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp (+6)
- (modified) llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp (+30-19)
- (modified) llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp (+1-1)
- (modified) llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp (+17-3)
``````````diff
diff --git a/llvm/include/llvm/Analysis/SimplifyQuery.h b/llvm/include/llvm/Analysis/SimplifyQuery.h
index d1d34f22a2fc5..55aca1aac24de 100644
--- a/llvm/include/llvm/Analysis/SimplifyQuery.h
+++ b/llvm/include/llvm/Analysis/SimplifyQuery.h
@@ -120,6 +120,15 @@ struct SimplifyQuery {
/// Otherwise always return false.
LLVM_ABI bool isUndefValue(Value *V) const;
+ bool isStrictFP() const {
+ if (CxtI) {
+ assert(CxtI->getParent() && "isolated instruction");
+ const Function *F = CxtI->getFunction();
+ return F->hasFnAttribute(Attribute::StrictFP);
+ }
+ return true;
+ }
+
SimplifyQuery getWithoutDomCondCache() const {
SimplifyQuery Copy(*this);
Copy.DC = nullptr;
diff --git a/llvm/include/llvm/Transforms/InstCombine/InstCombiner.h b/llvm/include/llvm/Transforms/InstCombine/InstCombiner.h
index 6de06addac71c..f1856e73e67d3 100644
--- a/llvm/include/llvm/Transforms/InstCombine/InstCombiner.h
+++ b/llvm/include/llvm/Transforms/InstCombine/InstCombiner.h
@@ -99,6 +99,9 @@ class LLVM_LIBRARY_VISIBILITY InstCombiner {
SmallDenseSet<std::pair<const BasicBlock *, const BasicBlock *>, 8> BackEdges;
bool ComputedBackEdges = false;
+ /// Caches StrictFP function attribute.
+ bool StrictFPFunction;
+
public:
InstCombiner(InstructionWorklist &Worklist, BuilderTy &Builder, Function &F,
AAResults *AA, AssumptionCache &AC, TargetLibraryInfo &TLI,
@@ -111,7 +114,8 @@ class LLVM_LIBRARY_VISIBILITY InstCombiner {
F(F), MinimizeSize(F.hasMinSize()), AA(AA), AC(AC), TLI(TLI), DT(DT),
DL(DL), SQ(DL, &TLI, &DT, &AC, nullptr, /*UseInstrInfo*/ true,
/*CanUseUndef*/ true, &DC),
- ORE(ORE), BFI(BFI), BPI(BPI), PSI(PSI), RPOT(RPOT) {}
+ ORE(ORE), BFI(BFI), BPI(BPI), PSI(PSI), RPOT(RPOT),
+ StrictFPFunction(F.hasFnAttribute(Attribute::StrictFP)) {}
virtual ~InstCombiner() = default;
@@ -354,6 +358,7 @@ class LLVM_LIBRARY_VISIBILITY InstCombiner {
}
BlockFrequencyInfo *getBlockFrequencyInfo() const { return BFI; }
ProfileSummaryInfo *getProfileSummaryInfo() const { return PSI; }
+ bool isStrictFP() const { return StrictFPFunction; }
// Call target specific combiners
std::optional<Instruction *> targetInstCombineIntrinsic(IntrinsicInst &II);
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 12c3edc0ced30..054efe77adf72 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -6093,8 +6093,11 @@ static Value *simplifyFMAFMul(Value *Op0, Value *Op1, FastMathFlags FMF,
// 3. Ignore -0.0 because sqrt(-0.0) == -0.0, but -0.0 * -0.0 == 0.0.
Value *X;
if (Op0 == Op1 && match(Op0, m_Sqrt(m_Value(X))) && FMF.allowReassoc() &&
- FMF.noNaNs() && FMF.noSignedZeros())
+ FMF.noNaNs() && FMF.noSignedZeros()) {
+ if (Q.isStrictFP())
+ return nullptr;
return X;
+ }
return nullptr;
}
@@ -6571,31 +6574,31 @@ static Value *simplifyUnaryIntrinsic(Function *F, Value *Op0,
}
case Intrinsic::exp:
// exp(log(x)) -> x
- if (Call->hasAllowReassoc() &&
+ if (Call->hasAllowReassoc() && !isCalledFromStrictFPFunction(Call) &&
match(Op0, m_Intrinsic<Intrinsic::log>(m_Value(X))))
return X;
break;
case Intrinsic::exp2:
// exp2(log2(x)) -> x
- if (Call->hasAllowReassoc() &&
+ if (Call->hasAllowReassoc() && !isCalledFromStrictFPFunction(Call) &&
match(Op0, m_Intrinsic<Intrinsic::log2>(m_Value(X))))
return X;
break;
case Intrinsic::exp10:
// exp10(log10(x)) -> x
- if (Call->hasAllowReassoc() &&
+ if (Call->hasAllowReassoc() && !isCalledFromStrictFPFunction(Call) &&
match(Op0, m_Intrinsic<Intrinsic::log10>(m_Value(X))))
return X;
break;
case Intrinsic::log:
// log(exp(x)) -> x
- if (Call->hasAllowReassoc() &&
+ if (Call->hasAllowReassoc() && !isCalledFromStrictFPFunction(Call) &&
match(Op0, m_Intrinsic<Intrinsic::exp>(m_Value(X))))
return X;
break;
case Intrinsic::log2:
// log2(exp2(x)) -> x
- if (Call->hasAllowReassoc() &&
+ if (Call->hasAllowReassoc() && !isCalledFromStrictFPFunction(Call) &&
(match(Op0, m_Intrinsic<Intrinsic::exp2>(m_Value(X))) ||
match(Op0,
m_Intrinsic<Intrinsic::pow>(m_SpecificFP(2.0), m_Value(X)))))
@@ -6604,7 +6607,7 @@ static Value *simplifyUnaryIntrinsic(Function *F, Value *Op0,
case Intrinsic::log10:
// log10(pow(10.0, x)) -> x
// log10(exp10(x)) -> x
- if (Call->hasAllowReassoc() &&
+ if (Call->hasAllowReassoc() && !isCalledFromStrictFPFunction(Call) &&
(match(Op0, m_Intrinsic<Intrinsic::exp10>(m_Value(X))) ||
match(Op0,
m_Intrinsic<Intrinsic::pow>(m_SpecificFP(10.0), m_Value(X)))))
@@ -6738,6 +6741,9 @@ static MinMaxOptResult OptimizeConstMinMax(const Constant *RHSConst,
return MinMaxOptResult::UseEither;
}
+ if (isCalledFromStrictFPFunction(Call))
+ return MinMaxOptResult::CannotOptimize;
+
const ConstantFP *CFP = dyn_cast<ConstantFP>(RHSConst);
if (!CFP)
return MinMaxOptResult::CannotOptimize;
@@ -7075,16 +7081,18 @@ Value *llvm::simplifyBinaryIntrinsic(Intrinsic::ID IID, Type *ReturnType,
break;
case Intrinsic::powi:
if (auto *Power = dyn_cast<ConstantInt>(Op1)) {
- // powi(x, 0) -> 1.0
- if (Power->isZero())
- return ConstantFP::get(Op0->getType(), 1.0);
- // powi(x, 1) -> x
- if (Power->isOne())
- return Op0;
+ if (!isCalledFromStrictFPFunction(Call)) {
+ // powi(x, 0) -> 1.0
+ if (Power->isZero())
+ return ConstantFP::get(Op0->getType(), 1.0);
+ // powi(x, 1) -> x
+ if (Power->isOne())
+ return Op0;
+ }
}
break;
case Intrinsic::ldexp:
- return simplifyLdexp(Op0, Op1, Q, false);
+ return simplifyLdexp(Op0, Op1, Q, isCalledFromStrictFPFunction(Call));
case Intrinsic::copysign:
// copysign X, X --> X
if (Op0 == Op1)
@@ -7119,6 +7127,9 @@ Value *llvm::simplifyBinaryIntrinsic(Intrinsic::ID IID, Type *ReturnType,
// inserting an llvm.canonicalize to transform input sNaNs into qNaNs,
// or may assume all NaN inputs are qNaNs.
+ if (isCalledFromStrictFPFunction(Call))
+ break;
+
// If the arguments are the same, this is a no-op (ignoring NaN quieting)
if (Op0 == Op1)
return Op0;
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index c781c6978b275..a3f2fcaf33086 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -2096,7 +2096,8 @@ Instruction *InstCombinerImpl::visitFAdd(BinaryOperator &I) {
}
// minumum(X, Y) + maximum(X, Y) => X + Y.
- if (match(&I,
+ if (!StrictFPFunction &&
+ match(&I,
m_c_FAdd(m_Intrinsic<Intrinsic::maximum>(m_Value(X), m_Value(Y)),
m_c_Intrinsic<Intrinsic::minimum>(m_Deferred(X),
m_Deferred(Y))))) {
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index b414a7ed4fe66..3f55dfd2e8c2a 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -2474,15 +2474,15 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
if (ConstantInt *Power = dyn_cast<ConstantInt>(II->getArgOperand(1))) {
// 0 and 1 are handled in instsimplify
// powi(x, -1) -> 1/x
- if (Power->isMinusOne())
+ if (Power->isMinusOne() && !StrictFPFunction)
return BinaryOperator::CreateFDivFMF(ConstantFP::get(CI.getType(), 1.0),
II->getArgOperand(0), II);
// powi(x, 2) -> x*x
- if (Power->equalsInt(2))
+ if (Power->equalsInt(2) && !StrictFPFunction)
return BinaryOperator::CreateFMulFMF(II->getArgOperand(0),
II->getArgOperand(0), II);
- if (!Power->getValue()[0]) {
+ if (!Power->getValue()[0] && !StrictFPFunction) {
Value *X;
// If power is even:
// powi(-x, p) -> powi(x, p)
@@ -2824,6 +2824,8 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
case Intrinsic::maximumnum:
case Intrinsic::minimum:
case Intrinsic::maximum: {
+ if (StrictFPFunction)
+ break;
Value *Arg0 = II->getArgOperand(0);
Value *Arg1 = II->getArgOperand(1);
Value *X, *Y;
@@ -3162,7 +3164,8 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
case Intrinsic::rint:
case Intrinsic::trunc: {
Value *ExtSrc;
- if (match(II->getArgOperand(0), m_OneUse(m_FPExt(m_Value(ExtSrc))))) {
+ if (!StrictFPFunction &&
+ match(II->getArgOperand(0), m_OneUse(m_FPExt(m_Value(ExtSrc))))) {
// Narrow the call: intrinsic (fpext x) -> fpext (intrinsic x)
Value *NarrowII = Builder.CreateUnaryIntrinsic(IID, ExtSrc, II);
return new FPExtInst(NarrowII, II->getType());
@@ -3229,6 +3232,9 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
}
}
+ if (StrictFPFunction)
+ break;
+
Value *InnerSrc;
Value *InnerExp;
if (match(Src, m_OneUse(m_Intrinsic<Intrinsic::ldexp>(
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
index bd3a5c1128f7a..d78d19f0003e3 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
@@ -2210,6 +2210,8 @@ Instruction *InstCombinerImpl::visitFPTrunc(FPTruncInst &FPT) {
// operation to be itself an fpext from the type to which we're
// truncating.
if (II->getIntrinsicID() != Intrinsic::fabs) {
+ if (StrictFPFunction)
+ break;
FPExtInst *FPExtSrc = dyn_cast<FPExtInst>(Src);
if (!FPExtSrc || FPExtSrc->getSrcTy() != Ty)
break;
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index dc860700db91b..00b4238dfd6e9 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -8559,6 +8559,9 @@ static Instruction *foldSqrtWithFcmpZero(FCmpInst &I, InstCombinerImpl &IC) {
if (!match(I.getOperand(1), m_PosZeroFP()))
return nullptr;
+ if (IC.isStrictFP())
+ return nullptr;
+
auto ReplacePredAndOp0 = [&](FCmpInst::Predicate P) {
I.setPredicate(P);
return IC.replaceOperand(I, 0, X);
@@ -8681,6 +8684,9 @@ static Instruction *foldFCmpFSubIntoFCmp(FCmpInst &I, Instruction *LHSI,
static Instruction *foldFCmpWithFloorAndCeil(FCmpInst &I,
InstCombinerImpl &IC) {
+ if (IC.isStrictFP())
+ return nullptr;
+
Value *LHS = I.getOperand(0), *RHS = I.getOperand(1);
Type *OpType = LHS->getType();
CmpInst::Predicate Pred = I.getPredicate();
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index 35ab21f6d8740..bdfd8676bf9f2 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -647,6 +647,8 @@ Instruction *InstCombinerImpl::foldPowiReassoc(BinaryOperator &I) {
unsigned Opcode = I.getOpcode();
assert((Opcode == Instruction::FMul || Opcode == Instruction::FDiv) &&
"Unexpected opcode");
+ if (StrictFPFunction)
+ return nullptr;
// powi(X, Y) * X --> powi(X, Y+1)
// X * powi(X, Y) --> powi(X, Y+1)
@@ -866,7 +868,7 @@ Instruction *InstCombinerImpl::foldFMulReassoc(BinaryOperator &I) {
// nnan disallows the possibility of returning a number if both operands are
// negative (in that case, we should return NaN).
if (I.hasNoNaNs() && match(Op0, m_OneUse(m_Sqrt(m_Value(X)))) &&
- match(Op1, m_OneUse(m_Sqrt(m_Value(Y))))) {
+ match(Op1, m_OneUse(m_Sqrt(m_Value(Y)))) && !StrictFPFunction) {
Value *XY = Builder.CreateFMulFMF(X, Y, &I);
Value *Sqrt = Builder.CreateUnaryIntrinsic(Intrinsic::sqrt, XY, &I);
return replaceInstUsesWith(I, Sqrt);
@@ -878,18 +880,19 @@ Instruction *InstCombinerImpl::foldFMulReassoc(BinaryOperator &I) {
// 2) X * 1.0/sqrt(X) -> X/sqrt(X)
// We always expect the backend to reduce X/sqrt(X) to sqrt(X), if it
// has the necessary (reassoc) fast-math-flags.
- if (I.hasNoSignedZeros() &&
+ if (I.hasNoSignedZeros() && !StrictFPFunction &&
match(Op0, (m_FDiv(m_SpecificFP(1.0), m_Value(Y)))) &&
match(Y, m_Sqrt(m_Value(X))) && Op1 == X)
return BinaryOperator::CreateFDivFMF(X, Y, &I);
- if (I.hasNoSignedZeros() &&
+ if (I.hasNoSignedZeros() && !StrictFPFunction &&
match(Op1, (m_FDiv(m_SpecificFP(1.0), m_Value(Y)))) &&
match(Y, m_Sqrt(m_Value(X))) && Op0 == X)
return BinaryOperator::CreateFDivFMF(X, Y, &I);
// Like the similar transform in instsimplify, this requires 'nsz' because
// sqrt(-0.0) = -0.0, and -0.0 * -0.0 does not simplify to -0.0.
- if (I.hasNoNaNs() && I.hasNoSignedZeros() && Op0 == Op1 && Op0->hasNUses(2)) {
+ if (I.hasNoNaNs() && I.hasNoSignedZeros() && Op0 == Op1 && Op0->hasNUses(2) &&
+ !StrictFPFunction) {
// Peek through fdiv to find squaring of square root:
// (X / sqrt(Y)) * (X / sqrt(Y)) --> (X * X) / Y
if (match(Op0, m_FDiv(m_Value(X), m_Sqrt(m_Value(Y))))) {
@@ -907,7 +910,8 @@ Instruction *InstCombinerImpl::foldFMulReassoc(BinaryOperator &I) {
// X * pow(X, Y) --> pow(X, Y+1)
if (match(&I, m_c_FMul(m_OneUse(m_Intrinsic<Intrinsic::pow>(m_Value(X),
m_Value(Y))),
- m_Deferred(X)))) {
+ m_Deferred(X))) &&
+ !StrictFPFunction) {
Value *Y1 = Builder.CreateFAddFMF(Y, ConstantFP::get(I.getType(), 1.0), &I);
Value *Pow = Builder.CreateBinaryIntrinsic(Intrinsic::pow, X, Y1, &I);
return replaceInstUsesWith(I, Pow);
@@ -919,14 +923,16 @@ Instruction *InstCombinerImpl::foldFMulReassoc(BinaryOperator &I) {
if (I.isOnlyUserOfAnyOperand()) {
// pow(X, Y) * pow(X, Z) -> pow(X, Y + Z)
if (match(Op0, m_Intrinsic<Intrinsic::pow>(m_Value(X), m_Value(Y))) &&
- match(Op1, m_Intrinsic<Intrinsic::pow>(m_Specific(X), m_Value(Z)))) {
+ match(Op1, m_Intrinsic<Intrinsic::pow>(m_Specific(X), m_Value(Z))) &&
+ !StrictFPFunction) {
auto *YZ = Builder.CreateFAddFMF(Y, Z, &I);
auto *NewPow = Builder.CreateBinaryIntrinsic(Intrinsic::pow, X, YZ, &I);
return replaceInstUsesWith(I, NewPow);
}
// pow(X, Y) * pow(Z, Y) -> pow(X * Z, Y)
if (match(Op0, m_Intrinsic<Intrinsic::pow>(m_Value(X), m_Value(Y))) &&
- match(Op1, m_Intrinsic<Intrinsic::pow>(m_Value(Z), m_Specific(Y)))) {
+ match(Op1, m_Intrinsic<Intrinsic::pow>(m_Value(Z), m_Specific(Y))) &&
+ !StrictFPFunction) {
auto *XZ = Builder.CreateFMulFMF(X, Z, &I);
auto *NewPow = Builder.CreateBinaryIntrinsic(Intrinsic::pow, XZ, Y, &I);
return replaceInstUsesWith(I, NewPow);
@@ -934,7 +940,8 @@ Instruction *InstCombinerImpl::foldFMulReassoc(BinaryOperator &I) {
// exp(X) * exp(Y) -> exp(X + Y)
if (match(Op0, m_Intrinsic<Intrinsic::exp>(m_Value(X))) &&
- match(Op1, m_Intrinsic<Intrinsic::exp>(m_Value(Y)))) {
+ match(Op1, m_Intrinsic<Intrinsic::exp>(m_Value(Y))) &&
+ !StrictFPFunction) {
Value *XY = Builder.CreateFAddFMF(X, Y, &I);
Value *Exp = Builder.CreateUnaryIntrinsic(Intrinsic::exp, XY, &I);
return replaceInstUsesWith(I, Exp);
@@ -942,7 +949,8 @@ Instruction *InstCombinerImpl::foldFMulReassoc(BinaryOperator &I) {
// exp2(X) * exp2(Y) -> exp2(X + Y)
if (match(Op0, m_Intrinsic<Intrinsic::exp2>(m_Value(X))) &&
- match(Op1, m_Intrinsic<Intrinsic::exp2>(m_Value(Y)))) {
+ match(Op1, m_Intrinsic<Intrinsic::exp2>(m_Value(Y))) &&
+ !StrictFPFunction) {
Value *XY = Builder.CreateFAddFMF(X, Y, &I);
Value *Exp2 = Builder.CreateUnaryIntrinsic(Intrinsic::exp2, XY, &I);
return replaceInstUsesWith(I, Exp2);
@@ -1036,7 +1044,7 @@ Instruction *InstCombinerImpl::visitFMul(BinaryOperator &I) {
return FoldedMul;
// log2(X * 0.5) * Y = log2(X) * Y - Y
- if (I.isFast()) {
+ if (I.isFast() && !StrictFPFunction) {
IntrinsicInst *Log2 = nullptr;
if (match(Op0, m_OneUse(m_Intrinsic<Intrinsic::log2>(
m_OneUse(m_FMul(m_Value(X), m_SpecificFP(0.5))))))) {
@@ -1065,7 +1073,8 @@ Instruction *InstCombinerImpl::visitFMul(BinaryOperator &I) {
return replaceInstUsesWith(I, Start);
// minimum(X, Y) * maximum(X, Y) => X * Y.
- if (match(&I,
+ if (!StrictFPFunction &&
+ match(&I,
m_c_FMul(m_Intrinsic<Intrinsic::maximum>(m_Value(X), m_Value(Y)),
m_c_Intrinsic<Intrinsic::minimum>(m_Deferred(X),
m_Deferred(Y))))) {
@@ -1079,7 +1088,7 @@ Instruction *InstCombinerImpl::visitFMul(BinaryOperator &I) {
}
// tan(X) * cos(X) -> sin(X)
- if (I.hasAllowContract() &&
+ if (I.hasAllowContract() && !StrictFPFunction &&
match(&I,
m_c_FMul(m_OneUse(m_Intrinsic<Intrinsic::tan>(m_Value(X))),
m_OneUse(m_Intrinsic<Intrinsic::cos>(m_Deferred(X)))))) {
@@ -1986,7 +1995,7 @@ static Instruction *foldFDivPowDivisor(BinaryOperator &I,
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
auto *II = dyn_cast<IntrinsicInst>(Op1);
if (!II || !II->hasOneUse() || !I.hasAllowReassoc() ||
- !I.hasAllowReciprocal())
+ !I.hasAllowReciprocal() || isCalledFromStrictFPFunction(II))
return nullptr;
// Z / pow(X, Y) --> Z * pow(X, -Y)
@@ -2035,7 +2044,8 @@ static Instruction *foldFDivSqrtDivisor(BinaryOperator &I,
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
auto *II = dyn_cast<IntrinsicInst>(Op1);
if (!II || II->getIntrinsicID() != Intrinsic::sqrt || !II->hasOneUse() ||
- !II->hasAllowReassoc() || !II->hasAllowReciprocal())
+ !II->hasAllowReassoc() || !II->hasAllowReciprocal() ||
+ isCalledFromStrictFPFunction(II))
return nullptr;
Value *Y, *Z;
@@ -2157,7 +2167,7 @@ Instruction *InstCombinerImpl::visitFDiv(BinaryOperator &I) {
// r2 = sqrt(a)
// x = r1 * r2
SmallPtrSet<Instruction *, 2> R1, R2;
- if (isFSqrtDivToFMulLegal(&I, R1, R2)) {
+ if (isFSqrtDivToFMulLegal(&I, R1, R2) && !StrictFPFunction) {
CallInst *CI = cast<CallInst>(I.getOperand(1));
if (Instruction *D = convertFSqrtDivIntoFMul(CI, &I, R1, R2, Builder, this))
return D;
@@ -2197,7 +2207,8 @@ Instruction *InstCombinerImpl::visitFDiv(BinaryOperator &I) {
return BinaryOperator::CreateFMulFMF(Y, Op0, &I);
}
- if (I.hasAllowReassoc() && Op0->hasOneUse() && Op1->hasOneUse()) {
+ if (I.hasAllowReassoc() && Op0->hasOneUse() && Op1->hasOneUse() &&
+ !StrictFPFunction) {
// sin(X) / cos(X) -> tan(X)
// cos(X) / sin(X) -> 1/tan(X) (cotangent)
Value *X;
@@ -2226,7 +2237,7 @@ Instruction *InstCombinerImpl::visitFDiv(BinaryOperator &I) {
// Reassociate to (X / X -> 1.0) is legal when NaNs are not allowed.
// We can ignore the possibility that X is infinity because INF/INF is NaN.
Value *X, *Y;
- if (I.hasNoNaNs() && I.hasAllowReassoc() &&
+ if (I.hasNoNaNs() && I.hasAllowReassoc() && !StrictFPFunction &&
match(Op1, m_c_FMul(m_Specific(Op0), m_Value(Y)))) {
replaceOperand(I, 0, ConstantFP::get(I.getType(), 1.0));
replaceOperand(I, 1, Y);
@@ -2235,7 +2246,7 @@ Instruction *InstCombinerImpl::visitFDiv(BinaryOperator &I) {
// X / fabs(X) -> copysign(1.0, X)
// fabs(X) / X -> copysign(1.0, X)
- if (I.hasNoNaNs() && I.hasNoInfs() &&
+ if (I.hasNoNaNs() && I.hasNoInfs() && !StrictFPFunction &&
(match(&I, m_FDiv(m_Value(X), m_FAbs(m_Deferred(X)))) ||
match(&I, m_FDiv(m_FAbs(m_Value(X)), m_Deferred(X))))) {
Value *V = Builder.CreateBinaryIntrinsic(
@@ -2250,7 +2261,7 @@ Instruction *InstCombinerImpl::visitFDiv(BinaryOperator &I) {
return Mul;
// pow(X, Y) / X --> pow(X, Y-...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/201433
More information about the llvm-branch-commits
mailing list