19#include "mlir/Conversion/LLVMCommon/TypeConverter.h"
20#include "mlir/Conversion/OpenMPToLLVM/ConvertOpenMPToLLVM.h"
21#include "mlir/Dialect/DLTI/DLTI.h"
22#include "mlir/Dialect/Func/IR/FuncOps.h"
23#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
24#include "mlir/Dialect/LLVMIR/LLVMTypes.h"
25#include "mlir/Dialect/OpenMP/OpenMPDialect.h"
26#include "mlir/Dialect/OpenMP/Transforms/Passes.h"
27#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
28#include "mlir/IR/BuiltinAttributes.h"
29#include "mlir/IR/BuiltinDialect.h"
30#include "mlir/IR/BuiltinOps.h"
31#include "mlir/IR/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"
47#include "llvm/ADT/MapVector.h"
48#include "llvm/ADT/StringMap.h"
49#include "llvm/ADT/TypeSwitch.h"
50#include "llvm/IR/Module.h"
51#include "llvm/Support/Casting.h"
52#include "llvm/Support/ErrorHandling.h"
53#include "llvm/Support/TimeProfiler.h"
54#include "llvm/Support/VirtualFileSystem.h"
55#include "llvm/Support/raw_ostream.h"
70mlir::Type elementTypeIfVector(mlir::Type type) {
71 return llvm::TypeSwitch<mlir::Type, mlir::Type>(type)
72 .Case<cir::VectorType, mlir::VectorType>(
73 [](
auto p) {
return p.getElementType(); })
74 .
Default([](mlir::Type p) {
return p; });
82 mlir::DataLayout
const &dataLayout,
86 if (isa<cir::BoolType>(type)) {
87 return mlir::IntegerType::get(type.getContext(),
88 dataLayout.getTypeSizeInBits(type));
91 return converter.convertType(type);
95 mlir::IntegerType dstTy,
96 bool isSigned =
false) {
97 mlir::Type srcTy = src.getType();
98 assert(mlir::isa<mlir::IntegerType>(srcTy));
100 unsigned srcWidth = mlir::cast<mlir::IntegerType>(srcTy).getWidth();
101 unsigned dstWidth = mlir::cast<mlir::IntegerType>(dstTy).getWidth();
102 mlir::Location loc = src.getLoc();
104 if (dstWidth > srcWidth && isSigned)
105 return mlir::LLVM::SExtOp::create(bld, loc, dstTy, src);
106 if (dstWidth > srcWidth)
107 return mlir::LLVM::ZExtOp::create(bld, loc, dstTy, src);
108 if (dstWidth < srcWidth)
109 return mlir::LLVM::TruncOp::create(bld, loc, dstTy, src);
110 return mlir::LLVM::BitcastOp::create(bld, loc, dstTy, src);
113static mlir::LLVM::Visibility
115 switch (visibilityKind) {
116 case cir::VisibilityKind::Default:
117 return ::mlir::LLVM::Visibility::Default;
118 case cir::VisibilityKind::Hidden:
119 return ::mlir::LLVM::Visibility::Hidden;
120 case cir::VisibilityKind::Protected:
121 return ::mlir::LLVM::Visibility::Protected;
129 mlir::DataLayout
const &dataLayout,
130 cir::LoadOp op, mlir::Value value) {
133 if (
auto boolTy = mlir::dyn_cast<cir::BoolType>(op.getType())) {
135 assert(value.getType().isInteger(dataLayout.getTypeSizeInBits(boolTy)));
145static mlir::Value
emitToMemory(mlir::ConversionPatternRewriter &rewriter,
146 mlir::DataLayout
const &dataLayout,
147 mlir::Type origType, mlir::Value value) {
150 if (
auto boolTy = mlir::dyn_cast<cir::BoolType>(origType)) {
152 mlir::IntegerType memType =
153 rewriter.getIntegerType(dataLayout.getTypeSizeInBits(boolTy));
161 using CIR = cir::GlobalLinkageKind;
162 using LLVM = mlir::LLVM::Linkage;
165 case CIR::AppendingLinkage:
166 return LLVM::Appending;
167 case CIR::AvailableExternallyLinkage:
168 return LLVM::AvailableExternally;
169 case CIR::CommonLinkage:
171 case CIR::ExternalLinkage:
172 return LLVM::External;
173 case CIR::ExternalWeakLinkage:
174 return LLVM::ExternWeak;
175 case CIR::InternalLinkage:
176 return LLVM::Internal;
177 case CIR::LinkOnceAnyLinkage:
178 return LLVM::Linkonce;
179 case CIR::LinkOnceODRLinkage:
180 return LLVM::LinkonceODR;
181 case CIR::PrivateLinkage:
182 return LLVM::Private;
183 case CIR::WeakAnyLinkage:
185 case CIR::WeakODRLinkage:
186 return LLVM::WeakODR;
188 llvm_unreachable(
"Unknown CIR linkage type");
192 using CIR = cir::CallingConv;
193 using LLVM = mlir::LLVM::CConv;
195 switch (callingConv) {
198 case CIR::SpirKernel:
199 return LLVM::SPIR_KERNEL;
200 case CIR::SpirFunction:
201 return LLVM::SPIR_FUNC;
203 return LLVM::PTX_Kernel;
204 case CIR::AMDGPUKernel:
205 return LLVM::AMDGPU_KERNEL;
207 llvm_unreachable(
"Unknown calling convention");
210mlir::LogicalResult CIRToLLVMCopyOpLowering::matchAndRewrite(
211 cir::CopyOp op, OpAdaptor adaptor,
212 mlir::ConversionPatternRewriter &rewriter)
const {
213 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
214 const mlir::Value
length = mlir::LLVM::ConstantOp::create(
215 rewriter, op.getLoc(), rewriter.getI64Type(),
216 op.getCopySizeInBytes(layout));
218 rewriter.replaceOpWithNewOp<mlir::LLVM::MemcpyOp>(
219 op, adaptor.getDst(), adaptor.getSrc(),
length, op.getIsVolatile());
220 return mlir::success();
223mlir::LogicalResult CIRToLLVMMemCpyOpLowering::matchAndRewrite(
224 cir::MemCpyOp op, OpAdaptor adaptor,
225 mlir::ConversionPatternRewriter &rewriter)
const {
226 rewriter.replaceOpWithNewOp<mlir::LLVM::MemcpyOp>(
227 op, adaptor.getDst(), adaptor.getSrc(), adaptor.getLen(),
229 return mlir::success();
232mlir::LogicalResult CIRToLLVMMemMoveOpLowering::matchAndRewrite(
233 cir::MemMoveOp op, OpAdaptor adaptor,
234 mlir::ConversionPatternRewriter &rewriter)
const {
235 rewriter.replaceOpWithNewOp<mlir::LLVM::MemmoveOp>(
236 op, adaptor.getDst(), adaptor.getSrc(), adaptor.getLen(),
238 return mlir::success();
241mlir::LogicalResult CIRToLLVMMemSetOpLowering::matchAndRewrite(
242 cir::MemSetOp op, OpAdaptor adaptor,
243 mlir::ConversionPatternRewriter &rewriter)
const {
245 auto memset = rewriter.replaceOpWithNewOp<mlir::LLVM::MemsetOp>(
246 op, adaptor.getDst(), adaptor.getVal(), adaptor.getLen(),
249 if (op.getAlignmentAttr()) {
251 llvm::SmallVector<mlir::Attribute> attrs{
memset.getNumOperands(),
252 rewriter.getDictionaryAttr({})};
253 llvm::SmallVector<mlir::NamedAttribute> destAttrs;
255 {mlir::LLVM::LLVMDialect::getAlignAttrName(), op.getAlignmentAttr()});
256 attrs[
memset.odsIndex_dst] = rewriter.getDictionaryAttr(destAttrs);
258 auto arrayAttr = rewriter.getArrayAttr(attrs);
259 memset.setArgAttrsAttr(arrayAttr);
262 return mlir::success();
266 mlir::Value llvmSrc, mlir::Type llvmDstIntTy,
268 uint64_t cirDstIntWidth) {
269 if (cirSrcWidth == cirDstIntWidth)
272 auto loc = llvmSrc.getLoc();
273 if (cirSrcWidth < cirDstIntWidth) {
275 return mlir::LLVM::ZExtOp::create(rewriter, loc, llvmDstIntTy, llvmSrc);
276 return mlir::LLVM::SExtOp::create(rewriter, loc, llvmDstIntTy, llvmSrc);
280 return mlir::LLVM::TruncOp::create(rewriter, loc, llvmDstIntTy, llvmSrc);
286 mlir::ConversionPatternRewriter &rewriter,
287 const mlir::TypeConverter *converter)
288 : parentOp(parentOp), rewriter(rewriter), converter(converter) {}
290#define GET_CIR_ATTR_TO_VALUE_VISITOR_DECLS
291#include "clang/CIR/Dialect/IR/CIRLowering.inc"
292#undef GET_CIR_ATTR_TO_VALUE_VISITOR_DECLS
295 mlir::Operation *parentOp;
296 mlir::ConversionPatternRewriter &rewriter;
297 const mlir::TypeConverter *converter;
302 const mlir::Attribute attr,
303 mlir::ConversionPatternRewriter &rewriter,
304 const mlir::TypeConverter *converter) {
306 mlir::Value value = valueConverter.visit(attr);
308 llvm_unreachable(
"unhandled attribute type");
313 cir::SideEffect sideEffect,
314 mlir::LLVM::MemoryEffectsAttr &memoryEffect,
315 bool &noUnwind,
bool &willReturn,
317 using mlir::LLVM::ModRefInfo;
319 switch (sideEffect) {
320 case cir::SideEffect::All:
322 noUnwind = isNothrow;
326 case cir::SideEffect::Pure:
327 memoryEffect = mlir::LLVM::MemoryEffectsAttr::get(
328 callOp->getContext(), ModRefInfo::Ref,
338 case cir::SideEffect::Const:
339 memoryEffect = mlir::LLVM::MemoryEffectsAttr::get(
340 callOp->getContext(), ModRefInfo::NoModRef,
341 ModRefInfo::NoModRef,
342 ModRefInfo::NoModRef,
343 ModRefInfo::NoModRef,
344 ModRefInfo::NoModRef,
345 ModRefInfo::NoModRef);
351 noReturn = callOp->hasAttr(CIRDialect::getNoReturnAttrName());
354static mlir::LLVM::CallIntrinsicOp
356 mlir::Location loc,
const llvm::Twine &intrinsicName,
357 mlir::Type resultTy, mlir::ValueRange operands) {
358 auto intrinsicNameAttr =
359 mlir::StringAttr::get(rewriter.getContext(), intrinsicName);
360 return mlir::LLVM::CallIntrinsicOp::create(rewriter, loc, resultTy,
361 intrinsicNameAttr, operands);
365 mlir::ConversionPatternRewriter &rewriter, mlir::Operation *op,
366 const llvm::Twine &intrinsicName, mlir::Type resultTy,
367 mlir::ValueRange operands) {
369 rewriter, op->getLoc(), intrinsicName, resultTy, operands);
370 rewriter.replaceOp(op, callIntrinOp.getOperation());
374mlir::LogicalResult CIRToLLVMLLVMIntrinsicCallOpLowering::matchAndRewrite(
375 cir::LLVMIntrinsicCallOp op, OpAdaptor adaptor,
376 mlir::ConversionPatternRewriter &rewriter)
const {
377 mlir::Type llvmResTy =
378 getTypeConverter()->convertType(op->getResultTypes()[0]);
380 return op.emitError(
"expected LLVM result type");
381 StringRef name = op.getIntrinsicName();
394 adaptor.getOperands());
395 return mlir::success();
399mlir::Value CIRAttrToValue::visitCirAttr(cir::BoolAttr boolAttr) {
400 mlir::Location loc = parentOp->getLoc();
401 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
402 mlir::Value boolVal = mlir::LLVM::ConstantOp::create(
403 rewriter, loc, converter->convertType(boolAttr.getType()),
404 boolAttr.getValue());
405 return emitToMemory(rewriter, layout, boolAttr.getType(), boolVal);
409mlir::Value CIRAttrToValue::visitCirAttr(cir::IntAttr intAttr) {
410 mlir::Location loc = parentOp->getLoc();
411 return mlir::LLVM::ConstantOp::create(
412 rewriter, loc, converter->convertType(intAttr.getType()),
417mlir::Value CIRAttrToValue::visitCirAttr(cir::FPAttr fltAttr) {
418 mlir::Location loc = parentOp->getLoc();
419 return mlir::LLVM::ConstantOp::create(
420 rewriter, loc, converter->convertType(fltAttr.getType()),
425mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstComplexAttr complexAttr) {
426 auto complexType = mlir::cast<cir::ComplexType>(complexAttr.getType());
427 mlir::Type complexElemTy =
complexType.getElementType();
428 mlir::Type complexElemLLVMTy = converter->convertType(complexElemTy);
430 mlir::Attribute components[2];
431 if (
const auto intType = mlir::dyn_cast<cir::IntType>(complexElemTy)) {
432 components[0] = rewriter.getIntegerAttr(
434 mlir::cast<cir::IntAttr>(complexAttr.getReal()).getValue());
435 components[1] = rewriter.getIntegerAttr(
437 mlir::cast<cir::IntAttr>(complexAttr.getImag()).getValue());
439 components[0] = rewriter.getFloatAttr(
441 mlir::cast<cir::FPAttr>(complexAttr.getReal()).getValue());
442 components[1] = rewriter.getFloatAttr(
444 mlir::cast<cir::FPAttr>(complexAttr.getImag()).getValue());
447 mlir::Location loc = parentOp->getLoc();
448 return mlir::LLVM::ConstantOp::create(
449 rewriter, loc, converter->convertType(complexAttr.getType()),
450 rewriter.getArrayAttr(components));
454mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstPtrAttr ptrAttr) {
455 mlir::Location loc = parentOp->getLoc();
456 if (ptrAttr.isNullValue()) {
457 return mlir::LLVM::ZeroOp::create(
458 rewriter, loc, converter->convertType(ptrAttr.getType()));
460 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
461 mlir::Value ptrVal = mlir::LLVM::ConstantOp::create(
463 rewriter.getIntegerType(layout.getTypeSizeInBits(ptrAttr.getType())),
464 ptrAttr.getValue().getInt());
465 return mlir::LLVM::IntToPtrOp::create(
466 rewriter, loc, converter->convertType(ptrAttr.getType()), ptrVal);
470mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstArrayAttr attr) {
471 mlir::Type llvmTy = converter->convertType(
attr.getType());
472 mlir::Location loc = parentOp->getLoc();
475 if (
attr.hasTrailingZeros()) {
476 mlir::Type arrayTy =
attr.getType();
477 result = mlir::LLVM::ZeroOp::create(rewriter, loc,
478 converter->convertType(arrayTy));
480 result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
484 if (
auto arrayAttr = mlir::dyn_cast<mlir::ArrayAttr>(
attr.getElts())) {
485 for (
auto [idx, elt] : llvm::enumerate(arrayAttr)) {
486 mlir::DataLayout dataLayout(parentOp->getParentOfType<mlir::ModuleOp>());
487 mlir::Value init = visit(elt);
489 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
491 }
else if (
auto strAttr = mlir::dyn_cast<mlir::StringAttr>(
attr.getElts())) {
494 auto arrayTy = mlir::dyn_cast<cir::ArrayType>(strAttr.getType());
495 assert(arrayTy &&
"String attribute must have an array type");
496 mlir::Type eltTy = arrayTy.getElementType();
497 for (
auto [idx, elt] : llvm::enumerate(strAttr)) {
498 auto init = mlir::LLVM::ConstantOp::create(
499 rewriter, loc, converter->convertType(eltTy), elt);
501 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
504 llvm_unreachable(
"unexpected ConstArrayAttr elements");
511mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstRecordAttr constRecord) {
512 const mlir::Type llvmTy = converter->convertType(constRecord.getType());
513 const mlir::Location loc = parentOp->getLoc();
514 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
517 for (
auto [idx, elt] : llvm::enumerate(constRecord.getMembers())) {
518 mlir::Value init = visit(elt);
520 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
527mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstVectorAttr attr) {
528 const mlir::Type llvmTy = converter->convertType(
attr.getType());
529 const mlir::Location loc = parentOp->getLoc();
531 SmallVector<mlir::Attribute> mlirValues;
532 for (
const mlir::Attribute elementAttr :
attr.getElts()) {
533 mlir::Attribute mlirAttr;
534 if (
auto intAttr = mlir::dyn_cast<cir::IntAttr>(elementAttr)) {
535 mlirAttr = rewriter.getIntegerAttr(
536 converter->convertType(intAttr.getType()), intAttr.getValue());
537 }
else if (
auto floatAttr = mlir::dyn_cast<cir::FPAttr>(elementAttr)) {
538 mlirAttr = rewriter.getFloatAttr(
539 converter->convertType(floatAttr.getType()), floatAttr.getValue());
542 "vector constant with an element that is neither an int nor a float");
544 mlirValues.push_back(mlirAttr);
547 return mlir::LLVM::ConstantOp::create(
548 rewriter, loc, llvmTy,
549 mlir::DenseElementsAttr::get(mlir::cast<mlir::ShapedType>(llvmTy),
554mlir::Value CIRAttrToValue::visitCirAttr(cir::GlobalViewAttr globalAttr) {
555 auto moduleOp = parentOp->getParentOfType<mlir::ModuleOp>();
556 mlir::DataLayout dataLayout(moduleOp);
557 mlir::Type sourceType;
558 unsigned sourceAddrSpace = 0;
559 llvm::StringRef symName;
560 mlir::Operation *sourceSymbol =
561 mlir::SymbolTable::lookupSymbolIn(moduleOp, globalAttr.getSymbol());
562 if (
auto llvmSymbol = dyn_cast<mlir::LLVM::GlobalOp>(sourceSymbol)) {
563 sourceType = llvmSymbol.getType();
564 symName = llvmSymbol.getSymName();
565 sourceAddrSpace = llvmSymbol.getAddrSpace();
566 }
else if (
auto cirSymbol = dyn_cast<cir::GlobalOp>(sourceSymbol)) {
569 symName = cirSymbol.getSymName();
570 if (
auto targetAS = mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
571 cirSymbol.getAddrSpaceAttr()))
572 sourceAddrSpace = targetAS.getValue();
573 }
else if (
auto llvmFun = dyn_cast<mlir::LLVM::LLVMFuncOp>(sourceSymbol)) {
574 sourceType = llvmFun.getFunctionType();
575 symName = llvmFun.getSymName();
576 }
else if (
auto fun = dyn_cast<cir::FuncOp>(sourceSymbol)) {
577 sourceType = converter->convertType(fun.getFunctionType());
578 symName = fun.getSymName();
579 }
else if (
auto alias = dyn_cast<mlir::LLVM::AliasOp>(sourceSymbol)) {
580 sourceType = alias.getType();
581 symName = alias.getSymName();
583 llvm_unreachable(
"Unexpected GlobalOp type");
586 mlir::Location loc = parentOp->getLoc();
587 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
589 mlir::LLVM::LLVMPointerType::get(rewriter.getContext(), sourceAddrSpace),
592 if (globalAttr.getIndices()) {
593 llvm::SmallVector<mlir::LLVM::GEPArg> indices;
595 if (mlir::isa<mlir::LLVM::LLVMArrayType, mlir::LLVM::LLVMStructType>(
597 indices.push_back(0);
599 for (mlir::Attribute idx : globalAttr.getIndices()) {
600 auto intAttr = mlir::cast<mlir::IntegerAttr>(idx);
601 indices.push_back(intAttr.getValue().getSExtValue());
603 mlir::Type resTy = addrOp.getType();
604 mlir::Type eltTy = converter->convertType(sourceType);
606 mlir::LLVM::GEPOp::create(rewriter, loc, resTy, eltTy, addrOp, indices,
607 mlir::LLVM::GEPNoWrapFlags::none);
614 if (
auto intTy = mlir::dyn_cast<cir::IntType>(globalAttr.getType())) {
615 mlir::Type llvmDstTy = converter->convertType(globalAttr.getType());
616 return mlir::LLVM::PtrToIntOp::create(rewriter, parentOp->getLoc(),
620 if (
auto ptrTy = mlir::dyn_cast<cir::PointerType>(globalAttr.getType())) {
621 auto llvmDstTy = converter->convertType<mlir::LLVM::LLVMPointerType>(ptrTy);
622 unsigned dstAddrSpace = llvmDstTy.getAddressSpace();
624 if (sourceAddrSpace != dstAddrSpace)
625 addrOp = mlir::LLVM::AddrSpaceCastOp::create(rewriter, parentOp->getLoc(),
628 mlir::Type llvmEltTy =
632 if (llvmEltTy == sourceType)
638 if (addrOp.getType() == llvmDstTy)
641 return mlir::LLVM::BitcastOp::create(rewriter, parentOp->getLoc(),
645 if (mlir::isa<cir::VPtrType>(globalAttr.getType()))
648 llvm_unreachable(
"Expecting pointer or integer type for GlobalViewAttr");
652mlir::Value CIRAttrToValue::visitCirAttr(cir::TypeInfoAttr typeInfoAttr) {
653 mlir::Type llvmTy = converter->convertType(typeInfoAttr.getType());
654 mlir::Location loc = parentOp->getLoc();
655 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
657 for (
auto [idx, elt] : llvm::enumerate(typeInfoAttr.getData())) {
658 mlir::Value init = visit(elt);
660 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
667mlir::Value CIRAttrToValue::visitCirAttr(cir::UndefAttr undefAttr) {
668 mlir::Location loc = parentOp->getLoc();
669 return mlir::LLVM::UndefOp::create(
670 rewriter, loc, converter->convertType(undefAttr.getType()));
674mlir::Value CIRAttrToValue::visitCirAttr(cir::PoisonAttr poisonAttr) {
675 mlir::Location loc = parentOp->getLoc();
676 return mlir::LLVM::PoisonOp::create(
677 rewriter, loc, converter->convertType(poisonAttr.getType()));
681mlir::Value CIRAttrToValue::visitCirAttr(cir::VTableAttr vtableArr) {
682 mlir::Type llvmTy = converter->convertType(vtableArr.getType());
683 mlir::Location loc = parentOp->getLoc();
684 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
686 for (
auto [idx, elt] : llvm::enumerate(vtableArr.getData())) {
687 mlir::Value init = visit(elt);
689 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
696mlir::Value CIRAttrToValue::visitCirAttr(cir::ZeroAttr attr) {
697 mlir::Location loc = parentOp->getLoc();
698 return mlir::LLVM::ZeroOp::create(rewriter, loc,
699 converter->convertType(
attr.getType()));
707 mlir::ConversionPatternRewriter &rewriter)
708 : llvmType(type), rewriter(rewriter) {}
711 return llvm::TypeSwitch<mlir::Attribute, mlir::Attribute>(
attr)
712 .Case<cir::IntAttr, cir::FPAttr, cir::BoolAttr>(
714 .
Default([&](
auto attrT) {
return mlir::Attribute(); });
718 return rewriter.getIntegerAttr(llvmType,
attr.getValue());
722 return rewriter.getFloatAttr(llvmType,
attr.getValue());
726 return rewriter.getBoolAttr(
attr.getValue());
731 mlir::ConversionPatternRewriter &rewriter;
739 :
public mlir::PassWrapper<ConvertCIRToLLVMPass,
740 mlir::OperationPass<mlir::ModuleOp>> {
742 registry.insert<mlir::BuiltinDialect, mlir::DLTIDialect,
743 mlir::LLVM::LLVMDialect, mlir::func::FuncDialect>();
761 return "Convert the prepared CIR dialect module to LLVM dialect";
764 StringRef
getArgument()
const override {
return "cir-flat-to-llvm"; }
768 struct CollectedAnnotation {
769 mlir::StringAttr symName;
770 cir::AnnotationAttr annotation;
772 CollectedAnnotation(mlir::StringAttr symName,
773 cir::AnnotationAttr annotation, mlir::Location loc)
774 : symName(symName), annotation(annotation), loc(loc) {}
779mlir::LogicalResult CIRToLLVMIsFPClassOpLowering::matchAndRewrite(
780 cir::IsFPClassOp op, OpAdaptor adaptor,
781 mlir::ConversionPatternRewriter &rewriter)
const {
782 mlir::Value src = adaptor.getSrc();
783 cir::FPClassTest flags = adaptor.getFlags();
784 mlir::IntegerType retTy = rewriter.getI1Type();
786 rewriter.replaceOpWithNewOp<mlir::LLVM::IsFPClass>(
787 op, retTy, src,
static_cast<uint32_t>(flags));
788 return mlir::success();
791mlir::LogicalResult CIRToLLVMSignBitOpLowering::matchAndRewrite(
792 cir::SignBitOp op, OpAdaptor adaptor,
793 mlir::ConversionPatternRewriter &rewriter)
const {
796 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
797 int width = layout.getTypeSizeInBits(op.getInput().getType());
798 if (
auto longDoubleType =
799 mlir::dyn_cast<cir::LongDoubleType>(op.getInput().getType())) {
800 if (mlir::isa<cir::FP80Type>(longDoubleType.getUnderlying())) {
808 mlir::Type intTy = mlir::IntegerType::get(rewriter.getContext(), width);
809 auto bitcast = mlir::LLVM::BitcastOp::create(rewriter, op->getLoc(), intTy,
812 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op->getLoc(), intTy, 0);
813 auto cmpResult = mlir::LLVM::ICmpOp::create(rewriter, op.getLoc(),
814 mlir::LLVM::ICmpPredicate::slt,
815 bitcast.getResult(), zero);
816 rewriter.replaceOp(op, cmpResult);
817 return mlir::success();
820mlir::LogicalResult CIRToLLVMAssumeOpLowering::matchAndRewrite(
821 cir::AssumeOp op, OpAdaptor adaptor,
822 mlir::ConversionPatternRewriter &rewriter)
const {
823 auto cond = adaptor.getPredicate();
824 rewriter.replaceOpWithNewOp<mlir::LLVM::AssumeOp>(op, cond);
825 return mlir::success();
828mlir::LogicalResult CIRToLLVMAssumeAlignedOpLowering::matchAndRewrite(
829 cir::AssumeAlignedOp op, OpAdaptor adaptor,
830 mlir::ConversionPatternRewriter &rewriter)
const {
831 SmallVector<mlir::Value, 3> opBundleArgs{adaptor.getPointer()};
833 auto alignment = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
834 adaptor.getAlignmentAttr());
835 opBundleArgs.push_back(alignment);
837 if (mlir::Value offset = adaptor.getOffset())
838 opBundleArgs.push_back(offset);
840 auto cond = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
841 rewriter.getI1Type(), 1);
842 mlir::LLVM::AssumeOp::create(rewriter, op.getLoc(), cond,
"align",
847 rewriter.replaceOp(op, adaptor.getPointer());
848 return mlir::success();
851mlir::LogicalResult CIRToLLVMAssumeSepStorageOpLowering::matchAndRewrite(
852 cir::AssumeSepStorageOp op, OpAdaptor adaptor,
853 mlir::ConversionPatternRewriter &rewriter)
const {
854 auto cond = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
855 rewriter.getI1Type(), 1);
856 rewriter.replaceOpWithNewOp<mlir::LLVM::AssumeOp>(
857 op, cond, mlir::LLVM::AssumeSeparateStorageTag{}, adaptor.getPtr1(),
859 return mlir::success();
862static mlir::LLVM::AtomicOrdering
865 return mlir::LLVM::AtomicOrdering::not_atomic;
867 case cir::MemOrder::Relaxed:
868 return mlir::LLVM::AtomicOrdering::monotonic;
869 case cir::MemOrder::Consume:
870 case cir::MemOrder::Acquire:
871 return mlir::LLVM::AtomicOrdering::acquire;
872 case cir::MemOrder::Release:
873 return mlir::LLVM::AtomicOrdering::release;
874 case cir::MemOrder::AcquireRelease:
875 return mlir::LLVM::AtomicOrdering::acq_rel;
876 case cir::MemOrder::SequentiallyConsistent:
877 return mlir::LLVM::AtomicOrdering::seq_cst;
879 llvm_unreachable(
"unknown memory order");
883 return syncScope == cir::SyncScopeKind::SingleThread ?
"singlethread" :
"";
886static std::optional<llvm::StringRef>
888 if (syncScope.has_value())
893mlir::LogicalResult CIRToLLVMAtomicCmpXchgOpLowering::matchAndRewrite(
894 cir::AtomicCmpXchgOp op, OpAdaptor adaptor,
895 mlir::ConversionPatternRewriter &rewriter)
const {
896 mlir::Value expected = adaptor.getExpected();
897 mlir::Value desired = adaptor.getDesired();
899 auto cmpxchg = mlir::LLVM::AtomicCmpXchgOp::create(
900 rewriter, op.getLoc(), adaptor.getPtr(), expected, desired,
905 cmpxchg.setAlignment(adaptor.getAlignment());
906 cmpxchg.setWeak(adaptor.getWeak());
907 cmpxchg.setVolatile_(adaptor.getIsVolatile());
910 auto old = mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(),
911 cmpxchg.getResult(), 0);
912 auto cmp = mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(),
913 cmpxchg.getResult(), 1);
915 rewriter.replaceOp(op, {old, cmp});
916 return mlir::success();
919mlir::LogicalResult CIRToLLVMAtomicXchgOpLowering::matchAndRewrite(
920 cir::AtomicXchgOp op, OpAdaptor adaptor,
921 mlir::ConversionPatternRewriter &rewriter)
const {
923 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(adaptor.getMemOrder());
925 rewriter.replaceOpWithNewOp<mlir::LLVM::AtomicRMWOp>(
926 op, mlir::LLVM::AtomicBinOp::xchg, adaptor.getPtr(), adaptor.getVal(),
927 llvmOrder, llvmSyncScope);
928 return mlir::success();
931mlir::LogicalResult CIRToLLVMAtomicTestAndSetOpLowering::matchAndRewrite(
932 cir::AtomicTestAndSetOp op, OpAdaptor adaptor,
933 mlir::ConversionPatternRewriter &rewriter)
const {
936 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
938 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
939 rewriter.getI8Type(), 1);
940 auto rmw = mlir::LLVM::AtomicRMWOp::create(
941 rewriter, op.getLoc(), mlir::LLVM::AtomicBinOp::xchg, adaptor.getPtr(),
942 one, llvmOrder, llvm::StringRef(),
943 adaptor.getAlignment().value_or(0), op.getIsVolatile());
945 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
946 rewriter.getI8Type(), 0);
947 auto cmp = mlir::LLVM::ICmpOp::create(
948 rewriter, op.getLoc(), mlir::LLVM::ICmpPredicate::ne, rmw, zero);
950 rewriter.replaceOp(op, cmp);
951 return mlir::success();
954mlir::LogicalResult CIRToLLVMAtomicClearOpLowering::matchAndRewrite(
955 cir::AtomicClearOp op, OpAdaptor adaptor,
956 mlir::ConversionPatternRewriter &rewriter)
const {
959 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
960 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
961 rewriter.getI8Type(), 0);
962 auto store = mlir::LLVM::StoreOp::create(
963 rewriter, op.getLoc(), zero, adaptor.getPtr(),
964 adaptor.getAlignment().value_or(0), op.getIsVolatile(),
965 false,
false, llvmOrder);
967 rewriter.replaceOp(op, store);
968 return mlir::success();
971mlir::LogicalResult CIRToLLVMAtomicFenceOpLowering::matchAndRewrite(
972 cir::AtomicFenceOp op, OpAdaptor adaptor,
973 mlir::ConversionPatternRewriter &rewriter)
const {
974 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(adaptor.getOrdering());
976 auto fence = mlir::LLVM::FenceOp::create(rewriter, op.getLoc(), llvmOrder);
979 rewriter.replaceOp(op, fence);
981 return mlir::success();
984static mlir::LLVM::AtomicBinOp
987 case cir::AtomicFetchKind::Add:
988 return isInt ? mlir::LLVM::AtomicBinOp::add : mlir::LLVM::AtomicBinOp::fadd;
989 case cir::AtomicFetchKind::Sub:
990 return isInt ? mlir::LLVM::AtomicBinOp::sub : mlir::LLVM::AtomicBinOp::fsub;
991 case cir::AtomicFetchKind::And:
992 return mlir::LLVM::AtomicBinOp::_and;
993 case cir::AtomicFetchKind::Xor:
994 return mlir::LLVM::AtomicBinOp::_xor;
995 case cir::AtomicFetchKind::Or:
996 return mlir::LLVM::AtomicBinOp::_or;
997 case cir::AtomicFetchKind::Nand:
998 return mlir::LLVM::AtomicBinOp::nand;
999 case cir::AtomicFetchKind::Max: {
1001 return mlir::LLVM::AtomicBinOp::fmax;
1002 return isSignedInt ? mlir::LLVM::AtomicBinOp::max
1003 : mlir::LLVM::AtomicBinOp::umax;
1005 case cir::AtomicFetchKind::Min: {
1007 return mlir::LLVM::AtomicBinOp::fmin;
1008 return isSignedInt ? mlir::LLVM::AtomicBinOp::min
1009 : mlir::LLVM::AtomicBinOp::umin;
1011 case cir::AtomicFetchKind::UIncWrap:
1012 return mlir::LLVM::AtomicBinOp::uinc_wrap;
1013 case cir::AtomicFetchKind::UDecWrap:
1014 return mlir::LLVM::AtomicBinOp::udec_wrap;
1016 llvm_unreachable(
"Unknown atomic fetch opcode");
1022 case cir::AtomicFetchKind::Add:
1023 return isInt ? mlir::LLVM::AddOp::getOperationName()
1024 : mlir::LLVM::FAddOp::getOperationName();
1025 case cir::AtomicFetchKind::Sub:
1026 return isInt ? mlir::LLVM::SubOp::getOperationName()
1027 : mlir::LLVM::FSubOp::getOperationName();
1028 case cir::AtomicFetchKind::And:
1029 return mlir::LLVM::AndOp::getOperationName();
1030 case cir::AtomicFetchKind::Xor:
1031 return mlir::LLVM::XOrOp::getOperationName();
1032 case cir::AtomicFetchKind::Or:
1033 return mlir::LLVM::OrOp::getOperationName();
1034 case cir::AtomicFetchKind::Nand:
1036 return mlir::LLVM::AndOp::getOperationName();
1037 case cir::AtomicFetchKind::Max:
1038 case cir::AtomicFetchKind::Min:
1039 llvm_unreachable(
"handled in buildMinMaxPostOp");
1040 case cir::AtomicFetchKind::UIncWrap:
1041 case cir::AtomicFetchKind::UDecWrap:
1042 llvm_unreachable(
"uinc_wrap and udec_wrap are always fetch_first");
1044 llvm_unreachable(
"Unknown atomic fetch opcode");
1047mlir::Value CIRToLLVMAtomicFetchOpLowering::buildPostOp(
1048 cir::AtomicFetchOp op, OpAdaptor adaptor,
1049 mlir::ConversionPatternRewriter &rewriter, mlir::Value rmwVal,
1054 .create(op.getLoc(),
1055 rewriter.getStringAttr(
1057 atomicOperands, atomicResTys, {})
1061mlir::Value CIRToLLVMAtomicFetchOpLowering::buildMinMaxPostOp(
1062 cir::AtomicFetchOp op, OpAdaptor adaptor,
1063 mlir::ConversionPatternRewriter &rewriter, mlir::Value rmwVal,
bool isInt,
1064 bool isSigned)
const {
1065 mlir::Location loc = op.getLoc();
1068 if (op.getBinop() == cir::AtomicFetchKind::Max)
1069 return mlir::LLVM::MaxNumOp::create(rewriter, loc, rmwVal,
1071 return mlir::LLVM::MinNumOp::create(rewriter, loc, rmwVal,
1075 mlir::LLVM::ICmpPredicate pred;
1076 if (op.getBinop() == cir::AtomicFetchKind::Max) {
1077 pred = isSigned ? mlir::LLVM::ICmpPredicate::sgt
1078 : mlir::LLVM::ICmpPredicate::ugt;
1080 pred = isSigned ? mlir::LLVM::ICmpPredicate::slt
1081 : mlir::LLVM::ICmpPredicate::ult;
1083 mlir::Value cmp = mlir::LLVM::ICmpOp::create(
1085 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(), pred), rmwVal,
1087 return mlir::LLVM::SelectOp::create(rewriter, loc, cmp, rmwVal,
1091mlir::LogicalResult CIRToLLVMAtomicFetchOpLowering::matchAndRewrite(
1092 cir::AtomicFetchOp op, OpAdaptor adaptor,
1093 mlir::ConversionPatternRewriter &rewriter)
const {
1095 bool isSignedInt =
false;
1096 if (
auto intTy = mlir::dyn_cast<cir::IntType>(op.getVal().getType())) {
1098 isSignedInt = intTy.isSigned();
1099 }
else if (mlir::isa<cir::SingleType, cir::DoubleType>(
1100 op.getVal().getType())) {
1103 return op.emitError() <<
"Unsupported type: " << op.getVal().getType();
1106 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
1108 mlir::LLVM::AtomicBinOp llvmBinOp =
1110 auto rmwVal = mlir::LLVM::AtomicRMWOp::create(
1111 rewriter, op.getLoc(), llvmBinOp, adaptor.getPtr(), adaptor.getVal(),
1112 llvmOrder, llvmSyncScope);
1114 mlir::Value result = rmwVal.getResult();
1115 if (!op.getFetchFirst()) {
1116 if (op.getBinop() == cir::AtomicFetchKind::Max ||
1117 op.getBinop() == cir::AtomicFetchKind::Min)
1118 result = buildMinMaxPostOp(op, adaptor, rewriter, rmwVal.getRes(), isInt,
1121 result = buildPostOp(op, adaptor, rewriter, rmwVal.getRes(), isInt);
1124 if (op.getBinop() == cir::AtomicFetchKind::Nand) {
1125 auto negOne = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1126 result.getType(), -1);
1127 result = mlir::LLVM::XOrOp::create(rewriter, op.getLoc(), result, negOne);
1131 rewriter.replaceOp(op, result);
1132 return mlir::success();
1135mlir::LogicalResult CIRToLLVMBitClrsbOpLowering::matchAndRewrite(
1136 cir::BitClrsbOp op, OpAdaptor adaptor,
1137 mlir::ConversionPatternRewriter &rewriter)
const {
1138 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1139 adaptor.getInput().getType(), 0);
1140 auto isNeg = mlir::LLVM::ICmpOp::create(
1141 rewriter, op.getLoc(),
1142 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(),
1143 mlir::LLVM::ICmpPredicate::slt),
1144 adaptor.getInput(), zero);
1146 auto negOne = mlir::LLVM::ConstantOp::create(
1147 rewriter, op.getLoc(), adaptor.getInput().getType(), -1);
1148 auto flipped = mlir::LLVM::XOrOp::create(rewriter, op.getLoc(),
1149 adaptor.getInput(), negOne);
1151 auto select = mlir::LLVM::SelectOp::create(rewriter, op.getLoc(), isNeg,
1152 flipped, adaptor.getInput());
1154 auto resTy = getTypeConverter()->convertType(op.getType());
1155 auto clz = mlir::LLVM::CountLeadingZerosOp::create(
1156 rewriter, op.getLoc(), resTy,
select,
false);
1158 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1159 auto res = mlir::LLVM::SubOp::create(rewriter, op.getLoc(),
clz, one,
1160 mlir::LLVM::IntegerOverflowFlags::nuw);
1161 rewriter.replaceOp(op, res);
1163 return mlir::LogicalResult::success();
1166mlir::LogicalResult CIRToLLVMBitClzOpLowering::matchAndRewrite(
1167 cir::BitClzOp op, OpAdaptor adaptor,
1168 mlir::ConversionPatternRewriter &rewriter)
const {
1169 auto resTy = getTypeConverter()->convertType(op.getType());
1170 auto llvmOp = mlir::LLVM::CountLeadingZerosOp::create(
1171 rewriter, op.getLoc(), resTy, adaptor.getInput(), op.getPoisonZero());
1172 rewriter.replaceOp(op, llvmOp);
1173 return mlir::LogicalResult::success();
1176mlir::LogicalResult CIRToLLVMBitCtzOpLowering::matchAndRewrite(
1177 cir::BitCtzOp op, OpAdaptor adaptor,
1178 mlir::ConversionPatternRewriter &rewriter)
const {
1179 auto resTy = getTypeConverter()->convertType(op.getType());
1180 auto llvmOp = mlir::LLVM::CountTrailingZerosOp::create(
1181 rewriter, op.getLoc(), resTy, adaptor.getInput(), op.getPoisonZero());
1182 rewriter.replaceOp(op, llvmOp);
1183 return mlir::LogicalResult::success();
1186mlir::LogicalResult CIRToLLVMBitFfsOpLowering::matchAndRewrite(
1187 cir::BitFfsOp op, OpAdaptor adaptor,
1188 mlir::ConversionPatternRewriter &rewriter)
const {
1189 auto resTy = getTypeConverter()->convertType(op.getType());
1190 auto ctz = mlir::LLVM::CountTrailingZerosOp::create(rewriter, op.getLoc(),
1191 resTy, adaptor.getInput(),
1194 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1195 auto ctzAddOne = mlir::LLVM::AddOp::create(rewriter, op.getLoc(),
ctz, one);
1197 auto zeroInputTy = mlir::LLVM::ConstantOp::create(
1198 rewriter, op.getLoc(), adaptor.getInput().getType(), 0);
1199 auto isZero = mlir::LLVM::ICmpOp::create(
1200 rewriter, op.getLoc(),
1201 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(),
1202 mlir::LLVM::ICmpPredicate::eq),
1203 adaptor.getInput(), zeroInputTy);
1205 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 0);
1206 auto res = mlir::LLVM::SelectOp::create(rewriter, op.getLoc(), isZero, zero,
1208 rewriter.replaceOp(op, res);
1210 return mlir::LogicalResult::success();
1213mlir::LogicalResult CIRToLLVMBitParityOpLowering::matchAndRewrite(
1214 cir::BitParityOp op, OpAdaptor adaptor,
1215 mlir::ConversionPatternRewriter &rewriter)
const {
1216 auto resTy = getTypeConverter()->convertType(op.getType());
1217 auto popcnt = mlir::LLVM::CtPopOp::create(rewriter, op.getLoc(), resTy,
1218 adaptor.getInput());
1220 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1222 mlir::LLVM::AndOp::create(rewriter, op.getLoc(), popcnt, one);
1223 rewriter.replaceOp(op, popcntMod2);
1225 return mlir::LogicalResult::success();
1228mlir::LogicalResult CIRToLLVMBitPopcountOpLowering::matchAndRewrite(
1229 cir::BitPopcountOp op, OpAdaptor adaptor,
1230 mlir::ConversionPatternRewriter &rewriter)
const {
1231 auto resTy = getTypeConverter()->convertType(op.getType());
1232 auto llvmOp = mlir::LLVM::CtPopOp::create(rewriter, op.getLoc(), resTy,
1233 adaptor.getInput());
1234 rewriter.replaceOp(op, llvmOp);
1235 return mlir::LogicalResult::success();
1238mlir::LogicalResult CIRToLLVMBitReverseOpLowering::matchAndRewrite(
1239 cir::BitReverseOp op, OpAdaptor adaptor,
1240 mlir::ConversionPatternRewriter &rewriter)
const {
1241 rewriter.replaceOpWithNewOp<mlir::LLVM::BitReverseOp>(op, adaptor.getInput());
1242 return mlir::success();
1245mlir::LogicalResult CIRToLLVMBrCondOpLowering::matchAndRewrite(
1246 cir::BrCondOp brOp, OpAdaptor adaptor,
1247 mlir::ConversionPatternRewriter &rewriter)
const {
1252 mlir::Value i1Condition = adaptor.getCond();
1254 rewriter.replaceOpWithNewOp<mlir::LLVM::CondBrOp>(
1255 brOp, i1Condition, brOp.getDestTrue(), adaptor.getDestOperandsTrue(),
1256 brOp.getDestFalse(), adaptor.getDestOperandsFalse());
1258 return mlir::success();
1261mlir::LogicalResult CIRToLLVMByteSwapOpLowering::matchAndRewrite(
1262 cir::ByteSwapOp op, OpAdaptor adaptor,
1263 mlir::ConversionPatternRewriter &rewriter)
const {
1264 rewriter.replaceOpWithNewOp<mlir::LLVM::ByteSwapOp>(op, adaptor.getInput());
1265 return mlir::LogicalResult::success();
1268mlir::Type CIRToLLVMCastOpLowering::convertTy(mlir::Type ty)
const {
1269 return getTypeConverter()->convertType(ty);
1272mlir::LogicalResult CIRToLLVMCastOpLowering::matchAndRewrite(
1273 cir::CastOp castOp, OpAdaptor adaptor,
1274 mlir::ConversionPatternRewriter &rewriter)
const {
1279 switch (castOp.getKind()) {
1280 case cir::CastKind::array_to_ptrdecay: {
1281 const auto ptrTy = mlir::cast<cir::PointerType>(castOp.getType());
1282 mlir::Value sourceValue = adaptor.getSrc();
1283 mlir::Type targetType = convertTy(ptrTy);
1285 ptrTy.getPointee());
1286 llvm::SmallVector<mlir::LLVM::GEPArg> offset{0};
1287 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1288 castOp, targetType, elementTy, sourceValue, offset);
1291 case cir::CastKind::int_to_bool: {
1292 mlir::Value llvmSrcVal = adaptor.getSrc();
1293 mlir::Value zeroInt = mlir::LLVM::ConstantOp::create(
1294 rewriter, castOp.getLoc(), llvmSrcVal.getType(), 0);
1295 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
1296 castOp, mlir::LLVM::ICmpPredicate::ne, llvmSrcVal, zeroInt);
1299 case cir::CastKind::integral: {
1300 mlir::Type srcType = castOp.getSrc().getType();
1301 mlir::Type dstType = castOp.getType();
1302 mlir::Value llvmSrcVal = adaptor.getSrc();
1303 mlir::Type llvmDstType = getTypeConverter()->convertType(dstType);
1304 cir::IntType srcIntType =
1305 mlir::cast<cir::IntType>(elementTypeIfVector(srcType));
1306 cir::IntType dstIntType =
1307 mlir::cast<cir::IntType>(elementTypeIfVector(dstType));
1308 rewriter.replaceOp(castOp,
getLLVMIntCast(rewriter, llvmSrcVal, llvmDstType,
1309 srcIntType.isUnsigned(),
1310 srcIntType.getWidth(),
1311 dstIntType.getWidth()));
1314 case cir::CastKind::floating: {
1315 mlir::Value llvmSrcVal = adaptor.getSrc();
1316 mlir::Type llvmDstTy = getTypeConverter()->convertType(castOp.getType());
1318 mlir::Type srcTy = elementTypeIfVector(castOp.getSrc().getType());
1319 mlir::Type dstTy = elementTypeIfVector(castOp.getType());
1321 if (!mlir::isa<cir::FPTypeInterface>(dstTy) ||
1322 !mlir::isa<cir::FPTypeInterface>(srcTy))
1323 return castOp.emitError() <<
"NYI cast from " << srcTy <<
" to " << dstTy;
1325 auto getFloatWidth = [](mlir::Type ty) ->
unsigned {
1326 return mlir::cast<cir::FPTypeInterface>(ty).getWidth();
1329 if (getFloatWidth(srcTy) > getFloatWidth(dstTy))
1330 rewriter.replaceOpWithNewOp<mlir::LLVM::FPTruncOp>(castOp, llvmDstTy,
1333 rewriter.replaceOpWithNewOp<mlir::LLVM::FPExtOp>(castOp, llvmDstTy,
1335 return mlir::success();
1337 case cir::CastKind::int_to_ptr: {
1338 auto dstTy = mlir::cast<cir::PointerType>(castOp.getType());
1339 mlir::Value llvmSrcVal = adaptor.getSrc();
1340 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1341 rewriter.replaceOpWithNewOp<mlir::LLVM::IntToPtrOp>(castOp, llvmDstTy,
1343 return mlir::success();
1345 case cir::CastKind::ptr_to_int: {
1346 auto dstTy = mlir::cast<cir::IntType>(castOp.getType());
1347 mlir::Value llvmSrcVal = adaptor.getSrc();
1348 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1349 rewriter.replaceOpWithNewOp<mlir::LLVM::PtrToIntOp>(castOp, llvmDstTy,
1351 return mlir::success();
1353 case cir::CastKind::float_to_bool: {
1354 mlir::Value llvmSrcVal = adaptor.getSrc();
1355 auto kind = mlir::LLVM::FCmpPredicate::une;
1358 auto zeroFloat = mlir::LLVM::ConstantOp::create(
1359 rewriter, castOp.getLoc(), llvmSrcVal.getType(),
1360 mlir::FloatAttr::get(llvmSrcVal.getType(), 0.0));
1363 rewriter.replaceOpWithNewOp<mlir::LLVM::FCmpOp>(castOp,
kind, llvmSrcVal,
1366 return mlir::success();
1368 case cir::CastKind::bool_to_int: {
1369 auto dstTy = mlir::cast<cir::IntType>(castOp.getType());
1370 mlir::Value llvmSrcVal = adaptor.getSrc();
1371 auto llvmSrcTy = mlir::cast<mlir::IntegerType>(llvmSrcVal.getType());
1373 mlir::cast<mlir::IntegerType>(getTypeConverter()->convertType(dstTy));
1375 if (llvmSrcTy.getWidth() == llvmDstTy.getWidth())
1376 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(castOp, llvmDstTy,
1379 rewriter.replaceOpWithNewOp<mlir::LLVM::ZExtOp>(castOp, llvmDstTy,
1381 return mlir::success();
1383 case cir::CastKind::bool_to_float: {
1384 mlir::Type dstTy = castOp.getType();
1385 mlir::Value llvmSrcVal = adaptor.getSrc();
1386 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1387 rewriter.replaceOpWithNewOp<mlir::LLVM::UIToFPOp>(castOp, llvmDstTy,
1389 return mlir::success();
1391 case cir::CastKind::int_to_float: {
1392 mlir::Type dstTy = castOp.getType();
1393 mlir::Value llvmSrcVal = adaptor.getSrc();
1394 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1395 if (mlir::cast<cir::IntType>(elementTypeIfVector(castOp.getSrc().getType()))
1397 rewriter.replaceOpWithNewOp<mlir::LLVM::SIToFPOp>(castOp, llvmDstTy,
1400 rewriter.replaceOpWithNewOp<mlir::LLVM::UIToFPOp>(castOp, llvmDstTy,
1402 return mlir::success();
1404 case cir::CastKind::float_to_int: {
1405 mlir::Type dstTy = castOp.getType();
1406 mlir::Value llvmSrcVal = adaptor.getSrc();
1407 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1408 if (mlir::cast<cir::IntType>(elementTypeIfVector(castOp.getType()))
1410 rewriter.replaceOpWithNewOp<mlir::LLVM::FPToSIOp>(castOp, llvmDstTy,
1413 rewriter.replaceOpWithNewOp<mlir::LLVM::FPToUIOp>(castOp, llvmDstTy,
1415 return mlir::success();
1417 case cir::CastKind::bitcast: {
1418 mlir::Type dstTy = castOp.getType();
1419 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1424 mlir::Value llvmSrcVal = adaptor.getSrc();
1425 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(castOp, llvmDstTy,
1427 return mlir::success();
1429 case cir::CastKind::ptr_to_bool: {
1430 mlir::Value llvmSrcVal = adaptor.getSrc();
1431 mlir::Value zeroPtr = mlir::LLVM::ZeroOp::create(rewriter, castOp.getLoc(),
1432 llvmSrcVal.getType());
1433 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
1434 castOp, mlir::LLVM::ICmpPredicate::ne, llvmSrcVal, zeroPtr);
1437 case cir::CastKind::address_space: {
1438 mlir::Type dstTy = castOp.getType();
1439 mlir::Value llvmSrcVal = adaptor.getSrc();
1440 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1441 rewriter.replaceOpWithNewOp<mlir::LLVM::AddrSpaceCastOp>(castOp, llvmDstTy,
1445 case cir::CastKind::member_ptr_to_bool:
1450 return castOp.emitError(
"Unhandled cast kind: ")
1451 << castOp.getKindAttrName();
1455 return mlir::success();
1459 mlir::ModuleOp mod, mlir::Value index,
1460 mlir::Type baseTy, cir::IntType strideTy) {
1461 mlir::Operation *indexOp = index.getDefiningOp();
1465 auto indexType = mlir::cast<mlir::IntegerType>(index.getType());
1466 mlir::DataLayout llvmLayout(mod);
1467 std::optional<uint64_t> layoutWidth = llvmLayout.getTypeIndexBitwidth(baseTy);
1470 if (!layoutWidth || *layoutWidth == indexType.getWidth())
1476 auto sub = dyn_cast<mlir::LLVM::SubOp>(indexOp);
1477 bool rewriteSub =
false;
1480 dyn_cast<mlir::LLVM::ConstantOp>(sub.getLhs().getDefiningOp())) {
1481 auto lhsConstInt = mlir::dyn_cast<mlir::IntegerAttr>(lhsConst.getValue());
1482 if (lhsConstInt && lhsConstInt.getValue() == 0) {
1483 index = sub.getRhs();
1489 auto llvmDstType = rewriter.getIntegerType(*layoutWidth);
1490 bool isUnsigned = strideTy && strideTy.isUnsigned();
1492 indexType.getWidth(), *layoutWidth);
1495 index = mlir::LLVM::SubOp::create(
1496 rewriter, index.getLoc(),
1497 mlir::LLVM::ConstantOp::create(rewriter, index.getLoc(),
1498 index.getType(), 0),
1501 rewriter.eraseOp(sub);
1507mlir::LogicalResult CIRToLLVMPtrStrideOpLowering::matchAndRewrite(
1508 cir::PtrStrideOp ptrStrideOp, OpAdaptor adaptor,
1509 mlir::ConversionPatternRewriter &rewriter)
const {
1511 const mlir::TypeConverter *tc = getTypeConverter();
1512 const mlir::Type resultTy = tc->convertType(ptrStrideOp.getType());
1514 mlir::Type elementTy =
1519 if (mlir::isa<mlir::LLVM::LLVMVoidType>(elementTy) ||
1520 mlir::isa<mlir::LLVM::LLVMFunctionType>(elementTy))
1521 elementTy = mlir::IntegerType::get(elementTy.getContext(), 8,
1522 mlir::IntegerType::Signless);
1524 mlir::Value index = adaptor.getStride();
1526 rewriter, ptrStrideOp->getParentOfType<mlir::ModuleOp>(), index,
1527 adaptor.getBase().getType(),
1528 dyn_cast<cir::IntType>(ptrStrideOp.getOperand(1).getType()));
1530 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1531 ptrStrideOp, resultTy, elementTy, adaptor.getBase(), index);
1532 return mlir::success();
1535mlir::LogicalResult CIRToLLVMGetElementOpLowering::matchAndRewrite(
1536 cir::GetElementOp op, OpAdaptor adaptor,
1537 mlir::ConversionPatternRewriter &rewriter)
const {
1539 mlir::dyn_cast<cir::ArrayType>(op.getBaseType().getPointee())) {
1540 const mlir::TypeConverter *converter = getTypeConverter();
1541 const mlir::Type llArrayTy = converter->convertType(arrayTy);
1542 const mlir::Type llResultTy = converter->convertType(op.getType());
1543 mlir::Type elementTy =
1548 if (mlir::isa<mlir::LLVM::LLVMVoidType>(elementTy) ||
1549 mlir::isa<mlir::LLVM::LLVMFunctionType>(elementTy))
1550 elementTy = rewriter.getIntegerType(8);
1552 mlir::Value index = adaptor.getIndex();
1555 adaptor.getBase().getType(),
1556 dyn_cast<cir::IntType>(op.getOperand(1).getType()));
1561 std::array<mlir::LLVM::GEPArg, 2> offset{0, index};
1562 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, llResultTy, llArrayTy,
1563 adaptor.getBase(), offset);
1564 return mlir::success();
1567 op.emitError() <<
"NYI: GetElementOp lowering to LLVM for non-array";
1568 return mlir::failure();
1571mlir::LogicalResult CIRToLLVMBaseClassAddrOpLowering::matchAndRewrite(
1572 cir::BaseClassAddrOp baseClassOp, OpAdaptor adaptor,
1573 mlir::ConversionPatternRewriter &rewriter)
const {
1574 const mlir::Type resultType =
1575 getTypeConverter()->convertType(baseClassOp.getType());
1576 mlir::Value derivedAddr = adaptor.getDerivedAddr();
1577 llvm::SmallVector<mlir::LLVM::GEPArg, 1> offset = {
1578 adaptor.getOffset().getZExtValue()};
1579 mlir::Type byteType = mlir::IntegerType::get(resultType.getContext(), 8,
1580 mlir::IntegerType::Signless);
1581 if (adaptor.getOffset().getZExtValue() == 0) {
1582 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(
1583 baseClassOp, resultType, adaptor.getDerivedAddr());
1584 return mlir::success();
1587 if (baseClassOp.getAssumeNotNull()) {
1588 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1589 baseClassOp, resultType, byteType, derivedAddr, offset);
1591 auto loc = baseClassOp.getLoc();
1592 mlir::Value isNull = mlir::LLVM::ICmpOp::create(
1593 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, derivedAddr,
1594 mlir::LLVM::ZeroOp::create(rewriter, loc, derivedAddr.getType()));
1595 mlir::Value adjusted = mlir::LLVM::GEPOp::create(
1596 rewriter, loc, resultType, byteType, derivedAddr, offset);
1597 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(baseClassOp, isNull,
1598 derivedAddr, adjusted);
1600 return mlir::success();
1603mlir::LogicalResult CIRToLLVMDerivedClassAddrOpLowering::matchAndRewrite(
1604 cir::DerivedClassAddrOp derivedClassOp, OpAdaptor adaptor,
1605 mlir::ConversionPatternRewriter &rewriter)
const {
1606 const mlir::Type resultType =
1607 getTypeConverter()->convertType(derivedClassOp.getType());
1608 mlir::Value baseAddr = adaptor.getBaseAddr();
1611 int64_t offsetVal = -(adaptor.getOffset().getZExtValue());
1612 if (offsetVal == 0) {
1614 rewriter.replaceOp(derivedClassOp, baseAddr);
1615 return mlir::success();
1617 llvm::SmallVector<mlir::LLVM::GEPArg, 1> offset = {offsetVal};
1618 mlir::Type byteType = mlir::IntegerType::get(resultType.getContext(), 8,
1619 mlir::IntegerType::Signless);
1620 if (derivedClassOp.getAssumeNotNull()) {
1621 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1622 derivedClassOp, resultType, byteType, baseAddr, offset,
1623 mlir::LLVM::GEPNoWrapFlags::inbounds);
1625 mlir::Location loc = derivedClassOp.getLoc();
1626 mlir::Value isNull = mlir::LLVM::ICmpOp::create(
1627 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, baseAddr,
1628 mlir::LLVM::ZeroOp::create(rewriter, loc, baseAddr.getType()));
1629 mlir::Value adjusted =
1630 mlir::LLVM::GEPOp::create(rewriter, loc, resultType, byteType, baseAddr,
1631 offset, mlir::LLVM::GEPNoWrapFlags::inbounds);
1632 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(derivedClassOp, isNull,
1633 baseAddr, adjusted);
1635 return mlir::success();
1638mlir::LogicalResult CIRToLLVMFMaxNumOpLowering::matchAndRewrite(
1639 cir::FMaxNumOp op, OpAdaptor adaptor,
1640 mlir::ConversionPatternRewriter &rewriter)
const {
1641 mlir::Type resTy = typeConverter->convertType(op.getType());
1642 rewriter.replaceOpWithNewOp<mlir::LLVM::MaxNumOp>(
1643 op, resTy, adaptor.getLhs(), adaptor.getRhs(),
1644 mlir::LLVM::FastmathFlags::nsz);
1645 return mlir::success();
1648mlir::LogicalResult CIRToLLVMFMinNumOpLowering::matchAndRewrite(
1649 cir::FMinNumOp op, OpAdaptor adaptor,
1650 mlir::ConversionPatternRewriter &rewriter)
const {
1651 mlir::Type resTy = typeConverter->convertType(op.getType());
1652 rewriter.replaceOpWithNewOp<mlir::LLVM::MinNumOp>(
1653 op, resTy, adaptor.getLhs(), adaptor.getRhs(),
1654 mlir::LLVM::FastmathFlags::nsz);
1655 return mlir::success();
1658mlir::LogicalResult CIRToLLVMAllocaOpLowering::matchAndRewrite(
1659 cir::AllocaOp op, OpAdaptor adaptor,
1660 mlir::ConversionPatternRewriter &rewriter)
const {
1663 ? adaptor.getDynAllocSize()
1664 : mlir::LLVM::ConstantOp::create(
1665 rewriter, op.getLoc(),
1666 typeConverter->convertType(rewriter.getIndexType()), 1);
1667 mlir::Type elementTy =
1669 mlir::Type resultTy =
1675 rewriter.replaceOpWithNewOp<mlir::LLVM::AllocaOp>(op, resultTy, elementTy,
1676 size, op.getAlignment());
1678 return mlir::success();
1681mlir::LogicalResult CIRToLLVMReturnOpLowering::matchAndRewrite(
1682 cir::ReturnOp op, OpAdaptor adaptor,
1683 mlir::ConversionPatternRewriter &rewriter)
const {
1684 rewriter.replaceOpWithNewOp<mlir::LLVM::ReturnOp>(op, adaptor.getOperands());
1685 return mlir::LogicalResult::success();
1688mlir::LogicalResult CIRToLLVMRotateOpLowering::matchAndRewrite(
1689 cir::RotateOp op, OpAdaptor adaptor,
1690 mlir::ConversionPatternRewriter &rewriter)
const {
1693 mlir::Value input = adaptor.getInput();
1694 if (op.isRotateLeft())
1695 rewriter.replaceOpWithNewOp<mlir::LLVM::FshlOp>(op, input, input,
1696 adaptor.getAmount());
1698 rewriter.replaceOpWithNewOp<mlir::LLVM::FshrOp>(op, input, input,
1699 adaptor.getAmount());
1700 return mlir::LogicalResult::success();
1705 for (mlir::NamedAttribute attr : op->getAttrs()) {
1706 if (attr.getName() == CIRDialect::getCalleeAttrName() ||
1707 attr.getName() == CIRDialect::getSideEffectAttrName() ||
1708 attr.getName() == CIRDialect::getNoThrowAttrName() ||
1709 attr.getName() == CIRDialect::getNoUnwindAttrName() ||
1710 attr.getName() == CIRDialect::getNoReturnAttrName() ||
1711 attr.getName() == CIRDialect::getMustTailAttrName())
1715 result.push_back(attr);
1719static mlir::LogicalResult
1721 mlir::ConversionPatternRewriter &rewriter,
1722 const mlir::TypeConverter *converter,
1723 mlir::FlatSymbolRefAttr calleeAttr,
1724 mlir::Block *continueBlock =
nullptr,
1725 mlir::Block *landingPadBlock =
nullptr) {
1727 mlir::ValueTypeRange<mlir::ResultRange> cirResults = op->getResultTypes();
1728 auto call = cast<cir::CIRCallOpInterface>(op);
1730 if (converter->convertTypes(cirResults, llvmResults).failed())
1731 return mlir::failure();
1735 mlir::LLVM::MemoryEffectsAttr memoryEffects;
1736 bool noUnwind =
false;
1737 bool willReturn =
false;
1738 bool noReturn =
false;
1740 memoryEffects, noUnwind, willReturn, noReturn);
1745 mlir::LLVM::LLVMFunctionType llvmFnTy;
1752 mlir::Operation *callee =
1753 mlir::SymbolTable::lookupNearestSymbolFrom(op, calleeAttr);
1754 if (
auto fn = mlir::dyn_cast<mlir::FunctionOpInterface>(callee)) {
1755 llvmFnTy = converter->convertType<mlir::LLVM::LLVMFunctionType>(
1756 fn.getFunctionType());
1757 assert(llvmFnTy &&
"Failed to convert function type");
1758 }
else if (
auto alias = mlir::cast<mlir::LLVM::AliasOp>(callee)) {
1766 auto symAttr = mlir::cast<mlir::FlatSymbolRefAttr>(calleeAttr);
1768 mlir::LLVM::AddressOfOp::create(
1769 rewriter, op->getLoc(),
1770 mlir::LLVM::LLVMPointerType::get(rewriter.getContext()), symAttr)
1772 adjustedCallOperands.push_back(addrOfAlias);
1775 llvm::append_range(adjustedCallOperands, callOperands);
1776 callOperands = adjustedCallOperands;
1780 llvmFnTy = mlir::cast<mlir::LLVM::LLVMFunctionType>(alias.getType());
1783 return op->emitError(
"Unexpected callee type!");
1786 assert(!op->getOperands().empty() &&
1787 "operands list must no be empty for the indirect call");
1788 auto calleeTy = op->getOperands().front().getType();
1789 auto calleePtrTy = cast<cir::PointerType>(calleeTy);
1790 auto calleeFuncTy = cast<cir::FuncType>(calleePtrTy.getPointee());
1791 llvm::append_range(adjustedCallOperands, callOperands);
1792 llvmFnTy = cast<mlir::LLVM::LLVMFunctionType>(
1793 converter->convertType(calleeFuncTy));
1798 if (landingPadBlock) {
1799 auto newOp = rewriter.replaceOpWithNewOp<mlir::LLVM::InvokeOp>(
1800 op, llvmFnTy, calleeAttr, callOperands, continueBlock,
1801 mlir::ValueRange{}, landingPadBlock, mlir::ValueRange{});
1802 newOp->setAttrs(attributes);
1804 auto newOp = rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(
1805 op, llvmFnTy, calleeAttr, callOperands);
1806 newOp->setAttrs(attributes);
1808 newOp.setMemoryEffectsAttr(memoryEffects);
1809 newOp.setNoUnwind(noUnwind);
1810 newOp.setWillReturn(willReturn);
1811 newOp.setNoreturn(noReturn);
1812 if (op->hasAttr(CIRDialect::getMustTailAttrName()))
1813 newOp.setTailCallKind(mlir::LLVM::TailCallKind::MustTail);
1816 return mlir::success();
1819mlir::LogicalResult CIRToLLVMCallOpLowering::matchAndRewrite(
1820 cir::CallOp op, OpAdaptor adaptor,
1821 mlir::ConversionPatternRewriter &rewriter)
const {
1823 getTypeConverter(), op.getCalleeAttr());
1826mlir::LogicalResult CIRToLLVMTryCallOpLowering::matchAndRewrite(
1827 cir::TryCallOp op, OpAdaptor adaptor,
1828 mlir::ConversionPatternRewriter &rewriter)
const {
1831 getTypeConverter(), op.getCalleeAttr(),
1832 op.getNormalDest(), op.getUnwindDest());
1835mlir::LogicalResult CIRToLLVMReturnAddrOpLowering::matchAndRewrite(
1836 cir::ReturnAddrOp op, OpAdaptor adaptor,
1837 mlir::ConversionPatternRewriter &rewriter)
const {
1838 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
1840 llvmPtrTy, adaptor.getOperands());
1841 return mlir::success();
1844mlir::LogicalResult CIRToLLVMFrameAddrOpLowering::matchAndRewrite(
1845 cir::FrameAddrOp op, OpAdaptor adaptor,
1846 mlir::ConversionPatternRewriter &rewriter)
const {
1847 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
1849 adaptor.getOperands());
1850 return mlir::success();
1853mlir::LogicalResult CIRToLLVMClearCacheOpLowering::matchAndRewrite(
1854 cir::ClearCacheOp op, OpAdaptor adaptor,
1855 mlir::ConversionPatternRewriter &rewriter)
const {
1856 mlir::Value begin = adaptor.getBegin();
1857 mlir::Value end = adaptor.getEnd();
1858 auto intrinNameAttr =
1859 mlir::StringAttr::get(op.getContext(),
"llvm.clear_cache");
1860 rewriter.replaceOpWithNewOp<mlir::LLVM::CallIntrinsicOp>(
1861 op, mlir::Type{}, intrinNameAttr, mlir::ValueRange{begin, end});
1863 return mlir::success();
1866mlir::LogicalResult CIRToLLVMAddrOfReturnAddrOpLowering::matchAndRewrite(
1867 cir::AddrOfReturnAddrOp op, OpAdaptor adaptor,
1868 mlir::ConversionPatternRewriter &rewriter)
const {
1869 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
1871 llvmPtrTy, adaptor.getOperands());
1872 return mlir::success();
1875mlir::LogicalResult CIRToLLVMLoadOpLowering::matchAndRewrite(
1876 cir::LoadOp op, OpAdaptor adaptor,
1877 mlir::ConversionPatternRewriter &rewriter)
const {
1878 const mlir::Type llvmTy =
1880 mlir::LLVM::AtomicOrdering ordering =
getLLVMMemOrder(op.getMemOrder());
1881 std::optional<size_t> opAlign = op.getAlignment();
1882 unsigned alignment =
1883 (unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmTy));
1890 std::optional<llvm::StringRef> llvmSyncScope =
1893 mlir::LLVM::LoadOp newLoad = mlir::LLVM::LoadOp::create(
1894 rewriter, op->getLoc(), llvmTy, adaptor.getAddr(), alignment,
1895 op.getIsVolatile(),
false,
1896 false,
false, ordering,
1897 llvmSyncScope.value_or(std::string()));
1900 mlir::Value result =
1902 rewriter.replaceOp(op, result);
1904 return mlir::LogicalResult::success();
1908cir::direct::CIRToLLVMVecMaskedLoadOpLowering::matchAndRewrite(
1909 cir::VecMaskedLoadOp op, OpAdaptor adaptor,
1910 mlir::ConversionPatternRewriter &rewriter)
const {
1911 const mlir::Type llvmResTy =
1914 std::optional<size_t> opAlign = op.getAlignment();
1915 unsigned alignment =
1916 (unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmResTy));
1918 mlir::IntegerAttr alignAttr = rewriter.getI32IntegerAttr(alignment);
1920 auto newLoad = mlir::LLVM::MaskedLoadOp::create(
1921 rewriter, op.getLoc(), llvmResTy, adaptor.getAddr(), adaptor.getMask(),
1922 adaptor.getPassThru(), alignAttr);
1924 rewriter.replaceOp(op, newLoad.getResult());
1925 return mlir::success();
1928mlir::LogicalResult CIRToLLVMStoreOpLowering::matchAndRewrite(
1929 cir::StoreOp op, OpAdaptor adaptor,
1930 mlir::ConversionPatternRewriter &rewriter)
const {
1931 mlir::LLVM::AtomicOrdering memorder =
getLLVMMemOrder(op.getMemOrder());
1932 const mlir::Type llvmTy =
1933 getTypeConverter()->convertType(op.getValue().getType());
1934 std::optional<size_t> opAlign = op.getAlignment();
1935 unsigned alignment =
1936 (unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmTy));
1942 op.getValue().getType(), adaptor.getValue());
1947 std::optional<llvm::StringRef> llvmSyncScope =
1950 mlir::LLVM::StoreOp storeOp = mlir::LLVM::StoreOp::create(
1951 rewriter, op->getLoc(), value, adaptor.getAddr(), alignment,
1953 false,
false, memorder,
1954 llvmSyncScope.value_or(std::string()));
1955 rewriter.replaceOp(op, storeOp);
1957 return mlir::LogicalResult::success();
1961 auto array = mlir::dyn_cast<mlir::ArrayAttr>(attr.getElts());
1962 return attr.hasTrailingZeros() ||
1963 (array && std::count_if(array.begin(), array.end(), [](
auto elt) {
1964 auto ar = dyn_cast<cir::ConstArrayAttr>(elt);
1965 return ar && hasTrailingZeros(ar);
1969mlir::LogicalResult CIRToLLVMConstantOpLowering::matchAndRewrite(
1970 cir::ConstantOp op, OpAdaptor adaptor,
1971 mlir::ConversionPatternRewriter &rewriter)
const {
1972 mlir::Attribute attr = op.getValue();
1974 if (mlir::isa<cir::PoisonAttr>(attr)) {
1975 rewriter.replaceOpWithNewOp<mlir::LLVM::PoisonOp>(
1976 op, getTypeConverter()->convertType(op.getType()));
1977 return mlir::success();
1980 if (mlir::isa<mlir::IntegerType>(op.getType())) {
1985 attr = op.getValue();
1986 }
else if (mlir::isa<cir::BoolType>(op.getType())) {
1987 int value = mlir::cast<cir::BoolAttr>(op.getValue()).getValue();
1988 attr = rewriter.getIntegerAttr(typeConverter->convertType(op.getType()),
1990 }
else if (mlir::isa<cir::IntType>(op.getType())) {
1992 if (
auto ga = mlir::dyn_cast<cir::GlobalViewAttr>(op.getValue())) {
1998 op.emitError() <<
"global view with integer type";
1999 return mlir::failure();
2002 attr = rewriter.getIntegerAttr(
2003 typeConverter->convertType(op.getType()),
2004 mlir::cast<cir::IntAttr>(op.getValue()).getValue());
2005 }
else if (mlir::isa<cir::FPTypeInterface>(op.getType())) {
2006 attr = rewriter.getFloatAttr(
2007 typeConverter->convertType(op.getType()),
2008 mlir::cast<cir::FPAttr>(op.getValue()).getValue());
2009 }
else if (mlir::isa<cir::PointerType>(op.getType())) {
2011 if (mlir::isa<cir::ConstPtrAttr>(op.getValue())) {
2012 if (mlir::cast<cir::ConstPtrAttr>(op.getValue()).isNullValue()) {
2013 rewriter.replaceOpWithNewOp<mlir::LLVM::ZeroOp>(
2014 op, typeConverter->convertType(op.getType()));
2015 return mlir::success();
2019 if (
auto gv = mlir::dyn_cast<cir::GlobalViewAttr>(op.getValue())) {
2021 rewriter.replaceOp(op, newOp);
2022 return mlir::success();
2024 attr = op.getValue();
2025 }
else if (
const auto arrTy = mlir::dyn_cast<cir::ArrayType>(op.getType())) {
2026 const auto constArr = mlir::dyn_cast<cir::ConstArrayAttr>(op.getValue());
2027 if (!constArr && !isa<cir::ZeroAttr, cir::UndefAttr>(op.getValue()))
2028 return op.emitError() <<
"array does not have a constant initializer";
2030 std::optional<mlir::Attribute> denseAttr;
2032 const mlir::Value newOp =
2034 rewriter.replaceOp(op, newOp);
2035 return mlir::success();
2036 }
else if (constArr &&
2038 attr = denseAttr.value();
2040 const mlir::Value initVal =
2042 rewriter.replaceOp(op, initVal);
2043 return mlir::success();
2045 }
else if (
const auto recordAttr =
2046 mlir::dyn_cast<cir::ConstRecordAttr>(op.getValue())) {
2048 rewriter.replaceOp(op, initVal);
2049 return mlir::success();
2050 }
else if (
const auto vecTy = mlir::dyn_cast<cir::VectorType>(op.getType())) {
2052 getTypeConverter()));
2053 return mlir::success();
2054 }
else if (
auto recTy = mlir::dyn_cast<cir::RecordType>(op.getType())) {
2055 if (mlir::isa<cir::ZeroAttr, cir::UndefAttr>(attr)) {
2056 mlir::Value initVal =
2058 rewriter.replaceOp(op, initVal);
2059 return mlir::success();
2061 return op.emitError() <<
"unsupported lowering for record constant type "
2063 }
else if (
auto complexTy = mlir::dyn_cast<cir::ComplexType>(op.getType())) {
2064 mlir::Type complexElemTy = complexTy.getElementType();
2065 mlir::Type complexElemLLVMTy = typeConverter->convertType(complexElemTy);
2067 if (
auto zeroInitAttr = mlir::dyn_cast<cir::ZeroAttr>(op.getValue())) {
2068 mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(complexElemLLVMTy);
2069 mlir::ArrayAttr array = rewriter.getArrayAttr({zeroAttr, zeroAttr});
2070 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
2071 op, getTypeConverter()->convertType(op.getType()), array);
2072 return mlir::success();
2075 auto complexAttr = mlir::cast<cir::ConstComplexAttr>(op.getValue());
2077 mlir::Attribute components[2];
2078 if (mlir::isa<cir::IntType>(complexElemTy)) {
2079 components[0] = rewriter.getIntegerAttr(
2081 mlir::cast<cir::IntAttr>(complexAttr.getReal()).getValue());
2082 components[1] = rewriter.getIntegerAttr(
2084 mlir::cast<cir::IntAttr>(complexAttr.getImag()).getValue());
2086 components[0] = rewriter.getFloatAttr(
2088 mlir::cast<cir::FPAttr>(complexAttr.getReal()).getValue());
2089 components[1] = rewriter.getFloatAttr(
2091 mlir::cast<cir::FPAttr>(complexAttr.getImag()).getValue());
2094 attr = rewriter.getArrayAttr(components);
2096 return op.emitError() <<
"unsupported constant type " << op.getType();
2099 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
2100 op, getTypeConverter()->convertType(op.getType()),
attr);
2102 return mlir::success();
2106 mlir::DataLayout layout(op.getParentOfType<mlir::ModuleOp>());
2108 if (isa<cir::VoidType>(type))
2109 type = cir::IntType::get(type.getContext(), 8,
false);
2110 return llvm::divideCeil(layout.getTypeSizeInBits(type), 8);
2113mlir::LogicalResult CIRToLLVMPrefetchOpLowering::matchAndRewrite(
2114 cir::PrefetchOp op, OpAdaptor adaptor,
2115 mlir::ConversionPatternRewriter &rewriter)
const {
2116 rewriter.replaceOpWithNewOp<mlir::LLVM::Prefetch>(
2117 op, adaptor.getAddr(), adaptor.getIsWrite(), adaptor.getLocality(),
2119 return mlir::success();
2122mlir::LogicalResult CIRToLLVMPtrDiffOpLowering::matchAndRewrite(
2123 cir::PtrDiffOp op, OpAdaptor adaptor,
2124 mlir::ConversionPatternRewriter &rewriter)
const {
2125 auto dstTy = mlir::cast<cir::IntType>(op.getType());
2126 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
2128 auto lhs = mlir::LLVM::PtrToIntOp::create(rewriter, op.getLoc(), llvmDstTy,
2130 auto rhs = mlir::LLVM::PtrToIntOp::create(rewriter, op.getLoc(), llvmDstTy,
2134 mlir::LLVM::SubOp::create(rewriter, op.getLoc(), llvmDstTy, lhs, rhs);
2136 cir::PointerType ptrTy = op.getLhs().getType();
2138 uint64_t typeSize =
getTypeSize(ptrTy.getPointee(), *op);
2141 mlir::Value resultVal = diff.getResult();
2142 if (typeSize != 1) {
2143 auto typeSizeVal = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
2144 llvmDstTy, typeSize);
2146 if (dstTy.isUnsigned()) {
2148 mlir::LLVM::UDivOp::create(rewriter, op.getLoc(), diff, typeSizeVal);
2149 uDiv.setIsExact(
true);
2150 resultVal = uDiv.getResult();
2153 mlir::LLVM::SDivOp::create(rewriter, op.getLoc(), diff, typeSizeVal);
2154 sDiv.setIsExact(
true);
2155 resultVal = sDiv.getResult();
2158 rewriter.replaceOp(op, resultVal);
2159 return mlir::success();
2162mlir::LogicalResult CIRToLLVMExpectOpLowering::matchAndRewrite(
2163 cir::ExpectOp op, OpAdaptor adaptor,
2164 mlir::ConversionPatternRewriter &rewriter)
const {
2168 std::optional<llvm::APFloat> prob = op.getProb();
2170 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpectWithProbabilityOp>(
2171 op, adaptor.getVal(), adaptor.getExpected(), prob.value());
2173 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpectOp>(op, adaptor.getVal(),
2174 adaptor.getExpected());
2175 return mlir::success();
2178mlir::LogicalResult CIRToLLVMAbsOpLowering::matchAndRewrite(
2179 cir::AbsOp op, OpAdaptor adaptor,
2180 mlir::ConversionPatternRewriter &rewriter)
const {
2181 mlir::Type resTy = typeConverter->convertType(op.getType());
2182 auto absOp = mlir::LLVM::AbsOp::create(rewriter, op.getLoc(), resTy,
2183 adaptor.getOperands()[0],
2184 adaptor.getMinIsPoison());
2185 rewriter.replaceOp(op, absOp);
2186 return mlir::success();
2193void CIRToLLVMFuncOpLowering::lowerFuncAttributes(
2194 cir::FuncOp func,
bool filterArgAndResAttrs,
2195 SmallVectorImpl<mlir::NamedAttribute> &result)
const {
2196 for (mlir::NamedAttribute attr : func->getAttrs()) {
2197 if (
attr.getName() == mlir::SymbolTable::getSymbolAttrName() ||
2198 attr.getName() == func.getFunctionTypeAttrName() ||
2200 attr.getName() == func.getCallingConvAttrName() ||
2201 attr.getName() == func.getDsoLocalAttrName() ||
2202 attr.getName() == func.getInlineKindAttrName() ||
2203 attr.getName() == func.getSideEffectAttrName() ||
2204 attr.getName() == CIRDialect::getNoReturnAttrName() ||
2205 attr.getName() == func.getAnnotationsAttrName() ||
2206 (filterArgAndResAttrs &&
2207 (
attr.getName() == func.getArgAttrsAttrName() ||
2208 attr.getName() == func.getResAttrsAttrName())))
2212 result.push_back(attr);
2216mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewriteAlias(
2217 cir::FuncOp op, llvm::StringRef aliasee, mlir::Type ty, OpAdaptor adaptor,
2218 mlir::ConversionPatternRewriter &rewriter)
const {
2219 SmallVector<mlir::NamedAttribute, 4> attributes;
2220 lowerFuncAttributes(op,
false, attributes);
2222 mlir::Location loc = op.getLoc();
2223 auto aliasOp = rewriter.replaceOpWithNewOp<mlir::LLVM::AliasOp>(
2224 op, ty,
convertLinkage(op.getLinkage()), op.getName(), op.getDsoLocal(),
2228 mlir::OpBuilder builder(op.getContext());
2229 mlir::Block *block = builder.createBlock(&aliasOp.getInitializerRegion());
2230 builder.setInsertionPointToStart(block);
2233 mlir::Type ptrTy = mlir::LLVM::LLVMPointerType::get(ty.getContext());
2234 auto addrOp = mlir::LLVM::AddressOfOp::create(builder, loc, ptrTy, aliasee);
2235 mlir::LLVM::ReturnOp::create(builder, loc, addrOp);
2237 return mlir::success();
2240mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewrite(
2241 cir::FuncOp op, OpAdaptor adaptor,
2242 mlir::ConversionPatternRewriter &rewriter)
const {
2244 cir::FuncType fnType = op.getFunctionType();
2245 bool isDsoLocal = op.getDsoLocal();
2246 mlir::TypeConverter::SignatureConversion signatureConversion(
2247 fnType.getNumInputs());
2249 for (
const auto &argType : llvm::enumerate(fnType.getInputs())) {
2250 mlir::Type convertedType = typeConverter->convertType(argType.value());
2252 return mlir::failure();
2253 signatureConversion.addInputs(argType.index(), convertedType);
2256 mlir::Type resultType =
2257 getTypeConverter()->convertType(fnType.getReturnType());
2260 mlir::Type llvmFnTy = mlir::LLVM::LLVMFunctionType::get(
2261 resultType ? resultType : mlir::LLVM::LLVMVoidType::get(getContext()),
2262 signatureConversion.getConvertedTypes(),
2266 if (std::optional<llvm::StringRef> aliasee = op.getAliasee())
2267 return matchAndRewriteAlias(op, *aliasee, llvmFnTy, adaptor, rewriter);
2271 mlir::Location loc = op.getLoc();
2272 if (mlir::FusedLoc fusedLoc = mlir::dyn_cast<mlir::FusedLoc>(loc))
2273 loc = fusedLoc.getLocations()[0];
2274 assert((mlir::isa<mlir::FileLineColLoc>(loc) ||
2275 mlir::isa<mlir::UnknownLoc>(loc)) &&
2276 "expected single location or unknown location here");
2280 SmallVector<mlir::NamedAttribute, 4> attributes;
2281 lowerFuncAttributes(op,
false, attributes);
2283 mlir::LLVM::LLVMFuncOp fn = mlir::LLVM::LLVMFuncOp::create(
2284 rewriter, loc, op.getName(), llvmFnTy, linkage, isDsoLocal, cconv,
2285 mlir::SymbolRefAttr(), attributes);
2289 if (std::optional<cir::SideEffect> sideEffectKind = op.getSideEffect()) {
2290 switch (*sideEffectKind) {
2291 case cir::SideEffect::All:
2293 case cir::SideEffect::Pure:
2294 fn.setMemoryEffectsAttr(mlir::LLVM::MemoryEffectsAttr::get(
2296 mlir::LLVM::ModRefInfo::Ref,
2297 mlir::LLVM::ModRefInfo::Ref,
2298 mlir::LLVM::ModRefInfo::Ref,
2299 mlir::LLVM::ModRefInfo::Ref,
2300 mlir::LLVM::ModRefInfo::Ref,
2301 mlir::LLVM::ModRefInfo::Ref));
2302 fn.setNoUnwind(
true);
2303 fn.setWillReturn(
true);
2305 case cir::SideEffect::Const:
2306 fn.setMemoryEffectsAttr(mlir::LLVM::MemoryEffectsAttr::get(
2308 mlir::LLVM::ModRefInfo::NoModRef,
2309 mlir::LLVM::ModRefInfo::NoModRef,
2310 mlir::LLVM::ModRefInfo::NoModRef,
2311 mlir::LLVM::ModRefInfo::NoModRef,
2312 mlir::LLVM::ModRefInfo::NoModRef,
2313 mlir::LLVM::ModRefInfo::NoModRef));
2314 fn.setNoUnwind(
true);
2315 fn.setWillReturn(
true);
2320 if (op->hasAttr(CIRDialect::getNoReturnAttrName()))
2321 fn.setNoreturn(
true);
2323 if (std::optional<cir::InlineKind> inlineKind = op.getInlineKind()) {
2324 fn.setNoInline(*inlineKind == cir::InlineKind::NoInline);
2325 fn.setInlineHint(*inlineKind == cir::InlineKind::InlineHint);
2326 fn.setAlwaysInline(*inlineKind == cir::InlineKind::AlwaysInline);
2329 if (std::optional<llvm::StringRef> personality = op.getPersonality())
2330 fn.setPersonality(*personality);
2335 rewriter.inlineRegionBefore(op.getBody(), fn.getBody(), fn.end());
2336 if (failed(rewriter.convertRegionTypes(&fn.getBody(), *typeConverter,
2337 &signatureConversion)))
2338 return mlir::failure();
2340 rewriter.eraseOp(op);
2342 return mlir::LogicalResult::success();
2345mlir::LogicalResult CIRToLLVMGetGlobalOpLowering::matchAndRewrite(
2346 cir::GetGlobalOp op, OpAdaptor adaptor,
2347 mlir::ConversionPatternRewriter &rewriter)
const {
2350 if (op->getUses().empty()) {
2351 rewriter.eraseOp(op);
2352 return mlir::success();
2355 mlir::Type
type = getTypeConverter()->convertType(op.getType());
2356 mlir::Operation *newop = mlir::LLVM::AddressOfOp::create(
2357 rewriter, op.getLoc(), type, op.getName());
2361 newop = mlir::LLVM::ThreadlocalAddressOp::create(rewriter, op.getLoc(),
2362 type, newop->getResult(0));
2365 rewriter.replaceOp(op, newop);
2366 return mlir::success();
2369llvm::SmallVector<mlir::NamedAttribute>
2370CIRToLLVMGlobalOpLowering::lowerGlobalAttributes(
2371 cir::GlobalOp op, mlir::ConversionPatternRewriter &rewriter)
const {
2372 SmallVector<mlir::NamedAttribute> attributes;
2374 if (mlir::StringAttr sectionAttr = op.getSectionAttr())
2375 attributes.push_back(rewriter.getNamedAttr(
"section", sectionAttr));
2377 mlir::LLVM::VisibilityAttr visibility = mlir::LLVM::VisibilityAttr::get(
2380 attributes.push_back(rewriter.getNamedAttr(
"visibility_", visibility));
2382 if (op->getAttr(CUDAExternallyInitializedAttr::getMnemonic()))
2383 attributes.push_back(rewriter.getNamedAttr(
"externally_initialized",
2384 rewriter.getUnitAttr()));
2391void CIRToLLVMGlobalOpLowering::setupRegionInitializedLLVMGlobalOp(
2392 cir::GlobalOp op, mlir::ConversionPatternRewriter &rewriter)
const {
2393 const mlir::Type llvmType =
2400 const bool isConst = op.getConstant();
2401 unsigned addrSpace = 0;
2402 if (
auto targetAS = mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
2403 op.getAddrSpaceAttr()))
2404 addrSpace = targetAS.getValue();
2405 const bool isDsoLocal = op.getDsoLocal();
2406 const bool isThreadLocal = (
bool)op.getTlsModelAttr();
2407 const uint64_t alignment = op.getAlignment().value_or(0);
2408 const mlir::LLVM::Linkage linkage =
convertLinkage(op.getLinkage());
2409 const StringRef symbol = op.getSymName();
2410 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
2412 SmallVector<mlir::NamedAttribute> attributes =
2413 lowerGlobalAttributes(op, rewriter);
2415 mlir::LLVM::GlobalOp newGlobalOp =
2416 rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
2417 op, llvmType, isConst, linkage, symbol,
nullptr, alignment, addrSpace,
2418 isDsoLocal, isThreadLocal, comdatAttr, attributes);
2419 newGlobalOp.getRegion().emplaceBlock();
2420 rewriter.setInsertionPointToEnd(newGlobalOp.getInitializerBlock());
2424CIRToLLVMGlobalOpLowering::matchAndRewriteRegionInitializedGlobal(
2425 cir::GlobalOp op, mlir::Attribute init,
2426 mlir::ConversionPatternRewriter &rewriter)
const {
2428 assert((isa<cir::ConstArrayAttr, cir::ConstRecordAttr, cir::ConstVectorAttr,
2429 cir::ConstPtrAttr, cir::ConstComplexAttr, cir::GlobalViewAttr,
2430 cir::TypeInfoAttr, cir::UndefAttr, cir::PoisonAttr,
2431 cir::VTableAttr, cir::ZeroAttr>(init)));
2436 const mlir::Location loc = op.getLoc();
2437 setupRegionInitializedLLVMGlobalOp(op, rewriter);
2439 mlir::Value value = valueConverter.visit(init);
2440 mlir::LLVM::ReturnOp::create(rewriter, loc, value);
2441 return mlir::success();
2444mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite(
2445 cir::GlobalOp op, OpAdaptor adaptor,
2446 mlir::ConversionPatternRewriter &rewriter)
const {
2449 if (!op.getCtorRegion().empty() || !op.getDtorRegion().empty())
2450 return op.emitError() <<
"GlobalOp ctor and dtor regions should be removed "
2451 "in LoweringPrepare";
2453 std::optional<mlir::Attribute> init = op.getInitialValue();
2456 const mlir::Type cirSymType = op.getSymType();
2459 const mlir::Type llvmType =
2464 const bool isConst = op.getConstant();
2465 unsigned addrSpace = 0;
2466 if (
auto targetAS = mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
2467 op.getAddrSpaceAttr()))
2468 addrSpace = targetAS.getValue();
2469 const bool isDsoLocal = op.getDsoLocal();
2470 const bool isThreadLocal = (
bool)op.getTlsModelAttr();
2471 const uint64_t alignment = op.getAlignment().value_or(0);
2472 const mlir::LLVM::Linkage linkage =
convertLinkage(op.getLinkage());
2473 const StringRef symbol = op.getSymName();
2474 SmallVector<mlir::NamedAttribute> attributes =
2475 lowerGlobalAttributes(op, rewriter);
2478 if (std::optional<llvm::StringRef> aliasee = op.getAliasee()) {
2479 mlir::Location loc = op.getLoc();
2480 auto aliasOp = rewriter.replaceOpWithNewOp<mlir::LLVM::AliasOp>(
2481 op, llvmType, linkage, symbol, isDsoLocal, isThreadLocal, attributes);
2483 mlir::OpBuilder builder(op.getContext());
2484 mlir::Block *block = builder.createBlock(&aliasOp.getInitializerRegion());
2485 builder.setInsertionPointToStart(block);
2487 mlir::LLVM::LLVMPointerType::get(getContext(), addrSpace);
2489 mlir::LLVM::AddressOfOp::create(builder, loc, ptrTy, *aliasee);
2490 mlir::LLVM::ReturnOp::create(builder, loc, addrOp);
2491 return mlir::success();
2494 if (init.has_value()) {
2495 if (mlir::isa<cir::FPAttr, cir::IntAttr, cir::BoolAttr>(init.value())) {
2497 init = initRewriter.visit(init.value());
2502 if (!init.value()) {
2503 op.emitError() <<
"unsupported initializer '" << init.value() <<
"'";
2504 return mlir::failure();
2506 }
else if (mlir::isa<cir::ConstArrayAttr, cir::ConstVectorAttr,
2507 cir::ConstRecordAttr, cir::ConstPtrAttr,
2508 cir::ConstComplexAttr, cir::GlobalViewAttr,
2509 cir::TypeInfoAttr, cir::UndefAttr, cir::PoisonAttr,
2510 cir::VTableAttr, cir::ZeroAttr>(init.value())) {
2514 return matchAndRewriteRegionInitializedGlobal(op, init.value(), rewriter);
2518 op.emitError() <<
"unsupported initializer '" << init.value() <<
"'";
2519 return mlir::failure();
2523 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
2524 rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
2525 op, llvmType, isConst, linkage, symbol, init.value_or(mlir::Attribute()),
2526 alignment, addrSpace, isDsoLocal, isThreadLocal, comdatAttr, attributes);
2528 return mlir::success();
2532CIRToLLVMGlobalOpLowering::getComdatAttr(cir::GlobalOp &op,
2533 mlir::OpBuilder &builder)
const {
2534 if (!op.getComdat())
2535 return mlir::SymbolRefAttr{};
2537 mlir::ModuleOp module = op->getParentOfType<mlir::ModuleOp>();
2538 mlir::OpBuilder::InsertionGuard guard(builder);
2539 StringRef comdatName(
"__llvm_comdat_globals");
2541 builder.setInsertionPointToStart(module.getBody());
2543 mlir::LLVM::ComdatOp::create(builder, module.getLoc(), comdatName);
2546 if (
auto comdatSelector = comdatOp.lookupSymbol<mlir::LLVM::ComdatSelectorOp>(
2548 return mlir::SymbolRefAttr::get(
2549 builder.getContext(), comdatName,
2550 mlir::FlatSymbolRefAttr::get(comdatSelector.getSymNameAttr()));
2553 builder.setInsertionPointToStart(&comdatOp.getBody().back());
2554 auto selectorOp = mlir::LLVM::ComdatSelectorOp::create(
2555 builder, comdatOp.getLoc(), op.getSymName(),
2556 mlir::LLVM::comdat::Comdat::Any);
2557 return mlir::SymbolRefAttr::get(
2558 builder.getContext(), comdatName,
2559 mlir::FlatSymbolRefAttr::get(selectorOp.getSymNameAttr()));
2562mlir::LogicalResult CIRToLLVMSwitchFlatOpLowering::matchAndRewrite(
2563 cir::SwitchFlatOp op, OpAdaptor adaptor,
2564 mlir::ConversionPatternRewriter &rewriter)
const {
2566 llvm::SmallVector<mlir::APInt, 8> caseValues;
2567 for (mlir::Attribute val : op.getCaseValues()) {
2568 auto intAttr = cast<cir::IntAttr>(val);
2569 caseValues.push_back(intAttr.getValue());
2572 llvm::SmallVector<mlir::Block *, 8> caseDestinations;
2573 llvm::SmallVector<mlir::ValueRange, 8> caseOperands;
2575 for (mlir::Block *x : op.getCaseDestinations())
2576 caseDestinations.push_back(x);
2578 for (mlir::OperandRange x : op.getCaseOperands())
2579 caseOperands.push_back(x);
2582 rewriter.setInsertionPoint(op);
2583 rewriter.replaceOpWithNewOp<mlir::LLVM::SwitchOp>(
2584 op, adaptor.getCondition(), op.getDefaultDestination(),
2585 op.getDefaultOperands(), caseValues, caseDestinations, caseOperands);
2586 return mlir::success();
2589static mlir::LLVM::IntegerOverflowFlags
nswFlag(
bool nsw) {
2590 return nsw ? mlir::LLVM::IntegerOverflowFlags::nsw
2591 : mlir::LLVM::IntegerOverflowFlags::none;
2594template <
typename CIROp,
typename LLVMIntOp>
2595static mlir::LogicalResult
2597 mlir::ConversionPatternRewriter &rewriter,
double fpConstant) {
2598 mlir::Type elementType = elementTypeIfVector(op.getType());
2599 mlir::Type llvmType = adaptor.getInput().getType();
2600 mlir::Location loc = op.getLoc();
2602 if (mlir::isa<cir::IntType>(elementType)) {
2603 auto maybeNSW =
nswFlag(op.getNoSignedWrap());
2604 auto one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
2605 rewriter.replaceOpWithNewOp<LLVMIntOp>(op, adaptor.getInput(), one,
2607 return mlir::success();
2609 if (mlir::isa<cir::FPTypeInterface>(elementType)) {
2610 auto fpConst = mlir::LLVM::ConstantOp::create(
2611 rewriter, loc, rewriter.getFloatAttr(llvmType, fpConstant));
2612 rewriter.replaceOpWithNewOp<mlir::LLVM::FAddOp>(op, fpConst,
2613 adaptor.getInput());
2614 return mlir::success();
2616 return op.emitError() <<
"Unsupported type for IncOp/DecOp";
2619mlir::LogicalResult CIRToLLVMIncOpLowering::matchAndRewrite(
2620 cir::IncOp op, OpAdaptor adaptor,
2621 mlir::ConversionPatternRewriter &rewriter)
const {
2626mlir::LogicalResult CIRToLLVMDecOpLowering::matchAndRewrite(
2627 cir::DecOp op, OpAdaptor adaptor,
2628 mlir::ConversionPatternRewriter &rewriter)
const {
2633mlir::LogicalResult CIRToLLVMMinusOpLowering::matchAndRewrite(
2634 cir::MinusOp op, OpAdaptor adaptor,
2635 mlir::ConversionPatternRewriter &rewriter)
const {
2636 mlir::Type elementType = elementTypeIfVector(op.getType());
2637 bool isVector = mlir::isa<cir::VectorType>(op.getType());
2638 mlir::Type llvmType = adaptor.getInput().getType();
2639 mlir::Location loc = op.getLoc();
2641 if (mlir::isa<cir::IntType>(elementType)) {
2642 auto maybeNSW =
nswFlag(op.getNoSignedWrap());
2645 zero = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmType);
2647 zero = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 0);
2648 rewriter.replaceOpWithNewOp<mlir::LLVM::SubOp>(op, zero, adaptor.getInput(),
2650 return mlir::success();
2652 if (mlir::isa<cir::FPTypeInterface>(elementType)) {
2653 rewriter.replaceOpWithNewOp<mlir::LLVM::FNegOp>(op, adaptor.getInput());
2654 return mlir::success();
2656 return op.emitError() <<
"Unsupported type for unary minus";
2659mlir::LogicalResult CIRToLLVMNotOpLowering::matchAndRewrite(
2660 cir::NotOp op, OpAdaptor adaptor,
2661 mlir::ConversionPatternRewriter &rewriter)
const {
2662 mlir::Type elementType = elementTypeIfVector(op.getType());
2663 bool isVector = mlir::isa<cir::VectorType>(op.getType());
2664 mlir::Type llvmType = adaptor.getInput().getType();
2665 mlir::Location loc = op.getLoc();
2667 if (mlir::isa<cir::IntType>(elementType)) {
2668 mlir::Value minusOne;
2671 mlir::dyn_cast<cir::VectorType>(op.getType()).getSize();
2672 SmallVector<int32_t> values(numElements, -1);
2673 mlir::DenseIntElementsAttr denseVec = rewriter.getI32VectorAttr(values);
2675 mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, denseVec);
2677 minusOne = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, -1);
2679 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getInput(),
2681 return mlir::success();
2683 if (mlir::isa<cir::BoolType>(elementType)) {
2684 auto one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
2685 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getInput(), one);
2686 return mlir::success();
2688 return op.emitError() <<
"Unsupported type for bitwise NOT";
2693 return mlir::isa<cir::IntType>(type)
2694 ? mlir::cast<cir::IntType>(type).isUnsigned()
2695 : mlir::cast<mlir::IntegerType>(type).isUnsigned();
2702template <
typename BinOp>
2704 if (op.getNoUnsignedWrap())
2705 return mlir::LLVM::IntegerOverflowFlags::nuw;
2706 if (op.getNoSignedWrap())
2707 return mlir::LLVM::IntegerOverflowFlags::nsw;
2708 return mlir::LLVM::IntegerOverflowFlags::none;
2713template <
typename UIntSatOp,
typename SIntSatOp,
typename IntOp,
typename FPOp,
2715static mlir::LogicalResult
2717 mlir::ConversionPatternRewriter &rewriter) {
2718 const mlir::Type eltType = elementTypeIfVector(op.getRhs().getType());
2719 if (cir::isIntOrBoolType(eltType)) {
2720 if (op.getSaturated()) {
2722 rewriter.replaceOpWithNewOp<UIntSatOp>(op, lhs, rhs);
2724 rewriter.replaceOpWithNewOp<SIntSatOp>(op, lhs, rhs);
2725 return mlir::success();
2727 rewriter.replaceOpWithNewOp<IntOp>(op, lhs, rhs,
intOverflowFlag(op));
2729 rewriter.replaceOpWithNewOp<FPOp>(op, lhs, rhs);
2731 return mlir::success();
2734mlir::LogicalResult CIRToLLVMAddOpLowering::matchAndRewrite(
2735 cir::AddOp op, OpAdaptor adaptor,
2736 mlir::ConversionPatternRewriter &rewriter)
const {
2738 mlir::LLVM::AddOp, mlir::LLVM::FAddOp>(
2739 op, adaptor.getLhs(), adaptor.getRhs(), rewriter);
2742mlir::LogicalResult CIRToLLVMSubOpLowering::matchAndRewrite(
2743 cir::SubOp op, OpAdaptor adaptor,
2744 mlir::ConversionPatternRewriter &rewriter)
const {
2746 mlir::LLVM::SubOp, mlir::LLVM::FSubOp>(
2747 op, adaptor.getLhs(), adaptor.getRhs(), rewriter);
2750mlir::LogicalResult CIRToLLVMMulOpLowering::matchAndRewrite(
2751 cir::MulOp op, OpAdaptor adaptor,
2752 mlir::ConversionPatternRewriter &rewriter)
const {
2753 const mlir::Value lhs = adaptor.getLhs();
2754 const mlir::Value rhs = adaptor.getRhs();
2755 if (cir::isIntOrBoolType(elementTypeIfVector(op.getRhs().getType()))) {
2756 rewriter.replaceOpWithNewOp<mlir::LLVM::MulOp>(op, lhs, rhs,
2759 rewriter.replaceOpWithNewOp<mlir::LLVM::FMulOp>(op, lhs, rhs);
2761 return mlir::success();
2766template <
typename UIntOp,
typename SIntOp,
typename FPOp,
typename CIROp>
2767static mlir::LogicalResult
2769 mlir::ConversionPatternRewriter &rewriter) {
2770 const mlir::Type eltType = elementTypeIfVector(op.getRhs().getType());
2771 if (cir::isIntOrBoolType(eltType)) {
2773 rewriter.replaceOpWithNewOp<UIntOp>(op, lhs, rhs);
2775 rewriter.replaceOpWithNewOp<SIntOp>(op, lhs, rhs);
2777 rewriter.replaceOpWithNewOp<FPOp>(op, lhs, rhs);
2779 return mlir::success();
2782mlir::LogicalResult CIRToLLVMDivOpLowering::matchAndRewrite(
2783 cir::DivOp op, OpAdaptor adaptor,
2784 mlir::ConversionPatternRewriter &rewriter)
const {
2786 mlir::LLVM::FDivOp>(op, adaptor.getLhs(),
2787 adaptor.getRhs(), rewriter);
2790mlir::LogicalResult CIRToLLVMRemOpLowering::matchAndRewrite(
2791 cir::RemOp op, OpAdaptor adaptor,
2792 mlir::ConversionPatternRewriter &rewriter)
const {
2794 mlir::LLVM::FRemOp>(op, adaptor.getLhs(),
2795 adaptor.getRhs(), rewriter);
2798mlir::LogicalResult CIRToLLVMAndOpLowering::matchAndRewrite(
2799 cir::AndOp op, OpAdaptor adaptor,
2800 mlir::ConversionPatternRewriter &rewriter)
const {
2801 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(op, adaptor.getLhs(),
2803 return mlir::success();
2806mlir::LogicalResult CIRToLLVMOrOpLowering::matchAndRewrite(
2807 cir::OrOp op, OpAdaptor adaptor,
2808 mlir::ConversionPatternRewriter &rewriter)
const {
2809 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(op, adaptor.getLhs(),
2811 return mlir::success();
2814mlir::LogicalResult CIRToLLVMXorOpLowering::matchAndRewrite(
2815 cir::XorOp op, OpAdaptor adaptor,
2816 mlir::ConversionPatternRewriter &rewriter)
const {
2817 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getLhs(),
2819 return mlir::success();
2822template <
typename CIROp,
typename UIntOp,
typename SIntOp>
2823static mlir::LogicalResult
2825 mlir::ConversionPatternRewriter &rewriter) {
2826 const mlir::Value lhs = adaptor.getLhs();
2827 const mlir::Value rhs = adaptor.getRhs();
2829 rewriter.replaceOpWithNewOp<UIntOp>(op, lhs, rhs);
2831 rewriter.replaceOpWithNewOp<SIntOp>(op, lhs, rhs);
2832 return mlir::success();
2835mlir::LogicalResult CIRToLLVMMaxOpLowering::matchAndRewrite(
2836 cir::MaxOp op, OpAdaptor adaptor,
2837 mlir::ConversionPatternRewriter &rewriter)
const {
2839 op, adaptor, rewriter);
2842mlir::LogicalResult CIRToLLVMMinOpLowering::matchAndRewrite(
2843 cir::MinOp op, OpAdaptor adaptor,
2844 mlir::ConversionPatternRewriter &rewriter)
const {
2846 op, adaptor, rewriter);
2850static mlir::LLVM::ICmpPredicate
2852 using CIR = cir::CmpOpKind;
2853 using LLVMICmp = mlir::LLVM::ICmpPredicate;
2856 return LLVMICmp::eq;
2858 return LLVMICmp::ne;
2860 return (isSigned ? LLVMICmp::slt : LLVMICmp::ult);
2862 return (isSigned ? LLVMICmp::sle : LLVMICmp::ule);
2864 return (isSigned ? LLVMICmp::sgt : LLVMICmp::ugt);
2866 return (isSigned ? LLVMICmp::sge : LLVMICmp::uge);
2869 llvm_unreachable(
"FP-only comparison used with integer type");
2871 llvm_unreachable(
"Unknown CmpOpKind");
2876static mlir::LLVM::FCmpPredicate
2878 using CIR = cir::CmpOpKind;
2879 using LLVMFCmp = mlir::LLVM::FCmpPredicate;
2882 return LLVMFCmp::oeq;
2884 return LLVMFCmp::une;
2886 return LLVMFCmp::olt;
2888 return LLVMFCmp::ole;
2890 return LLVMFCmp::ogt;
2892 return LLVMFCmp::oge;
2894 return LLVMFCmp::one;
2896 return LLVMFCmp::uno;
2898 llvm_unreachable(
"Unknown CmpOpKind");
2901mlir::LogicalResult CIRToLLVMCmpOpLowering::matchAndRewrite(
2902 cir::CmpOp cmpOp, OpAdaptor adaptor,
2903 mlir::ConversionPatternRewriter &rewriter)
const {
2904 mlir::Type type = cmpOp.getLhs().getType();
2906 if (mlir::isa<cir::IntType, mlir::IntegerType>(type)) {
2907 bool isSigned = mlir::isa<cir::IntType>(type)
2908 ? mlir::cast<cir::IntType>(type).isSigned()
2909 : mlir::cast<mlir::IntegerType>(type).isSigned();
2910 mlir::LLVM::ICmpPredicate
kind =
2912 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
2913 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
2914 return mlir::success();
2917 if (
auto ptrTy = mlir::dyn_cast<cir::PointerType>(type)) {
2918 mlir::LLVM::ICmpPredicate
kind =
2921 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
2922 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
2923 return mlir::success();
2926 if (
auto vptrTy = mlir::dyn_cast<cir::VPtrType>(type)) {
2930 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
2931 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
2932 return mlir::success();
2935 if (mlir::isa<cir::FPTypeInterface>(type)) {
2936 mlir::LLVM::FCmpPredicate
kind =
2938 rewriter.replaceOpWithNewOp<mlir::LLVM::FCmpOp>(
2939 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
2940 return mlir::success();
2943 if (mlir::isa<cir::ComplexType>(type)) {
2944 mlir::Value lhs = adaptor.getLhs();
2945 mlir::Value rhs = adaptor.getRhs();
2946 mlir::Location loc = cmpOp.getLoc();
2948 auto complexType = mlir::cast<cir::ComplexType>(cmpOp.getLhs().getType());
2949 mlir::Type complexElemTy =
2950 getTypeConverter()->convertType(
complexType.getElementType());
2952 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
2953 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{0}));
2954 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
2955 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{1}));
2956 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
2957 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{0}));
2958 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
2959 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{1}));
2961 if (cmpOp.getKind() == cir::CmpOpKind::eq) {
2962 if (complexElemTy.isInteger()) {
2963 auto realCmp = mlir::LLVM::ICmpOp::create(
2964 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, lhsReal, rhsReal);
2965 auto imagCmp = mlir::LLVM::ICmpOp::create(
2966 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, lhsImag, rhsImag);
2967 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, imagCmp);
2968 return mlir::success();
2971 auto realCmp = mlir::LLVM::FCmpOp::create(
2972 rewriter, loc, mlir::LLVM::FCmpPredicate::oeq, lhsReal, rhsReal);
2973 auto imagCmp = mlir::LLVM::FCmpOp::create(
2974 rewriter, loc, mlir::LLVM::FCmpPredicate::oeq, lhsImag, rhsImag);
2975 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, imagCmp);
2976 return mlir::success();
2979 if (cmpOp.getKind() == cir::CmpOpKind::ne) {
2980 if (complexElemTy.isInteger()) {
2981 auto realCmp = mlir::LLVM::ICmpOp::create(
2982 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, lhsReal, rhsReal);
2983 auto imagCmp = mlir::LLVM::ICmpOp::create(
2984 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, lhsImag, rhsImag);
2985 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp);
2986 return mlir::success();
2989 auto realCmp = mlir::LLVM::FCmpOp::create(
2990 rewriter, loc, mlir::LLVM::FCmpPredicate::une, lhsReal, rhsReal);
2991 auto imagCmp = mlir::LLVM::FCmpOp::create(
2992 rewriter, loc, mlir::LLVM::FCmpPredicate::une, lhsImag, rhsImag);
2993 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp);
2994 return mlir::success();
2998 return cmpOp.emitError() <<
"unsupported type for CmpOp: " <<
type;
3004template <
typename OpTy>
3005static mlir::LogicalResult
3007 mlir::ConversionPatternRewriter &rewriter,
3008 const mlir::TypeConverter *typeConverter,
3009 llvm::StringRef opStr) {
3010 mlir::Location loc = op.getLoc();
3011 cir::IntType operandTy = op.getLhs().getType();
3012 cir::IntType resultTy = op.getResult().getType();
3014 bool sign = operandTy.getIsSigned() || resultTy.getIsSigned();
3016 std::max(operandTy.getWidth() + (
sign && operandTy.isUnsigned()),
3017 resultTy.getWidth() + (
sign && resultTy.isUnsigned()));
3019 mlir::IntegerType encompassedLLVMTy = rewriter.getIntegerType(width);
3021 mlir::Value lhs = adaptor.getLhs();
3022 mlir::Value rhs = adaptor.getRhs();
3023 if (operandTy.getWidth() < width) {
3024 if (operandTy.isSigned()) {
3025 lhs = mlir::LLVM::SExtOp::create(rewriter, loc, encompassedLLVMTy, lhs);
3026 rhs = mlir::LLVM::SExtOp::create(rewriter, loc, encompassedLLVMTy, rhs);
3028 lhs = mlir::LLVM::ZExtOp::create(rewriter, loc, encompassedLLVMTy, lhs);
3029 rhs = mlir::LLVM::ZExtOp::create(rewriter, loc, encompassedLLVMTy, rhs);
3034 std::string intrinName = (
"llvm." + llvm::Twine(
sign ?
's' :
'u') + opStr +
3035 ".with.overflow.i" + llvm::Twine(width))
3037 auto intrinNameAttr = mlir::StringAttr::get(op.getContext(), intrinName);
3039 mlir::IntegerType overflowLLVMTy = rewriter.getI1Type();
3040 auto intrinRetTy = mlir::LLVM::LLVMStructType::getLiteral(
3041 rewriter.getContext(), {encompassedLLVMTy, overflowLLVMTy});
3043 auto callLLVMIntrinOp = mlir::LLVM::CallIntrinsicOp::create(
3044 rewriter, loc, intrinRetTy, intrinNameAttr, mlir::ValueRange{lhs, rhs});
3045 mlir::Value intrinRet = callLLVMIntrinOp.getResult(0);
3047 mlir::Value result = mlir::LLVM::ExtractValueOp::create(
3050 mlir::Value overflow = mlir::LLVM::ExtractValueOp::create(
3054 if (resultTy.getWidth() < width) {
3055 mlir::Type resultLLVMTy = typeConverter->convertType(resultTy);
3057 mlir::LLVM::TruncOp::create(rewriter, loc, resultLLVMTy, result);
3061 mlir::Value truncResultExt;
3062 if (resultTy.isSigned())
3063 truncResultExt = mlir::LLVM::SExtOp::create(
3064 rewriter, loc, encompassedLLVMTy, truncResult);
3066 truncResultExt = mlir::LLVM::ZExtOp::create(
3067 rewriter, loc, encompassedLLVMTy, truncResult);
3068 auto truncOverflow = mlir::LLVM::ICmpOp::create(
3069 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, truncResultExt, result);
3071 result = truncResult;
3072 overflow = mlir::LLVM::OrOp::create(rewriter, loc, overflow, truncOverflow);
3075 mlir::Type boolLLVMTy =
3076 typeConverter->convertType(op.getOverflow().getType());
3077 if (boolLLVMTy != rewriter.getI1Type())
3078 overflow = mlir::LLVM::ZExtOp::create(rewriter, loc, boolLLVMTy, overflow);
3080 rewriter.replaceOp(op, mlir::ValueRange{result, overflow});
3082 return mlir::success();
3085mlir::LogicalResult CIRToLLVMAddOverflowOpLowering::matchAndRewrite(
3086 cir::AddOverflowOp op, OpAdaptor adaptor,
3087 mlir::ConversionPatternRewriter &rewriter)
const {
3091mlir::LogicalResult CIRToLLVMSubOverflowOpLowering::matchAndRewrite(
3092 cir::SubOverflowOp op, OpAdaptor adaptor,
3093 mlir::ConversionPatternRewriter &rewriter)
const {
3097mlir::LogicalResult CIRToLLVMMulOverflowOpLowering::matchAndRewrite(
3098 cir::MulOverflowOp op, OpAdaptor adaptor,
3099 mlir::ConversionPatternRewriter &rewriter)
const {
3103mlir::LogicalResult CIRToLLVMFrexpOpLowering::matchAndRewrite(
3104 cir::FrexpOp op, OpAdaptor adaptor,
3105 mlir::ConversionPatternRewriter &rewriter)
const {
3106 mlir::Location loc = op.getLoc();
3107 mlir::Type fpLLVMTy =
3108 getTypeConverter()->convertType(op.getResult().getType());
3109 mlir::Type intLLVMTy = getTypeConverter()->convertType(op.getExp().getType());
3111 auto structTy = mlir::LLVM::LLVMStructType::getLiteral(rewriter.getContext(),
3112 {fpLLVMTy, intLLVMTy});
3116 mlir::Value result = callOp.getResult(0);
3118 mlir::Value mantissa =
3119 mlir::LLVM::ExtractValueOp::create(rewriter, loc, result, 0);
3120 mlir::Value exponent =
3121 mlir::LLVM::ExtractValueOp::create(rewriter, loc, result, 1);
3122 rewriter.replaceOp(op, mlir::ValueRange{mantissa, exponent});
3123 return mlir::success();
3126mlir::LogicalResult CIRToLLVMModfOpLowering::matchAndRewrite(
3127 cir::ModfOp op, OpAdaptor adaptor,
3128 mlir::ConversionPatternRewriter &rewriter)
const {
3129 mlir::Location loc = op.getLoc();
3130 mlir::Type fpLLVMTy =
3131 getTypeConverter()->convertType(op.getFractional().getType());
3133 auto structTy = mlir::LLVM::LLVMStructType::getLiteral(rewriter.getContext(),
3134 {fpLLVMTy, fpLLVMTy});
3138 mlir::Value result = callOp.getResult(0);
3140 mlir::Value fractional =
3141 mlir::LLVM::ExtractValueOp::create(rewriter, loc, result, 0);
3142 mlir::Value integral =
3143 mlir::LLVM::ExtractValueOp::create(rewriter, loc, result, 1);
3144 rewriter.replaceOp(op, mlir::ValueRange{fractional, integral});
3145 return mlir::success();
3148mlir::LogicalResult CIRToLLVMShiftOpLowering::matchAndRewrite(
3149 cir::ShiftOp op, OpAdaptor adaptor,
3150 mlir::ConversionPatternRewriter &rewriter)
const {
3151 assert((op.getValue().getType() == op.getType()) &&
3152 "inconsistent operands' types NYI");
3154 const mlir::Type llvmTy = getTypeConverter()->convertType(op.getType());
3155 mlir::Value amt = adaptor.getAmount();
3156 mlir::Value val = adaptor.getValue();
3158 auto cirAmtTy = mlir::dyn_cast<cir::IntType>(op.getAmount().getType());
3161 auto cirValTy = mlir::cast<cir::IntType>(op.getValue().getType());
3169 amt =
getLLVMIntCast(rewriter, amt, llvmTy,
true, cirAmtTy.getWidth(),
3170 cirValTy.getWidth());
3172 auto cirValVTy = mlir::cast<cir::VectorType>(op.getValue().getType());
3174 mlir::cast<cir::IntType>(cirValVTy.getElementType()).isUnsigned();
3178 if (op.getIsShiftleft()) {
3179 rewriter.replaceOpWithNewOp<mlir::LLVM::ShlOp>(op, llvmTy, val, amt);
3180 return mlir::success();
3184 rewriter.replaceOpWithNewOp<mlir::LLVM::LShrOp>(op, llvmTy, val, amt);
3186 rewriter.replaceOpWithNewOp<mlir::LLVM::AShrOp>(op, llvmTy, val, amt);
3187 return mlir::success();
3190mlir::LogicalResult CIRToLLVMSelectOpLowering::matchAndRewrite(
3191 cir::SelectOp op, OpAdaptor adaptor,
3192 mlir::ConversionPatternRewriter &rewriter)
const {
3193 auto getConstantBool = [](mlir::Value value) -> cir::BoolAttr {
3194 auto definingOp = value.getDefiningOp<cir::ConstantOp>();
3198 auto constValue = definingOp.getValueAttr<cir::BoolAttr>();
3208 if (mlir::isa<cir::BoolType>(op.getTrueValue().getType())) {
3209 cir::BoolAttr trueValue = getConstantBool(op.getTrueValue());
3210 cir::BoolAttr falseValue = getConstantBool(op.getFalseValue());
3211 if (falseValue && !falseValue.getValue()) {
3213 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(op, adaptor.getCondition(),
3214 adaptor.getTrueValue());
3215 return mlir::success();
3217 if (trueValue && trueValue.getValue()) {
3219 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(op, adaptor.getCondition(),
3220 adaptor.getFalseValue());
3221 return mlir::success();
3225 mlir::Value llvmCondition = adaptor.getCondition();
3226 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(
3227 op, llvmCondition, adaptor.getTrueValue(), adaptor.getFalseValue());
3229 return mlir::success();
3233 mlir::DataLayout &dataLayout) {
3234 converter.addConversion([&](cir::PointerType type) -> mlir::Type {
3235 mlir::ptr::MemorySpaceAttrInterface addrSpaceAttr = type.getAddrSpace();
3236 unsigned numericAS = 0;
3238 if (
auto targetAsAttr =
3239 mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
3241 numericAS = targetAsAttr.getValue();
3242 return mlir::LLVM::LLVMPointerType::get(type.getContext(), numericAS);
3244 converter.addConversion([&](cir::VPtrType type) -> mlir::Type {
3246 return mlir::LLVM::LLVMPointerType::get(type.getContext());
3248 converter.addConversion([&](cir::ArrayType type) -> mlir::Type {
3251 return mlir::LLVM::LLVMArrayType::get(ty, type.getSize());
3253 converter.addConversion([&](cir::VectorType type) -> mlir::Type {
3254 const mlir::Type ty = converter.convertType(type.getElementType());
3255 return mlir::VectorType::get(type.getSize(), ty, {type.getIsScalable()});
3257 converter.addConversion([&](cir::BoolType type) -> mlir::Type {
3258 return mlir::IntegerType::get(type.getContext(), 1,
3259 mlir::IntegerType::Signless);
3261 converter.addConversion([&](cir::IntType type) -> mlir::Type {
3263 return mlir::IntegerType::get(type.getContext(), type.getWidth());
3265 converter.addConversion([&](cir::SingleType type) -> mlir::Type {
3266 return mlir::Float32Type::get(type.getContext());
3268 converter.addConversion([&](cir::DoubleType type) -> mlir::Type {
3269 return mlir::Float64Type::get(type.getContext());
3271 converter.addConversion([&](cir::FP80Type type) -> mlir::Type {
3272 return mlir::Float80Type::get(type.getContext());
3274 converter.addConversion([&](cir::FP128Type type) -> mlir::Type {
3275 return mlir::Float128Type::get(type.getContext());
3277 converter.addConversion([&](cir::LongDoubleType type) -> mlir::Type {
3278 return converter.convertType(type.getUnderlying());
3280 converter.addConversion([&](cir::FP16Type type) -> mlir::Type {
3281 return mlir::Float16Type::get(type.getContext());
3283 converter.addConversion([&](cir::BF16Type type) -> mlir::Type {
3284 return mlir::BFloat16Type::get(type.getContext());
3286 converter.addConversion([&](cir::ComplexType type) -> mlir::Type {
3289 mlir::Type elementTy = converter.convertType(type.getElementType());
3290 mlir::Type structFields[2] = {elementTy, elementTy};
3291 return mlir::LLVM::LLVMStructType::getLiteral(type.getContext(),
3294 converter.addConversion([&](cir::FuncType type) -> std::optional<mlir::Type> {
3295 auto result = converter.convertType(type.getReturnType());
3297 arguments.reserve(type.getNumInputs());
3298 if (converter.convertTypes(type.getInputs(), arguments).failed())
3299 return std::nullopt;
3300 auto varArg = type.isVarArg();
3301 return mlir::LLVM::LLVMFunctionType::get(result, arguments, varArg);
3303 converter.addConversion([&](cir::RecordType type) -> mlir::Type {
3306 switch (type.getKind()) {
3307 case cir::RecordType::Class:
3308 case cir::RecordType::Struct:
3309 for (mlir::Type ty : type.getMembers())
3313 case cir::RecordType::Union:
3314 if (type.getMembers().empty())
3316 if (
auto largestMember = type.getLargestMember(dataLayout))
3317 llvmMembers.push_back(
3319 if (type.getPadded()) {
3320 auto last = *type.getMembers().rbegin();
3321 llvmMembers.push_back(
3328 mlir::LLVM::LLVMStructType llvmStruct;
3329 if (type.getName()) {
3330 llvmStruct = mlir::LLVM::LLVMStructType::getIdentified(
3331 type.getContext(), type.getPrefixedName());
3332 if (llvmStruct.setBody(llvmMembers, type.getPacked()).failed())
3333 llvm_unreachable(
"Failed to set body of record");
3335 llvmStruct = mlir::LLVM::LLVMStructType::getLiteral(
3336 type.getContext(), llvmMembers, type.getPacked());
3341 converter.addConversion([&](cir::VoidType type) -> mlir::Type {
3342 return mlir::LLVM::LLVMVoidType::get(type.getContext());
3347 mlir::ModuleOp module, StringRef globalXtorName, StringRef llvmXtorName,
3348 llvm::function_ref<std::pair<StringRef, int>(mlir::Attribute)> createXtor) {
3350 for (
const mlir::NamedAttribute namedAttr : module->getAttrs()) {
3351 if (namedAttr.getName() == globalXtorName) {
3352 for (
auto attr : mlir::cast<mlir::ArrayAttr>(namedAttr.getValue()))
3353 globalXtors.emplace_back(createXtor(attr));
3358 if (globalXtors.empty())
3361 mlir::OpBuilder builder(module.getContext());
3362 builder.setInsertionPointToEnd(&module.getBodyRegion().back());
3366 auto ctorPFTy = mlir::LLVM::LLVMPointerType::get(builder.getContext());
3368 ctorStructFields.push_back(builder.getI32Type());
3369 ctorStructFields.push_back(ctorPFTy);
3370 ctorStructFields.push_back(ctorPFTy);
3372 auto ctorStructTy = mlir::LLVM::LLVMStructType::getLiteral(
3373 builder.getContext(), ctorStructFields);
3374 auto ctorStructArrayTy =
3375 mlir::LLVM::LLVMArrayType::get(ctorStructTy, globalXtors.size());
3377 mlir::Location loc =
module.getLoc();
3378 auto newGlobalOp = mlir::LLVM::GlobalOp::create(
3379 builder, loc, ctorStructArrayTy,
false,
3380 mlir::LLVM::Linkage::Appending, llvmXtorName, mlir::Attribute());
3382 builder.createBlock(&newGlobalOp.getRegion());
3383 builder.setInsertionPointToEnd(newGlobalOp.getInitializerBlock());
3385 mlir::Value result =
3386 mlir::LLVM::UndefOp::create(builder, loc, ctorStructArrayTy);
3388 for (
auto [index, fn] : llvm::enumerate(globalXtors)) {
3389 mlir::Value structInit =
3390 mlir::LLVM::UndefOp::create(builder, loc, ctorStructTy);
3391 mlir::Value initPriority = mlir::LLVM::ConstantOp::create(
3392 builder, loc, ctorStructFields[0], fn.second);
3393 mlir::Value initFuncAddr = mlir::LLVM::AddressOfOp::create(
3394 builder, loc, ctorStructFields[1], fn.first);
3395 mlir::Value initAssociate =
3396 mlir::LLVM::ZeroOp::create(builder, loc, ctorStructFields[2]);
3399 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
3400 initPriority, zero);
3401 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
3404 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
3406 result = mlir::LLVM::InsertValueOp::create(builder, loc, result, structInit,
3410 mlir::LLVM::ReturnOp::create(builder, loc, result);
3448 parent->walk([&](mlir::Block *blk) {
3449 if (blk->hasNoPredecessors() && !blk->isEntryBlock())
3450 unreachableBlocks.push_back(blk);
3453 std::set<mlir::Block *> visited;
3454 for (mlir::Block *root : unreachableBlocks) {
3457 std::deque<mlir::Block *> workList;
3458 workList.push_back(root);
3460 while (!workList.empty()) {
3461 mlir::Block *blk = workList.back();
3462 workList.pop_back();
3463 if (visited.count(blk))
3465 visited.emplace(blk);
3467 for (mlir::Operation &op : *blk)
3470 for (mlir::Block *succ : blk->getSuccessors())
3471 workList.push_back(succ);
3476mlir::LogicalResult CIRToLLVMObjSizeOpLowering::matchAndRewrite(
3477 cir::ObjSizeOp op, OpAdaptor adaptor,
3478 mlir::ConversionPatternRewriter &rewriter)
const {
3479 mlir::Type llvmResTy = getTypeConverter()->convertType(op.getType());
3480 mlir::Location loc = op->getLoc();
3482 mlir::IntegerType i1Ty = rewriter.getI1Type();
3484 auto i1Val = [&rewriter, &loc, &i1Ty](
bool val) {
3485 return mlir::LLVM::ConstantOp::create(rewriter, loc, i1Ty, val);
3492 i1Val(op.getNullunknown()),
3493 i1Val(op.getDynamic()),
3496 return mlir::LogicalResult::success();
3504constexpr StringRef llvmMetadataSectionName =
"llvm.metadata";
3509getOrCreateAnnotationStringGlobal(mlir::OpBuilder &builder, mlir::Location loc,
3510 mlir::ModuleOp module, llvm::StringRef str,
3511 llvm::StringMap<mlir::LLVM::GlobalOp> &cache,
3513 auto it = cache.find(str);
3514 if (it != cache.end())
3517 auto i8Ty = mlir::IntegerType::get(module.getContext(), 8);
3518 auto arrayTy = mlir::LLVM::LLVMArrayType::get(i8Ty, str.size() + 1);
3519 std::string
name =
".str";
3521 name +=
"." + std::to_string(cache.size());
3522 name +=
".annotation";
3526 mlir::LLVM::GlobalOp strGlobal = mlir::LLVM::GlobalOp::create(
3527 builder, loc, arrayTy,
true, mlir::LLVM::Linkage::Private,
3528 name, mlir::StringAttr::get(module.getContext(), std::string(str) +
'\0'),
3531 strGlobal.setSection(llvmMetadataSectionName);
3532 strGlobal.setUnnamedAddr(mlir::LLVM::UnnamedAddr::Global);
3533 strGlobal.setDsoLocal(
true);
3534 cache[str] = strGlobal;
3540mlir::LLVM::GlobalOp getOrCreateAnnotationArgsVar(
3541 mlir::OpBuilder &builder, mlir::Location loc, mlir::ModuleOp module,
3542 mlir::ArrayAttr argsAttr,
3543 llvm::StringMap<mlir::LLVM::GlobalOp> &argStringCache,
3544 llvm::MapVector<mlir::ArrayAttr, mlir::LLVM::GlobalOp> &argsCache) {
3545 auto it = argsCache.find(argsAttr);
3546 if (it != argsCache.end())
3549 auto ptrTy = mlir::LLVM::LLVMPointerType::get(builder.getContext());
3551 llvm::SmallVector<mlir::Type> fieldTypes;
3552 for (mlir::Attribute arg : argsAttr) {
3553 if (mlir::isa<mlir::StringAttr>(arg))
3554 fieldTypes.push_back(ptrTy);
3555 else if (
auto intAttr = mlir::dyn_cast<mlir::IntegerAttr>(arg))
3556 fieldTypes.push_back(intAttr.getType());
3558 llvm_unreachable(
"Unsupported annotation arg type");
3562 mlir::LLVM::LLVMStructType::getLiteral(builder.getContext(), fieldTypes);
3563 std::string
name =
".args";
3564 if (!argsCache.empty())
3565 name +=
"." + std::to_string(argsCache.size());
3566 name +=
".annotation";
3568 mlir::LLVM::GlobalOp argsGlobal = mlir::LLVM::GlobalOp::create(
3569 builder, loc, structTy,
true, mlir::LLVM::Linkage::Private,
3570 name, mlir::Attribute());
3571 argsGlobal.setSection(llvmMetadataSectionName);
3572 argsGlobal.setUnnamedAddr(mlir::LLVM::UnnamedAddr::Global);
3573 argsGlobal.setDsoLocal(
true);
3576 argsGlobal.getRegion().push_back(
new mlir::Block());
3577 mlir::OpBuilder initBuilder(module.getContext());
3578 initBuilder.setInsertionPointToEnd(argsGlobal.getInitializerBlock());
3580 mlir::Value structInit =
3581 mlir::LLVM::UndefOp::create(initBuilder, loc, structTy);
3582 for (
auto [idx, arg] : llvm::enumerate(argsAttr)) {
3583 if (
auto strArg = mlir::dyn_cast<mlir::StringAttr>(arg)) {
3584 mlir::LLVM::GlobalOp strGlobal = getOrCreateAnnotationStringGlobal(
3585 builder, loc, module, strArg.getValue(), argStringCache,
3587 mlir::LLVM::AddressOfOp strAddr = mlir::LLVM::AddressOfOp::create(
3588 initBuilder, loc, ptrTy, strGlobal.getSymName());
3589 structInit = mlir::LLVM::InsertValueOp::create(initBuilder, loc,
3590 structInit, strAddr, idx);
3591 }
else if (
auto intArg = mlir::dyn_cast<mlir::IntegerAttr>(arg)) {
3592 mlir::LLVM::ConstantOp intConst = mlir::LLVM::ConstantOp::create(
3593 initBuilder, loc, intArg.getType(), intArg.getValue());
3594 structInit = mlir::LLVM::InsertValueOp::create(initBuilder, loc,
3595 structInit, intConst, idx);
3597 llvm_unreachable(
"Unsupported annotation arg type");
3600 mlir::LLVM::ReturnOp::create(initBuilder, loc, structInit);
3602 argsCache[argsAttr] = argsGlobal;
3608std::pair<llvm::StringRef, unsigned> extractFileLine(mlir::Location loc) {
3609 mlir::Location resolved = loc;
3610 if (
auto fused = mlir::dyn_cast<mlir::FusedLoc>(resolved)) {
3611 if (!fused.getLocations().empty())
3612 resolved = fused.getLocations()[0];
3614 if (
auto fl = mlir::dyn_cast<mlir::FileLineColLoc>(resolved))
3615 return {fl.getFilename().getValue(), fl.getLine()};
3621 auto handleArray = [&](mlir::StringAttr symName, mlir::ArrayAttr arr,
3622 mlir::Location loc) {
3625 for (mlir::Attribute a : arr)
3626 if (
auto annot = mlir::dyn_cast<cir::AnnotationAttr>(a))
3627 collectedAnnotations.emplace_back(symName, annot, loc);
3632 module.walk([&](cir::GlobalOp op) {
3633 handleArray(op.getSymNameAttr(), op.getAnnotationsAttr(), op.getLoc());
3635 module.walk([&](cir::FuncOp op) {
3636 handleArray(op.getSymNameAttr(), op.getAnnotationsAttr(), op.getLoc());
3641 if (collectedAnnotations.empty())
3644 mlir::MLIRContext *ctx =
module.getContext();
3645 mlir::OpBuilder builder(ctx);
3646 builder.setInsertionPointToEnd(&module.getBodyRegion().back());
3648 auto ptrTy = mlir::LLVM::LLVMPointerType::get(ctx);
3649 auto i32Ty = builder.getI32Type();
3652 auto entryTy = mlir::LLVM::LLVMStructType::getLiteral(
3653 ctx, {ptrTy, ptrTy, ptrTy, i32Ty, ptrTy});
3655 mlir::LLVM::LLVMArrayType::get(entryTy, collectedAnnotations.size());
3657 mlir::Location moduleLoc =
module.getLoc();
3658 auto annotationsGlobal = mlir::LLVM::GlobalOp::create(
3659 builder, moduleLoc, arrayTy,
false,
3660 mlir::LLVM::Linkage::Appending,
"llvm.global.annotations",
3662 annotationsGlobal.setSection(llvmMetadataSectionName);
3666 mlir::OpBuilder constsBuilder(ctx);
3667 constsBuilder.setInsertionPoint(annotationsGlobal);
3669 llvm::StringMap<mlir::LLVM::GlobalOp> stringCache;
3670 llvm::StringMap<mlir::LLVM::GlobalOp> argStringCache;
3671 llvm::MapVector<mlir::ArrayAttr, mlir::LLVM::GlobalOp> argsCache;
3674 annotationsGlobal.getRegion().push_back(
new mlir::Block());
3675 mlir::OpBuilder initBuilder(ctx);
3676 initBuilder.setInsertionPointToEnd(annotationsGlobal.getInitializerBlock());
3678 mlir::Value arrayVal =
3679 mlir::LLVM::UndefOp::create(initBuilder, moduleLoc, arrayTy);
3681 for (
auto [idx, entry] : llvm::enumerate(collectedAnnotations)) {
3682 mlir::Value entryVal =
3683 mlir::LLVM::UndefOp::create(initBuilder, moduleLoc, entryTy);
3688 mlir::LLVM::AddressOfOp symAddr = mlir::LLVM::AddressOfOp::create(
3689 initBuilder, moduleLoc, ptrTy, entry.symName.getValue());
3690 entryVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
3691 entryVal, symAddr, zero);
3694 mlir::LLVM::GlobalOp nameGlobal = getOrCreateAnnotationStringGlobal(
3695 constsBuilder, moduleLoc, module, entry.annotation.getName().getValue(),
3696 stringCache,
false);
3697 mlir::LLVM::AddressOfOp nameAddr = mlir::LLVM::AddressOfOp::create(
3698 initBuilder, moduleLoc, ptrTy, nameGlobal.getSymName());
3699 entryVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
3700 entryVal, nameAddr, 1);
3703 auto [filename, line] = extractFileLine(entry.loc);
3704 mlir::LLVM::GlobalOp fileGlobal = getOrCreateAnnotationStringGlobal(
3705 constsBuilder, moduleLoc, module, filename, stringCache,
3707 mlir::LLVM::AddressOfOp fileAddr = mlir::LLVM::AddressOfOp::create(
3708 initBuilder, moduleLoc, ptrTy, fileGlobal.getSymName());
3709 entryVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
3710 entryVal, fileAddr, 2);
3711 mlir::LLVM::ConstantOp lineConst =
3712 mlir::LLVM::ConstantOp::create(initBuilder, moduleLoc, i32Ty, line);
3713 entryVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
3714 entryVal, lineConst, 3);
3717 mlir::ArrayAttr args = entry.annotation.getArgs();
3718 mlir::Value argsField;
3719 if (!args || args.empty()) {
3720 argsField = mlir::LLVM::ZeroOp::create(initBuilder, moduleLoc, ptrTy);
3722 mlir::LLVM::GlobalOp argsGlobal = getOrCreateAnnotationArgsVar(
3723 constsBuilder, moduleLoc, module, args, argStringCache, argsCache);
3724 argsField = mlir::LLVM::AddressOfOp::create(initBuilder, moduleLoc, ptrTy,
3725 argsGlobal.getSymName());
3727 entryVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
3728 entryVal, argsField, 4);
3730 arrayVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
3731 arrayVal, entryVal, idx);
3734 mlir::LLVM::ReturnOp::create(initBuilder, moduleLoc, arrayVal);
3740 mlir::ModuleOp module = getOperation();
3741 mlir::OpBuilder opBuilder(module.getContext());
3742 for (
auto &[blockAddOp, blockInfo] :
3744 mlir::LLVM::BlockTagOp resolvedLabel =
3746 assert(resolvedLabel &&
"expected BlockTagOp to already be emitted");
3747 mlir::FlatSymbolRefAttr fnSym = blockInfo.getFunc();
3748 auto blkAddTag = mlir::LLVM::BlockAddressAttr::get(
3749 opBuilder.getContext(), fnSym, resolvedLabel.getTagAttr());
3750 blockAddOp.setBlockAddrAttr(blkAddTag);
3757 if (mlir::Attribute tripleAttr =
3758 module->getAttr(cir::CIRDialect::getTripleAttrName()))
3759 module->setAttr(mlir::LLVM::LLVMDialect::getTargetTripleAttrName(),
3762 if (mlir::Attribute asmAttr =
3763 module->getAttr(cir::CIRDialect::getModuleLevelAsmAttrName()))
3764 module->setAttr(mlir::LLVM::LLVMDialect::getModuleLevelAsmAttrName(),
3769 llvm::TimeTraceScope scope(
"Convert CIR to LLVM Pass");
3771 mlir::ModuleOp module = getOperation();
3772 mlir::DataLayout dl(module);
3773 mlir::LLVMTypeConverter converter(&getContext());
3781 mlir::RewritePatternSet patterns(&getContext());
3782 patterns.add<CIRToLLVMBlockAddressOpLowering, CIRToLLVMLabelOpLowering>(
3783 converter, patterns.getContext(), dl, blockInfoAddr);
3786#define GET_LLVM_LOWERING_PATTERNS_LIST
3787#include "clang/CIR/Dialect/IR/CIRLowering.inc"
3788#undef GET_LLVM_LOWERING_PATTERNS_LIST
3789 >(converter, patterns.getContext(), dl);
3797 mlir::ConversionTarget target(getContext());
3798 target.addLegalOp<mlir::ModuleOp>();
3799 target.addLegalDialect<mlir::LLVM::LLVMDialect>();
3800 mlir::configureOpenMPToLLVMConversionLegality(target, converter);
3801 target.addLegalDialect<mlir::omp::OpenMPDialect>();
3802 mlir::populateOpenMPToLLVMConversionPatterns(converter, patterns);
3803 target.addIllegalDialect<mlir::BuiltinDialect, cir::CIRDialect,
3804 mlir::func::FuncDialect>();
3807 ops.push_back(module);
3810 if (failed(applyPartialConversion(ops, target, std::move(patterns))))
3811 signalPassFailure();
3815 "llvm.global_ctors", [](mlir::Attribute
attr) {
3816 auto ctorAttr = mlir::cast<cir::GlobalCtorAttr>(
attr);
3817 return std::make_pair(ctorAttr.getName(),
3818 ctorAttr.getPriority());
3822 "llvm.global_dtors", [](mlir::Attribute
attr) {
3823 auto dtorAttr = mlir::cast<cir::GlobalDtorAttr>(
attr);
3824 return std::make_pair(dtorAttr.getName(),
3825 dtorAttr.getPriority());
3833mlir::LogicalResult CIRToLLVMBrOpLowering::matchAndRewrite(
3834 cir::BrOp op, OpAdaptor adaptor,
3835 mlir::ConversionPatternRewriter &rewriter)
const {
3836 rewriter.replaceOpWithNewOp<mlir::LLVM::BrOp>(op, adaptor.getOperands(),
3838 return mlir::LogicalResult::success();
3841mlir::LogicalResult CIRToLLVMGetMemberOpLowering::matchAndRewrite(
3842 cir::GetMemberOp op, OpAdaptor adaptor,
3843 mlir::ConversionPatternRewriter &rewriter)
const {
3844 mlir::Type llResTy = getTypeConverter()->convertType(op.getType());
3845 const auto recordTy =
3846 mlir::cast<cir::RecordType>(op.getAddrTy().getPointee());
3847 assert(recordTy &&
"expected record type");
3849 switch (recordTy.getKind()) {
3850 case cir::RecordType::Class:
3851 case cir::RecordType::Struct: {
3855 const mlir::Type elementTy = getTypeConverter()->convertType(recordTy);
3860 mlir::LLVM::GEPNoWrapFlags flags =
3861 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
3862 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
3863 op, llResTy, elementTy, adaptor.getAddr(), offset, flags);
3864 return mlir::success();
3866 case cir::RecordType::Union:
3869 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(op, llResTy,
3871 return mlir::success();
3875mlir::LogicalResult CIRToLLVMExtractMemberOpLowering::matchAndRewrite(
3876 cir::ExtractMemberOp op, OpAdaptor adaptor,
3877 mlir::ConversionPatternRewriter &rewriter)
const {
3878 std::int64_t indices[1] = {
static_cast<std::int64_t
>(op.getIndex())};
3880 mlir::Type recordTy = op.getRecord().getType();
3881 auto cirRecordTy = mlir::cast<cir::RecordType>(recordTy);
3882 switch (cirRecordTy.getKind()) {
3883 case cir::RecordType::Struct:
3884 case cir::RecordType::Class:
3885 rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractValueOp>(
3886 op, adaptor.getRecord(), indices);
3887 return mlir::success();
3889 case cir::RecordType::Union:
3890 op.emitError(
"cir.extract_member cannot extract member from a union");
3891 return mlir::failure();
3893 llvm_unreachable(
"Unexpected record kind");
3896mlir::LogicalResult CIRToLLVMInsertMemberOpLowering::matchAndRewrite(
3897 cir::InsertMemberOp op, OpAdaptor adaptor,
3898 mlir::ConversionPatternRewriter &rewriter)
const {
3899 std::int64_t indecies[1] = {
static_cast<std::int64_t
>(op.getIndex())};
3900 mlir::Type recordTy = op.getRecord().getType();
3902 if (
auto cirRecordTy = mlir::dyn_cast<cir::RecordType>(recordTy)) {
3903 if (cirRecordTy.getKind() == cir::RecordType::Union) {
3904 op.emitError(
"cir.update_member cannot update member of a union");
3905 return mlir::failure();
3909 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
3910 op, adaptor.getRecord(), adaptor.getValue(), indecies);
3911 return mlir::success();
3914mlir::LogicalResult CIRToLLVMUnreachableOpLowering::matchAndRewrite(
3915 cir::UnreachableOp op, OpAdaptor adaptor,
3916 mlir::ConversionPatternRewriter &rewriter)
const {
3917 rewriter.replaceOpWithNewOp<mlir::LLVM::UnreachableOp>(op);
3918 return mlir::success();
3922 mlir::Operation *srcOp, llvm::StringRef fnName,
3924 mlir::ArrayAttr argAttrs =
nullptr,
3925 mlir::ArrayAttr resAttrs =
nullptr) {
3926 mlir::ModuleOp modOp = srcOp->getParentOfType<mlir::ModuleOp>();
3927 mlir::Operation *sourceSymbol =
3928 mlir::SymbolTable::lookupSymbolIn(modOp, fnName);
3929 if (!sourceSymbol) {
3930 mlir::OpBuilder::InsertionGuard guard(rewriter);
3931 auto enclosingFnOp = srcOp->getParentOfType<mlir::LLVM::LLVMFuncOp>();
3932 rewriter.setInsertionPoint(enclosingFnOp);
3934 mlir::LLVM::LLVMFuncOp::create(rewriter, srcOp->getLoc(), fnName, fnTy);
3936 fn.setArgAttrsAttr(argAttrs);
3938 fn.setResAttrsAttr(resAttrs);
3942mlir::LogicalResult CIRToLLVMThrowOpLowering::matchAndRewrite(
3943 cir::ThrowOp op, OpAdaptor adaptor,
3944 mlir::ConversionPatternRewriter &rewriter)
const {
3945 mlir::Location loc = op.getLoc();
3946 auto voidTy = mlir::LLVM::LLVMVoidType::get(getContext());
3948 if (op.rethrows()) {
3949 auto funcTy = mlir::LLVM::LLVMFunctionType::get(voidTy, {});
3952 const llvm::StringRef functionName =
"__cxa_rethrow";
3953 createLLVMFuncOpIfNotExist(rewriter, op, functionName, funcTy);
3955 auto cxaRethrow = mlir::LLVM::CallOp::create(
3956 rewriter, loc, mlir::TypeRange{}, functionName);
3958 rewriter.replaceOp(op, cxaRethrow);
3959 return mlir::success();
3962 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3963 auto fnTy = mlir::LLVM::LLVMFunctionType::get(
3964 voidTy, {llvmPtrTy, llvmPtrTy, llvmPtrTy});
3967 const llvm::StringRef fnName =
"__cxa_throw";
3970 mlir::Value typeInfo = mlir::LLVM::AddressOfOp::create(
3971 rewriter, loc, mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
3972 adaptor.getTypeInfoAttr());
3976 dtor = mlir::LLVM::AddressOfOp::create(rewriter, loc, llvmPtrTy,
3977 adaptor.getDtorAttr());
3979 dtor = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmPtrTy);
3982 auto cxaThrowCall = mlir::LLVM::CallOp::create(
3983 rewriter, loc, mlir::TypeRange{}, fnName,
3984 mlir::ValueRange{adaptor.getExceptionPtr(), typeInfo, dtor});
3986 rewriter.replaceOp(op, cxaThrowCall);
3987 return mlir::success();
3990mlir::LogicalResult CIRToLLVMAllocExceptionOpLowering::matchAndRewrite(
3991 cir::AllocExceptionOp op, OpAdaptor adaptor,
3992 mlir::ConversionPatternRewriter &rewriter)
const {
3994 StringRef fnName =
"__cxa_allocate_exception";
3995 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3996 auto int64Ty = mlir::IntegerType::get(rewriter.getContext(), 64);
3997 auto fnTy = mlir::LLVM::LLVMFunctionType::get(llvmPtrTy, {int64Ty});
4000 auto exceptionSize = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
4001 adaptor.getSizeAttr());
4003 auto allocaExceptionCall = mlir::LLVM::CallOp::create(
4004 rewriter, op.getLoc(), mlir::TypeRange{llvmPtrTy}, fnName,
4005 mlir::ValueRange{exceptionSize});
4007 rewriter.replaceOp(op, allocaExceptionCall);
4008 return mlir::success();
4011static mlir::LLVM::LLVMStructType
4014 mlir::MLIRContext *ctx = rewriter.getContext();
4015 auto llvmPtr = mlir::LLVM::LLVMPointerType::get(ctx);
4017 return mlir::LLVM::LLVMStructType::getLiteral(ctx, structFields);
4020mlir::LogicalResult CIRToLLVMEhInflightOpLowering::matchAndRewrite(
4021 cir::EhInflightOp op, OpAdaptor adaptor,
4022 mlir::ConversionPatternRewriter &rewriter)
const {
4023 auto llvmFn = op->getParentOfType<mlir::LLVM::LLVMFuncOp>();
4024 assert(llvmFn &&
"expected LLVM function parent");
4025 mlir::Block *entryBlock = &llvmFn.getRegion().front();
4026 assert(entryBlock->isEntryBlock());
4028 mlir::ArrayAttr catchListAttr = op.getCatchTypeListAttr();
4029 mlir::SmallVector<mlir::Value> catchSymAddrs;
4031 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4032 mlir::Location loc = op.getLoc();
4037 if (catchListAttr) {
4040 for (mlir::Attribute catchAttr : catchListAttr) {
4041 auto symAttr = cast<mlir::FlatSymbolRefAttr>(catchAttr);
4044 mlir::OpBuilder::InsertionGuard guard(rewriter);
4045 rewriter.setInsertionPointToStart(entryBlock);
4046 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
4047 rewriter, loc, llvmPtrTy, symAttr.getValue());
4048 catchSymAddrs.push_back(addrOp);
4055 if (op.getCatchAll() || (!catchListAttr && !op.getCleanup())) {
4056 mlir::OpBuilder::InsertionGuard guard(rewriter);
4057 rewriter.setInsertionPointToStart(entryBlock);
4058 mlir::Value nullOp = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmPtrTy);
4059 catchSymAddrs.push_back(nullOp);
4064 mlir::LLVM::LLVMStructType llvmLandingPadStructTy =
4066 auto landingPadOp = mlir::LLVM::LandingpadOp::create(
4067 rewriter, loc, llvmLandingPadStructTy, catchSymAddrs);
4072 if (op.getCleanup() && !op.getCatchAll())
4073 landingPadOp.setCleanup(
true);
4076 mlir::LLVM::ExtractValueOp::create(rewriter, loc, landingPadOp, 0);
4077 mlir::Value selector =
4078 mlir::LLVM::ExtractValueOp::create(rewriter, loc, landingPadOp, 1);
4079 rewriter.replaceOp(op, mlir::ValueRange{slot, selector});
4081 return mlir::success();
4084mlir::LogicalResult CIRToLLVMResumeFlatOpLowering::matchAndRewrite(
4085 cir::ResumeFlatOp op, OpAdaptor adaptor,
4086 mlir::ConversionPatternRewriter &rewriter)
const {
4091 mlir::Value poison = mlir::LLVM::PoisonOp::create(rewriter, op.getLoc(),
4092 llvmLandingPadStructTy);
4095 mlir::Value slot = mlir::LLVM::InsertValueOp::create(
4096 rewriter, op.getLoc(), poison, adaptor.getExceptionPtr(), slotIdx);
4099 mlir::Value selector = mlir::LLVM::InsertValueOp::create(
4100 rewriter, op.getLoc(), slot, adaptor.getTypeId(), selectorIdx);
4102 rewriter.replaceOpWithNewOp<mlir::LLVM::ResumeOp>(op, selector);
4103 return mlir::success();
4106mlir::LogicalResult CIRToLLVMEhTypeIdOpLowering::matchAndRewrite(
4107 cir::EhTypeIdOp op, OpAdaptor adaptor,
4108 mlir::ConversionPatternRewriter &rewriter)
const {
4109 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
4110 rewriter, op.getLoc(),
4111 mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
4112 op.getTypeSymAttr());
4113 rewriter.replaceOpWithNewOp<mlir::LLVM::EhTypeidForOp>(
4114 op, rewriter.getI32Type(), addrOp);
4115 return mlir::success();
4118mlir::LogicalResult CIRToLLVMEhSetjmpOpLowering::matchAndRewrite(
4119 cir::EhSetjmpOp op, OpAdaptor adaptor,
4120 mlir::ConversionPatternRewriter &rewriter)
const {
4121 mlir::Type returnType = typeConverter->convertType(op.getType());
4122 mlir::LLVM::CallIntrinsicOp newOp =
4124 returnType, adaptor.getEnv());
4125 rewriter.replaceOp(op, newOp);
4126 return mlir::success();
4129mlir::LogicalResult CIRToLLVMEhLongjmpOpLowering::matchAndRewrite(
4130 cir::EhLongjmpOp op, OpAdaptor adaptor,
4131 mlir::ConversionPatternRewriter &rewriter)
const {
4133 {}, adaptor.getOperands());
4134 return mlir::success();
4137mlir::LogicalResult CIRToLLVMTrapOpLowering::matchAndRewrite(
4138 cir::TrapOp op, OpAdaptor adaptor,
4139 mlir::ConversionPatternRewriter &rewriter)
const {
4140 mlir::Location loc = op->getLoc();
4141 rewriter.eraseOp(op);
4143 mlir::LLVM::Trap::create(rewriter, loc);
4148 mlir::LLVM::UnreachableOp::create(rewriter, loc);
4150 return mlir::success();
4155 mlir::ConversionPatternRewriter &rewriter,
4156 const mlir::TypeConverter *converter,
4157 mlir::FlatSymbolRefAttr nameAttr, mlir::Type &eltType) {
4158 auto module = op->getParentOfType<mlir::ModuleOp>();
4159 mlir::Operation *symbol = mlir::SymbolTable::lookupSymbolIn(module, nameAttr);
4160 if (
auto llvmSymbol = mlir::dyn_cast<mlir::LLVM::GlobalOp>(symbol)) {
4161 eltType = llvmSymbol.getType();
4162 }
else if (
auto cirSymbol = mlir::dyn_cast<cir::GlobalOp>(symbol)) {
4163 eltType = converter->convertType(cirSymbol.getSymType());
4165 op->emitError() <<
"unexpected symbol type for " << symbol;
4169 return mlir::LLVM::AddressOfOp::create(
4170 rewriter, op->getLoc(),
4171 mlir::LLVM::LLVMPointerType::get(op->getContext()), nameAttr.getValue());
4174mlir::LogicalResult CIRToLLVMVTableAddrPointOpLowering::matchAndRewrite(
4175 cir::VTableAddrPointOp op, OpAdaptor adaptor,
4176 mlir::ConversionPatternRewriter &rewriter)
const {
4177 const mlir::TypeConverter *converter = getTypeConverter();
4178 mlir::Type targetType = converter->convertType(op.getType());
4181 mlir::Value symAddr = getValueForVTableSymbol(op, rewriter, converter,
4182 op.getNameAttr(), eltType);
4184 return op.emitError() <<
"Unable to get value for vtable symbol";
4187 0, op.getAddressPointAttr().getIndex(),
4188 op.getAddressPointAttr().getOffset()};
4190 assert(eltType &&
"Shouldn't ever be missing an eltType here");
4191 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
4192 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
4193 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, targetType, eltType,
4194 symAddr, offsets, inboundsNuw);
4195 return mlir::success();
4198mlir::LogicalResult CIRToLLVMVTableGetVPtrOpLowering::matchAndRewrite(
4199 cir::VTableGetVPtrOp op, OpAdaptor adaptor,
4200 mlir::ConversionPatternRewriter &rewriter)
const {
4204 mlir::Value srcVal = adaptor.getSrc();
4205 rewriter.replaceOp(op, srcVal);
4206 return mlir::success();
4209mlir::LogicalResult CIRToLLVMVTableGetVirtualFnAddrOpLowering::matchAndRewrite(
4210 cir::VTableGetVirtualFnAddrOp op, OpAdaptor adaptor,
4211 mlir::ConversionPatternRewriter &rewriter)
const {
4212 mlir::Type targetType = getTypeConverter()->convertType(op.getType());
4213 auto eltType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4216 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
4217 op, targetType, eltType, adaptor.getVptr(), offsets,
4218 mlir::LLVM::GEPNoWrapFlags::inbounds);
4219 return mlir::success();
4222mlir::LogicalResult CIRToLLVMVTTAddrPointOpLowering::matchAndRewrite(
4223 cir::VTTAddrPointOp op, OpAdaptor adaptor,
4224 mlir::ConversionPatternRewriter &rewriter)
const {
4225 const mlir::Type resultType = getTypeConverter()->convertType(op.getType());
4228 mlir::Value llvmAddr = adaptor.getSymAddr();
4230 if (op.getSymAddr()) {
4231 if (op.getOffset() == 0) {
4232 rewriter.replaceOp(op, {llvmAddr});
4233 return mlir::success();
4236 offsets.push_back(adaptor.getOffset());
4237 eltType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4240 op.getNameAttr(), eltType);
4241 assert(eltType &&
"Shouldn't ever be missing an eltType here");
4242 offsets.push_back(0);
4243 offsets.push_back(adaptor.getOffset());
4245 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
4246 op, resultType, eltType, llvmAddr, offsets,
4247 mlir::LLVM::GEPNoWrapFlags::inbounds);
4248 return mlir::success();
4251mlir::LogicalResult CIRToLLVMStackSaveOpLowering::matchAndRewrite(
4252 cir::StackSaveOp op, OpAdaptor adaptor,
4253 mlir::ConversionPatternRewriter &rewriter)
const {
4254 const mlir::Type ptrTy = getTypeConverter()->convertType(op.getType());
4255 rewriter.replaceOpWithNewOp<mlir::LLVM::StackSaveOp>(op, ptrTy);
4256 return mlir::success();
4259mlir::LogicalResult CIRToLLVMStackRestoreOpLowering::matchAndRewrite(
4260 cir::StackRestoreOp op, OpAdaptor adaptor,
4261 mlir::ConversionPatternRewriter &rewriter)
const {
4262 rewriter.replaceOpWithNewOp<mlir::LLVM::StackRestoreOp>(op, adaptor.getPtr());
4263 return mlir::success();
4266mlir::LogicalResult CIRToLLVMVecCreateOpLowering::matchAndRewrite(
4267 cir::VecCreateOp op, OpAdaptor adaptor,
4268 mlir::ConversionPatternRewriter &rewriter)
const {
4271 const auto vecTy = mlir::cast<cir::VectorType>(op.getType());
4272 const mlir::Type llvmTy = typeConverter->convertType(vecTy);
4273 const mlir::Location loc = op.getLoc();
4274 mlir::Value result = mlir::LLVM::PoisonOp::create(rewriter, loc, llvmTy);
4275 assert(vecTy.getSize() == op.getElements().size() &&
4276 "cir.vec.create op count doesn't match vector type elements count");
4278 for (uint64_t i = 0; i < vecTy.getSize(); ++i) {
4279 const mlir::Value indexValue =
4280 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
4281 result = mlir::LLVM::InsertElementOp::create(
4282 rewriter, loc, result, adaptor.getElements()[i], indexValue);
4285 rewriter.replaceOp(op, result);
4286 return mlir::success();
4289mlir::LogicalResult CIRToLLVMVecExtractOpLowering::matchAndRewrite(
4290 cir::VecExtractOp op, OpAdaptor adaptor,
4291 mlir::ConversionPatternRewriter &rewriter)
const {
4292 rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractElementOp>(
4293 op, adaptor.getVec(), adaptor.getIndex());
4294 return mlir::success();
4297mlir::LogicalResult CIRToLLVMVecInsertOpLowering::matchAndRewrite(
4298 cir::VecInsertOp op, OpAdaptor adaptor,
4299 mlir::ConversionPatternRewriter &rewriter)
const {
4300 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertElementOp>(
4301 op, adaptor.getVec(), adaptor.getValue(), adaptor.getIndex());
4302 return mlir::success();
4305mlir::LogicalResult CIRToLLVMVecCmpOpLowering::matchAndRewrite(
4306 cir::VecCmpOp op, OpAdaptor adaptor,
4307 mlir::ConversionPatternRewriter &rewriter)
const {
4308 mlir::Type elementType = elementTypeIfVector(op.getLhs().getType());
4309 mlir::Value bitResult;
4310 if (
auto intType = mlir::dyn_cast<cir::IntType>(elementType)) {
4311 bitResult = mlir::LLVM::ICmpOp::create(
4312 rewriter, op.getLoc(),
4314 adaptor.getLhs(), adaptor.getRhs());
4315 }
else if (mlir::isa<cir::FPTypeInterface>(elementType)) {
4316 bitResult = mlir::LLVM::FCmpOp::create(
4318 adaptor.getLhs(), adaptor.getRhs());
4320 return op.emitError() <<
"unsupported type for VecCmpOp: " << elementType;
4326 if (cast<cir::IntType>(cast<cir::VectorType>(op.getType()).getElementType())
4328 rewriter.replaceOpWithNewOp<mlir::LLVM::SExtOp>(
4329 op, typeConverter->convertType(op.getType()), bitResult);
4331 rewriter.replaceOp(op, bitResult);
4332 return mlir::success();
4335mlir::LogicalResult CIRToLLVMVecSplatOpLowering::matchAndRewrite(
4336 cir::VecSplatOp op, OpAdaptor adaptor,
4337 mlir::ConversionPatternRewriter &rewriter)
const {
4343 cir::VectorType vecTy = op.getType();
4344 mlir::Type llvmTy = typeConverter->convertType(vecTy);
4345 mlir::Location loc = op.getLoc();
4346 mlir::Value poison = mlir::LLVM::PoisonOp::create(rewriter, loc, llvmTy);
4348 mlir::Value elementValue = adaptor.getValue();
4349 if (elementValue.getDefiningOp<mlir::LLVM::PoisonOp>()) {
4352 rewriter.replaceOp(op, poison);
4353 return mlir::success();
4356 if (
auto constValue = elementValue.getDefiningOp<mlir::LLVM::ConstantOp>()) {
4357 if (
auto intAttr = dyn_cast<mlir::IntegerAttr>(constValue.getValue())) {
4358 mlir::DenseIntElementsAttr denseVec = mlir::DenseIntElementsAttr::get(
4359 mlir::cast<mlir::ShapedType>(llvmTy), intAttr.getValue());
4360 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
4361 op, denseVec.getType(), denseVec);
4362 return mlir::success();
4365 if (
auto fpAttr = dyn_cast<mlir::FloatAttr>(constValue.getValue())) {
4366 mlir::DenseFPElementsAttr denseVec = mlir::DenseFPElementsAttr::get(
4367 mlir::cast<mlir::ShapedType>(llvmTy), fpAttr.getValue());
4368 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
4369 op, denseVec.getType(), denseVec);
4370 return mlir::success();
4374 mlir::Value indexValue =
4375 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), 0);
4376 mlir::Value oneElement = mlir::LLVM::InsertElementOp::create(
4377 rewriter, loc, poison, elementValue, indexValue);
4379 rewriter.replaceOpWithNewOp<mlir::LLVM::ShuffleVectorOp>(op, oneElement,
4380 poison, zeroValues);
4381 return mlir::success();
4384mlir::LogicalResult CIRToLLVMVecShuffleOpLowering::matchAndRewrite(
4385 cir::VecShuffleOp op, OpAdaptor adaptor,
4386 mlir::ConversionPatternRewriter &rewriter)
const {
4392 op.getIndices().begin(), op.getIndices().end(),
4393 std::back_inserter(indices), [](mlir::Attribute intAttr) {
4394 return mlir::cast<cir::IntAttr>(intAttr).getValue().getSExtValue();
4396 rewriter.replaceOpWithNewOp<mlir::LLVM::ShuffleVectorOp>(
4397 op, adaptor.getVec1(), adaptor.getVec2(), indices);
4398 return mlir::success();
4401mlir::LogicalResult CIRToLLVMVecShuffleDynamicOpLowering::matchAndRewrite(
4402 cir::VecShuffleDynamicOp op, OpAdaptor adaptor,
4403 mlir::ConversionPatternRewriter &rewriter)
const {
4415 mlir::Location loc = op.getLoc();
4416 mlir::Value input = adaptor.getVec();
4417 mlir::Type llvmIndexVecType =
4418 getTypeConverter()->convertType(op.getIndices().getType());
4419 mlir::Type llvmIndexType = getTypeConverter()->convertType(
4420 elementTypeIfVector(op.getIndices().getType()));
4421 uint64_t numElements =
4422 mlir::cast<cir::VectorType>(op.getVec().getType()).getSize();
4424 uint64_t maskBits = llvm::NextPowerOf2(numElements - 1) - 1;
4425 mlir::Value maskValue = mlir::LLVM::ConstantOp::create(
4426 rewriter, loc, llvmIndexType,
4427 rewriter.getIntegerAttr(llvmIndexType, maskBits));
4428 mlir::Value maskVector =
4429 mlir::LLVM::UndefOp::create(rewriter, loc, llvmIndexVecType);
4431 for (uint64_t i = 0; i < numElements; ++i) {
4432 mlir::Value idxValue =
4433 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
4434 maskVector = mlir::LLVM::InsertElementOp::create(rewriter, loc, maskVector,
4435 maskValue, idxValue);
4438 mlir::Value maskedIndices = mlir::LLVM::AndOp::create(
4439 rewriter, loc, llvmIndexVecType, adaptor.getIndices(), maskVector);
4440 mlir::Value result = mlir::LLVM::UndefOp::create(
4441 rewriter, loc, getTypeConverter()->convertType(op.getVec().getType()));
4442 for (uint64_t i = 0; i < numElements; ++i) {
4443 mlir::Value iValue =
4444 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
4445 mlir::Value indexValue = mlir::LLVM::ExtractElementOp::create(
4446 rewriter, loc, maskedIndices, iValue);
4447 mlir::Value valueAtIndex =
4448 mlir::LLVM::ExtractElementOp::create(rewriter, loc, input, indexValue);
4449 result = mlir::LLVM::InsertElementOp::create(rewriter, loc, result,
4450 valueAtIndex, iValue);
4452 rewriter.replaceOp(op, result);
4453 return mlir::success();
4456mlir::LogicalResult CIRToLLVMVecTernaryOpLowering::matchAndRewrite(
4457 cir::VecTernaryOp op, OpAdaptor adaptor,
4458 mlir::ConversionPatternRewriter &rewriter)
const {
4460 mlir::Value bitVec = mlir::LLVM::ICmpOp::create(
4461 rewriter, op.getLoc(), mlir::LLVM::ICmpPredicate::ne, adaptor.getCond(),
4462 mlir::LLVM::ZeroOp::create(
4463 rewriter, op.getCond().getLoc(),
4464 typeConverter->convertType(op.getCond().getType())));
4465 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(
4466 op, bitVec, adaptor.getLhs(), adaptor.getRhs());
4467 return mlir::success();
4470mlir::LogicalResult CIRToLLVMComplexAddOpLowering::matchAndRewrite(
4471 cir::ComplexAddOp op, OpAdaptor adaptor,
4472 mlir::ConversionPatternRewriter &rewriter)
const {
4473 mlir::Value lhs = adaptor.getLhs();
4474 mlir::Value rhs = adaptor.getRhs();
4475 mlir::Location loc = op.getLoc();
4477 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
4478 mlir::Type complexElemTy =
4479 getTypeConverter()->convertType(
complexType.getElementType());
4480 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
4481 rewriter, loc, complexElemTy, lhs,
ArrayRef(int64_t{0}));
4482 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
4483 rewriter, loc, complexElemTy, lhs,
ArrayRef(int64_t{1}));
4484 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
4485 rewriter, loc, complexElemTy, rhs,
ArrayRef(int64_t{0}));
4486 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
4487 rewriter, loc, complexElemTy, rhs,
ArrayRef(int64_t{1}));
4489 mlir::Value newReal;
4490 mlir::Value newImag;
4491 if (complexElemTy.isInteger()) {
4492 newReal = mlir::LLVM::AddOp::create(rewriter, loc, complexElemTy, lhsReal,
4494 newImag = mlir::LLVM::AddOp::create(rewriter, loc, complexElemTy, lhsImag,
4499 newReal = mlir::LLVM::FAddOp::create(rewriter, loc, complexElemTy, lhsReal,
4501 newImag = mlir::LLVM::FAddOp::create(rewriter, loc, complexElemTy, lhsImag,
4505 mlir::Type complexLLVMTy =
4506 getTypeConverter()->convertType(op.getResult().getType());
4507 auto initialComplex =
4508 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), complexLLVMTy);
4510 auto realComplex = mlir::LLVM::InsertValueOp::create(
4511 rewriter, op->getLoc(), initialComplex, newReal,
ArrayRef(int64_t{0}));
4513 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
4514 op, realComplex, newImag,
ArrayRef(int64_t{1}));
4516 return mlir::success();
4519mlir::LogicalResult CIRToLLVMComplexCreateOpLowering::matchAndRewrite(
4520 cir::ComplexCreateOp op, OpAdaptor adaptor,
4521 mlir::ConversionPatternRewriter &rewriter)
const {
4522 mlir::Type complexLLVMTy =
4523 getTypeConverter()->convertType(op.getResult().getType());
4524 auto initialComplex =
4525 mlir::LLVM::UndefOp::create(rewriter, op->getLoc(), complexLLVMTy);
4527 auto realComplex = mlir::LLVM::InsertValueOp::create(
4528 rewriter, op->getLoc(), initialComplex, adaptor.getReal(),
4531 auto complex = mlir::LLVM::InsertValueOp::create(
4532 rewriter, op->getLoc(), realComplex, adaptor.getImag(),
4535 rewriter.replaceOp(op, complex);
4536 return mlir::success();
4539mlir::LogicalResult CIRToLLVMComplexRealOpLowering::matchAndRewrite(
4540 cir::ComplexRealOp op, OpAdaptor adaptor,
4541 mlir::ConversionPatternRewriter &rewriter)
const {
4542 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
4543 mlir::Value operand = adaptor.getOperand();
4544 if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) {
4545 operand = mlir::LLVM::ExtractValueOp::create(
4546 rewriter, op.getLoc(), resultLLVMTy, operand,
4549 rewriter.replaceOp(op, operand);
4550 return mlir::success();
4553mlir::LogicalResult CIRToLLVMComplexSubOpLowering::matchAndRewrite(
4554 cir::ComplexSubOp op, OpAdaptor adaptor,
4555 mlir::ConversionPatternRewriter &rewriter)
const {
4556 mlir::Value lhs = adaptor.getLhs();
4557 mlir::Value rhs = adaptor.getRhs();
4558 mlir::Location loc = op.getLoc();
4560 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
4561 mlir::Type complexElemTy =
4562 getTypeConverter()->convertType(
complexType.getElementType());
4563 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
4564 rewriter, loc, complexElemTy, lhs,
ArrayRef(int64_t{0}));
4565 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
4566 rewriter, loc, complexElemTy, lhs,
ArrayRef(int64_t{1}));
4567 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
4568 rewriter, loc, complexElemTy, rhs,
ArrayRef(int64_t{0}));
4569 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
4570 rewriter, loc, complexElemTy, rhs,
ArrayRef(int64_t{1}));
4572 mlir::Value newReal;
4573 mlir::Value newImag;
4574 if (complexElemTy.isInteger()) {
4575 newReal = mlir::LLVM::SubOp::create(rewriter, loc, complexElemTy, lhsReal,
4577 newImag = mlir::LLVM::SubOp::create(rewriter, loc, complexElemTy, lhsImag,
4582 newReal = mlir::LLVM::FSubOp::create(rewriter, loc, complexElemTy, lhsReal,
4584 newImag = mlir::LLVM::FSubOp::create(rewriter, loc, complexElemTy, lhsImag,
4588 mlir::Type complexLLVMTy =
4589 getTypeConverter()->convertType(op.getResult().getType());
4590 auto initialComplex =
4591 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), complexLLVMTy);
4593 auto realComplex = mlir::LLVM::InsertValueOp::create(
4594 rewriter, op->getLoc(), initialComplex, newReal,
ArrayRef(int64_t{0}));
4596 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
4597 op, realComplex, newImag,
ArrayRef(int64_t{1}));
4599 return mlir::success();
4602mlir::LogicalResult CIRToLLVMComplexImagOpLowering::matchAndRewrite(
4603 cir::ComplexImagOp op, OpAdaptor adaptor,
4604 mlir::ConversionPatternRewriter &rewriter)
const {
4605 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
4606 mlir::Value operand = adaptor.getOperand();
4607 mlir::Location loc = op.getLoc();
4609 if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) {
4610 operand = mlir::LLVM::ExtractValueOp::create(
4613 mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(resultLLVMTy);
4615 mlir::LLVM::ConstantOp::create(rewriter, loc, resultLLVMTy, zeroAttr);
4618 rewriter.replaceOp(op, operand);
4619 return mlir::success();
4623 mlir::MLIRContext *context,
4624 unsigned &storageSize) {
4625 return TypeSwitch<mlir::Type, mlir::IntegerType>(storageType)
4626 .Case<cir::ArrayType>([&](cir::ArrayType atTy) {
4627 storageSize = atTy.getSize() * 8;
4628 return mlir::IntegerType::get(context, storageSize);
4630 .Case<cir::IntType>([&](cir::IntType intTy) {
4631 storageSize = intTy.getWidth();
4632 return mlir::IntegerType::get(context, storageSize);
4634 .Default([](mlir::Type) -> mlir::IntegerType {
4636 "Either ArrayType or IntType expected for bitfields storage");
4640mlir::LogicalResult CIRToLLVMSetBitfieldOpLowering::matchAndRewrite(
4641 cir::SetBitfieldOp op, OpAdaptor adaptor,
4642 mlir::ConversionPatternRewriter &rewriter)
const {
4643 mlir::OpBuilder::InsertionGuard guard(rewriter);
4644 rewriter.setInsertionPoint(op);
4646 cir::BitfieldInfoAttr info = op.getBitfieldInfo();
4647 uint64_t size = info.getSize();
4648 uint64_t offset = info.getOffset();
4649 mlir::Type storageType = info.getStorageType();
4650 mlir::MLIRContext *context = storageType.getContext();
4652 unsigned storageSize = 0;
4654 mlir::IntegerType intType =
4655 computeBitfieldIntType(storageType, context, storageSize);
4657 mlir::Value srcVal = createIntCast(rewriter, adaptor.getSrc(), intType);
4658 unsigned srcWidth = storageSize;
4659 mlir::Value resultVal = srcVal;
4661 if (storageSize != size) {
4662 assert(storageSize > size &&
"Invalid bitfield size.");
4664 mlir::Value val = mlir::LLVM::LoadOp::create(
4665 rewriter, op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(),
4666 op.getIsVolatile());
4669 createAnd(rewriter, srcVal, llvm::APInt::getLowBitsSet(srcWidth, size));
4671 srcVal =
createShL(rewriter, srcVal, offset);
4675 ~llvm::APInt::getBitsSet(srcWidth, offset, offset + size));
4678 srcVal = mlir::LLVM::OrOp::create(rewriter, op.getLoc(), val, srcVal);
4681 mlir::LLVM::StoreOp::create(rewriter, op.getLoc(), srcVal, adaptor.getAddr(),
4682 op.getAlignment(), op.getIsVolatile());
4684 mlir::Type resultTy = getTypeConverter()->convertType(op.getType());
4686 if (info.getIsSigned()) {
4687 assert(size <= storageSize);
4688 unsigned highBits = storageSize - size;
4691 resultVal =
createShL(rewriter, resultVal, highBits);
4692 resultVal =
createAShR(rewriter, resultVal, highBits);
4697 mlir::cast<mlir::IntegerType>(resultTy),
4698 info.getIsSigned());
4700 rewriter.replaceOp(op, resultVal);
4701 return mlir::success();
4704mlir::LogicalResult CIRToLLVMComplexImagPtrOpLowering::matchAndRewrite(
4705 cir::ComplexImagPtrOp op, OpAdaptor adaptor,
4706 mlir::ConversionPatternRewriter &rewriter)
const {
4707 cir::PointerType operandTy = op.getOperand().getType();
4708 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
4709 mlir::Type elementLLVMTy =
4710 getTypeConverter()->convertType(operandTy.getPointee());
4712 mlir::LLVM::GEPArg gepIndices[2] = {{0}, {1}};
4713 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
4714 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
4715 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
4716 op, resultLLVMTy, elementLLVMTy, adaptor.getOperand(), gepIndices,
4718 return mlir::success();
4721mlir::LogicalResult CIRToLLVMComplexRealPtrOpLowering::matchAndRewrite(
4722 cir::ComplexRealPtrOp op, OpAdaptor adaptor,
4723 mlir::ConversionPatternRewriter &rewriter)
const {
4724 cir::PointerType operandTy = op.getOperand().getType();
4725 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
4726 mlir::Type elementLLVMTy =
4727 getTypeConverter()->convertType(operandTy.getPointee());
4729 mlir::LLVM::GEPArg gepIndices[2] = {0, 0};
4730 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
4731 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
4732 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
4733 op, resultLLVMTy, elementLLVMTy, adaptor.getOperand(), gepIndices,
4735 return mlir::success();
4738mlir::LogicalResult CIRToLLVMGetBitfieldOpLowering::matchAndRewrite(
4739 cir::GetBitfieldOp op, OpAdaptor adaptor,
4740 mlir::ConversionPatternRewriter &rewriter)
const {
4742 mlir::OpBuilder::InsertionGuard guard(rewriter);
4743 rewriter.setInsertionPoint(op);
4745 cir::BitfieldInfoAttr info = op.getBitfieldInfo();
4746 uint64_t size = info.getSize();
4747 uint64_t offset = info.getOffset();
4748 mlir::Type storageType = info.getStorageType();
4749 mlir::MLIRContext *context = storageType.getContext();
4750 unsigned storageSize = 0;
4752 mlir::IntegerType intType =
4755 mlir::Value val = mlir::LLVM::LoadOp::create(
4756 rewriter, op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(),
4757 op.getIsVolatile());
4758 val = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), intType, val);
4760 if (info.getIsSigned()) {
4761 assert(
static_cast<unsigned>(offset + size) <= storageSize);
4762 unsigned highBits = storageSize - offset - size;
4763 val =
createShL(rewriter, val, highBits);
4764 val =
createAShR(rewriter, val, offset + highBits);
4768 if (
static_cast<unsigned>(offset) + size < storageSize)
4770 llvm::APInt::getLowBitsSet(storageSize, size));
4773 mlir::Type resTy = getTypeConverter()->convertType(op.getType());
4775 rewriter, val, mlir::cast<mlir::IntegerType>(resTy), info.getIsSigned());
4776 rewriter.replaceOp(op, newOp);
4777 return mlir::success();
4780mlir::LogicalResult CIRToLLVMIsConstantOpLowering::matchAndRewrite(
4781 cir::IsConstantOp op, OpAdaptor adaptor,
4782 mlir::ConversionPatternRewriter &rewriter)
const {
4783 rewriter.replaceOpWithNewOp<mlir::LLVM::IsConstantOp>(op, adaptor.getVal());
4784 return mlir::success();
4787mlir::LogicalResult CIRToLLVMInlineAsmOpLowering::matchAndRewrite(
4788 cir::InlineAsmOp op, OpAdaptor adaptor,
4789 mlir::ConversionPatternRewriter &rewriter)
const {
4791 if (op.getNumResults())
4792 llResTy = getTypeConverter()->convertType(op.getType(0));
4794 cir::AsmFlavor dialect = op.getAsmFlavor();
4795 mlir::LLVM::AsmDialect llDialect = dialect == cir::AsmFlavor::x86_att
4796 ? mlir::LLVM::AsmDialect::AD_ATT
4797 : mlir::LLVM::AsmDialect::AD_Intel;
4800 StringRef llvmAttrName = mlir::LLVM::InlineAsmOp::getElementTypeAttrName();
4806 if (!op.getNumResults())
4807 opAttrs.push_back(mlir::Attribute());
4811 for (
auto const &[llvmOp, cirOp] :
4812 zip(adaptor.getAsmOperands(), op.getAsmOperands())) {
4813 append_range(llvmOperands, llvmOp);
4814 append_range(cirOperands, cirOp);
4819 for (
auto const &[cirOpAttr, cirOp] :
4820 zip(op.getOperandAttrs(), cirOperands)) {
4821 if (!mlir::isa<mlir::UnitAttr>(cirOpAttr)) {
4822 opAttrs.push_back(mlir::Attribute());
4827 cir::PointerType typ = mlir::cast<cir::PointerType>(cirOp.getType());
4829 *getTypeConverter(), dataLayout, typ.getPointee()));
4831 attrs.push_back(rewriter.getNamedAttr(llvmAttrName, typAttr));
4832 mlir::DictionaryAttr newDict = rewriter.getDictionaryAttr(attrs);
4833 opAttrs.push_back(newDict);
4836 rewriter.replaceOpWithNewOp<mlir::LLVM::InlineAsmOp>(
4837 op, llResTy, llvmOperands, op.getAsmStringAttr(), op.getConstraintsAttr(),
4838 op.getSideEffectsAttr(),
4841 mlir::LLVM::TailCallKindAttr::get(
4842 getContext(), mlir::LLVM::tailcallkind::TailCallKind::None),
4843 mlir::LLVM::AsmDialectAttr::get(getContext(), llDialect),
4844 rewriter.getArrayAttr(opAttrs));
4846 return mlir::success();
4849mlir::LogicalResult CIRToLLVMVAStartOpLowering::matchAndRewrite(
4850 cir::VAStartOp op, OpAdaptor adaptor,
4851 mlir::ConversionPatternRewriter &rewriter)
const {
4852 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4853 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4854 adaptor.getArgList());
4855 rewriter.replaceOpWithNewOp<mlir::LLVM::VaStartOp>(op, vaList);
4856 return mlir::success();
4859mlir::LogicalResult CIRToLLVMVAEndOpLowering::matchAndRewrite(
4860 cir::VAEndOp op, OpAdaptor adaptor,
4861 mlir::ConversionPatternRewriter &rewriter)
const {
4862 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4863 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4864 adaptor.getArgList());
4865 rewriter.replaceOpWithNewOp<mlir::LLVM::VaEndOp>(op, vaList);
4866 return mlir::success();
4869mlir::LogicalResult CIRToLLVMVACopyOpLowering::matchAndRewrite(
4870 cir::VACopyOp op, OpAdaptor adaptor,
4871 mlir::ConversionPatternRewriter &rewriter)
const {
4872 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4873 auto dstList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4874 adaptor.getDstList());
4875 auto srcList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4876 adaptor.getSrcList());
4877 rewriter.replaceOpWithNewOp<mlir::LLVM::VaCopyOp>(op, dstList, srcList);
4878 return mlir::success();
4881mlir::LogicalResult CIRToLLVMVAArgOpLowering::matchAndRewrite(
4882 cir::VAArgOp op, OpAdaptor adaptor,
4883 mlir::ConversionPatternRewriter &rewriter)
const {
4885 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4886 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4887 adaptor.getArgList());
4889 mlir::Type llvmType =
4890 getTypeConverter()->convertType(op->getResultTypes().front());
4892 return mlir::failure();
4894 rewriter.replaceOpWithNewOp<mlir::LLVM::VaArgOp>(op, llvmType, vaList);
4895 return mlir::success();
4898mlir::LogicalResult CIRToLLVMLabelOpLowering::matchAndRewrite(
4899 cir::LabelOp op, OpAdaptor adaptor,
4900 mlir::ConversionPatternRewriter &rewriter)
const {
4901 mlir::MLIRContext *ctx = rewriter.getContext();
4902 mlir::Block *block = op->getBlock();
4905 if (block->isEntryBlock()) {
4906 mlir::Block *newBlock =
4907 rewriter.splitBlock(op->getBlock(), mlir::Block::iterator(op));
4908 rewriter.setInsertionPointToEnd(block);
4909 mlir::LLVM::BrOp::create(rewriter, op.getLoc(), newBlock);
4912 mlir::LLVM::BlockTagAttr::get(ctx, blockInfoAddr.getTagIndex());
4913 rewriter.setInsertionPoint(op);
4916 mlir::LLVM::BlockTagOp::create(rewriter, op->getLoc(), tagAttr);
4917 mlir::LLVM::LLVMFuncOp func = op->getParentOfType<mlir::LLVM::LLVMFuncOp>();
4918 auto blockInfoAttr =
4919 cir::BlockAddrInfoAttr::get(ctx, func.getSymName(), op.getLabel());
4920 blockInfoAddr.mapBlockTag(blockInfoAttr, blockTagOp);
4921 rewriter.eraseOp(op);
4923 return mlir::success();
4926mlir::LogicalResult CIRToLLVMBlockAddressOpLowering::matchAndRewrite(
4927 cir::BlockAddressOp op, OpAdaptor adaptor,
4928 mlir::ConversionPatternRewriter &rewriter)
const {
4929 mlir::MLIRContext *ctx = rewriter.getContext();
4931 mlir::LLVM::BlockTagOp matchLabel =
4932 blockInfoAddr.lookupBlockTag(op.getBlockAddrInfoAttr());
4933 mlir::LLVM::BlockTagAttr tagAttr;
4940 tagAttr = matchLabel.getTag();
4942 auto blkAddr = mlir::LLVM::BlockAddressAttr::get(
4943 rewriter.getContext(), op.getBlockAddrInfoAttr().getFunc(), tagAttr);
4944 rewriter.setInsertionPoint(op);
4945 auto newOp = mlir::LLVM::BlockAddressOp::create(
4946 rewriter, op.getLoc(), mlir::LLVM::LLVMPointerType::get(ctx), blkAddr);
4948 blockInfoAddr.addUnresolvedBlockAddress(newOp, op.getBlockAddrInfoAttr());
4949 rewriter.replaceOp(op, newOp);
4950 return mlir::success();
4953mlir::LogicalResult CIRToLLVMIndirectBrOpLowering::matchAndRewrite(
4954 cir::IndirectBrOp op, OpAdaptor adaptor,
4955 mlir::ConversionPatternRewriter &rewriter)
const {
4957 mlir::Value targetAddr = adaptor.getAddr();
4965 if (op.getPoison()) {
4966 auto llvmPtrType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4968 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), llvmPtrType);
4971 rewriter.replaceOpWithNewOp<mlir::LLVM::IndirectBrOp>(
4972 op, targetAddr, adaptor.getSuccOperands(), op.getSuccessors());
4973 return mlir::success();
4976mlir::LogicalResult CIRToLLVMAwaitOpLowering::matchAndRewrite(
4977 cir::AwaitOp op, OpAdaptor adaptor,
4978 mlir::ConversionPatternRewriter &rewriter)
const {
4979 return mlir::failure();
4982mlir::LogicalResult CIRToLLVMCpuIdOpLowering::matchAndRewrite(
4983 cir::CpuIdOp op, OpAdaptor adaptor,
4984 mlir::ConversionPatternRewriter &rewriter)
const {
4985 mlir::Type i32Ty = rewriter.getI32Type();
4986 mlir::Type i64Ty = rewriter.getI64Type();
4987 mlir::Type i32PtrTy = mlir::LLVM::LLVMPointerType::get(i32Ty.getContext(), 0);
4989 mlir::Type cpuidRetTy = mlir::LLVM::LLVMStructType::getLiteral(
4990 rewriter.getContext(), {i32Ty, i32Ty, i32Ty, i32Ty});
4992 mlir::Value functionId = adaptor.getFunctionId();
4993 mlir::Value subFunctionId = adaptor.getSubFunctionId();
4995 StringRef asmString, constraints;
4996 mlir::ModuleOp moduleOp = op->getParentOfType<mlir::ModuleOp>();
4997 llvm::Triple triple(
4998 mlir::cast<mlir::StringAttr>(
4999 moduleOp->getAttr(cir::CIRDialect::getTripleAttrName()))
5001 if (triple.getArch() == llvm::Triple::x86) {
5002 asmString =
"cpuid";
5003 constraints =
"={ax},={bx},={cx},={dx},{ax},{cx}";
5006 asmString =
"xchgq %rbx, ${1:q}\n"
5008 "xchgq %rbx, ${1:q}";
5009 constraints =
"={ax},=r,={cx},={dx},0,2";
5012 mlir::Value inlineAsm =
5013 mlir::LLVM::InlineAsmOp::create(
5014 rewriter, op.getLoc(), cpuidRetTy, {functionId, subFunctionId},
5015 rewriter.getStringAttr(asmString),
5016 rewriter.getStringAttr(constraints),
5019 mlir::LLVM::TailCallKindAttr{},
5020 mlir::LLVM::AsmDialectAttr{},
5024 mlir::Value basePtr = adaptor.getCpuInfo();
5026 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
5027 unsigned alignment = layout.getTypeABIAlignment(i32Ty);
5028 for (
unsigned i = 0; i < 4; i++) {
5029 mlir::Value extracted =
5030 mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(), inlineAsm, i)
5032 mlir::Value index = mlir::LLVM::ConstantOp::create(
5033 rewriter, op.getLoc(), i64Ty, rewriter.getI64IntegerAttr(i));
5035 mlir::Value storePtr = mlir::LLVM::GEPOp::create(
5036 rewriter, op.getLoc(), i32PtrTy, i32Ty, basePtr,
5037 gepIndices, mlir::LLVM::GEPNoWrapFlags::none)
5039 mlir::LLVM::StoreOp::create(rewriter, op.getLoc(), extracted, storePtr,
5043 rewriter.eraseOp(op);
5044 return mlir::success();
5047mlir::LogicalResult CIRToLLVMMemChrOpLowering::matchAndRewrite(
5048 cir::MemChrOp op, OpAdaptor adaptor,
5049 mlir::ConversionPatternRewriter &rewriter)
const {
5050 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
5051 mlir::Type srcTy = getTypeConverter()->convertType(op.getSrc().getType());
5052 mlir::Type patternTy =
5053 getTypeConverter()->convertType(op.getPattern().getType());
5054 mlir::Type lenTy = getTypeConverter()->convertType(op.getLen().getType());
5056 mlir::LLVM::LLVMFunctionType::get(llvmPtrTy, {srcTy, patternTy, lenTy},
5058 llvm::StringRef fnName =
"memchr";
5060 mlir::Builder
b(rewriter.getContext());
5061 mlir::NamedAttribute noundefAttr =
5062 b.getNamedAttr(
"llvm.noundef",
b.getUnitAttr());
5063 mlir::DictionaryAttr noundefDict = mlir::DictionaryAttr::get(
5066 mlir::ArrayAttr argAttrs =
5067 mlir::ArrayAttr::get(rewriter.getContext(), argAttrVec);
5071 mlir::LLVM::CallOp newCall = rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(
5072 op, mlir::TypeRange{llvmPtrTy}, fnName,
5073 mlir::ValueRange{adaptor.getSrc(), adaptor.getPattern(),
5075 newCall.setArgAttrsAttr(argAttrs);
5076 return mlir::success();
5080 return std::make_unique<ConvertCIRToLLVMPass>();
5085 pm.addPass(mlir::omp::createMarkDeclareTargetPass());
5089std::unique_ptr<llvm::Module>
5091 StringRef mlirSaveTempsOutFile,
5092 llvm::vfs::FileSystem *fs) {
5093 llvm::TimeTraceScope scope(
"lower from CIR to LLVM directly");
5095 mlir::MLIRContext *mlirCtx = mlirModule.getContext();
5097 mlir::PassManager pm(mlirCtx);
5100 (void)mlir::applyPassManagerCLOptions(pm);
5102 if (mlir::failed(pm.run(mlirModule))) {
5105 "The pass manager failed to lower CIR to LLVMIR dialect!");
5108 if (!mlirSaveTempsOutFile.empty()) {
5110 llvm::raw_fd_ostream out(mlirSaveTempsOutFile, ec);
5112 mlirModule->print(out);
5115 mlir::registerBuiltinDialectTranslation(*mlirCtx);
5116 mlir::registerLLVMDialectTranslation(*mlirCtx);
5117 mlir::registerOpenMPDialectTranslation(*mlirCtx);
5120 llvm::TimeTraceScope translateScope(
"translateModuleToLLVMIR");
5122 StringRef moduleName = mlirModule.getName().value_or(
"CIRToLLVMModule");
5123 std::unique_ptr<llvm::Module> llvmModule = mlir::translateModuleToLLVMIR(
5124 mlirModule, llvmCtx, moduleName,
false, fs);
5128 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.
static void collectUnreachable(mlir::Operation *parent, llvm::SmallVector< mlir::Operation * > &ops)
mlir::Value createLShR(mlir::OpBuilder &bld, mlir::Value lhs, unsigned rhs)
mlir::Value createShL(mlir::OpBuilder &bld, mlir::Value lhs, unsigned rhs)
std::optional< mlir::Attribute > lowerConstArrayAttr(cir::ConstArrayAttr constArr, const mlir::TypeConverter *converter)
mlir::Value createAShR(mlir::OpBuilder &bld, mlir::Value lhs, unsigned rhs)
mlir::Value createAnd(mlir::OpBuilder &bld, mlir::Value lhs, const llvm::APInt &rhs)
*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)
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 void collectUnreachable(mlir::Operation *parent, llvm::SmallVector< mlir::Operation * > &ops)
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 mlir::LogicalResult lowerIncDecOp(CIROp op, typename CIROp::Adaptor adaptor, mlir::ConversionPatternRewriter &rewriter, double fpConstant)
static mlir::LLVM::IntegerOverflowFlags intOverflowFlag(BinOp op)
static mlir::LogicalResult lowerIntFPBinaryOp(CIROp op, mlir::Value lhs, mlir::Value rhs, mlir::ConversionPatternRewriter &rewriter)
Lower a binary op that maps to unsigned/signed/FP LLVM ops depending on operand type.
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)
bool hasTrailingZeros(cir::ConstArrayAttr attr)
static mlir::LogicalResult lowerMinMaxOp(CIROp op, typename CIROp::Adaptor adaptor, mlir::ConversionPatternRewriter &rewriter)
static mlir::LLVM::LLVMStructType getLLVMLandingPadStructTy(mlir::ConversionPatternRewriter &rewriter)
mlir::Value lowerCirAttrAsValue(mlir::Operation *parentOp, const mlir::Attribute attr, mlir::ConversionPatternRewriter &rewriter, const mlir::TypeConverter *converter)
Switches on the type of attribute and calls the appropriate conversion.
static mlir::Value convertToIndexTy(mlir::ConversionPatternRewriter &rewriter, mlir::ModuleOp mod, mlir::Value index, mlir::Type baseTy, cir::IntType strideTy)
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 variant.
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::LLVM::FCmpPredicate convertCmpKindToFCmpPredicate(cir::CmpOpKind kind)
Convert from a CIR comparison kind to an LLVM IR floating-point comparison kind.
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::LogicalResult rewriteCallOrInvoke(mlir::Operation *op, mlir::ValueRange callOperands, mlir::ConversionPatternRewriter &rewriter, const mlir::TypeConverter *converter, mlir::FlatSymbolRefAttr calleeAttr, mlir::Block *continueBlock=nullptr, mlir::Block *landingPadBlock=nullptr)
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)
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
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 ?
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 opLoadStoreNontemporal()
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()