Skip to content

Commit 6752925

Browse files
authored
Merge pull request #38973 from eeckstein/simplify-retain-release
SIL optimizer: remove unbalanced retains/releases from immortal objects
2 parents 01a7a0e + 8be0ca0 commit 6752925

22 files changed

+456
-183
lines changed

include/swift/SIL/SILBridging.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,8 @@ OptionalBridgedInstruction SILInstruction_next(BridgedInstruction inst);
191191
OptionalBridgedInstruction SILInstruction_previous(BridgedInstruction inst);
192192
BridgedBasicBlock SILInstruction_getParent(BridgedInstruction inst);
193193
BridgedArrayRef SILInstruction_getOperands(BridgedInstruction inst);
194+
void SILInstruction_setOperand(BridgedInstruction inst, SwiftInt index,
195+
BridgedValue value);
194196
BridgedLocation SILInstruction_getLocation(BridgedInstruction inst);
195197
BridgedMemoryBehavior SILInstruction_getMemBehavior(BridgedInstruction inst);
196198

include/swift/SIL/SILNodes.def

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -497,11 +497,11 @@ ABSTRACT_VALUE_AND_INST(SingleValueInstruction, ValueBase, SILInstruction)
497497
ABSTRACT_SINGLE_VALUE_INST(ConversionInst, SingleValueInstruction)
498498
BRIDGED_SINGLE_VALUE_INST(UpcastInst, upcast,
499499
ConversionInst, None, DoesNotRelease)
500-
SINGLE_VALUE_INST(AddressToPointerInst, address_to_pointer,
500+
BRIDGED_SINGLE_VALUE_INST(AddressToPointerInst, address_to_pointer,
501501
ConversionInst, None, DoesNotRelease)
502502
SINGLE_VALUE_INST(PointerToAddressInst, pointer_to_address,
503503
ConversionInst, None, DoesNotRelease)
504-
SINGLE_VALUE_INST(UncheckedRefCastInst, unchecked_ref_cast,
504+
BRIDGED_SINGLE_VALUE_INST(UncheckedRefCastInst, unchecked_ref_cast,
505505
ConversionInst, None, DoesNotRelease)
506506
SINGLE_VALUE_INST(UncheckedAddrCastInst, unchecked_addr_cast,
507507
ConversionInst, None, DoesNotRelease)
@@ -513,15 +513,15 @@ ABSTRACT_VALUE_AND_INST(SingleValueInstruction, ValueBase, SILInstruction)
513513
ConversionInst, None, DoesNotRelease)
514514
SINGLE_VALUE_INST(RefToRawPointerInst, ref_to_raw_pointer,
515515
ConversionInst, None, DoesNotRelease)
516-
SINGLE_VALUE_INST(RawPointerToRefInst, raw_pointer_to_ref,
516+
BRIDGED_SINGLE_VALUE_INST(RawPointerToRefInst, raw_pointer_to_ref,
517517
ConversionInst, None, DoesNotRelease)
518518
#define LOADABLE_REF_STORAGE(Name, name, ...) \
519519
SINGLE_VALUE_INST(RefTo##Name##Inst, ref_to_##name, \
520520
ConversionInst, None, DoesNotRelease) \
521521
SINGLE_VALUE_INST(Name##ToRefInst, name##_to_ref, \
522522
ConversionInst, None, DoesNotRelease)
523523
#include "swift/AST/ReferenceStorage.def"
524-
SINGLE_VALUE_INST(ConvertFunctionInst, convert_function,
524+
BRIDGED_SINGLE_VALUE_INST(ConvertFunctionInst, convert_function,
525525
ConversionInst, None, DoesNotRelease)
526526
SINGLE_VALUE_INST(ConvertEscapeToNoEscapeInst, convert_escape_to_noescape,
527527
ConversionInst, None, DoesNotRelease)
@@ -535,15 +535,15 @@ ABSTRACT_VALUE_AND_INST(SingleValueInstruction, ValueBase, SILInstruction)
535535
ConversionInst, None, DoesNotRelease)
536536
SINGLE_VALUE_INST(BridgeObjectToWordInst, bridge_object_to_word,
537537
ConversionInst, None, DoesNotRelease)
538-
SINGLE_VALUE_INST(ThinToThickFunctionInst, thin_to_thick_function,
538+
BRIDGED_SINGLE_VALUE_INST(ThinToThickFunctionInst, thin_to_thick_function,
539539
ConversionInst, None, DoesNotRelease)
540540
SINGLE_VALUE_INST(ThickToObjCMetatypeInst, thick_to_objc_metatype,
541541
ConversionInst, None, DoesNotRelease)
542542
SINGLE_VALUE_INST(ObjCToThickMetatypeInst, objc_to_thick_metatype,
543543
ConversionInst, None, DoesNotRelease)
544-
SINGLE_VALUE_INST(ObjCMetatypeToObjectInst, objc_metatype_to_object,
544+
BRIDGED_SINGLE_VALUE_INST(ObjCMetatypeToObjectInst, objc_metatype_to_object,
545545
ConversionInst, None, DoesNotRelease)
546-
SINGLE_VALUE_INST(ObjCExistentialMetatypeToObjectInst, objc_existential_metatype_to_object,
546+
BRIDGED_SINGLE_VALUE_INST(ObjCExistentialMetatypeToObjectInst, objc_existential_metatype_to_object,
547547
ConversionInst, None, DoesNotRelease)
548548
// unconditional_checked_cast_value reads the source value and produces
549549
// a new value with a potentially different representation.
@@ -566,7 +566,7 @@ ABSTRACT_VALUE_AND_INST(SingleValueInstruction, ValueBase, SILInstruction)
566566

567567
BRIDGED_SINGLE_VALUE_INST(ClassifyBridgeObjectInst, classify_bridge_object,
568568
SingleValueInstruction, None, DoesNotRelease)
569-
SINGLE_VALUE_INST(ValueToBridgeObjectInst, value_to_bridge_object,
569+
BRIDGED_SINGLE_VALUE_INST(ValueToBridgeObjectInst, value_to_bridge_object,
570570
SingleValueInstruction, None, DoesNotRelease)
571571
SINGLE_VALUE_INST(MarkDependenceInst, mark_dependence,
572572
SingleValueInstruction, None, DoesNotRelease)

include/swift/SILOptimizer/OptimizerBridging.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,9 @@ void SILPassManager_registerFunctionPass(BridgedStringRef name,
5252
void SILCombine_registerInstructionPass(BridgedStringRef name,
5353
BridgedInstructionPassRunFn runFn);
5454

55-
BridgedAliasAnalysis PassContext_getAliasAnalysis(BridgedPassContext context,
56-
BridgedFunction function);
55+
SwiftInt PassContext_isSwift51RuntimeAvailable(BridgedPassContext context);
56+
57+
BridgedAliasAnalysis PassContext_getAliasAnalysis(BridgedPassContext context);
5758

5859
BridgedMemoryBehavior AliasAnalysis_getMemBehavior(BridgedAliasAnalysis aa,
5960
BridgedInstruction inst,

include/swift/SILOptimizer/PassManager/PassManager.h

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,19 +48,28 @@ void executePassPipelinePlan(SILModule *SM, const SILPassPipelinePlan &plan,
4848
class LibswiftPassInvocation {
4949
/// Backlink to the pass manager.
5050
SILPassManager *passManager;
51-
51+
52+
/// The currently optimized function.
53+
SILFunction *function = nullptr;
54+
5255
/// Non-null if this is an instruction pass, invoked from SILCombine.
53-
SILCombiner *silCombiner;
56+
SILCombiner *silCombiner = nullptr;
5457

5558
/// All slabs, allocated by the pass.
5659
SILModule::SlabList allocatedSlabs;
5760

5861
public:
59-
LibswiftPassInvocation(SILPassManager *passManager, SILCombiner *silCombiner) :
60-
passManager(passManager), silCombiner(silCombiner) {}
62+
LibswiftPassInvocation(SILPassManager *passManager, SILFunction *function,
63+
SILCombiner *silCombiner) :
64+
passManager(passManager), function(function), silCombiner(silCombiner) {}
65+
66+
LibswiftPassInvocation(SILPassManager *passManager) :
67+
passManager(passManager) {}
6168

6269
SILPassManager *getPassManager() const { return passManager; }
6370

71+
SILFunction *getFunction() const { return function; }
72+
6473
FixedSizeSlab *allocSlab(FixedSizeSlab *afterSlab);
6574

6675
FixedSizeSlab *freeSlab(FixedSizeSlab *slab);
@@ -71,6 +80,9 @@ class LibswiftPassInvocation {
7180
/// Called by the pass when changes are made to the SIL.
7281
void notifyChanges(SILAnalysis::InvalidationKind invalidationKind);
7382

83+
/// Called by the pass manager before the pass starts running.
84+
void startPassRun(SILFunction *function);
85+
7486
/// Called by the pass manager when the pass has finished.
7587
void finishedPassRun();
7688
};

include/swift/SILOptimizer/PassManager/Passes.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,8 @@ PASS(PruneVTables, "prune-vtables",
422422
PASS_RANGE(AllPasses, AADumper, PruneVTables)
423423

424424
SWIFT_INSTRUCTION_PASS_WITH_LEGACY(GlobalValueInst, "simplify-global_value")
425+
SWIFT_INSTRUCTION_PASS_WITH_LEGACY(StrongRetainInst, "simplify-strong_retain")
426+
SWIFT_INSTRUCTION_PASS_WITH_LEGACY(StrongReleaseInst, "simplify-strong_release")
425427

426428
#undef IRGEN_PASS
427429
#undef SWIFT_FUNCTION_PASS

lib/SIL/Utils/SILBridging.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,11 @@ BridgedArrayRef SILInstruction_getOperands(BridgedInstruction inst) {
357357
return {(const unsigned char *)operands.data(), operands.size()};
358358
}
359359

360+
void SILInstruction_setOperand(BridgedInstruction inst, SwiftInt index,
361+
BridgedValue value) {
362+
castToInst(inst)->setOperand((unsigned)index, castToSILValue(value));
363+
}
364+
360365
BridgedLocation SILInstruction_getLocation(BridgedInstruction inst) {
361366
SILDebugLocation loc = castToInst(inst)->getDebugLocation();
362367
return *reinterpret_cast<BridgedLocation *>(&loc);

lib/SILOptimizer/PassManager/PassManager.cpp

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ void swift::executePassPipelinePlan(SILModule *SM,
322322
SILPassManager::SILPassManager(SILModule *M, bool isMandatory,
323323
irgen::IRGenModule *IRMod)
324324
: Mod(M), IRMod(IRMod),
325-
libswiftPassInvocation(this, /*SILCombiner*/ nullptr),
325+
libswiftPassInvocation(this),
326326
isMandatory(isMandatory), deserializationNotificationHandler(nullptr) {
327327
#define ANALYSIS(NAME) \
328328
Analyses.push_back(create##NAME##Analysis(Mod));
@@ -469,7 +469,9 @@ void SILPassManager::runPassOnFunction(unsigned TransIdx, SILFunction *F) {
469469

470470
assert(changeNotifications == SILAnalysis::InvalidationKind::Nothing
471471
&& "change notifications not cleared");
472-
472+
473+
libswiftPassInvocation.startPassRun(F);
474+
473475
// Run it!
474476
SFT->run();
475477

@@ -1100,8 +1102,14 @@ FixedSizeSlab *LibswiftPassInvocation::freeSlab(FixedSizeSlab *slab) {
11001102
return prev;
11011103
}
11021104

1105+
void LibswiftPassInvocation::startPassRun(SILFunction *function) {
1106+
assert(!this->function && "a pass is already running");
1107+
this->function = function;
1108+
}
1109+
11031110
void LibswiftPassInvocation::finishedPassRun() {
11041111
assert(allocatedSlabs.empty() && "StackList is leaking slabs");
1112+
function = nullptr;
11051113
}
11061114

11071115
//===----------------------------------------------------------------------===//
@@ -1166,10 +1174,17 @@ void PassContext_eraseInstruction(BridgedPassContext passContext,
11661174
castToPassInvocation(passContext)->eraseInstruction(castToInst(inst));
11671175
}
11681176

1169-
BridgedAliasAnalysis PassContext_getAliasAnalysis(BridgedPassContext context,
1170-
BridgedFunction function) {
1177+
SwiftInt PassContext_isSwift51RuntimeAvailable(BridgedPassContext context) {
11711178
SILPassManager *pm = castToPassInvocation(context)->getPassManager();
1172-
return {pm->getAnalysis<AliasAnalysis>(castToFunction(function))};
1179+
ASTContext &ctxt = pm->getModule()->getASTContext();
1180+
return AvailabilityContext::forDeploymentTarget(ctxt).
1181+
isContainedIn(ctxt.getSwift51Availability());
1182+
}
1183+
1184+
BridgedAliasAnalysis PassContext_getAliasAnalysis(BridgedPassContext context) {
1185+
LibswiftPassInvocation *invocation = castToPassInvocation(context);
1186+
SILPassManager *pm = invocation->getPassManager();
1187+
return {pm->getAnalysis<AliasAnalysis>(invocation->getFunction())};
11731188
}
11741189

11751190
BridgedCalleeAnalysis PassContext_getCalleeAnalysis(BridgedPassContext context) {

lib/SILOptimizer/SILCombiner/SILCombiner.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,8 @@ class SILCombiner :
158158
[&](SILInstruction *I) { eraseInstFromFunction(*I); }),
159159
deBlocks(&B.getFunction()),
160160
ownershipFixupContext(getInstModCallbacks(), deBlocks),
161-
libswiftPassInvocation(parentTransform->getPassManager(), this) {}
161+
libswiftPassInvocation(parentTransform->getPassManager(),
162+
parentTransform->getFunction(), this) {}
162163

163164
bool runOnFunction(SILFunction &F);
164165

@@ -278,7 +279,7 @@ class SILCombiner :
278279
SILInstruction *optimizeStringObject(BuiltinInst *BI);
279280
SILInstruction *visitBuiltinInst(BuiltinInst *BI);
280281
SILInstruction *visitCondFailInst(CondFailInst *CFI);
281-
SILInstruction *visitStrongRetainInst(StrongRetainInst *SRI);
282+
SILInstruction *legacyVisitStrongRetainInst(StrongRetainInst *SRI);
282283
SILInstruction *visitCopyValueInst(CopyValueInst *cvi);
283284
SILInstruction *visitDestroyValueInst(DestroyValueInst *dvi);
284285
SILInstruction *visitRefToRawPointerInst(RefToRawPointerInst *RRPI);
@@ -308,7 +309,7 @@ class SILCombiner :
308309
SILInstruction *visitRawPointerToRefInst(RawPointerToRefInst *RPTR);
309310
SILInstruction *
310311
visitUncheckedTakeEnumDataAddrInst(UncheckedTakeEnumDataAddrInst *TEDAI);
311-
SILInstruction *visitStrongReleaseInst(StrongReleaseInst *SRI);
312+
SILInstruction *legacyVisitStrongReleaseInst(StrongReleaseInst *SRI);
312313
SILInstruction *visitCondBranchInst(CondBranchInst *CBI);
313314
SILInstruction *
314315
visitUncheckedTrivialBitCastInst(UncheckedTrivialBitCastInst *UTBCI);

lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1213,7 +1213,7 @@ SILInstruction *SILCombiner::visitDestroyValueInst(DestroyValueInst *dvi) {
12131213
return nullptr;
12141214
}
12151215

1216-
SILInstruction *SILCombiner::visitStrongRetainInst(StrongRetainInst *SRI) {
1216+
SILInstruction *SILCombiner::legacyVisitStrongRetainInst(StrongRetainInst *SRI) {
12171217
assert(!SRI->getFunction()->hasOwnership());
12181218

12191219
// Retain of ThinToThickFunction is a no-op.
@@ -1821,7 +1821,7 @@ SILInstruction *SILCombiner::visitUncheckedTakeEnumDataAddrInst(
18211821
return eraseInstFromFunction(*tedai);
18221822
}
18231823

1824-
SILInstruction *SILCombiner::visitStrongReleaseInst(StrongReleaseInst *SRI) {
1824+
SILInstruction *SILCombiner::legacyVisitStrongReleaseInst(StrongReleaseInst *SRI) {
18251825
assert(!SRI->getFunction()->hasOwnership());
18261826

18271827
// Release of ThinToThickFunction is a no-op.

libswift/Sources/Optimizer/FunctionPasses/MergeCondFails.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ let mergeCondFailsPass = FunctionPass(name: "merge-cond_fails", runMergeCondFail
1717
/// Return true if the operand of the cond_fail instruction looks like
1818
/// the overflow bit of an arithmetic instruction.
1919
private func hasOverflowConditionOperand(_ cfi: CondFailInst) -> Bool {
20-
if let tei = cfi.condition as? TupleExtractInst {
21-
return tei.tuple is BuiltinInst
20+
if let tei = cfi.operand as? TupleExtractInst {
21+
return tei.operand is BuiltinInst
2222
}
2323
return false
2424
}
@@ -29,7 +29,7 @@ private func hasOverflowConditionOperand(_ cfi: CondFailInst) -> Bool {
2929
/// write in between them.
3030
/// This pass merges cond_fail instructions by building the disjunction of
3131
/// their operands.
32-
private func runMergeCondFails(function: Function, context: FunctionPassContext) {
32+
private func runMergeCondFails(function: Function, context: PassContext) {
3333

3434
// Merge cond_fail instructions if there is no side-effect or read in
3535
// between them.
@@ -59,7 +59,7 @@ private func runMergeCondFails(function: Function, context: FunctionPassContext)
5959
/// Try to merge the cond_fail instructions. Returns true if any could
6060
/// be merge.
6161
private func mergeCondFails(_ condFailToMerge: inout StackList<CondFailInst>,
62-
context: FunctionPassContext) {
62+
context: PassContext) {
6363
guard let lastCFI = condFailToMerge.last else {
6464
return
6565
}
@@ -73,10 +73,10 @@ private func mergeCondFails(_ condFailToMerge: inout StackList<CondFailInst>,
7373
mergedCond = builder.createBuiltinBinaryFunction(name: "or",
7474
operandType: prevCond.type,
7575
resultType: prevCond.type,
76-
arguments: [prevCond, cfi.condition])
76+
arguments: [prevCond, cfi.operand])
7777
didMerge = true
7878
} else {
79-
mergedCond = cfi.condition
79+
mergedCond = cfi.operand
8080
}
8181
}
8282
if !didMerge {

libswift/Sources/Optimizer/FunctionPasses/SILPrinter.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import SIL
1414

1515
let silPrinterPass = FunctionPass(name: "sil-printer", runSILPrinter)
1616

17-
func runSILPrinter(function: Function, context: FunctionPassContext) {
17+
func runSILPrinter(function: Function, context: PassContext) {
1818
print("run SILPrinter on function: \(function.name)")
1919

2020
for (bbIdx, block) in function.blocks.enumerated() {

libswift/Sources/Optimizer/InstructionPasses/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@
77
# See http://swift.org/CONTRIBUTORS.txt for Swift project authors
88

99
libswift_sources(Optimizer
10-
SimplifyGlobalValue.swift)
10+
SimplifyGlobalValue.swift
11+
SimplifyStrongRetainRelease.swift)

libswift/Sources/Optimizer/InstructionPasses/SimplifyGlobalValue.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,15 @@
1212

1313
import SIL
1414

15+
// Removes all reference counting instructions of a `global_value` instruction
16+
// if it does not escape.
17+
//
18+
// Note that `simplifyStrongRetainPass` and `simplifyStrongReleasePass` can
19+
// even remove "unbalanced" retains/releases of a `global_value`, but this
20+
// requires a minimum deployment target.
1521
let simplifyGlobalValuePass = InstructionPass<GlobalValueInst>(
1622
name: "simplify-global_value", {
17-
(globalValue: GlobalValueInst, context: InstructionPassContext) in
23+
(globalValue: GlobalValueInst, context: PassContext) in
1824

1925
var users = StackList<Instruction>(context)
2026
if checkUsers(of: globalValue, users: &users) {

0 commit comments

Comments
 (0)