@@ -678,12 +678,9 @@ static bool mayHaveEffect(Operation *srcMemOp, Operation *destMemOp,
678
678
}
679
679
680
680
template <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) {
687
684
// A boolean representing whether an intervening operation could have impacted
688
685
// memOp.
689
686
bool hasSideEffect = false ;
@@ -704,11 +701,8 @@ bool mlir::affine::hasNoInterveningEffect(Operation *start, T memOp) {
704
701
// If op causes EffectType on a potentially aliasing location for
705
702
// memOp, mark as having the effect.
706
703
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.
709
704
if (effect.getValue () && effect.getValue () != memref &&
710
- isLocallyAllocated (memref) &&
711
- isLocallyAllocated (effect.getValue ()))
705
+ !mayAlias (effect.getValue (), memref))
712
706
continue ;
713
707
opMayHaveEffect = true ;
714
708
break ;
@@ -832,10 +826,10 @@ bool mlir::affine::hasNoInterveningEffect(Operation *start, T memOp) {
832
826
// / other operations will overwrite the memory loaded between the given load
833
827
// / and store. If such a value exists, the replaced `loadOp` will be added to
834
828
// / `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 ) {
839
833
840
834
// The store op candidate for forwarding that satisfies all conditions
841
835
// to replace the load, if any.
@@ -872,7 +866,8 @@ static void forwardStoreToLoad(AffineReadOpInterface loadOp,
872
866
873
867
// 4. Ensure there is no intermediate operation which could replace the
874
868
// value in memory.
875
- if (!affine::hasNoInterveningEffect<MemoryEffects::Write>(storeOp, loadOp))
869
+ if (!affine::hasNoInterveningEffect<MemoryEffects::Write>(storeOp, loadOp,
870
+ mayAlias))
876
871
continue ;
877
872
878
873
// We now have a candidate for forwarding.
@@ -901,7 +896,8 @@ static void forwardStoreToLoad(AffineReadOpInterface loadOp,
901
896
template bool
902
897
mlir::affine::hasNoInterveningEffect<mlir::MemoryEffects::Read,
903
898
affine::AffineReadOpInterface>(
904
- mlir::Operation *, affine::AffineReadOpInterface);
899
+ mlir::Operation *, affine::AffineReadOpInterface,
900
+ llvm::function_ref<bool (Value, Value)>);
905
901
906
902
// This attempts to find stores which have no impact on the final result.
907
903
// A writing op writeA will be eliminated if there exists an op writeB if
@@ -910,7 +906,8 @@ mlir::affine::hasNoInterveningEffect<mlir::MemoryEffects::Read,
910
906
// 3) There is no potential read between writeA and writeB.
911
907
static void findUnusedStore (AffineWriteOpInterface writeA,
912
908
SmallVectorImpl<Operation *> &opsToErase,
913
- PostDominanceInfo &postDominanceInfo) {
909
+ PostDominanceInfo &postDominanceInfo,
910
+ llvm::function_ref<bool (Value, Value)> mayAlias) {
914
911
915
912
for (Operation *user : writeA.getMemRef ().getUsers ()) {
916
913
// Only consider writing operations.
@@ -939,7 +936,8 @@ static void findUnusedStore(AffineWriteOpInterface writeA,
939
936
940
937
// There cannot be an operation which reads from memory between
941
938
// the two writes.
942
- if (!affine::hasNoInterveningEffect<MemoryEffects::Read>(writeA, writeB))
939
+ if (!affine::hasNoInterveningEffect<MemoryEffects::Read>(writeA, writeB,
940
+ mayAlias))
943
941
continue ;
944
942
945
943
opsToErase.push_back (writeA);
@@ -955,7 +953,8 @@ static void findUnusedStore(AffineWriteOpInterface writeA,
955
953
// 3) There is no write between loadA and loadB.
956
954
static void loadCSE (AffineReadOpInterface loadA,
957
955
SmallVectorImpl<Operation *> &loadOpsToErase,
958
- DominanceInfo &domInfo) {
956
+ DominanceInfo &domInfo,
957
+ llvm::function_ref<bool (Value, Value)> mayAlias) {
959
958
SmallVector<AffineReadOpInterface, 4 > loadCandidates;
960
959
for (auto *user : loadA.getMemRef ().getUsers ()) {
961
960
auto loadB = dyn_cast<AffineReadOpInterface>(user);
@@ -976,7 +975,7 @@ static void loadCSE(AffineReadOpInterface loadA,
976
975
977
976
// 3. There should not be a write between loadA and loadB.
978
977
if (!affine::hasNoInterveningEffect<MemoryEffects::Write>(
979
- loadB.getOperation (), loadA))
978
+ loadB.getOperation (), loadA, mayAlias ))
980
979
continue ;
981
980
982
981
// Check if two values have the same shape. This is needed for affine vector
@@ -1034,24 +1033,29 @@ static void loadCSE(AffineReadOpInterface loadA,
1034
1033
// than dealloc) remain.
1035
1034
//
1036
1035
void mlir::affine::affineScalarReplace (func::FuncOp f, DominanceInfo &domInfo,
1037
- PostDominanceInfo &postDomInfo) {
1036
+ PostDominanceInfo &postDomInfo,
1037
+ AliasAnalysis &aliasAnalysis) {
1038
1038
// Load op's whose results were replaced by those forwarded from stores.
1039
1039
SmallVector<Operation *, 8 > opsToErase;
1040
1040
1041
1041
// A list of memref's that are potentially dead / could be eliminated.
1042
1042
SmallPtrSet<Value, 4 > memrefsToErase;
1043
1043
1044
+ auto mayAlias = [&](Value val1, Value val2) -> bool {
1045
+ return !aliasAnalysis.alias (val1, val2).isNo ();
1046
+ };
1047
+
1044
1048
// Walk all load's and perform store to load forwarding.
1045
1049
f.walk ([&](AffineReadOpInterface loadOp) {
1046
- forwardStoreToLoad (loadOp, opsToErase, memrefsToErase, domInfo);
1050
+ forwardStoreToLoad (loadOp, opsToErase, memrefsToErase, domInfo, mayAlias );
1047
1051
});
1048
1052
for (auto *op : opsToErase)
1049
1053
op->erase ();
1050
1054
opsToErase.clear ();
1051
1055
1052
1056
// Walk all store's and perform unused store elimination
1053
1057
f.walk ([&](AffineWriteOpInterface storeOp) {
1054
- findUnusedStore (storeOp, opsToErase, postDomInfo);
1058
+ findUnusedStore (storeOp, opsToErase, postDomInfo, mayAlias );
1055
1059
});
1056
1060
for (auto *op : opsToErase)
1057
1061
op->erase ();
@@ -1084,7 +1088,7 @@ void mlir::affine::affineScalarReplace(func::FuncOp f, DominanceInfo &domInfo,
1084
1088
// stores. Otherwise, some stores are wrongly seen as having an intervening
1085
1089
// effect.
1086
1090
f.walk ([&](AffineReadOpInterface loadOp) {
1087
- loadCSE (loadOp, opsToErase, domInfo);
1091
+ loadCSE (loadOp, opsToErase, domInfo, mayAlias );
1088
1092
});
1089
1093
for (auto *op : opsToErase)
1090
1094
op->erase ();
0 commit comments