@@ -133,27 +133,6 @@ struct FunctionOptimizer : public WalkerPass<PostWalker<FunctionOptimizer>> {
133
133
return PossibleConstantValues{};
134
134
}
135
135
136
- // Returns a block dropping the `ref` operand of the argument.
137
- template <typename T> Block* makeRefDroppingBlock (T* curr) {
138
- Builder builder (*getModule ());
139
- return builder.blockify (
140
- builder.makeDrop (builder.makeRefAs (RefAsNonNull, curr->ref )));
141
- }
142
-
143
- // If an optimized access is sequentially consistent, then it synchronizes
144
- // with other threads at least by participating in the global order of
145
- // sequentially consistent operations. Preserve that effect by replacing the
146
- // access with a fence. On the other hand, if we're optimizing an
147
- // acquire-release operation, then we know the accessed field is constant and
148
- // will not be modified, so the operation does not necessarily synchronize
149
- // with other threads and no fence is required.
150
- Block* maybeAddFence (Block* block, MemoryOrder order) {
151
- if (order == MemoryOrder::SeqCst) {
152
- block->list .push_back (Builder (*getModule ()).makeAtomicFence ());
153
- }
154
- return block;
155
- }
156
-
157
136
// Given information about a constant value, and the struct type and
158
137
// StructGet/RMW/Cmpxchg that reads it, create an expression for that value.
159
138
template <typename T>
@@ -216,6 +195,16 @@ struct FunctionOptimizer : public WalkerPass<PostWalker<FunctionOptimizer>> {
216
195
return ;
217
196
}
218
197
198
+ if (curr->order != MemoryOrder::Unordered) {
199
+ // The analysis we're basing the optimization on is not precise enough to
200
+ // rule out the field being used to synchronize between a write of the
201
+ // constant value and a subsequent read on another thread. This
202
+ // synchronization is possible even when the write does not change the
203
+ // value of the field. For now, simply avoid optimizing this case.
204
+ // TODO: Track release and acquire operations in the analysis.
205
+ return ;
206
+ }
207
+
219
208
// If the value is not a constant, then it is unknown and we must give up
220
209
// on simply applying a constant. However, we can try to use a ref.test, if
221
210
// that is allowed.
@@ -231,69 +220,8 @@ struct FunctionOptimizer : public WalkerPass<PostWalker<FunctionOptimizer>> {
231
220
// constant value. (Leave it to further optimizations to get rid of the
232
221
// ref.)
233
222
auto * value = makeExpression (info, heapType, curr);
234
- auto * replacement = makeRefDroppingBlock (curr);
235
- replacement = maybeAddFence (replacement, curr->order );
236
- replacement->list .push_back (value);
237
- replacement->type = value->type ;
238
- replaceCurrent (replacement);
239
- changed = true ;
240
- }
241
-
242
- template <typename T>
243
- std::optional<std::pair<HeapType, PossibleConstantValues>>
244
- shouldOptimizeRMW (T* curr) {
245
- auto type = getRelevantHeapType (curr);
246
- if (!type) {
247
- return std::nullopt;
248
- }
249
- auto heapType = *type;
250
-
251
- // Get the info about the field. Since RMWs can only copy or mutate the
252
- // value, we always have something recorded.
253
- PossibleConstantValues info = getInfo (heapType, curr->index );
254
- assert (info.hasNoted () && " unexpected lack of info for RMW" );
255
-
256
- if (!info.isConstant ()) {
257
- // Optimizing using ref.test is not an option here because that only works
258
- // on immutable fields, but RMW operations always access mutable fields.
259
- return std::nullopt;
260
- }
261
-
262
- // We can optimize.
263
- return std::pair (heapType, info);
264
- }
265
-
266
- void visitStructRMW (StructRMW* curr) {
267
- auto typeAndInfo = shouldOptimizeRMW (curr);
268
- if (!typeAndInfo) {
269
- return ;
270
- }
271
- // Only xchg allows the field to have a constant value.
272
- assert (curr->op == RMWXchg && " unexpected op" );
273
- auto & [type, info] = *typeAndInfo;
274
- Builder builder (*getModule ());
275
- auto * value = makeExpression (info, type, curr);
276
- auto * replacement = makeRefDroppingBlock (curr);
277
- replacement->list .push_back (builder.makeDrop (curr->value ));
278
- replacement = maybeAddFence (replacement, curr->order );
279
- replacement->list .push_back (value);
280
- replacement->type = value->type ;
281
- replaceCurrent (replacement);
282
- changed = true ;
283
- }
284
-
285
- void visitStructCmpxchg (StructCmpxchg* curr) {
286
- auto typeAndInfo = shouldOptimizeRMW (curr);
287
- if (!typeAndInfo) {
288
- return ;
289
- }
290
- auto & [type, info] = *typeAndInfo;
291
- Builder builder (*getModule ());
292
- auto * value = makeExpression (info, type, curr);
293
- auto * replacement = makeRefDroppingBlock (curr);
294
- replacement->list .push_back (builder.makeDrop (curr->expected ));
295
- replacement->list .push_back (builder.makeDrop (curr->replacement ));
296
- replacement = maybeAddFence (replacement, curr->order );
223
+ auto * replacement = builder.blockify (
224
+ builder.makeDrop (builder.makeRefAs (RefAsNonNull, curr->ref )));
297
225
replacement->list .push_back (value);
298
226
replacement->type = value->type ;
299
227
replaceCurrent (replacement);
0 commit comments