@@ -93,19 +93,6 @@ regionanalysisimpl::getApplyIsolationCrossing(SILInstruction *inst) {
93
93
94
94
namespace {
95
95
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
-
109
96
struct UseDefChainVisitor
110
97
: public AccessUseDefChainVisitor<UseDefChainVisitor, SILValue> {
111
98
bool isMerge = false ;
@@ -337,95 +324,6 @@ static bool isLookThroughIfOperandAndResultNonSendable(SILInstruction *inst) {
337
324
}
338
325
}
339
326
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
-
429
327
namespace {
430
328
431
329
struct TermArgSources {
@@ -915,6 +813,97 @@ void RegionAnalysisValueMap::print(llvm::raw_ostream &os) const {
915
813
#endif
916
814
}
917
815
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
+
918
907
// ===----------------------------------------------------------------------===//
919
908
// MARK: TrackableValue
920
909
// ===----------------------------------------------------------------------===//
@@ -988,6 +977,7 @@ namespace {
988
977
// /
989
978
// / 2. Just computing reachability early is a very easy way to do this.
990
979
struct PartialApplyReachabilityDataflow {
980
+ RegionAnalysisValueMap &valueMap;
991
981
PostOrderFunctionInfo *pofi;
992
982
llvm::DenseMap<SILValue, unsigned > valueToBit;
993
983
std::vector<std::pair<SILValue, SILInstruction *>> valueToGenInsts;
@@ -1002,8 +992,10 @@ struct PartialApplyReachabilityDataflow {
1002
992
BasicBlockData<BlockState> blockData;
1003
993
bool propagatedReachability = false ;
1004
994
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) {}
1007
999
1008
1000
// / Begin tracking an operand of a partial apply.
1009
1001
void add (Operand *op);
@@ -1035,7 +1027,7 @@ struct PartialApplyReachabilityDataflow {
1035
1027
1036
1028
private:
1037
1029
SILValue getRootValue (SILValue value) const {
1038
- return getUnderlyingTrackedValue (value). value ;
1030
+ return valueMap. getRepresentative (value);
1039
1031
}
1040
1032
1041
1033
unsigned getBitForValue (SILValue value) const {
@@ -1767,7 +1759,8 @@ class PartitionOpTranslator {
1767
1759
RegionAnalysisValueMap &valueMap,
1768
1760
IsolationHistory::Factory &historyFactory)
1769
1761
: function(function), functionArgPartition(), builder(),
1770
- partialApplyReachabilityDataflow (function, pofi), valueMap(valueMap) {
1762
+ partialApplyReachabilityDataflow (function, valueMap, pofi),
1763
+ valueMap(valueMap) {
1771
1764
builder.translator = this ;
1772
1765
1773
1766
REGIONBASEDISOLATION_LOG (
0 commit comments