mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 18:54:02 +01:00
[Constant] add floating-point helpers for normal/finite-nz; NFC
...and delete the equivalent local functiona from InstCombine. These might be useful to other InstCombine files or other passes and makes FP queries more similar to integer constant queries. llvm-svn: 325398
This commit is contained in:
parent
ea1863ee2e
commit
eae6de7a63
@ -71,6 +71,14 @@ public:
|
|||||||
/// Return true if the value is the smallest signed value.
|
/// Return true if the value is the smallest signed value.
|
||||||
bool isMinSignedValue() const;
|
bool isMinSignedValue() const;
|
||||||
|
|
||||||
|
/// Return true if this is a finite and non-zero floating-point scalar
|
||||||
|
/// constant or a vector constant with all finite and non-zero elements.
|
||||||
|
bool isFiniteNonZeroFP() const;
|
||||||
|
|
||||||
|
/// Return true if this is a normal (as opposed to denormal) floating-point
|
||||||
|
/// scalar constant or a vector constant with all normal elements.
|
||||||
|
bool isNormalFP() const;
|
||||||
|
|
||||||
/// Return true if evaluation of this constant could trap. This is true for
|
/// Return true if evaluation of this constant could trap. This is true for
|
||||||
/// things like constant expressions that could divide by zero.
|
/// things like constant expressions that could divide by zero.
|
||||||
bool canTrap() const;
|
bool canTrap() const;
|
||||||
|
@ -202,6 +202,32 @@ bool Constant::isNotMinSignedValue() const {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Constant::isFiniteNonZeroFP() const {
|
||||||
|
if (auto *CFP = dyn_cast<ConstantFP>(this))
|
||||||
|
return CFP->getValueAPF().isFiniteNonZero();
|
||||||
|
if (!getType()->isVectorTy())
|
||||||
|
return false;
|
||||||
|
for (unsigned i = 0, e = getType()->getVectorNumElements(); i != e; ++i) {
|
||||||
|
auto *CFP = dyn_cast_or_null<ConstantFP>(this->getAggregateElement(i));
|
||||||
|
if (!CFP || !CFP->getValueAPF().isFiniteNonZero())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Constant::isNormalFP() const {
|
||||||
|
if (auto *CFP = dyn_cast<ConstantFP>(this))
|
||||||
|
return CFP->getValueAPF().isNormal();
|
||||||
|
if (!getType()->isVectorTy())
|
||||||
|
return false;
|
||||||
|
for (unsigned i = 0, e = getType()->getVectorNumElements(); i != e; ++i) {
|
||||||
|
auto *CFP = dyn_cast_or_null<ConstantFP>(this->getAggregateElement(i));
|
||||||
|
if (!CFP || !CFP->getValueAPF().isNormal())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/// Constructor to create a '0' constant of arbitrary type.
|
/// Constructor to create a '0' constant of arbitrary type.
|
||||||
Constant *Constant::getNullValue(Type *Ty) {
|
Constant *Constant::getNullValue(Type *Ty) {
|
||||||
switch (Ty->getTypeID()) {
|
switch (Ty->getTypeID()) {
|
||||||
|
@ -478,35 +478,6 @@ static void detectLog2OfHalf(Value *&Op, Value *&Y, IntrinsicInst *&Log2) {
|
|||||||
Y = I->getOperand(0);
|
Y = I->getOperand(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isFiniteNonZeroFp(Constant *C) {
|
|
||||||
if (C->getType()->isVectorTy()) {
|
|
||||||
for (unsigned I = 0, E = C->getType()->getVectorNumElements(); I != E;
|
|
||||||
++I) {
|
|
||||||
ConstantFP *CFP = dyn_cast_or_null<ConstantFP>(C->getAggregateElement(I));
|
|
||||||
if (!CFP || !CFP->getValueAPF().isFiniteNonZero())
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return isa<ConstantFP>(C) &&
|
|
||||||
cast<ConstantFP>(C)->getValueAPF().isFiniteNonZero();
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool isNormalFp(Constant *C) {
|
|
||||||
if (C->getType()->isVectorTy()) {
|
|
||||||
for (unsigned I = 0, E = C->getType()->getVectorNumElements(); I != E;
|
|
||||||
++I) {
|
|
||||||
ConstantFP *CFP = dyn_cast_or_null<ConstantFP>(C->getAggregateElement(I));
|
|
||||||
if (!CFP || !CFP->getValueAPF().isNormal())
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return isa<ConstantFP>(C) && cast<ConstantFP>(C)->getValueAPF().isNormal();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Helper function of InstCombiner::visitFMul(). Return true iff the given
|
/// Helper function of InstCombiner::visitFMul(). Return true iff the given
|
||||||
/// value is FMul or FDiv with one and only one operand being a finite-non-zero
|
/// value is FMul or FDiv with one and only one operand being a finite-non-zero
|
||||||
/// constant (i.e. not Zero/NaN/Infinity).
|
/// constant (i.e. not Zero/NaN/Infinity).
|
||||||
@ -514,7 +485,7 @@ static bool isFMulOrFDivWithConstant(Value *V) {
|
|||||||
Constant *C;
|
Constant *C;
|
||||||
return (match(V, m_FMul(m_Value(), m_Constant(C))) ||
|
return (match(V, m_FMul(m_Value(), m_Constant(C))) ||
|
||||||
match(V, m_FDiv(m_Value(), m_Constant(C))) ||
|
match(V, m_FDiv(m_Value(), m_Constant(C))) ||
|
||||||
match(V, m_FDiv(m_Constant(C), m_Value()))) && isFiniteNonZeroFp(C);
|
match(V, m_FDiv(m_Constant(C), m_Value()))) && C->isFiniteNonZeroFP();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// foldFMulConst() is a helper routine of InstCombiner::visitFMul().
|
/// foldFMulConst() is a helper routine of InstCombiner::visitFMul().
|
||||||
@ -538,7 +509,7 @@ Value *InstCombiner::foldFMulConst(Instruction *FMulOrDiv, Constant *C,
|
|||||||
// (X * C0) * C => X * (C0*C)
|
// (X * C0) * C => X * (C0*C)
|
||||||
if (FMulOrDiv->getOpcode() == Instruction::FMul) {
|
if (FMulOrDiv->getOpcode() == Instruction::FMul) {
|
||||||
Constant *F = ConstantExpr::getFMul(C1 ? C1 : C0, C);
|
Constant *F = ConstantExpr::getFMul(C1 ? C1 : C0, C);
|
||||||
if (isNormalFp(F))
|
if (F->isNormalFP())
|
||||||
R = BinaryOperator::CreateFMul(C1 ? Opnd0 : Opnd1, F);
|
R = BinaryOperator::CreateFMul(C1 ? Opnd0 : Opnd1, F);
|
||||||
} else {
|
} else {
|
||||||
if (C0) {
|
if (C0) {
|
||||||
@ -546,18 +517,18 @@ Value *InstCombiner::foldFMulConst(Instruction *FMulOrDiv, Constant *C,
|
|||||||
if (FMulOrDiv->hasOneUse()) {
|
if (FMulOrDiv->hasOneUse()) {
|
||||||
// It would otherwise introduce another div.
|
// It would otherwise introduce another div.
|
||||||
Constant *F = ConstantExpr::getFMul(C0, C);
|
Constant *F = ConstantExpr::getFMul(C0, C);
|
||||||
if (isNormalFp(F))
|
if (F->isNormalFP())
|
||||||
R = BinaryOperator::CreateFDiv(F, Opnd1);
|
R = BinaryOperator::CreateFDiv(F, Opnd1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// (X / C1) * C => X * (C/C1) if C/C1 is not a denormal
|
// (X / C1) * C => X * (C/C1) if C/C1 is not a denormal
|
||||||
Constant *F = ConstantExpr::getFDiv(C, C1);
|
Constant *F = ConstantExpr::getFDiv(C, C1);
|
||||||
if (isNormalFp(F)) {
|
if (F->isNormalFP()) {
|
||||||
R = BinaryOperator::CreateFMul(Opnd0, F);
|
R = BinaryOperator::CreateFMul(Opnd0, F);
|
||||||
} else {
|
} else {
|
||||||
// (X / C1) * C => X / (C1/C)
|
// (X / C1) * C => X / (C1/C)
|
||||||
Constant *F = ConstantExpr::getFDiv(C1, C);
|
Constant *F = ConstantExpr::getFDiv(C1, C);
|
||||||
if (isNormalFp(F))
|
if (F->isNormalFP())
|
||||||
R = BinaryOperator::CreateFDiv(Opnd0, F);
|
R = BinaryOperator::CreateFDiv(Opnd0, F);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -600,7 +571,7 @@ Instruction *InstCombiner::visitFMul(BinaryOperator &I) {
|
|||||||
return RI;
|
return RI;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (AllowReassociate && isFiniteNonZeroFp(C)) {
|
if (AllowReassociate && C->isFiniteNonZeroFP()) {
|
||||||
// Let MDC denote an expression in one of these forms:
|
// Let MDC denote an expression in one of these forms:
|
||||||
// X * C, C/X, X/C, where C is a constant.
|
// X * C, C/X, X/C, where C is a constant.
|
||||||
//
|
//
|
||||||
@ -625,11 +596,11 @@ Instruction *InstCombiner::visitFMul(BinaryOperator &I) {
|
|||||||
Swap = true;
|
Swap = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (C1 && isFiniteNonZeroFp(C1) && isFMulOrFDivWithConstant(Opnd0)) {
|
if (C1 && C1->isFiniteNonZeroFP() && isFMulOrFDivWithConstant(Opnd0)) {
|
||||||
Value *M1 = ConstantExpr::getFMul(C1, C);
|
Value *M1 = ConstantExpr::getFMul(C1, C);
|
||||||
Value *M0 = isNormalFp(cast<Constant>(M1)) ?
|
Value *M0 = cast<Constant>(M1)->isNormalFP() ?
|
||||||
foldFMulConst(cast<Instruction>(Opnd0), C, &I) :
|
foldFMulConst(cast<Instruction>(Opnd0), C, &I) :
|
||||||
nullptr;
|
nullptr;
|
||||||
if (M0 && M1) {
|
if (M0 && M1) {
|
||||||
if (Swap && FAddSub->getOpcode() == Instruction::FSub)
|
if (Swap && FAddSub->getOpcode() == Instruction::FSub)
|
||||||
std::swap(M0, M1);
|
std::swap(M0, M1);
|
||||||
@ -1380,12 +1351,12 @@ Instruction *InstCombiner::visitFDiv(BinaryOperator &I) {
|
|||||||
if (match(Op0, m_FMul(m_Value(X), m_Constant(C1)))) {
|
if (match(Op0, m_FMul(m_Value(X), m_Constant(C1)))) {
|
||||||
// (X*C1)/C2 => X * (C1/C2)
|
// (X*C1)/C2 => X * (C1/C2)
|
||||||
Constant *C = ConstantExpr::getFDiv(C1, C2);
|
Constant *C = ConstantExpr::getFDiv(C1, C2);
|
||||||
if (isNormalFp(C))
|
if (C->isNormalFP())
|
||||||
Res = BinaryOperator::CreateFMul(X, C);
|
Res = BinaryOperator::CreateFMul(X, C);
|
||||||
} else if (match(Op0, m_FDiv(m_Value(X), m_Constant(C1)))) {
|
} else if (match(Op0, m_FDiv(m_Value(X), m_Constant(C1)))) {
|
||||||
// (X/C1)/C2 => X /(C2*C1)
|
// (X/C1)/C2 => X /(C2*C1)
|
||||||
Constant *C = ConstantExpr::getFMul(C1, C2);
|
Constant *C = ConstantExpr::getFMul(C1, C2);
|
||||||
if (isNormalFp(C))
|
if (C->isNormalFP())
|
||||||
Res = BinaryOperator::CreateFDiv(X, C);
|
Res = BinaryOperator::CreateFDiv(X, C);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1415,7 +1386,7 @@ Instruction *InstCombiner::visitFDiv(BinaryOperator &I) {
|
|||||||
CreateDiv = false;
|
CreateDiv = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Fold && isNormalFp(Fold)) {
|
if (Fold && Fold->isNormalFP()) {
|
||||||
Instruction *R = CreateDiv ? BinaryOperator::CreateFDiv(Fold, X)
|
Instruction *R = CreateDiv ? BinaryOperator::CreateFDiv(Fold, X)
|
||||||
: BinaryOperator::CreateFMul(X, Fold);
|
: BinaryOperator::CreateFMul(X, Fold);
|
||||||
R->setFastMathFlags(I.getFastMathFlags());
|
R->setFastMathFlags(I.getFastMathFlags());
|
||||||
|
Loading…
Reference in New Issue
Block a user