19#include "mlir/Conversion/LLVMCommon/TypeConverter.h"
20#include "mlir/Conversion/OpenMPToLLVM/ConvertOpenMPToLLVM.h"
21#include "mlir/Dialect/DLTI/DLTI.h"
22#include "mlir/Dialect/Func/IR/FuncOps.h"
23#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
24#include "mlir/Dialect/LLVMIR/LLVMTypes.h"
25#include "mlir/Dialect/OpenMP/OpenMPDialect.h"
26#include "mlir/Dialect/OpenMP/Transforms/Passes.h"
27#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
28#include "mlir/IR/BuiltinAttributes.h"
29#include "mlir/IR/BuiltinDialect.h"
30#include "mlir/IR/BuiltinOps.h"
31#include "mlir/IR/Location.h"
32#include "mlir/IR/Types.h"
33#include "mlir/Pass/Pass.h"
34#include "mlir/Pass/PassManager.h"
35#include "mlir/Support/LLVM.h"
36#include "mlir/Target/LLVMIR/Dialect/Builtin/BuiltinToLLVMIRTranslation.h"
37#include "mlir/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.h"
38#include "mlir/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.h"
39#include "mlir/Target/LLVMIR/Export.h"
40#include "mlir/Transforms/DialectConversion.h"
49#include "llvm/ADT/MapVector.h"
50#include "llvm/ADT/StringMap.h"
51#include "llvm/ADT/TypeSwitch.h"
52#include "llvm/IR/Module.h"
53#include "llvm/Support/Casting.h"
54#include "llvm/Support/ErrorHandling.h"
55#include "llvm/Support/TimeProfiler.h"
56#include "llvm/Support/VirtualFileSystem.h"
57#include "llvm/Support/raw_ostream.h"
72mlir::Type elementTypeIfVector(mlir::Type type) {
73 return llvm::TypeSwitch<mlir::Type, mlir::Type>(type)
74 .Case<cir::VectorType, mlir::VectorType>(
75 [](
auto p) {
return p.getElementType(); })
76 .
Default([](mlir::Type p) {
return p; });
84 mlir::Type llvmMemType,
85 const mlir::DataLayout &dataLayout) {
86 if (
auto intTy = mlir::dyn_cast<cir::IntType>(cirType);
87 intTy && intTy.isBitInt())
88 return intTy.getABIAlignment(dataLayout, {});
89 return dataLayout.getTypeABIAlignment(llvmMemType);
93 mlir::IntegerType dstTy,
94 bool isSigned =
false) {
95 mlir::Type srcTy = src.getType();
96 assert(mlir::isa<mlir::IntegerType>(srcTy));
98 unsigned srcWidth = mlir::cast<mlir::IntegerType>(srcTy).getWidth();
99 unsigned dstWidth = mlir::cast<mlir::IntegerType>(dstTy).getWidth();
100 mlir::Location loc = src.getLoc();
102 if (dstWidth > srcWidth && isSigned)
103 return mlir::LLVM::SExtOp::create(bld, loc, dstTy, src);
104 if (dstWidth > srcWidth)
105 return mlir::LLVM::ZExtOp::create(bld, loc, dstTy, src);
106 if (dstWidth < srcWidth)
107 return mlir::LLVM::TruncOp::create(bld, loc, dstTy, src);
108 return mlir::LLVM::BitcastOp::create(bld, loc, dstTy, src);
118 const mlir::DataLayout &dataLayout, cir::IntType intTy,
119 mlir::Value value,
bool toMemory) {
120 unsigned storageBits = intTy.getStorageTypeWidth(dataLayout);
121 if (storageBits == intTy.getWidth())
123 unsigned dstBits = toMemory ? storageBits : intTy.getWidth();
124 return createIntCast(rewriter, value, rewriter.getIntegerType(dstBits),
125 toMemory && intTy.isSigned());
128static mlir::LLVM::Visibility
130 switch (visibilityKind) {
131 case cir::VisibilityKind::Default:
132 return ::mlir::LLVM::Visibility::Default;
133 case cir::VisibilityKind::Hidden:
134 return ::mlir::LLVM::Visibility::Hidden;
135 case cir::VisibilityKind::Protected:
136 return ::mlir::LLVM::Visibility::Protected;
142 mlir::Value srcVec,
unsigned numElementsDst) {
143 auto srcTy = mlir::cast<mlir::VectorType>(srcVec.getType());
144 unsigned numElementsSrc = srcTy.getNumElements();
145 if (numElementsSrc == numElementsDst)
149 for (
unsigned i : llvm::seq(std::min(numElementsDst, numElementsSrc)))
152 mlir::Location loc = srcVec.getLoc();
153 auto poison = mlir::LLVM::PoisonOp::create(rewriter, loc, srcVec.getType());
154 return mlir::LLVM::ShuffleVectorOp::create(rewriter, loc, srcVec, poison,
162 const mlir::TypeConverter &converter,
163 mlir::DataLayout
const &dataLayout,
164 cir::LoadOp op, mlir::Value value) {
166 if (
auto boolTy = mlir::dyn_cast<cir::BoolType>(op.getType())) {
168 assert(value.getType().isInteger(dataLayout.getTypeSizeInBits(boolTy)));
173 if (
auto vecTy = mlir::dyn_cast<cir::VectorType>(op.getType())) {
174 if (mlir::isa<cir::BoolType>(vecTy.getElementType())) {
175 auto rawIntTy = mlir::cast<mlir::IntegerType>(value.getType());
177 cir::VectorType::get(vecTy.getElementType(), rawIntTy.getWidth());
178 mlir::Type mlirVecTy = converter.convertType(paddedVecTy);
180 auto v = mlir::LLVM::BitcastOp::create(rewriter, value.getLoc(),
188 if (
auto intTy = mlir::dyn_cast<cir::IntType>(op.getType());
189 intTy && intTy.isBitInt())
199static mlir::Value
emitToMemory(mlir::ConversionPatternRewriter &rewriter,
200 mlir::DataLayout
const &dataLayout,
201 mlir::Type origType, mlir::Value value) {
204 if (
auto boolTy = mlir::dyn_cast<cir::BoolType>(origType)) {
206 mlir::IntegerType memType =
207 rewriter.getIntegerType(dataLayout.getTypeSizeInBits(boolTy));
212 if (
auto vecTy = mlir::dyn_cast<cir::VectorType>(origType)) {
213 if (mlir::isa<cir::BoolType>(vecTy.getElementType())) {
214 uint64_t bytePadded = std::max<uint64_t>(vecTy.getSize(), 8);
215 auto resultTy = mlir::IntegerType::get(origType.getContext(), bytePadded);
217 return mlir::LLVM::BitcastOp::create(rewriter, value.getLoc(), resultTy,
223 if (
auto intTy = mlir::dyn_cast<cir::IntType>(origType);
224 intTy && intTy.isBitInt())
232 using CIR = cir::GlobalLinkageKind;
233 using LLVM = mlir::LLVM::Linkage;
236 case CIR::AppendingLinkage:
237 return LLVM::Appending;
238 case CIR::AvailableExternallyLinkage:
239 return LLVM::AvailableExternally;
240 case CIR::CommonLinkage:
242 case CIR::ExternalLinkage:
243 return LLVM::External;
244 case CIR::ExternalWeakLinkage:
245 return LLVM::ExternWeak;
246 case CIR::InternalLinkage:
247 return LLVM::Internal;
248 case CIR::LinkOnceAnyLinkage:
249 return LLVM::Linkonce;
250 case CIR::LinkOnceODRLinkage:
251 return LLVM::LinkonceODR;
252 case CIR::PrivateLinkage:
253 return LLVM::Private;
254 case CIR::WeakAnyLinkage:
256 case CIR::WeakODRLinkage:
257 return LLVM::WeakODR;
259 llvm_unreachable(
"Unknown CIR linkage type");
263 using CIR = cir::CallingConv;
264 using LLVM = mlir::LLVM::CConv;
266 switch (callingConv) {
269 case CIR::SpirKernel:
270 return LLVM::SPIR_KERNEL;
271 case CIR::SpirFunction:
272 return LLVM::SPIR_FUNC;
274 return LLVM::PTX_Kernel;
275 case CIR::AMDGPUKernel:
276 return LLVM::AMDGPU_KERNEL;
278 llvm_unreachable(
"Unknown calling convention");
281mlir::LogicalResult CIRToLLVMCopyOpLowering::matchAndRewrite(
282 cir::CopyOp op, OpAdaptor adaptor,
283 mlir::ConversionPatternRewriter &rewriter)
const {
284 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
285 const mlir::Value
length = mlir::LLVM::ConstantOp::create(
286 rewriter, op.getLoc(), rewriter.getI64Type(),
287 op.getCopySizeInBytes(layout));
291 *getTypeConverter(), dataLayout, op.getDst().getType().getPointee()));
293 *getTypeConverter(), dataLayout, op.getSrc().getType().getPointee()));
295 mlir::NamedAttribute dstAlignAttr = rewriter.getNamedAttr(
296 mlir::LLVM::LLVMDialect::getAlignAttrName(),
297 rewriter.getI64IntegerAttr(op.getDstAlignment().value_or(dstTypeAlign)));
298 mlir::NamedAttribute srcAlignAttr = rewriter.getNamedAttr(
299 mlir::LLVM::LLVMDialect::getAlignAttrName(),
300 rewriter.getI64IntegerAttr(op.getSrcAlignment().value_or(srcTypeAlign)));
301 mlir::ArrayAttr argAttrs = rewriter.getArrayAttr({
302 rewriter.getDictionaryAttr({dstAlignAttr}),
303 rewriter.getDictionaryAttr({srcAlignAttr}),
306 rewriter.replaceOpWithNewOp<mlir::LLVM::MemcpyOp>(
307 op, adaptor.getDst(), adaptor.getSrc(),
length, op.getIsVolatile(),
309 nullptr,
nullptr, argAttrs,
311 return mlir::success();
314mlir::LogicalResult CIRToLLVMMemCpyOpLowering::matchAndRewrite(
315 cir::MemCpyOp op, OpAdaptor adaptor,
316 mlir::ConversionPatternRewriter &rewriter)
const {
317 rewriter.replaceOpWithNewOp<mlir::LLVM::MemcpyOp>(
318 op, adaptor.getDst(), adaptor.getSrc(), adaptor.getLen(),
320 return mlir::success();
323mlir::LogicalResult CIRToLLVMMemMoveOpLowering::matchAndRewrite(
324 cir::MemMoveOp op, OpAdaptor adaptor,
325 mlir::ConversionPatternRewriter &rewriter)
const {
326 rewriter.replaceOpWithNewOp<mlir::LLVM::MemmoveOp>(
327 op, adaptor.getDst(), adaptor.getSrc(), adaptor.getLen(),
329 return mlir::success();
332mlir::LogicalResult CIRToLLVMMemSetOpLowering::matchAndRewrite(
333 cir::MemSetOp op, OpAdaptor adaptor,
334 mlir::ConversionPatternRewriter &rewriter)
const {
336 auto memset = rewriter.replaceOpWithNewOp<mlir::LLVM::MemsetOp>(
337 op, adaptor.getDst(), adaptor.getVal(), adaptor.getLen(),
340 if (op.getAlignmentAttr()) {
342 llvm::SmallVector<mlir::Attribute> attrs{
memset.getNumOperands(),
343 rewriter.getDictionaryAttr({})};
344 llvm::SmallVector<mlir::NamedAttribute> destAttrs;
346 {mlir::LLVM::LLVMDialect::getAlignAttrName(), op.getAlignmentAttr()});
347 attrs[
memset.odsIndex_dst] = rewriter.getDictionaryAttr(destAttrs);
349 auto arrayAttr = rewriter.getArrayAttr(attrs);
350 memset.setArgAttrsAttr(arrayAttr);
353 return mlir::success();
357 mlir::Value llvmSrc, mlir::Type llvmDstIntTy,
359 uint64_t cirDstIntWidth) {
360 if (cirSrcWidth == cirDstIntWidth)
363 auto loc = llvmSrc.getLoc();
364 if (cirSrcWidth < cirDstIntWidth) {
366 return mlir::LLVM::ZExtOp::create(rewriter, loc, llvmDstIntTy, llvmSrc);
367 return mlir::LLVM::SExtOp::create(rewriter, loc, llvmDstIntTy, llvmSrc);
371 return mlir::LLVM::TruncOp::create(rewriter, loc, llvmDstIntTy, llvmSrc);
377 mlir::ConversionPatternRewriter &rewriter,
378 mlir::SymbolTableCollection &symbolTables,
379 const mlir::TypeConverter *converter,
381 : parentOp(parentOp), rewriter(rewriter), symbolTables(symbolTables),
382 converter(converter), blockInfoAddr(blockInfoAddr) {}
384#define GET_CIR_ATTR_TO_VALUE_VISITOR_DECLS
385#include "clang/CIR/Dialect/IR/CIRLowering.inc"
386#undef GET_CIR_ATTR_TO_VALUE_VISITOR_DECLS
389 struct LoweredGlobalSymbol {
391 mlir::Type sourceType;
395 LoweredGlobalSymbol getAddressOfSymbol(mlir::FlatSymbolRefAttr symbol);
396 mlir::Value castGlobalAddrToType(mlir::Value addr, mlir::Type attrType,
397 mlir::Type sourceType,
unsigned addrSpace);
399 mlir::Operation *parentOp;
400 mlir::ConversionPatternRewriter &rewriter;
401 mlir::SymbolTableCollection &symbolTables;
402 const mlir::TypeConverter *converter;
405 LLVMBlockAddressInfo *blockInfoAddr;
410 const mlir::Attribute attr,
411 mlir::ConversionPatternRewriter &rewriter,
412 mlir::SymbolTableCollection &symbolTables,
413 const mlir::TypeConverter *converter,
415 CIRAttrToValue valueConverter(parentOp, rewriter, symbolTables, converter,
417 mlir::Value value = valueConverter.visit(attr);
419 llvm_unreachable(
"unhandled attribute type");
424 cir::SideEffect sideEffect,
425 mlir::LLVM::MemoryEffectsAttr &memoryEffect,
426 bool &noUnwind,
bool &willReturn,
428 using mlir::LLVM::ModRefInfo;
430 switch (sideEffect) {
431 case cir::SideEffect::All:
433 noUnwind = isNothrow;
437 case cir::SideEffect::Pure:
438 memoryEffect = mlir::LLVM::MemoryEffectsAttr::get(
439 callOp->getContext(), ModRefInfo::Ref,
449 case cir::SideEffect::Const:
450 memoryEffect = mlir::LLVM::MemoryEffectsAttr::get(
451 callOp->getContext(), ModRefInfo::NoModRef,
452 ModRefInfo::NoModRef,
453 ModRefInfo::NoModRef,
454 ModRefInfo::NoModRef,
455 ModRefInfo::NoModRef,
456 ModRefInfo::NoModRef);
462 noReturn = callOp->hasAttr(CIRDialect::getNoReturnAttrName());
465static mlir::LLVM::CallIntrinsicOp
467 mlir::Location loc,
const llvm::Twine &intrinsicName,
468 mlir::Type resultTy, mlir::ValueRange operands,
469 mlir::LLVM::FastmathFlags fastmathFlags = {}) {
470 auto intrinsicNameAttr =
471 mlir::StringAttr::get(rewriter.getContext(), intrinsicName);
473 mlir::LLVM::FastmathFlagsAttr::get(rewriter.getContext(), fastmathFlags);
477 return mlir::LLVM::CallIntrinsicOp::create(
478 rewriter, loc, mlir::TypeRange{resultTy}, intrinsicNameAttr, operands,
480 return mlir::LLVM::CallIntrinsicOp::create(rewriter, loc, intrinsicNameAttr,
485 mlir::ConversionPatternRewriter &rewriter, mlir::Operation *op,
486 const llvm::Twine &intrinsicName, mlir::Type resultTy,
487 mlir::ValueRange operands, mlir::LLVM::FastmathFlags fastmathFlags = {}) {
489 rewriter, op->getLoc(), intrinsicName, resultTy, operands, fastmathFlags);
490 rewriter.replaceOp(op, callIntrinOp.getOperation());
495 std::optional<cir::FPDynamicRoundingMode> rounding =
496 fenv.getDynamicRoundingMode();
498 return "round.tonearest";
500 case cir::FPDynamicRoundingMode::ToNearest:
501 return "round.tonearest";
502 case cir::FPDynamicRoundingMode::Downward:
503 return "round.downward";
504 case cir::FPDynamicRoundingMode::Upward:
505 return "round.upward";
506 case cir::FPDynamicRoundingMode::UpwardZero:
507 return "round.towardzero";
508 case cir::FPDynamicRoundingMode::ToNearestAway:
509 return "round.tonearestaway";
510 case cir::FPDynamicRoundingMode::Unknown:
511 return "round.dynamic";
513 llvm_unreachable(
"unknown FP dynamic rounding mode");
517 std::optional<cir::FPExceptionMode> exceptMode = fenv.getExceptMode();
518 if (exceptMode == cir::FPExceptionMode::Masked)
519 return "fpexcept.ignore";
520 mlir::BoolAttr strictExcept = fenv.getStrictExcept();
522 return "fpexcept.ignore";
523 return strictExcept.getValue() ?
"fpexcept.strict" :
"fpexcept.maytrap";
528 mlir::Location loc, llvm::StringRef str) {
529 auto mdString = mlir::LLVM::MDStringAttr::get(
530 rewriter.getContext(), mlir::StringAttr::get(rewriter.getContext(), str));
531 return mlir::LLVM::MetadataAsValueOp::create(rewriter, loc, mdString);
535 mlir::Operation *op, mlir::ValueRange operands, cir::FenvAttr fenv,
536 mlir::Type llvmResTy, mlir::ConversionPatternRewriter &rewriter,
537 llvm::StringRef constrainedMnemonic,
bool hasRoundingMode,
538 mlir::LLVM::FastmathFlags fastmathFlags) {
539 mlir::Location loc = op->getLoc();
548 rewriter, op,
"llvm.experimental.constrained." + constrainedMnemonic,
549 llvmResTy, callOperands, fastmathFlags);
550 return mlir::success();
553template <
typename LLVMOp>
555 mlir::Operation *op, mlir::ValueRange operands, cir::FenvAttr fenv,
556 const mlir::TypeConverter &typeConverter,
557 mlir::ConversionPatternRewriter &rewriter,
558 llvm::StringRef constrainedMnemonic,
bool hasRoundingMode) {
559 mlir::Type llvmResTy = typeConverter.convertType(op->getResultTypes()[0]);
561 return op->emitError(
"expected LLVM result type for floating-point op");
564 rewriter.replaceOpWithNewOp<LLVMOp>(op, llvmResTy, operands);
565 return mlir::success();
569 constrainedMnemonic, hasRoundingMode);
572mlir::LogicalResult CIRToLLVMLLVMIntrinsicCallOpLowering::matchAndRewrite(
573 cir::LLVMIntrinsicCallOp op, OpAdaptor adaptor,
574 mlir::ConversionPatternRewriter &rewriter)
const {
577 mlir::Type llvmResTy;
578 if (op->getNumResults() != 0) {
579 llvmResTy = getTypeConverter()->convertType(op->getResultTypes()[0]);
581 return op.emitError(
"expected LLVM result type");
583 StringRef name = op.getIntrinsicName();
596 adaptor.getOperands());
597 return mlir::success();
601mlir::Value CIRAttrToValue::visitCirAttr(cir::BoolAttr boolAttr) {
602 mlir::Location loc = parentOp->getLoc();
603 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
604 mlir::Value boolVal = mlir::LLVM::ConstantOp::create(
605 rewriter, loc, converter->convertType(boolAttr.getType()),
606 boolAttr.getValue());
607 return emitToMemory(rewriter, layout, boolAttr.getType(), boolVal);
611mlir::Value CIRAttrToValue::visitCirAttr(cir::IntAttr intAttr) {
612 mlir::Location loc = parentOp->getLoc();
613 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
617 mlir::Value val = mlir::LLVM::ConstantOp::create(
618 rewriter, loc, converter->convertType(intAttr.getType()),
620 return emitToMemory(rewriter, layout, intAttr.getType(), val);
624mlir::Value CIRAttrToValue::visitCirAttr(cir::FPAttr fltAttr) {
625 mlir::Location loc = parentOp->getLoc();
626 return mlir::LLVM::ConstantOp::create(
627 rewriter, loc, converter->convertType(fltAttr.getType()),
632mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstComplexAttr complexAttr) {
633 cir::ComplexType
complexType = complexAttr.getType();
634 mlir::Type complexElemTy =
complexType.getElementType();
635 mlir::Type complexElemLLVMTy = converter->convertType(complexElemTy);
637 mlir::Attribute components[2];
638 if (
const auto intType = mlir::dyn_cast<cir::IntType>(complexElemTy)) {
639 components[0] = rewriter.getIntegerAttr(
641 mlir::cast<cir::IntAttr>(complexAttr.getReal()).getValue());
642 components[1] = rewriter.getIntegerAttr(
644 mlir::cast<cir::IntAttr>(complexAttr.getImag()).getValue());
646 components[0] = rewriter.getFloatAttr(
648 mlir::cast<cir::FPAttr>(complexAttr.getReal()).getValue());
649 components[1] = rewriter.getFloatAttr(
651 mlir::cast<cir::FPAttr>(complexAttr.getImag()).getValue());
654 mlir::Location loc = parentOp->getLoc();
655 return mlir::LLVM::ConstantOp::create(
656 rewriter, loc, converter->convertType(complexAttr.getType()),
657 rewriter.getArrayAttr(components));
661mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstPtrAttr ptrAttr) {
662 mlir::Location loc = parentOp->getLoc();
663 if (ptrAttr.isNullValue()) {
664 return mlir::LLVM::ZeroOp::create(
665 rewriter, loc, converter->convertType(ptrAttr.getType()));
667 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
668 mlir::Value ptrVal = mlir::LLVM::ConstantOp::create(
670 rewriter.getIntegerType(layout.getTypeSizeInBits(ptrAttr.getType())),
671 ptrAttr.getValue().getInt());
672 return mlir::LLVM::IntToPtrOp::create(
673 rewriter, loc, converter->convertType(ptrAttr.getType()), ptrVal);
677mlir::Value CIRAttrToValue::visitCirAttr(cir::BlockAddrInfoAttr blockAddrInfo) {
678 assert(blockInfoAddr &&
679 "block address lowering requires LLVMBlockAddressInfo");
684 mlir::Location loc = parentOp->getLoc();
685 mlir::LLVM::BlockTagOp matchLabel =
686 blockInfoAddr->lookupBlockTag(blockAddrInfo);
687 mlir::LLVM::BlockTagAttr tagAttr =
688 matchLabel ? matchLabel.getTag() : mlir::LLVM::BlockTagAttr{};
689 auto blkAddr = mlir::LLVM::BlockAddressAttr::get(
690 rewriter.getContext(), blockAddrInfo.getFunc(), tagAttr);
691 auto blockAddressOp = mlir::LLVM::BlockAddressOp::create(
692 rewriter, loc, mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
695 blockInfoAddr->addUnresolvedBlockAddress(blockAddressOp, blockAddrInfo);
696 return blockAddressOp;
700mlir::Value CIRAttrToValue::visitCirAttr(cir::BlockAddrDiffAttr blockAddrDiff) {
701 assert(blockInfoAddr &&
702 "block address lowering requires LLVMBlockAddressInfo");
708 mlir::Location loc = parentOp->getLoc();
709 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
710 mlir::MLIRContext *ctx = rewriter.getContext();
711 auto ptrTy = mlir::LLVM::LLVMPointerType::get(ctx);
713 auto emitBlockAddr = [&](mlir::StringAttr label) -> mlir::Value {
714 auto info = cir::BlockAddrInfoAttr::get(
715 ctx, blockAddrDiff.getFunc().getValue(), label.getValue());
716 mlir::LLVM::BlockTagOp matchLabel = blockInfoAddr->lookupBlockTag(info);
717 mlir::LLVM::BlockTagAttr tagAttr =
718 matchLabel ? matchLabel.getTag() : mlir::LLVM::BlockTagAttr{};
719 auto blkAddr = mlir::LLVM::BlockAddressAttr::get(
720 ctx, blockAddrDiff.getFunc(), tagAttr);
722 mlir::LLVM::BlockAddressOp::create(rewriter, loc, ptrTy, blkAddr);
724 blockInfoAddr->addUnresolvedBlockAddress(addrOp, info);
728 mlir::Value lhsAddr = emitBlockAddr(blockAddrDiff.getLhsLabel());
729 mlir::Value rhsAddr = emitBlockAddr(blockAddrDiff.getRhsLabel());
735 mlir::Type intptrTy =
736 rewriter.getIntegerType(layout.getTypeSizeInBits(ptrTy));
738 mlir::LLVM::PtrToIntOp::create(rewriter, loc, intptrTy, lhsAddr);
740 mlir::LLVM::PtrToIntOp::create(rewriter, loc, intptrTy, rhsAddr);
741 mlir::Value diffVal =
742 mlir::LLVM::SubOp::create(rewriter, loc, lhsInt, rhsInt);
744 mlir::Type resultTy = converter->convertType(blockAddrDiff.getType());
745 mlir::Value result = diffVal;
746 if (resultTy != intptrTy)
747 result = mlir::LLVM::TruncOp::create(rewriter, loc, resultTy, diffVal);
752mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstArrayAttr attr) {
753 mlir::Type llvmTy = converter->convertType(
attr.getType());
754 mlir::DataLayout dataLayout(parentOp->getParentOfType<mlir::ModuleOp>());
756 mlir::Location loc = parentOp->getLoc();
761 if (std::optional<mlir::Attribute> denseAttr =
763 return mlir::LLVM::ConstantOp::create(rewriter, loc, llvmTy, *denseAttr);
765 if (
attr.hasTrailingZeros())
766 result = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmTy);
768 result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
771 if (
auto arrayAttr = mlir::dyn_cast<mlir::ArrayAttr>(
attr.getElts())) {
772 for (
auto [idx, elt] : llvm::enumerate(arrayAttr)) {
773 mlir::Value init = visit(elt);
775 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
777 }
else if (
auto strAttr = mlir::dyn_cast<mlir::StringAttr>(
attr.getElts())) {
780 auto arrayTy = mlir::dyn_cast<cir::ArrayType>(strAttr.getType());
781 assert(arrayTy &&
"String attribute must have an array type");
782 mlir::Type eltTy = arrayTy.getElementType();
783 for (
auto [idx, elt] : llvm::enumerate(strAttr)) {
784 auto init = mlir::LLVM::ConstantOp::create(
785 rewriter, loc, converter->convertType(eltTy), elt);
787 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
790 llvm_unreachable(
"unexpected ConstArrayAttr elements");
797mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstRecordAttr constRecord) {
798 mlir::Type llvmTy = converter->convertType(constRecord.getType());
799 mlir::DataLayout dataLayout(parentOp->getParentOfType<mlir::ModuleOp>());
800 llvm::SmallVector<unsigned> paddingAddedIndexes;
802 paddingAddedIndexes);
803 const mlir::Location loc = parentOp->getLoc();
804 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
807 auto paddingItr = paddingAddedIndexes.begin();
812 for (
auto [idx, elt] : llvm::enumerate(constRecord.getMembers())) {
813 if (paddingItr != paddingAddedIndexes.end() && *paddingItr == idx) {
818 result = mlir::LLVM::InsertValueOp::create(rewriter, loc, result,
819 visit(elt), insertIdx);
827mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstVectorAttr attr) {
828 const mlir::Type llvmTy = converter->convertType(
attr.getType());
829 const mlir::Location loc = parentOp->getLoc();
831 SmallVector<mlir::Attribute> mlirValues;
832 for (
const mlir::Attribute elementAttr :
attr.getElts()) {
833 mlir::Attribute mlirAttr;
834 if (
auto intAttr = mlir::dyn_cast<cir::IntAttr>(elementAttr)) {
835 mlirAttr = rewriter.getIntegerAttr(
836 converter->convertType(intAttr.getType()), intAttr.getValue());
837 }
else if (
auto floatAttr = mlir::dyn_cast<cir::FPAttr>(elementAttr)) {
838 mlirAttr = rewriter.getFloatAttr(
839 converter->convertType(floatAttr.getType()), floatAttr.getValue());
840 }
else if (
auto boolAttr = mlir::dyn_cast<cir::BoolAttr>(elementAttr)) {
841 mlirAttr = rewriter.getBoolAttr(boolAttr.getValue());
843 llvm_unreachable(
"vector constant with an element that is neither an "
844 "int, a float, or a bool");
846 mlirValues.push_back(mlirAttr);
849 return mlir::LLVM::ConstantOp::create(
850 rewriter, loc, llvmTy,
851 mlir::DenseElementsAttr::get(mlir::cast<mlir::ShapedType>(llvmTy),
856CIRAttrToValue::LoweredGlobalSymbol
857CIRAttrToValue::getAddressOfSymbol(mlir::FlatSymbolRefAttr symbol) {
858 auto moduleOp = parentOp->getParentOfType<mlir::ModuleOp>();
859 mlir::DataLayout dataLayout(moduleOp);
860 mlir::Type sourceType;
861 unsigned addrSpace = 0;
862 llvm::StringRef symName;
863 mlir::Operation *sourceSymbol = symbolTables.lookupSymbolIn(moduleOp, symbol);
864 if (
auto llvmSymbol = dyn_cast<mlir::LLVM::GlobalOp>(sourceSymbol)) {
865 sourceType = llvmSymbol.getType();
866 symName = llvmSymbol.getSymName();
867 addrSpace = llvmSymbol.getAddrSpace();
868 }
else if (
auto cirSymbol = dyn_cast<cir::GlobalOp>(sourceSymbol)) {
871 symName = cirSymbol.getSymName();
872 if (
auto targetAS = mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
873 cirSymbol.getAddrSpaceAttr()))
874 addrSpace = targetAS.getValue();
875 }
else if (
auto llvmFun = dyn_cast<mlir::LLVM::LLVMFuncOp>(sourceSymbol)) {
876 sourceType = llvmFun.getFunctionType();
877 symName = llvmFun.getSymName();
878 }
else if (
auto fun = dyn_cast<cir::FuncOp>(sourceSymbol)) {
879 sourceType = converter->convertType(fun.getFunctionType());
880 symName = fun.getSymName();
881 }
else if (
auto alias = dyn_cast<mlir::LLVM::AliasOp>(sourceSymbol)) {
882 sourceType = alias.getType();
883 symName = alias.getSymName();
885 llvm_unreachable(
"Unexpected GlobalOp type");
888 mlir::Location loc = parentOp->getLoc();
889 mlir::Value addr = mlir::LLVM::AddressOfOp::create(
891 mlir::LLVM::LLVMPointerType::get(rewriter.getContext(), addrSpace),
893 return {addr, sourceType, addrSpace};
896mlir::Value CIRAttrToValue::castGlobalAddrToType(mlir::Value addr,
898 mlir::Type sourceType,
899 unsigned addrSpace) {
900 mlir::Location loc = parentOp->getLoc();
906 if (mlir::isa<cir::IntType>(attrType)) {
907 mlir::Type llvmDstTy = converter->convertType(attrType);
908 return mlir::LLVM::PtrToIntOp::create(rewriter, loc, llvmDstTy, addr);
911 if (
auto ptrTy = mlir::dyn_cast<cir::PointerType>(attrType)) {
912 auto llvmDstTy = converter->convertType<mlir::LLVM::LLVMPointerType>(ptrTy);
914 if (llvmDstTy.getAddressSpace() != addrSpace)
916 mlir::LLVM::AddrSpaceCastOp::create(rewriter, loc, llvmDstTy, addr);
918 auto moduleOp = parentOp->getParentOfType<mlir::ModuleOp>();
919 mlir::DataLayout dataLayout(moduleOp);
920 mlir::Type llvmEltTy =
924 if (llvmEltTy == sourceType)
930 if (addr.getType() == llvmDstTy)
933 return mlir::LLVM::BitcastOp::create(rewriter, loc, llvmDstTy, addr);
936 if (mlir::isa<cir::VPtrType>(attrType))
939 llvm_unreachable(
"Expecting pointer or integer type");
942mlir::Value CIRAttrToValue::visitCirAttr(cir::GlobalViewAttr globalAttr) {
943 LoweredGlobalSymbol lowered = getAddressOfSymbol(globalAttr.getSymbol());
944 mlir::Value addrOp = lowered.addr;
945 mlir::Type sourceType = lowered.sourceType;
947 if (globalAttr.getIndices()) {
948 llvm::SmallVector<mlir::LLVM::GEPArg> indices;
950 if (mlir::isa<mlir::LLVM::LLVMArrayType, mlir::LLVM::LLVMStructType>(
952 indices.push_back(0);
954 for (mlir::Attribute idx : globalAttr.getIndices()) {
955 auto intAttr = mlir::cast<mlir::IntegerAttr>(idx);
956 indices.push_back(intAttr.getValue().getSExtValue());
958 mlir::Type resTy = addrOp.getType();
959 mlir::Type eltTy = converter->convertType(sourceType);
960 addrOp = mlir::LLVM::GEPOp::create(rewriter, parentOp->getLoc(), resTy,
961 eltTy, addrOp, indices,
962 mlir::LLVM::GEPNoWrapFlags::none);
965 return castGlobalAddrToType(addrOp, globalAttr.getType(), sourceType,
969mlir::Value CIRAttrToValue::visitCirAttr(cir::GlobalOffsetAttr globalAttr) {
970 LoweredGlobalSymbol lowered = getAddressOfSymbol(globalAttr.getSymbol());
971 mlir::Value addrOp = lowered.addr;
972 mlir::Location loc = parentOp->getLoc();
976 mlir::Value offset = mlir::LLVM::ConstantOp::create(
977 rewriter, loc, rewriter.getI64Type(),
978 rewriter.getI64IntegerAttr(globalAttr.getOffset()));
979 addrOp = mlir::LLVM::GEPOp::create(
980 rewriter, loc, addrOp.getType(), rewriter.getI8Type(), addrOp,
981 mlir::ValueRange{offset}, mlir::LLVM::GEPNoWrapFlags::none);
983 return castGlobalAddrToType(addrOp, globalAttr.getType(), lowered.sourceType,
988mlir::Value CIRAttrToValue::visitCirAttr(cir::TypeInfoAttr typeInfoAttr) {
989 mlir::Type llvmTy = converter->convertType(typeInfoAttr.getType());
990 mlir::Location loc = parentOp->getLoc();
991 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
993 for (
auto [idx, elt] : llvm::enumerate(typeInfoAttr.getData())) {
994 mlir::Value init = visit(elt);
996 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
1003mlir::Value CIRAttrToValue::visitCirAttr(cir::UndefAttr undefAttr) {
1004 mlir::Location loc = parentOp->getLoc();
1005 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
1006 return mlir::LLVM::UndefOp::create(
1012mlir::Value CIRAttrToValue::visitCirAttr(cir::PoisonAttr poisonAttr) {
1013 mlir::Location loc = parentOp->getLoc();
1014 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
1015 return mlir::LLVM::PoisonOp::create(
1021mlir::Value CIRAttrToValue::visitCirAttr(cir::VTableAttr vtableArr) {
1022 mlir::Type llvmTy = converter->convertType(vtableArr.getType());
1023 mlir::Location loc = parentOp->getLoc();
1024 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
1026 for (
auto [idx, elt] : llvm::enumerate(vtableArr.getData())) {
1027 mlir::Value init = visit(elt);
1029 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
1036mlir::Value CIRAttrToValue::visitCirAttr(cir::ZeroAttr attr) {
1037 mlir::Location loc = parentOp->getLoc();
1038 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
1039 return mlir::LLVM::ZeroOp::create(
1048 mlir::ConversionPatternRewriter &rewriter)
1049 : llvmType(type), rewriter(rewriter) {}
1052 return llvm::TypeSwitch<mlir::Attribute, mlir::Attribute>(
attr)
1053 .Case<cir::IntAttr, cir::FPAttr, cir::BoolAttr>(
1055 .
Default([&](
auto attrT) {
return mlir::Attribute(); });
1062 llvm::APInt val =
attr.getValue();
1063 auto destTy = mlir::cast<mlir::IntegerType>(llvmType);
1064 if (val.getBitWidth() != destTy.getWidth()) {
1065 cir::IntTypeInterface cirIntTy =
attr.getType();
1066 val = cirIntTy.isSigned() ? val.sext(destTy.getWidth())
1067 : val.zext(destTy.getWidth());
1069 return rewriter.getIntegerAttr(llvmType, val);
1073 return rewriter.getFloatAttr(llvmType,
attr.getValue());
1077 return rewriter.getBoolAttr(
attr.getValue());
1081 mlir::Type llvmType;
1082 mlir::ConversionPatternRewriter &rewriter;
1090 :
public mlir::PassWrapper<ConvertCIRToLLVMPass,
1091 mlir::OperationPass<mlir::ModuleOp>> {
1093 registry.insert<mlir::BuiltinDialect, mlir::DLTIDialect,
1094 mlir::LLVM::LLVMDialect, mlir::func::FuncDialect>();
1112 return "Convert the prepared CIR dialect module to LLVM dialect";
1119 struct CollectedAnnotation {
1120 mlir::StringAttr symName;
1121 cir::AnnotationAttr annotation;
1123 CollectedAnnotation(mlir::StringAttr symName,
1124 cir::AnnotationAttr annotation, mlir::Location loc)
1125 : symName(symName), annotation(annotation), loc(loc) {}
1130mlir::LogicalResult CIRToLLVMIsFPClassOpLowering::matchAndRewrite(
1131 cir::IsFPClassOp op, OpAdaptor adaptor,
1132 mlir::ConversionPatternRewriter &rewriter)
const {
1133 mlir::Value src = adaptor.getSrc();
1134 cir::FPClassTest flags = adaptor.getFlags();
1135 mlir::IntegerType retTy = rewriter.getI1Type();
1137 rewriter.replaceOpWithNewOp<mlir::LLVM::IsFPClass>(
1138 op, retTy, src,
static_cast<uint32_t>(flags));
1139 return mlir::success();
1142mlir::LogicalResult CIRToLLVMSignBitOpLowering::matchAndRewrite(
1143 cir::SignBitOp op, OpAdaptor adaptor,
1144 mlir::ConversionPatternRewriter &rewriter)
const {
1147 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
1148 int width = layout.getTypeSizeInBits(op.getInput().getType());
1149 if (
auto longDoubleType =
1150 mlir::dyn_cast<cir::LongDoubleType>(op.getInput().getType())) {
1151 if (mlir::isa<cir::FP80Type>(longDoubleType.getUnderlying())) {
1159 mlir::Type intTy = mlir::IntegerType::get(rewriter.getContext(), width);
1160 auto bitcast = mlir::LLVM::BitcastOp::create(rewriter, op->getLoc(), intTy,
1161 adaptor.getInput());
1163 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op->getLoc(), intTy, 0);
1164 auto cmpResult = mlir::LLVM::ICmpOp::create(rewriter, op.getLoc(),
1165 mlir::LLVM::ICmpPredicate::slt,
1166 bitcast.getResult(), zero);
1167 rewriter.replaceOp(op, cmpResult);
1168 return mlir::success();
1171mlir::LogicalResult CIRToLLVMAssumeOpLowering::matchAndRewrite(
1172 cir::AssumeOp op, OpAdaptor adaptor,
1173 mlir::ConversionPatternRewriter &rewriter)
const {
1174 mlir::Value cond = adaptor.getPredicate();
1175 if (op.getBundleKind() == cir::AssumeBundleKind::None) {
1176 rewriter.replaceOpWithNewOp<mlir::LLVM::AssumeOp>(op, cond);
1177 return mlir::success();
1180 llvm::StringRef tag = cir::stringifyAssumeBundleKind(op.getBundleKind());
1181 rewriter.replaceOpWithNewOp<mlir::LLVM::AssumeOp>(op, cond, tag,
1182 adaptor.getBundleArgs());
1183 return mlir::success();
1186static mlir::LLVM::AtomicOrdering
1189 return mlir::LLVM::AtomicOrdering::not_atomic;
1190 switch (*memorder) {
1191 case cir::MemOrder::Relaxed:
1192 return mlir::LLVM::AtomicOrdering::monotonic;
1193 case cir::MemOrder::Consume:
1194 case cir::MemOrder::Acquire:
1195 return mlir::LLVM::AtomicOrdering::acquire;
1196 case cir::MemOrder::Release:
1197 return mlir::LLVM::AtomicOrdering::release;
1198 case cir::MemOrder::AcquireRelease:
1199 return mlir::LLVM::AtomicOrdering::acq_rel;
1200 case cir::MemOrder::SequentiallyConsistent:
1201 return mlir::LLVM::AtomicOrdering::seq_cst;
1203 llvm_unreachable(
"unknown memory order");
1207 switch (syncScope) {
1208 case cir::SyncScopeKind::SingleThread:
1209 return "singlethread";
1210 case cir::SyncScopeKind::Workgroup:
1217static std::optional<llvm::StringRef>
1219 if (syncScope.has_value())
1221 return std::nullopt;
1224mlir::LogicalResult CIRToLLVMAtomicCmpXchgOpLowering::matchAndRewrite(
1225 cir::AtomicCmpXchgOp op, OpAdaptor adaptor,
1226 mlir::ConversionPatternRewriter &rewriter)
const {
1227 mlir::Value expected = adaptor.getExpected();
1228 mlir::Value desired = adaptor.getDesired();
1230 auto cmpxchg = mlir::LLVM::AtomicCmpXchgOp::create(
1231 rewriter, op.getLoc(), adaptor.getPtr(), expected, desired,
1236 cmpxchg.setAlignment(adaptor.getAlignment());
1237 cmpxchg.setWeak(adaptor.getWeak());
1238 cmpxchg.setVolatile_(adaptor.getIsVolatile());
1241 auto old = mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(),
1242 cmpxchg.getResult(), 0);
1243 auto cmp = mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(),
1244 cmpxchg.getResult(), 1);
1246 rewriter.replaceOp(op, {old, cmp});
1247 return mlir::success();
1250mlir::LogicalResult CIRToLLVMAtomicXchgOpLowering::matchAndRewrite(
1251 cir::AtomicXchgOp op, OpAdaptor adaptor,
1252 mlir::ConversionPatternRewriter &rewriter)
const {
1254 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(adaptor.getMemOrder());
1256 rewriter.replaceOpWithNewOp<mlir::LLVM::AtomicRMWOp>(
1257 op, mlir::LLVM::AtomicBinOp::xchg, adaptor.getPtr(), adaptor.getVal(),
1258 llvmOrder, llvmSyncScope);
1259 return mlir::success();
1262mlir::LogicalResult CIRToLLVMAtomicTestAndSetOpLowering::matchAndRewrite(
1263 cir::AtomicTestAndSetOp op, OpAdaptor adaptor,
1264 mlir::ConversionPatternRewriter &rewriter)
const {
1267 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
1269 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1270 rewriter.getI8Type(), 1);
1271 auto rmw = mlir::LLVM::AtomicRMWOp::create(
1272 rewriter, op.getLoc(), mlir::LLVM::AtomicBinOp::xchg, adaptor.getPtr(),
1273 one, llvmOrder, llvm::StringRef(),
1274 adaptor.getAlignment().value_or(0), op.getIsVolatile());
1276 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1277 rewriter.getI8Type(), 0);
1278 auto cmp = mlir::LLVM::ICmpOp::create(
1279 rewriter, op.getLoc(), mlir::LLVM::ICmpPredicate::ne, rmw, zero);
1281 rewriter.replaceOp(op, cmp);
1282 return mlir::success();
1285mlir::LogicalResult CIRToLLVMAtomicClearOpLowering::matchAndRewrite(
1286 cir::AtomicClearOp op, OpAdaptor adaptor,
1287 mlir::ConversionPatternRewriter &rewriter)
const {
1290 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
1291 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1292 rewriter.getI8Type(), 0);
1293 auto store = mlir::LLVM::StoreOp::create(
1294 rewriter, op.getLoc(), zero, adaptor.getPtr(),
1295 adaptor.getAlignment().value_or(0), op.getIsVolatile(),
1296 false,
false, llvmOrder);
1298 rewriter.replaceOp(op, store);
1299 return mlir::success();
1302mlir::LogicalResult CIRToLLVMAtomicFenceOpLowering::matchAndRewrite(
1303 cir::AtomicFenceOp op, OpAdaptor adaptor,
1304 mlir::ConversionPatternRewriter &rewriter)
const {
1305 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(adaptor.getOrdering());
1307 auto fence = mlir::LLVM::FenceOp::create(rewriter, op.getLoc(), llvmOrder);
1310 rewriter.replaceOp(op, fence);
1312 return mlir::success();
1315static mlir::LLVM::AtomicBinOp
1318 case cir::AtomicFetchKind::Add:
1319 return isInt ? mlir::LLVM::AtomicBinOp::add : mlir::LLVM::AtomicBinOp::fadd;
1320 case cir::AtomicFetchKind::Sub:
1321 return isInt ? mlir::LLVM::AtomicBinOp::sub : mlir::LLVM::AtomicBinOp::fsub;
1322 case cir::AtomicFetchKind::And:
1323 return mlir::LLVM::AtomicBinOp::_and;
1324 case cir::AtomicFetchKind::Xor:
1325 return mlir::LLVM::AtomicBinOp::_xor;
1326 case cir::AtomicFetchKind::Or:
1327 return mlir::LLVM::AtomicBinOp::_or;
1328 case cir::AtomicFetchKind::Nand:
1329 return mlir::LLVM::AtomicBinOp::nand;
1330 case cir::AtomicFetchKind::Max: {
1332 return mlir::LLVM::AtomicBinOp::fmax;
1333 return isSignedInt ? mlir::LLVM::AtomicBinOp::max
1334 : mlir::LLVM::AtomicBinOp::umax;
1336 case cir::AtomicFetchKind::Min: {
1338 return mlir::LLVM::AtomicBinOp::fmin;
1339 return isSignedInt ? mlir::LLVM::AtomicBinOp::min
1340 : mlir::LLVM::AtomicBinOp::umin;
1342 case cir::AtomicFetchKind::UIncWrap:
1343 return mlir::LLVM::AtomicBinOp::uinc_wrap;
1344 case cir::AtomicFetchKind::UDecWrap:
1345 return mlir::LLVM::AtomicBinOp::udec_wrap;
1346 case cir::AtomicFetchKind::Maximum:
1347 return mlir::LLVM::AtomicBinOp::fmaximum;
1348 case cir::AtomicFetchKind::Minimum:
1349 return mlir::LLVM::AtomicBinOp::fminimum;
1350 case cir::AtomicFetchKind::MaximumNum:
1351 return mlir::LLVM::AtomicBinOp::fmaximumnum;
1352 case cir::AtomicFetchKind::MinimumNum:
1353 return mlir::LLVM::AtomicBinOp::fminimumnum;
1355 llvm_unreachable(
"Unknown atomic fetch opcode");
1361 case cir::AtomicFetchKind::Add:
1362 return isInt ? mlir::LLVM::AddOp::getOperationName()
1363 : mlir::LLVM::FAddOp::getOperationName();
1364 case cir::AtomicFetchKind::Sub:
1365 return isInt ? mlir::LLVM::SubOp::getOperationName()
1366 : mlir::LLVM::FSubOp::getOperationName();
1367 case cir::AtomicFetchKind::And:
1368 return mlir::LLVM::AndOp::getOperationName();
1369 case cir::AtomicFetchKind::Xor:
1370 return mlir::LLVM::XOrOp::getOperationName();
1371 case cir::AtomicFetchKind::Or:
1372 return mlir::LLVM::OrOp::getOperationName();
1373 case cir::AtomicFetchKind::Nand:
1375 return mlir::LLVM::AndOp::getOperationName();
1376 case cir::AtomicFetchKind::Max:
1377 case cir::AtomicFetchKind::Min:
1378 llvm_unreachable(
"handled in buildMinMaxPostOp");
1379 case cir::AtomicFetchKind::UIncWrap:
1380 case cir::AtomicFetchKind::UDecWrap:
1381 case cir::AtomicFetchKind::Maximum:
1382 case cir::AtomicFetchKind::Minimum:
1383 case cir::AtomicFetchKind::MaximumNum:
1384 case cir::AtomicFetchKind::MinimumNum:
1385 llvm_unreachable(
"uinc_wrap, udec_wrap, maximum, minimum, maximum_num, and "
1386 "minimum_num are always fetch_first");
1388 llvm_unreachable(
"Unknown atomic fetch opcode");
1391mlir::Value CIRToLLVMAtomicFetchOpLowering::buildPostOp(
1392 cir::AtomicFetchOp op, OpAdaptor adaptor,
1393 mlir::ConversionPatternRewriter &rewriter, mlir::Value rmwVal,
1398 .create(op.getLoc(),
1399 rewriter.getStringAttr(
1401 atomicOperands, atomicResTys, {})
1405mlir::Value CIRToLLVMAtomicFetchOpLowering::buildMinMaxPostOp(
1406 cir::AtomicFetchOp op, OpAdaptor adaptor,
1407 mlir::ConversionPatternRewriter &rewriter, mlir::Value rmwVal,
bool isInt,
1408 bool isSigned)
const {
1409 mlir::Location loc = op.getLoc();
1412 if (op.getBinop() == cir::AtomicFetchKind::Max)
1413 return mlir::LLVM::MaxNumOp::create(rewriter, loc, rmwVal,
1415 return mlir::LLVM::MinNumOp::create(rewriter, loc, rmwVal,
1419 mlir::LLVM::ICmpPredicate pred;
1420 if (op.getBinop() == cir::AtomicFetchKind::Max) {
1421 pred = isSigned ? mlir::LLVM::ICmpPredicate::sgt
1422 : mlir::LLVM::ICmpPredicate::ugt;
1424 pred = isSigned ? mlir::LLVM::ICmpPredicate::slt
1425 : mlir::LLVM::ICmpPredicate::ult;
1427 mlir::Value cmp = mlir::LLVM::ICmpOp::create(
1429 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(), pred), rmwVal,
1431 return mlir::LLVM::SelectOp::create(rewriter, loc, cmp, rmwVal,
1435mlir::LogicalResult CIRToLLVMAtomicFetchOpLowering::matchAndRewrite(
1436 cir::AtomicFetchOp op, OpAdaptor adaptor,
1437 mlir::ConversionPatternRewriter &rewriter)
const {
1439 bool isSignedInt =
false;
1440 if (
auto intTy = mlir::dyn_cast<cir::IntType>(op.getVal().getType())) {
1442 isSignedInt = intTy.isSigned();
1443 }
else if (mlir::isa<cir::SingleType, cir::DoubleType>(
1444 op.getVal().getType())) {
1447 return op.emitError() <<
"Unsupported type: " << op.getVal().getType();
1450 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
1452 mlir::LLVM::AtomicBinOp llvmBinOp =
1454 auto rmwVal = mlir::LLVM::AtomicRMWOp::create(
1455 rewriter, op.getLoc(), llvmBinOp, adaptor.getPtr(), adaptor.getVal(),
1456 llvmOrder, llvmSyncScope);
1458 mlir::Value result = rmwVal.getResult();
1459 if (!op.getFetchFirst()) {
1460 if (op.getBinop() == cir::AtomicFetchKind::Max ||
1461 op.getBinop() == cir::AtomicFetchKind::Min)
1462 result = buildMinMaxPostOp(op, adaptor, rewriter, rmwVal.getRes(), isInt,
1465 result = buildPostOp(op, adaptor, rewriter, rmwVal.getRes(), isInt);
1468 if (op.getBinop() == cir::AtomicFetchKind::Nand) {
1469 auto negOne = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1470 result.getType(), -1);
1471 result = mlir::LLVM::XOrOp::create(rewriter, op.getLoc(), result, negOne);
1475 rewriter.replaceOp(op, result);
1476 return mlir::success();
1479mlir::LogicalResult CIRToLLVMBitClrsbOpLowering::matchAndRewrite(
1480 cir::BitClrsbOp op, OpAdaptor adaptor,
1481 mlir::ConversionPatternRewriter &rewriter)
const {
1482 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1483 adaptor.getInput().getType(), 0);
1484 auto isNeg = mlir::LLVM::ICmpOp::create(
1485 rewriter, op.getLoc(),
1486 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(),
1487 mlir::LLVM::ICmpPredicate::slt),
1488 adaptor.getInput(), zero);
1490 auto negOne = mlir::LLVM::ConstantOp::create(
1491 rewriter, op.getLoc(), adaptor.getInput().getType(), -1);
1492 auto flipped = mlir::LLVM::XOrOp::create(rewriter, op.getLoc(),
1493 adaptor.getInput(), negOne);
1495 auto select = mlir::LLVM::SelectOp::create(rewriter, op.getLoc(), isNeg,
1496 flipped, adaptor.getInput());
1498 auto resTy = getTypeConverter()->convertType(op.getType());
1499 auto clz = mlir::LLVM::CountLeadingZerosOp::create(
1500 rewriter, op.getLoc(), resTy,
select,
false);
1502 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1503 auto res = mlir::LLVM::SubOp::create(rewriter, op.getLoc(),
clz, one,
1504 mlir::LLVM::IntegerOverflowFlags::nuw);
1505 rewriter.replaceOp(op, res);
1507 return mlir::LogicalResult::success();
1510mlir::LogicalResult CIRToLLVMBitClzOpLowering::matchAndRewrite(
1511 cir::BitClzOp op, OpAdaptor adaptor,
1512 mlir::ConversionPatternRewriter &rewriter)
const {
1513 auto resTy = getTypeConverter()->convertType(op.getType());
1514 auto llvmOp = mlir::LLVM::CountLeadingZerosOp::create(
1515 rewriter, op.getLoc(), resTy, adaptor.getInput(), op.getPoisonZero());
1516 rewriter.replaceOp(op, llvmOp);
1517 return mlir::LogicalResult::success();
1520mlir::LogicalResult CIRToLLVMBitCtzOpLowering::matchAndRewrite(
1521 cir::BitCtzOp op, OpAdaptor adaptor,
1522 mlir::ConversionPatternRewriter &rewriter)
const {
1523 auto resTy = getTypeConverter()->convertType(op.getType());
1524 auto llvmOp = mlir::LLVM::CountTrailingZerosOp::create(
1525 rewriter, op.getLoc(), resTy, adaptor.getInput(), op.getPoisonZero());
1526 rewriter.replaceOp(op, llvmOp);
1527 return mlir::LogicalResult::success();
1530mlir::LogicalResult CIRToLLVMBitFfsOpLowering::matchAndRewrite(
1531 cir::BitFfsOp op, OpAdaptor adaptor,
1532 mlir::ConversionPatternRewriter &rewriter)
const {
1533 auto resTy = getTypeConverter()->convertType(op.getType());
1534 auto ctz = mlir::LLVM::CountTrailingZerosOp::create(rewriter, op.getLoc(),
1535 resTy, adaptor.getInput(),
1538 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1539 auto ctzAddOne = mlir::LLVM::AddOp::create(rewriter, op.getLoc(),
ctz, one);
1541 auto zeroInputTy = mlir::LLVM::ConstantOp::create(
1542 rewriter, op.getLoc(), adaptor.getInput().getType(), 0);
1543 auto isZero = mlir::LLVM::ICmpOp::create(
1544 rewriter, op.getLoc(),
1545 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(),
1546 mlir::LLVM::ICmpPredicate::eq),
1547 adaptor.getInput(), zeroInputTy);
1549 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 0);
1550 auto res = mlir::LLVM::SelectOp::create(rewriter, op.getLoc(), isZero, zero,
1552 rewriter.replaceOp(op, res);
1554 return mlir::LogicalResult::success();
1557mlir::LogicalResult CIRToLLVMBitParityOpLowering::matchAndRewrite(
1558 cir::BitParityOp op, OpAdaptor adaptor,
1559 mlir::ConversionPatternRewriter &rewriter)
const {
1560 auto resTy = getTypeConverter()->convertType(op.getType());
1561 auto popcnt = mlir::LLVM::CtPopOp::create(rewriter, op.getLoc(), resTy,
1562 adaptor.getInput());
1564 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1566 mlir::LLVM::AndOp::create(rewriter, op.getLoc(), popcnt, one);
1567 rewriter.replaceOp(op, popcntMod2);
1569 return mlir::LogicalResult::success();
1572mlir::LogicalResult CIRToLLVMBitPopcountOpLowering::matchAndRewrite(
1573 cir::BitPopcountOp op, OpAdaptor adaptor,
1574 mlir::ConversionPatternRewriter &rewriter)
const {
1575 auto resTy = getTypeConverter()->convertType(op.getType());
1576 auto llvmOp = mlir::LLVM::CtPopOp::create(rewriter, op.getLoc(), resTy,
1577 adaptor.getInput());
1578 rewriter.replaceOp(op, llvmOp);
1579 return mlir::LogicalResult::success();
1582mlir::LogicalResult CIRToLLVMBrCondOpLowering::matchAndRewrite(
1583 cir::BrCondOp brOp, OpAdaptor adaptor,
1584 mlir::ConversionPatternRewriter &rewriter)
const {
1589 mlir::Value i1Condition = adaptor.getCond();
1591 rewriter.replaceOpWithNewOp<mlir::LLVM::CondBrOp>(
1592 brOp, i1Condition, brOp.getDestTrue(), adaptor.getDestOperandsTrue(),
1593 brOp.getDestFalse(), adaptor.getDestOperandsFalse());
1595 return mlir::success();
1598mlir::Type CIRToLLVMCastOpLowering::convertTy(mlir::Type ty)
const {
1599 return getTypeConverter()->convertType(ty);
1602mlir::LogicalResult CIRToLLVMCastOpLowering::matchAndRewrite(
1603 cir::CastOp castOp, OpAdaptor adaptor,
1604 mlir::ConversionPatternRewriter &rewriter)
const {
1609 switch (castOp.getKind()) {
1610 case cir::CastKind::array_to_ptrdecay: {
1611 const auto ptrTy = mlir::cast<cir::PointerType>(castOp.getType());
1612 mlir::Value sourceValue = adaptor.getSrc();
1613 mlir::Type targetType = convertTy(ptrTy);
1615 ptrTy.getPointee());
1616 llvm::SmallVector<mlir::LLVM::GEPArg> offset{0};
1617 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1618 castOp, targetType, elementTy, sourceValue, offset);
1621 case cir::CastKind::int_to_bool: {
1622 mlir::Value llvmSrcVal = adaptor.getSrc();
1626 mlir::Value zeroInt = mlir::LLVM::ConstantOp::create(
1627 rewriter, castOp.getLoc(), llvmSrcVal.getType(),
1628 rewriter.getZeroAttr(llvmSrcVal.getType()));
1629 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
1630 castOp, mlir::LLVM::ICmpPredicate::ne, llvmSrcVal, zeroInt);
1633 case cir::CastKind::integral: {
1634 mlir::Type srcType = castOp.getSrc().getType();
1635 mlir::Type dstType = castOp.getType();
1636 mlir::Value llvmSrcVal = adaptor.getSrc();
1637 mlir::Type llvmDstType = getTypeConverter()->convertType(dstType);
1638 cir::IntType srcIntType =
1639 mlir::cast<cir::IntType>(elementTypeIfVector(srcType));
1640 cir::IntType dstIntType =
1641 mlir::cast<cir::IntType>(elementTypeIfVector(dstType));
1642 rewriter.replaceOp(castOp,
getLLVMIntCast(rewriter, llvmSrcVal, llvmDstType,
1643 srcIntType.isUnsigned(),
1644 srcIntType.getWidth(),
1645 dstIntType.getWidth()));
1648 case cir::CastKind::floating: {
1649 mlir::Value llvmSrcVal = adaptor.getSrc();
1650 mlir::Type llvmDstTy = getTypeConverter()->convertType(castOp.getType());
1652 mlir::Type srcTy = elementTypeIfVector(castOp.getSrc().getType());
1653 mlir::Type dstTy = elementTypeIfVector(castOp.getType());
1655 if (!mlir::isa<cir::FPTypeInterface>(dstTy) ||
1656 !mlir::isa<cir::FPTypeInterface>(srcTy))
1657 return castOp.emitError() <<
"NYI cast from " << srcTy <<
" to " << dstTy;
1659 auto getFloatWidth = [](mlir::Type ty) ->
unsigned {
1660 return mlir::cast<cir::FPTypeInterface>(ty).getWidth();
1663 bool isTrunc = getFloatWidth(srcTy) > getFloatWidth(dstTy);
1664 if (cir::FenvAttr fenv = castOp.getFenvAttr()) {
1668 castOp, llvmSrcVal, fenv, llvmDstTy, rewriter,
1669 isTrunc ?
"fptrunc" :
"fpext", isTrunc);
1672 rewriter.replaceOpWithNewOp<mlir::LLVM::FPTruncOp>(castOp, llvmDstTy,
1675 rewriter.replaceOpWithNewOp<mlir::LLVM::FPExtOp>(castOp, llvmDstTy,
1677 return mlir::success();
1679 case cir::CastKind::int_to_ptr: {
1680 auto dstTy = mlir::cast<cir::PointerType>(castOp.getType());
1681 mlir::Value llvmSrcVal = adaptor.getSrc();
1682 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1683 rewriter.replaceOpWithNewOp<mlir::LLVM::IntToPtrOp>(castOp, llvmDstTy,
1685 return mlir::success();
1687 case cir::CastKind::ptr_to_int: {
1688 auto dstTy = mlir::cast<cir::IntType>(castOp.getType());
1689 mlir::Value llvmSrcVal = adaptor.getSrc();
1690 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1691 rewriter.replaceOpWithNewOp<mlir::LLVM::PtrToIntOp>(castOp, llvmDstTy,
1693 return mlir::success();
1695 case cir::CastKind::float_to_bool: {
1696 mlir::Value llvmSrcVal = adaptor.getSrc();
1697 auto kind = mlir::LLVM::FCmpPredicate::une;
1702 auto zeroFloat = mlir::LLVM::ConstantOp::create(
1703 rewriter, castOp.getLoc(), llvmSrcVal.getType(),
1704 rewriter.getZeroAttr(llvmSrcVal.getType()));
1707 rewriter.replaceOpWithNewOp<mlir::LLVM::FCmpOp>(castOp,
kind, llvmSrcVal,
1710 return mlir::success();
1712 case cir::CastKind::bool_to_int: {
1713 mlir::Type dstTy = castOp.getType();
1714 mlir::Value llvmSrcVal = adaptor.getSrc();
1715 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1717 auto srcElemTy = mlir::cast<mlir::IntegerType>(
1718 elementTypeIfVector(llvmSrcVal.getType()));
1719 auto dstElemTy = mlir::cast<cir::IntType>(elementTypeIfVector(dstTy));
1721 if (srcElemTy.getWidth() == dstElemTy.getWidth())
1722 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(castOp, llvmDstTy,
1725 rewriter.replaceOpWithNewOp<mlir::LLVM::ZExtOp>(castOp, llvmDstTy,
1727 return mlir::success();
1729 case cir::CastKind::bool_to_float: {
1730 mlir::Type dstTy = castOp.getType();
1731 mlir::Value llvmSrcVal = adaptor.getSrc();
1732 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1733 rewriter.replaceOpWithNewOp<mlir::LLVM::UIToFPOp>(castOp, llvmDstTy,
1735 return mlir::success();
1737 case cir::CastKind::int_to_float: {
1738 mlir::Type dstTy = castOp.getType();
1739 mlir::Value llvmSrcVal = adaptor.getSrc();
1740 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1742 mlir::cast<cir::IntType>(elementTypeIfVector(castOp.getSrc().getType()))
1744 if (cir::FenvAttr fenv = castOp.getFenvAttr()) {
1746 castOp, llvmSrcVal, fenv, llvmDstTy, rewriter,
1747 isSigned ?
"sitofp" :
"uitofp",
true);
1750 rewriter.replaceOpWithNewOp<mlir::LLVM::SIToFPOp>(castOp, llvmDstTy,
1753 rewriter.replaceOpWithNewOp<mlir::LLVM::UIToFPOp>(castOp, llvmDstTy,
1755 return mlir::success();
1757 case cir::CastKind::float_to_int: {
1758 mlir::Type dstTy = castOp.getType();
1759 mlir::Value llvmSrcVal = adaptor.getSrc();
1760 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1762 mlir::cast<cir::IntType>(elementTypeIfVector(castOp.getType()))
1764 if (cir::FenvAttr fenv = castOp.getFenvAttr()) {
1766 castOp, llvmSrcVal, fenv, llvmDstTy, rewriter,
1767 isSigned ?
"fptosi" :
"fptoui",
false);
1770 rewriter.replaceOpWithNewOp<mlir::LLVM::FPToSIOp>(castOp, llvmDstTy,
1773 rewriter.replaceOpWithNewOp<mlir::LLVM::FPToUIOp>(castOp, llvmDstTy,
1775 return mlir::success();
1777 case cir::CastKind::bitcast: {
1778 mlir::Type dstTy = castOp.getType();
1779 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1784 mlir::Value llvmSrcVal = adaptor.getSrc();
1785 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(castOp, llvmDstTy,
1787 return mlir::success();
1789 case cir::CastKind::ptr_to_bool: {
1790 mlir::Value llvmSrcVal = adaptor.getSrc();
1791 mlir::Value zeroPtr = mlir::LLVM::ZeroOp::create(rewriter, castOp.getLoc(),
1792 llvmSrcVal.getType());
1793 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
1794 castOp, mlir::LLVM::ICmpPredicate::ne, llvmSrcVal, zeroPtr);
1797 case cir::CastKind::address_space: {
1798 mlir::Type dstTy = castOp.getType();
1799 mlir::Value llvmSrcVal = adaptor.getSrc();
1800 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1801 rewriter.replaceOpWithNewOp<mlir::LLVM::AddrSpaceCastOp>(castOp, llvmDstTy,
1805 case cir::CastKind::member_ptr_to_bool:
1810 return castOp.emitError(
"Unhandled cast kind: ")
1811 << castOp.getKindAttrName();
1815 return mlir::success();
1818mlir::LogicalResult CIRToLLVMBuiltinIntCastOpLowering::matchAndRewrite(
1819 cir::BuiltinIntCastOp op, OpAdaptor adaptor,
1820 mlir::ConversionPatternRewriter &rewriter)
const {
1825 if (
auto cirSrc = mlir::dyn_cast<cir::IntType>(op.getSrc().getType()))
1827 else if (
auto cirDst = mlir::dyn_cast<cir::IntType>(op.getType()))
1830 mlir::Value llvmSrc = adaptor.getSrc();
1831 mlir::Type llvmDstTy = getTypeConverter()->convertType(op.getType());
1832 auto srcIntTy = mlir::cast<mlir::IntegerType>(llvmSrc.getType());
1833 auto dstIntTy = mlir::cast<mlir::IntegerType>(llvmDstTy);
1834 unsigned srcWidth = srcIntTy.getWidth();
1835 unsigned dstWidth = dstIntTy.getWidth();
1840 assert((srcWidth == dstWidth ||
1841 mlir::isa<mlir::IndexType>(op.getSrc().getType()) ||
1842 mlir::isa<mlir::IndexType>(op.getType())) &&
1843 "only index casts may change width during lowering");
1848 srcWidth, dstWidth));
1849 return mlir::success();
1853 mlir::ModuleOp mod, mlir::Value index,
1854 mlir::Type baseTy, cir::IntType strideTy) {
1855 mlir::Operation *indexOp = index.getDefiningOp();
1859 auto indexType = mlir::cast<mlir::IntegerType>(index.getType());
1860 mlir::DataLayout llvmLayout(mod);
1861 std::optional<uint64_t> layoutWidth = llvmLayout.getTypeIndexBitwidth(baseTy);
1864 if (!layoutWidth || *layoutWidth == indexType.getWidth())
1870 auto sub = dyn_cast<mlir::LLVM::SubOp>(indexOp);
1871 bool rewriteSub =
false;
1874 dyn_cast<mlir::LLVM::ConstantOp>(sub.getLhs().getDefiningOp())) {
1875 auto lhsConstInt = mlir::dyn_cast<mlir::IntegerAttr>(lhsConst.getValue());
1876 if (lhsConstInt && lhsConstInt.getValue() == 0) {
1877 index = sub.getRhs();
1883 auto llvmDstType = rewriter.getIntegerType(*layoutWidth);
1884 bool isUnsigned = strideTy && strideTy.isUnsigned();
1886 indexType.getWidth(), *layoutWidth);
1889 index = mlir::LLVM::SubOp::create(
1890 rewriter, index.getLoc(),
1891 mlir::LLVM::ConstantOp::create(rewriter, index.getLoc(),
1892 index.getType(), 0),
1895 rewriter.eraseOp(sub);
1901mlir::LogicalResult CIRToLLVMPtrStrideOpLowering::matchAndRewrite(
1902 cir::PtrStrideOp ptrStrideOp, OpAdaptor adaptor,
1903 mlir::ConversionPatternRewriter &rewriter)
const {
1905 const mlir::TypeConverter *tc = getTypeConverter();
1906 const mlir::Type resultTy = tc->convertType(ptrStrideOp.getType());
1908 mlir::Type elementTy =
1913 if (mlir::isa<mlir::LLVM::LLVMVoidType>(elementTy) ||
1914 mlir::isa<mlir::LLVM::LLVMFunctionType>(elementTy))
1915 elementTy = mlir::IntegerType::get(elementTy.getContext(), 8,
1916 mlir::IntegerType::Signless);
1918 mlir::Value index = adaptor.getStride();
1920 rewriter, ptrStrideOp->getParentOfType<mlir::ModuleOp>(), index,
1921 adaptor.getBase().getType(),
1922 dyn_cast<cir::IntType>(ptrStrideOp.getOperand(1).getType()));
1924 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1925 ptrStrideOp, resultTy, elementTy, adaptor.getBase(), index);
1926 return mlir::success();
1929mlir::LogicalResult CIRToLLVMGetElementOpLowering::matchAndRewrite(
1930 cir::GetElementOp op, OpAdaptor adaptor,
1931 mlir::ConversionPatternRewriter &rewriter)
const {
1933 mlir::dyn_cast<cir::ArrayType>(op.getBaseType().getPointee())) {
1934 const mlir::TypeConverter *converter = getTypeConverter();
1935 const mlir::Type llArrayTy = converter->convertType(arrayTy);
1936 const mlir::Type llResultTy = converter->convertType(op.getType());
1937 mlir::Type elementTy =
1942 if (mlir::isa<mlir::LLVM::LLVMVoidType>(elementTy) ||
1943 mlir::isa<mlir::LLVM::LLVMFunctionType>(elementTy))
1944 elementTy = rewriter.getIntegerType(8);
1946 mlir::Value index = adaptor.getIndex();
1949 adaptor.getBase().getType(),
1950 dyn_cast<cir::IntType>(op.getOperand(1).getType()));
1955 std::array<mlir::LLVM::GEPArg, 2> offset{0, index};
1956 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, llResultTy, llArrayTy,
1957 adaptor.getBase(), offset);
1958 return mlir::success();
1961 op.emitError() <<
"NYI: GetElementOp lowering to LLVM for non-array";
1962 return mlir::failure();
1965mlir::LogicalResult CIRToLLVMBaseClassAddrOpLowering::matchAndRewrite(
1966 cir::BaseClassAddrOp baseClassOp, OpAdaptor adaptor,
1967 mlir::ConversionPatternRewriter &rewriter)
const {
1968 const mlir::Type resultType =
1969 getTypeConverter()->convertType(baseClassOp.getType());
1970 mlir::Value derivedAddr = adaptor.getDerivedAddr();
1971 llvm::SmallVector<mlir::LLVM::GEPArg, 1> offset = {
1972 adaptor.getOffset().getZExtValue()};
1973 mlir::Type byteType = mlir::IntegerType::get(resultType.getContext(), 8,
1974 mlir::IntegerType::Signless);
1975 if (adaptor.getOffset().getZExtValue() == 0) {
1976 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(
1977 baseClassOp, resultType, adaptor.getDerivedAddr());
1978 return mlir::success();
1981 if (baseClassOp.getAssumeNotNull()) {
1982 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1983 baseClassOp, resultType, byteType, derivedAddr, offset);
1985 auto loc = baseClassOp.getLoc();
1986 mlir::Value isNull = mlir::LLVM::ICmpOp::create(
1987 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, derivedAddr,
1988 mlir::LLVM::ZeroOp::create(rewriter, loc, derivedAddr.getType()));
1989 mlir::Value adjusted = mlir::LLVM::GEPOp::create(
1990 rewriter, loc, resultType, byteType, derivedAddr, offset);
1991 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(baseClassOp, isNull,
1992 derivedAddr, adjusted);
1994 return mlir::success();
1997mlir::LogicalResult CIRToLLVMDerivedClassAddrOpLowering::matchAndRewrite(
1998 cir::DerivedClassAddrOp derivedClassOp, OpAdaptor adaptor,
1999 mlir::ConversionPatternRewriter &rewriter)
const {
2000 const mlir::Type resultType =
2001 getTypeConverter()->convertType(derivedClassOp.getType());
2002 mlir::Value baseAddr = adaptor.getBaseAddr();
2005 int64_t offsetVal = -(adaptor.getOffset().getZExtValue());
2006 if (offsetVal == 0) {
2008 rewriter.replaceOp(derivedClassOp, baseAddr);
2009 return mlir::success();
2011 llvm::SmallVector<mlir::LLVM::GEPArg, 1> offset = {offsetVal};
2012 mlir::Type byteType = mlir::IntegerType::get(resultType.getContext(), 8,
2013 mlir::IntegerType::Signless);
2014 if (derivedClassOp.getAssumeNotNull()) {
2015 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
2016 derivedClassOp, resultType, byteType, baseAddr, offset,
2017 mlir::LLVM::GEPNoWrapFlags::inbounds);
2019 mlir::Location loc = derivedClassOp.getLoc();
2020 mlir::Value isNull = mlir::LLVM::ICmpOp::create(
2021 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, baseAddr,
2022 mlir::LLVM::ZeroOp::create(rewriter, loc, baseAddr.getType()));
2023 mlir::Value adjusted =
2024 mlir::LLVM::GEPOp::create(rewriter, loc, resultType, byteType, baseAddr,
2025 offset, mlir::LLVM::GEPNoWrapFlags::inbounds);
2026 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(derivedClassOp, isNull,
2027 baseAddr, adjusted);
2029 return mlir::success();
2032mlir::LogicalResult CIRToLLVMFMaxNumOpLowering::matchAndRewrite(
2033 cir::FMaxNumOp op, OpAdaptor adaptor,
2034 mlir::ConversionPatternRewriter &rewriter)
const {
2035 mlir::Type resTy = typeConverter->convertType(op.getType());
2036 if (cir::FenvAttr fenv = op.getFenvAttr())
2038 op, adaptor.getOperands(), fenv, resTy, rewriter,
"maxnum",
2039 false, mlir::LLVM::FastmathFlags::nsz);
2040 rewriter.replaceOpWithNewOp<mlir::LLVM::MaxNumOp>(
2041 op, resTy, adaptor.getLhs(), adaptor.getRhs(),
2042 mlir::LLVM::FastmathFlags::nsz);
2043 return mlir::success();
2046mlir::LogicalResult CIRToLLVMFMinNumOpLowering::matchAndRewrite(
2047 cir::FMinNumOp op, OpAdaptor adaptor,
2048 mlir::ConversionPatternRewriter &rewriter)
const {
2049 mlir::Type resTy = typeConverter->convertType(op.getType());
2050 if (cir::FenvAttr fenv = op.getFenvAttr())
2052 op, adaptor.getOperands(), fenv, resTy, rewriter,
"minnum",
2053 false, mlir::LLVM::FastmathFlags::nsz);
2054 rewriter.replaceOpWithNewOp<mlir::LLVM::MinNumOp>(
2055 op, resTy, adaptor.getLhs(), adaptor.getRhs(),
2056 mlir::LLVM::FastmathFlags::nsz);
2057 return mlir::success();
2060mlir::LogicalResult CIRToLLVMAllocaOpLowering::matchAndRewrite(
2061 cir::AllocaOp op, OpAdaptor adaptor,
2062 mlir::ConversionPatternRewriter &rewriter)
const {
2065 ? adaptor.getDynAllocSize()
2066 : mlir::LLVM::ConstantOp::create(
2067 rewriter, op.getLoc(),
2068 typeConverter->convertType(rewriter.getI32Type()), 1);
2069 mlir::Type elementTy =
2072 return op.emitError()
2073 <<
"NYI: lowering alloca of a type with no memory representation";
2074 mlir::Type resultTy =
2080 rewriter.replaceOpWithNewOp<mlir::LLVM::AllocaOp>(op, resultTy, elementTy,
2081 size, op.getAlignment());
2083 return mlir::success();
2086mlir::LogicalResult CIRToLLVMRotateOpLowering::matchAndRewrite(
2087 cir::RotateOp op, OpAdaptor adaptor,
2088 mlir::ConversionPatternRewriter &rewriter)
const {
2091 mlir::Value input = adaptor.getInput();
2092 if (op.isRotateLeft())
2093 rewriter.replaceOpWithNewOp<mlir::LLVM::FshlOp>(op, input, input,
2094 adaptor.getAmount());
2096 rewriter.replaceOpWithNewOp<mlir::LLVM::FshrOp>(op, input, input,
2097 adaptor.getAmount());
2098 return mlir::LogicalResult::success();
2106static mlir::ArrayAttr
2108 const mlir::TypeConverter &converter,
2109 mlir::MLIRContext *ctx) {
2112 bool changed =
false;
2114 loweredArgAttrs.reserve(argAttrs.size());
2115 for (mlir::Attribute a : argAttrs) {
2116 auto dict = cast<mlir::DictionaryAttr>(a);
2118 for (mlir::NamedAttribute &entry : entries) {
2119 StringRef name = entry.getName().strref();
2120 if (name != mlir::LLVM::LLVMDialect::getByValAttrName() &&
2121 name != mlir::LLVM::LLVMDialect::getStructRetAttrName() &&
2122 name != mlir::LLVM::LLVMDialect::getByRefAttrName())
2124 auto typeAttr = dyn_cast<mlir::TypeAttr>(entry.getValue());
2127 mlir::Type lowered = converter.convertType(typeAttr.getValue());
2128 if (lowered && lowered != typeAttr.getValue()) {
2129 entry.setValue(mlir::TypeAttr::get(lowered));
2133 loweredArgAttrs.push_back(mlir::DictionaryAttr::get(ctx, entries));
2135 return changed ? mlir::ArrayAttr::get(ctx, loweredArgAttrs) : argAttrs;
2139 const mlir::TypeConverter &converter,
2141 for (mlir::NamedAttribute attr : op->getAttrs()) {
2142 if (attr.getName() == CIRDialect::getCalleeAttrName() ||
2143 attr.getName() == CIRDialect::getSideEffectAttrName() ||
2144 attr.getName() == CIRDialect::getNoThrowAttrName() ||
2145 attr.getName() == CIRDialect::getNoUnwindAttrName() ||
2146 attr.getName() == CIRDialect::getNoReturnAttrName() ||
2147 attr.getName() == op.getInlineKindAttrName() ||
2148 attr.getName() == CIRDialect::getMustTailAttrName())
2152 if (attr.getName() == CIRDialect::getArgAttrsAttrName()) {
2153 auto argAttrs = cast<mlir::ArrayAttr>(attr.getValue());
2154 result.emplace_back(
2159 result.push_back(attr);
2163static mlir::LogicalResult
2165 mlir::ConversionPatternRewriter &rewriter,
2166 const mlir::TypeConverter *converter,
2167 mlir::SymbolTableCollection &symbolTables,
2168 mlir::FlatSymbolRefAttr calleeAttr,
2169 mlir::Block *continueBlock =
nullptr,
2170 mlir::Block *landingPadBlock =
nullptr) {
2172 mlir::ValueTypeRange<mlir::ResultRange> cirResults = op->getResultTypes();
2173 auto call = cast<cir::CIRCallOpInterface>(op);
2175 if (converter->convertTypes(cirResults, llvmResults).failed())
2176 return mlir::failure();
2180 mlir::LLVM::MemoryEffectsAttr memoryEffects;
2181 bool noUnwind =
false;
2182 bool willReturn =
false;
2183 bool noReturn =
false;
2185 memoryEffects, noUnwind, willReturn, noReturn);
2190 mlir::LLVM::LLVMFunctionType llvmFnTy;
2197 mlir::Operation *callee =
2198 symbolTables.lookupNearestSymbolFrom(op, calleeAttr);
2199 if (
auto fn = mlir::dyn_cast<mlir::FunctionOpInterface>(callee)) {
2200 llvmFnTy = converter->convertType<mlir::LLVM::LLVMFunctionType>(
2201 fn.getFunctionType());
2202 assert(llvmFnTy &&
"Failed to convert function type");
2203 }
else if (
auto alias = mlir::cast<mlir::LLVM::AliasOp>(callee)) {
2211 auto symAttr = mlir::cast<mlir::FlatSymbolRefAttr>(calleeAttr);
2213 mlir::LLVM::AddressOfOp::create(
2214 rewriter, op->getLoc(),
2215 mlir::LLVM::LLVMPointerType::get(rewriter.getContext()), symAttr)
2217 adjustedCallOperands.push_back(addrOfAlias);
2220 llvm::append_range(adjustedCallOperands, callOperands);
2221 callOperands = adjustedCallOperands;
2225 llvmFnTy = mlir::cast<mlir::LLVM::LLVMFunctionType>(alias.getType());
2228 return op->emitError(
"Unexpected callee type!");
2231 assert(!op->getOperands().empty() &&
2232 "operands list must no be empty for the indirect call");
2233 auto calleeTy = op->getOperands().front().getType();
2234 auto calleePtrTy = cast<cir::PointerType>(calleeTy);
2235 auto calleeFuncTy = cast<cir::FuncType>(calleePtrTy.getPointee());
2236 llvm::append_range(adjustedCallOperands, callOperands);
2237 llvmFnTy = cast<mlir::LLVM::LLVMFunctionType>(
2238 converter->convertType(calleeFuncTy));
2243 if (landingPadBlock) {
2244 auto newOp = rewriter.replaceOpWithNewOp<mlir::LLVM::InvokeOp>(
2245 op, llvmFnTy, calleeAttr, callOperands, continueBlock,
2246 mlir::ValueRange{}, landingPadBlock, mlir::ValueRange{});
2247 newOp->setAttrs(attributes);
2249 auto newOp = rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(
2250 op, llvmFnTy, calleeAttr, callOperands);
2251 newOp->setAttrs(attributes);
2253 newOp.setMemoryEffectsAttr(memoryEffects);
2254 newOp.setNoUnwind(noUnwind);
2255 newOp.setWillReturn(willReturn);
2256 newOp.setNoreturn(noReturn);
2257 if (op->hasAttr(CIRDialect::getMustTailAttrName()))
2258 newOp.setTailCallKind(mlir::LLVM::TailCallKind::MustTail);
2260 if (std::optional<cir::InlineKind> inlineKind = call.getInlineKind()) {
2261 newOp.setNoInline(*inlineKind == cir::InlineKind::NoInline);
2262 newOp.setInlineHint(*inlineKind == cir::InlineKind::InlineHint);
2263 newOp.setAlwaysInline(*inlineKind == cir::InlineKind::AlwaysInline);
2267 return mlir::success();
2270mlir::LogicalResult CIRToLLVMCallOpLowering::matchAndRewrite(
2271 cir::CallOp op, OpAdaptor adaptor,
2272 mlir::ConversionPatternRewriter &rewriter)
const {
2274 getTypeConverter(), symbolTables,
2275 op.getCalleeAttr());
2278mlir::LogicalResult CIRToLLVMTryCallOpLowering::matchAndRewrite(
2279 cir::TryCallOp op, OpAdaptor adaptor,
2280 mlir::ConversionPatternRewriter &rewriter)
const {
2283 op.getOperation(), adaptor.getOperands(), rewriter, getTypeConverter(),
2284 symbolTables, op.getCalleeAttr(), op.getNormalDest(), op.getUnwindDest());
2287mlir::LogicalResult CIRToLLVMReturnAddrOpLowering::matchAndRewrite(
2288 cir::ReturnAddrOp op, OpAdaptor adaptor,
2289 mlir::ConversionPatternRewriter &rewriter)
const {
2290 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
2292 llvmPtrTy, adaptor.getOperands());
2293 return mlir::success();
2296mlir::LogicalResult CIRToLLVMFrameAddrOpLowering::matchAndRewrite(
2297 cir::FrameAddrOp op, OpAdaptor adaptor,
2298 mlir::ConversionPatternRewriter &rewriter)
const {
2299 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
2301 adaptor.getOperands());
2302 return mlir::success();
2305mlir::LogicalResult CIRToLLVMClearCacheOpLowering::matchAndRewrite(
2306 cir::ClearCacheOp op, OpAdaptor adaptor,
2307 mlir::ConversionPatternRewriter &rewriter)
const {
2308 mlir::Value begin = adaptor.getBegin();
2309 mlir::Value end = adaptor.getEnd();
2310 auto intrinNameAttr =
2311 mlir::StringAttr::get(op.getContext(),
"llvm.clear_cache");
2312 rewriter.replaceOpWithNewOp<mlir::LLVM::CallIntrinsicOp>(
2313 op, mlir::Type{}, intrinNameAttr, mlir::ValueRange{begin, end});
2315 return mlir::success();
2318mlir::LogicalResult CIRToLLVMAddrOfReturnAddrOpLowering::matchAndRewrite(
2319 cir::AddrOfReturnAddrOp op, OpAdaptor adaptor,
2320 mlir::ConversionPatternRewriter &rewriter)
const {
2321 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
2323 llvmPtrTy, adaptor.getOperands());
2324 return mlir::success();
2327mlir::LogicalResult CIRToLLVMLoadOpLowering::matchAndRewrite(
2328 cir::LoadOp op, OpAdaptor adaptor,
2329 mlir::ConversionPatternRewriter &rewriter)
const {
2330 const mlir::Type llvmTy =
2333 return op.emitError()
2334 <<
"NYI: lowering load of a type with no memory representation";
2335 mlir::LLVM::AtomicOrdering ordering =
getLLVMMemOrder(op.getMemOrder());
2336 std::optional<size_t> opAlign = op.getAlignment();
2337 unsigned alignment = (unsigned)opAlign.value_or(
2342 std::optional<llvm::StringRef> llvmSyncScope =
2345 mlir::LLVM::LoadOp newLoad = mlir::LLVM::LoadOp::create(
2346 rewriter, op->getLoc(), llvmTy, adaptor.getAddr(), alignment,
2347 op.getIsVolatile(), op.getIsNontemporal(),
2348 op.getInvariant(),
false, ordering,
2349 llvmSyncScope.value_or(std::string()));
2350 if (mlir::Attribute domain = op->getAttr(
"cir.riscv_nontemporal_domain"))
2351 newLoad->setAttr(
"cir.riscv_nontemporal_domain", domain);
2354 mlir::Value result =
emitFromMemory(rewriter, *getTypeConverter(), dataLayout,
2355 op, newLoad.getResult());
2356 rewriter.replaceOp(op, result);
2358 return mlir::LogicalResult::success();
2362cir::direct::CIRToLLVMVecMaskedLoadOpLowering::matchAndRewrite(
2363 cir::VecMaskedLoadOp op, OpAdaptor adaptor,
2364 mlir::ConversionPatternRewriter &rewriter)
const {
2365 const mlir::Type llvmResTy =
2368 return op.emitError()
2369 <<
"NYI: lowering masked load of a type with no memory "
2372 std::optional<size_t> opAlign = op.getAlignment();
2373 unsigned alignment =
2374 (unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmResTy));
2376 mlir::IntegerAttr alignAttr = rewriter.getI32IntegerAttr(alignment);
2378 auto newLoad = mlir::LLVM::MaskedLoadOp::create(
2379 rewriter, op.getLoc(), llvmResTy, adaptor.getAddr(), adaptor.getMask(),
2380 adaptor.getPassThru(), alignAttr);
2382 rewriter.replaceOp(op, newLoad.getResult());
2383 return mlir::success();
2386mlir::LogicalResult CIRToLLVMStoreOpLowering::matchAndRewrite(
2387 cir::StoreOp op, OpAdaptor adaptor,
2388 mlir::ConversionPatternRewriter &rewriter)
const {
2389 mlir::LLVM::AtomicOrdering memorder =
getLLVMMemOrder(op.getMemOrder());
2390 mlir::Type valueType = op.getValue().getType();
2391 const mlir::Type llvmTy =
2394 return op.emitError()
2395 <<
"NYI: lowering store of a type with no memory representation";
2396 std::optional<size_t> opAlign = op.getAlignment();
2397 unsigned alignment = (unsigned)opAlign.value_or(
2404 op.getValue().getType(), adaptor.getValue());
2407 std::optional<llvm::StringRef> llvmSyncScope =
2410 mlir::LLVM::StoreOp storeOp = mlir::LLVM::StoreOp::create(
2411 rewriter, op->getLoc(), value, adaptor.getAddr(), alignment,
2413 op.getIsNontemporal(),
false,
2414 memorder, llvmSyncScope.value_or(std::string()));
2415 if (mlir::Attribute domain = op->getAttr(
"cir.riscv_nontemporal_domain"))
2416 storeOp->setAttr(
"cir.riscv_nontemporal_domain", domain);
2417 rewriter.replaceOp(op, storeOp);
2419 return mlir::LogicalResult::success();
2423 while (
auto arrTy = mlir::dyn_cast<cir::ArrayType>(ty))
2424 ty = arrTy.getElementType();
2429 return mlir::isa<cir::PointerType, cir::IntType, cir::BoolType,
2433mlir::LogicalResult CIRToLLVMConstantOpLowering::matchAndRewrite(
2434 cir::ConstantOp op, OpAdaptor adaptor,
2435 mlir::ConversionPatternRewriter &rewriter)
const {
2436 mlir::Attribute attr = op.getValue();
2438 if (mlir::isa<cir::PoisonAttr>(attr)) {
2439 rewriter.replaceOpWithNewOp<mlir::LLVM::PoisonOp>(
2440 op, getTypeConverter()->convertType(op.getType()));
2441 return mlir::success();
2444 if (mlir::isa<cir::UndefAttr>(attr)) {
2445 rewriter.replaceOpWithNewOp<mlir::LLVM::UndefOp>(
2446 op, getTypeConverter()->convertType(op.getType()));
2447 return mlir::success();
2450 if (mlir::isa<mlir::IntegerType>(op.getType())) {
2455 attr = op.getValue();
2456 }
else if (mlir::isa<cir::BoolType>(op.getType())) {
2457 int value = mlir::cast<cir::BoolAttr>(op.getValue()).getValue();
2458 attr = rewriter.getIntegerAttr(typeConverter->convertType(op.getType()),
2460 }
else if (mlir::isa<cir::IntType>(op.getType())) {
2462 if (
auto ga = mlir::dyn_cast<cir::GlobalViewAttr>(op.getValue())) {
2468 op.emitError() <<
"global view with integer type";
2469 return mlir::failure();
2472 attr = rewriter.getIntegerAttr(
2473 typeConverter->convertType(op.getType()),
2474 mlir::cast<cir::IntAttr>(op.getValue()).getValue());
2475 }
else if (mlir::isa<cir::FPTypeInterface>(op.getType())) {
2476 attr = rewriter.getFloatAttr(
2477 typeConverter->convertType(op.getType()),
2478 mlir::cast<cir::FPAttr>(op.getValue()).getValue());
2479 }
else if (mlir::isa<cir::PointerType>(op.getType())) {
2481 if (mlir::isa<cir::ConstPtrAttr>(op.getValue())) {
2482 if (mlir::cast<cir::ConstPtrAttr>(op.getValue()).isNullValue()) {
2483 rewriter.replaceOpWithNewOp<mlir::LLVM::ZeroOp>(
2484 op, typeConverter->convertType(op.getType()));
2485 return mlir::success();
2489 if (mlir::isa<cir::GlobalViewAttr, cir::GlobalOffsetAttr>(op.getValue())) {
2491 symbolTables, getTypeConverter());
2492 rewriter.replaceOp(op, newOp);
2493 return mlir::success();
2495 attr = op.getValue();
2496 }
else if (
const auto arrTy = mlir::dyn_cast<cir::ArrayType>(op.getType())) {
2497 const auto constArr = mlir::dyn_cast<cir::ConstArrayAttr>(op.getValue());
2498 if (!constArr && !isa<cir::ZeroAttr, cir::UndefAttr>(op.getValue()))
2499 return op.emitError() <<
"array does not have a constant initializer";
2501 std::optional<mlir::Attribute> denseAttr;
2504 attr = denseAttr.value();
2507 op, op.getValue(), rewriter, symbolTables, typeConverter);
2508 rewriter.replaceOp(op, initVal);
2509 return mlir::success();
2511 }
else if (
const auto recordAttr =
2512 mlir::dyn_cast<cir::ConstRecordAttr>(op.getValue())) {
2515 rewriter.replaceOp(op, initVal);
2516 return mlir::success();
2517 }
else if (
const auto vecTy = mlir::dyn_cast<cir::VectorType>(op.getType())) {
2518 rewriter.replaceOp(op,
2520 symbolTables, getTypeConverter()));
2521 return mlir::success();
2522 }
else if (mlir::isa<cir::RecordType>(op.getType())) {
2523 if (mlir::isa<cir::ZeroAttr, cir::UndefAttr>(attr)) {
2524 mlir::Value initVal =
2526 rewriter.replaceOp(op, initVal);
2527 return mlir::success();
2529 return op.emitError() <<
"unsupported lowering for record constant type "
2531 }
else if (
auto complexTy = mlir::dyn_cast<cir::ComplexType>(op.getType())) {
2532 mlir::Type complexElemTy = complexTy.getElementType();
2533 mlir::Type complexElemLLVMTy = typeConverter->convertType(complexElemTy);
2535 if (
auto zeroInitAttr = mlir::dyn_cast<cir::ZeroAttr>(op.getValue())) {
2536 mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(complexElemLLVMTy);
2537 mlir::ArrayAttr array = rewriter.getArrayAttr({zeroAttr, zeroAttr});
2538 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
2539 op, getTypeConverter()->convertType(op.getType()), array);
2540 return mlir::success();
2543 if (mlir::isa<cir::UndefAttr>(op.getValue())) {
2544 rewriter.replaceOpWithNewOp<mlir::LLVM::UndefOp>(
2545 op, getTypeConverter()->convertType(op.getType()));
2546 return mlir::success();
2549 auto complexAttr = mlir::cast<cir::ConstComplexAttr>(op.getValue());
2551 mlir::Attribute components[2];
2552 if (mlir::isa<cir::IntType>(complexElemTy)) {
2553 components[0] = rewriter.getIntegerAttr(
2555 mlir::cast<cir::IntAttr>(complexAttr.getReal()).getValue());
2556 components[1] = rewriter.getIntegerAttr(
2558 mlir::cast<cir::IntAttr>(complexAttr.getImag()).getValue());
2560 components[0] = rewriter.getFloatAttr(
2562 mlir::cast<cir::FPAttr>(complexAttr.getReal()).getValue());
2563 components[1] = rewriter.getFloatAttr(
2565 mlir::cast<cir::FPAttr>(complexAttr.getImag()).getValue());
2568 attr = rewriter.getArrayAttr(components);
2570 return op.emitError() <<
"unsupported constant type " << op.getType();
2573 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
2574 op, getTypeConverter()->convertType(op.getType()),
attr);
2576 return mlir::success();
2580 mlir::DataLayout layout(op.getParentOfType<mlir::ModuleOp>());
2582 if (isa<cir::VoidType>(type))
2583 type = cir::IntType::get(type.getContext(), 8,
false);
2584 return llvm::divideCeil(layout.getTypeSizeInBits(type), 8);
2587mlir::LogicalResult CIRToLLVMPrefetchOpLowering::matchAndRewrite(
2588 cir::PrefetchOp op, OpAdaptor adaptor,
2589 mlir::ConversionPatternRewriter &rewriter)
const {
2590 rewriter.replaceOpWithNewOp<mlir::LLVM::Prefetch>(
2591 op, adaptor.getAddr(), adaptor.getIsWrite(), adaptor.getLocality(),
2593 return mlir::success();
2596mlir::LogicalResult CIRToLLVMPtrDiffOpLowering::matchAndRewrite(
2597 cir::PtrDiffOp op, OpAdaptor adaptor,
2598 mlir::ConversionPatternRewriter &rewriter)
const {
2599 auto dstTy = mlir::cast<cir::IntType>(op.getType());
2600 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
2602 auto lhs = mlir::LLVM::PtrToIntOp::create(rewriter, op.getLoc(), llvmDstTy,
2604 auto rhs = mlir::LLVM::PtrToIntOp::create(rewriter, op.getLoc(), llvmDstTy,
2608 mlir::LLVM::SubOp::create(rewriter, op.getLoc(), llvmDstTy, lhs, rhs);
2610 cir::PointerType ptrTy = op.getLhs().getType();
2612 uint64_t typeSize =
getTypeSize(ptrTy.getPointee(), *op);
2615 mlir::Value resultVal = diff.getResult();
2616 if (typeSize != 1) {
2617 auto typeSizeVal = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
2618 llvmDstTy, typeSize);
2620 if (dstTy.isUnsigned()) {
2622 mlir::LLVM::UDivOp::create(rewriter, op.getLoc(), diff, typeSizeVal);
2623 uDiv.setIsExact(
true);
2624 resultVal = uDiv.getResult();
2627 mlir::LLVM::SDivOp::create(rewriter, op.getLoc(), diff, typeSizeVal);
2628 sDiv.setIsExact(
true);
2629 resultVal = sDiv.getResult();
2632 rewriter.replaceOp(op, resultVal);
2633 return mlir::success();
2636mlir::LogicalResult CIRToLLVMExpectOpLowering::matchAndRewrite(
2637 cir::ExpectOp op, OpAdaptor adaptor,
2638 mlir::ConversionPatternRewriter &rewriter)
const {
2642 std::optional<llvm::APFloat> prob = op.getProb();
2644 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpectWithProbabilityOp>(
2645 op, adaptor.getVal(), adaptor.getExpected(), prob.value());
2647 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpectOp>(op, adaptor.getVal(),
2648 adaptor.getExpected());
2649 return mlir::success();
2652mlir::LogicalResult CIRToLLVMAbsOpLowering::matchAndRewrite(
2653 cir::AbsOp op, OpAdaptor adaptor,
2654 mlir::ConversionPatternRewriter &rewriter)
const {
2655 mlir::Type resTy = typeConverter->convertType(op.getType());
2656 auto absOp = mlir::LLVM::AbsOp::create(rewriter, op.getLoc(), resTy,
2657 adaptor.getOperands()[0],
2658 adaptor.getMinIsPoison());
2659 rewriter.replaceOp(op, absOp);
2660 return mlir::success();
2665 mlir::StringRef linkageAttrName) {
2666 return attr.getName() == func.getSymNameAttrName() ||
2667 attr.getName() == func.getFunctionTypeAttrName() ||
2668 attr.getName() == linkageAttrName ||
2669 attr.getName() == func.getCallingConvAttrName() ||
2670 attr.getName() == func.getDsoLocalAttrName() ||
2671 attr.getName() == func.getInlineKindAttrName() ||
2672 attr.getName() == func.getSideEffectAttrName() ||
2673 attr.getName() == CIRDialect::getNoReturnAttrName() ||
2674 attr.getName() == CIRDialect::getStrictFPAttrName() ||
2675 attr.getName() == func.getAnnotationsAttrName();
2682void CIRToLLVMFuncOpLowering::lowerFuncAttributes(
2683 cir::FuncOp func,
bool includeFunctionOnlyAttrs,
2685 OpenCLFunctionMetadataLowering openCLMetadataLowering(func.getContext());
2686 for (mlir::NamedAttribute attr : func->getAttrs()) {
2689 if (openCLMetadataLowering.lower(attr, includeFunctionOnlyAttrs))
2693 if (attr.getName() == func.getArgAttrsAttrName()) {
2694 auto argAttrs = cast<mlir::ArrayAttr>(attr.getValue());
2695 result.emplace_back(
2700 result.push_back(attr);
2703 if (includeFunctionOnlyAttrs)
2704 openCLMetadataLowering.appendAttrs(result);
2707mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewriteAlias(
2708 cir::FuncOp op, llvm::StringRef aliasee, mlir::Type ty, OpAdaptor adaptor,
2709 mlir::ConversionPatternRewriter &rewriter)
const {
2710 SmallVector<mlir::NamedAttribute, 4> attributes;
2711 lowerFuncAttributes(op,
false, attributes);
2713 mlir::Location loc = op.getLoc();
2714 auto aliasOp = rewriter.replaceOpWithNewOp<mlir::LLVM::AliasOp>(
2715 op, ty,
convertLinkage(op.getLinkage()), op.getName(), op.getDsoLocal(),
2716 mlir::LLVM::ThreadLocalMode::NotThreadLocal, attributes);
2719 mlir::OpBuilder builder(op.getContext());
2720 mlir::Block *block = builder.createBlock(&aliasOp.getInitializerRegion());
2721 builder.setInsertionPointToStart(block);
2724 mlir::Type ptrTy = mlir::LLVM::LLVMPointerType::get(ty.getContext());
2725 auto addrOp = mlir::LLVM::AddressOfOp::create(builder, loc, ptrTy, aliasee);
2726 mlir::LLVM::ReturnOp::create(builder, loc, addrOp);
2728 return mlir::success();
2731mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewrite(
2732 cir::FuncOp op, OpAdaptor adaptor,
2733 mlir::ConversionPatternRewriter &rewriter)
const {
2735 cir::FuncType fnType = op.getFunctionType();
2736 bool isDsoLocal = op.getDsoLocal();
2737 mlir::TypeConverter::SignatureConversion signatureConversion(
2738 fnType.getNumInputs());
2740 for (
const auto &argType : llvm::enumerate(fnType.getInputs())) {
2741 mlir::Type convertedType = typeConverter->convertType(argType.value());
2743 return mlir::failure();
2744 signatureConversion.addInputs(argType.index(), convertedType);
2747 mlir::Type resultType =
2748 getTypeConverter()->convertType(fnType.getReturnType());
2751 mlir::Type llvmFnTy = mlir::LLVM::LLVMFunctionType::get(
2752 resultType ? resultType : mlir::LLVM::LLVMVoidType::get(getContext()),
2753 signatureConversion.getConvertedTypes(),
2757 if (std::optional<llvm::StringRef> aliasee = op.getAliasee())
2758 return matchAndRewriteAlias(op, *aliasee, llvmFnTy, adaptor, rewriter);
2762 mlir::Location loc = op.getLoc();
2763 if (mlir::FusedLoc fusedLoc = mlir::dyn_cast<mlir::FusedLoc>(loc))
2764 loc = fusedLoc.getLocations()[0];
2765 assert((mlir::isa<mlir::FileLineColLoc>(loc) ||
2766 mlir::isa<mlir::UnknownLoc>(loc)) &&
2767 "expected single location or unknown location here");
2771 SmallVector<mlir::NamedAttribute, 4> attributes;
2772 lowerFuncAttributes(op,
true, attributes);
2774 mlir::LLVM::LLVMFuncOp fn = mlir::LLVM::LLVMFuncOp::create(
2775 rewriter, loc, op.getName(), llvmFnTy, linkage, isDsoLocal, cconv,
2776 mlir::SymbolRefAttr(), attributes);
2780 if (std::optional<cir::SideEffect> sideEffectKind = op.getSideEffect()) {
2781 switch (*sideEffectKind) {
2782 case cir::SideEffect::All:
2784 case cir::SideEffect::Pure:
2785 fn.setMemoryEffectsAttr(mlir::LLVM::MemoryEffectsAttr::get(
2787 mlir::LLVM::ModRefInfo::Ref,
2788 mlir::LLVM::ModRefInfo::Ref,
2789 mlir::LLVM::ModRefInfo::Ref,
2790 mlir::LLVM::ModRefInfo::Ref,
2791 mlir::LLVM::ModRefInfo::Ref,
2792 mlir::LLVM::ModRefInfo::Ref));
2793 fn.setNoUnwind(
true);
2794 fn.setWillReturn(
true);
2796 case cir::SideEffect::Const:
2797 fn.setMemoryEffectsAttr(mlir::LLVM::MemoryEffectsAttr::get(
2799 mlir::LLVM::ModRefInfo::NoModRef,
2800 mlir::LLVM::ModRefInfo::NoModRef,
2801 mlir::LLVM::ModRefInfo::NoModRef,
2802 mlir::LLVM::ModRefInfo::NoModRef,
2803 mlir::LLVM::ModRefInfo::NoModRef,
2804 mlir::LLVM::ModRefInfo::NoModRef));
2805 fn.setNoUnwind(
true);
2806 fn.setWillReturn(
true);
2811 if (op->hasAttr(CIRDialect::getNoReturnAttrName()))
2812 fn.setNoreturn(
true);
2818 if (op->hasAttr(CIRDialect::getStrictFPAttrName()))
2819 fn.setPassthroughAttr(rewriter.getArrayAttr(
2820 {rewriter.getStringAttr(CIRDialect::getStrictFPAttrName())}));
2822 if (std::optional<cir::InlineKind> inlineKind = op.getInlineKind()) {
2823 fn.setNoInline(*inlineKind == cir::InlineKind::NoInline);
2824 fn.setInlineHint(*inlineKind == cir::InlineKind::InlineHint);
2825 fn.setAlwaysInline(*inlineKind == cir::InlineKind::AlwaysInline);
2828 if (std::optional<llvm::StringRef> personality = op.getPersonality())
2829 fn.setPersonality(*personality);
2834 rewriter.inlineRegionBefore(op.getBody(), fn.getBody(), fn.end());
2835 if (failed(rewriter.convertRegionTypes(&fn.getBody(), *typeConverter,
2836 &signatureConversion)))
2837 return mlir::failure();
2839 rewriter.eraseOp(op);
2841 return mlir::LogicalResult::success();
2844mlir::LogicalResult CIRToLLVMGetGlobalOpLowering::matchAndRewrite(
2845 cir::GetGlobalOp op, OpAdaptor adaptor,
2846 mlir::ConversionPatternRewriter &rewriter)
const {
2849 if (op->getUses().empty()) {
2850 rewriter.eraseOp(op);
2851 return mlir::success();
2854 mlir::Type
type = getTypeConverter()->convertType(op.getType());
2855 mlir::Operation *newop = mlir::LLVM::AddressOfOp::create(
2856 rewriter, op.getLoc(), type, op.getName());
2860 newop = mlir::LLVM::ThreadlocalAddressOp::create(rewriter, op.getLoc(),
2861 type, newop->getResult(0));
2864 rewriter.replaceOp(op, newop);
2865 return mlir::success();
2868llvm::SmallVector<mlir::NamedAttribute>
2869CIRToLLVMGlobalOpLowering::lowerGlobalAttributes(
2870 cir::GlobalOp op, mlir::ConversionPatternRewriter &rewriter)
const {
2871 SmallVector<mlir::NamedAttribute> attributes;
2873 if (mlir::StringAttr sectionAttr = op.getSectionAttr())
2874 attributes.push_back(rewriter.getNamedAttr(
"section", sectionAttr));
2876 mlir::LLVM::VisibilityAttr visibility = mlir::LLVM::VisibilityAttr::get(
2879 attributes.push_back(rewriter.getNamedAttr(
"visibility_", visibility));
2881 if (op->getAttr(CUDAExternallyInitializedAttr::getMnemonic()))
2882 attributes.push_back(rewriter.getNamedAttr(
"externally_initialized",
2883 rewriter.getUnitAttr()));
2888static mlir::LLVM::ThreadLocalMode
2891#define CHECK_ENUM(CIR, LLVM_VAL) \
2892 static_assert(static_cast<unsigned>(TLSModel::CIR) == \
2893 static_cast<unsigned>(mlir::LLVM::ThreadLocalMode::LLVM_VAL))
2901 return mlir::LLVM::ThreadLocalMode::NotThreadLocal;
2903 return static_cast<mlir::LLVM::ThreadLocalMode
>(attr.getValue());
2908void CIRToLLVMGlobalOpLowering::setupRegionInitializedLLVMGlobalOp(
2909 cir::GlobalOp op, mlir::ConversionPatternRewriter &rewriter)
const {
2910 mlir::Type llvmType =
2915 if (std::optional<mlir::Attribute> init = op.getInitialValue())
2923 const bool isConst = op.getConstant();
2924 unsigned addrSpace = 0;
2925 if (
auto targetAS = mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
2926 op.getAddrSpaceAttr()))
2927 addrSpace = targetAS.getValue();
2928 const bool isDsoLocal = op.getDsoLocal();
2929 mlir::LLVM::ThreadLocalMode threadLocalMode =
2931 const uint64_t alignment = op.getAlignment().value_or(0);
2932 const mlir::LLVM::Linkage linkage =
convertLinkage(op.getLinkage());
2933 const StringRef symbol = op.getSymName();
2934 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
2937 lowerGlobalAttributes(op, rewriter);
2939 mlir::LLVM::GlobalOp newGlobalOp =
2940 rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
2941 op, llvmType, isConst, linkage, symbol,
nullptr, alignment, addrSpace,
2942 isDsoLocal, threadLocalMode, comdatAttr, attributes);
2943 newGlobalOp.getRegion().emplaceBlock();
2944 rewriter.setInsertionPointToEnd(newGlobalOp.getInitializerBlock());
2948CIRToLLVMGlobalOpLowering::matchAndRewriteRegionInitializedGlobal(
2949 cir::GlobalOp op, mlir::Attribute init,
2950 mlir::ConversionPatternRewriter &rewriter)
const {
2952 assert((isa<cir::BlockAddrDiffAttr, cir::BlockAddrInfoAttr,
2953 cir::ConstArrayAttr, cir::ConstRecordAttr, cir::ConstVectorAttr,
2954 cir::ConstPtrAttr, cir::ConstComplexAttr, cir::GlobalOffsetAttr,
2955 cir::GlobalViewAttr, cir::TypeInfoAttr, cir::UndefAttr,
2956 cir::PoisonAttr, cir::VTableAttr, cir::ZeroAttr>(init)));
2961 const mlir::Location loc = op.getLoc();
2962 setupRegionInitializedLLVMGlobalOp(op, rewriter);
2967 CIRAttrToValue valueConverter(op, rewriter, symbolTables, typeConverter,
2969 mlir::Value value = valueConverter.visit(init);
2970 mlir::LLVM::ReturnOp::create(rewriter, loc, value);
2971 return mlir::success();
2974mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite(
2975 cir::GlobalOp op, OpAdaptor adaptor,
2976 mlir::ConversionPatternRewriter &rewriter)
const {
2979 if (!op.getCtorRegion().empty() || !op.getDtorRegion().empty())
2980 return op.emitError() <<
"GlobalOp ctor and dtor regions should be removed "
2981 "in LoweringPrepare";
2983 std::optional<mlir::Attribute> init = op.getInitialValue();
2986 const mlir::Type cirSymType = op.getSymType();
2989 mlir::Type llvmType =
2992 return op.emitError()
2993 <<
"NYI: lowering global of a type with no memory representation";
2998 if (init.has_value())
3004 const bool isConst = op.getConstant();
3005 unsigned addrSpace = 0;
3006 if (
auto targetAS = mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
3007 op.getAddrSpaceAttr()))
3008 addrSpace = targetAS.getValue();
3009 const bool isDsoLocal = op.getDsoLocal();
3010 mlir::LLVM::ThreadLocalMode threadLocalMode =
3012 const uint64_t alignment = op.getAlignment().value_or(0);
3013 const mlir::LLVM::Linkage linkage =
convertLinkage(op.getLinkage());
3014 const StringRef symbol = op.getSymName();
3015 SmallVector<mlir::NamedAttribute> attributes =
3016 lowerGlobalAttributes(op, rewriter);
3019 if (std::optional<llvm::StringRef> aliasee = op.getAliasee()) {
3020 mlir::Location loc = op.getLoc();
3021 auto aliasOp = rewriter.replaceOpWithNewOp<mlir::LLVM::AliasOp>(
3022 op, llvmType, linkage, symbol, isDsoLocal, threadLocalMode, attributes);
3024 mlir::OpBuilder builder(op.getContext());
3025 mlir::Block *block = builder.createBlock(&aliasOp.getInitializerRegion());
3026 builder.setInsertionPointToStart(block);
3028 mlir::LLVM::LLVMPointerType::get(getContext(), addrSpace);
3030 mlir::LLVM::AddressOfOp::create(builder, loc, ptrTy, *aliasee);
3031 mlir::LLVM::ReturnOp::create(builder, loc, addrOp);
3032 return mlir::success();
3035 if (init.has_value()) {
3036 if (mlir::isa<cir::FPAttr, cir::IntAttr, cir::BoolAttr>(init.value())) {
3038 init = initRewriter.visit(init.value());
3043 if (!init.value()) {
3044 op.emitError() <<
"unsupported initializer '" << init.value() <<
"'";
3045 return mlir::failure();
3047 }
else if (
auto constArr =
3048 mlir::dyn_cast<cir::ConstArrayAttr>(init.value())) {
3056 mlir::ModuleOp modOp = op->getParentOfType<mlir::ModuleOp>();
3058 constArr, symbolTables, typeConverter, modOp)) {
3059 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
3060 rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
3061 op, llvmType, isConst, linkage, symbol, bulkInit.value(),
3062 alignment, addrSpace, isDsoLocal, threadLocalMode, comdatAttr,
3064 return mlir::success();
3067 return matchAndRewriteRegionInitializedGlobal(op, init.value(), rewriter);
3068 }
else if (
auto constRecord =
3069 mlir::dyn_cast<cir::ConstRecordAttr>(init.value())) {
3075 mlir::ModuleOp modOp = op->getParentOfType<mlir::ModuleOp>();
3077 constRecord, symbolTables, typeConverter, modOp)) {
3078 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
3079 rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
3080 op, llvmType, isConst, linkage, symbol, bulkInit.value(), alignment,
3081 addrSpace, isDsoLocal, threadLocalMode, comdatAttr, attributes);
3082 return mlir::success();
3084 return matchAndRewriteRegionInitializedGlobal(op, init.value(), rewriter);
3085 }
else if (mlir::isa<cir::BlockAddrDiffAttr, cir::BlockAddrInfoAttr,
3086 cir::ConstVectorAttr, cir::ConstRecordAttr,
3087 cir::ConstPtrAttr, cir::ConstComplexAttr,
3088 cir::GlobalOffsetAttr, cir::GlobalViewAttr,
3089 cir::TypeInfoAttr, cir::UndefAttr, cir::PoisonAttr,
3090 cir::VTableAttr, cir::ZeroAttr>(init.value())) {
3094 return matchAndRewriteRegionInitializedGlobal(op, init.value(), rewriter);
3098 op.emitError() <<
"unsupported initializer '" << init.value() <<
"'";
3099 return mlir::failure();
3103 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
3104 rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
3105 op, llvmType, isConst, linkage, symbol, init.value_or(mlir::Attribute()),
3106 alignment, addrSpace, isDsoLocal, threadLocalMode, comdatAttr,
3109 return mlir::success();
3113CIRToLLVMGlobalOpLowering::getComdatAttr(cir::GlobalOp &op,
3114 mlir::OpBuilder &builder)
const {
3115 if (!op.getComdat())
3116 return mlir::SymbolRefAttr{};
3118 mlir::ModuleOp modOp = op->getParentOfType<mlir::ModuleOp>();
3119 mlir::OpBuilder::InsertionGuard guard(builder);
3120 StringRef comdatName(
"__llvm_comdat_globals");
3122 builder.setInsertionPointToStart(modOp.getBody());
3124 mlir::LLVM::ComdatOp::create(builder, modOp.getLoc(), comdatName);
3127 if (
auto comdatSelector = comdatOp.lookupSymbol<mlir::LLVM::ComdatSelectorOp>(
3129 return mlir::SymbolRefAttr::get(
3130 builder.getContext(), comdatName,
3131 mlir::FlatSymbolRefAttr::get(comdatSelector.getSymNameAttr()));
3134 builder.setInsertionPointToStart(&comdatOp.getBody().back());
3135 auto selectorOp = mlir::LLVM::ComdatSelectorOp::create(
3136 builder, comdatOp.getLoc(), op.getSymName(),
3137 mlir::LLVM::comdat::Comdat::Any,
nullptr);
3138 return mlir::SymbolRefAttr::get(
3139 builder.getContext(), comdatName,
3140 mlir::FlatSymbolRefAttr::get(selectorOp.getSymNameAttr()));
3143mlir::LogicalResult CIRToLLVMSwitchFlatOpLowering::matchAndRewrite(
3144 cir::SwitchFlatOp op, OpAdaptor adaptor,
3145 mlir::ConversionPatternRewriter &rewriter)
const {
3147 llvm::SmallVector<mlir::APInt, 8> caseValues;
3148 for (mlir::Attribute val : op.getCaseValues()) {
3149 auto intAttr = cast<cir::IntAttr>(val);
3150 caseValues.push_back(intAttr.getValue());
3153 llvm::SmallVector<mlir::Block *, 8> caseDestinations;
3154 llvm::SmallVector<mlir::ValueRange, 8> caseOperands;
3156 for (mlir::Block *x : op.getCaseDestinations())
3157 caseDestinations.push_back(x);
3159 for (mlir::OperandRange x : op.getCaseOperands())
3160 caseOperands.push_back(x);
3163 rewriter.setInsertionPoint(op);
3164 rewriter.replaceOpWithNewOp<mlir::LLVM::SwitchOp>(
3165 op, adaptor.getCondition(), op.getDefaultDestination(),
3166 op.getDefaultOperands(), caseValues, caseDestinations, caseOperands);
3167 return mlir::success();
3170static mlir::LLVM::IntegerOverflowFlags
nswFlag(
bool nsw) {
3171 return nsw ? mlir::LLVM::IntegerOverflowFlags::nsw
3172 : mlir::LLVM::IntegerOverflowFlags::none;
3175template <
typename CIROp,
typename LLVMIntOp>
3176static mlir::LogicalResult
3178 mlir::ConversionPatternRewriter &rewriter) {
3179 mlir::Type llvmType = adaptor.getInput().getType();
3180 mlir::Location loc = op.getLoc();
3182 auto maybeNSW =
nswFlag(op.getNoSignedWrap());
3183 mlir::LLVM::ConstantOp one;
3184 if (mlir::isa<cir::VectorType>(op.getType())) {
3185 mlir::DenseIntElementsAttr oneVec = mlir::DenseIntElementsAttr::get(
3186 mlir::cast<mlir::ShapedType>(llvmType), 1);
3187 one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, oneVec);
3189 one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
3191 rewriter.replaceOpWithNewOp<LLVMIntOp>(op, adaptor.getInput(), one, maybeNSW);
3192 return mlir::success();
3195mlir::LogicalResult CIRToLLVMIncOpLowering::matchAndRewrite(
3196 cir::IncOp op, OpAdaptor adaptor,
3197 mlir::ConversionPatternRewriter &rewriter)
const {
3201mlir::LogicalResult CIRToLLVMDecOpLowering::matchAndRewrite(
3202 cir::DecOp op, OpAdaptor adaptor,
3203 mlir::ConversionPatternRewriter &rewriter)
const {
3207mlir::LogicalResult CIRToLLVMMinusOpLowering::matchAndRewrite(
3208 cir::MinusOp op, OpAdaptor adaptor,
3209 mlir::ConversionPatternRewriter &rewriter)
const {
3210 bool isVector = mlir::isa<cir::VectorType>(op.getType());
3211 mlir::Type llvmType = adaptor.getInput().getType();
3212 mlir::Location loc = op.getLoc();
3214 auto maybeNSW =
nswFlag(op.getNoSignedWrap());
3217 zero = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmType);
3219 zero = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 0);
3220 rewriter.replaceOpWithNewOp<mlir::LLVM::SubOp>(op, zero, adaptor.getInput(),
3222 return mlir::success();
3225mlir::LogicalResult CIRToLLVMNotOpLowering::matchAndRewrite(
3226 cir::NotOp op, OpAdaptor adaptor,
3227 mlir::ConversionPatternRewriter &rewriter)
const {
3228 mlir::Type elementType = elementTypeIfVector(op.getType());
3229 bool isVector = mlir::isa<cir::VectorType>(op.getType());
3230 mlir::Type llvmType = adaptor.getInput().getType();
3231 mlir::Location loc = op.getLoc();
3233 if (mlir::isa<cir::IntType>(elementType)) {
3234 mlir::Value minusOne;
3237 mlir::cast<cir::VectorType>(op.getType()).getSize();
3238 const unsigned eltWidth =
3239 mlir::cast<cir::IntType>(elementType).getWidth();
3240 SmallVector<APInt> values(numElements, APInt::getAllOnes(eltWidth));
3241 mlir::DenseIntElementsAttr denseVec = mlir::DenseIntElementsAttr::get(
3242 mlir::cast<mlir::ShapedType>(llvmType), values);
3244 mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, denseVec);
3246 minusOne = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, -1);
3248 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getInput(),
3250 return mlir::success();
3253 if (mlir::isa<cir::BoolType>(elementType)) {
3257 mlir::cast<cir::VectorType>(op.getType()).getSize();
3258 SmallVector<bool> values(numElements,
true);
3259 mlir::DenseIntElementsAttr denseVec = rewriter.getBoolVectorAttr(values);
3260 one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, denseVec);
3262 one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
3264 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getInput(), one);
3265 return mlir::success();
3268 return op.emitError() <<
"Unsupported type for bitwise NOT";
3273 return mlir::isa<cir::IntType>(type)
3274 ? mlir::cast<cir::IntType>(type).isUnsigned()
3275 : mlir::cast<mlir::IntegerType>(type).isUnsigned();
3282template <
typename BinOp>
3284 if (op.getNoUnsignedWrap())
3285 return mlir::LLVM::IntegerOverflowFlags::nuw;
3286 if (op.getNoSignedWrap())
3287 return mlir::LLVM::IntegerOverflowFlags::nsw;
3288 return mlir::LLVM::IntegerOverflowFlags::none;
3293template <
typename UIntSatOp,
typename SIntSatOp,
typename IntOp,
3295static mlir::LogicalResult
3297 mlir::ConversionPatternRewriter &rewriter) {
3298 const mlir::Type eltType = elementTypeIfVector(op.getRhs().getType());
3299 assert(cir::isIntOrBoolType(eltType) &&
3300 "saturatable arith op expects integer operand types");
3301 if (op.getSaturated()) {
3303 rewriter.replaceOpWithNewOp<UIntSatOp>(op, lhs, rhs);
3305 rewriter.replaceOpWithNewOp<SIntSatOp>(op, lhs, rhs);
3306 return mlir::success();
3308 rewriter.replaceOpWithNewOp<IntOp>(op, lhs, rhs,
intOverflowFlag(op));
3309 return mlir::success();
3312mlir::LogicalResult CIRToLLVMAddOpLowering::matchAndRewrite(
3313 cir::AddOp op, OpAdaptor adaptor,
3314 mlir::ConversionPatternRewriter &rewriter)
const {
3316 mlir::LLVM::AddOp>(op, adaptor.getLhs(),
3317 adaptor.getRhs(), rewriter);
3320mlir::LogicalResult CIRToLLVMSubOpLowering::matchAndRewrite(
3321 cir::SubOp op, OpAdaptor adaptor,
3322 mlir::ConversionPatternRewriter &rewriter)
const {
3324 mlir::LLVM::SubOp>(op, adaptor.getLhs(),
3325 adaptor.getRhs(), rewriter);
3328mlir::LogicalResult CIRToLLVMMulOpLowering::matchAndRewrite(
3329 cir::MulOp op, OpAdaptor adaptor,
3330 mlir::ConversionPatternRewriter &rewriter)
const {
3331 assert(cir::isIntOrBoolType(elementTypeIfVector(op.getRhs().getType())) &&
3332 "cir.mul expects integer operand types");
3333 rewriter.replaceOpWithNewOp<mlir::LLVM::MulOp>(
3335 return mlir::success();
3339template <
typename UIntOp,
typename SIntOp,
typename CIROp>
3340static mlir::LogicalResult
3342 mlir::ConversionPatternRewriter &rewriter) {
3343 const mlir::Type eltType = elementTypeIfVector(op.getRhs().getType());
3344 assert(cir::isIntOrBoolType(eltType) &&
3345 "integer binary op expects integer operand types");
3347 rewriter.replaceOpWithNewOp<UIntOp>(op, lhs, rhs);
3349 rewriter.replaceOpWithNewOp<SIntOp>(op, lhs, rhs);
3350 return mlir::success();
3353mlir::LogicalResult CIRToLLVMDivOpLowering::matchAndRewrite(
3354 cir::DivOp op, OpAdaptor adaptor,
3355 mlir::ConversionPatternRewriter &rewriter)
const {
3357 op, adaptor.getLhs(), adaptor.getRhs(), rewriter);
3360mlir::LogicalResult CIRToLLVMRemOpLowering::matchAndRewrite(
3361 cir::RemOp op, OpAdaptor adaptor,
3362 mlir::ConversionPatternRewriter &rewriter)
const {
3364 op, adaptor.getLhs(), adaptor.getRhs(), rewriter);
3367template <
typename CIROp,
typename UIntOp,
typename SIntOp>
3368static mlir::LogicalResult
3370 mlir::ConversionPatternRewriter &rewriter) {
3371 const mlir::Value lhs = adaptor.getLhs();
3372 const mlir::Value rhs = adaptor.getRhs();
3374 rewriter.replaceOpWithNewOp<UIntOp>(op, lhs, rhs);
3376 rewriter.replaceOpWithNewOp<SIntOp>(op, lhs, rhs);
3377 return mlir::success();
3380mlir::LogicalResult CIRToLLVMMaxOpLowering::matchAndRewrite(
3381 cir::MaxOp op, OpAdaptor adaptor,
3382 mlir::ConversionPatternRewriter &rewriter)
const {
3384 op, adaptor, rewriter);
3387mlir::LogicalResult CIRToLLVMMinOpLowering::matchAndRewrite(
3388 cir::MinOp op, OpAdaptor adaptor,
3389 mlir::ConversionPatternRewriter &rewriter)
const {
3391 op, adaptor, rewriter);
3395static mlir::LLVM::ICmpPredicate
3397 using CIR = cir::CmpOpKind;
3398 using LLVMICmp = mlir::LLVM::ICmpPredicate;
3401 return LLVMICmp::eq;
3403 return LLVMICmp::ne;
3405 return (isSigned ? LLVMICmp::slt : LLVMICmp::ult);
3407 return (isSigned ? LLVMICmp::sle : LLVMICmp::ule);
3409 return (isSigned ? LLVMICmp::sgt : LLVMICmp::ugt);
3411 return (isSigned ? LLVMICmp::sge : LLVMICmp::uge);
3414 llvm_unreachable(
"FP-only comparison used with integer type");
3416 llvm_unreachable(
"Unknown CmpOpKind");
3421static mlir::LLVM::FCmpPredicate
3423 using CIR = cir::CmpOpKind;
3424 using LLVMFCmp = mlir::LLVM::FCmpPredicate;
3427 return LLVMFCmp::oeq;
3429 return LLVMFCmp::une;
3431 return LLVMFCmp::olt;
3433 return LLVMFCmp::ole;
3435 return LLVMFCmp::ogt;
3437 return LLVMFCmp::oge;
3439 return LLVMFCmp::one;
3441 return LLVMFCmp::uno;
3443 llvm_unreachable(
"Unknown CmpOpKind");
3446static llvm::StringRef
3448 using CIR = cir::CmpOpKind;
3467 llvm_unreachable(
"Unknown CmpOpKind");
3471 using CIR = cir::CmpOpKind;
3484 llvm_unreachable(
"Unknown CmpOpKind");
3487static mlir::LLVM::CallIntrinsicOp
3489 mlir::Location loc, mlir::Value lhs, mlir::Value rhs,
3490 cir::CmpOpKind
kind, cir::FenvAttr fenv,
3491 mlir::Type llvmResTy) {
3499 ?
"llvm.experimental.constrained.fcmps"
3500 :
"llvm.experimental.constrained.fcmp";
3505mlir::LogicalResult CIRToLLVMCmpOpLowering::matchAndRewrite(
3506 cir::CmpOp cmpOp, OpAdaptor adaptor,
3507 mlir::ConversionPatternRewriter &rewriter)
const {
3508 mlir::Type type = cmpOp.getLhs().getType();
3510 if (mlir::isa<cir::IntType, mlir::IntegerType>(type)) {
3511 bool isSigned = mlir::isa<cir::IntType>(type)
3512 ? mlir::cast<cir::IntType>(type).isSigned()
3513 : mlir::cast<mlir::IntegerType>(type).isSigned();
3514 mlir::LLVM::ICmpPredicate
kind =
3516 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
3517 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
3518 return mlir::success();
3521 if (mlir::isa<cir::BoolType, cir::PointerType, cir::VPtrType>(type)) {
3525 mlir::LLVM::ICmpPredicate
kind =
3527 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
3528 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
3529 return mlir::success();
3532 if (mlir::isa<cir::FPTypeInterface>(type)) {
3533 mlir::Type llvmResTy = getTypeConverter()->convertType(cmpOp.getType());
3534 if (cir::FenvAttr fenv = cmpOp.getFenvAttr()) {
3536 rewriter, cmpOp.getLoc(), adaptor.getLhs(), adaptor.getRhs(),
3537 cmpOp.getKind(), fenv, llvmResTy);
3538 rewriter.replaceOp(cmpOp, call.getResult(0));
3539 return mlir::success();
3541 mlir::LLVM::FCmpPredicate
kind =
3543 rewriter.replaceOpWithNewOp<mlir::LLVM::FCmpOp>(
3544 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
3545 return mlir::success();
3548 if (mlir::isa<cir::ComplexType>(type)) {
3549 mlir::Value lhs = adaptor.getLhs();
3550 mlir::Value rhs = adaptor.getRhs();
3551 mlir::Location loc = cmpOp.getLoc();
3553 auto complexType = mlir::cast<cir::ComplexType>(cmpOp.getLhs().getType());
3554 mlir::Type complexElemTy =
3555 getTypeConverter()->convertType(
complexType.getElementType());
3557 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
3558 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{0}));
3559 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
3560 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{1}));
3561 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
3562 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{0}));
3563 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
3564 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{1}));
3566 if (cmpOp.getKind() == cir::CmpOpKind::eq) {
3567 if (complexElemTy.isInteger()) {
3568 auto realCmp = mlir::LLVM::ICmpOp::create(
3569 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, lhsReal, rhsReal);
3570 auto imagCmp = mlir::LLVM::ICmpOp::create(
3571 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, lhsImag, rhsImag);
3572 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, imagCmp);
3573 return mlir::success();
3576 auto realCmp = mlir::LLVM::FCmpOp::create(
3577 rewriter, loc, mlir::LLVM::FCmpPredicate::oeq, lhsReal, rhsReal);
3578 auto imagCmp = mlir::LLVM::FCmpOp::create(
3579 rewriter, loc, mlir::LLVM::FCmpPredicate::oeq, lhsImag, rhsImag);
3580 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, imagCmp);
3581 return mlir::success();
3584 if (cmpOp.getKind() == cir::CmpOpKind::ne) {
3585 if (complexElemTy.isInteger()) {
3586 auto realCmp = mlir::LLVM::ICmpOp::create(
3587 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, lhsReal, rhsReal);
3588 auto imagCmp = mlir::LLVM::ICmpOp::create(
3589 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, lhsImag, rhsImag);
3590 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp);
3591 return mlir::success();
3594 auto realCmp = mlir::LLVM::FCmpOp::create(
3595 rewriter, loc, mlir::LLVM::FCmpPredicate::une, lhsReal, rhsReal);
3596 auto imagCmp = mlir::LLVM::FCmpOp::create(
3597 rewriter, loc, mlir::LLVM::FCmpPredicate::une, lhsImag, rhsImag);
3598 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp);
3599 return mlir::success();
3603 return cmpOp.emitError() <<
"unsupported type for CmpOp: " <<
type;
3609template <
typename OpTy>
3610static mlir::LogicalResult
3612 mlir::ConversionPatternRewriter &rewriter,
3613 const mlir::TypeConverter *typeConverter,
3614 llvm::StringRef opStr) {
3615 mlir::Location loc = op.getLoc();
3616 cir::IntType operandTy = op.getLhs().getType();
3619 mlir::Type resultTy = op.getResult().getType();
3620 auto resultIntTy = mlir::dyn_cast<cir::IntType>(resultTy);
3621 unsigned resultWidth = resultIntTy ? resultIntTy.getWidth() : 1;
3622 bool resultSigned = resultIntTy && resultIntTy.getIsSigned();
3624 bool sign = operandTy.getIsSigned() || resultSigned;
3626 std::max(operandTy.getWidth() + (
sign && operandTy.isUnsigned()),
3627 resultWidth + (
sign && !resultSigned));
3629 mlir::IntegerType encompassedLLVMTy = rewriter.getIntegerType(width);
3631 mlir::Value lhs = adaptor.getLhs();
3632 mlir::Value rhs = adaptor.getRhs();
3633 if (operandTy.getWidth() < width) {
3634 if (operandTy.isSigned()) {
3635 lhs = mlir::LLVM::SExtOp::create(rewriter, loc, encompassedLLVMTy, lhs);
3636 rhs = mlir::LLVM::SExtOp::create(rewriter, loc, encompassedLLVMTy, rhs);
3638 lhs = mlir::LLVM::ZExtOp::create(rewriter, loc, encompassedLLVMTy, lhs);
3639 rhs = mlir::LLVM::ZExtOp::create(rewriter, loc, encompassedLLVMTy, rhs);
3644 std::string intrinName = (
"llvm." + llvm::Twine(
sign ?
's' :
'u') + opStr +
3645 ".with.overflow.i" + llvm::Twine(width))
3647 auto intrinNameAttr = mlir::StringAttr::get(op.getContext(), intrinName);
3649 mlir::IntegerType overflowLLVMTy = rewriter.getI1Type();
3650 auto intrinRetTy = mlir::LLVM::LLVMStructType::getLiteral(
3651 rewriter.getContext(), {encompassedLLVMTy, overflowLLVMTy});
3653 auto callLLVMIntrinOp = mlir::LLVM::CallIntrinsicOp::create(
3654 rewriter, loc, intrinRetTy, intrinNameAttr, mlir::ValueRange{lhs, rhs});
3655 mlir::Value intrinRet = callLLVMIntrinOp.getResult(0);
3657 mlir::Value result = mlir::LLVM::ExtractValueOp::create(
3660 mlir::Value overflow = mlir::LLVM::ExtractValueOp::create(
3664 if (resultWidth < width) {
3665 mlir::Type resultLLVMTy = typeConverter->convertType(resultTy);
3667 mlir::LLVM::TruncOp::create(rewriter, loc, resultLLVMTy, result);
3671 mlir::Value truncResultExt;
3673 truncResultExt = mlir::LLVM::SExtOp::create(
3674 rewriter, loc, encompassedLLVMTy, truncResult);
3676 truncResultExt = mlir::LLVM::ZExtOp::create(
3677 rewriter, loc, encompassedLLVMTy, truncResult);
3678 auto truncOverflow = mlir::LLVM::ICmpOp::create(
3679 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, truncResultExt, result);
3681 result = truncResult;
3682 overflow = mlir::LLVM::OrOp::create(rewriter, loc, overflow, truncOverflow);
3685 mlir::Type boolLLVMTy =
3686 typeConverter->convertType(op.getOverflow().getType());
3687 if (boolLLVMTy != rewriter.getI1Type())
3688 overflow = mlir::LLVM::ZExtOp::create(rewriter, loc, boolLLVMTy, overflow);
3690 rewriter.replaceOp(op, mlir::ValueRange{result, overflow});
3692 return mlir::success();
3695mlir::LogicalResult CIRToLLVMAddOverflowOpLowering::matchAndRewrite(
3696 cir::AddOverflowOp op, OpAdaptor adaptor,
3697 mlir::ConversionPatternRewriter &rewriter)
const {
3701mlir::LogicalResult CIRToLLVMSubOverflowOpLowering::matchAndRewrite(
3702 cir::SubOverflowOp op, OpAdaptor adaptor,
3703 mlir::ConversionPatternRewriter &rewriter)
const {
3707mlir::LogicalResult CIRToLLVMMulOverflowOpLowering::matchAndRewrite(
3708 cir::MulOverflowOp op, OpAdaptor adaptor,
3709 mlir::ConversionPatternRewriter &rewriter)
const {
3713mlir::LogicalResult CIRToLLVMFrexpOpLowering::matchAndRewrite(
3714 cir::FrexpOp op, OpAdaptor adaptor,
3715 mlir::ConversionPatternRewriter &rewriter)
const {
3716 mlir::Location loc = op.getLoc();
3717 mlir::Type fpLLVMTy =
3718 getTypeConverter()->convertType(op.getResult().getType());
3719 mlir::Type intLLVMTy = getTypeConverter()->convertType(op.getExp().getType());
3721 auto structTy = mlir::LLVM::LLVMStructType::getLiteral(rewriter.getContext(),
3722 {fpLLVMTy, intLLVMTy});
3726 mlir::Value result = callOp.getResult(0);
3728 mlir::Value mantissa =
3729 mlir::LLVM::ExtractValueOp::create(rewriter, loc, result, 0);
3730 mlir::Value exponent =
3731 mlir::LLVM::ExtractValueOp::create(rewriter, loc, result, 1);
3732 rewriter.replaceOp(op, mlir::ValueRange{mantissa, exponent});
3733 return mlir::success();
3736mlir::LogicalResult CIRToLLVMModfOpLowering::matchAndRewrite(
3737 cir::ModfOp op, OpAdaptor adaptor,
3738 mlir::ConversionPatternRewriter &rewriter)
const {
3739 mlir::Location loc = op.getLoc();
3740 mlir::Type fpLLVMTy =
3741 getTypeConverter()->convertType(op.getFractional().getType());
3743 auto structTy = mlir::LLVM::LLVMStructType::getLiteral(rewriter.getContext(),
3744 {fpLLVMTy, fpLLVMTy});
3748 mlir::Value result = callOp.getResult(0);
3750 mlir::Value fractional =
3751 mlir::LLVM::ExtractValueOp::create(rewriter, loc, result, 0);
3752 mlir::Value integral =
3753 mlir::LLVM::ExtractValueOp::create(rewriter, loc, result, 1);
3754 rewriter.replaceOp(op, mlir::ValueRange{fractional, integral});
3755 return mlir::success();
3758mlir::LogicalResult CIRToLLVMShiftOpLowering::matchAndRewrite(
3759 cir::ShiftOp op, OpAdaptor adaptor,
3760 mlir::ConversionPatternRewriter &rewriter)
const {
3761 assert((op.getValue().getType() == op.getType()) &&
3762 "inconsistent operands' types NYI");
3764 const mlir::Type llvmTy = getTypeConverter()->convertType(op.getType());
3765 mlir::Value amt = adaptor.getAmount();
3766 mlir::Value val = adaptor.getValue();
3768 auto cirAmtTy = mlir::dyn_cast<cir::IntType>(op.getAmount().getType());
3771 auto cirValTy = mlir::cast<cir::IntType>(op.getValue().getType());
3779 amt =
getLLVMIntCast(rewriter, amt, llvmTy,
true, cirAmtTy.getWidth(),
3780 cirValTy.getWidth());
3782 auto cirValVTy = mlir::cast<cir::VectorType>(op.getValue().getType());
3784 mlir::cast<cir::IntType>(cirValVTy.getElementType()).isUnsigned();
3788 if (op.getIsShiftleft()) {
3789 rewriter.replaceOpWithNewOp<mlir::LLVM::ShlOp>(op, llvmTy, val, amt);
3790 return mlir::success();
3794 rewriter.replaceOpWithNewOp<mlir::LLVM::LShrOp>(op, llvmTy, val, amt);
3796 rewriter.replaceOpWithNewOp<mlir::LLVM::AShrOp>(op, llvmTy, val, amt);
3797 return mlir::success();
3800mlir::LogicalResult CIRToLLVMSelectOpLowering::matchAndRewrite(
3801 cir::SelectOp op, OpAdaptor adaptor,
3802 mlir::ConversionPatternRewriter &rewriter)
const {
3803 auto getConstantBool = [](mlir::Value value) -> cir::BoolAttr {
3804 auto definingOp = value.getDefiningOp<cir::ConstantOp>();
3808 auto constValue = definingOp.getValueAttr<cir::BoolAttr>();
3818 if (mlir::isa<cir::BoolType>(op.getTrueValue().getType())) {
3819 cir::BoolAttr trueValue = getConstantBool(op.getTrueValue());
3820 cir::BoolAttr falseValue = getConstantBool(op.getFalseValue());
3821 if (falseValue && !falseValue.getValue()) {
3823 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(op, adaptor.getCondition(),
3824 adaptor.getTrueValue());
3825 return mlir::success();
3827 if (trueValue && trueValue.getValue()) {
3829 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(op, adaptor.getCondition(),
3830 adaptor.getFalseValue());
3831 return mlir::success();
3835 mlir::Value llvmCondition = adaptor.getCondition();
3836 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(
3837 op, llvmCondition, adaptor.getTrueValue(), adaptor.getFalseValue());
3839 return mlir::success();
3843 mlir::DataLayout &dataLayout) {
3844 converter.addConversion([&](cir::PointerType type) -> mlir::Type {
3845 mlir::ptr::MemorySpaceAttrInterface addrSpaceAttr = type.getAddrSpace();
3846 unsigned numericAS = 0;
3848 if (
auto targetAsAttr =
3849 mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
3851 numericAS = targetAsAttr.getValue();
3852 return mlir::LLVM::LLVMPointerType::get(type.getContext(), numericAS);
3854 converter.addConversion([&](cir::VPtrType type) -> mlir::Type {
3856 return mlir::LLVM::LLVMPointerType::get(type.getContext());
3858 converter.addConversion([&](cir::CUDADeviceTextureType type) -> mlir::Type {
3859 return mlir::IntegerType::get(type.getContext(), 64);
3861 converter.addConversion([&](cir::ArrayType type) -> mlir::Type {
3868 return mlir::LLVM::LLVMArrayType::get(ty, type.getSize());
3870 converter.addConversion([&](cir::VectorType type) -> mlir::Type {
3874 if (
auto intTy = mlir::dyn_cast<cir::IntType>(type.getElementType());
3875 intTy && intTy.isBitInt())
3877 const mlir::Type ty = converter.convertType(type.getElementType());
3878 return mlir::VectorType::get(type.getSize(), ty, {type.getIsScalable()});
3880 converter.addConversion([&](cir::BoolType type) -> mlir::Type {
3881 return mlir::IntegerType::get(type.getContext(), 1,
3882 mlir::IntegerType::Signless);
3884 converter.addConversion([&](cir::IntType type) -> mlir::Type {
3886 return mlir::IntegerType::get(type.getContext(), type.getWidth());
3888 converter.addConversion([&](cir::SingleType type) -> mlir::Type {
3889 return mlir::Float32Type::get(type.getContext());
3891 converter.addConversion([&](cir::DoubleType type) -> mlir::Type {
3892 return mlir::Float64Type::get(type.getContext());
3894 converter.addConversion([&](cir::FP80Type type) -> mlir::Type {
3895 return mlir::Float80Type::get(type.getContext());
3897 converter.addConversion([&](cir::FP128Type type) -> mlir::Type {
3898 return mlir::Float128Type::get(type.getContext());
3900 converter.addConversion([&](cir::LongDoubleType type) -> mlir::Type {
3901 return converter.convertType(type.getUnderlying());
3903 converter.addConversion([&](cir::FP16Type type) -> mlir::Type {
3904 return mlir::Float16Type::get(type.getContext());
3906 converter.addConversion([&](cir::BF16Type type) -> mlir::Type {
3907 return mlir::BFloat16Type::get(type.getContext());
3909 converter.addConversion([&](cir::ComplexType type) -> mlir::Type {
3912 mlir::Type elementTy = converter.convertType(type.getElementType());
3913 mlir::Type structFields[2] = {elementTy, elementTy};
3914 return mlir::LLVM::LLVMStructType::getLiteral(type.getContext(),
3917 converter.addConversion([&](cir::FuncType type) -> std::optional<mlir::Type> {
3918 auto result = converter.convertType(type.getReturnType());
3920 arguments.reserve(type.getNumInputs());
3921 if (converter.convertTypes(type.getInputs(), arguments).failed())
3922 return std::nullopt;
3923 auto varArg = type.isVarArg();
3924 return mlir::LLVM::LLVMFunctionType::get(result, arguments, varArg);
3926 converter.addConversion([&](cir::StructType type) -> mlir::Type {
3928 for (mlir::Type ty : type.getMembers()) {
3941 llvmMembers.push_back(memberTy);
3944 mlir::LLVM::LLVMStructType llvmStruct;
3945 if (type.getName()) {
3946 llvmStruct = mlir::LLVM::LLVMStructType::getIdentified(
3947 type.getContext(), type.getPrefixedName());
3948 if (llvmStruct.setBody(llvmMembers, type.getPacked()).failed())
3949 llvm_unreachable(
"Failed to set body of record");
3951 llvmStruct = mlir::LLVM::LLVMStructType::getLiteral(
3952 type.getContext(), llvmMembers, type.getPacked());
3957 converter.addConversion([&](cir::UnionType type) -> mlir::Type {
3959 if (!type.getMembers().empty())
3960 if (
auto storage = type.getUnionStorageType(dataLayout)) {
3961 mlir::Type storageTy =
3965 llvmMembers.push_back(storageTy);
3967 if (mlir::Type pad = type.getPadding()) {
3971 llvmMembers.push_back(padTy);
3974 mlir::LLVM::LLVMStructType llvmStruct;
3975 if (type.getName()) {
3976 llvmStruct = mlir::LLVM::LLVMStructType::getIdentified(
3977 type.getContext(), type.getPrefixedName());
3978 if (llvmStruct.setBody(llvmMembers, type.getPacked()).failed())
3979 llvm_unreachable(
"Failed to set body of record");
3981 llvmStruct = mlir::LLVM::LLVMStructType::getLiteral(
3982 type.getContext(), llvmMembers, type.getPacked());
3986 converter.addConversion([&](cir::VoidType type) -> mlir::Type {
3987 return mlir::LLVM::LLVMVoidType::get(type.getContext());
3992 mlir::ModuleOp module, StringRef globalXtorName, StringRef llvmXtorName,
3993 llvm::function_ref<std::pair<StringRef, int>(mlir::Attribute)> createXtor) {
3995 for (
const mlir::NamedAttribute namedAttr : module->getAttrs()) {
3996 if (namedAttr.getName() == globalXtorName) {
3997 for (
auto attr : mlir::cast<mlir::ArrayAttr>(namedAttr.getValue()))
3998 globalXtors.emplace_back(createXtor(attr));
4003 if (globalXtors.empty())
4006 mlir::OpBuilder builder(module.getContext());
4007 builder.setInsertionPointToEnd(&module.getBodyRegion().back());
4011 auto ctorPFTy = mlir::LLVM::LLVMPointerType::get(builder.getContext());
4013 ctorStructFields.push_back(builder.getI32Type());
4014 ctorStructFields.push_back(ctorPFTy);
4015 ctorStructFields.push_back(ctorPFTy);
4017 auto ctorStructTy = mlir::LLVM::LLVMStructType::getLiteral(
4018 builder.getContext(), ctorStructFields);
4019 auto ctorStructArrayTy =
4020 mlir::LLVM::LLVMArrayType::get(ctorStructTy, globalXtors.size());
4022 mlir::Location loc =
module.getLoc();
4023 auto newGlobalOp = mlir::LLVM::GlobalOp::create(
4024 builder, loc, ctorStructArrayTy,
false,
4025 mlir::LLVM::Linkage::Appending, llvmXtorName, mlir::Attribute());
4027 builder.createBlock(&newGlobalOp.getRegion());
4028 builder.setInsertionPointToEnd(newGlobalOp.getInitializerBlock());
4030 mlir::Value result =
4031 mlir::LLVM::UndefOp::create(builder, loc, ctorStructArrayTy);
4033 for (
auto [index, fn] : llvm::enumerate(globalXtors)) {
4034 mlir::Value structInit =
4035 mlir::LLVM::UndefOp::create(builder, loc, ctorStructTy);
4036 mlir::Value initPriority = mlir::LLVM::ConstantOp::create(
4037 builder, loc, ctorStructFields[0], fn.second);
4038 mlir::Value initFuncAddr = mlir::LLVM::AddressOfOp::create(
4039 builder, loc, ctorStructFields[1], fn.first);
4040 mlir::Value initAssociate =
4041 mlir::LLVM::ZeroOp::create(builder, loc, ctorStructFields[2]);
4044 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
4045 initPriority, zero);
4046 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
4049 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
4051 result = mlir::LLVM::InsertValueOp::create(builder, loc, result, structInit,
4055 mlir::LLVM::ReturnOp::create(builder, loc, result);
4058mlir::LogicalResult CIRToLLVMObjSizeOpLowering::matchAndRewrite(
4059 cir::ObjSizeOp op, OpAdaptor adaptor,
4060 mlir::ConversionPatternRewriter &rewriter)
const {
4061 mlir::Type llvmResTy = getTypeConverter()->convertType(op.getType());
4062 mlir::Location loc = op->getLoc();
4064 mlir::IntegerType i1Ty = rewriter.getI1Type();
4066 auto i1Val = [&rewriter, &loc, &i1Ty](
bool val) {
4067 return mlir::LLVM::ConstantOp::create(rewriter, loc, i1Ty, val);
4074 i1Val(op.getNullunknown()),
4075 i1Val(op.getDynamic()),
4078 return mlir::LogicalResult::success();
4086constexpr StringRef llvmMetadataSectionName =
"llvm.metadata";
4091getOrCreateAnnotationStringGlobal(mlir::OpBuilder &builder, mlir::Location loc,
4092 mlir::ModuleOp module, llvm::StringRef str,
4093 llvm::StringMap<mlir::LLVM::GlobalOp> &cache,
4095 auto it = cache.find(str);
4096 if (it != cache.end())
4099 auto i8Ty = mlir::IntegerType::get(module.getContext(), 8);
4100 auto arrayTy = mlir::LLVM::LLVMArrayType::get(i8Ty, str.size() + 1);
4101 std::string
name =
".str";
4103 name +=
"." + std::to_string(cache.size());
4104 name +=
".annotation";
4108 mlir::LLVM::GlobalOp strGlobal = mlir::LLVM::GlobalOp::create(
4109 builder, loc, arrayTy,
true, mlir::LLVM::Linkage::Private,
4110 name, mlir::StringAttr::get(module.getContext(), std::string(str) +
'\0'),
4113 strGlobal.setSection(llvmMetadataSectionName);
4114 strGlobal.setUnnamedAddr(mlir::LLVM::UnnamedAddr::Global);
4115 strGlobal.setDsoLocal(
true);
4116 cache[str] = strGlobal;
4122mlir::LLVM::GlobalOp getOrCreateAnnotationArgsVar(
4123 mlir::OpBuilder &builder, mlir::Location loc, mlir::ModuleOp module,
4124 mlir::ArrayAttr argsAttr,
4125 llvm::StringMap<mlir::LLVM::GlobalOp> &argStringCache,
4126 llvm::MapVector<mlir::ArrayAttr, mlir::LLVM::GlobalOp> &argsCache) {
4127 auto it = argsCache.find(argsAttr);
4128 if (it != argsCache.end())
4131 auto ptrTy = mlir::LLVM::LLVMPointerType::get(builder.getContext());
4133 llvm::SmallVector<mlir::Type> fieldTypes;
4134 for (mlir::Attribute arg : argsAttr) {
4135 if (mlir::isa<mlir::StringAttr>(arg))
4136 fieldTypes.push_back(ptrTy);
4137 else if (
auto intAttr = mlir::dyn_cast<mlir::IntegerAttr>(arg))
4138 fieldTypes.push_back(intAttr.getType());
4140 llvm_unreachable(
"Unsupported annotation arg type");
4144 mlir::LLVM::LLVMStructType::getLiteral(builder.getContext(), fieldTypes);
4145 std::string
name =
".args";
4146 if (!argsCache.empty())
4147 name +=
"." + std::to_string(argsCache.size());
4148 name +=
".annotation";
4150 mlir::LLVM::GlobalOp argsGlobal = mlir::LLVM::GlobalOp::create(
4151 builder, loc, structTy,
true, mlir::LLVM::Linkage::Private,
4152 name, mlir::Attribute());
4153 argsGlobal.setSection(llvmMetadataSectionName);
4154 argsGlobal.setUnnamedAddr(mlir::LLVM::UnnamedAddr::Global);
4155 argsGlobal.setDsoLocal(
true);
4158 argsGlobal.getRegion().push_back(
new mlir::Block());
4159 mlir::OpBuilder initBuilder(module.getContext());
4160 initBuilder.setInsertionPointToEnd(argsGlobal.getInitializerBlock());
4162 mlir::Value structInit =
4163 mlir::LLVM::UndefOp::create(initBuilder, loc, structTy);
4164 for (
auto [idx, arg] : llvm::enumerate(argsAttr)) {
4165 if (
auto strArg = mlir::dyn_cast<mlir::StringAttr>(arg)) {
4166 mlir::LLVM::GlobalOp strGlobal = getOrCreateAnnotationStringGlobal(
4167 builder, loc, module, strArg.getValue(), argStringCache,
4169 mlir::LLVM::AddressOfOp strAddr = mlir::LLVM::AddressOfOp::create(
4170 initBuilder, loc, ptrTy, strGlobal.getSymName());
4171 structInit = mlir::LLVM::InsertValueOp::create(initBuilder, loc,
4172 structInit, strAddr, idx);
4173 }
else if (
auto intArg = mlir::dyn_cast<mlir::IntegerAttr>(arg)) {
4174 mlir::LLVM::ConstantOp intConst = mlir::LLVM::ConstantOp::create(
4175 initBuilder, loc, intArg.getType(), intArg.getValue());
4176 structInit = mlir::LLVM::InsertValueOp::create(initBuilder, loc,
4177 structInit, intConst, idx);
4179 llvm_unreachable(
"Unsupported annotation arg type");
4182 mlir::LLVM::ReturnOp::create(initBuilder, loc, structInit);
4184 argsCache[argsAttr] = argsGlobal;
4190std::pair<llvm::StringRef, unsigned> extractFileLine(mlir::Location loc) {
4191 mlir::Location resolved = loc;
4192 if (
auto fused = mlir::dyn_cast<mlir::FusedLoc>(resolved)) {
4193 if (!fused.getLocations().empty())
4194 resolved = fused.getLocations()[0];
4196 if (
auto fl = mlir::dyn_cast<mlir::FileLineColLoc>(resolved))
4197 return {fl.getFilename().getValue(), fl.getLine()};
4203 auto handleArray = [&](mlir::StringAttr symName, mlir::ArrayAttr arr,
4204 mlir::Location loc) {
4207 for (mlir::Attribute a : arr)
4208 if (
auto annot = mlir::dyn_cast<cir::AnnotationAttr>(a))
4209 collectedAnnotations.emplace_back(symName, annot, loc);
4214 module.walk([&](cir::GlobalOp op) {
4215 handleArray(op.getSymNameAttr(), op.getAnnotationsAttr(), op.getLoc());
4217 module.walk([&](cir::FuncOp op) {
4218 handleArray(op.getSymNameAttr(), op.getAnnotationsAttr(), op.getLoc());
4223 if (collectedAnnotations.empty())
4226 mlir::MLIRContext *ctx =
module.getContext();
4227 mlir::OpBuilder builder(ctx);
4228 builder.setInsertionPointToEnd(&module.getBodyRegion().back());
4230 auto ptrTy = mlir::LLVM::LLVMPointerType::get(ctx);
4231 auto i32Ty = builder.getI32Type();
4234 auto entryTy = mlir::LLVM::LLVMStructType::getLiteral(
4235 ctx, {ptrTy, ptrTy, ptrTy, i32Ty, ptrTy});
4237 mlir::LLVM::LLVMArrayType::get(entryTy, collectedAnnotations.size());
4239 mlir::Location moduleLoc =
module.getLoc();
4240 auto annotationsGlobal = mlir::LLVM::GlobalOp::create(
4241 builder, moduleLoc, arrayTy,
false,
4242 mlir::LLVM::Linkage::Appending,
"llvm.global.annotations",
4244 annotationsGlobal.setSection(llvmMetadataSectionName);
4248 mlir::OpBuilder constsBuilder(ctx);
4249 constsBuilder.setInsertionPoint(annotationsGlobal);
4251 llvm::StringMap<mlir::LLVM::GlobalOp> stringCache;
4252 llvm::StringMap<mlir::LLVM::GlobalOp> argStringCache;
4253 llvm::MapVector<mlir::ArrayAttr, mlir::LLVM::GlobalOp> argsCache;
4256 annotationsGlobal.getRegion().push_back(
new mlir::Block());
4257 mlir::OpBuilder initBuilder(ctx);
4258 initBuilder.setInsertionPointToEnd(annotationsGlobal.getInitializerBlock());
4260 mlir::Value arrayVal =
4261 mlir::LLVM::UndefOp::create(initBuilder, moduleLoc, arrayTy);
4263 for (
auto [idx, entry] : llvm::enumerate(collectedAnnotations)) {
4264 mlir::Value entryVal =
4265 mlir::LLVM::UndefOp::create(initBuilder, moduleLoc, entryTy);
4270 mlir::LLVM::AddressOfOp symAddr = mlir::LLVM::AddressOfOp::create(
4271 initBuilder, moduleLoc, ptrTy, entry.symName.getValue());
4272 entryVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
4273 entryVal, symAddr, zero);
4276 mlir::LLVM::GlobalOp nameGlobal = getOrCreateAnnotationStringGlobal(
4277 constsBuilder, moduleLoc, module, entry.annotation.getName().getValue(),
4278 stringCache,
false);
4279 mlir::LLVM::AddressOfOp nameAddr = mlir::LLVM::AddressOfOp::create(
4280 initBuilder, moduleLoc, ptrTy, nameGlobal.getSymName());
4281 entryVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
4282 entryVal, nameAddr, 1);
4285 auto [filename, line] = extractFileLine(entry.loc);
4286 mlir::LLVM::GlobalOp fileGlobal = getOrCreateAnnotationStringGlobal(
4287 constsBuilder, moduleLoc, module, filename, stringCache,
4289 mlir::LLVM::AddressOfOp fileAddr = mlir::LLVM::AddressOfOp::create(
4290 initBuilder, moduleLoc, ptrTy, fileGlobal.getSymName());
4291 entryVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
4292 entryVal, fileAddr, 2);
4293 mlir::LLVM::ConstantOp lineConst =
4294 mlir::LLVM::ConstantOp::create(initBuilder, moduleLoc, i32Ty, line);
4295 entryVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
4296 entryVal, lineConst, 3);
4299 mlir::ArrayAttr args = entry.annotation.getArgs();
4300 mlir::Value argsField;
4301 if (!args || args.empty()) {
4302 argsField = mlir::LLVM::ZeroOp::create(initBuilder, moduleLoc, ptrTy);
4304 mlir::LLVM::GlobalOp argsGlobal = getOrCreateAnnotationArgsVar(
4305 constsBuilder, moduleLoc, module, args, argStringCache, argsCache);
4306 argsField = mlir::LLVM::AddressOfOp::create(initBuilder, moduleLoc, ptrTy,
4307 argsGlobal.getSymName());
4309 entryVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
4310 entryVal, argsField, 4);
4312 arrayVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
4313 arrayVal, entryVal, idx);
4316 mlir::LLVM::ReturnOp::create(initBuilder, moduleLoc, arrayVal);
4322 mlir::ModuleOp module = getOperation();
4323 mlir::OpBuilder opBuilder(module.getContext());
4324 for (
auto &[blockAddOp, blockInfo] :
4326 mlir::LLVM::BlockTagOp resolvedLabel =
4328 assert(resolvedLabel &&
"expected BlockTagOp to already be emitted");
4329 mlir::FlatSymbolRefAttr fnSym = blockInfo.getFunc();
4330 auto blkAddTag = mlir::LLVM::BlockAddressAttr::get(
4331 opBuilder.getContext(), fnSym, resolvedLabel.getTagAttr());
4332 blockAddOp.setBlockAddrAttr(blkAddTag);
4339 if (mlir::Attribute tripleAttr =
4340 module->getAttr(cir::CIRDialect::getTripleAttrName()))
4341 module->setAttr(mlir::LLVM::LLVMDialect::getTargetTripleAttrName(),
4344 if (mlir::Attribute asmAttr =
4345 module->getAttr(cir::CIRDialect::getModuleLevelAsmAttrName()))
4346 module->setAttr(mlir::LLVM::LLVMDialect::getModuleLevelAsmAttrName(),
4351 llvm::TimeTraceScope scope(
"Convert CIR to LLVM Pass");
4353 mlir::ModuleOp module = getOperation();
4354 mlir::DataLayout dl(module);
4355 mlir::LLVMTypeConverter converter(&getContext());
4365 mlir::SymbolTableCollection symbolTables;
4366 mlir::RewritePatternSet patterns(&getContext());
4367 patterns.add<CIRToLLVMBlockAddressOpLowering, CIRToLLVMGlobalOpLowering,
4368 CIRToLLVMLabelOpLowering>(converter, patterns.getContext(), dl,
4369 symbolTables, blockInfoAddr);
4372#define GET_LLVM_LOWERING_PATTERNS_LIST
4373#include "clang/CIR/Dialect/IR/CIRLowering.inc"
4374#undef GET_LLVM_LOWERING_PATTERNS_LIST
4375 >(converter, patterns.getContext(), dl, symbolTables);
4383 mlir::ConversionTarget target(getContext());
4384 target.addLegalOp<mlir::ModuleOp>();
4385 target.addLegalDialect<mlir::LLVM::LLVMDialect>();
4386 mlir::configureOpenMPToLLVMConversionLegality(target, converter);
4387 target.addLegalDialect<mlir::omp::OpenMPDialect>();
4388 mlir::populateOpenMPToLLVMConversionPatterns(converter, patterns);
4389 target.addIllegalDialect<mlir::BuiltinDialect, cir::CIRDialect,
4390 mlir::func::FuncDialect>();
4393 ops.push_back(module);
4396 if (failed(applyPartialConversion(ops, target, std::move(patterns))))
4397 signalPassFailure();
4401 if (
auto dlSpec = mlir::dyn_cast_or_null<mlir::DataLayoutSpecAttr>(
4402 module->getAttr(mlir::DLTIDialect::kDataLayoutAttrName))) {
4404 for (mlir::DataLayoutEntryInterface entry : dlSpec.getEntries()) {
4405 if (entry.isTypeEntry() &&
4406 mlir::isa<cir::PointerType>(mlir::cast<mlir::Type>(entry.getKey())))
4408 kept.push_back(entry);
4410 module->setAttr(mlir::DLTIDialect::kDataLayoutAttrName,
4411 mlir::DataLayoutSpecAttr::get(module.getContext(), kept));
4416 "llvm.global_ctors", [](mlir::Attribute
attr) {
4417 auto ctorAttr = mlir::cast<cir::GlobalCtorAttr>(
attr);
4418 return std::make_pair(ctorAttr.getName(),
4419 ctorAttr.getPriority());
4423 "llvm.global_dtors", [](mlir::Attribute
attr) {
4424 auto dtorAttr = mlir::cast<cir::GlobalDtorAttr>(
attr);
4425 return std::make_pair(dtorAttr.getName(),
4426 dtorAttr.getPriority());
4434mlir::LogicalResult CIRToLLVMBrOpLowering::matchAndRewrite(
4435 cir::BrOp op, OpAdaptor adaptor,
4436 mlir::ConversionPatternRewriter &rewriter)
const {
4437 rewriter.replaceOpWithNewOp<mlir::LLVM::BrOp>(op, adaptor.getOperands(),
4439 return mlir::LogicalResult::success();
4442mlir::LogicalResult CIRToLLVMGetMemberOpLowering::matchAndRewrite(
4443 cir::GetMemberOp op, OpAdaptor adaptor,
4444 mlir::ConversionPatternRewriter &rewriter)
const {
4445 mlir::Type llResTy = getTypeConverter()->convertType(op.getType());
4446 mlir::Type pointee = op.getAddrTy().getPointee();
4448 if (mlir::isa<cir::UnionType>(pointee)) {
4451 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(op, llResTy,
4453 return mlir::success();
4456 auto structTy = mlir::cast<cir::StructType>(pointee);
4462 0,
static_cast<int32_t>(structTy.getLLVMFieldIndex(op.getIndex()))};
4463 const mlir::Type elementTy = getTypeConverter()->convertType(structTy);
4468 mlir::LLVM::GEPNoWrapFlags flags =
4469 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
4470 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
4471 op, llResTy, elementTy, adaptor.getAddr(), offset, flags);
4472 return mlir::success();
4475mlir::LogicalResult CIRToLLVMExtractMemberOpLowering::matchAndRewrite(
4476 cir::ExtractMemberOp op, OpAdaptor adaptor,
4477 mlir::ConversionPatternRewriter &rewriter)
const {
4478 if (mlir::isa<cir::UnionType>(op.getRecord().getType())) {
4479 op.emitError(
"cir.extract_member cannot extract member from a union");
4480 return mlir::failure();
4483 auto structTy = mlir::cast<cir::StructType>(op.getRecord().getType());
4484 std::int64_t indices[1] = {
4485 static_cast<std::int64_t
>(structTy.getLLVMFieldIndex(op.getIndex()))};
4486 rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractValueOp>(
4487 op, adaptor.getRecord(), indices);
4488 return mlir::success();
4491mlir::LogicalResult CIRToLLVMInsertMemberOpLowering::matchAndRewrite(
4492 cir::InsertMemberOp op, OpAdaptor adaptor,
4493 mlir::ConversionPatternRewriter &rewriter)
const {
4494 if (mlir::isa<cir::UnionType>(op.getRecord().getType())) {
4495 op.emitError(
"cir.update_member cannot update member of a union");
4496 return mlir::failure();
4499 auto structTy = mlir::cast<cir::StructType>(op.getRecord().getType());
4500 std::int64_t indices[1] = {
4501 static_cast<std::int64_t
>(structTy.getLLVMFieldIndex(op.getIndex()))};
4502 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
4503 op, adaptor.getRecord(), adaptor.getValue(), indices);
4504 return mlir::success();
4508 mlir::SymbolTableCollection &symbolTables,
4509 mlir::Operation *srcOp, llvm::StringRef fnName,
4511 mlir::ArrayAttr argAttrs =
nullptr,
4512 mlir::ArrayAttr resAttrs =
nullptr) {
4513 mlir::ModuleOp modOp = srcOp->getParentOfType<mlir::ModuleOp>();
4514 mlir::Operation *sourceSymbol = symbolTables.lookupSymbolIn(
4515 modOp, mlir::StringAttr::get(fnTy.getContext(), fnName));
4516 if (!sourceSymbol) {
4517 mlir::OpBuilder::InsertionGuard guard(rewriter);
4518 auto enclosingFnOp = srcOp->getParentOfType<mlir::LLVM::LLVMFuncOp>();
4519 rewriter.setInsertionPoint(enclosingFnOp);
4521 mlir::LLVM::LLVMFuncOp::create(rewriter, srcOp->getLoc(), fnName, fnTy);
4523 fn.setArgAttrsAttr(argAttrs);
4525 fn.setResAttrsAttr(resAttrs);
4527 symbolTables.getSymbolTable(fn->getParentOp()).insert(fn);
4531mlir::LogicalResult CIRToLLVMThrowOpLowering::matchAndRewrite(
4532 cir::ThrowOp op, OpAdaptor adaptor,
4533 mlir::ConversionPatternRewriter &rewriter)
const {
4534 mlir::Location loc = op.getLoc();
4535 auto voidTy = mlir::LLVM::LLVMVoidType::get(getContext());
4537 if (op.rethrows()) {
4538 auto funcTy = mlir::LLVM::LLVMFunctionType::get(voidTy, {});
4541 const llvm::StringRef functionName =
"__cxa_rethrow";
4542 createLLVMFuncOpIfNotExist(rewriter, symbolTables, op, functionName,
4545 auto cxaRethrow = mlir::LLVM::CallOp::create(
4546 rewriter, loc, mlir::TypeRange{}, functionName);
4548 rewriter.replaceOp(op, cxaRethrow);
4549 return mlir::success();
4552 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4553 auto fnTy = mlir::LLVM::LLVMFunctionType::get(
4554 voidTy, {llvmPtrTy, llvmPtrTy, llvmPtrTy});
4557 const llvm::StringRef fnName =
"__cxa_throw";
4560 mlir::Value typeInfo = mlir::LLVM::AddressOfOp::create(
4561 rewriter, loc, mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
4562 adaptor.getTypeInfoAttr());
4566 dtor = mlir::LLVM::AddressOfOp::create(rewriter, loc, llvmPtrTy,
4567 adaptor.getDtorAttr());
4569 dtor = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmPtrTy);
4572 auto cxaThrowCall = mlir::LLVM::CallOp::create(
4573 rewriter, loc, mlir::TypeRange{}, fnName,
4574 mlir::ValueRange{adaptor.getExceptionPtr(), typeInfo, dtor});
4576 rewriter.replaceOp(op, cxaThrowCall);
4577 return mlir::success();
4580mlir::LogicalResult CIRToLLVMAllocExceptionOpLowering::matchAndRewrite(
4581 cir::AllocExceptionOp op, OpAdaptor adaptor,
4582 mlir::ConversionPatternRewriter &rewriter)
const {
4584 StringRef fnName =
"__cxa_allocate_exception";
4585 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4586 auto int64Ty = mlir::IntegerType::get(rewriter.getContext(), 64);
4587 auto fnTy = mlir::LLVM::LLVMFunctionType::get(llvmPtrTy, {int64Ty});
4590 auto exceptionSize = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
4591 adaptor.getSizeAttr());
4593 auto allocaExceptionCall = mlir::LLVM::CallOp::create(
4594 rewriter, op.getLoc(), mlir::TypeRange{llvmPtrTy}, fnName,
4595 mlir::ValueRange{exceptionSize});
4597 rewriter.replaceOp(op, allocaExceptionCall);
4598 return mlir::success();
4601static mlir::LLVM::LLVMStructType
4604 mlir::MLIRContext *ctx = rewriter.getContext();
4605 auto llvmPtr = mlir::LLVM::LLVMPointerType::get(ctx);
4607 return mlir::LLVM::LLVMStructType::getLiteral(ctx, structFields);
4610mlir::LogicalResult CIRToLLVMEhInflightOpLowering::matchAndRewrite(
4611 cir::EhInflightOp op, OpAdaptor adaptor,
4612 mlir::ConversionPatternRewriter &rewriter)
const {
4613 auto llvmFn = op->getParentOfType<mlir::LLVM::LLVMFuncOp>();
4614 assert(llvmFn &&
"expected LLVM function parent");
4615 mlir::Block *entryBlock = &llvmFn.getRegion().front();
4616 assert(entryBlock->isEntryBlock());
4618 mlir::ArrayAttr catchListAttr = op.getCatchTypeListAttr();
4619 mlir::SmallVector<mlir::Value> catchSymAddrs;
4621 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4622 mlir::Location loc = op.getLoc();
4627 if (catchListAttr) {
4630 for (mlir::Attribute catchAttr : catchListAttr) {
4631 auto symAttr = cast<mlir::FlatSymbolRefAttr>(catchAttr);
4634 mlir::OpBuilder::InsertionGuard guard(rewriter);
4635 rewriter.setInsertionPointToStart(entryBlock);
4636 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
4637 rewriter, loc, llvmPtrTy, symAttr.getValue());
4638 catchSymAddrs.push_back(addrOp);
4645 if (op.getCatchAll() || (!catchListAttr && !op.getCleanup())) {
4646 mlir::OpBuilder::InsertionGuard guard(rewriter);
4647 rewriter.setInsertionPointToStart(entryBlock);
4648 mlir::Value nullOp = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmPtrTy);
4649 catchSymAddrs.push_back(nullOp);
4654 mlir::LLVM::LLVMStructType llvmLandingPadStructTy =
4656 auto landingPadOp = mlir::LLVM::LandingpadOp::create(
4657 rewriter, loc, llvmLandingPadStructTy, catchSymAddrs);
4662 if (op.getCleanup() && !op.getCatchAll())
4663 landingPadOp.setCleanup(
true);
4666 mlir::LLVM::ExtractValueOp::create(rewriter, loc, landingPadOp, 0);
4667 mlir::Value selector =
4668 mlir::LLVM::ExtractValueOp::create(rewriter, loc, landingPadOp, 1);
4669 rewriter.replaceOp(op, mlir::ValueRange{slot, selector});
4671 return mlir::success();
4674mlir::LogicalResult CIRToLLVMResumeFlatOpLowering::matchAndRewrite(
4675 cir::ResumeFlatOp op, OpAdaptor adaptor,
4676 mlir::ConversionPatternRewriter &rewriter)
const {
4681 mlir::Value poison = mlir::LLVM::PoisonOp::create(rewriter, op.getLoc(),
4682 llvmLandingPadStructTy);
4685 mlir::Value slot = mlir::LLVM::InsertValueOp::create(
4686 rewriter, op.getLoc(), poison, adaptor.getExceptionPtr(), slotIdx);
4689 mlir::Value selector = mlir::LLVM::InsertValueOp::create(
4690 rewriter, op.getLoc(), slot, adaptor.getTypeId(), selectorIdx);
4692 rewriter.replaceOpWithNewOp<mlir::LLVM::ResumeOp>(op, selector);
4693 return mlir::success();
4696mlir::LogicalResult CIRToLLVMEhTypeIdOpLowering::matchAndRewrite(
4697 cir::EhTypeIdOp op, OpAdaptor adaptor,
4698 mlir::ConversionPatternRewriter &rewriter)
const {
4699 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
4700 rewriter, op.getLoc(),
4701 mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
4702 op.getTypeSymAttr());
4703 rewriter.replaceOpWithNewOp<mlir::LLVM::EhTypeidForOp>(
4704 op, rewriter.getI32Type(), addrOp);
4705 return mlir::success();
4708mlir::LogicalResult CIRToLLVMEhSetjmpOpLowering::matchAndRewrite(
4709 cir::EhSetjmpOp op, OpAdaptor adaptor,
4710 mlir::ConversionPatternRewriter &rewriter)
const {
4711 mlir::Type returnType = typeConverter->convertType(op.getType());
4712 mlir::LLVM::CallIntrinsicOp newOp =
4714 returnType, adaptor.getEnv());
4715 rewriter.replaceOp(op, newOp);
4716 return mlir::success();
4719mlir::LogicalResult CIRToLLVMEhLongjmpOpLowering::matchAndRewrite(
4720 cir::EhLongjmpOp op, OpAdaptor adaptor,
4721 mlir::ConversionPatternRewriter &rewriter)
const {
4723 {}, adaptor.getOperands());
4724 return mlir::success();
4727mlir::LogicalResult CIRToLLVMTrapOpLowering::matchAndRewrite(
4728 cir::TrapOp op, OpAdaptor adaptor,
4729 mlir::ConversionPatternRewriter &rewriter)
const {
4730 mlir::Location loc = op->getLoc();
4731 rewriter.eraseOp(op);
4733 mlir::LLVM::Trap::create(rewriter, loc);
4738 mlir::LLVM::UnreachableOp::create(rewriter, loc);
4740 return mlir::success();
4745 mlir::ConversionPatternRewriter &rewriter,
4746 mlir::SymbolTableCollection &symbolTables,
4747 const mlir::TypeConverter *converter,
4748 mlir::FlatSymbolRefAttr nameAttr, mlir::Type &eltType) {
4749 auto module = op->getParentOfType<mlir::ModuleOp>();
4750 mlir::Operation *symbol = symbolTables.lookupSymbolIn(module, nameAttr);
4751 if (
auto llvmSymbol = mlir::dyn_cast<mlir::LLVM::GlobalOp>(symbol)) {
4752 eltType = llvmSymbol.getType();
4753 }
else if (
auto cirSymbol = mlir::dyn_cast<cir::GlobalOp>(symbol)) {
4754 eltType = converter->convertType(cirSymbol.getSymType());
4756 op->emitError() <<
"unexpected symbol type for " << symbol;
4760 return mlir::LLVM::AddressOfOp::create(
4761 rewriter, op->getLoc(),
4762 mlir::LLVM::LLVMPointerType::get(op->getContext()), nameAttr.getValue());
4765mlir::LogicalResult CIRToLLVMVTableAddrPointOpLowering::matchAndRewrite(
4766 cir::VTableAddrPointOp op, OpAdaptor adaptor,
4767 mlir::ConversionPatternRewriter &rewriter)
const {
4768 const mlir::TypeConverter *converter = getTypeConverter();
4769 mlir::Type targetType = converter->convertType(op.getType());
4772 mlir::Value symAddr = getValueForVTableSymbol(
4773 op, rewriter, symbolTables, converter, op.getNameAttr(), eltType);
4775 return op.emitError() <<
"Unable to get value for vtable symbol";
4778 0, op.getAddressPointAttr().getIndex(),
4779 op.getAddressPointAttr().getOffset()};
4781 assert(eltType &&
"Shouldn't ever be missing an eltType here");
4782 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
4783 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
4784 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, targetType, eltType,
4785 symAddr, offsets, inboundsNuw);
4786 return mlir::success();
4789mlir::LogicalResult CIRToLLVMVTableGetVPtrOpLowering::matchAndRewrite(
4790 cir::VTableGetVPtrOp op, OpAdaptor adaptor,
4791 mlir::ConversionPatternRewriter &rewriter)
const {
4795 mlir::Value srcVal = adaptor.getSrc();
4796 rewriter.replaceOp(op, srcVal);
4797 return mlir::success();
4800mlir::LogicalResult CIRToLLVMVTableGetVirtualFnAddrOpLowering::matchAndRewrite(
4801 cir::VTableGetVirtualFnAddrOp op, OpAdaptor adaptor,
4802 mlir::ConversionPatternRewriter &rewriter)
const {
4803 mlir::Type targetType = getTypeConverter()->convertType(op.getType());
4804 auto eltType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4807 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
4808 op, targetType, eltType, adaptor.getVptr(), offsets,
4809 mlir::LLVM::GEPNoWrapFlags::inbounds);
4810 return mlir::success();
4813mlir::LogicalResult CIRToLLVMVTTAddrPointOpLowering::matchAndRewrite(
4814 cir::VTTAddrPointOp op, OpAdaptor adaptor,
4815 mlir::ConversionPatternRewriter &rewriter)
const {
4816 const mlir::Type resultType = getTypeConverter()->convertType(op.getType());
4819 mlir::Value llvmAddr = adaptor.getSymAddr();
4821 if (op.getSymAddr()) {
4822 if (op.getOffset() == 0) {
4823 rewriter.replaceOp(op, {llvmAddr});
4824 return mlir::success();
4827 offsets.push_back(adaptor.getOffset());
4828 eltType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4832 op.getNameAttr(), eltType);
4833 assert(eltType &&
"Shouldn't ever be missing an eltType here");
4834 offsets.push_back(0);
4835 offsets.push_back(adaptor.getOffset());
4837 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
4838 op, resultType, eltType, llvmAddr, offsets,
4839 mlir::LLVM::GEPNoWrapFlags::inbounds);
4840 return mlir::success();
4843mlir::LogicalResult CIRToLLVMVecCreateOpLowering::matchAndRewrite(
4844 cir::VecCreateOp op, OpAdaptor adaptor,
4845 mlir::ConversionPatternRewriter &rewriter)
const {
4848 const cir::VectorType vecTy = op.getType();
4849 const mlir::Type llvmTy = typeConverter->convertType(vecTy);
4850 const mlir::Location loc = op.getLoc();
4851 mlir::Value result = mlir::LLVM::PoisonOp::create(rewriter, loc, llvmTy);
4852 assert(vecTy.getSize() == op.getElements().size() &&
4853 "cir.vec.create op count doesn't match vector type elements count");
4855 for (uint64_t i = 0; i < vecTy.getSize(); ++i) {
4856 const mlir::Value indexValue =
4857 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
4858 result = mlir::LLVM::InsertElementOp::create(
4859 rewriter, loc, result, adaptor.getElements()[i], indexValue);
4862 rewriter.replaceOp(op, result);
4863 return mlir::success();
4866mlir::LogicalResult CIRToLLVMVecExtractOpLowering::matchAndRewrite(
4867 cir::VecExtractOp op, OpAdaptor adaptor,
4868 mlir::ConversionPatternRewriter &rewriter)
const {
4869 rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractElementOp>(
4870 op, adaptor.getVec(), adaptor.getIndex());
4871 return mlir::success();
4874mlir::LogicalResult CIRToLLVMVecInsertOpLowering::matchAndRewrite(
4875 cir::VecInsertOp op, OpAdaptor adaptor,
4876 mlir::ConversionPatternRewriter &rewriter)
const {
4877 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertElementOp>(
4878 op, adaptor.getVec(), adaptor.getValue(), adaptor.getIndex());
4879 return mlir::success();
4882mlir::LogicalResult CIRToLLVMVecCmpOpLowering::matchAndRewrite(
4883 cir::VecCmpOp op, OpAdaptor adaptor,
4884 mlir::ConversionPatternRewriter &rewriter)
const {
4885 mlir::Type elementType = op.getLhs().getType().getElementType();
4886 mlir::Value bitResult;
4887 if (
auto intType = mlir::dyn_cast<cir::IntType>(elementType)) {
4888 bitResult = mlir::LLVM::ICmpOp::create(
4889 rewriter, op.getLoc(),
4891 adaptor.getLhs(), adaptor.getRhs());
4892 }
else if (
auto boolType = mlir::dyn_cast<cir::BoolType>(elementType)) {
4893 bitResult = mlir::LLVM::ICmpOp::create(
4894 rewriter, op.getLoc(),
4896 adaptor.getLhs(), adaptor.getRhs());
4897 }
else if (mlir::isa<cir::FPTypeInterface>(elementType)) {
4898 if (cir::FenvAttr fenv = op.getFenvAttr()) {
4899 auto i1VecTy = mlir::VectorType::get(op.getLhs().getType().getSize(),
4900 rewriter.getI1Type());
4902 adaptor.getLhs(), adaptor.getRhs(),
4903 op.getKind(), fenv, i1VecTy)
4906 bitResult = mlir::LLVM::FCmpOp::create(
4908 adaptor.getLhs(), adaptor.getRhs());
4911 return op.emitError() <<
"unsupported type for VecCmpOp: " << elementType;
4917 mlir::Type vecElemTy = op.getType().getElementType();
4918 if (isa<cir::IntType>(vecElemTy) &&
4919 cast<cir::IntType>(vecElemTy).getWidth() > 1)
4920 rewriter.replaceOpWithNewOp<mlir::LLVM::SExtOp>(
4921 op, typeConverter->convertType(op.getType()), bitResult);
4923 rewriter.replaceOp(op, bitResult);
4924 return mlir::success();
4927mlir::LogicalResult CIRToLLVMVecSplatOpLowering::matchAndRewrite(
4928 cir::VecSplatOp op, OpAdaptor adaptor,
4929 mlir::ConversionPatternRewriter &rewriter)
const {
4935 cir::VectorType vecTy = op.getType();
4936 mlir::Type llvmTy = typeConverter->convertType(vecTy);
4937 mlir::Location loc = op.getLoc();
4938 mlir::Value poison = mlir::LLVM::PoisonOp::create(rewriter, loc, llvmTy);
4940 mlir::Value elementValue = adaptor.getValue();
4941 if (elementValue.getDefiningOp<mlir::LLVM::PoisonOp>()) {
4944 rewriter.replaceOp(op, poison);
4945 return mlir::success();
4948 if (
auto constValue = elementValue.getDefiningOp<mlir::LLVM::ConstantOp>()) {
4949 if (
auto intAttr = dyn_cast<mlir::IntegerAttr>(constValue.getValue())) {
4950 mlir::DenseIntElementsAttr denseVec = mlir::DenseIntElementsAttr::get(
4951 mlir::cast<mlir::ShapedType>(llvmTy), intAttr.getValue());
4952 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
4953 op, denseVec.getType(), denseVec);
4954 return mlir::success();
4957 if (
auto fpAttr = dyn_cast<mlir::FloatAttr>(constValue.getValue())) {
4958 mlir::DenseFPElementsAttr denseVec = mlir::DenseFPElementsAttr::get(
4959 mlir::cast<mlir::ShapedType>(llvmTy), fpAttr.getValue());
4960 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
4961 op, denseVec.getType(), denseVec);
4962 return mlir::success();
4966 mlir::Value indexValue =
4967 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), 0);
4968 mlir::Value oneElement = mlir::LLVM::InsertElementOp::create(
4969 rewriter, loc, poison, elementValue, indexValue);
4971 rewriter.replaceOpWithNewOp<mlir::LLVM::ShuffleVectorOp>(op, oneElement,
4972 poison, zeroValues);
4973 return mlir::success();
4976mlir::LogicalResult CIRToLLVMVecShuffleOpLowering::matchAndRewrite(
4977 cir::VecShuffleOp op, OpAdaptor adaptor,
4978 mlir::ConversionPatternRewriter &rewriter)
const {
4984 op.getIndices().begin(), op.getIndices().end(),
4985 std::back_inserter(indices), [](mlir::Attribute intAttr) {
4986 return mlir::cast<cir::IntAttr>(intAttr).getValue().getSExtValue();
4988 rewriter.replaceOpWithNewOp<mlir::LLVM::ShuffleVectorOp>(
4989 op, adaptor.getVec1(), adaptor.getVec2(), indices);
4990 return mlir::success();
4993mlir::LogicalResult CIRToLLVMVecShuffleDynamicOpLowering::matchAndRewrite(
4994 cir::VecShuffleDynamicOp op, OpAdaptor adaptor,
4995 mlir::ConversionPatternRewriter &rewriter)
const {
5007 mlir::Location loc = op.getLoc();
5008 mlir::Value input = adaptor.getVec();
5009 mlir::Type llvmIndexVecType =
5010 getTypeConverter()->convertType(op.getIndices().getType());
5011 mlir::Type llvmIndexType = getTypeConverter()->convertType(
5012 op.getIndices().getType().getElementType());
5013 uint64_t numElements = op.getVec().getType().getSize();
5015 uint64_t maskBits = llvm::NextPowerOf2(numElements - 1) - 1;
5016 mlir::Value maskValue = mlir::LLVM::ConstantOp::create(
5017 rewriter, loc, llvmIndexType,
5018 rewriter.getIntegerAttr(llvmIndexType, maskBits));
5019 mlir::Value maskVector =
5020 mlir::LLVM::UndefOp::create(rewriter, loc, llvmIndexVecType);
5022 for (uint64_t i = 0; i < numElements; ++i) {
5023 mlir::Value idxValue =
5024 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
5025 maskVector = mlir::LLVM::InsertElementOp::create(rewriter, loc, maskVector,
5026 maskValue, idxValue);
5029 mlir::Value maskedIndices = mlir::LLVM::AndOp::create(
5030 rewriter, loc, llvmIndexVecType, adaptor.getIndices(), maskVector);
5031 mlir::Value result = mlir::LLVM::UndefOp::create(
5032 rewriter, loc, getTypeConverter()->convertType(op.getVec().getType()));
5033 for (uint64_t i = 0; i < numElements; ++i) {
5034 mlir::Value iValue =
5035 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
5036 mlir::Value indexValue = mlir::LLVM::ExtractElementOp::create(
5037 rewriter, loc, maskedIndices, iValue);
5038 mlir::Value valueAtIndex =
5039 mlir::LLVM::ExtractElementOp::create(rewriter, loc, input, indexValue);
5040 result = mlir::LLVM::InsertElementOp::create(rewriter, loc, result,
5041 valueAtIndex, iValue);
5043 rewriter.replaceOp(op, result);
5044 return mlir::success();
5047mlir::LogicalResult CIRToLLVMVecTernaryOpLowering::matchAndRewrite(
5048 cir::VecTernaryOp op, OpAdaptor adaptor,
5049 mlir::ConversionPatternRewriter &rewriter)
const {
5050 mlir::Value bitVec = adaptor.getCond();
5052 if (!isa<cir::BoolType>(op.getCond().getType().getElementType())) {
5054 bitVec = mlir::LLVM::ICmpOp::create(
5055 rewriter, op.getLoc(), mlir::LLVM::ICmpPredicate::ne, adaptor.getCond(),
5056 mlir::LLVM::ZeroOp::create(
5057 rewriter, op.getCond().getLoc(),
5058 typeConverter->convertType(op.getCond().getType())));
5061 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(
5062 op, bitVec, adaptor.getLhs(), adaptor.getRhs());
5063 return mlir::success();
5066mlir::LogicalResult CIRToLLVMComplexAddOpLowering::matchAndRewrite(
5067 cir::ComplexAddOp op, OpAdaptor adaptor,
5068 mlir::ConversionPatternRewriter &rewriter)
const {
5069 mlir::Value lhs = adaptor.getLhs();
5070 mlir::Value rhs = adaptor.getRhs();
5071 mlir::Location loc = op.getLoc();
5073 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
5074 mlir::Type complexElemTy =
5075 getTypeConverter()->convertType(
complexType.getElementType());
5076 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
5077 rewriter, loc, complexElemTy, lhs,
ArrayRef(int64_t{0}));
5078 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
5079 rewriter, loc, complexElemTy, lhs,
ArrayRef(int64_t{1}));
5080 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
5081 rewriter, loc, complexElemTy, rhs,
ArrayRef(int64_t{0}));
5082 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
5083 rewriter, loc, complexElemTy, rhs,
ArrayRef(int64_t{1}));
5085 mlir::Value newReal;
5086 mlir::Value newImag;
5087 if (complexElemTy.isInteger()) {
5088 newReal = mlir::LLVM::AddOp::create(rewriter, loc, complexElemTy, lhsReal,
5090 newImag = mlir::LLVM::AddOp::create(rewriter, loc, complexElemTy, lhsImag,
5095 newReal = mlir::LLVM::FAddOp::create(rewriter, loc, complexElemTy, lhsReal,
5097 newImag = mlir::LLVM::FAddOp::create(rewriter, loc, complexElemTy, lhsImag,
5101 mlir::Type complexLLVMTy =
5102 getTypeConverter()->convertType(op.getResult().getType());
5103 auto initialComplex =
5104 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), complexLLVMTy);
5106 auto realComplex = mlir::LLVM::InsertValueOp::create(
5107 rewriter, op->getLoc(), initialComplex, newReal,
ArrayRef(int64_t{0}));
5109 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
5110 op, realComplex, newImag,
ArrayRef(int64_t{1}));
5112 return mlir::success();
5115mlir::LogicalResult CIRToLLVMComplexCreateOpLowering::matchAndRewrite(
5116 cir::ComplexCreateOp op, OpAdaptor adaptor,
5117 mlir::ConversionPatternRewriter &rewriter)
const {
5118 mlir::Type complexLLVMTy =
5119 getTypeConverter()->convertType(op.getResult().getType());
5120 auto initialComplex =
5121 mlir::LLVM::UndefOp::create(rewriter, op->getLoc(), complexLLVMTy);
5123 auto realComplex = mlir::LLVM::InsertValueOp::create(
5124 rewriter, op->getLoc(), initialComplex, adaptor.getReal(),
5127 auto complex = mlir::LLVM::InsertValueOp::create(
5128 rewriter, op->getLoc(), realComplex, adaptor.getImag(),
5131 rewriter.replaceOp(op, complex);
5132 return mlir::success();
5135mlir::LogicalResult CIRToLLVMComplexRealOpLowering::matchAndRewrite(
5136 cir::ComplexRealOp op, OpAdaptor adaptor,
5137 mlir::ConversionPatternRewriter &rewriter)
const {
5138 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
5139 mlir::Value operand = adaptor.getOperand();
5140 if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) {
5141 operand = mlir::LLVM::ExtractValueOp::create(
5142 rewriter, op.getLoc(), resultLLVMTy, operand,
5145 rewriter.replaceOp(op, operand);
5146 return mlir::success();
5149mlir::LogicalResult CIRToLLVMComplexSubOpLowering::matchAndRewrite(
5150 cir::ComplexSubOp op, OpAdaptor adaptor,
5151 mlir::ConversionPatternRewriter &rewriter)
const {
5152 mlir::Value lhs = adaptor.getLhs();
5153 mlir::Value rhs = adaptor.getRhs();
5154 mlir::Location loc = op.getLoc();
5156 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
5157 mlir::Type complexElemTy =
5158 getTypeConverter()->convertType(
complexType.getElementType());
5159 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
5160 rewriter, loc, complexElemTy, lhs,
ArrayRef(int64_t{0}));
5161 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
5162 rewriter, loc, complexElemTy, lhs,
ArrayRef(int64_t{1}));
5163 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
5164 rewriter, loc, complexElemTy, rhs,
ArrayRef(int64_t{0}));
5165 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
5166 rewriter, loc, complexElemTy, rhs,
ArrayRef(int64_t{1}));
5168 mlir::Value newReal;
5169 mlir::Value newImag;
5170 if (complexElemTy.isInteger()) {
5171 newReal = mlir::LLVM::SubOp::create(rewriter, loc, complexElemTy, lhsReal,
5173 newImag = mlir::LLVM::SubOp::create(rewriter, loc, complexElemTy, lhsImag,
5178 newReal = mlir::LLVM::FSubOp::create(rewriter, loc, complexElemTy, lhsReal,
5180 newImag = mlir::LLVM::FSubOp::create(rewriter, loc, complexElemTy, lhsImag,
5184 mlir::Type complexLLVMTy =
5185 getTypeConverter()->convertType(op.getResult().getType());
5186 auto initialComplex =
5187 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), complexLLVMTy);
5189 auto realComplex = mlir::LLVM::InsertValueOp::create(
5190 rewriter, op->getLoc(), initialComplex, newReal,
ArrayRef(int64_t{0}));
5192 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
5193 op, realComplex, newImag,
ArrayRef(int64_t{1}));
5195 return mlir::success();
5198mlir::LogicalResult CIRToLLVMComplexImagOpLowering::matchAndRewrite(
5199 cir::ComplexImagOp op, OpAdaptor adaptor,
5200 mlir::ConversionPatternRewriter &rewriter)
const {
5201 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
5202 mlir::Value operand = adaptor.getOperand();
5203 mlir::Location loc = op.getLoc();
5205 if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) {
5206 operand = mlir::LLVM::ExtractValueOp::create(
5209 mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(resultLLVMTy);
5211 mlir::LLVM::ConstantOp::create(rewriter, loc, resultLLVMTy, zeroAttr);
5214 rewriter.replaceOp(op, operand);
5215 return mlir::success();
5219 mlir::MLIRContext *context,
5220 unsigned &storageSize) {
5221 return TypeSwitch<mlir::Type, mlir::IntegerType>(storageType)
5222 .Case<cir::ArrayType>([&](cir::ArrayType atTy) {
5223 storageSize = atTy.getSize() * 8;
5224 return mlir::IntegerType::get(context, storageSize);
5226 .Case<cir::IntType>([&](cir::IntType intTy) {
5227 storageSize = intTy.getWidth();
5228 return mlir::IntegerType::get(context, storageSize);
5230 .Default([](mlir::Type) -> mlir::IntegerType {
5232 "Either ArrayType or IntType expected for bitfields storage");
5236mlir::LogicalResult CIRToLLVMSetBitfieldOpLowering::matchAndRewrite(
5237 cir::SetBitfieldOp op, OpAdaptor adaptor,
5238 mlir::ConversionPatternRewriter &rewriter)
const {
5239 mlir::OpBuilder::InsertionGuard guard(rewriter);
5240 rewriter.setInsertionPoint(op);
5242 cir::BitfieldInfoAttr info = op.getBitfieldInfo();
5243 uint64_t size = info.getSize();
5244 uint64_t offset = info.getOffset();
5245 mlir::Type storageType = info.getStorageType();
5246 mlir::MLIRContext *context = storageType.getContext();
5248 unsigned storageSize = 0;
5250 mlir::IntegerType intType =
5251 computeBitfieldIntType(storageType, context, storageSize);
5253 mlir::Value srcVal = createIntCast(rewriter, adaptor.getSrc(), intType);
5254 unsigned srcWidth = storageSize;
5255 mlir::Value resultVal = srcVal;
5257 if (storageSize != size) {
5258 assert(storageSize > size &&
"Invalid bitfield size.");
5260 mlir::Value val = mlir::LLVM::LoadOp::create(
5261 rewriter, op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(),
5262 op.getIsVolatile());
5265 createAnd(rewriter, srcVal, llvm::APInt::getLowBitsSet(srcWidth, size));
5267 srcVal =
createShL(rewriter, srcVal, offset);
5271 ~llvm::APInt::getBitsSet(srcWidth, offset, offset + size));
5274 srcVal = mlir::LLVM::OrOp::create(rewriter, op.getLoc(), val, srcVal);
5277 mlir::LLVM::StoreOp::create(rewriter, op.getLoc(), srcVal, adaptor.getAddr(),
5278 op.getAlignment(), op.getIsVolatile());
5280 mlir::Type resultTy = getTypeConverter()->convertType(op.getType());
5282 if (info.getIsSigned()) {
5283 assert(size <= storageSize);
5284 unsigned highBits = storageSize - size;
5287 resultVal =
createShL(rewriter, resultVal, highBits);
5288 resultVal =
createAShR(rewriter, resultVal, highBits);
5293 mlir::cast<mlir::IntegerType>(resultTy),
5294 info.getIsSigned());
5296 rewriter.replaceOp(op, resultVal);
5297 return mlir::success();
5300mlir::LogicalResult CIRToLLVMComplexImagPtrOpLowering::matchAndRewrite(
5301 cir::ComplexImagPtrOp op, OpAdaptor adaptor,
5302 mlir::ConversionPatternRewriter &rewriter)
const {
5303 cir::PointerType operandTy = op.getOperand().getType();
5304 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
5305 mlir::Type elementLLVMTy =
5306 getTypeConverter()->convertType(operandTy.getPointee());
5308 mlir::LLVM::GEPArg gepIndices[2] = {{0}, {1}};
5309 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
5310 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
5311 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
5312 op, resultLLVMTy, elementLLVMTy, adaptor.getOperand(), gepIndices,
5314 return mlir::success();
5317mlir::LogicalResult CIRToLLVMComplexRealPtrOpLowering::matchAndRewrite(
5318 cir::ComplexRealPtrOp op, OpAdaptor adaptor,
5319 mlir::ConversionPatternRewriter &rewriter)
const {
5320 cir::PointerType operandTy = op.getOperand().getType();
5321 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
5322 mlir::Type elementLLVMTy =
5323 getTypeConverter()->convertType(operandTy.getPointee());
5325 mlir::LLVM::GEPArg gepIndices[2] = {0, 0};
5326 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
5327 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
5328 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
5329 op, resultLLVMTy, elementLLVMTy, adaptor.getOperand(), gepIndices,
5331 return mlir::success();
5334mlir::LogicalResult CIRToLLVMGetBitfieldOpLowering::matchAndRewrite(
5335 cir::GetBitfieldOp op, OpAdaptor adaptor,
5336 mlir::ConversionPatternRewriter &rewriter)
const {
5338 mlir::OpBuilder::InsertionGuard guard(rewriter);
5339 rewriter.setInsertionPoint(op);
5341 cir::BitfieldInfoAttr
info = op.getBitfieldInfo();
5342 uint64_t size =
info.getSize();
5343 uint64_t offset =
info.getOffset();
5344 mlir::Type storageType =
info.getStorageType();
5345 mlir::MLIRContext *context = storageType.getContext();
5346 unsigned storageSize = 0;
5348 mlir::IntegerType intType =
5351 mlir::Value val = mlir::LLVM::LoadOp::create(
5352 rewriter, op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(),
5353 op.getIsVolatile());
5354 val = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), intType, val);
5356 if (
info.getIsSigned()) {
5357 assert(
static_cast<unsigned>(offset + size) <= storageSize);
5358 unsigned highBits = storageSize - offset - size;
5359 val =
createShL(rewriter, val, highBits);
5360 val =
createAShR(rewriter, val, offset + highBits);
5364 if (
static_cast<unsigned>(offset) + size < storageSize)
5366 llvm::APInt::getLowBitsSet(storageSize, size));
5369 mlir::Type resTy = getTypeConverter()->convertType(op.getType());
5371 rewriter, val, mlir::cast<mlir::IntegerType>(resTy),
info.getIsSigned());
5372 rewriter.replaceOp(op, newOp);
5373 return mlir::success();
5376mlir::LogicalResult CIRToLLVMInlineAsmOpLowering::matchAndRewrite(
5377 cir::InlineAsmOp op, OpAdaptor adaptor,
5378 mlir::ConversionPatternRewriter &rewriter)
const {
5380 if (op.getNumResults())
5381 llResTy = getTypeConverter()->convertType(op.getType(0));
5383 cir::AsmFlavor dialect = op.getAsmFlavor();
5384 mlir::LLVM::AsmDialect llDialect = dialect == cir::AsmFlavor::x86_att
5385 ? mlir::LLVM::AsmDialect::AD_ATT
5386 : mlir::LLVM::AsmDialect::AD_Intel;
5389 StringRef llvmAttrName = mlir::LLVM::InlineAsmOp::getElementTypeAttrName();
5395 if (!op.getNumResults())
5396 opAttrs.push_back(mlir::Attribute());
5400 for (
auto const &[llvmOp, cirOp] :
5401 zip(adaptor.getAsmOperands(), op.getAsmOperands())) {
5402 append_range(llvmOperands, llvmOp);
5403 append_range(cirOperands, cirOp);
5408 for (
auto const &[cirOpAttr, cirOp] :
5409 zip(op.getOperandAttrs(), cirOperands)) {
5410 if (!mlir::isa<mlir::UnitAttr>(cirOpAttr)) {
5411 opAttrs.push_back(mlir::Attribute());
5416 cir::PointerType typ = mlir::cast<cir::PointerType>(cirOp.getType());
5418 *getTypeConverter(), dataLayout, typ.getPointee()));
5420 attrs.push_back(rewriter.getNamedAttr(llvmAttrName, typAttr));
5421 mlir::DictionaryAttr newDict = rewriter.getDictionaryAttr(attrs);
5422 opAttrs.push_back(newDict);
5425 rewriter.replaceOpWithNewOp<mlir::LLVM::InlineAsmOp>(
5426 op, llResTy, llvmOperands, op.getAsmStringAttr(), op.getConstraintsAttr(),
5427 op.getSideEffectsAttr(),
5430 mlir::LLVM::TailCallKindAttr::get(
5431 getContext(), mlir::LLVM::tailcallkind::TailCallKind::None),
5432 mlir::LLVM::AsmDialectAttr::get(getContext(), llDialect),
5433 rewriter.getArrayAttr(opAttrs));
5435 return mlir::success();
5438mlir::LogicalResult CIRToLLVMVAStartOpLowering::matchAndRewrite(
5439 cir::VAStartOp op, OpAdaptor adaptor,
5440 mlir::ConversionPatternRewriter &rewriter)
const {
5441 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
5442 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
5443 adaptor.getArgList());
5444 rewriter.replaceOpWithNewOp<mlir::LLVM::VaStartOp>(op, vaList);
5445 return mlir::success();
5448mlir::LogicalResult CIRToLLVMVAEndOpLowering::matchAndRewrite(
5449 cir::VAEndOp op, OpAdaptor adaptor,
5450 mlir::ConversionPatternRewriter &rewriter)
const {
5451 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
5452 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
5453 adaptor.getArgList());
5454 rewriter.replaceOpWithNewOp<mlir::LLVM::VaEndOp>(op, vaList);
5455 return mlir::success();
5458mlir::LogicalResult CIRToLLVMVACopyOpLowering::matchAndRewrite(
5459 cir::VACopyOp op, OpAdaptor adaptor,
5460 mlir::ConversionPatternRewriter &rewriter)
const {
5461 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
5462 auto dstList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
5463 adaptor.getDstList());
5464 auto srcList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
5465 adaptor.getSrcList());
5466 rewriter.replaceOpWithNewOp<mlir::LLVM::VaCopyOp>(op, dstList, srcList);
5467 return mlir::success();
5470mlir::LogicalResult CIRToLLVMVAArgOpLowering::matchAndRewrite(
5471 cir::VAArgOp op, OpAdaptor adaptor,
5472 mlir::ConversionPatternRewriter &rewriter)
const {
5474 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
5475 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
5476 adaptor.getArgList());
5478 mlir::Type llvmType =
5479 getTypeConverter()->convertType(op->getResultTypes().front());
5481 return mlir::failure();
5483 rewriter.replaceOpWithNewOp<mlir::LLVM::VaArgOp>(op, llvmType, vaList);
5484 return mlir::success();
5487mlir::LogicalResult CIRToLLVMLabelOpLowering::matchAndRewrite(
5488 cir::LabelOp op, OpAdaptor adaptor,
5489 mlir::ConversionPatternRewriter &rewriter)
const {
5490 mlir::MLIRContext *ctx = rewriter.getContext();
5491 mlir::Block *block = op->getBlock();
5494 if (block->isEntryBlock()) {
5495 mlir::Block *newBlock =
5496 rewriter.splitBlock(op->getBlock(), mlir::Block::iterator(op));
5497 rewriter.setInsertionPointToEnd(block);
5498 mlir::LLVM::BrOp::create(rewriter, op.getLoc(), newBlock);
5501 mlir::LLVM::BlockTagAttr::get(ctx, blockInfoAddr.getTagIndex());
5502 rewriter.setInsertionPoint(op);
5505 mlir::LLVM::BlockTagOp::create(rewriter, op->getLoc(), tagAttr);
5506 mlir::LLVM::LLVMFuncOp func = op->getParentOfType<mlir::LLVM::LLVMFuncOp>();
5507 auto blockInfoAttr =
5508 cir::BlockAddrInfoAttr::get(ctx, func.getSymName(), op.getLabel());
5509 blockInfoAddr.mapBlockTag(blockInfoAttr, blockTagOp);
5510 rewriter.eraseOp(op);
5512 return mlir::success();
5515mlir::LogicalResult CIRToLLVMBlockAddressOpLowering::matchAndRewrite(
5516 cir::BlockAddressOp op, OpAdaptor adaptor,
5517 mlir::ConversionPatternRewriter &rewriter)
const {
5518 mlir::MLIRContext *ctx = rewriter.getContext();
5520 mlir::LLVM::BlockTagOp matchLabel =
5521 blockInfoAddr.lookupBlockTag(op.getBlockAddrInfoAttr());
5522 mlir::LLVM::BlockTagAttr tagAttr;
5529 tagAttr = matchLabel.getTag();
5531 auto blkAddr = mlir::LLVM::BlockAddressAttr::get(
5532 rewriter.getContext(), op.getBlockAddrInfoAttr().getFunc(), tagAttr);
5533 rewriter.setInsertionPoint(op);
5534 auto newOp = mlir::LLVM::BlockAddressOp::create(
5535 rewriter, op.getLoc(), mlir::LLVM::LLVMPointerType::get(ctx), blkAddr);
5537 blockInfoAddr.addUnresolvedBlockAddress(newOp, op.getBlockAddrInfoAttr());
5538 rewriter.replaceOp(op, newOp);
5539 return mlir::success();
5542mlir::LogicalResult CIRToLLVMIndirectBrOpLowering::matchAndRewrite(
5543 cir::IndirectBrOp op, OpAdaptor adaptor,
5544 mlir::ConversionPatternRewriter &rewriter)
const {
5546 mlir::Value targetAddr = adaptor.getAddr();
5554 if (op.getPoison()) {
5555 auto llvmPtrType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
5557 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), llvmPtrType);
5560 rewriter.replaceOpWithNewOp<mlir::LLVM::IndirectBrOp>(
5561 op, targetAddr, adaptor.getSuccOperands(), op.getSuccessors());
5562 return mlir::success();
5565mlir::LogicalResult CIRToLLVMTokenNoneOpLowering::matchAndRewrite(
5566 cir::TokenNoneOp op, OpAdaptor adaptor,
5567 mlir::ConversionPatternRewriter &rewriter)
const {
5568 rewriter.replaceOpWithNewOp<mlir::LLVM::NoneTokenOp>(
5569 op, mlir::TokenType::get(rewriter.getContext()));
5570 return mlir::success();
5573mlir::LogicalResult CIRToLLVMCpuIdOpLowering::matchAndRewrite(
5574 cir::CpuIdOp op, OpAdaptor adaptor,
5575 mlir::ConversionPatternRewriter &rewriter)
const {
5576 mlir::Type i32Ty = rewriter.getI32Type();
5577 mlir::Type i64Ty = rewriter.getI64Type();
5578 mlir::Type i32PtrTy = mlir::LLVM::LLVMPointerType::get(i32Ty.getContext(), 0);
5580 mlir::Type cpuidRetTy = mlir::LLVM::LLVMStructType::getLiteral(
5581 rewriter.getContext(), {i32Ty, i32Ty, i32Ty, i32Ty});
5583 mlir::Value functionId = adaptor.getFunctionId();
5584 mlir::Value subFunctionId = adaptor.getSubFunctionId();
5586 StringRef asmString, constraints;
5587 mlir::ModuleOp moduleOp = op->getParentOfType<mlir::ModuleOp>();
5588 llvm::Triple triple(
5589 mlir::cast<mlir::StringAttr>(
5590 moduleOp->getAttr(cir::CIRDialect::getTripleAttrName()))
5592 if (triple.getArch() == llvm::Triple::x86) {
5593 asmString =
"cpuid";
5594 constraints =
"={ax},={bx},={cx},={dx},{ax},{cx}";
5597 asmString =
"xchgq %rbx, ${1:q}\n"
5599 "xchgq %rbx, ${1:q}";
5600 constraints =
"={ax},=r,={cx},={dx},0,2";
5603 mlir::Value inlineAsm =
5604 mlir::LLVM::InlineAsmOp::create(
5605 rewriter, op.getLoc(), cpuidRetTy, {functionId, subFunctionId},
5606 rewriter.getStringAttr(asmString),
5607 rewriter.getStringAttr(constraints),
5610 mlir::LLVM::TailCallKindAttr{},
5611 mlir::LLVM::AsmDialectAttr{},
5615 mlir::Value basePtr = adaptor.getCpuInfo();
5617 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
5618 unsigned alignment = layout.getTypeABIAlignment(i32Ty);
5619 for (
unsigned i = 0; i < 4; i++) {
5620 mlir::Value extracted =
5621 mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(), inlineAsm, i)
5623 mlir::Value index = mlir::LLVM::ConstantOp::create(
5624 rewriter, op.getLoc(), i64Ty, rewriter.getI64IntegerAttr(i));
5626 mlir::Value storePtr = mlir::LLVM::GEPOp::create(
5627 rewriter, op.getLoc(), i32PtrTy, i32Ty, basePtr,
5628 gepIndices, mlir::LLVM::GEPNoWrapFlags::none)
5630 mlir::LLVM::StoreOp::create(rewriter, op.getLoc(), extracted, storePtr,
5634 rewriter.eraseOp(op);
5635 return mlir::success();
5638mlir::LogicalResult CIRToLLVMMemChrOpLowering::matchAndRewrite(
5639 cir::MemChrOp op, OpAdaptor adaptor,
5640 mlir::ConversionPatternRewriter &rewriter)
const {
5641 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
5642 mlir::Type srcTy = getTypeConverter()->convertType(op.getSrc().getType());
5643 mlir::Type patternTy =
5644 getTypeConverter()->convertType(op.getPattern().getType());
5645 mlir::Type lenTy = getTypeConverter()->convertType(op.getLen().getType());
5647 mlir::LLVM::LLVMFunctionType::get(llvmPtrTy, {srcTy, patternTy, lenTy},
5649 llvm::StringRef fnName =
"memchr";
5651 mlir::Builder b(rewriter.getContext());
5652 mlir::NamedAttribute noundefAttr =
5653 b.getNamedAttr(
"llvm.noundef", b.getUnitAttr());
5654 mlir::DictionaryAttr noundefDict = mlir::DictionaryAttr::get(
5657 mlir::ArrayAttr argAttrs =
5658 mlir::ArrayAttr::get(rewriter.getContext(), argAttrVec);
5663 mlir::LLVM::CallOp newCall = rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(
5664 op, mlir::TypeRange{llvmPtrTy}, fnName,
5665 mlir::ValueRange{adaptor.getSrc(), adaptor.getPattern(),
5667 newCall.setArgAttrsAttr(argAttrs);
5668 return mlir::success();
5674 mlir::Location loc, mlir::Value inputPtr,
5675 uint64_t baseAlignment,
5676 cir::OffsetPairAttr paddingAttr) {
5681 uint64_t charWidth = 8;
5682 mlir::Type i8Ty = rewriter.getI8Type();
5683 mlir::Type ptrTy = mlir::LLVM::LLVMPointerType::get(i8Ty.getContext());
5685 auto startByte = paddingAttr.getStart() / charWidth;
5686 auto startBit = paddingAttr.getStart() % charWidth;
5687 auto endByte = paddingAttr.getEnd() / charWidth;
5688 auto endBit = paddingAttr.getEnd() % charWidth;
5690 if (startByte == endByte) {
5692 auto index = mlir::LLVM::ConstantOp::create(
5693 rewriter, loc, rewriter.getI32Type(), startByte);
5694 auto element = mlir::LLVM::GEPOp::create(rewriter, loc, ptrTy, i8Ty,
5697 uint64_t adjustedAlignment = llvm::MinAlign(baseAlignment, startByte);
5699 auto value = mlir::LLVM::LoadOp::create(rewriter, loc, i8Ty, element,
5704 uint8_t bitsToClear = ((1 << endBit) - 1) & ~((1 << startBit) - 1);
5705 uint8_t bitsToKeep = ~bitsToClear;
5707 mlir::LLVM::ConstantOp::create(rewriter, loc, i8Ty, bitsToKeep);
5708 auto newValue = mlir::LLVM::AndOp::create(rewriter, loc, value, maskValue);
5710 mlir::LLVM::StoreOp::create(rewriter, loc, newValue, element,
5714 if (startBit != 0) {
5715 auto index = mlir::LLVM::ConstantOp::create(
5716 rewriter, loc, rewriter.getI32Type(), startByte);
5717 auto element = mlir::LLVM::GEPOp::create(rewriter, loc, ptrTy, i8Ty,
5719 uint64_t adjustedAlignment = llvm::MinAlign(baseAlignment, startByte);
5721 auto value = mlir::LLVM::LoadOp::create(rewriter, loc, i8Ty, element,
5724 uint8_t bitsToClear = ((1 << (charWidth - startBit)) - 1) << startBit;
5725 uint8_t bitsToKeep = ~bitsToClear;
5727 mlir::LLVM::ConstantOp::create(rewriter, loc, i8Ty, bitsToKeep);
5729 mlir::LLVM::AndOp::create(rewriter, loc, value, maskValue);
5731 mlir::LLVM::StoreOp::create(rewriter, loc, newValue, element,
5737 for (
auto offset = startByte; offset < endByte; ++offset) {
5738 auto index = mlir::LLVM::ConstantOp::create(
5739 rewriter, loc, rewriter.getI32Type(), offset);
5740 auto element = mlir::LLVM::GEPOp::create(rewriter, loc, ptrTy, i8Ty,
5742 uint64_t adjustedAlignment = llvm::MinAlign(baseAlignment, offset);
5744 auto zero = mlir::LLVM::ConstantOp::create(rewriter, loc, i8Ty, 0);
5745 mlir::LLVM::StoreOp::create(rewriter, loc, zero, element,
5751 auto index = mlir::LLVM::ConstantOp::create(
5752 rewriter, loc, rewriter.getI32Type(), endByte);
5753 auto element = mlir::LLVM::GEPOp::create(rewriter, loc, ptrTy, i8Ty,
5755 uint64_t adjustedAlignment = llvm::MinAlign(baseAlignment, endByte);
5757 auto value = mlir::LLVM::LoadOp::create(rewriter, loc, i8Ty, element,
5760 uint8_t bitsToClear = (1 << endBit) - 1;
5761 uint8_t bitsToKeep = ~bitsToClear;
5763 mlir::LLVM::ConstantOp::create(rewriter, loc, i8Ty, bitsToKeep);
5765 mlir::LLVM::AndOp::create(rewriter, loc, value, maskValue);
5767 mlir::LLVM::StoreOp::create(rewriter, loc, newValue, element,
5773mlir::LogicalResult CIRToLLVMClearPaddingOpLowering::matchAndRewrite(
5774 cir::ClearPaddingOp op, OpAdaptor adaptor,
5775 mlir::ConversionPatternRewriter &rewriter)
const {
5777 mlir::Value inputPtr = adaptor.getArg();
5778 for (mlir::Attribute attr : op.getPadding())
5779 clearPadding(rewriter, op.getLoc(), inputPtr, op.getAlignment(),
5780 cast<cir::OffsetPairAttr>(attr));
5782 rewriter.eraseOp(op);
5783 return mlir::success();
5787 return std::make_unique<ConvertCIRToLLVMPass>();
5793 pm.addPass(mlir::omp::createMarkDeclareTargetPass());
5796 pm.addPass(mlir::omp::createHostOpFilteringPass());
5799std::unique_ptr<llvm::Module>
5801 bool enableOpenMP, StringRef mlirSaveTempsOutFile,
5802 llvm::vfs::FileSystem *fs) {
5803 llvm::TimeTraceScope scope(
"lower from CIR to LLVM directly");
5805 mlir::MLIRContext *mlirCtx = mlirModule.getContext();
5807 mlir::PassManager pm(mlirCtx);
5810 (void)mlir::applyPassManagerCLOptions(pm);
5812 if (mlir::failed(pm.run(mlirModule))) {
5815 "The pass manager failed to lower CIR to LLVMIR dialect!");
5818 if (!mlirSaveTempsOutFile.empty()) {
5820 llvm::raw_fd_ostream out(mlirSaveTempsOutFile, ec);
5822 mlirModule->print(out);
5825 mlir::registerBuiltinDialectTranslation(*mlirCtx);
5826 mlir::registerLLVMDialectTranslation(*mlirCtx);
5827 mlir::registerOpenMPDialectTranslation(*mlirCtx);
5830 llvm::TimeTraceScope translateScope(
"translateModuleToLLVMIR");
5832 StringRef moduleName = mlirModule.getName().value_or(
"CIRToLLVMModule");
5833 std::unique_ptr<llvm::Module> llvmModule = mlir::translateModuleToLLVMIR(
5834 mlirModule, llvmCtx, moduleName,
false, fs);
5838 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::Type convertTypeForMemory(const mlir::TypeConverter &converter, mlir::DataLayout const &dataLayout, mlir::Type type)
mlir::Value createLShR(mlir::OpBuilder &bld, mlir::Value lhs, unsigned rhs)
mlir::Value createShL(mlir::OpBuilder &bld, mlir::Value lhs, unsigned rhs)
mlir::Type adjustGlobalTypeForInit(mlir::Type llvmType, mlir::Attribute init, const mlir::TypeConverter &converter, const mlir::DataLayout &dataLayout)
Adjust llvmType (the converted type of init) to the concrete LLVM type a global constant initialized ...
std::optional< mlir::Attribute > lowerConstRecordAttr(cir::ConstRecordAttr constRecord, mlir::SymbolTableCollection &symbolTables, const mlir::TypeConverter *converter, mlir::ModuleOp moduleOp={})
mlir::Value createAShR(mlir::OpBuilder &bld, mlir::Value lhs, unsigned rhs)
mlir::Value createAnd(mlir::OpBuilder &bld, mlir::Value lhs, const llvm::APInt &rhs)
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 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 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 bool shouldDropFuncAttribute(cir::FuncOp func, mlir::NamedAttribute attr, mlir::StringRef linkageAttrName)
Return true for attributes constructed by LLVMFuncOp::build.
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::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)
mlir::Type memberStorageType(mlir::Type memberTy)
The storage a member is stored as: the access unit for a bit-field member, and the member type itself...
void collectUnreachable(mlir::Operation *parent, llvm::SmallVectorImpl< mlir::Operation * > &ops)
Collect ops in blocks that are unreachable from their region's entry, appending them to ops.
bool memberOwnsBytes(mlir::Type memberTy)
Whether a record member occupies bytes of its record.
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 int32_t
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 __packed_splat2 __packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 uint32_t
static bool dataMemberType()
static bool addressSpace()
static bool 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()