1212
1313#define DEBUG_TYPE " sil-semantic-arc-opts"
1414
15- #include " OwnershipLiveRange.h"
16- #include " OwnershipPhiOperand.h"
1715#include " SemanticARCOptVisitor.h"
1816#include " Transforms.h"
1917
20- #include " swift/Basic/LLVM.h"
21-
22- #include " swift/Basic/BlotSetVector.h"
23- #include " swift/Basic/FrozenMultiMap.h"
24- #include " swift/Basic/MultiMapCache.h"
25- #include " swift/Basic/STLExtras.h"
26- #include " swift/SIL/BasicBlockUtils.h"
27- #include " swift/SIL/DebugUtils.h"
28- #include " swift/SIL/LinearLifetimeChecker.h"
29- #include " swift/SIL/MemAccessUtils.h"
30- #include " swift/SIL/OwnershipUtils.h"
31- #include " swift/SIL/Projection.h"
32- #include " swift/SIL/SILArgument.h"
33- #include " swift/SIL/SILBuilder.h"
34- #include " swift/SIL/SILInstruction.h"
35- #include " swift/SIL/SILVisitor.h"
36- #include " swift/SILOptimizer/Analysis/PostOrderAnalysis.h"
37- #include " swift/SILOptimizer/PassManager/Passes.h"
3818#include " swift/SILOptimizer/PassManager/Transforms.h"
39- #include " swift/SILOptimizer/Utils/InstOptUtils.h"
40- #include " swift/SILOptimizer/Utils/ValueLifetime.h"
41- #include " llvm/ADT/SmallPtrSet.h"
42- #include " llvm/ADT/SmallVector.h"
43- #include " llvm/ADT/Statistic.h"
4419
4520using namespace swift ;
4621using namespace swift ::semanticarc;
4722
48- // ===----------------------------------------------------------------------===//
49- // Implementation
50- // ===----------------------------------------------------------------------===//
51-
52- bool SemanticARCOptVisitor::optimize () {
53- bool madeChange = false ;
54-
55- // First process the worklist until we reach a fixed point.
56- madeChange |= processWorklist ();
57-
58- {
59- // If we made a change, set that we assume we are at fixed point and then
60- // re-run the worklist so that we can
61- // properly seeded the ARC peephole map.
62- ctx.assumingAtFixedPoint = true ;
63- SWIFT_DEFER { ctx.assumingAtFixedPoint = false ; };
64-
65- // Add everything in visitedSinceLastMutation to the worklist so we
66- // recompute our fixed point.
67- drainVisitedSinceLastMutationIntoWorklist ();
68-
69- // Then re-run the worklist. We shouldn't modify anything since we are at a
70- // fixed point and are just using this to seed the
71- // joinedOwnedIntroducerToConsumedOperands after we have finished changing
72- // things. If we did change something, we did something weird, so assert!
73- bool madeAdditionalChanges = processWorklist ();
74- (void )madeAdditionalChanges;
75- assert (!madeAdditionalChanges && " Should be at the fixed point" );
76- }
77-
78- return madeChange;
79- }
80-
81- bool SemanticARCOptVisitor::processWorklist () {
82- // NOTE: The madeChange here is not strictly necessary since we only have
83- // items added to the worklist today if we have already made /some/ sort of
84- // change. That being said, I think there is a low cost to including this here
85- // and makes the algorithm more correct, visually and in the face of potential
86- // refactoring.
87- bool madeChange = false ;
88-
89- while (!worklist.empty ()) {
90- // Pop the last element off the list. If we were returned None, we blotted
91- // this element, so skip it.
92- SILValue next = worklist.pop_back_val ().getValueOr (SILValue ());
93- if (!next)
94- continue ;
95-
96- // First check if this is a value that we have visited since the last time
97- // we erased an instruction. If we have visited it, skip it. Every time we
98- // modify something, we should be deleting an instruction, so we have not
99- // found any further information.
100- if (!visitedSinceLastMutation.insert (next).second ) {
101- continue ;
102- }
103-
104- // First check if this is an instruction that is trivially dead. This can
105- // occur if we eliminate rr traffic resulting in dead projections and the
106- // like.
107- //
108- // If we delete, we first add all of our deleted instructions operands to
109- // the worklist and then remove all results (since we are going to delete
110- // the instruction).
111- if (auto *defInst = next->getDefiningInstruction ()) {
112- if (isInstructionTriviallyDead (defInst)) {
113- assert (!ctx.assumingAtFixedPoint &&
114- " Assumed was at fixed point and recomputing state?!" );
115- deleteAllDebugUses (defInst);
116- eraseInstruction (defInst);
117- madeChange = true ;
118- ctx.verify ();
119- continue ;
120- }
121- }
122-
123- // Otherwise, if we have a single value instruction (to be expanded later
124- // perhaps), try to visit that value recursively.
125- if (auto *svi = dyn_cast<SingleValueInstruction>(next)) {
126- bool madeSingleChange = visit (svi);
127- assert ((!madeSingleChange || !ctx.assumingAtFixedPoint ) &&
128- " Assumed was at fixed point and modified state?!" );
129- madeChange |= madeSingleChange;
130- if (madeSingleChange) {
131- ctx.verify ();
132- }
133- continue ;
134- }
135- }
136-
137- return madeChange;
138- }
139-
14023// ===----------------------------------------------------------------------===//
14124// Top Level Entrypoint
14225// ===----------------------------------------------------------------------===//
@@ -179,7 +62,7 @@ struct SemanticARCOpts : SILFunctionTransform {
17962 }
18063
18164 // Then process the worklist, performing peepholes.
182- bool madeChange = visitor.optimize ();
65+ bool eliminatedARCInst = visitor.optimize ();
18366
18467 // Now that we have seeded the map of phis to incoming values that could be
18568 // converted to guaranteed, ignoring the phi, try convert those phis to be
@@ -191,7 +74,7 @@ struct SemanticARCOpts : SILFunctionTransform {
19174 }
19275
19376 // Otherwise, we only deleted instructions and did not touch phis.
194- if (madeChange )
77+ if (eliminatedARCInst )
19578 invalidateAnalysis (SILAnalysis::InvalidationKind::Instructions);
19679 }
19780};
0 commit comments