@@ -1553,7 +1553,10 @@ AvailableValueDataflowContext::AvailableValueDataflowContext(
1553
1553
1554
1554
llvm_unreachable (" Unhandled SILInstructionKind for PMOUseKind::Load?!" );
1555
1555
}
1556
-
1556
+ if (Use.Kind == PMOUseKind::DependenceBase) {
1557
+ // An address used as a dependence base does not affect load promotion.
1558
+ continue ;
1559
+ }
1557
1560
// Keep track of all the uses that aren't loads.
1558
1561
NonLoadUses[Use.Inst ] = ui;
1559
1562
HasLocalDefinition.set (Use.Inst ->getParent ());
@@ -2421,14 +2424,17 @@ struct Promotions {
2421
2424
SmallVector<AvailableValue, 32 > allAvailableValues;
2422
2425
PromotableInstructions loadTakes;
2423
2426
PromotableInstructions destroys;
2427
+ PromotableInstructions markDepBases;
2424
2428
2425
2429
Promotions ()
2426
- : loadTakes(allAvailableValues), destroys(allAvailableValues) {}
2430
+ : loadTakes(allAvailableValues), destroys(allAvailableValues),
2431
+ markDepBases (allAvailableValues) {}
2427
2432
2428
2433
#ifndef NDEBUG
2429
2434
void verify () {
2430
2435
loadTakes.verify ();
2431
2436
destroys.verify ();
2437
+ markDepBases.verify ();
2432
2438
}
2433
2439
#endif
2434
2440
};
@@ -2496,11 +2502,18 @@ class OptimizeDeadAlloc {
2496
2502
private:
2497
2503
SILInstruction *collectUsesForPromotion ();
2498
2504
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
+
2499
2509
// / Return true if a load [take] or destroy_addr can be promoted. If so, this
2500
2510
// / initializes the available values in promotions.
2501
2511
bool canPromoteTake (SILInstruction *i,
2502
2512
PromotableInstructions &promotableInsts);
2503
2513
2514
+ SILValue promoteMarkDepBase (MarkDependenceInst *md,
2515
+ ArrayRef<AvailableValue> availableValues);
2516
+
2504
2517
// / Promote a load take cleaning up everything except for RAUWing the
2505
2518
// / instruction with the aggregated result. The routine returns the new
2506
2519
// / aggregated result to the caller and expects the caller to eventually RAUW
@@ -2552,6 +2565,10 @@ bool OptimizeDeadAlloc::tryToRemoveDeadAllocation() {
2552
2565
2553
2566
SWIFT_DEFER { DataflowContext.fixupOwnership (deleter, deadEndBlocks); };
2554
2567
2568
+ for (auto *md : promotions.markDepBases .instructions ()) {
2569
+ if (!canPromoteMarkDepBase (cast<MarkDependenceInst>(md)))
2570
+ return false ;
2571
+ }
2555
2572
if (isTrivial ()) {
2556
2573
removeDeadAllocation ();
2557
2574
return true ;
@@ -2620,6 +2637,9 @@ SILInstruction *OptimizeDeadAlloc::collectUsesForPromotion() {
2620
2637
}
2621
2638
}
2622
2639
return u.Inst ;
2640
+ case PMOUseKind::DependenceBase:
2641
+ promotions.markDepBases .push (u.Inst );
2642
+ continue ;
2623
2643
case PMOUseKind::Initialization:
2624
2644
if (!isa<ApplyInst>(u.Inst ) &&
2625
2645
// A copy_addr that is not a take affects the retain count
@@ -2652,6 +2672,28 @@ SILInstruction *OptimizeDeadAlloc::collectUsesForPromotion() {
2652
2672
return nullptr ;
2653
2673
}
2654
2674
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
+
2655
2697
// / Return true if we can promote the given destroy.
2656
2698
bool OptimizeDeadAlloc::canPromoteTake (
2657
2699
SILInstruction *inst, PromotableInstructions &promotableInsts) {
@@ -2692,6 +2734,12 @@ bool OptimizeDeadAlloc::canPromoteTake(
2692
2734
}
2693
2735
2694
2736
void 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
+
2695
2743
// If our memory is trivially typed, we can just remove it without needing to
2696
2744
// consider if the stored value needs to be destroyed. So at this point,
2697
2745
// delete the memory!
@@ -2798,6 +2846,23 @@ void OptimizeDeadAlloc::removeDeadAllocation() {
2798
2846
}
2799
2847
}
2800
2848
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
+
2801
2866
SILValue
2802
2867
OptimizeDeadAlloc::promoteLoadTake (LoadInst *li,
2803
2868
ArrayRef<AvailableValue> availableValues) {
0 commit comments