Skip to content

Commit b952184

Browse files
authored
Merge pull request swiftlang#42191 from eeckstein/small-optimizer-tweaks
Some small optimizer tweaks
2 parents b74b044 + 07f2ec3 commit b952184

File tree

10 files changed

+95
-63
lines changed

10 files changed

+95
-63
lines changed

SwiftCompilerSources/Sources/Optimizer/Analysis/CalleeAnalysis.swift

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,32 @@ import SIL
1616
public struct CalleeAnalysis {
1717
let bridged: BridgedCalleeAnalysis
1818

19-
public func getCallees(callee: Value) -> FunctionArray {
19+
public func getCallees(callee: Value) -> FunctionArray? {
20+
let bridgedFuncs = CalleeAnalysis_getCallees(bridged, callee.bridged)
21+
if bridgedFuncs.incomplete != 0 {
22+
return nil
23+
}
24+
return FunctionArray(bridged: bridgedFuncs)
25+
}
26+
27+
public func getIncompleteCallees(callee: Value) -> FunctionArray {
2028
return FunctionArray(bridged: CalleeAnalysis_getCallees(bridged, callee.bridged))
2129
}
2230

23-
public func getDestructors(destroyInst: Instruction) -> FunctionArray {
24-
return FunctionArray(bridged:
25-
CalleeAnalysis_getInstCallees(bridged, destroyInst.bridged))
31+
public func getDestructor(ofExactType type: Type) -> Function? {
32+
let destructors = FunctionArray(bridged: CalleeAnalysis_getDestructors(bridged, type.bridged, /*isExactType*/ 1))
33+
if destructors.count == 1 {
34+
return destructors[0]
35+
}
36+
return nil
37+
}
38+
39+
public func getDestructors(of type: Type) -> FunctionArray? {
40+
let bridgedDtors = CalleeAnalysis_getDestructors(bridged, type.bridged, /*isExactType*/ 0)
41+
if bridgedDtors.incomplete != 0 {
42+
return nil
43+
}
44+
return FunctionArray(bridged: bridgedDtors)
2645
}
2746
}
2847

@@ -35,6 +54,4 @@ public struct FunctionArray : RandomAccessCollection, FormattedLikeArray {
3554
public subscript(_ index: Int) -> Function {
3655
return BridgedFunctionArray_get(bridged, index).function
3756
}
38-
39-
public var allCalleesKnown: Bool { bridged.incomplete == 0 }
4057
}

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/ReleaseDevirtualizer.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ private func tryDevirtualizeReleaseOfObject(
8282

8383
let type = allocRefInstruction.type
8484

85-
guard let dealloc = context.getDestructor(ofClass: type) else {
85+
guard let dealloc = context.calleeAnalysis.getDestructor(ofExactType: type) else {
8686
return
8787
}
8888

SwiftCompilerSources/Sources/Optimizer/InstructionPasses/SimplifyGlobalValue.swift

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37,22 +37,20 @@ let simplifyGlobalValuePass = InstructionPass<GlobalValueInst>(
3737
private func checkUsers(of val: Value, users: inout Stack<Instruction>) -> Bool {
3838
for use in val.uses {
3939
let user = use.instruction
40-
if user is RefCountingInst || user is DebugValueInst {
41-
users.push(user)
42-
continue
43-
}
44-
if let upCast = user as? UpcastInst {
45-
if !checkUsers(of: upCast, users: &users) {
40+
switch user {
41+
case is RefCountingInst, is DebugValueInst, is FixLifetimeInst:
42+
users.push(user)
43+
case let upCast as UpcastInst:
44+
if !checkUsers(of: upCast, users: &users) {
45+
return false
46+
}
47+
case is RefElementAddrInst, is RefTailAddrInst:
48+
// Projection instructions don't access the object header, so they don't
49+
// prevent deleting reference counting instructions.
50+
break
51+
default:
4652
return false
47-
}
48-
continue
49-
}
50-
// Projection instructions don't access the object header, so they don't
51-
// prevent deleting reference counting instructions.
52-
if user is RefElementAddrInst || user is RefTailAddrInst {
53-
continue
5453
}
55-
return false
5654
}
5755
return true
5856
}

SwiftCompilerSources/Sources/Optimizer/PassManager/PassUtils.swift

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,6 @@ struct PassContext {
112112
PassContext_fixStackNesting(_bridged, function.bridged)
113113
}
114114

115-
func getDestructor(ofClass type: Type) -> Function? {
116-
PassContext_getDestructor(_bridged, type.bridged).function
117-
}
118-
119115
func getContextSubstitutionMap(for type: Type) -> SubstitutionMap {
120116
SubstitutionMap(PassContext_getContextSubstitutionMap(_bridged, type.bridged))
121117
}

include/swift/SILOptimizer/Analysis/BasicCalleeAnalysis.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ class CalleeCache {
147147

148148
/// Return the list of callees that can potentially be called at the
149149
/// given instruction. E.g. it could be destructors.
150-
CalleeList getCalleeList(SILInstruction *I) const;
150+
CalleeList getDestructors(SILType type, bool isExactType) const;
151151

152152
CalleeList getCalleeList(SILDeclRef Decl) const;
153153

@@ -224,9 +224,9 @@ class BasicCalleeAnalysis : public SILAnalysis {
224224
return Cache->getCalleeListOfValue(callee);
225225
}
226226

227-
CalleeList getCalleeList(SILInstruction *I) {
227+
CalleeList getDestructors(SILType type, bool isExactType) {
228228
updateCache();
229-
return Cache->getCalleeList(I);
229+
return Cache->getDestructors(type, isExactType);
230230
}
231231
};
232232

include/swift/SILOptimizer/OptimizerBridging.h

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,9 @@ BridgedCalleeAnalysis PassContext_getCalleeAnalysis(BridgedPassContext context);
9696

9797
BridgedCalleeList CalleeAnalysis_getCallees(BridgedCalleeAnalysis calleeAnalysis,
9898
BridgedValue callee);
99-
BridgedCalleeList CalleeAnalysis_getInstCallees(BridgedCalleeAnalysis calleeAnalysis,
100-
BridgedInstruction inst);
99+
BridgedCalleeList CalleeAnalysis_getDestructors(BridgedCalleeAnalysis calleeAnalysis,
100+
BridgedType type,
101+
SwiftInt isExactType);
101102
SwiftInt BridgedFunctionArray_size(BridgedCalleeList callees);
102103
BridgedFunction BridgedFunctionArray_get(BridgedCalleeList callees,
103104
SwiftInt index);
@@ -140,9 +141,6 @@ BridgedFunction BasicBlockSet_getFunction(BridgedBasicBlockSet set);
140141

141142
void AllocRefInstBase_setIsStackAllocatable(BridgedInstruction arb);
142143

143-
OptionalBridgedFunction PassContext_getDestructor(BridgedPassContext context,
144-
BridgedType type);
145-
146144
BridgedSubstitutionMap
147145
PassContext_getContextSubstitutionMap(BridgedPassContext context,
148146
BridgedType bridgedType);

lib/SILOptimizer/Analysis/BasicCalleeAnalysis.cpp

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -287,19 +287,28 @@ CalleeList CalleeCache::getCalleeList(FullApplySite FAS) const {
287287
return getCalleeListForCalleeKind(FAS.getCalleeOrigin());
288288
}
289289

290-
// Return the list of functions that can be called via the given instruction.
291-
CalleeList CalleeCache::getCalleeList(SILInstruction *I) const {
292-
// We support only deallocation instructions at the moment.
293-
assert((isa<StrongReleaseInst>(I) || isa<ReleaseValueInst>(I)) &&
294-
"A deallocation instruction expected");
295-
auto Ty = I->getOperand(0)->getType();
296-
while (auto payloadTy = Ty.getOptionalObjectType())
297-
Ty = payloadTy;
298-
auto Class = Ty.getClassOrBoundGenericClass();
299-
if (!Class || Class->hasClangNode())
290+
/// Return the list of destructors of the class type \p type.
291+
///
292+
/// If \p type is an optional, look through that optional.
293+
/// If \p exactType is true, then \p type is treated like a final class type.
294+
CalleeList CalleeCache::getDestructors(SILType type, bool isExactType) const {
295+
while (auto payloadTy = type.getOptionalObjectType()) {
296+
type = payloadTy;
297+
}
298+
ClassDecl *classDecl = type.getClassOrBoundGenericClass();
299+
if (!classDecl || classDecl->hasClangNode())
300+
return CalleeList();
301+
302+
if (isExactType || classDecl->isFinal()) {
303+
// In case of a final class, just pick the deinit of the class.
304+
SILDeclRef destructor = SILDeclRef(classDecl->getDestructor());
305+
if (SILFunction *destrImpl = M.lookUpFunction(destructor))
306+
return CalleeList(destrImpl);
300307
return CalleeList();
301-
SILDeclRef Destructor = SILDeclRef(Class->getDestructor());
302-
return getCalleeList(Destructor);
308+
}
309+
// If all that doesn't help get the list of deinits as we do for regular class
310+
// methods.
311+
return getCalleeList(SILDeclRef(classDecl->getDestructor()));
303312
}
304313

305314
void BasicCalleeAnalysis::dump() const {
@@ -332,10 +341,11 @@ BridgedCalleeList CalleeAnalysis_getCallees(BridgedCalleeAnalysis calleeAnalysis
332341
return {cl.getOpaquePtr(), cl.getOpaqueKind(), cl.isIncomplete()};
333342
}
334343

335-
BridgedCalleeList CalleeAnalysis_getInstCallees(BridgedCalleeAnalysis calleeAnalysis,
336-
BridgedInstruction inst) {
344+
BridgedCalleeList CalleeAnalysis_getDestructors(BridgedCalleeAnalysis calleeAnalysis,
345+
BridgedType type,
346+
SwiftInt isExactType) {
337347
BasicCalleeAnalysis *bca = static_cast<BasicCalleeAnalysis *>(calleeAnalysis.bca);
338-
CalleeList cl = bca->getCalleeList(castToInst(inst));
348+
CalleeList cl = bca->getDestructors(castToSILType(type), isExactType != 0);
339349
return {cl.getOpaquePtr(), cl.getOpaqueKind(), cl.isIncomplete()};
340350
}
341351

lib/SILOptimizer/Analysis/FunctionOrder.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,13 @@ void BottomUpFunctionOrder::DFS(SILFunction *Start) {
4040
for (auto &B : *Start) {
4141
for (auto &I : B) {
4242
auto FAS = FullApplySite::isa(&I);
43-
if (!FAS && !isa<StrongReleaseInst>(&I) && !isa<ReleaseValueInst>(&I))
43+
if (!FAS && !isa<StrongReleaseInst>(&I) && !isa<ReleaseValueInst>(&I) &&
44+
!isa<DestroyValueInst>(&I))
4445
continue;
4546

46-
auto Callees = FAS ? BCA->getCalleeList(FAS) : BCA->getCalleeList(&I);
47+
auto Callees = FAS ? BCA->getCalleeList(FAS)
48+
: BCA->getDestructors(I.getOperand(0)->getType(),
49+
/*isExactType*/ false);
4750
for (auto *CalleeFn : Callees) {
4851
// If not yet visited, visit the callee.
4952
if (DFSNum.find(CalleeFn) == DFSNum.end()) {

lib/SILOptimizer/PassManager/PassManager.cpp

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1391,19 +1391,6 @@ void AllocRefInstBase_setIsStackAllocatable(BridgedInstruction arb) {
13911391
castToInst<AllocRefInstBase>(arb)->setStackAllocatable();
13921392
}
13931393

1394-
OptionalBridgedFunction PassContext_getDestructor(BridgedPassContext context,
1395-
BridgedType type) {
1396-
auto *cd = castToSILType(type).getClassOrBoundGenericClass();
1397-
assert(cd && "no class type allocated with alloc_ref");
1398-
1399-
auto *pm = castToPassInvocation(context)->getPassManager();
1400-
// Find the destructor of the type.
1401-
auto *destructor = cd->getDestructor();
1402-
SILDeclRef deallocRef(destructor, SILDeclRef::Kind::Deallocator);
1403-
1404-
return {pm->getModule()->lookUpFunction(deallocRef)};
1405-
}
1406-
14071394
BridgedSubstitutionMap
14081395
PassContext_getContextSubstitutionMap(BridgedPassContext context,
14091396
BridgedType bridgedType) {

test/SILOptimizer/sil_combine_cow.sil renamed to test/SILOptimizer/sil_combine_inst_passes.sil

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,26 @@ bb0:
104104
return %t : $(Builtin.Int1, Builtin.BridgeObject)
105105
}
106106

107+
sil_global private @outlined_global : $_ContiguousArrayStorage<Int>
108+
109+
// CHECK-LABEL: sil @remove_arc_of_global_value
110+
// CHECK-NOT: retain
111+
// CHECK-NOT: release
112+
// CHECK-NOT: fix_lifetime
113+
// CHECK-NOT: debug_value
114+
// CHECK: } // end sil function 'remove_arc_of_global_value'
115+
sil @remove_arc_of_global_value : $@convention(thin) () -> Int {
116+
bb0:
117+
%0 = global_value @outlined_global : $_ContiguousArrayStorage<Int>
118+
strong_retain %0 : $_ContiguousArrayStorage<Int>
119+
debug_value %0 : $_ContiguousArrayStorage<Int>, let, name "x"
120+
%2 = upcast %0 : $_ContiguousArrayStorage<Int> to $__ContiguousArrayStorageBase
121+
strong_retain %2 : $__ContiguousArrayStorageBase
122+
%13 = ref_tail_addr [immutable] %2 : $__ContiguousArrayStorageBase, $Int
123+
%16 = load %13 : $*Int
124+
fix_lifetime %0 : $_ContiguousArrayStorage<Int>
125+
strong_release %2 : $__ContiguousArrayStorageBase
126+
strong_release %0 : $_ContiguousArrayStorage<Int>
127+
return %16 : $Int
128+
}
129+

0 commit comments

Comments
 (0)