@@ -348,6 +348,14 @@ struct AlwaysSpeculatableImplTrait
348
348
// ===----------------------------------------------------------------------===//
349
349
350
350
namespace MemoryEffects {
351
+ enum Priority {
352
+ kDefault = 0 ,
353
+ kAllocPriority = 1 ,
354
+ kFreePriority = 2 ,
355
+ kReadPriority = 3 ,
356
+ kWritePriority = 4
357
+ };
358
+
351
359
// / This class represents the base class used for memory effects.
352
360
struct Effect : public SideEffects ::Effect {
353
361
using SideEffects::Effect::Effect;
@@ -357,28 +365,48 @@ struct Effect : public SideEffects::Effect {
357
365
using Base = SideEffects::Effect::Base<DerivedEffect, Effect>;
358
366
359
367
static bool classof (const SideEffects::Effect *effect);
368
+
369
+ // / Return the priority associated with this memory effect.
370
+ Priority getPriority () const { return priority; }
371
+
372
+ protected:
373
+ // / Priority value for this effect. Lower numbers indicate higher precedence.
374
+ Priority priority = kDefault ;
360
375
};
361
376
using EffectInstance = SideEffects::EffectInstance<Effect>;
362
377
378
+ // / Returns vector of effects sorted by effect stage then priority
379
+ // / priority order: allocate -> free -> read -> write
380
+ llvm::SmallVector<MemoryEffects::EffectInstance>
381
+ getMemoryEffectsSorted (Operation *op);
382
+
363
383
// / The following effect indicates that the operation allocates from some
364
384
// / resource. An 'allocate' effect implies only allocation of the resource, and
365
385
// / not any visible mutation or dereference.
366
- struct Allocate : public Effect ::Base<Allocate> {};
386
+ struct Allocate : public Effect ::Base<Allocate> {
387
+ Allocate () : Effect::Base<Allocate>() { this ->priority = kAllocPriority ; }
388
+ };
367
389
368
390
// / The following effect indicates that the operation frees some resource that
369
391
// / has been allocated. An 'allocate' effect implies only de-allocation of the
370
392
// / resource, and not any visible allocation, mutation or dereference.
371
- struct Free : public Effect ::Base<Free> {};
393
+ struct Free : public Effect ::Base<Free> {
394
+ Free () : Effect::Base<Free>() { this ->priority = kFreePriority ; }
395
+ };
372
396
373
397
// / The following effect indicates that the operation reads from some resource.
374
398
// / A 'read' effect implies only dereferencing of the resource, and not any
375
399
// / visible mutation.
376
- struct Read : public Effect ::Base<Read> {};
400
+ struct Read : public Effect ::Base<Read> {
401
+ Read () : Effect::Base<Read>() { this ->priority = kReadPriority ; }
402
+ };
377
403
378
404
// / The following effect indicates that the operation writes to some resource. A
379
405
// / 'write' effect implies only mutating a resource, and not any visible
380
406
// / dereference or read.
381
- struct Write : public Effect ::Base<Write> {};
407
+ struct Write : public Effect ::Base<Write> {
408
+ Write () : Effect::Base<Write>() { this ->priority = kWritePriority ; }
409
+ };
382
410
} // namespace MemoryEffects
383
411
384
412
// ===----------------------------------------------------------------------===//
@@ -470,17 +498,6 @@ bool wouldOpBeTriviallyDead(Operation *op);
470
498
// /
471
499
std::optional<bool > isZeroTrip (mlir::LoopLikeOpInterface &loop);
472
500
473
- // / Returns true if the given operation is allowed to be moved under the
474
- // / memory effects interface.
475
- // /
476
- // / An operation is movable if either case is true:
477
- // / (a) free of memory effects as defined in isMemoryEffectFree()
478
- // / (b) if the operation does have memory effects, it must be conflict-free
479
- // / as defined in isMemoryEffectConflictFree()
480
- // /
481
- // / If the operation meets either criteria, then it is movable under memory effects
482
- bool isMemoryEffectMovable (Operation *op);
483
-
484
501
// / Returns true if the given operation is free of memory effects.
485
502
// /
486
503
// / An operation is free of memory effects if its implementation of
@@ -493,35 +510,6 @@ bool isMemoryEffectMovable(Operation *op);
493
510
// / conditions are satisfied.
494
511
bool isMemoryEffectFree (Operation *op);
495
512
496
- // / Returns true if the given operation has conflict-free write effects
497
- // /
498
- // / An operation is conflict free:
499
- // / (1) Parent is a loop with the LoopLikeOpInterface
500
- // / (2) Parent loop is not a zero trip loop and has constant bounds/steps
501
- // / (3) all of the op's memory effects are of type Write
502
- // / (4) there are no other ops with Alloc/Free/Write effects on the same
503
- // / resources within the op's parent loop region
504
- // / (5) all ops in the parent loop region with Read effects on the same
505
- // / resources are dominated by the operation
506
- // /
507
- // / If the operation meets all criteria, then it is conflict free
508
- bool isMemoryEffectConflictFree (Operation *op);
509
-
510
- // / Returns true if op and/or any operations within its nested regions
511
- // / have a memory effect conflict with mainOp as defined below:
512
- // /
513
- // / op has a memory effect conflict with mainOp if op and/or any of
514
- // / the operations in its nested regions meet any of these criteria:
515
- // / (a) they have any Alloc/Free/Write effects on the resources used by mainOp
516
- // / (b) they dominate mainOp and have any read effect on the resources used by mainOp
517
- // /
518
- // / Function mutates resources map
519
- // /
520
- // / If none of the critera above are met, mainOp and op are conflict free
521
- bool hasMemoryEffectConflict (
522
- Operation *mainOp, Operation *op,
523
- mlir::DominanceInfo &dom, DenseMap<TypeID, int > &resourceCounts);
524
-
525
513
// / Returns the side effects of an operation. If the operation has
526
514
// / RecursiveMemoryEffects, include all side effects of child operations.
527
515
// /
0 commit comments