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/LLVMDialect.h"
24#include "mlir/Dialect/LLVMIR/LLVMTypes.h"
25#include "mlir/Dialect/OpenMP/OpenMPDialect.h"
26#include "mlir/Dialect/OpenMP/Transforms/Passes.h"
27#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
28#include "mlir/IR/BuiltinAttributes.h"
29#include "mlir/IR/BuiltinDialect.h"
30#include "mlir/IR/BuiltinOps.h"
31#include "mlir/IR/Location.h"
32#include "mlir/IR/Types.h"
33#include "mlir/Pass/Pass.h"
34#include "mlir/Pass/PassManager.h"
35#include "mlir/Support/LLVM.h"
36#include "mlir/Target/LLVMIR/Dialect/Builtin/BuiltinToLLVMIRTranslation.h"
37#include "mlir/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.h"
38#include "mlir/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.h"
39#include "mlir/Target/LLVMIR/Export.h"
40#include "mlir/Transforms/DialectConversion.h"
49#include "llvm/ADT/MapVector.h"
50#include "llvm/ADT/StringMap.h"
51#include "llvm/ADT/TypeSwitch.h"
52#include "llvm/IR/Module.h"
53#include "llvm/Support/Casting.h"
54#include "llvm/Support/ErrorHandling.h"
55#include "llvm/Support/TimeProfiler.h"
56#include "llvm/Support/VirtualFileSystem.h"
57#include "llvm/Support/raw_ostream.h"
72mlir::Type elementTypeIfVector(mlir::Type type) {
73 return llvm::TypeSwitch<mlir::Type, mlir::Type>(type)
74 .Case<cir::VectorType, mlir::VectorType>(
75 [](
auto p) {
return p.getElementType(); })
76 .
Default([](mlir::Type p) {
return p; });
84 mlir::Type llvmMemType,
85 const mlir::DataLayout &dataLayout) {
86 if (
auto intTy = mlir::dyn_cast<cir::IntType>(cirType);
87 intTy && intTy.isBitInt())
88 return intTy.getABIAlignment(dataLayout, {});
89 return dataLayout.getTypeABIAlignment(llvmMemType);
93 mlir::IntegerType dstTy,
94 bool isSigned =
false) {
95 mlir::Type srcTy = src.getType();
96 assert(mlir::isa<mlir::IntegerType>(srcTy));
98 unsigned srcWidth = mlir::cast<mlir::IntegerType>(srcTy).getWidth();
99 unsigned dstWidth = mlir::cast<mlir::IntegerType>(dstTy).getWidth();
100 mlir::Location loc = src.getLoc();
102 if (dstWidth > srcWidth && isSigned)
103 return mlir::LLVM::SExtOp::create(bld, loc, dstTy, src);
104 if (dstWidth > srcWidth)
105 return mlir::LLVM::ZExtOp::create(bld, loc, dstTy, src);
106 if (dstWidth < srcWidth)
107 return mlir::LLVM::TruncOp::create(bld, loc, dstTy, src);
108 return mlir::LLVM::BitcastOp::create(bld, loc, dstTy, src);
118 const mlir::DataLayout &dataLayout, cir::IntType intTy,
119 mlir::Value value,
bool toMemory) {
120 unsigned storageBits = intTy.getStorageTypeWidth(dataLayout);
121 if (storageBits == intTy.getWidth())
123 unsigned dstBits = toMemory ? storageBits : intTy.getWidth();
124 return createIntCast(rewriter, value, rewriter.getIntegerType(dstBits),
125 toMemory && intTy.isSigned());
128static mlir::LLVM::Visibility
130 switch (visibilityKind) {
131 case cir::VisibilityKind::Default:
132 return ::mlir::LLVM::Visibility::Default;
133 case cir::VisibilityKind::Hidden:
134 return ::mlir::LLVM::Visibility::Hidden;
135 case cir::VisibilityKind::Protected:
136 return ::mlir::LLVM::Visibility::Protected;
142 mlir::Value srcVec,
unsigned numElementsDst) {
143 auto srcTy = mlir::cast<mlir::VectorType>(srcVec.getType());
144 unsigned numElementsSrc = srcTy.getNumElements();
145 if (numElementsSrc == numElementsDst)
149 for (
unsigned i : llvm::seq(std::min(numElementsDst, numElementsSrc)))
152 mlir::Location loc = srcVec.getLoc();
153 auto poison = mlir::LLVM::PoisonOp::create(rewriter, loc, srcVec.getType());
154 return mlir::LLVM::ShuffleVectorOp::create(rewriter, loc, srcVec, poison,
162 const mlir::TypeConverter &converter,
163 mlir::DataLayout
const &dataLayout,
164 cir::LoadOp op, mlir::Value value) {
166 if (
auto boolTy = mlir::dyn_cast<cir::BoolType>(op.getType())) {
168 assert(value.getType().isInteger(dataLayout.getTypeSizeInBits(boolTy)));
173 if (
auto vecTy = mlir::dyn_cast<cir::VectorType>(op.getType())) {
174 if (mlir::isa<cir::BoolType>(vecTy.getElementType())) {
175 auto rawIntTy = mlir::cast<mlir::IntegerType>(value.getType());
177 cir::VectorType::get(vecTy.getElementType(), rawIntTy.getWidth());
178 mlir::Type mlirVecTy = converter.convertType(paddedVecTy);
180 auto v = mlir::LLVM::BitcastOp::create(rewriter, value.getLoc(),
188 if (
auto intTy = mlir::dyn_cast<cir::IntType>(op.getType());
189 intTy && intTy.isBitInt())
199static mlir::Value
emitToMemory(mlir::ConversionPatternRewriter &rewriter,
200 mlir::DataLayout
const &dataLayout,
201 mlir::Type origType, mlir::Value value) {
204 if (
auto boolTy = mlir::dyn_cast<cir::BoolType>(origType)) {
206 mlir::IntegerType memType =
207 rewriter.getIntegerType(dataLayout.getTypeSizeInBits(boolTy));
215 if (
auto vecTy = mlir::dyn_cast<cir::VectorType>(origType)) {
216 if (mlir::isa<cir::BoolType>(vecTy.getElementType())) {
218 if (vecTy.getIsScalable())
219 resultTy = mlir::VectorType::get(
220 vecTy.getSize(), vecTy.getElementType(), vecTy.getIsScalable());
222 uint64_t bytePadded = std::max<uint64_t>(vecTy.getSize(), 8);
223 resultTy = mlir::IntegerType::get(origType.getContext(), bytePadded);
225 rewriter, value, dyn_cast<mlir::IntegerType>(resultTy).getWidth());
227 return mlir::LLVM::BitcastOp::create(rewriter, value.getLoc(), resultTy,
233 if (
auto intTy = mlir::dyn_cast<cir::IntType>(origType);
234 intTy && intTy.isBitInt())
242 using CIR = cir::GlobalLinkageKind;
243 using LLVM = mlir::LLVM::Linkage;
246 case CIR::AppendingLinkage:
247 return LLVM::Appending;
248 case CIR::AvailableExternallyLinkage:
249 return LLVM::AvailableExternally;
250 case CIR::CommonLinkage:
252 case CIR::ExternalLinkage:
253 return LLVM::External;
254 case CIR::ExternalWeakLinkage:
255 return LLVM::ExternWeak;
256 case CIR::InternalLinkage:
257 return LLVM::Internal;
258 case CIR::LinkOnceAnyLinkage:
259 return LLVM::Linkonce;
260 case CIR::LinkOnceODRLinkage:
261 return LLVM::LinkonceODR;
262 case CIR::PrivateLinkage:
263 return LLVM::Private;
264 case CIR::WeakAnyLinkage:
266 case CIR::WeakODRLinkage:
267 return LLVM::WeakODR;
269 llvm_unreachable(
"Unknown CIR linkage type");
273 using CIR = cir::CallingConv;
274 using LLVM = mlir::LLVM::CConv;
276 switch (callingConv) {
279 case CIR::SpirKernel:
280 return LLVM::SPIR_KERNEL;
281 case CIR::SpirFunction:
282 return LLVM::SPIR_FUNC;
284 return LLVM::PTX_Kernel;
285 case CIR::AMDGPUKernel:
286 return LLVM::AMDGPU_KERNEL;
288 llvm_unreachable(
"Unknown calling convention");
291mlir::LogicalResult CIRToLLVMCopyOpLowering::matchAndRewrite(
292 cir::CopyOp op, OpAdaptor adaptor,
293 mlir::ConversionPatternRewriter &rewriter)
const {
294 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
295 const mlir::Value
length = mlir::LLVM::ConstantOp::create(
296 rewriter, op.getLoc(), rewriter.getI64Type(),
297 op.getCopySizeInBytes(layout));
300 uint64_t dstTypeAlign =
301 dataLayout.getTypeABIAlignment(op.getDst().getType().getPointee());
302 uint64_t srcTypeAlign =
303 dataLayout.getTypeABIAlignment(op.getSrc().getType().getPointee());
305 mlir::NamedAttribute dstAlignAttr = rewriter.getNamedAttr(
306 mlir::LLVM::LLVMDialect::getAlignAttrName(),
307 rewriter.getI64IntegerAttr(op.getDstAlignment().value_or(dstTypeAlign)));
308 mlir::NamedAttribute srcAlignAttr = rewriter.getNamedAttr(
309 mlir::LLVM::LLVMDialect::getAlignAttrName(),
310 rewriter.getI64IntegerAttr(op.getSrcAlignment().value_or(srcTypeAlign)));
311 mlir::ArrayAttr argAttrs = rewriter.getArrayAttr({
312 rewriter.getDictionaryAttr({dstAlignAttr}),
313 rewriter.getDictionaryAttr({srcAlignAttr}),
316 rewriter.replaceOpWithNewOp<mlir::LLVM::MemcpyOp>(
317 op, adaptor.getDst(), adaptor.getSrc(),
length, op.getIsVolatile(),
319 nullptr,
nullptr, argAttrs,
321 return mlir::success();
324mlir::LogicalResult CIRToLLVMMemCpyOpLowering::matchAndRewrite(
325 cir::MemCpyOp op, OpAdaptor adaptor,
326 mlir::ConversionPatternRewriter &rewriter)
const {
327 mlir::ArrayAttr argAttrs;
328 if (op.getDstAlignment() || op.getSrcAlignment()) {
329 mlir::NamedAttribute dstAlignAttr = rewriter.getNamedAttr(
330 mlir::LLVM::LLVMDialect::getAlignAttrName(),
331 rewriter.getI64IntegerAttr(op.getDstAlignment().value_or(1)));
332 mlir::NamedAttribute srcAlignAttr = rewriter.getNamedAttr(
333 mlir::LLVM::LLVMDialect::getAlignAttrName(),
334 rewriter.getI64IntegerAttr(op.getSrcAlignment().value_or(1)));
335 argAttrs = rewriter.getArrayAttr({
336 rewriter.getDictionaryAttr({dstAlignAttr}),
337 rewriter.getDictionaryAttr({srcAlignAttr}),
340 rewriter.replaceOpWithNewOp<mlir::LLVM::MemcpyOp>(
341 op, adaptor.getDst(), adaptor.getSrc(), adaptor.getLen(),
344 nullptr,
nullptr, argAttrs,
346 return mlir::success();
349mlir::LogicalResult CIRToLLVMMemMoveOpLowering::matchAndRewrite(
350 cir::MemMoveOp op, OpAdaptor adaptor,
351 mlir::ConversionPatternRewriter &rewriter)
const {
352 rewriter.replaceOpWithNewOp<mlir::LLVM::MemmoveOp>(
353 op, adaptor.getDst(), adaptor.getSrc(), adaptor.getLen(),
355 return mlir::success();
358mlir::LogicalResult CIRToLLVMMemSetOpLowering::matchAndRewrite(
359 cir::MemSetOp op, OpAdaptor adaptor,
360 mlir::ConversionPatternRewriter &rewriter)
const {
362 auto memset = rewriter.replaceOpWithNewOp<mlir::LLVM::MemsetOp>(
363 op, adaptor.getDst(), adaptor.getVal(), adaptor.getLen(),
366 if (op.getAlignmentAttr()) {
368 llvm::SmallVector<mlir::Attribute> attrs{
memset.getNumOperands(),
369 rewriter.getDictionaryAttr({})};
370 llvm::SmallVector<mlir::NamedAttribute> destAttrs;
372 {mlir::LLVM::LLVMDialect::getAlignAttrName(), op.getAlignmentAttr()});
373 attrs[
memset.odsIndex_dst] = rewriter.getDictionaryAttr(destAttrs);
375 auto arrayAttr = rewriter.getArrayAttr(attrs);
376 memset.setArgAttrsAttr(arrayAttr);
379 return mlir::success();
383 mlir::Value llvmSrc, mlir::Type llvmDstIntTy,
385 uint64_t cirDstIntWidth) {
386 if (cirSrcWidth == cirDstIntWidth)
389 auto loc = llvmSrc.getLoc();
390 if (cirSrcWidth < cirDstIntWidth) {
392 return mlir::LLVM::ZExtOp::create(rewriter, loc, llvmDstIntTy, llvmSrc);
393 return mlir::LLVM::SExtOp::create(rewriter, loc, llvmDstIntTy, llvmSrc);
397 return mlir::LLVM::TruncOp::create(rewriter, loc, llvmDstIntTy, llvmSrc);
403 mlir::ConversionPatternRewriter &rewriter,
404 mlir::SymbolTableCollection &symbolTables,
405 const mlir::TypeConverter *converter,
407 : parentOp(parentOp), rewriter(rewriter), symbolTables(symbolTables),
408 converter(converter), blockInfoAddr(blockInfoAddr) {}
410#define GET_CIR_ATTR_TO_VALUE_VISITOR_DECLS
411#include "clang/CIR/Dialect/IR/CIRLowering.inc"
412#undef GET_CIR_ATTR_TO_VALUE_VISITOR_DECLS
415 struct LoweredGlobalSymbol {
417 mlir::Type sourceType;
421 LoweredGlobalSymbol getAddressOfSymbol(mlir::FlatSymbolRefAttr symbol);
422 mlir::Value castGlobalAddrToType(mlir::Value addr, mlir::Type attrType,
423 mlir::Type sourceType,
unsigned addrSpace);
425 mlir::Operation *parentOp;
426 mlir::ConversionPatternRewriter &rewriter;
427 mlir::SymbolTableCollection &symbolTables;
428 const mlir::TypeConverter *converter;
431 LLVMBlockAddressInfo *blockInfoAddr;
436 const mlir::Attribute attr,
437 mlir::ConversionPatternRewriter &rewriter,
438 mlir::SymbolTableCollection &symbolTables,
439 const mlir::TypeConverter *converter,
441 CIRAttrToValue valueConverter(parentOp, rewriter, symbolTables, converter,
443 mlir::Value value = valueConverter.visit(attr);
445 llvm_unreachable(
"unhandled attribute type");
451 case cir::ModRefInfo::NoModRef:
452 return mlir::LLVM::ModRefInfo::NoModRef;
453 case cir::ModRefInfo::Ref:
454 return mlir::LLVM::ModRefInfo::Ref;
455 case cir::ModRefInfo::Mod:
456 return mlir::LLVM::ModRefInfo::Mod;
457 case cir::ModRefInfo::ModRef:
458 return mlir::LLVM::ModRefInfo::ModRef;
460 llvm_unreachable(
"unhandled cir::ModRefInfo");
464static mlir::LLVM::MemoryEffectsAttr
469 return mlir::LLVM::MemoryEffectsAttr::get(
479 cir::MemoryEffectsAttr effects,
480 mlir::LLVM::MemoryEffectsAttr &memoryEffect,
481 bool &noUnwind,
bool &willReturn,
487 noUnwind = isNothrow || callOp->hasAttr(CIRDialect::getNoUnwindAttrName());
488 willReturn = callOp->hasAttr(CIRDialect::getWillReturnAttrName());
489 noReturn = callOp->hasAttr(CIRDialect::getNoReturnAttrName());
492static mlir::LLVM::CallIntrinsicOp
494 mlir::Location loc,
const llvm::Twine &intrinsicName,
495 mlir::Type resultTy, mlir::ValueRange operands,
496 mlir::LLVM::FastmathFlags fastmathFlags = {}) {
497 auto intrinsicNameAttr =
498 mlir::StringAttr::get(rewriter.getContext(), intrinsicName);
500 mlir::LLVM::FastmathFlagsAttr::get(rewriter.getContext(), fastmathFlags);
504 return mlir::LLVM::CallIntrinsicOp::create(
505 rewriter, loc, mlir::TypeRange{resultTy}, intrinsicNameAttr, operands,
507 return mlir::LLVM::CallIntrinsicOp::create(rewriter, loc, intrinsicNameAttr,
512 mlir::ConversionPatternRewriter &rewriter, mlir::Operation *op,
513 const llvm::Twine &intrinsicName, mlir::Type resultTy,
514 mlir::ValueRange operands, mlir::LLVM::FastmathFlags fastmathFlags = {}) {
516 rewriter, op->getLoc(), intrinsicName, resultTy, operands, fastmathFlags);
517 rewriter.replaceOp(op, callIntrinOp.getOperation());
522 std::optional<cir::FPDynamicRoundingMode> rounding =
523 fenv.getDynamicRoundingMode();
525 return "round.tonearest";
527 case cir::FPDynamicRoundingMode::ToNearest:
528 return "round.tonearest";
529 case cir::FPDynamicRoundingMode::Downward:
530 return "round.downward";
531 case cir::FPDynamicRoundingMode::Upward:
532 return "round.upward";
533 case cir::FPDynamicRoundingMode::UpwardZero:
534 return "round.towardzero";
535 case cir::FPDynamicRoundingMode::ToNearestAway:
536 return "round.tonearestaway";
537 case cir::FPDynamicRoundingMode::Unknown:
538 return "round.dynamic";
540 llvm_unreachable(
"unknown FP dynamic rounding mode");
544 std::optional<cir::FPExceptionMode> exceptMode = fenv.getExceptMode();
545 if (exceptMode == cir::FPExceptionMode::Masked)
546 return "fpexcept.ignore";
547 mlir::BoolAttr strictExcept = fenv.getStrictExcept();
549 return "fpexcept.ignore";
550 return strictExcept.getValue() ?
"fpexcept.strict" :
"fpexcept.maytrap";
555 mlir::Location loc, llvm::StringRef str) {
556 auto mdString = mlir::LLVM::MDStringAttr::get(
557 rewriter.getContext(), mlir::StringAttr::get(rewriter.getContext(), str));
558 return mlir::LLVM::MetadataAsValueOp::create(rewriter, loc, mdString);
562 mlir::Operation *op, mlir::ValueRange operands, cir::FenvAttr fenv,
563 mlir::Type llvmResTy, mlir::ConversionPatternRewriter &rewriter,
564 llvm::StringRef constrainedMnemonic,
bool hasRoundingMode,
565 mlir::LLVM::FastmathFlags fastmathFlags) {
566 mlir::Location loc = op->getLoc();
575 rewriter, op,
"llvm.experimental.constrained." + constrainedMnemonic,
576 llvmResTy, callOperands, fastmathFlags);
577 return mlir::success();
580template <
typename LLVMOp>
582 mlir::Operation *op, mlir::ValueRange operands, cir::FenvAttr fenv,
583 const mlir::TypeConverter &typeConverter,
584 mlir::ConversionPatternRewriter &rewriter,
585 llvm::StringRef constrainedMnemonic,
bool hasRoundingMode) {
586 mlir::Type llvmResTy = typeConverter.convertType(op->getResultTypes()[0]);
588 return op->emitError(
"expected LLVM result type for floating-point op");
591 rewriter.replaceOpWithNewOp<LLVMOp>(
592 op, mlir::TypeRange{llvmResTy}, operands,
594 return mlir::success();
598 constrainedMnemonic, hasRoundingMode);
601static mlir::LLVM::FastmathFlags
603 mlir::LLVM::FastmathFlags llvmFlags{};
604 const std::pair<cir::FastMathFlags, mlir::LLVM::FastmathFlags> flags[] = {
605 {cir::FastMathFlags::nnan, mlir::LLVM::FastmathFlags::nnan},
606 {cir::FastMathFlags::ninf, mlir::LLVM::FastmathFlags::ninf},
607 {cir::FastMathFlags::nsz, mlir::LLVM::FastmathFlags::nsz},
608 {cir::FastMathFlags::arcp, mlir::LLVM::FastmathFlags::arcp},
609 {cir::FastMathFlags::contract, mlir::LLVM::FastmathFlags::contract},
610 {cir::FastMathFlags::afn, mlir::LLVM::FastmathFlags::afn},
611 {cir::FastMathFlags::reassoc, mlir::LLVM::FastmathFlags::reassoc},
614 for (
auto [cirFlag, llvmFlag] : flags) {
615 if (bitEnumContainsAny(cirFlags, cirFlag))
616 llvmFlags = llvmFlags | llvmFlag;
622mlir::LogicalResult CIRToLLVMLLVMIntrinsicCallOpLowering::matchAndRewrite(
623 cir::LLVMIntrinsicCallOp op, OpAdaptor adaptor,
624 mlir::ConversionPatternRewriter &rewriter)
const {
627 mlir::Type llvmResTy;
628 if (op->getNumResults() != 0) {
629 llvmResTy = getTypeConverter()->convertType(op->getResultTypes()[0]);
631 return op.emitError(
"expected LLVM result type");
633 StringRef name = op.getIntrinsicName();
634 mlir::LLVM::FastmathFlags fastmathFlags = {};
635 if (std::optional<cir::FastMathFlags> fastmath = op.getFastmathFlags())
649 adaptor.getOperands(), fastmathFlags);
650 return mlir::success();
654mlir::Value CIRAttrToValue::visitCirAttr(cir::BoolAttr boolAttr) {
655 mlir::Location loc = parentOp->getLoc();
656 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
657 mlir::Value boolVal = mlir::LLVM::ConstantOp::create(
658 rewriter, loc, converter->convertType(boolAttr.getType()),
659 boolAttr.getValue());
660 return emitToMemory(rewriter, layout, boolAttr.getType(), boolVal);
664mlir::Value CIRAttrToValue::visitCirAttr(cir::IntAttr intAttr) {
665 mlir::Location loc = parentOp->getLoc();
666 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
668 if (
auto intTy = mlir::dyn_cast<cir::IntType>(intAttr.getType());
669 intTy && intTy.isBitInt()) {
671 return mlir::LLVM::ConstantOp::create(
678 mlir::Value val = mlir::LLVM::ConstantOp::create(
679 rewriter, loc, converter->convertType(intAttr.getType()),
681 return emitToMemory(rewriter, layout, intAttr.getType(), val);
685mlir::Value CIRAttrToValue::visitCirAttr(cir::FPAttr fltAttr) {
686 mlir::Location loc = parentOp->getLoc();
687 return mlir::LLVM::ConstantOp::create(
688 rewriter, loc, converter->convertType(fltAttr.getType()),
693mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstComplexAttr complexAttr) {
694 cir::ComplexType
complexType = complexAttr.getType();
695 mlir::Type complexElemTy =
complexType.getElementType();
696 mlir::Type complexElemLLVMTy = converter->convertType(complexElemTy);
698 mlir::Attribute components[2];
699 if (
const auto intType = mlir::dyn_cast<cir::IntType>(complexElemTy)) {
700 components[0] = rewriter.getIntegerAttr(
702 mlir::cast<cir::IntAttr>(complexAttr.getReal()).getValue());
703 components[1] = rewriter.getIntegerAttr(
705 mlir::cast<cir::IntAttr>(complexAttr.getImag()).getValue());
707 components[0] = rewriter.getFloatAttr(
709 mlir::cast<cir::FPAttr>(complexAttr.getReal()).getValue());
710 components[1] = rewriter.getFloatAttr(
712 mlir::cast<cir::FPAttr>(complexAttr.getImag()).getValue());
715 mlir::Location loc = parentOp->getLoc();
716 return mlir::LLVM::ConstantOp::create(
717 rewriter, loc, converter->convertType(complexAttr.getType()),
718 rewriter.getArrayAttr(components));
722mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstPtrAttr ptrAttr) {
723 mlir::Location loc = parentOp->getLoc();
724 if (ptrAttr.isNullValue()) {
725 return mlir::LLVM::ZeroOp::create(
726 rewriter, loc, converter->convertType(ptrAttr.getType()));
728 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
729 mlir::Value ptrVal = mlir::LLVM::ConstantOp::create(
731 rewriter.getIntegerType(layout.getTypeSizeInBits(ptrAttr.getType())),
732 ptrAttr.getValue().getInt());
733 return mlir::LLVM::IntToPtrOp::create(
734 rewriter, loc, converter->convertType(ptrAttr.getType()), ptrVal);
738mlir::Value CIRAttrToValue::visitCirAttr(cir::BlockAddrInfoAttr blockAddrInfo) {
739 assert(blockInfoAddr &&
740 "block address lowering requires LLVMBlockAddressInfo");
745 mlir::Location loc = parentOp->getLoc();
746 mlir::LLVM::BlockTagOp matchLabel =
747 blockInfoAddr->lookupBlockTag(blockAddrInfo);
748 mlir::LLVM::BlockTagAttr tagAttr =
749 matchLabel ? matchLabel.getTag() : mlir::LLVM::BlockTagAttr{};
750 auto blkAddr = mlir::LLVM::BlockAddressAttr::get(
751 rewriter.getContext(), blockAddrInfo.getFunc(), tagAttr);
752 auto blockAddressOp = mlir::LLVM::BlockAddressOp::create(
753 rewriter, loc, mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
756 blockInfoAddr->addUnresolvedBlockAddress(blockAddressOp, blockAddrInfo);
757 return blockAddressOp;
761mlir::Value CIRAttrToValue::visitCirAttr(cir::BlockAddrDiffAttr blockAddrDiff) {
762 assert(blockInfoAddr &&
763 "block address lowering requires LLVMBlockAddressInfo");
769 mlir::Location loc = parentOp->getLoc();
770 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
771 mlir::MLIRContext *ctx = rewriter.getContext();
772 auto ptrTy = mlir::LLVM::LLVMPointerType::get(ctx);
774 auto emitBlockAddr = [&](mlir::StringAttr label) -> mlir::Value {
775 auto info = cir::BlockAddrInfoAttr::get(
776 ctx, blockAddrDiff.getFunc().getValue(), label.getValue());
777 mlir::LLVM::BlockTagOp matchLabel = blockInfoAddr->lookupBlockTag(info);
778 mlir::LLVM::BlockTagAttr tagAttr =
779 matchLabel ? matchLabel.getTag() : mlir::LLVM::BlockTagAttr{};
780 auto blkAddr = mlir::LLVM::BlockAddressAttr::get(
781 ctx, blockAddrDiff.getFunc(), tagAttr);
783 mlir::LLVM::BlockAddressOp::create(rewriter, loc, ptrTy, blkAddr);
785 blockInfoAddr->addUnresolvedBlockAddress(addrOp, info);
789 mlir::Value lhsAddr = emitBlockAddr(blockAddrDiff.getLhsLabel());
790 mlir::Value rhsAddr = emitBlockAddr(blockAddrDiff.getRhsLabel());
796 mlir::Type intptrTy =
797 rewriter.getIntegerType(layout.getTypeSizeInBits(ptrTy));
799 mlir::LLVM::PtrToIntOp::create(rewriter, loc, intptrTy, lhsAddr);
801 mlir::LLVM::PtrToIntOp::create(rewriter, loc, intptrTy, rhsAddr);
802 mlir::Value diffVal =
803 mlir::LLVM::SubOp::create(rewriter, loc, lhsInt, rhsInt);
805 mlir::Type resultTy = converter->convertType(blockAddrDiff.getType());
806 mlir::Value result = diffVal;
807 if (resultTy != intptrTy)
808 result = mlir::LLVM::TruncOp::create(rewriter, loc, resultTy, diffVal);
813mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstArrayAttr attr) {
814 mlir::Type llvmTy = converter->convertType(
attr.getType());
815 mlir::DataLayout dataLayout(parentOp->getParentOfType<mlir::ModuleOp>());
817 mlir::Location loc = parentOp->getLoc();
822 if (std::optional<mlir::Attribute> denseAttr =
824 return mlir::LLVM::ConstantOp::create(rewriter, loc, llvmTy, *denseAttr);
826 if (
attr.hasTrailingZeros())
827 result = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmTy);
829 result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
832 if (
auto arrayAttr = mlir::dyn_cast<mlir::ArrayAttr>(
attr.getElts())) {
833 for (
auto [idx, elt] : llvm::enumerate(arrayAttr)) {
834 mlir::Value init = visit(elt);
836 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
838 }
else if (
auto strAttr = mlir::dyn_cast<mlir::StringAttr>(
attr.getElts())) {
841 auto arrayTy = mlir::dyn_cast<cir::ArrayType>(strAttr.getType());
842 assert(arrayTy &&
"String attribute must have an array type");
843 mlir::Type eltTy = arrayTy.getElementType();
844 for (
auto [idx, elt] : llvm::enumerate(strAttr)) {
845 auto init = mlir::LLVM::ConstantOp::create(
846 rewriter, loc, converter->convertType(eltTy), elt);
848 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
851 llvm_unreachable(
"unexpected ConstArrayAttr elements");
858mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstRecordAttr constRecord) {
859 mlir::Type llvmTy = converter->convertType(constRecord.getType());
860 mlir::DataLayout dataLayout(parentOp->getParentOfType<mlir::ModuleOp>());
861 llvm::SmallVector<unsigned> paddingAddedIndexes;
863 paddingAddedIndexes);
864 const mlir::Location loc = parentOp->getLoc();
865 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
868 auto paddingItr = paddingAddedIndexes.begin();
873 for (
auto [idx, elt] : llvm::enumerate(constRecord.getMembers())) {
874 if (paddingItr != paddingAddedIndexes.end() && *paddingItr == idx) {
879 result = mlir::LLVM::InsertValueOp::create(rewriter, loc, result,
880 visit(elt), insertIdx);
888mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstVectorAttr attr) {
889 const mlir::Type llvmTy = converter->convertType(
attr.getType());
890 const mlir::Location loc = parentOp->getLoc();
892 SmallVector<mlir::Attribute> mlirValues;
893 for (
const mlir::Attribute elementAttr :
attr.getElts()) {
894 mlir::Attribute mlirAttr;
895 if (
auto intAttr = mlir::dyn_cast<cir::IntAttr>(elementAttr)) {
896 mlirAttr = rewriter.getIntegerAttr(
897 converter->convertType(intAttr.getType()), intAttr.getValue());
898 }
else if (
auto floatAttr = mlir::dyn_cast<cir::FPAttr>(elementAttr)) {
899 mlirAttr = rewriter.getFloatAttr(
900 converter->convertType(floatAttr.getType()), floatAttr.getValue());
901 }
else if (
auto boolAttr = mlir::dyn_cast<cir::BoolAttr>(elementAttr)) {
902 mlirAttr = rewriter.getBoolAttr(boolAttr.getValue());
904 llvm_unreachable(
"vector constant with an element that is neither an "
905 "int, a float, or a bool");
907 mlirValues.push_back(mlirAttr);
910 return mlir::LLVM::ConstantOp::create(
911 rewriter, loc, llvmTy,
912 mlir::DenseElementsAttr::get(mlir::cast<mlir::ShapedType>(llvmTy),
917CIRAttrToValue::LoweredGlobalSymbol
918CIRAttrToValue::getAddressOfSymbol(mlir::FlatSymbolRefAttr symbol) {
919 auto moduleOp = parentOp->getParentOfType<mlir::ModuleOp>();
920 mlir::DataLayout dataLayout(moduleOp);
921 mlir::Type sourceType;
922 unsigned addrSpace = 0;
923 llvm::StringRef symName;
924 mlir::Operation *sourceSymbol = symbolTables.lookupSymbolIn(moduleOp, symbol);
925 if (
auto llvmSymbol = dyn_cast<mlir::LLVM::GlobalOp>(sourceSymbol)) {
926 sourceType = llvmSymbol.getType();
927 symName = llvmSymbol.getSymName();
928 addrSpace = llvmSymbol.getAddrSpace();
929 }
else if (
auto cirSymbol = dyn_cast<cir::GlobalOp>(sourceSymbol)) {
932 symName = cirSymbol.getSymName();
933 if (
auto targetAS = mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
934 cirSymbol.getAddrSpaceAttr()))
935 addrSpace = targetAS.getValue();
936 }
else if (
auto llvmFun = dyn_cast<mlir::LLVM::LLVMFuncOp>(sourceSymbol)) {
937 sourceType = llvmFun.getFunctionType();
938 symName = llvmFun.getSymName();
939 }
else if (
auto fun = dyn_cast<cir::FuncOp>(sourceSymbol)) {
940 sourceType = converter->convertType(fun.getFunctionType());
941 symName = fun.getSymName();
942 }
else if (
auto alias = dyn_cast<mlir::LLVM::AliasOp>(sourceSymbol)) {
943 sourceType = alias.getType();
944 symName = alias.getSymName();
946 llvm_unreachable(
"Unexpected GlobalOp type");
949 mlir::Location loc = parentOp->getLoc();
950 mlir::Value addr = mlir::LLVM::AddressOfOp::create(
952 mlir::LLVM::LLVMPointerType::get(rewriter.getContext(), addrSpace),
954 return {addr, sourceType, addrSpace};
957mlir::Value CIRAttrToValue::castGlobalAddrToType(mlir::Value addr,
959 mlir::Type sourceType,
960 unsigned addrSpace) {
961 mlir::Location loc = parentOp->getLoc();
967 if (mlir::isa<cir::IntType>(attrType)) {
968 mlir::Type llvmDstTy = converter->convertType(attrType);
969 return mlir::LLVM::PtrToIntOp::create(rewriter, loc, llvmDstTy, addr);
972 if (
auto ptrTy = mlir::dyn_cast<cir::PointerType>(attrType)) {
973 auto llvmDstTy = converter->convertType<mlir::LLVM::LLVMPointerType>(ptrTy);
975 if (llvmDstTy.getAddressSpace() != addrSpace)
977 mlir::LLVM::AddrSpaceCastOp::create(rewriter, loc, llvmDstTy, addr);
979 auto moduleOp = parentOp->getParentOfType<mlir::ModuleOp>();
980 mlir::DataLayout dataLayout(moduleOp);
981 mlir::Type llvmEltTy =
985 if (llvmEltTy == sourceType)
991 if (addr.getType() == llvmDstTy)
994 return mlir::LLVM::BitcastOp::create(rewriter, loc, llvmDstTy, addr);
997 if (mlir::isa<cir::VPtrType>(attrType))
1000 llvm_unreachable(
"Expecting pointer or integer type");
1003mlir::Value CIRAttrToValue::visitCirAttr(cir::GlobalViewAttr globalAttr) {
1004 LoweredGlobalSymbol lowered = getAddressOfSymbol(globalAttr.getSymbol());
1005 mlir::Value addrOp = lowered.addr;
1006 mlir::Type sourceType = lowered.sourceType;
1008 if (globalAttr.getIndices()) {
1009 llvm::SmallVector<mlir::LLVM::GEPArg> indices;
1011 if (mlir::isa<mlir::LLVM::LLVMArrayType, mlir::LLVM::LLVMStructType>(
1013 indices.push_back(0);
1015 for (mlir::Attribute idx : globalAttr.getIndices()) {
1016 auto intAttr = mlir::cast<mlir::IntegerAttr>(idx);
1017 indices.push_back(intAttr.getValue().getSExtValue());
1019 mlir::Type resTy = addrOp.getType();
1020 mlir::Type eltTy = converter->convertType(sourceType);
1021 addrOp = mlir::LLVM::GEPOp::create(rewriter, parentOp->getLoc(), resTy,
1022 eltTy, addrOp, indices,
1023 mlir::LLVM::GEPNoWrapFlags::none);
1026 return castGlobalAddrToType(addrOp, globalAttr.getType(), sourceType,
1030mlir::Value CIRAttrToValue::visitCirAttr(cir::GlobalOffsetAttr globalAttr) {
1031 LoweredGlobalSymbol lowered = getAddressOfSymbol(globalAttr.getSymbol());
1032 mlir::Value addrOp = lowered.addr;
1033 mlir::Location loc = parentOp->getLoc();
1037 mlir::Value offset = mlir::LLVM::ConstantOp::create(
1038 rewriter, loc, rewriter.getI64Type(),
1039 rewriter.getI64IntegerAttr(globalAttr.getOffset()));
1040 addrOp = mlir::LLVM::GEPOp::create(
1041 rewriter, loc, addrOp.getType(), rewriter.getI8Type(), addrOp,
1042 mlir::ValueRange{offset}, mlir::LLVM::GEPNoWrapFlags::none);
1044 return castGlobalAddrToType(addrOp, globalAttr.getType(), lowered.sourceType,
1049mlir::Value CIRAttrToValue::visitCirAttr(cir::TypeInfoAttr typeInfoAttr) {
1050 mlir::Type llvmTy = converter->convertType(typeInfoAttr.getType());
1051 mlir::Location loc = parentOp->getLoc();
1052 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
1054 for (
auto [idx, elt] : llvm::enumerate(typeInfoAttr.getData())) {
1055 mlir::Value init = visit(elt);
1057 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
1064mlir::Value CIRAttrToValue::visitCirAttr(cir::UndefAttr undefAttr) {
1065 mlir::Location loc = parentOp->getLoc();
1066 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
1067 return mlir::LLVM::UndefOp::create(
1073mlir::Value CIRAttrToValue::visitCirAttr(cir::PoisonAttr poisonAttr) {
1074 mlir::Location loc = parentOp->getLoc();
1075 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
1076 return mlir::LLVM::PoisonOp::create(
1082mlir::Value CIRAttrToValue::visitCirAttr(cir::VTableAttr vtableArr) {
1083 mlir::Type llvmTy = converter->convertType(vtableArr.getType());
1084 mlir::Location loc = parentOp->getLoc();
1085 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
1087 for (
auto [idx, elt] : llvm::enumerate(vtableArr.getData())) {
1088 mlir::Value init = visit(elt);
1090 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
1097mlir::Value CIRAttrToValue::visitCirAttr(cir::ZeroAttr attr) {
1098 mlir::Location loc = parentOp->getLoc();
1099 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
1100 return mlir::LLVM::ZeroOp::create(
1109 mlir::ConversionPatternRewriter &rewriter)
1110 : llvmType(type), dataLayout(dataLayout), rewriter(rewriter) {}
1113 return llvm::TypeSwitch<mlir::Attribute, mlir::Attribute>(
attr)
1114 .Case<cir::IntAttr, cir::FPAttr, cir::BoolAttr>(
1116 .
Default([&](
auto attrT) {
return mlir::Attribute(); });
1123 if (
auto intTy = mlir::dyn_cast<cir::IntType>(
attr.getType());
1124 intTy && intTy.isBitInt())
1126 llvm::APInt val =
attr.getValue();
1128 return rewriter.getIntegerAttr(llvmType,
attr.getValue());
1132 return rewriter.getFloatAttr(llvmType,
attr.getValue());
1136 return rewriter.getBoolAttr(
attr.getValue());
1140 mlir::Type llvmType;
1141 const mlir::DataLayout &dataLayout;
1142 mlir::ConversionPatternRewriter &rewriter;
1150 :
public mlir::PassWrapper<ConvertCIRToLLVMPass,
1151 mlir::OperationPass<mlir::ModuleOp>> {
1153 registry.insert<mlir::BuiltinDialect, mlir::DLTIDialect,
1154 mlir::LLVM::LLVMDialect, mlir::func::FuncDialect>();
1172 return "Convert the prepared CIR dialect module to LLVM dialect";
1179 struct CollectedAnnotation {
1180 mlir::StringAttr symName;
1181 cir::AnnotationAttr annotation;
1183 CollectedAnnotation(mlir::StringAttr symName,
1184 cir::AnnotationAttr annotation, mlir::Location loc)
1185 : symName(symName), annotation(annotation), loc(loc) {}
1190mlir::LogicalResult CIRToLLVMIsFPClassOpLowering::matchAndRewrite(
1191 cir::IsFPClassOp op, OpAdaptor adaptor,
1192 mlir::ConversionPatternRewriter &rewriter)
const {
1193 mlir::Value src = adaptor.getSrc();
1194 cir::FPClassTest flags = adaptor.getFlags();
1195 mlir::IntegerType retTy = rewriter.getI1Type();
1197 rewriter.replaceOpWithNewOp<mlir::LLVM::IsFPClass>(
1198 op, retTy, src,
static_cast<uint32_t>(flags));
1199 return mlir::success();
1202mlir::LogicalResult CIRToLLVMSignBitOpLowering::matchAndRewrite(
1203 cir::SignBitOp op, OpAdaptor adaptor,
1204 mlir::ConversionPatternRewriter &rewriter)
const {
1207 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
1208 int width = layout.getTypeSizeInBits(op.getInput().getType());
1209 if (
auto longDoubleType =
1210 mlir::dyn_cast<cir::LongDoubleType>(op.getInput().getType())) {
1211 if (mlir::isa<cir::FP80Type>(longDoubleType.getUnderlying())) {
1219 mlir::Type intTy = mlir::IntegerType::get(rewriter.getContext(), width);
1220 auto bitcast = mlir::LLVM::BitcastOp::create(rewriter, op->getLoc(), intTy,
1221 adaptor.getInput());
1223 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op->getLoc(), intTy, 0);
1224 auto cmpResult = mlir::LLVM::ICmpOp::create(rewriter, op.getLoc(),
1225 mlir::LLVM::ICmpPredicate::slt,
1226 bitcast.getResult(), zero);
1227 rewriter.replaceOp(op, cmpResult);
1228 return mlir::success();
1231mlir::LogicalResult CIRToLLVMAssumeOpLowering::matchAndRewrite(
1232 cir::AssumeOp op, OpAdaptor adaptor,
1233 mlir::ConversionPatternRewriter &rewriter)
const {
1234 mlir::Value cond = adaptor.getPredicate();
1235 if (op.getBundleKind() == cir::AssumeBundleKind::None) {
1236 rewriter.replaceOpWithNewOp<mlir::LLVM::AssumeOp>(op, cond);
1237 return mlir::success();
1240 llvm::StringRef tag = cir::stringifyAssumeBundleKind(op.getBundleKind());
1241 rewriter.replaceOpWithNewOp<mlir::LLVM::AssumeOp>(op, cond, tag,
1242 adaptor.getBundleArgs());
1243 return mlir::success();
1246static mlir::LLVM::AtomicOrdering
1249 return mlir::LLVM::AtomicOrdering::not_atomic;
1250 switch (*memorder) {
1251 case cir::MemOrder::Relaxed:
1252 return mlir::LLVM::AtomicOrdering::monotonic;
1253 case cir::MemOrder::Consume:
1254 case cir::MemOrder::Acquire:
1255 return mlir::LLVM::AtomicOrdering::acquire;
1256 case cir::MemOrder::Release:
1257 return mlir::LLVM::AtomicOrdering::release;
1258 case cir::MemOrder::AcquireRelease:
1259 return mlir::LLVM::AtomicOrdering::acq_rel;
1260 case cir::MemOrder::SequentiallyConsistent:
1261 return mlir::LLVM::AtomicOrdering::seq_cst;
1263 llvm_unreachable(
"unknown memory order");
1267 switch (syncScope) {
1268 case cir::SyncScopeKind::SingleThread:
1269 return "singlethread";
1270 case cir::SyncScopeKind::Workgroup:
1277static std::optional<llvm::StringRef>
1279 if (syncScope.has_value())
1281 return std::nullopt;
1284mlir::LogicalResult CIRToLLVMAtomicCmpXchgOpLowering::matchAndRewrite(
1285 cir::AtomicCmpXchgOp op, OpAdaptor adaptor,
1286 mlir::ConversionPatternRewriter &rewriter)
const {
1287 mlir::Value expected = adaptor.getExpected();
1288 mlir::Value desired = adaptor.getDesired();
1290 auto cmpxchg = mlir::LLVM::AtomicCmpXchgOp::create(
1291 rewriter, op.getLoc(), adaptor.getPtr(), expected, desired,
1296 cmpxchg.setAlignment(adaptor.getAlignment());
1297 cmpxchg.setWeak(adaptor.getWeak());
1298 cmpxchg.setVolatile_(adaptor.getIsVolatile());
1301 auto old = mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(),
1302 cmpxchg.getResult(), 0);
1303 auto cmp = mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(),
1304 cmpxchg.getResult(), 1);
1306 rewriter.replaceOp(op, {old, cmp});
1307 return mlir::success();
1310mlir::LogicalResult CIRToLLVMAtomicXchgOpLowering::matchAndRewrite(
1311 cir::AtomicXchgOp op, OpAdaptor adaptor,
1312 mlir::ConversionPatternRewriter &rewriter)
const {
1314 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(adaptor.getMemOrder());
1316 rewriter.replaceOpWithNewOp<mlir::LLVM::AtomicRMWOp>(
1317 op, mlir::LLVM::AtomicBinOp::xchg, adaptor.getPtr(), adaptor.getVal(),
1318 llvmOrder, llvmSyncScope, 0, op.getIsVolatile());
1319 return mlir::success();
1322mlir::LogicalResult CIRToLLVMAtomicTestAndSetOpLowering::matchAndRewrite(
1323 cir::AtomicTestAndSetOp op, OpAdaptor adaptor,
1324 mlir::ConversionPatternRewriter &rewriter)
const {
1327 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
1329 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1330 rewriter.getI8Type(), 1);
1331 auto rmw = mlir::LLVM::AtomicRMWOp::create(
1332 rewriter, op.getLoc(), mlir::LLVM::AtomicBinOp::xchg, adaptor.getPtr(),
1333 one, llvmOrder, llvm::StringRef(),
1334 adaptor.getAlignment().value_or(0), op.getIsVolatile());
1336 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1337 rewriter.getI8Type(), 0);
1338 auto cmp = mlir::LLVM::ICmpOp::create(
1339 rewriter, op.getLoc(), mlir::LLVM::ICmpPredicate::ne, rmw, zero);
1341 rewriter.replaceOp(op, cmp);
1342 return mlir::success();
1345mlir::LogicalResult CIRToLLVMAtomicClearOpLowering::matchAndRewrite(
1346 cir::AtomicClearOp op, OpAdaptor adaptor,
1347 mlir::ConversionPatternRewriter &rewriter)
const {
1350 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
1351 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1352 rewriter.getI8Type(), 0);
1353 auto store = mlir::LLVM::StoreOp::create(
1354 rewriter, op.getLoc(), zero, adaptor.getPtr(),
1355 adaptor.getAlignment().value_or(0), op.getIsVolatile(),
1356 false,
false, llvmOrder);
1358 rewriter.replaceOp(op, store);
1359 return mlir::success();
1362mlir::LogicalResult CIRToLLVMAtomicFenceOpLowering::matchAndRewrite(
1363 cir::AtomicFenceOp op, OpAdaptor adaptor,
1364 mlir::ConversionPatternRewriter &rewriter)
const {
1365 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(adaptor.getOrdering());
1367 auto fence = mlir::LLVM::FenceOp::create(rewriter, op.getLoc(), llvmOrder);
1370 rewriter.replaceOp(op, fence);
1372 return mlir::success();
1375static mlir::LLVM::AtomicBinOp
1378 case cir::AtomicFetchKind::Add:
1379 return isInt ? mlir::LLVM::AtomicBinOp::add : mlir::LLVM::AtomicBinOp::fadd;
1380 case cir::AtomicFetchKind::Sub:
1381 return isInt ? mlir::LLVM::AtomicBinOp::sub : mlir::LLVM::AtomicBinOp::fsub;
1382 case cir::AtomicFetchKind::And:
1383 return mlir::LLVM::AtomicBinOp::_and;
1384 case cir::AtomicFetchKind::Xor:
1385 return mlir::LLVM::AtomicBinOp::_xor;
1386 case cir::AtomicFetchKind::Or:
1387 return mlir::LLVM::AtomicBinOp::_or;
1388 case cir::AtomicFetchKind::Nand:
1389 return mlir::LLVM::AtomicBinOp::nand;
1390 case cir::AtomicFetchKind::Max: {
1392 return mlir::LLVM::AtomicBinOp::fmax;
1393 return isSignedInt ? mlir::LLVM::AtomicBinOp::max
1394 : mlir::LLVM::AtomicBinOp::umax;
1396 case cir::AtomicFetchKind::Min: {
1398 return mlir::LLVM::AtomicBinOp::fmin;
1399 return isSignedInt ? mlir::LLVM::AtomicBinOp::min
1400 : mlir::LLVM::AtomicBinOp::umin;
1402 case cir::AtomicFetchKind::UIncWrap:
1403 return mlir::LLVM::AtomicBinOp::uinc_wrap;
1404 case cir::AtomicFetchKind::UDecWrap:
1405 return mlir::LLVM::AtomicBinOp::udec_wrap;
1406 case cir::AtomicFetchKind::Maximum:
1407 return mlir::LLVM::AtomicBinOp::fmaximum;
1408 case cir::AtomicFetchKind::Minimum:
1409 return mlir::LLVM::AtomicBinOp::fminimum;
1410 case cir::AtomicFetchKind::MaximumNum:
1411 return mlir::LLVM::AtomicBinOp::fmaximumnum;
1412 case cir::AtomicFetchKind::MinimumNum:
1413 return mlir::LLVM::AtomicBinOp::fminimumnum;
1415 llvm_unreachable(
"Unknown atomic fetch opcode");
1421 case cir::AtomicFetchKind::Add:
1422 return isInt ? mlir::LLVM::AddOp::getOperationName()
1423 : mlir::LLVM::FAddOp::getOperationName();
1424 case cir::AtomicFetchKind::Sub:
1425 return isInt ? mlir::LLVM::SubOp::getOperationName()
1426 : mlir::LLVM::FSubOp::getOperationName();
1427 case cir::AtomicFetchKind::And:
1428 return mlir::LLVM::AndOp::getOperationName();
1429 case cir::AtomicFetchKind::Xor:
1430 return mlir::LLVM::XOrOp::getOperationName();
1431 case cir::AtomicFetchKind::Or:
1432 return mlir::LLVM::OrOp::getOperationName();
1433 case cir::AtomicFetchKind::Nand:
1435 return mlir::LLVM::AndOp::getOperationName();
1436 case cir::AtomicFetchKind::Max:
1437 case cir::AtomicFetchKind::Min:
1438 llvm_unreachable(
"handled in buildMinMaxPostOp");
1439 case cir::AtomicFetchKind::UIncWrap:
1440 case cir::AtomicFetchKind::UDecWrap:
1441 case cir::AtomicFetchKind::Maximum:
1442 case cir::AtomicFetchKind::Minimum:
1443 case cir::AtomicFetchKind::MaximumNum:
1444 case cir::AtomicFetchKind::MinimumNum:
1445 llvm_unreachable(
"uinc_wrap, udec_wrap, maximum, minimum, maximum_num, and "
1446 "minimum_num are always fetch_first");
1448 llvm_unreachable(
"Unknown atomic fetch opcode");
1451mlir::Value CIRToLLVMAtomicFetchOpLowering::buildPostOp(
1452 cir::AtomicFetchOp op, OpAdaptor adaptor,
1453 mlir::ConversionPatternRewriter &rewriter, mlir::Value rmwVal,
1458 .create(op.getLoc(),
1459 rewriter.getStringAttr(
1461 atomicOperands, atomicResTys, {})
1465mlir::Value CIRToLLVMAtomicFetchOpLowering::buildMinMaxPostOp(
1466 cir::AtomicFetchOp op, OpAdaptor adaptor,
1467 mlir::ConversionPatternRewriter &rewriter, mlir::Value rmwVal,
bool isInt,
1468 bool isSigned)
const {
1469 mlir::Location loc = op.getLoc();
1472 if (op.getBinop() == cir::AtomicFetchKind::Max)
1473 return mlir::LLVM::MaxNumOp::create(rewriter, loc, rmwVal,
1475 return mlir::LLVM::MinNumOp::create(rewriter, loc, rmwVal,
1479 mlir::LLVM::ICmpPredicate pred;
1480 if (op.getBinop() == cir::AtomicFetchKind::Max) {
1481 pred = isSigned ? mlir::LLVM::ICmpPredicate::sgt
1482 : mlir::LLVM::ICmpPredicate::ugt;
1484 pred = isSigned ? mlir::LLVM::ICmpPredicate::slt
1485 : mlir::LLVM::ICmpPredicate::ult;
1487 mlir::Value cmp = mlir::LLVM::ICmpOp::create(
1489 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(), pred), rmwVal,
1491 return mlir::LLVM::SelectOp::create(rewriter, loc, cmp, rmwVal,
1495mlir::LogicalResult CIRToLLVMAtomicFetchOpLowering::matchAndRewrite(
1496 cir::AtomicFetchOp op, OpAdaptor adaptor,
1497 mlir::ConversionPatternRewriter &rewriter)
const {
1499 bool isSignedInt =
false;
1500 if (
auto intTy = mlir::dyn_cast<cir::IntType>(op.getVal().getType())) {
1502 isSignedInt = intTy.isSigned();
1503 }
else if (mlir::isa<cir::SingleType, cir::DoubleType>(
1504 op.getVal().getType())) {
1507 return op.emitError() <<
"Unsupported type: " << op.getVal().getType();
1510 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
1512 mlir::LLVM::AtomicBinOp llvmBinOp =
1514 auto rmwVal = mlir::LLVM::AtomicRMWOp::create(
1515 rewriter, op.getLoc(), llvmBinOp, adaptor.getPtr(), adaptor.getVal(),
1516 llvmOrder, llvmSyncScope, 0, op.getIsVolatile());
1518 mlir::Value result = rmwVal.getResult();
1519 if (!op.getFetchFirst()) {
1520 if (op.getBinop() == cir::AtomicFetchKind::Max ||
1521 op.getBinop() == cir::AtomicFetchKind::Min)
1522 result = buildMinMaxPostOp(op, adaptor, rewriter, rmwVal.getRes(), isInt,
1525 result = buildPostOp(op, adaptor, rewriter, rmwVal.getRes(), isInt);
1528 if (op.getBinop() == cir::AtomicFetchKind::Nand) {
1529 auto negOne = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1530 result.getType(), -1);
1531 result = mlir::LLVM::XOrOp::create(rewriter, op.getLoc(), result, negOne);
1535 rewriter.replaceOp(op, result);
1536 return mlir::success();
1539mlir::LogicalResult CIRToLLVMBitClrsbOpLowering::matchAndRewrite(
1540 cir::BitClrsbOp op, OpAdaptor adaptor,
1541 mlir::ConversionPatternRewriter &rewriter)
const {
1542 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1543 adaptor.getInput().getType(), 0);
1544 auto isNeg = mlir::LLVM::ICmpOp::create(
1545 rewriter, op.getLoc(),
1546 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(),
1547 mlir::LLVM::ICmpPredicate::slt),
1548 adaptor.getInput(), zero);
1550 auto negOne = mlir::LLVM::ConstantOp::create(
1551 rewriter, op.getLoc(), adaptor.getInput().getType(), -1);
1552 auto flipped = mlir::LLVM::XOrOp::create(rewriter, op.getLoc(),
1553 adaptor.getInput(), negOne);
1555 auto select = mlir::LLVM::SelectOp::create(rewriter, op.getLoc(), isNeg,
1556 flipped, adaptor.getInput());
1558 auto resTy = getTypeConverter()->convertType(op.getType());
1559 auto clz = mlir::LLVM::CountLeadingZerosOp::create(
1560 rewriter, op.getLoc(), resTy,
select,
false);
1562 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1563 auto res = mlir::LLVM::SubOp::create(rewriter, op.getLoc(),
clz, one,
1564 mlir::LLVM::IntegerOverflowFlags::nuw);
1565 rewriter.replaceOp(op, res);
1567 return mlir::LogicalResult::success();
1570mlir::LogicalResult CIRToLLVMBitClzOpLowering::matchAndRewrite(
1571 cir::BitClzOp op, OpAdaptor adaptor,
1572 mlir::ConversionPatternRewriter &rewriter)
const {
1573 auto resTy = getTypeConverter()->convertType(op.getType());
1574 auto llvmOp = mlir::LLVM::CountLeadingZerosOp::create(
1575 rewriter, op.getLoc(), resTy, adaptor.getInput(), op.getPoisonZero());
1576 rewriter.replaceOp(op, llvmOp);
1577 return mlir::LogicalResult::success();
1580mlir::LogicalResult CIRToLLVMBitCtzOpLowering::matchAndRewrite(
1581 cir::BitCtzOp op, OpAdaptor adaptor,
1582 mlir::ConversionPatternRewriter &rewriter)
const {
1583 auto resTy = getTypeConverter()->convertType(op.getType());
1584 auto llvmOp = mlir::LLVM::CountTrailingZerosOp::create(
1585 rewriter, op.getLoc(), resTy, adaptor.getInput(), op.getPoisonZero());
1586 rewriter.replaceOp(op, llvmOp);
1587 return mlir::LogicalResult::success();
1590mlir::LogicalResult CIRToLLVMBitFfsOpLowering::matchAndRewrite(
1591 cir::BitFfsOp op, OpAdaptor adaptor,
1592 mlir::ConversionPatternRewriter &rewriter)
const {
1593 auto resTy = getTypeConverter()->convertType(op.getType());
1594 auto ctz = mlir::LLVM::CountTrailingZerosOp::create(rewriter, op.getLoc(),
1595 resTy, adaptor.getInput(),
1598 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1599 auto ctzAddOne = mlir::LLVM::AddOp::create(rewriter, op.getLoc(),
ctz, one);
1601 auto zeroInputTy = mlir::LLVM::ConstantOp::create(
1602 rewriter, op.getLoc(), adaptor.getInput().getType(), 0);
1603 auto isZero = mlir::LLVM::ICmpOp::create(
1604 rewriter, op.getLoc(),
1605 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(),
1606 mlir::LLVM::ICmpPredicate::eq),
1607 adaptor.getInput(), zeroInputTy);
1609 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 0);
1610 auto res = mlir::LLVM::SelectOp::create(rewriter, op.getLoc(), isZero, zero,
1612 rewriter.replaceOp(op, res);
1614 return mlir::LogicalResult::success();
1617mlir::LogicalResult CIRToLLVMBitParityOpLowering::matchAndRewrite(
1618 cir::BitParityOp op, OpAdaptor adaptor,
1619 mlir::ConversionPatternRewriter &rewriter)
const {
1620 auto resTy = getTypeConverter()->convertType(op.getType());
1621 auto popcnt = mlir::LLVM::CtPopOp::create(rewriter, op.getLoc(), resTy,
1622 adaptor.getInput());
1624 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1626 mlir::LLVM::AndOp::create(rewriter, op.getLoc(), popcnt, one);
1627 rewriter.replaceOp(op, popcntMod2);
1629 return mlir::LogicalResult::success();
1632mlir::LogicalResult CIRToLLVMBitPopcountOpLowering::matchAndRewrite(
1633 cir::BitPopcountOp op, OpAdaptor adaptor,
1634 mlir::ConversionPatternRewriter &rewriter)
const {
1635 auto resTy = getTypeConverter()->convertType(op.getType());
1636 auto llvmOp = mlir::LLVM::CtPopOp::create(rewriter, op.getLoc(), resTy,
1637 adaptor.getInput());
1638 rewriter.replaceOp(op, llvmOp);
1639 return mlir::LogicalResult::success();
1642mlir::LogicalResult CIRToLLVMBrCondOpLowering::matchAndRewrite(
1643 cir::BrCondOp brOp, OpAdaptor adaptor,
1644 mlir::ConversionPatternRewriter &rewriter)
const {
1649 mlir::Value i1Condition = adaptor.getCond();
1651 rewriter.replaceOpWithNewOp<mlir::LLVM::CondBrOp>(
1652 brOp, i1Condition, brOp.getDestTrue(), adaptor.getDestOperandsTrue(),
1653 brOp.getDestFalse(), adaptor.getDestOperandsFalse());
1655 return mlir::success();
1658mlir::Type CIRToLLVMCastOpLowering::convertTy(mlir::Type ty)
const {
1659 return getTypeConverter()->convertType(ty);
1662mlir::LogicalResult CIRToLLVMCastOpLowering::matchAndRewrite(
1663 cir::CastOp castOp, OpAdaptor adaptor,
1664 mlir::ConversionPatternRewriter &rewriter)
const {
1669 switch (castOp.getKind()) {
1670 case cir::CastKind::array_to_ptrdecay: {
1671 const auto ptrTy = mlir::cast<cir::PointerType>(castOp.getType());
1672 mlir::Value sourceValue = adaptor.getSrc();
1673 mlir::Type targetType = convertTy(ptrTy);
1675 ptrTy.getPointee());
1676 llvm::SmallVector<mlir::LLVM::GEPArg> offset{0};
1677 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1678 castOp, targetType, elementTy, sourceValue, offset);
1681 case cir::CastKind::int_to_bool: {
1682 mlir::Value llvmSrcVal = adaptor.getSrc();
1686 mlir::Value zeroInt = mlir::LLVM::ConstantOp::create(
1687 rewriter, castOp.getLoc(), llvmSrcVal.getType(),
1688 rewriter.getZeroAttr(llvmSrcVal.getType()));
1689 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
1690 castOp, mlir::LLVM::ICmpPredicate::ne, llvmSrcVal, zeroInt);
1693 case cir::CastKind::integral: {
1694 mlir::Type srcType = castOp.getSrc().getType();
1695 mlir::Type dstType = castOp.getType();
1696 mlir::Value llvmSrcVal = adaptor.getSrc();
1697 mlir::Type llvmDstType = getTypeConverter()->convertType(dstType);
1698 cir::IntType srcIntType =
1699 mlir::cast<cir::IntType>(elementTypeIfVector(srcType));
1700 cir::IntType dstIntType =
1701 mlir::cast<cir::IntType>(elementTypeIfVector(dstType));
1702 rewriter.replaceOp(castOp,
getLLVMIntCast(rewriter, llvmSrcVal, llvmDstType,
1703 srcIntType.isUnsigned(),
1704 srcIntType.getWidth(),
1705 dstIntType.getWidth()));
1708 case cir::CastKind::floating: {
1709 mlir::Value llvmSrcVal = adaptor.getSrc();
1710 mlir::Type llvmDstTy = getTypeConverter()->convertType(castOp.getType());
1712 mlir::Type srcTy = elementTypeIfVector(castOp.getSrc().getType());
1713 mlir::Type dstTy = elementTypeIfVector(castOp.getType());
1715 if (!mlir::isa<cir::FPTypeInterface>(dstTy) ||
1716 !mlir::isa<cir::FPTypeInterface>(srcTy))
1717 return castOp.emitError() <<
"NYI cast from " << srcTy <<
" to " << dstTy;
1719 auto getFloatWidth = [](mlir::Type ty) ->
unsigned {
1720 return mlir::cast<cir::FPTypeInterface>(ty).getWidth();
1723 bool isTrunc = getFloatWidth(srcTy) > getFloatWidth(dstTy);
1724 if (cir::FenvAttr fenv = castOp.getFenvAttr()) {
1728 castOp, llvmSrcVal, fenv, llvmDstTy, rewriter,
1729 isTrunc ?
"fptrunc" :
"fpext", isTrunc);
1732 rewriter.replaceOpWithNewOp<mlir::LLVM::FPTruncOp>(castOp, llvmDstTy,
1735 rewriter.replaceOpWithNewOp<mlir::LLVM::FPExtOp>(castOp, llvmDstTy,
1737 return mlir::success();
1739 case cir::CastKind::int_to_ptr: {
1740 auto dstTy = mlir::cast<cir::PointerType>(castOp.getType());
1741 mlir::Value llvmSrcVal = adaptor.getSrc();
1742 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1743 rewriter.replaceOpWithNewOp<mlir::LLVM::IntToPtrOp>(castOp, llvmDstTy,
1745 return mlir::success();
1747 case cir::CastKind::ptr_to_int: {
1748 auto dstTy = mlir::cast<cir::IntType>(castOp.getType());
1749 mlir::Value llvmSrcVal = adaptor.getSrc();
1750 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1751 rewriter.replaceOpWithNewOp<mlir::LLVM::PtrToIntOp>(castOp, llvmDstTy,
1753 return mlir::success();
1755 case cir::CastKind::float_to_bool: {
1756 mlir::Value llvmSrcVal = adaptor.getSrc();
1757 auto kind = mlir::LLVM::FCmpPredicate::une;
1762 auto zeroFloat = mlir::LLVM::ConstantOp::create(
1763 rewriter, castOp.getLoc(), llvmSrcVal.getType(),
1764 rewriter.getZeroAttr(llvmSrcVal.getType()));
1767 rewriter.replaceOpWithNewOp<mlir::LLVM::FCmpOp>(castOp,
kind, llvmSrcVal,
1770 return mlir::success();
1772 case cir::CastKind::bool_to_int: {
1773 mlir::Type dstTy = castOp.getType();
1774 mlir::Value llvmSrcVal = adaptor.getSrc();
1775 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1777 auto srcElemTy = mlir::cast<mlir::IntegerType>(
1778 elementTypeIfVector(llvmSrcVal.getType()));
1779 auto dstElemTy = mlir::cast<cir::IntType>(elementTypeIfVector(dstTy));
1781 if (srcElemTy.getWidth() == dstElemTy.getWidth())
1782 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(castOp, llvmDstTy,
1785 rewriter.replaceOpWithNewOp<mlir::LLVM::ZExtOp>(castOp, llvmDstTy,
1787 return mlir::success();
1789 case cir::CastKind::bool_to_float: {
1790 mlir::Type dstTy = castOp.getType();
1791 mlir::Value llvmSrcVal = adaptor.getSrc();
1792 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1793 rewriter.replaceOpWithNewOp<mlir::LLVM::UIToFPOp>(castOp, llvmDstTy,
1795 return mlir::success();
1797 case cir::CastKind::int_to_float: {
1798 mlir::Type dstTy = castOp.getType();
1799 mlir::Value llvmSrcVal = adaptor.getSrc();
1800 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1802 mlir::cast<cir::IntType>(elementTypeIfVector(castOp.getSrc().getType()))
1804 if (cir::FenvAttr fenv = castOp.getFenvAttr()) {
1806 castOp, llvmSrcVal, fenv, llvmDstTy, rewriter,
1807 isSigned ?
"sitofp" :
"uitofp",
true);
1810 rewriter.replaceOpWithNewOp<mlir::LLVM::SIToFPOp>(castOp, llvmDstTy,
1813 rewriter.replaceOpWithNewOp<mlir::LLVM::UIToFPOp>(castOp, llvmDstTy,
1815 return mlir::success();
1817 case cir::CastKind::float_to_int: {
1818 mlir::Type dstTy = castOp.getType();
1819 mlir::Value llvmSrcVal = adaptor.getSrc();
1820 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1822 mlir::cast<cir::IntType>(elementTypeIfVector(castOp.getType()))
1824 if (cir::FenvAttr fenv = castOp.getFenvAttr()) {
1826 castOp, llvmSrcVal, fenv, llvmDstTy, rewriter,
1827 isSigned ?
"fptosi" :
"fptoui",
false);
1830 rewriter.replaceOpWithNewOp<mlir::LLVM::FPToSIOp>(castOp, llvmDstTy,
1833 rewriter.replaceOpWithNewOp<mlir::LLVM::FPToUIOp>(castOp, llvmDstTy,
1835 return mlir::success();
1837 case cir::CastKind::bitcast: {
1838 mlir::Type dstTy = castOp.getType();
1839 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1844 mlir::Value llvmSrcVal = adaptor.getSrc();
1845 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(castOp, llvmDstTy,
1847 return mlir::success();
1849 case cir::CastKind::ptr_to_bool: {
1850 mlir::Value llvmSrcVal = adaptor.getSrc();
1851 mlir::Value zeroPtr = mlir::LLVM::ZeroOp::create(rewriter, castOp.getLoc(),
1852 llvmSrcVal.getType());
1853 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
1854 castOp, mlir::LLVM::ICmpPredicate::ne, llvmSrcVal, zeroPtr);
1857 case cir::CastKind::address_space: {
1858 mlir::Type dstTy = castOp.getType();
1859 mlir::Value llvmSrcVal = adaptor.getSrc();
1860 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1861 rewriter.replaceOpWithNewOp<mlir::LLVM::AddrSpaceCastOp>(castOp, llvmDstTy,
1865 case cir::CastKind::member_ptr_to_bool:
1870 return castOp.emitError(
"Unhandled cast kind: ")
1871 << castOp.getKindAttrName();
1875 return mlir::success();
1878mlir::LogicalResult CIRToLLVMBuiltinIntCastOpLowering::matchAndRewrite(
1879 cir::BuiltinIntCastOp op, OpAdaptor adaptor,
1880 mlir::ConversionPatternRewriter &rewriter)
const {
1885 if (
auto cirSrc = mlir::dyn_cast<cir::IntType>(op.getSrc().getType()))
1887 else if (
auto cirDst = mlir::dyn_cast<cir::IntType>(op.getType()))
1890 mlir::Value llvmSrc = adaptor.getSrc();
1891 mlir::Type llvmDstTy = getTypeConverter()->convertType(op.getType());
1892 auto srcIntTy = mlir::cast<mlir::IntegerType>(llvmSrc.getType());
1893 auto dstIntTy = mlir::cast<mlir::IntegerType>(llvmDstTy);
1894 unsigned srcWidth = srcIntTy.getWidth();
1895 unsigned dstWidth = dstIntTy.getWidth();
1900 assert((srcWidth == dstWidth ||
1901 mlir::isa<mlir::IndexType>(op.getSrc().getType()) ||
1902 mlir::isa<mlir::IndexType>(op.getType())) &&
1903 "only index casts may change width during lowering");
1908 srcWidth, dstWidth));
1909 return mlir::success();
1913 mlir::ModuleOp mod, mlir::Value index,
1914 mlir::Type baseTy, cir::IntType strideTy) {
1915 mlir::Operation *indexOp = index.getDefiningOp();
1919 auto indexType = mlir::cast<mlir::IntegerType>(index.getType());
1920 mlir::DataLayout llvmLayout(mod);
1921 std::optional<uint64_t> layoutWidth = llvmLayout.getTypeIndexBitwidth(baseTy);
1924 if (!layoutWidth || *layoutWidth == indexType.getWidth())
1930 auto sub = dyn_cast<mlir::LLVM::SubOp>(indexOp);
1931 bool rewriteSub =
false;
1933 if (
auto lhsConst = dyn_cast_if_present<mlir::LLVM::ConstantOp>(
1934 sub.getLhs().getDefiningOp())) {
1935 auto lhsConstInt = mlir::dyn_cast<mlir::IntegerAttr>(lhsConst.getValue());
1936 if (lhsConstInt && lhsConstInt.getValue() == 0) {
1937 index = sub.getRhs();
1943 auto llvmDstType = rewriter.getIntegerType(*layoutWidth);
1944 bool isUnsigned = strideTy && strideTy.isUnsigned();
1946 indexType.getWidth(), *layoutWidth);
1949 index = mlir::LLVM::SubOp::create(
1950 rewriter, index.getLoc(),
1951 mlir::LLVM::ConstantOp::create(rewriter, index.getLoc(),
1952 index.getType(), 0),
1959mlir::LogicalResult CIRToLLVMPtrStrideOpLowering::matchAndRewrite(
1960 cir::PtrStrideOp ptrStrideOp, OpAdaptor adaptor,
1961 mlir::ConversionPatternRewriter &rewriter)
const {
1963 const mlir::TypeConverter *tc = getTypeConverter();
1964 const mlir::Type resultTy = tc->convertType(ptrStrideOp.getType());
1966 mlir::Type elementTy =
1971 if (mlir::isa<mlir::LLVM::LLVMVoidType>(elementTy) ||
1972 mlir::isa<mlir::LLVM::LLVMFunctionType>(elementTy))
1973 elementTy = mlir::IntegerType::get(elementTy.getContext(), 8,
1974 mlir::IntegerType::Signless);
1976 mlir::Value index = adaptor.getStride();
1978 rewriter, ptrStrideOp->getParentOfType<mlir::ModuleOp>(), index,
1979 adaptor.getBase().getType(),
1980 dyn_cast<cir::IntType>(ptrStrideOp.getOperand(1).getType()));
1982 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1983 ptrStrideOp, resultTy, elementTy, adaptor.getBase(), index);
1984 return mlir::success();
1987mlir::LogicalResult CIRToLLVMGetElementOpLowering::matchAndRewrite(
1988 cir::GetElementOp op, OpAdaptor adaptor,
1989 mlir::ConversionPatternRewriter &rewriter)
const {
1991 mlir::dyn_cast<cir::ArrayType>(op.getBaseType().getPointee())) {
1992 const mlir::TypeConverter *converter = getTypeConverter();
1993 const mlir::Type llArrayTy = converter->convertType(arrayTy);
1994 const mlir::Type llResultTy = converter->convertType(op.getType());
1995 mlir::Type elementTy =
2000 if (mlir::isa<mlir::LLVM::LLVMVoidType>(elementTy) ||
2001 mlir::isa<mlir::LLVM::LLVMFunctionType>(elementTy))
2002 elementTy = rewriter.getIntegerType(8);
2004 mlir::Value index = adaptor.getIndex();
2007 adaptor.getBase().getType(),
2008 dyn_cast<cir::IntType>(op.getOperand(1).getType()));
2013 std::array<mlir::LLVM::GEPArg, 2> offset{0, index};
2014 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, llResultTy, llArrayTy,
2015 adaptor.getBase(), offset);
2016 return mlir::success();
2019 op.emitError() <<
"NYI: GetElementOp lowering to LLVM for non-array";
2020 return mlir::failure();
2023mlir::LogicalResult CIRToLLVMBaseClassAddrOpLowering::matchAndRewrite(
2024 cir::BaseClassAddrOp baseClassOp, OpAdaptor adaptor,
2025 mlir::ConversionPatternRewriter &rewriter)
const {
2026 const mlir::Type resultType =
2027 getTypeConverter()->convertType(baseClassOp.getType());
2028 mlir::Value derivedAddr = adaptor.getDerivedAddr();
2029 llvm::SmallVector<mlir::LLVM::GEPArg, 1> offset = {
2030 adaptor.getOffset().getZExtValue()};
2031 mlir::Type byteType = mlir::IntegerType::get(resultType.getContext(), 8,
2032 mlir::IntegerType::Signless);
2033 if (adaptor.getOffset().getZExtValue() == 0) {
2034 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(
2035 baseClassOp, resultType, adaptor.getDerivedAddr());
2036 return mlir::success();
2039 if (baseClassOp.getAssumeNotNull()) {
2040 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
2041 baseClassOp, resultType, byteType, derivedAddr, offset);
2043 auto loc = baseClassOp.getLoc();
2044 mlir::Value isNull = mlir::LLVM::ICmpOp::create(
2045 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, derivedAddr,
2046 mlir::LLVM::ZeroOp::create(rewriter, loc, derivedAddr.getType()));
2047 mlir::Value adjusted = mlir::LLVM::GEPOp::create(
2048 rewriter, loc, resultType, byteType, derivedAddr, offset);
2049 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(baseClassOp, isNull,
2050 derivedAddr, adjusted);
2052 return mlir::success();
2055mlir::LogicalResult CIRToLLVMDerivedClassAddrOpLowering::matchAndRewrite(
2056 cir::DerivedClassAddrOp derivedClassOp, OpAdaptor adaptor,
2057 mlir::ConversionPatternRewriter &rewriter)
const {
2058 const mlir::Type resultType =
2059 getTypeConverter()->convertType(derivedClassOp.getType());
2060 mlir::Value baseAddr = adaptor.getBaseAddr();
2063 int64_t offsetVal = -(adaptor.getOffset().getZExtValue());
2064 if (offsetVal == 0) {
2066 rewriter.replaceOp(derivedClassOp, baseAddr);
2067 return mlir::success();
2069 llvm::SmallVector<mlir::LLVM::GEPArg, 1> offset = {offsetVal};
2070 mlir::Type byteType = mlir::IntegerType::get(resultType.getContext(), 8,
2071 mlir::IntegerType::Signless);
2072 if (derivedClassOp.getAssumeNotNull()) {
2073 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
2074 derivedClassOp, resultType, byteType, baseAddr, offset,
2075 mlir::LLVM::GEPNoWrapFlags::inbounds);
2077 mlir::Location loc = derivedClassOp.getLoc();
2078 mlir::Value isNull = mlir::LLVM::ICmpOp::create(
2079 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, baseAddr,
2080 mlir::LLVM::ZeroOp::create(rewriter, loc, baseAddr.getType()));
2081 mlir::Value adjusted =
2082 mlir::LLVM::GEPOp::create(rewriter, loc, resultType, byteType, baseAddr,
2083 offset, mlir::LLVM::GEPNoWrapFlags::inbounds);
2084 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(derivedClassOp, isNull,
2085 baseAddr, adjusted);
2087 return mlir::success();
2090mlir::LogicalResult CIRToLLVMFMaxNumOpLowering::matchAndRewrite(
2091 cir::FMaxNumOp op, OpAdaptor adaptor,
2092 mlir::ConversionPatternRewriter &rewriter)
const {
2093 mlir::Type resTy = typeConverter->convertType(op.getType());
2094 if (cir::FenvAttr fenv = op.getFenvAttr())
2096 op, adaptor.getOperands(), fenv, resTy, rewriter,
"maxnum",
2097 false, mlir::LLVM::FastmathFlags::nsz);
2098 rewriter.replaceOpWithNewOp<mlir::LLVM::MaxNumOp>(
2099 op, resTy, adaptor.getLhs(), adaptor.getRhs(),
2100 mlir::LLVM::FastmathFlags::nsz);
2101 return mlir::success();
2104mlir::LogicalResult CIRToLLVMFMinNumOpLowering::matchAndRewrite(
2105 cir::FMinNumOp op, OpAdaptor adaptor,
2106 mlir::ConversionPatternRewriter &rewriter)
const {
2107 mlir::Type resTy = typeConverter->convertType(op.getType());
2108 if (cir::FenvAttr fenv = op.getFenvAttr())
2110 op, adaptor.getOperands(), fenv, resTy, rewriter,
"minnum",
2111 false, mlir::LLVM::FastmathFlags::nsz);
2112 rewriter.replaceOpWithNewOp<mlir::LLVM::MinNumOp>(
2113 op, resTy, adaptor.getLhs(), adaptor.getRhs(),
2114 mlir::LLVM::FastmathFlags::nsz);
2115 return mlir::success();
2118mlir::LogicalResult CIRToLLVMAllocaOpLowering::matchAndRewrite(
2119 cir::AllocaOp op, OpAdaptor adaptor,
2120 mlir::ConversionPatternRewriter &rewriter)
const {
2123 ? adaptor.getDynAllocSize()
2124 : mlir::LLVM::ConstantOp::create(
2125 rewriter, op.getLoc(),
2126 typeConverter->convertType(rewriter.getI32Type()), 1);
2127 mlir::Type elementTy =
2130 return op.emitError()
2131 <<
"NYI: lowering alloca of a type with no memory representation";
2132 mlir::Type resultTy =
2138 rewriter.replaceOpWithNewOp<mlir::LLVM::AllocaOp>(op, resultTy, elementTy,
2139 size, op.getAlignment());
2141 return mlir::success();
2144mlir::LogicalResult CIRToLLVMRotateOpLowering::matchAndRewrite(
2145 cir::RotateOp op, OpAdaptor adaptor,
2146 mlir::ConversionPatternRewriter &rewriter)
const {
2149 mlir::Value input = adaptor.getInput();
2150 if (op.isRotateLeft())
2151 rewriter.replaceOpWithNewOp<mlir::LLVM::FshlOp>(op, input, input,
2152 adaptor.getAmount());
2154 rewriter.replaceOpWithNewOp<mlir::LLVM::FshrOp>(op, input, input,
2155 adaptor.getAmount());
2156 return mlir::LogicalResult::success();
2169 mlir::ArrayAttr argAttrs,
const mlir::TypeConverter &converter,
2170 const mlir::DataLayout &dataLayout, mlir::MLIRContext *ctx) {
2173 bool changed =
false;
2175 loweredArgAttrs.reserve(argAttrs.size());
2176 for (mlir::Attribute a : argAttrs) {
2177 auto dict = cast<mlir::DictionaryAttr>(a);
2179 for (mlir::NamedAttribute &entry : entries) {
2180 StringRef name = entry.getName().strref();
2181 if (name != mlir::LLVM::LLVMDialect::getByValAttrName() &&
2182 name != mlir::LLVM::LLVMDialect::getStructRetAttrName() &&
2183 name != mlir::LLVM::LLVMDialect::getByRefAttrName())
2185 auto typeAttr = dyn_cast<mlir::TypeAttr>(entry.getValue());
2188 mlir::Type lowered =
2191 return std::nullopt;
2192 if (lowered != typeAttr.getValue()) {
2193 entry.setValue(mlir::TypeAttr::get(lowered));
2197 loweredArgAttrs.push_back(mlir::DictionaryAttr::get(ctx, entries));
2199 return changed ? mlir::ArrayAttr::get(ctx, loweredArgAttrs) : argAttrs;
2209 cir::CIRCallOpInterface op,
const mlir::TypeConverter &converter,
2211 if (
auto argAttrs = mlir::dyn_cast_if_present<mlir::ArrayAttr>(
2212 op->getInherentAttr(CIRDialect::getArgAttrsAttrName())
2213 .value_or(mlir::Attribute{}))) {
2214 std::optional<mlir::ArrayAttr> lowered =
2217 return op->emitError() <<
"NYI: lowering a byval/sret/byref call "
2218 "argument whose pointee type has no "
2219 "memory representation";
2222 result.
resAttrs = mlir::dyn_cast_if_present<mlir::ArrayAttr>(
2223 op->getInherentAttr(CIRDialect::getResAttrsAttrName())
2224 .value_or(mlir::Attribute{}));
2226 for (mlir::NamedAttribute attr : op->getDiscardableAttrs()) {
2227 if (attr.getName() == CIRDialect::getNoUnwindAttrName() ||
2228 attr.getName() == CIRDialect::getNoReturnAttrName())
2233 return mlir::success();
2236template <
typename CallLikeOp>
2240 op.setArgAttrsAttr(attributes.
argAttrs);
2242 op.setResAttrsAttr(attributes.
resAttrs);
2244 if (op->getInherentAttr(attr.getName()).has_value())
2245 op->setInherentAttr(attr.getName(), attr.getValue());
2247 op->setDiscardableAttr(attr.getName(), attr.getValue());
2252 mlir::Operation *op, mlir::ValueRange callOperands,
2253 mlir::ConversionPatternRewriter &rewriter,
2254 const mlir::TypeConverter *converter,
const mlir::DataLayout &dataLayout,
2255 mlir::SymbolTableCollection &symbolTables,
2256 mlir::FlatSymbolRefAttr calleeAttr, mlir::Block *continueBlock =
nullptr,
2257 mlir::Block *landingPadBlock =
nullptr) {
2259 mlir::ValueTypeRange<mlir::ResultRange> cirResults = op->getResultTypes();
2260 auto call = cast<cir::CIRCallOpInterface>(op);
2262 if (converter->convertTypes(cirResults, llvmResults).failed())
2263 return mlir::failure();
2267 mlir::LLVM::MemoryEffectsAttr memoryEffects;
2268 bool noUnwind =
false;
2269 bool willReturn =
false;
2270 bool noReturn =
false;
2272 memoryEffects, noUnwind, willReturn, noReturn);
2277 return mlir::failure();
2279 mlir::LLVM::LLVMFunctionType llvmFnTy;
2286 mlir::Operation *callee =
2287 symbolTables.lookupNearestSymbolFrom(op, calleeAttr);
2288 if (
auto fn = mlir::dyn_cast<mlir::FunctionOpInterface>(callee)) {
2289 llvmFnTy = converter->convertType<mlir::LLVM::LLVMFunctionType>(
2290 fn.getFunctionType());
2291 assert(llvmFnTy &&
"Failed to convert function type");
2292 }
else if (
auto alias = mlir::cast<mlir::LLVM::AliasOp>(callee)) {
2300 auto symAttr = mlir::cast<mlir::FlatSymbolRefAttr>(calleeAttr);
2302 mlir::LLVM::AddressOfOp::create(
2303 rewriter, op->getLoc(),
2304 mlir::LLVM::LLVMPointerType::get(rewriter.getContext()), symAttr)
2306 adjustedCallOperands.push_back(addrOfAlias);
2309 llvm::append_range(adjustedCallOperands, callOperands);
2310 callOperands = adjustedCallOperands;
2314 llvmFnTy = mlir::cast<mlir::LLVM::LLVMFunctionType>(alias.getType());
2317 return op->emitError(
"Unexpected callee type!");
2320 assert(!op->getOperands().empty() &&
2321 "operands list must no be empty for the indirect call");
2322 auto calleeTy = op->getOperands().front().getType();
2323 auto calleePtrTy = cast<cir::PointerType>(calleeTy);
2324 auto calleeFuncTy = cast<cir::FuncType>(calleePtrTy.getPointee());
2325 llvm::append_range(adjustedCallOperands, callOperands);
2326 llvmFnTy = cast<mlir::LLVM::LLVMFunctionType>(
2327 converter->convertType(calleeFuncTy));
2332 if (landingPadBlock) {
2334 auto newOp = rewriter.replaceOpWithNewOp<mlir::LLVM::InvokeOp>(
2335 op, llvmFnTy, calleeAttr, callOperands, continueBlock,
2336 mlir::ValueRange{}, landingPadBlock, mlir::ValueRange{});
2339 auto newOp = rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(
2340 op, llvmFnTy, calleeAttr, callOperands);
2343 newOp.setMemoryEffectsAttr(memoryEffects);
2344 newOp.setNoUnwind(noUnwind);
2345 newOp.setWillReturn(willReturn);
2346 newOp.setNoreturn(noReturn);
2347 if (op->hasAttr(CIRDialect::getMustTailAttrName()))
2348 newOp.setTailCallKind(mlir::LLVM::TailCallKind::MustTail);
2350 if (std::optional<cir::InlineKind> inlineKind = call.getInlineKind()) {
2351 newOp.setNoInline(*inlineKind == cir::InlineKind::NoInline);
2352 newOp.setInlineHint(*inlineKind == cir::InlineKind::InlineHint);
2353 newOp.setAlwaysInline(*inlineKind == cir::InlineKind::AlwaysInline);
2357 return mlir::success();
2360mlir::LogicalResult CIRToLLVMCallOpLowering::matchAndRewrite(
2361 cir::CallOp op, OpAdaptor adaptor,
2362 mlir::ConversionPatternRewriter &rewriter)
const {
2364 getTypeConverter(), dataLayout, symbolTables,
2365 op.getCalleeAttr());
2368mlir::LogicalResult CIRToLLVMTryCallOpLowering::matchAndRewrite(
2369 cir::TryCallOp op, OpAdaptor adaptor,
2370 mlir::ConversionPatternRewriter &rewriter)
const {
2373 getTypeConverter(), dataLayout, symbolTables,
2374 op.getCalleeAttr(), op.getNormalDest(),
2375 op.getUnwindDest());
2378mlir::LogicalResult CIRToLLVMReturnAddrOpLowering::matchAndRewrite(
2379 cir::ReturnAddrOp op, OpAdaptor adaptor,
2380 mlir::ConversionPatternRewriter &rewriter)
const {
2381 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
2383 llvmPtrTy, adaptor.getOperands());
2384 return mlir::success();
2387mlir::LogicalResult CIRToLLVMFrameAddrOpLowering::matchAndRewrite(
2388 cir::FrameAddrOp op, OpAdaptor adaptor,
2389 mlir::ConversionPatternRewriter &rewriter)
const {
2390 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
2392 adaptor.getOperands());
2393 return mlir::success();
2396mlir::LogicalResult CIRToLLVMClearCacheOpLowering::matchAndRewrite(
2397 cir::ClearCacheOp op, OpAdaptor adaptor,
2398 mlir::ConversionPatternRewriter &rewriter)
const {
2399 mlir::Value begin = adaptor.getBegin();
2400 mlir::Value end = adaptor.getEnd();
2401 auto intrinNameAttr =
2402 mlir::StringAttr::get(op.getContext(),
"llvm.clear_cache");
2403 rewriter.replaceOpWithNewOp<mlir::LLVM::CallIntrinsicOp>(
2404 op, mlir::Type{}, intrinNameAttr, mlir::ValueRange{begin, end});
2406 return mlir::success();
2409mlir::LogicalResult CIRToLLVMAddrOfReturnAddrOpLowering::matchAndRewrite(
2410 cir::AddrOfReturnAddrOp op, OpAdaptor adaptor,
2411 mlir::ConversionPatternRewriter &rewriter)
const {
2412 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
2414 llvmPtrTy, adaptor.getOperands());
2415 return mlir::success();
2418mlir::LogicalResult CIRToLLVMLoadOpLowering::matchAndRewrite(
2419 cir::LoadOp op, OpAdaptor adaptor,
2420 mlir::ConversionPatternRewriter &rewriter)
const {
2421 const mlir::Type llvmTy =
2424 return op.emitError()
2425 <<
"NYI: lowering load of a type with no memory representation";
2426 mlir::LLVM::AtomicOrdering ordering =
getLLVMMemOrder(op.getMemOrder());
2427 std::optional<size_t> opAlign = op.getAlignment();
2428 unsigned alignment = (unsigned)opAlign.value_or(
2433 std::optional<llvm::StringRef> llvmSyncScope =
2436 mlir::LLVM::LoadOp newLoad = mlir::LLVM::LoadOp::create(
2437 rewriter, op->getLoc(), llvmTy, adaptor.getAddr(), alignment,
2438 op.getIsVolatile(), op.getIsNontemporal(),
2439 op.getInvariant(),
false, ordering,
2440 llvmSyncScope.value_or(std::string()));
2441 if (mlir::Attribute domain = op->getAttr(
"cir.riscv_nontemporal_domain"))
2442 newLoad->setAttr(
"cir.riscv_nontemporal_domain", domain);
2445 mlir::Value result =
emitFromMemory(rewriter, *getTypeConverter(), dataLayout,
2446 op, newLoad.getResult());
2447 rewriter.replaceOp(op, result);
2449 return mlir::LogicalResult::success();
2453cir::direct::CIRToLLVMVecMaskedLoadOpLowering::matchAndRewrite(
2454 cir::VecMaskedLoadOp op, OpAdaptor adaptor,
2455 mlir::ConversionPatternRewriter &rewriter)
const {
2456 const mlir::Type llvmResTy =
2459 return op.emitError()
2460 <<
"NYI: lowering masked load of a type with no memory "
2463 std::optional<size_t> opAlign = op.getAlignment();
2464 unsigned alignment =
2465 (unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmResTy));
2467 auto newLoad = mlir::LLVM::MaskedLoadOp::create(
2468 rewriter, op.getLoc(), llvmResTy, adaptor.getAddr(), adaptor.getMask(),
2469 adaptor.getPassThru(), alignment);
2471 rewriter.replaceOp(op, newLoad.getResult());
2472 return mlir::success();
2475mlir::LogicalResult CIRToLLVMStoreOpLowering::matchAndRewrite(
2476 cir::StoreOp op, OpAdaptor adaptor,
2477 mlir::ConversionPatternRewriter &rewriter)
const {
2478 mlir::LLVM::AtomicOrdering memorder =
getLLVMMemOrder(op.getMemOrder());
2479 mlir::Type valueType = op.getValue().getType();
2480 const mlir::Type llvmTy =
2483 return op.emitError()
2484 <<
"NYI: lowering store of a type with no memory representation";
2485 std::optional<size_t> opAlign = op.getAlignment();
2486 unsigned alignment = (unsigned)opAlign.value_or(
2493 op.getValue().getType(), adaptor.getValue());
2496 std::optional<llvm::StringRef> llvmSyncScope =
2499 mlir::LLVM::StoreOp storeOp = mlir::LLVM::StoreOp::create(
2500 rewriter, op->getLoc(), value, adaptor.getAddr(), alignment,
2502 op.getIsNontemporal(),
false,
2503 memorder, llvmSyncScope.value_or(std::string()));
2504 if (mlir::Attribute domain = op->getAttr(
"cir.riscv_nontemporal_domain"))
2505 storeOp->setAttr(
"cir.riscv_nontemporal_domain", domain);
2506 rewriter.replaceOp(op, storeOp);
2508 return mlir::LogicalResult::success();
2512 while (
auto arrTy = mlir::dyn_cast<cir::ArrayType>(ty))
2513 ty = arrTy.getElementType();
2518 return mlir::isa<cir::PointerType, cir::IntType, cir::BoolType,
2522mlir::LogicalResult CIRToLLVMConstantOpLowering::matchAndRewrite(
2523 cir::ConstantOp op, OpAdaptor adaptor,
2524 mlir::ConversionPatternRewriter &rewriter)
const {
2525 mlir::Attribute attr = op.getValue();
2527 if (mlir::isa<cir::PoisonAttr>(attr)) {
2528 rewriter.replaceOpWithNewOp<mlir::LLVM::PoisonOp>(
2529 op, getTypeConverter()->convertType(op.getType()));
2530 return mlir::success();
2533 if (mlir::isa<cir::UndefAttr>(attr)) {
2534 rewriter.replaceOpWithNewOp<mlir::LLVM::UndefOp>(
2535 op, getTypeConverter()->convertType(op.getType()));
2536 return mlir::success();
2539 if (mlir::isa<mlir::IntegerType>(op.getType())) {
2544 attr = op.getValue();
2545 }
else if (mlir::isa<cir::BoolType>(op.getType())) {
2546 int value = mlir::cast<cir::BoolAttr>(op.getValue()).getValue();
2547 attr = rewriter.getIntegerAttr(typeConverter->convertType(op.getType()),
2549 }
else if (mlir::isa<cir::IntType>(op.getType())) {
2551 if (
auto gv = mlir::dyn_cast<cir::GlobalViewAttr>(op.getValue())) {
2553 getTypeConverter());
2554 rewriter.replaceOp(op, newOp);
2555 return mlir::success();
2558 attr = rewriter.getIntegerAttr(
2559 typeConverter->convertType(op.getType()),
2560 mlir::cast<cir::IntAttr>(op.getValue()).getValue());
2561 }
else if (mlir::isa<cir::FPTypeInterface>(op.getType())) {
2562 attr = rewriter.getFloatAttr(
2563 typeConverter->convertType(op.getType()),
2564 mlir::cast<cir::FPAttr>(op.getValue()).getValue());
2565 }
else if (mlir::isa<cir::PointerType>(op.getType())) {
2567 if (mlir::isa<cir::ConstPtrAttr>(op.getValue())) {
2568 if (mlir::cast<cir::ConstPtrAttr>(op.getValue()).isNullValue()) {
2569 rewriter.replaceOpWithNewOp<mlir::LLVM::ZeroOp>(
2570 op, typeConverter->convertType(op.getType()));
2571 return mlir::success();
2575 if (mlir::isa<cir::GlobalViewAttr, cir::GlobalOffsetAttr>(op.getValue())) {
2577 symbolTables, getTypeConverter());
2578 rewriter.replaceOp(op, newOp);
2579 return mlir::success();
2581 attr = op.getValue();
2582 }
else if (
const auto arrTy = mlir::dyn_cast<cir::ArrayType>(op.getType())) {
2583 const auto constArr = mlir::dyn_cast<cir::ConstArrayAttr>(op.getValue());
2584 if (!constArr && !isa<cir::ZeroAttr, cir::UndefAttr>(op.getValue()))
2585 return op.emitError() <<
"array does not have a constant initializer";
2587 std::optional<mlir::Attribute> denseAttr;
2590 attr = denseAttr.value();
2593 op, op.getValue(), rewriter, symbolTables, typeConverter);
2594 rewriter.replaceOp(op, initVal);
2595 return mlir::success();
2597 }
else if (
const auto recordAttr =
2598 mlir::dyn_cast<cir::ConstRecordAttr>(op.getValue())) {
2601 rewriter.replaceOp(op, initVal);
2602 return mlir::success();
2603 }
else if (
const auto vecTy = mlir::dyn_cast<cir::VectorType>(op.getType())) {
2604 rewriter.replaceOp(op,
2606 symbolTables, getTypeConverter()));
2607 return mlir::success();
2608 }
else if (mlir::isa<cir::RecordType>(op.getType())) {
2609 if (mlir::isa<cir::ZeroAttr, cir::UndefAttr>(attr)) {
2610 mlir::Value initVal =
2612 rewriter.replaceOp(op, initVal);
2613 return mlir::success();
2615 return op.emitError() <<
"unsupported lowering for record constant type "
2617 }
else if (
auto complexTy = mlir::dyn_cast<cir::ComplexType>(op.getType())) {
2618 mlir::Type complexElemTy = complexTy.getElementType();
2619 mlir::Type complexElemLLVMTy = typeConverter->convertType(complexElemTy);
2621 if (
auto zeroInitAttr = mlir::dyn_cast<cir::ZeroAttr>(op.getValue())) {
2622 mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(complexElemLLVMTy);
2623 mlir::ArrayAttr array = rewriter.getArrayAttr({zeroAttr, zeroAttr});
2624 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
2625 op, getTypeConverter()->convertType(op.getType()), array);
2626 return mlir::success();
2629 if (mlir::isa<cir::UndefAttr>(op.getValue())) {
2630 rewriter.replaceOpWithNewOp<mlir::LLVM::UndefOp>(
2631 op, getTypeConverter()->convertType(op.getType()));
2632 return mlir::success();
2635 auto complexAttr = mlir::cast<cir::ConstComplexAttr>(op.getValue());
2637 mlir::Attribute components[2];
2638 if (mlir::isa<cir::IntType>(complexElemTy)) {
2639 components[0] = rewriter.getIntegerAttr(
2641 mlir::cast<cir::IntAttr>(complexAttr.getReal()).getValue());
2642 components[1] = rewriter.getIntegerAttr(
2644 mlir::cast<cir::IntAttr>(complexAttr.getImag()).getValue());
2646 components[0] = rewriter.getFloatAttr(
2648 mlir::cast<cir::FPAttr>(complexAttr.getReal()).getValue());
2649 components[1] = rewriter.getFloatAttr(
2651 mlir::cast<cir::FPAttr>(complexAttr.getImag()).getValue());
2654 attr = rewriter.getArrayAttr(components);
2656 return op.emitError() <<
"unsupported constant type " << op.getType();
2659 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
2660 op, getTypeConverter()->convertType(op.getType()),
attr);
2662 return mlir::success();
2666 mlir::DataLayout layout(op.getParentOfType<mlir::ModuleOp>());
2668 if (isa<cir::VoidType>(type))
2669 type = cir::IntType::get(type.getContext(), 8,
false);
2670 return llvm::divideCeil(layout.getTypeSizeInBits(type), 8);
2673mlir::LogicalResult CIRToLLVMPrefetchOpLowering::matchAndRewrite(
2674 cir::PrefetchOp op, OpAdaptor adaptor,
2675 mlir::ConversionPatternRewriter &rewriter)
const {
2676 rewriter.replaceOpWithNewOp<mlir::LLVM::Prefetch>(
2677 op, adaptor.getAddr(), adaptor.getIsWrite(), adaptor.getLocality(),
2679 return mlir::success();
2682mlir::LogicalResult CIRToLLVMPtrDiffOpLowering::matchAndRewrite(
2683 cir::PtrDiffOp op, OpAdaptor adaptor,
2684 mlir::ConversionPatternRewriter &rewriter)
const {
2685 auto dstTy = mlir::cast<cir::IntType>(op.getType());
2686 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
2688 auto lhs = mlir::LLVM::PtrToIntOp::create(rewriter, op.getLoc(), llvmDstTy,
2690 auto rhs = mlir::LLVM::PtrToIntOp::create(rewriter, op.getLoc(), llvmDstTy,
2694 mlir::LLVM::SubOp::create(rewriter, op.getLoc(), llvmDstTy, lhs, rhs);
2696 cir::PointerType ptrTy = op.getLhs().getType();
2698 uint64_t typeSize =
getTypeSize(ptrTy.getPointee(), *op);
2701 mlir::Value resultVal = diff.getResult();
2702 if (typeSize != 1) {
2703 auto typeSizeVal = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
2704 llvmDstTy, typeSize);
2706 if (dstTy.isUnsigned()) {
2708 mlir::LLVM::UDivOp::create(rewriter, op.getLoc(), diff, typeSizeVal);
2709 uDiv.setIsExact(
true);
2710 resultVal = uDiv.getResult();
2713 mlir::LLVM::SDivOp::create(rewriter, op.getLoc(), diff, typeSizeVal);
2714 sDiv.setIsExact(
true);
2715 resultVal = sDiv.getResult();
2718 rewriter.replaceOp(op, resultVal);
2719 return mlir::success();
2722mlir::LogicalResult CIRToLLVMExpectOpLowering::matchAndRewrite(
2723 cir::ExpectOp op, OpAdaptor adaptor,
2724 mlir::ConversionPatternRewriter &rewriter)
const {
2728 std::optional<llvm::APFloat> prob = op.getProb();
2730 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpectWithProbabilityOp>(
2731 op, adaptor.getVal(), adaptor.getExpected(), prob.value());
2733 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpectOp>(op, adaptor.getVal(),
2734 adaptor.getExpected());
2735 return mlir::success();
2738mlir::LogicalResult CIRToLLVMAbsOpLowering::matchAndRewrite(
2739 cir::AbsOp op, OpAdaptor adaptor,
2740 mlir::ConversionPatternRewriter &rewriter)
const {
2741 mlir::Type resTy = typeConverter->convertType(op.getType());
2742 auto absOp = mlir::LLVM::AbsOp::create(rewriter, op.getLoc(), resTy,
2743 adaptor.getOperands()[0],
2744 adaptor.getMinIsPoison());
2745 rewriter.replaceOp(op, absOp);
2746 return mlir::success();
2751 return attr.getName() == CIRDialect::getNoReturnAttrName() ||
2752 attr.getName() == CIRDialect::getNoUnwindAttrName() ||
2753 attr.getName() == CIRDialect::getWillReturnAttrName() ||
2754 attr.getName() == CIRDialect::getStrictFPAttrName() ||
2755 attr.getName() == CIRDialect::getNoRecurseAttrName() ||
2756 attr.getName() == CIRDialect::getMustProgressAttrName() ||
2757 attr.getName() == CIRDialect::getNoBuiltinAttrName() ||
2758 attr.getName() == CIRDialect::getSYCLModuleIdAttrName();
2766mlir::LogicalResult CIRToLLVMFuncOpLowering::lowerFuncAttributes(
2767 cir::FuncOp func,
bool includeFunctionOnlyAttrs,
2769 OpenCLFunctionMetadataLowering openCLMetadataLowering(func.getContext());
2770 for (mlir::NamedAttribute attr : func->getDiscardableAttrs()) {
2773 if (openCLMetadataLowering.lower(attr, includeFunctionOnlyAttrs))
2776 result.push_back(attr);
2779 if (mlir::StringAttr visibility = func.getSymVisibilityAttr())
2780 result.emplace_back(func.getSymVisibilityAttrName(), visibility);
2782 if (includeFunctionOnlyAttrs) {
2783 if (mlir::ArrayAttr argAttrs = func.getArgAttrsAttr()) {
2785 argAttrs, *getTypeConverter(), dataLayout, getContext());
2787 return func.emitError() <<
"NYI: lowering a byval/sret/byref "
2788 "argument whose pointee type has no "
2789 "memory representation";
2790 result.emplace_back(func.getArgAttrsAttrName(), *lowered);
2792 if (mlir::ArrayAttr resAttrs = func.getResAttrsAttr())
2793 result.emplace_back(func.getResAttrsAttrName(), resAttrs);
2796 if (includeFunctionOnlyAttrs)
2797 openCLMetadataLowering.appendAttrs(result);
2799 return mlir::success();
2802mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewriteAlias(
2803 cir::FuncOp op, llvm::StringRef aliasee, mlir::Type ty, OpAdaptor adaptor,
2804 mlir::ConversionPatternRewriter &rewriter)
const {
2805 SmallVector<mlir::NamedAttribute, 4> attributes;
2806 if (mlir::failed(lowerFuncAttributes(op,
false,
2808 return mlir::failure();
2810 mlir::Location loc = op.getLoc();
2811 auto aliasOp = rewriter.replaceOpWithNewOp<mlir::LLVM::AliasOp>(
2812 op, ty,
convertLinkage(op.getLinkage()), op.getName(), op.getDsoLocal(),
2813 mlir::LLVM::ThreadLocalMode::NotThreadLocal, attributes);
2816 mlir::OpBuilder builder(op.getContext());
2817 mlir::Block *block = builder.createBlock(&aliasOp.getInitializerRegion());
2818 builder.setInsertionPointToStart(block);
2821 mlir::Type ptrTy = mlir::LLVM::LLVMPointerType::get(ty.getContext());
2822 auto addrOp = mlir::LLVM::AddressOfOp::create(builder, loc, ptrTy, aliasee);
2823 mlir::LLVM::ReturnOp::create(builder, loc, addrOp);
2825 return mlir::success();
2828mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewrite(
2829 cir::FuncOp op, OpAdaptor adaptor,
2830 mlir::ConversionPatternRewriter &rewriter)
const {
2832 cir::FuncType fnType = op.getFunctionType();
2833 bool isDsoLocal = op.getDsoLocal();
2834 mlir::TypeConverter::SignatureConversion signatureConversion(
2835 fnType.getNumInputs());
2837 for (
const auto &argType : llvm::enumerate(fnType.getInputs())) {
2838 mlir::Type convertedType = typeConverter->convertType(argType.value());
2840 return mlir::failure();
2841 signatureConversion.addInputs(argType.index(), convertedType);
2844 mlir::Type resultType =
2845 getTypeConverter()->convertType(fnType.getReturnType());
2848 mlir::Type llvmFnTy = mlir::LLVM::LLVMFunctionType::get(
2849 resultType ? resultType : mlir::LLVM::LLVMVoidType::get(getContext()),
2850 signatureConversion.getConvertedTypes(),
2854 if (std::optional<llvm::StringRef> aliasee = op.getAliasee())
2855 return matchAndRewriteAlias(op, *aliasee, llvmFnTy, adaptor, rewriter);
2859 mlir::Location loc = op.getLoc();
2860 if (mlir::FusedLoc fusedLoc = mlir::dyn_cast<mlir::FusedLoc>(loc))
2861 loc = fusedLoc.getLocations()[0];
2862 assert((mlir::isa<mlir::FileLineColLoc>(loc) ||
2863 mlir::isa<mlir::UnknownLoc>(loc)) &&
2864 "expected single location or unknown location here");
2868 SmallVector<mlir::NamedAttribute, 4> attributes;
2869 if (mlir::failed(lowerFuncAttributes(op,
true,
2871 return mlir::failure();
2873 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
2875 mlir::LLVM::LLVMFuncOp fn = mlir::LLVM::LLVMFuncOp::create(
2876 rewriter, loc, op.getName(), llvmFnTy, linkage, isDsoLocal, cconv,
2877 comdatAttr, attributes);
2881 if (cir::MemoryEffectsAttr effects = op.getMemoryEffectsAttr())
2884 if (op->hasAttr(CIRDialect::getNoUnwindAttrName()))
2885 fn.setNoUnwind(
true);
2886 if (op->hasAttr(CIRDialect::getWillReturnAttrName()))
2887 fn.setWillReturn(
true);
2889 if (op->hasAttr(CIRDialect::getNoReturnAttrName()))
2890 fn.setNoreturn(
true);
2896 SmallVector<mlir::Attribute> passthrough;
2897 for (llvm::StringRef flagAttr :
2898 {CIRDialect::getStrictFPAttrName(), CIRDialect::getNoRecurseAttrName(),
2899 CIRDialect::getMustProgressAttrName(),
2900 CIRDialect::getNoBuiltinAttrName()})
2901 if (op->hasAttr(flagAttr))
2902 passthrough.push_back(rewriter.getStringAttr(flagAttr));
2904 if (
auto moduleId = op->getAttrOfType<mlir::StringAttr>(
2905 CIRDialect::getSYCLModuleIdAttrName()))
2906 passthrough.push_back(rewriter.getArrayAttr(
2907 {rewriter.getStringAttr(CIRDialect::getSYCLModuleIdAttrName()),
2910 if (!passthrough.empty())
2911 fn.setPassthroughAttr(rewriter.getArrayAttr(passthrough));
2913 if (std::optional<cir::InlineKind> inlineKind = op.getInlineKind()) {
2914 fn.setNoInline(*inlineKind == cir::InlineKind::NoInline);
2915 fn.setInlineHint(*inlineKind == cir::InlineKind::InlineHint);
2916 fn.setAlwaysInline(*inlineKind == cir::InlineKind::AlwaysInline);
2919 if (std::optional<llvm::StringRef> personality = op.getPersonality())
2920 fn.setPersonality(*personality);
2925 fn.setAlignment(op.getAlignment());
2928 rewriter.inlineRegionBefore(op.getBody(), fn.getBody(), fn.end());
2929 if (failed(rewriter.convertRegionTypes(&fn.getBody(), *typeConverter,
2930 &signatureConversion)))
2931 return mlir::failure();
2933 rewriter.eraseOp(op);
2935 return mlir::LogicalResult::success();
2938mlir::LogicalResult CIRToLLVMGetGlobalOpLowering::matchAndRewrite(
2939 cir::GetGlobalOp op, OpAdaptor adaptor,
2940 mlir::ConversionPatternRewriter &rewriter)
const {
2943 if (op->getUses().empty()) {
2944 rewriter.eraseOp(op);
2945 return mlir::success();
2948 mlir::Type
type = getTypeConverter()->convertType(op.getType());
2949 mlir::Operation *newop = mlir::LLVM::AddressOfOp::create(
2950 rewriter, op.getLoc(), type, op.getName());
2954 newop = mlir::LLVM::ThreadlocalAddressOp::create(rewriter, op.getLoc(),
2955 type, newop->getResult(0));
2958 rewriter.replaceOp(op, newop);
2959 return mlir::success();
2962llvm::SmallVector<mlir::NamedAttribute>
2963CIRToLLVMGlobalOpLowering::lowerGlobalAttributes(
2964 cir::GlobalOp op, mlir::ConversionPatternRewriter &rewriter)
const {
2965 SmallVector<mlir::NamedAttribute> attributes;
2967 if (mlir::StringAttr sectionAttr = op.getSectionAttr())
2968 attributes.push_back(rewriter.getNamedAttr(
"section", sectionAttr));
2970 mlir::LLVM::VisibilityAttr visibility = mlir::LLVM::VisibilityAttr::get(
2973 attributes.push_back(rewriter.getNamedAttr(
"visibility_", visibility));
2975 if (op->getAttr(CUDAExternallyInitializedAttr::getMnemonic()))
2976 attributes.push_back(rewriter.getNamedAttr(
"externally_initialized",
2977 rewriter.getUnitAttr()));
2982static mlir::LLVM::ThreadLocalMode
2985#define CHECK_ENUM(CIR, LLVM_VAL) \
2986 static_assert(static_cast<unsigned>(TLSModel::CIR) == \
2987 static_cast<unsigned>(mlir::LLVM::ThreadLocalMode::LLVM_VAL))
2995 return mlir::LLVM::ThreadLocalMode::NotThreadLocal;
2997 return static_cast<mlir::LLVM::ThreadLocalMode
>(attr.getValue());
3002void CIRToLLVMGlobalOpLowering::setupRegionInitializedLLVMGlobalOp(
3003 cir::GlobalOp op, mlir::ConversionPatternRewriter &rewriter)
const {
3004 mlir::Type llvmType =
3009 if (std::optional<mlir::Attribute> init = op.getInitialValue())
3017 const bool isConst = op.getConstant();
3018 unsigned addrSpace = 0;
3019 if (
auto targetAS = mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
3020 op.getAddrSpaceAttr()))
3021 addrSpace = targetAS.getValue();
3022 const bool isDsoLocal = op.getDsoLocal();
3023 mlir::LLVM::ThreadLocalMode threadLocalMode =
3025 const uint64_t alignment = op.getAlignment().value_or(0);
3026 const mlir::LLVM::Linkage linkage =
convertLinkage(op.getLinkage());
3027 const StringRef symbol = op.getSymName();
3028 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
3031 lowerGlobalAttributes(op, rewriter);
3033 mlir::LLVM::GlobalOp newGlobalOp =
3034 rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
3035 op, llvmType, isConst, linkage, symbol,
nullptr, alignment, addrSpace,
3036 isDsoLocal, threadLocalMode, comdatAttr, attributes);
3037 newGlobalOp.getRegion().emplaceBlock();
3038 rewriter.setInsertionPointToEnd(newGlobalOp.getInitializerBlock());
3042CIRToLLVMGlobalOpLowering::matchAndRewriteRegionInitializedGlobal(
3043 cir::GlobalOp op, mlir::Attribute init,
3044 mlir::ConversionPatternRewriter &rewriter)
const {
3046 assert((isa<cir::BlockAddrDiffAttr, cir::BlockAddrInfoAttr,
3047 cir::ConstArrayAttr, cir::ConstRecordAttr, cir::ConstVectorAttr,
3048 cir::ConstPtrAttr, cir::ConstComplexAttr, cir::GlobalOffsetAttr,
3049 cir::GlobalViewAttr, cir::TypeInfoAttr, cir::UndefAttr,
3050 cir::PoisonAttr, cir::VTableAttr, cir::ZeroAttr>(init)));
3055 const mlir::Location loc = op.getLoc();
3056 setupRegionInitializedLLVMGlobalOp(op, rewriter);
3061 CIRAttrToValue valueConverter(op, rewriter, symbolTables, typeConverter,
3063 mlir::Value value = valueConverter.visit(init);
3064 mlir::LLVM::ReturnOp::create(rewriter, loc, value);
3065 return mlir::success();
3068mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite(
3069 cir::GlobalOp op, OpAdaptor adaptor,
3070 mlir::ConversionPatternRewriter &rewriter)
const {
3071 if (mlir::isa_and_present<cir::LangAddressSpaceAttr>(op.getAddrSpaceAttr()))
3072 return op.emitError()
3073 <<
"cannot lower a global with a language address space";
3077 if (!op.getCtorRegion().empty() || !op.getDtorRegion().empty())
3078 return op.emitError() <<
"GlobalOp ctor and dtor regions should be removed "
3079 "in LoweringPrepare";
3081 std::optional<mlir::Attribute> init = op.getInitialValue();
3084 const mlir::Type cirSymType = op.getSymType();
3087 mlir::Type llvmType =
3090 return op.emitError()
3091 <<
"NYI: lowering global of a type with no memory representation";
3096 if (init.has_value())
3102 const bool isConst = op.getConstant();
3103 unsigned addrSpace = 0;
3104 if (
auto targetAS = mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
3105 op.getAddrSpaceAttr()))
3106 addrSpace = targetAS.getValue();
3107 const bool isDsoLocal = op.getDsoLocal();
3108 mlir::LLVM::ThreadLocalMode threadLocalMode =
3110 const uint64_t alignment = op.getAlignment().value_or(0);
3111 const mlir::LLVM::Linkage linkage =
convertLinkage(op.getLinkage());
3112 const StringRef symbol = op.getSymName();
3113 SmallVector<mlir::NamedAttribute> attributes =
3114 lowerGlobalAttributes(op, rewriter);
3117 if (std::optional<llvm::StringRef> aliasee = op.getAliasee()) {
3118 mlir::Location loc = op.getLoc();
3119 auto aliasOp = rewriter.replaceOpWithNewOp<mlir::LLVM::AliasOp>(
3120 op, llvmType, linkage, symbol, isDsoLocal, threadLocalMode, attributes);
3122 mlir::OpBuilder builder(op.getContext());
3123 mlir::Block *block = builder.createBlock(&aliasOp.getInitializerRegion());
3124 builder.setInsertionPointToStart(block);
3126 mlir::LLVM::LLVMPointerType::get(getContext(), addrSpace);
3128 mlir::LLVM::AddressOfOp::create(builder, loc, ptrTy, *aliasee);
3129 mlir::LLVM::ReturnOp::create(builder, loc, addrOp);
3130 return mlir::success();
3133 if (init.has_value()) {
3134 if (mlir::isa<cir::FPAttr, cir::IntAttr, cir::BoolAttr>(init.value())) {
3136 init = initRewriter.visit(init.value());
3141 if (!init.value()) {
3142 op.emitError() <<
"unsupported initializer '" << init.value() <<
"'";
3143 return mlir::failure();
3145 }
else if (
auto constArr =
3146 mlir::dyn_cast<cir::ConstArrayAttr>(init.value())) {
3154 mlir::ModuleOp modOp = op->getParentOfType<mlir::ModuleOp>();
3156 constArr, symbolTables, typeConverter, modOp)) {
3157 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
3158 rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
3159 op, llvmType, isConst, linkage, symbol, bulkInit.value(),
3160 alignment, addrSpace, isDsoLocal, threadLocalMode, comdatAttr,
3162 return mlir::success();
3165 return matchAndRewriteRegionInitializedGlobal(op, init.value(), rewriter);
3166 }
else if (
auto constRecord =
3167 mlir::dyn_cast<cir::ConstRecordAttr>(init.value())) {
3173 mlir::ModuleOp modOp = op->getParentOfType<mlir::ModuleOp>();
3175 constRecord, symbolTables, typeConverter, modOp)) {
3176 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
3177 rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
3178 op, llvmType, isConst, linkage, symbol, bulkInit.value(), alignment,
3179 addrSpace, isDsoLocal, threadLocalMode, comdatAttr, attributes);
3180 return mlir::success();
3182 return matchAndRewriteRegionInitializedGlobal(op, init.value(), rewriter);
3183 }
else if (mlir::isa<cir::BlockAddrDiffAttr, cir::BlockAddrInfoAttr,
3184 cir::ConstVectorAttr, cir::ConstRecordAttr,
3185 cir::ConstPtrAttr, cir::ConstComplexAttr,
3186 cir::GlobalOffsetAttr, cir::GlobalViewAttr,
3187 cir::TypeInfoAttr, cir::UndefAttr, cir::PoisonAttr,
3188 cir::VTableAttr, cir::ZeroAttr>(init.value())) {
3192 return matchAndRewriteRegionInitializedGlobal(op, init.value(), rewriter);
3196 op.emitError() <<
"unsupported initializer '" << init.value() <<
"'";
3197 return mlir::failure();
3201 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
3202 rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
3203 op, llvmType, isConst, linkage, symbol, init.value_or(mlir::Attribute()),
3204 alignment, addrSpace, isDsoLocal, threadLocalMode, comdatAttr,
3207 return mlir::success();
3211 mlir::OpBuilder &builder,
3213 mlir::LLVM::ComdatOp &comdatOp) {
3214 mlir::OpBuilder::InsertionGuard guard(builder);
3215 StringRef comdatName =
"__llvm_comdat";
3221 comdatOp = modOp.lookupSymbol<mlir::LLVM::ComdatOp>(comdatName);
3225 builder.setInsertionPointToStart(modOp.getBody());
3227 mlir::LLVM::ComdatOp::create(builder, modOp.getLoc(), comdatName);
3230 if (
auto comdatSelector =
3231 comdatOp.lookupSymbol<mlir::LLVM::ComdatSelectorOp>(symName)) {
3232 return mlir::SymbolRefAttr::get(
3233 builder.getContext(), comdatName,
3234 mlir::FlatSymbolRefAttr::get(comdatSelector.getSymNameAttr()));
3237 builder.setInsertionPointToStart(&comdatOp.getBody().back());
3238 auto selectorOp = mlir::LLVM::ComdatSelectorOp::create(
3239 builder, comdatOp.getLoc(), symName, mlir::LLVM::comdat::Comdat::Any,
3241 return mlir::SymbolRefAttr::get(
3242 builder.getContext(), comdatName,
3243 mlir::FlatSymbolRefAttr::get(selectorOp.getSymNameAttr()));
3247CIRToLLVMGlobalOpLowering::getComdatAttr(cir::GlobalOp &op,
3248 mlir::OpBuilder &builder)
const {
3249 if (!op.getComdat())
3250 return mlir::SymbolRefAttr{};
3252 op.getSymName(), comdatOp);
3256CIRToLLVMFuncOpLowering::getComdatAttr(cir::FuncOp &op,
3257 mlir::OpBuilder &builder)
const {
3258 std::optional<llvm::StringRef> comdat = op.getComdat();
3260 return mlir::SymbolRefAttr{};
3261 llvm::StringRef comdatKey = comdat->empty() ? op.getSymName() : *comdat;
3263 comdatKey, comdatOp);
3266mlir::LogicalResult CIRToLLVMSwitchFlatOpLowering::matchAndRewrite(
3267 cir::SwitchFlatOp op, OpAdaptor adaptor,
3268 mlir::ConversionPatternRewriter &rewriter)
const {
3270 llvm::SmallVector<mlir::APInt, 8> caseValues;
3271 for (mlir::Attribute val : op.getCaseValues()) {
3272 auto intAttr = cast<cir::IntAttr>(val);
3273 caseValues.push_back(intAttr.getValue());
3276 llvm::SmallVector<mlir::Block *, 8> caseDestinations;
3277 llvm::SmallVector<mlir::ValueRange, 8> caseOperands;
3279 for (mlir::Block *x : op.getCaseDestinations())
3280 caseDestinations.push_back(x);
3282 for (mlir::OperandRange x : op.getCaseOperands())
3283 caseOperands.push_back(x);
3286 rewriter.setInsertionPoint(op);
3287 rewriter.replaceOpWithNewOp<mlir::LLVM::SwitchOp>(
3288 op, adaptor.getCondition(), op.getDefaultDestination(),
3289 op.getDefaultOperands(), caseValues, caseDestinations, caseOperands);
3290 return mlir::success();
3293static mlir::LLVM::IntegerOverflowFlags
nswFlag(
bool nsw) {
3294 return nsw ? mlir::LLVM::IntegerOverflowFlags::nsw
3295 : mlir::LLVM::IntegerOverflowFlags::none;
3298template <
typename CIROp,
typename LLVMIntOp>
3299static mlir::LogicalResult
3301 mlir::ConversionPatternRewriter &rewriter) {
3302 mlir::Type llvmType = adaptor.getInput().getType();
3303 mlir::Location loc = op.getLoc();
3305 auto maybeNSW =
nswFlag(op.getNoSignedWrap());
3306 mlir::LLVM::ConstantOp one;
3307 if (mlir::isa<cir::VectorType>(op.getType())) {
3308 mlir::DenseIntElementsAttr oneVec = mlir::DenseIntElementsAttr::get(
3309 mlir::cast<mlir::ShapedType>(llvmType), 1);
3310 one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, oneVec);
3312 one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
3314 rewriter.replaceOpWithNewOp<LLVMIntOp>(op, adaptor.getInput(), one, maybeNSW);
3315 return mlir::success();
3318mlir::LogicalResult CIRToLLVMIncOpLowering::matchAndRewrite(
3319 cir::IncOp op, OpAdaptor adaptor,
3320 mlir::ConversionPatternRewriter &rewriter)
const {
3324mlir::LogicalResult CIRToLLVMDecOpLowering::matchAndRewrite(
3325 cir::DecOp op, OpAdaptor adaptor,
3326 mlir::ConversionPatternRewriter &rewriter)
const {
3330mlir::LogicalResult CIRToLLVMMinusOpLowering::matchAndRewrite(
3331 cir::MinusOp op, OpAdaptor adaptor,
3332 mlir::ConversionPatternRewriter &rewriter)
const {
3333 bool isVector = mlir::isa<cir::VectorType>(op.getType());
3334 mlir::Type llvmType = adaptor.getInput().getType();
3335 mlir::Location loc = op.getLoc();
3337 auto maybeNSW =
nswFlag(op.getNoSignedWrap());
3340 zero = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmType);
3342 zero = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 0);
3343 rewriter.replaceOpWithNewOp<mlir::LLVM::SubOp>(op, zero, adaptor.getInput(),
3345 return mlir::success();
3348mlir::LogicalResult CIRToLLVMNotOpLowering::matchAndRewrite(
3349 cir::NotOp op, OpAdaptor adaptor,
3350 mlir::ConversionPatternRewriter &rewriter)
const {
3351 mlir::Type elementType = elementTypeIfVector(op.getType());
3352 bool isVector = mlir::isa<cir::VectorType>(op.getType());
3353 mlir::Type llvmType = adaptor.getInput().getType();
3354 mlir::Location loc = op.getLoc();
3356 if (mlir::isa<cir::IntType>(elementType)) {
3357 mlir::Value minusOne;
3360 mlir::cast<cir::VectorType>(op.getType()).getSize();
3361 const unsigned eltWidth =
3362 mlir::cast<cir::IntType>(elementType).getWidth();
3363 SmallVector<APInt> values(numElements, APInt::getAllOnes(eltWidth));
3364 mlir::DenseIntElementsAttr denseVec = mlir::DenseIntElementsAttr::get(
3365 mlir::cast<mlir::ShapedType>(llvmType), values);
3367 mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, denseVec);
3369 minusOne = mlir::LLVM::ConstantOp::create(
3370 rewriter, loc, llvmType,
3371 APInt::getAllOnes(cast<mlir::IntegerType>(llvmType).getWidth()));
3373 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getInput(),
3375 return mlir::success();
3378 if (mlir::isa<cir::BoolType>(elementType)) {
3382 mlir::cast<cir::VectorType>(op.getType()).getSize();
3383 SmallVector<bool> values(numElements,
true);
3384 mlir::DenseIntElementsAttr denseVec = rewriter.getBoolVectorAttr(values);
3385 one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, denseVec);
3387 one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
3389 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getInput(), one);
3390 return mlir::success();
3393 return op.emitError() <<
"Unsupported type for bitwise NOT";
3398 return mlir::isa<cir::IntType>(type)
3399 ? mlir::cast<cir::IntType>(type).isUnsigned()
3400 : mlir::cast<mlir::IntegerType>(type).isUnsigned();
3407template <
typename BinOp>
3409 if (op.getNoUnsignedWrap())
3410 return mlir::LLVM::IntegerOverflowFlags::nuw;
3411 if (op.getNoSignedWrap())
3412 return mlir::LLVM::IntegerOverflowFlags::nsw;
3413 return mlir::LLVM::IntegerOverflowFlags::none;
3418template <
typename UIntSatOp,
typename SIntSatOp,
typename IntOp,
3420static mlir::LogicalResult
3422 mlir::ConversionPatternRewriter &rewriter) {
3423 const mlir::Type eltType = elementTypeIfVector(op.getRhs().getType());
3424 assert(cir::isIntOrBoolType(eltType) &&
3425 "saturatable arith op expects integer operand types");
3426 if (op.getSaturated()) {
3428 rewriter.replaceOpWithNewOp<UIntSatOp>(op, lhs, rhs);
3430 rewriter.replaceOpWithNewOp<SIntSatOp>(op, lhs, rhs);
3431 return mlir::success();
3433 rewriter.replaceOpWithNewOp<IntOp>(op, lhs, rhs,
intOverflowFlag(op));
3434 return mlir::success();
3437mlir::LogicalResult CIRToLLVMAddOpLowering::matchAndRewrite(
3438 cir::AddOp op, OpAdaptor adaptor,
3439 mlir::ConversionPatternRewriter &rewriter)
const {
3441 mlir::LLVM::AddOp>(op, adaptor.getLhs(),
3442 adaptor.getRhs(), rewriter);
3445mlir::LogicalResult CIRToLLVMSubOpLowering::matchAndRewrite(
3446 cir::SubOp op, OpAdaptor adaptor,
3447 mlir::ConversionPatternRewriter &rewriter)
const {
3449 mlir::LLVM::SubOp>(op, adaptor.getLhs(),
3450 adaptor.getRhs(), rewriter);
3453mlir::LogicalResult CIRToLLVMMulOpLowering::matchAndRewrite(
3454 cir::MulOp op, OpAdaptor adaptor,
3455 mlir::ConversionPatternRewriter &rewriter)
const {
3456 assert(cir::isIntOrBoolType(elementTypeIfVector(op.getRhs().getType())) &&
3457 "cir.mul expects integer operand types");
3458 rewriter.replaceOpWithNewOp<mlir::LLVM::MulOp>(
3460 return mlir::success();
3464template <
typename UIntOp,
typename SIntOp,
typename CIROp>
3465static mlir::LogicalResult
3467 mlir::ConversionPatternRewriter &rewriter) {
3468 const mlir::Type eltType = elementTypeIfVector(op.getRhs().getType());
3469 assert(cir::isIntOrBoolType(eltType) &&
3470 "integer binary op expects integer operand types");
3472 rewriter.replaceOpWithNewOp<UIntOp>(op, lhs, rhs);
3474 rewriter.replaceOpWithNewOp<SIntOp>(op, lhs, rhs);
3475 return mlir::success();
3478mlir::LogicalResult CIRToLLVMDivOpLowering::matchAndRewrite(
3479 cir::DivOp op, OpAdaptor adaptor,
3480 mlir::ConversionPatternRewriter &rewriter)
const {
3482 op, adaptor.getLhs(), adaptor.getRhs(), rewriter);
3485mlir::LogicalResult CIRToLLVMRemOpLowering::matchAndRewrite(
3486 cir::RemOp op, OpAdaptor adaptor,
3487 mlir::ConversionPatternRewriter &rewriter)
const {
3489 op, adaptor.getLhs(), adaptor.getRhs(), rewriter);
3492template <
typename CIROp,
typename UIntOp,
typename SIntOp>
3493static mlir::LogicalResult
3495 mlir::ConversionPatternRewriter &rewriter) {
3496 const mlir::Value lhs = adaptor.getLhs();
3497 const mlir::Value rhs = adaptor.getRhs();
3499 rewriter.replaceOpWithNewOp<UIntOp>(op, lhs, rhs);
3501 rewriter.replaceOpWithNewOp<SIntOp>(op, lhs, rhs);
3502 return mlir::success();
3505mlir::LogicalResult CIRToLLVMMaxOpLowering::matchAndRewrite(
3506 cir::MaxOp op, OpAdaptor adaptor,
3507 mlir::ConversionPatternRewriter &rewriter)
const {
3509 op, adaptor, rewriter);
3512mlir::LogicalResult CIRToLLVMMinOpLowering::matchAndRewrite(
3513 cir::MinOp op, OpAdaptor adaptor,
3514 mlir::ConversionPatternRewriter &rewriter)
const {
3516 op, adaptor, rewriter);
3520static mlir::LLVM::ICmpPredicate
3522 using CIR = cir::CmpOpKind;
3523 using LLVMICmp = mlir::LLVM::ICmpPredicate;
3526 return LLVMICmp::eq;
3528 return LLVMICmp::ne;
3530 return (isSigned ? LLVMICmp::slt : LLVMICmp::ult);
3532 return (isSigned ? LLVMICmp::sle : LLVMICmp::ule);
3534 return (isSigned ? LLVMICmp::sgt : LLVMICmp::ugt);
3536 return (isSigned ? LLVMICmp::sge : LLVMICmp::uge);
3539 llvm_unreachable(
"FP-only comparison used with integer type");
3541 llvm_unreachable(
"Unknown CmpOpKind");
3546static mlir::LLVM::FCmpPredicate
3548 using CIR = cir::CmpOpKind;
3549 using LLVMFCmp = mlir::LLVM::FCmpPredicate;
3552 return LLVMFCmp::oeq;
3554 return LLVMFCmp::une;
3556 return LLVMFCmp::olt;
3558 return LLVMFCmp::ole;
3560 return LLVMFCmp::ogt;
3562 return LLVMFCmp::oge;
3564 return LLVMFCmp::one;
3566 return LLVMFCmp::uno;
3568 llvm_unreachable(
"Unknown CmpOpKind");
3571static llvm::StringRef
3573 using CIR = cir::CmpOpKind;
3592 llvm_unreachable(
"Unknown CmpOpKind");
3596 using CIR = cir::CmpOpKind;
3609 llvm_unreachable(
"Unknown CmpOpKind");
3612static mlir::LLVM::CallIntrinsicOp
3614 mlir::Location loc, mlir::Value lhs, mlir::Value rhs,
3615 cir::CmpOpKind
kind, cir::FenvAttr fenv,
3616 mlir::Type llvmResTy) {
3624 ?
"llvm.experimental.constrained.fcmps"
3625 :
"llvm.experimental.constrained.fcmp";
3630mlir::LogicalResult CIRToLLVMCmpOpLowering::matchAndRewrite(
3631 cir::CmpOp cmpOp, OpAdaptor adaptor,
3632 mlir::ConversionPatternRewriter &rewriter)
const {
3633 mlir::Type type = cmpOp.getLhs().getType();
3635 if (mlir::isa<cir::IntType, mlir::IntegerType>(type)) {
3636 bool isSigned = mlir::isa<cir::IntType>(type)
3637 ? mlir::cast<cir::IntType>(type).isSigned()
3638 : mlir::cast<mlir::IntegerType>(type).isSigned();
3639 mlir::LLVM::ICmpPredicate
kind =
3641 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
3642 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
3643 return mlir::success();
3646 if (mlir::isa<cir::BoolType, cir::PointerType, cir::VPtrType>(type)) {
3650 mlir::LLVM::ICmpPredicate
kind =
3652 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
3653 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
3654 return mlir::success();
3657 if (mlir::isa<cir::FPTypeInterface>(type)) {
3658 mlir::Type llvmResTy = getTypeConverter()->convertType(cmpOp.getType());
3659 if (cir::FenvAttr fenv = cmpOp.getFenvAttr()) {
3661 rewriter, cmpOp.getLoc(), adaptor.getLhs(), adaptor.getRhs(),
3662 cmpOp.getKind(), fenv, llvmResTy);
3663 rewriter.replaceOp(cmpOp, call.getResult(0));
3664 return mlir::success();
3666 mlir::LLVM::FCmpPredicate
kind =
3668 rewriter.replaceOpWithNewOp<mlir::LLVM::FCmpOp>(
3669 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
3670 return mlir::success();
3673 if (mlir::isa<cir::ComplexType>(type)) {
3674 mlir::Value lhs = adaptor.getLhs();
3675 mlir::Value rhs = adaptor.getRhs();
3676 mlir::Location loc = cmpOp.getLoc();
3678 auto complexType = mlir::cast<cir::ComplexType>(cmpOp.getLhs().getType());
3679 mlir::Type complexElemTy =
3680 getTypeConverter()->convertType(
complexType.getElementType());
3682 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
3683 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{0}));
3684 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
3685 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{1}));
3686 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
3687 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{0}));
3688 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
3689 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{1}));
3691 if (cmpOp.getKind() == cir::CmpOpKind::eq) {
3692 if (complexElemTy.isInteger()) {
3693 auto realCmp = mlir::LLVM::ICmpOp::create(
3694 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, lhsReal, rhsReal);
3695 auto imagCmp = mlir::LLVM::ICmpOp::create(
3696 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, lhsImag, rhsImag);
3697 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, imagCmp);
3698 return mlir::success();
3701 auto realCmp = mlir::LLVM::FCmpOp::create(
3702 rewriter, loc, mlir::LLVM::FCmpPredicate::oeq, lhsReal, rhsReal);
3703 auto imagCmp = mlir::LLVM::FCmpOp::create(
3704 rewriter, loc, mlir::LLVM::FCmpPredicate::oeq, lhsImag, rhsImag);
3705 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, imagCmp);
3706 return mlir::success();
3709 if (cmpOp.getKind() == cir::CmpOpKind::ne) {
3710 if (complexElemTy.isInteger()) {
3711 auto realCmp = mlir::LLVM::ICmpOp::create(
3712 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, lhsReal, rhsReal);
3713 auto imagCmp = mlir::LLVM::ICmpOp::create(
3714 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, lhsImag, rhsImag);
3715 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp);
3716 return mlir::success();
3719 auto realCmp = mlir::LLVM::FCmpOp::create(
3720 rewriter, loc, mlir::LLVM::FCmpPredicate::une, lhsReal, rhsReal);
3721 auto imagCmp = mlir::LLVM::FCmpOp::create(
3722 rewriter, loc, mlir::LLVM::FCmpPredicate::une, lhsImag, rhsImag);
3723 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp);
3724 return mlir::success();
3728 return cmpOp.emitError() <<
"unsupported type for CmpOp: " <<
type;
3734template <
typename OpTy>
3735static mlir::LogicalResult
3737 mlir::ConversionPatternRewriter &rewriter,
3738 const mlir::TypeConverter *typeConverter,
3739 llvm::StringRef opStr) {
3740 mlir::Location loc = op.getLoc();
3741 cir::IntType operandTy = op.getLhs().getType();
3744 mlir::Type resultTy = op.getResult().getType();
3745 auto resultIntTy = mlir::dyn_cast<cir::IntType>(resultTy);
3746 unsigned resultWidth = resultIntTy ? resultIntTy.getWidth() : 1;
3747 bool resultSigned = resultIntTy && resultIntTy.getIsSigned();
3749 bool sign = operandTy.getIsSigned() || resultSigned;
3751 std::max(operandTy.getWidth() + (
sign && operandTy.isUnsigned()),
3752 resultWidth + (
sign && !resultSigned));
3754 mlir::IntegerType encompassedLLVMTy = rewriter.getIntegerType(width);
3756 mlir::Value lhs = adaptor.getLhs();
3757 mlir::Value rhs = adaptor.getRhs();
3758 if (operandTy.getWidth() < width) {
3759 if (operandTy.isSigned()) {
3760 lhs = mlir::LLVM::SExtOp::create(rewriter, loc, encompassedLLVMTy, lhs);
3761 rhs = mlir::LLVM::SExtOp::create(rewriter, loc, encompassedLLVMTy, rhs);
3763 lhs = mlir::LLVM::ZExtOp::create(rewriter, loc, encompassedLLVMTy, lhs);
3764 rhs = mlir::LLVM::ZExtOp::create(rewriter, loc, encompassedLLVMTy, rhs);
3769 std::string intrinName = (
"llvm." + llvm::Twine(
sign ?
's' :
'u') + opStr +
3770 ".with.overflow.i" + llvm::Twine(width))
3772 auto intrinNameAttr = mlir::StringAttr::get(op.getContext(), intrinName);
3774 mlir::IntegerType overflowLLVMTy = rewriter.getI1Type();
3775 auto intrinRetTy = mlir::LLVM::LLVMStructType::getLiteral(
3776 rewriter.getContext(), {encompassedLLVMTy, overflowLLVMTy});
3778 auto callLLVMIntrinOp = mlir::LLVM::CallIntrinsicOp::create(
3779 rewriter, loc, intrinRetTy, intrinNameAttr, mlir::ValueRange{lhs, rhs});
3780 mlir::Value intrinRet = callLLVMIntrinOp.getResult(0);
3782 mlir::Value result = mlir::LLVM::ExtractValueOp::create(
3785 mlir::Value overflow = mlir::LLVM::ExtractValueOp::create(
3789 if (resultWidth < width) {
3790 mlir::Type resultLLVMTy = typeConverter->convertType(resultTy);
3792 mlir::LLVM::TruncOp::create(rewriter, loc, resultLLVMTy, result);
3796 mlir::Value truncResultExt;
3798 truncResultExt = mlir::LLVM::SExtOp::create(
3799 rewriter, loc, encompassedLLVMTy, truncResult);
3801 truncResultExt = mlir::LLVM::ZExtOp::create(
3802 rewriter, loc, encompassedLLVMTy, truncResult);
3803 auto truncOverflow = mlir::LLVM::ICmpOp::create(
3804 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, truncResultExt, result);
3806 result = truncResult;
3807 overflow = mlir::LLVM::OrOp::create(rewriter, loc, overflow, truncOverflow);
3810 mlir::Type boolLLVMTy =
3811 typeConverter->convertType(op.getOverflow().getType());
3812 if (boolLLVMTy != rewriter.getI1Type())
3813 overflow = mlir::LLVM::ZExtOp::create(rewriter, loc, boolLLVMTy, overflow);
3815 rewriter.replaceOp(op, mlir::ValueRange{result, overflow});
3817 return mlir::success();
3820mlir::LogicalResult CIRToLLVMAddOverflowOpLowering::matchAndRewrite(
3821 cir::AddOverflowOp op, OpAdaptor adaptor,
3822 mlir::ConversionPatternRewriter &rewriter)
const {
3826mlir::LogicalResult CIRToLLVMSubOverflowOpLowering::matchAndRewrite(
3827 cir::SubOverflowOp op, OpAdaptor adaptor,
3828 mlir::ConversionPatternRewriter &rewriter)
const {
3832mlir::LogicalResult CIRToLLVMMulOverflowOpLowering::matchAndRewrite(
3833 cir::MulOverflowOp op, OpAdaptor adaptor,
3834 mlir::ConversionPatternRewriter &rewriter)
const {
3838mlir::LogicalResult CIRToLLVMFrexpOpLowering::matchAndRewrite(
3839 cir::FrexpOp op, OpAdaptor adaptor,
3840 mlir::ConversionPatternRewriter &rewriter)
const {
3841 mlir::Location loc = op.getLoc();
3842 mlir::Type fpLLVMTy =
3843 getTypeConverter()->convertType(op.getResult().getType());
3844 mlir::Type intLLVMTy = getTypeConverter()->convertType(op.getExp().getType());
3846 auto structTy = mlir::LLVM::LLVMStructType::getLiteral(rewriter.getContext(),
3847 {fpLLVMTy, intLLVMTy});
3851 mlir::Value result = callOp.getResult(0);
3853 mlir::Value mantissa =
3854 mlir::LLVM::ExtractValueOp::create(rewriter, loc, result, 0);
3855 mlir::Value exponent =
3856 mlir::LLVM::ExtractValueOp::create(rewriter, loc, result, 1);
3857 rewriter.replaceOp(op, mlir::ValueRange{mantissa, exponent});
3858 return mlir::success();
3861mlir::LogicalResult CIRToLLVMModfOpLowering::matchAndRewrite(
3862 cir::ModfOp op, OpAdaptor adaptor,
3863 mlir::ConversionPatternRewriter &rewriter)
const {
3864 mlir::Location loc = op.getLoc();
3865 mlir::Type fpLLVMTy =
3866 getTypeConverter()->convertType(op.getFractional().getType());
3868 auto structTy = mlir::LLVM::LLVMStructType::getLiteral(rewriter.getContext(),
3869 {fpLLVMTy, fpLLVMTy});
3873 mlir::Value result = callOp.getResult(0);
3875 mlir::Value fractional =
3876 mlir::LLVM::ExtractValueOp::create(rewriter, loc, result, 0);
3877 mlir::Value integral =
3878 mlir::LLVM::ExtractValueOp::create(rewriter, loc, result, 1);
3879 rewriter.replaceOp(op, mlir::ValueRange{fractional, integral});
3880 return mlir::success();
3883mlir::LogicalResult CIRToLLVMShiftOpLowering::matchAndRewrite(
3884 cir::ShiftOp op, OpAdaptor adaptor,
3885 mlir::ConversionPatternRewriter &rewriter)
const {
3886 assert((op.getValue().getType() == op.getType()) &&
3887 "inconsistent operands' types NYI");
3889 const mlir::Type llvmTy = getTypeConverter()->convertType(op.getType());
3890 mlir::Value amt = adaptor.getAmount();
3891 mlir::Value val = adaptor.getValue();
3893 auto cirAmtTy = mlir::dyn_cast<cir::IntType>(op.getAmount().getType());
3896 auto cirValTy = mlir::cast<cir::IntType>(op.getValue().getType());
3904 amt =
getLLVMIntCast(rewriter, amt, llvmTy,
true, cirAmtTy.getWidth(),
3905 cirValTy.getWidth());
3907 auto cirValVTy = mlir::cast<cir::VectorType>(op.getValue().getType());
3909 mlir::cast<cir::IntType>(cirValVTy.getElementType()).isUnsigned();
3913 if (op.getIsShiftleft()) {
3914 rewriter.replaceOpWithNewOp<mlir::LLVM::ShlOp>(op, llvmTy, val, amt);
3915 return mlir::success();
3919 rewriter.replaceOpWithNewOp<mlir::LLVM::LShrOp>(op, llvmTy, val, amt);
3921 rewriter.replaceOpWithNewOp<mlir::LLVM::AShrOp>(op, llvmTy, val, amt);
3922 return mlir::success();
3925mlir::LogicalResult CIRToLLVMSelectOpLowering::matchAndRewrite(
3926 cir::SelectOp op, OpAdaptor adaptor,
3927 mlir::ConversionPatternRewriter &rewriter)
const {
3928 auto getConstantBool = [](mlir::Value value) -> cir::BoolAttr {
3929 auto definingOp = value.getDefiningOp<cir::ConstantOp>();
3933 auto constValue = definingOp.getValueAttr<cir::BoolAttr>();
3943 if (mlir::isa<cir::BoolType>(op.getTrueValue().getType())) {
3944 cir::BoolAttr trueValue = getConstantBool(op.getTrueValue());
3945 cir::BoolAttr falseValue = getConstantBool(op.getFalseValue());
3946 if (falseValue && !falseValue.getValue()) {
3948 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(op, adaptor.getCondition(),
3949 adaptor.getTrueValue());
3950 return mlir::success();
3952 if (trueValue && trueValue.getValue()) {
3954 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(op, adaptor.getCondition(),
3955 adaptor.getFalseValue());
3956 return mlir::success();
3960 mlir::Value llvmCondition = adaptor.getCondition();
3961 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(
3962 op, llvmCondition, adaptor.getTrueValue(), adaptor.getFalseValue());
3964 return mlir::success();
3968 mlir::DataLayout &dataLayout) {
3969 converter.addConversion([&](cir::PointerType type) -> mlir::Type {
3970 mlir::ptr::MemorySpaceAttrInterface addrSpaceAttr = type.getAddrSpace();
3971 unsigned numericAS = 0;
3973 if (
auto targetAsAttr =
3974 mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
3976 numericAS = targetAsAttr.getValue();
3977 return mlir::LLVM::LLVMPointerType::get(type.getContext(), numericAS);
3979 converter.addConversion([&](cir::VPtrType type) -> mlir::Type {
3981 return mlir::LLVM::LLVMPointerType::get(type.getContext());
3985 converter.addConversion([&](cir::CUDADeviceSurfaceType type) -> mlir::Type {
3986 return mlir::IntegerType::get(type.getContext(), 64);
3988 converter.addConversion([&](cir::CUDADeviceTextureType type) -> mlir::Type {
3989 return mlir::IntegerType::get(type.getContext(), 64);
3991 converter.addConversion([&](cir::ArrayType type) -> mlir::Type {
3998 return mlir::LLVM::LLVMArrayType::get(ty, type.getSize());
4000 converter.addConversion([&](cir::VectorType type) -> mlir::Type {
4004 if (
auto intTy = mlir::dyn_cast<cir::IntType>(type.getElementType());
4005 intTy && intTy.isBitInt())
4007 const mlir::Type ty = converter.convertType(type.getElementType());
4008 return mlir::VectorType::get(type.getSize(), ty, {type.getIsScalable()});
4010 converter.addConversion([&](cir::BoolType type) -> mlir::Type {
4011 return mlir::IntegerType::get(type.getContext(), 1,
4012 mlir::IntegerType::Signless);
4014 converter.addConversion([&](cir::IntType type) -> mlir::Type {
4016 return mlir::IntegerType::get(type.getContext(), type.getWidth());
4018 converter.addConversion([&](cir::SingleType type) -> mlir::Type {
4019 return mlir::Float32Type::get(type.getContext());
4021 converter.addConversion([&](cir::DoubleType type) -> mlir::Type {
4022 return mlir::Float64Type::get(type.getContext());
4024 converter.addConversion([&](cir::FP80Type type) -> mlir::Type {
4025 return mlir::Float80Type::get(type.getContext());
4027 converter.addConversion([&](cir::FP128Type type) -> mlir::Type {
4028 return mlir::Float128Type::get(type.getContext());
4030 converter.addConversion([&](cir::LongDoubleType type) -> mlir::Type {
4031 return converter.convertType(type.getUnderlying());
4033 converter.addConversion([&](cir::FP16Type type) -> mlir::Type {
4034 return mlir::Float16Type::get(type.getContext());
4036 converter.addConversion([&](cir::BF16Type type) -> mlir::Type {
4037 return mlir::BFloat16Type::get(type.getContext());
4039 converter.addConversion([&](cir::ComplexType type) -> mlir::Type {
4042 mlir::Type elementTy = converter.convertType(type.getElementType());
4043 mlir::Type structFields[2] = {elementTy, elementTy};
4044 return mlir::LLVM::LLVMStructType::getLiteral(type.getContext(),
4047 converter.addConversion([&](cir::FuncType type) -> std::optional<mlir::Type> {
4048 auto result = converter.convertType(type.getReturnType());
4050 arguments.reserve(type.getNumInputs());
4051 if (converter.convertTypes(type.getInputs(), arguments).failed())
4052 return std::nullopt;
4053 auto varArg = type.isVarArg();
4054 return mlir::LLVM::LLVMFunctionType::get(result, arguments, varArg);
4056 converter.addConversion([&](cir::StructType type) -> mlir::Type {
4058 for (mlir::Type ty : type.getMembers()) {
4071 llvmMembers.push_back(memberTy);
4074 mlir::LLVM::LLVMStructType llvmStruct;
4075 if (type.getName()) {
4076 llvmStruct = mlir::LLVM::LLVMStructType::getIdentified(
4077 type.getContext(), type.getPrefixedName());
4078 if (llvmStruct.setBody(llvmMembers, type.getPacked()).failed())
4079 llvm_unreachable(
"Failed to set body of record");
4081 llvmStruct = mlir::LLVM::LLVMStructType::getLiteral(
4082 type.getContext(), llvmMembers, type.getPacked());
4087 converter.addConversion([&](cir::UnionType type) -> mlir::Type {
4089 if (!type.getMembers().empty())
4090 if (
auto storage = type.getUnionStorageType(dataLayout)) {
4091 mlir::Type storageTy =
4095 llvmMembers.push_back(storageTy);
4097 if (mlir::Type pad = type.getPadding()) {
4101 llvmMembers.push_back(padTy);
4104 mlir::LLVM::LLVMStructType llvmStruct;
4105 if (type.getName()) {
4106 llvmStruct = mlir::LLVM::LLVMStructType::getIdentified(
4107 type.getContext(), type.getPrefixedName());
4108 if (llvmStruct.setBody(llvmMembers, type.getPacked()).failed())
4109 llvm_unreachable(
"Failed to set body of record");
4111 llvmStruct = mlir::LLVM::LLVMStructType::getLiteral(
4112 type.getContext(), llvmMembers, type.getPacked());
4116 converter.addConversion([&](cir::VoidType type) -> mlir::Type {
4117 return mlir::LLVM::LLVMVoidType::get(type.getContext());
4122 mlir::ModuleOp module, StringRef globalXtorName, StringRef llvmXtorName,
4123 llvm::function_ref<std::pair<StringRef, int>(mlir::Attribute)> createXtor) {
4126 module->getDiscardableAttrOfType<mlir::ArrayAttr>(globalXtorName))
4127 for (mlir::Attribute element : attr)
4128 globalXtors.emplace_back(createXtor(element));
4130 if (globalXtors.empty())
4133 mlir::OpBuilder builder(module.getContext());
4134 builder.setInsertionPointToEnd(&module.getBodyRegion().back());
4138 auto ctorPFTy = mlir::LLVM::LLVMPointerType::get(builder.getContext());
4140 ctorStructFields.push_back(builder.getI32Type());
4141 ctorStructFields.push_back(ctorPFTy);
4142 ctorStructFields.push_back(ctorPFTy);
4144 auto ctorStructTy = mlir::LLVM::LLVMStructType::getLiteral(
4145 builder.getContext(), ctorStructFields);
4146 auto ctorStructArrayTy =
4147 mlir::LLVM::LLVMArrayType::get(ctorStructTy, globalXtors.size());
4149 mlir::Location loc =
module.getLoc();
4150 auto newGlobalOp = mlir::LLVM::GlobalOp::create(
4151 builder, loc, ctorStructArrayTy,
false,
4152 mlir::LLVM::Linkage::Appending, llvmXtorName, mlir::Attribute());
4154 builder.createBlock(&newGlobalOp.getRegion());
4155 builder.setInsertionPointToEnd(newGlobalOp.getInitializerBlock());
4157 mlir::Value result =
4158 mlir::LLVM::UndefOp::create(builder, loc, ctorStructArrayTy);
4160 for (
auto [index, fn] : llvm::enumerate(globalXtors)) {
4161 mlir::Value structInit =
4162 mlir::LLVM::UndefOp::create(builder, loc, ctorStructTy);
4163 mlir::Value initPriority = mlir::LLVM::ConstantOp::create(
4164 builder, loc, ctorStructFields[0], fn.second);
4165 mlir::Value initFuncAddr = mlir::LLVM::AddressOfOp::create(
4166 builder, loc, ctorStructFields[1], fn.first);
4167 mlir::Value initAssociate =
4168 mlir::LLVM::ZeroOp::create(builder, loc, ctorStructFields[2]);
4171 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
4172 initPriority, zero);
4173 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
4176 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
4178 result = mlir::LLVM::InsertValueOp::create(builder, loc, result, structInit,
4182 mlir::LLVM::ReturnOp::create(builder, loc, result);
4185mlir::LogicalResult CIRToLLVMObjSizeOpLowering::matchAndRewrite(
4186 cir::ObjSizeOp op, OpAdaptor adaptor,
4187 mlir::ConversionPatternRewriter &rewriter)
const {
4188 mlir::Type llvmResTy = getTypeConverter()->convertType(op.getType());
4189 mlir::Location loc = op->getLoc();
4191 mlir::IntegerType i1Ty = rewriter.getI1Type();
4193 auto i1Val = [&rewriter, &loc, &i1Ty](
bool val) {
4194 return mlir::LLVM::ConstantOp::create(rewriter, loc, i1Ty, val);
4201 i1Val(op.getNullunknown()),
4202 i1Val(op.getDynamic()),
4205 return mlir::LogicalResult::success();
4213constexpr StringRef llvmMetadataSectionName =
"llvm.metadata";
4218getOrCreateAnnotationStringGlobal(mlir::OpBuilder &builder, mlir::Location loc,
4219 mlir::ModuleOp module, llvm::StringRef str,
4220 llvm::StringMap<mlir::LLVM::GlobalOp> &cache,
4222 auto it = cache.find(str);
4223 if (it != cache.end())
4226 auto i8Ty = mlir::IntegerType::get(module.getContext(), 8);
4227 auto arrayTy = mlir::LLVM::LLVMArrayType::get(i8Ty, str.size() + 1);
4228 std::string
name =
".str";
4230 name +=
"." + std::to_string(cache.size());
4231 name +=
".annotation";
4235 mlir::LLVM::GlobalOp strGlobal = mlir::LLVM::GlobalOp::create(
4236 builder, loc, arrayTy,
true, mlir::LLVM::Linkage::Private,
4237 name, mlir::StringAttr::get(module.getContext(), std::string(str) +
'\0'),
4240 strGlobal.setSection(llvmMetadataSectionName);
4241 strGlobal.setUnnamedAddr(mlir::LLVM::UnnamedAddr::Global);
4242 strGlobal.setDsoLocal(
true);
4243 cache[str] = strGlobal;
4249mlir::LLVM::GlobalOp getOrCreateAnnotationArgsVar(
4250 mlir::OpBuilder &builder, mlir::Location loc, mlir::ModuleOp module,
4251 mlir::ArrayAttr argsAttr,
4252 llvm::StringMap<mlir::LLVM::GlobalOp> &argStringCache,
4253 llvm::MapVector<mlir::ArrayAttr, mlir::LLVM::GlobalOp> &argsCache) {
4254 auto it = argsCache.find(argsAttr);
4255 if (it != argsCache.end())
4258 auto ptrTy = mlir::LLVM::LLVMPointerType::get(builder.getContext());
4260 llvm::SmallVector<mlir::Type> fieldTypes;
4261 for (mlir::Attribute arg : argsAttr) {
4262 if (mlir::isa<mlir::StringAttr>(arg))
4263 fieldTypes.push_back(ptrTy);
4264 else if (
auto intAttr = mlir::dyn_cast<mlir::IntegerAttr>(arg))
4265 fieldTypes.push_back(intAttr.getType());
4267 llvm_unreachable(
"Unsupported annotation arg type");
4271 mlir::LLVM::LLVMStructType::getLiteral(builder.getContext(), fieldTypes);
4272 std::string
name =
".args";
4273 if (!argsCache.empty())
4274 name +=
"." + std::to_string(argsCache.size());
4275 name +=
".annotation";
4277 mlir::LLVM::GlobalOp argsGlobal = mlir::LLVM::GlobalOp::create(
4278 builder, loc, structTy,
true, mlir::LLVM::Linkage::Private,
4279 name, mlir::Attribute());
4280 argsGlobal.setSection(llvmMetadataSectionName);
4281 argsGlobal.setUnnamedAddr(mlir::LLVM::UnnamedAddr::Global);
4282 argsGlobal.setDsoLocal(
true);
4285 argsGlobal.getRegion().push_back(
new mlir::Block());
4286 mlir::OpBuilder initBuilder(module.getContext());
4287 initBuilder.setInsertionPointToEnd(argsGlobal.getInitializerBlock());
4289 mlir::Value structInit =
4290 mlir::LLVM::UndefOp::create(initBuilder, loc, structTy);
4291 for (
auto [idx, arg] : llvm::enumerate(argsAttr)) {
4292 if (
auto strArg = mlir::dyn_cast<mlir::StringAttr>(arg)) {
4293 mlir::LLVM::GlobalOp strGlobal = getOrCreateAnnotationStringGlobal(
4294 builder, loc, module, strArg.getValue(), argStringCache,
4296 mlir::LLVM::AddressOfOp strAddr = mlir::LLVM::AddressOfOp::create(
4297 initBuilder, loc, ptrTy, strGlobal.getSymName());
4298 structInit = mlir::LLVM::InsertValueOp::create(initBuilder, loc,
4299 structInit, strAddr, idx);
4300 }
else if (
auto intArg = mlir::dyn_cast<mlir::IntegerAttr>(arg)) {
4301 mlir::LLVM::ConstantOp intConst = mlir::LLVM::ConstantOp::create(
4302 initBuilder, loc, intArg.getType(), intArg.getValue());
4303 structInit = mlir::LLVM::InsertValueOp::create(initBuilder, loc,
4304 structInit, intConst, idx);
4306 llvm_unreachable(
"Unsupported annotation arg type");
4309 mlir::LLVM::ReturnOp::create(initBuilder, loc, structInit);
4311 argsCache[argsAttr] = argsGlobal;
4317std::pair<llvm::StringRef, unsigned> extractFileLine(mlir::Location loc) {
4318 mlir::Location resolved = loc;
4319 if (
auto fused = mlir::dyn_cast<mlir::FusedLoc>(resolved)) {
4320 if (!fused.getLocations().empty())
4321 resolved = fused.getLocations()[0];
4323 if (
auto fl = mlir::dyn_cast<mlir::FileLineColLoc>(resolved))
4324 return {fl.getFilename().getValue(), fl.getLine()};
4330 auto handleArray = [&](mlir::StringAttr symName, mlir::ArrayAttr arr,
4331 mlir::Location loc) {
4334 for (mlir::Attribute a : arr)
4335 if (
auto annot = mlir::dyn_cast<cir::AnnotationAttr>(a))
4336 collectedAnnotations.emplace_back(symName, annot, loc);
4341 module.walk([&](cir::GlobalOp op) {
4342 handleArray(op.getSymNameAttr(), op.getAnnotationsAttr(), op.getLoc());
4344 module.walk([&](cir::FuncOp op) {
4345 handleArray(op.getSymNameAttr(), op.getAnnotationsAttr(), op.getLoc());
4350 if (collectedAnnotations.empty())
4353 mlir::MLIRContext *ctx =
module.getContext();
4354 mlir::OpBuilder builder(ctx);
4355 builder.setInsertionPointToEnd(&module.getBodyRegion().back());
4357 auto ptrTy = mlir::LLVM::LLVMPointerType::get(ctx);
4358 auto i32Ty = builder.getI32Type();
4361 auto entryTy = mlir::LLVM::LLVMStructType::getLiteral(
4362 ctx, {ptrTy, ptrTy, ptrTy, i32Ty, ptrTy});
4364 mlir::LLVM::LLVMArrayType::get(entryTy, collectedAnnotations.size());
4366 mlir::Location moduleLoc =
module.getLoc();
4367 auto annotationsGlobal = mlir::LLVM::GlobalOp::create(
4368 builder, moduleLoc, arrayTy,
false,
4369 mlir::LLVM::Linkage::Appending,
"llvm.global.annotations",
4371 annotationsGlobal.setSection(llvmMetadataSectionName);
4375 mlir::OpBuilder constsBuilder(ctx);
4376 constsBuilder.setInsertionPoint(annotationsGlobal);
4378 llvm::StringMap<mlir::LLVM::GlobalOp> stringCache;
4379 llvm::StringMap<mlir::LLVM::GlobalOp> argStringCache;
4380 llvm::MapVector<mlir::ArrayAttr, mlir::LLVM::GlobalOp> argsCache;
4383 annotationsGlobal.getRegion().push_back(
new mlir::Block());
4384 mlir::OpBuilder initBuilder(ctx);
4385 initBuilder.setInsertionPointToEnd(annotationsGlobal.getInitializerBlock());
4387 mlir::Value arrayVal =
4388 mlir::LLVM::UndefOp::create(initBuilder, moduleLoc, arrayTy);
4390 for (
auto [idx, entry] : llvm::enumerate(collectedAnnotations)) {
4391 mlir::Value entryVal =
4392 mlir::LLVM::UndefOp::create(initBuilder, moduleLoc, entryTy);
4397 mlir::LLVM::AddressOfOp symAddr = mlir::LLVM::AddressOfOp::create(
4398 initBuilder, moduleLoc, ptrTy, entry.symName.getValue());
4399 entryVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
4400 entryVal, symAddr, zero);
4403 mlir::LLVM::GlobalOp nameGlobal = getOrCreateAnnotationStringGlobal(
4404 constsBuilder, moduleLoc, module, entry.annotation.getName().getValue(),
4405 stringCache,
false);
4406 mlir::LLVM::AddressOfOp nameAddr = mlir::LLVM::AddressOfOp::create(
4407 initBuilder, moduleLoc, ptrTy, nameGlobal.getSymName());
4408 entryVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
4409 entryVal, nameAddr, 1);
4412 auto [filename, line] = extractFileLine(entry.loc);
4413 mlir::LLVM::GlobalOp fileGlobal = getOrCreateAnnotationStringGlobal(
4414 constsBuilder, moduleLoc, module, filename, stringCache,
4416 mlir::LLVM::AddressOfOp fileAddr = mlir::LLVM::AddressOfOp::create(
4417 initBuilder, moduleLoc, ptrTy, fileGlobal.getSymName());
4418 entryVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
4419 entryVal, fileAddr, 2);
4420 mlir::LLVM::ConstantOp lineConst =
4421 mlir::LLVM::ConstantOp::create(initBuilder, moduleLoc, i32Ty, line);
4422 entryVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
4423 entryVal, lineConst, 3);
4426 mlir::ArrayAttr args = entry.annotation.getArgs();
4427 mlir::Value argsField;
4428 if (!args || args.empty()) {
4429 argsField = mlir::LLVM::ZeroOp::create(initBuilder, moduleLoc, ptrTy);
4431 mlir::LLVM::GlobalOp argsGlobal = getOrCreateAnnotationArgsVar(
4432 constsBuilder, moduleLoc, module, args, argStringCache, argsCache);
4433 argsField = mlir::LLVM::AddressOfOp::create(initBuilder, moduleLoc, ptrTy,
4434 argsGlobal.getSymName());
4436 entryVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
4437 entryVal, argsField, 4);
4439 arrayVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
4440 arrayVal, entryVal, idx);
4443 mlir::LLVM::ReturnOp::create(initBuilder, moduleLoc, arrayVal);
4449 mlir::ModuleOp module = getOperation();
4450 mlir::OpBuilder opBuilder(module.getContext());
4451 for (
auto &[blockAddOp, blockInfo] :
4453 mlir::LLVM::BlockTagOp resolvedLabel =
4455 assert(resolvedLabel &&
"expected BlockTagOp to already be emitted");
4456 mlir::FlatSymbolRefAttr fnSym = blockInfo.getFunc();
4457 auto blkAddTag = mlir::LLVM::BlockAddressAttr::get(
4458 opBuilder.getContext(), fnSym, resolvedLabel.getTagAttr());
4459 blockAddOp.setBlockAddrAttr(blkAddTag);
4466 if (mlir::Attribute tripleAttr =
4467 module->getAttr(cir::CIRDialect::getTripleAttrName()))
4468 module->setAttr(mlir::LLVM::LLVMDialect::getTargetTripleAttrName(),
4471 if (mlir::Attribute asmAttr =
4472 module->getAttr(cir::CIRDialect::getModuleLevelAsmAttrName()))
4473 module->setAttr(mlir::LLVM::LLVMDialect::getModuleLevelAsmAttrName(),
4480 llvm::TimeTraceScope scope(
"Convert CIR to LLVM Pass");
4482 mlir::ModuleOp module = getOperation();
4483 mlir::DataLayout dl(module);
4484 mlir::LLVMTypeConverter converter(&getContext());
4494 mlir::SymbolTableCollection symbolTables;
4495 mlir::RewritePatternSet patterns(&getContext());
4496 patterns.add<CIRToLLVMBlockAddressOpLowering, CIRToLLVMGlobalOpLowering,
4497 CIRToLLVMLabelOpLowering>(converter, patterns.getContext(), dl,
4498 symbolTables, blockInfoAddr);
4501#define GET_LLVM_LOWERING_PATTERNS_LIST
4502#include "clang/CIR/Dialect/IR/CIRLowering.inc"
4503#undef GET_LLVM_LOWERING_PATTERNS_LIST
4504 >(converter, patterns.getContext(), dl, symbolTables);
4512 mlir::ConversionTarget target(getContext());
4513 target.addLegalOp<mlir::ModuleOp>();
4514 target.addLegalDialect<mlir::LLVM::LLVMDialect>();
4515 mlir::configureOpenMPToLLVMConversionLegality(target, converter);
4516 target.addLegalDialect<mlir::omp::OpenMPDialect>();
4517 mlir::populateOpenMPToLLVMConversionPatterns(converter, patterns);
4518 target.addIllegalDialect<mlir::BuiltinDialect, cir::CIRDialect,
4519 mlir::func::FuncDialect>();
4522 ops.push_back(module);
4525 if (failed(applyPartialConversion(ops, target, std::move(patterns))))
4526 signalPassFailure();
4530 if (
auto dlSpec = mlir::dyn_cast_or_null<mlir::DataLayoutSpecAttr>(
4531 module->getAttr(mlir::DLTIDialect::kDataLayoutAttrName))) {
4533 for (mlir::DataLayoutEntryInterface entry : dlSpec.getEntries()) {
4534 if (entry.isTypeEntry() &&
4535 mlir::isa<cir::PointerType>(mlir::cast<mlir::Type>(entry.getKey())))
4537 kept.push_back(entry);
4539 module->setAttr(mlir::DLTIDialect::kDataLayoutAttrName,
4540 mlir::DataLayoutSpecAttr::get(module.getContext(), kept));
4545 "llvm.global_ctors", [](mlir::Attribute
attr) {
4546 auto ctorAttr = mlir::cast<cir::GlobalCtorAttr>(
attr);
4547 return std::make_pair(ctorAttr.getName(),
4548 ctorAttr.getPriority());
4552 "llvm.global_dtors", [](mlir::Attribute
attr) {
4553 auto dtorAttr = mlir::cast<cir::GlobalDtorAttr>(
attr);
4554 return std::make_pair(dtorAttr.getName(),
4555 dtorAttr.getPriority());
4563mlir::LogicalResult CIRToLLVMBrOpLowering::matchAndRewrite(
4564 cir::BrOp op, OpAdaptor adaptor,
4565 mlir::ConversionPatternRewriter &rewriter)
const {
4566 rewriter.replaceOpWithNewOp<mlir::LLVM::BrOp>(op, adaptor.getOperands(),
4568 return mlir::LogicalResult::success();
4571mlir::LogicalResult CIRToLLVMGetMemberOpLowering::matchAndRewrite(
4572 cir::GetMemberOp op, OpAdaptor adaptor,
4573 mlir::ConversionPatternRewriter &rewriter)
const {
4574 mlir::Type llResTy = getTypeConverter()->convertType(op.getType());
4575 mlir::Type pointee = op.getAddrTy().getPointee();
4577 if (mlir::isa<cir::UnionType>(pointee)) {
4580 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(op, llResTy,
4582 return mlir::success();
4585 auto structTy = mlir::cast<cir::StructType>(pointee);
4591 0,
static_cast<int32_t>(structTy.getLLVMFieldIndex(op.getIndex()))};
4592 const mlir::Type elementTy = getTypeConverter()->convertType(structTy);
4597 mlir::LLVM::GEPNoWrapFlags flags =
4598 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
4599 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
4600 op, llResTy, elementTy, adaptor.getAddr(), offset, flags);
4601 return mlir::success();
4604mlir::LogicalResult CIRToLLVMExtractMemberOpLowering::matchAndRewrite(
4605 cir::ExtractMemberOp op, OpAdaptor adaptor,
4606 mlir::ConversionPatternRewriter &rewriter)
const {
4607 if (mlir::isa<cir::UnionType>(op.getRecord().getType())) {
4608 op.emitError(
"cir.extract_member cannot extract member from a union");
4609 return mlir::failure();
4612 auto structTy = mlir::cast<cir::StructType>(op.getRecord().getType());
4613 std::int64_t indices[1] = {
4614 static_cast<std::int64_t
>(structTy.getLLVMFieldIndex(op.getIndex()))};
4615 rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractValueOp>(
4616 op, adaptor.getRecord(), indices);
4617 return mlir::success();
4620mlir::LogicalResult CIRToLLVMInsertMemberOpLowering::matchAndRewrite(
4621 cir::InsertMemberOp op, OpAdaptor adaptor,
4622 mlir::ConversionPatternRewriter &rewriter)
const {
4623 if (mlir::isa<cir::UnionType>(op.getRecord().getType())) {
4624 op.emitError(
"cir.update_member cannot update member of a union");
4625 return mlir::failure();
4628 auto structTy = mlir::cast<cir::StructType>(op.getRecord().getType());
4629 std::int64_t indices[1] = {
4630 static_cast<std::int64_t
>(structTy.getLLVMFieldIndex(op.getIndex()))};
4631 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
4632 op, adaptor.getRecord(), adaptor.getValue(), indices);
4633 return mlir::success();
4637 mlir::SymbolTableCollection &symbolTables,
4638 mlir::Operation *srcOp, llvm::StringRef fnName,
4640 mlir::ArrayAttr argAttrs =
nullptr,
4641 mlir::ArrayAttr resAttrs =
nullptr) {
4642 mlir::ModuleOp modOp = srcOp->getParentOfType<mlir::ModuleOp>();
4643 mlir::Operation *sourceSymbol = symbolTables.lookupSymbolIn(
4644 modOp, mlir::StringAttr::get(fnTy.getContext(), fnName));
4645 if (!sourceSymbol) {
4646 mlir::OpBuilder::InsertionGuard guard(rewriter);
4647 auto enclosingFnOp = srcOp->getParentOfType<mlir::LLVM::LLVMFuncOp>();
4648 rewriter.setInsertionPoint(enclosingFnOp);
4650 mlir::LLVM::LLVMFuncOp::create(rewriter, srcOp->getLoc(), fnName, fnTy);
4652 fn.setArgAttrsAttr(argAttrs);
4654 fn.setResAttrsAttr(resAttrs);
4656 symbolTables.getSymbolTable(fn->getParentOp()).insert(fn);
4660mlir::LogicalResult CIRToLLVMThrowOpLowering::matchAndRewrite(
4661 cir::ThrowOp op, OpAdaptor adaptor,
4662 mlir::ConversionPatternRewriter &rewriter)
const {
4663 mlir::Location loc = op.getLoc();
4664 auto voidTy = mlir::LLVM::LLVMVoidType::get(getContext());
4666 if (op.rethrows()) {
4667 auto funcTy = mlir::LLVM::LLVMFunctionType::get(voidTy, {});
4670 const llvm::StringRef functionName =
"__cxa_rethrow";
4671 createLLVMFuncOpIfNotExist(rewriter, symbolTables, op, functionName,
4674 auto cxaRethrow = mlir::LLVM::CallOp::create(
4675 rewriter, loc, mlir::TypeRange{}, functionName);
4677 rewriter.replaceOp(op, cxaRethrow);
4678 return mlir::success();
4681 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4682 auto fnTy = mlir::LLVM::LLVMFunctionType::get(
4683 voidTy, {llvmPtrTy, llvmPtrTy, llvmPtrTy});
4686 const llvm::StringRef fnName =
"__cxa_throw";
4689 mlir::Value typeInfo = mlir::LLVM::AddressOfOp::create(
4690 rewriter, loc, mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
4691 adaptor.getTypeInfoAttr());
4695 dtor = mlir::LLVM::AddressOfOp::create(rewriter, loc, llvmPtrTy,
4696 adaptor.getDtorAttr());
4698 dtor = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmPtrTy);
4701 auto cxaThrowCall = mlir::LLVM::CallOp::create(
4702 rewriter, loc, mlir::TypeRange{}, fnName,
4703 mlir::ValueRange{adaptor.getExceptionPtr(), typeInfo, dtor});
4705 rewriter.replaceOp(op, cxaThrowCall);
4706 return mlir::success();
4709mlir::LogicalResult CIRToLLVMAllocExceptionOpLowering::matchAndRewrite(
4710 cir::AllocExceptionOp op, OpAdaptor adaptor,
4711 mlir::ConversionPatternRewriter &rewriter)
const {
4713 StringRef fnName =
"__cxa_allocate_exception";
4714 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4715 auto int64Ty = mlir::IntegerType::get(rewriter.getContext(), 64);
4716 auto fnTy = mlir::LLVM::LLVMFunctionType::get(llvmPtrTy, {int64Ty});
4719 auto exceptionSize = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
4720 adaptor.getSizeAttr());
4722 auto allocaExceptionCall = mlir::LLVM::CallOp::create(
4723 rewriter, op.getLoc(), mlir::TypeRange{llvmPtrTy}, fnName,
4724 mlir::ValueRange{exceptionSize});
4726 rewriter.replaceOp(op, allocaExceptionCall);
4727 return mlir::success();
4730static mlir::LLVM::LLVMStructType
4733 mlir::MLIRContext *ctx = rewriter.getContext();
4734 auto llvmPtr = mlir::LLVM::LLVMPointerType::get(ctx);
4736 return mlir::LLVM::LLVMStructType::getLiteral(ctx, structFields);
4739mlir::LogicalResult CIRToLLVMEhInflightOpLowering::matchAndRewrite(
4740 cir::EhInflightOp op, OpAdaptor adaptor,
4741 mlir::ConversionPatternRewriter &rewriter)
const {
4742 auto llvmFn = op->getParentOfType<mlir::LLVM::LLVMFuncOp>();
4743 assert(llvmFn &&
"expected LLVM function parent");
4744 mlir::Block *entryBlock = &llvmFn.getRegion().front();
4745 assert(entryBlock->isEntryBlock());
4747 mlir::ArrayAttr catchListAttr = op.getCatchTypeListAttr();
4748 mlir::ArrayAttr filterListAttr = op.getFilterTypeListAttr();
4749 mlir::SmallVector<mlir::Value> landingPadClauses;
4751 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4752 mlir::Location loc = op.getLoc();
4757 if (catchListAttr) {
4760 for (mlir::Attribute catchAttr : catchListAttr) {
4761 auto symAttr = cast<mlir::FlatSymbolRefAttr>(catchAttr);
4764 mlir::OpBuilder::InsertionGuard guard(rewriter);
4765 rewriter.setInsertionPointToStart(entryBlock);
4766 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
4767 rewriter, loc, llvmPtrTy, symAttr.getValue());
4768 landingPadClauses.push_back(addrOp);
4775 if (op.getCatchAll() ||
4776 (!catchListAttr && !op.getCleanup() && !filterListAttr)) {
4777 mlir::OpBuilder::InsertionGuard guard(rewriter);
4778 rewriter.setInsertionPointToStart(entryBlock);
4779 mlir::Value nullOp = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmPtrTy);
4780 landingPadClauses.push_back(nullOp);
4783 if (filterListAttr) {
4787 mlir::OpBuilder::InsertionGuard guard(rewriter);
4788 rewriter.setInsertionPointToStart(entryBlock);
4789 auto filterArrayTy =
4790 mlir::LLVM::LLVMArrayType::get(llvmPtrTy, filterListAttr.size());
4791 mlir::Value filterVal;
4792 if (filterListAttr.empty()) {
4793 filterVal = mlir::LLVM::ZeroOp::create(rewriter, loc, filterArrayTy);
4795 filterVal = mlir::LLVM::UndefOp::create(rewriter, loc, filterArrayTy);
4796 for (
auto [i, filterAttr] : llvm::enumerate(filterListAttr)) {
4797 auto symAttr = mlir::cast<mlir::FlatSymbolRefAttr>(filterAttr);
4798 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
4799 rewriter, loc, llvmPtrTy, symAttr.getValue());
4800 filterVal = mlir::LLVM::InsertValueOp::create(
4801 rewriter, loc, filterVal, addrOp,
4805 landingPadClauses.push_back(filterVal);
4810 mlir::LLVM::LLVMStructType llvmLandingPadStructTy =
4812 auto landingPadOp = mlir::LLVM::LandingpadOp::create(
4813 rewriter, loc, llvmLandingPadStructTy, landingPadClauses);
4818 if (op.getCleanup() && !op.getCatchAll())
4819 landingPadOp.setCleanup(
true);
4822 mlir::LLVM::ExtractValueOp::create(rewriter, loc, landingPadOp, 0);
4823 mlir::Value selector =
4824 mlir::LLVM::ExtractValueOp::create(rewriter, loc, landingPadOp, 1);
4825 rewriter.replaceOp(op, mlir::ValueRange{slot, selector});
4827 return mlir::success();
4830mlir::LogicalResult CIRToLLVMResumeFlatOpLowering::matchAndRewrite(
4831 cir::ResumeFlatOp op, OpAdaptor adaptor,
4832 mlir::ConversionPatternRewriter &rewriter)
const {
4837 mlir::Value poison = mlir::LLVM::PoisonOp::create(rewriter, op.getLoc(),
4838 llvmLandingPadStructTy);
4841 mlir::Value slot = mlir::LLVM::InsertValueOp::create(
4842 rewriter, op.getLoc(), poison, adaptor.getExceptionPtr(), slotIdx);
4845 mlir::Value selector = mlir::LLVM::InsertValueOp::create(
4846 rewriter, op.getLoc(), slot, adaptor.getTypeId(), selectorIdx);
4848 rewriter.replaceOpWithNewOp<mlir::LLVM::ResumeOp>(op, selector);
4849 return mlir::success();
4852mlir::LogicalResult CIRToLLVMEhTypeIdOpLowering::matchAndRewrite(
4853 cir::EhTypeIdOp op, OpAdaptor adaptor,
4854 mlir::ConversionPatternRewriter &rewriter)
const {
4855 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
4856 rewriter, op.getLoc(),
4857 mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
4858 op.getTypeSymAttr());
4859 rewriter.replaceOpWithNewOp<mlir::LLVM::EhTypeidForOp>(
4860 op, rewriter.getI32Type(), addrOp);
4861 return mlir::success();
4864mlir::LogicalResult CIRToLLVMEhSetjmpOpLowering::matchAndRewrite(
4865 cir::EhSetjmpOp op, OpAdaptor adaptor,
4866 mlir::ConversionPatternRewriter &rewriter)
const {
4867 mlir::Type returnType = typeConverter->convertType(op.getType());
4868 mlir::LLVM::CallIntrinsicOp newOp =
4870 returnType, adaptor.getEnv());
4871 rewriter.replaceOp(op, newOp);
4872 return mlir::success();
4875mlir::LogicalResult CIRToLLVMEhLongjmpOpLowering::matchAndRewrite(
4876 cir::EhLongjmpOp op, OpAdaptor adaptor,
4877 mlir::ConversionPatternRewriter &rewriter)
const {
4879 {}, adaptor.getOperands());
4880 return mlir::success();
4883mlir::LogicalResult CIRToLLVMTrapOpLowering::matchAndRewrite(
4884 cir::TrapOp op, OpAdaptor adaptor,
4885 mlir::ConversionPatternRewriter &rewriter)
const {
4886 mlir::Location loc = op->getLoc();
4887 rewriter.eraseOp(op);
4889 mlir::LLVM::Trap::create(rewriter, loc);
4894 mlir::LLVM::UnreachableOp::create(rewriter, loc);
4896 return mlir::success();
4901 mlir::ConversionPatternRewriter &rewriter,
4902 mlir::SymbolTableCollection &symbolTables,
4903 const mlir::TypeConverter *converter,
4904 mlir::FlatSymbolRefAttr nameAttr, mlir::Type &eltType) {
4905 auto module = op->getParentOfType<mlir::ModuleOp>();
4906 mlir::Operation *symbol = symbolTables.lookupSymbolIn(module, nameAttr);
4907 if (
auto llvmSymbol = mlir::dyn_cast<mlir::LLVM::GlobalOp>(symbol)) {
4908 eltType = llvmSymbol.getType();
4909 }
else if (
auto cirSymbol = mlir::dyn_cast<cir::GlobalOp>(symbol)) {
4910 eltType = converter->convertType(cirSymbol.getSymType());
4912 op->emitError() <<
"unexpected symbol type for " << symbol;
4916 return mlir::LLVM::AddressOfOp::create(
4917 rewriter, op->getLoc(),
4918 mlir::LLVM::LLVMPointerType::get(op->getContext()), nameAttr.getValue());
4921mlir::LogicalResult CIRToLLVMVTableAddrPointOpLowering::matchAndRewrite(
4922 cir::VTableAddrPointOp op, OpAdaptor adaptor,
4923 mlir::ConversionPatternRewriter &rewriter)
const {
4924 const mlir::TypeConverter *converter = getTypeConverter();
4925 mlir::Type targetType = converter->convertType(op.getType());
4928 mlir::Value symAddr = getValueForVTableSymbol(
4929 op, rewriter, symbolTables, converter, op.getNameAttr(), eltType);
4931 return op.emitError() <<
"Unable to get value for vtable symbol";
4934 0, op.getAddressPointAttr().getIndex(),
4935 op.getAddressPointAttr().getOffset()};
4937 assert(eltType &&
"Shouldn't ever be missing an eltType here");
4938 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
4939 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
4940 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, targetType, eltType,
4941 symAddr, offsets, inboundsNuw);
4942 return mlir::success();
4945mlir::LogicalResult CIRToLLVMVTableGetVPtrOpLowering::matchAndRewrite(
4946 cir::VTableGetVPtrOp op, OpAdaptor adaptor,
4947 mlir::ConversionPatternRewriter &rewriter)
const {
4951 mlir::Value srcVal = adaptor.getSrc();
4952 rewriter.replaceOp(op, srcVal);
4953 return mlir::success();
4956mlir::LogicalResult CIRToLLVMVTableGetVirtualFnAddrOpLowering::matchAndRewrite(
4957 cir::VTableGetVirtualFnAddrOp op, OpAdaptor adaptor,
4958 mlir::ConversionPatternRewriter &rewriter)
const {
4959 mlir::Type targetType = getTypeConverter()->convertType(op.getType());
4960 auto eltType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4963 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
4964 op, targetType, eltType, adaptor.getVptr(), offsets,
4965 mlir::LLVM::GEPNoWrapFlags::inbounds);
4966 return mlir::success();
4969mlir::LogicalResult CIRToLLVMVTTAddrPointOpLowering::matchAndRewrite(
4970 cir::VTTAddrPointOp op, OpAdaptor adaptor,
4971 mlir::ConversionPatternRewriter &rewriter)
const {
4972 const mlir::Type resultType = getTypeConverter()->convertType(op.getType());
4975 mlir::Value llvmAddr = adaptor.getSymAddr();
4977 if (op.getSymAddr()) {
4978 if (op.getOffset() == 0) {
4979 rewriter.replaceOp(op, {llvmAddr});
4980 return mlir::success();
4983 offsets.push_back(adaptor.getOffset());
4984 eltType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4988 op.getNameAttr(), eltType);
4989 assert(eltType &&
"Shouldn't ever be missing an eltType here");
4990 offsets.push_back(0);
4991 offsets.push_back(adaptor.getOffset());
4993 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
4994 op, resultType, eltType, llvmAddr, offsets,
4995 mlir::LLVM::GEPNoWrapFlags::inbounds);
4996 return mlir::success();
4999mlir::LogicalResult CIRToLLVMVecCreateOpLowering::matchAndRewrite(
5000 cir::VecCreateOp op, OpAdaptor adaptor,
5001 mlir::ConversionPatternRewriter &rewriter)
const {
5004 const cir::VectorType vecTy = op.getType();
5005 const mlir::Type llvmTy = typeConverter->convertType(vecTy);
5006 const mlir::Location loc = op.getLoc();
5007 mlir::Value result = mlir::LLVM::PoisonOp::create(rewriter, loc, llvmTy);
5008 assert(vecTy.getSize() == op.getElements().size() &&
5009 "cir.vec.create op count doesn't match vector type elements count");
5011 for (uint64_t i = 0; i < vecTy.getSize(); ++i) {
5012 const mlir::Value indexValue =
5013 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
5014 result = mlir::LLVM::InsertElementOp::create(
5015 rewriter, loc, result, adaptor.getElements()[i], indexValue);
5018 rewriter.replaceOp(op, result);
5019 return mlir::success();
5022mlir::LogicalResult CIRToLLVMVecExtractOpLowering::matchAndRewrite(
5023 cir::VecExtractOp op, OpAdaptor adaptor,
5024 mlir::ConversionPatternRewriter &rewriter)
const {
5025 rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractElementOp>(
5026 op, adaptor.getVec(), adaptor.getIndex());
5027 return mlir::success();
5030mlir::LogicalResult CIRToLLVMVecInsertOpLowering::matchAndRewrite(
5031 cir::VecInsertOp op, OpAdaptor adaptor,
5032 mlir::ConversionPatternRewriter &rewriter)
const {
5033 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertElementOp>(
5034 op, adaptor.getVec(), adaptor.getValue(), adaptor.getIndex());
5035 return mlir::success();
5038mlir::LogicalResult CIRToLLVMVecCmpOpLowering::matchAndRewrite(
5039 cir::VecCmpOp op, OpAdaptor adaptor,
5040 mlir::ConversionPatternRewriter &rewriter)
const {
5041 mlir::Type elementType = op.getLhs().getType().getElementType();
5042 mlir::Value bitResult;
5043 if (
auto intType = mlir::dyn_cast<cir::IntType>(elementType)) {
5044 bitResult = mlir::LLVM::ICmpOp::create(
5045 rewriter, op.getLoc(),
5047 adaptor.getLhs(), adaptor.getRhs());
5048 }
else if (
auto boolType = mlir::dyn_cast<cir::BoolType>(elementType)) {
5049 bitResult = mlir::LLVM::ICmpOp::create(
5050 rewriter, op.getLoc(),
5052 adaptor.getLhs(), adaptor.getRhs());
5053 }
else if (mlir::isa<cir::FPTypeInterface>(elementType)) {
5054 if (cir::FenvAttr fenv = op.getFenvAttr()) {
5055 auto i1VecTy = mlir::VectorType::get(op.getLhs().getType().getSize(),
5056 rewriter.getI1Type());
5058 adaptor.getLhs(), adaptor.getRhs(),
5059 op.getKind(), fenv, i1VecTy)
5062 bitResult = mlir::LLVM::FCmpOp::create(
5064 adaptor.getLhs(), adaptor.getRhs());
5067 return op.emitError() <<
"unsupported type for VecCmpOp: " << elementType;
5073 mlir::Type vecElemTy = op.getType().getElementType();
5074 if (isa<cir::IntType>(vecElemTy) &&
5075 cast<cir::IntType>(vecElemTy).getWidth() > 1)
5076 rewriter.replaceOpWithNewOp<mlir::LLVM::SExtOp>(
5077 op, typeConverter->convertType(op.getType()), bitResult);
5079 rewriter.replaceOp(op, bitResult);
5080 return mlir::success();
5083mlir::LogicalResult CIRToLLVMVecSplatOpLowering::matchAndRewrite(
5084 cir::VecSplatOp op, OpAdaptor adaptor,
5085 mlir::ConversionPatternRewriter &rewriter)
const {
5091 cir::VectorType vecTy = op.getType();
5092 mlir::Type llvmTy = typeConverter->convertType(vecTy);
5093 mlir::Location loc = op.getLoc();
5094 mlir::Value poison = mlir::LLVM::PoisonOp::create(rewriter, loc, llvmTy);
5096 mlir::Value elementValue = adaptor.getValue();
5097 if (elementValue.getDefiningOp<mlir::LLVM::PoisonOp>()) {
5100 rewriter.replaceOp(op, poison);
5101 return mlir::success();
5104 if (
auto constValue = elementValue.getDefiningOp<mlir::LLVM::ConstantOp>()) {
5105 if (
auto intAttr = dyn_cast<mlir::IntegerAttr>(constValue.getValue())) {
5106 mlir::DenseIntElementsAttr denseVec = mlir::DenseIntElementsAttr::get(
5107 mlir::cast<mlir::ShapedType>(llvmTy), intAttr.getValue());
5108 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
5109 op, denseVec.getType(), denseVec);
5110 return mlir::success();
5113 if (
auto fpAttr = dyn_cast<mlir::FloatAttr>(constValue.getValue())) {
5114 mlir::DenseFPElementsAttr denseVec = mlir::DenseFPElementsAttr::get(
5115 mlir::cast<mlir::ShapedType>(llvmTy), fpAttr.getValue());
5116 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
5117 op, denseVec.getType(), denseVec);
5118 return mlir::success();
5122 mlir::Value indexValue =
5123 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), 0);
5124 mlir::Value oneElement = mlir::LLVM::InsertElementOp::create(
5125 rewriter, loc, poison, elementValue, indexValue);
5127 rewriter.replaceOpWithNewOp<mlir::LLVM::ShuffleVectorOp>(op, oneElement,
5128 poison, zeroValues);
5129 return mlir::success();
5132mlir::LogicalResult CIRToLLVMVecShuffleOpLowering::matchAndRewrite(
5133 cir::VecShuffleOp op, OpAdaptor adaptor,
5134 mlir::ConversionPatternRewriter &rewriter)
const {
5140 op.getIndices().begin(), op.getIndices().end(),
5141 std::back_inserter(indices), [](mlir::Attribute intAttr) {
5142 return mlir::cast<cir::IntAttr>(intAttr).getValue().getSExtValue();
5144 rewriter.replaceOpWithNewOp<mlir::LLVM::ShuffleVectorOp>(
5145 op, adaptor.getVec1(), adaptor.getVec2(), indices);
5146 return mlir::success();
5149mlir::LogicalResult CIRToLLVMVecShuffleDynamicOpLowering::matchAndRewrite(
5150 cir::VecShuffleDynamicOp op, OpAdaptor adaptor,
5151 mlir::ConversionPatternRewriter &rewriter)
const {
5163 mlir::Location loc = op.getLoc();
5164 mlir::Value input = adaptor.getVec();
5165 mlir::Type llvmIndexVecType =
5166 getTypeConverter()->convertType(op.getIndices().getType());
5167 mlir::Type llvmIndexType = getTypeConverter()->convertType(
5168 op.getIndices().getType().getElementType());
5169 uint64_t numElements = op.getVec().getType().getSize();
5171 uint64_t maskBits = llvm::NextPowerOf2(numElements - 1) - 1;
5172 mlir::Value maskValue = mlir::LLVM::ConstantOp::create(
5173 rewriter, loc, llvmIndexType,
5174 rewriter.getIntegerAttr(llvmIndexType, maskBits));
5175 mlir::Value maskVector =
5176 mlir::LLVM::UndefOp::create(rewriter, loc, llvmIndexVecType);
5178 for (uint64_t i = 0; i < numElements; ++i) {
5179 mlir::Value idxValue =
5180 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
5181 maskVector = mlir::LLVM::InsertElementOp::create(rewriter, loc, maskVector,
5182 maskValue, idxValue);
5185 mlir::Value maskedIndices = mlir::LLVM::AndOp::create(
5186 rewriter, loc, llvmIndexVecType, adaptor.getIndices(), maskVector);
5187 mlir::Value result = mlir::LLVM::UndefOp::create(
5188 rewriter, loc, getTypeConverter()->convertType(op.getVec().getType()));
5189 for (uint64_t i = 0; i < numElements; ++i) {
5190 mlir::Value iValue =
5191 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
5192 mlir::Value indexValue = mlir::LLVM::ExtractElementOp::create(
5193 rewriter, loc, maskedIndices, iValue);
5194 mlir::Value valueAtIndex =
5195 mlir::LLVM::ExtractElementOp::create(rewriter, loc, input, indexValue);
5196 result = mlir::LLVM::InsertElementOp::create(rewriter, loc, result,
5197 valueAtIndex, iValue);
5199 rewriter.replaceOp(op, result);
5200 return mlir::success();
5203mlir::LogicalResult CIRToLLVMVecTernaryOpLowering::matchAndRewrite(
5204 cir::VecTernaryOp op, OpAdaptor adaptor,
5205 mlir::ConversionPatternRewriter &rewriter)
const {
5206 mlir::Value bitVec = adaptor.getCond();
5208 if (!isa<cir::BoolType>(op.getCond().getType().getElementType())) {
5210 bitVec = mlir::LLVM::ICmpOp::create(
5211 rewriter, op.getLoc(), mlir::LLVM::ICmpPredicate::ne, adaptor.getCond(),
5212 mlir::LLVM::ZeroOp::create(
5213 rewriter, op.getCond().getLoc(),
5214 typeConverter->convertType(op.getCond().getType())));
5217 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(
5218 op, bitVec, adaptor.getLhs(), adaptor.getRhs());
5219 return mlir::success();
5222mlir::LogicalResult CIRToLLVMComplexAddOpLowering::matchAndRewrite(
5223 cir::ComplexAddOp op, OpAdaptor adaptor,
5224 mlir::ConversionPatternRewriter &rewriter)
const {
5225 mlir::Value lhs = adaptor.getLhs();
5226 mlir::Value rhs = adaptor.getRhs();
5227 mlir::Location loc = op.getLoc();
5229 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
5230 mlir::Type complexElemTy =
5231 getTypeConverter()->convertType(
complexType.getElementType());
5232 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
5233 rewriter, loc, complexElemTy, lhs,
ArrayRef(int64_t{0}));
5234 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
5235 rewriter, loc, complexElemTy, lhs,
ArrayRef(int64_t{1}));
5236 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
5237 rewriter, loc, complexElemTy, rhs,
ArrayRef(int64_t{0}));
5238 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
5239 rewriter, loc, complexElemTy, rhs,
ArrayRef(int64_t{1}));
5241 mlir::Value newReal;
5242 mlir::Value newImag;
5243 if (complexElemTy.isInteger()) {
5244 newReal = mlir::LLVM::AddOp::create(rewriter, loc, complexElemTy, lhsReal,
5246 newImag = mlir::LLVM::AddOp::create(rewriter, loc, complexElemTy, lhsImag,
5251 newReal = mlir::LLVM::FAddOp::create(rewriter, loc, complexElemTy, lhsReal,
5253 newImag = mlir::LLVM::FAddOp::create(rewriter, loc, complexElemTy, lhsImag,
5257 mlir::Type complexLLVMTy =
5258 getTypeConverter()->convertType(op.getResult().getType());
5259 auto initialComplex =
5260 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), complexLLVMTy);
5262 auto realComplex = mlir::LLVM::InsertValueOp::create(
5263 rewriter, op->getLoc(), initialComplex, newReal,
ArrayRef(int64_t{0}));
5265 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
5266 op, realComplex, newImag,
ArrayRef(int64_t{1}));
5268 return mlir::success();
5271mlir::LogicalResult CIRToLLVMComplexCreateOpLowering::matchAndRewrite(
5272 cir::ComplexCreateOp op, OpAdaptor adaptor,
5273 mlir::ConversionPatternRewriter &rewriter)
const {
5274 mlir::Type complexLLVMTy =
5275 getTypeConverter()->convertType(op.getResult().getType());
5276 auto initialComplex =
5277 mlir::LLVM::UndefOp::create(rewriter, op->getLoc(), complexLLVMTy);
5279 auto realComplex = mlir::LLVM::InsertValueOp::create(
5280 rewriter, op->getLoc(), initialComplex, adaptor.getReal(),
5283 auto complex = mlir::LLVM::InsertValueOp::create(
5284 rewriter, op->getLoc(), realComplex, adaptor.getImag(),
5287 rewriter.replaceOp(op, complex);
5288 return mlir::success();
5291mlir::LogicalResult CIRToLLVMComplexRealOpLowering::matchAndRewrite(
5292 cir::ComplexRealOp op, OpAdaptor adaptor,
5293 mlir::ConversionPatternRewriter &rewriter)
const {
5294 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
5295 mlir::Value operand = adaptor.getOperand();
5296 if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) {
5297 operand = mlir::LLVM::ExtractValueOp::create(
5298 rewriter, op.getLoc(), resultLLVMTy, operand,
5301 rewriter.replaceOp(op, operand);
5302 return mlir::success();
5305mlir::LogicalResult CIRToLLVMComplexSubOpLowering::matchAndRewrite(
5306 cir::ComplexSubOp op, OpAdaptor adaptor,
5307 mlir::ConversionPatternRewriter &rewriter)
const {
5308 mlir::Value lhs = adaptor.getLhs();
5309 mlir::Value rhs = adaptor.getRhs();
5310 mlir::Location loc = op.getLoc();
5312 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
5313 mlir::Type complexElemTy =
5314 getTypeConverter()->convertType(
complexType.getElementType());
5315 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
5316 rewriter, loc, complexElemTy, lhs,
ArrayRef(int64_t{0}));
5317 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
5318 rewriter, loc, complexElemTy, lhs,
ArrayRef(int64_t{1}));
5319 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
5320 rewriter, loc, complexElemTy, rhs,
ArrayRef(int64_t{0}));
5321 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
5322 rewriter, loc, complexElemTy, rhs,
ArrayRef(int64_t{1}));
5324 mlir::Value newReal;
5325 mlir::Value newImag;
5326 if (complexElemTy.isInteger()) {
5327 newReal = mlir::LLVM::SubOp::create(rewriter, loc, complexElemTy, lhsReal,
5329 newImag = mlir::LLVM::SubOp::create(rewriter, loc, complexElemTy, lhsImag,
5334 newReal = mlir::LLVM::FSubOp::create(rewriter, loc, complexElemTy, lhsReal,
5336 newImag = mlir::LLVM::FSubOp::create(rewriter, loc, complexElemTy, lhsImag,
5340 mlir::Type complexLLVMTy =
5341 getTypeConverter()->convertType(op.getResult().getType());
5342 auto initialComplex =
5343 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), complexLLVMTy);
5345 auto realComplex = mlir::LLVM::InsertValueOp::create(
5346 rewriter, op->getLoc(), initialComplex, newReal,
ArrayRef(int64_t{0}));
5348 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
5349 op, realComplex, newImag,
ArrayRef(int64_t{1}));
5351 return mlir::success();
5354mlir::LogicalResult CIRToLLVMComplexImagOpLowering::matchAndRewrite(
5355 cir::ComplexImagOp op, OpAdaptor adaptor,
5356 mlir::ConversionPatternRewriter &rewriter)
const {
5357 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
5358 mlir::Value operand = adaptor.getOperand();
5359 mlir::Location loc = op.getLoc();
5361 if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) {
5362 operand = mlir::LLVM::ExtractValueOp::create(
5365 mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(resultLLVMTy);
5367 mlir::LLVM::ConstantOp::create(rewriter, loc, resultLLVMTy, zeroAttr);
5370 rewriter.replaceOp(op, operand);
5371 return mlir::success();
5375 mlir::MLIRContext *context,
5376 unsigned &storageSize) {
5377 return TypeSwitch<mlir::Type, mlir::IntegerType>(storageType)
5378 .Case<cir::ArrayType>([&](cir::ArrayType atTy) {
5379 storageSize = atTy.getSize() * 8;
5380 return mlir::IntegerType::get(context, storageSize);
5382 .Case<cir::IntType>([&](cir::IntType intTy) {
5383 storageSize = intTy.getWidth();
5384 return mlir::IntegerType::get(context, storageSize);
5386 .Default([](mlir::Type) -> mlir::IntegerType {
5388 "Either ArrayType or IntType expected for bitfields storage");
5392mlir::LogicalResult CIRToLLVMSetBitfieldOpLowering::matchAndRewrite(
5393 cir::SetBitfieldOp op, OpAdaptor adaptor,
5394 mlir::ConversionPatternRewriter &rewriter)
const {
5395 mlir::OpBuilder::InsertionGuard guard(rewriter);
5396 rewriter.setInsertionPoint(op);
5398 cir::BitfieldInfoAttr info = op.getBitfieldInfo();
5399 uint64_t size = info.getSize();
5400 uint64_t offset = info.getOffset();
5401 mlir::Type storageType = info.getStorageType();
5402 mlir::MLIRContext *context = storageType.getContext();
5404 unsigned storageSize = 0;
5406 mlir::IntegerType intType =
5407 computeBitfieldIntType(storageType, context, storageSize);
5409 mlir::Value srcVal = createIntCast(rewriter, adaptor.getSrc(), intType);
5410 unsigned srcWidth = storageSize;
5411 mlir::Value resultVal = srcVal;
5413 if (storageSize != size) {
5414 assert(storageSize > size &&
"Invalid bitfield size.");
5416 mlir::Value val = mlir::LLVM::LoadOp::create(
5417 rewriter, op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(),
5418 op.getIsVolatile());
5421 createAnd(rewriter, srcVal, llvm::APInt::getLowBitsSet(srcWidth, size));
5423 srcVal =
createShL(rewriter, srcVal, offset);
5427 ~llvm::APInt::getBitsSet(srcWidth, offset, offset + size));
5430 srcVal = mlir::LLVM::OrOp::create(rewriter, op.getLoc(), val, srcVal);
5433 mlir::LLVM::StoreOp::create(rewriter, op.getLoc(), srcVal, adaptor.getAddr(),
5434 op.getAlignment(), op.getIsVolatile());
5436 mlir::Type resultTy = getTypeConverter()->convertType(op.getType());
5438 if (info.getIsSigned()) {
5439 assert(size <= storageSize);
5440 unsigned highBits = storageSize - size;
5443 resultVal =
createShL(rewriter, resultVal, highBits);
5444 resultVal =
createAShR(rewriter, resultVal, highBits);
5449 mlir::cast<mlir::IntegerType>(resultTy),
5450 info.getIsSigned());
5452 rewriter.replaceOp(op, resultVal);
5453 return mlir::success();
5456mlir::LogicalResult CIRToLLVMComplexImagPtrOpLowering::matchAndRewrite(
5457 cir::ComplexImagPtrOp op, OpAdaptor adaptor,
5458 mlir::ConversionPatternRewriter &rewriter)
const {
5459 cir::PointerType operandTy = op.getOperand().getType();
5460 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
5461 mlir::Type elementLLVMTy =
5462 getTypeConverter()->convertType(operandTy.getPointee());
5464 mlir::LLVM::GEPArg gepIndices[2] = {{0}, {1}};
5465 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
5466 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
5467 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
5468 op, resultLLVMTy, elementLLVMTy, adaptor.getOperand(), gepIndices,
5470 return mlir::success();
5473mlir::LogicalResult CIRToLLVMComplexRealPtrOpLowering::matchAndRewrite(
5474 cir::ComplexRealPtrOp op, OpAdaptor adaptor,
5475 mlir::ConversionPatternRewriter &rewriter)
const {
5476 cir::PointerType operandTy = op.getOperand().getType();
5477 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
5478 mlir::Type elementLLVMTy =
5479 getTypeConverter()->convertType(operandTy.getPointee());
5481 mlir::LLVM::GEPArg gepIndices[2] = {0, 0};
5482 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
5483 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
5484 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
5485 op, resultLLVMTy, elementLLVMTy, adaptor.getOperand(), gepIndices,
5487 return mlir::success();
5490mlir::LogicalResult CIRToLLVMGetBitfieldOpLowering::matchAndRewrite(
5491 cir::GetBitfieldOp op, OpAdaptor adaptor,
5492 mlir::ConversionPatternRewriter &rewriter)
const {
5494 mlir::OpBuilder::InsertionGuard guard(rewriter);
5495 rewriter.setInsertionPoint(op);
5497 cir::BitfieldInfoAttr
info = op.getBitfieldInfo();
5498 uint64_t size =
info.getSize();
5499 uint64_t offset =
info.getOffset();
5500 mlir::Type storageType =
info.getStorageType();
5501 mlir::MLIRContext *context = storageType.getContext();
5502 unsigned storageSize = 0;
5504 mlir::IntegerType intType =
5507 mlir::Value val = mlir::LLVM::LoadOp::create(
5508 rewriter, op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(),
5509 op.getIsVolatile());
5510 val = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), intType, val);
5512 if (
info.getIsSigned()) {
5513 assert(
static_cast<unsigned>(offset + size) <= storageSize);
5514 unsigned highBits = storageSize - offset - size;
5515 val =
createShL(rewriter, val, highBits);
5516 val =
createAShR(rewriter, val, offset + highBits);
5520 if (
static_cast<unsigned>(offset) + size < storageSize)
5522 llvm::APInt::getLowBitsSet(storageSize, size));
5525 mlir::Type resTy = getTypeConverter()->convertType(op.getType());
5527 rewriter, val, mlir::cast<mlir::IntegerType>(resTy),
info.getIsSigned());
5528 rewriter.replaceOp(op, newOp);
5529 return mlir::success();
5532mlir::LogicalResult CIRToLLVMInlineAsmOpLowering::matchAndRewrite(
5533 cir::InlineAsmOp op, OpAdaptor adaptor,
5534 mlir::ConversionPatternRewriter &rewriter)
const {
5536 if (op.getNumResults())
5537 llResTy = getTypeConverter()->convertType(op.getType(0));
5539 cir::AsmFlavor dialect = op.getAsmFlavor();
5540 mlir::LLVM::AsmDialect llDialect = dialect == cir::AsmFlavor::x86_att
5541 ? mlir::LLVM::AsmDialect::AD_ATT
5542 : mlir::LLVM::AsmDialect::AD_Intel;
5545 StringRef llvmAttrName = mlir::LLVM::InlineAsmOp::getElementTypeAttrName();
5551 if (!op.getNumResults())
5552 opAttrs.push_back(mlir::Attribute());
5556 for (
auto const &[llvmOp, cirOp] :
5557 zip(adaptor.getAsmOperands(), op.getAsmOperands())) {
5558 append_range(llvmOperands, llvmOp);
5559 append_range(cirOperands, cirOp);
5564 for (
auto const &[cirOpAttr, cirOp] :
5565 zip(op.getOperandAttrs(), cirOperands)) {
5566 if (!mlir::isa<mlir::UnitAttr>(cirOpAttr)) {
5567 opAttrs.push_back(mlir::Attribute());
5572 cir::PointerType typ = mlir::cast<cir::PointerType>(cirOp.getType());
5574 *getTypeConverter(), dataLayout, typ.getPointee()));
5576 attrs.push_back(rewriter.getNamedAttr(llvmAttrName, typAttr));
5577 mlir::DictionaryAttr newDict = rewriter.getDictionaryAttr(attrs);
5578 opAttrs.push_back(newDict);
5581 rewriter.replaceOpWithNewOp<mlir::LLVM::InlineAsmOp>(
5582 op, llResTy, llvmOperands, op.getAsmStringAttr(), op.getConstraintsAttr(),
5583 op.getSideEffectsAttr(),
5586 mlir::LLVM::TailCallKindAttr::get(
5587 getContext(), mlir::LLVM::tailcallkind::TailCallKind::None),
5589 mlir::LLVM::AsmDialectAttr::get(getContext(), llDialect),
5590 rewriter.getArrayAttr(opAttrs));
5592 return mlir::success();
5595mlir::LogicalResult CIRToLLVMVAStartOpLowering::matchAndRewrite(
5596 cir::VAStartOp op, OpAdaptor adaptor,
5597 mlir::ConversionPatternRewriter &rewriter)
const {
5598 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
5599 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
5600 adaptor.getArgList());
5601 rewriter.replaceOpWithNewOp<mlir::LLVM::VaStartOp>(op, vaList);
5602 return mlir::success();
5605mlir::LogicalResult CIRToLLVMVAEndOpLowering::matchAndRewrite(
5606 cir::VAEndOp op, OpAdaptor adaptor,
5607 mlir::ConversionPatternRewriter &rewriter)
const {
5608 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
5609 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
5610 adaptor.getArgList());
5611 rewriter.replaceOpWithNewOp<mlir::LLVM::VaEndOp>(op, vaList);
5612 return mlir::success();
5615mlir::LogicalResult CIRToLLVMVACopyOpLowering::matchAndRewrite(
5616 cir::VACopyOp op, OpAdaptor adaptor,
5617 mlir::ConversionPatternRewriter &rewriter)
const {
5618 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
5619 auto dstList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
5620 adaptor.getDstList());
5621 auto srcList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
5622 adaptor.getSrcList());
5623 rewriter.replaceOpWithNewOp<mlir::LLVM::VaCopyOp>(op, dstList, srcList);
5624 return mlir::success();
5627mlir::LogicalResult CIRToLLVMVAArgOpLowering::matchAndRewrite(
5628 cir::VAArgOp op, OpAdaptor adaptor,
5629 mlir::ConversionPatternRewriter &rewriter)
const {
5631 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
5632 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
5633 adaptor.getArgList());
5635 mlir::Type llvmType =
5636 getTypeConverter()->convertType(op->getResultTypes().front());
5638 return mlir::failure();
5640 rewriter.replaceOpWithNewOp<mlir::LLVM::VaArgOp>(op, llvmType, vaList);
5641 return mlir::success();
5644mlir::LogicalResult CIRToLLVMLabelOpLowering::matchAndRewrite(
5645 cir::LabelOp op, OpAdaptor adaptor,
5646 mlir::ConversionPatternRewriter &rewriter)
const {
5647 mlir::MLIRContext *ctx = rewriter.getContext();
5648 mlir::Block *block = op->getBlock();
5651 if (block->isEntryBlock()) {
5652 mlir::Block *newBlock =
5653 rewriter.splitBlock(op->getBlock(), mlir::Block::iterator(op));
5654 rewriter.setInsertionPointToEnd(block);
5655 mlir::LLVM::BrOp::create(rewriter, op.getLoc(), newBlock);
5658 mlir::LLVM::BlockTagAttr::get(ctx, blockInfoAddr.getTagIndex());
5659 rewriter.setInsertionPoint(op);
5662 mlir::LLVM::BlockTagOp::create(rewriter, op->getLoc(), tagAttr);
5663 mlir::LLVM::LLVMFuncOp func = op->getParentOfType<mlir::LLVM::LLVMFuncOp>();
5664 auto blockInfoAttr =
5665 cir::BlockAddrInfoAttr::get(ctx, func.getSymName(), op.getLabel());
5666 blockInfoAddr.mapBlockTag(blockInfoAttr, blockTagOp);
5667 rewriter.eraseOp(op);
5669 return mlir::success();
5672mlir::LogicalResult CIRToLLVMBlockAddressOpLowering::matchAndRewrite(
5673 cir::BlockAddressOp op, OpAdaptor adaptor,
5674 mlir::ConversionPatternRewriter &rewriter)
const {
5675 mlir::MLIRContext *ctx = rewriter.getContext();
5677 mlir::LLVM::BlockTagOp matchLabel =
5678 blockInfoAddr.lookupBlockTag(op.getBlockAddrInfoAttr());
5679 mlir::LLVM::BlockTagAttr tagAttr;
5686 tagAttr = matchLabel.getTag();
5688 auto blkAddr = mlir::LLVM::BlockAddressAttr::get(
5689 rewriter.getContext(), op.getBlockAddrInfoAttr().getFunc(), tagAttr);
5690 rewriter.setInsertionPoint(op);
5691 auto newOp = mlir::LLVM::BlockAddressOp::create(
5692 rewriter, op.getLoc(), mlir::LLVM::LLVMPointerType::get(ctx), blkAddr);
5694 blockInfoAddr.addUnresolvedBlockAddress(newOp, op.getBlockAddrInfoAttr());
5695 rewriter.replaceOp(op, newOp);
5696 return mlir::success();
5699mlir::LogicalResult CIRToLLVMIndirectBrOpLowering::matchAndRewrite(
5700 cir::IndirectBrOp op, OpAdaptor adaptor,
5701 mlir::ConversionPatternRewriter &rewriter)
const {
5703 mlir::Value targetAddr = adaptor.getAddr();
5711 if (op.getPoison()) {
5712 auto llvmPtrType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
5714 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), llvmPtrType);
5717 rewriter.replaceOpWithNewOp<mlir::LLVM::IndirectBrOp>(
5718 op, targetAddr, adaptor.getSuccOperands(), op.getSuccessors());
5719 return mlir::success();
5722mlir::LogicalResult CIRToLLVMTokenNoneOpLowering::matchAndRewrite(
5723 cir::TokenNoneOp op, OpAdaptor adaptor,
5724 mlir::ConversionPatternRewriter &rewriter)
const {
5725 rewriter.replaceOpWithNewOp<mlir::LLVM::NoneTokenOp>(
5726 op, mlir::TokenType::get(rewriter.getContext()));
5727 return mlir::success();
5730mlir::LogicalResult CIRToLLVMCpuIdOpLowering::matchAndRewrite(
5731 cir::CpuIdOp op, OpAdaptor adaptor,
5732 mlir::ConversionPatternRewriter &rewriter)
const {
5733 mlir::Type i32Ty = rewriter.getI32Type();
5734 mlir::Type i64Ty = rewriter.getI64Type();
5735 mlir::Type i32PtrTy = mlir::LLVM::LLVMPointerType::get(i32Ty.getContext(), 0);
5737 mlir::Type cpuidRetTy = mlir::LLVM::LLVMStructType::getLiteral(
5738 rewriter.getContext(), {i32Ty, i32Ty, i32Ty, i32Ty});
5740 mlir::Value functionId = adaptor.getFunctionId();
5741 mlir::Value subFunctionId = adaptor.getSubFunctionId();
5743 StringRef asmString, constraints;
5744 mlir::ModuleOp moduleOp = op->getParentOfType<mlir::ModuleOp>();
5745 llvm::Triple triple(
5746 mlir::cast<mlir::StringAttr>(
5747 moduleOp->getAttr(cir::CIRDialect::getTripleAttrName()))
5749 if (triple.getArch() == llvm::Triple::x86) {
5750 asmString =
"cpuid";
5751 constraints =
"={ax},={bx},={cx},={dx},{ax},{cx}";
5754 asmString =
"xchgq %rbx, ${1:q}\n"
5756 "xchgq %rbx, ${1:q}";
5757 constraints =
"={ax},=r,={cx},={dx},0,2";
5760 mlir::Value inlineAsm =
5761 mlir::LLVM::InlineAsmOp::create(
5762 rewriter, op.getLoc(), cpuidRetTy, {functionId, subFunctionId},
5763 rewriter.getStringAttr(asmString),
5764 rewriter.getStringAttr(constraints),
5767 mlir::LLVM::TailCallKindAttr{},
5769 mlir::LLVM::AsmDialectAttr{},
5773 mlir::Value basePtr = adaptor.getCpuInfo();
5775 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
5776 unsigned alignment = layout.getTypeABIAlignment(i32Ty);
5777 for (
unsigned i = 0; i < 4; i++) {
5778 mlir::Value extracted =
5779 mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(), inlineAsm, i)
5781 mlir::Value index = mlir::LLVM::ConstantOp::create(
5782 rewriter, op.getLoc(), i64Ty, rewriter.getI64IntegerAttr(i));
5784 mlir::Value storePtr = mlir::LLVM::GEPOp::create(
5785 rewriter, op.getLoc(), i32PtrTy, i32Ty, basePtr,
5786 gepIndices, mlir::LLVM::GEPNoWrapFlags::none)
5788 mlir::LLVM::StoreOp::create(rewriter, op.getLoc(), extracted, storePtr,
5792 rewriter.eraseOp(op);
5793 return mlir::success();
5796mlir::LogicalResult CIRToLLVMMemChrOpLowering::matchAndRewrite(
5797 cir::MemChrOp op, OpAdaptor adaptor,
5798 mlir::ConversionPatternRewriter &rewriter)
const {
5799 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
5800 mlir::Type srcTy = getTypeConverter()->convertType(op.getSrc().getType());
5801 mlir::Type patternTy =
5802 getTypeConverter()->convertType(op.getPattern().getType());
5803 mlir::Type lenTy = getTypeConverter()->convertType(op.getLen().getType());
5805 mlir::LLVM::LLVMFunctionType::get(llvmPtrTy, {srcTy, patternTy, lenTy},
5807 llvm::StringRef fnName =
"memchr";
5809 mlir::Builder b(rewriter.getContext());
5810 mlir::NamedAttribute noundefAttr =
5811 b.getNamedAttr(
"llvm.noundef", b.getUnitAttr());
5812 mlir::DictionaryAttr noundefDict = mlir::DictionaryAttr::get(
5815 mlir::ArrayAttr argAttrs =
5816 mlir::ArrayAttr::get(rewriter.getContext(), argAttrVec);
5821 mlir::LLVM::CallOp newCall = rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(
5822 op, mlir::TypeRange{llvmPtrTy}, fnName,
5823 mlir::ValueRange{adaptor.getSrc(), adaptor.getPattern(),
5825 newCall.setArgAttrsAttr(argAttrs);
5826 return mlir::success();
5832 mlir::Location loc, mlir::Value inputPtr,
5833 uint64_t baseAlignment,
5834 cir::OffsetPairAttr paddingAttr) {
5839 uint64_t charWidth = 8;
5840 mlir::Type i8Ty = rewriter.getI8Type();
5841 mlir::Type ptrTy = mlir::LLVM::LLVMPointerType::get(i8Ty.getContext());
5843 auto startByte = paddingAttr.getStart() / charWidth;
5844 auto startBit = paddingAttr.getStart() % charWidth;
5845 auto endByte = paddingAttr.getEnd() / charWidth;
5846 auto endBit = paddingAttr.getEnd() % charWidth;
5848 if (startByte == endByte) {
5850 auto index = mlir::LLVM::ConstantOp::create(
5851 rewriter, loc, rewriter.getI32Type(), startByte);
5852 auto element = mlir::LLVM::GEPOp::create(rewriter, loc, ptrTy, i8Ty,
5855 uint64_t adjustedAlignment = llvm::MinAlign(baseAlignment, startByte);
5857 auto value = mlir::LLVM::LoadOp::create(rewriter, loc, i8Ty, element,
5862 uint8_t bitsToClear = ((1 << endBit) - 1) & ~((1 << startBit) - 1);
5863 uint8_t bitsToKeep = ~bitsToClear;
5865 mlir::LLVM::ConstantOp::create(rewriter, loc, i8Ty, bitsToKeep);
5866 auto newValue = mlir::LLVM::AndOp::create(rewriter, loc, value, maskValue);
5868 mlir::LLVM::StoreOp::create(rewriter, loc, newValue, element,
5872 if (startBit != 0) {
5873 auto index = mlir::LLVM::ConstantOp::create(
5874 rewriter, loc, rewriter.getI32Type(), startByte);
5875 auto element = mlir::LLVM::GEPOp::create(rewriter, loc, ptrTy, i8Ty,
5877 uint64_t adjustedAlignment = llvm::MinAlign(baseAlignment, startByte);
5879 auto value = mlir::LLVM::LoadOp::create(rewriter, loc, i8Ty, element,
5882 uint8_t bitsToClear = ((1 << (charWidth - startBit)) - 1) << startBit;
5883 uint8_t bitsToKeep = ~bitsToClear;
5885 mlir::LLVM::ConstantOp::create(rewriter, loc, i8Ty, bitsToKeep);
5887 mlir::LLVM::AndOp::create(rewriter, loc, value, maskValue);
5889 mlir::LLVM::StoreOp::create(rewriter, loc, newValue, element,
5895 for (
auto offset = startByte; offset < endByte; ++offset) {
5896 auto index = mlir::LLVM::ConstantOp::create(
5897 rewriter, loc, rewriter.getI32Type(), offset);
5898 auto element = mlir::LLVM::GEPOp::create(rewriter, loc, ptrTy, i8Ty,
5900 uint64_t adjustedAlignment = llvm::MinAlign(baseAlignment, offset);
5902 auto zero = mlir::LLVM::ConstantOp::create(rewriter, loc, i8Ty, 0);
5903 mlir::LLVM::StoreOp::create(rewriter, loc, zero, element,
5909 auto index = mlir::LLVM::ConstantOp::create(
5910 rewriter, loc, rewriter.getI32Type(), endByte);
5911 auto element = mlir::LLVM::GEPOp::create(rewriter, loc, ptrTy, i8Ty,
5913 uint64_t adjustedAlignment = llvm::MinAlign(baseAlignment, endByte);
5915 auto value = mlir::LLVM::LoadOp::create(rewriter, loc, i8Ty, element,
5918 uint8_t bitsToClear = (1 << endBit) - 1;
5919 uint8_t bitsToKeep = ~bitsToClear;
5921 mlir::LLVM::ConstantOp::create(rewriter, loc, i8Ty, bitsToKeep);
5923 mlir::LLVM::AndOp::create(rewriter, loc, value, maskValue);
5925 mlir::LLVM::StoreOp::create(rewriter, loc, newValue, element,
5931mlir::LogicalResult CIRToLLVMClearPaddingOpLowering::matchAndRewrite(
5932 cir::ClearPaddingOp op, OpAdaptor adaptor,
5933 mlir::ConversionPatternRewriter &rewriter)
const {
5935 mlir::Value inputPtr = adaptor.getArg();
5936 for (mlir::Attribute attr : op.getPadding())
5937 clearPadding(rewriter, op.getLoc(), inputPtr, op.getAlignment(),
5938 cast<cir::OffsetPairAttr>(attr));
5940 rewriter.eraseOp(op);
5941 return mlir::success();
5945 return std::make_unique<ConvertCIRToLLVMPass>();
5951 pm.addPass(mlir::omp::createMarkDeclareTargetPass());
5954 pm.addPass(mlir::omp::createHostOpFilteringPass());
5957std::unique_ptr<llvm::Module>
5959 bool enableOpenMP, StringRef mlirSaveTempsOutFile,
5960 llvm::vfs::FileSystem *fs) {
5961 llvm::TimeTraceScope scope(
"lower from CIR to LLVM directly");
5963 mlir::MLIRContext *mlirCtx = mlirModule.getContext();
5965 mlir::PassManager pm(mlirCtx);
5968 (void)mlir::applyPassManagerCLOptions(pm);
5970 if (mlir::failed(pm.run(mlirModule))) {
5973 "The pass manager failed to lower CIR to LLVMIR dialect!");
5976 if (!mlirSaveTempsOutFile.empty()) {
5978 llvm::raw_fd_ostream out(mlirSaveTempsOutFile, ec);
5980 mlirModule->print(out);
5983 mlir::registerBuiltinDialectTranslation(*mlirCtx);
5984 mlir::registerLLVMDialectTranslation(*mlirCtx);
5985 mlir::registerOpenMPDialectTranslation(*mlirCtx);
5988 llvm::TimeTraceScope translateScope(
"translateModuleToLLVMIR");
5990 StringRef moduleName = mlirModule.getName().value_or(
"CIRToLLVMModule");
5991 std::unique_ptr<llvm::Module> llvmModule = mlir::translateModuleToLLVMIR(
5992 mlirModule, llvmCtx, moduleName,
false, fs);
5996 report_fatal_error(
"Lowering from LLVMIR dialect to llvm IR failed!");
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 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 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::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 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)
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::SymbolRefAttr getComdatAttrHelper(mlir::ModuleOp modOp, mlir::OpBuilder &builder, StringRef symName, mlir::LLVM::ComdatOp &comdatOp)
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::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=nullptr, mlir::ArrayAttr resAttrs=nullptr)
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)
std::unique_ptr< llvm::Module > lowerDirectlyFromCIRToLLVMIR(mlir::ModuleOp mlirModule, llvm::LLVMContext &llvmCtx, bool enableOpenMP, llvm::StringRef mlirSaveTempsOutFile={}, llvm::vfs::FileSystem *fs=nullptr)
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 llvm::StringRef getLLVMSyncScope(cir::SyncScopeKind syncScope)
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 uint64_t getTypeSize(mlir::Type type, mlir::Operation &op)
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 llvm::StringLiteral getLLVMBinopForPostAtomic(cir::AtomicFetchKind k, bool isInt)
mlir::LLVM::Linkage convertLinkage(cir::GlobalLinkageKind linkage)
static void buildCtorDtorList(mlir::ModuleOp module, StringRef globalXtorName, StringRef llvmXtorName, llvm::function_ref< std::pair< StringRef, int >(mlir::Attribute)> createXtor)
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 bool isIntTypeUnsigned(mlir::Type type)
mlir::LogicalResult lowerConstrainableFPOp(mlir::Operation *op, mlir::ValueRange operands, cir::FenvAttr fenv, const mlir::TypeConverter &typeConverter, mlir::ConversionPatternRewriter &rewriter, llvm::StringRef constrainedMnemonic, bool hasRoundingMode)
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_elementwise_add_sat __builtin_elementwise_sub_sat uint32_t __packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 __packed_splat2 __packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 uint32_t
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 opCallCallConv()
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