return nullptr;
}
-static Value *simplifyAndOrOfFCmps(const TargetLibraryInfo *TLI, FCmpInst *LHS,
+static Value *simplifyAndOrOfFCmps(const DataLayout &DL,
+ const TargetLibraryInfo *TLI, FCmpInst *LHS,
FCmpInst *RHS, bool IsAnd) {
Value *LHS0 = LHS->getOperand(0), *LHS1 = LHS->getOperand(1);
Value *RHS0 = RHS->getOperand(0), *RHS1 = RHS->getOperand(1);
// (fcmp uno NNAN, X) | (fcmp uno Y, X) --> fcmp uno Y, X
// (fcmp uno X, NNAN) | (fcmp uno X, Y) --> fcmp uno X, Y
// (fcmp uno X, NNAN) | (fcmp uno Y, X) --> fcmp uno Y, X
- if (((LHS1 == RHS0 || LHS1 == RHS1) && isKnownNeverNaN(LHS0, TLI)) ||
- ((LHS0 == RHS0 || LHS0 == RHS1) && isKnownNeverNaN(LHS1, TLI)))
+ if (((LHS1 == RHS0 || LHS1 == RHS1) && isKnownNeverNaN(LHS0, DL, TLI)) ||
+ ((LHS0 == RHS0 || LHS0 == RHS1) && isKnownNeverNaN(LHS1, DL, TLI)))
return RHS;
// (fcmp ord X, Y) & (fcmp ord NNAN, X) --> fcmp ord X, Y
// (fcmp uno Y, X) | (fcmp uno NNAN, X) --> fcmp uno Y, X
// (fcmp uno X, Y) | (fcmp uno X, NNAN) --> fcmp uno X, Y
// (fcmp uno Y, X) | (fcmp uno X, NNAN) --> fcmp uno Y, X
- if (((RHS1 == LHS0 || RHS1 == LHS1) && isKnownNeverNaN(RHS0, TLI)) ||
- ((RHS0 == LHS0 || RHS0 == LHS1) && isKnownNeverNaN(RHS1, TLI)))
+ if (((RHS1 == LHS0 || RHS1 == LHS1) && isKnownNeverNaN(RHS0, DL, TLI)) ||
+ ((RHS0 == LHS0 || RHS0 == LHS1) && isKnownNeverNaN(RHS1, DL, TLI)))
return LHS;
}
auto *FCmp0 = dyn_cast<FCmpInst>(Op0);
auto *FCmp1 = dyn_cast<FCmpInst>(Op1);
if (FCmp0 && FCmp1)
- V = simplifyAndOrOfFCmps(Q.TLI, FCmp0, FCmp1, IsAnd);
+ V = simplifyAndOrOfFCmps(Q.DL, Q.TLI, FCmp0, FCmp1, IsAnd);
if (!V)
return nullptr;
// Fold (un)ordered comparison if we can determine there are no NaNs.
if (Pred == FCmpInst::FCMP_UNO || Pred == FCmpInst::FCMP_ORD)
- if (FMF.noNaNs() ||
- (isKnownNeverNaN(LHS, Q.TLI) && isKnownNeverNaN(RHS, Q.TLI)))
+ if (FMF.noNaNs() || (isKnownNeverNaN(LHS, Q.DL, Q.TLI) &&
+ isKnownNeverNaN(RHS, Q.DL, Q.TLI)))
return ConstantInt::get(RetTy, Pred == FCmpInst::FCMP_ORD);
// NaN is unordered; NaN is not ordered.
}
// LHS == Inf
- if (Pred == FCmpInst::FCMP_OEQ && isKnownNeverInfinity(LHS, Q.TLI))
+ if (Pred == FCmpInst::FCMP_OEQ && isKnownNeverInfinity(LHS, Q.DL, Q.TLI))
return getFalse(RetTy);
// LHS != Inf
- if (Pred == FCmpInst::FCMP_UNE && isKnownNeverInfinity(LHS, Q.TLI))
+ if (Pred == FCmpInst::FCMP_UNE && isKnownNeverInfinity(LHS, Q.DL, Q.TLI))
return getTrue(RetTy);
// LHS == Inf || LHS == NaN
- if (Pred == FCmpInst::FCMP_UEQ && isKnownNeverInfinity(LHS, Q.TLI) &&
- isKnownNeverNaN(LHS, Q.TLI))
+ if (Pred == FCmpInst::FCMP_UEQ &&
+ isKnownNeverInfinity(LHS, Q.DL, Q.TLI) &&
+ isKnownNeverNaN(LHS, Q.DL, Q.TLI))
return getFalse(RetTy);
// LHS != Inf && LHS != NaN
- if (Pred == FCmpInst::FCMP_ONE && isKnownNeverInfinity(LHS, Q.TLI) &&
- isKnownNeverNaN(LHS, Q.TLI))
+ if (Pred == FCmpInst::FCMP_ONE &&
+ isKnownNeverInfinity(LHS, Q.DL, Q.TLI) &&
+ isKnownNeverNaN(LHS, Q.DL, Q.TLI))
return getTrue(RetTy);
}
if (C->isNegative() && !C->isNegZero()) {
case FCmpInst::FCMP_UGT:
case FCmpInst::FCMP_UNE:
// (X >= 0) implies (X > C) when (C < 0)
- if (CannotBeOrderedLessThanZero(LHS, Q.TLI))
+ if (CannotBeOrderedLessThanZero(LHS, Q.DL, Q.TLI))
return getTrue(RetTy);
break;
case FCmpInst::FCMP_OEQ:
case FCmpInst::FCMP_OLE:
case FCmpInst::FCMP_OLT:
// (X >= 0) implies !(X < C) when (C < 0)
- if (CannotBeOrderedLessThanZero(LHS, Q.TLI))
+ if (CannotBeOrderedLessThanZero(LHS, Q.DL, Q.TLI))
return getFalse(RetTy);
break;
default:
case FCmpInst::FCMP_ULT:
// Positive or zero X >= 0.0 --> true
// Positive or zero X < 0.0 --> false
- if ((FMF.noNaNs() || isKnownNeverNaN(LHS, Q.TLI)) &&
- CannotBeOrderedLessThanZero(LHS, Q.TLI))
+ if ((FMF.noNaNs() || isKnownNeverNaN(LHS, Q.DL, Q.TLI)) &&
+ CannotBeOrderedLessThanZero(LHS, Q.DL, Q.TLI))
return Pred == FCmpInst::FCMP_OGE ? getTrue(RetTy) : getFalse(RetTy);
break;
case FCmpInst::FCMP_UGE:
case FCmpInst::FCMP_OLT:
// Positive or zero or nan X >= 0.0 --> true
// Positive or zero or nan X < 0.0 --> false
- if (CannotBeOrderedLessThanZero(LHS, Q.TLI))
+ if (CannotBeOrderedLessThanZero(LHS, Q.DL, Q.TLI))
return Pred == FCmpInst::FCMP_UGE ? getTrue(RetTy) : getFalse(RetTy);
break;
default:
return ConstantFP::getZero(Op0->getType());
// +normal number * (-)0.0 --> (-)0.0
- if (isKnownNeverInfinity(Op0, Q.TLI) && isKnownNeverNaN(Op0, Q.TLI) &&
- SignBitMustBeZero(Op0, Q.TLI))
+ // TODO: Use computeKnownFPClass
+ if (isKnownNeverInfinity(Op0, Q.DL, Q.TLI) &&
+ isKnownNeverNaN(Op0, Q.DL, Q.TLI) &&
+ SignBitMustBeZero(Op0, Q.DL, Q.TLI))
return Op1;
}
Value *X;
switch (IID) {
case Intrinsic::fabs:
- if (SignBitMustBeZero(Op0, Q.TLI))
+ if (SignBitMustBeZero(Op0, Q.DL, Q.TLI))
return Op0;
break;
case Intrinsic::bswap:
/// standard ordered compare. e.g. make -0.0 olt 0.0 be true because of the sign
/// bit despite comparing equal.
static bool cannotBeOrderedLessThanZeroImpl(const Value *V,
+ const DataLayout &DL,
const TargetLibraryInfo *TLI,
- bool SignBitOnly,
- unsigned Depth) {
+ bool SignBitOnly, unsigned Depth) {
// TODO: This function does not do the right thing when SignBitOnly is true
// and we're lowering to a hypothetical IEEE 754-compliant-but-evil platform
// which flips the sign bits of NaNs. See
return true;
// Set SignBitOnly for RHS, because X / -0.0 is -Inf (or NaN).
- return cannotBeOrderedLessThanZeroImpl(I->getOperand(0), TLI, SignBitOnly,
- Depth + 1) &&
- cannotBeOrderedLessThanZeroImpl(I->getOperand(1), TLI,
+ return cannotBeOrderedLessThanZeroImpl(I->getOperand(0), DL, TLI,
+ SignBitOnly, Depth + 1) &&
+ cannotBeOrderedLessThanZeroImpl(I->getOperand(1), DL, TLI,
/*SignBitOnly*/ true, Depth + 1);
case Instruction::FMul:
// X * X is always non-negative or a NaN.
[[fallthrough]];
case Instruction::FAdd:
case Instruction::FRem:
- return cannotBeOrderedLessThanZeroImpl(I->getOperand(0), TLI, SignBitOnly,
- Depth + 1) &&
- cannotBeOrderedLessThanZeroImpl(I->getOperand(1), TLI, SignBitOnly,
- Depth + 1);
+ return cannotBeOrderedLessThanZeroImpl(I->getOperand(0), DL, TLI,
+ SignBitOnly, Depth + 1) &&
+ cannotBeOrderedLessThanZeroImpl(I->getOperand(1), DL, TLI,
+ SignBitOnly, Depth + 1);
case Instruction::Select:
- return cannotBeOrderedLessThanZeroImpl(I->getOperand(1), TLI, SignBitOnly,
- Depth + 1) &&
- cannotBeOrderedLessThanZeroImpl(I->getOperand(2), TLI, SignBitOnly,
- Depth + 1);
+ return cannotBeOrderedLessThanZeroImpl(I->getOperand(1), DL, TLI,
+ SignBitOnly, Depth + 1) &&
+ cannotBeOrderedLessThanZeroImpl(I->getOperand(2), DL, TLI,
+ SignBitOnly, Depth + 1);
case Instruction::FPExt:
case Instruction::FPTrunc:
// Widening/narrowing never change sign.
- return cannotBeOrderedLessThanZeroImpl(I->getOperand(0), TLI, SignBitOnly,
- Depth + 1);
+ return cannotBeOrderedLessThanZeroImpl(I->getOperand(0), DL, TLI,
+ SignBitOnly, Depth + 1);
case Instruction::ExtractElement:
// Look through extract element. At the moment we keep this simple and skip
// tracking the specific element. But at least we might find information
// valid for all elements of the vector.
- return cannotBeOrderedLessThanZeroImpl(I->getOperand(0), TLI, SignBitOnly,
- Depth + 1);
+ return cannotBeOrderedLessThanZeroImpl(I->getOperand(0), DL, TLI,
+ SignBitOnly, Depth + 1);
case Instruction::Call:
const auto *CI = cast<CallInst>(I);
Intrinsic::ID IID = getIntrinsicForCallSite(*CI, TLI);
case Intrinsic::round:
case Intrinsic::roundeven:
case Intrinsic::fptrunc_round:
- return cannotBeOrderedLessThanZeroImpl(I->getOperand(0), TLI, SignBitOnly, Depth + 1);
+ return cannotBeOrderedLessThanZeroImpl(I->getOperand(0), DL, TLI,
+ SignBitOnly, Depth + 1);
case Intrinsic::maxnum: {
Value *V0 = I->getOperand(0), *V1 = I->getOperand(1);
auto isPositiveNum = [&](Value *V) {
// -0.0 compares equal to 0.0, so if this operand is at least -0.0,
// maxnum can't be ordered-less-than-zero.
- return isKnownNeverNaN(V, TLI) &&
- cannotBeOrderedLessThanZeroImpl(V, TLI, false, Depth + 1);
+ return isKnownNeverNaN(V, DL, TLI) &&
+ cannotBeOrderedLessThanZeroImpl(V, DL, TLI, false, Depth + 1);
};
// TODO: This could be improved. We could also check that neither operand
}
case Intrinsic::maximum:
- return cannotBeOrderedLessThanZeroImpl(I->getOperand(0), TLI, SignBitOnly,
- Depth + 1) ||
- cannotBeOrderedLessThanZeroImpl(I->getOperand(1), TLI, SignBitOnly,
- Depth + 1);
+ return cannotBeOrderedLessThanZeroImpl(I->getOperand(0), DL, TLI,
+ SignBitOnly, Depth + 1) ||
+ cannotBeOrderedLessThanZeroImpl(I->getOperand(1), DL, TLI,
+ SignBitOnly, Depth + 1);
case Intrinsic::minnum:
case Intrinsic::minimum:
- return cannotBeOrderedLessThanZeroImpl(I->getOperand(0), TLI, SignBitOnly,
- Depth + 1) &&
- cannotBeOrderedLessThanZeroImpl(I->getOperand(1), TLI, SignBitOnly,
- Depth + 1);
+ return cannotBeOrderedLessThanZeroImpl(I->getOperand(0), DL, TLI,
+ SignBitOnly, Depth + 1) &&
+ cannotBeOrderedLessThanZeroImpl(I->getOperand(1), DL, TLI,
+ SignBitOnly, Depth + 1);
case Intrinsic::exp:
case Intrinsic::exp2:
case Intrinsic::fabs:
return true;
case Intrinsic::copysign:
// Only the sign operand matters.
- return cannotBeOrderedLessThanZeroImpl(I->getOperand(1), TLI, true,
+ return cannotBeOrderedLessThanZeroImpl(I->getOperand(1), DL, TLI, true,
Depth + 1);
case Intrinsic::sqrt:
// sqrt(x) is always >= -0 or NaN. Moreover, sqrt(x) == -0 iff x == -0.
// but we must return false if x == -0. Unfortunately we do not currently
// have a way of expressing this constraint. See details in
// https://llvm.org/bugs/show_bug.cgi?id=31702.
- return cannotBeOrderedLessThanZeroImpl(I->getOperand(0), TLI, SignBitOnly,
- Depth + 1);
+ return cannotBeOrderedLessThanZeroImpl(I->getOperand(0), DL, TLI,
+ SignBitOnly, Depth + 1);
case Intrinsic::fma:
case Intrinsic::fmuladd:
// x*x+y is non-negative if y is non-negative.
return I->getOperand(0) == I->getOperand(1) &&
(!SignBitOnly || cast<FPMathOperator>(I)->hasNoNaNs()) &&
- cannotBeOrderedLessThanZeroImpl(I->getOperand(2), TLI, SignBitOnly,
- Depth + 1);
+ cannotBeOrderedLessThanZeroImpl(I->getOperand(2), DL, TLI,
+ SignBitOnly, Depth + 1);
}
break;
}
return false;
}
-bool llvm::CannotBeOrderedLessThanZero(const Value *V,
+bool llvm::CannotBeOrderedLessThanZero(const Value *V, const DataLayout &DL,
const TargetLibraryInfo *TLI) {
- return cannotBeOrderedLessThanZeroImpl(V, TLI, false, 0);
+ return cannotBeOrderedLessThanZeroImpl(V, DL, TLI, false, 0);
}
-bool llvm::SignBitMustBeZero(const Value *V, const TargetLibraryInfo *TLI) {
- return cannotBeOrderedLessThanZeroImpl(V, TLI, true, 0);
-}
-
-bool llvm::isKnownNeverInfinity(const Value *V, const TargetLibraryInfo *TLI,
- unsigned Depth) {
+bool llvm::isKnownNeverInfinity(const Value *V, const DataLayout &DL,
+ const TargetLibraryInfo *TLI, unsigned Depth,
+ AssumptionCache *AC, const Instruction *CtxI,
+ const DominatorTree *DT,
+ OptimizationRemarkEmitter *ORE,
+ bool UseInstrInfo) {
assert(V->getType()->isFPOrFPVectorTy() && "Querying for Inf on non-FP type");
// If we're told that infinities won't happen, assume they won't.
if (auto *Inst = dyn_cast<Instruction>(V)) {
switch (Inst->getOpcode()) {
case Instruction::Select: {
- return isKnownNeverInfinity(Inst->getOperand(1), TLI, Depth + 1) &&
- isKnownNeverInfinity(Inst->getOperand(2), TLI, Depth + 1);
+ return isKnownNeverInfinity(Inst->getOperand(1), DL, TLI, Depth + 1) &&
+ isKnownNeverInfinity(Inst->getOperand(2), DL, TLI, Depth + 1);
}
case Instruction::SIToFP:
case Instruction::UIToFP: {
case Instruction::FNeg:
case Instruction::FPExt: {
// Peek through to source op. If it is not infinity, this is not infinity.
- return isKnownNeverInfinity(Inst->getOperand(0), TLI, Depth + 1);
+ return isKnownNeverInfinity(Inst->getOperand(0), DL, TLI, Depth + 1);
}
case Instruction::FPTrunc: {
// Need a range check.
case Intrinsic::copysign:
case Intrinsic::arithmetic_fence:
case Intrinsic::trunc:
- return isKnownNeverInfinity(Inst->getOperand(0), TLI, Depth + 1);
+ return isKnownNeverInfinity(Inst->getOperand(0), DL, TLI, Depth + 1);
case Intrinsic::floor:
case Intrinsic::ceil:
case Intrinsic::rint:
// PPC_FP128 is a special case.
if (V->getType()->isMultiUnitFPType())
return false;
- return isKnownNeverInfinity(Inst->getOperand(0), TLI, Depth + 1);
+ return isKnownNeverInfinity(Inst->getOperand(0), DL, TLI, Depth + 1);
case Intrinsic::fptrunc_round:
// Requires knowing the value range.
return false;
case Intrinsic::maxnum:
case Intrinsic::minimum:
case Intrinsic::maximum:
- return isKnownNeverInfinity(Inst->getOperand(0), TLI, Depth + 1) &&
- isKnownNeverInfinity(Inst->getOperand(1), TLI, Depth + 1);
+ return isKnownNeverInfinity(Inst->getOperand(0), DL, TLI, Depth + 1) &&
+ isKnownNeverInfinity(Inst->getOperand(1), DL, TLI, Depth + 1);
case Intrinsic::log:
case Intrinsic::log10:
case Intrinsic::log2:
return false;
}
-bool llvm::isKnownNeverNaN(const Value *V, const TargetLibraryInfo *TLI,
- unsigned Depth) {
+bool llvm::SignBitMustBeZero(const Value *V, const DataLayout &DL,
+ const TargetLibraryInfo *TLI) {
+ return cannotBeOrderedLessThanZeroImpl(V, DL, TLI, true, 0);
+}
+
+bool llvm::isKnownNeverNaN(const Value *V, const DataLayout &DL,
+ const TargetLibraryInfo *TLI, unsigned Depth,
+ AssumptionCache *AC, const Instruction *CtxI,
+ const DominatorTree *DT,
+ OptimizationRemarkEmitter *ORE, bool UseInstrInfo) {
assert(V->getType()->isFPOrFPVectorTy() && "Querying for NaN on non-FP type");
// If we're told that NaNs won't happen, assume they won't.
case Instruction::FAdd:
case Instruction::FSub:
// Adding positive and negative infinity produces NaN.
- return isKnownNeverNaN(Inst->getOperand(0), TLI, Depth + 1) &&
- isKnownNeverNaN(Inst->getOperand(1), TLI, Depth + 1) &&
- (isKnownNeverInfinity(Inst->getOperand(0), TLI, Depth + 1) ||
- isKnownNeverInfinity(Inst->getOperand(1), TLI, Depth + 1));
+ return isKnownNeverNaN(Inst->getOperand(0), DL, TLI, Depth + 1) &&
+ isKnownNeverNaN(Inst->getOperand(1), DL, TLI, Depth + 1) &&
+ (isKnownNeverInfinity(Inst->getOperand(0), DL, TLI, Depth + 1) ||
+ isKnownNeverInfinity(Inst->getOperand(1), DL, TLI, Depth + 1));
case Instruction::FMul:
// Zero multiplied with infinity produces NaN.
// FIXME: If neither side can be zero fmul never produces NaN.
- return isKnownNeverNaN(Inst->getOperand(0), TLI, Depth + 1) &&
- isKnownNeverInfinity(Inst->getOperand(0), TLI, Depth + 1) &&
- isKnownNeverNaN(Inst->getOperand(1), TLI, Depth + 1) &&
- isKnownNeverInfinity(Inst->getOperand(1), TLI, Depth + 1);
+ return isKnownNeverNaN(Inst->getOperand(0), DL, TLI, Depth + 1) &&
+ isKnownNeverInfinity(Inst->getOperand(0), DL, TLI, Depth + 1) &&
+ isKnownNeverNaN(Inst->getOperand(1), DL, TLI, Depth + 1) &&
+ isKnownNeverInfinity(Inst->getOperand(1), DL, TLI, Depth + 1);
case Instruction::FDiv:
case Instruction::FRem:
return false;
case Instruction::Select: {
- return isKnownNeverNaN(Inst->getOperand(1), TLI, Depth + 1) &&
- isKnownNeverNaN(Inst->getOperand(2), TLI, Depth + 1);
+ return isKnownNeverNaN(Inst->getOperand(1), DL, TLI, Depth + 1) &&
+ isKnownNeverNaN(Inst->getOperand(2), DL, TLI, Depth + 1);
}
case Instruction::SIToFP:
case Instruction::UIToFP:
case Instruction::FPTrunc:
case Instruction::FPExt:
case Instruction::FNeg:
- return isKnownNeverNaN(Inst->getOperand(0), TLI, Depth + 1);
+ return isKnownNeverNaN(Inst->getOperand(0), DL, TLI, Depth + 1);
default:
break;
}
case Intrinsic::round:
case Intrinsic::roundeven:
case Intrinsic::arithmetic_fence:
- return isKnownNeverNaN(II->getArgOperand(0), TLI, Depth + 1);
+ return isKnownNeverNaN(II->getArgOperand(0), DL, TLI, Depth + 1);
case Intrinsic::sqrt:
- return isKnownNeverNaN(II->getArgOperand(0), TLI, Depth + 1) &&
- CannotBeOrderedLessThanZero(II->getArgOperand(0), TLI);
+ return isKnownNeverNaN(II->getArgOperand(0), DL, TLI, Depth + 1) &&
+ CannotBeOrderedLessThanZero(II->getArgOperand(0), DL, TLI);
case Intrinsic::minnum:
case Intrinsic::maxnum:
// If either operand is not NaN, the result is not NaN.
- return isKnownNeverNaN(II->getArgOperand(0), TLI, Depth + 1) ||
- isKnownNeverNaN(II->getArgOperand(1), TLI, Depth + 1);
+ return isKnownNeverNaN(II->getArgOperand(0), DL, TLI, Depth + 1) ||
+ isKnownNeverNaN(II->getArgOperand(1), DL, TLI, Depth + 1);
default:
return false;
}