11#ifndef SWIFT_PARTITIONUTILS_H
22#define SWIFT_PARTITIONUTILS_H
33
4+ #include " swift/Basic/Defer.h"
45#include " swift/Basic/LLVM.h"
56#include " swift/SIL/SILInstruction.h"
67#include " llvm/ADT/SmallVector.h"
@@ -13,6 +14,18 @@ namespace swift {
1314
1415namespace PartitionPrimitives {
1516
17+ #ifndef NDEBUG
18+ extern bool REGIONBASEDISOLATION_ENABLE_VERBOSE_LOGGING;
19+ #define REGIONBASEDISOLATION_VERBOSE_LOG (...) \
20+ do { \
21+ if (REGIONBASEDISOLATION_ENABLE_VERBOSE_LOGGING) { \
22+ LLVM_DEBUG (__VA_ARGS__); \
23+ } \
24+ } while (0 );
25+ #else
26+ #define REGIONBASEDISOLATION_VERBOSE_LOG (...)
27+ #endif
28+
1629struct Element {
1730 unsigned num;
1831
@@ -36,9 +49,9 @@ struct Region {
3649
3750 operator signed () const { return num; }
3851
39- bool isConsumed () const { return num < 0 ; }
52+ bool isTransferred () const { return num < 0 ; }
4053
41- static Region consumed () { return Region (-1 ); }
54+ static Region transferred () { return Region (-1 ); }
4255};
4356}
4457
@@ -48,20 +61,20 @@ using namespace PartitionPrimitives;
4861// / SILInstructions can be translated to
4962enum class PartitionOpKind : uint8_t {
5063 // / Assign one value to the region of another, takes two args, second arg
51- // / must already be tracked with a non-consumed region
64+ // / must already be tracked with a non-transferred region
5265 Assign,
5366
5467 // / Assign one value to a fresh region, takes one arg.
5568 AssignFresh,
5669
5770 // / Merge the regions of two values, takes two args, both must be from
58- // / non-consumed regions.
71+ // / non-transferred regions.
5972 Merge,
6073
61- // / Consume the region of a value if not already consumed , takes one arg.
74+ // / Consume the region of a value if not already transferred , takes one arg.
6275 Transfer,
6376
64- // / Require the region of a value to be non-consumed , takes one arg.
77+ // / Require the region of a value to be non-transferred , takes one arg.
6578 Require,
6679};
6780
@@ -79,7 +92,8 @@ class PartitionOp {
7992 SILInstruction *sourceInst;
8093
8194 // Record an AST expression corresponding to this PartitionOp, currently
82- // populated only for Consume expressions to indicate the value being consumed
95+ // populated only for Consume expressions to indicate the value being
96+ // transferred
8397 Expr *sourceExpr;
8498
8599 // TODO: can the following declarations be merged?
@@ -163,7 +177,7 @@ class PartitionOp {
163177 os << " assign_fresh %%" << OpArgs[0 ] << " \n " ;
164178 break ;
165179 case PartitionOpKind::Transfer:
166- os << " consume %%" << OpArgs[0 ] << " \n " ;
180+ os << " transfer %%" << OpArgs[0 ] << " \n " ;
167181 break ;
168182 case PartitionOpKind::Merge:
169183 os << " merge %%" << OpArgs[0 ] << " with %%" << OpArgs[1 ] << " \n " ;
@@ -200,8 +214,8 @@ static void horizontalUpdate(std::map<Element, Region> &map, Element key,
200214class Partition {
201215private:
202216 // Label each index with a non-negative (unsigned) label if it is associated
203- // with a valid region, and with -1 if it is associated with a consumed region
204- // in-order traversal relied upon.
217+ // with a valid region, and with -1 if it is associated with a transferred
218+ // region in-order traversal relied upon.
205219 std::map<Element, Region> labels;
206220
207221 // Track a label that is guaranteed to be strictly larger than all in use,
@@ -227,8 +241,8 @@ class Partition {
227241 };
228242
229243 for (auto &[i, label] : labels) {
230- // correctness vacuous at consumed indices
231- if (label.isConsumed ())
244+ // correctness vacuous at transferred indices
245+ if (label.isTransferred ())
232246 continue ;
233247
234248 // this label should not exceed fresh_label
@@ -253,7 +267,7 @@ class Partition {
253267
254268 // linear time - For each region label that occurs, find the first index
255269 // at which it occurs and relabel all instances of it to that index.
256- // This excludes the -1 label for consumed regions.
270+ // This excludes the -1 label for transferred regions.
257271 void canonicalize () {
258272 if (canonical)
259273 return ;
@@ -263,8 +277,8 @@ class Partition {
263277
264278 // relies on in-order traversal of labels
265279 for (auto &[i, label] : labels) {
266- // leave -1 (consumed region) as is
267- if (label.isConsumed ())
280+ // leave -1 (transferred region) as is
281+ if (label.isTransferred ())
268282 continue ;
269283
270284 if (!relabel.count (label)) {
@@ -309,7 +323,7 @@ class Partition {
309323 // so set to false to begin with
310324 Partition (bool canonical) : labels({}), canonical(canonical) {}
311325
312- static Partition singleRegion (std::vector <Element> indices) {
326+ static Partition singleRegion (ArrayRef <Element> indices) {
313327 Partition p;
314328 if (!indices.empty ()) {
315329 Region min_index =
@@ -335,8 +349,8 @@ class Partition {
335349
336350 bool isTracked (Element val) const { return labels.count (val); }
337351
338- bool isConsumed (Element val) const {
339- return isTracked (val) && labels.at (val).isConsumed ();
352+ bool isTransferred (Element val) const {
353+ return isTracked (val) && labels.at (val).isTransferred ();
340354 }
341355
342356 // quadratic time - Construct the partition corresponding to the join of the
@@ -361,9 +375,10 @@ class Partition {
361375 // of indices that are in the same region in snd are also in the same region
362376 // in fst - the desired property
363377 for (const auto [i, snd_label] : snd_reduced.labels ) {
364- if (snd_label.isConsumed ())
365- // if snd says that the region has been consumed, mark it consumed in fst
366- horizontalUpdate (fst_reduced.labels , i, Region::consumed ());
378+ if (snd_label.isTransferred ())
379+ // if snd says that the region has been transferred, mark it transferred
380+ // in fst
381+ horizontalUpdate (fst_reduced.labels , i, Region::transferred ());
367382 else
368383 fst_reduced.merge (i, Element (snd_label));
369384 }
@@ -381,29 +396,35 @@ class Partition {
381396
382397 // Apply the passed PartitionOp to this partition, performing its action.
383398 // A `handleFailure` closure can optionally be passed in that will be called
384- // if a consumed region is required. The closure is given the PartitionOp that
385- // failed, and the index of the SIL value that was required but consumed.
386- // Additionally, a list of "nonconsumable" indices can be passed in along with
387- // a handleConsumeNonConsumable closure. In the event that a region containing
388- // one of the nonconsumable indices is consumed , the closure will be called
389- // with the offending Consume.
399+ // if a transferred region is required. The closure is given the PartitionOp
400+ // that failed, and the index of the SIL value that was required but
401+ // transferred. Additionally, a list of "nonconsumable" indices can be passed
402+ // in along with a handleConsumeNonConsumable closure. In the event that a
403+ // region containing one of the nonconsumable indices is transferred , the
404+ // closure will be called with the offending Consume.
390405 void apply (
391406 PartitionOp op,
392407 llvm::function_ref<void (const PartitionOp &, Element)> handleFailure =
393408 [](const PartitionOp &, Element) {},
394-
395409 ArrayRef<Element> nonconsumables = {},
396-
397410 llvm::function_ref<void (const PartitionOp &, Element)>
398411 handleConsumeNonConsumable = [](const PartitionOp &, Element) {}) {
412+ REGIONBASEDISOLATION_VERBOSE_LOG (llvm::dbgs () << " Applying: " ;
413+ op.print (llvm::dbgs ()));
414+ REGIONBASEDISOLATION_VERBOSE_LOG (llvm::dbgs () << " Before: " ;
415+ print (llvm::dbgs ()));
416+ SWIFT_DEFER {
417+ REGIONBASEDISOLATION_VERBOSE_LOG (llvm::dbgs () << " After: " ;
418+ print (llvm::dbgs ()));
419+ };
399420 switch (op.OpKind ) {
400421 case PartitionOpKind::Assign:
401422 assert (op.OpArgs .size () == 2 &&
402423 " Assign PartitionOp should be passed 2 arguments" );
403424 assert (labels.count (op.OpArgs [1 ]) &&
404425 " Assign PartitionOp's source argument should be already tracked" );
405426 // if assigning to a missing region, handle the failure
406- if (isConsumed (op.OpArgs [1 ]))
427+ if (isTransferred (op.OpArgs [1 ]))
407428 handleFailure (op, op.OpArgs [1 ]);
408429
409430 labels.insert_or_assign (op.OpArgs [0 ], labels.at (op.OpArgs [1 ]));
@@ -429,25 +450,24 @@ class Partition {
429450 assert (labels.count (op.OpArgs [0 ]) &&
430451 " Consume PartitionOp's argument should already be tracked" );
431452
432- // check if any nonconsumables are consumed here, and handle the failure if so
453+ // check if any nonconsumables are transferred here, and handle the
454+ // failure if so
433455 for (Element nonconsumable : nonconsumables) {
434456 assert (labels.count (nonconsumable) &&
435457 " nonconsumables should be function args and self, and therefore"
436458 " always present in the label map because of initialization at "
437459 " entry" );
438- if (!isConsumed (nonconsumable) &&
460+ if (!isTransferred (nonconsumable) &&
439461 labels.at (nonconsumable) == labels.at (op.OpArgs [0 ])) {
440462 handleConsumeNonConsumable (op, nonconsumable);
441463 break ;
442464 }
443465 }
444466
445- // ensure region is consumed
446- if (!isConsumed (op.OpArgs [0 ]))
447- // mark region as consumed
448- horizontalUpdate (labels, op.OpArgs [0 ], Region::consumed ());
449-
450-
467+ // ensure region is transferred
468+ if (!isTransferred (op.OpArgs [0 ]))
469+ // mark region as transferred
470+ horizontalUpdate (labels, op.OpArgs [0 ], Region::transferred ());
451471
452472 break ;
453473 case PartitionOpKind::Merge:
@@ -456,10 +476,10 @@ class Partition {
456476 assert (labels.count (op.OpArgs [0 ]) && labels.count (op.OpArgs [1 ]) &&
457477 " Merge PartitionOp's arguments should already be tracked" );
458478
459- // if attempting to merge a consumed region, handle the failure
460- if (isConsumed (op.OpArgs [0 ]))
479+ // if attempting to merge a transferred region, handle the failure
480+ if (isTransferred (op.OpArgs [0 ]))
461481 handleFailure (op, op.OpArgs [0 ]);
462- if (isConsumed (op.OpArgs [1 ]))
482+ if (isTransferred (op.OpArgs [1 ]))
463483 handleFailure (op, op.OpArgs [1 ]);
464484
465485 merge (op.OpArgs [0 ], op.OpArgs [1 ]);
@@ -469,26 +489,26 @@ class Partition {
469489 " Require PartitionOp should be passed 1 argument" );
470490 assert (labels.count (op.OpArgs [0 ]) &&
471491 " Require PartitionOp's argument should already be tracked" );
472- if (isConsumed (op.OpArgs [0 ]))
492+ if (isTransferred (op.OpArgs [0 ]))
473493 handleFailure (op, op.OpArgs [0 ]);
474494 }
475495
476496 assert (is_canonical_correct ());
477497 }
478498
479- // return a vector of the consumed values in this partition
480- std::vector<Element> getConsumedVals () const {
499+ // return a vector of the transferred values in this partition
500+ std::vector<Element> getTransferredVals () const {
481501 // for effeciency, this could return an iterator not a vector
482- std::vector<Element> consumedVals ;
502+ std::vector<Element> transferredVals ;
483503 for (auto [i, _] : labels)
484- if (isConsumed (i))
485- consumedVals .push_back (i);
486- return consumedVals ;
504+ if (isTransferred (i))
505+ transferredVals .push_back (i);
506+ return transferredVals ;
487507 }
488508
489- // return a vector of the non-consumed regions in this partition, each
509+ // return a vector of the non-transferred regions in this partition, each
490510 // represented as a vector of values
491- std::vector<std::vector<Element>> getNonConsumedRegions () const {
511+ std::vector<std::vector<Element>> getNonTransferredRegions () const {
492512 // for effeciency, this could return an iterator not a vector
493513 std::map<Region, std::vector<Element>> buckets;
494514
@@ -523,12 +543,12 @@ class Partition {
523543
524544 os << " [" ;
525545 for (auto [label, indices] : buckets) {
526- os << (label.isConsumed () ? " {" : " (" );
546+ os << (label.isTransferred () ? " {" : " (" );
527547 int j = 0 ;
528548 for (Element i : indices) {
529549 os << (j++ ? " " : " " ) << i;
530550 }
531- os << (label.isConsumed () ? " }" : " )" );
551+ os << (label.isTransferred () ? " }" : " )" );
532552 }
533553 os << " ]\n " ;
534554 }
0 commit comments