From 4a6b31b8d87748f48756674015e00d89e1880dbf Mon Sep 17 00:00:00 2001 From: Alex Zinenko Date: Mon, 17 Jul 2023 12:57:55 +0000 Subject: [PATCH] [mlir] NFC: untangle SCF Patterns.h and Transforms.h These two headers both contained a strange mix of definitions related to both patterns and non-pattern transforms. Put patterns and "populate" functions into Patterns.h and standalone transforms into Transforms.h. Depends On: D155223 Reviewed By: nicolasvasilache Differential Revision: https://reviews.llvm.org/D155454 --- .../mlir/Dialect/SCF/Transforms/Patterns.h | 57 ++++++++++-------- .../mlir/Dialect/SCF/Transforms/Transforms.h | 59 ++++++++----------- .../NVGPU/TransformOps/NVGPUTransformOps.cpp | 1 - mlir/lib/Dialect/SCF/Transforms/Bufferize.cpp | 2 +- .../SCF/Transforms/LoopCanonicalization.cpp | 2 +- .../Transforms/StructuralTypeConversions.cpp | 3 +- .../Transforms/SparseTensorPasses.cpp | 2 +- .../TestOneToNTypeConversionPass.cpp | 2 +- .../Linalg/TestLinalgFusionTransforms.cpp | 2 +- mlir/test/lib/Dialect/SCF/TestSCFUtils.cpp | 2 +- 10 files changed, 64 insertions(+), 68 deletions(-) diff --git a/mlir/include/mlir/Dialect/SCF/Transforms/Patterns.h b/mlir/include/mlir/Dialect/SCF/Transforms/Patterns.h index e6df65ae347c..d8550e99bfbc 100644 --- a/mlir/include/mlir/Dialect/SCF/Transforms/Patterns.h +++ b/mlir/include/mlir/Dialect/SCF/Transforms/Patterns.h @@ -14,31 +14,11 @@ #include "mlir/IR/PatternMatch.h" namespace mlir { + +class ConversionTarget; +class TypeConverter; + namespace scf { -/// Generate a pipelined version of the scf.for loop based on the schedule given -/// as option. This applies the mechanical transformation of changing the loop -/// and generating the prologue/epilogue for the pipelining and doesn't make any -/// decision regarding the schedule. -/// Based on the options the loop is split into several stages. -/// The transformation assumes that the scheduling given by user is valid. -/// For example if we break a loop into 3 stages named S0, S1, S2 we would -/// generate the following code with the number in parenthesis as the iteration -/// index: -/// -/// S0(0) // Prologue -/// S0(1) S1(0) // Prologue -/// scf.for %I = %C0 to %N - 2 { -/// S0(I+2) S1(I+1) S2(I) // Pipelined kernel -/// } -/// S1(N) S2(N-1) // Epilogue -/// S2(N) // Epilogue -/// -/// If `modifiedIR` is provided, it will be set to a value that indicates -/// whether pipelining modified the IR before failing, signaling to the caller -/// whether they can proceed with different transformations. -FailureOr pipelineForLoop(RewriterBase &rewriter, ForOp forOp, - const PipeliningOption &options, - bool *modifiedIR = nullptr); // TODO: such patterns should be auto-generated. class ForLoopPipeliningPattern : public OpRewritePattern { @@ -60,6 +40,35 @@ protected: PipeliningOption options; }; +/// Populates patterns for SCF structural type conversions and sets up the +/// provided ConversionTarget with the appropriate legality configuration for +/// the ops to get converted properly. +/// +/// A "structural" type conversion is one where the underlying ops are +/// completely agnostic to the actual types involved and simply need to update +/// their types. An example of this is scf.if -- the scf.if op and the +/// corresponding scf.yield ops need to update their types accordingly to the +/// TypeConverter, but otherwise don't care what type conversions are happening. +void populateSCFStructuralTypeConversionsAndLegality( + TypeConverter &typeConverter, RewritePatternSet &patterns, + ConversionTarget &target); + +/// Populates the provided pattern set with patterns that do 1:N type +/// conversions on (some) SCF ops. This is intended to be used with +/// applyPartialOneToNConversion. +void populateSCFStructuralOneToNTypeConversions(TypeConverter &typeConverter, + RewritePatternSet &patterns); + +/// Populate patterns for SCF software pipelining transformation. See the +/// ForLoopPipeliningPattern for the transformation details. +void populateSCFLoopPipeliningPatterns(RewritePatternSet &patterns, + const PipeliningOption &options); + +/// Populate patterns for canonicalizing operations inside SCF loop bodies. +/// At the moment, only affine.min/max computations with iteration variables, +/// loop bounds and loop steps are canonicalized. +void populateSCFForLoopCanonicalizationPatterns(RewritePatternSet &patterns); + } // namespace scf } // namespace mlir diff --git a/mlir/include/mlir/Dialect/SCF/Transforms/Transforms.h b/mlir/include/mlir/Dialect/SCF/Transforms/Transforms.h index cdd2b1b2d861..347beb9e4c64 100644 --- a/mlir/include/mlir/Dialect/SCF/Transforms/Transforms.h +++ b/mlir/include/mlir/Dialect/SCF/Transforms/Transforms.h @@ -19,18 +19,11 @@ namespace mlir { -class AffineMap; -class ConversionTarget; struct LogicalResult; -class MLIRContext; class Region; class RewriterBase; -class TypeConverter; -class RewritePatternSet; class Operation; class Value; -class ValueRange; -class PatternRewriter; namespace scf { @@ -107,25 +100,6 @@ std::pair tileParallelLoop(ParallelOp op, llvm::ArrayRef tileSizes, bool noMinMaxBounds); -/// Populates patterns for SCF structural type conversions and sets up the -/// provided ConversionTarget with the appropriate legality configuration for -/// the ops to get converted properly. -/// -/// A "structural" type conversion is one where the underlying ops are -/// completely agnostic to the actual types involved and simply need to update -/// their types. An example of this is scf.if -- the scf.if op and the -/// corresponding scf.yield ops need to update their types accordingly to the -/// TypeConverter, but otherwise don't care what type conversions are happening. -void populateSCFStructuralTypeConversionsAndLegality( - TypeConverter &typeConverter, RewritePatternSet &patterns, - ConversionTarget &target); - -/// Populates the provided pattern set with patterns that do 1:N type -/// conversions on (some) SCF ops. This is intended to be used with -/// applyPartialOneToNConversion. -void populateSCFStructuralOneToNTypeConversions(TypeConverter &typeConverter, - RewritePatternSet &patterns); - /// Options to dictate how loops should be pipelined. struct PipeliningOption { /// Lambda returning all the operation in the forOp, with their stage, in the @@ -167,15 +141,30 @@ struct PipeliningOption { // TODO: add option to decide if the prologue should be peeled. }; -/// Populate patterns for SCF software pipelining transformation. See the -/// ForLoopPipeliningPattern for the transformation details. -void populateSCFLoopPipeliningPatterns(RewritePatternSet &patterns, - const PipeliningOption &options); - -/// Populate patterns for canonicalizing operations inside SCF loop bodies. -/// At the moment, only affine.min/max computations with iteration variables, -/// loop bounds and loop steps are canonicalized. -void populateSCFForLoopCanonicalizationPatterns(RewritePatternSet &patterns); +/// Generate a pipelined version of the scf.for loop based on the schedule given +/// as option. This applies the mechanical transformation of changing the loop +/// and generating the prologue/epilogue for the pipelining and doesn't make any +/// decision regarding the schedule. +/// Based on the options the loop is split into several stages. +/// The transformation assumes that the scheduling given by user is valid. +/// For example if we break a loop into 3 stages named S0, S1, S2 we would +/// generate the following code with the number in parenthesis as the iteration +/// index: +/// +/// S0(0) // Prologue +/// S0(1) S1(0) // Prologue +/// scf.for %I = %C0 to %N - 2 { +/// S0(I+2) S1(I+1) S2(I) // Pipelined kernel +/// } +/// S1(N) S2(N-1) // Epilogue +/// S2(N) // Epilogue +/// +/// If `modifiedIR` is provided, it will be set to a value that indicates +/// whether pipelining modified the IR before failing, signaling to the caller +/// whether they can proceed with different transformations. +FailureOr pipelineForLoop(RewriterBase &rewriter, ForOp forOp, + const PipeliningOption &options, + bool *modifiedIR = nullptr); } // namespace scf } // namespace mlir diff --git a/mlir/lib/Dialect/NVGPU/TransformOps/NVGPUTransformOps.cpp b/mlir/lib/Dialect/NVGPU/TransformOps/NVGPUTransformOps.cpp index 94a61d7de87e..b194012f8563 100644 --- a/mlir/lib/Dialect/NVGPU/TransformOps/NVGPUTransformOps.cpp +++ b/mlir/lib/Dialect/NVGPU/TransformOps/NVGPUTransformOps.cpp @@ -17,7 +17,6 @@ #include "mlir/Dialect/MemRef/IR/MemRef.h" #include "mlir/Dialect/NVGPU/IR/NVGPUDialect.h" #include "mlir/Dialect/SCF/IR/SCF.h" -#include "mlir/Dialect/SCF/Transforms/Patterns.h" #include "mlir/Dialect/SCF/Transforms/Transforms.h" #include "mlir/Dialect/Utils/IndexingUtils.h" #include "mlir/Dialect/Vector/IR/VectorOps.h" diff --git a/mlir/lib/Dialect/SCF/Transforms/Bufferize.cpp b/mlir/lib/Dialect/SCF/Transforms/Bufferize.cpp index f2f71d3e5b16..21c618ab633f 100644 --- a/mlir/lib/Dialect/SCF/Transforms/Bufferize.cpp +++ b/mlir/lib/Dialect/SCF/Transforms/Bufferize.cpp @@ -12,7 +12,7 @@ #include "mlir/Dialect/Bufferization/Transforms/Bufferize.h" #include "mlir/Dialect/MemRef/IR/MemRef.h" #include "mlir/Dialect/SCF/IR/SCF.h" -#include "mlir/Dialect/SCF/Transforms/Transforms.h" +#include "mlir/Dialect/SCF/Transforms/Patterns.h" #include "mlir/Transforms/DialectConversion.h" namespace mlir { diff --git a/mlir/lib/Dialect/SCF/Transforms/LoopCanonicalization.cpp b/mlir/lib/Dialect/SCF/Transforms/LoopCanonicalization.cpp index 99591493d132..1da10ddd6371 100644 --- a/mlir/lib/Dialect/SCF/Transforms/LoopCanonicalization.cpp +++ b/mlir/lib/Dialect/SCF/Transforms/LoopCanonicalization.cpp @@ -16,7 +16,7 @@ #include "mlir/Dialect/Affine/IR/AffineOps.h" #include "mlir/Dialect/MemRef/IR/MemRef.h" #include "mlir/Dialect/SCF/IR/SCF.h" -#include "mlir/Dialect/SCF/Transforms/Transforms.h" +#include "mlir/Dialect/SCF/Transforms/Patterns.h" #include "mlir/Dialect/SCF/Utils/AffineCanonicalizationUtils.h" #include "mlir/Dialect/Tensor/IR/Tensor.h" #include "mlir/IR/PatternMatch.h" diff --git a/mlir/lib/Dialect/SCF/Transforms/StructuralTypeConversions.cpp b/mlir/lib/Dialect/SCF/Transforms/StructuralTypeConversions.cpp index 487aa0d7cf6a..9a1fa1871ffa 100644 --- a/mlir/lib/Dialect/SCF/Transforms/StructuralTypeConversions.cpp +++ b/mlir/lib/Dialect/SCF/Transforms/StructuralTypeConversions.cpp @@ -7,8 +7,7 @@ //===----------------------------------------------------------------------===// #include "mlir/Dialect/SCF/IR/SCF.h" -#include "mlir/Dialect/SCF/Transforms/Passes.h" -#include "mlir/Dialect/SCF/Transforms/Transforms.h" +#include "mlir/Dialect/SCF/Transforms/Patterns.h" #include "mlir/Transforms/DialectConversion.h" #include diff --git a/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorPasses.cpp b/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorPasses.cpp index f59e6ed346c1..cfe3fe881450 100644 --- a/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorPasses.cpp +++ b/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorPasses.cpp @@ -15,7 +15,7 @@ #include "mlir/Dialect/GPU/IR/GPUDialect.h" #include "mlir/Dialect/LLVMIR/LLVMDialect.h" #include "mlir/Dialect/Linalg/Transforms/Transforms.h" -#include "mlir/Dialect/SCF/Transforms/Transforms.h" +#include "mlir/Dialect/SCF/Transforms/Patterns.h" #include "mlir/Dialect/SparseTensor/IR/SparseTensor.h" #include "mlir/Dialect/SparseTensor/Transforms/Passes.h" #include "mlir/Dialect/Tensor/IR/Tensor.h" diff --git a/mlir/test/lib/Conversion/OneToNTypeConversion/TestOneToNTypeConversionPass.cpp b/mlir/test/lib/Conversion/OneToNTypeConversion/TestOneToNTypeConversionPass.cpp index e1ccc1b900df..3c4067b35d8e 100644 --- a/mlir/test/lib/Conversion/OneToNTypeConversion/TestOneToNTypeConversionPass.cpp +++ b/mlir/test/lib/Conversion/OneToNTypeConversion/TestOneToNTypeConversionPass.cpp @@ -8,7 +8,7 @@ #include "TestDialect.h" #include "mlir/Dialect/Func/Transforms/OneToNFuncConversions.h" -#include "mlir/Dialect/SCF/Transforms/Transforms.h" +#include "mlir/Dialect/SCF/Transforms/Patterns.h" #include "mlir/Pass/Pass.h" #include "mlir/Transforms/OneToNTypeConversion.h" diff --git a/mlir/test/lib/Dialect/Linalg/TestLinalgFusionTransforms.cpp b/mlir/test/lib/Dialect/Linalg/TestLinalgFusionTransforms.cpp index 2231e427007a..1466f541f231 100644 --- a/mlir/test/lib/Dialect/Linalg/TestLinalgFusionTransforms.cpp +++ b/mlir/test/lib/Dialect/Linalg/TestLinalgFusionTransforms.cpp @@ -13,7 +13,7 @@ #include "mlir/Dialect/Affine/IR/AffineOps.h" #include "mlir/Dialect/Func/IR/FuncOps.h" #include "mlir/Dialect/Linalg/Transforms/Transforms.h" -#include "mlir/Dialect/SCF/Transforms/Transforms.h" +#include "mlir/Dialect/SCF/Transforms/Patterns.h" #include "mlir/Pass/Pass.h" #include "mlir/Pass/PassManager.h" #include "mlir/Transforms/GreedyPatternRewriteDriver.h" diff --git a/mlir/test/lib/Dialect/SCF/TestSCFUtils.cpp b/mlir/test/lib/Dialect/SCF/TestSCFUtils.cpp index f35e774c9704..455c9234b8c9 100644 --- a/mlir/test/lib/Dialect/SCF/TestSCFUtils.cpp +++ b/mlir/test/lib/Dialect/SCF/TestSCFUtils.cpp @@ -14,7 +14,7 @@ #include "mlir/Dialect/Func/IR/FuncOps.h" #include "mlir/Dialect/MemRef/IR/MemRef.h" #include "mlir/Dialect/SCF/IR/SCF.h" -#include "mlir/Dialect/SCF/Transforms/Transforms.h" +#include "mlir/Dialect/SCF/Transforms/Patterns.h" #include "mlir/Dialect/SCF/Utils/Utils.h" #include "mlir/IR/Builders.h" #include "mlir/IR/PatternMatch.h"