Skip to content

[semantic-arc] Add support for specifying the specific sub-semantic arc transforms to perform from the command line. #33979

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
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
1 change: 1 addition & 0 deletions lib/SILOptimizer/SemanticARC/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ target_sources(swiftSILOptimizer PRIVATE
CopyValueOpts.cpp
OwnedToGuaranteedPhiOpt.cpp
Context.cpp
SemanticARCOptVisitor.cpp
)
5 changes: 4 additions & 1 deletion lib/SILOptimizer/SemanticARC/Context.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ struct LLVM_LIBRARY_VISIBILITY Context {
/// copy_values we /do/ allow.
bool onlyGuaranteedOpts;

/// Callbacks that we must use to remove or RAUW values.
InstModCallbacks instModCallbacks;

using FrozenMultiMapRange =
decltype(joinedOwnedIntroducerToConsumedOperands)::PairToSecondEltRange;

Expand All @@ -81,7 +84,7 @@ struct LLVM_LIBRARY_VISIBILITY Context {
return *deadEndBlocks;
}

Context(SILFunction &fn, bool onlyGuaranteedOpts)
Context(SILFunction &fn, bool onlyGuaranteedOpts, InstModCallbacks callbacks)
: fn(fn), deadEndBlocks(), lifetimeFrontier(),
addressToExhaustiveWriteListCache(constructCacheValue),
onlyGuaranteedOpts(onlyGuaranteedOpts) {}
Expand Down
9 changes: 5 additions & 4 deletions lib/SILOptimizer/SemanticARC/OwnedToGuaranteedPhiOpt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@
///
//===----------------------------------------------------------------------===//

#include "Context.h"
#include "OwnershipPhiOperand.h"
#include "SemanticARCOptVisitor.h"
#include "Transforms.h"

using namespace swift;
using namespace swift::semanticarc;
Expand Down Expand Up @@ -120,7 +121,7 @@ static bool getIncomingJoinedLiveRangeOperands(
// Top Level Entrypoint
//===----------------------------------------------------------------------===//

bool SemanticARCOptVisitor::performPostPeepholeOwnedArgElimination() {
bool swift::semanticarc::tryConvertOwnedPhisToGuaranteedPhis(Context &ctx) {
bool madeChange = false;

// First freeze our multi-map so we can use it for map queries. Also, setup a
Expand Down Expand Up @@ -211,7 +212,7 @@ bool SemanticARCOptVisitor::performPostPeepholeOwnedArgElimination() {
incomingValueUpdates.emplace_back(cvi->getOperand(), updateOffset);
}
std::move(lr).convertToGuaranteedAndRAUW(cvi->getOperand(),
getCallbacks());
ctx.instModCallbacks);
continue;
}
llvm_unreachable("Unhandled optimizable introducer!");
Expand All @@ -227,7 +228,7 @@ bool SemanticARCOptVisitor::performPostPeepholeOwnedArgElimination() {
// Then convert the phi's live range to be guaranteed.
std::move(joinedLiveRange)
.convertJoinedLiveRangePhiToGuaranteed(
getDeadEndBlocks(), ctx.lifetimeFrontier, getCallbacks());
ctx.getDeadEndBlocks(), ctx.lifetimeFrontier, ctx.instModCallbacks);

// Now if our phi operand consumes/forwards its guaranteed input, insert a
// begin_borrow along the incoming value edges. We have to do this after
Expand Down
112 changes: 112 additions & 0 deletions lib/SILOptimizer/SemanticARC/SemanticARCOptVisitor.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
//===--- SemanticARCOptVisitor.cpp ----------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2020 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
//
//===----------------------------------------------------------------------===//
///
/// \file
///
/// Implementation of the main optimize loop of the ARC visitor peephole
/// optimizer.
///
//===----------------------------------------------------------------------===//

#include "SemanticARCOptVisitor.h"
#include "swift/SIL/DebugUtils.h"

using namespace swift;
using namespace swift::semanticarc;

bool SemanticARCOptVisitor::optimize() {
bool madeChange = false;

// First process the worklist until we reach a fixed point.
madeChange |= processWorklist();

{
// If we made a change, set that we assume we are at fixed point and then
// re-run the worklist so that we can
// properly seeded the ARC peephole map.
ctx.assumingAtFixedPoint = true;
SWIFT_DEFER { ctx.assumingAtFixedPoint = false; };

// Add everything in visitedSinceLastMutation to the worklist so we
// recompute our fixed point.
drainVisitedSinceLastMutationIntoWorklist();

// Then re-run the worklist. We shouldn't modify anything since we are at a
// fixed point and are just using this to seed the
// joinedOwnedIntroducerToConsumedOperands after we have finished changing
// things. If we did change something, we did something weird, so assert!
bool madeAdditionalChanges = processWorklist();
(void)madeAdditionalChanges;
assert(!madeAdditionalChanges && "Should be at the fixed point");
}

return madeChange;
}

bool SemanticARCOptVisitor::processWorklist() {
// NOTE: The madeChange here is not strictly necessary since we only have
// items added to the worklist today if we have already made /some/ sort of
// change. That being said, I think there is a low cost to including this here
// and makes the algorithm more correct, visually and in the face of potential
// refactoring.
bool madeChange = false;

while (!worklist.empty()) {
// Pop the last element off the list. If we were returned None, we blotted
// this element, so skip it.
SILValue next = worklist.pop_back_val().getValueOr(SILValue());
if (!next)
continue;

// First check if this is a value that we have visited since the last time
// we erased an instruction. If we have visited it, skip it. Every time we
// modify something, we should be deleting an instruction, so we have not
// found any further information.
if (!visitedSinceLastMutation.insert(next).second) {
continue;
}

// First check if this is an instruction that is trivially dead. This can
// occur if we eliminate rr traffic resulting in dead projections and the
// like.
//
// If we delete, we first add all of our deleted instructions operands to
// the worklist and then remove all results (since we are going to delete
// the instruction).
if (auto *defInst = next->getDefiningInstruction()) {
if (isInstructionTriviallyDead(defInst)) {
assert(!ctx.assumingAtFixedPoint &&
"Assumed was at fixed point and recomputing state?!");
deleteAllDebugUses(defInst);
eraseInstruction(defInst);
madeChange = true;
ctx.verify();
continue;
}
}

// Otherwise, if we have a single value instruction (to be expanded later
// perhaps), try to visit that value recursively.
if (auto *svi = dyn_cast<SingleValueInstruction>(next)) {
bool madeSingleChange = visit(svi);
assert((!madeSingleChange || !ctx.assumingAtFixedPoint) &&
"Assumed was at fixed point and modified state?!");
madeChange |= madeSingleChange;
if (madeSingleChange) {
ctx.verify();
}
continue;
}
}

return madeChange;
}
9 changes: 7 additions & 2 deletions lib/SILOptimizer/SemanticARC/SemanticARCOptVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,13 @@ struct LLVM_LIBRARY_VISIBILITY SemanticARCOptVisitor
Context ctx;

explicit SemanticARCOptVisitor(SILFunction &fn, bool onlyGuaranteedOpts)
: ctx(fn, onlyGuaranteedOpts) {}
: ctx(fn, onlyGuaranteedOpts,
InstModCallbacks(
[this](SILInstruction *inst) { eraseInstruction(inst); },
[](SILInstruction *) {}, [](SILValue, SILValue) {},
[this](SingleValueInstruction *i, SILValue value) {
eraseAndRAUWSingleValueInstruction(i, value);
})) {}

DeadEndBlocks &getDeadEndBlocks() { return ctx.getDeadEndBlocks(); }

Expand Down Expand Up @@ -190,7 +196,6 @@ struct LLVM_LIBRARY_VISIBILITY SemanticARCOptVisitor
bool performGuaranteedCopyValueOptimization(CopyValueInst *cvi);
bool eliminateDeadLiveRangeCopyValue(CopyValueInst *cvi);
bool tryJoiningCopyValueLiveRangeWithOperand(CopyValueInst *cvi);
bool performPostPeepholeOwnedArgElimination();
};

} // namespace semanticarc
Expand Down
Loading