[LVI] Apply transfer rule for overdefine inputs for binary operators

As pointed out by John Regehr over in http://reviews.llvm.org/D19485, LVI was being incredibly stupid about applying its transfer rules.  Rather than gathering local facts from the expression itself, it was simply giving up entirely if one of the inputs was overdefined.  This greatly impacts the precision of the overall analysis and makes it far more fragile as well.

This patch builds on 267609 which did the same thing for unary casts.

llvm-svn: 267620
This commit is contained in:
Philip Reames 2016-04-26 23:10:35 +00:00
parent c1b9d47b3b
commit 053c2a6f25
2 changed files with 42 additions and 14 deletions

View File

@ -1063,22 +1063,27 @@ bool LazyValueInfoCache::solveBlockValueCast(LVILatticeVal &BBLV,
bool LazyValueInfoCache::solveBlockValueBinaryOp(LVILatticeVal &BBLV,
Instruction *BBI,
BasicBlock *BB) {
// Figure out the range of the LHS. If that fails, bail.
if (!hasBlockValue(BBI->getOperand(0), BB)) {
if (pushBlockValue(std::make_pair(BB, BBI->getOperand(0))))
return false;
BBLV.markOverdefined();
return true;
}
LVILatticeVal LHSVal = getBlockValue(BBI->getOperand(0), BB);
intersectAssumeBlockValueConstantRange(BBI->getOperand(0), LHSVal, BBI);
if (!LHSVal.isConstantRange()) {
BBLV.markOverdefined();
return true;
assert(BBI->getOperand(0)->getType()->isSized() &&
"all operands to binary operators are sized");
// Figure out the range of the LHS. If that fails, use a conservative range,
// but apply the transfer rule anyways. This lets us pick up facts from
// expressions like "and i32 (call i32 @foo()), 32"
if (!hasBlockValue(BBI->getOperand(0), BB))
if (pushBlockValue(std::make_pair(BB, BBI->getOperand(0))))
// More work to do before applying this transfer rule.
return false;
const unsigned OperandBitWidth =
DL.getTypeSizeInBits(BBI->getOperand(0)->getType());
ConstantRange LHSRange = ConstantRange(OperandBitWidth);
if (hasBlockValue(BBI->getOperand(0), BB)) {
LVILatticeVal LHSVal = getBlockValue(BBI->getOperand(0), BB);
intersectAssumeBlockValueConstantRange(BBI->getOperand(0), LHSVal, BBI);
if (LHSVal.isConstantRange())
LHSRange = LHSVal.getConstantRange();
}
ConstantRange LHSRange = LHSVal.getConstantRange();
ConstantInt *RHS = cast<ConstantInt>(BBI->getOperand(1));
ConstantRange RHSRange = ConstantRange(RHS->getValue());

View File

@ -440,3 +440,26 @@ entry:
exit:
ret i1 %cmp
}
define i1 @and_unknown(i32 %a) {
; CHECK-LABEL: @and_unknown
; CHECK: ret i1 true
entry:
%and = and i32 %a, 128
%cmp = icmp sle i32 %and, 128
br label %exit
exit:
ret i1 %cmp
}
define i1 @lshr_unknown(i32 %a) {
; CHECK-LABEL: @lshr_unknown
; CHECK: ret i1 true
entry:
%and = lshr i32 %a, 30
%cmp = icmp sle i32 %and, 128
br label %exit
exit:
ret i1 %cmp
}