24#include "llvm/ADT/FloatingPointMode.h"
25#include "llvm/ADT/TypeSwitch.h"
26#include "llvm/Support/FormatVariadic.h"
28#define DEBUG_TYPE "spirv-to-llvm-pattern"
40 if (
auto vecType = dyn_cast<VectorType>(type))
41 return vecType.getElementType().isSignedInteger();
49 if (
auto vecType = dyn_cast<VectorType>(type))
50 return vecType.getElementType().isUnsignedInteger();
57 if (
auto intType = dyn_cast<IntegerType>(type))
58 return intType.getWidth();
59 if (
auto vecType = dyn_cast<VectorType>(type))
60 if (
auto intType = dyn_cast<IntegerType>(vecType.getElementType()))
61 return intType.getWidth();
68 "bitwidth is not supported for this type");
71 auto vecType = dyn_cast<VectorType>(type);
72 auto elementType = vecType.getElementType();
73 assert(elementType.isIntOrFloat() &&
74 "only integers and floats have a bitwidth");
75 return elementType.getIntOrFloatBitWidth();
80 if (
auto vecTy = dyn_cast<VectorType>(type))
81 type = vecTy.getElementType();
82 return cast<IntegerType>(type).getWidth();
89 IntegerAttr scalarAttr) {
90 if (
auto vecType = dyn_cast<VectorType>(srcType))
91 return LLVM::ConstantOp::create(
93 return LLVM::ConstantOp::create(rewriter, loc, dstType, scalarAttr);
99 auto integerType = cast<IntegerType>(
100 isa<VectorType>(srcType) ? cast<VectorType>(srcType).
getElementType()
109 if (
auto vecType = dyn_cast<VectorType>(srcType)) {
110 auto floatType = cast<FloatType>(vecType.getElementType());
111 return LLVM::ConstantOp::create(
112 rewriter, loc, dstType,
116 auto floatType = cast<FloatType>(srcType);
117 return LLVM::ConstantOp::create(rewriter, loc, dstType,
130 auto srcType = value.
getType();
136 if (valueBitWidth < targetBitWidth)
137 return LLVM::ZExtOp::create(rewriter, loc, llvmType, value);
142 if (valueBitWidth > targetBitWidth)
143 return LLVM::TruncOp::create(rewriter, loc, llvmType, value);
150 ConversionPatternRewriter &rewriter) {
151 auto vectorType = VectorType::get(numElements, toBroadcast.
getType());
152 auto llvmVectorType = typeConverter.convertType(vectorType);
153 auto llvmI32Type = typeConverter.convertType(rewriter.getIntegerType(32));
154 Value broadcasted = LLVM::PoisonOp::create(rewriter, loc, llvmVectorType);
155 for (
unsigned i = 0; i < numElements; ++i) {
156 auto index = LLVM::ConstantOp::create(rewriter, loc, llvmI32Type,
157 rewriter.getI32IntegerAttr(i));
158 broadcasted = LLVM::InsertElementOp::create(
159 rewriter, loc, llvmVectorType, broadcasted, toBroadcast,
index);
167 ConversionPatternRewriter &rewriter) {
168 if (
auto vectorType = dyn_cast<VectorType>(srcType)) {
169 unsigned numElements = vectorType.getNumElements();
170 return broadcast(loc, value, numElements, typeConverter, rewriter);
187 ConversionPatternRewriter &rewriter) {
201 if (failed(converter.convertTypes(type.
getElementTypes(), elementsVector)))
203 return LLVM::LLVMStructType::getLiteral(type.getContext(), elementsVector,
211 if (failed(converter.convertTypes(type.
getElementTypes(), elementsVector)))
213 return LLVM::LLVMStructType::getLiteral(type.getContext(), elementsVector,
220 return LLVM::ConstantOp::create(
221 rewriter, loc, IntegerType::get(rewriter.
getContext(), 32),
227 ConversionPatternRewriter &rewriter,
229 unsigned alignment,
bool isVolatile,
230 bool isNonTemporal) {
231 if (
auto loadOp = dyn_cast<spirv::LoadOp>(op)) {
232 auto dstType = typeConverter.convertType(loadOp.getType());
234 return rewriter.notifyMatchFailure(op,
"type conversion failed");
235 rewriter.replaceOpWithNewOp<LLVM::LoadOp>(
236 loadOp, dstType, spirv::LoadOpAdaptor(operands).getPtr(), alignment,
237 isVolatile, isNonTemporal);
240 auto storeOp = cast<spirv::StoreOp>(op);
241 spirv::StoreOpAdaptor adaptor(operands);
242 rewriter.replaceOpWithNewOp<LLVM::StoreOp>(storeOp, adaptor.getValue(),
243 adaptor.getPtr(), alignment,
244 isVolatile, isNonTemporal);
259 auto sizeInBytes = cast<spirv::SPIRVType>(elementType).getSizeInBytes();
260 if (stride != 0 && (!sizeInBytes || *sizeInBytes != stride))
263 auto llvmElementType = converter.convertType(elementType);
265 return LLVM::LLVMArrayType::get(llvmElementType, numElements);
272 spirv::ClientAPI clientAPI) {
273 unsigned addressSpace =
275 return LLVM::LLVMPointerType::get(type.getContext(), addressSpace);
286 return LLVM::LLVMArrayType::get(elementType, 0);
295 if (!memberDecorations.empty())
308template <
typename TargetOp,
typename SourceOp>
310collectAttrsForConversion(SourceOp op,
311 typename TargetOp::Properties &properties,
314 if (
auto sourceProperties =
315 dyn_cast_or_null<DictionaryAttr>(op->getPropertiesAsAttribute()))
316 attrs.append(sourceProperties.getValue());
318 if constexpr (std::is_same_v<
typename TargetOp::Properties,
320 llvm::append_range(discardableAttrs, attrs);
324 TargetOp::populateDefaultProperties(
325 OperationName(TargetOp::getOperationName(), op->getContext()),
327 if (
failed(TargetOp::setPropertiesFromAttr(
328 properties, attrs.getDictionary(op->getContext()),
329 [&]() { return op.emitError(
"failed to convert properties"); })))
332 auto convertedProperties = dyn_cast_or_null<DictionaryAttr>(
333 TargetOp::getPropertiesAsAttr(op->getContext(), properties));
335 StringRef name = attr.getName().getValue();
336 bool isProperty = convertedProperties && convertedProperties.contains(name);
337 if (name ==
"operand_segment_sizes")
338 isProperty |= convertedProperties &&
339 convertedProperties.contains(
"operandSegmentSizes");
340 if (name ==
"result_segment_sizes")
341 isProperty |= convertedProperties &&
342 convertedProperties.contains(
"resultSegmentSizes");
344 discardableAttrs.push_back(attr);
349template <
typename SPIRVOp,
bool InBounds>
352 using SPIRVToLLVMConversion<SPIRVOp>::SPIRVToLLVMConversion;
355 matchAndRewrite(SPIRVOp op,
typename SPIRVOp::Adaptor adaptor,
356 ConversionPatternRewriter &rewriter)
const override {
358 this->getTypeConverter()->convertType(op.getComponentPtr().getType());
360 return rewriter.notifyMatchFailure(op,
"type conversion failed");
361 if (op.getIndices().empty()) {
362 rewriter.replaceOp(op, adaptor.getBasePtr());
365 auto elementType = this->getTypeConverter()->convertType(
366 cast<spirv::PointerType>(op.getBasePtr().getType()).getPointeeType());
368 return rewriter.notifyMatchFailure(op,
"type conversion failed");
370 auto indices = llvm::to_vector<4>(adaptor.getIndices());
371 Type indexType = op.getIndices().front().getType();
372 auto llvmIndexType = this->getTypeConverter()->convertType(indexType);
374 return rewriter.notifyMatchFailure(op,
"type conversion failed");
376 LLVM::ConstantOp::create(rewriter, op.getLoc(), llvmIndexType,
377 rewriter.getIntegerAttr(llvmIndexType, 0));
380 rewriter.replaceOpWithNewOp<LLVM::GEPOp>(
381 op, dstType, elementType, adaptor.getBasePtr(),
indices,
382 InBounds ? LLVM::GEPNoWrapFlags::inbounds : LLVM::GEPNoWrapFlags::none);
390template <
typename SPIRVOp,
bool InBounds>
393 using SPIRVToLLVMConversion<SPIRVOp>::SPIRVToLLVMConversion;
396 matchAndRewrite(SPIRVOp op,
typename SPIRVOp::Adaptor adaptor,
397 ConversionPatternRewriter &rewriter)
const override {
398 auto baseType = cast<spirv::PointerType>(op.getBasePtr().getType());
401 switch (baseType.getStorageClass()) {
402 case spirv::StorageClass::Uniform:
403 case spirv::StorageClass::StorageBuffer:
404 case spirv::StorageClass::PushConstant:
405 case spirv::StorageClass::PhysicalStorageBuffer:
406 return rewriter.notifyMatchFailure(
407 op,
"pointer ArrayStride is not supported for this storage class");
412 auto dstType = this->getTypeConverter()->convertType(op.getType());
414 return rewriter.notifyMatchFailure(op,
"type conversion failed");
417 this->getTypeConverter()->convertType(baseType.getPointeeType());
419 return rewriter.notifyMatchFailure(op,
"type conversion failed");
422 indices.push_back(adaptor.getElement());
423 llvm::append_range(
indices, adaptor.getIndices());
425 rewriter.replaceOpWithNewOp<LLVM::GEPOp>(
426 op, dstType, elementType, adaptor.getBasePtr(),
indices,
427 InBounds ? LLVM::GEPNoWrapFlags::inbounds : LLVM::GEPNoWrapFlags::none);
434 using SPIRVToLLVMConversion<spirv::AddressOfOp>::SPIRVToLLVMConversion;
437 matchAndRewrite(spirv::AddressOfOp op, OpAdaptor adaptor,
438 ConversionPatternRewriter &rewriter)
const override {
439 auto dstType = getTypeConverter()->convertType(op.getPointer().getType());
441 return rewriter.notifyMatchFailure(op,
"type conversion failed");
442 rewriter.replaceOpWithNewOp<LLVM::AddressOfOp>(op, dstType,
448class BitFieldInsertPattern
451 using SPIRVToLLVMConversion<spirv::BitFieldInsertOp>::SPIRVToLLVMConversion;
454 matchAndRewrite(spirv::BitFieldInsertOp op, OpAdaptor adaptor,
455 ConversionPatternRewriter &rewriter)
const override {
456 auto srcType = op.getType();
457 auto dstType = getTypeConverter()->convertType(srcType);
459 return rewriter.notifyMatchFailure(op,
"type conversion failed");
460 Location loc = op.getLoc();
464 *getTypeConverter(), rewriter);
466 *getTypeConverter(), rewriter);
470 Value maskShiftedByCount =
471 LLVM::ShlOp::create(rewriter, loc, dstType, minusOne, count);
472 Value negated = LLVM::XOrOp::create(rewriter, loc, dstType,
473 maskShiftedByCount, minusOne);
474 Value maskShiftedByCountAndOffset =
475 LLVM::ShlOp::create(rewriter, loc, dstType, negated, offset);
476 Value mask = LLVM::XOrOp::create(rewriter, loc, dstType,
477 maskShiftedByCountAndOffset, minusOne);
482 LLVM::AndOp::create(rewriter, loc, dstType, op.getBase(), mask);
483 Value insertShiftedByOffset =
484 LLVM::ShlOp::create(rewriter, loc, dstType, op.getInsert(), offset);
485 rewriter.replaceOpWithNewOp<LLVM::OrOp>(op, dstType, baseAndMask,
486 insertShiftedByOffset);
492class ConstantScalarAndVectorPattern
495 using SPIRVToLLVMConversion<spirv::ConstantOp>::SPIRVToLLVMConversion;
498 matchAndRewrite(spirv::ConstantOp constOp, OpAdaptor adaptor,
499 ConversionPatternRewriter &rewriter)
const override {
500 auto srcType = constOp.getType();
501 if (!isa<VectorType>(srcType) && !srcType.isIntOrFloat())
504 auto dstType = getTypeConverter()->convertType(srcType);
506 return rewriter.notifyMatchFailure(constOp,
"type conversion failed");
515 auto signlessType = rewriter.getIntegerType(
getBitWidth(srcType));
517 if (isa<VectorType>(srcType)) {
518 auto dstElementsAttr = cast<DenseIntElementsAttr>(constOp.getValue());
519 rewriter.replaceOpWithNewOp<LLVM::ConstantOp>(
521 dstElementsAttr.mapValues(
522 signlessType, [&](
const APInt &value) {
return value; }));
525 auto srcAttr = cast<IntegerAttr>(constOp.getValue());
526 auto dstAttr = rewriter.getIntegerAttr(signlessType, srcAttr.getValue());
527 rewriter.replaceOpWithNewOp<LLVM::ConstantOp>(constOp, dstType, dstAttr);
530 LLVM::ConstantOp::Properties properties{};
531 SmallVector<NamedAttribute> discardableAttrs;
532 if (
failed(collectAttrsForConversion<LLVM::ConstantOp>(constOp, properties,
535 rewriter.replaceOpWithNewOp<LLVM::ConstantOp>(
536 constOp, dstType, adaptor.getOperands(), properties, discardableAttrs);
541class BitFieldSExtractPattern
544 using SPIRVToLLVMConversion<spirv::BitFieldSExtractOp>::SPIRVToLLVMConversion;
547 matchAndRewrite(spirv::BitFieldSExtractOp op, OpAdaptor adaptor,
548 ConversionPatternRewriter &rewriter)
const override {
549 auto srcType = op.getType();
550 auto dstType = getTypeConverter()->convertType(srcType);
552 return rewriter.notifyMatchFailure(op,
"type conversion failed");
553 Location loc = op.getLoc();
557 *getTypeConverter(), rewriter);
559 *getTypeConverter(), rewriter);
562 IntegerType integerType;
563 if (
auto vecType = dyn_cast<VectorType>(srcType))
564 integerType = cast<IntegerType>(vecType.getElementType());
566 integerType = cast<IntegerType>(srcType);
568 auto baseSize = rewriter.getIntegerAttr(integerType,
getBitWidth(srcType));
570 isa<VectorType>(srcType)
571 ? LLVM::ConstantOp::create(
572 rewriter, loc, dstType,
573 SplatElementsAttr::get(cast<ShapedType>(srcType), baseSize))
574 : LLVM::ConstantOp::create(rewriter, loc, dstType, baseSize);
578 Value countPlusOffset =
579 LLVM::AddOp::create(rewriter, loc, dstType, count, offset);
580 Value amountToShiftLeft =
581 LLVM::SubOp::create(rewriter, loc, dstType, size, countPlusOffset);
582 Value baseShiftedLeft = LLVM::ShlOp::create(
583 rewriter, loc, dstType, op.getBase(), amountToShiftLeft);
586 Value amountToShiftRight =
587 LLVM::AddOp::create(rewriter, loc, dstType, offset, amountToShiftLeft);
588 rewriter.replaceOpWithNewOp<LLVM::AShrOp>(op, dstType, baseShiftedLeft,
594class BitFieldUExtractPattern
597 using SPIRVToLLVMConversion<spirv::BitFieldUExtractOp>::SPIRVToLLVMConversion;
600 matchAndRewrite(spirv::BitFieldUExtractOp op, OpAdaptor adaptor,
601 ConversionPatternRewriter &rewriter)
const override {
602 auto srcType = op.getType();
603 auto dstType = getTypeConverter()->convertType(srcType);
605 return rewriter.notifyMatchFailure(op,
"type conversion failed");
606 Location loc = op.getLoc();
610 *getTypeConverter(), rewriter);
612 *getTypeConverter(), rewriter);
616 Value maskShiftedByCount =
617 LLVM::ShlOp::create(rewriter, loc, dstType, minusOne, count);
618 Value mask = LLVM::XOrOp::create(rewriter, loc, dstType, maskShiftedByCount,
623 LLVM::LShrOp::create(rewriter, loc, dstType, op.getBase(), offset);
624 rewriter.replaceOpWithNewOp<LLVM::AndOp>(op, dstType, shiftedBase, mask);
631 using SPIRVToLLVMConversion<spirv::BranchOp>::SPIRVToLLVMConversion;
634 matchAndRewrite(spirv::BranchOp branchOp, OpAdaptor adaptor,
635 ConversionPatternRewriter &rewriter)
const override {
636 rewriter.replaceOpWithNewOp<LLVM::BrOp>(branchOp, adaptor.getOperands(),
637 branchOp.getTarget());
642class BranchConditionalConversionPattern
645 using SPIRVToLLVMConversion<
646 spirv::BranchConditionalOp>::SPIRVToLLVMConversion;
649 matchAndRewrite(spirv::BranchConditionalOp op, OpAdaptor adaptor,
650 ConversionPatternRewriter &rewriter)
const override {
653 if (
auto weights = op.getBranchWeights()) {
654 SmallVector<int32_t> weightValues;
655 for (
auto weight : weights->getAsRange<IntegerAttr>())
656 weightValues.push_back(weight.getInt());
660 rewriter.replaceOpWithNewOp<LLVM::CondBrOp>(
661 op, op.getCondition(), op.getTrueBlockArguments(),
662 op.getFalseBlockArguments(), branchWeights, op.getTrueBlock(),
671class CompositeExtractPattern
674 using SPIRVToLLVMConversion<spirv::CompositeExtractOp>::SPIRVToLLVMConversion;
677 matchAndRewrite(spirv::CompositeExtractOp op, OpAdaptor adaptor,
678 ConversionPatternRewriter &rewriter)
const override {
679 auto dstType = this->getTypeConverter()->convertType(op.getType());
681 return rewriter.notifyMatchFailure(op,
"type conversion failed");
683 Type containerType = op.getComposite().getType();
684 if (isa<VectorType>(containerType)) {
685 Location loc = op.getLoc();
686 IntegerAttr value = cast<IntegerAttr>(op.getIndices()[0]);
688 rewriter.replaceOpWithNewOp<LLVM::ExtractElementOp>(
689 op, dstType, adaptor.getComposite(), index);
693 rewriter.replaceOpWithNewOp<LLVM::ExtractValueOp>(
694 op, adaptor.getComposite(),
695 LLVM::convertArrayToIndices(op.getIndices()));
703class CompositeInsertPattern
706 using SPIRVToLLVMConversion<spirv::CompositeInsertOp>::SPIRVToLLVMConversion;
709 matchAndRewrite(spirv::CompositeInsertOp op, OpAdaptor adaptor,
710 ConversionPatternRewriter &rewriter)
const override {
711 auto dstType = this->getTypeConverter()->convertType(op.getType());
713 return rewriter.notifyMatchFailure(op,
"type conversion failed");
715 Type containerType = op.getComposite().getType();
716 if (isa<VectorType>(containerType)) {
717 Location loc = op.getLoc();
718 IntegerAttr value = cast<IntegerAttr>(op.getIndices()[0]);
720 rewriter.replaceOpWithNewOp<LLVM::InsertElementOp>(
721 op, dstType, adaptor.getComposite(), adaptor.getObject(), index);
725 rewriter.replaceOpWithNewOp<LLVM::InsertValueOp>(
726 op, adaptor.getComposite(), adaptor.getObject(),
727 LLVM::convertArrayToIndices(op.getIndices()));
734template <
typename SPIRVOp,
typename LLVMOp>
737 using SPIRVToLLVMConversion<SPIRVOp>::SPIRVToLLVMConversion;
740 matchAndRewrite(SPIRVOp op,
typename SPIRVOp::Adaptor adaptor,
741 ConversionPatternRewriter &rewriter)
const override {
742 auto dstType = this->getTypeConverter()->convertType(op.getType());
744 return rewriter.notifyMatchFailure(op,
"type conversion failed");
745 typename LLVMOp::Properties properties{};
746 SmallVector<NamedAttribute> discardableAttrs;
747 if (
failed(collectAttrsForConversion<LLVMOp>(op, properties,
750 rewriter.template replaceOpWithNewOp<LLVMOp>(
751 op, dstType, adaptor.getOperands(), properties, discardableAttrs);
761template <
typename SPIRVOp,
typename LLVMOp>
764 using SPIRVToLLVMConversion<SPIRVOp>::SPIRVToLLVMConversion;
767 matchAndRewrite(SPIRVOp op,
typename SPIRVOp::Adaptor adaptor,
768 ConversionPatternRewriter &rewriter)
const override {
769 Type dstType = this->getTypeConverter()->convertType(op.getType());
771 return rewriter.notifyMatchFailure(op,
"type conversion failed");
773 Location loc = op.getLoc();
774 Type operandType = adaptor.getOperand1().getType();
775 Type overflowType = rewriter.getI1Type();
776 if (
auto vecType = dyn_cast<VectorType>(operandType))
777 overflowType = VectorType::get(vecType.getShape(), overflowType);
779 Type intrType = LLVM::LLVMStructType::getLiteral(
780 rewriter.getContext(), {operandType, overflowType});
781 Value intrResult = LLVMOp::create(
782 rewriter, loc, intrType, adaptor.getOperand1(), adaptor.getOperand2());
783 Value lowBits = LLVM::ExtractValueOp::create(rewriter, loc, intrResult, 0);
784 Value overflow = LLVM::ExtractValueOp::create(rewriter, loc, intrResult, 1);
785 overflow = LLVM::ZExtOp::create(rewriter, loc, operandType, overflow);
787 Value
result = LLVM::PoisonOp::create(rewriter, loc, dstType);
788 result = LLVM::InsertValueOp::create(rewriter, loc,
result, lowBits,
789 ArrayRef<int64_t>{0});
790 result = LLVM::InsertValueOp::create(rewriter, loc,
result, overflow,
791 ArrayRef<int64_t>{1});
792 rewriter.replaceOp(op,
result);
800template <
typename SPIRVOp,
typename LLVMExtOp>
803 using SPIRVToLLVMConversion<SPIRVOp>::SPIRVToLLVMConversion;
806 matchAndRewrite(SPIRVOp op,
typename SPIRVOp::Adaptor adaptor,
807 ConversionPatternRewriter &rewriter)
const override {
808 Type dstType = this->getTypeConverter()->convertType(op.getType());
810 return rewriter.notifyMatchFailure(op,
"type conversion failed");
812 Location loc = op.getLoc();
813 Type operandType = adaptor.getOperand1().getType();
815 IntegerType wideElemType = rewriter.getIntegerType(bitwidth * 2);
816 Type wideType = wideElemType;
817 if (
auto vecType = dyn_cast<VectorType>(operandType))
818 wideType = VectorType::get(vecType.getShape(), wideElemType);
821 LLVMExtOp::create(rewriter, loc, wideType, adaptor.getOperand1());
823 LLVMExtOp::create(rewriter, loc, wideType, adaptor.getOperand2());
824 Value
mul = LLVM::MulOp::create(rewriter, loc, wideType,
lhs,
rhs);
825 Value low = LLVM::TruncOp::create(rewriter, loc, operandType,
mul);
828 rewriter.getIntegerAttr(wideElemType, bitwidth));
829 Value high = LLVM::LShrOp::create(rewriter, loc,
mul, shift);
830 high = LLVM::TruncOp::create(rewriter, loc, operandType, high);
832 Value
result = LLVM::PoisonOp::create(rewriter, loc, dstType);
833 result = LLVM::InsertValueOp::create(rewriter, loc,
result, low,
834 ArrayRef<int64_t>{0});
835 result = LLVM::InsertValueOp::create(rewriter, loc,
result, high,
836 ArrayRef<int64_t>{1});
837 rewriter.replaceOp(op,
result);
844class ExecutionModePattern
847 using SPIRVToLLVMConversion<spirv::ExecutionModeOp>::SPIRVToLLVMConversion;
850 matchAndRewrite(spirv::ExecutionModeOp op, OpAdaptor adaptor,
851 ConversionPatternRewriter &rewriter)
const override {
855 ModuleOp module = op->getParentOfType<ModuleOp>();
856 spirv::ExecutionModeAttr executionModeAttr = op.getExecutionModeAttr();
857 std::string moduleName;
858 if (module.getName().has_value())
859 moduleName =
"_" +
module.getName()->str();
862 std::string executionModeInfoName = llvm::formatv(
863 "__spv_{0}_{1}_execution_mode_info_{2}", moduleName, op.getFn().str(),
864 static_cast<uint32_t
>(executionModeAttr.getValue()));
866 MLIRContext *context = rewriter.getContext();
867 OpBuilder::InsertionGuard guard(rewriter);
868 rewriter.setInsertionPointToStart(module.getBody());
875 auto llvmI32Type = IntegerType::get(context, 32);
876 SmallVector<Type, 2> fields;
877 fields.push_back(llvmI32Type);
879 if (!values.empty()) {
880 auto arrayType = LLVM::LLVMArrayType::get(llvmI32Type, values.size());
881 fields.push_back(arrayType);
883 auto structType = LLVM::LLVMStructType::getLiteral(context, fields);
886 auto global = LLVM::GlobalOp::create(
887 rewriter, UnknownLoc::get(context), structType,
true,
888 LLVM::Linkage::External, executionModeInfoName, Attribute(),
890 Location loc = global.getLoc();
891 Region ®ion = global.getInitializerRegion();
892 Block *block = rewriter.createBlock(®ion);
895 rewriter.setInsertionPointToStart(block);
896 Value structValue = LLVM::PoisonOp::create(rewriter, loc, structType);
897 Value executionMode = LLVM::ConstantOp::create(
898 rewriter, loc, llvmI32Type,
899 rewriter.getI32IntegerAttr(
900 static_cast<uint32_t
>(executionModeAttr.getValue())));
901 SmallVector<int64_t> position{0};
902 structValue = LLVM::InsertValueOp::create(rewriter, loc, structValue,
903 executionMode, position);
906 for (
unsigned i = 0, e = values.size(); i < e; ++i) {
907 auto attr = values.getValue()[i];
908 Value entry = LLVM::ConstantOp::create(rewriter, loc, llvmI32Type, attr);
909 structValue = LLVM::InsertValueOp::create(
910 rewriter, loc, structValue, entry, ArrayRef<int64_t>({1, i}));
912 LLVM::ReturnOp::create(rewriter, loc, ArrayRef<Value>({structValue}));
913 rewriter.eraseOp(op);
922class GlobalVariablePattern
925 template <
typename... Args>
926 GlobalVariablePattern(spirv::ClientAPI clientAPI, Args &&...args)
927 : SPIRVToLLVMConversion<spirv::GlobalVariableOp>(
928 std::forward<Args>(args)...),
929 clientAPI(clientAPI) {}
932 matchAndRewrite(spirv::GlobalVariableOp op, OpAdaptor adaptor,
933 ConversionPatternRewriter &rewriter)
const override {
936 if (op.getInitializer())
939 auto srcType = cast<spirv::PointerType>(op.getType());
940 auto dstType = getTypeConverter()->convertType(srcType.getPointeeType());
942 return rewriter.notifyMatchFailure(op,
"type conversion failed");
947 auto storageClass = srcType.getStorageClass();
948 switch (storageClass) {
949 case spirv::StorageClass::Input:
950 case spirv::StorageClass::Private:
951 case spirv::StorageClass::Output:
952 case spirv::StorageClass::StorageBuffer:
953 case spirv::StorageClass::UniformConstant:
962 bool isConstant = (storageClass == spirv::StorageClass::Input) ||
963 (storageClass == spirv::StorageClass::UniformConstant);
969 auto linkage = storageClass == spirv::StorageClass::Private
970 ? LLVM::Linkage::Private
971 : LLVM::Linkage::External;
972 StringAttr locationAttrName = op.getLocationAttrName();
973 IntegerAttr locationAttr = op.getLocationAttr();
974 auto newGlobalOp = rewriter.replaceOpWithNewOp<LLVM::GlobalOp>(
975 op, dstType, isConstant, linkage, op.getSymName(), Attribute(),
980 newGlobalOp->setDiscardableAttr(locationAttrName, locationAttr);
986 spirv::ClientAPI clientAPI;
991template <
typename SPIRVOp,
typename LLVMExtOp,
typename LLVMTruncOp>
994 using SPIRVToLLVMConversion<SPIRVOp>::SPIRVToLLVMConversion;
997 matchAndRewrite(SPIRVOp op,
typename SPIRVOp::Adaptor adaptor,
998 ConversionPatternRewriter &rewriter)
const override {
1000 Type fromType = op.getOperand().getType();
1001 Type toType = op.getType();
1003 auto dstType = this->getTypeConverter()->convertType(toType);
1005 return rewriter.notifyMatchFailure(op,
"type conversion failed");
1008 rewriter.template replaceOpWithNewOp<LLVMExtOp>(op, dstType,
1009 adaptor.getOperands());
1013 rewriter.template replaceOpWithNewOp<LLVMTruncOp>(op, dstType,
1014 adaptor.getOperands());
1021class FunctionCallPattern
1024 using SPIRVToLLVMConversion<spirv::FunctionCallOp>::SPIRVToLLVMConversion;
1027 matchAndRewrite(spirv::FunctionCallOp callOp, OpAdaptor adaptor,
1028 ConversionPatternRewriter &rewriter)
const override {
1029 LLVM::CallOp::Properties properties{};
1030 SmallVector<NamedAttribute> discardableAttrs;
1031 if (
failed(collectAttrsForConversion<LLVM::CallOp>(callOp, properties,
1034 properties.operandSegmentSizes = {
1035 static_cast<int32_t
>(adaptor.getOperands().size()), 0};
1036 properties.op_bundle_sizes = rewriter.getDenseI32ArrayAttr({});
1038 if (callOp.getNumResults() == 0) {
1039 rewriter.replaceOpWithNewOp<LLVM::CallOp>(callOp,
TypeRange(),
1040 adaptor.getOperands(),
1041 properties, discardableAttrs);
1046 auto dstType = getTypeConverter()->convertType(callOp.getType(0));
1048 return rewriter.notifyMatchFailure(callOp,
"type conversion failed");
1049 rewriter.replaceOpWithNewOp<LLVM::CallOp>(
1050 callOp, dstType, adaptor.getOperands(), properties, discardableAttrs);
1056template <
typename SPIRVOp, LLVM::FCmpPredicate predicate>
1059 using SPIRVToLLVMConversion<SPIRVOp>::SPIRVToLLVMConversion;
1062 matchAndRewrite(SPIRVOp op,
typename SPIRVOp::Adaptor adaptor,
1063 ConversionPatternRewriter &rewriter)
const override {
1065 auto dstType = this->getTypeConverter()->convertType(op.getType());
1067 return rewriter.notifyMatchFailure(op,
"type conversion failed");
1069 rewriter.template replaceOpWithNewOp<LLVM::FCmpOp>(
1070 op, dstType, predicate, op.getOperand1(), op.getOperand2());
1076template <
typename SPIRVOp, LLVM::ICmpPredicate predicate>
1079 using SPIRVToLLVMConversion<SPIRVOp>::SPIRVToLLVMConversion;
1082 matchAndRewrite(SPIRVOp op,
typename SPIRVOp::Adaptor adaptor,
1083 ConversionPatternRewriter &rewriter)
const override {
1085 auto dstType = this->getTypeConverter()->convertType(op.getType());
1087 return rewriter.notifyMatchFailure(op,
"type conversion failed");
1089 rewriter.template replaceOpWithNewOp<LLVM::ICmpOp>(
1090 op, dstType, predicate, op.getOperand1(), op.getOperand2());
1100template <
typename SPIRVOp, llvm::FPClassTest
classMask>
1103 using SPIRVToLLVMConversion<SPIRVOp>::SPIRVToLLVMConversion;
1106 matchAndRewrite(SPIRVOp op,
typename SPIRVOp::Adaptor adaptor,
1107 ConversionPatternRewriter &rewriter)
const override {
1108 auto dstType = this->getTypeConverter()->convertType(op.getType());
1110 return rewriter.notifyMatchFailure(op,
"type conversion failed");
1112 rewriter.template replaceOpWithNewOp<LLVM::IsFPClass>(
1113 op, dstType, adaptor.getOperand(), classMask);
1118template <
typename SPIRVOp>
1121 using SPIRVToLLVMConversion<SPIRVOp>::SPIRVToLLVMConversion;
1124 matchAndRewrite(SPIRVOp op,
typename SPIRVOp::Adaptor adaptor,
1125 ConversionPatternRewriter &rewriter)
const override {
1126 auto srcType = op.getType();
1127 auto dstType = this->getTypeConverter()->convertType(srcType);
1129 return rewriter.notifyMatchFailure(op,
"type conversion failed");
1131 Location loc = op.getLoc();
1133 Value sqrt = LLVM::SqrtOp::create(rewriter, loc, dstType, op.getOperand());
1134 rewriter.template replaceOpWithNewOp<LLVM::FDivOp>(op, dstType, one, sqrt);
1141class VectorTimesScalarPattern
1144 using SPIRVToLLVMConversion<
1145 spirv::VectorTimesScalarOp>::SPIRVToLLVMConversion;
1148 matchAndRewrite(spirv::VectorTimesScalarOp op, OpAdaptor adaptor,
1149 ConversionPatternRewriter &rewriter)
const override {
1150 Type srcType = op.getType();
1151 Type dstType = getTypeConverter()->convertType(srcType);
1153 return rewriter.notifyMatchFailure(op,
"type conversion failed");
1155 unsigned numElements = op.getVector().getType().getNumElements();
1156 Value broadcasted =
broadcast(op.getLoc(), adaptor.getScalar(), numElements,
1157 *getTypeConverter(), rewriter);
1158 rewriter.replaceOpWithNewOp<LLVM::FMulOp>(op, dstType, adaptor.getVector(),
1167 using SPIRVToLLVMConversion<spirv::SNegateOp>::SPIRVToLLVMConversion;
1170 matchAndRewrite(spirv::SNegateOp op, OpAdaptor adaptor,
1171 ConversionPatternRewriter &rewriter)
const override {
1172 Type srcType = op.getType();
1173 Type dstType = getTypeConverter()->convertType(srcType);
1175 return rewriter.notifyMatchFailure(op,
"type conversion failed");
1177 Location loc = op.getLoc();
1178 IntegerAttr zeroAttr = rewriter.getIntegerAttr(
1182 rewriter.replaceOpWithNewOp<LLVM::SubOp>(op, dstType, zero,
1183 adaptor.getOperand());
1190template <
typename SPIRVOp,
typename LLVMMinOp,
typename LLVMMaxOp>
1193 using SPIRVToLLVMConversion<SPIRVOp>::SPIRVToLLVMConversion;
1196 matchAndRewrite(SPIRVOp op,
typename SPIRVOp::Adaptor adaptor,
1197 ConversionPatternRewriter &rewriter)
const override {
1198 Type dstType = this->getTypeConverter()->convertType(op.getType());
1200 return rewriter.notifyMatchFailure(op,
"type conversion failed");
1202 Location loc = op.getLoc();
1203 Value
max = LLVMMaxOp::create(rewriter, loc, dstType, adaptor.getX(),
1205 rewriter.template replaceOpWithNewOp<LLVMMinOp>(op, dstType,
max,
1216 using SPIRVToLLVMConversion<spirv::FModOp>::SPIRVToLLVMConversion;
1219 matchAndRewrite(spirv::FModOp op, OpAdaptor adaptor,
1220 ConversionPatternRewriter &rewriter)
const override {
1221 Type dstType = getTypeConverter()->convertType(op.getType());
1223 return rewriter.notifyMatchFailure(op,
"type conversion failed");
1225 Location loc = op.getLoc();
1226 Value
lhs = adaptor.getOperand1();
1227 Value
rhs = adaptor.getOperand2();
1228 Value
div = LLVM::FDivOp::create(rewriter, loc, dstType,
lhs,
rhs);
1229 Value floored = LLVM::FFloorOp::create(rewriter, loc, dstType,
div);
1230 Value scaled = LLVM::FMulOp::create(rewriter, loc, dstType,
rhs, floored);
1231 rewriter.replaceOpWithNewOp<LLVM::FSubOp>(op, dstType,
lhs, scaled);
1242 using SPIRVToLLVMConversion<spirv::SModOp>::SPIRVToLLVMConversion;
1245 matchAndRewrite(spirv::SModOp op, OpAdaptor adaptor,
1246 ConversionPatternRewriter &rewriter)
const override {
1247 Type srcType = op.getType();
1248 Type dstType = getTypeConverter()->convertType(srcType);
1250 return rewriter.notifyMatchFailure(op,
"type conversion failed");
1252 Location loc = op.getLoc();
1253 Value
lhs = adaptor.getOperand1();
1254 Value
rhs = adaptor.getOperand2();
1255 Type i1Type = rewriter.getI1Type();
1256 auto vecSrcType = dyn_cast<VectorType>(srcType);
1258 vecSrcType ? VectorType::get(vecSrcType.getShape(), i1Type) : i1Type;
1260 Value
rem = LLVM::SRemOp::create(rewriter, loc, dstType,
lhs,
rhs);
1261 IntegerAttr zeroAttr = rewriter.getIntegerAttr(
1266 Value remNonZero = LLVM::ICmpOp::create(rewriter, loc, cmpType,
1267 LLVM::ICmpPredicate::ne,
rem, zero);
1268 Value remNeg = LLVM::ICmpOp::create(rewriter, loc, cmpType,
1269 LLVM::ICmpPredicate::slt,
rem, zero);
1270 Value rhsNeg = LLVM::ICmpOp::create(rewriter, loc, cmpType,
1271 LLVM::ICmpPredicate::slt,
rhs, zero);
1272 Value signMismatch =
1273 LLVM::XOrOp::create(rewriter, loc, cmpType, remNeg, rhsNeg);
1275 LLVM::AndOp::create(rewriter, loc, cmpType, remNonZero, signMismatch);
1277 Value adjusted = LLVM::AddOp::create(rewriter, loc, dstType,
rem,
rhs);
1278 rewriter.replaceOpWithNewOp<LLVM::SelectOp>(op, dstType, needsAdjust,
1285template <
typename SPIRVOp>
1288 using SPIRVToLLVMConversion<SPIRVOp>::SPIRVToLLVMConversion;
1291 matchAndRewrite(SPIRVOp op,
typename SPIRVOp::Adaptor adaptor,
1292 ConversionPatternRewriter &rewriter)
const override {
1293 if (!op.getMemoryAccess()) {
1295 *this->getTypeConverter(), 0,
1299 auto memoryAccess = *op.getMemoryAccess();
1300 switch (memoryAccess) {
1301 case spirv::MemoryAccess::Aligned:
1302 case spirv::MemoryAccess::None:
1303 case spirv::MemoryAccess::Nontemporal:
1304 case spirv::MemoryAccess::Volatile: {
1305 unsigned alignment =
1306 memoryAccess == spirv::MemoryAccess::Aligned ? *op.getAlignment() : 0;
1307 bool isNonTemporal = memoryAccess == spirv::MemoryAccess::Nontemporal;
1308 bool isVolatile = memoryAccess == spirv::MemoryAccess::Volatile;
1310 *this->getTypeConverter(), alignment,
1311 isVolatile, isNonTemporal);
1324static bool containsRuntimeArray(
Type type) {
1325 if (isa<spirv::RuntimeArrayType>(type))
1327 if (
auto arrayType = dyn_cast<spirv::ArrayType>(type))
1328 return containsRuntimeArray(arrayType.getElementType());
1329 if (
auto structType = dyn_cast<spirv::StructType>(type))
1330 return llvm::any_of(structType.getElementTypes(), containsRuntimeArray);
1337 using SPIRVToLLVMConversion<spirv::CopyMemoryOp>::SPIRVToLLVMConversion;
1340 matchAndRewrite(spirv::CopyMemoryOp op, OpAdaptor adaptor,
1341 ConversionPatternRewriter &rewriter)
const override {
1343 cast<spirv::PointerType>(op.getTarget().getType()).getPointeeType();
1347 if (containsRuntimeArray(pointeeType))
1348 return rewriter.notifyMatchFailure(op,
"pointee has no static size");
1350 Type dstPointeeType = getTypeConverter()->convertType(pointeeType);
1351 if (!dstPointeeType)
1352 return rewriter.notifyMatchFailure(op,
"type conversion failed");
1356 DataLayout::closest(op).getTypeSize(dstPointeeType).getFixedValue();
1361 using spirv::MemoryAccess;
1362 constexpr MemoryAccess supportedMask = MemoryAccess::Aligned |
1363 MemoryAccess::Volatile |
1364 MemoryAccess::Nontemporal;
1365 MemoryAccess targetAccess =
1366 op.getMemoryAccess().value_or(MemoryAccess::None);
1367 bool hasSourceAccess = op.getSourceMemoryAccess().has_value();
1368 MemoryAccess sourceAccess =
1369 hasSourceAccess ? *op.getSourceMemoryAccess() : targetAccess;
1370 if (((targetAccess | sourceAccess) & ~supportedMask) != MemoryAccess::None)
1371 return rewriter.notifyMatchFailure(
1372 op,
"unsupported memory access attributes");
1374 bool isVolatile = spirv::bitEnumContainsAny(targetAccess | sourceAccess,
1375 MemoryAccess::Volatile);
1376 uint32_t targetAlign =
1377 spirv::bitEnumContainsAny(targetAccess, MemoryAccess::Aligned)
1378 ? op.getAlignment().value_or(0)
1380 uint32_t sourceAlign =
1381 spirv::bitEnumContainsAny(sourceAccess, MemoryAccess::Aligned)
1382 ? (hasSourceAccess ? op.getSourceAlignment().value_or(0)
1386 Location loc = op.getLoc();
1387 Value size = LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(),
1388 rewriter.getI64IntegerAttr(byteSize));
1389 auto memcpy = rewriter.replaceOpWithNewOp<LLVM::MemcpyOp>(
1390 op, adaptor.getTarget(), adaptor.getSource(), size, isVolatile);
1392 if (targetAlign || sourceAlign) {
1393 auto makeAlignDict = [&](uint32_t align) {
1395 return rewriter.getDictionaryAttr({});
1396 return rewriter.getDictionaryAttr(
1397 {rewriter.getNamedAttr(LLVM::LLVMDialect::getAlignAttrName(),
1398 rewriter.getI64IntegerAttr(align))});
1400 memcpy.setArgAttrsAttr(rewriter.getArrayAttr(
1401 {makeAlignDict(targetAlign), makeAlignDict(sourceAlign),
1402 rewriter.getDictionaryAttr({})}));
1409template <
typename SPIRVOp>
1412 using SPIRVToLLVMConversion<SPIRVOp>::SPIRVToLLVMConversion;
1415 matchAndRewrite(SPIRVOp notOp,
typename SPIRVOp::Adaptor adaptor,
1416 ConversionPatternRewriter &rewriter)
const override {
1417 auto srcType = notOp.getType();
1418 auto dstType = this->getTypeConverter()->convertType(srcType);
1420 return rewriter.notifyMatchFailure(notOp,
"type conversion failed");
1422 Location loc = notOp.getLoc();
1424 rewriter.template replaceOpWithNewOp<LLVM::XOrOp>(notOp, dstType,
1425 notOp.getOperand(), mask);
1431template <
typename SPIRVOp>
1434 using SPIRVToLLVMConversion<SPIRVOp>::SPIRVToLLVMConversion;
1437 matchAndRewrite(SPIRVOp op,
typename SPIRVOp::Adaptor adaptor,
1438 ConversionPatternRewriter &rewriter)
const override {
1439 rewriter.eraseOp(op);
1446 using SPIRVToLLVMConversion<spirv::ReturnOp>::SPIRVToLLVMConversion;
1449 matchAndRewrite(spirv::ReturnOp returnOp, OpAdaptor adaptor,
1450 ConversionPatternRewriter &rewriter)
const override {
1451 rewriter.replaceOpWithNewOp<LLVM::ReturnOp>(returnOp, ArrayRef<Type>(),
1459 using SPIRVToLLVMConversion<spirv::ReturnValueOp>::SPIRVToLLVMConversion;
1462 matchAndRewrite(spirv::ReturnValueOp returnValueOp, OpAdaptor adaptor,
1463 ConversionPatternRewriter &rewriter)
const override {
1464 rewriter.replaceOpWithNewOp<LLVM::ReturnOp>(returnValueOp, ArrayRef<Type>(),
1465 adaptor.getOperands());
1472 using SPIRVToLLVMConversion<spirv::UnreachableOp>::SPIRVToLLVMConversion;
1475 matchAndRewrite(spirv::UnreachableOp unreachableOp, OpAdaptor adaptor,
1476 ConversionPatternRewriter &rewriter)
const override {
1477 rewriter.replaceOpWithNewOp<LLVM::UnreachableOp>(unreachableOp);
1486 bool convergent =
true) {
1487 auto func = dyn_cast_or_null<LLVM::LLVMFuncOp>(
1493 func = LLVM::LLVMFuncOp::create(
1494 b, symbolTable->
getLoc(), name,
1495 LLVM::LLVMFunctionType::get(resultType, paramTypes));
1496 func.setCConv(LLVM::cconv::CConv::SPIR_FUNC);
1497 func.setConvergent(convergent);
1498 func.setNoUnwind(
true);
1499 func.setWillReturn(
true);
1504 LLVM::LLVMFuncOp
func,
1506 auto call = LLVM::CallOp::create(builder, loc,
func, args);
1507 call.setCConv(
func.getCConv());
1508 call.setConvergentAttr(
func.getConvergentAttr());
1509 call.setNoUnwindAttr(
func.getNoUnwindAttr());
1510 call.setWillReturnAttr(
func.getWillReturnAttr());
1514template <
typename BarrierOpTy>
1517 using OpAdaptor =
typename SPIRVToLLVMConversion<BarrierOpTy>::OpAdaptor;
1519 using SPIRVToLLVMConversion<BarrierOpTy>::SPIRVToLLVMConversion;
1521 static constexpr StringRef getFuncName();
1524 matchAndRewrite(BarrierOpTy controlBarrierOp, OpAdaptor adaptor,
1525 ConversionPatternRewriter &rewriter)
const override {
1526 constexpr StringRef funcName = getFuncName();
1527 Operation *symbolTable =
1528 controlBarrierOp->template getParentWithTrait<OpTrait::SymbolTable>();
1530 Type i32 = rewriter.getI32Type();
1532 Type voidTy = rewriter.getType<LLVM::LLVMVoidType>();
1533 LLVM::LLVMFuncOp func =
1536 Location loc = controlBarrierOp->getLoc();
1537 Value execution = LLVM::ConstantOp::create(
1538 rewriter, loc, i32,
static_cast<int32_t
>(adaptor.getExecutionScope()));
1539 Value memory = LLVM::ConstantOp::create(
1540 rewriter, loc, i32,
static_cast<int32_t
>(adaptor.getMemoryScope()));
1541 Value semantics = LLVM::ConstantOp::create(
1542 rewriter, loc, i32,
static_cast<int32_t
>(adaptor.getMemorySemantics()));
1545 {execution, memory, semantics});
1547 rewriter.replaceOp(controlBarrierOp, call);
1554StringRef getTypeMangling(
Type type,
bool isSigned) {
1556 .Case([](Float16Type) {
return "Dh"; })
1557 .Case([](Float32Type) {
return "f"; })
1558 .Case([](Float64Type) {
return "d"; })
1559 .Case([isSigned](IntegerType intTy) {
1560 switch (intTy.getWidth()) {
1564 return (isSigned) ?
"a" :
"c";
1566 return (isSigned) ?
"s" :
"t";
1568 return (isSigned) ?
"i" :
"j";
1570 return (isSigned) ?
"l" :
"m";
1572 llvm_unreachable(
"Unsupported integer width");
1575 .DefaultUnreachable(
"No mangling defined");
1578template <
typename ReduceOp>
1579constexpr StringLiteral getGroupFuncName();
1582constexpr StringLiteral getGroupFuncName<spirv::GroupIAddOp>() {
1583 return "_Z17__spirv_GroupIAddii";
1586constexpr StringLiteral getGroupFuncName<spirv::GroupFAddOp>() {
1587 return "_Z17__spirv_GroupFAddii";
1590constexpr StringLiteral getGroupFuncName<spirv::GroupSMinOp>() {
1591 return "_Z17__spirv_GroupSMinii";
1594constexpr StringLiteral getGroupFuncName<spirv::GroupUMinOp>() {
1595 return "_Z17__spirv_GroupUMinii";
1598constexpr StringLiteral getGroupFuncName<spirv::GroupFMinOp>() {
1599 return "_Z17__spirv_GroupFMinii";
1602constexpr StringLiteral getGroupFuncName<spirv::GroupSMaxOp>() {
1603 return "_Z17__spirv_GroupSMaxii";
1606constexpr StringLiteral getGroupFuncName<spirv::GroupUMaxOp>() {
1607 return "_Z17__spirv_GroupUMaxii";
1610constexpr StringLiteral getGroupFuncName<spirv::GroupFMaxOp>() {
1611 return "_Z17__spirv_GroupFMaxii";
1614constexpr StringLiteral getGroupFuncName<spirv::GroupNonUniformIAddOp>() {
1615 return "_Z27__spirv_GroupNonUniformIAddii";
1618constexpr StringLiteral getGroupFuncName<spirv::GroupNonUniformFAddOp>() {
1619 return "_Z27__spirv_GroupNonUniformFAddii";
1622constexpr StringLiteral getGroupFuncName<spirv::GroupNonUniformIMulOp>() {
1623 return "_Z27__spirv_GroupNonUniformIMulii";
1626constexpr StringLiteral getGroupFuncName<spirv::GroupNonUniformFMulOp>() {
1627 return "_Z27__spirv_GroupNonUniformFMulii";
1630constexpr StringLiteral getGroupFuncName<spirv::GroupNonUniformSMinOp>() {
1631 return "_Z27__spirv_GroupNonUniformSMinii";
1634constexpr StringLiteral getGroupFuncName<spirv::GroupNonUniformUMinOp>() {
1635 return "_Z27__spirv_GroupNonUniformUMinii";
1638constexpr StringLiteral getGroupFuncName<spirv::GroupNonUniformFMinOp>() {
1639 return "_Z27__spirv_GroupNonUniformFMinii";
1642constexpr StringLiteral getGroupFuncName<spirv::GroupNonUniformSMaxOp>() {
1643 return "_Z27__spirv_GroupNonUniformSMaxii";
1646constexpr StringLiteral getGroupFuncName<spirv::GroupNonUniformUMaxOp>() {
1647 return "_Z27__spirv_GroupNonUniformUMaxii";
1650constexpr StringLiteral getGroupFuncName<spirv::GroupNonUniformFMaxOp>() {
1651 return "_Z27__spirv_GroupNonUniformFMaxii";
1654constexpr StringLiteral getGroupFuncName<spirv::GroupNonUniformBitwiseAndOp>() {
1655 return "_Z33__spirv_GroupNonUniformBitwiseAndii";
1658constexpr StringLiteral getGroupFuncName<spirv::GroupNonUniformBitwiseOrOp>() {
1659 return "_Z32__spirv_GroupNonUniformBitwiseOrii";
1662constexpr StringLiteral getGroupFuncName<spirv::GroupNonUniformBitwiseXorOp>() {
1663 return "_Z33__spirv_GroupNonUniformBitwiseXorii";
1666constexpr StringLiteral getGroupFuncName<spirv::GroupNonUniformLogicalAndOp>() {
1667 return "_Z33__spirv_GroupNonUniformLogicalAndii";
1670constexpr StringLiteral getGroupFuncName<spirv::GroupNonUniformLogicalOrOp>() {
1671 return "_Z32__spirv_GroupNonUniformLogicalOrii";
1674constexpr StringLiteral getGroupFuncName<spirv::GroupNonUniformLogicalXorOp>() {
1675 return "_Z33__spirv_GroupNonUniformLogicalXorii";
1679template <
typename ReduceOp,
bool Signed = false,
bool NonUniform = false>
1682 using SPIRVToLLVMConversion<ReduceOp>::SPIRVToLLVMConversion;
1685 matchAndRewrite(ReduceOp op,
typename ReduceOp::Adaptor adaptor,
1686 ConversionPatternRewriter &rewriter)
const override {
1688 Type retTy = op.getResult().getType();
1692 SmallString<36> funcName = getGroupFuncName<ReduceOp>();
1693 funcName += getTypeMangling(retTy,
false);
1695 Type i32Ty = rewriter.getI32Type();
1696 SmallVector<Type> paramTypes{i32Ty, i32Ty, retTy};
1697 if constexpr (NonUniform) {
1698 if (adaptor.getClusterSize()) {
1700 paramTypes.push_back(i32Ty);
1704 Operation *symbolTable =
1705 op->template getParentWithTrait<OpTrait::SymbolTable>();
1707 LLVM::LLVMFuncOp func =
1710 Location loc = op.getLoc();
1711 Value scope = LLVM::ConstantOp::create(
1712 rewriter, loc, i32Ty,
1713 static_cast<int32_t
>(adaptor.getExecutionScope()));
1714 Value groupOp = LLVM::ConstantOp::create(
1715 rewriter, loc, i32Ty,
1716 static_cast<int32_t
>(adaptor.getGroupOperation()));
1717 SmallVector<Value> operands{scope, groupOp};
1718 operands.append(adaptor.getOperands().begin(), adaptor.getOperands().end());
1721 rewriter.replaceOp(op, call);
1728ControlBarrierPattern<spirv::ControlBarrierOp>::getFuncName() {
1729 return "_Z22__spirv_ControlBarrieriii";
1734ControlBarrierPattern<spirv::INTELControlBarrierArriveOp>::getFuncName() {
1735 return "_Z33__spirv_ControlBarrierArriveINTELiii";
1740ControlBarrierPattern<spirv::INTELControlBarrierWaitOp>::getFuncName() {
1741 return "_Z31__spirv_ControlBarrierWaitINTELiii";
1794 using SPIRVToLLVMConversion<spirv::LoopOp>::SPIRVToLLVMConversion;
1797 matchAndRewrite(spirv::LoopOp loopOp, OpAdaptor adaptor,
1798 ConversionPatternRewriter &rewriter)
const override {
1800 if (loopOp.getLoopControl() != spirv::LoopControl::None)
1804 if (loopOp.getBody().empty()) {
1805 rewriter.eraseOp(loopOp);
1809 Location loc = loopOp.getLoc();
1813 Block *currentBlock = rewriter.getBlock();
1815 Block *endBlock = rewriter.splitBlock(currentBlock, position);
1819 Block *entryBlock = loopOp.getEntryBlock();
1821 auto brOp = dyn_cast<spirv::BranchOp>(entryBlock->
getOperations().front());
1824 Block *headerBlock = loopOp.getHeaderBlock();
1825 rewriter.setInsertionPointToEnd(currentBlock);
1826 LLVM::BrOp::create(rewriter, loc, brOp.getBlockArguments(), headerBlock);
1827 rewriter.eraseBlock(entryBlock);
1830 Block *mergeBlock = loopOp.getMergeBlock();
1833 rewriter.setInsertionPointToEnd(mergeBlock);
1834 LLVM::BrOp::create(rewriter, loc, terminatorOperands, endBlock);
1836 rewriter.inlineRegionBefore(loopOp.getBody(), endBlock);
1846 using SPIRVToLLVMConversion<spirv::SelectionOp>::SPIRVToLLVMConversion;
1849 matchAndRewrite(spirv::SelectionOp op, OpAdaptor adaptor,
1850 ConversionPatternRewriter &rewriter)
const override {
1854 if (op.getSelectionControl() != spirv::SelectionControl::None)
1858 if (op.getBody().empty()) {
1859 rewriter.eraseOp(op);
1863 Location loc = op.getLoc();
1865 SmallVector<Type> resultTypes;
1867 getTypeConverter()->convertTypes(op.getResultTypes(), resultTypes)))
1868 return rewriter.notifyMatchFailure(op,
"failed to convert type");
1872 auto *currentBlock = rewriter.getInsertionBlock();
1873 rewriter.setInsertionPointAfter(op);
1874 auto position = rewriter.getInsertionPoint();
1875 auto *continueBlock = rewriter.splitBlock(currentBlock, position);
1878 for (Type ty : resultTypes)
1879 continueBlock->addArgument(ty, loc);
1882 auto *mergeBlock = op.getMergeBlock();
1885 rewriter.setInsertionPointToEnd(mergeBlock);
1886 LLVM::BrOp::create(rewriter, loc, terminatorOperands, continueBlock);
1890 Block *headerBlock = op.getHeaderBlock();
1891 rewriter.inlineRegionBefore(op.getBody(), continueBlock);
1892 rewriter.mergeBlocks(headerBlock, currentBlock);
1893 rewriter.replaceOp(op, continueBlock->getArguments());
1902template <
typename SPIRVOp,
typename LLVMOp>
1905 using SPIRVToLLVMConversion<SPIRVOp>::SPIRVToLLVMConversion;
1908 matchAndRewrite(SPIRVOp op,
typename SPIRVOp::Adaptor adaptor,
1909 ConversionPatternRewriter &rewriter)
const override {
1911 auto dstType = this->getTypeConverter()->convertType(op.getType());
1913 return rewriter.notifyMatchFailure(op,
"type conversion failed");
1915 Type op1Type = op.getOperand1().getType();
1916 Type op2Type = op.getOperand2().getType();
1918 if (op1Type == op2Type) {
1919 rewriter.template replaceOpWithNewOp<LLVMOp>(op, dstType,
1920 adaptor.getOperands());
1924 std::optional<uint64_t> dstTypeWidth =
1926 std::optional<uint64_t> op2TypeWidth =
1929 if (!dstTypeWidth || !op2TypeWidth)
1932 Location loc = op.getLoc();
1934 if (op2TypeWidth < dstTypeWidth) {
1937 LLVM::ZExtOp::create(rewriter, loc, dstType, adaptor.getOperand2());
1940 LLVM::SExtOp::create(rewriter, loc, dstType, adaptor.getOperand2());
1942 }
else if (op2TypeWidth == dstTypeWidth) {
1943 extended = adaptor.getOperand2();
1949 LLVMOp::create(rewriter, loc, dstType, adaptor.getOperand1(), extended);
1950 rewriter.replaceOp(op,
result);
1958template <
typename SPIRVOp>
1961 using SPIRVToLLVMConversion<SPIRVOp>::SPIRVToLLVMConversion;
1964 matchAndRewrite(SPIRVOp op,
typename SPIRVOp::Adaptor adaptor,
1965 ConversionPatternRewriter &rewriter)
const override {
1966 Type dstType = this->getTypeConverter()->convertType(op.getType());
1968 return rewriter.notifyMatchFailure(op,
"type conversion failed");
1970 rewriter.template replaceOpWithNewOp<LLVM::AbsOp>(
1971 op, dstType, adaptor.getOperand(),
false);
1978template <
typename SPIRVOp,
typename LLVMOp>
1981 using SPIRVToLLVMConversion<SPIRVOp>::SPIRVToLLVMConversion;
1984 matchAndRewrite(SPIRVOp op,
typename SPIRVOp::Adaptor adaptor,
1985 ConversionPatternRewriter &rewriter)
const override {
1986 Type dstType = this->getTypeConverter()->convertType(op.getType());
1988 return rewriter.notifyMatchFailure(op,
"type conversion failed");
1990 rewriter.template replaceOpWithNewOp<LLVMOp>(op, dstType,
1991 adaptor.getOperand(),
2000 using SPIRVToLLVMConversion<spirv::GLFractOp>::SPIRVToLLVMConversion;
2003 matchAndRewrite(spirv::GLFractOp op, OpAdaptor adaptor,
2004 ConversionPatternRewriter &rewriter)
const override {
2005 Type dstType = getTypeConverter()->convertType(op.getType());
2007 return rewriter.notifyMatchFailure(op,
"type conversion failed");
2009 Location loc = op.getLoc();
2010 Value operand = adaptor.getOperand();
2011 Value floored = LLVM::FFloorOp::create(rewriter, loc, dstType, operand);
2012 rewriter.replaceOpWithNewOp<LLVM::FSubOp>(op, dstType, operand, floored);
2021 using SPIRVToLLVMConversion<spirv::GLFMixOp>::SPIRVToLLVMConversion;
2024 matchAndRewrite(spirv::GLFMixOp op, OpAdaptor adaptor,
2025 ConversionPatternRewriter &rewriter)
const override {
2026 Type dstType = getTypeConverter()->convertType(op.getType());
2028 return rewriter.notifyMatchFailure(op,
"type conversion failed");
2030 Location loc = op.getLoc();
2031 Value x = adaptor.getX();
2032 Value y = adaptor.getY();
2033 Value a = adaptor.getA();
2035 Value oneMinusA = LLVM::FSubOp::create(rewriter, loc, dstType, one, a);
2036 Value
lhs = LLVM::FMulOp::create(rewriter, loc, dstType, x, oneMinusA);
2037 Value
rhs = LLVM::FMulOp::create(rewriter, loc, dstType, y, a);
2038 rewriter.replaceOpWithNewOp<LLVM::FAddOp>(op, dstType,
lhs,
rhs);
2047 using SPIRVToLLVMConversion<spirv::CLMixOp>::SPIRVToLLVMConversion;
2050 matchAndRewrite(spirv::CLMixOp op, OpAdaptor adaptor,
2051 ConversionPatternRewriter &rewriter)
const override {
2052 Type dstType = getTypeConverter()->convertType(op.getType());
2054 return rewriter.notifyMatchFailure(op,
"type conversion failed");
2056 Location loc = op.getLoc();
2057 Value x = adaptor.getX();
2058 Value y = adaptor.getY();
2059 Value a = adaptor.getZ();
2060 Value diff = LLVM::FSubOp::create(rewriter, loc, dstType, y, x);
2061 rewriter.replaceOpWithNewOp<LLVM::FMAOp>(op, dstType, a, diff, x);
2070 using SPIRVToLLVMConversion<spirv::CLSincosOp>::SPIRVToLLVMConversion;
2073 matchAndRewrite(spirv::CLSincosOp op, OpAdaptor adaptor,
2074 ConversionPatternRewriter &rewriter)
const override {
2075 Type dstType = getTypeConverter()->convertType(op.getType());
2077 return rewriter.notifyMatchFailure(op,
"type conversion failed");
2079 Location loc = op.getLoc();
2080 auto structType = LLVM::LLVMStructType::getLiteral(rewriter.getContext(),
2081 {dstType, dstType});
2083 LLVM::SincosOp::create(rewriter, loc, structType, adaptor.getX());
2084 Value sin = LLVM::ExtractValueOp::create(rewriter, loc, sincos, 0);
2085 Value cos = LLVM::ExtractValueOp::create(rewriter, loc, sincos, 1);
2086 LLVM::StoreOp::create(rewriter, loc, cos, adaptor.getCosval());
2087 rewriter.replaceOp(op, sin);
2094template <
typename SPIRVOp>
2097 template <
typename... Args>
2098 ScalePattern(
double scale, Args &&...args)
2099 : SPIRVToLLVMConversion<SPIRVOp>(std::forward<Args>(args)...),
2103 matchAndRewrite(SPIRVOp op,
typename SPIRVOp::Adaptor adaptor,
2104 ConversionPatternRewriter &rewriter)
const override {
2105 Type srcType = op.getType();
2106 Type dstType = this->getTypeConverter()->convertType(srcType);
2108 return rewriter.notifyMatchFailure(op,
"type conversion failed");
2110 Location loc = op.getLoc();
2112 rewriter.replaceOpWithNewOp<LLVM::FMulOp>(op, dstType, adaptor.getOperand(),
2124template <
typename SPIRVOp,
bool isFloat>
2127 using SPIRVToLLVMConversion<SPIRVOp>::SPIRVToLLVMConversion;
2130 matchAndRewrite(SPIRVOp op,
typename SPIRVOp::Adaptor adaptor,
2131 ConversionPatternRewriter &rewriter)
const override {
2132 Type srcType = op.getType();
2133 Type dstType = this->getTypeConverter()->convertType(srcType);
2135 return rewriter.notifyMatchFailure(op,
"type conversion failed");
2137 Location loc = op.getLoc();
2138 Value operand = adaptor.getOperand();
2139 auto vecSrcType = dyn_cast<VectorType>(srcType);
2140 Type i1Type = rewriter.getI1Type();
2142 vecSrcType ? VectorType::get(vecSrcType.getShape(), i1Type) : i1Type;
2144 Value zero, one, minusOne, gt, lt;
2145 if constexpr (isFloat) {
2149 gt = LLVM::FCmpOp::create(rewriter, loc, cmpType,
2150 LLVM::FCmpPredicate::ogt, operand, zero);
2151 lt = LLVM::FCmpOp::create(rewriter, loc, cmpType,
2152 LLVM::FCmpPredicate::olt, operand, zero);
2156 rewriter.getIntegerAttr(intElemType, 0));
2158 rewriter.getIntegerAttr(intElemType, 1));
2160 gt = LLVM::ICmpOp::create(rewriter, loc, cmpType,
2161 LLVM::ICmpPredicate::sgt, operand, zero);
2162 lt = LLVM::ICmpOp::create(rewriter, loc, cmpType,
2163 LLVM::ICmpPredicate::slt, operand, zero);
2167 LLVM::SelectOp::create(rewriter, loc, dstType, lt, minusOne, zero);
2168 rewriter.replaceOpWithNewOp<LLVM::SelectOp>(op, dstType, gt, one,
2176 using SPIRVToLLVMConversion<spirv::VariableOp>::SPIRVToLLVMConversion;
2179 matchAndRewrite(spirv::VariableOp varOp, OpAdaptor adaptor,
2180 ConversionPatternRewriter &rewriter)
const override {
2181 auto srcType = varOp.getType();
2183 auto pointerTo = cast<spirv::PointerType>(srcType).getPointeeType();
2184 auto init = varOp.getInitializer();
2185 if (init && !pointerTo.isIntOrFloat() && !isa<VectorType>(pointerTo))
2188 auto dstType = getTypeConverter()->convertType(srcType);
2190 return rewriter.notifyMatchFailure(varOp,
"type conversion failed");
2192 Location loc = varOp.getLoc();
2195 auto elementType = getTypeConverter()->convertType(pointerTo);
2197 return rewriter.notifyMatchFailure(varOp,
"type conversion failed");
2198 rewriter.replaceOpWithNewOp<LLVM::AllocaOp>(varOp, dstType, elementType,
2202 auto elementType = getTypeConverter()->convertType(pointerTo);
2204 return rewriter.notifyMatchFailure(varOp,
"type conversion failed");
2206 LLVM::AllocaOp::create(rewriter, loc, dstType, elementType, size);
2207 LLVM::StoreOp::create(rewriter, loc, adaptor.getInitializer(), allocated);
2208 rewriter.replaceOp(varOp, allocated);
2217class BitcastConversionPattern
2220 using SPIRVToLLVMConversion<spirv::BitcastOp>::SPIRVToLLVMConversion;
2223 matchAndRewrite(spirv::BitcastOp bitcastOp, OpAdaptor adaptor,
2224 ConversionPatternRewriter &rewriter)
const override {
2225 auto dstType = getTypeConverter()->convertType(bitcastOp.getType());
2227 return rewriter.notifyMatchFailure(bitcastOp,
"type conversion failed");
2230 if (isa<LLVM::LLVMPointerType>(dstType)) {
2231 rewriter.replaceOp(bitcastOp, adaptor.getOperand());
2235 LLVM::BitcastOp::Properties properties{};
2236 SmallVector<NamedAttribute> discardableAttrs;
2237 if (
failed(collectAttrsForConversion<LLVM::BitcastOp>(bitcastOp, properties,
2240 rewriter.replaceOpWithNewOp<LLVM::BitcastOp>(bitcastOp, dstType,
2241 adaptor.getOperands(),
2242 properties, discardableAttrs);
2253 using SPIRVToLLVMConversion<spirv::FuncOp>::SPIRVToLLVMConversion;
2256 matchAndRewrite(spirv::FuncOp funcOp, OpAdaptor adaptor,
2257 ConversionPatternRewriter &rewriter)
const override {
2261 auto funcType = funcOp.getFunctionType();
2262 TypeConverter::SignatureConversion signatureConverter(
2263 funcType.getNumInputs());
2264 auto llvmType =
static_cast<const LLVMTypeConverter *
>(getTypeConverter())
2265 ->convertFunctionSignature(
2267 false, signatureConverter);
2272 Location loc = funcOp.getLoc();
2273 StringRef name = funcOp.getName();
2274 auto newFuncOp = LLVM::LLVMFuncOp::create(rewriter, loc, name, llvmType);
2277 MLIRContext *context = funcOp.getContext();
2278 switch (funcOp.getFunctionControl()) {
2279 case spirv::FunctionControl::Inline:
2280 newFuncOp.setAlwaysInline(
true);
2282 case spirv::FunctionControl::DontInline:
2283 newFuncOp.setNoInline(
true);
2286#define DISPATCH(functionControl, llvmAttr) \
2287 case functionControl: \
2288 newFuncOp->setDiscardableAttr("passthrough", \
2289 ArrayAttr::get(context, {llvmAttr})); \
2292 DISPATCH(spirv::FunctionControl::Pure,
2293 StringAttr::get(context,
"readonly"));
2294 DISPATCH(spirv::FunctionControl::Const,
2295 StringAttr::get(context,
"readnone"));
2305 rewriter.inlineRegionBefore(funcOp.getBody(), newFuncOp.getBody(),
2307 if (
failed(rewriter.convertRegionTypes(
2308 &newFuncOp.getBody(), *getTypeConverter(), &signatureConverter))) {
2311 rewriter.eraseOp(funcOp);
2322 using SPIRVToLLVMConversion<spirv::ModuleOp>::SPIRVToLLVMConversion;
2325 matchAndRewrite(spirv::ModuleOp spvModuleOp, OpAdaptor adaptor,
2326 ConversionPatternRewriter &rewriter)
const override {
2329 ModuleOp::create(rewriter, spvModuleOp.getLoc(), spvModuleOp.getName());
2330 rewriter.inlineRegionBefore(spvModuleOp.getRegion(), newModuleOp.getBody());
2333 rewriter.eraseBlock(&newModuleOp.getBodyRegion().back());
2334 rewriter.eraseOp(spvModuleOp);
2343class VectorShufflePattern
2346 using SPIRVToLLVMConversion<spirv::VectorShuffleOp>::SPIRVToLLVMConversion;
2348 matchAndRewrite(spirv::VectorShuffleOp op, OpAdaptor adaptor,
2349 ConversionPatternRewriter &rewriter)
const override {
2350 Location loc = op.getLoc();
2351 auto components = adaptor.getComponents();
2352 auto vector1 = adaptor.getVector1();
2353 auto vector2 = adaptor.getVector2();
2354 int vector1Size = cast<VectorType>(vector1.getType()).getNumElements();
2355 int vector2Size = cast<VectorType>(vector2.getType()).getNumElements();
2356 if (vector1Size == vector2Size) {
2357 rewriter.replaceOpWithNewOp<LLVM::ShuffleVectorOp>(
2358 op, vector1, vector2,
2359 LLVM::convertArrayToIndices<int32_t>(components));
2363 auto dstType = getTypeConverter()->convertType(op.getType());
2365 return rewriter.notifyMatchFailure(op,
"type conversion failed");
2366 auto scalarType = cast<VectorType>(dstType).getElementType();
2367 auto componentsArray = components.getValue();
2368 auto *context = rewriter.getContext();
2369 auto llvmI32Type = IntegerType::get(context, 32);
2370 Value targetOp = LLVM::PoisonOp::create(rewriter, loc, dstType);
2371 for (
unsigned i = 0; i < componentsArray.size(); i++) {
2372 if (!isa<IntegerAttr>(componentsArray[i]))
2373 return op.emitError(
"unable to support non-constant component");
2375 int indexVal = cast<IntegerAttr>(componentsArray[i]).getInt();
2380 Value baseVector = vector1;
2381 if (indexVal >= vector1Size) {
2382 offsetVal = vector1Size;
2383 baseVector = vector2;
2386 Value dstIndex = LLVM::ConstantOp::create(
2387 rewriter, loc, llvmI32Type,
2388 rewriter.getIntegerAttr(rewriter.getI32Type(), i));
2389 Value index = LLVM::ConstantOp::create(
2390 rewriter, loc, llvmI32Type,
2391 rewriter.getIntegerAttr(rewriter.getI32Type(), indexVal - offsetVal));
2393 auto extractOp = LLVM::ExtractElementOp::create(rewriter, loc, scalarType,
2395 targetOp = LLVM::InsertElementOp::create(rewriter, loc, dstType, targetOp,
2396 extractOp, dstIndex);
2398 rewriter.replaceOp(op, targetOp);
2409 spirv::ClientAPI clientAPI) {
2426 spirv::ClientAPI clientAPI) {
2429 DirectConversionPattern<spirv::IAddOp, LLVM::AddOp>,
2430 DirectConversionPattern<spirv::IMulOp, LLVM::MulOp>,
2431 DirectConversionPattern<spirv::ISubOp, LLVM::SubOp>,
2432 DirectConversionPattern<spirv::FAddOp, LLVM::FAddOp>,
2433 DirectConversionPattern<spirv::FDivOp, LLVM::FDivOp>,
2434 DirectConversionPattern<spirv::FMulOp, LLVM::FMulOp>,
2435 DirectConversionPattern<spirv::FNegateOp, LLVM::FNegOp>,
2436 DirectConversionPattern<spirv::FRemOp, LLVM::FRemOp>,
2437 DirectConversionPattern<spirv::FSubOp, LLVM::FSubOp>,
2438 DirectConversionPattern<spirv::SDivOp, LLVM::SDivOp>,
2439 DirectConversionPattern<spirv::SRemOp, LLVM::SRemOp>,
2440 DirectConversionPattern<spirv::UDivOp, LLVM::UDivOp>,
2441 DirectConversionPattern<spirv::UModOp, LLVM::URemOp>, FModPattern,
2442 SModPattern, VectorTimesScalarPattern, SNegatePattern,
2443 ArithmeticWithOverflowPattern<spirv::IAddCarryOp,
2444 LLVM::UAddWithOverflowOp>,
2445 ArithmeticWithOverflowPattern<spirv::ISubBorrowOp,
2446 LLVM::USubWithOverflowOp>,
2447 MulExtendedPattern<spirv::SMulExtendedOp, LLVM::SExtOp>,
2448 MulExtendedPattern<spirv::UMulExtendedOp, LLVM::ZExtOp>,
2451 BitFieldInsertPattern, BitFieldUExtractPattern, BitFieldSExtractPattern,
2452 DirectConversionPattern<spirv::BitCountOp, LLVM::CtPopOp>,
2453 DirectConversionPattern<spirv::BitReverseOp, LLVM::BitReverseOp>,
2454 DirectConversionPattern<spirv::BitwiseAndOp, LLVM::AndOp>,
2455 DirectConversionPattern<spirv::BitwiseOrOp, LLVM::OrOp>,
2456 DirectConversionPattern<spirv::BitwiseXorOp, LLVM::XOrOp>,
2457 NotPattern<spirv::NotOp>,
2460 BitcastConversionPattern,
2461 DirectConversionPattern<spirv::ConvertFToSOp, LLVM::FPToSIOp>,
2462 DirectConversionPattern<spirv::ConvertFToUOp, LLVM::FPToUIOp>,
2463 DirectConversionPattern<spirv::ConvertSToFOp, LLVM::SIToFPOp>,
2464 DirectConversionPattern<spirv::ConvertUToFOp, LLVM::UIToFPOp>,
2465 IndirectCastPattern<spirv::FConvertOp, LLVM::FPExtOp, LLVM::FPTruncOp>,
2466 IndirectCastPattern<spirv::SConvertOp, LLVM::SExtOp, LLVM::TruncOp>,
2467 IndirectCastPattern<spirv::UConvertOp, LLVM::ZExtOp, LLVM::TruncOp>,
2468 DirectConversionPattern<spirv::ConvertPtrToUOp, LLVM::PtrToIntOp>,
2469 DirectConversionPattern<spirv::ConvertUToPtrOp, LLVM::IntToPtrOp>,
2470 DirectConversionPattern<spirv::PtrCastToGenericOp, LLVM::AddrSpaceCastOp>,
2471 DirectConversionPattern<spirv::GenericCastToPtrOp, LLVM::AddrSpaceCastOp>,
2472 DirectConversionPattern<spirv::GenericCastToPtrExplicitOp,
2473 LLVM::AddrSpaceCastOp>,
2476 IComparePattern<spirv::IEqualOp, LLVM::ICmpPredicate::eq>,
2477 IComparePattern<spirv::INotEqualOp, LLVM::ICmpPredicate::ne>,
2478 FComparePattern<spirv::FOrdEqualOp, LLVM::FCmpPredicate::oeq>,
2479 FComparePattern<spirv::FOrdGreaterThanOp, LLVM::FCmpPredicate::ogt>,
2480 FComparePattern<spirv::FOrdGreaterThanEqualOp, LLVM::FCmpPredicate::oge>,
2481 FComparePattern<spirv::FOrdLessThanEqualOp, LLVM::FCmpPredicate::ole>,
2482 FComparePattern<spirv::FOrdLessThanOp, LLVM::FCmpPredicate::olt>,
2483 FComparePattern<spirv::FOrdNotEqualOp, LLVM::FCmpPredicate::one>,
2484 FComparePattern<spirv::FUnordEqualOp, LLVM::FCmpPredicate::ueq>,
2485 FComparePattern<spirv::FUnordGreaterThanOp, LLVM::FCmpPredicate::ugt>,
2486 FComparePattern<spirv::FUnordGreaterThanEqualOp,
2487 LLVM::FCmpPredicate::uge>,
2488 FComparePattern<spirv::FUnordLessThanEqualOp, LLVM::FCmpPredicate::ule>,
2489 FComparePattern<spirv::FUnordLessThanOp, LLVM::FCmpPredicate::ult>,
2490 FComparePattern<spirv::FUnordNotEqualOp, LLVM::FCmpPredicate::une>,
2491 FComparePattern<spirv::OrderedOp, LLVM::FCmpPredicate::ord>,
2492 FComparePattern<spirv::UnorderedOp, LLVM::FCmpPredicate::uno>,
2493 IComparePattern<spirv::SGreaterThanOp, LLVM::ICmpPredicate::sgt>,
2494 IComparePattern<spirv::SGreaterThanEqualOp, LLVM::ICmpPredicate::sge>,
2495 IComparePattern<spirv::SLessThanEqualOp, LLVM::ICmpPredicate::sle>,
2496 IComparePattern<spirv::SLessThanOp, LLVM::ICmpPredicate::slt>,
2497 IComparePattern<spirv::UGreaterThanOp, LLVM::ICmpPredicate::ugt>,
2498 IComparePattern<spirv::UGreaterThanEqualOp, LLVM::ICmpPredicate::uge>,
2499 IComparePattern<spirv::ULessThanEqualOp, LLVM::ICmpPredicate::ule>,
2500 IComparePattern<spirv::ULessThanOp, LLVM::ICmpPredicate::ult>,
2503 ConstantScalarAndVectorPattern,
2506 BranchConversionPattern, BranchConditionalConversionPattern,
2507 FunctionCallPattern, LoopPattern, SelectionPattern,
2508 ErasePattern<spirv::MergeOp>,
2511 ErasePattern<spirv::EntryPointOp>, ExecutionModePattern,
2514 DirectConversionPattern<spirv::GLCeilOp, LLVM::FCeilOp>,
2515 DirectConversionPattern<spirv::GLCosOp, LLVM::CosOp>,
2516 DirectConversionPattern<spirv::GLExpOp, LLVM::ExpOp>,
2517 DirectConversionPattern<spirv::GLExp2Op, LLVM::Exp2Op>,
2518 DirectConversionPattern<spirv::GLFAbsOp, LLVM::FAbsOp>,
2519 DirectConversionPattern<spirv::GLFloorOp, LLVM::FFloorOp>,
2520 DirectConversionPattern<spirv::GLFmaOp, LLVM::FMAOp>,
2521 ClampPattern<spirv::GLFClampOp, LLVM::MinNumOp, LLVM::MaxNumOp>,
2522 ClampPattern<spirv::GLSClampOp, LLVM::SMinOp, LLVM::SMaxOp>,
2523 ClampPattern<spirv::GLUClampOp, LLVM::UMinOp, LLVM::UMaxOp>,
2524 DirectConversionPattern<spirv::GLFMaxOp, LLVM::MaxNumOp>,
2525 DirectConversionPattern<spirv::GLFMinOp, LLVM::MinNumOp>,
2526 DirectConversionPattern<spirv::GLNMaxOp, LLVM::MaxNumOp>,
2527 DirectConversionPattern<spirv::GLNMinOp, LLVM::MinNumOp>,
2528 DirectConversionPattern<spirv::GLLdexpOp, LLVM::LoadExpOp>,
2529 DirectConversionPattern<spirv::GLLogOp, LLVM::LogOp>,
2530 DirectConversionPattern<spirv::GLLog2Op, LLVM::Log2Op>,
2531 DirectConversionPattern<spirv::GLPowOp, LLVM::PowOp>,
2532 DirectConversionPattern<spirv::GLRoundOp, LLVM::RoundOp>,
2533 DirectConversionPattern<spirv::GLRoundEvenOp, LLVM::RoundEvenOp>,
2534 DirectConversionPattern<spirv::GLSinOp, LLVM::SinOp>,
2535 DirectConversionPattern<spirv::GLSinhOp, LLVM::SinhOp>,
2536 DirectConversionPattern<spirv::GLCoshOp, LLVM::CoshOp>,
2537 DirectConversionPattern<spirv::GLSMaxOp, LLVM::SMaxOp>,
2538 DirectConversionPattern<spirv::GLSMinOp, LLVM::SMinOp>,
2539 DirectConversionPattern<spirv::GLSqrtOp, LLVM::SqrtOp>,
2540 DirectConversionPattern<spirv::GLUMaxOp, LLVM::UMaxOp>,
2541 DirectConversionPattern<spirv::GLUMinOp, LLVM::UMinOp>,
2542 DirectConversionPattern<spirv::GLTruncOp, LLVM::FTruncOp>,
2543 DirectConversionPattern<spirv::GLAsinOp, LLVM::ASinOp>,
2544 DirectConversionPattern<spirv::GLAcosOp, LLVM::ACosOp>,
2545 DirectConversionPattern<spirv::GLAtanOp, LLVM::ATanOp>,
2546 DirectConversionPattern<spirv::GLAtan2Op, LLVM::ATan2Op>,
2547 DirectConversionPattern<spirv::GLTanOp, LLVM::TanOp>,
2548 DirectConversionPattern<spirv::GLTanhOp, LLVM::TanhOp>,
2549 InverseSqrtPattern<spirv::GLInverseSqrtOp>, SAbsPattern<spirv::GLSAbsOp>,
2550 FractPattern, SignPattern<spirv::GLFSignOp,
true>,
2551 SignPattern<spirv::GLSSignOp,
false>, GLFMixPattern,
2554 DirectConversionPattern<spirv::CLCeilOp, LLVM::FCeilOp>,
2555 DirectConversionPattern<spirv::CLCosOp, LLVM::CosOp>,
2556 DirectConversionPattern<spirv::CLExpOp, LLVM::ExpOp>,
2557 DirectConversionPattern<spirv::CLExp2Op, LLVM::Exp2Op>,
2558 DirectConversionPattern<spirv::CLExp10Op, LLVM::Exp10Op>,
2559 DirectConversionPattern<spirv::CLFAbsOp, LLVM::FAbsOp>,
2560 DirectConversionPattern<spirv::CLFloorOp, LLVM::FFloorOp>,
2561 DirectConversionPattern<spirv::CLFmaOp, LLVM::FMAOp>,
2562 DirectConversionPattern<spirv::CLFMaxOp, LLVM::MaxNumOp>,
2563 DirectConversionPattern<spirv::CLFMinOp, LLVM::MinNumOp>,
2564 DirectConversionPattern<spirv::CLLdexpOp, LLVM::LoadExpOp>,
2565 DirectConversionPattern<spirv::CLLogOp, LLVM::LogOp>,
2566 DirectConversionPattern<spirv::CLLog2Op, LLVM::Log2Op>,
2567 DirectConversionPattern<spirv::CLLog10Op, LLVM::Log10Op>,
2568 DirectConversionPattern<spirv::CLPowOp, LLVM::PowOp>,
2569 DirectConversionPattern<spirv::CLRintOp, LLVM::RintOp>,
2570 DirectConversionPattern<spirv::CLRoundOp, LLVM::RoundOp>,
2571 DirectConversionPattern<spirv::CLSinOp, LLVM::SinOp>,
2572 DirectConversionPattern<spirv::CLSinhOp, LLVM::SinhOp>,
2573 DirectConversionPattern<spirv::CLCoshOp, LLVM::CoshOp>,
2574 DirectConversionPattern<spirv::CLTanOp, LLVM::TanOp>,
2575 DirectConversionPattern<spirv::CLTanhOp, LLVM::TanhOp>,
2576 DirectConversionPattern<spirv::CLAsinOp, LLVM::ASinOp>,
2577 DirectConversionPattern<spirv::CLAcosOp, LLVM::ACosOp>,
2578 DirectConversionPattern<spirv::CLAtanOp, LLVM::ATanOp>,
2579 DirectConversionPattern<spirv::CLAtan2Op, LLVM::ATan2Op>,
2580 DirectConversionPattern<spirv::CLSqrtOp, LLVM::SqrtOp>,
2581 DirectConversionPattern<spirv::CLTruncOp, LLVM::FTruncOp>,
2582 DirectConversionPattern<spirv::CLCopysignOp, LLVM::CopySignOp>,
2583 DirectConversionPattern<spirv::CLFmodOp, LLVM::FRemOp>,
2584 DirectConversionPattern<spirv::CLSMaxOp, LLVM::SMaxOp>,
2585 DirectConversionPattern<spirv::CLSMinOp, LLVM::SMinOp>,
2586 DirectConversionPattern<spirv::CLUMaxOp, LLVM::UMaxOp>,
2587 DirectConversionPattern<spirv::CLUMinOp, LLVM::UMinOp>, CLMixPattern,
2588 CLSincosPattern, InverseSqrtPattern<spirv::CLRsqrtOp>,
2589 SAbsPattern<spirv::CLSAbsOp>,
2590 ClampPattern<spirv::CLFClampOp, LLVM::MinNumOp, LLVM::MaxNumOp>,
2591 ClampPattern<spirv::CLSClampOp, LLVM::SMinOp, LLVM::SMaxOp>,
2592 ClampPattern<spirv::CLUClampOp, LLVM::UMinOp, LLVM::UMaxOp>,
2593 CountZerosPattern<spirv::CLClzOp, LLVM::CountLeadingZerosOp>,
2594 CountZerosPattern<spirv::CLCtzOp, LLVM::CountTrailingZerosOp>,
2597 DirectConversionPattern<spirv::LogicalAndOp, LLVM::AndOp>,
2598 DirectConversionPattern<spirv::LogicalOrOp, LLVM::OrOp>,
2599 IComparePattern<spirv::LogicalEqualOp, LLVM::ICmpPredicate::eq>,
2600 IComparePattern<spirv::LogicalNotEqualOp, LLVM::ICmpPredicate::ne>,
2601 NotPattern<spirv::LogicalNotOp>,
2602 FPClassPattern<spirv::IsInfOp, llvm::fcInf>,
2603 FPClassPattern<spirv::IsNanOp, llvm::fcNan>,
2604 FPClassPattern<spirv::IsFiniteOp, llvm::fcFinite>,
2605 FPClassPattern<spirv::IsNormalOp, llvm::fcNormal>,
2608 AccessChainPattern<spirv::AccessChainOp,
false>,
2609 AccessChainPattern<spirv::InBoundsAccessChainOp,
true>,
2610 PtrAccessChainPattern<spirv::PtrAccessChainOp,
false>,
2611 PtrAccessChainPattern<spirv::InBoundsPtrAccessChainOp,
true>,
2612 AddressOfPattern, CopyMemoryPattern, LoadStorePattern<spirv::LoadOp>,
2613 LoadStorePattern<spirv::StoreOp>, VariablePattern,
2616 CompositeExtractPattern, CompositeInsertPattern,
2617 DirectConversionPattern<spirv::SelectOp, LLVM::SelectOp>,
2618 DirectConversionPattern<spirv::UndefOp, LLVM::UndefOp>,
2619 VectorShufflePattern,
2622 ShiftPattern<spirv::ShiftRightArithmeticOp, LLVM::AShrOp>,
2623 ShiftPattern<spirv::ShiftRightLogicalOp, LLVM::LShrOp>,
2624 ShiftPattern<spirv::ShiftLeftLogicalOp, LLVM::ShlOp>,
2627 ReturnPattern, ReturnValuePattern,
2633 ControlBarrierPattern<spirv::ControlBarrierOp>,
2634 ControlBarrierPattern<spirv::INTELControlBarrierArriveOp>,
2635 ControlBarrierPattern<spirv::INTELControlBarrierWaitOp>,
2638 GroupReducePattern<spirv::GroupIAddOp>,
2639 GroupReducePattern<spirv::GroupFAddOp>,
2640 GroupReducePattern<spirv::GroupFMinOp>,
2641 GroupReducePattern<spirv::GroupUMinOp>,
2642 GroupReducePattern<spirv::GroupSMinOp,
true>,
2643 GroupReducePattern<spirv::GroupFMaxOp>,
2644 GroupReducePattern<spirv::GroupUMaxOp>,
2645 GroupReducePattern<spirv::GroupSMaxOp,
true>,
2646 GroupReducePattern<spirv::GroupNonUniformIAddOp,
false,
2648 GroupReducePattern<spirv::GroupNonUniformFAddOp,
false,
2650 GroupReducePattern<spirv::GroupNonUniformIMulOp,
false,
2652 GroupReducePattern<spirv::GroupNonUniformFMulOp,
false,
2654 GroupReducePattern<spirv::GroupNonUniformSMinOp,
true,
2656 GroupReducePattern<spirv::GroupNonUniformUMinOp,
false,
2658 GroupReducePattern<spirv::GroupNonUniformFMinOp,
false,
2660 GroupReducePattern<spirv::GroupNonUniformSMaxOp,
true,
2662 GroupReducePattern<spirv::GroupNonUniformUMaxOp,
false,
2664 GroupReducePattern<spirv::GroupNonUniformFMaxOp,
false,
2666 GroupReducePattern<spirv::GroupNonUniformBitwiseAndOp,
false,
2668 GroupReducePattern<spirv::GroupNonUniformBitwiseOrOp,
false,
2670 GroupReducePattern<spirv::GroupNonUniformBitwiseXorOp,
false,
2672 GroupReducePattern<spirv::GroupNonUniformLogicalAndOp,
false,
2674 GroupReducePattern<spirv::GroupNonUniformLogicalOrOp,
false,
2676 GroupReducePattern<spirv::GroupNonUniformLogicalXorOp,
false,
2680 patterns.
add<GlobalVariablePattern>(clientAPI, patterns.
getContext(),
2683 patterns.
add<ScalePattern<spirv::GLRadiansOp>>(
2684 0.017453292519943295, patterns.
getContext(), typeConverter);
2686 patterns.
add<ScalePattern<spirv::GLDegreesOp>>(
2687 57.29577951308232, patterns.
getContext(), typeConverter);
2692 patterns.
add<FuncConversionPattern>(patterns.
getContext(), typeConverter);
2697 patterns.
add<ModuleConversionPattern>(patterns.
getContext(), typeConverter);
2706 auto spvModules =
module.getOps<spirv::ModuleOp>();
2707 for (
auto spvModule : spvModules) {
2708 spvModule.walk([&](spirv::GlobalVariableOp op) {
2709 IntegerAttr descriptorSet = op.getDescriptorSetAttr();
2710 IntegerAttr binding = op.getBindingAttr();
2713 if (descriptorSet && binding) {
2716 auto moduleAndName =
2717 spvModule.getName().has_value()
2718 ? spvModule.getName()->str() +
"_" + op.getSymName().str()
2719 : op.getSymName().str();
2721 llvm::formatv(
"{0}_descriptor_set{1}_binding{2}", moduleAndName,
2722 std::to_string(descriptorSet.getInt()),
2723 std::to_string(binding.getInt()));
2724 auto nameAttr = StringAttr::get(op->getContext(), name);
2729 op.emitError(
"unable to replace all symbol uses for ") << name;
2731 op.removeDescriptorSetAttr();
2732 op.removeBindingAttr();
static LLVM::CallOp createSPIRVBuiltinCall(Location loc, ConversionPatternRewriter &rewriter, LLVM::LLVMFuncOp func, ValueRange args)
static LLVM::LLVMFuncOp lookupOrCreateSPIRVFn(Operation *symbolTable, StringRef name, ArrayRef< Type > paramTypes, Type resultType, bool isMemNone, bool isConvergent)
static Value max(ImplicitLocOpBuilder &builder, Value value, Value bound)
static Type getElementType(Type type, ArrayRef< int32_t > indices, function_ref< InFlightDiagnostic(StringRef)> emitErrorFn)
Walks the given type hierarchy with the given indices, potentially down to component granularity,...
static Value optionallyTruncateOrExtend(Location loc, Value value, Type llvmType, PatternRewriter &rewriter)
Utility function for bitfield ops:
static Value createFPConstant(Location loc, Type srcType, Type dstType, PatternRewriter &rewriter, double value)
Creates llvm.mlir.constant with a floating-point scalar or vector value.
static Value createI32ConstantOf(Location loc, PatternRewriter &rewriter, unsigned value)
Creates LLVM dialect constant with the given value.
static Type convertPointerType(spirv::PointerType type, const TypeConverter &converter, spirv::ClientAPI clientAPI)
Converts SPIR-V pointer type to LLVM pointer.
static Value processCountOrOffset(Location loc, Value value, Type srcType, Type dstType, const TypeConverter &converter, ConversionPatternRewriter &rewriter)
Utility function for bitfield ops: BitFieldInsert, BitFieldSExtract and BitFieldUExtract.
static unsigned getBitWidth(Type type)
Returns the bit width of integer, float or vector of float or integer values.
static LogicalResult replaceWithLoadOrStore(Operation *op, ValueRange operands, ConversionPatternRewriter &rewriter, const TypeConverter &typeConverter, unsigned alignment, bool isVolatile, bool isNonTemporal)
Utility for spirv.Load and spirv.Store conversion.
static Type convertStructTypePacked(spirv::StructType type, const TypeConverter &converter)
Converts SPIR-V struct with no offset to packed LLVM struct.
static bool isSignedIntegerOrVector(Type type)
Returns true if the given type is a signed integer or vector type.
static bool isUnsignedIntegerOrVector(Type type)
Returns true if the given type is an unsigned integer or vector type.
static std::optional< Type > convertRuntimeArrayType(spirv::RuntimeArrayType type, TypeConverter &converter)
Converts SPIR-V runtime array to LLVM array.
static Value optionallyBroadcast(Location loc, Value value, Type srcType, const TypeConverter &typeConverter, ConversionPatternRewriter &rewriter)
Broadcasts the value. If srcType is a scalar, the value remains unchanged.
static Value createConstantAllBitsSet(Location loc, Type srcType, Type dstType, PatternRewriter &rewriter)
Creates llvm.mlir.constant with all bits set for the given type.
static unsigned getLLVMTypeBitWidth(Type type)
Returns the bit width of LLVMType integer or vector.
static std::optional< uint64_t > getIntegerOrVectorElementWidth(Type type)
Returns the width of an integer or of the element type of an integer vector, if applicable.
#define DISPATCH(functionControl, llvmAttr)
static Type convertStructTypeWithOffset(spirv::StructType type, const TypeConverter &converter)
Converts SPIR-V struct with a regular (according to VulkanLayoutUtils) offset to LLVM struct.
static Type convertStructType(spirv::StructType type, const TypeConverter &converter)
Converts SPIR-V struct to LLVM struct.
static Value broadcast(Location loc, Value toBroadcast, unsigned numElements, const TypeConverter &typeConverter, ConversionPatternRewriter &rewriter)
Broadcasts the value to vector with numElements number of elements.
static Value createIntegerConstant(Location loc, Type srcType, Type dstType, PatternRewriter &rewriter, IntegerAttr scalarAttr)
Creates llvm.mlir.constant with a scalar or vector integer value, broadcasting scalarAttr across the ...
static std::optional< Type > convertArrayType(spirv::ArrayType type, TypeConverter &converter)
Converts SPIR-V array type to LLVM array.
OpListType::iterator iterator
OpListType & getOperations()
Operation * getTerminator()
Get the terminator operation of this block.
BlockArgListType getArguments()
IntegerAttr getIntegerAttr(Type type, int64_t value)
FloatAttr getFloatAttr(Type type, double value)
MLIRContext * getContext() const
static DenseElementsAttr get(ShapedType type, ArrayRef< Attribute > values)
Constructs a dense elements attribute from an array of element values.
Conversion from types to the LLVM IR dialect.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
NamedAttrList is array of NamedAttributes that tracks whether it is sorted and does some basic work t...
NamedAttribute represents a combination of a name and an Attribute value.
This class helps build Operations.
Operation is the basic unit of execution within MLIR.
Region & getRegion(unsigned index)
Returns the region held by this operation at position 'index'.
Location getLoc()
The source location the operation was defined or derived from.
operand_range getOperands()
Returns an iterator on the underlying Value's.
A special type of RewriterBase that coordinates the application of a rewrite pattern on the current I...
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.
static LogicalResult replaceAllSymbolUses(StringAttr oldSymbol, StringAttr newSymbol, Operation *from)
Attempt to replace all uses of the given symbol 'oldSymbol' with the provided symbol 'newSymbol' that...
static Operation * lookupSymbolIn(Operation *op, StringAttr symbol)
Returns the operation registered with the given symbol name with the regions of 'symbolTableOp'.
static void setSymbolName(Operation *symbol, StringAttr name)
Sets the name of the given symbol operation.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
bool isSignedInteger() const
Return true if this is a signed integer type (with the specified width).
bool isUnsignedInteger() const
Return true if this is an unsigned integer type (with the specified width).
bool isIntOrFloat() const
Return true if this is an integer (of any signedness) or a float type.
unsigned getIntOrFloatBitWidth() const
Return the bit width of an integer or a float type, assert failure on other types.
This class provides an abstraction over the different types of ranges over Values.
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.
static spirv::StructType decorateType(spirv::StructType structType)
Returns a new StructType with layout decoration.
static DenseArrayAttrImpl get(MLIRContext *context, ArrayRef< int32_t > content)
Type getElementType() const
unsigned getArrayStride() const
Returns the array stride in bytes.
unsigned getNumElements() const
StorageClass getStorageClass() const
Type getElementType() const
unsigned getArrayStride() const
Returns the array stride in bytes.
void getMemberDecorations(SmallVectorImpl< StructType::MemberDecorationInfo > &memberDecorations) const
TypeRange getElementTypes() const
bool isCompatibleType(Type type)
Returns true if the given type is compatible with the LLVM dialect.
Include the generated interface declarations.
unsigned storageClassToAddressSpace(spirv::ClientAPI clientAPI, spirv::StorageClass storageClass)
void populateSPIRVToLLVMTypeConversion(LLVMTypeConverter &typeConverter, spirv::ClientAPI clientAPIForAddressSpaceMapping=spirv::ClientAPI::Unknown)
Populates type conversions with additional SPIR-V types.
void populateSPIRVToLLVMFunctionConversionPatterns(const LLVMTypeConverter &typeConverter, RewritePatternSet &patterns)
Populates the given list with patterns for function conversion from SPIR-V to LLVM.
Type getElementTypeOrSelf(Type type)
Return the element type or return the type itself.
detail::DenseArrayAttrImpl< int32_t > DenseI32ArrayAttr
void populateSPIRVToLLVMConversionPatterns(const LLVMTypeConverter &typeConverter, RewritePatternSet &patterns, spirv::ClientAPI clientAPIForAddressSpaceMapping=spirv::ClientAPI::Unknown)
Populates the given list with patterns that convert from SPIR-V to LLVM.
void encodeBindAttribute(ModuleOp module)
Encodes global variable's descriptor set and binding into its name if they both exist.
void populateSPIRVToLLVMModuleConversionPatterns(const LLVMTypeConverter &typeConverter, RewritePatternSet &patterns)
Populates the given patterns for module conversion from SPIR-V to LLVM.
Structure used by default as a "marker" when no "Properties" are set on an Operation.