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/Location.h"
33#include "mlir/IR/Types.h"
34#include "mlir/Pass/Pass.h"
35#include "mlir/Pass/PassManager.h"
36#include "mlir/Support/LLVM.h"
37#include "mlir/Target/LLVMIR/Dialect/Builtin/BuiltinToLLVMIRTranslation.h"
38#include "mlir/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.h"
39#include "mlir/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.h"
40#include "mlir/Target/LLVMIR/Export.h"
41#include "mlir/Transforms/DialectConversion.h"
51#include "llvm/ADT/MapVector.h"
52#include "llvm/ADT/StringMap.h"
53#include "llvm/ADT/TypeSwitch.h"
54#include "llvm/IR/Module.h"
55#include "llvm/Support/AMDGPUAddrSpace.h"
56#include "llvm/Support/Casting.h"
57#include "llvm/Support/ErrorHandling.h"
58#include "llvm/Support/TimeProfiler.h"
59#include "llvm/Support/VirtualFileSystem.h"
60#include "llvm/Support/raw_ostream.h"
61#include "llvm/TargetParser/AtomicScope.h"
76mlir::Type elementTypeIfVectorOrMatrix(mlir::Type type) {
77 return llvm::TypeSwitch<mlir::Type, mlir::Type>(type)
78 .Case<cir::VectorType, cir::MatrixType, mlir::VectorType>(
79 [](
auto p) {
return p.getElementType(); })
80 .
Default([](mlir::Type p) {
return p; });
88 mlir::Type llvmMemType,
89 const mlir::DataLayout &dataLayout) {
90 if (
auto intTy = mlir::dyn_cast<cir::IntType>(cirType);
91 intTy && intTy.isBitInt())
92 return intTy.getABIAlignment(dataLayout, {});
93 return dataLayout.getTypeABIAlignment(llvmMemType);
97 mlir::IntegerType dstTy,
98 bool isSigned =
false) {
99 mlir::Type srcTy = src.getType();
100 assert(mlir::isa<mlir::IntegerType>(srcTy));
102 unsigned srcWidth = mlir::cast<mlir::IntegerType>(srcTy).getWidth();
103 unsigned dstWidth = mlir::cast<mlir::IntegerType>(dstTy).getWidth();
104 mlir::Location loc = src.getLoc();
106 if (dstWidth > srcWidth && isSigned)
107 return mlir::LLVM::SExtOp::create(bld, loc, dstTy, src);
108 if (dstWidth > srcWidth)
109 return mlir::LLVM::ZExtOp::create(bld, loc, dstTy, src);
110 if (dstWidth < srcWidth)
111 return mlir::LLVM::TruncOp::create(bld, loc, dstTy, src);
112 return mlir::LLVM::BitcastOp::create(bld, loc, dstTy, src);
122 const mlir::DataLayout &dataLayout, cir::IntType intTy,
123 mlir::Value value,
bool toMemory) {
124 unsigned storageBits = intTy.getStorageTypeWidth(dataLayout);
125 if (storageBits == intTy.getWidth())
127 unsigned dstBits = toMemory ? storageBits : intTy.getWidth();
128 return createIntCast(rewriter, value, rewriter.getIntegerType(dstBits),
129 toMemory && intTy.isSigned());
132static mlir::LLVM::Visibility
134 switch (visibilityKind) {
135 case cir::VisibilityKind::Default:
136 return ::mlir::LLVM::Visibility::Default;
137 case cir::VisibilityKind::Hidden:
138 return ::mlir::LLVM::Visibility::Hidden;
139 case cir::VisibilityKind::Protected:
140 return ::mlir::LLVM::Visibility::Protected;
146 mlir::Value srcVec,
unsigned numElementsDst) {
147 auto srcTy = mlir::cast<mlir::VectorType>(srcVec.getType());
148 unsigned numElementsSrc = srcTy.getNumElements();
149 if (numElementsSrc == numElementsDst)
153 for (
unsigned i : llvm::seq(std::min(numElementsDst, numElementsSrc)))
156 mlir::Location loc = srcVec.getLoc();
157 auto poison = mlir::LLVM::PoisonOp::create(rewriter, loc, srcVec.getType());
158 return mlir::LLVM::ShuffleVectorOp::create(rewriter, loc, srcVec, poison,
166 const mlir::TypeConverter &converter,
167 mlir::DataLayout
const &dataLayout,
168 cir::LoadOp op, mlir::Value value) {
170 if (
auto boolTy = mlir::dyn_cast<cir::BoolType>(op.getType())) {
172 assert(value.getType().isInteger(dataLayout.getTypeSizeInBits(boolTy)));
177 if (
auto vecTy = mlir::dyn_cast<cir::VectorType>(op.getType())) {
178 if (mlir::isa<cir::BoolType>(vecTy.getElementType())) {
179 auto rawIntTy = mlir::cast<mlir::IntegerType>(value.getType());
181 cir::VectorType::get(vecTy.getElementType(), rawIntTy.getWidth());
182 mlir::Type mlirVecTy = converter.convertType(paddedVecTy);
184 auto v = mlir::LLVM::BitcastOp::create(rewriter, value.getLoc(),
192 if (
auto intTy = mlir::dyn_cast<cir::IntType>(op.getType());
193 intTy && intTy.isBitInt())
203static mlir::Value
emitToMemory(mlir::ConversionPatternRewriter &rewriter,
204 mlir::DataLayout
const &dataLayout,
205 mlir::Type origType, mlir::Value value) {
208 if (
auto boolTy = mlir::dyn_cast<cir::BoolType>(origType)) {
210 mlir::IntegerType memType =
211 rewriter.getIntegerType(dataLayout.getTypeSizeInBits(boolTy));
219 if (
auto vecTy = mlir::dyn_cast<cir::VectorType>(origType)) {
220 if (mlir::isa<cir::BoolType>(vecTy.getElementType())) {
222 if (vecTy.getIsScalable())
223 resultTy = mlir::VectorType::get(
224 vecTy.getSize(), vecTy.getElementType(), vecTy.getIsScalable());
226 resultTy = mlir::IntegerType::get(origType.getContext(),
227 vecTy.getBoolStorageWidth());
231 return mlir::LLVM::BitcastOp::create(rewriter, value.getLoc(), resultTy,
237 if (
auto intTy = mlir::dyn_cast<cir::IntType>(origType);
238 intTy && intTy.isBitInt())
246 using CIR = cir::GlobalLinkageKind;
247 using LLVM = mlir::LLVM::Linkage;
250 case CIR::AppendingLinkage:
251 return LLVM::Appending;
252 case CIR::AvailableExternallyLinkage:
253 return LLVM::AvailableExternally;
254 case CIR::CommonLinkage:
256 case CIR::ExternalLinkage:
257 return LLVM::External;
258 case CIR::ExternalWeakLinkage:
259 return LLVM::ExternWeak;
260 case CIR::InternalLinkage:
261 return LLVM::Internal;
262 case CIR::LinkOnceAnyLinkage:
263 return LLVM::Linkonce;
264 case CIR::LinkOnceODRLinkage:
265 return LLVM::LinkonceODR;
266 case CIR::PrivateLinkage:
267 return LLVM::Private;
268 case CIR::WeakAnyLinkage:
270 case CIR::WeakODRLinkage:
271 return LLVM::WeakODR;
273 llvm_unreachable(
"Unknown CIR linkage type");
277 using CIR = cir::CallingConv;
278 using LLVM = mlir::LLVM::CConv;
280 switch (callingConv) {
283 case CIR::SpirKernel:
284 return LLVM::SPIR_KERNEL;
285 case CIR::SpirFunction:
286 return LLVM::SPIR_FUNC;
288 return LLVM::PTX_Kernel;
289 case CIR::AMDGPUKernel:
290 return LLVM::AMDGPU_KERNEL;
292 llvm_unreachable(
"Unknown calling convention");
295static mlir::LLVM::uwtable::UWTableKind
297 using CIR = cir::UnwindTableKind;
298 using LLVM = mlir::LLVM::uwtable::UWTableKind;
308 llvm_unreachable(
"Unknown CIR unwind table kind");
311static mlir::LLVM::framePointerKind::FramePointerKind
313 using CIR = cir::FramePointerKind;
314 using LLVM = mlir::LLVM::framePointerKind::FramePointerKind;
320 return LLVM::NonLeaf;
324 return LLVM::Reserved;
325 case CIR::NonLeafNoReserve:
326 return LLVM::NonLeafNoReserve;
328 llvm_unreachable(
"Unknown CIR frame pointer kind");
333static llvm::FramePointerKind
335 using CIR = cir::FramePointerKind;
336 using LLVM = llvm::FramePointerKind;
342 return LLVM::NonLeaf;
346 return LLVM::Reserved;
347 case CIR::NonLeafNoReserve:
348 return LLVM::NonLeafNoReserve;
350 llvm_unreachable(
"Unknown CIR frame pointer kind");
353mlir::LogicalResult CIRToLLVMCopyOpLowering::matchAndRewrite(
354 cir::CopyOp op, OpAdaptor adaptor,
355 mlir::ConversionPatternRewriter &rewriter)
const {
356 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
357 const mlir::Value
length = mlir::LLVM::ConstantOp::create(
358 rewriter, op.getLoc(), rewriter.getI64Type(),
359 op.getCopySizeInBytes(layout));
362 uint64_t dstTypeAlign =
363 dataLayout.getTypeABIAlignment(op.getDst().getType().getPointee());
364 uint64_t srcTypeAlign =
365 dataLayout.getTypeABIAlignment(op.getSrc().getType().getPointee());
367 mlir::NamedAttribute dstAlignAttr = rewriter.getNamedAttr(
368 mlir::LLVM::LLVMDialect::getAlignAttrName(),
369 rewriter.getI64IntegerAttr(op.getDstAlignment().value_or(dstTypeAlign)));
370 mlir::NamedAttribute srcAlignAttr = rewriter.getNamedAttr(
371 mlir::LLVM::LLVMDialect::getAlignAttrName(),
372 rewriter.getI64IntegerAttr(op.getSrcAlignment().value_or(srcTypeAlign)));
373 mlir::ArrayAttr argAttrs = rewriter.getArrayAttr({
374 rewriter.getDictionaryAttr({dstAlignAttr}),
375 rewriter.getDictionaryAttr({srcAlignAttr}),
378 rewriter.replaceOpWithNewOp<mlir::LLVM::MemcpyOp>(
379 op, adaptor.getDst(), adaptor.getSrc(),
length, op.getIsVolatile(),
381 nullptr,
nullptr, argAttrs,
383 return mlir::success();
386template <
typename CIROp,
typename LLVMOp>
387static mlir::LogicalResult
389 mlir::ConversionPatternRewriter &rewriter) {
390 mlir::ArrayAttr argAttrs;
391 if (op.getDstAlignment() || op.getSrcAlignment()) {
392 mlir::NamedAttribute dstAlignAttr = rewriter.getNamedAttr(
393 mlir::LLVM::LLVMDialect::getAlignAttrName(),
394 rewriter.getI64IntegerAttr(op.getDstAlignment().value_or(1)));
395 mlir::NamedAttribute srcAlignAttr = rewriter.getNamedAttr(
396 mlir::LLVM::LLVMDialect::getAlignAttrName(),
397 rewriter.getI64IntegerAttr(op.getSrcAlignment().value_or(1)));
398 argAttrs = rewriter.getArrayAttr({
399 rewriter.getDictionaryAttr({dstAlignAttr}),
400 rewriter.getDictionaryAttr({srcAlignAttr}),
403 rewriter.replaceOpWithNewOp<LLVMOp>(
404 op, adaptor.getDst(), adaptor.getSrc(), adaptor.getLen(),
407 nullptr,
nullptr, argAttrs,
409 return mlir::success();
412mlir::LogicalResult CIRToLLVMMemCpyOpLowering::matchAndRewrite(
413 cir::MemCpyOp op, OpAdaptor adaptor,
414 mlir::ConversionPatternRewriter &rewriter)
const {
419mlir::LogicalResult CIRToLLVMMemMoveOpLowering::matchAndRewrite(
420 cir::MemMoveOp op, OpAdaptor adaptor,
421 mlir::ConversionPatternRewriter &rewriter)
const {
426mlir::LogicalResult CIRToLLVMMemSetOpLowering::matchAndRewrite(
427 cir::MemSetOp op, OpAdaptor adaptor,
428 mlir::ConversionPatternRewriter &rewriter)
const {
430 auto memset = rewriter.replaceOpWithNewOp<mlir::LLVM::MemsetOp>(
431 op, adaptor.getDst(), adaptor.getVal(), adaptor.getLen(),
434 if (op.getAlignmentAttr()) {
436 llvm::SmallVector<mlir::Attribute> attrs{
memset.getNumOperands(),
437 rewriter.getDictionaryAttr({})};
438 llvm::SmallVector<mlir::NamedAttribute> destAttrs;
440 {mlir::LLVM::LLVMDialect::getAlignAttrName(), op.getAlignmentAttr()});
441 attrs[
memset.odsIndex_dst] = rewriter.getDictionaryAttr(destAttrs);
443 auto arrayAttr = rewriter.getArrayAttr(attrs);
444 memset.setArgAttrsAttr(arrayAttr);
447 return mlir::success();
451 mlir::Value llvmSrc, mlir::Type llvmDstIntTy,
453 uint64_t cirDstIntWidth) {
454 if (cirSrcWidth == cirDstIntWidth)
457 auto loc = llvmSrc.getLoc();
458 if (cirSrcWidth < cirDstIntWidth) {
460 return mlir::LLVM::ZExtOp::create(rewriter, loc, llvmDstIntTy, llvmSrc);
461 return mlir::LLVM::SExtOp::create(rewriter, loc, llvmDstIntTy, llvmSrc);
465 return mlir::LLVM::TruncOp::create(rewriter, loc, llvmDstIntTy, llvmSrc);
471 mlir::ConversionPatternRewriter &rewriter,
472 mlir::SymbolTableCollection &symbolTables,
473 const mlir::TypeConverter *converter,
475 : parentOp(parentOp), rewriter(rewriter), symbolTables(symbolTables),
476 converter(converter), blockInfoAddr(blockInfoAddr) {}
478#define GET_CIR_ATTR_TO_VALUE_VISITOR_DECLS
479#include "clang/CIR/Dialect/IR/CIRLowering.inc"
480#undef GET_CIR_ATTR_TO_VALUE_VISITOR_DECLS
483 struct LoweredGlobalSymbol {
485 mlir::Type sourceType;
489 LoweredGlobalSymbol getAddressOfSymbol(mlir::FlatSymbolRefAttr symbol);
490 mlir::Value castGlobalAddrToType(mlir::Value addr, mlir::Type attrType,
491 mlir::Type sourceType,
unsigned addrSpace);
493 mlir::Operation *parentOp;
494 mlir::ConversionPatternRewriter &rewriter;
495 mlir::SymbolTableCollection &symbolTables;
496 const mlir::TypeConverter *converter;
499 LLVMBlockAddressInfo *blockInfoAddr;
504 const mlir::Attribute attr,
505 mlir::ConversionPatternRewriter &rewriter,
506 mlir::SymbolTableCollection &symbolTables,
507 const mlir::TypeConverter *converter,
509 CIRAttrToValue valueConverter(parentOp, rewriter, symbolTables, converter,
511 mlir::Value value = valueConverter.visit(attr);
513 llvm_unreachable(
"unhandled attribute type");
519 case cir::ModRefInfo::NoModRef:
520 return mlir::LLVM::ModRefInfo::NoModRef;
521 case cir::ModRefInfo::Ref:
522 return mlir::LLVM::ModRefInfo::Ref;
523 case cir::ModRefInfo::Mod:
524 return mlir::LLVM::ModRefInfo::Mod;
525 case cir::ModRefInfo::ModRef:
526 return mlir::LLVM::ModRefInfo::ModRef;
528 llvm_unreachable(
"unhandled cir::ModRefInfo");
532static mlir::LLVM::MemoryEffectsAttr
537 return mlir::LLVM::MemoryEffectsAttr::get(
547 cir::MemoryEffectsAttr effects,
548 mlir::LLVM::MemoryEffectsAttr &memoryEffect,
549 bool &noUnwind,
bool &willReturn,
555 noUnwind = isNothrow || callOp->hasAttr(CIRDialect::getNoUnwindAttrName());
556 willReturn = callOp->hasAttr(CIRDialect::getWillReturnAttrName());
557 noReturn = callOp->hasAttr(CIRDialect::getNoReturnAttrName());
560static mlir::LLVM::CallIntrinsicOp
562 mlir::Location loc,
const llvm::Twine &intrinsicName,
563 mlir::Type resultTy, mlir::ValueRange operands,
564 mlir::LLVM::FastmathFlags fastmathFlags = {}) {
565 auto intrinsicNameAttr =
566 mlir::StringAttr::get(rewriter.getContext(), intrinsicName);
568 mlir::LLVM::FastmathFlagsAttr::get(rewriter.getContext(), fastmathFlags);
572 return mlir::LLVM::CallIntrinsicOp::create(
573 rewriter, loc, mlir::TypeRange{resultTy}, intrinsicNameAttr, operands,
575 return mlir::LLVM::CallIntrinsicOp::create(rewriter, loc, intrinsicNameAttr,
580 mlir::ConversionPatternRewriter &rewriter, mlir::Operation *op,
581 const llvm::Twine &intrinsicName, mlir::Type resultTy,
582 mlir::ValueRange operands, mlir::LLVM::FastmathFlags fastmathFlags = {}) {
584 rewriter, op->getLoc(), intrinsicName, resultTy, operands, fastmathFlags);
585 rewriter.replaceOp(op, callIntrinOp.getOperation());
590 std::optional<cir::FPDynamicRoundingMode> rounding =
591 fenv.getDynamicRoundingMode();
593 return "round.tonearest";
595 case cir::FPDynamicRoundingMode::ToNearest:
596 return "round.tonearest";
597 case cir::FPDynamicRoundingMode::Downward:
598 return "round.downward";
599 case cir::FPDynamicRoundingMode::Upward:
600 return "round.upward";
601 case cir::FPDynamicRoundingMode::UpwardZero:
602 return "round.towardzero";
603 case cir::FPDynamicRoundingMode::ToNearestAway:
604 return "round.tonearestaway";
605 case cir::FPDynamicRoundingMode::Unknown:
606 return "round.dynamic";
608 llvm_unreachable(
"unknown FP dynamic rounding mode");
612 std::optional<cir::FPExceptionMode> exceptMode = fenv.getExceptMode();
613 if (exceptMode == cir::FPExceptionMode::Masked)
614 return "fpexcept.ignore";
615 mlir::BoolAttr strictExcept = fenv.getStrictExcept();
617 return "fpexcept.ignore";
618 return strictExcept.getValue() ?
"fpexcept.strict" :
"fpexcept.maytrap";
623 mlir::Location loc, llvm::StringRef str) {
624 auto mdString = mlir::LLVM::MDStringAttr::get(
625 rewriter.getContext(), mlir::StringAttr::get(rewriter.getContext(), str));
626 return mlir::LLVM::MetadataAsValueOp::create(rewriter, loc, mdString);
630 mlir::Operation *op, mlir::ValueRange operands, cir::FenvAttr fenv,
631 mlir::Type llvmResTy, mlir::ConversionPatternRewriter &rewriter,
632 llvm::StringRef constrainedMnemonic,
bool hasRoundingMode,
633 mlir::LLVM::FastmathFlags fastmathFlags) {
634 mlir::Location loc = op->getLoc();
643 rewriter, op,
"llvm.experimental.constrained." + constrainedMnemonic,
644 llvmResTy, callOperands, fastmathFlags);
645 return mlir::success();
648static mlir::LLVM::FastmathFlags
652 mlir::ConversionPatternRewriter &rewriter, mlir::Location loc,
653 mlir::ValueRange operands, mlir::Type llvmResTy, cir::FenvAttr fenv,
654 llvm::StringRef constrainedMnemonic,
bool hasRoundingMode,
655 mlir::LLVM::FastmathFlags fastmathFlags = {}) {
665 rewriter, loc,
"llvm.experimental.constrained." + constrainedMnemonic,
666 llvmResTy, callOperands, fastmathFlags);
667 return intrinsic->getResult(0);
670template <
typename LLVMOp>
672 mlir::Operation *op, mlir::ValueRange operands, cir::FenvAttr fenv,
673 cir::FastMathFlagsAttr fastmath,
const mlir::TypeConverter &typeConverter,
674 mlir::ConversionPatternRewriter &rewriter,
675 llvm::StringRef constrainedMnemonic,
bool hasRoundingMode) {
676 mlir::Type llvmResTy = typeConverter.convertType(op->getResultTypes()[0]);
678 return op->emitError(
"expected LLVM result type for floating-point op");
680 mlir::LLVM::FastmathFlags fastmathFlags = {};
685 auto newOp = rewriter.replaceOpWithNewOp<LLVMOp>(
686 op, mlir::TypeRange{llvmResTy}, operands,
688 if (fastmathFlags != mlir::LLVM::FastmathFlags::none)
689 mlir::cast<mlir::LLVM::FastmathFlagsInterface>(newOp.getOperation())
690 .setFastmathAttr(mlir::LLVM::FastmathFlagsAttr::get(
691 rewriter.getContext(), fastmathFlags));
692 return mlir::success();
696 constrainedMnemonic, hasRoundingMode,
700static mlir::LLVM::FastmathFlags
702 mlir::LLVM::FastmathFlags llvmFlags{};
703 const std::pair<cir::FastMathFlags, mlir::LLVM::FastmathFlags> flags[] = {
704 {cir::FastMathFlags::nnan, mlir::LLVM::FastmathFlags::nnan},
705 {cir::FastMathFlags::ninf, mlir::LLVM::FastmathFlags::ninf},
706 {cir::FastMathFlags::nsz, mlir::LLVM::FastmathFlags::nsz},
707 {cir::FastMathFlags::arcp, mlir::LLVM::FastmathFlags::arcp},
708 {cir::FastMathFlags::contract, mlir::LLVM::FastmathFlags::contract},
709 {cir::FastMathFlags::afn, mlir::LLVM::FastmathFlags::afn},
710 {cir::FastMathFlags::reassoc, mlir::LLVM::FastmathFlags::reassoc},
713 for (
auto [cirFlag, llvmFlag] : flags) {
714 if (bitEnumContainsAny(cirFlags, cirFlag))
715 llvmFlags = llvmFlags | llvmFlag;
721mlir::LogicalResult CIRToLLVMLLVMIntrinsicCallOpLowering::matchAndRewrite(
722 cir::LLVMIntrinsicCallOp op, OpAdaptor adaptor,
723 mlir::ConversionPatternRewriter &rewriter)
const {
726 mlir::Type llvmResTy;
727 if (op->getNumResults() != 0) {
728 llvmResTy = getTypeConverter()->convertType(op->getResultTypes()[0]);
730 return op.emitError(
"expected LLVM result type");
732 StringRef name = op.getIntrinsicName();
733 mlir::LLVM::FastmathFlags fastmathFlags = {};
734 if (std::optional<cir::FastMathFlags> fastmath = op.getFastmathFlags())
748 adaptor.getOperands(), fastmathFlags);
749 return mlir::success();
753mlir::Value CIRAttrToValue::visitCirAttr(cir::BoolAttr boolAttr) {
754 mlir::Location loc = parentOp->getLoc();
755 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
756 mlir::Value boolVal = mlir::LLVM::ConstantOp::create(
757 rewriter, loc, converter->convertType(boolAttr.getType()),
758 boolAttr.getValue());
759 return emitToMemory(rewriter, layout, boolAttr.getType(), boolVal);
763mlir::Value CIRAttrToValue::visitCirAttr(cir::IntAttr intAttr) {
764 mlir::Location loc = parentOp->getLoc();
765 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
767 if (
auto intTy = mlir::dyn_cast<cir::IntType>(intAttr.getType());
768 intTy && intTy.isBitInt()) {
770 return mlir::LLVM::ConstantOp::create(
777 mlir::Value val = mlir::LLVM::ConstantOp::create(
778 rewriter, loc, converter->convertType(intAttr.getType()),
780 return emitToMemory(rewriter, layout, intAttr.getType(), val);
784mlir::Value CIRAttrToValue::visitCirAttr(cir::FPAttr fltAttr) {
785 mlir::Location loc = parentOp->getLoc();
786 return mlir::LLVM::ConstantOp::create(
787 rewriter, loc, converter->convertType(fltAttr.getType()),
792mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstComplexAttr complexAttr) {
793 cir::ComplexType
complexType = complexAttr.getType();
794 mlir::Type complexElemTy =
complexType.getElementType();
795 mlir::Type complexElemLLVMTy = converter->convertType(complexElemTy);
797 mlir::Attribute components[2];
798 if (
const auto intType = mlir::dyn_cast<cir::IntType>(complexElemTy)) {
799 components[0] = rewriter.getIntegerAttr(
801 mlir::cast<cir::IntAttr>(complexAttr.getReal()).getValue());
802 components[1] = rewriter.getIntegerAttr(
804 mlir::cast<cir::IntAttr>(complexAttr.getImag()).getValue());
806 components[0] = rewriter.getFloatAttr(
808 mlir::cast<cir::FPAttr>(complexAttr.getReal()).getValue());
809 components[1] = rewriter.getFloatAttr(
811 mlir::cast<cir::FPAttr>(complexAttr.getImag()).getValue());
814 mlir::Location loc = parentOp->getLoc();
815 return mlir::LLVM::ConstantOp::create(
816 rewriter, loc, converter->convertType(complexAttr.getType()),
817 rewriter.getArrayAttr(components));
821mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstPtrAttr ptrAttr) {
822 mlir::Location loc = parentOp->getLoc();
823 if (ptrAttr.isNullValue()) {
824 return mlir::LLVM::ZeroOp::create(
825 rewriter, loc, converter->convertType(ptrAttr.getType()));
827 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
828 mlir::Value ptrVal = mlir::LLVM::ConstantOp::create(
830 rewriter.getIntegerType(layout.getTypeSizeInBits(ptrAttr.getType())),
831 ptrAttr.getValue().getInt());
832 return mlir::LLVM::IntToPtrOp::create(
833 rewriter, loc, converter->convertType(ptrAttr.getType()), ptrVal);
837mlir::Value CIRAttrToValue::visitCirAttr(cir::BlockAddrInfoAttr blockAddrInfo) {
838 assert(blockInfoAddr &&
839 "block address lowering requires LLVMBlockAddressInfo");
844 mlir::Location loc = parentOp->getLoc();
845 mlir::LLVM::BlockTagOp matchLabel =
846 blockInfoAddr->lookupBlockTag(blockAddrInfo);
847 mlir::LLVM::BlockTagAttr tagAttr =
848 matchLabel ? matchLabel.getTag() : mlir::LLVM::BlockTagAttr{};
849 auto blkAddr = mlir::LLVM::BlockAddressAttr::get(
850 rewriter.getContext(), blockAddrInfo.getFunc(), tagAttr);
851 auto blockAddressOp = mlir::LLVM::BlockAddressOp::create(
852 rewriter, loc, mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
855 blockInfoAddr->addUnresolvedBlockAddress(blockAddressOp, blockAddrInfo);
856 return blockAddressOp;
860mlir::Value CIRAttrToValue::visitCirAttr(cir::BlockAddrDiffAttr blockAddrDiff) {
861 assert(blockInfoAddr &&
862 "block address lowering requires LLVMBlockAddressInfo");
868 mlir::Location loc = parentOp->getLoc();
869 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
870 mlir::MLIRContext *ctx = rewriter.getContext();
871 auto ptrTy = mlir::LLVM::LLVMPointerType::get(ctx);
873 auto emitBlockAddr = [&](mlir::StringAttr label) -> mlir::Value {
874 auto info = cir::BlockAddrInfoAttr::get(
875 ctx, blockAddrDiff.getFunc().getValue(), label.getValue());
876 mlir::LLVM::BlockTagOp matchLabel = blockInfoAddr->lookupBlockTag(info);
877 mlir::LLVM::BlockTagAttr tagAttr =
878 matchLabel ? matchLabel.getTag() : mlir::LLVM::BlockTagAttr{};
879 auto blkAddr = mlir::LLVM::BlockAddressAttr::get(
880 ctx, blockAddrDiff.getFunc(), tagAttr);
882 mlir::LLVM::BlockAddressOp::create(rewriter, loc, ptrTy, blkAddr);
884 blockInfoAddr->addUnresolvedBlockAddress(addrOp, info);
888 mlir::Value lhsAddr = emitBlockAddr(blockAddrDiff.getLhsLabel());
889 mlir::Value rhsAddr = emitBlockAddr(blockAddrDiff.getRhsLabel());
895 mlir::Type intptrTy =
896 rewriter.getIntegerType(layout.getTypeSizeInBits(ptrTy));
898 mlir::LLVM::PtrToIntOp::create(rewriter, loc, intptrTy, lhsAddr);
900 mlir::LLVM::PtrToIntOp::create(rewriter, loc, intptrTy, rhsAddr);
901 mlir::Value diffVal =
902 mlir::LLVM::SubOp::create(rewriter, loc, lhsInt, rhsInt);
904 mlir::Type resultTy = converter->convertType(blockAddrDiff.getType());
905 mlir::Value result = diffVal;
906 if (resultTy != intptrTy)
907 result = mlir::LLVM::TruncOp::create(rewriter, loc, resultTy, diffVal);
912mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstArrayAttr attr) {
913 mlir::Type llvmTy = converter->convertType(
attr.getType());
914 mlir::DataLayout dataLayout(parentOp->getParentOfType<mlir::ModuleOp>());
916 mlir::Location loc = parentOp->getLoc();
921 if (std::optional<mlir::Attribute> denseAttr =
923 return mlir::LLVM::ConstantOp::create(rewriter, loc, llvmTy, *denseAttr);
925 if (
attr.hasTrailingZeros())
926 result = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmTy);
928 result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
931 if (
auto arrayAttr = mlir::dyn_cast<mlir::ArrayAttr>(
attr.getElts())) {
932 for (
auto [idx, elt] : llvm::enumerate(arrayAttr)) {
933 mlir::Value init = visit(elt);
935 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
937 }
else if (
auto strAttr = mlir::dyn_cast<mlir::StringAttr>(
attr.getElts())) {
940 auto arrayTy = mlir::dyn_cast<cir::ArrayType>(strAttr.getType());
941 assert(arrayTy &&
"String attribute must have an array type");
942 mlir::Type eltTy = arrayTy.getElementType();
943 for (
auto [idx, elt] : llvm::enumerate(strAttr)) {
944 auto init = mlir::LLVM::ConstantOp::create(
945 rewriter, loc, converter->convertType(eltTy), elt);
947 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
950 llvm_unreachable(
"unexpected ConstArrayAttr elements");
957mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstRecordAttr constRecord) {
958 mlir::Type llvmTy = converter->convertType(constRecord.getType());
959 mlir::DataLayout dataLayout(parentOp->getParentOfType<mlir::ModuleOp>());
960 llvm::SmallVector<unsigned> paddingAddedIndexes;
962 paddingAddedIndexes);
963 const mlir::Location loc = parentOp->getLoc();
964 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
967 auto paddingItr = paddingAddedIndexes.begin();
972 for (
auto [idx, elt] : llvm::enumerate(constRecord.getMembers())) {
973 if (paddingItr != paddingAddedIndexes.end() && *paddingItr == idx) {
978 result = mlir::LLVM::InsertValueOp::create(rewriter, loc, result,
979 visit(elt), insertIdx);
987mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstVectorAttr attr) {
988 const mlir::Type llvmTy = converter->convertType(
attr.getType());
989 const mlir::Location loc = parentOp->getLoc();
991 SmallVector<mlir::Attribute> mlirValues;
992 for (
const mlir::Attribute elementAttr :
attr.getElts()) {
993 mlir::Attribute mlirAttr;
994 if (
auto intAttr = mlir::dyn_cast<cir::IntAttr>(elementAttr)) {
995 mlirAttr = rewriter.getIntegerAttr(
996 converter->convertType(intAttr.getType()), intAttr.getValue());
997 }
else if (
auto floatAttr = mlir::dyn_cast<cir::FPAttr>(elementAttr)) {
998 mlirAttr = rewriter.getFloatAttr(
999 converter->convertType(floatAttr.getType()), floatAttr.getValue());
1000 }
else if (
auto boolAttr = mlir::dyn_cast<cir::BoolAttr>(elementAttr)) {
1001 mlirAttr = rewriter.getBoolAttr(boolAttr.getValue());
1003 llvm_unreachable(
"vector constant with an element that is neither an "
1004 "int, a float, or a bool");
1006 mlirValues.push_back(mlirAttr);
1009 return mlir::LLVM::ConstantOp::create(
1010 rewriter, loc, llvmTy,
1011 mlir::DenseElementsAttr::get(mlir::cast<mlir::ShapedType>(llvmTy),
1016CIRAttrToValue::LoweredGlobalSymbol
1017CIRAttrToValue::getAddressOfSymbol(mlir::FlatSymbolRefAttr symbol) {
1018 auto moduleOp = parentOp->getParentOfType<mlir::ModuleOp>();
1019 cir::CIRDataLayout cirDataLayout(moduleOp);
1020 const mlir::DataLayout &dataLayout = cirDataLayout.layout;
1021 mlir::Type sourceType;
1022 unsigned addrSpace = 0;
1023 llvm::StringRef symName;
1024 mlir::Operation *sourceSymbol = symbolTables.lookupSymbolIn(moduleOp, symbol);
1025 if (
auto llvmSymbol = dyn_cast<mlir::LLVM::GlobalOp>(sourceSymbol)) {
1026 sourceType = llvmSymbol.getType();
1027 symName = llvmSymbol.getSymName();
1028 addrSpace = llvmSymbol.getAddrSpace();
1029 }
else if (
auto cirSymbol = dyn_cast<cir::GlobalOp>(sourceSymbol)) {
1032 symName = cirSymbol.getSymName();
1033 if (
auto targetAS = mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
1034 cirSymbol.getAddrSpaceAttr()))
1035 addrSpace = targetAS.getValue();
1036 }
else if (
auto llvmFun = dyn_cast<mlir::LLVM::LLVMFuncOp>(sourceSymbol)) {
1037 sourceType = llvmFun.getFunctionType();
1038 symName = llvmFun.getSymName();
1039 addrSpace = cirDataLayout.getProgramAddressSpace();
1040 }
else if (
auto fun = dyn_cast<cir::FuncOp>(sourceSymbol)) {
1041 sourceType = converter->convertType(fun.getFunctionType());
1042 symName = fun.getSymName();
1043 addrSpace = cirDataLayout.getProgramAddressSpace();
1044 }
else if (
auto alias = dyn_cast<mlir::LLVM::AliasOp>(sourceSymbol)) {
1045 sourceType = alias.getType();
1046 symName = alias.getSymName();
1048 llvm_unreachable(
"Unexpected GlobalOp type");
1051 mlir::Location loc = parentOp->getLoc();
1052 mlir::Value addr = mlir::LLVM::AddressOfOp::create(
1054 mlir::LLVM::LLVMPointerType::get(rewriter.getContext(), addrSpace),
1056 return {addr, sourceType, addrSpace};
1059mlir::Value CIRAttrToValue::castGlobalAddrToType(mlir::Value addr,
1060 mlir::Type attrType,
1061 mlir::Type sourceType,
1062 unsigned addrSpace) {
1063 mlir::Location loc = parentOp->getLoc();
1069 if (mlir::isa<cir::IntType>(attrType)) {
1070 mlir::Type llvmDstTy = converter->convertType(attrType);
1071 return mlir::LLVM::PtrToIntOp::create(rewriter, loc, llvmDstTy, addr);
1074 if (
auto ptrTy = mlir::dyn_cast<cir::PointerType>(attrType)) {
1075 auto llvmDstTy = converter->convertType<mlir::LLVM::LLVMPointerType>(ptrTy);
1077 if (llvmDstTy.getAddressSpace() != addrSpace)
1079 mlir::LLVM::AddrSpaceCastOp::create(rewriter, loc, llvmDstTy, addr);
1081 auto moduleOp = parentOp->getParentOfType<mlir::ModuleOp>();
1082 mlir::DataLayout dataLayout(moduleOp);
1083 mlir::Type llvmEltTy =
1087 if (llvmEltTy == sourceType)
1093 if (addr.getType() == llvmDstTy)
1096 return mlir::LLVM::BitcastOp::create(rewriter, loc, llvmDstTy, addr);
1099 if (mlir::isa<cir::VPtrType>(attrType))
1102 llvm_unreachable(
"Expecting pointer or integer type");
1105mlir::Value CIRAttrToValue::visitCirAttr(cir::GlobalViewAttr globalAttr) {
1106 LoweredGlobalSymbol lowered = getAddressOfSymbol(globalAttr.getSymbol());
1107 mlir::Value addrOp = lowered.addr;
1108 mlir::Type sourceType = lowered.sourceType;
1110 if (globalAttr.getIndices()) {
1111 llvm::SmallVector<mlir::LLVM::GEPArg> indices;
1113 if (mlir::isa<mlir::LLVM::LLVMArrayType, mlir::LLVM::LLVMStructType>(
1115 indices.push_back(0);
1117 for (mlir::Attribute idx : globalAttr.getIndices()) {
1118 auto intAttr = mlir::cast<mlir::IntegerAttr>(idx);
1119 indices.push_back(intAttr.getValue().getSExtValue());
1121 mlir::Type resTy = addrOp.getType();
1122 mlir::Type eltTy = converter->convertType(sourceType);
1123 auto gep = mlir::LLVM::GEPOp::create(rewriter, parentOp->getLoc(), resTy,
1124 eltTy, addrOp, indices,
1125 mlir::LLVM::GEPNoWrapFlags::none);
1126 if (globalAttr.getAddressPoint()) {
1130 globalAttr.getIndices().getAsValueRange<mlir::IntegerAttr>();
1131 assert(llvm::range_size(indices) == 2 &&
1132 "address point takes a vtable index and a slot index");
1133 auto vtableTy = mlir::cast<mlir::LLVM::LLVMArrayType>(
1134 mlir::cast<mlir::LLVM::LLVMStructType>(eltTy)
1135 .getBody()[(*indices.begin()).getZExtValue()]);
1136 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
1137 int64_t slotSize = layout.getTypeSize(vtableTy.getElementType());
1138 int64_t offset = (*std::next(indices.begin())).getSExtValue() * slotSize;
1139 int64_t size = vtableTy.getNumElements() * slotSize;
1140 unsigned indexBits = *layout.getTypeIndexBitwidth(
1141 mlir::cast<mlir::LLVM::LLVMPointerType>(addrOp.getType()));
1142 gep.setNoWrapFlags(mlir::LLVM::GEPNoWrapFlags::inbounds);
1143 gep.setInrangeAttr(mlir::LLVM::ConstantRangeAttr::get(
1144 rewriter.getContext(), indexBits, -offset, size - offset));
1149 return castGlobalAddrToType(addrOp, globalAttr.getType(), sourceType,
1153mlir::Value CIRAttrToValue::visitCirAttr(cir::GlobalOffsetAttr globalAttr) {
1154 LoweredGlobalSymbol lowered = getAddressOfSymbol(globalAttr.getSymbol());
1155 mlir::Value addrOp = lowered.addr;
1156 mlir::Location loc = parentOp->getLoc();
1160 mlir::Value offset = mlir::LLVM::ConstantOp::create(
1161 rewriter, loc, rewriter.getI64Type(),
1162 rewriter.getI64IntegerAttr(globalAttr.getOffset()));
1163 addrOp = mlir::LLVM::GEPOp::create(
1164 rewriter, loc, addrOp.getType(), rewriter.getI8Type(), addrOp,
1165 mlir::ValueRange{offset}, mlir::LLVM::GEPNoWrapFlags::none);
1167 return castGlobalAddrToType(addrOp, globalAttr.getType(), lowered.sourceType,
1172mlir::Value CIRAttrToValue::visitCirAttr(cir::TypeInfoAttr typeInfoAttr) {
1173 mlir::Type llvmTy = converter->convertType(typeInfoAttr.getType());
1174 mlir::Location loc = parentOp->getLoc();
1175 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
1177 for (
auto [idx, elt] : llvm::enumerate(typeInfoAttr.getData())) {
1178 mlir::Value init = visit(elt);
1180 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
1187mlir::Value CIRAttrToValue::visitCirAttr(cir::UndefAttr undefAttr) {
1188 mlir::Location loc = parentOp->getLoc();
1189 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
1190 return mlir::LLVM::UndefOp::create(
1196mlir::Value CIRAttrToValue::visitCirAttr(cir::PoisonAttr poisonAttr) {
1197 mlir::Location loc = parentOp->getLoc();
1198 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
1199 return mlir::LLVM::PoisonOp::create(
1205mlir::Value CIRAttrToValue::visitCirAttr(cir::VTableAttr vtableArr) {
1206 mlir::Type llvmTy = converter->convertType(vtableArr.getType());
1207 mlir::Location loc = parentOp->getLoc();
1208 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
1210 for (
auto [idx, elt] : llvm::enumerate(vtableArr.getData())) {
1211 mlir::Value init = visit(elt);
1213 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
1220mlir::Value CIRAttrToValue::visitCirAttr(cir::ZeroAttr attr) {
1221 mlir::Location loc = parentOp->getLoc();
1222 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
1223 return mlir::LLVM::ZeroOp::create(
1232 mlir::ConversionPatternRewriter &rewriter)
1233 : llvmType(type), dataLayout(dataLayout), rewriter(rewriter) {}
1236 return llvm::TypeSwitch<mlir::Attribute, mlir::Attribute>(
attr)
1237 .Case<cir::IntAttr, cir::FPAttr, cir::BoolAttr>(
1239 .
Default([&](
auto attrT) {
return mlir::Attribute(); });
1246 if (
auto intTy = mlir::dyn_cast<cir::IntType>(
attr.getType());
1247 intTy && intTy.isBitInt())
1249 llvm::APInt val =
attr.getValue();
1251 return rewriter.getIntegerAttr(llvmType,
attr.getValue());
1255 return rewriter.getFloatAttr(llvmType,
attr.getValue());
1259 return rewriter.getBoolAttr(
attr.getValue());
1263 mlir::Type llvmType;
1264 const mlir::DataLayout &dataLayout;
1265 mlir::ConversionPatternRewriter &rewriter;
1273 :
public mlir::PassWrapper<ConvertCIRToLLVMPass,
1274 mlir::OperationPass<mlir::ModuleOp>> {
1276 registry.insert<mlir::BuiltinDialect, mlir::DLTIDialect,
1277 mlir::LLVM::LLVMDialect, mlir::func::FuncDialect>();
1295 return "Convert the prepared CIR dialect module to LLVM dialect";
1302 struct CollectedAnnotation {
1303 mlir::StringAttr symName;
1304 cir::AnnotationAttr annotation;
1306 CollectedAnnotation(mlir::StringAttr symName,
1307 cir::AnnotationAttr annotation, mlir::Location loc)
1308 : symName(symName), annotation(annotation), loc(loc) {}
1313mlir::LogicalResult CIRToLLVMIsFPClassOpLowering::matchAndRewrite(
1314 cir::IsFPClassOp op, OpAdaptor adaptor,
1315 mlir::ConversionPatternRewriter &rewriter)
const {
1316 mlir::Value src = adaptor.getSrc();
1317 cir::FPClassTest flags = adaptor.getFlags();
1318 mlir::IntegerType retTy = rewriter.getI1Type();
1320 rewriter.replaceOpWithNewOp<mlir::LLVM::IsFPClass>(
1321 op, retTy, src,
static_cast<uint32_t>(flags));
1322 return mlir::success();
1325mlir::LogicalResult CIRToLLVMSignBitOpLowering::matchAndRewrite(
1326 cir::SignBitOp op, OpAdaptor adaptor,
1327 mlir::ConversionPatternRewriter &rewriter)
const {
1330 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
1331 int width = layout.getTypeSizeInBits(op.getInput().getType());
1332 if (
auto longDoubleType =
1333 mlir::dyn_cast<cir::LongDoubleType>(op.getInput().getType())) {
1334 if (mlir::isa<cir::FP80Type>(longDoubleType.getUnderlying())) {
1342 mlir::Type intTy = mlir::IntegerType::get(rewriter.getContext(), width);
1343 auto bitcast = mlir::LLVM::BitcastOp::create(rewriter, op->getLoc(), intTy,
1344 adaptor.getInput());
1346 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op->getLoc(), intTy, 0);
1347 auto cmpResult = mlir::LLVM::ICmpOp::create(rewriter, op.getLoc(),
1348 mlir::LLVM::ICmpPredicate::slt,
1349 bitcast.getResult(), zero);
1350 rewriter.replaceOp(op, cmpResult);
1351 return mlir::success();
1354mlir::LogicalResult CIRToLLVMAssumeOpLowering::matchAndRewrite(
1355 cir::AssumeOp op, OpAdaptor adaptor,
1356 mlir::ConversionPatternRewriter &rewriter)
const {
1357 mlir::Value cond = adaptor.getPredicate();
1358 if (op.getBundleKind() == cir::AssumeBundleKind::None) {
1359 rewriter.replaceOpWithNewOp<mlir::LLVM::AssumeOp>(op, cond);
1360 return mlir::success();
1363 llvm::StringRef tag = cir::stringifyAssumeBundleKind(op.getBundleKind());
1364 rewriter.replaceOpWithNewOp<mlir::LLVM::AssumeOp>(op, cond, tag,
1365 adaptor.getBundleArgs());
1366 return mlir::success();
1369static mlir::LLVM::AtomicOrdering
1372 return mlir::LLVM::AtomicOrdering::not_atomic;
1373 switch (*memorder) {
1374 case cir::MemOrder::Relaxed:
1375 return mlir::LLVM::AtomicOrdering::monotonic;
1376 case cir::MemOrder::Consume:
1377 case cir::MemOrder::Acquire:
1378 return mlir::LLVM::AtomicOrdering::acquire;
1379 case cir::MemOrder::Release:
1380 return mlir::LLVM::AtomicOrdering::release;
1381 case cir::MemOrder::AcquireRelease:
1382 return mlir::LLVM::AtomicOrdering::acq_rel;
1383 case cir::MemOrder::SequentiallyConsistent:
1384 return mlir::LLVM::AtomicOrdering::seq_cst;
1386 llvm_unreachable(
"unknown memory order");
1390 switch (syncScope) {
1391 case cir::SyncScopeKind::SingleThread:
1392 case cir::SyncScopeKind::HIPSingleThread:
1393 return llvm::AtomicScope::Single;
1394 case cir::SyncScopeKind::Wavefront:
1395 case cir::SyncScopeKind::HIPWavefront:
1396 case cir::SyncScopeKind::OpenCLSubGroup:
1397 return llvm::AtomicScope::Wavefront;
1398 case cir::SyncScopeKind::Workgroup:
1399 case cir::SyncScopeKind::HIPWorkgroup:
1400 case cir::SyncScopeKind::OpenCLWorkGroup:
1401 return llvm::AtomicScope::Workgroup;
1402 case cir::SyncScopeKind::Cluster:
1403 case cir::SyncScopeKind::HIPCluster:
1404 return llvm::AtomicScope::Cluster;
1405 case cir::SyncScopeKind::Device:
1406 case cir::SyncScopeKind::HIPAgent:
1407 case cir::SyncScopeKind::OpenCLDevice:
1408 return llvm::AtomicScope::Device;
1409 case cir::SyncScopeKind::System:
1410 case cir::SyncScopeKind::HIPSystem:
1411 case cir::SyncScopeKind::OpenCLAllSVMDevices:
1412 return llvm::AtomicScope::System;
1414 llvm_unreachable(
"unknown sync scope");
1418 mlir::ModuleOp moduleOp) {
1420 if (
auto triple = moduleOp->getAttrOfType<mlir::StringAttr>(
1421 cir::CIRDialect::getTripleAttrName()))
1422 if (std::optional<llvm::StringRef> name = llvm::getAtomicScopeIRString(
1423 llvm::Triple(triple.getValue()), scope))
1425 return scope == llvm::AtomicScope::Single ?
"singlethread" :
"";
1428static std::optional<llvm::StringRef>
1430 mlir::ModuleOp moduleOp) {
1431 if (syncScope.has_value())
1433 return std::nullopt;
1437 mlir::Operation *llvmOp,
1438 mlir::Value llvmPtr) {
1439 llvm::StringRef name = cir::CIRDialect::getAMDGPUNoPrivateAddrSpaceAttrName();
1440 auto ptrTy = mlir::cast<mlir::LLVM::LLVMPointerType>(llvmPtr.getType());
1441 mlir::Attribute a = op->getAttr(name);
1442 if (a && ptrTy.getAddressSpace() == llvm::AMDGPUAS::FLAT_ADDRESS)
1443 llvmOp->setAttr(name, a);
1446mlir::LogicalResult CIRToLLVMAtomicCmpXchgOpLowering::matchAndRewrite(
1447 cir::AtomicCmpXchgOp op, OpAdaptor adaptor,
1448 mlir::ConversionPatternRewriter &rewriter)
const {
1449 mlir::Value expected = adaptor.getExpected();
1450 mlir::Value desired = adaptor.getDesired();
1452 auto cmpxchg = mlir::LLVM::AtomicCmpXchgOp::create(
1453 rewriter, op.getLoc(), adaptor.getPtr(), expected, desired,
1457 op->getParentOfType<mlir::ModuleOp>()));
1459 cmpxchg.setAlignment(adaptor.getAlignment());
1460 cmpxchg.setWeak(adaptor.getWeak());
1461 cmpxchg.setVolatile_(adaptor.getIsVolatile());
1465 auto old = mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(),
1466 cmpxchg.getResult(), 0);
1467 auto cmp = mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(),
1468 cmpxchg.getResult(), 1);
1470 rewriter.replaceOp(op, {old, cmp});
1471 return mlir::success();
1474mlir::LogicalResult CIRToLLVMAtomicXchgOpLowering::matchAndRewrite(
1475 cir::AtomicXchgOp op, OpAdaptor adaptor,
1476 mlir::ConversionPatternRewriter &rewriter)
const {
1478 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(adaptor.getMemOrder());
1480 op.getSyncScope(), op->getParentOfType<mlir::ModuleOp>());
1481 auto xchg = rewriter.replaceOpWithNewOp<mlir::LLVM::AtomicRMWOp>(
1482 op, mlir::LLVM::AtomicBinOp::xchg, adaptor.getPtr(), adaptor.getVal(),
1483 llvmOrder, llvmSyncScope, 0, op.getIsVolatile());
1485 return mlir::success();
1488mlir::LogicalResult CIRToLLVMAtomicTestAndSetOpLowering::matchAndRewrite(
1489 cir::AtomicTestAndSetOp op, OpAdaptor adaptor,
1490 mlir::ConversionPatternRewriter &rewriter)
const {
1493 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
1495 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1496 rewriter.getI8Type(), 1);
1497 auto rmw = mlir::LLVM::AtomicRMWOp::create(
1498 rewriter, op.getLoc(), mlir::LLVM::AtomicBinOp::xchg, adaptor.getPtr(),
1499 one, llvmOrder, llvm::StringRef(),
1500 adaptor.getAlignment().value_or(0), op.getIsVolatile());
1502 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1503 rewriter.getI8Type(), 0);
1504 auto cmp = mlir::LLVM::ICmpOp::create(
1505 rewriter, op.getLoc(), mlir::LLVM::ICmpPredicate::ne, rmw, zero);
1507 rewriter.replaceOp(op, cmp);
1508 return mlir::success();
1511mlir::LogicalResult CIRToLLVMAtomicClearOpLowering::matchAndRewrite(
1512 cir::AtomicClearOp op, OpAdaptor adaptor,
1513 mlir::ConversionPatternRewriter &rewriter)
const {
1516 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
1517 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1518 rewriter.getI8Type(), 0);
1519 auto store = mlir::LLVM::StoreOp::create(
1520 rewriter, op.getLoc(), zero, adaptor.getPtr(),
1521 adaptor.getAlignment().value_or(0), op.getIsVolatile(),
1522 false,
false, llvmOrder);
1524 rewriter.replaceOp(op, store);
1525 return mlir::success();
1528mlir::LogicalResult CIRToLLVMAtomicFenceOpLowering::matchAndRewrite(
1529 cir::AtomicFenceOp op, OpAdaptor adaptor,
1530 mlir::ConversionPatternRewriter &rewriter)
const {
1531 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(adaptor.getOrdering());
1533 auto fence = mlir::LLVM::FenceOp::create(rewriter, op.getLoc(), llvmOrder);
1535 op->getParentOfType<mlir::ModuleOp>()));
1536 if (mlir::Attribute mmra =
1537 op->getAttr(mlir::LLVM::LLVMDialect::getMmraAttrName()))
1538 fence->setAttr(mlir::LLVM::LLVMDialect::getMmraAttrName(), mmra);
1540 rewriter.replaceOp(op, fence);
1542 return mlir::success();
1545static mlir::LLVM::AtomicBinOp
1548 case cir::AtomicFetchKind::Add:
1549 return isInt ? mlir::LLVM::AtomicBinOp::add : mlir::LLVM::AtomicBinOp::fadd;
1550 case cir::AtomicFetchKind::Sub:
1551 return isInt ? mlir::LLVM::AtomicBinOp::sub : mlir::LLVM::AtomicBinOp::fsub;
1552 case cir::AtomicFetchKind::And:
1553 return mlir::LLVM::AtomicBinOp::_and;
1554 case cir::AtomicFetchKind::Xor:
1555 return mlir::LLVM::AtomicBinOp::_xor;
1556 case cir::AtomicFetchKind::Or:
1557 return mlir::LLVM::AtomicBinOp::_or;
1558 case cir::AtomicFetchKind::Nand:
1559 return mlir::LLVM::AtomicBinOp::nand;
1560 case cir::AtomicFetchKind::Max: {
1562 return mlir::LLVM::AtomicBinOp::fmax;
1563 return isSignedInt ? mlir::LLVM::AtomicBinOp::max
1564 : mlir::LLVM::AtomicBinOp::umax;
1566 case cir::AtomicFetchKind::Min: {
1568 return mlir::LLVM::AtomicBinOp::fmin;
1569 return isSignedInt ? mlir::LLVM::AtomicBinOp::min
1570 : mlir::LLVM::AtomicBinOp::umin;
1572 case cir::AtomicFetchKind::UIncWrap:
1573 return mlir::LLVM::AtomicBinOp::uinc_wrap;
1574 case cir::AtomicFetchKind::UDecWrap:
1575 return mlir::LLVM::AtomicBinOp::udec_wrap;
1576 case cir::AtomicFetchKind::Maximum:
1577 return mlir::LLVM::AtomicBinOp::fmaximum;
1578 case cir::AtomicFetchKind::Minimum:
1579 return mlir::LLVM::AtomicBinOp::fminimum;
1580 case cir::AtomicFetchKind::MaximumNum:
1581 return mlir::LLVM::AtomicBinOp::fmaximumnum;
1582 case cir::AtomicFetchKind::MinimumNum:
1583 return mlir::LLVM::AtomicBinOp::fminimumnum;
1585 llvm_unreachable(
"Unknown atomic fetch opcode");
1591 case cir::AtomicFetchKind::Add:
1592 return isInt ? mlir::LLVM::AddOp::getOperationName()
1593 : mlir::LLVM::FAddOp::getOperationName();
1594 case cir::AtomicFetchKind::Sub:
1595 return isInt ? mlir::LLVM::SubOp::getOperationName()
1596 : mlir::LLVM::FSubOp::getOperationName();
1597 case cir::AtomicFetchKind::And:
1598 return mlir::LLVM::AndOp::getOperationName();
1599 case cir::AtomicFetchKind::Xor:
1600 return mlir::LLVM::XOrOp::getOperationName();
1601 case cir::AtomicFetchKind::Or:
1602 return mlir::LLVM::OrOp::getOperationName();
1603 case cir::AtomicFetchKind::Nand:
1605 return mlir::LLVM::AndOp::getOperationName();
1606 case cir::AtomicFetchKind::Max:
1607 case cir::AtomicFetchKind::Min:
1608 llvm_unreachable(
"handled in buildMinMaxPostOp");
1609 case cir::AtomicFetchKind::UIncWrap:
1610 case cir::AtomicFetchKind::UDecWrap:
1611 case cir::AtomicFetchKind::Maximum:
1612 case cir::AtomicFetchKind::Minimum:
1613 case cir::AtomicFetchKind::MaximumNum:
1614 case cir::AtomicFetchKind::MinimumNum:
1615 llvm_unreachable(
"uinc_wrap, udec_wrap, maximum, minimum, maximum_num, and "
1616 "minimum_num are always fetch_first");
1618 llvm_unreachable(
"Unknown atomic fetch opcode");
1621mlir::Value CIRToLLVMAtomicFetchOpLowering::buildPostOp(
1622 cir::AtomicFetchOp op, OpAdaptor adaptor,
1623 mlir::ConversionPatternRewriter &rewriter, mlir::Value rmwVal,
1628 .create(op.getLoc(),
1629 rewriter.getStringAttr(
1631 atomicOperands, atomicResTys, {})
1635mlir::Value CIRToLLVMAtomicFetchOpLowering::buildMinMaxPostOp(
1636 cir::AtomicFetchOp op, OpAdaptor adaptor,
1637 mlir::ConversionPatternRewriter &rewriter, mlir::Value rmwVal,
bool isInt,
1638 bool isSigned)
const {
1639 mlir::Location loc = op.getLoc();
1642 if (op.getBinop() == cir::AtomicFetchKind::Max)
1643 return mlir::LLVM::MaxNumOp::create(rewriter, loc, rmwVal,
1645 return mlir::LLVM::MinNumOp::create(rewriter, loc, rmwVal,
1649 mlir::LLVM::ICmpPredicate pred;
1650 if (op.getBinop() == cir::AtomicFetchKind::Max) {
1651 pred = isSigned ? mlir::LLVM::ICmpPredicate::sgt
1652 : mlir::LLVM::ICmpPredicate::ugt;
1654 pred = isSigned ? mlir::LLVM::ICmpPredicate::slt
1655 : mlir::LLVM::ICmpPredicate::ult;
1657 mlir::Value cmp = mlir::LLVM::ICmpOp::create(
1659 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(), pred), rmwVal,
1661 return mlir::LLVM::SelectOp::create(rewriter, loc, cmp, rmwVal,
1665mlir::LogicalResult CIRToLLVMAtomicFetchOpLowering::matchAndRewrite(
1666 cir::AtomicFetchOp op, OpAdaptor adaptor,
1667 mlir::ConversionPatternRewriter &rewriter)
const {
1669 bool isSignedInt =
false;
1670 if (
auto intTy = mlir::dyn_cast<cir::IntType>(op.getVal().getType())) {
1672 isSignedInt = intTy.isSigned();
1673 }
else if (mlir::isa<cir::SingleType, cir::DoubleType>(
1674 op.getVal().getType())) {
1677 return op.emitError() <<
"Unsupported type: " << op.getVal().getType();
1680 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
1682 op.getSyncScope(), op->getParentOfType<mlir::ModuleOp>());
1683 mlir::LLVM::AtomicBinOp llvmBinOp =
1685 auto rmwVal = mlir::LLVM::AtomicRMWOp::create(
1686 rewriter, op.getLoc(), llvmBinOp, adaptor.getPtr(), adaptor.getVal(),
1687 llvmOrder, llvmSyncScope, 0, op.getIsVolatile());
1691 for (llvm::StringRef marker :
1692 {cir::CIRDialect::getAMDGPUNoFineGrainedMemoryAttrName(),
1693 cir::CIRDialect::getAMDGPUNoRemoteMemoryAttrName(),
1694 cir::CIRDialect::getAMDGPUIgnoreDenormalModeAttrName()})
1695 if (mlir::Attribute a = op->getAttr(marker))
1696 rmwVal->setAttr(marker, a);
1702 if (op->hasAttr(cir::CIRDialect::getAMDGPURawAtomicAttrName())) {
1704 mlir::cast<mlir::LLVM::LLVMPointerType>(adaptor.getPtr().getType());
1705 if (ptrTy.getAddressSpace() != llvm::AMDGPUAS::LOCAL_ADDRESS) {
1706 mlir::UnitAttr unit = rewriter.getUnitAttr();
1707 rmwVal->setAttr(cir::CIRDialect::getAMDGPUNoFineGrainedMemoryAttrName(),
1710 if (llvmBinOp == mlir::LLVM::AtomicBinOp::fadd &&
1711 mlir::isa<cir::SingleType>(op.getVal().getType()))
1712 rmwVal->setAttr(cir::CIRDialect::getAMDGPUIgnoreDenormalModeAttrName(),
1717 mlir::Value result = rmwVal.getResult();
1718 if (!op.getFetchFirst()) {
1719 if (op.getBinop() == cir::AtomicFetchKind::Max ||
1720 op.getBinop() == cir::AtomicFetchKind::Min)
1721 result = buildMinMaxPostOp(op, adaptor, rewriter, rmwVal.getRes(), isInt,
1724 result = buildPostOp(op, adaptor, rewriter, rmwVal.getRes(), isInt);
1727 if (op.getBinop() == cir::AtomicFetchKind::Nand) {
1728 auto negOne = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1729 result.getType(), -1);
1730 result = mlir::LLVM::XOrOp::create(rewriter, op.getLoc(), result, negOne);
1734 rewriter.replaceOp(op, result);
1735 return mlir::success();
1738mlir::LogicalResult CIRToLLVMBitClrsbOpLowering::matchAndRewrite(
1739 cir::BitClrsbOp op, OpAdaptor adaptor,
1740 mlir::ConversionPatternRewriter &rewriter)
const {
1741 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1742 adaptor.getInput().getType(), 0);
1743 auto isNeg = mlir::LLVM::ICmpOp::create(
1744 rewriter, op.getLoc(),
1745 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(),
1746 mlir::LLVM::ICmpPredicate::slt),
1747 adaptor.getInput(), zero);
1749 auto negOne = mlir::LLVM::ConstantOp::create(
1750 rewriter, op.getLoc(), adaptor.getInput().getType(), -1);
1751 auto flipped = mlir::LLVM::XOrOp::create(rewriter, op.getLoc(),
1752 adaptor.getInput(), negOne);
1754 auto select = mlir::LLVM::SelectOp::create(rewriter, op.getLoc(), isNeg,
1755 flipped, adaptor.getInput());
1757 auto resTy = getTypeConverter()->convertType(op.getType());
1758 auto clz = mlir::LLVM::CountLeadingZerosOp::create(
1759 rewriter, op.getLoc(), resTy,
select,
false);
1761 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1762 auto res = mlir::LLVM::SubOp::create(rewriter, op.getLoc(),
clz, one,
1763 mlir::LLVM::IntegerOverflowFlags::nuw);
1764 rewriter.replaceOp(op, res);
1766 return mlir::LogicalResult::success();
1769mlir::LogicalResult CIRToLLVMBitClzOpLowering::matchAndRewrite(
1770 cir::BitClzOp op, OpAdaptor adaptor,
1771 mlir::ConversionPatternRewriter &rewriter)
const {
1772 auto resTy = getTypeConverter()->convertType(op.getType());
1773 auto llvmOp = mlir::LLVM::CountLeadingZerosOp::create(
1774 rewriter, op.getLoc(), resTy, adaptor.getInput(), op.getPoisonZero());
1775 rewriter.replaceOp(op, llvmOp);
1776 return mlir::LogicalResult::success();
1779mlir::LogicalResult CIRToLLVMBitCtzOpLowering::matchAndRewrite(
1780 cir::BitCtzOp op, OpAdaptor adaptor,
1781 mlir::ConversionPatternRewriter &rewriter)
const {
1782 auto resTy = getTypeConverter()->convertType(op.getType());
1783 auto llvmOp = mlir::LLVM::CountTrailingZerosOp::create(
1784 rewriter, op.getLoc(), resTy, adaptor.getInput(), op.getPoisonZero());
1785 rewriter.replaceOp(op, llvmOp);
1786 return mlir::LogicalResult::success();
1789mlir::LogicalResult CIRToLLVMBitFfsOpLowering::matchAndRewrite(
1790 cir::BitFfsOp op, OpAdaptor adaptor,
1791 mlir::ConversionPatternRewriter &rewriter)
const {
1792 auto resTy = getTypeConverter()->convertType(op.getType());
1793 auto ctz = mlir::LLVM::CountTrailingZerosOp::create(rewriter, op.getLoc(),
1794 resTy, adaptor.getInput(),
1797 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1798 auto ctzAddOne = mlir::LLVM::AddOp::create(rewriter, op.getLoc(),
ctz, one);
1800 auto zeroInputTy = mlir::LLVM::ConstantOp::create(
1801 rewriter, op.getLoc(), adaptor.getInput().getType(), 0);
1802 auto isZero = mlir::LLVM::ICmpOp::create(
1803 rewriter, op.getLoc(),
1804 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(),
1805 mlir::LLVM::ICmpPredicate::eq),
1806 adaptor.getInput(), zeroInputTy);
1808 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 0);
1809 auto res = mlir::LLVM::SelectOp::create(rewriter, op.getLoc(), isZero, zero,
1811 rewriter.replaceOp(op, res);
1813 return mlir::LogicalResult::success();
1816mlir::LogicalResult CIRToLLVMBitParityOpLowering::matchAndRewrite(
1817 cir::BitParityOp op, OpAdaptor adaptor,
1818 mlir::ConversionPatternRewriter &rewriter)
const {
1819 auto resTy = getTypeConverter()->convertType(op.getType());
1820 auto popcnt = mlir::LLVM::CtPopOp::create(rewriter, op.getLoc(), resTy,
1821 adaptor.getInput());
1823 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1825 mlir::LLVM::AndOp::create(rewriter, op.getLoc(), popcnt, one);
1826 rewriter.replaceOp(op, popcntMod2);
1828 return mlir::LogicalResult::success();
1831mlir::LogicalResult CIRToLLVMBitPopcountOpLowering::matchAndRewrite(
1832 cir::BitPopcountOp op, OpAdaptor adaptor,
1833 mlir::ConversionPatternRewriter &rewriter)
const {
1834 auto resTy = getTypeConverter()->convertType(op.getType());
1835 auto llvmOp = mlir::LLVM::CtPopOp::create(rewriter, op.getLoc(), resTy,
1836 adaptor.getInput());
1837 rewriter.replaceOp(op, llvmOp);
1838 return mlir::LogicalResult::success();
1841mlir::LogicalResult CIRToLLVMBrCondOpLowering::matchAndRewrite(
1842 cir::BrCondOp brOp, OpAdaptor adaptor,
1843 mlir::ConversionPatternRewriter &rewriter)
const {
1848 mlir::Value i1Condition = adaptor.getCond();
1850 rewriter.replaceOpWithNewOp<mlir::LLVM::CondBrOp>(
1851 brOp, i1Condition, brOp.getDestTrue(), adaptor.getDestOperandsTrue(),
1852 brOp.getDestFalse(), adaptor.getDestOperandsFalse());
1854 return mlir::success();
1857mlir::Type CIRToLLVMCastOpLowering::convertTy(mlir::Type ty)
const {
1858 return getTypeConverter()->convertType(ty);
1861mlir::LogicalResult CIRToLLVMCastOpLowering::matchAndRewrite(
1862 cir::CastOp castOp, OpAdaptor adaptor,
1863 mlir::ConversionPatternRewriter &rewriter)
const {
1868 switch (castOp.getKind()) {
1869 case cir::CastKind::array_to_ptrdecay: {
1870 const auto ptrTy = mlir::cast<cir::PointerType>(castOp.getType());
1871 mlir::Value sourceValue = adaptor.getSrc();
1872 mlir::Type targetType = convertTy(ptrTy);
1874 ptrTy.getPointee());
1875 llvm::SmallVector<mlir::LLVM::GEPArg> offset{0};
1876 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1877 castOp, targetType, elementTy, sourceValue, offset);
1880 case cir::CastKind::int_to_bool: {
1881 mlir::Value llvmSrcVal = adaptor.getSrc();
1885 mlir::Value zeroInt = mlir::LLVM::ConstantOp::create(
1886 rewriter, castOp.getLoc(), llvmSrcVal.getType(),
1887 rewriter.getZeroAttr(llvmSrcVal.getType()));
1888 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
1889 castOp, mlir::LLVM::ICmpPredicate::ne, llvmSrcVal, zeroInt);
1892 case cir::CastKind::integral: {
1893 mlir::Type srcType = castOp.getSrc().getType();
1894 mlir::Type dstType = castOp.getType();
1895 mlir::Value llvmSrcVal = adaptor.getSrc();
1896 mlir::Type llvmDstType = getTypeConverter()->convertType(dstType);
1897 cir::IntType srcIntType =
1898 mlir::cast<cir::IntType>(elementTypeIfVectorOrMatrix(srcType));
1899 cir::IntType dstIntType =
1900 mlir::cast<cir::IntType>(elementTypeIfVectorOrMatrix(dstType));
1901 rewriter.replaceOp(castOp,
getLLVMIntCast(rewriter, llvmSrcVal, llvmDstType,
1902 srcIntType.isUnsigned(),
1903 srcIntType.getWidth(),
1904 dstIntType.getWidth()));
1907 case cir::CastKind::floating: {
1908 mlir::Value llvmSrcVal = adaptor.getSrc();
1909 mlir::Type llvmDstTy = getTypeConverter()->convertType(castOp.getType());
1911 mlir::Type srcTy = elementTypeIfVectorOrMatrix(castOp.getSrc().getType());
1912 mlir::Type dstTy = elementTypeIfVectorOrMatrix(castOp.getType());
1914 if (!mlir::isa<cir::FPTypeInterface>(dstTy) ||
1915 !mlir::isa<cir::FPTypeInterface>(srcTy))
1916 return castOp.emitError() <<
"NYI cast from " << srcTy <<
" to " << dstTy;
1918 auto getFloatWidth = [](mlir::Type ty) ->
unsigned {
1919 return mlir::cast<cir::FPTypeInterface>(ty).getWidth();
1922 bool isTrunc = getFloatWidth(srcTy) > getFloatWidth(dstTy);
1923 if (cir::FenvAttr fenv = castOp.getFenvAttr()) {
1927 castOp, llvmSrcVal, fenv, llvmDstTy, rewriter,
1928 isTrunc ?
"fptrunc" :
"fpext", isTrunc);
1931 rewriter.replaceOpWithNewOp<mlir::LLVM::FPTruncOp>(castOp, llvmDstTy,
1934 rewriter.replaceOpWithNewOp<mlir::LLVM::FPExtOp>(castOp, llvmDstTy,
1936 return mlir::success();
1938 case cir::CastKind::int_to_ptr: {
1939 auto dstTy = mlir::cast<cir::PointerType>(castOp.getType());
1940 mlir::Value llvmSrcVal = adaptor.getSrc();
1941 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1942 rewriter.replaceOpWithNewOp<mlir::LLVM::IntToPtrOp>(castOp, llvmDstTy,
1944 return mlir::success();
1946 case cir::CastKind::ptr_to_int: {
1947 auto dstTy = mlir::cast<cir::IntType>(castOp.getType());
1948 mlir::Value llvmSrcVal = adaptor.getSrc();
1949 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1950 rewriter.replaceOpWithNewOp<mlir::LLVM::PtrToIntOp>(castOp, llvmDstTy,
1952 return mlir::success();
1954 case cir::CastKind::float_to_bool: {
1955 mlir::Value llvmSrcVal = adaptor.getSrc();
1956 auto kind = mlir::LLVM::FCmpPredicate::une;
1961 auto zeroFloat = mlir::LLVM::ConstantOp::create(
1962 rewriter, castOp.getLoc(), llvmSrcVal.getType(),
1963 rewriter.getZeroAttr(llvmSrcVal.getType()));
1966 rewriter.replaceOpWithNewOp<mlir::LLVM::FCmpOp>(castOp,
kind, llvmSrcVal,
1969 return mlir::success();
1971 case cir::CastKind::bool_to_int: {
1972 mlir::Type dstTy = castOp.getType();
1973 mlir::Value llvmSrcVal = adaptor.getSrc();
1974 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1976 auto srcElemTy = mlir::cast<mlir::IntegerType>(
1977 elementTypeIfVectorOrMatrix(llvmSrcVal.getType()));
1979 mlir::cast<cir::IntType>(elementTypeIfVectorOrMatrix(dstTy));
1981 if (srcElemTy.getWidth() == dstElemTy.getWidth())
1982 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(castOp, llvmDstTy,
1985 rewriter.replaceOpWithNewOp<mlir::LLVM::ZExtOp>(castOp, llvmDstTy,
1987 return mlir::success();
1989 case cir::CastKind::bool_to_float: {
1990 mlir::Type dstTy = castOp.getType();
1991 mlir::Value llvmSrcVal = adaptor.getSrc();
1992 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1993 rewriter.replaceOpWithNewOp<mlir::LLVM::UIToFPOp>(castOp, llvmDstTy,
1995 return mlir::success();
1997 case cir::CastKind::int_to_float: {
1998 mlir::Type dstTy = castOp.getType();
1999 mlir::Value llvmSrcVal = adaptor.getSrc();
2000 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
2001 bool isSigned = mlir::cast<cir::IntType>(
2002 elementTypeIfVectorOrMatrix(castOp.getSrc().getType()))
2004 if (cir::FenvAttr fenv = castOp.getFenvAttr()) {
2006 castOp, llvmSrcVal, fenv, llvmDstTy, rewriter,
2007 isSigned ?
"sitofp" :
"uitofp",
true);
2010 rewriter.replaceOpWithNewOp<mlir::LLVM::SIToFPOp>(castOp, llvmDstTy,
2013 rewriter.replaceOpWithNewOp<mlir::LLVM::UIToFPOp>(castOp, llvmDstTy,
2015 return mlir::success();
2017 case cir::CastKind::float_to_int: {
2018 mlir::Type dstTy = castOp.getType();
2019 mlir::Value llvmSrcVal = adaptor.getSrc();
2020 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
2022 mlir::cast<cir::IntType>(elementTypeIfVectorOrMatrix(castOp.getType()))
2024 if (cir::FenvAttr fenv = castOp.getFenvAttr()) {
2026 castOp, llvmSrcVal, fenv, llvmDstTy, rewriter,
2027 isSigned ?
"fptosi" :
"fptoui",
false);
2030 rewriter.replaceOpWithNewOp<mlir::LLVM::FPToSIOp>(castOp, llvmDstTy,
2033 rewriter.replaceOpWithNewOp<mlir::LLVM::FPToUIOp>(castOp, llvmDstTy,
2035 return mlir::success();
2037 case cir::CastKind::bitcast: {
2038 mlir::Type dstTy = castOp.getType();
2039 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
2044 mlir::Value llvmSrcVal = adaptor.getSrc();
2045 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(castOp, llvmDstTy,
2047 return mlir::success();
2049 case cir::CastKind::ptr_to_bool: {
2050 mlir::Value llvmSrcVal = adaptor.getSrc();
2051 mlir::Value zeroPtr = mlir::LLVM::ZeroOp::create(rewriter, castOp.getLoc(),
2052 llvmSrcVal.getType());
2053 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
2054 castOp, mlir::LLVM::ICmpPredicate::ne, llvmSrcVal, zeroPtr);
2057 case cir::CastKind::address_space: {
2058 mlir::Type dstTy = castOp.getType();
2059 mlir::Value llvmSrcVal = adaptor.getSrc();
2060 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
2061 rewriter.replaceOpWithNewOp<mlir::LLVM::AddrSpaceCastOp>(castOp, llvmDstTy,
2065 case cir::CastKind::member_ptr_to_bool:
2070 return castOp.emitError(
"Unhandled cast kind: ")
2071 << castOp.getKindAttrName();
2075 return mlir::success();
2078mlir::LogicalResult CIRToLLVMBuiltinIntCastOpLowering::matchAndRewrite(
2079 cir::BuiltinIntCastOp op, OpAdaptor adaptor,
2080 mlir::ConversionPatternRewriter &rewriter)
const {
2085 if (
auto cirSrc = mlir::dyn_cast<cir::IntType>(op.getSrc().getType()))
2087 else if (
auto cirDst = mlir::dyn_cast<cir::IntType>(op.getType()))
2090 mlir::Value llvmSrc = adaptor.getSrc();
2091 mlir::Type llvmDstTy = getTypeConverter()->convertType(op.getType());
2092 auto srcIntTy = mlir::cast<mlir::IntegerType>(llvmSrc.getType());
2093 auto dstIntTy = mlir::cast<mlir::IntegerType>(llvmDstTy);
2094 unsigned srcWidth = srcIntTy.getWidth();
2095 unsigned dstWidth = dstIntTy.getWidth();
2100 assert((srcWidth == dstWidth ||
2101 mlir::isa<mlir::IndexType>(op.getSrc().getType()) ||
2102 mlir::isa<mlir::IndexType>(op.getType())) &&
2103 "only index casts may change width during lowering");
2108 srcWidth, dstWidth));
2109 return mlir::success();
2113 mlir::ModuleOp mod, mlir::Value index,
2114 mlir::Type baseTy, cir::IntType strideTy) {
2115 mlir::Operation *indexOp = index.getDefiningOp();
2119 auto indexType = mlir::cast<mlir::IntegerType>(index.getType());
2120 mlir::DataLayout llvmLayout(mod);
2121 std::optional<uint64_t> layoutWidth = llvmLayout.getTypeIndexBitwidth(baseTy);
2124 if (!layoutWidth || *layoutWidth == indexType.getWidth())
2130 auto sub = dyn_cast<mlir::LLVM::SubOp>(indexOp);
2131 bool rewriteSub =
false;
2133 if (
auto lhsConst = dyn_cast_if_present<mlir::LLVM::ConstantOp>(
2134 sub.getLhs().getDefiningOp())) {
2135 auto lhsConstInt = mlir::dyn_cast<mlir::IntegerAttr>(lhsConst.getValue());
2136 if (lhsConstInt && lhsConstInt.getValue() == 0) {
2137 index = sub.getRhs();
2143 auto llvmDstType = rewriter.getIntegerType(*layoutWidth);
2144 bool isUnsigned = strideTy && strideTy.isUnsigned();
2146 indexType.getWidth(), *layoutWidth);
2149 index = mlir::LLVM::SubOp::create(
2150 rewriter, index.getLoc(),
2151 mlir::LLVM::ConstantOp::create(rewriter, index.getLoc(),
2152 index.getType(), 0),
2159mlir::LogicalResult CIRToLLVMPtrStrideOpLowering::matchAndRewrite(
2160 cir::PtrStrideOp ptrStrideOp, OpAdaptor adaptor,
2161 mlir::ConversionPatternRewriter &rewriter)
const {
2163 const mlir::TypeConverter *tc = getTypeConverter();
2164 const mlir::Type resultTy = tc->convertType(ptrStrideOp.getType());
2166 mlir::Type elementTy =
2171 if (mlir::isa<mlir::LLVM::LLVMVoidType>(elementTy) ||
2172 mlir::isa<mlir::LLVM::LLVMFunctionType>(elementTy))
2173 elementTy = mlir::IntegerType::get(elementTy.getContext(), 8,
2174 mlir::IntegerType::Signless);
2176 mlir::Value index = adaptor.getStride();
2178 rewriter, ptrStrideOp->getParentOfType<mlir::ModuleOp>(), index,
2179 adaptor.getBase().getType(),
2180 dyn_cast<cir::IntType>(ptrStrideOp.getOperand(1).getType()));
2182 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
2183 ptrStrideOp, resultTy, elementTy, adaptor.getBase(), index);
2184 return mlir::success();
2187mlir::LogicalResult CIRToLLVMGetElementOpLowering::matchAndRewrite(
2188 cir::GetElementOp op, OpAdaptor adaptor,
2189 mlir::ConversionPatternRewriter &rewriter)
const {
2191 mlir::dyn_cast<cir::ArrayType>(op.getBaseType().getPointee())) {
2192 const mlir::TypeConverter *converter = getTypeConverter();
2193 const mlir::Type llArrayTy = converter->convertType(arrayTy);
2194 const mlir::Type llResultTy = converter->convertType(op.getType());
2195 mlir::Type elementTy =
2200 if (mlir::isa<mlir::LLVM::LLVMVoidType>(elementTy) ||
2201 mlir::isa<mlir::LLVM::LLVMFunctionType>(elementTy))
2202 elementTy = rewriter.getIntegerType(8);
2204 mlir::Value index = adaptor.getIndex();
2207 adaptor.getBase().getType(),
2208 dyn_cast<cir::IntType>(op.getOperand(1).getType()));
2213 std::array<mlir::LLVM::GEPArg, 2> offset{0, index};
2214 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, llResultTy, llArrayTy,
2215 adaptor.getBase(), offset);
2216 return mlir::success();
2219 op.emitError() <<
"NYI: GetElementOp lowering to LLVM for non-array";
2220 return mlir::failure();
2223mlir::LogicalResult CIRToLLVMBaseClassAddrOpLowering::matchAndRewrite(
2224 cir::BaseClassAddrOp baseClassOp, OpAdaptor adaptor,
2225 mlir::ConversionPatternRewriter &rewriter)
const {
2226 const mlir::Type resultType =
2227 getTypeConverter()->convertType(baseClassOp.getType());
2228 mlir::Value derivedAddr = adaptor.getSrcAddr();
2229 llvm::SmallVector<mlir::LLVM::GEPArg, 1> offset = {
2230 adaptor.getOffset().getZExtValue()};
2231 mlir::Type byteType = mlir::IntegerType::get(resultType.getContext(), 8,
2232 mlir::IntegerType::Signless);
2233 if (adaptor.getOffset().getZExtValue() == 0) {
2234 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(baseClassOp, resultType,
2235 adaptor.getSrcAddr());
2236 return mlir::success();
2239 if (baseClassOp.getAssumeNotNull()) {
2240 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
2241 baseClassOp, resultType, byteType, derivedAddr, offset);
2243 auto loc = baseClassOp.getLoc();
2244 mlir::Value isNull = mlir::LLVM::ICmpOp::create(
2245 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, derivedAddr,
2246 mlir::LLVM::ZeroOp::create(rewriter, loc, derivedAddr.getType()));
2247 mlir::Value adjusted = mlir::LLVM::GEPOp::create(
2248 rewriter, loc, resultType, byteType, derivedAddr, offset);
2249 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(baseClassOp, isNull,
2250 derivedAddr, adjusted);
2252 return mlir::success();
2255mlir::LogicalResult CIRToLLVMDerivedClassAddrOpLowering::matchAndRewrite(
2256 cir::DerivedClassAddrOp derivedClassOp, OpAdaptor adaptor,
2257 mlir::ConversionPatternRewriter &rewriter)
const {
2258 const mlir::Type resultType =
2259 getTypeConverter()->convertType(derivedClassOp.getType());
2260 mlir::Value baseAddr = adaptor.getSrcAddr();
2263 int64_t offsetVal = -(adaptor.getOffset().getZExtValue());
2264 if (offsetVal == 0) {
2266 rewriter.replaceOp(derivedClassOp, baseAddr);
2267 return mlir::success();
2269 llvm::SmallVector<mlir::LLVM::GEPArg, 1> offset = {offsetVal};
2270 mlir::Type byteType = mlir::IntegerType::get(resultType.getContext(), 8,
2271 mlir::IntegerType::Signless);
2272 if (derivedClassOp.getAssumeNotNull()) {
2273 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
2274 derivedClassOp, resultType, byteType, baseAddr, offset,
2275 mlir::LLVM::GEPNoWrapFlags::inbounds);
2277 mlir::Location loc = derivedClassOp.getLoc();
2278 mlir::Value isNull = mlir::LLVM::ICmpOp::create(
2279 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, baseAddr,
2280 mlir::LLVM::ZeroOp::create(rewriter, loc, baseAddr.getType()));
2281 mlir::Value adjusted =
2282 mlir::LLVM::GEPOp::create(rewriter, loc, resultType, byteType, baseAddr,
2283 offset, mlir::LLVM::GEPNoWrapFlags::inbounds);
2284 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(derivedClassOp, isNull,
2285 baseAddr, adjusted);
2287 return mlir::success();
2290mlir::LogicalResult CIRToLLVMFMaxNumOpLowering::matchAndRewrite(
2291 cir::FMaxNumOp op, OpAdaptor adaptor,
2292 mlir::ConversionPatternRewriter &rewriter)
const {
2293 mlir::Type resTy = typeConverter->convertType(op.getType());
2294 if (cir::FenvAttr fenv = op.getFenvAttr())
2296 op, adaptor.getOperands(), fenv, resTy, rewriter,
"maxnum",
2297 false, mlir::LLVM::FastmathFlags::nsz);
2298 rewriter.replaceOpWithNewOp<mlir::LLVM::MaxNumOp>(
2299 op, resTy, adaptor.getLhs(), adaptor.getRhs(),
2300 mlir::LLVM::FastmathFlags::nsz);
2301 return mlir::success();
2304mlir::LogicalResult CIRToLLVMFMinNumOpLowering::matchAndRewrite(
2305 cir::FMinNumOp op, OpAdaptor adaptor,
2306 mlir::ConversionPatternRewriter &rewriter)
const {
2307 mlir::Type resTy = typeConverter->convertType(op.getType());
2308 if (cir::FenvAttr fenv = op.getFenvAttr())
2310 op, adaptor.getOperands(), fenv, resTy, rewriter,
"minnum",
2311 false, mlir::LLVM::FastmathFlags::nsz);
2312 rewriter.replaceOpWithNewOp<mlir::LLVM::MinNumOp>(
2313 op, resTy, adaptor.getLhs(), adaptor.getRhs(),
2314 mlir::LLVM::FastmathFlags::nsz);
2315 return mlir::success();
2318mlir::LogicalResult CIRToLLVMAllocaOpLowering::matchAndRewrite(
2319 cir::AllocaOp op, OpAdaptor adaptor,
2320 mlir::ConversionPatternRewriter &rewriter)
const {
2323 ? adaptor.getDynAllocSize()
2324 : mlir::LLVM::ConstantOp::create(
2325 rewriter, op.getLoc(),
2326 typeConverter->convertType(rewriter.getI32Type()), 1);
2327 mlir::Type elementTy =
2330 return op.emitError()
2331 <<
"NYI: lowering alloca of a type with no memory representation";
2332 mlir::Type resultTy =
2338 rewriter.replaceOpWithNewOp<mlir::LLVM::AllocaOp>(op, resultTy, elementTy,
2339 size, op.getAlignment());
2341 return mlir::success();
2344mlir::LogicalResult CIRToLLVMRotateOpLowering::matchAndRewrite(
2345 cir::RotateOp op, OpAdaptor adaptor,
2346 mlir::ConversionPatternRewriter &rewriter)
const {
2349 mlir::Value input = adaptor.getInput();
2350 if (op.isRotateLeft())
2351 rewriter.replaceOpWithNewOp<mlir::LLVM::FshlOp>(op, input, input,
2352 adaptor.getAmount());
2354 rewriter.replaceOpWithNewOp<mlir::LLVM::FshrOp>(op, input, input,
2355 adaptor.getAmount());
2356 return mlir::LogicalResult::success();
2369 mlir::ArrayAttr argAttrs,
const mlir::TypeConverter &converter,
2370 const mlir::DataLayout &dataLayout, mlir::MLIRContext *ctx) {
2373 bool changed =
false;
2375 loweredArgAttrs.reserve(argAttrs.size());
2376 for (mlir::Attribute a : argAttrs) {
2377 auto dict = cast<mlir::DictionaryAttr>(a);
2379 for (mlir::NamedAttribute &entry : entries) {
2380 StringRef name = entry.getName().strref();
2381 if (name != mlir::LLVM::LLVMDialect::getByValAttrName() &&
2382 name != mlir::LLVM::LLVMDialect::getStructRetAttrName() &&
2383 name != mlir::LLVM::LLVMDialect::getByRefAttrName())
2385 auto typeAttr = dyn_cast<mlir::TypeAttr>(entry.getValue());
2388 mlir::Type lowered =
2391 return std::nullopt;
2392 if (lowered != typeAttr.getValue()) {
2393 entry.setValue(mlir::TypeAttr::get(lowered));
2397 loweredArgAttrs.push_back(mlir::DictionaryAttr::get(ctx, entries));
2399 return changed ? mlir::ArrayAttr::get(ctx, loweredArgAttrs) : argAttrs;
2409 cir::CIRCallOpInterface op,
const mlir::TypeConverter &converter,
2411 if (
auto argAttrs = mlir::dyn_cast_if_present<mlir::ArrayAttr>(
2412 op->getInherentAttr(CIRDialect::getArgAttrsAttrName())
2413 .value_or(mlir::Attribute{}))) {
2414 std::optional<mlir::ArrayAttr> lowered =
2417 return op->emitError() <<
"NYI: lowering a byval/sret/byref call "
2418 "argument whose pointee type has no "
2419 "memory representation";
2422 result.
resAttrs = mlir::dyn_cast_if_present<mlir::ArrayAttr>(
2423 op->getInherentAttr(CIRDialect::getResAttrsAttrName())
2424 .value_or(mlir::Attribute{}));
2426 for (mlir::NamedAttribute attr : op->getDiscardableAttrs()) {
2427 if (attr.getName() == CIRDialect::getNoUnwindAttrName() ||
2428 attr.getName() == CIRDialect::getNoReturnAttrName())
2433 return mlir::success();
2436template <
typename CallLikeOp>
2440 op.setArgAttrsAttr(attributes.
argAttrs);
2442 op.setResAttrsAttr(attributes.
resAttrs);
2444 if (op->getInherentAttr(attr.getName()).has_value())
2445 op->setInherentAttr(attr.getName(), attr.getValue());
2447 op->setDiscardableAttr(attr.getName(), attr.getValue());
2452 mlir::Operation *op, mlir::ValueRange callOperands,
2453 mlir::ConversionPatternRewriter &rewriter,
2454 const mlir::TypeConverter *converter,
const mlir::DataLayout &dataLayout,
2455 mlir::SymbolTableCollection &symbolTables,
2456 mlir::FlatSymbolRefAttr calleeAttr, mlir::Block *continueBlock =
nullptr,
2457 mlir::Block *landingPadBlock =
nullptr) {
2459 mlir::ValueTypeRange<mlir::ResultRange> cirResults = op->getResultTypes();
2460 auto call = cast<cir::CIRCallOpInterface>(op);
2462 if (converter->convertTypes(cirResults, llvmResults).failed())
2463 return mlir::failure();
2465 mlir::LLVM::MemoryEffectsAttr memoryEffects;
2466 bool noUnwind =
false;
2467 bool willReturn =
false;
2468 bool noReturn =
false;
2470 memoryEffects, noUnwind, willReturn, noReturn);
2475 return mlir::failure();
2477 mlir::LLVM::LLVMFunctionType llvmFnTy;
2484 mlir::Operation *callee =
2485 symbolTables.lookupNearestSymbolFrom(op, calleeAttr);
2486 if (
auto fn = mlir::dyn_cast<mlir::FunctionOpInterface>(callee)) {
2487 llvmFnTy = converter->convertType<mlir::LLVM::LLVMFunctionType>(
2488 fn.getFunctionType());
2489 assert(llvmFnTy &&
"Failed to convert function type");
2490 }
else if (
auto alias = mlir::cast<mlir::LLVM::AliasOp>(callee)) {
2498 auto symAttr = mlir::cast<mlir::FlatSymbolRefAttr>(calleeAttr);
2500 mlir::LLVM::AddressOfOp::create(
2501 rewriter, op->getLoc(),
2502 mlir::LLVM::LLVMPointerType::get(rewriter.getContext()), symAttr)
2504 adjustedCallOperands.push_back(addrOfAlias);
2507 llvm::append_range(adjustedCallOperands, callOperands);
2508 callOperands = adjustedCallOperands;
2512 llvmFnTy = mlir::cast<mlir::LLVM::LLVMFunctionType>(alias.getType());
2515 return op->emitError(
"Unexpected callee type!");
2518 assert(!op->getOperands().empty() &&
2519 "operands list must no be empty for the indirect call");
2520 auto calleeTy = op->getOperands().front().getType();
2521 auto calleePtrTy = cast<cir::PointerType>(calleeTy);
2522 auto calleeFuncTy = cast<cir::FuncType>(calleePtrTy.getPointee());
2523 llvm::append_range(adjustedCallOperands, callOperands);
2524 llvmFnTy = cast<mlir::LLVM::LLVMFunctionType>(
2525 converter->convertType(calleeFuncTy));
2530 if (landingPadBlock) {
2532 auto newOp = rewriter.replaceOpWithNewOp<mlir::LLVM::InvokeOp>(
2533 op, llvmFnTy, calleeAttr, callOperands, continueBlock,
2534 mlir::ValueRange{}, landingPadBlock, mlir::ValueRange{});
2535 newOp.setCConv(cconv);
2538 auto newOp = rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(
2539 op, llvmFnTy, calleeAttr, callOperands);
2540 newOp.setCConv(cconv);
2543 newOp.setMemoryEffectsAttr(memoryEffects);
2544 newOp.setNoUnwind(noUnwind);
2545 newOp.setWillReturn(willReturn);
2546 newOp.setNoreturn(noReturn);
2547 if (op->hasAttr(CIRDialect::getMustTailAttrName()))
2548 newOp.setTailCallKind(mlir::LLVM::TailCallKind::MustTail);
2550 if (std::optional<cir::InlineKind> inlineKind = call.getInlineKind()) {
2551 newOp.setNoInline(*inlineKind == cir::InlineKind::NoInline);
2552 newOp.setInlineHint(*inlineKind == cir::InlineKind::InlineHint);
2553 newOp.setAlwaysInline(*inlineKind == cir::InlineKind::AlwaysInline);
2557 return mlir::success();
2560mlir::LogicalResult CIRToLLVMCallOpLowering::matchAndRewrite(
2561 cir::CallOp op, OpAdaptor adaptor,
2562 mlir::ConversionPatternRewriter &rewriter)
const {
2564 getTypeConverter(), dataLayout, symbolTables,
2565 op.getCalleeAttr());
2568mlir::LogicalResult CIRToLLVMTryCallOpLowering::matchAndRewrite(
2569 cir::TryCallOp op, OpAdaptor adaptor,
2570 mlir::ConversionPatternRewriter &rewriter)
const {
2572 getTypeConverter(), dataLayout, symbolTables,
2573 op.getCalleeAttr(), op.getNormalDest(),
2574 op.getUnwindDest());
2577mlir::LogicalResult CIRToLLVMReturnAddrOpLowering::matchAndRewrite(
2578 cir::ReturnAddrOp op, OpAdaptor adaptor,
2579 mlir::ConversionPatternRewriter &rewriter)
const {
2580 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
2582 llvmPtrTy, adaptor.getOperands());
2583 return mlir::success();
2586mlir::LogicalResult CIRToLLVMFrameAddrOpLowering::matchAndRewrite(
2587 cir::FrameAddrOp op, OpAdaptor adaptor,
2588 mlir::ConversionPatternRewriter &rewriter)
const {
2589 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
2591 adaptor.getOperands());
2592 return mlir::success();
2595mlir::LogicalResult CIRToLLVMClearCacheOpLowering::matchAndRewrite(
2596 cir::ClearCacheOp op, OpAdaptor adaptor,
2597 mlir::ConversionPatternRewriter &rewriter)
const {
2598 mlir::Value begin = adaptor.getBegin();
2599 mlir::Value end = adaptor.getEnd();
2600 auto intrinNameAttr =
2601 mlir::StringAttr::get(op.getContext(),
"llvm.clear_cache");
2602 rewriter.replaceOpWithNewOp<mlir::LLVM::CallIntrinsicOp>(
2603 op, mlir::Type{}, intrinNameAttr, mlir::ValueRange{begin, end});
2605 return mlir::success();
2608mlir::LogicalResult CIRToLLVMAddrOfReturnAddrOpLowering::matchAndRewrite(
2609 cir::AddrOfReturnAddrOp op, OpAdaptor adaptor,
2610 mlir::ConversionPatternRewriter &rewriter)
const {
2611 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
2613 llvmPtrTy, adaptor.getOperands());
2614 return mlir::success();
2617mlir::LogicalResult CIRToLLVMLoadOpLowering::matchAndRewrite(
2618 cir::LoadOp op, OpAdaptor adaptor,
2619 mlir::ConversionPatternRewriter &rewriter)
const {
2620 const mlir::Type llvmTy =
2623 return op.emitError()
2624 <<
"NYI: lowering load of a type with no memory representation";
2625 mlir::LLVM::AtomicOrdering ordering =
getLLVMMemOrder(op.getMemOrder());
2626 std::optional<size_t> opAlign = op.getAlignment();
2627 unsigned alignment = (unsigned)opAlign.value_or(
2633 op.getSyncScope(), op->getParentOfType<mlir::ModuleOp>());
2635 mlir::LLVM::LoadOp newLoad = mlir::LLVM::LoadOp::create(
2636 rewriter, op->getLoc(), llvmTy, adaptor.getAddr(), alignment,
2637 op.getIsVolatile(), op.getIsNontemporal(),
2638 op.getInvariant(),
false,
2639 false, ordering, llvmSyncScope.value_or(std::string()));
2640 if (mlir::Attribute domain = op->getAttr(
"cir.riscv_nontemporal_domain"))
2641 newLoad->setAttr(
"cir.riscv_nontemporal_domain", domain);
2644 mlir::Value result =
emitFromMemory(rewriter, *getTypeConverter(), dataLayout,
2645 op, newLoad.getResult());
2646 rewriter.replaceOp(op, result);
2648 return mlir::LogicalResult::success();
2652cir::direct::CIRToLLVMVecMaskedLoadOpLowering::matchAndRewrite(
2653 cir::VecMaskedLoadOp op, OpAdaptor adaptor,
2654 mlir::ConversionPatternRewriter &rewriter)
const {
2655 const mlir::Type llvmResTy =
2658 return op.emitError()
2659 <<
"NYI: lowering masked load of a type with no memory "
2662 std::optional<size_t> opAlign = op.getAlignment();
2663 unsigned alignment =
2664 (unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmResTy));
2666 auto newLoad = mlir::LLVM::MaskedLoadOp::create(
2667 rewriter, op.getLoc(), llvmResTy, adaptor.getAddr(), adaptor.getMask(),
2668 adaptor.getPassThru(), alignment);
2670 rewriter.replaceOp(op, newLoad.getResult());
2671 return mlir::success();
2674mlir::LogicalResult CIRToLLVMStoreOpLowering::matchAndRewrite(
2675 cir::StoreOp op, OpAdaptor adaptor,
2676 mlir::ConversionPatternRewriter &rewriter)
const {
2677 mlir::LLVM::AtomicOrdering memorder =
getLLVMMemOrder(op.getMemOrder());
2678 mlir::Type valueType = op.getValue().getType();
2679 const mlir::Type llvmTy =
2682 return op.emitError()
2683 <<
"NYI: lowering store of a type with no memory representation";
2684 std::optional<size_t> opAlign = op.getAlignment();
2685 unsigned alignment = (unsigned)opAlign.value_or(
2692 op.getValue().getType(), adaptor.getValue());
2696 op.getSyncScope(), op->getParentOfType<mlir::ModuleOp>());
2698 mlir::LLVM::StoreOp storeOp = mlir::LLVM::StoreOp::create(
2699 rewriter, op->getLoc(), value, adaptor.getAddr(), alignment,
2701 op.getIsNontemporal(),
false,
2702 memorder, llvmSyncScope.value_or(std::string()));
2703 if (mlir::Attribute domain = op->getAttr(
"cir.riscv_nontemporal_domain"))
2704 storeOp->setAttr(
"cir.riscv_nontemporal_domain", domain);
2705 rewriter.replaceOp(op, storeOp);
2707 return mlir::LogicalResult::success();
2711 while (
auto arrTy = mlir::dyn_cast<cir::ArrayType>(ty))
2712 ty = arrTy.getElementType();
2717 return mlir::isa<cir::PointerType, cir::IntType, cir::BoolType,
2721mlir::LogicalResult CIRToLLVMConstantOpLowering::matchAndRewrite(
2722 cir::ConstantOp op, OpAdaptor adaptor,
2723 mlir::ConversionPatternRewriter &rewriter)
const {
2724 mlir::Attribute attr = op.getValue();
2726 if (mlir::isa<cir::PoisonAttr>(attr)) {
2727 rewriter.replaceOpWithNewOp<mlir::LLVM::PoisonOp>(
2728 op, getTypeConverter()->convertType(op.getType()));
2729 return mlir::success();
2732 if (mlir::isa<cir::UndefAttr>(attr)) {
2733 rewriter.replaceOpWithNewOp<mlir::LLVM::UndefOp>(
2734 op, getTypeConverter()->convertType(op.getType()));
2735 return mlir::success();
2738 if (mlir::isa<mlir::IntegerType>(op.getType())) {
2743 attr = op.getValue();
2744 }
else if (mlir::isa<cir::BoolType>(op.getType())) {
2745 int value = mlir::cast<cir::BoolAttr>(op.getValue()).getValue();
2746 attr = rewriter.getIntegerAttr(typeConverter->convertType(op.getType()),
2748 }
else if (mlir::isa<cir::IntType>(op.getType())) {
2751 if (mlir::isa<cir::GlobalViewAttr, cir::BlockAddrDiffAttr>(op.getValue())) {
2754 getTypeConverter(), &blockInfoAddr);
2755 rewriter.replaceOp(op, newOp);
2756 return mlir::success();
2759 attr = rewriter.getIntegerAttr(
2760 typeConverter->convertType(op.getType()),
2761 mlir::cast<cir::IntAttr>(op.getValue()).getValue());
2762 }
else if (mlir::isa<cir::FPTypeInterface>(op.getType())) {
2763 attr = rewriter.getFloatAttr(
2764 typeConverter->convertType(op.getType()),
2765 mlir::cast<cir::FPAttr>(op.getValue()).getValue());
2766 }
else if (mlir::isa<cir::PointerType>(op.getType())) {
2768 if (mlir::isa<cir::ConstPtrAttr>(op.getValue())) {
2769 if (mlir::cast<cir::ConstPtrAttr>(op.getValue()).isNullValue()) {
2770 rewriter.replaceOpWithNewOp<mlir::LLVM::ZeroOp>(
2771 op, typeConverter->convertType(op.getType()));
2772 return mlir::success();
2778 if (mlir::isa<cir::GlobalViewAttr, cir::GlobalOffsetAttr, cir::ConstPtrAttr,
2779 cir::BlockAddrInfoAttr>(op.getValue())) {
2782 getTypeConverter(), &blockInfoAddr);
2783 rewriter.replaceOp(op, newOp);
2784 return mlir::success();
2786 attr = op.getValue();
2787 }
else if (
const auto arrTy = mlir::dyn_cast<cir::ArrayType>(op.getType())) {
2788 const auto constArr = mlir::dyn_cast<cir::ConstArrayAttr>(op.getValue());
2789 if (!constArr && !isa<cir::ZeroAttr, cir::UndefAttr>(op.getValue()))
2790 return op.emitError() <<
"array does not have a constant initializer";
2792 std::optional<mlir::Attribute> denseAttr;
2795 attr = denseAttr.value();
2798 op, op.getValue(), rewriter, symbolTables, typeConverter);
2799 rewriter.replaceOp(op, initVal);
2800 return mlir::success();
2802 }
else if (
const auto recordAttr =
2803 mlir::dyn_cast<cir::ConstRecordAttr>(op.getValue())) {
2806 rewriter.replaceOp(op, initVal);
2807 return mlir::success();
2808 }
else if (
const auto vecTy = mlir::dyn_cast<cir::VectorType>(op.getType())) {
2809 rewriter.replaceOp(op,
2811 symbolTables, getTypeConverter()));
2812 return mlir::success();
2813 }
else if (mlir::isa<cir::RecordType>(op.getType())) {
2814 if (mlir::isa<cir::ZeroAttr, cir::UndefAttr>(attr)) {
2815 mlir::Value initVal =
2817 rewriter.replaceOp(op, initVal);
2818 return mlir::success();
2820 return op.emitError() <<
"unsupported lowering for record constant type "
2822 }
else if (
auto complexTy = mlir::dyn_cast<cir::ComplexType>(op.getType())) {
2823 mlir::Type complexElemTy = complexTy.getElementType();
2824 mlir::Type complexElemLLVMTy = typeConverter->convertType(complexElemTy);
2826 if (
auto zeroInitAttr = mlir::dyn_cast<cir::ZeroAttr>(op.getValue())) {
2827 mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(complexElemLLVMTy);
2828 mlir::ArrayAttr array = rewriter.getArrayAttr({zeroAttr, zeroAttr});
2829 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
2830 op, getTypeConverter()->convertType(op.getType()), array);
2831 return mlir::success();
2834 if (mlir::isa<cir::UndefAttr>(op.getValue())) {
2835 rewriter.replaceOpWithNewOp<mlir::LLVM::UndefOp>(
2836 op, getTypeConverter()->convertType(op.getType()));
2837 return mlir::success();
2840 auto complexAttr = mlir::cast<cir::ConstComplexAttr>(op.getValue());
2842 mlir::Attribute components[2];
2843 if (mlir::isa<cir::IntType>(complexElemTy)) {
2844 components[0] = rewriter.getIntegerAttr(
2846 mlir::cast<cir::IntAttr>(complexAttr.getReal()).getValue());
2847 components[1] = rewriter.getIntegerAttr(
2849 mlir::cast<cir::IntAttr>(complexAttr.getImag()).getValue());
2851 components[0] = rewriter.getFloatAttr(
2853 mlir::cast<cir::FPAttr>(complexAttr.getReal()).getValue());
2854 components[1] = rewriter.getFloatAttr(
2856 mlir::cast<cir::FPAttr>(complexAttr.getImag()).getValue());
2859 attr = rewriter.getArrayAttr(components);
2861 return op.emitError() <<
"unsupported constant type " << op.getType();
2864 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
2865 op, getTypeConverter()->convertType(op.getType()),
attr);
2867 return mlir::success();
2871 mlir::DataLayout layout(op.getParentOfType<mlir::ModuleOp>());
2873 if (isa<cir::VoidType>(type))
2874 type = cir::IntType::get(type.getContext(), 8,
false);
2875 return layout.getTypeAllocSize(type);
2878mlir::LogicalResult CIRToLLVMPrefetchOpLowering::matchAndRewrite(
2879 cir::PrefetchOp op, OpAdaptor adaptor,
2880 mlir::ConversionPatternRewriter &rewriter)
const {
2881 rewriter.replaceOpWithNewOp<mlir::LLVM::Prefetch>(
2882 op, adaptor.getAddr(), adaptor.getIsWrite(), adaptor.getLocality(),
2884 return mlir::success();
2887mlir::LogicalResult CIRToLLVMPtrDiffOpLowering::matchAndRewrite(
2888 cir::PtrDiffOp op, OpAdaptor adaptor,
2889 mlir::ConversionPatternRewriter &rewriter)
const {
2890 auto dstTy = mlir::cast<cir::IntType>(op.getType());
2891 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
2893 auto lhs = mlir::LLVM::PtrToIntOp::create(rewriter, op.getLoc(), llvmDstTy,
2895 auto rhs = mlir::LLVM::PtrToIntOp::create(rewriter, op.getLoc(), llvmDstTy,
2899 mlir::LLVM::SubOp::create(rewriter, op.getLoc(), llvmDstTy, lhs, rhs);
2901 cir::PointerType ptrTy = op.getLhs().getType();
2906 mlir::Value resultVal = diff.getResult();
2907 if (typeSize != 1) {
2908 auto typeSizeVal = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
2909 llvmDstTy, typeSize);
2911 if (dstTy.isUnsigned()) {
2913 mlir::LLVM::UDivOp::create(rewriter, op.getLoc(), diff, typeSizeVal);
2914 uDiv.setIsExact(
true);
2915 resultVal = uDiv.getResult();
2918 mlir::LLVM::SDivOp::create(rewriter, op.getLoc(), diff, typeSizeVal);
2919 sDiv.setIsExact(
true);
2920 resultVal = sDiv.getResult();
2923 rewriter.replaceOp(op, resultVal);
2924 return mlir::success();
2927mlir::LogicalResult CIRToLLVMExpectOpLowering::matchAndRewrite(
2928 cir::ExpectOp op, OpAdaptor adaptor,
2929 mlir::ConversionPatternRewriter &rewriter)
const {
2933 std::optional<llvm::APFloat> prob = op.getProb();
2935 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpectWithProbabilityOp>(
2936 op, adaptor.getVal(), adaptor.getExpected(), prob.value());
2938 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpectOp>(op, adaptor.getVal(),
2939 adaptor.getExpected());
2940 return mlir::success();
2943mlir::LogicalResult CIRToLLVMAbsOpLowering::matchAndRewrite(
2944 cir::AbsOp op, OpAdaptor adaptor,
2945 mlir::ConversionPatternRewriter &rewriter)
const {
2946 mlir::Type resTy = typeConverter->convertType(op.getType());
2947 auto absOp = mlir::LLVM::AbsOp::create(rewriter, op.getLoc(), resTy,
2948 adaptor.getOperands()[0],
2949 adaptor.getMinIsPoison());
2950 rewriter.replaceOp(op, absOp);
2951 return mlir::success();
2956 return attr.getName() == CIRDialect::getNoReturnAttrName() ||
2957 attr.getName() == CIRDialect::getNoUnwindAttrName() ||
2958 attr.getName() == CIRDialect::getWillReturnAttrName() ||
2959 attr.getName() == CIRDialect::getStrictFPAttrName() ||
2960 attr.getName() == CIRDialect::getNoRecurseAttrName() ||
2961 attr.getName() == CIRDialect::getMustProgressAttrName() ||
2962 attr.getName() == CIRDialect::getNoBuiltinAttrName() ||
2963 attr.getName() == CIRDialect::getOptNoneAttrName() ||
2964 attr.getName() == CIRDialect::getNakedAttrName() ||
2965 attr.getName() == CIRDialect::getSYCLModuleIdAttrName() ||
2966 attr.getName() == CIRDialect::getDontCallErrorAttrName() ||
2967 attr.getName() == CIRDialect::getDontCallWarnAttrName();
2975mlir::LogicalResult CIRToLLVMFuncOpLowering::lowerFuncAttributes(
2976 cir::FuncOp func,
bool includeFunctionOnlyAttrs,
2978 OpenCLFunctionMetadataLowering openCLMetadataLowering(func.getContext());
2979 for (mlir::NamedAttribute attr : func->getDiscardableAttrs()) {
2982 if (openCLMetadataLowering.lower(attr, includeFunctionOnlyAttrs))
2985 result.push_back(attr);
2988 if (mlir::StringAttr visibility = func.getSymVisibilityAttr())
2989 result.emplace_back(func.getSymVisibilityAttrName(), visibility);
2991 if (includeFunctionOnlyAttrs) {
2992 if (mlir::ArrayAttr argAttrs = func.getArgAttrsAttr()) {
2994 argAttrs, *getTypeConverter(), dataLayout, getContext());
2996 return func.emitError() <<
"NYI: lowering a byval/sret/byref "
2997 "argument whose pointee type has no "
2998 "memory representation";
2999 result.emplace_back(func.getArgAttrsAttrName(), *lowered);
3001 if (mlir::ArrayAttr resAttrs = func.getResAttrsAttr())
3002 result.emplace_back(func.getResAttrsAttrName(), resAttrs);
3005 if (includeFunctionOnlyAttrs)
3006 openCLMetadataLowering.appendAttrs(result);
3008 return mlir::success();
3011mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewriteAlias(
3012 cir::FuncOp op, llvm::StringRef aliasee, mlir::Type ty, OpAdaptor adaptor,
3013 mlir::ConversionPatternRewriter &rewriter)
const {
3014 SmallVector<mlir::NamedAttribute, 4> attributes;
3015 if (mlir::failed(lowerFuncAttributes(op,
false,
3017 return mlir::failure();
3019 mlir::Location loc = op.getLoc();
3020 auto aliasOp = rewriter.replaceOpWithNewOp<mlir::LLVM::AliasOp>(
3021 op, ty,
convertLinkage(op.getLinkage()), op.getName(), op.getDsoLocal(),
3022 mlir::LLVM::ThreadLocalMode::NotThreadLocal, attributes);
3025 mlir::OpBuilder builder(op.getContext());
3026 mlir::Block *block = builder.createBlock(&aliasOp.getInitializerRegion());
3027 builder.setInsertionPointToStart(block);
3030 mlir::Type ptrTy = mlir::LLVM::LLVMPointerType::get(ty.getContext());
3031 auto addrOp = mlir::LLVM::AddressOfOp::create(builder, loc, ptrTy, aliasee);
3032 mlir::LLVM::ReturnOp::create(builder, loc, addrOp);
3034 return mlir::success();
3037mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewrite(
3038 cir::FuncOp op, OpAdaptor adaptor,
3039 mlir::ConversionPatternRewriter &rewriter)
const {
3041 cir::FuncType fnType = op.getFunctionType();
3042 bool isDsoLocal = op.getDsoLocal();
3043 mlir::TypeConverter::SignatureConversion signatureConversion(
3044 fnType.getNumInputs());
3046 for (
const auto &argType : llvm::enumerate(fnType.getInputs())) {
3047 mlir::Type convertedType = typeConverter->convertType(argType.value());
3049 return mlir::failure();
3050 signatureConversion.addInputs(argType.index(), convertedType);
3053 mlir::Type resultType =
3054 getTypeConverter()->convertType(fnType.getReturnType());
3057 mlir::Type llvmFnTy = mlir::LLVM::LLVMFunctionType::get(
3058 resultType ? resultType : mlir::LLVM::LLVMVoidType::get(getContext()),
3059 signatureConversion.getConvertedTypes(),
3063 if (std::optional<llvm::StringRef> aliasee = op.getAliasee())
3064 return matchAndRewriteAlias(op, *aliasee, llvmFnTy, adaptor, rewriter);
3068 mlir::Location loc = op.getLoc();
3069 if (mlir::FusedLoc fusedLoc = mlir::dyn_cast<mlir::FusedLoc>(loc))
3070 loc = fusedLoc.getLocations()[0];
3071 assert((mlir::isa<mlir::FileLineColLoc>(loc) ||
3072 mlir::isa<mlir::UnknownLoc>(loc)) &&
3073 "expected single location or unknown location here");
3077 SmallVector<mlir::NamedAttribute, 4> attributes;
3078 if (mlir::failed(lowerFuncAttributes(op,
true,
3080 return mlir::failure();
3082 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
3084 mlir::LLVM::LLVMFuncOp fn = mlir::LLVM::LLVMFuncOp::create(
3085 rewriter, loc, op.getName(), llvmFnTy, linkage, isDsoLocal, cconv,
3086 comdatAttr, attributes);
3090 if (cir::MemoryEffectsAttr effects = op.getMemoryEffectsAttr())
3094 if (op->hasAttr(CIRDialect::getNoUnwindAttrName()) ||
3095 op->hasAttr(CIRDialect::getNoThrowAttrName()))
3096 fn.setNoUnwind(
true);
3097 if (op->hasAttr(CIRDialect::getWillReturnAttrName()))
3098 fn.setWillReturn(
true);
3100 if (op->hasAttr(CIRDialect::getNoReturnAttrName()))
3101 fn.setNoreturn(
true);
3103 if (op->hasAttr(CIRDialect::getOptNoneAttrName()))
3104 fn.setOptimizeNone(
true);
3106 if (std::optional<cir::UnwindTableKind> uwtableKind = op.getUwtable())
3107 fn.setUwtableKindAttr(mlir::LLVM::UWTableKindAttr::get(
3110 if (std::optional<cir::FramePointerKind> framePointerKind =
3111 op.getFramePointer())
3112 fn.setFramePointerAttr(mlir::LLVM::FramePointerKindAttr::get(
3119 SmallVector<mlir::Attribute> passthrough;
3120 for (llvm::StringRef flagAttr :
3121 {CIRDialect::getStrictFPAttrName(), CIRDialect::getNoRecurseAttrName(),
3122 CIRDialect::getMustProgressAttrName(),
3123 CIRDialect::getNoBuiltinAttrName(), CIRDialect::getNakedAttrName()})
3124 if (op->hasAttr(flagAttr))
3125 passthrough.push_back(rewriter.getStringAttr(flagAttr));
3127 if (
auto moduleId = op->getAttrOfType<mlir::StringAttr>(
3128 CIRDialect::getSYCLModuleIdAttrName()))
3129 passthrough.push_back(rewriter.getArrayAttr(
3130 {rewriter.getStringAttr(CIRDialect::getSYCLModuleIdAttrName()),
3133 for (llvm::StringRef dontCallAttr : {CIRDialect::getDontCallErrorAttrName(),
3134 CIRDialect::getDontCallWarnAttrName()})
3135 if (
auto diagnostic = op->getAttrOfType<mlir::StringAttr>(dontCallAttr))
3136 passthrough.push_back(rewriter.getArrayAttr(
3137 {rewriter.getStringAttr(dontCallAttr), diagnostic}));
3139 if (!passthrough.empty())
3140 fn.setPassthroughAttr(rewriter.getArrayAttr(passthrough));
3142 if (std::optional<cir::InlineKind> inlineKind = op.getInlineKind()) {
3143 fn.setNoInline(*inlineKind == cir::InlineKind::NoInline);
3144 fn.setInlineHint(*inlineKind == cir::InlineKind::InlineHint);
3145 fn.setAlwaysInline(*inlineKind == cir::InlineKind::AlwaysInline);
3148 if (std::optional<llvm::StringRef> personality = op.getPersonality())
3149 fn.setPersonality(*personality);
3154 fn.setAlignment(op.getAlignment());
3157 rewriter.inlineRegionBefore(op.getBody(), fn.getBody(), fn.end());
3158 if (failed(rewriter.convertRegionTypes(&fn.getBody(), *typeConverter,
3159 &signatureConversion)))
3160 return mlir::failure();
3162 rewriter.eraseOp(op);
3164 return mlir::LogicalResult::success();
3167mlir::LogicalResult CIRToLLVMGetGlobalOpLowering::matchAndRewrite(
3168 cir::GetGlobalOp op, OpAdaptor adaptor,
3169 mlir::ConversionPatternRewriter &rewriter)
const {
3172 if (op->getUses().empty()) {
3173 rewriter.eraseOp(op);
3174 return mlir::success();
3177 mlir::Type
type = getTypeConverter()->convertType(op.getType());
3178 mlir::Operation *newop = mlir::LLVM::AddressOfOp::create(
3179 rewriter, op.getLoc(), type, op.getName());
3183 newop = mlir::LLVM::ThreadlocalAddressOp::create(rewriter, op.getLoc(),
3184 type, newop->getResult(0));
3187 rewriter.replaceOp(op, newop);
3188 return mlir::success();
3191llvm::SmallVector<mlir::NamedAttribute>
3192CIRToLLVMGlobalOpLowering::lowerGlobalAttributes(
3193 cir::GlobalOp op, mlir::ConversionPatternRewriter &rewriter)
const {
3194 SmallVector<mlir::NamedAttribute> attributes;
3196 if (mlir::StringAttr sectionAttr = op.getSectionAttr())
3197 attributes.push_back(rewriter.getNamedAttr(
"section", sectionAttr));
3199 mlir::LLVM::VisibilityAttr visibility = mlir::LLVM::VisibilityAttr::get(
3202 attributes.push_back(rewriter.getNamedAttr(
"visibility_", visibility));
3204 if (op->getAttr(CUDAExternallyInitializedAttr::getMnemonic()))
3205 attributes.push_back(rewriter.getNamedAttr(
"externally_initialized",
3206 rewriter.getUnitAttr()));
3211static mlir::LLVM::ThreadLocalMode
3214#define CHECK_ENUM(CIR, LLVM_VAL) \
3215 static_assert(static_cast<unsigned>(TLSModel::CIR) == \
3216 static_cast<unsigned>(mlir::LLVM::ThreadLocalMode::LLVM_VAL))
3224 return mlir::LLVM::ThreadLocalMode::NotThreadLocal;
3226 return static_cast<mlir::LLVM::ThreadLocalMode
>(attr.getValue());
3231void CIRToLLVMGlobalOpLowering::setupRegionInitializedLLVMGlobalOp(
3232 cir::GlobalOp op, mlir::ConversionPatternRewriter &rewriter)
const {
3233 mlir::Type llvmType =
3238 if (std::optional<mlir::Attribute> init = op.getInitialValue())
3246 const bool isConst = op.getConstant();
3247 unsigned addrSpace = 0;
3248 if (
auto targetAS = mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
3249 op.getAddrSpaceAttr()))
3250 addrSpace = targetAS.getValue();
3251 const bool isDsoLocal = op.getDsoLocal();
3252 mlir::LLVM::ThreadLocalMode threadLocalMode =
3254 const uint64_t alignment = op.getAlignment().value_or(0);
3255 const mlir::LLVM::Linkage linkage =
convertLinkage(op.getLinkage());
3256 const StringRef symbol = op.getSymName();
3257 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
3260 lowerGlobalAttributes(op, rewriter);
3262 mlir::LLVM::GlobalOp newGlobalOp =
3263 rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
3264 op, llvmType, isConst, linkage, symbol,
nullptr, alignment, addrSpace,
3265 isDsoLocal, threadLocalMode, comdatAttr, attributes);
3266 newGlobalOp.getRegion().emplaceBlock();
3267 rewriter.setInsertionPointToEnd(newGlobalOp.getInitializerBlock());
3271CIRToLLVMGlobalOpLowering::matchAndRewriteRegionInitializedGlobal(
3272 cir::GlobalOp op, mlir::Attribute init,
3273 mlir::ConversionPatternRewriter &rewriter)
const {
3275 assert((isa<cir::BlockAddrDiffAttr, cir::BlockAddrInfoAttr,
3276 cir::ConstArrayAttr, cir::ConstRecordAttr, cir::ConstVectorAttr,
3277 cir::ConstPtrAttr, cir::ConstComplexAttr, cir::GlobalOffsetAttr,
3278 cir::GlobalViewAttr, cir::TypeInfoAttr, cir::UndefAttr,
3279 cir::PoisonAttr, cir::VTableAttr, cir::ZeroAttr>(init)));
3284 const mlir::Location loc = op.getLoc();
3285 setupRegionInitializedLLVMGlobalOp(op, rewriter);
3290 CIRAttrToValue valueConverter(op, rewriter, symbolTables, typeConverter,
3292 mlir::Value value = valueConverter.visit(init);
3293 mlir::LLVM::ReturnOp::create(rewriter, loc, value);
3294 return mlir::success();
3297mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite(
3298 cir::GlobalOp op, OpAdaptor adaptor,
3299 mlir::ConversionPatternRewriter &rewriter)
const {
3300 if (mlir::isa_and_present<cir::LangAddressSpaceAttr>(op.getAddrSpaceAttr()))
3301 return op.emitError()
3302 <<
"cannot lower a global with a language address space";
3306 if (!op.getCtorRegion().empty() || !op.getDtorRegion().empty())
3307 return op.emitError() <<
"GlobalOp ctor and dtor regions should be removed "
3308 "in LoweringPrepare";
3310 std::optional<mlir::Attribute> init = op.getInitialValue();
3313 const mlir::Type cirSymType = op.getSymType();
3316 mlir::Type llvmType =
3319 return op.emitError()
3320 <<
"NYI: lowering global of a type with no memory representation";
3325 if (init.has_value())
3331 const bool isConst = op.getConstant();
3332 unsigned addrSpace = 0;
3333 if (
auto targetAS = mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
3334 op.getAddrSpaceAttr()))
3335 addrSpace = targetAS.getValue();
3336 const bool isDsoLocal = op.getDsoLocal();
3337 mlir::LLVM::ThreadLocalMode threadLocalMode =
3339 const uint64_t alignment = op.getAlignment().value_or(0);
3340 const mlir::LLVM::Linkage linkage =
convertLinkage(op.getLinkage());
3341 const StringRef symbol = op.getSymName();
3342 SmallVector<mlir::NamedAttribute> attributes =
3343 lowerGlobalAttributes(op, rewriter);
3346 if (std::optional<llvm::StringRef> aliasee = op.getAliasee()) {
3347 mlir::Location loc = op.getLoc();
3348 auto aliasOp = rewriter.replaceOpWithNewOp<mlir::LLVM::AliasOp>(
3349 op, llvmType, linkage, symbol, isDsoLocal, threadLocalMode, attributes);
3351 mlir::OpBuilder builder(op.getContext());
3352 mlir::Block *block = builder.createBlock(&aliasOp.getInitializerRegion());
3353 builder.setInsertionPointToStart(block);
3355 mlir::LLVM::LLVMPointerType::get(getContext(), addrSpace);
3357 mlir::LLVM::AddressOfOp::create(builder, loc, ptrTy, *aliasee);
3358 mlir::LLVM::ReturnOp::create(builder, loc, addrOp);
3359 return mlir::success();
3362 if (init.has_value()) {
3363 if (mlir::isa<cir::FPAttr, cir::IntAttr, cir::BoolAttr>(init.value())) {
3365 init = initRewriter.visit(init.value());
3370 if (!init.value()) {
3371 op.emitError() <<
"unsupported initializer '" << init.value() <<
"'";
3372 return mlir::failure();
3374 }
else if (
auto constArr =
3375 mlir::dyn_cast<cir::ConstArrayAttr>(init.value())) {
3383 mlir::ModuleOp modOp = op->getParentOfType<mlir::ModuleOp>();
3385 constArr, symbolTables, typeConverter, modOp)) {
3386 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
3387 rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
3388 op, llvmType, isConst, linkage, symbol, bulkInit.value(),
3389 alignment, addrSpace, isDsoLocal, threadLocalMode, comdatAttr,
3391 return mlir::success();
3394 return matchAndRewriteRegionInitializedGlobal(op, init.value(), rewriter);
3395 }
else if (
auto constRecord =
3396 mlir::dyn_cast<cir::ConstRecordAttr>(init.value())) {
3402 mlir::ModuleOp modOp = op->getParentOfType<mlir::ModuleOp>();
3404 constRecord, symbolTables, typeConverter, modOp)) {
3405 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
3406 rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
3407 op, llvmType, isConst, linkage, symbol, bulkInit.value(), alignment,
3408 addrSpace, isDsoLocal, threadLocalMode, comdatAttr, attributes);
3409 return mlir::success();
3411 return matchAndRewriteRegionInitializedGlobal(op, init.value(), rewriter);
3412 }
else if (mlir::isa<cir::BlockAddrDiffAttr, cir::BlockAddrInfoAttr,
3413 cir::ConstVectorAttr, cir::ConstRecordAttr,
3414 cir::ConstPtrAttr, cir::ConstComplexAttr,
3415 cir::GlobalOffsetAttr, cir::GlobalViewAttr,
3416 cir::TypeInfoAttr, cir::UndefAttr, cir::PoisonAttr,
3417 cir::VTableAttr, cir::ZeroAttr>(init.value())) {
3421 return matchAndRewriteRegionInitializedGlobal(op, init.value(), rewriter);
3425 op.emitError() <<
"unsupported initializer '" << init.value() <<
"'";
3426 return mlir::failure();
3430 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
3431 rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
3432 op, llvmType, isConst, linkage, symbol, init.value_or(mlir::Attribute()),
3433 alignment, addrSpace, isDsoLocal, threadLocalMode, comdatAttr,
3436 return mlir::success();
3439static mlir::SymbolRefAttr
3441 StringRef symName, mlir::LLVM::ComdatOp &comdatOp,
3442 mlir::SymbolTableCollection &symbolTables) {
3443 mlir::OpBuilder::InsertionGuard guard(builder);
3444 StringRef comdatName =
"__llvm_comdat";
3450 comdatOp = modOp.lookupSymbol<mlir::LLVM::ComdatOp>(comdatName);
3454 builder.setInsertionPointToStart(modOp.getBody());
3456 mlir::LLVM::ComdatOp::create(builder, modOp.getLoc(), comdatName);
3461 mlir::SymbolTable &selectors = symbolTables.getSymbolTable(comdatOp);
3462 if (
auto comdatSelector =
3463 selectors.lookup<mlir::LLVM::ComdatSelectorOp>(symName)) {
3464 return mlir::SymbolRefAttr::get(
3465 builder.getContext(), comdatName,
3466 mlir::FlatSymbolRefAttr::get(comdatSelector.getSymNameAttr()));
3469 builder.setInsertionPointToStart(&comdatOp.getBody().back());
3470 auto selectorOp = mlir::LLVM::ComdatSelectorOp::create(
3471 builder, comdatOp.getLoc(), symName, mlir::LLVM::comdat::Comdat::Any,
3473 selectors.insert(selectorOp);
3474 return mlir::SymbolRefAttr::get(
3475 builder.getContext(), comdatName,
3476 mlir::FlatSymbolRefAttr::get(selectorOp.getSymNameAttr()));
3480CIRToLLVMGlobalOpLowering::getComdatAttr(cir::GlobalOp &op,
3481 mlir::OpBuilder &builder)
const {
3482 std::optional<llvm::StringRef> comdat = op.getComdat();
3484 return mlir::SymbolRefAttr{};
3485 llvm::StringRef comdatKey = comdat->empty() ? op.getSymName() : *comdat;
3487 comdatKey, comdatOp, symbolTables);
3491CIRToLLVMFuncOpLowering::getComdatAttr(cir::FuncOp &op,
3492 mlir::OpBuilder &builder)
const {
3493 std::optional<llvm::StringRef> comdat = op.getComdat();
3495 return mlir::SymbolRefAttr{};
3496 llvm::StringRef comdatKey = comdat->empty() ? op.getSymName() : *comdat;
3498 comdatKey, comdatOp, symbolTables);
3501mlir::LogicalResult CIRToLLVMSwitchFlatOpLowering::matchAndRewrite(
3502 cir::SwitchFlatOp op, OpAdaptor adaptor,
3503 mlir::ConversionPatternRewriter &rewriter)
const {
3505 llvm::SmallVector<mlir::APInt, 8> caseValues;
3506 for (mlir::Attribute val : op.getCaseValues()) {
3507 auto intAttr = cast<cir::IntAttr>(val);
3508 caseValues.push_back(intAttr.getValue());
3511 llvm::SmallVector<mlir::Block *, 8> caseDestinations;
3513 for (mlir::Block *x : op.getCaseDestinations())
3514 caseDestinations.push_back(x);
3518 llvm::SmallVector<mlir::ValueRange> caseOperands = adaptor.getCaseOperands();
3521 rewriter.setInsertionPoint(op);
3522 rewriter.replaceOpWithNewOp<mlir::LLVM::SwitchOp>(
3523 op, adaptor.getCondition(), op.getDefaultDestination(),
3524 adaptor.getDefaultOperands(), caseValues, caseDestinations, caseOperands);
3525 return mlir::success();
3528static mlir::LLVM::IntegerOverflowFlags
nswFlag(
bool nsw) {
3529 return nsw ? mlir::LLVM::IntegerOverflowFlags::nsw
3530 : mlir::LLVM::IntegerOverflowFlags::none;
3533template <
typename CIROp,
typename LLVMIntOp>
3534static mlir::LogicalResult
3536 mlir::ConversionPatternRewriter &rewriter) {
3537 mlir::Type llvmType = adaptor.getInput().getType();
3538 mlir::Location loc = op.getLoc();
3540 auto maybeNSW =
nswFlag(op.getNoSignedWrap());
3541 mlir::LLVM::ConstantOp one;
3542 if (mlir::isa<cir::VectorType>(op.getType())) {
3543 mlir::ShapedType shapedTy = mlir::cast<mlir::ShapedType>(llvmType);
3544 mlir::APInt oneAP(shapedTy.getElementTypeBitWidth(), 1);
3545 auto oneVec = mlir::DenseElementsAttr::get(shapedTy, {oneAP});
3546 one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, oneVec);
3548 one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
3550 rewriter.replaceOpWithNewOp<LLVMIntOp>(op, adaptor.getInput(), one, maybeNSW);
3551 return mlir::success();
3554mlir::LogicalResult CIRToLLVMIncOpLowering::matchAndRewrite(
3555 cir::IncOp op, OpAdaptor adaptor,
3556 mlir::ConversionPatternRewriter &rewriter)
const {
3560mlir::LogicalResult CIRToLLVMDecOpLowering::matchAndRewrite(
3561 cir::DecOp op, OpAdaptor adaptor,
3562 mlir::ConversionPatternRewriter &rewriter)
const {
3566mlir::LogicalResult CIRToLLVMMinusOpLowering::matchAndRewrite(
3567 cir::MinusOp op, OpAdaptor adaptor,
3568 mlir::ConversionPatternRewriter &rewriter)
const {
3569 bool isVector = mlir::isa<cir::VectorType>(op.getType());
3570 mlir::Type llvmType = adaptor.getInput().getType();
3571 mlir::Location loc = op.getLoc();
3573 auto maybeNSW =
nswFlag(op.getNoSignedWrap());
3576 zero = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmType);
3578 zero = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 0);
3579 rewriter.replaceOpWithNewOp<mlir::LLVM::SubOp>(op, zero, adaptor.getInput(),
3581 return mlir::success();
3584mlir::LogicalResult CIRToLLVMNotOpLowering::matchAndRewrite(
3585 cir::NotOp op, OpAdaptor adaptor,
3586 mlir::ConversionPatternRewriter &rewriter)
const {
3587 mlir::Type elementType = elementTypeIfVectorOrMatrix(op.getType());
3588 bool isVector = mlir::isa<cir::VectorType>(op.getType());
3589 mlir::Type llvmType = adaptor.getInput().getType();
3590 mlir::Location loc = op.getLoc();
3592 if (mlir::isa<cir::IntType>(elementType)) {
3593 mlir::Value minusOne;
3596 mlir::cast<cir::VectorType>(op.getType()).getSize();
3597 const unsigned eltWidth =
3598 mlir::cast<cir::IntType>(elementType).getWidth();
3599 SmallVector<APInt> values(numElements, APInt::getAllOnes(eltWidth));
3600 mlir::DenseIntElementsAttr denseVec = mlir::DenseIntElementsAttr::get(
3601 mlir::cast<mlir::ShapedType>(llvmType), values);
3603 mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, denseVec);
3605 minusOne = mlir::LLVM::ConstantOp::create(
3606 rewriter, loc, llvmType,
3607 APInt::getAllOnes(cast<mlir::IntegerType>(llvmType).getWidth()));
3609 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getInput(),
3611 return mlir::success();
3614 if (mlir::isa<cir::BoolType>(elementType)) {
3618 mlir::cast<cir::VectorType>(op.getType()).getSize();
3619 SmallVector<bool> values(numElements,
true);
3620 mlir::DenseIntElementsAttr denseVec = rewriter.getBoolVectorAttr(values);
3621 one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, denseVec);
3623 one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
3625 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getInput(), one);
3626 return mlir::success();
3629 return op.emitError() <<
"Unsupported type for bitwise NOT";
3634 return mlir::isa<cir::IntType>(type)
3635 ? mlir::cast<cir::IntType>(type).isUnsigned()
3636 : mlir::cast<mlir::IntegerType>(type).isUnsigned();
3643template <
typename BinOp>
3645 if (op.getNoUnsignedWrap())
3646 return mlir::LLVM::IntegerOverflowFlags::nuw;
3647 if (op.getNoSignedWrap())
3648 return mlir::LLVM::IntegerOverflowFlags::nsw;
3649 return mlir::LLVM::IntegerOverflowFlags::none;
3654template <
typename UIntSatOp,
typename SIntSatOp,
typename IntOp,
3656static mlir::LogicalResult
3658 mlir::ConversionPatternRewriter &rewriter) {
3659 const mlir::Type eltType = elementTypeIfVectorOrMatrix(op.getRhs().getType());
3660 assert(cir::isIntOrBoolType(eltType) &&
3661 "saturatable arith op expects integer operand types");
3662 if (op.getSaturated()) {
3664 rewriter.replaceOpWithNewOp<UIntSatOp>(op, lhs, rhs);
3666 rewriter.replaceOpWithNewOp<SIntSatOp>(op, lhs, rhs);
3667 return mlir::success();
3669 rewriter.replaceOpWithNewOp<IntOp>(op, lhs, rhs,
intOverflowFlag(op));
3670 return mlir::success();
3673mlir::LogicalResult CIRToLLVMAddOpLowering::matchAndRewrite(
3674 cir::AddOp op, OpAdaptor adaptor,
3675 mlir::ConversionPatternRewriter &rewriter)
const {
3677 mlir::LLVM::AddOp>(op, adaptor.getLhs(),
3678 adaptor.getRhs(), rewriter);
3681mlir::LogicalResult CIRToLLVMSubOpLowering::matchAndRewrite(
3682 cir::SubOp op, OpAdaptor adaptor,
3683 mlir::ConversionPatternRewriter &rewriter)
const {
3685 mlir::LLVM::SubOp>(op, adaptor.getLhs(),
3686 adaptor.getRhs(), rewriter);
3689mlir::LogicalResult CIRToLLVMMulOpLowering::matchAndRewrite(
3690 cir::MulOp op, OpAdaptor adaptor,
3691 mlir::ConversionPatternRewriter &rewriter)
const {
3692 assert(cir::isIntOrBoolType(
3693 elementTypeIfVectorOrMatrix(op.getRhs().getType())) &&
3694 "cir.mul expects integer operand types");
3695 rewriter.replaceOpWithNewOp<mlir::LLVM::MulOp>(
3697 return mlir::success();
3701template <
typename UIntOp,
typename SIntOp,
typename CIROp>
3702static mlir::LogicalResult
3704 mlir::ConversionPatternRewriter &rewriter) {
3705 const mlir::Type eltType = elementTypeIfVectorOrMatrix(op.getRhs().getType());
3706 assert(cir::isIntOrBoolType(eltType) &&
3707 "integer binary op expects integer operand types");
3709 rewriter.replaceOpWithNewOp<UIntOp>(op, lhs, rhs);
3711 rewriter.replaceOpWithNewOp<SIntOp>(op, lhs, rhs);
3712 return mlir::success();
3715mlir::LogicalResult CIRToLLVMDivOpLowering::matchAndRewrite(
3716 cir::DivOp op, OpAdaptor adaptor,
3717 mlir::ConversionPatternRewriter &rewriter)
const {
3719 op, adaptor.getLhs(), adaptor.getRhs(), rewriter);
3722mlir::LogicalResult CIRToLLVMRemOpLowering::matchAndRewrite(
3723 cir::RemOp op, OpAdaptor adaptor,
3724 mlir::ConversionPatternRewriter &rewriter)
const {
3726 op, adaptor.getLhs(), adaptor.getRhs(), rewriter);
3729template <
typename CIROp,
typename UIntOp,
typename SIntOp>
3730static mlir::LogicalResult
3732 mlir::ConversionPatternRewriter &rewriter) {
3733 const mlir::Value lhs = adaptor.getLhs();
3734 const mlir::Value rhs = adaptor.getRhs();
3736 rewriter.replaceOpWithNewOp<UIntOp>(op, lhs, rhs);
3738 rewriter.replaceOpWithNewOp<SIntOp>(op, lhs, rhs);
3739 return mlir::success();
3742mlir::LogicalResult CIRToLLVMMaxOpLowering::matchAndRewrite(
3743 cir::MaxOp op, OpAdaptor adaptor,
3744 mlir::ConversionPatternRewriter &rewriter)
const {
3746 op, adaptor, rewriter);
3749mlir::LogicalResult CIRToLLVMMinOpLowering::matchAndRewrite(
3750 cir::MinOp op, OpAdaptor adaptor,
3751 mlir::ConversionPatternRewriter &rewriter)
const {
3753 op, adaptor, rewriter);
3757static mlir::LLVM::ICmpPredicate
3759 using CIR = cir::CmpOpKind;
3760 using LLVMICmp = mlir::LLVM::ICmpPredicate;
3763 return LLVMICmp::eq;
3765 return LLVMICmp::ne;
3767 return (isSigned ? LLVMICmp::slt : LLVMICmp::ult);
3769 return (isSigned ? LLVMICmp::sle : LLVMICmp::ule);
3771 return (isSigned ? LLVMICmp::sgt : LLVMICmp::ugt);
3773 return (isSigned ? LLVMICmp::sge : LLVMICmp::uge);
3776 llvm_unreachable(
"FP-only comparison used with integer type");
3778 llvm_unreachable(
"Unknown CmpOpKind");
3783static mlir::LLVM::FCmpPredicate
3785 using CIR = cir::CmpOpKind;
3786 using LLVMFCmp = mlir::LLVM::FCmpPredicate;
3789 return LLVMFCmp::oeq;
3791 return LLVMFCmp::une;
3793 return LLVMFCmp::olt;
3795 return LLVMFCmp::ole;
3797 return LLVMFCmp::ogt;
3799 return LLVMFCmp::oge;
3801 return LLVMFCmp::one;
3803 return LLVMFCmp::uno;
3805 llvm_unreachable(
"Unknown CmpOpKind");
3808static llvm::StringRef
3810 using CIR = cir::CmpOpKind;
3829 llvm_unreachable(
"Unknown CmpOpKind");
3833 using CIR = cir::CmpOpKind;
3846 llvm_unreachable(
"Unknown CmpOpKind");
3849static mlir::LLVM::CallIntrinsicOp
3851 mlir::Location loc, mlir::Value lhs, mlir::Value rhs,
3852 cir::CmpOpKind
kind, cir::FenvAttr fenv,
3853 mlir::Type llvmResTy) {
3861 ?
"llvm.experimental.constrained.fcmps"
3862 :
"llvm.experimental.constrained.fcmp";
3867mlir::LogicalResult CIRToLLVMCmpOpLowering::matchAndRewrite(
3868 cir::CmpOp cmpOp, OpAdaptor adaptor,
3869 mlir::ConversionPatternRewriter &rewriter)
const {
3870 mlir::Type type = cmpOp.getLhs().getType();
3872 if (mlir::isa<cir::IntType, mlir::IntegerType>(type)) {
3873 bool isSigned = mlir::isa<cir::IntType>(type)
3874 ? mlir::cast<cir::IntType>(type).isSigned()
3875 : mlir::cast<mlir::IntegerType>(type).isSigned();
3876 mlir::LLVM::ICmpPredicate
kind =
3878 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
3879 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
3880 return mlir::success();
3883 if (mlir::isa<cir::BoolType, cir::PointerType, cir::VPtrType>(type)) {
3887 mlir::LLVM::ICmpPredicate
kind =
3889 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
3890 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
3891 return mlir::success();
3894 if (mlir::isa<cir::FPTypeInterface>(type)) {
3895 mlir::Type llvmResTy = getTypeConverter()->convertType(cmpOp.getType());
3896 if (cir::FenvAttr fenv = cmpOp.getFenvAttr()) {
3898 rewriter, cmpOp.getLoc(), adaptor.getLhs(), adaptor.getRhs(),
3899 cmpOp.getKind(), fenv, llvmResTy);
3900 rewriter.replaceOp(cmpOp, call.getResult(0));
3901 return mlir::success();
3903 mlir::LLVM::FCmpPredicate
kind =
3905 rewriter.replaceOpWithNewOp<mlir::LLVM::FCmpOp>(
3906 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
3907 return mlir::success();
3910 if (mlir::isa<cir::ComplexType>(type)) {
3911 mlir::Value lhs = adaptor.getLhs();
3912 mlir::Value rhs = adaptor.getRhs();
3913 mlir::Location loc = cmpOp.getLoc();
3915 auto complexType = mlir::cast<cir::ComplexType>(cmpOp.getLhs().getType());
3916 mlir::Type complexElemTy =
3917 getTypeConverter()->convertType(
complexType.getElementType());
3919 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
3920 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{0}));
3921 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
3922 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{1}));
3923 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
3924 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{0}));
3925 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
3926 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{1}));
3928 if (cmpOp.getKind() == cir::CmpOpKind::eq) {
3929 if (complexElemTy.isInteger()) {
3930 auto realCmp = mlir::LLVM::ICmpOp::create(
3931 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, lhsReal, rhsReal);
3932 auto imagCmp = mlir::LLVM::ICmpOp::create(
3933 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, lhsImag, rhsImag);
3934 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, imagCmp);
3935 return mlir::success();
3938 auto realCmp = mlir::LLVM::FCmpOp::create(
3939 rewriter, loc, mlir::LLVM::FCmpPredicate::oeq, lhsReal, rhsReal);
3940 auto imagCmp = mlir::LLVM::FCmpOp::create(
3941 rewriter, loc, mlir::LLVM::FCmpPredicate::oeq, lhsImag, rhsImag);
3942 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, imagCmp);
3943 return mlir::success();
3946 if (cmpOp.getKind() == cir::CmpOpKind::ne) {
3947 if (complexElemTy.isInteger()) {
3948 auto realCmp = mlir::LLVM::ICmpOp::create(
3949 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, lhsReal, rhsReal);
3950 auto imagCmp = mlir::LLVM::ICmpOp::create(
3951 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, lhsImag, rhsImag);
3952 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp);
3953 return mlir::success();
3956 auto realCmp = mlir::LLVM::FCmpOp::create(
3957 rewriter, loc, mlir::LLVM::FCmpPredicate::une, lhsReal, rhsReal);
3958 auto imagCmp = mlir::LLVM::FCmpOp::create(
3959 rewriter, loc, mlir::LLVM::FCmpPredicate::une, lhsImag, rhsImag);
3960 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp);
3961 return mlir::success();
3965 return cmpOp.emitError() <<
"unsupported type for CmpOp: " <<
type;
3971template <
typename OpTy>
3972static mlir::LogicalResult
3974 mlir::ConversionPatternRewriter &rewriter,
3975 const mlir::TypeConverter *typeConverter,
3976 llvm::StringRef opStr) {
3977 mlir::Location loc = op.getLoc();
3978 cir::IntType operandTy = op.getLhs().getType();
3981 mlir::Type resultTy = op.getResult().getType();
3982 auto resultIntTy = mlir::dyn_cast<cir::IntType>(resultTy);
3983 unsigned resultWidth = resultIntTy ? resultIntTy.getWidth() : 1;
3984 bool resultSigned = resultIntTy && resultIntTy.getIsSigned();
3986 bool sign = operandTy.getIsSigned() || resultSigned;
3988 std::max(operandTy.getWidth() + (
sign && operandTy.isUnsigned()),
3989 resultWidth + (
sign && !resultSigned));
3991 mlir::IntegerType encompassedLLVMTy = rewriter.getIntegerType(width);
3993 mlir::Value lhs = adaptor.getLhs();
3994 mlir::Value rhs = adaptor.getRhs();
3995 if (operandTy.getWidth() < width) {
3996 if (operandTy.isSigned()) {
3997 lhs = mlir::LLVM::SExtOp::create(rewriter, loc, encompassedLLVMTy, lhs);
3998 rhs = mlir::LLVM::SExtOp::create(rewriter, loc, encompassedLLVMTy, rhs);
4000 lhs = mlir::LLVM::ZExtOp::create(rewriter, loc, encompassedLLVMTy, lhs);
4001 rhs = mlir::LLVM::ZExtOp::create(rewriter, loc, encompassedLLVMTy, rhs);
4006 std::string intrinName = (
"llvm." + llvm::Twine(
sign ?
's' :
'u') + opStr +
4007 ".with.overflow.i" + llvm::Twine(width))
4009 auto intrinNameAttr = mlir::StringAttr::get(op.getContext(), intrinName);
4011 mlir::IntegerType overflowLLVMTy = rewriter.getI1Type();
4012 auto intrinRetTy = mlir::LLVM::LLVMStructType::getLiteral(
4013 rewriter.getContext(), {encompassedLLVMTy, overflowLLVMTy});
4015 auto callLLVMIntrinOp = mlir::LLVM::CallIntrinsicOp::create(
4016 rewriter, loc, intrinRetTy, intrinNameAttr, mlir::ValueRange{lhs, rhs});
4017 mlir::Value intrinRet = callLLVMIntrinOp.getResult(0);
4019 mlir::Value result = mlir::LLVM::ExtractValueOp::create(
4022 mlir::Value overflow = mlir::LLVM::ExtractValueOp::create(
4026 if (resultWidth < width) {
4027 mlir::Type resultLLVMTy = typeConverter->convertType(resultTy);
4029 mlir::LLVM::TruncOp::create(rewriter, loc, resultLLVMTy, result);
4033 mlir::Value truncResultExt;
4035 truncResultExt = mlir::LLVM::SExtOp::create(
4036 rewriter, loc, encompassedLLVMTy, truncResult);
4038 truncResultExt = mlir::LLVM::ZExtOp::create(
4039 rewriter, loc, encompassedLLVMTy, truncResult);
4040 auto truncOverflow = mlir::LLVM::ICmpOp::create(
4041 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, truncResultExt, result);
4043 result = truncResult;
4044 overflow = mlir::LLVM::OrOp::create(rewriter, loc, overflow, truncOverflow);
4047 mlir::Type boolLLVMTy =
4048 typeConverter->convertType(op.getOverflow().getType());
4049 if (boolLLVMTy != rewriter.getI1Type())
4050 overflow = mlir::LLVM::ZExtOp::create(rewriter, loc, boolLLVMTy, overflow);
4052 rewriter.replaceOp(op, mlir::ValueRange{result, overflow});
4054 return mlir::success();
4057mlir::LogicalResult CIRToLLVMAddOverflowOpLowering::matchAndRewrite(
4058 cir::AddOverflowOp op, OpAdaptor adaptor,
4059 mlir::ConversionPatternRewriter &rewriter)
const {
4063mlir::LogicalResult CIRToLLVMSubOverflowOpLowering::matchAndRewrite(
4064 cir::SubOverflowOp op, OpAdaptor adaptor,
4065 mlir::ConversionPatternRewriter &rewriter)
const {
4069mlir::LogicalResult CIRToLLVMMulOverflowOpLowering::matchAndRewrite(
4070 cir::MulOverflowOp op, OpAdaptor adaptor,
4071 mlir::ConversionPatternRewriter &rewriter)
const {
4075mlir::LogicalResult CIRToLLVMFrexpOpLowering::matchAndRewrite(
4076 cir::FrexpOp op, OpAdaptor adaptor,
4077 mlir::ConversionPatternRewriter &rewriter)
const {
4078 mlir::Location loc = op.getLoc();
4079 mlir::Type fpLLVMTy =
4080 getTypeConverter()->convertType(op.getResult().getType());
4081 mlir::Type intLLVMTy = getTypeConverter()->convertType(op.getExp().getType());
4083 auto structTy = mlir::LLVM::LLVMStructType::getLiteral(rewriter.getContext(),
4084 {fpLLVMTy, intLLVMTy});
4088 mlir::Value result = callOp.getResult(0);
4090 mlir::Value mantissa =
4091 mlir::LLVM::ExtractValueOp::create(rewriter, loc, result, 0);
4092 mlir::Value exponent =
4093 mlir::LLVM::ExtractValueOp::create(rewriter, loc, result, 1);
4094 rewriter.replaceOp(op, mlir::ValueRange{mantissa, exponent});
4095 return mlir::success();
4098mlir::LogicalResult CIRToLLVMModfOpLowering::matchAndRewrite(
4099 cir::ModfOp op, OpAdaptor adaptor,
4100 mlir::ConversionPatternRewriter &rewriter)
const {
4101 mlir::Location loc = op.getLoc();
4102 mlir::Type fpLLVMTy =
4103 getTypeConverter()->convertType(op.getFractional().getType());
4105 auto structTy = mlir::LLVM::LLVMStructType::getLiteral(rewriter.getContext(),
4106 {fpLLVMTy, fpLLVMTy});
4110 mlir::Value result = callOp.getResult(0);
4112 mlir::Value fractional =
4113 mlir::LLVM::ExtractValueOp::create(rewriter, loc, result, 0);
4114 mlir::Value integral =
4115 mlir::LLVM::ExtractValueOp::create(rewriter, loc, result, 1);
4116 rewriter.replaceOp(op, mlir::ValueRange{fractional, integral});
4117 return mlir::success();
4120mlir::LogicalResult CIRToLLVMShiftOpLowering::matchAndRewrite(
4121 cir::ShiftOp op, OpAdaptor adaptor,
4122 mlir::ConversionPatternRewriter &rewriter)
const {
4123 assert((op.getValue().getType() == op.getType()) &&
4124 "inconsistent operands' types NYI");
4126 const mlir::Type llvmTy = getTypeConverter()->convertType(op.getType());
4127 mlir::Value amt = adaptor.getAmount();
4128 mlir::Value val = adaptor.getValue();
4130 auto cirAmtTy = mlir::dyn_cast<cir::IntType>(op.getAmount().getType());
4133 auto cirValTy = mlir::cast<cir::IntType>(op.getValue().getType());
4141 amt =
getLLVMIntCast(rewriter, amt, llvmTy,
true, cirAmtTy.getWidth(),
4142 cirValTy.getWidth());
4144 auto cirValVTy = mlir::cast<cir::VectorType>(op.getValue().getType());
4146 mlir::cast<cir::IntType>(cirValVTy.getElementType()).isUnsigned();
4150 if (op.getIsShiftleft()) {
4151 rewriter.replaceOpWithNewOp<mlir::LLVM::ShlOp>(op, llvmTy, val, amt);
4152 return mlir::success();
4156 rewriter.replaceOpWithNewOp<mlir::LLVM::LShrOp>(op, llvmTy, val, amt);
4158 rewriter.replaceOpWithNewOp<mlir::LLVM::AShrOp>(op, llvmTy, val, amt);
4159 return mlir::success();
4162mlir::LogicalResult CIRToLLVMSelectOpLowering::matchAndRewrite(
4163 cir::SelectOp op, OpAdaptor adaptor,
4164 mlir::ConversionPatternRewriter &rewriter)
const {
4165 auto getConstantBool = [](mlir::Value value) -> cir::BoolAttr {
4166 auto definingOp = value.getDefiningOp<cir::ConstantOp>();
4170 auto constValue = definingOp.getValueAttr<cir::BoolAttr>();
4180 if (mlir::isa<cir::BoolType>(op.getTrueValue().getType())) {
4181 cir::BoolAttr trueValue = getConstantBool(op.getTrueValue());
4182 cir::BoolAttr falseValue = getConstantBool(op.getFalseValue());
4183 if (falseValue && !falseValue.getValue()) {
4185 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(op, adaptor.getCondition(),
4186 adaptor.getTrueValue());
4187 return mlir::success();
4189 if (trueValue && trueValue.getValue()) {
4191 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(op, adaptor.getCondition(),
4192 adaptor.getFalseValue());
4193 return mlir::success();
4197 mlir::Value llvmCondition = adaptor.getCondition();
4198 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(
4199 op, llvmCondition, adaptor.getTrueValue(), adaptor.getFalseValue());
4201 return mlir::success();
4205 mlir::DataLayout &dataLayout) {
4206 converter.addConversion([&](cir::PointerType type) -> mlir::Type {
4207 mlir::ptr::MemorySpaceAttrInterface addrSpaceAttr = type.getAddrSpace();
4208 unsigned numericAS = 0;
4210 if (
auto targetAsAttr =
4211 mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
4213 numericAS = targetAsAttr.getValue();
4214 return mlir::LLVM::LLVMPointerType::get(type.getContext(), numericAS);
4216 converter.addConversion([&](cir::VPtrType type) -> mlir::Type {
4218 return mlir::LLVM::LLVMPointerType::get(type.getContext());
4222 converter.addConversion([&](cir::CUDADeviceSurfaceType type) -> mlir::Type {
4223 return mlir::IntegerType::get(type.getContext(), 64);
4225 converter.addConversion([&](cir::CUDADeviceTextureType type) -> mlir::Type {
4226 return mlir::IntegerType::get(type.getContext(), 64);
4228 converter.addConversion([&](cir::ArrayType type) -> mlir::Type {
4235 return mlir::LLVM::LLVMArrayType::get(ty, type.getSize());
4237 converter.addConversion([&](cir::VectorType type) -> mlir::Type {
4241 if (
auto intTy = mlir::dyn_cast<cir::IntType>(type.getElementType());
4242 intTy && intTy.isBitInt())
4244 const mlir::Type ty = converter.convertType(type.getElementType());
4245 return mlir::VectorType::get(type.getSize(), ty, {type.getIsScalable()});
4247 converter.addConversion([&](cir::MatrixType type) -> mlir::Type {
4248 const uint64_t size = type.getNumRows() * type.getNumColumns();
4249 const mlir::Type elemTy = converter.convertType(type.getElementType());
4250 return mlir::VectorType::get(size, elemTy);
4252 converter.addConversion([&](cir::BoolType type) -> mlir::Type {
4253 return mlir::IntegerType::get(type.getContext(), 1,
4254 mlir::IntegerType::Signless);
4256 converter.addConversion([&](cir::IntType type) -> mlir::Type {
4258 return mlir::IntegerType::get(type.getContext(), type.getWidth());
4260 converter.addConversion([&](cir::SingleType type) -> mlir::Type {
4261 return mlir::Float32Type::get(type.getContext());
4263 converter.addConversion([&](cir::DoubleType type) -> mlir::Type {
4264 return mlir::Float64Type::get(type.getContext());
4266 converter.addConversion([&](cir::FP80Type type) -> mlir::Type {
4267 return mlir::Float80Type::get(type.getContext());
4269 converter.addConversion([&](cir::FP128Type type) -> mlir::Type {
4270 return mlir::Float128Type::get(type.getContext());
4272 converter.addConversion([&](cir::LongDoubleType type) -> mlir::Type {
4273 return converter.convertType(type.getUnderlying());
4275 converter.addConversion([&](cir::FP16Type type) -> mlir::Type {
4276 return mlir::Float16Type::get(type.getContext());
4278 converter.addConversion([&](cir::BF16Type type) -> mlir::Type {
4279 return mlir::BFloat16Type::get(type.getContext());
4281 converter.addConversion([&](cir::ComplexType type) -> mlir::Type {
4284 mlir::Type elementTy = converter.convertType(type.getElementType());
4285 mlir::Type structFields[2] = {elementTy, elementTy};
4286 return mlir::LLVM::LLVMStructType::getLiteral(type.getContext(),
4289 converter.addConversion([&](cir::FuncType type) -> std::optional<mlir::Type> {
4290 auto result = converter.convertType(type.getReturnType());
4292 arguments.reserve(type.getNumInputs());
4293 if (converter.convertTypes(type.getInputs(), arguments).failed())
4294 return std::nullopt;
4295 auto varArg = type.isVarArg();
4296 return mlir::LLVM::LLVMFunctionType::get(result, arguments, varArg);
4298 converter.addConversion([&](cir::StructType type) -> mlir::Type {
4300 for (mlir::Type ty : type.getMembers()) {
4313 llvmMembers.push_back(memberTy);
4316 mlir::LLVM::LLVMStructType llvmStruct;
4317 if (type.getName()) {
4318 llvmStruct = mlir::LLVM::LLVMStructType::getIdentified(
4319 type.getContext(), type.getPrefixedName());
4320 if (llvmStruct.setBody(llvmMembers, type.getPacked()).failed())
4321 llvm_unreachable(
"Failed to set body of record");
4323 llvmStruct = mlir::LLVM::LLVMStructType::getLiteral(
4324 type.getContext(), llvmMembers, type.getPacked());
4329 converter.addConversion([&](cir::UnionType type) -> mlir::Type {
4331 if (!type.getMembers().empty())
4332 if (
auto storage = type.getUnionStorageType(dataLayout)) {
4333 mlir::Type storageTy =
4337 llvmMembers.push_back(storageTy);
4339 if (mlir::Type pad = type.getPadding()) {
4343 llvmMembers.push_back(padTy);
4346 mlir::LLVM::LLVMStructType llvmStruct;
4347 if (type.getName()) {
4348 llvmStruct = mlir::LLVM::LLVMStructType::getIdentified(
4349 type.getContext(), type.getPrefixedName());
4350 if (llvmStruct.setBody(llvmMembers, type.getPacked()).failed())
4351 llvm_unreachable(
"Failed to set body of record");
4353 llvmStruct = mlir::LLVM::LLVMStructType::getLiteral(
4354 type.getContext(), llvmMembers, type.getPacked());
4358 converter.addConversion([&](cir::VoidType type) -> mlir::Type {
4359 return mlir::LLVM::LLVMVoidType::get(type.getContext());
4363 mlir::ModuleOp module, StringRef globalXtorName, StringRef llvmXtorName,
4367 module->getDiscardableAttrOfType<mlir::ArrayAttr>(globalXtorName))
4368 for (mlir::Attribute element : attr)
4369 globalXtors.emplace_back(createXtor(element));
4371 if (globalXtors.empty())
4374 mlir::OpBuilder builder(module.getContext());
4375 builder.setInsertionPointToEnd(&module.getBodyRegion().back());
4379 auto ctorPFTy = mlir::LLVM::LLVMPointerType::get(builder.getContext());
4381 ctorStructFields.push_back(builder.getI32Type());
4382 ctorStructFields.push_back(ctorPFTy);
4383 ctorStructFields.push_back(ctorPFTy);
4385 auto ctorStructTy = mlir::LLVM::LLVMStructType::getLiteral(
4386 builder.getContext(), ctorStructFields);
4387 auto ctorStructArrayTy =
4388 mlir::LLVM::LLVMArrayType::get(ctorStructTy, globalXtors.size());
4390 mlir::Location loc =
module.getLoc();
4391 auto newGlobalOp = mlir::LLVM::GlobalOp::create(
4392 builder, loc, ctorStructArrayTy,
false,
4393 mlir::LLVM::Linkage::Appending, llvmXtorName, mlir::Attribute());
4395 builder.createBlock(&newGlobalOp.getRegion());
4396 builder.setInsertionPointToEnd(newGlobalOp.getInitializerBlock());
4398 mlir::Value result =
4399 mlir::LLVM::UndefOp::create(builder, loc, ctorStructArrayTy);
4401 for (
auto [index, xtorInfo] : llvm::enumerate(globalXtors)) {
4402 mlir::Value structInit =
4403 mlir::LLVM::UndefOp::create(builder, loc, ctorStructTy);
4404 mlir::Value initPriority = mlir::LLVM::ConstantOp::create(
4405 builder, loc, ctorStructFields[0], xtorInfo.priority);
4406 mlir::Value initFuncAddr = mlir::LLVM::AddressOfOp::create(
4407 builder, loc, ctorStructFields[1], xtorInfo.name);
4408 mlir::Value initAssociate =
4409 xtorInfo.associated.empty()
4410 ? mlir::LLVM::ZeroOp::create(builder, loc, ctorStructFields[2])
4412 : mlir::LLVM::AddressOfOp::create(builder, loc, ctorStructFields[2],
4413 xtorInfo.associated)
4417 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
4418 initPriority, zero);
4419 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
4421 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
4423 result = mlir::LLVM::InsertValueOp::create(builder, loc, result, structInit,
4427 mlir::LLVM::ReturnOp::create(builder, loc, result);
4430mlir::LogicalResult CIRToLLVMObjSizeOpLowering::matchAndRewrite(
4431 cir::ObjSizeOp op, OpAdaptor adaptor,
4432 mlir::ConversionPatternRewriter &rewriter)
const {
4433 mlir::Type llvmResTy = getTypeConverter()->convertType(op.getType());
4434 mlir::Location loc = op->getLoc();
4436 mlir::IntegerType i1Ty = rewriter.getI1Type();
4438 auto i1Val = [&rewriter, &loc, &i1Ty](
bool val) {
4439 return mlir::LLVM::ConstantOp::create(rewriter, loc, i1Ty, val);
4446 i1Val(op.getNullunknown()),
4447 i1Val(op.getDynamic()),
4450 return mlir::LogicalResult::success();
4458constexpr StringRef llvmMetadataSectionName =
"llvm.metadata";
4463getOrCreateAnnotationStringGlobal(mlir::OpBuilder &builder, mlir::Location loc,
4464 mlir::ModuleOp module, llvm::StringRef str,
4465 llvm::StringMap<mlir::LLVM::GlobalOp> &cache,
4467 auto it = cache.find(str);
4468 if (it != cache.end())
4471 auto i8Ty = mlir::IntegerType::get(module.getContext(), 8);
4472 auto arrayTy = mlir::LLVM::LLVMArrayType::get(i8Ty, str.size() + 1);
4473 std::string
name =
".str";
4475 name +=
"." + std::to_string(cache.size());
4476 name +=
".annotation";
4480 mlir::LLVM::GlobalOp strGlobal = mlir::LLVM::GlobalOp::create(
4481 builder, loc, arrayTy,
true, mlir::LLVM::Linkage::Private,
4482 name, mlir::StringAttr::get(module.getContext(), std::string(str) +
'\0'),
4485 strGlobal.setSection(llvmMetadataSectionName);
4486 strGlobal.setUnnamedAddr(mlir::LLVM::UnnamedAddr::Global);
4487 strGlobal.setDsoLocal(
true);
4488 cache[str] = strGlobal;
4494mlir::LLVM::GlobalOp getOrCreateAnnotationArgsVar(
4495 mlir::OpBuilder &builder, mlir::Location loc, mlir::ModuleOp module,
4496 mlir::ArrayAttr argsAttr,
4497 llvm::StringMap<mlir::LLVM::GlobalOp> &argStringCache,
4498 llvm::MapVector<mlir::ArrayAttr, mlir::LLVM::GlobalOp> &argsCache) {
4499 auto it = argsCache.find(argsAttr);
4500 if (it != argsCache.end())
4503 auto ptrTy = mlir::LLVM::LLVMPointerType::get(builder.getContext());
4505 llvm::SmallVector<mlir::Type> fieldTypes;
4506 for (mlir::Attribute arg : argsAttr) {
4507 if (mlir::isa<mlir::StringAttr>(arg))
4508 fieldTypes.push_back(ptrTy);
4509 else if (
auto intAttr = mlir::dyn_cast<mlir::IntegerAttr>(arg))
4510 fieldTypes.push_back(intAttr.getType());
4512 llvm_unreachable(
"Unsupported annotation arg type");
4516 mlir::LLVM::LLVMStructType::getLiteral(builder.getContext(), fieldTypes);
4517 std::string
name =
".args";
4518 if (!argsCache.empty())
4519 name +=
"." + std::to_string(argsCache.size());
4520 name +=
".annotation";
4522 mlir::LLVM::GlobalOp argsGlobal = mlir::LLVM::GlobalOp::create(
4523 builder, loc, structTy,
true, mlir::LLVM::Linkage::Private,
4524 name, mlir::Attribute());
4525 argsGlobal.setSection(llvmMetadataSectionName);
4526 argsGlobal.setUnnamedAddr(mlir::LLVM::UnnamedAddr::Global);
4527 argsGlobal.setDsoLocal(
true);
4530 argsGlobal.getRegion().push_back(
new mlir::Block());
4531 mlir::OpBuilder initBuilder(module.getContext());
4532 initBuilder.setInsertionPointToEnd(argsGlobal.getInitializerBlock());
4534 mlir::Value structInit =
4535 mlir::LLVM::UndefOp::create(initBuilder, loc, structTy);
4536 for (
auto [idx, arg] : llvm::enumerate(argsAttr)) {
4537 if (
auto strArg = mlir::dyn_cast<mlir::StringAttr>(arg)) {
4538 mlir::LLVM::GlobalOp strGlobal = getOrCreateAnnotationStringGlobal(
4539 builder, loc, module, strArg.getValue(), argStringCache,
4541 mlir::LLVM::AddressOfOp strAddr = mlir::LLVM::AddressOfOp::create(
4542 initBuilder, loc, ptrTy, strGlobal.getSymName());
4543 structInit = mlir::LLVM::InsertValueOp::create(initBuilder, loc,
4544 structInit, strAddr, idx);
4545 }
else if (
auto intArg = mlir::dyn_cast<mlir::IntegerAttr>(arg)) {
4546 mlir::LLVM::ConstantOp intConst = mlir::LLVM::ConstantOp::create(
4547 initBuilder, loc, intArg.getType(), intArg.getValue());
4548 structInit = mlir::LLVM::InsertValueOp::create(initBuilder, loc,
4549 structInit, intConst, idx);
4551 llvm_unreachable(
"Unsupported annotation arg type");
4554 mlir::LLVM::ReturnOp::create(initBuilder, loc, structInit);
4556 argsCache[argsAttr] = argsGlobal;
4562std::pair<llvm::StringRef, unsigned> extractFileLine(mlir::Location loc) {
4563 mlir::Location resolved = loc;
4564 if (
auto fused = mlir::dyn_cast<mlir::FusedLoc>(resolved)) {
4565 if (!fused.getLocations().empty())
4566 resolved = fused.getLocations()[0];
4568 if (
auto fl = mlir::dyn_cast<mlir::FileLineColLoc>(resolved))
4569 return {fl.getFilename().getValue(), fl.getLine()};
4575 auto handleArray = [&](mlir::StringAttr symName, mlir::ArrayAttr arr,
4576 mlir::Location loc) {
4579 for (mlir::Attribute a : arr)
4580 if (
auto annot = mlir::dyn_cast<cir::AnnotationAttr>(a))
4581 collectedAnnotations.emplace_back(symName, annot, loc);
4586 module.walk([&](cir::GlobalOp op) {
4587 handleArray(op.getSymNameAttr(), op.getAnnotationsAttr(), op.getLoc());
4589 module.walk([&](cir::FuncOp op) {
4590 handleArray(op.getSymNameAttr(), op.getAnnotationsAttr(), op.getLoc());
4595 if (collectedAnnotations.empty())
4598 mlir::MLIRContext *ctx =
module.getContext();
4599 mlir::OpBuilder builder(ctx);
4600 builder.setInsertionPointToEnd(&module.getBodyRegion().back());
4602 auto ptrTy = mlir::LLVM::LLVMPointerType::get(ctx);
4603 auto i32Ty = builder.getI32Type();
4606 auto entryTy = mlir::LLVM::LLVMStructType::getLiteral(
4607 ctx, {ptrTy, ptrTy, ptrTy, i32Ty, ptrTy});
4609 mlir::LLVM::LLVMArrayType::get(entryTy, collectedAnnotations.size());
4611 mlir::Location moduleLoc =
module.getLoc();
4612 auto annotationsGlobal = mlir::LLVM::GlobalOp::create(
4613 builder, moduleLoc, arrayTy,
false,
4614 mlir::LLVM::Linkage::Appending,
"llvm.global.annotations",
4616 annotationsGlobal.setSection(llvmMetadataSectionName);
4620 mlir::OpBuilder constsBuilder(ctx);
4621 constsBuilder.setInsertionPoint(annotationsGlobal);
4623 llvm::StringMap<mlir::LLVM::GlobalOp> stringCache;
4624 llvm::StringMap<mlir::LLVM::GlobalOp> argStringCache;
4625 llvm::MapVector<mlir::ArrayAttr, mlir::LLVM::GlobalOp> argsCache;
4628 annotationsGlobal.getRegion().push_back(
new mlir::Block());
4629 mlir::OpBuilder initBuilder(ctx);
4630 initBuilder.setInsertionPointToEnd(annotationsGlobal.getInitializerBlock());
4632 mlir::Value arrayVal =
4633 mlir::LLVM::UndefOp::create(initBuilder, moduleLoc, arrayTy);
4635 for (
auto [idx, entry] : llvm::enumerate(collectedAnnotations)) {
4636 mlir::Value entryVal =
4637 mlir::LLVM::UndefOp::create(initBuilder, moduleLoc, entryTy);
4642 mlir::LLVM::AddressOfOp symAddr = mlir::LLVM::AddressOfOp::create(
4643 initBuilder, moduleLoc, ptrTy, entry.symName.getValue());
4644 entryVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
4645 entryVal, symAddr, zero);
4648 mlir::LLVM::GlobalOp nameGlobal = getOrCreateAnnotationStringGlobal(
4649 constsBuilder, moduleLoc, module, entry.annotation.getName().getValue(),
4650 stringCache,
false);
4651 mlir::LLVM::AddressOfOp nameAddr = mlir::LLVM::AddressOfOp::create(
4652 initBuilder, moduleLoc, ptrTy, nameGlobal.getSymName());
4653 entryVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
4654 entryVal, nameAddr, 1);
4657 auto [filename, line] = extractFileLine(entry.loc);
4658 mlir::LLVM::GlobalOp fileGlobal = getOrCreateAnnotationStringGlobal(
4659 constsBuilder, moduleLoc, module, filename, stringCache,
4661 mlir::LLVM::AddressOfOp fileAddr = mlir::LLVM::AddressOfOp::create(
4662 initBuilder, moduleLoc, ptrTy, fileGlobal.getSymName());
4663 entryVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
4664 entryVal, fileAddr, 2);
4665 mlir::LLVM::ConstantOp lineConst =
4666 mlir::LLVM::ConstantOp::create(initBuilder, moduleLoc, i32Ty, line);
4667 entryVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
4668 entryVal, lineConst, 3);
4671 mlir::ArrayAttr args = entry.annotation.getArgs();
4672 mlir::Value argsField;
4673 if (!args || args.empty()) {
4674 argsField = mlir::LLVM::ZeroOp::create(initBuilder, moduleLoc, ptrTy);
4676 mlir::LLVM::GlobalOp argsGlobal = getOrCreateAnnotationArgsVar(
4677 constsBuilder, moduleLoc, module, args, argStringCache, argsCache);
4678 argsField = mlir::LLVM::AddressOfOp::create(initBuilder, moduleLoc, ptrTy,
4679 argsGlobal.getSymName());
4681 entryVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
4682 entryVal, argsField, 4);
4684 arrayVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
4685 arrayVal, entryVal, idx);
4688 mlir::LLVM::ReturnOp::create(initBuilder, moduleLoc, arrayVal);
4694 mlir::ModuleOp module = getOperation();
4695 mlir::OpBuilder opBuilder(module.getContext());
4696 for (
auto &[blockAddOp, blockInfo] :
4698 mlir::LLVM::BlockTagOp resolvedLabel =
4700 assert(resolvedLabel &&
"expected BlockTagOp to already be emitted");
4701 mlir::FlatSymbolRefAttr fnSym = blockInfo.getFunc();
4702 auto blkAddTag = mlir::LLVM::BlockAddressAttr::get(
4703 opBuilder.getContext(), fnSym, resolvedLabel.getTagAttr());
4704 blockAddOp.setBlockAddrAttr(blkAddTag);
4711 if (mlir::Attribute tripleAttr =
4712 module->getAttr(cir::CIRDialect::getTripleAttrName()))
4713 module->setAttr(mlir::LLVM::LLVMDialect::getTargetTripleAttrName(),
4716 if (mlir::Attribute asmAttr =
4717 module->getAttr(cir::CIRDialect::getModuleLevelAsmAttrName()))
4718 module->setAttr(mlir::LLVM::LLVMDialect::getModuleLevelAsmAttrName(),
4721 if (
auto framePointerAttr = module->getAttrOfType<cir::FramePointerKindAttr>(
4722 cir::CIRDialect::getModuleFramePointerAttrName())) {
4723 mlir::OpBuilder builder(module.getContext());
4724 builder.setInsertionPointToEnd(module.getBody());
4725 auto flag = mlir::LLVM::ModuleFlagAttr::get(
4726 module.getContext(), mlir::LLVM::ModFlagBehavior::Max,
4727 builder.getStringAttr(
"frame-pointer"),
4728 builder.getI32IntegerAttr(
static_cast<int32_t
>(
4730 mlir::LLVM::ModuleFlagsOp::create(builder, module.getLoc(),
4731 builder.getArrayAttr({flag}));
4738 llvm::TimeTraceScope scope(
"Convert CIR to LLVM Pass");
4740 mlir::ModuleOp module = getOperation();
4741 mlir::DataLayout dl(module);
4742 mlir::LLVMTypeConverter converter(&getContext());
4752 mlir::SymbolTableCollection symbolTables;
4753 mlir::RewritePatternSet patterns(&getContext());
4754 patterns.add<CIRToLLVMBlockAddressOpLowering, CIRToLLVMConstantOpLowering,
4755 CIRToLLVMGlobalOpLowering, CIRToLLVMLabelOpLowering>(
4756 converter, patterns.getContext(), dl, symbolTables, blockInfoAddr);
4759#define GET_LLVM_LOWERING_PATTERNS_LIST
4760#include "clang/CIR/Dialect/IR/CIRLowering.inc"
4761#undef GET_LLVM_LOWERING_PATTERNS_LIST
4762 >(converter, patterns.getContext(), dl, symbolTables);
4770 mlir::ConversionTarget target(getContext());
4771 target.addLegalOp<mlir::ModuleOp>();
4772 target.addLegalDialect<mlir::LLVM::LLVMDialect>();
4773 mlir::configureOpenMPToLLVMConversionLegality(target, converter);
4774 target.addLegalDialect<mlir::omp::OpenMPDialect>();
4775 mlir::populateOpenMPToLLVMConversionPatterns(converter, patterns);
4776 target.addIllegalDialect<mlir::BuiltinDialect, cir::CIRDialect,
4777 mlir::func::FuncDialect>();
4780 ops.push_back(module);
4783 if (failed(applyPartialConversion(ops, target, std::move(patterns))))
4784 signalPassFailure();
4788 if (
auto dlSpec = mlir::dyn_cast_or_null<mlir::DataLayoutSpecAttr>(
4789 module->getAttr(mlir::DLTIDialect::kDataLayoutAttrName))) {
4791 for (mlir::DataLayoutEntryInterface entry : dlSpec.getEntries()) {
4792 if (entry.isTypeEntry() &&
4793 mlir::isa<cir::PointerType>(mlir::cast<mlir::Type>(entry.getKey())))
4795 kept.push_back(entry);
4797 module->setAttr(mlir::DLTIDialect::kDataLayoutAttrName,
4798 mlir::DataLayoutSpecAttr::get(module.getContext(), kept));
4803 module, cir::CIRDialect::getGlobalCtorsAttrName(),
"llvm.global_ctors",
4804 [](mlir::Attribute
attr) {
4805 auto ctorAttr = mlir::cast<cir::GlobalCtorAttr>(
attr);
4806 StringRef associated;
4807 if (mlir::FlatSymbolRefAttr assoc = ctorAttr.getAssociated())
4808 associated = assoc.getValue();
4810 ctorAttr.getPriority(), associated);
4814 module, cir::CIRDialect::getGlobalDtorsAttrName(),
"llvm.global_dtors",
4815 [](mlir::Attribute
attr) {
4816 auto dtorAttr = mlir::cast<cir::GlobalDtorAttr>(
attr);
4817 StringRef associated;
4818 if (mlir::FlatSymbolRefAttr assoc = dtorAttr.getAssociated())
4819 associated = assoc.getValue();
4821 dtorAttr.getPriority(), associated);
4829mlir::LogicalResult CIRToLLVMBrOpLowering::matchAndRewrite(
4830 cir::BrOp op, OpAdaptor adaptor,
4831 mlir::ConversionPatternRewriter &rewriter)
const {
4832 rewriter.replaceOpWithNewOp<mlir::LLVM::BrOp>(op, adaptor.getOperands(),
4834 return mlir::LogicalResult::success();
4837mlir::LogicalResult CIRToLLVMGetMemberOpLowering::matchAndRewrite(
4838 cir::GetMemberOp op, OpAdaptor adaptor,
4839 mlir::ConversionPatternRewriter &rewriter)
const {
4840 mlir::Type llResTy = getTypeConverter()->convertType(op.getType());
4841 mlir::Type pointee = op.getAddrTy().getPointee();
4843 if (mlir::isa<cir::UnionType>(pointee)) {
4846 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(op, llResTy,
4848 return mlir::success();
4851 auto structTy = mlir::cast<cir::StructType>(pointee);
4857 0,
static_cast<int32_t>(structTy.getLLVMFieldIndex(op.getIndex()))};
4858 const mlir::Type elementTy = getTypeConverter()->convertType(structTy);
4863 mlir::LLVM::GEPNoWrapFlags flags =
4864 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
4865 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
4866 op, llResTy, elementTy, adaptor.getAddr(), offset, flags);
4867 return mlir::success();
4870mlir::LogicalResult CIRToLLVMExtractMemberOpLowering::matchAndRewrite(
4871 cir::ExtractMemberOp op, OpAdaptor adaptor,
4872 mlir::ConversionPatternRewriter &rewriter)
const {
4873 if (mlir::isa<cir::UnionType>(op.getRecord().getType())) {
4874 op.emitError(
"cir.extract_member cannot extract member from a union");
4875 return mlir::failure();
4878 auto structTy = mlir::cast<cir::StructType>(op.getRecord().getType());
4879 std::int64_t indices[1] = {
4880 static_cast<std::int64_t
>(structTy.getLLVMFieldIndex(op.getIndex()))};
4881 rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractValueOp>(
4882 op, adaptor.getRecord(), indices);
4883 return mlir::success();
4886mlir::LogicalResult CIRToLLVMInsertMemberOpLowering::matchAndRewrite(
4887 cir::InsertMemberOp op, OpAdaptor adaptor,
4888 mlir::ConversionPatternRewriter &rewriter)
const {
4889 if (mlir::isa<cir::UnionType>(op.getRecord().getType())) {
4890 op.emitError(
"cir.update_member cannot update member of a union");
4891 return mlir::failure();
4894 auto structTy = mlir::cast<cir::StructType>(op.getRecord().getType());
4895 std::int64_t indices[1] = {
4896 static_cast<std::int64_t
>(structTy.getLLVMFieldIndex(op.getIndex()))};
4897 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
4898 op, adaptor.getRecord(), adaptor.getValue(), indices);
4899 return mlir::success();
4903 mlir::SymbolTableCollection &symbolTables,
4904 mlir::Operation *srcOp, llvm::StringRef fnName,
4905 mlir::Type fnTy, mlir::ArrayAttr argAttrs,
4906 mlir::ArrayAttr resAttrs) {
4907 mlir::ModuleOp modOp = srcOp->getParentOfType<mlir::ModuleOp>();
4908 mlir::Operation *sourceSymbol = symbolTables.lookupSymbolIn(
4909 modOp, mlir::StringAttr::get(fnTy.getContext(), fnName));
4910 if (!sourceSymbol) {
4911 mlir::OpBuilder::InsertionGuard guard(rewriter);
4912 auto enclosingFnOp = srcOp->getParentOfType<mlir::LLVM::LLVMFuncOp>();
4913 rewriter.setInsertionPoint(enclosingFnOp);
4915 mlir::LLVM::LLVMFuncOp::create(rewriter, srcOp->getLoc(), fnName, fnTy);
4917 fn.setArgAttrsAttr(argAttrs);
4919 fn.setResAttrsAttr(resAttrs);
4921 symbolTables.getSymbolTable(fn->getParentOp()).insert(fn);
4925mlir::LogicalResult CIRToLLVMThrowOpLowering::matchAndRewrite(
4926 cir::ThrowOp op, OpAdaptor adaptor,
4927 mlir::ConversionPatternRewriter &rewriter)
const {
4928 mlir::Location loc = op.getLoc();
4929 auto voidTy = mlir::LLVM::LLVMVoidType::get(getContext());
4934 if (op.rethrows()) {
4935 auto funcTy = mlir::LLVM::LLVMFunctionType::get(voidTy, {});
4938 const llvm::StringRef functionName =
"__cxa_rethrow";
4939 createLLVMFuncOpIfNotExist(rewriter, symbolTables, op, functionName,
4942 auto cxaRethrow = mlir::LLVM::CallOp::create(
4943 rewriter, loc, mlir::TypeRange{}, functionName);
4945 rewriter.replaceOp(op, cxaRethrow);
4946 return mlir::success();
4949 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4950 auto fnTy = mlir::LLVM::LLVMFunctionType::get(
4951 voidTy, {llvmPtrTy, llvmPtrTy, llvmPtrTy});
4954 const llvm::StringRef fnName =
"__cxa_throw";
4957 mlir::Value typeInfo = mlir::LLVM::AddressOfOp::create(
4958 rewriter, loc, mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
4959 adaptor.getTypeInfoAttr());
4963 dtor = mlir::LLVM::AddressOfOp::create(rewriter, loc, llvmPtrTy,
4964 adaptor.getDtorAttr());
4966 dtor = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmPtrTy);
4969 auto cxaThrowCall = mlir::LLVM::CallOp::create(
4970 rewriter, loc, mlir::TypeRange{}, fnName,
4971 mlir::ValueRange{adaptor.getExceptionPtr(), typeInfo, dtor});
4973 rewriter.replaceOp(op, cxaThrowCall);
4974 return mlir::success();
4977mlir::LogicalResult CIRToLLVMAllocExceptionOpLowering::matchAndRewrite(
4978 cir::AllocExceptionOp op, OpAdaptor adaptor,
4979 mlir::ConversionPatternRewriter &rewriter)
const {
4981 StringRef fnName =
"__cxa_allocate_exception";
4982 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4983 auto int64Ty = mlir::IntegerType::get(rewriter.getContext(), 64);
4984 auto fnTy = mlir::LLVM::LLVMFunctionType::get(llvmPtrTy, {int64Ty});
4987 auto exceptionSize = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
4988 adaptor.getSizeAttr());
4990 auto allocaExceptionCall = mlir::LLVM::CallOp::create(
4991 rewriter, op.getLoc(), mlir::TypeRange{llvmPtrTy}, fnName,
4992 mlir::ValueRange{exceptionSize});
4994 rewriter.replaceOp(op, allocaExceptionCall);
4995 return mlir::success();
4998static mlir::LLVM::LLVMStructType
5001 mlir::MLIRContext *ctx = rewriter.getContext();
5002 auto llvmPtr = mlir::LLVM::LLVMPointerType::get(ctx);
5004 return mlir::LLVM::LLVMStructType::getLiteral(ctx, structFields);
5007mlir::LogicalResult CIRToLLVMEhInflightOpLowering::matchAndRewrite(
5008 cir::EhInflightOp op, OpAdaptor adaptor,
5009 mlir::ConversionPatternRewriter &rewriter)
const {
5010 auto llvmFn = op->getParentOfType<mlir::LLVM::LLVMFuncOp>();
5011 assert(llvmFn &&
"expected LLVM function parent");
5012 mlir::Block *entryBlock = &llvmFn.getRegion().front();
5013 assert(entryBlock->isEntryBlock());
5015 mlir::ArrayAttr catchListAttr = op.getCatchTypeListAttr();
5016 mlir::ArrayAttr filterListAttr = op.getFilterTypeListAttr();
5017 mlir::SmallVector<mlir::Value> landingPadClauses;
5019 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
5020 mlir::Location loc = op.getLoc();
5025 if (catchListAttr) {
5028 for (mlir::Attribute catchAttr : catchListAttr) {
5029 auto symAttr = cast<mlir::FlatSymbolRefAttr>(catchAttr);
5032 mlir::OpBuilder::InsertionGuard guard(rewriter);
5033 rewriter.setInsertionPointToStart(entryBlock);
5034 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
5035 rewriter, loc, llvmPtrTy, symAttr.getValue());
5036 landingPadClauses.push_back(addrOp);
5043 if (op.getCatchAll() ||
5044 (!catchListAttr && !op.getCleanup() && !filterListAttr)) {
5045 mlir::OpBuilder::InsertionGuard guard(rewriter);
5046 rewriter.setInsertionPointToStart(entryBlock);
5047 mlir::Value nullOp = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmPtrTy);
5048 landingPadClauses.push_back(nullOp);
5051 if (filterListAttr) {
5055 mlir::OpBuilder::InsertionGuard guard(rewriter);
5056 rewriter.setInsertionPointToStart(entryBlock);
5057 auto filterArrayTy =
5058 mlir::LLVM::LLVMArrayType::get(llvmPtrTy, filterListAttr.size());
5059 mlir::Value filterVal;
5060 if (filterListAttr.empty()) {
5061 filterVal = mlir::LLVM::ZeroOp::create(rewriter, loc, filterArrayTy);
5063 filterVal = mlir::LLVM::UndefOp::create(rewriter, loc, filterArrayTy);
5064 for (
auto [i, filterAttr] : llvm::enumerate(filterListAttr)) {
5065 auto symAttr = mlir::cast<mlir::FlatSymbolRefAttr>(filterAttr);
5066 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
5067 rewriter, loc, llvmPtrTy, symAttr.getValue());
5068 filterVal = mlir::LLVM::InsertValueOp::create(
5069 rewriter, loc, filterVal, addrOp,
5073 landingPadClauses.push_back(filterVal);
5078 mlir::LLVM::LLVMStructType llvmLandingPadStructTy =
5080 auto landingPadOp = mlir::LLVM::LandingpadOp::create(
5081 rewriter, loc, llvmLandingPadStructTy, landingPadClauses);
5086 if (op.getCleanup() && !op.getCatchAll())
5087 landingPadOp.setCleanup(
true);
5090 mlir::LLVM::ExtractValueOp::create(rewriter, loc, landingPadOp, 0);
5091 mlir::Value selector =
5092 mlir::LLVM::ExtractValueOp::create(rewriter, loc, landingPadOp, 1);
5093 rewriter.replaceOp(op, mlir::ValueRange{slot, selector});
5095 return mlir::success();
5098mlir::LogicalResult CIRToLLVMResumeFlatOpLowering::matchAndRewrite(
5099 cir::ResumeFlatOp op, OpAdaptor adaptor,
5100 mlir::ConversionPatternRewriter &rewriter)
const {
5105 mlir::Value poison = mlir::LLVM::PoisonOp::create(rewriter, op.getLoc(),
5106 llvmLandingPadStructTy);
5109 mlir::Value slot = mlir::LLVM::InsertValueOp::create(
5110 rewriter, op.getLoc(), poison, adaptor.getExceptionPtr(), slotIdx);
5113 mlir::Value selector = mlir::LLVM::InsertValueOp::create(
5114 rewriter, op.getLoc(), slot, adaptor.getTypeId(), selectorIdx);
5116 rewriter.replaceOpWithNewOp<mlir::LLVM::ResumeOp>(op, selector);
5117 return mlir::success();
5120mlir::LogicalResult CIRToLLVMEhTypeIdOpLowering::matchAndRewrite(
5121 cir::EhTypeIdOp op, OpAdaptor adaptor,
5122 mlir::ConversionPatternRewriter &rewriter)
const {
5123 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
5124 rewriter, op.getLoc(),
5125 mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
5126 op.getTypeSymAttr());
5127 rewriter.replaceOpWithNewOp<mlir::LLVM::EhTypeidForOp>(
5128 op, rewriter.getI32Type(), addrOp);
5129 return mlir::success();
5132mlir::LogicalResult CIRToLLVMEhSetjmpOpLowering::matchAndRewrite(
5133 cir::EhSetjmpOp op, OpAdaptor adaptor,
5134 mlir::ConversionPatternRewriter &rewriter)
const {
5135 mlir::Type returnType = typeConverter->convertType(op.getType());
5136 mlir::LLVM::CallIntrinsicOp newOp =
5138 returnType, adaptor.getEnv());
5139 rewriter.replaceOp(op, newOp);
5140 return mlir::success();
5143mlir::LogicalResult CIRToLLVMEhLongjmpOpLowering::matchAndRewrite(
5144 cir::EhLongjmpOp op, OpAdaptor adaptor,
5145 mlir::ConversionPatternRewriter &rewriter)
const {
5147 {}, adaptor.getOperands());
5148 return mlir::success();
5151mlir::LogicalResult CIRToLLVMTrapOpLowering::matchAndRewrite(
5152 cir::TrapOp op, OpAdaptor adaptor,
5153 mlir::ConversionPatternRewriter &rewriter)
const {
5154 mlir::Location loc = op->getLoc();
5155 rewriter.eraseOp(op);
5157 mlir::LLVM::Trap::create(rewriter, loc);
5162 mlir::LLVM::UnreachableOp::create(rewriter, loc);
5164 return mlir::success();
5169 mlir::ConversionPatternRewriter &rewriter,
5170 mlir::SymbolTableCollection &symbolTables,
5171 const mlir::TypeConverter *converter,
5172 mlir::FlatSymbolRefAttr nameAttr, mlir::Type &eltType) {
5173 auto module = op->getParentOfType<mlir::ModuleOp>();
5174 mlir::Operation *symbol = symbolTables.lookupSymbolIn(module, nameAttr);
5175 if (
auto llvmSymbol = mlir::dyn_cast<mlir::LLVM::GlobalOp>(symbol)) {
5176 eltType = llvmSymbol.getType();
5177 }
else if (
auto cirSymbol = mlir::dyn_cast<cir::GlobalOp>(symbol)) {
5178 eltType = converter->convertType(cirSymbol.getSymType());
5180 op->emitError() <<
"unexpected symbol type for " << symbol;
5184 return mlir::LLVM::AddressOfOp::create(
5185 rewriter, op->getLoc(),
5186 mlir::LLVM::LLVMPointerType::get(op->getContext()), nameAttr.getValue());
5189mlir::LogicalResult CIRToLLVMVTableAddrPointOpLowering::matchAndRewrite(
5190 cir::VTableAddrPointOp op, OpAdaptor adaptor,
5191 mlir::ConversionPatternRewriter &rewriter)
const {
5192 const mlir::TypeConverter *converter = getTypeConverter();
5193 mlir::Type targetType = converter->convertType(op.getType());
5196 mlir::Value symAddr = getValueForVTableSymbol(
5197 op, rewriter, symbolTables, converter, op.getNameAttr(), eltType);
5199 return op.emitError() <<
"Unable to get value for vtable symbol";
5202 0, op.getAddressPointAttr().getIndex(),
5203 op.getAddressPointAttr().getOffset()};
5205 assert(eltType &&
"Shouldn't ever be missing an eltType here");
5206 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
5207 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
5208 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, targetType, eltType,
5209 symAddr, offsets, inboundsNuw);
5210 return mlir::success();
5213mlir::LogicalResult CIRToLLVMVTableGetVPtrOpLowering::matchAndRewrite(
5214 cir::VTableGetVPtrOp op, OpAdaptor adaptor,
5215 mlir::ConversionPatternRewriter &rewriter)
const {
5219 mlir::Value srcVal = adaptor.getSrc();
5220 rewriter.replaceOp(op, srcVal);
5221 return mlir::success();
5224mlir::LogicalResult CIRToLLVMVTableGetVirtualFnAddrOpLowering::matchAndRewrite(
5225 cir::VTableGetVirtualFnAddrOp op, OpAdaptor adaptor,
5226 mlir::ConversionPatternRewriter &rewriter)
const {
5227 mlir::Type targetType = getTypeConverter()->convertType(op.getType());
5228 auto eltType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
5231 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
5232 op, targetType, eltType, adaptor.getVptr(), offsets,
5233 mlir::LLVM::GEPNoWrapFlags::inbounds);
5234 return mlir::success();
5237mlir::LogicalResult CIRToLLVMVTTAddrPointOpLowering::matchAndRewrite(
5238 cir::VTTAddrPointOp op, OpAdaptor adaptor,
5239 mlir::ConversionPatternRewriter &rewriter)
const {
5240 const mlir::Type resultType = getTypeConverter()->convertType(op.getType());
5243 mlir::Value llvmAddr = adaptor.getSymAddr();
5245 if (op.getSymAddr()) {
5246 if (op.getOffset() == 0) {
5247 rewriter.replaceOp(op, {llvmAddr});
5248 return mlir::success();
5251 offsets.push_back(adaptor.getOffset());
5252 eltType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
5256 op.getNameAttr(), eltType);
5257 assert(eltType &&
"Shouldn't ever be missing an eltType here");
5258 offsets.push_back(0);
5259 offsets.push_back(adaptor.getOffset());
5261 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
5262 op, resultType, eltType, llvmAddr, offsets,
5263 mlir::LLVM::GEPNoWrapFlags::inbounds);
5264 return mlir::success();
5267mlir::LogicalResult CIRToLLVMVecCreateOpLowering::matchAndRewrite(
5268 cir::VecCreateOp op, OpAdaptor adaptor,
5269 mlir::ConversionPatternRewriter &rewriter)
const {
5272 const cir::VectorType vecTy = op.getType();
5273 const mlir::Type llvmTy = typeConverter->convertType(vecTy);
5274 const mlir::Location loc = op.getLoc();
5275 mlir::Value result = mlir::LLVM::PoisonOp::create(rewriter, loc, llvmTy);
5276 assert(vecTy.getSize() == op.getElements().size() &&
5277 "cir.vec.create op count doesn't match vector type elements count");
5279 for (uint64_t i = 0; i < vecTy.getSize(); ++i) {
5280 const mlir::Value indexValue =
5281 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
5282 result = mlir::LLVM::InsertElementOp::create(
5283 rewriter, loc, result, adaptor.getElements()[i], indexValue);
5286 rewriter.replaceOp(op, result);
5287 return mlir::success();
5290mlir::LogicalResult CIRToLLVMVecExtractOpLowering::matchAndRewrite(
5291 cir::VecExtractOp op, OpAdaptor adaptor,
5292 mlir::ConversionPatternRewriter &rewriter)
const {
5293 rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractElementOp>(
5294 op, adaptor.getVec(), adaptor.getIndex());
5295 return mlir::success();
5298mlir::LogicalResult CIRToLLVMVecInsertOpLowering::matchAndRewrite(
5299 cir::VecInsertOp op, OpAdaptor adaptor,
5300 mlir::ConversionPatternRewriter &rewriter)
const {
5301 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertElementOp>(
5302 op, adaptor.getVec(), adaptor.getValue(), adaptor.getIndex());
5303 return mlir::success();
5306template <
typename LLVMOp,
typename CIROp>
5307static mlir::LogicalResult
5309 const mlir::TypeConverter &typeConverter,
5310 mlir::ConversionPatternRewriter &rewriter) {
5311 mlir::Type resultTy = typeConverter.convertType(op.getType());
5312 mlir::LLVM::FastmathFlags fastmathFlags{};
5313 if (std::optional<cir::FastMathFlags> fastmath = op.getFastmathFlags())
5316 typename LLVMOp::Properties properties =
5318 properties.setFastmathFlags(
5319 mlir::LLVM::FastmathFlagsAttr::get(op.getContext(), fastmathFlags));
5320 rewriter.replaceOpWithNewOp<LLVMOp>(op, mlir::TypeRange{resultTy},
5321 adaptor.getOperands(), properties);
5323 return mlir::success();
5326mlir::LogicalResult CIRToLLVMVecReduceFAddOpLowering::matchAndRewrite(
5327 cir::VecReduceFAddOp op, OpAdaptor adaptor,
5328 mlir::ConversionPatternRewriter &rewriter)
const {
5329 return lowerFPVectorReduction<mlir::LLVM::vector_reduce_fadd>(
5330 op, adaptor, *getTypeConverter(), rewriter);
5333mlir::LogicalResult CIRToLLVMVecReduceFMulOpLowering::matchAndRewrite(
5334 cir::VecReduceFMulOp op, OpAdaptor adaptor,
5335 mlir::ConversionPatternRewriter &rewriter)
const {
5336 return lowerFPVectorReduction<mlir::LLVM::vector_reduce_fmul>(
5337 op, adaptor, *getTypeConverter(), rewriter);
5340mlir::LogicalResult CIRToLLVMVecReduceFMaxOpLowering::matchAndRewrite(
5341 cir::VecReduceFMaxOp op, OpAdaptor adaptor,
5342 mlir::ConversionPatternRewriter &rewriter)
const {
5343 return lowerFPVectorReduction<mlir::LLVM::vector_reduce_fmax>(
5344 op, adaptor, *getTypeConverter(), rewriter);
5347mlir::LogicalResult CIRToLLVMVecReduceFMinOpLowering::matchAndRewrite(
5348 cir::VecReduceFMinOp op, OpAdaptor adaptor,
5349 mlir::ConversionPatternRewriter &rewriter)
const {
5350 return lowerFPVectorReduction<mlir::LLVM::vector_reduce_fmin>(
5351 op, adaptor, *getTypeConverter(), rewriter);
5354mlir::LogicalResult CIRToLLVMVecCmpOpLowering::matchAndRewrite(
5355 cir::VecCmpOp op, OpAdaptor adaptor,
5356 mlir::ConversionPatternRewriter &rewriter)
const {
5357 mlir::Type elementType = op.getLhs().getType().getElementType();
5358 mlir::Value bitResult;
5359 if (
auto intType = mlir::dyn_cast<cir::IntType>(elementType)) {
5360 bitResult = mlir::LLVM::ICmpOp::create(
5361 rewriter, op.getLoc(),
5363 adaptor.getLhs(), adaptor.getRhs());
5364 }
else if (
auto boolType = mlir::dyn_cast<cir::BoolType>(elementType)) {
5365 bitResult = mlir::LLVM::ICmpOp::create(
5366 rewriter, op.getLoc(),
5368 adaptor.getLhs(), adaptor.getRhs());
5369 }
else if (mlir::isa<cir::FPTypeInterface>(elementType)) {
5370 if (cir::FenvAttr fenv = op.getFenvAttr()) {
5371 auto i1VecTy = mlir::VectorType::get(op.getLhs().getType().getSize(),
5372 rewriter.getI1Type());
5374 adaptor.getLhs(), adaptor.getRhs(),
5375 op.getKind(), fenv, i1VecTy)
5378 bitResult = mlir::LLVM::FCmpOp::create(
5380 adaptor.getLhs(), adaptor.getRhs());
5383 return op.emitError() <<
"unsupported type for VecCmpOp: " << elementType;
5389 mlir::Type vecElemTy = op.getType().getElementType();
5390 if (isa<cir::IntType>(vecElemTy) &&
5391 cast<cir::IntType>(vecElemTy).getWidth() > 1)
5392 rewriter.replaceOpWithNewOp<mlir::LLVM::SExtOp>(
5393 op, typeConverter->convertType(op.getType()), bitResult);
5395 rewriter.replaceOp(op, bitResult);
5396 return mlir::success();
5399mlir::LogicalResult CIRToLLVMVecSplatOpLowering::matchAndRewrite(
5400 cir::VecSplatOp op, OpAdaptor adaptor,
5401 mlir::ConversionPatternRewriter &rewriter)
const {
5407 mlir::Type llvmTy = typeConverter->convertType(op.getType());
5408 mlir::Location loc = op.getLoc();
5409 mlir::Value poison = mlir::LLVM::PoisonOp::create(rewriter, loc, llvmTy);
5411 mlir::Value elementValue = adaptor.getValue();
5412 if (elementValue.getDefiningOp<mlir::LLVM::PoisonOp>()) {
5415 rewriter.replaceOp(op, poison);
5416 return mlir::success();
5419 if (
auto constValue = elementValue.getDefiningOp<mlir::LLVM::ConstantOp>()) {
5420 if (
auto intAttr = dyn_cast<mlir::IntegerAttr>(constValue.getValue())) {
5421 mlir::DenseIntElementsAttr denseVec = mlir::DenseIntElementsAttr::get(
5422 mlir::cast<mlir::ShapedType>(llvmTy), intAttr.getValue());
5423 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
5424 op, denseVec.getType(), denseVec);
5425 return mlir::success();
5428 if (
auto fpAttr = dyn_cast<mlir::FloatAttr>(constValue.getValue())) {
5429 mlir::DenseFPElementsAttr denseVec = mlir::DenseFPElementsAttr::get(
5430 mlir::cast<mlir::ShapedType>(llvmTy), fpAttr.getValue());
5431 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
5432 op, denseVec.getType(), denseVec);
5433 return mlir::success();
5437 mlir::Value indexValue =
5438 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), 0);
5439 mlir::Value oneElement = mlir::LLVM::InsertElementOp::create(
5440 rewriter, loc, poison, elementValue, indexValue);
5442 mlir::cast<mlir::VectorType>(llvmTy).getNumElements(), 0);
5443 rewriter.replaceOpWithNewOp<mlir::LLVM::ShuffleVectorOp>(op, oneElement,
5444 poison, zeroValues);
5445 return mlir::success();
5448mlir::LogicalResult CIRToLLVMVecShuffleOpLowering::matchAndRewrite(
5449 cir::VecShuffleOp op, OpAdaptor adaptor,
5450 mlir::ConversionPatternRewriter &rewriter)
const {
5456 op.getIndices().begin(), op.getIndices().end(),
5457 std::back_inserter(indices), [](mlir::Attribute intAttr) {
5458 return mlir::cast<cir::IntAttr>(intAttr).getValue().getSExtValue();
5460 rewriter.replaceOpWithNewOp<mlir::LLVM::ShuffleVectorOp>(
5461 op, adaptor.getVec1(), adaptor.getVec2(), indices);
5462 return mlir::success();
5465mlir::LogicalResult CIRToLLVMVecShuffleDynamicOpLowering::matchAndRewrite(
5466 cir::VecShuffleDynamicOp op, OpAdaptor adaptor,
5467 mlir::ConversionPatternRewriter &rewriter)
const {
5479 mlir::Location loc = op.getLoc();
5480 mlir::Value input = adaptor.getVec();
5481 mlir::Type llvmIndexVecType =
5482 getTypeConverter()->convertType(op.getIndices().getType());
5483 mlir::Type llvmIndexType = getTypeConverter()->convertType(
5484 op.getIndices().getType().getElementType());
5485 uint64_t numElements = op.getVec().getType().getSize();
5487 uint64_t maskBits = llvm::NextPowerOf2(numElements - 1) - 1;
5488 mlir::Value maskValue = mlir::LLVM::ConstantOp::create(
5489 rewriter, loc, llvmIndexType,
5490 rewriter.getIntegerAttr(llvmIndexType, maskBits));
5491 mlir::Value maskVector =
5492 mlir::LLVM::UndefOp::create(rewriter, loc, llvmIndexVecType);
5494 for (uint64_t i = 0; i < numElements; ++i) {
5495 mlir::Value idxValue =
5496 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
5497 maskVector = mlir::LLVM::InsertElementOp::create(rewriter, loc, maskVector,
5498 maskValue, idxValue);
5501 mlir::Value maskedIndices = mlir::LLVM::AndOp::create(
5502 rewriter, loc, llvmIndexVecType, adaptor.getIndices(), maskVector);
5503 mlir::Value result = mlir::LLVM::UndefOp::create(
5504 rewriter, loc, getTypeConverter()->convertType(op.getVec().getType()));
5505 for (uint64_t i = 0; i < numElements; ++i) {
5506 mlir::Value iValue =
5507 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
5508 mlir::Value indexValue = mlir::LLVM::ExtractElementOp::create(
5509 rewriter, loc, maskedIndices, iValue);
5510 mlir::Value valueAtIndex =
5511 mlir::LLVM::ExtractElementOp::create(rewriter, loc, input, indexValue);
5512 result = mlir::LLVM::InsertElementOp::create(rewriter, loc, result,
5513 valueAtIndex, iValue);
5515 rewriter.replaceOp(op, result);
5516 return mlir::success();
5519mlir::LogicalResult CIRToLLVMVecTernaryOpLowering::matchAndRewrite(
5520 cir::VecTernaryOp op, OpAdaptor adaptor,
5521 mlir::ConversionPatternRewriter &rewriter)
const {
5522 mlir::Value bitVec = adaptor.getCond();
5524 if (!isa<cir::BoolType>(op.getCond().getType().getElementType())) {
5526 bitVec = mlir::LLVM::ICmpOp::create(
5527 rewriter, op.getLoc(), mlir::LLVM::ICmpPredicate::ne, adaptor.getCond(),
5528 mlir::LLVM::ZeroOp::create(
5529 rewriter, op.getCond().getLoc(),
5530 typeConverter->convertType(op.getCond().getType())));
5533 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(
5534 op, bitVec, adaptor.getLhs(), adaptor.getRhs());
5535 return mlir::success();
5541 mlir::Location loc, cir::MatrixType matrixTy,
5542 mlir::Value rowIdx, mlir::Value columnIdx) {
5543 rowIdx =
createIntCast(rewriter, rowIdx, rewriter.getI64Type(),
false);
5544 columnIdx =
createIntCast(rewriter, columnIdx, rewriter.getI64Type(),
false);
5545 mlir::Type indexTy = rowIdx.getType();
5546 mlir::Value numRows = mlir::LLVM::ConstantOp::create(
5547 rewriter, loc, indexTy,
5548 rewriter.getIntegerAttr(indexTy, matrixTy.getNumRows()));
5549 mlir::Value flatIndex = mlir::LLVM::MulOp::create(
5550 rewriter, loc, {columnIdx, numRows}, {},
5552 return mlir::LLVM::AddOp::create(rewriter, loc, flatIndex, rowIdx,
5556mlir::LogicalResult CIRToLLVMMatrixExtractOpLowering::matchAndRewrite(
5557 cir::MatrixExtractOp op, OpAdaptor adaptor,
5558 mlir::ConversionPatternRewriter &rewriter)
const {
5559 mlir::Value flatIndex =
5560 computeMatrixFlatIndex(rewriter, op.getLoc(), op.getMatrix().getType(),
5561 adaptor.getRowIdx(), adaptor.getColumnIdx());
5562 rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractElementOp>(
5563 op, adaptor.getMatrix(), flatIndex);
5564 return mlir::success();
5567mlir::LogicalResult CIRToLLVMMatrixInsertOpLowering::matchAndRewrite(
5568 cir::MatrixInsertOp op, OpAdaptor adaptor,
5569 mlir::ConversionPatternRewriter &rewriter)
const {
5570 mlir::Value flatIndex =
5571 computeMatrixFlatIndex(rewriter, op.getLoc(), op.getMatrix().getType(),
5572 adaptor.getRowIdx(), adaptor.getColumnIdx());
5573 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertElementOp>(
5574 op, adaptor.getMatrix(), adaptor.getValue(), flatIndex);
5575 return mlir::success();
5578mlir::LogicalResult CIRToLLVMMatrixColumnMajorLoadOpLowering::matchAndRewrite(
5579 cir::MatrixColumnMajorLoadOp op, OpAdaptor adaptor,
5580 mlir::ConversionPatternRewriter &rewriter)
const {
5581 cir::MatrixType resultMatrixTy = op.getResult().getType();
5582 mlir::Type resultTy = typeConverter->convertType(resultMatrixTy);
5583 rewriter.replaceOpWithNewOp<mlir::LLVM::MatrixColumnMajorLoadOp>(
5584 op, resultTy, adaptor.getValue(), adaptor.getStride(),
5585 rewriter.getBoolAttr(op.getIsVolatile()),
5586 rewriter.getI32IntegerAttr(resultMatrixTy.getNumRows()),
5587 rewriter.getI32IntegerAttr(resultMatrixTy.getNumColumns()));
5588 return mlir::success();
5591mlir::LogicalResult CIRToLLVMMatrixColumnMajorStoreOpLowering::matchAndRewrite(
5592 cir::MatrixColumnMajorStoreOp op, OpAdaptor adaptor,
5593 mlir::ConversionPatternRewriter &rewriter)
const {
5594 cir::MatrixType matrixTy = op.getMatrix().getType();
5595 rewriter.replaceOpWithNewOp<mlir::LLVM::MatrixColumnMajorStoreOp>(
5596 op, adaptor.getMatrix(), adaptor.getValue(), adaptor.getStride(),
5597 rewriter.getBoolAttr(op.getIsVolatile()),
5598 rewriter.getI32IntegerAttr(matrixTy.getNumRows()),
5599 rewriter.getI32IntegerAttr(matrixTy.getNumColumns()));
5600 return mlir::success();
5603mlir::LogicalResult CIRToLLVMMatrixMultiplyOpLowering::matchAndRewrite(
5604 cir::MatrixMultiplyOp op, OpAdaptor adaptor,
5605 mlir::ConversionPatternRewriter &rewriter)
const {
5606 cir::MatrixType lhsTy = op.getLhs().getType();
5607 cir::MatrixType rhsTy = op.getRhs().getType();
5608 mlir::Type resultTy = typeConverter->convertType(op.getResult().getType());
5609 rewriter.replaceOpWithNewOp<mlir::LLVM::MatrixMultiplyOp>(
5610 op, resultTy, adaptor.getLhs(), adaptor.getRhs(), lhsTy.getNumRows(),
5611 lhsTy.getNumColumns(), rhsTy.getNumColumns());
5612 return mlir::success();
5615mlir::LogicalResult CIRToLLVMMatrixTransposeOpLowering::matchAndRewrite(
5616 cir::MatrixTransposeOp op, OpAdaptor adaptor,
5617 mlir::ConversionPatternRewriter &rewriter)
const {
5618 cir::MatrixType resultMatrixTy = op.getValue().getType();
5619 mlir::Type resultTy = typeConverter->convertType(resultMatrixTy);
5620 rewriter.replaceOpWithNewOp<mlir::LLVM::MatrixTransposeOp>(
5621 op, resultTy, adaptor.getValue(), resultMatrixTy.getNumRows(),
5622 resultMatrixTy.getNumColumns());
5623 return mlir::success();
5626mlir::LogicalResult CIRToLLVMComplexCreateOpLowering::matchAndRewrite(
5627 cir::ComplexCreateOp op, OpAdaptor adaptor,
5628 mlir::ConversionPatternRewriter &rewriter)
const {
5629 mlir::Type complexLLVMTy =
5630 getTypeConverter()->convertType(op.getResult().getType());
5631 auto initialComplex =
5632 mlir::LLVM::UndefOp::create(rewriter, op->getLoc(), complexLLVMTy);
5634 auto realComplex = mlir::LLVM::InsertValueOp::create(
5635 rewriter, op->getLoc(), initialComplex, adaptor.getReal(),
5638 auto complex = mlir::LLVM::InsertValueOp::create(
5639 rewriter, op->getLoc(), realComplex, adaptor.getImag(),
5642 rewriter.replaceOp(op, complex);
5643 return mlir::success();
5646mlir::LogicalResult CIRToLLVMComplexRealOpLowering::matchAndRewrite(
5647 cir::ComplexRealOp op, OpAdaptor adaptor,
5648 mlir::ConversionPatternRewriter &rewriter)
const {
5649 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
5650 mlir::Value operand = adaptor.getOperand();
5651 if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) {
5652 operand = mlir::LLVM::ExtractValueOp::create(
5653 rewriter, op.getLoc(), resultLLVMTy, operand,
5656 rewriter.replaceOp(op, operand);
5657 return mlir::success();
5660mlir::LogicalResult CIRToLLVMComplexImagOpLowering::matchAndRewrite(
5661 cir::ComplexImagOp op, OpAdaptor adaptor,
5662 mlir::ConversionPatternRewriter &rewriter)
const {
5663 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
5664 mlir::Value operand = adaptor.getOperand();
5665 mlir::Location loc = op.getLoc();
5667 if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) {
5668 operand = mlir::LLVM::ExtractValueOp::create(
5671 mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(resultLLVMTy);
5673 mlir::LLVM::ConstantOp::create(rewriter, loc, resultLLVMTy, zeroAttr);
5676 rewriter.replaceOp(op, operand);
5677 return mlir::success();
5680mlir::LogicalResult CIRToLLVMComplexAddOpLowering::matchAndRewrite(
5681 cir::ComplexAddOp op, OpAdaptor adaptor,
5682 mlir::ConversionPatternRewriter &rewriter)
const {
5683 mlir::Value lhs = adaptor.getLhs();
5684 mlir::Value rhs = adaptor.getRhs();
5685 mlir::Location loc = op.getLoc();
5687 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
5688 mlir::Type complexElemTy =
5689 getTypeConverter()->convertType(
complexType.getElementType());
5690 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
5691 rewriter, loc, complexElemTy, lhs,
ArrayRef(int64_t{0}));
5692 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
5693 rewriter, loc, complexElemTy, lhs,
ArrayRef(int64_t{1}));
5694 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
5695 rewriter, loc, complexElemTy, rhs,
ArrayRef(int64_t{0}));
5696 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
5697 rewriter, loc, complexElemTy, rhs,
ArrayRef(int64_t{1}));
5699 mlir::Value newReal;
5700 mlir::Value newImag;
5701 if (complexElemTy.isInteger()) {
5702 newReal = mlir::LLVM::AddOp::create(rewriter, loc, complexElemTy, lhsReal,
5704 newImag = mlir::LLVM::AddOp::create(rewriter, loc, complexElemTy, lhsImag,
5709 newReal = mlir::LLVM::FAddOp::create(rewriter, loc, complexElemTy, lhsReal,
5711 newImag = mlir::LLVM::FAddOp::create(rewriter, loc, complexElemTy, lhsImag,
5715 mlir::Type complexLLVMTy =
5716 getTypeConverter()->convertType(op.getResult().getType());
5717 auto initialComplex =
5718 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), complexLLVMTy);
5720 auto realComplex = mlir::LLVM::InsertValueOp::create(
5721 rewriter, op->getLoc(), initialComplex, newReal,
ArrayRef(int64_t{0}));
5723 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
5724 op, realComplex, newImag,
ArrayRef(int64_t{1}));
5726 return mlir::success();
5729mlir::LogicalResult CIRToLLVMComplexSubOpLowering::matchAndRewrite(
5730 cir::ComplexSubOp op, OpAdaptor adaptor,
5731 mlir::ConversionPatternRewriter &rewriter)
const {
5732 mlir::Value lhs = adaptor.getLhs();
5733 mlir::Value rhs = adaptor.getRhs();
5734 mlir::Location loc = op.getLoc();
5736 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
5737 mlir::Type complexElemTy =
5738 getTypeConverter()->convertType(
complexType.getElementType());
5739 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
5740 rewriter, loc, complexElemTy, lhs,
ArrayRef(int64_t{0}));
5741 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
5742 rewriter, loc, complexElemTy, lhs,
ArrayRef(int64_t{1}));
5743 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
5744 rewriter, loc, complexElemTy, rhs,
ArrayRef(int64_t{0}));
5745 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
5746 rewriter, loc, complexElemTy, rhs,
ArrayRef(int64_t{1}));
5748 mlir::Value newReal;
5749 mlir::Value newImag;
5750 if (complexElemTy.isInteger()) {
5751 newReal = mlir::LLVM::SubOp::create(rewriter, loc, complexElemTy, lhsReal,
5753 newImag = mlir::LLVM::SubOp::create(rewriter, loc, complexElemTy, lhsImag,
5758 newReal = mlir::LLVM::FSubOp::create(rewriter, loc, complexElemTy, lhsReal,
5760 newImag = mlir::LLVM::FSubOp::create(rewriter, loc, complexElemTy, lhsImag,
5764 mlir::Type complexLLVMTy =
5765 getTypeConverter()->convertType(op.getResult().getType());
5766 auto initialComplex =
5767 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), complexLLVMTy);
5769 auto realComplex = mlir::LLVM::InsertValueOp::create(
5770 rewriter, op->getLoc(), initialComplex, newReal,
ArrayRef(int64_t{0}));
5772 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
5773 op, realComplex, newImag,
ArrayRef(int64_t{1}));
5775 return mlir::success();
5778mlir::LogicalResult CIRToLLVMComplexFAddOpLowering::matchAndRewrite(
5779 cir::ComplexFAddOp op, OpAdaptor adaptor,
5780 mlir::ConversionPatternRewriter &rewriter)
const {
5781 mlir::Value lhs = adaptor.getLhs();
5782 mlir::Value rhs = adaptor.getRhs();
5783 mlir::Location loc = op.getLoc();
5785 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
5786 mlir::Type complexElemTy =
5787 getTypeConverter()->convertType(
complexType.getElementType());
5788 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
5789 rewriter, loc, complexElemTy, lhs,
ArrayRef(int64_t{0}));
5790 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
5791 rewriter, loc, complexElemTy, lhs,
ArrayRef(int64_t{1}));
5792 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
5793 rewriter, loc, complexElemTy, rhs,
ArrayRef(int64_t{0}));
5794 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
5795 rewriter, loc, complexElemTy, rhs,
ArrayRef(int64_t{1}));
5798 mlir::Value newReal;
5799 mlir::Value newImag;
5800 if (cir::FenvAttr fenv = op.getFenvAttr()) {
5802 rewriter, loc, {lhsReal, rhsReal}, complexElemTy, fenv,
5807 rewriter, loc, {lhsImag, rhsImag}, complexElemTy, fenv,
5811 newReal = mlir::LLVM::FAddOp::create(rewriter, loc, complexElemTy, lhsReal,
5813 newImag = mlir::LLVM::FAddOp::create(rewriter, loc, complexElemTy, lhsImag,
5817 mlir::Type complexLLVMTy =
5818 getTypeConverter()->convertType(op.getResult().getType());
5819 auto initialComplex =
5820 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), complexLLVMTy);
5822 auto realComplex = mlir::LLVM::InsertValueOp::create(
5823 rewriter, op->getLoc(), initialComplex, newReal,
ArrayRef(int64_t{0}));
5825 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
5826 op, realComplex, newImag,
ArrayRef(int64_t{1}));
5828 return mlir::success();
5831mlir::LogicalResult CIRToLLVMComplexFSubOpLowering::matchAndRewrite(
5832 cir::ComplexFSubOp op, OpAdaptor adaptor,
5833 mlir::ConversionPatternRewriter &rewriter)
const {
5834 mlir::Value lhs = adaptor.getLhs();
5835 mlir::Value rhs = adaptor.getRhs();
5836 mlir::Location loc = op.getLoc();
5838 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
5839 mlir::Type complexElemTy =
5840 getTypeConverter()->convertType(
complexType.getElementType());
5841 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
5842 rewriter, loc, complexElemTy, lhs,
ArrayRef(int64_t{0}));
5843 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
5844 rewriter, loc, complexElemTy, lhs,
ArrayRef(int64_t{1}));
5845 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
5846 rewriter, loc, complexElemTy, rhs,
ArrayRef(int64_t{0}));
5847 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
5848 rewriter, loc, complexElemTy, rhs,
ArrayRef(int64_t{1}));
5851 mlir::Value newReal;
5852 mlir::Value newImag;
5853 if (cir::FenvAttr fenv = op.getFenvAttr()) {
5855 rewriter, loc, {lhsReal, rhsReal}, complexElemTy, fenv,
5860 rewriter, loc, {lhsImag, rhsImag}, complexElemTy, fenv,
5864 newReal = mlir::LLVM::FSubOp::create(rewriter, loc, complexElemTy, lhsReal,
5866 newImag = mlir::LLVM::FSubOp::create(rewriter, loc, complexElemTy, lhsImag,
5870 mlir::Type complexLLVMTy =
5871 getTypeConverter()->convertType(op.getResult().getType());
5872 auto initialComplex =
5873 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), complexLLVMTy);
5875 auto realComplex = mlir::LLVM::InsertValueOp::create(
5876 rewriter, op->getLoc(), initialComplex, newReal,
ArrayRef(int64_t{0}));
5878 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
5879 op, realComplex, newImag,
ArrayRef(int64_t{1}));
5881 return mlir::success();
5885 mlir::MLIRContext *context,
5886 unsigned &storageSize) {
5887 return TypeSwitch<mlir::Type, mlir::IntegerType>(storageType)
5888 .Case<cir::ArrayType>([&](cir::ArrayType atTy) {
5889 storageSize = atTy.getSize() * 8;
5890 return mlir::IntegerType::get(context, storageSize);
5892 .Case<cir::IntType>([&](cir::IntType intTy) {
5893 storageSize = intTy.getWidth();
5894 return mlir::IntegerType::get(context, storageSize);
5896 .Default([](mlir::Type) -> mlir::IntegerType {
5898 "Either ArrayType or IntType expected for bitfields storage");
5902mlir::LogicalResult CIRToLLVMSetBitfieldOpLowering::matchAndRewrite(
5903 cir::SetBitfieldOp op, OpAdaptor adaptor,
5904 mlir::ConversionPatternRewriter &rewriter)
const {
5905 mlir::OpBuilder::InsertionGuard guard(rewriter);
5906 rewriter.setInsertionPoint(op);
5908 cir::BitfieldInfoAttr info = op.getBitfieldInfo();
5909 uint64_t size = info.getSize();
5910 uint64_t offset = info.getOffset();
5911 mlir::Type storageType = info.getStorageType();
5912 mlir::MLIRContext *context = storageType.getContext();
5914 unsigned storageSize = 0;
5916 mlir::IntegerType intType =
5917 computeBitfieldIntType(storageType, context, storageSize);
5919 mlir::Value srcVal = createIntCast(rewriter, adaptor.getSrc(), intType);
5920 unsigned srcWidth = storageSize;
5921 mlir::Value resultVal = srcVal;
5923 if (storageSize != size) {
5924 assert(storageSize > size &&
"Invalid bitfield size.");
5926 mlir::Value val = mlir::LLVM::LoadOp::create(
5927 rewriter, op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(),
5928 op.getIsVolatile());
5931 createAnd(rewriter, srcVal, llvm::APInt::getLowBitsSet(srcWidth, size));
5933 srcVal =
createShL(rewriter, srcVal, offset);
5937 ~llvm::APInt::getBitsSet(srcWidth, offset, offset + size));
5940 srcVal = mlir::LLVM::OrOp::create(rewriter, op.getLoc(), val, srcVal);
5943 mlir::LLVM::StoreOp::create(rewriter, op.getLoc(), srcVal, adaptor.getAddr(),
5944 op.getAlignment(), op.getIsVolatile());
5946 mlir::Type resultTy = getTypeConverter()->convertType(op.getType());
5948 if (info.getIsSigned()) {
5949 assert(size <= storageSize);
5950 unsigned highBits = storageSize - size;
5953 resultVal =
createShL(rewriter, resultVal, highBits);
5954 resultVal =
createAShR(rewriter, resultVal, highBits);
5959 mlir::cast<mlir::IntegerType>(resultTy),
5960 info.getIsSigned());
5962 rewriter.replaceOp(op, resultVal);
5963 return mlir::success();
5966mlir::LogicalResult CIRToLLVMComplexImagPtrOpLowering::matchAndRewrite(
5967 cir::ComplexImagPtrOp op, OpAdaptor adaptor,
5968 mlir::ConversionPatternRewriter &rewriter)
const {
5969 cir::PointerType operandTy = op.getOperand().getType();
5970 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
5971 mlir::Type elementLLVMTy =
5972 getTypeConverter()->convertType(operandTy.getPointee());
5974 mlir::LLVM::GEPArg gepIndices[2] = {{0}, {1}};
5975 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
5976 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
5977 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
5978 op, resultLLVMTy, elementLLVMTy, adaptor.getOperand(), gepIndices,
5980 return mlir::success();
5983mlir::LogicalResult CIRToLLVMComplexRealPtrOpLowering::matchAndRewrite(
5984 cir::ComplexRealPtrOp op, OpAdaptor adaptor,
5985 mlir::ConversionPatternRewriter &rewriter)
const {
5986 cir::PointerType operandTy = op.getOperand().getType();
5987 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
5988 mlir::Type elementLLVMTy =
5989 getTypeConverter()->convertType(operandTy.getPointee());
5991 mlir::LLVM::GEPArg gepIndices[2] = {0, 0};
5992 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
5993 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
5994 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
5995 op, resultLLVMTy, elementLLVMTy, adaptor.getOperand(), gepIndices,
5997 return mlir::success();
6000mlir::LogicalResult CIRToLLVMGetBitfieldOpLowering::matchAndRewrite(
6001 cir::GetBitfieldOp op, OpAdaptor adaptor,
6002 mlir::ConversionPatternRewriter &rewriter)
const {
6004 mlir::OpBuilder::InsertionGuard guard(rewriter);
6005 rewriter.setInsertionPoint(op);
6007 cir::BitfieldInfoAttr
info = op.getBitfieldInfo();
6008 uint64_t size =
info.getSize();
6009 uint64_t offset =
info.getOffset();
6010 mlir::Type storageType =
info.getStorageType();
6011 mlir::MLIRContext *context = storageType.getContext();
6012 unsigned storageSize = 0;
6014 mlir::IntegerType intType =
6017 mlir::Value val = mlir::LLVM::LoadOp::create(
6018 rewriter, op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(),
6019 op.getIsVolatile());
6020 val = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), intType, val);
6022 if (
info.getIsSigned()) {
6023 assert(
static_cast<unsigned>(offset + size) <= storageSize);
6024 unsigned highBits = storageSize - offset - size;
6025 val =
createShL(rewriter, val, highBits);
6026 val =
createAShR(rewriter, val, offset + highBits);
6030 if (
static_cast<unsigned>(offset) + size < storageSize)
6032 llvm::APInt::getLowBitsSet(storageSize, size));
6035 mlir::Type resTy = getTypeConverter()->convertType(op.getType());
6037 rewriter, val, mlir::cast<mlir::IntegerType>(resTy),
info.getIsSigned());
6038 rewriter.replaceOp(op, newOp);
6039 return mlir::success();
6042mlir::LogicalResult CIRToLLVMInlineAsmOpLowering::matchAndRewrite(
6043 cir::InlineAsmOp op, OpAdaptor adaptor,
6044 mlir::ConversionPatternRewriter &rewriter)
const {
6046 if (op.getNumResults())
6047 llResTy = getTypeConverter()->convertType(op.getType(0));
6049 cir::AsmFlavor dialect = op.getAsmFlavor();
6050 mlir::LLVM::AsmDialect llDialect = dialect == cir::AsmFlavor::x86_att
6051 ? mlir::LLVM::AsmDialect::AD_ATT
6052 : mlir::LLVM::AsmDialect::AD_Intel;
6055 StringRef llvmAttrName = mlir::LLVM::InlineAsmOp::getElementTypeAttrName();
6061 if (!op.getNumResults())
6062 opAttrs.push_back(mlir::Attribute());
6066 for (
auto const &[llvmOp, cirOp] :
6067 zip(adaptor.getAsmOperands(), op.getAsmOperands())) {
6068 append_range(llvmOperands, llvmOp);
6069 append_range(cirOperands, cirOp);
6074 for (
auto const &[cirOpAttr, cirOp] :
6075 zip(op.getOperandAttrs(), cirOperands)) {
6076 if (!mlir::isa<mlir::UnitAttr>(cirOpAttr)) {
6077 opAttrs.push_back(mlir::Attribute());
6082 cir::PointerType typ = mlir::cast<cir::PointerType>(cirOp.getType());
6084 *getTypeConverter(), dataLayout, typ.getPointee()));
6086 attrs.push_back(rewriter.getNamedAttr(llvmAttrName, typAttr));
6087 mlir::DictionaryAttr newDict = rewriter.getDictionaryAttr(attrs);
6088 opAttrs.push_back(newDict);
6091 rewriter.replaceOpWithNewOp<mlir::LLVM::InlineAsmOp>(
6092 op, llResTy, llvmOperands, op.getAsmStringAttr(), op.getConstraintsAttr(),
6093 op.getSideEffectsAttr(),
6096 mlir::LLVM::TailCallKindAttr::get(
6097 getContext(), mlir::LLVM::tailcallkind::TailCallKind::None),
6099 mlir::LLVM::AsmDialectAttr::get(getContext(), llDialect),
6100 rewriter.getArrayAttr(opAttrs));
6102 return mlir::success();
6105mlir::LogicalResult CIRToLLVMVAStartOpLowering::matchAndRewrite(
6106 cir::VAStartOp op, OpAdaptor adaptor,
6107 mlir::ConversionPatternRewriter &rewriter)
const {
6108 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
6109 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
6110 adaptor.getArgList());
6111 rewriter.replaceOpWithNewOp<mlir::LLVM::VaStartOp>(op, vaList);
6112 return mlir::success();
6115mlir::LogicalResult CIRToLLVMVAEndOpLowering::matchAndRewrite(
6116 cir::VAEndOp op, OpAdaptor adaptor,
6117 mlir::ConversionPatternRewriter &rewriter)
const {
6118 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
6119 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
6120 adaptor.getArgList());
6121 rewriter.replaceOpWithNewOp<mlir::LLVM::VaEndOp>(op, vaList);
6122 return mlir::success();
6125mlir::LogicalResult CIRToLLVMVACopyOpLowering::matchAndRewrite(
6126 cir::VACopyOp op, OpAdaptor adaptor,
6127 mlir::ConversionPatternRewriter &rewriter)
const {
6128 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
6129 auto dstList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
6130 adaptor.getDstList());
6131 auto srcList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
6132 adaptor.getSrcList());
6133 rewriter.replaceOpWithNewOp<mlir::LLVM::VaCopyOp>(op, dstList, srcList);
6134 return mlir::success();
6137mlir::LogicalResult CIRToLLVMVAArgOpLowering::matchAndRewrite(
6138 cir::VAArgOp op, OpAdaptor adaptor,
6139 mlir::ConversionPatternRewriter &rewriter)
const {
6141 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
6142 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
6143 adaptor.getArgList());
6145 mlir::Type llvmType =
6146 getTypeConverter()->convertType(op->getResultTypes().front());
6148 return mlir::failure();
6150 rewriter.replaceOpWithNewOp<mlir::LLVM::VaArgOp>(op, llvmType, vaList);
6151 return mlir::success();
6154mlir::LogicalResult CIRToLLVMLabelOpLowering::matchAndRewrite(
6155 cir::LabelOp op, OpAdaptor adaptor,
6156 mlir::ConversionPatternRewriter &rewriter)
const {
6157 mlir::MLIRContext *ctx = rewriter.getContext();
6158 mlir::Block *block = op->getBlock();
6161 if (block->isEntryBlock()) {
6162 mlir::Block *newBlock =
6163 rewriter.splitBlock(op->getBlock(), mlir::Block::iterator(op));
6164 rewriter.setInsertionPointToEnd(block);
6165 mlir::LLVM::BrOp::create(rewriter, op.getLoc(), newBlock);
6168 mlir::LLVM::BlockTagAttr::get(ctx, blockInfoAddr.getTagIndex());
6169 rewriter.setInsertionPoint(op);
6172 mlir::LLVM::BlockTagOp::create(rewriter, op->getLoc(), tagAttr);
6173 mlir::LLVM::LLVMFuncOp func = op->getParentOfType<mlir::LLVM::LLVMFuncOp>();
6174 auto blockInfoAttr =
6175 cir::BlockAddrInfoAttr::get(ctx, func.getSymName(), op.getLabel());
6176 blockInfoAddr.mapBlockTag(blockInfoAttr, blockTagOp);
6177 rewriter.eraseOp(op);
6179 return mlir::success();
6182mlir::LogicalResult CIRToLLVMBlockAddressOpLowering::matchAndRewrite(
6183 cir::BlockAddressOp op, OpAdaptor adaptor,
6184 mlir::ConversionPatternRewriter &rewriter)
const {
6185 mlir::MLIRContext *ctx = rewriter.getContext();
6187 mlir::LLVM::BlockTagOp matchLabel =
6188 blockInfoAddr.lookupBlockTag(op.getBlockAddrInfoAttr());
6189 mlir::LLVM::BlockTagAttr tagAttr;
6196 tagAttr = matchLabel.getTag();
6198 auto blkAddr = mlir::LLVM::BlockAddressAttr::get(
6199 rewriter.getContext(), op.getBlockAddrInfoAttr().getFunc(), tagAttr);
6200 rewriter.setInsertionPoint(op);
6201 auto newOp = mlir::LLVM::BlockAddressOp::create(
6202 rewriter, op.getLoc(), mlir::LLVM::LLVMPointerType::get(ctx), blkAddr);
6204 blockInfoAddr.addUnresolvedBlockAddress(newOp, op.getBlockAddrInfoAttr());
6205 rewriter.replaceOp(op, newOp);
6206 return mlir::success();
6209mlir::LogicalResult CIRToLLVMIndirectBrOpLowering::matchAndRewrite(
6210 cir::IndirectBrOp op, OpAdaptor adaptor,
6211 mlir::ConversionPatternRewriter &rewriter)
const {
6213 mlir::Value targetAddr = adaptor.getAddr();
6221 if (op.getPoison()) {
6222 auto llvmPtrType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
6224 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), llvmPtrType);
6227 rewriter.replaceOpWithNewOp<mlir::LLVM::IndirectBrOp>(
6228 op, targetAddr, adaptor.getSuccOperands(), op.getSuccessors());
6229 return mlir::success();
6232mlir::LogicalResult CIRToLLVMTokenNoneOpLowering::matchAndRewrite(
6233 cir::TokenNoneOp op, OpAdaptor adaptor,
6234 mlir::ConversionPatternRewriter &rewriter)
const {
6235 rewriter.replaceOpWithNewOp<mlir::LLVM::NoneTokenOp>(
6236 op, mlir::TokenType::get(rewriter.getContext()));
6237 return mlir::success();
6240mlir::LogicalResult CIRToLLVMCpuIdOpLowering::matchAndRewrite(
6241 cir::CpuIdOp op, OpAdaptor adaptor,
6242 mlir::ConversionPatternRewriter &rewriter)
const {
6243 mlir::Type i32Ty = rewriter.getI32Type();
6244 mlir::Type i64Ty = rewriter.getI64Type();
6245 mlir::Type i32PtrTy = mlir::LLVM::LLVMPointerType::get(i32Ty.getContext(), 0);
6247 mlir::Type cpuidRetTy = mlir::LLVM::LLVMStructType::getLiteral(
6248 rewriter.getContext(), {i32Ty, i32Ty, i32Ty, i32Ty});
6250 mlir::Value functionId = adaptor.getFunctionId();
6251 mlir::Value subFunctionId = adaptor.getSubFunctionId();
6253 StringRef asmString, constraints;
6254 mlir::ModuleOp moduleOp = op->getParentOfType<mlir::ModuleOp>();
6255 llvm::Triple triple(
6256 mlir::cast<mlir::StringAttr>(
6257 moduleOp->getAttr(cir::CIRDialect::getTripleAttrName()))
6259 if (triple.getArch() == llvm::Triple::x86) {
6260 asmString =
"cpuid";
6261 constraints =
"={ax},={bx},={cx},={dx},{ax},{cx}";
6264 asmString =
"xchgq %rbx, ${1:q}\n"
6266 "xchgq %rbx, ${1:q}";
6267 constraints =
"={ax},=r,={cx},={dx},0,2";
6270 mlir::Value inlineAsm =
6271 mlir::LLVM::InlineAsmOp::create(
6272 rewriter, op.getLoc(), cpuidRetTy, {functionId, subFunctionId},
6273 rewriter.getStringAttr(asmString),
6274 rewriter.getStringAttr(constraints),
6277 mlir::LLVM::TailCallKindAttr{},
6279 mlir::LLVM::AsmDialectAttr{},
6283 mlir::Value basePtr = adaptor.getCpuInfo();
6285 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
6286 unsigned alignment = layout.getTypeABIAlignment(i32Ty);
6287 for (
unsigned i = 0; i < 4; i++) {
6288 mlir::Value extracted =
6289 mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(), inlineAsm, i)
6291 mlir::Value index = mlir::LLVM::ConstantOp::create(
6292 rewriter, op.getLoc(), i64Ty, rewriter.getI64IntegerAttr(i));
6294 mlir::Value storePtr = mlir::LLVM::GEPOp::create(
6295 rewriter, op.getLoc(), i32PtrTy, i32Ty, basePtr,
6296 gepIndices, mlir::LLVM::GEPNoWrapFlags::none)
6298 mlir::LLVM::StoreOp::create(rewriter, op.getLoc(), extracted, storePtr,
6302 rewriter.eraseOp(op);
6303 return mlir::success();
6306mlir::LogicalResult CIRToLLVMMemChrOpLowering::matchAndRewrite(
6307 cir::MemChrOp op, OpAdaptor adaptor,
6308 mlir::ConversionPatternRewriter &rewriter)
const {
6309 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
6310 mlir::Type srcTy = getTypeConverter()->convertType(op.getSrc().getType());
6311 mlir::Type patternTy =
6312 getTypeConverter()->convertType(op.getPattern().getType());
6313 mlir::Type lenTy = getTypeConverter()->convertType(op.getLen().getType());
6315 mlir::LLVM::LLVMFunctionType::get(llvmPtrTy, {srcTy, patternTy, lenTy},
6317 llvm::StringRef fnName =
"memchr";
6319 mlir::Builder b(rewriter.getContext());
6320 mlir::NamedAttribute noundefAttr =
6321 b.getNamedAttr(
"llvm.noundef", b.getUnitAttr());
6322 mlir::DictionaryAttr noundefDict = mlir::DictionaryAttr::get(
6325 mlir::ArrayAttr argAttrs =
6326 mlir::ArrayAttr::get(rewriter.getContext(), argAttrVec);
6331 mlir::LLVM::CallOp newCall = rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(
6332 op, mlir::TypeRange{llvmPtrTy}, fnName,
6333 mlir::ValueRange{adaptor.getSrc(), adaptor.getPattern(),
6335 newCall.setArgAttrsAttr(argAttrs);
6336 return mlir::success();
6342 mlir::Location loc, mlir::Value inputPtr,
6343 uint64_t baseAlignment,
6344 cir::OffsetPairAttr paddingAttr) {
6349 uint64_t charWidth = 8;
6350 mlir::Type i8Ty = rewriter.getI8Type();
6351 mlir::Type ptrTy = mlir::LLVM::LLVMPointerType::get(i8Ty.getContext());
6353 auto startByte = paddingAttr.getStart() / charWidth;
6354 auto startBit = paddingAttr.getStart() % charWidth;
6355 auto endByte = paddingAttr.getEnd() / charWidth;
6356 auto endBit = paddingAttr.getEnd() % charWidth;
6358 if (startByte == endByte) {
6360 auto index = mlir::LLVM::ConstantOp::create(
6361 rewriter, loc, rewriter.getI32Type(), startByte);
6362 auto element = mlir::LLVM::GEPOp::create(rewriter, loc, ptrTy, i8Ty,
6365 uint64_t adjustedAlignment = llvm::MinAlign(baseAlignment, startByte);
6367 auto value = mlir::LLVM::LoadOp::create(rewriter, loc, i8Ty, element,
6372 uint8_t bitsToClear = ((1 << endBit) - 1) & ~((1 << startBit) - 1);
6373 uint8_t bitsToKeep = ~bitsToClear;
6375 mlir::LLVM::ConstantOp::create(rewriter, loc, i8Ty, bitsToKeep);
6376 auto newValue = mlir::LLVM::AndOp::create(rewriter, loc, value, maskValue);
6378 mlir::LLVM::StoreOp::create(rewriter, loc, newValue, element,
6382 if (startBit != 0) {
6383 auto index = mlir::LLVM::ConstantOp::create(
6384 rewriter, loc, rewriter.getI32Type(), startByte);
6385 auto element = mlir::LLVM::GEPOp::create(rewriter, loc, ptrTy, i8Ty,
6387 uint64_t adjustedAlignment = llvm::MinAlign(baseAlignment, startByte);
6389 auto value = mlir::LLVM::LoadOp::create(rewriter, loc, i8Ty, element,
6392 uint8_t bitsToClear = ((1 << (charWidth - startBit)) - 1) << startBit;
6393 uint8_t bitsToKeep = ~bitsToClear;
6395 mlir::LLVM::ConstantOp::create(rewriter, loc, i8Ty, bitsToKeep);
6397 mlir::LLVM::AndOp::create(rewriter, loc, value, maskValue);
6399 mlir::LLVM::StoreOp::create(rewriter, loc, newValue, element,
6405 for (
auto offset = startByte; offset < endByte; ++offset) {
6406 auto index = mlir::LLVM::ConstantOp::create(
6407 rewriter, loc, rewriter.getI32Type(), offset);
6408 auto element = mlir::LLVM::GEPOp::create(rewriter, loc, ptrTy, i8Ty,
6410 uint64_t adjustedAlignment = llvm::MinAlign(baseAlignment, offset);
6412 auto zero = mlir::LLVM::ConstantOp::create(rewriter, loc, i8Ty, 0);
6413 mlir::LLVM::StoreOp::create(rewriter, loc, zero, element,
6419 auto index = mlir::LLVM::ConstantOp::create(
6420 rewriter, loc, rewriter.getI32Type(), endByte);
6421 auto element = mlir::LLVM::GEPOp::create(rewriter, loc, ptrTy, i8Ty,
6423 uint64_t adjustedAlignment = llvm::MinAlign(baseAlignment, endByte);
6425 auto value = mlir::LLVM::LoadOp::create(rewriter, loc, i8Ty, element,
6428 uint8_t bitsToClear = (1 << endBit) - 1;
6429 uint8_t bitsToKeep = ~bitsToClear;
6431 mlir::LLVM::ConstantOp::create(rewriter, loc, i8Ty, bitsToKeep);
6433 mlir::LLVM::AndOp::create(rewriter, loc, value, maskValue);
6435 mlir::LLVM::StoreOp::create(rewriter, loc, newValue, element,
6441mlir::LogicalResult CIRToLLVMClearPaddingOpLowering::matchAndRewrite(
6442 cir::ClearPaddingOp op, OpAdaptor adaptor,
6443 mlir::ConversionPatternRewriter &rewriter)
const {
6445 mlir::Value inputPtr = adaptor.getArg();
6446 for (mlir::Attribute attr : op.getPadding())
6447 clearPadding(rewriter, op.getLoc(), inputPtr, op.getAlignment(),
6448 cast<cir::OffsetPairAttr>(attr));
6450 rewriter.eraseOp(op);
6451 return mlir::success();
6455 return std::make_unique<ConvertCIRToLLVMPass>();
6461 pm.addPass(mlir::omp::createMarkDeclareTargetPass());
6464 pm.addPass(mlir::omp::createHostOpFilteringPass());
6465 pm.nest<mlir::LLVM::LLVMFuncOp>().addPass(
6466 mlir::omp::createStackToSharedPass());
6470std::unique_ptr<llvm::Module>
6472 bool enableOpenMP, StringRef mlirSaveTempsOutFile,
6473 llvm::vfs::FileSystem *fs) {
6474 llvm::TimeTraceScope scope(
"lower from CIR to LLVM directly");
6476 mlir::MLIRContext *mlirCtx = mlirModule.getContext();
6478 mlir::PassManager pm(mlirCtx);
6481 (void)mlir::applyPassManagerCLOptions(pm);
6485 if (mlir::failed(pm.run(mlirModule)))
6488 if (!mlirSaveTempsOutFile.empty()) {
6490 llvm::raw_fd_ostream out(mlirSaveTempsOutFile, ec);
6492 mlirModule->print(out);
6495 mlir::registerBuiltinDialectTranslation(*mlirCtx);
6496 mlir::registerLLVMDialectTranslation(*mlirCtx);
6497 mlir::registerOpenMPDialectTranslation(*mlirCtx);
6500 llvm::TimeTraceScope translateScope(
"translateModuleToLLVMIR");
6502 StringRef moduleName = mlirModule.getName().value_or(
"CIRToLLVMModule");
6503 std::unique_ptr<llvm::Module> llvmModule = mlir::translateModuleToLLVMIR(
6504 mlirModule, llvmCtx, moduleName,
false, fs);
static bool isUnsigned(SValBuilder &SVB, NonLoc Value)
#define CHECK_ENUM(CIR, LLVM_VAL)
mlir::Type convertTypeForMemory(const mlir::TypeConverter &converter, mlir::DataLayout const &dataLayout, mlir::Type type)
mlir::Value createLShR(mlir::OpBuilder &bld, mlir::Value lhs, unsigned rhs)
mlir::Value createShL(mlir::OpBuilder &bld, mlir::Value lhs, unsigned rhs)
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 ...
std::optional< mlir::Attribute > lowerConstRecordAttr(cir::ConstRecordAttr constRecord, mlir::SymbolTableCollection &symbolTables, const mlir::TypeConverter *converter, mlir::ModuleOp moduleOp={})
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...
mlir::Attribute getBitIntStorageAttr(mlir::ConversionPatternRewriter &rewriter, cir::IntAttr attr, const mlir::DataLayout &dataLayout)
std::optional< mlir::Attribute > lowerConstArrayAttr(cir::ConstArrayAttr constArr, mlir::SymbolTableCollection &symbolTables, const mlir::TypeConverter *converter, mlir::ModuleOp moduleOp={})
*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)
C++ view class that accepts both !cir.struct and !cir.union types.
CIRAttrToValue(mlir::Operation *parentOp, mlir::ConversionPatternRewriter &rewriter, mlir::SymbolTableCollection &symbolTables, const mlir::TypeConverter *converter, 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 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 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 llvm::StringRef getConstrainedExceptMetadata(cir::FenvAttr fenv)
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::Value getValueForVTableSymbol(mlir::Operation *op, mlir::ConversionPatternRewriter &rewriter, mlir::SymbolTableCollection &symbolTables, const mlir::TypeConverter *converter, mlir::FlatSymbolRefAttr nameAttr, mlir::Type &eltType)
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)
mlir::Value lowerCirAttrAsValue(mlir::Operation *parentOp, const mlir::Attribute attr, mlir::ConversionPatternRewriter &rewriter, mlir::SymbolTableCollection &symbolTables, const mlir::TypeConverter *converter, LLVMBlockAddressInfo *blockInfoAddr)
Switches on the type of attribute and calls the appropriate conversion.
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 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
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