Adding verification after EncodeHostTensors/EncodeDeviceTensors passes. (#16255)
This is a lighter check than the existing verification of async lowering
that only checks that there are no tensor ops remaining.
Fixes #16231.
diff --git a/compiler/src/iree/compiler/Dialect/Stream/Transforms/Passes.cpp b/compiler/src/iree/compiler/Dialect/Stream/Transforms/Passes.cpp
index d6b4e5a..f741745 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/Transforms/Passes.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/Transforms/Passes.cpp
@@ -125,6 +125,10 @@
addCleanupPatterns(passManager);
+ // Everything must now be in stream.async.* form but we don't yet have
+ // lifetime assigned.
+ passManager.addPass(IREE::Stream::createVerifyLoweringToAsyncResourcesPass());
+
// Materialize copy-on-write behavior with explicit stream.async.* ops.
// This will insert a lot of copies, so follow it up with a pass that elides
// ones that aren't needed. This is easier to verify than if there was one
diff --git a/compiler/src/iree/compiler/Dialect/Stream/Transforms/Passes.td b/compiler/src/iree/compiler/Dialect/Stream/Transforms/Passes.td
index f7d760b..fabe47f 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/Transforms/Passes.td
+++ b/compiler/src/iree/compiler/Dialect/Stream/Transforms/Passes.td
@@ -492,9 +492,14 @@
let summary = "Verifies that input dialects are converted to stream.tensor.* ops.";
}
+def VerifyLoweringToAsyncResourcesPass :
+ Pass<"iree-stream-verify-lowering-to-async-resources", "mlir::ModuleOp"> {
+ let summary = "Verifies that all stream.tensor.* ops and types are fully lowered to stream.async.* resource ops.";
+}
+
def VerifyLoweringToAsyncPass :
Pass<"iree-stream-verify-lowering-to-async", "mlir::ModuleOp"> {
- let summary = "Verifies that all stream.tensor.* ops and types are fully lowered to stream.async.* ops.";
+ let summary = "Verifies that all stream.tensor.* ops and types are fully lowered to stream.async.* ops and all resources have an assigned lifetime.";
}
def VerifyAsyncAccessRangesPass :
diff --git a/compiler/src/iree/compiler/Dialect/Stream/Transforms/VerifyLowerings.cpp b/compiler/src/iree/compiler/Dialect/Stream/Transforms/VerifyLowerings.cpp
index b515a97..2860f48 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/Transforms/VerifyLowerings.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/Transforms/VerifyLowerings.cpp
@@ -24,6 +24,7 @@
#define GEN_PASS_DEF_VERIFYINPUTPASS
#define GEN_PASS_DEF_VERIFYLOWERINGTOTENSORSPASS
+#define GEN_PASS_DEF_VERIFYLOWERINGTOASYNCRESOURCESPASS
#define GEN_PASS_DEF_VERIFYLOWERINGTOASYNCPASS
#define GEN_PASS_DEF_VERIFYLOWERINGTOCMDPASS
#include "iree/compiler/Dialect/Stream/Transforms/Passes.h.inc"
@@ -297,7 +298,28 @@
};
//===----------------------------------------------------------------------===//
-// --iree-stream-verify-lowering-to-tensors
+// --iree-stream-verify-lowering-to-async-resources
+//===----------------------------------------------------------------------===//
+
+struct VerifyLoweringToAsyncResourcesPass
+ : public IREE::Stream::impl::VerifyLoweringToAsyncResourcesPassBase<
+ VerifyLoweringToAsyncResourcesPass> {
+ void runOnOperation() override {
+ // We cannot have stream.cmd.* ops mixed with stream.tensor/async.* ops
+ // as they use different memory models. We need to allow them through,
+ // though, to allow for compiler re-entrancy.
+ Verifier verifier;
+ setupDefaultOpLegality(verifier);
+ markTensorInputsIllegal(verifier);
+ markStreamTensorOpsIllegal(verifier);
+ if (failed(verifier.run(getOperation()))) {
+ return signalPassFailure();
+ }
+ }
+};
+
+//===----------------------------------------------------------------------===//
+// --iree-stream-verify-lowering-to-async
//===----------------------------------------------------------------------===//
struct VerifyLoweringToAsyncPass
diff --git a/compiler/src/iree/compiler/Dialect/Stream/Transforms/test/refine_usage.mlir b/compiler/src/iree/compiler/Dialect/Stream/Transforms/test/refine_usage.mlir
index b1cb56a..7276441 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/Transforms/test/refine_usage.mlir
+++ b/compiler/src/iree/compiler/Dialect/Stream/Transforms/test/refine_usage.mlir
@@ -318,14 +318,14 @@
%c1 = arith.constant 1 : index
%c4 = arith.constant 4 : index
-// CHECK: %[[C0:.+]] = arith.constant 0 : index
-// CHECK: %[[C1:.+]] = arith.constant 1 : index
-// CHECK: %[[C4:.+]] = arith.constant 4 : index
-// CHECK: %[[DISP0:.+]] = stream.async.dispatch @dispatch0(%arg1[%[[C0]] to %[[ARG0]] for %[[ARG0]]]) : (!stream.resource<external>{%[[C4]]}) -> !stream.resource<transient>{%[[C4]]}
+ // CHECK: %[[C0:.+]] = arith.constant 0 : index
+ // CHECK: %[[C1:.+]] = arith.constant 1 : index
+ // CHECK: %[[C4:.+]] = arith.constant 4 : index
+ // CHECK: %[[DISP0:.+]] = stream.async.dispatch @dispatch0(%arg1[%[[C0]] to %[[ARG0]] for %[[ARG0]]]) : (!stream.resource<external>{%[[C4]]}) -> !stream.resource<transient>{%[[C4]]}
%dispatch6 = stream.async.dispatch @dispatch0(%arg1[%c0 to %arg0 for %arg0]) : (!stream.resource<*>{%c4}) -> !stream.resource<*>{%c4}
+
// CHECK: %[[FOR:.+]] = scf.for %[[ARG2:.+]] = %[[C0]] to %[[ARG0]] step %[[C1]] iter_args(%[[ARG3:.+]] = %[[DISP0]]) -> (!stream.resource<transient>) {
%for = scf.for %i = %c0 to %arg0 step %c1 iter_args(%arg3 = %dispatch6) -> (!stream.resource<*>) {
-
// CHECK: %[[DISP1:.+]] = stream.async.dispatch @dispatch1(%[[ARG3]][%[[C0]] to %[[ARG0]] for %[[ARG0]]]) : (!stream.resource<transient>{%[[C4]]}) -> !stream.resource<transient>{%[[C4]]}
// CHECK: %[[DISP2:.+]] = stream.async.dispatch @dispatch2(%[[DISP1]][%[[C0]] to %[[ARG0]] for %[[ARG0]]]) : (!stream.resource<transient>{%[[C4]]}) -> !stream.resource<transient>{%[[C4]]}
// CHECK: %[[DISP3:.+]] = stream.async.dispatch @dispatch3(%[[DISP2]][%[[C0]] to %[[ARG0]] for %[[ARG0]]]) : (!stream.resource<transient>{%[[C4]]}) -> !stream.resource<transient>{%[[C4]]}
@@ -335,6 +335,7 @@
// CHECK: scf.yield %[[DISP3]] : !stream.resource<transient>
scf.yield %dispatch3 : !stream.resource<*>
}
+
// CHECK: %[[DISP4:.+]] = stream.async.dispatch @dispatch4(%[[FOR]][%[[C0]] to %[[ARG0]] for %[[ARG0]]]) : (!stream.resource<transient>{%[[C4]]}) -> !stream.resource<external>{%[[C4]]}
%dispatch5 = stream.async.dispatch @dispatch4(%for[%c0 to %arg0 for %arg0]) : (!stream.resource<*>{%c4}) -> !stream.resource<*>{%c4}
%transfer = stream.async.transfer %dispatch5 : !stream.resource<*>{%arg0} -> !stream.resource<external>{%arg0}