Skip to content

Commit c01fd7e

Browse files
authored
Merge pull request swiftlang#40781 from apple/maxd/assume-single-threaded
libswift: reimplement `AssumeSingleThreaded` pass I don't think that `AssumeSingleThreaded` is widely used, certainly doesn't look like a mandatory pass, and it seemed trivial enough for a first try of rewriting passes in Swift.
2 parents c5efe9a + 5ef19cf commit c01fd7e

File tree

10 files changed

+64
-9
lines changed

10 files changed

+64
-9
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//===--- AssumeSingleThreaded.swift - Assume single-threaded execution ----===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// Assume that user code is single-threaded.
14+
//
15+
// Convert all reference counting operations into non-atomic ones.
16+
//
17+
// To get rid of most atomic reference counting operations, the standard
18+
// library should be compiled in this mode as well .
19+
//
20+
// This pass affects only reference counting operations resulting from SIL
21+
// instructions. It wouldn't affect places in the runtime C++ code which
22+
// hard-code calls to retain/release. We could take advantage of the Instruments
23+
// instrumentation stubs to redirect calls from the runtime if it was
24+
// significant, or else just build a single-threaded variant of the runtime.
25+
//
26+
//===----------------------------------------------------------------------===//
27+
28+
import SIL
29+
30+
let assumeSingleThreadedPass = FunctionPass(
31+
name: "sil-assume-single-threaded", { function, context in
32+
for block in function.blocks {
33+
for inst in block.instructions {
34+
guard let rcInst = inst as? RefCountingInst else { continue }
35+
36+
context.setAtomicity(of: rcInst, isAtomic: false)
37+
}
38+
}
39+
}
40+
)

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
# See http://swift.org/CONTRIBUTORS.txt for Swift project authors
88

99
swift_compiler_sources(Optimizer
10+
AssumeSingleThreaded.swift
1011
SILPrinter.swift
1112
MergeCondFails.swift
1213
)

SwiftCompilerSources/Sources/Optimizer/PassManager/PassRegistration.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,5 @@ private func registerSwiftPasses() {
5050
registerPass(simplifyGlobalValuePass, { simplifyGlobalValuePass.run($0) })
5151
registerPass(simplifyStrongRetainPass, { simplifyStrongRetainPass.run($0) })
5252
registerPass(simplifyStrongReleasePass, { simplifyStrongReleasePass.run($0) })
53+
registerPass(assumeSingleThreadedPass, { assumeSingleThreadedPass.run($0) })
5354
}

SwiftCompilerSources/Sources/Optimizer/PassManager/PassUtils.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,12 @@ struct PassContext {
7878

7979
SILInstruction_setOperand(instruction.bridged, index, value.bridged)
8080
}
81+
82+
func setAtomicity(of instruction: RefCountingInst, isAtomic: Bool) {
83+
PassContext_notifyChanges(passContext, instructionsChanged)
84+
85+
RefCountingInst_setIsAtomic(instruction.bridged, isAtomic)
86+
}
8187
}
8288

8389
struct FunctionPass {

include/swift/SIL/SILBridging.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ BridgedBasicBlock BranchInst_getTargetBlock(BridgedInstruction bi);
233233
SwiftInt SwitchEnumInst_getNumCases(BridgedInstruction se);
234234
SwiftInt SwitchEnumInst_getCaseIndex(BridgedInstruction se, SwiftInt idx);
235235
SwiftInt StoreInst_getStoreOwnership(BridgedInstruction store);
236+
void RefCountingInst_setIsAtomic(BridgedInstruction rc, bool isAtomic);
236237

237238
BridgedInstruction SILBuilder_createBuiltinBinaryFunction(
238239
BridgedInstruction insertionPoint,

include/swift/SILOptimizer/PassManager/Passes.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ PASS(ArrayCountPropagation, "array-count-propagation",
131131
"Array Count Propagation")
132132
PASS(ArrayElementPropagation, "array-element-propagation",
133133
"Array Element Propagation")
134-
PASS(AssumeSingleThreaded, "sil-assume-single-threaded",
134+
SWIFT_FUNCTION_PASS_WITH_LEGACY(AssumeSingleThreaded, "sil-assume-single-threaded",
135135
"Assume Single-Threaded Environment")
136136
PASS(BasicInstructionPropertyDumper, "basic-instruction-property-dump",
137137
"Print SIL Instruction MemBehavior and ReleaseBehavior Information")

lib/SIL/Utils/SILBridging.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,11 @@ SwiftInt StoreInst_getStoreOwnership(BridgedInstruction store) {
483483
return (SwiftInt)castToInst<StoreInst>(store)->getOwnershipQualifier();
484484
}
485485

486+
void RefCountingInst_setIsAtomic(BridgedInstruction rc, bool isAtomic) {
487+
castToInst<RefCountingInst>(rc)->setAtomicity(
488+
isAtomic ? RefCountingInst::Atomicity::Atomic
489+
: RefCountingInst::Atomicity::NonAtomic);
490+
}
486491

487492
//===----------------------------------------------------------------------===//
488493
// SILBuilder

lib/SILOptimizer/PassManager/PassPipeline.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -766,7 +766,9 @@ static void addLastChanceOptPassPipeline(SILPassPipelinePlan &P) {
766766
#endif
767767

768768
// Only has an effect if the -assume-single-thread option is specified.
769-
P.addAssumeSingleThreaded();
769+
if (P.getOptions().AssumeSingleThreaded) {
770+
P.addAssumeSingleThreaded();
771+
}
770772

771773
// Emits remarks on all functions with @_assemblyVision attribute.
772774
P.addAssemblyVisionRemarkGenerator();
@@ -925,7 +927,9 @@ SILPassPipelinePlan::getOnonePassPipeline(const SILOptions &Options) {
925927
P.addUsePrespecialized();
926928

927929
// Has only an effect if the -assume-single-thread option is specified.
928-
P.addAssumeSingleThreaded();
930+
if (P.getOptions().AssumeSingleThreaded) {
931+
P.addAssumeSingleThreaded();
932+
}
929933

930934
// Create pre-specializations.
931935
P.addOnonePrespecializations();

lib/SILOptimizer/Transforms/AssumeSingleThreaded.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
// Convert all reference counting operations into non-atomic ones.
1616
//
1717
// To get read of most atomic reference counting operations, the standard
18-
// library should be compiled in this mode as well
18+
// library should be compiled in this mode as well
1919
//
2020
// This pass affects only reference counting operations resulting from SIL
2121
// instructions. It wouldn't affect places in the runtime C++ code which
@@ -49,11 +49,9 @@ class AssumeSingleThreaded : public swift::SILFunctionTransform {
4949
}
5050
invalidateAnalysis(SILAnalysis::InvalidationKind::Instructions);
5151
}
52-
5352
};
5453
} // end anonymous namespace
5554

56-
57-
SILTransform *swift::createAssumeSingleThreaded() {
55+
SILTransform *swift::createLegacyAssumeSingleThreaded() {
5856
return new AssumeSingleThreaded();
5957
}

test/sil-passpipeline-dump/basic.test-sh

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,5 @@
88
// CHECK: passes: [ "serialize-sil", "ownership-model-eliminator" ]
99
// CHECK: ---
1010
// CHECK: name: Rest of Onone
11-
// CHECK: passes: [ "use-prespecialized", "sil-assume-single-threaded",
12-
// CHECK: "sil-debuginfo-gen" ]
11+
// CHECK: passes: [ "use-prespecialized", "onone-prespecializer", "sil-debuginfo-gen" ]
1312
// CHECK: ...

0 commit comments

Comments
 (0)