23#include "llvm/ADT/TypeSwitch.h"
24#include "llvm/Support/FormatVariadic.h"
26#define DEBUG_TYPE "spirv-to-llvm-pattern"
38 if (
auto vecType = dyn_cast<VectorType>(type))
39 return vecType.getElementType().isSignedInteger();
47 if (
auto vecType = dyn_cast<VectorType>(type))
48 return vecType.getElementType().isUnsignedInteger();
55 if (
auto intType = dyn_cast<IntegerType>(type))
56 return intType.getWidth();
57 if (
auto vecType = dyn_cast<VectorType>(type))
58 if (
auto intType = dyn_cast<IntegerType>(vecType.getElementType()))
59 return intType.getWidth();
66 "bitwidth is not supported for this type");
69 auto vecType = dyn_cast<VectorType>(type);
70 auto elementType = vecType.getElementType();
71 assert(elementType.isIntOrFloat() &&
72 "only integers and floats have a bitwidth");
73 return elementType.getIntOrFloatBitWidth();
78 if (
auto vecTy = dyn_cast<VectorType>(type))
79 type = vecTy.getElementType();
80 return cast<IntegerType>(type).getWidth();
85 if (
auto vecType = dyn_cast<VectorType>(type)) {
86 auto integerType = cast<IntegerType>(vecType.getElementType());
89 auto integerType = cast<IntegerType>(type);
96 if (isa<VectorType>(srcType)) {
97 return LLVM::ConstantOp::create(
98 rewriter, loc, dstType,
102 return LLVM::ConstantOp::create(rewriter, loc, dstType,
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())
310 using SPIRVToLLVMConversion<spirv::AccessChainOp>::SPIRVToLLVMConversion;
313 matchAndRewrite(spirv::AccessChainOp op, OpAdaptor adaptor,
314 ConversionPatternRewriter &rewriter)
const override {
316 getTypeConverter()->convertType(op.getComponentPtr().getType());
318 return rewriter.notifyMatchFailure(op,
"type conversion failed");
320 auto indices = llvm::to_vector<4>(adaptor.getIndices());
321 Type indexType = op.getIndices().front().getType();
322 auto llvmIndexType = getTypeConverter()->convertType(indexType);
324 return rewriter.notifyMatchFailure(op,
"type conversion failed");
326 LLVM::ConstantOp::create(rewriter, op.getLoc(), llvmIndexType,
327 rewriter.getIntegerAttr(indexType, 0));
330 auto elementType = getTypeConverter()->convertType(
331 cast<spirv::PointerType>(op.getBasePtr().getType()).getPointeeType());
333 return rewriter.notifyMatchFailure(op,
"type conversion failed");
334 rewriter.replaceOpWithNewOp<LLVM::GEPOp>(op, dstType, elementType,
335 adaptor.getBasePtr(),
indices);
342 using SPIRVToLLVMConversion<spirv::AddressOfOp>::SPIRVToLLVMConversion;
345 matchAndRewrite(spirv::AddressOfOp op, OpAdaptor adaptor,
346 ConversionPatternRewriter &rewriter)
const override {
347 auto dstType = getTypeConverter()->convertType(op.getPointer().getType());
349 return rewriter.notifyMatchFailure(op,
"type conversion failed");
350 rewriter.replaceOpWithNewOp<LLVM::AddressOfOp>(op, dstType,
356class BitFieldInsertPattern
359 using SPIRVToLLVMConversion<spirv::BitFieldInsertOp>::SPIRVToLLVMConversion;
362 matchAndRewrite(spirv::BitFieldInsertOp op, OpAdaptor adaptor,
363 ConversionPatternRewriter &rewriter)
const override {
364 auto srcType = op.getType();
365 auto dstType = getTypeConverter()->convertType(srcType);
367 return rewriter.notifyMatchFailure(op,
"type conversion failed");
368 Location loc = op.getLoc();
372 *getTypeConverter(), rewriter);
374 *getTypeConverter(), rewriter);
378 Value maskShiftedByCount =
379 LLVM::ShlOp::create(rewriter, loc, dstType, minusOne, count);
380 Value negated = LLVM::XOrOp::create(rewriter, loc, dstType,
381 maskShiftedByCount, minusOne);
382 Value maskShiftedByCountAndOffset =
383 LLVM::ShlOp::create(rewriter, loc, dstType, negated, offset);
384 Value mask = LLVM::XOrOp::create(rewriter, loc, dstType,
385 maskShiftedByCountAndOffset, minusOne);
390 LLVM::AndOp::create(rewriter, loc, dstType, op.getBase(), mask);
391 Value insertShiftedByOffset =
392 LLVM::ShlOp::create(rewriter, loc, dstType, op.getInsert(), offset);
393 rewriter.replaceOpWithNewOp<LLVM::OrOp>(op, dstType, baseAndMask,
394 insertShiftedByOffset);
400class ConstantScalarAndVectorPattern
403 using SPIRVToLLVMConversion<spirv::ConstantOp>::SPIRVToLLVMConversion;
406 matchAndRewrite(spirv::ConstantOp constOp, OpAdaptor adaptor,
407 ConversionPatternRewriter &rewriter)
const override {
408 auto srcType = constOp.getType();
409 if (!isa<VectorType>(srcType) && !srcType.isIntOrFloat())
412 auto dstType = getTypeConverter()->convertType(srcType);
414 return rewriter.notifyMatchFailure(constOp,
"type conversion failed");
423 auto signlessType = rewriter.getIntegerType(
getBitWidth(srcType));
425 if (isa<VectorType>(srcType)) {
426 auto dstElementsAttr = cast<DenseIntElementsAttr>(constOp.getValue());
427 rewriter.replaceOpWithNewOp<LLVM::ConstantOp>(
429 dstElementsAttr.mapValues(
430 signlessType, [&](
const APInt &value) {
return value; }));
433 auto srcAttr = cast<IntegerAttr>(constOp.getValue());
434 auto dstAttr = rewriter.getIntegerAttr(signlessType, srcAttr.getValue());
435 rewriter.replaceOpWithNewOp<LLVM::ConstantOp>(constOp, dstType, dstAttr);
438 rewriter.replaceOpWithNewOp<LLVM::ConstantOp>(
439 constOp, dstType, adaptor.getOperands(), constOp->getAttrs());
444class BitFieldSExtractPattern
447 using SPIRVToLLVMConversion<spirv::BitFieldSExtractOp>::SPIRVToLLVMConversion;
450 matchAndRewrite(spirv::BitFieldSExtractOp op, OpAdaptor adaptor,
451 ConversionPatternRewriter &rewriter)
const override {
452 auto srcType = op.getType();
453 auto dstType = getTypeConverter()->convertType(srcType);
455 return rewriter.notifyMatchFailure(op,
"type conversion failed");
456 Location loc = op.getLoc();
460 *getTypeConverter(), rewriter);
462 *getTypeConverter(), rewriter);
465 IntegerType integerType;
466 if (
auto vecType = dyn_cast<VectorType>(srcType))
467 integerType = cast<IntegerType>(vecType.getElementType());
469 integerType = cast<IntegerType>(srcType);
471 auto baseSize = rewriter.getIntegerAttr(integerType,
getBitWidth(srcType));
473 isa<VectorType>(srcType)
474 ? LLVM::ConstantOp::create(
475 rewriter, loc, dstType,
476 SplatElementsAttr::get(cast<ShapedType>(srcType), baseSize))
477 : LLVM::ConstantOp::create(rewriter, loc, dstType, baseSize);
481 Value countPlusOffset =
482 LLVM::AddOp::create(rewriter, loc, dstType, count, offset);
483 Value amountToShiftLeft =
484 LLVM::SubOp::create(rewriter, loc, dstType, size, countPlusOffset);
485 Value baseShiftedLeft = LLVM::ShlOp::create(
486 rewriter, loc, dstType, op.getBase(), amountToShiftLeft);
489 Value amountToShiftRight =
490 LLVM::AddOp::create(rewriter, loc, dstType, offset, amountToShiftLeft);
491 rewriter.replaceOpWithNewOp<LLVM::AShrOp>(op, dstType, baseShiftedLeft,
497class BitFieldUExtractPattern
500 using SPIRVToLLVMConversion<spirv::BitFieldUExtractOp>::SPIRVToLLVMConversion;
503 matchAndRewrite(spirv::BitFieldUExtractOp op, OpAdaptor adaptor,
504 ConversionPatternRewriter &rewriter)
const override {
505 auto srcType = op.getType();
506 auto dstType = getTypeConverter()->convertType(srcType);
508 return rewriter.notifyMatchFailure(op,
"type conversion failed");
509 Location loc = op.getLoc();
513 *getTypeConverter(), rewriter);
515 *getTypeConverter(), rewriter);
519 Value maskShiftedByCount =
520 LLVM::ShlOp::create(rewriter, loc, dstType, minusOne, count);
521 Value mask = LLVM::XOrOp::create(rewriter, loc, dstType, maskShiftedByCount,
526 LLVM::LShrOp::create(rewriter, loc, dstType, op.getBase(), offset);
527 rewriter.replaceOpWithNewOp<LLVM::AndOp>(op, dstType, shiftedBase, mask);
534 using SPIRVToLLVMConversion<spirv::BranchOp>::SPIRVToLLVMConversion;
537 matchAndRewrite(spirv::BranchOp branchOp, OpAdaptor adaptor,
538 ConversionPatternRewriter &rewriter)
const override {
539 rewriter.replaceOpWithNewOp<LLVM::BrOp>(branchOp, adaptor.getOperands(),
540 branchOp.getTarget());
545class BranchConditionalConversionPattern
548 using SPIRVToLLVMConversion<
549 spirv::BranchConditionalOp>::SPIRVToLLVMConversion;
552 matchAndRewrite(spirv::BranchConditionalOp op, OpAdaptor adaptor,
553 ConversionPatternRewriter &rewriter)
const override {
556 if (
auto weights = op.getBranchWeights()) {
557 SmallVector<int32_t> weightValues;
558 for (
auto weight : weights->getAsRange<IntegerAttr>())
559 weightValues.push_back(weight.getInt());
563 rewriter.replaceOpWithNewOp<LLVM::CondBrOp>(
564 op, op.getCondition(), op.getTrueBlockArguments(),
565 op.getFalseBlockArguments(), branchWeights, op.getTrueBlock(),
574class CompositeExtractPattern
577 using SPIRVToLLVMConversion<spirv::CompositeExtractOp>::SPIRVToLLVMConversion;
580 matchAndRewrite(spirv::CompositeExtractOp op, OpAdaptor adaptor,
581 ConversionPatternRewriter &rewriter)
const override {
582 auto dstType = this->getTypeConverter()->convertType(op.getType());
584 return rewriter.notifyMatchFailure(op,
"type conversion failed");
586 Type containerType = op.getComposite().getType();
587 if (isa<VectorType>(containerType)) {
588 Location loc = op.getLoc();
589 IntegerAttr value = cast<IntegerAttr>(op.getIndices()[0]);
591 rewriter.replaceOpWithNewOp<LLVM::ExtractElementOp>(
592 op, dstType, adaptor.getComposite(), index);
596 rewriter.replaceOpWithNewOp<LLVM::ExtractValueOp>(
597 op, adaptor.getComposite(),
606class CompositeInsertPattern
609 using SPIRVToLLVMConversion<spirv::CompositeInsertOp>::SPIRVToLLVMConversion;
612 matchAndRewrite(spirv::CompositeInsertOp op, OpAdaptor adaptor,
613 ConversionPatternRewriter &rewriter)
const override {
614 auto dstType = this->getTypeConverter()->convertType(op.getType());
616 return rewriter.notifyMatchFailure(op,
"type conversion failed");
618 Type containerType = op.getComposite().getType();
619 if (isa<VectorType>(containerType)) {
620 Location loc = op.getLoc();
621 IntegerAttr value = cast<IntegerAttr>(op.getIndices()[0]);
623 rewriter.replaceOpWithNewOp<LLVM::InsertElementOp>(
624 op, dstType, adaptor.getComposite(), adaptor.getObject(), index);
628 rewriter.replaceOpWithNewOp<LLVM::InsertValueOp>(
629 op, adaptor.getComposite(), adaptor.getObject(),
637template <
typename SPIRVOp,
typename LLVMOp>
640 using SPIRVToLLVMConversion<SPIRVOp>::SPIRVToLLVMConversion;
643 matchAndRewrite(SPIRVOp op,
typename SPIRVOp::Adaptor adaptor,
644 ConversionPatternRewriter &rewriter)
const override {
645 auto dstType = this->getTypeConverter()->convertType(op.getType());
647 return rewriter.notifyMatchFailure(op,
"type conversion failed");
648 rewriter.template replaceOpWithNewOp<LLVMOp>(
649 op, dstType, adaptor.getOperands(), op->getAttrs());
656class ExecutionModePattern
659 using SPIRVToLLVMConversion<spirv::ExecutionModeOp>::SPIRVToLLVMConversion;
662 matchAndRewrite(spirv::ExecutionModeOp op, OpAdaptor adaptor,
663 ConversionPatternRewriter &rewriter)
const override {
667 ModuleOp module = op->getParentOfType<ModuleOp>();
668 spirv::ExecutionModeAttr executionModeAttr = op.getExecutionModeAttr();
669 std::string moduleName;
670 if (module.getName().has_value())
671 moduleName =
"_" +
module.getName()->str();
674 std::string executionModeInfoName = llvm::formatv(
675 "__spv_{0}_{1}_execution_mode_info_{2}", moduleName, op.getFn().str(),
676 static_cast<uint32_t
>(executionModeAttr.getValue()));
678 MLIRContext *context = rewriter.getContext();
679 OpBuilder::InsertionGuard guard(rewriter);
680 rewriter.setInsertionPointToStart(module.getBody());
687 auto llvmI32Type = IntegerType::get(context, 32);
688 SmallVector<Type, 2> fields;
689 fields.push_back(llvmI32Type);
691 if (!values.empty()) {
692 auto arrayType = LLVM::LLVMArrayType::get(llvmI32Type, values.size());
693 fields.push_back(arrayType);
695 auto structType = LLVM::LLVMStructType::getLiteral(context, fields);
698 auto global = LLVM::GlobalOp::create(
699 rewriter, UnknownLoc::get(context), structType,
true,
700 LLVM::Linkage::External, executionModeInfoName, Attribute(),
702 Location loc = global.getLoc();
703 Region ®ion = global.getInitializerRegion();
704 Block *block = rewriter.createBlock(®ion);
707 rewriter.setInsertionPointToStart(block);
708 Value structValue = LLVM::PoisonOp::create(rewriter, loc, structType);
709 Value executionMode = LLVM::ConstantOp::create(
710 rewriter, loc, llvmI32Type,
711 rewriter.getI32IntegerAttr(
712 static_cast<uint32_t
>(executionModeAttr.getValue())));
713 SmallVector<int64_t> position{0};
714 structValue = LLVM::InsertValueOp::create(rewriter, loc, structValue,
715 executionMode, position);
718 for (
unsigned i = 0, e = values.size(); i < e; ++i) {
719 auto attr = values.getValue()[i];
720 Value entry = LLVM::ConstantOp::create(rewriter, loc, llvmI32Type, attr);
721 structValue = LLVM::InsertValueOp::create(
722 rewriter, loc, structValue, entry, ArrayRef<int64_t>({1, i}));
724 LLVM::ReturnOp::create(rewriter, loc, ArrayRef<Value>({structValue}));
725 rewriter.eraseOp(op);
734class GlobalVariablePattern
737 template <
typename... Args>
738 GlobalVariablePattern(spirv::ClientAPI clientAPI, Args &&...args)
739 : SPIRVToLLVMConversion<spirv::GlobalVariableOp>(
740 std::forward<Args>(args)...),
741 clientAPI(clientAPI) {}
744 matchAndRewrite(spirv::GlobalVariableOp op, OpAdaptor adaptor,
745 ConversionPatternRewriter &rewriter)
const override {
748 if (op.getInitializer())
751 auto srcType = cast<spirv::PointerType>(op.getType());
752 auto dstType = getTypeConverter()->convertType(srcType.getPointeeType());
754 return rewriter.notifyMatchFailure(op,
"type conversion failed");
759 auto storageClass = srcType.getStorageClass();
760 switch (storageClass) {
761 case spirv::StorageClass::Input:
762 case spirv::StorageClass::Private:
763 case spirv::StorageClass::Output:
764 case spirv::StorageClass::StorageBuffer:
765 case spirv::StorageClass::UniformConstant:
774 bool isConstant = (storageClass == spirv::StorageClass::Input) ||
775 (storageClass == spirv::StorageClass::UniformConstant);
781 auto linkage = storageClass == spirv::StorageClass::Private
782 ? LLVM::Linkage::Private
783 : LLVM::Linkage::External;
784 StringAttr locationAttrName = op.getLocationAttrName();
785 IntegerAttr locationAttr = op.getLocationAttr();
786 auto newGlobalOp = rewriter.replaceOpWithNewOp<LLVM::GlobalOp>(
787 op, dstType, isConstant, linkage, op.getSymName(), Attribute(),
792 newGlobalOp->setAttr(locationAttrName, locationAttr);
798 spirv::ClientAPI clientAPI;
803template <
typename SPIRVOp,
typename LLVMExtOp,
typename LLVMTruncOp>
806 using SPIRVToLLVMConversion<SPIRVOp>::SPIRVToLLVMConversion;
809 matchAndRewrite(SPIRVOp op,
typename SPIRVOp::Adaptor adaptor,
810 ConversionPatternRewriter &rewriter)
const override {
812 Type fromType = op.getOperand().getType();
813 Type toType = op.getType();
815 auto dstType = this->getTypeConverter()->convertType(toType);
817 return rewriter.notifyMatchFailure(op,
"type conversion failed");
820 rewriter.template replaceOpWithNewOp<LLVMExtOp>(op, dstType,
821 adaptor.getOperands());
825 rewriter.template replaceOpWithNewOp<LLVMTruncOp>(op, dstType,
826 adaptor.getOperands());
833class FunctionCallPattern
836 using SPIRVToLLVMConversion<spirv::FunctionCallOp>::SPIRVToLLVMConversion;
839 matchAndRewrite(spirv::FunctionCallOp callOp, OpAdaptor adaptor,
840 ConversionPatternRewriter &rewriter)
const override {
841 if (callOp.getNumResults() == 0) {
842 auto newOp = rewriter.replaceOpWithNewOp<LLVM::CallOp>(
843 callOp,
TypeRange(), adaptor.getOperands(), callOp->getAttrs());
844 newOp.getProperties().operandSegmentSizes = {
845 static_cast<int32_t
>(adaptor.getOperands().size()), 0};
846 newOp.getProperties().op_bundle_sizes = rewriter.getDenseI32ArrayAttr({});
851 auto dstType = getTypeConverter()->convertType(callOp.getType(0));
853 return rewriter.notifyMatchFailure(callOp,
"type conversion failed");
854 auto newOp = rewriter.replaceOpWithNewOp<LLVM::CallOp>(
855 callOp, dstType, adaptor.getOperands(), callOp->getAttrs());
856 newOp.getProperties().operandSegmentSizes = {
857 static_cast<int32_t
>(adaptor.getOperands().size()), 0};
858 newOp.getProperties().op_bundle_sizes = rewriter.getDenseI32ArrayAttr({});
864template <
typename SPIRVOp, LLVM::FCmpPredicate predicate>
867 using SPIRVToLLVMConversion<SPIRVOp>::SPIRVToLLVMConversion;
870 matchAndRewrite(SPIRVOp op,
typename SPIRVOp::Adaptor adaptor,
871 ConversionPatternRewriter &rewriter)
const override {
873 auto dstType = this->getTypeConverter()->convertType(op.getType());
875 return rewriter.notifyMatchFailure(op,
"type conversion failed");
877 rewriter.template replaceOpWithNewOp<LLVM::FCmpOp>(
878 op, dstType, predicate, op.getOperand1(), op.getOperand2());
884template <
typename SPIRVOp, LLVM::ICmpPredicate predicate>
887 using SPIRVToLLVMConversion<SPIRVOp>::SPIRVToLLVMConversion;
890 matchAndRewrite(SPIRVOp op,
typename SPIRVOp::Adaptor adaptor,
891 ConversionPatternRewriter &rewriter)
const override {
893 auto dstType = this->getTypeConverter()->convertType(op.getType());
895 return rewriter.notifyMatchFailure(op,
"type conversion failed");
897 rewriter.template replaceOpWithNewOp<LLVM::ICmpOp>(
898 op, dstType, predicate, op.getOperand1(), op.getOperand2());
903class InverseSqrtPattern
906 using SPIRVToLLVMConversion<spirv::GLInverseSqrtOp>::SPIRVToLLVMConversion;
909 matchAndRewrite(spirv::GLInverseSqrtOp op, OpAdaptor adaptor,
910 ConversionPatternRewriter &rewriter)
const override {
911 auto srcType = op.getType();
912 auto dstType = getTypeConverter()->convertType(srcType);
914 return rewriter.notifyMatchFailure(op,
"type conversion failed");
916 Location loc = op.getLoc();
918 Value sqrt = LLVM::SqrtOp::create(rewriter, loc, dstType, op.getOperand());
919 rewriter.replaceOpWithNewOp<LLVM::FDivOp>(op, dstType, one, sqrt);
926template <
typename SPIRVOp,
typename LLVMMinOp,
typename LLVMMaxOp>
929 using SPIRVToLLVMConversion<SPIRVOp>::SPIRVToLLVMConversion;
932 matchAndRewrite(SPIRVOp op,
typename SPIRVOp::Adaptor adaptor,
933 ConversionPatternRewriter &rewriter)
const override {
934 Type dstType = this->getTypeConverter()->convertType(op.getType());
936 return rewriter.notifyMatchFailure(op,
"type conversion failed");
938 Location loc = op.getLoc();
939 Value
max = LLVMMaxOp::create(rewriter, loc, dstType, adaptor.getX(),
941 rewriter.template replaceOpWithNewOp<LLVMMinOp>(op, dstType,
max,
948template <
typename SPIRVOp>
951 using SPIRVToLLVMConversion<SPIRVOp>::SPIRVToLLVMConversion;
954 matchAndRewrite(SPIRVOp op,
typename SPIRVOp::Adaptor adaptor,
955 ConversionPatternRewriter &rewriter)
const override {
956 if (!op.getMemoryAccess()) {
958 *this->getTypeConverter(), 0,
962 auto memoryAccess = *op.getMemoryAccess();
963 switch (memoryAccess) {
964 case spirv::MemoryAccess::Aligned:
965 case spirv::MemoryAccess::None:
966 case spirv::MemoryAccess::Nontemporal:
967 case spirv::MemoryAccess::Volatile: {
969 memoryAccess == spirv::MemoryAccess::Aligned ? *op.getAlignment() : 0;
970 bool isNonTemporal = memoryAccess == spirv::MemoryAccess::Nontemporal;
971 bool isVolatile = memoryAccess == spirv::MemoryAccess::Volatile;
973 *this->getTypeConverter(), alignment,
974 isVolatile, isNonTemporal);
984template <
typename SPIRVOp>
987 using SPIRVToLLVMConversion<SPIRVOp>::SPIRVToLLVMConversion;
990 matchAndRewrite(SPIRVOp notOp,
typename SPIRVOp::Adaptor adaptor,
991 ConversionPatternRewriter &rewriter)
const override {
992 auto srcType = notOp.getType();
993 auto dstType = this->getTypeConverter()->convertType(srcType);
995 return rewriter.notifyMatchFailure(notOp,
"type conversion failed");
997 Location loc = notOp.getLoc();
1000 isa<VectorType>(srcType)
1001 ? LLVM::ConstantOp::create(
1002 rewriter, loc, dstType,
1003 SplatElementsAttr::get(cast<VectorType>(srcType), minusOne))
1004 : LLVM::ConstantOp::create(rewriter, loc, dstType, minusOne);
1005 rewriter.template replaceOpWithNewOp<LLVM::XOrOp>(notOp, dstType,
1006 notOp.getOperand(), mask);
1012template <
typename SPIRVOp>
1015 using SPIRVToLLVMConversion<SPIRVOp>::SPIRVToLLVMConversion;
1018 matchAndRewrite(SPIRVOp op,
typename SPIRVOp::Adaptor adaptor,
1019 ConversionPatternRewriter &rewriter)
const override {
1020 rewriter.eraseOp(op);
1027 using SPIRVToLLVMConversion<spirv::ReturnOp>::SPIRVToLLVMConversion;
1030 matchAndRewrite(spirv::ReturnOp returnOp, OpAdaptor adaptor,
1031 ConversionPatternRewriter &rewriter)
const override {
1032 rewriter.replaceOpWithNewOp<LLVM::ReturnOp>(returnOp, ArrayRef<Type>(),
1040 using SPIRVToLLVMConversion<spirv::ReturnValueOp>::SPIRVToLLVMConversion;
1043 matchAndRewrite(spirv::ReturnValueOp returnValueOp, OpAdaptor adaptor,
1044 ConversionPatternRewriter &rewriter)
const override {
1045 rewriter.replaceOpWithNewOp<LLVM::ReturnOp>(returnValueOp, ArrayRef<Type>(),
1046 adaptor.getOperands());
1053 using SPIRVToLLVMConversion<spirv::UnreachableOp>::SPIRVToLLVMConversion;
1056 matchAndRewrite(spirv::UnreachableOp unreachableOp, OpAdaptor adaptor,
1057 ConversionPatternRewriter &rewriter)
const override {
1058 rewriter.replaceOpWithNewOp<LLVM::UnreachableOp>(unreachableOp);
1067 bool convergent =
true) {
1068 auto func = dyn_cast_or_null<LLVM::LLVMFuncOp>(
1074 func = LLVM::LLVMFuncOp::create(
1075 b, symbolTable->
getLoc(), name,
1076 LLVM::LLVMFunctionType::get(resultType, paramTypes));
1077 func.setCConv(LLVM::cconv::CConv::SPIR_FUNC);
1078 func.setConvergent(convergent);
1079 func.setNoUnwind(
true);
1080 func.setWillReturn(
true);
1085 LLVM::LLVMFuncOp
func,
1087 auto call = LLVM::CallOp::create(builder, loc,
func, args);
1088 call.setCConv(
func.getCConv());
1089 call.setConvergentAttr(
func.getConvergentAttr());
1090 call.setNoUnwindAttr(
func.getNoUnwindAttr());
1091 call.setWillReturnAttr(
func.getWillReturnAttr());
1095template <
typename BarrierOpTy>
1098 using OpAdaptor =
typename SPIRVToLLVMConversion<BarrierOpTy>::OpAdaptor;
1100 using SPIRVToLLVMConversion<BarrierOpTy>::SPIRVToLLVMConversion;
1102 static constexpr StringRef getFuncName();
1105 matchAndRewrite(BarrierOpTy controlBarrierOp, OpAdaptor adaptor,
1106 ConversionPatternRewriter &rewriter)
const override {
1107 constexpr StringRef funcName = getFuncName();
1108 Operation *symbolTable =
1109 controlBarrierOp->template getParentWithTrait<OpTrait::SymbolTable>();
1111 Type i32 = rewriter.getI32Type();
1113 Type voidTy = rewriter.getType<LLVM::LLVMVoidType>();
1114 LLVM::LLVMFuncOp func =
1117 Location loc = controlBarrierOp->getLoc();
1118 Value execution = LLVM::ConstantOp::create(
1119 rewriter, loc, i32,
static_cast<int32_t
>(adaptor.getExecutionScope()));
1120 Value memory = LLVM::ConstantOp::create(
1121 rewriter, loc, i32,
static_cast<int32_t
>(adaptor.getMemoryScope()));
1122 Value semantics = LLVM::ConstantOp::create(
1123 rewriter, loc, i32,
static_cast<int32_t
>(adaptor.getMemorySemantics()));
1126 {execution, memory, semantics});
1128 rewriter.replaceOp(controlBarrierOp, call);
1135StringRef getTypeMangling(
Type type,
bool isSigned) {
1137 .Case([](Float16Type) {
return "Dh"; })
1138 .Case([](Float32Type) {
return "f"; })
1139 .Case([](Float64Type) {
return "d"; })
1140 .Case([isSigned](IntegerType intTy) {
1141 switch (intTy.getWidth()) {
1145 return (isSigned) ?
"a" :
"c";
1147 return (isSigned) ?
"s" :
"t";
1149 return (isSigned) ?
"i" :
"j";
1151 return (isSigned) ?
"l" :
"m";
1153 llvm_unreachable(
"Unsupported integer width");
1156 .DefaultUnreachable(
"No mangling defined");
1159template <
typename ReduceOp>
1160constexpr StringLiteral getGroupFuncName();
1163constexpr StringLiteral getGroupFuncName<spirv::GroupIAddOp>() {
1164 return "_Z17__spirv_GroupIAddii";
1167constexpr StringLiteral getGroupFuncName<spirv::GroupFAddOp>() {
1168 return "_Z17__spirv_GroupFAddii";
1171constexpr StringLiteral getGroupFuncName<spirv::GroupSMinOp>() {
1172 return "_Z17__spirv_GroupSMinii";
1175constexpr StringLiteral getGroupFuncName<spirv::GroupUMinOp>() {
1176 return "_Z17__spirv_GroupUMinii";
1179constexpr StringLiteral getGroupFuncName<spirv::GroupFMinOp>() {
1180 return "_Z17__spirv_GroupFMinii";
1183constexpr StringLiteral getGroupFuncName<spirv::GroupSMaxOp>() {
1184 return "_Z17__spirv_GroupSMaxii";
1187constexpr StringLiteral getGroupFuncName<spirv::GroupUMaxOp>() {
1188 return "_Z17__spirv_GroupUMaxii";
1191constexpr StringLiteral getGroupFuncName<spirv::GroupFMaxOp>() {
1192 return "_Z17__spirv_GroupFMaxii";
1195constexpr StringLiteral getGroupFuncName<spirv::GroupNonUniformIAddOp>() {
1196 return "_Z27__spirv_GroupNonUniformIAddii";
1199constexpr StringLiteral getGroupFuncName<spirv::GroupNonUniformFAddOp>() {
1200 return "_Z27__spirv_GroupNonUniformFAddii";
1203constexpr StringLiteral getGroupFuncName<spirv::GroupNonUniformIMulOp>() {
1204 return "_Z27__spirv_GroupNonUniformIMulii";
1207constexpr StringLiteral getGroupFuncName<spirv::GroupNonUniformFMulOp>() {
1208 return "_Z27__spirv_GroupNonUniformFMulii";
1211constexpr StringLiteral getGroupFuncName<spirv::GroupNonUniformSMinOp>() {
1212 return "_Z27__spirv_GroupNonUniformSMinii";
1215constexpr StringLiteral getGroupFuncName<spirv::GroupNonUniformUMinOp>() {
1216 return "_Z27__spirv_GroupNonUniformUMinii";
1219constexpr StringLiteral getGroupFuncName<spirv::GroupNonUniformFMinOp>() {
1220 return "_Z27__spirv_GroupNonUniformFMinii";
1223constexpr StringLiteral getGroupFuncName<spirv::GroupNonUniformSMaxOp>() {
1224 return "_Z27__spirv_GroupNonUniformSMaxii";
1227constexpr StringLiteral getGroupFuncName<spirv::GroupNonUniformUMaxOp>() {
1228 return "_Z27__spirv_GroupNonUniformUMaxii";
1231constexpr StringLiteral getGroupFuncName<spirv::GroupNonUniformFMaxOp>() {
1232 return "_Z27__spirv_GroupNonUniformFMaxii";
1235constexpr StringLiteral getGroupFuncName<spirv::GroupNonUniformBitwiseAndOp>() {
1236 return "_Z33__spirv_GroupNonUniformBitwiseAndii";
1239constexpr StringLiteral getGroupFuncName<spirv::GroupNonUniformBitwiseOrOp>() {
1240 return "_Z32__spirv_GroupNonUniformBitwiseOrii";
1243constexpr StringLiteral getGroupFuncName<spirv::GroupNonUniformBitwiseXorOp>() {
1244 return "_Z33__spirv_GroupNonUniformBitwiseXorii";
1247constexpr StringLiteral getGroupFuncName<spirv::GroupNonUniformLogicalAndOp>() {
1248 return "_Z33__spirv_GroupNonUniformLogicalAndii";
1251constexpr StringLiteral getGroupFuncName<spirv::GroupNonUniformLogicalOrOp>() {
1252 return "_Z32__spirv_GroupNonUniformLogicalOrii";
1255constexpr StringLiteral getGroupFuncName<spirv::GroupNonUniformLogicalXorOp>() {
1256 return "_Z33__spirv_GroupNonUniformLogicalXorii";
1260template <
typename ReduceOp,
bool Signed = false,
bool NonUniform = false>
1263 using SPIRVToLLVMConversion<ReduceOp>::SPIRVToLLVMConversion;
1266 matchAndRewrite(ReduceOp op,
typename ReduceOp::Adaptor adaptor,
1267 ConversionPatternRewriter &rewriter)
const override {
1269 Type retTy = op.getResult().getType();
1273 SmallString<36> funcName = getGroupFuncName<ReduceOp>();
1274 funcName += getTypeMangling(retTy,
false);
1276 Type i32Ty = rewriter.getI32Type();
1277 SmallVector<Type> paramTypes{i32Ty, i32Ty, retTy};
1278 if constexpr (NonUniform) {
1279 if (adaptor.getClusterSize()) {
1281 paramTypes.push_back(i32Ty);
1285 Operation *symbolTable =
1286 op->template getParentWithTrait<OpTrait::SymbolTable>();
1288 LLVM::LLVMFuncOp func =
1291 Location loc = op.getLoc();
1292 Value scope = LLVM::ConstantOp::create(
1293 rewriter, loc, i32Ty,
1294 static_cast<int32_t
>(adaptor.getExecutionScope()));
1295 Value groupOp = LLVM::ConstantOp::create(
1296 rewriter, loc, i32Ty,
1297 static_cast<int32_t
>(adaptor.getGroupOperation()));
1298 SmallVector<Value> operands{scope, groupOp};
1299 operands.append(adaptor.getOperands().begin(), adaptor.getOperands().end());
1302 rewriter.replaceOp(op, call);
1309ControlBarrierPattern<spirv::ControlBarrierOp>::getFuncName() {
1310 return "_Z22__spirv_ControlBarrieriii";
1315ControlBarrierPattern<spirv::INTELControlBarrierArriveOp>::getFuncName() {
1316 return "_Z33__spirv_ControlBarrierArriveINTELiii";
1321ControlBarrierPattern<spirv::INTELControlBarrierWaitOp>::getFuncName() {
1322 return "_Z31__spirv_ControlBarrierWaitINTELiii";
1375 using SPIRVToLLVMConversion<spirv::LoopOp>::SPIRVToLLVMConversion;
1378 matchAndRewrite(spirv::LoopOp loopOp, OpAdaptor adaptor,
1379 ConversionPatternRewriter &rewriter)
const override {
1381 if (loopOp.getLoopControl() != spirv::LoopControl::None)
1385 if (loopOp.getBody().empty()) {
1386 rewriter.eraseOp(loopOp);
1390 Location loc = loopOp.getLoc();
1394 Block *currentBlock = rewriter.getBlock();
1396 Block *endBlock = rewriter.splitBlock(currentBlock, position);
1400 Block *entryBlock = loopOp.getEntryBlock();
1402 auto brOp = dyn_cast<spirv::BranchOp>(entryBlock->
getOperations().front());
1405 Block *headerBlock = loopOp.getHeaderBlock();
1406 rewriter.setInsertionPointToEnd(currentBlock);
1407 LLVM::BrOp::create(rewriter, loc, brOp.getBlockArguments(), headerBlock);
1408 rewriter.eraseBlock(entryBlock);
1411 Block *mergeBlock = loopOp.getMergeBlock();
1414 rewriter.setInsertionPointToEnd(mergeBlock);
1415 LLVM::BrOp::create(rewriter, loc, terminatorOperands, endBlock);
1417 rewriter.inlineRegionBefore(loopOp.getBody(), endBlock);
1428 using SPIRVToLLVMConversion<spirv::SelectionOp>::SPIRVToLLVMConversion;
1431 matchAndRewrite(spirv::SelectionOp op, OpAdaptor adaptor,
1432 ConversionPatternRewriter &rewriter)
const override {
1436 if (op.getSelectionControl() != spirv::SelectionControl::None)
1443 if (op.getBody().getBlocks().size() <= 2) {
1444 rewriter.eraseOp(op);
1448 Location loc = op.getLoc();
1452 auto *currentBlock = rewriter.getInsertionBlock();
1453 rewriter.setInsertionPointAfter(op);
1454 auto position = rewriter.getInsertionPoint();
1455 auto *continueBlock = rewriter.splitBlock(currentBlock, position);
1461 auto *headerBlock = op.getHeaderBlock();
1463 auto condBrOp = dyn_cast<spirv::BranchConditionalOp>(
1469 auto *mergeBlock = op.getMergeBlock();
1472 rewriter.setInsertionPointToEnd(mergeBlock);
1473 LLVM::BrOp::create(rewriter, loc, terminatorOperands, continueBlock);
1476 Block *trueBlock = condBrOp.getTrueBlock();
1477 Block *falseBlock = condBrOp.getFalseBlock();
1478 rewriter.setInsertionPointToEnd(currentBlock);
1479 LLVM::CondBrOp::create(rewriter, loc, condBrOp.getCondition(), trueBlock,
1480 condBrOp.getTrueTargetOperands(), falseBlock,
1481 condBrOp.getFalseTargetOperands());
1483 rewriter.eraseBlock(headerBlock);
1484 rewriter.inlineRegionBefore(op.getBody(), continueBlock);
1485 rewriter.replaceOp(op, continueBlock->getArguments());
1494template <
typename SPIRVOp,
typename LLVMOp>
1497 using SPIRVToLLVMConversion<SPIRVOp>::SPIRVToLLVMConversion;
1500 matchAndRewrite(SPIRVOp op,
typename SPIRVOp::Adaptor adaptor,
1501 ConversionPatternRewriter &rewriter)
const override {
1503 auto dstType = this->getTypeConverter()->convertType(op.getType());
1505 return rewriter.notifyMatchFailure(op,
"type conversion failed");
1507 Type op1Type = op.getOperand1().getType();
1508 Type op2Type = op.getOperand2().getType();
1510 if (op1Type == op2Type) {
1511 rewriter.template replaceOpWithNewOp<LLVMOp>(op, dstType,
1512 adaptor.getOperands());
1516 std::optional<uint64_t> dstTypeWidth =
1518 std::optional<uint64_t> op2TypeWidth =
1521 if (!dstTypeWidth || !op2TypeWidth)
1524 Location loc = op.getLoc();
1526 if (op2TypeWidth < dstTypeWidth) {
1529 LLVM::ZExtOp::create(rewriter, loc, dstType, adaptor.getOperand2());
1532 LLVM::SExtOp::create(rewriter, loc, dstType, adaptor.getOperand2());
1534 }
else if (op2TypeWidth == dstTypeWidth) {
1535 extended = adaptor.getOperand2();
1541 LLVMOp::create(rewriter, loc, dstType, adaptor.getOperand1(), extended);
1542 rewriter.replaceOp(op,
result);
1549 using SPIRVToLLVMConversion<spirv::GLTanOp>::SPIRVToLLVMConversion;
1552 matchAndRewrite(spirv::GLTanOp tanOp, OpAdaptor adaptor,
1553 ConversionPatternRewriter &rewriter)
const override {
1554 auto dstType = getTypeConverter()->convertType(tanOp.getType());
1556 return rewriter.notifyMatchFailure(tanOp,
"type conversion failed");
1558 rewriter.replaceOpWithNewOp<LLVM::TanOp>(tanOp, dstType,
1559 adaptor.getOperands());
1566 using SPIRVToLLVMConversion<spirv::GLTanhOp>::SPIRVToLLVMConversion;
1569 matchAndRewrite(spirv::GLTanhOp tanhOp, OpAdaptor adaptor,
1570 ConversionPatternRewriter &rewriter)
const override {
1571 auto srcType = tanhOp.getType();
1572 auto dstType = getTypeConverter()->convertType(srcType);
1574 return rewriter.notifyMatchFailure(tanhOp,
"type conversion failed");
1576 rewriter.replaceOpWithNewOp<LLVM::TanhOp>(tanhOp, dstType,
1577 adaptor.getOperands());
1587 using SPIRVToLLVMConversion<spirv::GLSAbsOp>::SPIRVToLLVMConversion;
1590 matchAndRewrite(spirv::GLSAbsOp op, OpAdaptor adaptor,
1591 ConversionPatternRewriter &rewriter)
const override {
1592 Type dstType = getTypeConverter()->convertType(op.getType());
1594 return rewriter.notifyMatchFailure(op,
"type conversion failed");
1596 rewriter.replaceOpWithNewOp<LLVM::AbsOp>(op, dstType, adaptor.getOperand(),
1605 using SPIRVToLLVMConversion<spirv::GLFractOp>::SPIRVToLLVMConversion;
1608 matchAndRewrite(spirv::GLFractOp op, OpAdaptor adaptor,
1609 ConversionPatternRewriter &rewriter)
const override {
1610 Type dstType = getTypeConverter()->convertType(op.getType());
1612 return rewriter.notifyMatchFailure(op,
"type conversion failed");
1614 Location loc = op.getLoc();
1615 Value operand = adaptor.getOperand();
1616 Value floored = LLVM::FFloorOp::create(rewriter, loc, dstType, operand);
1617 rewriter.replaceOpWithNewOp<LLVM::FSubOp>(op, dstType, operand, floored);
1626 using SPIRVToLLVMConversion<spirv::GLFMixOp>::SPIRVToLLVMConversion;
1629 matchAndRewrite(spirv::GLFMixOp op, OpAdaptor adaptor,
1630 ConversionPatternRewriter &rewriter)
const override {
1631 Type dstType = getTypeConverter()->convertType(op.getType());
1633 return rewriter.notifyMatchFailure(op,
"type conversion failed");
1635 Location loc = op.getLoc();
1636 Value x = adaptor.getX();
1637 Value y = adaptor.getY();
1638 Value a = adaptor.getA();
1640 Value oneMinusA = LLVM::FSubOp::create(rewriter, loc, dstType, one, a);
1641 Value
lhs = LLVM::FMulOp::create(rewriter, loc, dstType, x, oneMinusA);
1642 Value
rhs = LLVM::FMulOp::create(rewriter, loc, dstType, y, a);
1643 rewriter.replaceOpWithNewOp<LLVM::FAddOp>(op, dstType,
lhs,
rhs);
1652 using SPIRVToLLVMConversion<spirv::CLMixOp>::SPIRVToLLVMConversion;
1655 matchAndRewrite(spirv::CLMixOp op, OpAdaptor adaptor,
1656 ConversionPatternRewriter &rewriter)
const override {
1657 Type dstType = getTypeConverter()->convertType(op.getType());
1659 return rewriter.notifyMatchFailure(op,
"type conversion failed");
1661 Location loc = op.getLoc();
1662 Value x = adaptor.getX();
1663 Value y = adaptor.getY();
1664 Value a = adaptor.getZ();
1665 Value diff = LLVM::FSubOp::create(rewriter, loc, dstType, y, x);
1666 rewriter.replaceOpWithNewOp<LLVM::FMAOp>(op, dstType, a, diff, x);
1673template <
typename SPIRVOp>
1676 template <
typename... Args>
1677 ScalePattern(
double scale, Args &&...args)
1678 : SPIRVToLLVMConversion<SPIRVOp>(std::forward<Args>(args)...),
1682 matchAndRewrite(SPIRVOp op,
typename SPIRVOp::Adaptor adaptor,
1683 ConversionPatternRewriter &rewriter)
const override {
1684 Type srcType = op.getType();
1685 Type dstType = this->getTypeConverter()->convertType(srcType);
1687 return rewriter.notifyMatchFailure(op,
"type conversion failed");
1689 Location loc = op.getLoc();
1691 rewriter.replaceOpWithNewOp<LLVM::FMulOp>(op, dstType, adaptor.getOperand(),
1702 using SPIRVToLLVMConversion<spirv::VariableOp>::SPIRVToLLVMConversion;
1705 matchAndRewrite(spirv::VariableOp varOp, OpAdaptor adaptor,
1706 ConversionPatternRewriter &rewriter)
const override {
1707 auto srcType = varOp.getType();
1709 auto pointerTo = cast<spirv::PointerType>(srcType).getPointeeType();
1710 auto init = varOp.getInitializer();
1711 if (init && !pointerTo.isIntOrFloat() && !isa<VectorType>(pointerTo))
1714 auto dstType = getTypeConverter()->convertType(srcType);
1716 return rewriter.notifyMatchFailure(varOp,
"type conversion failed");
1718 Location loc = varOp.getLoc();
1721 auto elementType = getTypeConverter()->convertType(pointerTo);
1723 return rewriter.notifyMatchFailure(varOp,
"type conversion failed");
1724 rewriter.replaceOpWithNewOp<LLVM::AllocaOp>(varOp, dstType, elementType,
1728 auto elementType = getTypeConverter()->convertType(pointerTo);
1730 return rewriter.notifyMatchFailure(varOp,
"type conversion failed");
1732 LLVM::AllocaOp::create(rewriter, loc, dstType, elementType, size);
1733 LLVM::StoreOp::create(rewriter, loc, adaptor.getInitializer(), allocated);
1734 rewriter.replaceOp(varOp, allocated);
1743class BitcastConversionPattern
1746 using SPIRVToLLVMConversion<spirv::BitcastOp>::SPIRVToLLVMConversion;
1749 matchAndRewrite(spirv::BitcastOp bitcastOp, OpAdaptor adaptor,
1750 ConversionPatternRewriter &rewriter)
const override {
1751 auto dstType = getTypeConverter()->convertType(bitcastOp.getType());
1753 return rewriter.notifyMatchFailure(bitcastOp,
"type conversion failed");
1756 if (isa<LLVM::LLVMPointerType>(dstType)) {
1757 rewriter.replaceOp(bitcastOp, adaptor.getOperand());
1761 rewriter.replaceOpWithNewOp<LLVM::BitcastOp>(
1762 bitcastOp, dstType, adaptor.getOperands(), bitcastOp->getAttrs());
1773 using SPIRVToLLVMConversion<spirv::FuncOp>::SPIRVToLLVMConversion;
1776 matchAndRewrite(spirv::FuncOp funcOp, OpAdaptor adaptor,
1777 ConversionPatternRewriter &rewriter)
const override {
1781 auto funcType = funcOp.getFunctionType();
1782 TypeConverter::SignatureConversion signatureConverter(
1783 funcType.getNumInputs());
1784 auto llvmType =
static_cast<const LLVMTypeConverter *
>(getTypeConverter())
1785 ->convertFunctionSignature(
1787 false, signatureConverter);
1792 Location loc = funcOp.getLoc();
1793 StringRef name = funcOp.getName();
1794 auto newFuncOp = LLVM::LLVMFuncOp::create(rewriter, loc, name, llvmType);
1797 MLIRContext *context = funcOp.getContext();
1798 switch (funcOp.getFunctionControl()) {
1799 case spirv::FunctionControl::Inline:
1800 newFuncOp.setAlwaysInline(
true);
1802 case spirv::FunctionControl::DontInline:
1803 newFuncOp.setNoInline(
true);
1806#define DISPATCH(functionControl, llvmAttr) \
1807 case functionControl: \
1808 newFuncOp->setAttr("passthrough", ArrayAttr::get(context, {llvmAttr})); \
1811 DISPATCH(spirv::FunctionControl::Pure,
1812 StringAttr::get(context,
"readonly"));
1813 DISPATCH(spirv::FunctionControl::Const,
1814 StringAttr::get(context,
"readnone"));
1824 rewriter.inlineRegionBefore(funcOp.getBody(), newFuncOp.getBody(),
1826 if (
failed(rewriter.convertRegionTypes(
1827 &newFuncOp.getBody(), *getTypeConverter(), &signatureConverter))) {
1830 rewriter.eraseOp(funcOp);
1841 using SPIRVToLLVMConversion<spirv::ModuleOp>::SPIRVToLLVMConversion;
1844 matchAndRewrite(spirv::ModuleOp spvModuleOp, OpAdaptor adaptor,
1845 ConversionPatternRewriter &rewriter)
const override {
1848 ModuleOp::create(rewriter, spvModuleOp.getLoc(), spvModuleOp.getName());
1849 rewriter.inlineRegionBefore(spvModuleOp.getRegion(), newModuleOp.getBody());
1852 rewriter.eraseBlock(&newModuleOp.getBodyRegion().back());
1853 rewriter.eraseOp(spvModuleOp);
1862class VectorShufflePattern
1865 using SPIRVToLLVMConversion<spirv::VectorShuffleOp>::SPIRVToLLVMConversion;
1867 matchAndRewrite(spirv::VectorShuffleOp op, OpAdaptor adaptor,
1868 ConversionPatternRewriter &rewriter)
const override {
1869 Location loc = op.getLoc();
1870 auto components = adaptor.getComponents();
1871 auto vector1 = adaptor.getVector1();
1872 auto vector2 = adaptor.getVector2();
1873 int vector1Size = cast<VectorType>(vector1.getType()).getNumElements();
1874 int vector2Size = cast<VectorType>(vector2.getType()).getNumElements();
1875 if (vector1Size == vector2Size) {
1876 rewriter.replaceOpWithNewOp<LLVM::ShuffleVectorOp>(
1877 op, vector1, vector2,
1882 auto dstType = getTypeConverter()->convertType(op.getType());
1884 return rewriter.notifyMatchFailure(op,
"type conversion failed");
1885 auto scalarType = cast<VectorType>(dstType).getElementType();
1886 auto componentsArray = components.getValue();
1887 auto *context = rewriter.getContext();
1888 auto llvmI32Type = IntegerType::get(context, 32);
1889 Value targetOp = LLVM::PoisonOp::create(rewriter, loc, dstType);
1890 for (
unsigned i = 0; i < componentsArray.size(); i++) {
1891 if (!isa<IntegerAttr>(componentsArray[i]))
1892 return op.emitError(
"unable to support non-constant component");
1894 int indexVal = cast<IntegerAttr>(componentsArray[i]).getInt();
1899 Value baseVector = vector1;
1900 if (indexVal >= vector1Size) {
1901 offsetVal = vector1Size;
1902 baseVector = vector2;
1905 Value dstIndex = LLVM::ConstantOp::create(
1906 rewriter, loc, llvmI32Type,
1907 rewriter.getIntegerAttr(rewriter.getI32Type(), i));
1908 Value index = LLVM::ConstantOp::create(
1909 rewriter, loc, llvmI32Type,
1910 rewriter.getIntegerAttr(rewriter.getI32Type(), indexVal - offsetVal));
1912 auto extractOp = LLVM::ExtractElementOp::create(rewriter, loc, scalarType,
1914 targetOp = LLVM::InsertElementOp::create(rewriter, loc, dstType, targetOp,
1915 extractOp, dstIndex);
1917 rewriter.replaceOp(op, targetOp);
1928 spirv::ClientAPI clientAPI) {
1945 spirv::ClientAPI clientAPI) {
1948 DirectConversionPattern<spirv::IAddOp, LLVM::AddOp>,
1949 DirectConversionPattern<spirv::IMulOp, LLVM::MulOp>,
1950 DirectConversionPattern<spirv::ISubOp, LLVM::SubOp>,
1951 DirectConversionPattern<spirv::FAddOp, LLVM::FAddOp>,
1952 DirectConversionPattern<spirv::FDivOp, LLVM::FDivOp>,
1953 DirectConversionPattern<spirv::FMulOp, LLVM::FMulOp>,
1954 DirectConversionPattern<spirv::FNegateOp, LLVM::FNegOp>,
1955 DirectConversionPattern<spirv::FRemOp, LLVM::FRemOp>,
1956 DirectConversionPattern<spirv::FSubOp, LLVM::FSubOp>,
1957 DirectConversionPattern<spirv::SDivOp, LLVM::SDivOp>,
1958 DirectConversionPattern<spirv::SRemOp, LLVM::SRemOp>,
1959 DirectConversionPattern<spirv::UDivOp, LLVM::UDivOp>,
1960 DirectConversionPattern<spirv::UModOp, LLVM::URemOp>,
1963 BitFieldInsertPattern, BitFieldUExtractPattern, BitFieldSExtractPattern,
1964 DirectConversionPattern<spirv::BitCountOp, LLVM::CtPopOp>,
1965 DirectConversionPattern<spirv::BitReverseOp, LLVM::BitReverseOp>,
1966 DirectConversionPattern<spirv::BitwiseAndOp, LLVM::AndOp>,
1967 DirectConversionPattern<spirv::BitwiseOrOp, LLVM::OrOp>,
1968 DirectConversionPattern<spirv::BitwiseXorOp, LLVM::XOrOp>,
1969 NotPattern<spirv::NotOp>,
1972 BitcastConversionPattern,
1973 DirectConversionPattern<spirv::ConvertFToSOp, LLVM::FPToSIOp>,
1974 DirectConversionPattern<spirv::ConvertFToUOp, LLVM::FPToUIOp>,
1975 DirectConversionPattern<spirv::ConvertSToFOp, LLVM::SIToFPOp>,
1976 DirectConversionPattern<spirv::ConvertUToFOp, LLVM::UIToFPOp>,
1977 IndirectCastPattern<spirv::FConvertOp, LLVM::FPExtOp, LLVM::FPTruncOp>,
1978 IndirectCastPattern<spirv::SConvertOp, LLVM::SExtOp, LLVM::TruncOp>,
1979 IndirectCastPattern<spirv::UConvertOp, LLVM::ZExtOp, LLVM::TruncOp>,
1980 DirectConversionPattern<spirv::ConvertPtrToUOp, LLVM::PtrToIntOp>,
1981 DirectConversionPattern<spirv::ConvertUToPtrOp, LLVM::IntToPtrOp>,
1982 DirectConversionPattern<spirv::PtrCastToGenericOp, LLVM::AddrSpaceCastOp>,
1983 DirectConversionPattern<spirv::GenericCastToPtrOp, LLVM::AddrSpaceCastOp>,
1984 DirectConversionPattern<spirv::GenericCastToPtrExplicitOp,
1985 LLVM::AddrSpaceCastOp>,
1988 IComparePattern<spirv::IEqualOp, LLVM::ICmpPredicate::eq>,
1989 IComparePattern<spirv::INotEqualOp, LLVM::ICmpPredicate::ne>,
1990 FComparePattern<spirv::FOrdEqualOp, LLVM::FCmpPredicate::oeq>,
1991 FComparePattern<spirv::FOrdGreaterThanOp, LLVM::FCmpPredicate::ogt>,
1992 FComparePattern<spirv::FOrdGreaterThanEqualOp, LLVM::FCmpPredicate::oge>,
1993 FComparePattern<spirv::FOrdLessThanEqualOp, LLVM::FCmpPredicate::ole>,
1994 FComparePattern<spirv::FOrdLessThanOp, LLVM::FCmpPredicate::olt>,
1995 FComparePattern<spirv::FOrdNotEqualOp, LLVM::FCmpPredicate::one>,
1996 FComparePattern<spirv::FUnordEqualOp, LLVM::FCmpPredicate::ueq>,
1997 FComparePattern<spirv::FUnordGreaterThanOp, LLVM::FCmpPredicate::ugt>,
1998 FComparePattern<spirv::FUnordGreaterThanEqualOp,
1999 LLVM::FCmpPredicate::uge>,
2000 FComparePattern<spirv::FUnordLessThanEqualOp, LLVM::FCmpPredicate::ule>,
2001 FComparePattern<spirv::FUnordLessThanOp, LLVM::FCmpPredicate::ult>,
2002 FComparePattern<spirv::FUnordNotEqualOp, LLVM::FCmpPredicate::une>,
2003 FComparePattern<spirv::OrderedOp, LLVM::FCmpPredicate::ord>,
2004 FComparePattern<spirv::UnorderedOp, LLVM::FCmpPredicate::uno>,
2005 IComparePattern<spirv::SGreaterThanOp, LLVM::ICmpPredicate::sgt>,
2006 IComparePattern<spirv::SGreaterThanEqualOp, LLVM::ICmpPredicate::sge>,
2007 IComparePattern<spirv::SLessThanEqualOp, LLVM::ICmpPredicate::sle>,
2008 IComparePattern<spirv::SLessThanOp, LLVM::ICmpPredicate::slt>,
2009 IComparePattern<spirv::UGreaterThanOp, LLVM::ICmpPredicate::ugt>,
2010 IComparePattern<spirv::UGreaterThanEqualOp, LLVM::ICmpPredicate::uge>,
2011 IComparePattern<spirv::ULessThanEqualOp, LLVM::ICmpPredicate::ule>,
2012 IComparePattern<spirv::ULessThanOp, LLVM::ICmpPredicate::ult>,
2015 ConstantScalarAndVectorPattern,
2018 BranchConversionPattern, BranchConditionalConversionPattern,
2019 FunctionCallPattern, LoopPattern, SelectionPattern,
2020 ErasePattern<spirv::MergeOp>,
2023 ErasePattern<spirv::EntryPointOp>, ExecutionModePattern,
2026 DirectConversionPattern<spirv::GLCeilOp, LLVM::FCeilOp>,
2027 DirectConversionPattern<spirv::GLCosOp, LLVM::CosOp>,
2028 DirectConversionPattern<spirv::GLExpOp, LLVM::ExpOp>,
2029 DirectConversionPattern<spirv::GLExp2Op, LLVM::Exp2Op>,
2030 DirectConversionPattern<spirv::GLFAbsOp, LLVM::FAbsOp>,
2031 DirectConversionPattern<spirv::GLFloorOp, LLVM::FFloorOp>,
2032 DirectConversionPattern<spirv::GLFmaOp, LLVM::FMAOp>,
2033 ClampPattern<spirv::GLFClampOp, LLVM::MinNumOp, LLVM::MaxNumOp>,
2034 ClampPattern<spirv::GLSClampOp, LLVM::SMinOp, LLVM::SMaxOp>,
2035 ClampPattern<spirv::GLUClampOp, LLVM::UMinOp, LLVM::UMaxOp>,
2036 DirectConversionPattern<spirv::GLFMaxOp, LLVM::MaxNumOp>,
2037 DirectConversionPattern<spirv::GLFMinOp, LLVM::MinNumOp>,
2038 DirectConversionPattern<spirv::GLNMaxOp, LLVM::MaxNumOp>,
2039 DirectConversionPattern<spirv::GLNMinOp, LLVM::MinNumOp>,
2040 DirectConversionPattern<spirv::GLLogOp, LLVM::LogOp>,
2041 DirectConversionPattern<spirv::GLLog2Op, LLVM::Log2Op>,
2042 DirectConversionPattern<spirv::GLPowOp, LLVM::PowOp>,
2043 DirectConversionPattern<spirv::GLRoundOp, LLVM::RoundOp>,
2044 DirectConversionPattern<spirv::GLRoundEvenOp, LLVM::RoundEvenOp>,
2045 DirectConversionPattern<spirv::GLSinOp, LLVM::SinOp>,
2046 DirectConversionPattern<spirv::GLSinhOp, LLVM::SinhOp>,
2047 DirectConversionPattern<spirv::GLCoshOp, LLVM::CoshOp>,
2048 DirectConversionPattern<spirv::GLSMaxOp, LLVM::SMaxOp>,
2049 DirectConversionPattern<spirv::GLSMinOp, LLVM::SMinOp>,
2050 DirectConversionPattern<spirv::GLSqrtOp, LLVM::SqrtOp>,
2051 DirectConversionPattern<spirv::GLUMaxOp, LLVM::UMaxOp>,
2052 DirectConversionPattern<spirv::GLUMinOp, LLVM::UMinOp>,
2053 DirectConversionPattern<spirv::GLTruncOp, LLVM::FTruncOp>,
2054 DirectConversionPattern<spirv::GLAsinOp, LLVM::ASinOp>,
2055 DirectConversionPattern<spirv::GLAcosOp, LLVM::ACosOp>,
2056 DirectConversionPattern<spirv::GLAtanOp, LLVM::ATanOp>,
2057 InverseSqrtPattern, SAbsPattern, TanPattern, TanhPattern, FractPattern,
2061 DirectConversionPattern<spirv::CLCeilOp, LLVM::FCeilOp>,
2062 DirectConversionPattern<spirv::CLCosOp, LLVM::CosOp>,
2063 DirectConversionPattern<spirv::CLExpOp, LLVM::ExpOp>,
2064 DirectConversionPattern<spirv::CLExp2Op, LLVM::Exp2Op>,
2065 DirectConversionPattern<spirv::CLExp10Op, LLVM::Exp10Op>,
2066 DirectConversionPattern<spirv::CLFAbsOp, LLVM::FAbsOp>,
2067 DirectConversionPattern<spirv::CLFloorOp, LLVM::FFloorOp>,
2068 DirectConversionPattern<spirv::CLFmaOp, LLVM::FMAOp>,
2069 DirectConversionPattern<spirv::CLFMaxOp, LLVM::MaxNumOp>,
2070 DirectConversionPattern<spirv::CLFMinOp, LLVM::MinNumOp>,
2071 DirectConversionPattern<spirv::CLLogOp, LLVM::LogOp>,
2072 DirectConversionPattern<spirv::CLLog2Op, LLVM::Log2Op>,
2073 DirectConversionPattern<spirv::CLLog10Op, LLVM::Log10Op>,
2074 DirectConversionPattern<spirv::CLPowOp, LLVM::PowOp>,
2075 DirectConversionPattern<spirv::CLRintOp, LLVM::RintOp>,
2076 DirectConversionPattern<spirv::CLRoundOp, LLVM::RoundOp>,
2077 DirectConversionPattern<spirv::CLSinOp, LLVM::SinOp>,
2078 DirectConversionPattern<spirv::CLSinhOp, LLVM::SinhOp>,
2079 DirectConversionPattern<spirv::CLCoshOp, LLVM::CoshOp>,
2080 DirectConversionPattern<spirv::CLTanOp, LLVM::TanOp>,
2081 DirectConversionPattern<spirv::CLTanhOp, LLVM::TanhOp>,
2082 DirectConversionPattern<spirv::CLAsinOp, LLVM::ASinOp>,
2083 DirectConversionPattern<spirv::CLAcosOp, LLVM::ACosOp>,
2084 DirectConversionPattern<spirv::CLAtanOp, LLVM::ATanOp>,
2085 DirectConversionPattern<spirv::CLAtan2Op, LLVM::ATan2Op>,
2086 DirectConversionPattern<spirv::CLSqrtOp, LLVM::SqrtOp>,
2087 DirectConversionPattern<spirv::CLTruncOp, LLVM::FTruncOp>,
2088 DirectConversionPattern<spirv::CLCopysignOp, LLVM::CopySignOp>,
2089 DirectConversionPattern<spirv::CLFmodOp, LLVM::FRemOp>,
2090 DirectConversionPattern<spirv::CLSMaxOp, LLVM::SMaxOp>,
2091 DirectConversionPattern<spirv::CLSMinOp, LLVM::SMinOp>,
2092 DirectConversionPattern<spirv::CLUMaxOp, LLVM::UMaxOp>,
2093 DirectConversionPattern<spirv::CLUMinOp, LLVM::UMinOp>, CLMixPattern,
2096 DirectConversionPattern<spirv::LogicalAndOp, LLVM::AndOp>,
2097 DirectConversionPattern<spirv::LogicalOrOp, LLVM::OrOp>,
2098 IComparePattern<spirv::LogicalEqualOp, LLVM::ICmpPredicate::eq>,
2099 IComparePattern<spirv::LogicalNotEqualOp, LLVM::ICmpPredicate::ne>,
2100 NotPattern<spirv::LogicalNotOp>,
2103 AccessChainPattern, AddressOfPattern, LoadStorePattern<spirv::LoadOp>,
2104 LoadStorePattern<spirv::StoreOp>, VariablePattern,
2107 CompositeExtractPattern, CompositeInsertPattern,
2108 DirectConversionPattern<spirv::SelectOp, LLVM::SelectOp>,
2109 DirectConversionPattern<spirv::UndefOp, LLVM::UndefOp>,
2110 VectorShufflePattern,
2113 ShiftPattern<spirv::ShiftRightArithmeticOp, LLVM::AShrOp>,
2114 ShiftPattern<spirv::ShiftRightLogicalOp, LLVM::LShrOp>,
2115 ShiftPattern<spirv::ShiftLeftLogicalOp, LLVM::ShlOp>,
2118 ReturnPattern, ReturnValuePattern,
2124 ControlBarrierPattern<spirv::ControlBarrierOp>,
2125 ControlBarrierPattern<spirv::INTELControlBarrierArriveOp>,
2126 ControlBarrierPattern<spirv::INTELControlBarrierWaitOp>,
2129 GroupReducePattern<spirv::GroupIAddOp>,
2130 GroupReducePattern<spirv::GroupFAddOp>,
2131 GroupReducePattern<spirv::GroupFMinOp>,
2132 GroupReducePattern<spirv::GroupUMinOp>,
2133 GroupReducePattern<spirv::GroupSMinOp,
true>,
2134 GroupReducePattern<spirv::GroupFMaxOp>,
2135 GroupReducePattern<spirv::GroupUMaxOp>,
2136 GroupReducePattern<spirv::GroupSMaxOp,
true>,
2137 GroupReducePattern<spirv::GroupNonUniformIAddOp,
false,
2139 GroupReducePattern<spirv::GroupNonUniformFAddOp,
false,
2141 GroupReducePattern<spirv::GroupNonUniformIMulOp,
false,
2143 GroupReducePattern<spirv::GroupNonUniformFMulOp,
false,
2145 GroupReducePattern<spirv::GroupNonUniformSMinOp,
true,
2147 GroupReducePattern<spirv::GroupNonUniformUMinOp,
false,
2149 GroupReducePattern<spirv::GroupNonUniformFMinOp,
false,
2151 GroupReducePattern<spirv::GroupNonUniformSMaxOp,
true,
2153 GroupReducePattern<spirv::GroupNonUniformUMaxOp,
false,
2155 GroupReducePattern<spirv::GroupNonUniformFMaxOp,
false,
2157 GroupReducePattern<spirv::GroupNonUniformBitwiseAndOp,
false,
2159 GroupReducePattern<spirv::GroupNonUniformBitwiseOrOp,
false,
2161 GroupReducePattern<spirv::GroupNonUniformBitwiseXorOp,
false,
2163 GroupReducePattern<spirv::GroupNonUniformLogicalAndOp,
false,
2165 GroupReducePattern<spirv::GroupNonUniformLogicalOrOp,
false,
2167 GroupReducePattern<spirv::GroupNonUniformLogicalXorOp,
false,
2171 patterns.
add<GlobalVariablePattern>(clientAPI, patterns.
getContext(),
2174 patterns.
add<ScalePattern<spirv::GLRadiansOp>>(
2175 0.017453292519943295, patterns.
getContext(), typeConverter);
2177 patterns.
add<ScalePattern<spirv::GLDegreesOp>>(
2178 57.29577951308232, patterns.
getContext(), typeConverter);
2183 patterns.
add<FuncConversionPattern>(patterns.
getContext(), typeConverter);
2188 patterns.
add<ModuleConversionPattern>(patterns.
getContext(), typeConverter);
2199 auto spvModules =
module.getOps<spirv::ModuleOp>();
2200 for (
auto spvModule : spvModules) {
2201 spvModule.walk([&](spirv::GlobalVariableOp op) {
2202 IntegerAttr descriptorSet =
2204 IntegerAttr binding = op->getAttrOfType<IntegerAttr>(
kBinding);
2207 if (descriptorSet && binding) {
2210 auto moduleAndName =
2211 spvModule.getName().has_value()
2212 ? spvModule.getName()->str() +
"_" + op.getSymName().str()
2213 : op.getSymName().str();
2215 llvm::formatv(
"{0}_descriptor_set{1}_binding{2}", moduleAndName,
2216 std::to_string(descriptorSet.getInt()),
2217 std::to_string(binding.getInt()));
2218 auto nameAttr = StringAttr::get(op->getContext(), name);
2223 op.emitError(
"unable to replace all symbol uses for ") << name;
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 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 constexpr StringRef kDescriptorSet
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 constexpr StringRef kBinding
Hook for descriptor set and binding number encoding.
static IntegerAttr minusOneIntegerAttribute(Type type, Builder builder)
Creates IntegerAttribute with all bits set for given type.
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 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()
This class is a general helper class for creating context-global objects like types,...
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...
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
SmallVector< IntT > convertArrayToIndices(ArrayRef< Attribute > attrs)
Convert an array of integer attributes to a vector of integers that can be used as indices in LLVM op...
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.
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.