Skip to content

[pull] swiftwasm from main #4101

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
Jan 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//===--- AssumeSingleThreaded.swift - Assume single-threaded execution ----===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// Assume that user code is single-threaded.
//
// Convert all reference counting operations into non-atomic ones.
//
// To get rid of most atomic reference counting operations, the standard
// library should be compiled in this mode as well .
//
// This pass affects only reference counting operations resulting from SIL
// instructions. It wouldn't affect places in the runtime C++ code which
// hard-code calls to retain/release. We could take advantage of the Instruments
// instrumentation stubs to redirect calls from the runtime if it was
// significant, or else just build a single-threaded variant of the runtime.
//
//===----------------------------------------------------------------------===//

import SIL

let assumeSingleThreadedPass = FunctionPass(
name: "sil-assume-single-threaded", { function, context in
for block in function.blocks {
for inst in block.instructions {
guard let rcInst = inst as? RefCountingInst else { continue }

context.setAtomicity(of: rcInst, isAtomic: false)
}
}
}
)
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
# See http://swift.org/CONTRIBUTORS.txt for Swift project authors

swift_compiler_sources(Optimizer
AssumeSingleThreaded.swift
SILPrinter.swift
MergeCondFails.swift
)
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,5 @@ private func registerSwiftPasses() {
registerPass(simplifyGlobalValuePass, { simplifyGlobalValuePass.run($0) })
registerPass(simplifyStrongRetainPass, { simplifyStrongRetainPass.run($0) })
registerPass(simplifyStrongReleasePass, { simplifyStrongReleasePass.run($0) })
registerPass(assumeSingleThreadedPass, { assumeSingleThreadedPass.run($0) })
}
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,12 @@ struct PassContext {

SILInstruction_setOperand(instruction.bridged, index, value.bridged)
}

func setAtomicity(of instruction: RefCountingInst, isAtomic: Bool) {
PassContext_notifyChanges(passContext, instructionsChanged)

RefCountingInst_setIsAtomic(instruction.bridged, isAtomic)
}
}

struct FunctionPass {
Expand Down
1 change: 1 addition & 0 deletions include/swift/SIL/SILBridging.h
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ BridgedBasicBlock BranchInst_getTargetBlock(BridgedInstruction bi);
SwiftInt SwitchEnumInst_getNumCases(BridgedInstruction se);
SwiftInt SwitchEnumInst_getCaseIndex(BridgedInstruction se, SwiftInt idx);
SwiftInt StoreInst_getStoreOwnership(BridgedInstruction store);
void RefCountingInst_setIsAtomic(BridgedInstruction rc, bool isAtomic);

BridgedInstruction SILBuilder_createBuiltinBinaryFunction(
BridgedInstruction insertionPoint,
Expand Down
2 changes: 1 addition & 1 deletion include/swift/SILOptimizer/PassManager/Passes.def
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ PASS(ArrayCountPropagation, "array-count-propagation",
"Array Count Propagation")
PASS(ArrayElementPropagation, "array-element-propagation",
"Array Element Propagation")
PASS(AssumeSingleThreaded, "sil-assume-single-threaded",
SWIFT_FUNCTION_PASS_WITH_LEGACY(AssumeSingleThreaded, "sil-assume-single-threaded",
"Assume Single-Threaded Environment")
PASS(BasicInstructionPropertyDumper, "basic-instruction-property-dump",
"Print SIL Instruction MemBehavior and ReleaseBehavior Information")
Expand Down
5 changes: 5 additions & 0 deletions lib/SIL/Utils/SILBridging.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,11 @@ SwiftInt StoreInst_getStoreOwnership(BridgedInstruction store) {
return (SwiftInt)castToInst<StoreInst>(store)->getOwnershipQualifier();
}

void RefCountingInst_setIsAtomic(BridgedInstruction rc, bool isAtomic) {
castToInst<RefCountingInst>(rc)->setAtomicity(
isAtomic ? RefCountingInst::Atomicity::Atomic
: RefCountingInst::Atomicity::NonAtomic);
}

//===----------------------------------------------------------------------===//
// SILBuilder
Expand Down
8 changes: 6 additions & 2 deletions lib/SILOptimizer/PassManager/PassPipeline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -766,7 +766,9 @@ static void addLastChanceOptPassPipeline(SILPassPipelinePlan &P) {
#endif

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

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

// Has only an effect if the -assume-single-thread option is specified.
P.addAssumeSingleThreaded();
if (P.getOptions().AssumeSingleThreaded) {
P.addAssumeSingleThreaded();
}

// Create pre-specializations.
P.addOnonePrespecializations();
Expand Down
6 changes: 2 additions & 4 deletions lib/SILOptimizer/Transforms/AssumeSingleThreaded.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
// Convert all reference counting operations into non-atomic ones.
//
// To get read of most atomic reference counting operations, the standard
// library should be compiled in this mode as well
// library should be compiled in this mode as well
//
// This pass affects only reference counting operations resulting from SIL
// instructions. It wouldn't affect places in the runtime C++ code which
Expand Down Expand Up @@ -49,11 +49,9 @@ class AssumeSingleThreaded : public swift::SILFunctionTransform {
}
invalidateAnalysis(SILAnalysis::InvalidationKind::Instructions);
}

};
} // end anonymous namespace


SILTransform *swift::createAssumeSingleThreaded() {
SILTransform *swift::createLegacyAssumeSingleThreaded() {
return new AssumeSingleThreaded();
}
57 changes: 6 additions & 51 deletions lib/SILOptimizer/Utils/ShrinkBorrowScope.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,6 @@ class ShrinkBorrowScope {
/// which is itself a deinit barrier.
SmallPtrSet<SILBasicBlock *, 8> barredBlocks;

llvm::SmallDenseMap<ApplySite, size_t> transitiveUsesPerApplySite;

// The list of blocks to look for new points at which to insert end_borrows
// in. A block must not be processed if all of its successors have not yet
// been. For that reason, it is necessary to allow the same block to be
Expand Down Expand Up @@ -136,48 +134,16 @@ class ShrinkBorrowScope {
}
}

size_t usesInApply(ApplySite apply) {
if (auto count = transitiveUsesPerApplySite.lookup(apply))
return count;
return 0;
}

bool canHoistOverInstruction(SILInstruction *instruction) {
return tryHoistOverInstruction(instruction, /*rewrite=*/false);
}

bool tryHoistOverInstruction(SILInstruction *instruction, bool rewrite = true) {
if (instruction == introducer) {
return false;
}
if (users.contains(instruction)) {
if (auto apply = ApplySite::isa(instruction)) {
SmallVector<int, 2> rewritableArgumentIndices;
auto count = apply.getNumArguments();
for (unsigned index = 0; index < count; ++index) {
auto argument = apply.getArgument(index);
if (canReplaceValueWithBorrowedValue(argument)) {
rewritableArgumentIndices.push_back(index);
}
}
if (rewritableArgumentIndices.size() != usesInApply(apply)) {
return false;
}
if (rewrite) {
// We can rewrite all the arguments which are transitive uses of the
// borrow.
for (auto index : rewritableArgumentIndices) {
auto argument = apply.getArgument(index);
auto borrowee = introducer->getOperand();
if (auto *cvi = dyn_cast<CopyValueInst>(argument)) {
cvi->setOperand(borrowee);
modifiedCopyValueInsts.push_back(cvi);
madeChange = true;
} else {
apply.setArgument(index, borrowee);
madeChange = true;
}
}
}
return true;
} else if (auto *bbi = dyn_cast<BeginBorrowInst>(instruction)) {
if (auto *bbi = dyn_cast<BeginBorrowInst>(instruction)) {
if (bbi->isLexical() &&
canReplaceValueWithBorrowedValue(bbi->getOperand())) {
if (rewrite) {
Expand Down Expand Up @@ -234,9 +200,6 @@ bool ShrinkBorrowScope::populateUsers() {
for (auto *use : uses) {
auto *user = use->getUser();
users.insert(user);
if (auto apply = ApplySite::isa(user)) {
++transitiveUsesPerApplySite[apply];
}
}
return true;
}
Expand Down Expand Up @@ -298,20 +261,12 @@ void ShrinkBorrowScope::findBarriers() {
// At that time, it was checked that this block (along with all that
// successor's other predecessors) had a terminator over which the borrow
// scope could be shrunk. Shrink it now.
#ifndef NDEBUG
bool hoisted =
#endif
tryHoistOverInstruction(block->getTerminator());
#ifndef NDEBUG
bool hoisted = tryHoistOverInstruction(block->getTerminator());
assert(hoisted);
#endif
(void)hoisted;
}
SILInstruction *barrier = nullptr;
while ((instruction = instruction->getPreviousInstruction())) {
if (instruction == introducer) {
barrier = instruction;
break;
}
if (!tryHoistOverInstruction(instruction)) {
barrier = instruction;
break;
Expand Down
6 changes: 2 additions & 4 deletions stdlib/public/Concurrency/Actor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,7 @@
#include "swift/ABI/Task.h"
#include "swift/ABI/Actor.h"
#include "swift/Basic/ListMerger.h"
#ifndef SWIFT_CONCURRENCY_BACK_DEPLOYMENT
#include "llvm/Config/config.h"
#else
#ifdef SWIFT_CONCURRENCY_BACK_DEPLOYMENT
// All platforms where we care about back deployment have a known
// configurations.
#define HAVE_PTHREAD_H 1
Expand Down Expand Up @@ -72,7 +70,7 @@
#include <sys/syscall.h>
#endif

#if HAVE_PTHREAD_H
#if defined(_POSIX_THREADS)
#include <pthread.h>

// Only use __has_include since HAVE_PTHREAD_NP_H is not provided.
Expand Down
9 changes: 7 additions & 2 deletions test/SILOptimizer/copy_propagation_borrow.sil
Original file line number Diff line number Diff line change
Expand Up @@ -394,9 +394,11 @@ bb3:
// CHECK: [[ALLOC:%.*]] = alloc_ref $C
// CHECK-NEXT: [[B1:%.*]] = begin_borrow [[ALLOC]]
// CHECK-NOT: copy
// CHECK: [[B2:%.*]] = begin_borrow [[ALLOC]]
// CHECK-NOT: copy
// CHECK: end_borrow [[B1]] : $C
// CHECK: apply %0([[ALLOC]]) : $@convention(thin) (@guaranteed C) -> ()
// CHECK: apply %0([[B2]]) : $@convention(thin) (@guaranteed C) -> ()
// CHECK: end_borrow [[B2]] : $C
// CHECK-NEXT: return [[ALLOC]] : $C
// CHECK-LABEL: } // end sil function 'testInterleavedBorrow'
sil [ossa] @testInterleavedBorrow : $@convention(thin) () -> @owned C {
Expand Down Expand Up @@ -426,11 +428,14 @@ bb0:
// CHECK: [[B1:%.*]] = begin_borrow [[ALLOC]]
// CHECK: apply %{{.*}}([[B1]]) : $@convention(thin) (@guaranteed C) -> ()
// CHECK-NEXT: end_borrow [[B1]] : $C
// CHECK-NEXT: [[B2:%.*]] = begin_borrow [[ALLOC]]
// CHECK-NEXT: cond_br undef, bb1, bb2
// CHECK: bb1:
// CHECK: apply %{{.*}}([[ALLOC]]) : $@convention(thin) (@guaranteed C) -> ()
// CHECK: apply %{{.*}}([[B2]]) : $@convention(thin) (@guaranteed C) -> ()
// CHECK-NEXT: end_borrow [[B2]] : $C
// CHECK-NEXT: br bb3
// CHECK: bb2:
// CHECK-NEXT: end_borrow [[B2]] : $C
// CHECK-NEXT: br bb3
// CHECK: bb3:
// CHECK-NEXT: return [[ALLOC]] : $C
Expand Down
Loading