1 //===- SparseTensorPipelines.cpp - Pipelines for sparse tensor code -------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "mlir/Dialect/SparseTensor/Pipelines/Passes.h"
10
11 #include "mlir/Conversion/Passes.h"
12 #include "mlir/Dialect/Bufferization/Transforms/Bufferize.h"
13 #include "mlir/Dialect/Bufferization/Transforms/OneShotAnalysis.h"
14 #include "mlir/Dialect/Bufferization/Transforms/Passes.h"
15 #include "mlir/Dialect/Func/IR/FuncOps.h"
16 #include "mlir/Dialect/Linalg/Passes.h"
17 #include "mlir/Dialect/SparseTensor/IR/SparseTensor.h"
18 #include "mlir/Dialect/SparseTensor/Transforms/Passes.h"
19 #include "mlir/Pass/PassManager.h"
20
21 using namespace mlir;
22 using namespace mlir::sparse_tensor;
23
24 /// Return configuration options for One-Shot Bufferize.
25 static bufferization::OneShotBufferizationOptions
getBufferizationOptions(bool analysisOnly)26 getBufferizationOptions(bool analysisOnly) {
27 using namespace bufferization;
28 OneShotBufferizationOptions options;
29 options.bufferizeFunctionBoundaries = true;
30 // TODO(springerm): To spot memory leaks more easily, returning dense allocs
31 // should be disallowed.
32 options.allowReturnAllocs = true;
33 options.functionBoundaryTypeConversion =
34 BufferizationOptions::LayoutMapOption::IdentityLayoutMap;
35 options.unknownTypeConverterFn = [](Value value, unsigned memorySpace,
36 const BufferizationOptions &options) {
37 return getMemRefTypeWithStaticIdentityLayout(
38 value.getType().cast<TensorType>(), memorySpace);
39 };
40 if (analysisOnly) {
41 options.testAnalysisOnly = true;
42 options.printConflicts = true;
43 }
44 return options;
45 }
46
47 //===----------------------------------------------------------------------===//
48 // Pipeline implementation.
49 //===----------------------------------------------------------------------===//
50
buildSparseCompiler(OpPassManager & pm,const SparseCompilerOptions & options)51 void mlir::sparse_tensor::buildSparseCompiler(
52 OpPassManager &pm, const SparseCompilerOptions &options) {
53 // TODO(wrengr): ensure the original `pm` is for ModuleOp
54 pm.addNestedPass<func::FuncOp>(createLinalgGeneralizationPass());
55 pm.addPass(
56 bufferization::createTensorCopyInsertionPass(getBufferizationOptions(
57 /*analysisOnly=*/options.testBufferizationAnalysisOnly)));
58 if (options.testBufferizationAnalysisOnly)
59 return;
60 pm.addPass(createSparsificationPass(options.sparsificationOptions()));
61 pm.addPass(createSparseTensorConversionPass(
62 options.sparseTensorConversionOptions()));
63 pm.addPass(createDenseBufferizationPass(
64 getBufferizationOptions(/*analysisOnly=*/false)));
65 pm.addNestedPass<func::FuncOp>(
66 mlir::bufferization::createFinalizingBufferizePass());
67 // TODO(springerm): Add sparse support to the BufferDeallocation pass and add
68 // it to this pipeline.
69 pm.addNestedPass<func::FuncOp>(createConvertLinalgToLoopsPass());
70 pm.addNestedPass<func::FuncOp>(createConvertVectorToSCFPass());
71 pm.addNestedPass<func::FuncOp>(createConvertSCFToCFPass());
72 pm.addPass(createLowerAffinePass());
73 pm.addPass(createConvertVectorToLLVMPass(options.lowerVectorToLLVMOptions()));
74 pm.addPass(createMemRefToLLVMPass());
75 pm.addNestedPass<func::FuncOp>(createConvertComplexToStandardPass());
76 pm.addNestedPass<func::FuncOp>(createConvertMathToLLVMPass());
77 pm.addPass(createConvertMathToLibmPass());
78 pm.addPass(createConvertComplexToLibmPass());
79 pm.addPass(createConvertComplexToLLVMPass());
80 pm.addPass(createConvertFuncToLLVMPass());
81 pm.addPass(createReconcileUnrealizedCastsPass());
82 }
83
84 //===----------------------------------------------------------------------===//
85 // Pipeline registration.
86 //===----------------------------------------------------------------------===//
87
registerSparseTensorPipelines()88 void mlir::sparse_tensor::registerSparseTensorPipelines() {
89 PassPipelineRegistration<SparseCompilerOptions>(
90 "sparse-compiler",
91 "The standard pipeline for taking sparsity-agnostic IR using the"
92 " sparse-tensor type, and lowering it to LLVM IR with concrete"
93 " representations and algorithms for sparse tensors.",
94 buildSparseCompiler);
95 }
96