@@ -827,6 +827,87 @@ class TrackableValueState {
827827 SWIFT_DEBUG_DUMP { print (llvm::dbgs ()); }
828828};
829829
830+ // / The representative value of the equivalence class that makes up a tracked
831+ // / value.
832+ // /
833+ // / We use a wrapper struct here so that we can inject "fake" actor isolated
834+ // / values into the regions of values that become merged into an actor by
835+ // / calling a function without a non-sendable result.
836+ class RepresentativeValue {
837+ friend llvm::DenseMapInfo<RepresentativeValue>;
838+
839+ using InnerType = PointerUnion<SILValue, SILInstruction *>;
840+
841+ // / If this is set to a SILValue then it is the actual represented value. If
842+ // / it is set to a SILInstruction, then this is a "fake" representative value
843+ // / used to inject actor isolatedness. The instruction stored is the
844+ // / instruction that introduced the actor isolated-ness.
845+ InnerType value;
846+
847+ public:
848+ RepresentativeValue () : value() {}
849+ RepresentativeValue (SILValue value) : value(value) {}
850+ RepresentativeValue (SILInstruction *actorRegionInst)
851+ : value(actorRegionInst) {}
852+
853+ operator bool () const { return bool (value); }
854+
855+ void print (llvm::raw_ostream &os) const {
856+ if (auto *inst = value.dyn_cast <SILInstruction *>()) {
857+ os << " ActorRegionIntroducingInst: " << *inst;
858+ return ;
859+ }
860+
861+ os << *value.get <SILValue>();
862+ }
863+
864+ SILValue getValue () const { return value.get <SILValue>(); }
865+ SILValue maybeGetValue () const { return value.dyn_cast <SILValue>(); }
866+ SILInstruction *getActorRegionIntroducingInst () const {
867+ return value.get <SILInstruction *>();
868+ }
869+
870+ SWIFT_DEBUG_DUMP { print (llvm::dbgs ()); }
871+
872+ private:
873+ RepresentativeValue (InnerType value) : value(value) {}
874+ };
875+
876+ } // namespace
877+
878+ namespace llvm {
879+ llvm::raw_ostream &operator <<(llvm::raw_ostream &os,
880+ const RepresentativeValue &value) {
881+ value.print (os);
882+ return os;
883+ }
884+
885+ template <>
886+ struct DenseMapInfo <::RepresentativeValue> {
887+ using RepresentativeValue = ::RepresentativeValue;
888+ using InnerType = RepresentativeValue::InnerType;
889+ using InnerDenseMapInfo = DenseMapInfo<InnerType>;
890+
891+ static RepresentativeValue getEmptyKey () {
892+ return RepresentativeValue (InnerDenseMapInfo::getEmptyKey ());
893+ }
894+ static RepresentativeValue getTombstoneKey () {
895+ return RepresentativeValue (InnerDenseMapInfo::getTombstoneKey ());
896+ }
897+
898+ static unsigned getHashValue (RepresentativeValue value) {
899+ return InnerDenseMapInfo::getHashValue (value.value );
900+ }
901+
902+ static bool isEqual (RepresentativeValue LHS, RepresentativeValue RHS) {
903+ return InnerDenseMapInfo::isEqual (LHS.value , RHS.value );
904+ }
905+ };
906+
907+ } // namespace llvm
908+
909+ namespace {
910+
830911// / A tuple consisting of a base value and its value state.
831912// /
832913// / DISCUSSION: We are computing regions among equivalence classes of values
@@ -843,11 +924,12 @@ class TrackableValueState {
843924// /
844925// / In the above example, %2 will be mapped to %0 by our value mapping.
845926class TrackableValue {
846- SILValue representativeValue;
927+ RepresentativeValue representativeValue;
847928 TrackableValueState valueState;
848929
849930public:
850- TrackableValue (SILValue representativeValue, TrackableValueState valueState)
931+ TrackableValue (RepresentativeValue representativeValue,
932+ TrackableValueState valueState)
851933 : representativeValue(representativeValue), valueState(valueState) {}
852934
853935 bool isMayAlias () const { return valueState.isMayAlias (); }
@@ -865,12 +947,12 @@ class TrackableValue {
865947 }
866948
867949 // / Return the representative value of this equivalence class of values.
868- SILValue getRepresentative () const { return representativeValue; }
950+ RepresentativeValue getRepresentative () const { return representativeValue; }
869951
870952 void print (llvm::raw_ostream &os) const {
871953 os << " TrackableValue. State: " ;
872954 valueState.print (os);
873- os << " \n Rep Value: " << * getRepresentative ();
955+ os << " \n Rep Value: " << getRepresentative ();
874956 }
875957
876958 SWIFT_DEBUG_DUMP { print (llvm::dbgs ()); }
@@ -898,6 +980,8 @@ struct PartitionOpBuilder {
898980 TrackableValueID lookupValueID (SILValue value);
899981 bool valueHasID (SILValue value, bool dumpIfHasNoID = false );
900982
983+ TrackableValueID getActorIntroducingRepresentative ();
984+
901985 void addAssignFresh (SILValue value) {
902986 currentInstPartitionOps.emplace_back (
903987 PartitionOp::AssignFresh (lookupValueID (value), currentInst));
@@ -948,6 +1032,19 @@ struct PartitionOpBuilder {
9481032 lookupValueID (fst), lookupValueID (snd), currentInst));
9491033 }
9501034
1035+ // / Mark \p value artifically as being part of an actor isolated region by
1036+ // / introducing a new fake actor introducing representative and merging them.
1037+ void addActorIntroducingInst (SILValue value) {
1038+ assert (valueHasID (value, /* dumpIfHasNoID=*/ true ) &&
1039+ " merged values should already have been encountered" );
1040+
1041+ auto elt = getActorIntroducingRepresentative ();
1042+ currentInstPartitionOps.emplace_back (
1043+ PartitionOp::AssignFresh (elt, currentInst));
1044+ currentInstPartitionOps.emplace_back (
1045+ PartitionOp::Merge (lookupValueID (value), elt, currentInst));
1046+ }
1047+
9511048 void addRequire (SILValue value) {
9521049 assert (valueHasID (value, /* dumpIfHasNoID=*/ true ) &&
9531050 " required value should already have been encountered" );
@@ -990,8 +1087,9 @@ class PartitionOpTranslator {
9901087 // / non-Sendable values. Implicit conversion from SILValue used pervasively.
9911088 // / ensure getUnderlyingTrackedValue is called on SILValues before entering
9921089 // / into this map
993- llvm::DenseMap<SILValue, TrackableValueState> equivalenceClassValuesToState;
994- llvm::DenseMap<unsigned , SILValue> stateIndexToEquivalenceClass;
1090+ llvm::DenseMap<RepresentativeValue, TrackableValueState>
1091+ equivalenceClassValuesToState;
1092+ llvm::DenseMap<unsigned , RepresentativeValue> stateIndexToEquivalenceClass;
9951093
9961094 // / A list of values that can never be transferred.
9971095 // /
@@ -1075,8 +1173,8 @@ class PartitionOpTranslator {
10751173
10761174 // Check if our base is a ref_element_addr from an actor. In such a case,
10771175 // mark this value as actor derived.
1078- if (isa<LoadInst, LoadBorrowInst>(iter.first ->first )) {
1079- auto *svi = cast<SingleValueInstruction>(iter.first ->first );
1176+ if (isa<LoadInst, LoadBorrowInst>(iter.first ->first . getValue () )) {
1177+ auto *svi = cast<SingleValueInstruction>(iter.first ->first . getValue () );
10801178 auto storage = AccessStorageWithBase::compute (svi->getOperand (0 ));
10811179 if (storage.storage && isa<RefElementAddrInst>(storage.base )) {
10821180 if (storage.storage .getRoot ()->getType ().isActor ()) {
@@ -1087,7 +1185,7 @@ class PartitionOpTranslator {
10871185
10881186 // Check if we have an unsafeMutableAddressor from a global actor, mark the
10891187 // returned value as being actor derived.
1090- if (auto applySite = FullApplySite::isa (iter.first ->first )) {
1188+ if (auto applySite = FullApplySite::isa (iter.first ->first . getValue () )) {
10911189 if (auto *calleeFunction = applySite.getCalleeFunction ()) {
10921190 if (calleeFunction->isGlobalInit () &&
10931191 isGlobalActorInit (calleeFunction)) {
@@ -1102,6 +1200,25 @@ class PartitionOpTranslator {
11021200 return {iter.first ->first , iter.first ->second };
11031201 }
11041202
1203+ TrackableValue
1204+ getActorIntroducingRepresentative (SILInstruction *introducingInst) const {
1205+ auto *self = const_cast <PartitionOpTranslator *>(this );
1206+ auto iter = self->equivalenceClassValuesToState .try_emplace (
1207+ introducingInst,
1208+ TrackableValueState (equivalenceClassValuesToState.size ()));
1209+
1210+ // If we did not insert, just return the already stored value.
1211+ if (!iter.second ) {
1212+ return {iter.first ->first , iter.first ->second };
1213+ }
1214+
1215+ // Otherwise, wire up the value.
1216+ self->stateIndexToEquivalenceClass [iter.first ->second .getID ()] =
1217+ introducingInst;
1218+ iter.first ->getSecond ().addFlag (TrackableValueFlag::isActorDerived);
1219+ return {iter.first ->first , iter.first ->second };
1220+ }
1221+
11051222 bool markValueAsActorDerived (SILValue value) {
11061223 value = getUnderlyingTrackedValue (value);
11071224 auto iter = equivalenceClassValuesToState.find (value);
@@ -1300,7 +1417,7 @@ class PartitionOpTranslator {
13001417 void dumpValues () const {
13011418 // Since this is just used for debug output, be inefficient to make nicer
13021419 // output.
1303- std::vector<std::pair<unsigned , SILValue >> temp;
1420+ std::vector<std::pair<unsigned , RepresentativeValue >> temp;
13041421 for (auto p : stateIndexToEquivalenceClass) {
13051422 temp.emplace_back (p.first , p.second );
13061423 }
@@ -1336,13 +1453,13 @@ class PartitionOpTranslator {
13361453
13371454 for (SILValue src : sourceValues) {
13381455 if (auto value = tryToTrackValue (src)) {
1339- assignOperands.push_back (value->getRepresentative ());
1456+ assignOperands.push_back (value->getRepresentative (). getValue () );
13401457 }
13411458 }
13421459
13431460 for (SILValue result : resultValues) {
13441461 if (auto value = tryToTrackValue (result)) {
1345- assignResults.push_back (value->getRepresentative ());
1462+ assignResults.push_back (value->getRepresentative (). getValue () );
13461463 // TODO: Can we pass back a reference to value perhaps?
13471464 if (options.contains (SILMultiAssignFlags::PropagatesActorSelf)) {
13481465 markValueAsActorDerived (result);
@@ -1360,8 +1477,18 @@ class PartitionOpTranslator {
13601477 }
13611478
13621479 // If we do not have any non sendable results, return early.
1363- if (assignResults.empty ())
1480+ if (assignResults.empty ()) {
1481+ // If we did not have any non-Sendable results and we did have
1482+ // non-Sendable operands and we are supposed to mark value as actor
1483+ // derived, introduce a fake element so we just propagate the actor
1484+ // region.
1485+ if (assignOperands.size () &&
1486+ options.contains (SILMultiAssignFlags::PropagatesActorSelf)) {
1487+ builder.addActorIntroducingInst (assignOperands.back ());
1488+ }
1489+
13641490 return ;
1491+ }
13651492
13661493 auto assignResultsRef = llvm::makeArrayRef (assignResults);
13671494 SILValue front = assignResultsRef.front ();
@@ -1426,7 +1553,8 @@ class PartitionOpTranslator {
14261553 }))
14271554 continue ;
14281555
1429- builder.addUndoTransfer (trackedArgValue->getRepresentative (), ai);
1556+ builder.addUndoTransfer (trackedArgValue->getRepresentative ().getValue (),
1557+ ai);
14301558 }
14311559 }
14321560 }
@@ -1444,8 +1572,9 @@ class PartitionOpTranslator {
14441572 // useValue(x2)
14451573 for (auto &op : ApplySite (pai).getArgumentOperands ()) {
14461574 if (auto trackedArgValue = tryToTrackValue (op.get ())) {
1447- builder.addRequire (trackedArgValue->getRepresentative ());
1448- builder.addTransfer (trackedArgValue->getRepresentative (), &op);
1575+ builder.addRequire (trackedArgValue->getRepresentative ().getValue ());
1576+ builder.addTransfer (trackedArgValue->getRepresentative ().getValue (),
1577+ &op);
14491578 }
14501579 }
14511580 }
@@ -1538,19 +1667,19 @@ class PartitionOpTranslator {
15381667 // require all operands
15391668 for (auto op : applySite->getOperandValues ())
15401669 if (auto value = tryToTrackValue (op))
1541- builder.addRequire (value->getRepresentative ());
1670+ builder.addRequire (value->getRepresentative (). getValue () );
15421671
15431672 auto handleSILOperands = [&](MutableArrayRef<Operand> operands) {
15441673 for (auto &op : operands) {
15451674 if (auto value = tryToTrackValue (op.get ())) {
1546- builder.addTransfer (value->getRepresentative (), &op);
1675+ builder.addTransfer (value->getRepresentative (). getValue () , &op);
15471676 }
15481677 }
15491678 };
15501679
15511680 auto handleSILSelf = [&](Operand *self) {
15521681 if (auto value = tryToTrackValue (self->get ())) {
1553- builder.addTransfer (value->getRepresentative (), self);
1682+ builder.addTransfer (value->getRepresentative (). getValue () , self);
15541683 }
15551684 };
15561685
@@ -1568,7 +1697,7 @@ class PartitionOpTranslator {
15681697 getApplyResults (*applySite, applyResults);
15691698 for (auto result : applyResults)
15701699 if (auto value = tryToTrackValue (result))
1571- builder.addAssignFresh (value->getRepresentative ());
1700+ builder.addAssignFresh (value->getRepresentative (). getValue () );
15721701 }
15731702
15741703 template <typename DestValues>
@@ -1636,8 +1765,8 @@ class PartitionOpTranslator {
16361765 return ;
16371766 for (SILValue elt : collection) {
16381767 if (auto trackableSrc = tryToTrackValue (elt)) {
1639- builder.addMerge (trackableDest->getRepresentative (),
1640- trackableSrc->getRepresentative ());
1768+ builder.addMerge (trackableDest->getRepresentative (). getValue () ,
1769+ trackableSrc->getRepresentative (). getValue () );
16411770 }
16421771 }
16431772 }
@@ -1701,7 +1830,7 @@ class PartitionOpTranslator {
17011830
17021831 void translateSILRequire (SILValue val) {
17031832 if (auto nonSendableVal = tryToTrackValue (val))
1704- return builder.addRequire (nonSendableVal->getRepresentative ());
1833+ return builder.addRequire (nonSendableVal->getRepresentative (). getValue () );
17051834 }
17061835
17071836 // / An enum select is just a multi assign.
@@ -2084,6 +2213,10 @@ TrackableValueID PartitionOpBuilder::lookupValueID(SILValue value) {
20842213 return translator->lookupValueID (value);
20852214}
20862215
2216+ TrackableValueID PartitionOpBuilder::getActorIntroducingRepresentative () {
2217+ return translator->getActorIntroducingRepresentative (currentInst).getID ();
2218+ }
2219+
20872220bool PartitionOpBuilder::valueHasID (SILValue value, bool dumpIfHasNoID) {
20882221 return translator->valueHasID (value, dumpIfHasNoID);
20892222}
@@ -2129,7 +2262,7 @@ void PartitionOpBuilder::print(llvm::raw_ostream &os) const {
21292262 sortUnique (opsToPrint);
21302263 for (unsigned opArg : opsToPrint) {
21312264 llvm::dbgs () << " └╼ " ;
2132- SILValue value = translator->stateIndexToEquivalenceClass [opArg];
2265+ auto value = translator->stateIndexToEquivalenceClass [opArg];
21332266 auto iter = translator->equivalenceClassValuesToState .find (value);
21342267 assert (iter != translator->equivalenceClassValuesToState .end ());
21352268 llvm::dbgs () << " State: %%" << opArg << " . " ;
@@ -2191,8 +2324,10 @@ class BlockPartitionState {
21912324 auto iter = translator.getValueForId (element);
21922325 if (!iter)
21932326 return false ;
2194- return translator.isClosureCaptured (iter->getRepresentative (),
2195- op->getUser ());
2327+ auto value = iter->getRepresentative ().maybeGetValue ();
2328+ if (!value)
2329+ return false ;
2330+ return translator.isClosureCaptured (value, op->getUser ());
21962331 };
21972332 for (const auto &partitionOp : blockPartitionOps) {
21982333 // By calling apply without providing a `handleFailure` closure, errors
@@ -2609,8 +2744,9 @@ class PartitionAnalysis {
26092744 }
26102745 }
26112746
2612- auto rep =
2613- translator.getValueForId (transferredVal)->getRepresentative ();
2747+ auto rep = translator.getValueForId (transferredVal)
2748+ ->getRepresentative ()
2749+ .getValue ();
26142750 LLVM_DEBUG (
26152751 llvm::dbgs ()
26162752 << " Emitting Use After Transfer Error!\n "
@@ -2630,7 +2766,8 @@ class PartitionAnalysis {
26302766 << " ID: %%" << transferredVal << " \n "
26312767 << " Rep: "
26322768 << *translator.getValueForId (transferredVal)
2633- ->getRepresentative ());
2769+ ->getRepresentative ()
2770+ .getValue ());
26342771 diagnose (partitionOp,
26352772 diag::regionbasedisolation_selforargtransferred);
26362773 };
@@ -2646,8 +2783,10 @@ class PartitionAnalysis {
26462783 auto iter = translator.getValueForId (element);
26472784 if (!iter)
26482785 return false ;
2649- return translator.isClosureCaptured (iter->getRepresentative (),
2650- op->getUser ());
2786+ auto value = iter->getRepresentative ().maybeGetValue ();
2787+ if (!value)
2788+ return false ;
2789+ return translator.isClosureCaptured (value, op->getUser ());
26512790 };
26522791
26532792 // And then evaluate all of our partition ops on the entry partition.
0 commit comments