}
}
+static LVILatticeVal intersect(LVILatticeVal A, LVILatticeVal B);
+
//===----------------------------------------------------------------------===//
// LazyValueInfoCache Decl
//===----------------------------------------------------------------------===//
SelectInst *S, BasicBlock *BB);
bool solveBlockValueConstantRange(LVILatticeVal &BBLV,
Instruction *BBI, BasicBlock *BB);
- void mergeAssumeBlockValueConstantRange(Value *Val, LVILatticeVal &BBLV,
+ void intersectAssumeBlockValueConstantRange(Value *Val, LVILatticeVal &BBLV,
Instruction *BBI);
void solve();
}
break;
};
- // Nothing known - Note that we do not want overdefined here. We may know
- // something else about the value and not having range metadata shouldn't
- // cause us to throw away those facts.
- return LVILatticeVal();
+ // Nothing known - will be intersected with other facts
+ return LVILatticeVal::getOverdefined();
}
bool LazyValueInfoCache::solveBlockValue(Value *Val, BasicBlock *BB) {
return true;
}
- // If this is an instruction which supports range metadata, return the
- // implied range. TODO: This should be an intersection, not a union.
- Res.mergeIn(getFromRangeMetadata(BBI), DL);
+ // If this is an instruction which supports range metadata, intersect the
+ // implied range.
+ Res = intersect(Res, getFromRangeMetadata(BBI));
// We can only analyze the definitions of certain classes of instructions
// (integral binops and casts at the moment), so bail if this isn't one.
LVILatticeVal &Result,
bool isTrueDest = true);
-// If we can determine a constant range for the value Val in the context
-// provided by the instruction BBI, then merge it into BBLV. If we did find a
-// constant range, return true.
-void LazyValueInfoCache::mergeAssumeBlockValueConstantRange(Value *Val,
+// If we can determine a constraint on the value given conditions assumed by
+// the program, intersect those constraints with BBLV
+void LazyValueInfoCache::intersectAssumeBlockValueConstantRange(Value *Val,
LVILatticeVal &BBLV,
Instruction *BBI) {
BBI = BBI ? BBI : dyn_cast<Instruction>(Val);
Value *C = I->getArgOperand(0);
if (ICmpInst *ICI = dyn_cast<ICmpInst>(C)) {
LVILatticeVal Result;
- if (getValueFromFromCondition(Val, ICI, Result)) {
- if (BBLV.isOverdefined())
- BBLV = Result;
- else
- BBLV.mergeIn(Result, DL);
- }
+ if (getValueFromFromCondition(Val, ICI, Result))
+ BBLV = intersect(BBLV, Result);
}
}
}
}
LVILatticeVal LHSVal = getBlockValue(BBI->getOperand(0), BB);
- mergeAssumeBlockValueConstantRange(BBI->getOperand(0), LHSVal, BBI);
+ intersectAssumeBlockValueConstantRange(BBI->getOperand(0), LHSVal, BBI);
if (!LHSVal.isConstantRange()) {
BBLV.markOverdefined();
return true;
// Try to intersect ranges of the BB and the constraint on the edge.
LVILatticeVal InBlock = getBlockValue(Val, BBFrom);
- mergeAssumeBlockValueConstantRange(Val, InBlock, BBFrom->getTerminator());
+ intersectAssumeBlockValueConstantRange(Val, InBlock, BBFrom->getTerminator());
// We can use the context instruction (generically the ultimate instruction
// the calling pass is trying to simplify) here, even though the result of
// this function is generally cached when called from the solve* functions
// functions, the context instruction is not provided. When called from
// LazyValueInfoCache::getValueOnEdge, the context instruction is provided,
// but then the result is not cached.
- mergeAssumeBlockValueConstantRange(Val, InBlock, CxtI);
+ intersectAssumeBlockValueConstantRange(Val, InBlock, CxtI);
Result = intersect(LocalResult, InBlock);
return true;
solve();
LVILatticeVal Result = getBlockValue(V, BB);
- mergeAssumeBlockValueConstantRange(V, Result, CxtI);
+ intersectAssumeBlockValueConstantRange(V, Result, CxtI);
DEBUG(dbgs() << " Result = " << Result << "\n");
return Result;
DEBUG(dbgs() << "LVI Getting value " << *V << " at '"
<< CxtI->getName() << "'\n");
- LVILatticeVal Result;
+ LVILatticeVal Result = LVILatticeVal::getOverdefined();
if (auto *I = dyn_cast<Instruction>(V))
Result = getFromRangeMetadata(I);
- mergeAssumeBlockValueConstantRange(V, Result, CxtI);
-
- // Note: What's actually happening here is that we're starting at overdefined
- // and then intersecting two different types of facts. The code is not
- // structured that way (FIXME), and we need to take particular care to not
- // let the undefined state escape since we have *not* proven the particular
- // value to be unreachable at the context instruction.
- if (Result.isUndefined())
- Result.markOverdefined();
+ intersectAssumeBlockValueConstantRange(V, Result, CxtI);
DEBUG(dbgs() << " Result = " << Result << "\n");
return Result;