18#include "mlir/Conversion/LLVMCommon/TypeConverter.h"
19#include "mlir/Conversion/OpenMPToLLVM/ConvertOpenMPToLLVM.h"
20#include "mlir/Dialect/DLTI/DLTI.h"
21#include "mlir/Dialect/Func/IR/FuncOps.h"
22#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
23#include "mlir/Dialect/LLVMIR/LLVMTypes.h"
24#include "mlir/Dialect/OpenMP/OpenMPDialect.h"
25#include "mlir/Dialect/OpenMP/Transforms/Passes.h"
26#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
27#include "mlir/IR/BuiltinAttributes.h"
28#include "mlir/IR/BuiltinDialect.h"
29#include "mlir/IR/BuiltinOps.h"
30#include "mlir/IR/Location.h"
31#include "mlir/IR/Types.h"
32#include "mlir/Pass/Pass.h"
33#include "mlir/Pass/PassManager.h"
34#include "mlir/Support/LLVM.h"
35#include "mlir/Target/LLVMIR/Dialect/Builtin/BuiltinToLLVMIRTranslation.h"
36#include "mlir/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.h"
37#include "mlir/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.h"
38#include "mlir/Target/LLVMIR/Export.h"
39#include "mlir/Transforms/DialectConversion.h"
48#include "llvm/ADT/MapVector.h"
49#include "llvm/ADT/StringMap.h"
50#include "llvm/ADT/TypeSwitch.h"
51#include "llvm/IR/Module.h"
52#include "llvm/Support/Casting.h"
53#include "llvm/Support/ErrorHandling.h"
54#include "llvm/Support/TimeProfiler.h"
55#include "llvm/Support/VirtualFileSystem.h"
56#include "llvm/Support/raw_ostream.h"
71mlir::Type elementTypeIfVector(mlir::Type type) {
72 return llvm::TypeSwitch<mlir::Type, mlir::Type>(type)
73 .Case<cir::VectorType, mlir::VectorType>(
74 [](
auto p) {
return p.getElementType(); })
75 .
Default([](mlir::Type p) {
return p; });
83 mlir::DataLayout
const &dataLayout,
87 if (isa<cir::BoolType>(type)) {
88 return mlir::IntegerType::get(type.getContext(),
89 dataLayout.getTypeSizeInBits(type));
92 return converter.convertType(type);
96 mlir::IntegerType dstTy,
97 bool isSigned =
false) {
98 mlir::Type srcTy = src.getType();
99 assert(mlir::isa<mlir::IntegerType>(srcTy));
101 unsigned srcWidth = mlir::cast<mlir::IntegerType>(srcTy).getWidth();
102 unsigned dstWidth = mlir::cast<mlir::IntegerType>(dstTy).getWidth();
103 mlir::Location loc = src.getLoc();
105 if (dstWidth > srcWidth && isSigned)
106 return mlir::LLVM::SExtOp::create(bld, loc, dstTy, src);
107 if (dstWidth > srcWidth)
108 return mlir::LLVM::ZExtOp::create(bld, loc, dstTy, src);
109 if (dstWidth < srcWidth)
110 return mlir::LLVM::TruncOp::create(bld, loc, dstTy, src);
111 return mlir::LLVM::BitcastOp::create(bld, loc, dstTy, src);
114static mlir::LLVM::Visibility
116 switch (visibilityKind) {
117 case cir::VisibilityKind::Default:
118 return ::mlir::LLVM::Visibility::Default;
119 case cir::VisibilityKind::Hidden:
120 return ::mlir::LLVM::Visibility::Hidden;
121 case cir::VisibilityKind::Protected:
122 return ::mlir::LLVM::Visibility::Protected;
130 mlir::DataLayout
const &dataLayout,
131 cir::LoadOp op, mlir::Value value) {
134 if (
auto boolTy = mlir::dyn_cast<cir::BoolType>(op.getType())) {
136 assert(value.getType().isInteger(dataLayout.getTypeSizeInBits(boolTy)));
146static mlir::Value
emitToMemory(mlir::ConversionPatternRewriter &rewriter,
147 mlir::DataLayout
const &dataLayout,
148 mlir::Type origType, mlir::Value value) {
151 if (
auto boolTy = mlir::dyn_cast<cir::BoolType>(origType)) {
153 mlir::IntegerType memType =
154 rewriter.getIntegerType(dataLayout.getTypeSizeInBits(boolTy));
162 using CIR = cir::GlobalLinkageKind;
163 using LLVM = mlir::LLVM::Linkage;
166 case CIR::AppendingLinkage:
167 return LLVM::Appending;
168 case CIR::AvailableExternallyLinkage:
169 return LLVM::AvailableExternally;
170 case CIR::CommonLinkage:
172 case CIR::ExternalLinkage:
173 return LLVM::External;
174 case CIR::ExternalWeakLinkage:
175 return LLVM::ExternWeak;
176 case CIR::InternalLinkage:
177 return LLVM::Internal;
178 case CIR::LinkOnceAnyLinkage:
179 return LLVM::Linkonce;
180 case CIR::LinkOnceODRLinkage:
181 return LLVM::LinkonceODR;
182 case CIR::PrivateLinkage:
183 return LLVM::Private;
184 case CIR::WeakAnyLinkage:
186 case CIR::WeakODRLinkage:
187 return LLVM::WeakODR;
189 llvm_unreachable(
"Unknown CIR linkage type");
193 using CIR = cir::CallingConv;
194 using LLVM = mlir::LLVM::CConv;
196 switch (callingConv) {
199 case CIR::SpirKernel:
200 return LLVM::SPIR_KERNEL;
201 case CIR::SpirFunction:
202 return LLVM::SPIR_FUNC;
204 return LLVM::PTX_Kernel;
205 case CIR::AMDGPUKernel:
206 return LLVM::AMDGPU_KERNEL;
208 llvm_unreachable(
"Unknown calling convention");
211mlir::LogicalResult CIRToLLVMCopyOpLowering::matchAndRewrite(
212 cir::CopyOp op, OpAdaptor adaptor,
213 mlir::ConversionPatternRewriter &rewriter)
const {
214 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
215 const mlir::Value
length = mlir::LLVM::ConstantOp::create(
216 rewriter, op.getLoc(), rewriter.getI64Type(),
217 op.getCopySizeInBytes(layout));
221 *getTypeConverter(), dataLayout, op.getDst().getType().getPointee()));
223 *getTypeConverter(), dataLayout, op.getSrc().getType().getPointee()));
225 mlir::NamedAttribute dstAlignAttr = rewriter.getNamedAttr(
226 mlir::LLVM::LLVMDialect::getAlignAttrName(),
227 rewriter.getI64IntegerAttr(op.getDstAlignment().value_or(dstTypeAlign)));
228 mlir::NamedAttribute srcAlignAttr = rewriter.getNamedAttr(
229 mlir::LLVM::LLVMDialect::getAlignAttrName(),
230 rewriter.getI64IntegerAttr(op.getSrcAlignment().value_or(srcTypeAlign)));
231 mlir::ArrayAttr argAttrs = rewriter.getArrayAttr({
232 rewriter.getDictionaryAttr({dstAlignAttr}),
233 rewriter.getDictionaryAttr({srcAlignAttr}),
236 rewriter.replaceOpWithNewOp<mlir::LLVM::MemcpyOp>(
237 op, adaptor.getDst(), adaptor.getSrc(),
length, op.getIsVolatile(),
239 nullptr,
nullptr, argAttrs,
241 return mlir::success();
244mlir::LogicalResult CIRToLLVMMemCpyOpLowering::matchAndRewrite(
245 cir::MemCpyOp op, OpAdaptor adaptor,
246 mlir::ConversionPatternRewriter &rewriter)
const {
247 rewriter.replaceOpWithNewOp<mlir::LLVM::MemcpyOp>(
248 op, adaptor.getDst(), adaptor.getSrc(), adaptor.getLen(),
250 return mlir::success();
253mlir::LogicalResult CIRToLLVMMemMoveOpLowering::matchAndRewrite(
254 cir::MemMoveOp op, OpAdaptor adaptor,
255 mlir::ConversionPatternRewriter &rewriter)
const {
256 rewriter.replaceOpWithNewOp<mlir::LLVM::MemmoveOp>(
257 op, adaptor.getDst(), adaptor.getSrc(), adaptor.getLen(),
259 return mlir::success();
262mlir::LogicalResult CIRToLLVMMemSetOpLowering::matchAndRewrite(
263 cir::MemSetOp op, OpAdaptor adaptor,
264 mlir::ConversionPatternRewriter &rewriter)
const {
266 auto memset = rewriter.replaceOpWithNewOp<mlir::LLVM::MemsetOp>(
267 op, adaptor.getDst(), adaptor.getVal(), adaptor.getLen(),
270 if (op.getAlignmentAttr()) {
272 llvm::SmallVector<mlir::Attribute> attrs{
memset.getNumOperands(),
273 rewriter.getDictionaryAttr({})};
274 llvm::SmallVector<mlir::NamedAttribute> destAttrs;
276 {mlir::LLVM::LLVMDialect::getAlignAttrName(), op.getAlignmentAttr()});
277 attrs[
memset.odsIndex_dst] = rewriter.getDictionaryAttr(destAttrs);
279 auto arrayAttr = rewriter.getArrayAttr(attrs);
280 memset.setArgAttrsAttr(arrayAttr);
283 return mlir::success();
287 mlir::Value llvmSrc, mlir::Type llvmDstIntTy,
289 uint64_t cirDstIntWidth) {
290 if (cirSrcWidth == cirDstIntWidth)
293 auto loc = llvmSrc.getLoc();
294 if (cirSrcWidth < cirDstIntWidth) {
296 return mlir::LLVM::ZExtOp::create(rewriter, loc, llvmDstIntTy, llvmSrc);
297 return mlir::LLVM::SExtOp::create(rewriter, loc, llvmDstIntTy, llvmSrc);
301 return mlir::LLVM::TruncOp::create(rewriter, loc, llvmDstIntTy, llvmSrc);
307 mlir::ConversionPatternRewriter &rewriter,
308 const mlir::TypeConverter *converter,
310 : parentOp(parentOp), rewriter(rewriter), converter(converter),
311 blockInfoAddr(blockInfoAddr) {}
313#define GET_CIR_ATTR_TO_VALUE_VISITOR_DECLS
314#include "clang/CIR/Dialect/IR/CIRLowering.inc"
315#undef GET_CIR_ATTR_TO_VALUE_VISITOR_DECLS
318 mlir::Operation *parentOp;
319 mlir::ConversionPatternRewriter &rewriter;
320 const mlir::TypeConverter *converter;
323 LLVMBlockAddressInfo *blockInfoAddr;
328 const mlir::Attribute attr,
329 mlir::ConversionPatternRewriter &rewriter,
330 const mlir::TypeConverter *converter,
332 CIRAttrToValue valueConverter(parentOp, rewriter, converter, blockInfoAddr);
333 mlir::Value value = valueConverter.visit(attr);
335 llvm_unreachable(
"unhandled attribute type");
340 cir::SideEffect sideEffect,
341 mlir::LLVM::MemoryEffectsAttr &memoryEffect,
342 bool &noUnwind,
bool &willReturn,
344 using mlir::LLVM::ModRefInfo;
346 switch (sideEffect) {
347 case cir::SideEffect::All:
349 noUnwind = isNothrow;
353 case cir::SideEffect::Pure:
354 memoryEffect = mlir::LLVM::MemoryEffectsAttr::get(
355 callOp->getContext(), ModRefInfo::Ref,
365 case cir::SideEffect::Const:
366 memoryEffect = mlir::LLVM::MemoryEffectsAttr::get(
367 callOp->getContext(), ModRefInfo::NoModRef,
368 ModRefInfo::NoModRef,
369 ModRefInfo::NoModRef,
370 ModRefInfo::NoModRef,
371 ModRefInfo::NoModRef,
372 ModRefInfo::NoModRef);
378 noReturn = callOp->hasAttr(CIRDialect::getNoReturnAttrName());
381static mlir::LLVM::CallIntrinsicOp
383 mlir::Location loc,
const llvm::Twine &intrinsicName,
384 mlir::Type resultTy, mlir::ValueRange operands) {
385 auto intrinsicNameAttr =
386 mlir::StringAttr::get(rewriter.getContext(), intrinsicName);
389 return mlir::LLVM::CallIntrinsicOp::create(rewriter, loc, resultTy,
390 intrinsicNameAttr, operands);
391 return mlir::LLVM::CallIntrinsicOp::create(rewriter, loc, intrinsicNameAttr,
396 mlir::ConversionPatternRewriter &rewriter, mlir::Operation *op,
397 const llvm::Twine &intrinsicName, mlir::Type resultTy,
398 mlir::ValueRange operands) {
400 rewriter, op->getLoc(), intrinsicName, resultTy, operands);
401 rewriter.replaceOp(op, callIntrinOp.getOperation());
405mlir::LogicalResult CIRToLLVMLLVMIntrinsicCallOpLowering::matchAndRewrite(
406 cir::LLVMIntrinsicCallOp op, OpAdaptor adaptor,
407 mlir::ConversionPatternRewriter &rewriter)
const {
410 mlir::Type llvmResTy;
411 if (op->getNumResults() != 0) {
412 llvmResTy = getTypeConverter()->convertType(op->getResultTypes()[0]);
414 return op.emitError(
"expected LLVM result type");
416 StringRef name = op.getIntrinsicName();
429 adaptor.getOperands());
430 return mlir::success();
434mlir::Value CIRAttrToValue::visitCirAttr(cir::BoolAttr boolAttr) {
435 mlir::Location loc = parentOp->getLoc();
436 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
437 mlir::Value boolVal = mlir::LLVM::ConstantOp::create(
438 rewriter, loc, converter->convertType(boolAttr.getType()),
439 boolAttr.getValue());
440 return emitToMemory(rewriter, layout, boolAttr.getType(), boolVal);
444mlir::Value CIRAttrToValue::visitCirAttr(cir::IntAttr intAttr) {
445 mlir::Location loc = parentOp->getLoc();
446 return mlir::LLVM::ConstantOp::create(
447 rewriter, loc, converter->convertType(intAttr.getType()),
452mlir::Value CIRAttrToValue::visitCirAttr(cir::FPAttr fltAttr) {
453 mlir::Location loc = parentOp->getLoc();
454 return mlir::LLVM::ConstantOp::create(
455 rewriter, loc, converter->convertType(fltAttr.getType()),
460mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstComplexAttr complexAttr) {
461 auto complexType = mlir::cast<cir::ComplexType>(complexAttr.getType());
462 mlir::Type complexElemTy =
complexType.getElementType();
463 mlir::Type complexElemLLVMTy = converter->convertType(complexElemTy);
465 mlir::Attribute components[2];
466 if (
const auto intType = mlir::dyn_cast<cir::IntType>(complexElemTy)) {
467 components[0] = rewriter.getIntegerAttr(
469 mlir::cast<cir::IntAttr>(complexAttr.getReal()).getValue());
470 components[1] = rewriter.getIntegerAttr(
472 mlir::cast<cir::IntAttr>(complexAttr.getImag()).getValue());
474 components[0] = rewriter.getFloatAttr(
476 mlir::cast<cir::FPAttr>(complexAttr.getReal()).getValue());
477 components[1] = rewriter.getFloatAttr(
479 mlir::cast<cir::FPAttr>(complexAttr.getImag()).getValue());
482 mlir::Location loc = parentOp->getLoc();
483 return mlir::LLVM::ConstantOp::create(
484 rewriter, loc, converter->convertType(complexAttr.getType()),
485 rewriter.getArrayAttr(components));
489mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstPtrAttr ptrAttr) {
490 mlir::Location loc = parentOp->getLoc();
491 if (ptrAttr.isNullValue()) {
492 return mlir::LLVM::ZeroOp::create(
493 rewriter, loc, converter->convertType(ptrAttr.getType()));
495 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
496 mlir::Value ptrVal = mlir::LLVM::ConstantOp::create(
498 rewriter.getIntegerType(layout.getTypeSizeInBits(ptrAttr.getType())),
499 ptrAttr.getValue().getInt());
500 return mlir::LLVM::IntToPtrOp::create(
501 rewriter, loc, converter->convertType(ptrAttr.getType()), ptrVal);
505mlir::Value CIRAttrToValue::visitCirAttr(cir::BlockAddrInfoAttr blockAddrInfo) {
506 assert(blockInfoAddr &&
507 "block address lowering requires LLVMBlockAddressInfo");
512 mlir::Location loc = parentOp->getLoc();
513 mlir::LLVM::BlockTagOp matchLabel =
514 blockInfoAddr->lookupBlockTag(blockAddrInfo);
515 mlir::LLVM::BlockTagAttr tagAttr =
516 matchLabel ? matchLabel.getTag() : mlir::LLVM::BlockTagAttr{};
517 auto blkAddr = mlir::LLVM::BlockAddressAttr::get(
518 rewriter.getContext(), blockAddrInfo.getFunc(), tagAttr);
519 auto blockAddressOp = mlir::LLVM::BlockAddressOp::create(
520 rewriter, loc, mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
523 blockInfoAddr->addUnresolvedBlockAddress(blockAddressOp, blockAddrInfo);
524 return blockAddressOp;
528mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstArrayAttr attr) {
529 mlir::Type llvmTy = converter->convertType(
attr.getType());
530 mlir::Location loc = parentOp->getLoc();
535 if (std::optional<mlir::Attribute> denseAttr =
537 return mlir::LLVM::ConstantOp::create(rewriter, loc, llvmTy, *denseAttr);
539 if (
attr.hasTrailingZeros()) {
540 mlir::Type arrayTy =
attr.getType();
541 result = mlir::LLVM::ZeroOp::create(rewriter, loc,
542 converter->convertType(arrayTy));
544 result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
548 if (
auto arrayAttr = mlir::dyn_cast<mlir::ArrayAttr>(
attr.getElts())) {
549 for (
auto [idx, elt] : llvm::enumerate(arrayAttr)) {
550 mlir::Value init = visit(elt);
552 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
554 }
else if (
auto strAttr = mlir::dyn_cast<mlir::StringAttr>(
attr.getElts())) {
557 auto arrayTy = mlir::dyn_cast<cir::ArrayType>(strAttr.getType());
558 assert(arrayTy &&
"String attribute must have an array type");
559 mlir::Type eltTy = arrayTy.getElementType();
560 for (
auto [idx, elt] : llvm::enumerate(strAttr)) {
561 auto init = mlir::LLVM::ConstantOp::create(
562 rewriter, loc, converter->convertType(eltTy), elt);
564 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
567 llvm_unreachable(
"unexpected ConstArrayAttr elements");
584 uint64_t maxAlign = 1;
585 uint64_t totalSize = 0;
586 for (mlir::Type member : members) {
587 uint64_t align = dataLayout.getTypeABIAlignment(member);
588 maxAlign = std::max(maxAlign, align);
589 uint64_t size = dataLayout.getTypeSize(member).getFixedValue();
591 if (llvm::alignTo(totalSize, align) != totalSize)
596 return llvm::alignTo(totalSize, maxAlign) != totalSize;
610 const mlir::TypeConverter &converter,
611 const mlir::DataLayout &dataLayout) {
613 auto constRecord = mlir::dyn_cast_if_present<cir::ConstRecordAttr>(init);
619 auto structTy = mlir::dyn_cast<mlir::LLVM::LLVMStructType>(llvmType);
620 if (!structTy || structTy.getBody().empty())
624 auto fam = dyn_cast<mlir::LLVM::LLVMArrayType>(structTy.getBody().back());
625 if (!fam || fam.getNumElements() != 0)
629 constRecord.getMembers().getValue();
630 mlir::Type lastInitType = cast<mlir::TypedAttr>(initMembers.back()).getType();
633 if (cast<cir::ArrayType>(lastInitType).getSize() == 0)
637 newBody[newBody.size() - 1] = converter.convertType(lastInitType);
641 return mlir::LLVM::LLVMStructType::getLiteral(structTy.getContext(), newBody,
646mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstRecordAttr constRecord) {
647 mlir::Type llvmTy = converter->convertType(constRecord.getType());
648 mlir::DataLayout dataLayout(parentOp->getParentOfType<mlir::ModuleOp>());
651 const mlir::Location loc = parentOp->getLoc();
652 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
655 for (
auto [idx, elt] : llvm::enumerate(constRecord.getMembers())) {
656 mlir::Value init = visit(elt);
658 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
665mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstVectorAttr attr) {
666 const mlir::Type llvmTy = converter->convertType(
attr.getType());
667 const mlir::Location loc = parentOp->getLoc();
669 SmallVector<mlir::Attribute> mlirValues;
670 for (
const mlir::Attribute elementAttr :
attr.getElts()) {
671 mlir::Attribute mlirAttr;
672 if (
auto intAttr = mlir::dyn_cast<cir::IntAttr>(elementAttr)) {
673 mlirAttr = rewriter.getIntegerAttr(
674 converter->convertType(intAttr.getType()), intAttr.getValue());
675 }
else if (
auto floatAttr = mlir::dyn_cast<cir::FPAttr>(elementAttr)) {
676 mlirAttr = rewriter.getFloatAttr(
677 converter->convertType(floatAttr.getType()), floatAttr.getValue());
680 "vector constant with an element that is neither an int nor a float");
682 mlirValues.push_back(mlirAttr);
685 return mlir::LLVM::ConstantOp::create(
686 rewriter, loc, llvmTy,
687 mlir::DenseElementsAttr::get(mlir::cast<mlir::ShapedType>(llvmTy),
692mlir::Value CIRAttrToValue::visitCirAttr(cir::GlobalViewAttr globalAttr) {
693 auto moduleOp = parentOp->getParentOfType<mlir::ModuleOp>();
694 mlir::DataLayout dataLayout(moduleOp);
695 mlir::Type sourceType;
696 unsigned sourceAddrSpace = 0;
697 llvm::StringRef symName;
698 mlir::Operation *sourceSymbol =
699 mlir::SymbolTable::lookupSymbolIn(moduleOp, globalAttr.getSymbol());
700 if (
auto llvmSymbol = dyn_cast<mlir::LLVM::GlobalOp>(sourceSymbol)) {
701 sourceType = llvmSymbol.getType();
702 symName = llvmSymbol.getSymName();
703 sourceAddrSpace = llvmSymbol.getAddrSpace();
704 }
else if (
auto cirSymbol = dyn_cast<cir::GlobalOp>(sourceSymbol)) {
707 symName = cirSymbol.getSymName();
708 if (
auto targetAS = mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
709 cirSymbol.getAddrSpaceAttr()))
710 sourceAddrSpace = targetAS.getValue();
711 }
else if (
auto llvmFun = dyn_cast<mlir::LLVM::LLVMFuncOp>(sourceSymbol)) {
712 sourceType = llvmFun.getFunctionType();
713 symName = llvmFun.getSymName();
714 }
else if (
auto fun = dyn_cast<cir::FuncOp>(sourceSymbol)) {
715 sourceType = converter->convertType(fun.getFunctionType());
716 symName = fun.getSymName();
717 }
else if (
auto alias = dyn_cast<mlir::LLVM::AliasOp>(sourceSymbol)) {
718 sourceType = alias.getType();
719 symName = alias.getSymName();
721 llvm_unreachable(
"Unexpected GlobalOp type");
724 mlir::Location loc = parentOp->getLoc();
725 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
727 mlir::LLVM::LLVMPointerType::get(rewriter.getContext(), sourceAddrSpace),
730 if (globalAttr.getIndices()) {
731 llvm::SmallVector<mlir::LLVM::GEPArg> indices;
733 if (mlir::isa<mlir::LLVM::LLVMArrayType, mlir::LLVM::LLVMStructType>(
735 indices.push_back(0);
737 for (mlir::Attribute idx : globalAttr.getIndices()) {
738 auto intAttr = mlir::cast<mlir::IntegerAttr>(idx);
739 indices.push_back(intAttr.getValue().getSExtValue());
741 mlir::Type resTy = addrOp.getType();
742 mlir::Type eltTy = converter->convertType(sourceType);
744 mlir::LLVM::GEPOp::create(rewriter, loc, resTy, eltTy, addrOp, indices,
745 mlir::LLVM::GEPNoWrapFlags::none);
752 if (
auto intTy = mlir::dyn_cast<cir::IntType>(globalAttr.getType())) {
753 mlir::Type llvmDstTy = converter->convertType(globalAttr.getType());
754 return mlir::LLVM::PtrToIntOp::create(rewriter, parentOp->getLoc(),
758 if (
auto ptrTy = mlir::dyn_cast<cir::PointerType>(globalAttr.getType())) {
759 auto llvmDstTy = converter->convertType<mlir::LLVM::LLVMPointerType>(ptrTy);
760 unsigned dstAddrSpace = llvmDstTy.getAddressSpace();
762 if (sourceAddrSpace != dstAddrSpace)
763 addrOp = mlir::LLVM::AddrSpaceCastOp::create(rewriter, parentOp->getLoc(),
766 mlir::Type llvmEltTy =
770 if (llvmEltTy == sourceType)
776 if (addrOp.getType() == llvmDstTy)
779 return mlir::LLVM::BitcastOp::create(rewriter, parentOp->getLoc(),
783 if (mlir::isa<cir::VPtrType>(globalAttr.getType()))
786 llvm_unreachable(
"Expecting pointer or integer type for GlobalViewAttr");
790mlir::Value CIRAttrToValue::visitCirAttr(cir::TypeInfoAttr typeInfoAttr) {
791 mlir::Type llvmTy = converter->convertType(typeInfoAttr.getType());
792 mlir::Location loc = parentOp->getLoc();
793 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
795 for (
auto [idx, elt] : llvm::enumerate(typeInfoAttr.getData())) {
796 mlir::Value init = visit(elt);
798 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
805mlir::Value CIRAttrToValue::visitCirAttr(cir::UndefAttr undefAttr) {
806 mlir::Location loc = parentOp->getLoc();
807 return mlir::LLVM::UndefOp::create(
808 rewriter, loc, converter->convertType(undefAttr.getType()));
812mlir::Value CIRAttrToValue::visitCirAttr(cir::PoisonAttr poisonAttr) {
813 mlir::Location loc = parentOp->getLoc();
814 return mlir::LLVM::PoisonOp::create(
815 rewriter, loc, converter->convertType(poisonAttr.getType()));
819mlir::Value CIRAttrToValue::visitCirAttr(cir::VTableAttr vtableArr) {
820 mlir::Type llvmTy = converter->convertType(vtableArr.getType());
821 mlir::Location loc = parentOp->getLoc();
822 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
824 for (
auto [idx, elt] : llvm::enumerate(vtableArr.getData())) {
825 mlir::Value init = visit(elt);
827 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
834mlir::Value CIRAttrToValue::visitCirAttr(cir::ZeroAttr attr) {
835 mlir::Location loc = parentOp->getLoc();
836 return mlir::LLVM::ZeroOp::create(rewriter, loc,
837 converter->convertType(
attr.getType()));
845 mlir::ConversionPatternRewriter &rewriter)
846 : llvmType(type), rewriter(rewriter) {}
849 return llvm::TypeSwitch<mlir::Attribute, mlir::Attribute>(
attr)
850 .Case<cir::IntAttr, cir::FPAttr, cir::BoolAttr>(
852 .
Default([&](
auto attrT) {
return mlir::Attribute(); });
856 return rewriter.getIntegerAttr(llvmType,
attr.getValue());
860 return rewriter.getFloatAttr(llvmType,
attr.getValue());
864 return rewriter.getBoolAttr(
attr.getValue());
869 mlir::ConversionPatternRewriter &rewriter;
877 :
public mlir::PassWrapper<ConvertCIRToLLVMPass,
878 mlir::OperationPass<mlir::ModuleOp>> {
880 registry.insert<mlir::BuiltinDialect, mlir::DLTIDialect,
881 mlir::LLVM::LLVMDialect, mlir::func::FuncDialect>();
899 return "Convert the prepared CIR dialect module to LLVM dialect";
902 StringRef
getArgument()
const override {
return "cir-flat-to-llvm"; }
906 struct CollectedAnnotation {
907 mlir::StringAttr symName;
908 cir::AnnotationAttr annotation;
910 CollectedAnnotation(mlir::StringAttr symName,
911 cir::AnnotationAttr annotation, mlir::Location loc)
912 : symName(symName), annotation(annotation), loc(loc) {}
917mlir::LogicalResult CIRToLLVMIsFPClassOpLowering::matchAndRewrite(
918 cir::IsFPClassOp op, OpAdaptor adaptor,
919 mlir::ConversionPatternRewriter &rewriter)
const {
920 mlir::Value src = adaptor.getSrc();
921 cir::FPClassTest flags = adaptor.getFlags();
922 mlir::IntegerType retTy = rewriter.getI1Type();
924 rewriter.replaceOpWithNewOp<mlir::LLVM::IsFPClass>(
925 op, retTy, src,
static_cast<uint32_t>(flags));
926 return mlir::success();
929mlir::LogicalResult CIRToLLVMSignBitOpLowering::matchAndRewrite(
930 cir::SignBitOp op, OpAdaptor adaptor,
931 mlir::ConversionPatternRewriter &rewriter)
const {
934 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
935 int width = layout.getTypeSizeInBits(op.getInput().getType());
936 if (
auto longDoubleType =
937 mlir::dyn_cast<cir::LongDoubleType>(op.getInput().getType())) {
938 if (mlir::isa<cir::FP80Type>(longDoubleType.getUnderlying())) {
946 mlir::Type intTy = mlir::IntegerType::get(rewriter.getContext(), width);
947 auto bitcast = mlir::LLVM::BitcastOp::create(rewriter, op->getLoc(), intTy,
950 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op->getLoc(), intTy, 0);
951 auto cmpResult = mlir::LLVM::ICmpOp::create(rewriter, op.getLoc(),
952 mlir::LLVM::ICmpPredicate::slt,
953 bitcast.getResult(), zero);
954 rewriter.replaceOp(op, cmpResult);
955 return mlir::success();
958mlir::LogicalResult CIRToLLVMAssumeOpLowering::matchAndRewrite(
959 cir::AssumeOp op, OpAdaptor adaptor,
960 mlir::ConversionPatternRewriter &rewriter)
const {
961 mlir::Value cond = adaptor.getPredicate();
962 if (op.getBundleKind() == cir::AssumeBundleKind::None) {
963 rewriter.replaceOpWithNewOp<mlir::LLVM::AssumeOp>(op, cond);
964 return mlir::success();
967 llvm::StringRef tag = cir::stringifyAssumeBundleKind(op.getBundleKind());
968 rewriter.replaceOpWithNewOp<mlir::LLVM::AssumeOp>(op, cond, tag,
969 adaptor.getBundleArgs());
970 return mlir::success();
973static mlir::LLVM::AtomicOrdering
976 return mlir::LLVM::AtomicOrdering::not_atomic;
978 case cir::MemOrder::Relaxed:
979 return mlir::LLVM::AtomicOrdering::monotonic;
980 case cir::MemOrder::Consume:
981 case cir::MemOrder::Acquire:
982 return mlir::LLVM::AtomicOrdering::acquire;
983 case cir::MemOrder::Release:
984 return mlir::LLVM::AtomicOrdering::release;
985 case cir::MemOrder::AcquireRelease:
986 return mlir::LLVM::AtomicOrdering::acq_rel;
987 case cir::MemOrder::SequentiallyConsistent:
988 return mlir::LLVM::AtomicOrdering::seq_cst;
990 llvm_unreachable(
"unknown memory order");
994 return syncScope == cir::SyncScopeKind::SingleThread ?
"singlethread" :
"";
997static std::optional<llvm::StringRef>
999 if (syncScope.has_value())
1001 return std::nullopt;
1004mlir::LogicalResult CIRToLLVMAtomicCmpXchgOpLowering::matchAndRewrite(
1005 cir::AtomicCmpXchgOp op, OpAdaptor adaptor,
1006 mlir::ConversionPatternRewriter &rewriter)
const {
1007 mlir::Value expected = adaptor.getExpected();
1008 mlir::Value desired = adaptor.getDesired();
1010 auto cmpxchg = mlir::LLVM::AtomicCmpXchgOp::create(
1011 rewriter, op.getLoc(), adaptor.getPtr(), expected, desired,
1016 cmpxchg.setAlignment(adaptor.getAlignment());
1017 cmpxchg.setWeak(adaptor.getWeak());
1018 cmpxchg.setVolatile_(adaptor.getIsVolatile());
1021 auto old = mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(),
1022 cmpxchg.getResult(), 0);
1023 auto cmp = mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(),
1024 cmpxchg.getResult(), 1);
1026 rewriter.replaceOp(op, {old, cmp});
1027 return mlir::success();
1030mlir::LogicalResult CIRToLLVMAtomicXchgOpLowering::matchAndRewrite(
1031 cir::AtomicXchgOp op, OpAdaptor adaptor,
1032 mlir::ConversionPatternRewriter &rewriter)
const {
1034 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(adaptor.getMemOrder());
1036 rewriter.replaceOpWithNewOp<mlir::LLVM::AtomicRMWOp>(
1037 op, mlir::LLVM::AtomicBinOp::xchg, adaptor.getPtr(), adaptor.getVal(),
1038 llvmOrder, llvmSyncScope);
1039 return mlir::success();
1042mlir::LogicalResult CIRToLLVMAtomicTestAndSetOpLowering::matchAndRewrite(
1043 cir::AtomicTestAndSetOp op, OpAdaptor adaptor,
1044 mlir::ConversionPatternRewriter &rewriter)
const {
1047 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
1049 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1050 rewriter.getI8Type(), 1);
1051 auto rmw = mlir::LLVM::AtomicRMWOp::create(
1052 rewriter, op.getLoc(), mlir::LLVM::AtomicBinOp::xchg, adaptor.getPtr(),
1053 one, llvmOrder, llvm::StringRef(),
1054 adaptor.getAlignment().value_or(0), op.getIsVolatile());
1056 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1057 rewriter.getI8Type(), 0);
1058 auto cmp = mlir::LLVM::ICmpOp::create(
1059 rewriter, op.getLoc(), mlir::LLVM::ICmpPredicate::ne, rmw, zero);
1061 rewriter.replaceOp(op, cmp);
1062 return mlir::success();
1065mlir::LogicalResult CIRToLLVMAtomicClearOpLowering::matchAndRewrite(
1066 cir::AtomicClearOp op, OpAdaptor adaptor,
1067 mlir::ConversionPatternRewriter &rewriter)
const {
1070 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
1071 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1072 rewriter.getI8Type(), 0);
1073 auto store = mlir::LLVM::StoreOp::create(
1074 rewriter, op.getLoc(), zero, adaptor.getPtr(),
1075 adaptor.getAlignment().value_or(0), op.getIsVolatile(),
1076 false,
false, llvmOrder);
1078 rewriter.replaceOp(op, store);
1079 return mlir::success();
1082mlir::LogicalResult CIRToLLVMAtomicFenceOpLowering::matchAndRewrite(
1083 cir::AtomicFenceOp op, OpAdaptor adaptor,
1084 mlir::ConversionPatternRewriter &rewriter)
const {
1085 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(adaptor.getOrdering());
1087 auto fence = mlir::LLVM::FenceOp::create(rewriter, op.getLoc(), llvmOrder);
1090 rewriter.replaceOp(op, fence);
1092 return mlir::success();
1095static mlir::LLVM::AtomicBinOp
1098 case cir::AtomicFetchKind::Add:
1099 return isInt ? mlir::LLVM::AtomicBinOp::add : mlir::LLVM::AtomicBinOp::fadd;
1100 case cir::AtomicFetchKind::Sub:
1101 return isInt ? mlir::LLVM::AtomicBinOp::sub : mlir::LLVM::AtomicBinOp::fsub;
1102 case cir::AtomicFetchKind::And:
1103 return mlir::LLVM::AtomicBinOp::_and;
1104 case cir::AtomicFetchKind::Xor:
1105 return mlir::LLVM::AtomicBinOp::_xor;
1106 case cir::AtomicFetchKind::Or:
1107 return mlir::LLVM::AtomicBinOp::_or;
1108 case cir::AtomicFetchKind::Nand:
1109 return mlir::LLVM::AtomicBinOp::nand;
1110 case cir::AtomicFetchKind::Max: {
1112 return mlir::LLVM::AtomicBinOp::fmax;
1113 return isSignedInt ? mlir::LLVM::AtomicBinOp::max
1114 : mlir::LLVM::AtomicBinOp::umax;
1116 case cir::AtomicFetchKind::Min: {
1118 return mlir::LLVM::AtomicBinOp::fmin;
1119 return isSignedInt ? mlir::LLVM::AtomicBinOp::min
1120 : mlir::LLVM::AtomicBinOp::umin;
1122 case cir::AtomicFetchKind::UIncWrap:
1123 return mlir::LLVM::AtomicBinOp::uinc_wrap;
1124 case cir::AtomicFetchKind::UDecWrap:
1125 return mlir::LLVM::AtomicBinOp::udec_wrap;
1127 llvm_unreachable(
"Unknown atomic fetch opcode");
1133 case cir::AtomicFetchKind::Add:
1134 return isInt ? mlir::LLVM::AddOp::getOperationName()
1135 : mlir::LLVM::FAddOp::getOperationName();
1136 case cir::AtomicFetchKind::Sub:
1137 return isInt ? mlir::LLVM::SubOp::getOperationName()
1138 : mlir::LLVM::FSubOp::getOperationName();
1139 case cir::AtomicFetchKind::And:
1140 return mlir::LLVM::AndOp::getOperationName();
1141 case cir::AtomicFetchKind::Xor:
1142 return mlir::LLVM::XOrOp::getOperationName();
1143 case cir::AtomicFetchKind::Or:
1144 return mlir::LLVM::OrOp::getOperationName();
1145 case cir::AtomicFetchKind::Nand:
1147 return mlir::LLVM::AndOp::getOperationName();
1148 case cir::AtomicFetchKind::Max:
1149 case cir::AtomicFetchKind::Min:
1150 llvm_unreachable(
"handled in buildMinMaxPostOp");
1151 case cir::AtomicFetchKind::UIncWrap:
1152 case cir::AtomicFetchKind::UDecWrap:
1153 llvm_unreachable(
"uinc_wrap and udec_wrap are always fetch_first");
1155 llvm_unreachable(
"Unknown atomic fetch opcode");
1158mlir::Value CIRToLLVMAtomicFetchOpLowering::buildPostOp(
1159 cir::AtomicFetchOp op, OpAdaptor adaptor,
1160 mlir::ConversionPatternRewriter &rewriter, mlir::Value rmwVal,
1165 .create(op.getLoc(),
1166 rewriter.getStringAttr(
1168 atomicOperands, atomicResTys, {})
1172mlir::Value CIRToLLVMAtomicFetchOpLowering::buildMinMaxPostOp(
1173 cir::AtomicFetchOp op, OpAdaptor adaptor,
1174 mlir::ConversionPatternRewriter &rewriter, mlir::Value rmwVal,
bool isInt,
1175 bool isSigned)
const {
1176 mlir::Location loc = op.getLoc();
1179 if (op.getBinop() == cir::AtomicFetchKind::Max)
1180 return mlir::LLVM::MaxNumOp::create(rewriter, loc, rmwVal,
1182 return mlir::LLVM::MinNumOp::create(rewriter, loc, rmwVal,
1186 mlir::LLVM::ICmpPredicate pred;
1187 if (op.getBinop() == cir::AtomicFetchKind::Max) {
1188 pred = isSigned ? mlir::LLVM::ICmpPredicate::sgt
1189 : mlir::LLVM::ICmpPredicate::ugt;
1191 pred = isSigned ? mlir::LLVM::ICmpPredicate::slt
1192 : mlir::LLVM::ICmpPredicate::ult;
1194 mlir::Value cmp = mlir::LLVM::ICmpOp::create(
1196 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(), pred), rmwVal,
1198 return mlir::LLVM::SelectOp::create(rewriter, loc, cmp, rmwVal,
1202mlir::LogicalResult CIRToLLVMAtomicFetchOpLowering::matchAndRewrite(
1203 cir::AtomicFetchOp op, OpAdaptor adaptor,
1204 mlir::ConversionPatternRewriter &rewriter)
const {
1206 bool isSignedInt =
false;
1207 if (
auto intTy = mlir::dyn_cast<cir::IntType>(op.getVal().getType())) {
1209 isSignedInt = intTy.isSigned();
1210 }
else if (mlir::isa<cir::SingleType, cir::DoubleType>(
1211 op.getVal().getType())) {
1214 return op.emitError() <<
"Unsupported type: " << op.getVal().getType();
1217 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
1219 mlir::LLVM::AtomicBinOp llvmBinOp =
1221 auto rmwVal = mlir::LLVM::AtomicRMWOp::create(
1222 rewriter, op.getLoc(), llvmBinOp, adaptor.getPtr(), adaptor.getVal(),
1223 llvmOrder, llvmSyncScope);
1225 mlir::Value result = rmwVal.getResult();
1226 if (!op.getFetchFirst()) {
1227 if (op.getBinop() == cir::AtomicFetchKind::Max ||
1228 op.getBinop() == cir::AtomicFetchKind::Min)
1229 result = buildMinMaxPostOp(op, adaptor, rewriter, rmwVal.getRes(), isInt,
1232 result = buildPostOp(op, adaptor, rewriter, rmwVal.getRes(), isInt);
1235 if (op.getBinop() == cir::AtomicFetchKind::Nand) {
1236 auto negOne = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1237 result.getType(), -1);
1238 result = mlir::LLVM::XOrOp::create(rewriter, op.getLoc(), result, negOne);
1242 rewriter.replaceOp(op, result);
1243 return mlir::success();
1246mlir::LogicalResult CIRToLLVMBitClrsbOpLowering::matchAndRewrite(
1247 cir::BitClrsbOp op, OpAdaptor adaptor,
1248 mlir::ConversionPatternRewriter &rewriter)
const {
1249 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1250 adaptor.getInput().getType(), 0);
1251 auto isNeg = mlir::LLVM::ICmpOp::create(
1252 rewriter, op.getLoc(),
1253 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(),
1254 mlir::LLVM::ICmpPredicate::slt),
1255 adaptor.getInput(), zero);
1257 auto negOne = mlir::LLVM::ConstantOp::create(
1258 rewriter, op.getLoc(), adaptor.getInput().getType(), -1);
1259 auto flipped = mlir::LLVM::XOrOp::create(rewriter, op.getLoc(),
1260 adaptor.getInput(), negOne);
1262 auto select = mlir::LLVM::SelectOp::create(rewriter, op.getLoc(), isNeg,
1263 flipped, adaptor.getInput());
1265 auto resTy = getTypeConverter()->convertType(op.getType());
1266 auto clz = mlir::LLVM::CountLeadingZerosOp::create(
1267 rewriter, op.getLoc(), resTy,
select,
false);
1269 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1270 auto res = mlir::LLVM::SubOp::create(rewriter, op.getLoc(),
clz, one,
1271 mlir::LLVM::IntegerOverflowFlags::nuw);
1272 rewriter.replaceOp(op, res);
1274 return mlir::LogicalResult::success();
1277mlir::LogicalResult CIRToLLVMBitClzOpLowering::matchAndRewrite(
1278 cir::BitClzOp op, OpAdaptor adaptor,
1279 mlir::ConversionPatternRewriter &rewriter)
const {
1280 auto resTy = getTypeConverter()->convertType(op.getType());
1281 auto llvmOp = mlir::LLVM::CountLeadingZerosOp::create(
1282 rewriter, op.getLoc(), resTy, adaptor.getInput(), op.getPoisonZero());
1283 rewriter.replaceOp(op, llvmOp);
1284 return mlir::LogicalResult::success();
1287mlir::LogicalResult CIRToLLVMBitCtzOpLowering::matchAndRewrite(
1288 cir::BitCtzOp op, OpAdaptor adaptor,
1289 mlir::ConversionPatternRewriter &rewriter)
const {
1290 auto resTy = getTypeConverter()->convertType(op.getType());
1291 auto llvmOp = mlir::LLVM::CountTrailingZerosOp::create(
1292 rewriter, op.getLoc(), resTy, adaptor.getInput(), op.getPoisonZero());
1293 rewriter.replaceOp(op, llvmOp);
1294 return mlir::LogicalResult::success();
1297mlir::LogicalResult CIRToLLVMBitFfsOpLowering::matchAndRewrite(
1298 cir::BitFfsOp op, OpAdaptor adaptor,
1299 mlir::ConversionPatternRewriter &rewriter)
const {
1300 auto resTy = getTypeConverter()->convertType(op.getType());
1301 auto ctz = mlir::LLVM::CountTrailingZerosOp::create(rewriter, op.getLoc(),
1302 resTy, adaptor.getInput(),
1305 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1306 auto ctzAddOne = mlir::LLVM::AddOp::create(rewriter, op.getLoc(),
ctz, one);
1308 auto zeroInputTy = mlir::LLVM::ConstantOp::create(
1309 rewriter, op.getLoc(), adaptor.getInput().getType(), 0);
1310 auto isZero = mlir::LLVM::ICmpOp::create(
1311 rewriter, op.getLoc(),
1312 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(),
1313 mlir::LLVM::ICmpPredicate::eq),
1314 adaptor.getInput(), zeroInputTy);
1316 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 0);
1317 auto res = mlir::LLVM::SelectOp::create(rewriter, op.getLoc(), isZero, zero,
1319 rewriter.replaceOp(op, res);
1321 return mlir::LogicalResult::success();
1324mlir::LogicalResult CIRToLLVMBitParityOpLowering::matchAndRewrite(
1325 cir::BitParityOp op, OpAdaptor adaptor,
1326 mlir::ConversionPatternRewriter &rewriter)
const {
1327 auto resTy = getTypeConverter()->convertType(op.getType());
1328 auto popcnt = mlir::LLVM::CtPopOp::create(rewriter, op.getLoc(), resTy,
1329 adaptor.getInput());
1331 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1333 mlir::LLVM::AndOp::create(rewriter, op.getLoc(), popcnt, one);
1334 rewriter.replaceOp(op, popcntMod2);
1336 return mlir::LogicalResult::success();
1339mlir::LogicalResult CIRToLLVMBitPopcountOpLowering::matchAndRewrite(
1340 cir::BitPopcountOp op, OpAdaptor adaptor,
1341 mlir::ConversionPatternRewriter &rewriter)
const {
1342 auto resTy = getTypeConverter()->convertType(op.getType());
1343 auto llvmOp = mlir::LLVM::CtPopOp::create(rewriter, op.getLoc(), resTy,
1344 adaptor.getInput());
1345 rewriter.replaceOp(op, llvmOp);
1346 return mlir::LogicalResult::success();
1349mlir::LogicalResult CIRToLLVMBrCondOpLowering::matchAndRewrite(
1350 cir::BrCondOp brOp, OpAdaptor adaptor,
1351 mlir::ConversionPatternRewriter &rewriter)
const {
1356 mlir::Value i1Condition = adaptor.getCond();
1358 rewriter.replaceOpWithNewOp<mlir::LLVM::CondBrOp>(
1359 brOp, i1Condition, brOp.getDestTrue(), adaptor.getDestOperandsTrue(),
1360 brOp.getDestFalse(), adaptor.getDestOperandsFalse());
1362 return mlir::success();
1365mlir::Type CIRToLLVMCastOpLowering::convertTy(mlir::Type ty)
const {
1366 return getTypeConverter()->convertType(ty);
1369mlir::LogicalResult CIRToLLVMCastOpLowering::matchAndRewrite(
1370 cir::CastOp castOp, OpAdaptor adaptor,
1371 mlir::ConversionPatternRewriter &rewriter)
const {
1376 switch (castOp.getKind()) {
1377 case cir::CastKind::array_to_ptrdecay: {
1378 const auto ptrTy = mlir::cast<cir::PointerType>(castOp.getType());
1379 mlir::Value sourceValue = adaptor.getSrc();
1380 mlir::Type targetType = convertTy(ptrTy);
1382 ptrTy.getPointee());
1383 llvm::SmallVector<mlir::LLVM::GEPArg> offset{0};
1384 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1385 castOp, targetType, elementTy, sourceValue, offset);
1388 case cir::CastKind::int_to_bool: {
1389 mlir::Value llvmSrcVal = adaptor.getSrc();
1393 mlir::Value zeroInt = mlir::LLVM::ConstantOp::create(
1394 rewriter, castOp.getLoc(), llvmSrcVal.getType(),
1395 rewriter.getZeroAttr(llvmSrcVal.getType()));
1396 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
1397 castOp, mlir::LLVM::ICmpPredicate::ne, llvmSrcVal, zeroInt);
1400 case cir::CastKind::integral: {
1401 mlir::Type srcType = castOp.getSrc().getType();
1402 mlir::Type dstType = castOp.getType();
1403 mlir::Value llvmSrcVal = adaptor.getSrc();
1404 mlir::Type llvmDstType = getTypeConverter()->convertType(dstType);
1405 cir::IntType srcIntType =
1406 mlir::cast<cir::IntType>(elementTypeIfVector(srcType));
1407 cir::IntType dstIntType =
1408 mlir::cast<cir::IntType>(elementTypeIfVector(dstType));
1409 rewriter.replaceOp(castOp,
getLLVMIntCast(rewriter, llvmSrcVal, llvmDstType,
1410 srcIntType.isUnsigned(),
1411 srcIntType.getWidth(),
1412 dstIntType.getWidth()));
1415 case cir::CastKind::floating: {
1416 mlir::Value llvmSrcVal = adaptor.getSrc();
1417 mlir::Type llvmDstTy = getTypeConverter()->convertType(castOp.getType());
1419 mlir::Type srcTy = elementTypeIfVector(castOp.getSrc().getType());
1420 mlir::Type dstTy = elementTypeIfVector(castOp.getType());
1422 if (!mlir::isa<cir::FPTypeInterface>(dstTy) ||
1423 !mlir::isa<cir::FPTypeInterface>(srcTy))
1424 return castOp.emitError() <<
"NYI cast from " << srcTy <<
" to " << dstTy;
1426 auto getFloatWidth = [](mlir::Type ty) ->
unsigned {
1427 return mlir::cast<cir::FPTypeInterface>(ty).getWidth();
1430 if (getFloatWidth(srcTy) > getFloatWidth(dstTy))
1431 rewriter.replaceOpWithNewOp<mlir::LLVM::FPTruncOp>(castOp, llvmDstTy,
1434 rewriter.replaceOpWithNewOp<mlir::LLVM::FPExtOp>(castOp, llvmDstTy,
1436 return mlir::success();
1438 case cir::CastKind::int_to_ptr: {
1439 auto dstTy = mlir::cast<cir::PointerType>(castOp.getType());
1440 mlir::Value llvmSrcVal = adaptor.getSrc();
1441 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1442 rewriter.replaceOpWithNewOp<mlir::LLVM::IntToPtrOp>(castOp, llvmDstTy,
1444 return mlir::success();
1446 case cir::CastKind::ptr_to_int: {
1447 auto dstTy = mlir::cast<cir::IntType>(castOp.getType());
1448 mlir::Value llvmSrcVal = adaptor.getSrc();
1449 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1450 rewriter.replaceOpWithNewOp<mlir::LLVM::PtrToIntOp>(castOp, llvmDstTy,
1452 return mlir::success();
1454 case cir::CastKind::float_to_bool: {
1455 mlir::Value llvmSrcVal = adaptor.getSrc();
1456 auto kind = mlir::LLVM::FCmpPredicate::une;
1461 auto zeroFloat = mlir::LLVM::ConstantOp::create(
1462 rewriter, castOp.getLoc(), llvmSrcVal.getType(),
1463 rewriter.getZeroAttr(llvmSrcVal.getType()));
1466 rewriter.replaceOpWithNewOp<mlir::LLVM::FCmpOp>(castOp,
kind, llvmSrcVal,
1469 return mlir::success();
1471 case cir::CastKind::bool_to_int: {
1472 mlir::Type dstTy = castOp.getType();
1473 mlir::Value llvmSrcVal = adaptor.getSrc();
1474 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1476 auto srcElemTy = mlir::cast<mlir::IntegerType>(
1477 elementTypeIfVector(llvmSrcVal.getType()));
1478 auto dstElemTy = mlir::cast<cir::IntType>(elementTypeIfVector(dstTy));
1480 if (srcElemTy.getWidth() == dstElemTy.getWidth())
1481 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(castOp, llvmDstTy,
1484 rewriter.replaceOpWithNewOp<mlir::LLVM::ZExtOp>(castOp, llvmDstTy,
1486 return mlir::success();
1488 case cir::CastKind::bool_to_float: {
1489 mlir::Type dstTy = castOp.getType();
1490 mlir::Value llvmSrcVal = adaptor.getSrc();
1491 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1492 rewriter.replaceOpWithNewOp<mlir::LLVM::UIToFPOp>(castOp, llvmDstTy,
1494 return mlir::success();
1496 case cir::CastKind::int_to_float: {
1497 mlir::Type dstTy = castOp.getType();
1498 mlir::Value llvmSrcVal = adaptor.getSrc();
1499 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1500 if (mlir::cast<cir::IntType>(elementTypeIfVector(castOp.getSrc().getType()))
1502 rewriter.replaceOpWithNewOp<mlir::LLVM::SIToFPOp>(castOp, llvmDstTy,
1505 rewriter.replaceOpWithNewOp<mlir::LLVM::UIToFPOp>(castOp, llvmDstTy,
1507 return mlir::success();
1509 case cir::CastKind::float_to_int: {
1510 mlir::Type dstTy = castOp.getType();
1511 mlir::Value llvmSrcVal = adaptor.getSrc();
1512 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1513 if (mlir::cast<cir::IntType>(elementTypeIfVector(castOp.getType()))
1515 rewriter.replaceOpWithNewOp<mlir::LLVM::FPToSIOp>(castOp, llvmDstTy,
1518 rewriter.replaceOpWithNewOp<mlir::LLVM::FPToUIOp>(castOp, llvmDstTy,
1520 return mlir::success();
1522 case cir::CastKind::bitcast: {
1523 mlir::Type dstTy = castOp.getType();
1524 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1529 mlir::Value llvmSrcVal = adaptor.getSrc();
1530 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(castOp, llvmDstTy,
1532 return mlir::success();
1534 case cir::CastKind::ptr_to_bool: {
1535 mlir::Value llvmSrcVal = adaptor.getSrc();
1536 mlir::Value zeroPtr = mlir::LLVM::ZeroOp::create(rewriter, castOp.getLoc(),
1537 llvmSrcVal.getType());
1538 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
1539 castOp, mlir::LLVM::ICmpPredicate::ne, llvmSrcVal, zeroPtr);
1542 case cir::CastKind::address_space: {
1543 mlir::Type dstTy = castOp.getType();
1544 mlir::Value llvmSrcVal = adaptor.getSrc();
1545 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1546 rewriter.replaceOpWithNewOp<mlir::LLVM::AddrSpaceCastOp>(castOp, llvmDstTy,
1550 case cir::CastKind::member_ptr_to_bool:
1555 return castOp.emitError(
"Unhandled cast kind: ")
1556 << castOp.getKindAttrName();
1560 return mlir::success();
1563mlir::LogicalResult CIRToLLVMBuiltinIntCastOpLowering::matchAndRewrite(
1564 cir::BuiltinIntCastOp op, OpAdaptor adaptor,
1565 mlir::ConversionPatternRewriter &rewriter)
const {
1570 if (
auto cirSrc = mlir::dyn_cast<cir::IntType>(op.getSrc().getType()))
1572 else if (
auto cirDst = mlir::dyn_cast<cir::IntType>(op.getType()))
1575 mlir::Value llvmSrc = adaptor.getSrc();
1576 mlir::Type llvmDstTy = getTypeConverter()->convertType(op.getType());
1577 auto srcIntTy = mlir::cast<mlir::IntegerType>(llvmSrc.getType());
1578 auto dstIntTy = mlir::cast<mlir::IntegerType>(llvmDstTy);
1579 unsigned srcWidth = srcIntTy.getWidth();
1580 unsigned dstWidth = dstIntTy.getWidth();
1585 assert((srcWidth == dstWidth ||
1586 mlir::isa<mlir::IndexType>(op.getSrc().getType()) ||
1587 mlir::isa<mlir::IndexType>(op.getType())) &&
1588 "only index casts may change width during lowering");
1593 srcWidth, dstWidth));
1594 return mlir::success();
1598 mlir::ModuleOp mod, mlir::Value index,
1599 mlir::Type baseTy, cir::IntType strideTy) {
1600 mlir::Operation *indexOp = index.getDefiningOp();
1604 auto indexType = mlir::cast<mlir::IntegerType>(index.getType());
1605 mlir::DataLayout llvmLayout(mod);
1606 std::optional<uint64_t> layoutWidth = llvmLayout.getTypeIndexBitwidth(baseTy);
1609 if (!layoutWidth || *layoutWidth == indexType.getWidth())
1615 auto sub = dyn_cast<mlir::LLVM::SubOp>(indexOp);
1616 bool rewriteSub =
false;
1619 dyn_cast<mlir::LLVM::ConstantOp>(sub.getLhs().getDefiningOp())) {
1620 auto lhsConstInt = mlir::dyn_cast<mlir::IntegerAttr>(lhsConst.getValue());
1621 if (lhsConstInt && lhsConstInt.getValue() == 0) {
1622 index = sub.getRhs();
1628 auto llvmDstType = rewriter.getIntegerType(*layoutWidth);
1629 bool isUnsigned = strideTy && strideTy.isUnsigned();
1631 indexType.getWidth(), *layoutWidth);
1634 index = mlir::LLVM::SubOp::create(
1635 rewriter, index.getLoc(),
1636 mlir::LLVM::ConstantOp::create(rewriter, index.getLoc(),
1637 index.getType(), 0),
1640 rewriter.eraseOp(sub);
1646mlir::LogicalResult CIRToLLVMPtrStrideOpLowering::matchAndRewrite(
1647 cir::PtrStrideOp ptrStrideOp, OpAdaptor adaptor,
1648 mlir::ConversionPatternRewriter &rewriter)
const {
1650 const mlir::TypeConverter *tc = getTypeConverter();
1651 const mlir::Type resultTy = tc->convertType(ptrStrideOp.getType());
1653 mlir::Type elementTy =
1658 if (mlir::isa<mlir::LLVM::LLVMVoidType>(elementTy) ||
1659 mlir::isa<mlir::LLVM::LLVMFunctionType>(elementTy))
1660 elementTy = mlir::IntegerType::get(elementTy.getContext(), 8,
1661 mlir::IntegerType::Signless);
1663 mlir::Value index = adaptor.getStride();
1665 rewriter, ptrStrideOp->getParentOfType<mlir::ModuleOp>(), index,
1666 adaptor.getBase().getType(),
1667 dyn_cast<cir::IntType>(ptrStrideOp.getOperand(1).getType()));
1669 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1670 ptrStrideOp, resultTy, elementTy, adaptor.getBase(), index);
1671 return mlir::success();
1674mlir::LogicalResult CIRToLLVMGetElementOpLowering::matchAndRewrite(
1675 cir::GetElementOp op, OpAdaptor adaptor,
1676 mlir::ConversionPatternRewriter &rewriter)
const {
1678 mlir::dyn_cast<cir::ArrayType>(op.getBaseType().getPointee())) {
1679 const mlir::TypeConverter *converter = getTypeConverter();
1680 const mlir::Type llArrayTy = converter->convertType(arrayTy);
1681 const mlir::Type llResultTy = converter->convertType(op.getType());
1682 mlir::Type elementTy =
1687 if (mlir::isa<mlir::LLVM::LLVMVoidType>(elementTy) ||
1688 mlir::isa<mlir::LLVM::LLVMFunctionType>(elementTy))
1689 elementTy = rewriter.getIntegerType(8);
1691 mlir::Value index = adaptor.getIndex();
1694 adaptor.getBase().getType(),
1695 dyn_cast<cir::IntType>(op.getOperand(1).getType()));
1700 std::array<mlir::LLVM::GEPArg, 2> offset{0, index};
1701 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, llResultTy, llArrayTy,
1702 adaptor.getBase(), offset);
1703 return mlir::success();
1706 op.emitError() <<
"NYI: GetElementOp lowering to LLVM for non-array";
1707 return mlir::failure();
1710mlir::LogicalResult CIRToLLVMBaseClassAddrOpLowering::matchAndRewrite(
1711 cir::BaseClassAddrOp baseClassOp, OpAdaptor adaptor,
1712 mlir::ConversionPatternRewriter &rewriter)
const {
1713 const mlir::Type resultType =
1714 getTypeConverter()->convertType(baseClassOp.getType());
1715 mlir::Value derivedAddr = adaptor.getDerivedAddr();
1716 llvm::SmallVector<mlir::LLVM::GEPArg, 1> offset = {
1717 adaptor.getOffset().getZExtValue()};
1718 mlir::Type byteType = mlir::IntegerType::get(resultType.getContext(), 8,
1719 mlir::IntegerType::Signless);
1720 if (adaptor.getOffset().getZExtValue() == 0) {
1721 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(
1722 baseClassOp, resultType, adaptor.getDerivedAddr());
1723 return mlir::success();
1726 if (baseClassOp.getAssumeNotNull()) {
1727 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1728 baseClassOp, resultType, byteType, derivedAddr, offset);
1730 auto loc = baseClassOp.getLoc();
1731 mlir::Value isNull = mlir::LLVM::ICmpOp::create(
1732 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, derivedAddr,
1733 mlir::LLVM::ZeroOp::create(rewriter, loc, derivedAddr.getType()));
1734 mlir::Value adjusted = mlir::LLVM::GEPOp::create(
1735 rewriter, loc, resultType, byteType, derivedAddr, offset);
1736 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(baseClassOp, isNull,
1737 derivedAddr, adjusted);
1739 return mlir::success();
1742mlir::LogicalResult CIRToLLVMDerivedClassAddrOpLowering::matchAndRewrite(
1743 cir::DerivedClassAddrOp derivedClassOp, OpAdaptor adaptor,
1744 mlir::ConversionPatternRewriter &rewriter)
const {
1745 const mlir::Type resultType =
1746 getTypeConverter()->convertType(derivedClassOp.getType());
1747 mlir::Value baseAddr = adaptor.getBaseAddr();
1750 int64_t offsetVal = -(adaptor.getOffset().getZExtValue());
1751 if (offsetVal == 0) {
1753 rewriter.replaceOp(derivedClassOp, baseAddr);
1754 return mlir::success();
1756 llvm::SmallVector<mlir::LLVM::GEPArg, 1> offset = {offsetVal};
1757 mlir::Type byteType = mlir::IntegerType::get(resultType.getContext(), 8,
1758 mlir::IntegerType::Signless);
1759 if (derivedClassOp.getAssumeNotNull()) {
1760 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1761 derivedClassOp, resultType, byteType, baseAddr, offset,
1762 mlir::LLVM::GEPNoWrapFlags::inbounds);
1764 mlir::Location loc = derivedClassOp.getLoc();
1765 mlir::Value isNull = mlir::LLVM::ICmpOp::create(
1766 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, baseAddr,
1767 mlir::LLVM::ZeroOp::create(rewriter, loc, baseAddr.getType()));
1768 mlir::Value adjusted =
1769 mlir::LLVM::GEPOp::create(rewriter, loc, resultType, byteType, baseAddr,
1770 offset, mlir::LLVM::GEPNoWrapFlags::inbounds);
1771 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(derivedClassOp, isNull,
1772 baseAddr, adjusted);
1774 return mlir::success();
1777mlir::LogicalResult CIRToLLVMFMaxNumOpLowering::matchAndRewrite(
1778 cir::FMaxNumOp op, OpAdaptor adaptor,
1779 mlir::ConversionPatternRewriter &rewriter)
const {
1780 mlir::Type resTy = typeConverter->convertType(op.getType());
1781 rewriter.replaceOpWithNewOp<mlir::LLVM::MaxNumOp>(
1782 op, resTy, adaptor.getLhs(), adaptor.getRhs(),
1783 mlir::LLVM::FastmathFlags::nsz);
1784 return mlir::success();
1787mlir::LogicalResult CIRToLLVMFMinNumOpLowering::matchAndRewrite(
1788 cir::FMinNumOp op, OpAdaptor adaptor,
1789 mlir::ConversionPatternRewriter &rewriter)
const {
1790 mlir::Type resTy = typeConverter->convertType(op.getType());
1791 rewriter.replaceOpWithNewOp<mlir::LLVM::MinNumOp>(
1792 op, resTy, adaptor.getLhs(), adaptor.getRhs(),
1793 mlir::LLVM::FastmathFlags::nsz);
1794 return mlir::success();
1797mlir::LogicalResult CIRToLLVMAllocaOpLowering::matchAndRewrite(
1798 cir::AllocaOp op, OpAdaptor adaptor,
1799 mlir::ConversionPatternRewriter &rewriter)
const {
1802 ? adaptor.getDynAllocSize()
1803 : mlir::LLVM::ConstantOp::create(
1804 rewriter, op.getLoc(),
1805 typeConverter->convertType(rewriter.getIndexType()), 1);
1806 mlir::Type elementTy =
1808 mlir::Type resultTy =
1814 rewriter.replaceOpWithNewOp<mlir::LLVM::AllocaOp>(op, resultTy, elementTy,
1815 size, op.getAlignment());
1817 return mlir::success();
1820mlir::LogicalResult CIRToLLVMRotateOpLowering::matchAndRewrite(
1821 cir::RotateOp op, OpAdaptor adaptor,
1822 mlir::ConversionPatternRewriter &rewriter)
const {
1825 mlir::Value input = adaptor.getInput();
1826 if (op.isRotateLeft())
1827 rewriter.replaceOpWithNewOp<mlir::LLVM::FshlOp>(op, input, input,
1828 adaptor.getAmount());
1830 rewriter.replaceOpWithNewOp<mlir::LLVM::FshrOp>(op, input, input,
1831 adaptor.getAmount());
1832 return mlir::LogicalResult::success();
1837 for (mlir::NamedAttribute attr : op->getAttrs()) {
1838 if (attr.getName() == CIRDialect::getCalleeAttrName() ||
1839 attr.getName() == CIRDialect::getSideEffectAttrName() ||
1840 attr.getName() == CIRDialect::getNoThrowAttrName() ||
1841 attr.getName() == CIRDialect::getNoUnwindAttrName() ||
1842 attr.getName() == CIRDialect::getNoReturnAttrName() ||
1843 attr.getName() == CIRDialect::getMustTailAttrName())
1847 result.push_back(attr);
1851static mlir::LogicalResult
1853 mlir::ConversionPatternRewriter &rewriter,
1854 const mlir::TypeConverter *converter,
1855 mlir::SymbolTableCollection &symbolTables,
1856 mlir::FlatSymbolRefAttr calleeAttr,
1857 mlir::Block *continueBlock =
nullptr,
1858 mlir::Block *landingPadBlock =
nullptr) {
1860 mlir::ValueTypeRange<mlir::ResultRange> cirResults = op->getResultTypes();
1861 auto call = cast<cir::CIRCallOpInterface>(op);
1863 if (converter->convertTypes(cirResults, llvmResults).failed())
1864 return mlir::failure();
1868 mlir::LLVM::MemoryEffectsAttr memoryEffects;
1869 bool noUnwind =
false;
1870 bool willReturn =
false;
1871 bool noReturn =
false;
1873 memoryEffects, noUnwind, willReturn, noReturn);
1878 mlir::LLVM::LLVMFunctionType llvmFnTy;
1885 mlir::Operation *callee =
1886 symbolTables.lookupNearestSymbolFrom(op, calleeAttr);
1887 if (
auto fn = mlir::dyn_cast<mlir::FunctionOpInterface>(callee)) {
1888 llvmFnTy = converter->convertType<mlir::LLVM::LLVMFunctionType>(
1889 fn.getFunctionType());
1890 assert(llvmFnTy &&
"Failed to convert function type");
1891 }
else if (
auto alias = mlir::cast<mlir::LLVM::AliasOp>(callee)) {
1899 auto symAttr = mlir::cast<mlir::FlatSymbolRefAttr>(calleeAttr);
1901 mlir::LLVM::AddressOfOp::create(
1902 rewriter, op->getLoc(),
1903 mlir::LLVM::LLVMPointerType::get(rewriter.getContext()), symAttr)
1905 adjustedCallOperands.push_back(addrOfAlias);
1908 llvm::append_range(adjustedCallOperands, callOperands);
1909 callOperands = adjustedCallOperands;
1913 llvmFnTy = mlir::cast<mlir::LLVM::LLVMFunctionType>(alias.getType());
1916 return op->emitError(
"Unexpected callee type!");
1919 assert(!op->getOperands().empty() &&
1920 "operands list must no be empty for the indirect call");
1921 auto calleeTy = op->getOperands().front().getType();
1922 auto calleePtrTy = cast<cir::PointerType>(calleeTy);
1923 auto calleeFuncTy = cast<cir::FuncType>(calleePtrTy.getPointee());
1924 llvm::append_range(adjustedCallOperands, callOperands);
1925 llvmFnTy = cast<mlir::LLVM::LLVMFunctionType>(
1926 converter->convertType(calleeFuncTy));
1931 if (landingPadBlock) {
1932 auto newOp = rewriter.replaceOpWithNewOp<mlir::LLVM::InvokeOp>(
1933 op, llvmFnTy, calleeAttr, callOperands, continueBlock,
1934 mlir::ValueRange{}, landingPadBlock, mlir::ValueRange{});
1935 newOp->setAttrs(attributes);
1937 auto newOp = rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(
1938 op, llvmFnTy, calleeAttr, callOperands);
1939 newOp->setAttrs(attributes);
1941 newOp.setMemoryEffectsAttr(memoryEffects);
1942 newOp.setNoUnwind(noUnwind);
1943 newOp.setWillReturn(willReturn);
1944 newOp.setNoreturn(noReturn);
1945 if (op->hasAttr(CIRDialect::getMustTailAttrName()))
1946 newOp.setTailCallKind(mlir::LLVM::TailCallKind::MustTail);
1949 return mlir::success();
1952mlir::LogicalResult CIRToLLVMCallOpLowering::matchAndRewrite(
1953 cir::CallOp op, OpAdaptor adaptor,
1954 mlir::ConversionPatternRewriter &rewriter)
const {
1956 getTypeConverter(), symbolTables,
1957 op.getCalleeAttr());
1960mlir::LogicalResult CIRToLLVMTryCallOpLowering::matchAndRewrite(
1961 cir::TryCallOp op, OpAdaptor adaptor,
1962 mlir::ConversionPatternRewriter &rewriter)
const {
1965 op.getOperation(), adaptor.getOperands(), rewriter, getTypeConverter(),
1966 symbolTables, op.getCalleeAttr(), op.getNormalDest(), op.getUnwindDest());
1969mlir::LogicalResult CIRToLLVMReturnAddrOpLowering::matchAndRewrite(
1970 cir::ReturnAddrOp op, OpAdaptor adaptor,
1971 mlir::ConversionPatternRewriter &rewriter)
const {
1972 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
1974 llvmPtrTy, adaptor.getOperands());
1975 return mlir::success();
1978mlir::LogicalResult CIRToLLVMFrameAddrOpLowering::matchAndRewrite(
1979 cir::FrameAddrOp op, OpAdaptor adaptor,
1980 mlir::ConversionPatternRewriter &rewriter)
const {
1981 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
1983 adaptor.getOperands());
1984 return mlir::success();
1987mlir::LogicalResult CIRToLLVMClearCacheOpLowering::matchAndRewrite(
1988 cir::ClearCacheOp op, OpAdaptor adaptor,
1989 mlir::ConversionPatternRewriter &rewriter)
const {
1990 mlir::Value begin = adaptor.getBegin();
1991 mlir::Value end = adaptor.getEnd();
1992 auto intrinNameAttr =
1993 mlir::StringAttr::get(op.getContext(),
"llvm.clear_cache");
1994 rewriter.replaceOpWithNewOp<mlir::LLVM::CallIntrinsicOp>(
1995 op, mlir::Type{}, intrinNameAttr, mlir::ValueRange{begin, end});
1997 return mlir::success();
2000mlir::LogicalResult CIRToLLVMAddrOfReturnAddrOpLowering::matchAndRewrite(
2001 cir::AddrOfReturnAddrOp op, OpAdaptor adaptor,
2002 mlir::ConversionPatternRewriter &rewriter)
const {
2003 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
2005 llvmPtrTy, adaptor.getOperands());
2006 return mlir::success();
2009mlir::LogicalResult CIRToLLVMLoadOpLowering::matchAndRewrite(
2010 cir::LoadOp op, OpAdaptor adaptor,
2011 mlir::ConversionPatternRewriter &rewriter)
const {
2012 const mlir::Type llvmTy =
2014 mlir::LLVM::AtomicOrdering ordering =
getLLVMMemOrder(op.getMemOrder());
2015 std::optional<size_t> opAlign = op.getAlignment();
2016 unsigned alignment =
2017 (unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmTy));
2021 std::optional<llvm::StringRef> llvmSyncScope =
2024 mlir::LLVM::LoadOp newLoad = mlir::LLVM::LoadOp::create(
2025 rewriter, op->getLoc(), llvmTy, adaptor.getAddr(), alignment,
2026 op.getIsVolatile(), op.getIsNontemporal(),
2027 op.getInvariant(),
false, ordering,
2028 llvmSyncScope.value_or(std::string()));
2031 mlir::Value result =
2033 rewriter.replaceOp(op, result);
2035 return mlir::LogicalResult::success();
2039cir::direct::CIRToLLVMVecMaskedLoadOpLowering::matchAndRewrite(
2040 cir::VecMaskedLoadOp op, OpAdaptor adaptor,
2041 mlir::ConversionPatternRewriter &rewriter)
const {
2042 const mlir::Type llvmResTy =
2045 std::optional<size_t> opAlign = op.getAlignment();
2046 unsigned alignment =
2047 (unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmResTy));
2049 mlir::IntegerAttr alignAttr = rewriter.getI32IntegerAttr(alignment);
2051 auto newLoad = mlir::LLVM::MaskedLoadOp::create(
2052 rewriter, op.getLoc(), llvmResTy, adaptor.getAddr(), adaptor.getMask(),
2053 adaptor.getPassThru(), alignAttr);
2055 rewriter.replaceOp(op, newLoad.getResult());
2056 return mlir::success();
2059mlir::LogicalResult CIRToLLVMStoreOpLowering::matchAndRewrite(
2060 cir::StoreOp op, OpAdaptor adaptor,
2061 mlir::ConversionPatternRewriter &rewriter)
const {
2062 mlir::LLVM::AtomicOrdering memorder =
getLLVMMemOrder(op.getMemOrder());
2063 const mlir::Type llvmTy =
2064 getTypeConverter()->convertType(op.getValue().getType());
2065 std::optional<size_t> opAlign = op.getAlignment();
2066 unsigned alignment =
2067 (unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmTy));
2073 op.getValue().getType(), adaptor.getValue());
2076 std::optional<llvm::StringRef> llvmSyncScope =
2079 mlir::LLVM::StoreOp storeOp = mlir::LLVM::StoreOp::create(
2080 rewriter, op->getLoc(), value, adaptor.getAddr(), alignment,
2082 op.getIsNontemporal(),
false,
2083 memorder, llvmSyncScope.value_or(std::string()));
2084 rewriter.replaceOp(op, storeOp);
2086 return mlir::LogicalResult::success();
2090 while (
auto arrTy = mlir::dyn_cast<cir::ArrayType>(ty))
2091 ty = arrTy.getElementType();
2096 return mlir::isa<cir::PointerType, cir::IntType, cir::BoolType,
2097 cir::FPTypeInterface>(baseElemTy);
2100mlir::LogicalResult CIRToLLVMConstantOpLowering::matchAndRewrite(
2101 cir::ConstantOp op, OpAdaptor adaptor,
2102 mlir::ConversionPatternRewriter &rewriter)
const {
2103 mlir::Attribute attr = op.getValue();
2105 if (mlir::isa<cir::PoisonAttr>(attr)) {
2106 rewriter.replaceOpWithNewOp<mlir::LLVM::PoisonOp>(
2107 op, getTypeConverter()->convertType(op.getType()));
2108 return mlir::success();
2111 if (mlir::isa<cir::UndefAttr>(attr)) {
2112 rewriter.replaceOpWithNewOp<mlir::LLVM::UndefOp>(
2113 op, getTypeConverter()->convertType(op.getType()));
2114 return mlir::success();
2117 if (mlir::isa<mlir::IntegerType>(op.getType())) {
2122 attr = op.getValue();
2123 }
else if (mlir::isa<cir::BoolType>(op.getType())) {
2124 int value = mlir::cast<cir::BoolAttr>(op.getValue()).getValue();
2125 attr = rewriter.getIntegerAttr(typeConverter->convertType(op.getType()),
2127 }
else if (mlir::isa<cir::IntType>(op.getType())) {
2129 if (
auto ga = mlir::dyn_cast<cir::GlobalViewAttr>(op.getValue())) {
2135 op.emitError() <<
"global view with integer type";
2136 return mlir::failure();
2139 attr = rewriter.getIntegerAttr(
2140 typeConverter->convertType(op.getType()),
2141 mlir::cast<cir::IntAttr>(op.getValue()).getValue());
2142 }
else if (mlir::isa<cir::FPTypeInterface>(op.getType())) {
2143 attr = rewriter.getFloatAttr(
2144 typeConverter->convertType(op.getType()),
2145 mlir::cast<cir::FPAttr>(op.getValue()).getValue());
2146 }
else if (mlir::isa<cir::PointerType>(op.getType())) {
2148 if (mlir::isa<cir::ConstPtrAttr>(op.getValue())) {
2149 if (mlir::cast<cir::ConstPtrAttr>(op.getValue()).isNullValue()) {
2150 rewriter.replaceOpWithNewOp<mlir::LLVM::ZeroOp>(
2151 op, typeConverter->convertType(op.getType()));
2152 return mlir::success();
2156 if (
auto gv = mlir::dyn_cast<cir::GlobalViewAttr>(op.getValue())) {
2158 rewriter.replaceOp(op, newOp);
2159 return mlir::success();
2161 attr = op.getValue();
2162 }
else if (
const auto arrTy = mlir::dyn_cast<cir::ArrayType>(op.getType())) {
2163 const auto constArr = mlir::dyn_cast<cir::ConstArrayAttr>(op.getValue());
2164 if (!constArr && !isa<cir::ZeroAttr, cir::UndefAttr>(op.getValue()))
2165 return op.emitError() <<
"array does not have a constant initializer";
2167 std::optional<mlir::Attribute> denseAttr;
2170 attr = denseAttr.value();
2172 const mlir::Value initVal =
2174 rewriter.replaceOp(op, initVal);
2175 return mlir::success();
2177 }
else if (
const auto recordAttr =
2178 mlir::dyn_cast<cir::ConstRecordAttr>(op.getValue())) {
2180 rewriter.replaceOp(op, initVal);
2181 return mlir::success();
2182 }
else if (
const auto vecTy = mlir::dyn_cast<cir::VectorType>(op.getType())) {
2184 getTypeConverter()));
2185 return mlir::success();
2186 }
else if (mlir::isa<cir::RecordType>(op.getType())) {
2187 if (mlir::isa<cir::ZeroAttr, cir::UndefAttr>(attr)) {
2188 mlir::Value initVal =
2190 rewriter.replaceOp(op, initVal);
2191 return mlir::success();
2193 return op.emitError() <<
"unsupported lowering for record constant type "
2195 }
else if (
auto complexTy = mlir::dyn_cast<cir::ComplexType>(op.getType())) {
2196 mlir::Type complexElemTy = complexTy.getElementType();
2197 mlir::Type complexElemLLVMTy = typeConverter->convertType(complexElemTy);
2199 if (
auto zeroInitAttr = mlir::dyn_cast<cir::ZeroAttr>(op.getValue())) {
2200 mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(complexElemLLVMTy);
2201 mlir::ArrayAttr array = rewriter.getArrayAttr({zeroAttr, zeroAttr});
2202 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
2203 op, getTypeConverter()->convertType(op.getType()), array);
2204 return mlir::success();
2207 if (mlir::isa<cir::UndefAttr>(op.getValue())) {
2208 rewriter.replaceOpWithNewOp<mlir::LLVM::UndefOp>(
2209 op, getTypeConverter()->convertType(op.getType()));
2210 return mlir::success();
2213 auto complexAttr = mlir::cast<cir::ConstComplexAttr>(op.getValue());
2215 mlir::Attribute components[2];
2216 if (mlir::isa<cir::IntType>(complexElemTy)) {
2217 components[0] = rewriter.getIntegerAttr(
2219 mlir::cast<cir::IntAttr>(complexAttr.getReal()).getValue());
2220 components[1] = rewriter.getIntegerAttr(
2222 mlir::cast<cir::IntAttr>(complexAttr.getImag()).getValue());
2224 components[0] = rewriter.getFloatAttr(
2226 mlir::cast<cir::FPAttr>(complexAttr.getReal()).getValue());
2227 components[1] = rewriter.getFloatAttr(
2229 mlir::cast<cir::FPAttr>(complexAttr.getImag()).getValue());
2232 attr = rewriter.getArrayAttr(components);
2234 return op.emitError() <<
"unsupported constant type " << op.getType();
2237 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
2238 op, getTypeConverter()->convertType(op.getType()),
attr);
2240 return mlir::success();
2244 mlir::DataLayout layout(op.getParentOfType<mlir::ModuleOp>());
2246 if (isa<cir::VoidType>(type))
2247 type = cir::IntType::get(type.getContext(), 8,
false);
2248 return llvm::divideCeil(layout.getTypeSizeInBits(type), 8);
2251mlir::LogicalResult CIRToLLVMPrefetchOpLowering::matchAndRewrite(
2252 cir::PrefetchOp op, OpAdaptor adaptor,
2253 mlir::ConversionPatternRewriter &rewriter)
const {
2254 rewriter.replaceOpWithNewOp<mlir::LLVM::Prefetch>(
2255 op, adaptor.getAddr(), adaptor.getIsWrite(), adaptor.getLocality(),
2257 return mlir::success();
2260mlir::LogicalResult CIRToLLVMPtrDiffOpLowering::matchAndRewrite(
2261 cir::PtrDiffOp op, OpAdaptor adaptor,
2262 mlir::ConversionPatternRewriter &rewriter)
const {
2263 auto dstTy = mlir::cast<cir::IntType>(op.getType());
2264 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
2266 auto lhs = mlir::LLVM::PtrToIntOp::create(rewriter, op.getLoc(), llvmDstTy,
2268 auto rhs = mlir::LLVM::PtrToIntOp::create(rewriter, op.getLoc(), llvmDstTy,
2272 mlir::LLVM::SubOp::create(rewriter, op.getLoc(), llvmDstTy, lhs, rhs);
2274 cir::PointerType ptrTy = op.getLhs().getType();
2276 uint64_t typeSize =
getTypeSize(ptrTy.getPointee(), *op);
2279 mlir::Value resultVal = diff.getResult();
2280 if (typeSize != 1) {
2281 auto typeSizeVal = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
2282 llvmDstTy, typeSize);
2284 if (dstTy.isUnsigned()) {
2286 mlir::LLVM::UDivOp::create(rewriter, op.getLoc(), diff, typeSizeVal);
2287 uDiv.setIsExact(
true);
2288 resultVal = uDiv.getResult();
2291 mlir::LLVM::SDivOp::create(rewriter, op.getLoc(), diff, typeSizeVal);
2292 sDiv.setIsExact(
true);
2293 resultVal = sDiv.getResult();
2296 rewriter.replaceOp(op, resultVal);
2297 return mlir::success();
2300mlir::LogicalResult CIRToLLVMExpectOpLowering::matchAndRewrite(
2301 cir::ExpectOp op, OpAdaptor adaptor,
2302 mlir::ConversionPatternRewriter &rewriter)
const {
2306 std::optional<llvm::APFloat> prob = op.getProb();
2308 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpectWithProbabilityOp>(
2309 op, adaptor.getVal(), adaptor.getExpected(), prob.value());
2311 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpectOp>(op, adaptor.getVal(),
2312 adaptor.getExpected());
2313 return mlir::success();
2316mlir::LogicalResult CIRToLLVMAbsOpLowering::matchAndRewrite(
2317 cir::AbsOp op, OpAdaptor adaptor,
2318 mlir::ConversionPatternRewriter &rewriter)
const {
2319 mlir::Type resTy = typeConverter->convertType(op.getType());
2320 auto absOp = mlir::LLVM::AbsOp::create(rewriter, op.getLoc(), resTy,
2321 adaptor.getOperands()[0],
2322 adaptor.getMinIsPoison());
2323 rewriter.replaceOp(op, absOp);
2324 return mlir::success();
2331void CIRToLLVMFuncOpLowering::lowerFuncAttributes(
2332 cir::FuncOp func,
bool filterArgAndResAttrs,
2333 SmallVectorImpl<mlir::NamedAttribute> &result)
const {
2334 for (mlir::NamedAttribute attr : func->getAttrs()) {
2335 if (
attr.getName() == mlir::SymbolTable::getSymbolAttrName() ||
2336 attr.getName() == func.getFunctionTypeAttrName() ||
2338 attr.getName() == func.getCallingConvAttrName() ||
2339 attr.getName() == func.getDsoLocalAttrName() ||
2340 attr.getName() == func.getInlineKindAttrName() ||
2341 attr.getName() == func.getSideEffectAttrName() ||
2342 attr.getName() == CIRDialect::getNoReturnAttrName() ||
2343 attr.getName() == func.getAnnotationsAttrName() ||
2344 (filterArgAndResAttrs &&
2345 (
attr.getName() == func.getArgAttrsAttrName() ||
2346 attr.getName() == func.getResAttrsAttrName())))
2350 result.push_back(attr);
2354mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewriteAlias(
2355 cir::FuncOp op, llvm::StringRef aliasee, mlir::Type ty, OpAdaptor adaptor,
2356 mlir::ConversionPatternRewriter &rewriter)
const {
2357 SmallVector<mlir::NamedAttribute, 4> attributes;
2358 lowerFuncAttributes(op,
false, attributes);
2360 mlir::Location loc = op.getLoc();
2361 auto aliasOp = rewriter.replaceOpWithNewOp<mlir::LLVM::AliasOp>(
2362 op, ty,
convertLinkage(op.getLinkage()), op.getName(), op.getDsoLocal(),
2366 mlir::OpBuilder builder(op.getContext());
2367 mlir::Block *block = builder.createBlock(&aliasOp.getInitializerRegion());
2368 builder.setInsertionPointToStart(block);
2371 mlir::Type ptrTy = mlir::LLVM::LLVMPointerType::get(ty.getContext());
2372 auto addrOp = mlir::LLVM::AddressOfOp::create(builder, loc, ptrTy, aliasee);
2373 mlir::LLVM::ReturnOp::create(builder, loc, addrOp);
2375 return mlir::success();
2378mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewrite(
2379 cir::FuncOp op, OpAdaptor adaptor,
2380 mlir::ConversionPatternRewriter &rewriter)
const {
2382 cir::FuncType fnType = op.getFunctionType();
2383 bool isDsoLocal = op.getDsoLocal();
2384 mlir::TypeConverter::SignatureConversion signatureConversion(
2385 fnType.getNumInputs());
2387 for (
const auto &argType : llvm::enumerate(fnType.getInputs())) {
2388 mlir::Type convertedType = typeConverter->convertType(argType.value());
2390 return mlir::failure();
2391 signatureConversion.addInputs(argType.index(), convertedType);
2394 mlir::Type resultType =
2395 getTypeConverter()->convertType(fnType.getReturnType());
2398 mlir::Type llvmFnTy = mlir::LLVM::LLVMFunctionType::get(
2399 resultType ? resultType : mlir::LLVM::LLVMVoidType::get(getContext()),
2400 signatureConversion.getConvertedTypes(),
2404 if (std::optional<llvm::StringRef> aliasee = op.getAliasee())
2405 return matchAndRewriteAlias(op, *aliasee, llvmFnTy, adaptor, rewriter);
2409 mlir::Location loc = op.getLoc();
2410 if (mlir::FusedLoc fusedLoc = mlir::dyn_cast<mlir::FusedLoc>(loc))
2411 loc = fusedLoc.getLocations()[0];
2412 assert((mlir::isa<mlir::FileLineColLoc>(loc) ||
2413 mlir::isa<mlir::UnknownLoc>(loc)) &&
2414 "expected single location or unknown location here");
2418 SmallVector<mlir::NamedAttribute, 4> attributes;
2419 lowerFuncAttributes(op,
false, attributes);
2421 mlir::LLVM::LLVMFuncOp fn = mlir::LLVM::LLVMFuncOp::create(
2422 rewriter, loc, op.getName(), llvmFnTy, linkage, isDsoLocal, cconv,
2423 mlir::SymbolRefAttr(), attributes);
2427 if (std::optional<cir::SideEffect> sideEffectKind = op.getSideEffect()) {
2428 switch (*sideEffectKind) {
2429 case cir::SideEffect::All:
2431 case cir::SideEffect::Pure:
2432 fn.setMemoryEffectsAttr(mlir::LLVM::MemoryEffectsAttr::get(
2434 mlir::LLVM::ModRefInfo::Ref,
2435 mlir::LLVM::ModRefInfo::Ref,
2436 mlir::LLVM::ModRefInfo::Ref,
2437 mlir::LLVM::ModRefInfo::Ref,
2438 mlir::LLVM::ModRefInfo::Ref,
2439 mlir::LLVM::ModRefInfo::Ref));
2440 fn.setNoUnwind(
true);
2441 fn.setWillReturn(
true);
2443 case cir::SideEffect::Const:
2444 fn.setMemoryEffectsAttr(mlir::LLVM::MemoryEffectsAttr::get(
2446 mlir::LLVM::ModRefInfo::NoModRef,
2447 mlir::LLVM::ModRefInfo::NoModRef,
2448 mlir::LLVM::ModRefInfo::NoModRef,
2449 mlir::LLVM::ModRefInfo::NoModRef,
2450 mlir::LLVM::ModRefInfo::NoModRef,
2451 mlir::LLVM::ModRefInfo::NoModRef));
2452 fn.setNoUnwind(
true);
2453 fn.setWillReturn(
true);
2458 if (op->hasAttr(CIRDialect::getNoReturnAttrName()))
2459 fn.setNoreturn(
true);
2461 if (std::optional<cir::InlineKind> inlineKind = op.getInlineKind()) {
2462 fn.setNoInline(*inlineKind == cir::InlineKind::NoInline);
2463 fn.setInlineHint(*inlineKind == cir::InlineKind::InlineHint);
2464 fn.setAlwaysInline(*inlineKind == cir::InlineKind::AlwaysInline);
2467 if (std::optional<llvm::StringRef> personality = op.getPersonality())
2468 fn.setPersonality(*personality);
2473 rewriter.inlineRegionBefore(op.getBody(), fn.getBody(), fn.end());
2474 if (failed(rewriter.convertRegionTypes(&fn.getBody(), *typeConverter,
2475 &signatureConversion)))
2476 return mlir::failure();
2478 rewriter.eraseOp(op);
2480 return mlir::LogicalResult::success();
2483mlir::LogicalResult CIRToLLVMGetGlobalOpLowering::matchAndRewrite(
2484 cir::GetGlobalOp op, OpAdaptor adaptor,
2485 mlir::ConversionPatternRewriter &rewriter)
const {
2488 if (op->getUses().empty()) {
2489 rewriter.eraseOp(op);
2490 return mlir::success();
2493 mlir::Type
type = getTypeConverter()->convertType(op.getType());
2494 mlir::Operation *newop = mlir::LLVM::AddressOfOp::create(
2495 rewriter, op.getLoc(), type, op.getName());
2499 newop = mlir::LLVM::ThreadlocalAddressOp::create(rewriter, op.getLoc(),
2500 type, newop->getResult(0));
2503 rewriter.replaceOp(op, newop);
2504 return mlir::success();
2507llvm::SmallVector<mlir::NamedAttribute>
2508CIRToLLVMGlobalOpLowering::lowerGlobalAttributes(
2509 cir::GlobalOp op, mlir::ConversionPatternRewriter &rewriter)
const {
2510 SmallVector<mlir::NamedAttribute> attributes;
2512 if (mlir::StringAttr sectionAttr = op.getSectionAttr())
2513 attributes.push_back(rewriter.getNamedAttr(
"section", sectionAttr));
2515 mlir::LLVM::VisibilityAttr visibility = mlir::LLVM::VisibilityAttr::get(
2518 attributes.push_back(rewriter.getNamedAttr(
"visibility_", visibility));
2520 if (op->getAttr(CUDAExternallyInitializedAttr::getMnemonic()))
2521 attributes.push_back(rewriter.getNamedAttr(
"externally_initialized",
2522 rewriter.getUnitAttr()));
2529void CIRToLLVMGlobalOpLowering::setupRegionInitializedLLVMGlobalOp(
2530 cir::GlobalOp op, mlir::ConversionPatternRewriter &rewriter)
const {
2531 mlir::Type llvmType =
2536 if (std::optional<mlir::Attribute> init = op.getInitialValue())
2538 llvmType, *init, *getTypeConverter(), dataLayout);
2544 const bool isConst = op.getConstant();
2545 unsigned addrSpace = 0;
2546 if (
auto targetAS = mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
2547 op.getAddrSpaceAttr()))
2548 addrSpace = targetAS.getValue();
2549 const bool isDsoLocal = op.getDsoLocal();
2550 const bool isThreadLocal = (
bool)op.getTlsModelAttr();
2551 const uint64_t alignment = op.getAlignment().value_or(0);
2552 const mlir::LLVM::Linkage linkage =
convertLinkage(op.getLinkage());
2553 const StringRef symbol = op.getSymName();
2554 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
2556 SmallVector<mlir::NamedAttribute> attributes =
2557 lowerGlobalAttributes(op, rewriter);
2559 mlir::LLVM::GlobalOp newGlobalOp =
2560 rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
2561 op, llvmType, isConst, linkage, symbol,
nullptr, alignment, addrSpace,
2562 isDsoLocal, isThreadLocal, comdatAttr, attributes);
2563 newGlobalOp.getRegion().emplaceBlock();
2564 rewriter.setInsertionPointToEnd(newGlobalOp.getInitializerBlock());
2568CIRToLLVMGlobalOpLowering::matchAndRewriteRegionInitializedGlobal(
2569 cir::GlobalOp op, mlir::Attribute init,
2570 mlir::ConversionPatternRewriter &rewriter)
const {
2572 assert((isa<cir::BlockAddrInfoAttr, cir::ConstArrayAttr, cir::ConstRecordAttr,
2573 cir::ConstVectorAttr, cir::ConstPtrAttr, cir::ConstComplexAttr,
2574 cir::GlobalViewAttr, cir::TypeInfoAttr, cir::UndefAttr,
2575 cir::PoisonAttr, cir::VTableAttr, cir::ZeroAttr>(init)));
2580 const mlir::Location loc = op.getLoc();
2581 setupRegionInitializedLLVMGlobalOp(op, rewriter);
2586 CIRAttrToValue valueConverter(op, rewriter, typeConverter, &blockInfoAddr);
2587 mlir::Value value = valueConverter.visit(init);
2588 mlir::LLVM::ReturnOp::create(rewriter, loc, value);
2589 return mlir::success();
2592mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite(
2593 cir::GlobalOp op, OpAdaptor adaptor,
2594 mlir::ConversionPatternRewriter &rewriter)
const {
2597 if (!op.getCtorRegion().empty() || !op.getDtorRegion().empty())
2598 return op.emitError() <<
"GlobalOp ctor and dtor regions should be removed "
2599 "in LoweringPrepare";
2601 std::optional<mlir::Attribute> init = op.getInitialValue();
2604 const mlir::Type cirSymType = op.getSymType();
2607 mlir::Type llvmType =
2613 if (init.has_value())
2615 llvmType, *init, *getTypeConverter(), dataLayout);
2619 const bool isConst = op.getConstant();
2620 unsigned addrSpace = 0;
2621 if (
auto targetAS = mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
2622 op.getAddrSpaceAttr()))
2623 addrSpace = targetAS.getValue();
2624 const bool isDsoLocal = op.getDsoLocal();
2625 const bool isThreadLocal = (
bool)op.getTlsModelAttr();
2626 const uint64_t alignment = op.getAlignment().value_or(0);
2627 const mlir::LLVM::Linkage linkage =
convertLinkage(op.getLinkage());
2628 const StringRef symbol = op.getSymName();
2629 SmallVector<mlir::NamedAttribute> attributes =
2630 lowerGlobalAttributes(op, rewriter);
2633 if (std::optional<llvm::StringRef> aliasee = op.getAliasee()) {
2634 mlir::Location loc = op.getLoc();
2635 auto aliasOp = rewriter.replaceOpWithNewOp<mlir::LLVM::AliasOp>(
2636 op, llvmType, linkage, symbol, isDsoLocal, isThreadLocal, attributes);
2638 mlir::OpBuilder builder(op.getContext());
2639 mlir::Block *block = builder.createBlock(&aliasOp.getInitializerRegion());
2640 builder.setInsertionPointToStart(block);
2642 mlir::LLVM::LLVMPointerType::get(getContext(), addrSpace);
2644 mlir::LLVM::AddressOfOp::create(builder, loc, ptrTy, *aliasee);
2645 mlir::LLVM::ReturnOp::create(builder, loc, addrOp);
2646 return mlir::success();
2649 if (init.has_value()) {
2650 if (mlir::isa<cir::FPAttr, cir::IntAttr, cir::BoolAttr>(init.value())) {
2652 init = initRewriter.visit(init.value());
2657 if (!init.value()) {
2658 op.emitError() <<
"unsupported initializer '" << init.value() <<
"'";
2659 return mlir::failure();
2661 }
else if (
auto constArr =
2662 mlir::dyn_cast<cir::ConstArrayAttr>(init.value())) {
2670 mlir::ModuleOp modOp = op->getParentOfType<mlir::ModuleOp>();
2671 if (std::optional<mlir::Attribute> bulkInit =
2673 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
2674 rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
2675 op, llvmType, isConst, linkage, symbol, bulkInit.value(),
2676 alignment, addrSpace, isDsoLocal, isThreadLocal, comdatAttr,
2678 return mlir::success();
2681 return matchAndRewriteRegionInitializedGlobal(op, init.value(), rewriter);
2682 }
else if (
auto constRecord =
2683 mlir::dyn_cast<cir::ConstRecordAttr>(init.value())) {
2689 mlir::ModuleOp modOp = op->getParentOfType<mlir::ModuleOp>();
2690 if (std::optional<mlir::Attribute> bulkInit =
2692 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
2693 rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
2694 op, llvmType, isConst, linkage, symbol, bulkInit.value(), alignment,
2695 addrSpace, isDsoLocal, isThreadLocal, comdatAttr, attributes);
2696 return mlir::success();
2698 return matchAndRewriteRegionInitializedGlobal(op, init.value(), rewriter);
2699 }
else if (mlir::isa<cir::BlockAddrInfoAttr, cir::ConstVectorAttr,
2700 cir::ConstRecordAttr, cir::ConstPtrAttr,
2701 cir::ConstComplexAttr, cir::GlobalViewAttr,
2702 cir::TypeInfoAttr, cir::UndefAttr, cir::PoisonAttr,
2703 cir::VTableAttr, cir::ZeroAttr>(init.value())) {
2707 return matchAndRewriteRegionInitializedGlobal(op, init.value(), rewriter);
2711 op.emitError() <<
"unsupported initializer '" << init.value() <<
"'";
2712 return mlir::failure();
2716 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
2717 rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
2718 op, llvmType, isConst, linkage, symbol, init.value_or(mlir::Attribute()),
2719 alignment, addrSpace, isDsoLocal, isThreadLocal, comdatAttr, attributes);
2721 return mlir::success();
2725CIRToLLVMGlobalOpLowering::getComdatAttr(cir::GlobalOp &op,
2726 mlir::OpBuilder &builder)
const {
2727 if (!op.getComdat())
2728 return mlir::SymbolRefAttr{};
2730 mlir::ModuleOp modOp = op->getParentOfType<mlir::ModuleOp>();
2731 mlir::OpBuilder::InsertionGuard guard(builder);
2732 StringRef comdatName(
"__llvm_comdat_globals");
2734 builder.setInsertionPointToStart(modOp.getBody());
2736 mlir::LLVM::ComdatOp::create(builder, modOp.getLoc(), comdatName);
2739 if (
auto comdatSelector = comdatOp.lookupSymbol<mlir::LLVM::ComdatSelectorOp>(
2741 return mlir::SymbolRefAttr::get(
2742 builder.getContext(), comdatName,
2743 mlir::FlatSymbolRefAttr::get(comdatSelector.getSymNameAttr()));
2746 builder.setInsertionPointToStart(&comdatOp.getBody().back());
2747 auto selectorOp = mlir::LLVM::ComdatSelectorOp::create(
2748 builder, comdatOp.getLoc(), op.getSymName(),
2749 mlir::LLVM::comdat::Comdat::Any);
2750 return mlir::SymbolRefAttr::get(
2751 builder.getContext(), comdatName,
2752 mlir::FlatSymbolRefAttr::get(selectorOp.getSymNameAttr()));
2755mlir::LogicalResult CIRToLLVMSwitchFlatOpLowering::matchAndRewrite(
2756 cir::SwitchFlatOp op, OpAdaptor adaptor,
2757 mlir::ConversionPatternRewriter &rewriter)
const {
2759 llvm::SmallVector<mlir::APInt, 8> caseValues;
2760 for (mlir::Attribute val : op.getCaseValues()) {
2761 auto intAttr = cast<cir::IntAttr>(val);
2762 caseValues.push_back(intAttr.getValue());
2765 llvm::SmallVector<mlir::Block *, 8> caseDestinations;
2766 llvm::SmallVector<mlir::ValueRange, 8> caseOperands;
2768 for (mlir::Block *x : op.getCaseDestinations())
2769 caseDestinations.push_back(x);
2771 for (mlir::OperandRange x : op.getCaseOperands())
2772 caseOperands.push_back(x);
2775 rewriter.setInsertionPoint(op);
2776 rewriter.replaceOpWithNewOp<mlir::LLVM::SwitchOp>(
2777 op, adaptor.getCondition(), op.getDefaultDestination(),
2778 op.getDefaultOperands(), caseValues, caseDestinations, caseOperands);
2779 return mlir::success();
2782static mlir::LLVM::IntegerOverflowFlags
nswFlag(
bool nsw) {
2783 return nsw ? mlir::LLVM::IntegerOverflowFlags::nsw
2784 : mlir::LLVM::IntegerOverflowFlags::none;
2787template <
typename CIROp,
typename LLVMIntOp>
2788static mlir::LogicalResult
2790 mlir::ConversionPatternRewriter &rewriter) {
2791 mlir::Type llvmType = adaptor.getInput().getType();
2792 mlir::Location loc = op.getLoc();
2794 auto maybeNSW =
nswFlag(op.getNoSignedWrap());
2795 mlir::LLVM::ConstantOp one;
2796 if (mlir::isa<cir::VectorType>(op.getType())) {
2797 mlir::DenseIntElementsAttr oneVec = mlir::DenseIntElementsAttr::get(
2798 mlir::cast<mlir::ShapedType>(llvmType), 1);
2799 one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, oneVec);
2801 one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
2803 rewriter.replaceOpWithNewOp<LLVMIntOp>(op, adaptor.getInput(), one, maybeNSW);
2804 return mlir::success();
2807mlir::LogicalResult CIRToLLVMIncOpLowering::matchAndRewrite(
2808 cir::IncOp op, OpAdaptor adaptor,
2809 mlir::ConversionPatternRewriter &rewriter)
const {
2813mlir::LogicalResult CIRToLLVMDecOpLowering::matchAndRewrite(
2814 cir::DecOp op, OpAdaptor adaptor,
2815 mlir::ConversionPatternRewriter &rewriter)
const {
2819mlir::LogicalResult CIRToLLVMMinusOpLowering::matchAndRewrite(
2820 cir::MinusOp op, OpAdaptor adaptor,
2821 mlir::ConversionPatternRewriter &rewriter)
const {
2822 bool isVector = mlir::isa<cir::VectorType>(op.getType());
2823 mlir::Type llvmType = adaptor.getInput().getType();
2824 mlir::Location loc = op.getLoc();
2826 auto maybeNSW =
nswFlag(op.getNoSignedWrap());
2829 zero = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmType);
2831 zero = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 0);
2832 rewriter.replaceOpWithNewOp<mlir::LLVM::SubOp>(op, zero, adaptor.getInput(),
2834 return mlir::success();
2837mlir::LogicalResult CIRToLLVMNotOpLowering::matchAndRewrite(
2838 cir::NotOp op, OpAdaptor adaptor,
2839 mlir::ConversionPatternRewriter &rewriter)
const {
2840 mlir::Type elementType = elementTypeIfVector(op.getType());
2841 bool isVector = mlir::isa<cir::VectorType>(op.getType());
2842 mlir::Type llvmType = adaptor.getInput().getType();
2843 mlir::Location loc = op.getLoc();
2845 if (mlir::isa<cir::IntType>(elementType)) {
2846 mlir::Value minusOne;
2849 mlir::dyn_cast<cir::VectorType>(op.getType()).getSize();
2850 SmallVector<int32_t> values(numElements, -1);
2851 mlir::DenseIntElementsAttr denseVec = rewriter.getI32VectorAttr(values);
2853 mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, denseVec);
2855 minusOne = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, -1);
2857 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getInput(),
2859 return mlir::success();
2861 if (mlir::isa<cir::BoolType>(elementType)) {
2862 auto one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
2863 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getInput(), one);
2864 return mlir::success();
2866 return op.emitError() <<
"Unsupported type for bitwise NOT";
2871 return mlir::isa<cir::IntType>(type)
2872 ? mlir::cast<cir::IntType>(type).isUnsigned()
2873 : mlir::cast<mlir::IntegerType>(type).isUnsigned();
2880template <
typename BinOp>
2882 if (op.getNoUnsignedWrap())
2883 return mlir::LLVM::IntegerOverflowFlags::nuw;
2884 if (op.getNoSignedWrap())
2885 return mlir::LLVM::IntegerOverflowFlags::nsw;
2886 return mlir::LLVM::IntegerOverflowFlags::none;
2891template <
typename UIntSatOp,
typename SIntSatOp,
typename IntOp,
2893static mlir::LogicalResult
2895 mlir::ConversionPatternRewriter &rewriter) {
2896 const mlir::Type eltType = elementTypeIfVector(op.getRhs().getType());
2897 assert(cir::isIntOrBoolType(eltType) &&
2898 "saturatable arith op expects integer operand types");
2899 if (op.getSaturated()) {
2901 rewriter.replaceOpWithNewOp<UIntSatOp>(op, lhs, rhs);
2903 rewriter.replaceOpWithNewOp<SIntSatOp>(op, lhs, rhs);
2904 return mlir::success();
2906 rewriter.replaceOpWithNewOp<IntOp>(op, lhs, rhs,
intOverflowFlag(op));
2907 return mlir::success();
2910mlir::LogicalResult CIRToLLVMAddOpLowering::matchAndRewrite(
2911 cir::AddOp op, OpAdaptor adaptor,
2912 mlir::ConversionPatternRewriter &rewriter)
const {
2914 mlir::LLVM::AddOp>(op, adaptor.getLhs(),
2915 adaptor.getRhs(), rewriter);
2918mlir::LogicalResult CIRToLLVMSubOpLowering::matchAndRewrite(
2919 cir::SubOp op, OpAdaptor adaptor,
2920 mlir::ConversionPatternRewriter &rewriter)
const {
2922 mlir::LLVM::SubOp>(op, adaptor.getLhs(),
2923 adaptor.getRhs(), rewriter);
2926mlir::LogicalResult CIRToLLVMMulOpLowering::matchAndRewrite(
2927 cir::MulOp op, OpAdaptor adaptor,
2928 mlir::ConversionPatternRewriter &rewriter)
const {
2929 assert(cir::isIntOrBoolType(elementTypeIfVector(op.getRhs().getType())) &&
2930 "cir.mul expects integer operand types");
2931 rewriter.replaceOpWithNewOp<mlir::LLVM::MulOp>(
2933 return mlir::success();
2937template <
typename UIntOp,
typename SIntOp,
typename CIROp>
2938static mlir::LogicalResult
2940 mlir::ConversionPatternRewriter &rewriter) {
2941 const mlir::Type eltType = elementTypeIfVector(op.getRhs().getType());
2942 assert(cir::isIntOrBoolType(eltType) &&
2943 "integer binary op expects integer operand types");
2945 rewriter.replaceOpWithNewOp<UIntOp>(op, lhs, rhs);
2947 rewriter.replaceOpWithNewOp<SIntOp>(op, lhs, rhs);
2948 return mlir::success();
2951mlir::LogicalResult CIRToLLVMDivOpLowering::matchAndRewrite(
2952 cir::DivOp op, OpAdaptor adaptor,
2953 mlir::ConversionPatternRewriter &rewriter)
const {
2955 op, adaptor.getLhs(), adaptor.getRhs(), rewriter);
2958mlir::LogicalResult CIRToLLVMRemOpLowering::matchAndRewrite(
2959 cir::RemOp op, OpAdaptor adaptor,
2960 mlir::ConversionPatternRewriter &rewriter)
const {
2962 op, adaptor.getLhs(), adaptor.getRhs(), rewriter);
2965template <
typename CIROp,
typename UIntOp,
typename SIntOp>
2966static mlir::LogicalResult
2968 mlir::ConversionPatternRewriter &rewriter) {
2969 const mlir::Value lhs = adaptor.getLhs();
2970 const mlir::Value rhs = adaptor.getRhs();
2972 rewriter.replaceOpWithNewOp<UIntOp>(op, lhs, rhs);
2974 rewriter.replaceOpWithNewOp<SIntOp>(op, lhs, rhs);
2975 return mlir::success();
2978mlir::LogicalResult CIRToLLVMMaxOpLowering::matchAndRewrite(
2979 cir::MaxOp op, OpAdaptor adaptor,
2980 mlir::ConversionPatternRewriter &rewriter)
const {
2982 op, adaptor, rewriter);
2985mlir::LogicalResult CIRToLLVMMinOpLowering::matchAndRewrite(
2986 cir::MinOp op, OpAdaptor adaptor,
2987 mlir::ConversionPatternRewriter &rewriter)
const {
2989 op, adaptor, rewriter);
2993static mlir::LLVM::ICmpPredicate
2995 using CIR = cir::CmpOpKind;
2996 using LLVMICmp = mlir::LLVM::ICmpPredicate;
2999 return LLVMICmp::eq;
3001 return LLVMICmp::ne;
3003 return (isSigned ? LLVMICmp::slt : LLVMICmp::ult);
3005 return (isSigned ? LLVMICmp::sle : LLVMICmp::ule);
3007 return (isSigned ? LLVMICmp::sgt : LLVMICmp::ugt);
3009 return (isSigned ? LLVMICmp::sge : LLVMICmp::uge);
3012 llvm_unreachable(
"FP-only comparison used with integer type");
3014 llvm_unreachable(
"Unknown CmpOpKind");
3019static mlir::LLVM::FCmpPredicate
3021 using CIR = cir::CmpOpKind;
3022 using LLVMFCmp = mlir::LLVM::FCmpPredicate;
3025 return LLVMFCmp::oeq;
3027 return LLVMFCmp::une;
3029 return LLVMFCmp::olt;
3031 return LLVMFCmp::ole;
3033 return LLVMFCmp::ogt;
3035 return LLVMFCmp::oge;
3037 return LLVMFCmp::one;
3039 return LLVMFCmp::uno;
3041 llvm_unreachable(
"Unknown CmpOpKind");
3044mlir::LogicalResult CIRToLLVMCmpOpLowering::matchAndRewrite(
3045 cir::CmpOp cmpOp, OpAdaptor adaptor,
3046 mlir::ConversionPatternRewriter &rewriter)
const {
3047 mlir::Type type = cmpOp.getLhs().getType();
3049 if (mlir::isa<cir::IntType, mlir::IntegerType>(type)) {
3050 bool isSigned = mlir::isa<cir::IntType>(type)
3051 ? mlir::cast<cir::IntType>(type).isSigned()
3052 : mlir::cast<mlir::IntegerType>(type).isSigned();
3053 mlir::LLVM::ICmpPredicate
kind =
3055 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
3056 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
3057 return mlir::success();
3060 if (
auto ptrTy = mlir::dyn_cast<cir::PointerType>(type)) {
3061 mlir::LLVM::ICmpPredicate
kind =
3064 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
3065 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
3066 return mlir::success();
3069 if (
auto vptrTy = mlir::dyn_cast<cir::VPtrType>(type)) {
3073 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
3074 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
3075 return mlir::success();
3078 if (mlir::isa<cir::FPTypeInterface>(type)) {
3079 mlir::LLVM::FCmpPredicate
kind =
3081 rewriter.replaceOpWithNewOp<mlir::LLVM::FCmpOp>(
3082 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
3083 return mlir::success();
3086 if (mlir::isa<cir::ComplexType>(type)) {
3087 mlir::Value lhs = adaptor.getLhs();
3088 mlir::Value rhs = adaptor.getRhs();
3089 mlir::Location loc = cmpOp.getLoc();
3091 auto complexType = mlir::cast<cir::ComplexType>(cmpOp.getLhs().getType());
3092 mlir::Type complexElemTy =
3093 getTypeConverter()->convertType(
complexType.getElementType());
3095 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
3096 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{0}));
3097 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
3098 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{1}));
3099 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
3100 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{0}));
3101 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
3102 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{1}));
3104 if (cmpOp.getKind() == cir::CmpOpKind::eq) {
3105 if (complexElemTy.isInteger()) {
3106 auto realCmp = mlir::LLVM::ICmpOp::create(
3107 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, lhsReal, rhsReal);
3108 auto imagCmp = mlir::LLVM::ICmpOp::create(
3109 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, lhsImag, rhsImag);
3110 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, imagCmp);
3111 return mlir::success();
3114 auto realCmp = mlir::LLVM::FCmpOp::create(
3115 rewriter, loc, mlir::LLVM::FCmpPredicate::oeq, lhsReal, rhsReal);
3116 auto imagCmp = mlir::LLVM::FCmpOp::create(
3117 rewriter, loc, mlir::LLVM::FCmpPredicate::oeq, lhsImag, rhsImag);
3118 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, imagCmp);
3119 return mlir::success();
3122 if (cmpOp.getKind() == cir::CmpOpKind::ne) {
3123 if (complexElemTy.isInteger()) {
3124 auto realCmp = mlir::LLVM::ICmpOp::create(
3125 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, lhsReal, rhsReal);
3126 auto imagCmp = mlir::LLVM::ICmpOp::create(
3127 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, lhsImag, rhsImag);
3128 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp);
3129 return mlir::success();
3132 auto realCmp = mlir::LLVM::FCmpOp::create(
3133 rewriter, loc, mlir::LLVM::FCmpPredicate::une, lhsReal, rhsReal);
3134 auto imagCmp = mlir::LLVM::FCmpOp::create(
3135 rewriter, loc, mlir::LLVM::FCmpPredicate::une, lhsImag, rhsImag);
3136 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp);
3137 return mlir::success();
3141 return cmpOp.emitError() <<
"unsupported type for CmpOp: " <<
type;
3147template <
typename OpTy>
3148static mlir::LogicalResult
3150 mlir::ConversionPatternRewriter &rewriter,
3151 const mlir::TypeConverter *typeConverter,
3152 llvm::StringRef opStr) {
3153 mlir::Location loc = op.getLoc();
3154 cir::IntType operandTy = op.getLhs().getType();
3157 mlir::Type resultTy = op.getResult().getType();
3158 auto resultIntTy = mlir::dyn_cast<cir::IntType>(resultTy);
3159 unsigned resultWidth = resultIntTy ? resultIntTy.getWidth() : 1;
3160 bool resultSigned = resultIntTy && resultIntTy.getIsSigned();
3162 bool sign = operandTy.getIsSigned() || resultSigned;
3164 std::max(operandTy.getWidth() + (
sign && operandTy.isUnsigned()),
3165 resultWidth + (
sign && !resultSigned));
3167 mlir::IntegerType encompassedLLVMTy = rewriter.getIntegerType(width);
3169 mlir::Value lhs = adaptor.getLhs();
3170 mlir::Value rhs = adaptor.getRhs();
3171 if (operandTy.getWidth() < width) {
3172 if (operandTy.isSigned()) {
3173 lhs = mlir::LLVM::SExtOp::create(rewriter, loc, encompassedLLVMTy, lhs);
3174 rhs = mlir::LLVM::SExtOp::create(rewriter, loc, encompassedLLVMTy, rhs);
3176 lhs = mlir::LLVM::ZExtOp::create(rewriter, loc, encompassedLLVMTy, lhs);
3177 rhs = mlir::LLVM::ZExtOp::create(rewriter, loc, encompassedLLVMTy, rhs);
3182 std::string intrinName = (
"llvm." + llvm::Twine(
sign ?
's' :
'u') + opStr +
3183 ".with.overflow.i" + llvm::Twine(width))
3185 auto intrinNameAttr = mlir::StringAttr::get(op.getContext(), intrinName);
3187 mlir::IntegerType overflowLLVMTy = rewriter.getI1Type();
3188 auto intrinRetTy = mlir::LLVM::LLVMStructType::getLiteral(
3189 rewriter.getContext(), {encompassedLLVMTy, overflowLLVMTy});
3191 auto callLLVMIntrinOp = mlir::LLVM::CallIntrinsicOp::create(
3192 rewriter, loc, intrinRetTy, intrinNameAttr, mlir::ValueRange{lhs, rhs});
3193 mlir::Value intrinRet = callLLVMIntrinOp.getResult(0);
3195 mlir::Value result = mlir::LLVM::ExtractValueOp::create(
3198 mlir::Value overflow = mlir::LLVM::ExtractValueOp::create(
3202 if (resultWidth < width) {
3203 mlir::Type resultLLVMTy = typeConverter->convertType(resultTy);
3205 mlir::LLVM::TruncOp::create(rewriter, loc, resultLLVMTy, result);
3209 mlir::Value truncResultExt;
3211 truncResultExt = mlir::LLVM::SExtOp::create(
3212 rewriter, loc, encompassedLLVMTy, truncResult);
3214 truncResultExt = mlir::LLVM::ZExtOp::create(
3215 rewriter, loc, encompassedLLVMTy, truncResult);
3216 auto truncOverflow = mlir::LLVM::ICmpOp::create(
3217 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, truncResultExt, result);
3219 result = truncResult;
3220 overflow = mlir::LLVM::OrOp::create(rewriter, loc, overflow, truncOverflow);
3223 mlir::Type boolLLVMTy =
3224 typeConverter->convertType(op.getOverflow().getType());
3225 if (boolLLVMTy != rewriter.getI1Type())
3226 overflow = mlir::LLVM::ZExtOp::create(rewriter, loc, boolLLVMTy, overflow);
3228 rewriter.replaceOp(op, mlir::ValueRange{result, overflow});
3230 return mlir::success();
3233mlir::LogicalResult CIRToLLVMAddOverflowOpLowering::matchAndRewrite(
3234 cir::AddOverflowOp op, OpAdaptor adaptor,
3235 mlir::ConversionPatternRewriter &rewriter)
const {
3239mlir::LogicalResult CIRToLLVMSubOverflowOpLowering::matchAndRewrite(
3240 cir::SubOverflowOp op, OpAdaptor adaptor,
3241 mlir::ConversionPatternRewriter &rewriter)
const {
3245mlir::LogicalResult CIRToLLVMMulOverflowOpLowering::matchAndRewrite(
3246 cir::MulOverflowOp op, OpAdaptor adaptor,
3247 mlir::ConversionPatternRewriter &rewriter)
const {
3251mlir::LogicalResult CIRToLLVMFrexpOpLowering::matchAndRewrite(
3252 cir::FrexpOp op, OpAdaptor adaptor,
3253 mlir::ConversionPatternRewriter &rewriter)
const {
3254 mlir::Location loc = op.getLoc();
3255 mlir::Type fpLLVMTy =
3256 getTypeConverter()->convertType(op.getResult().getType());
3257 mlir::Type intLLVMTy = getTypeConverter()->convertType(op.getExp().getType());
3259 auto structTy = mlir::LLVM::LLVMStructType::getLiteral(rewriter.getContext(),
3260 {fpLLVMTy, intLLVMTy});
3264 mlir::Value result = callOp.getResult(0);
3266 mlir::Value mantissa =
3267 mlir::LLVM::ExtractValueOp::create(rewriter, loc, result, 0);
3268 mlir::Value exponent =
3269 mlir::LLVM::ExtractValueOp::create(rewriter, loc, result, 1);
3270 rewriter.replaceOp(op, mlir::ValueRange{mantissa, exponent});
3271 return mlir::success();
3274mlir::LogicalResult CIRToLLVMModfOpLowering::matchAndRewrite(
3275 cir::ModfOp op, OpAdaptor adaptor,
3276 mlir::ConversionPatternRewriter &rewriter)
const {
3277 mlir::Location loc = op.getLoc();
3278 mlir::Type fpLLVMTy =
3279 getTypeConverter()->convertType(op.getFractional().getType());
3281 auto structTy = mlir::LLVM::LLVMStructType::getLiteral(rewriter.getContext(),
3282 {fpLLVMTy, fpLLVMTy});
3286 mlir::Value result = callOp.getResult(0);
3288 mlir::Value fractional =
3289 mlir::LLVM::ExtractValueOp::create(rewriter, loc, result, 0);
3290 mlir::Value integral =
3291 mlir::LLVM::ExtractValueOp::create(rewriter, loc, result, 1);
3292 rewriter.replaceOp(op, mlir::ValueRange{fractional, integral});
3293 return mlir::success();
3296mlir::LogicalResult CIRToLLVMShiftOpLowering::matchAndRewrite(
3297 cir::ShiftOp op, OpAdaptor adaptor,
3298 mlir::ConversionPatternRewriter &rewriter)
const {
3299 assert((op.getValue().getType() == op.getType()) &&
3300 "inconsistent operands' types NYI");
3302 const mlir::Type llvmTy = getTypeConverter()->convertType(op.getType());
3303 mlir::Value amt = adaptor.getAmount();
3304 mlir::Value val = adaptor.getValue();
3306 auto cirAmtTy = mlir::dyn_cast<cir::IntType>(op.getAmount().getType());
3309 auto cirValTy = mlir::cast<cir::IntType>(op.getValue().getType());
3317 amt =
getLLVMIntCast(rewriter, amt, llvmTy,
true, cirAmtTy.getWidth(),
3318 cirValTy.getWidth());
3320 auto cirValVTy = mlir::cast<cir::VectorType>(op.getValue().getType());
3322 mlir::cast<cir::IntType>(cirValVTy.getElementType()).isUnsigned();
3326 if (op.getIsShiftleft()) {
3327 rewriter.replaceOpWithNewOp<mlir::LLVM::ShlOp>(op, llvmTy, val, amt);
3328 return mlir::success();
3332 rewriter.replaceOpWithNewOp<mlir::LLVM::LShrOp>(op, llvmTy, val, amt);
3334 rewriter.replaceOpWithNewOp<mlir::LLVM::AShrOp>(op, llvmTy, val, amt);
3335 return mlir::success();
3338mlir::LogicalResult CIRToLLVMSelectOpLowering::matchAndRewrite(
3339 cir::SelectOp op, OpAdaptor adaptor,
3340 mlir::ConversionPatternRewriter &rewriter)
const {
3341 auto getConstantBool = [](mlir::Value value) -> cir::BoolAttr {
3342 auto definingOp = value.getDefiningOp<cir::ConstantOp>();
3346 auto constValue = definingOp.getValueAttr<cir::BoolAttr>();
3356 if (mlir::isa<cir::BoolType>(op.getTrueValue().getType())) {
3357 cir::BoolAttr trueValue = getConstantBool(op.getTrueValue());
3358 cir::BoolAttr falseValue = getConstantBool(op.getFalseValue());
3359 if (falseValue && !falseValue.getValue()) {
3361 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(op, adaptor.getCondition(),
3362 adaptor.getTrueValue());
3363 return mlir::success();
3365 if (trueValue && trueValue.getValue()) {
3367 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(op, adaptor.getCondition(),
3368 adaptor.getFalseValue());
3369 return mlir::success();
3373 mlir::Value llvmCondition = adaptor.getCondition();
3374 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(
3375 op, llvmCondition, adaptor.getTrueValue(), adaptor.getFalseValue());
3377 return mlir::success();
3381 mlir::DataLayout &dataLayout) {
3382 converter.addConversion([&](cir::PointerType type) -> mlir::Type {
3383 mlir::ptr::MemorySpaceAttrInterface addrSpaceAttr = type.getAddrSpace();
3384 unsigned numericAS = 0;
3386 if (
auto targetAsAttr =
3387 mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
3389 numericAS = targetAsAttr.getValue();
3390 return mlir::LLVM::LLVMPointerType::get(type.getContext(), numericAS);
3392 converter.addConversion([&](cir::VPtrType type) -> mlir::Type {
3394 return mlir::LLVM::LLVMPointerType::get(type.getContext());
3396 converter.addConversion([&](cir::ArrayType type) -> mlir::Type {
3399 return mlir::LLVM::LLVMArrayType::get(ty, type.getSize());
3401 converter.addConversion([&](cir::VectorType type) -> mlir::Type {
3402 const mlir::Type ty = converter.convertType(type.getElementType());
3403 return mlir::VectorType::get(type.getSize(), ty, {type.getIsScalable()});
3405 converter.addConversion([&](cir::BoolType type) -> mlir::Type {
3406 return mlir::IntegerType::get(type.getContext(), 1,
3407 mlir::IntegerType::Signless);
3409 converter.addConversion([&](cir::IntType type) -> mlir::Type {
3411 return mlir::IntegerType::get(type.getContext(), type.getWidth());
3413 converter.addConversion([&](cir::SingleType type) -> mlir::Type {
3414 return mlir::Float32Type::get(type.getContext());
3416 converter.addConversion([&](cir::DoubleType type) -> mlir::Type {
3417 return mlir::Float64Type::get(type.getContext());
3419 converter.addConversion([&](cir::FP80Type type) -> mlir::Type {
3420 return mlir::Float80Type::get(type.getContext());
3422 converter.addConversion([&](cir::FP128Type type) -> mlir::Type {
3423 return mlir::Float128Type::get(type.getContext());
3425 converter.addConversion([&](cir::LongDoubleType type) -> mlir::Type {
3426 return converter.convertType(type.getUnderlying());
3428 converter.addConversion([&](cir::FP16Type type) -> mlir::Type {
3429 return mlir::Float16Type::get(type.getContext());
3431 converter.addConversion([&](cir::BF16Type type) -> mlir::Type {
3432 return mlir::BFloat16Type::get(type.getContext());
3434 converter.addConversion([&](cir::ComplexType type) -> mlir::Type {
3437 mlir::Type elementTy = converter.convertType(type.getElementType());
3438 mlir::Type structFields[2] = {elementTy, elementTy};
3439 return mlir::LLVM::LLVMStructType::getLiteral(type.getContext(),
3442 converter.addConversion([&](cir::FuncType type) -> std::optional<mlir::Type> {
3443 auto result = converter.convertType(type.getReturnType());
3445 arguments.reserve(type.getNumInputs());
3446 if (converter.convertTypes(type.getInputs(), arguments).failed())
3447 return std::nullopt;
3448 auto varArg = type.isVarArg();
3449 return mlir::LLVM::LLVMFunctionType::get(result, arguments, varArg);
3451 converter.addConversion([&](cir::StructType type) -> mlir::Type {
3453 for (mlir::Type ty : type.getMembers())
3456 mlir::LLVM::LLVMStructType llvmStruct;
3457 if (type.getName()) {
3458 llvmStruct = mlir::LLVM::LLVMStructType::getIdentified(
3459 type.getContext(), type.getPrefixedName());
3460 if (llvmStruct.setBody(llvmMembers, type.getPacked()).failed())
3461 llvm_unreachable(
"Failed to set body of record");
3463 llvmStruct = mlir::LLVM::LLVMStructType::getLiteral(
3464 type.getContext(), llvmMembers, type.getPacked());
3469 converter.addConversion([&](cir::UnionType type) -> mlir::Type {
3471 if (!type.getMembers().empty())
3472 if (
auto storage = type.getUnionStorageType(dataLayout))
3473 llvmMembers.push_back(
3475 if (mlir::Type pad = type.getPadding())
3478 mlir::LLVM::LLVMStructType llvmStruct;
3479 if (type.getName()) {
3480 llvmStruct = mlir::LLVM::LLVMStructType::getIdentified(
3481 type.getContext(), type.getPrefixedName());
3482 if (llvmStruct.setBody(llvmMembers, type.getPacked()).failed())
3483 llvm_unreachable(
"Failed to set body of record");
3485 llvmStruct = mlir::LLVM::LLVMStructType::getLiteral(
3486 type.getContext(), llvmMembers, type.getPacked());
3490 converter.addConversion([&](cir::VoidType type) -> mlir::Type {
3491 return mlir::LLVM::LLVMVoidType::get(type.getContext());
3496 mlir::ModuleOp module, StringRef globalXtorName, StringRef llvmXtorName,
3497 llvm::function_ref<std::pair<StringRef, int>(mlir::Attribute)> createXtor) {
3499 for (
const mlir::NamedAttribute namedAttr : module->getAttrs()) {
3500 if (namedAttr.getName() == globalXtorName) {
3501 for (
auto attr : mlir::cast<mlir::ArrayAttr>(namedAttr.getValue()))
3502 globalXtors.emplace_back(createXtor(attr));
3507 if (globalXtors.empty())
3510 mlir::OpBuilder builder(module.getContext());
3511 builder.setInsertionPointToEnd(&module.getBodyRegion().back());
3515 auto ctorPFTy = mlir::LLVM::LLVMPointerType::get(builder.getContext());
3517 ctorStructFields.push_back(builder.getI32Type());
3518 ctorStructFields.push_back(ctorPFTy);
3519 ctorStructFields.push_back(ctorPFTy);
3521 auto ctorStructTy = mlir::LLVM::LLVMStructType::getLiteral(
3522 builder.getContext(), ctorStructFields);
3523 auto ctorStructArrayTy =
3524 mlir::LLVM::LLVMArrayType::get(ctorStructTy, globalXtors.size());
3526 mlir::Location loc =
module.getLoc();
3527 auto newGlobalOp = mlir::LLVM::GlobalOp::create(
3528 builder, loc, ctorStructArrayTy,
false,
3529 mlir::LLVM::Linkage::Appending, llvmXtorName, mlir::Attribute());
3531 builder.createBlock(&newGlobalOp.getRegion());
3532 builder.setInsertionPointToEnd(newGlobalOp.getInitializerBlock());
3534 mlir::Value result =
3535 mlir::LLVM::UndefOp::create(builder, loc, ctorStructArrayTy);
3537 for (
auto [index, fn] : llvm::enumerate(globalXtors)) {
3538 mlir::Value structInit =
3539 mlir::LLVM::UndefOp::create(builder, loc, ctorStructTy);
3540 mlir::Value initPriority = mlir::LLVM::ConstantOp::create(
3541 builder, loc, ctorStructFields[0], fn.second);
3542 mlir::Value initFuncAddr = mlir::LLVM::AddressOfOp::create(
3543 builder, loc, ctorStructFields[1], fn.first);
3544 mlir::Value initAssociate =
3545 mlir::LLVM::ZeroOp::create(builder, loc, ctorStructFields[2]);
3548 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
3549 initPriority, zero);
3550 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
3553 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
3555 result = mlir::LLVM::InsertValueOp::create(builder, loc, result, structInit,
3559 mlir::LLVM::ReturnOp::create(builder, loc, result);
3562mlir::LogicalResult CIRToLLVMObjSizeOpLowering::matchAndRewrite(
3563 cir::ObjSizeOp op, OpAdaptor adaptor,
3564 mlir::ConversionPatternRewriter &rewriter)
const {
3565 mlir::Type llvmResTy = getTypeConverter()->convertType(op.getType());
3566 mlir::Location loc = op->getLoc();
3568 mlir::IntegerType i1Ty = rewriter.getI1Type();
3570 auto i1Val = [&rewriter, &loc, &i1Ty](
bool val) {
3571 return mlir::LLVM::ConstantOp::create(rewriter, loc, i1Ty, val);
3578 i1Val(op.getNullunknown()),
3579 i1Val(op.getDynamic()),
3582 return mlir::LogicalResult::success();
3590constexpr StringRef llvmMetadataSectionName =
"llvm.metadata";
3595getOrCreateAnnotationStringGlobal(mlir::OpBuilder &builder, mlir::Location loc,
3596 mlir::ModuleOp module, llvm::StringRef str,
3597 llvm::StringMap<mlir::LLVM::GlobalOp> &cache,
3599 auto it = cache.find(str);
3600 if (it != cache.end())
3603 auto i8Ty = mlir::IntegerType::get(module.getContext(), 8);
3604 auto arrayTy = mlir::LLVM::LLVMArrayType::get(i8Ty, str.size() + 1);
3605 std::string
name =
".str";
3607 name +=
"." + std::to_string(cache.size());
3608 name +=
".annotation";
3612 mlir::LLVM::GlobalOp strGlobal = mlir::LLVM::GlobalOp::create(
3613 builder, loc, arrayTy,
true, mlir::LLVM::Linkage::Private,
3614 name, mlir::StringAttr::get(module.getContext(), std::string(str) +
'\0'),
3617 strGlobal.setSection(llvmMetadataSectionName);
3618 strGlobal.setUnnamedAddr(mlir::LLVM::UnnamedAddr::Global);
3619 strGlobal.setDsoLocal(
true);
3620 cache[str] = strGlobal;
3626mlir::LLVM::GlobalOp getOrCreateAnnotationArgsVar(
3627 mlir::OpBuilder &builder, mlir::Location loc, mlir::ModuleOp module,
3628 mlir::ArrayAttr argsAttr,
3629 llvm::StringMap<mlir::LLVM::GlobalOp> &argStringCache,
3630 llvm::MapVector<mlir::ArrayAttr, mlir::LLVM::GlobalOp> &argsCache) {
3631 auto it = argsCache.find(argsAttr);
3632 if (it != argsCache.end())
3635 auto ptrTy = mlir::LLVM::LLVMPointerType::get(builder.getContext());
3637 llvm::SmallVector<mlir::Type> fieldTypes;
3638 for (mlir::Attribute arg : argsAttr) {
3639 if (mlir::isa<mlir::StringAttr>(arg))
3640 fieldTypes.push_back(ptrTy);
3641 else if (
auto intAttr = mlir::dyn_cast<mlir::IntegerAttr>(arg))
3642 fieldTypes.push_back(intAttr.getType());
3644 llvm_unreachable(
"Unsupported annotation arg type");
3648 mlir::LLVM::LLVMStructType::getLiteral(builder.getContext(), fieldTypes);
3649 std::string
name =
".args";
3650 if (!argsCache.empty())
3651 name +=
"." + std::to_string(argsCache.size());
3652 name +=
".annotation";
3654 mlir::LLVM::GlobalOp argsGlobal = mlir::LLVM::GlobalOp::create(
3655 builder, loc, structTy,
true, mlir::LLVM::Linkage::Private,
3656 name, mlir::Attribute());
3657 argsGlobal.setSection(llvmMetadataSectionName);
3658 argsGlobal.setUnnamedAddr(mlir::LLVM::UnnamedAddr::Global);
3659 argsGlobal.setDsoLocal(
true);
3662 argsGlobal.getRegion().push_back(
new mlir::Block());
3663 mlir::OpBuilder initBuilder(module.getContext());
3664 initBuilder.setInsertionPointToEnd(argsGlobal.getInitializerBlock());
3666 mlir::Value structInit =
3667 mlir::LLVM::UndefOp::create(initBuilder, loc, structTy);
3668 for (
auto [idx, arg] : llvm::enumerate(argsAttr)) {
3669 if (
auto strArg = mlir::dyn_cast<mlir::StringAttr>(arg)) {
3670 mlir::LLVM::GlobalOp strGlobal = getOrCreateAnnotationStringGlobal(
3671 builder, loc, module, strArg.getValue(), argStringCache,
3673 mlir::LLVM::AddressOfOp strAddr = mlir::LLVM::AddressOfOp::create(
3674 initBuilder, loc, ptrTy, strGlobal.getSymName());
3675 structInit = mlir::LLVM::InsertValueOp::create(initBuilder, loc,
3676 structInit, strAddr, idx);
3677 }
else if (
auto intArg = mlir::dyn_cast<mlir::IntegerAttr>(arg)) {
3678 mlir::LLVM::ConstantOp intConst = mlir::LLVM::ConstantOp::create(
3679 initBuilder, loc, intArg.getType(), intArg.getValue());
3680 structInit = mlir::LLVM::InsertValueOp::create(initBuilder, loc,
3681 structInit, intConst, idx);
3683 llvm_unreachable(
"Unsupported annotation arg type");
3686 mlir::LLVM::ReturnOp::create(initBuilder, loc, structInit);
3688 argsCache[argsAttr] = argsGlobal;
3694std::pair<llvm::StringRef, unsigned> extractFileLine(mlir::Location loc) {
3695 mlir::Location resolved = loc;
3696 if (
auto fused = mlir::dyn_cast<mlir::FusedLoc>(resolved)) {
3697 if (!fused.getLocations().empty())
3698 resolved = fused.getLocations()[0];
3700 if (
auto fl = mlir::dyn_cast<mlir::FileLineColLoc>(resolved))
3701 return {fl.getFilename().getValue(), fl.getLine()};
3707 auto handleArray = [&](mlir::StringAttr symName, mlir::ArrayAttr arr,
3708 mlir::Location loc) {
3711 for (mlir::Attribute a : arr)
3712 if (
auto annot = mlir::dyn_cast<cir::AnnotationAttr>(a))
3713 collectedAnnotations.emplace_back(symName, annot, loc);
3718 module.walk([&](cir::GlobalOp op) {
3719 handleArray(op.getSymNameAttr(), op.getAnnotationsAttr(), op.getLoc());
3721 module.walk([&](cir::FuncOp op) {
3722 handleArray(op.getSymNameAttr(), op.getAnnotationsAttr(), op.getLoc());
3727 if (collectedAnnotations.empty())
3730 mlir::MLIRContext *ctx =
module.getContext();
3731 mlir::OpBuilder builder(ctx);
3732 builder.setInsertionPointToEnd(&module.getBodyRegion().back());
3734 auto ptrTy = mlir::LLVM::LLVMPointerType::get(ctx);
3735 auto i32Ty = builder.getI32Type();
3738 auto entryTy = mlir::LLVM::LLVMStructType::getLiteral(
3739 ctx, {ptrTy, ptrTy, ptrTy, i32Ty, ptrTy});
3741 mlir::LLVM::LLVMArrayType::get(entryTy, collectedAnnotations.size());
3743 mlir::Location moduleLoc =
module.getLoc();
3744 auto annotationsGlobal = mlir::LLVM::GlobalOp::create(
3745 builder, moduleLoc, arrayTy,
false,
3746 mlir::LLVM::Linkage::Appending,
"llvm.global.annotations",
3748 annotationsGlobal.setSection(llvmMetadataSectionName);
3752 mlir::OpBuilder constsBuilder(ctx);
3753 constsBuilder.setInsertionPoint(annotationsGlobal);
3755 llvm::StringMap<mlir::LLVM::GlobalOp> stringCache;
3756 llvm::StringMap<mlir::LLVM::GlobalOp> argStringCache;
3757 llvm::MapVector<mlir::ArrayAttr, mlir::LLVM::GlobalOp> argsCache;
3760 annotationsGlobal.getRegion().push_back(
new mlir::Block());
3761 mlir::OpBuilder initBuilder(ctx);
3762 initBuilder.setInsertionPointToEnd(annotationsGlobal.getInitializerBlock());
3764 mlir::Value arrayVal =
3765 mlir::LLVM::UndefOp::create(initBuilder, moduleLoc, arrayTy);
3767 for (
auto [idx, entry] : llvm::enumerate(collectedAnnotations)) {
3768 mlir::Value entryVal =
3769 mlir::LLVM::UndefOp::create(initBuilder, moduleLoc, entryTy);
3774 mlir::LLVM::AddressOfOp symAddr = mlir::LLVM::AddressOfOp::create(
3775 initBuilder, moduleLoc, ptrTy, entry.symName.getValue());
3776 entryVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
3777 entryVal, symAddr, zero);
3780 mlir::LLVM::GlobalOp nameGlobal = getOrCreateAnnotationStringGlobal(
3781 constsBuilder, moduleLoc, module, entry.annotation.getName().getValue(),
3782 stringCache,
false);
3783 mlir::LLVM::AddressOfOp nameAddr = mlir::LLVM::AddressOfOp::create(
3784 initBuilder, moduleLoc, ptrTy, nameGlobal.getSymName());
3785 entryVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
3786 entryVal, nameAddr, 1);
3789 auto [filename, line] = extractFileLine(entry.loc);
3790 mlir::LLVM::GlobalOp fileGlobal = getOrCreateAnnotationStringGlobal(
3791 constsBuilder, moduleLoc, module, filename, stringCache,
3793 mlir::LLVM::AddressOfOp fileAddr = mlir::LLVM::AddressOfOp::create(
3794 initBuilder, moduleLoc, ptrTy, fileGlobal.getSymName());
3795 entryVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
3796 entryVal, fileAddr, 2);
3797 mlir::LLVM::ConstantOp lineConst =
3798 mlir::LLVM::ConstantOp::create(initBuilder, moduleLoc, i32Ty, line);
3799 entryVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
3800 entryVal, lineConst, 3);
3803 mlir::ArrayAttr args = entry.annotation.getArgs();
3804 mlir::Value argsField;
3805 if (!args || args.empty()) {
3806 argsField = mlir::LLVM::ZeroOp::create(initBuilder, moduleLoc, ptrTy);
3808 mlir::LLVM::GlobalOp argsGlobal = getOrCreateAnnotationArgsVar(
3809 constsBuilder, moduleLoc, module, args, argStringCache, argsCache);
3810 argsField = mlir::LLVM::AddressOfOp::create(initBuilder, moduleLoc, ptrTy,
3811 argsGlobal.getSymName());
3813 entryVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
3814 entryVal, argsField, 4);
3816 arrayVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
3817 arrayVal, entryVal, idx);
3820 mlir::LLVM::ReturnOp::create(initBuilder, moduleLoc, arrayVal);
3826 mlir::ModuleOp module = getOperation();
3827 mlir::OpBuilder opBuilder(module.getContext());
3828 for (
auto &[blockAddOp, blockInfo] :
3830 mlir::LLVM::BlockTagOp resolvedLabel =
3832 assert(resolvedLabel &&
"expected BlockTagOp to already be emitted");
3833 mlir::FlatSymbolRefAttr fnSym = blockInfo.getFunc();
3834 auto blkAddTag = mlir::LLVM::BlockAddressAttr::get(
3835 opBuilder.getContext(), fnSym, resolvedLabel.getTagAttr());
3836 blockAddOp.setBlockAddrAttr(blkAddTag);
3843 if (mlir::Attribute tripleAttr =
3844 module->getAttr(cir::CIRDialect::getTripleAttrName()))
3845 module->setAttr(mlir::LLVM::LLVMDialect::getTargetTripleAttrName(),
3848 if (mlir::Attribute asmAttr =
3849 module->getAttr(cir::CIRDialect::getModuleLevelAsmAttrName()))
3850 module->setAttr(mlir::LLVM::LLVMDialect::getModuleLevelAsmAttrName(),
3855 llvm::TimeTraceScope scope(
"Convert CIR to LLVM Pass");
3857 mlir::ModuleOp module = getOperation();
3858 mlir::DataLayout dl(module);
3859 mlir::LLVMTypeConverter converter(&getContext());
3869 mlir::SymbolTableCollection symbolTables;
3870 mlir::RewritePatternSet patterns(&getContext());
3871 patterns.add<CIRToLLVMBlockAddressOpLowering, CIRToLLVMGlobalOpLowering,
3872 CIRToLLVMLabelOpLowering>(converter, patterns.getContext(), dl,
3874 patterns.add<CIRToLLVMCallOpLowering, CIRToLLVMTryCallOpLowering>(
3875 converter, patterns.getContext(), dl, symbolTables);
3878#define GET_LLVM_LOWERING_PATTERNS_LIST
3879#include "clang/CIR/Dialect/IR/CIRLowering.inc"
3880#undef GET_LLVM_LOWERING_PATTERNS_LIST
3881 >(converter, patterns.getContext(), dl);
3889 mlir::ConversionTarget target(getContext());
3890 target.addLegalOp<mlir::ModuleOp>();
3891 target.addLegalDialect<mlir::LLVM::LLVMDialect>();
3892 mlir::configureOpenMPToLLVMConversionLegality(target, converter);
3893 target.addLegalDialect<mlir::omp::OpenMPDialect>();
3894 mlir::populateOpenMPToLLVMConversionPatterns(converter, patterns);
3895 target.addIllegalDialect<mlir::BuiltinDialect, cir::CIRDialect,
3896 mlir::func::FuncDialect>();
3899 ops.push_back(module);
3902 if (failed(applyPartialConversion(ops, target, std::move(patterns))))
3903 signalPassFailure();
3907 "llvm.global_ctors", [](mlir::Attribute
attr) {
3908 auto ctorAttr = mlir::cast<cir::GlobalCtorAttr>(
attr);
3909 return std::make_pair(ctorAttr.getName(),
3910 ctorAttr.getPriority());
3914 "llvm.global_dtors", [](mlir::Attribute
attr) {
3915 auto dtorAttr = mlir::cast<cir::GlobalDtorAttr>(
attr);
3916 return std::make_pair(dtorAttr.getName(),
3917 dtorAttr.getPriority());
3925mlir::LogicalResult CIRToLLVMBrOpLowering::matchAndRewrite(
3926 cir::BrOp op, OpAdaptor adaptor,
3927 mlir::ConversionPatternRewriter &rewriter)
const {
3928 rewriter.replaceOpWithNewOp<mlir::LLVM::BrOp>(op, adaptor.getOperands(),
3930 return mlir::LogicalResult::success();
3933mlir::LogicalResult CIRToLLVMGetMemberOpLowering::matchAndRewrite(
3934 cir::GetMemberOp op, OpAdaptor adaptor,
3935 mlir::ConversionPatternRewriter &rewriter)
const {
3936 mlir::Type llResTy = getTypeConverter()->convertType(op.getType());
3937 mlir::Type pointee = op.getAddrTy().getPointee();
3939 if (mlir::isa<cir::UnionType>(pointee)) {
3942 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(op, llResTy,
3944 return mlir::success();
3947 auto structTy = mlir::cast<cir::StructType>(pointee);
3951 const mlir::Type elementTy = getTypeConverter()->convertType(structTy);
3956 mlir::LLVM::GEPNoWrapFlags flags =
3957 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
3958 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
3959 op, llResTy, elementTy, adaptor.getAddr(), offset, flags);
3960 return mlir::success();
3963mlir::LogicalResult CIRToLLVMExtractMemberOpLowering::matchAndRewrite(
3964 cir::ExtractMemberOp op, OpAdaptor adaptor,
3965 mlir::ConversionPatternRewriter &rewriter)
const {
3966 std::int64_t indices[1] = {
static_cast<std::int64_t
>(op.getIndex())};
3968 if (mlir::isa<cir::UnionType>(op.getRecord().getType())) {
3969 op.emitError(
"cir.extract_member cannot extract member from a union");
3970 return mlir::failure();
3973 rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractValueOp>(
3974 op, adaptor.getRecord(), indices);
3975 return mlir::success();
3978mlir::LogicalResult CIRToLLVMInsertMemberOpLowering::matchAndRewrite(
3979 cir::InsertMemberOp op, OpAdaptor adaptor,
3980 mlir::ConversionPatternRewriter &rewriter)
const {
3981 std::int64_t indecies[1] = {
static_cast<std::int64_t
>(op.getIndex())};
3983 if (mlir::isa<cir::UnionType>(op.getRecord().getType())) {
3984 op.emitError(
"cir.update_member cannot update member of a union");
3985 return mlir::failure();
3988 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
3989 op, adaptor.getRecord(), adaptor.getValue(), indecies);
3990 return mlir::success();
3994 mlir::Operation *srcOp, llvm::StringRef fnName,
3996 mlir::ArrayAttr argAttrs =
nullptr,
3997 mlir::ArrayAttr resAttrs =
nullptr) {
3998 mlir::ModuleOp modOp = srcOp->getParentOfType<mlir::ModuleOp>();
3999 mlir::Operation *sourceSymbol =
4000 mlir::SymbolTable::lookupSymbolIn(modOp, fnName);
4001 if (!sourceSymbol) {
4002 mlir::OpBuilder::InsertionGuard guard(rewriter);
4003 auto enclosingFnOp = srcOp->getParentOfType<mlir::LLVM::LLVMFuncOp>();
4004 rewriter.setInsertionPoint(enclosingFnOp);
4006 mlir::LLVM::LLVMFuncOp::create(rewriter, srcOp->getLoc(), fnName, fnTy);
4008 fn.setArgAttrsAttr(argAttrs);
4010 fn.setResAttrsAttr(resAttrs);
4014mlir::LogicalResult CIRToLLVMThrowOpLowering::matchAndRewrite(
4015 cir::ThrowOp op, OpAdaptor adaptor,
4016 mlir::ConversionPatternRewriter &rewriter)
const {
4017 mlir::Location loc = op.getLoc();
4018 auto voidTy = mlir::LLVM::LLVMVoidType::get(getContext());
4020 if (op.rethrows()) {
4021 auto funcTy = mlir::LLVM::LLVMFunctionType::get(voidTy, {});
4024 const llvm::StringRef functionName =
"__cxa_rethrow";
4025 createLLVMFuncOpIfNotExist(rewriter, op, functionName, funcTy);
4027 auto cxaRethrow = mlir::LLVM::CallOp::create(
4028 rewriter, loc, mlir::TypeRange{}, functionName);
4030 rewriter.replaceOp(op, cxaRethrow);
4031 return mlir::success();
4034 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4035 auto fnTy = mlir::LLVM::LLVMFunctionType::get(
4036 voidTy, {llvmPtrTy, llvmPtrTy, llvmPtrTy});
4039 const llvm::StringRef fnName =
"__cxa_throw";
4042 mlir::Value typeInfo = mlir::LLVM::AddressOfOp::create(
4043 rewriter, loc, mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
4044 adaptor.getTypeInfoAttr());
4048 dtor = mlir::LLVM::AddressOfOp::create(rewriter, loc, llvmPtrTy,
4049 adaptor.getDtorAttr());
4051 dtor = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmPtrTy);
4054 auto cxaThrowCall = mlir::LLVM::CallOp::create(
4055 rewriter, loc, mlir::TypeRange{}, fnName,
4056 mlir::ValueRange{adaptor.getExceptionPtr(), typeInfo, dtor});
4058 rewriter.replaceOp(op, cxaThrowCall);
4059 return mlir::success();
4062mlir::LogicalResult CIRToLLVMAllocExceptionOpLowering::matchAndRewrite(
4063 cir::AllocExceptionOp op, OpAdaptor adaptor,
4064 mlir::ConversionPatternRewriter &rewriter)
const {
4066 StringRef fnName =
"__cxa_allocate_exception";
4067 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4068 auto int64Ty = mlir::IntegerType::get(rewriter.getContext(), 64);
4069 auto fnTy = mlir::LLVM::LLVMFunctionType::get(llvmPtrTy, {int64Ty});
4072 auto exceptionSize = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
4073 adaptor.getSizeAttr());
4075 auto allocaExceptionCall = mlir::LLVM::CallOp::create(
4076 rewriter, op.getLoc(), mlir::TypeRange{llvmPtrTy}, fnName,
4077 mlir::ValueRange{exceptionSize});
4079 rewriter.replaceOp(op, allocaExceptionCall);
4080 return mlir::success();
4083static mlir::LLVM::LLVMStructType
4086 mlir::MLIRContext *ctx = rewriter.getContext();
4087 auto llvmPtr = mlir::LLVM::LLVMPointerType::get(ctx);
4089 return mlir::LLVM::LLVMStructType::getLiteral(ctx, structFields);
4092mlir::LogicalResult CIRToLLVMEhInflightOpLowering::matchAndRewrite(
4093 cir::EhInflightOp op, OpAdaptor adaptor,
4094 mlir::ConversionPatternRewriter &rewriter)
const {
4095 auto llvmFn = op->getParentOfType<mlir::LLVM::LLVMFuncOp>();
4096 assert(llvmFn &&
"expected LLVM function parent");
4097 mlir::Block *entryBlock = &llvmFn.getRegion().front();
4098 assert(entryBlock->isEntryBlock());
4100 mlir::ArrayAttr catchListAttr = op.getCatchTypeListAttr();
4101 mlir::SmallVector<mlir::Value> catchSymAddrs;
4103 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4104 mlir::Location loc = op.getLoc();
4109 if (catchListAttr) {
4112 for (mlir::Attribute catchAttr : catchListAttr) {
4113 auto symAttr = cast<mlir::FlatSymbolRefAttr>(catchAttr);
4116 mlir::OpBuilder::InsertionGuard guard(rewriter);
4117 rewriter.setInsertionPointToStart(entryBlock);
4118 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
4119 rewriter, loc, llvmPtrTy, symAttr.getValue());
4120 catchSymAddrs.push_back(addrOp);
4127 if (op.getCatchAll() || (!catchListAttr && !op.getCleanup())) {
4128 mlir::OpBuilder::InsertionGuard guard(rewriter);
4129 rewriter.setInsertionPointToStart(entryBlock);
4130 mlir::Value nullOp = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmPtrTy);
4131 catchSymAddrs.push_back(nullOp);
4136 mlir::LLVM::LLVMStructType llvmLandingPadStructTy =
4138 auto landingPadOp = mlir::LLVM::LandingpadOp::create(
4139 rewriter, loc, llvmLandingPadStructTy, catchSymAddrs);
4144 if (op.getCleanup() && !op.getCatchAll())
4145 landingPadOp.setCleanup(
true);
4148 mlir::LLVM::ExtractValueOp::create(rewriter, loc, landingPadOp, 0);
4149 mlir::Value selector =
4150 mlir::LLVM::ExtractValueOp::create(rewriter, loc, landingPadOp, 1);
4151 rewriter.replaceOp(op, mlir::ValueRange{slot, selector});
4153 return mlir::success();
4156mlir::LogicalResult CIRToLLVMResumeFlatOpLowering::matchAndRewrite(
4157 cir::ResumeFlatOp op, OpAdaptor adaptor,
4158 mlir::ConversionPatternRewriter &rewriter)
const {
4163 mlir::Value poison = mlir::LLVM::PoisonOp::create(rewriter, op.getLoc(),
4164 llvmLandingPadStructTy);
4167 mlir::Value slot = mlir::LLVM::InsertValueOp::create(
4168 rewriter, op.getLoc(), poison, adaptor.getExceptionPtr(), slotIdx);
4171 mlir::Value selector = mlir::LLVM::InsertValueOp::create(
4172 rewriter, op.getLoc(), slot, adaptor.getTypeId(), selectorIdx);
4174 rewriter.replaceOpWithNewOp<mlir::LLVM::ResumeOp>(op, selector);
4175 return mlir::success();
4178mlir::LogicalResult CIRToLLVMEhTypeIdOpLowering::matchAndRewrite(
4179 cir::EhTypeIdOp op, OpAdaptor adaptor,
4180 mlir::ConversionPatternRewriter &rewriter)
const {
4181 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
4182 rewriter, op.getLoc(),
4183 mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
4184 op.getTypeSymAttr());
4185 rewriter.replaceOpWithNewOp<mlir::LLVM::EhTypeidForOp>(
4186 op, rewriter.getI32Type(), addrOp);
4187 return mlir::success();
4190mlir::LogicalResult CIRToLLVMEhSetjmpOpLowering::matchAndRewrite(
4191 cir::EhSetjmpOp op, OpAdaptor adaptor,
4192 mlir::ConversionPatternRewriter &rewriter)
const {
4193 mlir::Type returnType = typeConverter->convertType(op.getType());
4194 mlir::LLVM::CallIntrinsicOp newOp =
4196 returnType, adaptor.getEnv());
4197 rewriter.replaceOp(op, newOp);
4198 return mlir::success();
4201mlir::LogicalResult CIRToLLVMEhLongjmpOpLowering::matchAndRewrite(
4202 cir::EhLongjmpOp op, OpAdaptor adaptor,
4203 mlir::ConversionPatternRewriter &rewriter)
const {
4205 {}, adaptor.getOperands());
4206 return mlir::success();
4209mlir::LogicalResult CIRToLLVMTrapOpLowering::matchAndRewrite(
4210 cir::TrapOp op, OpAdaptor adaptor,
4211 mlir::ConversionPatternRewriter &rewriter)
const {
4212 mlir::Location loc = op->getLoc();
4213 rewriter.eraseOp(op);
4215 mlir::LLVM::Trap::create(rewriter, loc);
4220 mlir::LLVM::UnreachableOp::create(rewriter, loc);
4222 return mlir::success();
4227 mlir::ConversionPatternRewriter &rewriter,
4228 const mlir::TypeConverter *converter,
4229 mlir::FlatSymbolRefAttr nameAttr, mlir::Type &eltType) {
4230 auto module = op->getParentOfType<mlir::ModuleOp>();
4231 mlir::Operation *symbol = mlir::SymbolTable::lookupSymbolIn(module, nameAttr);
4232 if (
auto llvmSymbol = mlir::dyn_cast<mlir::LLVM::GlobalOp>(symbol)) {
4233 eltType = llvmSymbol.getType();
4234 }
else if (
auto cirSymbol = mlir::dyn_cast<cir::GlobalOp>(symbol)) {
4235 eltType = converter->convertType(cirSymbol.getSymType());
4237 op->emitError() <<
"unexpected symbol type for " << symbol;
4241 return mlir::LLVM::AddressOfOp::create(
4242 rewriter, op->getLoc(),
4243 mlir::LLVM::LLVMPointerType::get(op->getContext()), nameAttr.getValue());
4246mlir::LogicalResult CIRToLLVMVTableAddrPointOpLowering::matchAndRewrite(
4247 cir::VTableAddrPointOp op, OpAdaptor adaptor,
4248 mlir::ConversionPatternRewriter &rewriter)
const {
4249 const mlir::TypeConverter *converter = getTypeConverter();
4250 mlir::Type targetType = converter->convertType(op.getType());
4253 mlir::Value symAddr = getValueForVTableSymbol(op, rewriter, converter,
4254 op.getNameAttr(), eltType);
4256 return op.emitError() <<
"Unable to get value for vtable symbol";
4259 0, op.getAddressPointAttr().getIndex(),
4260 op.getAddressPointAttr().getOffset()};
4262 assert(eltType &&
"Shouldn't ever be missing an eltType here");
4263 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
4264 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
4265 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, targetType, eltType,
4266 symAddr, offsets, inboundsNuw);
4267 return mlir::success();
4270mlir::LogicalResult CIRToLLVMVTableGetVPtrOpLowering::matchAndRewrite(
4271 cir::VTableGetVPtrOp op, OpAdaptor adaptor,
4272 mlir::ConversionPatternRewriter &rewriter)
const {
4276 mlir::Value srcVal = adaptor.getSrc();
4277 rewriter.replaceOp(op, srcVal);
4278 return mlir::success();
4281mlir::LogicalResult CIRToLLVMVTableGetVirtualFnAddrOpLowering::matchAndRewrite(
4282 cir::VTableGetVirtualFnAddrOp op, OpAdaptor adaptor,
4283 mlir::ConversionPatternRewriter &rewriter)
const {
4284 mlir::Type targetType = getTypeConverter()->convertType(op.getType());
4285 auto eltType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4288 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
4289 op, targetType, eltType, adaptor.getVptr(), offsets,
4290 mlir::LLVM::GEPNoWrapFlags::inbounds);
4291 return mlir::success();
4294mlir::LogicalResult CIRToLLVMVTTAddrPointOpLowering::matchAndRewrite(
4295 cir::VTTAddrPointOp op, OpAdaptor adaptor,
4296 mlir::ConversionPatternRewriter &rewriter)
const {
4297 const mlir::Type resultType = getTypeConverter()->convertType(op.getType());
4300 mlir::Value llvmAddr = adaptor.getSymAddr();
4302 if (op.getSymAddr()) {
4303 if (op.getOffset() == 0) {
4304 rewriter.replaceOp(op, {llvmAddr});
4305 return mlir::success();
4308 offsets.push_back(adaptor.getOffset());
4309 eltType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4312 op.getNameAttr(), eltType);
4313 assert(eltType &&
"Shouldn't ever be missing an eltType here");
4314 offsets.push_back(0);
4315 offsets.push_back(adaptor.getOffset());
4317 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
4318 op, resultType, eltType, llvmAddr, offsets,
4319 mlir::LLVM::GEPNoWrapFlags::inbounds);
4320 return mlir::success();
4323mlir::LogicalResult CIRToLLVMVecCreateOpLowering::matchAndRewrite(
4324 cir::VecCreateOp op, OpAdaptor adaptor,
4325 mlir::ConversionPatternRewriter &rewriter)
const {
4328 const auto vecTy = mlir::cast<cir::VectorType>(op.getType());
4329 const mlir::Type llvmTy = typeConverter->convertType(vecTy);
4330 const mlir::Location loc = op.getLoc();
4331 mlir::Value result = mlir::LLVM::PoisonOp::create(rewriter, loc, llvmTy);
4332 assert(vecTy.getSize() == op.getElements().size() &&
4333 "cir.vec.create op count doesn't match vector type elements count");
4335 for (uint64_t i = 0; i < vecTy.getSize(); ++i) {
4336 const mlir::Value indexValue =
4337 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
4338 result = mlir::LLVM::InsertElementOp::create(
4339 rewriter, loc, result, adaptor.getElements()[i], indexValue);
4342 rewriter.replaceOp(op, result);
4343 return mlir::success();
4346mlir::LogicalResult CIRToLLVMVecExtractOpLowering::matchAndRewrite(
4347 cir::VecExtractOp op, OpAdaptor adaptor,
4348 mlir::ConversionPatternRewriter &rewriter)
const {
4349 rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractElementOp>(
4350 op, adaptor.getVec(), adaptor.getIndex());
4351 return mlir::success();
4354mlir::LogicalResult CIRToLLVMVecInsertOpLowering::matchAndRewrite(
4355 cir::VecInsertOp op, OpAdaptor adaptor,
4356 mlir::ConversionPatternRewriter &rewriter)
const {
4357 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertElementOp>(
4358 op, adaptor.getVec(), adaptor.getValue(), adaptor.getIndex());
4359 return mlir::success();
4362mlir::LogicalResult CIRToLLVMVecCmpOpLowering::matchAndRewrite(
4363 cir::VecCmpOp op, OpAdaptor adaptor,
4364 mlir::ConversionPatternRewriter &rewriter)
const {
4365 mlir::Type elementType = elementTypeIfVector(op.getLhs().getType());
4366 mlir::Value bitResult;
4367 if (
auto intType = mlir::dyn_cast<cir::IntType>(elementType)) {
4368 bitResult = mlir::LLVM::ICmpOp::create(
4369 rewriter, op.getLoc(),
4371 adaptor.getLhs(), adaptor.getRhs());
4372 }
else if (mlir::isa<cir::FPTypeInterface>(elementType)) {
4373 bitResult = mlir::LLVM::FCmpOp::create(
4375 adaptor.getLhs(), adaptor.getRhs());
4377 return op.emitError() <<
"unsupported type for VecCmpOp: " << elementType;
4383 if (cast<cir::IntType>(cast<cir::VectorType>(op.getType()).getElementType())
4385 rewriter.replaceOpWithNewOp<mlir::LLVM::SExtOp>(
4386 op, typeConverter->convertType(op.getType()), bitResult);
4388 rewriter.replaceOp(op, bitResult);
4389 return mlir::success();
4392mlir::LogicalResult CIRToLLVMVecSplatOpLowering::matchAndRewrite(
4393 cir::VecSplatOp op, OpAdaptor adaptor,
4394 mlir::ConversionPatternRewriter &rewriter)
const {
4400 cir::VectorType vecTy = op.getType();
4401 mlir::Type llvmTy = typeConverter->convertType(vecTy);
4402 mlir::Location loc = op.getLoc();
4403 mlir::Value poison = mlir::LLVM::PoisonOp::create(rewriter, loc, llvmTy);
4405 mlir::Value elementValue = adaptor.getValue();
4406 if (elementValue.getDefiningOp<mlir::LLVM::PoisonOp>()) {
4409 rewriter.replaceOp(op, poison);
4410 return mlir::success();
4413 if (
auto constValue = elementValue.getDefiningOp<mlir::LLVM::ConstantOp>()) {
4414 if (
auto intAttr = dyn_cast<mlir::IntegerAttr>(constValue.getValue())) {
4415 mlir::DenseIntElementsAttr denseVec = mlir::DenseIntElementsAttr::get(
4416 mlir::cast<mlir::ShapedType>(llvmTy), intAttr.getValue());
4417 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
4418 op, denseVec.getType(), denseVec);
4419 return mlir::success();
4422 if (
auto fpAttr = dyn_cast<mlir::FloatAttr>(constValue.getValue())) {
4423 mlir::DenseFPElementsAttr denseVec = mlir::DenseFPElementsAttr::get(
4424 mlir::cast<mlir::ShapedType>(llvmTy), fpAttr.getValue());
4425 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
4426 op, denseVec.getType(), denseVec);
4427 return mlir::success();
4431 mlir::Value indexValue =
4432 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), 0);
4433 mlir::Value oneElement = mlir::LLVM::InsertElementOp::create(
4434 rewriter, loc, poison, elementValue, indexValue);
4436 rewriter.replaceOpWithNewOp<mlir::LLVM::ShuffleVectorOp>(op, oneElement,
4437 poison, zeroValues);
4438 return mlir::success();
4441mlir::LogicalResult CIRToLLVMVecShuffleOpLowering::matchAndRewrite(
4442 cir::VecShuffleOp op, OpAdaptor adaptor,
4443 mlir::ConversionPatternRewriter &rewriter)
const {
4449 op.getIndices().begin(), op.getIndices().end(),
4450 std::back_inserter(indices), [](mlir::Attribute intAttr) {
4451 return mlir::cast<cir::IntAttr>(intAttr).getValue().getSExtValue();
4453 rewriter.replaceOpWithNewOp<mlir::LLVM::ShuffleVectorOp>(
4454 op, adaptor.getVec1(), adaptor.getVec2(), indices);
4455 return mlir::success();
4458mlir::LogicalResult CIRToLLVMVecShuffleDynamicOpLowering::matchAndRewrite(
4459 cir::VecShuffleDynamicOp op, OpAdaptor adaptor,
4460 mlir::ConversionPatternRewriter &rewriter)
const {
4472 mlir::Location loc = op.getLoc();
4473 mlir::Value input = adaptor.getVec();
4474 mlir::Type llvmIndexVecType =
4475 getTypeConverter()->convertType(op.getIndices().getType());
4476 mlir::Type llvmIndexType = getTypeConverter()->convertType(
4477 elementTypeIfVector(op.getIndices().getType()));
4478 uint64_t numElements =
4479 mlir::cast<cir::VectorType>(op.getVec().getType()).getSize();
4481 uint64_t maskBits = llvm::NextPowerOf2(numElements - 1) - 1;
4482 mlir::Value maskValue = mlir::LLVM::ConstantOp::create(
4483 rewriter, loc, llvmIndexType,
4484 rewriter.getIntegerAttr(llvmIndexType, maskBits));
4485 mlir::Value maskVector =
4486 mlir::LLVM::UndefOp::create(rewriter, loc, llvmIndexVecType);
4488 for (uint64_t i = 0; i < numElements; ++i) {
4489 mlir::Value idxValue =
4490 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
4491 maskVector = mlir::LLVM::InsertElementOp::create(rewriter, loc, maskVector,
4492 maskValue, idxValue);
4495 mlir::Value maskedIndices = mlir::LLVM::AndOp::create(
4496 rewriter, loc, llvmIndexVecType, adaptor.getIndices(), maskVector);
4497 mlir::Value result = mlir::LLVM::UndefOp::create(
4498 rewriter, loc, getTypeConverter()->convertType(op.getVec().getType()));
4499 for (uint64_t i = 0; i < numElements; ++i) {
4500 mlir::Value iValue =
4501 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
4502 mlir::Value indexValue = mlir::LLVM::ExtractElementOp::create(
4503 rewriter, loc, maskedIndices, iValue);
4504 mlir::Value valueAtIndex =
4505 mlir::LLVM::ExtractElementOp::create(rewriter, loc, input, indexValue);
4506 result = mlir::LLVM::InsertElementOp::create(rewriter, loc, result,
4507 valueAtIndex, iValue);
4509 rewriter.replaceOp(op, result);
4510 return mlir::success();
4513mlir::LogicalResult CIRToLLVMVecTernaryOpLowering::matchAndRewrite(
4514 cir::VecTernaryOp op, OpAdaptor adaptor,
4515 mlir::ConversionPatternRewriter &rewriter)
const {
4517 mlir::Value bitVec = mlir::LLVM::ICmpOp::create(
4518 rewriter, op.getLoc(), mlir::LLVM::ICmpPredicate::ne, adaptor.getCond(),
4519 mlir::LLVM::ZeroOp::create(
4520 rewriter, op.getCond().getLoc(),
4521 typeConverter->convertType(op.getCond().getType())));
4522 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(
4523 op, bitVec, adaptor.getLhs(), adaptor.getRhs());
4524 return mlir::success();
4527mlir::LogicalResult CIRToLLVMComplexAddOpLowering::matchAndRewrite(
4528 cir::ComplexAddOp op, OpAdaptor adaptor,
4529 mlir::ConversionPatternRewriter &rewriter)
const {
4530 mlir::Value lhs = adaptor.getLhs();
4531 mlir::Value rhs = adaptor.getRhs();
4532 mlir::Location loc = op.getLoc();
4534 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
4535 mlir::Type complexElemTy =
4536 getTypeConverter()->convertType(
complexType.getElementType());
4537 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
4538 rewriter, loc, complexElemTy, lhs,
ArrayRef(int64_t{0}));
4539 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
4540 rewriter, loc, complexElemTy, lhs,
ArrayRef(int64_t{1}));
4541 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
4542 rewriter, loc, complexElemTy, rhs,
ArrayRef(int64_t{0}));
4543 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
4544 rewriter, loc, complexElemTy, rhs,
ArrayRef(int64_t{1}));
4546 mlir::Value newReal;
4547 mlir::Value newImag;
4548 if (complexElemTy.isInteger()) {
4549 newReal = mlir::LLVM::AddOp::create(rewriter, loc, complexElemTy, lhsReal,
4551 newImag = mlir::LLVM::AddOp::create(rewriter, loc, complexElemTy, lhsImag,
4556 newReal = mlir::LLVM::FAddOp::create(rewriter, loc, complexElemTy, lhsReal,
4558 newImag = mlir::LLVM::FAddOp::create(rewriter, loc, complexElemTy, lhsImag,
4562 mlir::Type complexLLVMTy =
4563 getTypeConverter()->convertType(op.getResult().getType());
4564 auto initialComplex =
4565 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), complexLLVMTy);
4567 auto realComplex = mlir::LLVM::InsertValueOp::create(
4568 rewriter, op->getLoc(), initialComplex, newReal,
ArrayRef(int64_t{0}));
4570 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
4571 op, realComplex, newImag,
ArrayRef(int64_t{1}));
4573 return mlir::success();
4576mlir::LogicalResult CIRToLLVMComplexCreateOpLowering::matchAndRewrite(
4577 cir::ComplexCreateOp op, OpAdaptor adaptor,
4578 mlir::ConversionPatternRewriter &rewriter)
const {
4579 mlir::Type complexLLVMTy =
4580 getTypeConverter()->convertType(op.getResult().getType());
4581 auto initialComplex =
4582 mlir::LLVM::UndefOp::create(rewriter, op->getLoc(), complexLLVMTy);
4584 auto realComplex = mlir::LLVM::InsertValueOp::create(
4585 rewriter, op->getLoc(), initialComplex, adaptor.getReal(),
4588 auto complex = mlir::LLVM::InsertValueOp::create(
4589 rewriter, op->getLoc(), realComplex, adaptor.getImag(),
4592 rewriter.replaceOp(op, complex);
4593 return mlir::success();
4596mlir::LogicalResult CIRToLLVMComplexRealOpLowering::matchAndRewrite(
4597 cir::ComplexRealOp op, OpAdaptor adaptor,
4598 mlir::ConversionPatternRewriter &rewriter)
const {
4599 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
4600 mlir::Value operand = adaptor.getOperand();
4601 if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) {
4602 operand = mlir::LLVM::ExtractValueOp::create(
4603 rewriter, op.getLoc(), resultLLVMTy, operand,
4606 rewriter.replaceOp(op, operand);
4607 return mlir::success();
4610mlir::LogicalResult CIRToLLVMComplexSubOpLowering::matchAndRewrite(
4611 cir::ComplexSubOp op, OpAdaptor adaptor,
4612 mlir::ConversionPatternRewriter &rewriter)
const {
4613 mlir::Value lhs = adaptor.getLhs();
4614 mlir::Value rhs = adaptor.getRhs();
4615 mlir::Location loc = op.getLoc();
4617 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
4618 mlir::Type complexElemTy =
4619 getTypeConverter()->convertType(
complexType.getElementType());
4620 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
4621 rewriter, loc, complexElemTy, lhs,
ArrayRef(int64_t{0}));
4622 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
4623 rewriter, loc, complexElemTy, lhs,
ArrayRef(int64_t{1}));
4624 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
4625 rewriter, loc, complexElemTy, rhs,
ArrayRef(int64_t{0}));
4626 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
4627 rewriter, loc, complexElemTy, rhs,
ArrayRef(int64_t{1}));
4629 mlir::Value newReal;
4630 mlir::Value newImag;
4631 if (complexElemTy.isInteger()) {
4632 newReal = mlir::LLVM::SubOp::create(rewriter, loc, complexElemTy, lhsReal,
4634 newImag = mlir::LLVM::SubOp::create(rewriter, loc, complexElemTy, lhsImag,
4639 newReal = mlir::LLVM::FSubOp::create(rewriter, loc, complexElemTy, lhsReal,
4641 newImag = mlir::LLVM::FSubOp::create(rewriter, loc, complexElemTy, lhsImag,
4645 mlir::Type complexLLVMTy =
4646 getTypeConverter()->convertType(op.getResult().getType());
4647 auto initialComplex =
4648 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), complexLLVMTy);
4650 auto realComplex = mlir::LLVM::InsertValueOp::create(
4651 rewriter, op->getLoc(), initialComplex, newReal,
ArrayRef(int64_t{0}));
4653 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
4654 op, realComplex, newImag,
ArrayRef(int64_t{1}));
4656 return mlir::success();
4659mlir::LogicalResult CIRToLLVMComplexImagOpLowering::matchAndRewrite(
4660 cir::ComplexImagOp op, OpAdaptor adaptor,
4661 mlir::ConversionPatternRewriter &rewriter)
const {
4662 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
4663 mlir::Value operand = adaptor.getOperand();
4664 mlir::Location loc = op.getLoc();
4666 if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) {
4667 operand = mlir::LLVM::ExtractValueOp::create(
4670 mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(resultLLVMTy);
4672 mlir::LLVM::ConstantOp::create(rewriter, loc, resultLLVMTy, zeroAttr);
4675 rewriter.replaceOp(op, operand);
4676 return mlir::success();
4680 mlir::MLIRContext *context,
4681 unsigned &storageSize) {
4682 return TypeSwitch<mlir::Type, mlir::IntegerType>(storageType)
4683 .Case<cir::ArrayType>([&](cir::ArrayType atTy) {
4684 storageSize = atTy.getSize() * 8;
4685 return mlir::IntegerType::get(context, storageSize);
4687 .Case<cir::IntType>([&](cir::IntType intTy) {
4688 storageSize = intTy.getWidth();
4689 return mlir::IntegerType::get(context, storageSize);
4691 .Default([](mlir::Type) -> mlir::IntegerType {
4693 "Either ArrayType or IntType expected for bitfields storage");
4697mlir::LogicalResult CIRToLLVMSetBitfieldOpLowering::matchAndRewrite(
4698 cir::SetBitfieldOp op, OpAdaptor adaptor,
4699 mlir::ConversionPatternRewriter &rewriter)
const {
4700 mlir::OpBuilder::InsertionGuard guard(rewriter);
4701 rewriter.setInsertionPoint(op);
4703 cir::BitfieldInfoAttr info = op.getBitfieldInfo();
4704 uint64_t size = info.getSize();
4705 uint64_t offset = info.getOffset();
4706 mlir::Type storageType = info.getStorageType();
4707 mlir::MLIRContext *context = storageType.getContext();
4709 unsigned storageSize = 0;
4711 mlir::IntegerType intType =
4712 computeBitfieldIntType(storageType, context, storageSize);
4714 mlir::Value srcVal = createIntCast(rewriter, adaptor.getSrc(), intType);
4715 unsigned srcWidth = storageSize;
4716 mlir::Value resultVal = srcVal;
4718 if (storageSize != size) {
4719 assert(storageSize > size &&
"Invalid bitfield size.");
4721 mlir::Value val = mlir::LLVM::LoadOp::create(
4722 rewriter, op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(),
4723 op.getIsVolatile());
4726 createAnd(rewriter, srcVal, llvm::APInt::getLowBitsSet(srcWidth, size));
4728 srcVal =
createShL(rewriter, srcVal, offset);
4732 ~llvm::APInt::getBitsSet(srcWidth, offset, offset + size));
4735 srcVal = mlir::LLVM::OrOp::create(rewriter, op.getLoc(), val, srcVal);
4738 mlir::LLVM::StoreOp::create(rewriter, op.getLoc(), srcVal, adaptor.getAddr(),
4739 op.getAlignment(), op.getIsVolatile());
4741 mlir::Type resultTy = getTypeConverter()->convertType(op.getType());
4743 if (info.getIsSigned()) {
4744 assert(size <= storageSize);
4745 unsigned highBits = storageSize - size;
4748 resultVal =
createShL(rewriter, resultVal, highBits);
4749 resultVal =
createAShR(rewriter, resultVal, highBits);
4754 mlir::cast<mlir::IntegerType>(resultTy),
4755 info.getIsSigned());
4757 rewriter.replaceOp(op, resultVal);
4758 return mlir::success();
4761mlir::LogicalResult CIRToLLVMComplexImagPtrOpLowering::matchAndRewrite(
4762 cir::ComplexImagPtrOp op, OpAdaptor adaptor,
4763 mlir::ConversionPatternRewriter &rewriter)
const {
4764 cir::PointerType operandTy = op.getOperand().getType();
4765 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
4766 mlir::Type elementLLVMTy =
4767 getTypeConverter()->convertType(operandTy.getPointee());
4769 mlir::LLVM::GEPArg gepIndices[2] = {{0}, {1}};
4770 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
4771 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
4772 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
4773 op, resultLLVMTy, elementLLVMTy, adaptor.getOperand(), gepIndices,
4775 return mlir::success();
4778mlir::LogicalResult CIRToLLVMComplexRealPtrOpLowering::matchAndRewrite(
4779 cir::ComplexRealPtrOp op, OpAdaptor adaptor,
4780 mlir::ConversionPatternRewriter &rewriter)
const {
4781 cir::PointerType operandTy = op.getOperand().getType();
4782 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
4783 mlir::Type elementLLVMTy =
4784 getTypeConverter()->convertType(operandTy.getPointee());
4786 mlir::LLVM::GEPArg gepIndices[2] = {0, 0};
4787 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
4788 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
4789 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
4790 op, resultLLVMTy, elementLLVMTy, adaptor.getOperand(), gepIndices,
4792 return mlir::success();
4795mlir::LogicalResult CIRToLLVMGetBitfieldOpLowering::matchAndRewrite(
4796 cir::GetBitfieldOp op, OpAdaptor adaptor,
4797 mlir::ConversionPatternRewriter &rewriter)
const {
4799 mlir::OpBuilder::InsertionGuard guard(rewriter);
4800 rewriter.setInsertionPoint(op);
4802 cir::BitfieldInfoAttr info = op.getBitfieldInfo();
4803 uint64_t size = info.getSize();
4804 uint64_t offset = info.getOffset();
4805 mlir::Type storageType = info.getStorageType();
4806 mlir::MLIRContext *context = storageType.getContext();
4807 unsigned storageSize = 0;
4809 mlir::IntegerType intType =
4812 mlir::Value val = mlir::LLVM::LoadOp::create(
4813 rewriter, op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(),
4814 op.getIsVolatile());
4815 val = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), intType, val);
4817 if (info.getIsSigned()) {
4818 assert(
static_cast<unsigned>(offset + size) <= storageSize);
4819 unsigned highBits = storageSize - offset - size;
4820 val =
createShL(rewriter, val, highBits);
4821 val =
createAShR(rewriter, val, offset + highBits);
4825 if (
static_cast<unsigned>(offset) + size < storageSize)
4827 llvm::APInt::getLowBitsSet(storageSize, size));
4830 mlir::Type resTy = getTypeConverter()->convertType(op.getType());
4832 rewriter, val, mlir::cast<mlir::IntegerType>(resTy), info.getIsSigned());
4833 rewriter.replaceOp(op, newOp);
4834 return mlir::success();
4837mlir::LogicalResult CIRToLLVMInlineAsmOpLowering::matchAndRewrite(
4838 cir::InlineAsmOp op, OpAdaptor adaptor,
4839 mlir::ConversionPatternRewriter &rewriter)
const {
4841 if (op.getNumResults())
4842 llResTy = getTypeConverter()->convertType(op.getType(0));
4844 cir::AsmFlavor dialect = op.getAsmFlavor();
4845 mlir::LLVM::AsmDialect llDialect = dialect == cir::AsmFlavor::x86_att
4846 ? mlir::LLVM::AsmDialect::AD_ATT
4847 : mlir::LLVM::AsmDialect::AD_Intel;
4850 StringRef llvmAttrName = mlir::LLVM::InlineAsmOp::getElementTypeAttrName();
4856 if (!op.getNumResults())
4857 opAttrs.push_back(mlir::Attribute());
4861 for (
auto const &[llvmOp, cirOp] :
4862 zip(adaptor.getAsmOperands(), op.getAsmOperands())) {
4863 append_range(llvmOperands, llvmOp);
4864 append_range(cirOperands, cirOp);
4869 for (
auto const &[cirOpAttr, cirOp] :
4870 zip(op.getOperandAttrs(), cirOperands)) {
4871 if (!mlir::isa<mlir::UnitAttr>(cirOpAttr)) {
4872 opAttrs.push_back(mlir::Attribute());
4877 cir::PointerType typ = mlir::cast<cir::PointerType>(cirOp.getType());
4879 *getTypeConverter(), dataLayout, typ.getPointee()));
4881 attrs.push_back(rewriter.getNamedAttr(llvmAttrName, typAttr));
4882 mlir::DictionaryAttr newDict = rewriter.getDictionaryAttr(attrs);
4883 opAttrs.push_back(newDict);
4886 rewriter.replaceOpWithNewOp<mlir::LLVM::InlineAsmOp>(
4887 op, llResTy, llvmOperands, op.getAsmStringAttr(), op.getConstraintsAttr(),
4888 op.getSideEffectsAttr(),
4891 mlir::LLVM::TailCallKindAttr::get(
4892 getContext(), mlir::LLVM::tailcallkind::TailCallKind::None),
4893 mlir::LLVM::AsmDialectAttr::get(getContext(), llDialect),
4894 rewriter.getArrayAttr(opAttrs));
4896 return mlir::success();
4899mlir::LogicalResult CIRToLLVMVAStartOpLowering::matchAndRewrite(
4900 cir::VAStartOp op, OpAdaptor adaptor,
4901 mlir::ConversionPatternRewriter &rewriter)
const {
4902 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4903 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4904 adaptor.getArgList());
4905 rewriter.replaceOpWithNewOp<mlir::LLVM::VaStartOp>(op, vaList);
4906 return mlir::success();
4909mlir::LogicalResult CIRToLLVMVAEndOpLowering::matchAndRewrite(
4910 cir::VAEndOp op, OpAdaptor adaptor,
4911 mlir::ConversionPatternRewriter &rewriter)
const {
4912 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4913 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4914 adaptor.getArgList());
4915 rewriter.replaceOpWithNewOp<mlir::LLVM::VaEndOp>(op, vaList);
4916 return mlir::success();
4919mlir::LogicalResult CIRToLLVMVACopyOpLowering::matchAndRewrite(
4920 cir::VACopyOp op, OpAdaptor adaptor,
4921 mlir::ConversionPatternRewriter &rewriter)
const {
4922 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4923 auto dstList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4924 adaptor.getDstList());
4925 auto srcList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4926 adaptor.getSrcList());
4927 rewriter.replaceOpWithNewOp<mlir::LLVM::VaCopyOp>(op, dstList, srcList);
4928 return mlir::success();
4931mlir::LogicalResult CIRToLLVMVAArgOpLowering::matchAndRewrite(
4932 cir::VAArgOp op, OpAdaptor adaptor,
4933 mlir::ConversionPatternRewriter &rewriter)
const {
4935 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4936 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4937 adaptor.getArgList());
4939 mlir::Type llvmType =
4940 getTypeConverter()->convertType(op->getResultTypes().front());
4942 return mlir::failure();
4944 rewriter.replaceOpWithNewOp<mlir::LLVM::VaArgOp>(op, llvmType, vaList);
4945 return mlir::success();
4948mlir::LogicalResult CIRToLLVMLabelOpLowering::matchAndRewrite(
4949 cir::LabelOp op, OpAdaptor adaptor,
4950 mlir::ConversionPatternRewriter &rewriter)
const {
4951 mlir::MLIRContext *ctx = rewriter.getContext();
4952 mlir::Block *block = op->getBlock();
4955 if (block->isEntryBlock()) {
4956 mlir::Block *newBlock =
4957 rewriter.splitBlock(op->getBlock(), mlir::Block::iterator(op));
4958 rewriter.setInsertionPointToEnd(block);
4959 mlir::LLVM::BrOp::create(rewriter, op.getLoc(), newBlock);
4962 mlir::LLVM::BlockTagAttr::get(ctx, blockInfoAddr.getTagIndex());
4963 rewriter.setInsertionPoint(op);
4966 mlir::LLVM::BlockTagOp::create(rewriter, op->getLoc(), tagAttr);
4967 mlir::LLVM::LLVMFuncOp func = op->getParentOfType<mlir::LLVM::LLVMFuncOp>();
4968 auto blockInfoAttr =
4969 cir::BlockAddrInfoAttr::get(ctx, func.getSymName(), op.getLabel());
4970 blockInfoAddr.mapBlockTag(blockInfoAttr, blockTagOp);
4971 rewriter.eraseOp(op);
4973 return mlir::success();
4976mlir::LogicalResult CIRToLLVMBlockAddressOpLowering::matchAndRewrite(
4977 cir::BlockAddressOp op, OpAdaptor adaptor,
4978 mlir::ConversionPatternRewriter &rewriter)
const {
4979 mlir::MLIRContext *ctx = rewriter.getContext();
4981 mlir::LLVM::BlockTagOp matchLabel =
4982 blockInfoAddr.lookupBlockTag(op.getBlockAddrInfoAttr());
4983 mlir::LLVM::BlockTagAttr tagAttr;
4990 tagAttr = matchLabel.getTag();
4992 auto blkAddr = mlir::LLVM::BlockAddressAttr::get(
4993 rewriter.getContext(), op.getBlockAddrInfoAttr().getFunc(), tagAttr);
4994 rewriter.setInsertionPoint(op);
4995 auto newOp = mlir::LLVM::BlockAddressOp::create(
4996 rewriter, op.getLoc(), mlir::LLVM::LLVMPointerType::get(ctx), blkAddr);
4998 blockInfoAddr.addUnresolvedBlockAddress(newOp, op.getBlockAddrInfoAttr());
4999 rewriter.replaceOp(op, newOp);
5000 return mlir::success();
5003mlir::LogicalResult CIRToLLVMIndirectBrOpLowering::matchAndRewrite(
5004 cir::IndirectBrOp op, OpAdaptor adaptor,
5005 mlir::ConversionPatternRewriter &rewriter)
const {
5007 mlir::Value targetAddr = adaptor.getAddr();
5015 if (op.getPoison()) {
5016 auto llvmPtrType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
5018 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), llvmPtrType);
5021 rewriter.replaceOpWithNewOp<mlir::LLVM::IndirectBrOp>(
5022 op, targetAddr, adaptor.getSuccOperands(), op.getSuccessors());
5023 return mlir::success();
5026mlir::LogicalResult CIRToLLVMAwaitOpLowering::matchAndRewrite(
5027 cir::AwaitOp op, OpAdaptor adaptor,
5028 mlir::ConversionPatternRewriter &rewriter)
const {
5029 return mlir::failure();
5032mlir::LogicalResult CIRToLLVMCpuIdOpLowering::matchAndRewrite(
5033 cir::CpuIdOp op, OpAdaptor adaptor,
5034 mlir::ConversionPatternRewriter &rewriter)
const {
5035 mlir::Type i32Ty = rewriter.getI32Type();
5036 mlir::Type i64Ty = rewriter.getI64Type();
5037 mlir::Type i32PtrTy = mlir::LLVM::LLVMPointerType::get(i32Ty.getContext(), 0);
5039 mlir::Type cpuidRetTy = mlir::LLVM::LLVMStructType::getLiteral(
5040 rewriter.getContext(), {i32Ty, i32Ty, i32Ty, i32Ty});
5042 mlir::Value functionId = adaptor.getFunctionId();
5043 mlir::Value subFunctionId = adaptor.getSubFunctionId();
5045 StringRef asmString, constraints;
5046 mlir::ModuleOp moduleOp = op->getParentOfType<mlir::ModuleOp>();
5047 llvm::Triple triple(
5048 mlir::cast<mlir::StringAttr>(
5049 moduleOp->getAttr(cir::CIRDialect::getTripleAttrName()))
5051 if (triple.getArch() == llvm::Triple::x86) {
5052 asmString =
"cpuid";
5053 constraints =
"={ax},={bx},={cx},={dx},{ax},{cx}";
5056 asmString =
"xchgq %rbx, ${1:q}\n"
5058 "xchgq %rbx, ${1:q}";
5059 constraints =
"={ax},=r,={cx},={dx},0,2";
5062 mlir::Value inlineAsm =
5063 mlir::LLVM::InlineAsmOp::create(
5064 rewriter, op.getLoc(), cpuidRetTy, {functionId, subFunctionId},
5065 rewriter.getStringAttr(asmString),
5066 rewriter.getStringAttr(constraints),
5069 mlir::LLVM::TailCallKindAttr{},
5070 mlir::LLVM::AsmDialectAttr{},
5074 mlir::Value basePtr = adaptor.getCpuInfo();
5076 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
5077 unsigned alignment = layout.getTypeABIAlignment(i32Ty);
5078 for (
unsigned i = 0; i < 4; i++) {
5079 mlir::Value extracted =
5080 mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(), inlineAsm, i)
5082 mlir::Value index = mlir::LLVM::ConstantOp::create(
5083 rewriter, op.getLoc(), i64Ty, rewriter.getI64IntegerAttr(i));
5085 mlir::Value storePtr = mlir::LLVM::GEPOp::create(
5086 rewriter, op.getLoc(), i32PtrTy, i32Ty, basePtr,
5087 gepIndices, mlir::LLVM::GEPNoWrapFlags::none)
5089 mlir::LLVM::StoreOp::create(rewriter, op.getLoc(), extracted, storePtr,
5093 rewriter.eraseOp(op);
5094 return mlir::success();
5097mlir::LogicalResult CIRToLLVMMemChrOpLowering::matchAndRewrite(
5098 cir::MemChrOp op, OpAdaptor adaptor,
5099 mlir::ConversionPatternRewriter &rewriter)
const {
5100 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
5101 mlir::Type srcTy = getTypeConverter()->convertType(op.getSrc().getType());
5102 mlir::Type patternTy =
5103 getTypeConverter()->convertType(op.getPattern().getType());
5104 mlir::Type lenTy = getTypeConverter()->convertType(op.getLen().getType());
5106 mlir::LLVM::LLVMFunctionType::get(llvmPtrTy, {srcTy, patternTy, lenTy},
5108 llvm::StringRef fnName =
"memchr";
5110 mlir::Builder b(rewriter.getContext());
5111 mlir::NamedAttribute noundefAttr =
5112 b.getNamedAttr(
"llvm.noundef", b.getUnitAttr());
5113 mlir::DictionaryAttr noundefDict = mlir::DictionaryAttr::get(
5116 mlir::ArrayAttr argAttrs =
5117 mlir::ArrayAttr::get(rewriter.getContext(), argAttrVec);
5121 mlir::LLVM::CallOp newCall = rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(
5122 op, mlir::TypeRange{llvmPtrTy}, fnName,
5123 mlir::ValueRange{adaptor.getSrc(), adaptor.getPattern(),
5125 newCall.setArgAttrsAttr(argAttrs);
5126 return mlir::success();
5130 return std::make_unique<ConvertCIRToLLVMPass>();
5135 pm.addPass(mlir::omp::createMarkDeclareTargetPass());
5139std::unique_ptr<llvm::Module>
5141 StringRef mlirSaveTempsOutFile,
5142 llvm::vfs::FileSystem *fs) {
5143 llvm::TimeTraceScope scope(
"lower from CIR to LLVM directly");
5145 mlir::MLIRContext *mlirCtx = mlirModule.getContext();
5147 mlir::PassManager pm(mlirCtx);
5150 (void)mlir::applyPassManagerCLOptions(pm);
5152 if (mlir::failed(pm.run(mlirModule))) {
5155 "The pass manager failed to lower CIR to LLVMIR dialect!");
5158 if (!mlirSaveTempsOutFile.empty()) {
5160 llvm::raw_fd_ostream out(mlirSaveTempsOutFile, ec);
5162 mlirModule->print(out);
5165 mlir::registerBuiltinDialectTranslation(*mlirCtx);
5166 mlir::registerLLVMDialectTranslation(*mlirCtx);
5167 mlir::registerOpenMPDialectTranslation(*mlirCtx);
5170 llvm::TimeTraceScope translateScope(
"translateModuleToLLVMIR");
5172 StringRef moduleName = mlirModule.getName().value_or(
"CIRToLLVMModule");
5173 std::unique_ptr<llvm::Module> llvmModule = mlir::translateModuleToLLVMIR(
5174 mlirModule, llvmCtx, moduleName,
false, fs);
5178 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.
mlir::Value createLShR(mlir::OpBuilder &bld, mlir::Value lhs, unsigned rhs)
mlir::Value createShL(mlir::OpBuilder &bld, mlir::Value lhs, unsigned rhs)
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, const mlir::TypeConverter *converter, mlir::ModuleOp moduleOp={})
std::optional< mlir::Attribute > lowerConstRecordAttr(cir::ConstRecordAttr constRecord, 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)
CIRAttrToValue(mlir::Operation *parentOp, mlir::ConversionPatternRewriter &rewriter, 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 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)
void createLLVMFuncOpIfNotExist(mlir::ConversionPatternRewriter &rewriter, mlir::Operation *srcOp, llvm::StringRef fnName, mlir::Type fnTy, mlir::ArrayAttr argAttrs=nullptr, mlir::ArrayAttr resAttrs=nullptr)
static mlir::Value getLLVMIntCast(mlir::ConversionPatternRewriter &rewriter, mlir::Value llvmSrc, mlir::Type llvmDstIntTy, bool isUnsigned, uint64_t cirSrcWidth, uint64_t cirDstIntWidth)
static mlir::Value emitFromMemory(mlir::ConversionPatternRewriter &rewriter, mlir::DataLayout const &dataLayout, cir::LoadOp op, mlir::Value value)
Emits the value from memory as expected by its users.
mlir::IntegerType computeBitfieldIntType(mlir::Type storageType, mlir::MLIRContext *context, unsigned &storageSize)
static mlir::LLVM::CallIntrinsicOp createCallLLVMIntrinsicOp(mlir::ConversionPatternRewriter &rewriter, mlir::Location loc, const llvm::Twine &intrinsicName, mlir::Type resultTy, mlir::ValueRange operands)
static mlir::LogicalResult lowerMinMaxOp(CIROp op, typename CIROp::Adaptor adaptor, mlir::ConversionPatternRewriter &rewriter)
static mlir::LLVM::LLVMStructType getLLVMLandingPadStructTy(mlir::ConversionPatternRewriter &rewriter)
static mlir::Value convertToIndexTy(mlir::ConversionPatternRewriter &rewriter, mlir::ModuleOp mod, mlir::Value index, mlir::Type baseTy, cir::IntType strideTy)
static mlir::LogicalResult lowerIntBinaryOp(CIROp op, mlir::Value lhs, mlir::Value rhs, mlir::ConversionPatternRewriter &rewriter)
Lower an integer Div/Rem op to its signed or unsigned LLVM counterpart.
static mlir::LLVM::CallIntrinsicOp replaceOpWithCallLLVMIntrinsicOp(mlir::ConversionPatternRewriter &rewriter, mlir::Operation *op, const llvm::Twine &intrinsicName, mlir::Type resultTy, mlir::ValueRange operands)
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 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 bool shouldPackFAMStruct(const mlir::DataLayout &dataLayout, llvm::ArrayRef< mlir::Type > members)
static mlir::LLVM::Visibility lowerCIRVisibilityToLLVMVisibility(cir::VisibilityKind visibilityKind)
static void lowerCallAttributes(cir::CIRCallOpInterface op, SmallVectorImpl< mlir::NamedAttribute > &result)
static uint64_t getTypeSize(mlir::Type type, mlir::Operation &op)
void populateCIRToLLVMPasses(mlir::OpPassManager &pm)
Adds passes that fully lower CIR to the LLVMIR dialect.
static llvm::StringLiteral getLLVMBinopForPostAtomic(cir::AtomicFetchKind k, bool isInt)
mlir::LLVM::Linkage convertLinkage(cir::GlobalLinkageKind linkage)
static void buildCtorDtorList(mlir::ModuleOp module, StringRef globalXtorName, StringRef llvmXtorName, llvm::function_ref< std::pair< StringRef, int >(mlir::Attribute)> createXtor)
static mlir::LogicalResult lowerBinOpOverflow(OpTy op, typename OpTy::Adaptor adaptor, mlir::ConversionPatternRewriter &rewriter, const mlir::TypeConverter *typeConverter, llvm::StringRef opStr)
Shared lowering logic for checked binary arithmetic overflow operations.
static mlir::Type convertTypeForMemory(const mlir::TypeConverter &converter, mlir::DataLayout const &dataLayout, mlir::Type type)
Given a type convertor and a data layout, convert the given type to a type that is suitable for memor...
static mlir::Value createIntCast(mlir::OpBuilder &bld, mlir::Value src, mlir::IntegerType dstTy, bool isSigned=false)
static mlir::LLVM::IntegerOverflowFlags nswFlag(bool nsw)
static mlir::Value getValueForVTableSymbol(mlir::Operation *op, mlir::ConversionPatternRewriter &rewriter, const mlir::TypeConverter *converter, mlir::FlatSymbolRefAttr nameAttr, mlir::Type &eltType)
static mlir::Value emitToMemory(mlir::ConversionPatternRewriter &rewriter, mlir::DataLayout const &dataLayout, mlir::Type origType, mlir::Value value)
Emits a value to memory with the expected scalar type.
static mlir::Type adjustGlobalTypeForFlexibleArrayInit(mlir::Type llvmType, mlir::Attribute init, const mlir::TypeConverter &converter, const mlir::DataLayout &dataLayout)
mlir::Value lowerCirAttrAsValue(mlir::Operation *parentOp, const mlir::Attribute attr, mlir::ConversionPatternRewriter &rewriter, const mlir::TypeConverter *converter, LLVMBlockAddressInfo *blockInfoAddr)
Switches on the type of attribute and calls the appropriate conversion.
std::unique_ptr< llvm::Module > lowerDirectlyFromCIRToLLVMIR(mlir::ModuleOp mlirModule, llvm::LLVMContext &llvmCtx, llvm::StringRef mlirSaveTempsOutFile={}, llvm::vfs::FileSystem *fs=nullptr)
static bool isIntTypeUnsigned(mlir::Type type)
void collectUnreachable(mlir::Operation *parent, llvm::SmallVectorImpl< mlir::Operation * > &ops)
Collect ops in blocks that are unreachable from their region's entry, appending them to ops.
llvm::Type * convertTypeForMemory(CodeGenModule &CGM, QualType T)
const internal::VariadicAllOfMatcher< Attr > attr
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const AstTypeMatcher< ComplexType > complexType
@ Default
Set to the current date and time.
Diagnostic wrappers for TextAPI types for error reporting.
void populateCIRPreLoweringPasses(mlir::OpPassManager &pm)
void registerCIRDialectTranslation(mlir::MLIRContext &context)
char __ovld __cnfn clz(char)
Returns the number of leading 0-bits in x, starting at the most significant bit position.
char __ovld __cnfn ctz(char)
Returns the count of trailing 0-bits in x.
float __ovld __cnfn sign(float)
Returns 1.0 if x > 0, -0.0 if x = -0.0, +0.0 if x = +0.0, or -1.0 if x < 0.
float __ovld __cnfn length(float)
Return the length of vector p, i.e., sqrt(p.x2 + p.y 2 + ...)
char __ovld __cnfn select(char, char, char)
For each component of a vector type, result[i] = if MSB of c[i] is set ?
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 __packed_splat2 __packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 uint32_t
static bool dataMemberType()
static bool addressSpace()
static bool globalViewIntLowering()
static bool opAllocaAnnotations()
static bool opLoadStoreTbaa()
static bool optInfoAttr()
static bool opFuncExtraAttrs()
static bool isPPC_FP128Ty()
static bool vaArgABILowering()
static bool fpConstraints()
static bool intrinsicElementTypeSupport()
static bool lowerModeOptLevel()
static bool opCallCallConv()
static bool aggValueSlotVolatile()
static bool fastMathFlags()
static bool llvmLoweringPtrDiffConsidersPointee()
static bool atomicSyncScopeID()
static bool opFuncMultipleReturnVals()
void collectGlobalAnnotations(mlir::ModuleOp module)
Collect (symbol_name, annotations, loc) from cir.func and cir.global ops before the conversion runs (...
void runOnOperation() final
StringRef getDescription() const override
StringRef getArgument() const override
void getDependentDialects(mlir::DialectRegistry ®istry) const override
void resolveBlockAddressOp(LLVMBlockAddressInfo &blockInfoAddr)
void buildGlobalAnnotationsVar(mlir::ModuleOp module)
Emit @llvm.global.annotations and supporting string/args constants from the previously-collected anno...
void processCIRAttrs(mlir::ModuleOp module)
mlir::LLVM::BlockTagOp lookupBlockTag(cir::BlockAddrInfoAttr info) const
void clearUnresolvedMap()
llvm::DenseMap< mlir::LLVM::BlockAddressOp, cir::BlockAddrInfoAttr > & getUnresolvedBlockAddress()