@@ -678,12 +678,9 @@ static bool mayHaveEffect(Operation *srcMemOp, Operation *destMemOp,
678678}
679679
680680template <typename EffectType, typename T>
681- bool mlir::affine::hasNoInterveningEffect (Operation *start, T memOp) {
682- auto isLocallyAllocated = [](Value memref) {
683- auto *defOp = memref.getDefiningOp ();
684- return defOp && hasSingleEffect<MemoryEffects::Allocate>(defOp, memref);
685- };
686-
681+ bool mlir::affine::hasNoInterveningEffect (
682+ Operation *start, T memOp,
683+ llvm::function_ref<bool (Value, Value)> mayAlias) {
687684 // A boolean representing whether an intervening operation could have impacted
688685 // memOp.
689686 bool hasSideEffect = false ;
@@ -704,11 +701,8 @@ bool mlir::affine::hasNoInterveningEffect(Operation *start, T memOp) {
704701 // If op causes EffectType on a potentially aliasing location for
705702 // memOp, mark as having the effect.
706703 if (isa<EffectType>(effect.getEffect ())) {
707- // TODO: This should be replaced with a check for no aliasing.
708- // Aliasing information should be passed to this method.
709704 if (effect.getValue () && effect.getValue () != memref &&
710- isLocallyAllocated (memref) &&
711- isLocallyAllocated (effect.getValue ()))
705+ !mayAlias (effect.getValue (), memref))
712706 continue ;
713707 opMayHaveEffect = true ;
714708 break ;
@@ -832,10 +826,10 @@ bool mlir::affine::hasNoInterveningEffect(Operation *start, T memOp) {
832826// / other operations will overwrite the memory loaded between the given load
833827// / and store. If such a value exists, the replaced `loadOp` will be added to
834828// / `loadOpsToErase` and its memref will be added to `memrefsToErase`.
835- static void forwardStoreToLoad (AffineReadOpInterface loadOp,
836- SmallVectorImpl<Operation *> &loadOpsToErase,
837- SmallPtrSetImpl<Value> &memrefsToErase,
838- DominanceInfo &domInfo ) {
829+ static void forwardStoreToLoad (
830+ AffineReadOpInterface loadOp, SmallVectorImpl<Operation *> &loadOpsToErase,
831+ SmallPtrSetImpl<Value> &memrefsToErase, DominanceInfo &domInfo ,
832+ llvm::function_ref< bool (Value, Value)> mayAlias ) {
839833
840834 // The store op candidate for forwarding that satisfies all conditions
841835 // to replace the load, if any.
@@ -872,7 +866,8 @@ static void forwardStoreToLoad(AffineReadOpInterface loadOp,
872866
873867 // 4. Ensure there is no intermediate operation which could replace the
874868 // value in memory.
875- if (!affine::hasNoInterveningEffect<MemoryEffects::Write>(storeOp, loadOp))
869+ if (!affine::hasNoInterveningEffect<MemoryEffects::Write>(storeOp, loadOp,
870+ mayAlias))
876871 continue ;
877872
878873 // We now have a candidate for forwarding.
@@ -901,7 +896,8 @@ static void forwardStoreToLoad(AffineReadOpInterface loadOp,
901896template bool
902897mlir::affine::hasNoInterveningEffect<mlir::MemoryEffects::Read,
903898 affine::AffineReadOpInterface>(
904- mlir::Operation *, affine::AffineReadOpInterface);
899+ mlir::Operation *, affine::AffineReadOpInterface,
900+ llvm::function_ref<bool (Value, Value)>);
905901
906902// This attempts to find stores which have no impact on the final result.
907903// A writing op writeA will be eliminated if there exists an op writeB if
@@ -910,7 +906,8 @@ mlir::affine::hasNoInterveningEffect<mlir::MemoryEffects::Read,
910906// 3) There is no potential read between writeA and writeB.
911907static void findUnusedStore (AffineWriteOpInterface writeA,
912908 SmallVectorImpl<Operation *> &opsToErase,
913- PostDominanceInfo &postDominanceInfo) {
909+ PostDominanceInfo &postDominanceInfo,
910+ llvm::function_ref<bool (Value, Value)> mayAlias) {
914911
915912 for (Operation *user : writeA.getMemRef ().getUsers ()) {
916913 // Only consider writing operations.
@@ -939,7 +936,8 @@ static void findUnusedStore(AffineWriteOpInterface writeA,
939936
940937 // There cannot be an operation which reads from memory between
941938 // the two writes.
942- if (!affine::hasNoInterveningEffect<MemoryEffects::Read>(writeA, writeB))
939+ if (!affine::hasNoInterveningEffect<MemoryEffects::Read>(writeA, writeB,
940+ mayAlias))
943941 continue ;
944942
945943 opsToErase.push_back (writeA);
@@ -955,7 +953,8 @@ static void findUnusedStore(AffineWriteOpInterface writeA,
955953// 3) There is no write between loadA and loadB.
956954static void loadCSE (AffineReadOpInterface loadA,
957955 SmallVectorImpl<Operation *> &loadOpsToErase,
958- DominanceInfo &domInfo) {
956+ DominanceInfo &domInfo,
957+ llvm::function_ref<bool (Value, Value)> mayAlias) {
959958 SmallVector<AffineReadOpInterface, 4 > loadCandidates;
960959 for (auto *user : loadA.getMemRef ().getUsers ()) {
961960 auto loadB = dyn_cast<AffineReadOpInterface>(user);
@@ -976,7 +975,7 @@ static void loadCSE(AffineReadOpInterface loadA,
976975
977976 // 3. There should not be a write between loadA and loadB.
978977 if (!affine::hasNoInterveningEffect<MemoryEffects::Write>(
979- loadB.getOperation (), loadA))
978+ loadB.getOperation (), loadA, mayAlias ))
980979 continue ;
981980
982981 // Check if two values have the same shape. This is needed for affine vector
@@ -1034,24 +1033,29 @@ static void loadCSE(AffineReadOpInterface loadA,
10341033// than dealloc) remain.
10351034//
10361035void mlir::affine::affineScalarReplace (func::FuncOp f, DominanceInfo &domInfo,
1037- PostDominanceInfo &postDomInfo) {
1036+ PostDominanceInfo &postDomInfo,
1037+ AliasAnalysis &aliasAnalysis) {
10381038 // Load op's whose results were replaced by those forwarded from stores.
10391039 SmallVector<Operation *, 8 > opsToErase;
10401040
10411041 // A list of memref's that are potentially dead / could be eliminated.
10421042 SmallPtrSet<Value, 4 > memrefsToErase;
10431043
1044+ auto mayAlias = [&](Value val1, Value val2) -> bool {
1045+ return !aliasAnalysis.alias (val1, val2).isNo ();
1046+ };
1047+
10441048 // Walk all load's and perform store to load forwarding.
10451049 f.walk ([&](AffineReadOpInterface loadOp) {
1046- forwardStoreToLoad (loadOp, opsToErase, memrefsToErase, domInfo);
1050+ forwardStoreToLoad (loadOp, opsToErase, memrefsToErase, domInfo, mayAlias );
10471051 });
10481052 for (auto *op : opsToErase)
10491053 op->erase ();
10501054 opsToErase.clear ();
10511055
10521056 // Walk all store's and perform unused store elimination
10531057 f.walk ([&](AffineWriteOpInterface storeOp) {
1054- findUnusedStore (storeOp, opsToErase, postDomInfo);
1058+ findUnusedStore (storeOp, opsToErase, postDomInfo, mayAlias );
10551059 });
10561060 for (auto *op : opsToErase)
10571061 op->erase ();
@@ -1084,7 +1088,7 @@ void mlir::affine::affineScalarReplace(func::FuncOp f, DominanceInfo &domInfo,
10841088 // stores. Otherwise, some stores are wrongly seen as having an intervening
10851089 // effect.
10861090 f.walk ([&](AffineReadOpInterface loadOp) {
1087- loadCSE (loadOp, opsToErase, domInfo);
1091+ loadCSE (loadOp, opsToErase, domInfo, mayAlias );
10881092 });
10891093 for (auto *op : opsToErase)
10901094 op->erase ();
0 commit comments