8
8
9
9
#include " mlir/Interfaces/SideEffectInterfaces.h"
10
10
11
+ #include " mlir/IR/Dominance.h"
11
12
#include " mlir/IR/SymbolTable.h"
12
13
#include " llvm/ADT/SmallPtrSet.h"
13
14
#include < unordered_set>
@@ -27,7 +28,7 @@ using namespace mlir;
27
28
// ===----------------------------------------------------------------------===//
28
29
29
30
bool MemoryEffects::Effect::classof (const SideEffects::Effect *effect) {
30
- return isa<Allocate, Free, Read, Write, Init >(effect);
31
+ return isa<Allocate, Free, Read, Write>(effect);
31
32
}
32
33
33
34
// ===----------------------------------------------------------------------===//
@@ -132,7 +133,6 @@ template bool mlir::hasSingleEffect<MemoryEffects::Allocate>(Operation *);
132
133
template bool mlir::hasSingleEffect<MemoryEffects::Free>(Operation *);
133
134
template bool mlir::hasSingleEffect<MemoryEffects::Read>(Operation *);
134
135
template bool mlir::hasSingleEffect<MemoryEffects::Write>(Operation *);
135
- template bool mlir::hasSingleEffect<MemoryEffects::Init>(Operation *);
136
136
137
137
template <typename EffectTy>
138
138
bool mlir::hasSingleEffect (Operation *op, Value value) {
@@ -162,8 +162,6 @@ template bool mlir::hasSingleEffect<MemoryEffects::Read>(Operation *,
162
162
Value value);
163
163
template bool mlir::hasSingleEffect<MemoryEffects::Write>(Operation *,
164
164
Value value);
165
- template bool mlir::hasSingleEffect<MemoryEffects::Init>(Operation *,
166
- Value value);
167
165
168
166
template <typename ValueTy, typename EffectTy>
169
167
bool mlir::hasSingleEffect (Operation *op, ValueTy value) {
@@ -198,18 +196,13 @@ template bool
198
196
mlir::hasSingleEffect<OpOperand *, MemoryEffects::Write>(Operation *,
199
197
OpOperand *);
200
198
template bool
201
- mlir::hasSingleEffect<OpOperand *, MemoryEffects::Init>(Operation *,
202
- OpOperand *);
203
- template bool
204
199
mlir::hasSingleEffect<OpResult, MemoryEffects::Allocate>(Operation *, OpResult);
205
200
template bool mlir::hasSingleEffect<OpResult, MemoryEffects::Free>(Operation *,
206
201
OpResult);
207
202
template bool mlir::hasSingleEffect<OpResult, MemoryEffects::Read>(Operation *,
208
203
OpResult);
209
204
template bool mlir::hasSingleEffect<OpResult, MemoryEffects::Write>(Operation *,
210
205
OpResult);
211
- template bool mlir::hasSingleEffect<OpResult, MemoryEffects::Init>(Operation *,
212
- OpResult);
213
206
template bool
214
207
mlir::hasSingleEffect<BlockArgument, MemoryEffects::Allocate>(Operation *,
215
208
BlockArgument);
@@ -222,9 +215,6 @@ mlir::hasSingleEffect<BlockArgument, MemoryEffects::Read>(Operation *,
222
215
template bool
223
216
mlir::hasSingleEffect<BlockArgument, MemoryEffects::Write>(Operation *,
224
217
BlockArgument);
225
- template bool
226
- mlir::hasSingleEffect<BlockArgument, MemoryEffects::Init>(Operation *,
227
- BlockArgument);
228
218
229
219
template <typename ... EffectTys>
230
220
bool mlir::hasEffect (Operation *op) {
@@ -241,7 +231,6 @@ template bool mlir::hasEffect<MemoryEffects::Allocate>(Operation *);
241
231
template bool mlir::hasEffect<MemoryEffects::Free>(Operation *);
242
232
template bool mlir::hasEffect<MemoryEffects::Read>(Operation *);
243
233
template bool mlir::hasEffect<MemoryEffects::Write>(Operation *);
244
- template bool mlir::hasEffect<MemoryEffects::Init>(Operation *);
245
234
template bool
246
235
mlir::hasEffect<MemoryEffects::Write, MemoryEffects::Free>(Operation *);
247
236
@@ -263,7 +252,6 @@ template bool mlir::hasEffect<MemoryEffects::Allocate>(Operation *,
263
252
template bool mlir::hasEffect<MemoryEffects::Free>(Operation *, Value value);
264
253
template bool mlir::hasEffect<MemoryEffects::Read>(Operation *, Value value);
265
254
template bool mlir::hasEffect<MemoryEffects::Write>(Operation *, Value value);
266
- template bool mlir::hasEffect<MemoryEffects::Init>(Operation *, Value value);
267
255
template bool
268
256
mlir::hasEffect<MemoryEffects::Write, MemoryEffects::Free>(Operation *,
269
257
Value value);
@@ -289,8 +277,6 @@ template bool mlir::hasEffect<OpOperand *, MemoryEffects::Read>(Operation *,
289
277
OpOperand *);
290
278
template bool mlir::hasEffect<OpOperand *, MemoryEffects::Write>(Operation *,
291
279
OpOperand *);
292
- template bool mlir::hasEffect<OpOperand *, MemoryEffects::Init>(Operation *,
293
- OpOperand *);
294
280
template bool
295
281
mlir::hasEffect<OpOperand *, MemoryEffects::Write, MemoryEffects::Free>(
296
282
Operation *, OpOperand *);
@@ -303,8 +289,6 @@ template bool mlir::hasEffect<OpResult, MemoryEffects::Read>(Operation *,
303
289
OpResult);
304
290
template bool mlir::hasEffect<OpResult, MemoryEffects::Write>(Operation *,
305
291
OpResult);
306
- template bool mlir::hasEffect<OpResult, MemoryEffects::Init>(Operation *,
307
- OpResult);
308
292
template bool
309
293
mlir::hasEffect<OpResult, MemoryEffects::Write, MemoryEffects::Free>(
310
294
Operation *, OpResult);
@@ -320,8 +304,6 @@ template bool
320
304
mlir::hasEffect<BlockArgument, MemoryEffects::Write>(Operation *,
321
305
BlockArgument);
322
306
template bool
323
- mlir::hasEffect<BlockArgument, MemoryEffects::Init>(Operation *, BlockArgument);
324
- template bool
325
307
mlir::hasEffect<BlockArgument, MemoryEffects::Write, MemoryEffects::Free>(
326
308
Operation *, BlockArgument);
327
309
@@ -334,7 +316,13 @@ bool mlir::wouldOpBeTriviallyDead(Operation *op) {
334
316
}
335
317
336
318
bool mlir::isMemoryEffectMovable (Operation *op) {
337
- return (isMemoryEffectFree (op) || isMemoryInitMovable (op));
319
+ if (isMemoryEffectFree (op))
320
+ return true ;
321
+
322
+ if (isMemoryEffectConflictFree (op))
323
+ return true ;
324
+
325
+ return false ;
338
326
}
339
327
340
328
bool mlir::isMemoryEffectFree (Operation *op) {
@@ -358,16 +346,15 @@ bool mlir::isMemoryEffectFree(Operation *op) {
358
346
// free.
359
347
for (Region ®ion : op->getRegions ())
360
348
for (Operation &op : region.getOps ())
361
- if (!isMemoryEffectFree (&op))
349
+ if (!isMemoryEffectMovable (&op))
362
350
return false ;
363
351
364
352
return true ;
365
353
}
366
354
367
- bool mlir::isMemoryInitMovable (Operation *op) {
355
+ bool mlir::isMemoryEffectConflictFree (Operation *op) {
368
356
auto memInterface = dyn_cast<MemoryEffectOpInterface>(op);
369
357
// op does not implement the memory effect op interface
370
- // meaning it doesn't have any memory init effects and
371
358
// shouldn't be flagged as movable to be conservative
372
359
if (!memInterface) return false ;
373
360
@@ -378,60 +365,68 @@ bool mlir::isMemoryInitMovable(Operation *op) {
378
365
// op has interface but no effects, be conservative
379
366
if (effects.empty ()) return false ;
380
367
381
-
382
368
DenseMap<TypeID, int > resourceCounts;
383
369
384
- // ensure op only has Init effects and gather unique
370
+ // ensure op only has Write effects and gather unique
385
371
// resource names
386
372
for (const MemoryEffects::EffectInstance &effect : effects) {
387
- if (!isa<MemoryEffects::Init >(effect.getEffect ()))
373
+ if (!isa<MemoryEffects::Write >(effect.getEffect ()))
388
374
return false ;
389
375
390
376
resourceCounts.try_emplace (effect.getResource ()->getResourceID (), 0 );
391
377
}
392
378
393
379
// op itself is good, need to check rest of its parent region
394
380
Operation *parent = op->getParentOp ();
381
+ mlir::DominanceInfo dom (parent);
395
382
396
383
for (Region ®ion : parent->getRegions ())
397
- for (Operation &op_i : region.getOps ())
398
- if (hasMemoryEffectInitConflict (&op_i , resourceCounts))
384
+ for (Operation &opI : region.getOps ())
385
+ if (hasMemoryEffectConflict (op, &opI, dom , resourceCounts))
399
386
return false ;
400
387
401
388
return true ;
402
389
}
403
390
404
- bool mlir::hasMemoryEffectInitConflict (
405
- Operation *op, DenseMap<TypeID, int > &resourceCounts) {
391
+ bool mlir::hasMemoryEffectConflict (
392
+ Operation *mainOp, Operation *op,
393
+ mlir::DominanceInfo &dom, DenseMap<TypeID, int > &resourceCounts) {
406
394
407
395
if (auto memInterface = dyn_cast<MemoryEffectOpInterface>(op)) {
408
- if (!memInterface.hasNoEffect ()) {
409
- llvm::SmallVector<MemoryEffects::EffectInstance> effects;
410
- memInterface.getEffects (effects);
411
-
412
- // ensure op only has Init effects and gather unique
413
- // resource names
414
- for (const MemoryEffects::EffectInstance &effect : effects) {
415
- if (!isa<MemoryEffects::Init>(effect.getEffect ()))
416
- return true ;
396
+
397
+ llvm::SmallVector<MemoryEffects::EffectInstance> effects;
398
+ memInterface.getEffects (effects);
399
+
400
+ auto isDominated = dom.properlyDominates (mainOp, op);
417
401
418
- // only care about resources of the op that called
419
- // this recursive function for the first time
420
- auto resourceID = effect.getResource ()->getResourceID ();
402
+ // ensure op only has Write or dominated Read effects
403
+ // check used resources
404
+ for (const MemoryEffects::EffectInstance &effect : effects) {
405
+ auto resourceID = effect.getResource ()->getResourceID ();
421
406
422
- if (resourceCounts.contains (resourceID))
423
- if (++resourceCounts[resourceID] > 1 )
424
- return true ;
407
+ if (resourceCounts.contains (resourceID)) {
408
+ if (isa<MemoryEffects::Read>(effect.getEffect ())) {
409
+ if (isDominated) {
410
+ continue ; // skip dominated reads
411
+ }
412
+ }
413
+ else if (!isa<MemoryEffects::Write>(effect.getEffect ())) {
414
+ return true ; // count alloc/free in same region as conflict, be conservative
415
+ }
416
+
417
+ // update write counts, should always be <=1 per resource in region
418
+ if (++resourceCounts[resourceID] > 1 ) {
419
+ return true ;
420
+ }
425
421
}
426
- return false ;
427
422
}
428
423
}
429
424
430
425
// Recurse into the regions and ensure that nested ops don't
431
- // conflict with each others MemInits
426
+ // conflict with each other's MemWrites
432
427
for (Region ®ion : op->getRegions ())
433
- for (Operation &op : region.getOps ())
434
- if (hasMemoryEffectInitConflict (&op , resourceCounts))
428
+ for (Operation &opI : region.getOps ())
429
+ if (hasMemoryEffectConflict (mainOp, &opI, dom , resourceCounts))
435
430
return true ;
436
431
437
432
return false ;
0 commit comments