llvm.org GIT mirror llvm / 91f4bc6
[Analysis] Make LocationSizes carry an 'imprecise' bit There are places where we need to merge multiple LocationSizes of different sizes into one, and get a sensible result. There are other places where we want to optimize aggressively based on the value of a LocationSizes (e.g. how can a store of four bytes be to an area of storage that's only two bytes large?) This patch makes LocationSize hold an 'imprecise' bit to note whether the LocationSize can be treated as an upper-bound and lower-bound for the size of a location, or just an upper-bound. This concludes the series of patches leading up to this. The most recent of which is r344108. Fixes PR36228. Differential Revision: https://reviews.llvm.org/D44748 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@344114 91177308-0d34-0410-b5e6-96231b3b80d8 George Burgess IV 11 months ago
9 changed file(s) with 286 addition(s) and 48 deletion(s). Raw diff Collapse all Expand all
5151 PointerRec **PrevInList = nullptr;
5252 PointerRec *NextInList = nullptr;
5353 AliasSet *AS = nullptr;
54 LocationSize Size = 0;
54 LocationSize Size = LocationSize::mapEmpty();
5555 AAMDNodes AAInfo;
56
57 // Whether the size for this record has been set at all. This makes no
58 // guarantees about the size being known.
59 bool isSizeSet() const { return Size != LocationSize::mapEmpty(); }
5660
5761 public:
5862 PointerRec(Value *V)
7074
7175 bool updateSizeAndAAInfo(LocationSize NewSize, const AAMDNodes &NewAAInfo) {
7276 bool SizeChanged = false;
73 if (NewSize > Size) {
74 Size = NewSize;
75 SizeChanged = true;
77 if (NewSize != Size) {
78 LocationSize OldSize = Size;
79 Size = isSizeSet() ? Size.unionWith(NewSize) : NewSize;
80 SizeChanged = OldSize != Size;
7681 }
7782
7883 if (AAInfo == DenseMapInfo::getEmptyKey())
9095 return SizeChanged;
9196 }
9297
93 LocationSize getSize() const { return Size; }
98 LocationSize getSize() const {
99 assert(isSizeSet() && "Getting an unset size!");
100 return Size;
101 }
94102
95103 /// Return the AAInfo, or null if there is no information or conflicting
96104 /// information.
3333 class TargetLibraryInfo;
3434
3535 // Represents the size of a MemoryLocation. Logically, it's an
36 // Optional.
37 //
38 // We plan to use it for more soon, but we're trying to transition to this brave
39 // new world in small, easily-reviewable pieces; please see D44748.
36 // Optional that also carries a bit to represent whether the integer
37 // it contains, N, is 'precise'. Precise, in this context, means that we know
38 // that the area of storage referenced by the given MemoryLocation must be
39 // precisely N bytes. An imprecise value is formed as the union of two or more
40 // precise values, and can conservatively represent all of the values unioned
41 // into it. Importantly, imprecise values are an *upper-bound* on the size of a
42 // MemoryLocation.
43 //
44 // Concretely, a precise MemoryLocation is (%p, 4) in
45 // store i32 0, i32* %p
46 //
47 // Since we know that %p must be at least 4 bytes large at this point.
48 // Otherwise, we have UB. An example of an imprecise MemoryLocation is (%p, 4)
49 // at the memcpy in
50 //
51 // %n = select i1 %foo, i64 1, i64 4
52 // call void @llvm.memcpy.p0i8.p0i8.i64(i8* %p, i8* %baz, i64 %n, i32 1,
53 // i1 false)
54 //
55 // ...Since we'll copy *up to* 4 bytes into %p, but we can't guarantee that
56 // we'll ever actually do so.
57 //
58 // If asked to represent a pathologically large value, this will degrade to
59 // None.
4060 class LocationSize {
4161 enum : uint64_t {
4262 Unknown = ~uint64_t(0),
63 ImpreciseBit = uint64_t(1) << 63,
4364 MapEmpty = Unknown - 1,
4465 MapTombstone = Unknown - 2,
4566
4667 // The maximum value we can represent without falling back to 'unknown'.
47 MaxValue = MapTombstone - 1,
68 MaxValue = (MapTombstone - 1) & ~ImpreciseBit,
4869 };
4970
5071 uint64_t Value;
5576
5677 constexpr LocationSize(uint64_t Raw, DirectConstruction): Value(Raw) {}
5778
79 static_assert(Unknown & ImpreciseBit, "Unknown is imprecise by definition.");
5880 public:
81 // FIXME: Migrate all users to construct via either `precise` or `upperBound`,
82 // to make it more obvious at the callsite the kind of size that they're
83 // providing.
84 //
85 // Since the overwhelming majority of users of this provide precise values,
86 // this assumes the provided value is precise.
5987 constexpr LocationSize(uint64_t Raw)
6088 : Value(Raw > MaxValue ? Unknown : Raw) {}
6189
6290 static LocationSize precise(uint64_t Value) { return LocationSize(Value); }
91
92 static LocationSize upperBound(uint64_t Value) {
93 // You can't go lower than 0, so give a precise result.
94 if (LLVM_UNLIKELY(Value == 0))
95 return precise(0);
96 if (LLVM_UNLIKELY(Value > MaxValue))
97 return unknown();
98 return LocationSize(Value | ImpreciseBit, Direct);
99 }
100
63101 constexpr static LocationSize unknown() {
64102 return LocationSize(Unknown, Direct);
65103 }
72110 return LocationSize(MapEmpty, Direct);
73111 }
74112
113 // Returns a LocationSize that can correctly represent either `*this` or
114 // `Other`.
115 LocationSize unionWith(LocationSize Other) const {
116 if (Other == *this)
117 return *this;
118
119 if (!hasValue() || !Other.hasValue())
120 return unknown();
121
122 return upperBound(std::max(getValue(), Other.getValue()));
123 }
124
75125 bool hasValue() const { return Value != Unknown; }
76126 uint64_t getValue() const {
77127 assert(hasValue() && "Getting value from an unknown LocationSize!");
78 return Value;
128 return Value & ~ImpreciseBit;
129 }
130
131 // Returns whether or not this value is precise. Note that if a value is
132 // precise, it's guaranteed to not be `unknown()`.
133 bool isPrecise() const {
134 return (Value & ImpreciseBit) == 0;
79135 }
80136
81137 bool operator==(const LocationSize &Other) const {
85141 bool operator!=(const LocationSize &Other) const {
86142 return !(*this == Other);
87143 }
144
145 // Ordering operators are not provided, since it's unclear if there's only one
146 // reasonable way to compare:
147 // - values that don't exist against values that do, and
148 // - precise values to imprecise values
88149
89150 void print(raw_ostream &OS) const;
90151
91152 // Returns an opaque value that represents this LocationSize. Cannot be
92153 // reliably converted back into a LocationSize.
93154 uint64_t toRaw() const { return Value; }
94
95 // NOTE: These comparison operators will go away with D44748. Please don't
96 // rely on them.
97 bool operator<(const LocationSize &Other) const {
98 return Value < Other.Value;
99 }
100
101 bool operator>(const LocationSize &Other) const {
102 return Other < *this;
103 }
104155 };
105156
106157 inline raw_ostream &operator<<(raw_ostream &OS, LocationSize Size) {
17141714 // If the size of one access is larger than the entire object on the other
17151715 // side, then we know such behavior is undefined and can assume no alias.
17161716 bool NullIsValidLocation = NullPointerIsDefined(&F);
1717 if ((V1Size != MemoryLocation::UnknownSize &&
1718 isObjectSmallerThan(O2, V1Size.getValue(), DL, TLI,
1719 NullIsValidLocation)) ||
1720 (V2Size != MemoryLocation::UnknownSize &&
1721 isObjectSmallerThan(O1, V2Size.getValue(), DL, TLI,
1722 NullIsValidLocation)))
1717 if ((V1Size.isPrecise() && isObjectSmallerThan(O2, V1Size.getValue(), DL, TLI,
1718 NullIsValidLocation)) ||
1719 (V2Size.isPrecise() && isObjectSmallerThan(O1, V2Size.getValue(), DL, TLI,
1720 NullIsValidLocation)))
17231721 return NoAlias;
17241722
17251723 // Check the cache before climbing up use-def chains. This also terminates
17771775 // If both pointers are pointing into the same object and one of them
17781776 // accesses the entire object, then the accesses must overlap in some way.
17791777 if (O1 == O2)
1780 if (V1Size != MemoryLocation::UnknownSize &&
1781 V2Size != MemoryLocation::UnknownSize &&
1778 if (V1Size.isPrecise() && V2Size.isPrecise() &&
17821779 (isObjectSize(O1, V1Size.getValue(), DL, TLI, NullIsValidLocation) ||
17831780 isObjectSize(O2, V2Size.getValue(), DL, TLI, NullIsValidLocation)))
17841781 return AliasCache[Locs] = PartialAlias;
11121112 // If we already have a cache entry for this CacheKey, we may need to do some
11131113 // work to reconcile the cache entry and the current query.
11141114 if (!Pair.second) {
1115 if (CacheInfo->Size < Loc.Size) {
1116 // The query's Size is greater than the cached one. Throw out the
1117 // cached data and proceed with the query at the greater size.
1118 CacheInfo->Pair = BBSkipFirstBlockPair();
1119 CacheInfo->Size = Loc.Size;
1120 for (auto &Entry : CacheInfo->NonLocalDeps)
1121 if (Instruction *Inst = Entry.getResult().getInst())
1122 RemoveFromReverseMap(ReverseNonLocalPtrDeps, Inst, CacheKey);
1123 CacheInfo->NonLocalDeps.clear();
1124 } else if (CacheInfo->Size > Loc.Size) {
1125 // This query's Size is less than the cached one. Conservatively restart
1126 // the query using the greater size.
1127 return getNonLocalPointerDepFromBB(
1128 QueryInst, Pointer, Loc.getWithNewSize(CacheInfo->Size), isLoad,
1129 StartBB, Result, Visited, SkipFirstBlock);
1115 if (CacheInfo->Size != Loc.Size) {
1116 bool ThrowOutEverything;
1117 if (CacheInfo->Size.hasValue() && Loc.Size.hasValue()) {
1118 // FIXME: We may be able to do better in the face of results with mixed
1119 // precision. We don't appear to get them in practice, though, so just
1120 // be conservative.
1121 ThrowOutEverything =
1122 CacheInfo->Size.isPrecise() != Loc.Size.isPrecise() ||
1123 CacheInfo->Size.getValue() < Loc.Size.getValue();
1124 } else {
1125 // For our purposes, unknown size > all others.
1126 ThrowOutEverything = !Loc.Size.hasValue();
1127 }
1128
1129 if (ThrowOutEverything) {
1130 // The query's Size is greater than the cached one. Throw out the
1131 // cached data and proceed with the query at the greater size.
1132 CacheInfo->Pair = BBSkipFirstBlockPair();
1133 CacheInfo->Size = Loc.Size;
1134 for (auto &Entry : CacheInfo->NonLocalDeps)
1135 if (Instruction *Inst = Entry.getResult().getInst())
1136 RemoveFromReverseMap(ReverseNonLocalPtrDeps, Inst, CacheKey);
1137 CacheInfo->NonLocalDeps.clear();
1138 } else {
1139 // This query's Size is less than the cached one. Conservatively restart
1140 // the query using the greater size.
1141 return getNonLocalPointerDepFromBB(
1142 QueryInst, Pointer, Loc.getWithNewSize(CacheInfo->Size), isLoad,
1143 StartBB, Result, Visited, SkipFirstBlock);
1144 }
11301145 }
11311146
11321147 // If the query's AATags are inconsistent with the cached one,
2525 OS << "mapEmpty";
2626 else if (*this == mapTombstone())
2727 OS << "mapTombstone";
28 else if (isPrecise())
29 OS << "precise(" << getValue() << ')';
2830 else
29 OS << "precise(" << getValue() << ')';
31 OS << "upperBound(" << getValue() << ')';
3032 }
3133
3234 MemoryLocation MemoryLocation::get(const LoadInst *LI) {
348348 InstOverlapIntervalsTy &IOL,
349349 AliasAnalysis &AA,
350350 const Function *F) {
351 // If we don't know the sizes of either access, then we can't do a comparison.
352 if (Later.Size == MemoryLocation::UnknownSize ||
353 Earlier.Size == MemoryLocation::UnknownSize)
351 // FIXME: Vet that this works for size upper-bounds. Seems unlikely that we'll
352 // get imprecise values here, though (except for unknown sizes).
353 if (!Later.Size.isPrecise() || !Earlier.Size.isPrecise())
354354 return OW_Unknown;
355355
356356 const uint64_t LaterSize = Later.Size.getValue();
0 ; RUN: opt -S -licm -o - %s | FileCheck %s
1 ;
2 ; Be sure that we don't hoist loads incorrectly if a loop has conditional UB.
3 ; See PR36228.
4
5 declare void @check(i8)
6 declare void @llvm.memcpy.p0i8.p0i8.i64(i8*, i8*, i64, i32, i1)
7
8 ; CHECK-LABEL: define void @buggy
9 define void @buggy(i8* %src, i1* %kOne) {
10 entry:
11 %dst = alloca [1 x i8], align 1
12 %0 = getelementptr inbounds [1 x i8], [1 x i8]* %dst, i64 0, i64 0
13 store i8 42, i8* %0, align 1
14 %src16 = bitcast i8* %src to i16*
15 %srcval = load i16, i16* %src16
16 br label %while.cond
17
18 while.cond: ; preds = %if.end, %entry
19 %dp.0 = phi i8* [ %0, %entry ], [ %dp.1, %if.end ]
20 %1 = load volatile i1, i1* %kOne, align 4
21 br i1 %1, label %if.else, label %if.then
22
23 if.then: ; preds = %while.cond
24 store i8 9, i8* %dp.0, align 1
25 br label %if.end
26
27 if.else: ; preds = %while.cond
28 call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dp.0, i8* %src, i64 2, i32 1, i1 false)
29 %dp.new = getelementptr inbounds i8, i8* %dp.0, i64 1
30 br label %if.end
31
32 if.end: ; preds = %if.else, %if.then
33 %dp.1 = phi i8* [ %dp.0, %if.then ], [ %dp.new, %if.else ]
34 ; CHECK: %2 = load i8, i8* %0
35 %2 = load i8, i8* %0, align 1
36 ; CHECK-NEXT: call void @check(i8 %2)
37 call void @check(i8 %2)
38 br label %while.cond
39 }
0 //===- BasicAliasAnalysisTest.cpp - Unit tests for BasicAA ----------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Targeted tests that are hard/convoluted to make happen with just `opt`.
10 //
11
12 #include "llvm/Analysis/BasicAliasAnalysis.h"
13 #include "llvm/Analysis/AliasAnalysis.h"
14 #include "llvm/AsmParser/Parser.h"
15 #include "llvm/IR/Dominators.h"
16 #include "llvm/IR/IRBuilder.h"
17 #include "llvm/IR/LLVMContext.h"
18 #include "llvm/IR/Module.h"
19 #include "llvm/Support/SourceMgr.h"
20 #include "gtest/gtest.h"
21
22 using namespace llvm;
23
24 // FIXME: This is duplicated between this file and MemorySSATest. Refactor.
25 const static char DLString[] = "e-i64:64-f80:128-n8:16:32:64-S128";
26
27 /// There's a lot of common setup between these tests. This fixture helps reduce
28 /// that. Tests should mock up a function, store it in F, and then call
29 /// setupAnalyses().
30 class BasicAATest : public testing::Test {
31 protected:
32 // N.B. Many of these members depend on each other (e.g. the Module depends on
33 // the Context, etc.). So, order matters here (and in TestAnalyses).
34 LLVMContext C;
35 Module M;
36 IRBuilder<> B;
37 DataLayout DL;
38 TargetLibraryInfoImpl TLII;
39 TargetLibraryInfo TLI;
40 Function *F;
41
42 // Things that we need to build after the function is created.
43 struct TestAnalyses {
44 DominatorTree DT;
45 AssumptionCache AC;
46 BasicAAResult BAA;
47
48 TestAnalyses(BasicAATest &Test)
49 : DT(*Test.F), AC(*Test.F), BAA(Test.DL, *Test.F, Test.TLI, AC, &DT) {}
50 };
51
52 llvm::Optional Analyses;
53
54 BasicAAResult &setupAnalyses() {
55 assert(F);
56 Analyses.emplace(*this);
57 return Analyses->BAA;
58 }
59
60 public:
61 BasicAATest()
62 : M("BasicAATest", C), B(C), DL(DLString), TLI(TLII), F(nullptr) {}
63 };
64
65 // Check that a function arg can't trivially alias a global when we're accessing
66 // >sizeof(global) bytes through that arg, unless the access size is just an
67 // upper-bound.
68 TEST_F(BasicAATest, AliasInstWithObjectOfImpreciseSize) {
69 F = Function::Create(
70 FunctionType::get(B.getVoidTy(), {B.getInt32Ty()->getPointerTo()}, false),
71 GlobalValue::ExternalLinkage, "F", &M);
72
73 BasicBlock *Entry(BasicBlock::Create(C, "", F));
74 B.SetInsertPoint(Entry);
75
76 Value *IncomingI32Ptr = F->arg_begin();
77
78 auto *GlobalPtr =
79 cast(M.getOrInsertGlobal("some_global", B.getInt8Ty()));
80
81 // Without sufficiently restricted linkage/an init, some of the object size
82 // checking bits get more conservative.
83 GlobalPtr->setLinkage(GlobalValue::LinkageTypes::InternalLinkage);
84 GlobalPtr->setInitializer(B.getInt8(0));
85
86 BasicAAResult &BasicAA = setupAnalyses();
87 ASSERT_EQ(
88 BasicAA.alias(MemoryLocation(IncomingI32Ptr, LocationSize::precise(4)),
89 MemoryLocation(GlobalPtr, LocationSize::precise(1))),
90 AliasResult::NoAlias);
91
92 ASSERT_EQ(
93 BasicAA.alias(MemoryLocation(IncomingI32Ptr, LocationSize::upperBound(4)),
94 MemoryLocation(GlobalPtr, LocationSize::precise(1))),
95 AliasResult::MayAlias);
96 }
97
98 // Check that we fall back to MayAlias if we see an access of an entire object
99 // that's just an upper-bound.
100 TEST_F(BasicAATest, AliasInstWithFullObjectOfImpreciseSize) {
101 F = Function::Create(
102 FunctionType::get(B.getVoidTy(), {B.getInt64Ty()}, false),
103 GlobalValue::ExternalLinkage, "F", &M);
104
105 BasicBlock *Entry(BasicBlock::Create(C, "", F));
106 B.SetInsertPoint(Entry);
107
108 Value *ArbitraryI32 = F->arg_begin();
109 AllocaInst *I8 = B.CreateAlloca(B.getInt8Ty(), B.getInt32(2));
110 auto *I8AtUncertainOffset =
111 cast(B.CreateGEP(I8, ArbitraryI32));
112
113 BasicAAResult &BasicAA = setupAnalyses();
114 ASSERT_EQ(BasicAA.alias(
115 MemoryLocation(I8, LocationSize::precise(2)),
116 MemoryLocation(I8AtUncertainOffset, LocationSize::precise(1))),
117 AliasResult::PartialAlias);
118
119 ASSERT_EQ(BasicAA.alias(
120 MemoryLocation(I8, LocationSize::upperBound(2)),
121 MemoryLocation(I8AtUncertainOffset, LocationSize::precise(1))),
122 AliasResult::MayAlias);
123 }
77 add_llvm_unittest(AnalysisTests
88 AliasAnalysisTest.cpp
99 AliasSetTrackerTest.cpp
10 BasicAliasAnalysisTest.cpp
1011 BlockFrequencyInfoTest.cpp
1112 BranchProbabilityInfoTest.cpp
1213 CallGraphTest.cpp