@@ -52,27 +52,33 @@ llvm::cl::opt<bool> EnableAccessMarkers(
52
52
53
53
namespace {
54
54
55
- struct AccessMarkerElimination : SILModuleTransform {
56
- virtual bool isFullElimination () = 0;
55
+ struct AccessMarkerElimination {
56
+ SILModule *Mod;
57
+ SILFunction *F;
58
+ bool isFullElimination;
57
59
58
60
bool removedAny = false ;
59
61
62
+ AccessMarkerElimination (SILFunction *F, bool isFullElimination)
63
+ : Mod(&F->getModule ()), F(F), isFullElimination(isFullElimination) {}
64
+
60
65
SILBasicBlock::iterator eraseInst (SILInstruction *inst) {
61
66
removedAny = true ;
62
67
return inst->getParent ()->erase (inst);
63
68
};
64
69
65
70
void replaceBeginAccessUsers (BeginAccessInst *beginAccess);
66
71
67
- // Precondition: !EnableAccessMarkers || isFullElimination()
72
+ // Precondition: !EnableAccessMarkers || isFullElimination
68
73
bool shouldPreserveAccess (SILAccessEnforcement enforcement);
69
74
70
75
// Check if the instruction is a marker that should be eliminated. If so,
71
76
// updated the SIL, short of erasing the marker itself, and return true.
72
77
bool checkAndEliminateMarker (SILInstruction *inst);
73
78
74
- // Entry point called by the pass manager.
75
- void run () override ;
79
+ // Entry point called either by the pass by the same name
80
+ // or as a utility (e.g. during deserialization).
81
+ bool stripMarkers ();
76
82
};
77
83
78
84
void AccessMarkerElimination::replaceBeginAccessUsers (
@@ -93,24 +99,24 @@ void AccessMarkerElimination::replaceBeginAccessUsers(
93
99
}
94
100
}
95
101
96
- // Precondition: !EnableAccessMarkers || isFullElimination()
102
+ // Precondition: !EnableAccessMarkers || isFullElimination
97
103
bool AccessMarkerElimination::shouldPreserveAccess (
98
104
SILAccessEnforcement enforcement) {
99
- if (isFullElimination () )
105
+ if (isFullElimination)
100
106
return false ;
101
107
102
- auto &M = *getModule ();
103
108
switch (enforcement) {
104
109
case SILAccessEnforcement::Unknown:
105
110
return false ;
106
111
case SILAccessEnforcement::Static:
107
112
// Even though static enforcement is already performed, this flag is
108
113
// useful to control marker preservation for now.
109
- return EnableAccessMarkers || M. getOptions ().EnforceExclusivityStatic ;
114
+ return EnableAccessMarkers || Mod-> getOptions ().EnforceExclusivityStatic ;
110
115
case SILAccessEnforcement::Dynamic:
111
116
// FIXME: when dynamic markers are fully supported, don't strip:
112
- // return EnableAccessMarkers || M.getOptions().EnforceExclusivityDynamic;
113
- return M.getOptions ().EnforceExclusivityDynamic ;
117
+ // return
118
+ // EnableAccessMarkers || Mod->getOptions().EnforceExclusivityDynamic;
119
+ return Mod->getOptions ().EnforceExclusivityDynamic ;
114
120
case SILAccessEnforcement::Unsafe:
115
121
return false ;
116
122
}
@@ -152,38 +158,64 @@ bool AccessMarkerElimination::checkAndEliminateMarker(SILInstruction *inst) {
152
158
return false ;
153
159
}
154
160
155
- void AccessMarkerElimination::run () {
161
+ // Top-level per-function entry-point.
162
+ // Return `true` if any markers were removed.
163
+ bool AccessMarkerElimination::stripMarkers () {
156
164
// FIXME: When dynamic markers are fully supported, just skip this pass:
157
- // if (EnableAccessMarkers && !isFullElimination())
158
- // return;
159
-
160
- auto &M = *getModule ();
161
- for (auto &F : M) {
162
- // Iterating in reverse eliminates more begin_access users before they
163
- // need to be replaced.
164
- for (auto &BB : reversed (F)) {
165
- // Don't cache the begin iterator since we're reverse iterating.
166
- for (auto II = BB.end (); II != BB.begin ();) {
167
- SILInstruction *inst = &*(--II);
168
- if (checkAndEliminateMarker (inst))
169
- II = eraseInst (inst);
170
- }
165
+ // if (EnableAccessMarkers && !isFullElimination)
166
+ // return false;
167
+
168
+ // Iterating in reverse eliminates more begin_access users before they
169
+ // need to be replaced.
170
+ for (auto &BB : reversed (*F)) {
171
+ // Don't cache the begin iterator since we're reverse iterating.
172
+ for (auto II = BB.end (); II != BB.begin ();) {
173
+ SILInstruction *inst = &*(--II);
174
+ if (checkAndEliminateMarker (inst))
175
+ II = eraseInst (inst);
171
176
}
177
+ }
178
+ return removedAny;
179
+ }
172
180
173
- // Don't invalidate any analyses if we didn't do anything.
174
- if (!removedAny)
175
- continue ;
181
+ } // end anonymous namespace
176
182
177
- auto InvalidKind = SILAnalysis::InvalidationKind::Instructions;
178
- invalidateAnalysis (&F, InvalidKind);
179
- }
183
+ // Implement a SILModule::SILFunctionBodyCallback that strips all access
184
+ // markers from newly deserialized function bodies.
185
+ static void prepareSILFunctionForOptimization (ModuleDecl *, SILFunction *F) {
186
+ AccessMarkerElimination (F, /* isFullElimination=*/ true ).stripMarkers ();
180
187
}
181
188
182
- struct InactiveAccessMarkerElimination : AccessMarkerElimination {
189
+ namespace {
190
+
191
+ struct AccessMarkerEliminationPass : SILModuleTransform {
192
+ virtual bool isFullElimination () = 0;
193
+
194
+ void run () override {
195
+ auto &M = *getModule ();
196
+ for (auto &F : M) {
197
+ bool removedAny = AccessMarkerElimination (&F, isFullElimination ())
198
+ .stripMarkers ();
199
+
200
+ // Only invalidate analyses if we removed some markers.
201
+ if (removedAny) {
202
+ auto InvalidKind = SILAnalysis::InvalidationKind::Instructions;
203
+ invalidateAnalysis (&F, InvalidKind);
204
+ }
205
+
206
+ // Markers from all current SIL functions are stripped. Register a
207
+ // callback to strip an subsequently loaded functions on-the-fly.
208
+ if (isFullElimination ())
209
+ M.registerDeserializationCallback (prepareSILFunctionForOptimization);
210
+ }
211
+ }
212
+ };
213
+
214
+ struct InactiveAccessMarkerElimination : AccessMarkerEliminationPass {
183
215
virtual bool isFullElimination () { return false ; }
184
216
};
185
217
186
- struct FullAccessMarkerElimination : AccessMarkerElimination {
218
+ struct FullAccessMarkerElimination : AccessMarkerEliminationPass {
187
219
virtual bool isFullElimination () { return true ; }
188
220
};
189
221
0 commit comments