|
28 | 28 |
|
29 | 29 | using namespace swift;
|
30 | 30 |
|
| 31 | +using SILValueSet = llvm::DenseSet<SILValue>; |
| 32 | +using SILValueList = llvm::SmallVector<SILValue, 8>; |
| 33 | + |
31 | 34 | //===----------------------------------------------------------------------===//
|
32 | 35 | // AA Debugging
|
33 | 36 | //===----------------------------------------------------------------------===//
|
@@ -99,6 +102,80 @@ llvm::raw_ostream &swift::operator<<(llvm::raw_ostream &OS,
|
99 | 102 | }
|
100 | 103 | }
|
101 | 104 |
|
| 105 | +/// Return true if the SILValue is the result of multiple SILValues, e.g. |
| 106 | +/// select_enum, silargument. |
| 107 | +static bool isMultiUnderlyingObjectValue(SILValue V) { |
| 108 | + if (isa<SelectEnumInst>(V)) |
| 109 | + return true; |
| 110 | + // We are only interested in basic block SILArguments as those are the |
| 111 | + // ones we can collect all the possible incoming values. |
| 112 | + if (SILArgument *SA = dyn_cast<SILArgument>(V)) |
| 113 | + if (!SA->isFunctionArg()) |
| 114 | + return true; |
| 115 | + return false; |
| 116 | +} |
| 117 | + |
| 118 | +/// Get the first level underlying objects, e.g. in case of select_enum, |
| 119 | +/// look to the possible underlying objects from all the cases. |
| 120 | +static bool getFirstLevelUnderlyingObjects(SILValue V, SILValueSet &Cache, |
| 121 | + SILValueList &WorkList) { |
| 122 | + // Look through SILArgument. |
| 123 | + if (auto *SA = dyn_cast<SILArgument>(V)) { |
| 124 | + SILValueList Args; |
| 125 | + bool Succ = SA->getIncomingValues(Args); |
| 126 | + // Unable to get SILValue for every predecessor. |
| 127 | + if (!Succ) |
| 128 | + return false; |
| 129 | + for (auto &X : Args) { |
| 130 | + if (Cache.count(X)) |
| 131 | + continue; |
| 132 | + // We have not seen this SILValue before. |
| 133 | + Cache.insert(X); |
| 134 | + WorkList.push_back(X); |
| 135 | + } |
| 136 | + } |
| 137 | + |
| 138 | + // Look through SelectEnumInst. |
| 139 | + if (auto *SE = dyn_cast<SelectEnumInst>(V)) { |
| 140 | + unsigned CaseNum = SE->getNumCases(); |
| 141 | + for (unsigned i = 0; i < CaseNum; ++i) { |
| 142 | + SILValue C = SE->getCase(i).second; |
| 143 | + if (Cache.count(C)) |
| 144 | + continue; |
| 145 | + // We have not seen this SILValue before. |
| 146 | + Cache.insert(C); |
| 147 | + WorkList.push_back(C); |
| 148 | + } |
| 149 | + } |
| 150 | + return true; |
| 151 | +} |
| 152 | + |
| 153 | +/// Collect all the underlying objects for the given SILValue. Return false |
| 154 | +/// if fail to collect all possible underlying objects. |
| 155 | +static bool getTransistiveUnderlyingObjects(SILValue V, SILValueList &Objs) { |
| 156 | + // Cache keeps track of what has been processed, so that we do not collected |
| 157 | + // it again. |
| 158 | + SILValueSet Cache; |
| 159 | + SILValueList WorkList; |
| 160 | + |
| 161 | + // Start with the given SILValue. |
| 162 | + WorkList.push_back(V); |
| 163 | + while(!WorkList.empty()) { |
| 164 | + SILValue V = WorkList.pop_back_val(); |
| 165 | + if (isMultiUnderlyingObjectValue(V)) { |
| 166 | + if (getFirstLevelUnderlyingObjects(V, Cache, WorkList)) |
| 167 | + continue; |
| 168 | + // Failed to get all possible underlying value, bail out. |
| 169 | + return false; |
| 170 | + } |
| 171 | + |
| 172 | + // This is single base SILValue. |
| 173 | + Objs.push_back(V); |
| 174 | + Cache.insert(V); |
| 175 | + } |
| 176 | + return true; |
| 177 | +} |
| 178 | + |
102 | 179 | //===----------------------------------------------------------------------===//
|
103 | 180 | // Unequal Base Object AA
|
104 | 181 | //===----------------------------------------------------------------------===//
|
@@ -527,6 +604,37 @@ static bool typesMayAlias(SILType T1, SILType T2, SILType TBAA1Ty,
|
527 | 604 | // Entry Points
|
528 | 605 | //===----------------------------------------------------------------------===//
|
529 | 606 |
|
| 607 | +AliasAnalysis::AliasResult |
| 608 | +AliasAnalysis::handleMultiUnderlyingObjectAlias(SILValue V1, SILValue V2) { |
| 609 | + const unsigned AliasQueryLimit = 16; |
| 610 | + SmallVector<SILValue, 8> V1Base, V2Base; |
| 611 | + // Collect the transistive closure of all the SILValue V1 and V2 can |
| 612 | + // point to. If for some reason we can not collect all the possible |
| 613 | + // underlying objects, return MayAlias to be conservative. |
| 614 | + if (!getTransistiveUnderlyingObjects(V1, V1Base) || |
| 615 | + !getTransistiveUnderlyingObjects(V2, V2Base)) |
| 616 | + return AliasResult::MayAlias; |
| 617 | + |
| 618 | + // An mxn alias analysis query, bail out if this results in too many |
| 619 | + // alias queries. |
| 620 | + if (V1Base.size() * V2Base.size() > AliasQueryLimit) |
| 621 | + return AliasResult::MayAlias; |
| 622 | + |
| 623 | + // Return MayAlias if any pair does not have a NoAlias relation. |
| 624 | + for (auto &M : V1Base) { |
| 625 | + for (auto &N : V2Base) { |
| 626 | + AliasAnalysis::AliasResult R = alias(M, N, findTypedAccessType(M), |
| 627 | + findTypedAccessType(N)); |
| 628 | + // Return MayAlias whenever we have 1 non-NoAlias pair. This is a |
| 629 | + // tradeoff between compilation time and being conservative. |
| 630 | + if (R != AliasResult::NoAlias) |
| 631 | + return AliasResult::MayAlias; |
| 632 | + } |
| 633 | + } |
| 634 | + |
| 635 | + return AliasResult::NoAlias; |
| 636 | +} |
| 637 | + |
530 | 638 | /// The main AA entry point. Performs various analyses on V1, V2 in an attempt
|
531 | 639 | /// to disambiguate the two values.
|
532 | 640 | AliasAnalysis::AliasResult AliasAnalysis::alias(SILValue V1, SILValue V2,
|
@@ -589,8 +697,13 @@ AliasAnalysis::AliasResult AliasAnalysis::aliasInner(SILValue V1, SILValue V2,
|
589 | 697 | }
|
590 | 698 | }
|
591 | 699 |
|
592 |
| - // Ok, we need to actually compute an Alias Analysis result for V1, V2. Begin |
593 |
| - // by finding the "base" of V1, V2 by stripping off all casts and GEPs. |
| 700 | + // Ok, we need to actually compute an Alias Analysis result for V1, V2. First |
| 701 | + // find whether V1, V2 potentially have multiple underlying objects. |
| 702 | + if (isMultiUnderlyingObjectValue(V1) || isMultiUnderlyingObjectValue(V2)) |
| 703 | + return handleMultiUnderlyingObjectAlias(V1, V2); |
| 704 | + |
| 705 | + // At this point, V1 and V2 are both single base SIlValues, begin by |
| 706 | + // finding the "base" of V1, V2 by stripping off all casts and GEPs. |
594 | 707 | SILValue O1 = getUnderlyingObject(V1);
|
595 | 708 | SILValue O2 = getUnderlyingObject(V2);
|
596 | 709 | DEBUG(llvm::dbgs() << " Underlying V1:" << *O1.getDef());
|
@@ -626,6 +739,7 @@ AliasAnalysis::AliasResult AliasAnalysis::aliasInner(SILValue V1, SILValue V2,
|
626 | 739 | return AliasResult::MayAlias;
|
627 | 740 | }
|
628 | 741 |
|
| 742 | + |
629 | 743 | /// Check if this is the address of a "let" member.
|
630 | 744 | /// Nobody can write into let members.
|
631 | 745 | bool swift::isLetPointer(SILValue V) {
|
|
0 commit comments