[Mlir-commits] [mlir] b6ceadf - [MLIR] NFC. Split out code from hasNoInterveningEffect
Uday Bondhugula
llvmlistbot at llvm.org
Wed Dec 14 23:59:09 PST 2022
Author: Uday Bondhugula
Date: 2022-12-15T13:23:36+05:30
New Revision: b6ceadf3b663427f3cc233bbfdb5e35017cabd9e
URL: https://github.com/llvm/llvm-project/commit/b6ceadf3b663427f3cc233bbfdb5e35017cabd9e
DIFF: https://github.com/llvm/llvm-project/commit/b6ceadf3b663427f3cc233bbfdb5e35017cabd9e.diff
LOG: [MLIR] NFC. Split out code from hasNoInterveningEffect
The `hasNoInterveningEffect` utility is too long with too deeply nested
logic. Split out a part into a helper. NFC.
Reviewed By: springerm
Differential Revision: https://reviews.llvm.org/D139795
Added:
Modified:
mlir/lib/Dialect/Affine/Utils/Utils.cpp
Removed:
################################################################################
diff --git a/mlir/lib/Dialect/Affine/Utils/Utils.cpp b/mlir/lib/Dialect/Affine/Utils/Utils.cpp
index 739588fd02ef6..e93455a5b066d 100644
--- a/mlir/lib/Dialect/Affine/Utils/Utils.cpp
+++ b/mlir/lib/Dialect/Affine/Utils/Utils.cpp
@@ -643,6 +643,41 @@ LogicalResult mlir::normalizeAffineFor(AffineForOp op, bool promoteSingleIter) {
return success();
}
+/// Returns true if `srcMemOp` may have an effect on `destMemOp` within the
+/// scope of the outermost `minSurroundingLoops` loops that surround them.
+/// `srcMemOp` and `destMemOp` are expected to be affine read/write ops.
+static bool mayHaveEffect(Operation *srcMemOp, Operation *destMemOp,
+ unsigned minSurroundingLoops) {
+ MemRefAccess srcAccess(srcMemOp);
+ MemRefAccess destAccess(destMemOp);
+
+ // Affine dependence analysis here is applicable only if both ops operate on
+ // the same memref and if `srcMemOp` and `destMemOp` are in the same
+ // AffineScope. Also, we can only check if our affine scope is isolated from
+ // above; otherwise, values can from outside of the affine scope that the
+ // check below cannot analyze.
+ Region *srcScope = getAffineScope(srcMemOp);
+ if (srcAccess.memref == destAccess.memref &&
+ srcScope == getAffineScope(destMemOp)) {
+ unsigned nsLoops = getNumCommonSurroundingLoops(*srcMemOp, *destMemOp);
+ FlatAffineValueConstraints dependenceConstraints;
+ for (unsigned d = nsLoops + 1; d > minSurroundingLoops; d--) {
+ DependenceResult result = checkMemrefAccessDependence(
+ srcAccess, destAccess, d, &dependenceConstraints,
+ /*dependenceComponents=*/nullptr);
+ // A dependence failure or the presence of a dependence implies a
+ // side effect.
+ if (!noDependence(result))
+ return true;
+ }
+ // No side effect was seen.
+ return false;
+ }
+ // TODO: Check here if the memrefs alias: there is no side effect if
+ // `srcAccess.memref` and `destAccess.memref` don't alias.
+ return true;
+}
+
template <typename EffectType, typename T>
bool mlir::hasNoInterveningEffect(Operation *start, T memOp) {
auto isLocallyAllocated = [](Value memref) {
@@ -687,49 +722,19 @@ bool mlir::hasNoInterveningEffect(Operation *start, T memOp) {
// If the side effect comes from an affine read or write, try to
// prove the side effecting `op` cannot reach `memOp`.
if (isa<AffineReadOpInterface, AffineWriteOpInterface>(op)) {
- MemRefAccess srcAccess(op);
- MemRefAccess destAccess(memOp);
- // Affine dependence analysis here is applicable only if both ops
- // operate on the same memref and if `op`, `memOp`, and `start` are in
- // the same AffineScope.
- if (srcAccess.memref == destAccess.memref &&
- getAffineScope(op) == getAffineScope(memOp) &&
- getAffineScope(op) == getAffineScope(start)) {
- // Number of loops containing the start op and the ending operation.
- unsigned minSurroundingLoops =
- getNumCommonSurroundingLoops(*start, *memOp);
-
- // Number of loops containing the operation `op` which has the
- // potential memory side effect and can occur on a path between
- // `start` and `memOp`.
- unsigned nsLoops = getNumCommonSurroundingLoops(*op, *memOp);
-
- // For ease, let's consider the case that `op` is a store and we're
- // looking for other potential stores (e.g `op`) that overwrite memory
- // after `start`, and before being read in `memOp`. In this case, we
- // only need to consider other potential stores with depth >
- // minSurrounding loops since `start` would overwrite any store with a
- // smaller number of surrounding loops before.
- unsigned d;
- FlatAffineValueConstraints dependenceConstraints;
- for (d = nsLoops + 1; d > minSurroundingLoops; d--) {
- DependenceResult result = checkMemrefAccessDependence(
- srcAccess, destAccess, d, &dependenceConstraints,
- /*dependenceComponents=*/nullptr);
- // A dependence failure or the presence of a dependence implies a
- // side effect.
- if (!noDependence(result)) {
- hasSideEffect = true;
- return;
- }
- }
-
- // No side effect was seen, simply return.
- return;
- }
- // TODO: Check here if the memrefs alias: there is no side effect if
- // `srcAccess.memref` and `destAccess.memref` don't alias.
+ // For ease, let's consider the case that `op` is a store and
+ // we're looking for other potential stores that overwrite memory after
+ // `start`, and before being read in `memOp`. In this case, we only
+ // need to consider other potential stores with depth >
+ // minSurroundingLoops since `start` would overwrite any store with a
+ // smaller number of surrounding loops before.
+ unsigned minSurroundingLoops =
+ getNumCommonSurroundingLoops(*start, *memOp);
+ if (mayHaveEffect(op, memOp, minSurroundingLoops))
+ hasSideEffect = true;
+ return;
}
+
// We have an op with a memory effect and we cannot prove if it
// intervenes.
hasSideEffect = true;
More information about the Mlir-commits
mailing list