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