1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 11:13:28 +01:00

[LVI] Use Optional instead of out parameter (NFC)

As suggested on D76788, this switches the LVI implementation to
return Optional<ValueLatticeElement> from various methods, instead
of passing in a ValueLatticeElement reference and returning a boolean.

Differential Revision: https://reviews.llvm.org/D78383
This commit is contained in:
Nikita Popov 2020-04-09 21:13:03 +02:00
parent 3e13a16ca5
commit 810d61807e

View File

@ -211,21 +211,18 @@ namespace {
return ODI->second.count(V);
}
bool getCachedValueInfo(ValueLatticeElement &BBLV, Value *V,
BasicBlock *BB) const {
if (isOverdefined(V, BB)) {
BBLV = ValueLatticeElement::getOverdefined();
return true;
}
Optional<ValueLatticeElement> getCachedValueInfo(Value *V,
BasicBlock *BB) const {
if (isOverdefined(V, BB))
return ValueLatticeElement::getOverdefined();
auto I = ValueCache.find_as(V);
if (I == ValueCache.end())
return false;
return None;
auto BBI = I->second->BlockVals.find(BB);
if (BBI == I->second->BlockVals.end())
return false;
BBLV = BBI->second;
return true;
return None;
return BBI->second;
}
/// clear - Empty the cache.
@ -402,40 +399,39 @@ namespace {
DominatorTree *DT; ///< An optional DT pointer.
DominatorTree *DisabledDT; ///< Stores DT if it's disabled.
bool getBlockValue(ValueLatticeElement &Result, Value *Val, BasicBlock *BB);
bool getEdgeValue(Value *V, BasicBlock *F, BasicBlock *T,
ValueLatticeElement &Result, Instruction *CxtI = nullptr);
Optional<ValueLatticeElement> getBlockValue(Value *Val, BasicBlock *BB);
Optional<ValueLatticeElement> getEdgeValue(Value *V, BasicBlock *F,
BasicBlock *T, Instruction *CxtI = nullptr);
// These methods process one work item and may add more. A false value
// returned means that the work item was not completely processed and must
// be revisited after going through the new items.
bool solveBlockValue(Value *Val, BasicBlock *BB);
bool solveBlockValueImpl(ValueLatticeElement &Res, Value *Val,
BasicBlock *BB);
bool solveBlockValueNonLocal(ValueLatticeElement &BBLV, Value *Val,
BasicBlock *BB);
bool solveBlockValuePHINode(ValueLatticeElement &BBLV, PHINode *PN,
BasicBlock *BB);
bool solveBlockValueSelect(ValueLatticeElement &BBLV, SelectInst *S,
BasicBlock *BB);
Optional<ValueLatticeElement> solveBlockValueImpl(Value *Val, BasicBlock *BB);
Optional<ValueLatticeElement> solveBlockValueNonLocal(Value *Val,
BasicBlock *BB);
Optional<ValueLatticeElement> solveBlockValuePHINode(PHINode *PN,
BasicBlock *BB);
Optional<ValueLatticeElement> solveBlockValueSelect(SelectInst *S,
BasicBlock *BB);
Optional<ConstantRange> getRangeForOperand(unsigned Op, Instruction *I,
BasicBlock *BB);
bool solveBlockValueBinaryOpImpl(
ValueLatticeElement &BBLV, Instruction *I, BasicBlock *BB,
Optional<ValueLatticeElement> solveBlockValueBinaryOpImpl(
Instruction *I, BasicBlock *BB,
std::function<ConstantRange(const ConstantRange &,
const ConstantRange &)> OpFn);
bool solveBlockValueBinaryOp(ValueLatticeElement &BBLV, BinaryOperator *BBI,
BasicBlock *BB);
bool solveBlockValueCast(ValueLatticeElement &BBLV, CastInst *CI,
BasicBlock *BB);
bool solveBlockValueOverflowIntrinsic(
ValueLatticeElement &BBLV, WithOverflowInst *WO, BasicBlock *BB);
bool solveBlockValueSaturatingIntrinsic(ValueLatticeElement &BBLV,
SaturatingInst *SI, BasicBlock *BB);
bool solveBlockValueIntrinsic(ValueLatticeElement &BBLV, IntrinsicInst *II,
BasicBlock *BB);
bool solveBlockValueExtractValue(ValueLatticeElement &BBLV,
ExtractValueInst *EVI, BasicBlock *BB);
Optional<ValueLatticeElement> solveBlockValueBinaryOp(BinaryOperator *BBI,
BasicBlock *BB);
Optional<ValueLatticeElement> solveBlockValueCast(CastInst *CI,
BasicBlock *BB);
Optional<ValueLatticeElement> solveBlockValueOverflowIntrinsic(
WithOverflowInst *WO, BasicBlock *BB);
Optional<ValueLatticeElement> solveBlockValueSaturatingIntrinsic(
SaturatingInst *SI, BasicBlock *BB);
Optional<ValueLatticeElement> solveBlockValueIntrinsic(IntrinsicInst *II,
BasicBlock *BB);
Optional<ValueLatticeElement> solveBlockValueExtractValue(
ExtractValueInst *EVI, BasicBlock *BB);
void intersectAssumeOrGuardBlockValueConstantRange(Value *Val,
ValueLatticeElement &BBLV,
Instruction *BBI);
@ -540,12 +536,12 @@ void LazyValueInfoImpl::solve() {
// The work item was completely processed.
assert(BlockValueStack.back() == e && "Nothing should have been pushed!");
#ifndef NDEBUG
ValueLatticeElement BBLV;
assert(TheCache.getCachedValueInfo(BBLV, e.second, e.first) &&
"Result should be in cache!");
Optional<ValueLatticeElement> BBLV =
TheCache.getCachedValueInfo(e.second, e.first);
assert(BBLV && "Result should be in cache!");
LLVM_DEBUG(
dbgs() << "POP " << *e.second << " in " << e.first->getName() << " = "
<< BBLV << "\n");
<< *BBLV << "\n");
#endif
BlockValueStack.pop_back();
@ -557,25 +553,22 @@ void LazyValueInfoImpl::solve() {
}
}
bool LazyValueInfoImpl::getBlockValue(ValueLatticeElement &BBLV,
Value *Val, BasicBlock *BB) {
Optional<ValueLatticeElement> LazyValueInfoImpl::getBlockValue(Value *Val,
BasicBlock *BB) {
// If already a constant, there is nothing to compute.
if (Constant *VC = dyn_cast<Constant>(Val)) {
BBLV = ValueLatticeElement::get(VC);
return true;
}
if (Constant *VC = dyn_cast<Constant>(Val))
return ValueLatticeElement::get(VC);
if (TheCache.getCachedValueInfo(BBLV, Val, BB))
return true;
if (Optional<ValueLatticeElement> OptLatticeVal =
TheCache.getCachedValueInfo(Val, BB))
return OptLatticeVal;
// We have hit a cycle, assume overdefined.
if (!pushBlockValue({ BB, Val })) {
BBLV = ValueLatticeElement::getOverdefined();
return true;
}
if (!pushBlockValue({ BB, Val }))
return ValueLatticeElement::getOverdefined();
// Yet to be resolved.
return false;
return None;
}
static ValueLatticeElement getFromRangeMetadata(Instruction *BBI) {
@ -596,36 +589,32 @@ static ValueLatticeElement getFromRangeMetadata(Instruction *BBI) {
}
bool LazyValueInfoImpl::solveBlockValue(Value *Val, BasicBlock *BB) {
#ifndef NDEBUG
ValueLatticeElement BBLV;
assert(!isa<Constant>(Val) && "Value should not be constant");
assert(!TheCache.getCachedValueInfo(BBLV, Val, BB) &&
assert(!TheCache.getCachedValueInfo(Val, BB) &&
"Value should not be in cache");
#endif
// Hold off inserting this value into the Cache in case we have to return
// false and come back later.
ValueLatticeElement Res;
if (!solveBlockValueImpl(Res, Val, BB))
Optional<ValueLatticeElement> Res = solveBlockValueImpl(Val, BB);
if (!Res)
// Work pushed, will revisit
return false;
TheCache.insertResult(Val, BB, Res);
TheCache.insertResult(Val, BB, *Res);
return true;
}
bool LazyValueInfoImpl::solveBlockValueImpl(ValueLatticeElement &Res,
Value *Val, BasicBlock *BB) {
Optional<ValueLatticeElement> LazyValueInfoImpl::solveBlockValueImpl(
Value *Val, BasicBlock *BB) {
Instruction *BBI = dyn_cast<Instruction>(Val);
if (!BBI || BBI->getParent() != BB)
return solveBlockValueNonLocal(Res, Val, BB);
return solveBlockValueNonLocal(Val, BB);
if (PHINode *PN = dyn_cast<PHINode>(BBI))
return solveBlockValuePHINode(Res, PN, BB);
return solveBlockValuePHINode(PN, BB);
if (auto *SI = dyn_cast<SelectInst>(BBI))
return solveBlockValueSelect(Res, SI, BB);
return solveBlockValueSelect(SI, BB);
// If this value is a nonnull pointer, record it's range and bailout. Note
// that for all other pointer typed values, we terminate the search at the
@ -637,28 +626,26 @@ bool LazyValueInfoImpl::solveBlockValueImpl(ValueLatticeElement &Res,
// instruction is placed, even if it could legally be hoisted much higher.
// That is unfortunate.
PointerType *PT = dyn_cast<PointerType>(BBI->getType());
if (PT && isKnownNonZero(BBI, DL)) {
Res = ValueLatticeElement::getNot(ConstantPointerNull::get(PT));
return true;
}
if (PT && isKnownNonZero(BBI, DL))
return ValueLatticeElement::getNot(ConstantPointerNull::get(PT));
if (BBI->getType()->isIntegerTy()) {
if (auto *CI = dyn_cast<CastInst>(BBI))
return solveBlockValueCast(Res, CI, BB);
return solveBlockValueCast(CI, BB);
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(BBI))
return solveBlockValueBinaryOp(Res, BO, BB);
return solveBlockValueBinaryOp(BO, BB);
if (auto *EVI = dyn_cast<ExtractValueInst>(BBI))
return solveBlockValueExtractValue(Res, EVI, BB);
return solveBlockValueExtractValue(EVI, BB);
if (auto *II = dyn_cast<IntrinsicInst>(BBI))
return solveBlockValueIntrinsic(Res, II, BB);
return solveBlockValueIntrinsic(II, BB);
}
LLVM_DEBUG(dbgs() << " compute BB '" << BB->getName()
<< "' - unknown inst def found.\n");
Res = getFromRangeMetadata(BBI);
return true;
return getFromRangeMetadata(BBI);
}
static bool InstructionDereferencesPointer(Instruction *I, Value *Ptr) {
@ -710,8 +697,8 @@ static bool isObjectDereferencedInBlock(Value *Val, BasicBlock *BB) {
return false;
}
bool LazyValueInfoImpl::solveBlockValueNonLocal(ValueLatticeElement &BBLV,
Value *Val, BasicBlock *BB) {
Optional<ValueLatticeElement> LazyValueInfoImpl::solveBlockValueNonLocal(
Value *Val, BasicBlock *BB) {
ValueLatticeElement Result; // Start Undefined.
// If this is the entry block, we must be asking about an argument. The
@ -724,13 +711,10 @@ bool LazyValueInfoImpl::solveBlockValueNonLocal(ValueLatticeElement &BBLV,
if (PTy &&
(isKnownNonZero(Val, DL) ||
(isObjectDereferencedInBlock(Val, BB) &&
!NullPointerIsDefined(BB->getParent(), PTy->getAddressSpace())))) {
Result = ValueLatticeElement::getNot(ConstantPointerNull::get(PTy));
} else {
Result = ValueLatticeElement::getOverdefined();
}
BBLV = Result;
return true;
!NullPointerIsDefined(BB->getParent(), PTy->getAddressSpace()))))
return ValueLatticeElement::getNot(ConstantPointerNull::get(PTy));
else
return ValueLatticeElement::getOverdefined();
}
// Loop over all of our predecessors, merging what we know from them into
@ -743,12 +727,12 @@ bool LazyValueInfoImpl::solveBlockValueNonLocal(ValueLatticeElement &BBLV,
// canonicalizing to make this true rather than relying on this happy
// accident.
for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) {
ValueLatticeElement EdgeResult;
if (!getEdgeValue(Val, *PI, BB, EdgeResult))
Optional<ValueLatticeElement> EdgeResult = getEdgeValue(Val, *PI, BB);
if (!EdgeResult)
// Explore that input, then return here
return false;
return None;
Result.mergeIn(EdgeResult);
Result.mergeIn(*EdgeResult);
// If we hit overdefined, exit early. The BlockVals entry is already set
// to overdefined.
@ -763,19 +747,17 @@ bool LazyValueInfoImpl::solveBlockValueNonLocal(ValueLatticeElement &BBLV,
Result = ValueLatticeElement::getNot(ConstantPointerNull::get(PTy));
}
BBLV = Result;
return true;
return Result;
}
}
// Return the merged value, which is more precise than 'overdefined'.
assert(!Result.isOverdefined());
BBLV = Result;
return true;
return Result;
}
bool LazyValueInfoImpl::solveBlockValuePHINode(ValueLatticeElement &BBLV,
PHINode *PN, BasicBlock *BB) {
Optional<ValueLatticeElement> LazyValueInfoImpl::solveBlockValuePHINode(
PHINode *PN, BasicBlock *BB) {
ValueLatticeElement Result; // Start Undefined.
// Loop over all of our predecessors, merging what we know from them into
@ -784,15 +766,16 @@ bool LazyValueInfoImpl::solveBlockValuePHINode(ValueLatticeElement &BBLV,
for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
BasicBlock *PhiBB = PN->getIncomingBlock(i);
Value *PhiVal = PN->getIncomingValue(i);
ValueLatticeElement EdgeResult;
// Note that we can provide PN as the context value to getEdgeValue, even
// though the results will be cached, because PN is the value being used as
// the cache key in the caller.
if (!getEdgeValue(PhiVal, PhiBB, BB, EdgeResult, PN))
Optional<ValueLatticeElement> EdgeResult =
getEdgeValue(PhiVal, PhiBB, BB, PN);
if (!EdgeResult)
// Explore that input, then return here
return false;
return None;
Result.mergeIn(EdgeResult);
Result.mergeIn(*EdgeResult);
// If we hit overdefined, exit early. The BlockVals entry is already set
// to overdefined.
@ -800,15 +783,13 @@ bool LazyValueInfoImpl::solveBlockValuePHINode(ValueLatticeElement &BBLV,
LLVM_DEBUG(dbgs() << " compute BB '" << BB->getName()
<< "' - overdefined because of pred (local).\n");
BBLV = Result;
return true;
return Result;
}
}
// Return the merged value, which is more precise than 'overdefined'.
assert(!Result.isOverdefined() && "Possible PHI in entry block?");
BBLV = Result;
return true;
return Result;
}
static ValueLatticeElement getValueFromCondition(Value *Val, Value *Cond,
@ -848,31 +829,30 @@ void LazyValueInfoImpl::intersectAssumeOrGuardBlockValueConstantRange(
}
}
bool LazyValueInfoImpl::solveBlockValueSelect(ValueLatticeElement &BBLV,
SelectInst *SI, BasicBlock *BB) {
Optional<ValueLatticeElement> LazyValueInfoImpl::solveBlockValueSelect(
SelectInst *SI, BasicBlock *BB) {
// Recurse on our inputs if needed
ValueLatticeElement TrueVal;
if (!getBlockValue(TrueVal, SI->getTrueValue(), BB))
return false;
Optional<ValueLatticeElement> OptTrueVal =
getBlockValue(SI->getTrueValue(), BB);
if (!OptTrueVal)
return None;
ValueLatticeElement &TrueVal = *OptTrueVal;
// If we hit overdefined, don't ask more queries. We want to avoid poisoning
// extra slots in the table if we can.
if (TrueVal.isOverdefined()) {
BBLV = ValueLatticeElement::getOverdefined();
return true;
}
if (TrueVal.isOverdefined())
return ValueLatticeElement::getOverdefined();
ValueLatticeElement FalseVal;
if (!getBlockValue(FalseVal, SI->getFalseValue(), BB))
return false;
Optional<ValueLatticeElement> OptFalseVal =
getBlockValue(SI->getFalseValue(), BB);
if (!OptFalseVal)
return None;
ValueLatticeElement &FalseVal = *OptFalseVal;
// If we hit overdefined, don't ask more queries. We want to avoid poisoning
// extra slots in the table if we can.
if (FalseVal.isOverdefined()) {
BBLV = ValueLatticeElement::getOverdefined();
return true;
}
if (FalseVal.isOverdefined())
return ValueLatticeElement::getOverdefined();
if (TrueVal.isConstantRange() && FalseVal.isConstantRange()) {
const ConstantRange &TrueCR = TrueVal.getConstantRange();
@ -898,37 +878,28 @@ bool LazyValueInfoImpl::solveBlockValueSelect(ValueLatticeElement &BBLV,
return TrueCR.umax(FalseCR);
};
}();
BBLV = ValueLatticeElement::getRange(
return ValueLatticeElement::getRange(
ResultCR, TrueVal.isConstantRangeIncludingUndef() |
FalseVal.isConstantRangeIncludingUndef());
return true;
}
if (SPR.Flavor == SPF_ABS) {
if (LHS == SI->getTrueValue()) {
BBLV = ValueLatticeElement::getRange(
if (LHS == SI->getTrueValue())
return ValueLatticeElement::getRange(
TrueCR.abs(), TrueVal.isConstantRangeIncludingUndef());
return true;
}
if (LHS == SI->getFalseValue()) {
BBLV = ValueLatticeElement::getRange(
if (LHS == SI->getFalseValue())
return ValueLatticeElement::getRange(
FalseCR.abs(), FalseVal.isConstantRangeIncludingUndef());
return true;
}
}
if (SPR.Flavor == SPF_NABS) {
ConstantRange Zero(APInt::getNullValue(TrueCR.getBitWidth()));
if (LHS == SI->getTrueValue()) {
BBLV = ValueLatticeElement::getRange(
if (LHS == SI->getTrueValue())
return ValueLatticeElement::getRange(
Zero.sub(TrueCR.abs()), FalseVal.isConstantRangeIncludingUndef());
return true;
}
if (LHS == SI->getFalseValue()) {
BBLV = ValueLatticeElement::getRange(
if (LHS == SI->getFalseValue())
return ValueLatticeElement::getRange(
Zero.sub(FalseCR.abs()), FalseVal.isConstantRangeIncludingUndef());
return true;
}
}
}
@ -983,20 +954,19 @@ bool LazyValueInfoImpl::solveBlockValueSelect(ValueLatticeElement &BBLV,
}
}
ValueLatticeElement Result; // Start Undefined.
Result.mergeIn(TrueVal);
ValueLatticeElement Result = TrueVal;
Result.mergeIn(FalseVal);
BBLV = Result;
return true;
return Result;
}
Optional<ConstantRange> LazyValueInfoImpl::getRangeForOperand(unsigned Op,
Instruction *I,
BasicBlock *BB) {
ValueLatticeElement Val;
if (!getBlockValue(Val, I->getOperand(Op), BB))
Optional<ValueLatticeElement> OptVal = getBlockValue(I->getOperand(Op), BB);
if (!OptVal)
return None;
ValueLatticeElement &Val = *OptVal;
intersectAssumeOrGuardBlockValueConstantRange(I->getOperand(Op), Val, I);
if (Val.isConstantRange())
return Val.getConstantRange();
@ -1006,15 +976,12 @@ Optional<ConstantRange> LazyValueInfoImpl::getRangeForOperand(unsigned Op,
return ConstantRange::getFull(OperandBitWidth);
}
bool LazyValueInfoImpl::solveBlockValueCast(ValueLatticeElement &BBLV,
CastInst *CI,
BasicBlock *BB) {
if (!CI->getOperand(0)->getType()->isSized()) {
// Without knowing how wide the input is, we can't analyze it in any useful
// way.
BBLV = ValueLatticeElement::getOverdefined();
return true;
}
Optional<ValueLatticeElement> LazyValueInfoImpl::solveBlockValueCast(
CastInst *CI, BasicBlock *BB) {
// Without knowing how wide the input is, we can't analyze it in any useful
// way.
if (!CI->getOperand(0)->getType()->isSized())
return ValueLatticeElement::getOverdefined();
// Filter out casts we don't know how to reason about before attempting to
// recurse on our operand. This can cut a long search short if we know we're
@ -1029,8 +996,7 @@ bool LazyValueInfoImpl::solveBlockValueCast(ValueLatticeElement &BBLV,
// Unhandled instructions are overdefined.
LLVM_DEBUG(dbgs() << " compute BB '" << BB->getName()
<< "' - overdefined (unknown cast).\n");
BBLV = ValueLatticeElement::getOverdefined();
return true;
return ValueLatticeElement::getOverdefined();
}
// Figure out the range of the LHS. If that fails, we still apply the
@ -1039,21 +1005,20 @@ bool LazyValueInfoImpl::solveBlockValueCast(ValueLatticeElement &BBLV,
Optional<ConstantRange> LHSRes = getRangeForOperand(0, CI, BB);
if (!LHSRes.hasValue())
// More work to do before applying this transfer rule.
return false;
ConstantRange LHSRange = LHSRes.getValue();
return None;
const ConstantRange &LHSRange = LHSRes.getValue();
const unsigned ResultBitWidth = CI->getType()->getIntegerBitWidth();
// NOTE: We're currently limited by the set of operations that ConstantRange
// can evaluate symbolically. Enhancing that set will allows us to analyze
// more definitions.
BBLV = ValueLatticeElement::getRange(LHSRange.castOp(CI->getOpcode(),
return ValueLatticeElement::getRange(LHSRange.castOp(CI->getOpcode(),
ResultBitWidth));
return true;
}
bool LazyValueInfoImpl::solveBlockValueBinaryOpImpl(
ValueLatticeElement &BBLV, Instruction *I, BasicBlock *BB,
Optional<ValueLatticeElement> LazyValueInfoImpl::solveBlockValueBinaryOpImpl(
Instruction *I, BasicBlock *BB,
std::function<ConstantRange(const ConstantRange &,
const ConstantRange &)> OpFn) {
// Figure out the ranges of the operands. If that fails, use a
@ -1064,26 +1029,22 @@ bool LazyValueInfoImpl::solveBlockValueBinaryOpImpl(
Optional<ConstantRange> RHSRes = getRangeForOperand(1, I, BB);
if (!LHSRes.hasValue() || !RHSRes.hasValue())
// More work to do before applying this transfer rule.
return false;
return None;
ConstantRange LHSRange = LHSRes.getValue();
ConstantRange RHSRange = RHSRes.getValue();
BBLV = ValueLatticeElement::getRange(OpFn(LHSRange, RHSRange));
return true;
const ConstantRange &LHSRange = LHSRes.getValue();
const ConstantRange &RHSRange = RHSRes.getValue();
return ValueLatticeElement::getRange(OpFn(LHSRange, RHSRange));
}
bool LazyValueInfoImpl::solveBlockValueBinaryOp(ValueLatticeElement &BBLV,
BinaryOperator *BO,
BasicBlock *BB) {
Optional<ValueLatticeElement> LazyValueInfoImpl::solveBlockValueBinaryOp(
BinaryOperator *BO, BasicBlock *BB) {
assert(BO->getOperand(0)->getType()->isSized() &&
"all operands to binary operators are sized");
if (BO->getOpcode() == Instruction::Xor) {
// Xor is the only operation not supported by ConstantRange::binaryOp().
LLVM_DEBUG(dbgs() << " compute BB '" << BB->getName()
<< "' - overdefined (unknown binary operator).\n");
BBLV = ValueLatticeElement::getOverdefined();
return true;
return ValueLatticeElement::getOverdefined();
}
if (auto *OBO = dyn_cast<OverflowingBinaryOperator>(BO)) {
@ -1094,47 +1055,49 @@ bool LazyValueInfoImpl::solveBlockValueBinaryOp(ValueLatticeElement &BBLV,
NoWrapKind |= OverflowingBinaryOperator::NoSignedWrap;
return solveBlockValueBinaryOpImpl(
BBLV, BO, BB,
BO, BB,
[BO, NoWrapKind](const ConstantRange &CR1, const ConstantRange &CR2) {
return CR1.overflowingBinaryOp(BO->getOpcode(), CR2, NoWrapKind);
});
}
return solveBlockValueBinaryOpImpl(
BBLV, BO, BB, [BO](const ConstantRange &CR1, const ConstantRange &CR2) {
BO, BB, [BO](const ConstantRange &CR1, const ConstantRange &CR2) {
return CR1.binaryOp(BO->getOpcode(), CR2);
});
}
bool LazyValueInfoImpl::solveBlockValueOverflowIntrinsic(
ValueLatticeElement &BBLV, WithOverflowInst *WO, BasicBlock *BB) {
return solveBlockValueBinaryOpImpl(BBLV, WO, BB,
[WO](const ConstantRange &CR1, const ConstantRange &CR2) {
Optional<ValueLatticeElement>
LazyValueInfoImpl::solveBlockValueOverflowIntrinsic(WithOverflowInst *WO,
BasicBlock *BB) {
return solveBlockValueBinaryOpImpl(
WO, BB, [WO](const ConstantRange &CR1, const ConstantRange &CR2) {
return CR1.binaryOp(WO->getBinaryOp(), CR2);
});
}
bool LazyValueInfoImpl::solveBlockValueSaturatingIntrinsic(
ValueLatticeElement &BBLV, SaturatingInst *SI, BasicBlock *BB) {
Optional<ValueLatticeElement>
LazyValueInfoImpl::solveBlockValueSaturatingIntrinsic(SaturatingInst *SI,
BasicBlock *BB) {
switch (SI->getIntrinsicID()) {
case Intrinsic::uadd_sat:
return solveBlockValueBinaryOpImpl(
BBLV, SI, BB, [](const ConstantRange &CR1, const ConstantRange &CR2) {
SI, BB, [](const ConstantRange &CR1, const ConstantRange &CR2) {
return CR1.uadd_sat(CR2);
});
case Intrinsic::usub_sat:
return solveBlockValueBinaryOpImpl(
BBLV, SI, BB, [](const ConstantRange &CR1, const ConstantRange &CR2) {
SI, BB, [](const ConstantRange &CR1, const ConstantRange &CR2) {
return CR1.usub_sat(CR2);
});
case Intrinsic::sadd_sat:
return solveBlockValueBinaryOpImpl(
BBLV, SI, BB, [](const ConstantRange &CR1, const ConstantRange &CR2) {
SI, BB, [](const ConstantRange &CR1, const ConstantRange &CR2) {
return CR1.sadd_sat(CR2);
});
case Intrinsic::ssub_sat:
return solveBlockValueBinaryOpImpl(
BBLV, SI, BB, [](const ConstantRange &CR1, const ConstantRange &CR2) {
SI, BB, [](const ConstantRange &CR1, const ConstantRange &CR2) {
return CR1.ssub_sat(CR2);
});
default:
@ -1142,35 +1105,32 @@ bool LazyValueInfoImpl::solveBlockValueSaturatingIntrinsic(
}
}
bool LazyValueInfoImpl::solveBlockValueIntrinsic(ValueLatticeElement &BBLV,
IntrinsicInst *II,
BasicBlock *BB) {
Optional<ValueLatticeElement> LazyValueInfoImpl::solveBlockValueIntrinsic(
IntrinsicInst *II, BasicBlock *BB) {
if (auto *SI = dyn_cast<SaturatingInst>(II))
return solveBlockValueSaturatingIntrinsic(BBLV, SI, BB);
return solveBlockValueSaturatingIntrinsic(SI, BB);
LLVM_DEBUG(dbgs() << " compute BB '" << BB->getName()
<< "' - overdefined (unknown intrinsic).\n");
BBLV = ValueLatticeElement::getOverdefined();
return true;
return ValueLatticeElement::getOverdefined();
}
bool LazyValueInfoImpl::solveBlockValueExtractValue(
ValueLatticeElement &BBLV, ExtractValueInst *EVI, BasicBlock *BB) {
Optional<ValueLatticeElement> LazyValueInfoImpl::solveBlockValueExtractValue(
ExtractValueInst *EVI, BasicBlock *BB) {
if (auto *WO = dyn_cast<WithOverflowInst>(EVI->getAggregateOperand()))
if (EVI->getNumIndices() == 1 && *EVI->idx_begin() == 0)
return solveBlockValueOverflowIntrinsic(BBLV, WO, BB);
return solveBlockValueOverflowIntrinsic(WO, BB);
// Handle extractvalue of insertvalue to allow further simplification
// based on replaced with.overflow intrinsics.
if (Value *V = SimplifyExtractValueInst(
EVI->getAggregateOperand(), EVI->getIndices(),
EVI->getModule()->getDataLayout()))
return getBlockValue(BBLV, V, BB);
return getBlockValue(V, BB);
LLVM_DEBUG(dbgs() << " compute BB '" << BB->getName()
<< "' - overdefined (unknown extractvalue).\n");
BBLV = ValueLatticeElement::getOverdefined();
return true;
return ValueLatticeElement::getOverdefined();
}
static ValueLatticeElement getValueFromICmpCondition(Value *Val, ICmpInst *ICI,
@ -1362,8 +1322,9 @@ static ValueLatticeElement constantFoldUser(User *Usr, Value *Op,
/// Compute the value of Val on the edge BBFrom -> BBTo. Returns false if
/// Val is not constrained on the edge. Result is unspecified if return value
/// is false.
static bool getEdgeValueLocal(Value *Val, BasicBlock *BBFrom,
BasicBlock *BBTo, ValueLatticeElement &Result) {
static Optional<ValueLatticeElement> getEdgeValueLocal(Value *Val,
BasicBlock *BBFrom,
BasicBlock *BBTo) {
// TODO: Handle more complex conditionals. If (v == 0 || v2 < 1) is false, we
// know that v != 0.
if (BranchInst *BI = dyn_cast<BranchInst>(BBFrom->getTerminator())) {
@ -1378,17 +1339,16 @@ static bool getEdgeValueLocal(Value *Val, BasicBlock *BBFrom,
// If V is the condition of the branch itself, then we know exactly what
// it is.
if (Condition == Val) {
Result = ValueLatticeElement::get(ConstantInt::get(
if (Condition == Val)
return ValueLatticeElement::get(ConstantInt::get(
Type::getInt1Ty(Val->getContext()), isTrueDest));
return true;
}
// If the condition of the branch is an equality comparison, we may be
// able to infer the value.
Result = getValueFromCondition(Val, Condition, isTrueDest);
ValueLatticeElement Result = getValueFromCondition(Val, Condition,
isTrueDest);
if (!Result.isOverdefined())
return true;
return Result;
if (User *Usr = dyn_cast<User>(Val)) {
assert(Result.isOverdefined() && "Result isn't overdefined");
@ -1428,7 +1388,7 @@ static bool getEdgeValueLocal(Value *Val, BasicBlock *BBFrom,
}
}
if (!Result.isOverdefined())
return true;
return Result;
}
}
@ -1437,7 +1397,7 @@ static bool getEdgeValueLocal(Value *Val, BasicBlock *BBFrom,
if (SwitchInst *SI = dyn_cast<SwitchInst>(BBFrom->getTerminator())) {
Value *Condition = SI->getCondition();
if (!isa<IntegerType>(Val->getType()))
return false;
return None;
bool ValUsesConditionAndMayBeFoldable = false;
if (Condition != Val) {
// Check if Val has Condition as an operand.
@ -1445,7 +1405,7 @@ static bool getEdgeValueLocal(Value *Val, BasicBlock *BBFrom,
ValUsesConditionAndMayBeFoldable = isOperationFoldable(Usr) &&
usesOperand(Usr, Condition);
if (!ValUsesConditionAndMayBeFoldable)
return false;
return None;
}
assert((Condition == Val || ValUsesConditionAndMayBeFoldable) &&
"Condition != Val nor Val doesn't use Condition");
@ -1463,7 +1423,7 @@ static bool getEdgeValueLocal(Value *Val, BasicBlock *BBFrom,
ValueLatticeElement EdgeLatticeVal =
constantFoldUser(Usr, Condition, CaseValue, DL);
if (EdgeLatticeVal.isOverdefined())
return false;
return None;
EdgeVal = EdgeLatticeVal.getConstantRange();
}
if (DefaultCase) {
@ -1478,39 +1438,29 @@ static bool getEdgeValueLocal(Value *Val, BasicBlock *BBFrom,
} else if (Case.getCaseSuccessor() == BBTo)
EdgesVals = EdgesVals.unionWith(EdgeVal);
}
Result = ValueLatticeElement::getRange(std::move(EdgesVals));
return true;
return ValueLatticeElement::getRange(std::move(EdgesVals));
}
return false;
return None;
}
/// Compute the value of Val on the edge BBFrom -> BBTo or the value at
/// the basic block if the edge does not constrain Val.
bool LazyValueInfoImpl::getEdgeValue(Value *Val, BasicBlock *BBFrom,
BasicBlock *BBTo,
ValueLatticeElement &Result,
Instruction *CxtI) {
Optional<ValueLatticeElement> LazyValueInfoImpl::getEdgeValue(
Value *Val, BasicBlock *BBFrom, BasicBlock *BBTo, Instruction *CxtI) {
// If already a constant, there is nothing to compute.
if (Constant *VC = dyn_cast<Constant>(Val)) {
Result = ValueLatticeElement::get(VC);
return true;
}
if (Constant *VC = dyn_cast<Constant>(Val))
return ValueLatticeElement::get(VC);
ValueLatticeElement LocalResult;
if (!getEdgeValueLocal(Val, BBFrom, BBTo, LocalResult))
// If we couldn't constrain the value on the edge, LocalResult doesn't
// provide any information.
LocalResult = ValueLatticeElement::getOverdefined();
if (hasSingleValue(LocalResult)) {
ValueLatticeElement LocalResult = getEdgeValueLocal(Val, BBFrom, BBTo)
.getValueOr(ValueLatticeElement::getOverdefined());
if (hasSingleValue(LocalResult))
// Can't get any more precise here
Result = LocalResult;
return true;
}
return LocalResult;
ValueLatticeElement InBlock;
if (!getBlockValue(InBlock, Val, BBFrom))
return false;
Optional<ValueLatticeElement> OptInBlock = getBlockValue(Val, BBFrom);
if (!OptInBlock)
return None;
ValueLatticeElement &InBlock = *OptInBlock;
// Try to intersect ranges of the BB and the constraint on the edge.
intersectAssumeOrGuardBlockValueConstantRange(Val, InBlock,
@ -1525,8 +1475,7 @@ bool LazyValueInfoImpl::getEdgeValue(Value *Val, BasicBlock *BBFrom,
// but then the result is not cached.
intersectAssumeOrGuardBlockValueConstantRange(Val, InBlock, CxtI);
Result = intersect(LocalResult, InBlock);
return true;
return intersect(LocalResult, InBlock);
}
ValueLatticeElement LazyValueInfoImpl::getValueInBlock(Value *V, BasicBlock *BB,
@ -1535,13 +1484,13 @@ ValueLatticeElement LazyValueInfoImpl::getValueInBlock(Value *V, BasicBlock *BB,
<< BB->getName() << "'\n");
assert(BlockValueStack.empty() && BlockValueSet.empty());
ValueLatticeElement Result;
if (!getBlockValue(Result, V, BB)) {
Optional<ValueLatticeElement> OptResult = getBlockValue(V, BB);
if (!OptResult) {
solve();
bool ValueAvailable = getBlockValue(Result, V, BB);
(void) ValueAvailable;
assert(ValueAvailable && "Value not available after solving");
OptResult = getBlockValue(V, BB);
assert(OptResult && "Value not available after solving");
}
ValueLatticeElement Result = *OptResult;
intersectAssumeOrGuardBlockValueConstantRange(V, Result, CxtI);
LLVM_DEBUG(dbgs() << " Result = " << Result << "\n");
@ -1571,16 +1520,15 @@ getValueOnEdge(Value *V, BasicBlock *FromBB, BasicBlock *ToBB,
<< FromBB->getName() << "' to '" << ToBB->getName()
<< "'\n");
ValueLatticeElement Result;
if (!getEdgeValue(V, FromBB, ToBB, Result, CxtI)) {
Optional<ValueLatticeElement> Result = getEdgeValue(V, FromBB, ToBB, CxtI);
if (!Result) {
solve();
bool WasFastQuery = getEdgeValue(V, FromBB, ToBB, Result, CxtI);
(void)WasFastQuery;
assert(WasFastQuery && "More work to do after problem solved?");
Result = getEdgeValue(V, FromBB, ToBB, CxtI);
assert(Result && "More work to do after problem solved?");
}
LLVM_DEBUG(dbgs() << " Result = " << Result << "\n");
return Result;
LLVM_DEBUG(dbgs() << " Result = " << *Result << "\n");
return *Result;
}
void LazyValueInfoImpl::threadEdge(BasicBlock *PredBB, BasicBlock *OldSucc,