32template <
typename SourceOp, spirv::BuiltIn builtin>
33class LaunchConfigConversion :
public OpConversionPattern<SourceOp> {
35 using OpConversionPattern<SourceOp>::OpConversionPattern;
38 matchAndRewrite(SourceOp op,
typename SourceOp::Adaptor adaptor,
39 ConversionPatternRewriter &rewriter)
const override;
44template <
typename SourceOp, spirv::BuiltIn builtin>
45class SingleDimLaunchConfigConversion :
public OpConversionPattern<SourceOp> {
47 using OpConversionPattern<SourceOp>::OpConversionPattern;
50 matchAndRewrite(SourceOp op,
typename SourceOp::Adaptor adaptor,
51 ConversionPatternRewriter &rewriter)
const override;
58class WorkGroupSizeConversion :
public OpConversionPattern<gpu::BlockDimOp> {
62 : OpConversionPattern(typeConverter, context, 10) {}
65 matchAndRewrite(gpu::BlockDimOp op, OpAdaptor adaptor,
66 ConversionPatternRewriter &rewriter)
const override;
70class GPUFuncOpConversion final :
public OpConversionPattern<gpu::GPUFuncOp> {
75 matchAndRewrite(gpu::GPUFuncOp funcOp, OpAdaptor adaptor,
76 ConversionPatternRewriter &rewriter)
const override;
83class GPUModuleConversion final :
public OpConversionPattern<gpu::GPUModuleOp> {
88 matchAndRewrite(gpu::GPUModuleOp moduleOp, OpAdaptor adaptor,
89 ConversionPatternRewriter &rewriter)
const override;
94class GPUReturnOpConversion final :
public OpConversionPattern<gpu::ReturnOp> {
99 matchAndRewrite(gpu::ReturnOp returnOp, OpAdaptor adaptor,
100 ConversionPatternRewriter &rewriter)
const override;
104class GPUBarrierConversion final :
public OpConversionPattern<gpu::BarrierOp> {
109 matchAndRewrite(gpu::BarrierOp barrierOp, OpAdaptor adaptor,
110 ConversionPatternRewriter &rewriter)
const override;
114class GPUShuffleConversion final :
public OpConversionPattern<gpu::ShuffleOp> {
119 matchAndRewrite(gpu::ShuffleOp shuffleOp, OpAdaptor adaptor,
120 ConversionPatternRewriter &rewriter)
const override;
124class GPURotateConversion final :
public OpConversionPattern<gpu::RotateOp> {
129 matchAndRewrite(gpu::RotateOp rotateOp, OpAdaptor adaptor,
130 ConversionPatternRewriter &rewriter)
const override;
133class GPUPrintfConversion final :
public OpConversionPattern<gpu::PrintfOp> {
138 matchAndRewrite(gpu::PrintfOp gpuPrintfOp, OpAdaptor adaptor,
139 ConversionPatternRewriter &rewriter)
const override;
148template <
typename SourceOp, spirv::BuiltIn builtin>
149LogicalResult LaunchConfigConversion<SourceOp, builtin>::matchAndRewrite(
150 SourceOp op,
typename SourceOp::Adaptor adaptor,
151 ConversionPatternRewriter &rewriter)
const {
152 auto *typeConverter = this->
template getTypeConverter<SPIRVTypeConverter>();
153 Type indexType = typeConverter->getIndexType();
167 typeConverter->getTargetEnv().allows(spirv::Capability::Shader);
168 Type builtinType = forShader ? rewriter.getIntegerType(32) : indexType;
172 Value dim = spirv::CompositeExtractOp::create(
173 rewriter, op.getLoc(), builtinType,
vector,
174 rewriter.getI32ArrayAttr({static_cast<int32_t>(op.getDimension())}));
175 if (forShader && builtinType != indexType)
176 dim = spirv::UConvertOp::create(rewriter, op.getLoc(), indexType, dim);
177 rewriter.replaceOp(op, dim);
181template <
typename SourceOp, spirv::BuiltIn builtin>
183SingleDimLaunchConfigConversion<SourceOp, builtin>::matchAndRewrite(
184 SourceOp op,
typename SourceOp::Adaptor adaptor,
185 ConversionPatternRewriter &rewriter)
const {
186 auto *typeConverter = this->
template getTypeConverter<SPIRVTypeConverter>();
187 Type indexType = typeConverter->getIndexType();
188 Type i32Type = rewriter.getIntegerType(32);
200 if (i32Type != indexType)
201 builtinValue = spirv::UConvertOp::create(rewriter, op.getLoc(), indexType,
203 rewriter.replaceOp(op, builtinValue);
207LogicalResult WorkGroupSizeConversion::matchAndRewrite(
208 gpu::BlockDimOp op, OpAdaptor adaptor,
209 ConversionPatternRewriter &rewriter)
const {
211 if (!workGroupSizeAttr)
215 workGroupSizeAttr.
asArrayRef()[
static_cast<int32_t
>(op.getDimension())];
217 getTypeConverter()->convertType(op.getResult().getType());
220 rewriter.replaceOpWithNewOp<spirv::ConstantOp>(
221 op, convertedType, IntegerAttr::get(convertedType, val));
232 ConversionPatternRewriter &rewriter,
233 spirv::EntryPointABIAttr entryPointInfo,
235 auto fnType = funcOp.getFunctionType();
236 if (fnType.getNumResults()) {
237 funcOp.emitError(
"SPIR-V lowering only supports entry functions"
238 "with no return values right now");
241 if (!argABIInfo.empty() && fnType.getNumInputs() != argABIInfo.size()) {
243 "lowering as entry functions requires ABI info for all arguments "
250 TypeConverter::SignatureConversion signatureConverter(fnType.getNumInputs());
252 for (
const auto &argType :
253 enumerate(funcOp.getFunctionType().getInputs())) {
254 auto convertedType = typeConverter.convertType(argType.value());
257 signatureConverter.addInputs(argType.index(), convertedType);
260 auto newFuncOp = spirv::FuncOp::create(
261 rewriter, funcOp.getLoc(), funcOp.getName(),
262 rewriter.getFunctionType(signatureConverter.getConvertedTypes(), {}));
263 for (
const auto &namedAttr : funcOp->getAttrs()) {
264 if (namedAttr.getName() == funcOp.getFunctionTypeAttrName() ||
267 newFuncOp->setAttr(namedAttr.getName(), namedAttr.getValue());
270 rewriter.inlineRegionBefore(funcOp.getBody(), newFuncOp.getBody(),
272 if (failed(rewriter.convertRegionTypes(&newFuncOp.getBody(), typeConverter,
273 &signatureConverter)))
275 rewriter.eraseOp(funcOp);
279 for (
auto argIndex : llvm::seq<unsigned>(0, argABIInfo.size())) {
280 newFuncOp.setArgAttr(argIndex, argABIAttrName, argABIInfo[argIndex]);
296 for (
auto argIndex : llvm::seq<unsigned>(0, funcOp.getNumArguments())) {
302 std::optional<spirv::StorageClass> sc;
303 if (funcOp.getArgument(argIndex).getType().isIntOrIndexOrFloat())
304 sc = spirv::StorageClass::StorageBuffer;
311LogicalResult GPUFuncOpConversion::matchAndRewrite(
312 gpu::GPUFuncOp funcOp, OpAdaptor adaptor,
313 ConversionPatternRewriter &rewriter)
const {
314 if (!gpu::GPUDialect::isKernel(funcOp))
317 auto *typeConverter = getTypeConverter<SPIRVTypeConverter>();
318 SmallVector<spirv::InterfaceVarABIAttr, 4> argABI;
322 for (
auto argIndex : llvm::seq<unsigned>(0, funcOp.getNumArguments())) {
324 auto abiAttr = funcOp.getArgAttrOfType<spirv::InterfaceVarABIAttr>(
328 "match failure: missing 'spirv.interface_var_abi' attribute at "
333 argABI.push_back(abiAttr);
338 if (!entryPointAttr) {
340 "match failure: missing 'spirv.entry_point_abi' attribute");
344 funcOp, *getTypeConverter(), rewriter, entryPointAttr, argABI);
347 newFuncOp->removeAttr(
348 rewriter.getStringAttr(gpu::GPUDialect::getKernelFuncAttrName()));
356LogicalResult GPUModuleConversion::matchAndRewrite(
357 gpu::GPUModuleOp moduleOp, OpAdaptor adaptor,
358 ConversionPatternRewriter &rewriter)
const {
359 auto *typeConverter = getTypeConverter<SPIRVTypeConverter>();
360 const spirv::TargetEnv &targetEnv = typeConverter->getTargetEnv();
362 targetEnv, typeConverter->getOptions().use64bitIndex);
365 return moduleOp.emitRemark(
366 "cannot deduce memory model from 'spirv.target_env'");
369 std::string spvModuleName = (
kSPIRVModule + moduleOp.getName()).str();
370 auto spvModule = spirv::ModuleOp::create(
371 rewriter, moduleOp.getLoc(), addressingModel, *memoryModel, std::nullopt,
372 StringRef(spvModuleName));
375 Region &spvModuleRegion = spvModule.getRegion();
376 rewriter.inlineRegionBefore(moduleOp.getBodyRegion(), spvModuleRegion,
377 spvModuleRegion.
begin());
379 rewriter.eraseBlock(&spvModuleRegion.
back());
385 if (
auto attr = moduleOp->getAttrOfType<spirv::TargetEnvAttr>(
388 if (
ArrayAttr targets = moduleOp.getTargetsAttr()) {
389 for (Attribute targetAttr : targets)
390 if (
auto spirvTargetEnvAttr =
391 dyn_cast<spirv::TargetEnvAttr>(targetAttr)) {
397 rewriter.eraseOp(moduleOp);
405LogicalResult GPUReturnOpConversion::matchAndRewrite(
406 gpu::ReturnOp returnOp, OpAdaptor adaptor,
407 ConversionPatternRewriter &rewriter)
const {
408 if (!adaptor.getOperands().empty())
411 rewriter.replaceOpWithNewOp<spirv::ReturnOp>(returnOp);
419LogicalResult GPUBarrierConversion::matchAndRewrite(
420 gpu::BarrierOp barrierOp, OpAdaptor adaptor,
421 ConversionPatternRewriter &rewriter)
const {
424 auto scope = spirv::ScopeAttr::get(context, spirv::Scope::Workgroup);
426 auto memorySemantics = spirv::MemorySemanticsAttr::get(
427 context, spirv::MemorySemantics::WorkgroupMemory |
428 spirv::MemorySemantics::AcquireRelease);
429 rewriter.replaceOpWithNewOp<spirv::ControlBarrierOp>(barrierOp, scope, scope,
438LogicalResult GPUShuffleConversion::matchAndRewrite(
439 gpu::ShuffleOp shuffleOp, OpAdaptor adaptor,
440 ConversionPatternRewriter &rewriter)
const {
444 auto targetEnv = getTypeConverter<SPIRVTypeConverter>()->getTargetEnv();
445 unsigned subgroupSize =
447 IntegerAttr widthAttr;
449 widthAttr.getValue().getZExtValue() != subgroupSize)
450 return rewriter.notifyMatchFailure(
451 shuffleOp,
"shuffle width and target subgroup size mismatch");
453 assert(!adaptor.getOffset().getType().isSignedInteger() &&
454 "shuffle offset must be a signless/unsigned integer");
456 Location loc = shuffleOp.getLoc();
457 auto scope = rewriter.getAttr<spirv::ScopeAttr>(spirv::Scope::Subgroup);
461 switch (shuffleOp.getMode()) {
462 case gpu::ShuffleMode::XOR: {
463 result = spirv::GroupNonUniformShuffleXorOp::create(
464 rewriter, loc, scope, adaptor.getValue(), adaptor.getOffset());
465 validVal = spirv::ConstantOp::getOne(rewriter.getI1Type(),
466 shuffleOp.getLoc(), rewriter);
469 case gpu::ShuffleMode::IDX: {
470 result = spirv::GroupNonUniformShuffleOp::create(
471 rewriter, loc, scope, adaptor.getValue(), adaptor.getOffset());
472 validVal = spirv::ConstantOp::getOne(rewriter.getI1Type(),
473 shuffleOp.getLoc(), rewriter);
476 case gpu::ShuffleMode::DOWN: {
477 result = spirv::GroupNonUniformShuffleDownOp::create(
478 rewriter, loc, scope, adaptor.getValue(), adaptor.getOffset());
480 Value laneId = gpu::LaneIdOp::create(rewriter, loc, widthAttr);
482 arith::AddIOp::create(rewriter, loc, laneId, adaptor.getOffset());
483 validVal = arith::CmpIOp::create(rewriter, loc, arith::CmpIPredicate::ult,
484 resultLaneId, adaptor.getWidth());
487 case gpu::ShuffleMode::UP: {
488 result = spirv::GroupNonUniformShuffleUpOp::create(
489 rewriter, loc, scope, adaptor.getValue(), adaptor.getOffset());
491 Value laneId = gpu::LaneIdOp::create(rewriter, loc, widthAttr);
493 arith::SubIOp::create(rewriter, loc, laneId, adaptor.getOffset());
494 auto i32Type = rewriter.getIntegerType(32);
495 validVal = arith::CmpIOp::create(
496 rewriter, loc, arith::CmpIPredicate::sge, resultLaneId,
497 arith::ConstantOp::create(rewriter, loc, i32Type,
498 rewriter.getIntegerAttr(i32Type, 0)));
503 rewriter.replaceOp(shuffleOp, {
result, validVal});
511LogicalResult GPURotateConversion::matchAndRewrite(
512 gpu::RotateOp rotateOp, OpAdaptor adaptor,
513 ConversionPatternRewriter &rewriter)
const {
514 const spirv::TargetEnv &targetEnv =
515 getTypeConverter<SPIRVTypeConverter>()->getTargetEnv();
516 unsigned subgroupSize =
518 unsigned width = rotateOp.getWidth();
519 if (width > subgroupSize)
520 return rewriter.notifyMatchFailure(
521 rotateOp,
"rotate width is larger than target subgroup size");
523 Location loc = rotateOp.getLoc();
524 auto scope = rewriter.getAttr<spirv::ScopeAttr>(spirv::Scope::Subgroup);
526 arith::ConstantOp::create(rewriter, loc, adaptor.getOffsetAttr());
528 arith::ConstantOp::create(rewriter, loc, adaptor.getWidthAttr());
529 Value rotateResult = spirv::GroupNonUniformRotateKHROp::create(
530 rewriter, loc, scope, adaptor.getValue(), offsetVal, widthVal);
532 if (width == subgroupSize) {
533 validVal = spirv::ConstantOp::getOne(rewriter.getI1Type(), loc, rewriter);
535 IntegerAttr widthAttr = adaptor.getWidthAttr();
536 Value laneId = gpu::LaneIdOp::create(rewriter, loc, widthAttr);
537 validVal = arith::CmpIOp::create(rewriter, loc, arith::CmpIPredicate::ult,
541 rewriter.replaceOp(rotateOp, {rotateResult, validVal});
549template <
typename UniformOp,
typename NonUniformOp>
551 Value arg,
bool isGroup,
bool isUniform,
552 std::optional<uint32_t> clusterSize) {
554 auto scope = mlir::spirv::ScopeAttr::get(builder.
getContext(),
555 isGroup ? spirv::Scope::Workgroup
556 : spirv::Scope::Subgroup);
557 auto groupOp = spirv::GroupOperationAttr::get(
559 ? spirv::GroupOperation::ClusteredReduce
560 : spirv::GroupOperation::Reduce);
562 return UniformOp::create(builder, loc, type, scope, groupOp, arg)
566 Value clusterSizeValue;
567 if (clusterSize.has_value())
568 clusterSizeValue = spirv::ConstantOp::create(
572 return NonUniformOp::create(builder, loc, type, scope, groupOp, arg,
577static std::optional<Value>
579 gpu::AllReduceOperation opType,
bool isGroup,
580 bool isUniform, std::optional<uint32_t> clusterSize) {
581 enum class ElemType { Float, Boolean, Integer };
583 std::optional<uint32_t>);
585 gpu::AllReduceOperation kind;
591 ElemType elementType;
592 if (isa<FloatType>(type)) {
593 elementType = ElemType::Float;
594 }
else if (
auto intTy = dyn_cast<IntegerType>(type)) {
595 elementType = (intTy.getIntOrFloatBitWidth() == 1) ? ElemType::Boolean
606 using ReduceType = gpu::AllReduceOperation;
607 const OpHandler handlers[] = {
608 {ReduceType::ADD, ElemType::Integer,
610 spirv::GroupNonUniformIAddOp>},
611 {ReduceType::ADD, ElemType::Float,
613 spirv::GroupNonUniformFAddOp>},
614 {ReduceType::MUL, ElemType::Integer,
616 spirv::GroupNonUniformIMulOp>},
617 {ReduceType::MUL, ElemType::Float,
619 spirv::GroupNonUniformFMulOp>},
620 {ReduceType::MINUI, ElemType::Integer,
622 spirv::GroupNonUniformUMinOp>},
623 {ReduceType::MINSI, ElemType::Integer,
625 spirv::GroupNonUniformSMinOp>},
626 {ReduceType::MINNUMF, ElemType::Float,
628 spirv::GroupNonUniformFMinOp>},
629 {ReduceType::MAXUI, ElemType::Integer,
631 spirv::GroupNonUniformUMaxOp>},
632 {ReduceType::MAXSI, ElemType::Integer,
634 spirv::GroupNonUniformSMaxOp>},
635 {ReduceType::MAXNUMF, ElemType::Float,
637 spirv::GroupNonUniformFMaxOp>},
638 {ReduceType::MINIMUMF, ElemType::Float,
640 spirv::GroupNonUniformFMinOp>},
641 {ReduceType::MAXIMUMF, ElemType::Float,
643 spirv::GroupNonUniformFMaxOp>}};
645 for (
const OpHandler &handler : handlers)
646 if (handler.kind == opType && elementType == handler.elemType)
647 return handler.func(builder, loc, arg, isGroup, isUniform, clusterSize);
654 :
public OpConversionPattern<gpu::AllReduceOp> {
660 ConversionPatternRewriter &rewriter)
const override {
661 auto opType = op.getOp();
670 true, op.getUniform(), std::nullopt);
674 rewriter.replaceOp(op, *
result);
681 :
public OpConversionPattern<gpu::SubgroupReduceOp> {
687 ConversionPatternRewriter &rewriter)
const override {
688 if (op.getClusterStride() > 1) {
689 return rewriter.notifyMatchFailure(
690 op,
"lowering for cluster stride > 1 is not implemented");
693 if (!isa<spirv::ScalarType>(adaptor.getValue().getType()))
694 return rewriter.notifyMatchFailure(op,
"reduction type is not a scalar");
697 rewriter, op.getLoc(), adaptor.getValue(), adaptor.getOp(),
698 false, adaptor.getUniform(), op.getClusterSize());
702 rewriter.replaceOp(op, *
result);
711static std::string
makeVarName(spirv::ModuleOp moduleOp, llvm::Twine prefix) {
717 name = (prefix + llvm::Twine(number++)).str();
718 }
while (moduleOp.lookupSymbol(name));
725LogicalResult GPUPrintfConversion::matchAndRewrite(
726 gpu::PrintfOp gpuPrintfOp, OpAdaptor adaptor,
727 ConversionPatternRewriter &rewriter)
const {
729 Location loc = gpuPrintfOp.getLoc();
731 auto moduleOp = gpuPrintfOp->getParentOfType<spirv::ModuleOp>();
738 std::string globalVarName =
makeVarName(moduleOp, llvm::Twine(
"printfMsg"));
739 spirv::GlobalVariableOp globalVar;
741 IntegerType i8Type = rewriter.getI8Type();
742 IntegerType i32Type = rewriter.getI32Type();
749 auto createSpecConstant = [&](
unsigned value) {
750 auto attr = rewriter.getI8IntegerAttr(value);
751 std::string specCstName =
752 makeVarName(moduleOp, llvm::Twine(globalVarName) +
"_sc");
754 return spirv::SpecConstantOp::create(
755 rewriter, loc, rewriter.getStringAttr(specCstName), attr);
761 ConversionPatternRewriter::InsertionGuard guard(rewriter);
764 rewriter.setInsertionPointToStart(
771 llvm::SmallString<20> formatString(adaptor.getFormat());
772 formatString.push_back(
'\0');
773 SmallVector<Attribute, 4> constituents;
774 for (
char c : formatString) {
775 spirv::SpecConstantOp cSpecConstantOp = createSpecConstant(c);
776 constituents.push_back(SymbolRefAttr::get(cSpecConstantOp));
780 size_t contentSize = constituents.size();
782 spirv::SpecConstantCompositeOp specCstComposite;
785 std::string specCstCompositeName =
786 (llvm::Twine(globalVarName) +
"_scc").str();
788 specCstComposite = spirv::SpecConstantCompositeOp::create(
789 rewriter, loc, TypeAttr::get(globalType),
790 rewriter.getStringAttr(specCstCompositeName),
791 rewriter.getArrayAttr(constituents));
794 globalType, spirv::StorageClass::UniformConstant);
799 globalVar = spirv::GlobalVariableOp::create(
800 rewriter, loc, ptrType, globalVarName,
803 globalVar->setAttr(
"Constant", rewriter.getUnitAttr());
807 Value globalPtr = spirv::AddressOfOp::create(rewriter, loc, globalVar);
808 Value fmtStr = spirv::BitcastOp::create(
814 auto printfArgs = llvm::to_vector_of<Value, 4>(adaptor.getArgs());
816 spirv::CLPrintfOp::create(rewriter, loc, i32Type, fmtStr, printfArgs);
821 rewriter.eraseOp(gpuPrintfOp);
833 GPUBarrierConversion, GPUFuncOpConversion, GPUModuleConversion,
834 GPUReturnOpConversion, GPUShuffleConversion, GPURotateConversion,
835 LaunchConfigConversion<gpu::BlockIdOp, spirv::BuiltIn::WorkgroupId>,
836 LaunchConfigConversion<gpu::GridDimOp, spirv::BuiltIn::NumWorkgroups>,
837 LaunchConfigConversion<gpu::BlockDimOp, spirv::BuiltIn::WorkgroupSize>,
838 LaunchConfigConversion<gpu::ThreadIdOp,
839 spirv::BuiltIn::LocalInvocationId>,
840 LaunchConfigConversion<gpu::GlobalIdOp,
841 spirv::BuiltIn::GlobalInvocationId>,
842 SingleDimLaunchConfigConversion<gpu::SubgroupIdOp,
843 spirv::BuiltIn::SubgroupId>,
844 SingleDimLaunchConfigConversion<gpu::NumSubgroupsOp,
845 spirv::BuiltIn::NumSubgroups>,
846 SingleDimLaunchConfigConversion<gpu::SubgroupSizeOp,
847 spirv::BuiltIn::SubgroupSize>,
848 SingleDimLaunchConfigConversion<
849 gpu::LaneIdOp, spirv::BuiltIn::SubgroupLocalInvocationId>,
static std::optional< Value > createGroupReduceOp(OpBuilder &builder, Location loc, Value arg, gpu::AllReduceOperation opType, bool isGroup, bool isUniform, std::optional< uint32_t > clusterSize)
static LogicalResult getDefaultABIAttrs(const spirv::TargetEnv &targetEnv, gpu::GPUFuncOp funcOp, SmallVectorImpl< spirv::InterfaceVarABIAttr > &argABI)
Populates argABI with spirv.interface_var_abi attributes for lowering gpu.func to spirv....
static constexpr const char kSPIRVModule[]
static Value createGroupReduceOpImpl(OpBuilder &builder, Location loc, Value arg, bool isGroup, bool isUniform, std::optional< uint32_t > clusterSize)
static spirv::FuncOp lowerAsEntryFunction(gpu::GPUFuncOp funcOp, const TypeConverter &typeConverter, ConversionPatternRewriter &rewriter, spirv::EntryPointABIAttr entryPointInfo, ArrayRef< spirv::InterfaceVarABIAttr > argABIInfo)
static std::string makeVarName(spirv::ModuleOp moduleOp, llvm::Twine prefix)
Pattern to convert a gpu.all_reduce op into a SPIR-V group op.
LogicalResult matchAndRewrite(gpu::AllReduceOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
Pattern to convert a gpu.subgroup_reduce op into a SPIR-V group op.
LogicalResult matchAndRewrite(gpu::SubgroupReduceOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
IntegerAttr getIntegerAttr(Type type, int64_t value)
MLIRContext * getContext() const
static FlatSymbolRefAttr get(StringAttr value)
Construct a symbol reference for the given value name.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
MLIRContext is the top-level object for a collection of MLIR operations.
This class helps build Operations.
Region & getRegion(unsigned index)
Returns the region held by this operation at position 'index'.
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.
static Operation * getNearestSymbolTable(Operation *from)
Returns the nearest symbol table from a given operation from.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Type getType() const
Return the type of this value.
ArrayRef< T > asArrayRef() const
static ArrayType get(Type elementType, unsigned elementCount)
An attribute that specifies the information regarding the interface variable: descriptor set,...
static PointerType get(Type pointeeType, StorageClass storageClass)
ResourceLimitsAttr getResourceLimits() const
Returns the target resource limits.
A wrapper class around a spirv::TargetEnvAttr to provide query methods for allowed version/capabiliti...
TargetEnvAttr getAttr() const
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...
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, StringRef prefix="__builtin__", StringRef suffix="__")
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, bool use64bitAddress)
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.
const FrozenRewritePatternSet & patterns
detail::DenseArrayAttrImpl< int32_t > DenseI32ArrayAttr
void populateGPUToSPIRVPatterns(const SPIRVTypeConverter &typeConverter, RewritePatternSet &patterns)
Appends to a pattern list additional patterns for translating GPU Ops to SPIR-V ops.
detail::constant_op_matcher m_Constant()
Matches a constant foldable operation.