Skip to content

Commit 2e03a56

Browse files
authored
Merge pull request #6041 from swiftix/wip-single-threaded-app-flag
Add a new -assume-single-threaded option
2 parents 35574a3 + 354fd29 commit 2e03a56

File tree

8 files changed

+131
-0
lines changed

8 files changed

+131
-0
lines changed

include/swift/AST/SILOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,9 @@ class SILOptions {
119119

120120
/// When parsing SIL, assume unqualified ownership.
121121
bool AssumeUnqualifiedOwnershipWhenParsing = false;
122+
123+
/// Assume that code will be executed in a single-threaded environment.
124+
bool AssumeSingleThreaded = false;
122125
};
123126

124127
} // end namespace swift

include/swift/Option/Options.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,10 @@ def Oplayground : Flag<["-"], "Oplayground">, Group<O_Group>,
311311
Flags<[HelpHidden, FrontendOption]>,
312312
HelpText<"Compile with optimizations appropriate for a playground">;
313313

314+
def AssumeSingleThreaded : Flag<["-"], "assume-single-threaded">,
315+
Flags<[FrontendOption, HelpHidden]>,
316+
HelpText<"Assume that code will be executed in a single-threaded "
317+
"environment">;
314318

315319
// Debug info options
316320

include/swift/SILOptimizer/PassManager/Passes.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ PASS(ArrayCountPropagation, "array-count-propagation",
4040
"Propagate the count of arrays")
4141
PASS(ArrayElementPropagation, "array-element-propagation",
4242
"Propagate the value of array elements")
43+
PASS(AssumeSingleThreaded, "sil-assume-single-threaded",
44+
"Assume that code will be executed in a single-threaded environment")
4345
PASS(BasicInstructionPropertyDumper, "basic-instruction-property-dump",
4446
"Dump MemBehavior and ReleaseBehavior results from calling "
4547
"SILInstruction::{getMemoryBehavior,getReleasingBehavior}()"

lib/Frontend/CompilerInvocation.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1114,6 +1114,10 @@ static bool ParseSILArgs(SILOptions &Opts, ArgList &Args,
11141114
}
11151115
}
11161116

1117+
if (Args.getLastArg(OPT_AssumeSingleThreaded)) {
1118+
Opts.AssumeSingleThreaded = true;
1119+
}
1120+
11171121
// Parse the assert configuration identifier.
11181122
if (const Arg *A = Args.getLastArg(OPT_AssertConfig)) {
11191123
StringRef Configuration = A->getValue();

lib/SILOptimizer/PassManager/Passes.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,9 @@ void swift::runSILOptimizationPasses(SILModule &Module) {
412412
// after FSO.
413413
PM.addLateReleaseHoisting();
414414

415+
// Has only an effect if the -assume-single-thread option is specified.
416+
PM.addAssumeSingleThreaded();
417+
415418
PM.runOneIteration();
416419

417420
PM.resetAndRemoveTransformations();
@@ -452,6 +455,9 @@ void swift::runSILPassesForOnone(SILModule &Module) {
452455
// eventually remove unused declarations.
453456
PM.addExternalDefsToDecls();
454457

458+
// Has only an effect if the -assume-single-thread option is specified.
459+
PM.addAssumeSingleThreaded();
460+
455461
// Has only an effect if the -gsil option is specified.
456462
PM.addSILDebugInfoGenerator();
457463

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
//===--- AssumeSingleThreaded.cpp - Assume single-threaded execution ---===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2016 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-thread.
14+
//
15+
// Convert all reference counting operations into non-atomic ones.
16+
//
17+
// To get read 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+
#include "swift/SILOptimizer/PassManager/Passes.h"
29+
#include "swift/SIL/SILFunction.h"
30+
#include "swift/SIL/SILInstruction.h"
31+
#include "swift/SIL/SILModule.h"
32+
#include "swift/SILOptimizer/Utils/Local.h"
33+
#include "swift/SILOptimizer/PassManager/Transforms.h"
34+
#include "llvm/Support/CommandLine.h"
35+
36+
using namespace swift;
37+
38+
namespace {
39+
class AssumeSingleThreaded : public swift::SILFunctionTransform {
40+
/// The entry point to the transformation.
41+
void run() override {
42+
if (!getOptions().AssumeSingleThreaded)
43+
return;
44+
for (auto &BB : *getFunction()) {
45+
for (auto &I : BB) {
46+
if (auto RCInst = dyn_cast<RefCountingInst>(&I))
47+
RCInst->setNonAtomic();
48+
}
49+
}
50+
invalidateAnalysis(SILAnalysis::InvalidationKind::Instructions);
51+
}
52+
53+
StringRef getName() override { return "Assume single threaded"; }
54+
};
55+
} // end anonymous namespace
56+
57+
58+
SILTransform *swift::createAssumeSingleThreaded() {
59+
return new AssumeSingleThreaded();
60+
}

lib/SILOptimizer/Transforms/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ set(TRANSFORMS_SOURCES
33
Transforms/AllocBoxToStack.cpp
44
Transforms/ArrayCountPropagation.cpp
55
Transforms/ArrayElementValuePropagation.cpp
6+
Transforms/AssumeSingleThreaded.cpp
67
Transforms/CSE.cpp
78
Transforms/ConditionForwarding.cpp
89
Transforms/CopyForwarding.cpp
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// RUN: %target-swift-frontend -emit-sil -assume-parsing-unqualified-ownership-sil %s -assume-single-threaded | %FileCheck %s
2+
// RUN: %target-swift-frontend -emit-sil -assume-parsing-unqualified-ownership-sil %s -O -assume-single-threaded | %FileCheck %s
3+
4+
// Check that all reference counting instructions are converted to [nonatomic]
5+
// if -assume-single-threaded is used.
6+
7+
sil_stage canonical
8+
9+
import Builtin
10+
import Swift
11+
import SwiftShims
12+
13+
public class C {
14+
deinit
15+
init()
16+
}
17+
18+
19+
// CHECK-LABEL: sil{{.*}}@test_atomic_to_nonatomic_retain
20+
// CHECK: strong_retain [nonatomic]
21+
// CHECK: return
22+
sil @test_atomic_to_nonatomic_retain: $@convention(thin) () -> @owned C {
23+
bb0:
24+
%1 = alloc_ref $C
25+
strong_retain %1 : $C
26+
return %1 : $C
27+
}
28+
29+
// CHECK-LABEL: sil{{.*}}@test_atomic_to_nonatomic_release
30+
// CHECK: strong_release [nonatomic]
31+
// CHECK: return
32+
sil @test_atomic_to_nonatomic_release: $@convention(thin) (C) -> C {
33+
bb0(%0 : $C):
34+
strong_release %0 : $C
35+
return %0 : $C
36+
}
37+
38+
39+
40+
// C.__deallocating_deinit
41+
sil @_TFC28nonatomic_reference_counting1CD : $@convention(method) (@owned C) -> () {
42+
bb0(%0 : $C):
43+
dealloc_ref %0 : $C
44+
%4 = tuple ()
45+
return %4 : $()
46+
}
47+
48+
sil_vtable C {
49+
#C.deinit!deallocator: _TFC28nonatomic_reference_counting1CD // C.__deallocating_deinit
50+
}
51+

0 commit comments

Comments
 (0)