Skip to content

Commit d1ad768

Browse files
committed
[Reachability] Added findBarriersBackward.
1 parent c39b0e2 commit d1ad768

File tree

3 files changed

+145
-0
lines changed

3 files changed

+145
-0
lines changed

include/swift/SILOptimizer/Analysis/Reachability.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -903,6 +903,41 @@ void IterativeBackwardReachability<Effects>::Result::setEffectForBlock(
903903
}
904904
}
905905

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+
906941
} // end namespace swift
907942

908943
#endif

lib/SILOptimizer/Analysis/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ target_sources(swiftSILOptimizer PRIVATE
2222
NonLocalAccessBlockAnalysis.cpp
2323
PassManagerVerifierAnalysis.cpp
2424
ProtocolConformanceAnalysis.cpp
25+
Reachability.cpp
2526
RCIdentityAnalysis.cpp
2627
SimplifyInstruction.cpp
2728
TypeExpansionAnalysis.cpp
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
//=----------- Reachability.cpp - Walking from roots to barriers. -----------=//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2023 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#include "swift/SILOptimizer/Analysis/Reachability.h"
14+
15+
using namespace swift;
16+
17+
/// Walks backwards from the specified roots to find barrier instructions, phis,
18+
/// and blocks via the isBarrier predicate.
19+
///
20+
/// Implements IterativeBackwardReachability::Effects
21+
/// Implements IterativeBackwardReachability::findBarriers::Visitor
22+
class FindBarriersBackwardDataflow final {
23+
using Reachability =
24+
IterativeBackwardReachability<FindBarriersBackwardDataflow>;
25+
using Effect = Reachability::Effect;
26+
ArrayRef<SILInstruction *> const roots;
27+
function_ref<bool(SILInstruction *)> isBarrier;
28+
ReachableBarriers &barriers;
29+
Reachability::Result result;
30+
Reachability reachability;
31+
32+
public:
33+
FindBarriersBackwardDataflow(SILFunction &function,
34+
ArrayRef<SILInstruction *> roots,
35+
ArrayRef<SILBasicBlock *> stopBlocks,
36+
ReachableBarriers &barriers,
37+
function_ref<bool(SILInstruction *)> isBarrier)
38+
: roots(roots), isBarrier(isBarrier), barriers(barriers),
39+
result(&function), reachability(&function, stopBlocks, *this, result) {}
40+
FindBarriersBackwardDataflow(FindBarriersBackwardDataflow const &) = delete;
41+
FindBarriersBackwardDataflow &
42+
operator=(FindBarriersBackwardDataflow const &) = delete;
43+
44+
void run();
45+
46+
private:
47+
friend Reachability;
48+
49+
/// IterativeBackwardReachability::Effects
50+
51+
auto gens() { return roots; }
52+
53+
Effect effectForInstruction(SILInstruction *);
54+
Effect effectForPhi(SILBasicBlock *);
55+
56+
auto localGens() { return result.localGens; }
57+
58+
bool isLocalGen(SILInstruction *instruction) {
59+
return result.localGens.contains(instruction);
60+
}
61+
62+
/// IterativeBackwardReachability::findBarriers::Visitor
63+
64+
void visitBarrierInstruction(SILInstruction *instruction) {
65+
barriers.instructions.push_back(instruction);
66+
}
67+
68+
void visitBarrierPhi(SILBasicBlock *block) { barriers.phis.push_back(block); }
69+
70+
void visitBarrierBlock(SILBasicBlock *block) {
71+
barriers.edges.push_back(block);
72+
}
73+
};
74+
75+
FindBarriersBackwardDataflow::Effect
76+
FindBarriersBackwardDataflow::effectForInstruction(
77+
SILInstruction *instruction) {
78+
if (llvm::is_contained(roots, instruction))
79+
return Effect::Gen();
80+
auto barrier = isBarrier(instruction);
81+
return barrier ? Effect::Kill() : Effect::NoEffect();
82+
}
83+
84+
FindBarriersBackwardDataflow::Effect
85+
FindBarriersBackwardDataflow::effectForPhi(SILBasicBlock *block) {
86+
assert(llvm::all_of(block->getArguments(),
87+
[&](auto argument) { return PhiValue(argument); }));
88+
89+
bool barrier =
90+
llvm::any_of(block->getPredecessorBlocks(), [&](auto *predecessor) {
91+
return isBarrier(predecessor->getTerminator());
92+
});
93+
return barrier ? Effect::Kill() : Effect::NoEffect();
94+
}
95+
96+
void FindBarriersBackwardDataflow::run() {
97+
reachability.initialize();
98+
reachability.solve();
99+
reachability.findBarriers(*this);
100+
}
101+
102+
void swift::findBarriersBackward(
103+
ArrayRef<SILInstruction *> roots, ArrayRef<SILBasicBlock *> initialBlocks,
104+
SILFunction &function, ReachableBarriers &barriers,
105+
function_ref<bool(SILInstruction *)> isBarrier) {
106+
FindBarriersBackwardDataflow flow(function, roots, initialBlocks, barriers,
107+
isBarrier);
108+
flow.run();
109+
}

0 commit comments

Comments
 (0)