@@ -81,7 +81,22 @@ class PartitionOp {
81
81
return PartitionOp (PartitionOpKind::Require, tgt, sourceInst);
82
82
}
83
83
84
- SILInstruction *getSourceInst () const {
84
+ bool operator ==(const PartitionOp& other) const = default ;
85
+ // implemented for insertion into std::map
86
+ bool operator <(const PartitionOp& other) const {
87
+ if (OpKind != other.OpKind )
88
+ return OpKind < other.OpKind ;
89
+ return sourceInst < other.sourceInst ;
90
+ }
91
+
92
+ PartitionOpKind getKind () const {
93
+ return OpKind;
94
+ }
95
+
96
+ SILInstruction *getSourceInst (bool assertNonNull = false ) const {
97
+ assert (!assertNonNull || sourceInst
98
+ && " PartitionOps should be assigned SILInstruction"
99
+ " sources when used for the core analysis" );
85
100
return sourceInst;
86
101
}
87
102
@@ -196,7 +211,7 @@ class Partition {
196
211
return ;
197
212
canonical = true ;
198
213
199
- std::map<signed , unsigned > relabel;
214
+ std::map<unsigned , unsigned > relabel;
200
215
201
216
// relies on in-order traversal of labels
202
217
for (auto &[i, label] : labels) {
@@ -268,6 +283,14 @@ class Partition {
268
283
return fst.labels == snd.labels ;
269
284
}
270
285
286
+ bool isTracked (unsigned val) const {
287
+ return labels.count (val);
288
+ }
289
+
290
+ bool isConsumed (unsigned val) const {
291
+ return isTracked (val) && labels.at (val) < 0 ;
292
+ }
293
+
271
294
// quadratic time - Construct the partition corresponding to the join of the
272
295
// two passed partitions; the join labels each index labelled by both operands
273
296
// and two indices are in the same region of the join iff they are in the same
@@ -320,25 +343,17 @@ class Partition {
320
343
nonconsumables = {},
321
344
322
345
llvm::function_ref<void (const PartitionOp&, unsigned )>
323
- handleConsumeNonConsumable = [](const PartitionOp&, unsigned ) {},
324
-
325
- bool reviveAfterFailure = false
346
+ handleConsumeNonConsumable = [](const PartitionOp&, unsigned ) {}
326
347
) {
327
- auto handleFailureAndRevive =
328
- [&](const PartitionOp& partitionOp, unsigned consumedVal) {
329
- if (reviveAfterFailure)
330
- horizontalUpdate (labels, consumedVal, fresh_label++);
331
- handleFailure (partitionOp, consumedVal);
332
- };
333
348
switch (op.OpKind ) {
334
349
case PartitionOpKind::Assign:
335
350
assert (op.OpArgs .size () == 2 &&
336
351
" Assign PartitionOp should be passed 2 arguments" );
337
352
assert (labels.count (op.OpArgs [1 ]) &&
338
353
" Assign PartitionOp's source argument should be already tracked" );
339
354
// if assigning to a missing region, handle the failure
340
- if (labels[ op.OpArgs [1 ]] < 0 )
341
- handleFailureAndRevive (op, op.OpArgs [1 ]);
355
+ if (isConsumed ( op.OpArgs [1 ]) )
356
+ handleFailure (op, op.OpArgs [1 ]);
342
357
343
358
labels[op.OpArgs [0 ]] = labels[op.OpArgs [1 ]];
344
359
@@ -361,8 +376,8 @@ class Partition {
361
376
" Consume PartitionOp's argument should already be tracked" );
362
377
363
378
// if attempting to consume a consumed region, handle the failure
364
- if (labels[ op.OpArgs [0 ]] < 0 )
365
- handleFailureAndRevive (op, op.OpArgs [0 ]);
379
+ if (isConsumed ( op.OpArgs [0 ]) )
380
+ handleFailure (op, op.OpArgs [0 ]);
366
381
367
382
// mark region as consumed
368
383
horizontalUpdate (labels, op.OpArgs [0 ], -1 );
@@ -387,10 +402,10 @@ class Partition {
387
402
" Merge PartitionOp's arguments should already be tracked" );
388
403
389
404
// if attempting to merge a consumed region, handle the failure
390
- if (labels[ op.OpArgs [0 ]] < 0 )
391
- handleFailureAndRevive (op, op.OpArgs [0 ]);
392
- if (labels[ op.OpArgs [1 ]] < 0 )
393
- handleFailureAndRevive (op, op.OpArgs [1 ]);
405
+ if (isConsumed ( op.OpArgs [0 ]) )
406
+ handleFailure (op, op.OpArgs [0 ]);
407
+ if (isConsumed ( op.OpArgs [1 ]) )
408
+ handleFailure (op, op.OpArgs [1 ]);
394
409
395
410
merge (op.OpArgs [0 ], op.OpArgs [1 ]);
396
411
break ;
@@ -399,13 +414,40 @@ class Partition {
399
414
" Require PartitionOp should be passed 1 argument" );
400
415
assert (labels.count (op.OpArgs [0 ]) &&
401
416
" Require PartitionOp's argument should already be tracked" );
402
- if (labels[ op.OpArgs [0 ]] < 0 )
403
- handleFailureAndRevive (op, op.OpArgs [0 ]);
417
+ if (isConsumed ( op.OpArgs [0 ]) )
418
+ handleFailure (op, op.OpArgs [0 ]);
404
419
}
405
420
406
421
assert (is_canonical_correct ());
407
422
}
408
423
424
+ // return a vector of the consumed values in this partition
425
+ std::vector<unsigned > getConsumedVals () const {
426
+ // for effeciency, this could return an iterator not a vector
427
+ std::vector<unsigned > consumedVals;
428
+ for (auto [i, _] : labels)
429
+ if (isConsumed (i))
430
+ consumedVals.push_back (i);
431
+ return consumedVals;
432
+ }
433
+
434
+ // return a vector of the non-consumed regions in this partition, each
435
+ // represented as a vector of values
436
+ std::vector<std::vector<unsigned >> getNonConsumedRegions () const {
437
+ // for effeciency, this could return an iterator not a vector
438
+ std::map<signed , std::vector<unsigned >> buckets;
439
+
440
+ for (auto [i, label] : labels)
441
+ buckets[label].push_back (i);
442
+
443
+ std::vector<std::vector<unsigned >> doubleVec;
444
+
445
+ for (auto [_, bucket] : buckets)
446
+ doubleVec.push_back (bucket);
447
+
448
+ return doubleVec;
449
+ }
450
+
409
451
void dump_labels () const LLVM_ATTRIBUTE_USED {
410
452
llvm::dbgs () << " Partition" ;
411
453
if (canonical)
@@ -419,9 +461,8 @@ class Partition {
419
461
void dump () LLVM_ATTRIBUTE_USED {
420
462
std::map<signed , std::vector<unsigned >> buckets;
421
463
422
- for (auto [i, label] : labels) {
464
+ for (auto [i, label] : labels)
423
465
buckets[label].push_back (i);
424
- }
425
466
426
467
llvm::dbgs () << " [" ;
427
468
for (auto [label, indices] : buckets) {
@@ -432,9 +473,9 @@ class Partition {
432
473
}
433
474
llvm::dbgs () << (label < 0 ? " }" : " )" );
434
475
}
435
- llvm::dbgs () << " ]" ;
476
+ llvm::dbgs () << " ]\n " ;
436
477
}
437
478
};
438
479
}
439
480
440
- #endif
481
+ #endif // SWIFT_PARTITIONUTILS_H
0 commit comments