[llvm] [LVI][CVP] `getRangeFor` propagates `MayIncludeUndef` (PR #68190)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Oct 4 01:37:50 PDT 2023
https://github.com/DianQK created https://github.com/llvm/llvm-project/pull/68190
Fix mis-compilation encountered in https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/Implementing.20niche.20checks.
I'm still thinking about interface changes and test cases.
>From be2a22b1bb4da30a08753bb6f3601b42ac48abe0 Mon Sep 17 00:00:00 2001
From: DianQK <dianqk at dianqk.net>
Date: Wed, 4 Oct 2023 15:50:25 +0800
Subject: [PATCH] [LVI][CVP] `getRangeFor` propagates `MayIncludeUndef`
---
llvm/lib/Analysis/LazyValueInfo.cpp | 36 ++++++++++++++++++++---------
1 file changed, 25 insertions(+), 11 deletions(-)
diff --git a/llvm/lib/Analysis/LazyValueInfo.cpp b/llvm/lib/Analysis/LazyValueInfo.cpp
index 0892aa9d75fb417..8140b18d54e54d0 100644
--- a/llvm/lib/Analysis/LazyValueInfo.cpp
+++ b/llvm/lib/Analysis/LazyValueInfo.cpp
@@ -411,7 +411,8 @@ class LazyValueInfoImpl {
std::optional<ValueLatticeElement> solveBlockValueSelect(SelectInst *S,
BasicBlock *BB);
std::optional<ConstantRange> getRangeFor(Value *V, Instruction *CxtI,
- BasicBlock *BB);
+ BasicBlock *BB,
+ bool &MayIncludeUndef);
std::optional<ValueLatticeElement> solveBlockValueBinaryOpImpl(
Instruction *I, BasicBlock *BB,
std::function<ConstantRange(const ConstantRange &, const ConstantRange &)>
@@ -892,10 +893,14 @@ LazyValueInfoImpl::solveBlockValueSelect(SelectInst *SI, BasicBlock *BB) {
}
std::optional<ConstantRange>
-LazyValueInfoImpl::getRangeFor(Value *V, Instruction *CxtI, BasicBlock *BB) {
+LazyValueInfoImpl::getRangeFor(Value *V, Instruction *CxtI, BasicBlock *BB,
+ bool &MayIncludeUndef) {
std::optional<ValueLatticeElement> OptVal = getBlockValue(V, BB, CxtI);
if (!OptVal)
return std::nullopt;
+ // TODO: A better way to update MayIncludeUndef for multiple calls?
+ if (OptVal->isUndef() || OptVal->isConstantRangeIncludingUndef())
+ MayIncludeUndef = true;
return getConstantRangeOrFull(*OptVal, V->getType(), DL);
}
@@ -922,10 +927,12 @@ LazyValueInfoImpl::solveBlockValueCast(CastInst *CI, BasicBlock *BB) {
return ValueLatticeElement::getOverdefined();
}
+ bool MayIncludeUndef = false;
// Figure out the range of the LHS. If that fails, we still apply the
// transfer rule on the full set since we may be able to locally infer
// interesting facts.
- std::optional<ConstantRange> LHSRes = getRangeFor(CI->getOperand(0), CI, BB);
+ std::optional<ConstantRange> LHSRes =
+ getRangeFor(CI->getOperand(0), CI, BB, MayIncludeUndef);
if (!LHSRes)
// More work to do before applying this transfer rule.
return std::nullopt;
@@ -936,8 +943,8 @@ LazyValueInfoImpl::solveBlockValueCast(CastInst *CI, BasicBlock *BB) {
// 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.
- return ValueLatticeElement::getRange(LHSRange.castOp(CI->getOpcode(),
- ResultBitWidth));
+ return ValueLatticeElement::getRange(
+ LHSRange.castOp(CI->getOpcode(), ResultBitWidth), MayIncludeUndef);
}
std::optional<ValueLatticeElement>
@@ -949,15 +956,19 @@ LazyValueInfoImpl::solveBlockValueBinaryOpImpl(
// conservative range, but apply the transfer rule anyways. This
// lets us pick up facts from expressions like "and i32 (call i32
// @foo()), 32"
- std::optional<ConstantRange> LHSRes = getRangeFor(I->getOperand(0), I, BB);
- std::optional<ConstantRange> RHSRes = getRangeFor(I->getOperand(1), I, BB);
+ bool MayIncludeUndef = false;
+ std::optional<ConstantRange> LHSRes =
+ getRangeFor(I->getOperand(0), I, BB, MayIncludeUndef);
+ std::optional<ConstantRange> RHSRes =
+ getRangeFor(I->getOperand(1), I, BB, MayIncludeUndef);
if (!LHSRes || !RHSRes)
// More work to do before applying this transfer rule.
return std::nullopt;
const ConstantRange &LHSRange = *LHSRes;
const ConstantRange &RHSRange = *RHSRes;
- return ValueLatticeElement::getRange(OpFn(LHSRange, RHSRange));
+ return ValueLatticeElement::getRange(OpFn(LHSRange, RHSRange),
+ MayIncludeUndef);
}
std::optional<ValueLatticeElement>
@@ -1002,16 +1013,19 @@ LazyValueInfoImpl::solveBlockValueIntrinsic(IntrinsicInst *II, BasicBlock *BB) {
return MetadataVal;
}
+ bool MayIncludeUndef = false;
SmallVector<ConstantRange, 2> OpRanges;
for (Value *Op : II->args()) {
- std::optional<ConstantRange> Range = getRangeFor(Op, II, BB);
+ std::optional<ConstantRange> Range =
+ getRangeFor(Op, II, BB, MayIncludeUndef);
if (!Range)
return std::nullopt;
OpRanges.push_back(*Range);
}
- return intersect(ValueLatticeElement::getRange(ConstantRange::intrinsic(
- II->getIntrinsicID(), OpRanges)),
+ return intersect(ValueLatticeElement::getRange(
+ ConstantRange::intrinsic(II->getIntrinsicID(), OpRanges),
+ MayIncludeUndef),
MetadataVal);
}
More information about the llvm-commits
mailing list