Skip to content

Commit d6b4f16

Browse files
committed
[region-isolation] Add a SILLocation to SequenceBoundary in IsolationHistory.
We package all isolation history nodes from a single instruction by placing a sequence boundary at the bottom. When ever we pop, we actually pop a PartitionOp at a time meaning that we pop until we see a SequenceBoundary. Thus the sequence boundary will always be the last element visited when popping meaning that it is a convenient place to stick the SILLocation associated with the entire PartitionOp. As a benefit, there was some unused space in IsolationHistory::Node for that case since we were not using the std::variant field at all.
1 parent aee5a37 commit d6b4f16

File tree

4 files changed

+97
-64
lines changed

4 files changed

+97
-64
lines changed

include/swift/SILOptimizer/Utils/PartitionUtils.h

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,10 @@ class IsolationHistory {
249249
/// Push a node that signals the end of a new sequence of history nodes that
250250
/// should execute together. Must be explicitly ended by a push sequence
251251
/// end. Is non-rentrant, so one cannot have multiple sequence starts.
252-
Node *pushHistorySequenceBoundary();
252+
///
253+
/// \p loc the SILLocation that identifies the instruction that the "package"
254+
/// of history nodes that this sequence boundary ends is associated with.
255+
Node *pushHistorySequenceBoundary(SILLocation loc);
253256

254257
/// Push onto the history list that \p value should be added into its own
255258
/// independent region.
@@ -325,9 +328,12 @@ class IsolationHistory::Node final
325328
/// Child node. Never set on construction.
326329
Node *child = nullptr;
327330

328-
// Either the element that we are adding/removing/modifying or the Node that
329-
// we are merging into.
330-
std::variant<Element, Node *> subject;
331+
/// Contains:
332+
///
333+
/// 1. Node * if we have a CFGHistoryJoin.
334+
/// 2. A SILLocation if we have a SequenceBoundary.
335+
/// 3. An element otherwise.
336+
std::variant<Element, Node *, SILLocation> subject;
331337

332338
/// Number of additional element arguments stored in the tail allocated array.
333339
unsigned numAdditionalElements;
@@ -339,6 +345,8 @@ class IsolationHistory::Node final
339345

340346
Node(Kind kind, Node *parent)
341347
: kind(kind), parent(parent), subject(nullptr) {}
348+
Node(Kind kind, Node *parent, SILLocation loc)
349+
: kind(kind), parent(parent), subject(loc) {}
342350
Node(Kind kind, Node *parent, Element value)
343351
: kind(kind), parent(parent), subject(value), numAdditionalElements(0) {}
344352
Node(Kind kind, Node *parent, Element primaryElement,
@@ -405,6 +413,12 @@ class IsolationHistory::Node final
405413
return nullptr;
406414
return getFirstArgAsNode();
407415
}
416+
417+
std::optional<SILLocation> getHistoryBoundaryLoc() const {
418+
if (kind != SequenceBoundary)
419+
return {};
420+
return std::get<SILLocation>(subject);
421+
}
408422
};
409423

410424
class IsolationHistory::Factory {
@@ -671,12 +685,12 @@ class Partition {
671685

672686
/// Return a new Partition that has a single region containing the elements of
673687
/// \p indices.
674-
static Partition singleRegion(ArrayRef<Element> indices,
688+
static Partition singleRegion(SILLocation loc, ArrayRef<Element> indices,
675689
IsolationHistory inputHistory);
676690

677691
/// Return a new Partition that has each element of \p indices in their own
678692
/// region.
679-
static Partition separateRegions(ArrayRef<Element> indices,
693+
static Partition separateRegions(SILLocation loc, ArrayRef<Element> indices,
680694
IsolationHistory inputHistory);
681695

682696
/// Test two partititons for equality by first putting them in canonical form
@@ -829,8 +843,8 @@ class Partition {
829843
void printHistory(llvm::raw_ostream &os) const;
830844

831845
/// See docs on \p history.pushHistorySequenceBoundary().
832-
IsolationHistoryNode *pushHistorySequenceBoundary() {
833-
return history.pushHistorySequenceBoundary();
846+
IsolationHistoryNode *pushHistorySequenceBoundary(SILLocation loc) {
847+
return history.pushHistorySequenceBoundary(loc);
834848
}
835849

836850
bool isTransferred(Element val) const {
@@ -1043,6 +1057,11 @@ struct PartitionOpEvaluator {
10431057
return asImpl().isClosureCaptured(elt, op);
10441058
}
10451059

1060+
/// Some evaluators pass in mock instructions that one cannot call getLoc()
1061+
/// upon. So to allow for this, provide a routine that our impl can override
1062+
/// if they need to.
1063+
static SILLocation getLoc(SILInstruction *inst) { return Impl::getLoc(inst); }
1064+
10461065
/// Apply \p op to the partition op.
10471066
void apply(const PartitionOp &op) const {
10481067
if (shouldEmitVerboseLogging()) {
@@ -1061,7 +1080,7 @@ struct PartitionOpEvaluator {
10611080

10621081
// Set the boundary so that as we push, this shows when to stop processing
10631082
// for this PartitionOp.
1064-
p.pushHistorySequenceBoundary();
1083+
p.pushHistorySequenceBoundary(getLoc(op.getSourceInst()));
10651084

10661085
switch (op.getKind()) {
10671086
case PartitionOpKind::Assign:
@@ -1299,6 +1318,8 @@ struct PartitionOpEvaluatorBaseImpl : PartitionOpEvaluator<Subclass> {
12991318

13001319
/// By default squelch errors.
13011320
bool shouldTryToSquelchErrors() const { return true; }
1321+
1322+
static SILLocation getLoc(SILInstruction *inst) { return inst->getLoc(); }
13021323
};
13031324

13041325
/// A subclass of PartitionOpEvaluatorBaseImpl that doesn't have any special

lib/SILOptimizer/Analysis/RegionAnalysis.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1460,7 +1460,8 @@ class PartitionOpTranslator {
14601460
auto functionArguments = function->getArguments();
14611461
if (functionArguments.empty()) {
14621462
LLVM_DEBUG(llvm::dbgs() << " None.\n");
1463-
functionArgPartition = Partition::singleRegion({}, historyFactory.get());
1463+
functionArgPartition = Partition::singleRegion(SILLocation::invalid(), {},
1464+
historyFactory.get());
14641465
return;
14651466
}
14661467

@@ -1489,8 +1490,8 @@ class PartitionOpTranslator {
14891490
}
14901491
}
14911492

1492-
functionArgPartition =
1493-
Partition::singleRegion(nonSendableJoinedIndices, historyFactory.get());
1493+
functionArgPartition = Partition::singleRegion(
1494+
SILLocation::invalid(), nonSendableJoinedIndices, historyFactory.get());
14941495
for (Element elt : nonSendableSeparateIndices) {
14951496
functionArgPartition->trackNewElement(elt);
14961497
}

lib/SILOptimizer/Utils/PartitionUtils.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ void PartitionOp::print(llvm::raw_ostream &os, bool extraSpace) const {
237237
// MARK: Partition
238238
//===----------------------------------------------------------------------===//
239239

240-
Partition Partition::singleRegion(ArrayRef<Element> indices,
240+
Partition Partition::singleRegion(SILLocation loc, ArrayRef<Element> indices,
241241
IsolationHistory inputHistory) {
242242
Partition p(inputHistory);
243243
if (!indices.empty()) {
@@ -249,7 +249,7 @@ Partition Partition::singleRegion(ArrayRef<Element> indices,
249249

250250
// Place all of the operations until end of scope into one history
251251
// sequence.
252-
p.pushHistorySequenceBoundary();
252+
p.pushHistorySequenceBoundary(loc);
253253

254254
// First create a region for repElement. We are going to merge all other
255255
// regions into its region.
@@ -269,14 +269,14 @@ Partition Partition::singleRegion(ArrayRef<Element> indices,
269269
return p;
270270
}
271271

272-
Partition Partition::separateRegions(ArrayRef<Element> indices,
272+
Partition Partition::separateRegions(SILLocation loc, ArrayRef<Element> indices,
273273
IsolationHistory inputHistory) {
274274
Partition p(inputHistory);
275275
if (indices.empty())
276276
return p;
277277

278278
// Place all operations in one history sequence.
279-
p.pushHistorySequenceBoundary();
279+
p.pushHistorySequenceBoundary(loc);
280280

281281
auto maxIndex = Element(0);
282282
for (Element index : indices) {
@@ -954,10 +954,11 @@ IsolationHistory::pushNewElementRegion(Element element) {
954954
return getHead();
955955
}
956956

957-
IsolationHistory::Node *IsolationHistory::pushHistorySequenceBoundary() {
957+
IsolationHistory::Node *
958+
IsolationHistory::pushHistorySequenceBoundary(SILLocation loc) {
958959
unsigned size = Node::totalSizeToAlloc<Element>(0);
959960
void *mem = factory->allocator.Allocate(size, alignof(Node));
960-
head = new (mem) Node(Node::SequenceBoundary, head);
961+
head = new (mem) Node(Node::SequenceBoundary, head, loc);
961962
return getHead();
962963
}
963964

unittests/SILOptimizer/PartitionUtilsTest.cpp

Lines changed: 56 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,44 @@ struct MockedPartitionOpEvaluator final
4949
}
5050

5151
bool shouldTryToSquelchErrors() const { return false; }
52+
53+
static SILLocation getLoc(SILInstruction *inst) {
54+
return SILLocation::invalid();
55+
}
56+
};
57+
58+
} // namespace
59+
60+
namespace {
61+
62+
struct MockedPartitionOpEvaluatorWithFailureCallback final
63+
: PartitionOpEvaluatorBaseImpl<
64+
MockedPartitionOpEvaluatorWithFailureCallback> {
65+
using FailureCallbackTy =
66+
std::function<void(const PartitionOp &, unsigned, TransferringOperand *)>;
67+
FailureCallbackTy failureCallback;
68+
69+
MockedPartitionOpEvaluatorWithFailureCallback(
70+
Partition &workingPartition, TransferringOperandSetFactory &ptrSetFactory,
71+
FailureCallbackTy failureCallback)
72+
: PartitionOpEvaluatorBaseImpl(workingPartition, ptrSetFactory),
73+
failureCallback(failureCallback) {}
74+
75+
void handleLocalUseAfterTransfer(const PartitionOp &op, Element elt,
76+
TransferringOperand *transferringOp) const {
77+
failureCallback(op, elt, transferringOp);
78+
}
79+
80+
// Just say that we always have a disconnected value.
81+
SILIsolationInfo getIsolationRegionInfo(Element elt) const {
82+
return SILIsolationInfo::getDisconnected();
83+
}
84+
85+
bool shouldTryToSquelchErrors() const { return false; }
86+
87+
static SILLocation getLoc(SILInstruction *inst) {
88+
return SILLocation::invalid();
89+
}
5290
};
5391

5492
} // namespace
@@ -71,6 +109,8 @@ SILInstruction *instSingletons[5] = {
71109
(SILInstruction *)0xBBDA0000,
72110
};
73111

112+
SILLocation fakeLoc = SILLocation::invalid();
113+
74114
// This test tests that if a series of merges is split between two partitions
75115
// p1 and p2, but also applied in its entirety to p3, then joining p1 and p2
76116
// yields p3.
@@ -198,8 +238,8 @@ TEST(PartitionUtilsTest, Join1) {
198238

199239
Element data1[] = {Element(0), Element(1), Element(2),
200240
Element(3), Element(4), Element(5)};
201-
Partition p1 =
202-
Partition::separateRegions(llvm::ArrayRef(data1), historyFactory.get());
241+
Partition p1 = Partition::separateRegions(fakeLoc, llvm::ArrayRef(data1),
242+
historyFactory.get());
203243

204244
{
205245
MockedPartitionOpEvaluator eval(p1, factory);
@@ -211,8 +251,8 @@ TEST(PartitionUtilsTest, Join1) {
211251
PartitionOp::Assign(Element(5), Element(2))});
212252
}
213253

214-
Partition p2 =
215-
Partition::separateRegions(llvm::ArrayRef(data1), historyFactory.get());
254+
Partition p2 = Partition::separateRegions(fakeLoc, llvm::ArrayRef(data1),
255+
historyFactory.get());
216256
{
217257
MockedPartitionOpEvaluator eval(p2, factory);
218258
eval.apply({PartitionOp::Assign(Element(0), Element(0)),
@@ -240,8 +280,8 @@ TEST(PartitionUtilsTest, Join2) {
240280

241281
Element data1[] = {Element(0), Element(1), Element(2),
242282
Element(3), Element(4), Element(5)};
243-
Partition p1 =
244-
Partition::separateRegions(llvm::ArrayRef(data1), historyFactory.get());
283+
Partition p1 = Partition::separateRegions(fakeLoc, llvm::ArrayRef(data1),
284+
historyFactory.get());
245285

246286
{
247287
MockedPartitionOpEvaluator eval(p1, factory);
@@ -255,8 +295,8 @@ TEST(PartitionUtilsTest, Join2) {
255295

256296
Element data2[] = {Element(4), Element(5), Element(6),
257297
Element(7), Element(8), Element(9)};
258-
Partition p2 =
259-
Partition::separateRegions(llvm::ArrayRef(data2), historyFactory.get());
298+
Partition p2 = Partition::separateRegions(fakeLoc, llvm::ArrayRef(data2),
299+
historyFactory.get());
260300
{
261301
MockedPartitionOpEvaluator eval(p2, factory);
262302
eval.apply({PartitionOp::Assign(Element(4), Element(4)),
@@ -288,8 +328,8 @@ TEST(PartitionUtilsTest, Join2Reversed) {
288328

289329
Element data1[] = {Element(0), Element(1), Element(2),
290330
Element(3), Element(4), Element(5)};
291-
Partition p1 =
292-
Partition::separateRegions(llvm::ArrayRef(data1), historyFactory.get());
331+
Partition p1 = Partition::separateRegions(fakeLoc, llvm::ArrayRef(data1),
332+
historyFactory.get());
293333

294334
{
295335
MockedPartitionOpEvaluator eval(p1, factory);
@@ -303,8 +343,8 @@ TEST(PartitionUtilsTest, Join2Reversed) {
303343

304344
Element data2[] = {Element(4), Element(5), Element(6),
305345
Element(7), Element(8), Element(9)};
306-
Partition p2 =
307-
Partition::separateRegions(llvm::ArrayRef(data2), historyFactory.get());
346+
Partition p2 = Partition::separateRegions(fakeLoc, llvm::ArrayRef(data2),
347+
historyFactory.get());
308348
{
309349
MockedPartitionOpEvaluator eval(p2, factory);
310350
eval.apply({PartitionOp::Assign(Element(4), Element(4)),
@@ -341,8 +381,8 @@ TEST(PartitionUtilsTest, JoinLarge) {
341381
Element(15), Element(16), Element(17), Element(18), Element(19),
342382
Element(20), Element(21), Element(22), Element(23), Element(24),
343383
Element(25), Element(26), Element(27), Element(28), Element(29)};
344-
Partition p1 =
345-
Partition::separateRegions(llvm::ArrayRef(data1), historyFactory.get());
384+
Partition p1 = Partition::separateRegions(fakeLoc, llvm::ArrayRef(data1),
385+
historyFactory.get());
346386
{
347387
MockedPartitionOpEvaluator eval(p1, factory);
348388
eval.apply({PartitionOp::Assign(Element(0), Element(29)),
@@ -384,8 +424,8 @@ TEST(PartitionUtilsTest, JoinLarge) {
384424
Element(30), Element(31), Element(32), Element(33), Element(34),
385425
Element(35), Element(36), Element(37), Element(38), Element(39),
386426
Element(40), Element(41), Element(42), Element(43), Element(44)};
387-
Partition p2 =
388-
Partition::separateRegions(llvm::ArrayRef(data2), historyFactory.get());
427+
Partition p2 = Partition::separateRegions(fakeLoc, llvm::ArrayRef(data2),
428+
historyFactory.get());
389429
{
390430
MockedPartitionOpEvaluator eval(p2, factory);
391431
eval.apply({PartitionOp::Assign(Element(15), Element(31)),
@@ -558,36 +598,6 @@ TEST(PartitionUtilsTest, TestAssign) {
558598
EXPECT_TRUE(Partition::equals(p1, p3));
559599
}
560600

561-
namespace {
562-
563-
struct MockedPartitionOpEvaluatorWithFailureCallback final
564-
: PartitionOpEvaluatorBaseImpl<
565-
MockedPartitionOpEvaluatorWithFailureCallback> {
566-
using FailureCallbackTy =
567-
std::function<void(const PartitionOp &, unsigned, TransferringOperand *)>;
568-
FailureCallbackTy failureCallback;
569-
570-
MockedPartitionOpEvaluatorWithFailureCallback(
571-
Partition &workingPartition, TransferringOperandSetFactory &ptrSetFactory,
572-
FailureCallbackTy failureCallback)
573-
: PartitionOpEvaluatorBaseImpl(workingPartition, ptrSetFactory),
574-
failureCallback(failureCallback) {}
575-
576-
void handleLocalUseAfterTransfer(const PartitionOp &op, Element elt,
577-
TransferringOperand *transferringOp) const {
578-
failureCallback(op, elt, transferringOp);
579-
}
580-
581-
// Just say that we always have a disconnected value.
582-
SILIsolationInfo getIsolationRegionInfo(Element elt) const {
583-
return SILIsolationInfo::getDisconnected();
584-
}
585-
586-
bool shouldTryToSquelchErrors() const { return false; }
587-
};
588-
589-
} // namespace
590-
591601
// This test tests that consumption consumes entire regions as expected
592602
TEST(PartitionUtilsTest, TestConsumeAndRequire) {
593603
llvm::BumpPtrAllocator allocator;

0 commit comments

Comments
 (0)