Skip to content

Commit 24ae5d7

Browse files
committed
[Reachability] Added findBarriersBeforeInsts.
1 parent 2d52058 commit 24ae5d7

File tree

3 files changed

+144
-0
lines changed

3 files changed

+144
-0
lines changed

include/swift/SILOptimizer/Analysis/Reachability.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -888,6 +888,32 @@ void IterativeBackwardReachability<Effects>::Result::setEffectForBlock(
888888
}
889889
}
890890

891+
//===----------------------------------------------------------------------===//
892+
// MARK: findBarriersBeforeInstructions
893+
//===----------------------------------------------------------------------===//
894+
895+
using llvm::ArrayRef;
896+
using llvm::function_ref;
897+
898+
struct ReachableBarriers final {
899+
/// Instructions which are deinit barriers.
900+
llvm::SmallVector<SILInstruction *, 4> instructions;
901+
902+
/// Blocks one of whose phis is a deinit barrier.
903+
llvm::SmallVector<SILBasicBlock *, 4> phis;
904+
905+
llvm::SmallVector<SILBasicBlock *, 4> blocks;
906+
907+
ReachableBarriers() {}
908+
ReachableBarriers(ReachableBarriers const &) = delete;
909+
ReachableBarriers &operator=(ReachableBarriers const &) = delete;
910+
};
911+
912+
void findBarriersBeforeInstructions(
913+
ArrayRef<SILInstruction *> roots, SILBasicBlock *defBlock,
914+
SILFunction &function, ReachableBarriers &barriers,
915+
function_ref<bool(SILInstruction *)> isBarrier);
916+
891917
} // end namespace swift
892918

893919
#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: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
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+
namespace FindBarriersBeforeInstructions {
18+
19+
struct Context final {
20+
SILFunction &function;
21+
SILBasicBlock *defBlock;
22+
ArrayRef<SILInstruction *> roots;
23+
};
24+
25+
/// Walks backwards from the specified roots to find barrier instructions, phis,
26+
/// and blocks via the isBarrier predicate.
27+
///
28+
/// Implements IterativeBackwardReachability::Effects
29+
/// Implements IterativeBackwardReachability::findBarriers::Visitor
30+
class Dataflow final {
31+
using Reachability = IterativeBackwardReachability<Dataflow>;
32+
using Effect = Reachability::Effect;
33+
Context const &context;
34+
function_ref<bool(SILInstruction *)> isBarrier;
35+
ReachableBarriers &barriers;
36+
Reachability::Result result;
37+
Reachability reachability;
38+
39+
public:
40+
Dataflow(Context const &context, ReachableBarriers &barriers,
41+
function_ref<bool(SILInstruction *)> isBarrier)
42+
: context(context), isBarrier(isBarrier), barriers(barriers),
43+
result(&context.function),
44+
reachability(&context.function, nullptr, *this, result) {}
45+
Dataflow(Dataflow const &) = delete;
46+
Dataflow &operator=(Dataflow const &) = delete;
47+
48+
void run();
49+
50+
private:
51+
friend Reachability;
52+
53+
/// IterativeBackwardReachability::Effects
54+
55+
auto gens() { return context.roots; }
56+
57+
Effect effectForInstruction(SILInstruction *);
58+
Effect effectForPhi(SILBasicBlock *);
59+
60+
auto localGens() { return result.localGens; }
61+
62+
bool isLocalGen(SILInstruction *instruction) {
63+
return result.localGens.contains(instruction);
64+
}
65+
66+
/// IterativeBackwardReachability::findBarriers::Visitor
67+
68+
void visitBarrierInstruction(SILInstruction *instruction) {
69+
barriers.instructions.push_back(instruction);
70+
}
71+
72+
void visitBarrierPhi(SILBasicBlock *block) { barriers.phis.push_back(block); }
73+
74+
void visitBarrierBlock(SILBasicBlock *block) {
75+
barriers.blocks.push_back(block);
76+
}
77+
};
78+
79+
Dataflow::Effect Dataflow::effectForInstruction(SILInstruction *instruction) {
80+
if (llvm::is_contained(context.roots, instruction))
81+
return Effect::Gen();
82+
auto barrier = isBarrier(instruction);
83+
return barrier ? Effect::Kill() : Effect::NoEffect();
84+
}
85+
86+
Dataflow::Effect Dataflow::effectForPhi(SILBasicBlock *block) {
87+
assert(llvm::all_of(block->getArguments(),
88+
[&](auto argument) { return PhiValue(argument); }));
89+
90+
bool barrier =
91+
llvm::any_of(block->getPredecessorBlocks(), [&](auto *predecessor) {
92+
return isBarrier(predecessor->getTerminator());
93+
});
94+
return barrier ? Effect::Kill() : Effect::NoEffect();
95+
}
96+
97+
void Dataflow::run() {
98+
reachability.initialize();
99+
reachability.solve();
100+
reachability.findBarriers(*this);
101+
}
102+
103+
void run(Context &context, ReachableBarriers &barriers,
104+
function_ref<bool(SILInstruction *)> isBarrier) {
105+
Dataflow flow(context, barriers, isBarrier);
106+
flow.run();
107+
}
108+
109+
} // namespace FindBarriersBeforeInstructions
110+
111+
void swift::findBarriersBeforeInstructions(
112+
ArrayRef<SILInstruction *> roots, SILBasicBlock *defBlock,
113+
SILFunction &function, ReachableBarriers &barriers,
114+
function_ref<bool(SILInstruction *)> isBarrier) {
115+
FindBarriersBeforeInstructions::Context context = {function, defBlock, roots};
116+
return run(context, barriers, isBarrier);
117+
}

0 commit comments

Comments
 (0)