Skip to content

Commit 1dea855

Browse files
[Prototype] Implement public KeyPath elimination
1 parent 5d22d4f commit 1dea855

File tree

5 files changed

+103
-16
lines changed

5 files changed

+103
-16
lines changed

include/swift/SIL/SILInstruction.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2953,7 +2953,10 @@ class KeyPathPatternComponent {
29532953
void visitReferencedFunctionsAndMethods(
29542954
std::function<void (SILFunction *)> functionCallBack,
29552955
std::function<void (SILDeclRef)> methodCallBack) const;
2956-
2956+
2957+
void clearReferencedFunctions_if(
2958+
llvm::function_ref<bool(SILFunction *)> predicate);
2959+
29572960
void incrementRefCounts() const;
29582961
void decrementRefCounts() const;
29592962

include/swift/SIL/SILProperty.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,14 @@ class SILProperty : public llvm::ilist_node<SILProperty>,
6767
const Optional<KeyPathPatternComponent> &getComponent() const {
6868
return Component;
6969
}
70-
70+
71+
void clearReferencedFunctions_if(
72+
llvm::function_ref<bool(SILFunction *)> predicate) {
73+
if (Component) {
74+
Component->clearReferencedFunctions_if(predicate);
75+
}
76+
}
77+
7178
void print(SILPrintContext &Ctx) const;
7279
void dump() const;
7380

lib/IRGen/GenKeyPath.cpp

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,11 @@ getAccessorForComputedComponent(IRGenModule &IGM,
119119
accessor = component.getSubscriptIndexHash();
120120
break;
121121
}
122-
122+
123+
if (!accessor) {
124+
return nullptr;
125+
}
126+
123127
// If the accessor is not generic, and locally available, we can use it as is.
124128
// If it's only externally available, we need a local thunk to relative-
125129
// reference.
@@ -510,10 +514,18 @@ getWitnessTableForComputedComponent(IRGenModule &IGM,
510514
fields.addNullPointer(IGM.FunctionPtrTy);
511515
fields.addSignedPointer(copy, schemaKeyPath,
512516
PointerAuthEntity::Special::KeyPathCopy);
513-
fields.addSignedPointer(equals, schemaKeyPath,
514-
PointerAuthEntity::Special::KeyPathEquals);
515-
fields.addSignedPointer(hash, schemaKeyPath,
516-
PointerAuthEntity::Special::KeyPathHash);
517+
if (equals)
518+
fields.addSignedPointer(equals, schemaKeyPath,
519+
PointerAuthEntity::Special::KeyPathEquals);
520+
else
521+
fields.addNullPointer(IGM.FunctionPtrTy);
522+
523+
if (hash)
524+
fields.addSignedPointer(hash, schemaKeyPath,
525+
PointerAuthEntity::Special::KeyPathHash);
526+
else
527+
fields.addNullPointer(IGM.FunctionPtrTy);
528+
517529
return fields.finishAndCreateGlobal(
518530
"keypath_witnesses", IGM.getPointerAlignment(), /*constant*/ true,
519531
llvm::GlobalVariable::PrivateLinkage);
@@ -914,6 +926,11 @@ emitKeyPathComponent(IRGenModule &IGM,
914926
switch (id.getKind()) {
915927
case KeyPathPatternComponent::ComputedPropertyId::Function: {
916928
idKind = KeyPathComponentHeader::Pointer;
929+
if (!id.getFunction()) {
930+
idValue = nullptr;
931+
idResolution = KeyPathComponentHeader::Resolved;
932+
break;
933+
}
917934
// FIXME: Does this need to be signed?
918935
auto idRef = IGM.getAddrOfLLVMVariableOrGOTEquivalent(
919936
LinkEntity::forSILFunction(id.getFunction(), false));
@@ -1066,7 +1083,7 @@ emitKeyPathComponent(IRGenModule &IGM,
10661083
switch (idKind) {
10671084
case KeyPathComponentHeader::Pointer:
10681085
// Use a relative offset to the referent.
1069-
fields.addRelativeAddress(idValue);
1086+
fields.addRelativeAddressOrNull(idValue);
10701087
break;
10711088

10721089
case KeyPathComponentHeader::VTableOffset:
@@ -1077,15 +1094,12 @@ emitKeyPathComponent(IRGenModule &IGM,
10771094
}
10781095

10791096
// Push the accessors, possibly thunked to marshal generic environment.
1080-
fields.addRelativeAddress(
1081-
getAccessorForComputedComponent(IGM, component, Getter,
1082-
genericEnv, requirements,
1083-
hasSubscriptIndices));
1097+
fields.addRelativeAddressOrNull(getAccessorForComputedComponent(
1098+
IGM, component, Getter, genericEnv, requirements, hasSubscriptIndices));
10841099
if (settable)
1085-
fields.addRelativeAddress(
1086-
getAccessorForComputedComponent(IGM, component, Setter,
1087-
genericEnv, requirements,
1088-
hasSubscriptIndices));
1100+
fields.addRelativeAddressOrNull(
1101+
getAccessorForComputedComponent(IGM, component, Setter, genericEnv,
1102+
requirements, hasSubscriptIndices));
10891103

10901104
if (!isInstantiableOnce) {
10911105
// If there's generic context or subscript indexes, embed as

lib/SIL/IR/SILInstructions.cpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2530,6 +2530,57 @@ forEachRefcountableReference(const KeyPathPatternComponent &component,
25302530
}
25312531
}
25322532

2533+
void KeyPathPatternComponent::clearReferencedFunctions_if(
2534+
llvm::function_ref<bool(SILFunction *)> predicate) {
2535+
switch (getKind()) {
2536+
case KeyPathPatternComponent::Kind::StoredProperty:
2537+
case KeyPathPatternComponent::Kind::OptionalChain:
2538+
case KeyPathPatternComponent::Kind::OptionalWrap:
2539+
case KeyPathPatternComponent::Kind::OptionalForce:
2540+
case KeyPathPatternComponent::Kind::TupleElement:
2541+
return;
2542+
case KeyPathPatternComponent::Kind::SettableProperty: {
2543+
auto setter = getComputedPropertySetter();
2544+
if (predicate(setter)) {
2545+
SetterAndIdKind.setPointer(nullptr);
2546+
}
2547+
LLVM_FALLTHROUGH;
2548+
}
2549+
case KeyPathPatternComponent::Kind::GettableProperty:
2550+
auto getter = getComputedPropertyGetter();
2551+
if (predicate(getter)) {
2552+
ValueAndKind.setPointer(nullptr);
2553+
}
2554+
switch (getComputedPropertyId().getKind()) {
2555+
case KeyPathPatternComponent::ComputedPropertyId::DeclRef:
2556+
// Mark the vtable entry as used somehow?
2557+
break;
2558+
case KeyPathPatternComponent::ComputedPropertyId::Function: {
2559+
auto idFn = getComputedPropertyId().getFunction();
2560+
if (predicate(idFn)) {
2561+
IdValue = ComputedPropertyId::ValueType();
2562+
}
2563+
break;
2564+
}
2565+
case KeyPathPatternComponent::ComputedPropertyId::Property:
2566+
break;
2567+
}
2568+
2569+
if (auto equals = getSubscriptIndexEquals()) {
2570+
if (predicate(equals)) {
2571+
IndexEquality.Equal = nullptr;
2572+
}
2573+
}
2574+
2575+
if (auto hash = getSubscriptIndexHash()) {
2576+
if (predicate(hash)) {
2577+
IndexEquality.Hash = nullptr;
2578+
}
2579+
}
2580+
return;
2581+
}
2582+
}
2583+
25332584
void KeyPathPatternComponent::incrementRefCounts() const {
25342585
forEachRefcountableReference(*this,
25352586
[&](SILFunction *f) { f->incrementRefCount(); });

lib/SILOptimizer/IPO/CrossDeadFunctionElimination.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,17 @@ class SILCrossDeadFuncElimination : public SILModuleTransform {
113113
}
114114
}
115115

116+
void cleanupSILProperty(SILModule &M,
117+
const std::vector<SILFunction *> &DeadFunctions) {
118+
std::set<SILFunction *> DeadFunctionsSet(DeadFunctions.begin(),
119+
DeadFunctions.end());
120+
for (SILProperty &P : M.getPropertyList()) {
121+
P.clearReferencedFunctions_if([&](SILFunction *f) {
122+
return DeadFunctionsSet.find(f) != DeadFunctionsSet.end();
123+
});
124+
}
125+
}
126+
116127
void run() override {
117128
LLVM_DEBUG(llvm::dbgs() << "Running CrossDeadFuncElimination\n");
118129
auto &Context = getModule()->getASTContext();
@@ -134,6 +145,7 @@ class SILCrossDeadFuncElimination : public SILModuleTransform {
134145
this->eliminateDeadEntriesFromTables(M);
135146
std::vector<SILFunction *> DeadFunctions;
136147
this->eliminateDeadFunctions(M, DeadFunctions);
148+
this->cleanupSILProperty(M, DeadFunctions);
137149

138150
while (!DeadFunctions.empty()) {
139151
SILFunction *F = DeadFunctions.back();

0 commit comments

Comments
 (0)