57
57
#include " llvm/ADT/DenseSet.h"
58
58
#include " llvm/ADT/SetVector.h"
59
59
60
+ // Run mlir-opt with `-debug-only="one-shot-analysis"` for detailed debug
61
+ // output.
62
+ #define DEBUG_TYPE " one-shot-analysis"
63
+
60
64
using namespace mlir ;
61
65
using namespace mlir ::bufferization;
62
66
@@ -553,6 +557,7 @@ static bool hasReadAfterWriteInterference(
553
557
554
558
// Check if op dominance can be used to rule out read-after-write conflicts.
555
559
bool useDominance = canUseOpDominance (usesRead, usesWrite, state);
560
+ LLVM_DEBUG (llvm::dbgs () << " \n - useDominance = " << useDominance << " \n " );
556
561
557
562
for (OpOperand *uRead : usesRead) {
558
563
Operation *readingOp = uRead->getOwner ();
@@ -572,6 +577,14 @@ static bool hasReadAfterWriteInterference(
572
577
// Look for conflicting memory writes. Potential conflicts are writes to an
573
578
// alias that have been decided to bufferize inplace.
574
579
for (OpOperand *uConflictingWrite : usesWrite) {
580
+ LLVM_DEBUG (llvm::dbgs () << " \n - check conflict:\n " );
581
+ LLVM_DEBUG (llvm::dbgs ()
582
+ << " uRead = operand " << uRead->getOperandNumber () << " of "
583
+ << *uRead->getOwner () << " \n " );
584
+ LLVM_DEBUG (llvm::dbgs () << " unConflictingWrite = operand "
585
+ << uConflictingWrite->getOperandNumber () << " of "
586
+ << *uConflictingWrite->getOwner () << " \n " );
587
+
575
588
// Throughout this loop, check for multiple requirements that have to be
576
589
// met for uConflictingWrite to be an actual conflict.
577
590
Operation *conflictingWritingOp = uConflictingWrite->getOwner ();
@@ -585,8 +598,11 @@ static bool hasReadAfterWriteInterference(
585
598
// Note: If ops are executed multiple times (e.g., because they are
586
599
// inside a loop), there may be no meaningful `happensBefore`
587
600
// relationship.
588
- if (happensBefore (readingOp, conflictingWritingOp, domInfo))
601
+ if (happensBefore (readingOp, conflictingWritingOp, domInfo)) {
602
+ LLVM_DEBUG (llvm::dbgs ()
603
+ << " no conflict: read happens before write\n " );
589
604
continue ;
605
+ }
590
606
591
607
// No conflict if the reading use equals the use of the conflicting
592
608
// write. A use cannot conflict with itself.
@@ -595,61 +611,93 @@ static bool hasReadAfterWriteInterference(
595
611
// use.
596
612
// Note: If the op is executed multiple times (e.g., because it is
597
613
// inside a loop), it may be conflicting with itself.
598
- if (uConflictingWrite == uRead)
614
+ if (uConflictingWrite == uRead) {
615
+ LLVM_DEBUG (llvm::dbgs ()
616
+ << " no conflict: read and write are same use\n " );
599
617
continue ;
618
+ }
600
619
601
620
// Ops are not conflicting if they are in mutually exclusive regions.
602
621
//
603
622
// Note: If ops are executed multiple times (e.g., because they are
604
623
// inside a loop), mutually exclusive regions may be executed
605
624
// multiple times.
606
- if (insideMutuallyExclusiveRegions (readingOp, conflictingWritingOp))
625
+ if (insideMutuallyExclusiveRegions (readingOp, conflictingWritingOp)) {
626
+ LLVM_DEBUG (llvm::dbgs () << " no conflict: read and write are in "
627
+ " mutually exclusive regions\n " );
607
628
continue ;
629
+ }
608
630
}
609
631
610
632
// No conflict if the op interface says so.
611
- if (auto bufferizableOp = options.dynCastBufferizableOp (readingOp))
612
- if (bufferizableOp.isNotConflicting (uRead, uConflictingWrite, state))
633
+ if (auto bufferizableOp = options.dynCastBufferizableOp (readingOp)) {
634
+ if (bufferizableOp.isNotConflicting (uRead, uConflictingWrite, state)) {
635
+ LLVM_DEBUG (llvm::dbgs ()
636
+ << " no conflict: op interace of reading op says 'no'\n " );
613
637
continue ;
638
+ }
639
+ }
614
640
615
- if (conflictingWritingOp != readingOp)
641
+ if (conflictingWritingOp != readingOp) {
616
642
if (auto bufferizableOp =
617
- options.dynCastBufferizableOp (conflictingWritingOp))
618
- if (bufferizableOp.isNotConflicting (uRead, uConflictingWrite, state))
643
+ options.dynCastBufferizableOp (conflictingWritingOp)) {
644
+ if (bufferizableOp.isNotConflicting (uRead, uConflictingWrite,
645
+ state)) {
646
+ LLVM_DEBUG (
647
+ llvm::dbgs ()
648
+ << " no conflict: op interace of writing op says 'no'\n " );
619
649
continue ;
650
+ }
651
+ }
652
+ }
620
653
621
654
// Check all possible last writes.
622
655
for (Value lastWrite : lastWrites) {
656
+ LLVM_DEBUG (llvm::dbgs () << " * lastWrite = " << lastWrite << " \n " );
657
+
623
658
// No conflict if the conflicting write happens before the last
624
659
// write.
625
660
if (Operation *writingOp = lastWrite.getDefiningOp ()) {
626
- if (happensBefore (conflictingWritingOp, writingOp, domInfo))
661
+ if (happensBefore (conflictingWritingOp, writingOp, domInfo)) {
627
662
// conflictingWritingOp happens before writingOp. No conflict.
663
+ LLVM_DEBUG (llvm::dbgs ()
664
+ << " no conflict: write happens before last write\n " );
628
665
continue ;
666
+ }
629
667
// No conflict if conflictingWritingOp is contained in writingOp.
630
- if (writingOp->isProperAncestor (conflictingWritingOp))
668
+ if (writingOp->isProperAncestor (conflictingWritingOp)) {
669
+ LLVM_DEBUG (
670
+ llvm::dbgs ()
671
+ << " no conflict: write is contained in last write\n " );
631
672
continue ;
673
+ }
632
674
} else {
633
675
auto bbArg = lastWrite.cast <BlockArgument>();
634
676
Block *block = bbArg.getOwner ();
635
- if (!block->findAncestorOpInBlock (*conflictingWritingOp))
677
+ if (!block->findAncestorOpInBlock (*conflictingWritingOp)) {
678
+ LLVM_DEBUG (llvm::dbgs () << " no conflict: last write is bbArg "
679
+ " and write happens outside of block\n " );
636
680
// conflictingWritingOp happens outside of the block. No
637
681
// conflict.
638
682
continue ;
683
+ }
639
684
}
640
685
641
686
// No conflict if the conflicting write and the last write are the same
642
687
// use.
643
688
SmallVector<OpResult> aliasingOpResult =
644
689
state.getAliasingOpResult (*uConflictingWrite);
645
- if (aliasingOpResult.size () == 1 && aliasingOpResult[0 ] == lastWrite)
690
+ if (aliasingOpResult.size () == 1 && aliasingOpResult[0 ] == lastWrite) {
691
+ LLVM_DEBUG (llvm::dbgs ()
692
+ << " no conflict: last write and write are same\n " );
646
693
continue ;
694
+ }
647
695
648
696
// All requirements are met. Conflict found!
649
697
650
698
if (options.printConflicts )
651
699
annotateConflict (uRead, uConflictingWrite, lastWrite);
652
-
700
+ LLVM_DEBUG ( llvm::dbgs () << " => RaW CONFLICT FOUND \n " );
653
701
return true ;
654
702
}
655
703
}
@@ -803,10 +851,13 @@ static bool wouldCreateWriteToNonWritableBuffer(
803
851
// Assuming that `operand` bufferizes in-place: For each write (to each
804
852
// alias), check if there is a non-writable tensor in the reverse SSA use-def
805
853
// chain.
806
- for (OpOperand *uWrite : usesWrite)
854
+ for (OpOperand *uWrite : usesWrite) {
807
855
if (hasPrecedingAliasingNonWritableTensor (uWrite->get (), &operand,
808
- aliasInfo, state))
856
+ aliasInfo, state)) {
857
+ LLVM_DEBUG (llvm::dbgs () << " => NOT WRITABLE\n " );
809
858
return true ;
859
+ }
860
+ }
810
861
811
862
return false ;
812
863
}
@@ -819,6 +870,11 @@ static bool wouldCreateWriteToNonWritableBuffer(
819
870
static LogicalResult bufferizableInPlaceAnalysisImpl (
820
871
OpOperand &operand, BufferizationAliasInfo &aliasInfo,
821
872
OneShotAnalysisState &state, const DominanceInfo &domInfo) {
873
+ LLVM_DEBUG (
874
+ llvm::dbgs () << " //===-------------------------------------------===//\n "
875
+ << " Analyzing operand #" << operand.getOperandNumber ()
876
+ << " of " << *operand.getOwner () << " \n " );
877
+
822
878
bool foundInterference =
823
879
wouldCreateWriteToNonWritableBuffer (operand, aliasInfo, state) ||
824
880
wouldCreateReadAfterWriteInterference (operand, domInfo, state, aliasInfo);
@@ -828,6 +884,8 @@ static LogicalResult bufferizableInPlaceAnalysisImpl(
828
884
else
829
885
aliasInfo.bufferizeInPlace (operand, state);
830
886
887
+ LLVM_DEBUG (llvm::dbgs ()
888
+ << " //===-------------------------------------------===//\n " );
831
889
return success ();
832
890
}
833
891
0 commit comments