Skip to content

Commit 895a8a5

Browse files
committed
[Reachability] Added findBarriersBeforeInsts.
1 parent c39b0e2 commit 895a8a5

File tree

3 files changed

+141
-0
lines changed

3 files changed

+141
-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: findBarriersBackwards
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 findBarriersBackwards(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: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
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 FindBarriersDataflow final {
23+
using Reachability = IterativeBackwardReachability<FindBarriersDataflow>;
24+
using Effect = Reachability::Effect;
25+
ArrayRef<SILInstruction *> const roots;
26+
function_ref<bool(SILInstruction *)> isBarrier;
27+
ReachableBarriers &barriers;
28+
Reachability::Result result;
29+
Reachability reachability;
30+
31+
public:
32+
FindBarriersDataflow(SILFunction &function, ArrayRef<SILInstruction *> roots,
33+
ArrayRef<SILBasicBlock *> stopBlocks,
34+
ReachableBarriers &barriers,
35+
function_ref<bool(SILInstruction *)> isBarrier)
36+
: roots(roots), isBarrier(isBarrier), barriers(barriers),
37+
result(&function), reachability(&function, stopBlocks, *this, result) {}
38+
FindBarriersDataflow(FindBarriersDataflow const &) = delete;
39+
FindBarriersDataflow &operator=(FindBarriersDataflow const &) = delete;
40+
41+
void run();
42+
43+
private:
44+
friend Reachability;
45+
46+
/// IterativeBackwardReachability::Effects
47+
48+
auto gens() { return roots; }
49+
50+
Effect effectForInstruction(SILInstruction *);
51+
Effect effectForPhi(SILBasicBlock *);
52+
53+
auto localGens() { return result.localGens; }
54+
55+
bool isLocalGen(SILInstruction *instruction) {
56+
return result.localGens.contains(instruction);
57+
}
58+
59+
/// IterativeBackwardReachability::findBarriers::Visitor
60+
61+
void visitBarrierInstruction(SILInstruction *instruction) {
62+
barriers.instructions.push_back(instruction);
63+
}
64+
65+
void visitBarrierPhi(SILBasicBlock *block) { barriers.phis.push_back(block); }
66+
67+
void visitBarrierBlock(SILBasicBlock *block) {
68+
barriers.edges.push_back(block);
69+
}
70+
};
71+
72+
FindBarriersDataflow::Effect
73+
FindBarriersDataflow::effectForInstruction(SILInstruction *instruction) {
74+
if (llvm::is_contained(roots, instruction))
75+
return Effect::Gen();
76+
auto barrier = isBarrier(instruction);
77+
return barrier ? Effect::Kill() : Effect::NoEffect();
78+
}
79+
80+
FindBarriersDataflow::Effect
81+
FindBarriersDataflow::effectForPhi(SILBasicBlock *block) {
82+
assert(llvm::all_of(block->getArguments(),
83+
[&](auto argument) { return PhiValue(argument); }));
84+
85+
bool barrier =
86+
llvm::any_of(block->getPredecessorBlocks(), [&](auto *predecessor) {
87+
return isBarrier(predecessor->getTerminator());
88+
});
89+
return barrier ? Effect::Kill() : Effect::NoEffect();
90+
}
91+
92+
void FindBarriersDataflow::run() {
93+
reachability.initialize();
94+
reachability.solve();
95+
reachability.findBarriers(*this);
96+
}
97+
98+
void swift::findBarriersBackwards(
99+
ArrayRef<SILInstruction *> roots, ArrayRef<SILBasicBlock *> initialBlocks,
100+
SILFunction &function, ReachableBarriers &barriers,
101+
function_ref<bool(SILInstruction *)> isBarrier) {
102+
FindBarriersDataflow flow(function, roots, initialBlocks, barriers,
103+
isBarrier);
104+
flow.run();
105+
}

0 commit comments

Comments
 (0)