Skip to content

Commit 6c41d09

Browse files
authored
Merge pull request #4101 from swiftwasm/main
2 parents d850aff + 7972139 commit 6c41d09

File tree

17 files changed

+191
-87
lines changed

17 files changed

+191
-87
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
}

lib/SILOptimizer/Utils/ShrinkBorrowScope.cpp

Lines changed: 6 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,6 @@ class ShrinkBorrowScope {
5151
/// which is itself a deinit barrier.
5252
SmallPtrSet<SILBasicBlock *, 8> barredBlocks;
5353

54-
llvm::SmallDenseMap<ApplySite, size_t> transitiveUsesPerApplySite;
55-
5654
// The list of blocks to look for new points at which to insert end_borrows
5755
// in. A block must not be processed if all of its successors have not yet
5856
// been. For that reason, it is necessary to allow the same block to be
@@ -136,48 +134,16 @@ class ShrinkBorrowScope {
136134
}
137135
}
138136

139-
size_t usesInApply(ApplySite apply) {
140-
if (auto count = transitiveUsesPerApplySite.lookup(apply))
141-
return count;
142-
return 0;
143-
}
144-
145137
bool canHoistOverInstruction(SILInstruction *instruction) {
146138
return tryHoistOverInstruction(instruction, /*rewrite=*/false);
147139
}
148140

149141
bool tryHoistOverInstruction(SILInstruction *instruction, bool rewrite = true) {
142+
if (instruction == introducer) {
143+
return false;
144+
}
150145
if (users.contains(instruction)) {
151-
if (auto apply = ApplySite::isa(instruction)) {
152-
SmallVector<int, 2> rewritableArgumentIndices;
153-
auto count = apply.getNumArguments();
154-
for (unsigned index = 0; index < count; ++index) {
155-
auto argument = apply.getArgument(index);
156-
if (canReplaceValueWithBorrowedValue(argument)) {
157-
rewritableArgumentIndices.push_back(index);
158-
}
159-
}
160-
if (rewritableArgumentIndices.size() != usesInApply(apply)) {
161-
return false;
162-
}
163-
if (rewrite) {
164-
// We can rewrite all the arguments which are transitive uses of the
165-
// borrow.
166-
for (auto index : rewritableArgumentIndices) {
167-
auto argument = apply.getArgument(index);
168-
auto borrowee = introducer->getOperand();
169-
if (auto *cvi = dyn_cast<CopyValueInst>(argument)) {
170-
cvi->setOperand(borrowee);
171-
modifiedCopyValueInsts.push_back(cvi);
172-
madeChange = true;
173-
} else {
174-
apply.setArgument(index, borrowee);
175-
madeChange = true;
176-
}
177-
}
178-
}
179-
return true;
180-
} else if (auto *bbi = dyn_cast<BeginBorrowInst>(instruction)) {
146+
if (auto *bbi = dyn_cast<BeginBorrowInst>(instruction)) {
181147
if (bbi->isLexical() &&
182148
canReplaceValueWithBorrowedValue(bbi->getOperand())) {
183149
if (rewrite) {
@@ -234,9 +200,6 @@ bool ShrinkBorrowScope::populateUsers() {
234200
for (auto *use : uses) {
235201
auto *user = use->getUser();
236202
users.insert(user);
237-
if (auto apply = ApplySite::isa(user)) {
238-
++transitiveUsesPerApplySite[apply];
239-
}
240203
}
241204
return true;
242205
}
@@ -298,20 +261,12 @@ void ShrinkBorrowScope::findBarriers() {
298261
// At that time, it was checked that this block (along with all that
299262
// successor's other predecessors) had a terminator over which the borrow
300263
// scope could be shrunk. Shrink it now.
301-
#ifndef NDEBUG
302-
bool hoisted =
303-
#endif
304-
tryHoistOverInstruction(block->getTerminator());
305-
#ifndef NDEBUG
264+
bool hoisted = tryHoistOverInstruction(block->getTerminator());
306265
assert(hoisted);
307-
#endif
266+
(void)hoisted;
308267
}
309268
SILInstruction *barrier = nullptr;
310269
while ((instruction = instruction->getPreviousInstruction())) {
311-
if (instruction == introducer) {
312-
barrier = instruction;
313-
break;
314-
}
315270
if (!tryHoistOverInstruction(instruction)) {
316271
barrier = instruction;
317272
break;

stdlib/public/Concurrency/Actor.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,7 @@
3636
#include "swift/ABI/Task.h"
3737
#include "swift/ABI/Actor.h"
3838
#include "swift/Basic/ListMerger.h"
39-
#ifndef SWIFT_CONCURRENCY_BACK_DEPLOYMENT
40-
#include "llvm/Config/config.h"
41-
#else
39+
#ifdef SWIFT_CONCURRENCY_BACK_DEPLOYMENT
4240
// All platforms where we care about back deployment have a known
4341
// configurations.
4442
#define HAVE_PTHREAD_H 1
@@ -72,7 +70,7 @@
7270
#include <sys/syscall.h>
7371
#endif
7472

75-
#if HAVE_PTHREAD_H
73+
#if defined(_POSIX_THREADS)
7674
#include <pthread.h>
7775

7876
// Only use __has_include since HAVE_PTHREAD_NP_H is not provided.

test/SILOptimizer/copy_propagation_borrow.sil

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -394,9 +394,11 @@ bb3:
394394
// CHECK: [[ALLOC:%.*]] = alloc_ref $C
395395
// CHECK-NEXT: [[B1:%.*]] = begin_borrow [[ALLOC]]
396396
// CHECK-NOT: copy
397+
// CHECK: [[B2:%.*]] = begin_borrow [[ALLOC]]
397398
// CHECK-NOT: copy
398399
// CHECK: end_borrow [[B1]] : $C
399-
// CHECK: apply %0([[ALLOC]]) : $@convention(thin) (@guaranteed C) -> ()
400+
// CHECK: apply %0([[B2]]) : $@convention(thin) (@guaranteed C) -> ()
401+
// CHECK: end_borrow [[B2]] : $C
400402
// CHECK-NEXT: return [[ALLOC]] : $C
401403
// CHECK-LABEL: } // end sil function 'testInterleavedBorrow'
402404
sil [ossa] @testInterleavedBorrow : $@convention(thin) () -> @owned C {
@@ -426,11 +428,14 @@ bb0:
426428
// CHECK: [[B1:%.*]] = begin_borrow [[ALLOC]]
427429
// CHECK: apply %{{.*}}([[B1]]) : $@convention(thin) (@guaranteed C) -> ()
428430
// CHECK-NEXT: end_borrow [[B1]] : $C
431+
// CHECK-NEXT: [[B2:%.*]] = begin_borrow [[ALLOC]]
429432
// CHECK-NEXT: cond_br undef, bb1, bb2
430433
// CHECK: bb1:
431-
// CHECK: apply %{{.*}}([[ALLOC]]) : $@convention(thin) (@guaranteed C) -> ()
434+
// CHECK: apply %{{.*}}([[B2]]) : $@convention(thin) (@guaranteed C) -> ()
435+
// CHECK-NEXT: end_borrow [[B2]] : $C
432436
// CHECK-NEXT: br bb3
433437
// CHECK: bb2:
438+
// CHECK-NEXT: end_borrow [[B2]] : $C
434439
// CHECK-NEXT: br bb3
435440
// CHECK: bb3:
436441
// CHECK-NEXT: return [[ALLOC]] : $C

0 commit comments

Comments
 (0)