Skip to content

Commit e33ce42

Browse files
committed
[capture-promotion] Eliminate non-OSSA support/tests.
This only runs on OSSA now, so I am deleting the non-OSSA tests and put in an early bail out since there are some tests that have not been updated yet for OSSA, that run the diagnostic passes, but for which this pass never kicked in on. NOTE: I also while updating the tests noticed a bunch were assuming load_borrow like semantics. So I updated them with that in mind and implemented support in the pass for that.
1 parent d1c7890 commit e33ce42

File tree

5 files changed

+253
-794
lines changed

5 files changed

+253
-794
lines changed

lib/SILOptimizer/Mandatory/CapturePromotion.cpp

Lines changed: 43 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
#include "swift/AST/DiagnosticsSIL.h"
4848
#include "swift/AST/GenericEnvironment.h"
4949
#include "swift/Basic/FrozenMultiMap.h"
50+
#include "swift/SIL/OwnershipUtils.h"
5051
#include "swift/SIL/SILCloner.h"
5152
#include "swift/SIL/SILInstruction.h"
5253
#include "swift/SIL/TypeSubstCloner.h"
@@ -313,11 +314,11 @@ class ClosureCloner : public SILClonerWithScopes<ClosureCloner> {
313314
SILValue getProjectBoxMappedVal(SILValue operandValue);
314315

315316
void visitDebugValueAddrInst(DebugValueAddrInst *inst);
316-
void visitStrongReleaseInst(StrongReleaseInst *inst);
317317
void visitDestroyValueInst(DestroyValueInst *inst);
318318
void visitStructElementAddrInst(StructElementAddrInst *inst);
319319
void visitLoadInst(LoadInst *inst);
320320
void visitLoadBorrowInst(LoadBorrowInst *inst);
321+
void visitEndBorrowInst(EndBorrowInst *inst);
321322
void visitProjectBoxInst(ProjectBoxInst *inst);
322323
void visitBeginAccessInst(BeginAccessInst *inst);
323324
void visitEndAccessInst(EndAccessInst *inst);
@@ -467,9 +468,6 @@ ClosureCloner::initCloned(SILOptFunctionBuilder &functionBuilder,
467468
orig->getEffectsKind(), orig, orig->getDebugScope());
468469
for (auto &attr : orig->getSemanticsAttrs())
469470
fn->addSemanticsAttr(attr);
470-
if (!orig->hasOwnership()) {
471-
fn->setOwnershipEliminated();
472-
}
473471
return fn;
474472
}
475473

@@ -510,8 +508,7 @@ void ClosureCloner::populateCloned() {
510508
// If SIL ownership is enabled, we need to perform a borrow here if we have
511509
// a non-trivial value. We know that our value is not written to and it does
512510
// not escape. The use of a borrow enforces this.
513-
if (cloned->hasOwnership() &&
514-
mappedValue.getOwnershipKind() != OwnershipKind::None) {
511+
if (mappedValue.getOwnershipKind() != OwnershipKind::None) {
515512
SILLocation loc(const_cast<ValueDecl *>((*ai)->getDecl()));
516513
mappedValue = getBuilder().emitBeginBorrowOperation(loc, mappedValue);
517514
}
@@ -565,7 +562,6 @@ SILFunction *ClosureCloner::constructClonedFunction(
565562
SILValue ClosureCloner::getProjectBoxMappedVal(SILValue operandValue) {
566563
if (auto *bai = dyn_cast<BeginAccessInst>(operandValue))
567564
operandValue = bai->getSource();
568-
569565
if (auto *pbi = dyn_cast<ProjectBoxInst>(operandValue)) {
570566
auto iter = projectBoxArgumentMap.find(pbi);
571567
if (iter != projectBoxArgumentMap.end())
@@ -586,50 +582,25 @@ void ClosureCloner::visitDebugValueAddrInst(DebugValueAddrInst *inst) {
586582
SILCloner<ClosureCloner>::visitDebugValueAddrInst(inst);
587583
}
588584

589-
/// Handle a strong_release instruction during cloning of a closure; if
590-
/// it is a strong release of a promoted box argument, then it is replaced with
591-
/// a ReleaseValue of the new object type argument, otherwise it is handled
592-
/// normally.
593-
void ClosureCloner::visitStrongReleaseInst(StrongReleaseInst *inst) {
594-
assert(
595-
!inst->getFunction()->hasOwnership() &&
596-
"Should not see strong release in a function with qualified ownership");
597-
SILValue operandValue = inst->getOperand();
598-
if (auto *arg = dyn_cast<SILArgument>(operandValue)) {
599-
auto iter = boxArgumentMap.find(arg);
600-
if (iter != boxArgumentMap.end()) {
601-
// Releases of the box arguments get replaced with ReleaseValue of the new
602-
// object type argument.
603-
auto &typeLowering =
604-
getBuilder().getTypeLowering(iter->second->getType());
605-
SILBuilderWithPostProcess<ClosureCloner, 1> b(this, inst);
606-
typeLowering.emitDestroyValue(b, inst->getLoc(), iter->second);
607-
return;
608-
}
609-
}
610-
611-
SILCloner<ClosureCloner>::visitStrongReleaseInst(inst);
612-
}
613-
614-
/// Handle a destroy_value instruction during cloning of a closure; if
615-
/// it is a strong release of a promoted box argument, then it is replaced with
616-
/// a destroy_value of the new object type argument, otherwise it is handled
585+
/// Handle a destroy_value instruction during cloning of a closure; if it is a
586+
/// destroy_value of a promoted box argument, then it is replaced with a
587+
/// destroy_value of the new object type argument, otherwise it is handled
617588
/// normally.
618589
void ClosureCloner::visitDestroyValueInst(DestroyValueInst *inst) {
619590
SILValue operand = inst->getOperand();
620591
if (auto *arg = dyn_cast<SILArgument>(operand)) {
621592
auto iter = boxArgumentMap.find(arg);
622593
if (iter != boxArgumentMap.end()) {
623-
// Releases of the box arguments get replaced with an end_borrow,
594+
// destroy_value of the box arguments get replaced with an end_borrow,
624595
// destroy_value of the new object type argument.
625596
SILFunction &f = getBuilder().getFunction();
626597
auto &typeLowering = f.getTypeLowering(iter->second->getType());
627598
SILBuilderWithPostProcess<ClosureCloner, 1> b(this, inst);
628599
SILValue value = iter->second;
629600

630-
// If ownership is enabled, then we must emit a begin_borrow for any
631-
// non-trivial value.
632-
if (f.hasOwnership() && value.getOwnershipKind() != OwnershipKind::None) {
601+
// We must have emitted a begin_borrow for any non-trivial value. Insert
602+
// an end_borrow if so.
603+
if (value.getOwnershipKind() != OwnershipKind::None) {
633604
auto *bbi = cast<BeginBorrowInst>(value);
634605
value = bbi->getOperand();
635606
b.emitEndBorrowOperation(inst->getLoc(), bbi);
@@ -643,6 +614,29 @@ void ClosureCloner::visitDestroyValueInst(DestroyValueInst *inst) {
643614
SILCloner<ClosureCloner>::visitDestroyValueInst(inst);
644615
}
645616

617+
/// Handle an end_borrow instruction during cloning of a closure; if it is a
618+
/// end_borrow from a load_borrow of a promoted box argument, then it is
619+
/// deleted, otherwise it is handled normally.
620+
void ClosureCloner::visitEndBorrowInst(EndBorrowInst *inst) {
621+
SILValue operand = inst->getOperand();
622+
623+
if (auto *lbi = dyn_cast<LoadBorrowInst>(operand)) {
624+
SILValue op = lbi->getOperand();
625+
// When we check if we can do this, we only need to look through a single
626+
// struct_element_addr since when checking if this is safe, we only look
627+
// through a single struct_element_addr.
628+
if (auto *sea = dyn_cast<StructElementAddrInst>(op))
629+
op = sea->getOperand();
630+
631+
// If after optionally looking through a gep, we have our project_box, just
632+
// eliminate the end_borrow.
633+
if (getProjectBoxMappedVal(op))
634+
return;
635+
}
636+
637+
SILCloner<ClosureCloner>::visitEndBorrowInst(inst);
638+
}
639+
646640
/// Handle a struct_element_addr instruction during cloning of a closure.
647641
///
648642
/// If its operand is the promoted address argument then ignore it, otherwise it
@@ -798,6 +792,8 @@ static SILArgument *getBoxFromIndex(SILFunction *f, unsigned index) {
798792
}
799793

800794
static bool isNonMutatingLoad(SILInstruction *inst) {
795+
if (isa<LoadBorrowInst>(inst))
796+
return true;
801797
auto *li = dyn_cast<LoadInst>(inst);
802798
if (!li)
803799
return false;
@@ -1573,14 +1569,17 @@ class CapturePromotionPass : public SILModuleTransform {
15731569
void run() override {
15741570
SmallVector<SILFunction *, 128> worklist;
15751571
for (auto &f : *getModule()) {
1576-
if (f.wasDeserializedCanonical())
1572+
if (f.wasDeserializedCanonical() || !f.hasOwnership())
15771573
continue;
15781574

15791575
processFunction(&f, worklist);
15801576
}
15811577

15821578
while (!worklist.empty()) {
1583-
processFunction(worklist.pop_back_val(), worklist);
1579+
auto *f = worklist.pop_back_val();
1580+
if (!f->hasOwnership())
1581+
continue;
1582+
processFunction(f, worklist);
15841583
}
15851584
}
15861585

@@ -1592,6 +1591,9 @@ class CapturePromotionPass : public SILModuleTransform {
15921591

15931592
void CapturePromotionPass::processFunction(
15941593
SILFunction *func, SmallVectorImpl<SILFunction *> &worklist) {
1594+
assert(func->hasOwnership() &&
1595+
"Only can perform capture promotion on functions with ownership. All "
1596+
"functions in raw SIL should have OSSA now out of SILGen");
15951597
LLVM_DEBUG(llvm::dbgs() << "******** Performing Capture Promotion on: "
15961598
<< func->getName() << "********\n");
15971599
// This is a map from each partial apply to a set of indices of promotable

0 commit comments

Comments
 (0)