[Mlir-commits] [mlir] [llvm] [mlir] Add config for PDL (PR #69927)

Jacques Pienaar llvmlistbot at llvm.org
Tue Dec 19 11:03:28 PST 2023


https://github.com/jpienaar updated https://github.com/llvm/llvm-project/pull/69927

>From b2c293bc867bcd6000841e7e515e119bf3a13a01 Mon Sep 17 00:00:00 2001
From: Jacques Pienaar <jpienaar at google.com>
Date: Sun, 22 Oct 2023 09:33:40 -0700
Subject: [PATCH 1/6] [mlir] Add config for PDL

Make it so that PDL can be optionally disabled. PDL is different than
other dialects as its included in rewrite framework. This results in
these being included even where it isn't used and not removed during
compilation. Add option to disable for workloads where it isn't needed
or used. This ends up being rather invasive due to how PDL is included.
Ideally we'd have less ifdefs.

PDL is enabled by default (and not optional bazel).

This only works with tests disabled. With tests enabled this still
compiles but tests fail as there is no lit config to disable tests that
depend on PDL yet.
---
 mlir/CMakeLists.txt                           | 12 ++--
 mlir/cmake/modules/AddMLIR.cmake              |  3 +
 mlir/examples/CMakeLists.txt                  |  4 +-
 mlir/examples/minimal-opt/README.md           |  9 +--
 mlir/include/mlir/Config/mlir-config.h.cmake  |  3 +
 mlir/include/mlir/Conversion/Passes.td        |  2 +
 mlir/include/mlir/Dialect/CMakeLists.txt      |  6 +-
 .../mlir/Dialect/Transform/CMakeLists.txt     |  4 +-
 mlir/include/mlir/IR/PatternMatch.h           | 17 +++++
 mlir/include/mlir/InitAllDialects.h           |  9 ++-
 mlir/include/mlir/InitAllExtensions.h         | 11 +++-
 .../mlir/Rewrite/FrozenRewritePatternSet.h    |  6 ++
 mlir/include/mlir/Rewrite/PatternApplicator.h |  5 ++
 .../mlir/Transforms/DialectConversion.h       |  2 +
 mlir/lib/CAPI/Dialect/CMakeLists.txt          | 18 +++---
 mlir/lib/Conversion/CMakeLists.txt            |  4 +-
 mlir/lib/Dialect/Bufferization/CMakeLists.txt |  4 +-
 .../Bufferization/TransformOps/CMakeLists.txt |  1 -
 mlir/lib/Dialect/CMakeLists.txt               |  6 +-
 mlir/lib/Dialect/Transform/CMakeLists.txt     |  4 +-
 mlir/lib/IR/PatternMatch.cpp                  |  2 +
 mlir/lib/Rewrite/CMakeLists.txt               | 24 +++++--
 mlir/lib/Rewrite/FrozenRewritePatternSet.cpp  | 13 +++-
 mlir/lib/Rewrite/PatternApplicator.cpp        | 26 +++++++-
 mlir/lib/Tools/CMakeLists.txt                 |  6 +-
 .../Transforms/Utils/DialectConversion.cpp    |  2 +
 mlir/python/CMakeLists.txt                    | 62 ++++++++++---------
 mlir/test/CAPI/CMakeLists.txt                 | 16 ++---
 mlir/test/CMakeLists.txt                      | 20 ++++--
 mlir/test/lib/Dialect/CMakeLists.txt          |  5 +-
 mlir/test/lib/Rewrite/CMakeLists.txt          |  3 +-
 mlir/test/lib/Tools/CMakeLists.txt            |  4 +-
 mlir/test/lib/Transforms/CMakeLists.txt       | 28 ++++++---
 mlir/tools/CMakeLists.txt                     |  4 +-
 mlir/tools/mlir-lsp-server/CMakeLists.txt     | 10 ++-
 .../tools/mlir-lsp-server/mlir-lsp-server.cpp |  4 ++
 mlir/tools/mlir-opt/CMakeLists.txt            | 10 ++-
 mlir/tools/mlir-opt/mlir-opt.cpp              | 16 +++--
 mlir/unittests/Conversion/CMakeLists.txt      |  4 +-
 mlir/unittests/Dialect/CMakeLists.txt         |  4 +-
 .../llvm-project-overlay/mlir/BUILD.bazel     |  1 +
 41 files changed, 284 insertions(+), 110 deletions(-)

diff --git a/mlir/CMakeLists.txt b/mlir/CMakeLists.txt
index 16ff950089734b..42b9eb3ec7949e 100644
--- a/mlir/CMakeLists.txt
+++ b/mlir/CMakeLists.txt
@@ -133,6 +133,8 @@ set(MLIR_ENABLE_NVPTXCOMPILER 0 CACHE BOOL
     "Statically link the nvptxlibrary instead of calling ptxas as a subprocess \
     for compiling PTX to cubin")
 
+set(MLIR_ENABLE_PDL 1 CACHE BOOL "Enable PDL")
+
 option(MLIR_INCLUDE_TESTS
        "Generate build targets for the MLIR unit tests."
        ${LLVM_INCLUDE_TESTS})
@@ -180,12 +182,14 @@ include_directories( ${MLIR_INCLUDE_DIR})
 # from another directory like tools
 add_subdirectory(tools/mlir-tblgen)
 add_subdirectory(tools/mlir-linalg-ods-gen)
-add_subdirectory(tools/mlir-pdll)
-
 set(MLIR_TABLEGEN_EXE "${MLIR_TABLEGEN_EXE}" CACHE INTERNAL "")
 set(MLIR_TABLEGEN_TARGET "${MLIR_TABLEGEN_TARGET}" CACHE INTERNAL "")
-set(MLIR_PDLL_TABLEGEN_EXE "${MLIR_PDLL_TABLEGEN_EXE}" CACHE INTERNAL "")
-set(MLIR_PDLL_TABLEGEN_TARGET "${MLIR_PDLL_TABLEGEN_TARGET}" CACHE INTERNAL "")
+
+if(MLIR_ENABLE_PDL)
+  add_subdirectory(tools/mlir-pdll)
+  set(MLIR_PDLL_TABLEGEN_EXE "${MLIR_PDLL_TABLEGEN_EXE}" CACHE INTERNAL "")
+  set(MLIR_PDLL_TABLEGEN_TARGET "${MLIR_PDLL_TABLEGEN_TARGET}" CACHE INTERNAL "")
+endif()
 
 add_subdirectory(include/mlir)
 add_subdirectory(lib)
diff --git a/mlir/cmake/modules/AddMLIR.cmake b/mlir/cmake/modules/AddMLIR.cmake
index 1d2ed748bc2f13..2f698f8311df3a 100644
--- a/mlir/cmake/modules/AddMLIR.cmake
+++ b/mlir/cmake/modules/AddMLIR.cmake
@@ -2,6 +2,9 @@ include(GNUInstallDirs)
 include(LLVMDistributionSupport)
 
 function(mlir_tablegen ofn)
+  if (MLIR_ENABLE_PDL)
+    list(APPEND LLVM_TABLEGEN_FLAGS "-DMLIR_ENABLE_PDL")
+  endif()
   tablegen(MLIR ${ARGV})
   set(TABLEGEN_OUTPUT ${TABLEGEN_OUTPUT} ${CMAKE_CURRENT_BINARY_DIR}/${ofn}
       PARENT_SCOPE)
diff --git a/mlir/examples/CMakeLists.txt b/mlir/examples/CMakeLists.txt
index d256bf1a5cbb13..88a22201c73d9f 100644
--- a/mlir/examples/CMakeLists.txt
+++ b/mlir/examples/CMakeLists.txt
@@ -1,3 +1,5 @@
 add_subdirectory(toy)
-add_subdirectory(transform)
+if(MLIR_ENABLE_PDL)
+  add_subdirectory(transform)
+endif()
 add_subdirectory(minimal-opt)
diff --git a/mlir/examples/minimal-opt/README.md b/mlir/examples/minimal-opt/README.md
index b8a455f7a79662..09d0f20c34e426 100644
--- a/mlir/examples/minimal-opt/README.md
+++ b/mlir/examples/minimal-opt/README.md
@@ -14,10 +14,10 @@ Below are some example measurements taken at the time of the LLVM 17 release,
 using clang-14 on a X86 Ubuntu and [bloaty](https://github.com/google/bloaty).
 
 |                                  | Base   | Os     | Oz     | Os LTO | Oz LTO |
-| :-----------------------------: | ------ | ------ | ------ | ------ | ------ |
-| `mlir-cat`                      | 1018kB | 836KB  | 879KB  | 697KB  | 649KB  |
-| `mlir-minimal-opt`              | 1.54MB | 1.25MB | 1.29MB | 1.10MB | 1.00MB |
-| `mlir-minimal-opt-canonicalize` | 2.24MB | 1.81MB | 1.86MB | 1.62MB | 1.48MB |
+| :------------------------------: | ------ | ------ | ------ | ------ | ------ |
+| `mlir-cat`                       | 1024KB |  840KB |  885KB |  706KB |  657KB |
+| `mlir-minimal-opt`               | 1.62MB | 1.32MB | 1.36MB | 1.17MB | 1.07MB |
+| `mlir-minimal-opt-canonicalize`  | 1.83MB | 1.40MB | 1.45MB | 1.25MB | 1.14MB |
 
 Base configuration:
 
@@ -32,6 +32,7 @@ cmake ../llvm/ -G Ninja \
    -DCMAKE_CXX_COMPILER=clang++ \
    -DLLVM_ENABLE_LLD=ON \
    -DLLVM_ENABLE_BACKTRACES=OFF \
+   -DMLIR_ENABLE_PDL=OFF \
    -DCMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO=-Wl,-icf=all
 ```
 
diff --git a/mlir/include/mlir/Config/mlir-config.h.cmake b/mlir/include/mlir/Config/mlir-config.h.cmake
index efa77b2e5ce5db..a2789b8e2d5867 100644
--- a/mlir/include/mlir/Config/mlir-config.h.cmake
+++ b/mlir/include/mlir/Config/mlir-config.h.cmake
@@ -26,4 +26,7 @@
    numeric seed that is passed to the random number generator. */
 #cmakedefine MLIR_GREEDY_REWRITE_RANDOMIZER_SEED ${MLIR_GREEDY_REWRITE_RANDOMIZER_SEED}
 
+/* If set, enables PDL usage. */
+#cmakedefine MLIR_ENABLE_PDL ${MLIR_ENABLE_PDL}
+
 #endif
diff --git a/mlir/include/mlir/Conversion/Passes.td b/mlir/include/mlir/Conversion/Passes.td
index 6193aeb545bc6b..5ef7aeb2514b7d 100644
--- a/mlir/include/mlir/Conversion/Passes.td
+++ b/mlir/include/mlir/Conversion/Passes.td
@@ -831,6 +831,7 @@ def ConvertOpenMPToLLVMPass : Pass<"convert-openmp-to-llvm", "ModuleOp"> {
   let dependentDialects = ["LLVM::LLVMDialect"];
 }
 
+#ifdef MLIR_ENABLE_PDL
 //===----------------------------------------------------------------------===//
 // PDLToPDLInterp
 //===----------------------------------------------------------------------===//
@@ -840,6 +841,7 @@ def ConvertPDLToPDLInterp : Pass<"convert-pdl-to-pdl-interp", "ModuleOp"> {
   let constructor = "mlir::createPDLToPDLInterpPass()";
   let dependentDialects = ["pdl_interp::PDLInterpDialect"];
 }
+#endif
 
 //===----------------------------------------------------------------------===//
 // ReconcileUnrealizedCasts
diff --git a/mlir/include/mlir/Dialect/CMakeLists.txt b/mlir/include/mlir/Dialect/CMakeLists.txt
index 1c4569ecfa5848..c2dd7a9dcfd9c7 100644
--- a/mlir/include/mlir/Dialect/CMakeLists.txt
+++ b/mlir/include/mlir/Dialect/CMakeLists.txt
@@ -25,8 +25,10 @@ add_subdirectory(NVGPU)
 add_subdirectory(OpenACC)
 add_subdirectory(OpenACCMPCommon)
 add_subdirectory(OpenMP)
-add_subdirectory(PDL)
-add_subdirectory(PDLInterp)
+if (MLIR_ENABLE_PDL)
+  add_subdirectory(PDL)
+  add_subdirectory(PDLInterp)
+endif()
 add_subdirectory(Quant)
 add_subdirectory(SCF)
 add_subdirectory(Shape)
diff --git a/mlir/include/mlir/Dialect/Transform/CMakeLists.txt b/mlir/include/mlir/Dialect/Transform/CMakeLists.txt
index d6c5c975c2e93c..3e6b222c208f25 100644
--- a/mlir/include/mlir/Dialect/Transform/CMakeLists.txt
+++ b/mlir/include/mlir/Dialect/Transform/CMakeLists.txt
@@ -1,4 +1,6 @@
 add_subdirectory(IR)
 add_subdirectory(LoopExtension)
-add_subdirectory(PDLExtension)
+if (MLIR_ENABLE_PDL)
+  add_subdirectory(PDLExtension)
+endif()
 add_subdirectory(Transforms)
diff --git a/mlir/include/mlir/IR/PatternMatch.h b/mlir/include/mlir/IR/PatternMatch.h
index 6625ef553eba21..060f8f5f602b99 100644
--- a/mlir/include/mlir/IR/PatternMatch.h
+++ b/mlir/include/mlir/IR/PatternMatch.h
@@ -9,6 +9,7 @@
 #ifndef MLIR_IR_PATTERNMATCH_H
 #define MLIR_IR_PATTERNMATCH_H
 
+#include "mlir/Config/mlir-config.h"
 #include "mlir/IR/Builders.h"
 #include "mlir/IR/BuiltinOps.h"
 #include "llvm/ADT/FunctionExtras.h"
@@ -735,6 +736,7 @@ class PatternRewriter : public RewriterBase {
   virtual bool canRecoverFromRewriteFailure() const { return false; }
 };
 
+#if MLIR_ENABLE_PDL
 //===----------------------------------------------------------------------===//
 // PDL Patterns
 //===----------------------------------------------------------------------===//
@@ -1661,6 +1663,7 @@ class PDLPatternModule {
   llvm::StringMap<PDLConstraintFunction> constraintFunctions;
   llvm::StringMap<PDLRewriteFunction> rewriteFunctions;
 };
+#endif // MLIR_ENABLE_PDL
 
 //===----------------------------------------------------------------------===//
 // RewritePatternSet
@@ -1678,22 +1681,28 @@ class RewritePatternSet {
       : context(context) {
     nativePatterns.emplace_back(std::move(pattern));
   }
+#if MLIR_ENABLE_PDL
   RewritePatternSet(PDLPatternModule &&pattern)
       : context(pattern.getModule()->getContext()),
         pdlPatterns(std::move(pattern)) {}
+#endif // MLIR_ENABLE_PDL
 
   MLIRContext *getContext() const { return context; }
 
   /// Return the native patterns held in this list.
   NativePatternListT &getNativePatterns() { return nativePatterns; }
 
+#if MLIR_ENABLE_PDL
   /// Return the PDL patterns held in this list.
   PDLPatternModule &getPDLPatterns() { return pdlPatterns; }
+#endif
 
   /// Clear out all of the held patterns in this list.
   void clear() {
     nativePatterns.clear();
+#if MLIR_ENABLE_PDL
     pdlPatterns.clear();
+#endif
   }
 
   //===--------------------------------------------------------------------===//
@@ -1746,12 +1755,14 @@ class RewritePatternSet {
     return *this;
   }
 
+#if MLIR_ENABLE_PDL
   /// Add the given PDL pattern to the pattern list. Return a reference to
   /// `this` for chaining insertions.
   RewritePatternSet &add(PDLPatternModule &&pattern) {
     pdlPatterns.mergeIn(std::move(pattern));
     return *this;
   }
+#endif // MLIR_ENABLE_PDL
 
   // Add a matchAndRewrite style pattern represented as a C function pointer.
   template <typename OpType>
@@ -1812,12 +1823,14 @@ class RewritePatternSet {
     return *this;
   }
 
+#if MLIR_ENABLE_PDL
   /// Add the given PDL pattern to the pattern list. Return a reference to
   /// `this` for chaining insertions.
   RewritePatternSet &insert(PDLPatternModule &&pattern) {
     pdlPatterns.mergeIn(std::move(pattern));
     return *this;
   }
+#endif // MLIR_ENABLE_PDL
 
   // Add a matchAndRewrite style pattern represented as a C function pointer.
   template <typename OpType>
@@ -1853,6 +1866,7 @@ class RewritePatternSet {
     pattern->addDebugLabels(debugLabels);
     nativePatterns.emplace_back(std::move(pattern));
   }
+#if MLIR_ENABLE_PDL
   template <typename T, typename... Args>
   std::enable_if_t<std::is_base_of<PDLPatternModule, T>::value>
   addImpl(ArrayRef<StringRef> debugLabels, Args &&...args) {
@@ -1860,10 +1874,13 @@ class RewritePatternSet {
     // labels.
     pdlPatterns.mergeIn(T(std::forward<Args>(args)...));
   }
+#endif // MLIR_ENABLE_PDL
 
   MLIRContext *const context;
   NativePatternListT nativePatterns;
+#if MLIR_ENABLE_PDL
   PDLPatternModule pdlPatterns;
+#endif // MLIR_ENABLE_PDL
 };
 
 } // namespace mlir
diff --git a/mlir/include/mlir/InitAllDialects.h b/mlir/include/mlir/InitAllDialects.h
index 19a62cadaa2e04..c75a599b40f0bc 100644
--- a/mlir/include/mlir/InitAllDialects.h
+++ b/mlir/include/mlir/InitAllDialects.h
@@ -14,6 +14,7 @@
 #ifndef MLIR_INITALLDIALECTS_H_
 #define MLIR_INITALLDIALECTS_H_
 
+#include "mlir/Config/mlir-config.h"
 #include "mlir/Dialect/AMDGPU/IR/AMDGPUDialect.h"
 #include "mlir/Dialect/AMX/AMXDialect.h"
 #include "mlir/Dialect/Affine/IR/AffineOps.h"
@@ -58,8 +59,6 @@
 #include "mlir/Dialect/NVGPU/IR/NVGPUDialect.h"
 #include "mlir/Dialect/OpenACC/OpenACC.h"
 #include "mlir/Dialect/OpenMP/OpenMPDialect.h"
-#include "mlir/Dialect/PDL/IR/PDL.h"
-#include "mlir/Dialect/PDLInterp/IR/PDLInterp.h"
 #include "mlir/Dialect/Quant/QuantOps.h"
 #include "mlir/Dialect/SCF/IR/SCF.h"
 #include "mlir/Dialect/SCF/IR/ValueBoundsOpInterfaceImpl.h"
@@ -92,6 +91,10 @@
 #include "mlir/Target/LLVM/NVVM/Target.h"
 #include "mlir/Target/LLVM/ROCDL/Target.h"
 #include "mlir/Target/SPIRV/Target.h"
+#if MLIR_ENABLE_PDL
+#include "mlir/Dialect/PDL/IR/PDL.h"
+#include "mlir/Dialect/PDLInterp/IR/PDLInterp.h"
+#endif // MLIR_ENABLE_PDL
 
 namespace mlir {
 
@@ -125,8 +128,10 @@ inline void registerAllDialects(DialectRegistry &registry) {
                   nvgpu::NVGPUDialect,
                   NVVM::NVVMDialect,
                   omp::OpenMPDialect,
+#if MLIR_ENABLE_PDL
                   pdl::PDLDialect,
                   pdl_interp::PDLInterpDialect,
+#endif // MLIR_ENABLE_PDL
                   quant::QuantizationDialect,
                   ROCDL::ROCDLDialect,
                   scf::SCFDialect,
diff --git a/mlir/include/mlir/InitAllExtensions.h b/mlir/include/mlir/InitAllExtensions.h
index c04ce850fb96f4..ae898ef6a86646 100644
--- a/mlir/include/mlir/InitAllExtensions.h
+++ b/mlir/include/mlir/InitAllExtensions.h
@@ -14,6 +14,7 @@
 #ifndef MLIR_INITALLEXTENSIONS_H_
 #define MLIR_INITALLEXTENSIONS_H_
 
+#include "mlir/Config/mlir-config.h"
 #include "mlir/Conversion/ArithToLLVM/ArithToLLVM.h"
 #include "mlir/Conversion/ComplexToLLVM/ComplexToLLVM.h"
 #include "mlir/Conversion/ControlFlowToLLVM/ControlFlowToLLVM.h"
@@ -24,7 +25,6 @@
 #include "mlir/Conversion/NVVMToLLVM/NVVMToLLVM.h"
 #include "mlir/Conversion/UBToLLVM/UBToLLVM.h"
 #include "mlir/Dialect/Affine/TransformOps/AffineTransformOps.h"
-#include "mlir/Dialect/Bufferization/TransformOps/BufferizationTransformOps.h"
 #include "mlir/Dialect/Func/Extensions/AllExtensions.h"
 #include "mlir/Dialect/Func/TransformOps/FuncTransformOps.h"
 #include "mlir/Dialect/GPU/TransformOps/GPUTransformOps.h"
@@ -35,12 +35,15 @@
 #include "mlir/Dialect/SparseTensor/TransformOps/SparseTensorTransformOps.h"
 #include "mlir/Dialect/Tensor/TransformOps/TensorTransformOps.h"
 #include "mlir/Dialect/Transform/LoopExtension/LoopExtension.h"
-#include "mlir/Dialect/Transform/PDLExtension/PDLExtension.h"
 #include "mlir/Dialect/Vector/TransformOps/VectorTransformOps.h"
 #include "mlir/Target/LLVMIR/Dialect/Builtin/BuiltinToLLVMIRTranslation.h"
 #include "mlir/Target/LLVMIR/Dialect/GPU/GPUToLLVMIRTranslation.h"
 #include "mlir/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.h"
 #include "mlir/Target/LLVMIR/Dialect/ROCDL/ROCDLToLLVMIRTranslation.h"
+#if MLIR_ENABLE_PDL
+#include "mlir/Dialect/Bufferization/TransformOps/BufferizationTransformOps.h"
+#include "mlir/Dialect/Transform/PDLExtension/PDLExtension.h"
+#endif // MLIR_ENABLE_PDL
 
 #include <cstdlib>
 
@@ -66,7 +69,6 @@ inline void registerAllExtensions(DialectRegistry &registry) {
 
   // Register all transform dialect extensions.
   affine::registerTransformDialectExtension(registry);
-  bufferization::registerTransformDialectExtension(registry);
   func::registerTransformDialectExtension(registry);
   gpu::registerTransformDialectExtension(registry);
   linalg::registerTransformDialectExtension(registry);
@@ -76,7 +78,10 @@ inline void registerAllExtensions(DialectRegistry &registry) {
   sparse_tensor::registerTransformDialectExtension(registry);
   tensor::registerTransformDialectExtension(registry);
   transform::registerLoopExtension(registry);
+#if MLIR_ENABLE_PDL
+  bufferization::registerTransformDialectExtension(registry);
   transform::registerPDLExtension(registry);
+#endif
   vector::registerTransformDialectExtension(registry);
 
   // Translation extensions need to be registered by calling
diff --git a/mlir/include/mlir/Rewrite/FrozenRewritePatternSet.h b/mlir/include/mlir/Rewrite/FrozenRewritePatternSet.h
index 4c6e3cd9ce6f4c..5c2edade10f0ce 100644
--- a/mlir/include/mlir/Rewrite/FrozenRewritePatternSet.h
+++ b/mlir/include/mlir/Rewrite/FrozenRewritePatternSet.h
@@ -12,9 +12,11 @@
 #include "mlir/IR/PatternMatch.h"
 
 namespace mlir {
+#if MLIR_ENABLE_PDL
 namespace detail {
 class PDLByteCode;
 } // namespace detail
+#endif // MLIR_ENABLE_PDL
 
 /// This class represents a frozen set of patterns that can be processed by a
 /// pattern applicator. This class is designed to enable caching pattern lists
@@ -64,11 +66,13 @@ class FrozenRewritePatternSet {
     return llvm::make_pointee_range(nativeList);
   }
 
+#if MLIR_ENABLE_PDL
   /// Return the compiled PDL bytecode held by this list. Returns null if
   /// there are no PDL patterns within the list.
   const detail::PDLByteCode *getPDLByteCode() const {
     return impl->pdlByteCode.get();
   }
+#endif // MLIR_ENABLE_PDL
 
 private:
   /// The internal implementation of the frozen pattern list.
@@ -85,8 +89,10 @@ class FrozenRewritePatternSet {
     /// operation.
     NativePatternListT nativeAnyOpPatterns;
 
+#if MLIR_ENABLE_PDL
     /// The bytecode containing the compiled PDL patterns.
     std::unique_ptr<detail::PDLByteCode> pdlByteCode;
+#endif // MLIR_ENABLE_PDL
   };
 
   /// A pointer to the internal pattern list. This uses a shared_ptr to avoid
diff --git a/mlir/include/mlir/Rewrite/PatternApplicator.h b/mlir/include/mlir/Rewrite/PatternApplicator.h
index f7871f819a273b..1c0f94c1bcc54d 100644
--- a/mlir/include/mlir/Rewrite/PatternApplicator.h
+++ b/mlir/include/mlir/Rewrite/PatternApplicator.h
@@ -21,9 +21,11 @@
 namespace mlir {
 class PatternRewriter;
 
+#if MLIR_ENABLE_PDL
 namespace detail {
 class PDLByteCodeMutableState;
 } // namespace detail
+#endif // MLIR_ENABLE_PDL
 
 /// This is the type of Action that is dispatched when a pattern is applied.
 /// It captures the pattern to apply on top of the usual context.
@@ -92,8 +94,11 @@ class PatternApplicator {
   /// The set of patterns that may match against any operation type, stable
   /// sorted by benefit.
   SmallVector<const RewritePattern *, 1> anyOpPatterns;
+
+#if MLIR_ENABLE_PDL
   /// The mutable state used during execution of the PDL bytecode.
   std::unique_ptr<detail::PDLByteCodeMutableState> mutableByteCodeState;
+#endif // MLIR_ENABLE_PDL
 };
 
 } // namespace mlir
diff --git a/mlir/include/mlir/Transforms/DialectConversion.h b/mlir/include/mlir/Transforms/DialectConversion.h
index 6de981d35c8c3a..9c5e3aa4e7e42a 100644
--- a/mlir/include/mlir/Transforms/DialectConversion.h
+++ b/mlir/include/mlir/Transforms/DialectConversion.h
@@ -1015,6 +1015,7 @@ class ConversionTarget {
   MLIRContext &ctx;
 };
 
+#if MLIR_ENABLE_PDL
 //===----------------------------------------------------------------------===//
 // PDL Configuration
 //===----------------------------------------------------------------------===//
@@ -1043,6 +1044,7 @@ class PDLConversionConfig final
 
 /// Register the dialect conversion PDL functions with the given pattern set.
 void registerConversionPDLFunctions(RewritePatternSet &patterns);
+#endif // MLIR_ENABLE_PDL
 
 //===----------------------------------------------------------------------===//
 // Op Conversion Entry Points
diff --git a/mlir/lib/CAPI/Dialect/CMakeLists.txt b/mlir/lib/CAPI/Dialect/CMakeLists.txt
index d815eba48d9b9d..73488d4b41bc84 100644
--- a/mlir/lib/CAPI/Dialect/CMakeLists.txt
+++ b/mlir/lib/CAPI/Dialect/CMakeLists.txt
@@ -207,14 +207,16 @@ add_mlir_upstream_c_api_library(MLIRCAPIOpenMP
   MLIROpenMPDialect
 )
 
-add_mlir_upstream_c_api_library(MLIRCAPIPDL
-  PDL.cpp
-
-  PARTIAL_SOURCES_INTENDED
-  LINK_LIBS PUBLIC
-  MLIRCAPIIR
-  MLIRPDLDialect
-)
+if(MLIR_ENABLE_PDL)
+  add_mlir_upstream_c_api_library(MLIRCAPIPDL
+    PDL.cpp
+
+    PARTIAL_SOURCES_INTENDED
+    LINK_LIBS PUBLIC
+    MLIRCAPIIR
+    MLIRPDLDialect
+  )
+endif()
 
 add_mlir_upstream_c_api_library(MLIRCAPIVector
   Vector.cpp
diff --git a/mlir/lib/Conversion/CMakeLists.txt b/mlir/lib/Conversion/CMakeLists.txt
index c3a2481975040c..113bb55aa4df33 100644
--- a/mlir/lib/Conversion/CMakeLists.txt
+++ b/mlir/lib/Conversion/CMakeLists.txt
@@ -38,7 +38,9 @@ add_subdirectory(NVGPUToNVVM)
 add_subdirectory(NVVMToLLVM)
 add_subdirectory(OpenACCToSCF)
 add_subdirectory(OpenMPToLLVM)
-add_subdirectory(PDLToPDLInterp)
+if(MLIR_ENABLE_PDL)
+  add_subdirectory(PDLToPDLInterp)
+endif()
 add_subdirectory(ReconcileUnrealizedCasts)
 add_subdirectory(SCFToControlFlow)
 add_subdirectory(SCFToEmitC)
diff --git a/mlir/lib/Dialect/Bufferization/CMakeLists.txt b/mlir/lib/Dialect/Bufferization/CMakeLists.txt
index 215ec562c9818c..a6ebca41ff3487 100644
--- a/mlir/lib/Dialect/Bufferization/CMakeLists.txt
+++ b/mlir/lib/Dialect/Bufferization/CMakeLists.txt
@@ -1,4 +1,6 @@
 add_subdirectory(IR)
 add_subdirectory(Pipelines)
-add_subdirectory(TransformOps)
+if(MLIR_ENABLE_PDL)
+  add_subdirectory(TransformOps)
+endif()
 add_subdirectory(Transforms)
diff --git a/mlir/lib/Dialect/Bufferization/TransformOps/CMakeLists.txt b/mlir/lib/Dialect/Bufferization/TransformOps/CMakeLists.txt
index 7f7b348b17ae68..be5eb73b91229f 100644
--- a/mlir/lib/Dialect/Bufferization/TransformOps/CMakeLists.txt
+++ b/mlir/lib/Dialect/Bufferization/TransformOps/CMakeLists.txt
@@ -14,7 +14,6 @@ add_mlir_dialect_library(MLIRBufferizationTransformOps
   MLIRFunctionInterfaces
   MLIRLinalgDialect
   MLIRParser
-  MLIRPDLDialect
   MLIRSideEffectInterfaces
   MLIRTransformDialect
   )
diff --git a/mlir/lib/Dialect/CMakeLists.txt b/mlir/lib/Dialect/CMakeLists.txt
index 68776a695cac4d..ae7c1d50e47939 100644
--- a/mlir/lib/Dialect/CMakeLists.txt
+++ b/mlir/lib/Dialect/CMakeLists.txt
@@ -25,8 +25,10 @@ add_subdirectory(NVGPU)
 add_subdirectory(OpenACC)
 add_subdirectory(OpenACCMPCommon)
 add_subdirectory(OpenMP)
-add_subdirectory(PDL)
-add_subdirectory(PDLInterp)
+if (MLIR_ENABLE_PDL)
+  add_subdirectory(PDL)
+  add_subdirectory(PDLInterp)
+endif()
 add_subdirectory(Quant)
 add_subdirectory(SCF)
 add_subdirectory(Shape)
diff --git a/mlir/lib/Dialect/Transform/CMakeLists.txt b/mlir/lib/Dialect/Transform/CMakeLists.txt
index 6898d81df7ca63..e0c7a7704fb865 100644
--- a/mlir/lib/Dialect/Transform/CMakeLists.txt
+++ b/mlir/lib/Dialect/Transform/CMakeLists.txt
@@ -1,5 +1,7 @@
 add_subdirectory(IR)
 add_subdirectory(LoopExtension)
-add_subdirectory(PDLExtension)
+if (MLIR_ENABLE_PDL)
+  add_subdirectory(PDLExtension)
+endif()
 add_subdirectory(Transforms)
 add_subdirectory(Utils)
diff --git a/mlir/lib/IR/PatternMatch.cpp b/mlir/lib/IR/PatternMatch.cpp
index 5e9b9b2a810a4c..a95b669557aab1 100644
--- a/mlir/lib/IR/PatternMatch.cpp
+++ b/mlir/lib/IR/PatternMatch.cpp
@@ -97,6 +97,7 @@ LogicalResult RewritePattern::match(Operation *op) const {
 /// Out-of-line vtable anchor.
 void RewritePattern::anchor() {}
 
+#if MLIR_ENABLE_PDL
 //===----------------------------------------------------------------------===//
 // PDLValue
 //===----------------------------------------------------------------------===//
@@ -214,6 +215,7 @@ void PDLPatternModule::registerRewriteFunction(StringRef name,
   // rewrite.
   rewriteFunctions.try_emplace(name, std::move(rewriteFn));
 }
+#endif // MLIR_ENABLE_PDL
 
 //===----------------------------------------------------------------------===//
 // RewriterBase
diff --git a/mlir/lib/Rewrite/CMakeLists.txt b/mlir/lib/Rewrite/CMakeLists.txt
index e0395be6cd6f59..3f0ad81e96967c 100644
--- a/mlir/lib/Rewrite/CMakeLists.txt
+++ b/mlir/lib/Rewrite/CMakeLists.txt
@@ -1,5 +1,23 @@
+set(LLVM_OPTIONAL_SOURCES ByteCode.cpp)
+
+if(MLIR_ENABLE_PDL)
+  set(MLIRRewritePDLDeps
+    MLIRPDLDialect
+    MLIRPDLInterpDialect
+    MLIRPDLToPDLInterp)
+else()
+  set(MLIRRewritePDLDeps)
+endif()
+
+if(MLIR_ENABLE_PDL)
+  set(MLIRRewritePDLSource
+    ByteCode.cpp)
+else()
+  set(MLIRRewritePDLSource)
+endif()
+
 add_mlir_library(MLIRRewrite
-  ByteCode.cpp
+  ${MLIRRewritePDLSource}
   FrozenRewritePatternSet.cpp
   PatternApplicator.cpp
 
@@ -11,8 +29,6 @@ add_mlir_library(MLIRRewrite
 
   LINK_LIBS PUBLIC
   MLIRIR
-  MLIRPDLDialect
-  MLIRPDLInterpDialect
-  MLIRPDLToPDLInterp
+  ${MLIRRewritePDLDeps}
   MLIRSideEffectInterfaces
   )
diff --git a/mlir/lib/Rewrite/FrozenRewritePatternSet.cpp b/mlir/lib/Rewrite/FrozenRewritePatternSet.cpp
index 43840d1e8cec2f..8793a6791ad94e 100644
--- a/mlir/lib/Rewrite/FrozenRewritePatternSet.cpp
+++ b/mlir/lib/Rewrite/FrozenRewritePatternSet.cpp
@@ -7,16 +7,20 @@
 //===----------------------------------------------------------------------===//
 
 #include "mlir/Rewrite/FrozenRewritePatternSet.h"
-#include "ByteCode.h"
-#include "mlir/Conversion/PDLToPDLInterp/PDLToPDLInterp.h"
-#include "mlir/Dialect/PDL/IR/PDLOps.h"
 #include "mlir/Interfaces/SideEffectInterfaces.h"
 #include "mlir/Pass/Pass.h"
 #include "mlir/Pass/PassManager.h"
 #include <optional>
 
+#if MLIR_ENABLE_PDL
+#include "ByteCode.h"
+#include "mlir/Conversion/PDLToPDLInterp/PDLToPDLInterp.h"
+#include "mlir/Dialect/PDL/IR/PDLOps.h"
+#endif // MLIR_ENABLE_PDL
+
 using namespace mlir;
 
+#if MLIR_ENABLE_PDL
 static LogicalResult
 convertPDLToPDLInterp(ModuleOp pdlModule,
                       DenseMap<Operation *, PDLPatternConfigSet *> &configMap) {
@@ -48,6 +52,7 @@ convertPDLToPDLInterp(ModuleOp pdlModule,
   pdlModule.getBody()->walk(simplifyFn);
   return success();
 }
+#endif // MLIR_ENABLE_PDL
 
 //===----------------------------------------------------------------------===//
 // FrozenRewritePatternSet
@@ -121,6 +126,7 @@ FrozenRewritePatternSet::FrozenRewritePatternSet(
     impl->nativeAnyOpPatterns.push_back(std::move(pat));
   }
 
+#if MLIR_ENABLE_PDL
   // Generate the bytecode for the PDL patterns if any were provided.
   PDLPatternModule &pdlPatterns = patterns.getPDLPatterns();
   ModuleOp pdlModule = pdlPatterns.getModule();
@@ -137,6 +143,7 @@ FrozenRewritePatternSet::FrozenRewritePatternSet(
       pdlModule, pdlPatterns.takeConfigs(), configMap,
       pdlPatterns.takeConstraintFunctions(),
       pdlPatterns.takeRewriteFunctions());
+#endif // MLIR_ENABLE_PDL
 }
 
 FrozenRewritePatternSet::~FrozenRewritePatternSet() = default;
diff --git a/mlir/lib/Rewrite/PatternApplicator.cpp b/mlir/lib/Rewrite/PatternApplicator.cpp
index 08d6ee618ac690..157de4bff06400 100644
--- a/mlir/lib/Rewrite/PatternApplicator.cpp
+++ b/mlir/lib/Rewrite/PatternApplicator.cpp
@@ -12,8 +12,10 @@
 //===----------------------------------------------------------------------===//
 
 #include "mlir/Rewrite/PatternApplicator.h"
-#include "ByteCode.h"
 #include "llvm/Support/Debug.h"
+#if MLIR_ENABLE_PDL
+#include "ByteCode.h"
+#endif // MLIR_ENABLE_PDL
 
 #define DEBUG_TYPE "pattern-application"
 
@@ -23,10 +25,12 @@ using namespace mlir::detail;
 PatternApplicator::PatternApplicator(
     const FrozenRewritePatternSet &frozenPatternList)
     : frozenPatternList(frozenPatternList) {
+#if MLIR_ENABLE_PDL
   if (const PDLByteCode *bytecode = frozenPatternList.getPDLByteCode()) {
     mutableByteCodeState = std::make_unique<PDLByteCodeMutableState>();
     bytecode->initializeMutableState(*mutableByteCodeState);
   }
+#endif // MLIR_ENABLE_PDL
 }
 PatternApplicator::~PatternApplicator() = default;
 
@@ -50,12 +54,14 @@ static void logSucessfulPatternApplication(Operation *op) {
 #endif
 
 void PatternApplicator::applyCostModel(CostModel model) {
+#if MLIR_ENABLE_PDL
   // Apply the cost model to the bytecode patterns first, and then the native
   // patterns.
   if (const PDLByteCode *bytecode = frozenPatternList.getPDLByteCode()) {
     for (const auto &it : llvm::enumerate(bytecode->getPatterns()))
       mutableByteCodeState->updatePatternBenefit(it.index(), model(it.value()));
   }
+#endif // MLIR_ENABLE_PDL
 
   // Copy over the patterns so that we can sort by benefit based on the cost
   // model. Patterns that are already impossible to match are ignored.
@@ -117,10 +123,12 @@ void PatternApplicator::walkAllPatterns(
       walk(*pattern);
   for (const Pattern &it : frozenPatternList.getMatchAnyOpNativePatterns())
     walk(it);
+#if MLIR_ENABLE_PDL
   if (const PDLByteCode *bytecode = frozenPatternList.getPDLByteCode()) {
     for (const Pattern &it : bytecode->getPatterns())
       walk(it);
   }
+#endif // MLIR_ENABLE_PDL
 }
 
 LogicalResult PatternApplicator::matchAndRewrite(
@@ -128,6 +136,7 @@ LogicalResult PatternApplicator::matchAndRewrite(
     function_ref<bool(const Pattern &)> canApply,
     function_ref<void(const Pattern &)> onFailure,
     function_ref<LogicalResult(const Pattern &)> onSuccess) {
+#if MLIR_ENABLE_PDL
   // Before checking native patterns, first match against the bytecode. This
   // won't automatically perform any rewrites so there is no need to worry about
   // conflicts.
@@ -135,6 +144,7 @@ LogicalResult PatternApplicator::matchAndRewrite(
   const PDLByteCode *bytecode = frozenPatternList.getPDLByteCode();
   if (bytecode)
     bytecode->match(op, rewriter, pdlMatches, *mutableByteCodeState);
+#endif // MLIR_ENABLE_PDL
 
   // Check to see if there are patterns matching this specific operation type.
   MutableArrayRef<const RewritePattern *> opPatterns;
@@ -146,13 +156,14 @@ LogicalResult PatternApplicator::matchAndRewrite(
   // operation type in an interleaved fashion.
   unsigned opIt = 0, opE = opPatterns.size();
   unsigned anyIt = 0, anyE = anyOpPatterns.size();
+#if MLIR_ENABLE_PDL
   unsigned pdlIt = 0, pdlE = pdlMatches.size();
+#endif // MLIR_ENABLE_PDL
   LogicalResult result = failure();
   do {
     // Find the next pattern with the highest benefit.
     const Pattern *bestPattern = nullptr;
     unsigned *bestPatternIt = &opIt;
-    const PDLByteCode::MatchResult *pdlMatch = nullptr;
 
     /// Operation specific patterns.
     if (opIt < opE)
@@ -164,6 +175,9 @@ LogicalResult PatternApplicator::matchAndRewrite(
       bestPatternIt = &anyIt;
       bestPattern = anyOpPatterns[anyIt];
     }
+
+#if MLIR_ENABLE_PDL
+    const PDLByteCode::MatchResult *pdlMatch = nullptr;
     /// PDL patterns.
     if (pdlIt < pdlE && (!bestPattern || bestPattern->getBenefit() <
                                              pdlMatches[pdlIt].benefit)) {
@@ -171,6 +185,8 @@ LogicalResult PatternApplicator::matchAndRewrite(
       pdlMatch = &pdlMatches[pdlIt];
       bestPattern = pdlMatch->pattern;
     }
+#endif // MLIR_ENABLE_PDL
+
     if (!bestPattern)
       break;
 
@@ -194,10 +210,14 @@ LogicalResult PatternApplicator::matchAndRewrite(
           // pattern.
           Operation *dumpRootOp = getDumpRootOp(op);
 #endif
+#if MLIR_ENABLE_PDL
           if (pdlMatch) {
             result =
                 bytecode->rewrite(rewriter, *pdlMatch, *mutableByteCodeState);
           } else {
+#else
+          {
+#endif // MLIR_ENABLE_PDL
             LLVM_DEBUG(llvm::dbgs() << "Trying to match \""
                                     << bestPattern->getDebugName() << "\"\n");
 
@@ -228,7 +248,9 @@ LogicalResult PatternApplicator::matchAndRewrite(
       break;
   } while (true);
 
+#if MLIR_ENABLE_PDL
   if (mutableByteCodeState)
     mutableByteCodeState->cleanupAfterMatchAndRewrite();
+#endif
   return result;
 }
diff --git a/mlir/lib/Tools/CMakeLists.txt b/mlir/lib/Tools/CMakeLists.txt
index 01270fa4b0fc34..54f03bd711d168 100644
--- a/mlir/lib/Tools/CMakeLists.txt
+++ b/mlir/lib/Tools/CMakeLists.txt
@@ -1,11 +1,13 @@
 add_subdirectory(lsp-server-support)
 add_subdirectory(mlir-lsp-server)
 add_subdirectory(mlir-opt)
-add_subdirectory(mlir-pdll-lsp-server)
 add_subdirectory(mlir-query)
 add_subdirectory(mlir-reduce)
 add_subdirectory(mlir-tblgen)
 add_subdirectory(mlir-translate)
-add_subdirectory(PDLL)
+if(MLIR_ENABLE_PDL)
+  add_subdirectory(PDLL)
+  add_subdirectory(mlir-pdll-lsp-server)
+endif()	
 add_subdirectory(Plugins)
 add_subdirectory(tblgen-lsp-server)
diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index 4d2afe462b9281..f9e0db11a92e2c 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -3312,6 +3312,7 @@ auto ConversionTarget::getOpInfo(OperationName op) const
   return std::nullopt;
 }
 
+#if MLIR_ENABLE_PDL
 //===----------------------------------------------------------------------===//
 // PDL Configuration
 //===----------------------------------------------------------------------===//
@@ -3382,6 +3383,7 @@ void mlir::registerConversionPDLFunctions(RewritePatternSet &patterns) {
         return std::move(remappedTypes);
       });
 }
+#endif // MLIR_ENABLE_PDL
 
 //===----------------------------------------------------------------------===//
 // Op Conversion Entry Points
diff --git a/mlir/python/CMakeLists.txt b/mlir/python/CMakeLists.txt
index 41d91cf6778338..0ea9104cc0a123 100644
--- a/mlir/python/CMakeLists.txt
+++ b/mlir/python/CMakeLists.txt
@@ -145,14 +145,16 @@ declare_mlir_dialect_python_bindings(
   DIALECT_NAME llvm
   GEN_ENUM_BINDINGS)
 
-declare_mlir_dialect_extension_python_bindings(
-ADD_TO_PARENT MLIRPythonSources.Dialects
-ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/mlir"
-  TD_FILE dialects/TransformPDLExtensionOps.td
-  SOURCES
-    dialects/transform/pdl.py
-  DIALECT_NAME transform
-  EXTENSION_NAME transform_pdl_extension)
+if(MLIR_ENABLE_PDL)
+  declare_mlir_dialect_extension_python_bindings(
+  ADD_TO_PARENT MLIRPythonSources.Dialects
+  ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/mlir"
+    TD_FILE dialects/TransformPDLExtensionOps.td
+    SOURCES
+      dialects/transform/pdl.py
+    DIALECT_NAME transform
+    EXTENSION_NAME transform_pdl_extension)
+endif()
 
 declare_mlir_dialect_python_bindings(
   ADD_TO_PARENT MLIRPythonSources.Dialects
@@ -328,14 +330,16 @@ declare_mlir_python_sources(
     dialects/quant.py
     _mlir_libs/_mlir/dialects/quant.pyi)
 
-declare_mlir_dialect_python_bindings(
-  ADD_TO_PARENT MLIRPythonSources.Dialects
-  ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/mlir"
-  TD_FILE dialects/PDLOps.td
-  SOURCES
-    dialects/pdl.py
-    _mlir_libs/_mlir/dialects/pdl.pyi
-  DIALECT_NAME pdl)
+if(MLIR_ENABLE_PDL)
+  declare_mlir_dialect_python_bindings(
+    ADD_TO_PARENT MLIRPythonSources.Dialects
+    ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/mlir"
+    TD_FILE dialects/PDLOps.td
+    SOURCES
+      dialects/pdl.py
+      _mlir_libs/_mlir/dialects/pdl.pyi
+    DIALECT_NAME pdl)
+endif()
 
 declare_mlir_dialect_python_bindings(
   ADD_TO_PARENT MLIRPythonSources.Dialects
@@ -481,18 +485,20 @@ declare_mlir_python_extension(MLIRPythonExtension.Dialects.Quant.Pybind
     MLIRCAPIQuant
 )
 
-declare_mlir_python_extension(MLIRPythonExtension.Dialects.PDL.Pybind
-  MODULE_NAME _mlirDialectsPDL
-  ADD_TO_PARENT MLIRPythonSources.Dialects.pdl
-  ROOT_DIR "${PYTHON_SOURCE_DIR}"
-  SOURCES
-    DialectPDL.cpp
-  PRIVATE_LINK_LIBS
-    LLVMSupport
-  EMBED_CAPI_LINK_LIBS
-    MLIRCAPIIR
-    MLIRCAPIPDL
-)
+if(MLIR_ENABLE_PDL)
+  declare_mlir_python_extension(MLIRPythonExtension.Dialects.PDL.Pybind
+    MODULE_NAME _mlirDialectsPDL
+    ADD_TO_PARENT MLIRPythonSources.Dialects.pdl
+    ROOT_DIR "${PYTHON_SOURCE_DIR}"
+    SOURCES
+      DialectPDL.cpp
+    PRIVATE_LINK_LIBS
+      LLVMSupport
+    EMBED_CAPI_LINK_LIBS
+      MLIRCAPIIR
+      MLIRCAPIPDL
+  )
+endif()
 
 declare_mlir_python_extension(MLIRPythonExtension.Dialects.SparseTensor.Pybind
   MODULE_NAME _mlirDialectsSparseTensor
diff --git a/mlir/test/CAPI/CMakeLists.txt b/mlir/test/CAPI/CMakeLists.txt
index 1096a3b0806648..e76ad5868c0359 100644
--- a/mlir/test/CAPI/CMakeLists.txt
+++ b/mlir/test/CAPI/CMakeLists.txt
@@ -54,13 +54,15 @@ _add_capi_test_executable(mlir-capi-pass-test
     MLIRCAPITransforms
 )
 
-_add_capi_test_executable(mlir-capi-pdl-test
-  pdl.c
-  LINK_LIBS PRIVATE
-    MLIRCAPIIR
-    MLIRCAPIRegisterEverything
-    MLIRCAPIPDL
-)
+if(MLIR_ENABLE_PDL)
+  _add_capi_test_executable(mlir-capi-pdl-test
+    pdl.c
+    LINK_LIBS PRIVATE
+      MLIRCAPIIR
+      MLIRCAPIRegisterEverything
+      MLIRCAPIPDL
+  )
+endif()
 
 _add_capi_test_executable(mlir-capi-sparse-tensor-test
   sparse_tensor.c
diff --git a/mlir/test/CMakeLists.txt b/mlir/test/CMakeLists.txt
index 3f312164cb1f35..66f2bc7a926cdc 100644
--- a/mlir/test/CMakeLists.txt
+++ b/mlir/test/CMakeLists.txt
@@ -97,16 +97,13 @@ set(MLIR_TEST_DEPENDS
   mlir-capi-ir-test
   mlir-capi-llvm-test
   mlir-capi-pass-test
-  mlir-capi-pdl-test
   mlir-capi-quant-test
   mlir-capi-sparse-tensor-test
   mlir-capi-transform-test
   mlir-capi-translation-test
   mlir-linalg-ods-yaml-gen
   mlir-lsp-server
-  mlir-pdll-lsp-server
   mlir-opt
-  mlir-pdll
   mlir-query
   mlir-reduce
   mlir-tblgen
@@ -115,6 +112,14 @@ set(MLIR_TEST_DEPENDS
   tblgen-to-irdl
   )
 
+if(MLIR_ENABLE_PDL)
+  set(MLIR_TEST_DEPENDS ${MLIR_TEST_DEPENDS}
+    mlir-capi-pdl-test
+    mlir-pdll-lsp-server
+    mlir-pdll
+    )
+endif()
+
 # The native target may not be enabled, in this case we won't
 # run tests that involves executing on the host: do not build
 # useless binaries.
@@ -159,10 +164,13 @@ if(LLVM_BUILD_EXAMPLES)
     toyc-ch3
     toyc-ch4
     toyc-ch5
-    transform-opt-ch2
-    transform-opt-ch3
-    mlir-minimal-opt
     )
+  if(MLIR_ENABLE_PDL)
+    list(APPEND MLIR_TEST_DEPENDS
+      transform-opt-ch2
+      transform-opt-ch3
+      )
+  endif()
   if(MLIR_ENABLE_EXECUTION_ENGINE)
     list(APPEND MLIR_TEST_DEPENDS
       toyc-ch6
diff --git a/mlir/test/lib/Dialect/CMakeLists.txt b/mlir/test/lib/Dialect/CMakeLists.txt
index 30a17c201ff763..f09bcf160f211a 100644
--- a/mlir/test/lib/Dialect/CMakeLists.txt
+++ b/mlir/test/lib/Dialect/CMakeLists.txt
@@ -18,5 +18,8 @@ add_subdirectory(Tensor)
 add_subdirectory(Test)
 add_subdirectory(TestDyn)
 add_subdirectory(Tosa)
-add_subdirectory(Transform)
+if(MLIR_ENABLE_PDL)
+  # Depends on PDL for testing.
+  add_subdirectory(Transform)
+endif()
 add_subdirectory(Vector)
diff --git a/mlir/test/lib/Rewrite/CMakeLists.txt b/mlir/test/lib/Rewrite/CMakeLists.txt
index fd5d5d58616018..e5c73613aaa84a 100644
--- a/mlir/test/lib/Rewrite/CMakeLists.txt
+++ b/mlir/test/lib/Rewrite/CMakeLists.txt
@@ -1,4 +1,5 @@
 # Exclude tests from libMLIR.so
+if(MLIR_ENABLE_PDL)
 add_mlir_library(MLIRTestRewrite
   TestPDLByteCode.cpp
 
@@ -13,4 +14,4 @@ add_mlir_library(MLIRTestRewrite
   MLIRSupport
   MLIRTransformUtils
   )
-
+endif()
diff --git a/mlir/test/lib/Tools/CMakeLists.txt b/mlir/test/lib/Tools/CMakeLists.txt
index 5aa03a3833812e..5b8e02a14b22ee 100644
--- a/mlir/test/lib/Tools/CMakeLists.txt
+++ b/mlir/test/lib/Tools/CMakeLists.txt
@@ -1 +1,3 @@
-add_subdirectory(PDLL)
+if(MLIR_ENABLE_PDL)
+  add_subdirectory(PDLL)
+endif()
diff --git a/mlir/test/lib/Transforms/CMakeLists.txt b/mlir/test/lib/Transforms/CMakeLists.txt
index e032ce7200fbf8..ee7c215a430205 100644
--- a/mlir/test/lib/Transforms/CMakeLists.txt
+++ b/mlir/test/lib/Transforms/CMakeLists.txt
@@ -1,22 +1,32 @@
-add_mlir_pdll_library(MLIRTestDialectConversionPDLLPatternsIncGen
-  TestDialectConversion.pdll
-  TestDialectConversionPDLLPatterns.h.inc
+set(LLVM_OPTIONAL_SOURCES 
+  TestDialectConversion.cpp)
+set(MLIRTestTransformsPDLDep)
+set(MLIRTestTransformsPDLSrc)
+if(MLIR_ENABLE_PDL)
+  add_mlir_pdll_library(MLIRTestDialectConversionPDLLPatternsIncGen
+    TestDialectConversion.pdll
+    TestDialectConversionPDLLPatterns.h.inc
 
-  EXTRA_INCLUDES
-  ${CMAKE_CURRENT_SOURCE_DIR}/../Dialect/Test
-  ${CMAKE_CURRENT_BINARY_DIR}/../Dialect/Test
-  )
+    EXTRA_INCLUDES
+    ${CMAKE_CURRENT_SOURCE_DIR}/../Dialect/Test
+    ${CMAKE_CURRENT_BINARY_DIR}/../Dialect/Test
+    )
+    set(MLIRTestTransformsPDLSrc
+      TestDialectConversion.cpp)
+    set(MLIRTestTransformsPDLDep
+      MLIRTestDialectConversionPDLLPatternsIncGen)
+endif()
 
 # Exclude tests from libMLIR.so
 add_mlir_library(MLIRTestTransforms
   TestCommutativityUtils.cpp
   TestConstantFold.cpp
   TestControlFlowSink.cpp
-  TestDialectConversion.cpp
   TestInlining.cpp
   TestIntRangeInference.cpp
   TestMakeIsolatedFromAbove.cpp
   TestTopologicalSort.cpp
+  ${MLIRTestTransformsPDLSrc}
 
   EXCLUDE_FROM_LIBMLIR
 
@@ -24,7 +34,7 @@ add_mlir_library(MLIRTestTransforms
   ${MLIR_MAIN_INCLUDE_DIR}/mlir/Transforms
 
   DEPENDS
-  MLIRTestDialectConversionPDLLPatternsIncGen
+  ${MLIRTestTransformsPDLDep}
 
   LINK_LIBS PUBLIC
   MLIRAnalysis
diff --git a/mlir/tools/CMakeLists.txt b/mlir/tools/CMakeLists.txt
index 9b474385fdae18..997d601701a25c 100644
--- a/mlir/tools/CMakeLists.txt
+++ b/mlir/tools/CMakeLists.txt
@@ -1,7 +1,9 @@
 add_subdirectory(mlir-lsp-server)
 add_subdirectory(mlir-opt)
 add_subdirectory(mlir-parser-fuzzer)
-add_subdirectory(mlir-pdll-lsp-server)
+if(MLIR_ENABLE_PDL)
+  add_subdirectory(mlir-pdll-lsp-server)
+endif()
 add_subdirectory(mlir-query)
 add_subdirectory(mlir-reduce)
 add_subdirectory(mlir-shlib)
diff --git a/mlir/tools/mlir-lsp-server/CMakeLists.txt b/mlir/tools/mlir-lsp-server/CMakeLists.txt
index e90ccf17af17f5..8b960d7977d341 100644
--- a/mlir/tools/mlir-lsp-server/CMakeLists.txt
+++ b/mlir/tools/mlir-lsp-server/CMakeLists.txt
@@ -21,10 +21,14 @@ if(MLIR_INCLUDE_TESTS)
     MLIRTestIR
     MLIRTestPass
     MLIRTestReducer
-    MLIRTestRewrite
-    MLIRTestTransformDialect
-    MLIRTestTransforms
     )
+  if(MLIR_ENABLE_PDL)
+    set(test_libs
+      ${test_libs}
+      MLIRTestRewrite
+      MLIRTestTransformDialect
+      MLIRTestTransforms)
+  endif()
 endif()
 
 set(LIBS
diff --git a/mlir/tools/mlir-lsp-server/mlir-lsp-server.cpp b/mlir/tools/mlir-lsp-server/mlir-lsp-server.cpp
index f0ecc5adc68b36..4d6b83da05d8b1 100644
--- a/mlir/tools/mlir-lsp-server/mlir-lsp-server.cpp
+++ b/mlir/tools/mlir-lsp-server/mlir-lsp-server.cpp
@@ -18,7 +18,9 @@ using namespace mlir;
 namespace test {
 void registerTestDialect(DialectRegistry &);
 void registerTestDynDialect(DialectRegistry &);
+#if MLIR_ENABLE_PDL
 void registerTestTransformDialectExtension(DialectRegistry &);
+#endif // MLIR_ENABLE_PDL
 } // namespace test
 #endif
 
@@ -29,7 +31,9 @@ int main(int argc, char **argv) {
 
 #ifdef MLIR_INCLUDE_TESTS
   ::test::registerTestDialect(registry);
+#if MLIR_ENABLE_PDL
   ::test::registerTestTransformDialectExtension(registry);
+#endif // MLIR_ENABLE_PDL
   ::test::registerTestDynDialect(registry);
 #endif
   return failed(MlirLspServerMain(argc, argv, registry));
diff --git a/mlir/tools/mlir-opt/CMakeLists.txt b/mlir/tools/mlir-opt/CMakeLists.txt
index b6ada66d321880..3e0acec806cf5c 100644
--- a/mlir/tools/mlir-opt/CMakeLists.txt
+++ b/mlir/tools/mlir-opt/CMakeLists.txt
@@ -38,16 +38,20 @@ if(MLIR_INCLUDE_TESTS)
     MLIRTestIR
     MLIRTestOneToNTypeConversionPass
     MLIRTestPass
-    MLIRTestPDLL
     MLIRTestReducer
-    MLIRTestRewrite
-    MLIRTestTransformDialect
     MLIRTestTransforms
     MLIRTilingInterfaceTestPasses
     MLIRVectorTestPasses
     MLIRTestVectorToSPIRV
     MLIRLLVMTestPasses
     )
+  if(MLIR_ENABLE_PDL)
+    set(test_libs ${test_libs}
+      MLIRTestPDLL
+      MLIRTestRewrite
+      MLIRTestTransformDialect
+      )
+  endif()
 endif()
 
 set(LIBS
diff --git a/mlir/tools/mlir-opt/mlir-opt.cpp b/mlir/tools/mlir-opt/mlir-opt.cpp
index b7c69eabbcd8bf..f425c83e0b43f6 100644
--- a/mlir/tools/mlir-opt/mlir-opt.cpp
+++ b/mlir/tools/mlir-opt/mlir-opt.cpp
@@ -146,8 +146,8 @@ void registerTestNvgpuLowerings();
 
 namespace test {
 void registerTestDialect(DialectRegistry &);
-void registerTestTransformDialectExtension(DialectRegistry &);
 void registerTestDynDialect(DialectRegistry &);
+void registerTestTransformDialectExtension(DialectRegistry &);
 } // namespace test
 
 #ifdef MLIR_INCLUDE_TESTS
@@ -201,7 +201,6 @@ void registerTestPasses() {
   mlir::test::registerTestConstantFold();
   mlir::test::registerTestControlFlowSink();
   mlir::test::registerTestDiagnosticsPass();
-  mlir::test::registerTestDialectConversionPasses();
 #if MLIR_CUDA_CONVERSIONS_ENABLED
   mlir::test::registerTestLowerToNVVM();
 #endif
@@ -244,8 +243,6 @@ void registerTestPasses() {
   mlir::test::registerTestOneToNTypeConversionPass();
   mlir::test::registerTestOpaqueLoc();
   mlir::test::registerTestPadFusion();
-  mlir::test::registerTestPDLByteCodePass();
-  mlir::test::registerTestPDLLPasses();
   mlir::test::registerTestRecursiveTypesPass();
   mlir::test::registerTestSCFUtilsPass();
   mlir::test::registerTestSCFWhileOpBuilderPass();
@@ -255,12 +252,17 @@ void registerTestPasses() {
   mlir::test::registerTestTensorTransforms();
   mlir::test::registerTestTilingInterface();
   mlir::test::registerTestTopologicalSortAnalysisPass();
-  mlir::test::registerTestTransformDialectEraseSchedulePass();
-  mlir::test::registerTestTransformDialectInterpreterPass();
   mlir::test::registerTestVectorLowerings();
   mlir::test::registerTestVectorReductionToSPIRVDotProd();
   mlir::test::registerTestNvgpuLowerings();
   mlir::test::registerTestWrittenToPass();
+#if MLIR_ENABLE_PDL
+  mlir::test::registerTestDialectConversionPasses();
+  mlir::test::registerTestPDLByteCodePass();
+  mlir::test::registerTestPDLLPasses();
+  mlir::test::registerTestTransformDialectEraseSchedulePass();
+  mlir::test::registerTestTransformDialectInterpreterPass();
+#endif
 }
 #endif
 
@@ -284,7 +286,9 @@ int main(int argc, char **argv) {
 
 #ifdef MLIR_INCLUDE_TESTS
   ::test::registerTestDialect(registry);
+#if MLIR_ENABLE_PDL
   ::test::registerTestTransformDialectExtension(registry);
+#endif
   ::test::registerTestDynDialect(registry);
 #endif
   return mlir::asMainReturnCode(mlir::MlirOptMain(
diff --git a/mlir/unittests/Conversion/CMakeLists.txt b/mlir/unittests/Conversion/CMakeLists.txt
index 2dee5e7dac90c4..7ca1ee2c3f2395 100644
--- a/mlir/unittests/Conversion/CMakeLists.txt
+++ b/mlir/unittests/Conversion/CMakeLists.txt
@@ -1 +1,3 @@
-add_subdirectory(PDLToPDLInterp)
+if(MLIR_ENABLE_PDL)
+  add_subdirectory(PDLToPDLInterp)
+endif()
diff --git a/mlir/unittests/Dialect/CMakeLists.txt b/mlir/unittests/Dialect/CMakeLists.txt
index 2dec4ba3c001e8..2e4c8e5c05eb38 100644
--- a/mlir/unittests/Dialect/CMakeLists.txt
+++ b/mlir/unittests/Dialect/CMakeLists.txt
@@ -13,5 +13,7 @@ add_subdirectory(MemRef)
 add_subdirectory(SCF)
 add_subdirectory(SparseTensor)
 add_subdirectory(SPIRV)
-add_subdirectory(Transform)
+if(MLIR_ENABLE_PDL)
+  add_subdirectory(Transform)
+endif()
 add_subdirectory(Utils)
diff --git a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel
index cdb35d87992ed4..e9449ad2f7e45b 100644
--- a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel
@@ -35,6 +35,7 @@ expand_template(
     substitutions = {
         "#cmakedefine01 MLIR_ENABLE_EXPENSIVE_PATTERN_API_CHECKS": "#define MLIR_ENABLE_EXPENSIVE_PATTERN_API_CHECKS 0",
         "#cmakedefine MLIR_GREEDY_REWRITE_RANDOMIZER_SEED ${MLIR_GREEDY_REWRITE_RANDOMIZER_SEED}": "/* #undef MLIR_GREEDY_REWRITE_RANDOMIZER_SEED */",
+        "#cmakedefine MLIR_ENABLE_PDL ${MLIR_ENABLE_PDL}": "#define MLIR_ENABLE_PDLL 1",
     },
     template = "include/mlir/Config/mlir-config.h.cmake",
 )

>From 5c85ffa1de9905f07a35a420282affee6da8fbc5 Mon Sep 17 00:00:00 2001
From: Jacques Pienaar <jpienaar at google.com>
Date: Sat, 9 Dec 2023 16:23:30 -0800
Subject: [PATCH 2/6] Use stubs more to reduce ifdefs

Not sure if this is ideal, seems like it could be more tricky to
maintain. This does also change that the dialect being built vs being
enabled in rewrite are separate (didn't update the flag name yet).
---
 mlir/CMakeLists.txt                           |   8 +-
 mlir/cmake/modules/AddMLIR.cmake              |   3 -
 mlir/examples/CMakeLists.txt                  |   4 +-
 mlir/include/mlir/Config/mlir-config.h.cmake  |   2 +-
 .../Conversion/LLVMCommon/TypeConverter.h     |   1 +
 mlir/include/mlir/Conversion/Passes.td        |   2 -
 mlir/include/mlir/Dialect/CMakeLists.txt      |   6 +-
 .../mlir/Dialect/Transform/CMakeLists.txt     |   4 +-
 .../mlir/Dialect/Vector/IR/VectorOps.h        |   1 +
 mlir/include/mlir/IR/PDLPatternMatch.h.inc    | 992 ++++++++++++++++++
 mlir/include/mlir/IR/PatternMatch.h           | 950 +----------------
 mlir/include/mlir/InitAllDialects.h           |   8 +-
 mlir/include/mlir/InitAllExtensions.h         |   8 +-
 .../mlir/Rewrite/FrozenRewritePatternSet.h    |   6 -
 mlir/include/mlir/Rewrite/PatternApplicator.h |   4 -
 .../mlir/Transforms/DialectConversion.h       |  13 +
 mlir/lib/CAPI/Dialect/CMakeLists.txt          |  18 +-
 mlir/lib/Conversion/CMakeLists.txt            |   4 +-
 mlir/lib/Dialect/Bufferization/CMakeLists.txt |   4 +-
 mlir/lib/Dialect/CMakeLists.txt               |   6 +-
 mlir/lib/Dialect/Transform/CMakeLists.txt     |   4 +-
 mlir/lib/IR/PatternMatch.cpp                  |   1 +
 mlir/lib/Rewrite/ByteCode.cpp                 |   2 +
 mlir/lib/Rewrite/ByteCode.h                   |  35 +
 mlir/lib/Rewrite/CMakeLists.txt               |  21 +-
 mlir/lib/Rewrite/FrozenRewritePatternSet.cpp  |  10 +-
 mlir/lib/Rewrite/PatternApplicator.cpp        |  22 +-
 mlir/lib/Tools/CMakeLists.txt                 |   6 +-
 mlir/python/CMakeLists.txt                    |  24 +-
 mlir/test/CAPI/CMakeLists.txt                 |  16 +-
 mlir/test/CMakeLists.txt                      |  22 +-
 mlir/test/lib/Dialect/CMakeLists.txt          |   5 +-
 mlir/test/lib/Rewrite/CMakeLists.txt          |   2 -
 mlir/test/lib/Tools/CMakeLists.txt            |   4 +-
 mlir/test/lib/Transforms/CMakeLists.txt       |  22 +-
 mlir/tools/CMakeLists.txt                     |   4 +-
 mlir/tools/mlir-lsp-server/CMakeLists.txt     |  12 +-
 .../tools/mlir-lsp-server/mlir-lsp-server.cpp |   4 -
 mlir/tools/mlir-opt/CMakeLists.txt            |  12 +-
 mlir/tools/mlir-opt/mlir-opt.cpp              |   6 +-
 mlir/unittests/Conversion/CMakeLists.txt      |   4 +-
 mlir/unittests/Dialect/CMakeLists.txt         |   4 +-
 .../llvm-project-overlay/mlir/BUILD.bazel     |   2 +-
 43 files changed, 1149 insertions(+), 1139 deletions(-)
 create mode 100644 mlir/include/mlir/IR/PDLPatternMatch.h.inc

diff --git a/mlir/CMakeLists.txt b/mlir/CMakeLists.txt
index 42b9eb3ec7949e..3ff21ed0d5aa81 100644
--- a/mlir/CMakeLists.txt
+++ b/mlir/CMakeLists.txt
@@ -185,11 +185,9 @@ add_subdirectory(tools/mlir-linalg-ods-gen)
 set(MLIR_TABLEGEN_EXE "${MLIR_TABLEGEN_EXE}" CACHE INTERNAL "")
 set(MLIR_TABLEGEN_TARGET "${MLIR_TABLEGEN_TARGET}" CACHE INTERNAL "")
 
-if(MLIR_ENABLE_PDL)
-  add_subdirectory(tools/mlir-pdll)
-  set(MLIR_PDLL_TABLEGEN_EXE "${MLIR_PDLL_TABLEGEN_EXE}" CACHE INTERNAL "")
-  set(MLIR_PDLL_TABLEGEN_TARGET "${MLIR_PDLL_TABLEGEN_TARGET}" CACHE INTERNAL "")
-endif()
+add_subdirectory(tools/mlir-pdll)
+set(MLIR_PDLL_TABLEGEN_EXE "${MLIR_PDLL_TABLEGEN_EXE}" CACHE INTERNAL "")
+set(MLIR_PDLL_TABLEGEN_TARGET "${MLIR_PDLL_TABLEGEN_TARGET}" CACHE INTERNAL "")
 
 add_subdirectory(include/mlir)
 add_subdirectory(lib)
diff --git a/mlir/cmake/modules/AddMLIR.cmake b/mlir/cmake/modules/AddMLIR.cmake
index 2f698f8311df3a..1d2ed748bc2f13 100644
--- a/mlir/cmake/modules/AddMLIR.cmake
+++ b/mlir/cmake/modules/AddMLIR.cmake
@@ -2,9 +2,6 @@ include(GNUInstallDirs)
 include(LLVMDistributionSupport)
 
 function(mlir_tablegen ofn)
-  if (MLIR_ENABLE_PDL)
-    list(APPEND LLVM_TABLEGEN_FLAGS "-DMLIR_ENABLE_PDL")
-  endif()
   tablegen(MLIR ${ARGV})
   set(TABLEGEN_OUTPUT ${TABLEGEN_OUTPUT} ${CMAKE_CURRENT_BINARY_DIR}/${ofn}
       PARENT_SCOPE)
diff --git a/mlir/examples/CMakeLists.txt b/mlir/examples/CMakeLists.txt
index 88a22201c73d9f..d256bf1a5cbb13 100644
--- a/mlir/examples/CMakeLists.txt
+++ b/mlir/examples/CMakeLists.txt
@@ -1,5 +1,3 @@
 add_subdirectory(toy)
-if(MLIR_ENABLE_PDL)
-  add_subdirectory(transform)
-endif()
+add_subdirectory(transform)
 add_subdirectory(minimal-opt)
diff --git a/mlir/include/mlir/Config/mlir-config.h.cmake b/mlir/include/mlir/Config/mlir-config.h.cmake
index a2789b8e2d5867..71e394eeec6133 100644
--- a/mlir/include/mlir/Config/mlir-config.h.cmake
+++ b/mlir/include/mlir/Config/mlir-config.h.cmake
@@ -27,6 +27,6 @@
 #cmakedefine MLIR_GREEDY_REWRITE_RANDOMIZER_SEED ${MLIR_GREEDY_REWRITE_RANDOMIZER_SEED}
 
 /* If set, enables PDL usage. */
-#cmakedefine MLIR_ENABLE_PDL ${MLIR_ENABLE_PDL}
+#cmakedefine01 MLIR_ENABLE_PDL
 
 #endif
diff --git a/mlir/include/mlir/Conversion/LLVMCommon/TypeConverter.h b/mlir/include/mlir/Conversion/LLVMCommon/TypeConverter.h
index 74f9c977b70286..e228229302cff4 100644
--- a/mlir/include/mlir/Conversion/LLVMCommon/TypeConverter.h
+++ b/mlir/include/mlir/Conversion/LLVMCommon/TypeConverter.h
@@ -15,6 +15,7 @@
 #define MLIR_CONVERSION_LLVMCOMMON_TYPECONVERTER_H
 
 #include "mlir/Conversion/LLVMCommon/LoweringOptions.h"
+#include "mlir/IR/BuiltinTypes.h"
 #include "mlir/Transforms/DialectConversion.h"
 
 namespace mlir {
diff --git a/mlir/include/mlir/Conversion/Passes.td b/mlir/include/mlir/Conversion/Passes.td
index 5ef7aeb2514b7d..6193aeb545bc6b 100644
--- a/mlir/include/mlir/Conversion/Passes.td
+++ b/mlir/include/mlir/Conversion/Passes.td
@@ -831,7 +831,6 @@ def ConvertOpenMPToLLVMPass : Pass<"convert-openmp-to-llvm", "ModuleOp"> {
   let dependentDialects = ["LLVM::LLVMDialect"];
 }
 
-#ifdef MLIR_ENABLE_PDL
 //===----------------------------------------------------------------------===//
 // PDLToPDLInterp
 //===----------------------------------------------------------------------===//
@@ -841,7 +840,6 @@ def ConvertPDLToPDLInterp : Pass<"convert-pdl-to-pdl-interp", "ModuleOp"> {
   let constructor = "mlir::createPDLToPDLInterpPass()";
   let dependentDialects = ["pdl_interp::PDLInterpDialect"];
 }
-#endif
 
 //===----------------------------------------------------------------------===//
 // ReconcileUnrealizedCasts
diff --git a/mlir/include/mlir/Dialect/CMakeLists.txt b/mlir/include/mlir/Dialect/CMakeLists.txt
index c2dd7a9dcfd9c7..1c4569ecfa5848 100644
--- a/mlir/include/mlir/Dialect/CMakeLists.txt
+++ b/mlir/include/mlir/Dialect/CMakeLists.txt
@@ -25,10 +25,8 @@ add_subdirectory(NVGPU)
 add_subdirectory(OpenACC)
 add_subdirectory(OpenACCMPCommon)
 add_subdirectory(OpenMP)
-if (MLIR_ENABLE_PDL)
-  add_subdirectory(PDL)
-  add_subdirectory(PDLInterp)
-endif()
+add_subdirectory(PDL)
+add_subdirectory(PDLInterp)
 add_subdirectory(Quant)
 add_subdirectory(SCF)
 add_subdirectory(Shape)
diff --git a/mlir/include/mlir/Dialect/Transform/CMakeLists.txt b/mlir/include/mlir/Dialect/Transform/CMakeLists.txt
index 3e6b222c208f25..d6c5c975c2e93c 100644
--- a/mlir/include/mlir/Dialect/Transform/CMakeLists.txt
+++ b/mlir/include/mlir/Dialect/Transform/CMakeLists.txt
@@ -1,6 +1,4 @@
 add_subdirectory(IR)
 add_subdirectory(LoopExtension)
-if (MLIR_ENABLE_PDL)
-  add_subdirectory(PDLExtension)
-endif()
+add_subdirectory(PDLExtension)
 add_subdirectory(Transforms)
diff --git a/mlir/include/mlir/Dialect/Vector/IR/VectorOps.h b/mlir/include/mlir/Dialect/Vector/IR/VectorOps.h
index 59d585a77b1e29..9dfbd0ff31ecea 100644
--- a/mlir/include/mlir/Dialect/Vector/IR/VectorOps.h
+++ b/mlir/include/mlir/Dialect/Vector/IR/VectorOps.h
@@ -29,6 +29,7 @@
 #include "mlir/Interfaces/SideEffectInterfaces.h"
 #include "mlir/Interfaces/VectorInterfaces.h"
 #include "mlir/Interfaces/ViewLikeInterface.h"
+#include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/StringExtras.h"
 
 // Pull in all enum type definitions and utility function declarations.
diff --git a/mlir/include/mlir/IR/PDLPatternMatch.h.inc b/mlir/include/mlir/IR/PDLPatternMatch.h.inc
new file mode 100644
index 00000000000000..e4d63248bf1908
--- /dev/null
+++ b/mlir/include/mlir/IR/PDLPatternMatch.h.inc
@@ -0,0 +1,992 @@
+//===- PDLPatternMatch.h - PDLPatternMatcher classes -------==---*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_IR_PDLPATTERNMATCH_H
+#define MLIR_IR_PDLPATTERNMATCH_H
+
+#if MLIR_ENABLE_PDL
+#include "mlir/IR/Builders.h"
+#include "mlir/IR/BuiltinOps.h"
+
+namespace mlir {
+//===----------------------------------------------------------------------===//
+// PDL Patterns
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// PDLValue
+
+/// Storage type of byte-code interpreter values. These are passed to constraint
+/// functions as arguments.
+class PDLValue {
+public:
+  /// The underlying kind of a PDL value.
+  enum class Kind { Attribute, Operation, Type, TypeRange, Value, ValueRange };
+
+  /// Construct a new PDL value.
+  PDLValue(const PDLValue &other) = default;
+  PDLValue(std::nullptr_t = nullptr) {}
+  PDLValue(Attribute value)
+      : value(value.getAsOpaquePointer()), kind(Kind::Attribute) {}
+  PDLValue(Operation *value) : value(value), kind(Kind::Operation) {}
+  PDLValue(Type value) : value(value.getAsOpaquePointer()), kind(Kind::Type) {}
+  PDLValue(TypeRange *value) : value(value), kind(Kind::TypeRange) {}
+  PDLValue(Value value)
+      : value(value.getAsOpaquePointer()), kind(Kind::Value) {}
+  PDLValue(ValueRange *value) : value(value), kind(Kind::ValueRange) {}
+
+  /// Returns true if the type of the held value is `T`.
+  template <typename T>
+  bool isa() const {
+    assert(value && "isa<> used on a null value");
+    return kind == getKindOf<T>();
+  }
+
+  /// Attempt to dynamically cast this value to type `T`, returns null if this
+  /// value is not an instance of `T`.
+  template <typename T,
+            typename ResultT = std::conditional_t<
+                std::is_convertible<T, bool>::value, T, std::optional<T>>>
+  ResultT dyn_cast() const {
+    return isa<T>() ? castImpl<T>() : ResultT();
+  }
+
+  /// Cast this value to type `T`, asserts if this value is not an instance of
+  /// `T`.
+  template <typename T>
+  T cast() const {
+    assert(isa<T>() && "expected value to be of type `T`");
+    return castImpl<T>();
+  }
+
+  /// Get an opaque pointer to the value.
+  const void *getAsOpaquePointer() const { return value; }
+
+  /// Return if this value is null or not.
+  explicit operator bool() const { return value; }
+
+  /// Return the kind of this value.
+  Kind getKind() const { return kind; }
+
+  /// Print this value to the provided output stream.
+  void print(raw_ostream &os) const;
+
+  /// Print the specified value kind to an output stream.
+  static void print(raw_ostream &os, Kind kind);
+
+private:
+  /// Find the index of a given type in a range of other types.
+  template <typename...>
+  struct index_of_t;
+  template <typename T, typename... R>
+  struct index_of_t<T, T, R...> : std::integral_constant<size_t, 0> {};
+  template <typename T, typename F, typename... R>
+  struct index_of_t<T, F, R...>
+      : std::integral_constant<size_t, 1 + index_of_t<T, R...>::value> {};
+
+  /// Return the kind used for the given T.
+  template <typename T>
+  static Kind getKindOf() {
+    return static_cast<Kind>(index_of_t<T, Attribute, Operation *, Type,
+                                        TypeRange, Value, ValueRange>::value);
+  }
+
+  /// The internal implementation of `cast`, that returns the underlying value
+  /// as the given type `T`.
+  template <typename T>
+  std::enable_if_t<llvm::is_one_of<T, Attribute, Type, Value>::value, T>
+  castImpl() const {
+    return T::getFromOpaquePointer(value);
+  }
+  template <typename T>
+  std::enable_if_t<llvm::is_one_of<T, TypeRange, ValueRange>::value, T>
+  castImpl() const {
+    return *reinterpret_cast<T *>(const_cast<void *>(value));
+  }
+  template <typename T>
+  std::enable_if_t<std::is_pointer<T>::value, T> castImpl() const {
+    return reinterpret_cast<T>(const_cast<void *>(value));
+  }
+
+  /// The internal opaque representation of a PDLValue.
+  const void *value{nullptr};
+  /// The kind of the opaque value.
+  Kind kind{Kind::Attribute};
+};
+
+inline raw_ostream &operator<<(raw_ostream &os, PDLValue value) {
+  value.print(os);
+  return os;
+}
+
+inline raw_ostream &operator<<(raw_ostream &os, PDLValue::Kind kind) {
+  PDLValue::print(os, kind);
+  return os;
+}
+
+//===----------------------------------------------------------------------===//
+// PDLResultList
+
+/// The class represents a list of PDL results, returned by a native rewrite
+/// method. It provides the mechanism with which to pass PDLValues back to the
+/// PDL bytecode.
+class PDLResultList {
+public:
+  /// Push a new Attribute value onto the result list.
+  void push_back(Attribute value) { results.push_back(value); }
+
+  /// Push a new Operation onto the result list.
+  void push_back(Operation *value) { results.push_back(value); }
+
+  /// Push a new Type onto the result list.
+  void push_back(Type value) { results.push_back(value); }
+
+  /// Push a new TypeRange onto the result list.
+  void push_back(TypeRange value) {
+    // The lifetime of a TypeRange can't be guaranteed, so we'll need to
+    // allocate a storage for it.
+    llvm::OwningArrayRef<Type> storage(value.size());
+    llvm::copy(value, storage.begin());
+    allocatedTypeRanges.emplace_back(std::move(storage));
+    typeRanges.push_back(allocatedTypeRanges.back());
+    results.push_back(&typeRanges.back());
+  }
+  void push_back(ValueTypeRange<OperandRange> value) {
+    typeRanges.push_back(value);
+    results.push_back(&typeRanges.back());
+  }
+  void push_back(ValueTypeRange<ResultRange> value) {
+    typeRanges.push_back(value);
+    results.push_back(&typeRanges.back());
+  }
+
+  /// Push a new Value onto the result list.
+  void push_back(Value value) { results.push_back(value); }
+
+  /// Push a new ValueRange onto the result list.
+  void push_back(ValueRange value) {
+    // The lifetime of a ValueRange can't be guaranteed, so we'll need to
+    // allocate a storage for it.
+    llvm::OwningArrayRef<Value> storage(value.size());
+    llvm::copy(value, storage.begin());
+    allocatedValueRanges.emplace_back(std::move(storage));
+    valueRanges.push_back(allocatedValueRanges.back());
+    results.push_back(&valueRanges.back());
+  }
+  void push_back(OperandRange value) {
+    valueRanges.push_back(value);
+    results.push_back(&valueRanges.back());
+  }
+  void push_back(ResultRange value) {
+    valueRanges.push_back(value);
+    results.push_back(&valueRanges.back());
+  }
+
+protected:
+  /// Create a new result list with the expected number of results.
+  PDLResultList(unsigned maxNumResults) {
+    // For now just reserve enough space for all of the results. We could do
+    // separate counts per range type, but it isn't really worth it unless there
+    // are a "large" number of results.
+    typeRanges.reserve(maxNumResults);
+    valueRanges.reserve(maxNumResults);
+  }
+
+  /// The PDL results held by this list.
+  SmallVector<PDLValue> results;
+  /// Memory used to store ranges held by the list.
+  SmallVector<TypeRange> typeRanges;
+  SmallVector<ValueRange> valueRanges;
+  /// Memory allocated to store ranges in the result list whose lifetime was
+  /// generated in the native function.
+  SmallVector<llvm::OwningArrayRef<Type>> allocatedTypeRanges;
+  SmallVector<llvm::OwningArrayRef<Value>> allocatedValueRanges;
+};
+
+//===----------------------------------------------------------------------===//
+// PDLPatternConfig
+
+/// An individual configuration for a pattern, which can be accessed by native
+/// functions via the PDLPatternConfigSet. This allows for injecting additional
+/// configuration into PDL patterns that is specific to certain compilation
+/// flows.
+class PDLPatternConfig {
+public:
+  virtual ~PDLPatternConfig() = default;
+
+  /// Hooks that are invoked at the beginning and end of a rewrite of a matched
+  /// pattern. These can be used to setup any specific state necessary for the
+  /// rewrite.
+  virtual void notifyRewriteBegin(PatternRewriter &rewriter) {}
+  virtual void notifyRewriteEnd(PatternRewriter &rewriter) {}
+
+  /// Return the TypeID that represents this configuration.
+  TypeID getTypeID() const { return id; }
+
+protected:
+  PDLPatternConfig(TypeID id) : id(id) {}
+
+private:
+  TypeID id;
+};
+
+/// This class provides a base class for users implementing a type of pattern
+/// configuration.
+template <typename T>
+class PDLPatternConfigBase : public PDLPatternConfig {
+public:
+  /// Support LLVM style casting.
+  static bool classof(const PDLPatternConfig *config) {
+    return config->getTypeID() == getConfigID();
+  }
+
+  /// Return the type id used for this configuration.
+  static TypeID getConfigID() { return TypeID::get<T>(); }
+
+protected:
+  PDLPatternConfigBase() : PDLPatternConfig(getConfigID()) {}
+};
+
+/// This class contains a set of configurations for a specific pattern.
+/// Configurations are uniqued by TypeID, meaning that only one configuration of
+/// each type is allowed.
+class PDLPatternConfigSet {
+public:
+  PDLPatternConfigSet() = default;
+
+  /// Construct a set with the given configurations.
+  template <typename... ConfigsT>
+  PDLPatternConfigSet(ConfigsT &&...configs) {
+    (addConfig(std::forward<ConfigsT>(configs)), ...);
+  }
+
+  /// Get the configuration defined by the given type. Asserts that the
+  /// configuration of the provided type exists.
+  template <typename T>
+  const T &get() const {
+    const T *config = tryGet<T>();
+    assert(config && "configuration not found");
+    return *config;
+  }
+
+  /// Get the configuration defined by the given type, returns nullptr if the
+  /// configuration does not exist.
+  template <typename T>
+  const T *tryGet() const {
+    for (const auto &configIt : configs)
+      if (const T *config = dyn_cast<T>(configIt.get()))
+        return config;
+    return nullptr;
+  }
+
+  /// Notify the configurations within this set at the beginning or end of a
+  /// rewrite of a matched pattern.
+  void notifyRewriteBegin(PatternRewriter &rewriter) {
+    for (const auto &config : configs)
+      config->notifyRewriteBegin(rewriter);
+  }
+  void notifyRewriteEnd(PatternRewriter &rewriter) {
+    for (const auto &config : configs)
+      config->notifyRewriteEnd(rewriter);
+  }
+
+protected:
+  /// Add a configuration to the set.
+  template <typename T>
+  void addConfig(T &&config) {
+    assert(!tryGet<std::decay_t<T>>() && "configuration already exists");
+    configs.emplace_back(
+        std::make_unique<std::decay_t<T>>(std::forward<T>(config)));
+  }
+
+  /// The set of configurations for this pattern. This uses a vector instead of
+  /// a map with the expectation that the number of configurations per set is
+  /// small (<= 1).
+  SmallVector<std::unique_ptr<PDLPatternConfig>> configs;
+};
+
+//===----------------------------------------------------------------------===//
+// PDLPatternModule
+
+/// A generic PDL pattern constraint function. This function applies a
+/// constraint to a given set of opaque PDLValue entities. Returns success if
+/// the constraint successfully held, failure otherwise.
+using PDLConstraintFunction =
+    std::function<LogicalResult(PatternRewriter &, ArrayRef<PDLValue>)>;
+/// A native PDL rewrite function. This function performs a rewrite on the
+/// given set of values. Any results from this rewrite that should be passed
+/// back to PDL should be added to the provided result list. This method is only
+/// invoked when the corresponding match was successful. Returns failure if an
+/// invariant of the rewrite was broken (certain rewriters may recover from
+/// partial pattern application).
+using PDLRewriteFunction = std::function<LogicalResult(
+    PatternRewriter &, PDLResultList &, ArrayRef<PDLValue>)>;
+
+namespace detail {
+namespace pdl_function_builder {
+/// A utility variable that always resolves to false. This is useful for static
+/// asserts that are always false, but only should fire in certain templated
+/// constructs. For example, if a templated function should never be called, the
+/// function could be defined as:
+///
+/// template <typename T>
+/// void foo() {
+///  static_assert(always_false<T>, "This function should never be called");
+/// }
+///
+template <class... T>
+constexpr bool always_false = false;
+
+//===----------------------------------------------------------------------===//
+// PDL Function Builder: Type Processing
+//===----------------------------------------------------------------------===//
+
+/// This struct provides a convenient way to determine how to process a given
+/// type as either a PDL parameter, or a result value. This allows for
+/// supporting complex types in constraint and rewrite functions, without
+/// requiring the user to hand-write the necessary glue code themselves.
+/// Specializations of this class should implement the following methods to
+/// enable support as a PDL argument or result type:
+///
+///   static LogicalResult verifyAsArg(
+///     function_ref<LogicalResult(const Twine &)> errorFn, PDLValue pdlValue,
+///     size_t argIdx);
+///
+///     * This method verifies that the given PDLValue is valid for use as a
+///       value of `T`.
+///
+///   static T processAsArg(PDLValue pdlValue);
+///
+///     *  This method processes the given PDLValue as a value of `T`.
+///
+///   static void processAsResult(PatternRewriter &, PDLResultList &results,
+///                               const T &value);
+///
+///     *  This method processes the given value of `T` as the result of a
+///        function invocation. The method should package the value into an
+///        appropriate form and append it to the given result list.
+///
+/// If the type `T` is based on a higher order value, consider using
+/// `ProcessPDLValueBasedOn` as a base class of the specialization to simplify
+/// the implementation.
+///
+template <typename T, typename Enable = void>
+struct ProcessPDLValue;
+
+/// This struct provides a simplified model for processing types that are based
+/// on another type, e.g. APInt is based on the handling for IntegerAttr. This
+/// allows for building the necessary processing functions on top of the base
+/// value instead of a PDLValue. Derived users should implement the following
+/// (which subsume the ProcessPDLValue variants):
+///
+///   static LogicalResult verifyAsArg(
+///     function_ref<LogicalResult(const Twine &)> errorFn,
+///     const BaseT &baseValue, size_t argIdx);
+///
+///     * This method verifies that the given PDLValue is valid for use as a
+///       value of `T`.
+///
+///   static T processAsArg(BaseT baseValue);
+///
+///     *  This method processes the given base value as a value of `T`.
+///
+template <typename T, typename BaseT>
+struct ProcessPDLValueBasedOn {
+  static LogicalResult
+  verifyAsArg(function_ref<LogicalResult(const Twine &)> errorFn,
+              PDLValue pdlValue, size_t argIdx) {
+    // Verify the base class before continuing.
+    if (failed(ProcessPDLValue<BaseT>::verifyAsArg(errorFn, pdlValue, argIdx)))
+      return failure();
+    return ProcessPDLValue<T>::verifyAsArg(
+        errorFn, ProcessPDLValue<BaseT>::processAsArg(pdlValue), argIdx);
+  }
+  static T processAsArg(PDLValue pdlValue) {
+    return ProcessPDLValue<T>::processAsArg(
+        ProcessPDLValue<BaseT>::processAsArg(pdlValue));
+  }
+
+  /// Explicitly add the expected parent API to ensure the parent class
+  /// implements the necessary API (and doesn't implicitly inherit it from
+  /// somewhere else).
+  static LogicalResult
+  verifyAsArg(function_ref<LogicalResult(const Twine &)> errorFn, BaseT value,
+              size_t argIdx) {
+    return success();
+  }
+  static T processAsArg(BaseT baseValue);
+};
+
+/// This struct provides a simplified model for processing types that have
+/// "builtin" PDLValue support:
+///   * Attribute, Operation *, Type, TypeRange, ValueRange
+template <typename T>
+struct ProcessBuiltinPDLValue {
+  static LogicalResult
+  verifyAsArg(function_ref<LogicalResult(const Twine &)> errorFn,
+              PDLValue pdlValue, size_t argIdx) {
+    if (pdlValue)
+      return success();
+    return errorFn("expected a non-null value for argument " + Twine(argIdx) +
+                   " of type: " + llvm::getTypeName<T>());
+  }
+
+  static T processAsArg(PDLValue pdlValue) { return pdlValue.cast<T>(); }
+  static void processAsResult(PatternRewriter &, PDLResultList &results,
+                              T value) {
+    results.push_back(value);
+  }
+};
+
+/// This struct provides a simplified model for processing types that inherit
+/// from builtin PDLValue types. For example, derived attributes like
+/// IntegerAttr, derived types like IntegerType, derived operations like
+/// ModuleOp, Interfaces, etc.
+template <typename T, typename BaseT>
+struct ProcessDerivedPDLValue : public ProcessPDLValueBasedOn<T, BaseT> {
+  static LogicalResult
+  verifyAsArg(function_ref<LogicalResult(const Twine &)> errorFn,
+              BaseT baseValue, size_t argIdx) {
+    return TypeSwitch<BaseT, LogicalResult>(baseValue)
+        .Case([&](T) { return success(); })
+        .Default([&](BaseT) {
+          return errorFn("expected argument " + Twine(argIdx) +
+                         " to be of type: " + llvm::getTypeName<T>());
+        });
+  }
+  using ProcessPDLValueBasedOn<T, BaseT>::verifyAsArg;
+
+  static T processAsArg(BaseT baseValue) {
+    return baseValue.template cast<T>();
+  }
+  using ProcessPDLValueBasedOn<T, BaseT>::processAsArg;
+
+  static void processAsResult(PatternRewriter &, PDLResultList &results,
+                              T value) {
+    results.push_back(value);
+  }
+};
+
+//===----------------------------------------------------------------------===//
+// Attribute
+
+template <>
+struct ProcessPDLValue<Attribute> : public ProcessBuiltinPDLValue<Attribute> {};
+template <typename T>
+struct ProcessPDLValue<T,
+                       std::enable_if_t<std::is_base_of<Attribute, T>::value>>
+    : public ProcessDerivedPDLValue<T, Attribute> {};
+
+/// Handling for various Attribute value types.
+template <>
+struct ProcessPDLValue<StringRef>
+    : public ProcessPDLValueBasedOn<StringRef, StringAttr> {
+  static StringRef processAsArg(StringAttr value) { return value.getValue(); }
+  using ProcessPDLValueBasedOn<StringRef, StringAttr>::processAsArg;
+
+  static void processAsResult(PatternRewriter &rewriter, PDLResultList &results,
+                              StringRef value) {
+    results.push_back(rewriter.getStringAttr(value));
+  }
+};
+template <>
+struct ProcessPDLValue<std::string>
+    : public ProcessPDLValueBasedOn<std::string, StringAttr> {
+  template <typename T>
+  static std::string processAsArg(T value) {
+    static_assert(always_false<T>,
+                  "`std::string` arguments require a string copy, use "
+                  "`StringRef` for string-like arguments instead");
+    return {};
+  }
+  static void processAsResult(PatternRewriter &rewriter, PDLResultList &results,
+                              StringRef value) {
+    results.push_back(rewriter.getStringAttr(value));
+  }
+};
+
+//===----------------------------------------------------------------------===//
+// Operation
+
+template <>
+struct ProcessPDLValue<Operation *>
+    : public ProcessBuiltinPDLValue<Operation *> {};
+template <typename T>
+struct ProcessPDLValue<T, std::enable_if_t<std::is_base_of<OpState, T>::value>>
+    : public ProcessDerivedPDLValue<T, Operation *> {
+  static T processAsArg(Operation *value) { return cast<T>(value); }
+};
+
+//===----------------------------------------------------------------------===//
+// Type
+
+template <>
+struct ProcessPDLValue<Type> : public ProcessBuiltinPDLValue<Type> {};
+template <typename T>
+struct ProcessPDLValue<T, std::enable_if_t<std::is_base_of<Type, T>::value>>
+    : public ProcessDerivedPDLValue<T, Type> {};
+
+//===----------------------------------------------------------------------===//
+// TypeRange
+
+template <>
+struct ProcessPDLValue<TypeRange> : public ProcessBuiltinPDLValue<TypeRange> {};
+template <>
+struct ProcessPDLValue<ValueTypeRange<OperandRange>> {
+  static void processAsResult(PatternRewriter &, PDLResultList &results,
+                              ValueTypeRange<OperandRange> types) {
+    results.push_back(types);
+  }
+};
+template <>
+struct ProcessPDLValue<ValueTypeRange<ResultRange>> {
+  static void processAsResult(PatternRewriter &, PDLResultList &results,
+                              ValueTypeRange<ResultRange> types) {
+    results.push_back(types);
+  }
+};
+template <unsigned N>
+struct ProcessPDLValue<SmallVector<Type, N>> {
+  static void processAsResult(PatternRewriter &, PDLResultList &results,
+                              SmallVector<Type, N> values) {
+    results.push_back(TypeRange(values));
+  }
+};
+
+//===----------------------------------------------------------------------===//
+// Value
+
+template <>
+struct ProcessPDLValue<Value> : public ProcessBuiltinPDLValue<Value> {};
+
+//===----------------------------------------------------------------------===//
+// ValueRange
+
+template <>
+struct ProcessPDLValue<ValueRange> : public ProcessBuiltinPDLValue<ValueRange> {
+};
+template <>
+struct ProcessPDLValue<OperandRange> {
+  static void processAsResult(PatternRewriter &, PDLResultList &results,
+                              OperandRange values) {
+    results.push_back(values);
+  }
+};
+template <>
+struct ProcessPDLValue<ResultRange> {
+  static void processAsResult(PatternRewriter &, PDLResultList &results,
+                              ResultRange values) {
+    results.push_back(values);
+  }
+};
+template <unsigned N>
+struct ProcessPDLValue<SmallVector<Value, N>> {
+  static void processAsResult(PatternRewriter &, PDLResultList &results,
+                              SmallVector<Value, N> values) {
+    results.push_back(ValueRange(values));
+  }
+};
+
+//===----------------------------------------------------------------------===//
+// PDL Function Builder: Argument Handling
+//===----------------------------------------------------------------------===//
+
+/// Validate the given PDLValues match the constraints defined by the argument
+/// types of the given function. In the case of failure, a match failure
+/// diagnostic is emitted.
+/// FIXME: This should be completely removed in favor of `assertArgs`, but PDL
+/// does not currently preserve Constraint application ordering.
+template <typename PDLFnT, std::size_t... I>
+LogicalResult verifyAsArgs(PatternRewriter &rewriter, ArrayRef<PDLValue> values,
+                           std::index_sequence<I...>) {
+  using FnTraitsT = llvm::function_traits<PDLFnT>;
+
+  auto errorFn = [&](const Twine &msg) {
+    return rewriter.notifyMatchFailure(rewriter.getUnknownLoc(), msg);
+  };
+  return success(
+      (succeeded(ProcessPDLValue<typename FnTraitsT::template arg_t<I + 1>>::
+                     verifyAsArg(errorFn, values[I], I)) &&
+       ...));
+}
+
+/// Assert that the given PDLValues match the constraints defined by the
+/// arguments of the given function. In the case of failure, a fatal error
+/// is emitted.
+template <typename PDLFnT, std::size_t... I>
+void assertArgs(PatternRewriter &rewriter, ArrayRef<PDLValue> values,
+                std::index_sequence<I...>) {
+  // We only want to do verification in debug builds, same as with `assert`.
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS
+  using FnTraitsT = llvm::function_traits<PDLFnT>;
+  auto errorFn = [&](const Twine &msg) -> LogicalResult {
+    llvm::report_fatal_error(msg);
+  };
+  (void)errorFn;
+  assert((succeeded(ProcessPDLValue<typename FnTraitsT::template arg_t<I + 1>>::
+                        verifyAsArg(errorFn, values[I], I)) &&
+          ...));
+#endif
+  (void)values;
+}
+
+//===----------------------------------------------------------------------===//
+// PDL Function Builder: Results Handling
+//===----------------------------------------------------------------------===//
+
+/// Store a single result within the result list.
+template <typename T>
+static LogicalResult processResults(PatternRewriter &rewriter,
+                                    PDLResultList &results, T &&value) {
+  ProcessPDLValue<T>::processAsResult(rewriter, results,
+                                      std::forward<T>(value));
+  return success();
+}
+
+/// Store a std::pair<> as individual results within the result list.
+template <typename T1, typename T2>
+static LogicalResult processResults(PatternRewriter &rewriter,
+                                    PDLResultList &results,
+                                    std::pair<T1, T2> &&pair) {
+  if (failed(processResults(rewriter, results, std::move(pair.first))) ||
+      failed(processResults(rewriter, results, std::move(pair.second))))
+    return failure();
+  return success();
+}
+
+/// Store a std::tuple<> as individual results within the result list.
+template <typename... Ts>
+static LogicalResult processResults(PatternRewriter &rewriter,
+                                    PDLResultList &results,
+                                    std::tuple<Ts...> &&tuple) {
+  auto applyFn = [&](auto &&...args) {
+    return (succeeded(processResults(rewriter, results, std::move(args))) &&
+            ...);
+  };
+  return success(std::apply(applyFn, std::move(tuple)));
+}
+
+/// Handle LogicalResult propagation.
+inline LogicalResult processResults(PatternRewriter &rewriter,
+                                    PDLResultList &results,
+                                    LogicalResult &&result) {
+  return result;
+}
+template <typename T>
+static LogicalResult processResults(PatternRewriter &rewriter,
+                                    PDLResultList &results,
+                                    FailureOr<T> &&result) {
+  if (failed(result))
+    return failure();
+  return processResults(rewriter, results, std::move(*result));
+}
+
+//===----------------------------------------------------------------------===//
+// PDL Constraint Builder
+//===----------------------------------------------------------------------===//
+
+/// Process the arguments of a native constraint and invoke it.
+template <typename PDLFnT, std::size_t... I,
+          typename FnTraitsT = llvm::function_traits<PDLFnT>>
+typename FnTraitsT::result_t
+processArgsAndInvokeConstraint(PDLFnT &fn, PatternRewriter &rewriter,
+                               ArrayRef<PDLValue> values,
+                               std::index_sequence<I...>) {
+  return fn(
+      rewriter,
+      (ProcessPDLValue<typename FnTraitsT::template arg_t<I + 1>>::processAsArg(
+          values[I]))...);
+}
+
+/// Build a constraint function from the given function `ConstraintFnT`. This
+/// allows for enabling the user to define simpler, more direct constraint
+/// functions without needing to handle the low-level PDL goop.
+///
+/// If the constraint function is already in the correct form, we just forward
+/// it directly.
+template <typename ConstraintFnT>
+std::enable_if_t<
+    std::is_convertible<ConstraintFnT, PDLConstraintFunction>::value,
+    PDLConstraintFunction>
+buildConstraintFn(ConstraintFnT &&constraintFn) {
+  return std::forward<ConstraintFnT>(constraintFn);
+}
+/// Otherwise, we generate a wrapper that will unpack the PDLValues in the form
+/// we desire.
+template <typename ConstraintFnT>
+std::enable_if_t<
+    !std::is_convertible<ConstraintFnT, PDLConstraintFunction>::value,
+    PDLConstraintFunction>
+buildConstraintFn(ConstraintFnT &&constraintFn) {
+  return [constraintFn = std::forward<ConstraintFnT>(constraintFn)](
+             PatternRewriter &rewriter,
+             ArrayRef<PDLValue> values) -> LogicalResult {
+    auto argIndices = std::make_index_sequence<
+        llvm::function_traits<ConstraintFnT>::num_args - 1>();
+    if (failed(verifyAsArgs<ConstraintFnT>(rewriter, values, argIndices)))
+      return failure();
+    return processArgsAndInvokeConstraint(constraintFn, rewriter, values,
+                                          argIndices);
+  };
+}
+
+//===----------------------------------------------------------------------===//
+// PDL Rewrite Builder
+//===----------------------------------------------------------------------===//
+
+/// Process the arguments of a native rewrite and invoke it.
+/// This overload handles the case of no return values.
+template <typename PDLFnT, std::size_t... I,
+          typename FnTraitsT = llvm::function_traits<PDLFnT>>
+std::enable_if_t<std::is_same<typename FnTraitsT::result_t, void>::value,
+                 LogicalResult>
+processArgsAndInvokeRewrite(PDLFnT &fn, PatternRewriter &rewriter,
+                            PDLResultList &, ArrayRef<PDLValue> values,
+                            std::index_sequence<I...>) {
+  fn(rewriter,
+     (ProcessPDLValue<typename FnTraitsT::template arg_t<I + 1>>::processAsArg(
+         values[I]))...);
+  return success();
+}
+/// This overload handles the case of return values, which need to be packaged
+/// into the result list.
+template <typename PDLFnT, std::size_t... I,
+          typename FnTraitsT = llvm::function_traits<PDLFnT>>
+std::enable_if_t<!std::is_same<typename FnTraitsT::result_t, void>::value,
+                 LogicalResult>
+processArgsAndInvokeRewrite(PDLFnT &fn, PatternRewriter &rewriter,
+                            PDLResultList &results, ArrayRef<PDLValue> values,
+                            std::index_sequence<I...>) {
+  return processResults(
+      rewriter, results,
+      fn(rewriter, (ProcessPDLValue<typename FnTraitsT::template arg_t<I + 1>>::
+                        processAsArg(values[I]))...));
+  (void)values;
+}
+
+/// Build a rewrite function from the given function `RewriteFnT`. This
+/// allows for enabling the user to define simpler, more direct rewrite
+/// functions without needing to handle the low-level PDL goop.
+///
+/// If the rewrite function is already in the correct form, we just forward
+/// it directly.
+template <typename RewriteFnT>
+std::enable_if_t<std::is_convertible<RewriteFnT, PDLRewriteFunction>::value,
+                 PDLRewriteFunction>
+buildRewriteFn(RewriteFnT &&rewriteFn) {
+  return std::forward<RewriteFnT>(rewriteFn);
+}
+/// Otherwise, we generate a wrapper that will unpack the PDLValues in the form
+/// we desire.
+template <typename RewriteFnT>
+std::enable_if_t<!std::is_convertible<RewriteFnT, PDLRewriteFunction>::value,
+                 PDLRewriteFunction>
+buildRewriteFn(RewriteFnT &&rewriteFn) {
+  return [rewriteFn = std::forward<RewriteFnT>(rewriteFn)](
+             PatternRewriter &rewriter, PDLResultList &results,
+             ArrayRef<PDLValue> values) {
+    auto argIndices =
+        std::make_index_sequence<llvm::function_traits<RewriteFnT>::num_args -
+                                 1>();
+    assertArgs<RewriteFnT>(rewriter, values, argIndices);
+    return processArgsAndInvokeRewrite(rewriteFn, rewriter, results, values,
+                                       argIndices);
+  };
+}
+
+} // namespace pdl_function_builder
+} // namespace detail
+
+//===----------------------------------------------------------------------===//
+// PDLPatternModule
+
+/// This class contains all of the necessary data for a set of PDL patterns, or
+/// pattern rewrites specified in the form of the PDL dialect. This PDL module
+/// contained by this pattern may contain any number of `pdl.pattern`
+/// operations.
+class PDLPatternModule {
+public:
+  PDLPatternModule() = default;
+
+  /// Construct a PDL pattern with the given module and configurations.
+  PDLPatternModule(OwningOpRef<ModuleOp> module)
+      : pdlModule(std::move(module)) {}
+  template <typename... ConfigsT>
+  PDLPatternModule(OwningOpRef<ModuleOp> module, ConfigsT &&...patternConfigs)
+      : PDLPatternModule(std::move(module)) {
+    auto configSet = std::make_unique<PDLPatternConfigSet>(
+        std::forward<ConfigsT>(patternConfigs)...);
+    attachConfigToPatterns(*pdlModule, *configSet);
+    configs.emplace_back(std::move(configSet));
+  }
+
+  /// Merge the state in `other` into this pattern module.
+  void mergeIn(PDLPatternModule &&other);
+
+  /// Return the internal PDL module of this pattern.
+  ModuleOp getModule() { return pdlModule.get(); }
+
+  /// Return the MLIR context of this pattern.
+  MLIRContext *getContext() { return getModule()->getContext(); }
+
+  //===--------------------------------------------------------------------===//
+  // Function Registry
+
+  /// Register a constraint function with PDL. A constraint function may be
+  /// specified in one of two ways:
+  ///
+  ///   * `LogicalResult (PatternRewriter &, ArrayRef<PDLValue>)`
+  ///
+  ///   In this overload the arguments of the constraint function are passed via
+  ///   the low-level PDLValue form.
+  ///
+  ///   * `LogicalResult (PatternRewriter &, ValueTs... values)`
+  ///
+  ///   In this form the arguments of the constraint function are passed via the
+  ///   expected high level C++ type. In this form, the framework will
+  ///   automatically unwrap PDLValues and convert them to the expected ValueTs.
+  ///   For example, if the constraint function accepts a `Operation *`, the
+  ///   framework will automatically cast the input PDLValue. In the case of a
+  ///   `StringRef`, the framework will automatically unwrap the argument as a
+  ///   StringAttr and pass the underlying string value. To see the full list of
+  ///   supported types, or to see how to add handling for custom types, view
+  ///   the definition of `ProcessPDLValue` above.
+  void registerConstraintFunction(StringRef name,
+                                  PDLConstraintFunction constraintFn);
+  template <typename ConstraintFnT>
+  void registerConstraintFunction(StringRef name,
+                                  ConstraintFnT &&constraintFn) {
+    registerConstraintFunction(name,
+                               detail::pdl_function_builder::buildConstraintFn(
+                                   std::forward<ConstraintFnT>(constraintFn)));
+  }
+
+  /// Register a rewrite function with PDL. A rewrite function may be specified
+  /// in one of two ways:
+  ///
+  ///   * `void (PatternRewriter &, PDLResultList &, ArrayRef<PDLValue>)`
+  ///
+  ///   In this overload the arguments of the constraint function are passed via
+  ///   the low-level PDLValue form, and the results are manually appended to
+  ///   the given result list.
+  ///
+  ///   * `ResultT (PatternRewriter &, ValueTs... values)`
+  ///
+  ///   In this form the arguments and result of the rewrite function are passed
+  ///   via the expected high level C++ type. In this form, the framework will
+  ///   automatically unwrap the PDLValues arguments and convert them to the
+  ///   expected ValueTs. It will also automatically handle the processing and
+  ///   packaging of the result value to the result list. For example, if the
+  ///   rewrite function takes a `Operation *`, the framework will automatically
+  ///   cast the input PDLValue. In the case of a `StringRef`, the framework
+  ///   will automatically unwrap the argument as a StringAttr and pass the
+  ///   underlying string value. In the reverse case, if the rewrite returns a
+  ///   StringRef or std::string, it will automatically package this as a
+  ///   StringAttr and append it to the result list. To see the full list of
+  ///   supported types, or to see how to add handling for custom types, view
+  ///   the definition of `ProcessPDLValue` above.
+  void registerRewriteFunction(StringRef name, PDLRewriteFunction rewriteFn);
+  template <typename RewriteFnT>
+  void registerRewriteFunction(StringRef name, RewriteFnT &&rewriteFn) {
+    registerRewriteFunction(name, detail::pdl_function_builder::buildRewriteFn(
+                                      std::forward<RewriteFnT>(rewriteFn)));
+  }
+
+  /// Return the set of the registered constraint functions.
+  const llvm::StringMap<PDLConstraintFunction> &getConstraintFunctions() const {
+    return constraintFunctions;
+  }
+  llvm::StringMap<PDLConstraintFunction> takeConstraintFunctions() {
+    return constraintFunctions;
+  }
+  /// Return the set of the registered rewrite functions.
+  const llvm::StringMap<PDLRewriteFunction> &getRewriteFunctions() const {
+    return rewriteFunctions;
+  }
+  llvm::StringMap<PDLRewriteFunction> takeRewriteFunctions() {
+    return rewriteFunctions;
+  }
+
+  /// Return the set of the registered pattern configs.
+  SmallVector<std::unique_ptr<PDLPatternConfigSet>> takeConfigs() {
+    return std::move(configs);
+  }
+  DenseMap<Operation *, PDLPatternConfigSet *> takeConfigMap() {
+    return std::move(configMap);
+  }
+
+  /// Clear out the patterns and functions within this module.
+  void clear() {
+    pdlModule = nullptr;
+    constraintFunctions.clear();
+    rewriteFunctions.clear();
+  }
+
+private:
+  /// Attach the given pattern config set to the patterns defined within the
+  /// given module.
+  void attachConfigToPatterns(ModuleOp module, PDLPatternConfigSet &configSet);
+
+  /// The module containing the `pdl.pattern` operations.
+  OwningOpRef<ModuleOp> pdlModule;
+
+  /// The set of configuration sets referenced by patterns within `pdlModule`.
+  SmallVector<std::unique_ptr<PDLPatternConfigSet>> configs;
+  DenseMap<Operation *, PDLPatternConfigSet *> configMap;
+
+  /// The external functions referenced from within the PDL module.
+  llvm::StringMap<PDLConstraintFunction> constraintFunctions;
+  llvm::StringMap<PDLRewriteFunction> rewriteFunctions;
+};
+} // namespace mlir
+#else
+
+namespace mlir {
+// Stubs for when PDL in pattern rewrites is not enabled.
+
+class PDLValue {
+public:
+  template <typename T>
+  T dyn_cast() const {
+    return nullptr;
+  }
+};
+class PDLResultList {};
+using PDLConstraintFunction =
+    std::function<LogicalResult(PatternRewriter &, ArrayRef<PDLValue>)>;
+using PDLRewriteFunction = std::function<LogicalResult(
+    PatternRewriter &, PDLResultList &, ArrayRef<PDLValue>)>;
+
+class PDLPatternModule {
+public:
+  PDLPatternModule() = default;
+
+  PDLPatternModule(OwningOpRef<ModuleOp> /*module*/) {}
+  MLIRContext *getContext() {
+    llvm_unreachable("Error: PDL for rewrites when PDL is not enabled");
+  }
+  void mergeIn(PDLPatternModule &&other) {}
+  void clear() {}
+  template <typename ConstraintFnT>
+  void registerConstraintFunction(StringRef name,
+                                  ConstraintFnT &&constraintFn) {}
+  void registerRewriteFunction(StringRef name, PDLRewriteFunction rewriteFn) {}
+  template <typename RewriteFnT>
+  void registerRewriteFunction(StringRef name, RewriteFnT &&rewriteFn) {}
+  const llvm::StringMap<PDLConstraintFunction> &getConstraintFunctions() const {
+    return constraintFunctions;
+  }
+
+private:
+  llvm::StringMap<PDLConstraintFunction> constraintFunctions;
+};
+
+} // namespace mlir
+#endif
+
+#endif // MLIR_IR_PDLPATTERNMATCH_H
diff --git a/mlir/include/mlir/IR/PatternMatch.h b/mlir/include/mlir/IR/PatternMatch.h
index 060f8f5f602b99..46f49e8acffcdd 100644
--- a/mlir/include/mlir/IR/PatternMatch.h
+++ b/mlir/include/mlir/IR/PatternMatch.h
@@ -736,934 +736,12 @@ class PatternRewriter : public RewriterBase {
   virtual bool canRecoverFromRewriteFailure() const { return false; }
 };
 
-#if MLIR_ENABLE_PDL
-//===----------------------------------------------------------------------===//
-// PDL Patterns
-//===----------------------------------------------------------------------===//
-
-//===----------------------------------------------------------------------===//
-// PDLValue
-
-/// Storage type of byte-code interpreter values. These are passed to constraint
-/// functions as arguments.
-class PDLValue {
-public:
-  /// The underlying kind of a PDL value.
-  enum class Kind { Attribute, Operation, Type, TypeRange, Value, ValueRange };
-
-  /// Construct a new PDL value.
-  PDLValue(const PDLValue &other) = default;
-  PDLValue(std::nullptr_t = nullptr) {}
-  PDLValue(Attribute value)
-      : value(value.getAsOpaquePointer()), kind(Kind::Attribute) {}
-  PDLValue(Operation *value) : value(value), kind(Kind::Operation) {}
-  PDLValue(Type value) : value(value.getAsOpaquePointer()), kind(Kind::Type) {}
-  PDLValue(TypeRange *value) : value(value), kind(Kind::TypeRange) {}
-  PDLValue(Value value)
-      : value(value.getAsOpaquePointer()), kind(Kind::Value) {}
-  PDLValue(ValueRange *value) : value(value), kind(Kind::ValueRange) {}
-
-  /// Returns true if the type of the held value is `T`.
-  template <typename T>
-  bool isa() const {
-    assert(value && "isa<> used on a null value");
-    return kind == getKindOf<T>();
-  }
-
-  /// Attempt to dynamically cast this value to type `T`, returns null if this
-  /// value is not an instance of `T`.
-  template <typename T,
-            typename ResultT = std::conditional_t<
-                std::is_convertible<T, bool>::value, T, std::optional<T>>>
-  ResultT dyn_cast() const {
-    return isa<T>() ? castImpl<T>() : ResultT();
-  }
-
-  /// Cast this value to type `T`, asserts if this value is not an instance of
-  /// `T`.
-  template <typename T>
-  T cast() const {
-    assert(isa<T>() && "expected value to be of type `T`");
-    return castImpl<T>();
-  }
-
-  /// Get an opaque pointer to the value.
-  const void *getAsOpaquePointer() const { return value; }
-
-  /// Return if this value is null or not.
-  explicit operator bool() const { return value; }
-
-  /// Return the kind of this value.
-  Kind getKind() const { return kind; }
-
-  /// Print this value to the provided output stream.
-  void print(raw_ostream &os) const;
-
-  /// Print the specified value kind to an output stream.
-  static void print(raw_ostream &os, Kind kind);
-
-private:
-  /// Find the index of a given type in a range of other types.
-  template <typename...>
-  struct index_of_t;
-  template <typename T, typename... R>
-  struct index_of_t<T, T, R...> : std::integral_constant<size_t, 0> {};
-  template <typename T, typename F, typename... R>
-  struct index_of_t<T, F, R...>
-      : std::integral_constant<size_t, 1 + index_of_t<T, R...>::value> {};
-
-  /// Return the kind used for the given T.
-  template <typename T>
-  static Kind getKindOf() {
-    return static_cast<Kind>(index_of_t<T, Attribute, Operation *, Type,
-                                        TypeRange, Value, ValueRange>::value);
-  }
-
-  /// The internal implementation of `cast`, that returns the underlying value
-  /// as the given type `T`.
-  template <typename T>
-  std::enable_if_t<llvm::is_one_of<T, Attribute, Type, Value>::value, T>
-  castImpl() const {
-    return T::getFromOpaquePointer(value);
-  }
-  template <typename T>
-  std::enable_if_t<llvm::is_one_of<T, TypeRange, ValueRange>::value, T>
-  castImpl() const {
-    return *reinterpret_cast<T *>(const_cast<void *>(value));
-  }
-  template <typename T>
-  std::enable_if_t<std::is_pointer<T>::value, T> castImpl() const {
-    return reinterpret_cast<T>(const_cast<void *>(value));
-  }
-
-  /// The internal opaque representation of a PDLValue.
-  const void *value{nullptr};
-  /// The kind of the opaque value.
-  Kind kind{Kind::Attribute};
-};
-
-inline raw_ostream &operator<<(raw_ostream &os, PDLValue value) {
-  value.print(os);
-  return os;
-}
-
-inline raw_ostream &operator<<(raw_ostream &os, PDLValue::Kind kind) {
-  PDLValue::print(os, kind);
-  return os;
-}
-
-//===----------------------------------------------------------------------===//
-// PDLResultList
-
-/// The class represents a list of PDL results, returned by a native rewrite
-/// method. It provides the mechanism with which to pass PDLValues back to the
-/// PDL bytecode.
-class PDLResultList {
-public:
-  /// Push a new Attribute value onto the result list.
-  void push_back(Attribute value) { results.push_back(value); }
-
-  /// Push a new Operation onto the result list.
-  void push_back(Operation *value) { results.push_back(value); }
-
-  /// Push a new Type onto the result list.
-  void push_back(Type value) { results.push_back(value); }
-
-  /// Push a new TypeRange onto the result list.
-  void push_back(TypeRange value) {
-    // The lifetime of a TypeRange can't be guaranteed, so we'll need to
-    // allocate a storage for it.
-    llvm::OwningArrayRef<Type> storage(value.size());
-    llvm::copy(value, storage.begin());
-    allocatedTypeRanges.emplace_back(std::move(storage));
-    typeRanges.push_back(allocatedTypeRanges.back());
-    results.push_back(&typeRanges.back());
-  }
-  void push_back(ValueTypeRange<OperandRange> value) {
-    typeRanges.push_back(value);
-    results.push_back(&typeRanges.back());
-  }
-  void push_back(ValueTypeRange<ResultRange> value) {
-    typeRanges.push_back(value);
-    results.push_back(&typeRanges.back());
-  }
-
-  /// Push a new Value onto the result list.
-  void push_back(Value value) { results.push_back(value); }
-
-  /// Push a new ValueRange onto the result list.
-  void push_back(ValueRange value) {
-    // The lifetime of a ValueRange can't be guaranteed, so we'll need to
-    // allocate a storage for it.
-    llvm::OwningArrayRef<Value> storage(value.size());
-    llvm::copy(value, storage.begin());
-    allocatedValueRanges.emplace_back(std::move(storage));
-    valueRanges.push_back(allocatedValueRanges.back());
-    results.push_back(&valueRanges.back());
-  }
-  void push_back(OperandRange value) {
-    valueRanges.push_back(value);
-    results.push_back(&valueRanges.back());
-  }
-  void push_back(ResultRange value) {
-    valueRanges.push_back(value);
-    results.push_back(&valueRanges.back());
-  }
-
-protected:
-  /// Create a new result list with the expected number of results.
-  PDLResultList(unsigned maxNumResults) {
-    // For now just reserve enough space for all of the results. We could do
-    // separate counts per range type, but it isn't really worth it unless there
-    // are a "large" number of results.
-    typeRanges.reserve(maxNumResults);
-    valueRanges.reserve(maxNumResults);
-  }
-
-  /// The PDL results held by this list.
-  SmallVector<PDLValue> results;
-  /// Memory used to store ranges held by the list.
-  SmallVector<TypeRange> typeRanges;
-  SmallVector<ValueRange> valueRanges;
-  /// Memory allocated to store ranges in the result list whose lifetime was
-  /// generated in the native function.
-  SmallVector<llvm::OwningArrayRef<Type>> allocatedTypeRanges;
-  SmallVector<llvm::OwningArrayRef<Value>> allocatedValueRanges;
-};
-
-//===----------------------------------------------------------------------===//
-// PDLPatternConfig
-
-/// An individual configuration for a pattern, which can be accessed by native
-/// functions via the PDLPatternConfigSet. This allows for injecting additional
-/// configuration into PDL patterns that is specific to certain compilation
-/// flows.
-class PDLPatternConfig {
-public:
-  virtual ~PDLPatternConfig() = default;
-
-  /// Hooks that are invoked at the beginning and end of a rewrite of a matched
-  /// pattern. These can be used to setup any specific state necessary for the
-  /// rewrite.
-  virtual void notifyRewriteBegin(PatternRewriter &rewriter) {}
-  virtual void notifyRewriteEnd(PatternRewriter &rewriter) {}
-
-  /// Return the TypeID that represents this configuration.
-  TypeID getTypeID() const { return id; }
-
-protected:
-  PDLPatternConfig(TypeID id) : id(id) {}
-
-private:
-  TypeID id;
-};
-
-/// This class provides a base class for users implementing a type of pattern
-/// configuration.
-template <typename T>
-class PDLPatternConfigBase : public PDLPatternConfig {
-public:
-  /// Support LLVM style casting.
-  static bool classof(const PDLPatternConfig *config) {
-    return config->getTypeID() == getConfigID();
-  }
-
-  /// Return the type id used for this configuration.
-  static TypeID getConfigID() { return TypeID::get<T>(); }
-
-protected:
-  PDLPatternConfigBase() : PDLPatternConfig(getConfigID()) {}
-};
-
-/// This class contains a set of configurations for a specific pattern.
-/// Configurations are uniqued by TypeID, meaning that only one configuration of
-/// each type is allowed.
-class PDLPatternConfigSet {
-public:
-  PDLPatternConfigSet() = default;
-
-  /// Construct a set with the given configurations.
-  template <typename... ConfigsT>
-  PDLPatternConfigSet(ConfigsT &&...configs) {
-    (addConfig(std::forward<ConfigsT>(configs)), ...);
-  }
-
-  /// Get the configuration defined by the given type. Asserts that the
-  /// configuration of the provided type exists.
-  template <typename T>
-  const T &get() const {
-    const T *config = tryGet<T>();
-    assert(config && "configuration not found");
-    return *config;
-  }
-
-  /// Get the configuration defined by the given type, returns nullptr if the
-  /// configuration does not exist.
-  template <typename T>
-  const T *tryGet() const {
-    for (const auto &configIt : configs)
-      if (const T *config = dyn_cast<T>(configIt.get()))
-        return config;
-    return nullptr;
-  }
-
-  /// Notify the configurations within this set at the beginning or end of a
-  /// rewrite of a matched pattern.
-  void notifyRewriteBegin(PatternRewriter &rewriter) {
-    for (const auto &config : configs)
-      config->notifyRewriteBegin(rewriter);
-  }
-  void notifyRewriteEnd(PatternRewriter &rewriter) {
-    for (const auto &config : configs)
-      config->notifyRewriteEnd(rewriter);
-  }
-
-protected:
-  /// Add a configuration to the set.
-  template <typename T>
-  void addConfig(T &&config) {
-    assert(!tryGet<std::decay_t<T>>() && "configuration already exists");
-    configs.emplace_back(
-        std::make_unique<std::decay_t<T>>(std::forward<T>(config)));
-  }
-
-  /// The set of configurations for this pattern. This uses a vector instead of
-  /// a map with the expectation that the number of configurations per set is
-  /// small (<= 1).
-  SmallVector<std::unique_ptr<PDLPatternConfig>> configs;
-};
-
-//===----------------------------------------------------------------------===//
-// PDLPatternModule
-
-/// A generic PDL pattern constraint function. This function applies a
-/// constraint to a given set of opaque PDLValue entities. Returns success if
-/// the constraint successfully held, failure otherwise.
-using PDLConstraintFunction =
-    std::function<LogicalResult(PatternRewriter &, ArrayRef<PDLValue>)>;
-/// A native PDL rewrite function. This function performs a rewrite on the
-/// given set of values. Any results from this rewrite that should be passed
-/// back to PDL should be added to the provided result list. This method is only
-/// invoked when the corresponding match was successful. Returns failure if an
-/// invariant of the rewrite was broken (certain rewriters may recover from
-/// partial pattern application).
-using PDLRewriteFunction = std::function<LogicalResult(
-    PatternRewriter &, PDLResultList &, ArrayRef<PDLValue>)>;
-
-namespace detail {
-namespace pdl_function_builder {
-/// A utility variable that always resolves to false. This is useful for static
-/// asserts that are always false, but only should fire in certain templated
-/// constructs. For example, if a templated function should never be called, the
-/// function could be defined as:
-///
-/// template <typename T>
-/// void foo() {
-///  static_assert(always_false<T>, "This function should never be called");
-/// }
-///
-template <class... T>
-constexpr bool always_false = false;
-
-//===----------------------------------------------------------------------===//
-// PDL Function Builder: Type Processing
-//===----------------------------------------------------------------------===//
-
-/// This struct provides a convenient way to determine how to process a given
-/// type as either a PDL parameter, or a result value. This allows for
-/// supporting complex types in constraint and rewrite functions, without
-/// requiring the user to hand-write the necessary glue code themselves.
-/// Specializations of this class should implement the following methods to
-/// enable support as a PDL argument or result type:
-///
-///   static LogicalResult verifyAsArg(
-///     function_ref<LogicalResult(const Twine &)> errorFn, PDLValue pdlValue,
-///     size_t argIdx);
-///
-///     * This method verifies that the given PDLValue is valid for use as a
-///       value of `T`.
-///
-///   static T processAsArg(PDLValue pdlValue);
-///
-///     *  This method processes the given PDLValue as a value of `T`.
-///
-///   static void processAsResult(PatternRewriter &, PDLResultList &results,
-///                               const T &value);
-///
-///     *  This method processes the given value of `T` as the result of a
-///        function invocation. The method should package the value into an
-///        appropriate form and append it to the given result list.
-///
-/// If the type `T` is based on a higher order value, consider using
-/// `ProcessPDLValueBasedOn` as a base class of the specialization to simplify
-/// the implementation.
-///
-template <typename T, typename Enable = void>
-struct ProcessPDLValue;
-
-/// This struct provides a simplified model for processing types that are based
-/// on another type, e.g. APInt is based on the handling for IntegerAttr. This
-/// allows for building the necessary processing functions on top of the base
-/// value instead of a PDLValue. Derived users should implement the following
-/// (which subsume the ProcessPDLValue variants):
-///
-///   static LogicalResult verifyAsArg(
-///     function_ref<LogicalResult(const Twine &)> errorFn,
-///     const BaseT &baseValue, size_t argIdx);
-///
-///     * This method verifies that the given PDLValue is valid for use as a
-///       value of `T`.
-///
-///   static T processAsArg(BaseT baseValue);
-///
-///     *  This method processes the given base value as a value of `T`.
-///
-template <typename T, typename BaseT>
-struct ProcessPDLValueBasedOn {
-  static LogicalResult
-  verifyAsArg(function_ref<LogicalResult(const Twine &)> errorFn,
-              PDLValue pdlValue, size_t argIdx) {
-    // Verify the base class before continuing.
-    if (failed(ProcessPDLValue<BaseT>::verifyAsArg(errorFn, pdlValue, argIdx)))
-      return failure();
-    return ProcessPDLValue<T>::verifyAsArg(
-        errorFn, ProcessPDLValue<BaseT>::processAsArg(pdlValue), argIdx);
-  }
-  static T processAsArg(PDLValue pdlValue) {
-    return ProcessPDLValue<T>::processAsArg(
-        ProcessPDLValue<BaseT>::processAsArg(pdlValue));
-  }
-
-  /// Explicitly add the expected parent API to ensure the parent class
-  /// implements the necessary API (and doesn't implicitly inherit it from
-  /// somewhere else).
-  static LogicalResult
-  verifyAsArg(function_ref<LogicalResult(const Twine &)> errorFn, BaseT value,
-              size_t argIdx) {
-    return success();
-  }
-  static T processAsArg(BaseT baseValue);
-};
-
-/// This struct provides a simplified model for processing types that have
-/// "builtin" PDLValue support:
-///   * Attribute, Operation *, Type, TypeRange, ValueRange
-template <typename T>
-struct ProcessBuiltinPDLValue {
-  static LogicalResult
-  verifyAsArg(function_ref<LogicalResult(const Twine &)> errorFn,
-              PDLValue pdlValue, size_t argIdx) {
-    if (pdlValue)
-      return success();
-    return errorFn("expected a non-null value for argument " + Twine(argIdx) +
-                   " of type: " + llvm::getTypeName<T>());
-  }
-
-  static T processAsArg(PDLValue pdlValue) { return pdlValue.cast<T>(); }
-  static void processAsResult(PatternRewriter &, PDLResultList &results,
-                              T value) {
-    results.push_back(value);
-  }
-};
-
-/// This struct provides a simplified model for processing types that inherit
-/// from builtin PDLValue types. For example, derived attributes like
-/// IntegerAttr, derived types like IntegerType, derived operations like
-/// ModuleOp, Interfaces, etc.
-template <typename T, typename BaseT>
-struct ProcessDerivedPDLValue : public ProcessPDLValueBasedOn<T, BaseT> {
-  static LogicalResult
-  verifyAsArg(function_ref<LogicalResult(const Twine &)> errorFn,
-              BaseT baseValue, size_t argIdx) {
-    return TypeSwitch<BaseT, LogicalResult>(baseValue)
-        .Case([&](T) { return success(); })
-        .Default([&](BaseT) {
-          return errorFn("expected argument " + Twine(argIdx) +
-                         " to be of type: " + llvm::getTypeName<T>());
-        });
-  }
-  using ProcessPDLValueBasedOn<T, BaseT>::verifyAsArg;
-
-  static T processAsArg(BaseT baseValue) {
-    return baseValue.template cast<T>();
-  }
-  using ProcessPDLValueBasedOn<T, BaseT>::processAsArg;
-
-  static void processAsResult(PatternRewriter &, PDLResultList &results,
-                              T value) {
-    results.push_back(value);
-  }
-};
-
-//===----------------------------------------------------------------------===//
-// Attribute
-
-template <>
-struct ProcessPDLValue<Attribute> : public ProcessBuiltinPDLValue<Attribute> {};
-template <typename T>
-struct ProcessPDLValue<T,
-                       std::enable_if_t<std::is_base_of<Attribute, T>::value>>
-    : public ProcessDerivedPDLValue<T, Attribute> {};
-
-/// Handling for various Attribute value types.
-template <>
-struct ProcessPDLValue<StringRef>
-    : public ProcessPDLValueBasedOn<StringRef, StringAttr> {
-  static StringRef processAsArg(StringAttr value) { return value.getValue(); }
-  using ProcessPDLValueBasedOn<StringRef, StringAttr>::processAsArg;
-
-  static void processAsResult(PatternRewriter &rewriter, PDLResultList &results,
-                              StringRef value) {
-    results.push_back(rewriter.getStringAttr(value));
-  }
-};
-template <>
-struct ProcessPDLValue<std::string>
-    : public ProcessPDLValueBasedOn<std::string, StringAttr> {
-  template <typename T>
-  static std::string processAsArg(T value) {
-    static_assert(always_false<T>,
-                  "`std::string` arguments require a string copy, use "
-                  "`StringRef` for string-like arguments instead");
-    return {};
-  }
-  static void processAsResult(PatternRewriter &rewriter, PDLResultList &results,
-                              StringRef value) {
-    results.push_back(rewriter.getStringAttr(value));
-  }
-};
-
-//===----------------------------------------------------------------------===//
-// Operation
-
-template <>
-struct ProcessPDLValue<Operation *>
-    : public ProcessBuiltinPDLValue<Operation *> {};
-template <typename T>
-struct ProcessPDLValue<T, std::enable_if_t<std::is_base_of<OpState, T>::value>>
-    : public ProcessDerivedPDLValue<T, Operation *> {
-  static T processAsArg(Operation *value) { return cast<T>(value); }
-};
-
-//===----------------------------------------------------------------------===//
-// Type
-
-template <>
-struct ProcessPDLValue<Type> : public ProcessBuiltinPDLValue<Type> {};
-template <typename T>
-struct ProcessPDLValue<T, std::enable_if_t<std::is_base_of<Type, T>::value>>
-    : public ProcessDerivedPDLValue<T, Type> {};
-
-//===----------------------------------------------------------------------===//
-// TypeRange
-
-template <>
-struct ProcessPDLValue<TypeRange> : public ProcessBuiltinPDLValue<TypeRange> {};
-template <>
-struct ProcessPDLValue<ValueTypeRange<OperandRange>> {
-  static void processAsResult(PatternRewriter &, PDLResultList &results,
-                              ValueTypeRange<OperandRange> types) {
-    results.push_back(types);
-  }
-};
-template <>
-struct ProcessPDLValue<ValueTypeRange<ResultRange>> {
-  static void processAsResult(PatternRewriter &, PDLResultList &results,
-                              ValueTypeRange<ResultRange> types) {
-    results.push_back(types);
-  }
-};
-template <unsigned N>
-struct ProcessPDLValue<SmallVector<Type, N>> {
-  static void processAsResult(PatternRewriter &, PDLResultList &results,
-                              SmallVector<Type, N> values) {
-    results.push_back(TypeRange(values));
-  }
-};
-
-//===----------------------------------------------------------------------===//
-// Value
-
-template <>
-struct ProcessPDLValue<Value> : public ProcessBuiltinPDLValue<Value> {};
-
-//===----------------------------------------------------------------------===//
-// ValueRange
-
-template <>
-struct ProcessPDLValue<ValueRange> : public ProcessBuiltinPDLValue<ValueRange> {
-};
-template <>
-struct ProcessPDLValue<OperandRange> {
-  static void processAsResult(PatternRewriter &, PDLResultList &results,
-                              OperandRange values) {
-    results.push_back(values);
-  }
-};
-template <>
-struct ProcessPDLValue<ResultRange> {
-  static void processAsResult(PatternRewriter &, PDLResultList &results,
-                              ResultRange values) {
-    results.push_back(values);
-  }
-};
-template <unsigned N>
-struct ProcessPDLValue<SmallVector<Value, N>> {
-  static void processAsResult(PatternRewriter &, PDLResultList &results,
-                              SmallVector<Value, N> values) {
-    results.push_back(ValueRange(values));
-  }
-};
-
-//===----------------------------------------------------------------------===//
-// PDL Function Builder: Argument Handling
-//===----------------------------------------------------------------------===//
-
-/// Validate the given PDLValues match the constraints defined by the argument
-/// types of the given function. In the case of failure, a match failure
-/// diagnostic is emitted.
-/// FIXME: This should be completely removed in favor of `assertArgs`, but PDL
-/// does not currently preserve Constraint application ordering.
-template <typename PDLFnT, std::size_t... I>
-LogicalResult verifyAsArgs(PatternRewriter &rewriter, ArrayRef<PDLValue> values,
-                           std::index_sequence<I...>) {
-  using FnTraitsT = llvm::function_traits<PDLFnT>;
-
-  auto errorFn = [&](const Twine &msg) {
-    return rewriter.notifyMatchFailure(rewriter.getUnknownLoc(), msg);
-  };
-  return success(
-      (succeeded(ProcessPDLValue<typename FnTraitsT::template arg_t<I + 1>>::
-                     verifyAsArg(errorFn, values[I], I)) &&
-       ...));
-}
-
-/// Assert that the given PDLValues match the constraints defined by the
-/// arguments of the given function. In the case of failure, a fatal error
-/// is emitted.
-template <typename PDLFnT, std::size_t... I>
-void assertArgs(PatternRewriter &rewriter, ArrayRef<PDLValue> values,
-                std::index_sequence<I...>) {
-  // We only want to do verification in debug builds, same as with `assert`.
-#if LLVM_ENABLE_ABI_BREAKING_CHECKS
-  using FnTraitsT = llvm::function_traits<PDLFnT>;
-  auto errorFn = [&](const Twine &msg) -> LogicalResult {
-    llvm::report_fatal_error(msg);
-  };
-  (void)errorFn;
-  assert((succeeded(ProcessPDLValue<typename FnTraitsT::template arg_t<I + 1>>::
-                        verifyAsArg(errorFn, values[I], I)) &&
-          ...));
-#endif
-  (void)values;
-}
-
-//===----------------------------------------------------------------------===//
-// PDL Function Builder: Results Handling
-//===----------------------------------------------------------------------===//
-
-/// Store a single result within the result list.
-template <typename T>
-static LogicalResult processResults(PatternRewriter &rewriter,
-                                    PDLResultList &results, T &&value) {
-  ProcessPDLValue<T>::processAsResult(rewriter, results,
-                                      std::forward<T>(value));
-  return success();
-}
-
-/// Store a std::pair<> as individual results within the result list.
-template <typename T1, typename T2>
-static LogicalResult processResults(PatternRewriter &rewriter,
-                                    PDLResultList &results,
-                                    std::pair<T1, T2> &&pair) {
-  if (failed(processResults(rewriter, results, std::move(pair.first))) ||
-      failed(processResults(rewriter, results, std::move(pair.second))))
-    return failure();
-  return success();
-}
-
-/// Store a std::tuple<> as individual results within the result list.
-template <typename... Ts>
-static LogicalResult processResults(PatternRewriter &rewriter,
-                                    PDLResultList &results,
-                                    std::tuple<Ts...> &&tuple) {
-  auto applyFn = [&](auto &&...args) {
-    return (succeeded(processResults(rewriter, results, std::move(args))) &&
-            ...);
-  };
-  return success(std::apply(applyFn, std::move(tuple)));
-}
-
-/// Handle LogicalResult propagation.
-inline LogicalResult processResults(PatternRewriter &rewriter,
-                                    PDLResultList &results,
-                                    LogicalResult &&result) {
-  return result;
-}
-template <typename T>
-static LogicalResult processResults(PatternRewriter &rewriter,
-                                    PDLResultList &results,
-                                    FailureOr<T> &&result) {
-  if (failed(result))
-    return failure();
-  return processResults(rewriter, results, std::move(*result));
-}
-
-//===----------------------------------------------------------------------===//
-// PDL Constraint Builder
-//===----------------------------------------------------------------------===//
-
-/// Process the arguments of a native constraint and invoke it.
-template <typename PDLFnT, std::size_t... I,
-          typename FnTraitsT = llvm::function_traits<PDLFnT>>
-typename FnTraitsT::result_t
-processArgsAndInvokeConstraint(PDLFnT &fn, PatternRewriter &rewriter,
-                               ArrayRef<PDLValue> values,
-                               std::index_sequence<I...>) {
-  return fn(
-      rewriter,
-      (ProcessPDLValue<typename FnTraitsT::template arg_t<I + 1>>::processAsArg(
-          values[I]))...);
-}
-
-/// Build a constraint function from the given function `ConstraintFnT`. This
-/// allows for enabling the user to define simpler, more direct constraint
-/// functions without needing to handle the low-level PDL goop.
-///
-/// If the constraint function is already in the correct form, we just forward
-/// it directly.
-template <typename ConstraintFnT>
-std::enable_if_t<
-    std::is_convertible<ConstraintFnT, PDLConstraintFunction>::value,
-    PDLConstraintFunction>
-buildConstraintFn(ConstraintFnT &&constraintFn) {
-  return std::forward<ConstraintFnT>(constraintFn);
-}
-/// Otherwise, we generate a wrapper that will unpack the PDLValues in the form
-/// we desire.
-template <typename ConstraintFnT>
-std::enable_if_t<
-    !std::is_convertible<ConstraintFnT, PDLConstraintFunction>::value,
-    PDLConstraintFunction>
-buildConstraintFn(ConstraintFnT &&constraintFn) {
-  return [constraintFn = std::forward<ConstraintFnT>(constraintFn)](
-             PatternRewriter &rewriter,
-             ArrayRef<PDLValue> values) -> LogicalResult {
-    auto argIndices = std::make_index_sequence<
-        llvm::function_traits<ConstraintFnT>::num_args - 1>();
-    if (failed(verifyAsArgs<ConstraintFnT>(rewriter, values, argIndices)))
-      return failure();
-    return processArgsAndInvokeConstraint(constraintFn, rewriter, values,
-                                          argIndices);
-  };
-}
-
-//===----------------------------------------------------------------------===//
-// PDL Rewrite Builder
-//===----------------------------------------------------------------------===//
-
-/// Process the arguments of a native rewrite and invoke it.
-/// This overload handles the case of no return values.
-template <typename PDLFnT, std::size_t... I,
-          typename FnTraitsT = llvm::function_traits<PDLFnT>>
-std::enable_if_t<std::is_same<typename FnTraitsT::result_t, void>::value,
-                 LogicalResult>
-processArgsAndInvokeRewrite(PDLFnT &fn, PatternRewriter &rewriter,
-                            PDLResultList &, ArrayRef<PDLValue> values,
-                            std::index_sequence<I...>) {
-  fn(rewriter,
-     (ProcessPDLValue<typename FnTraitsT::template arg_t<I + 1>>::processAsArg(
-         values[I]))...);
-  return success();
-}
-/// This overload handles the case of return values, which need to be packaged
-/// into the result list.
-template <typename PDLFnT, std::size_t... I,
-          typename FnTraitsT = llvm::function_traits<PDLFnT>>
-std::enable_if_t<!std::is_same<typename FnTraitsT::result_t, void>::value,
-                 LogicalResult>
-processArgsAndInvokeRewrite(PDLFnT &fn, PatternRewriter &rewriter,
-                            PDLResultList &results, ArrayRef<PDLValue> values,
-                            std::index_sequence<I...>) {
-  return processResults(
-      rewriter, results,
-      fn(rewriter, (ProcessPDLValue<typename FnTraitsT::template arg_t<I + 1>>::
-                        processAsArg(values[I]))...));
-  (void)values;
-}
-
-/// Build a rewrite function from the given function `RewriteFnT`. This
-/// allows for enabling the user to define simpler, more direct rewrite
-/// functions without needing to handle the low-level PDL goop.
-///
-/// If the rewrite function is already in the correct form, we just forward
-/// it directly.
-template <typename RewriteFnT>
-std::enable_if_t<std::is_convertible<RewriteFnT, PDLRewriteFunction>::value,
-                 PDLRewriteFunction>
-buildRewriteFn(RewriteFnT &&rewriteFn) {
-  return std::forward<RewriteFnT>(rewriteFn);
-}
-/// Otherwise, we generate a wrapper that will unpack the PDLValues in the form
-/// we desire.
-template <typename RewriteFnT>
-std::enable_if_t<!std::is_convertible<RewriteFnT, PDLRewriteFunction>::value,
-                 PDLRewriteFunction>
-buildRewriteFn(RewriteFnT &&rewriteFn) {
-  return [rewriteFn = std::forward<RewriteFnT>(rewriteFn)](
-             PatternRewriter &rewriter, PDLResultList &results,
-             ArrayRef<PDLValue> values) {
-    auto argIndices =
-        std::make_index_sequence<llvm::function_traits<RewriteFnT>::num_args -
-                                 1>();
-    assertArgs<RewriteFnT>(rewriter, values, argIndices);
-    return processArgsAndInvokeRewrite(rewriteFn, rewriter, results, values,
-                                       argIndices);
-  };
-}
-
-} // namespace pdl_function_builder
-} // namespace detail
-
-//===----------------------------------------------------------------------===//
-// PDLPatternModule
-
-/// This class contains all of the necessary data for a set of PDL patterns, or
-/// pattern rewrites specified in the form of the PDL dialect. This PDL module
-/// contained by this pattern may contain any number of `pdl.pattern`
-/// operations.
-class PDLPatternModule {
-public:
-  PDLPatternModule() = default;
-
-  /// Construct a PDL pattern with the given module and configurations.
-  PDLPatternModule(OwningOpRef<ModuleOp> module)
-      : pdlModule(std::move(module)) {}
-  template <typename... ConfigsT>
-  PDLPatternModule(OwningOpRef<ModuleOp> module, ConfigsT &&...patternConfigs)
-      : PDLPatternModule(std::move(module)) {
-    auto configSet = std::make_unique<PDLPatternConfigSet>(
-        std::forward<ConfigsT>(patternConfigs)...);
-    attachConfigToPatterns(*pdlModule, *configSet);
-    configs.emplace_back(std::move(configSet));
-  }
-
-  /// Merge the state in `other` into this pattern module.
-  void mergeIn(PDLPatternModule &&other);
-
-  /// Return the internal PDL module of this pattern.
-  ModuleOp getModule() { return pdlModule.get(); }
-
-  //===--------------------------------------------------------------------===//
-  // Function Registry
-
-  /// Register a constraint function with PDL. A constraint function may be
-  /// specified in one of two ways:
-  ///
-  ///   * `LogicalResult (PatternRewriter &, ArrayRef<PDLValue>)`
-  ///
-  ///   In this overload the arguments of the constraint function are passed via
-  ///   the low-level PDLValue form.
-  ///
-  ///   * `LogicalResult (PatternRewriter &, ValueTs... values)`
-  ///
-  ///   In this form the arguments of the constraint function are passed via the
-  ///   expected high level C++ type. In this form, the framework will
-  ///   automatically unwrap PDLValues and convert them to the expected ValueTs.
-  ///   For example, if the constraint function accepts a `Operation *`, the
-  ///   framework will automatically cast the input PDLValue. In the case of a
-  ///   `StringRef`, the framework will automatically unwrap the argument as a
-  ///   StringAttr and pass the underlying string value. To see the full list of
-  ///   supported types, or to see how to add handling for custom types, view
-  ///   the definition of `ProcessPDLValue` above.
-  void registerConstraintFunction(StringRef name,
-                                  PDLConstraintFunction constraintFn);
-  template <typename ConstraintFnT>
-  void registerConstraintFunction(StringRef name,
-                                  ConstraintFnT &&constraintFn) {
-    registerConstraintFunction(name,
-                               detail::pdl_function_builder::buildConstraintFn(
-                                   std::forward<ConstraintFnT>(constraintFn)));
-  }
-
-  /// Register a rewrite function with PDL. A rewrite function may be specified
-  /// in one of two ways:
-  ///
-  ///   * `void (PatternRewriter &, PDLResultList &, ArrayRef<PDLValue>)`
-  ///
-  ///   In this overload the arguments of the constraint function are passed via
-  ///   the low-level PDLValue form, and the results are manually appended to
-  ///   the given result list.
-  ///
-  ///   * `ResultT (PatternRewriter &, ValueTs... values)`
-  ///
-  ///   In this form the arguments and result of the rewrite function are passed
-  ///   via the expected high level C++ type. In this form, the framework will
-  ///   automatically unwrap the PDLValues arguments and convert them to the
-  ///   expected ValueTs. It will also automatically handle the processing and
-  ///   packaging of the result value to the result list. For example, if the
-  ///   rewrite function takes a `Operation *`, the framework will automatically
-  ///   cast the input PDLValue. In the case of a `StringRef`, the framework
-  ///   will automatically unwrap the argument as a StringAttr and pass the
-  ///   underlying string value. In the reverse case, if the rewrite returns a
-  ///   StringRef or std::string, it will automatically package this as a
-  ///   StringAttr and append it to the result list. To see the full list of
-  ///   supported types, or to see how to add handling for custom types, view
-  ///   the definition of `ProcessPDLValue` above.
-  void registerRewriteFunction(StringRef name, PDLRewriteFunction rewriteFn);
-  template <typename RewriteFnT>
-  void registerRewriteFunction(StringRef name, RewriteFnT &&rewriteFn) {
-    registerRewriteFunction(name, detail::pdl_function_builder::buildRewriteFn(
-                                      std::forward<RewriteFnT>(rewriteFn)));
-  }
-
-  /// Return the set of the registered constraint functions.
-  const llvm::StringMap<PDLConstraintFunction> &getConstraintFunctions() const {
-    return constraintFunctions;
-  }
-  llvm::StringMap<PDLConstraintFunction> takeConstraintFunctions() {
-    return constraintFunctions;
-  }
-  /// Return the set of the registered rewrite functions.
-  const llvm::StringMap<PDLRewriteFunction> &getRewriteFunctions() const {
-    return rewriteFunctions;
-  }
-  llvm::StringMap<PDLRewriteFunction> takeRewriteFunctions() {
-    return rewriteFunctions;
-  }
-
-  /// Return the set of the registered pattern configs.
-  SmallVector<std::unique_ptr<PDLPatternConfigSet>> takeConfigs() {
-    return std::move(configs);
-  }
-  DenseMap<Operation *, PDLPatternConfigSet *> takeConfigMap() {
-    return std::move(configMap);
-  }
-
-  /// Clear out the patterns and functions within this module.
-  void clear() {
-    pdlModule = nullptr;
-    constraintFunctions.clear();
-    rewriteFunctions.clear();
-  }
-
-private:
-  /// Attach the given pattern config set to the patterns defined within the
-  /// given module.
-  void attachConfigToPatterns(ModuleOp module, PDLPatternConfigSet &configSet);
-
-  /// The module containing the `pdl.pattern` operations.
-  OwningOpRef<ModuleOp> pdlModule;
+} // namespace mlir
 
-  /// The set of configuration sets referenced by patterns within `pdlModule`.
-  SmallVector<std::unique_ptr<PDLPatternConfigSet>> configs;
-  DenseMap<Operation *, PDLPatternConfigSet *> configMap;
+// Optionally expose PDL pattern matching methods.
+#include "PDLPatternMatch.h.inc"
 
-  /// The external functions referenced from within the PDL module.
-  llvm::StringMap<PDLConstraintFunction> constraintFunctions;
-  llvm::StringMap<PDLRewriteFunction> rewriteFunctions;
-};
-#endif // MLIR_ENABLE_PDL
+namespace mlir {
 
 //===----------------------------------------------------------------------===//
 // RewritePatternSet
@@ -1681,28 +759,21 @@ class RewritePatternSet {
       : context(context) {
     nativePatterns.emplace_back(std::move(pattern));
   }
-#if MLIR_ENABLE_PDL
   RewritePatternSet(PDLPatternModule &&pattern)
-      : context(pattern.getModule()->getContext()),
-        pdlPatterns(std::move(pattern)) {}
-#endif // MLIR_ENABLE_PDL
+      : context(pattern.getContext()), pdlPatterns(std::move(pattern)) {}
 
   MLIRContext *getContext() const { return context; }
 
   /// Return the native patterns held in this list.
   NativePatternListT &getNativePatterns() { return nativePatterns; }
 
-#if MLIR_ENABLE_PDL
   /// Return the PDL patterns held in this list.
   PDLPatternModule &getPDLPatterns() { return pdlPatterns; }
-#endif
 
   /// Clear out all of the held patterns in this list.
   void clear() {
     nativePatterns.clear();
-#if MLIR_ENABLE_PDL
     pdlPatterns.clear();
-#endif
   }
 
   //===--------------------------------------------------------------------===//
@@ -1755,14 +826,12 @@ class RewritePatternSet {
     return *this;
   }
 
-#if MLIR_ENABLE_PDL
   /// Add the given PDL pattern to the pattern list. Return a reference to
   /// `this` for chaining insertions.
   RewritePatternSet &add(PDLPatternModule &&pattern) {
     pdlPatterns.mergeIn(std::move(pattern));
     return *this;
   }
-#endif // MLIR_ENABLE_PDL
 
   // Add a matchAndRewrite style pattern represented as a C function pointer.
   template <typename OpType>
@@ -1823,14 +892,12 @@ class RewritePatternSet {
     return *this;
   }
 
-#if MLIR_ENABLE_PDL
   /// Add the given PDL pattern to the pattern list. Return a reference to
   /// `this` for chaining insertions.
   RewritePatternSet &insert(PDLPatternModule &&pattern) {
     pdlPatterns.mergeIn(std::move(pattern));
     return *this;
   }
-#endif // MLIR_ENABLE_PDL
 
   // Add a matchAndRewrite style pattern represented as a C function pointer.
   template <typename OpType>
@@ -1866,7 +933,7 @@ class RewritePatternSet {
     pattern->addDebugLabels(debugLabels);
     nativePatterns.emplace_back(std::move(pattern));
   }
-#if MLIR_ENABLE_PDL
+
   template <typename T, typename... Args>
   std::enable_if_t<std::is_base_of<PDLPatternModule, T>::value>
   addImpl(ArrayRef<StringRef> debugLabels, Args &&...args) {
@@ -1874,13 +941,12 @@ class RewritePatternSet {
     // labels.
     pdlPatterns.mergeIn(T(std::forward<Args>(args)...));
   }
-#endif // MLIR_ENABLE_PDL
 
   MLIRContext *const context;
   NativePatternListT nativePatterns;
-#if MLIR_ENABLE_PDL
+
+  // Technically not needed if PDL not enabled. Stubs enable less ifdefs.
   PDLPatternModule pdlPatterns;
-#endif // MLIR_ENABLE_PDL
 };
 
 } // namespace mlir
diff --git a/mlir/include/mlir/InitAllDialects.h b/mlir/include/mlir/InitAllDialects.h
index c75a599b40f0bc..e7067ef476faf9 100644
--- a/mlir/include/mlir/InitAllDialects.h
+++ b/mlir/include/mlir/InitAllDialects.h
@@ -59,6 +59,8 @@
 #include "mlir/Dialect/NVGPU/IR/NVGPUDialect.h"
 #include "mlir/Dialect/OpenACC/OpenACC.h"
 #include "mlir/Dialect/OpenMP/OpenMPDialect.h"
+#include "mlir/Dialect/PDL/IR/PDL.h"
+#include "mlir/Dialect/PDLInterp/IR/PDLInterp.h"
 #include "mlir/Dialect/Quant/QuantOps.h"
 #include "mlir/Dialect/SCF/IR/SCF.h"
 #include "mlir/Dialect/SCF/IR/ValueBoundsOpInterfaceImpl.h"
@@ -91,10 +93,6 @@
 #include "mlir/Target/LLVM/NVVM/Target.h"
 #include "mlir/Target/LLVM/ROCDL/Target.h"
 #include "mlir/Target/SPIRV/Target.h"
-#if MLIR_ENABLE_PDL
-#include "mlir/Dialect/PDL/IR/PDL.h"
-#include "mlir/Dialect/PDLInterp/IR/PDLInterp.h"
-#endif // MLIR_ENABLE_PDL
 
 namespace mlir {
 
@@ -128,10 +126,8 @@ inline void registerAllDialects(DialectRegistry &registry) {
                   nvgpu::NVGPUDialect,
                   NVVM::NVVMDialect,
                   omp::OpenMPDialect,
-#if MLIR_ENABLE_PDL
                   pdl::PDLDialect,
                   pdl_interp::PDLInterpDialect,
-#endif // MLIR_ENABLE_PDL
                   quant::QuantizationDialect,
                   ROCDL::ROCDLDialect,
                   scf::SCFDialect,
diff --git a/mlir/include/mlir/InitAllExtensions.h b/mlir/include/mlir/InitAllExtensions.h
index ae898ef6a86646..c3ccf68adc9318 100644
--- a/mlir/include/mlir/InitAllExtensions.h
+++ b/mlir/include/mlir/InitAllExtensions.h
@@ -25,6 +25,7 @@
 #include "mlir/Conversion/NVVMToLLVM/NVVMToLLVM.h"
 #include "mlir/Conversion/UBToLLVM/UBToLLVM.h"
 #include "mlir/Dialect/Affine/TransformOps/AffineTransformOps.h"
+#include "mlir/Dialect/Bufferization/TransformOps/BufferizationTransformOps.h"
 #include "mlir/Dialect/Func/Extensions/AllExtensions.h"
 #include "mlir/Dialect/Func/TransformOps/FuncTransformOps.h"
 #include "mlir/Dialect/GPU/TransformOps/GPUTransformOps.h"
@@ -35,15 +36,12 @@
 #include "mlir/Dialect/SparseTensor/TransformOps/SparseTensorTransformOps.h"
 #include "mlir/Dialect/Tensor/TransformOps/TensorTransformOps.h"
 #include "mlir/Dialect/Transform/LoopExtension/LoopExtension.h"
+#include "mlir/Dialect/Transform/PDLExtension/PDLExtension.h"
 #include "mlir/Dialect/Vector/TransformOps/VectorTransformOps.h"
 #include "mlir/Target/LLVMIR/Dialect/Builtin/BuiltinToLLVMIRTranslation.h"
 #include "mlir/Target/LLVMIR/Dialect/GPU/GPUToLLVMIRTranslation.h"
 #include "mlir/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.h"
 #include "mlir/Target/LLVMIR/Dialect/ROCDL/ROCDLToLLVMIRTranslation.h"
-#if MLIR_ENABLE_PDL
-#include "mlir/Dialect/Bufferization/TransformOps/BufferizationTransformOps.h"
-#include "mlir/Dialect/Transform/PDLExtension/PDLExtension.h"
-#endif // MLIR_ENABLE_PDL
 
 #include <cstdlib>
 
@@ -78,10 +76,8 @@ inline void registerAllExtensions(DialectRegistry &registry) {
   sparse_tensor::registerTransformDialectExtension(registry);
   tensor::registerTransformDialectExtension(registry);
   transform::registerLoopExtension(registry);
-#if MLIR_ENABLE_PDL
   bufferization::registerTransformDialectExtension(registry);
   transform::registerPDLExtension(registry);
-#endif
   vector::registerTransformDialectExtension(registry);
 
   // Translation extensions need to be registered by calling
diff --git a/mlir/include/mlir/Rewrite/FrozenRewritePatternSet.h b/mlir/include/mlir/Rewrite/FrozenRewritePatternSet.h
index 5c2edade10f0ce..4c6e3cd9ce6f4c 100644
--- a/mlir/include/mlir/Rewrite/FrozenRewritePatternSet.h
+++ b/mlir/include/mlir/Rewrite/FrozenRewritePatternSet.h
@@ -12,11 +12,9 @@
 #include "mlir/IR/PatternMatch.h"
 
 namespace mlir {
-#if MLIR_ENABLE_PDL
 namespace detail {
 class PDLByteCode;
 } // namespace detail
-#endif // MLIR_ENABLE_PDL
 
 /// This class represents a frozen set of patterns that can be processed by a
 /// pattern applicator. This class is designed to enable caching pattern lists
@@ -66,13 +64,11 @@ class FrozenRewritePatternSet {
     return llvm::make_pointee_range(nativeList);
   }
 
-#if MLIR_ENABLE_PDL
   /// Return the compiled PDL bytecode held by this list. Returns null if
   /// there are no PDL patterns within the list.
   const detail::PDLByteCode *getPDLByteCode() const {
     return impl->pdlByteCode.get();
   }
-#endif // MLIR_ENABLE_PDL
 
 private:
   /// The internal implementation of the frozen pattern list.
@@ -89,10 +85,8 @@ class FrozenRewritePatternSet {
     /// operation.
     NativePatternListT nativeAnyOpPatterns;
 
-#if MLIR_ENABLE_PDL
     /// The bytecode containing the compiled PDL patterns.
     std::unique_ptr<detail::PDLByteCode> pdlByteCode;
-#endif // MLIR_ENABLE_PDL
   };
 
   /// A pointer to the internal pattern list. This uses a shared_ptr to avoid
diff --git a/mlir/include/mlir/Rewrite/PatternApplicator.h b/mlir/include/mlir/Rewrite/PatternApplicator.h
index 1c0f94c1bcc54d..9b5280d1546281 100644
--- a/mlir/include/mlir/Rewrite/PatternApplicator.h
+++ b/mlir/include/mlir/Rewrite/PatternApplicator.h
@@ -21,11 +21,9 @@
 namespace mlir {
 class PatternRewriter;
 
-#if MLIR_ENABLE_PDL
 namespace detail {
 class PDLByteCodeMutableState;
 } // namespace detail
-#endif // MLIR_ENABLE_PDL
 
 /// This is the type of Action that is dispatched when a pattern is applied.
 /// It captures the pattern to apply on top of the usual context.
@@ -95,10 +93,8 @@ class PatternApplicator {
   /// sorted by benefit.
   SmallVector<const RewritePattern *, 1> anyOpPatterns;
 
-#if MLIR_ENABLE_PDL
   /// The mutable state used during execution of the PDL bytecode.
   std::unique_ptr<detail::PDLByteCodeMutableState> mutableByteCodeState;
-#endif // MLIR_ENABLE_PDL
 };
 
 } // namespace mlir
diff --git a/mlir/include/mlir/Transforms/DialectConversion.h b/mlir/include/mlir/Transforms/DialectConversion.h
index 9c5e3aa4e7e42a..22cb85fbacb96d 100644
--- a/mlir/include/mlir/Transforms/DialectConversion.h
+++ b/mlir/include/mlir/Transforms/DialectConversion.h
@@ -13,6 +13,7 @@
 #ifndef MLIR_TRANSFORMS_DIALECTCONVERSION_H_
 #define MLIR_TRANSFORMS_DIALECTCONVERSION_H_
 
+#include "mlir/Config/mlir-config.h"
 #include "mlir/Rewrite/FrozenRewritePatternSet.h"
 #include "llvm/ADT/MapVector.h"
 #include "llvm/ADT/StringMap.h"
@@ -1044,6 +1045,18 @@ class PDLConversionConfig final
 
 /// Register the dialect conversion PDL functions with the given pattern set.
 void registerConversionPDLFunctions(RewritePatternSet &patterns);
+
+#else
+
+// Stubs for when PDL in rewriting is not enabled.
+
+inline void registerConversionPDLFunctions(RewritePatternSet &patterns) {}
+
+class PDLConversionConfig final {
+public:
+  PDLConversionConfig(const TypeConverter * /*converter*/) {}
+};
+
 #endif // MLIR_ENABLE_PDL
 
 //===----------------------------------------------------------------------===//
diff --git a/mlir/lib/CAPI/Dialect/CMakeLists.txt b/mlir/lib/CAPI/Dialect/CMakeLists.txt
index 73488d4b41bc84..d815eba48d9b9d 100644
--- a/mlir/lib/CAPI/Dialect/CMakeLists.txt
+++ b/mlir/lib/CAPI/Dialect/CMakeLists.txt
@@ -207,16 +207,14 @@ add_mlir_upstream_c_api_library(MLIRCAPIOpenMP
   MLIROpenMPDialect
 )
 
-if(MLIR_ENABLE_PDL)
-  add_mlir_upstream_c_api_library(MLIRCAPIPDL
-    PDL.cpp
-
-    PARTIAL_SOURCES_INTENDED
-    LINK_LIBS PUBLIC
-    MLIRCAPIIR
-    MLIRPDLDialect
-  )
-endif()
+add_mlir_upstream_c_api_library(MLIRCAPIPDL
+  PDL.cpp
+
+  PARTIAL_SOURCES_INTENDED
+  LINK_LIBS PUBLIC
+  MLIRCAPIIR
+  MLIRPDLDialect
+)
 
 add_mlir_upstream_c_api_library(MLIRCAPIVector
   Vector.cpp
diff --git a/mlir/lib/Conversion/CMakeLists.txt b/mlir/lib/Conversion/CMakeLists.txt
index 113bb55aa4df33..c3a2481975040c 100644
--- a/mlir/lib/Conversion/CMakeLists.txt
+++ b/mlir/lib/Conversion/CMakeLists.txt
@@ -38,9 +38,7 @@ add_subdirectory(NVGPUToNVVM)
 add_subdirectory(NVVMToLLVM)
 add_subdirectory(OpenACCToSCF)
 add_subdirectory(OpenMPToLLVM)
-if(MLIR_ENABLE_PDL)
-  add_subdirectory(PDLToPDLInterp)
-endif()
+add_subdirectory(PDLToPDLInterp)
 add_subdirectory(ReconcileUnrealizedCasts)
 add_subdirectory(SCFToControlFlow)
 add_subdirectory(SCFToEmitC)
diff --git a/mlir/lib/Dialect/Bufferization/CMakeLists.txt b/mlir/lib/Dialect/Bufferization/CMakeLists.txt
index a6ebca41ff3487..215ec562c9818c 100644
--- a/mlir/lib/Dialect/Bufferization/CMakeLists.txt
+++ b/mlir/lib/Dialect/Bufferization/CMakeLists.txt
@@ -1,6 +1,4 @@
 add_subdirectory(IR)
 add_subdirectory(Pipelines)
-if(MLIR_ENABLE_PDL)
-  add_subdirectory(TransformOps)
-endif()
+add_subdirectory(TransformOps)
 add_subdirectory(Transforms)
diff --git a/mlir/lib/Dialect/CMakeLists.txt b/mlir/lib/Dialect/CMakeLists.txt
index ae7c1d50e47939..68776a695cac4d 100644
--- a/mlir/lib/Dialect/CMakeLists.txt
+++ b/mlir/lib/Dialect/CMakeLists.txt
@@ -25,10 +25,8 @@ add_subdirectory(NVGPU)
 add_subdirectory(OpenACC)
 add_subdirectory(OpenACCMPCommon)
 add_subdirectory(OpenMP)
-if (MLIR_ENABLE_PDL)
-  add_subdirectory(PDL)
-  add_subdirectory(PDLInterp)
-endif()
+add_subdirectory(PDL)
+add_subdirectory(PDLInterp)
 add_subdirectory(Quant)
 add_subdirectory(SCF)
 add_subdirectory(Shape)
diff --git a/mlir/lib/Dialect/Transform/CMakeLists.txt b/mlir/lib/Dialect/Transform/CMakeLists.txt
index e0c7a7704fb865..6898d81df7ca63 100644
--- a/mlir/lib/Dialect/Transform/CMakeLists.txt
+++ b/mlir/lib/Dialect/Transform/CMakeLists.txt
@@ -1,7 +1,5 @@
 add_subdirectory(IR)
 add_subdirectory(LoopExtension)
-if (MLIR_ENABLE_PDL)
-  add_subdirectory(PDLExtension)
-endif()
+add_subdirectory(PDLExtension)
 add_subdirectory(Transforms)
 add_subdirectory(Utils)
diff --git a/mlir/lib/IR/PatternMatch.cpp b/mlir/lib/IR/PatternMatch.cpp
index a95b669557aab1..c9481687b8275f 100644
--- a/mlir/lib/IR/PatternMatch.cpp
+++ b/mlir/lib/IR/PatternMatch.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "mlir/IR/PatternMatch.h"
+#include "mlir/Config/mlir-config.h"
 #include "mlir/IR/IRMapping.h"
 #include "mlir/IR/Iterators.h"
 #include "mlir/IR/RegionKindInterface.h"
diff --git a/mlir/lib/Rewrite/ByteCode.cpp b/mlir/lib/Rewrite/ByteCode.cpp
index 6e6992dcdeea78..31b164c2a9a6e4 100644
--- a/mlir/lib/Rewrite/ByteCode.cpp
+++ b/mlir/lib/Rewrite/ByteCode.cpp
@@ -10,6 +10,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#if MLIR_ENABLE_PDL
 #include "ByteCode.h"
 #include "mlir/Analysis/Liveness.h"
 #include "mlir/Dialect/PDL/IR/PDLTypes.h"
@@ -2333,3 +2334,4 @@ LogicalResult PDLByteCode::rewrite(PatternRewriter &rewriter,
   }
   return result;
 }
+#endif // MLIR_ENABLE_PDL
diff --git a/mlir/lib/Rewrite/ByteCode.h b/mlir/lib/Rewrite/ByteCode.h
index 4d43fe636bd1f2..fa80ed0045f29b 100644
--- a/mlir/lib/Rewrite/ByteCode.h
+++ b/mlir/lib/Rewrite/ByteCode.h
@@ -16,6 +16,8 @@
 
 #include "mlir/IR/PatternMatch.h"
 
+#if MLIR_ENABLE_PDL
+
 namespace mlir {
 namespace pdl_interp {
 class RecordMatchOp;
@@ -223,5 +225,38 @@ class PDLByteCode {
 
 } // namespace detail
 } // namespace mlir
+#else
+
+namespace mlir::detail {
+
+class PDLByteCodeMutableState {
+public:
+  void cleanupAfterMatchAndRewrite() {}
+  void updatePatternBenefit(unsigned patternIndex, PatternBenefit benefit) {}
+};
+
+class PDLByteCodePattern : public Pattern {};
+
+class PDLByteCode {
+public:
+  struct MatchResult {
+    const PDLByteCodePattern *pattern = nullptr;
+    PatternBenefit benefit;
+  };
+
+  void initializeMutableState(PDLByteCodeMutableState &state) const {}
+  void match(Operation *op, PatternRewriter &rewriter,
+             SmallVectorImpl<MatchResult> &matches,
+             PDLByteCodeMutableState &state) const {}
+  LogicalResult rewrite(PatternRewriter &rewriter, const MatchResult &match,
+                        PDLByteCodeMutableState &state) const {
+    return failure();
+  }
+  ArrayRef<PDLByteCodePattern> getPatterns() const { return {}; }
+};
+
+} // namespace mlir::detail
+
+#endif // MLIR_ENABLE_PDL
 
 #endif // MLIR_REWRITE_BYTECODE_H_
diff --git a/mlir/lib/Rewrite/CMakeLists.txt b/mlir/lib/Rewrite/CMakeLists.txt
index 3f0ad81e96967c..8ce94014af2a07 100644
--- a/mlir/lib/Rewrite/CMakeLists.txt
+++ b/mlir/lib/Rewrite/CMakeLists.txt
@@ -1,23 +1,16 @@
 set(LLVM_OPTIONAL_SOURCES ByteCode.cpp)
 
 if(MLIR_ENABLE_PDL)
-  set(MLIRRewritePDLDeps
-    MLIRPDLDialect
-    MLIRPDLInterpDialect
-    MLIRPDLToPDLInterp)
+set(MLIRRewritePDLDeps
+  MLIRPDLDialect
+  MLIRPDLInterpDialect
+  MLIRPDLToPDLInterp)
 else()
   set(MLIRRewritePDLDeps)
 endif()
 
-if(MLIR_ENABLE_PDL)
-  set(MLIRRewritePDLSource
-    ByteCode.cpp)
-else()
-  set(MLIRRewritePDLSource)
-endif()
-
 add_mlir_library(MLIRRewrite
-  ${MLIRRewritePDLSource}
+  ByteCode.cpp
   FrozenRewritePatternSet.cpp
   PatternApplicator.cpp
 
@@ -29,6 +22,8 @@ add_mlir_library(MLIRRewrite
 
   LINK_LIBS PUBLIC
   MLIRIR
-  ${MLIRRewritePDLDeps}
+  MLIRPDLDialect
+  MLIRPDLInterpDialect
+  MLIRPDLToPDLInterp
   MLIRSideEffectInterfaces
   )
diff --git a/mlir/lib/Rewrite/FrozenRewritePatternSet.cpp b/mlir/lib/Rewrite/FrozenRewritePatternSet.cpp
index 8793a6791ad94e..1b251d7d5ef593 100644
--- a/mlir/lib/Rewrite/FrozenRewritePatternSet.cpp
+++ b/mlir/lib/Rewrite/FrozenRewritePatternSet.cpp
@@ -7,20 +7,20 @@
 //===----------------------------------------------------------------------===//
 
 #include "mlir/Rewrite/FrozenRewritePatternSet.h"
+#include "ByteCode.h"
 #include "mlir/Interfaces/SideEffectInterfaces.h"
 #include "mlir/Pass/Pass.h"
 #include "mlir/Pass/PassManager.h"
 #include <optional>
 
+using namespace mlir;
+
+// Include the PDL rewrite support.
 #if MLIR_ENABLE_PDL
-#include "ByteCode.h"
+#include "PDLRewrite.cpp"
 #include "mlir/Conversion/PDLToPDLInterp/PDLToPDLInterp.h"
 #include "mlir/Dialect/PDL/IR/PDLOps.h"
-#endif // MLIR_ENABLE_PDL
-
-using namespace mlir;
 
-#if MLIR_ENABLE_PDL
 static LogicalResult
 convertPDLToPDLInterp(ModuleOp pdlModule,
                       DenseMap<Operation *, PDLPatternConfigSet *> &configMap) {
diff --git a/mlir/lib/Rewrite/PatternApplicator.cpp b/mlir/lib/Rewrite/PatternApplicator.cpp
index 157de4bff06400..0064eb84aba84d 100644
--- a/mlir/lib/Rewrite/PatternApplicator.cpp
+++ b/mlir/lib/Rewrite/PatternApplicator.cpp
@@ -12,10 +12,8 @@
 //===----------------------------------------------------------------------===//
 
 #include "mlir/Rewrite/PatternApplicator.h"
-#include "llvm/Support/Debug.h"
-#if MLIR_ENABLE_PDL
 #include "ByteCode.h"
-#endif // MLIR_ENABLE_PDL
+#include "llvm/Support/Debug.h"
 
 #define DEBUG_TYPE "pattern-application"
 
@@ -25,12 +23,10 @@ using namespace mlir::detail;
 PatternApplicator::PatternApplicator(
     const FrozenRewritePatternSet &frozenPatternList)
     : frozenPatternList(frozenPatternList) {
-#if MLIR_ENABLE_PDL
   if (const PDLByteCode *bytecode = frozenPatternList.getPDLByteCode()) {
     mutableByteCodeState = std::make_unique<PDLByteCodeMutableState>();
     bytecode->initializeMutableState(*mutableByteCodeState);
   }
-#endif // MLIR_ENABLE_PDL
 }
 PatternApplicator::~PatternApplicator() = default;
 
@@ -54,14 +50,12 @@ static void logSucessfulPatternApplication(Operation *op) {
 #endif
 
 void PatternApplicator::applyCostModel(CostModel model) {
-#if MLIR_ENABLE_PDL
   // Apply the cost model to the bytecode patterns first, and then the native
   // patterns.
   if (const PDLByteCode *bytecode = frozenPatternList.getPDLByteCode()) {
     for (const auto &it : llvm::enumerate(bytecode->getPatterns()))
       mutableByteCodeState->updatePatternBenefit(it.index(), model(it.value()));
   }
-#endif // MLIR_ENABLE_PDL
 
   // Copy over the patterns so that we can sort by benefit based on the cost
   // model. Patterns that are already impossible to match are ignored.
@@ -123,12 +117,10 @@ void PatternApplicator::walkAllPatterns(
       walk(*pattern);
   for (const Pattern &it : frozenPatternList.getMatchAnyOpNativePatterns())
     walk(it);
-#if MLIR_ENABLE_PDL
   if (const PDLByteCode *bytecode = frozenPatternList.getPDLByteCode()) {
     for (const Pattern &it : bytecode->getPatterns())
       walk(it);
   }
-#endif // MLIR_ENABLE_PDL
 }
 
 LogicalResult PatternApplicator::matchAndRewrite(
@@ -136,7 +128,6 @@ LogicalResult PatternApplicator::matchAndRewrite(
     function_ref<bool(const Pattern &)> canApply,
     function_ref<void(const Pattern &)> onFailure,
     function_ref<LogicalResult(const Pattern &)> onSuccess) {
-#if MLIR_ENABLE_PDL
   // Before checking native patterns, first match against the bytecode. This
   // won't automatically perform any rewrites so there is no need to worry about
   // conflicts.
@@ -144,7 +135,6 @@ LogicalResult PatternApplicator::matchAndRewrite(
   const PDLByteCode *bytecode = frozenPatternList.getPDLByteCode();
   if (bytecode)
     bytecode->match(op, rewriter, pdlMatches, *mutableByteCodeState);
-#endif // MLIR_ENABLE_PDL
 
   // Check to see if there are patterns matching this specific operation type.
   MutableArrayRef<const RewritePattern *> opPatterns;
@@ -156,9 +146,7 @@ LogicalResult PatternApplicator::matchAndRewrite(
   // operation type in an interleaved fashion.
   unsigned opIt = 0, opE = opPatterns.size();
   unsigned anyIt = 0, anyE = anyOpPatterns.size();
-#if MLIR_ENABLE_PDL
   unsigned pdlIt = 0, pdlE = pdlMatches.size();
-#endif // MLIR_ENABLE_PDL
   LogicalResult result = failure();
   do {
     // Find the next pattern with the highest benefit.
@@ -176,7 +164,6 @@ LogicalResult PatternApplicator::matchAndRewrite(
       bestPattern = anyOpPatterns[anyIt];
     }
 
-#if MLIR_ENABLE_PDL
     const PDLByteCode::MatchResult *pdlMatch = nullptr;
     /// PDL patterns.
     if (pdlIt < pdlE && (!bestPattern || bestPattern->getBenefit() <
@@ -185,7 +172,6 @@ LogicalResult PatternApplicator::matchAndRewrite(
       pdlMatch = &pdlMatches[pdlIt];
       bestPattern = pdlMatch->pattern;
     }
-#endif // MLIR_ENABLE_PDL
 
     if (!bestPattern)
       break;
@@ -210,14 +196,10 @@ LogicalResult PatternApplicator::matchAndRewrite(
           // pattern.
           Operation *dumpRootOp = getDumpRootOp(op);
 #endif
-#if MLIR_ENABLE_PDL
           if (pdlMatch) {
             result =
                 bytecode->rewrite(rewriter, *pdlMatch, *mutableByteCodeState);
           } else {
-#else
-          {
-#endif // MLIR_ENABLE_PDL
             LLVM_DEBUG(llvm::dbgs() << "Trying to match \""
                                     << bestPattern->getDebugName() << "\"\n");
 
@@ -248,9 +230,7 @@ LogicalResult PatternApplicator::matchAndRewrite(
       break;
   } while (true);
 
-#if MLIR_ENABLE_PDL
   if (mutableByteCodeState)
     mutableByteCodeState->cleanupAfterMatchAndRewrite();
-#endif
   return result;
 }
diff --git a/mlir/lib/Tools/CMakeLists.txt b/mlir/lib/Tools/CMakeLists.txt
index 54f03bd711d168..80d4e741bffd92 100644
--- a/mlir/lib/Tools/CMakeLists.txt
+++ b/mlir/lib/Tools/CMakeLists.txt
@@ -5,9 +5,7 @@ add_subdirectory(mlir-query)
 add_subdirectory(mlir-reduce)
 add_subdirectory(mlir-tblgen)
 add_subdirectory(mlir-translate)
-if(MLIR_ENABLE_PDL)
-  add_subdirectory(PDLL)
-  add_subdirectory(mlir-pdll-lsp-server)
-endif()	
+add_subdirectory(PDLL)
+add_subdirectory(mlir-pdll-lsp-server)
 add_subdirectory(Plugins)
 add_subdirectory(tblgen-lsp-server)
diff --git a/mlir/python/CMakeLists.txt b/mlir/python/CMakeLists.txt
index 0ea9104cc0a123..f966e4c491fa69 100644
--- a/mlir/python/CMakeLists.txt
+++ b/mlir/python/CMakeLists.txt
@@ -145,8 +145,7 @@ declare_mlir_dialect_python_bindings(
   DIALECT_NAME llvm
   GEN_ENUM_BINDINGS)
 
-if(MLIR_ENABLE_PDL)
-  declare_mlir_dialect_extension_python_bindings(
+declare_mlir_dialect_extension_python_bindings(
   ADD_TO_PARENT MLIRPythonSources.Dialects
   ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/mlir"
     TD_FILE dialects/TransformPDLExtensionOps.td
@@ -154,7 +153,6 @@ if(MLIR_ENABLE_PDL)
       dialects/transform/pdl.py
     DIALECT_NAME transform
     EXTENSION_NAME transform_pdl_extension)
-endif()
 
 declare_mlir_dialect_python_bindings(
   ADD_TO_PARENT MLIRPythonSources.Dialects
@@ -330,16 +328,14 @@ declare_mlir_python_sources(
     dialects/quant.py
     _mlir_libs/_mlir/dialects/quant.pyi)
 
-if(MLIR_ENABLE_PDL)
-  declare_mlir_dialect_python_bindings(
-    ADD_TO_PARENT MLIRPythonSources.Dialects
-    ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/mlir"
-    TD_FILE dialects/PDLOps.td
-    SOURCES
-      dialects/pdl.py
-      _mlir_libs/_mlir/dialects/pdl.pyi
-    DIALECT_NAME pdl)
-endif()
+declare_mlir_dialect_python_bindings(
+  ADD_TO_PARENT MLIRPythonSources.Dialects
+  ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/mlir"
+  TD_FILE dialects/PDLOps.td
+  SOURCES
+    dialects/pdl.py
+    _mlir_libs/_mlir/dialects/pdl.pyi
+  DIALECT_NAME pdl)
 
 declare_mlir_dialect_python_bindings(
   ADD_TO_PARENT MLIRPythonSources.Dialects
@@ -485,7 +481,6 @@ declare_mlir_python_extension(MLIRPythonExtension.Dialects.Quant.Pybind
     MLIRCAPIQuant
 )
 
-if(MLIR_ENABLE_PDL)
   declare_mlir_python_extension(MLIRPythonExtension.Dialects.PDL.Pybind
     MODULE_NAME _mlirDialectsPDL
     ADD_TO_PARENT MLIRPythonSources.Dialects.pdl
@@ -498,7 +493,6 @@ if(MLIR_ENABLE_PDL)
       MLIRCAPIIR
       MLIRCAPIPDL
   )
-endif()
 
 declare_mlir_python_extension(MLIRPythonExtension.Dialects.SparseTensor.Pybind
   MODULE_NAME _mlirDialectsSparseTensor
diff --git a/mlir/test/CAPI/CMakeLists.txt b/mlir/test/CAPI/CMakeLists.txt
index e76ad5868c0359..1096a3b0806648 100644
--- a/mlir/test/CAPI/CMakeLists.txt
+++ b/mlir/test/CAPI/CMakeLists.txt
@@ -54,15 +54,13 @@ _add_capi_test_executable(mlir-capi-pass-test
     MLIRCAPITransforms
 )
 
-if(MLIR_ENABLE_PDL)
-  _add_capi_test_executable(mlir-capi-pdl-test
-    pdl.c
-    LINK_LIBS PRIVATE
-      MLIRCAPIIR
-      MLIRCAPIRegisterEverything
-      MLIRCAPIPDL
-  )
-endif()
+_add_capi_test_executable(mlir-capi-pdl-test
+  pdl.c
+  LINK_LIBS PRIVATE
+    MLIRCAPIIR
+    MLIRCAPIRegisterEverything
+    MLIRCAPIPDL
+)
 
 _add_capi_test_executable(mlir-capi-sparse-tensor-test
   sparse_tensor.c
diff --git a/mlir/test/CMakeLists.txt b/mlir/test/CMakeLists.txt
index 66f2bc7a926cdc..7ec4c8f0963a2d 100644
--- a/mlir/test/CMakeLists.txt
+++ b/mlir/test/CMakeLists.txt
@@ -112,13 +112,11 @@ set(MLIR_TEST_DEPENDS
   tblgen-to-irdl
   )
 
-if(MLIR_ENABLE_PDL)
-  set(MLIR_TEST_DEPENDS ${MLIR_TEST_DEPENDS}
-    mlir-capi-pdl-test
-    mlir-pdll-lsp-server
-    mlir-pdll
-    )
-endif()
+set(MLIR_TEST_DEPENDS ${MLIR_TEST_DEPENDS}
+  mlir-capi-pdl-test
+  mlir-pdll-lsp-server
+  mlir-pdll
+  )
 
 # The native target may not be enabled, in this case we won't
 # run tests that involves executing on the host: do not build
@@ -165,12 +163,10 @@ if(LLVM_BUILD_EXAMPLES)
     toyc-ch4
     toyc-ch5
     )
-  if(MLIR_ENABLE_PDL)
-    list(APPEND MLIR_TEST_DEPENDS
-      transform-opt-ch2
-      transform-opt-ch3
-      )
-  endif()
+  list(APPEND MLIR_TEST_DEPENDS
+    transform-opt-ch2
+    transform-opt-ch3
+    )
   if(MLIR_ENABLE_EXECUTION_ENGINE)
     list(APPEND MLIR_TEST_DEPENDS
       toyc-ch6
diff --git a/mlir/test/lib/Dialect/CMakeLists.txt b/mlir/test/lib/Dialect/CMakeLists.txt
index f09bcf160f211a..30a17c201ff763 100644
--- a/mlir/test/lib/Dialect/CMakeLists.txt
+++ b/mlir/test/lib/Dialect/CMakeLists.txt
@@ -18,8 +18,5 @@ add_subdirectory(Tensor)
 add_subdirectory(Test)
 add_subdirectory(TestDyn)
 add_subdirectory(Tosa)
-if(MLIR_ENABLE_PDL)
-  # Depends on PDL for testing.
-  add_subdirectory(Transform)
-endif()
+add_subdirectory(Transform)
 add_subdirectory(Vector)
diff --git a/mlir/test/lib/Rewrite/CMakeLists.txt b/mlir/test/lib/Rewrite/CMakeLists.txt
index e5c73613aaa84a..7ab38af20738b6 100644
--- a/mlir/test/lib/Rewrite/CMakeLists.txt
+++ b/mlir/test/lib/Rewrite/CMakeLists.txt
@@ -1,5 +1,4 @@
 # Exclude tests from libMLIR.so
-if(MLIR_ENABLE_PDL)
 add_mlir_library(MLIRTestRewrite
   TestPDLByteCode.cpp
 
@@ -14,4 +13,3 @@ add_mlir_library(MLIRTestRewrite
   MLIRSupport
   MLIRTransformUtils
   )
-endif()
diff --git a/mlir/test/lib/Tools/CMakeLists.txt b/mlir/test/lib/Tools/CMakeLists.txt
index 5b8e02a14b22ee..5aa03a3833812e 100644
--- a/mlir/test/lib/Tools/CMakeLists.txt
+++ b/mlir/test/lib/Tools/CMakeLists.txt
@@ -1,3 +1 @@
-if(MLIR_ENABLE_PDL)
-  add_subdirectory(PDLL)
-endif()
+add_subdirectory(PDLL)
diff --git a/mlir/test/lib/Transforms/CMakeLists.txt b/mlir/test/lib/Transforms/CMakeLists.txt
index ee7c215a430205..7c52db2a9d3076 100644
--- a/mlir/test/lib/Transforms/CMakeLists.txt
+++ b/mlir/test/lib/Transforms/CMakeLists.txt
@@ -3,18 +3,18 @@ set(LLVM_OPTIONAL_SOURCES
 set(MLIRTestTransformsPDLDep)
 set(MLIRTestTransformsPDLSrc)
 if(MLIR_ENABLE_PDL)
-  add_mlir_pdll_library(MLIRTestDialectConversionPDLLPatternsIncGen
-    TestDialectConversion.pdll
-    TestDialectConversionPDLLPatterns.h.inc
+add_mlir_pdll_library(MLIRTestDialectConversionPDLLPatternsIncGen
+  TestDialectConversion.pdll
+  TestDialectConversionPDLLPatterns.h.inc
 
-    EXTRA_INCLUDES
-    ${CMAKE_CURRENT_SOURCE_DIR}/../Dialect/Test
-    ${CMAKE_CURRENT_BINARY_DIR}/../Dialect/Test
-    )
-    set(MLIRTestTransformsPDLSrc
-      TestDialectConversion.cpp)
-    set(MLIRTestTransformsPDLDep
-      MLIRTestDialectConversionPDLLPatternsIncGen)
+  EXTRA_INCLUDES
+  ${CMAKE_CURRENT_SOURCE_DIR}/../Dialect/Test
+  ${CMAKE_CURRENT_BINARY_DIR}/../Dialect/Test
+  )
+  set(MLIRTestTransformsPDLSrc
+    TestDialectConversion.cpp)
+  set(MLIRTestTransformsPDLDep
+    MLIRTestDialectConversionPDLLPatternsIncGen)
 endif()
 
 # Exclude tests from libMLIR.so
diff --git a/mlir/tools/CMakeLists.txt b/mlir/tools/CMakeLists.txt
index 997d601701a25c..9b474385fdae18 100644
--- a/mlir/tools/CMakeLists.txt
+++ b/mlir/tools/CMakeLists.txt
@@ -1,9 +1,7 @@
 add_subdirectory(mlir-lsp-server)
 add_subdirectory(mlir-opt)
 add_subdirectory(mlir-parser-fuzzer)
-if(MLIR_ENABLE_PDL)
-  add_subdirectory(mlir-pdll-lsp-server)
-endif()
+add_subdirectory(mlir-pdll-lsp-server)
 add_subdirectory(mlir-query)
 add_subdirectory(mlir-reduce)
 add_subdirectory(mlir-shlib)
diff --git a/mlir/tools/mlir-lsp-server/CMakeLists.txt b/mlir/tools/mlir-lsp-server/CMakeLists.txt
index 8b960d7977d341..9664f6b94844e6 100644
--- a/mlir/tools/mlir-lsp-server/CMakeLists.txt
+++ b/mlir/tools/mlir-lsp-server/CMakeLists.txt
@@ -22,13 +22,11 @@ if(MLIR_INCLUDE_TESTS)
     MLIRTestPass
     MLIRTestReducer
     )
-  if(MLIR_ENABLE_PDL)
-    set(test_libs
-      ${test_libs}
-      MLIRTestRewrite
-      MLIRTestTransformDialect
-      MLIRTestTransforms)
-  endif()
+  set(test_libs
+    ${test_libs}
+    MLIRTestRewrite
+    MLIRTestTransformDialect
+    MLIRTestTransforms)
 endif()
 
 set(LIBS
diff --git a/mlir/tools/mlir-lsp-server/mlir-lsp-server.cpp b/mlir/tools/mlir-lsp-server/mlir-lsp-server.cpp
index 4d6b83da05d8b1..f0ecc5adc68b36 100644
--- a/mlir/tools/mlir-lsp-server/mlir-lsp-server.cpp
+++ b/mlir/tools/mlir-lsp-server/mlir-lsp-server.cpp
@@ -18,9 +18,7 @@ using namespace mlir;
 namespace test {
 void registerTestDialect(DialectRegistry &);
 void registerTestDynDialect(DialectRegistry &);
-#if MLIR_ENABLE_PDL
 void registerTestTransformDialectExtension(DialectRegistry &);
-#endif // MLIR_ENABLE_PDL
 } // namespace test
 #endif
 
@@ -31,9 +29,7 @@ int main(int argc, char **argv) {
 
 #ifdef MLIR_INCLUDE_TESTS
   ::test::registerTestDialect(registry);
-#if MLIR_ENABLE_PDL
   ::test::registerTestTransformDialectExtension(registry);
-#endif // MLIR_ENABLE_PDL
   ::test::registerTestDynDialect(registry);
 #endif
   return failed(MlirLspServerMain(argc, argv, registry));
diff --git a/mlir/tools/mlir-opt/CMakeLists.txt b/mlir/tools/mlir-opt/CMakeLists.txt
index 3e0acec806cf5c..15317a119c154c 100644
--- a/mlir/tools/mlir-opt/CMakeLists.txt
+++ b/mlir/tools/mlir-opt/CMakeLists.txt
@@ -45,13 +45,11 @@ if(MLIR_INCLUDE_TESTS)
     MLIRTestVectorToSPIRV
     MLIRLLVMTestPasses
     )
-  if(MLIR_ENABLE_PDL)
-    set(test_libs ${test_libs}
-      MLIRTestPDLL
-      MLIRTestRewrite
-      MLIRTestTransformDialect
-      )
-  endif()
+  set(test_libs ${test_libs}
+    MLIRTestPDLL
+    MLIRTestRewrite
+    MLIRTestTransformDialect
+    )
 endif()
 
 set(LIBS
diff --git a/mlir/tools/mlir-opt/mlir-opt.cpp b/mlir/tools/mlir-opt/mlir-opt.cpp
index f425c83e0b43f6..e550edfa2d131f 100644
--- a/mlir/tools/mlir-opt/mlir-opt.cpp
+++ b/mlir/tools/mlir-opt/mlir-opt.cpp
@@ -85,7 +85,9 @@ void registerTestDataLayoutQuery();
 void registerTestDeadCodeAnalysisPass();
 void registerTestDecomposeCallGraphTypes();
 void registerTestDiagnosticsPass();
+#if MLIR_ENABLE_PDL
 void registerTestDialectConversionPasses();
+#endif
 void registerTestDominancePass();
 void registerTestDynamicPipelinePass();
 void registerTestEmulateNarrowTypePass();
@@ -258,11 +260,11 @@ void registerTestPasses() {
   mlir::test::registerTestWrittenToPass();
 #if MLIR_ENABLE_PDL
   mlir::test::registerTestDialectConversionPasses();
+#endif
   mlir::test::registerTestPDLByteCodePass();
   mlir::test::registerTestPDLLPasses();
   mlir::test::registerTestTransformDialectEraseSchedulePass();
   mlir::test::registerTestTransformDialectInterpreterPass();
-#endif
 }
 #endif
 
@@ -286,9 +288,7 @@ int main(int argc, char **argv) {
 
 #ifdef MLIR_INCLUDE_TESTS
   ::test::registerTestDialect(registry);
-#if MLIR_ENABLE_PDL
   ::test::registerTestTransformDialectExtension(registry);
-#endif
   ::test::registerTestDynDialect(registry);
 #endif
   return mlir::asMainReturnCode(mlir::MlirOptMain(
diff --git a/mlir/unittests/Conversion/CMakeLists.txt b/mlir/unittests/Conversion/CMakeLists.txt
index 7ca1ee2c3f2395..2dee5e7dac90c4 100644
--- a/mlir/unittests/Conversion/CMakeLists.txt
+++ b/mlir/unittests/Conversion/CMakeLists.txt
@@ -1,3 +1 @@
-if(MLIR_ENABLE_PDL)
-  add_subdirectory(PDLToPDLInterp)
-endif()
+add_subdirectory(PDLToPDLInterp)
diff --git a/mlir/unittests/Dialect/CMakeLists.txt b/mlir/unittests/Dialect/CMakeLists.txt
index 2e4c8e5c05eb38..2dec4ba3c001e8 100644
--- a/mlir/unittests/Dialect/CMakeLists.txt
+++ b/mlir/unittests/Dialect/CMakeLists.txt
@@ -13,7 +13,5 @@ add_subdirectory(MemRef)
 add_subdirectory(SCF)
 add_subdirectory(SparseTensor)
 add_subdirectory(SPIRV)
-if(MLIR_ENABLE_PDL)
-  add_subdirectory(Transform)
-endif()
+add_subdirectory(Transform)
 add_subdirectory(Utils)
diff --git a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel
index e9449ad2f7e45b..8606a81e8c542c 100644
--- a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel
@@ -35,7 +35,7 @@ expand_template(
     substitutions = {
         "#cmakedefine01 MLIR_ENABLE_EXPENSIVE_PATTERN_API_CHECKS": "#define MLIR_ENABLE_EXPENSIVE_PATTERN_API_CHECKS 0",
         "#cmakedefine MLIR_GREEDY_REWRITE_RANDOMIZER_SEED ${MLIR_GREEDY_REWRITE_RANDOMIZER_SEED}": "/* #undef MLIR_GREEDY_REWRITE_RANDOMIZER_SEED */",
-        "#cmakedefine MLIR_ENABLE_PDL ${MLIR_ENABLE_PDL}": "#define MLIR_ENABLE_PDLL 1",
+        "#cmakedefine01 MLIR_ENABLE_PDL ${MLIR_ENABLE_PDL}": "#define MLIR_ENABLE_PDL 1",
     },
     template = "include/mlir/Config/mlir-config.h.cmake",
 )

>From f8392149f33c13f5599e574e0a64e0316d8731d7 Mon Sep 17 00:00:00 2001
From: Jacques Pienaar <jpienaar at google.com>
Date: Mon, 18 Dec 2023 15:57:20 -0800
Subject: [PATCH 3/6] Addressed review comments to move more to cmake
 conditionals

---
 mlir/CMakeLists.txt                           |   5 +-
 mlir/include/mlir/IR/PDLPatternMatch.h.inc    |   3 +
 mlir/include/mlir/IR/PatternMatch.h           |   1 -
 mlir/include/mlir/InitAllDialects.h           |   1 -
 mlir/include/mlir/InitAllExtensions.h         |   3 +-
 mlir/include/mlir/Rewrite/PatternApplicator.h |   1 -
 mlir/lib/IR/CMakeLists.txt                    |   7 +
 mlir/lib/IR/PDL/CMakeLists.txt                |   7 +
 mlir/lib/IR/PDL/PDLPatternMatch.cpp           | 133 ++++++++++++++++++
 mlir/lib/IR/PatternMatch.cpp                  | 120 ----------------
 mlir/lib/Rewrite/ByteCode.cpp                 |   3 +-
 mlir/lib/Rewrite/ByteCode.h                   |   1 +
 mlir/lib/Rewrite/CMakeLists.txt               |  39 +++--
 mlir/lib/Rewrite/FrozenRewritePatternSet.cpp  |   1 -
 mlir/lib/Transforms/Utils/CMakeLists.txt      |   2 +
 mlir/python/CMakeLists.txt                    |  38 ++---
 mlir/test/lib/Rewrite/CMakeLists.txt          |   1 +
 mlir/tools/mlir-opt/mlir-opt.cpp              |   8 +-
 18 files changed, 207 insertions(+), 167 deletions(-)
 create mode 100644 mlir/lib/IR/PDL/CMakeLists.txt
 create mode 100644 mlir/lib/IR/PDL/PDLPatternMatch.cpp

diff --git a/mlir/CMakeLists.txt b/mlir/CMakeLists.txt
index 3ff21ed0d5aa81..d085c6f261f883 100644
--- a/mlir/CMakeLists.txt
+++ b/mlir/CMakeLists.txt
@@ -180,12 +180,11 @@ include_directories( ${MLIR_INCLUDE_DIR})
 # Adding tools/mlir-tblgen here as calling add_tablegen sets some variables like
 # MLIR_TABLEGEN_EXE in PARENT_SCOPE which gets lost if that folder is included
 # from another directory like tools
-add_subdirectory(tools/mlir-tblgen)
 add_subdirectory(tools/mlir-linalg-ods-gen)
+add_subdirectory(tools/mlir-pdll)
+add_subdirectory(tools/mlir-tblgen)
 set(MLIR_TABLEGEN_EXE "${MLIR_TABLEGEN_EXE}" CACHE INTERNAL "")
 set(MLIR_TABLEGEN_TARGET "${MLIR_TABLEGEN_TARGET}" CACHE INTERNAL "")
-
-add_subdirectory(tools/mlir-pdll)
 set(MLIR_PDLL_TABLEGEN_EXE "${MLIR_PDLL_TABLEGEN_EXE}" CACHE INTERNAL "")
 set(MLIR_PDLL_TABLEGEN_TARGET "${MLIR_PDLL_TABLEGEN_TARGET}" CACHE INTERNAL "")
 
diff --git a/mlir/include/mlir/IR/PDLPatternMatch.h.inc b/mlir/include/mlir/IR/PDLPatternMatch.h.inc
index e4d63248bf1908..bd8135d4c309c6 100644
--- a/mlir/include/mlir/IR/PDLPatternMatch.h.inc
+++ b/mlir/include/mlir/IR/PDLPatternMatch.h.inc
@@ -9,6 +9,8 @@
 #ifndef MLIR_IR_PDLPATTERNMATCH_H
 #define MLIR_IR_PDLPATTERNMATCH_H
 
+#include "mlir/Config/mlir-config.h"
+
 #if MLIR_ENABLE_PDL
 #include "mlir/IR/Builders.h"
 #include "mlir/IR/BuiltinOps.h"
@@ -944,6 +946,7 @@ private:
   llvm::StringMap<PDLRewriteFunction> rewriteFunctions;
 };
 } // namespace mlir
+
 #else
 
 namespace mlir {
diff --git a/mlir/include/mlir/IR/PatternMatch.h b/mlir/include/mlir/IR/PatternMatch.h
index 46f49e8acffcdd..f37a0c7cd321bd 100644
--- a/mlir/include/mlir/IR/PatternMatch.h
+++ b/mlir/include/mlir/IR/PatternMatch.h
@@ -9,7 +9,6 @@
 #ifndef MLIR_IR_PATTERNMATCH_H
 #define MLIR_IR_PATTERNMATCH_H
 
-#include "mlir/Config/mlir-config.h"
 #include "mlir/IR/Builders.h"
 #include "mlir/IR/BuiltinOps.h"
 #include "llvm/ADT/FunctionExtras.h"
diff --git a/mlir/include/mlir/InitAllDialects.h b/mlir/include/mlir/InitAllDialects.h
index e7067ef476faf9..19a62cadaa2e04 100644
--- a/mlir/include/mlir/InitAllDialects.h
+++ b/mlir/include/mlir/InitAllDialects.h
@@ -14,7 +14,6 @@
 #ifndef MLIR_INITALLDIALECTS_H_
 #define MLIR_INITALLDIALECTS_H_
 
-#include "mlir/Config/mlir-config.h"
 #include "mlir/Dialect/AMDGPU/IR/AMDGPUDialect.h"
 #include "mlir/Dialect/AMX/AMXDialect.h"
 #include "mlir/Dialect/Affine/IR/AffineOps.h"
diff --git a/mlir/include/mlir/InitAllExtensions.h b/mlir/include/mlir/InitAllExtensions.h
index c3ccf68adc9318..c04ce850fb96f4 100644
--- a/mlir/include/mlir/InitAllExtensions.h
+++ b/mlir/include/mlir/InitAllExtensions.h
@@ -14,7 +14,6 @@
 #ifndef MLIR_INITALLEXTENSIONS_H_
 #define MLIR_INITALLEXTENSIONS_H_
 
-#include "mlir/Config/mlir-config.h"
 #include "mlir/Conversion/ArithToLLVM/ArithToLLVM.h"
 #include "mlir/Conversion/ComplexToLLVM/ComplexToLLVM.h"
 #include "mlir/Conversion/ControlFlowToLLVM/ControlFlowToLLVM.h"
@@ -67,6 +66,7 @@ inline void registerAllExtensions(DialectRegistry &registry) {
 
   // Register all transform dialect extensions.
   affine::registerTransformDialectExtension(registry);
+  bufferization::registerTransformDialectExtension(registry);
   func::registerTransformDialectExtension(registry);
   gpu::registerTransformDialectExtension(registry);
   linalg::registerTransformDialectExtension(registry);
@@ -76,7 +76,6 @@ inline void registerAllExtensions(DialectRegistry &registry) {
   sparse_tensor::registerTransformDialectExtension(registry);
   tensor::registerTransformDialectExtension(registry);
   transform::registerLoopExtension(registry);
-  bufferization::registerTransformDialectExtension(registry);
   transform::registerPDLExtension(registry);
   vector::registerTransformDialectExtension(registry);
 
diff --git a/mlir/include/mlir/Rewrite/PatternApplicator.h b/mlir/include/mlir/Rewrite/PatternApplicator.h
index 9b5280d1546281..f7871f819a273b 100644
--- a/mlir/include/mlir/Rewrite/PatternApplicator.h
+++ b/mlir/include/mlir/Rewrite/PatternApplicator.h
@@ -92,7 +92,6 @@ class PatternApplicator {
   /// The set of patterns that may match against any operation type, stable
   /// sorted by benefit.
   SmallVector<const RewritePattern *, 1> anyOpPatterns;
-
   /// The mutable state used during execution of the PDL bytecode.
   std::unique_ptr<detail::PDLByteCodeMutableState> mutableByteCodeState;
 };
diff --git a/mlir/lib/IR/CMakeLists.txt b/mlir/lib/IR/CMakeLists.txt
index 21bba11b851171..057a650cf78070 100644
--- a/mlir/lib/IR/CMakeLists.txt
+++ b/mlir/lib/IR/CMakeLists.txt
@@ -61,3 +61,10 @@ add_mlir_library(MLIRIR
   LINK_LIBS PUBLIC
   MLIRSupport
   )
+
+if(MLIR_ENABLE_PDL)
+  add_subdirectory(PDL)
+  target_link_libraries(MLIRIR PUBLIC
+    MLIRIRPDLPatternMatch)
+endif()
+
diff --git a/mlir/lib/IR/PDL/CMakeLists.txt b/mlir/lib/IR/PDL/CMakeLists.txt
new file mode 100644
index 00000000000000..08b7fe36fac096
--- /dev/null
+++ b/mlir/lib/IR/PDL/CMakeLists.txt
@@ -0,0 +1,7 @@
+add_mlir_library(MLIRIRPDLPatternMatch
+  PDLPatternMatch.cpp
+
+  ADDITIONAL_HEADER_DIRS
+  ${MLIR_MAIN_INCLUDE_DIR}/mlir/IR
+)
+
diff --git a/mlir/lib/IR/PDL/PDLPatternMatch.cpp b/mlir/lib/IR/PDL/PDLPatternMatch.cpp
new file mode 100644
index 00000000000000..89f6bbdaa27b8b
--- /dev/null
+++ b/mlir/lib/IR/PDL/PDLPatternMatch.cpp
@@ -0,0 +1,133 @@
+//===- PDLPatternMatch.cpp - Base classes for PDL pattern match ------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/IR/PatternMatch.h"
+#include "mlir/IR/IRMapping.h"
+#include "mlir/IR/Iterators.h"
+#include "mlir/IR/RegionKindInterface.h"
+
+using namespace mlir;
+
+//===----------------------------------------------------------------------===//
+// PDLValue
+//===----------------------------------------------------------------------===//
+
+void PDLValue::print(raw_ostream &os) const {
+  if (!value) {
+    os << "<NULL-PDLValue>";
+    return;
+  }
+  switch (kind) {
+  case Kind::Attribute:
+    os << cast<Attribute>();
+    break;
+  case Kind::Operation:
+    os << *cast<Operation *>();
+    break;
+  case Kind::Type:
+    os << cast<Type>();
+    break;
+  case Kind::TypeRange:
+    llvm::interleaveComma(cast<TypeRange>(), os);
+    break;
+  case Kind::Value:
+    os << cast<Value>();
+    break;
+  case Kind::ValueRange:
+    llvm::interleaveComma(cast<ValueRange>(), os);
+    break;
+  }
+}
+
+void PDLValue::print(raw_ostream &os, Kind kind) {
+  switch (kind) {
+  case Kind::Attribute:
+    os << "Attribute";
+    break;
+  case Kind::Operation:
+    os << "Operation";
+    break;
+  case Kind::Type:
+    os << "Type";
+    break;
+  case Kind::TypeRange:
+    os << "TypeRange";
+    break;
+  case Kind::Value:
+    os << "Value";
+    break;
+  case Kind::ValueRange:
+    os << "ValueRange";
+    break;
+  }
+}
+
+//===----------------------------------------------------------------------===//
+// PDLPatternModule
+//===----------------------------------------------------------------------===//
+
+void PDLPatternModule::mergeIn(PDLPatternModule &&other) {
+  // Ignore the other module if it has no patterns.
+  if (!other.pdlModule)
+    return;
+
+  // Steal the functions and config of the other module.
+  for (auto &it : other.constraintFunctions)
+    registerConstraintFunction(it.first(), std::move(it.second));
+  for (auto &it : other.rewriteFunctions)
+    registerRewriteFunction(it.first(), std::move(it.second));
+  for (auto &it : other.configs)
+    configs.emplace_back(std::move(it));
+  for (auto &it : other.configMap)
+    configMap.insert(it);
+
+  // Steal the other state if we have no patterns.
+  if (!pdlModule) {
+    pdlModule = std::move(other.pdlModule);
+    return;
+  }
+
+  // Merge the pattern operations from the other module into this one.
+  Block *block = pdlModule->getBody();
+  block->getOperations().splice(block->end(),
+                                other.pdlModule->getBody()->getOperations());
+}
+
+void PDLPatternModule::attachConfigToPatterns(ModuleOp module,
+                                              PDLPatternConfigSet &configSet) {
+  // Attach the configuration to the symbols within the module. We only add
+  // to symbols to avoid hardcoding any specific operation names here (given
+  // that we don't depend on any PDL dialect). We can't use
+  // cast<SymbolOpInterface> here because patterns may be optional symbols.
+  module->walk([&](Operation *op) {
+    if (op->hasTrait<SymbolOpInterface::Trait>())
+      configMap[op] = &configSet;
+  });
+}
+
+//===----------------------------------------------------------------------===//
+// Function Registry
+
+void PDLPatternModule::registerConstraintFunction(
+    StringRef name, PDLConstraintFunction constraintFn) {
+  // TODO: Is it possible to diagnose when `name` is already registered to
+  // a function that is not equivalent to `constraintFn`?
+  // Allow existing mappings in the case multiple patterns depend on the same
+  // constraint.
+  constraintFunctions.try_emplace(name, std::move(constraintFn));
+}
+
+void PDLPatternModule::registerRewriteFunction(StringRef name,
+                                               PDLRewriteFunction rewriteFn) {
+  // TODO: Is it possible to diagnose when `name` is already registered to
+  // a function that is not equivalent to `rewriteFn`?
+  // Allow existing mappings in the case multiple patterns depend on the same
+  // rewrite.
+  rewriteFunctions.try_emplace(name, std::move(rewriteFn));
+}
+
diff --git a/mlir/lib/IR/PatternMatch.cpp b/mlir/lib/IR/PatternMatch.cpp
index c9481687b8275f..5e788cdb4897d3 100644
--- a/mlir/lib/IR/PatternMatch.cpp
+++ b/mlir/lib/IR/PatternMatch.cpp
@@ -98,126 +98,6 @@ LogicalResult RewritePattern::match(Operation *op) const {
 /// Out-of-line vtable anchor.
 void RewritePattern::anchor() {}
 
-#if MLIR_ENABLE_PDL
-//===----------------------------------------------------------------------===//
-// PDLValue
-//===----------------------------------------------------------------------===//
-
-void PDLValue::print(raw_ostream &os) const {
-  if (!value) {
-    os << "<NULL-PDLValue>";
-    return;
-  }
-  switch (kind) {
-  case Kind::Attribute:
-    os << cast<Attribute>();
-    break;
-  case Kind::Operation:
-    os << *cast<Operation *>();
-    break;
-  case Kind::Type:
-    os << cast<Type>();
-    break;
-  case Kind::TypeRange:
-    llvm::interleaveComma(cast<TypeRange>(), os);
-    break;
-  case Kind::Value:
-    os << cast<Value>();
-    break;
-  case Kind::ValueRange:
-    llvm::interleaveComma(cast<ValueRange>(), os);
-    break;
-  }
-}
-
-void PDLValue::print(raw_ostream &os, Kind kind) {
-  switch (kind) {
-  case Kind::Attribute:
-    os << "Attribute";
-    break;
-  case Kind::Operation:
-    os << "Operation";
-    break;
-  case Kind::Type:
-    os << "Type";
-    break;
-  case Kind::TypeRange:
-    os << "TypeRange";
-    break;
-  case Kind::Value:
-    os << "Value";
-    break;
-  case Kind::ValueRange:
-    os << "ValueRange";
-    break;
-  }
-}
-
-//===----------------------------------------------------------------------===//
-// PDLPatternModule
-//===----------------------------------------------------------------------===//
-
-void PDLPatternModule::mergeIn(PDLPatternModule &&other) {
-  // Ignore the other module if it has no patterns.
-  if (!other.pdlModule)
-    return;
-
-  // Steal the functions and config of the other module.
-  for (auto &it : other.constraintFunctions)
-    registerConstraintFunction(it.first(), std::move(it.second));
-  for (auto &it : other.rewriteFunctions)
-    registerRewriteFunction(it.first(), std::move(it.second));
-  for (auto &it : other.configs)
-    configs.emplace_back(std::move(it));
-  for (auto &it : other.configMap)
-    configMap.insert(it);
-
-  // Steal the other state if we have no patterns.
-  if (!pdlModule) {
-    pdlModule = std::move(other.pdlModule);
-    return;
-  }
-
-  // Merge the pattern operations from the other module into this one.
-  Block *block = pdlModule->getBody();
-  block->getOperations().splice(block->end(),
-                                other.pdlModule->getBody()->getOperations());
-}
-
-void PDLPatternModule::attachConfigToPatterns(ModuleOp module,
-                                              PDLPatternConfigSet &configSet) {
-  // Attach the configuration to the symbols within the module. We only add
-  // to symbols to avoid hardcoding any specific operation names here (given
-  // that we don't depend on any PDL dialect). We can't use
-  // cast<SymbolOpInterface> here because patterns may be optional symbols.
-  module->walk([&](Operation *op) {
-    if (op->hasTrait<SymbolOpInterface::Trait>())
-      configMap[op] = &configSet;
-  });
-}
-
-//===----------------------------------------------------------------------===//
-// Function Registry
-
-void PDLPatternModule::registerConstraintFunction(
-    StringRef name, PDLConstraintFunction constraintFn) {
-  // TODO: Is it possible to diagnose when `name` is already registered to
-  // a function that is not equivalent to `constraintFn`?
-  // Allow existing mappings in the case multiple patterns depend on the same
-  // constraint.
-  constraintFunctions.try_emplace(name, std::move(constraintFn));
-}
-
-void PDLPatternModule::registerRewriteFunction(StringRef name,
-                                               PDLRewriteFunction rewriteFn) {
-  // TODO: Is it possible to diagnose when `name` is already registered to
-  // a function that is not equivalent to `rewriteFn`?
-  // Allow existing mappings in the case multiple patterns depend on the same
-  // rewrite.
-  rewriteFunctions.try_emplace(name, std::move(rewriteFn));
-}
-#endif // MLIR_ENABLE_PDL
-
 //===----------------------------------------------------------------------===//
 // RewriterBase
 //===----------------------------------------------------------------------===//
diff --git a/mlir/lib/Rewrite/ByteCode.cpp b/mlir/lib/Rewrite/ByteCode.cpp
index 31b164c2a9a6e4..01f58eee26398a 100644
--- a/mlir/lib/Rewrite/ByteCode.cpp
+++ b/mlir/lib/Rewrite/ByteCode.cpp
@@ -10,7 +10,6 @@
 //
 //===----------------------------------------------------------------------===//
 
-#if MLIR_ENABLE_PDL
 #include "ByteCode.h"
 #include "mlir/Analysis/Liveness.h"
 #include "mlir/Dialect/PDL/IR/PDLTypes.h"
@@ -2334,4 +2333,4 @@ LogicalResult PDLByteCode::rewrite(PatternRewriter &rewriter,
   }
   return result;
 }
-#endif // MLIR_ENABLE_PDL
+
diff --git a/mlir/lib/Rewrite/ByteCode.h b/mlir/lib/Rewrite/ByteCode.h
index fa80ed0045f29b..0b0b8fbf2945a9 100644
--- a/mlir/lib/Rewrite/ByteCode.h
+++ b/mlir/lib/Rewrite/ByteCode.h
@@ -225,6 +225,7 @@ class PDLByteCode {
 
 } // namespace detail
 } // namespace mlir
+
 #else
 
 namespace mlir::detail {
diff --git a/mlir/lib/Rewrite/CMakeLists.txt b/mlir/lib/Rewrite/CMakeLists.txt
index 8ce94014af2a07..828e3bc5677d9e 100644
--- a/mlir/lib/Rewrite/CMakeLists.txt
+++ b/mlir/lib/Rewrite/CMakeLists.txt
@@ -1,16 +1,6 @@
 set(LLVM_OPTIONAL_SOURCES ByteCode.cpp)
 
-if(MLIR_ENABLE_PDL)
-set(MLIRRewritePDLDeps
-  MLIRPDLDialect
-  MLIRPDLInterpDialect
-  MLIRPDLToPDLInterp)
-else()
-  set(MLIRRewritePDLDeps)
-endif()
-
 add_mlir_library(MLIRRewrite
-  ByteCode.cpp
   FrozenRewritePatternSet.cpp
   PatternApplicator.cpp
 
@@ -22,8 +12,31 @@ add_mlir_library(MLIRRewrite
 
   LINK_LIBS PUBLIC
   MLIRIR
-  MLIRPDLDialect
-  MLIRPDLInterpDialect
-  MLIRPDLToPDLInterp
   MLIRSideEffectInterfaces
   )
+
+if(MLIR_ENABLE_PDL)
+  add_mlir_library(MLIRRewritePDL
+    ByteCode.cpp
+
+    ADDITIONAL_HEADER_DIRS
+    ${MLIR_MAIN_INCLUDE_DIR}/mlir/Rewrite
+
+    DEPENDS
+    mlir-generic-headers
+
+    LINK_LIBS PUBLIC
+    MLIRIR
+    MLIRPDLDialect
+    MLIRPDLInterpDialect
+    MLIRPDLToPDLInterp
+    MLIRSideEffectInterfaces
+  )
+
+  target_link_libraries(MLIRRewrite PUBLIC
+    MLIRPDLDialect
+    MLIRPDLInterpDialect
+    MLIRPDLToPDLInterp
+    MLIRRewritePDL)
+endif()
+
diff --git a/mlir/lib/Rewrite/FrozenRewritePatternSet.cpp b/mlir/lib/Rewrite/FrozenRewritePatternSet.cpp
index 1b251d7d5ef593..7ea6495820ab6c 100644
--- a/mlir/lib/Rewrite/FrozenRewritePatternSet.cpp
+++ b/mlir/lib/Rewrite/FrozenRewritePatternSet.cpp
@@ -17,7 +17,6 @@ using namespace mlir;
 
 // Include the PDL rewrite support.
 #if MLIR_ENABLE_PDL
-#include "PDLRewrite.cpp"
 #include "mlir/Conversion/PDLToPDLInterp/PDLToPDLInterp.h"
 #include "mlir/Dialect/PDL/IR/PDLOps.h"
 
diff --git a/mlir/lib/Transforms/Utils/CMakeLists.txt b/mlir/lib/Transforms/Utils/CMakeLists.txt
index 1c608e0634a67e..6411f28fb6d4da 100644
--- a/mlir/lib/Transforms/Utils/CMakeLists.txt
+++ b/mlir/lib/Transforms/Utils/CMakeLists.txt
@@ -23,3 +23,5 @@ add_mlir_library(MLIRTransformUtils
   MLIRSubsetOpInterface
   MLIRRewrite
   )
+
+
diff --git a/mlir/python/CMakeLists.txt b/mlir/python/CMakeLists.txt
index f966e4c491fa69..41d91cf6778338 100644
--- a/mlir/python/CMakeLists.txt
+++ b/mlir/python/CMakeLists.txt
@@ -146,13 +146,13 @@ declare_mlir_dialect_python_bindings(
   GEN_ENUM_BINDINGS)
 
 declare_mlir_dialect_extension_python_bindings(
-  ADD_TO_PARENT MLIRPythonSources.Dialects
-  ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/mlir"
-    TD_FILE dialects/TransformPDLExtensionOps.td
-    SOURCES
-      dialects/transform/pdl.py
-    DIALECT_NAME transform
-    EXTENSION_NAME transform_pdl_extension)
+ADD_TO_PARENT MLIRPythonSources.Dialects
+ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/mlir"
+  TD_FILE dialects/TransformPDLExtensionOps.td
+  SOURCES
+    dialects/transform/pdl.py
+  DIALECT_NAME transform
+  EXTENSION_NAME transform_pdl_extension)
 
 declare_mlir_dialect_python_bindings(
   ADD_TO_PARENT MLIRPythonSources.Dialects
@@ -481,18 +481,18 @@ declare_mlir_python_extension(MLIRPythonExtension.Dialects.Quant.Pybind
     MLIRCAPIQuant
 )
 
-  declare_mlir_python_extension(MLIRPythonExtension.Dialects.PDL.Pybind
-    MODULE_NAME _mlirDialectsPDL
-    ADD_TO_PARENT MLIRPythonSources.Dialects.pdl
-    ROOT_DIR "${PYTHON_SOURCE_DIR}"
-    SOURCES
-      DialectPDL.cpp
-    PRIVATE_LINK_LIBS
-      LLVMSupport
-    EMBED_CAPI_LINK_LIBS
-      MLIRCAPIIR
-      MLIRCAPIPDL
-  )
+declare_mlir_python_extension(MLIRPythonExtension.Dialects.PDL.Pybind
+  MODULE_NAME _mlirDialectsPDL
+  ADD_TO_PARENT MLIRPythonSources.Dialects.pdl
+  ROOT_DIR "${PYTHON_SOURCE_DIR}"
+  SOURCES
+    DialectPDL.cpp
+  PRIVATE_LINK_LIBS
+    LLVMSupport
+  EMBED_CAPI_LINK_LIBS
+    MLIRCAPIIR
+    MLIRCAPIPDL
+)
 
 declare_mlir_python_extension(MLIRPythonExtension.Dialects.SparseTensor.Pybind
   MODULE_NAME _mlirDialectsSparseTensor
diff --git a/mlir/test/lib/Rewrite/CMakeLists.txt b/mlir/test/lib/Rewrite/CMakeLists.txt
index 7ab38af20738b6..fd5d5d58616018 100644
--- a/mlir/test/lib/Rewrite/CMakeLists.txt
+++ b/mlir/test/lib/Rewrite/CMakeLists.txt
@@ -13,3 +13,4 @@ add_mlir_library(MLIRTestRewrite
   MLIRSupport
   MLIRTransformUtils
   )
+
diff --git a/mlir/tools/mlir-opt/mlir-opt.cpp b/mlir/tools/mlir-opt/mlir-opt.cpp
index e550edfa2d131f..4b7533d8b66329 100644
--- a/mlir/tools/mlir-opt/mlir-opt.cpp
+++ b/mlir/tools/mlir-opt/mlir-opt.cpp
@@ -245,6 +245,8 @@ void registerTestPasses() {
   mlir::test::registerTestOneToNTypeConversionPass();
   mlir::test::registerTestOpaqueLoc();
   mlir::test::registerTestPadFusion();
+  mlir::test::registerTestPDLByteCodePass();
+  mlir::test::registerTestPDLLPasses();
   mlir::test::registerTestRecursiveTypesPass();
   mlir::test::registerTestSCFUtilsPass();
   mlir::test::registerTestSCFWhileOpBuilderPass();
@@ -254,6 +256,8 @@ void registerTestPasses() {
   mlir::test::registerTestTensorTransforms();
   mlir::test::registerTestTilingInterface();
   mlir::test::registerTestTopologicalSortAnalysisPass();
+  mlir::test::registerTestTransformDialectEraseSchedulePass();
+  mlir::test::registerTestTransformDialectInterpreterPass();
   mlir::test::registerTestVectorLowerings();
   mlir::test::registerTestVectorReductionToSPIRVDotProd();
   mlir::test::registerTestNvgpuLowerings();
@@ -261,10 +265,6 @@ void registerTestPasses() {
 #if MLIR_ENABLE_PDL
   mlir::test::registerTestDialectConversionPasses();
 #endif
-  mlir::test::registerTestPDLByteCodePass();
-  mlir::test::registerTestPDLLPasses();
-  mlir::test::registerTestTransformDialectEraseSchedulePass();
-  mlir::test::registerTestTransformDialectInterpreterPass();
 }
 #endif
 

>From 1ccfb2356115f4fc7ae4eee32336bb068c994974 Mon Sep 17 00:00:00 2001
From: Jacques Pienaar <jpienaar at google.com>
Date: Mon, 18 Dec 2023 15:58:15 -0800
Subject: [PATCH 4/6] clang-format

---
 mlir/lib/IR/PDL/PDLPatternMatch.cpp | 6 +++---
 mlir/lib/Rewrite/ByteCode.cpp       | 1 -
 2 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/mlir/lib/IR/PDL/PDLPatternMatch.cpp b/mlir/lib/IR/PDL/PDLPatternMatch.cpp
index 89f6bbdaa27b8b..da07cc462a5a13 100644
--- a/mlir/lib/IR/PDL/PDLPatternMatch.cpp
+++ b/mlir/lib/IR/PDL/PDLPatternMatch.cpp
@@ -1,4 +1,5 @@
-//===- PDLPatternMatch.cpp - Base classes for PDL pattern match ------------===//
+//===- PDLPatternMatch.cpp - Base classes for PDL pattern match
+//------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,9 +7,9 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "mlir/IR/PatternMatch.h"
 #include "mlir/IR/IRMapping.h"
 #include "mlir/IR/Iterators.h"
+#include "mlir/IR/PatternMatch.h"
 #include "mlir/IR/RegionKindInterface.h"
 
 using namespace mlir;
@@ -130,4 +131,3 @@ void PDLPatternModule::registerRewriteFunction(StringRef name,
   // rewrite.
   rewriteFunctions.try_emplace(name, std::move(rewriteFn));
 }
-
diff --git a/mlir/lib/Rewrite/ByteCode.cpp b/mlir/lib/Rewrite/ByteCode.cpp
index 01f58eee26398a..6e6992dcdeea78 100644
--- a/mlir/lib/Rewrite/ByteCode.cpp
+++ b/mlir/lib/Rewrite/ByteCode.cpp
@@ -2333,4 +2333,3 @@ LogicalResult PDLByteCode::rewrite(PatternRewriter &rewriter,
   }
   return result;
 }
-

>From f6d878fad319823ee704298b4832fba31fe34bc7 Mon Sep 17 00:00:00 2001
From: Jacques Pienaar <jpienaar at google.com>
Date: Tue, 19 Dec 2023 10:49:03 -0800
Subject: [PATCH 5/6] Fixup bazel side

---
 mlir/lib/Transforms/Utils/DialectConversion.cpp   | 1 +
 utils/bazel/llvm-project-overlay/mlir/BUILD.bazel | 5 ++++-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index f9e0db11a92e2c..b13f3f8d404712 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "mlir/Transforms/DialectConversion.h"
+#include "mlir/Config/mlir-config.h"
 #include "mlir/IR/Block.h"
 #include "mlir/IR/Builders.h"
 #include "mlir/IR/BuiltinOps.h"
diff --git a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel
index 8606a81e8c542c..370d0547591250 100644
--- a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel
@@ -35,7 +35,7 @@ expand_template(
     substitutions = {
         "#cmakedefine01 MLIR_ENABLE_EXPENSIVE_PATTERN_API_CHECKS": "#define MLIR_ENABLE_EXPENSIVE_PATTERN_API_CHECKS 0",
         "#cmakedefine MLIR_GREEDY_REWRITE_RANDOMIZER_SEED ${MLIR_GREEDY_REWRITE_RANDOMIZER_SEED}": "/* #undef MLIR_GREEDY_REWRITE_RANDOMIZER_SEED */",
-        "#cmakedefine01 MLIR_ENABLE_PDL ${MLIR_ENABLE_PDL}": "#define MLIR_ENABLE_PDL 1",
+        "#cmakedefine01 MLIR_ENABLE_PDL": "#define MLIR_ENABLE_PDL 1",
     },
     template = "include/mlir/Config/mlir-config.h.cmake",
 )
@@ -319,11 +319,13 @@ cc_library(
     srcs = glob([
         "lib/IR/*.cpp",
         "lib/IR/*.h",
+        "lib/IR/PDL/*.cpp",
         "lib/Bytecode/Reader/*.h",
         "lib/Bytecode/Writer/*.h",
         "lib/Bytecode/*.h",
     ]) + [
         "lib/Bytecode/BytecodeOpInterface.cpp",
+        "include/mlir/IR/PDLPatternMatch.h.inc",
     ],
     hdrs = glob([
         "include/mlir/IR/*.h",
@@ -346,6 +348,7 @@ cc_library(
         ":BuiltinTypesIncGen",
         ":BytecodeOpInterfaceIncGen",
         ":CallOpInterfacesIncGen",
+        ":config",
         ":DataLayoutInterfacesIncGen",
         ":InferTypeOpInterfaceIncGen",
         ":OpAsmInterfaceIncGen",

>From 3c7402a41d437af9792e041ff72786bdd41fe7df Mon Sep 17 00:00:00 2001
From: Jacques Pienaar <jpienaar at google.com>
Date: Tue, 19 Dec 2023 11:03:04 -0800
Subject: [PATCH 6/6] Address review comments

---
 mlir/include/mlir/IR/PatternMatch.h      | 3 ++-
 mlir/lib/Tools/CMakeLists.txt            | 2 +-
 mlir/lib/Transforms/Utils/CMakeLists.txt | 2 --
 3 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/mlir/include/mlir/IR/PatternMatch.h b/mlir/include/mlir/IR/PatternMatch.h
index f37a0c7cd321bd..9b4fa65bff49e1 100644
--- a/mlir/include/mlir/IR/PatternMatch.h
+++ b/mlir/include/mlir/IR/PatternMatch.h
@@ -944,7 +944,8 @@ class RewritePatternSet {
   MLIRContext *const context;
   NativePatternListT nativePatterns;
 
-  // Technically not needed if PDL not enabled. Stubs enable less ifdefs.
+  // Patterns expressed with PDL. This will compile to a stub class when PDL is
+  // not enabled.
   PDLPatternModule pdlPatterns;
 };
 
diff --git a/mlir/lib/Tools/CMakeLists.txt b/mlir/lib/Tools/CMakeLists.txt
index 80d4e741bffd92..01270fa4b0fc34 100644
--- a/mlir/lib/Tools/CMakeLists.txt
+++ b/mlir/lib/Tools/CMakeLists.txt
@@ -1,11 +1,11 @@
 add_subdirectory(lsp-server-support)
 add_subdirectory(mlir-lsp-server)
 add_subdirectory(mlir-opt)
+add_subdirectory(mlir-pdll-lsp-server)
 add_subdirectory(mlir-query)
 add_subdirectory(mlir-reduce)
 add_subdirectory(mlir-tblgen)
 add_subdirectory(mlir-translate)
 add_subdirectory(PDLL)
-add_subdirectory(mlir-pdll-lsp-server)
 add_subdirectory(Plugins)
 add_subdirectory(tblgen-lsp-server)
diff --git a/mlir/lib/Transforms/Utils/CMakeLists.txt b/mlir/lib/Transforms/Utils/CMakeLists.txt
index 6411f28fb6d4da..1c608e0634a67e 100644
--- a/mlir/lib/Transforms/Utils/CMakeLists.txt
+++ b/mlir/lib/Transforms/Utils/CMakeLists.txt
@@ -23,5 +23,3 @@ add_mlir_library(MLIRTransformUtils
   MLIRSubsetOpInterface
   MLIRRewrite
   )
-
-



More information about the Mlir-commits mailing list