[Mlir-commits] [mlir] 4157455 - [mlir][Pass] Deprecate FunctionPass in favor of OperationPass<FuncOp>

River Riddle llvmlistbot at llvm.org
Tue Jan 18 20:02:58 PST 2022


Author: River Riddle
Date: 2022-01-18T19:52:44-08:00
New Revision: 41574554257b4ebb478b89c01497a05773dbfc14

URL: https://github.com/llvm/llvm-project/commit/41574554257b4ebb478b89c01497a05773dbfc14
DIFF: https://github.com/llvm/llvm-project/commit/41574554257b4ebb478b89c01497a05773dbfc14.diff

LOG: [mlir][Pass] Deprecate FunctionPass in favor of OperationPass<FuncOp>

The only benefit of FunctionPass is that it filters out function
declarations. This isn't enough to justify carrying it around, as we can
simplify filter out declarations when necessary within the pass. We can
also explore with better scheduling primitives to filter out declarations
at the pipeline level in the future.

The definition of FunctionPass is left intact for now to allow time for downstream
users to migrate.

Differential Revision: https://reviews.llvm.org/D117182

Added: 
    

Modified: 
    mlir/docs/Bufferization.md
    mlir/docs/Rationale/Rationale.md
    mlir/docs/Tutorials/Toy/Ch-4.md
    mlir/docs/Tutorials/Toy/Ch-5.md
    mlir/examples/toy/Ch4/mlir/ShapeInferencePass.cpp
    mlir/examples/toy/Ch5/mlir/LowerToAffineLoops.cpp
    mlir/examples/toy/Ch5/mlir/ShapeInferencePass.cpp
    mlir/examples/toy/Ch6/mlir/LowerToAffineLoops.cpp
    mlir/examples/toy/Ch6/mlir/ShapeInferencePass.cpp
    mlir/examples/toy/Ch7/mlir/LowerToAffineLoops.cpp
    mlir/examples/toy/Ch7/mlir/ShapeInferencePass.cpp
    mlir/include/mlir/Conversion/Passes.td
    mlir/include/mlir/Dialect/Affine/Passes.h
    mlir/include/mlir/Dialect/Affine/Passes.td
    mlir/include/mlir/Dialect/Arithmetic/Transforms/Passes.td
    mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.h
    mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.td
    mlir/include/mlir/Dialect/GPU/Passes.td
    mlir/include/mlir/Dialect/Linalg/Passes.td
    mlir/include/mlir/Dialect/Quant/Passes.td
    mlir/include/mlir/Dialect/SCF/Passes.td
    mlir/include/mlir/Dialect/Shape/Transforms/Passes.h
    mlir/include/mlir/Dialect/Shape/Transforms/Passes.td
    mlir/include/mlir/Dialect/StandardOps/Transforms/Passes.td
    mlir/include/mlir/Dialect/Tensor/Transforms/Passes.td
    mlir/include/mlir/Dialect/Tosa/Transforms/Passes.td
    mlir/include/mlir/Pass/Pass.h
    mlir/include/mlir/Pass/PassBase.td
    mlir/include/mlir/Transforms/Passes.td
    mlir/lib/Conversion/ArithmeticToLLVM/ArithmeticToLLVM.cpp
    mlir/lib/Conversion/ArithmeticToSPIRV/ArithmeticToSPIRV.cpp
    mlir/lib/Conversion/ComplexToStandard/ComplexToStandard.cpp
    mlir/lib/Conversion/MathToLLVM/MathToLLVM.cpp
    mlir/lib/Conversion/SCFToGPU/SCFToGPUPass.cpp
    mlir/lib/Conversion/TosaToLinalg/TosaToLinalgNamedPass.cpp
    mlir/lib/Conversion/TosaToLinalg/TosaToLinalgPass.cpp
    mlir/lib/Conversion/VectorToGPU/VectorToGPU.cpp
    mlir/lib/Conversion/VectorToSCF/VectorToSCF.cpp
    mlir/lib/Dialect/Affine/Transforms/AffineDataCopyGeneration.cpp
    mlir/lib/Dialect/Affine/Transforms/AffineLoopInvariantCodeMotion.cpp
    mlir/lib/Dialect/Affine/Transforms/AffineLoopNormalize.cpp
    mlir/lib/Dialect/Affine/Transforms/AffineParallelize.cpp
    mlir/lib/Dialect/Affine/Transforms/AffineScalarReplacement.cpp
    mlir/lib/Dialect/Affine/Transforms/LoopTiling.cpp
    mlir/lib/Dialect/Affine/Transforms/LoopUnroll.cpp
    mlir/lib/Dialect/Affine/Transforms/LoopUnrollAndJam.cpp
    mlir/lib/Dialect/Affine/Transforms/SimplifyAffineStructures.cpp
    mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp
    mlir/lib/Dialect/Arithmetic/Transforms/Bufferize.cpp
    mlir/lib/Dialect/Arithmetic/Transforms/ExpandOps.cpp
    mlir/lib/Dialect/Bufferization/Transforms/BufferDeallocation.cpp
    mlir/lib/Dialect/Bufferization/Transforms/Bufferize.cpp
    mlir/lib/Dialect/GPU/Transforms/AsyncRegionRewriter.cpp
    mlir/lib/Dialect/Linalg/Transforms/Generalization.cpp
    mlir/lib/Dialect/Linalg/Transforms/InlineScalarOperands.cpp
    mlir/lib/Dialect/Linalg/Transforms/LinalgStrategyPasses.cpp
    mlir/lib/Dialect/Linalg/Transforms/Loops.cpp
    mlir/lib/Dialect/Linalg/Transforms/Promotion.cpp
    mlir/lib/Dialect/Linalg/Transforms/Tiling.cpp
    mlir/lib/Dialect/Quant/Transforms/ConvertConst.cpp
    mlir/lib/Dialect/Quant/Transforms/ConvertSimQuant.cpp
    mlir/lib/Dialect/SCF/Transforms/Bufferize.cpp
    mlir/lib/Dialect/SCF/Transforms/ForToWhile.cpp
    mlir/lib/Dialect/SCF/Transforms/LoopCanonicalization.cpp
    mlir/lib/Dialect/SCF/Transforms/LoopSpecialization.cpp
    mlir/lib/Dialect/SCF/Transforms/ParallelLoopTiling.cpp
    mlir/lib/Dialect/Shape/Transforms/Bufferize.cpp
    mlir/lib/Dialect/Shape/Transforms/RemoveShapeConstraints.cpp
    mlir/lib/Dialect/Shape/Transforms/ShapeToShapeLowering.cpp
    mlir/lib/Dialect/StandardOps/Transforms/Bufferize.cpp
    mlir/lib/Dialect/StandardOps/Transforms/ExpandOps.cpp
    mlir/lib/Dialect/Tensor/Transforms/Bufferize.cpp
    mlir/lib/Dialect/Tosa/Transforms/TosaInferShapes.cpp
    mlir/lib/Dialect/Tosa/Transforms/TosaMakeBroadcastable.cpp
    mlir/lib/Dialect/Tosa/Transforms/TosaOptionalDecompositions.cpp
    mlir/lib/Transforms/BufferOptimizations.cpp
    mlir/lib/Transforms/LoopCoalescing.cpp
    mlir/lib/Transforms/LoopFusion.cpp
    mlir/lib/Transforms/PipelineDataTransfer.cpp
    mlir/test/lib/Analysis/TestLiveness.cpp
    mlir/test/lib/Analysis/TestMatchReduction.cpp
    mlir/test/lib/Analysis/TestMemRefBoundCheck.cpp
    mlir/test/lib/Analysis/TestMemRefDependenceCheck.cpp
    mlir/test/lib/Analysis/TestMemRefStrideCalculation.cpp
    mlir/test/lib/Analysis/TestSlice.cpp
    mlir/test/lib/Dialect/Affine/TestAffineDataCopy.cpp
    mlir/test/lib/Dialect/Affine/TestAffineLoopParametricTiling.cpp
    mlir/test/lib/Dialect/Affine/TestAffineLoopUnswitching.cpp
    mlir/test/lib/Dialect/Affine/TestLoopPermutation.cpp
    mlir/test/lib/Dialect/Affine/TestVectorizationUtils.cpp
    mlir/test/lib/Dialect/DLTI/TestDataLayoutQuery.cpp
    mlir/test/lib/Dialect/Linalg/TestComprehensiveBufferize.cpp
    mlir/test/lib/Dialect/Linalg/TestLinalgCodegenStrategy.cpp
    mlir/test/lib/Dialect/Linalg/TestLinalgDistribution.cpp
    mlir/test/lib/Dialect/Linalg/TestLinalgElementwiseFusion.cpp
    mlir/test/lib/Dialect/Linalg/TestLinalgFusionTransforms.cpp
    mlir/test/lib/Dialect/Linalg/TestLinalgHoisting.cpp
    mlir/test/lib/Dialect/Linalg/TestLinalgTransforms.cpp
    mlir/test/lib/Dialect/Linalg/TestPadFusion.cpp
    mlir/test/lib/Dialect/Math/TestAlgebraicSimplification.cpp
    mlir/test/lib/Dialect/Math/TestExpandTanh.cpp
    mlir/test/lib/Dialect/Math/TestPolynomialApproximation.cpp
    mlir/test/lib/Dialect/SCF/TestSCFUtils.cpp
    mlir/test/lib/Dialect/SPIRV/TestAvailability.cpp
    mlir/test/lib/Dialect/StandardOps/TestComposeSubView.cpp
    mlir/test/lib/Dialect/Test/TestPatterns.cpp
    mlir/test/lib/Dialect/Test/TestTraits.cpp
    mlir/test/lib/Dialect/Tosa/TosaTestPasses.cpp
    mlir/test/lib/Dialect/Vector/TestVectorTransforms.cpp
    mlir/test/lib/IR/TestDominance.cpp
    mlir/test/lib/IR/TestMatchers.cpp
    mlir/test/lib/IR/TestTypes.cpp
    mlir/test/lib/Pass/TestPassManager.cpp
    mlir/test/lib/Transforms/TestConstantFold.cpp
    mlir/test/lib/Transforms/TestInlining.cpp
    mlir/test/lib/Transforms/TestLoopFusion.cpp
    mlir/test/lib/Transforms/TestLoopMapping.cpp
    mlir/test/lib/Transforms/TestLoopParametricTiling.cpp
    mlir/test/lib/Transforms/TestLoopUnrolling.cpp
    mlir/unittests/Pass/PassManagerTest.cpp

Removed: 
    


################################################################################
diff  --git a/mlir/docs/Bufferization.md b/mlir/docs/Bufferization.md
index e00cc3a8b5da4..f1ccff783e606 100644
--- a/mlir/docs/Bufferization.md
+++ b/mlir/docs/Bufferization.md
@@ -163,7 +163,7 @@ void mlir::populateTensorBufferizePatterns(
 }
 
 struct TensorBufferizePass : public TensorBufferizeBase<TensorBufferizePass> {
-  void runOnFunction() override {
+  void runOnOperation() override {
     auto *context = &getContext();
     BufferizeTypeConverter typeConverter;
     RewritePatternSet patterns(context);
@@ -174,7 +174,7 @@ struct TensorBufferizePass : public TensorBufferizeBase<TensorBufferizePass> {
     target.addLegalDialect<StandardOpsDialect>();
 
     if (failed(
-            applyPartialConversion(getFunction(), target, std::move(patterns))))
+            applyPartialConversion(getOperation(), target, std::move(patterns))))
       signalPassFailure();
   }
 };

diff  --git a/mlir/docs/Rationale/Rationale.md b/mlir/docs/Rationale/Rationale.md
index 32f5ea3abfcfd..0f19c2a812ce0 100644
--- a/mlir/docs/Rationale/Rationale.md
+++ b/mlir/docs/Rationale/Rationale.md
@@ -1054,12 +1054,12 @@ design choices:
 
 1.  MLIR makes use of extensive uniqued immutable data structures (affine
     expressions, types, etc are all immutable, uniqued, and immortal).
-2.  Constants are defined in per-function pools, instead of being globally
+2.  Constants are defined in per-operation pools, instead of being globally
     uniqued.
-3.  Functions themselves are not SSA values either, so they don't have the same
-    problem as constants.
-4.  FunctionPasses are copied (through their copy ctor) into one instance per
+3.  Functions, and other global-like operations, themselves are not SSA values
+    either, so they don't have the same problem as constants.
+4.  Passes are copied (through their copy ctor) into one instance per
     thread, avoiding sharing of local state across threads.
 
-This allows MLIR function passes to support efficient multithreaded compilation
+This allows MLIR passes to support efficient multithreaded compilation
 and code generation.

diff  --git a/mlir/docs/Tutorials/Toy/Ch-4.md b/mlir/docs/Tutorials/Toy/Ch-4.md
index 78cdfec4e4b2f..134fd2675fdb0 100644
--- a/mlir/docs/Tutorials/Toy/Ch-4.md
+++ b/mlir/docs/Tutorials/Toy/Ch-4.md
@@ -356,20 +356,20 @@ void MulOp::inferShapes() { getResult().setType(getOperand(0).getType()); }
 ```
 
 At this point, each of the necessary Toy operations provide a mechanism by which
-to infer their output shapes. The ShapeInferencePass is a FunctionPass: it will
-run on each Function in isolation. MLIR also supports general
-[OperationPasses](../../PassManagement.md/#operation-pass) that run on any isolated
-operation (i.e. other function-like operations), but here our module only
-contains functions, so there is no need to generalize to all operations.
+to infer their output shapes. The ShapeInferencePass will operate on functions:
+it will run on each Function in isolation. MLIR also supports general
+[OperationPasses](../../PassManagement.md#operation-pass) that run on any
+isolated operation (i.e. other function-like operations), but here our module
+only contains functions, so there is no need to generalize to all operations.
 
 Implementing such a pass is done by creating a class inheriting from
-`mlir::FunctionPass` and overriding the `runOnFunction()` method.
+`mlir::OperationPass<FuncOp>` and overriding the `runOnOperation()` method.
 
 ```c++
 class ShapeInferencePass
-    : public mlir::PassWrapper<ShapeInferencePass, FunctionPass> {
-  void runOnFunction() override {
-    FuncOp function = getFunction();
+    : public mlir::PassWrapper<ShapeInferencePass, OperationPass<FuncOp>> {
+  void runOnOperation() override {
+    FuncOp function = getOperation();
     ...
   }
 };

diff  --git a/mlir/docs/Tutorials/Toy/Ch-5.md b/mlir/docs/Tutorials/Toy/Ch-5.md
index 20cb4967d4c00..b5ab60628a359 100644
--- a/mlir/docs/Tutorials/Toy/Ch-5.md
+++ b/mlir/docs/Tutorials/Toy/Ch-5.md
@@ -56,7 +56,7 @@ for further optimization. To start off the lowering, we first define our
 conversion target:
 
 ```c++
-void ToyToAffineLoweringPass::runOnFunction() {
+void ToyToAffineLoweringPass::runOnOperation() {
   // The first thing to define is the conversion target. This will define the
   // final target for this lowering.
   mlir::ConversionTarget target(getContext());
@@ -147,7 +147,7 @@ struct TransposeOpLowering : public mlir::ConversionPattern {
 Now we can prepare the list of patterns to use during the lowering process:
 
 ```c++
-void ToyToAffineLoweringPass::runOnFunction() {
+void ToyToAffineLoweringPass::runOnOperation() {
   ...
 
   // Now that the conversion target has been defined, we just need to provide
@@ -166,13 +166,13 @@ for our purposes, we will perform a partial lowering, as we will not convert
 `toy.print` at this time.
 
 ```c++
-void ToyToAffineLoweringPass::runOnFunction() {
+void ToyToAffineLoweringPass::runOnOperation() {
   ...
 
   // With the target and rewrite patterns defined, we can now attempt the
   // conversion. The conversion will signal failure if any of our *illegal*
   // operations were not converted successfully.
-  auto function = getFunction();
+  mlir::FuncOp function = getOperation();
   if (mlir::failed(mlir::applyPartialConversion(function, target, patterns)))
     signalPassFailure();
 }

diff  --git a/mlir/examples/toy/Ch4/mlir/ShapeInferencePass.cpp b/mlir/examples/toy/Ch4/mlir/ShapeInferencePass.cpp
index d35679cb55cee..49ce1a521128a 100644
--- a/mlir/examples/toy/Ch4/mlir/ShapeInferencePass.cpp
+++ b/mlir/examples/toy/Ch4/mlir/ShapeInferencePass.cpp
@@ -28,7 +28,7 @@ using namespace toy;
 #include "toy/ShapeInferenceOpInterfaces.cpp.inc"
 
 namespace {
-/// The ShapeInferencePass is a FunctionPass that performs intra-procedural
+/// The ShapeInferencePass is a pass that performs intra-procedural
 /// shape inference.
 ///
 ///    Algorithm:
@@ -45,10 +45,10 @@ namespace {
 ///   3) If the worklist is empty, the algorithm succeeded.
 ///
 class ShapeInferencePass
-    : public mlir::PassWrapper<ShapeInferencePass, FunctionPass> {
+    : public mlir::PassWrapper<ShapeInferencePass, OperationPass<FuncOp>> {
 public:
-  void runOnFunction() override {
-    auto f = getFunction();
+  void runOnOperation() override {
+    auto f = getOperation();
 
     // Populate the worklist with the operations that need shape inference:
     // these are operations that return a dynamic shape.

diff  --git a/mlir/examples/toy/Ch5/mlir/LowerToAffineLoops.cpp b/mlir/examples/toy/Ch5/mlir/LowerToAffineLoops.cpp
index 8ac869df8c666..545a71445ac7c 100644
--- a/mlir/examples/toy/Ch5/mlir/LowerToAffineLoops.cpp
+++ b/mlir/examples/toy/Ch5/mlir/LowerToAffineLoops.cpp
@@ -277,16 +277,16 @@ struct TransposeOpLowering : public ConversionPattern {
 /// rest of the code in the Toy dialect.
 namespace {
 struct ToyToAffineLoweringPass
-    : public PassWrapper<ToyToAffineLoweringPass, FunctionPass> {
+    : public PassWrapper<ToyToAffineLoweringPass, OperationPass<FuncOp>> {
   void getDependentDialects(DialectRegistry &registry) const override {
     registry.insert<AffineDialect, memref::MemRefDialect, StandardOpsDialect>();
   }
-  void runOnFunction() final;
+  void runOnOperation() final;
 };
 } // namespace
 
-void ToyToAffineLoweringPass::runOnFunction() {
-  auto function = getFunction();
+void ToyToAffineLoweringPass::runOnOperation() {
+  FuncOp function = getOperation();
 
   // We only lower the main function as we expect that all other functions have
   // been inlined.
@@ -332,7 +332,7 @@ void ToyToAffineLoweringPass::runOnFunction() {
   // conversion. The conversion will signal failure if any of our `illegal`
   // operations were not converted successfully.
   if (failed(
-          applyPartialConversion(getFunction(), target, std::move(patterns))))
+          applyPartialConversion(getOperation(), target, std::move(patterns))))
     signalPassFailure();
 }
 

diff  --git a/mlir/examples/toy/Ch5/mlir/ShapeInferencePass.cpp b/mlir/examples/toy/Ch5/mlir/ShapeInferencePass.cpp
index d35679cb55cee..49ce1a521128a 100644
--- a/mlir/examples/toy/Ch5/mlir/ShapeInferencePass.cpp
+++ b/mlir/examples/toy/Ch5/mlir/ShapeInferencePass.cpp
@@ -28,7 +28,7 @@ using namespace toy;
 #include "toy/ShapeInferenceOpInterfaces.cpp.inc"
 
 namespace {
-/// The ShapeInferencePass is a FunctionPass that performs intra-procedural
+/// The ShapeInferencePass is a pass that performs intra-procedural
 /// shape inference.
 ///
 ///    Algorithm:
@@ -45,10 +45,10 @@ namespace {
 ///   3) If the worklist is empty, the algorithm succeeded.
 ///
 class ShapeInferencePass
-    : public mlir::PassWrapper<ShapeInferencePass, FunctionPass> {
+    : public mlir::PassWrapper<ShapeInferencePass, OperationPass<FuncOp>> {
 public:
-  void runOnFunction() override {
-    auto f = getFunction();
+  void runOnOperation() override {
+    auto f = getOperation();
 
     // Populate the worklist with the operations that need shape inference:
     // these are operations that return a dynamic shape.

diff  --git a/mlir/examples/toy/Ch6/mlir/LowerToAffineLoops.cpp b/mlir/examples/toy/Ch6/mlir/LowerToAffineLoops.cpp
index 8ac869df8c666..78de920c2a257 100644
--- a/mlir/examples/toy/Ch6/mlir/LowerToAffineLoops.cpp
+++ b/mlir/examples/toy/Ch6/mlir/LowerToAffineLoops.cpp
@@ -277,16 +277,16 @@ struct TransposeOpLowering : public ConversionPattern {
 /// rest of the code in the Toy dialect.
 namespace {
 struct ToyToAffineLoweringPass
-    : public PassWrapper<ToyToAffineLoweringPass, FunctionPass> {
+    : public PassWrapper<ToyToAffineLoweringPass, OperationPass<FuncOp>> {
   void getDependentDialects(DialectRegistry &registry) const override {
     registry.insert<AffineDialect, memref::MemRefDialect, StandardOpsDialect>();
   }
-  void runOnFunction() final;
+  void runOnOperation() final;
 };
 } // namespace
 
-void ToyToAffineLoweringPass::runOnFunction() {
-  auto function = getFunction();
+void ToyToAffineLoweringPass::runOnOperation() {
+  auto function = getOperation();
 
   // We only lower the main function as we expect that all other functions have
   // been inlined.
@@ -332,7 +332,7 @@ void ToyToAffineLoweringPass::runOnFunction() {
   // conversion. The conversion will signal failure if any of our `illegal`
   // operations were not converted successfully.
   if (failed(
-          applyPartialConversion(getFunction(), target, std::move(patterns))))
+          applyPartialConversion(getOperation(), target, std::move(patterns))))
     signalPassFailure();
 }
 

diff  --git a/mlir/examples/toy/Ch6/mlir/ShapeInferencePass.cpp b/mlir/examples/toy/Ch6/mlir/ShapeInferencePass.cpp
index d35679cb55cee..49ce1a521128a 100644
--- a/mlir/examples/toy/Ch6/mlir/ShapeInferencePass.cpp
+++ b/mlir/examples/toy/Ch6/mlir/ShapeInferencePass.cpp
@@ -28,7 +28,7 @@ using namespace toy;
 #include "toy/ShapeInferenceOpInterfaces.cpp.inc"
 
 namespace {
-/// The ShapeInferencePass is a FunctionPass that performs intra-procedural
+/// The ShapeInferencePass is a pass that performs intra-procedural
 /// shape inference.
 ///
 ///    Algorithm:
@@ -45,10 +45,10 @@ namespace {
 ///   3) If the worklist is empty, the algorithm succeeded.
 ///
 class ShapeInferencePass
-    : public mlir::PassWrapper<ShapeInferencePass, FunctionPass> {
+    : public mlir::PassWrapper<ShapeInferencePass, OperationPass<FuncOp>> {
 public:
-  void runOnFunction() override {
-    auto f = getFunction();
+  void runOnOperation() override {
+    auto f = getOperation();
 
     // Populate the worklist with the operations that need shape inference:
     // these are operations that return a dynamic shape.

diff  --git a/mlir/examples/toy/Ch7/mlir/LowerToAffineLoops.cpp b/mlir/examples/toy/Ch7/mlir/LowerToAffineLoops.cpp
index 8ac869df8c666..78de920c2a257 100644
--- a/mlir/examples/toy/Ch7/mlir/LowerToAffineLoops.cpp
+++ b/mlir/examples/toy/Ch7/mlir/LowerToAffineLoops.cpp
@@ -277,16 +277,16 @@ struct TransposeOpLowering : public ConversionPattern {
 /// rest of the code in the Toy dialect.
 namespace {
 struct ToyToAffineLoweringPass
-    : public PassWrapper<ToyToAffineLoweringPass, FunctionPass> {
+    : public PassWrapper<ToyToAffineLoweringPass, OperationPass<FuncOp>> {
   void getDependentDialects(DialectRegistry &registry) const override {
     registry.insert<AffineDialect, memref::MemRefDialect, StandardOpsDialect>();
   }
-  void runOnFunction() final;
+  void runOnOperation() final;
 };
 } // namespace
 
-void ToyToAffineLoweringPass::runOnFunction() {
-  auto function = getFunction();
+void ToyToAffineLoweringPass::runOnOperation() {
+  auto function = getOperation();
 
   // We only lower the main function as we expect that all other functions have
   // been inlined.
@@ -332,7 +332,7 @@ void ToyToAffineLoweringPass::runOnFunction() {
   // conversion. The conversion will signal failure if any of our `illegal`
   // operations were not converted successfully.
   if (failed(
-          applyPartialConversion(getFunction(), target, std::move(patterns))))
+          applyPartialConversion(getOperation(), target, std::move(patterns))))
     signalPassFailure();
 }
 

diff  --git a/mlir/examples/toy/Ch7/mlir/ShapeInferencePass.cpp b/mlir/examples/toy/Ch7/mlir/ShapeInferencePass.cpp
index d35679cb55cee..49ce1a521128a 100644
--- a/mlir/examples/toy/Ch7/mlir/ShapeInferencePass.cpp
+++ b/mlir/examples/toy/Ch7/mlir/ShapeInferencePass.cpp
@@ -28,7 +28,7 @@ using namespace toy;
 #include "toy/ShapeInferenceOpInterfaces.cpp.inc"
 
 namespace {
-/// The ShapeInferencePass is a FunctionPass that performs intra-procedural
+/// The ShapeInferencePass is a pass that performs intra-procedural
 /// shape inference.
 ///
 ///    Algorithm:
@@ -45,10 +45,10 @@ namespace {
 ///   3) If the worklist is empty, the algorithm succeeded.
 ///
 class ShapeInferencePass
-    : public mlir::PassWrapper<ShapeInferencePass, FunctionPass> {
+    : public mlir::PassWrapper<ShapeInferencePass, OperationPass<FuncOp>> {
 public:
-  void runOnFunction() override {
-    auto f = getFunction();
+  void runOnOperation() override {
+    auto f = getOperation();
 
     // Populate the worklist with the operations that need shape inference:
     // these are operations that return a dynamic shape.

diff  --git a/mlir/include/mlir/Conversion/Passes.td b/mlir/include/mlir/Conversion/Passes.td
index 4d1f383c02294..1133db2b8bb24 100644
--- a/mlir/include/mlir/Conversion/Passes.td
+++ b/mlir/include/mlir/Conversion/Passes.td
@@ -78,7 +78,7 @@ def ConvertAffineToStandard : Pass<"lower-affine"> {
 // ArithmeticToLLVM
 //===----------------------------------------------------------------------===//
 
-def ConvertArithmeticToLLVM : FunctionPass<"convert-arith-to-llvm"> {
+def ConvertArithmeticToLLVM : Pass<"convert-arith-to-llvm", "FuncOp"> {
   let summary = "Convert Arithmetic dialect to LLVM dialect";
   let description = [{
     This pass converts supported Arithmetic ops to LLVM dialect instructions.
@@ -96,7 +96,7 @@ def ConvertArithmeticToLLVM : FunctionPass<"convert-arith-to-llvm"> {
 // ArithmeticToSPIRV
 //===----------------------------------------------------------------------===//
 
-def ConvertArithmeticToSPIRV : FunctionPass<"convert-arith-to-spirv"> {
+def ConvertArithmeticToSPIRV : Pass<"convert-arith-to-spirv", "FuncOp"> {
   let summary = "Convert Arithmetic dialect to SPIR-V dialect";
   let constructor = "mlir::arith::createConvertArithmeticToSPIRVPass()";
   let dependentDialects = ["spirv::SPIRVDialect"];
@@ -175,7 +175,7 @@ def ConvertComplexToLLVM : Pass<"convert-complex-to-llvm", "ModuleOp"> {
 // ComplexToStandard
 //===----------------------------------------------------------------------===//
 
-def ConvertComplexToStandard : FunctionPass<"convert-complex-to-standard"> {
+def ConvertComplexToStandard : Pass<"convert-complex-to-standard", "FuncOp"> {
   let summary = "Convert Complex dialect to standard dialect";
   let constructor = "mlir::createConvertComplexToStandardPass()";
   let dependentDialects = ["math::MathDialect"];
@@ -343,7 +343,7 @@ def ConvertMathToLibm : Pass<"convert-math-to-libm", "ModuleOp"> {
 // MathToLLVM
 //===----------------------------------------------------------------------===//
 
-def ConvertMathToLLVM : FunctionPass<"convert-math-to-llvm"> {
+def ConvertMathToLLVM : Pass<"convert-math-to-llvm", "FuncOp"> {
   let summary = "Convert Math dialect to LLVM dialect";
   let description = [{
     This pass converts supported Math ops to LLVM dialect intrinsics.
@@ -503,7 +503,7 @@ def SCFToStandard : Pass<"convert-scf-to-std"> {
 // SCFToGPU
 //===----------------------------------------------------------------------===//
 
-def ConvertAffineForToGPU : FunctionPass<"convert-affine-for-to-gpu"> {
+def ConvertAffineForToGPU : Pass<"convert-affine-for-to-gpu", "FuncOp"> {
   let summary = "Convert top-level AffineFor Ops to GPU kernels";
   let constructor = "mlir::createAffineForToGPUPass()";
   let dependentDialects = ["gpu::GPUDialect"];
@@ -635,7 +635,7 @@ def ConvertStandardToSPIRV : Pass<"convert-std-to-spirv", "ModuleOp"> {
 // TosaToLinalg
 //===----------------------------------------------------------------------===//
 
-def TosaToLinalg : FunctionPass<"tosa-to-linalg"> {
+def TosaToLinalg : Pass<"tosa-to-linalg", "FuncOp"> {
   let summary = "Lower TOSA to LinAlg on tensors";
   let description = [{
     Pass that converts TOSA operations to the equivalent operations using the
@@ -649,7 +649,7 @@ def TosaToLinalg : FunctionPass<"tosa-to-linalg"> {
 // TosaToLinalgNamed
 //===----------------------------------------------------------------------===//
 
-def TosaToLinalgNamed : FunctionPass<"tosa-to-linalg-named"> {
+def TosaToLinalgNamed : Pass<"tosa-to-linalg-named", "FuncOp"> {
   let summary = "Lower TOSA to LinAlg named operations";
   let description = [{
     Pass that converts TOSA operations to the equivalent operations using the
@@ -697,7 +697,7 @@ def TosaToStandard : Pass<"tosa-to-standard"> {
 // VectorToGPU
 //===----------------------------------------------------------------------===//
 
-def ConvertVectorToGPU : FunctionPass<"convert-vector-to-gpu"> {
+def ConvertVectorToGPU : Pass<"convert-vector-to-gpu", "FuncOp"> {
   let summary = "Lower the operations from the vector dialect into the GPU "
                 "dialect";
   let constructor = "mlir::createConvertVectorToGPUPass()";
@@ -711,7 +711,7 @@ def ConvertVectorToGPU : FunctionPass<"convert-vector-to-gpu"> {
 // VectorToSCF
 //===----------------------------------------------------------------------===//
 
-def ConvertVectorToSCF : FunctionPass<"convert-vector-to-scf"> {
+def ConvertVectorToSCF : Pass<"convert-vector-to-scf", "FuncOp"> {
   let summary = "Lower the operations from the vector dialect into the SCF "
                 "dialect";
   let constructor = "mlir::createConvertVectorToSCFPass()";

diff  --git a/mlir/include/mlir/Dialect/Affine/Passes.h b/mlir/include/mlir/Dialect/Affine/Passes.h
index bf7ea08f4ee0a..e4f6d2034902f 100644
--- a/mlir/include/mlir/Dialect/Affine/Passes.h
+++ b/mlir/include/mlir/Dialect/Affine/Passes.h
@@ -51,7 +51,7 @@ std::unique_ptr<OperationPass<FuncOp>> createAffineDataCopyGenerationPass();
 /// Creates a pass to replace affine memref accesses by scalars using store to
 /// load forwarding and redundant load elimination; consequently also eliminate
 /// dead allocs.
-std::unique_ptr<FunctionPass> createAffineScalarReplacementPass();
+std::unique_ptr<OperationPass<FuncOp>> createAffineScalarReplacementPass();
 
 /// Creates a pass to perform tiling on loop nests.
 std::unique_ptr<OperationPass<FuncOp>>

diff  --git a/mlir/include/mlir/Dialect/Affine/Passes.td b/mlir/include/mlir/Dialect/Affine/Passes.td
index f87d084ff78bd..8ec4b84ea5ca0 100644
--- a/mlir/include/mlir/Dialect/Affine/Passes.td
+++ b/mlir/include/mlir/Dialect/Affine/Passes.td
@@ -15,7 +15,7 @@
 
 include "mlir/Pass/PassBase.td"
 
-def AffineDataCopyGeneration : FunctionPass<"affine-data-copy-generate"> {
+def AffineDataCopyGeneration : Pass<"affine-data-copy-generate", "FuncOp"> {
   let summary = "Generate explicit copying for affine memory operations";
   let constructor = "mlir::createAffineDataCopyGenerationPass()";
   let dependentDialects = ["memref::MemRefDialect"];
@@ -44,12 +44,12 @@ def AffineDataCopyGeneration : FunctionPass<"affine-data-copy-generate"> {
 }
 
 def AffineLoopInvariantCodeMotion
-    : FunctionPass<"affine-loop-invariant-code-motion"> {
+    : Pass<"affine-loop-invariant-code-motion", "FuncOp"> {
   let summary = "Hoist loop invariant instructions outside of affine loops";
   let constructor = "mlir::createAffineLoopInvariantCodeMotionPass()";
 }
 
-def AffineLoopTiling : FunctionPass<"affine-loop-tile"> {
+def AffineLoopTiling : Pass<"affine-loop-tile", "FuncOp"> {
   let summary = "Tile affine loop nests";
   let constructor = "mlir::createLoopTilingPass()";
   let options = [
@@ -66,7 +66,7 @@ def AffineLoopTiling : FunctionPass<"affine-loop-tile"> {
   ];
 }
 
-def AffineLoopUnroll : FunctionPass<"affine-loop-unroll"> {
+def AffineLoopUnroll : Pass<"affine-loop-unroll", "FuncOp"> {
   let summary = "Unroll affine loops";
   let constructor = "mlir::createLoopUnrollPass()";
   let options = [
@@ -84,7 +84,7 @@ def AffineLoopUnroll : FunctionPass<"affine-loop-unroll"> {
   ];
 }
 
-def AffineLoopUnrollAndJam : FunctionPass<"affine-loop-unroll-jam"> {
+def AffineLoopUnrollAndJam : Pass<"affine-loop-unroll-jam", "FuncOp"> {
   let summary = "Unroll and jam affine loops";
   let constructor = "mlir::createLoopUnrollAndJamPass()";
   let options = [
@@ -94,7 +94,7 @@ def AffineLoopUnrollAndJam : FunctionPass<"affine-loop-unroll-jam"> {
   ];
 }
 
-def AffineScalarReplacement : FunctionPass<"affine-scalrep"> {
+def AffineScalarReplacement : Pass<"affine-scalrep", "FuncOp"> {
   let summary = "Replace affine memref acceses by scalars by forwarding stores "
                 "to loads and eliminating redundant loads";
   let description = [{
@@ -140,7 +140,7 @@ def AffineScalarReplacement : FunctionPass<"affine-scalrep"> {
   let constructor = "mlir::createAffineScalarReplacementPass()";
 }
 
-def AffineVectorize : FunctionPass<"affine-super-vectorize"> {
+def AffineVectorize : Pass<"affine-super-vectorize", "FuncOp"> {
   let summary = "Vectorize to a target independent n-D vector abstraction";
   let constructor = "mlir::createSuperVectorizePass()";
   let dependentDialects = ["vector::VectorDialect"];
@@ -166,7 +166,7 @@ def AffineVectorize : FunctionPass<"affine-super-vectorize"> {
   ];
 }
 
-def AffineParallelize : FunctionPass<"affine-parallelize"> {
+def AffineParallelize : Pass<"affine-parallelize", "FuncOp"> {
   let summary = "Convert affine.for ops into 1-D affine.parallel";
   let constructor = "mlir::createAffineParallelizePass()";
   let options = [
@@ -179,12 +179,12 @@ def AffineParallelize : FunctionPass<"affine-parallelize"> {
   ];
 }
 
-def AffineLoopNormalize : FunctionPass<"affine-loop-normalize"> {
+def AffineLoopNormalize : Pass<"affine-loop-normalize", "FuncOp"> {
   let summary = "Apply normalization transformations to affine loop-like ops";
   let constructor = "mlir::createAffineLoopNormalizePass()";
 }
 
-def SimplifyAffineStructures : FunctionPass<"simplify-affine-structures"> {
+def SimplifyAffineStructures : Pass<"simplify-affine-structures", "FuncOp"> {
   let summary = "Simplify affine expressions in maps/sets and normalize "
                 "memrefs";
   let constructor = "mlir::createSimplifyAffineStructuresPass()";

diff  --git a/mlir/include/mlir/Dialect/Arithmetic/Transforms/Passes.td b/mlir/include/mlir/Dialect/Arithmetic/Transforms/Passes.td
index 6bf61133b85b6..d4fe952b7f12e 100644
--- a/mlir/include/mlir/Dialect/Arithmetic/Transforms/Passes.td
+++ b/mlir/include/mlir/Dialect/Arithmetic/Transforms/Passes.td
@@ -11,14 +11,14 @@
 
 include "mlir/Pass/PassBase.td"
 
-def ArithmeticBufferize : FunctionPass<"arith-bufferize"> {
+def ArithmeticBufferize : Pass<"arith-bufferize", "FuncOp"> {
   let summary = "Bufferize Arithmetic dialect ops.";
   let constructor = "mlir::arith::createArithmeticBufferizePass()";
   let dependentDialects = ["bufferization::BufferizationDialect",
                            "memref::MemRefDialect"];
 }
 
-def ArithmeticExpandOps : FunctionPass<"arith-expand"> {
+def ArithmeticExpandOps : Pass<"arith-expand", "FuncOp"> {
   let summary = "Legalize Arithmetic ops to be convertible to LLVM.";
   let constructor = "mlir::arith::createArithmeticExpandOpsPass()";
   let dependentDialects = ["StandardOpsDialect"];

diff  --git a/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.h b/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.h
index 78873cf58fcb1..72c5136eb1988 100644
--- a/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.h
+++ b/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.h
@@ -16,7 +16,7 @@ std::unique_ptr<Pass> createBufferDeallocationPass();
 
 /// Creates a pass that finalizes a partial bufferization by removing remaining
 /// bufferization.to_tensor and bufferization.to_memref operations.
-std::unique_ptr<FunctionPass> createFinalizingBufferizePass();
+std::unique_ptr<OperationPass<FuncOp>> createFinalizingBufferizePass();
 
 //===----------------------------------------------------------------------===//
 // Registration

diff  --git a/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.td b/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.td
index f128cc5467958..f37e2611579f1 100644
--- a/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.td
+++ b/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.td
@@ -11,7 +11,7 @@
 
 include "mlir/Pass/PassBase.td"
 
-def BufferDeallocation : FunctionPass<"buffer-deallocation"> {
+def BufferDeallocation : Pass<"buffer-deallocation", "FuncOp"> {
   let summary = "Adds all required dealloc operations for all allocations in "
                 "the input program";
   let description = [{
@@ -88,7 +88,7 @@ def BufferDeallocation : FunctionPass<"buffer-deallocation"> {
   let constructor = "mlir::bufferization::createBufferDeallocationPass()";
 }
 
-def FinalizingBufferize : FunctionPass<"finalizing-bufferize"> {
+def FinalizingBufferize : Pass<"finalizing-bufferize", "FuncOp"> {
   let summary = "Finalize a partial bufferization";
   let description = [{
     A bufferize pass that finalizes a partial bufferization by removing

diff  --git a/mlir/include/mlir/Dialect/GPU/Passes.td b/mlir/include/mlir/Dialect/GPU/Passes.td
index 4c0d54b8801a4..eaabc6ea36012 100644
--- a/mlir/include/mlir/Dialect/GPU/Passes.td
+++ b/mlir/include/mlir/Dialect/GPU/Passes.td
@@ -17,7 +17,7 @@ def GpuKernelOutlining : Pass<"gpu-kernel-outlining", "ModuleOp"> {
   let dependentDialects = ["mlir::DLTIDialect"];
 }
 
-def GpuAsyncRegionPass : FunctionPass<"gpu-async-region"> {
+def GpuAsyncRegionPass : Pass<"gpu-async-region", "FuncOp"> {
   let summary = "Make GPU ops async";
   let constructor = "mlir::createGpuAsyncRegionPass()";
   let dependentDialects = ["async::AsyncDialect"];

diff  --git a/mlir/include/mlir/Dialect/Linalg/Passes.td b/mlir/include/mlir/Dialect/Linalg/Passes.td
index b2befd03a3b50..aba2fb7e0db64 100644
--- a/mlir/include/mlir/Dialect/Linalg/Passes.td
+++ b/mlir/include/mlir/Dialect/Linalg/Passes.td
@@ -114,7 +114,7 @@ def LinalgNamedOpConversion: Pass<"linalg-named-op-conversion"> {
 }
 
 def LinalgLowerTiledLoopsToSCF
-    : FunctionPass<"convert-linalg-tiled-loops-to-scf"> {
+    : Pass<"convert-linalg-tiled-loops-to-scf", "FuncOp"> {
   let summary = "Lower linalg tiled loops to SCF loops and parallel loops";
   let constructor = "mlir::createConvertLinalgTiledLoopsToSCFPass()";
   let dependentDialects = [
@@ -124,7 +124,7 @@ def LinalgLowerTiledLoopsToSCF
   ];
 }
 
-def LinalgInlineScalarOperands : FunctionPass<"linalg-inline-scalar-operands"> {
+def LinalgInlineScalarOperands : Pass<"linalg-inline-scalar-operands", "FuncOp"> {
   let summary = "Inline scalar operands into linalg generic ops";
   let constructor = "mlir::createLinalgInlineScalarOperandsPass()";
   let dependentDialects = [
@@ -132,7 +132,7 @@ def LinalgInlineScalarOperands : FunctionPass<"linalg-inline-scalar-operands"> {
   ];
 }
 
-def LinalgLowerToAffineLoops : FunctionPass<"convert-linalg-to-affine-loops"> {
+def LinalgLowerToAffineLoops : Pass<"convert-linalg-to-affine-loops", "FuncOp"> {
   let summary = "Lower the operations from the linalg dialect into affine "
                 "loops";
   let constructor = "mlir::createConvertLinalgToAffineLoopsPass()";
@@ -140,7 +140,7 @@ def LinalgLowerToAffineLoops : FunctionPass<"convert-linalg-to-affine-loops"> {
     "AffineDialect", "linalg::LinalgDialect", "memref::MemRefDialect"];
 }
 
-def LinalgLowerToLoops : FunctionPass<"convert-linalg-to-loops"> {
+def LinalgLowerToLoops : Pass<"convert-linalg-to-loops", "FuncOp"> {
   let summary = "Lower the operations from the linalg dialect into loops";
   let constructor = "mlir::createConvertLinalgToLoopsPass()";
   let dependentDialects = [
@@ -151,7 +151,7 @@ def LinalgLowerToLoops : FunctionPass<"convert-linalg-to-loops"> {
 }
 
 def LinalgLowerToParallelLoops
-    : FunctionPass<"convert-linalg-to-parallel-loops"> {
+    : Pass<"convert-linalg-to-parallel-loops", "FuncOp"> {
   let summary = "Lower the operations from the linalg dialect into parallel "
                 "loops";
   let constructor = "mlir::createConvertLinalgToParallelLoopsPass()";
@@ -174,7 +174,7 @@ def LinalgBufferize : Pass<"linalg-bufferize", "FuncOp"> {
   ];
 }
 
-def LinalgPromotion : FunctionPass<"linalg-promote-subviews"> {
+def LinalgPromotion : Pass<"linalg-promote-subviews", "FuncOp"> {
   let summary = "Promote subview ops to local buffers";
   let constructor = "mlir::createLinalgPromotionPass()";
   let options = [
@@ -186,7 +186,7 @@ def LinalgPromotion : FunctionPass<"linalg-promote-subviews"> {
   let dependentDialects = ["linalg::LinalgDialect"];
 }
 
-def LinalgTiling : FunctionPass<"linalg-tile"> {
+def LinalgTiling : Pass<"linalg-tile", "FuncOp"> {
   let summary = "Tile operations in the linalg dialect";
   let constructor = "mlir::createLinalgTilingPass()";
   let dependentDialects = [
@@ -208,7 +208,7 @@ def LinalgTiling : FunctionPass<"linalg-tile"> {
   ];
 }
 
-def LinalgGeneralization : FunctionPass<"linalg-generalize-named-ops"> {
+def LinalgGeneralization : Pass<"linalg-generalize-named-ops", "FuncOp"> {
   let summary = "Convert named ops into generic ops";
   let constructor = "mlir::createLinalgGeneralizationPass()";
   let dependentDialects = ["linalg::LinalgDialect"];
@@ -253,7 +253,7 @@ def LinalgDetensorize : Pass<"linalg-detensorize", ""> {
 }
 
 def LinalgStrategyTileAndFusePass
-    : FunctionPass<"linalg-strategy-tile-and-fuse-pass"> {
+    : Pass<"linalg-strategy-tile-and-fuse-pass", "FuncOp"> {
   let summary = "Configurable pass to apply pattern-based tiling and fusion.";
   let constructor = "mlir::createLinalgStrategyTileAndFusePass()";
   let options = [
@@ -265,7 +265,7 @@ def LinalgStrategyTileAndFusePass
 }
 
 def LinalgStrategyTilePass
-    : FunctionPass<"linalg-strategy-tile-pass"> {
+    : Pass<"linalg-strategy-tile-pass", "FuncOp"> {
   let summary = "Configurable pass to apply pattern-based linalg tiling.";
   let constructor = "mlir::createLinalgStrategyTilePass()";
   let dependentDialects = ["linalg::LinalgDialect"];
@@ -278,7 +278,7 @@ def LinalgStrategyTilePass
 }
 
 def LinalgStrategyPadPass
-    : FunctionPass<"linalg-strategy-pad-pass"> {
+    : Pass<"linalg-strategy-pad-pass", "FuncOp"> {
   let summary = "Configurable pass to apply padding and hoisting.";
   let constructor = "mlir::createLinalgStrategyPadPass()";
   let dependentDialects = ["linalg::LinalgDialect"];
@@ -291,7 +291,7 @@ def LinalgStrategyPadPass
 }
 
 def LinalgStrategyPromotePass
-    : FunctionPass<"linalg-strategy-promote-pass"> {
+    : Pass<"linalg-strategy-promote-pass", "FuncOp"> {
   let summary = "Configurable pass to apply pattern-based linalg promotion.";
   let constructor = "mlir::createLinalgStrategyPromotePass()";
   let dependentDialects = ["linalg::LinalgDialect"];
@@ -304,7 +304,7 @@ def LinalgStrategyPromotePass
 }
 
 def LinalgStrategyGeneralizePass
-    : FunctionPass<"linalg-strategy-generalize-pass"> {
+    : Pass<"linalg-strategy-generalize-pass", "FuncOp"> {
   let summary = "Configurable pass to apply pattern-based generalization.";
   let constructor = "mlir::createLinalgStrategyGeneralizePass()";
   let dependentDialects = ["linalg::LinalgDialect"];
@@ -318,7 +318,7 @@ def LinalgStrategyGeneralizePass
 
 // TODO: if/when we need finer control add an anchorOp option.
 def LinalgStrategyDecomposePass
-    : FunctionPass<"linalg-strategy-decompose-pass"> {
+    : Pass<"linalg-strategy-decompose-pass", "FuncOp"> {
   let summary = "Configurable pass to apply pattern-based generalization.";
   let constructor = "mlir::createLinalgStrategyDecomposePass()";
   let dependentDialects = ["linalg::LinalgDialect"];
@@ -329,7 +329,7 @@ def LinalgStrategyDecomposePass
 }
 
 def LinalgStrategyInterchangePass
-    : FunctionPass<"linalg-strategy-interchange-pass"> {
+    : Pass<"linalg-strategy-interchange-pass", "FuncOp"> {
   let summary = "Configurable pass to apply pattern-based iterator interchange.";
   let constructor = "mlir::createLinalgStrategyInterchangePass()";
   let dependentDialects = ["linalg::LinalgDialect"];
@@ -340,7 +340,7 @@ def LinalgStrategyInterchangePass
 }
 
 def LinalgStrategyVectorizePass
-    : FunctionPass<"linalg-strategy-vectorize-pass"> {
+    : Pass<"linalg-strategy-vectorize-pass", "FuncOp"> {
   let summary = "Configurable pass to apply pattern-based linalg vectorization.";
   let constructor = "mlir::createLinalgStrategyVectorizePass()";
   let dependentDialects = ["linalg::LinalgDialect"];
@@ -355,7 +355,7 @@ def LinalgStrategyVectorizePass
 }
 
 def LinalgStrategyEnablePass
-    : FunctionPass<"linalg-strategy-enable-pass"> {
+    : Pass<"linalg-strategy-enable-pass", "FuncOp"> {
   let summary = "Configurable pass to enable the application of other "
     "pattern-based linalg passes.";
   let constructor = "mlir::createLinalgStrategyEnablePass()";
@@ -367,7 +367,7 @@ def LinalgStrategyEnablePass
 }
 
 def LinalgStrategyLowerVectorsPass
-    : FunctionPass<"linalg-strategy-lower-vectors-pass"> {
+    : Pass<"linalg-strategy-lower-vectors-pass", "FuncOp"> {
   let summary = "Configurable pass to lower vector operations.";
   let constructor = "mlir::createLinalgStrategyLowerVectorsPass()";
   let dependentDialects = ["linalg::LinalgDialect"];
@@ -378,7 +378,7 @@ def LinalgStrategyLowerVectorsPass
 }
 
 def LinalgStrategyRemoveMarkersPass
-    : FunctionPass<"linalg-strategy-remove-markers-pass"> {
+    : Pass<"linalg-strategy-remove-markers-pass", "FuncOp"> {
   let summary = "Cleanup pass that drops markers.";
   let constructor = "mlir::createLinalgStrategyRemoveMarkersPass()";
   let dependentDialects = ["linalg::LinalgDialect"];

diff  --git a/mlir/include/mlir/Dialect/Quant/Passes.td b/mlir/include/mlir/Dialect/Quant/Passes.td
index d0ca17ce41bbb..65dfb47d76b04 100644
--- a/mlir/include/mlir/Dialect/Quant/Passes.td
+++ b/mlir/include/mlir/Dialect/Quant/Passes.td
@@ -11,14 +11,14 @@
 
 include "mlir/Pass/PassBase.td"
 
-def QuantConvertConst : FunctionPass<"quant-convert-const"> {
+def QuantConvertConst : Pass<"quant-convert-const", "FuncOp"> {
   let summary = "Converts constants followed by qbarrier to actual quantized "
                 "values";
   let constructor = "mlir::quant::createConvertConstPass()";
 }
 
 def QuantConvertSimulatedQuant
-    : FunctionPass<"quant-convert-simulated-quantization"> {
+    : Pass<"quant-convert-simulated-quantization", "FuncOp"> {
   let summary = "Converts training-time simulated quantization ops to "
                 "corresponding quantize/dequantize casts";
   let constructor = "mlir::quant::createConvertSimulatedQuantPass()";

diff  --git a/mlir/include/mlir/Dialect/SCF/Passes.td b/mlir/include/mlir/Dialect/SCF/Passes.td
index 487b40edc8cf3..52227c2b915a5 100644
--- a/mlir/include/mlir/Dialect/SCF/Passes.td
+++ b/mlir/include/mlir/Dialect/SCF/Passes.td
@@ -11,7 +11,7 @@
 
 include "mlir/Pass/PassBase.td"
 
-def SCFBufferize : FunctionPass<"scf-bufferize"> {
+def SCFBufferize : Pass<"scf-bufferize", "FuncOp"> {
   let summary = "Bufferize the scf dialect.";
   let constructor = "mlir::createSCFBufferizePass()";
   let dependentDialects = ["bufferization::BufferizationDialect",
@@ -21,7 +21,7 @@ def SCFBufferize : FunctionPass<"scf-bufferize"> {
 // Note: Making these canonicalization patterns would require a dependency
 // of the SCF dialect on the Affine/Tensor/MemRef dialects or vice versa.
 def SCFForLoopCanonicalization
-    : FunctionPass<"for-loop-canonicalization"> {
+    : Pass<"for-loop-canonicalization", "FuncOp"> {
   let summary = "Canonicalize operations within scf.for loop bodies";
   let constructor = "mlir::createSCFForLoopCanonicalizationPass()";
   let dependentDialects = ["AffineDialect", "tensor::TensorDialect",
@@ -29,7 +29,7 @@ def SCFForLoopCanonicalization
 }
 
 def SCFForLoopPeeling
-    : FunctionPass<"for-loop-peeling"> {
+    : Pass<"for-loop-peeling", "FuncOp"> {
   let summary = "Peel `for` loops at their upper bounds.";
   let constructor = "mlir::createForLoopPeelingPass()";
   let options = [
@@ -42,7 +42,7 @@ def SCFForLoopPeeling
 }
 
 def SCFForLoopSpecialization
-    : FunctionPass<"for-loop-specialization"> {
+    : Pass<"for-loop-specialization", "FuncOp"> {
   let summary = "Specialize `for` loops for vectorization";
   let constructor = "mlir::createForLoopSpecializationPass()";
 }
@@ -53,12 +53,12 @@ def SCFParallelLoopFusion : Pass<"parallel-loop-fusion"> {
 }
 
 def SCFParallelLoopSpecialization
-    : FunctionPass<"parallel-loop-specialization"> {
+    : Pass<"parallel-loop-specialization", "FuncOp"> {
   let summary = "Specialize parallel loops for vectorization";
   let constructor = "mlir::createParallelLoopSpecializationPass()";
 }
 
-def SCFParallelLoopTiling : FunctionPass<"parallel-loop-tiling"> {
+def SCFParallelLoopTiling : Pass<"parallel-loop-tiling", "FuncOp"> {
   let summary = "Tile parallel loops";
   let constructor = "mlir::createParallelLoopTilingPass()";
   let options = [
@@ -80,7 +80,7 @@ def SCFForLoopRangeFolding
 }
 
 def SCFForToWhileLoop
-    : FunctionPass<"scf-for-to-while"> {
+    : Pass<"scf-for-to-while", "FuncOp"> {
   let summary = "Convert SCF for loops to SCF while loops";
   let constructor = "mlir::createForToWhileLoopPass()";
   let description = [{

diff  --git a/mlir/include/mlir/Dialect/Shape/Transforms/Passes.h b/mlir/include/mlir/Dialect/Shape/Transforms/Passes.h
index 4ed7e0a9b54e8..99c764c8207cc 100644
--- a/mlir/include/mlir/Dialect/Shape/Transforms/Passes.h
+++ b/mlir/include/mlir/Dialect/Shape/Transforms/Passes.h
@@ -37,7 +37,7 @@ void populateShapeRewritePatterns(RewritePatternSet &patterns);
 //
 // After this pass, no cstr_ operations exist.
 void populateRemoveShapeConstraintsPatterns(RewritePatternSet &patterns);
-std::unique_ptr<FunctionPass> createRemoveShapeConstraintsPass();
+std::unique_ptr<OperationPass<FuncOp>> createRemoveShapeConstraintsPass();
 
 /// Populates patterns for shape dialect structural type conversions and sets up
 /// the provided ConversionTarget with the appropriate legality configuration
@@ -59,7 +59,7 @@ void populateShapeStructuralTypeConversionsAndLegality(
 // Note that most shape dialect ops must be converted to std before
 // bufferization happens, as they are intended to be bufferized at the std
 // level.
-std::unique_ptr<FunctionPass> createShapeBufferizePass();
+std::unique_ptr<OperationPass<FuncOp>> createShapeBufferizePass();
 
 //===----------------------------------------------------------------------===//
 // Registration

diff  --git a/mlir/include/mlir/Dialect/Shape/Transforms/Passes.td b/mlir/include/mlir/Dialect/Shape/Transforms/Passes.td
index 19c226c38fac5..e2592e3696665 100644
--- a/mlir/include/mlir/Dialect/Shape/Transforms/Passes.td
+++ b/mlir/include/mlir/Dialect/Shape/Transforms/Passes.td
@@ -11,18 +11,18 @@
 
 include "mlir/Pass/PassBase.td"
 
-def RemoveShapeConstraints : FunctionPass<"remove-shape-constraints"> {
+def RemoveShapeConstraints : Pass<"remove-shape-constraints", "FuncOp"> {
   let summary = "Replace all cstr_ ops with a true witness";
   let constructor = "mlir::createRemoveShapeConstraintsPass()";
 }
 
-def ShapeToShapeLowering : FunctionPass<"shape-to-shape-lowering"> {
+def ShapeToShapeLowering : Pass<"shape-to-shape-lowering", "FuncOp"> {
   let summary = "Legalize Shape dialect to be convertible to Standard";
   let constructor = "mlir::createShapeToShapeLowering()";
 }
 
 // TODO: Generalize this to allow any type conversions desired.
-def ShapeBufferize : FunctionPass<"shape-bufferize"> {
+def ShapeBufferize : Pass<"shape-bufferize", "FuncOp"> {
   let summary = "Bufferize the shape dialect.";
   let constructor = "mlir::createShapeBufferizePass()";
   let dependentDialects = ["bufferization::BufferizationDialect",

diff  --git a/mlir/include/mlir/Dialect/StandardOps/Transforms/Passes.td b/mlir/include/mlir/Dialect/StandardOps/Transforms/Passes.td
index d8e0e7e6b15da..8ac2b64a8006d 100644
--- a/mlir/include/mlir/Dialect/StandardOps/Transforms/Passes.td
+++ b/mlir/include/mlir/Dialect/StandardOps/Transforms/Passes.td
@@ -11,14 +11,14 @@
 
 include "mlir/Pass/PassBase.td"
 
-def StdBufferize : FunctionPass<"std-bufferize"> {
+def StdBufferize : Pass<"std-bufferize", "FuncOp"> {
   let summary = "Bufferize the std dialect";
   let constructor = "mlir::createStdBufferizePass()";
   let dependentDialects = ["bufferization::BufferizationDialect",
                            "memref::MemRefDialect", "scf::SCFDialect"];
 }
 
-def StdExpandOps : FunctionPass<"std-expand"> {
+def StdExpandOps : Pass<"std-expand", "FuncOp"> {
   let summary = "Legalize std operations to be convertible to LLVM.";
   let constructor = "mlir::createStdExpandOpsPass()";
 }

diff  --git a/mlir/include/mlir/Dialect/Tensor/Transforms/Passes.td b/mlir/include/mlir/Dialect/Tensor/Transforms/Passes.td
index a1f646c0f0f37..57c754c84c321 100644
--- a/mlir/include/mlir/Dialect/Tensor/Transforms/Passes.td
+++ b/mlir/include/mlir/Dialect/Tensor/Transforms/Passes.td
@@ -11,7 +11,7 @@
 
 include "mlir/Pass/PassBase.td"
 
-def TensorBufferize : FunctionPass<"tensor-bufferize"> {
+def TensorBufferize : Pass<"tensor-bufferize", "FuncOp"> {
   let summary = "Bufferize the `tensor` dialect";
   let constructor = "mlir::createTensorBufferizePass()";
   let dependentDialects = [

diff  --git a/mlir/include/mlir/Dialect/Tosa/Transforms/Passes.td b/mlir/include/mlir/Dialect/Tosa/Transforms/Passes.td
index fbb3134e00411..0de4d3229f132 100644
--- a/mlir/include/mlir/Dialect/Tosa/Transforms/Passes.td
+++ b/mlir/include/mlir/Dialect/Tosa/Transforms/Passes.td
@@ -15,7 +15,7 @@
 
 include "mlir/Pass/PassBase.td"
 
-def TosaInferShapes : FunctionPass<"tosa-infer-shapes"> {
+def TosaInferShapes : Pass<"tosa-infer-shapes", "FuncOp"> {
   let summary = "Propagate shapes across TOSA operations";
   let description = [{
     Pass that uses operand types and propagates shapes to TOSA operations.
@@ -30,7 +30,7 @@ def TosaInferShapes : FunctionPass<"tosa-infer-shapes"> {
   ];
 }
 
-def TosaMakeBroadcastable : FunctionPass<"tosa-make-broadcastable"> {
+def TosaMakeBroadcastable : Pass<"tosa-make-broadcastable", "FuncOp"> {
   let summary = "TOSA rank Reshape to enable Broadcasting";
   let description = [{
     Pass that enables broadcast by making all input arrays have the same
@@ -43,7 +43,8 @@ def TosaMakeBroadcastable : FunctionPass<"tosa-make-broadcastable"> {
   let constructor = "createTosaMakeBroadcastablePass()";
 }
 
-def TosaOptionalDecompositions : FunctionPass<"tosa-optional-decompositions"> {
+def TosaOptionalDecompositions
+  : Pass<"tosa-optional-decompositions", "FuncOp"> {
   let summary = "Applies Tosa operations optional decompositions";
   let description = [{
     Pass to apply the Tosa operations decompositions 

diff  --git a/mlir/include/mlir/Pass/Pass.h b/mlir/include/mlir/Pass/Pass.h
index 308df1c7ced97..8a543b2948d75 100644
--- a/mlir/include/mlir/Pass/Pass.h
+++ b/mlir/include/mlir/Pass/Pass.h
@@ -170,7 +170,7 @@ class Pass {
     return *passState;
   }
 
-  /// Return the MLIR context for the current function being transformed.
+  /// Return the MLIR context for the current operation being transformed.
   MLIRContext &getContext() { return *getOperation()->getContext(); }
 
   /// The polymorphic API that runs the pass over the currently held operation.
@@ -332,7 +332,7 @@ class Pass {
 ///   - modify any state within the parent operation, this includes adding
 ///     additional operations.
 ///
-/// Derived function passes are expected to provide the following:
+/// Derived operation passes are expected to provide the following:
 ///   - A 'void runOnOperation()' method.
 ///   - A 'StringRef getName() const' method.
 ///   - A 'std::unique_ptr<Pass> clonePass() const' method.
@@ -365,7 +365,7 @@ template <typename OpT = void> class OperationPass : public Pass {
 ///   - modify any state within the parent operation, this includes adding
 ///     additional operations.
 ///
-/// Derived function passes are expected to provide the following:
+/// Derived operation passes are expected to provide the following:
 ///   - A 'void runOnOperation()' method.
 ///   - A 'StringRef getName() const' method.
 ///   - A 'std::unique_ptr<Pass> clonePass() const' method.
@@ -375,6 +375,8 @@ template <> class OperationPass<void> : public Pass {
   OperationPass(const OperationPass &) = default;
 };
 
+/// NOTICE: This class is deprecated in favor of `OperationPass<FuncOp>`
+/// and will be removed soon.
 /// A model for providing function pass specific utilities.
 ///
 /// Derived function passes are expected to provide the following:

diff  --git a/mlir/include/mlir/Pass/PassBase.td b/mlir/include/mlir/Pass/PassBase.td
index 7a2feff4fe045..e075fb99e41f2 100644
--- a/mlir/include/mlir/Pass/PassBase.td
+++ b/mlir/include/mlir/Pass/PassBase.td
@@ -92,6 +92,8 @@ class PassBase<string passArg, string base> {
 class Pass<string passArg, string operation = "">
   : PassBase<passArg, "::mlir::OperationPass<" # operation # ">">;
 
+/// NOTICE: This class is deprecated in favor of `Pass<..., "mlir::FuncOp">`
+/// and will be removed soon.
 // This class represents an mlir::FunctionPass.
 class FunctionPass<string passArg> : PassBase<passArg, "::mlir::FunctionPass">;
 

diff  --git a/mlir/include/mlir/Transforms/Passes.td b/mlir/include/mlir/Transforms/Passes.td
index d7e4da8ad04de..ff15df372aa26 100644
--- a/mlir/include/mlir/Transforms/Passes.td
+++ b/mlir/include/mlir/Transforms/Passes.td
@@ -16,7 +16,7 @@
 include "mlir/Pass/PassBase.td"
 include "mlir/Rewrite/PassUtil.td"
 
-def AffineLoopFusion : FunctionPass<"affine-loop-fusion"> {
+def AffineLoopFusion : Pass<"affine-loop-fusion", "FuncOp"> {
   let summary = "Fuse affine loop nests";
   let description = [{
     This pass performs fusion of loop nests using a slicing-based approach. It
@@ -149,7 +149,7 @@ def AffineLoopFusion : FunctionPass<"affine-loop-fusion"> {
 }
 
 def AffinePipelineDataTransfer
-    : FunctionPass<"affine-pipeline-data-transfer"> {
+    : Pass<"affine-pipeline-data-transfer", "FuncOp"> {
   let summary = "Pipeline non-blocking data transfers between explicitly "
                 "managed levels of the memory hierarchy";
   let description = [{
@@ -217,7 +217,7 @@ def AffinePipelineDataTransfer
   let constructor = "mlir::createPipelineDataTransferPass()";
 }
 
-def BufferHoisting : FunctionPass<"buffer-hoisting"> {
+def BufferHoisting : Pass<"buffer-hoisting", "FuncOp"> {
   let summary = "Optimizes placement of allocation operations by moving them "
                 "into common dominators and out of nested regions";
   let description = [{
@@ -227,7 +227,7 @@ def BufferHoisting : FunctionPass<"buffer-hoisting"> {
   let constructor = "mlir::createBufferHoistingPass()";
 }
 
-def BufferLoopHoisting : FunctionPass<"buffer-loop-hoisting"> {
+def BufferLoopHoisting : Pass<"buffer-loop-hoisting", "FuncOp"> {
   let summary = "Optimizes placement of allocation operations by moving them "
                 "out of loop nests";
   let description = [{
@@ -237,7 +237,7 @@ def BufferLoopHoisting : FunctionPass<"buffer-loop-hoisting"> {
   let constructor = "mlir::createBufferLoopHoistingPass()";
 }
 
-def PromoteBuffersToStack : FunctionPass<"promote-buffers-to-stack"> {
+def PromoteBuffersToStack : Pass<"promote-buffers-to-stack", "FuncOp"> {
   let summary = "Promotes heap-based allocations to automatically managed "
                 "stack-based allocations";
   let description = [{
@@ -384,7 +384,7 @@ def LocationSnapshot : Pass<"snapshot-op-locations"> {
   ];
 }
 
-def LoopCoalescing : FunctionPass<"loop-coalescing"> {
+def LoopCoalescing : Pass<"loop-coalescing", "FuncOp"> {
   let summary = "Coalesce nested loops with independent bounds into a single "
                 "loop";
   let constructor = "mlir::createLoopCoalescingPass()";

diff  --git a/mlir/lib/Conversion/ArithmeticToLLVM/ArithmeticToLLVM.cpp b/mlir/lib/Conversion/ArithmeticToLLVM/ArithmeticToLLVM.cpp
index 564b8343df791..dd01fd71bc9c4 100644
--- a/mlir/lib/Conversion/ArithmeticToLLVM/ArithmeticToLLVM.cpp
+++ b/mlir/lib/Conversion/ArithmeticToLLVM/ArithmeticToLLVM.cpp
@@ -233,7 +233,7 @@ struct ConvertArithmeticToLLVMPass
     : public ConvertArithmeticToLLVMBase<ConvertArithmeticToLLVMPass> {
   ConvertArithmeticToLLVMPass() = default;
 
-  void runOnFunction() override {
+  void runOnOperation() override {
     LLVMConversionTarget target(getContext());
     RewritePatternSet patterns(&getContext());
 
@@ -245,8 +245,8 @@ struct ConvertArithmeticToLLVMPass
     mlir::arith::populateArithmeticToLLVMConversionPatterns(converter,
                                                             patterns);
 
-    if (failed(
-            applyPartialConversion(getFunction(), target, std::move(patterns))))
+    if (failed(applyPartialConversion(getOperation(), target,
+                                      std::move(patterns))))
       signalPassFailure();
   }
 };

diff  --git a/mlir/lib/Conversion/ArithmeticToSPIRV/ArithmeticToSPIRV.cpp b/mlir/lib/Conversion/ArithmeticToSPIRV/ArithmeticToSPIRV.cpp
index 4bd6a4230f9e5..4fd2b6df9fa5f 100644
--- a/mlir/lib/Conversion/ArithmeticToSPIRV/ArithmeticToSPIRV.cpp
+++ b/mlir/lib/Conversion/ArithmeticToSPIRV/ArithmeticToSPIRV.cpp
@@ -837,7 +837,7 @@ void mlir::arith::populateArithmeticToSPIRVPatterns(
 namespace {
 struct ConvertArithmeticToSPIRVPass
     : public ConvertArithmeticToSPIRVBase<ConvertArithmeticToSPIRVPass> {
-  void runOnFunction() override {
+  void runOnOperation() override {
     auto module = getOperation()->getParentOfType<ModuleOp>();
     auto targetAttr = spirv::lookupTargetEnvOrDefault(module);
     auto target = SPIRVConversionTarget::get(targetAttr);

diff  --git a/mlir/lib/Conversion/ComplexToStandard/ComplexToStandard.cpp b/mlir/lib/Conversion/ComplexToStandard/ComplexToStandard.cpp
index 2766c12663506..47d132f9e8bd9 100644
--- a/mlir/lib/Conversion/ComplexToStandard/ComplexToStandard.cpp
+++ b/mlir/lib/Conversion/ComplexToStandard/ComplexToStandard.cpp
@@ -637,11 +637,11 @@ void mlir::populateComplexToStandardConversionPatterns(
 namespace {
 struct ConvertComplexToStandardPass
     : public ConvertComplexToStandardBase<ConvertComplexToStandardPass> {
-  void runOnFunction() override;
+  void runOnOperation() override;
 };
 
-void ConvertComplexToStandardPass::runOnFunction() {
-  auto function = getFunction();
+void ConvertComplexToStandardPass::runOnOperation() {
+  auto function = getOperation();
 
   // Convert to the Standard dialect using the converter defined above.
   RewritePatternSet patterns(&getContext());

diff  --git a/mlir/lib/Conversion/MathToLLVM/MathToLLVM.cpp b/mlir/lib/Conversion/MathToLLVM/MathToLLVM.cpp
index e83e491926a02..ea7a13b29e265 100644
--- a/mlir/lib/Conversion/MathToLLVM/MathToLLVM.cpp
+++ b/mlir/lib/Conversion/MathToLLVM/MathToLLVM.cpp
@@ -250,13 +250,13 @@ struct ConvertMathToLLVMPass
     : public ConvertMathToLLVMBase<ConvertMathToLLVMPass> {
   ConvertMathToLLVMPass() = default;
 
-  void runOnFunction() override {
+  void runOnOperation() override {
     RewritePatternSet patterns(&getContext());
     LLVMTypeConverter converter(&getContext());
     populateMathToLLVMConversionPatterns(converter, patterns);
     LLVMConversionTarget target(getContext());
-    if (failed(
-            applyPartialConversion(getFunction(), target, std::move(patterns))))
+    if (failed(applyPartialConversion(getOperation(), target,
+                                      std::move(patterns))))
       signalPassFailure();
   }
 };

diff  --git a/mlir/lib/Conversion/SCFToGPU/SCFToGPUPass.cpp b/mlir/lib/Conversion/SCFToGPU/SCFToGPUPass.cpp
index bb244e70de4b1..6acfd3852f78e 100644
--- a/mlir/lib/Conversion/SCFToGPU/SCFToGPUPass.cpp
+++ b/mlir/lib/Conversion/SCFToGPU/SCFToGPUPass.cpp
@@ -34,8 +34,8 @@ struct ForLoopMapper : public ConvertAffineForToGPUBase<ForLoopMapper> {
     this->numThreadDims = numThreadDims;
   }
 
-  void runOnFunction() override {
-    for (Operation &op : llvm::make_early_inc_range(getFunction().getOps())) {
+  void runOnOperation() override {
+    for (Operation &op : llvm::make_early_inc_range(getOperation().getOps())) {
       if (auto forOp = dyn_cast<AffineForOp>(&op)) {
         if (failed(convertAffineLoopNestToGPULaunch(forOp, numBlockDims,
                                                     numThreadDims)))

diff  --git a/mlir/lib/Conversion/TosaToLinalg/TosaToLinalgNamedPass.cpp b/mlir/lib/Conversion/TosaToLinalg/TosaToLinalgNamedPass.cpp
index f5f6ac1a5469c..ccf6424390a2c 100644
--- a/mlir/lib/Conversion/TosaToLinalg/TosaToLinalgNamedPass.cpp
+++ b/mlir/lib/Conversion/TosaToLinalg/TosaToLinalgNamedPass.cpp
@@ -38,7 +38,7 @@ struct TosaToLinalgNamed : public TosaToLinalgNamedBase<TosaToLinalgNamed> {
                     tensor::TensorDialect, scf::SCFDialect>();
   }
 
-  void runOnFunction() override {
+  void runOnOperation() override {
     RewritePatternSet patterns(&getContext());
     ConversionTarget target(getContext());
     target.addLegalDialect<linalg::LinalgDialect, StandardOpsDialect,
@@ -55,7 +55,7 @@ struct TosaToLinalgNamed : public TosaToLinalgNamedBase<TosaToLinalgNamed> {
 
     target.markUnknownOpDynamicallyLegal([](Operation *) { return true; });
 
-    FuncOp func = getFunction();
+    FuncOp func = getOperation();
     mlir::tosa::populateTosaToLinalgNamedConversionPatterns(&patterns);
     if (failed(applyFullConversion(func, target, std::move(patterns))))
       signalPassFailure();

diff  --git a/mlir/lib/Conversion/TosaToLinalg/TosaToLinalgPass.cpp b/mlir/lib/Conversion/TosaToLinalg/TosaToLinalgPass.cpp
index cfc31ded98835..55b6726efb82f 100644
--- a/mlir/lib/Conversion/TosaToLinalg/TosaToLinalgPass.cpp
+++ b/mlir/lib/Conversion/TosaToLinalg/TosaToLinalgPass.cpp
@@ -39,7 +39,7 @@ struct TosaToLinalg : public TosaToLinalgBase<TosaToLinalg> {
                     tensor::TensorDialect, scf::SCFDialect>();
   }
 
-  void runOnFunction() override {
+  void runOnOperation() override {
     RewritePatternSet patterns(&getContext());
     ConversionTarget target(getContext());
     target.addLegalDialect<linalg::LinalgDialect, StandardOpsDialect,
@@ -55,7 +55,7 @@ struct TosaToLinalg : public TosaToLinalgBase<TosaToLinalg> {
 
     target.markUnknownOpDynamicallyLegal([](Operation *) { return true; });
 
-    FuncOp func = getFunction();
+    FuncOp func = getOperation();
     mlir::tosa::populateTosaToLinalgConversionPatterns(&patterns);
     if (failed(applyFullConversion(func, target, std::move(patterns))))
       signalPassFailure();

diff  --git a/mlir/lib/Conversion/VectorToGPU/VectorToGPU.cpp b/mlir/lib/Conversion/VectorToGPU/VectorToGPU.cpp
index 725264d31fc7d..dcba23cb2ef18 100644
--- a/mlir/lib/Conversion/VectorToGPU/VectorToGPU.cpp
+++ b/mlir/lib/Conversion/VectorToGPU/VectorToGPU.cpp
@@ -535,12 +535,12 @@ namespace {
 
 struct ConvertVectorToGPUPass
     : public ConvertVectorToGPUBase<ConvertVectorToGPUPass> {
-  void runOnFunction() override {
-    RewritePatternSet patterns(getFunction().getContext());
+  void runOnOperation() override {
+    RewritePatternSet patterns(getOperation().getContext());
     populatePrepareVectorToMMAPatterns(patterns);
-    (void)applyPatternsAndFoldGreedily(getFunction(), std::move(patterns));
+    (void)applyPatternsAndFoldGreedily(getOperation(), std::move(patterns));
 
-    convertVectorToMMAOps(getFunction());
+    convertVectorToMMAOps(getOperation());
   }
 };
 

diff  --git a/mlir/lib/Conversion/VectorToSCF/VectorToSCF.cpp b/mlir/lib/Conversion/VectorToSCF/VectorToSCF.cpp
index 4709bed076377..98968eb20d0a7 100644
--- a/mlir/lib/Conversion/VectorToSCF/VectorToSCF.cpp
+++ b/mlir/lib/Conversion/VectorToSCF/VectorToSCF.cpp
@@ -1284,7 +1284,7 @@ struct ConvertVectorToSCFPass
     this->lowerTensors = options.lowerTensors;
   }
 
-  void runOnFunction() override {
+  void runOnOperation() override {
     VectorTransferToSCFOptions options;
     options.unroll = fullUnroll;
     options.targetRank = targetRank;
@@ -1293,16 +1293,16 @@ struct ConvertVectorToSCFPass
 
     // Lower permutation maps first.
     if (lowerPermutationMaps) {
-      RewritePatternSet lowerTransferPatterns(getFunction().getContext());
+      RewritePatternSet lowerTransferPatterns(getOperation().getContext());
       mlir::vector::populateVectorTransferPermutationMapLoweringPatterns(
           lowerTransferPatterns);
-      (void)applyPatternsAndFoldGreedily(getFunction(),
+      (void)applyPatternsAndFoldGreedily(getOperation(),
                                          std::move(lowerTransferPatterns));
     }
 
-    RewritePatternSet patterns(getFunction().getContext());
+    RewritePatternSet patterns(getOperation().getContext());
     populateVectorToSCFConversionPatterns(patterns, options);
-    (void)applyPatternsAndFoldGreedily(getFunction(), std::move(patterns));
+    (void)applyPatternsAndFoldGreedily(getOperation(), std::move(patterns));
   }
 };
 

diff  --git a/mlir/lib/Dialect/Affine/Transforms/AffineDataCopyGeneration.cpp b/mlir/lib/Dialect/Affine/Transforms/AffineDataCopyGeneration.cpp
index a20b70f9734cc..f902909a7c3b2 100644
--- a/mlir/lib/Dialect/Affine/Transforms/AffineDataCopyGeneration.cpp
+++ b/mlir/lib/Dialect/Affine/Transforms/AffineDataCopyGeneration.cpp
@@ -65,7 +65,7 @@ struct AffineDataCopyGeneration
     this->fastMemoryCapacity = fastMemCapacityBytes / 1024;
   }
 
-  void runOnFunction() override;
+  void runOnOperation() override;
   void runOnBlock(Block *block, DenseSet<Operation *> &copyNests);
 
   // Constant zero index to avoid too many duplicates.
@@ -196,8 +196,8 @@ void AffineDataCopyGeneration::runOnBlock(Block *block,
   }
 }
 
-void AffineDataCopyGeneration::runOnFunction() {
-  FuncOp f = getFunction();
+void AffineDataCopyGeneration::runOnOperation() {
+  FuncOp f = getOperation();
   OpBuilder topBuilder(f.getBody());
   zeroIndex = topBuilder.create<arith::ConstantIndexOp>(f.getLoc(), 0);
 

diff  --git a/mlir/lib/Dialect/Affine/Transforms/AffineLoopInvariantCodeMotion.cpp b/mlir/lib/Dialect/Affine/Transforms/AffineLoopInvariantCodeMotion.cpp
index caad8d648718d..19c16cf9ce2a7 100644
--- a/mlir/lib/Dialect/Affine/Transforms/AffineLoopInvariantCodeMotion.cpp
+++ b/mlir/lib/Dialect/Affine/Transforms/AffineLoopInvariantCodeMotion.cpp
@@ -44,7 +44,7 @@ namespace {
 ///       uses.
 struct LoopInvariantCodeMotion
     : public AffineLoopInvariantCodeMotionBase<LoopInvariantCodeMotion> {
-  void runOnFunction() override;
+  void runOnOperation() override;
   void runOnAffineForOp(AffineForOp forOp);
 };
 } // namespace
@@ -227,11 +227,11 @@ void LoopInvariantCodeMotion::runOnAffineForOp(AffineForOp forOp) {
   LLVM_DEBUG(forOp->print(llvm::dbgs() << "Modified loop\n"));
 }
 
-void LoopInvariantCodeMotion::runOnFunction() {
+void LoopInvariantCodeMotion::runOnOperation() {
   // Walk through all loops in a function in innermost-loop-first order.  This
   // way, we first LICM from the inner loop, and place the ops in
   // the outer loop, which in turn can be further LICM'ed.
-  getFunction().walk([&](AffineForOp op) {
+  getOperation().walk([&](AffineForOp op) {
     LLVM_DEBUG(op->print(llvm::dbgs() << "\nOriginal loop\n"));
     runOnAffineForOp(op);
   });

diff  --git a/mlir/lib/Dialect/Affine/Transforms/AffineLoopNormalize.cpp b/mlir/lib/Dialect/Affine/Transforms/AffineLoopNormalize.cpp
index bd411a623d997..fe645576b7980 100644
--- a/mlir/lib/Dialect/Affine/Transforms/AffineLoopNormalize.cpp
+++ b/mlir/lib/Dialect/Affine/Transforms/AffineLoopNormalize.cpp
@@ -25,8 +25,8 @@ namespace {
 struct AffineLoopNormalizePass
     : public AffineLoopNormalizeBase<AffineLoopNormalizePass> {
 
-  void runOnFunction() override {
-    getFunction().walk([](Operation *op) {
+  void runOnOperation() override {
+    getOperation().walk([](Operation *op) {
       if (auto affineParallel = dyn_cast<AffineParallelOp>(op))
         normalizeAffineParallel(affineParallel);
       else if (auto affineFor = dyn_cast<AffineForOp>(op))

diff  --git a/mlir/lib/Dialect/Affine/Transforms/AffineParallelize.cpp b/mlir/lib/Dialect/Affine/Transforms/AffineParallelize.cpp
index 86712a3a2540a..2fed4921c2a4b 100644
--- a/mlir/lib/Dialect/Affine/Transforms/AffineParallelize.cpp
+++ b/mlir/lib/Dialect/Affine/Transforms/AffineParallelize.cpp
@@ -32,7 +32,7 @@ using namespace mlir;
 namespace {
 /// Convert all parallel affine.for op into 1-D affine.parallel op.
 struct AffineParallelize : public AffineParallelizeBase<AffineParallelize> {
-  void runOnFunction() override;
+  void runOnOperation() override;
 };
 
 /// Descriptor of a potentially parallelizable loop.
@@ -47,8 +47,8 @@ struct ParallelizationCandidate {
 };
 } // namespace
 
-void AffineParallelize::runOnFunction() {
-  FuncOp f = getFunction();
+void AffineParallelize::runOnOperation() {
+  FuncOp f = getOperation();
 
   // The walker proceeds in pre-order to process the outer loops first
   // and control the number of outer parallel loops.

diff  --git a/mlir/lib/Dialect/Affine/Transforms/AffineScalarReplacement.cpp b/mlir/lib/Dialect/Affine/Transforms/AffineScalarReplacement.cpp
index 527a54d5ee025..c5a347bced7a9 100644
--- a/mlir/lib/Dialect/Affine/Transforms/AffineScalarReplacement.cpp
+++ b/mlir/lib/Dialect/Affine/Transforms/AffineScalarReplacement.cpp
@@ -29,16 +29,17 @@ using namespace mlir;
 namespace {
 struct AffineScalarReplacement
     : public AffineScalarReplacementBase<AffineScalarReplacement> {
-  void runOnFunction() override;
+  void runOnOperation() override;
 };
 
 } // namespace
 
-std::unique_ptr<FunctionPass> mlir::createAffineScalarReplacementPass() {
+std::unique_ptr<OperationPass<FuncOp>>
+mlir::createAffineScalarReplacementPass() {
   return std::make_unique<AffineScalarReplacement>();
 }
 
-void AffineScalarReplacement::runOnFunction() {
-  affineScalarReplace(getFunction(), getAnalysis<DominanceInfo>(),
+void AffineScalarReplacement::runOnOperation() {
+  affineScalarReplace(getOperation(), getAnalysis<DominanceInfo>(),
                       getAnalysis<PostDominanceInfo>());
 }

diff  --git a/mlir/lib/Dialect/Affine/Transforms/LoopTiling.cpp b/mlir/lib/Dialect/Affine/Transforms/LoopTiling.cpp
index d1823c918e392..f15571660b4d8 100644
--- a/mlir/lib/Dialect/Affine/Transforms/LoopTiling.cpp
+++ b/mlir/lib/Dialect/Affine/Transforms/LoopTiling.cpp
@@ -38,7 +38,7 @@ struct LoopTiling : public AffineLoopTilingBase<LoopTiling> {
     this->cacheSizeInKiB = cacheSizeBytes / 1024;
   }
 
-  void runOnFunction() override;
+  void runOnOperation() override;
   void getTileSizes(ArrayRef<AffineForOp> band,
                     SmallVectorImpl<unsigned> *tileSizes);
 
@@ -160,10 +160,10 @@ void LoopTiling::getTileSizes(ArrayRef<AffineForOp> band,
     adjustToDivisorsOfTripCounts(band, tileSizes);
 }
 
-void LoopTiling::runOnFunction() {
+void LoopTiling::runOnOperation() {
   // Bands of loops to tile.
   std::vector<SmallVector<AffineForOp, 6>> bands;
-  getTileableBands(getFunction(), &bands);
+  getTileableBands(getOperation(), &bands);
 
   // Tile each band.
   for (auto &band : bands) {

diff  --git a/mlir/lib/Dialect/Affine/Transforms/LoopUnroll.cpp b/mlir/lib/Dialect/Affine/Transforms/LoopUnroll.cpp
index b232c1134644b..fb7cd11ebe6da 100644
--- a/mlir/lib/Dialect/Affine/Transforms/LoopUnroll.cpp
+++ b/mlir/lib/Dialect/Affine/Transforms/LoopUnroll.cpp
@@ -54,7 +54,7 @@ struct LoopUnroll : public AffineLoopUnrollBase<LoopUnroll> {
     this->unrollFull = unrollFull;
   }
 
-  void runOnFunction() override;
+  void runOnOperation() override;
 
   /// Unroll this for op. Returns failure if nothing was done.
   LogicalResult runOnAffineForOp(AffineForOp forOp);
@@ -82,7 +82,11 @@ static void gatherInnermostLoops(FuncOp f,
   });
 }
 
-void LoopUnroll::runOnFunction() {
+void LoopUnroll::runOnOperation() {
+  FuncOp func = getOperation();
+  if (func.isExternal())
+    return;
+
   if (unrollFull && unrollFullThreshold.hasValue()) {
     // Store short loops as we walk.
     SmallVector<AffineForOp, 4> loops;
@@ -90,7 +94,7 @@ void LoopUnroll::runOnFunction() {
     // Gathers all loops with trip count <= minTripCount. Do a post order walk
     // so that loops are gathered from innermost to outermost (or else unrolling
     // an outer one may delete gathered inner ones).
-    getFunction().walk([&](AffineForOp forOp) {
+    getOperation().walk([&](AffineForOp forOp) {
       Optional<uint64_t> tripCount = getConstantTripCount(forOp);
       if (tripCount.hasValue() && tripCount.getValue() <= unrollFullThreshold)
         loops.push_back(forOp);
@@ -101,7 +105,6 @@ void LoopUnroll::runOnFunction() {
   }
 
   // If the call back is provided, we will recurse until no loops are found.
-  FuncOp func = getFunction();
   SmallVector<AffineForOp, 4> loops;
   for (unsigned i = 0; i < numRepetitions || getUnrollFactor; i++) {
     loops.clear();

diff  --git a/mlir/lib/Dialect/Affine/Transforms/LoopUnrollAndJam.cpp b/mlir/lib/Dialect/Affine/Transforms/LoopUnrollAndJam.cpp
index 948e2ba2f03a0..b763017d0837f 100644
--- a/mlir/lib/Dialect/Affine/Transforms/LoopUnrollAndJam.cpp
+++ b/mlir/lib/Dialect/Affine/Transforms/LoopUnrollAndJam.cpp
@@ -59,7 +59,7 @@ struct LoopUnrollAndJam : public AffineLoopUnrollAndJamBase<LoopUnrollAndJam> {
       this->unrollJamFactor = *unrollJamFactor;
   }
 
-  void runOnFunction() override;
+  void runOnOperation() override;
 };
 } // namespace
 
@@ -69,11 +69,14 @@ mlir::createLoopUnrollAndJamPass(int unrollJamFactor) {
       unrollJamFactor == -1 ? None : Optional<unsigned>(unrollJamFactor));
 }
 
-void LoopUnrollAndJam::runOnFunction() {
+void LoopUnrollAndJam::runOnOperation() {
+  if (getOperation().isExternal())
+    return;
+
   // Currently, just the outermost loop from the first loop nest is
   // unroll-and-jammed by this pass. However, runOnAffineForOp can be called on
   // any for operation.
-  auto &entryBlock = getFunction().front();
+  auto &entryBlock = getOperation().front();
   if (auto forOp = dyn_cast<AffineForOp>(entryBlock.front()))
     (void)loopUnrollJamByFactor(forOp, unrollJamFactor);
 }

diff  --git a/mlir/lib/Dialect/Affine/Transforms/SimplifyAffineStructures.cpp b/mlir/lib/Dialect/Affine/Transforms/SimplifyAffineStructures.cpp
index 51794e3698d7b..08ccac678113e 100644
--- a/mlir/lib/Dialect/Affine/Transforms/SimplifyAffineStructures.cpp
+++ b/mlir/lib/Dialect/Affine/Transforms/SimplifyAffineStructures.cpp
@@ -30,7 +30,7 @@ namespace {
 /// identity layout ones.
 struct SimplifyAffineStructures
     : public SimplifyAffineStructuresBase<SimplifyAffineStructures> {
-  void runOnFunction() override;
+  void runOnOperation() override;
 
   /// Utility to simplify an affine attribute and update its entry in the parent
   /// operation if necessary.
@@ -76,8 +76,8 @@ mlir::createSimplifyAffineStructuresPass() {
   return std::make_unique<SimplifyAffineStructures>();
 }
 
-void SimplifyAffineStructures::runOnFunction() {
-  auto func = getFunction();
+void SimplifyAffineStructures::runOnOperation() {
+  auto func = getOperation();
   simplifiedAttributes.clear();
   RewritePatternSet patterns(func.getContext());
   AffineApplyOp::getCanonicalizationPatterns(patterns, func.getContext());

diff  --git a/mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp b/mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp
index 5dba727a70d09..6b7098baba3f2 100644
--- a/mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp
+++ b/mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp
@@ -608,7 +608,7 @@ namespace {
 struct Vectorize : public AffineVectorizeBase<Vectorize> {
   Vectorize() = default;
   Vectorize(ArrayRef<int64_t> virtualVectorSize);
-  void runOnFunction() override;
+  void runOnOperation() override;
 };
 
 } // namespace
@@ -1709,8 +1709,8 @@ std::unique_ptr<OperationPass<FuncOp>> createSuperVectorizePass() {
 
 /// Applies vectorization to the current function by searching over a bunch of
 /// predetermined patterns.
-void Vectorize::runOnFunction() {
-  FuncOp f = getFunction();
+void Vectorize::runOnOperation() {
+  FuncOp f = getOperation();
   if (!fastestVaryingPattern.empty() &&
       fastestVaryingPattern.size() != vectorSizes.size()) {
     f.emitRemark("Fastest varying pattern specified with 
diff erent size than "

diff  --git a/mlir/lib/Dialect/Arithmetic/Transforms/Bufferize.cpp b/mlir/lib/Dialect/Arithmetic/Transforms/Bufferize.cpp
index a7691e53ce6fc..715fb1c81cbc5 100644
--- a/mlir/lib/Dialect/Arithmetic/Transforms/Bufferize.cpp
+++ b/mlir/lib/Dialect/Arithmetic/Transforms/Bufferize.cpp
@@ -35,7 +35,7 @@ struct BufferizeIndexCastOp : public OpConversionPattern<arith::IndexCastOp> {
 /// Pass to bufferize Arithmetic ops.
 struct ArithmeticBufferizePass
     : public ArithmeticBufferizeBase<ArithmeticBufferizePass> {
-  void runOnFunction() override {
+  void runOnOperation() override {
     bufferization::BufferizeTypeConverter typeConverter;
     RewritePatternSet patterns(&getContext());
     ConversionTarget target(getContext());
@@ -49,8 +49,8 @@ struct ArithmeticBufferizePass
           return typeConverter.isLegal(op.getType());
         });
 
-    if (failed(
-            applyPartialConversion(getFunction(), target, std::move(patterns))))
+    if (failed(applyPartialConversion(getOperation(), target,
+                                      std::move(patterns))))
       signalPassFailure();
   }
 };

diff  --git a/mlir/lib/Dialect/Arithmetic/Transforms/ExpandOps.cpp b/mlir/lib/Dialect/Arithmetic/Transforms/ExpandOps.cpp
index 7aa5ca555924d..127b27effd8db 100644
--- a/mlir/lib/Dialect/Arithmetic/Transforms/ExpandOps.cpp
+++ b/mlir/lib/Dialect/Arithmetic/Transforms/ExpandOps.cpp
@@ -189,7 +189,7 @@ struct MaxMinIOpConverter : public OpRewritePattern<OpTy> {
 
 struct ArithmeticExpandOpsPass
     : public ArithmeticExpandOpsBase<ArithmeticExpandOpsPass> {
-  void runOnFunction() override {
+  void runOnOperation() override {
     RewritePatternSet patterns(&getContext());
     ConversionTarget target(getContext());
 
@@ -209,8 +209,8 @@ struct ArithmeticExpandOpsPass
       arith::MinUIOp
     >();
     // clang-format on
-    if (failed(
-            applyPartialConversion(getFunction(), target, std::move(patterns))))
+    if (failed(applyPartialConversion(getOperation(), target,
+                                      std::move(patterns))))
       signalPassFailure();
   }
 };

diff  --git a/mlir/lib/Dialect/Bufferization/Transforms/BufferDeallocation.cpp b/mlir/lib/Dialect/Bufferization/Transforms/BufferDeallocation.cpp
index 33c8793cbc253..32a77430fa3a9 100644
--- a/mlir/lib/Dialect/Bufferization/Transforms/BufferDeallocation.cpp
+++ b/mlir/lib/Dialect/Bufferization/Transforms/BufferDeallocation.cpp
@@ -638,9 +638,12 @@ struct BufferDeallocationPass : BufferDeallocationBase<BufferDeallocationPass> {
     registry.addOpInterface<memref::AllocOp, DefaultAllocationInterface>();
   }
 
-  void runOnFunction() override {
+  void runOnOperation() override {
+    FuncOp func = getOperation();
+    if (func.isExternal())
+      return;
+
     // Ensure that there are supported loops only.
-    FuncOp func = getFunction();
     Backedges backedges(func);
     if (backedges.size()) {
       func.emitError("Only structured control-flow loops are supported.");

diff  --git a/mlir/lib/Dialect/Bufferization/Transforms/Bufferize.cpp b/mlir/lib/Dialect/Bufferization/Transforms/Bufferize.cpp
index 609d7382e6d14..cebff6a7a860f 100644
--- a/mlir/lib/Dialect/Bufferization/Transforms/Bufferize.cpp
+++ b/mlir/lib/Dialect/Bufferization/Transforms/Bufferize.cpp
@@ -98,8 +98,8 @@ struct FinalizingBufferizePass
   using FinalizingBufferizeBase<
       FinalizingBufferizePass>::FinalizingBufferizeBase;
 
-  void runOnFunction() override {
-    auto func = getFunction();
+  void runOnOperation() override {
+    auto func = getOperation();
     auto *context = &getContext();
 
     BufferizeTypeConverter typeConverter;
@@ -125,7 +125,7 @@ struct FinalizingBufferizePass
 };
 } // namespace
 
-std::unique_ptr<FunctionPass>
+std::unique_ptr<OperationPass<FuncOp>>
 mlir::bufferization::createFinalizingBufferizePass() {
   return std::make_unique<FinalizingBufferizePass>();
 }

diff  --git a/mlir/lib/Dialect/GPU/Transforms/AsyncRegionRewriter.cpp b/mlir/lib/Dialect/GPU/Transforms/AsyncRegionRewriter.cpp
index e4e3d72b4a475..fc00b5fc67cb6 100644
--- a/mlir/lib/Dialect/GPU/Transforms/AsyncRegionRewriter.cpp
+++ b/mlir/lib/Dialect/GPU/Transforms/AsyncRegionRewriter.cpp
@@ -31,7 +31,7 @@ class GpuAsyncRegionPass : public GpuAsyncRegionPassBase<GpuAsyncRegionPass> {
   struct ThreadTokenCallback;
   struct DeferWaitCallback;
   struct SingleTokenUseCallback;
-  void runOnFunction() override;
+  void runOnOperation() override;
 };
 } // namespace
 
@@ -327,14 +327,14 @@ struct GpuAsyncRegionPass::SingleTokenUseCallback {
 // Replaces synchronous GPU ops in the op's region with asynchronous ones and
 // inserts the necessary synchronization (as gpu.wait ops). Assumes sequential
 // execution semantics and that no GPU ops are asynchronous yet.
-void GpuAsyncRegionPass::runOnFunction() {
-  if (getFunction()->walk(ThreadTokenCallback(getContext())).wasInterrupted())
+void GpuAsyncRegionPass::runOnOperation() {
+  if (getOperation()->walk(ThreadTokenCallback(getContext())).wasInterrupted())
     return signalPassFailure();
 
   // Collect gpu.wait ops that we can move out of async.execute regions.
-  getFunction().getRegion().walk(DeferWaitCallback());
+  getOperation().getRegion().walk(DeferWaitCallback());
   // Makes each !gpu.async.token returned from async.execute op have single use.
-  getFunction().getRegion().walk(SingleTokenUseCallback());
+  getOperation().getRegion().walk(SingleTokenUseCallback());
 }
 
 std::unique_ptr<OperationPass<FuncOp>> mlir::createGpuAsyncRegionPass() {

diff  --git a/mlir/lib/Dialect/Linalg/Transforms/Generalization.cpp b/mlir/lib/Dialect/Linalg/Transforms/Generalization.cpp
index f8378d9009523..1eacc93f74825 100644
--- a/mlir/lib/Dialect/Linalg/Transforms/Generalization.cpp
+++ b/mlir/lib/Dialect/Linalg/Transforms/Generalization.cpp
@@ -68,13 +68,13 @@ namespace {
 
 struct LinalgGeneralizationPass
     : public LinalgGeneralizationBase<LinalgGeneralizationPass> {
-  void runOnFunction() override;
+  void runOnOperation() override;
 };
 
 } // namespace
 
-void LinalgGeneralizationPass::runOnFunction() {
-  FuncOp func = getFunction();
+void LinalgGeneralizationPass::runOnOperation() {
+  FuncOp func = getOperation();
   RewritePatternSet patterns(&getContext());
   populateLinalgNamedOpsGeneralizationPatterns(patterns);
   (void)applyPatternsAndFoldGreedily(func.getBody(), std::move(patterns));

diff  --git a/mlir/lib/Dialect/Linalg/Transforms/InlineScalarOperands.cpp b/mlir/lib/Dialect/Linalg/Transforms/InlineScalarOperands.cpp
index 8859547ad6f83..1b81113bfcf0b 100644
--- a/mlir/lib/Dialect/Linalg/Transforms/InlineScalarOperands.cpp
+++ b/mlir/lib/Dialect/Linalg/Transforms/InlineScalarOperands.cpp
@@ -97,8 +97,8 @@ namespace {
 /// Pass that removes unit-extent dims within generic ops.
 struct LinalgInlineScalarOperandsPass
     : public LinalgInlineScalarOperandsBase<LinalgInlineScalarOperandsPass> {
-  void runOnFunction() override {
-    FuncOp funcOp = getFunction();
+  void runOnOperation() override {
+    FuncOp funcOp = getOperation();
     MLIRContext *context = funcOp.getContext();
     RewritePatternSet patterns(context);
 

diff  --git a/mlir/lib/Dialect/Linalg/Transforms/LinalgStrategyPasses.cpp b/mlir/lib/Dialect/Linalg/Transforms/LinalgStrategyPasses.cpp
index 2a052c037380c..31f8fa5b369e3 100644
--- a/mlir/lib/Dialect/Linalg/Transforms/LinalgStrategyPasses.cpp
+++ b/mlir/lib/Dialect/Linalg/Transforms/LinalgStrategyPasses.cpp
@@ -52,8 +52,8 @@ struct LinalgStrategyTileAndFusePass
     this->anchorOpName.setValue(opName.str());
   }
 
-  void runOnFunction() override {
-    auto funcOp = getFunction();
+  void runOnOperation() override {
+    auto funcOp = getOperation();
     if (!anchorFuncName.empty() && funcOp.getName() != anchorFuncName)
       return;
 
@@ -88,8 +88,8 @@ struct LinalgStrategyTilePass
     this->anchorOpName.setValue(opName.str());
   }
 
-  void runOnFunction() override {
-    auto funcOp = getFunction();
+  void runOnOperation() override {
+    auto funcOp = getOperation();
     if (!anchorFuncName.empty() && funcOp.getName() != anchorFuncName)
       return;
 
@@ -121,8 +121,8 @@ struct LinalgStrategyPadPass
     this->anchorOpName.setValue(opName.str());
   }
 
-  void runOnFunction() override {
-    auto funcOp = getFunction();
+  void runOnOperation() override {
+    auto funcOp = getOperation();
     if (!anchorFuncName.empty() && funcOp.getName() != anchorFuncName)
       return;
 
@@ -153,8 +153,8 @@ struct LinalgStrategyGeneralizePass
     this->anchorOpName.setValue(opName.str());
   }
 
-  void runOnFunction() override {
-    auto funcOp = getFunction();
+  void runOnOperation() override {
+    auto funcOp = getOperation();
     if (!anchorFuncName.empty() && funcOp.getName() != anchorFuncName)
       return;
 
@@ -184,8 +184,8 @@ struct LinalgStrategyDecomposePass
   LinalgStrategyDecomposePass(LinalgTransformationFilter filter)
       : filter(std::move(filter)) {}
 
-  void runOnFunction() override {
-    auto funcOp = getFunction();
+  void runOnOperation() override {
+    auto funcOp = getOperation();
     if (!anchorFuncName.empty() && funcOp.getName() != anchorFuncName)
       return;
     RewritePatternSet decompositionPattern(funcOp.getContext());
@@ -210,8 +210,8 @@ struct LinalgStrategyInterchangePass
                             iteratorInterchange.end()),
         filter(std::move(filter)) {}
 
-  void runOnFunction() override {
-    auto funcOp = getFunction();
+  void runOnOperation() override {
+    auto funcOp = getOperation();
     if (!anchorFuncName.empty() && funcOp.getName() != anchorFuncName)
       return;
 
@@ -241,8 +241,8 @@ struct LinalgStrategyPromotePass
     this->anchorOpName.setValue(opName.str());
   }
 
-  void runOnFunction() override {
-    auto funcOp = getFunction();
+  void runOnOperation() override {
+    auto funcOp = getOperation();
     if (!anchorFuncName.empty() && funcOp.getName() != anchorFuncName)
       return;
 
@@ -275,8 +275,8 @@ struct LinalgStrategyVectorizePass
     this->vectorizePadding.setValue(padVectorize);
   }
 
-  void runOnFunction() override {
-    auto funcOp = getFunction();
+  void runOnOperation() override {
+    auto funcOp = getOperation();
     if (!anchorFuncName.empty() && funcOp.getName() != anchorFuncName)
       return;
 
@@ -325,8 +325,8 @@ struct LinalgStrategyEnablePass
                            LinalgTransformationFilter filt)
       : options(opt), filter(std::move(filt)) {}
 
-  void runOnFunction() override {
-    auto funcOp = getFunction();
+  void runOnOperation() override {
+    auto funcOp = getOperation();
     if (!anchorFuncName.empty() && funcOp.getName() != anchorFuncName)
       return;
 
@@ -375,8 +375,8 @@ struct LinalgStrategyLowerVectorsPass
                                  LinalgTransformationFilter filt)
       : options(opt), filter(std::move(filt)) {}
 
-  void runOnFunction() override {
-    auto funcOp = getFunction();
+  void runOnOperation() override {
+    auto funcOp = getOperation();
     if (!anchorFuncName.empty() && funcOp.getName() != anchorFuncName)
       return;
 
@@ -436,8 +436,8 @@ struct LinalgStrategyRemoveMarkersPass
     : public LinalgStrategyRemoveMarkersPassBase<
           LinalgStrategyRemoveMarkersPass> {
 
-  void runOnFunction() override {
-    auto funcOp = getFunction();
+  void runOnOperation() override {
+    auto funcOp = getOperation();
     if (!anchorFuncName.empty() && funcOp.getName() != anchorFuncName)
       return;
     funcOp.walk([](LinalgOp op) {

diff  --git a/mlir/lib/Dialect/Linalg/Transforms/Loops.cpp b/mlir/lib/Dialect/Linalg/Transforms/Loops.cpp
index d3936eb366cc5..52d60b20f2b93 100644
--- a/mlir/lib/Dialect/Linalg/Transforms/Loops.cpp
+++ b/mlir/lib/Dialect/Linalg/Transforms/Loops.cpp
@@ -381,8 +381,8 @@ struct LowerToAffineLoops
   void getDependentDialects(DialectRegistry &registry) const override {
     registry.insert<memref::MemRefDialect>();
   }
-  void runOnFunction() override {
-    lowerLinalgToLoopsImpl<AffineForOp>(getFunction());
+  void runOnOperation() override {
+    lowerLinalgToLoopsImpl<AffineForOp>(getOperation());
   }
 };
 
@@ -390,25 +390,25 @@ struct LowerToLoops : public LinalgLowerToLoopsBase<LowerToLoops> {
   void getDependentDialects(DialectRegistry &registry) const override {
     registry.insert<memref::MemRefDialect, scf::SCFDialect>();
   }
-  void runOnFunction() override {
-    lowerLinalgToLoopsImpl<scf::ForOp>(getFunction());
+  void runOnOperation() override {
+    lowerLinalgToLoopsImpl<scf::ForOp>(getOperation());
   }
 };
 
 struct LowerToParallelLoops
     : public LinalgLowerToParallelLoopsBase<LowerToParallelLoops> {
-  void runOnFunction() override {
-    lowerLinalgToLoopsImpl<scf::ParallelOp>(getFunction());
+  void runOnOperation() override {
+    lowerLinalgToLoopsImpl<scf::ParallelOp>(getOperation());
   }
 };
 
 struct LowerTiledLoopsToSCF
     : public LinalgLowerTiledLoopsToSCFBase<LowerTiledLoopsToSCF> {
-  void runOnFunction() override {
+  void runOnOperation() override {
     MLIRContext *context = &getContext();
     RewritePatternSet patterns(context);
     populateTiledLoopToSCFPattern(patterns);
-    (void)applyPatternsAndFoldGreedily(getFunction(), std::move(patterns));
+    (void)applyPatternsAndFoldGreedily(getOperation(), std::move(patterns));
   }
 };
 } // namespace

diff  --git a/mlir/lib/Dialect/Linalg/Transforms/Promotion.cpp b/mlir/lib/Dialect/Linalg/Transforms/Promotion.cpp
index fb281b319f67c..9963381715fc5 100644
--- a/mlir/lib/Dialect/Linalg/Transforms/Promotion.cpp
+++ b/mlir/lib/Dialect/Linalg/Transforms/Promotion.cpp
@@ -397,8 +397,8 @@ struct LinalgPromotionPass : public LinalgPromotionBase<LinalgPromotionPass> {
     this->useAlloca = useAlloca;
   }
 
-  void runOnFunction() override {
-    getFunction().walk([&](LinalgOp op) {
+  void runOnOperation() override {
+    getOperation().walk([&](LinalgOp op) {
       auto options = LinalgPromotionOptions()
                          .setDynamicBuffers(dynamicBuffers)
                          .setUseAlloca(useAlloca);

diff  --git a/mlir/lib/Dialect/Linalg/Transforms/Tiling.cpp b/mlir/lib/Dialect/Linalg/Transforms/Tiling.cpp
index 36bd434e845da..f005846ef4667 100644
--- a/mlir/lib/Dialect/Linalg/Transforms/Tiling.cpp
+++ b/mlir/lib/Dialect/Linalg/Transforms/Tiling.cpp
@@ -519,8 +519,8 @@ struct LinalgTilingPass : public LinalgTilingBase<LinalgTilingPass> {
         distributionTypes, [](StringRef ref) { return ref.str(); }));
   }
 
-  void runOnFunction() override {
-    FuncOp funcOp = getFunction();
+  void runOnOperation() override {
+    FuncOp funcOp = getOperation();
     LinalgTilingLoopType type =
         llvm::StringSwitch<LinalgTilingLoopType>(loopType)
             .Case("for", LinalgTilingLoopType::Loops)

diff  --git a/mlir/lib/Dialect/Quant/Transforms/ConvertConst.cpp b/mlir/lib/Dialect/Quant/Transforms/ConvertConst.cpp
index 64844ef3ca652..7b66dba229541 100644
--- a/mlir/lib/Dialect/Quant/Transforms/ConvertConst.cpp
+++ b/mlir/lib/Dialect/Quant/Transforms/ConvertConst.cpp
@@ -22,7 +22,7 @@ using namespace mlir::quant;
 
 namespace {
 struct ConvertConstPass : public QuantConvertConstBase<ConvertConstPass> {
-  void runOnFunction() override;
+  void runOnOperation() override;
 };
 
 struct QuantizedConstRewrite : public OpRewritePattern<QuantizeCastOp> {
@@ -91,9 +91,9 @@ QuantizedConstRewrite::matchAndRewrite(QuantizeCastOp qbarrier,
   return success();
 }
 
-void ConvertConstPass::runOnFunction() {
+void ConvertConstPass::runOnOperation() {
   RewritePatternSet patterns(&getContext());
-  auto func = getFunction();
+  auto func = getOperation();
   auto *context = &getContext();
   patterns.add<QuantizedConstRewrite>(context);
   (void)applyPatternsAndFoldGreedily(func, std::move(patterns));

diff  --git a/mlir/lib/Dialect/Quant/Transforms/ConvertSimQuant.cpp b/mlir/lib/Dialect/Quant/Transforms/ConvertSimQuant.cpp
index 7920bee01c51f..faad830fd05a3 100644
--- a/mlir/lib/Dialect/Quant/Transforms/ConvertSimQuant.cpp
+++ b/mlir/lib/Dialect/Quant/Transforms/ConvertSimQuant.cpp
@@ -20,7 +20,7 @@ using namespace mlir::quant;
 namespace {
 struct ConvertSimulatedQuantPass
     : public QuantConvertSimulatedQuantBase<ConvertSimulatedQuantPass> {
-  void runOnFunction() override;
+  void runOnOperation() override;
 };
 
 /// Base class rewrites ConstFakeQuant into a qbarrier/dbarrier pair.
@@ -122,9 +122,9 @@ class ConstFakeQuantPerAxisRewrite
 
 } // namespace
 
-void ConvertSimulatedQuantPass::runOnFunction() {
+void ConvertSimulatedQuantPass::runOnOperation() {
   bool hadFailure = false;
-  auto func = getFunction();
+  auto func = getOperation();
   RewritePatternSet patterns(func.getContext());
   auto *ctx = func.getContext();
   patterns.add<ConstFakeQuantRewrite, ConstFakeQuantPerAxisRewrite>(

diff  --git a/mlir/lib/Dialect/SCF/Transforms/Bufferize.cpp b/mlir/lib/Dialect/SCF/Transforms/Bufferize.cpp
index a3f9b5b8ca847..b31593b90ea67 100644
--- a/mlir/lib/Dialect/SCF/Transforms/Bufferize.cpp
+++ b/mlir/lib/Dialect/SCF/Transforms/Bufferize.cpp
@@ -21,7 +21,7 @@ using namespace mlir::scf;
 
 namespace {
 struct SCFBufferizePass : public SCFBufferizeBase<SCFBufferizePass> {
-  void runOnFunction() override {
+  void runOnOperation() override {
     auto func = getOperation();
     auto *context = &getContext();
 

diff  --git a/mlir/lib/Dialect/SCF/Transforms/ForToWhile.cpp b/mlir/lib/Dialect/SCF/Transforms/ForToWhile.cpp
index d74b5d0457ccf..a297c7bb06b4a 100644
--- a/mlir/lib/Dialect/SCF/Transforms/ForToWhile.cpp
+++ b/mlir/lib/Dialect/SCF/Transforms/ForToWhile.cpp
@@ -96,8 +96,8 @@ struct ForLoopLoweringPattern : public OpRewritePattern<ForOp> {
 };
 
 struct ForToWhileLoop : public SCFForToWhileLoopBase<ForToWhileLoop> {
-  void runOnFunction() override {
-    FuncOp funcOp = getFunction();
+  void runOnOperation() override {
+    FuncOp funcOp = getOperation();
     MLIRContext *ctx = funcOp.getContext();
     RewritePatternSet patterns(ctx);
     patterns.add<ForLoopLoweringPattern>(ctx);

diff  --git a/mlir/lib/Dialect/SCF/Transforms/LoopCanonicalization.cpp b/mlir/lib/Dialect/SCF/Transforms/LoopCanonicalization.cpp
index 1c133979b22c1..a0cdb41a2d4de 100644
--- a/mlir/lib/Dialect/SCF/Transforms/LoopCanonicalization.cpp
+++ b/mlir/lib/Dialect/SCF/Transforms/LoopCanonicalization.cpp
@@ -181,8 +181,8 @@ struct AffineOpSCFCanonicalizationPattern : public OpRewritePattern<OpTy> {
 
 struct SCFForLoopCanonicalization
     : public SCFForLoopCanonicalizationBase<SCFForLoopCanonicalization> {
-  void runOnFunction() override {
-    FuncOp funcOp = getFunction();
+  void runOnOperation() override {
+    FuncOp funcOp = getOperation();
     MLIRContext *ctx = funcOp.getContext();
     RewritePatternSet patterns(ctx);
     scf::populateSCFForLoopCanonicalizationPatterns(patterns);

diff  --git a/mlir/lib/Dialect/SCF/Transforms/LoopSpecialization.cpp b/mlir/lib/Dialect/SCF/Transforms/LoopSpecialization.cpp
index acdc95c059e95..103dbac12125a 100644
--- a/mlir/lib/Dialect/SCF/Transforms/LoopSpecialization.cpp
+++ b/mlir/lib/Dialect/SCF/Transforms/LoopSpecialization.cpp
@@ -237,22 +237,22 @@ struct ForLoopPeelingPattern : public OpRewritePattern<ForOp> {
 namespace {
 struct ParallelLoopSpecialization
     : public SCFParallelLoopSpecializationBase<ParallelLoopSpecialization> {
-  void runOnFunction() override {
-    getFunction().walk(
+  void runOnOperation() override {
+    getOperation().walk(
         [](ParallelOp op) { specializeParallelLoopForUnrolling(op); });
   }
 };
 
 struct ForLoopSpecialization
     : public SCFForLoopSpecializationBase<ForLoopSpecialization> {
-  void runOnFunction() override {
-    getFunction().walk([](ForOp op) { specializeForLoopForUnrolling(op); });
+  void runOnOperation() override {
+    getOperation().walk([](ForOp op) { specializeForLoopForUnrolling(op); });
   }
 };
 
 struct ForLoopPeeling : public SCFForLoopPeelingBase<ForLoopPeeling> {
-  void runOnFunction() override {
-    FuncOp funcOp = getFunction();
+  void runOnOperation() override {
+    FuncOp funcOp = getOperation();
     MLIRContext *ctx = funcOp.getContext();
     RewritePatternSet patterns(ctx);
     patterns.add<ForLoopPeelingPattern>(ctx, skipPartial);

diff  --git a/mlir/lib/Dialect/SCF/Transforms/ParallelLoopTiling.cpp b/mlir/lib/Dialect/SCF/Transforms/ParallelLoopTiling.cpp
index 8bf32ac68c7f7..0bf4917bfee1f 100644
--- a/mlir/lib/Dialect/SCF/Transforms/ParallelLoopTiling.cpp
+++ b/mlir/lib/Dialect/SCF/Transforms/ParallelLoopTiling.cpp
@@ -195,9 +195,9 @@ struct ParallelLoopTiling
     this->noMinMaxBounds = noMinMaxBounds;
   }
 
-  void runOnFunction() override {
+  void runOnOperation() override {
     SmallVector<ParallelOp, 2> innermostPloops;
-    getInnermostParallelLoops(getFunction().getOperation(), innermostPloops);
+    getInnermostParallelLoops(getOperation().getOperation(), innermostPloops);
     for (ParallelOp ploop : innermostPloops) {
       // FIXME: Add reduction support.
       if (ploop.getNumReductions() == 0)

diff  --git a/mlir/lib/Dialect/Shape/Transforms/Bufferize.cpp b/mlir/lib/Dialect/Shape/Transforms/Bufferize.cpp
index 670c9eeba5147..7b712dc9176fa 100644
--- a/mlir/lib/Dialect/Shape/Transforms/Bufferize.cpp
+++ b/mlir/lib/Dialect/Shape/Transforms/Bufferize.cpp
@@ -17,7 +17,7 @@ using namespace mlir;
 
 namespace {
 struct ShapeBufferizePass : public ShapeBufferizeBase<ShapeBufferizePass> {
-  void runOnFunction() override {
+  void runOnOperation() override {
     MLIRContext &ctx = getContext();
 
     RewritePatternSet patterns(&ctx);
@@ -28,13 +28,13 @@ struct ShapeBufferizePass : public ShapeBufferizeBase<ShapeBufferizePass> {
     populateShapeStructuralTypeConversionsAndLegality(typeConverter, patterns,
                                                       target);
 
-    if (failed(
-            applyPartialConversion(getFunction(), target, std::move(patterns))))
+    if (failed(applyPartialConversion(getOperation(), target,
+                                      std::move(patterns))))
       signalPassFailure();
   }
 };
 } // namespace
 
-std::unique_ptr<FunctionPass> mlir::createShapeBufferizePass() {
+std::unique_ptr<OperationPass<FuncOp>> mlir::createShapeBufferizePass() {
   return std::make_unique<ShapeBufferizePass>();
 }

diff  --git a/mlir/lib/Dialect/Shape/Transforms/RemoveShapeConstraints.cpp b/mlir/lib/Dialect/Shape/Transforms/RemoveShapeConstraints.cpp
index dc403b0ceacd8..506b260927edf 100644
--- a/mlir/lib/Dialect/Shape/Transforms/RemoveShapeConstraints.cpp
+++ b/mlir/lib/Dialect/Shape/Transforms/RemoveShapeConstraints.cpp
@@ -43,13 +43,13 @@ class RemoveCstrEqOp : public OpRewritePattern<shape::CstrEqOp> {
 class RemoveShapeConstraintsPass
     : public RemoveShapeConstraintsBase<RemoveShapeConstraintsPass> {
 
-  void runOnFunction() override {
+  void runOnOperation() override {
     MLIRContext &ctx = getContext();
 
     RewritePatternSet patterns(&ctx);
     populateRemoveShapeConstraintsPatterns(patterns);
 
-    (void)applyPatternsAndFoldGreedily(getFunction(), std::move(patterns));
+    (void)applyPatternsAndFoldGreedily(getOperation(), std::move(patterns));
   }
 };
 
@@ -60,6 +60,7 @@ void mlir::populateRemoveShapeConstraintsPatterns(RewritePatternSet &patterns) {
       patterns.getContext());
 }
 
-std::unique_ptr<FunctionPass> mlir::createRemoveShapeConstraintsPass() {
+std::unique_ptr<OperationPass<FuncOp>>
+mlir::createRemoveShapeConstraintsPass() {
   return std::make_unique<RemoveShapeConstraintsPass>();
 }

diff  --git a/mlir/lib/Dialect/Shape/Transforms/ShapeToShapeLowering.cpp b/mlir/lib/Dialect/Shape/Transforms/ShapeToShapeLowering.cpp
index 3c1b84023ce94..e9e7f00c61644 100644
--- a/mlir/lib/Dialect/Shape/Transforms/ShapeToShapeLowering.cpp
+++ b/mlir/lib/Dialect/Shape/Transforms/ShapeToShapeLowering.cpp
@@ -55,11 +55,11 @@ NumElementsOpConverter::matchAndRewrite(NumElementsOp op,
 namespace {
 struct ShapeToShapeLowering
     : public ShapeToShapeLoweringBase<ShapeToShapeLowering> {
-  void runOnFunction() override;
+  void runOnOperation() override;
 };
 } // namespace
 
-void ShapeToShapeLowering::runOnFunction() {
+void ShapeToShapeLowering::runOnOperation() {
   MLIRContext &ctx = getContext();
 
   RewritePatternSet patterns(&ctx);
@@ -69,7 +69,7 @@ void ShapeToShapeLowering::runOnFunction() {
   target.addLegalDialect<arith::ArithmeticDialect, ShapeDialect,
                          StandardOpsDialect>();
   target.addIllegalOp<NumElementsOp>();
-  if (failed(mlir::applyPartialConversion(getFunction(), target,
+  if (failed(mlir::applyPartialConversion(getOperation(), target,
                                           std::move(patterns))))
     signalPassFailure();
 }

diff  --git a/mlir/lib/Dialect/StandardOps/Transforms/Bufferize.cpp b/mlir/lib/Dialect/StandardOps/Transforms/Bufferize.cpp
index 1af5233adc483..9851784d4951c 100644
--- a/mlir/lib/Dialect/StandardOps/Transforms/Bufferize.cpp
+++ b/mlir/lib/Dialect/StandardOps/Transforms/Bufferize.cpp
@@ -49,7 +49,7 @@ void mlir::populateStdBufferizePatterns(
 
 namespace {
 struct StdBufferizePass : public StdBufferizeBase<StdBufferizePass> {
-  void runOnFunction() override {
+  void runOnOperation() override {
     auto *context = &getContext();
     bufferization::BufferizeTypeConverter typeConverter;
     RewritePatternSet patterns(context);
@@ -66,8 +66,8 @@ struct StdBufferizePass : public StdBufferizeBase<StdBufferizePass> {
       return typeConverter.isLegal(op.getType()) ||
              !op.getCondition().getType().isa<IntegerType>();
     });
-    if (failed(
-            applyPartialConversion(getFunction(), target, std::move(patterns))))
+    if (failed(applyPartialConversion(getOperation(), target,
+                                      std::move(patterns))))
       signalPassFailure();
   }
 };

diff  --git a/mlir/lib/Dialect/StandardOps/Transforms/ExpandOps.cpp b/mlir/lib/Dialect/StandardOps/Transforms/ExpandOps.cpp
index a62f6a076f936..d7c7755e24029 100644
--- a/mlir/lib/Dialect/StandardOps/Transforms/ExpandOps.cpp
+++ b/mlir/lib/Dialect/StandardOps/Transforms/ExpandOps.cpp
@@ -121,7 +121,7 @@ struct MemRefReshapeOpConverter : public OpRewritePattern<memref::ReshapeOp> {
 };
 
 struct StdExpandOpsPass : public StdExpandOpsBase<StdExpandOpsPass> {
-  void runOnFunction() override {
+  void runOnOperation() override {
     MLIRContext &ctx = getContext();
 
     RewritePatternSet patterns(&ctx);
@@ -138,8 +138,8 @@ struct StdExpandOpsPass : public StdExpandOpsBase<StdExpandOpsPass> {
     target.addDynamicallyLegalOp<memref::ReshapeOp>([](memref::ReshapeOp op) {
       return !op.shape().getType().cast<MemRefType>().hasStaticShape();
     });
-    if (failed(
-            applyPartialConversion(getFunction(), target, std::move(patterns))))
+    if (failed(applyPartialConversion(getOperation(), target,
+                                      std::move(patterns))))
       signalPassFailure();
   }
 };

diff  --git a/mlir/lib/Dialect/Tensor/Transforms/Bufferize.cpp b/mlir/lib/Dialect/Tensor/Transforms/Bufferize.cpp
index e4369c53112d3..0bd01dabdfef5 100644
--- a/mlir/lib/Dialect/Tensor/Transforms/Bufferize.cpp
+++ b/mlir/lib/Dialect/Tensor/Transforms/Bufferize.cpp
@@ -198,7 +198,7 @@ struct BufferizeRankOp : public OpConversionPattern<tensor::RankOp> {
 };
 
 struct TensorBufferizePass : public TensorBufferizeBase<TensorBufferizePass> {
-  void runOnFunction() override {
+  void runOnOperation() override {
     auto *context = &getContext();
     bufferization::BufferizeTypeConverter typeConverter;
 
@@ -214,8 +214,8 @@ struct TensorBufferizePass : public TensorBufferizeBase<TensorBufferizePass> {
 
     RewritePatternSet patterns(context);
     populateTensorBufferizePatterns(typeConverter, patterns);
-    if (failed(
-            applyPartialConversion(getFunction(), target, std::move(patterns))))
+    if (failed(applyPartialConversion(getOperation(), target,
+                                      std::move(patterns))))
       signalPassFailure();
   }
 };

diff  --git a/mlir/lib/Dialect/Tosa/Transforms/TosaInferShapes.cpp b/mlir/lib/Dialect/Tosa/Transforms/TosaInferShapes.cpp
index 3a50336c3d4ab..c23830259f9a5 100644
--- a/mlir/lib/Dialect/Tosa/Transforms/TosaInferShapes.cpp
+++ b/mlir/lib/Dialect/Tosa/Transforms/TosaInferShapes.cpp
@@ -278,7 +278,7 @@ void propagateShapesInRegion(Region &region) {
 /// migrating to within the regions of if/while operations.
 struct TosaInferShapes : public TosaInferShapesBase<TosaInferShapes> {
 public:
-  void runOnFunction() override {
+  void runOnOperation() override {
     FuncOp func = getOperation();
 
     IRRewriter rewriter(func.getContext());

diff  --git a/mlir/lib/Dialect/Tosa/Transforms/TosaMakeBroadcastable.cpp b/mlir/lib/Dialect/Tosa/Transforms/TosaMakeBroadcastable.cpp
index d3b2297059b1e..134ae6f333946 100644
--- a/mlir/lib/Dialect/Tosa/Transforms/TosaMakeBroadcastable.cpp
+++ b/mlir/lib/Dialect/Tosa/Transforms/TosaMakeBroadcastable.cpp
@@ -235,8 +235,8 @@ namespace {
 struct TosaMakeBroadcastable
     : public TosaMakeBroadcastableBase<TosaMakeBroadcastable> {
 public:
-  void runOnFunction() override {
-    auto func = getFunction();
+  void runOnOperation() override {
+    auto func = getOperation();
     RewritePatternSet patterns(func.getContext());
     MLIRContext *ctx = func.getContext();
     // Add the generated patterns to the list.

diff  --git a/mlir/lib/Dialect/Tosa/Transforms/TosaOptionalDecompositions.cpp b/mlir/lib/Dialect/Tosa/Transforms/TosaOptionalDecompositions.cpp
index d0a8f16c1d7da..0bf9eed621107 100644
--- a/mlir/lib/Dialect/Tosa/Transforms/TosaOptionalDecompositions.cpp
+++ b/mlir/lib/Dialect/Tosa/Transforms/TosaOptionalDecompositions.cpp
@@ -25,10 +25,10 @@ namespace {
 
 struct TosaOptionalDecompositions
     : public TosaOptionalDecompositionsBase<TosaOptionalDecompositions> {
-  void runOnFunction() override {
+  void runOnOperation() override {
     auto *ctx = &getContext();
     RewritePatternSet patterns(ctx);
-    auto func = getFunction();
+    auto func = getOperation();
 
     mlir::tosa::populateTosaDecomposeConv2D(ctx, patterns);
     mlir::tosa::populateTosaDecomposeTransposeConv(ctx, patterns);

diff  --git a/mlir/lib/Transforms/BufferOptimizations.cpp b/mlir/lib/Transforms/BufferOptimizations.cpp
index 9421e85193b12..4fa035a939923 100644
--- a/mlir/lib/Transforms/BufferOptimizations.cpp
+++ b/mlir/lib/Transforms/BufferOptimizations.cpp
@@ -364,10 +364,10 @@ class BufferPlacementPromotion : BufferPlacementTransformationBase {
 /// blocks.
 struct BufferHoistingPass : BufferHoistingBase<BufferHoistingPass> {
 
-  void runOnFunction() override {
+  void runOnOperation() override {
     // Hoist all allocations into dominator blocks.
     BufferAllocationHoisting<BufferAllocationHoistingState> optimizer(
-        getFunction());
+        getOperation());
     optimizer.hoist();
   }
 };
@@ -375,10 +375,10 @@ struct BufferHoistingPass : BufferHoistingBase<BufferHoistingPass> {
 /// The buffer loop hoisting pass that hoists allocation nodes out of loops.
 struct BufferLoopHoistingPass : BufferLoopHoistingBase<BufferLoopHoistingPass> {
 
-  void runOnFunction() override {
+  void runOnOperation() override {
     // Hoist all allocations out of loops.
     BufferAllocationHoisting<BufferAllocationLoopHoistingState> optimizer(
-        getFunction());
+        getOperation());
     optimizer.hoist();
   }
 };
@@ -410,9 +410,9 @@ class PromoteBuffersToStackPass
     return success();
   }
 
-  void runOnFunction() override {
+  void runOnOperation() override {
     // Move all allocation nodes and convert candidates into allocas.
-    BufferPlacementPromotion optimizer(getFunction());
+    BufferPlacementPromotion optimizer(getOperation());
     optimizer.promote(isSmallAlloc);
   }
 

diff  --git a/mlir/lib/Transforms/LoopCoalescing.cpp b/mlir/lib/Transforms/LoopCoalescing.cpp
index 32a7e52e42bf8..4b6780398103a 100644
--- a/mlir/lib/Transforms/LoopCoalescing.cpp
+++ b/mlir/lib/Transforms/LoopCoalescing.cpp
@@ -83,8 +83,8 @@ struct LoopCoalescingPass : public LoopCoalescingBase<LoopCoalescingPass> {
     }
   }
 
-  void runOnFunction() override {
-    FuncOp func = getFunction();
+  void runOnOperation() override {
+    FuncOp func = getOperation();
     func.walk([&](Operation *op) {
       if (auto scfForOp = dyn_cast<scf::ForOp>(op))
         walkLoop(scfForOp);

diff  --git a/mlir/lib/Transforms/LoopFusion.cpp b/mlir/lib/Transforms/LoopFusion.cpp
index 9646eeb5f9b80..3ab98e0ee20cb 100644
--- a/mlir/lib/Transforms/LoopFusion.cpp
+++ b/mlir/lib/Transforms/LoopFusion.cpp
@@ -56,7 +56,7 @@ struct LoopFusion : public AffineLoopFusionBase<LoopFusion> {
     this->affineFusionMode = affineFusionMode;
   }
 
-  void runOnFunction() override;
+  void runOnOperation() override;
 };
 
 } // namespace
@@ -1975,9 +1975,9 @@ struct GreedyFusion {
 
 } // namespace
 
-void LoopFusion::runOnFunction() {
+void LoopFusion::runOnOperation() {
   MemRefDependenceGraph g;
-  if (!g.init(getFunction()))
+  if (!g.init(getOperation()))
     return;
 
   Optional<unsigned> fastMemorySpaceOpt;

diff  --git a/mlir/lib/Transforms/PipelineDataTransfer.cpp b/mlir/lib/Transforms/PipelineDataTransfer.cpp
index 1b1a9ccdc864b..87ac14e770249 100644
--- a/mlir/lib/Transforms/PipelineDataTransfer.cpp
+++ b/mlir/lib/Transforms/PipelineDataTransfer.cpp
@@ -32,7 +32,7 @@ using namespace mlir;
 namespace {
 struct PipelineDataTransfer
     : public AffinePipelineDataTransferBase<PipelineDataTransfer> {
-  void runOnFunction() override;
+  void runOnOperation() override;
   void runOnAffineForOp(AffineForOp forOp);
 
   std::vector<AffineForOp> forOps;
@@ -124,14 +124,14 @@ static bool doubleBuffer(Value oldMemRef, AffineForOp forOp) {
 }
 
 /// Returns success if the IR is in a valid state.
-void PipelineDataTransfer::runOnFunction() {
+void PipelineDataTransfer::runOnOperation() {
   // Do a post order walk so that inner loop DMAs are processed first. This is
   // necessary since 'affine.for' operations nested within would otherwise
   // become invalid (erased) when the outer loop is pipelined (the pipelined one
   // gets deleted and replaced by a prologue, a new steady-state loop and an
   // epilogue).
   forOps.clear();
-  getFunction().walk([&](AffineForOp forOp) { forOps.push_back(forOp); });
+  getOperation().walk([&](AffineForOp forOp) { forOps.push_back(forOp); });
   for (auto forOp : forOps)
     runOnAffineForOp(forOp);
 }

diff  --git a/mlir/test/lib/Analysis/TestLiveness.cpp b/mlir/test/lib/Analysis/TestLiveness.cpp
index 287f742783bba..0f758d557b18b 100644
--- a/mlir/test/lib/Analysis/TestLiveness.cpp
+++ b/mlir/test/lib/Analysis/TestLiveness.cpp
@@ -19,13 +19,14 @@ using namespace mlir;
 
 namespace {
 
-struct TestLivenessPass : public PassWrapper<TestLivenessPass, FunctionPass> {
+struct TestLivenessPass
+    : public PassWrapper<TestLivenessPass, OperationPass<FuncOp>> {
   StringRef getArgument() const final { return "test-print-liveness"; }
   StringRef getDescription() const final {
     return "Print the contents of a constructed liveness information.";
   }
-  void runOnFunction() override {
-    llvm::errs() << "Testing : " << getFunction().getName() << "\n";
+  void runOnOperation() override {
+    llvm::errs() << "Testing : " << getOperation().getName() << "\n";
     getAnalysis<Liveness>().print(llvm::errs());
   }
 };

diff  --git a/mlir/test/lib/Analysis/TestMatchReduction.cpp b/mlir/test/lib/Analysis/TestMatchReduction.cpp
index ee5170516b840..843e37359082c 100644
--- a/mlir/test/lib/Analysis/TestMatchReduction.cpp
+++ b/mlir/test/lib/Analysis/TestMatchReduction.cpp
@@ -34,14 +34,14 @@ void printReductionResult(Operation *redRegionOp, unsigned numOutput,
 }
 
 struct TestMatchReductionPass
-    : public PassWrapper<TestMatchReductionPass, FunctionPass> {
+    : public PassWrapper<TestMatchReductionPass, OperationPass<FuncOp>> {
   StringRef getArgument() const final { return "test-match-reduction"; }
   StringRef getDescription() const final {
     return "Test the match reduction utility.";
   }
 
-  void runOnFunction() override {
-    FuncOp func = getFunction();
+  void runOnOperation() override {
+    FuncOp func = getOperation();
     func->emitRemark("Testing function");
 
     func.walk<WalkOrder::PreOrder>([](Operation *op) {

diff  --git a/mlir/test/lib/Analysis/TestMemRefBoundCheck.cpp b/mlir/test/lib/Analysis/TestMemRefBoundCheck.cpp
index 6931d8c0f8338..ea0e6ddb0ea42 100644
--- a/mlir/test/lib/Analysis/TestMemRefBoundCheck.cpp
+++ b/mlir/test/lib/Analysis/TestMemRefBoundCheck.cpp
@@ -28,18 +28,18 @@ namespace {
 
 /// Checks for out of bound memref access subscripts..
 struct TestMemRefBoundCheck
-    : public PassWrapper<TestMemRefBoundCheck, FunctionPass> {
+    : public PassWrapper<TestMemRefBoundCheck, OperationPass<FuncOp>> {
   StringRef getArgument() const final { return "test-memref-bound-check"; }
   StringRef getDescription() const final {
     return "Check memref access bounds in a Function";
   }
-  void runOnFunction() override;
+  void runOnOperation() override;
 };
 
 } // namespace
 
-void TestMemRefBoundCheck::runOnFunction() {
-  getFunction().walk([](Operation *opInst) {
+void TestMemRefBoundCheck::runOnOperation() {
+  getOperation().walk([](Operation *opInst) {
     TypeSwitch<Operation *>(opInst)
         .Case<AffineReadOpInterface, AffineWriteOpInterface>(
             [](auto op) { (void)boundCheckLoadOrStoreOp(op); });

diff  --git a/mlir/test/lib/Analysis/TestMemRefDependenceCheck.cpp b/mlir/test/lib/Analysis/TestMemRefDependenceCheck.cpp
index bbe18b0b186ed..066076970ace9 100644
--- a/mlir/test/lib/Analysis/TestMemRefDependenceCheck.cpp
+++ b/mlir/test/lib/Analysis/TestMemRefDependenceCheck.cpp
@@ -27,13 +27,13 @@ namespace {
 // TODO: Add common surrounding loop depth-wise dependence checks.
 /// Checks dependences between all pairs of memref accesses in a Function.
 struct TestMemRefDependenceCheck
-    : public PassWrapper<TestMemRefDependenceCheck, FunctionPass> {
+    : public PassWrapper<TestMemRefDependenceCheck, OperationPass<FuncOp>> {
   StringRef getArgument() const final { return "test-memref-dependence-check"; }
   StringRef getDescription() const final {
     return "Checks dependences between all pairs of memref accesses.";
   }
   SmallVector<Operation *, 4> loadsAndStores;
-  void runOnFunction() override;
+  void runOnOperation() override;
 };
 
 } // namespace
@@ -102,10 +102,10 @@ static void checkDependences(ArrayRef<Operation *> loadsAndStores) {
 
 // Walks the Function 'f' adding load and store ops to 'loadsAndStores'.
 // Runs pair-wise dependence checks.
-void TestMemRefDependenceCheck::runOnFunction() {
+void TestMemRefDependenceCheck::runOnOperation() {
   // Collect the loads and stores within the function.
   loadsAndStores.clear();
-  getFunction().walk([&](Operation *op) {
+  getOperation().walk([&](Operation *op) {
     if (isa<AffineLoadOp, AffineStoreOp>(op))
       loadsAndStores.push_back(op);
   });

diff  --git a/mlir/test/lib/Analysis/TestMemRefStrideCalculation.cpp b/mlir/test/lib/Analysis/TestMemRefStrideCalculation.cpp
index 8142024b63606..a0b9d039093c4 100644
--- a/mlir/test/lib/Analysis/TestMemRefStrideCalculation.cpp
+++ b/mlir/test/lib/Analysis/TestMemRefStrideCalculation.cpp
@@ -14,21 +14,21 @@ using namespace mlir;
 
 namespace {
 struct TestMemRefStrideCalculation
-    : public PassWrapper<TestMemRefStrideCalculation, FunctionPass> {
+    : public PassWrapper<TestMemRefStrideCalculation, OperationPass<FuncOp>> {
   StringRef getArgument() const final {
     return "test-memref-stride-calculation";
   }
   StringRef getDescription() const final {
     return "Test operation constant folding";
   }
-  void runOnFunction() override;
+  void runOnOperation() override;
 };
 } // namespace
 
 /// Traverse AllocOp and compute strides of each MemRefType independently.
-void TestMemRefStrideCalculation::runOnFunction() {
-  llvm::outs() << "Testing: " << getFunction().getName() << "\n";
-  getFunction().walk([&](memref::AllocOp allocOp) {
+void TestMemRefStrideCalculation::runOnOperation() {
+  llvm::outs() << "Testing: " << getOperation().getName() << "\n";
+  getOperation().walk([&](memref::AllocOp allocOp) {
     auto memrefType = allocOp.getResult().getType().cast<MemRefType>();
     int64_t offset;
     SmallVector<int64_t, 4> strides;

diff  --git a/mlir/test/lib/Analysis/TestSlice.cpp b/mlir/test/lib/Analysis/TestSlice.cpp
index dbdcfd950cbbe..1a1cc4c1ea576 100644
--- a/mlir/test/lib/Analysis/TestSlice.cpp
+++ b/mlir/test/lib/Analysis/TestSlice.cpp
@@ -16,14 +16,14 @@ static const StringLiteral kOrderMarker = "__test_sort_original_idx__";
 namespace {
 
 struct TestTopologicalSortPass
-    : public PassWrapper<TestTopologicalSortPass, FunctionPass> {
+    : public PassWrapper<TestTopologicalSortPass, OperationPass<FuncOp>> {
   StringRef getArgument() const final { return "test-print-topological-sort"; }
   StringRef getDescription() const final {
     return "Print operations in topological order";
   }
-  void runOnFunction() override {
+  void runOnOperation() override {
     std::map<int, Operation *> ops;
-    getFunction().walk([&ops](Operation *op) {
+    getOperation().walk([&ops](Operation *op) {
       if (auto originalOrderAttr = op->getAttrOfType<IntegerAttr>(kOrderMarker))
         ops[originalOrderAttr.getInt()] = op;
     });
@@ -31,7 +31,7 @@ struct TestTopologicalSortPass
     for (auto op : ops)
       sortedOp.insert(op.second);
     sortedOp = topologicalSort(sortedOp);
-    llvm::errs() << "Testing : " << getFunction().getName() << "\n";
+    llvm::errs() << "Testing : " << getOperation().getName() << "\n";
     for (Operation *op : sortedOp) {
       op->print(llvm::errs());
       llvm::errs() << "\n";

diff  --git a/mlir/test/lib/Dialect/Affine/TestAffineDataCopy.cpp b/mlir/test/lib/Dialect/Affine/TestAffineDataCopy.cpp
index d618da4421901..400af2a66ba7c 100644
--- a/mlir/test/lib/Dialect/Affine/TestAffineDataCopy.cpp
+++ b/mlir/test/lib/Dialect/Affine/TestAffineDataCopy.cpp
@@ -28,7 +28,7 @@ static llvm::cl::OptionCategory clOptionsCategory(PASS_NAME " options");
 namespace {
 
 struct TestAffineDataCopy
-    : public PassWrapper<TestAffineDataCopy, FunctionPass> {
+    : public PassWrapper<TestAffineDataCopy, OperationPass<FuncOp>> {
   StringRef getArgument() const final { return PASS_NAME; }
   StringRef getDescription() const final {
     return "Tests affine data copy utility functions.";
@@ -39,7 +39,7 @@ struct TestAffineDataCopy
   void getDependentDialects(DialectRegistry &registry) const override {
     registry.insert<memref::MemRefDialect>();
   }
-  void runOnFunction() override;
+  void runOnOperation() override;
 
 private:
   Option<bool> clMemRefFilter{
@@ -55,10 +55,10 @@ struct TestAffineDataCopy
 
 } // namespace
 
-void TestAffineDataCopy::runOnFunction() {
+void TestAffineDataCopy::runOnOperation() {
   // Gather all AffineForOps by loop depth.
   std::vector<SmallVector<AffineForOp, 2>> depthToLoops;
-  gatherLoops(getFunction(), depthToLoops);
+  gatherLoops(getOperation(), depthToLoops);
   assert(!depthToLoops.empty() && "Loop nest not found");
 
   // Only support tests with a single loop nest and a single innermost loop

diff  --git a/mlir/test/lib/Dialect/Affine/TestAffineLoopParametricTiling.cpp b/mlir/test/lib/Dialect/Affine/TestAffineLoopParametricTiling.cpp
index 6038ec3b25f4e..d215a3a792dd6 100644
--- a/mlir/test/lib/Dialect/Affine/TestAffineLoopParametricTiling.cpp
+++ b/mlir/test/lib/Dialect/Affine/TestAffineLoopParametricTiling.cpp
@@ -21,12 +21,13 @@ using namespace mlir;
 
 namespace {
 struct TestAffineLoopParametricTiling
-    : public PassWrapper<TestAffineLoopParametricTiling, FunctionPass> {
+    : public PassWrapper<TestAffineLoopParametricTiling,
+                         OperationPass<FuncOp>> {
   StringRef getArgument() const final { return "test-affine-parametric-tile"; }
   StringRef getDescription() const final {
     return "Tile affine loops using SSA values as tile sizes";
   }
-  void runOnFunction() override;
+  void runOnOperation() override;
 };
 } // namespace
 
@@ -61,10 +62,10 @@ static void getTilingParameters(ArrayRef<AffineForOp> band,
   }
 }
 
-void TestAffineLoopParametricTiling::runOnFunction() {
+void TestAffineLoopParametricTiling::runOnOperation() {
   // Bands of loops to tile.
   std::vector<SmallVector<AffineForOp, 6>> bands;
-  getTileableBands(getFunction(), &bands);
+  getTileableBands(getOperation(), &bands);
 
   // Tile each band.
   for (MutableArrayRef<AffineForOp> band : bands) {

diff  --git a/mlir/test/lib/Dialect/Affine/TestAffineLoopUnswitching.cpp b/mlir/test/lib/Dialect/Affine/TestAffineLoopUnswitching.cpp
index 837c64aa0ea0f..cd75a505e6409 100644
--- a/mlir/test/lib/Dialect/Affine/TestAffineLoopUnswitching.cpp
+++ b/mlir/test/lib/Dialect/Affine/TestAffineLoopUnswitching.cpp
@@ -24,7 +24,7 @@ namespace {
 
 /// This pass applies the permutation on the first maximal perfect nest.
 struct TestAffineLoopUnswitching
-    : public PassWrapper<TestAffineLoopUnswitching, FunctionPass> {
+    : public PassWrapper<TestAffineLoopUnswitching, OperationPass<FuncOp>> {
   StringRef getArgument() const final { return PASS_NAME; }
   StringRef getDescription() const final {
     return "Tests affine loop unswitching / if/else hoisting";
@@ -32,7 +32,7 @@ struct TestAffineLoopUnswitching
   TestAffineLoopUnswitching() = default;
   TestAffineLoopUnswitching(const TestAffineLoopUnswitching &pass) = default;
 
-  void runOnFunction() override;
+  void runOnOperation() override;
 
   /// The maximum number of iterations to run this for.
   constexpr static unsigned kMaxIterations = 5;
@@ -40,11 +40,11 @@ struct TestAffineLoopUnswitching
 
 } // namespace
 
-void TestAffineLoopUnswitching::runOnFunction() {
+void TestAffineLoopUnswitching::runOnOperation() {
   // Each hoisting invalidates a lot of IR around. Just stop the walk after the
   // first if/else hoisting, and repeat until no more hoisting can be done, or
   // the maximum number of iterations have been run.
-  auto func = getFunction();
+  auto func = getOperation();
   unsigned i = 0;
   do {
     auto walkFn = [](AffineIfOp op) {

diff  --git a/mlir/test/lib/Dialect/Affine/TestLoopPermutation.cpp b/mlir/test/lib/Dialect/Affine/TestLoopPermutation.cpp
index 6db6c80e4c1cb..1db0981485e84 100644
--- a/mlir/test/lib/Dialect/Affine/TestLoopPermutation.cpp
+++ b/mlir/test/lib/Dialect/Affine/TestLoopPermutation.cpp
@@ -26,7 +26,7 @@ namespace {
 
 /// This pass applies the permutation on the first maximal perfect nest.
 struct TestLoopPermutation
-    : public PassWrapper<TestLoopPermutation, FunctionPass> {
+    : public PassWrapper<TestLoopPermutation, OperationPass<FuncOp>> {
   StringRef getArgument() const final { return PASS_NAME; }
   StringRef getDescription() const final {
     return "Tests affine loop permutation utility";
@@ -34,7 +34,7 @@ struct TestLoopPermutation
   TestLoopPermutation() = default;
   TestLoopPermutation(const TestLoopPermutation &pass) : PassWrapper(pass){};
 
-  void runOnFunction() override;
+  void runOnOperation() override;
 
 private:
   /// Permutation specifying loop i is mapped to permList[i] in
@@ -46,12 +46,12 @@ struct TestLoopPermutation
 
 } // namespace
 
-void TestLoopPermutation::runOnFunction() {
+void TestLoopPermutation::runOnOperation() {
 
   SmallVector<unsigned, 4> permMap(permList.begin(), permList.end());
 
   SmallVector<AffineForOp, 2> forOps;
-  getFunction().walk([&](AffineForOp forOp) { forOps.push_back(forOp); });
+  getOperation().walk([&](AffineForOp forOp) { forOps.push_back(forOp); });
 
   for (auto forOp : forOps) {
     SmallVector<AffineForOp, 6> nest;

diff  --git a/mlir/test/lib/Dialect/Affine/TestVectorizationUtils.cpp b/mlir/test/lib/Dialect/Affine/TestVectorizationUtils.cpp
index 06c9366248a09..958d3621a054a 100644
--- a/mlir/test/lib/Dialect/Affine/TestVectorizationUtils.cpp
+++ b/mlir/test/lib/Dialect/Affine/TestVectorizationUtils.cpp
@@ -69,7 +69,7 @@ static llvm::cl::opt<bool> clTestVecAffineLoopNest(
 
 namespace {
 struct VectorizerTestPass
-    : public PassWrapper<VectorizerTestPass, FunctionPass> {
+    : public PassWrapper<VectorizerTestPass, OperationPass<FuncOp>> {
   static constexpr auto kTestAffineMapOpName = "test_affine_map";
   static constexpr auto kTestAffineMapAttrName = "affine_map";
   void getDependentDialects(DialectRegistry &registry) const override {
@@ -80,7 +80,7 @@ struct VectorizerTestPass
     return "Tests vectorizer standalone functionality.";
   }
 
-  void runOnFunction() override;
+  void runOnOperation() override;
   void testVectorShapeRatio(llvm::raw_ostream &outs);
   void testForwardSlicing(llvm::raw_ostream &outs);
   void testBackwardSlicing(llvm::raw_ostream &outs);
@@ -94,7 +94,7 @@ struct VectorizerTestPass
 } // namespace
 
 void VectorizerTestPass::testVectorShapeRatio(llvm::raw_ostream &outs) {
-  auto f = getFunction();
+  auto f = getOperation();
   using matcher::Op;
   SmallVector<int64_t, 8> shape(clTestVectorShapeRatio.begin(),
                                 clTestVectorShapeRatio.end());
@@ -144,7 +144,7 @@ static NestedPattern patternTestSlicingOps() {
 }
 
 void VectorizerTestPass::testBackwardSlicing(llvm::raw_ostream &outs) {
-  auto f = getFunction();
+  auto f = getOperation();
   outs << "\n" << f.getName();
 
   SmallVector<NestedMatch, 8> matches;
@@ -160,7 +160,7 @@ void VectorizerTestPass::testBackwardSlicing(llvm::raw_ostream &outs) {
 }
 
 void VectorizerTestPass::testForwardSlicing(llvm::raw_ostream &outs) {
-  auto f = getFunction();
+  auto f = getOperation();
   outs << "\n" << f.getName();
 
   SmallVector<NestedMatch, 8> matches;
@@ -176,7 +176,7 @@ void VectorizerTestPass::testForwardSlicing(llvm::raw_ostream &outs) {
 }
 
 void VectorizerTestPass::testSlicing(llvm::raw_ostream &outs) {
-  auto f = getFunction();
+  auto f = getOperation();
   outs << "\n" << f.getName();
 
   SmallVector<NestedMatch, 8> matches;
@@ -195,7 +195,7 @@ static bool customOpWithAffineMapAttribute(Operation &op) {
 }
 
 void VectorizerTestPass::testComposeMaps(llvm::raw_ostream &outs) {
-  auto f = getFunction();
+  auto f = getOperation();
 
   using matcher::Op;
   auto pattern = Op(customOpWithAffineMapAttribute);
@@ -220,7 +220,7 @@ void VectorizerTestPass::testComposeMaps(llvm::raw_ostream &outs) {
 /// Test for 'vectorizeAffineLoopNest' utility.
 void VectorizerTestPass::testVecAffineLoopNest() {
   std::vector<SmallVector<AffineForOp, 2>> loops;
-  gatherLoops(getFunction(), loops);
+  gatherLoops(getOperation(), loops);
 
   // Expected only one loop nest.
   if (loops.empty() || loops[0].size() != 1)
@@ -236,9 +236,9 @@ void VectorizerTestPass::testVecAffineLoopNest() {
   (void)vectorizeAffineLoopNest(loopsToVectorize, strategy);
 }
 
-void VectorizerTestPass::runOnFunction() {
+void VectorizerTestPass::runOnOperation() {
   // Only support single block functions at this point.
-  FuncOp f = getFunction();
+  FuncOp f = getOperation();
   if (!llvm::hasSingleElement(f))
     return;
 

diff  --git a/mlir/test/lib/Dialect/DLTI/TestDataLayoutQuery.cpp b/mlir/test/lib/Dialect/DLTI/TestDataLayoutQuery.cpp
index 078f84fa44c91..9f25ac79a087d 100644
--- a/mlir/test/lib/Dialect/DLTI/TestDataLayoutQuery.cpp
+++ b/mlir/test/lib/Dialect/DLTI/TestDataLayoutQuery.cpp
@@ -20,11 +20,11 @@ namespace {
 /// attributes containing the results of data layout queries for operation
 /// result types.
 struct TestDataLayoutQuery
-    : public PassWrapper<TestDataLayoutQuery, FunctionPass> {
+    : public PassWrapper<TestDataLayoutQuery, OperationPass<FuncOp>> {
   StringRef getArgument() const final { return "test-data-layout-query"; }
   StringRef getDescription() const final { return "Test data layout queries"; }
-  void runOnFunction() override {
-    FuncOp func = getFunction();
+  void runOnOperation() override {
+    FuncOp func = getOperation();
     Builder builder(func.getContext());
     const DataLayoutAnalysis &layouts = getAnalysis<DataLayoutAnalysis>();
 

diff  --git a/mlir/test/lib/Dialect/Linalg/TestComprehensiveBufferize.cpp b/mlir/test/lib/Dialect/Linalg/TestComprehensiveBufferize.cpp
index 844b21cde8282..4006c38400afa 100644
--- a/mlir/test/lib/Dialect/Linalg/TestComprehensiveBufferize.cpp
+++ b/mlir/test/lib/Dialect/Linalg/TestComprehensiveBufferize.cpp
@@ -39,7 +39,8 @@ namespace {
 /// A helper struct for FunctionBufferize and ModuleBufferize. Both passes are
 /// mostly identical.
 struct TestComprehensiveFunctionBufferize
-    : public PassWrapper<TestComprehensiveFunctionBufferize, FunctionPass> {
+    : public PassWrapper<TestComprehensiveFunctionBufferize,
+                         OperationPass<FuncOp>> {
   StringRef getArgument() const final {
     return "test-comprehensive-function-bufferize";
   }
@@ -68,7 +69,7 @@ struct TestComprehensiveFunctionBufferize
     vector_ext::registerBufferizableOpInterfaceExternalModels(registry);
   }
 
-  void runOnFunction() override;
+  void runOnOperation() override;
 
   Option<bool> allowReturnMemref{
       *this, "allow-return-memref",
@@ -99,7 +100,7 @@ struct TestComprehensiveFunctionBufferize
 };
 } // namespace
 
-void TestComprehensiveFunctionBufferize::runOnFunction() {
+void TestComprehensiveFunctionBufferize::runOnOperation() {
   auto options = std::make_unique<BufferizationOptions>();
 
   if (!allowReturnMemref)
@@ -117,7 +118,7 @@ void TestComprehensiveFunctionBufferize::runOnFunction() {
       options->dialectFilter->insert(dialectNamespace);
   }
 
-  Operation *op = getFunction().getOperation();
+  Operation *op = getOperation().getOperation();
   if (failed(runComprehensiveBufferize(op, std::move(options))))
     return;
 

diff  --git a/mlir/test/lib/Dialect/Linalg/TestLinalgCodegenStrategy.cpp b/mlir/test/lib/Dialect/Linalg/TestLinalgCodegenStrategy.cpp
index d56337130c073..b79059a3ebb64 100644
--- a/mlir/test/lib/Dialect/Linalg/TestLinalgCodegenStrategy.cpp
+++ b/mlir/test/lib/Dialect/Linalg/TestLinalgCodegenStrategy.cpp
@@ -29,7 +29,7 @@ using namespace mlir::linalg;
 
 namespace {
 struct TestLinalgCodegenStrategy
-    : public PassWrapper<TestLinalgCodegenStrategy, FunctionPass> {
+    : public PassWrapper<TestLinalgCodegenStrategy, OperationPass<FuncOp>> {
   StringRef getArgument() const final { return "test-linalg-codegen-strategy"; }
   StringRef getDescription() const final {
     return "Test Linalg Codegen Strategy.";
@@ -53,7 +53,7 @@ struct TestLinalgCodegenStrategy
   template <typename LinalgNamedOp>
   void applyStrategyToNamedLinalgOp();
 
-  void runOnFunction() override;
+  void runOnOperation() override;
 
   void runStrategy(const LinalgTilingAndFusionOptions &tilingAndFusionOptions,
                    const LinalgTilingOptions &tilingOptions,
@@ -208,7 +208,7 @@ void TestLinalgCodegenStrategy::runStrategy(
               .enableContractionLowering()
               .enableTransferToSCFConversion());
   // Created a nested OpPassManager and run.
-  FuncOp funcOp = getFunction();
+  FuncOp funcOp = getOperation();
   OpPassManager dynamicPM("builtin.func");
   strategy.configurePassPipeline(dynamicPM, funcOp.getContext(), runEnablePass);
   if (failed(runPipeline(dynamicPM, funcOp)))
@@ -225,8 +225,8 @@ static Value getNeutralOfLinalgOp(OpBuilder &b, OpOperand &op) {
 }
 
 /// Apply transformations specified as patterns.
-void TestLinalgCodegenStrategy::runOnFunction() {
-  if (!anchorFuncOpName.empty() && anchorFuncOpName != getFunction().getName())
+void TestLinalgCodegenStrategy::runOnOperation() {
+  if (!anchorFuncOpName.empty() && anchorFuncOpName != getOperation().getName())
     return;
 
   LinalgTilingAndFusionOptions tilingAndFusionOptions;

diff  --git a/mlir/test/lib/Dialect/Linalg/TestLinalgDistribution.cpp b/mlir/test/lib/Dialect/Linalg/TestLinalgDistribution.cpp
index 226e2ba24ec6b..cabb23d479af3 100644
--- a/mlir/test/lib/Dialect/Linalg/TestLinalgDistribution.cpp
+++ b/mlir/test/lib/Dialect/Linalg/TestLinalgDistribution.cpp
@@ -38,7 +38,7 @@ static LinalgLoopDistributionOptions getDistributionOptions() {
 
 namespace {
 struct TestLinalgDistribution
-    : public PassWrapper<TestLinalgDistribution, FunctionPass> {
+    : public PassWrapper<TestLinalgDistribution, OperationPass<FuncOp>> {
   StringRef getArgument() const final { return "test-linalg-distribution"; }
   StringRef getDescription() const final { return "Test Linalg distribution."; }
   TestLinalgDistribution() = default;
@@ -47,12 +47,12 @@ struct TestLinalgDistribution
     registry.insert<AffineDialect, gpu::GPUDialect>();
   }
 
-  void runOnFunction() override;
+  void runOnOperation() override;
 };
 } // namespace
 
-void TestLinalgDistribution::runOnFunction() {
-  auto funcOp = getFunction();
+void TestLinalgDistribution::runOnOperation() {
+  auto funcOp = getOperation();
   OwningRewritePatternList distributeTiledLoopsPatterns(&getContext());
   populateLinalgDistributeTiledLoopPattern(
       distributeTiledLoopsPatterns, getDistributionOptions(),

diff  --git a/mlir/test/lib/Dialect/Linalg/TestLinalgElementwiseFusion.cpp b/mlir/test/lib/Dialect/Linalg/TestLinalgElementwiseFusion.cpp
index 4819bcfcd43dc..30bef4af8bcc3 100644
--- a/mlir/test/lib/Dialect/Linalg/TestLinalgElementwiseFusion.cpp
+++ b/mlir/test/lib/Dialect/Linalg/TestLinalgElementwiseFusion.cpp
@@ -46,7 +46,7 @@ static bool setFusedOpOperandLimit(const OpResult &producer,
 
 namespace {
 struct TestLinalgElementwiseFusion
-    : public PassWrapper<TestLinalgElementwiseFusion, FunctionPass> {
+    : public PassWrapper<TestLinalgElementwiseFusion, OperationPass<FuncOp>> {
   void getDependentDialects(DialectRegistry &registry) const override {
     registry.insert<AffineDialect, linalg::LinalgDialect, memref::MemRefDialect,
                     tensor::TensorDialect>();
@@ -58,9 +58,9 @@ struct TestLinalgElementwiseFusion
     return "Test Linalg element wise operation fusion patterns";
   }
 
-  void runOnFunction() override {
+  void runOnOperation() override {
     MLIRContext *context = &this->getContext();
-    FuncOp funcOp = this->getFunction();
+    FuncOp funcOp = this->getOperation();
     RewritePatternSet fusionPatterns(context);
 
     linalg::populateElementwiseOpsFusionPatterns(
@@ -74,7 +74,8 @@ struct TestLinalgElementwiseFusion
 };
 
 struct TestLinalgControlFuseByExpansion
-    : public PassWrapper<TestLinalgControlFuseByExpansion, FunctionPass> {
+    : public PassWrapper<TestLinalgControlFuseByExpansion,
+                         OperationPass<FuncOp>> {
   void getDependentDialects(DialectRegistry &registry) const override {
     registry
         .insert<AffineDialect, linalg::LinalgDialect, tensor::TensorDialect>();
@@ -87,9 +88,9 @@ struct TestLinalgControlFuseByExpansion
            "expansion";
   }
 
-  void runOnFunction() override {
+  void runOnOperation() override {
     MLIRContext *context = &this->getContext();
-    FuncOp funcOp = this->getFunction();
+    FuncOp funcOp = this->getOperation();
     RewritePatternSet fusionPatterns(context);
 
     linalg::ControlElementwiseOpsFusionFn controlReshapeFusionFn =
@@ -120,7 +121,7 @@ struct TestLinalgControlFuseByExpansion
 };
 
 struct TestPushExpandingReshape
-    : public PassWrapper<TestPushExpandingReshape, FunctionPass> {
+    : public PassWrapper<TestPushExpandingReshape, OperationPass<FuncOp>> {
   void getDependentDialects(DialectRegistry &registry) const override {
     registry
         .insert<AffineDialect, linalg::LinalgDialect, tensor::TensorDialect>();
@@ -130,9 +131,9 @@ struct TestPushExpandingReshape
     return "Test Linalg reshape push patterns";
   }
 
-  void runOnFunction() override {
+  void runOnOperation() override {
     MLIRContext *context = &this->getContext();
-    FuncOp funcOp = this->getFunction();
+    FuncOp funcOp = this->getOperation();
     RewritePatternSet patterns(context);
     linalg::populatePushReshapeOpsPatterns(patterns);
     (void)applyPatternsAndFoldGreedily(funcOp.getBody(), std::move(patterns));

diff  --git a/mlir/test/lib/Dialect/Linalg/TestLinalgFusionTransforms.cpp b/mlir/test/lib/Dialect/Linalg/TestLinalgFusionTransforms.cpp
index d5391a1b3b3e0..f8a39b02aae88 100644
--- a/mlir/test/lib/Dialect/Linalg/TestLinalgFusionTransforms.cpp
+++ b/mlir/test/lib/Dialect/Linalg/TestLinalgFusionTransforms.cpp
@@ -111,7 +111,8 @@ static void fillFusionPatterns(MLIRContext *context,
 namespace {
 template <LinalgTilingLoopType LoopType>
 struct TestLinalgFusionTransforms
-    : public PassWrapper<TestLinalgFusionTransforms<LoopType>, FunctionPass> {
+    : public PassWrapper<TestLinalgFusionTransforms<LoopType>,
+                         OperationPass<FuncOp>> {
   void getDependentDialects(DialectRegistry &registry) const override {
     registry.insert<AffineDialect, linalg::LinalgDialect, memref::MemRefDialect,
                     scf::SCFDialect, StandardOpsDialect>();
@@ -119,9 +120,9 @@ struct TestLinalgFusionTransforms
   TestLinalgFusionTransforms() = default;
   TestLinalgFusionTransforms(const TestLinalgFusionTransforms &pass) {}
 
-  void runOnFunction() override {
+  void runOnOperation() override {
     MLIRContext *context = &this->getContext();
-    FuncOp funcOp = this->getFunction();
+    FuncOp funcOp = this->getOperation();
     RewritePatternSet fusionPatterns(context);
     Aliases alias;
     LinalgDependenceGraph dependenceGraph =
@@ -225,7 +226,7 @@ static LogicalResult fuseLinalgOpsGreedily(FuncOp f) {
 
 namespace {
 struct TestLinalgGreedyFusion
-    : public PassWrapper<TestLinalgGreedyFusion, FunctionPass> {
+    : public PassWrapper<TestLinalgGreedyFusion, OperationPass<FuncOp>> {
   void getDependentDialects(DialectRegistry &registry) const override {
     registry.insert<AffineDialect, linalg::LinalgDialect, memref::MemRefDialect,
                     scf::SCFDialect>();
@@ -234,7 +235,7 @@ struct TestLinalgGreedyFusion
   StringRef getDescription() const final {
     return "Test Linalg fusion by applying a greedy test transformation.";
   }
-  void runOnFunction() override {
+  void runOnOperation() override {
     MLIRContext *context = &getContext();
     RewritePatternSet patterns =
         linalg::getLinalgTilingCanonicalizationPatterns(context);
@@ -242,22 +243,23 @@ struct TestLinalgGreedyFusion
     scf::populateSCFForLoopCanonicalizationPatterns(patterns);
     FrozenRewritePatternSet frozenPatterns(std::move(patterns));
     do {
-      (void)applyPatternsAndFoldGreedily(getFunction(), frozenPatterns);
+      (void)applyPatternsAndFoldGreedily(getOperation(), frozenPatterns);
       PassManager pm(context);
       pm.addPass(createLoopInvariantCodeMotionPass());
       pm.addPass(createCanonicalizerPass());
       pm.addPass(createCSEPass());
-      LogicalResult res = pm.run(getFunction()->getParentOfType<ModuleOp>());
+      LogicalResult res = pm.run(getOperation()->getParentOfType<ModuleOp>());
       if (failed(res))
         this->signalPassFailure();
-    } while (succeeded(fuseLinalgOpsGreedily(getFunction())));
+    } while (succeeded(fuseLinalgOpsGreedily(getOperation())));
   }
 };
 
 /// Pass to test tile and fuse of sequence of operations. Intended only for
 /// testing.
 struct TestLinalgTileAndFuseSequencePass
-    : public PassWrapper<TestLinalgTileAndFuseSequencePass, FunctionPass> {
+    : public PassWrapper<TestLinalgTileAndFuseSequencePass,
+                         OperationPass<FuncOp>> {
   StringRef getArgument() const final { return "test-linalg-tile-and-fuse"; }
   StringRef getDescription() const final {
     return "Test Linalg tiling and fusion of a sequence of Linalg operations.";
@@ -276,7 +278,7 @@ struct TestLinalgTileAndFuseSequencePass
                     scf::SCFDialect>();
   }
 
-  void runOnFunction() override {
+  void runOnOperation() override {
     FuncOp funcOp = getOperation();
     auto &blocks = funcOp.getBody().getBlocks();
     if (!llvm::hasSingleElement(blocks)) {

diff  --git a/mlir/test/lib/Dialect/Linalg/TestLinalgHoisting.cpp b/mlir/test/lib/Dialect/Linalg/TestLinalgHoisting.cpp
index 4fa90ede1a987..249e3d873da92 100644
--- a/mlir/test/lib/Dialect/Linalg/TestLinalgHoisting.cpp
+++ b/mlir/test/lib/Dialect/Linalg/TestLinalgHoisting.cpp
@@ -20,7 +20,7 @@ using namespace mlir::linalg;
 
 namespace {
 struct TestLinalgHoisting
-    : public PassWrapper<TestLinalgHoisting, FunctionPass> {
+    : public PassWrapper<TestLinalgHoisting, OperationPass<FuncOp>> {
   TestLinalgHoisting() = default;
   TestLinalgHoisting(const TestLinalgHoisting &pass) : PassWrapper(pass) {}
   void getDependentDialects(DialectRegistry &registry) const override {
@@ -31,7 +31,7 @@ struct TestLinalgHoisting
     return "Test Linalg hoisting functions.";
   }
 
-  void runOnFunction() override;
+  void runOnOperation() override;
 
   Option<bool> testHoistRedundantTransfers{
       *this, "test-hoist-redundant-transfers",
@@ -40,10 +40,10 @@ struct TestLinalgHoisting
 };
 } // namespace
 
-void TestLinalgHoisting::runOnFunction() {
+void TestLinalgHoisting::runOnOperation() {
   if (testHoistRedundantTransfers) {
-    hoistRedundantVectorTransfers(getFunction());
-    hoistRedundantVectorTransfersOnTensor(getFunction());
+    hoistRedundantVectorTransfers(getOperation());
+    hoistRedundantVectorTransfersOnTensor(getOperation());
     return;
   }
 }

diff  --git a/mlir/test/lib/Dialect/Linalg/TestLinalgTransforms.cpp b/mlir/test/lib/Dialect/Linalg/TestLinalgTransforms.cpp
index c7ee04b08966e..76d983d3892e4 100644
--- a/mlir/test/lib/Dialect/Linalg/TestLinalgTransforms.cpp
+++ b/mlir/test/lib/Dialect/Linalg/TestLinalgTransforms.cpp
@@ -32,7 +32,7 @@ using namespace mlir::linalg;
 
 namespace {
 struct TestLinalgTransforms
-    : public PassWrapper<TestLinalgTransforms, FunctionPass> {
+    : public PassWrapper<TestLinalgTransforms, OperationPass<FuncOp>> {
   TestLinalgTransforms() = default;
   TestLinalgTransforms(const TestLinalgTransforms &pass) : PassWrapper(pass) {}
 
@@ -53,7 +53,7 @@ struct TestLinalgTransforms
     return "Test Linalg transformation patterns by applying them greedily.";
   }
 
-  void runOnFunction() override;
+  void runOnOperation() override;
 
   Option<bool> testPatterns{*this, "test-patterns",
                             llvm::cl::desc("Test a mixed set of patterns"),
@@ -674,9 +674,9 @@ static void applyTiledLoopPeelingPattern(FuncOp funcOp,
 }
 
 /// Apply transformations specified as patterns.
-void TestLinalgTransforms::runOnFunction() {
+void TestLinalgTransforms::runOnOperation() {
   auto lambda = [&](void *) {
-    getFunction().walk([](LinalgOp op) {
+    getOperation().walk([](LinalgOp op) {
       op->removeAttr(LinalgTransforms::kLinalgTransformMarker);
     });
   };
@@ -685,39 +685,39 @@ void TestLinalgTransforms::runOnFunction() {
   if (testPromotionOptions) {
     RewritePatternSet patterns(&getContext());
     fillPromotionCallBackPatterns(&getContext(), patterns);
-    (void)applyPatternsAndFoldGreedily(getFunction(), std::move(patterns));
+    (void)applyPatternsAndFoldGreedily(getOperation(), std::move(patterns));
     return;
   }
   if (testTileAndDistributionOptions) {
     RewritePatternSet patterns(&getContext());
     fillTileAndDistributePatterns(&getContext(), patterns);
-    (void)applyPatternsAndFoldGreedily(getFunction(), std::move(patterns));
+    (void)applyPatternsAndFoldGreedily(getOperation(), std::move(patterns));
     return;
   }
   if (testPatterns)
-    return applyPatterns(getFunction());
+    return applyPatterns(getOperation());
   if (testMatmulToVectorPatterns1dTiling || testMatmulToVectorPatterns2dTiling)
-    return applyMatmulToVectorPatterns(getFunction(),
+    return applyMatmulToVectorPatterns(getOperation(),
                                        testMatmulToVectorPatterns1dTiling,
                                        testMatmulToVectorPatterns2dTiling);
   if (testVectorTransferForwardingPatterns)
-    return applyVectorTransferForwardingPatterns(getFunction());
+    return applyVectorTransferForwardingPatterns(getOperation());
   if (testGenericToVectorPattern)
-    return applyLinalgToVectorPatterns(getFunction());
+    return applyLinalgToVectorPatterns(getOperation());
   if (testTransformPadTensor)
-    return applyPadTensorToGenericPatterns(getFunction());
+    return applyPadTensorToGenericPatterns(getOperation());
   if (testGeneralizePadTensor)
-    return applyGeneralizePadTensorPatterns(getFunction());
+    return applyGeneralizePadTensorPatterns(getOperation());
   if (testSwapSubTensorPadTensor)
-    return applyExtractSliceOfPadTensorSwapPattern(getFunction());
+    return applyExtractSliceOfPadTensorSwapPattern(getOperation());
   if (testTiledLoopPeeling.hasValue())
-    return applyTiledLoopPeelingPattern(getFunction(), testTiledLoopPeeling,
+    return applyTiledLoopPeelingPattern(getOperation(), testTiledLoopPeeling,
                                         skipPartial);
   if (testTilePattern)
-    return applyTilePattern(getFunction(), loopType, tileSizes, peeledLoops,
+    return applyTilePattern(getOperation(), loopType, tileSizes, peeledLoops,
                             /*scalarizeDynamicDims=*/false);
   if (testTileScalarizeDynamicDims)
-    return applyTilePattern(getFunction(), loopType, tileSizes,
+    return applyTilePattern(getOperation(), loopType, tileSizes,
                             /*peeledLoops=*/{}, /*scalarizeDynamicDims=*/true);
 }
 

diff  --git a/mlir/test/lib/Dialect/Linalg/TestPadFusion.cpp b/mlir/test/lib/Dialect/Linalg/TestPadFusion.cpp
index bfe84e5d63d05..0c3f51d309635 100644
--- a/mlir/test/lib/Dialect/Linalg/TestPadFusion.cpp
+++ b/mlir/test/lib/Dialect/Linalg/TestPadFusion.cpp
@@ -19,7 +19,8 @@
 namespace mlir {
 
 namespace {
-struct TestPadFusionPass : public PassWrapper<TestPadFusionPass, FunctionPass> {
+struct TestPadFusionPass
+    : public PassWrapper<TestPadFusionPass, OperationPass<FuncOp>> {
 
   void getDependentDialects(DialectRegistry &registry) const override {
     registry
@@ -29,9 +30,9 @@ struct TestPadFusionPass : public PassWrapper<TestPadFusionPass, FunctionPass> {
   StringRef getArgument() const final { return "test-linalg-pad-fusion"; }
   StringRef getDescription() const final { return "Test PadOp fusion"; }
 
-  void runOnFunction() override {
+  void runOnOperation() override {
     MLIRContext *context = &getContext();
-    FuncOp funcOp = getFunction();
+    FuncOp funcOp = getOperation();
     RewritePatternSet patterns(context);
     linalg::populateFusePadTensorWithProducerLinalgOpPatterns(patterns);
     if (failed(applyPatternsAndFoldGreedily(funcOp.getBody(),

diff  --git a/mlir/test/lib/Dialect/Math/TestAlgebraicSimplification.cpp b/mlir/test/lib/Dialect/Math/TestAlgebraicSimplification.cpp
index 9977065775486..294f15615b78c 100644
--- a/mlir/test/lib/Dialect/Math/TestAlgebraicSimplification.cpp
+++ b/mlir/test/lib/Dialect/Math/TestAlgebraicSimplification.cpp
@@ -20,8 +20,9 @@ using namespace mlir;
 
 namespace {
 struct TestMathAlgebraicSimplificationPass
-    : public PassWrapper<TestMathAlgebraicSimplificationPass, FunctionPass> {
-  void runOnFunction() override;
+    : public PassWrapper<TestMathAlgebraicSimplificationPass,
+                         OperationPass<FuncOp>> {
+  void runOnOperation() override;
   void getDependentDialects(DialectRegistry &registry) const override {
     registry.insert<vector::VectorDialect, math::MathDialect>();
   }
@@ -34,7 +35,7 @@ struct TestMathAlgebraicSimplificationPass
 };
 } // namespace
 
-void TestMathAlgebraicSimplificationPass::runOnFunction() {
+void TestMathAlgebraicSimplificationPass::runOnOperation() {
   RewritePatternSet patterns(&getContext());
   populateMathAlgebraicSimplificationPatterns(patterns);
   (void)applyPatternsAndFoldGreedily(getOperation(), std::move(patterns));

diff  --git a/mlir/test/lib/Dialect/Math/TestExpandTanh.cpp b/mlir/test/lib/Dialect/Math/TestExpandTanh.cpp
index bd5e09d7debe2..f906863a3f92b 100644
--- a/mlir/test/lib/Dialect/Math/TestExpandTanh.cpp
+++ b/mlir/test/lib/Dialect/Math/TestExpandTanh.cpp
@@ -18,14 +18,14 @@ using namespace mlir;
 
 namespace {
 struct TestExpandTanhPass
-    : public PassWrapper<TestExpandTanhPass, FunctionPass> {
-  void runOnFunction() override;
+    : public PassWrapper<TestExpandTanhPass, OperationPass<FuncOp>> {
+  void runOnOperation() override;
   StringRef getArgument() const final { return "test-expand-tanh"; }
   StringRef getDescription() const final { return "Test expanding tanh"; }
 };
 } // namespace
 
-void TestExpandTanhPass::runOnFunction() {
+void TestExpandTanhPass::runOnOperation() {
   RewritePatternSet patterns(&getContext());
   populateExpandTanhPattern(patterns);
   (void)applyPatternsAndFoldGreedily(getOperation(), std::move(patterns));

diff  --git a/mlir/test/lib/Dialect/Math/TestPolynomialApproximation.cpp b/mlir/test/lib/Dialect/Math/TestPolynomialApproximation.cpp
index 486ea582cb768..32c75271da37e 100644
--- a/mlir/test/lib/Dialect/Math/TestPolynomialApproximation.cpp
+++ b/mlir/test/lib/Dialect/Math/TestPolynomialApproximation.cpp
@@ -23,13 +23,14 @@ using namespace mlir;
 
 namespace {
 struct TestMathPolynomialApproximationPass
-    : public PassWrapper<TestMathPolynomialApproximationPass, FunctionPass> {
+    : public PassWrapper<TestMathPolynomialApproximationPass,
+                         OperationPass<FuncOp>> {
   TestMathPolynomialApproximationPass() = default;
   TestMathPolynomialApproximationPass(
       const TestMathPolynomialApproximationPass &pass)
       : PassWrapper(pass) {}
 
-  void runOnFunction() override;
+  void runOnOperation() override;
   void getDependentDialects(DialectRegistry &registry) const override {
     registry.insert<arith::ArithmeticDialect, math::MathDialect,
                     vector::VectorDialect>();
@@ -51,7 +52,7 @@ struct TestMathPolynomialApproximationPass
 };
 } // namespace
 
-void TestMathPolynomialApproximationPass::runOnFunction() {
+void TestMathPolynomialApproximationPass::runOnOperation() {
   RewritePatternSet patterns(&getContext());
   MathPolynomialApproximationOptions approxOptions;
   approxOptions.enableAvx2 = enableAvx2;

diff  --git a/mlir/test/lib/Dialect/SCF/TestSCFUtils.cpp b/mlir/test/lib/Dialect/SCF/TestSCFUtils.cpp
index 56f54f5e7dd92..7c438ebf82211 100644
--- a/mlir/test/lib/Dialect/SCF/TestSCFUtils.cpp
+++ b/mlir/test/lib/Dialect/SCF/TestSCFUtils.cpp
@@ -27,14 +27,14 @@ using namespace mlir;
 
 namespace {
 class TestSCFForUtilsPass
-    : public PassWrapper<TestSCFForUtilsPass, FunctionPass> {
+    : public PassWrapper<TestSCFForUtilsPass, OperationPass<FuncOp>> {
 public:
   StringRef getArgument() const final { return "test-scf-for-utils"; }
   StringRef getDescription() const final { return "test scf.for utils"; }
   explicit TestSCFForUtilsPass() = default;
 
-  void runOnFunction() override {
-    FuncOp func = getFunction();
+  void runOnOperation() override {
+    FuncOp func = getOperation();
     SmallVector<scf::ForOp, 4> toErase;
 
     func.walk([&](Operation *fakeRead) {
@@ -92,7 +92,7 @@ static const StringLiteral kTestPipeliningOpOrderMarker =
     "__test_pipelining_op_order__";
 
 class TestSCFPipeliningPass
-    : public PassWrapper<TestSCFPipeliningPass, FunctionPass> {
+    : public PassWrapper<TestSCFPipeliningPass, OperationPass<FuncOp>> {
 public:
   StringRef getArgument() const final { return "test-scf-pipelining"; }
   StringRef getDescription() const final { return "test scf.forOp pipelining"; }
@@ -120,14 +120,14 @@ class TestSCFPipeliningPass
     registry.insert<arith::ArithmeticDialect, StandardOpsDialect>();
   }
 
-  void runOnFunction() override {
+  void runOnOperation() override {
     RewritePatternSet patterns(&getContext());
     mlir::scf::PipeliningOption options;
     options.getScheduleFn = getSchedule;
 
     scf::populateSCFLoopPipeliningPatterns(patterns, options);
-    (void)applyPatternsAndFoldGreedily(getFunction(), std::move(patterns));
-    getFunction().walk([](Operation *op) {
+    (void)applyPatternsAndFoldGreedily(getOperation(), std::move(patterns));
+    getOperation().walk([](Operation *op) {
       // Clean up the markers.
       op->removeAttr(kTestPipeliningStageMarker);
       op->removeAttr(kTestPipeliningOpOrderMarker);

diff  --git a/mlir/test/lib/Dialect/SPIRV/TestAvailability.cpp b/mlir/test/lib/Dialect/SPIRV/TestAvailability.cpp
index 09c6c3f75de30..07092290eb480 100644
--- a/mlir/test/lib/Dialect/SPIRV/TestAvailability.cpp
+++ b/mlir/test/lib/Dialect/SPIRV/TestAvailability.cpp
@@ -21,8 +21,8 @@ using namespace mlir;
 namespace {
 /// A pass for testing SPIR-V op availability.
 struct PrintOpAvailability
-    : public PassWrapper<PrintOpAvailability, FunctionPass> {
-  void runOnFunction() override;
+    : public PassWrapper<PrintOpAvailability, OperationPass<FuncOp>> {
+  void runOnOperation() override;
   StringRef getArgument() const final { return "test-spirv-op-availability"; }
   StringRef getDescription() const final {
     return "Test SPIR-V op availability";
@@ -30,8 +30,8 @@ struct PrintOpAvailability
 };
 } // namespace
 
-void PrintOpAvailability::runOnFunction() {
-  auto f = getFunction();
+void PrintOpAvailability::runOnOperation() {
+  auto f = getOperation();
   llvm::outs() << f.getName() << "\n";
 
   Dialect *spvDialect = getContext().getLoadedDialect("spv");
@@ -103,12 +103,12 @@ void registerPrintSpirvAvailabilityPass() {
 namespace {
 /// A pass for testing SPIR-V op availability.
 struct ConvertToTargetEnv
-    : public PassWrapper<ConvertToTargetEnv, FunctionPass> {
+    : public PassWrapper<ConvertToTargetEnv, OperationPass<FuncOp>> {
   StringRef getArgument() const override { return "test-spirv-target-env"; }
   StringRef getDescription() const override {
     return "Test SPIR-V target environment";
   }
-  void runOnFunction() override;
+  void runOnOperation() override;
 };
 
 struct ConvertToAtomCmpExchangeWeak : public RewritePattern {
@@ -142,9 +142,9 @@ struct ConvertToSubgroupBallot : public RewritePattern {
 };
 } // namespace
 
-void ConvertToTargetEnv::runOnFunction() {
+void ConvertToTargetEnv::runOnOperation() {
   MLIRContext *context = &getContext();
-  FuncOp fn = getFunction();
+  FuncOp fn = getOperation();
 
   auto targetEnv = fn.getOperation()
                        ->getAttr(spirv::getTargetEnvAttrName())

diff  --git a/mlir/test/lib/Dialect/StandardOps/TestComposeSubView.cpp b/mlir/test/lib/Dialect/StandardOps/TestComposeSubView.cpp
index 01179721d3cd0..1638ee3debe0a 100644
--- a/mlir/test/lib/Dialect/StandardOps/TestComposeSubView.cpp
+++ b/mlir/test/lib/Dialect/StandardOps/TestComposeSubView.cpp
@@ -19,12 +19,12 @@ using namespace mlir;
 
 namespace {
 struct TestComposeSubViewPass
-    : public PassWrapper<TestComposeSubViewPass, FunctionPass> {
+    : public PassWrapper<TestComposeSubViewPass, OperationPass<FuncOp>> {
   StringRef getArgument() const final { return "test-compose-subview"; }
   StringRef getDescription() const final {
     return "Test combining composed subviews";
   }
-  void runOnFunction() override;
+  void runOnOperation() override;
   void getDependentDialects(DialectRegistry &registry) const override;
 };
 
@@ -33,7 +33,7 @@ void TestComposeSubViewPass::getDependentDialects(
   registry.insert<AffineDialect>();
 }
 
-void TestComposeSubViewPass::runOnFunction() {
+void TestComposeSubViewPass::runOnOperation() {
   OwningRewritePatternList patterns(&getContext());
   populateComposeSubViewPatterns(patterns, &getContext());
   (void)applyPatternsAndFoldGreedily(getOperation(), std::move(patterns));

diff  --git a/mlir/test/lib/Dialect/Test/TestPatterns.cpp b/mlir/test/lib/Dialect/Test/TestPatterns.cpp
index cc165cd003909..7b112e17f682d 100644
--- a/mlir/test/lib/Dialect/Test/TestPatterns.cpp
+++ b/mlir/test/lib/Dialect/Test/TestPatterns.cpp
@@ -124,10 +124,11 @@ struct FolderInsertBeforePreviouslyFoldedConstantPattern
   }
 };
 
-struct TestPatternDriver : public PassWrapper<TestPatternDriver, FunctionPass> {
+struct TestPatternDriver
+    : public PassWrapper<TestPatternDriver, OperationPass<FuncOp>> {
   StringRef getArgument() const final { return "test-patterns"; }
   StringRef getDescription() const final { return "Run test dialect patterns"; }
-  void runOnFunction() override {
+  void runOnOperation() override {
     mlir::RewritePatternSet patterns(&getContext());
     populateWithGenerated(patterns);
 
@@ -136,7 +137,7 @@ struct TestPatternDriver : public PassWrapper<TestPatternDriver, FunctionPass> {
                  FolderInsertBeforePreviouslyFoldedConstantPattern>(
         &getContext());
 
-    (void)applyPatternsAndFoldGreedily(getFunction(), std::move(patterns));
+    (void)applyPatternsAndFoldGreedily(getOperation(), std::move(patterns));
   }
 };
 } // namespace
@@ -189,18 +190,18 @@ static void reifyReturnShape(Operation *op) {
 }
 
 struct TestReturnTypeDriver
-    : public PassWrapper<TestReturnTypeDriver, FunctionPass> {
+    : public PassWrapper<TestReturnTypeDriver, OperationPass<FuncOp>> {
   void getDependentDialects(DialectRegistry &registry) const override {
     registry.insert<tensor::TensorDialect>();
   }
   StringRef getArgument() const final { return "test-return-type"; }
   StringRef getDescription() const final { return "Run return type functions"; }
 
-  void runOnFunction() override {
-    if (getFunction().getName() == "testCreateFunctions") {
+  void runOnOperation() override {
+    if (getOperation().getName() == "testCreateFunctions") {
       std::vector<Operation *> ops;
       // Collect ops to avoid triggering on inserted ops.
-      for (auto &op : getFunction().getBody().front())
+      for (auto &op : getOperation().getBody().front())
         ops.push_back(&op);
       // Generate test patterns for each, but skip terminator.
       for (auto *op : llvm::makeArrayRef(ops).drop_back()) {
@@ -213,10 +214,10 @@ struct TestReturnTypeDriver
       };
       return;
     }
-    if (getFunction().getName() == "testReifyFunctions") {
+    if (getOperation().getName() == "testReifyFunctions") {
       std::vector<Operation *> ops;
       // Collect ops to avoid triggering on inserted ops.
-      for (auto &op : getFunction().getBody().front())
+      for (auto &op : getOperation().getBody().front())
         if (isa<OpWithShapedTypeInferTypeInterfaceOp>(op))
           ops.push_back(&op);
       // Generate test patterns for each, but skip terminator.
@@ -229,17 +230,17 @@ struct TestReturnTypeDriver
 
 namespace {
 struct TestDerivedAttributeDriver
-    : public PassWrapper<TestDerivedAttributeDriver, FunctionPass> {
+    : public PassWrapper<TestDerivedAttributeDriver, OperationPass<FuncOp>> {
   StringRef getArgument() const final { return "test-derived-attr"; }
   StringRef getDescription() const final {
     return "Run test derived attributes";
   }
-  void runOnFunction() override;
+  void runOnOperation() override;
 };
 } // namespace
 
-void TestDerivedAttributeDriver::runOnFunction() {
-  getFunction().walk([](DerivedAttributeOpInterface dOp) {
+void TestDerivedAttributeDriver::runOnOperation() {
+  getOperation().walk([](DerivedAttributeOpInterface dOp) {
     auto dAttr = dOp.materializeDerivedAttributes();
     if (!dAttr)
       return;
@@ -835,12 +836,12 @@ struct TestRemapValueInRegion
 };
 
 struct TestRemappedValue
-    : public mlir::PassWrapper<TestRemappedValue, FunctionPass> {
+    : public mlir::PassWrapper<TestRemappedValue, OperationPass<FuncOp>> {
   StringRef getArgument() const final { return "test-remapped-value"; }
   StringRef getDescription() const final {
     return "Test public remapped value mechanism in ConversionPatternRewriter";
   }
-  void runOnFunction() override {
+  void runOnOperation() override {
     TestRemapValueTypeConverter typeConverter;
 
     mlir::RewritePatternSet patterns(&getContext());
@@ -865,7 +866,7 @@ struct TestRemappedValue
     target.addDynamicallyLegalOp<OneVResOneVOperandOp1>(
         [](Operation *op) { return op->getNumOperands() > 1; });
 
-    if (failed(mlir::applyFullConversion(getFunction(), target,
+    if (failed(mlir::applyFullConversion(getOperation(), target,
                                          std::move(patterns)))) {
       signalPassFailure();
     }
@@ -893,21 +894,21 @@ struct RemoveTestDialectOps : public RewritePattern {
 };
 
 struct TestUnknownRootOpDriver
-    : public mlir::PassWrapper<TestUnknownRootOpDriver, FunctionPass> {
+    : public mlir::PassWrapper<TestUnknownRootOpDriver, OperationPass<FuncOp>> {
   StringRef getArgument() const final {
     return "test-legalize-unknown-root-patterns";
   }
   StringRef getDescription() const final {
     return "Test public remapped value mechanism in ConversionPatternRewriter";
   }
-  void runOnFunction() override {
+  void runOnOperation() override {
     mlir::RewritePatternSet patterns(&getContext());
     patterns.add<RemoveTestDialectOps>(&getContext());
 
     mlir::ConversionTarget target(getContext());
     target.addIllegalDialect<TestDialect>();
-    if (failed(
-            applyPartialConversion(getFunction(), target, std::move(patterns))))
+    if (failed(applyPartialConversion(getOperation(), target,
+                                      std::move(patterns))))
       signalPassFailure();
   }
 };

diff  --git a/mlir/test/lib/Dialect/Test/TestTraits.cpp b/mlir/test/lib/Dialect/Test/TestTraits.cpp
index a19c3b1649ba7..56a14049cbe52 100644
--- a/mlir/test/lib/Dialect/Test/TestTraits.cpp
+++ b/mlir/test/lib/Dialect/Test/TestTraits.cpp
@@ -31,11 +31,12 @@ OpFoldResult TestInvolutionTraitSuccesfulOperationFolderOp::fold(
 }
 
 namespace {
-struct TestTraitFolder : public PassWrapper<TestTraitFolder, FunctionPass> {
+struct TestTraitFolder
+    : public PassWrapper<TestTraitFolder, OperationPass<FuncOp>> {
   StringRef getArgument() const final { return "test-trait-folder"; }
   StringRef getDescription() const final { return "Run trait folding"; }
-  void runOnFunction() override {
-    (void)applyPatternsAndFoldGreedily(getFunction(),
+  void runOnOperation() override {
+    (void)applyPatternsAndFoldGreedily(getOperation(),
                                        RewritePatternSet(&getContext()));
   }
 };

diff  --git a/mlir/test/lib/Dialect/Tosa/TosaTestPasses.cpp b/mlir/test/lib/Dialect/Tosa/TosaTestPasses.cpp
index d753378559a38..ba37c0fb9a235 100644
--- a/mlir/test/lib/Dialect/Tosa/TosaTestPasses.cpp
+++ b/mlir/test/lib/Dialect/Tosa/TosaTestPasses.cpp
@@ -179,18 +179,18 @@ ConvertTosaConv2DOp::matchAndRewrite(Operation *op,
 namespace {
 
 struct TosaTestQuantUtilAPI
-    : public PassWrapper<TosaTestQuantUtilAPI, FunctionPass> {
+    : public PassWrapper<TosaTestQuantUtilAPI, OperationPass<FuncOp>> {
   StringRef getArgument() const final { return PASS_NAME; }
   StringRef getDescription() const final {
     return "TOSA Test: Exercise the APIs in QuantUtils.cpp.";
   }
-  void runOnFunction() override;
+  void runOnOperation() override;
 };
 
-void TosaTestQuantUtilAPI::runOnFunction() {
+void TosaTestQuantUtilAPI::runOnOperation() {
   auto *ctx = &getContext();
   RewritePatternSet patterns(ctx);
-  auto func = getFunction();
+  auto func = getOperation();
 
   patterns.add<ConvertTosaNegateOp>(ctx);
   patterns.add<ConvertTosaConv2DOp>(ctx);

diff  --git a/mlir/test/lib/Dialect/Vector/TestVectorTransforms.cpp b/mlir/test/lib/Dialect/Vector/TestVectorTransforms.cpp
index 6fc3d4a22fcb0..5e9e2fc1e3ae0 100644
--- a/mlir/test/lib/Dialect/Vector/TestVectorTransforms.cpp
+++ b/mlir/test/lib/Dialect/Vector/TestVectorTransforms.cpp
@@ -29,7 +29,7 @@ using namespace mlir::vector;
 namespace {
 
 struct TestVectorToVectorLowering
-    : public PassWrapper<TestVectorToVectorLowering, FunctionPass> {
+    : public PassWrapper<TestVectorToVectorLowering, OperationPass<FuncOp>> {
   TestVectorToVectorLowering() = default;
   TestVectorToVectorLowering(const TestVectorToVectorLowering &pass)
       : PassWrapper(pass) {}
@@ -47,7 +47,7 @@ struct TestVectorToVectorLowering
   Option<bool> unroll{*this, "unroll", llvm::cl::desc("Include unrolling"),
                       llvm::cl::init(false)};
 
-  void runOnFunction() override {
+  void runOnOperation() override {
     auto *ctx = &getContext();
     RewritePatternSet patterns(ctx);
     if (unroll) {
@@ -59,7 +59,7 @@ struct TestVectorToVectorLowering
     populateVectorToVectorCanonicalizationPatterns(patterns);
     populateBubbleVectorBitCastOpPatterns(patterns);
     populateCastAwayVectorLeadingOneDimPatterns(patterns);
-    (void)applyPatternsAndFoldGreedily(getFunction(), std::move(patterns));
+    (void)applyPatternsAndFoldGreedily(getOperation(), std::move(patterns));
   }
 
 private:
@@ -102,7 +102,7 @@ struct TestVectorToVectorLowering
 };
 
 struct TestVectorContractionLowering
-    : public PassWrapper<TestVectorContractionLowering, FunctionPass> {
+    : public PassWrapper<TestVectorContractionLowering, OperationPass<FuncOp>> {
   StringRef getArgument() const final {
     return "test-vector-contraction-lowering";
   }
@@ -128,7 +128,7 @@ struct TestVectorContractionLowering
                      "vectors of size 4."),
       llvm::cl::init(false)};
 
-  void runOnFunction() override {
+  void runOnOperation() override {
     RewritePatternSet patterns(&getContext());
 
     // Test on one pattern in isolation.
@@ -137,7 +137,7 @@ struct TestVectorContractionLowering
       VectorTransformsOptions options{lowering};
       patterns.add<ContractionOpToOuterProductOpLowering>(options,
                                                           &getContext());
-      (void)applyPatternsAndFoldGreedily(getFunction(), std::move(patterns));
+      (void)applyPatternsAndFoldGreedily(getOperation(), std::move(patterns));
       return;
     }
 
@@ -153,7 +153,7 @@ struct TestVectorContractionLowering
               return failure();
             return success();
           });
-      (void)applyPatternsAndFoldGreedily(getFunction(), std::move(patterns));
+      (void)applyPatternsAndFoldGreedily(getOperation(), std::move(patterns));
       return;
     }
 
@@ -170,12 +170,12 @@ struct TestVectorContractionLowering
     populateVectorContractLoweringPatterns(patterns, options);
     populateVectorMaskOpLoweringPatterns(patterns);
     populateVectorShapeCastLoweringPatterns(patterns);
-    (void)applyPatternsAndFoldGreedily(getFunction(), std::move(patterns));
+    (void)applyPatternsAndFoldGreedily(getOperation(), std::move(patterns));
   }
 };
 
 struct TestVectorTransposeLowering
-    : public PassWrapper<TestVectorTransposeLowering, FunctionPass> {
+    : public PassWrapper<TestVectorTransposeLowering, OperationPass<FuncOp>> {
   StringRef getArgument() const final {
     return "test-vector-transpose-lowering";
   }
@@ -208,7 +208,7 @@ struct TestVectorTransposeLowering
     registry.insert<LLVM::LLVMDialect>();
   }
 
-  void runOnFunction() override {
+  void runOnOperation() override {
     RewritePatternSet patterns(&getContext());
 
     // Test on one pattern in isolation.
@@ -241,13 +241,13 @@ struct TestVectorTransposeLowering
 
     OpPassManager dynamicPM("builtin.func");
     dynamicPM.addPass(createLinalgStrategyLowerVectorsPass(options));
-    if (failed(runPipeline(dynamicPM, getFunction())))
+    if (failed(runPipeline(dynamicPM, getOperation())))
       return signalPassFailure();
   }
 };
 
 struct TestVectorUnrollingPatterns
-    : public PassWrapper<TestVectorUnrollingPatterns, FunctionPass> {
+    : public PassWrapper<TestVectorUnrollingPatterns, OperationPass<FuncOp>> {
   StringRef getArgument() const final {
     return "test-vector-unrolling-patterns";
   }
@@ -258,7 +258,7 @@ struct TestVectorUnrollingPatterns
   TestVectorUnrollingPatterns() = default;
   TestVectorUnrollingPatterns(const TestVectorUnrollingPatterns &pass)
       : PassWrapper(pass) {}
-  void runOnFunction() override {
+  void runOnOperation() override {
     MLIRContext *ctx = &getContext();
     RewritePatternSet patterns(ctx);
     populateVectorUnrollPatterns(
@@ -297,7 +297,7 @@ struct TestVectorUnrollingPatterns
                         }));
     }
     populateVectorToVectorCanonicalizationPatterns(patterns);
-    (void)applyPatternsAndFoldGreedily(getFunction(), std::move(patterns));
+    (void)applyPatternsAndFoldGreedily(getOperation(), std::move(patterns));
   }
 
   Option<bool> unrollBasedOnType{
@@ -307,7 +307,7 @@ struct TestVectorUnrollingPatterns
 };
 
 struct TestVectorDistributePatterns
-    : public PassWrapper<TestVectorDistributePatterns, FunctionPass> {
+    : public PassWrapper<TestVectorDistributePatterns, OperationPass<FuncOp>> {
   StringRef getArgument() const final {
     return "test-vector-distribute-patterns";
   }
@@ -326,10 +326,10 @@ struct TestVectorDistributePatterns
       *this, "distribution-multiplicity", llvm::cl::MiscFlags::CommaSeparated,
       llvm::cl::desc("Set the multiplicity used for distributing vector")};
 
-  void runOnFunction() override {
+  void runOnOperation() override {
     MLIRContext *ctx = &getContext();
     RewritePatternSet patterns(ctx);
-    FuncOp func = getFunction();
+    FuncOp func = getOperation();
     func.walk([&](arith::AddFOp op) {
       OpBuilder builder(op);
       if (auto vecType = op.getType().dyn_cast<VectorType>()) {
@@ -359,12 +359,12 @@ struct TestVectorDistributePatterns
       }
     });
     populatePropagateVectorDistributionPatterns(patterns);
-    (void)applyPatternsAndFoldGreedily(getFunction(), std::move(patterns));
+    (void)applyPatternsAndFoldGreedily(getOperation(), std::move(patterns));
   }
 };
 
 struct TestVectorToLoopPatterns
-    : public PassWrapper<TestVectorToLoopPatterns, FunctionPass> {
+    : public PassWrapper<TestVectorToLoopPatterns, OperationPass<FuncOp>> {
   StringRef getArgument() const final { return "test-vector-to-forloop"; }
   StringRef getDescription() const final {
     return "Test lowering patterns to break up a vector op into a for loop";
@@ -380,10 +380,10 @@ struct TestVectorToLoopPatterns
       *this, "distribution-multiplicity",
       llvm::cl::desc("Set the multiplicity used for distributing vector"),
       llvm::cl::init(32)};
-  void runOnFunction() override {
+  void runOnOperation() override {
     MLIRContext *ctx = &getContext();
     RewritePatternSet patterns(ctx);
-    FuncOp func = getFunction();
+    FuncOp func = getOperation();
     func.walk([&](arith::AddFOp op) {
       // Check that the operation type can be broken down into a loop.
       VectorType type = op.getType().dyn_cast<VectorType>();
@@ -416,12 +416,13 @@ struct TestVectorToLoopPatterns
       return mlir::WalkResult::interrupt();
     });
     populatePropagateVectorDistributionPatterns(patterns);
-    (void)applyPatternsAndFoldGreedily(getFunction(), std::move(patterns));
+    (void)applyPatternsAndFoldGreedily(getOperation(), std::move(patterns));
   }
 };
 
 struct TestVectorTransferUnrollingPatterns
-    : public PassWrapper<TestVectorTransferUnrollingPatterns, FunctionPass> {
+    : public PassWrapper<TestVectorTransferUnrollingPatterns,
+                         OperationPass<FuncOp>> {
   void getDependentDialects(DialectRegistry &registry) const override {
     registry.insert<AffineDialect>();
   }
@@ -432,7 +433,7 @@ struct TestVectorTransferUnrollingPatterns
     return "Test lowering patterns to unroll transfer ops in the vector "
            "dialect";
   }
-  void runOnFunction() override {
+  void runOnOperation() override {
     MLIRContext *ctx = &getContext();
     RewritePatternSet patterns(ctx);
     populateVectorUnrollPatterns(
@@ -444,13 +445,13 @@ struct TestVectorTransferUnrollingPatterns
                   isa<vector::TransferReadOp, vector::TransferWriteOp>(op));
             }));
     populateVectorToVectorCanonicalizationPatterns(patterns);
-    (void)applyPatternsAndFoldGreedily(getFunction(), std::move(patterns));
+    (void)applyPatternsAndFoldGreedily(getOperation(), std::move(patterns));
   }
 };
 
 struct TestVectorTransferFullPartialSplitPatterns
     : public PassWrapper<TestVectorTransferFullPartialSplitPatterns,
-                         FunctionPass> {
+                         OperationPass<FuncOp>> {
   StringRef getArgument() const final {
     return "test-vector-transfer-full-partial-split";
   }
@@ -473,7 +474,7 @@ struct TestVectorTransferFullPartialSplitPatterns
       llvm::cl::desc("Split using a unmasked vector.transfer + linalg.fill + "
                      "linalg.copy operations."),
       llvm::cl::init(false)};
-  void runOnFunction() override {
+  void runOnOperation() override {
     MLIRContext *ctx = &getContext();
     RewritePatternSet patterns(ctx);
     VectorTransformsOptions options;
@@ -482,21 +483,22 @@ struct TestVectorTransferFullPartialSplitPatterns
     else
       options.setVectorTransferSplit(VectorTransferSplit::VectorTransfer);
     patterns.add<VectorTransferFullPartialRewriter>(ctx, options);
-    (void)applyPatternsAndFoldGreedily(getFunction(), std::move(patterns));
+    (void)applyPatternsAndFoldGreedily(getOperation(), std::move(patterns));
   }
 };
 
 struct TestVectorTransferOpt
-    : public PassWrapper<TestVectorTransferOpt, FunctionPass> {
+    : public PassWrapper<TestVectorTransferOpt, OperationPass<FuncOp>> {
   StringRef getArgument() const final { return "test-vector-transferop-opt"; }
   StringRef getDescription() const final {
     return "Test optimization transformations for transfer ops";
   }
-  void runOnFunction() override { transferOpflowOpt(getFunction()); }
+  void runOnOperation() override { transferOpflowOpt(getOperation()); }
 };
 
 struct TestVectorTransferLoweringPatterns
-    : public PassWrapper<TestVectorTransferLoweringPatterns, FunctionPass> {
+    : public PassWrapper<TestVectorTransferLoweringPatterns,
+                         OperationPass<FuncOp>> {
   void getDependentDialects(DialectRegistry &registry) const override {
     registry.insert<tensor::TensorDialect, memref::MemRefDialect>();
   }
@@ -506,17 +508,17 @@ struct TestVectorTransferLoweringPatterns
   StringRef getDescription() const final {
     return "Test lowering patterns to lower transfer ops to other vector ops";
   }
-  void runOnFunction() override {
+  void runOnOperation() override {
     RewritePatternSet patterns(&getContext());
     populateVectorTransferLoweringPatterns(patterns);
     populateVectorTransferPermutationMapLoweringPatterns(patterns);
-    (void)applyPatternsAndFoldGreedily(getFunction(), std::move(patterns));
+    (void)applyPatternsAndFoldGreedily(getOperation(), std::move(patterns));
   }
 };
 
 struct TestVectorMultiReductionLoweringPatterns
     : public PassWrapper<TestVectorMultiReductionLoweringPatterns,
-                         FunctionPass> {
+                         OperationPass<FuncOp>> {
   TestVectorMultiReductionLoweringPatterns() = default;
   TestVectorMultiReductionLoweringPatterns(
       const TestVectorMultiReductionLoweringPatterns &pass)
@@ -535,19 +537,19 @@ struct TestVectorMultiReductionLoweringPatterns
       *this, "use-outer-reductions",
       llvm::cl::desc("Move reductions to outer most dimensions"),
       llvm::cl::init(false)};
-  void runOnFunction() override {
+  void runOnOperation() override {
     RewritePatternSet patterns(&getContext());
     populateVectorMultiReductionLoweringPatterns(
         patterns, useOuterReductions
                       ? vector::VectorMultiReductionLowering::InnerParallel
                       : vector::VectorMultiReductionLowering::InnerReduction);
-    (void)applyPatternsAndFoldGreedily(getFunction(), std::move(patterns));
+    (void)applyPatternsAndFoldGreedily(getOperation(), std::move(patterns));
   }
 };
 
 struct TestVectorTransferCollapseInnerMostContiguousDims
     : public PassWrapper<TestVectorTransferCollapseInnerMostContiguousDims,
-                         FunctionPass> {
+                         OperationPass<FuncOp>> {
   TestVectorTransferCollapseInnerMostContiguousDims() = default;
   TestVectorTransferCollapseInnerMostContiguousDims(
       const TestVectorTransferCollapseInnerMostContiguousDims &pass) = default;
@@ -565,16 +567,16 @@ struct TestVectorTransferCollapseInnerMostContiguousDims
            "transfer memory and vector operands.";
   }
 
-  void runOnFunction() override {
+  void runOnOperation() override {
     RewritePatternSet patterns(&getContext());
     populateVectorTransferCollapseInnerMostContiguousDimsPatterns(patterns);
-    (void)applyPatternsAndFoldGreedily(getFunction(), std::move(patterns));
+    (void)applyPatternsAndFoldGreedily(getOperation(), std::move(patterns));
   }
 };
 
 struct TestVectorReduceToContractPatternsPatterns
     : public PassWrapper<TestVectorReduceToContractPatternsPatterns,
-                         FunctionPass> {
+                         OperationPass<FuncOp>> {
   StringRef getArgument() const final {
     return "test-vector-reduction-to-contract-patterns";
   }
@@ -582,30 +584,32 @@ struct TestVectorReduceToContractPatternsPatterns
     return "Test patterns to convert multireduce op to contract and combine "
            "broadcast/transpose to contract";
   }
-  void runOnFunction() override {
+  void runOnOperation() override {
     RewritePatternSet patterns(&getContext());
     populateVectorReductionToContractPatterns(patterns);
-    (void)applyPatternsAndFoldGreedily(getFunction(), std::move(patterns));
+    (void)applyPatternsAndFoldGreedily(getOperation(), std::move(patterns));
   }
 };
 
 struct TestVectorTransferDropUnitDimsPatterns
-    : public PassWrapper<TestVectorTransferDropUnitDimsPatterns, FunctionPass> {
+    : public PassWrapper<TestVectorTransferDropUnitDimsPatterns,
+                         OperationPass<FuncOp>> {
   StringRef getArgument() const final {
     return "test-vector-transfer-drop-unit-dims-patterns";
   }
   void getDependentDialects(DialectRegistry &registry) const override {
     registry.insert<memref::MemRefDialect>();
   }
-  void runOnFunction() override {
+  void runOnOperation() override {
     RewritePatternSet patterns(&getContext());
     populateVectorTransferDropUnitDimsPatterns(patterns);
-    (void)applyPatternsAndFoldGreedily(getFunction(), std::move(patterns));
+    (void)applyPatternsAndFoldGreedily(getOperation(), std::move(patterns));
   }
 };
 
 struct TestFlattenVectorTransferPatterns
-    : public PassWrapper<TestFlattenVectorTransferPatterns, FunctionPass> {
+    : public PassWrapper<TestFlattenVectorTransferPatterns,
+                         OperationPass<FuncOp>> {
   StringRef getArgument() const final {
     return "test-vector-transfer-flatten-patterns";
   }
@@ -616,10 +620,10 @@ struct TestFlattenVectorTransferPatterns
   void getDependentDialects(DialectRegistry &registry) const override {
     registry.insert<memref::MemRefDialect>();
   }
-  void runOnFunction() override {
+  void runOnOperation() override {
     RewritePatternSet patterns(&getContext());
     populateFlattenVectorTransferPatterns(patterns);
-    (void)applyPatternsAndFoldGreedily(getFunction(), std::move(patterns));
+    (void)applyPatternsAndFoldGreedily(getOperation(), std::move(patterns));
   }
 };
 

diff  --git a/mlir/test/lib/IR/TestDominance.cpp b/mlir/test/lib/IR/TestDominance.cpp
index b49b73c860625..23e9e759bee4d 100644
--- a/mlir/test/lib/IR/TestDominance.cpp
+++ b/mlir/test/lib/IR/TestDominance.cpp
@@ -90,15 +90,16 @@ class DominanceTest {
   DenseMap<Block *, size_t> blockIds;
 };
 
-struct TestDominancePass : public PassWrapper<TestDominancePass, FunctionPass> {
+struct TestDominancePass
+    : public PassWrapper<TestDominancePass, OperationPass<FuncOp>> {
   StringRef getArgument() const final { return "test-print-dominance"; }
   StringRef getDescription() const final {
     return "Print the dominance information for multiple regions.";
   }
 
-  void runOnFunction() override {
-    llvm::errs() << "Testing : " << getFunction().getName() << "\n";
-    DominanceTest dominanceTest(getFunction());
+  void runOnOperation() override {
+    llvm::errs() << "Testing : " << getOperation().getName() << "\n";
+    DominanceTest dominanceTest(getOperation());
 
     // Print dominance information.
     llvm::errs() << "--- DominanceInfo ---\n";

diff  --git a/mlir/test/lib/IR/TestMatchers.cpp b/mlir/test/lib/IR/TestMatchers.cpp
index 66b9ad81f07ee..f76078f02d00c 100644
--- a/mlir/test/lib/IR/TestMatchers.cpp
+++ b/mlir/test/lib/IR/TestMatchers.cpp
@@ -15,8 +15,8 @@ using namespace mlir;
 
 namespace {
 /// This is a test pass for verifying matchers.
-struct TestMatchers : public PassWrapper<TestMatchers, FunctionPass> {
-  void runOnFunction() override;
+struct TestMatchers : public PassWrapper<TestMatchers, OperationPass<FuncOp>> {
+  void runOnOperation() override;
   StringRef getArgument() const final { return "test-matchers"; }
   StringRef getDescription() const final {
     return "Test C++ pattern matchers.";
@@ -144,8 +144,8 @@ void test2(FuncOp f) {
     llvm::outs() << "Pattern add(add(a, constant), a) matched\n";
 }
 
-void TestMatchers::runOnFunction() {
-  auto f = getFunction();
+void TestMatchers::runOnOperation() {
+  auto f = getOperation();
   llvm::outs() << f.getName() << "\n";
   if (f.getName() == "test1")
     test1(f);

diff  --git a/mlir/test/lib/IR/TestTypes.cpp b/mlir/test/lib/IR/TestTypes.cpp
index 7d078868f9dd8..3127ee567a8f3 100644
--- a/mlir/test/lib/IR/TestTypes.cpp
+++ b/mlir/test/lib/IR/TestTypes.cpp
@@ -15,15 +15,15 @@ using namespace test;
 
 namespace {
 struct TestRecursiveTypesPass
-    : public PassWrapper<TestRecursiveTypesPass, FunctionPass> {
+    : public PassWrapper<TestRecursiveTypesPass, OperationPass<FuncOp>> {
   LogicalResult createIRWithTypes();
 
   StringRef getArgument() const final { return "test-recursive-types"; }
   StringRef getDescription() const final {
     return "Test support for recursive types";
   }
-  void runOnFunction() override {
-    FuncOp func = getFunction();
+  void runOnOperation() override {
+    FuncOp func = getOperation();
 
     // Just make sure recursive types are printed and parsed.
     if (func.getName() == "roundtrip")
@@ -45,7 +45,7 @@ struct TestRecursiveTypesPass
 
 LogicalResult TestRecursiveTypesPass::createIRWithTypes() {
   MLIRContext *ctx = &getContext();
-  FuncOp func = getFunction();
+  FuncOp func = getOperation();
   auto type = TestRecursiveType::get(ctx, "some_long_and_unique_name");
   if (failed(type.setBody(type)))
     return func.emitError("expected to be able to set the type body");

diff  --git a/mlir/test/lib/Pass/TestPassManager.cpp b/mlir/test/lib/Pass/TestPassManager.cpp
index 243bd8b86981e..af429ebeeca54 100644
--- a/mlir/test/lib/Pass/TestPassManager.cpp
+++ b/mlir/test/lib/Pass/TestPassManager.cpp
@@ -21,14 +21,16 @@ struct TestModulePass
     return "Test a module pass in the pass manager";
   }
 };
-struct TestFunctionPass : public PassWrapper<TestFunctionPass, FunctionPass> {
-  void runOnFunction() final {}
+struct TestFunctionPass
+    : public PassWrapper<TestFunctionPass, OperationPass<FuncOp>> {
+  void runOnOperation() final {}
   StringRef getArgument() const final { return "test-function-pass"; }
   StringRef getDescription() const final {
     return "Test a function pass in the pass manager";
   }
 };
-class TestOptionsPass : public PassWrapper<TestOptionsPass, FunctionPass> {
+class TestOptionsPass
+    : public PassWrapper<TestOptionsPass, OperationPass<FuncOp>> {
 public:
   struct Options : public PassPipelineOptions<Options> {
     ListOption<int> listOption{*this, "list",
@@ -48,7 +50,7 @@ class TestOptionsPass : public PassWrapper<TestOptionsPass, FunctionPass> {
     stringListOption = options.stringListOption;
   }
 
-  void runOnFunction() final {}
+  void runOnOperation() final {}
   StringRef getArgument() const final { return "test-options-pass"; }
   StringRef getDescription() const final {
     return "Test options parsing capabilities";

diff  --git a/mlir/test/lib/Transforms/TestConstantFold.cpp b/mlir/test/lib/Transforms/TestConstantFold.cpp
index ef5c995f4b1ae..f0ea5fa888265 100644
--- a/mlir/test/lib/Transforms/TestConstantFold.cpp
+++ b/mlir/test/lib/Transforms/TestConstantFold.cpp
@@ -15,7 +15,8 @@ using namespace mlir;
 
 namespace {
 /// Simple constant folding pass.
-struct TestConstantFold : public PassWrapper<TestConstantFold, FunctionPass> {
+struct TestConstantFold
+    : public PassWrapper<TestConstantFold, OperationPass<FuncOp>> {
   StringRef getArgument() const final { return "test-constant-fold"; }
   StringRef getDescription() const final {
     return "Test operation constant folding";
@@ -24,7 +25,7 @@ struct TestConstantFold : public PassWrapper<TestConstantFold, FunctionPass> {
   SmallVector<Operation *, 8> existingConstants;
 
   void foldOperation(Operation *op, OperationFolder &helper);
-  void runOnFunction() override;
+  void runOnOperation() override;
 };
 } // namespace
 
@@ -41,12 +42,12 @@ void TestConstantFold::foldOperation(Operation *op, OperationFolder &helper) {
 // For now, we do a simple top-down pass over a function folding constants.  We
 // don't handle conditional control flow, block arguments, folding conditional
 // branches, or anything else fancy.
-void TestConstantFold::runOnFunction() {
+void TestConstantFold::runOnOperation() {
   existingConstants.clear();
 
   // Collect and fold the operations within the function.
   SmallVector<Operation *, 8> ops;
-  getFunction().walk([&](Operation *op) { ops.push_back(op); });
+  getOperation().walk([&](Operation *op) { ops.push_back(op); });
 
   // Fold the constants in reverse so that the last generated constants from
   // folding are at the beginning. This creates somewhat of a linear ordering to

diff  --git a/mlir/test/lib/Transforms/TestInlining.cpp b/mlir/test/lib/Transforms/TestInlining.cpp
index f4ccede65a24a..8f1706357affd 100644
--- a/mlir/test/lib/Transforms/TestInlining.cpp
+++ b/mlir/test/lib/Transforms/TestInlining.cpp
@@ -25,14 +25,14 @@ using namespace mlir;
 using namespace test;
 
 namespace {
-struct Inliner : public PassWrapper<Inliner, FunctionPass> {
+struct Inliner : public PassWrapper<Inliner, OperationPass<FuncOp>> {
   StringRef getArgument() const final { return "test-inline"; }
   StringRef getDescription() const final {
     return "Test inlining region calls";
   }
 
-  void runOnFunction() override {
-    auto function = getFunction();
+  void runOnOperation() override {
+    auto function = getOperation();
 
     // Collect each of the direct function calls within the module.
     SmallVector<CallIndirectOp, 16> callers;

diff  --git a/mlir/test/lib/Transforms/TestLoopFusion.cpp b/mlir/test/lib/Transforms/TestLoopFusion.cpp
index 7c1e3a2674625..70fcdeb9f5517 100644
--- a/mlir/test/lib/Transforms/TestLoopFusion.cpp
+++ b/mlir/test/lib/Transforms/TestLoopFusion.cpp
@@ -41,12 +41,13 @@ static llvm::cl::opt<bool> clTestLoopFusionTransformation(
 
 namespace {
 
-struct TestLoopFusion : public PassWrapper<TestLoopFusion, FunctionPass> {
+struct TestLoopFusion
+    : public PassWrapper<TestLoopFusion, OperationPass<FuncOp>> {
   StringRef getArgument() const final { return "test-loop-fusion"; }
   StringRef getDescription() const final {
     return "Tests loop fusion utility functions.";
   }
-  void runOnFunction() override;
+  void runOnOperation() override;
 };
 
 } // namespace
@@ -175,14 +176,14 @@ static bool iterateLoops(ArrayRef<SmallVector<AffineForOp, 2>> depthToLoops,
   return changed;
 }
 
-void TestLoopFusion::runOnFunction() {
+void TestLoopFusion::runOnOperation() {
   std::vector<SmallVector<AffineForOp, 2>> depthToLoops;
   if (clTestLoopFusionTransformation) {
     // Run loop fusion until a fixed point is reached.
     do {
       depthToLoops.clear();
       // Gather all AffineForOps by loop depth.
-      gatherLoops(getFunction(), depthToLoops);
+      gatherLoops(getOperation(), depthToLoops);
 
       // Try to fuse all combinations of src/dst loop nests in 'depthToLoops'.
     } while (iterateLoops(depthToLoops, testLoopFusionTransformation,
@@ -191,7 +192,7 @@ void TestLoopFusion::runOnFunction() {
   }
 
   // Gather all AffineForOps by loop depth.
-  gatherLoops(getFunction(), depthToLoops);
+  gatherLoops(getOperation(), depthToLoops);
 
   // Run tests on all combinations of src/dst loop nests in 'depthToLoops'.
   if (clTestDependenceCheck)

diff  --git a/mlir/test/lib/Transforms/TestLoopMapping.cpp b/mlir/test/lib/Transforms/TestLoopMapping.cpp
index 721e697dd902d..09ea69d68dcbe 100644
--- a/mlir/test/lib/Transforms/TestLoopMapping.cpp
+++ b/mlir/test/lib/Transforms/TestLoopMapping.cpp
@@ -24,7 +24,7 @@ using namespace mlir;
 
 namespace {
 class TestLoopMappingPass
-    : public PassWrapper<TestLoopMappingPass, FunctionPass> {
+    : public PassWrapper<TestLoopMappingPass, OperationPass<FuncOp>> {
 public:
   StringRef getArgument() const final {
     return "test-mapping-to-processing-elements";
@@ -38,8 +38,8 @@ class TestLoopMappingPass
     registry.insert<AffineDialect, scf::SCFDialect>();
   }
 
-  void runOnFunction() override {
-    FuncOp func = getFunction();
+  void runOnOperation() override {
+    FuncOp func = getOperation();
 
     // SSA values for the transformation are created out of thin air by
     // unregistered "new_processor_id_and_range" operations. This is enough to

diff  --git a/mlir/test/lib/Transforms/TestLoopParametricTiling.cpp b/mlir/test/lib/Transforms/TestLoopParametricTiling.cpp
index d362c2eccba14..184a7331bc559 100644
--- a/mlir/test/lib/Transforms/TestLoopParametricTiling.cpp
+++ b/mlir/test/lib/Transforms/TestLoopParametricTiling.cpp
@@ -23,7 +23,8 @@ namespace {
 // Extracts fixed-range loops for top-level loop nests with ranges defined in
 // the pass constructor.  Assumes loops are permutable.
 class SimpleParametricLoopTilingPass
-    : public PassWrapper<SimpleParametricLoopTilingPass, FunctionPass> {
+    : public PassWrapper<SimpleParametricLoopTilingPass,
+                         OperationPass<FuncOp>> {
 public:
   StringRef getArgument() const final {
     return "test-extract-fixed-outer-loops";
@@ -39,8 +40,8 @@ class SimpleParametricLoopTilingPass
     sizes = outerLoopSizes;
   }
 
-  void runOnFunction() override {
-    FuncOp func = getFunction();
+  void runOnOperation() override {
+    FuncOp func = getOperation();
     func.walk([this](scf::ForOp op) {
       // Ignore nested loops.
       if (op->getParentRegion()->getParentOfType<scf::ForOp>())

diff  --git a/mlir/test/lib/Transforms/TestLoopUnrolling.cpp b/mlir/test/lib/Transforms/TestLoopUnrolling.cpp
index 7ec2c8b30be02..1063853e434ba 100644
--- a/mlir/test/lib/Transforms/TestLoopUnrolling.cpp
+++ b/mlir/test/lib/Transforms/TestLoopUnrolling.cpp
@@ -33,7 +33,7 @@ static unsigned getNestingDepth(Operation *op) {
 }
 
 class TestLoopUnrollingPass
-    : public PassWrapper<TestLoopUnrollingPass, FunctionPass> {
+    : public PassWrapper<TestLoopUnrollingPass, OperationPass<FuncOp>> {
 public:
   StringRef getArgument() const final { return "test-loop-unrolling"; }
   StringRef getDescription() const final {
@@ -53,8 +53,8 @@ class TestLoopUnrollingPass
     registry.insert<arith::ArithmeticDialect, StandardOpsDialect>();
   }
 
-  void runOnFunction() override {
-    FuncOp func = getFunction();
+  void runOnOperation() override {
+    FuncOp func = getOperation();
     SmallVector<scf::ForOp, 4> loops;
     func.walk([&](scf::ForOp forOp) {
       if (getNestingDepth(forOp) == loopDepth)

diff  --git a/mlir/unittests/Pass/PassManagerTest.cpp b/mlir/unittests/Pass/PassManagerTest.cpp
index ff1cda2116ba9..8421bcc33a21e 100644
--- a/mlir/unittests/Pass/PassManagerTest.cpp
+++ b/mlir/unittests/Pass/PassManagerTest.cpp
@@ -31,7 +31,6 @@ struct OpSpecificAnalysis {
 };
 
 /// Simple pass to annotate a FuncOp with the results of analysis.
-/// Note: not using FunctionPass as it skip external functions.
 struct AnnotateFunctionPass
     : public PassWrapper<AnnotateFunctionPass, OperationPass<FuncOp>> {
   void runOnOperation() override {


        


More information about the Mlir-commits mailing list