18#include "mlir/Conversion/LLVMCommon/TypeConverter.h"
19#include "mlir/Conversion/OpenMPToLLVM/ConvertOpenMPToLLVM.h"
20#include "mlir/Dialect/DLTI/DLTI.h"
21#include "mlir/Dialect/Func/IR/FuncOps.h"
22#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
23#include "mlir/Dialect/LLVMIR/LLVMTypes.h"
24#include "mlir/Dialect/OpenMP/OpenMPDialect.h"
25#include "mlir/Dialect/OpenMP/Transforms/Passes.h"
26#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
27#include "mlir/IR/BuiltinAttributes.h"
28#include "mlir/IR/BuiltinDialect.h"
29#include "mlir/IR/BuiltinOps.h"
30#include "mlir/IR/Location.h"
31#include "mlir/IR/Types.h"
32#include "mlir/Pass/Pass.h"
33#include "mlir/Pass/PassManager.h"
34#include "mlir/Support/LLVM.h"
35#include "mlir/Target/LLVMIR/Dialect/Builtin/BuiltinToLLVMIRTranslation.h"
36#include "mlir/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.h"
37#include "mlir/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.h"
38#include "mlir/Target/LLVMIR/Export.h"
39#include "mlir/Transforms/DialectConversion.h"
48#include "llvm/ADT/MapVector.h"
49#include "llvm/ADT/StringMap.h"
50#include "llvm/ADT/TypeSwitch.h"
51#include "llvm/IR/Module.h"
52#include "llvm/Support/Casting.h"
53#include "llvm/Support/ErrorHandling.h"
54#include "llvm/Support/TimeProfiler.h"
55#include "llvm/Support/VirtualFileSystem.h"
56#include "llvm/Support/raw_ostream.h"
71mlir::Type elementTypeIfVector(mlir::Type type) {
72 return llvm::TypeSwitch<mlir::Type, mlir::Type>(type)
73 .Case<cir::VectorType, mlir::VectorType>(
74 [](
auto p) {
return p.getElementType(); })
75 .
Default([](mlir::Type p) {
return p; });
83 const mlir::DataLayout &dataLayout) {
84 uint64_t alignBits = ty.getABIAlignment(dataLayout, {}) * 8;
85 return llvm::alignTo(ty.getWidth(), alignBits);
94 const mlir::DataLayout &dataLayout) {
98 auto storageTy = mlir::IntegerType::get(ty.getContext(), storageBits);
99 uint64_t storeSize = storageBits / 8;
101 llvm::alignTo(storeSize, dataLayout.getTypeABIAlignment(storageTy));
102 return allocSize != storeSize;
109 mlir::DataLayout
const &dataLayout,
113 if (isa<cir::BoolType>(type)) {
114 return mlir::IntegerType::get(type.getContext(),
115 dataLayout.getTypeSizeInBits(type));
118 if (
auto vecTy = mlir::dyn_cast<cir::VectorType>(type)) {
119 if (mlir::isa<cir::BoolType>(vecTy.getElementType())) {
122 uint64_t bytePadded = std::max<uint64_t>(vecTy.getSize(), 8);
123 return mlir::IntegerType::get(type.getContext(), bytePadded);
131 if (
auto intTy = mlir::dyn_cast<cir::IntType>(type);
132 intTy && intTy.isBitInt()) {
135 return mlir::IntegerType::get(
139 return converter.convertType(type);
146 mlir::Type llvmMemType,
147 const mlir::DataLayout &dataLayout) {
148 if (
auto intTy = mlir::dyn_cast<cir::IntType>(cirType);
149 intTy && intTy.isBitInt())
150 return intTy.getABIAlignment(dataLayout, {});
151 return dataLayout.getTypeABIAlignment(llvmMemType);
155 mlir::IntegerType dstTy,
156 bool isSigned =
false) {
157 mlir::Type srcTy = src.getType();
158 assert(mlir::isa<mlir::IntegerType>(srcTy));
160 unsigned srcWidth = mlir::cast<mlir::IntegerType>(srcTy).getWidth();
161 unsigned dstWidth = mlir::cast<mlir::IntegerType>(dstTy).getWidth();
162 mlir::Location loc = src.getLoc();
164 if (dstWidth > srcWidth && isSigned)
165 return mlir::LLVM::SExtOp::create(bld, loc, dstTy, src);
166 if (dstWidth > srcWidth)
167 return mlir::LLVM::ZExtOp::create(bld, loc, dstTy, src);
168 if (dstWidth < srcWidth)
169 return mlir::LLVM::TruncOp::create(bld, loc, dstTy, src);
170 return mlir::LLVM::BitcastOp::create(bld, loc, dstTy, src);
180 const mlir::DataLayout &dataLayout, cir::IntType intTy,
181 mlir::Value value,
bool toMemory) {
183 if (storageBits == intTy.getWidth())
185 unsigned dstBits = toMemory ? storageBits : intTy.getWidth();
186 return createIntCast(rewriter, value, rewriter.getIntegerType(dstBits),
187 toMemory && intTy.isSigned());
190static mlir::LLVM::Visibility
192 switch (visibilityKind) {
193 case cir::VisibilityKind::Default:
194 return ::mlir::LLVM::Visibility::Default;
195 case cir::VisibilityKind::Hidden:
196 return ::mlir::LLVM::Visibility::Hidden;
197 case cir::VisibilityKind::Protected:
198 return ::mlir::LLVM::Visibility::Protected;
204 mlir::Value srcVec,
unsigned numElementsDst) {
205 auto srcTy = mlir::cast<mlir::VectorType>(srcVec.getType());
206 unsigned numElementsSrc = srcTy.getNumElements();
207 if (numElementsSrc == numElementsDst)
211 for (
unsigned i : llvm::seq(std::min(numElementsDst, numElementsSrc)))
214 mlir::Location loc = srcVec.getLoc();
215 auto poison = mlir::LLVM::PoisonOp::create(rewriter, loc, srcVec.getType());
216 return mlir::LLVM::ShuffleVectorOp::create(rewriter, loc, srcVec, poison,
224 const mlir::TypeConverter &converter,
225 mlir::DataLayout
const &dataLayout,
226 cir::LoadOp op, mlir::Value value) {
228 if (
auto boolTy = mlir::dyn_cast<cir::BoolType>(op.getType())) {
230 assert(value.getType().isInteger(dataLayout.getTypeSizeInBits(boolTy)));
235 if (
auto vecTy = mlir::dyn_cast<cir::VectorType>(op.getType())) {
236 if (mlir::isa<cir::BoolType>(vecTy.getElementType())) {
237 auto rawIntTy = mlir::cast<mlir::IntegerType>(value.getType());
239 cir::VectorType::get(vecTy.getElementType(), rawIntTy.getWidth());
240 mlir::Type mlirVecTy = converter.convertType(paddedVecTy);
242 auto v = mlir::LLVM::BitcastOp::create(rewriter, value.getLoc(),
250 if (
auto intTy = mlir::dyn_cast<cir::IntType>(op.getType());
251 intTy && intTy.isBitInt())
261static mlir::Value
emitToMemory(mlir::ConversionPatternRewriter &rewriter,
262 mlir::DataLayout
const &dataLayout,
263 mlir::Type origType, mlir::Value value) {
266 if (
auto boolTy = mlir::dyn_cast<cir::BoolType>(origType)) {
268 mlir::IntegerType memType =
269 rewriter.getIntegerType(dataLayout.getTypeSizeInBits(boolTy));
274 if (
auto vecTy = mlir::dyn_cast<cir::VectorType>(origType)) {
275 if (mlir::isa<cir::BoolType>(vecTy.getElementType())) {
276 uint64_t bytePadded = std::max<uint64_t>(vecTy.getSize(), 8);
277 auto resultTy = mlir::IntegerType::get(origType.getContext(), bytePadded);
279 return mlir::LLVM::BitcastOp::create(rewriter, value.getLoc(), resultTy,
285 if (
auto intTy = mlir::dyn_cast<cir::IntType>(origType);
286 intTy && intTy.isBitInt())
294 using CIR = cir::GlobalLinkageKind;
295 using LLVM = mlir::LLVM::Linkage;
298 case CIR::AppendingLinkage:
299 return LLVM::Appending;
300 case CIR::AvailableExternallyLinkage:
301 return LLVM::AvailableExternally;
302 case CIR::CommonLinkage:
304 case CIR::ExternalLinkage:
305 return LLVM::External;
306 case CIR::ExternalWeakLinkage:
307 return LLVM::ExternWeak;
308 case CIR::InternalLinkage:
309 return LLVM::Internal;
310 case CIR::LinkOnceAnyLinkage:
311 return LLVM::Linkonce;
312 case CIR::LinkOnceODRLinkage:
313 return LLVM::LinkonceODR;
314 case CIR::PrivateLinkage:
315 return LLVM::Private;
316 case CIR::WeakAnyLinkage:
318 case CIR::WeakODRLinkage:
319 return LLVM::WeakODR;
321 llvm_unreachable(
"Unknown CIR linkage type");
325 using CIR = cir::CallingConv;
326 using LLVM = mlir::LLVM::CConv;
328 switch (callingConv) {
331 case CIR::SpirKernel:
332 return LLVM::SPIR_KERNEL;
333 case CIR::SpirFunction:
334 return LLVM::SPIR_FUNC;
336 return LLVM::PTX_Kernel;
337 case CIR::AMDGPUKernel:
338 return LLVM::AMDGPU_KERNEL;
340 llvm_unreachable(
"Unknown calling convention");
343mlir::LogicalResult CIRToLLVMCopyOpLowering::matchAndRewrite(
344 cir::CopyOp op, OpAdaptor adaptor,
345 mlir::ConversionPatternRewriter &rewriter)
const {
346 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
347 const mlir::Value
length = mlir::LLVM::ConstantOp::create(
348 rewriter, op.getLoc(), rewriter.getI64Type(),
349 op.getCopySizeInBytes(layout));
353 *getTypeConverter(), dataLayout, op.getDst().getType().getPointee()));
355 *getTypeConverter(), dataLayout, op.getSrc().getType().getPointee()));
357 mlir::NamedAttribute dstAlignAttr = rewriter.getNamedAttr(
358 mlir::LLVM::LLVMDialect::getAlignAttrName(),
359 rewriter.getI64IntegerAttr(op.getDstAlignment().value_or(dstTypeAlign)));
360 mlir::NamedAttribute srcAlignAttr = rewriter.getNamedAttr(
361 mlir::LLVM::LLVMDialect::getAlignAttrName(),
362 rewriter.getI64IntegerAttr(op.getSrcAlignment().value_or(srcTypeAlign)));
363 mlir::ArrayAttr argAttrs = rewriter.getArrayAttr({
364 rewriter.getDictionaryAttr({dstAlignAttr}),
365 rewriter.getDictionaryAttr({srcAlignAttr}),
368 rewriter.replaceOpWithNewOp<mlir::LLVM::MemcpyOp>(
369 op, adaptor.getDst(), adaptor.getSrc(),
length, op.getIsVolatile(),
371 nullptr,
nullptr, argAttrs,
373 return mlir::success();
376mlir::LogicalResult CIRToLLVMMemCpyOpLowering::matchAndRewrite(
377 cir::MemCpyOp op, OpAdaptor adaptor,
378 mlir::ConversionPatternRewriter &rewriter)
const {
379 rewriter.replaceOpWithNewOp<mlir::LLVM::MemcpyOp>(
380 op, adaptor.getDst(), adaptor.getSrc(), adaptor.getLen(),
382 return mlir::success();
385mlir::LogicalResult CIRToLLVMMemMoveOpLowering::matchAndRewrite(
386 cir::MemMoveOp op, OpAdaptor adaptor,
387 mlir::ConversionPatternRewriter &rewriter)
const {
388 rewriter.replaceOpWithNewOp<mlir::LLVM::MemmoveOp>(
389 op, adaptor.getDst(), adaptor.getSrc(), adaptor.getLen(),
391 return mlir::success();
394mlir::LogicalResult CIRToLLVMMemSetOpLowering::matchAndRewrite(
395 cir::MemSetOp op, OpAdaptor adaptor,
396 mlir::ConversionPatternRewriter &rewriter)
const {
398 auto memset = rewriter.replaceOpWithNewOp<mlir::LLVM::MemsetOp>(
399 op, adaptor.getDst(), adaptor.getVal(), adaptor.getLen(),
402 if (op.getAlignmentAttr()) {
404 llvm::SmallVector<mlir::Attribute> attrs{
memset.getNumOperands(),
405 rewriter.getDictionaryAttr({})};
406 llvm::SmallVector<mlir::NamedAttribute> destAttrs;
408 {mlir::LLVM::LLVMDialect::getAlignAttrName(), op.getAlignmentAttr()});
409 attrs[
memset.odsIndex_dst] = rewriter.getDictionaryAttr(destAttrs);
411 auto arrayAttr = rewriter.getArrayAttr(attrs);
412 memset.setArgAttrsAttr(arrayAttr);
415 return mlir::success();
419 mlir::Value llvmSrc, mlir::Type llvmDstIntTy,
421 uint64_t cirDstIntWidth) {
422 if (cirSrcWidth == cirDstIntWidth)
425 auto loc = llvmSrc.getLoc();
426 if (cirSrcWidth < cirDstIntWidth) {
428 return mlir::LLVM::ZExtOp::create(rewriter, loc, llvmDstIntTy, llvmSrc);
429 return mlir::LLVM::SExtOp::create(rewriter, loc, llvmDstIntTy, llvmSrc);
433 return mlir::LLVM::TruncOp::create(rewriter, loc, llvmDstIntTy, llvmSrc);
439 mlir::ConversionPatternRewriter &rewriter,
440 mlir::SymbolTableCollection &symbolTables,
441 const mlir::TypeConverter *converter,
443 : parentOp(parentOp), rewriter(rewriter), symbolTables(symbolTables),
444 converter(converter), blockInfoAddr(blockInfoAddr) {}
446#define GET_CIR_ATTR_TO_VALUE_VISITOR_DECLS
447#include "clang/CIR/Dialect/IR/CIRLowering.inc"
448#undef GET_CIR_ATTR_TO_VALUE_VISITOR_DECLS
451 mlir::Operation *parentOp;
452 mlir::ConversionPatternRewriter &rewriter;
453 mlir::SymbolTableCollection &symbolTables;
454 const mlir::TypeConverter *converter;
457 LLVMBlockAddressInfo *blockInfoAddr;
462 const mlir::Attribute attr,
463 mlir::ConversionPatternRewriter &rewriter,
464 mlir::SymbolTableCollection &symbolTables,
465 const mlir::TypeConverter *converter,
467 CIRAttrToValue valueConverter(parentOp, rewriter, symbolTables, converter,
469 mlir::Value value = valueConverter.visit(attr);
471 llvm_unreachable(
"unhandled attribute type");
476 cir::SideEffect sideEffect,
477 mlir::LLVM::MemoryEffectsAttr &memoryEffect,
478 bool &noUnwind,
bool &willReturn,
480 using mlir::LLVM::ModRefInfo;
482 switch (sideEffect) {
483 case cir::SideEffect::All:
485 noUnwind = isNothrow;
489 case cir::SideEffect::Pure:
490 memoryEffect = mlir::LLVM::MemoryEffectsAttr::get(
491 callOp->getContext(), ModRefInfo::Ref,
501 case cir::SideEffect::Const:
502 memoryEffect = mlir::LLVM::MemoryEffectsAttr::get(
503 callOp->getContext(), ModRefInfo::NoModRef,
504 ModRefInfo::NoModRef,
505 ModRefInfo::NoModRef,
506 ModRefInfo::NoModRef,
507 ModRefInfo::NoModRef,
508 ModRefInfo::NoModRef);
514 noReturn = callOp->hasAttr(CIRDialect::getNoReturnAttrName());
517static mlir::LLVM::CallIntrinsicOp
519 mlir::Location loc,
const llvm::Twine &intrinsicName,
520 mlir::Type resultTy, mlir::ValueRange operands,
521 mlir::LLVM::FastmathFlags fastmathFlags = {}) {
522 auto intrinsicNameAttr =
523 mlir::StringAttr::get(rewriter.getContext(), intrinsicName);
525 mlir::LLVM::FastmathFlagsAttr::get(rewriter.getContext(), fastmathFlags);
529 return mlir::LLVM::CallIntrinsicOp::create(
530 rewriter, loc, mlir::TypeRange{resultTy}, intrinsicNameAttr, operands,
532 return mlir::LLVM::CallIntrinsicOp::create(rewriter, loc, intrinsicNameAttr,
537 mlir::ConversionPatternRewriter &rewriter, mlir::Operation *op,
538 const llvm::Twine &intrinsicName, mlir::Type resultTy,
539 mlir::ValueRange operands, mlir::LLVM::FastmathFlags fastmathFlags = {}) {
541 rewriter, op->getLoc(), intrinsicName, resultTy, operands, fastmathFlags);
542 rewriter.replaceOp(op, callIntrinOp.getOperation());
547 std::optional<cir::FPDynamicRoundingMode> rounding =
548 fenv.getDynamicRoundingMode();
550 return "round.tonearest";
552 case cir::FPDynamicRoundingMode::ToNearest:
553 return "round.tonearest";
554 case cir::FPDynamicRoundingMode::Downward:
555 return "round.downward";
556 case cir::FPDynamicRoundingMode::Upward:
557 return "round.upward";
558 case cir::FPDynamicRoundingMode::UpwardZero:
559 return "round.towardzero";
560 case cir::FPDynamicRoundingMode::ToNearestAway:
561 return "round.tonearestaway";
562 case cir::FPDynamicRoundingMode::Unknown:
563 return "round.dynamic";
565 llvm_unreachable(
"unknown FP dynamic rounding mode");
569 std::optional<cir::FPExceptionMode> exceptMode = fenv.getExceptMode();
570 if (exceptMode == cir::FPExceptionMode::Masked)
571 return "fpexcept.ignore";
572 mlir::BoolAttr strictExcept = fenv.getStrictExcept();
574 return "fpexcept.ignore";
575 return strictExcept.getValue() ?
"fpexcept.strict" :
"fpexcept.maytrap";
580 mlir::Location loc, llvm::StringRef str) {
581 auto mdString = mlir::LLVM::MDStringAttr::get(
582 rewriter.getContext(), mlir::StringAttr::get(rewriter.getContext(), str));
583 return mlir::LLVM::MetadataAsValueOp::create(rewriter, loc, mdString);
587 mlir::Operation *op, mlir::ValueRange operands, cir::FenvAttr fenv,
588 mlir::Type llvmResTy, mlir::ConversionPatternRewriter &rewriter,
589 llvm::StringRef constrainedMnemonic,
bool hasRoundingMode,
590 mlir::LLVM::FastmathFlags fastmathFlags) {
591 mlir::Location loc = op->getLoc();
600 rewriter, op,
"llvm.experimental.constrained." + constrainedMnemonic,
601 llvmResTy, callOperands, fastmathFlags);
602 return mlir::success();
605template <
typename LLVMOp>
607 mlir::Operation *op, mlir::ValueRange operands, cir::FenvAttr fenv,
608 const mlir::TypeConverter &typeConverter,
609 mlir::ConversionPatternRewriter &rewriter,
610 llvm::StringRef constrainedMnemonic,
bool hasRoundingMode) {
611 mlir::Type llvmResTy = typeConverter.convertType(op->getResultTypes()[0]);
613 return op->emitError(
"expected LLVM result type for floating-point op");
616 rewriter.replaceOpWithNewOp<LLVMOp>(op, llvmResTy, operands);
617 return mlir::success();
621 constrainedMnemonic, hasRoundingMode);
624mlir::LogicalResult CIRToLLVMLLVMIntrinsicCallOpLowering::matchAndRewrite(
625 cir::LLVMIntrinsicCallOp op, OpAdaptor adaptor,
626 mlir::ConversionPatternRewriter &rewriter)
const {
629 mlir::Type llvmResTy;
630 if (op->getNumResults() != 0) {
631 llvmResTy = getTypeConverter()->convertType(op->getResultTypes()[0]);
633 return op.emitError(
"expected LLVM result type");
635 StringRef name = op.getIntrinsicName();
648 adaptor.getOperands());
649 return mlir::success();
653mlir::Value CIRAttrToValue::visitCirAttr(cir::BoolAttr boolAttr) {
654 mlir::Location loc = parentOp->getLoc();
655 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
656 mlir::Value boolVal = mlir::LLVM::ConstantOp::create(
657 rewriter, loc, converter->convertType(boolAttr.getType()),
658 boolAttr.getValue());
659 return emitToMemory(rewriter, layout, boolAttr.getType(), boolVal);
663mlir::Value CIRAttrToValue::visitCirAttr(cir::IntAttr intAttr) {
664 mlir::Location loc = parentOp->getLoc();
665 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
669 mlir::Value val = mlir::LLVM::ConstantOp::create(
670 rewriter, loc, converter->convertType(intAttr.getType()),
672 return emitToMemory(rewriter, layout, intAttr.getType(), val);
676mlir::Value CIRAttrToValue::visitCirAttr(cir::FPAttr fltAttr) {
677 mlir::Location loc = parentOp->getLoc();
678 return mlir::LLVM::ConstantOp::create(
679 rewriter, loc, converter->convertType(fltAttr.getType()),
684mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstComplexAttr complexAttr) {
685 cir::ComplexType
complexType = complexAttr.getType();
686 mlir::Type complexElemTy =
complexType.getElementType();
687 mlir::Type complexElemLLVMTy = converter->convertType(complexElemTy);
689 mlir::Attribute components[2];
690 if (
const auto intType = mlir::dyn_cast<cir::IntType>(complexElemTy)) {
691 components[0] = rewriter.getIntegerAttr(
693 mlir::cast<cir::IntAttr>(complexAttr.getReal()).getValue());
694 components[1] = rewriter.getIntegerAttr(
696 mlir::cast<cir::IntAttr>(complexAttr.getImag()).getValue());
698 components[0] = rewriter.getFloatAttr(
700 mlir::cast<cir::FPAttr>(complexAttr.getReal()).getValue());
701 components[1] = rewriter.getFloatAttr(
703 mlir::cast<cir::FPAttr>(complexAttr.getImag()).getValue());
706 mlir::Location loc = parentOp->getLoc();
707 return mlir::LLVM::ConstantOp::create(
708 rewriter, loc, converter->convertType(complexAttr.getType()),
709 rewriter.getArrayAttr(components));
713mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstPtrAttr ptrAttr) {
714 mlir::Location loc = parentOp->getLoc();
715 if (ptrAttr.isNullValue()) {
716 return mlir::LLVM::ZeroOp::create(
717 rewriter, loc, converter->convertType(ptrAttr.getType()));
719 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
720 mlir::Value ptrVal = mlir::LLVM::ConstantOp::create(
722 rewriter.getIntegerType(layout.getTypeSizeInBits(ptrAttr.getType())),
723 ptrAttr.getValue().getInt());
724 return mlir::LLVM::IntToPtrOp::create(
725 rewriter, loc, converter->convertType(ptrAttr.getType()), ptrVal);
729mlir::Value CIRAttrToValue::visitCirAttr(cir::BlockAddrInfoAttr blockAddrInfo) {
730 assert(blockInfoAddr &&
731 "block address lowering requires LLVMBlockAddressInfo");
736 mlir::Location loc = parentOp->getLoc();
737 mlir::LLVM::BlockTagOp matchLabel =
738 blockInfoAddr->lookupBlockTag(blockAddrInfo);
739 mlir::LLVM::BlockTagAttr tagAttr =
740 matchLabel ? matchLabel.getTag() : mlir::LLVM::BlockTagAttr{};
741 auto blkAddr = mlir::LLVM::BlockAddressAttr::get(
742 rewriter.getContext(), blockAddrInfo.getFunc(), tagAttr);
743 auto blockAddressOp = mlir::LLVM::BlockAddressOp::create(
744 rewriter, loc, mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
747 blockInfoAddr->addUnresolvedBlockAddress(blockAddressOp, blockAddrInfo);
748 return blockAddressOp;
752mlir::Value CIRAttrToValue::visitCirAttr(cir::BlockAddrDiffAttr blockAddrDiff) {
753 assert(blockInfoAddr &&
754 "block address lowering requires LLVMBlockAddressInfo");
760 mlir::Location loc = parentOp->getLoc();
761 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
762 mlir::MLIRContext *ctx = rewriter.getContext();
763 auto ptrTy = mlir::LLVM::LLVMPointerType::get(ctx);
765 auto emitBlockAddr = [&](mlir::StringAttr label) -> mlir::Value {
766 auto info = cir::BlockAddrInfoAttr::get(
767 ctx, blockAddrDiff.getFunc().getValue(), label.getValue());
768 mlir::LLVM::BlockTagOp matchLabel = blockInfoAddr->lookupBlockTag(info);
769 mlir::LLVM::BlockTagAttr tagAttr =
770 matchLabel ? matchLabel.getTag() : mlir::LLVM::BlockTagAttr{};
771 auto blkAddr = mlir::LLVM::BlockAddressAttr::get(
772 ctx, blockAddrDiff.getFunc(), tagAttr);
774 mlir::LLVM::BlockAddressOp::create(rewriter, loc, ptrTy, blkAddr);
776 blockInfoAddr->addUnresolvedBlockAddress(addrOp, info);
780 mlir::Value lhsAddr = emitBlockAddr(blockAddrDiff.getLhsLabel());
781 mlir::Value rhsAddr = emitBlockAddr(blockAddrDiff.getRhsLabel());
787 mlir::Type intptrTy =
788 rewriter.getIntegerType(layout.getTypeSizeInBits(ptrTy));
790 mlir::LLVM::PtrToIntOp::create(rewriter, loc, intptrTy, lhsAddr);
792 mlir::LLVM::PtrToIntOp::create(rewriter, loc, intptrTy, rhsAddr);
793 mlir::Value diffVal =
794 mlir::LLVM::SubOp::create(rewriter, loc, lhsInt, rhsInt);
796 mlir::Type resultTy = converter->convertType(blockAddrDiff.getType());
797 mlir::Value result = diffVal;
798 if (resultTy != intptrTy)
799 result = mlir::LLVM::TruncOp::create(rewriter, loc, resultTy, diffVal);
804mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstArrayAttr attr) {
805 mlir::Type llvmTy = converter->convertType(
attr.getType());
806 mlir::DataLayout dataLayout(parentOp->getParentOfType<mlir::ModuleOp>());
808 mlir::Location loc = parentOp->getLoc();
813 if (std::optional<mlir::Attribute> denseAttr =
815 return mlir::LLVM::ConstantOp::create(rewriter, loc, llvmTy, *denseAttr);
817 if (
attr.hasTrailingZeros())
818 result = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmTy);
820 result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
823 if (
auto arrayAttr = mlir::dyn_cast<mlir::ArrayAttr>(
attr.getElts())) {
824 for (
auto [idx, elt] : llvm::enumerate(arrayAttr)) {
825 mlir::Value init = visit(elt);
827 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
829 }
else if (
auto strAttr = mlir::dyn_cast<mlir::StringAttr>(
attr.getElts())) {
832 auto arrayTy = mlir::dyn_cast<cir::ArrayType>(strAttr.getType());
833 assert(arrayTy &&
"String attribute must have an array type");
834 mlir::Type eltTy = arrayTy.getElementType();
835 for (
auto [idx, elt] : llvm::enumerate(strAttr)) {
836 auto init = mlir::LLVM::ConstantOp::create(
837 rewriter, loc, converter->convertType(eltTy), elt);
839 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
842 llvm_unreachable(
"unexpected ConstArrayAttr elements");
849mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstRecordAttr constRecord) {
850 mlir::Type llvmTy = converter->convertType(constRecord.getType());
851 mlir::DataLayout dataLayout(parentOp->getParentOfType<mlir::ModuleOp>());
852 llvm::SmallVector<unsigned> paddingAddedIndexes;
854 paddingAddedIndexes);
855 const mlir::Location loc = parentOp->getLoc();
856 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
859 auto paddingItr = paddingAddedIndexes.begin();
862 for (
auto [idx, elt] : llvm::enumerate(constRecord.getMembers())) {
863 if (paddingItr != paddingAddedIndexes.end() && *paddingItr == idx) {
868 mlir::Value init = visit(elt);
869 result = mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init,
878mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstVectorAttr attr) {
879 const mlir::Type llvmTy = converter->convertType(
attr.getType());
880 const mlir::Location loc = parentOp->getLoc();
882 SmallVector<mlir::Attribute> mlirValues;
883 for (
const mlir::Attribute elementAttr :
attr.getElts()) {
884 mlir::Attribute mlirAttr;
885 if (
auto intAttr = mlir::dyn_cast<cir::IntAttr>(elementAttr)) {
886 mlirAttr = rewriter.getIntegerAttr(
887 converter->convertType(intAttr.getType()), intAttr.getValue());
888 }
else if (
auto floatAttr = mlir::dyn_cast<cir::FPAttr>(elementAttr)) {
889 mlirAttr = rewriter.getFloatAttr(
890 converter->convertType(floatAttr.getType()), floatAttr.getValue());
891 }
else if (
auto boolAttr = mlir::dyn_cast<cir::BoolAttr>(elementAttr)) {
892 mlirAttr = rewriter.getBoolAttr(boolAttr.getValue());
894 llvm_unreachable(
"vector constant with an element that is neither an "
895 "int, a float, or a bool");
897 mlirValues.push_back(mlirAttr);
900 return mlir::LLVM::ConstantOp::create(
901 rewriter, loc, llvmTy,
902 mlir::DenseElementsAttr::get(mlir::cast<mlir::ShapedType>(llvmTy),
907mlir::Value CIRAttrToValue::visitCirAttr(cir::GlobalViewAttr globalAttr) {
908 auto moduleOp = parentOp->getParentOfType<mlir::ModuleOp>();
909 mlir::DataLayout dataLayout(moduleOp);
910 mlir::Type sourceType;
911 unsigned sourceAddrSpace = 0;
912 llvm::StringRef symName;
913 mlir::Operation *sourceSymbol =
914 symbolTables.lookupSymbolIn(moduleOp, globalAttr.getSymbol());
915 if (
auto llvmSymbol = dyn_cast<mlir::LLVM::GlobalOp>(sourceSymbol)) {
916 sourceType = llvmSymbol.getType();
917 symName = llvmSymbol.getSymName();
918 sourceAddrSpace = llvmSymbol.getAddrSpace();
919 }
else if (
auto cirSymbol = dyn_cast<cir::GlobalOp>(sourceSymbol)) {
922 symName = cirSymbol.getSymName();
923 if (
auto targetAS = mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
924 cirSymbol.getAddrSpaceAttr()))
925 sourceAddrSpace = targetAS.getValue();
926 }
else if (
auto llvmFun = dyn_cast<mlir::LLVM::LLVMFuncOp>(sourceSymbol)) {
927 sourceType = llvmFun.getFunctionType();
928 symName = llvmFun.getSymName();
929 }
else if (
auto fun = dyn_cast<cir::FuncOp>(sourceSymbol)) {
930 sourceType = converter->convertType(fun.getFunctionType());
931 symName = fun.getSymName();
932 }
else if (
auto alias = dyn_cast<mlir::LLVM::AliasOp>(sourceSymbol)) {
933 sourceType = alias.getType();
934 symName = alias.getSymName();
936 llvm_unreachable(
"Unexpected GlobalOp type");
939 mlir::Location loc = parentOp->getLoc();
940 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
942 mlir::LLVM::LLVMPointerType::get(rewriter.getContext(), sourceAddrSpace),
945 if (globalAttr.getIndices()) {
946 llvm::SmallVector<mlir::LLVM::GEPArg> indices;
948 if (mlir::isa<mlir::LLVM::LLVMArrayType, mlir::LLVM::LLVMStructType>(
950 indices.push_back(0);
952 for (mlir::Attribute idx : globalAttr.getIndices()) {
953 auto intAttr = mlir::cast<mlir::IntegerAttr>(idx);
954 indices.push_back(intAttr.getValue().getSExtValue());
956 mlir::Type resTy = addrOp.getType();
957 mlir::Type eltTy = converter->convertType(sourceType);
959 mlir::LLVM::GEPOp::create(rewriter, loc, resTy, eltTy, addrOp, indices,
960 mlir::LLVM::GEPNoWrapFlags::none);
967 if (
auto intTy = mlir::dyn_cast<cir::IntType>(globalAttr.getType())) {
968 mlir::Type llvmDstTy = converter->convertType(globalAttr.getType());
969 return mlir::LLVM::PtrToIntOp::create(rewriter, parentOp->getLoc(),
973 if (
auto ptrTy = mlir::dyn_cast<cir::PointerType>(globalAttr.getType())) {
974 auto llvmDstTy = converter->convertType<mlir::LLVM::LLVMPointerType>(ptrTy);
975 unsigned dstAddrSpace = llvmDstTy.getAddressSpace();
977 if (sourceAddrSpace != dstAddrSpace)
978 addrOp = mlir::LLVM::AddrSpaceCastOp::create(rewriter, parentOp->getLoc(),
981 mlir::Type llvmEltTy =
985 if (llvmEltTy == sourceType)
991 if (addrOp.getType() == llvmDstTy)
994 return mlir::LLVM::BitcastOp::create(rewriter, parentOp->getLoc(),
998 if (mlir::isa<cir::VPtrType>(globalAttr.getType()))
1001 llvm_unreachable(
"Expecting pointer or integer type for GlobalViewAttr");
1005mlir::Value CIRAttrToValue::visitCirAttr(cir::TypeInfoAttr typeInfoAttr) {
1006 mlir::Type llvmTy = converter->convertType(typeInfoAttr.getType());
1007 mlir::Location loc = parentOp->getLoc();
1008 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
1010 for (
auto [idx, elt] : llvm::enumerate(typeInfoAttr.getData())) {
1011 mlir::Value init = visit(elt);
1013 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
1020mlir::Value CIRAttrToValue::visitCirAttr(cir::UndefAttr undefAttr) {
1021 mlir::Location loc = parentOp->getLoc();
1022 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
1023 return mlir::LLVM::UndefOp::create(
1029mlir::Value CIRAttrToValue::visitCirAttr(cir::PoisonAttr poisonAttr) {
1030 mlir::Location loc = parentOp->getLoc();
1031 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
1032 return mlir::LLVM::PoisonOp::create(
1038mlir::Value CIRAttrToValue::visitCirAttr(cir::VTableAttr vtableArr) {
1039 mlir::Type llvmTy = converter->convertType(vtableArr.getType());
1040 mlir::Location loc = parentOp->getLoc();
1041 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
1043 for (
auto [idx, elt] : llvm::enumerate(vtableArr.getData())) {
1044 mlir::Value init = visit(elt);
1046 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
1053mlir::Value CIRAttrToValue::visitCirAttr(cir::ZeroAttr attr) {
1054 mlir::Location loc = parentOp->getLoc();
1055 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
1056 return mlir::LLVM::ZeroOp::create(
1065 mlir::ConversionPatternRewriter &rewriter)
1066 : llvmType(type), rewriter(rewriter) {}
1069 return llvm::TypeSwitch<mlir::Attribute, mlir::Attribute>(
attr)
1070 .Case<cir::IntAttr, cir::FPAttr, cir::BoolAttr>(
1072 .
Default([&](
auto attrT) {
return mlir::Attribute(); });
1079 llvm::APInt val =
attr.getValue();
1080 auto destTy = mlir::cast<mlir::IntegerType>(llvmType);
1081 if (val.getBitWidth() != destTy.getWidth()) {
1082 cir::IntTypeInterface cirIntTy =
attr.getType();
1083 val = cirIntTy.isSigned() ? val.sext(destTy.getWidth())
1084 : val.zext(destTy.getWidth());
1086 return rewriter.getIntegerAttr(llvmType, val);
1090 return rewriter.getFloatAttr(llvmType,
attr.getValue());
1094 return rewriter.getBoolAttr(
attr.getValue());
1098 mlir::Type llvmType;
1099 mlir::ConversionPatternRewriter &rewriter;
1107 :
public mlir::PassWrapper<ConvertCIRToLLVMPass,
1108 mlir::OperationPass<mlir::ModuleOp>> {
1110 registry.insert<mlir::BuiltinDialect, mlir::DLTIDialect,
1111 mlir::LLVM::LLVMDialect, mlir::func::FuncDialect>();
1129 return "Convert the prepared CIR dialect module to LLVM dialect";
1136 struct CollectedAnnotation {
1137 mlir::StringAttr symName;
1138 cir::AnnotationAttr annotation;
1140 CollectedAnnotation(mlir::StringAttr symName,
1141 cir::AnnotationAttr annotation, mlir::Location loc)
1142 : symName(symName), annotation(annotation), loc(loc) {}
1147mlir::LogicalResult CIRToLLVMIsFPClassOpLowering::matchAndRewrite(
1148 cir::IsFPClassOp op, OpAdaptor adaptor,
1149 mlir::ConversionPatternRewriter &rewriter)
const {
1150 mlir::Value src = adaptor.getSrc();
1151 cir::FPClassTest flags = adaptor.getFlags();
1152 mlir::IntegerType retTy = rewriter.getI1Type();
1154 rewriter.replaceOpWithNewOp<mlir::LLVM::IsFPClass>(
1155 op, retTy, src,
static_cast<uint32_t>(flags));
1156 return mlir::success();
1159mlir::LogicalResult CIRToLLVMSignBitOpLowering::matchAndRewrite(
1160 cir::SignBitOp op, OpAdaptor adaptor,
1161 mlir::ConversionPatternRewriter &rewriter)
const {
1164 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
1165 int width = layout.getTypeSizeInBits(op.getInput().getType());
1166 if (
auto longDoubleType =
1167 mlir::dyn_cast<cir::LongDoubleType>(op.getInput().getType())) {
1168 if (mlir::isa<cir::FP80Type>(longDoubleType.getUnderlying())) {
1176 mlir::Type intTy = mlir::IntegerType::get(rewriter.getContext(), width);
1177 auto bitcast = mlir::LLVM::BitcastOp::create(rewriter, op->getLoc(), intTy,
1178 adaptor.getInput());
1180 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op->getLoc(), intTy, 0);
1181 auto cmpResult = mlir::LLVM::ICmpOp::create(rewriter, op.getLoc(),
1182 mlir::LLVM::ICmpPredicate::slt,
1183 bitcast.getResult(), zero);
1184 rewriter.replaceOp(op, cmpResult);
1185 return mlir::success();
1188mlir::LogicalResult CIRToLLVMAssumeOpLowering::matchAndRewrite(
1189 cir::AssumeOp op, OpAdaptor adaptor,
1190 mlir::ConversionPatternRewriter &rewriter)
const {
1191 mlir::Value cond = adaptor.getPredicate();
1192 if (op.getBundleKind() == cir::AssumeBundleKind::None) {
1193 rewriter.replaceOpWithNewOp<mlir::LLVM::AssumeOp>(op, cond);
1194 return mlir::success();
1197 llvm::StringRef tag = cir::stringifyAssumeBundleKind(op.getBundleKind());
1198 rewriter.replaceOpWithNewOp<mlir::LLVM::AssumeOp>(op, cond, tag,
1199 adaptor.getBundleArgs());
1200 return mlir::success();
1203static mlir::LLVM::AtomicOrdering
1206 return mlir::LLVM::AtomicOrdering::not_atomic;
1207 switch (*memorder) {
1208 case cir::MemOrder::Relaxed:
1209 return mlir::LLVM::AtomicOrdering::monotonic;
1210 case cir::MemOrder::Consume:
1211 case cir::MemOrder::Acquire:
1212 return mlir::LLVM::AtomicOrdering::acquire;
1213 case cir::MemOrder::Release:
1214 return mlir::LLVM::AtomicOrdering::release;
1215 case cir::MemOrder::AcquireRelease:
1216 return mlir::LLVM::AtomicOrdering::acq_rel;
1217 case cir::MemOrder::SequentiallyConsistent:
1218 return mlir::LLVM::AtomicOrdering::seq_cst;
1220 llvm_unreachable(
"unknown memory order");
1224 switch (syncScope) {
1225 case cir::SyncScopeKind::SingleThread:
1226 return "singlethread";
1227 case cir::SyncScopeKind::Workgroup:
1234static std::optional<llvm::StringRef>
1236 if (syncScope.has_value())
1238 return std::nullopt;
1241mlir::LogicalResult CIRToLLVMAtomicCmpXchgOpLowering::matchAndRewrite(
1242 cir::AtomicCmpXchgOp op, OpAdaptor adaptor,
1243 mlir::ConversionPatternRewriter &rewriter)
const {
1244 mlir::Value expected = adaptor.getExpected();
1245 mlir::Value desired = adaptor.getDesired();
1247 auto cmpxchg = mlir::LLVM::AtomicCmpXchgOp::create(
1248 rewriter, op.getLoc(), adaptor.getPtr(), expected, desired,
1253 cmpxchg.setAlignment(adaptor.getAlignment());
1254 cmpxchg.setWeak(adaptor.getWeak());
1255 cmpxchg.setVolatile_(adaptor.getIsVolatile());
1258 auto old = mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(),
1259 cmpxchg.getResult(), 0);
1260 auto cmp = mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(),
1261 cmpxchg.getResult(), 1);
1263 rewriter.replaceOp(op, {old, cmp});
1264 return mlir::success();
1267mlir::LogicalResult CIRToLLVMAtomicXchgOpLowering::matchAndRewrite(
1268 cir::AtomicXchgOp op, OpAdaptor adaptor,
1269 mlir::ConversionPatternRewriter &rewriter)
const {
1271 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(adaptor.getMemOrder());
1273 rewriter.replaceOpWithNewOp<mlir::LLVM::AtomicRMWOp>(
1274 op, mlir::LLVM::AtomicBinOp::xchg, adaptor.getPtr(), adaptor.getVal(),
1275 llvmOrder, llvmSyncScope);
1276 return mlir::success();
1279mlir::LogicalResult CIRToLLVMAtomicTestAndSetOpLowering::matchAndRewrite(
1280 cir::AtomicTestAndSetOp op, OpAdaptor adaptor,
1281 mlir::ConversionPatternRewriter &rewriter)
const {
1284 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
1286 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1287 rewriter.getI8Type(), 1);
1288 auto rmw = mlir::LLVM::AtomicRMWOp::create(
1289 rewriter, op.getLoc(), mlir::LLVM::AtomicBinOp::xchg, adaptor.getPtr(),
1290 one, llvmOrder, llvm::StringRef(),
1291 adaptor.getAlignment().value_or(0), op.getIsVolatile());
1293 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1294 rewriter.getI8Type(), 0);
1295 auto cmp = mlir::LLVM::ICmpOp::create(
1296 rewriter, op.getLoc(), mlir::LLVM::ICmpPredicate::ne, rmw, zero);
1298 rewriter.replaceOp(op, cmp);
1299 return mlir::success();
1302mlir::LogicalResult CIRToLLVMAtomicClearOpLowering::matchAndRewrite(
1303 cir::AtomicClearOp op, OpAdaptor adaptor,
1304 mlir::ConversionPatternRewriter &rewriter)
const {
1307 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
1308 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1309 rewriter.getI8Type(), 0);
1310 auto store = mlir::LLVM::StoreOp::create(
1311 rewriter, op.getLoc(), zero, adaptor.getPtr(),
1312 adaptor.getAlignment().value_or(0), op.getIsVolatile(),
1313 false,
false, llvmOrder);
1315 rewriter.replaceOp(op, store);
1316 return mlir::success();
1319mlir::LogicalResult CIRToLLVMAtomicFenceOpLowering::matchAndRewrite(
1320 cir::AtomicFenceOp op, OpAdaptor adaptor,
1321 mlir::ConversionPatternRewriter &rewriter)
const {
1322 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(adaptor.getOrdering());
1324 auto fence = mlir::LLVM::FenceOp::create(rewriter, op.getLoc(), llvmOrder);
1327 rewriter.replaceOp(op, fence);
1329 return mlir::success();
1332static mlir::LLVM::AtomicBinOp
1335 case cir::AtomicFetchKind::Add:
1336 return isInt ? mlir::LLVM::AtomicBinOp::add : mlir::LLVM::AtomicBinOp::fadd;
1337 case cir::AtomicFetchKind::Sub:
1338 return isInt ? mlir::LLVM::AtomicBinOp::sub : mlir::LLVM::AtomicBinOp::fsub;
1339 case cir::AtomicFetchKind::And:
1340 return mlir::LLVM::AtomicBinOp::_and;
1341 case cir::AtomicFetchKind::Xor:
1342 return mlir::LLVM::AtomicBinOp::_xor;
1343 case cir::AtomicFetchKind::Or:
1344 return mlir::LLVM::AtomicBinOp::_or;
1345 case cir::AtomicFetchKind::Nand:
1346 return mlir::LLVM::AtomicBinOp::nand;
1347 case cir::AtomicFetchKind::Max: {
1349 return mlir::LLVM::AtomicBinOp::fmax;
1350 return isSignedInt ? mlir::LLVM::AtomicBinOp::max
1351 : mlir::LLVM::AtomicBinOp::umax;
1353 case cir::AtomicFetchKind::Min: {
1355 return mlir::LLVM::AtomicBinOp::fmin;
1356 return isSignedInt ? mlir::LLVM::AtomicBinOp::min
1357 : mlir::LLVM::AtomicBinOp::umin;
1359 case cir::AtomicFetchKind::UIncWrap:
1360 return mlir::LLVM::AtomicBinOp::uinc_wrap;
1361 case cir::AtomicFetchKind::UDecWrap:
1362 return mlir::LLVM::AtomicBinOp::udec_wrap;
1363 case cir::AtomicFetchKind::Maximum:
1364 return mlir::LLVM::AtomicBinOp::fmaximum;
1365 case cir::AtomicFetchKind::Minimum:
1366 return mlir::LLVM::AtomicBinOp::fminimum;
1367 case cir::AtomicFetchKind::MaximumNum:
1368 return mlir::LLVM::AtomicBinOp::fmaximumnum;
1369 case cir::AtomicFetchKind::MinimumNum:
1370 return mlir::LLVM::AtomicBinOp::fminimumnum;
1372 llvm_unreachable(
"Unknown atomic fetch opcode");
1378 case cir::AtomicFetchKind::Add:
1379 return isInt ? mlir::LLVM::AddOp::getOperationName()
1380 : mlir::LLVM::FAddOp::getOperationName();
1381 case cir::AtomicFetchKind::Sub:
1382 return isInt ? mlir::LLVM::SubOp::getOperationName()
1383 : mlir::LLVM::FSubOp::getOperationName();
1384 case cir::AtomicFetchKind::And:
1385 return mlir::LLVM::AndOp::getOperationName();
1386 case cir::AtomicFetchKind::Xor:
1387 return mlir::LLVM::XOrOp::getOperationName();
1388 case cir::AtomicFetchKind::Or:
1389 return mlir::LLVM::OrOp::getOperationName();
1390 case cir::AtomicFetchKind::Nand:
1392 return mlir::LLVM::AndOp::getOperationName();
1393 case cir::AtomicFetchKind::Max:
1394 case cir::AtomicFetchKind::Min:
1395 llvm_unreachable(
"handled in buildMinMaxPostOp");
1396 case cir::AtomicFetchKind::UIncWrap:
1397 case cir::AtomicFetchKind::UDecWrap:
1398 case cir::AtomicFetchKind::Maximum:
1399 case cir::AtomicFetchKind::Minimum:
1400 case cir::AtomicFetchKind::MaximumNum:
1401 case cir::AtomicFetchKind::MinimumNum:
1402 llvm_unreachable(
"uinc_wrap, udec_wrap, maximum, minimum, maximum_num, and "
1403 "minimum_num are always fetch_first");
1405 llvm_unreachable(
"Unknown atomic fetch opcode");
1408mlir::Value CIRToLLVMAtomicFetchOpLowering::buildPostOp(
1409 cir::AtomicFetchOp op, OpAdaptor adaptor,
1410 mlir::ConversionPatternRewriter &rewriter, mlir::Value rmwVal,
1415 .create(op.getLoc(),
1416 rewriter.getStringAttr(
1418 atomicOperands, atomicResTys, {})
1422mlir::Value CIRToLLVMAtomicFetchOpLowering::buildMinMaxPostOp(
1423 cir::AtomicFetchOp op, OpAdaptor adaptor,
1424 mlir::ConversionPatternRewriter &rewriter, mlir::Value rmwVal,
bool isInt,
1425 bool isSigned)
const {
1426 mlir::Location loc = op.getLoc();
1429 if (op.getBinop() == cir::AtomicFetchKind::Max)
1430 return mlir::LLVM::MaxNumOp::create(rewriter, loc, rmwVal,
1432 return mlir::LLVM::MinNumOp::create(rewriter, loc, rmwVal,
1436 mlir::LLVM::ICmpPredicate pred;
1437 if (op.getBinop() == cir::AtomicFetchKind::Max) {
1438 pred = isSigned ? mlir::LLVM::ICmpPredicate::sgt
1439 : mlir::LLVM::ICmpPredicate::ugt;
1441 pred = isSigned ? mlir::LLVM::ICmpPredicate::slt
1442 : mlir::LLVM::ICmpPredicate::ult;
1444 mlir::Value cmp = mlir::LLVM::ICmpOp::create(
1446 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(), pred), rmwVal,
1448 return mlir::LLVM::SelectOp::create(rewriter, loc, cmp, rmwVal,
1452mlir::LogicalResult CIRToLLVMAtomicFetchOpLowering::matchAndRewrite(
1453 cir::AtomicFetchOp op, OpAdaptor adaptor,
1454 mlir::ConversionPatternRewriter &rewriter)
const {
1456 bool isSignedInt =
false;
1457 if (
auto intTy = mlir::dyn_cast<cir::IntType>(op.getVal().getType())) {
1459 isSignedInt = intTy.isSigned();
1460 }
else if (mlir::isa<cir::SingleType, cir::DoubleType>(
1461 op.getVal().getType())) {
1464 return op.emitError() <<
"Unsupported type: " << op.getVal().getType();
1467 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
1469 mlir::LLVM::AtomicBinOp llvmBinOp =
1471 auto rmwVal = mlir::LLVM::AtomicRMWOp::create(
1472 rewriter, op.getLoc(), llvmBinOp, adaptor.getPtr(), adaptor.getVal(),
1473 llvmOrder, llvmSyncScope);
1475 mlir::Value result = rmwVal.getResult();
1476 if (!op.getFetchFirst()) {
1477 if (op.getBinop() == cir::AtomicFetchKind::Max ||
1478 op.getBinop() == cir::AtomicFetchKind::Min)
1479 result = buildMinMaxPostOp(op, adaptor, rewriter, rmwVal.getRes(), isInt,
1482 result = buildPostOp(op, adaptor, rewriter, rmwVal.getRes(), isInt);
1485 if (op.getBinop() == cir::AtomicFetchKind::Nand) {
1486 auto negOne = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1487 result.getType(), -1);
1488 result = mlir::LLVM::XOrOp::create(rewriter, op.getLoc(), result, negOne);
1492 rewriter.replaceOp(op, result);
1493 return mlir::success();
1496mlir::LogicalResult CIRToLLVMBitClrsbOpLowering::matchAndRewrite(
1497 cir::BitClrsbOp op, OpAdaptor adaptor,
1498 mlir::ConversionPatternRewriter &rewriter)
const {
1499 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1500 adaptor.getInput().getType(), 0);
1501 auto isNeg = mlir::LLVM::ICmpOp::create(
1502 rewriter, op.getLoc(),
1503 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(),
1504 mlir::LLVM::ICmpPredicate::slt),
1505 adaptor.getInput(), zero);
1507 auto negOne = mlir::LLVM::ConstantOp::create(
1508 rewriter, op.getLoc(), adaptor.getInput().getType(), -1);
1509 auto flipped = mlir::LLVM::XOrOp::create(rewriter, op.getLoc(),
1510 adaptor.getInput(), negOne);
1512 auto select = mlir::LLVM::SelectOp::create(rewriter, op.getLoc(), isNeg,
1513 flipped, adaptor.getInput());
1515 auto resTy = getTypeConverter()->convertType(op.getType());
1516 auto clz = mlir::LLVM::CountLeadingZerosOp::create(
1517 rewriter, op.getLoc(), resTy,
select,
false);
1519 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1520 auto res = mlir::LLVM::SubOp::create(rewriter, op.getLoc(),
clz, one,
1521 mlir::LLVM::IntegerOverflowFlags::nuw);
1522 rewriter.replaceOp(op, res);
1524 return mlir::LogicalResult::success();
1527mlir::LogicalResult CIRToLLVMBitClzOpLowering::matchAndRewrite(
1528 cir::BitClzOp op, OpAdaptor adaptor,
1529 mlir::ConversionPatternRewriter &rewriter)
const {
1530 auto resTy = getTypeConverter()->convertType(op.getType());
1531 auto llvmOp = mlir::LLVM::CountLeadingZerosOp::create(
1532 rewriter, op.getLoc(), resTy, adaptor.getInput(), op.getPoisonZero());
1533 rewriter.replaceOp(op, llvmOp);
1534 return mlir::LogicalResult::success();
1537mlir::LogicalResult CIRToLLVMBitCtzOpLowering::matchAndRewrite(
1538 cir::BitCtzOp op, OpAdaptor adaptor,
1539 mlir::ConversionPatternRewriter &rewriter)
const {
1540 auto resTy = getTypeConverter()->convertType(op.getType());
1541 auto llvmOp = mlir::LLVM::CountTrailingZerosOp::create(
1542 rewriter, op.getLoc(), resTy, adaptor.getInput(), op.getPoisonZero());
1543 rewriter.replaceOp(op, llvmOp);
1544 return mlir::LogicalResult::success();
1547mlir::LogicalResult CIRToLLVMBitFfsOpLowering::matchAndRewrite(
1548 cir::BitFfsOp op, OpAdaptor adaptor,
1549 mlir::ConversionPatternRewriter &rewriter)
const {
1550 auto resTy = getTypeConverter()->convertType(op.getType());
1551 auto ctz = mlir::LLVM::CountTrailingZerosOp::create(rewriter, op.getLoc(),
1552 resTy, adaptor.getInput(),
1555 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1556 auto ctzAddOne = mlir::LLVM::AddOp::create(rewriter, op.getLoc(),
ctz, one);
1558 auto zeroInputTy = mlir::LLVM::ConstantOp::create(
1559 rewriter, op.getLoc(), adaptor.getInput().getType(), 0);
1560 auto isZero = mlir::LLVM::ICmpOp::create(
1561 rewriter, op.getLoc(),
1562 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(),
1563 mlir::LLVM::ICmpPredicate::eq),
1564 adaptor.getInput(), zeroInputTy);
1566 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 0);
1567 auto res = mlir::LLVM::SelectOp::create(rewriter, op.getLoc(), isZero, zero,
1569 rewriter.replaceOp(op, res);
1571 return mlir::LogicalResult::success();
1574mlir::LogicalResult CIRToLLVMBitParityOpLowering::matchAndRewrite(
1575 cir::BitParityOp op, OpAdaptor adaptor,
1576 mlir::ConversionPatternRewriter &rewriter)
const {
1577 auto resTy = getTypeConverter()->convertType(op.getType());
1578 auto popcnt = mlir::LLVM::CtPopOp::create(rewriter, op.getLoc(), resTy,
1579 adaptor.getInput());
1581 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1583 mlir::LLVM::AndOp::create(rewriter, op.getLoc(), popcnt, one);
1584 rewriter.replaceOp(op, popcntMod2);
1586 return mlir::LogicalResult::success();
1589mlir::LogicalResult CIRToLLVMBitPopcountOpLowering::matchAndRewrite(
1590 cir::BitPopcountOp op, OpAdaptor adaptor,
1591 mlir::ConversionPatternRewriter &rewriter)
const {
1592 auto resTy = getTypeConverter()->convertType(op.getType());
1593 auto llvmOp = mlir::LLVM::CtPopOp::create(rewriter, op.getLoc(), resTy,
1594 adaptor.getInput());
1595 rewriter.replaceOp(op, llvmOp);
1596 return mlir::LogicalResult::success();
1599mlir::LogicalResult CIRToLLVMBrCondOpLowering::matchAndRewrite(
1600 cir::BrCondOp brOp, OpAdaptor adaptor,
1601 mlir::ConversionPatternRewriter &rewriter)
const {
1606 mlir::Value i1Condition = adaptor.getCond();
1608 rewriter.replaceOpWithNewOp<mlir::LLVM::CondBrOp>(
1609 brOp, i1Condition, brOp.getDestTrue(), adaptor.getDestOperandsTrue(),
1610 brOp.getDestFalse(), adaptor.getDestOperandsFalse());
1612 return mlir::success();
1615mlir::Type CIRToLLVMCastOpLowering::convertTy(mlir::Type ty)
const {
1616 return getTypeConverter()->convertType(ty);
1619mlir::LogicalResult CIRToLLVMCastOpLowering::matchAndRewrite(
1620 cir::CastOp castOp, OpAdaptor adaptor,
1621 mlir::ConversionPatternRewriter &rewriter)
const {
1626 switch (castOp.getKind()) {
1627 case cir::CastKind::array_to_ptrdecay: {
1628 const auto ptrTy = mlir::cast<cir::PointerType>(castOp.getType());
1629 mlir::Value sourceValue = adaptor.getSrc();
1630 mlir::Type targetType = convertTy(ptrTy);
1632 ptrTy.getPointee());
1633 llvm::SmallVector<mlir::LLVM::GEPArg> offset{0};
1634 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1635 castOp, targetType, elementTy, sourceValue, offset);
1638 case cir::CastKind::int_to_bool: {
1639 mlir::Value llvmSrcVal = adaptor.getSrc();
1643 mlir::Value zeroInt = mlir::LLVM::ConstantOp::create(
1644 rewriter, castOp.getLoc(), llvmSrcVal.getType(),
1645 rewriter.getZeroAttr(llvmSrcVal.getType()));
1646 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
1647 castOp, mlir::LLVM::ICmpPredicate::ne, llvmSrcVal, zeroInt);
1650 case cir::CastKind::integral: {
1651 mlir::Type srcType = castOp.getSrc().getType();
1652 mlir::Type dstType = castOp.getType();
1653 mlir::Value llvmSrcVal = adaptor.getSrc();
1654 mlir::Type llvmDstType = getTypeConverter()->convertType(dstType);
1655 cir::IntType srcIntType =
1656 mlir::cast<cir::IntType>(elementTypeIfVector(srcType));
1657 cir::IntType dstIntType =
1658 mlir::cast<cir::IntType>(elementTypeIfVector(dstType));
1659 rewriter.replaceOp(castOp,
getLLVMIntCast(rewriter, llvmSrcVal, llvmDstType,
1660 srcIntType.isUnsigned(),
1661 srcIntType.getWidth(),
1662 dstIntType.getWidth()));
1665 case cir::CastKind::floating: {
1666 mlir::Value llvmSrcVal = adaptor.getSrc();
1667 mlir::Type llvmDstTy = getTypeConverter()->convertType(castOp.getType());
1669 mlir::Type srcTy = elementTypeIfVector(castOp.getSrc().getType());
1670 mlir::Type dstTy = elementTypeIfVector(castOp.getType());
1672 if (!mlir::isa<cir::FPTypeInterface>(dstTy) ||
1673 !mlir::isa<cir::FPTypeInterface>(srcTy))
1674 return castOp.emitError() <<
"NYI cast from " << srcTy <<
" to " << dstTy;
1676 auto getFloatWidth = [](mlir::Type ty) ->
unsigned {
1677 return mlir::cast<cir::FPTypeInterface>(ty).getWidth();
1680 bool isTrunc = getFloatWidth(srcTy) > getFloatWidth(dstTy);
1681 if (cir::FenvAttr fenv = castOp.getFenvAttr()) {
1685 castOp, llvmSrcVal, fenv, llvmDstTy, rewriter,
1686 isTrunc ?
"fptrunc" :
"fpext", isTrunc);
1689 rewriter.replaceOpWithNewOp<mlir::LLVM::FPTruncOp>(castOp, llvmDstTy,
1692 rewriter.replaceOpWithNewOp<mlir::LLVM::FPExtOp>(castOp, llvmDstTy,
1694 return mlir::success();
1696 case cir::CastKind::int_to_ptr: {
1697 auto dstTy = mlir::cast<cir::PointerType>(castOp.getType());
1698 mlir::Value llvmSrcVal = adaptor.getSrc();
1699 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1700 rewriter.replaceOpWithNewOp<mlir::LLVM::IntToPtrOp>(castOp, llvmDstTy,
1702 return mlir::success();
1704 case cir::CastKind::ptr_to_int: {
1705 auto dstTy = mlir::cast<cir::IntType>(castOp.getType());
1706 mlir::Value llvmSrcVal = adaptor.getSrc();
1707 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1708 rewriter.replaceOpWithNewOp<mlir::LLVM::PtrToIntOp>(castOp, llvmDstTy,
1710 return mlir::success();
1712 case cir::CastKind::float_to_bool: {
1713 mlir::Value llvmSrcVal = adaptor.getSrc();
1714 auto kind = mlir::LLVM::FCmpPredicate::une;
1719 auto zeroFloat = mlir::LLVM::ConstantOp::create(
1720 rewriter, castOp.getLoc(), llvmSrcVal.getType(),
1721 rewriter.getZeroAttr(llvmSrcVal.getType()));
1724 rewriter.replaceOpWithNewOp<mlir::LLVM::FCmpOp>(castOp,
kind, llvmSrcVal,
1727 return mlir::success();
1729 case cir::CastKind::bool_to_int: {
1730 mlir::Type dstTy = castOp.getType();
1731 mlir::Value llvmSrcVal = adaptor.getSrc();
1732 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1734 auto srcElemTy = mlir::cast<mlir::IntegerType>(
1735 elementTypeIfVector(llvmSrcVal.getType()));
1736 auto dstElemTy = mlir::cast<cir::IntType>(elementTypeIfVector(dstTy));
1738 if (srcElemTy.getWidth() == dstElemTy.getWidth())
1739 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(castOp, llvmDstTy,
1742 rewriter.replaceOpWithNewOp<mlir::LLVM::ZExtOp>(castOp, llvmDstTy,
1744 return mlir::success();
1746 case cir::CastKind::bool_to_float: {
1747 mlir::Type dstTy = castOp.getType();
1748 mlir::Value llvmSrcVal = adaptor.getSrc();
1749 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1750 rewriter.replaceOpWithNewOp<mlir::LLVM::UIToFPOp>(castOp, llvmDstTy,
1752 return mlir::success();
1754 case cir::CastKind::int_to_float: {
1755 mlir::Type dstTy = castOp.getType();
1756 mlir::Value llvmSrcVal = adaptor.getSrc();
1757 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1759 mlir::cast<cir::IntType>(elementTypeIfVector(castOp.getSrc().getType()))
1761 if (cir::FenvAttr fenv = castOp.getFenvAttr()) {
1763 castOp, llvmSrcVal, fenv, llvmDstTy, rewriter,
1764 isSigned ?
"sitofp" :
"uitofp",
true);
1767 rewriter.replaceOpWithNewOp<mlir::LLVM::SIToFPOp>(castOp, llvmDstTy,
1770 rewriter.replaceOpWithNewOp<mlir::LLVM::UIToFPOp>(castOp, llvmDstTy,
1772 return mlir::success();
1774 case cir::CastKind::float_to_int: {
1775 mlir::Type dstTy = castOp.getType();
1776 mlir::Value llvmSrcVal = adaptor.getSrc();
1777 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1779 mlir::cast<cir::IntType>(elementTypeIfVector(castOp.getType()))
1781 if (cir::FenvAttr fenv = castOp.getFenvAttr()) {
1783 castOp, llvmSrcVal, fenv, llvmDstTy, rewriter,
1784 isSigned ?
"fptosi" :
"fptoui",
false);
1787 rewriter.replaceOpWithNewOp<mlir::LLVM::FPToSIOp>(castOp, llvmDstTy,
1790 rewriter.replaceOpWithNewOp<mlir::LLVM::FPToUIOp>(castOp, llvmDstTy,
1792 return mlir::success();
1794 case cir::CastKind::bitcast: {
1795 mlir::Type dstTy = castOp.getType();
1796 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1801 mlir::Value llvmSrcVal = adaptor.getSrc();
1802 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(castOp, llvmDstTy,
1804 return mlir::success();
1806 case cir::CastKind::ptr_to_bool: {
1807 mlir::Value llvmSrcVal = adaptor.getSrc();
1808 mlir::Value zeroPtr = mlir::LLVM::ZeroOp::create(rewriter, castOp.getLoc(),
1809 llvmSrcVal.getType());
1810 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
1811 castOp, mlir::LLVM::ICmpPredicate::ne, llvmSrcVal, zeroPtr);
1814 case cir::CastKind::address_space: {
1815 mlir::Type dstTy = castOp.getType();
1816 mlir::Value llvmSrcVal = adaptor.getSrc();
1817 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1818 rewriter.replaceOpWithNewOp<mlir::LLVM::AddrSpaceCastOp>(castOp, llvmDstTy,
1822 case cir::CastKind::member_ptr_to_bool:
1827 return castOp.emitError(
"Unhandled cast kind: ")
1828 << castOp.getKindAttrName();
1832 return mlir::success();
1835mlir::LogicalResult CIRToLLVMBuiltinIntCastOpLowering::matchAndRewrite(
1836 cir::BuiltinIntCastOp op, OpAdaptor adaptor,
1837 mlir::ConversionPatternRewriter &rewriter)
const {
1842 if (
auto cirSrc = mlir::dyn_cast<cir::IntType>(op.getSrc().getType()))
1844 else if (
auto cirDst = mlir::dyn_cast<cir::IntType>(op.getType()))
1847 mlir::Value llvmSrc = adaptor.getSrc();
1848 mlir::Type llvmDstTy = getTypeConverter()->convertType(op.getType());
1849 auto srcIntTy = mlir::cast<mlir::IntegerType>(llvmSrc.getType());
1850 auto dstIntTy = mlir::cast<mlir::IntegerType>(llvmDstTy);
1851 unsigned srcWidth = srcIntTy.getWidth();
1852 unsigned dstWidth = dstIntTy.getWidth();
1857 assert((srcWidth == dstWidth ||
1858 mlir::isa<mlir::IndexType>(op.getSrc().getType()) ||
1859 mlir::isa<mlir::IndexType>(op.getType())) &&
1860 "only index casts may change width during lowering");
1865 srcWidth, dstWidth));
1866 return mlir::success();
1870 mlir::ModuleOp mod, mlir::Value index,
1871 mlir::Type baseTy, cir::IntType strideTy) {
1872 mlir::Operation *indexOp = index.getDefiningOp();
1876 auto indexType = mlir::cast<mlir::IntegerType>(index.getType());
1877 mlir::DataLayout llvmLayout(mod);
1878 std::optional<uint64_t> layoutWidth = llvmLayout.getTypeIndexBitwidth(baseTy);
1881 if (!layoutWidth || *layoutWidth == indexType.getWidth())
1887 auto sub = dyn_cast<mlir::LLVM::SubOp>(indexOp);
1888 bool rewriteSub =
false;
1891 dyn_cast<mlir::LLVM::ConstantOp>(sub.getLhs().getDefiningOp())) {
1892 auto lhsConstInt = mlir::dyn_cast<mlir::IntegerAttr>(lhsConst.getValue());
1893 if (lhsConstInt && lhsConstInt.getValue() == 0) {
1894 index = sub.getRhs();
1900 auto llvmDstType = rewriter.getIntegerType(*layoutWidth);
1901 bool isUnsigned = strideTy && strideTy.isUnsigned();
1903 indexType.getWidth(), *layoutWidth);
1906 index = mlir::LLVM::SubOp::create(
1907 rewriter, index.getLoc(),
1908 mlir::LLVM::ConstantOp::create(rewriter, index.getLoc(),
1909 index.getType(), 0),
1912 rewriter.eraseOp(sub);
1918mlir::LogicalResult CIRToLLVMPtrStrideOpLowering::matchAndRewrite(
1919 cir::PtrStrideOp ptrStrideOp, OpAdaptor adaptor,
1920 mlir::ConversionPatternRewriter &rewriter)
const {
1922 const mlir::TypeConverter *tc = getTypeConverter();
1923 const mlir::Type resultTy = tc->convertType(ptrStrideOp.getType());
1925 mlir::Type elementTy =
1930 if (mlir::isa<mlir::LLVM::LLVMVoidType>(elementTy) ||
1931 mlir::isa<mlir::LLVM::LLVMFunctionType>(elementTy))
1932 elementTy = mlir::IntegerType::get(elementTy.getContext(), 8,
1933 mlir::IntegerType::Signless);
1935 mlir::Value index = adaptor.getStride();
1937 rewriter, ptrStrideOp->getParentOfType<mlir::ModuleOp>(), index,
1938 adaptor.getBase().getType(),
1939 dyn_cast<cir::IntType>(ptrStrideOp.getOperand(1).getType()));
1941 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1942 ptrStrideOp, resultTy, elementTy, adaptor.getBase(), index);
1943 return mlir::success();
1946mlir::LogicalResult CIRToLLVMGetElementOpLowering::matchAndRewrite(
1947 cir::GetElementOp op, OpAdaptor adaptor,
1948 mlir::ConversionPatternRewriter &rewriter)
const {
1950 mlir::dyn_cast<cir::ArrayType>(op.getBaseType().getPointee())) {
1951 const mlir::TypeConverter *converter = getTypeConverter();
1952 const mlir::Type llArrayTy = converter->convertType(arrayTy);
1953 const mlir::Type llResultTy = converter->convertType(op.getType());
1954 mlir::Type elementTy =
1959 if (mlir::isa<mlir::LLVM::LLVMVoidType>(elementTy) ||
1960 mlir::isa<mlir::LLVM::LLVMFunctionType>(elementTy))
1961 elementTy = rewriter.getIntegerType(8);
1963 mlir::Value index = adaptor.getIndex();
1966 adaptor.getBase().getType(),
1967 dyn_cast<cir::IntType>(op.getOperand(1).getType()));
1972 std::array<mlir::LLVM::GEPArg, 2> offset{0, index};
1973 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, llResultTy, llArrayTy,
1974 adaptor.getBase(), offset);
1975 return mlir::success();
1978 op.emitError() <<
"NYI: GetElementOp lowering to LLVM for non-array";
1979 return mlir::failure();
1982mlir::LogicalResult CIRToLLVMBaseClassAddrOpLowering::matchAndRewrite(
1983 cir::BaseClassAddrOp baseClassOp, OpAdaptor adaptor,
1984 mlir::ConversionPatternRewriter &rewriter)
const {
1985 const mlir::Type resultType =
1986 getTypeConverter()->convertType(baseClassOp.getType());
1987 mlir::Value derivedAddr = adaptor.getDerivedAddr();
1988 llvm::SmallVector<mlir::LLVM::GEPArg, 1> offset = {
1989 adaptor.getOffset().getZExtValue()};
1990 mlir::Type byteType = mlir::IntegerType::get(resultType.getContext(), 8,
1991 mlir::IntegerType::Signless);
1992 if (adaptor.getOffset().getZExtValue() == 0) {
1993 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(
1994 baseClassOp, resultType, adaptor.getDerivedAddr());
1995 return mlir::success();
1998 if (baseClassOp.getAssumeNotNull()) {
1999 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
2000 baseClassOp, resultType, byteType, derivedAddr, offset);
2002 auto loc = baseClassOp.getLoc();
2003 mlir::Value isNull = mlir::LLVM::ICmpOp::create(
2004 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, derivedAddr,
2005 mlir::LLVM::ZeroOp::create(rewriter, loc, derivedAddr.getType()));
2006 mlir::Value adjusted = mlir::LLVM::GEPOp::create(
2007 rewriter, loc, resultType, byteType, derivedAddr, offset);
2008 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(baseClassOp, isNull,
2009 derivedAddr, adjusted);
2011 return mlir::success();
2014mlir::LogicalResult CIRToLLVMDerivedClassAddrOpLowering::matchAndRewrite(
2015 cir::DerivedClassAddrOp derivedClassOp, OpAdaptor adaptor,
2016 mlir::ConversionPatternRewriter &rewriter)
const {
2017 const mlir::Type resultType =
2018 getTypeConverter()->convertType(derivedClassOp.getType());
2019 mlir::Value baseAddr = adaptor.getBaseAddr();
2022 int64_t offsetVal = -(adaptor.getOffset().getZExtValue());
2023 if (offsetVal == 0) {
2025 rewriter.replaceOp(derivedClassOp, baseAddr);
2026 return mlir::success();
2028 llvm::SmallVector<mlir::LLVM::GEPArg, 1> offset = {offsetVal};
2029 mlir::Type byteType = mlir::IntegerType::get(resultType.getContext(), 8,
2030 mlir::IntegerType::Signless);
2031 if (derivedClassOp.getAssumeNotNull()) {
2032 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
2033 derivedClassOp, resultType, byteType, baseAddr, offset,
2034 mlir::LLVM::GEPNoWrapFlags::inbounds);
2036 mlir::Location loc = derivedClassOp.getLoc();
2037 mlir::Value isNull = mlir::LLVM::ICmpOp::create(
2038 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, baseAddr,
2039 mlir::LLVM::ZeroOp::create(rewriter, loc, baseAddr.getType()));
2040 mlir::Value adjusted =
2041 mlir::LLVM::GEPOp::create(rewriter, loc, resultType, byteType, baseAddr,
2042 offset, mlir::LLVM::GEPNoWrapFlags::inbounds);
2043 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(derivedClassOp, isNull,
2044 baseAddr, adjusted);
2046 return mlir::success();
2049mlir::LogicalResult CIRToLLVMFMaxNumOpLowering::matchAndRewrite(
2050 cir::FMaxNumOp op, OpAdaptor adaptor,
2051 mlir::ConversionPatternRewriter &rewriter)
const {
2052 mlir::Type resTy = typeConverter->convertType(op.getType());
2053 if (cir::FenvAttr fenv = op.getFenvAttr())
2055 op, adaptor.getOperands(), fenv, resTy, rewriter,
"maxnum",
2056 false, mlir::LLVM::FastmathFlags::nsz);
2057 rewriter.replaceOpWithNewOp<mlir::LLVM::MaxNumOp>(
2058 op, resTy, adaptor.getLhs(), adaptor.getRhs(),
2059 mlir::LLVM::FastmathFlags::nsz);
2060 return mlir::success();
2063mlir::LogicalResult CIRToLLVMFMinNumOpLowering::matchAndRewrite(
2064 cir::FMinNumOp op, OpAdaptor adaptor,
2065 mlir::ConversionPatternRewriter &rewriter)
const {
2066 mlir::Type resTy = typeConverter->convertType(op.getType());
2067 if (cir::FenvAttr fenv = op.getFenvAttr())
2069 op, adaptor.getOperands(), fenv, resTy, rewriter,
"minnum",
2070 false, mlir::LLVM::FastmathFlags::nsz);
2071 rewriter.replaceOpWithNewOp<mlir::LLVM::MinNumOp>(
2072 op, resTy, adaptor.getLhs(), adaptor.getRhs(),
2073 mlir::LLVM::FastmathFlags::nsz);
2074 return mlir::success();
2077mlir::LogicalResult CIRToLLVMAllocaOpLowering::matchAndRewrite(
2078 cir::AllocaOp op, OpAdaptor adaptor,
2079 mlir::ConversionPatternRewriter &rewriter)
const {
2082 ? adaptor.getDynAllocSize()
2083 : mlir::LLVM::ConstantOp::create(
2084 rewriter, op.getLoc(),
2085 typeConverter->convertType(rewriter.getI32Type()), 1);
2086 mlir::Type elementTy =
2089 return op.emitError()
2090 <<
"NYI: lowering alloca of a type with no memory representation";
2091 mlir::Type resultTy =
2097 rewriter.replaceOpWithNewOp<mlir::LLVM::AllocaOp>(op, resultTy, elementTy,
2098 size, op.getAlignment());
2100 return mlir::success();
2103mlir::LogicalResult CIRToLLVMRotateOpLowering::matchAndRewrite(
2104 cir::RotateOp op, OpAdaptor adaptor,
2105 mlir::ConversionPatternRewriter &rewriter)
const {
2108 mlir::Value input = adaptor.getInput();
2109 if (op.isRotateLeft())
2110 rewriter.replaceOpWithNewOp<mlir::LLVM::FshlOp>(op, input, input,
2111 adaptor.getAmount());
2113 rewriter.replaceOpWithNewOp<mlir::LLVM::FshrOp>(op, input, input,
2114 adaptor.getAmount());
2115 return mlir::LogicalResult::success();
2123static mlir::ArrayAttr
2125 const mlir::TypeConverter &converter,
2126 mlir::MLIRContext *ctx) {
2129 bool changed =
false;
2131 loweredArgAttrs.reserve(argAttrs.size());
2132 for (mlir::Attribute a : argAttrs) {
2133 auto dict = cast<mlir::DictionaryAttr>(a);
2135 for (mlir::NamedAttribute &entry : entries) {
2136 StringRef name = entry.getName().strref();
2137 if (name != mlir::LLVM::LLVMDialect::getByValAttrName() &&
2138 name != mlir::LLVM::LLVMDialect::getStructRetAttrName() &&
2139 name != mlir::LLVM::LLVMDialect::getByRefAttrName())
2141 auto typeAttr = dyn_cast<mlir::TypeAttr>(entry.getValue());
2144 mlir::Type lowered = converter.convertType(typeAttr.getValue());
2145 if (lowered && lowered != typeAttr.getValue()) {
2146 entry.setValue(mlir::TypeAttr::get(lowered));
2150 loweredArgAttrs.push_back(mlir::DictionaryAttr::get(ctx, entries));
2152 return changed ? mlir::ArrayAttr::get(ctx, loweredArgAttrs) : argAttrs;
2156 const mlir::TypeConverter &converter,
2158 for (mlir::NamedAttribute attr : op->getAttrs()) {
2159 if (attr.getName() == CIRDialect::getCalleeAttrName() ||
2160 attr.getName() == CIRDialect::getSideEffectAttrName() ||
2161 attr.getName() == CIRDialect::getNoThrowAttrName() ||
2162 attr.getName() == CIRDialect::getNoUnwindAttrName() ||
2163 attr.getName() == CIRDialect::getNoReturnAttrName() ||
2164 attr.getName() == op.getInlineKindAttrName() ||
2165 attr.getName() == CIRDialect::getMustTailAttrName())
2169 if (attr.getName() == CIRDialect::getArgAttrsAttrName()) {
2170 auto argAttrs = cast<mlir::ArrayAttr>(attr.getValue());
2171 result.emplace_back(
2176 result.push_back(attr);
2180static mlir::LogicalResult
2182 mlir::ConversionPatternRewriter &rewriter,
2183 const mlir::TypeConverter *converter,
2184 mlir::SymbolTableCollection &symbolTables,
2185 mlir::FlatSymbolRefAttr calleeAttr,
2186 mlir::Block *continueBlock =
nullptr,
2187 mlir::Block *landingPadBlock =
nullptr) {
2189 mlir::ValueTypeRange<mlir::ResultRange> cirResults = op->getResultTypes();
2190 auto call = cast<cir::CIRCallOpInterface>(op);
2192 if (converter->convertTypes(cirResults, llvmResults).failed())
2193 return mlir::failure();
2197 mlir::LLVM::MemoryEffectsAttr memoryEffects;
2198 bool noUnwind =
false;
2199 bool willReturn =
false;
2200 bool noReturn =
false;
2202 memoryEffects, noUnwind, willReturn, noReturn);
2207 mlir::LLVM::LLVMFunctionType llvmFnTy;
2214 mlir::Operation *callee =
2215 symbolTables.lookupNearestSymbolFrom(op, calleeAttr);
2216 if (
auto fn = mlir::dyn_cast<mlir::FunctionOpInterface>(callee)) {
2217 llvmFnTy = converter->convertType<mlir::LLVM::LLVMFunctionType>(
2218 fn.getFunctionType());
2219 assert(llvmFnTy &&
"Failed to convert function type");
2220 }
else if (
auto alias = mlir::cast<mlir::LLVM::AliasOp>(callee)) {
2228 auto symAttr = mlir::cast<mlir::FlatSymbolRefAttr>(calleeAttr);
2230 mlir::LLVM::AddressOfOp::create(
2231 rewriter, op->getLoc(),
2232 mlir::LLVM::LLVMPointerType::get(rewriter.getContext()), symAttr)
2234 adjustedCallOperands.push_back(addrOfAlias);
2237 llvm::append_range(adjustedCallOperands, callOperands);
2238 callOperands = adjustedCallOperands;
2242 llvmFnTy = mlir::cast<mlir::LLVM::LLVMFunctionType>(alias.getType());
2245 return op->emitError(
"Unexpected callee type!");
2248 assert(!op->getOperands().empty() &&
2249 "operands list must no be empty for the indirect call");
2250 auto calleeTy = op->getOperands().front().getType();
2251 auto calleePtrTy = cast<cir::PointerType>(calleeTy);
2252 auto calleeFuncTy = cast<cir::FuncType>(calleePtrTy.getPointee());
2253 llvm::append_range(adjustedCallOperands, callOperands);
2254 llvmFnTy = cast<mlir::LLVM::LLVMFunctionType>(
2255 converter->convertType(calleeFuncTy));
2260 if (landingPadBlock) {
2261 auto newOp = rewriter.replaceOpWithNewOp<mlir::LLVM::InvokeOp>(
2262 op, llvmFnTy, calleeAttr, callOperands, continueBlock,
2263 mlir::ValueRange{}, landingPadBlock, mlir::ValueRange{});
2264 newOp->setAttrs(attributes);
2266 auto newOp = rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(
2267 op, llvmFnTy, calleeAttr, callOperands);
2268 newOp->setAttrs(attributes);
2270 newOp.setMemoryEffectsAttr(memoryEffects);
2271 newOp.setNoUnwind(noUnwind);
2272 newOp.setWillReturn(willReturn);
2273 newOp.setNoreturn(noReturn);
2274 if (op->hasAttr(CIRDialect::getMustTailAttrName()))
2275 newOp.setTailCallKind(mlir::LLVM::TailCallKind::MustTail);
2277 if (std::optional<cir::InlineKind> inlineKind = call.getInlineKind()) {
2278 newOp.setNoInline(*inlineKind == cir::InlineKind::NoInline);
2279 newOp.setInlineHint(*inlineKind == cir::InlineKind::InlineHint);
2280 newOp.setAlwaysInline(*inlineKind == cir::InlineKind::AlwaysInline);
2284 return mlir::success();
2287mlir::LogicalResult CIRToLLVMCallOpLowering::matchAndRewrite(
2288 cir::CallOp op, OpAdaptor adaptor,
2289 mlir::ConversionPatternRewriter &rewriter)
const {
2291 getTypeConverter(), symbolTables,
2292 op.getCalleeAttr());
2295mlir::LogicalResult CIRToLLVMTryCallOpLowering::matchAndRewrite(
2296 cir::TryCallOp op, OpAdaptor adaptor,
2297 mlir::ConversionPatternRewriter &rewriter)
const {
2300 op.getOperation(), adaptor.getOperands(), rewriter, getTypeConverter(),
2301 symbolTables, op.getCalleeAttr(), op.getNormalDest(), op.getUnwindDest());
2304mlir::LogicalResult CIRToLLVMReturnAddrOpLowering::matchAndRewrite(
2305 cir::ReturnAddrOp op, OpAdaptor adaptor,
2306 mlir::ConversionPatternRewriter &rewriter)
const {
2307 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
2309 llvmPtrTy, adaptor.getOperands());
2310 return mlir::success();
2313mlir::LogicalResult CIRToLLVMFrameAddrOpLowering::matchAndRewrite(
2314 cir::FrameAddrOp op, OpAdaptor adaptor,
2315 mlir::ConversionPatternRewriter &rewriter)
const {
2316 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
2318 adaptor.getOperands());
2319 return mlir::success();
2322mlir::LogicalResult CIRToLLVMClearCacheOpLowering::matchAndRewrite(
2323 cir::ClearCacheOp op, OpAdaptor adaptor,
2324 mlir::ConversionPatternRewriter &rewriter)
const {
2325 mlir::Value begin = adaptor.getBegin();
2326 mlir::Value end = adaptor.getEnd();
2327 auto intrinNameAttr =
2328 mlir::StringAttr::get(op.getContext(),
"llvm.clear_cache");
2329 rewriter.replaceOpWithNewOp<mlir::LLVM::CallIntrinsicOp>(
2330 op, mlir::Type{}, intrinNameAttr, mlir::ValueRange{begin, end});
2332 return mlir::success();
2335mlir::LogicalResult CIRToLLVMAddrOfReturnAddrOpLowering::matchAndRewrite(
2336 cir::AddrOfReturnAddrOp op, OpAdaptor adaptor,
2337 mlir::ConversionPatternRewriter &rewriter)
const {
2338 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
2340 llvmPtrTy, adaptor.getOperands());
2341 return mlir::success();
2344mlir::LogicalResult CIRToLLVMLoadOpLowering::matchAndRewrite(
2345 cir::LoadOp op, OpAdaptor adaptor,
2346 mlir::ConversionPatternRewriter &rewriter)
const {
2347 const mlir::Type llvmTy =
2350 return op.emitError()
2351 <<
"NYI: lowering load of a type with no memory representation";
2352 mlir::LLVM::AtomicOrdering ordering =
getLLVMMemOrder(op.getMemOrder());
2353 std::optional<size_t> opAlign = op.getAlignment();
2354 unsigned alignment = (unsigned)opAlign.value_or(
2359 std::optional<llvm::StringRef> llvmSyncScope =
2362 mlir::LLVM::LoadOp newLoad = mlir::LLVM::LoadOp::create(
2363 rewriter, op->getLoc(), llvmTy, adaptor.getAddr(), alignment,
2364 op.getIsVolatile(), op.getIsNontemporal(),
2365 op.getInvariant(),
false, ordering,
2366 llvmSyncScope.value_or(std::string()));
2367 if (mlir::Attribute domain = op->getAttr(
"cir.riscv_nontemporal_domain"))
2368 newLoad->setAttr(
"cir.riscv_nontemporal_domain", domain);
2371 mlir::Value result =
emitFromMemory(rewriter, *getTypeConverter(), dataLayout,
2372 op, newLoad.getResult());
2373 rewriter.replaceOp(op, result);
2375 return mlir::LogicalResult::success();
2379cir::direct::CIRToLLVMVecMaskedLoadOpLowering::matchAndRewrite(
2380 cir::VecMaskedLoadOp op, OpAdaptor adaptor,
2381 mlir::ConversionPatternRewriter &rewriter)
const {
2382 const mlir::Type llvmResTy =
2385 return op.emitError()
2386 <<
"NYI: lowering masked load of a type with no memory "
2389 std::optional<size_t> opAlign = op.getAlignment();
2390 unsigned alignment =
2391 (unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmResTy));
2393 mlir::IntegerAttr alignAttr = rewriter.getI32IntegerAttr(alignment);
2395 auto newLoad = mlir::LLVM::MaskedLoadOp::create(
2396 rewriter, op.getLoc(), llvmResTy, adaptor.getAddr(), adaptor.getMask(),
2397 adaptor.getPassThru(), alignAttr);
2399 rewriter.replaceOp(op, newLoad.getResult());
2400 return mlir::success();
2403mlir::LogicalResult CIRToLLVMStoreOpLowering::matchAndRewrite(
2404 cir::StoreOp op, OpAdaptor adaptor,
2405 mlir::ConversionPatternRewriter &rewriter)
const {
2406 mlir::LLVM::AtomicOrdering memorder =
getLLVMMemOrder(op.getMemOrder());
2407 mlir::Type valueType = op.getValue().getType();
2408 const mlir::Type llvmTy =
2411 return op.emitError()
2412 <<
"NYI: lowering store of a type with no memory representation";
2413 std::optional<size_t> opAlign = op.getAlignment();
2414 unsigned alignment = (unsigned)opAlign.value_or(
2421 op.getValue().getType(), adaptor.getValue());
2424 std::optional<llvm::StringRef> llvmSyncScope =
2427 mlir::LLVM::StoreOp storeOp = mlir::LLVM::StoreOp::create(
2428 rewriter, op->getLoc(), value, adaptor.getAddr(), alignment,
2430 op.getIsNontemporal(),
false,
2431 memorder, llvmSyncScope.value_or(std::string()));
2432 if (mlir::Attribute domain = op->getAttr(
"cir.riscv_nontemporal_domain"))
2433 storeOp->setAttr(
"cir.riscv_nontemporal_domain", domain);
2434 rewriter.replaceOp(op, storeOp);
2436 return mlir::LogicalResult::success();
2440 while (
auto arrTy = mlir::dyn_cast<cir::ArrayType>(ty))
2441 ty = arrTy.getElementType();
2446 return mlir::isa<cir::PointerType, cir::IntType, cir::BoolType,
2450mlir::LogicalResult CIRToLLVMConstantOpLowering::matchAndRewrite(
2451 cir::ConstantOp op, OpAdaptor adaptor,
2452 mlir::ConversionPatternRewriter &rewriter)
const {
2453 mlir::Attribute attr = op.getValue();
2455 if (mlir::isa<cir::PoisonAttr>(attr)) {
2456 rewriter.replaceOpWithNewOp<mlir::LLVM::PoisonOp>(
2457 op, getTypeConverter()->convertType(op.getType()));
2458 return mlir::success();
2461 if (mlir::isa<cir::UndefAttr>(attr)) {
2462 rewriter.replaceOpWithNewOp<mlir::LLVM::UndefOp>(
2463 op, getTypeConverter()->convertType(op.getType()));
2464 return mlir::success();
2467 if (mlir::isa<mlir::IntegerType>(op.getType())) {
2472 attr = op.getValue();
2473 }
else if (mlir::isa<cir::BoolType>(op.getType())) {
2474 int value = mlir::cast<cir::BoolAttr>(op.getValue()).getValue();
2475 attr = rewriter.getIntegerAttr(typeConverter->convertType(op.getType()),
2477 }
else if (mlir::isa<cir::IntType>(op.getType())) {
2479 if (
auto ga = mlir::dyn_cast<cir::GlobalViewAttr>(op.getValue())) {
2485 op.emitError() <<
"global view with integer type";
2486 return mlir::failure();
2489 attr = rewriter.getIntegerAttr(
2490 typeConverter->convertType(op.getType()),
2491 mlir::cast<cir::IntAttr>(op.getValue()).getValue());
2492 }
else if (mlir::isa<cir::FPTypeInterface>(op.getType())) {
2493 attr = rewriter.getFloatAttr(
2494 typeConverter->convertType(op.getType()),
2495 mlir::cast<cir::FPAttr>(op.getValue()).getValue());
2496 }
else if (mlir::isa<cir::PointerType>(op.getType())) {
2498 if (mlir::isa<cir::ConstPtrAttr>(op.getValue())) {
2499 if (mlir::cast<cir::ConstPtrAttr>(op.getValue()).isNullValue()) {
2500 rewriter.replaceOpWithNewOp<mlir::LLVM::ZeroOp>(
2501 op, typeConverter->convertType(op.getType()));
2502 return mlir::success();
2506 if (
auto gv = mlir::dyn_cast<cir::GlobalViewAttr>(op.getValue())) {
2508 getTypeConverter());
2509 rewriter.replaceOp(op, newOp);
2510 return mlir::success();
2512 attr = op.getValue();
2513 }
else if (
const auto arrTy = mlir::dyn_cast<cir::ArrayType>(op.getType())) {
2514 const auto constArr = mlir::dyn_cast<cir::ConstArrayAttr>(op.getValue());
2515 if (!constArr && !isa<cir::ZeroAttr, cir::UndefAttr>(op.getValue()))
2516 return op.emitError() <<
"array does not have a constant initializer";
2518 std::optional<mlir::Attribute> denseAttr;
2521 attr = denseAttr.value();
2524 op, op.getValue(), rewriter, symbolTables, typeConverter);
2525 rewriter.replaceOp(op, initVal);
2526 return mlir::success();
2528 }
else if (
const auto recordAttr =
2529 mlir::dyn_cast<cir::ConstRecordAttr>(op.getValue())) {
2532 rewriter.replaceOp(op, initVal);
2533 return mlir::success();
2534 }
else if (
const auto vecTy = mlir::dyn_cast<cir::VectorType>(op.getType())) {
2535 rewriter.replaceOp(op,
2537 symbolTables, getTypeConverter()));
2538 return mlir::success();
2539 }
else if (mlir::isa<cir::RecordType>(op.getType())) {
2540 if (mlir::isa<cir::ZeroAttr, cir::UndefAttr>(attr)) {
2541 mlir::Value initVal =
2543 rewriter.replaceOp(op, initVal);
2544 return mlir::success();
2546 return op.emitError() <<
"unsupported lowering for record constant type "
2548 }
else if (
auto complexTy = mlir::dyn_cast<cir::ComplexType>(op.getType())) {
2549 mlir::Type complexElemTy = complexTy.getElementType();
2550 mlir::Type complexElemLLVMTy = typeConverter->convertType(complexElemTy);
2552 if (
auto zeroInitAttr = mlir::dyn_cast<cir::ZeroAttr>(op.getValue())) {
2553 mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(complexElemLLVMTy);
2554 mlir::ArrayAttr array = rewriter.getArrayAttr({zeroAttr, zeroAttr});
2555 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
2556 op, getTypeConverter()->convertType(op.getType()), array);
2557 return mlir::success();
2560 if (mlir::isa<cir::UndefAttr>(op.getValue())) {
2561 rewriter.replaceOpWithNewOp<mlir::LLVM::UndefOp>(
2562 op, getTypeConverter()->convertType(op.getType()));
2563 return mlir::success();
2566 auto complexAttr = mlir::cast<cir::ConstComplexAttr>(op.getValue());
2568 mlir::Attribute components[2];
2569 if (mlir::isa<cir::IntType>(complexElemTy)) {
2570 components[0] = rewriter.getIntegerAttr(
2572 mlir::cast<cir::IntAttr>(complexAttr.getReal()).getValue());
2573 components[1] = rewriter.getIntegerAttr(
2575 mlir::cast<cir::IntAttr>(complexAttr.getImag()).getValue());
2577 components[0] = rewriter.getFloatAttr(
2579 mlir::cast<cir::FPAttr>(complexAttr.getReal()).getValue());
2580 components[1] = rewriter.getFloatAttr(
2582 mlir::cast<cir::FPAttr>(complexAttr.getImag()).getValue());
2585 attr = rewriter.getArrayAttr(components);
2587 return op.emitError() <<
"unsupported constant type " << op.getType();
2590 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
2591 op, getTypeConverter()->convertType(op.getType()),
attr);
2593 return mlir::success();
2597 mlir::DataLayout layout(op.getParentOfType<mlir::ModuleOp>());
2599 if (isa<cir::VoidType>(type))
2600 type = cir::IntType::get(type.getContext(), 8,
false);
2601 return llvm::divideCeil(layout.getTypeSizeInBits(type), 8);
2604mlir::LogicalResult CIRToLLVMPrefetchOpLowering::matchAndRewrite(
2605 cir::PrefetchOp op, OpAdaptor adaptor,
2606 mlir::ConversionPatternRewriter &rewriter)
const {
2607 rewriter.replaceOpWithNewOp<mlir::LLVM::Prefetch>(
2608 op, adaptor.getAddr(), adaptor.getIsWrite(), adaptor.getLocality(),
2610 return mlir::success();
2613mlir::LogicalResult CIRToLLVMPtrDiffOpLowering::matchAndRewrite(
2614 cir::PtrDiffOp op, OpAdaptor adaptor,
2615 mlir::ConversionPatternRewriter &rewriter)
const {
2616 auto dstTy = mlir::cast<cir::IntType>(op.getType());
2617 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
2619 auto lhs = mlir::LLVM::PtrToIntOp::create(rewriter, op.getLoc(), llvmDstTy,
2621 auto rhs = mlir::LLVM::PtrToIntOp::create(rewriter, op.getLoc(), llvmDstTy,
2625 mlir::LLVM::SubOp::create(rewriter, op.getLoc(), llvmDstTy, lhs, rhs);
2627 cir::PointerType ptrTy = op.getLhs().getType();
2629 uint64_t typeSize =
getTypeSize(ptrTy.getPointee(), *op);
2632 mlir::Value resultVal = diff.getResult();
2633 if (typeSize != 1) {
2634 auto typeSizeVal = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
2635 llvmDstTy, typeSize);
2637 if (dstTy.isUnsigned()) {
2639 mlir::LLVM::UDivOp::create(rewriter, op.getLoc(), diff, typeSizeVal);
2640 uDiv.setIsExact(
true);
2641 resultVal = uDiv.getResult();
2644 mlir::LLVM::SDivOp::create(rewriter, op.getLoc(), diff, typeSizeVal);
2645 sDiv.setIsExact(
true);
2646 resultVal = sDiv.getResult();
2649 rewriter.replaceOp(op, resultVal);
2650 return mlir::success();
2653mlir::LogicalResult CIRToLLVMExpectOpLowering::matchAndRewrite(
2654 cir::ExpectOp op, OpAdaptor adaptor,
2655 mlir::ConversionPatternRewriter &rewriter)
const {
2659 std::optional<llvm::APFloat> prob = op.getProb();
2661 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpectWithProbabilityOp>(
2662 op, adaptor.getVal(), adaptor.getExpected(), prob.value());
2664 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpectOp>(op, adaptor.getVal(),
2665 adaptor.getExpected());
2666 return mlir::success();
2669mlir::LogicalResult CIRToLLVMAbsOpLowering::matchAndRewrite(
2670 cir::AbsOp op, OpAdaptor adaptor,
2671 mlir::ConversionPatternRewriter &rewriter)
const {
2672 mlir::Type resTy = typeConverter->convertType(op.getType());
2673 auto absOp = mlir::LLVM::AbsOp::create(rewriter, op.getLoc(), resTy,
2674 adaptor.getOperands()[0],
2675 adaptor.getMinIsPoison());
2676 rewriter.replaceOp(op, absOp);
2677 return mlir::success();
2684void CIRToLLVMFuncOpLowering::lowerFuncAttributes(
2685 cir::FuncOp func,
bool filterArgAndResAttrs,
2686 SmallVectorImpl<mlir::NamedAttribute> &result)
const {
2687 for (mlir::NamedAttribute attr : func->getAttrs()) {
2688 if (
attr.getName() == mlir::SymbolTable::getSymbolAttrName() ||
2689 attr.getName() == func.getFunctionTypeAttrName() ||
2691 attr.getName() == func.getCallingConvAttrName() ||
2692 attr.getName() == func.getDsoLocalAttrName() ||
2693 attr.getName() == func.getInlineKindAttrName() ||
2694 attr.getName() == func.getSideEffectAttrName() ||
2695 attr.getName() == CIRDialect::getNoReturnAttrName() ||
2696 attr.getName() == CIRDialect::getStrictFPAttrName() ||
2697 attr.getName() == func.getAnnotationsAttrName() ||
2698 (filterArgAndResAttrs &&
2699 (
attr.getName() == func.getArgAttrsAttrName() ||
2700 attr.getName() == func.getResAttrsAttrName())))
2704 if (
attr.getName() == func.getArgAttrsAttrName()) {
2705 auto argAttrs = cast<mlir::ArrayAttr>(
attr.getValue());
2706 result.emplace_back(
2711 result.push_back(attr);
2715mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewriteAlias(
2716 cir::FuncOp op, llvm::StringRef aliasee, mlir::Type ty, OpAdaptor adaptor,
2717 mlir::ConversionPatternRewriter &rewriter)
const {
2718 SmallVector<mlir::NamedAttribute, 4> attributes;
2719 lowerFuncAttributes(op,
false, attributes);
2721 mlir::Location loc = op.getLoc();
2722 auto aliasOp = rewriter.replaceOpWithNewOp<mlir::LLVM::AliasOp>(
2723 op, ty,
convertLinkage(op.getLinkage()), op.getName(), op.getDsoLocal(),
2724 mlir::LLVM::ThreadLocalMode::NotThreadLocal, attributes);
2727 mlir::OpBuilder builder(op.getContext());
2728 mlir::Block *block = builder.createBlock(&aliasOp.getInitializerRegion());
2729 builder.setInsertionPointToStart(block);
2732 mlir::Type ptrTy = mlir::LLVM::LLVMPointerType::get(ty.getContext());
2733 auto addrOp = mlir::LLVM::AddressOfOp::create(builder, loc, ptrTy, aliasee);
2734 mlir::LLVM::ReturnOp::create(builder, loc, addrOp);
2736 return mlir::success();
2739mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewrite(
2740 cir::FuncOp op, OpAdaptor adaptor,
2741 mlir::ConversionPatternRewriter &rewriter)
const {
2743 cir::FuncType fnType = op.getFunctionType();
2744 bool isDsoLocal = op.getDsoLocal();
2745 mlir::TypeConverter::SignatureConversion signatureConversion(
2746 fnType.getNumInputs());
2748 for (
const auto &argType : llvm::enumerate(fnType.getInputs())) {
2749 mlir::Type convertedType = typeConverter->convertType(argType.value());
2751 return mlir::failure();
2752 signatureConversion.addInputs(argType.index(), convertedType);
2755 mlir::Type resultType =
2756 getTypeConverter()->convertType(fnType.getReturnType());
2759 mlir::Type llvmFnTy = mlir::LLVM::LLVMFunctionType::get(
2760 resultType ? resultType : mlir::LLVM::LLVMVoidType::get(getContext()),
2761 signatureConversion.getConvertedTypes(),
2765 if (std::optional<llvm::StringRef> aliasee = op.getAliasee())
2766 return matchAndRewriteAlias(op, *aliasee, llvmFnTy, adaptor, rewriter);
2770 mlir::Location loc = op.getLoc();
2771 if (mlir::FusedLoc fusedLoc = mlir::dyn_cast<mlir::FusedLoc>(loc))
2772 loc = fusedLoc.getLocations()[0];
2773 assert((mlir::isa<mlir::FileLineColLoc>(loc) ||
2774 mlir::isa<mlir::UnknownLoc>(loc)) &&
2775 "expected single location or unknown location here");
2779 SmallVector<mlir::NamedAttribute, 4> attributes;
2780 lowerFuncAttributes(op,
false, attributes);
2782 mlir::LLVM::LLVMFuncOp fn = mlir::LLVM::LLVMFuncOp::create(
2783 rewriter, loc, op.getName(), llvmFnTy, linkage, isDsoLocal, cconv,
2784 mlir::SymbolRefAttr(), attributes);
2788 if (std::optional<cir::SideEffect> sideEffectKind = op.getSideEffect()) {
2789 switch (*sideEffectKind) {
2790 case cir::SideEffect::All:
2792 case cir::SideEffect::Pure:
2793 fn.setMemoryEffectsAttr(mlir::LLVM::MemoryEffectsAttr::get(
2795 mlir::LLVM::ModRefInfo::Ref,
2796 mlir::LLVM::ModRefInfo::Ref,
2797 mlir::LLVM::ModRefInfo::Ref,
2798 mlir::LLVM::ModRefInfo::Ref,
2799 mlir::LLVM::ModRefInfo::Ref,
2800 mlir::LLVM::ModRefInfo::Ref));
2801 fn.setNoUnwind(
true);
2802 fn.setWillReturn(
true);
2804 case cir::SideEffect::Const:
2805 fn.setMemoryEffectsAttr(mlir::LLVM::MemoryEffectsAttr::get(
2807 mlir::LLVM::ModRefInfo::NoModRef,
2808 mlir::LLVM::ModRefInfo::NoModRef,
2809 mlir::LLVM::ModRefInfo::NoModRef,
2810 mlir::LLVM::ModRefInfo::NoModRef,
2811 mlir::LLVM::ModRefInfo::NoModRef,
2812 mlir::LLVM::ModRefInfo::NoModRef));
2813 fn.setNoUnwind(
true);
2814 fn.setWillReturn(
true);
2819 if (op->hasAttr(CIRDialect::getNoReturnAttrName()))
2820 fn.setNoreturn(
true);
2826 if (op->hasAttr(CIRDialect::getStrictFPAttrName()))
2827 fn.setPassthroughAttr(rewriter.getArrayAttr(
2828 {rewriter.getStringAttr(CIRDialect::getStrictFPAttrName())}));
2830 if (std::optional<cir::InlineKind> inlineKind = op.getInlineKind()) {
2831 fn.setNoInline(*inlineKind == cir::InlineKind::NoInline);
2832 fn.setInlineHint(*inlineKind == cir::InlineKind::InlineHint);
2833 fn.setAlwaysInline(*inlineKind == cir::InlineKind::AlwaysInline);
2836 if (std::optional<llvm::StringRef> personality = op.getPersonality())
2837 fn.setPersonality(*personality);
2842 rewriter.inlineRegionBefore(op.getBody(), fn.getBody(), fn.end());
2843 if (failed(rewriter.convertRegionTypes(&fn.getBody(), *typeConverter,
2844 &signatureConversion)))
2845 return mlir::failure();
2847 rewriter.eraseOp(op);
2849 return mlir::LogicalResult::success();
2852mlir::LogicalResult CIRToLLVMGetGlobalOpLowering::matchAndRewrite(
2853 cir::GetGlobalOp op, OpAdaptor adaptor,
2854 mlir::ConversionPatternRewriter &rewriter)
const {
2857 if (op->getUses().empty()) {
2858 rewriter.eraseOp(op);
2859 return mlir::success();
2862 mlir::Type
type = getTypeConverter()->convertType(op.getType());
2863 mlir::Operation *newop = mlir::LLVM::AddressOfOp::create(
2864 rewriter, op.getLoc(), type, op.getName());
2868 newop = mlir::LLVM::ThreadlocalAddressOp::create(rewriter, op.getLoc(),
2869 type, newop->getResult(0));
2872 rewriter.replaceOp(op, newop);
2873 return mlir::success();
2876llvm::SmallVector<mlir::NamedAttribute>
2877CIRToLLVMGlobalOpLowering::lowerGlobalAttributes(
2878 cir::GlobalOp op, mlir::ConversionPatternRewriter &rewriter)
const {
2879 SmallVector<mlir::NamedAttribute> attributes;
2881 if (mlir::StringAttr sectionAttr = op.getSectionAttr())
2882 attributes.push_back(rewriter.getNamedAttr(
"section", sectionAttr));
2884 mlir::LLVM::VisibilityAttr visibility = mlir::LLVM::VisibilityAttr::get(
2887 attributes.push_back(rewriter.getNamedAttr(
"visibility_", visibility));
2889 if (op->getAttr(CUDAExternallyInitializedAttr::getMnemonic()))
2890 attributes.push_back(rewriter.getNamedAttr(
"externally_initialized",
2891 rewriter.getUnitAttr()));
2896static mlir::LLVM::ThreadLocalMode
2899#define CHECK_ENUM(CIR, LLVM_VAL) \
2900 static_assert(static_cast<unsigned>(TLSModel::CIR) == \
2901 static_cast<unsigned>(mlir::LLVM::ThreadLocalMode::LLVM_VAL))
2909 return mlir::LLVM::ThreadLocalMode::NotThreadLocal;
2911 return static_cast<mlir::LLVM::ThreadLocalMode
>(attr.getValue());
2916void CIRToLLVMGlobalOpLowering::setupRegionInitializedLLVMGlobalOp(
2917 cir::GlobalOp op, mlir::ConversionPatternRewriter &rewriter)
const {
2918 mlir::Type llvmType =
2923 if (std::optional<mlir::Attribute> init = op.getInitialValue())
2931 const bool isConst = op.getConstant();
2932 unsigned addrSpace = 0;
2933 if (
auto targetAS = mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
2934 op.getAddrSpaceAttr()))
2935 addrSpace = targetAS.getValue();
2936 const bool isDsoLocal = op.getDsoLocal();
2937 mlir::LLVM::ThreadLocalMode threadLocalMode =
2939 const uint64_t alignment = op.getAlignment().value_or(0);
2940 const mlir::LLVM::Linkage linkage =
convertLinkage(op.getLinkage());
2941 const StringRef symbol = op.getSymName();
2942 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
2945 lowerGlobalAttributes(op, rewriter);
2947 mlir::LLVM::GlobalOp newGlobalOp =
2948 rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
2949 op, llvmType, isConst, linkage, symbol,
nullptr, alignment, addrSpace,
2950 isDsoLocal, threadLocalMode, comdatAttr, attributes);
2951 newGlobalOp.getRegion().emplaceBlock();
2952 rewriter.setInsertionPointToEnd(newGlobalOp.getInitializerBlock());
2956CIRToLLVMGlobalOpLowering::matchAndRewriteRegionInitializedGlobal(
2957 cir::GlobalOp op, mlir::Attribute init,
2958 mlir::ConversionPatternRewriter &rewriter)
const {
2961 (isa<cir::BlockAddrDiffAttr, cir::BlockAddrInfoAttr, cir::ConstArrayAttr,
2962 cir::ConstRecordAttr, cir::ConstVectorAttr, cir::ConstPtrAttr,
2963 cir::ConstComplexAttr, cir::GlobalViewAttr, cir::TypeInfoAttr,
2964 cir::UndefAttr, cir::PoisonAttr, cir::VTableAttr, cir::ZeroAttr>(
2970 const mlir::Location loc = op.getLoc();
2971 setupRegionInitializedLLVMGlobalOp(op, rewriter);
2976 CIRAttrToValue valueConverter(op, rewriter, symbolTables, typeConverter,
2978 mlir::Value value = valueConverter.visit(init);
2979 mlir::LLVM::ReturnOp::create(rewriter, loc, value);
2980 return mlir::success();
2983mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite(
2984 cir::GlobalOp op, OpAdaptor adaptor,
2985 mlir::ConversionPatternRewriter &rewriter)
const {
2988 if (!op.getCtorRegion().empty() || !op.getDtorRegion().empty())
2989 return op.emitError() <<
"GlobalOp ctor and dtor regions should be removed "
2990 "in LoweringPrepare";
2992 std::optional<mlir::Attribute> init = op.getInitialValue();
2995 const mlir::Type cirSymType = op.getSymType();
2998 mlir::Type llvmType =
3001 return op.emitError()
3002 <<
"NYI: lowering global of a type with no memory representation";
3007 if (init.has_value())
3013 const bool isConst = op.getConstant();
3014 unsigned addrSpace = 0;
3015 if (
auto targetAS = mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
3016 op.getAddrSpaceAttr()))
3017 addrSpace = targetAS.getValue();
3018 const bool isDsoLocal = op.getDsoLocal();
3019 mlir::LLVM::ThreadLocalMode threadLocalMode =
3021 const uint64_t alignment = op.getAlignment().value_or(0);
3022 const mlir::LLVM::Linkage linkage =
convertLinkage(op.getLinkage());
3023 const StringRef symbol = op.getSymName();
3024 SmallVector<mlir::NamedAttribute> attributes =
3025 lowerGlobalAttributes(op, rewriter);
3028 if (std::optional<llvm::StringRef> aliasee = op.getAliasee()) {
3029 mlir::Location loc = op.getLoc();
3030 auto aliasOp = rewriter.replaceOpWithNewOp<mlir::LLVM::AliasOp>(
3031 op, llvmType, linkage, symbol, isDsoLocal, threadLocalMode, attributes);
3033 mlir::OpBuilder builder(op.getContext());
3034 mlir::Block *block = builder.createBlock(&aliasOp.getInitializerRegion());
3035 builder.setInsertionPointToStart(block);
3037 mlir::LLVM::LLVMPointerType::get(getContext(), addrSpace);
3039 mlir::LLVM::AddressOfOp::create(builder, loc, ptrTy, *aliasee);
3040 mlir::LLVM::ReturnOp::create(builder, loc, addrOp);
3041 return mlir::success();
3044 if (init.has_value()) {
3045 if (mlir::isa<cir::FPAttr, cir::IntAttr, cir::BoolAttr>(init.value())) {
3047 init = initRewriter.visit(init.value());
3052 if (!init.value()) {
3053 op.emitError() <<
"unsupported initializer '" << init.value() <<
"'";
3054 return mlir::failure();
3056 }
else if (
auto constArr =
3057 mlir::dyn_cast<cir::ConstArrayAttr>(init.value())) {
3065 mlir::ModuleOp modOp = op->getParentOfType<mlir::ModuleOp>();
3067 constArr, symbolTables, typeConverter, modOp)) {
3068 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
3069 rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
3070 op, llvmType, isConst, linkage, symbol, bulkInit.value(),
3071 alignment, addrSpace, isDsoLocal, threadLocalMode, comdatAttr,
3073 return mlir::success();
3076 return matchAndRewriteRegionInitializedGlobal(op, init.value(), rewriter);
3077 }
else if (
auto constRecord =
3078 mlir::dyn_cast<cir::ConstRecordAttr>(init.value())) {
3084 mlir::ModuleOp modOp = op->getParentOfType<mlir::ModuleOp>();
3086 constRecord, symbolTables, typeConverter, modOp)) {
3087 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
3088 rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
3089 op, llvmType, isConst, linkage, symbol, bulkInit.value(), alignment,
3090 addrSpace, isDsoLocal, threadLocalMode, comdatAttr, attributes);
3091 return mlir::success();
3093 return matchAndRewriteRegionInitializedGlobal(op, init.value(), rewriter);
3094 }
else if (mlir::isa<cir::BlockAddrDiffAttr, cir::BlockAddrInfoAttr,
3095 cir::ConstVectorAttr, cir::ConstRecordAttr,
3096 cir::ConstPtrAttr, cir::ConstComplexAttr,
3097 cir::GlobalViewAttr, cir::TypeInfoAttr, cir::UndefAttr,
3098 cir::PoisonAttr, cir::VTableAttr, cir::ZeroAttr>(
3103 return matchAndRewriteRegionInitializedGlobal(op, init.value(), rewriter);
3107 op.emitError() <<
"unsupported initializer '" << init.value() <<
"'";
3108 return mlir::failure();
3112 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
3113 rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
3114 op, llvmType, isConst, linkage, symbol, init.value_or(mlir::Attribute()),
3115 alignment, addrSpace, isDsoLocal, threadLocalMode, comdatAttr,
3118 return mlir::success();
3122CIRToLLVMGlobalOpLowering::getComdatAttr(cir::GlobalOp &op,
3123 mlir::OpBuilder &builder)
const {
3124 if (!op.getComdat())
3125 return mlir::SymbolRefAttr{};
3127 mlir::ModuleOp modOp = op->getParentOfType<mlir::ModuleOp>();
3128 mlir::OpBuilder::InsertionGuard guard(builder);
3129 StringRef comdatName(
"__llvm_comdat_globals");
3131 builder.setInsertionPointToStart(modOp.getBody());
3133 mlir::LLVM::ComdatOp::create(builder, modOp.getLoc(), comdatName);
3136 if (
auto comdatSelector = comdatOp.lookupSymbol<mlir::LLVM::ComdatSelectorOp>(
3138 return mlir::SymbolRefAttr::get(
3139 builder.getContext(), comdatName,
3140 mlir::FlatSymbolRefAttr::get(comdatSelector.getSymNameAttr()));
3143 builder.setInsertionPointToStart(&comdatOp.getBody().back());
3144 auto selectorOp = mlir::LLVM::ComdatSelectorOp::create(
3145 builder, comdatOp.getLoc(), op.getSymName(),
3146 mlir::LLVM::comdat::Comdat::Any);
3147 return mlir::SymbolRefAttr::get(
3148 builder.getContext(), comdatName,
3149 mlir::FlatSymbolRefAttr::get(selectorOp.getSymNameAttr()));
3152mlir::LogicalResult CIRToLLVMSwitchFlatOpLowering::matchAndRewrite(
3153 cir::SwitchFlatOp op, OpAdaptor adaptor,
3154 mlir::ConversionPatternRewriter &rewriter)
const {
3156 llvm::SmallVector<mlir::APInt, 8> caseValues;
3157 for (mlir::Attribute val : op.getCaseValues()) {
3158 auto intAttr = cast<cir::IntAttr>(val);
3159 caseValues.push_back(intAttr.getValue());
3162 llvm::SmallVector<mlir::Block *, 8> caseDestinations;
3163 llvm::SmallVector<mlir::ValueRange, 8> caseOperands;
3165 for (mlir::Block *x : op.getCaseDestinations())
3166 caseDestinations.push_back(x);
3168 for (mlir::OperandRange x : op.getCaseOperands())
3169 caseOperands.push_back(x);
3172 rewriter.setInsertionPoint(op);
3173 rewriter.replaceOpWithNewOp<mlir::LLVM::SwitchOp>(
3174 op, adaptor.getCondition(), op.getDefaultDestination(),
3175 op.getDefaultOperands(), caseValues, caseDestinations, caseOperands);
3176 return mlir::success();
3179static mlir::LLVM::IntegerOverflowFlags
nswFlag(
bool nsw) {
3180 return nsw ? mlir::LLVM::IntegerOverflowFlags::nsw
3181 : mlir::LLVM::IntegerOverflowFlags::none;
3184template <
typename CIROp,
typename LLVMIntOp>
3185static mlir::LogicalResult
3187 mlir::ConversionPatternRewriter &rewriter) {
3188 mlir::Type llvmType = adaptor.getInput().getType();
3189 mlir::Location loc = op.getLoc();
3191 auto maybeNSW =
nswFlag(op.getNoSignedWrap());
3192 mlir::LLVM::ConstantOp one;
3193 if (mlir::isa<cir::VectorType>(op.getType())) {
3194 mlir::DenseIntElementsAttr oneVec = mlir::DenseIntElementsAttr::get(
3195 mlir::cast<mlir::ShapedType>(llvmType), 1);
3196 one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, oneVec);
3198 one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
3200 rewriter.replaceOpWithNewOp<LLVMIntOp>(op, adaptor.getInput(), one, maybeNSW);
3201 return mlir::success();
3204mlir::LogicalResult CIRToLLVMIncOpLowering::matchAndRewrite(
3205 cir::IncOp op, OpAdaptor adaptor,
3206 mlir::ConversionPatternRewriter &rewriter)
const {
3210mlir::LogicalResult CIRToLLVMDecOpLowering::matchAndRewrite(
3211 cir::DecOp op, OpAdaptor adaptor,
3212 mlir::ConversionPatternRewriter &rewriter)
const {
3216mlir::LogicalResult CIRToLLVMMinusOpLowering::matchAndRewrite(
3217 cir::MinusOp op, OpAdaptor adaptor,
3218 mlir::ConversionPatternRewriter &rewriter)
const {
3219 bool isVector = mlir::isa<cir::VectorType>(op.getType());
3220 mlir::Type llvmType = adaptor.getInput().getType();
3221 mlir::Location loc = op.getLoc();
3223 auto maybeNSW =
nswFlag(op.getNoSignedWrap());
3226 zero = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmType);
3228 zero = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 0);
3229 rewriter.replaceOpWithNewOp<mlir::LLVM::SubOp>(op, zero, adaptor.getInput(),
3231 return mlir::success();
3234mlir::LogicalResult CIRToLLVMNotOpLowering::matchAndRewrite(
3235 cir::NotOp op, OpAdaptor adaptor,
3236 mlir::ConversionPatternRewriter &rewriter)
const {
3237 mlir::Type elementType = elementTypeIfVector(op.getType());
3238 bool isVector = mlir::isa<cir::VectorType>(op.getType());
3239 mlir::Type llvmType = adaptor.getInput().getType();
3240 mlir::Location loc = op.getLoc();
3242 if (mlir::isa<cir::IntType>(elementType)) {
3243 mlir::Value minusOne;
3246 mlir::dyn_cast<cir::VectorType>(op.getType()).getSize();
3247 SmallVector<int32_t> values(numElements, -1);
3248 mlir::DenseIntElementsAttr denseVec = rewriter.getI32VectorAttr(values);
3250 mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, denseVec);
3252 minusOne = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, -1);
3254 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getInput(),
3256 return mlir::success();
3258 if (mlir::isa<cir::BoolType>(elementType)) {
3259 auto one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
3260 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getInput(), one);
3261 return mlir::success();
3263 return op.emitError() <<
"Unsupported type for bitwise NOT";
3268 return mlir::isa<cir::IntType>(type)
3269 ? mlir::cast<cir::IntType>(type).isUnsigned()
3270 : mlir::cast<mlir::IntegerType>(type).isUnsigned();
3277template <
typename BinOp>
3279 if (op.getNoUnsignedWrap())
3280 return mlir::LLVM::IntegerOverflowFlags::nuw;
3281 if (op.getNoSignedWrap())
3282 return mlir::LLVM::IntegerOverflowFlags::nsw;
3283 return mlir::LLVM::IntegerOverflowFlags::none;
3288template <
typename UIntSatOp,
typename SIntSatOp,
typename IntOp,
3290static mlir::LogicalResult
3292 mlir::ConversionPatternRewriter &rewriter) {
3293 const mlir::Type eltType = elementTypeIfVector(op.getRhs().getType());
3294 assert(cir::isIntOrBoolType(eltType) &&
3295 "saturatable arith op expects integer operand types");
3296 if (op.getSaturated()) {
3298 rewriter.replaceOpWithNewOp<UIntSatOp>(op, lhs, rhs);
3300 rewriter.replaceOpWithNewOp<SIntSatOp>(op, lhs, rhs);
3301 return mlir::success();
3303 rewriter.replaceOpWithNewOp<IntOp>(op, lhs, rhs,
intOverflowFlag(op));
3304 return mlir::success();
3307mlir::LogicalResult CIRToLLVMAddOpLowering::matchAndRewrite(
3308 cir::AddOp op, OpAdaptor adaptor,
3309 mlir::ConversionPatternRewriter &rewriter)
const {
3311 mlir::LLVM::AddOp>(op, adaptor.getLhs(),
3312 adaptor.getRhs(), rewriter);
3315mlir::LogicalResult CIRToLLVMSubOpLowering::matchAndRewrite(
3316 cir::SubOp op, OpAdaptor adaptor,
3317 mlir::ConversionPatternRewriter &rewriter)
const {
3319 mlir::LLVM::SubOp>(op, adaptor.getLhs(),
3320 adaptor.getRhs(), rewriter);
3323mlir::LogicalResult CIRToLLVMMulOpLowering::matchAndRewrite(
3324 cir::MulOp op, OpAdaptor adaptor,
3325 mlir::ConversionPatternRewriter &rewriter)
const {
3326 assert(cir::isIntOrBoolType(elementTypeIfVector(op.getRhs().getType())) &&
3327 "cir.mul expects integer operand types");
3328 rewriter.replaceOpWithNewOp<mlir::LLVM::MulOp>(
3330 return mlir::success();
3334template <
typename UIntOp,
typename SIntOp,
typename CIROp>
3335static mlir::LogicalResult
3337 mlir::ConversionPatternRewriter &rewriter) {
3338 const mlir::Type eltType = elementTypeIfVector(op.getRhs().getType());
3339 assert(cir::isIntOrBoolType(eltType) &&
3340 "integer binary op expects integer operand types");
3342 rewriter.replaceOpWithNewOp<UIntOp>(op, lhs, rhs);
3344 rewriter.replaceOpWithNewOp<SIntOp>(op, lhs, rhs);
3345 return mlir::success();
3348mlir::LogicalResult CIRToLLVMDivOpLowering::matchAndRewrite(
3349 cir::DivOp op, OpAdaptor adaptor,
3350 mlir::ConversionPatternRewriter &rewriter)
const {
3352 op, adaptor.getLhs(), adaptor.getRhs(), rewriter);
3355mlir::LogicalResult CIRToLLVMRemOpLowering::matchAndRewrite(
3356 cir::RemOp op, OpAdaptor adaptor,
3357 mlir::ConversionPatternRewriter &rewriter)
const {
3359 op, adaptor.getLhs(), adaptor.getRhs(), rewriter);
3362template <
typename CIROp,
typename UIntOp,
typename SIntOp>
3363static mlir::LogicalResult
3365 mlir::ConversionPatternRewriter &rewriter) {
3366 const mlir::Value lhs = adaptor.getLhs();
3367 const mlir::Value rhs = adaptor.getRhs();
3369 rewriter.replaceOpWithNewOp<UIntOp>(op, lhs, rhs);
3371 rewriter.replaceOpWithNewOp<SIntOp>(op, lhs, rhs);
3372 return mlir::success();
3375mlir::LogicalResult CIRToLLVMMaxOpLowering::matchAndRewrite(
3376 cir::MaxOp op, OpAdaptor adaptor,
3377 mlir::ConversionPatternRewriter &rewriter)
const {
3379 op, adaptor, rewriter);
3382mlir::LogicalResult CIRToLLVMMinOpLowering::matchAndRewrite(
3383 cir::MinOp op, OpAdaptor adaptor,
3384 mlir::ConversionPatternRewriter &rewriter)
const {
3386 op, adaptor, rewriter);
3390static mlir::LLVM::ICmpPredicate
3392 using CIR = cir::CmpOpKind;
3393 using LLVMICmp = mlir::LLVM::ICmpPredicate;
3396 return LLVMICmp::eq;
3398 return LLVMICmp::ne;
3400 return (isSigned ? LLVMICmp::slt : LLVMICmp::ult);
3402 return (isSigned ? LLVMICmp::sle : LLVMICmp::ule);
3404 return (isSigned ? LLVMICmp::sgt : LLVMICmp::ugt);
3406 return (isSigned ? LLVMICmp::sge : LLVMICmp::uge);
3409 llvm_unreachable(
"FP-only comparison used with integer type");
3411 llvm_unreachable(
"Unknown CmpOpKind");
3416static mlir::LLVM::FCmpPredicate
3418 using CIR = cir::CmpOpKind;
3419 using LLVMFCmp = mlir::LLVM::FCmpPredicate;
3422 return LLVMFCmp::oeq;
3424 return LLVMFCmp::une;
3426 return LLVMFCmp::olt;
3428 return LLVMFCmp::ole;
3430 return LLVMFCmp::ogt;
3432 return LLVMFCmp::oge;
3434 return LLVMFCmp::one;
3436 return LLVMFCmp::uno;
3438 llvm_unreachable(
"Unknown CmpOpKind");
3441static llvm::StringRef
3443 using CIR = cir::CmpOpKind;
3462 llvm_unreachable(
"Unknown CmpOpKind");
3466 using CIR = cir::CmpOpKind;
3479 llvm_unreachable(
"Unknown CmpOpKind");
3482static mlir::LLVM::CallIntrinsicOp
3484 mlir::Location loc, mlir::Value lhs, mlir::Value rhs,
3485 cir::CmpOpKind
kind, cir::FenvAttr fenv,
3486 mlir::Type llvmResTy) {
3494 ?
"llvm.experimental.constrained.fcmps"
3495 :
"llvm.experimental.constrained.fcmp";
3500mlir::LogicalResult CIRToLLVMCmpOpLowering::matchAndRewrite(
3501 cir::CmpOp cmpOp, OpAdaptor adaptor,
3502 mlir::ConversionPatternRewriter &rewriter)
const {
3503 mlir::Type type = cmpOp.getLhs().getType();
3505 if (mlir::isa<cir::IntType, mlir::IntegerType>(type)) {
3506 bool isSigned = mlir::isa<cir::IntType>(type)
3507 ? mlir::cast<cir::IntType>(type).isSigned()
3508 : mlir::cast<mlir::IntegerType>(type).isSigned();
3509 mlir::LLVM::ICmpPredicate
kind =
3511 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
3512 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
3513 return mlir::success();
3516 if (mlir::isa<cir::BoolType, cir::PointerType, cir::VPtrType>(type)) {
3520 mlir::LLVM::ICmpPredicate
kind =
3522 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
3523 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
3524 return mlir::success();
3527 if (mlir::isa<cir::FPTypeInterface>(type)) {
3528 mlir::Type llvmResTy = getTypeConverter()->convertType(cmpOp.getType());
3529 if (cir::FenvAttr fenv = cmpOp.getFenvAttr()) {
3531 rewriter, cmpOp.getLoc(), adaptor.getLhs(), adaptor.getRhs(),
3532 cmpOp.getKind(), fenv, llvmResTy);
3533 rewriter.replaceOp(cmpOp, call.getResult(0));
3534 return mlir::success();
3536 mlir::LLVM::FCmpPredicate
kind =
3538 rewriter.replaceOpWithNewOp<mlir::LLVM::FCmpOp>(
3539 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
3540 return mlir::success();
3543 if (mlir::isa<cir::ComplexType>(type)) {
3544 mlir::Value lhs = adaptor.getLhs();
3545 mlir::Value rhs = adaptor.getRhs();
3546 mlir::Location loc = cmpOp.getLoc();
3548 auto complexType = mlir::cast<cir::ComplexType>(cmpOp.getLhs().getType());
3549 mlir::Type complexElemTy =
3550 getTypeConverter()->convertType(
complexType.getElementType());
3552 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
3553 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{0}));
3554 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
3555 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{1}));
3556 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
3557 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{0}));
3558 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
3559 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{1}));
3561 if (cmpOp.getKind() == cir::CmpOpKind::eq) {
3562 if (complexElemTy.isInteger()) {
3563 auto realCmp = mlir::LLVM::ICmpOp::create(
3564 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, lhsReal, rhsReal);
3565 auto imagCmp = mlir::LLVM::ICmpOp::create(
3566 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, lhsImag, rhsImag);
3567 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, imagCmp);
3568 return mlir::success();
3571 auto realCmp = mlir::LLVM::FCmpOp::create(
3572 rewriter, loc, mlir::LLVM::FCmpPredicate::oeq, lhsReal, rhsReal);
3573 auto imagCmp = mlir::LLVM::FCmpOp::create(
3574 rewriter, loc, mlir::LLVM::FCmpPredicate::oeq, lhsImag, rhsImag);
3575 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, imagCmp);
3576 return mlir::success();
3579 if (cmpOp.getKind() == cir::CmpOpKind::ne) {
3580 if (complexElemTy.isInteger()) {
3581 auto realCmp = mlir::LLVM::ICmpOp::create(
3582 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, lhsReal, rhsReal);
3583 auto imagCmp = mlir::LLVM::ICmpOp::create(
3584 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, lhsImag, rhsImag);
3585 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp);
3586 return mlir::success();
3589 auto realCmp = mlir::LLVM::FCmpOp::create(
3590 rewriter, loc, mlir::LLVM::FCmpPredicate::une, lhsReal, rhsReal);
3591 auto imagCmp = mlir::LLVM::FCmpOp::create(
3592 rewriter, loc, mlir::LLVM::FCmpPredicate::une, lhsImag, rhsImag);
3593 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp);
3594 return mlir::success();
3598 return cmpOp.emitError() <<
"unsupported type for CmpOp: " <<
type;
3604template <
typename OpTy>
3605static mlir::LogicalResult
3607 mlir::ConversionPatternRewriter &rewriter,
3608 const mlir::TypeConverter *typeConverter,
3609 llvm::StringRef opStr) {
3610 mlir::Location loc = op.getLoc();
3611 cir::IntType operandTy = op.getLhs().getType();
3614 mlir::Type resultTy = op.getResult().getType();
3615 auto resultIntTy = mlir::dyn_cast<cir::IntType>(resultTy);
3616 unsigned resultWidth = resultIntTy ? resultIntTy.getWidth() : 1;
3617 bool resultSigned = resultIntTy && resultIntTy.getIsSigned();
3619 bool sign = operandTy.getIsSigned() || resultSigned;
3621 std::max(operandTy.getWidth() + (
sign && operandTy.isUnsigned()),
3622 resultWidth + (
sign && !resultSigned));
3624 mlir::IntegerType encompassedLLVMTy = rewriter.getIntegerType(width);
3626 mlir::Value lhs = adaptor.getLhs();
3627 mlir::Value rhs = adaptor.getRhs();
3628 if (operandTy.getWidth() < width) {
3629 if (operandTy.isSigned()) {
3630 lhs = mlir::LLVM::SExtOp::create(rewriter, loc, encompassedLLVMTy, lhs);
3631 rhs = mlir::LLVM::SExtOp::create(rewriter, loc, encompassedLLVMTy, rhs);
3633 lhs = mlir::LLVM::ZExtOp::create(rewriter, loc, encompassedLLVMTy, lhs);
3634 rhs = mlir::LLVM::ZExtOp::create(rewriter, loc, encompassedLLVMTy, rhs);
3639 std::string intrinName = (
"llvm." + llvm::Twine(
sign ?
's' :
'u') + opStr +
3640 ".with.overflow.i" + llvm::Twine(width))
3642 auto intrinNameAttr = mlir::StringAttr::get(op.getContext(), intrinName);
3644 mlir::IntegerType overflowLLVMTy = rewriter.getI1Type();
3645 auto intrinRetTy = mlir::LLVM::LLVMStructType::getLiteral(
3646 rewriter.getContext(), {encompassedLLVMTy, overflowLLVMTy});
3648 auto callLLVMIntrinOp = mlir::LLVM::CallIntrinsicOp::create(
3649 rewriter, loc, intrinRetTy, intrinNameAttr, mlir::ValueRange{lhs, rhs});
3650 mlir::Value intrinRet = callLLVMIntrinOp.getResult(0);
3652 mlir::Value result = mlir::LLVM::ExtractValueOp::create(
3655 mlir::Value overflow = mlir::LLVM::ExtractValueOp::create(
3659 if (resultWidth < width) {
3660 mlir::Type resultLLVMTy = typeConverter->convertType(resultTy);
3662 mlir::LLVM::TruncOp::create(rewriter, loc, resultLLVMTy, result);
3666 mlir::Value truncResultExt;
3668 truncResultExt = mlir::LLVM::SExtOp::create(
3669 rewriter, loc, encompassedLLVMTy, truncResult);
3671 truncResultExt = mlir::LLVM::ZExtOp::create(
3672 rewriter, loc, encompassedLLVMTy, truncResult);
3673 auto truncOverflow = mlir::LLVM::ICmpOp::create(
3674 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, truncResultExt, result);
3676 result = truncResult;
3677 overflow = mlir::LLVM::OrOp::create(rewriter, loc, overflow, truncOverflow);
3680 mlir::Type boolLLVMTy =
3681 typeConverter->convertType(op.getOverflow().getType());
3682 if (boolLLVMTy != rewriter.getI1Type())
3683 overflow = mlir::LLVM::ZExtOp::create(rewriter, loc, boolLLVMTy, overflow);
3685 rewriter.replaceOp(op, mlir::ValueRange{result, overflow});
3687 return mlir::success();
3690mlir::LogicalResult CIRToLLVMAddOverflowOpLowering::matchAndRewrite(
3691 cir::AddOverflowOp op, OpAdaptor adaptor,
3692 mlir::ConversionPatternRewriter &rewriter)
const {
3696mlir::LogicalResult CIRToLLVMSubOverflowOpLowering::matchAndRewrite(
3697 cir::SubOverflowOp op, OpAdaptor adaptor,
3698 mlir::ConversionPatternRewriter &rewriter)
const {
3702mlir::LogicalResult CIRToLLVMMulOverflowOpLowering::matchAndRewrite(
3703 cir::MulOverflowOp op, OpAdaptor adaptor,
3704 mlir::ConversionPatternRewriter &rewriter)
const {
3708mlir::LogicalResult CIRToLLVMFrexpOpLowering::matchAndRewrite(
3709 cir::FrexpOp op, OpAdaptor adaptor,
3710 mlir::ConversionPatternRewriter &rewriter)
const {
3711 mlir::Location loc = op.getLoc();
3712 mlir::Type fpLLVMTy =
3713 getTypeConverter()->convertType(op.getResult().getType());
3714 mlir::Type intLLVMTy = getTypeConverter()->convertType(op.getExp().getType());
3716 auto structTy = mlir::LLVM::LLVMStructType::getLiteral(rewriter.getContext(),
3717 {fpLLVMTy, intLLVMTy});
3721 mlir::Value result = callOp.getResult(0);
3723 mlir::Value mantissa =
3724 mlir::LLVM::ExtractValueOp::create(rewriter, loc, result, 0);
3725 mlir::Value exponent =
3726 mlir::LLVM::ExtractValueOp::create(rewriter, loc, result, 1);
3727 rewriter.replaceOp(op, mlir::ValueRange{mantissa, exponent});
3728 return mlir::success();
3731mlir::LogicalResult CIRToLLVMModfOpLowering::matchAndRewrite(
3732 cir::ModfOp op, OpAdaptor adaptor,
3733 mlir::ConversionPatternRewriter &rewriter)
const {
3734 mlir::Location loc = op.getLoc();
3735 mlir::Type fpLLVMTy =
3736 getTypeConverter()->convertType(op.getFractional().getType());
3738 auto structTy = mlir::LLVM::LLVMStructType::getLiteral(rewriter.getContext(),
3739 {fpLLVMTy, fpLLVMTy});
3743 mlir::Value result = callOp.getResult(0);
3745 mlir::Value fractional =
3746 mlir::LLVM::ExtractValueOp::create(rewriter, loc, result, 0);
3747 mlir::Value integral =
3748 mlir::LLVM::ExtractValueOp::create(rewriter, loc, result, 1);
3749 rewriter.replaceOp(op, mlir::ValueRange{fractional, integral});
3750 return mlir::success();
3753mlir::LogicalResult CIRToLLVMShiftOpLowering::matchAndRewrite(
3754 cir::ShiftOp op, OpAdaptor adaptor,
3755 mlir::ConversionPatternRewriter &rewriter)
const {
3756 assert((op.getValue().getType() == op.getType()) &&
3757 "inconsistent operands' types NYI");
3759 const mlir::Type llvmTy = getTypeConverter()->convertType(op.getType());
3760 mlir::Value amt = adaptor.getAmount();
3761 mlir::Value val = adaptor.getValue();
3763 auto cirAmtTy = mlir::dyn_cast<cir::IntType>(op.getAmount().getType());
3766 auto cirValTy = mlir::cast<cir::IntType>(op.getValue().getType());
3774 amt =
getLLVMIntCast(rewriter, amt, llvmTy,
true, cirAmtTy.getWidth(),
3775 cirValTy.getWidth());
3777 auto cirValVTy = mlir::cast<cir::VectorType>(op.getValue().getType());
3779 mlir::cast<cir::IntType>(cirValVTy.getElementType()).isUnsigned();
3783 if (op.getIsShiftleft()) {
3784 rewriter.replaceOpWithNewOp<mlir::LLVM::ShlOp>(op, llvmTy, val, amt);
3785 return mlir::success();
3789 rewriter.replaceOpWithNewOp<mlir::LLVM::LShrOp>(op, llvmTy, val, amt);
3791 rewriter.replaceOpWithNewOp<mlir::LLVM::AShrOp>(op, llvmTy, val, amt);
3792 return mlir::success();
3795mlir::LogicalResult CIRToLLVMSelectOpLowering::matchAndRewrite(
3796 cir::SelectOp op, OpAdaptor adaptor,
3797 mlir::ConversionPatternRewriter &rewriter)
const {
3798 auto getConstantBool = [](mlir::Value value) -> cir::BoolAttr {
3799 auto definingOp = value.getDefiningOp<cir::ConstantOp>();
3803 auto constValue = definingOp.getValueAttr<cir::BoolAttr>();
3813 if (mlir::isa<cir::BoolType>(op.getTrueValue().getType())) {
3814 cir::BoolAttr trueValue = getConstantBool(op.getTrueValue());
3815 cir::BoolAttr falseValue = getConstantBool(op.getFalseValue());
3816 if (falseValue && !falseValue.getValue()) {
3818 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(op, adaptor.getCondition(),
3819 adaptor.getTrueValue());
3820 return mlir::success();
3822 if (trueValue && trueValue.getValue()) {
3824 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(op, adaptor.getCondition(),
3825 adaptor.getFalseValue());
3826 return mlir::success();
3830 mlir::Value llvmCondition = adaptor.getCondition();
3831 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(
3832 op, llvmCondition, adaptor.getTrueValue(), adaptor.getFalseValue());
3834 return mlir::success();
3838 mlir::DataLayout &dataLayout) {
3839 converter.addConversion([&](cir::PointerType type) -> mlir::Type {
3840 mlir::ptr::MemorySpaceAttrInterface addrSpaceAttr = type.getAddrSpace();
3841 unsigned numericAS = 0;
3843 if (
auto targetAsAttr =
3844 mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
3846 numericAS = targetAsAttr.getValue();
3847 return mlir::LLVM::LLVMPointerType::get(type.getContext(), numericAS);
3849 converter.addConversion([&](cir::VPtrType type) -> mlir::Type {
3851 return mlir::LLVM::LLVMPointerType::get(type.getContext());
3853 converter.addConversion([&](cir::ArrayType type) -> mlir::Type {
3860 return mlir::LLVM::LLVMArrayType::get(ty, type.getSize());
3862 converter.addConversion([&](cir::VectorType type) -> mlir::Type {
3866 if (
auto intTy = mlir::dyn_cast<cir::IntType>(type.getElementType());
3867 intTy && intTy.isBitInt())
3869 const mlir::Type ty = converter.convertType(type.getElementType());
3870 return mlir::VectorType::get(type.getSize(), ty, {type.getIsScalable()});
3872 converter.addConversion([&](cir::BoolType type) -> mlir::Type {
3873 return mlir::IntegerType::get(type.getContext(), 1,
3874 mlir::IntegerType::Signless);
3876 converter.addConversion([&](cir::IntType type) -> mlir::Type {
3878 return mlir::IntegerType::get(type.getContext(), type.getWidth());
3880 converter.addConversion([&](cir::SingleType type) -> mlir::Type {
3881 return mlir::Float32Type::get(type.getContext());
3883 converter.addConversion([&](cir::DoubleType type) -> mlir::Type {
3884 return mlir::Float64Type::get(type.getContext());
3886 converter.addConversion([&](cir::FP80Type type) -> mlir::Type {
3887 return mlir::Float80Type::get(type.getContext());
3889 converter.addConversion([&](cir::FP128Type type) -> mlir::Type {
3890 return mlir::Float128Type::get(type.getContext());
3892 converter.addConversion([&](cir::LongDoubleType type) -> mlir::Type {
3893 return converter.convertType(type.getUnderlying());
3895 converter.addConversion([&](cir::FP16Type type) -> mlir::Type {
3896 return mlir::Float16Type::get(type.getContext());
3898 converter.addConversion([&](cir::BF16Type type) -> mlir::Type {
3899 return mlir::BFloat16Type::get(type.getContext());
3901 converter.addConversion([&](cir::ComplexType type) -> mlir::Type {
3904 mlir::Type elementTy = converter.convertType(type.getElementType());
3905 mlir::Type structFields[2] = {elementTy, elementTy};
3906 return mlir::LLVM::LLVMStructType::getLiteral(type.getContext(),
3909 converter.addConversion([&](cir::FuncType type) -> std::optional<mlir::Type> {
3910 auto result = converter.convertType(type.getReturnType());
3912 arguments.reserve(type.getNumInputs());
3913 if (converter.convertTypes(type.getInputs(), arguments).failed())
3914 return std::nullopt;
3915 auto varArg = type.isVarArg();
3916 return mlir::LLVM::LLVMFunctionType::get(result, arguments, varArg);
3918 converter.addConversion([&](cir::StructType type) -> mlir::Type {
3920 for (mlir::Type ty : type.getMembers()) {
3927 llvmMembers.push_back(memberTy);
3930 mlir::LLVM::LLVMStructType llvmStruct;
3931 if (type.getName()) {
3932 llvmStruct = mlir::LLVM::LLVMStructType::getIdentified(
3933 type.getContext(), type.getPrefixedName());
3934 if (llvmStruct.setBody(llvmMembers, type.getPacked()).failed())
3935 llvm_unreachable(
"Failed to set body of record");
3937 llvmStruct = mlir::LLVM::LLVMStructType::getLiteral(
3938 type.getContext(), llvmMembers, type.getPacked());
3943 converter.addConversion([&](cir::UnionType type) -> mlir::Type {
3945 if (!type.getMembers().empty())
3946 if (
auto storage = type.getUnionStorageType(dataLayout)) {
3947 mlir::Type storageTy =
3951 llvmMembers.push_back(storageTy);
3953 if (mlir::Type pad = type.getPadding()) {
3957 llvmMembers.push_back(padTy);
3960 mlir::LLVM::LLVMStructType llvmStruct;
3961 if (type.getName()) {
3962 llvmStruct = mlir::LLVM::LLVMStructType::getIdentified(
3963 type.getContext(), type.getPrefixedName());
3964 if (llvmStruct.setBody(llvmMembers, type.getPacked()).failed())
3965 llvm_unreachable(
"Failed to set body of record");
3967 llvmStruct = mlir::LLVM::LLVMStructType::getLiteral(
3968 type.getContext(), llvmMembers, type.getPacked());
3972 converter.addConversion([&](cir::VoidType type) -> mlir::Type {
3973 return mlir::LLVM::LLVMVoidType::get(type.getContext());
3978 mlir::ModuleOp module, StringRef globalXtorName, StringRef llvmXtorName,
3979 llvm::function_ref<std::pair<StringRef, int>(mlir::Attribute)> createXtor) {
3981 for (
const mlir::NamedAttribute namedAttr : module->getAttrs()) {
3982 if (namedAttr.getName() == globalXtorName) {
3983 for (
auto attr : mlir::cast<mlir::ArrayAttr>(namedAttr.getValue()))
3984 globalXtors.emplace_back(createXtor(attr));
3989 if (globalXtors.empty())
3992 mlir::OpBuilder builder(module.getContext());
3993 builder.setInsertionPointToEnd(&module.getBodyRegion().back());
3997 auto ctorPFTy = mlir::LLVM::LLVMPointerType::get(builder.getContext());
3999 ctorStructFields.push_back(builder.getI32Type());
4000 ctorStructFields.push_back(ctorPFTy);
4001 ctorStructFields.push_back(ctorPFTy);
4003 auto ctorStructTy = mlir::LLVM::LLVMStructType::getLiteral(
4004 builder.getContext(), ctorStructFields);
4005 auto ctorStructArrayTy =
4006 mlir::LLVM::LLVMArrayType::get(ctorStructTy, globalXtors.size());
4008 mlir::Location loc =
module.getLoc();
4009 auto newGlobalOp = mlir::LLVM::GlobalOp::create(
4010 builder, loc, ctorStructArrayTy,
false,
4011 mlir::LLVM::Linkage::Appending, llvmXtorName, mlir::Attribute());
4013 builder.createBlock(&newGlobalOp.getRegion());
4014 builder.setInsertionPointToEnd(newGlobalOp.getInitializerBlock());
4016 mlir::Value result =
4017 mlir::LLVM::UndefOp::create(builder, loc, ctorStructArrayTy);
4019 for (
auto [index, fn] : llvm::enumerate(globalXtors)) {
4020 mlir::Value structInit =
4021 mlir::LLVM::UndefOp::create(builder, loc, ctorStructTy);
4022 mlir::Value initPriority = mlir::LLVM::ConstantOp::create(
4023 builder, loc, ctorStructFields[0], fn.second);
4024 mlir::Value initFuncAddr = mlir::LLVM::AddressOfOp::create(
4025 builder, loc, ctorStructFields[1], fn.first);
4026 mlir::Value initAssociate =
4027 mlir::LLVM::ZeroOp::create(builder, loc, ctorStructFields[2]);
4030 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
4031 initPriority, zero);
4032 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
4035 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
4037 result = mlir::LLVM::InsertValueOp::create(builder, loc, result, structInit,
4041 mlir::LLVM::ReturnOp::create(builder, loc, result);
4044mlir::LogicalResult CIRToLLVMObjSizeOpLowering::matchAndRewrite(
4045 cir::ObjSizeOp op, OpAdaptor adaptor,
4046 mlir::ConversionPatternRewriter &rewriter)
const {
4047 mlir::Type llvmResTy = getTypeConverter()->convertType(op.getType());
4048 mlir::Location loc = op->getLoc();
4050 mlir::IntegerType i1Ty = rewriter.getI1Type();
4052 auto i1Val = [&rewriter, &loc, &i1Ty](
bool val) {
4053 return mlir::LLVM::ConstantOp::create(rewriter, loc, i1Ty, val);
4060 i1Val(op.getNullunknown()),
4061 i1Val(op.getDynamic()),
4064 return mlir::LogicalResult::success();
4072constexpr StringRef llvmMetadataSectionName =
"llvm.metadata";
4077getOrCreateAnnotationStringGlobal(mlir::OpBuilder &builder, mlir::Location loc,
4078 mlir::ModuleOp module, llvm::StringRef str,
4079 llvm::StringMap<mlir::LLVM::GlobalOp> &cache,
4081 auto it = cache.find(str);
4082 if (it != cache.end())
4085 auto i8Ty = mlir::IntegerType::get(module.getContext(), 8);
4086 auto arrayTy = mlir::LLVM::LLVMArrayType::get(i8Ty, str.size() + 1);
4087 std::string
name =
".str";
4089 name +=
"." + std::to_string(cache.size());
4090 name +=
".annotation";
4094 mlir::LLVM::GlobalOp strGlobal = mlir::LLVM::GlobalOp::create(
4095 builder, loc, arrayTy,
true, mlir::LLVM::Linkage::Private,
4096 name, mlir::StringAttr::get(module.getContext(), std::string(str) +
'\0'),
4099 strGlobal.setSection(llvmMetadataSectionName);
4100 strGlobal.setUnnamedAddr(mlir::LLVM::UnnamedAddr::Global);
4101 strGlobal.setDsoLocal(
true);
4102 cache[str] = strGlobal;
4108mlir::LLVM::GlobalOp getOrCreateAnnotationArgsVar(
4109 mlir::OpBuilder &builder, mlir::Location loc, mlir::ModuleOp module,
4110 mlir::ArrayAttr argsAttr,
4111 llvm::StringMap<mlir::LLVM::GlobalOp> &argStringCache,
4112 llvm::MapVector<mlir::ArrayAttr, mlir::LLVM::GlobalOp> &argsCache) {
4113 auto it = argsCache.find(argsAttr);
4114 if (it != argsCache.end())
4117 auto ptrTy = mlir::LLVM::LLVMPointerType::get(builder.getContext());
4119 llvm::SmallVector<mlir::Type> fieldTypes;
4120 for (mlir::Attribute arg : argsAttr) {
4121 if (mlir::isa<mlir::StringAttr>(arg))
4122 fieldTypes.push_back(ptrTy);
4123 else if (
auto intAttr = mlir::dyn_cast<mlir::IntegerAttr>(arg))
4124 fieldTypes.push_back(intAttr.getType());
4126 llvm_unreachable(
"Unsupported annotation arg type");
4130 mlir::LLVM::LLVMStructType::getLiteral(builder.getContext(), fieldTypes);
4131 std::string
name =
".args";
4132 if (!argsCache.empty())
4133 name +=
"." + std::to_string(argsCache.size());
4134 name +=
".annotation";
4136 mlir::LLVM::GlobalOp argsGlobal = mlir::LLVM::GlobalOp::create(
4137 builder, loc, structTy,
true, mlir::LLVM::Linkage::Private,
4138 name, mlir::Attribute());
4139 argsGlobal.setSection(llvmMetadataSectionName);
4140 argsGlobal.setUnnamedAddr(mlir::LLVM::UnnamedAddr::Global);
4141 argsGlobal.setDsoLocal(
true);
4144 argsGlobal.getRegion().push_back(
new mlir::Block());
4145 mlir::OpBuilder initBuilder(module.getContext());
4146 initBuilder.setInsertionPointToEnd(argsGlobal.getInitializerBlock());
4148 mlir::Value structInit =
4149 mlir::LLVM::UndefOp::create(initBuilder, loc, structTy);
4150 for (
auto [idx, arg] : llvm::enumerate(argsAttr)) {
4151 if (
auto strArg = mlir::dyn_cast<mlir::StringAttr>(arg)) {
4152 mlir::LLVM::GlobalOp strGlobal = getOrCreateAnnotationStringGlobal(
4153 builder, loc, module, strArg.getValue(), argStringCache,
4155 mlir::LLVM::AddressOfOp strAddr = mlir::LLVM::AddressOfOp::create(
4156 initBuilder, loc, ptrTy, strGlobal.getSymName());
4157 structInit = mlir::LLVM::InsertValueOp::create(initBuilder, loc,
4158 structInit, strAddr, idx);
4159 }
else if (
auto intArg = mlir::dyn_cast<mlir::IntegerAttr>(arg)) {
4160 mlir::LLVM::ConstantOp intConst = mlir::LLVM::ConstantOp::create(
4161 initBuilder, loc, intArg.getType(), intArg.getValue());
4162 structInit = mlir::LLVM::InsertValueOp::create(initBuilder, loc,
4163 structInit, intConst, idx);
4165 llvm_unreachable(
"Unsupported annotation arg type");
4168 mlir::LLVM::ReturnOp::create(initBuilder, loc, structInit);
4170 argsCache[argsAttr] = argsGlobal;
4176std::pair<llvm::StringRef, unsigned> extractFileLine(mlir::Location loc) {
4177 mlir::Location resolved = loc;
4178 if (
auto fused = mlir::dyn_cast<mlir::FusedLoc>(resolved)) {
4179 if (!fused.getLocations().empty())
4180 resolved = fused.getLocations()[0];
4182 if (
auto fl = mlir::dyn_cast<mlir::FileLineColLoc>(resolved))
4183 return {fl.getFilename().getValue(), fl.getLine()};
4189 auto handleArray = [&](mlir::StringAttr symName, mlir::ArrayAttr arr,
4190 mlir::Location loc) {
4193 for (mlir::Attribute a : arr)
4194 if (
auto annot = mlir::dyn_cast<cir::AnnotationAttr>(a))
4195 collectedAnnotations.emplace_back(symName, annot, loc);
4200 module.walk([&](cir::GlobalOp op) {
4201 handleArray(op.getSymNameAttr(), op.getAnnotationsAttr(), op.getLoc());
4203 module.walk([&](cir::FuncOp op) {
4204 handleArray(op.getSymNameAttr(), op.getAnnotationsAttr(), op.getLoc());
4209 if (collectedAnnotations.empty())
4212 mlir::MLIRContext *ctx =
module.getContext();
4213 mlir::OpBuilder builder(ctx);
4214 builder.setInsertionPointToEnd(&module.getBodyRegion().back());
4216 auto ptrTy = mlir::LLVM::LLVMPointerType::get(ctx);
4217 auto i32Ty = builder.getI32Type();
4220 auto entryTy = mlir::LLVM::LLVMStructType::getLiteral(
4221 ctx, {ptrTy, ptrTy, ptrTy, i32Ty, ptrTy});
4223 mlir::LLVM::LLVMArrayType::get(entryTy, collectedAnnotations.size());
4225 mlir::Location moduleLoc =
module.getLoc();
4226 auto annotationsGlobal = mlir::LLVM::GlobalOp::create(
4227 builder, moduleLoc, arrayTy,
false,
4228 mlir::LLVM::Linkage::Appending,
"llvm.global.annotations",
4230 annotationsGlobal.setSection(llvmMetadataSectionName);
4234 mlir::OpBuilder constsBuilder(ctx);
4235 constsBuilder.setInsertionPoint(annotationsGlobal);
4237 llvm::StringMap<mlir::LLVM::GlobalOp> stringCache;
4238 llvm::StringMap<mlir::LLVM::GlobalOp> argStringCache;
4239 llvm::MapVector<mlir::ArrayAttr, mlir::LLVM::GlobalOp> argsCache;
4242 annotationsGlobal.getRegion().push_back(
new mlir::Block());
4243 mlir::OpBuilder initBuilder(ctx);
4244 initBuilder.setInsertionPointToEnd(annotationsGlobal.getInitializerBlock());
4246 mlir::Value arrayVal =
4247 mlir::LLVM::UndefOp::create(initBuilder, moduleLoc, arrayTy);
4249 for (
auto [idx, entry] : llvm::enumerate(collectedAnnotations)) {
4250 mlir::Value entryVal =
4251 mlir::LLVM::UndefOp::create(initBuilder, moduleLoc, entryTy);
4256 mlir::LLVM::AddressOfOp symAddr = mlir::LLVM::AddressOfOp::create(
4257 initBuilder, moduleLoc, ptrTy, entry.symName.getValue());
4258 entryVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
4259 entryVal, symAddr, zero);
4262 mlir::LLVM::GlobalOp nameGlobal = getOrCreateAnnotationStringGlobal(
4263 constsBuilder, moduleLoc, module, entry.annotation.getName().getValue(),
4264 stringCache,
false);
4265 mlir::LLVM::AddressOfOp nameAddr = mlir::LLVM::AddressOfOp::create(
4266 initBuilder, moduleLoc, ptrTy, nameGlobal.getSymName());
4267 entryVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
4268 entryVal, nameAddr, 1);
4271 auto [filename, line] = extractFileLine(entry.loc);
4272 mlir::LLVM::GlobalOp fileGlobal = getOrCreateAnnotationStringGlobal(
4273 constsBuilder, moduleLoc, module, filename, stringCache,
4275 mlir::LLVM::AddressOfOp fileAddr = mlir::LLVM::AddressOfOp::create(
4276 initBuilder, moduleLoc, ptrTy, fileGlobal.getSymName());
4277 entryVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
4278 entryVal, fileAddr, 2);
4279 mlir::LLVM::ConstantOp lineConst =
4280 mlir::LLVM::ConstantOp::create(initBuilder, moduleLoc, i32Ty, line);
4281 entryVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
4282 entryVal, lineConst, 3);
4285 mlir::ArrayAttr args = entry.annotation.getArgs();
4286 mlir::Value argsField;
4287 if (!args || args.empty()) {
4288 argsField = mlir::LLVM::ZeroOp::create(initBuilder, moduleLoc, ptrTy);
4290 mlir::LLVM::GlobalOp argsGlobal = getOrCreateAnnotationArgsVar(
4291 constsBuilder, moduleLoc, module, args, argStringCache, argsCache);
4292 argsField = mlir::LLVM::AddressOfOp::create(initBuilder, moduleLoc, ptrTy,
4293 argsGlobal.getSymName());
4295 entryVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
4296 entryVal, argsField, 4);
4298 arrayVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
4299 arrayVal, entryVal, idx);
4302 mlir::LLVM::ReturnOp::create(initBuilder, moduleLoc, arrayVal);
4308 mlir::ModuleOp module = getOperation();
4309 mlir::OpBuilder opBuilder(module.getContext());
4310 for (
auto &[blockAddOp, blockInfo] :
4312 mlir::LLVM::BlockTagOp resolvedLabel =
4314 assert(resolvedLabel &&
"expected BlockTagOp to already be emitted");
4315 mlir::FlatSymbolRefAttr fnSym = blockInfo.getFunc();
4316 auto blkAddTag = mlir::LLVM::BlockAddressAttr::get(
4317 opBuilder.getContext(), fnSym, resolvedLabel.getTagAttr());
4318 blockAddOp.setBlockAddrAttr(blkAddTag);
4325 if (mlir::Attribute tripleAttr =
4326 module->getAttr(cir::CIRDialect::getTripleAttrName()))
4327 module->setAttr(mlir::LLVM::LLVMDialect::getTargetTripleAttrName(),
4330 if (mlir::Attribute asmAttr =
4331 module->getAttr(cir::CIRDialect::getModuleLevelAsmAttrName()))
4332 module->setAttr(mlir::LLVM::LLVMDialect::getModuleLevelAsmAttrName(),
4337 llvm::TimeTraceScope scope(
"Convert CIR to LLVM Pass");
4339 mlir::ModuleOp module = getOperation();
4340 mlir::DataLayout dl(module);
4341 mlir::LLVMTypeConverter converter(&getContext());
4351 mlir::SymbolTableCollection symbolTables;
4352 mlir::RewritePatternSet patterns(&getContext());
4353 patterns.add<CIRToLLVMBlockAddressOpLowering, CIRToLLVMGlobalOpLowering,
4354 CIRToLLVMLabelOpLowering>(converter, patterns.getContext(), dl,
4355 symbolTables, blockInfoAddr);
4358#define GET_LLVM_LOWERING_PATTERNS_LIST
4359#include "clang/CIR/Dialect/IR/CIRLowering.inc"
4360#undef GET_LLVM_LOWERING_PATTERNS_LIST
4361 >(converter, patterns.getContext(), dl, symbolTables);
4369 mlir::ConversionTarget target(getContext());
4370 target.addLegalOp<mlir::ModuleOp>();
4371 target.addLegalDialect<mlir::LLVM::LLVMDialect>();
4372 mlir::configureOpenMPToLLVMConversionLegality(target, converter);
4373 target.addLegalDialect<mlir::omp::OpenMPDialect>();
4374 mlir::populateOpenMPToLLVMConversionPatterns(converter, patterns);
4375 target.addIllegalDialect<mlir::BuiltinDialect, cir::CIRDialect,
4376 mlir::func::FuncDialect>();
4379 ops.push_back(module);
4382 if (failed(applyPartialConversion(ops, target, std::move(patterns))))
4383 signalPassFailure();
4387 if (
auto dlSpec = mlir::dyn_cast_or_null<mlir::DataLayoutSpecAttr>(
4388 module->getAttr(mlir::DLTIDialect::kDataLayoutAttrName))) {
4390 for (mlir::DataLayoutEntryInterface entry : dlSpec.getEntries()) {
4391 if (entry.isTypeEntry() &&
4392 mlir::isa<cir::PointerType>(mlir::cast<mlir::Type>(entry.getKey())))
4394 kept.push_back(entry);
4396 module->setAttr(mlir::DLTIDialect::kDataLayoutAttrName,
4397 mlir::DataLayoutSpecAttr::get(module.getContext(), kept));
4402 "llvm.global_ctors", [](mlir::Attribute
attr) {
4403 auto ctorAttr = mlir::cast<cir::GlobalCtorAttr>(
attr);
4404 return std::make_pair(ctorAttr.getName(),
4405 ctorAttr.getPriority());
4409 "llvm.global_dtors", [](mlir::Attribute
attr) {
4410 auto dtorAttr = mlir::cast<cir::GlobalDtorAttr>(
attr);
4411 return std::make_pair(dtorAttr.getName(),
4412 dtorAttr.getPriority());
4420mlir::LogicalResult CIRToLLVMBrOpLowering::matchAndRewrite(
4421 cir::BrOp op, OpAdaptor adaptor,
4422 mlir::ConversionPatternRewriter &rewriter)
const {
4423 rewriter.replaceOpWithNewOp<mlir::LLVM::BrOp>(op, adaptor.getOperands(),
4425 return mlir::LogicalResult::success();
4428mlir::LogicalResult CIRToLLVMGetMemberOpLowering::matchAndRewrite(
4429 cir::GetMemberOp op, OpAdaptor adaptor,
4430 mlir::ConversionPatternRewriter &rewriter)
const {
4431 mlir::Type llResTy = getTypeConverter()->convertType(op.getType());
4432 mlir::Type pointee = op.getAddrTy().getPointee();
4434 if (mlir::isa<cir::UnionType>(pointee)) {
4437 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(op, llResTy,
4439 return mlir::success();
4442 auto structTy = mlir::cast<cir::StructType>(pointee);
4446 const mlir::Type elementTy = getTypeConverter()->convertType(structTy);
4451 mlir::LLVM::GEPNoWrapFlags flags =
4452 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
4453 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
4454 op, llResTy, elementTy, adaptor.getAddr(), offset, flags);
4455 return mlir::success();
4458mlir::LogicalResult CIRToLLVMExtractMemberOpLowering::matchAndRewrite(
4459 cir::ExtractMemberOp op, OpAdaptor adaptor,
4460 mlir::ConversionPatternRewriter &rewriter)
const {
4461 std::int64_t indices[1] = {
static_cast<std::int64_t
>(op.getIndex())};
4463 if (mlir::isa<cir::UnionType>(op.getRecord().getType())) {
4464 op.emitError(
"cir.extract_member cannot extract member from a union");
4465 return mlir::failure();
4468 rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractValueOp>(
4469 op, adaptor.getRecord(), indices);
4470 return mlir::success();
4473mlir::LogicalResult CIRToLLVMInsertMemberOpLowering::matchAndRewrite(
4474 cir::InsertMemberOp op, OpAdaptor adaptor,
4475 mlir::ConversionPatternRewriter &rewriter)
const {
4476 std::int64_t indecies[1] = {
static_cast<std::int64_t
>(op.getIndex())};
4478 if (mlir::isa<cir::UnionType>(op.getRecord().getType())) {
4479 op.emitError(
"cir.update_member cannot update member of a union");
4480 return mlir::failure();
4483 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
4484 op, adaptor.getRecord(), adaptor.getValue(), indecies);
4485 return mlir::success();
4489 mlir::SymbolTableCollection &symbolTables,
4490 mlir::Operation *srcOp, llvm::StringRef fnName,
4492 mlir::ArrayAttr argAttrs =
nullptr,
4493 mlir::ArrayAttr resAttrs =
nullptr) {
4494 mlir::ModuleOp modOp = srcOp->getParentOfType<mlir::ModuleOp>();
4495 mlir::Operation *sourceSymbol = symbolTables.lookupSymbolIn(
4496 modOp, mlir::StringAttr::get(fnTy.getContext(), fnName));
4497 if (!sourceSymbol) {
4498 mlir::OpBuilder::InsertionGuard guard(rewriter);
4499 auto enclosingFnOp = srcOp->getParentOfType<mlir::LLVM::LLVMFuncOp>();
4500 rewriter.setInsertionPoint(enclosingFnOp);
4502 mlir::LLVM::LLVMFuncOp::create(rewriter, srcOp->getLoc(), fnName, fnTy);
4504 fn.setArgAttrsAttr(argAttrs);
4506 fn.setResAttrsAttr(resAttrs);
4508 symbolTables.getSymbolTable(fn->getParentOp()).insert(fn);
4512mlir::LogicalResult CIRToLLVMThrowOpLowering::matchAndRewrite(
4513 cir::ThrowOp op, OpAdaptor adaptor,
4514 mlir::ConversionPatternRewriter &rewriter)
const {
4515 mlir::Location loc = op.getLoc();
4516 auto voidTy = mlir::LLVM::LLVMVoidType::get(getContext());
4518 if (op.rethrows()) {
4519 auto funcTy = mlir::LLVM::LLVMFunctionType::get(voidTy, {});
4522 const llvm::StringRef functionName =
"__cxa_rethrow";
4523 createLLVMFuncOpIfNotExist(rewriter, symbolTables, op, functionName,
4526 auto cxaRethrow = mlir::LLVM::CallOp::create(
4527 rewriter, loc, mlir::TypeRange{}, functionName);
4529 rewriter.replaceOp(op, cxaRethrow);
4530 return mlir::success();
4533 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4534 auto fnTy = mlir::LLVM::LLVMFunctionType::get(
4535 voidTy, {llvmPtrTy, llvmPtrTy, llvmPtrTy});
4538 const llvm::StringRef fnName =
"__cxa_throw";
4541 mlir::Value typeInfo = mlir::LLVM::AddressOfOp::create(
4542 rewriter, loc, mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
4543 adaptor.getTypeInfoAttr());
4547 dtor = mlir::LLVM::AddressOfOp::create(rewriter, loc, llvmPtrTy,
4548 adaptor.getDtorAttr());
4550 dtor = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmPtrTy);
4553 auto cxaThrowCall = mlir::LLVM::CallOp::create(
4554 rewriter, loc, mlir::TypeRange{}, fnName,
4555 mlir::ValueRange{adaptor.getExceptionPtr(), typeInfo, dtor});
4557 rewriter.replaceOp(op, cxaThrowCall);
4558 return mlir::success();
4561mlir::LogicalResult CIRToLLVMAllocExceptionOpLowering::matchAndRewrite(
4562 cir::AllocExceptionOp op, OpAdaptor adaptor,
4563 mlir::ConversionPatternRewriter &rewriter)
const {
4565 StringRef fnName =
"__cxa_allocate_exception";
4566 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4567 auto int64Ty = mlir::IntegerType::get(rewriter.getContext(), 64);
4568 auto fnTy = mlir::LLVM::LLVMFunctionType::get(llvmPtrTy, {int64Ty});
4571 auto exceptionSize = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
4572 adaptor.getSizeAttr());
4574 auto allocaExceptionCall = mlir::LLVM::CallOp::create(
4575 rewriter, op.getLoc(), mlir::TypeRange{llvmPtrTy}, fnName,
4576 mlir::ValueRange{exceptionSize});
4578 rewriter.replaceOp(op, allocaExceptionCall);
4579 return mlir::success();
4582static mlir::LLVM::LLVMStructType
4585 mlir::MLIRContext *ctx = rewriter.getContext();
4586 auto llvmPtr = mlir::LLVM::LLVMPointerType::get(ctx);
4588 return mlir::LLVM::LLVMStructType::getLiteral(ctx, structFields);
4591mlir::LogicalResult CIRToLLVMEhInflightOpLowering::matchAndRewrite(
4592 cir::EhInflightOp op, OpAdaptor adaptor,
4593 mlir::ConversionPatternRewriter &rewriter)
const {
4594 auto llvmFn = op->getParentOfType<mlir::LLVM::LLVMFuncOp>();
4595 assert(llvmFn &&
"expected LLVM function parent");
4596 mlir::Block *entryBlock = &llvmFn.getRegion().front();
4597 assert(entryBlock->isEntryBlock());
4599 mlir::ArrayAttr catchListAttr = op.getCatchTypeListAttr();
4600 mlir::SmallVector<mlir::Value> catchSymAddrs;
4602 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4603 mlir::Location loc = op.getLoc();
4608 if (catchListAttr) {
4611 for (mlir::Attribute catchAttr : catchListAttr) {
4612 auto symAttr = cast<mlir::FlatSymbolRefAttr>(catchAttr);
4615 mlir::OpBuilder::InsertionGuard guard(rewriter);
4616 rewriter.setInsertionPointToStart(entryBlock);
4617 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
4618 rewriter, loc, llvmPtrTy, symAttr.getValue());
4619 catchSymAddrs.push_back(addrOp);
4626 if (op.getCatchAll() || (!catchListAttr && !op.getCleanup())) {
4627 mlir::OpBuilder::InsertionGuard guard(rewriter);
4628 rewriter.setInsertionPointToStart(entryBlock);
4629 mlir::Value nullOp = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmPtrTy);
4630 catchSymAddrs.push_back(nullOp);
4635 mlir::LLVM::LLVMStructType llvmLandingPadStructTy =
4637 auto landingPadOp = mlir::LLVM::LandingpadOp::create(
4638 rewriter, loc, llvmLandingPadStructTy, catchSymAddrs);
4643 if (op.getCleanup() && !op.getCatchAll())
4644 landingPadOp.setCleanup(
true);
4647 mlir::LLVM::ExtractValueOp::create(rewriter, loc, landingPadOp, 0);
4648 mlir::Value selector =
4649 mlir::LLVM::ExtractValueOp::create(rewriter, loc, landingPadOp, 1);
4650 rewriter.replaceOp(op, mlir::ValueRange{slot, selector});
4652 return mlir::success();
4655mlir::LogicalResult CIRToLLVMResumeFlatOpLowering::matchAndRewrite(
4656 cir::ResumeFlatOp op, OpAdaptor adaptor,
4657 mlir::ConversionPatternRewriter &rewriter)
const {
4662 mlir::Value poison = mlir::LLVM::PoisonOp::create(rewriter, op.getLoc(),
4663 llvmLandingPadStructTy);
4666 mlir::Value slot = mlir::LLVM::InsertValueOp::create(
4667 rewriter, op.getLoc(), poison, adaptor.getExceptionPtr(), slotIdx);
4670 mlir::Value selector = mlir::LLVM::InsertValueOp::create(
4671 rewriter, op.getLoc(), slot, adaptor.getTypeId(), selectorIdx);
4673 rewriter.replaceOpWithNewOp<mlir::LLVM::ResumeOp>(op, selector);
4674 return mlir::success();
4677mlir::LogicalResult CIRToLLVMEhTypeIdOpLowering::matchAndRewrite(
4678 cir::EhTypeIdOp op, OpAdaptor adaptor,
4679 mlir::ConversionPatternRewriter &rewriter)
const {
4680 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
4681 rewriter, op.getLoc(),
4682 mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
4683 op.getTypeSymAttr());
4684 rewriter.replaceOpWithNewOp<mlir::LLVM::EhTypeidForOp>(
4685 op, rewriter.getI32Type(), addrOp);
4686 return mlir::success();
4689mlir::LogicalResult CIRToLLVMEhSetjmpOpLowering::matchAndRewrite(
4690 cir::EhSetjmpOp op, OpAdaptor adaptor,
4691 mlir::ConversionPatternRewriter &rewriter)
const {
4692 mlir::Type returnType = typeConverter->convertType(op.getType());
4693 mlir::LLVM::CallIntrinsicOp newOp =
4695 returnType, adaptor.getEnv());
4696 rewriter.replaceOp(op, newOp);
4697 return mlir::success();
4700mlir::LogicalResult CIRToLLVMEhLongjmpOpLowering::matchAndRewrite(
4701 cir::EhLongjmpOp op, OpAdaptor adaptor,
4702 mlir::ConversionPatternRewriter &rewriter)
const {
4704 {}, adaptor.getOperands());
4705 return mlir::success();
4708mlir::LogicalResult CIRToLLVMTrapOpLowering::matchAndRewrite(
4709 cir::TrapOp op, OpAdaptor adaptor,
4710 mlir::ConversionPatternRewriter &rewriter)
const {
4711 mlir::Location loc = op->getLoc();
4712 rewriter.eraseOp(op);
4714 mlir::LLVM::Trap::create(rewriter, loc);
4719 mlir::LLVM::UnreachableOp::create(rewriter, loc);
4721 return mlir::success();
4726 mlir::ConversionPatternRewriter &rewriter,
4727 mlir::SymbolTableCollection &symbolTables,
4728 const mlir::TypeConverter *converter,
4729 mlir::FlatSymbolRefAttr nameAttr, mlir::Type &eltType) {
4730 auto module = op->getParentOfType<mlir::ModuleOp>();
4731 mlir::Operation *symbol = symbolTables.lookupSymbolIn(module, nameAttr);
4732 if (
auto llvmSymbol = mlir::dyn_cast<mlir::LLVM::GlobalOp>(symbol)) {
4733 eltType = llvmSymbol.getType();
4734 }
else if (
auto cirSymbol = mlir::dyn_cast<cir::GlobalOp>(symbol)) {
4735 eltType = converter->convertType(cirSymbol.getSymType());
4737 op->emitError() <<
"unexpected symbol type for " << symbol;
4741 return mlir::LLVM::AddressOfOp::create(
4742 rewriter, op->getLoc(),
4743 mlir::LLVM::LLVMPointerType::get(op->getContext()), nameAttr.getValue());
4746mlir::LogicalResult CIRToLLVMVTableAddrPointOpLowering::matchAndRewrite(
4747 cir::VTableAddrPointOp op, OpAdaptor adaptor,
4748 mlir::ConversionPatternRewriter &rewriter)
const {
4749 const mlir::TypeConverter *converter = getTypeConverter();
4750 mlir::Type targetType = converter->convertType(op.getType());
4753 mlir::Value symAddr = getValueForVTableSymbol(
4754 op, rewriter, symbolTables, converter, op.getNameAttr(), eltType);
4756 return op.emitError() <<
"Unable to get value for vtable symbol";
4759 0, op.getAddressPointAttr().getIndex(),
4760 op.getAddressPointAttr().getOffset()};
4762 assert(eltType &&
"Shouldn't ever be missing an eltType here");
4763 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
4764 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
4765 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, targetType, eltType,
4766 symAddr, offsets, inboundsNuw);
4767 return mlir::success();
4770mlir::LogicalResult CIRToLLVMVTableGetVPtrOpLowering::matchAndRewrite(
4771 cir::VTableGetVPtrOp op, OpAdaptor adaptor,
4772 mlir::ConversionPatternRewriter &rewriter)
const {
4776 mlir::Value srcVal = adaptor.getSrc();
4777 rewriter.replaceOp(op, srcVal);
4778 return mlir::success();
4781mlir::LogicalResult CIRToLLVMVTableGetVirtualFnAddrOpLowering::matchAndRewrite(
4782 cir::VTableGetVirtualFnAddrOp op, OpAdaptor adaptor,
4783 mlir::ConversionPatternRewriter &rewriter)
const {
4784 mlir::Type targetType = getTypeConverter()->convertType(op.getType());
4785 auto eltType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4788 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
4789 op, targetType, eltType, adaptor.getVptr(), offsets,
4790 mlir::LLVM::GEPNoWrapFlags::inbounds);
4791 return mlir::success();
4794mlir::LogicalResult CIRToLLVMVTTAddrPointOpLowering::matchAndRewrite(
4795 cir::VTTAddrPointOp op, OpAdaptor adaptor,
4796 mlir::ConversionPatternRewriter &rewriter)
const {
4797 const mlir::Type resultType = getTypeConverter()->convertType(op.getType());
4800 mlir::Value llvmAddr = adaptor.getSymAddr();
4802 if (op.getSymAddr()) {
4803 if (op.getOffset() == 0) {
4804 rewriter.replaceOp(op, {llvmAddr});
4805 return mlir::success();
4808 offsets.push_back(adaptor.getOffset());
4809 eltType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4813 op.getNameAttr(), eltType);
4814 assert(eltType &&
"Shouldn't ever be missing an eltType here");
4815 offsets.push_back(0);
4816 offsets.push_back(adaptor.getOffset());
4818 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
4819 op, resultType, eltType, llvmAddr, offsets,
4820 mlir::LLVM::GEPNoWrapFlags::inbounds);
4821 return mlir::success();
4824mlir::LogicalResult CIRToLLVMVecCreateOpLowering::matchAndRewrite(
4825 cir::VecCreateOp op, OpAdaptor adaptor,
4826 mlir::ConversionPatternRewriter &rewriter)
const {
4829 const cir::VectorType vecTy = op.getType();
4830 const mlir::Type llvmTy = typeConverter->convertType(vecTy);
4831 const mlir::Location loc = op.getLoc();
4832 mlir::Value result = mlir::LLVM::PoisonOp::create(rewriter, loc, llvmTy);
4833 assert(vecTy.getSize() == op.getElements().size() &&
4834 "cir.vec.create op count doesn't match vector type elements count");
4836 for (uint64_t i = 0; i < vecTy.getSize(); ++i) {
4837 const mlir::Value indexValue =
4838 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
4839 result = mlir::LLVM::InsertElementOp::create(
4840 rewriter, loc, result, adaptor.getElements()[i], indexValue);
4843 rewriter.replaceOp(op, result);
4844 return mlir::success();
4847mlir::LogicalResult CIRToLLVMVecExtractOpLowering::matchAndRewrite(
4848 cir::VecExtractOp op, OpAdaptor adaptor,
4849 mlir::ConversionPatternRewriter &rewriter)
const {
4850 rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractElementOp>(
4851 op, adaptor.getVec(), adaptor.getIndex());
4852 return mlir::success();
4855mlir::LogicalResult CIRToLLVMVecInsertOpLowering::matchAndRewrite(
4856 cir::VecInsertOp op, OpAdaptor adaptor,
4857 mlir::ConversionPatternRewriter &rewriter)
const {
4858 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertElementOp>(
4859 op, adaptor.getVec(), adaptor.getValue(), adaptor.getIndex());
4860 return mlir::success();
4863mlir::LogicalResult CIRToLLVMVecCmpOpLowering::matchAndRewrite(
4864 cir::VecCmpOp op, OpAdaptor adaptor,
4865 mlir::ConversionPatternRewriter &rewriter)
const {
4866 mlir::Type elementType = elementTypeIfVector(op.getLhs().getType());
4867 mlir::Value bitResult;
4868 if (
auto intType = mlir::dyn_cast<cir::IntType>(elementType)) {
4869 bitResult = mlir::LLVM::ICmpOp::create(
4870 rewriter, op.getLoc(),
4872 adaptor.getLhs(), adaptor.getRhs());
4873 }
else if (mlir::isa<cir::FPTypeInterface>(elementType)) {
4874 if (cir::FenvAttr fenv = op.getFenvAttr()) {
4875 auto i1VecTy = mlir::VectorType::get(op.getLhs().getType().getSize(),
4876 rewriter.getI1Type());
4878 adaptor.getLhs(), adaptor.getRhs(),
4879 op.getKind(), fenv, i1VecTy)
4882 bitResult = mlir::LLVM::FCmpOp::create(
4884 adaptor.getLhs(), adaptor.getRhs());
4887 return op.emitError() <<
"unsupported type for VecCmpOp: " << elementType;
4893 if (cast<cir::IntType>(op.getType().getElementType()).getWidth() > 1)
4894 rewriter.replaceOpWithNewOp<mlir::LLVM::SExtOp>(
4895 op, typeConverter->convertType(op.getType()), bitResult);
4897 rewriter.replaceOp(op, bitResult);
4898 return mlir::success();
4901mlir::LogicalResult CIRToLLVMVecSplatOpLowering::matchAndRewrite(
4902 cir::VecSplatOp op, OpAdaptor adaptor,
4903 mlir::ConversionPatternRewriter &rewriter)
const {
4909 cir::VectorType vecTy = op.getType();
4910 mlir::Type llvmTy = typeConverter->convertType(vecTy);
4911 mlir::Location loc = op.getLoc();
4912 mlir::Value poison = mlir::LLVM::PoisonOp::create(rewriter, loc, llvmTy);
4914 mlir::Value elementValue = adaptor.getValue();
4915 if (elementValue.getDefiningOp<mlir::LLVM::PoisonOp>()) {
4918 rewriter.replaceOp(op, poison);
4919 return mlir::success();
4922 if (
auto constValue = elementValue.getDefiningOp<mlir::LLVM::ConstantOp>()) {
4923 if (
auto intAttr = dyn_cast<mlir::IntegerAttr>(constValue.getValue())) {
4924 mlir::DenseIntElementsAttr denseVec = mlir::DenseIntElementsAttr::get(
4925 mlir::cast<mlir::ShapedType>(llvmTy), intAttr.getValue());
4926 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
4927 op, denseVec.getType(), denseVec);
4928 return mlir::success();
4931 if (
auto fpAttr = dyn_cast<mlir::FloatAttr>(constValue.getValue())) {
4932 mlir::DenseFPElementsAttr denseVec = mlir::DenseFPElementsAttr::get(
4933 mlir::cast<mlir::ShapedType>(llvmTy), fpAttr.getValue());
4934 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
4935 op, denseVec.getType(), denseVec);
4936 return mlir::success();
4940 mlir::Value indexValue =
4941 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), 0);
4942 mlir::Value oneElement = mlir::LLVM::InsertElementOp::create(
4943 rewriter, loc, poison, elementValue, indexValue);
4945 rewriter.replaceOpWithNewOp<mlir::LLVM::ShuffleVectorOp>(op, oneElement,
4946 poison, zeroValues);
4947 return mlir::success();
4950mlir::LogicalResult CIRToLLVMVecShuffleOpLowering::matchAndRewrite(
4951 cir::VecShuffleOp op, OpAdaptor adaptor,
4952 mlir::ConversionPatternRewriter &rewriter)
const {
4958 op.getIndices().begin(), op.getIndices().end(),
4959 std::back_inserter(indices), [](mlir::Attribute intAttr) {
4960 return mlir::cast<cir::IntAttr>(intAttr).getValue().getSExtValue();
4962 rewriter.replaceOpWithNewOp<mlir::LLVM::ShuffleVectorOp>(
4963 op, adaptor.getVec1(), adaptor.getVec2(), indices);
4964 return mlir::success();
4967mlir::LogicalResult CIRToLLVMVecShuffleDynamicOpLowering::matchAndRewrite(
4968 cir::VecShuffleDynamicOp op, OpAdaptor adaptor,
4969 mlir::ConversionPatternRewriter &rewriter)
const {
4981 mlir::Location loc = op.getLoc();
4982 mlir::Value input = adaptor.getVec();
4983 mlir::Type llvmIndexVecType =
4984 getTypeConverter()->convertType(op.getIndices().getType());
4985 mlir::Type llvmIndexType = getTypeConverter()->convertType(
4986 op.getIndices().getType().getElementType());
4987 uint64_t numElements = op.getVec().getType().getSize();
4989 uint64_t maskBits = llvm::NextPowerOf2(numElements - 1) - 1;
4990 mlir::Value maskValue = mlir::LLVM::ConstantOp::create(
4991 rewriter, loc, llvmIndexType,
4992 rewriter.getIntegerAttr(llvmIndexType, maskBits));
4993 mlir::Value maskVector =
4994 mlir::LLVM::UndefOp::create(rewriter, loc, llvmIndexVecType);
4996 for (uint64_t i = 0; i < numElements; ++i) {
4997 mlir::Value idxValue =
4998 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
4999 maskVector = mlir::LLVM::InsertElementOp::create(rewriter, loc, maskVector,
5000 maskValue, idxValue);
5003 mlir::Value maskedIndices = mlir::LLVM::AndOp::create(
5004 rewriter, loc, llvmIndexVecType, adaptor.getIndices(), maskVector);
5005 mlir::Value result = mlir::LLVM::UndefOp::create(
5006 rewriter, loc, getTypeConverter()->convertType(op.getVec().getType()));
5007 for (uint64_t i = 0; i < numElements; ++i) {
5008 mlir::Value iValue =
5009 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
5010 mlir::Value indexValue = mlir::LLVM::ExtractElementOp::create(
5011 rewriter, loc, maskedIndices, iValue);
5012 mlir::Value valueAtIndex =
5013 mlir::LLVM::ExtractElementOp::create(rewriter, loc, input, indexValue);
5014 result = mlir::LLVM::InsertElementOp::create(rewriter, loc, result,
5015 valueAtIndex, iValue);
5017 rewriter.replaceOp(op, result);
5018 return mlir::success();
5021mlir::LogicalResult CIRToLLVMVecTernaryOpLowering::matchAndRewrite(
5022 cir::VecTernaryOp op, OpAdaptor adaptor,
5023 mlir::ConversionPatternRewriter &rewriter)
const {
5025 mlir::Value bitVec = mlir::LLVM::ICmpOp::create(
5026 rewriter, op.getLoc(), mlir::LLVM::ICmpPredicate::ne, adaptor.getCond(),
5027 mlir::LLVM::ZeroOp::create(
5028 rewriter, op.getCond().getLoc(),
5029 typeConverter->convertType(op.getCond().getType())));
5030 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(
5031 op, bitVec, adaptor.getLhs(), adaptor.getRhs());
5032 return mlir::success();
5035mlir::LogicalResult CIRToLLVMComplexAddOpLowering::matchAndRewrite(
5036 cir::ComplexAddOp op, OpAdaptor adaptor,
5037 mlir::ConversionPatternRewriter &rewriter)
const {
5038 mlir::Value lhs = adaptor.getLhs();
5039 mlir::Value rhs = adaptor.getRhs();
5040 mlir::Location loc = op.getLoc();
5042 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
5043 mlir::Type complexElemTy =
5044 getTypeConverter()->convertType(
complexType.getElementType());
5045 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
5046 rewriter, loc, complexElemTy, lhs,
ArrayRef(int64_t{0}));
5047 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
5048 rewriter, loc, complexElemTy, lhs,
ArrayRef(int64_t{1}));
5049 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
5050 rewriter, loc, complexElemTy, rhs,
ArrayRef(int64_t{0}));
5051 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
5052 rewriter, loc, complexElemTy, rhs,
ArrayRef(int64_t{1}));
5054 mlir::Value newReal;
5055 mlir::Value newImag;
5056 if (complexElemTy.isInteger()) {
5057 newReal = mlir::LLVM::AddOp::create(rewriter, loc, complexElemTy, lhsReal,
5059 newImag = mlir::LLVM::AddOp::create(rewriter, loc, complexElemTy, lhsImag,
5064 newReal = mlir::LLVM::FAddOp::create(rewriter, loc, complexElemTy, lhsReal,
5066 newImag = mlir::LLVM::FAddOp::create(rewriter, loc, complexElemTy, lhsImag,
5070 mlir::Type complexLLVMTy =
5071 getTypeConverter()->convertType(op.getResult().getType());
5072 auto initialComplex =
5073 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), complexLLVMTy);
5075 auto realComplex = mlir::LLVM::InsertValueOp::create(
5076 rewriter, op->getLoc(), initialComplex, newReal,
ArrayRef(int64_t{0}));
5078 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
5079 op, realComplex, newImag,
ArrayRef(int64_t{1}));
5081 return mlir::success();
5084mlir::LogicalResult CIRToLLVMComplexCreateOpLowering::matchAndRewrite(
5085 cir::ComplexCreateOp op, OpAdaptor adaptor,
5086 mlir::ConversionPatternRewriter &rewriter)
const {
5087 mlir::Type complexLLVMTy =
5088 getTypeConverter()->convertType(op.getResult().getType());
5089 auto initialComplex =
5090 mlir::LLVM::UndefOp::create(rewriter, op->getLoc(), complexLLVMTy);
5092 auto realComplex = mlir::LLVM::InsertValueOp::create(
5093 rewriter, op->getLoc(), initialComplex, adaptor.getReal(),
5096 auto complex = mlir::LLVM::InsertValueOp::create(
5097 rewriter, op->getLoc(), realComplex, adaptor.getImag(),
5100 rewriter.replaceOp(op, complex);
5101 return mlir::success();
5104mlir::LogicalResult CIRToLLVMComplexRealOpLowering::matchAndRewrite(
5105 cir::ComplexRealOp op, OpAdaptor adaptor,
5106 mlir::ConversionPatternRewriter &rewriter)
const {
5107 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
5108 mlir::Value operand = adaptor.getOperand();
5109 if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) {
5110 operand = mlir::LLVM::ExtractValueOp::create(
5111 rewriter, op.getLoc(), resultLLVMTy, operand,
5114 rewriter.replaceOp(op, operand);
5115 return mlir::success();
5118mlir::LogicalResult CIRToLLVMComplexSubOpLowering::matchAndRewrite(
5119 cir::ComplexSubOp op, OpAdaptor adaptor,
5120 mlir::ConversionPatternRewriter &rewriter)
const {
5121 mlir::Value lhs = adaptor.getLhs();
5122 mlir::Value rhs = adaptor.getRhs();
5123 mlir::Location loc = op.getLoc();
5125 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
5126 mlir::Type complexElemTy =
5127 getTypeConverter()->convertType(
complexType.getElementType());
5128 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
5129 rewriter, loc, complexElemTy, lhs,
ArrayRef(int64_t{0}));
5130 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
5131 rewriter, loc, complexElemTy, lhs,
ArrayRef(int64_t{1}));
5132 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
5133 rewriter, loc, complexElemTy, rhs,
ArrayRef(int64_t{0}));
5134 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
5135 rewriter, loc, complexElemTy, rhs,
ArrayRef(int64_t{1}));
5137 mlir::Value newReal;
5138 mlir::Value newImag;
5139 if (complexElemTy.isInteger()) {
5140 newReal = mlir::LLVM::SubOp::create(rewriter, loc, complexElemTy, lhsReal,
5142 newImag = mlir::LLVM::SubOp::create(rewriter, loc, complexElemTy, lhsImag,
5147 newReal = mlir::LLVM::FSubOp::create(rewriter, loc, complexElemTy, lhsReal,
5149 newImag = mlir::LLVM::FSubOp::create(rewriter, loc, complexElemTy, lhsImag,
5153 mlir::Type complexLLVMTy =
5154 getTypeConverter()->convertType(op.getResult().getType());
5155 auto initialComplex =
5156 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), complexLLVMTy);
5158 auto realComplex = mlir::LLVM::InsertValueOp::create(
5159 rewriter, op->getLoc(), initialComplex, newReal,
ArrayRef(int64_t{0}));
5161 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
5162 op, realComplex, newImag,
ArrayRef(int64_t{1}));
5164 return mlir::success();
5167mlir::LogicalResult CIRToLLVMComplexImagOpLowering::matchAndRewrite(
5168 cir::ComplexImagOp op, OpAdaptor adaptor,
5169 mlir::ConversionPatternRewriter &rewriter)
const {
5170 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
5171 mlir::Value operand = adaptor.getOperand();
5172 mlir::Location loc = op.getLoc();
5174 if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) {
5175 operand = mlir::LLVM::ExtractValueOp::create(
5178 mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(resultLLVMTy);
5180 mlir::LLVM::ConstantOp::create(rewriter, loc, resultLLVMTy, zeroAttr);
5183 rewriter.replaceOp(op, operand);
5184 return mlir::success();
5188 mlir::MLIRContext *context,
5189 unsigned &storageSize) {
5190 return TypeSwitch<mlir::Type, mlir::IntegerType>(storageType)
5191 .Case<cir::ArrayType>([&](cir::ArrayType atTy) {
5192 storageSize = atTy.getSize() * 8;
5193 return mlir::IntegerType::get(context, storageSize);
5195 .Case<cir::IntType>([&](cir::IntType intTy) {
5196 storageSize = intTy.getWidth();
5197 return mlir::IntegerType::get(context, storageSize);
5199 .Default([](mlir::Type) -> mlir::IntegerType {
5201 "Either ArrayType or IntType expected for bitfields storage");
5205mlir::LogicalResult CIRToLLVMSetBitfieldOpLowering::matchAndRewrite(
5206 cir::SetBitfieldOp op, OpAdaptor adaptor,
5207 mlir::ConversionPatternRewriter &rewriter)
const {
5208 mlir::OpBuilder::InsertionGuard guard(rewriter);
5209 rewriter.setInsertionPoint(op);
5211 cir::BitfieldInfoAttr info = op.getBitfieldInfo();
5212 uint64_t size = info.getSize();
5213 uint64_t offset = info.getOffset();
5214 mlir::Type storageType = info.getStorageType();
5215 mlir::MLIRContext *context = storageType.getContext();
5217 unsigned storageSize = 0;
5219 mlir::IntegerType intType =
5220 computeBitfieldIntType(storageType, context, storageSize);
5222 mlir::Value srcVal = createIntCast(rewriter, adaptor.getSrc(), intType);
5223 unsigned srcWidth = storageSize;
5224 mlir::Value resultVal = srcVal;
5226 if (storageSize != size) {
5227 assert(storageSize > size &&
"Invalid bitfield size.");
5229 mlir::Value val = mlir::LLVM::LoadOp::create(
5230 rewriter, op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(),
5231 op.getIsVolatile());
5234 createAnd(rewriter, srcVal, llvm::APInt::getLowBitsSet(srcWidth, size));
5236 srcVal =
createShL(rewriter, srcVal, offset);
5240 ~llvm::APInt::getBitsSet(srcWidth, offset, offset + size));
5243 srcVal = mlir::LLVM::OrOp::create(rewriter, op.getLoc(), val, srcVal);
5246 mlir::LLVM::StoreOp::create(rewriter, op.getLoc(), srcVal, adaptor.getAddr(),
5247 op.getAlignment(), op.getIsVolatile());
5249 mlir::Type resultTy = getTypeConverter()->convertType(op.getType());
5251 if (info.getIsSigned()) {
5252 assert(size <= storageSize);
5253 unsigned highBits = storageSize - size;
5256 resultVal =
createShL(rewriter, resultVal, highBits);
5257 resultVal =
createAShR(rewriter, resultVal, highBits);
5262 mlir::cast<mlir::IntegerType>(resultTy),
5263 info.getIsSigned());
5265 rewriter.replaceOp(op, resultVal);
5266 return mlir::success();
5269mlir::LogicalResult CIRToLLVMComplexImagPtrOpLowering::matchAndRewrite(
5270 cir::ComplexImagPtrOp op, OpAdaptor adaptor,
5271 mlir::ConversionPatternRewriter &rewriter)
const {
5272 cir::PointerType operandTy = op.getOperand().getType();
5273 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
5274 mlir::Type elementLLVMTy =
5275 getTypeConverter()->convertType(operandTy.getPointee());
5277 mlir::LLVM::GEPArg gepIndices[2] = {{0}, {1}};
5278 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
5279 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
5280 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
5281 op, resultLLVMTy, elementLLVMTy, adaptor.getOperand(), gepIndices,
5283 return mlir::success();
5286mlir::LogicalResult CIRToLLVMComplexRealPtrOpLowering::matchAndRewrite(
5287 cir::ComplexRealPtrOp op, OpAdaptor adaptor,
5288 mlir::ConversionPatternRewriter &rewriter)
const {
5289 cir::PointerType operandTy = op.getOperand().getType();
5290 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
5291 mlir::Type elementLLVMTy =
5292 getTypeConverter()->convertType(operandTy.getPointee());
5294 mlir::LLVM::GEPArg gepIndices[2] = {0, 0};
5295 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
5296 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
5297 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
5298 op, resultLLVMTy, elementLLVMTy, adaptor.getOperand(), gepIndices,
5300 return mlir::success();
5303mlir::LogicalResult CIRToLLVMGetBitfieldOpLowering::matchAndRewrite(
5304 cir::GetBitfieldOp op, OpAdaptor adaptor,
5305 mlir::ConversionPatternRewriter &rewriter)
const {
5307 mlir::OpBuilder::InsertionGuard guard(rewriter);
5308 rewriter.setInsertionPoint(op);
5310 cir::BitfieldInfoAttr
info = op.getBitfieldInfo();
5311 uint64_t size =
info.getSize();
5312 uint64_t offset =
info.getOffset();
5313 mlir::Type storageType =
info.getStorageType();
5314 mlir::MLIRContext *context = storageType.getContext();
5315 unsigned storageSize = 0;
5317 mlir::IntegerType intType =
5320 mlir::Value val = mlir::LLVM::LoadOp::create(
5321 rewriter, op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(),
5322 op.getIsVolatile());
5323 val = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), intType, val);
5325 if (
info.getIsSigned()) {
5326 assert(
static_cast<unsigned>(offset + size) <= storageSize);
5327 unsigned highBits = storageSize - offset - size;
5328 val =
createShL(rewriter, val, highBits);
5329 val =
createAShR(rewriter, val, offset + highBits);
5333 if (
static_cast<unsigned>(offset) + size < storageSize)
5335 llvm::APInt::getLowBitsSet(storageSize, size));
5338 mlir::Type resTy = getTypeConverter()->convertType(op.getType());
5340 rewriter, val, mlir::cast<mlir::IntegerType>(resTy),
info.getIsSigned());
5341 rewriter.replaceOp(op, newOp);
5342 return mlir::success();
5345mlir::LogicalResult CIRToLLVMInlineAsmOpLowering::matchAndRewrite(
5346 cir::InlineAsmOp op, OpAdaptor adaptor,
5347 mlir::ConversionPatternRewriter &rewriter)
const {
5349 if (op.getNumResults())
5350 llResTy = getTypeConverter()->convertType(op.getType(0));
5352 cir::AsmFlavor dialect = op.getAsmFlavor();
5353 mlir::LLVM::AsmDialect llDialect = dialect == cir::AsmFlavor::x86_att
5354 ? mlir::LLVM::AsmDialect::AD_ATT
5355 : mlir::LLVM::AsmDialect::AD_Intel;
5358 StringRef llvmAttrName = mlir::LLVM::InlineAsmOp::getElementTypeAttrName();
5364 if (!op.getNumResults())
5365 opAttrs.push_back(mlir::Attribute());
5369 for (
auto const &[llvmOp, cirOp] :
5370 zip(adaptor.getAsmOperands(), op.getAsmOperands())) {
5371 append_range(llvmOperands, llvmOp);
5372 append_range(cirOperands, cirOp);
5377 for (
auto const &[cirOpAttr, cirOp] :
5378 zip(op.getOperandAttrs(), cirOperands)) {
5379 if (!mlir::isa<mlir::UnitAttr>(cirOpAttr)) {
5380 opAttrs.push_back(mlir::Attribute());
5385 cir::PointerType typ = mlir::cast<cir::PointerType>(cirOp.getType());
5387 *getTypeConverter(), dataLayout, typ.getPointee()));
5389 attrs.push_back(rewriter.getNamedAttr(llvmAttrName, typAttr));
5390 mlir::DictionaryAttr newDict = rewriter.getDictionaryAttr(attrs);
5391 opAttrs.push_back(newDict);
5394 rewriter.replaceOpWithNewOp<mlir::LLVM::InlineAsmOp>(
5395 op, llResTy, llvmOperands, op.getAsmStringAttr(), op.getConstraintsAttr(),
5396 op.getSideEffectsAttr(),
5399 mlir::LLVM::TailCallKindAttr::get(
5400 getContext(), mlir::LLVM::tailcallkind::TailCallKind::None),
5401 mlir::LLVM::AsmDialectAttr::get(getContext(), llDialect),
5402 rewriter.getArrayAttr(opAttrs));
5404 return mlir::success();
5407mlir::LogicalResult CIRToLLVMVAStartOpLowering::matchAndRewrite(
5408 cir::VAStartOp op, OpAdaptor adaptor,
5409 mlir::ConversionPatternRewriter &rewriter)
const {
5410 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
5411 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
5412 adaptor.getArgList());
5413 rewriter.replaceOpWithNewOp<mlir::LLVM::VaStartOp>(op, vaList);
5414 return mlir::success();
5417mlir::LogicalResult CIRToLLVMVAEndOpLowering::matchAndRewrite(
5418 cir::VAEndOp op, OpAdaptor adaptor,
5419 mlir::ConversionPatternRewriter &rewriter)
const {
5420 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
5421 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
5422 adaptor.getArgList());
5423 rewriter.replaceOpWithNewOp<mlir::LLVM::VaEndOp>(op, vaList);
5424 return mlir::success();
5427mlir::LogicalResult CIRToLLVMVACopyOpLowering::matchAndRewrite(
5428 cir::VACopyOp op, OpAdaptor adaptor,
5429 mlir::ConversionPatternRewriter &rewriter)
const {
5430 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
5431 auto dstList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
5432 adaptor.getDstList());
5433 auto srcList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
5434 adaptor.getSrcList());
5435 rewriter.replaceOpWithNewOp<mlir::LLVM::VaCopyOp>(op, dstList, srcList);
5436 return mlir::success();
5439mlir::LogicalResult CIRToLLVMVAArgOpLowering::matchAndRewrite(
5440 cir::VAArgOp op, OpAdaptor adaptor,
5441 mlir::ConversionPatternRewriter &rewriter)
const {
5443 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
5444 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
5445 adaptor.getArgList());
5447 mlir::Type llvmType =
5448 getTypeConverter()->convertType(op->getResultTypes().front());
5450 return mlir::failure();
5452 rewriter.replaceOpWithNewOp<mlir::LLVM::VaArgOp>(op, llvmType, vaList);
5453 return mlir::success();
5456mlir::LogicalResult CIRToLLVMLabelOpLowering::matchAndRewrite(
5457 cir::LabelOp op, OpAdaptor adaptor,
5458 mlir::ConversionPatternRewriter &rewriter)
const {
5459 mlir::MLIRContext *ctx = rewriter.getContext();
5460 mlir::Block *block = op->getBlock();
5463 if (block->isEntryBlock()) {
5464 mlir::Block *newBlock =
5465 rewriter.splitBlock(op->getBlock(), mlir::Block::iterator(op));
5466 rewriter.setInsertionPointToEnd(block);
5467 mlir::LLVM::BrOp::create(rewriter, op.getLoc(), newBlock);
5470 mlir::LLVM::BlockTagAttr::get(ctx, blockInfoAddr.getTagIndex());
5471 rewriter.setInsertionPoint(op);
5474 mlir::LLVM::BlockTagOp::create(rewriter, op->getLoc(), tagAttr);
5475 mlir::LLVM::LLVMFuncOp func = op->getParentOfType<mlir::LLVM::LLVMFuncOp>();
5476 auto blockInfoAttr =
5477 cir::BlockAddrInfoAttr::get(ctx, func.getSymName(), op.getLabel());
5478 blockInfoAddr.mapBlockTag(blockInfoAttr, blockTagOp);
5479 rewriter.eraseOp(op);
5481 return mlir::success();
5484mlir::LogicalResult CIRToLLVMBlockAddressOpLowering::matchAndRewrite(
5485 cir::BlockAddressOp op, OpAdaptor adaptor,
5486 mlir::ConversionPatternRewriter &rewriter)
const {
5487 mlir::MLIRContext *ctx = rewriter.getContext();
5489 mlir::LLVM::BlockTagOp matchLabel =
5490 blockInfoAddr.lookupBlockTag(op.getBlockAddrInfoAttr());
5491 mlir::LLVM::BlockTagAttr tagAttr;
5498 tagAttr = matchLabel.getTag();
5500 auto blkAddr = mlir::LLVM::BlockAddressAttr::get(
5501 rewriter.getContext(), op.getBlockAddrInfoAttr().getFunc(), tagAttr);
5502 rewriter.setInsertionPoint(op);
5503 auto newOp = mlir::LLVM::BlockAddressOp::create(
5504 rewriter, op.getLoc(), mlir::LLVM::LLVMPointerType::get(ctx), blkAddr);
5506 blockInfoAddr.addUnresolvedBlockAddress(newOp, op.getBlockAddrInfoAttr());
5507 rewriter.replaceOp(op, newOp);
5508 return mlir::success();
5511mlir::LogicalResult CIRToLLVMIndirectBrOpLowering::matchAndRewrite(
5512 cir::IndirectBrOp op, OpAdaptor adaptor,
5513 mlir::ConversionPatternRewriter &rewriter)
const {
5515 mlir::Value targetAddr = adaptor.getAddr();
5523 if (op.getPoison()) {
5524 auto llvmPtrType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
5526 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), llvmPtrType);
5529 rewriter.replaceOpWithNewOp<mlir::LLVM::IndirectBrOp>(
5530 op, targetAddr, adaptor.getSuccOperands(), op.getSuccessors());
5531 return mlir::success();
5534mlir::LogicalResult CIRToLLVMTokenNoneOpLowering::matchAndRewrite(
5535 cir::TokenNoneOp op, OpAdaptor adaptor,
5536 mlir::ConversionPatternRewriter &rewriter)
const {
5537 return mlir::failure();
5540mlir::LogicalResult CIRToLLVMCoroFreeOpLowering::matchAndRewrite(
5541 cir::CoroFreeOp op, OpAdaptor adaptor,
5542 mlir::ConversionPatternRewriter &rewriter)
const {
5543 return mlir::failure();
5546mlir::LogicalResult CIRToLLVMCoroEndOpLowering::matchAndRewrite(
5547 cir::CoroEndOp op, OpAdaptor adaptor,
5548 mlir::ConversionPatternRewriter &rewriter)
const {
5549 return mlir::failure();
5552mlir::LogicalResult CIRToLLVMCoroAllocOpLowering::matchAndRewrite(
5553 cir::CoroAllocOp op, OpAdaptor adaptor,
5554 mlir::ConversionPatternRewriter &rewriter)
const {
5555 return mlir::failure();
5558mlir::LogicalResult CIRToLLVMCoroBeginOpLowering::matchAndRewrite(
5559 cir::CoroBeginOp op, OpAdaptor adaptor,
5560 mlir::ConversionPatternRewriter &rewriter)
const {
5561 return mlir::failure();
5564mlir::LogicalResult CIRToLLVMCoroIdOpLowering::matchAndRewrite(
5565 cir::CoroIdOp op, OpAdaptor adaptor,
5566 mlir::ConversionPatternRewriter &rewriter)
const {
5567 return mlir::failure();
5570mlir::LogicalResult CIRToLLVMCoroSizeOpLowering::matchAndRewrite(
5571 cir::CoroSizeOp op, OpAdaptor adaptor,
5572 mlir::ConversionPatternRewriter &rewriter)
const {
5573 return mlir::failure();
5576mlir::LogicalResult CIRToLLVMCpuIdOpLowering::matchAndRewrite(
5577 cir::CpuIdOp op, OpAdaptor adaptor,
5578 mlir::ConversionPatternRewriter &rewriter)
const {
5579 mlir::Type i32Ty = rewriter.getI32Type();
5580 mlir::Type i64Ty = rewriter.getI64Type();
5581 mlir::Type i32PtrTy = mlir::LLVM::LLVMPointerType::get(i32Ty.getContext(), 0);
5583 mlir::Type cpuidRetTy = mlir::LLVM::LLVMStructType::getLiteral(
5584 rewriter.getContext(), {i32Ty, i32Ty, i32Ty, i32Ty});
5586 mlir::Value functionId = adaptor.getFunctionId();
5587 mlir::Value subFunctionId = adaptor.getSubFunctionId();
5589 StringRef asmString, constraints;
5590 mlir::ModuleOp moduleOp = op->getParentOfType<mlir::ModuleOp>();
5591 llvm::Triple triple(
5592 mlir::cast<mlir::StringAttr>(
5593 moduleOp->getAttr(cir::CIRDialect::getTripleAttrName()))
5595 if (triple.getArch() == llvm::Triple::x86) {
5596 asmString =
"cpuid";
5597 constraints =
"={ax},={bx},={cx},={dx},{ax},{cx}";
5600 asmString =
"xchgq %rbx, ${1:q}\n"
5602 "xchgq %rbx, ${1:q}";
5603 constraints =
"={ax},=r,={cx},={dx},0,2";
5606 mlir::Value inlineAsm =
5607 mlir::LLVM::InlineAsmOp::create(
5608 rewriter, op.getLoc(), cpuidRetTy, {functionId, subFunctionId},
5609 rewriter.getStringAttr(asmString),
5610 rewriter.getStringAttr(constraints),
5613 mlir::LLVM::TailCallKindAttr{},
5614 mlir::LLVM::AsmDialectAttr{},
5618 mlir::Value basePtr = adaptor.getCpuInfo();
5620 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
5621 unsigned alignment = layout.getTypeABIAlignment(i32Ty);
5622 for (
unsigned i = 0; i < 4; i++) {
5623 mlir::Value extracted =
5624 mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(), inlineAsm, i)
5626 mlir::Value index = mlir::LLVM::ConstantOp::create(
5627 rewriter, op.getLoc(), i64Ty, rewriter.getI64IntegerAttr(i));
5629 mlir::Value storePtr = mlir::LLVM::GEPOp::create(
5630 rewriter, op.getLoc(), i32PtrTy, i32Ty, basePtr,
5631 gepIndices, mlir::LLVM::GEPNoWrapFlags::none)
5633 mlir::LLVM::StoreOp::create(rewriter, op.getLoc(), extracted, storePtr,
5637 rewriter.eraseOp(op);
5638 return mlir::success();
5641mlir::LogicalResult CIRToLLVMMemChrOpLowering::matchAndRewrite(
5642 cir::MemChrOp op, OpAdaptor adaptor,
5643 mlir::ConversionPatternRewriter &rewriter)
const {
5644 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
5645 mlir::Type srcTy = getTypeConverter()->convertType(op.getSrc().getType());
5646 mlir::Type patternTy =
5647 getTypeConverter()->convertType(op.getPattern().getType());
5648 mlir::Type lenTy = getTypeConverter()->convertType(op.getLen().getType());
5650 mlir::LLVM::LLVMFunctionType::get(llvmPtrTy, {srcTy, patternTy, lenTy},
5652 llvm::StringRef fnName =
"memchr";
5654 mlir::Builder b(rewriter.getContext());
5655 mlir::NamedAttribute noundefAttr =
5656 b.getNamedAttr(
"llvm.noundef", b.getUnitAttr());
5657 mlir::DictionaryAttr noundefDict = mlir::DictionaryAttr::get(
5660 mlir::ArrayAttr argAttrs =
5661 mlir::ArrayAttr::get(rewriter.getContext(), argAttrVec);
5666 mlir::LLVM::CallOp newCall = rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(
5667 op, mlir::TypeRange{llvmPtrTy}, fnName,
5668 mlir::ValueRange{adaptor.getSrc(), adaptor.getPattern(),
5670 newCall.setArgAttrsAttr(argAttrs);
5671 return mlir::success();
5677 mlir::Location loc, mlir::Value inputPtr,
5678 uint64_t baseAlignment,
5679 cir::OffsetPairAttr paddingAttr) {
5684 uint64_t charWidth = 8;
5685 mlir::Type i8Ty = rewriter.getI8Type();
5686 mlir::Type ptrTy = mlir::LLVM::LLVMPointerType::get(i8Ty.getContext());
5688 auto startByte = paddingAttr.getStart() / charWidth;
5689 auto startBit = paddingAttr.getStart() % charWidth;
5690 auto endByte = paddingAttr.getEnd() / charWidth;
5691 auto endBit = paddingAttr.getEnd() % charWidth;
5693 if (startByte == endByte) {
5695 auto index = mlir::LLVM::ConstantOp::create(
5696 rewriter, loc, rewriter.getI32Type(), startByte);
5697 auto element = mlir::LLVM::GEPOp::create(rewriter, loc, ptrTy, i8Ty,
5700 uint64_t adjustedAlignment = llvm::MinAlign(baseAlignment, startByte);
5702 auto value = mlir::LLVM::LoadOp::create(rewriter, loc, i8Ty, element,
5707 uint8_t bitsToClear = ((1 << endBit) - 1) & ~((1 << startBit) - 1);
5708 uint8_t bitsToKeep = ~bitsToClear;
5710 mlir::LLVM::ConstantOp::create(rewriter, loc, i8Ty, bitsToKeep);
5711 auto newValue = mlir::LLVM::AndOp::create(rewriter, loc, value, maskValue);
5713 mlir::LLVM::StoreOp::create(rewriter, loc, newValue, element,
5717 if (startBit != 0) {
5718 auto index = mlir::LLVM::ConstantOp::create(
5719 rewriter, loc, rewriter.getI32Type(), startByte);
5720 auto element = mlir::LLVM::GEPOp::create(rewriter, loc, ptrTy, i8Ty,
5722 uint64_t adjustedAlignment = llvm::MinAlign(baseAlignment, startByte);
5724 auto value = mlir::LLVM::LoadOp::create(rewriter, loc, i8Ty, element,
5727 uint8_t bitsToClear = ((1 << (charWidth - startBit)) - 1) << startBit;
5728 uint8_t bitsToKeep = ~bitsToClear;
5730 mlir::LLVM::ConstantOp::create(rewriter, loc, i8Ty, bitsToKeep);
5732 mlir::LLVM::AndOp::create(rewriter, loc, value, maskValue);
5734 mlir::LLVM::StoreOp::create(rewriter, loc, newValue, element,
5740 for (
auto offset = startByte; offset < endByte; ++offset) {
5741 auto index = mlir::LLVM::ConstantOp::create(
5742 rewriter, loc, rewriter.getI32Type(), offset);
5743 auto element = mlir::LLVM::GEPOp::create(rewriter, loc, ptrTy, i8Ty,
5745 uint64_t adjustedAlignment = llvm::MinAlign(baseAlignment, offset);
5747 auto zero = mlir::LLVM::ConstantOp::create(rewriter, loc, i8Ty, 0);
5748 mlir::LLVM::StoreOp::create(rewriter, loc, zero, element,
5754 auto index = mlir::LLVM::ConstantOp::create(
5755 rewriter, loc, rewriter.getI32Type(), endByte);
5756 auto element = mlir::LLVM::GEPOp::create(rewriter, loc, ptrTy, i8Ty,
5758 uint64_t adjustedAlignment = llvm::MinAlign(baseAlignment, endByte);
5760 auto value = mlir::LLVM::LoadOp::create(rewriter, loc, i8Ty, element,
5763 uint8_t bitsToClear = (1 << endBit) - 1;
5764 uint8_t bitsToKeep = ~bitsToClear;
5766 mlir::LLVM::ConstantOp::create(rewriter, loc, i8Ty, bitsToKeep);
5768 mlir::LLVM::AndOp::create(rewriter, loc, value, maskValue);
5770 mlir::LLVM::StoreOp::create(rewriter, loc, newValue, element,
5776mlir::LogicalResult CIRToLLVMClearPaddingOpLowering::matchAndRewrite(
5777 cir::ClearPaddingOp op, OpAdaptor adaptor,
5778 mlir::ConversionPatternRewriter &rewriter)
const {
5780 mlir::Value inputPtr = adaptor.getArg();
5781 for (mlir::Attribute attr : op.getPadding())
5782 clearPadding(rewriter, op.getLoc(), inputPtr, op.getAlignment(),
5783 cast<cir::OffsetPairAttr>(attr));
5785 rewriter.eraseOp(op);
5786 return mlir::success();
5790 return std::make_unique<ConvertCIRToLLVMPass>();
5796 pm.addPass(mlir::omp::createMarkDeclareTargetPass());
5799 pm.addPass(mlir::omp::createHostOpFilteringPass());
5802std::unique_ptr<llvm::Module>
5804 bool enableOpenMP, StringRef mlirSaveTempsOutFile,
5805 llvm::vfs::FileSystem *fs) {
5806 llvm::TimeTraceScope scope(
"lower from CIR to LLVM directly");
5808 mlir::MLIRContext *mlirCtx = mlirModule.getContext();
5810 mlir::PassManager pm(mlirCtx);
5813 (void)mlir::applyPassManagerCLOptions(pm);
5815 if (mlir::failed(pm.run(mlirModule))) {
5818 "The pass manager failed to lower CIR to LLVMIR dialect!");
5821 if (!mlirSaveTempsOutFile.empty()) {
5823 llvm::raw_fd_ostream out(mlirSaveTempsOutFile, ec);
5825 mlirModule->print(out);
5828 mlir::registerBuiltinDialectTranslation(*mlirCtx);
5829 mlir::registerLLVMDialectTranslation(*mlirCtx);
5830 mlir::registerOpenMPDialectTranslation(*mlirCtx);
5833 llvm::TimeTraceScope translateScope(
"translateModuleToLLVMIR");
5835 StringRef moduleName = mlirModule.getName().value_or(
"CIRToLLVMModule");
5836 std::unique_ptr<llvm::Module> llvmModule = mlir::translateModuleToLLVMIR(
5837 mlirModule, llvmCtx, moduleName,
false, fs);
5841 report_fatal_error(
"Lowering from LLVMIR dialect to llvm IR failed!");
static bool isUnsigned(SValBuilder &SVB, NonLoc Value)
static llvm::StringRef getLinkageAttrNameString()
Returns the name used for the linkage attribute.
#define CHECK_ENUM(CIR, LLVM_VAL)
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)
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)
mlir::Attribute visit(mlir::Attribute attr)
mlir::Attribute visitCirAttr(cir::FPAttr attr)
mlir::Attribute visitCirAttr(cir::BoolAttr attr)
GlobalInitAttrRewriter(mlir::Type type, mlir::ConversionPatternRewriter &rewriter)
mlir::Attribute visitCirAttr(cir::IntAttr attr)
static mlir::LLVM::CConv convertCallingConv(cir::CallingConv callingConv)
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.
void convertSideEffectForCall(mlir::Operation *callOp, bool isNothrow, cir::SideEffect sideEffect, mlir::LLVM::MemoryEffectsAttr &memoryEffect, bool &noUnwind, bool &willReturn, bool &noReturn)
static bool isBulkLowerableConstArrayBaseElement(mlir::Type baseElemTy)
static mlir::LLVM::IntegerOverflowFlags intOverflowFlag(BinOp op)
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 bool isSplitStorageBitInt(cir::IntType ty, const mlir::DataLayout &dataLayout)
A _BitInt(N) whose padded storage integer iM has a larger alloc size than its M/8 store size is laid ...
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::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 mlir::ArrayAttr convertTypedArgAttrs(mlir::ArrayAttr argAttrs, const mlir::TypeConverter &converter, mlir::MLIRContext *ctx)
The llvm.byval, llvm.sret, and llvm.byref argument attributes carry the pointee type as a TypeAttr.
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 void lowerCallAttributes(cir::CIRCallOpInterface op, const mlir::TypeConverter &converter, SmallVectorImpl< mlir::NamedAttribute > &result)
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.
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 unsigned getBitIntMemoryStorageBits(cir::IntType ty, const mlir::DataLayout &dataLayout)
In-memory storage width in bits for a _BitInt(N): N rounded up to the type's ABI alignment.
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 mlir::LogicalResult rewriteCallOrInvoke(mlir::Operation *op, mlir::ValueRange callOperands, mlir::ConversionPatternRewriter &rewriter, const mlir::TypeConverter *converter, mlir::SymbolTableCollection &symbolTables, mlir::FlatSymbolRefAttr calleeAttr, mlir::Block *continueBlock=nullptr, mlir::Block *landingPadBlock=nullptr)
static llvm::StringRef convertCmpKindToConstrainedFCmpPredicate(cir::CmpOpKind kind)
static mlir::LLVM::Visibility lowerCIRVisibilityToLLVMVisibility(cir::VisibilityKind visibilityKind)
static uint64_t getTypeSize(mlir::Type type, mlir::Operation &op)
static mlir::Value emitBoolVecConversion(mlir::ConversionPatternRewriter &rewriter, mlir::Value srcVec, unsigned numElementsDst)
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.
static mlir::Type convertTypeForMemory(const mlir::TypeConverter &converter, mlir::DataLayout const &dataLayout, mlir::Type type)
Given a type convertor and a data layout, convert the given type to a type that is suitable for memor...
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 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)
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.
llvm::Type * convertTypeForMemory(CodeGenModule &CGM, QualType T)
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 ?
__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 globalViewIntLowering()
static bool opAllocaAnnotations()
static bool opLoadStoreTbaa()
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()