@@ -93,19 +93,6 @@ regionanalysisimpl::getApplyIsolationCrossing(SILInstruction *inst) {
9393
9494namespace {
9595
96- struct UnderlyingTrackedValueInfo {
97- SILValue value;
98-
99- // / Only used for addresses.
100- std::optional<ActorIsolation> actorIsolation;
101-
102- explicit UnderlyingTrackedValueInfo (SILValue value) : value(value) {}
103-
104- UnderlyingTrackedValueInfo (SILValue value,
105- std::optional<ActorIsolation> actorIsolation)
106- : value(value), actorIsolation(actorIsolation) {}
107- };
108-
10996struct UseDefChainVisitor
11097 : public AccessUseDefChainVisitor<UseDefChainVisitor, SILValue> {
11198 bool isMerge = false ;
@@ -337,95 +324,6 @@ static bool isLookThroughIfOperandAndResultNonSendable(SILInstruction *inst) {
337324 }
338325}
339326
340- static SILValue getUnderlyingTrackedObjectValue (SILValue value) {
341- auto *fn = value->getFunction ();
342- SILValue result = value;
343- while (true ) {
344- SILValue temp = result;
345-
346- if (auto *svi = dyn_cast<SingleValueInstruction>(temp)) {
347- if (isStaticallyLookThroughInst (svi)) {
348- temp = svi->getOperand (0 );
349- }
350-
351- // If we have a cast and our operand and result are non-Sendable, treat it
352- // as a look through.
353- if (isLookThroughIfOperandAndResultNonSendable (svi)) {
354- if (SILIsolationInfo::isNonSendableType (svi->getType (), fn) &&
355- SILIsolationInfo::isNonSendableType (svi->getOperand (0 )->getType (),
356- fn)) {
357- temp = svi->getOperand (0 );
358- }
359- }
360-
361- if (isLookThroughIfResultNonSendable (svi)) {
362- if (SILIsolationInfo::isNonSendableType (svi->getType (), fn)) {
363- temp = svi->getOperand (0 );
364- }
365- }
366-
367- if (isLookThroughIfOperandNonSendable (svi)) {
368- // If our operand is a non-Sendable type, look through this instruction.
369- if (SILIsolationInfo::isNonSendableType (svi->getOperand (0 )->getType (),
370- fn)) {
371- temp = svi->getOperand (0 );
372- }
373- }
374- }
375-
376- if (auto *inst = temp->getDefiningInstruction ()) {
377- if (isStaticallyLookThroughInst (inst)) {
378- temp = inst->getOperand (0 );
379- }
380- }
381-
382- if (temp != result) {
383- result = temp;
384- continue ;
385- }
386-
387- return result;
388- }
389- }
390-
391- static UnderlyingTrackedValueInfo getUnderlyingTrackedValue (SILValue value) {
392- // Before a check if the value we are attempting to access is Sendable. In
393- // such a case, just return early.
394- if (!SILIsolationInfo::isNonSendableType (value))
395- return UnderlyingTrackedValueInfo (value);
396-
397- // Look through a project_box, so that we process it like its operand object.
398- if (auto *pbi = dyn_cast<ProjectBoxInst>(value)) {
399- value = pbi->getOperand ();
400- }
401-
402- if (!value->getType ().isAddress ()) {
403- SILValue underlyingValue = getUnderlyingTrackedObjectValue (value);
404-
405- // If we do not have a load inst, just return the value.
406- if (!isa<LoadInst, LoadBorrowInst>(underlyingValue)) {
407- return UnderlyingTrackedValueInfo (underlyingValue);
408- }
409-
410- // If we got an address, lets see if we can do even better by looking at the
411- // address.
412- value = cast<SingleValueInstruction>(underlyingValue)->getOperand (0 );
413- }
414- assert (value->getType ().isAddress ());
415-
416- UseDefChainVisitor visitor;
417- SILValue base = visitor.visitAll (value);
418- assert (base);
419- if (base->getType ().isObject ())
420- return {getUnderlyingTrackedValue (base).value , visitor.actorIsolation };
421-
422- return {base, visitor.actorIsolation };
423- }
424-
425- SILValue RegionAnalysisFunctionInfo::getUnderlyingTrackedValue (SILValue value) {
426- return ::getUnderlyingTrackedValue (value).value ;
427- }
428-
429327namespace {
430328
431329struct TermArgSources {
@@ -915,6 +813,97 @@ void RegionAnalysisValueMap::print(llvm::raw_ostream &os) const {
915813#endif
916814}
917815
816+ static SILValue getUnderlyingTrackedObjectValue (SILValue value) {
817+ auto *fn = value->getFunction ();
818+ SILValue result = value;
819+ while (true ) {
820+ SILValue temp = result;
821+
822+ if (auto *svi = dyn_cast<SingleValueInstruction>(temp)) {
823+ if (isStaticallyLookThroughInst (svi)) {
824+ temp = svi->getOperand (0 );
825+ }
826+
827+ // If we have a cast and our operand and result are non-Sendable, treat it
828+ // as a look through.
829+ if (isLookThroughIfOperandAndResultNonSendable (svi)) {
830+ if (SILIsolationInfo::isNonSendableType (svi->getType (), fn) &&
831+ SILIsolationInfo::isNonSendableType (svi->getOperand (0 )->getType (),
832+ fn)) {
833+ temp = svi->getOperand (0 );
834+ }
835+ }
836+
837+ if (isLookThroughIfResultNonSendable (svi)) {
838+ if (SILIsolationInfo::isNonSendableType (svi->getType (), fn)) {
839+ temp = svi->getOperand (0 );
840+ }
841+ }
842+
843+ if (isLookThroughIfOperandNonSendable (svi)) {
844+ // If our operand is a non-Sendable type, look through this instruction.
845+ if (SILIsolationInfo::isNonSendableType (svi->getOperand (0 )->getType (),
846+ fn)) {
847+ temp = svi->getOperand (0 );
848+ }
849+ }
850+ }
851+
852+ if (auto *inst = temp->getDefiningInstruction ()) {
853+ if (isStaticallyLookThroughInst (inst)) {
854+ temp = inst->getOperand (0 );
855+ }
856+ }
857+
858+ if (temp != result) {
859+ result = temp;
860+ continue ;
861+ }
862+
863+ return result;
864+ }
865+ }
866+
867+ RegionAnalysisValueMap::UnderlyingTrackedValueInfo
868+ RegionAnalysisValueMap::getUnderlyingTrackedValueHelper (SILValue value) const {
869+ // Before a check if the value we are attempting to access is Sendable. In
870+ // such a case, just return early.
871+ if (!SILIsolationInfo::isNonSendableType (value))
872+ return UnderlyingTrackedValueInfo (value);
873+
874+ // Look through a project_box, so that we process it like its operand object.
875+ if (auto *pbi = dyn_cast<ProjectBoxInst>(value)) {
876+ value = pbi->getOperand ();
877+ }
878+
879+ if (!value->getType ().isAddress ()) {
880+ SILValue underlyingValue = getUnderlyingTrackedObjectValue (value);
881+
882+ // If we do not have a load inst, just return the value.
883+ if (!isa<LoadInst, LoadBorrowInst>(underlyingValue)) {
884+ return UnderlyingTrackedValueInfo (underlyingValue);
885+ }
886+
887+ // If we got an address, lets see if we can do even better by looking at the
888+ // address.
889+ value = cast<SingleValueInstruction>(underlyingValue)->getOperand (0 );
890+ }
891+ assert (value->getType ().isAddress ());
892+
893+ UseDefChainVisitor visitor;
894+ SILValue base = visitor.visitAll (value);
895+ assert (base);
896+ if (base->getType ().isObject ()) {
897+ // NOTE: We purposely recurse into the cached version of our computation
898+ // rather than recurse into getUnderlyingTrackedObjectValueHelper. This is
899+ // safe since we know that value was previously an address so if our base is
900+ // an object, it cannot be the same object.
901+ return {getUnderlyingTrackedValue (base).value , visitor.actorIsolation };
902+ }
903+
904+ return {base, visitor.actorIsolation };
905+ }
906+
918907// ===----------------------------------------------------------------------===//
919908// MARK: TrackableValue
920909// ===----------------------------------------------------------------------===//
@@ -988,6 +977,7 @@ namespace {
988977// /
989978// / 2. Just computing reachability early is a very easy way to do this.
990979struct PartialApplyReachabilityDataflow {
980+ RegionAnalysisValueMap &valueMap;
991981 PostOrderFunctionInfo *pofi;
992982 llvm::DenseMap<SILValue, unsigned > valueToBit;
993983 std::vector<std::pair<SILValue, SILInstruction *>> valueToGenInsts;
@@ -1002,8 +992,10 @@ struct PartialApplyReachabilityDataflow {
1002992 BasicBlockData<BlockState> blockData;
1003993 bool propagatedReachability = false ;
1004994
1005- PartialApplyReachabilityDataflow (SILFunction *fn, PostOrderFunctionInfo *pofi)
1006- : pofi(pofi), blockData(fn) {}
995+ PartialApplyReachabilityDataflow (SILFunction *fn,
996+ RegionAnalysisValueMap &valueMap,
997+ PostOrderFunctionInfo *pofi)
998+ : valueMap(valueMap), pofi(pofi), blockData(fn) {}
1007999
10081000 // / Begin tracking an operand of a partial apply.
10091001 void add (Operand *op);
@@ -1035,7 +1027,7 @@ struct PartialApplyReachabilityDataflow {
10351027
10361028private:
10371029 SILValue getRootValue (SILValue value) const {
1038- return getUnderlyingTrackedValue (value). value ;
1030+ return valueMap. getRepresentative (value);
10391031 }
10401032
10411033 unsigned getBitForValue (SILValue value) const {
@@ -1767,7 +1759,8 @@ class PartitionOpTranslator {
17671759 RegionAnalysisValueMap &valueMap,
17681760 IsolationHistory::Factory &historyFactory)
17691761 : function(function), functionArgPartition(), builder(),
1770- partialApplyReachabilityDataflow (function, pofi), valueMap(valueMap) {
1762+ partialApplyReachabilityDataflow (function, valueMap, pofi),
1763+ valueMap(valueMap) {
17711764 builder.translator = this ;
17721765
17731766 REGIONBASEDISOLATION_LOG (
0 commit comments