1
1
#ifndef SWIFT_PARTITIONUTILS_H
2
2
#define SWIFT_PARTITIONUTILS_H
3
3
4
+ #include " swift/Basic/Defer.h"
4
5
#include " swift/Basic/LLVM.h"
5
6
#include " swift/SIL/SILInstruction.h"
6
7
#include " llvm/ADT/SmallVector.h"
@@ -13,6 +14,18 @@ namespace swift {
13
14
14
15
namespace PartitionPrimitives {
15
16
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
+
16
29
struct Element {
17
30
unsigned num;
18
31
@@ -36,9 +49,9 @@ struct Region {
36
49
37
50
operator signed () const { return num; }
38
51
39
- bool isConsumed () const { return num < 0 ; }
52
+ bool isTransferred () const { return num < 0 ; }
40
53
41
- static Region consumed () { return Region (-1 ); }
54
+ static Region transferred () { return Region (-1 ); }
42
55
};
43
56
}
44
57
@@ -48,20 +61,20 @@ using namespace PartitionPrimitives;
48
61
// / SILInstructions can be translated to
49
62
enum class PartitionOpKind : uint8_t {
50
63
// / 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
52
65
Assign,
53
66
54
67
// / Assign one value to a fresh region, takes one arg.
55
68
AssignFresh,
56
69
57
70
// / Merge the regions of two values, takes two args, both must be from
58
- // / non-consumed regions.
71
+ // / non-transferred regions.
59
72
Merge,
60
73
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.
62
75
Transfer,
63
76
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.
65
78
Require,
66
79
};
67
80
@@ -79,7 +92,8 @@ class PartitionOp {
79
92
SILInstruction *sourceInst;
80
93
81
94
// 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
83
97
Expr *sourceExpr;
84
98
85
99
// TODO: can the following declarations be merged?
@@ -163,7 +177,7 @@ class PartitionOp {
163
177
os << " assign_fresh %%" << OpArgs[0 ] << " \n " ;
164
178
break ;
165
179
case PartitionOpKind::Transfer:
166
- os << " consume %%" << OpArgs[0 ] << " \n " ;
180
+ os << " transfer %%" << OpArgs[0 ] << " \n " ;
167
181
break ;
168
182
case PartitionOpKind::Merge:
169
183
os << " merge %%" << OpArgs[0 ] << " with %%" << OpArgs[1 ] << " \n " ;
@@ -200,8 +214,8 @@ static void horizontalUpdate(std::map<Element, Region> &map, Element key,
200
214
class Partition {
201
215
private:
202
216
// 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.
205
219
std::map<Element, Region> labels;
206
220
207
221
// Track a label that is guaranteed to be strictly larger than all in use,
@@ -227,8 +241,8 @@ class Partition {
227
241
};
228
242
229
243
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 ())
232
246
continue ;
233
247
234
248
// this label should not exceed fresh_label
@@ -253,7 +267,7 @@ class Partition {
253
267
254
268
// linear time - For each region label that occurs, find the first index
255
269
// 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.
257
271
void canonicalize () {
258
272
if (canonical)
259
273
return ;
@@ -263,8 +277,8 @@ class Partition {
263
277
264
278
// relies on in-order traversal of labels
265
279
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 ())
268
282
continue ;
269
283
270
284
if (!relabel.count (label)) {
@@ -309,7 +323,7 @@ class Partition {
309
323
// so set to false to begin with
310
324
Partition (bool canonical) : labels({}), canonical(canonical) {}
311
325
312
- static Partition singleRegion (std::vector <Element> indices) {
326
+ static Partition singleRegion (ArrayRef <Element> indices) {
313
327
Partition p;
314
328
if (!indices.empty ()) {
315
329
Region min_index =
@@ -335,8 +349,8 @@ class Partition {
335
349
336
350
bool isTracked (Element val) const { return labels.count (val); }
337
351
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 ();
340
354
}
341
355
342
356
// quadratic time - Construct the partition corresponding to the join of the
@@ -361,9 +375,10 @@ class Partition {
361
375
// of indices that are in the same region in snd are also in the same region
362
376
// in fst - the desired property
363
377
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 ());
367
382
else
368
383
fst_reduced.merge (i, Element (snd_label));
369
384
}
@@ -381,29 +396,35 @@ class Partition {
381
396
382
397
// Apply the passed PartitionOp to this partition, performing its action.
383
398
// 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.
390
405
void apply (
391
406
PartitionOp op,
392
407
llvm::function_ref<void (const PartitionOp &, Element)> handleFailure =
393
408
[](const PartitionOp &, Element) {},
394
-
395
409
ArrayRef<Element> nonconsumables = {},
396
-
397
410
llvm::function_ref<void (const PartitionOp &, Element)>
398
411
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
+ };
399
420
switch (op.OpKind ) {
400
421
case PartitionOpKind::Assign:
401
422
assert (op.OpArgs .size () == 2 &&
402
423
" Assign PartitionOp should be passed 2 arguments" );
403
424
assert (labels.count (op.OpArgs [1 ]) &&
404
425
" Assign PartitionOp's source argument should be already tracked" );
405
426
// if assigning to a missing region, handle the failure
406
- if (isConsumed (op.OpArgs [1 ]))
427
+ if (isTransferred (op.OpArgs [1 ]))
407
428
handleFailure (op, op.OpArgs [1 ]);
408
429
409
430
labels.insert_or_assign (op.OpArgs [0 ], labels.at (op.OpArgs [1 ]));
@@ -429,25 +450,24 @@ class Partition {
429
450
assert (labels.count (op.OpArgs [0 ]) &&
430
451
" Consume PartitionOp's argument should already be tracked" );
431
452
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
433
455
for (Element nonconsumable : nonconsumables) {
434
456
assert (labels.count (nonconsumable) &&
435
457
" nonconsumables should be function args and self, and therefore"
436
458
" always present in the label map because of initialization at "
437
459
" entry" );
438
- if (!isConsumed (nonconsumable) &&
460
+ if (!isTransferred (nonconsumable) &&
439
461
labels.at (nonconsumable) == labels.at (op.OpArgs [0 ])) {
440
462
handleConsumeNonConsumable (op, nonconsumable);
441
463
break ;
442
464
}
443
465
}
444
466
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 ());
451
471
452
472
break ;
453
473
case PartitionOpKind::Merge:
@@ -456,10 +476,10 @@ class Partition {
456
476
assert (labels.count (op.OpArgs [0 ]) && labels.count (op.OpArgs [1 ]) &&
457
477
" Merge PartitionOp's arguments should already be tracked" );
458
478
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 ]))
461
481
handleFailure (op, op.OpArgs [0 ]);
462
- if (isConsumed (op.OpArgs [1 ]))
482
+ if (isTransferred (op.OpArgs [1 ]))
463
483
handleFailure (op, op.OpArgs [1 ]);
464
484
465
485
merge (op.OpArgs [0 ], op.OpArgs [1 ]);
@@ -469,26 +489,26 @@ class Partition {
469
489
" Require PartitionOp should be passed 1 argument" );
470
490
assert (labels.count (op.OpArgs [0 ]) &&
471
491
" Require PartitionOp's argument should already be tracked" );
472
- if (isConsumed (op.OpArgs [0 ]))
492
+ if (isTransferred (op.OpArgs [0 ]))
473
493
handleFailure (op, op.OpArgs [0 ]);
474
494
}
475
495
476
496
assert (is_canonical_correct ());
477
497
}
478
498
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 {
481
501
// for effeciency, this could return an iterator not a vector
482
- std::vector<Element> consumedVals ;
502
+ std::vector<Element> transferredVals ;
483
503
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 ;
487
507
}
488
508
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
490
510
// represented as a vector of values
491
- std::vector<std::vector<Element>> getNonConsumedRegions () const {
511
+ std::vector<std::vector<Element>> getNonTransferredRegions () const {
492
512
// for effeciency, this could return an iterator not a vector
493
513
std::map<Region, std::vector<Element>> buckets;
494
514
@@ -523,12 +543,12 @@ class Partition {
523
543
524
544
os << " [" ;
525
545
for (auto [label, indices] : buckets) {
526
- os << (label.isConsumed () ? " {" : " (" );
546
+ os << (label.isTransferred () ? " {" : " (" );
527
547
int j = 0 ;
528
548
for (Element i : indices) {
529
549
os << (j++ ? " " : " " ) << i;
530
550
}
531
- os << (label.isConsumed () ? " }" : " )" );
551
+ os << (label.isTransferred () ? " }" : " )" );
532
552
}
533
553
os << " ]\n " ;
534
554
}
0 commit comments