@@ -56,6 +56,11 @@ class MemoryBehaviorVisitor
56
56
// / The value we are attempting to discover memory behavior relative to.
57
57
SILValue V;
58
58
59
+ // / Cache either the address of the access corresponding to memory at 'V', or
60
+ // / 'V' itself if it isn't recognized as part of an access. The cached value
61
+ // / is always a valid SILValue.
62
+ SILValue cachedValueAddress;
63
+
59
64
Optional<bool > cachedIsLetValue;
60
65
61
66
// / The SILType of the value.
@@ -77,11 +82,21 @@ class MemoryBehaviorVisitor
77
82
return *TypedAccessTy;
78
83
}
79
84
85
+ // / If 'V' is an address projection within a formal access, return the
86
+ // / canonical address of the formal access. Otherwise, return 'V' itself,
87
+ // / which is either a reference or unknown pointer or address.
88
+ SILValue getValueAddress () {
89
+ if (!cachedValueAddress) {
90
+ cachedValueAddress = V->getType ().isAddress () ? getAccessedAddress (V) : V;
91
+ }
92
+ return cachedValueAddress;
93
+ }
94
+
80
95
// / Return true if 'V's accessed address is that of a let variables.
81
96
bool isLetValue () {
82
97
if (!cachedIsLetValue) {
83
98
cachedIsLetValue =
84
- V->getType ().isAddress () && isLetAddress (getAccessedAddress (V ));
99
+ V->getType ().isAddress () && isLetAddress (getValueAddress ( ));
85
100
}
86
101
return cachedIsLetValue.getValue ();
87
102
}
@@ -124,15 +139,11 @@ class MemoryBehaviorVisitor
124
139
125
140
MemBehavior visitBeginAccessInst (BeginAccessInst *beginAccess) {
126
141
switch (beginAccess->getAccessKind ()) {
127
- case SILAccessKind::Init:
128
142
case SILAccessKind::Deinit:
129
- // No address aliasing is expected for variable initialization or
130
- // deinitialization.
131
- if (stripAccessMarkers (beginAccess) != getAccessedAddress (V))
132
- return MemBehavior::None;
133
-
134
- return MemBehavior::MayWrite;
135
-
143
+ // A [deinit] only directly reads from the object. The fact that it frees
144
+ // memory is modeled more precisely by the release operations within the
145
+ // deinit scope. Therefore, handle it like a [read] here...
146
+ LLVM_FALLTHROUGH;
136
147
case SILAccessKind::Read:
137
148
if (!mayAlias (beginAccess->getSource ()))
138
149
return MemBehavior::None;
@@ -141,10 +152,14 @@ class MemoryBehaviorVisitor
141
152
142
153
case SILAccessKind::Modify:
143
154
if (isLetValue ()) {
144
- assert (stripAccessMarkers (beginAccess) != getAccessedAddress (V )
155
+ assert (stripAccessMarkers (beginAccess) != getValueAddress ( )
145
156
&& " let modification not allowed" );
146
157
return MemBehavior::None;
147
158
}
159
+ // [modify] has a special case for ignoring 'let's, but otherwise is
160
+ // identical to an [init]...
161
+ LLVM_FALLTHROUGH;
162
+ case SILAccessKind::Init:
148
163
if (!mayAlias (beginAccess->getSource ()))
149
164
return MemBehavior::None;
150
165
@@ -229,15 +244,15 @@ MemBehavior MemoryBehaviorVisitor::visitLoadInst(LoadInst *LI) {
229
244
return MemBehavior::None;
230
245
231
246
LLVM_DEBUG (llvm::dbgs () << " Could not prove that load inst does not alias "
232
- " pointer. Returning may read." );
247
+ " pointer. Returning may read.\n " );
233
248
return MemBehavior::MayRead;
234
249
}
235
250
236
251
MemBehavior MemoryBehaviorVisitor::visitStoreInst (StoreInst *SI) {
237
252
// No store besides the initialization of a "let"-variable
238
253
// can have any effect on the value of this "let" variable.
239
254
if (isLetValue ()
240
- && (getAccessedAddress (SI->getDest ()) != getAccessedAddress (V ))) {
255
+ && (getAccessedAddress (SI->getDest ()) != getValueAddress ( ))) {
241
256
return MemBehavior::None;
242
257
}
243
258
// If the store dest cannot alias the pointer in question, then the
0 commit comments