MLIR 24.0.0git
DecorateCompositeTypeLayoutPass.cpp
Go to the documentation of this file.
1//===- DecorateCompositeTypeLayoutPass.cpp - Decorate composite type ------===//
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// This file implements a pass to decorate the composite types used by
10// composite objects in the StorageBuffer, PhysicalStorageBuffer, Uniform, and
11// PushConstant storage classes with layout information. See SPIR-V spec
12// "2.16.2. Validation Rules for Shader Capabilities" for more details.
13//
14//===----------------------------------------------------------------------===//
15
17
23
24#include "llvm/Support/FormatVariadic.h"
25
26using namespace mlir;
27
28namespace mlir {
29namespace spirv {
30#define GEN_PASS_DEF_SPIRVCOMPOSITETYPELAYOUTPASS
31#include "mlir/Dialect/SPIRV/Transforms/Passes.h.inc"
32} // namespace spirv
33} // namespace mlir
34
35namespace {
36class SPIRVGlobalVariableOpLayoutInfoDecoration
37 : public OpRewritePattern<spirv::GlobalVariableOp> {
38public:
39 using Base::Base;
40
41 LogicalResult matchAndRewrite(spirv::GlobalVariableOp op,
42 PatternRewriter &rewriter) const override {
43 NamedAttrList globalVarAttrs(op->getDiscardableAttrDictionary());
44 op->getName().populateInherentAttrs(op, globalVarAttrs);
45
46 auto ptrType = cast<spirv::PointerType>(op.getType());
47 auto pointeeType = cast<spirv::StructType>(ptrType.getPointeeType());
48 spirv::StructType structType = VulkanLayoutUtils::decorateType(pointeeType);
49
50 if (!structType)
51 return op->emitError(llvm::formatv(
52 "failed to decorate (unsuported pointee type: '{0}')", pointeeType));
53
54 auto decoratedType =
55 spirv::PointerType::get(structType, ptrType.getStorageClass());
56
57 // The new type is passed through the operation-specific builder below.
58 globalVarAttrs.erase("type");
59
60 rewriter.replaceOpWithNewOp<spirv::GlobalVariableOp>(
61 op, TypeAttr::get(decoratedType), globalVarAttrs);
62 return success();
63 }
64};
65
66class SPIRVAddressOfOpLayoutInfoDecoration
67 : public OpRewritePattern<spirv::AddressOfOp> {
68public:
69 using Base::Base;
70
71 LogicalResult matchAndRewrite(spirv::AddressOfOp op,
72 PatternRewriter &rewriter) const override {
73 auto spirvModule = op->getParentOfType<spirv::ModuleOp>();
74 auto varName = op.getVariableAttr();
75 auto varOp = spirvModule.lookupSymbol<spirv::GlobalVariableOp>(varName);
76
77 rewriter.replaceOpWithNewOp<spirv::AddressOfOp>(
78 op, varOp.getType(), SymbolRefAttr::get(varName.getAttr()));
79 return success();
80 }
81};
82
83template <typename OpT>
84class SPIRVPassThroughConversion : public OpConversionPattern<OpT> {
85public:
86 using OpConversionPattern<OpT>::OpConversionPattern;
87
88 LogicalResult
89 matchAndRewrite(OpT op, typename OpT::Adaptor adaptor,
90 ConversionPatternRewriter &rewriter) const override {
91 rewriter.modifyOpInPlace(op,
92 [&] { op->setOperands(adaptor.getOperands()); });
93 return success();
94 }
95};
96} // namespace
97
99 patterns.add<SPIRVGlobalVariableOpLayoutInfoDecoration,
100 SPIRVAddressOfOpLayoutInfoDecoration,
101 SPIRVPassThroughConversion<spirv::AccessChainOp>,
102 SPIRVPassThroughConversion<spirv::LoadOp>,
103 SPIRVPassThroughConversion<spirv::StoreOp>>(
104 patterns.getContext());
105}
106
107namespace {
108class DecorateSPIRVCompositeTypeLayoutPass
110 DecorateSPIRVCompositeTypeLayoutPass> {
111 void runOnOperation() override;
113} // namespace
115void DecorateSPIRVCompositeTypeLayoutPass::runOnOperation() {
116 auto module = getOperation();
117 RewritePatternSet patterns(module.getContext());
119 ConversionTarget target(*(module.getContext()));
120 target.addLegalDialect<spirv::SPIRVDialect>();
121 target.addLegalOp<func::FuncOp>();
122 target.addDynamicallyLegalOp<spirv::GlobalVariableOp>(
123 [](spirv::GlobalVariableOp op) {
124 return VulkanLayoutUtils::isLegalType(op.getType());
125 });
126
127 // Change the type for the direct users.
128 target.addDynamicallyLegalOp<spirv::AddressOfOp>([](spirv::AddressOfOp op) {
129 return VulkanLayoutUtils::isLegalType(op.getPointer().getType());
130 });
131
132 // Change the type for the indirect users.
133 target.addDynamicallyLegalOp<spirv::AccessChainOp, spirv::LoadOp,
134 spirv::StoreOp>([&](Operation *op) {
135 for (Value operand : op->getOperands()) {
136 auto addrOp = operand.getDefiningOp<spirv::AddressOfOp>();
137 if (addrOp &&
138 !VulkanLayoutUtils::isLegalType(addrOp.getPointer().getType()))
139 return false;
140 }
141 return true;
142 });
144 FrozenRewritePatternSet frozenPatterns(std::move(patterns));
145 for (auto spirvModule : module.getOps<spirv::ModuleOp>())
146 if (failed(applyFullConversion(spirvModule, target, frozenPatterns)))
148}
return success()
static void populateSPIRVLayoutInfoPatterns(RewritePatternSet &patterns)
This class represents a frozen set of patterns that can be processed by a pattern applicator.
Attribute erase(StringAttr name)
Erase the attribute with the given name from the list.
Operation is the basic unit of execution within MLIR.
Definition Operation.h:87
virtual void runOnOperation()=0
The polymorphic API that runs the pass over the currently held operation.
void signalPassFailure()
Signal that some invariant was broken when running.
Definition Pass.h:226
MLIRContext * getContext() const
RewritePatternSet & add(ConstructorArg &&arg, ConstructorArgs &&...args)
Add an instance of each of the pattern types 'Ts' to the pattern list with the given arguments.
OpTy replaceOpWithNewOp(Operation *op, Args &&...args)
Replace the results of the given (original) op with a new op that is created without verification (re...
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition Value.h:96
static bool isLegalType(Type type)
Checks whether a type is legal in terms of Vulkan layout info decoration.
static spirv::StructType decorateType(spirv::StructType structType)
Returns a new StructType with layout decoration.
static PointerType get(Type pointeeType, StorageClass storageClass)
Include the generated interface declarations.
OpRewritePattern is a wrapper around RewritePattern that allows for matching and rewriting against an...