Skip to content

Commit ecb745e

Browse files
authored
Merge pull request #80745 from gottesmm/rdar149019222
[rbi] Teach RBI how to handle non-Sendable bases of Sendable values
2 parents f5890ce + 23b6937 commit ecb745e

File tree

8 files changed

+1629
-483
lines changed

8 files changed

+1629
-483
lines changed

include/swift/SILOptimizer/Analysis/RegionAnalysis.h

+77-12
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ class BlockPartitionState {
108108

109109
class TrackableValue;
110110
class TrackableValueState;
111+
struct TrackableValueLookupResult;
111112

112113
enum class TrackableValueFlag {
113114
/// Base value that says a value is uniquely represented and is
@@ -272,6 +273,25 @@ class regionanalysisimpl::TrackableValue {
272273
}
273274
};
274275

276+
/// A class that contains both a lookup value as well as extra metadata about
277+
/// properties of the original value that we looked up up from that we
278+
/// discovered as we searched for the lookup value.
279+
struct regionanalysisimpl::TrackableValueLookupResult {
280+
/// The actual value that we are tracking.
281+
///
282+
/// If we are tracking a Sendable address that has a non-Sendable base, this
283+
/// will be an empty TrackableValue.
284+
TrackableValue value;
285+
286+
/// If we are tracking an address, this is the base trackable value that is
287+
/// being tracked. If the base is a Sendable value, then this will be an empty
288+
/// TrackableValue.
289+
std::optional<TrackableValue> base;
290+
291+
void print(llvm::raw_ostream &os) const;
292+
SWIFT_DEBUG_DUMP { print(llvm::dbgs()); }
293+
};
294+
275295
class RegionAnalysis;
276296

277297
class RegionAnalysisValueMap {
@@ -282,6 +302,8 @@ class RegionAnalysisValueMap {
282302
using Region = PartitionPrimitives::Region;
283303
using TrackableValue = regionanalysisimpl::TrackableValue;
284304
using TrackableValueState = regionanalysisimpl::TrackableValueState;
305+
using TrackableValueLookupResult =
306+
regionanalysisimpl::TrackableValueLookupResult;
285307

286308
private:
287309
/// A map from the representative of an equivalence class of values to their
@@ -301,30 +323,57 @@ class RegionAnalysisValueMap {
301323

302324
/// State that the value -> representative computation yields to us.
303325
struct UnderlyingTrackedValueInfo {
326+
/// The equivalence class value that we found that should be merged into
327+
/// regions.
328+
///
329+
/// Always set to a real value.
304330
SILValue value;
305331

306-
/// Only used for addresses.
307-
std::optional<ActorIsolation> actorIsolation;
332+
/// The actual base value that we found if we were looking for an address
333+
/// equivilance class and had a non-Sendable base. If we have an object or
334+
/// we do not have a separate base, this is SILValue().
335+
SILValue base;
308336

309-
explicit UnderlyingTrackedValueInfo(SILValue value) : value(value) {}
337+
/// Constructor for use if we only have either an object or an address
338+
/// equivalence class that involves a complete non-Sendable path.
339+
explicit UnderlyingTrackedValueInfo(SILValue value) : value(value), base() {
340+
assert(value);
341+
}
310342

311-
UnderlyingTrackedValueInfo() : value(), actorIsolation() {}
343+
/// Constructor for use with addresses only where we have either:
344+
///
345+
/// 1. A sendable address that is used but that has a non-Sendable base that
346+
/// we have to insert requires for.
347+
///
348+
/// 2. A non-Sendable address that is used but that has a separate
349+
/// non-Sendable base due to an access path chain that has a split in
350+
/// between the two due to the non-Sendable address being projected out of
351+
/// an intervening sendable struct. The struct can be Sendable due to things
352+
/// like being global actor isolated or by being marked @unchecked Sendable.
353+
explicit UnderlyingTrackedValueInfo(SILValue value, SILValue base)
354+
: value(value), base(base) {
355+
assert(value);
356+
assert(base);
357+
}
358+
UnderlyingTrackedValueInfo() : value(), base() {}
312359

313360
UnderlyingTrackedValueInfo(const UnderlyingTrackedValueInfo &newVal)
314-
: value(newVal.value), actorIsolation(newVal.actorIsolation) {}
361+
: value(newVal.value), base(newVal.base) {}
315362

316363
UnderlyingTrackedValueInfo &
317364
operator=(const UnderlyingTrackedValueInfo &newVal) {
318365
value = newVal.value;
319-
actorIsolation = newVal.actorIsolation;
366+
base = newVal.base;
320367
return *this;
321368
}
322369

323-
UnderlyingTrackedValueInfo(SILValue value,
324-
std::optional<ActorIsolation> actorIsolation)
325-
: value(value), actorIsolation(actorIsolation) {}
326-
327370
operator bool() const { return value; }
371+
372+
void print(llvm::raw_ostream &os) const;
373+
SWIFT_DEBUG_DUMP {
374+
print(llvm::dbgs());
375+
llvm::dbgs() << '\n';
376+
}
328377
};
329378

330379
/// A map from a SILValue to its equivalence class representative.
@@ -363,10 +412,16 @@ class RegionAnalysisValueMap {
363412
void print(llvm::raw_ostream &os) const;
364413
SWIFT_DEBUG_DUMP { print(llvm::dbgs()); }
365414

366-
TrackableValue
415+
TrackableValueLookupResult
367416
getTrackableValue(SILValue value,
368417
bool isAddressCapturedByPartialApply = false) const;
369418

419+
private:
420+
TrackableValue
421+
getTrackableValueHelper(SILValue value,
422+
bool isAddressCapturedByPartialApply = false) const;
423+
424+
public:
370425
/// An actor introducing inst is an instruction that doesn't have any
371426
/// non-Sendable parameters and produces a new value that has to be actor
372427
/// isolated.
@@ -378,7 +433,8 @@ class RegionAnalysisValueMap {
378433

379434
private:
380435
std::optional<TrackableValue> getValueForId(Element id) const;
381-
std::optional<TrackableValue> tryToTrackValue(SILValue value) const;
436+
std::optional<TrackableValueLookupResult>
437+
tryToTrackValue(SILValue value) const;
382438
TrackableValue
383439
getActorIntroducingRepresentative(SILInstruction *introducingInst,
384440
SILIsolationInfo isolation) const;
@@ -400,6 +456,15 @@ class RegionAnalysisValueMap {
400456
UnderlyingTrackedValueInfo
401457
getUnderlyingTrackedValueHelper(SILValue value) const;
402458

459+
/// A helper function that performs the actual getUnderlyingTrackedValue
460+
/// computation that is cached in getUnderlyingTrackedValue(). Please never
461+
/// call this directly! Only call it from getUnderlyingTrackedValue.
462+
UnderlyingTrackedValueInfo
463+
getUnderlyingTrackedValueHelperObject(SILValue value) const;
464+
465+
UnderlyingTrackedValueInfo
466+
getUnderlyingTrackedValueHelperAddress(SILValue value) const;
467+
403468
UnderlyingTrackedValueInfo getUnderlyingTrackedValue(SILValue value) const {
404469
// Use try_emplace so we only construct underlying tracked value info on
405470
// success and only lookup once in the hash table.

0 commit comments

Comments
 (0)