@@ -243,7 +243,7 @@ class IterativeBackwardReachability final {
243243 BasicBlockSet unknownEndBlocks;
244244
245245 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
247247 // / reachability may extend.
248248 BasicBlockSetVector discoveredBlocks;
249249 // / The sublist of gens which are killed within the blocks where they occur.
@@ -296,15 +296,32 @@ class IterativeBackwardReachability final {
296296 };
297297
298298 // / 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.
301302 // /
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,
305307 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+ }
308325
309326 // / Step 1: Prepare to run the global dataflow: discover and summarize the
310327 // / blocks in the relevant region.
@@ -358,9 +375,8 @@ class IterativeBackwardReachability final {
358375
359376 // / The function in which the dataflow will run.
360377 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;
364380
365381 // / Input to the dataflow.
366382 Effects &effects;
@@ -375,9 +391,9 @@ class IterativeBackwardReachability final {
375391 // / Current activity of the dataflow.
376392 Stage stage = Stage::Unstarted;
377393
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 ;
381397 }
382398
383399 // / Form the meet of the end state of the provided predecessor with the begin
@@ -424,8 +440,8 @@ class IterativeBackwardReachability final {
424440// / effect of each block for use by the dataflow.
425441// /
426442// / 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.
429445template <typename Effects>
430446void IterativeBackwardReachability<Effects>::initialize() {
431447 assert (stage == Stage::Unstarted);
@@ -454,9 +470,9 @@ void IterativeBackwardReachability<Effects>::initialize() {
454470 // adjacent successors.
455471 continue ;
456472 }
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.
460476 continue ;
461477 }
462478 for (auto *predecessor : block->getPredecessorBlocks ())
@@ -631,9 +647,9 @@ void IterativeBackwardReachability<Effects>::solve() {
631647template <typename Effects>
632648void IterativeBackwardReachability<Effects>::propagateIntoPredecessors(
633649 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))
637653 return ;
638654 assert (result.getBeginStateForBlock (successor) == State::Unreachable () &&
639655 " propagating unreachability into predecessors of block whose begin is "
@@ -761,7 +777,6 @@ bool IterativeBackwardReachability<Effects>::findBarrier(SILInstruction *from,
761777 if (!effect)
762778 continue ;
763779 if (effect == Effect::Gen ()) {
764- assert (false && " found gen (before kill) in reachable block" );
765780 continue ;
766781 }
767782 // effect == Effect::Kill
@@ -777,7 +792,7 @@ bool IterativeBackwardReachability<Effects>::findBarrier(SILInstruction *from,
777792 }
778793 }
779794 assert (result.getEffectForBlock (block) != Effect::Kill ());
780- if (isEffectiveDefBlock (block)) {
795+ if (stopAtBlock (block)) {
781796 visitor.visitBarrierBlock (block);
782797 return true ;
783798 }
@@ -888,6 +903,41 @@ void IterativeBackwardReachability<Effects>::Result::setEffectForBlock(
888903 }
889904}
890905
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+
891941} // end namespace swift
892942
893943#endif
0 commit comments