Skip to content

Commit 8a1f2c6

Browse files
authored
Merge pull request #32397 from gottesmm/pr-92e92ba00c4c145dbd650430947c43d7b3a743d5
[ownership] Loosen restrictions around what we specialize and add generic specialization tests behind a flag.
2 parents a94df37 + 1b97c03 commit 8a1f2c6

14 files changed

+2073
-60
lines changed

include/swift/SIL/ApplySite.h

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,11 @@
2121
#ifndef SWIFT_SIL_APPLYSITE_H
2222
#define SWIFT_SIL_APPLYSITE_H
2323

24+
#include "swift/SIL/SILArgument.h"
2425
#include "swift/SIL/SILBasicBlock.h"
25-
#include "swift/SIL/SILInstruction.h"
2626
#include "swift/SIL/SILFunction.h"
27+
#include "swift/SIL/SILInstruction.h"
28+
#include "llvm/ADT/ArrayRef.h"
2729

2830
namespace swift {
2931

@@ -502,6 +504,34 @@ class FullApplySite : public ApplySite {
502504
return getSubstCalleeConv().hasIndirectSILResults();
503505
}
504506

507+
/// If our apply site has a single direct result SILValue, return that
508+
/// SILValue. Return SILValue() otherwise.
509+
///
510+
/// This means that:
511+
///
512+
/// 1. If we have an ApplyInst, we just visit the apply.
513+
/// 2. If we have a TryApplyInst, we visit the first argument of the normal
514+
/// block.
515+
/// 3. If we have a BeginApplyInst, we return SILValue() since the begin_apply
516+
/// yields values instead of returning them. A returned value should only
517+
/// be valid after a full apply site has completely finished executing.
518+
SILValue getSingleDirectResult() const {
519+
switch (getKind()) {
520+
case FullApplySiteKind::ApplyInst:
521+
return SILValue(cast<ApplyInst>(getInstruction()));
522+
case FullApplySiteKind::BeginApplyInst: {
523+
return SILValue();
524+
}
525+
case FullApplySiteKind::TryApplyInst: {
526+
auto *normalBlock = cast<TryApplyInst>(getInstruction())->getNormalBB();
527+
assert(normalBlock->getNumArguments() == 1 &&
528+
"Expected try apply to have a single result");
529+
return normalBlock->getArgument(0);
530+
}
531+
}
532+
llvm_unreachable("Covered switch isn't covered?!");
533+
}
534+
505535
unsigned getNumIndirectSILResults() const {
506536
return getSubstCalleeConv().getNumIndirectSILResults();
507537
}

include/swift/SIL/SILBuilder.h

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -726,7 +726,8 @@ class SILBuilder {
726726
}
727727

728728
LoadBorrowInst *createLoadBorrow(SILLocation Loc, SILValue LV) {
729-
assert(isLoadableOrOpaque(LV->getType()));
729+
assert(isLoadableOrOpaque(LV->getType()) &&
730+
!LV->getType().isTrivial(getFunction()));
730731
return insert(new (getModule())
731732
LoadBorrowInst(getSILDebugLocation(Loc), LV));
732733
}
@@ -737,11 +738,19 @@ class SILBuilder {
737738
BeginBorrowInst(getSILDebugLocation(Loc), LV));
738739
}
739740

741+
/// Convenience function for creating a load_borrow on non-trivial values and
742+
/// load [trivial] on trivial values. Becomes load unqualified in non-ossa
743+
/// functions.
740744
SILValue emitLoadBorrowOperation(SILLocation loc, SILValue v) {
741745
if (!hasOwnership()) {
742746
return emitLoadValueOperation(loc, v,
743747
LoadOwnershipQualifier::Unqualified);
744748
}
749+
750+
if (v->getType().isTrivial(getFunction())) {
751+
return emitLoadValueOperation(loc, v, LoadOwnershipQualifier::Trivial);
752+
}
753+
745754
return createLoadBorrow(loc, v);
746755
}
747756

@@ -877,6 +886,33 @@ class SILBuilder {
877886
StoreBorrowInst(getSILDebugLocation(Loc), Src, DestAddr));
878887
}
879888

889+
/// A helper function for emitting store_borrow in operations where one must
890+
/// handle both ossa and non-ossa code.
891+
///
892+
/// In words:
893+
///
894+
/// * If the function does not have ownership, this just emits an unqualified
895+
/// store.
896+
///
897+
/// * If the function has ownership, but the type is trivial, use store
898+
/// [trivial].
899+
///
900+
/// * Otherwise, emit an actual store_borrow.
901+
void emitStoreBorrowOperation(SILLocation loc, SILValue src,
902+
SILValue destAddr) {
903+
if (!hasOwnership()) {
904+
return emitStoreValueOperation(loc, src, destAddr,
905+
StoreOwnershipQualifier::Unqualified);
906+
}
907+
908+
if (src->getType().isTrivial(getFunction())) {
909+
return emitStoreValueOperation(loc, src, destAddr,
910+
StoreOwnershipQualifier::Trivial);
911+
}
912+
913+
createStoreBorrow(loc, src, destAddr);
914+
}
915+
880916
MarkUninitializedInst *
881917
createMarkUninitialized(SILLocation Loc, SILValue src,
882918
MarkUninitializedInst::Kind k) {

lib/SILOptimizer/Transforms/GenericSpecializer.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@
2828

2929
using namespace swift;
3030

31+
// For testing during bring up.
32+
static llvm::cl::opt<bool> EnableGenericSpecializerWithOwnership(
33+
"sil-generic-specializer-enable-ownership", llvm::cl::init(false));
34+
3135
namespace {
3236

3337
class GenericSpecializer : public SILFunctionTransform {
@@ -39,7 +43,7 @@ class GenericSpecializer : public SILFunctionTransform {
3943
SILFunction &F = *getFunction();
4044

4145
// TODO: We should be able to handle ownership.
42-
if (F.hasOwnership())
46+
if (F.hasOwnership() && !EnableGenericSpecializerWithOwnership)
4347
return;
4448

4549
LLVM_DEBUG(llvm::dbgs() << "***** GenericSpecializer on function:"

lib/SILOptimizer/Utils/GenericCloner.cpp

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,9 @@ void GenericCloner::populateCloned() {
7979

8080
auto createAllocStack = [&]() {
8181
// We need an alloc_stack as a replacement for the indirect parameter.
82-
assert(mappedType.isAddress());
83-
mappedType = mappedType.getObjectType();
82+
if (mappedType.isAddress()) {
83+
mappedType = mappedType.getObjectType();
84+
}
8485
auto AllocStackLoc = RegularLocation::getAutoGeneratedLocation();
8586
ASI = getBuilder().createAllocStack(AllocStackLoc, mappedType);
8687
AllocStacks.push_back(ASI);
@@ -106,24 +107,36 @@ void GenericCloner::populateCloned() {
106107
// Handle arguments for formal parameters.
107108
unsigned paramIdx = ArgIdx - origConv.getSILArgIndexOfFirstParam();
108109
if (ReInfo.isParamConverted(paramIdx)) {
109-
// Store the new direct parameter to the alloc_stack.
110-
createAllocStack();
110+
assert(mappedType.isAddress());
111+
mappedType = mappedType.getObjectType();
111112
auto *NewArg = ClonedEntryBB->createFunctionArgument(
112113
mappedType, OrigArg->getDecl());
113-
getBuilder().createStore(Loc, NewArg, ASI,
114-
StoreOwnershipQualifier::Unqualified);
115114

116-
// Try to create a new debug_value from an existing debug_value_addr.
115+
// Try to create a new debug_value from an existing debug_value_addr
116+
// for the argument. We do this before storing to ensure that when we
117+
// are cloning code in ossa the argument has not been consumed by the
118+
// store below.
117119
for (Operand *ArgUse : OrigArg->getUses()) {
118120
if (auto *DVAI = dyn_cast<DebugValueAddrInst>(ArgUse->getUser())) {
121+
auto *oldScope = getBuilder().getCurrentDebugScope();
119122
getBuilder().setCurrentDebugScope(
120123
remapScope(DVAI->getDebugScope()));
121124
getBuilder().createDebugValue(DVAI->getLoc(), NewArg,
122125
*DVAI->getVarInfo());
123-
getBuilder().setCurrentDebugScope(nullptr);
126+
getBuilder().setCurrentDebugScope(oldScope);
124127
break;
125128
}
126129
}
130+
131+
// Store the new direct parameter to an alloc_stack.
132+
createAllocStack();
133+
if (!NewArg->getArgumentConvention().isGuaranteedConvention()) {
134+
getBuilder().emitStoreValueOperation(Loc, NewArg, ASI,
135+
StoreOwnershipQualifier::Init);
136+
} else {
137+
getBuilder().emitStoreBorrowOperation(Loc, NewArg, ASI);
138+
}
139+
127140
entryArgs.push_back(ASI);
128141
return true;
129142
}
@@ -150,9 +163,9 @@ void GenericCloner::visitTerminator(SILBasicBlock *BB) {
150163
if (ReturnValueAddr) {
151164
// The result is converted from indirect to direct. We have to load the
152165
// returned value from the alloc_stack.
153-
ReturnValue =
154-
getBuilder().createLoad(ReturnValueAddr->getLoc(), ReturnValueAddr,
155-
LoadOwnershipQualifier::Unqualified);
166+
ReturnValue = getBuilder().emitLoadValueOperation(
167+
ReturnValueAddr->getLoc(), ReturnValueAddr,
168+
LoadOwnershipQualifier::Take);
156169
}
157170
for (AllocStackInst *ASI : reverse(AllocStacks)) {
158171
getBuilder().createDeallocStack(ASI->getLoc(), ASI);

0 commit comments

Comments
 (0)