diff options
author | Kuter Dinel <kuterdinel@gmail.com> | 2020-05-13 12:49:15 -0500 |
---|---|---|
committer | Johannes Doerfert <johannes@jdoerfert.de> | 2020-05-13 16:44:15 -0500 |
commit | e57807769b5c21dd06ee293ed7ebaa13f8914ba2 (patch) | |
tree | cac7c86aa1a0dc9351dd741e86ec6c3e6cba4c97 /llvm/lib/IR/Value.cpp | |
parent | d6e3e55c40a973e233b168c19b1f1718212b41a4 (diff) | |
download | llvm-e57807769b5c21dd06ee293ed7ebaa13f8914ba2.zip llvm-e57807769b5c21dd06ee293ed7ebaa13f8914ba2.tar.gz llvm-e57807769b5c21dd06ee293ed7ebaa13f8914ba2.tar.bz2 |
[Attributor] Use AAValueConstantRange to infer dereferencability.
Reviewed By: jdoerfert
Differential Revision: https://reviews.llvm.org/D76208
Diffstat (limited to 'llvm/lib/IR/Value.cpp')
-rw-r--r-- | llvm/lib/IR/Value.cpp | 23 |
1 files changed, 18 insertions, 5 deletions
diff --git a/llvm/lib/IR/Value.cpp b/llvm/lib/IR/Value.cpp index 015bf20..cf54740 100644 --- a/llvm/lib/IR/Value.cpp +++ b/llvm/lib/IR/Value.cpp @@ -599,9 +599,9 @@ const Value *Value::stripPointerCastsAndInvariantGroups() const { return stripPointerCastsAndOffsets<PSK_ZeroIndicesAndInvariantGroups>(this); } -const Value * -Value::stripAndAccumulateConstantOffsets(const DataLayout &DL, APInt &Offset, - bool AllowNonInbounds) const { +const Value *Value::stripAndAccumulateConstantOffsets( + const DataLayout &DL, APInt &Offset, bool AllowNonInbounds, + function_ref<bool(Value &, APInt &)> ExternalAnalysis) const { if (!getType()->isPtrOrPtrVectorTy()) return this; @@ -627,7 +627,7 @@ Value::stripAndAccumulateConstantOffsets(const DataLayout &DL, APInt &Offset, // of GEP's pointer type rather than the size of the original // pointer type. APInt GEPOffset(DL.getIndexTypeSizeInBits(V->getType()), 0); - if (!GEP->accumulateConstantOffset(DL, GEPOffset)) + if (!GEP->accumulateConstantOffset(DL, GEPOffset, ExternalAnalysis)) return V; // Stop traversal if the pointer offset wouldn't fit in the bit-width @@ -636,7 +636,20 @@ Value::stripAndAccumulateConstantOffsets(const DataLayout &DL, APInt &Offset, if (GEPOffset.getMinSignedBits() > BitWidth) return V; - Offset += GEPOffset.sextOrTrunc(BitWidth); + // External Analysis can return a result higher/lower than the value + // represents. We need to detect overflow/underflow. + APInt GEPOffsetST = GEPOffset.sextOrTrunc(BitWidth); + if (!ExternalAnalysis) { + Offset += GEPOffsetST; + } else { + bool Overflow = false; + APInt OldOffset = Offset; + Offset = Offset.sadd_ov(GEPOffsetST, Overflow); + if (Overflow) { + Offset = OldOffset; + return V; + } + } V = GEP->getPointerOperand(); } else if (Operator::getOpcode(V) == Instruction::BitCast || Operator::getOpcode(V) == Instruction::AddrSpaceCast) { |