MLIR  17.0.0git
GPUToSPIRV.cpp
Go to the documentation of this file.
1 //===- GPUToSPIRV.cpp - GPU to SPIR-V Patterns ----------------------------===//
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 patterns to convert GPU dialect to SPIR-V dialect.
10 //
11 //===----------------------------------------------------------------------===//
12 
21 #include "mlir/IR/BuiltinOps.h"
22 #include "mlir/IR/Matchers.h"
24 #include <optional>
25 
26 using namespace mlir;
27 
28 static constexpr const char kSPIRVModule[] = "__spv__";
29 
30 namespace {
31 /// Pattern lowering GPU block/thread size/id to loading SPIR-V invocation
32 /// builtin variables.
33 template <typename SourceOp, spirv::BuiltIn builtin>
34 class LaunchConfigConversion : public OpConversionPattern<SourceOp> {
35 public:
37 
39  matchAndRewrite(SourceOp op, typename SourceOp::Adaptor adaptor,
40  ConversionPatternRewriter &rewriter) const override;
41 };
42 
43 /// Pattern lowering subgroup size/id to loading SPIR-V invocation
44 /// builtin variables.
45 template <typename SourceOp, spirv::BuiltIn builtin>
46 class SingleDimLaunchConfigConversion : public OpConversionPattern<SourceOp> {
47 public:
49 
51  matchAndRewrite(SourceOp op, typename SourceOp::Adaptor adaptor,
52  ConversionPatternRewriter &rewriter) const override;
53 };
54 
55 /// This is separate because in Vulkan workgroup size is exposed to shaders via
56 /// a constant with WorkgroupSize decoration. So here we cannot generate a
57 /// builtin variable; instead the information in the `spirv.entry_point_abi`
58 /// attribute on the surrounding FuncOp is used to replace the gpu::BlockDimOp.
59 class WorkGroupSizeConversion : public OpConversionPattern<gpu::BlockDimOp> {
60 public:
61  WorkGroupSizeConversion(TypeConverter &typeConverter, MLIRContext *context)
62  : OpConversionPattern(typeConverter, context, /*benefit*/ 10) {}
63 
65  matchAndRewrite(gpu::BlockDimOp op, OpAdaptor adaptor,
66  ConversionPatternRewriter &rewriter) const override;
67 };
68 
69 /// Pattern to convert a kernel function in GPU dialect within a spirv.module.
70 class GPUFuncOpConversion final : public OpConversionPattern<gpu::GPUFuncOp> {
71 public:
73 
75  matchAndRewrite(gpu::GPUFuncOp funcOp, OpAdaptor adaptor,
76  ConversionPatternRewriter &rewriter) const override;
77 
78 private:
79  SmallVector<int32_t, 3> workGroupSizeAsInt32;
80 };
81 
82 /// Pattern to convert a gpu.module to a spirv.module.
83 class GPUModuleConversion final : public OpConversionPattern<gpu::GPUModuleOp> {
84 public:
86 
88  matchAndRewrite(gpu::GPUModuleOp moduleOp, OpAdaptor adaptor,
89  ConversionPatternRewriter &rewriter) const override;
90 };
91 
92 class GPUModuleEndConversion final
93  : public OpConversionPattern<gpu::ModuleEndOp> {
94 public:
96 
98  matchAndRewrite(gpu::ModuleEndOp endOp, OpAdaptor adaptor,
99  ConversionPatternRewriter &rewriter) const override {
100  rewriter.eraseOp(endOp);
101  return success();
102  }
103 };
104 
105 /// Pattern to convert a gpu.return into a SPIR-V return.
106 // TODO: This can go to DRR when GPU return has operands.
107 class GPUReturnOpConversion final : public OpConversionPattern<gpu::ReturnOp> {
108 public:
110 
112  matchAndRewrite(gpu::ReturnOp returnOp, OpAdaptor adaptor,
113  ConversionPatternRewriter &rewriter) const override;
114 };
115 
116 /// Pattern to convert a gpu.barrier op into a spirv.ControlBarrier op.
117 class GPUBarrierConversion final : public OpConversionPattern<gpu::BarrierOp> {
118 public:
120 
122  matchAndRewrite(gpu::BarrierOp barrierOp, OpAdaptor adaptor,
123  ConversionPatternRewriter &rewriter) const override;
124 };
125 
126 /// Pattern to convert a gpu.shuffle op into a spirv.GroupNonUniformShuffle op.
127 class GPUShuffleConversion final : public OpConversionPattern<gpu::ShuffleOp> {
128 public:
130 
132  matchAndRewrite(gpu::ShuffleOp shuffleOp, OpAdaptor adaptor,
133  ConversionPatternRewriter &rewriter) const override;
134 };
135 
136 } // namespace
137 
138 //===----------------------------------------------------------------------===//
139 // Builtins.
140 //===----------------------------------------------------------------------===//
141 
142 template <typename SourceOp, spirv::BuiltIn builtin>
143 LogicalResult LaunchConfigConversion<SourceOp, builtin>::matchAndRewrite(
144  SourceOp op, typename SourceOp::Adaptor adaptor,
145  ConversionPatternRewriter &rewriter) const {
146  auto *typeConverter = this->template getTypeConverter<SPIRVTypeConverter>();
147  auto indexType = typeConverter->getIndexType();
148 
149  // SPIR-V invocation builtin variables are a vector of type <3xi32>
150  auto spirvBuiltin =
151  spirv::getBuiltinVariableValue(op, builtin, indexType, rewriter);
152  rewriter.replaceOpWithNewOp<spirv::CompositeExtractOp>(
153  op, indexType, spirvBuiltin,
154  rewriter.getI32ArrayAttr({static_cast<int32_t>(op.getDimension())}));
155  return success();
156 }
157 
158 template <typename SourceOp, spirv::BuiltIn builtin>
160 SingleDimLaunchConfigConversion<SourceOp, builtin>::matchAndRewrite(
161  SourceOp op, typename SourceOp::Adaptor adaptor,
162  ConversionPatternRewriter &rewriter) const {
163  auto *typeConverter = this->template getTypeConverter<SPIRVTypeConverter>();
164  auto indexType = typeConverter->getIndexType();
165 
166  auto spirvBuiltin =
167  spirv::getBuiltinVariableValue(op, builtin, indexType, rewriter);
168  rewriter.replaceOp(op, spirvBuiltin);
169  return success();
170 }
171 
172 LogicalResult WorkGroupSizeConversion::matchAndRewrite(
173  gpu::BlockDimOp op, OpAdaptor adaptor,
174  ConversionPatternRewriter &rewriter) const {
175  DenseI32ArrayAttr workGroupSizeAttr = spirv::lookupLocalWorkGroupSize(op);
176  if (!workGroupSizeAttr)
177  return failure();
178 
179  int val =
180  workGroupSizeAttr.asArrayRef()[static_cast<int32_t>(op.getDimension())];
181  auto convertedType =
182  getTypeConverter()->convertType(op.getResult().getType());
183  if (!convertedType)
184  return failure();
185  rewriter.replaceOpWithNewOp<spirv::ConstantOp>(
186  op, convertedType, IntegerAttr::get(convertedType, val));
187  return success();
188 }
189 
190 //===----------------------------------------------------------------------===//
191 // GPUFuncOp
192 //===----------------------------------------------------------------------===//
193 
194 // Legalizes a GPU function as an entry SPIR-V function.
195 static spirv::FuncOp
196 lowerAsEntryFunction(gpu::GPUFuncOp funcOp, TypeConverter &typeConverter,
197  ConversionPatternRewriter &rewriter,
198  spirv::EntryPointABIAttr entryPointInfo,
200  auto fnType = funcOp.getFunctionType();
201  if (fnType.getNumResults()) {
202  funcOp.emitError("SPIR-V lowering only supports entry functions"
203  "with no return values right now");
204  return nullptr;
205  }
206  if (!argABIInfo.empty() && fnType.getNumInputs() != argABIInfo.size()) {
207  funcOp.emitError(
208  "lowering as entry functions requires ABI info for all arguments "
209  "or none of them");
210  return nullptr;
211  }
212  // Update the signature to valid SPIR-V types and add the ABI
213  // attributes. These will be "materialized" by using the
214  // LowerABIAttributesPass.
215  TypeConverter::SignatureConversion signatureConverter(fnType.getNumInputs());
216  {
217  for (const auto &argType :
218  enumerate(funcOp.getFunctionType().getInputs())) {
219  auto convertedType = typeConverter.convertType(argType.value());
220  if (!convertedType)
221  return nullptr;
222  signatureConverter.addInputs(argType.index(), convertedType);
223  }
224  }
225  auto newFuncOp = rewriter.create<spirv::FuncOp>(
226  funcOp.getLoc(), funcOp.getName(),
227  rewriter.getFunctionType(signatureConverter.getConvertedTypes(),
228  std::nullopt));
229  for (const auto &namedAttr : funcOp->getAttrs()) {
230  if (namedAttr.getName() == funcOp.getFunctionTypeAttrName() ||
231  namedAttr.getName() == SymbolTable::getSymbolAttrName())
232  continue;
233  newFuncOp->setAttr(namedAttr.getName(), namedAttr.getValue());
234  }
235 
236  rewriter.inlineRegionBefore(funcOp.getBody(), newFuncOp.getBody(),
237  newFuncOp.end());
238  if (failed(rewriter.convertRegionTypes(&newFuncOp.getBody(), typeConverter,
239  &signatureConverter)))
240  return nullptr;
241  rewriter.eraseOp(funcOp);
242 
243  // Set the attributes for argument and the function.
244  StringRef argABIAttrName = spirv::getInterfaceVarABIAttrName();
245  for (auto argIndex : llvm::seq<unsigned>(0, argABIInfo.size())) {
246  newFuncOp.setArgAttr(argIndex, argABIAttrName, argABIInfo[argIndex]);
247  }
248  newFuncOp->setAttr(spirv::getEntryPointABIAttrName(), entryPointInfo);
249 
250  return newFuncOp;
251 }
252 
253 /// Populates `argABI` with spirv.interface_var_abi attributes for lowering
254 /// gpu.func to spirv.func if no arguments have the attributes set
255 /// already. Returns failure if any argument has the ABI attribute set already.
256 static LogicalResult
257 getDefaultABIAttrs(MLIRContext *context, gpu::GPUFuncOp funcOp,
260  if (!spirv::needsInterfaceVarABIAttrs(targetEnv))
261  return success();
262 
263  for (auto argIndex : llvm::seq<unsigned>(0, funcOp.getNumArguments())) {
264  if (funcOp.getArgAttrOfType<spirv::InterfaceVarABIAttr>(
266  return failure();
267  // Vulkan's interface variable requirements needs scalars to be wrapped in a
268  // struct. The struct held in storage buffer.
269  std::optional<spirv::StorageClass> sc;
270  if (funcOp.getArgument(argIndex).getType().isIntOrIndexOrFloat())
271  sc = spirv::StorageClass::StorageBuffer;
272  argABI.push_back(spirv::getInterfaceVarABIAttr(0, argIndex, sc, context));
273  }
274  return success();
275 }
276 
277 LogicalResult GPUFuncOpConversion::matchAndRewrite(
278  gpu::GPUFuncOp funcOp, OpAdaptor adaptor,
279  ConversionPatternRewriter &rewriter) const {
280  if (!gpu::GPUDialect::isKernel(funcOp))
281  return failure();
282 
284  if (failed(getDefaultABIAttrs(rewriter.getContext(), funcOp, argABI))) {
285  argABI.clear();
286  for (auto argIndex : llvm::seq<unsigned>(0, funcOp.getNumArguments())) {
287  // If the ABI is already specified, use it.
288  auto abiAttr = funcOp.getArgAttrOfType<spirv::InterfaceVarABIAttr>(
290  if (!abiAttr) {
291  funcOp.emitRemark(
292  "match failure: missing 'spirv.interface_var_abi' attribute at "
293  "argument ")
294  << argIndex;
295  return failure();
296  }
297  argABI.push_back(abiAttr);
298  }
299  }
300 
301  auto entryPointAttr = spirv::lookupEntryPointABI(funcOp);
302  if (!entryPointAttr) {
303  funcOp.emitRemark(
304  "match failure: missing 'spirv.entry_point_abi' attribute");
305  return failure();
306  }
307  spirv::FuncOp newFuncOp = lowerAsEntryFunction(
308  funcOp, *getTypeConverter(), rewriter, entryPointAttr, argABI);
309  if (!newFuncOp)
310  return failure();
311  newFuncOp->removeAttr(
312  rewriter.getStringAttr(gpu::GPUDialect::getKernelFuncAttrName()));
313  return success();
314 }
315 
316 //===----------------------------------------------------------------------===//
317 // ModuleOp with gpu.module.
318 //===----------------------------------------------------------------------===//
319 
320 LogicalResult GPUModuleConversion::matchAndRewrite(
321  gpu::GPUModuleOp moduleOp, OpAdaptor adaptor,
322  ConversionPatternRewriter &rewriter) const {
324  spirv::AddressingModel addressingModel = spirv::getAddressingModel(targetEnv);
325  FailureOr<spirv::MemoryModel> memoryModel = spirv::getMemoryModel(targetEnv);
326  if (failed(memoryModel))
327  return moduleOp.emitRemark("match failure: could not selected memory model "
328  "based on 'spirv.target_env'");
329 
330  // Add a keyword to the module name to avoid symbolic conflict.
331  std::string spvModuleName = (kSPIRVModule + moduleOp.getName()).str();
332  auto spvModule = rewriter.create<spirv::ModuleOp>(
333  moduleOp.getLoc(), addressingModel, *memoryModel, std::nullopt,
334  StringRef(spvModuleName));
335 
336  // Move the region from the module op into the SPIR-V module.
337  Region &spvModuleRegion = spvModule.getRegion();
338  rewriter.inlineRegionBefore(moduleOp.getBodyRegion(), spvModuleRegion,
339  spvModuleRegion.begin());
340  // The spirv.module build method adds a block. Remove that.
341  rewriter.eraseBlock(&spvModuleRegion.back());
342 
343  // Some of the patterns call `lookupTargetEnv` during conversion and they
344  // will fail if called after GPUModuleConversion and we don't preserve
345  // `TargetEnv` attribute.
346  // Copy TargetEnvAttr only if it is attached directly to the GPUModuleOp.
347  if (auto attr = moduleOp->getAttrOfType<spirv::TargetEnvAttr>(
349  spvModule->setAttr(spirv::getTargetEnvAttrName(), attr);
350 
351  rewriter.eraseOp(moduleOp);
352  return success();
353 }
354 
355 //===----------------------------------------------------------------------===//
356 // GPU return inside kernel functions to SPIR-V return.
357 //===----------------------------------------------------------------------===//
358 
359 LogicalResult GPUReturnOpConversion::matchAndRewrite(
360  gpu::ReturnOp returnOp, OpAdaptor adaptor,
361  ConversionPatternRewriter &rewriter) const {
362  if (!adaptor.getOperands().empty())
363  return failure();
364 
365  rewriter.replaceOpWithNewOp<spirv::ReturnOp>(returnOp);
366  return success();
367 }
368 
369 //===----------------------------------------------------------------------===//
370 // Barrier.
371 //===----------------------------------------------------------------------===//
372 
373 LogicalResult GPUBarrierConversion::matchAndRewrite(
374  gpu::BarrierOp barrierOp, OpAdaptor adaptor,
375  ConversionPatternRewriter &rewriter) const {
376  MLIRContext *context = getContext();
377  // Both execution and memory scope should be workgroup.
378  auto scope = spirv::ScopeAttr::get(context, spirv::Scope::Workgroup);
379  // Require acquire and release memory semantics for workgroup memory.
380  auto memorySemantics = spirv::MemorySemanticsAttr::get(
381  context, spirv::MemorySemantics::WorkgroupMemory |
382  spirv::MemorySemantics::AcquireRelease);
383  rewriter.replaceOpWithNewOp<spirv::ControlBarrierOp>(barrierOp, scope, scope,
384  memorySemantics);
385  return success();
386 }
387 
388 //===----------------------------------------------------------------------===//
389 // Shuffle
390 //===----------------------------------------------------------------------===//
391 
392 LogicalResult GPUShuffleConversion::matchAndRewrite(
393  gpu::ShuffleOp shuffleOp, OpAdaptor adaptor,
394  ConversionPatternRewriter &rewriter) const {
395  // Require the shuffle width to be the same as the target's subgroup size,
396  // given that for SPIR-V non-uniform subgroup ops, we cannot select
397  // participating invocations.
398  auto targetEnv = getTypeConverter<SPIRVTypeConverter>()->getTargetEnv();
399  unsigned subgroupSize =
400  targetEnv.getAttr().getResourceLimits().getSubgroupSize();
401  IntegerAttr widthAttr;
402  if (!matchPattern(shuffleOp.getWidth(), m_Constant(&widthAttr)) ||
403  widthAttr.getValue().getZExtValue() != subgroupSize)
404  return rewriter.notifyMatchFailure(
405  shuffleOp, "shuffle width and target subgroup size mismatch");
406 
407  Location loc = shuffleOp.getLoc();
408  Value trueVal = spirv::ConstantOp::getOne(rewriter.getI1Type(),
409  shuffleOp.getLoc(), rewriter);
410  auto scope = rewriter.getAttr<spirv::ScopeAttr>(spirv::Scope::Subgroup);
411  Value result;
412 
413  switch (shuffleOp.getMode()) {
414  case gpu::ShuffleMode::XOR:
415  result = rewriter.create<spirv::GroupNonUniformShuffleXorOp>(
416  loc, scope, adaptor.getValue(), adaptor.getOffset());
417  break;
418  case gpu::ShuffleMode::IDX:
419  result = rewriter.create<spirv::GroupNonUniformShuffleOp>(
420  loc, scope, adaptor.getValue(), adaptor.getOffset());
421  break;
422  default:
423  return rewriter.notifyMatchFailure(shuffleOp, "unimplemented shuffle mode");
424  }
425 
426  rewriter.replaceOp(shuffleOp, {result, trueVal});
427  return success();
428 }
429 
430 //===----------------------------------------------------------------------===//
431 // Group ops
432 //===----------------------------------------------------------------------===//
433 
434 template <typename UniformOp, typename NonUniformOp>
436  Value arg, bool isGroup, bool isUniform) {
437  Type type = arg.getType();
438  auto scope = mlir::spirv::ScopeAttr::get(builder.getContext(),
439  isGroup ? spirv::Scope::Workgroup
440  : spirv::Scope::Subgroup);
441  auto groupOp = spirv::GroupOperationAttr::get(builder.getContext(),
442  spirv::GroupOperation::Reduce);
443  if (isUniform) {
444  return builder.create<UniformOp>(loc, type, scope, groupOp, arg)
445  .getResult();
446  }
447  return builder.create<NonUniformOp>(loc, type, scope, groupOp, arg, Value{})
448  .getResult();
449 }
450 
451 static std::optional<Value> createGroupReduceOp(OpBuilder &builder,
452  Location loc, Value arg,
453  gpu::AllReduceOperation opType,
454  bool isGroup, bool isUniform) {
455  using FuncT = Value (*)(OpBuilder &, Location, Value, bool, bool);
456  struct OpHandler {
457  gpu::AllReduceOperation type;
458  FuncT intFunc;
459  FuncT floatFunc;
460  };
461 
462  Type type = arg.getType();
463  using MembptrT = FuncT OpHandler::*;
464  MembptrT handlerPtr;
465  if (type.isa<FloatType>()) {
466  handlerPtr = &OpHandler::floatFunc;
467  } else if (type.isa<IntegerType>()) {
468  handlerPtr = &OpHandler::intFunc;
469  } else {
470  return std::nullopt;
471  }
472 
473  using ReduceType = gpu::AllReduceOperation;
474  namespace spv = spirv;
475  const OpHandler handlers[] = {
476  {ReduceType::ADD,
477  &createGroupReduceOpImpl<spv::GroupIAddOp, spv::GroupNonUniformIAddOp>,
478  &createGroupReduceOpImpl<spv::GroupFAddOp, spv::GroupNonUniformFAddOp>},
479  {ReduceType::MUL,
480  &createGroupReduceOpImpl<spv::GroupIMulKHROp,
481  spv::GroupNonUniformIMulOp>,
482  &createGroupReduceOpImpl<spv::GroupFMulKHROp,
483  spv::GroupNonUniformFMulOp>},
484  };
485 
486  for (auto &handler : handlers)
487  if (handler.type == opType)
488  return (handler.*handlerPtr)(builder, loc, arg, isGroup, isUniform);
489 
490  return std::nullopt;
491 }
492 
493 /// Pattern to convert a gpu.all_reduce op into a SPIR-V group op.
495  : public OpConversionPattern<gpu::AllReduceOp> {
496 public:
498 
500  matchAndRewrite(gpu::AllReduceOp op, OpAdaptor adaptor,
501  ConversionPatternRewriter &rewriter) const override {
502  auto opType = op.getOp();
503 
504  // gpu.all_reduce can have either reduction op attribute or reduction
505  // region. Only attribute version is supported.
506  if (!opType)
507  return failure();
508 
509  auto result =
510  createGroupReduceOp(rewriter, op.getLoc(), adaptor.getValue(), *opType,
511  /*isGroup*/ true, op.getUniform());
512  if (!result)
513  return failure();
514 
515  rewriter.replaceOp(op, *result);
516  return success();
517  }
518 };
519 
520 /// Pattern to convert a gpu.subgroup_reduce op into a SPIR-V group op.
522  : public OpConversionPattern<gpu::SubgroupReduceOp> {
523 public:
525 
527  matchAndRewrite(gpu::SubgroupReduceOp op, OpAdaptor adaptor,
528  ConversionPatternRewriter &rewriter) const override {
529  auto opType = op.getOp();
530  auto result =
531  createGroupReduceOp(rewriter, op.getLoc(), adaptor.getValue(), opType,
532  /*isGroup*/ false, op.getUniform());
533  if (!result)
534  return failure();
535 
536  rewriter.replaceOp(op, *result);
537  return success();
538  }
539 };
540 
541 //===----------------------------------------------------------------------===//
542 // GPU To SPIRV Patterns.
543 //===----------------------------------------------------------------------===//
544 
546  RewritePatternSet &patterns) {
547  patterns.add<
548  GPUBarrierConversion, GPUFuncOpConversion, GPUModuleConversion,
549  GPUModuleEndConversion, GPUReturnOpConversion, GPUShuffleConversion,
550  LaunchConfigConversion<gpu::BlockIdOp, spirv::BuiltIn::WorkgroupId>,
551  LaunchConfigConversion<gpu::GridDimOp, spirv::BuiltIn::NumWorkgroups>,
552  LaunchConfigConversion<gpu::BlockDimOp, spirv::BuiltIn::WorkgroupSize>,
553  LaunchConfigConversion<gpu::ThreadIdOp,
554  spirv::BuiltIn::LocalInvocationId>,
555  LaunchConfigConversion<gpu::GlobalIdOp,
556  spirv::BuiltIn::GlobalInvocationId>,
557  SingleDimLaunchConfigConversion<gpu::SubgroupIdOp,
558  spirv::BuiltIn::SubgroupId>,
559  SingleDimLaunchConfigConversion<gpu::NumSubgroupsOp,
560  spirv::BuiltIn::NumSubgroups>,
561  SingleDimLaunchConfigConversion<gpu::SubgroupSizeOp,
562  spirv::BuiltIn::SubgroupSize>,
563  WorkGroupSizeConversion, GPUAllReduceConversion,
564  GPUSubgroupReduceConversion>(typeConverter, patterns.getContext());
565 }
static Value createGroupReduceOpImpl(OpBuilder &builder, Location loc, Value arg, bool isGroup, bool isUniform)
Definition: GPUToSPIRV.cpp:435
static LogicalResult getDefaultABIAttrs(MLIRContext *context, gpu::GPUFuncOp funcOp, SmallVectorImpl< spirv::InterfaceVarABIAttr > &argABI)
Populates argABI with spirv.interface_var_abi attributes for lowering gpu.func to spirv....
Definition: GPUToSPIRV.cpp:257
static std::optional< Value > createGroupReduceOp(OpBuilder &builder, Location loc, Value arg, gpu::AllReduceOperation opType, bool isGroup, bool isUniform)
Definition: GPUToSPIRV.cpp:451
static constexpr const char kSPIRVModule[]
Definition: GPUToSPIRV.cpp:28
static spirv::FuncOp lowerAsEntryFunction(gpu::GPUFuncOp funcOp, TypeConverter &typeConverter, ConversionPatternRewriter &rewriter, spirv::EntryPointABIAttr entryPointInfo, ArrayRef< spirv::InterfaceVarABIAttr > argABIInfo)
Definition: GPUToSPIRV.cpp:196
Pattern to convert a gpu.all_reduce op into a SPIR-V group op.
Definition: GPUToSPIRV.cpp:495
LogicalResult matchAndRewrite(gpu::AllReduceOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
Definition: GPUToSPIRV.cpp:500
Pattern to convert a gpu.subgroup_reduce op into a SPIR-V group op.
Definition: GPUToSPIRV.cpp:522
LogicalResult matchAndRewrite(gpu::SubgroupReduceOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
Definition: GPUToSPIRV.cpp:527
ArrayAttr getI32ArrayAttr(ArrayRef< int32_t > values)
Definition: Builders.cpp:257
FunctionType getFunctionType(TypeRange inputs, TypeRange results)
Definition: Builders.cpp:81
StringAttr getStringAttr(const Twine &bytes)
Definition: Builders.cpp:243
MLIRContext * getContext() const
Definition: Builders.h:55
IntegerType getI1Type()
Definition: Builders.cpp:58
Attr getAttr(Args &&...args)
Get or construct an instance of the attribute Attr with provided arguments.
Definition: Builders.h:96
This class implements a pattern rewriter for use with ConversionPatterns.
void replaceOp(Operation *op, ValueRange newValues) override
PatternRewriter hook for replacing the results of an operation.
LogicalResult notifyMatchFailure(Location loc, function_ref< void(Diagnostic &)> reasonCallback) override
PatternRewriter hook for notifying match failure reasons.
void inlineRegionBefore(Region &region, Region &parent, Region::iterator before) override
PatternRewriter hook for moving blocks out of a region.
void eraseOp(Operation *op) override
PatternRewriter hook for erasing a dead operation.
FailureOr< Block * > convertRegionTypes(Region *region, TypeConverter &converter, TypeConverter::SignatureConversion *entryConversion=nullptr)
Convert the types of block arguments within the given region.
void eraseBlock(Block *block) override
PatternRewriter hook for erase all operations in a block.
This class provides support for representing a failure result, or a valid value of type T.
Definition: LogicalResult.h:78
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition: Location.h:63
MLIRContext is the top-level object for a collection of MLIR operations.
Definition: MLIRContext.h:56
This class helps build Operations.
Definition: Builders.h:199
Operation * create(const OperationState &state)
Creates an operation given the fields represented as an OperationState.
Definition: Builders.cpp:422
OpConversionPattern is a wrapper around ConversionPattern that allows for matching and rewriting agai...
OpConversionPattern(MLIRContext *context, PatternBenefit benefit=1)
void setAttr(StringAttr name, Attribute value)
If the an attribute exists with the specified name, change it to the new value.
Definition: Operation.h:439
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Definition: Region.h:26
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)
Replaces the result op with a new op that is created without verification.
Definition: PatternMatch.h:451
Type conversion from builtin types to SPIR-V types for shader interface.
static StringRef getSymbolAttrName()
Return the name of the attribute used for symbol names.
Definition: SymbolTable.h:58
This class provides all of the information necessary to convert a type signature.
void addInputs(unsigned origInputNo, ArrayRef< Type > types)
Remap an input of the original signature with a new set of types.
ArrayRef< Type > getConvertedTypes() const
Return the argument types for the new signature.
Type conversion class.
LogicalResult convertType(Type t, SmallVectorImpl< Type > &results)
Convert the given type.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition: Types.h:74
bool isa() const
Definition: Types.h:301
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition: Value.h:93
Type getType() const
Return the type of this value.
Definition: Value.h:122
An attribute that specifies the information regarding the interface variable: descriptor set,...
An attribute that specifies the target version, allowed extensions and capabilities,...
ResourceLimitsAttr getResourceLimits() const
Returns the target resource limits.
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
Definition: Matchers.h:223
StringRef getInterfaceVarABIAttrName()
Returns the attribute name for specifying argument ABI information.
bool needsInterfaceVarABIAttrs(TargetEnvAttr targetAttr)
Returns whether the given SPIR-V target (described by TargetEnvAttr) needs ABI attributes for interfa...
TargetEnvAttr lookupTargetEnvOrDefault(Operation *op)
Queries the target environment recursively from enclosing symbol table ops containing the given op or...
InterfaceVarABIAttr getInterfaceVarABIAttr(unsigned descriptorSet, unsigned binding, std::optional< StorageClass > storageClass, MLIRContext *context)
Gets the InterfaceVarABIAttr given its fields.
Value getBuiltinVariableValue(Operation *op, BuiltIn builtin, Type integerType, OpBuilder &builder)
Returns the value for the given builtin variable.
EntryPointABIAttr lookupEntryPointABI(Operation *op)
Queries the entry point ABI on the nearest function-like op containing the given op.
StringRef getTargetEnvAttrName()
Returns the attribute name for specifying SPIR-V target environment.
DenseI32ArrayAttr lookupLocalWorkGroupSize(Operation *op)
Queries the local workgroup size from entry point ABI on the nearest function-like op containing the ...
AddressingModel getAddressingModel(TargetEnvAttr targetAttr)
Returns addressing model selected based on target environment.
FailureOr< MemoryModel > getMemoryModel(TargetEnvAttr targetAttr)
Returns memory model selected based on target environment.
StringRef getEntryPointABIAttrName()
Returns the attribute name for specifying entry point information.
Include the generated interface declarations.
bool matchPattern(Value value, const Pattern &pattern)
Entry point for matching a pattern over a Value.
Definition: Matchers.h:322
LogicalResult failure(bool isFailure=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:62
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:56
void populateGPUToSPIRVPatterns(SPIRVTypeConverter &typeConverter, RewritePatternSet &patterns)
Appends to a pattern list additional patterns for translating GPU Ops to SPIR-V ops.
Definition: GPUToSPIRV.cpp:545
detail::constant_op_matcher m_Constant()
Matches a constant foldable operation.
Definition: Matchers.h:248
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value.
Definition: LogicalResult.h:72
This class represents an efficient way to signal success or failure.
Definition: LogicalResult.h:26