Skip to content

Commit 1b97c03

Browse files
committed
[ownership] Loosen restrictions around what we specialize and add generic specialization tests behind a flag.
The idea is that this will let me remove these assertions that were in place to make sure we were really conservative around specializing ownership code. For me to remove that I need to be able to actually test out this code (since I think there are some code paths where this will trigger in other parts of the compiler now). So to work out the kinks, I added a flag that allows for the generic specializer to process ownership code and translated most of the .sil test cases/fixed any bugs that I found. This hopefully will expose anything that is missing. NOTE: I have not enabled the generic specializer running in ownership in the pipeline. This is just a step in that direction by adding tests/etc.
1 parent fbec91a commit 1b97c03

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)