Skip to content

Commit f353c40

Browse files
authored
Revert "[SILOptimizer] Generalize optimization of static keypaths"
1 parent 8c2cff8 commit f353c40

File tree

8 files changed

+121
-1222
lines changed

8 files changed

+121
-1222
lines changed

include/swift/SILOptimizer/Utils/KeyPathProjector.h

Lines changed: 0 additions & 84 deletions
This file was deleted.

lib/SILGen/SILGen.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1460,7 +1460,6 @@ void SILGenModule::tryEmitPropertyDescriptor(AbstractStorageDecl *decl) {
14601460
baseOperand, needsGenericContext,
14611461
subs, decl, {},
14621462
baseTy->getCanonicalType(),
1463-
M.getSwiftModule(),
14641463
/*property descriptor*/ true);
14651464

14661465
(void)SILProperty::create(M, /*serialized*/ false, decl, component);

lib/SILGen/SILGen.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,6 @@ class LLVM_LIBRARY_VISIBILITY SILGenModule : public ASTVisitor<SILGenModule> {
339339
AbstractStorageDecl *storage,
340340
ArrayRef<ProtocolConformanceRef> indexHashables,
341341
CanType baseTy,
342-
DeclContext *useDC,
343342
bool forPropertyDescriptor);
344343

345344
/// Known functions for bridging.

lib/SILGen/SILGenExpr.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3401,7 +3401,6 @@ SILGenModule::emitKeyPathComponentForDecl(SILLocation loc,
34013401
AbstractStorageDecl *storage,
34023402
ArrayRef<ProtocolConformanceRef> indexHashables,
34033403
CanType baseTy,
3404-
DeclContext *useDC,
34053404
bool forPropertyDescriptor) {
34063405
auto baseDecl = storage;
34073406

@@ -3471,8 +3470,8 @@ SILGenModule::emitKeyPathComponentForDecl(SILLocation loc,
34713470
// supply the settability if needed. We only reference it here if the
34723471
// setter is public.
34733472
if (shouldUseExternalKeyPathComponent())
3474-
return storage->isSettable(useDC)
3475-
&& storage->isSetterAccessibleFrom(useDC);
3473+
return storage->isSettable(M.getSwiftModule())
3474+
&& storage->isSetterAccessibleFrom(M.getSwiftModule());
34763475
return storage->isSettable(storage->getDeclContext());
34773476
};
34783477

@@ -3626,7 +3625,6 @@ RValue RValueEmitter::visitKeyPathExpr(KeyPathExpr *E, SGFContext C) {
36263625
decl,
36273626
component.getSubscriptIndexHashableConformances(),
36283627
baseTy,
3629-
SGF.FunctionDC,
36303628
/*for descriptor*/ false));
36313629
baseTy = loweredComponents.back().getComponentType();
36323630
if (kind == KeyPathExpr::Component::Kind::Property)

lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp

Lines changed: 114 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,11 @@
2828
#include "swift/SILOptimizer/Analysis/ValueTracking.h"
2929
#include "swift/SILOptimizer/Utils/CFGOptUtils.h"
3030
#include "swift/SILOptimizer/Utils/Existential.h"
31-
#include "swift/SILOptimizer/Utils/KeyPathProjector.h"
3231
#include "swift/SILOptimizer/Utils/ValueLifetime.h"
3332
#include "llvm/ADT/DenseMap.h"
3433
#include "llvm/ADT/SmallPtrSet.h"
3534
#include "llvm/ADT/SmallVector.h"
3635
#include "llvm/ADT/Statistic.h"
37-
#include <utility>
3836

3937
using namespace swift;
4038
using namespace swift::PatternMatch;
@@ -209,6 +207,92 @@ SILCombiner::optimizeApplyOfConvertFunctionInst(FullApplySite AI,
209207
return NAI;
210208
}
211209

210+
/// Ends the begin_access "scope" if a begin_access was inserted for optimizing
211+
/// a keypath pattern.
212+
static void insertEndAccess(BeginAccessInst *&beginAccess, bool isModify,
213+
SILBuilder &builder) {
214+
if (beginAccess) {
215+
builder.createEndAccess(beginAccess->getLoc(), beginAccess,
216+
/*aborted*/ false);
217+
if (isModify)
218+
beginAccess->setAccessKind(SILAccessKind::Modify);
219+
beginAccess = nullptr;
220+
}
221+
}
222+
223+
/// Creates the projection pattern for a keypath instruction.
224+
///
225+
/// Currently only the StoredProperty pattern is handled.
226+
/// TODO: handle other patterns, like getters/setters, optional chaining, etc.
227+
///
228+
/// Returns false if \p keyPath is not a keypath instruction or if there is any
229+
/// other reason why the optimization cannot be done.
230+
static SILValue createKeypathProjections(SILValue keyPath, SILValue root,
231+
SILLocation loc,
232+
BeginAccessInst *&beginAccess,
233+
SILBuilder &builder) {
234+
if (auto *upCast = dyn_cast<UpcastInst>(keyPath))
235+
keyPath = upCast->getOperand();
236+
237+
// Is it a keypath instruction at all?
238+
auto *kpInst = dyn_cast<KeyPathInst>(keyPath);
239+
if (!kpInst || !kpInst->hasPattern())
240+
return SILValue();
241+
242+
auto components = kpInst->getPattern()->getComponents();
243+
244+
// Check if the keypath only contains patterns which we support.
245+
for (const KeyPathPatternComponent &comp : components) {
246+
if (comp.getKind() != KeyPathPatternComponent::Kind::StoredProperty)
247+
return SILValue();
248+
}
249+
250+
SILValue addr = root;
251+
for (const KeyPathPatternComponent &comp : components) {
252+
assert(comp.getKind() == KeyPathPatternComponent::Kind::StoredProperty);
253+
VarDecl *storedProperty = comp.getStoredPropertyDecl();
254+
SILValue elementAddr;
255+
if (addr->getType().getStructOrBoundGenericStruct()) {
256+
addr = builder.createStructElementAddr(loc, addr, storedProperty);
257+
} else if (addr->getType().getClassOrBoundGenericClass()) {
258+
SingleValueInstruction *Ref = builder.createLoad(loc, addr,
259+
LoadOwnershipQualifier::Unqualified);
260+
insertEndAccess(beginAccess, /*isModify*/ false, builder);
261+
262+
// Handle the case where the storedProperty is in a super class.
263+
while (Ref->getType().getClassOrBoundGenericClass() !=
264+
storedProperty->getDeclContext()) {
265+
SILType superCl = Ref->getType().getSuperclass();
266+
if (!superCl) {
267+
// This should never happen, because the property should be in the
268+
// decl or in a superclass of it. Just handle this to be on the safe
269+
// side.
270+
return SILValue();
271+
}
272+
Ref = builder.createUpcast(loc, Ref, superCl);
273+
}
274+
275+
addr = builder.createRefElementAddr(loc, Ref, storedProperty);
276+
277+
// Class members need access enforcement.
278+
if (builder.getModule().getOptions().EnforceExclusivityDynamic) {
279+
beginAccess = builder.createBeginAccess(loc, addr, SILAccessKind::Read,
280+
SILAccessEnforcement::Dynamic,
281+
/*noNestedConflict*/ false,
282+
/*fromBuiltin*/ false);
283+
addr = beginAccess;
284+
}
285+
} else {
286+
// This should never happen, as a stored-property pattern can only be
287+
// applied to classes and structs. But to be safe - and future prove -
288+
// let's handle this case and bail.
289+
insertEndAccess(beginAccess, /*isModify*/ false, builder);
290+
return SILValue();
291+
}
292+
}
293+
return addr;
294+
}
295+
212296
/// Try to optimize a keypath application with an apply instruction.
213297
///
214298
/// Replaces (simplified SIL):
@@ -227,40 +311,36 @@ bool SILCombiner::tryOptimizeKeypath(ApplyInst *AI) {
227311
return false;
228312

229313
SILValue keyPath, rootAddr, valueAddr;
230-
bool isSet = false;
314+
bool isModify = false;
231315
if (callee->getName() == "swift_setAtWritableKeyPath" ||
232316
callee->getName() == "swift_setAtReferenceWritableKeyPath") {
233317
keyPath = AI->getArgument(1);
234318
rootAddr = AI->getArgument(0);
235319
valueAddr = AI->getArgument(2);
236-
isSet = true;
320+
isModify = true;
237321
} else if (callee->getName() == "swift_getAtKeyPath") {
238322
keyPath = AI->getArgument(2);
239323
rootAddr = AI->getArgument(1);
240324
valueAddr = AI->getArgument(0);
241325
} else {
242326
return false;
243327
}
244-
245-
auto projector = KeyPathProjector::create(keyPath, rootAddr,
246-
AI->getLoc(), Builder);
247-
if (!projector)
328+
329+
BeginAccessInst *beginAccess = nullptr;
330+
SILValue projectedAddr = createKeypathProjections(keyPath, rootAddr,
331+
AI->getLoc(), beginAccess,
332+
Builder);
333+
if (!projectedAddr)
248334
return false;
249-
250-
KeyPathProjector::AccessType accessType;
251-
if (isSet) accessType = KeyPathProjector::AccessType::Set;
252-
else accessType = KeyPathProjector::AccessType::Get;
253-
254-
projector->project(accessType, [&](SILValue projectedAddr) {
255-
if (isSet) {
256-
Builder.createCopyAddr(AI->getLoc(), valueAddr, projectedAddr,
257-
IsTake, IsInitialization);
258-
} else {
259-
Builder.createCopyAddr(AI->getLoc(), projectedAddr, valueAddr,
260-
IsNotTake, IsInitialization);
261-
}
262-
});
263-
335+
336+
if (isModify) {
337+
Builder.createCopyAddr(AI->getLoc(), valueAddr, projectedAddr,
338+
IsTake, IsNotInitialization);
339+
} else {
340+
Builder.createCopyAddr(AI->getLoc(), projectedAddr, valueAddr,
341+
IsNotTake, IsInitialization);
342+
}
343+
insertEndAccess(beginAccess, isModify, Builder);
264344
eraseInstFromFunction(*AI);
265345
++NumOptimizedKeypaths;
266346
return true;
@@ -305,24 +385,19 @@ bool SILCombiner::tryOptimizeInoutKeypath(BeginApplyInst *AI) {
305385
EndApplyInst *endApply = dyn_cast<EndApplyInst>(AIUse->getUser());
306386
if (!endApply)
307387
return false;
308-
309-
auto projector = KeyPathProjector::create(keyPath, rootAddr,
310-
AI->getLoc(), Builder);
311-
if (!projector)
388+
389+
BeginAccessInst *beginAccess = nullptr;
390+
SILValue projectedAddr = createKeypathProjections(keyPath, rootAddr,
391+
AI->getLoc(), beginAccess,
392+
Builder);
393+
if (!projectedAddr)
312394
return false;
313-
314-
KeyPathProjector::AccessType accessType;
315-
if (isModify) accessType = KeyPathProjector::AccessType::Modify;
316-
else accessType = KeyPathProjector::AccessType::Get;
317-
318-
projector->project(accessType, [&](SILValue projectedAddr) {
319-
// Replace the projected address.
320-
valueAddr->replaceAllUsesWith(projectedAddr);
321-
322-
// Skip to the end of the key path application before cleaning up.
323-
Builder.setInsertionPoint(endApply);
324-
});
325395

396+
// Replace the projected address.
397+
valueAddr->replaceAllUsesWith(projectedAddr);
398+
399+
Builder.setInsertionPoint(endApply);
400+
insertEndAccess(beginAccess, isModify, Builder);
326401
eraseInstFromFunction(*endApply);
327402
eraseInstFromFunction(*AI);
328403
++NumOptimizedKeypaths;

lib/SILOptimizer/Utils/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ silopt_register_sources(
1111
GenericCloner.cpp
1212
Generics.cpp
1313
InstOptUtils.cpp
14-
KeyPathProjector.cpp
1514
LoadStoreOptUtils.cpp
1615
LoopUtils.cpp
1716
OptimizerStatsUtils.cpp

0 commit comments

Comments
 (0)