@@ -243,7 +243,7 @@ class IterativeBackwardReachability final {
243
243
BasicBlockSet unknownEndBlocks;
244
244
245
245
public:
246
- // / The blocks found between the gens and the defBlock into which
246
+ // / The blocks found between the gens and the initialBlocks into which
247
247
// / reachability may extend.
248
248
BasicBlockSetVector discoveredBlocks;
249
249
// / The sublist of gens which are killed within the blocks where they occur.
@@ -296,15 +296,32 @@ class IterativeBackwardReachability final {
296
296
};
297
297
298
298
// / Construct a dataflow for the specified function to run from the gens
299
- // / provided by \p effects to the specified def block. So that the result
300
- // / structure can be owned by the caller, it is taken by reference here.
299
+ // / provided by \p effects to the specified \p initialBlocks. So that the
300
+ // / result structure can be owned by the caller, it is taken by reference
301
+ // / here.
301
302
// /
302
- // / If a nullptr defBlock is specified, the dataflow may run up to the begin
303
- // / of the function.
304
- IterativeBackwardReachability (SILFunction *function, SILBasicBlock *defBlock,
303
+ // / If \p initialBlocks is empty, the dataflow may run up to the begin of the
304
+ // / function.
305
+ IterativeBackwardReachability (SILFunction *function,
306
+ ArrayRef<SILBasicBlock *> initialBlocks,
305
307
Effects &effects, Result &result)
306
- : function(function), defBlock(defBlock), effects(effects),
307
- result(result), dataflowWorklist(function) {}
308
+ : function(function), initialBlocks(function), effects(effects),
309
+ result(result), dataflowWorklist(function) {
310
+ for (auto *block : initialBlocks) {
311
+ this ->initialBlocks .insert (block);
312
+ }
313
+ }
314
+
315
+ // / Convenience constructor to pass a single initial block.
316
+ static IterativeBackwardReachability
317
+ untilInitialBlock (SILFunction *function, SILBasicBlock *initialBlock,
318
+ Effects &effects, Result &result) {
319
+ using InitialBlocks = ArrayRef<SILBasicBlock *>;
320
+ InitialBlocks initialBlocks =
321
+ initialBlock ? InitialBlocks (initialBlock) : InitialBlocks ();
322
+ return IterativeBackwardReachability (function, initialBlocks, effects,
323
+ result);
324
+ }
308
325
309
326
// / Step 1: Prepare to run the global dataflow: discover and summarize the
310
327
// / blocks in the relevant region.
@@ -358,9 +375,8 @@ class IterativeBackwardReachability final {
358
375
359
376
// / The function in which the dataflow will run.
360
377
SILFunction *function;
361
- // / The block containing the def for the value--the dataflow will not
362
- // / propagate beyond this block.
363
- SILBasicBlock *defBlock;
378
+ // / The blocks beyond which the dataflow will not propagate.
379
+ BasicBlockSet initialBlocks;
364
380
365
381
// / Input to the dataflow.
366
382
Effects &effects;
@@ -375,9 +391,9 @@ class IterativeBackwardReachability final {
375
391
// / Current activity of the dataflow.
376
392
Stage stage = Stage::Unstarted;
377
393
378
- // / Whether the def effectively occurs within the specified block.
379
- bool isEffectiveDefBlock (SILBasicBlock *block) {
380
- return defBlock ? block == defBlock : block == &*function->begin ();
394
+ // / Whether dataflow continues beyond this block.
395
+ bool stopAtBlock (SILBasicBlock *block) {
396
+ return initialBlocks. contains ( block) || &*function->begin () == block ;
381
397
}
382
398
383
399
// / Form the meet of the end state of the provided predecessor with the begin
@@ -424,8 +440,8 @@ class IterativeBackwardReachability final {
424
440
// / effect of each block for use by the dataflow.
425
441
// /
426
442
// / Starting from the gens, find all blocks which might be reached up to and
427
- // / including the defBlock . Summarize the effects of these blocks along the
428
- // / way.
443
+ // / including the initialBlocks . Summarize the effects of these blocks along
444
+ // / the way.
429
445
template <typename Effects>
430
446
void IterativeBackwardReachability<Effects>::initialize() {
431
447
assert (stage == Stage::Unstarted);
@@ -454,9 +470,9 @@ void IterativeBackwardReachability<Effects>::initialize() {
454
470
// adjacent successors.
455
471
continue ;
456
472
}
457
- if (isEffectiveDefBlock (block)) {
458
- // If this block is the effective def block, dataflow mustn't propagate
459
- // a reachable state through this block to its predecessors.
473
+ if (stopAtBlock (block)) {
474
+ // If dataflow is to stop at this block, it mustn't propagate a reachable
475
+ // state through this block to its predecessors.
460
476
continue ;
461
477
}
462
478
for (auto *predecessor : block->getPredecessorBlocks ())
@@ -631,9 +647,9 @@ void IterativeBackwardReachability<Effects>::solve() {
631
647
template <typename Effects>
632
648
void IterativeBackwardReachability<Effects>::propagateIntoPredecessors(
633
649
SILBasicBlock *successor) {
634
- // State isn't tracked above the def block . Don't propagate state changes
635
- // into its predecessors.
636
- if (isEffectiveDefBlock (successor))
650
+ // State isn't tracked above the blocks dataflow stops at . Don't propagate
651
+ // state changes into its predecessors.
652
+ if (stopAtBlock (successor))
637
653
return ;
638
654
assert (result.getBeginStateForBlock (successor) == State::Unreachable () &&
639
655
" propagating unreachability into predecessors of block whose begin is "
@@ -761,7 +777,6 @@ bool IterativeBackwardReachability<Effects>::findBarrier(SILInstruction *from,
761
777
if (!effect)
762
778
continue ;
763
779
if (effect == Effect::Gen ()) {
764
- assert (false && " found gen (before kill) in reachable block" );
765
780
continue ;
766
781
}
767
782
// effect == Effect::Kill
@@ -777,7 +792,7 @@ bool IterativeBackwardReachability<Effects>::findBarrier(SILInstruction *from,
777
792
}
778
793
}
779
794
assert (result.getEffectForBlock (block) != Effect::Kill ());
780
- if (isEffectiveDefBlock (block)) {
795
+ if (stopAtBlock (block)) {
781
796
visitor.visitBarrierBlock (block);
782
797
return true ;
783
798
}
@@ -888,6 +903,41 @@ void IterativeBackwardReachability<Effects>::Result::setEffectForBlock(
888
903
}
889
904
}
890
905
906
+ // ===----------------------------------------------------------------------===//
907
+ // MARK: findBarriersBackward
908
+ // ===----------------------------------------------------------------------===//
909
+
910
+ using llvm::ArrayRef;
911
+ using llvm::function_ref;
912
+
913
+ struct ReachableBarriers final {
914
+ // / Instructions which are barriers.
915
+ llvm::SmallVector<SILInstruction *, 4 > instructions;
916
+
917
+ // / Blocks one of whose phis is a barrier.
918
+ llvm::SmallVector<SILBasicBlock *, 4 > phis;
919
+
920
+ // / Boundary edges; edges such that
921
+ // / (1) the target block is reachable-at-begin
922
+ // / (2) at least one adjacent edge's target is not reachable-at-begin.
923
+ llvm::SmallVector<SILBasicBlock *, 4 > edges;
924
+
925
+ ReachableBarriers () {}
926
+ ReachableBarriers (ReachableBarriers const &) = delete ;
927
+ ReachableBarriers &operator =(ReachableBarriers const &) = delete ;
928
+ };
929
+
930
+ // / Walk backwards from the specified \p roots through at the earliest \p
931
+ // / initialBlocks to populate \p barriers by querying \p isBarrier along the
932
+ // / way.
933
+ // /
934
+ // / If \p initialBlocks is empty, dataflow continues to the begin of the
935
+ // / function.
936
+ void findBarriersBackward (ArrayRef<SILInstruction *> roots,
937
+ ArrayRef<SILBasicBlock *> initialBlocks,
938
+ SILFunction &function, ReachableBarriers &barriers,
939
+ function_ref<bool (SILInstruction *)> isBarrier);
940
+
891
941
} // end namespace swift
892
942
893
943
#endif
0 commit comments