Skip to content

Commit 983ee29

Browse files
authored
Merge pull request #33979 from gottesmm/pr-6fc6a6364dc218208424a3de3cc104bc03cbce80
[semantic-arc] Add support for specifying the specific sub-semantic arc transforms to perform from the command line.
2 parents f0f2878 + 5850878 commit 983ee29

File tree

7 files changed

+251
-140
lines changed

7 files changed

+251
-140
lines changed

lib/SILOptimizer/SemanticARC/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ target_sources(swiftSILOptimizer PRIVATE
66
CopyValueOpts.cpp
77
OwnedToGuaranteedPhiOpt.cpp
88
Context.cpp
9+
SemanticARCOptVisitor.cpp
910
)

lib/SILOptimizer/SemanticARC/Context.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ struct LLVM_LIBRARY_VISIBILITY Context {
7272
/// copy_values we /do/ allow.
7373
bool onlyGuaranteedOpts;
7474

75+
/// Callbacks that we must use to remove or RAUW values.
76+
InstModCallbacks instModCallbacks;
77+
7578
using FrozenMultiMapRange =
7679
decltype(joinedOwnedIntroducerToConsumedOperands)::PairToSecondEltRange;
7780

@@ -81,7 +84,7 @@ struct LLVM_LIBRARY_VISIBILITY Context {
8184
return *deadEndBlocks;
8285
}
8386

84-
Context(SILFunction &fn, bool onlyGuaranteedOpts)
87+
Context(SILFunction &fn, bool onlyGuaranteedOpts, InstModCallbacks callbacks)
8588
: fn(fn), deadEndBlocks(), lifetimeFrontier(),
8689
addressToExhaustiveWriteListCache(constructCacheValue),
8790
onlyGuaranteedOpts(onlyGuaranteedOpts) {}

lib/SILOptimizer/SemanticARC/OwnedToGuaranteedPhiOpt.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@
1616
///
1717
//===----------------------------------------------------------------------===//
1818

19+
#include "Context.h"
1920
#include "OwnershipPhiOperand.h"
20-
#include "SemanticARCOptVisitor.h"
21+
#include "Transforms.h"
2122

2223
using namespace swift;
2324
using namespace swift::semanticarc;
@@ -120,7 +121,7 @@ static bool getIncomingJoinedLiveRangeOperands(
120121
// Top Level Entrypoint
121122
//===----------------------------------------------------------------------===//
122123

123-
bool SemanticARCOptVisitor::performPostPeepholeOwnedArgElimination() {
124+
bool swift::semanticarc::tryConvertOwnedPhisToGuaranteedPhis(Context &ctx) {
124125
bool madeChange = false;
125126

126127
// First freeze our multi-map so we can use it for map queries. Also, setup a
@@ -211,7 +212,7 @@ bool SemanticARCOptVisitor::performPostPeepholeOwnedArgElimination() {
211212
incomingValueUpdates.emplace_back(cvi->getOperand(), updateOffset);
212213
}
213214
std::move(lr).convertToGuaranteedAndRAUW(cvi->getOperand(),
214-
getCallbacks());
215+
ctx.instModCallbacks);
215216
continue;
216217
}
217218
llvm_unreachable("Unhandled optimizable introducer!");
@@ -227,7 +228,7 @@ bool SemanticARCOptVisitor::performPostPeepholeOwnedArgElimination() {
227228
// Then convert the phi's live range to be guaranteed.
228229
std::move(joinedLiveRange)
229230
.convertJoinedLiveRangePhiToGuaranteed(
230-
getDeadEndBlocks(), ctx.lifetimeFrontier, getCallbacks());
231+
ctx.getDeadEndBlocks(), ctx.lifetimeFrontier, ctx.instModCallbacks);
231232

232233
// Now if our phi operand consumes/forwards its guaranteed input, insert a
233234
// begin_borrow along the incoming value edges. We have to do this after
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
//===--- SemanticARCOptVisitor.cpp ----------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2020 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+
/// \file
14+
///
15+
/// Implementation of the main optimize loop of the ARC visitor peephole
16+
/// optimizer.
17+
///
18+
//===----------------------------------------------------------------------===//
19+
20+
#include "SemanticARCOptVisitor.h"
21+
#include "swift/SIL/DebugUtils.h"
22+
23+
using namespace swift;
24+
using namespace swift::semanticarc;
25+
26+
bool SemanticARCOptVisitor::optimize() {
27+
bool madeChange = false;
28+
29+
// First process the worklist until we reach a fixed point.
30+
madeChange |= processWorklist();
31+
32+
{
33+
// If we made a change, set that we assume we are at fixed point and then
34+
// re-run the worklist so that we can
35+
// properly seeded the ARC peephole map.
36+
ctx.assumingAtFixedPoint = true;
37+
SWIFT_DEFER { ctx.assumingAtFixedPoint = false; };
38+
39+
// Add everything in visitedSinceLastMutation to the worklist so we
40+
// recompute our fixed point.
41+
drainVisitedSinceLastMutationIntoWorklist();
42+
43+
// Then re-run the worklist. We shouldn't modify anything since we are at a
44+
// fixed point and are just using this to seed the
45+
// joinedOwnedIntroducerToConsumedOperands after we have finished changing
46+
// things. If we did change something, we did something weird, so assert!
47+
bool madeAdditionalChanges = processWorklist();
48+
(void)madeAdditionalChanges;
49+
assert(!madeAdditionalChanges && "Should be at the fixed point");
50+
}
51+
52+
return madeChange;
53+
}
54+
55+
bool SemanticARCOptVisitor::processWorklist() {
56+
// NOTE: The madeChange here is not strictly necessary since we only have
57+
// items added to the worklist today if we have already made /some/ sort of
58+
// change. That being said, I think there is a low cost to including this here
59+
// and makes the algorithm more correct, visually and in the face of potential
60+
// refactoring.
61+
bool madeChange = false;
62+
63+
while (!worklist.empty()) {
64+
// Pop the last element off the list. If we were returned None, we blotted
65+
// this element, so skip it.
66+
SILValue next = worklist.pop_back_val().getValueOr(SILValue());
67+
if (!next)
68+
continue;
69+
70+
// First check if this is a value that we have visited since the last time
71+
// we erased an instruction. If we have visited it, skip it. Every time we
72+
// modify something, we should be deleting an instruction, so we have not
73+
// found any further information.
74+
if (!visitedSinceLastMutation.insert(next).second) {
75+
continue;
76+
}
77+
78+
// First check if this is an instruction that is trivially dead. This can
79+
// occur if we eliminate rr traffic resulting in dead projections and the
80+
// like.
81+
//
82+
// If we delete, we first add all of our deleted instructions operands to
83+
// the worklist and then remove all results (since we are going to delete
84+
// the instruction).
85+
if (auto *defInst = next->getDefiningInstruction()) {
86+
if (isInstructionTriviallyDead(defInst)) {
87+
assert(!ctx.assumingAtFixedPoint &&
88+
"Assumed was at fixed point and recomputing state?!");
89+
deleteAllDebugUses(defInst);
90+
eraseInstruction(defInst);
91+
madeChange = true;
92+
ctx.verify();
93+
continue;
94+
}
95+
}
96+
97+
// Otherwise, if we have a single value instruction (to be expanded later
98+
// perhaps), try to visit that value recursively.
99+
if (auto *svi = dyn_cast<SingleValueInstruction>(next)) {
100+
bool madeSingleChange = visit(svi);
101+
assert((!madeSingleChange || !ctx.assumingAtFixedPoint) &&
102+
"Assumed was at fixed point and modified state?!");
103+
madeChange |= madeSingleChange;
104+
if (madeSingleChange) {
105+
ctx.verify();
106+
}
107+
continue;
108+
}
109+
}
110+
111+
return madeChange;
112+
}

lib/SILOptimizer/SemanticARC/SemanticARCOptVisitor.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,13 @@ struct LLVM_LIBRARY_VISIBILITY SemanticARCOptVisitor
4848
Context ctx;
4949

5050
explicit SemanticARCOptVisitor(SILFunction &fn, bool onlyGuaranteedOpts)
51-
: ctx(fn, onlyGuaranteedOpts) {}
51+
: ctx(fn, onlyGuaranteedOpts,
52+
InstModCallbacks(
53+
[this](SILInstruction *inst) { eraseInstruction(inst); },
54+
[](SILInstruction *) {}, [](SILValue, SILValue) {},
55+
[this](SingleValueInstruction *i, SILValue value) {
56+
eraseAndRAUWSingleValueInstruction(i, value);
57+
})) {}
5258

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

@@ -190,7 +196,6 @@ struct LLVM_LIBRARY_VISIBILITY SemanticARCOptVisitor
190196
bool performGuaranteedCopyValueOptimization(CopyValueInst *cvi);
191197
bool eliminateDeadLiveRangeCopyValue(CopyValueInst *cvi);
192198
bool tryJoiningCopyValueLiveRangeWithOperand(CopyValueInst *cvi);
193-
bool performPostPeepholeOwnedArgElimination();
194199
};
195200

196201
} // namespace semanticarc

0 commit comments

Comments
 (0)