@@ -1553,7 +1553,10 @@ AvailableValueDataflowContext::AvailableValueDataflowContext(
15531553
15541554 llvm_unreachable (" Unhandled SILInstructionKind for PMOUseKind::Load?!" );
15551555 }
1556-
1556+ if (Use.Kind == PMOUseKind::DependenceBase) {
1557+ // An address used as a dependence base does not affect load promotion.
1558+ continue ;
1559+ }
15571560 // Keep track of all the uses that aren't loads.
15581561 NonLoadUses[Use.Inst ] = ui;
15591562 HasLocalDefinition.set (Use.Inst ->getParent ());
@@ -2421,14 +2424,17 @@ struct Promotions {
24212424 SmallVector<AvailableValue, 32 > allAvailableValues;
24222425 PromotableInstructions loadTakes;
24232426 PromotableInstructions destroys;
2427+ PromotableInstructions markDepBases;
24242428
24252429 Promotions ()
2426- : loadTakes(allAvailableValues), destroys(allAvailableValues) {}
2430+ : loadTakes(allAvailableValues), destroys(allAvailableValues),
2431+ markDepBases (allAvailableValues) {}
24272432
24282433#ifndef NDEBUG
24292434 void verify () {
24302435 loadTakes.verify ();
24312436 destroys.verify ();
2437+ markDepBases.verify ();
24322438 }
24332439#endif
24342440};
@@ -2496,11 +2502,18 @@ class OptimizeDeadAlloc {
24962502private:
24972503 SILInstruction *collectUsesForPromotion ();
24982504
2505+ // / Return true if a mark_dependence can be promoted. If so, this initializes
2506+ // / the available values in promotions.
2507+ bool canPromoteMarkDepBase (MarkDependenceInst *md);
2508+
24992509 // / Return true if a load [take] or destroy_addr can be promoted. If so, this
25002510 // / initializes the available values in promotions.
25012511 bool canPromoteTake (SILInstruction *i,
25022512 PromotableInstructions &promotableInsts);
25032513
2514+ SILValue promoteMarkDepBase (MarkDependenceInst *md,
2515+ ArrayRef<AvailableValue> availableValues);
2516+
25042517 // / Promote a load take cleaning up everything except for RAUWing the
25052518 // / instruction with the aggregated result. The routine returns the new
25062519 // / aggregated result to the caller and expects the caller to eventually RAUW
@@ -2552,6 +2565,10 @@ bool OptimizeDeadAlloc::tryToRemoveDeadAllocation() {
25522565
25532566 SWIFT_DEFER { DataflowContext.fixupOwnership (deleter, deadEndBlocks); };
25542567
2568+ for (auto *md : promotions.markDepBases .instructions ()) {
2569+ if (!canPromoteMarkDepBase (cast<MarkDependenceInst>(md)))
2570+ return false ;
2571+ }
25552572 if (isTrivial ()) {
25562573 removeDeadAllocation ();
25572574 return true ;
@@ -2620,6 +2637,9 @@ SILInstruction *OptimizeDeadAlloc::collectUsesForPromotion() {
26202637 }
26212638 }
26222639 return u.Inst ;
2640+ case PMOUseKind::DependenceBase:
2641+ promotions.markDepBases .push (u.Inst );
2642+ continue ;
26232643 case PMOUseKind::Initialization:
26242644 if (!isa<ApplyInst>(u.Inst ) &&
26252645 // A copy_addr that is not a take affects the retain count
@@ -2652,6 +2672,28 @@ SILInstruction *OptimizeDeadAlloc::collectUsesForPromotion() {
26522672 return nullptr ;
26532673}
26542674
2675+ bool OptimizeDeadAlloc::canPromoteMarkDepBase (MarkDependenceInst *md) {
2676+ SILValue srcAddr = md->getBase ();
2677+ SmallVector<AvailableValue, 8 > availableValues;
2678+ auto result =
2679+ DataflowContext.computeAvailableValues (srcAddr, md, availableValues);
2680+ if (!result.has_value ())
2681+ return false ;
2682+
2683+ unsigned index = promotions.markDepBases .initializeAvailableValues (
2684+ md, std::move (availableValues));
2685+
2686+ SILType baseTy = result->first ;
2687+ if (auto *abi = dyn_cast<AllocBoxInst>(TheMemory)) {
2688+ if (baseTy == abi->getType ()) {
2689+ baseTy = MemoryType.getObjectType ();
2690+ }
2691+ }
2692+ unsigned firstElt = result->second ;
2693+ return isFullyAvailable (baseTy, firstElt,
2694+ promotions.markDepBases .availableValues (index));
2695+ }
2696+
26552697// / Return true if we can promote the given destroy.
26562698bool OptimizeDeadAlloc::canPromoteTake (
26572699 SILInstruction *inst, PromotableInstructions &promotableInsts) {
@@ -2692,6 +2734,12 @@ bool OptimizeDeadAlloc::canPromoteTake(
26922734}
26932735
26942736void OptimizeDeadAlloc::removeDeadAllocation () {
2737+ for (auto idxVal : llvm::enumerate (promotions.markDepBases .instructions ())) {
2738+ auto *md = cast<MarkDependenceInst>(idxVal.value ());
2739+ auto vals = promotions.markDepBases .availableValues (idxVal.index ());
2740+ promoteMarkDepBase (md, vals);
2741+ }
2742+
26952743 // If our memory is trivially typed, we can just remove it without needing to
26962744 // consider if the stored value needs to be destroyed. So at this point,
26972745 // delete the memory!
@@ -2798,6 +2846,23 @@ void OptimizeDeadAlloc::removeDeadAllocation() {
27982846 }
27992847}
28002848
2849+ SILValue OptimizeDeadAlloc::promoteMarkDepBase (
2850+ MarkDependenceInst *md, ArrayRef<AvailableValue> availableValues) {
2851+
2852+ LLVM_DEBUG (llvm::dbgs () << " *** Promoting mark_dependence base: " << *md);
2853+ SILBuilderWithScope B (md);
2854+ SILValue dependentValue = md->getValue ();
2855+ for (auto &availableValue : availableValues) {
2856+ dependentValue =
2857+ B.createMarkDependence (md->getLoc (), dependentValue,
2858+ availableValue.getValue (), md->dependenceKind ());
2859+ }
2860+ LLVM_DEBUG (llvm::dbgs () << " To value: " << dependentValue);
2861+ md->replaceAllUsesWith (dependentValue);
2862+ deleter.deleteIfDead (md);
2863+ return dependentValue;
2864+ }
2865+
28012866SILValue
28022867OptimizeDeadAlloc::promoteLoadTake (LoadInst *li,
28032868 ArrayRef<AvailableValue> availableValues) {
0 commit comments