19#include "mlir/Conversion/LLVMCommon/TypeConverter.h"
20#include "mlir/Conversion/OpenMPToLLVM/ConvertOpenMPToLLVM.h"
21#include "mlir/Dialect/DLTI/DLTI.h"
22#include "mlir/Dialect/Func/IR/FuncOps.h"
23#include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
24#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
25#include "mlir/Dialect/LLVMIR/LLVMTypes.h"
26#include "mlir/Dialect/OpenMP/OpenMPDialect.h"
27#include "mlir/Dialect/OpenMP/Transforms/Passes.h"
28#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
29#include "mlir/IR/BuiltinAttributes.h"
30#include "mlir/IR/BuiltinDialect.h"
31#include "mlir/IR/BuiltinOps.h"
32#include "mlir/IR/Diagnostics.h"
33#include "mlir/IR/Location.h"
34#include "mlir/IR/Matchers.h"
35#include "mlir/IR/Types.h"
36#include "mlir/Pass/Pass.h"
37#include "mlir/Pass/PassManager.h"
38#include "mlir/Support/LLVM.h"
39#include "mlir/Target/LLVMIR/Dialect/Builtin/BuiltinToLLVMIRTranslation.h"
40#include "mlir/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.h"
41#include "mlir/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.h"
42#include "mlir/Target/LLVMIR/Export.h"
43#include "mlir/Transforms/DialectConversion.h"
53#include "llvm/ADT/MapVector.h"
54#include "llvm/ADT/StringMap.h"
55#include "llvm/ADT/TypeSwitch.h"
56#include "llvm/IR/Module.h"
57#include "llvm/Support/AMDGPUAddrSpace.h"
58#include "llvm/Support/Casting.h"
59#include "llvm/Support/ErrorHandling.h"
60#include "llvm/Support/TimeProfiler.h"
61#include "llvm/Support/VirtualFileSystem.h"
62#include "llvm/Support/raw_ostream.h"
63#include "llvm/TargetParser/AtomicScope.h"
78mlir::Type elementTypeIfVectorOrMatrix(mlir::Type type) {
79 return llvm::TypeSwitch<mlir::Type, mlir::Type>(type)
80 .Case<cir::VectorType, cir::MatrixType, mlir::VectorType>(
81 [](
auto p) {
return p.getElementType(); })
82 .
Default([](mlir::Type p) {
return p; });
87 "ClangIR lowering NYI: cannot convert ";
103 mlir::Type llvmMemType,
104 const mlir::DataLayout &dataLayout) {
105 if (
auto intTy = mlir::dyn_cast<cir::IntType>(cirType);
106 intTy && intTy.isBitInt())
107 return intTy.getABIAlignment(dataLayout, {});
108 return dataLayout.getTypeABIAlignment(llvmMemType);
112 mlir::IntegerType dstTy,
113 bool isSigned =
false) {
114 mlir::Type srcTy = src.getType();
115 assert(mlir::isa<mlir::IntegerType>(srcTy));
117 unsigned srcWidth = mlir::cast<mlir::IntegerType>(srcTy).getWidth();
118 unsigned dstWidth = mlir::cast<mlir::IntegerType>(dstTy).getWidth();
119 mlir::Location loc = src.getLoc();
121 if (dstWidth > srcWidth && isSigned)
122 return mlir::LLVM::SExtOp::create(bld, loc, dstTy, src);
123 if (dstWidth > srcWidth)
124 return mlir::LLVM::ZExtOp::create(bld, loc, dstTy, src);
125 if (dstWidth < srcWidth)
126 return mlir::LLVM::TruncOp::create(bld, loc, dstTy, src);
127 return mlir::LLVM::BitcastOp::create(bld, loc, dstTy, src);
137 const mlir::DataLayout &dataLayout, cir::IntType intTy,
138 mlir::Value value,
bool toMemory) {
139 unsigned storageBits = intTy.getStorageTypeWidth(dataLayout);
140 if (storageBits == intTy.getWidth())
142 unsigned dstBits = toMemory ? storageBits : intTy.getWidth();
143 return createIntCast(rewriter, value, rewriter.getIntegerType(dstBits),
144 toMemory && intTy.isSigned());
147static mlir::LLVM::Visibility
149 switch (visibilityKind) {
150 case cir::VisibilityKind::Default:
151 return ::mlir::LLVM::Visibility::Default;
152 case cir::VisibilityKind::Hidden:
153 return ::mlir::LLVM::Visibility::Hidden;
154 case cir::VisibilityKind::Protected:
155 return ::mlir::LLVM::Visibility::Protected;
157 llvm_unreachable(
"fully covered switch");
162 mlir::Value srcVec,
unsigned numElementsDst) {
163 auto srcTy = mlir::cast<mlir::VectorType>(srcVec.getType());
164 unsigned numElementsSrc = srcTy.getNumElements();
165 if (numElementsSrc == numElementsDst)
169 for (
unsigned i : llvm::seq(std::min(numElementsDst, numElementsSrc)))
172 mlir::Location loc = srcVec.getLoc();
173 auto poison = mlir::LLVM::PoisonOp::create(rewriter, loc, srcVec.getType());
174 return mlir::LLVM::ShuffleVectorOp::create(rewriter, loc, srcVec, poison,
182 const mlir::TypeConverter &converter,
183 mlir::DataLayout
const &dataLayout,
184 cir::LoadOp op, mlir::Value value) {
186 if (
auto boolTy = mlir::dyn_cast<cir::BoolType>(op.getType())) {
188 assert(value.getType().isInteger(dataLayout.getTypeSizeInBits(boolTy)));
193 if (
auto vecTy = mlir::dyn_cast<cir::VectorType>(op.getType())) {
194 if (mlir::isa<cir::BoolType>(vecTy.getElementType())) {
195 if (vecTy.isScalable())
197 auto rawIntTy = mlir::cast<mlir::IntegerType>(value.getType());
198 auto paddedVecTy = cir::VectorType::getFixed(vecTy.getElementType(),
199 rawIntTy.getWidth());
200 mlir::Type mlirVecTy = converter.convertType(paddedVecTy);
202 auto v = mlir::LLVM::BitcastOp::create(rewriter, value.getLoc(),
210 if (
auto intTy = mlir::dyn_cast<cir::IntType>(op.getType());
211 intTy && intTy.isBitInt())
221static mlir::Value
emitToMemory(mlir::ConversionPatternRewriter &rewriter,
222 mlir::DataLayout
const &dataLayout,
223 mlir::Type origType, mlir::Value value) {
226 if (
auto boolTy = mlir::dyn_cast<cir::BoolType>(origType)) {
228 mlir::IntegerType memType =
229 rewriter.getIntegerType(dataLayout.getTypeSizeInBits(boolTy));
237 if (
auto vecTy = mlir::dyn_cast<cir::VectorType>(origType)) {
238 if (mlir::isa<cir::BoolType>(vecTy.getElementType())) {
240 if (vecTy.isScalable())
242 mlir::VectorType::get(vecTy.getSize().getKnownMinValue(),
243 vecTy.getElementType(), vecTy.isScalable());
245 resultTy = mlir::IntegerType::get(origType.getContext(),
246 vecTy.getBoolStorageWidth());
250 return mlir::LLVM::BitcastOp::create(rewriter, value.getLoc(), resultTy,
256 if (
auto intTy = mlir::dyn_cast<cir::IntType>(origType);
257 intTy && intTy.isBitInt())
265 using CIR = cir::GlobalLinkageKind;
266 using LLVM = mlir::LLVM::Linkage;
269 case CIR::AppendingLinkage:
270 return LLVM::Appending;
271 case CIR::AvailableExternallyLinkage:
272 return LLVM::AvailableExternally;
273 case CIR::CommonLinkage:
275 case CIR::ExternalLinkage:
276 return LLVM::External;
277 case CIR::ExternalWeakLinkage:
278 return LLVM::ExternWeak;
279 case CIR::InternalLinkage:
280 return LLVM::Internal;
281 case CIR::LinkOnceAnyLinkage:
282 return LLVM::Linkonce;
283 case CIR::LinkOnceODRLinkage:
284 return LLVM::LinkonceODR;
285 case CIR::PrivateLinkage:
286 return LLVM::Private;
287 case CIR::WeakAnyLinkage:
289 case CIR::WeakODRLinkage:
290 return LLVM::WeakODR;
292 llvm_unreachable(
"Unknown CIR linkage type");
296 using CIR = cir::CallingConv;
297 using LLVM = mlir::LLVM::CConv;
299 switch (callingConv) {
302 case CIR::SpirKernel:
303 return LLVM::SPIR_KERNEL;
304 case CIR::SpirFunction:
305 return LLVM::SPIR_FUNC;
307 return LLVM::PTX_Kernel;
308 case CIR::AMDGPUKernel:
309 return LLVM::AMDGPU_KERNEL;
311 llvm_unreachable(
"Unknown calling convention");
314static mlir::LLVM::uwtable::UWTableKind
316 using CIR = cir::UnwindTableKind;
317 using LLVM = mlir::LLVM::uwtable::UWTableKind;
327 llvm_unreachable(
"Unknown CIR unwind table kind");
330static mlir::LLVM::framePointerKind::FramePointerKind
332 using CIR = cir::FramePointerKind;
333 using LLVM = mlir::LLVM::framePointerKind::FramePointerKind;
339 return LLVM::NonLeaf;
343 return LLVM::Reserved;
344 case CIR::NonLeafNoReserve:
345 return LLVM::NonLeafNoReserve;
347 llvm_unreachable(
"Unknown CIR frame pointer kind");
352static llvm::FramePointerKind
354 using CIR = cir::FramePointerKind;
355 using LLVM = llvm::FramePointerKind;
361 return LLVM::NonLeaf;
365 return LLVM::Reserved;
366 case CIR::NonLeafNoReserve:
367 return LLVM::NonLeafNoReserve;
369 llvm_unreachable(
"Unknown CIR frame pointer kind");
372mlir::LogicalResult CIRToLLVMCopyOpLowering::matchAndRewrite(
373 cir::CopyOp op, OpAdaptor adaptor,
374 mlir::ConversionPatternRewriter &rewriter)
const {
376 mlir::Type pointeeType = op.getType().getPointee();
380 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
381 const mlir::Value
length = mlir::LLVM::ConstantOp::create(
382 rewriter, op.getLoc(), rewriter.getI64Type(),
383 op.getCopySizeInBytes(layout));
386 uint64_t dstTypeAlign =
387 dataLayout.getTypeABIAlignment(op.getDst().getType().getPointee());
388 uint64_t srcTypeAlign =
389 dataLayout.getTypeABIAlignment(op.getSrc().getType().getPointee());
391 mlir::NamedAttribute dstAlignAttr = rewriter.getNamedAttr(
392 mlir::LLVM::LLVMDialect::getAlignAttrName(),
393 rewriter.getI64IntegerAttr(op.getDstAlignment().value_or(dstTypeAlign)));
394 mlir::NamedAttribute srcAlignAttr = rewriter.getNamedAttr(
395 mlir::LLVM::LLVMDialect::getAlignAttrName(),
396 rewriter.getI64IntegerAttr(op.getSrcAlignment().value_or(srcTypeAlign)));
397 mlir::ArrayAttr argAttrs = rewriter.getArrayAttr({
398 rewriter.getDictionaryAttr({dstAlignAttr}),
399 rewriter.getDictionaryAttr({srcAlignAttr}),
402 rewriter.replaceOpWithNewOp<mlir::LLVM::MemcpyOp>(
403 op, adaptor.getDst(), adaptor.getSrc(),
length, op.getIsVolatile(),
405 nullptr,
nullptr, argAttrs,
407 return mlir::success();
410template <
typename CIROp,
typename LLVMOp>
411static mlir::LogicalResult
413 mlir::ConversionPatternRewriter &rewriter) {
414 mlir::ArrayAttr argAttrs;
415 if (op.getDstAlignment() || op.getSrcAlignment()) {
416 mlir::NamedAttribute dstAlignAttr = rewriter.getNamedAttr(
417 mlir::LLVM::LLVMDialect::getAlignAttrName(),
418 rewriter.getI64IntegerAttr(op.getDstAlignment().value_or(1)));
419 mlir::NamedAttribute srcAlignAttr = rewriter.getNamedAttr(
420 mlir::LLVM::LLVMDialect::getAlignAttrName(),
421 rewriter.getI64IntegerAttr(op.getSrcAlignment().value_or(1)));
422 argAttrs = rewriter.getArrayAttr({
423 rewriter.getDictionaryAttr({dstAlignAttr}),
424 rewriter.getDictionaryAttr({srcAlignAttr}),
427 rewriter.replaceOpWithNewOp<LLVMOp>(
428 op, adaptor.getDst(), adaptor.getSrc(), adaptor.getLen(),
431 nullptr,
nullptr, argAttrs,
433 return mlir::success();
436mlir::LogicalResult CIRToLLVMMemCpyOpLowering::matchAndRewrite(
437 cir::MemCpyOp op, OpAdaptor adaptor,
438 mlir::ConversionPatternRewriter &rewriter)
const {
443mlir::LogicalResult CIRToLLVMMemMoveOpLowering::matchAndRewrite(
444 cir::MemMoveOp op, OpAdaptor adaptor,
445 mlir::ConversionPatternRewriter &rewriter)
const {
450mlir::LogicalResult CIRToLLVMMemSetOpLowering::matchAndRewrite(
451 cir::MemSetOp op, OpAdaptor adaptor,
452 mlir::ConversionPatternRewriter &rewriter)
const {
455 mlir::Attribute alignAttr = op.getAlignmentAttr();
456 auto memset = rewriter.replaceOpWithNewOp<mlir::LLVM::MemsetOp>(
457 op, adaptor.getDst(), adaptor.getVal(), adaptor.getLen(),
462 llvm::SmallVector<mlir::Attribute> attrs{
memset.getNumOperands(),
463 rewriter.getDictionaryAttr({})};
464 llvm::SmallVector<mlir::NamedAttribute> destAttrs;
466 {mlir::LLVM::LLVMDialect::getAlignAttrName(), alignAttr});
467 attrs[
memset.odsIndex_dst] = rewriter.getDictionaryAttr(destAttrs);
469 auto arrayAttr = rewriter.getArrayAttr(attrs);
470 memset.setArgAttrsAttr(arrayAttr);
473 return mlir::success();
477 mlir::Value llvmSrc, mlir::Type llvmDstIntTy,
479 uint64_t cirDstIntWidth) {
480 if (cirSrcWidth == cirDstIntWidth)
483 auto loc = llvmSrc.getLoc();
484 if (cirSrcWidth < cirDstIntWidth) {
486 return mlir::LLVM::ZExtOp::create(rewriter, loc, llvmDstIntTy, llvmSrc);
487 return mlir::LLVM::SExtOp::create(rewriter, loc, llvmDstIntTy, llvmSrc);
491 return mlir::LLVM::TruncOp::create(rewriter, loc, llvmDstIntTy, llvmSrc);
497 mlir::ConversionPatternRewriter &rewriter,
498 mlir::SymbolTableCollection &symbolTables,
499 const mlir::TypeConverter *converter,
502 : parentLoc(parentLoc), parentModule(parentModule), rewriter(rewriter),
503 symbolTables(symbolTables), converter(converter),
504 preConversionTypes(preConversionTypes), blockInfoAddr(blockInfoAddr) {}
506#define GET_CIR_ATTR_TO_VALUE_VISITOR_DECLS
507#include "clang/CIR/Dialect/IR/CIRLowering.inc"
508#undef GET_CIR_ATTR_TO_VALUE_VISITOR_DECLS
511 struct LoweredGlobalSymbol {
513 mlir::Type sourceType;
514 mlir::Type originalType;
518 LoweredGlobalSymbol getAddressOfSymbol(mlir::FlatSymbolRefAttr symbol);
519 mlir::Value castGlobalAddrToType(mlir::Value addr, mlir::Type attrType,
520 mlir::Type sourceType,
unsigned addrSpace);
522 mlir::Location parentLoc;
523 mlir::ModuleOp parentModule;
524 mlir::ConversionPatternRewriter &rewriter;
525 mlir::SymbolTableCollection &symbolTables;
526 const mlir::TypeConverter *converter;
530 LLVMBlockAddressInfo *blockInfoAddr;
536 const mlir::Attribute attr,
537 mlir::ConversionPatternRewriter &rewriter,
538 mlir::SymbolTableCollection &symbolTables,
539 const mlir::TypeConverter *converter,
542 CIRAttrToValue valueConverter(parentLoc, parentModule, rewriter, symbolTables,
543 converter, preConversionTypes, blockInfoAddr);
544 return valueConverter.visit(attr);
549 case cir::ModRefInfo::NoModRef:
550 return mlir::LLVM::ModRefInfo::NoModRef;
551 case cir::ModRefInfo::Ref:
552 return mlir::LLVM::ModRefInfo::Ref;
553 case cir::ModRefInfo::Mod:
554 return mlir::LLVM::ModRefInfo::Mod;
555 case cir::ModRefInfo::ModRef:
556 return mlir::LLVM::ModRefInfo::ModRef;
558 llvm_unreachable(
"unhandled cir::ModRefInfo");
562static mlir::LLVM::MemoryEffectsAttr
567 return mlir::LLVM::MemoryEffectsAttr::get(
577 cir::MemoryEffectsAttr effects,
578 mlir::LLVM::MemoryEffectsAttr &memoryEffect,
579 bool &noUnwind,
bool &willReturn,
585 noUnwind = isNothrow || callOp->hasAttr(CIRDialect::getNoUnwindAttrName());
586 willReturn = callOp->hasAttr(CIRDialect::getWillReturnAttrName());
587 noReturn = callOp->hasAttr(CIRDialect::getNoReturnAttrName());
590static mlir::LLVM::CallIntrinsicOp
592 mlir::Location loc,
const llvm::Twine &intrinsicName,
593 mlir::Type resultTy, mlir::ValueRange operands,
594 mlir::LLVM::FastmathFlags fastmathFlags = {}) {
595 auto intrinsicNameAttr =
596 mlir::StringAttr::get(rewriter.getContext(), intrinsicName);
598 mlir::LLVM::FastmathFlagsAttr::get(rewriter.getContext(), fastmathFlags);
602 return mlir::LLVM::CallIntrinsicOp::create(
603 rewriter, loc, mlir::TypeRange{resultTy}, intrinsicNameAttr, operands,
605 return mlir::LLVM::CallIntrinsicOp::create(rewriter, loc, intrinsicNameAttr,
610 mlir::ConversionPatternRewriter &rewriter, mlir::Operation *op,
611 const llvm::Twine &intrinsicName, mlir::Type resultTy,
612 mlir::ValueRange operands, mlir::LLVM::FastmathFlags fastmathFlags = {}) {
614 rewriter, op->getLoc(), intrinsicName, resultTy, operands, fastmathFlags);
615 rewriter.replaceOp(op, callIntrinOp.getOperation());
620 std::optional<cir::FPDynamicRoundingMode> rounding =
621 fenv.getDynamicRoundingMode();
623 return "round.tonearest";
625 case cir::FPDynamicRoundingMode::ToNearest:
626 return "round.tonearest";
627 case cir::FPDynamicRoundingMode::Downward:
628 return "round.downward";
629 case cir::FPDynamicRoundingMode::Upward:
630 return "round.upward";
631 case cir::FPDynamicRoundingMode::UpwardZero:
632 return "round.towardzero";
633 case cir::FPDynamicRoundingMode::ToNearestAway:
634 return "round.tonearestaway";
635 case cir::FPDynamicRoundingMode::Unknown:
636 return "round.dynamic";
638 llvm_unreachable(
"unknown FP dynamic rounding mode");
642 std::optional<cir::FPExceptionMode> exceptMode = fenv.getExceptMode();
643 if (exceptMode == cir::FPExceptionMode::Masked)
644 return "fpexcept.ignore";
645 mlir::BoolAttr strictExcept = fenv.getStrictExcept();
647 return "fpexcept.ignore";
648 return strictExcept.getValue() ?
"fpexcept.strict" :
"fpexcept.maytrap";
653 mlir::Location loc, llvm::StringRef str) {
654 auto mdString = mlir::LLVM::MDStringAttr::get(
655 rewriter.getContext(), mlir::StringAttr::get(rewriter.getContext(), str));
656 return mlir::LLVM::MetadataAsValueOp::create(rewriter, loc, mdString);
660 mlir::Operation *op, mlir::ValueRange operands, cir::FenvAttr fenv,
661 mlir::Type llvmResTy, mlir::ConversionPatternRewriter &rewriter,
662 llvm::StringRef constrainedMnemonic,
bool hasRoundingMode,
663 mlir::LLVM::FastmathFlags fastmathFlags) {
664 mlir::Location loc = op->getLoc();
673 rewriter, op,
"llvm.experimental.constrained." + constrainedMnemonic,
674 llvmResTy, callOperands, fastmathFlags);
675 return mlir::success();
678static mlir::LLVM::FastmathFlags
682 mlir::ConversionPatternRewriter &rewriter, mlir::Location loc,
683 mlir::ValueRange operands, mlir::Type llvmResTy, cir::FenvAttr fenv,
684 llvm::StringRef constrainedMnemonic,
bool hasRoundingMode,
685 mlir::LLVM::FastmathFlags fastmathFlags = {}) {
695 rewriter, loc,
"llvm.experimental.constrained." + constrainedMnemonic,
696 llvmResTy, callOperands, fastmathFlags);
697 return intrinsic->getResult(0);
700template <
typename LLVMOp>
702 mlir::Operation *op, mlir::ValueRange operands, cir::FenvAttr fenv,
703 cir::FastMathFlagsAttr fastmath,
const mlir::TypeConverter &typeConverter,
704 mlir::ConversionPatternRewriter &rewriter,
705 llvm::StringRef constrainedMnemonic,
bool hasRoundingMode) {
706 mlir::Type llvmResTy = typeConverter.convertType(op->getResultTypes()[0]);
708 return op->emitError(
"expected LLVM result type for floating-point op");
710 mlir::LLVM::FastmathFlags fastmathFlags = {};
715 auto newOp = rewriter.replaceOpWithNewOp<LLVMOp>(
716 op, mlir::TypeRange{llvmResTy}, operands,
718 if (fastmathFlags != mlir::LLVM::FastmathFlags::none)
719 mlir::cast<mlir::LLVM::FastmathFlagsInterface>(newOp.getOperation())
720 .setFastmathAttr(mlir::LLVM::FastmathFlagsAttr::get(
721 rewriter.getContext(), fastmathFlags));
722 return mlir::success();
726 constrainedMnemonic, hasRoundingMode,
730static mlir::LLVM::FastmathFlags
732 mlir::LLVM::FastmathFlags llvmFlags{};
733 const std::pair<cir::FastMathFlags, mlir::LLVM::FastmathFlags> flags[] = {
734 {cir::FastMathFlags::nnan, mlir::LLVM::FastmathFlags::nnan},
735 {cir::FastMathFlags::ninf, mlir::LLVM::FastmathFlags::ninf},
736 {cir::FastMathFlags::nsz, mlir::LLVM::FastmathFlags::nsz},
737 {cir::FastMathFlags::arcp, mlir::LLVM::FastmathFlags::arcp},
738 {cir::FastMathFlags::contract, mlir::LLVM::FastmathFlags::contract},
739 {cir::FastMathFlags::afn, mlir::LLVM::FastmathFlags::afn},
740 {cir::FastMathFlags::reassoc, mlir::LLVM::FastmathFlags::reassoc},
743 for (
auto [cirFlag, llvmFlag] : flags) {
744 if (bitEnumContainsAny(cirFlags, cirFlag))
745 llvmFlags = llvmFlags | llvmFlag;
751mlir::LogicalResult CIRToLLVMLLVMIntrinsicCallOpLowering::matchAndRewrite(
752 cir::LLVMIntrinsicCallOp op, OpAdaptor adaptor,
753 mlir::ConversionPatternRewriter &rewriter)
const {
756 mlir::Type llvmResTy;
757 if (op->getNumResults() != 0) {
758 llvmResTy = getTypeConverter()->convertType(op->getResultTypes()[0]);
760 return op.emitError(
"expected LLVM result type");
762 StringRef name = op.getIntrinsicName();
763 mlir::LLVM::FastmathFlags fastmathFlags = {};
764 if (std::optional<cir::FastMathFlags> fastmath = op.getFastmathFlags())
778 adaptor.getOperands(), fastmathFlags);
779 return mlir::success();
783mlir::Value CIRAttrToValue::visitCirAttr(cir::BoolAttr boolAttr) {
784 mlir::DataLayout layout(parentModule);
785 mlir::Value boolVal = mlir::LLVM::ConstantOp::create(
786 rewriter, parentLoc, converter->convertType(boolAttr.getType()),
787 boolAttr.getValue());
788 return emitToMemory(rewriter, layout, boolAttr.getType(), boolVal);
792mlir::Value CIRAttrToValue::visitCirAttr(cir::IntAttr intAttr) {
793 mlir::DataLayout layout(parentModule);
795 if (
auto intTy = mlir::dyn_cast<cir::IntType>(intAttr.getType());
796 intTy && intTy.isBitInt()) {
798 return mlir::LLVM::ConstantOp::create(
799 rewriter, parentLoc, biTy,
806 mlir::Value val = mlir::LLVM::ConstantOp::create(
807 rewriter, parentLoc, converter->convertType(intAttr.getType()),
809 return emitToMemory(rewriter, layout, intAttr.getType(), val);
813mlir::Value CIRAttrToValue::visitCirAttr(cir::FPAttr fltAttr) {
814 return mlir::LLVM::ConstantOp::create(
815 rewriter, parentLoc, converter->convertType(fltAttr.getType()),
820mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstComplexAttr complexAttr) {
821 cir::ComplexType
complexType = complexAttr.getType();
822 mlir::Type complexElemTy =
complexType.getElementType();
823 mlir::Type complexElemLLVMTy = converter->convertType(complexElemTy);
825 mlir::Attribute components[2];
826 if (
const auto intType = mlir::dyn_cast<cir::IntType>(complexElemTy)) {
827 components[0] = rewriter.getIntegerAttr(
829 mlir::cast<cir::IntAttr>(complexAttr.getReal()).getValue());
830 components[1] = rewriter.getIntegerAttr(
832 mlir::cast<cir::IntAttr>(complexAttr.getImag()).getValue());
834 components[0] = rewriter.getFloatAttr(
836 mlir::cast<cir::FPAttr>(complexAttr.getReal()).getValue());
837 components[1] = rewriter.getFloatAttr(
839 mlir::cast<cir::FPAttr>(complexAttr.getImag()).getValue());
842 return mlir::LLVM::ConstantOp::create(
843 rewriter, parentLoc, converter->convertType(complexAttr.getType()),
844 rewriter.getArrayAttr(components));
848mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstPtrAttr ptrAttr) {
849 if (ptrAttr.isNullValue()) {
850 return mlir::LLVM::ZeroOp::create(
851 rewriter, parentLoc, converter->convertType(ptrAttr.getType()));
853 mlir::DataLayout layout(parentModule);
854 mlir::Value ptrVal = mlir::LLVM::ConstantOp::create(
856 rewriter.getIntegerType(layout.getTypeSizeInBits(ptrAttr.getType())),
857 ptrAttr.getValue().getInt());
858 return mlir::LLVM::IntToPtrOp::create(
859 rewriter, parentLoc, converter->convertType(ptrAttr.getType()), ptrVal);
863mlir::Value CIRAttrToValue::visitCirAttr(cir::BlockAddrInfoAttr blockAddrInfo) {
864 assert(blockInfoAddr &&
865 "block address lowering requires LLVMBlockAddressInfo");
870 mlir::LLVM::BlockTagOp matchLabel =
871 blockInfoAddr->lookupBlockTag(blockAddrInfo);
872 mlir::LLVM::BlockTagAttr tagAttr =
873 matchLabel ? matchLabel.getTag() : mlir::LLVM::BlockTagAttr{};
874 auto blkAddr = mlir::LLVM::BlockAddressAttr::get(
875 rewriter.getContext(), blockAddrInfo.getFunc(), tagAttr);
876 auto blockAddressOp = mlir::LLVM::BlockAddressOp::create(
878 mlir::LLVM::LLVMPointerType::get(rewriter.getContext()), blkAddr);
880 blockInfoAddr->addUnresolvedBlockAddress(blockAddressOp, blockAddrInfo);
881 return blockAddressOp;
885mlir::Value CIRAttrToValue::visitCirAttr(cir::BlockAddrDiffAttr blockAddrDiff) {
886 assert(blockInfoAddr &&
887 "block address lowering requires LLVMBlockAddressInfo");
893 mlir::DataLayout layout(parentModule);
894 mlir::MLIRContext *ctx = rewriter.getContext();
895 auto ptrTy = mlir::LLVM::LLVMPointerType::get(ctx);
897 auto emitBlockAddr = [&](mlir::StringAttr label) -> mlir::Value {
898 auto info = cir::BlockAddrInfoAttr::get(
899 ctx, blockAddrDiff.getFunc().getValue(), label.getValue());
900 mlir::LLVM::BlockTagOp matchLabel = blockInfoAddr->lookupBlockTag(info);
901 mlir::LLVM::BlockTagAttr tagAttr =
902 matchLabel ? matchLabel.getTag() : mlir::LLVM::BlockTagAttr{};
903 auto blkAddr = mlir::LLVM::BlockAddressAttr::get(
904 ctx, blockAddrDiff.getFunc(), tagAttr);
906 mlir::LLVM::BlockAddressOp::create(rewriter, parentLoc, ptrTy, blkAddr);
908 blockInfoAddr->addUnresolvedBlockAddress(addrOp, info);
912 mlir::Value lhsAddr = emitBlockAddr(blockAddrDiff.getLhsLabel());
913 mlir::Value rhsAddr = emitBlockAddr(blockAddrDiff.getRhsLabel());
919 mlir::Type intptrTy =
920 rewriter.getIntegerType(layout.getTypeSizeInBits(ptrTy));
922 mlir::LLVM::PtrToIntOp::create(rewriter, parentLoc, intptrTy, lhsAddr);
924 mlir::LLVM::PtrToIntOp::create(rewriter, parentLoc, intptrTy, rhsAddr);
925 mlir::Value diffVal =
926 mlir::LLVM::SubOp::create(rewriter, parentLoc, lhsInt, rhsInt);
928 mlir::Type resultTy = converter->convertType(blockAddrDiff.getType());
929 mlir::Value result = diffVal;
930 if (resultTy != intptrTy)
932 mlir::LLVM::TruncOp::create(rewriter, parentLoc, resultTy, diffVal);
937mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstArrayAttr attr) {
938 mlir::Type convertedTy = converter->convertType(
attr.getType());
939 mlir::DataLayout dataLayout(parentModule);
950 if (mlir::isa<mlir::LLVM::LLVMArrayType>(llvmTy))
952 attr, symbolTables, converter, preConversionTypes, parentModule))
953 return mlir::LLVM::ConstantOp::create(rewriter, parentLoc, llvmTy,
956 if (
attr.hasTrailingZeros())
957 result = mlir::LLVM::ZeroOp::create(rewriter, parentLoc, llvmTy);
959 result = mlir::LLVM::UndefOp::create(rewriter, parentLoc, llvmTy);
962 if (
auto arrayAttr = mlir::dyn_cast<mlir::ArrayAttr>(
attr.getElts())) {
973 auto structTy = mlir::dyn_cast<mlir::LLVM::LLVMStructType>(llvmTy);
974 if (structTy && structTy.getBody().size() < arrayAttr.size()) {
975 auto arrayTy = mlir::cast<cir::ArrayType>(
attr.getType());
976 auto prefix = cir::ConstArrayAttr::get(
977 cir::ArrayType::get(arrayTy.getElementType(), arrayAttr.size()),
979 mlir::Value init = visit(prefix);
982 return mlir::LLVM::InsertValueOp::create(
983 rewriter, parentLoc, result, init, llvm::ArrayRef<int64_t>{0});
985 for (
auto [idx, elt] : llvm::enumerate(arrayAttr)) {
986 mlir::Value init = visit(elt);
989 result = mlir::LLVM::InsertValueOp::create(rewriter, parentLoc, result,
992 }
else if (
auto strAttr = mlir::dyn_cast<mlir::StringAttr>(
attr.getElts())) {
995 auto arrayTy = mlir::dyn_cast<cir::ArrayType>(strAttr.getType());
996 assert(arrayTy &&
"String attribute must have an array type");
997 mlir::Type eltTy = arrayTy.getElementType();
998 for (
auto [idx, elt] : llvm::enumerate(strAttr)) {
999 auto init = mlir::LLVM::ConstantOp::create(
1000 rewriter, parentLoc, converter->convertType(eltTy), elt);
1001 result = mlir::LLVM::InsertValueOp::create(rewriter, parentLoc, result,
1005 llvm_unreachable(
"unexpected ConstArrayAttr elements");
1012mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstRecordAttr constRecord) {
1013 mlir::Type llvmTy = converter->convertType(constRecord.getType());
1014 mlir::DataLayout dataLayout(parentModule);
1015 llvm::SmallVector<unsigned> paddingAddedIndexes;
1017 paddingAddedIndexes);
1020 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, parentLoc, llvmTy);
1023 auto paddingItr = paddingAddedIndexes.begin();
1028 for (
auto [idx, elt] : llvm::enumerate(constRecord.getMembers())) {
1029 if (paddingItr != paddingAddedIndexes.end() && *paddingItr == idx) {
1034 mlir::Value init = visit(elt);
1037 result = mlir::LLVM::InsertValueOp::create(rewriter, parentLoc, result,
1046mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstVectorAttr attr) {
1047 const mlir::Type llvmTy = converter->convertType(
attr.getType());
1049 SmallVector<mlir::Attribute> mlirValues;
1050 for (
const mlir::Attribute elementAttr :
attr.getElts()) {
1051 mlir::Attribute mlirAttr;
1052 if (
auto intAttr = mlir::dyn_cast<cir::IntAttr>(elementAttr)) {
1053 mlirAttr = rewriter.getIntegerAttr(
1054 converter->convertType(intAttr.getType()), intAttr.getValue());
1055 }
else if (
auto floatAttr = mlir::dyn_cast<cir::FPAttr>(elementAttr)) {
1056 mlirAttr = rewriter.getFloatAttr(
1057 converter->convertType(floatAttr.getType()), floatAttr.getValue());
1058 }
else if (
auto boolAttr = mlir::dyn_cast<cir::BoolAttr>(elementAttr)) {
1059 mlirAttr = rewriter.getBoolAttr(boolAttr.getValue());
1061 llvm_unreachable(
"vector constant with an element that is neither an "
1062 "int, a float, or a bool");
1064 mlirValues.push_back(mlirAttr);
1067 return mlir::LLVM::ConstantOp::create(
1068 rewriter, parentLoc, llvmTy,
1069 mlir::DenseElementsAttr::get(mlir::cast<mlir::ShapedType>(llvmTy),
1074CIRAttrToValue::LoweredGlobalSymbol
1075CIRAttrToValue::getAddressOfSymbol(mlir::FlatSymbolRefAttr symbol) {
1076 cir::CIRDataLayout cirDataLayout(parentModule);
1077 const mlir::DataLayout &dataLayout = cirDataLayout.layout;
1078 mlir::Type sourceType;
1079 mlir::Type originalType;
1080 unsigned addrSpace = 0;
1081 llvm::StringRef symName;
1082 mlir::Operation *sourceSymbol =
1083 symbolTables.lookupSymbolIn(parentModule, symbol);
1084 if (
auto llvmSymbol = dyn_cast<mlir::LLVM::GlobalOp>(sourceSymbol)) {
1085 if (mlir::Type preType =
1086 preConversionTypes.lookup(llvmSymbol.getSymName())) {
1087 originalType = preType;
1090 sourceType = llvmSymbol.getType();
1092 symName = llvmSymbol.getSymName();
1093 addrSpace = llvmSymbol.getAddrSpace();
1094 }
else if (
auto cirSymbol = dyn_cast<cir::GlobalOp>(sourceSymbol)) {
1095 originalType = cirSymbol.getSymType();
1097 symName = cirSymbol.getSymName();
1098 if (
auto targetAS = mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
1099 cirSymbol.getAddrSpaceAttr()))
1100 addrSpace = targetAS.getValue();
1101 }
else if (
auto llvmFun = dyn_cast<mlir::LLVM::LLVMFuncOp>(sourceSymbol)) {
1102 if (mlir::Type preType = preConversionTypes.lookup(llvmFun.getSymName())) {
1103 originalType = preType;
1104 sourceType = converter->convertType(originalType);
1106 sourceType = llvmFun.getFunctionType();
1108 symName = llvmFun.getSymName();
1109 addrSpace = cirDataLayout.getProgramAddressSpace();
1110 }
else if (
auto fun = dyn_cast<cir::FuncOp>(sourceSymbol)) {
1111 originalType = fun.getFunctionType();
1112 sourceType = converter->convertType(originalType);
1113 symName = fun.getSymName();
1114 addrSpace = cirDataLayout.getProgramAddressSpace();
1115 }
else if (
auto alias = dyn_cast<mlir::LLVM::AliasOp>(sourceSymbol)) {
1116 if (mlir::Type preType = preConversionTypes.lookup(alias.getSymName())) {
1117 originalType = preType;
1118 if (mlir::isa<cir::FuncType>(preType))
1119 sourceType = converter->convertType(originalType);
1123 sourceType = alias.getType();
1125 symName = alias.getSymName();
1126 addrSpace = alias.getAddrSpace();
1128 llvm_unreachable(
"Unexpected GlobalOp type");
1131 mlir::Value addr = mlir::LLVM::AddressOfOp::create(
1132 rewriter, parentLoc,
1133 mlir::LLVM::LLVMPointerType::get(rewriter.getContext(), addrSpace),
1135 return {addr, sourceType, originalType, addrSpace};
1138mlir::Value CIRAttrToValue::castGlobalAddrToType(mlir::Value addr,
1139 mlir::Type attrType,
1140 mlir::Type sourceType,
1141 unsigned addrSpace) {
1147 if (mlir::isa<cir::IntType>(attrType)) {
1148 mlir::Type llvmDstTy = converter->convertType(attrType);
1149 return mlir::LLVM::PtrToIntOp::create(rewriter, parentLoc, llvmDstTy, addr);
1152 if (
auto ptrTy = mlir::dyn_cast<cir::PointerType>(attrType)) {
1153 auto llvmDstTy = converter->convertType<mlir::LLVM::LLVMPointerType>(ptrTy);
1155 if (llvmDstTy.getAddressSpace() != addrSpace)
1156 addr = mlir::LLVM::AddrSpaceCastOp::create(rewriter, parentLoc, llvmDstTy,
1159 mlir::DataLayout dataLayout(parentModule);
1160 mlir::Type llvmEltTy =
1164 if (llvmEltTy == sourceType)
1170 if (addr.getType() == llvmDstTy)
1173 return mlir::LLVM::BitcastOp::create(rewriter, parentLoc, llvmDstTy, addr);
1176 if (mlir::isa<cir::VPtrType>(attrType))
1179 llvm_unreachable(
"Expecting pointer or integer type");
1182mlir::Value CIRAttrToValue::visitCirAttr(cir::GlobalViewAttr globalAttr) {
1183 LoweredGlobalSymbol lowered = getAddressOfSymbol(globalAttr.getSymbol());
1184 mlir::Value addrOp = lowered.addr;
1185 mlir::Type sourceType = lowered.sourceType;
1187 if (globalAttr.getIndices()) {
1190 <<
" for symbol " << globalAttr.getSymbol();
1193 llvm::SmallVector<mlir::LLVM::GEPArg> indices;
1195 if (mlir::isa<mlir::LLVM::LLVMArrayType, mlir::LLVM::LLVMStructType>(
1197 indices.push_back(0);
1199 for (mlir::Attribute idx : globalAttr.getIndices()) {
1200 auto intAttr = mlir::cast<mlir::IntegerAttr>(idx);
1201 indices.push_back(intAttr.getValue().getSExtValue());
1203 mlir::Type resTy = addrOp.getType();
1204 mlir::Type eltTy = converter->convertType(sourceType);
1206 mlir::LLVM::GEPOp::create(rewriter, parentLoc, resTy, eltTy, addrOp,
1207 indices, mlir::LLVM::GEPNoWrapFlags::none);
1208 if (globalAttr.getAddressPoint()) {
1212 globalAttr.getIndices().getAsValueRange<mlir::IntegerAttr>();
1213 assert(llvm::range_size(indices) == 2 &&
1214 "address point takes a vtable index and a slot index");
1215 auto vtableTy = mlir::cast<mlir::LLVM::LLVMArrayType>(
1216 mlir::cast<mlir::LLVM::LLVMStructType>(eltTy)
1217 .getBody()[(*indices.begin()).getZExtValue()]);
1218 mlir::DataLayout layout(parentModule);
1219 int64_t slotSize = layout.getTypeSize(vtableTy.getElementType());
1220 int64_t offset = (*std::next(indices.begin())).getSExtValue() * slotSize;
1221 int64_t size = vtableTy.getNumElements() * slotSize;
1222 unsigned indexBits = *layout.getTypeIndexBitwidth(
1223 mlir::cast<mlir::LLVM::LLVMPointerType>(addrOp.getType()));
1224 gep.setNoWrapFlags(mlir::LLVM::GEPNoWrapFlags::inbounds);
1225 gep.setInrangeAttr(mlir::LLVM::ConstantRangeAttr::get(
1226 rewriter.getContext(), indexBits, -offset, size - offset));
1231 return castGlobalAddrToType(addrOp, globalAttr.getType(), sourceType,
1235mlir::Value CIRAttrToValue::visitCirAttr(cir::GlobalOffsetAttr globalAttr) {
1236 LoweredGlobalSymbol lowered = getAddressOfSymbol(globalAttr.getSymbol());
1237 mlir::Value addrOp = lowered.addr;
1241 mlir::Value offset = mlir::LLVM::ConstantOp::create(
1242 rewriter, parentLoc, rewriter.getI64Type(),
1243 rewriter.getI64IntegerAttr(globalAttr.getOffset()));
1244 addrOp = mlir::LLVM::GEPOp::create(
1245 rewriter, parentLoc, addrOp.getType(), rewriter.getI8Type(), addrOp,
1246 mlir::ValueRange{offset}, mlir::LLVM::GEPNoWrapFlags::none);
1248 return castGlobalAddrToType(addrOp, globalAttr.getType(), lowered.sourceType,
1253mlir::Value CIRAttrToValue::visitCirAttr(cir::TypeInfoAttr typeInfoAttr) {
1254 mlir::Type llvmTy = converter->convertType(typeInfoAttr.getType());
1255 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, parentLoc, llvmTy);
1257 for (
auto [idx, elt] : llvm::enumerate(typeInfoAttr.getData())) {
1258 mlir::Value init = visit(elt);
1261 result = mlir::LLVM::InsertValueOp::create(rewriter, parentLoc, result,
1269mlir::Value CIRAttrToValue::visitCirAttr(cir::UndefAttr undefAttr) {
1270 mlir::DataLayout layout(parentModule);
1271 return mlir::LLVM::UndefOp::create(
1272 rewriter, parentLoc,
1277mlir::Value CIRAttrToValue::visitCirAttr(cir::PoisonAttr poisonAttr) {
1278 mlir::DataLayout layout(parentModule);
1279 return mlir::LLVM::PoisonOp::create(
1280 rewriter, parentLoc,
1285mlir::Value CIRAttrToValue::visitCirAttr(cir::VTableAttr vtableArr) {
1286 mlir::Type llvmTy = converter->convertType(vtableArr.getType());
1287 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, parentLoc, llvmTy);
1289 for (
auto [idx, elt] : llvm::enumerate(vtableArr.getData())) {
1290 mlir::Value init = visit(elt);
1293 result = mlir::LLVM::InsertValueOp::create(rewriter, parentLoc, result,
1301mlir::Value CIRAttrToValue::visitCirAttr(cir::ZeroAttr attr) {
1302 mlir::DataLayout layout(parentModule);
1303 return mlir::LLVM::ZeroOp::create(
1304 rewriter, parentLoc,
1313 mlir::ConversionPatternRewriter &rewriter)
1314 : llvmType(type), dataLayout(dataLayout), rewriter(rewriter) {}
1317 return llvm::TypeSwitch<mlir::Attribute, mlir::Attribute>(
attr)
1318 .Case<cir::IntAttr, cir::FPAttr, cir::BoolAttr>(
1320 .
Default([&](
auto attrT) {
return mlir::Attribute(); });
1327 if (
auto intTy = mlir::dyn_cast<cir::IntType>(
attr.getType());
1328 intTy && intTy.isBitInt())
1331 return rewriter.getIntegerAttr(llvmType,
attr.getValue());
1335 return rewriter.getFloatAttr(llvmType,
attr.getValue());
1339 return rewriter.getBoolAttr(
attr.getValue());
1343 mlir::Type llvmType;
1344 const mlir::DataLayout &dataLayout;
1345 mlir::ConversionPatternRewriter &rewriter;
1353 :
public mlir::PassWrapper<ConvertCIRToLLVMPass,
1354 mlir::OperationPass<mlir::ModuleOp>> {
1356 registry.insert<mlir::BuiltinDialect, mlir::DLTIDialect,
1357 mlir::LLVM::LLVMDialect, mlir::func::FuncDialect>();
1375 return "Convert the prepared CIR dialect module to LLVM dialect";
1382 struct CollectedAnnotation {
1383 mlir::StringAttr symName;
1384 cir::AnnotationAttr annotation;
1386 CollectedAnnotation(mlir::StringAttr symName,
1387 cir::AnnotationAttr annotation, mlir::Location loc)
1388 : symName(symName), annotation(annotation), loc(loc) {}
1393mlir::LogicalResult CIRToLLVMIsFPClassOpLowering::matchAndRewrite(
1394 cir::IsFPClassOp op, OpAdaptor adaptor,
1395 mlir::ConversionPatternRewriter &rewriter)
const {
1396 mlir::Value src = adaptor.getSrc();
1397 cir::FPClassTest flags = adaptor.getFlags();
1398 mlir::IntegerType retTy = rewriter.getI1Type();
1400 rewriter.replaceOpWithNewOp<mlir::LLVM::IsFPClass>(
1401 op, retTy, src,
static_cast<uint32_t>(flags));
1402 return mlir::success();
1405mlir::LogicalResult CIRToLLVMSignBitOpLowering::matchAndRewrite(
1406 cir::SignBitOp op, OpAdaptor adaptor,
1407 mlir::ConversionPatternRewriter &rewriter)
const {
1410 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
1411 int width = layout.getTypeSizeInBits(op.getInput().getType());
1412 if (
auto longDoubleType =
1413 mlir::dyn_cast<cir::LongDoubleType>(op.getInput().getType())) {
1414 if (mlir::isa<cir::FP80Type>(longDoubleType.getUnderlying())) {
1422 mlir::Type intTy = mlir::IntegerType::get(rewriter.getContext(), width);
1423 auto bitcast = mlir::LLVM::BitcastOp::create(rewriter, op->getLoc(), intTy,
1424 adaptor.getInput());
1426 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op->getLoc(), intTy, 0);
1427 auto cmpResult = mlir::LLVM::ICmpOp::create(rewriter, op.getLoc(),
1428 mlir::LLVM::ICmpPredicate::slt,
1429 bitcast.getResult(), zero);
1430 rewriter.replaceOp(op, cmpResult);
1431 return mlir::success();
1434mlir::LogicalResult CIRToLLVMAssumeOpLowering::matchAndRewrite(
1435 cir::AssumeOp op, OpAdaptor adaptor,
1436 mlir::ConversionPatternRewriter &rewriter)
const {
1437 mlir::Value cond = adaptor.getPredicate();
1438 if (op.getBundleKind() == cir::AssumeBundleKind::None) {
1439 rewriter.replaceOpWithNewOp<mlir::LLVM::AssumeOp>(op, cond);
1440 return mlir::success();
1443 llvm::StringRef tag = cir::stringifyAssumeBundleKind(op.getBundleKind());
1444 rewriter.replaceOpWithNewOp<mlir::LLVM::AssumeOp>(op, cond, tag,
1445 adaptor.getBundleArgs());
1446 return mlir::success();
1449static mlir::LLVM::AtomicOrdering
1452 return mlir::LLVM::AtomicOrdering::not_atomic;
1453 switch (*memorder) {
1454 case cir::MemOrder::Relaxed:
1455 return mlir::LLVM::AtomicOrdering::monotonic;
1456 case cir::MemOrder::Consume:
1457 case cir::MemOrder::Acquire:
1458 return mlir::LLVM::AtomicOrdering::acquire;
1459 case cir::MemOrder::Release:
1460 return mlir::LLVM::AtomicOrdering::release;
1461 case cir::MemOrder::AcquireRelease:
1462 return mlir::LLVM::AtomicOrdering::acq_rel;
1463 case cir::MemOrder::SequentiallyConsistent:
1464 return mlir::LLVM::AtomicOrdering::seq_cst;
1466 llvm_unreachable(
"unknown memory order");
1470 switch (syncScope) {
1471 case cir::SyncScopeKind::SingleThread:
1472 case cir::SyncScopeKind::HIPSingleThread:
1473 return llvm::AtomicScope::Single;
1474 case cir::SyncScopeKind::Wavefront:
1475 case cir::SyncScopeKind::HIPWavefront:
1476 case cir::SyncScopeKind::OpenCLSubGroup:
1477 return llvm::AtomicScope::Wavefront;
1478 case cir::SyncScopeKind::Workgroup:
1479 case cir::SyncScopeKind::HIPWorkgroup:
1480 case cir::SyncScopeKind::OpenCLWorkGroup:
1481 return llvm::AtomicScope::Workgroup;
1482 case cir::SyncScopeKind::Cluster:
1483 case cir::SyncScopeKind::HIPCluster:
1484 return llvm::AtomicScope::Cluster;
1485 case cir::SyncScopeKind::Device:
1486 case cir::SyncScopeKind::HIPAgent:
1487 case cir::SyncScopeKind::OpenCLDevice:
1488 return llvm::AtomicScope::Device;
1489 case cir::SyncScopeKind::System:
1490 case cir::SyncScopeKind::HIPSystem:
1491 case cir::SyncScopeKind::OpenCLAllSVMDevices:
1492 return llvm::AtomicScope::System;
1494 llvm_unreachable(
"unknown sync scope");
1498 mlir::ModuleOp moduleOp) {
1500 if (
auto triple = moduleOp->getAttrOfType<mlir::StringAttr>(
1501 cir::CIRDialect::getTripleAttrName()))
1502 if (std::optional<llvm::StringRef> name = llvm::getAtomicScopeIRString(
1503 llvm::Triple(triple.getValue()), scope))
1505 return scope == llvm::AtomicScope::Single ?
"singlethread" :
"";
1508static std::optional<llvm::StringRef>
1510 mlir::ModuleOp moduleOp) {
1511 if (syncScope.has_value())
1513 return std::nullopt;
1517 mlir::Operation *llvmOp,
1518 mlir::Value llvmPtr) {
1519 llvm::StringRef name = cir::CIRDialect::getAMDGPUNoPrivateAddrSpaceAttrName();
1520 auto ptrTy = mlir::cast<mlir::LLVM::LLVMPointerType>(llvmPtr.getType());
1521 mlir::Attribute a = op->getAttr(name);
1522 if (a && ptrTy.getAddressSpace() == llvm::AMDGPUAS::FLAT_ADDRESS)
1523 llvmOp->setAttr(name, a);
1529 mlir::Operation *llvmOp) {
1530 for (llvm::StringRef marker :
1531 {cir::CIRDialect::getAMDGPUNoFineGrainedMemoryAttrName(),
1532 cir::CIRDialect::getAMDGPUNoRemoteMemoryAttrName(),
1533 cir::CIRDialect::getAMDGPUIgnoreDenormalModeAttrName()})
1534 if (mlir::Attribute a = op->getAttr(marker))
1535 llvmOp->setAttr(marker, a);
1538mlir::LogicalResult CIRToLLVMAtomicCmpXchgOpLowering::matchAndRewrite(
1539 cir::AtomicCmpXchgOp op, OpAdaptor adaptor,
1540 mlir::ConversionPatternRewriter &rewriter)
const {
1541 mlir::Value expected = adaptor.getExpected();
1542 mlir::Value desired = adaptor.getDesired();
1544 auto cmpxchg = mlir::LLVM::AtomicCmpXchgOp::create(
1545 rewriter, op.getLoc(), adaptor.getPtr(), expected, desired,
1549 op->getParentOfType<mlir::ModuleOp>()));
1551 cmpxchg.setAlignment(adaptor.getAlignment());
1552 cmpxchg.setWeak(adaptor.getWeak());
1553 cmpxchg.setVolatile_(adaptor.getIsVolatile());
1557 auto old = mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(),
1558 cmpxchg.getResult(), 0);
1559 auto cmp = mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(),
1560 cmpxchg.getResult(), 1);
1562 rewriter.replaceOp(op, {old, cmp});
1563 return mlir::success();
1566mlir::LogicalResult CIRToLLVMAtomicXchgOpLowering::matchAndRewrite(
1567 cir::AtomicXchgOp op, OpAdaptor adaptor,
1568 mlir::ConversionPatternRewriter &rewriter)
const {
1570 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(adaptor.getMemOrder());
1572 op.getSyncScope(), op->getParentOfType<mlir::ModuleOp>());
1575 auto xchg = mlir::LLVM::AtomicRMWOp::create(
1576 rewriter, op.getLoc(), mlir::LLVM::AtomicBinOp::xchg, adaptor.getPtr(),
1577 adaptor.getVal(), llvmOrder, llvmSyncScope, 0,
1578 op.getIsVolatile());
1581 rewriter.replaceOp(op, xchg);
1582 return mlir::success();
1585mlir::LogicalResult CIRToLLVMAtomicTestAndSetOpLowering::matchAndRewrite(
1586 cir::AtomicTestAndSetOp op, OpAdaptor adaptor,
1587 mlir::ConversionPatternRewriter &rewriter)
const {
1590 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
1592 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1593 rewriter.getI8Type(), 1);
1594 auto rmw = mlir::LLVM::AtomicRMWOp::create(
1595 rewriter, op.getLoc(), mlir::LLVM::AtomicBinOp::xchg, adaptor.getPtr(),
1596 one, llvmOrder, llvm::StringRef(),
1597 adaptor.getAlignment().value_or(0), op.getIsVolatile());
1599 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1600 rewriter.getI8Type(), 0);
1601 auto cmp = mlir::LLVM::ICmpOp::create(
1602 rewriter, op.getLoc(), mlir::LLVM::ICmpPredicate::ne, rmw, zero);
1604 rewriter.replaceOp(op, cmp);
1605 return mlir::success();
1608mlir::LogicalResult CIRToLLVMAtomicClearOpLowering::matchAndRewrite(
1609 cir::AtomicClearOp op, OpAdaptor adaptor,
1610 mlir::ConversionPatternRewriter &rewriter)
const {
1613 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
1614 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1615 rewriter.getI8Type(), 0);
1616 auto store = mlir::LLVM::StoreOp::create(
1617 rewriter, op.getLoc(), zero, adaptor.getPtr(),
1618 adaptor.getAlignment().value_or(0), op.getIsVolatile(),
1619 false,
false, llvmOrder);
1621 rewriter.replaceOp(op, store);
1622 return mlir::success();
1625mlir::LogicalResult CIRToLLVMAtomicFenceOpLowering::matchAndRewrite(
1626 cir::AtomicFenceOp op, OpAdaptor adaptor,
1627 mlir::ConversionPatternRewriter &rewriter)
const {
1628 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(adaptor.getOrdering());
1630 auto fence = mlir::LLVM::FenceOp::create(rewriter, op.getLoc(), llvmOrder);
1632 op->getParentOfType<mlir::ModuleOp>()));
1633 if (mlir::Attribute mmra =
1634 op->getAttr(mlir::LLVM::LLVMDialect::getMmraAttrName()))
1635 fence->setAttr(mlir::LLVM::LLVMDialect::getMmraAttrName(), mmra);
1637 rewriter.replaceOp(op, fence);
1639 return mlir::success();
1642static mlir::LLVM::AtomicBinOp
1645 case cir::AtomicFetchKind::Add:
1646 return isInt ? mlir::LLVM::AtomicBinOp::add : mlir::LLVM::AtomicBinOp::fadd;
1647 case cir::AtomicFetchKind::Sub:
1648 return isInt ? mlir::LLVM::AtomicBinOp::sub : mlir::LLVM::AtomicBinOp::fsub;
1649 case cir::AtomicFetchKind::And:
1650 return mlir::LLVM::AtomicBinOp::_and;
1651 case cir::AtomicFetchKind::Xor:
1652 return mlir::LLVM::AtomicBinOp::_xor;
1653 case cir::AtomicFetchKind::Or:
1654 return mlir::LLVM::AtomicBinOp::_or;
1655 case cir::AtomicFetchKind::Nand:
1656 return mlir::LLVM::AtomicBinOp::nand;
1657 case cir::AtomicFetchKind::Max: {
1659 return mlir::LLVM::AtomicBinOp::fmax;
1660 return isSignedInt ? mlir::LLVM::AtomicBinOp::max
1661 : mlir::LLVM::AtomicBinOp::umax;
1663 case cir::AtomicFetchKind::Min: {
1665 return mlir::LLVM::AtomicBinOp::fmin;
1666 return isSignedInt ? mlir::LLVM::AtomicBinOp::min
1667 : mlir::LLVM::AtomicBinOp::umin;
1669 case cir::AtomicFetchKind::UIncWrap:
1670 return mlir::LLVM::AtomicBinOp::uinc_wrap;
1671 case cir::AtomicFetchKind::UDecWrap:
1672 return mlir::LLVM::AtomicBinOp::udec_wrap;
1673 case cir::AtomicFetchKind::Maximum:
1674 return mlir::LLVM::AtomicBinOp::fmaximum;
1675 case cir::AtomicFetchKind::Minimum:
1676 return mlir::LLVM::AtomicBinOp::fminimum;
1677 case cir::AtomicFetchKind::MaximumNum:
1678 return mlir::LLVM::AtomicBinOp::fmaximumnum;
1679 case cir::AtomicFetchKind::MinimumNum:
1680 return mlir::LLVM::AtomicBinOp::fminimumnum;
1682 llvm_unreachable(
"Unknown atomic fetch opcode");
1688 case cir::AtomicFetchKind::Add:
1689 return isInt ? mlir::LLVM::AddOp::getOperationName()
1690 : mlir::LLVM::FAddOp::getOperationName();
1691 case cir::AtomicFetchKind::Sub:
1692 return isInt ? mlir::LLVM::SubOp::getOperationName()
1693 : mlir::LLVM::FSubOp::getOperationName();
1694 case cir::AtomicFetchKind::And:
1695 return mlir::LLVM::AndOp::getOperationName();
1696 case cir::AtomicFetchKind::Xor:
1697 return mlir::LLVM::XOrOp::getOperationName();
1698 case cir::AtomicFetchKind::Or:
1699 return mlir::LLVM::OrOp::getOperationName();
1700 case cir::AtomicFetchKind::Nand:
1702 return mlir::LLVM::AndOp::getOperationName();
1703 case cir::AtomicFetchKind::Max:
1704 case cir::AtomicFetchKind::Min:
1705 llvm_unreachable(
"handled in buildMinMaxPostOp");
1706 case cir::AtomicFetchKind::UIncWrap:
1707 case cir::AtomicFetchKind::UDecWrap:
1708 case cir::AtomicFetchKind::Maximum:
1709 case cir::AtomicFetchKind::Minimum:
1710 case cir::AtomicFetchKind::MaximumNum:
1711 case cir::AtomicFetchKind::MinimumNum:
1712 llvm_unreachable(
"uinc_wrap, udec_wrap, maximum, minimum, maximum_num, and "
1713 "minimum_num are always fetch_first");
1715 llvm_unreachable(
"Unknown atomic fetch opcode");
1718mlir::Value CIRToLLVMAtomicFetchOpLowering::buildPostOp(
1719 cir::AtomicFetchOp op, OpAdaptor adaptor,
1720 mlir::ConversionPatternRewriter &rewriter, mlir::Value rmwVal,
1725 .create(op.getLoc(),
1726 rewriter.getStringAttr(
1728 atomicOperands, atomicResTys, {})
1732mlir::Value CIRToLLVMAtomicFetchOpLowering::buildMinMaxPostOp(
1733 cir::AtomicFetchOp op, OpAdaptor adaptor,
1734 mlir::ConversionPatternRewriter &rewriter, mlir::Value rmwVal,
bool isInt,
1735 bool isSigned)
const {
1736 mlir::Location loc = op.getLoc();
1739 if (op.getBinop() == cir::AtomicFetchKind::Max)
1740 return mlir::LLVM::MaxNumOp::create(rewriter, loc, rmwVal,
1742 return mlir::LLVM::MinNumOp::create(rewriter, loc, rmwVal,
1746 mlir::LLVM::ICmpPredicate pred;
1747 if (op.getBinop() == cir::AtomicFetchKind::Max) {
1748 pred = isSigned ? mlir::LLVM::ICmpPredicate::sgt
1749 : mlir::LLVM::ICmpPredicate::ugt;
1751 pred = isSigned ? mlir::LLVM::ICmpPredicate::slt
1752 : mlir::LLVM::ICmpPredicate::ult;
1754 mlir::Value cmp = mlir::LLVM::ICmpOp::create(
1756 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(), pred), rmwVal,
1758 return mlir::LLVM::SelectOp::create(rewriter, loc, cmp, rmwVal,
1762mlir::LogicalResult CIRToLLVMAtomicFetchOpLowering::matchAndRewrite(
1763 cir::AtomicFetchOp op, OpAdaptor adaptor,
1764 mlir::ConversionPatternRewriter &rewriter)
const {
1766 bool isSignedInt =
false;
1767 if (
auto intTy = mlir::dyn_cast<cir::IntType>(op.getVal().getType())) {
1769 isSignedInt = intTy.isSigned();
1770 }
else if (cir::isFPOrVectorOfFPType(op.getVal().getType())) {
1773 return op.emitError() <<
"Unsupported type: " << op.getVal().getType();
1776 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
1778 op.getSyncScope(), op->getParentOfType<mlir::ModuleOp>());
1779 mlir::LLVM::AtomicBinOp llvmBinOp =
1781 auto rmwVal = mlir::LLVM::AtomicRMWOp::create(
1782 rewriter, op.getLoc(), llvmBinOp, adaptor.getPtr(), adaptor.getVal(),
1783 llvmOrder, llvmSyncScope, 0, op.getIsVolatile());
1791 if (op->hasAttr(cir::CIRDialect::getAMDGPURawAtomicAttrName())) {
1793 mlir::cast<mlir::LLVM::LLVMPointerType>(adaptor.getPtr().getType());
1794 if (ptrTy.getAddressSpace() != llvm::AMDGPUAS::LOCAL_ADDRESS) {
1795 mlir::UnitAttr unit = rewriter.getUnitAttr();
1796 rmwVal->setAttr(cir::CIRDialect::getAMDGPUNoFineGrainedMemoryAttrName(),
1799 if (llvmBinOp == mlir::LLVM::AtomicBinOp::fadd &&
1800 mlir::isa<cir::SingleType>(op.getVal().getType()))
1801 rmwVal->setAttr(cir::CIRDialect::getAMDGPUIgnoreDenormalModeAttrName(),
1806 mlir::Value result = rmwVal.getResult();
1807 if (!op.getFetchFirst()) {
1808 if (op.getBinop() == cir::AtomicFetchKind::Max ||
1809 op.getBinop() == cir::AtomicFetchKind::Min)
1810 result = buildMinMaxPostOp(op, adaptor, rewriter, rmwVal.getRes(), isInt,
1813 result = buildPostOp(op, adaptor, rewriter, rmwVal.getRes(), isInt);
1816 if (op.getBinop() == cir::AtomicFetchKind::Nand) {
1817 auto negOne = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1818 result.getType(), -1);
1819 result = mlir::LLVM::XOrOp::create(rewriter, op.getLoc(), result, negOne);
1823 rewriter.replaceOp(op, result);
1824 return mlir::success();
1827mlir::LogicalResult CIRToLLVMBitClrsbOpLowering::matchAndRewrite(
1828 cir::BitClrsbOp op, OpAdaptor adaptor,
1829 mlir::ConversionPatternRewriter &rewriter)
const {
1830 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1831 adaptor.getInput().getType(), 0);
1832 auto isNeg = mlir::LLVM::ICmpOp::create(
1833 rewriter, op.getLoc(),
1834 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(),
1835 mlir::LLVM::ICmpPredicate::slt),
1836 adaptor.getInput(), zero);
1838 auto negOne = mlir::LLVM::ConstantOp::create(
1839 rewriter, op.getLoc(), adaptor.getInput().getType(), -1);
1840 auto flipped = mlir::LLVM::XOrOp::create(rewriter, op.getLoc(),
1841 adaptor.getInput(), negOne);
1843 auto select = mlir::LLVM::SelectOp::create(rewriter, op.getLoc(), isNeg,
1844 flipped, adaptor.getInput());
1846 auto resTy = getTypeConverter()->convertType(op.getType());
1847 auto clz = mlir::LLVM::CountLeadingZerosOp::create(
1848 rewriter, op.getLoc(), resTy,
select,
false);
1850 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1851 auto res = mlir::LLVM::SubOp::create(rewriter, op.getLoc(),
clz, one,
1852 mlir::LLVM::IntegerOverflowFlags::nuw);
1853 rewriter.replaceOp(op, res);
1855 return mlir::LogicalResult::success();
1858mlir::LogicalResult CIRToLLVMBitClzOpLowering::matchAndRewrite(
1859 cir::BitClzOp op, OpAdaptor adaptor,
1860 mlir::ConversionPatternRewriter &rewriter)
const {
1861 auto resTy = getTypeConverter()->convertType(op.getType());
1862 auto llvmOp = mlir::LLVM::CountLeadingZerosOp::create(
1863 rewriter, op.getLoc(), resTy, adaptor.getInput(), op.getPoisonZero());
1864 rewriter.replaceOp(op, llvmOp);
1865 return mlir::LogicalResult::success();
1868mlir::LogicalResult CIRToLLVMBitCtzOpLowering::matchAndRewrite(
1869 cir::BitCtzOp op, OpAdaptor adaptor,
1870 mlir::ConversionPatternRewriter &rewriter)
const {
1871 auto resTy = getTypeConverter()->convertType(op.getType());
1872 auto llvmOp = mlir::LLVM::CountTrailingZerosOp::create(
1873 rewriter, op.getLoc(), resTy, adaptor.getInput(), op.getPoisonZero());
1874 rewriter.replaceOp(op, llvmOp);
1875 return mlir::LogicalResult::success();
1878mlir::LogicalResult CIRToLLVMBitFfsOpLowering::matchAndRewrite(
1879 cir::BitFfsOp op, OpAdaptor adaptor,
1880 mlir::ConversionPatternRewriter &rewriter)
const {
1881 auto resTy = getTypeConverter()->convertType(op.getType());
1882 auto ctz = mlir::LLVM::CountTrailingZerosOp::create(rewriter, op.getLoc(),
1883 resTy, adaptor.getInput(),
1886 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1887 auto ctzAddOne = mlir::LLVM::AddOp::create(rewriter, op.getLoc(),
ctz, one);
1889 auto zeroInputTy = mlir::LLVM::ConstantOp::create(
1890 rewriter, op.getLoc(), adaptor.getInput().getType(), 0);
1891 auto isZero = mlir::LLVM::ICmpOp::create(
1892 rewriter, op.getLoc(),
1893 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(),
1894 mlir::LLVM::ICmpPredicate::eq),
1895 adaptor.getInput(), zeroInputTy);
1897 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 0);
1898 auto res = mlir::LLVM::SelectOp::create(rewriter, op.getLoc(), isZero, zero,
1900 rewriter.replaceOp(op, res);
1902 return mlir::LogicalResult::success();
1905mlir::LogicalResult CIRToLLVMBitParityOpLowering::matchAndRewrite(
1906 cir::BitParityOp op, OpAdaptor adaptor,
1907 mlir::ConversionPatternRewriter &rewriter)
const {
1908 auto resTy = getTypeConverter()->convertType(op.getType());
1909 auto popcnt = mlir::LLVM::CtPopOp::create(rewriter, op.getLoc(), resTy,
1910 adaptor.getInput());
1912 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1914 mlir::LLVM::AndOp::create(rewriter, op.getLoc(), popcnt, one);
1915 rewriter.replaceOp(op, popcntMod2);
1917 return mlir::LogicalResult::success();
1920mlir::LogicalResult CIRToLLVMBitPopcountOpLowering::matchAndRewrite(
1921 cir::BitPopcountOp op, OpAdaptor adaptor,
1922 mlir::ConversionPatternRewriter &rewriter)
const {
1923 auto resTy = getTypeConverter()->convertType(op.getType());
1924 auto llvmOp = mlir::LLVM::CtPopOp::create(rewriter, op.getLoc(), resTy,
1925 adaptor.getInput());
1926 rewriter.replaceOp(op, llvmOp);
1927 return mlir::LogicalResult::success();
1930mlir::LogicalResult CIRToLLVMBrCondOpLowering::matchAndRewrite(
1931 cir::BrCondOp brOp, OpAdaptor adaptor,
1932 mlir::ConversionPatternRewriter &rewriter)
const {
1937 mlir::Value i1Condition = adaptor.getCond();
1939 rewriter.replaceOpWithNewOp<mlir::LLVM::CondBrOp>(
1940 brOp, i1Condition, brOp.getDestTrue(), adaptor.getDestOperandsTrue(),
1941 brOp.getDestFalse(), adaptor.getDestOperandsFalse());
1943 return mlir::success();
1946mlir::Type CIRToLLVMCastOpLowering::convertTy(mlir::Type ty)
const {
1947 return getTypeConverter()->convertType(ty);
1950mlir::LogicalResult CIRToLLVMCastOpLowering::matchAndRewrite(
1951 cir::CastOp castOp, OpAdaptor adaptor,
1952 mlir::ConversionPatternRewriter &rewriter)
const {
1957 if (!getTypeConverter()->convertType(castOp.getType()))
1960 switch (castOp.getKind()) {
1961 case cir::CastKind::array_to_ptrdecay: {
1962 const auto ptrTy = mlir::cast<cir::PointerType>(castOp.getType());
1963 mlir::Value sourceValue = adaptor.getSrc();
1964 mlir::Type targetType = convertTy(ptrTy);
1966 ptrTy.getPointee());
1969 llvm::SmallVector<mlir::LLVM::GEPArg> offset{0};
1970 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1971 castOp, targetType, elementTy, sourceValue, offset);
1974 case cir::CastKind::int_to_bool: {
1975 mlir::Value llvmSrcVal = adaptor.getSrc();
1979 mlir::Value zeroInt = mlir::LLVM::ConstantOp::create(
1980 rewriter, castOp.getLoc(), llvmSrcVal.getType(),
1981 rewriter.getZeroAttr(llvmSrcVal.getType()));
1982 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
1983 castOp, mlir::LLVM::ICmpPredicate::ne, llvmSrcVal, zeroInt);
1986 case cir::CastKind::integral: {
1987 mlir::Type srcType = castOp.getSrc().getType();
1988 mlir::Type dstType = castOp.getType();
1989 mlir::Value llvmSrcVal = adaptor.getSrc();
1990 mlir::Type llvmDstType = getTypeConverter()->convertType(dstType);
1991 cir::IntType srcIntType =
1992 mlir::cast<cir::IntType>(elementTypeIfVectorOrMatrix(srcType));
1993 cir::IntType dstIntType =
1994 mlir::cast<cir::IntType>(elementTypeIfVectorOrMatrix(dstType));
1995 rewriter.replaceOp(castOp,
getLLVMIntCast(rewriter, llvmSrcVal, llvmDstType,
1996 srcIntType.isUnsigned(),
1997 srcIntType.getWidth(),
1998 dstIntType.getWidth()));
2001 case cir::CastKind::floating: {
2002 mlir::Value llvmSrcVal = adaptor.getSrc();
2003 mlir::Type llvmDstTy = getTypeConverter()->convertType(castOp.getType());
2005 mlir::Type srcTy = elementTypeIfVectorOrMatrix(castOp.getSrc().getType());
2006 mlir::Type dstTy = elementTypeIfVectorOrMatrix(castOp.getType());
2008 if (!mlir::isa<cir::FPTypeInterface>(dstTy) ||
2009 !mlir::isa<cir::FPTypeInterface>(srcTy))
2010 return castOp.emitError() <<
"NYI cast from " << srcTy <<
" to " << dstTy;
2012 auto getFloatWidth = [](mlir::Type ty) ->
unsigned {
2013 return mlir::cast<cir::FPTypeInterface>(ty).getWidth();
2016 bool isTrunc = getFloatWidth(srcTy) > getFloatWidth(dstTy);
2017 if (cir::FenvAttr fenv = castOp.getFenvAttr()) {
2021 castOp, llvmSrcVal, fenv, llvmDstTy, rewriter,
2022 isTrunc ?
"fptrunc" :
"fpext", isTrunc);
2025 rewriter.replaceOpWithNewOp<mlir::LLVM::FPTruncOp>(castOp, llvmDstTy,
2028 rewriter.replaceOpWithNewOp<mlir::LLVM::FPExtOp>(castOp, llvmDstTy,
2030 return mlir::success();
2032 case cir::CastKind::int_to_ptr: {
2033 auto dstTy = mlir::cast<cir::PointerType>(castOp.getType());
2034 mlir::Value llvmSrcVal = adaptor.getSrc();
2035 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
2036 rewriter.replaceOpWithNewOp<mlir::LLVM::IntToPtrOp>(castOp, llvmDstTy,
2038 return mlir::success();
2040 case cir::CastKind::ptr_to_int: {
2041 auto dstTy = mlir::cast<cir::IntType>(castOp.getType());
2042 mlir::Value llvmSrcVal = adaptor.getSrc();
2043 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
2044 rewriter.replaceOpWithNewOp<mlir::LLVM::PtrToIntOp>(castOp, llvmDstTy,
2046 return mlir::success();
2048 case cir::CastKind::float_to_bool: {
2049 mlir::Value llvmSrcVal = adaptor.getSrc();
2050 auto kind = mlir::LLVM::FCmpPredicate::une;
2055 auto zeroFloat = mlir::LLVM::ConstantOp::create(
2056 rewriter, castOp.getLoc(), llvmSrcVal.getType(),
2057 rewriter.getZeroAttr(llvmSrcVal.getType()));
2060 rewriter.replaceOpWithNewOp<mlir::LLVM::FCmpOp>(castOp,
kind, llvmSrcVal,
2063 return mlir::success();
2065 case cir::CastKind::bool_to_int: {
2066 mlir::Type dstTy = castOp.getType();
2067 mlir::Value llvmSrcVal = adaptor.getSrc();
2068 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
2070 auto srcElemTy = mlir::cast<mlir::IntegerType>(
2071 elementTypeIfVectorOrMatrix(llvmSrcVal.getType()));
2073 mlir::cast<cir::IntType>(elementTypeIfVectorOrMatrix(dstTy));
2075 if (srcElemTy.getWidth() == dstElemTy.getWidth())
2076 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(castOp, llvmDstTy,
2079 rewriter.replaceOpWithNewOp<mlir::LLVM::ZExtOp>(castOp, llvmDstTy,
2081 return mlir::success();
2083 case cir::CastKind::bool_to_float: {
2084 mlir::Type dstTy = castOp.getType();
2085 mlir::Value llvmSrcVal = adaptor.getSrc();
2086 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
2087 rewriter.replaceOpWithNewOp<mlir::LLVM::UIToFPOp>(castOp, llvmDstTy,
2089 return mlir::success();
2091 case cir::CastKind::int_to_float: {
2092 mlir::Type dstTy = castOp.getType();
2093 mlir::Value llvmSrcVal = adaptor.getSrc();
2094 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
2095 bool isSigned = mlir::cast<cir::IntType>(
2096 elementTypeIfVectorOrMatrix(castOp.getSrc().getType()))
2098 if (cir::FenvAttr fenv = castOp.getFenvAttr()) {
2100 castOp, llvmSrcVal, fenv, llvmDstTy, rewriter,
2101 isSigned ?
"sitofp" :
"uitofp",
true);
2104 rewriter.replaceOpWithNewOp<mlir::LLVM::SIToFPOp>(castOp, llvmDstTy,
2107 rewriter.replaceOpWithNewOp<mlir::LLVM::UIToFPOp>(castOp, llvmDstTy,
2109 return mlir::success();
2111 case cir::CastKind::float_to_int: {
2112 mlir::Type dstTy = castOp.getType();
2113 mlir::Value llvmSrcVal = adaptor.getSrc();
2114 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
2116 mlir::cast<cir::IntType>(elementTypeIfVectorOrMatrix(castOp.getType()))
2118 if (cir::FenvAttr fenv = castOp.getFenvAttr()) {
2120 castOp, llvmSrcVal, fenv, llvmDstTy, rewriter,
2121 isSigned ?
"fptosi" :
"fptoui",
false);
2124 rewriter.replaceOpWithNewOp<mlir::LLVM::FPToSIOp>(castOp, llvmDstTy,
2127 rewriter.replaceOpWithNewOp<mlir::LLVM::FPToUIOp>(castOp, llvmDstTy,
2129 return mlir::success();
2131 case cir::CastKind::bitcast: {
2132 mlir::Type dstTy = castOp.getType();
2133 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
2138 mlir::Value llvmSrcVal = adaptor.getSrc();
2139 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(castOp, llvmDstTy,
2141 return mlir::success();
2143 case cir::CastKind::ptr_to_bool: {
2144 mlir::Value llvmSrcVal = adaptor.getSrc();
2145 mlir::Value zeroPtr = mlir::LLVM::ZeroOp::create(rewriter, castOp.getLoc(),
2146 llvmSrcVal.getType());
2147 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
2148 castOp, mlir::LLVM::ICmpPredicate::ne, llvmSrcVal, zeroPtr);
2151 case cir::CastKind::address_space: {
2152 mlir::Type dstTy = castOp.getType();
2153 mlir::Value llvmSrcVal = adaptor.getSrc();
2154 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
2155 rewriter.replaceOpWithNewOp<mlir::LLVM::AddrSpaceCastOp>(castOp, llvmDstTy,
2159 case cir::CastKind::member_ptr_to_bool:
2164 return castOp.emitError(
"Unhandled cast kind: ")
2165 << castOp.getKindAttrName();
2169 return mlir::success();
2172mlir::LogicalResult CIRToLLVMBuiltinIntCastOpLowering::matchAndRewrite(
2173 cir::BuiltinIntCastOp op, OpAdaptor adaptor,
2174 mlir::ConversionPatternRewriter &rewriter)
const {
2179 if (
auto cirSrc = mlir::dyn_cast<cir::IntType>(op.getSrc().getType()))
2181 else if (
auto cirDst = mlir::dyn_cast<cir::IntType>(op.getType()))
2184 mlir::Value llvmSrc = adaptor.getSrc();
2185 mlir::Type llvmDstTy = getTypeConverter()->convertType(op.getType());
2186 auto srcIntTy = mlir::cast<mlir::IntegerType>(llvmSrc.getType());
2187 auto dstIntTy = mlir::cast<mlir::IntegerType>(llvmDstTy);
2188 unsigned srcWidth = srcIntTy.getWidth();
2189 unsigned dstWidth = dstIntTy.getWidth();
2194 assert((srcWidth == dstWidth ||
2195 mlir::isa<mlir::IndexType>(op.getSrc().getType()) ||
2196 mlir::isa<mlir::IndexType>(op.getType())) &&
2197 "only index casts may change width during lowering");
2202 srcWidth, dstWidth));
2203 return mlir::success();
2207 mlir::ModuleOp mod, mlir::Value index,
2208 mlir::Type baseTy, cir::IntType strideTy) {
2209 mlir::Operation *indexOp = index.getDefiningOp();
2213 auto indexType = mlir::cast<mlir::IntegerType>(index.getType());
2214 mlir::DataLayout llvmLayout(mod);
2215 std::optional<uint64_t> layoutWidth = llvmLayout.getTypeIndexBitwidth(baseTy);
2218 if (!layoutWidth || *layoutWidth == indexType.getWidth())
2224 auto sub = dyn_cast<mlir::LLVM::SubOp>(indexOp);
2225 bool rewriteSub =
false;
2227 if (
auto lhsConst = dyn_cast_if_present<mlir::LLVM::ConstantOp>(
2228 sub.getLhs().getDefiningOp())) {
2229 auto lhsConstInt = mlir::dyn_cast<mlir::IntegerAttr>(lhsConst.getValue());
2230 if (lhsConstInt && lhsConstInt.getValue() == 0) {
2231 index = sub.getRhs();
2237 auto llvmDstType = rewriter.getIntegerType(*layoutWidth);
2238 bool isUnsigned = strideTy && strideTy.isUnsigned();
2240 indexType.getWidth(), *layoutWidth);
2243 index = mlir::LLVM::SubOp::create(
2244 rewriter, index.getLoc(),
2245 mlir::LLVM::ConstantOp::create(rewriter, index.getLoc(),
2246 index.getType(), 0),
2253mlir::LogicalResult CIRToLLVMPtrStrideOpLowering::matchAndRewrite(
2254 cir::PtrStrideOp ptrStrideOp, OpAdaptor adaptor,
2255 mlir::ConversionPatternRewriter &rewriter)
const {
2257 const mlir::TypeConverter *tc = getTypeConverter();
2258 const mlir::Type resultTy = tc->convertType(ptrStrideOp.getType());
2260 mlir::Type elementTy =
2267 if (mlir::isa<mlir::LLVM::LLVMVoidType>(elementTy) ||
2268 mlir::isa<mlir::LLVM::LLVMFunctionType>(elementTy))
2269 elementTy = mlir::IntegerType::get(elementTy.getContext(), 8,
2270 mlir::IntegerType::Signless);
2272 mlir::Value index = adaptor.getStride();
2274 rewriter, ptrStrideOp->getParentOfType<mlir::ModuleOp>(), index,
2275 adaptor.getBase().getType(),
2276 dyn_cast<cir::IntType>(ptrStrideOp.getOperand(1).getType()));
2278 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
2279 ptrStrideOp, resultTy, elementTy, adaptor.getBase(), index);
2280 return mlir::success();
2283mlir::LogicalResult CIRToLLVMGetElementOpLowering::matchAndRewrite(
2284 cir::GetElementOp op, OpAdaptor adaptor,
2285 mlir::ConversionPatternRewriter &rewriter)
const {
2287 mlir::dyn_cast<cir::ArrayType>(op.getBaseType().getPointee())) {
2288 const mlir::TypeConverter *converter = getTypeConverter();
2289 const mlir::Type llArrayTy = converter->convertType(arrayTy);
2292 const mlir::Type llResultTy = converter->convertType(op.getType());
2293 mlir::Type elementTy =
2298 if (mlir::isa<mlir::LLVM::LLVMVoidType>(elementTy) ||
2299 mlir::isa<mlir::LLVM::LLVMFunctionType>(elementTy))
2300 elementTy = rewriter.getIntegerType(8);
2302 mlir::Value index = adaptor.getIndex();
2305 adaptor.getBase().getType(),
2306 dyn_cast<cir::IntType>(op.getOperand(1).getType()));
2311 std::array<mlir::LLVM::GEPArg, 2> offset{0, index};
2312 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, llResultTy, llArrayTy,
2313 adaptor.getBase(), offset);
2314 return mlir::success();
2317 op.emitError() <<
"NYI: GetElementOp lowering to LLVM for non-array";
2318 return mlir::failure();
2321mlir::LogicalResult CIRToLLVMBaseClassAddrOpLowering::matchAndRewrite(
2322 cir::BaseClassAddrOp baseClassOp, OpAdaptor adaptor,
2323 mlir::ConversionPatternRewriter &rewriter)
const {
2324 const mlir::Type resultType =
2325 getTypeConverter()->convertType(baseClassOp.getType());
2328 mlir::Value derivedAddr = adaptor.getSrcAddr();
2329 llvm::SmallVector<mlir::LLVM::GEPArg, 1> offset = {
2330 adaptor.getOffset().getZExtValue()};
2331 mlir::Type byteType = mlir::IntegerType::get(resultType.getContext(), 8,
2332 mlir::IntegerType::Signless);
2333 if (adaptor.getOffset().getZExtValue() == 0) {
2334 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(baseClassOp, resultType,
2335 adaptor.getSrcAddr());
2336 return mlir::success();
2339 if (baseClassOp.getAssumeNotNull()) {
2340 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
2341 baseClassOp, resultType, byteType, derivedAddr, offset);
2343 auto loc = baseClassOp.getLoc();
2344 mlir::Value isNull = mlir::LLVM::ICmpOp::create(
2345 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, derivedAddr,
2346 mlir::LLVM::ZeroOp::create(rewriter, loc, derivedAddr.getType()));
2347 mlir::Value adjusted = mlir::LLVM::GEPOp::create(
2348 rewriter, loc, resultType, byteType, derivedAddr, offset);
2349 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(baseClassOp, isNull,
2350 derivedAddr, adjusted);
2352 return mlir::success();
2355mlir::LogicalResult CIRToLLVMDerivedClassAddrOpLowering::matchAndRewrite(
2356 cir::DerivedClassAddrOp derivedClassOp, OpAdaptor adaptor,
2357 mlir::ConversionPatternRewriter &rewriter)
const {
2358 const mlir::Type resultType =
2359 getTypeConverter()->convertType(derivedClassOp.getType());
2362 mlir::Value baseAddr = adaptor.getSrcAddr();
2365 int64_t offsetVal = -(adaptor.getOffset().getZExtValue());
2366 if (offsetVal == 0) {
2368 rewriter.replaceOp(derivedClassOp, baseAddr);
2369 return mlir::success();
2371 llvm::SmallVector<mlir::LLVM::GEPArg, 1> offset = {offsetVal};
2372 mlir::Type byteType = mlir::IntegerType::get(resultType.getContext(), 8,
2373 mlir::IntegerType::Signless);
2374 if (derivedClassOp.getAssumeNotNull()) {
2375 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
2376 derivedClassOp, resultType, byteType, baseAddr, offset,
2377 mlir::LLVM::GEPNoWrapFlags::inbounds);
2379 mlir::Location loc = derivedClassOp.getLoc();
2380 mlir::Value isNull = mlir::LLVM::ICmpOp::create(
2381 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, baseAddr,
2382 mlir::LLVM::ZeroOp::create(rewriter, loc, baseAddr.getType()));
2383 mlir::Value adjusted =
2384 mlir::LLVM::GEPOp::create(rewriter, loc, resultType, byteType, baseAddr,
2385 offset, mlir::LLVM::GEPNoWrapFlags::inbounds);
2386 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(derivedClassOp, isNull,
2387 baseAddr, adjusted);
2389 return mlir::success();
2392mlir::LogicalResult CIRToLLVMFMaxNumOpLowering::matchAndRewrite(
2393 cir::FMaxNumOp op, OpAdaptor adaptor,
2394 mlir::ConversionPatternRewriter &rewriter)
const {
2395 mlir::Type resTy = typeConverter->convertType(op.getType());
2396 if (cir::FenvAttr fenv = op.getFenvAttr())
2398 op, adaptor.getOperands(), fenv, resTy, rewriter,
"maxnum",
2399 false, mlir::LLVM::FastmathFlags::nsz);
2400 rewriter.replaceOpWithNewOp<mlir::LLVM::MaxNumOp>(
2401 op, resTy, adaptor.getLhs(), adaptor.getRhs(),
2402 mlir::LLVM::FastmathFlags::nsz);
2403 return mlir::success();
2406mlir::LogicalResult CIRToLLVMFMinNumOpLowering::matchAndRewrite(
2407 cir::FMinNumOp op, OpAdaptor adaptor,
2408 mlir::ConversionPatternRewriter &rewriter)
const {
2409 mlir::Type resTy = typeConverter->convertType(op.getType());
2410 if (cir::FenvAttr fenv = op.getFenvAttr())
2412 op, adaptor.getOperands(), fenv, resTy, rewriter,
"minnum",
2413 false, mlir::LLVM::FastmathFlags::nsz);
2414 rewriter.replaceOpWithNewOp<mlir::LLVM::MinNumOp>(
2415 op, resTy, adaptor.getLhs(), adaptor.getRhs(),
2416 mlir::LLVM::FastmathFlags::nsz);
2417 return mlir::success();
2420mlir::LogicalResult CIRToLLVMAllocaOpLowering::matchAndRewrite(
2421 cir::AllocaOp op, OpAdaptor adaptor,
2422 mlir::ConversionPatternRewriter &rewriter)
const {
2423 mlir::ModuleOp module = op->getParentOfType<mlir::ModuleOp>();
2424 mlir::Attribute langOpts =
2425 module->getAttr(cir::CIRDialect::getLoweringOptionsAttrName());
2426 auto loweringLangOps =
2427 dyn_cast_if_present<cir::LoweringOptionsAttr>(langOpts);
2429 bool isForHLSL = loweringLangOps ? loweringLangOps.getHlsl() :
false;
2430 if (isForHLSL && mlir::isa<cir::MatrixType>(op.getAllocaType()) &&
2431 mlir::isa<cir::BoolType>(
2432 cast<cir::MatrixType>(op.getAllocaType()).getElementType())) {
2433 return op.emitError()
2434 <<
"NYI: Builtin matrix type with bool element type for HLSL";
2439 ? adaptor.getDynAllocSize()
2440 : mlir::LLVM::ConstantOp::create(
2441 rewriter, op.getLoc(),
2442 typeConverter->convertType(rewriter.getI32Type()), 1);
2444 op.getAllocaType(), isForHLSL);
2446 return op.emitError()
2447 <<
"NYI: lowering alloca of a type with no memory representation";
2449 op.getType(), isForHLSL);
2456 rewriter.replaceOpWithNewOp<mlir::LLVM::AllocaOp>(op, resultTy, elementTy,
2457 size, op.getAlignment());
2459 return mlir::success();
2462mlir::LogicalResult CIRToLLVMRotateOpLowering::matchAndRewrite(
2463 cir::RotateOp op, OpAdaptor adaptor,
2464 mlir::ConversionPatternRewriter &rewriter)
const {
2467 mlir::Value input = adaptor.getInput();
2468 if (op.isRotateLeft())
2469 rewriter.replaceOpWithNewOp<mlir::LLVM::FshlOp>(op, input, input,
2470 adaptor.getAmount());
2472 rewriter.replaceOpWithNewOp<mlir::LLVM::FshrOp>(op, input, input,
2473 adaptor.getAmount());
2474 return mlir::LogicalResult::success();
2487 mlir::ArrayAttr argAttrs,
const mlir::TypeConverter &converter,
2488 const mlir::DataLayout &dataLayout, mlir::MLIRContext *ctx) {
2491 bool changed =
false;
2493 loweredArgAttrs.reserve(argAttrs.size());
2494 for (mlir::Attribute a : argAttrs) {
2495 auto dict = cast<mlir::DictionaryAttr>(a);
2497 for (mlir::NamedAttribute &entry : entries) {
2498 StringRef name = entry.getName().strref();
2499 if (name != mlir::LLVM::LLVMDialect::getByValAttrName() &&
2500 name != mlir::LLVM::LLVMDialect::getStructRetAttrName() &&
2501 name != mlir::LLVM::LLVMDialect::getByRefAttrName())
2503 auto typeAttr = dyn_cast<mlir::TypeAttr>(entry.getValue());
2506 mlir::Type lowered =
2509 return std::nullopt;
2510 if (lowered != typeAttr.getValue()) {
2511 entry.setValue(mlir::TypeAttr::get(lowered));
2515 loweredArgAttrs.push_back(mlir::DictionaryAttr::get(ctx, entries));
2517 return changed ? mlir::ArrayAttr::get(ctx, loweredArgAttrs) : argAttrs;
2527 cir::CIRCallOpInterface op,
const mlir::TypeConverter &converter,
2529 if (
auto argAttrs = mlir::dyn_cast_if_present<mlir::ArrayAttr>(
2530 op->getInherentAttr(CIRDialect::getArgAttrsAttrName())
2531 .value_or(mlir::Attribute{}))) {
2532 std::optional<mlir::ArrayAttr> lowered =
2535 return op->emitError() <<
"NYI: lowering a byval/sret/byref call "
2536 "argument whose pointee type has no "
2537 "memory representation";
2540 result.
resAttrs = mlir::dyn_cast_if_present<mlir::ArrayAttr>(
2541 op->getInherentAttr(CIRDialect::getResAttrsAttrName())
2542 .value_or(mlir::Attribute{}));
2544 for (mlir::NamedAttribute attr : op->getDiscardableAttrs()) {
2545 if (attr.getName() == CIRDialect::getNoUnwindAttrName() ||
2546 attr.getName() == CIRDialect::getNoReturnAttrName())
2551 return mlir::success();
2554template <
typename CallLikeOp>
2558 op.setArgAttrsAttr(attributes.
argAttrs);
2560 op.setResAttrsAttr(attributes.
resAttrs);
2562 if (op->getInherentAttr(attr.getName()).has_value())
2563 op->setInherentAttr(attr.getName(), attr.getValue());
2565 op->setDiscardableAttr(attr.getName(), attr.getValue());
2570 mlir::Operation *op, mlir::ValueRange callOperands,
2571 mlir::ConversionPatternRewriter &rewriter,
2572 const mlir::TypeConverter *converter,
const mlir::DataLayout &dataLayout,
2573 mlir::SymbolTableCollection &symbolTables,
2574 mlir::FlatSymbolRefAttr calleeAttr, mlir::Block *continueBlock =
nullptr,
2575 mlir::Block *landingPadBlock =
nullptr) {
2577 mlir::ValueTypeRange<mlir::ResultRange> cirResults = op->getResultTypes();
2578 auto call = cast<cir::CIRCallOpInterface>(op);
2580 if (converter->convertTypes(cirResults, llvmResults).failed())
2581 return mlir::failure();
2583 mlir::LLVM::MemoryEffectsAttr memoryEffects;
2584 bool noUnwind =
false;
2585 bool willReturn =
false;
2586 bool noReturn =
false;
2588 memoryEffects, noUnwind, willReturn, noReturn);
2593 return mlir::failure();
2595 mlir::LLVM::LLVMFunctionType llvmFnTy;
2602 mlir::Operation *callee =
2603 symbolTables.lookupNearestSymbolFrom(op, calleeAttr);
2604 if (
auto fn = mlir::dyn_cast<mlir::FunctionOpInterface>(callee)) {
2605 llvmFnTy = converter->convertType<mlir::LLVM::LLVMFunctionType>(
2606 fn.getFunctionType());
2607 assert(llvmFnTy &&
"Failed to convert function type");
2608 }
else if (
auto alias = mlir::cast<mlir::LLVM::AliasOp>(callee)) {
2616 auto symAttr = mlir::cast<mlir::FlatSymbolRefAttr>(calleeAttr);
2618 mlir::LLVM::AddressOfOp::create(
2619 rewriter, op->getLoc(),
2620 mlir::LLVM::LLVMPointerType::get(rewriter.getContext()), symAttr)
2622 adjustedCallOperands.push_back(addrOfAlias);
2625 llvm::append_range(adjustedCallOperands, callOperands);
2626 callOperands = adjustedCallOperands;
2630 llvmFnTy = mlir::cast<mlir::LLVM::LLVMFunctionType>(alias.getType());
2633 return op->emitError(
"Unexpected callee type!");
2636 assert(!op->getOperands().empty() &&
2637 "operands list must no be empty for the indirect call");
2638 auto calleeTy = op->getOperands().front().getType();
2639 auto calleePtrTy = cast<cir::PointerType>(calleeTy);
2640 auto calleeFuncTy = cast<cir::FuncType>(calleePtrTy.getPointee());
2641 llvm::append_range(adjustedCallOperands, callOperands);
2642 llvmFnTy = cast<mlir::LLVM::LLVMFunctionType>(
2643 converter->convertType(calleeFuncTy));
2650 const bool mustTail = op->hasAttr(CIRDialect::getMustTailAttrName());
2651 const std::optional<cir::InlineKind> inlineKind = call.getInlineKind();
2652 if (landingPadBlock) {
2654 auto newOp = rewriter.replaceOpWithNewOp<mlir::LLVM::InvokeOp>(
2655 op, llvmFnTy, calleeAttr, callOperands, continueBlock,
2656 mlir::ValueRange{}, landingPadBlock, mlir::ValueRange{});
2657 newOp.setCConv(cconv);
2660 auto newOp = rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(
2661 op, llvmFnTy, calleeAttr, callOperands);
2662 newOp.setCConv(cconv);
2665 newOp.setMemoryEffectsAttr(memoryEffects);
2666 newOp.setNoUnwind(noUnwind);
2667 newOp.setWillReturn(willReturn);
2668 newOp.setNoreturn(noReturn);
2670 newOp.setTailCallKind(mlir::LLVM::TailCallKind::MustTail);
2673 newOp.setNoInline(*inlineKind == cir::InlineKind::NoInline);
2674 newOp.setInlineHint(*inlineKind == cir::InlineKind::InlineHint);
2675 newOp.setAlwaysInline(*inlineKind == cir::InlineKind::AlwaysInline);
2679 return mlir::success();
2682mlir::LogicalResult CIRToLLVMCallOpLowering::matchAndRewrite(
2683 cir::CallOp op, OpAdaptor adaptor,
2684 mlir::ConversionPatternRewriter &rewriter)
const {
2686 getTypeConverter(), dataLayout, symbolTables,
2687 op.getCalleeAttr());
2690mlir::LogicalResult CIRToLLVMTryCallOpLowering::matchAndRewrite(
2691 cir::TryCallOp op, OpAdaptor adaptor,
2692 mlir::ConversionPatternRewriter &rewriter)
const {
2694 getTypeConverter(), dataLayout, symbolTables,
2695 op.getCalleeAttr(), op.getNormalDest(),
2696 op.getUnwindDest());
2699mlir::LogicalResult CIRToLLVMReturnAddrOpLowering::matchAndRewrite(
2700 cir::ReturnAddrOp op, OpAdaptor adaptor,
2701 mlir::ConversionPatternRewriter &rewriter)
const {
2702 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
2704 llvmPtrTy, adaptor.getOperands());
2705 return mlir::success();
2708mlir::LogicalResult CIRToLLVMFrameAddrOpLowering::matchAndRewrite(
2709 cir::FrameAddrOp op, OpAdaptor adaptor,
2710 mlir::ConversionPatternRewriter &rewriter)
const {
2711 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
2715 adaptor.getOperands());
2716 return mlir::success();
2719mlir::LogicalResult CIRToLLVMClearCacheOpLowering::matchAndRewrite(
2720 cir::ClearCacheOp op, OpAdaptor adaptor,
2721 mlir::ConversionPatternRewriter &rewriter)
const {
2722 mlir::Value begin = adaptor.getBegin();
2723 mlir::Value end = adaptor.getEnd();
2724 auto intrinNameAttr =
2725 mlir::StringAttr::get(op.getContext(),
"llvm.clear_cache");
2726 rewriter.replaceOpWithNewOp<mlir::LLVM::CallIntrinsicOp>(
2727 op, mlir::Type{}, intrinNameAttr, mlir::ValueRange{begin, end});
2729 return mlir::success();
2732mlir::LogicalResult CIRToLLVMAddrOfReturnAddrOpLowering::matchAndRewrite(
2733 cir::AddrOfReturnAddrOp op, OpAdaptor adaptor,
2734 mlir::ConversionPatternRewriter &rewriter)
const {
2735 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
2739 llvmPtrTy, adaptor.getOperands());
2740 return mlir::success();
2743mlir::LogicalResult CIRToLLVMAMDGPUFeaturePredicateOpLowering::matchAndRewrite(
2744 cir::AMDGPUFeaturePredicateOp op, OpAdaptor adaptor,
2745 mlir::ConversionPatternRewriter &rewriter)
const {
2746 mlir::Location loc = op.getLoc();
2747 mlir::MLIRContext *ctx = rewriter.getContext();
2748 mlir::Value specId =
2749 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI32Type(), -1);
2750 mlir::Value defaultValue =
2751 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI1Type(), 0);
2752 auto predicate = mlir::LLVM::MDNodeAttr::get(
2753 ctx, mlir::LLVM::MDStringAttr::get(ctx, op.getPredicateAttr()));
2755 mlir::LLVM::MetadataAsValueOp::create(rewriter, loc, predicate);
2757 rewriter, op,
"llvm.spv.named.boolean.spec.constant",
2758 getTypeConverter()->convertType(op.getType()),
2759 mlir::ValueRange{specId, defaultValue, md});
2760 return mlir::success();
2763mlir::LogicalResult CIRToLLVMLoadOpLowering::matchAndRewrite(
2764 cir::LoadOp op, OpAdaptor adaptor,
2765 mlir::ConversionPatternRewriter &rewriter)
const {
2766 const mlir::Type llvmTy =
2770 mlir::LLVM::AtomicOrdering ordering =
getLLVMMemOrder(op.getMemOrder());
2771 std::optional<size_t> opAlign = op.getAlignment();
2772 unsigned alignment = (unsigned)opAlign.value_or(
2778 op.getSyncScope(), op->getParentOfType<mlir::ModuleOp>());
2780 mlir::LLVM::LoadOp newLoad = mlir::LLVM::LoadOp::create(
2781 rewriter, op->getLoc(), llvmTy, adaptor.getAddr(), alignment,
2782 op.getIsVolatile(), op.getIsNontemporal(),
2783 op.getInvariant(),
false,
2784 false, ordering, llvmSyncScope.value_or(std::string()));
2785 if (mlir::Attribute domain = op->getAttr(
"cir.riscv_nontemporal_domain"))
2786 newLoad->setAttr(
"cir.riscv_nontemporal_domain", domain);
2789 mlir::Value result =
emitFromMemory(rewriter, *getTypeConverter(), dataLayout,
2790 op, newLoad.getResult());
2791 rewriter.replaceOp(op, result);
2793 return mlir::LogicalResult::success();
2797cir::direct::CIRToLLVMVecMaskedLoadOpLowering::matchAndRewrite(
2798 cir::VecMaskedLoadOp op, OpAdaptor adaptor,
2799 mlir::ConversionPatternRewriter &rewriter)
const {
2800 const mlir::Type llvmResTy =
2803 return op.emitError()
2804 <<
"NYI: lowering masked load of a type with no memory "
2807 std::optional<size_t> opAlign = op.getAlignment();
2808 unsigned alignment =
2809 (unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmResTy));
2811 auto newLoad = mlir::LLVM::MaskedLoadOp::create(
2812 rewriter, op.getLoc(), llvmResTy, adaptor.getAddr(), adaptor.getMask(),
2813 adaptor.getPassThru(), alignment);
2815 rewriter.replaceOp(op, newLoad.getResult());
2816 return mlir::success();
2819mlir::LogicalResult CIRToLLVMStoreOpLowering::matchAndRewrite(
2820 cir::StoreOp op, OpAdaptor adaptor,
2821 mlir::ConversionPatternRewriter &rewriter)
const {
2822 mlir::LLVM::AtomicOrdering memorder =
getLLVMMemOrder(op.getMemOrder());
2823 mlir::Type valueType = op.getValue().getType();
2824 const mlir::Type llvmTy =
2827 return op.emitError()
2828 <<
"NYI: lowering store of a type with no memory representation";
2829 std::optional<size_t> opAlign = op.getAlignment();
2830 unsigned alignment = (unsigned)opAlign.value_or(
2837 op.getValue().getType(), adaptor.getValue());
2841 op.getSyncScope(), op->getParentOfType<mlir::ModuleOp>());
2843 mlir::LLVM::StoreOp storeOp = mlir::LLVM::StoreOp::create(
2844 rewriter, op->getLoc(), value, adaptor.getAddr(), alignment,
2846 op.getIsNontemporal(),
false,
2847 memorder, llvmSyncScope.value_or(std::string()));
2848 if (mlir::Attribute domain = op->getAttr(
"cir.riscv_nontemporal_domain"))
2849 storeOp->setAttr(
"cir.riscv_nontemporal_domain", domain);
2850 rewriter.replaceOp(op, storeOp);
2852 return mlir::LogicalResult::success();
2856 while (
auto arrTy = mlir::dyn_cast<cir::ArrayType>(ty))
2857 ty = arrTy.getElementType();
2862 return mlir::isa<cir::PointerType, cir::IntType, cir::BoolType,
2866mlir::LogicalResult CIRToLLVMConstantOpLowering::matchAndRewrite(
2867 cir::ConstantOp op, OpAdaptor adaptor,
2868 mlir::ConversionPatternRewriter &rewriter)
const {
2869 mlir::Attribute attr = op.getValue();
2870 if (!getTypeConverter()->convertType(op.getType()))
2872 mlir::ModuleOp moduleOp = op->getParentOfType<mlir::ModuleOp>();
2874 if (mlir::isa<cir::PoisonAttr>(attr)) {
2875 rewriter.replaceOpWithNewOp<mlir::LLVM::PoisonOp>(
2876 op, getTypeConverter()->convertType(op.getType()));
2877 return mlir::success();
2880 if (mlir::isa<cir::UndefAttr>(attr)) {
2881 rewriter.replaceOpWithNewOp<mlir::LLVM::UndefOp>(
2882 op, getTypeConverter()->convertType(op.getType()));
2883 return mlir::success();
2886 if (mlir::isa<mlir::IntegerType>(op.getType())) {
2891 attr = op.getValue();
2892 }
else if (mlir::isa<cir::BoolType>(op.getType())) {
2893 int value = mlir::cast<cir::BoolAttr>(op.getValue()).getValue();
2894 attr = rewriter.getIntegerAttr(typeConverter->convertType(op.getType()),
2896 }
else if (mlir::isa<cir::IntType>(op.getType())) {
2899 if (mlir::isa<cir::GlobalViewAttr, cir::BlockAddrDiffAttr>(op.getValue())) {
2901 op->getLoc(), moduleOp, op.getValue(), rewriter, symbolTables,
2902 getTypeConverter(), preConversionTypes, &blockInfoAddr);
2903 rewriter.replaceOp(op, newOp);
2904 return mlir::success();
2907 attr = rewriter.getIntegerAttr(
2908 typeConverter->convertType(op.getType()),
2909 mlir::cast<cir::IntAttr>(op.getValue()).getValue());
2910 }
else if (mlir::isa<cir::FPTypeInterface>(op.getType())) {
2911 attr = rewriter.getFloatAttr(
2912 typeConverter->convertType(op.getType()),
2913 mlir::cast<cir::FPAttr>(op.getValue()).getValue());
2914 }
else if (mlir::isa<cir::PointerType>(op.getType())) {
2916 if (mlir::isa<cir::ConstPtrAttr>(op.getValue())) {
2917 if (mlir::cast<cir::ConstPtrAttr>(op.getValue()).isNullValue()) {
2918 rewriter.replaceOpWithNewOp<mlir::LLVM::ZeroOp>(
2919 op, typeConverter->convertType(op.getType()));
2920 return mlir::success();
2926 if (mlir::isa<cir::GlobalViewAttr, cir::GlobalOffsetAttr, cir::ConstPtrAttr,
2927 cir::BlockAddrInfoAttr>(op.getValue())) {
2929 op->getLoc(), moduleOp, op.getValue(), rewriter, symbolTables,
2930 getTypeConverter(), preConversionTypes, &blockInfoAddr);
2932 return mlir::failure();
2933 rewriter.replaceOp(op, newOp);
2934 return mlir::success();
2936 attr = op.getValue();
2937 }
else if (
const auto arrTy = mlir::dyn_cast<cir::ArrayType>(op.getType())) {
2940 const auto constArr = mlir::dyn_cast<cir::ConstArrayAttr>(value);
2941 if (!constArr && !isa<cir::ZeroAttr, cir::UndefAttr>(value))
2942 return op.emitError() <<
"array does not have a constant initializer";
2944 std::optional<mlir::Attribute> denseAttr;
2947 preConversionTypes))) {
2948 attr = denseAttr.value();
2950 const mlir::Value initVal =
2952 symbolTables, typeConverter, preConversionTypes);
2954 return mlir::failure();
2955 rewriter.replaceOp(op, initVal);
2956 return mlir::success();
2958 }
else if (
const auto recordAttr =
2959 mlir::dyn_cast<cir::ConstRecordAttr>(op.getValue())) {
2962 rewriter, symbolTables, typeConverter, preConversionTypes);
2964 return mlir::failure();
2965 rewriter.replaceOp(op, initVal);
2966 return mlir::success();
2967 }
else if (
const auto vecTy = mlir::dyn_cast<cir::VectorType>(op.getType())) {
2969 op->getLoc(), moduleOp, op.getValue(), rewriter, symbolTables,
2970 getTypeConverter(), preConversionTypes);
2972 return mlir::failure();
2973 rewriter.replaceOp(op, initVal);
2974 return mlir::success();
2975 }
else if (mlir::isa<cir::RecordType>(op.getType())) {
2976 if (mlir::isa<cir::ZeroAttr, cir::UndefAttr>(attr)) {
2977 mlir::Value initVal =
2979 symbolTables, typeConverter, preConversionTypes);
2981 return mlir::failure();
2982 rewriter.replaceOp(op, initVal);
2983 return mlir::success();
2985 return op.emitError() <<
"unsupported lowering for record constant type "
2987 }
else if (
auto complexTy = mlir::dyn_cast<cir::ComplexType>(op.getType())) {
2988 mlir::Type complexElemTy = complexTy.getElementType();
2989 mlir::Type complexElemLLVMTy = typeConverter->convertType(complexElemTy);
2991 if (
auto zeroInitAttr = mlir::dyn_cast<cir::ZeroAttr>(op.getValue())) {
2992 mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(complexElemLLVMTy);
2993 mlir::ArrayAttr array = rewriter.getArrayAttr({zeroAttr, zeroAttr});
2994 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
2995 op, getTypeConverter()->convertType(op.getType()), array);
2996 return mlir::success();
2999 if (mlir::isa<cir::UndefAttr>(op.getValue())) {
3000 rewriter.replaceOpWithNewOp<mlir::LLVM::UndefOp>(
3001 op, getTypeConverter()->convertType(op.getType()));
3002 return mlir::success();
3005 auto complexAttr = mlir::cast<cir::ConstComplexAttr>(op.getValue());
3007 mlir::Attribute components[2];
3008 if (mlir::isa<cir::IntType>(complexElemTy)) {
3009 components[0] = rewriter.getIntegerAttr(
3011 mlir::cast<cir::IntAttr>(complexAttr.getReal()).getValue());
3012 components[1] = rewriter.getIntegerAttr(
3014 mlir::cast<cir::IntAttr>(complexAttr.getImag()).getValue());
3016 components[0] = rewriter.getFloatAttr(
3018 mlir::cast<cir::FPAttr>(complexAttr.getReal()).getValue());
3019 components[1] = rewriter.getFloatAttr(
3021 mlir::cast<cir::FPAttr>(complexAttr.getImag()).getValue());
3024 attr = rewriter.getArrayAttr(components);
3026 return op.emitError() <<
"unsupported constant type " << op.getType();
3029 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
3030 op, getTypeConverter()->convertType(op.getType()),
attr);
3032 return mlir::success();
3036 mlir::DataLayout layout(op.getParentOfType<mlir::ModuleOp>());
3038 if (isa<cir::VoidType>(type))
3039 type = cir::IntType::get(type.getContext(), 8,
false);
3040 return layout.getTypeAllocSize(type);
3043mlir::LogicalResult CIRToLLVMPrefetchOpLowering::matchAndRewrite(
3044 cir::PrefetchOp op, OpAdaptor adaptor,
3045 mlir::ConversionPatternRewriter &rewriter)
const {
3046 rewriter.replaceOpWithNewOp<mlir::LLVM::Prefetch>(
3047 op, adaptor.getAddr(), adaptor.getIsWrite(), adaptor.getLocality(),
3049 return mlir::success();
3052mlir::LogicalResult CIRToLLVMPtrDiffOpLowering::matchAndRewrite(
3053 cir::PtrDiffOp op, OpAdaptor adaptor,
3054 mlir::ConversionPatternRewriter &rewriter)
const {
3055 mlir::Type pointeeType = op.getLhs().getType().getPointee();
3059 auto dstTy = mlir::cast<cir::IntType>(op.getType());
3060 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
3062 auto lhs = mlir::LLVM::PtrToIntOp::create(rewriter, op.getLoc(), llvmDstTy,
3064 auto rhs = mlir::LLVM::PtrToIntOp::create(rewriter, op.getLoc(), llvmDstTy,
3068 mlir::LLVM::SubOp::create(rewriter, op.getLoc(), llvmDstTy, lhs, rhs);
3074 mlir::Value resultVal = diff.getResult();
3075 if (typeSize != 1) {
3076 auto typeSizeVal = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
3077 llvmDstTy, typeSize);
3079 if (dstTy.isUnsigned()) {
3081 mlir::LLVM::UDivOp::create(rewriter, op.getLoc(), diff, typeSizeVal);
3082 uDiv.setIsExact(
true);
3083 resultVal = uDiv.getResult();
3086 mlir::LLVM::SDivOp::create(rewriter, op.getLoc(), diff, typeSizeVal);
3087 sDiv.setIsExact(
true);
3088 resultVal = sDiv.getResult();
3091 rewriter.replaceOp(op, resultVal);
3092 return mlir::success();
3095mlir::LogicalResult CIRToLLVMExpectOpLowering::matchAndRewrite(
3096 cir::ExpectOp op, OpAdaptor adaptor,
3097 mlir::ConversionPatternRewriter &rewriter)
const {
3101 std::optional<llvm::APFloat> prob = op.getProb();
3103 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpectWithProbabilityOp>(
3104 op, adaptor.getVal(), adaptor.getExpected(), prob.value());
3106 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpectOp>(op, adaptor.getVal(),
3107 adaptor.getExpected());
3108 return mlir::success();
3111mlir::LogicalResult CIRToLLVMAbsOpLowering::matchAndRewrite(
3112 cir::AbsOp op, OpAdaptor adaptor,
3113 mlir::ConversionPatternRewriter &rewriter)
const {
3114 mlir::Type resTy = typeConverter->convertType(op.getType());
3115 auto absOp = mlir::LLVM::AbsOp::create(rewriter, op.getLoc(), resTy,
3116 adaptor.getOperands()[0],
3117 adaptor.getMinIsPoison());
3118 rewriter.replaceOp(op, absOp);
3119 return mlir::success();
3124 return attr.getName() == CIRDialect::getNoReturnAttrName() ||
3125 attr.getName() == CIRDialect::getNoUnwindAttrName() ||
3126 attr.getName() == CIRDialect::getWillReturnAttrName() ||
3127 attr.getName() == CIRDialect::getStrictFPAttrName() ||
3128 attr.getName() == CIRDialect::getNoRecurseAttrName() ||
3129 attr.getName() == CIRDialect::getMustProgressAttrName() ||
3130 attr.getName() == CIRDialect::getNoBuiltinAttrName() ||
3131 attr.getName() == CIRDialect::getOptNoneAttrName() ||
3132 attr.getName() == CIRDialect::getNakedAttrName() ||
3133 attr.getName() == CIRDialect::getSYCLModuleIdAttrName() ||
3134 attr.getName() == CIRDialect::getDontCallErrorAttrName() ||
3135 attr.getName() == CIRDialect::getDontCallWarnAttrName();
3143mlir::LogicalResult CIRToLLVMFuncOpLowering::lowerFuncAttributes(
3144 cir::FuncOp func,
bool includeFunctionOnlyAttrs,
3146 OpenCLFunctionMetadataLowering openCLMetadataLowering(func.getContext());
3147 for (mlir::NamedAttribute attr : func->getDiscardableAttrs()) {
3150 if (openCLMetadataLowering.lower(attr, includeFunctionOnlyAttrs))
3153 result.push_back(attr);
3156 if (mlir::StringAttr visibility = func.getSymVisibilityAttr())
3157 result.emplace_back(func.getSymVisibilityAttrName(), visibility);
3159 if (includeFunctionOnlyAttrs) {
3160 if (mlir::ArrayAttr argAttrs = func.getArgAttrsAttr()) {
3162 argAttrs, *getTypeConverter(), dataLayout, getContext());
3164 return func.emitError() <<
"NYI: lowering a byval/sret/byref "
3165 "argument whose pointee type has no "
3166 "memory representation";
3167 result.emplace_back(func.getArgAttrsAttrName(), *lowered);
3169 if (mlir::ArrayAttr resAttrs = func.getResAttrsAttr())
3170 result.emplace_back(func.getResAttrsAttrName(), resAttrs);
3173 if (includeFunctionOnlyAttrs)
3174 openCLMetadataLowering.appendAttrs(result);
3176 return mlir::success();
3179mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewriteAlias(
3180 cir::FuncOp op, llvm::StringRef aliasee, mlir::Type ty, OpAdaptor adaptor,
3181 mlir::ConversionPatternRewriter &rewriter)
const {
3182 SmallVector<mlir::NamedAttribute, 4> attributes;
3183 if (mlir::failed(lowerFuncAttributes(op,
false,
3185 return mlir::failure();
3187 mlir::Location loc = op.getLoc();
3192 mlir::ModuleOp modOp = op->getParentOfType<mlir::ModuleOp>();
3193 symbolTables.getSymbolTable(modOp);
3194 auto aliasOp = mlir::LLVM::AliasOp::create(
3195 rewriter, loc, ty,
convertLinkage(op.getLinkage()), op.getName(),
3196 op.getDsoLocal(), mlir::LLVM::ThreadLocalMode::NotThreadLocal,
3198 aliasOp.setVisibility_(
3201 mlir::OpBuilder::InsertionGuard guard(rewriter);
3202 rewriter.createBlock(&aliasOp.getInitializerRegion());
3203 cir::CIRDataLayout cirDataLayout(
3204 aliasOp->getParentOfType<mlir::ModuleOp>());
3205 mlir::Type ptrTy = mlir::LLVM::LLVMPointerType::get(
3206 ty.getContext(), cirDataLayout.getProgramAddressSpace());
3208 mlir::LLVM::AddressOfOp::create(rewriter, loc, ptrTy, aliasee);
3209 mlir::LLVM::ReturnOp::create(rewriter, loc, addrOp);
3211 symbolTables.getSymbolTable(modOp).remove(op);
3212 rewriter.replaceOp(op, aliasOp);
3213 symbolTables.getSymbolTable(modOp).insert(aliasOp);
3215 return mlir::success();
3218mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewrite(
3219 cir::FuncOp op, OpAdaptor adaptor,
3220 mlir::ConversionPatternRewriter &rewriter)
const {
3222 cir::FuncType fnType = op.getFunctionType();
3223 bool isDsoLocal = op.getDsoLocal();
3224 mlir::TypeConverter::SignatureConversion signatureConversion(
3225 fnType.getNumInputs());
3227 for (
const auto &argType : llvm::enumerate(fnType.getInputs())) {
3228 mlir::Type convertedType = typeConverter->convertType(argType.value());
3231 signatureConversion.addInputs(argType.index(), convertedType);
3234 mlir::Type resultType =
3235 getTypeConverter()->convertType(fnType.getReturnType());
3240 mlir::Type llvmFnTy = mlir::LLVM::LLVMFunctionType::get(
3241 resultType, signatureConversion.getConvertedTypes(),
3245 if (std::optional<llvm::StringRef> aliasee = op.getAliasee())
3246 return matchAndRewriteAlias(op, *aliasee, llvmFnTy, adaptor, rewriter);
3250 mlir::Location loc = op.getLoc();
3251 if (mlir::FusedLoc fusedLoc = mlir::dyn_cast<mlir::FusedLoc>(loc))
3252 loc = fusedLoc.getLocations()[0];
3253 assert((mlir::isa<mlir::FileLineColLoc>(loc) ||
3254 mlir::isa<mlir::UnknownLoc>(loc)) &&
3255 "expected single location or unknown location here");
3259 SmallVector<mlir::NamedAttribute, 4> attributes;
3260 if (mlir::failed(lowerFuncAttributes(op,
true,
3262 return mlir::failure();
3267 if (failed(rewriter.convertRegionTypes(&op.getBody(), *typeConverter,
3268 &signatureConversion)))
3269 return mlir::failure();
3271 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
3275 mlir::ModuleOp modOp = op->getParentOfType<mlir::ModuleOp>();
3276 symbolTables.getSymbolTable(modOp);
3277 mlir::LLVM::LLVMFuncOp fn = mlir::LLVM::LLVMFuncOp::create(
3278 rewriter, loc, op.getName(), llvmFnTy, linkage, isDsoLocal, cconv,
3279 comdatAttr, attributes);
3283 if (cir::MemoryEffectsAttr effects = op.getMemoryEffectsAttr())
3287 if (op->hasAttr(CIRDialect::getNoUnwindAttrName()) ||
3288 op->hasAttr(CIRDialect::getNoThrowAttrName()))
3289 fn.setNoUnwind(
true);
3290 if (op->hasAttr(CIRDialect::getWillReturnAttrName()))
3291 fn.setWillReturn(
true);
3293 if (op->hasAttr(CIRDialect::getNoReturnAttrName()))
3294 fn.setNoreturn(
true);
3296 if (op->hasAttr(CIRDialect::getOptNoneAttrName()))
3297 fn.setOptimizeNone(
true);
3299 if (std::optional<cir::UnwindTableKind> uwtableKind = op.getUwtable())
3300 fn.setUwtableKindAttr(mlir::LLVM::UWTableKindAttr::get(
3303 if (std::optional<cir::FramePointerKind> framePointerKind =
3304 op.getFramePointer())
3305 fn.setFramePointerAttr(mlir::LLVM::FramePointerKindAttr::get(
3312 SmallVector<mlir::Attribute> passthrough;
3313 for (llvm::StringRef flagAttr :
3314 {CIRDialect::getStrictFPAttrName(), CIRDialect::getNoRecurseAttrName(),
3315 CIRDialect::getMustProgressAttrName(),
3316 CIRDialect::getNoBuiltinAttrName(), CIRDialect::getNakedAttrName()})
3317 if (op->hasAttr(flagAttr))
3318 passthrough.push_back(rewriter.getStringAttr(flagAttr));
3320 if (
auto moduleId = op->getAttrOfType<mlir::StringAttr>(
3321 CIRDialect::getSYCLModuleIdAttrName()))
3322 passthrough.push_back(rewriter.getArrayAttr(
3323 {rewriter.getStringAttr(CIRDialect::getSYCLModuleIdAttrName()),
3326 for (llvm::StringRef dontCallAttr : {CIRDialect::getDontCallErrorAttrName(),
3327 CIRDialect::getDontCallWarnAttrName()})
3328 if (
auto diagnostic = op->getAttrOfType<mlir::StringAttr>(dontCallAttr))
3329 passthrough.push_back(rewriter.getArrayAttr(
3330 {rewriter.getStringAttr(dontCallAttr), diagnostic}));
3332 if (!passthrough.empty())
3333 fn.setPassthroughAttr(rewriter.getArrayAttr(passthrough));
3335 if (std::optional<cir::InlineKind> inlineKind = op.getInlineKind()) {
3336 fn.setNoInline(*inlineKind == cir::InlineKind::NoInline);
3337 fn.setInlineHint(*inlineKind == cir::InlineKind::InlineHint);
3338 fn.setAlwaysInline(*inlineKind == cir::InlineKind::AlwaysInline);
3341 if (std::optional<llvm::StringRef> personality = op.getPersonality())
3342 fn.setPersonality(*personality);
3347 fn.setAlignment(op.getAlignment());
3350 symbolTables.getSymbolTable(modOp).remove(op);
3351 rewriter.inlineRegionBefore(op.getBody(), fn.getBody(), fn.end());
3353 rewriter.eraseOp(op);
3354 symbolTables.getSymbolTable(modOp).insert(fn);
3356 return mlir::LogicalResult::success();
3359mlir::LogicalResult CIRToLLVMGetGlobalOpLowering::matchAndRewrite(
3360 cir::GetGlobalOp op, OpAdaptor adaptor,
3361 mlir::ConversionPatternRewriter &rewriter)
const {
3364 if (op->getUses().empty()) {
3365 rewriter.eraseOp(op);
3366 return mlir::success();
3369 mlir::Type
type = getTypeConverter()->convertType(op.getType());
3372 mlir::Operation *newop = mlir::LLVM::AddressOfOp::create(
3373 rewriter, op.getLoc(), type, op.getName());
3377 newop = mlir::LLVM::ThreadlocalAddressOp::create(rewriter, op.getLoc(),
3378 type, newop->getResult(0));
3381 rewriter.replaceOp(op, newop);
3382 return mlir::success();
3385llvm::SmallVector<mlir::NamedAttribute>
3386CIRToLLVMGlobalOpLowering::lowerGlobalAttributes(
3387 cir::GlobalOp op, mlir::ConversionPatternRewriter &rewriter)
const {
3388 SmallVector<mlir::NamedAttribute> attributes;
3390 if (mlir::StringAttr sectionAttr = op.getSectionAttr())
3391 attributes.push_back(rewriter.getNamedAttr(
"section", sectionAttr));
3393 mlir::LLVM::VisibilityAttr visibility = mlir::LLVM::VisibilityAttr::get(
3396 attributes.push_back(rewriter.getNamedAttr(
"visibility_", visibility));
3398 if (op->getAttr(CUDAExternallyInitializedAttr::getMnemonic()))
3399 attributes.push_back(rewriter.getNamedAttr(
"externally_initialized",
3400 rewriter.getUnitAttr()));
3405static mlir::LLVM::ThreadLocalMode
3408#define CHECK_ENUM(CIR, LLVM_VAL) \
3409 static_assert(static_cast<unsigned>(TLSModel::CIR) == \
3410 static_cast<unsigned>(mlir::LLVM::ThreadLocalMode::LLVM_VAL))
3418 return mlir::LLVM::ThreadLocalMode::NotThreadLocal;
3420 return static_cast<mlir::LLVM::ThreadLocalMode
>(attr.getValue());
3429CIRToLLVMGlobalOpLowering::setupRegionInitializedLLVMGlobalOp(
3430 cir::GlobalOp op, mlir::ConversionPatternRewriter &rewriter)
const {
3431 mlir::Type llvmType =
3436 if (std::optional<mlir::Attribute> init = op.getInitialValue())
3446 const bool isConst = op.getConstant();
3447 unsigned addrSpace = 0;
3448 if (
auto targetAS = mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
3449 op.getAddrSpaceAttr()))
3450 addrSpace = targetAS.getValue();
3451 const bool isDsoLocal = op.getDsoLocal();
3452 mlir::LLVM::ThreadLocalMode threadLocalMode =
3454 const uint64_t alignment = op.getAlignment().value_or(0);
3455 const mlir::LLVM::Linkage linkage =
convertLinkage(op.getLinkage());
3456 const StringRef symbol = op.getSymName();
3459 lowerGlobalAttributes(op, rewriter);
3461 mlir::LLVM::GlobalOp newGlobalOp = mlir::LLVM::GlobalOp::create(
3462 rewriter, op.getLoc(), llvmType, isConst, linkage, symbol,
nullptr,
3463 alignment, addrSpace, isDsoLocal, threadLocalMode, mlir::SymbolRefAttr{},
3465 rewriter.createBlock(&newGlobalOp.getRegion());
3466 rewriter.setInsertionPointToEnd(newGlobalOp.getInitializerBlock());
3471CIRToLLVMGlobalOpLowering::matchAndRewriteRegionInitializedGlobal(
3472 cir::GlobalOp op, mlir::Attribute init,
3473 mlir::ConversionPatternRewriter &rewriter)
const {
3475 assert((isa<cir::BlockAddrDiffAttr, cir::BlockAddrInfoAttr,
3476 cir::ConstArrayAttr, cir::ConstRecordAttr, cir::ConstVectorAttr,
3477 cir::ConstPtrAttr, cir::ConstComplexAttr, cir::GlobalOffsetAttr,
3478 cir::GlobalViewAttr, cir::TypeInfoAttr, cir::UndefAttr,
3479 cir::PoisonAttr, cir::VTableAttr, cir::ZeroAttr>(init)));
3484 const mlir::Location loc = op.getLoc();
3485 mlir::ModuleOp moduleOp = op->getParentOfType<mlir::ModuleOp>();
3488 auto &symbolTable = symbolTables.getSymbolTable(moduleOp);
3491 rewriter.setInsertionPoint(op);
3492 mlir::LLVM::GlobalOp newGlobalOp =
3493 setupRegionInitializedLLVMGlobalOp(op, rewriter);
3495 return mlir::failure();
3501 CIRAttrToValue valueConverter(loc, moduleOp, rewriter, symbolTables,
3502 typeConverter, preConversionTypes,
3504 mlir::Value value = valueConverter.visit(init);
3511 rewriter.eraseOp(newGlobalOp);
3512 return mlir::failure();
3514 mlir::LLVM::ReturnOp::create(rewriter, loc, value);
3517 if (mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter))
3518 newGlobalOp.setComdatAttr(comdatAttr);
3519 symbolTable.remove(op);
3520 symbolTable.insert(newGlobalOp);
3521 rewriter.eraseOp(op);
3522 return mlir::success();
3528static mlir::LLVM::GlobalOp
3530 mlir::Type llvmType,
bool isConst, mlir::LLVM::Linkage linkage,
3531 llvm::StringRef symbol, mlir::Attribute init,
3532 uint64_t alignment,
unsigned addrSpace,
bool isDsoLocal,
3533 mlir::LLVM::ThreadLocalMode threadLocalMode,
3534 mlir::SymbolRefAttr comdatAttr,
3536 mlir::ConversionPatternRewriter &rewriter) {
3537 mlir::ModuleOp modOp = op->getParentOfType<mlir::ModuleOp>();
3538 symbolTables.getSymbolTable(modOp).remove(op);
3539 auto newGlobalOp = rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
3540 op, llvmType, isConst, linkage, symbol, init, alignment, addrSpace,
3541 isDsoLocal, threadLocalMode, comdatAttr, attributes);
3542 symbolTables.getSymbolTable(modOp).insert(newGlobalOp);
3546mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite(
3547 cir::GlobalOp op, OpAdaptor adaptor,
3548 mlir::ConversionPatternRewriter &rewriter)
const {
3549 if (mlir::isa_and_present<cir::LangAddressSpaceAttr>(op.getAddrSpaceAttr()))
3550 return op.emitError()
3551 <<
"cannot lower a global with a language address space";
3555 if (!op.getCtorRegion().empty() || !op.getDtorRegion().empty())
3556 return op.emitError() <<
"GlobalOp ctor and dtor regions should be removed "
3557 "in LoweringPrepare";
3559 std::optional<mlir::Attribute> init = op.getInitialValue();
3562 const mlir::Type cirSymType = op.getSymType();
3565 mlir::Type llvmType =
3568 return op.emitError()
3569 <<
"NYI: lowering global of a type with no memory representation";
3574 if (init.has_value())
3578 return mlir::failure();
3582 const bool isConst = op.getConstant();
3583 unsigned addrSpace = 0;
3584 if (
auto targetAS = mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
3585 op.getAddrSpaceAttr()))
3586 addrSpace = targetAS.getValue();
3587 const bool isDsoLocal = op.getDsoLocal();
3588 mlir::LLVM::ThreadLocalMode threadLocalMode =
3590 const uint64_t alignment = op.getAlignment().value_or(0);
3591 const mlir::LLVM::Linkage linkage =
convertLinkage(op.getLinkage());
3592 const StringRef symbol = op.getSymName();
3594 lowerGlobalAttributes(op, rewriter);
3597 if (std::optional<llvm::StringRef> aliasee = op.getAliasee()) {
3598 mlir::Location loc = op.getLoc();
3603 mlir::ModuleOp modOp = op->getParentOfType<mlir::ModuleOp>();
3604 symbolTables.getSymbolTable(modOp);
3606 mlir::LLVM::AliasOp::create(rewriter, loc, llvmType, linkage, symbol,
3607 isDsoLocal, threadLocalMode, attributes);
3609 mlir::OpBuilder::InsertionGuard guard(rewriter);
3610 rewriter.createBlock(&aliasOp.getInitializerRegion());
3612 mlir::LLVM::LLVMPointerType::get(getContext(), addrSpace);
3614 mlir::LLVM::AddressOfOp::create(rewriter, loc, ptrTy, *aliasee);
3615 mlir::LLVM::ReturnOp::create(rewriter, loc, addrOp);
3617 symbolTables.getSymbolTable(modOp).remove(op);
3618 rewriter.replaceOp(op, aliasOp);
3619 symbolTables.getSymbolTable(modOp).insert(aliasOp);
3620 return mlir::success();
3623 if (init.has_value()) {
3624 if (mlir::isa<cir::FPAttr, cir::IntAttr, cir::BoolAttr>(init.value())) {
3626 init = initRewriter.visit(init.value());
3631 if (!init.value()) {
3632 op.emitError() <<
"unsupported initializer '" << init.value() <<
"'";
3633 return mlir::failure();
3635 }
else if (
auto constArr =
3636 mlir::dyn_cast<cir::ConstArrayAttr>(init.value())) {
3644 mlir::ModuleOp modOp = op->getParentOfType<mlir::ModuleOp>();
3645 if (std::optional<mlir::Attribute> bulkInit =
3647 preConversionTypes, modOp)) {
3648 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
3650 bulkInit.value(), alignment, addrSpace, isDsoLocal,
3651 threadLocalMode, comdatAttr, attributes, rewriter);
3652 return mlir::success();
3655 return matchAndRewriteRegionInitializedGlobal(op, init.value(), rewriter);
3656 }
else if (
auto constRecord =
3657 mlir::dyn_cast<cir::ConstRecordAttr>(init.value())) {
3663 mlir::ModuleOp modOp = op->getParentOfType<mlir::ModuleOp>();
3664 if (std::optional<mlir::Attribute> bulkInit =
3666 preConversionTypes, modOp)) {
3667 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
3669 bulkInit.value(), alignment, addrSpace, isDsoLocal,
3670 threadLocalMode, comdatAttr, attributes, rewriter);
3671 return mlir::success();
3673 return matchAndRewriteRegionInitializedGlobal(op, init.value(), rewriter);
3674 }
else if (mlir::isa<cir::BlockAddrDiffAttr, cir::BlockAddrInfoAttr,
3675 cir::ConstVectorAttr, cir::ConstRecordAttr,
3676 cir::ConstPtrAttr, cir::ConstComplexAttr,
3677 cir::GlobalOffsetAttr, cir::GlobalViewAttr,
3678 cir::TypeInfoAttr, cir::UndefAttr, cir::PoisonAttr,
3679 cir::VTableAttr, cir::ZeroAttr>(init.value())) {
3683 return matchAndRewriteRegionInitializedGlobal(op, init.value(), rewriter);
3687 op.emitError() <<
"unsupported initializer '" << init.value() <<
"'";
3688 return mlir::failure();
3692 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
3694 init.value_or(mlir::Attribute()), alignment, addrSpace,
3695 isDsoLocal, threadLocalMode, comdatAttr, attributes,
3698 return mlir::success();
3701static mlir::SymbolRefAttr
3703 StringRef symName, mlir::LLVM::ComdatOp &comdatOp,
3704 mlir::SymbolTableCollection &symbolTables) {
3705 mlir::OpBuilder::InsertionGuard guard(builder);
3706 StringRef comdatName =
"__llvm_comdat";
3712 comdatOp = modOp.lookupSymbol<mlir::LLVM::ComdatOp>(comdatName);
3716 builder.setInsertionPointToStart(modOp.getBody());
3718 mlir::LLVM::ComdatOp::create(builder, modOp.getLoc(), comdatName);
3723 mlir::SymbolTable &selectors = symbolTables.getSymbolTable(comdatOp);
3724 if (
auto comdatSelector =
3725 selectors.lookup<mlir::LLVM::ComdatSelectorOp>(symName)) {
3726 return mlir::SymbolRefAttr::get(
3727 builder.getContext(), comdatName,
3728 mlir::FlatSymbolRefAttr::get(comdatSelector.getSymNameAttr()));
3731 builder.setInsertionPointToStart(&comdatOp.getBody().back());
3732 auto selectorOp = mlir::LLVM::ComdatSelectorOp::create(
3733 builder, comdatOp.getLoc(), symName, mlir::LLVM::comdat::Comdat::Any,
3735 selectors.insert(selectorOp);
3736 return mlir::SymbolRefAttr::get(
3737 builder.getContext(), comdatName,
3738 mlir::FlatSymbolRefAttr::get(selectorOp.getSymNameAttr()));
3742CIRToLLVMGlobalOpLowering::getComdatAttr(cir::GlobalOp &op,
3743 mlir::OpBuilder &builder)
const {
3744 std::optional<llvm::StringRef> comdat = op.getComdat();
3746 return mlir::SymbolRefAttr{};
3747 llvm::StringRef comdatKey = comdat->empty() ? op.getSymName() : *comdat;
3749 comdatKey, comdatOp, symbolTables);
3753CIRToLLVMFuncOpLowering::getComdatAttr(cir::FuncOp &op,
3754 mlir::OpBuilder &builder)
const {
3755 std::optional<llvm::StringRef> comdat = op.getComdat();
3757 return mlir::SymbolRefAttr{};
3758 llvm::StringRef comdatKey = comdat->empty() ? op.getSymName() : *comdat;
3760 comdatKey, comdatOp, symbolTables);
3763mlir::LogicalResult CIRToLLVMSwitchFlatOpLowering::matchAndRewrite(
3764 cir::SwitchFlatOp op, OpAdaptor adaptor,
3765 mlir::ConversionPatternRewriter &rewriter)
const {
3767 llvm::SmallVector<mlir::APInt, 8> caseValues;
3768 for (mlir::Attribute val : op.getCaseValues()) {
3769 auto intAttr = cast<cir::IntAttr>(val);
3770 caseValues.push_back(intAttr.getValue());
3773 llvm::SmallVector<mlir::Block *, 8> caseDestinations;
3775 for (mlir::Block *x : op.getCaseDestinations())
3776 caseDestinations.push_back(x);
3780 llvm::SmallVector<mlir::ValueRange> caseOperands = adaptor.getCaseOperands();
3783 rewriter.setInsertionPoint(op);
3784 rewriter.replaceOpWithNewOp<mlir::LLVM::SwitchOp>(
3785 op, adaptor.getCondition(), op.getDefaultDestination(),
3786 adaptor.getDefaultOperands(), caseValues, caseDestinations, caseOperands);
3787 return mlir::success();
3790static mlir::LLVM::IntegerOverflowFlags
nswFlag(
bool nsw) {
3791 return nsw ? mlir::LLVM::IntegerOverflowFlags::nsw
3792 : mlir::LLVM::IntegerOverflowFlags::none;
3795template <
typename CIROp,
typename LLVMIntOp>
3796static mlir::LogicalResult
3798 mlir::ConversionPatternRewriter &rewriter) {
3799 mlir::Type llvmType = adaptor.getInput().getType();
3800 mlir::Location loc = op.getLoc();
3802 auto maybeNSW =
nswFlag(op.getNoSignedWrap());
3803 mlir::LLVM::ConstantOp one;
3804 if (mlir::isa<cir::VectorType>(op.getType())) {
3805 mlir::ShapedType shapedTy = mlir::cast<mlir::ShapedType>(llvmType);
3806 mlir::APInt oneAP(shapedTy.getElementTypeBitWidth(), 1);
3807 auto oneVec = mlir::DenseElementsAttr::get(shapedTy, {oneAP});
3808 one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, oneVec);
3810 one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
3812 rewriter.replaceOpWithNewOp<LLVMIntOp>(op, adaptor.getInput(), one, maybeNSW);
3813 return mlir::success();
3816mlir::LogicalResult CIRToLLVMIncOpLowering::matchAndRewrite(
3817 cir::IncOp op, OpAdaptor adaptor,
3818 mlir::ConversionPatternRewriter &rewriter)
const {
3822mlir::LogicalResult CIRToLLVMDecOpLowering::matchAndRewrite(
3823 cir::DecOp op, OpAdaptor adaptor,
3824 mlir::ConversionPatternRewriter &rewriter)
const {
3828mlir::LogicalResult CIRToLLVMMinusOpLowering::matchAndRewrite(
3829 cir::MinusOp op, OpAdaptor adaptor,
3830 mlir::ConversionPatternRewriter &rewriter)
const {
3831 bool isVector = mlir::isa<cir::VectorType>(op.getType());
3832 mlir::Type llvmType = adaptor.getInput().getType();
3833 mlir::Location loc = op.getLoc();
3835 auto maybeNSW =
nswFlag(op.getNoSignedWrap());
3838 zero = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmType);
3840 zero = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 0);
3841 rewriter.replaceOpWithNewOp<mlir::LLVM::SubOp>(op, zero, adaptor.getInput(),
3843 return mlir::success();
3846mlir::LogicalResult CIRToLLVMNotOpLowering::matchAndRewrite(
3847 cir::NotOp op, OpAdaptor adaptor,
3848 mlir::ConversionPatternRewriter &rewriter)
const {
3849 mlir::Type elementType = elementTypeIfVectorOrMatrix(op.getType());
3850 bool isVector = mlir::isa<cir::VectorType>(op.getType());
3851 mlir::Type llvmType = adaptor.getInput().getType();
3852 mlir::Location loc = op.getLoc();
3854 if (mlir::isa<cir::IntType>(elementType)) {
3855 mlir::Value minusOne;
3857 const unsigned eltWidth =
3858 mlir::cast<cir::IntType>(elementType).getWidth();
3859 mlir::DenseElementsAttr denseVec =
3860 mlir::DenseElementsAttr::get(mlir::cast<mlir::ShapedType>(llvmType),
3861 {APInt::getAllOnes(eltWidth)});
3863 mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, denseVec);
3865 minusOne = mlir::LLVM::ConstantOp::create(
3866 rewriter, loc, llvmType,
3867 APInt::getAllOnes(cast<mlir::IntegerType>(llvmType).getWidth()));
3869 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getInput(),
3871 return mlir::success();
3874 if (mlir::isa<cir::BoolType>(elementType)) {
3877 mlir::DenseElementsAttr denseVec = mlir::DenseElementsAttr::get(
3878 mlir::cast<mlir::ShapedType>(llvmType), {
APInt(1, 1)});
3879 one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, denseVec);
3881 one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
3883 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getInput(), one);
3884 return mlir::success();
3887 return op.emitError() <<
"Unsupported type for bitwise NOT";
3892 return mlir::isa<cir::IntType>(type)
3893 ? mlir::cast<cir::IntType>(type).isUnsigned()
3894 : mlir::cast<mlir::IntegerType>(type).isUnsigned();
3901template <
typename BinOp>
3903 if (op.getNoUnsignedWrap())
3904 return mlir::LLVM::IntegerOverflowFlags::nuw;
3905 if (op.getNoSignedWrap())
3906 return mlir::LLVM::IntegerOverflowFlags::nsw;
3907 return mlir::LLVM::IntegerOverflowFlags::none;
3912template <
typename UIntSatOp,
typename SIntSatOp,
typename IntOp,
3914static mlir::LogicalResult
3916 mlir::ConversionPatternRewriter &rewriter) {
3917 const mlir::Type eltType = elementTypeIfVectorOrMatrix(op.getRhs().getType());
3918 assert(cir::isIntOrBoolType(eltType) &&
3919 "saturatable arith op expects integer operand types");
3920 if (op.getSaturated()) {
3922 rewriter.replaceOpWithNewOp<UIntSatOp>(op, lhs, rhs);
3924 rewriter.replaceOpWithNewOp<SIntSatOp>(op, lhs, rhs);
3925 return mlir::success();
3927 rewriter.replaceOpWithNewOp<IntOp>(op, lhs, rhs,
intOverflowFlag(op));
3928 return mlir::success();
3931mlir::LogicalResult CIRToLLVMAddOpLowering::matchAndRewrite(
3932 cir::AddOp op, OpAdaptor adaptor,
3933 mlir::ConversionPatternRewriter &rewriter)
const {
3935 mlir::LLVM::AddOp>(op, adaptor.getLhs(),
3936 adaptor.getRhs(), rewriter);
3939mlir::LogicalResult CIRToLLVMSubOpLowering::matchAndRewrite(
3940 cir::SubOp op, OpAdaptor adaptor,
3941 mlir::ConversionPatternRewriter &rewriter)
const {
3943 mlir::LLVM::SubOp>(op, adaptor.getLhs(),
3944 adaptor.getRhs(), rewriter);
3947mlir::LogicalResult CIRToLLVMMulOpLowering::matchAndRewrite(
3948 cir::MulOp op, OpAdaptor adaptor,
3949 mlir::ConversionPatternRewriter &rewriter)
const {
3950 assert(cir::isIntOrBoolType(
3951 elementTypeIfVectorOrMatrix(op.getRhs().getType())) &&
3952 "cir.mul expects integer operand types");
3953 rewriter.replaceOpWithNewOp<mlir::LLVM::MulOp>(
3955 return mlir::success();
3959template <
typename UIntOp,
typename SIntOp,
typename CIROp>
3960static mlir::LogicalResult
3962 mlir::ConversionPatternRewriter &rewriter) {
3963 const mlir::Type eltType = elementTypeIfVectorOrMatrix(op.getRhs().getType());
3964 assert(cir::isIntOrBoolType(eltType) &&
3965 "integer binary op expects integer operand types");
3967 rewriter.replaceOpWithNewOp<UIntOp>(op, lhs, rhs);
3969 rewriter.replaceOpWithNewOp<SIntOp>(op, lhs, rhs);
3970 return mlir::success();
3973mlir::LogicalResult CIRToLLVMDivOpLowering::matchAndRewrite(
3974 cir::DivOp op, OpAdaptor adaptor,
3975 mlir::ConversionPatternRewriter &rewriter)
const {
3977 op, adaptor.getLhs(), adaptor.getRhs(), rewriter);
3980mlir::LogicalResult CIRToLLVMRemOpLowering::matchAndRewrite(
3981 cir::RemOp op, OpAdaptor adaptor,
3982 mlir::ConversionPatternRewriter &rewriter)
const {
3984 op, adaptor.getLhs(), adaptor.getRhs(), rewriter);
3987template <
typename CIROp,
typename UIntOp,
typename SIntOp>
3988static mlir::LogicalResult
3990 mlir::ConversionPatternRewriter &rewriter) {
3991 const mlir::Value lhs = adaptor.getLhs();
3992 const mlir::Value rhs = adaptor.getRhs();
3994 rewriter.replaceOpWithNewOp<UIntOp>(op, lhs, rhs);
3996 rewriter.replaceOpWithNewOp<SIntOp>(op, lhs, rhs);
3997 return mlir::success();
4000mlir::LogicalResult CIRToLLVMMaxOpLowering::matchAndRewrite(
4001 cir::MaxOp op, OpAdaptor adaptor,
4002 mlir::ConversionPatternRewriter &rewriter)
const {
4004 op, adaptor, rewriter);
4007mlir::LogicalResult CIRToLLVMMinOpLowering::matchAndRewrite(
4008 cir::MinOp op, OpAdaptor adaptor,
4009 mlir::ConversionPatternRewriter &rewriter)
const {
4011 op, adaptor, rewriter);
4015static mlir::LLVM::ICmpPredicate
4017 using CIR = cir::CmpOpKind;
4018 using LLVMICmp = mlir::LLVM::ICmpPredicate;
4021 return LLVMICmp::eq;
4023 return LLVMICmp::ne;
4025 return (isSigned ? LLVMICmp::slt : LLVMICmp::ult);
4027 return (isSigned ? LLVMICmp::sle : LLVMICmp::ule);
4029 return (isSigned ? LLVMICmp::sgt : LLVMICmp::ugt);
4031 return (isSigned ? LLVMICmp::sge : LLVMICmp::uge);
4034 llvm_unreachable(
"FP-only comparison used with integer type");
4036 llvm_unreachable(
"Unknown CmpOpKind");
4041static mlir::LLVM::FCmpPredicate
4043 using CIR = cir::CmpOpKind;
4044 using LLVMFCmp = mlir::LLVM::FCmpPredicate;
4047 return LLVMFCmp::oeq;
4049 return LLVMFCmp::une;
4051 return LLVMFCmp::olt;
4053 return LLVMFCmp::ole;
4055 return LLVMFCmp::ogt;
4057 return LLVMFCmp::oge;
4059 return LLVMFCmp::one;
4061 return LLVMFCmp::uno;
4063 llvm_unreachable(
"Unknown CmpOpKind");
4066static llvm::StringRef
4068 using CIR = cir::CmpOpKind;
4087 llvm_unreachable(
"Unknown CmpOpKind");
4091 using CIR = cir::CmpOpKind;
4104 llvm_unreachable(
"Unknown CmpOpKind");
4107static mlir::LLVM::CallIntrinsicOp
4109 mlir::Location loc, mlir::Value lhs, mlir::Value rhs,
4110 cir::CmpOpKind
kind, cir::FenvAttr fenv,
4111 mlir::Type llvmResTy) {
4119 ?
"llvm.experimental.constrained.fcmps"
4120 :
"llvm.experimental.constrained.fcmp";
4125mlir::LogicalResult CIRToLLVMCmpOpLowering::matchAndRewrite(
4126 cir::CmpOp cmpOp, OpAdaptor adaptor,
4127 mlir::ConversionPatternRewriter &rewriter)
const {
4128 mlir::Type type = cmpOp.getLhs().getType();
4130 if (mlir::isa<cir::IntType, mlir::IntegerType>(type)) {
4131 bool isSigned = mlir::isa<cir::IntType>(type)
4132 ? mlir::cast<cir::IntType>(type).isSigned()
4133 : mlir::cast<mlir::IntegerType>(type).isSigned();
4134 mlir::LLVM::ICmpPredicate
kind =
4136 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
4137 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
4138 return mlir::success();
4141 if (mlir::isa<cir::BoolType, cir::PointerType, cir::VPtrType>(type)) {
4145 mlir::LLVM::ICmpPredicate
kind =
4147 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
4148 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
4149 return mlir::success();
4152 if (mlir::isa<cir::FPTypeInterface>(type)) {
4153 mlir::Type llvmResTy = getTypeConverter()->convertType(cmpOp.getType());
4154 if (cir::FenvAttr fenv = cmpOp.getFenvAttr()) {
4156 rewriter, cmpOp.getLoc(), adaptor.getLhs(), adaptor.getRhs(),
4157 cmpOp.getKind(), fenv, llvmResTy);
4158 rewriter.replaceOp(cmpOp, call.getResult(0));
4159 return mlir::success();
4161 mlir::LLVM::FCmpPredicate
kind =
4163 rewriter.replaceOpWithNewOp<mlir::LLVM::FCmpOp>(
4164 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
4165 return mlir::success();
4168 if (mlir::isa<cir::ComplexType>(type)) {
4169 mlir::Value lhs = adaptor.getLhs();
4170 mlir::Value rhs = adaptor.getRhs();
4171 mlir::Location loc = cmpOp.getLoc();
4173 auto complexType = mlir::cast<cir::ComplexType>(cmpOp.getLhs().getType());
4174 mlir::Type complexElemTy =
4175 getTypeConverter()->convertType(
complexType.getElementType());
4177 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
4178 rewriter, loc, complexElemTy, lhs, ArrayRef(
int64_t{0}));
4179 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
4180 rewriter, loc, complexElemTy, lhs, ArrayRef(
int64_t{1}));
4181 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
4182 rewriter, loc, complexElemTy, rhs, ArrayRef(
int64_t{0}));
4183 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
4184 rewriter, loc, complexElemTy, rhs, ArrayRef(
int64_t{1}));
4186 if (cmpOp.getKind() == cir::CmpOpKind::eq) {
4187 if (complexElemTy.isInteger()) {
4188 auto realCmp = mlir::LLVM::ICmpOp::create(
4189 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, lhsReal, rhsReal);
4190 auto imagCmp = mlir::LLVM::ICmpOp::create(
4191 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, lhsImag, rhsImag);
4192 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, imagCmp);
4193 return mlir::success();
4196 auto realCmp = mlir::LLVM::FCmpOp::create(
4197 rewriter, loc, mlir::LLVM::FCmpPredicate::oeq, lhsReal, rhsReal);
4198 auto imagCmp = mlir::LLVM::FCmpOp::create(
4199 rewriter, loc, mlir::LLVM::FCmpPredicate::oeq, lhsImag, rhsImag);
4200 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, imagCmp);
4201 return mlir::success();
4204 if (cmpOp.getKind() == cir::CmpOpKind::ne) {
4205 if (complexElemTy.isInteger()) {
4206 auto realCmp = mlir::LLVM::ICmpOp::create(
4207 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, lhsReal, rhsReal);
4208 auto imagCmp = mlir::LLVM::ICmpOp::create(
4209 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, lhsImag, rhsImag);
4210 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp);
4211 return mlir::success();
4214 auto realCmp = mlir::LLVM::FCmpOp::create(
4215 rewriter, loc, mlir::LLVM::FCmpPredicate::une, lhsReal, rhsReal);
4216 auto imagCmp = mlir::LLVM::FCmpOp::create(
4217 rewriter, loc, mlir::LLVM::FCmpPredicate::une, lhsImag, rhsImag);
4218 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp);
4219 return mlir::success();
4223 return cmpOp.emitError() <<
"unsupported type for CmpOp: " <<
type;
4229template <
typename OpTy>
4230static mlir::LogicalResult
4232 mlir::ConversionPatternRewriter &rewriter,
4233 const mlir::TypeConverter *typeConverter,
4234 llvm::StringRef opStr) {
4235 mlir::Location loc = op.getLoc();
4236 cir::IntType operandTy = op.getLhs().getType();
4239 mlir::Type resultTy = op.getResult().getType();
4240 auto resultIntTy = mlir::dyn_cast<cir::IntType>(resultTy);
4241 unsigned resultWidth = resultIntTy ? resultIntTy.getWidth() : 1;
4242 bool resultSigned = resultIntTy && resultIntTy.getIsSigned();
4244 bool sign = operandTy.getIsSigned() || resultSigned;
4246 std::max(operandTy.getWidth() + (
sign && operandTy.isUnsigned()),
4247 resultWidth + (
sign && !resultSigned));
4249 mlir::IntegerType encompassedLLVMTy = rewriter.getIntegerType(width);
4251 mlir::Value lhs = adaptor.getLhs();
4252 mlir::Value rhs = adaptor.getRhs();
4253 if (operandTy.getWidth() < width) {
4254 if (operandTy.isSigned()) {
4255 lhs = mlir::LLVM::SExtOp::create(rewriter, loc, encompassedLLVMTy, lhs);
4256 rhs = mlir::LLVM::SExtOp::create(rewriter, loc, encompassedLLVMTy, rhs);
4258 lhs = mlir::LLVM::ZExtOp::create(rewriter, loc, encompassedLLVMTy, lhs);
4259 rhs = mlir::LLVM::ZExtOp::create(rewriter, loc, encompassedLLVMTy, rhs);
4264 std::string intrinName = (
"llvm." + llvm::Twine(
sign ?
's' :
'u') + opStr +
4265 ".with.overflow.i" + llvm::Twine(width))
4267 auto intrinNameAttr = mlir::StringAttr::get(op.getContext(), intrinName);
4269 mlir::IntegerType overflowLLVMTy = rewriter.getI1Type();
4270 auto intrinRetTy = mlir::LLVM::LLVMStructType::getLiteral(
4271 rewriter.getContext(), {encompassedLLVMTy, overflowLLVMTy});
4273 auto callLLVMIntrinOp = mlir::LLVM::CallIntrinsicOp::create(
4274 rewriter, loc, intrinRetTy, intrinNameAttr, mlir::ValueRange{lhs, rhs});
4275 mlir::Value intrinRet = callLLVMIntrinOp.getResult(0);
4277 mlir::Value result = mlir::LLVM::ExtractValueOp::create(
4280 mlir::Value overflow = mlir::LLVM::ExtractValueOp::create(
4284 if (resultWidth < width) {
4285 mlir::Type resultLLVMTy = typeConverter->convertType(resultTy);
4287 mlir::LLVM::TruncOp::create(rewriter, loc, resultLLVMTy, result);
4291 mlir::Value truncResultExt;
4293 truncResultExt = mlir::LLVM::SExtOp::create(
4294 rewriter, loc, encompassedLLVMTy, truncResult);
4296 truncResultExt = mlir::LLVM::ZExtOp::create(
4297 rewriter, loc, encompassedLLVMTy, truncResult);
4298 auto truncOverflow = mlir::LLVM::ICmpOp::create(
4299 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, truncResultExt, result);
4301 result = truncResult;
4302 overflow = mlir::LLVM::OrOp::create(rewriter, loc, overflow, truncOverflow);
4305 mlir::Type boolLLVMTy =
4306 typeConverter->convertType(op.getOverflow().getType());
4307 if (boolLLVMTy != rewriter.getI1Type())
4308 overflow = mlir::LLVM::ZExtOp::create(rewriter, loc, boolLLVMTy, overflow);
4310 rewriter.replaceOp(op, mlir::ValueRange{result, overflow});
4312 return mlir::success();
4315mlir::LogicalResult CIRToLLVMAddOverflowOpLowering::matchAndRewrite(
4316 cir::AddOverflowOp op, OpAdaptor adaptor,
4317 mlir::ConversionPatternRewriter &rewriter)
const {
4321mlir::LogicalResult CIRToLLVMSubOverflowOpLowering::matchAndRewrite(
4322 cir::SubOverflowOp op, OpAdaptor adaptor,
4323 mlir::ConversionPatternRewriter &rewriter)
const {
4327mlir::LogicalResult CIRToLLVMMulOverflowOpLowering::matchAndRewrite(
4328 cir::MulOverflowOp op, OpAdaptor adaptor,
4329 mlir::ConversionPatternRewriter &rewriter)
const {
4333mlir::LogicalResult CIRToLLVMFrexpOpLowering::matchAndRewrite(
4334 cir::FrexpOp op, OpAdaptor adaptor,
4335 mlir::ConversionPatternRewriter &rewriter)
const {
4336 mlir::Location loc = op.getLoc();
4337 mlir::Type fpLLVMTy =
4338 getTypeConverter()->convertType(op.getResult().getType());
4339 mlir::Type intLLVMTy = getTypeConverter()->convertType(op.getExp().getType());
4341 auto structTy = mlir::LLVM::LLVMStructType::getLiteral(rewriter.getContext(),
4342 {fpLLVMTy, intLLVMTy});
4346 mlir::Value result = callOp.getResult(0);
4348 mlir::Value mantissa =
4349 mlir::LLVM::ExtractValueOp::create(rewriter, loc, result, 0);
4350 mlir::Value exponent =
4351 mlir::LLVM::ExtractValueOp::create(rewriter, loc, result, 1);
4352 rewriter.replaceOp(op, mlir::ValueRange{mantissa, exponent});
4353 return mlir::success();
4356mlir::LogicalResult CIRToLLVMModfOpLowering::matchAndRewrite(
4357 cir::ModfOp op, OpAdaptor adaptor,
4358 mlir::ConversionPatternRewriter &rewriter)
const {
4359 mlir::Location loc = op.getLoc();
4360 mlir::Type fpLLVMTy =
4361 getTypeConverter()->convertType(op.getFractional().getType());
4363 auto structTy = mlir::LLVM::LLVMStructType::getLiteral(rewriter.getContext(),
4364 {fpLLVMTy, fpLLVMTy});
4368 mlir::Value result = callOp.getResult(0);
4370 mlir::Value fractional =
4371 mlir::LLVM::ExtractValueOp::create(rewriter, loc, result, 0);
4372 mlir::Value integral =
4373 mlir::LLVM::ExtractValueOp::create(rewriter, loc, result, 1);
4374 rewriter.replaceOp(op, mlir::ValueRange{fractional, integral});
4375 return mlir::success();
4378mlir::LogicalResult CIRToLLVMShiftOpLowering::matchAndRewrite(
4379 cir::ShiftOp op, OpAdaptor adaptor,
4380 mlir::ConversionPatternRewriter &rewriter)
const {
4381 assert((op.getValue().getType() == op.getType()) &&
4382 "inconsistent operands' types NYI");
4384 const mlir::Type llvmTy = getTypeConverter()->convertType(op.getType());
4385 mlir::Value amt = adaptor.getAmount();
4386 mlir::Value val = adaptor.getValue();
4388 auto cirAmtTy = mlir::dyn_cast<cir::IntType>(op.getAmount().getType());
4391 auto cirValTy = mlir::cast<cir::IntType>(op.getValue().getType());
4399 amt =
getLLVMIntCast(rewriter, amt, llvmTy,
true, cirAmtTy.getWidth(),
4400 cirValTy.getWidth());
4402 auto cirValVTy = mlir::cast<cir::VectorType>(op.getValue().getType());
4404 mlir::cast<cir::IntType>(cirValVTy.getElementType()).isUnsigned();
4408 if (op.getIsShiftleft()) {
4409 rewriter.replaceOpWithNewOp<mlir::LLVM::ShlOp>(op, llvmTy, val, amt);
4410 return mlir::success();
4414 rewriter.replaceOpWithNewOp<mlir::LLVM::LShrOp>(op, llvmTy, val, amt);
4416 rewriter.replaceOpWithNewOp<mlir::LLVM::AShrOp>(op, llvmTy, val, amt);
4417 return mlir::success();
4420mlir::LogicalResult CIRToLLVMSelectOpLowering::matchAndRewrite(
4421 cir::SelectOp op, OpAdaptor adaptor,
4422 mlir::ConversionPatternRewriter &rewriter)
const {
4428 if (mlir::isa<cir::BoolType>(op.getType())) {
4429 if (mlir::matchPattern(adaptor.getFalseValue(), mlir::m_Zero())) {
4431 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(op, adaptor.getCondition(),
4432 adaptor.getTrueValue());
4433 return mlir::success();
4435 if (mlir::matchPattern(adaptor.getTrueValue(), mlir::m_One())) {
4437 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(op, adaptor.getCondition(),
4438 adaptor.getFalseValue());
4439 return mlir::success();
4443 mlir::Value llvmCondition = adaptor.getCondition();
4444 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(
4445 op, llvmCondition, adaptor.getTrueValue(), adaptor.getFalseValue());
4447 return mlir::success();
4451 mlir::DataLayout &dataLayout) {
4452 converter.addConversion([&](cir::PointerType type) -> mlir::Type {
4453 mlir::ptr::MemorySpaceAttrInterface addrSpaceAttr = type.getAddrSpace();
4454 unsigned numericAS = 0;
4456 if (mlir::isa_and_present<cir::LangAddressSpaceAttr>(addrSpaceAttr))
4459 if (
auto targetAsAttr =
4460 mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
4462 numericAS = targetAsAttr.getValue();
4463 return mlir::LLVM::LLVMPointerType::get(type.getContext(), numericAS);
4465 converter.addConversion([&](cir::VPtrType type) -> mlir::Type {
4467 return mlir::LLVM::LLVMPointerType::get(type.getContext());
4471 converter.addConversion([&](cir::CUDADeviceSurfaceType type) -> mlir::Type {
4472 return mlir::IntegerType::get(type.getContext(), 64);
4474 converter.addConversion([&](cir::CUDADeviceTextureType type) -> mlir::Type {
4475 return mlir::IntegerType::get(type.getContext(), 64);
4477 converter.addConversion([&](cir::ArrayType type) -> mlir::Type {
4484 return mlir::LLVM::LLVMArrayType::get(ty, type.getSize());
4486 converter.addConversion([&](cir::VectorType type) -> mlir::Type {
4490 if (
auto intTy = mlir::dyn_cast<cir::IntType>(type.getElementType());
4491 intTy && intTy.isBitInt())
4493 const mlir::Type ty = converter.convertType(type.getElementType());
4496 return mlir::VectorType::get(type.getSize().getKnownMinValue(), ty,
4497 {type.isScalable()});
4499 converter.addConversion([&](cir::MatrixType type) -> mlir::Type {
4500 const uint64_t size = type.getNumRows() * type.getNumColumns();
4501 const mlir::Type elemTy = converter.convertType(type.getElementType());
4502 return mlir::VectorType::get(size, elemTy);
4504 converter.addConversion([&](cir::BoolType type) -> mlir::Type {
4505 return mlir::IntegerType::get(type.getContext(), 1,
4506 mlir::IntegerType::Signless);
4508 converter.addConversion([&](cir::IntType type) -> mlir::Type {
4510 return mlir::IntegerType::get(type.getContext(), type.getWidth());
4512 converter.addConversion([&](cir::SingleType type) -> mlir::Type {
4513 return mlir::Float32Type::get(type.getContext());
4515 converter.addConversion([&](cir::DoubleType type) -> mlir::Type {
4516 return mlir::Float64Type::get(type.getContext());
4518 converter.addConversion([&](cir::FP80Type type) -> mlir::Type {
4519 return mlir::Float80Type::get(type.getContext());
4521 converter.addConversion([&](cir::FP128Type type) -> mlir::Type {
4522 return mlir::Float128Type::get(type.getContext());
4524 converter.addConversion([&](cir::LongDoubleType type) -> mlir::Type {
4525 return converter.convertType(type.getUnderlying());
4527 converter.addConversion([&](cir::FP16Type type) -> mlir::Type {
4528 return mlir::Float16Type::get(type.getContext());
4530 converter.addConversion([&](cir::BF16Type type) -> mlir::Type {
4531 return mlir::BFloat16Type::get(type.getContext());
4533 converter.addConversion([&](cir::ComplexType type) -> mlir::Type {
4536 mlir::Type elementTy = converter.convertType(type.getElementType());
4537 mlir::Type structFields[2] = {elementTy, elementTy};
4538 return mlir::LLVM::LLVMStructType::getLiteral(type.getContext(),
4541 converter.addConversion([&](cir::FuncType type) -> std::optional<mlir::Type> {
4542 auto result = converter.convertType(type.getReturnType());
4544 return std::nullopt;
4546 arguments.reserve(type.getNumInputs());
4547 if (converter.convertTypes(type.getInputs(), arguments).failed())
4548 return std::nullopt;
4549 auto varArg = type.isVarArg();
4550 return mlir::LLVM::LLVMFunctionType::get(result, arguments, varArg);
4552 converter.addConversion([&](cir::StructType type) -> mlir::Type {
4554 for (mlir::Type ty : type.getMembers()) {
4567 llvmMembers.push_back(memberTy);
4570 mlir::LLVM::LLVMStructType llvmStruct;
4571 if (type.getName()) {
4572 llvmStruct = mlir::LLVM::LLVMStructType::getIdentified(
4573 type.getContext(), type.getPrefixedName());
4574 if (llvmStruct.setBody(llvmMembers, type.getPacked()).failed())
4575 llvm_unreachable(
"Failed to set body of record");
4577 llvmStruct = mlir::LLVM::LLVMStructType::getLiteral(
4578 type.getContext(), llvmMembers, type.getPacked());
4583 converter.addConversion([&](cir::UnionType type) -> mlir::Type {
4585 if (!type.getMembers().empty())
4586 if (
auto storage = type.getUnionStorageType(dataLayout)) {
4587 mlir::Type storageTy =
4591 llvmMembers.push_back(storageTy);
4593 if (mlir::Type pad = type.getPadding()) {
4597 llvmMembers.push_back(padTy);
4600 mlir::LLVM::LLVMStructType llvmStruct;
4601 if (type.getName()) {
4602 llvmStruct = mlir::LLVM::LLVMStructType::getIdentified(
4603 type.getContext(), type.getPrefixedName());
4604 if (llvmStruct.setBody(llvmMembers, type.getPacked()).failed())
4605 llvm_unreachable(
"Failed to set body of record");
4607 llvmStruct = mlir::LLVM::LLVMStructType::getLiteral(
4608 type.getContext(), llvmMembers, type.getPacked());
4612 converter.addConversion([&](cir::VoidType type) -> mlir::Type {
4613 return mlir::LLVM::LLVMVoidType::get(type.getContext());
4617 mlir::ModuleOp module, StringRef globalXtorName, StringRef llvmXtorName,
4621 module->getDiscardableAttrOfType<mlir::ArrayAttr>(globalXtorName))
4622 for (mlir::Attribute element : attr)
4623 globalXtors.emplace_back(createXtor(element));
4625 if (globalXtors.empty())
4628 mlir::OpBuilder builder(module.getContext());
4629 builder.setInsertionPointToEnd(&module.getBodyRegion().back());
4634 auto ctorPFTy = mlir::LLVM::LLVMPointerType::get(
4637 ctorStructFields.push_back(builder.getI32Type());
4638 ctorStructFields.push_back(ctorPFTy);
4639 ctorStructFields.push_back(ctorPFTy);
4641 auto ctorStructTy = mlir::LLVM::LLVMStructType::getLiteral(
4642 builder.getContext(), ctorStructFields);
4643 auto ctorStructArrayTy =
4644 mlir::LLVM::LLVMArrayType::get(ctorStructTy, globalXtors.size());
4646 mlir::Location loc =
module.getLoc();
4647 auto newGlobalOp = mlir::LLVM::GlobalOp::create(
4648 builder, loc, ctorStructArrayTy,
false,
4649 mlir::LLVM::Linkage::Appending, llvmXtorName, mlir::Attribute());
4651 builder.createBlock(&newGlobalOp.getRegion());
4652 builder.setInsertionPointToEnd(newGlobalOp.getInitializerBlock());
4654 mlir::Value result =
4655 mlir::LLVM::UndefOp::create(builder, loc, ctorStructArrayTy);
4657 for (
auto [index, xtorInfo] : llvm::enumerate(globalXtors)) {
4658 mlir::Value structInit =
4659 mlir::LLVM::UndefOp::create(builder, loc, ctorStructTy);
4660 mlir::Value initPriority = mlir::LLVM::ConstantOp::create(
4661 builder, loc, ctorStructFields[0], xtorInfo.priority);
4662 mlir::Value initFuncAddr = mlir::LLVM::AddressOfOp::create(
4663 builder, loc, ctorStructFields[1], xtorInfo.name);
4664 mlir::Value initAssociate =
4665 xtorInfo.associated.empty()
4666 ? mlir::LLVM::ZeroOp::create(builder, loc, ctorStructFields[2])
4668 : mlir::LLVM::AddressOfOp::create(builder, loc, ctorStructFields[2],
4669 xtorInfo.associated)
4673 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
4674 initPriority, zero);
4675 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
4677 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
4679 result = mlir::LLVM::InsertValueOp::create(builder, loc, result, structInit,
4683 mlir::LLVM::ReturnOp::create(builder, loc, result);
4686mlir::LogicalResult CIRToLLVMObjSizeOpLowering::matchAndRewrite(
4687 cir::ObjSizeOp op, OpAdaptor adaptor,
4688 mlir::ConversionPatternRewriter &rewriter)
const {
4689 mlir::Type llvmResTy = getTypeConverter()->convertType(op.getType());
4690 mlir::Location loc = op->getLoc();
4692 mlir::IntegerType i1Ty = rewriter.getI1Type();
4694 auto i1Val = [&rewriter, &loc, &i1Ty](
bool val) {
4695 return mlir::LLVM::ConstantOp::create(rewriter, loc, i1Ty, val);
4702 i1Val(op.getNullunknown()),
4703 i1Val(op.getDynamic()),
4706 return mlir::LogicalResult::success();
4714constexpr StringRef llvmMetadataSectionName =
"llvm.metadata";
4719getOrCreateAnnotationStringGlobal(mlir::OpBuilder &builder, mlir::Location loc,
4720 mlir::ModuleOp module, llvm::StringRef str,
4721 llvm::StringMap<mlir::LLVM::GlobalOp> &cache,
4723 auto it = cache.find(str);
4724 if (it != cache.end())
4727 auto i8Ty = mlir::IntegerType::get(module.getContext(), 8);
4728 auto arrayTy = mlir::LLVM::LLVMArrayType::get(i8Ty, str.size() + 1);
4729 std::string
name =
".str";
4731 name +=
"." + std::to_string(cache.size());
4732 name +=
".annotation";
4736 mlir::LLVM::GlobalOp strGlobal = mlir::LLVM::GlobalOp::create(
4737 builder, loc, arrayTy,
true, mlir::LLVM::Linkage::Private,
4738 name, mlir::StringAttr::get(module.getContext(), std::string(str) +
'\0'),
4741 strGlobal.setSection(llvmMetadataSectionName);
4742 strGlobal.setUnnamedAddr(mlir::LLVM::UnnamedAddr::Global);
4743 strGlobal.setDsoLocal(
true);
4744 cache[str] = strGlobal;
4750mlir::LLVM::GlobalOp getOrCreateAnnotationArgsVar(
4751 mlir::OpBuilder &builder, mlir::Location loc, mlir::ModuleOp module,
4752 mlir::ArrayAttr argsAttr,
4753 llvm::StringMap<mlir::LLVM::GlobalOp> &argStringCache,
4754 llvm::MapVector<mlir::ArrayAttr, mlir::LLVM::GlobalOp> &argsCache) {
4755 auto it = argsCache.find(argsAttr);
4756 if (it != argsCache.end())
4759 auto ptrTy = mlir::LLVM::LLVMPointerType::get(builder.getContext());
4761 llvm::SmallVector<mlir::Type> fieldTypes;
4762 for (mlir::Attribute arg : argsAttr) {
4763 if (mlir::isa<mlir::StringAttr>(arg))
4764 fieldTypes.push_back(ptrTy);
4765 else if (
auto intAttr = mlir::dyn_cast<mlir::IntegerAttr>(arg))
4766 fieldTypes.push_back(intAttr.getType());
4768 llvm_unreachable(
"Unsupported annotation arg type");
4772 mlir::LLVM::LLVMStructType::getLiteral(builder.getContext(), fieldTypes);
4773 std::string
name =
".args";
4774 if (!argsCache.empty())
4775 name +=
"." + std::to_string(argsCache.size());
4776 name +=
".annotation";
4778 mlir::LLVM::GlobalOp argsGlobal = mlir::LLVM::GlobalOp::create(
4779 builder, loc, structTy,
true, mlir::LLVM::Linkage::Private,
4780 name, mlir::Attribute());
4781 argsGlobal.setSection(llvmMetadataSectionName);
4782 argsGlobal.setUnnamedAddr(mlir::LLVM::UnnamedAddr::Global);
4783 argsGlobal.setDsoLocal(
true);
4786 argsGlobal.getRegion().push_back(
new mlir::Block());
4787 mlir::OpBuilder initBuilder(module.getContext());
4788 initBuilder.setInsertionPointToEnd(argsGlobal.getInitializerBlock());
4790 mlir::Value structInit =
4791 mlir::LLVM::UndefOp::create(initBuilder, loc, structTy);
4792 for (
auto [idx, arg] : llvm::enumerate(argsAttr)) {
4793 if (
auto strArg = mlir::dyn_cast<mlir::StringAttr>(arg)) {
4794 mlir::LLVM::GlobalOp strGlobal = getOrCreateAnnotationStringGlobal(
4795 builder, loc, module, strArg.getValue(), argStringCache,
4797 mlir::LLVM::AddressOfOp strAddr = mlir::LLVM::AddressOfOp::create(
4798 initBuilder, loc, ptrTy, strGlobal.getSymName());
4799 structInit = mlir::LLVM::InsertValueOp::create(initBuilder, loc,
4800 structInit, strAddr, idx);
4801 }
else if (
auto intArg = mlir::dyn_cast<mlir::IntegerAttr>(arg)) {
4802 mlir::LLVM::ConstantOp intConst = mlir::LLVM::ConstantOp::create(
4803 initBuilder, loc, intArg.getType(), intArg.getValue());
4804 structInit = mlir::LLVM::InsertValueOp::create(initBuilder, loc,
4805 structInit, intConst, idx);
4807 llvm_unreachable(
"Unsupported annotation arg type");
4810 mlir::LLVM::ReturnOp::create(initBuilder, loc, structInit);
4812 argsCache[argsAttr] = argsGlobal;
4818std::pair<llvm::StringRef, unsigned> extractFileLine(mlir::Location loc) {
4819 mlir::Location resolved = loc;
4820 if (
auto fused = mlir::dyn_cast<mlir::FusedLoc>(resolved)) {
4821 if (!fused.getLocations().empty())
4822 resolved = fused.getLocations()[0];
4824 if (
auto fl = mlir::dyn_cast<mlir::FileLineColLoc>(resolved))
4825 return {fl.getFilename().getValue(), fl.getLine()};
4831 auto handleArray = [&](mlir::StringAttr symName, mlir::ArrayAttr arr,
4832 mlir::Location loc) {
4835 for (mlir::Attribute a : arr)
4836 if (
auto annot = mlir::dyn_cast<cir::AnnotationAttr>(a))
4837 collectedAnnotations.emplace_back(symName, annot, loc);
4842 module.walk([&](cir::GlobalOp op) {
4843 handleArray(op.getSymNameAttr(), op.getAnnotationsAttr(), op.getLoc());
4845 module.walk([&](cir::FuncOp op) {
4846 handleArray(op.getSymNameAttr(), op.getAnnotationsAttr(), op.getLoc());
4851 if (collectedAnnotations.empty())
4854 mlir::MLIRContext *ctx =
module.getContext();
4855 mlir::OpBuilder builder(ctx);
4856 builder.setInsertionPointToEnd(&module.getBodyRegion().back());
4858 auto ptrTy = mlir::LLVM::LLVMPointerType::get(ctx);
4859 auto i32Ty = builder.getI32Type();
4862 auto entryTy = mlir::LLVM::LLVMStructType::getLiteral(
4863 ctx, {ptrTy, ptrTy, ptrTy, i32Ty, ptrTy});
4865 mlir::LLVM::LLVMArrayType::get(entryTy, collectedAnnotations.size());
4867 mlir::Location moduleLoc =
module.getLoc();
4868 auto annotationsGlobal = mlir::LLVM::GlobalOp::create(
4869 builder, moduleLoc, arrayTy,
false,
4870 mlir::LLVM::Linkage::Appending,
"llvm.global.annotations",
4872 annotationsGlobal.setSection(llvmMetadataSectionName);
4876 mlir::OpBuilder constsBuilder(ctx);
4877 constsBuilder.setInsertionPoint(annotationsGlobal);
4879 llvm::StringMap<mlir::LLVM::GlobalOp> stringCache;
4880 llvm::StringMap<mlir::LLVM::GlobalOp> argStringCache;
4881 llvm::MapVector<mlir::ArrayAttr, mlir::LLVM::GlobalOp> argsCache;
4884 annotationsGlobal.getRegion().push_back(
new mlir::Block());
4885 mlir::OpBuilder initBuilder(ctx);
4886 initBuilder.setInsertionPointToEnd(annotationsGlobal.getInitializerBlock());
4888 mlir::Value arrayVal =
4889 mlir::LLVM::UndefOp::create(initBuilder, moduleLoc, arrayTy);
4891 for (
auto [idx, entry] : llvm::enumerate(collectedAnnotations)) {
4892 mlir::Value entryVal =
4893 mlir::LLVM::UndefOp::create(initBuilder, moduleLoc, entryTy);
4898 mlir::LLVM::AddressOfOp symAddr = mlir::LLVM::AddressOfOp::create(
4899 initBuilder, moduleLoc, ptrTy, entry.symName.getValue());
4900 entryVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
4901 entryVal, symAddr, zero);
4904 mlir::LLVM::GlobalOp nameGlobal = getOrCreateAnnotationStringGlobal(
4905 constsBuilder, moduleLoc, module, entry.annotation.getName().getValue(),
4906 stringCache,
false);
4907 mlir::LLVM::AddressOfOp nameAddr = mlir::LLVM::AddressOfOp::create(
4908 initBuilder, moduleLoc, ptrTy, nameGlobal.getSymName());
4909 entryVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
4910 entryVal, nameAddr, 1);
4913 auto [filename, line] = extractFileLine(entry.loc);
4914 mlir::LLVM::GlobalOp fileGlobal = getOrCreateAnnotationStringGlobal(
4915 constsBuilder, moduleLoc, module, filename, stringCache,
4917 mlir::LLVM::AddressOfOp fileAddr = mlir::LLVM::AddressOfOp::create(
4918 initBuilder, moduleLoc, ptrTy, fileGlobal.getSymName());
4919 entryVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
4920 entryVal, fileAddr, 2);
4921 mlir::LLVM::ConstantOp lineConst =
4922 mlir::LLVM::ConstantOp::create(initBuilder, moduleLoc, i32Ty, line);
4923 entryVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
4924 entryVal, lineConst, 3);
4927 mlir::ArrayAttr args = entry.annotation.getArgs();
4928 mlir::Value argsField;
4929 if (!args || args.empty()) {
4930 argsField = mlir::LLVM::ZeroOp::create(initBuilder, moduleLoc, ptrTy);
4932 mlir::LLVM::GlobalOp argsGlobal = getOrCreateAnnotationArgsVar(
4933 constsBuilder, moduleLoc, module, args, argStringCache, argsCache);
4934 argsField = mlir::LLVM::AddressOfOp::create(initBuilder, moduleLoc, ptrTy,
4935 argsGlobal.getSymName());
4937 entryVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
4938 entryVal, argsField, 4);
4940 arrayVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
4941 arrayVal, entryVal, idx);
4944 mlir::LLVM::ReturnOp::create(initBuilder, moduleLoc, arrayVal);
4950 mlir::ModuleOp module = getOperation();
4951 mlir::OpBuilder opBuilder(module.getContext());
4952 for (
auto &[blockAddOp, blockInfo] :
4954 mlir::LLVM::BlockTagOp resolvedLabel =
4956 assert(resolvedLabel &&
"expected BlockTagOp to already be emitted");
4957 mlir::FlatSymbolRefAttr fnSym = blockInfo.getFunc();
4958 auto blkAddTag = mlir::LLVM::BlockAddressAttr::get(
4959 opBuilder.getContext(), fnSym, resolvedLabel.getTagAttr());
4960 blockAddOp.setBlockAddrAttr(blkAddTag);
4967 if (mlir::Attribute tripleAttr =
4968 module->getAttr(cir::CIRDialect::getTripleAttrName()))
4969 module->setAttr(mlir::LLVM::LLVMDialect::getTargetTripleAttrName(),
4972 if (mlir::Attribute asmAttr =
4973 module->getAttr(cir::CIRDialect::getModuleLevelAsmAttrName()))
4974 module->setAttr(mlir::LLVM::LLVMDialect::getModuleLevelAsmAttrName(),
4977 if (
auto framePointerAttr = module->getAttrOfType<cir::FramePointerKindAttr>(
4978 cir::CIRDialect::getModuleFramePointerAttrName())) {
4979 mlir::OpBuilder builder(module.getContext());
4980 builder.setInsertionPointToEnd(module.getBody());
4981 auto flag = mlir::LLVM::ModuleFlagAttr::get(
4982 module.getContext(), mlir::LLVM::ModFlagBehavior::Max,
4983 builder.getStringAttr(
"frame-pointer"),
4984 builder.getI32IntegerAttr(
static_cast<int32_t
>(
4986 mlir::LLVM::ModuleFlagsOp::create(builder, module.getLoc(),
4987 builder.getArrayAttr({flag}));
4994 llvm::TimeTraceScope scope(
"Convert CIR to LLVM Pass");
4996 mlir::ModuleOp module = getOperation();
5005 for (mlir::Operation &op : module.getBody()->getOperations()) {
5006 if (
auto globalOp = mlir::dyn_cast<cir::GlobalOp>(op))
5007 preConversionTypes[globalOp.getSymName()] = globalOp.getSymType();
5008 else if (
auto funcOp = mlir::dyn_cast<cir::FuncOp>(op))
5009 preConversionTypes[funcOp.getSymName()] = funcOp.getFunctionType();
5011 mlir::DataLayout dl(module);
5012 mlir::LLVMTypeConverter converter(&getContext());
5022 mlir::SymbolTableCollection symbolTables;
5023 mlir::RewritePatternSet patterns(&getContext());
5024 patterns.add<CIRToLLVMBlockAddressOpLowering, CIRToLLVMLabelOpLowering>(
5025 converter, patterns.getContext(), dl, symbolTables, blockInfoAddr);
5026 patterns.add<CIRToLLVMGlobalOpLowering, CIRToLLVMConstantOpLowering>(
5027 converter, patterns.getContext(), dl, symbolTables, blockInfoAddr,
5028 preConversionTypes);
5031#define GET_LLVM_LOWERING_PATTERNS_LIST
5032#include "clang/CIR/Dialect/IR/CIRLowering.inc"
5033#undef GET_LLVM_LOWERING_PATTERNS_LIST
5034 >(converter, patterns.getContext(), dl, symbolTables);
5037 .add<CIRToLLVMVTableAddrPointOpLowering, CIRToLLVMVTTAddrPointOpLowering>(
5038 converter, patterns.getContext(), dl, symbolTables,
5039 preConversionTypes);
5047 mlir::ConversionTarget target(getContext());
5048 target.addLegalOp<mlir::ModuleOp>();
5049 target.addLegalDialect<mlir::LLVM::LLVMDialect>();
5050 mlir::configureOpenMPToLLVMConversionLegality(target, converter);
5051 target.addLegalDialect<mlir::omp::OpenMPDialect>();
5052 mlir::populateOpenMPToLLVMConversionPatterns(converter, patterns);
5053 target.addIllegalDialect<mlir::BuiltinDialect, cir::CIRDialect,
5054 mlir::func::FuncDialect>();
5057 ops.push_back(module);
5060 if (failed(applyPartialConversion(ops, target, std::move(patterns)))) {
5061 signalPassFailure();
5067 if (
auto dlSpec = mlir::dyn_cast_or_null<mlir::DataLayoutSpecAttr>(
5068 module->getAttr(mlir::DLTIDialect::kDataLayoutAttrName))) {
5070 for (mlir::DataLayoutEntryInterface entry : dlSpec.getEntries()) {
5071 if (entry.isTypeEntry() &&
5072 mlir::isa<cir::PointerType>(mlir::cast<mlir::Type>(entry.getKey())))
5074 kept.push_back(entry);
5076 module->setAttr(mlir::DLTIDialect::kDataLayoutAttrName,
5077 mlir::DataLayoutSpecAttr::get(module.getContext(), kept));
5082 module, cir::CIRDialect::getGlobalCtorsAttrName(),
"llvm.global_ctors",
5083 [](mlir::Attribute
attr) {
5084 auto ctorAttr = mlir::cast<cir::GlobalCtorAttr>(
attr);
5085 StringRef associated;
5086 if (mlir::FlatSymbolRefAttr assoc = ctorAttr.getAssociated())
5087 associated = assoc.getValue();
5089 ctorAttr.getPriority(), associated);
5093 module, cir::CIRDialect::getGlobalDtorsAttrName(),
"llvm.global_dtors",
5094 [](mlir::Attribute
attr) {
5095 auto dtorAttr = mlir::cast<cir::GlobalDtorAttr>(
attr);
5096 StringRef associated;
5097 if (mlir::FlatSymbolRefAttr assoc = dtorAttr.getAssociated())
5098 associated = assoc.getValue();
5100 dtorAttr.getPriority(), associated);
5108mlir::LogicalResult CIRToLLVMBrOpLowering::matchAndRewrite(
5109 cir::BrOp op, OpAdaptor adaptor,
5110 mlir::ConversionPatternRewriter &rewriter)
const {
5111 rewriter.replaceOpWithNewOp<mlir::LLVM::BrOp>(op, adaptor.getOperands(),
5113 return mlir::LogicalResult::success();
5116mlir::LogicalResult CIRToLLVMGetMemberOpLowering::matchAndRewrite(
5117 cir::GetMemberOp op, OpAdaptor adaptor,
5118 mlir::ConversionPatternRewriter &rewriter)
const {
5119 mlir::Type llResTy = getTypeConverter()->convertType(op.getType());
5121 return emitTypeConversionError(op, op.getType());
5122 mlir::Type pointee = op.getAddrTy().getPointee();
5124 if (mlir::isa<cir::UnionType>(pointee)) {
5127 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(op, llResTy,
5129 return mlir::success();
5132 auto structTy = mlir::cast<cir::StructType>(pointee);
5138 0,
static_cast<int32_t>(structTy.getLLVMFieldIndex(op.getIndex()))};
5139 const mlir::Type elementTy = getTypeConverter()->convertType(structTy);
5146 mlir::LLVM::GEPNoWrapFlags flags =
5147 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
5148 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
5149 op, llResTy, elementTy, adaptor.getAddr(), offset, flags);
5150 return mlir::success();
5153mlir::LogicalResult CIRToLLVMExtractMemberOpLowering::matchAndRewrite(
5154 cir::ExtractMemberOp op, OpAdaptor adaptor,
5155 mlir::ConversionPatternRewriter &rewriter)
const {
5156 if (mlir::isa<cir::UnionType>(op.getRecord().getType())) {
5157 op.emitError(
"cir.extract_member cannot extract member from a union");
5158 return mlir::failure();
5161 auto structTy = mlir::cast<cir::StructType>(op.getRecord().getType());
5162 std::int64_t indices[1] = {
5163 static_cast<std::int64_t
>(structTy.getLLVMFieldIndex(op.getIndex()))};
5164 rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractValueOp>(
5165 op, adaptor.getRecord(), indices);
5166 return mlir::success();
5169mlir::LogicalResult CIRToLLVMInsertMemberOpLowering::matchAndRewrite(
5170 cir::InsertMemberOp op, OpAdaptor adaptor,
5171 mlir::ConversionPatternRewriter &rewriter)
const {
5172 if (mlir::isa<cir::UnionType>(op.getRecord().getType())) {
5173 op.emitError(
"cir.update_member cannot update member of a union");
5174 return mlir::failure();
5177 auto structTy = mlir::cast<cir::StructType>(op.getRecord().getType());
5178 std::int64_t indices[1] = {
5179 static_cast<std::int64_t
>(structTy.getLLVMFieldIndex(op.getIndex()))};
5180 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
5181 op, adaptor.getRecord(), adaptor.getValue(), indices);
5182 return mlir::success();
5186 mlir::SymbolTableCollection &symbolTables,
5187 mlir::Operation *srcOp, llvm::StringRef fnName,
5188 mlir::Type fnTy, mlir::ArrayAttr argAttrs,
5189 mlir::ArrayAttr resAttrs) {
5190 mlir::ModuleOp modOp = srcOp->getParentOfType<mlir::ModuleOp>();
5191 mlir::Operation *sourceSymbol = symbolTables.lookupSymbolIn(
5192 modOp, mlir::StringAttr::get(fnTy.getContext(), fnName));
5193 if (!sourceSymbol) {
5194 mlir::OpBuilder::InsertionGuard guard(rewriter);
5195 auto enclosingFnOp = srcOp->getParentOfType<mlir::LLVM::LLVMFuncOp>();
5196 rewriter.setInsertionPoint(enclosingFnOp);
5198 mlir::LLVM::LLVMFuncOp::create(rewriter, srcOp->getLoc(), fnName, fnTy);
5200 fn.setArgAttrsAttr(argAttrs);
5202 fn.setResAttrsAttr(resAttrs);
5204 symbolTables.getSymbolTable(fn->getParentOp()).insert(fn);
5208mlir::LogicalResult CIRToLLVMThrowOpLowering::matchAndRewrite(
5209 cir::ThrowOp op, OpAdaptor adaptor,
5210 mlir::ConversionPatternRewriter &rewriter)
const {
5211 mlir::Location loc = op.getLoc();
5212 auto voidTy = mlir::LLVM::LLVMVoidType::get(getContext());
5217 if (op.rethrows()) {
5218 auto funcTy = mlir::LLVM::LLVMFunctionType::get(voidTy, {});
5221 const llvm::StringRef functionName =
"__cxa_rethrow";
5222 createLLVMFuncOpIfNotExist(rewriter, symbolTables, op, functionName,
5225 auto cxaRethrow = mlir::LLVM::CallOp::create(
5226 rewriter, loc, mlir::TypeRange{}, functionName);
5228 rewriter.replaceOp(op, cxaRethrow);
5229 return mlir::success();
5232 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
5233 auto fnTy = mlir::LLVM::LLVMFunctionType::get(
5234 voidTy, {llvmPtrTy, llvmPtrTy, llvmPtrTy});
5237 const llvm::StringRef fnName =
"__cxa_throw";
5240 mlir::Value typeInfo = mlir::LLVM::AddressOfOp::create(
5241 rewriter, loc, mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
5242 adaptor.getTypeInfoAttr());
5246 dtor = mlir::LLVM::AddressOfOp::create(rewriter, loc, llvmPtrTy,
5247 adaptor.getDtorAttr());
5249 dtor = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmPtrTy);
5252 auto cxaThrowCall = mlir::LLVM::CallOp::create(
5253 rewriter, loc, mlir::TypeRange{}, fnName,
5254 mlir::ValueRange{adaptor.getExceptionPtr(), typeInfo, dtor});
5256 rewriter.replaceOp(op, cxaThrowCall);
5257 return mlir::success();
5260mlir::LogicalResult CIRToLLVMAllocExceptionOpLowering::matchAndRewrite(
5261 cir::AllocExceptionOp op, OpAdaptor adaptor,
5262 mlir::ConversionPatternRewriter &rewriter)
const {
5264 StringRef fnName =
"__cxa_allocate_exception";
5265 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
5266 auto int64Ty = mlir::IntegerType::get(rewriter.getContext(), 64);
5267 auto fnTy = mlir::LLVM::LLVMFunctionType::get(llvmPtrTy, {int64Ty});
5270 auto exceptionSize = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
5271 adaptor.getSizeAttr());
5273 auto allocaExceptionCall = mlir::LLVM::CallOp::create(
5274 rewriter, op.getLoc(), mlir::TypeRange{llvmPtrTy}, fnName,
5275 mlir::ValueRange{exceptionSize});
5277 rewriter.replaceOp(op, allocaExceptionCall);
5278 return mlir::success();
5281static mlir::LLVM::LLVMStructType
5284 mlir::MLIRContext *ctx = rewriter.getContext();
5285 auto llvmPtr = mlir::LLVM::LLVMPointerType::get(ctx);
5287 return mlir::LLVM::LLVMStructType::getLiteral(ctx, structFields);
5290mlir::LogicalResult CIRToLLVMEhInflightOpLowering::matchAndRewrite(
5291 cir::EhInflightOp op, OpAdaptor adaptor,
5292 mlir::ConversionPatternRewriter &rewriter)
const {
5293 auto llvmFn = op->getParentOfType<mlir::LLVM::LLVMFuncOp>();
5294 assert(llvmFn &&
"expected LLVM function parent");
5295 mlir::Block *entryBlock = &llvmFn.getRegion().front();
5296 assert(entryBlock->isEntryBlock());
5298 mlir::ArrayAttr catchListAttr = op.getCatchTypeListAttr();
5299 mlir::ArrayAttr filterListAttr = op.getFilterTypeListAttr();
5300 mlir::SmallVector<mlir::Value> landingPadClauses;
5302 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
5303 mlir::Location loc = op.getLoc();
5308 if (catchListAttr) {
5311 for (mlir::Attribute catchAttr : catchListAttr) {
5312 auto symAttr = cast<mlir::FlatSymbolRefAttr>(catchAttr);
5315 mlir::OpBuilder::InsertionGuard guard(rewriter);
5316 rewriter.setInsertionPointToStart(entryBlock);
5317 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
5318 rewriter, loc, llvmPtrTy, symAttr.getValue());
5319 landingPadClauses.push_back(addrOp);
5326 if (op.getCatchAll() ||
5327 (!catchListAttr && !op.getCleanup() && !filterListAttr)) {
5328 mlir::OpBuilder::InsertionGuard guard(rewriter);
5329 rewriter.setInsertionPointToStart(entryBlock);
5330 mlir::Value nullOp = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmPtrTy);
5331 landingPadClauses.push_back(nullOp);
5334 if (filterListAttr) {
5338 mlir::OpBuilder::InsertionGuard guard(rewriter);
5339 rewriter.setInsertionPointToStart(entryBlock);
5340 auto filterArrayTy =
5341 mlir::LLVM::LLVMArrayType::get(llvmPtrTy, filterListAttr.size());
5342 mlir::Value filterVal;
5343 if (filterListAttr.empty()) {
5344 filterVal = mlir::LLVM::ZeroOp::create(rewriter, loc, filterArrayTy);
5346 filterVal = mlir::LLVM::UndefOp::create(rewriter, loc, filterArrayTy);
5347 for (
auto [i, filterAttr] : llvm::enumerate(filterListAttr)) {
5348 auto symAttr = mlir::cast<mlir::FlatSymbolRefAttr>(filterAttr);
5349 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
5350 rewriter, loc, llvmPtrTy, symAttr.getValue());
5351 filterVal = mlir::LLVM::InsertValueOp::create(
5352 rewriter, loc, filterVal, addrOp,
5356 landingPadClauses.push_back(filterVal);
5361 mlir::LLVM::LLVMStructType llvmLandingPadStructTy =
5363 auto landingPadOp = mlir::LLVM::LandingpadOp::create(
5364 rewriter, loc, llvmLandingPadStructTy, landingPadClauses);
5369 if (op.getCleanup() && !op.getCatchAll())
5370 landingPadOp.setCleanup(
true);
5373 mlir::LLVM::ExtractValueOp::create(rewriter, loc, landingPadOp, 0);
5374 mlir::Value selector =
5375 mlir::LLVM::ExtractValueOp::create(rewriter, loc, landingPadOp, 1);
5376 rewriter.replaceOp(op, mlir::ValueRange{slot, selector});
5378 return mlir::success();
5381mlir::LogicalResult CIRToLLVMResumeFlatOpLowering::matchAndRewrite(
5382 cir::ResumeFlatOp op, OpAdaptor adaptor,
5383 mlir::ConversionPatternRewriter &rewriter)
const {
5388 mlir::Value poison = mlir::LLVM::PoisonOp::create(rewriter, op.getLoc(),
5389 llvmLandingPadStructTy);
5392 mlir::Value slot = mlir::LLVM::InsertValueOp::create(
5393 rewriter, op.getLoc(), poison, adaptor.getExceptionPtr(), slotIdx);
5396 mlir::Value selector = mlir::LLVM::InsertValueOp::create(
5397 rewriter, op.getLoc(), slot, adaptor.getTypeId(), selectorIdx);
5399 rewriter.replaceOpWithNewOp<mlir::LLVM::ResumeOp>(op, selector);
5400 return mlir::success();
5403mlir::LogicalResult CIRToLLVMEhTypeIdOpLowering::matchAndRewrite(
5404 cir::EhTypeIdOp op, OpAdaptor adaptor,
5405 mlir::ConversionPatternRewriter &rewriter)
const {
5406 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
5407 rewriter, op.getLoc(),
5408 mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
5409 op.getTypeSymAttr());
5410 rewriter.replaceOpWithNewOp<mlir::LLVM::EhTypeidForOp>(
5411 op, rewriter.getI32Type(), addrOp);
5412 return mlir::success();
5415mlir::LogicalResult CIRToLLVMEhSetjmpOpLowering::matchAndRewrite(
5416 cir::EhSetjmpOp op, OpAdaptor adaptor,
5417 mlir::ConversionPatternRewriter &rewriter)
const {
5418 mlir::Type returnType = typeConverter->convertType(op.getType());
5419 mlir::LLVM::CallIntrinsicOp newOp =
5421 returnType, adaptor.getEnv());
5422 rewriter.replaceOp(op, newOp);
5423 return mlir::success();
5426mlir::LogicalResult CIRToLLVMEhLongjmpOpLowering::matchAndRewrite(
5427 cir::EhLongjmpOp op, OpAdaptor adaptor,
5428 mlir::ConversionPatternRewriter &rewriter)
const {
5430 {}, adaptor.getOperands());
5431 return mlir::success();
5434mlir::LogicalResult CIRToLLVMTrapOpLowering::matchAndRewrite(
5435 cir::TrapOp op, OpAdaptor adaptor,
5436 mlir::ConversionPatternRewriter &rewriter)
const {
5437 mlir::Location loc = op->getLoc();
5438 rewriter.eraseOp(op);
5440 mlir::LLVM::Trap::create(rewriter, loc);
5445 mlir::LLVM::UnreachableOp::create(rewriter, loc);
5447 return mlir::success();
5452 mlir::ConversionPatternRewriter &rewriter,
5453 mlir::SymbolTableCollection &symbolTables,
5454 const mlir::TypeConverter *converter,
5456 mlir::FlatSymbolRefAttr nameAttr, mlir::Type &eltType) {
5457 auto module = op->getParentOfType<mlir::ModuleOp>();
5458 mlir::Operation *symbol = symbolTables.lookupSymbolIn(module, nameAttr);
5459 if (
auto llvmSymbol = mlir::dyn_cast<mlir::LLVM::GlobalOp>(symbol)) {
5460 if (mlir::Type preType = preConversionTypes.lookup(nameAttr.getValue())) {
5461 eltType = converter->convertType(preType);
5464 <<
" for vtable symbol " << nameAttr;
5468 eltType = llvmSymbol.getType();
5470 }
else if (
auto cirSymbol = mlir::dyn_cast<cir::GlobalOp>(symbol)) {
5471 eltType = converter->convertType(cirSymbol.getSymType());
5474 <<
" for vtable symbol " << nameAttr;
5478 op->emitError() <<
"unexpected symbol type for " << symbol;
5482 return mlir::LLVM::AddressOfOp::create(
5483 rewriter, op->getLoc(),
5484 mlir::LLVM::LLVMPointerType::get(op->getContext()), nameAttr.getValue());
5487mlir::LogicalResult CIRToLLVMVTableAddrPointOpLowering::matchAndRewrite(
5488 cir::VTableAddrPointOp op, OpAdaptor adaptor,
5489 mlir::ConversionPatternRewriter &rewriter)
const {
5490 const mlir::TypeConverter *converter = getTypeConverter();
5491 mlir::Type targetType = converter->convertType(op.getType());
5494 mlir::Value symAddr =
5495 getValueForVTableSymbol(op, rewriter, symbolTables, converter,
5496 preConversionTypes, op.getNameAttr(), eltType);
5498 return mlir::failure();
5501 0, op.getAddressPointAttr().getIndex(),
5502 op.getAddressPointAttr().getOffset()};
5504 assert(eltType &&
"Shouldn't ever be missing an eltType here");
5505 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
5506 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
5507 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, targetType, eltType,
5508 symAddr, offsets, inboundsNuw);
5509 return mlir::success();
5512mlir::LogicalResult CIRToLLVMVTableGetVPtrOpLowering::matchAndRewrite(
5513 cir::VTableGetVPtrOp op, OpAdaptor adaptor,
5514 mlir::ConversionPatternRewriter &rewriter)
const {
5518 mlir::Value srcVal = adaptor.getSrc();
5519 rewriter.replaceOp(op, srcVal);
5520 return mlir::success();
5523mlir::LogicalResult CIRToLLVMVTableGetVirtualFnAddrOpLowering::matchAndRewrite(
5524 cir::VTableGetVirtualFnAddrOp op, OpAdaptor adaptor,
5525 mlir::ConversionPatternRewriter &rewriter)
const {
5526 mlir::Type targetType = getTypeConverter()->convertType(op.getType());
5529 auto eltType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
5532 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
5533 op, targetType, eltType, adaptor.getVptr(), offsets,
5534 mlir::LLVM::GEPNoWrapFlags::inbounds);
5535 return mlir::success();
5538mlir::LogicalResult CIRToLLVMVTTAddrPointOpLowering::matchAndRewrite(
5539 cir::VTTAddrPointOp op, OpAdaptor adaptor,
5540 mlir::ConversionPatternRewriter &rewriter)
const {
5541 const mlir::Type resultType = getTypeConverter()->convertType(op.getType());
5546 mlir::Value llvmAddr = adaptor.getSymAddr();
5548 if (op.getSymAddr()) {
5549 if (op.getOffset() == 0) {
5550 rewriter.replaceOp(op, {llvmAddr});
5551 return mlir::success();
5554 offsets.push_back(adaptor.getOffset());
5555 eltType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
5559 preConversionTypes, op.getNameAttr(), eltType);
5561 return mlir::failure();
5562 assert(eltType &&
"Shouldn't ever be missing an eltType here");
5563 offsets.push_back(0);
5564 offsets.push_back(adaptor.getOffset());
5566 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
5567 op, resultType, eltType, llvmAddr, offsets,
5568 mlir::LLVM::GEPNoWrapFlags::inbounds);
5569 return mlir::success();
5572mlir::LogicalResult CIRToLLVMVecCreateOpLowering::matchAndRewrite(
5573 cir::VecCreateOp op, OpAdaptor adaptor,
5574 mlir::ConversionPatternRewriter &rewriter)
const {
5577 const cir::VectorType vecTy = op.getType();
5578 const mlir::Type llvmTy = typeConverter->convertType(vecTy);
5579 const mlir::Location loc = op.getLoc();
5580 mlir::Value result = mlir::LLVM::PoisonOp::create(rewriter, loc, llvmTy);
5581 const uint64_t vectorSize = vecTy.getFixedSize();
5582 assert(vectorSize == op.getElements().size() &&
5583 "cir.vec.create op count doesn't match vector type elements count");
5585 for (uint64_t i = 0; i < vectorSize; ++i) {
5586 const mlir::Value indexValue =
5587 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
5588 result = mlir::LLVM::InsertElementOp::create(
5589 rewriter, loc, result, adaptor.getElements()[i], indexValue);
5592 rewriter.replaceOp(op, result);
5593 return mlir::success();
5596mlir::LogicalResult CIRToLLVMVecExtractOpLowering::matchAndRewrite(
5597 cir::VecExtractOp op, OpAdaptor adaptor,
5598 mlir::ConversionPatternRewriter &rewriter)
const {
5599 rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractElementOp>(
5600 op, adaptor.getVec(), adaptor.getIndex());
5601 return mlir::success();
5604mlir::LogicalResult CIRToLLVMVecInsertOpLowering::matchAndRewrite(
5605 cir::VecInsertOp op, OpAdaptor adaptor,
5606 mlir::ConversionPatternRewriter &rewriter)
const {
5607 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertElementOp>(
5608 op, adaptor.getVec(), adaptor.getValue(), adaptor.getIndex());
5609 return mlir::success();
5612template <
typename LLVMOp,
typename CIROp>
5613static mlir::LogicalResult
5615 const mlir::TypeConverter &typeConverter,
5616 mlir::ConversionPatternRewriter &rewriter) {
5617 mlir::Type resultTy = typeConverter.convertType(op.getType());
5618 mlir::LLVM::FastmathFlags fastmathFlags{};
5619 if (std::optional<cir::FastMathFlags> fastmath = op.getFastmathFlags())
5622 typename LLVMOp::Properties properties =
5624 properties.setFastmathFlags(
5625 mlir::LLVM::FastmathFlagsAttr::get(op.getContext(), fastmathFlags));
5626 rewriter.replaceOpWithNewOp<LLVMOp>(op, mlir::TypeRange{resultTy},
5627 adaptor.getOperands(), properties);
5629 return mlir::success();
5632mlir::LogicalResult CIRToLLVMVecReduceFAddOpLowering::matchAndRewrite(
5633 cir::VecReduceFAddOp op, OpAdaptor adaptor,
5634 mlir::ConversionPatternRewriter &rewriter)
const {
5635 return lowerFPVectorReduction<mlir::LLVM::vector_reduce_fadd>(
5636 op, adaptor, *getTypeConverter(), rewriter);
5639mlir::LogicalResult CIRToLLVMVecReduceFMulOpLowering::matchAndRewrite(
5640 cir::VecReduceFMulOp op, OpAdaptor adaptor,
5641 mlir::ConversionPatternRewriter &rewriter)
const {
5642 return lowerFPVectorReduction<mlir::LLVM::vector_reduce_fmul>(
5643 op, adaptor, *getTypeConverter(), rewriter);
5646mlir::LogicalResult CIRToLLVMVecReduceFMaxOpLowering::matchAndRewrite(
5647 cir::VecReduceFMaxOp op, OpAdaptor adaptor,
5648 mlir::ConversionPatternRewriter &rewriter)
const {
5649 return lowerFPVectorReduction<mlir::LLVM::vector_reduce_fmax>(
5650 op, adaptor, *getTypeConverter(), rewriter);
5653mlir::LogicalResult CIRToLLVMVecReduceFMinOpLowering::matchAndRewrite(
5654 cir::VecReduceFMinOp op, OpAdaptor adaptor,
5655 mlir::ConversionPatternRewriter &rewriter)
const {
5656 return lowerFPVectorReduction<mlir::LLVM::vector_reduce_fmin>(
5657 op, adaptor, *getTypeConverter(), rewriter);
5660mlir::LogicalResult CIRToLLVMVecCmpOpLowering::matchAndRewrite(
5661 cir::VecCmpOp op, OpAdaptor adaptor,
5662 mlir::ConversionPatternRewriter &rewriter)
const {
5663 mlir::Type elementType = op.getLhs().getType().getElementType();
5664 mlir::Value bitResult;
5665 if (
auto intType = mlir::dyn_cast<cir::IntType>(elementType)) {
5666 bitResult = mlir::LLVM::ICmpOp::create(
5667 rewriter, op.getLoc(),
5669 adaptor.getLhs(), adaptor.getRhs());
5670 }
else if (
auto boolType = mlir::dyn_cast<cir::BoolType>(elementType)) {
5671 bitResult = mlir::LLVM::ICmpOp::create(
5672 rewriter, op.getLoc(),
5674 adaptor.getLhs(), adaptor.getRhs());
5675 }
else if (mlir::isa<cir::FPTypeInterface>(elementType)) {
5676 if (cir::FenvAttr fenv = op.getFenvAttr()) {
5677 llvm::ElementCount size = op.getLhs().getType().getSize();
5678 auto i1VecTy = mlir::VectorType::get(
5679 size.getKnownMinValue(), rewriter.getI1Type(), {size.isScalable()});
5681 adaptor.getLhs(), adaptor.getRhs(),
5682 op.getKind(), fenv, i1VecTy)
5685 bitResult = mlir::LLVM::FCmpOp::create(
5687 adaptor.getLhs(), adaptor.getRhs());
5690 return op.emitError() <<
"unsupported type for VecCmpOp: " << elementType;
5696 mlir::Type vecElemTy = op.getType().getElementType();
5697 if (isa<cir::IntType>(vecElemTy) &&
5698 cast<cir::IntType>(vecElemTy).getWidth() > 1)
5699 rewriter.replaceOpWithNewOp<mlir::LLVM::SExtOp>(
5700 op, typeConverter->convertType(op.getType()), bitResult);
5702 rewriter.replaceOp(op, bitResult);
5703 return mlir::success();
5706mlir::LogicalResult CIRToLLVMVecSplatOpLowering::matchAndRewrite(
5707 cir::VecSplatOp op, OpAdaptor adaptor,
5708 mlir::ConversionPatternRewriter &rewriter)
const {
5714 mlir::Type llvmTy = typeConverter->convertType(op.getType());
5715 mlir::Location loc = op.getLoc();
5716 mlir::Value poison = mlir::LLVM::PoisonOp::create(rewriter, loc, llvmTy);
5718 mlir::Value elementValue = adaptor.getValue();
5719 if (elementValue.getDefiningOp<mlir::LLVM::PoisonOp>()) {
5722 rewriter.replaceOp(op, poison);
5723 return mlir::success();
5726 if (
auto constValue = elementValue.getDefiningOp<mlir::LLVM::ConstantOp>()) {
5727 if (
auto intAttr = dyn_cast<mlir::IntegerAttr>(constValue.getValue())) {
5728 mlir::DenseIntElementsAttr denseVec = mlir::DenseIntElementsAttr::get(
5729 mlir::cast<mlir::ShapedType>(llvmTy), intAttr.getValue());
5730 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
5731 op, denseVec.getType(), denseVec);
5732 return mlir::success();
5735 if (
auto fpAttr = dyn_cast<mlir::FloatAttr>(constValue.getValue())) {
5736 mlir::DenseFPElementsAttr denseVec = mlir::DenseFPElementsAttr::get(
5737 mlir::cast<mlir::ShapedType>(llvmTy), fpAttr.getValue());
5738 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
5739 op, denseVec.getType(), denseVec);
5740 return mlir::success();
5744 mlir::Value indexValue =
5745 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), 0);
5746 mlir::Value oneElement = mlir::LLVM::InsertElementOp::create(
5747 rewriter, loc, poison, elementValue, indexValue);
5749 mlir::cast<mlir::VectorType>(llvmTy).getNumElements(), 0);
5750 rewriter.replaceOpWithNewOp<mlir::LLVM::ShuffleVectorOp>(op, oneElement,
5751 poison, zeroValues);
5752 return mlir::success();
5755mlir::LogicalResult CIRToLLVMVecShuffleOpLowering::matchAndRewrite(
5756 cir::VecShuffleOp op, OpAdaptor adaptor,
5757 mlir::ConversionPatternRewriter &rewriter)
const {
5763 op.getIndices().begin(), op.getIndices().end(),
5764 std::back_inserter(indices), [](mlir::Attribute intAttr) {
5765 return mlir::cast<cir::IntAttr>(intAttr).getValue().getSExtValue();
5767 rewriter.replaceOpWithNewOp<mlir::LLVM::ShuffleVectorOp>(
5768 op, adaptor.getVec1(), adaptor.getVec2(), indices);
5769 return mlir::success();
5772mlir::LogicalResult CIRToLLVMVecShuffleDynamicOpLowering::matchAndRewrite(
5773 cir::VecShuffleDynamicOp op, OpAdaptor adaptor,
5774 mlir::ConversionPatternRewriter &rewriter)
const {
5786 mlir::Location loc = op.getLoc();
5787 mlir::Value input = adaptor.getVec();
5788 mlir::Type llvmIndexVecType =
5789 getTypeConverter()->convertType(op.getIndices().getType());
5790 mlir::Type llvmIndexType = getTypeConverter()->convertType(
5791 op.getIndices().getType().getElementType());
5792 uint64_t numElements = op.getVec().getType().getFixedSize();
5794 uint64_t maskBits = llvm::NextPowerOf2(numElements - 1) - 1;
5795 mlir::Value maskValue = mlir::LLVM::ConstantOp::create(
5796 rewriter, loc, llvmIndexType,
5797 rewriter.getIntegerAttr(llvmIndexType, maskBits));
5798 mlir::Value maskVector =
5799 mlir::LLVM::UndefOp::create(rewriter, loc, llvmIndexVecType);
5801 for (uint64_t i = 0; i < numElements; ++i) {
5802 mlir::Value idxValue =
5803 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
5804 maskVector = mlir::LLVM::InsertElementOp::create(rewriter, loc, maskVector,
5805 maskValue, idxValue);
5808 mlir::Value maskedIndices = mlir::LLVM::AndOp::create(
5809 rewriter, loc, llvmIndexVecType, adaptor.getIndices(), maskVector);
5810 mlir::Value result = mlir::LLVM::UndefOp::create(
5811 rewriter, loc, getTypeConverter()->convertType(op.getVec().getType()));
5812 for (uint64_t i = 0; i < numElements; ++i) {
5813 mlir::Value iValue =
5814 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
5815 mlir::Value indexValue = mlir::LLVM::ExtractElementOp::create(
5816 rewriter, loc, maskedIndices, iValue);
5817 mlir::Value valueAtIndex =
5818 mlir::LLVM::ExtractElementOp::create(rewriter, loc, input, indexValue);
5819 result = mlir::LLVM::InsertElementOp::create(rewriter, loc, result,
5820 valueAtIndex, iValue);
5822 rewriter.replaceOp(op, result);
5823 return mlir::success();
5826mlir::LogicalResult CIRToLLVMVecTernaryOpLowering::matchAndRewrite(
5827 cir::VecTernaryOp op, OpAdaptor adaptor,
5828 mlir::ConversionPatternRewriter &rewriter)
const {
5829 mlir::Value bitVec = adaptor.getCond();
5831 if (!isa<cir::BoolType>(op.getCond().getType().getElementType())) {
5833 bitVec = mlir::LLVM::ICmpOp::create(
5834 rewriter, op.getLoc(), mlir::LLVM::ICmpPredicate::ne, adaptor.getCond(),
5835 mlir::LLVM::ZeroOp::create(
5836 rewriter, op.getCond().getLoc(),
5837 typeConverter->convertType(op.getCond().getType())));
5840 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(
5841 op, bitVec, adaptor.getLhs(), adaptor.getRhs());
5842 return mlir::success();
5848 mlir::Location loc, cir::MatrixType matrixTy,
5849 mlir::Value rowIdx, mlir::Value columnIdx) {
5850 rowIdx =
createIntCast(rewriter, rowIdx, rewriter.getI64Type(),
false);
5851 columnIdx =
createIntCast(rewriter, columnIdx, rewriter.getI64Type(),
false);
5852 mlir::Type indexTy = rowIdx.getType();
5853 mlir::Value numRows = mlir::LLVM::ConstantOp::create(
5854 rewriter, loc, indexTy,
5855 rewriter.getIntegerAttr(indexTy, matrixTy.getNumRows()));
5856 mlir::Value flatIndex = mlir::LLVM::MulOp::create(
5857 rewriter, loc, {columnIdx, numRows}, {},
5859 return mlir::LLVM::AddOp::create(rewriter, loc, flatIndex, rowIdx,
5863mlir::LogicalResult CIRToLLVMMatrixExtractOpLowering::matchAndRewrite(
5864 cir::MatrixExtractOp op, OpAdaptor adaptor,
5865 mlir::ConversionPatternRewriter &rewriter)
const {
5866 mlir::Value flatIndex =
5867 computeMatrixFlatIndex(rewriter, op.getLoc(), op.getMatrix().getType(),
5868 adaptor.getRowIdx(), adaptor.getColumnIdx());
5869 rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractElementOp>(
5870 op, adaptor.getMatrix(), flatIndex);
5871 return mlir::success();
5874mlir::LogicalResult CIRToLLVMMatrixExtractRowOpLowering::matchAndRewrite(
5875 cir::MatrixExtractRowOp op, OpAdaptor adaptor,
5876 mlir::ConversionPatternRewriter &rewriter)
const {
5877 cir::MatrixType matrixTy = op.getMatrix().getType();
5878 mlir::Type elementType =
5879 typeConverter->convertType(matrixTy.getElementType());
5880 mlir::Type resultTy =
5881 mlir::VectorType::get(matrixTy.getNumColumns(), elementType);
5882 mlir::Value rowVec =
5883 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), resultTy);
5885 for (
unsigned col = 0; col != matrixTy.getNumColumns(); ++col) {
5886 mlir::Value columnIdx = mlir::LLVM::ConstantOp::create(
5887 rewriter, op.getLoc(), rewriter.getI32Type(),
5888 rewriter.getIntegerAttr(rewriter.getI32Type(), col));
5889 mlir::Value flatIndex = computeMatrixFlatIndex(
5890 rewriter, op.getLoc(), matrixTy, adaptor.getRowIdx(), columnIdx);
5892 auto element = mlir::LLVM::ExtractElementOp::create(
5893 rewriter, op->getLoc(), elementType, adaptor.getMatrix(), flatIndex);
5894 rowVec = mlir::LLVM::InsertElementOp::create(rewriter, op->getLoc(), rowVec,
5895 element, columnIdx);
5897 rewriter.replaceOp(op, rowVec);
5898 return mlir::success();
5901mlir::LogicalResult CIRToLLVMMatrixInsertOpLowering::matchAndRewrite(
5902 cir::MatrixInsertOp op, OpAdaptor adaptor,
5903 mlir::ConversionPatternRewriter &rewriter)
const {
5904 mlir::Value flatIndex =
5906 adaptor.getRowIdx(), adaptor.getColumnIdx());
5907 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertElementOp>(
5908 op, adaptor.getMatrix(), adaptor.getValue(), flatIndex);
5909 return mlir::success();
5912mlir::LogicalResult CIRToLLVMMatrixColumnMajorLoadOpLowering::matchAndRewrite(
5913 cir::MatrixColumnMajorLoadOp op, OpAdaptor adaptor,
5914 mlir::ConversionPatternRewriter &rewriter)
const {
5915 cir::MatrixType resultMatrixTy = op.getResult().getType();
5916 mlir::Type resultTy = typeConverter->convertType(resultMatrixTy);
5917 rewriter.replaceOpWithNewOp<mlir::LLVM::MatrixColumnMajorLoadOp>(
5918 op, resultTy, adaptor.getValue(), adaptor.getStride(),
5919 rewriter.getBoolAttr(op.getIsVolatile()),
5920 rewriter.getI32IntegerAttr(resultMatrixTy.getNumRows()),
5921 rewriter.getI32IntegerAttr(resultMatrixTy.getNumColumns()));
5922 return mlir::success();
5925mlir::LogicalResult CIRToLLVMMatrixColumnMajorStoreOpLowering::matchAndRewrite(
5926 cir::MatrixColumnMajorStoreOp op, OpAdaptor adaptor,
5927 mlir::ConversionPatternRewriter &rewriter)
const {
5928 cir::MatrixType matrixTy = op.getMatrix().getType();
5929 rewriter.replaceOpWithNewOp<mlir::LLVM::MatrixColumnMajorStoreOp>(
5930 op, adaptor.getMatrix(), adaptor.getValue(), adaptor.getStride(),
5931 rewriter.getBoolAttr(op.getIsVolatile()),
5932 rewriter.getI32IntegerAttr(matrixTy.getNumRows()),
5933 rewriter.getI32IntegerAttr(matrixTy.getNumColumns()));
5934 return mlir::success();
5937mlir::LogicalResult CIRToLLVMMatrixMultiplyOpLowering::matchAndRewrite(
5938 cir::MatrixMultiplyOp op, OpAdaptor adaptor,
5939 mlir::ConversionPatternRewriter &rewriter)
const {
5940 cir::MatrixType lhsTy = op.getLhs().getType();
5941 cir::MatrixType rhsTy = op.getRhs().getType();
5942 mlir::Type resultTy = typeConverter->convertType(op.getResult().getType());
5943 rewriter.replaceOpWithNewOp<mlir::LLVM::MatrixMultiplyOp>(
5944 op, resultTy, adaptor.getLhs(), adaptor.getRhs(), lhsTy.getNumRows(),
5945 lhsTy.getNumColumns(), rhsTy.getNumColumns());
5946 return mlir::success();
5949mlir::LogicalResult CIRToLLVMMatrixTransposeOpLowering::matchAndRewrite(
5950 cir::MatrixTransposeOp op, OpAdaptor adaptor,
5951 mlir::ConversionPatternRewriter &rewriter)
const {
5952 cir::MatrixType resultMatrixTy = op.getValue().getType();
5953 mlir::Type resultTy = typeConverter->convertType(resultMatrixTy);
5954 rewriter.replaceOpWithNewOp<mlir::LLVM::MatrixTransposeOp>(
5955 op, resultTy, adaptor.getValue(), resultMatrixTy.getNumRows(),
5956 resultMatrixTy.getNumColumns());
5957 return mlir::success();
5960mlir::LogicalResult CIRToLLVMComplexCreateOpLowering::matchAndRewrite(
5961 cir::ComplexCreateOp op, OpAdaptor adaptor,
5962 mlir::ConversionPatternRewriter &rewriter)
const {
5963 mlir::Type complexLLVMTy =
5964 getTypeConverter()->convertType(op.getResult().getType());
5965 auto initialComplex =
5966 mlir::LLVM::UndefOp::create(rewriter, op->getLoc(), complexLLVMTy);
5968 auto realComplex = mlir::LLVM::InsertValueOp::create(
5969 rewriter, op->getLoc(), initialComplex, adaptor.getReal(),
5972 auto complex = mlir::LLVM::InsertValueOp::create(
5973 rewriter, op->getLoc(), realComplex, adaptor.getImag(),
5976 rewriter.replaceOp(op, complex);
5977 return mlir::success();
5980mlir::LogicalResult CIRToLLVMComplexRealOpLowering::matchAndRewrite(
5981 cir::ComplexRealOp op, OpAdaptor adaptor,
5982 mlir::ConversionPatternRewriter &rewriter)
const {
5983 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
5984 mlir::Value operand = adaptor.getOperand();
5985 if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) {
5986 operand = mlir::LLVM::ExtractValueOp::create(
5987 rewriter, op.getLoc(), resultLLVMTy, operand,
5990 rewriter.replaceOp(op, operand);
5991 return mlir::success();
5994mlir::LogicalResult CIRToLLVMComplexImagOpLowering::matchAndRewrite(
5995 cir::ComplexImagOp op, OpAdaptor adaptor,
5996 mlir::ConversionPatternRewriter &rewriter)
const {
5997 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
5998 mlir::Value operand = adaptor.getOperand();
5999 mlir::Location loc = op.getLoc();
6001 if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) {
6002 operand = mlir::LLVM::ExtractValueOp::create(
6005 mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(resultLLVMTy);
6007 mlir::LLVM::ConstantOp::create(rewriter, loc, resultLLVMTy, zeroAttr);
6010 rewriter.replaceOp(op, operand);
6011 return mlir::success();
6014mlir::LogicalResult CIRToLLVMComplexAddOpLowering::matchAndRewrite(
6015 cir::ComplexAddOp op, OpAdaptor adaptor,
6016 mlir::ConversionPatternRewriter &rewriter)
const {
6017 mlir::Value lhs = adaptor.getLhs();
6018 mlir::Value rhs = adaptor.getRhs();
6019 mlir::Location loc = op.getLoc();
6021 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
6022 mlir::Type complexElemTy =
6023 getTypeConverter()->convertType(
complexType.getElementType());
6024 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
6026 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
6028 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
6030 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
6033 mlir::Value newReal;
6034 mlir::Value newImag;
6035 if (complexElemTy.isInteger()) {
6036 newReal = mlir::LLVM::AddOp::create(rewriter, loc, complexElemTy, lhsReal,
6038 newImag = mlir::LLVM::AddOp::create(rewriter, loc, complexElemTy, lhsImag,
6043 newReal = mlir::LLVM::FAddOp::create(rewriter, loc, complexElemTy, lhsReal,
6045 newImag = mlir::LLVM::FAddOp::create(rewriter, loc, complexElemTy, lhsImag,
6049 mlir::Type complexLLVMTy =
6050 getTypeConverter()->convertType(op.getResult().getType());
6051 auto initialComplex =
6052 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), complexLLVMTy);
6054 auto realComplex = mlir::LLVM::InsertValueOp::create(
6055 rewriter, op->getLoc(), initialComplex, newReal,
ArrayRef(
int64_t{0}));
6057 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
6060 return mlir::success();
6063mlir::LogicalResult CIRToLLVMComplexSubOpLowering::matchAndRewrite(
6064 cir::ComplexSubOp op, OpAdaptor adaptor,
6065 mlir::ConversionPatternRewriter &rewriter)
const {
6066 mlir::Value lhs = adaptor.getLhs();
6067 mlir::Value rhs = adaptor.getRhs();
6068 mlir::Location loc = op.getLoc();
6070 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
6071 mlir::Type complexElemTy =
6072 getTypeConverter()->convertType(
complexType.getElementType());
6073 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
6075 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
6077 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
6079 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
6082 mlir::Value newReal;
6083 mlir::Value newImag;
6084 if (complexElemTy.isInteger()) {
6085 newReal = mlir::LLVM::SubOp::create(rewriter, loc, complexElemTy, lhsReal,
6087 newImag = mlir::LLVM::SubOp::create(rewriter, loc, complexElemTy, lhsImag,
6092 newReal = mlir::LLVM::FSubOp::create(rewriter, loc, complexElemTy, lhsReal,
6094 newImag = mlir::LLVM::FSubOp::create(rewriter, loc, complexElemTy, lhsImag,
6098 mlir::Type complexLLVMTy =
6099 getTypeConverter()->convertType(op.getResult().getType());
6100 auto initialComplex =
6101 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), complexLLVMTy);
6103 auto realComplex = mlir::LLVM::InsertValueOp::create(
6104 rewriter, op->getLoc(), initialComplex, newReal,
ArrayRef(
int64_t{0}));
6106 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
6109 return mlir::success();
6112mlir::LogicalResult CIRToLLVMComplexFAddOpLowering::matchAndRewrite(
6113 cir::ComplexFAddOp op, OpAdaptor adaptor,
6114 mlir::ConversionPatternRewriter &rewriter)
const {
6115 mlir::Value lhs = adaptor.getLhs();
6116 mlir::Value rhs = adaptor.getRhs();
6117 mlir::Location loc = op.getLoc();
6119 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
6120 mlir::Type complexElemTy =
6121 getTypeConverter()->convertType(
complexType.getElementType());
6122 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
6124 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
6126 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
6128 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
6132 mlir::Value newReal;
6133 mlir::Value newImag;
6134 if (cir::FenvAttr fenv = op.getFenvAttr()) {
6136 rewriter, loc, {lhsReal, rhsReal}, complexElemTy, fenv,
6141 rewriter, loc, {lhsImag, rhsImag}, complexElemTy, fenv,
6145 newReal = mlir::LLVM::FAddOp::create(rewriter, loc, complexElemTy, lhsReal,
6147 newImag = mlir::LLVM::FAddOp::create(rewriter, loc, complexElemTy, lhsImag,
6151 mlir::Type complexLLVMTy =
6152 getTypeConverter()->convertType(op.getResult().getType());
6153 auto initialComplex =
6154 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), complexLLVMTy);
6156 auto realComplex = mlir::LLVM::InsertValueOp::create(
6157 rewriter, op->getLoc(), initialComplex, newReal,
ArrayRef(
int64_t{0}));
6159 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
6162 return mlir::success();
6165mlir::LogicalResult CIRToLLVMComplexFSubOpLowering::matchAndRewrite(
6166 cir::ComplexFSubOp op, OpAdaptor adaptor,
6167 mlir::ConversionPatternRewriter &rewriter)
const {
6168 mlir::Value lhs = adaptor.getLhs();
6169 mlir::Value rhs = adaptor.getRhs();
6170 mlir::Location loc = op.getLoc();
6172 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
6173 mlir::Type complexElemTy =
6174 getTypeConverter()->convertType(
complexType.getElementType());
6175 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
6177 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
6179 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
6181 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
6185 mlir::Value newReal;
6186 mlir::Value newImag;
6187 if (cir::FenvAttr fenv = op.getFenvAttr()) {
6189 rewriter, loc, {lhsReal, rhsReal}, complexElemTy, fenv,
6194 rewriter, loc, {lhsImag, rhsImag}, complexElemTy, fenv,
6198 newReal = mlir::LLVM::FSubOp::create(rewriter, loc, complexElemTy, lhsReal,
6200 newImag = mlir::LLVM::FSubOp::create(rewriter, loc, complexElemTy, lhsImag,
6204 mlir::Type complexLLVMTy =
6205 getTypeConverter()->convertType(op.getResult().getType());
6206 auto initialComplex =
6207 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), complexLLVMTy);
6209 auto realComplex = mlir::LLVM::InsertValueOp::create(
6210 rewriter, op->getLoc(), initialComplex, newReal,
ArrayRef(
int64_t{0}));
6212 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
6215 return mlir::success();
6219 mlir::MLIRContext *context,
6220 unsigned &storageSize) {
6221 return TypeSwitch<mlir::Type, mlir::IntegerType>(storageType)
6222 .Case<cir::ArrayType>([&](cir::ArrayType atTy) {
6223 storageSize = atTy.getSize() * 8;
6224 return mlir::IntegerType::get(context, storageSize);
6226 .Case<cir::IntType>([&](cir::IntType intTy) {
6227 storageSize = intTy.getWidth();
6228 return mlir::IntegerType::get(context, storageSize);
6230 .Default([](mlir::Type) -> mlir::IntegerType {
6232 "Either ArrayType or IntType expected for bitfields storage");
6236mlir::LogicalResult CIRToLLVMSetBitfieldOpLowering::matchAndRewrite(
6237 cir::SetBitfieldOp op, OpAdaptor adaptor,
6238 mlir::ConversionPatternRewriter &rewriter)
const {
6239 mlir::OpBuilder::InsertionGuard guard(rewriter);
6240 rewriter.setInsertionPoint(op);
6242 cir::BitfieldInfoAttr info = op.getBitfieldInfo();
6243 uint64_t size = info.getSize();
6244 uint64_t offset = info.getOffset();
6245 mlir::Type storageType = info.getStorageType();
6246 mlir::MLIRContext *context = storageType.getContext();
6248 unsigned storageSize = 0;
6250 mlir::IntegerType intType =
6251 computeBitfieldIntType(storageType, context, storageSize);
6253 mlir::Value srcVal = createIntCast(rewriter, adaptor.getSrc(), intType);
6254 unsigned srcWidth = storageSize;
6255 mlir::Value resultVal = srcVal;
6257 if (storageSize != size) {
6258 assert(storageSize > size &&
"Invalid bitfield size.");
6260 mlir::Value val = mlir::LLVM::LoadOp::create(
6261 rewriter, op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(),
6262 op.getIsVolatile());
6265 createAnd(rewriter, srcVal, llvm::APInt::getLowBitsSet(srcWidth, size));
6267 srcVal =
createShL(rewriter, srcVal, offset);
6271 ~llvm::APInt::getBitsSet(srcWidth, offset, offset + size));
6274 srcVal = mlir::LLVM::OrOp::create(rewriter, op.getLoc(), val, srcVal);
6277 mlir::LLVM::StoreOp::create(rewriter, op.getLoc(), srcVal, adaptor.getAddr(),
6278 op.getAlignment(), op.getIsVolatile());
6280 mlir::Type resultTy = getTypeConverter()->convertType(op.getType());
6282 if (info.getIsSigned()) {
6283 assert(size <= storageSize);
6284 unsigned highBits = storageSize - size;
6287 resultVal =
createShL(rewriter, resultVal, highBits);
6288 resultVal =
createAShR(rewriter, resultVal, highBits);
6293 mlir::cast<mlir::IntegerType>(resultTy),
6294 info.getIsSigned());
6296 rewriter.replaceOp(op, resultVal);
6297 return mlir::success();
6300mlir::LogicalResult CIRToLLVMComplexImagPtrOpLowering::matchAndRewrite(
6301 cir::ComplexImagPtrOp op, OpAdaptor adaptor,
6302 mlir::ConversionPatternRewriter &rewriter)
const {
6303 cir::PointerType operandTy = op.getOperand().getType();
6304 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
6307 mlir::Type elementLLVMTy =
6308 getTypeConverter()->convertType(operandTy.getPointee());
6310 mlir::LLVM::GEPArg gepIndices[2] = {{0}, {1}};
6311 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
6312 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
6313 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
6314 op, resultLLVMTy, elementLLVMTy, adaptor.getOperand(), gepIndices,
6316 return mlir::success();
6319mlir::LogicalResult CIRToLLVMComplexRealPtrOpLowering::matchAndRewrite(
6320 cir::ComplexRealPtrOp op, OpAdaptor adaptor,
6321 mlir::ConversionPatternRewriter &rewriter)
const {
6322 cir::PointerType operandTy = op.getOperand().getType();
6323 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
6326 mlir::Type elementLLVMTy =
6327 getTypeConverter()->convertType(operandTy.getPointee());
6329 mlir::LLVM::GEPArg gepIndices[2] = {0, 0};
6330 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
6331 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
6332 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
6333 op, resultLLVMTy, elementLLVMTy, adaptor.getOperand(), gepIndices,
6335 return mlir::success();
6338mlir::LogicalResult CIRToLLVMGetBitfieldOpLowering::matchAndRewrite(
6339 cir::GetBitfieldOp op, OpAdaptor adaptor,
6340 mlir::ConversionPatternRewriter &rewriter)
const {
6342 mlir::OpBuilder::InsertionGuard guard(rewriter);
6343 rewriter.setInsertionPoint(op);
6345 cir::BitfieldInfoAttr
info = op.getBitfieldInfo();
6346 uint64_t size =
info.getSize();
6347 uint64_t offset =
info.getOffset();
6348 mlir::Type storageType =
info.getStorageType();
6349 mlir::MLIRContext *context = storageType.getContext();
6350 unsigned storageSize = 0;
6352 mlir::IntegerType intType =
6355 mlir::Value val = mlir::LLVM::LoadOp::create(
6356 rewriter, op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(),
6357 op.getIsVolatile());
6358 val = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), intType, val);
6360 if (
info.getIsSigned()) {
6361 assert(
static_cast<unsigned>(offset + size) <= storageSize);
6362 unsigned highBits = storageSize - offset - size;
6363 val =
createShL(rewriter, val, highBits);
6364 val =
createAShR(rewriter, val, offset + highBits);
6368 if (
static_cast<unsigned>(offset) + size < storageSize)
6370 llvm::APInt::getLowBitsSet(storageSize, size));
6373 mlir::Type resTy = getTypeConverter()->convertType(op.getType());
6375 rewriter, val, mlir::cast<mlir::IntegerType>(resTy),
info.getIsSigned());
6376 rewriter.replaceOp(op, newOp);
6377 return mlir::success();
6380mlir::LogicalResult CIRToLLVMInlineAsmOpLowering::matchAndRewrite(
6381 cir::InlineAsmOp op, OpAdaptor adaptor,
6382 mlir::ConversionPatternRewriter &rewriter)
const {
6384 if (op.getNumResults()) {
6385 llResTy = getTypeConverter()->convertType(op.getType(0));
6390 cir::AsmFlavor dialect = op.getAsmFlavor();
6391 mlir::LLVM::AsmDialect llDialect = dialect == cir::AsmFlavor::x86_att
6392 ? mlir::LLVM::AsmDialect::AD_ATT
6393 : mlir::LLVM::AsmDialect::AD_Intel;
6396 StringRef llvmAttrName = mlir::LLVM::InlineAsmOp::getElementTypeAttrName();
6402 if (!op.getNumResults())
6403 opAttrs.push_back(mlir::Attribute());
6407 for (
auto const &[llvmOp, cirOp] :
6408 zip(adaptor.getAsmOperands(), op.getAsmOperands())) {
6409 append_range(llvmOperands, llvmOp);
6410 append_range(cirOperands, cirOp);
6415 for (
auto const &[cirOpAttr, cirOp] :
6416 zip(op.getOperandAttrs(), cirOperands)) {
6417 if (!mlir::isa<mlir::UnitAttr>(cirOpAttr)) {
6418 opAttrs.push_back(mlir::Attribute());
6423 cir::PointerType typ = mlir::cast<cir::PointerType>(cirOp.getType());
6424 mlir::Type elementTy =
6428 mlir::TypeAttr typAttr = mlir::TypeAttr::get(elementTy);
6430 attrs.push_back(rewriter.getNamedAttr(llvmAttrName, typAttr));
6431 mlir::DictionaryAttr newDict = rewriter.getDictionaryAttr(attrs);
6432 opAttrs.push_back(newDict);
6435 rewriter.replaceOpWithNewOp<mlir::LLVM::InlineAsmOp>(
6436 op, llResTy, llvmOperands, op.getAsmStringAttr(), op.getConstraintsAttr(),
6437 op.getSideEffectsAttr(),
6440 mlir::LLVM::TailCallKindAttr::get(
6441 getContext(), mlir::LLVM::tailcallkind::TailCallKind::None),
6443 mlir::LLVM::AsmDialectAttr::get(getContext(), llDialect),
6444 rewriter.getArrayAttr(opAttrs));
6446 return mlir::success();
6449mlir::LogicalResult CIRToLLVMVAStartOpLowering::matchAndRewrite(
6450 cir::VAStartOp op, OpAdaptor adaptor,
6451 mlir::ConversionPatternRewriter &rewriter)
const {
6452 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
6453 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
6454 adaptor.getArgList());
6455 rewriter.replaceOpWithNewOp<mlir::LLVM::VaStartOp>(op, vaList);
6456 return mlir::success();
6459mlir::LogicalResult CIRToLLVMVAEndOpLowering::matchAndRewrite(
6460 cir::VAEndOp op, OpAdaptor adaptor,
6461 mlir::ConversionPatternRewriter &rewriter)
const {
6462 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
6463 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
6464 adaptor.getArgList());
6465 rewriter.replaceOpWithNewOp<mlir::LLVM::VaEndOp>(op, vaList);
6466 return mlir::success();
6469mlir::LogicalResult CIRToLLVMVACopyOpLowering::matchAndRewrite(
6470 cir::VACopyOp op, OpAdaptor adaptor,
6471 mlir::ConversionPatternRewriter &rewriter)
const {
6472 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
6473 auto dstList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
6474 adaptor.getDstList());
6475 auto srcList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
6476 adaptor.getSrcList());
6477 rewriter.replaceOpWithNewOp<mlir::LLVM::VaCopyOp>(op, dstList, srcList);
6478 return mlir::success();
6481mlir::LogicalResult CIRToLLVMVAArgOpLowering::matchAndRewrite(
6482 cir::VAArgOp op, OpAdaptor adaptor,
6483 mlir::ConversionPatternRewriter &rewriter)
const {
6485 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
6486 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
6487 adaptor.getArgList());
6489 mlir::Type llvmType =
6490 getTypeConverter()->convertType(op->getResultTypes().front());
6492 return mlir::failure();
6494 rewriter.replaceOpWithNewOp<mlir::LLVM::VaArgOp>(op, llvmType, vaList);
6495 return mlir::success();
6498mlir::LogicalResult CIRToLLVMLabelOpLowering::matchAndRewrite(
6499 cir::LabelOp op, OpAdaptor adaptor,
6500 mlir::ConversionPatternRewriter &rewriter)
const {
6501 mlir::MLIRContext *ctx = rewriter.getContext();
6502 mlir::Block *block = op->getBlock();
6505 if (block->isEntryBlock()) {
6506 mlir::Block *newBlock =
6507 rewriter.splitBlock(op->getBlock(), mlir::Block::iterator(op));
6508 rewriter.setInsertionPointToEnd(block);
6509 mlir::LLVM::BrOp::create(rewriter, op.getLoc(), newBlock);
6512 mlir::LLVM::BlockTagAttr::get(ctx, blockInfoAddr.getTagIndex());
6513 rewriter.setInsertionPoint(op);
6516 mlir::LLVM::BlockTagOp::create(rewriter, op->getLoc(), tagAttr);
6517 mlir::LLVM::LLVMFuncOp func = op->getParentOfType<mlir::LLVM::LLVMFuncOp>();
6518 auto blockInfoAttr =
6519 cir::BlockAddrInfoAttr::get(ctx, func.getSymName(), op.getLabel());
6520 blockInfoAddr.mapBlockTag(blockInfoAttr, blockTagOp);
6521 rewriter.eraseOp(op);
6523 return mlir::success();
6526mlir::LogicalResult CIRToLLVMBlockAddressOpLowering::matchAndRewrite(
6527 cir::BlockAddressOp op, OpAdaptor adaptor,
6528 mlir::ConversionPatternRewriter &rewriter)
const {
6529 mlir::MLIRContext *ctx = rewriter.getContext();
6531 mlir::LLVM::BlockTagOp matchLabel =
6532 blockInfoAddr.lookupBlockTag(op.getBlockAddrInfoAttr());
6533 mlir::LLVM::BlockTagAttr tagAttr;
6540 tagAttr = matchLabel.getTag();
6542 auto blkAddr = mlir::LLVM::BlockAddressAttr::get(
6543 rewriter.getContext(), op.getBlockAddrInfoAttr().getFunc(), tagAttr);
6544 rewriter.setInsertionPoint(op);
6545 auto newOp = mlir::LLVM::BlockAddressOp::create(
6546 rewriter, op.getLoc(), mlir::LLVM::LLVMPointerType::get(ctx), blkAddr);
6548 blockInfoAddr.addUnresolvedBlockAddress(newOp, op.getBlockAddrInfoAttr());
6549 rewriter.replaceOp(op, newOp);
6550 return mlir::success();
6553mlir::LogicalResult CIRToLLVMIndirectBrOpLowering::matchAndRewrite(
6554 cir::IndirectBrOp op, OpAdaptor adaptor,
6555 mlir::ConversionPatternRewriter &rewriter)
const {
6557 mlir::Value targetAddr = adaptor.getAddr();
6565 if (op.getPoison()) {
6566 auto llvmPtrType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
6568 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), llvmPtrType);
6571 rewriter.replaceOpWithNewOp<mlir::LLVM::IndirectBrOp>(
6572 op, targetAddr, adaptor.getSuccOperands(), op.getSuccessors());
6573 return mlir::success();
6576mlir::LogicalResult CIRToLLVMTokenNoneOpLowering::matchAndRewrite(
6577 cir::TokenNoneOp op, OpAdaptor adaptor,
6578 mlir::ConversionPatternRewriter &rewriter)
const {
6579 rewriter.replaceOpWithNewOp<mlir::LLVM::NoneTokenOp>(
6580 op, mlir::TokenType::get(rewriter.getContext()));
6581 return mlir::success();
6584mlir::LogicalResult CIRToLLVMCpuIdOpLowering::matchAndRewrite(
6585 cir::CpuIdOp op, OpAdaptor adaptor,
6586 mlir::ConversionPatternRewriter &rewriter)
const {
6587 mlir::Type i32Ty = rewriter.getI32Type();
6588 mlir::Type i64Ty = rewriter.getI64Type();
6589 mlir::Type i32PtrTy = mlir::LLVM::LLVMPointerType::get(i32Ty.getContext(), 0);
6591 mlir::Type cpuidRetTy = mlir::LLVM::LLVMStructType::getLiteral(
6592 rewriter.getContext(), {i32Ty, i32Ty, i32Ty, i32Ty});
6594 mlir::Value functionId = adaptor.getFunctionId();
6595 mlir::Value subFunctionId = adaptor.getSubFunctionId();
6597 StringRef asmString, constraints;
6598 mlir::ModuleOp moduleOp = op->getParentOfType<mlir::ModuleOp>();
6599 llvm::Triple triple(
6600 mlir::cast<mlir::StringAttr>(
6601 moduleOp->getAttr(cir::CIRDialect::getTripleAttrName()))
6603 if (triple.getArch() == llvm::Triple::x86) {
6604 asmString =
"cpuid";
6605 constraints =
"={ax},={bx},={cx},={dx},{ax},{cx}";
6608 asmString =
"xchgq %rbx, ${1:q}\n"
6610 "xchgq %rbx, ${1:q}";
6611 constraints =
"={ax},=r,={cx},={dx},0,2";
6614 mlir::Value inlineAsm =
6615 mlir::LLVM::InlineAsmOp::create(
6616 rewriter, op.getLoc(), cpuidRetTy, {functionId, subFunctionId},
6617 rewriter.getStringAttr(asmString),
6618 rewriter.getStringAttr(constraints),
6621 mlir::LLVM::TailCallKindAttr{},
6623 mlir::LLVM::AsmDialectAttr{},
6627 mlir::Value basePtr = adaptor.getCpuInfo();
6629 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
6630 unsigned alignment = layout.getTypeABIAlignment(i32Ty);
6631 for (
unsigned i = 0; i < 4; i++) {
6632 mlir::Value extracted =
6633 mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(), inlineAsm, i)
6635 mlir::Value index = mlir::LLVM::ConstantOp::create(
6636 rewriter, op.getLoc(), i64Ty, rewriter.getI64IntegerAttr(i));
6638 mlir::Value storePtr = mlir::LLVM::GEPOp::create(
6639 rewriter, op.getLoc(), i32PtrTy, i32Ty, basePtr,
6640 gepIndices, mlir::LLVM::GEPNoWrapFlags::none)
6642 mlir::LLVM::StoreOp::create(rewriter, op.getLoc(), extracted, storePtr,
6646 rewriter.eraseOp(op);
6647 return mlir::success();
6650mlir::LogicalResult CIRToLLVMMemChrOpLowering::matchAndRewrite(
6651 cir::MemChrOp op, OpAdaptor adaptor,
6652 mlir::ConversionPatternRewriter &rewriter)
const {
6653 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
6654 mlir::Type srcTy = getTypeConverter()->convertType(op.getSrc().getType());
6655 mlir::Type patternTy =
6656 getTypeConverter()->convertType(op.getPattern().getType());
6657 mlir::Type lenTy = getTypeConverter()->convertType(op.getLen().getType());
6659 mlir::LLVM::LLVMFunctionType::get(llvmPtrTy, {srcTy, patternTy, lenTy},
6661 llvm::StringRef fnName =
"memchr";
6663 mlir::Builder b(rewriter.getContext());
6664 mlir::NamedAttribute noundefAttr =
6665 b.getNamedAttr(
"llvm.noundef", b.getUnitAttr());
6666 mlir::DictionaryAttr noundefDict = mlir::DictionaryAttr::get(
6669 mlir::ArrayAttr argAttrs =
6670 mlir::ArrayAttr::get(rewriter.getContext(), argAttrVec);
6675 mlir::LLVM::CallOp newCall = rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(
6676 op, mlir::TypeRange{llvmPtrTy}, fnName,
6677 mlir::ValueRange{adaptor.getSrc(), adaptor.getPattern(),
6679 newCall.setArgAttrsAttr(argAttrs);
6680 return mlir::success();
6686 mlir::Location loc, mlir::Value inputPtr,
6687 uint64_t baseAlignment,
6688 cir::OffsetPairAttr paddingAttr) {
6693 uint64_t charWidth = 8;
6694 mlir::Type i8Ty = rewriter.getI8Type();
6695 mlir::Type ptrTy = mlir::LLVM::LLVMPointerType::get(i8Ty.getContext());
6697 auto startByte = paddingAttr.getStart() / charWidth;
6698 auto startBit = paddingAttr.getStart() % charWidth;
6699 auto endByte = paddingAttr.getEnd() / charWidth;
6700 auto endBit = paddingAttr.getEnd() % charWidth;
6702 if (startByte == endByte) {
6704 auto index = mlir::LLVM::ConstantOp::create(
6705 rewriter, loc, rewriter.getI32Type(), startByte);
6706 auto element = mlir::LLVM::GEPOp::create(rewriter, loc, ptrTy, i8Ty,
6709 uint64_t adjustedAlignment = llvm::MinAlign(baseAlignment, startByte);
6711 auto value = mlir::LLVM::LoadOp::create(rewriter, loc, i8Ty, element,
6716 uint8_t bitsToClear = ((1 << endBit) - 1) & ~((1 << startBit) - 1);
6717 uint8_t bitsToKeep = ~bitsToClear;
6719 mlir::LLVM::ConstantOp::create(rewriter, loc, i8Ty, bitsToKeep);
6720 auto newValue = mlir::LLVM::AndOp::create(rewriter, loc, value, maskValue);
6722 mlir::LLVM::StoreOp::create(rewriter, loc, newValue, element,
6726 if (startBit != 0) {
6727 auto index = mlir::LLVM::ConstantOp::create(
6728 rewriter, loc, rewriter.getI32Type(), startByte);
6729 auto element = mlir::LLVM::GEPOp::create(rewriter, loc, ptrTy, i8Ty,
6731 uint64_t adjustedAlignment = llvm::MinAlign(baseAlignment, startByte);
6733 auto value = mlir::LLVM::LoadOp::create(rewriter, loc, i8Ty, element,
6736 uint8_t bitsToClear = ((1 << (charWidth - startBit)) - 1) << startBit;
6737 uint8_t bitsToKeep = ~bitsToClear;
6739 mlir::LLVM::ConstantOp::create(rewriter, loc, i8Ty, bitsToKeep);
6741 mlir::LLVM::AndOp::create(rewriter, loc, value, maskValue);
6743 mlir::LLVM::StoreOp::create(rewriter, loc, newValue, element,
6749 for (
auto offset = startByte; offset < endByte; ++offset) {
6750 auto index = mlir::LLVM::ConstantOp::create(
6751 rewriter, loc, rewriter.getI32Type(), offset);
6752 auto element = mlir::LLVM::GEPOp::create(rewriter, loc, ptrTy, i8Ty,
6754 uint64_t adjustedAlignment = llvm::MinAlign(baseAlignment, offset);
6756 auto zero = mlir::LLVM::ConstantOp::create(rewriter, loc, i8Ty, 0);
6757 mlir::LLVM::StoreOp::create(rewriter, loc, zero, element,
6763 auto index = mlir::LLVM::ConstantOp::create(
6764 rewriter, loc, rewriter.getI32Type(), endByte);
6765 auto element = mlir::LLVM::GEPOp::create(rewriter, loc, ptrTy, i8Ty,
6767 uint64_t adjustedAlignment = llvm::MinAlign(baseAlignment, endByte);
6769 auto value = mlir::LLVM::LoadOp::create(rewriter, loc, i8Ty, element,
6772 uint8_t bitsToClear = (1 << endBit) - 1;
6773 uint8_t bitsToKeep = ~bitsToClear;
6775 mlir::LLVM::ConstantOp::create(rewriter, loc, i8Ty, bitsToKeep);
6777 mlir::LLVM::AndOp::create(rewriter, loc, value, maskValue);
6779 mlir::LLVM::StoreOp::create(rewriter, loc, newValue, element,
6785mlir::LogicalResult CIRToLLVMClearPaddingOpLowering::matchAndRewrite(
6786 cir::ClearPaddingOp op, OpAdaptor adaptor,
6787 mlir::ConversionPatternRewriter &rewriter)
const {
6789 mlir::Value inputPtr = adaptor.getArg();
6790 for (mlir::Attribute attr : op.getPadding())
6791 clearPadding(rewriter, op.getLoc(), inputPtr, op.getAlignment(),
6792 cast<cir::OffsetPairAttr>(attr));
6794 rewriter.eraseOp(op);
6795 return mlir::success();
6799 return std::make_unique<ConvertCIRToLLVMPass>();
6805 pm.addPass(mlir::omp::createMarkDeclareTargetPass());
6808 pm.addPass(mlir::omp::createHostOpFilteringPass());
6809 pm.nest<mlir::LLVM::LLVMFuncOp>().addPass(
6810 mlir::omp::createStackToSharedPass());
6814std::unique_ptr<llvm::Module>
6816 bool enableOpenMP, StringRef mlirSaveTempsOutFile,
6817 llvm::vfs::FileSystem *fs) {
6818 llvm::TimeTraceScope scope(
"lower from CIR to LLVM directly");
6820 mlir::MLIRContext *mlirCtx = mlirModule.getContext();
6822 mlir::PassManager pm(mlirCtx);
6825 (void)mlir::applyPassManagerCLOptions(pm);
6829 if (mlir::failed(pm.run(mlirModule)))
6832 if (!mlirSaveTempsOutFile.empty()) {
6834 llvm::raw_fd_ostream out(mlirSaveTempsOutFile, ec);
6836 mlirModule->print(out);
6839 mlir::registerBuiltinDialectTranslation(*mlirCtx);
6840 mlir::registerLLVMDialectTranslation(*mlirCtx);
6841 mlir::registerOpenMPDialectTranslation(*mlirCtx);
6844 llvm::TimeTraceScope translateScope(
"translateModuleToLLVMIR");
6846 StringRef moduleName = mlirModule.getName().value_or(
"CIRToLLVMModule");
6847 std::unique_ptr<llvm::Module> llvmModule = mlir::translateModuleToLLVMIR(
6848 mlirModule, llvmCtx, moduleName,
false, fs);
static bool isUnsigned(SValBuilder &SVB, NonLoc Value)
#define CHECK_ENUM(CIR, LLVM_VAL)
mlir::Attribute spellOutSplitTrailingZeros(mlir::Attribute attr)
Return attr with the trailing zeros of any array that adjustGlobalTypeForInit would split off written...
mlir::Value createLShR(mlir::OpBuilder &bld, mlir::Value lhs, unsigned rhs)
mlir::Value createShL(mlir::OpBuilder &bld, mlir::Value lhs, unsigned rhs)
std::optional< mlir::Attribute > lowerConstRecordAttr(cir::ConstRecordAttr constRecord, mlir::SymbolTableCollection &symbolTables, const mlir::TypeConverter *converter, const CIRPreConversionTypeMap &preConversionTypes, mlir::ModuleOp moduleOp={})
mlir::Type adjustGlobalTypeForInit(mlir::Type llvmType, mlir::Attribute init, const mlir::TypeConverter &converter, const mlir::DataLayout &dataLayout)
Adjust llvmType (the converted type of init) to the concrete LLVM type a global constant initialized ...
mlir::Value createAShR(mlir::OpBuilder &bld, mlir::Value lhs, unsigned rhs)
mlir::Value createAnd(mlir::OpBuilder &bld, mlir::Value lhs, const llvm::APInt &rhs)
mlir::Type convertTypeForLoadStore(const mlir::TypeConverter &converter, mlir::DataLayout const &dataLayout, mlir::Type type)
The type of a load/store's value, as opposed to convertTypeForMemory's type of the memory it lives in...
std::optional< mlir::Attribute > lowerConstArrayAttr(cir::ConstArrayAttr constArr, mlir::SymbolTableCollection &symbolTables, const mlir::TypeConverter *converter, const CIRPreConversionTypeMap &preConversionTypes, mlir::ModuleOp moduleOp={})
llvm::StringMap< mlir::Type > CIRPreConversionTypeMap
mlir::Type convertTypeForMemory(const mlir::TypeConverter &converter, mlir::DataLayout const &dataLayout, mlir::Type type, bool isForHLSL=false)
mlir::Attribute getBitIntStorageAttr(mlir::ConversionPatternRewriter &rewriter, cir::IntAttr attr, const mlir::DataLayout &dataLayout)
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
static bool isVector(QualType QT, QualType ElementType)
This helper function returns true if QT is a vector type that has element type ElementType.
__DEVICE__ void * memset(void *__a, int __b, size_t __c)
unsigned getProgramAddressSpace() const
C++ view class that accepts both !cir.struct and !cir.union types.
CIRAttrToValue(mlir::Location parentLoc, mlir::ModuleOp parentModule, mlir::ConversionPatternRewriter &rewriter, mlir::SymbolTableCollection &symbolTables, const mlir::TypeConverter *converter, const CIRPreConversionTypeMap &preConversionTypes, LLVMBlockAddressInfo *blockInfoAddr=nullptr)
GlobalInitAttrRewriter(mlir::Type type, mlir::DataLayout const &dataLayout, mlir::ConversionPatternRewriter &rewriter)
mlir::Attribute visit(mlir::Attribute attr)
mlir::Attribute visitCirAttr(cir::FPAttr attr)
mlir::Attribute visitCirAttr(cir::BoolAttr attr)
mlir::Attribute visitCirAttr(cir::IntAttr attr)
static mlir::LLVM::CConv convertCallingConv(cir::CallingConv callingConv)
static uint64_t getTypeAllocSize(mlir::Type type, mlir::Operation &op)
static mlir::LogicalResult lowerCallAttributes(cir::CIRCallOpInterface op, const mlir::TypeConverter &converter, const mlir::DataLayout &dataLayout, LoweredCallAttributes &result)
static mlir::LLVM::FastmathFlags convertFastMathFlags(cir::FastMathFlags cirFlags)
static llvm::StringRef getLLVMSyncScope(cir::SyncScopeKind syncScope, mlir::ModuleOp moduleOp)
static void buildCtorDtorList(mlir::ModuleOp module, StringRef globalXtorName, StringRef llvmXtorName, llvm::function_ref< cir::GlobalCtorDtorEntry(mlir::Attribute)> createXtor)
static mlir::LogicalResult lowerIncDecOp(CIROp op, typename CIROp::Adaptor adaptor, mlir::ConversionPatternRewriter &rewriter)
static bool isSignalingConstrainedFCmp(cir::CmpOpKind kind)
void populateCIRToLLVMPasses(mlir::OpPassManager &pm, bool enableOpenMP)
Adds passes that fully lower CIR to the LLVMIR dialect.
static mlir::LLVM::AtomicBinOp getLLVMAtomicBinOp(cir::AtomicFetchKind k, bool isInt, bool isSignedInt)
static mlir::SymbolRefAttr getComdatAttrHelper(mlir::ModuleOp modOp, mlir::OpBuilder &builder, StringRef symName, mlir::LLVM::ComdatOp &comdatOp, mlir::SymbolTableCollection &symbolTables)
static mlir::LLVM::ICmpPredicate convertCmpKindToICmpPredicate(cir::CmpOpKind kind, bool isSigned)
Convert from a CIR comparison kind to an LLVM IR integral comparison kind.
static bool isBulkLowerableConstArrayBaseElement(mlir::Type baseElemTy)
static mlir::LLVM::IntegerOverflowFlags intOverflowFlag(BinOp op)
static bool isHandledDiscardableFuncAttr(mlir::NamedAttribute attr)
Return true for discardable CIR markers handled explicitly below.
static mlir::LogicalResult lowerFPVectorReduction(CIROp op, typename CIROp::Adaptor adaptor, const mlir::TypeConverter &typeConverter, mlir::ConversionPatternRewriter &rewriter)
static void forwardAMDGPUAtomicOptionMarkers(mlir::Operation *op, mlir::Operation *llvmOp)
mlir::Value lowerCirAttrAsValue(mlir::Location parentLoc, mlir::ModuleOp parentModule, const mlir::Attribute attr, mlir::ConversionPatternRewriter &rewriter, mlir::SymbolTableCollection &symbolTables, const mlir::TypeConverter *converter, const CIRPreConversionTypeMap &preConversionTypes, LLVMBlockAddressInfo *blockInfoAddr)
Switches on the type of attribute and calls the appropriate conversion.
static void setLoweredCallAttributes(CallLikeOp op, const LoweredCallAttributes &attributes)
static mlir::Value castBitIntMemoryStorage(mlir::ConversionPatternRewriter &rewriter, const mlir::DataLayout &dataLayout, cir::IntType intTy, mlir::Value value, bool toMemory)
Cast a _BitInt(N) value between its literal width iN and its padded in-memory storage iM (sign/zero-e...
static mlir::Value getLLVMIntCast(mlir::ConversionPatternRewriter &rewriter, mlir::Value llvmSrc, mlir::Type llvmDstIntTy, bool isUnsigned, uint64_t cirSrcWidth, uint64_t cirDstIntWidth)
static constexpr char kTypeConversionErrorMsg[]
static mlir::Value createConstrainedFPIntrinsicCall(mlir::ConversionPatternRewriter &rewriter, mlir::Location loc, mlir::ValueRange operands, mlir::Type llvmResTy, cir::FenvAttr fenv, llvm::StringRef constrainedMnemonic, bool hasRoundingMode, mlir::LLVM::FastmathFlags fastmathFlags={})
mlir::LogicalResult lowerToConstrainedFPIntrinsic(mlir::Operation *op, mlir::ValueRange operands, cir::FenvAttr fenv, mlir::Type llvmResTy, mlir::ConversionPatternRewriter &rewriter, llvm::StringRef constrainedMnemonic, bool hasRoundingMode, mlir::LLVM::FastmathFlags fastmathFlags)
mlir::IntegerType computeBitfieldIntType(mlir::Type storageType, mlir::MLIRContext *context, unsigned &storageSize)
static mlir::InFlightDiagnostic emitTypeConversionError(mlir::Operation *op, mlir::Type type)
static llvm::StringRef getConstrainedExceptMetadata(cir::FenvAttr fenv)
static mlir::Value getValueForVTableSymbol(mlir::Operation *op, mlir::ConversionPatternRewriter &rewriter, mlir::SymbolTableCollection &symbolTables, const mlir::TypeConverter *converter, const CIRPreConversionTypeMap &preConversionTypes, mlir::FlatSymbolRefAttr nameAttr, mlir::Type &eltType)
static mlir::LLVM::ThreadLocalMode convertTlsModelAttrToLLVM(TLSModelAttr attr)
static mlir::LLVM::CallIntrinsicOp replaceOpWithCallLLVMIntrinsicOp(mlir::ConversionPatternRewriter &rewriter, mlir::Operation *op, const llvm::Twine &intrinsicName, mlir::Type resultTy, mlir::ValueRange operands, mlir::LLVM::FastmathFlags fastmathFlags={})
static mlir::Value createFenvMetadataValue(mlir::ConversionPatternRewriter &rewriter, mlir::Location loc, llvm::StringRef str)
static mlir::Value computeMatrixFlatIndex(mlir::ConversionPatternRewriter &rewriter, mlir::Location loc, cir::MatrixType matrixTy, mlir::Value rowIdx, mlir::Value columnIdx)
Computes the column-major flat index (columnIdx * numRows) + rowIdx.
static mlir::LogicalResult lowerMinMaxOp(CIROp op, typename CIROp::Adaptor adaptor, mlir::ConversionPatternRewriter &rewriter)
static mlir::LLVM::LLVMStructType getLLVMLandingPadStructTy(mlir::ConversionPatternRewriter &rewriter)
static mlir::LLVM::CallIntrinsicOp createCallLLVMIntrinsicOp(mlir::ConversionPatternRewriter &rewriter, mlir::Location loc, const llvm::Twine &intrinsicName, mlir::Type resultTy, mlir::ValueRange operands, mlir::LLVM::FastmathFlags fastmathFlags={})
static llvm::StringRef getConstrainedRoundingMetadata(cir::FenvAttr fenv)
static mlir::LLVM::framePointerKind::FramePointerKind convertFramePointerKind(cir::FramePointerKind kind)
static mlir::LLVM::MemoryEffectsAttr convertMemoryEffects(mlir::MLIRContext *ctx, cir::MemoryEffectsAttr effects)
A null input stays null, which is how both dialects spell unknown effects.
static mlir::Value convertToIndexTy(mlir::ConversionPatternRewriter &rewriter, mlir::ModuleOp mod, mlir::Value index, mlir::Type baseTy, cir::IntType strideTy)
static mlir::LogicalResult lowerIntBinaryOp(CIROp op, mlir::Value lhs, mlir::Value rhs, mlir::ConversionPatternRewriter &rewriter)
Lower an integer Div/Rem op to its signed or unsigned LLVM counterpart.
static std::optional< mlir::ArrayAttr > convertTypedArgAttrs(mlir::ArrayAttr argAttrs, const mlir::TypeConverter &converter, const mlir::DataLayout &dataLayout, mlir::MLIRContext *ctx)
The llvm.byval, llvm.sret, and llvm.byref argument attributes carry the pointee type as a TypeAttr.
void createLLVMFuncOpIfNotExist(mlir::ConversionPatternRewriter &rewriter, mlir::SymbolTableCollection &symbolTables, mlir::Operation *srcOp, llvm::StringRef fnName, mlir::Type fnTy, mlir::ArrayAttr argAttrs, mlir::ArrayAttr resAttrs)
Declare fnName with type fnTy before the function enclosing srcOp, unless the module already has a sy...
static mlir::LLVM::CallIntrinsicOp createConstrainedFCmpCall(mlir::ConversionPatternRewriter &rewriter, mlir::Location loc, mlir::Value lhs, mlir::Value rhs, cir::CmpOpKind kind, cir::FenvAttr fenv, mlir::Type llvmResTy)
static mlir::LLVM::uwtable::UWTableKind convertUWTableKind(cir::UnwindTableKind kind)
std::unique_ptr< llvm::Module > lowerDirectlyFromCIRToLLVMIR(mlir::ModuleOp mlirModule, llvm::LLVMContext &llvmCtx, bool enableOpenMP, llvm::StringRef mlirSaveTempsOutFile={}, llvm::vfs::FileSystem *fs=nullptr)
Lowers mlirModule, a CIR module, to an LLVM module in llvmCtx.
static llvm::FramePointerKind convertFramePointerKindToLLVMIR(cir::FramePointerKind kind)
The "frame-pointer" module flag holds an llvm::FramePointerKind value, as written by llvm::Module::se...
static void prepareTypeConverter(mlir::LLVMTypeConverter &converter, mlir::DataLayout &dataLayout)
static mlir::LLVM::AtomicOrdering getLLVMMemOrder(std::optional< cir::MemOrder > memorder)
std::unique_ptr< mlir::Pass > createConvertCIRToLLVMPass()
Create a pass that fully lowers CIR to the LLVMIR dialect.
static mlir::LogicalResult lowerSaturatableArithOp(CIROp op, mlir::Value lhs, mlir::Value rhs, mlir::ConversionPatternRewriter &rewriter)
Lower an arithmetic op that supports saturation, overflow flags, and an FP Lower an integer Add/Sub o...
static uint64_t getMemoryFallbackAlignment(mlir::Type cirType, mlir::Type llvmMemType, const mlir::DataLayout &dataLayout)
Alignment to use for a memory access whose op carries no explicit alignment.
static mlir::Type getConstArrayBaseElementType(mlir::Type ty)
static mlir::LLVM::FCmpPredicate convertCmpKindToFCmpPredicate(cir::CmpOpKind kind)
Convert from a CIR comparison kind to an LLVM IR floating-point comparison kind.
static llvm::StringRef convertCmpKindToConstrainedFCmpPredicate(cir::CmpOpKind kind)
static mlir::LLVM::Visibility lowerCIRVisibilityToLLVMVisibility(cir::VisibilityKind visibilityKind)
static mlir::LLVM::ModRefInfo convertModRefInfo(cir::ModRefInfo info)
static llvm::AtomicScope getAtomicScope(cir::SyncScopeKind syncScope)
mlir::LogicalResult lowerConstrainableFPOp(mlir::Operation *op, mlir::ValueRange operands, cir::FenvAttr fenv, cir::FastMathFlagsAttr fastmath, const mlir::TypeConverter &typeConverter, mlir::ConversionPatternRewriter &rewriter, llvm::StringRef constrainedMnemonic, bool hasRoundingMode)
static mlir::Value emitBoolVecConversion(mlir::ConversionPatternRewriter &rewriter, mlir::Value srcVec, unsigned numElementsDst)
static void convertCallEffects(mlir::Operation *callOp, bool isNothrow, cir::MemoryEffectsAttr effects, mlir::LLVM::MemoryEffectsAttr &memoryEffect, bool &noUnwind, bool &willReturn, bool &noReturn)
static mlir::LogicalResult lowerMemTransferOp(CIROp op, typename CIROp::Adaptor adaptor, mlir::ConversionPatternRewriter &rewriter)
static llvm::StringLiteral getLLVMBinopForPostAtomic(cir::AtomicFetchKind k, bool isInt)
mlir::LLVM::Linkage convertLinkage(cir::GlobalLinkageKind linkage)
static mlir::LogicalResult lowerBinOpOverflow(OpTy op, typename OpTy::Adaptor adaptor, mlir::ConversionPatternRewriter &rewriter, const mlir::TypeConverter *typeConverter, llvm::StringRef opStr)
Shared lowering logic for checked binary arithmetic overflow operations.
void lowerOpenCLModuleMetadataAttrs(mlir::ModuleOp module)
static mlir::Value emitFromMemory(mlir::ConversionPatternRewriter &rewriter, const mlir::TypeConverter &converter, mlir::DataLayout const &dataLayout, cir::LoadOp op, mlir::Value value)
Emits the value from memory as expected by its users.
static mlir::Value createIntCast(mlir::OpBuilder &bld, mlir::Value src, mlir::IntegerType dstTy, bool isSigned=false)
static mlir::LLVM::IntegerOverflowFlags nswFlag(bool nsw)
static void clearPadding(mlir::ConversionPatternRewriter &rewriter, mlir::Location loc, mlir::Value inputPtr, uint64_t baseAlignment, cir::OffsetPairAttr paddingAttr)
static mlir::Value emitToMemory(mlir::ConversionPatternRewriter &rewriter, mlir::DataLayout const &dataLayout, mlir::Type origType, mlir::Value value)
Emits a value to memory with the expected scalar type.
static mlir::LogicalResult rewriteCallOrInvoke(mlir::Operation *op, mlir::ValueRange callOperands, mlir::ConversionPatternRewriter &rewriter, const mlir::TypeConverter *converter, const mlir::DataLayout &dataLayout, mlir::SymbolTableCollection &symbolTables, mlir::FlatSymbolRefAttr calleeAttr, mlir::Block *continueBlock=nullptr, mlir::Block *landingPadBlock=nullptr)
static mlir::LLVM::GlobalOp replaceCirGlobal(mlir::SymbolTableCollection &symbolTables, cir::GlobalOp op, mlir::Type llvmType, bool isConst, mlir::LLVM::Linkage linkage, llvm::StringRef symbol, mlir::Attribute init, uint64_t alignment, unsigned addrSpace, bool isDsoLocal, mlir::LLVM::ThreadLocalMode threadLocalMode, mlir::SymbolRefAttr comdatAttr, llvm::ArrayRef< mlir::NamedAttribute > attributes, mlir::ConversionPatternRewriter &rewriter)
static void forwardAMDGPUNoPrivateAddrSpace(mlir::Operation *op, mlir::Operation *llvmOp, mlir::Value llvmPtr)
static bool isIntTypeUnsigned(mlir::Type type)
mlir::Type memberStorageType(mlir::Type memberTy)
The storage a member is stored as: the access unit for a bit-field member, and the member type itself...
void collectUnreachable(mlir::Operation *parent, llvm::SmallVectorImpl< mlir::Operation * > &ops)
Collect ops in blocks that are unreachable from their region's entry, appending them to ops.
bool memberOwnsBytes(mlir::Type memberTy)
Whether a record member occupies bytes of its record.
Op::Properties getDefaultProperties(mlir::MLIRContext *context)
The properties of Op with every ODS-declared default applied.
const internal::VariadicAllOfMatcher< Attr > attr
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const AstTypeMatcher< ComplexType > complexType
void info(bool Verbose, unsigned Level, const char *Fmt, Ts &&...Args)
Prints an indented note to stderr when Verbose is set.
@ Default
Set to the current date and time.
Diagnostic wrappers for TextAPI types for error reporting.
void populateCIRPreLoweringPasses(mlir::OpPassManager &pm)
void registerCIRDialectTranslation(mlir::MLIRContext &context)
char __ovld __cnfn clz(char)
Returns the number of leading 0-bits in x, starting at the most significant bit position.
char __ovld __cnfn ctz(char)
Returns the count of trailing 0-bits in x.
float __ovld __cnfn sign(float)
Returns 1.0 if x > 0, -0.0 if x = -0.0, +0.0 if x = +0.0, or -1.0 if x < 0.
float __ovld __cnfn length(float)
Return the length of vector p, i.e., sqrt(p.x2 + p.y 2 + ...)
char __ovld __cnfn select(char, char, char)
For each component of a vector type, result[i] = if MSB of c[i] is set ?
__builtin_bitreverse32 uint32_t __builtin_riscv_aaddu_u32 __builtin_riscv_asubu_u32 __builtin_elementwise_add_sat __builtin_elementwise_sub_sat int32_t uint32_t uint32_t __builtin_riscv_mhacc_i32 __builtin_riscv_mhaccu_u32 __builtin_riscv_mhaccsu_i32 __builtin_riscv_mulq_i32 int64_t
__builtin_bitreverse32 uint32_t __builtin_riscv_aaddu_u32 __builtin_riscv_asubu_u32 __builtin_elementwise_add_sat __builtin_elementwise_sub_sat int32_t
Helper type for lowering global ctor/dtors, that contain all the values needed for transforming the v...
static bool dataMemberType()
static bool addressSpace()
static bool opCallInvokeAttrs()
static bool opAllocaAnnotations()
static bool opLoadStoreTbaa()
static bool opFuncPreferredAlignment()
static bool optInfoAttr()
static bool opFuncExtraAttrs()
static bool isPPC_FP128Ty()
static bool vaArgABILowering()
static bool fpConstraints()
static bool intrinsicElementTypeSupport()
static bool lowerModeOptLevel()
static bool opFuncCallingConv()
static bool aggValueSlotVolatile()
static bool fastMathFlags()
static bool llvmLoweringPtrDiffConsidersPointee()
static bool atomicSyncScopeID()
static bool opFuncMultipleReturnVals()
void collectGlobalAnnotations(mlir::ModuleOp module)
Collect (symbol_name, annotations, loc) from cir.func and cir.global ops before the conversion runs (...
void runOnOperation() final
StringRef getDescription() const override
StringRef getArgument() const override
void getDependentDialects(mlir::DialectRegistry ®istry) const override
void resolveBlockAddressOp(LLVMBlockAddressInfo &blockInfoAddr)
void buildGlobalAnnotationsVar(mlir::ModuleOp module)
Emit @llvm.global.annotations and supporting string/args constants from the previously-collected anno...
void processCIRAttrs(mlir::ModuleOp module)
mlir::LLVM::BlockTagOp lookupBlockTag(cir::BlockAddrInfoAttr info) const
void clearUnresolvedMap()
llvm::DenseMap< mlir::LLVM::BlockAddressOp, cir::BlockAddrInfoAttr > & getUnresolvedBlockAddress()
SmallVector< mlir::NamedAttribute > discardableAttrs