|
145 | 145 | #include "swift/SIL/PrunedLiveness.h"
|
146 | 146 | #include "swift/SIL/SILArgument.h"
|
147 | 147 | #include "swift/SIL/SILBuilder.h"
|
| 148 | +#include "swift/SIL/SILInstruction.h" |
| 149 | +#include "swift/SIL/SILValue.h" |
148 | 150 | #include "swift/SIL/SILVisitor.h"
|
149 | 151 | #include "swift/SILOptimizer/Analysis/PostOrderAnalysis.h"
|
150 | 152 | #include "swift/SILOptimizer/PassManager/Transforms.h"
|
@@ -432,6 +434,9 @@ struct AddressLoweringState {
|
432 | 434 | // All function-exiting terminators (return or throw instructions).
|
433 | 435 | SmallVector<TermInst *, 8> exitingInsts;
|
434 | 436 |
|
| 437 | + // All instructions that yield values to callees. |
| 438 | + TinyPtrVector<YieldInst *> yieldInsts; |
| 439 | + |
435 | 440 | // Handle moves from a phi's operand storage to the phi storage.
|
436 | 441 | std::unique_ptr<PhiRewriter> phiRewriter;
|
437 | 442 |
|
@@ -616,6 +621,10 @@ void OpaqueValueVisitor::mapValueStorage() {
|
616 | 621 | if (auto apply = FullApplySite::isa(&inst))
|
617 | 622 | checkForIndirectApply(apply);
|
618 | 623 |
|
| 624 | + if (auto *yieldInst = dyn_cast<YieldInst>(&inst)) { |
| 625 | + pass.yieldInsts.push_back(yieldInst); |
| 626 | + } |
| 627 | + |
619 | 628 | for (auto result : inst.getResults()) {
|
620 | 629 | if (isPseudoCallResult(result) || isPseudoReturnValue(result))
|
621 | 630 | continue;
|
@@ -2130,7 +2139,7 @@ static void emitEndBorrows(SILValue value, AddressLoweringState &pass);
|
2130 | 2139 | void ApplyRewriter::convertBeginApplyWithOpaqueYield() {
|
2131 | 2140 | // Avoid revisiting this apply.
|
2132 | 2141 | bool erased = pass.indirectApplies.erase(apply);
|
2133 |
| - assert(erased && "all yields should be rewritten at the same time"); |
| 2142 | + assert(erased && "all begin_applies should be rewritten at the same time"); |
2134 | 2143 | (void)erased;
|
2135 | 2144 |
|
2136 | 2145 | auto *origCall = cast<BeginApplyInst>(apply.getInstruction());
|
@@ -2591,6 +2600,119 @@ void ReturnRewriter::rewriteElement(SILValue oldResult,
|
2591 | 2600 | }
|
2592 | 2601 | }
|
2593 | 2602 |
|
| 2603 | +//===----------------------------------------------------------------------===// |
| 2604 | +// YieldRewriter |
| 2605 | +// |
| 2606 | +// Rewrite return instructions for indirect results. |
| 2607 | +//===----------------------------------------------------------------------===// |
| 2608 | + |
| 2609 | +class YieldRewriter { |
| 2610 | + AddressLoweringState &pass; |
| 2611 | + SILFunctionConventions opaqueFnConv; |
| 2612 | + |
| 2613 | +public: |
| 2614 | + YieldRewriter(AddressLoweringState &pass) |
| 2615 | + : pass(pass), opaqueFnConv(pass.function->getConventions()) {} |
| 2616 | + |
| 2617 | + void rewriteYields(); |
| 2618 | + |
| 2619 | + void rewriteYield(YieldInst *yieldInst); |
| 2620 | + |
| 2621 | +protected: |
| 2622 | + void rewriteOperand(YieldInst *yieldInst, unsigned index); |
| 2623 | +}; |
| 2624 | + |
| 2625 | +void YieldRewriter::rewriteYields() { |
| 2626 | + for (auto *yield : pass.yieldInsts) { |
| 2627 | + rewriteYield(yield); |
| 2628 | + } |
| 2629 | +} |
| 2630 | + |
| 2631 | +void YieldRewriter::rewriteYield(YieldInst *yieldInst) { |
| 2632 | + for (unsigned index = 0, count = yieldInst->getNumOperands(); index < count; |
| 2633 | + ++index) { |
| 2634 | + rewriteOperand(yieldInst, index); |
| 2635 | + } |
| 2636 | +} |
| 2637 | +void YieldRewriter::rewriteOperand(YieldInst *yieldInst, unsigned index) { |
| 2638 | + auto info = opaqueFnConv.getYieldInfoForOperandIndex(index); |
| 2639 | + auto convention = info.getConvention(); |
| 2640 | + auto ty = |
| 2641 | + opaqueFnConv.getSILType(info, pass.function->getTypeExpansionContext()); |
| 2642 | + if (ty.isAddressOnly(*pass.function)) { |
| 2643 | + assert(yieldInst->getOperand(index)->getType().isAddress() && |
| 2644 | + "rewriting yield of of address-only value after use rewriting!?"); |
| 2645 | + return; |
| 2646 | + } |
| 2647 | + |
| 2648 | + OwnershipKind ownership = OwnershipKind::None; |
| 2649 | + switch (convention) { |
| 2650 | + case ParameterConvention::Direct_Unowned: |
| 2651 | + case ParameterConvention::Direct_Guaranteed: |
| 2652 | + case ParameterConvention::Direct_Owned: |
| 2653 | + return; |
| 2654 | + case ParameterConvention::Indirect_Inout: |
| 2655 | + case ParameterConvention::Indirect_InoutAliasable: |
| 2656 | + return; |
| 2657 | + case ParameterConvention::Indirect_In: |
| 2658 | + case ParameterConvention::Indirect_In_Constant: |
| 2659 | + ownership = OwnershipKind::Owned; |
| 2660 | + break; |
| 2661 | + case ParameterConvention::Indirect_In_Guaranteed: |
| 2662 | + ownership = OwnershipKind::Guaranteed; |
| 2663 | + } |
| 2664 | + |
| 2665 | + if (ty.isTrivial(*pass.function)) |
| 2666 | + ownership = OwnershipKind::None; |
| 2667 | + |
| 2668 | + auto operand = yieldInst->getOperand(index); |
| 2669 | + |
| 2670 | + auto builder = pass.getBuilder(yieldInst->getIterator()); |
| 2671 | + |
| 2672 | + auto *asi = builder.createAllocStack(yieldInst->getLoc(), ty); |
| 2673 | + |
| 2674 | + auto withSuccessorBuilders = [&](auto perform) { |
| 2675 | + auto *resumeBB = &yieldInst->getResumeBB()->front(); |
| 2676 | + auto *unwindBB = &yieldInst->getUnwindBB()->front(); |
| 2677 | + auto resumeBuilder = pass.getBuilder(resumeBB->getIterator()); |
| 2678 | + auto unwindBuilder = pass.getBuilder(unwindBB->getIterator()); |
| 2679 | + perform(resumeBuilder, resumeBB->getLoc()); |
| 2680 | + perform(unwindBuilder, unwindBB->getLoc()); |
| 2681 | + }; |
| 2682 | + |
| 2683 | + switch (ownership) { |
| 2684 | + case OwnershipKind::Owned: |
| 2685 | + case OwnershipKind::None: |
| 2686 | + builder.createStore(yieldInst->getLoc(), operand, asi, |
| 2687 | + ownership == OwnershipKind::None |
| 2688 | + ? StoreOwnershipQualifier::Trivial |
| 2689 | + : StoreOwnershipQualifier::Init); |
| 2690 | + yieldInst->setOperand(index, asi); |
| 2691 | + withSuccessorBuilders( |
| 2692 | + [&](auto builder, auto loc) { builder.createDeallocStack(loc, asi); }); |
| 2693 | + break; |
| 2694 | + case OwnershipKind::Guaranteed: { |
| 2695 | + BeginBorrowInst *bbi = nullptr; |
| 2696 | + if (operand->getOwnershipKind() == OwnershipKind::Owned) { |
| 2697 | + bbi = builder.createBeginBorrow(yieldInst->getLoc(), operand); |
| 2698 | + } |
| 2699 | + auto *storeBorrow = builder.createStoreBorrow(yieldInst->getLoc(), |
| 2700 | + bbi ? bbi : operand, asi); |
| 2701 | + yieldInst->setOperand(index, storeBorrow); |
| 2702 | + withSuccessorBuilders([&](auto builder, auto loc) { |
| 2703 | + builder.createEndBorrow(loc, storeBorrow); |
| 2704 | + if (bbi) |
| 2705 | + builder.createEndBorrow(loc, bbi); |
| 2706 | + builder.createDeallocStack(loc, asi); |
| 2707 | + }); |
| 2708 | + break; |
| 2709 | + } |
| 2710 | + case OwnershipKind::Unowned: |
| 2711 | + case OwnershipKind::Any: |
| 2712 | + llvm_unreachable("unexpected ownership kind!?"); |
| 2713 | + } |
| 2714 | +} |
| 2715 | + |
2594 | 2716 | //===----------------------------------------------------------------------===//
|
2595 | 2717 | // UseRewriter
|
2596 | 2718 | //
|
@@ -3522,6 +3644,8 @@ static void rewriteFunction(AddressLoweringState &pass) {
|
3522 | 3644 | // projection operands.
|
3523 | 3645 | if (pass.function->getLoweredFunctionType()->hasIndirectFormalResults())
|
3524 | 3646 | ReturnRewriter(pass).rewriteReturns();
|
| 3647 | + if (pass.function->getLoweredFunctionType()->hasIndirectFormalYields()) |
| 3648 | + YieldRewriter(pass).rewriteYields(); |
3525 | 3649 | }
|
3526 | 3650 |
|
3527 | 3651 | // Given an array of terminator operand values, produce an array of
|
|
0 commit comments