18#include "mlir/Conversion/LLVMCommon/TypeConverter.h"
19#include "mlir/Conversion/OpenMPToLLVM/ConvertOpenMPToLLVM.h"
20#include "mlir/Dialect/DLTI/DLTI.h"
21#include "mlir/Dialect/Func/IR/FuncOps.h"
22#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
23#include "mlir/Dialect/LLVMIR/LLVMTypes.h"
24#include "mlir/Dialect/OpenMP/OpenMPDialect.h"
25#include "mlir/Dialect/OpenMP/Transforms/Passes.h"
26#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
27#include "mlir/IR/BuiltinAttributes.h"
28#include "mlir/IR/BuiltinDialect.h"
29#include "mlir/IR/BuiltinOps.h"
30#include "mlir/IR/Location.h"
31#include "mlir/IR/Types.h"
32#include "mlir/Pass/Pass.h"
33#include "mlir/Pass/PassManager.h"
34#include "mlir/Support/LLVM.h"
35#include "mlir/Target/LLVMIR/Dialect/Builtin/BuiltinToLLVMIRTranslation.h"
36#include "mlir/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.h"
37#include "mlir/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.h"
38#include "mlir/Target/LLVMIR/Export.h"
39#include "mlir/Transforms/DialectConversion.h"
48#include "llvm/ADT/MapVector.h"
49#include "llvm/ADT/StringMap.h"
50#include "llvm/ADT/TypeSwitch.h"
51#include "llvm/IR/Module.h"
52#include "llvm/Support/Casting.h"
53#include "llvm/Support/ErrorHandling.h"
54#include "llvm/Support/TimeProfiler.h"
55#include "llvm/Support/VirtualFileSystem.h"
56#include "llvm/Support/raw_ostream.h"
71mlir::Type elementTypeIfVector(mlir::Type type) {
72 return llvm::TypeSwitch<mlir::Type, mlir::Type>(type)
73 .Case<cir::VectorType, mlir::VectorType>(
74 [](
auto p) {
return p.getElementType(); })
75 .
Default([](mlir::Type p) {
return p; });
83 mlir::DataLayout
const &dataLayout,
87 if (isa<cir::BoolType>(type)) {
88 return mlir::IntegerType::get(type.getContext(),
89 dataLayout.getTypeSizeInBits(type));
92 return converter.convertType(type);
96 mlir::IntegerType dstTy,
97 bool isSigned =
false) {
98 mlir::Type srcTy = src.getType();
99 assert(mlir::isa<mlir::IntegerType>(srcTy));
101 unsigned srcWidth = mlir::cast<mlir::IntegerType>(srcTy).getWidth();
102 unsigned dstWidth = mlir::cast<mlir::IntegerType>(dstTy).getWidth();
103 mlir::Location loc = src.getLoc();
105 if (dstWidth > srcWidth && isSigned)
106 return mlir::LLVM::SExtOp::create(bld, loc, dstTy, src);
107 if (dstWidth > srcWidth)
108 return mlir::LLVM::ZExtOp::create(bld, loc, dstTy, src);
109 if (dstWidth < srcWidth)
110 return mlir::LLVM::TruncOp::create(bld, loc, dstTy, src);
111 return mlir::LLVM::BitcastOp::create(bld, loc, dstTy, src);
114static mlir::LLVM::Visibility
116 switch (visibilityKind) {
117 case cir::VisibilityKind::Default:
118 return ::mlir::LLVM::Visibility::Default;
119 case cir::VisibilityKind::Hidden:
120 return ::mlir::LLVM::Visibility::Hidden;
121 case cir::VisibilityKind::Protected:
122 return ::mlir::LLVM::Visibility::Protected;
130 mlir::DataLayout
const &dataLayout,
131 cir::LoadOp op, mlir::Value value) {
134 if (
auto boolTy = mlir::dyn_cast<cir::BoolType>(op.getType())) {
136 assert(value.getType().isInteger(dataLayout.getTypeSizeInBits(boolTy)));
146static mlir::Value
emitToMemory(mlir::ConversionPatternRewriter &rewriter,
147 mlir::DataLayout
const &dataLayout,
148 mlir::Type origType, mlir::Value value) {
151 if (
auto boolTy = mlir::dyn_cast<cir::BoolType>(origType)) {
153 mlir::IntegerType memType =
154 rewriter.getIntegerType(dataLayout.getTypeSizeInBits(boolTy));
162 using CIR = cir::GlobalLinkageKind;
163 using LLVM = mlir::LLVM::Linkage;
166 case CIR::AppendingLinkage:
167 return LLVM::Appending;
168 case CIR::AvailableExternallyLinkage:
169 return LLVM::AvailableExternally;
170 case CIR::CommonLinkage:
172 case CIR::ExternalLinkage:
173 return LLVM::External;
174 case CIR::ExternalWeakLinkage:
175 return LLVM::ExternWeak;
176 case CIR::InternalLinkage:
177 return LLVM::Internal;
178 case CIR::LinkOnceAnyLinkage:
179 return LLVM::Linkonce;
180 case CIR::LinkOnceODRLinkage:
181 return LLVM::LinkonceODR;
182 case CIR::PrivateLinkage:
183 return LLVM::Private;
184 case CIR::WeakAnyLinkage:
186 case CIR::WeakODRLinkage:
187 return LLVM::WeakODR;
189 llvm_unreachable(
"Unknown CIR linkage type");
193 using CIR = cir::CallingConv;
194 using LLVM = mlir::LLVM::CConv;
196 switch (callingConv) {
199 case CIR::SpirKernel:
200 return LLVM::SPIR_KERNEL;
201 case CIR::SpirFunction:
202 return LLVM::SPIR_FUNC;
204 return LLVM::PTX_Kernel;
205 case CIR::AMDGPUKernel:
206 return LLVM::AMDGPU_KERNEL;
208 llvm_unreachable(
"Unknown calling convention");
211mlir::LogicalResult CIRToLLVMCopyOpLowering::matchAndRewrite(
212 cir::CopyOp op, OpAdaptor adaptor,
213 mlir::ConversionPatternRewriter &rewriter)
const {
214 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
215 const mlir::Value
length = mlir::LLVM::ConstantOp::create(
216 rewriter, op.getLoc(), rewriter.getI64Type(),
217 op.getCopySizeInBytes(layout));
219 rewriter.replaceOpWithNewOp<mlir::LLVM::MemcpyOp>(
220 op, adaptor.getDst(), adaptor.getSrc(),
length, op.getIsVolatile());
221 return mlir::success();
224mlir::LogicalResult CIRToLLVMMemCpyOpLowering::matchAndRewrite(
225 cir::MemCpyOp op, OpAdaptor adaptor,
226 mlir::ConversionPatternRewriter &rewriter)
const {
227 rewriter.replaceOpWithNewOp<mlir::LLVM::MemcpyOp>(
228 op, adaptor.getDst(), adaptor.getSrc(), adaptor.getLen(),
230 return mlir::success();
233mlir::LogicalResult CIRToLLVMMemMoveOpLowering::matchAndRewrite(
234 cir::MemMoveOp op, OpAdaptor adaptor,
235 mlir::ConversionPatternRewriter &rewriter)
const {
236 rewriter.replaceOpWithNewOp<mlir::LLVM::MemmoveOp>(
237 op, adaptor.getDst(), adaptor.getSrc(), adaptor.getLen(),
239 return mlir::success();
242mlir::LogicalResult CIRToLLVMMemSetOpLowering::matchAndRewrite(
243 cir::MemSetOp op, OpAdaptor adaptor,
244 mlir::ConversionPatternRewriter &rewriter)
const {
246 auto memset = rewriter.replaceOpWithNewOp<mlir::LLVM::MemsetOp>(
247 op, adaptor.getDst(), adaptor.getVal(), adaptor.getLen(),
250 if (op.getAlignmentAttr()) {
252 llvm::SmallVector<mlir::Attribute> attrs{
memset.getNumOperands(),
253 rewriter.getDictionaryAttr({})};
254 llvm::SmallVector<mlir::NamedAttribute> destAttrs;
256 {mlir::LLVM::LLVMDialect::getAlignAttrName(), op.getAlignmentAttr()});
257 attrs[
memset.odsIndex_dst] = rewriter.getDictionaryAttr(destAttrs);
259 auto arrayAttr = rewriter.getArrayAttr(attrs);
260 memset.setArgAttrsAttr(arrayAttr);
263 return mlir::success();
267 mlir::Value llvmSrc, mlir::Type llvmDstIntTy,
269 uint64_t cirDstIntWidth) {
270 if (cirSrcWidth == cirDstIntWidth)
273 auto loc = llvmSrc.getLoc();
274 if (cirSrcWidth < cirDstIntWidth) {
276 return mlir::LLVM::ZExtOp::create(rewriter, loc, llvmDstIntTy, llvmSrc);
277 return mlir::LLVM::SExtOp::create(rewriter, loc, llvmDstIntTy, llvmSrc);
281 return mlir::LLVM::TruncOp::create(rewriter, loc, llvmDstIntTy, llvmSrc);
287 mlir::ConversionPatternRewriter &rewriter,
288 const mlir::TypeConverter *converter)
289 : parentOp(parentOp), rewriter(rewriter), converter(converter) {}
291#define GET_CIR_ATTR_TO_VALUE_VISITOR_DECLS
292#include "clang/CIR/Dialect/IR/CIRLowering.inc"
293#undef GET_CIR_ATTR_TO_VALUE_VISITOR_DECLS
296 mlir::Operation *parentOp;
297 mlir::ConversionPatternRewriter &rewriter;
298 const mlir::TypeConverter *converter;
303 const mlir::Attribute attr,
304 mlir::ConversionPatternRewriter &rewriter,
305 const mlir::TypeConverter *converter) {
307 mlir::Value value = valueConverter.visit(attr);
309 llvm_unreachable(
"unhandled attribute type");
314 cir::SideEffect sideEffect,
315 mlir::LLVM::MemoryEffectsAttr &memoryEffect,
316 bool &noUnwind,
bool &willReturn,
318 using mlir::LLVM::ModRefInfo;
320 switch (sideEffect) {
321 case cir::SideEffect::All:
323 noUnwind = isNothrow;
327 case cir::SideEffect::Pure:
328 memoryEffect = mlir::LLVM::MemoryEffectsAttr::get(
329 callOp->getContext(), ModRefInfo::Ref,
339 case cir::SideEffect::Const:
340 memoryEffect = mlir::LLVM::MemoryEffectsAttr::get(
341 callOp->getContext(), ModRefInfo::NoModRef,
342 ModRefInfo::NoModRef,
343 ModRefInfo::NoModRef,
344 ModRefInfo::NoModRef,
345 ModRefInfo::NoModRef,
346 ModRefInfo::NoModRef);
352 noReturn = callOp->hasAttr(CIRDialect::getNoReturnAttrName());
355static mlir::LLVM::CallIntrinsicOp
357 mlir::Location loc,
const llvm::Twine &intrinsicName,
358 mlir::Type resultTy, mlir::ValueRange operands) {
359 auto intrinsicNameAttr =
360 mlir::StringAttr::get(rewriter.getContext(), intrinsicName);
361 return mlir::LLVM::CallIntrinsicOp::create(rewriter, loc, resultTy,
362 intrinsicNameAttr, operands);
366 mlir::ConversionPatternRewriter &rewriter, mlir::Operation *op,
367 const llvm::Twine &intrinsicName, mlir::Type resultTy,
368 mlir::ValueRange operands) {
370 rewriter, op->getLoc(), intrinsicName, resultTy, operands);
371 rewriter.replaceOp(op, callIntrinOp.getOperation());
375mlir::LogicalResult CIRToLLVMLLVMIntrinsicCallOpLowering::matchAndRewrite(
376 cir::LLVMIntrinsicCallOp op, OpAdaptor adaptor,
377 mlir::ConversionPatternRewriter &rewriter)
const {
378 mlir::Type llvmResTy =
379 getTypeConverter()->convertType(op->getResultTypes()[0]);
381 return op.emitError(
"expected LLVM result type");
382 StringRef name = op.getIntrinsicName();
395 adaptor.getOperands());
396 return mlir::success();
400mlir::Value CIRAttrToValue::visitCirAttr(cir::BoolAttr boolAttr) {
401 mlir::Location loc = parentOp->getLoc();
402 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
403 mlir::Value boolVal = mlir::LLVM::ConstantOp::create(
404 rewriter, loc, converter->convertType(boolAttr.getType()),
405 boolAttr.getValue());
406 return emitToMemory(rewriter, layout, boolAttr.getType(), boolVal);
410mlir::Value CIRAttrToValue::visitCirAttr(cir::IntAttr intAttr) {
411 mlir::Location loc = parentOp->getLoc();
412 return mlir::LLVM::ConstantOp::create(
413 rewriter, loc, converter->convertType(intAttr.getType()),
418mlir::Value CIRAttrToValue::visitCirAttr(cir::FPAttr fltAttr) {
419 mlir::Location loc = parentOp->getLoc();
420 return mlir::LLVM::ConstantOp::create(
421 rewriter, loc, converter->convertType(fltAttr.getType()),
426mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstComplexAttr complexAttr) {
427 auto complexType = mlir::cast<cir::ComplexType>(complexAttr.getType());
428 mlir::Type complexElemTy =
complexType.getElementType();
429 mlir::Type complexElemLLVMTy = converter->convertType(complexElemTy);
431 mlir::Attribute components[2];
432 if (
const auto intType = mlir::dyn_cast<cir::IntType>(complexElemTy)) {
433 components[0] = rewriter.getIntegerAttr(
435 mlir::cast<cir::IntAttr>(complexAttr.getReal()).getValue());
436 components[1] = rewriter.getIntegerAttr(
438 mlir::cast<cir::IntAttr>(complexAttr.getImag()).getValue());
440 components[0] = rewriter.getFloatAttr(
442 mlir::cast<cir::FPAttr>(complexAttr.getReal()).getValue());
443 components[1] = rewriter.getFloatAttr(
445 mlir::cast<cir::FPAttr>(complexAttr.getImag()).getValue());
448 mlir::Location loc = parentOp->getLoc();
449 return mlir::LLVM::ConstantOp::create(
450 rewriter, loc, converter->convertType(complexAttr.getType()),
451 rewriter.getArrayAttr(components));
455mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstPtrAttr ptrAttr) {
456 mlir::Location loc = parentOp->getLoc();
457 if (ptrAttr.isNullValue()) {
458 return mlir::LLVM::ZeroOp::create(
459 rewriter, loc, converter->convertType(ptrAttr.getType()));
461 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
462 mlir::Value ptrVal = mlir::LLVM::ConstantOp::create(
464 rewriter.getIntegerType(layout.getTypeSizeInBits(ptrAttr.getType())),
465 ptrAttr.getValue().getInt());
466 return mlir::LLVM::IntToPtrOp::create(
467 rewriter, loc, converter->convertType(ptrAttr.getType()), ptrVal);
471mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstArrayAttr attr) {
472 mlir::Type llvmTy = converter->convertType(
attr.getType());
473 mlir::Location loc = parentOp->getLoc();
476 if (
attr.hasTrailingZeros()) {
477 mlir::Type arrayTy =
attr.getType();
478 result = mlir::LLVM::ZeroOp::create(rewriter, loc,
479 converter->convertType(arrayTy));
481 result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
485 if (
auto arrayAttr = mlir::dyn_cast<mlir::ArrayAttr>(
attr.getElts())) {
486 for (
auto [idx, elt] : llvm::enumerate(arrayAttr)) {
487 mlir::DataLayout dataLayout(parentOp->getParentOfType<mlir::ModuleOp>());
488 mlir::Value init = visit(elt);
490 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
492 }
else if (
auto strAttr = mlir::dyn_cast<mlir::StringAttr>(
attr.getElts())) {
495 auto arrayTy = mlir::dyn_cast<cir::ArrayType>(strAttr.getType());
496 assert(arrayTy &&
"String attribute must have an array type");
497 mlir::Type eltTy = arrayTy.getElementType();
498 for (
auto [idx, elt] : llvm::enumerate(strAttr)) {
499 auto init = mlir::LLVM::ConstantOp::create(
500 rewriter, loc, converter->convertType(eltTy), elt);
502 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
505 llvm_unreachable(
"unexpected ConstArrayAttr elements");
512mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstRecordAttr constRecord) {
513 const mlir::Type llvmTy = converter->convertType(constRecord.getType());
514 const mlir::Location loc = parentOp->getLoc();
515 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
518 for (
auto [idx, elt] : llvm::enumerate(constRecord.getMembers())) {
519 mlir::Value init = visit(elt);
521 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
528mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstVectorAttr attr) {
529 const mlir::Type llvmTy = converter->convertType(
attr.getType());
530 const mlir::Location loc = parentOp->getLoc();
532 SmallVector<mlir::Attribute> mlirValues;
533 for (
const mlir::Attribute elementAttr :
attr.getElts()) {
534 mlir::Attribute mlirAttr;
535 if (
auto intAttr = mlir::dyn_cast<cir::IntAttr>(elementAttr)) {
536 mlirAttr = rewriter.getIntegerAttr(
537 converter->convertType(intAttr.getType()), intAttr.getValue());
538 }
else if (
auto floatAttr = mlir::dyn_cast<cir::FPAttr>(elementAttr)) {
539 mlirAttr = rewriter.getFloatAttr(
540 converter->convertType(floatAttr.getType()), floatAttr.getValue());
543 "vector constant with an element that is neither an int nor a float");
545 mlirValues.push_back(mlirAttr);
548 return mlir::LLVM::ConstantOp::create(
549 rewriter, loc, llvmTy,
550 mlir::DenseElementsAttr::get(mlir::cast<mlir::ShapedType>(llvmTy),
555mlir::Value CIRAttrToValue::visitCirAttr(cir::GlobalViewAttr globalAttr) {
556 auto moduleOp = parentOp->getParentOfType<mlir::ModuleOp>();
557 mlir::DataLayout dataLayout(moduleOp);
558 mlir::Type sourceType;
559 unsigned sourceAddrSpace = 0;
560 llvm::StringRef symName;
561 mlir::Operation *sourceSymbol =
562 mlir::SymbolTable::lookupSymbolIn(moduleOp, globalAttr.getSymbol());
563 if (
auto llvmSymbol = dyn_cast<mlir::LLVM::GlobalOp>(sourceSymbol)) {
564 sourceType = llvmSymbol.getType();
565 symName = llvmSymbol.getSymName();
566 sourceAddrSpace = llvmSymbol.getAddrSpace();
567 }
else if (
auto cirSymbol = dyn_cast<cir::GlobalOp>(sourceSymbol)) {
570 symName = cirSymbol.getSymName();
571 if (
auto targetAS = mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
572 cirSymbol.getAddrSpaceAttr()))
573 sourceAddrSpace = targetAS.getValue();
574 }
else if (
auto llvmFun = dyn_cast<mlir::LLVM::LLVMFuncOp>(sourceSymbol)) {
575 sourceType = llvmFun.getFunctionType();
576 symName = llvmFun.getSymName();
577 }
else if (
auto fun = dyn_cast<cir::FuncOp>(sourceSymbol)) {
578 sourceType = converter->convertType(fun.getFunctionType());
579 symName = fun.getSymName();
580 }
else if (
auto alias = dyn_cast<mlir::LLVM::AliasOp>(sourceSymbol)) {
581 sourceType = alias.getType();
582 symName = alias.getSymName();
584 llvm_unreachable(
"Unexpected GlobalOp type");
587 mlir::Location loc = parentOp->getLoc();
588 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
590 mlir::LLVM::LLVMPointerType::get(rewriter.getContext(), sourceAddrSpace),
593 if (globalAttr.getIndices()) {
594 llvm::SmallVector<mlir::LLVM::GEPArg> indices;
596 if (mlir::isa<mlir::LLVM::LLVMArrayType, mlir::LLVM::LLVMStructType>(
598 indices.push_back(0);
600 for (mlir::Attribute idx : globalAttr.getIndices()) {
601 auto intAttr = mlir::cast<mlir::IntegerAttr>(idx);
602 indices.push_back(intAttr.getValue().getSExtValue());
604 mlir::Type resTy = addrOp.getType();
605 mlir::Type eltTy = converter->convertType(sourceType);
607 mlir::LLVM::GEPOp::create(rewriter, loc, resTy, eltTy, addrOp, indices,
608 mlir::LLVM::GEPNoWrapFlags::none);
615 if (
auto intTy = mlir::dyn_cast<cir::IntType>(globalAttr.getType())) {
616 mlir::Type llvmDstTy = converter->convertType(globalAttr.getType());
617 return mlir::LLVM::PtrToIntOp::create(rewriter, parentOp->getLoc(),
621 if (
auto ptrTy = mlir::dyn_cast<cir::PointerType>(globalAttr.getType())) {
622 auto llvmDstTy = converter->convertType<mlir::LLVM::LLVMPointerType>(ptrTy);
623 unsigned dstAddrSpace = llvmDstTy.getAddressSpace();
625 if (sourceAddrSpace != dstAddrSpace)
626 addrOp = mlir::LLVM::AddrSpaceCastOp::create(rewriter, parentOp->getLoc(),
629 mlir::Type llvmEltTy =
633 if (llvmEltTy == sourceType)
639 if (addrOp.getType() == llvmDstTy)
642 return mlir::LLVM::BitcastOp::create(rewriter, parentOp->getLoc(),
646 if (mlir::isa<cir::VPtrType>(globalAttr.getType()))
649 llvm_unreachable(
"Expecting pointer or integer type for GlobalViewAttr");
653mlir::Value CIRAttrToValue::visitCirAttr(cir::TypeInfoAttr typeInfoAttr) {
654 mlir::Type llvmTy = converter->convertType(typeInfoAttr.getType());
655 mlir::Location loc = parentOp->getLoc();
656 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
658 for (
auto [idx, elt] : llvm::enumerate(typeInfoAttr.getData())) {
659 mlir::Value init = visit(elt);
661 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
668mlir::Value CIRAttrToValue::visitCirAttr(cir::UndefAttr undefAttr) {
669 mlir::Location loc = parentOp->getLoc();
670 return mlir::LLVM::UndefOp::create(
671 rewriter, loc, converter->convertType(undefAttr.getType()));
675mlir::Value CIRAttrToValue::visitCirAttr(cir::PoisonAttr poisonAttr) {
676 mlir::Location loc = parentOp->getLoc();
677 return mlir::LLVM::PoisonOp::create(
678 rewriter, loc, converter->convertType(poisonAttr.getType()));
682mlir::Value CIRAttrToValue::visitCirAttr(cir::VTableAttr vtableArr) {
683 mlir::Type llvmTy = converter->convertType(vtableArr.getType());
684 mlir::Location loc = parentOp->getLoc();
685 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
687 for (
auto [idx, elt] : llvm::enumerate(vtableArr.getData())) {
688 mlir::Value init = visit(elt);
690 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
697mlir::Value CIRAttrToValue::visitCirAttr(cir::ZeroAttr attr) {
698 mlir::Location loc = parentOp->getLoc();
699 return mlir::LLVM::ZeroOp::create(rewriter, loc,
700 converter->convertType(
attr.getType()));
708 mlir::ConversionPatternRewriter &rewriter)
709 : llvmType(type), rewriter(rewriter) {}
712 return llvm::TypeSwitch<mlir::Attribute, mlir::Attribute>(
attr)
713 .Case<cir::IntAttr, cir::FPAttr, cir::BoolAttr>(
715 .
Default([&](
auto attrT) {
return mlir::Attribute(); });
719 return rewriter.getIntegerAttr(llvmType,
attr.getValue());
723 return rewriter.getFloatAttr(llvmType,
attr.getValue());
727 return rewriter.getBoolAttr(
attr.getValue());
732 mlir::ConversionPatternRewriter &rewriter;
740 :
public mlir::PassWrapper<ConvertCIRToLLVMPass,
741 mlir::OperationPass<mlir::ModuleOp>> {
743 registry.insert<mlir::BuiltinDialect, mlir::DLTIDialect,
744 mlir::LLVM::LLVMDialect, mlir::func::FuncDialect>();
762 return "Convert the prepared CIR dialect module to LLVM dialect";
765 StringRef
getArgument()
const override {
return "cir-flat-to-llvm"; }
769 struct CollectedAnnotation {
770 mlir::StringAttr symName;
771 cir::AnnotationAttr annotation;
773 CollectedAnnotation(mlir::StringAttr symName,
774 cir::AnnotationAttr annotation, mlir::Location loc)
775 : symName(symName), annotation(annotation), loc(loc) {}
780mlir::LogicalResult CIRToLLVMIsFPClassOpLowering::matchAndRewrite(
781 cir::IsFPClassOp op, OpAdaptor adaptor,
782 mlir::ConversionPatternRewriter &rewriter)
const {
783 mlir::Value src = adaptor.getSrc();
784 cir::FPClassTest flags = adaptor.getFlags();
785 mlir::IntegerType retTy = rewriter.getI1Type();
787 rewriter.replaceOpWithNewOp<mlir::LLVM::IsFPClass>(
788 op, retTy, src,
static_cast<uint32_t>(flags));
789 return mlir::success();
792mlir::LogicalResult CIRToLLVMSignBitOpLowering::matchAndRewrite(
793 cir::SignBitOp op, OpAdaptor adaptor,
794 mlir::ConversionPatternRewriter &rewriter)
const {
797 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
798 int width = layout.getTypeSizeInBits(op.getInput().getType());
799 if (
auto longDoubleType =
800 mlir::dyn_cast<cir::LongDoubleType>(op.getInput().getType())) {
801 if (mlir::isa<cir::FP80Type>(longDoubleType.getUnderlying())) {
809 mlir::Type intTy = mlir::IntegerType::get(rewriter.getContext(), width);
810 auto bitcast = mlir::LLVM::BitcastOp::create(rewriter, op->getLoc(), intTy,
813 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op->getLoc(), intTy, 0);
814 auto cmpResult = mlir::LLVM::ICmpOp::create(rewriter, op.getLoc(),
815 mlir::LLVM::ICmpPredicate::slt,
816 bitcast.getResult(), zero);
817 rewriter.replaceOp(op, cmpResult);
818 return mlir::success();
821mlir::LogicalResult CIRToLLVMAssumeOpLowering::matchAndRewrite(
822 cir::AssumeOp op, OpAdaptor adaptor,
823 mlir::ConversionPatternRewriter &rewriter)
const {
824 mlir::Value cond = adaptor.getPredicate();
825 if (op.getBundleKind() == cir::AssumeBundleKind::None) {
826 rewriter.replaceOpWithNewOp<mlir::LLVM::AssumeOp>(op, cond);
827 return mlir::success();
830 llvm::StringRef tag = cir::stringifyAssumeBundleKind(op.getBundleKind());
831 rewriter.replaceOpWithNewOp<mlir::LLVM::AssumeOp>(op, cond, tag,
832 adaptor.getBundleArgs());
833 return mlir::success();
836static mlir::LLVM::AtomicOrdering
839 return mlir::LLVM::AtomicOrdering::not_atomic;
841 case cir::MemOrder::Relaxed:
842 return mlir::LLVM::AtomicOrdering::monotonic;
843 case cir::MemOrder::Consume:
844 case cir::MemOrder::Acquire:
845 return mlir::LLVM::AtomicOrdering::acquire;
846 case cir::MemOrder::Release:
847 return mlir::LLVM::AtomicOrdering::release;
848 case cir::MemOrder::AcquireRelease:
849 return mlir::LLVM::AtomicOrdering::acq_rel;
850 case cir::MemOrder::SequentiallyConsistent:
851 return mlir::LLVM::AtomicOrdering::seq_cst;
853 llvm_unreachable(
"unknown memory order");
857 return syncScope == cir::SyncScopeKind::SingleThread ?
"singlethread" :
"";
860static std::optional<llvm::StringRef>
862 if (syncScope.has_value())
867mlir::LogicalResult CIRToLLVMAtomicCmpXchgOpLowering::matchAndRewrite(
868 cir::AtomicCmpXchgOp op, OpAdaptor adaptor,
869 mlir::ConversionPatternRewriter &rewriter)
const {
870 mlir::Value expected = adaptor.getExpected();
871 mlir::Value desired = adaptor.getDesired();
873 auto cmpxchg = mlir::LLVM::AtomicCmpXchgOp::create(
874 rewriter, op.getLoc(), adaptor.getPtr(), expected, desired,
879 cmpxchg.setAlignment(adaptor.getAlignment());
880 cmpxchg.setWeak(adaptor.getWeak());
881 cmpxchg.setVolatile_(adaptor.getIsVolatile());
884 auto old = mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(),
885 cmpxchg.getResult(), 0);
886 auto cmp = mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(),
887 cmpxchg.getResult(), 1);
889 rewriter.replaceOp(op, {old, cmp});
890 return mlir::success();
893mlir::LogicalResult CIRToLLVMAtomicXchgOpLowering::matchAndRewrite(
894 cir::AtomicXchgOp op, OpAdaptor adaptor,
895 mlir::ConversionPatternRewriter &rewriter)
const {
897 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(adaptor.getMemOrder());
899 rewriter.replaceOpWithNewOp<mlir::LLVM::AtomicRMWOp>(
900 op, mlir::LLVM::AtomicBinOp::xchg, adaptor.getPtr(), adaptor.getVal(),
901 llvmOrder, llvmSyncScope);
902 return mlir::success();
905mlir::LogicalResult CIRToLLVMAtomicTestAndSetOpLowering::matchAndRewrite(
906 cir::AtomicTestAndSetOp op, OpAdaptor adaptor,
907 mlir::ConversionPatternRewriter &rewriter)
const {
910 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
912 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
913 rewriter.getI8Type(), 1);
914 auto rmw = mlir::LLVM::AtomicRMWOp::create(
915 rewriter, op.getLoc(), mlir::LLVM::AtomicBinOp::xchg, adaptor.getPtr(),
916 one, llvmOrder, llvm::StringRef(),
917 adaptor.getAlignment().value_or(0), op.getIsVolatile());
919 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
920 rewriter.getI8Type(), 0);
921 auto cmp = mlir::LLVM::ICmpOp::create(
922 rewriter, op.getLoc(), mlir::LLVM::ICmpPredicate::ne, rmw, zero);
924 rewriter.replaceOp(op, cmp);
925 return mlir::success();
928mlir::LogicalResult CIRToLLVMAtomicClearOpLowering::matchAndRewrite(
929 cir::AtomicClearOp op, OpAdaptor adaptor,
930 mlir::ConversionPatternRewriter &rewriter)
const {
933 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
934 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
935 rewriter.getI8Type(), 0);
936 auto store = mlir::LLVM::StoreOp::create(
937 rewriter, op.getLoc(), zero, adaptor.getPtr(),
938 adaptor.getAlignment().value_or(0), op.getIsVolatile(),
939 false,
false, llvmOrder);
941 rewriter.replaceOp(op, store);
942 return mlir::success();
945mlir::LogicalResult CIRToLLVMAtomicFenceOpLowering::matchAndRewrite(
946 cir::AtomicFenceOp op, OpAdaptor adaptor,
947 mlir::ConversionPatternRewriter &rewriter)
const {
948 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(adaptor.getOrdering());
950 auto fence = mlir::LLVM::FenceOp::create(rewriter, op.getLoc(), llvmOrder);
953 rewriter.replaceOp(op, fence);
955 return mlir::success();
958static mlir::LLVM::AtomicBinOp
961 case cir::AtomicFetchKind::Add:
962 return isInt ? mlir::LLVM::AtomicBinOp::add : mlir::LLVM::AtomicBinOp::fadd;
963 case cir::AtomicFetchKind::Sub:
964 return isInt ? mlir::LLVM::AtomicBinOp::sub : mlir::LLVM::AtomicBinOp::fsub;
965 case cir::AtomicFetchKind::And:
966 return mlir::LLVM::AtomicBinOp::_and;
967 case cir::AtomicFetchKind::Xor:
968 return mlir::LLVM::AtomicBinOp::_xor;
969 case cir::AtomicFetchKind::Or:
970 return mlir::LLVM::AtomicBinOp::_or;
971 case cir::AtomicFetchKind::Nand:
972 return mlir::LLVM::AtomicBinOp::nand;
973 case cir::AtomicFetchKind::Max: {
975 return mlir::LLVM::AtomicBinOp::fmax;
976 return isSignedInt ? mlir::LLVM::AtomicBinOp::max
977 : mlir::LLVM::AtomicBinOp::umax;
979 case cir::AtomicFetchKind::Min: {
981 return mlir::LLVM::AtomicBinOp::fmin;
982 return isSignedInt ? mlir::LLVM::AtomicBinOp::min
983 : mlir::LLVM::AtomicBinOp::umin;
985 case cir::AtomicFetchKind::UIncWrap:
986 return mlir::LLVM::AtomicBinOp::uinc_wrap;
987 case cir::AtomicFetchKind::UDecWrap:
988 return mlir::LLVM::AtomicBinOp::udec_wrap;
990 llvm_unreachable(
"Unknown atomic fetch opcode");
996 case cir::AtomicFetchKind::Add:
997 return isInt ? mlir::LLVM::AddOp::getOperationName()
998 : mlir::LLVM::FAddOp::getOperationName();
999 case cir::AtomicFetchKind::Sub:
1000 return isInt ? mlir::LLVM::SubOp::getOperationName()
1001 : mlir::LLVM::FSubOp::getOperationName();
1002 case cir::AtomicFetchKind::And:
1003 return mlir::LLVM::AndOp::getOperationName();
1004 case cir::AtomicFetchKind::Xor:
1005 return mlir::LLVM::XOrOp::getOperationName();
1006 case cir::AtomicFetchKind::Or:
1007 return mlir::LLVM::OrOp::getOperationName();
1008 case cir::AtomicFetchKind::Nand:
1010 return mlir::LLVM::AndOp::getOperationName();
1011 case cir::AtomicFetchKind::Max:
1012 case cir::AtomicFetchKind::Min:
1013 llvm_unreachable(
"handled in buildMinMaxPostOp");
1014 case cir::AtomicFetchKind::UIncWrap:
1015 case cir::AtomicFetchKind::UDecWrap:
1016 llvm_unreachable(
"uinc_wrap and udec_wrap are always fetch_first");
1018 llvm_unreachable(
"Unknown atomic fetch opcode");
1021mlir::Value CIRToLLVMAtomicFetchOpLowering::buildPostOp(
1022 cir::AtomicFetchOp op, OpAdaptor adaptor,
1023 mlir::ConversionPatternRewriter &rewriter, mlir::Value rmwVal,
1028 .create(op.getLoc(),
1029 rewriter.getStringAttr(
1031 atomicOperands, atomicResTys, {})
1035mlir::Value CIRToLLVMAtomicFetchOpLowering::buildMinMaxPostOp(
1036 cir::AtomicFetchOp op, OpAdaptor adaptor,
1037 mlir::ConversionPatternRewriter &rewriter, mlir::Value rmwVal,
bool isInt,
1038 bool isSigned)
const {
1039 mlir::Location loc = op.getLoc();
1042 if (op.getBinop() == cir::AtomicFetchKind::Max)
1043 return mlir::LLVM::MaxNumOp::create(rewriter, loc, rmwVal,
1045 return mlir::LLVM::MinNumOp::create(rewriter, loc, rmwVal,
1049 mlir::LLVM::ICmpPredicate pred;
1050 if (op.getBinop() == cir::AtomicFetchKind::Max) {
1051 pred = isSigned ? mlir::LLVM::ICmpPredicate::sgt
1052 : mlir::LLVM::ICmpPredicate::ugt;
1054 pred = isSigned ? mlir::LLVM::ICmpPredicate::slt
1055 : mlir::LLVM::ICmpPredicate::ult;
1057 mlir::Value cmp = mlir::LLVM::ICmpOp::create(
1059 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(), pred), rmwVal,
1061 return mlir::LLVM::SelectOp::create(rewriter, loc, cmp, rmwVal,
1065mlir::LogicalResult CIRToLLVMAtomicFetchOpLowering::matchAndRewrite(
1066 cir::AtomicFetchOp op, OpAdaptor adaptor,
1067 mlir::ConversionPatternRewriter &rewriter)
const {
1069 bool isSignedInt =
false;
1070 if (
auto intTy = mlir::dyn_cast<cir::IntType>(op.getVal().getType())) {
1072 isSignedInt = intTy.isSigned();
1073 }
else if (mlir::isa<cir::SingleType, cir::DoubleType>(
1074 op.getVal().getType())) {
1077 return op.emitError() <<
"Unsupported type: " << op.getVal().getType();
1080 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
1082 mlir::LLVM::AtomicBinOp llvmBinOp =
1084 auto rmwVal = mlir::LLVM::AtomicRMWOp::create(
1085 rewriter, op.getLoc(), llvmBinOp, adaptor.getPtr(), adaptor.getVal(),
1086 llvmOrder, llvmSyncScope);
1088 mlir::Value result = rmwVal.getResult();
1089 if (!op.getFetchFirst()) {
1090 if (op.getBinop() == cir::AtomicFetchKind::Max ||
1091 op.getBinop() == cir::AtomicFetchKind::Min)
1092 result = buildMinMaxPostOp(op, adaptor, rewriter, rmwVal.getRes(), isInt,
1095 result = buildPostOp(op, adaptor, rewriter, rmwVal.getRes(), isInt);
1098 if (op.getBinop() == cir::AtomicFetchKind::Nand) {
1099 auto negOne = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1100 result.getType(), -1);
1101 result = mlir::LLVM::XOrOp::create(rewriter, op.getLoc(), result, negOne);
1105 rewriter.replaceOp(op, result);
1106 return mlir::success();
1109mlir::LogicalResult CIRToLLVMBitClrsbOpLowering::matchAndRewrite(
1110 cir::BitClrsbOp op, OpAdaptor adaptor,
1111 mlir::ConversionPatternRewriter &rewriter)
const {
1112 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1113 adaptor.getInput().getType(), 0);
1114 auto isNeg = mlir::LLVM::ICmpOp::create(
1115 rewriter, op.getLoc(),
1116 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(),
1117 mlir::LLVM::ICmpPredicate::slt),
1118 adaptor.getInput(), zero);
1120 auto negOne = mlir::LLVM::ConstantOp::create(
1121 rewriter, op.getLoc(), adaptor.getInput().getType(), -1);
1122 auto flipped = mlir::LLVM::XOrOp::create(rewriter, op.getLoc(),
1123 adaptor.getInput(), negOne);
1125 auto select = mlir::LLVM::SelectOp::create(rewriter, op.getLoc(), isNeg,
1126 flipped, adaptor.getInput());
1128 auto resTy = getTypeConverter()->convertType(op.getType());
1129 auto clz = mlir::LLVM::CountLeadingZerosOp::create(
1130 rewriter, op.getLoc(), resTy,
select,
false);
1132 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1133 auto res = mlir::LLVM::SubOp::create(rewriter, op.getLoc(),
clz, one,
1134 mlir::LLVM::IntegerOverflowFlags::nuw);
1135 rewriter.replaceOp(op, res);
1137 return mlir::LogicalResult::success();
1140mlir::LogicalResult CIRToLLVMBitClzOpLowering::matchAndRewrite(
1141 cir::BitClzOp op, OpAdaptor adaptor,
1142 mlir::ConversionPatternRewriter &rewriter)
const {
1143 auto resTy = getTypeConverter()->convertType(op.getType());
1144 auto llvmOp = mlir::LLVM::CountLeadingZerosOp::create(
1145 rewriter, op.getLoc(), resTy, adaptor.getInput(), op.getPoisonZero());
1146 rewriter.replaceOp(op, llvmOp);
1147 return mlir::LogicalResult::success();
1150mlir::LogicalResult CIRToLLVMBitCtzOpLowering::matchAndRewrite(
1151 cir::BitCtzOp op, OpAdaptor adaptor,
1152 mlir::ConversionPatternRewriter &rewriter)
const {
1153 auto resTy = getTypeConverter()->convertType(op.getType());
1154 auto llvmOp = mlir::LLVM::CountTrailingZerosOp::create(
1155 rewriter, op.getLoc(), resTy, adaptor.getInput(), op.getPoisonZero());
1156 rewriter.replaceOp(op, llvmOp);
1157 return mlir::LogicalResult::success();
1160mlir::LogicalResult CIRToLLVMBitFfsOpLowering::matchAndRewrite(
1161 cir::BitFfsOp op, OpAdaptor adaptor,
1162 mlir::ConversionPatternRewriter &rewriter)
const {
1163 auto resTy = getTypeConverter()->convertType(op.getType());
1164 auto ctz = mlir::LLVM::CountTrailingZerosOp::create(rewriter, op.getLoc(),
1165 resTy, adaptor.getInput(),
1168 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1169 auto ctzAddOne = mlir::LLVM::AddOp::create(rewriter, op.getLoc(),
ctz, one);
1171 auto zeroInputTy = mlir::LLVM::ConstantOp::create(
1172 rewriter, op.getLoc(), adaptor.getInput().getType(), 0);
1173 auto isZero = mlir::LLVM::ICmpOp::create(
1174 rewriter, op.getLoc(),
1175 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(),
1176 mlir::LLVM::ICmpPredicate::eq),
1177 adaptor.getInput(), zeroInputTy);
1179 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 0);
1180 auto res = mlir::LLVM::SelectOp::create(rewriter, op.getLoc(), isZero, zero,
1182 rewriter.replaceOp(op, res);
1184 return mlir::LogicalResult::success();
1187mlir::LogicalResult CIRToLLVMBitParityOpLowering::matchAndRewrite(
1188 cir::BitParityOp op, OpAdaptor adaptor,
1189 mlir::ConversionPatternRewriter &rewriter)
const {
1190 auto resTy = getTypeConverter()->convertType(op.getType());
1191 auto popcnt = mlir::LLVM::CtPopOp::create(rewriter, op.getLoc(), resTy,
1192 adaptor.getInput());
1194 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1196 mlir::LLVM::AndOp::create(rewriter, op.getLoc(), popcnt, one);
1197 rewriter.replaceOp(op, popcntMod2);
1199 return mlir::LogicalResult::success();
1202mlir::LogicalResult CIRToLLVMBitPopcountOpLowering::matchAndRewrite(
1203 cir::BitPopcountOp op, OpAdaptor adaptor,
1204 mlir::ConversionPatternRewriter &rewriter)
const {
1205 auto resTy = getTypeConverter()->convertType(op.getType());
1206 auto llvmOp = mlir::LLVM::CtPopOp::create(rewriter, op.getLoc(), resTy,
1207 adaptor.getInput());
1208 rewriter.replaceOp(op, llvmOp);
1209 return mlir::LogicalResult::success();
1212mlir::LogicalResult CIRToLLVMBitReverseOpLowering::matchAndRewrite(
1213 cir::BitReverseOp op, OpAdaptor adaptor,
1214 mlir::ConversionPatternRewriter &rewriter)
const {
1215 rewriter.replaceOpWithNewOp<mlir::LLVM::BitReverseOp>(op, adaptor.getInput());
1216 return mlir::success();
1219mlir::LogicalResult CIRToLLVMBrCondOpLowering::matchAndRewrite(
1220 cir::BrCondOp brOp, OpAdaptor adaptor,
1221 mlir::ConversionPatternRewriter &rewriter)
const {
1226 mlir::Value i1Condition = adaptor.getCond();
1228 rewriter.replaceOpWithNewOp<mlir::LLVM::CondBrOp>(
1229 brOp, i1Condition, brOp.getDestTrue(), adaptor.getDestOperandsTrue(),
1230 brOp.getDestFalse(), adaptor.getDestOperandsFalse());
1232 return mlir::success();
1235mlir::LogicalResult CIRToLLVMByteSwapOpLowering::matchAndRewrite(
1236 cir::ByteSwapOp op, OpAdaptor adaptor,
1237 mlir::ConversionPatternRewriter &rewriter)
const {
1238 rewriter.replaceOpWithNewOp<mlir::LLVM::ByteSwapOp>(op, adaptor.getInput());
1239 return mlir::LogicalResult::success();
1242mlir::Type CIRToLLVMCastOpLowering::convertTy(mlir::Type ty)
const {
1243 return getTypeConverter()->convertType(ty);
1246mlir::LogicalResult CIRToLLVMCastOpLowering::matchAndRewrite(
1247 cir::CastOp castOp, OpAdaptor adaptor,
1248 mlir::ConversionPatternRewriter &rewriter)
const {
1253 switch (castOp.getKind()) {
1254 case cir::CastKind::array_to_ptrdecay: {
1255 const auto ptrTy = mlir::cast<cir::PointerType>(castOp.getType());
1256 mlir::Value sourceValue = adaptor.getSrc();
1257 mlir::Type targetType = convertTy(ptrTy);
1259 ptrTy.getPointee());
1260 llvm::SmallVector<mlir::LLVM::GEPArg> offset{0};
1261 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1262 castOp, targetType, elementTy, sourceValue, offset);
1265 case cir::CastKind::int_to_bool: {
1266 mlir::Value llvmSrcVal = adaptor.getSrc();
1267 mlir::Value zeroInt = mlir::LLVM::ConstantOp::create(
1268 rewriter, castOp.getLoc(), llvmSrcVal.getType(), 0);
1269 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
1270 castOp, mlir::LLVM::ICmpPredicate::ne, llvmSrcVal, zeroInt);
1273 case cir::CastKind::integral: {
1274 mlir::Type srcType = castOp.getSrc().getType();
1275 mlir::Type dstType = castOp.getType();
1276 mlir::Value llvmSrcVal = adaptor.getSrc();
1277 mlir::Type llvmDstType = getTypeConverter()->convertType(dstType);
1278 cir::IntType srcIntType =
1279 mlir::cast<cir::IntType>(elementTypeIfVector(srcType));
1280 cir::IntType dstIntType =
1281 mlir::cast<cir::IntType>(elementTypeIfVector(dstType));
1282 rewriter.replaceOp(castOp,
getLLVMIntCast(rewriter, llvmSrcVal, llvmDstType,
1283 srcIntType.isUnsigned(),
1284 srcIntType.getWidth(),
1285 dstIntType.getWidth()));
1288 case cir::CastKind::floating: {
1289 mlir::Value llvmSrcVal = adaptor.getSrc();
1290 mlir::Type llvmDstTy = getTypeConverter()->convertType(castOp.getType());
1292 mlir::Type srcTy = elementTypeIfVector(castOp.getSrc().getType());
1293 mlir::Type dstTy = elementTypeIfVector(castOp.getType());
1295 if (!mlir::isa<cir::FPTypeInterface>(dstTy) ||
1296 !mlir::isa<cir::FPTypeInterface>(srcTy))
1297 return castOp.emitError() <<
"NYI cast from " << srcTy <<
" to " << dstTy;
1299 auto getFloatWidth = [](mlir::Type ty) ->
unsigned {
1300 return mlir::cast<cir::FPTypeInterface>(ty).getWidth();
1303 if (getFloatWidth(srcTy) > getFloatWidth(dstTy))
1304 rewriter.replaceOpWithNewOp<mlir::LLVM::FPTruncOp>(castOp, llvmDstTy,
1307 rewriter.replaceOpWithNewOp<mlir::LLVM::FPExtOp>(castOp, llvmDstTy,
1309 return mlir::success();
1311 case cir::CastKind::int_to_ptr: {
1312 auto dstTy = mlir::cast<cir::PointerType>(castOp.getType());
1313 mlir::Value llvmSrcVal = adaptor.getSrc();
1314 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1315 rewriter.replaceOpWithNewOp<mlir::LLVM::IntToPtrOp>(castOp, llvmDstTy,
1317 return mlir::success();
1319 case cir::CastKind::ptr_to_int: {
1320 auto dstTy = mlir::cast<cir::IntType>(castOp.getType());
1321 mlir::Value llvmSrcVal = adaptor.getSrc();
1322 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1323 rewriter.replaceOpWithNewOp<mlir::LLVM::PtrToIntOp>(castOp, llvmDstTy,
1325 return mlir::success();
1327 case cir::CastKind::float_to_bool: {
1328 mlir::Value llvmSrcVal = adaptor.getSrc();
1329 auto kind = mlir::LLVM::FCmpPredicate::une;
1332 auto zeroFloat = mlir::LLVM::ConstantOp::create(
1333 rewriter, castOp.getLoc(), llvmSrcVal.getType(),
1334 mlir::FloatAttr::get(llvmSrcVal.getType(), 0.0));
1337 rewriter.replaceOpWithNewOp<mlir::LLVM::FCmpOp>(castOp,
kind, llvmSrcVal,
1340 return mlir::success();
1342 case cir::CastKind::bool_to_int: {
1343 auto dstTy = mlir::cast<cir::IntType>(castOp.getType());
1344 mlir::Value llvmSrcVal = adaptor.getSrc();
1345 auto llvmSrcTy = mlir::cast<mlir::IntegerType>(llvmSrcVal.getType());
1347 mlir::cast<mlir::IntegerType>(getTypeConverter()->convertType(dstTy));
1349 if (llvmSrcTy.getWidth() == llvmDstTy.getWidth())
1350 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(castOp, llvmDstTy,
1353 rewriter.replaceOpWithNewOp<mlir::LLVM::ZExtOp>(castOp, llvmDstTy,
1355 return mlir::success();
1357 case cir::CastKind::bool_to_float: {
1358 mlir::Type dstTy = castOp.getType();
1359 mlir::Value llvmSrcVal = adaptor.getSrc();
1360 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1361 rewriter.replaceOpWithNewOp<mlir::LLVM::UIToFPOp>(castOp, llvmDstTy,
1363 return mlir::success();
1365 case cir::CastKind::int_to_float: {
1366 mlir::Type dstTy = castOp.getType();
1367 mlir::Value llvmSrcVal = adaptor.getSrc();
1368 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1369 if (mlir::cast<cir::IntType>(elementTypeIfVector(castOp.getSrc().getType()))
1371 rewriter.replaceOpWithNewOp<mlir::LLVM::SIToFPOp>(castOp, llvmDstTy,
1374 rewriter.replaceOpWithNewOp<mlir::LLVM::UIToFPOp>(castOp, llvmDstTy,
1376 return mlir::success();
1378 case cir::CastKind::float_to_int: {
1379 mlir::Type dstTy = castOp.getType();
1380 mlir::Value llvmSrcVal = adaptor.getSrc();
1381 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1382 if (mlir::cast<cir::IntType>(elementTypeIfVector(castOp.getType()))
1384 rewriter.replaceOpWithNewOp<mlir::LLVM::FPToSIOp>(castOp, llvmDstTy,
1387 rewriter.replaceOpWithNewOp<mlir::LLVM::FPToUIOp>(castOp, llvmDstTy,
1389 return mlir::success();
1391 case cir::CastKind::bitcast: {
1392 mlir::Type dstTy = castOp.getType();
1393 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1398 mlir::Value llvmSrcVal = adaptor.getSrc();
1399 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(castOp, llvmDstTy,
1401 return mlir::success();
1403 case cir::CastKind::ptr_to_bool: {
1404 mlir::Value llvmSrcVal = adaptor.getSrc();
1405 mlir::Value zeroPtr = mlir::LLVM::ZeroOp::create(rewriter, castOp.getLoc(),
1406 llvmSrcVal.getType());
1407 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
1408 castOp, mlir::LLVM::ICmpPredicate::ne, llvmSrcVal, zeroPtr);
1411 case cir::CastKind::address_space: {
1412 mlir::Type dstTy = castOp.getType();
1413 mlir::Value llvmSrcVal = adaptor.getSrc();
1414 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1415 rewriter.replaceOpWithNewOp<mlir::LLVM::AddrSpaceCastOp>(castOp, llvmDstTy,
1419 case cir::CastKind::member_ptr_to_bool:
1424 return castOp.emitError(
"Unhandled cast kind: ")
1425 << castOp.getKindAttrName();
1429 return mlir::success();
1433 mlir::ModuleOp mod, mlir::Value index,
1434 mlir::Type baseTy, cir::IntType strideTy) {
1435 mlir::Operation *indexOp = index.getDefiningOp();
1439 auto indexType = mlir::cast<mlir::IntegerType>(index.getType());
1440 mlir::DataLayout llvmLayout(mod);
1441 std::optional<uint64_t> layoutWidth = llvmLayout.getTypeIndexBitwidth(baseTy);
1444 if (!layoutWidth || *layoutWidth == indexType.getWidth())
1450 auto sub = dyn_cast<mlir::LLVM::SubOp>(indexOp);
1451 bool rewriteSub =
false;
1454 dyn_cast<mlir::LLVM::ConstantOp>(sub.getLhs().getDefiningOp())) {
1455 auto lhsConstInt = mlir::dyn_cast<mlir::IntegerAttr>(lhsConst.getValue());
1456 if (lhsConstInt && lhsConstInt.getValue() == 0) {
1457 index = sub.getRhs();
1463 auto llvmDstType = rewriter.getIntegerType(*layoutWidth);
1464 bool isUnsigned = strideTy && strideTy.isUnsigned();
1466 indexType.getWidth(), *layoutWidth);
1469 index = mlir::LLVM::SubOp::create(
1470 rewriter, index.getLoc(),
1471 mlir::LLVM::ConstantOp::create(rewriter, index.getLoc(),
1472 index.getType(), 0),
1475 rewriter.eraseOp(sub);
1481mlir::LogicalResult CIRToLLVMPtrStrideOpLowering::matchAndRewrite(
1482 cir::PtrStrideOp ptrStrideOp, OpAdaptor adaptor,
1483 mlir::ConversionPatternRewriter &rewriter)
const {
1485 const mlir::TypeConverter *tc = getTypeConverter();
1486 const mlir::Type resultTy = tc->convertType(ptrStrideOp.getType());
1488 mlir::Type elementTy =
1493 if (mlir::isa<mlir::LLVM::LLVMVoidType>(elementTy) ||
1494 mlir::isa<mlir::LLVM::LLVMFunctionType>(elementTy))
1495 elementTy = mlir::IntegerType::get(elementTy.getContext(), 8,
1496 mlir::IntegerType::Signless);
1498 mlir::Value index = adaptor.getStride();
1500 rewriter, ptrStrideOp->getParentOfType<mlir::ModuleOp>(), index,
1501 adaptor.getBase().getType(),
1502 dyn_cast<cir::IntType>(ptrStrideOp.getOperand(1).getType()));
1504 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1505 ptrStrideOp, resultTy, elementTy, adaptor.getBase(), index);
1506 return mlir::success();
1509mlir::LogicalResult CIRToLLVMGetElementOpLowering::matchAndRewrite(
1510 cir::GetElementOp op, OpAdaptor adaptor,
1511 mlir::ConversionPatternRewriter &rewriter)
const {
1513 mlir::dyn_cast<cir::ArrayType>(op.getBaseType().getPointee())) {
1514 const mlir::TypeConverter *converter = getTypeConverter();
1515 const mlir::Type llArrayTy = converter->convertType(arrayTy);
1516 const mlir::Type llResultTy = converter->convertType(op.getType());
1517 mlir::Type elementTy =
1522 if (mlir::isa<mlir::LLVM::LLVMVoidType>(elementTy) ||
1523 mlir::isa<mlir::LLVM::LLVMFunctionType>(elementTy))
1524 elementTy = rewriter.getIntegerType(8);
1526 mlir::Value index = adaptor.getIndex();
1529 adaptor.getBase().getType(),
1530 dyn_cast<cir::IntType>(op.getOperand(1).getType()));
1535 std::array<mlir::LLVM::GEPArg, 2> offset{0, index};
1536 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, llResultTy, llArrayTy,
1537 adaptor.getBase(), offset);
1538 return mlir::success();
1541 op.emitError() <<
"NYI: GetElementOp lowering to LLVM for non-array";
1542 return mlir::failure();
1545mlir::LogicalResult CIRToLLVMBaseClassAddrOpLowering::matchAndRewrite(
1546 cir::BaseClassAddrOp baseClassOp, OpAdaptor adaptor,
1547 mlir::ConversionPatternRewriter &rewriter)
const {
1548 const mlir::Type resultType =
1549 getTypeConverter()->convertType(baseClassOp.getType());
1550 mlir::Value derivedAddr = adaptor.getDerivedAddr();
1551 llvm::SmallVector<mlir::LLVM::GEPArg, 1> offset = {
1552 adaptor.getOffset().getZExtValue()};
1553 mlir::Type byteType = mlir::IntegerType::get(resultType.getContext(), 8,
1554 mlir::IntegerType::Signless);
1555 if (adaptor.getOffset().getZExtValue() == 0) {
1556 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(
1557 baseClassOp, resultType, adaptor.getDerivedAddr());
1558 return mlir::success();
1561 if (baseClassOp.getAssumeNotNull()) {
1562 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1563 baseClassOp, resultType, byteType, derivedAddr, offset);
1565 auto loc = baseClassOp.getLoc();
1566 mlir::Value isNull = mlir::LLVM::ICmpOp::create(
1567 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, derivedAddr,
1568 mlir::LLVM::ZeroOp::create(rewriter, loc, derivedAddr.getType()));
1569 mlir::Value adjusted = mlir::LLVM::GEPOp::create(
1570 rewriter, loc, resultType, byteType, derivedAddr, offset);
1571 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(baseClassOp, isNull,
1572 derivedAddr, adjusted);
1574 return mlir::success();
1577mlir::LogicalResult CIRToLLVMDerivedClassAddrOpLowering::matchAndRewrite(
1578 cir::DerivedClassAddrOp derivedClassOp, OpAdaptor adaptor,
1579 mlir::ConversionPatternRewriter &rewriter)
const {
1580 const mlir::Type resultType =
1581 getTypeConverter()->convertType(derivedClassOp.getType());
1582 mlir::Value baseAddr = adaptor.getBaseAddr();
1585 int64_t offsetVal = -(adaptor.getOffset().getZExtValue());
1586 if (offsetVal == 0) {
1588 rewriter.replaceOp(derivedClassOp, baseAddr);
1589 return mlir::success();
1591 llvm::SmallVector<mlir::LLVM::GEPArg, 1> offset = {offsetVal};
1592 mlir::Type byteType = mlir::IntegerType::get(resultType.getContext(), 8,
1593 mlir::IntegerType::Signless);
1594 if (derivedClassOp.getAssumeNotNull()) {
1595 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1596 derivedClassOp, resultType, byteType, baseAddr, offset,
1597 mlir::LLVM::GEPNoWrapFlags::inbounds);
1599 mlir::Location loc = derivedClassOp.getLoc();
1600 mlir::Value isNull = mlir::LLVM::ICmpOp::create(
1601 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, baseAddr,
1602 mlir::LLVM::ZeroOp::create(rewriter, loc, baseAddr.getType()));
1603 mlir::Value adjusted =
1604 mlir::LLVM::GEPOp::create(rewriter, loc, resultType, byteType, baseAddr,
1605 offset, mlir::LLVM::GEPNoWrapFlags::inbounds);
1606 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(derivedClassOp, isNull,
1607 baseAddr, adjusted);
1609 return mlir::success();
1612mlir::LogicalResult CIRToLLVMFMaxNumOpLowering::matchAndRewrite(
1613 cir::FMaxNumOp op, OpAdaptor adaptor,
1614 mlir::ConversionPatternRewriter &rewriter)
const {
1615 mlir::Type resTy = typeConverter->convertType(op.getType());
1616 rewriter.replaceOpWithNewOp<mlir::LLVM::MaxNumOp>(
1617 op, resTy, adaptor.getLhs(), adaptor.getRhs(),
1618 mlir::LLVM::FastmathFlags::nsz);
1619 return mlir::success();
1622mlir::LogicalResult CIRToLLVMFMinNumOpLowering::matchAndRewrite(
1623 cir::FMinNumOp op, OpAdaptor adaptor,
1624 mlir::ConversionPatternRewriter &rewriter)
const {
1625 mlir::Type resTy = typeConverter->convertType(op.getType());
1626 rewriter.replaceOpWithNewOp<mlir::LLVM::MinNumOp>(
1627 op, resTy, adaptor.getLhs(), adaptor.getRhs(),
1628 mlir::LLVM::FastmathFlags::nsz);
1629 return mlir::success();
1632mlir::LogicalResult CIRToLLVMAllocaOpLowering::matchAndRewrite(
1633 cir::AllocaOp op, OpAdaptor adaptor,
1634 mlir::ConversionPatternRewriter &rewriter)
const {
1637 ? adaptor.getDynAllocSize()
1638 : mlir::LLVM::ConstantOp::create(
1639 rewriter, op.getLoc(),
1640 typeConverter->convertType(rewriter.getIndexType()), 1);
1641 mlir::Type elementTy =
1643 mlir::Type resultTy =
1649 rewriter.replaceOpWithNewOp<mlir::LLVM::AllocaOp>(op, resultTy, elementTy,
1650 size, op.getAlignment());
1652 return mlir::success();
1655mlir::LogicalResult CIRToLLVMReturnOpLowering::matchAndRewrite(
1656 cir::ReturnOp op, OpAdaptor adaptor,
1657 mlir::ConversionPatternRewriter &rewriter)
const {
1658 rewriter.replaceOpWithNewOp<mlir::LLVM::ReturnOp>(op, adaptor.getOperands());
1659 return mlir::LogicalResult::success();
1662mlir::LogicalResult CIRToLLVMRotateOpLowering::matchAndRewrite(
1663 cir::RotateOp op, OpAdaptor adaptor,
1664 mlir::ConversionPatternRewriter &rewriter)
const {
1667 mlir::Value input = adaptor.getInput();
1668 if (op.isRotateLeft())
1669 rewriter.replaceOpWithNewOp<mlir::LLVM::FshlOp>(op, input, input,
1670 adaptor.getAmount());
1672 rewriter.replaceOpWithNewOp<mlir::LLVM::FshrOp>(op, input, input,
1673 adaptor.getAmount());
1674 return mlir::LogicalResult::success();
1679 for (mlir::NamedAttribute attr : op->getAttrs()) {
1680 if (attr.getName() == CIRDialect::getCalleeAttrName() ||
1681 attr.getName() == CIRDialect::getSideEffectAttrName() ||
1682 attr.getName() == CIRDialect::getNoThrowAttrName() ||
1683 attr.getName() == CIRDialect::getNoUnwindAttrName() ||
1684 attr.getName() == CIRDialect::getNoReturnAttrName() ||
1685 attr.getName() == CIRDialect::getMustTailAttrName())
1689 result.push_back(attr);
1693static mlir::LogicalResult
1695 mlir::ConversionPatternRewriter &rewriter,
1696 const mlir::TypeConverter *converter,
1697 mlir::SymbolTableCollection &symbolTables,
1698 mlir::FlatSymbolRefAttr calleeAttr,
1699 mlir::Block *continueBlock =
nullptr,
1700 mlir::Block *landingPadBlock =
nullptr) {
1702 mlir::ValueTypeRange<mlir::ResultRange> cirResults = op->getResultTypes();
1703 auto call = cast<cir::CIRCallOpInterface>(op);
1705 if (converter->convertTypes(cirResults, llvmResults).failed())
1706 return mlir::failure();
1710 mlir::LLVM::MemoryEffectsAttr memoryEffects;
1711 bool noUnwind =
false;
1712 bool willReturn =
false;
1713 bool noReturn =
false;
1715 memoryEffects, noUnwind, willReturn, noReturn);
1720 mlir::LLVM::LLVMFunctionType llvmFnTy;
1727 mlir::Operation *callee =
1728 symbolTables.lookupNearestSymbolFrom(op, calleeAttr);
1729 if (
auto fn = mlir::dyn_cast<mlir::FunctionOpInterface>(callee)) {
1730 llvmFnTy = converter->convertType<mlir::LLVM::LLVMFunctionType>(
1731 fn.getFunctionType());
1732 assert(llvmFnTy &&
"Failed to convert function type");
1733 }
else if (
auto alias = mlir::cast<mlir::LLVM::AliasOp>(callee)) {
1741 auto symAttr = mlir::cast<mlir::FlatSymbolRefAttr>(calleeAttr);
1743 mlir::LLVM::AddressOfOp::create(
1744 rewriter, op->getLoc(),
1745 mlir::LLVM::LLVMPointerType::get(rewriter.getContext()), symAttr)
1747 adjustedCallOperands.push_back(addrOfAlias);
1750 llvm::append_range(adjustedCallOperands, callOperands);
1751 callOperands = adjustedCallOperands;
1755 llvmFnTy = mlir::cast<mlir::LLVM::LLVMFunctionType>(alias.getType());
1758 return op->emitError(
"Unexpected callee type!");
1761 assert(!op->getOperands().empty() &&
1762 "operands list must no be empty for the indirect call");
1763 auto calleeTy = op->getOperands().front().getType();
1764 auto calleePtrTy = cast<cir::PointerType>(calleeTy);
1765 auto calleeFuncTy = cast<cir::FuncType>(calleePtrTy.getPointee());
1766 llvm::append_range(adjustedCallOperands, callOperands);
1767 llvmFnTy = cast<mlir::LLVM::LLVMFunctionType>(
1768 converter->convertType(calleeFuncTy));
1773 if (landingPadBlock) {
1774 auto newOp = rewriter.replaceOpWithNewOp<mlir::LLVM::InvokeOp>(
1775 op, llvmFnTy, calleeAttr, callOperands, continueBlock,
1776 mlir::ValueRange{}, landingPadBlock, mlir::ValueRange{});
1777 newOp->setAttrs(attributes);
1779 auto newOp = rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(
1780 op, llvmFnTy, calleeAttr, callOperands);
1781 newOp->setAttrs(attributes);
1783 newOp.setMemoryEffectsAttr(memoryEffects);
1784 newOp.setNoUnwind(noUnwind);
1785 newOp.setWillReturn(willReturn);
1786 newOp.setNoreturn(noReturn);
1787 if (op->hasAttr(CIRDialect::getMustTailAttrName()))
1788 newOp.setTailCallKind(mlir::LLVM::TailCallKind::MustTail);
1791 return mlir::success();
1794mlir::LogicalResult CIRToLLVMCallOpLowering::matchAndRewrite(
1795 cir::CallOp op, OpAdaptor adaptor,
1796 mlir::ConversionPatternRewriter &rewriter)
const {
1798 getTypeConverter(), symbolTables,
1799 op.getCalleeAttr());
1802mlir::LogicalResult CIRToLLVMTryCallOpLowering::matchAndRewrite(
1803 cir::TryCallOp op, OpAdaptor adaptor,
1804 mlir::ConversionPatternRewriter &rewriter)
const {
1807 op.getOperation(), adaptor.getOperands(), rewriter, getTypeConverter(),
1808 symbolTables, op.getCalleeAttr(), op.getNormalDest(), op.getUnwindDest());
1811mlir::LogicalResult CIRToLLVMReturnAddrOpLowering::matchAndRewrite(
1812 cir::ReturnAddrOp op, OpAdaptor adaptor,
1813 mlir::ConversionPatternRewriter &rewriter)
const {
1814 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
1816 llvmPtrTy, adaptor.getOperands());
1817 return mlir::success();
1820mlir::LogicalResult CIRToLLVMFrameAddrOpLowering::matchAndRewrite(
1821 cir::FrameAddrOp op, OpAdaptor adaptor,
1822 mlir::ConversionPatternRewriter &rewriter)
const {
1823 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
1825 adaptor.getOperands());
1826 return mlir::success();
1829mlir::LogicalResult CIRToLLVMClearCacheOpLowering::matchAndRewrite(
1830 cir::ClearCacheOp op, OpAdaptor adaptor,
1831 mlir::ConversionPatternRewriter &rewriter)
const {
1832 mlir::Value begin = adaptor.getBegin();
1833 mlir::Value end = adaptor.getEnd();
1834 auto intrinNameAttr =
1835 mlir::StringAttr::get(op.getContext(),
"llvm.clear_cache");
1836 rewriter.replaceOpWithNewOp<mlir::LLVM::CallIntrinsicOp>(
1837 op, mlir::Type{}, intrinNameAttr, mlir::ValueRange{begin, end});
1839 return mlir::success();
1842mlir::LogicalResult CIRToLLVMAddrOfReturnAddrOpLowering::matchAndRewrite(
1843 cir::AddrOfReturnAddrOp op, OpAdaptor adaptor,
1844 mlir::ConversionPatternRewriter &rewriter)
const {
1845 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
1847 llvmPtrTy, adaptor.getOperands());
1848 return mlir::success();
1851mlir::LogicalResult CIRToLLVMLoadOpLowering::matchAndRewrite(
1852 cir::LoadOp op, OpAdaptor adaptor,
1853 mlir::ConversionPatternRewriter &rewriter)
const {
1854 const mlir::Type llvmTy =
1856 mlir::LLVM::AtomicOrdering ordering =
getLLVMMemOrder(op.getMemOrder());
1857 std::optional<size_t> opAlign = op.getAlignment();
1858 unsigned alignment =
1859 (unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmTy));
1866 std::optional<llvm::StringRef> llvmSyncScope =
1869 mlir::LLVM::LoadOp newLoad = mlir::LLVM::LoadOp::create(
1870 rewriter, op->getLoc(), llvmTy, adaptor.getAddr(), alignment,
1871 op.getIsVolatile(),
false,
1872 false,
false, ordering,
1873 llvmSyncScope.value_or(std::string()));
1876 mlir::Value result =
1878 rewriter.replaceOp(op, result);
1880 return mlir::LogicalResult::success();
1884cir::direct::CIRToLLVMVecMaskedLoadOpLowering::matchAndRewrite(
1885 cir::VecMaskedLoadOp op, OpAdaptor adaptor,
1886 mlir::ConversionPatternRewriter &rewriter)
const {
1887 const mlir::Type llvmResTy =
1890 std::optional<size_t> opAlign = op.getAlignment();
1891 unsigned alignment =
1892 (unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmResTy));
1894 mlir::IntegerAttr alignAttr = rewriter.getI32IntegerAttr(alignment);
1896 auto newLoad = mlir::LLVM::MaskedLoadOp::create(
1897 rewriter, op.getLoc(), llvmResTy, adaptor.getAddr(), adaptor.getMask(),
1898 adaptor.getPassThru(), alignAttr);
1900 rewriter.replaceOp(op, newLoad.getResult());
1901 return mlir::success();
1904mlir::LogicalResult CIRToLLVMStoreOpLowering::matchAndRewrite(
1905 cir::StoreOp op, OpAdaptor adaptor,
1906 mlir::ConversionPatternRewriter &rewriter)
const {
1907 mlir::LLVM::AtomicOrdering memorder =
getLLVMMemOrder(op.getMemOrder());
1908 const mlir::Type llvmTy =
1909 getTypeConverter()->convertType(op.getValue().getType());
1910 std::optional<size_t> opAlign = op.getAlignment();
1911 unsigned alignment =
1912 (unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmTy));
1918 op.getValue().getType(), adaptor.getValue());
1923 std::optional<llvm::StringRef> llvmSyncScope =
1926 mlir::LLVM::StoreOp storeOp = mlir::LLVM::StoreOp::create(
1927 rewriter, op->getLoc(), value, adaptor.getAddr(), alignment,
1929 false,
false, memorder,
1930 llvmSyncScope.value_or(std::string()));
1931 rewriter.replaceOp(op, storeOp);
1933 return mlir::LogicalResult::success();
1937 auto array = mlir::dyn_cast<mlir::ArrayAttr>(attr.getElts());
1938 return attr.hasTrailingZeros() ||
1939 (array && std::count_if(array.begin(), array.end(), [](
auto elt) {
1940 auto ar = dyn_cast<cir::ConstArrayAttr>(elt);
1941 return ar && hasTrailingZeros(ar);
1945mlir::LogicalResult CIRToLLVMConstantOpLowering::matchAndRewrite(
1946 cir::ConstantOp op, OpAdaptor adaptor,
1947 mlir::ConversionPatternRewriter &rewriter)
const {
1948 mlir::Attribute attr = op.getValue();
1950 if (mlir::isa<cir::PoisonAttr>(attr)) {
1951 rewriter.replaceOpWithNewOp<mlir::LLVM::PoisonOp>(
1952 op, getTypeConverter()->convertType(op.getType()));
1953 return mlir::success();
1956 if (mlir::isa<cir::UndefAttr>(attr)) {
1957 rewriter.replaceOpWithNewOp<mlir::LLVM::UndefOp>(
1958 op, getTypeConverter()->convertType(op.getType()));
1959 return mlir::success();
1962 if (mlir::isa<mlir::IntegerType>(op.getType())) {
1967 attr = op.getValue();
1968 }
else if (mlir::isa<cir::BoolType>(op.getType())) {
1969 int value = mlir::cast<cir::BoolAttr>(op.getValue()).getValue();
1970 attr = rewriter.getIntegerAttr(typeConverter->convertType(op.getType()),
1972 }
else if (mlir::isa<cir::IntType>(op.getType())) {
1974 if (
auto ga = mlir::dyn_cast<cir::GlobalViewAttr>(op.getValue())) {
1980 op.emitError() <<
"global view with integer type";
1981 return mlir::failure();
1984 attr = rewriter.getIntegerAttr(
1985 typeConverter->convertType(op.getType()),
1986 mlir::cast<cir::IntAttr>(op.getValue()).getValue());
1987 }
else if (mlir::isa<cir::FPTypeInterface>(op.getType())) {
1988 attr = rewriter.getFloatAttr(
1989 typeConverter->convertType(op.getType()),
1990 mlir::cast<cir::FPAttr>(op.getValue()).getValue());
1991 }
else if (mlir::isa<cir::PointerType>(op.getType())) {
1993 if (mlir::isa<cir::ConstPtrAttr>(op.getValue())) {
1994 if (mlir::cast<cir::ConstPtrAttr>(op.getValue()).isNullValue()) {
1995 rewriter.replaceOpWithNewOp<mlir::LLVM::ZeroOp>(
1996 op, typeConverter->convertType(op.getType()));
1997 return mlir::success();
2001 if (
auto gv = mlir::dyn_cast<cir::GlobalViewAttr>(op.getValue())) {
2003 rewriter.replaceOp(op, newOp);
2004 return mlir::success();
2006 attr = op.getValue();
2007 }
else if (
const auto arrTy = mlir::dyn_cast<cir::ArrayType>(op.getType())) {
2008 const auto constArr = mlir::dyn_cast<cir::ConstArrayAttr>(op.getValue());
2009 if (!constArr && !isa<cir::ZeroAttr, cir::UndefAttr>(op.getValue()))
2010 return op.emitError() <<
"array does not have a constant initializer";
2012 std::optional<mlir::Attribute> denseAttr;
2014 const mlir::Value newOp =
2016 rewriter.replaceOp(op, newOp);
2017 return mlir::success();
2018 }
else if (constArr &&
2020 attr = denseAttr.value();
2022 const mlir::Value initVal =
2024 rewriter.replaceOp(op, initVal);
2025 return mlir::success();
2027 }
else if (
const auto recordAttr =
2028 mlir::dyn_cast<cir::ConstRecordAttr>(op.getValue())) {
2030 rewriter.replaceOp(op, initVal);
2031 return mlir::success();
2032 }
else if (
const auto vecTy = mlir::dyn_cast<cir::VectorType>(op.getType())) {
2034 getTypeConverter()));
2035 return mlir::success();
2036 }
else if (
auto recTy = mlir::dyn_cast<cir::RecordType>(op.getType())) {
2037 if (mlir::isa<cir::ZeroAttr, cir::UndefAttr>(attr)) {
2038 mlir::Value initVal =
2040 rewriter.replaceOp(op, initVal);
2041 return mlir::success();
2043 return op.emitError() <<
"unsupported lowering for record constant type "
2045 }
else if (
auto complexTy = mlir::dyn_cast<cir::ComplexType>(op.getType())) {
2046 mlir::Type complexElemTy = complexTy.getElementType();
2047 mlir::Type complexElemLLVMTy = typeConverter->convertType(complexElemTy);
2049 if (
auto zeroInitAttr = mlir::dyn_cast<cir::ZeroAttr>(op.getValue())) {
2050 mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(complexElemLLVMTy);
2051 mlir::ArrayAttr array = rewriter.getArrayAttr({zeroAttr, zeroAttr});
2052 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
2053 op, getTypeConverter()->convertType(op.getType()), array);
2054 return mlir::success();
2057 if (mlir::isa<cir::UndefAttr>(op.getValue())) {
2058 rewriter.replaceOpWithNewOp<mlir::LLVM::UndefOp>(
2059 op, getTypeConverter()->convertType(op.getType()));
2060 return mlir::success();
2063 auto complexAttr = mlir::cast<cir::ConstComplexAttr>(op.getValue());
2065 mlir::Attribute components[2];
2066 if (mlir::isa<cir::IntType>(complexElemTy)) {
2067 components[0] = rewriter.getIntegerAttr(
2069 mlir::cast<cir::IntAttr>(complexAttr.getReal()).getValue());
2070 components[1] = rewriter.getIntegerAttr(
2072 mlir::cast<cir::IntAttr>(complexAttr.getImag()).getValue());
2074 components[0] = rewriter.getFloatAttr(
2076 mlir::cast<cir::FPAttr>(complexAttr.getReal()).getValue());
2077 components[1] = rewriter.getFloatAttr(
2079 mlir::cast<cir::FPAttr>(complexAttr.getImag()).getValue());
2082 attr = rewriter.getArrayAttr(components);
2084 return op.emitError() <<
"unsupported constant type " << op.getType();
2087 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
2088 op, getTypeConverter()->convertType(op.getType()),
attr);
2090 return mlir::success();
2094 mlir::DataLayout layout(op.getParentOfType<mlir::ModuleOp>());
2096 if (isa<cir::VoidType>(type))
2097 type = cir::IntType::get(type.getContext(), 8,
false);
2098 return llvm::divideCeil(layout.getTypeSizeInBits(type), 8);
2101mlir::LogicalResult CIRToLLVMPrefetchOpLowering::matchAndRewrite(
2102 cir::PrefetchOp op, OpAdaptor adaptor,
2103 mlir::ConversionPatternRewriter &rewriter)
const {
2104 rewriter.replaceOpWithNewOp<mlir::LLVM::Prefetch>(
2105 op, adaptor.getAddr(), adaptor.getIsWrite(), adaptor.getLocality(),
2107 return mlir::success();
2110mlir::LogicalResult CIRToLLVMPtrDiffOpLowering::matchAndRewrite(
2111 cir::PtrDiffOp op, OpAdaptor adaptor,
2112 mlir::ConversionPatternRewriter &rewriter)
const {
2113 auto dstTy = mlir::cast<cir::IntType>(op.getType());
2114 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
2116 auto lhs = mlir::LLVM::PtrToIntOp::create(rewriter, op.getLoc(), llvmDstTy,
2118 auto rhs = mlir::LLVM::PtrToIntOp::create(rewriter, op.getLoc(), llvmDstTy,
2122 mlir::LLVM::SubOp::create(rewriter, op.getLoc(), llvmDstTy, lhs, rhs);
2124 cir::PointerType ptrTy = op.getLhs().getType();
2126 uint64_t typeSize =
getTypeSize(ptrTy.getPointee(), *op);
2129 mlir::Value resultVal = diff.getResult();
2130 if (typeSize != 1) {
2131 auto typeSizeVal = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
2132 llvmDstTy, typeSize);
2134 if (dstTy.isUnsigned()) {
2136 mlir::LLVM::UDivOp::create(rewriter, op.getLoc(), diff, typeSizeVal);
2137 uDiv.setIsExact(
true);
2138 resultVal = uDiv.getResult();
2141 mlir::LLVM::SDivOp::create(rewriter, op.getLoc(), diff, typeSizeVal);
2142 sDiv.setIsExact(
true);
2143 resultVal = sDiv.getResult();
2146 rewriter.replaceOp(op, resultVal);
2147 return mlir::success();
2150mlir::LogicalResult CIRToLLVMExpectOpLowering::matchAndRewrite(
2151 cir::ExpectOp op, OpAdaptor adaptor,
2152 mlir::ConversionPatternRewriter &rewriter)
const {
2156 std::optional<llvm::APFloat> prob = op.getProb();
2158 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpectWithProbabilityOp>(
2159 op, adaptor.getVal(), adaptor.getExpected(), prob.value());
2161 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpectOp>(op, adaptor.getVal(),
2162 adaptor.getExpected());
2163 return mlir::success();
2166mlir::LogicalResult CIRToLLVMAbsOpLowering::matchAndRewrite(
2167 cir::AbsOp op, OpAdaptor adaptor,
2168 mlir::ConversionPatternRewriter &rewriter)
const {
2169 mlir::Type resTy = typeConverter->convertType(op.getType());
2170 auto absOp = mlir::LLVM::AbsOp::create(rewriter, op.getLoc(), resTy,
2171 adaptor.getOperands()[0],
2172 adaptor.getMinIsPoison());
2173 rewriter.replaceOp(op, absOp);
2174 return mlir::success();
2181void CIRToLLVMFuncOpLowering::lowerFuncAttributes(
2182 cir::FuncOp func,
bool filterArgAndResAttrs,
2183 SmallVectorImpl<mlir::NamedAttribute> &result)
const {
2184 for (mlir::NamedAttribute attr : func->getAttrs()) {
2185 if (
attr.getName() == mlir::SymbolTable::getSymbolAttrName() ||
2186 attr.getName() == func.getFunctionTypeAttrName() ||
2188 attr.getName() == func.getCallingConvAttrName() ||
2189 attr.getName() == func.getDsoLocalAttrName() ||
2190 attr.getName() == func.getInlineKindAttrName() ||
2191 attr.getName() == func.getSideEffectAttrName() ||
2192 attr.getName() == CIRDialect::getNoReturnAttrName() ||
2193 attr.getName() == func.getAnnotationsAttrName() ||
2194 (filterArgAndResAttrs &&
2195 (
attr.getName() == func.getArgAttrsAttrName() ||
2196 attr.getName() == func.getResAttrsAttrName())))
2200 result.push_back(attr);
2204mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewriteAlias(
2205 cir::FuncOp op, llvm::StringRef aliasee, mlir::Type ty, OpAdaptor adaptor,
2206 mlir::ConversionPatternRewriter &rewriter)
const {
2207 SmallVector<mlir::NamedAttribute, 4> attributes;
2208 lowerFuncAttributes(op,
false, attributes);
2210 mlir::Location loc = op.getLoc();
2211 auto aliasOp = rewriter.replaceOpWithNewOp<mlir::LLVM::AliasOp>(
2212 op, ty,
convertLinkage(op.getLinkage()), op.getName(), op.getDsoLocal(),
2216 mlir::OpBuilder builder(op.getContext());
2217 mlir::Block *block = builder.createBlock(&aliasOp.getInitializerRegion());
2218 builder.setInsertionPointToStart(block);
2221 mlir::Type ptrTy = mlir::LLVM::LLVMPointerType::get(ty.getContext());
2222 auto addrOp = mlir::LLVM::AddressOfOp::create(builder, loc, ptrTy, aliasee);
2223 mlir::LLVM::ReturnOp::create(builder, loc, addrOp);
2225 return mlir::success();
2228mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewrite(
2229 cir::FuncOp op, OpAdaptor adaptor,
2230 mlir::ConversionPatternRewriter &rewriter)
const {
2232 cir::FuncType fnType = op.getFunctionType();
2233 bool isDsoLocal = op.getDsoLocal();
2234 mlir::TypeConverter::SignatureConversion signatureConversion(
2235 fnType.getNumInputs());
2237 for (
const auto &argType : llvm::enumerate(fnType.getInputs())) {
2238 mlir::Type convertedType = typeConverter->convertType(argType.value());
2240 return mlir::failure();
2241 signatureConversion.addInputs(argType.index(), convertedType);
2244 mlir::Type resultType =
2245 getTypeConverter()->convertType(fnType.getReturnType());
2248 mlir::Type llvmFnTy = mlir::LLVM::LLVMFunctionType::get(
2249 resultType ? resultType : mlir::LLVM::LLVMVoidType::get(getContext()),
2250 signatureConversion.getConvertedTypes(),
2254 if (std::optional<llvm::StringRef> aliasee = op.getAliasee())
2255 return matchAndRewriteAlias(op, *aliasee, llvmFnTy, adaptor, rewriter);
2259 mlir::Location loc = op.getLoc();
2260 if (mlir::FusedLoc fusedLoc = mlir::dyn_cast<mlir::FusedLoc>(loc))
2261 loc = fusedLoc.getLocations()[0];
2262 assert((mlir::isa<mlir::FileLineColLoc>(loc) ||
2263 mlir::isa<mlir::UnknownLoc>(loc)) &&
2264 "expected single location or unknown location here");
2268 SmallVector<mlir::NamedAttribute, 4> attributes;
2269 lowerFuncAttributes(op,
false, attributes);
2271 mlir::LLVM::LLVMFuncOp fn = mlir::LLVM::LLVMFuncOp::create(
2272 rewriter, loc, op.getName(), llvmFnTy, linkage, isDsoLocal, cconv,
2273 mlir::SymbolRefAttr(), attributes);
2277 if (std::optional<cir::SideEffect> sideEffectKind = op.getSideEffect()) {
2278 switch (*sideEffectKind) {
2279 case cir::SideEffect::All:
2281 case cir::SideEffect::Pure:
2282 fn.setMemoryEffectsAttr(mlir::LLVM::MemoryEffectsAttr::get(
2284 mlir::LLVM::ModRefInfo::Ref,
2285 mlir::LLVM::ModRefInfo::Ref,
2286 mlir::LLVM::ModRefInfo::Ref,
2287 mlir::LLVM::ModRefInfo::Ref,
2288 mlir::LLVM::ModRefInfo::Ref,
2289 mlir::LLVM::ModRefInfo::Ref));
2290 fn.setNoUnwind(
true);
2291 fn.setWillReturn(
true);
2293 case cir::SideEffect::Const:
2294 fn.setMemoryEffectsAttr(mlir::LLVM::MemoryEffectsAttr::get(
2296 mlir::LLVM::ModRefInfo::NoModRef,
2297 mlir::LLVM::ModRefInfo::NoModRef,
2298 mlir::LLVM::ModRefInfo::NoModRef,
2299 mlir::LLVM::ModRefInfo::NoModRef,
2300 mlir::LLVM::ModRefInfo::NoModRef,
2301 mlir::LLVM::ModRefInfo::NoModRef));
2302 fn.setNoUnwind(
true);
2303 fn.setWillReturn(
true);
2308 if (op->hasAttr(CIRDialect::getNoReturnAttrName()))
2309 fn.setNoreturn(
true);
2311 if (std::optional<cir::InlineKind> inlineKind = op.getInlineKind()) {
2312 fn.setNoInline(*inlineKind == cir::InlineKind::NoInline);
2313 fn.setInlineHint(*inlineKind == cir::InlineKind::InlineHint);
2314 fn.setAlwaysInline(*inlineKind == cir::InlineKind::AlwaysInline);
2317 if (std::optional<llvm::StringRef> personality = op.getPersonality())
2318 fn.setPersonality(*personality);
2323 rewriter.inlineRegionBefore(op.getBody(), fn.getBody(), fn.end());
2324 if (failed(rewriter.convertRegionTypes(&fn.getBody(), *typeConverter,
2325 &signatureConversion)))
2326 return mlir::failure();
2328 rewriter.eraseOp(op);
2330 return mlir::LogicalResult::success();
2333mlir::LogicalResult CIRToLLVMGetGlobalOpLowering::matchAndRewrite(
2334 cir::GetGlobalOp op, OpAdaptor adaptor,
2335 mlir::ConversionPatternRewriter &rewriter)
const {
2338 if (op->getUses().empty()) {
2339 rewriter.eraseOp(op);
2340 return mlir::success();
2343 mlir::Type
type = getTypeConverter()->convertType(op.getType());
2344 mlir::Operation *newop = mlir::LLVM::AddressOfOp::create(
2345 rewriter, op.getLoc(), type, op.getName());
2349 newop = mlir::LLVM::ThreadlocalAddressOp::create(rewriter, op.getLoc(),
2350 type, newop->getResult(0));
2353 rewriter.replaceOp(op, newop);
2354 return mlir::success();
2357llvm::SmallVector<mlir::NamedAttribute>
2358CIRToLLVMGlobalOpLowering::lowerGlobalAttributes(
2359 cir::GlobalOp op, mlir::ConversionPatternRewriter &rewriter)
const {
2360 SmallVector<mlir::NamedAttribute> attributes;
2362 if (mlir::StringAttr sectionAttr = op.getSectionAttr())
2363 attributes.push_back(rewriter.getNamedAttr(
"section", sectionAttr));
2365 mlir::LLVM::VisibilityAttr visibility = mlir::LLVM::VisibilityAttr::get(
2368 attributes.push_back(rewriter.getNamedAttr(
"visibility_", visibility));
2370 if (op->getAttr(CUDAExternallyInitializedAttr::getMnemonic()))
2371 attributes.push_back(rewriter.getNamedAttr(
"externally_initialized",
2372 rewriter.getUnitAttr()));
2379void CIRToLLVMGlobalOpLowering::setupRegionInitializedLLVMGlobalOp(
2380 cir::GlobalOp op, mlir::ConversionPatternRewriter &rewriter)
const {
2381 const mlir::Type llvmType =
2388 const bool isConst = op.getConstant();
2389 unsigned addrSpace = 0;
2390 if (
auto targetAS = mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
2391 op.getAddrSpaceAttr()))
2392 addrSpace = targetAS.getValue();
2393 const bool isDsoLocal = op.getDsoLocal();
2394 const bool isThreadLocal = (
bool)op.getTlsModelAttr();
2395 const uint64_t alignment = op.getAlignment().value_or(0);
2396 const mlir::LLVM::Linkage linkage =
convertLinkage(op.getLinkage());
2397 const StringRef symbol = op.getSymName();
2398 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
2400 SmallVector<mlir::NamedAttribute> attributes =
2401 lowerGlobalAttributes(op, rewriter);
2403 mlir::LLVM::GlobalOp newGlobalOp =
2404 rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
2405 op, llvmType, isConst, linkage, symbol,
nullptr, alignment, addrSpace,
2406 isDsoLocal, isThreadLocal, comdatAttr, attributes);
2407 newGlobalOp.getRegion().emplaceBlock();
2408 rewriter.setInsertionPointToEnd(newGlobalOp.getInitializerBlock());
2412CIRToLLVMGlobalOpLowering::matchAndRewriteRegionInitializedGlobal(
2413 cir::GlobalOp op, mlir::Attribute init,
2414 mlir::ConversionPatternRewriter &rewriter)
const {
2416 assert((isa<cir::ConstArrayAttr, cir::ConstRecordAttr, cir::ConstVectorAttr,
2417 cir::ConstPtrAttr, cir::ConstComplexAttr, cir::GlobalViewAttr,
2418 cir::TypeInfoAttr, cir::UndefAttr, cir::PoisonAttr,
2419 cir::VTableAttr, cir::ZeroAttr>(init)));
2424 const mlir::Location loc = op.getLoc();
2425 setupRegionInitializedLLVMGlobalOp(op, rewriter);
2427 mlir::Value value = valueConverter.visit(init);
2428 mlir::LLVM::ReturnOp::create(rewriter, loc, value);
2429 return mlir::success();
2432mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite(
2433 cir::GlobalOp op, OpAdaptor adaptor,
2434 mlir::ConversionPatternRewriter &rewriter)
const {
2437 if (!op.getCtorRegion().empty() || !op.getDtorRegion().empty())
2438 return op.emitError() <<
"GlobalOp ctor and dtor regions should be removed "
2439 "in LoweringPrepare";
2441 std::optional<mlir::Attribute> init = op.getInitialValue();
2444 const mlir::Type cirSymType = op.getSymType();
2447 const mlir::Type llvmType =
2452 const bool isConst = op.getConstant();
2453 unsigned addrSpace = 0;
2454 if (
auto targetAS = mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
2455 op.getAddrSpaceAttr()))
2456 addrSpace = targetAS.getValue();
2457 const bool isDsoLocal = op.getDsoLocal();
2458 const bool isThreadLocal = (
bool)op.getTlsModelAttr();
2459 const uint64_t alignment = op.getAlignment().value_or(0);
2460 const mlir::LLVM::Linkage linkage =
convertLinkage(op.getLinkage());
2461 const StringRef symbol = op.getSymName();
2462 SmallVector<mlir::NamedAttribute> attributes =
2463 lowerGlobalAttributes(op, rewriter);
2466 if (std::optional<llvm::StringRef> aliasee = op.getAliasee()) {
2467 mlir::Location loc = op.getLoc();
2468 auto aliasOp = rewriter.replaceOpWithNewOp<mlir::LLVM::AliasOp>(
2469 op, llvmType, linkage, symbol, isDsoLocal, isThreadLocal, attributes);
2471 mlir::OpBuilder builder(op.getContext());
2472 mlir::Block *block = builder.createBlock(&aliasOp.getInitializerRegion());
2473 builder.setInsertionPointToStart(block);
2475 mlir::LLVM::LLVMPointerType::get(getContext(), addrSpace);
2477 mlir::LLVM::AddressOfOp::create(builder, loc, ptrTy, *aliasee);
2478 mlir::LLVM::ReturnOp::create(builder, loc, addrOp);
2479 return mlir::success();
2482 if (init.has_value()) {
2483 if (mlir::isa<cir::FPAttr, cir::IntAttr, cir::BoolAttr>(init.value())) {
2485 init = initRewriter.visit(init.value());
2490 if (!init.value()) {
2491 op.emitError() <<
"unsupported initializer '" << init.value() <<
"'";
2492 return mlir::failure();
2494 }
else if (mlir::isa<cir::ConstArrayAttr, cir::ConstVectorAttr,
2495 cir::ConstRecordAttr, cir::ConstPtrAttr,
2496 cir::ConstComplexAttr, cir::GlobalViewAttr,
2497 cir::TypeInfoAttr, cir::UndefAttr, cir::PoisonAttr,
2498 cir::VTableAttr, cir::ZeroAttr>(init.value())) {
2502 return matchAndRewriteRegionInitializedGlobal(op, init.value(), rewriter);
2506 op.emitError() <<
"unsupported initializer '" << init.value() <<
"'";
2507 return mlir::failure();
2511 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
2512 rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
2513 op, llvmType, isConst, linkage, symbol, init.value_or(mlir::Attribute()),
2514 alignment, addrSpace, isDsoLocal, isThreadLocal, comdatAttr, attributes);
2516 return mlir::success();
2520CIRToLLVMGlobalOpLowering::getComdatAttr(cir::GlobalOp &op,
2521 mlir::OpBuilder &builder)
const {
2522 if (!op.getComdat())
2523 return mlir::SymbolRefAttr{};
2525 mlir::ModuleOp module = op->getParentOfType<mlir::ModuleOp>();
2526 mlir::OpBuilder::InsertionGuard guard(builder);
2527 StringRef comdatName(
"__llvm_comdat_globals");
2529 builder.setInsertionPointToStart(module.getBody());
2531 mlir::LLVM::ComdatOp::create(builder, module.getLoc(), comdatName);
2534 if (
auto comdatSelector = comdatOp.lookupSymbol<mlir::LLVM::ComdatSelectorOp>(
2536 return mlir::SymbolRefAttr::get(
2537 builder.getContext(), comdatName,
2538 mlir::FlatSymbolRefAttr::get(comdatSelector.getSymNameAttr()));
2541 builder.setInsertionPointToStart(&comdatOp.getBody().back());
2542 auto selectorOp = mlir::LLVM::ComdatSelectorOp::create(
2543 builder, comdatOp.getLoc(), op.getSymName(),
2544 mlir::LLVM::comdat::Comdat::Any);
2545 return mlir::SymbolRefAttr::get(
2546 builder.getContext(), comdatName,
2547 mlir::FlatSymbolRefAttr::get(selectorOp.getSymNameAttr()));
2550mlir::LogicalResult CIRToLLVMSwitchFlatOpLowering::matchAndRewrite(
2551 cir::SwitchFlatOp op, OpAdaptor adaptor,
2552 mlir::ConversionPatternRewriter &rewriter)
const {
2554 llvm::SmallVector<mlir::APInt, 8> caseValues;
2555 for (mlir::Attribute val : op.getCaseValues()) {
2556 auto intAttr = cast<cir::IntAttr>(val);
2557 caseValues.push_back(intAttr.getValue());
2560 llvm::SmallVector<mlir::Block *, 8> caseDestinations;
2561 llvm::SmallVector<mlir::ValueRange, 8> caseOperands;
2563 for (mlir::Block *x : op.getCaseDestinations())
2564 caseDestinations.push_back(x);
2566 for (mlir::OperandRange x : op.getCaseOperands())
2567 caseOperands.push_back(x);
2570 rewriter.setInsertionPoint(op);
2571 rewriter.replaceOpWithNewOp<mlir::LLVM::SwitchOp>(
2572 op, adaptor.getCondition(), op.getDefaultDestination(),
2573 op.getDefaultOperands(), caseValues, caseDestinations, caseOperands);
2574 return mlir::success();
2577static mlir::LLVM::IntegerOverflowFlags
nswFlag(
bool nsw) {
2578 return nsw ? mlir::LLVM::IntegerOverflowFlags::nsw
2579 : mlir::LLVM::IntegerOverflowFlags::none;
2582template <
typename CIROp,
typename LLVMIntOp>
2583static mlir::LogicalResult
2585 mlir::ConversionPatternRewriter &rewriter,
double fpConstant) {
2586 mlir::Type elementType = elementTypeIfVector(op.getType());
2587 mlir::Type llvmType = adaptor.getInput().getType();
2588 mlir::Location loc = op.getLoc();
2590 if (mlir::isa<cir::IntType>(elementType)) {
2591 auto maybeNSW =
nswFlag(op.getNoSignedWrap());
2592 auto one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
2593 rewriter.replaceOpWithNewOp<LLVMIntOp>(op, adaptor.getInput(), one,
2595 return mlir::success();
2597 if (mlir::isa<cir::FPTypeInterface>(elementType)) {
2598 auto fpConst = mlir::LLVM::ConstantOp::create(
2599 rewriter, loc, rewriter.getFloatAttr(llvmType, fpConstant));
2600 rewriter.replaceOpWithNewOp<mlir::LLVM::FAddOp>(op, fpConst,
2601 adaptor.getInput());
2602 return mlir::success();
2604 return op.emitError() <<
"Unsupported type for IncOp/DecOp";
2607mlir::LogicalResult CIRToLLVMIncOpLowering::matchAndRewrite(
2608 cir::IncOp op, OpAdaptor adaptor,
2609 mlir::ConversionPatternRewriter &rewriter)
const {
2614mlir::LogicalResult CIRToLLVMDecOpLowering::matchAndRewrite(
2615 cir::DecOp op, OpAdaptor adaptor,
2616 mlir::ConversionPatternRewriter &rewriter)
const {
2621mlir::LogicalResult CIRToLLVMMinusOpLowering::matchAndRewrite(
2622 cir::MinusOp op, OpAdaptor adaptor,
2623 mlir::ConversionPatternRewriter &rewriter)
const {
2624 mlir::Type elementType = elementTypeIfVector(op.getType());
2625 bool isVector = mlir::isa<cir::VectorType>(op.getType());
2626 mlir::Type llvmType = adaptor.getInput().getType();
2627 mlir::Location loc = op.getLoc();
2629 if (mlir::isa<cir::IntType>(elementType)) {
2630 auto maybeNSW =
nswFlag(op.getNoSignedWrap());
2633 zero = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmType);
2635 zero = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 0);
2636 rewriter.replaceOpWithNewOp<mlir::LLVM::SubOp>(op, zero, adaptor.getInput(),
2638 return mlir::success();
2640 if (mlir::isa<cir::FPTypeInterface>(elementType)) {
2641 rewriter.replaceOpWithNewOp<mlir::LLVM::FNegOp>(op, adaptor.getInput());
2642 return mlir::success();
2644 return op.emitError() <<
"Unsupported type for unary minus";
2647mlir::LogicalResult CIRToLLVMNotOpLowering::matchAndRewrite(
2648 cir::NotOp op, OpAdaptor adaptor,
2649 mlir::ConversionPatternRewriter &rewriter)
const {
2650 mlir::Type elementType = elementTypeIfVector(op.getType());
2651 bool isVector = mlir::isa<cir::VectorType>(op.getType());
2652 mlir::Type llvmType = adaptor.getInput().getType();
2653 mlir::Location loc = op.getLoc();
2655 if (mlir::isa<cir::IntType>(elementType)) {
2656 mlir::Value minusOne;
2659 mlir::dyn_cast<cir::VectorType>(op.getType()).getSize();
2660 SmallVector<int32_t> values(numElements, -1);
2661 mlir::DenseIntElementsAttr denseVec = rewriter.getI32VectorAttr(values);
2663 mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, denseVec);
2665 minusOne = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, -1);
2667 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getInput(),
2669 return mlir::success();
2671 if (mlir::isa<cir::BoolType>(elementType)) {
2672 auto one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
2673 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getInput(), one);
2674 return mlir::success();
2676 return op.emitError() <<
"Unsupported type for bitwise NOT";
2681 return mlir::isa<cir::IntType>(type)
2682 ? mlir::cast<cir::IntType>(type).isUnsigned()
2683 : mlir::cast<mlir::IntegerType>(type).isUnsigned();
2690template <
typename BinOp>
2692 if (op.getNoUnsignedWrap())
2693 return mlir::LLVM::IntegerOverflowFlags::nuw;
2694 if (op.getNoSignedWrap())
2695 return mlir::LLVM::IntegerOverflowFlags::nsw;
2696 return mlir::LLVM::IntegerOverflowFlags::none;
2701template <
typename UIntSatOp,
typename SIntSatOp,
typename IntOp,
typename FPOp,
2703static mlir::LogicalResult
2705 mlir::ConversionPatternRewriter &rewriter) {
2706 const mlir::Type eltType = elementTypeIfVector(op.getRhs().getType());
2707 if (cir::isIntOrBoolType(eltType)) {
2708 if (op.getSaturated()) {
2710 rewriter.replaceOpWithNewOp<UIntSatOp>(op, lhs, rhs);
2712 rewriter.replaceOpWithNewOp<SIntSatOp>(op, lhs, rhs);
2713 return mlir::success();
2715 rewriter.replaceOpWithNewOp<IntOp>(op, lhs, rhs,
intOverflowFlag(op));
2717 rewriter.replaceOpWithNewOp<FPOp>(op, lhs, rhs);
2719 return mlir::success();
2722mlir::LogicalResult CIRToLLVMAddOpLowering::matchAndRewrite(
2723 cir::AddOp op, OpAdaptor adaptor,
2724 mlir::ConversionPatternRewriter &rewriter)
const {
2726 mlir::LLVM::AddOp, mlir::LLVM::FAddOp>(
2727 op, adaptor.getLhs(), adaptor.getRhs(), rewriter);
2730mlir::LogicalResult CIRToLLVMSubOpLowering::matchAndRewrite(
2731 cir::SubOp op, OpAdaptor adaptor,
2732 mlir::ConversionPatternRewriter &rewriter)
const {
2734 mlir::LLVM::SubOp, mlir::LLVM::FSubOp>(
2735 op, adaptor.getLhs(), adaptor.getRhs(), rewriter);
2738mlir::LogicalResult CIRToLLVMMulOpLowering::matchAndRewrite(
2739 cir::MulOp op, OpAdaptor adaptor,
2740 mlir::ConversionPatternRewriter &rewriter)
const {
2741 const mlir::Value lhs = adaptor.getLhs();
2742 const mlir::Value rhs = adaptor.getRhs();
2743 if (cir::isIntOrBoolType(elementTypeIfVector(op.getRhs().getType()))) {
2744 rewriter.replaceOpWithNewOp<mlir::LLVM::MulOp>(op, lhs, rhs,
2747 rewriter.replaceOpWithNewOp<mlir::LLVM::FMulOp>(op, lhs, rhs);
2749 return mlir::success();
2754template <
typename UIntOp,
typename SIntOp,
typename FPOp,
typename CIROp>
2755static mlir::LogicalResult
2757 mlir::ConversionPatternRewriter &rewriter) {
2758 const mlir::Type eltType = elementTypeIfVector(op.getRhs().getType());
2759 if (cir::isIntOrBoolType(eltType)) {
2761 rewriter.replaceOpWithNewOp<UIntOp>(op, lhs, rhs);
2763 rewriter.replaceOpWithNewOp<SIntOp>(op, lhs, rhs);
2765 rewriter.replaceOpWithNewOp<FPOp>(op, lhs, rhs);
2767 return mlir::success();
2770mlir::LogicalResult CIRToLLVMDivOpLowering::matchAndRewrite(
2771 cir::DivOp op, OpAdaptor adaptor,
2772 mlir::ConversionPatternRewriter &rewriter)
const {
2774 mlir::LLVM::FDivOp>(op, adaptor.getLhs(),
2775 adaptor.getRhs(), rewriter);
2778mlir::LogicalResult CIRToLLVMRemOpLowering::matchAndRewrite(
2779 cir::RemOp op, OpAdaptor adaptor,
2780 mlir::ConversionPatternRewriter &rewriter)
const {
2782 mlir::LLVM::FRemOp>(op, adaptor.getLhs(),
2783 adaptor.getRhs(), rewriter);
2786mlir::LogicalResult CIRToLLVMAndOpLowering::matchAndRewrite(
2787 cir::AndOp op, OpAdaptor adaptor,
2788 mlir::ConversionPatternRewriter &rewriter)
const {
2789 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(op, adaptor.getLhs(),
2791 return mlir::success();
2794mlir::LogicalResult CIRToLLVMOrOpLowering::matchAndRewrite(
2795 cir::OrOp op, OpAdaptor adaptor,
2796 mlir::ConversionPatternRewriter &rewriter)
const {
2797 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(op, adaptor.getLhs(),
2799 return mlir::success();
2802mlir::LogicalResult CIRToLLVMXorOpLowering::matchAndRewrite(
2803 cir::XorOp op, OpAdaptor adaptor,
2804 mlir::ConversionPatternRewriter &rewriter)
const {
2805 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getLhs(),
2807 return mlir::success();
2810template <
typename CIROp,
typename UIntOp,
typename SIntOp>
2811static mlir::LogicalResult
2813 mlir::ConversionPatternRewriter &rewriter) {
2814 const mlir::Value lhs = adaptor.getLhs();
2815 const mlir::Value rhs = adaptor.getRhs();
2817 rewriter.replaceOpWithNewOp<UIntOp>(op, lhs, rhs);
2819 rewriter.replaceOpWithNewOp<SIntOp>(op, lhs, rhs);
2820 return mlir::success();
2823mlir::LogicalResult CIRToLLVMMaxOpLowering::matchAndRewrite(
2824 cir::MaxOp op, OpAdaptor adaptor,
2825 mlir::ConversionPatternRewriter &rewriter)
const {
2827 op, adaptor, rewriter);
2830mlir::LogicalResult CIRToLLVMMinOpLowering::matchAndRewrite(
2831 cir::MinOp op, OpAdaptor adaptor,
2832 mlir::ConversionPatternRewriter &rewriter)
const {
2834 op, adaptor, rewriter);
2838static mlir::LLVM::ICmpPredicate
2840 using CIR = cir::CmpOpKind;
2841 using LLVMICmp = mlir::LLVM::ICmpPredicate;
2844 return LLVMICmp::eq;
2846 return LLVMICmp::ne;
2848 return (isSigned ? LLVMICmp::slt : LLVMICmp::ult);
2850 return (isSigned ? LLVMICmp::sle : LLVMICmp::ule);
2852 return (isSigned ? LLVMICmp::sgt : LLVMICmp::ugt);
2854 return (isSigned ? LLVMICmp::sge : LLVMICmp::uge);
2857 llvm_unreachable(
"FP-only comparison used with integer type");
2859 llvm_unreachable(
"Unknown CmpOpKind");
2864static mlir::LLVM::FCmpPredicate
2866 using CIR = cir::CmpOpKind;
2867 using LLVMFCmp = mlir::LLVM::FCmpPredicate;
2870 return LLVMFCmp::oeq;
2872 return LLVMFCmp::une;
2874 return LLVMFCmp::olt;
2876 return LLVMFCmp::ole;
2878 return LLVMFCmp::ogt;
2880 return LLVMFCmp::oge;
2882 return LLVMFCmp::one;
2884 return LLVMFCmp::uno;
2886 llvm_unreachable(
"Unknown CmpOpKind");
2889mlir::LogicalResult CIRToLLVMCmpOpLowering::matchAndRewrite(
2890 cir::CmpOp cmpOp, OpAdaptor adaptor,
2891 mlir::ConversionPatternRewriter &rewriter)
const {
2892 mlir::Type type = cmpOp.getLhs().getType();
2894 if (mlir::isa<cir::IntType, mlir::IntegerType>(type)) {
2895 bool isSigned = mlir::isa<cir::IntType>(type)
2896 ? mlir::cast<cir::IntType>(type).isSigned()
2897 : mlir::cast<mlir::IntegerType>(type).isSigned();
2898 mlir::LLVM::ICmpPredicate
kind =
2900 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
2901 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
2902 return mlir::success();
2905 if (
auto ptrTy = mlir::dyn_cast<cir::PointerType>(type)) {
2906 mlir::LLVM::ICmpPredicate
kind =
2909 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
2910 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
2911 return mlir::success();
2914 if (
auto vptrTy = mlir::dyn_cast<cir::VPtrType>(type)) {
2918 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
2919 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
2920 return mlir::success();
2923 if (mlir::isa<cir::FPTypeInterface>(type)) {
2924 mlir::LLVM::FCmpPredicate
kind =
2926 rewriter.replaceOpWithNewOp<mlir::LLVM::FCmpOp>(
2927 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
2928 return mlir::success();
2931 if (mlir::isa<cir::ComplexType>(type)) {
2932 mlir::Value lhs = adaptor.getLhs();
2933 mlir::Value rhs = adaptor.getRhs();
2934 mlir::Location loc = cmpOp.getLoc();
2936 auto complexType = mlir::cast<cir::ComplexType>(cmpOp.getLhs().getType());
2937 mlir::Type complexElemTy =
2938 getTypeConverter()->convertType(
complexType.getElementType());
2940 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
2941 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{0}));
2942 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
2943 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{1}));
2944 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
2945 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{0}));
2946 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
2947 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{1}));
2949 if (cmpOp.getKind() == cir::CmpOpKind::eq) {
2950 if (complexElemTy.isInteger()) {
2951 auto realCmp = mlir::LLVM::ICmpOp::create(
2952 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, lhsReal, rhsReal);
2953 auto imagCmp = mlir::LLVM::ICmpOp::create(
2954 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, lhsImag, rhsImag);
2955 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, imagCmp);
2956 return mlir::success();
2959 auto realCmp = mlir::LLVM::FCmpOp::create(
2960 rewriter, loc, mlir::LLVM::FCmpPredicate::oeq, lhsReal, rhsReal);
2961 auto imagCmp = mlir::LLVM::FCmpOp::create(
2962 rewriter, loc, mlir::LLVM::FCmpPredicate::oeq, lhsImag, rhsImag);
2963 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, imagCmp);
2964 return mlir::success();
2967 if (cmpOp.getKind() == cir::CmpOpKind::ne) {
2968 if (complexElemTy.isInteger()) {
2969 auto realCmp = mlir::LLVM::ICmpOp::create(
2970 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, lhsReal, rhsReal);
2971 auto imagCmp = mlir::LLVM::ICmpOp::create(
2972 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, lhsImag, rhsImag);
2973 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp);
2974 return mlir::success();
2977 auto realCmp = mlir::LLVM::FCmpOp::create(
2978 rewriter, loc, mlir::LLVM::FCmpPredicate::une, lhsReal, rhsReal);
2979 auto imagCmp = mlir::LLVM::FCmpOp::create(
2980 rewriter, loc, mlir::LLVM::FCmpPredicate::une, lhsImag, rhsImag);
2981 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp);
2982 return mlir::success();
2986 return cmpOp.emitError() <<
"unsupported type for CmpOp: " <<
type;
2992template <
typename OpTy>
2993static mlir::LogicalResult
2995 mlir::ConversionPatternRewriter &rewriter,
2996 const mlir::TypeConverter *typeConverter,
2997 llvm::StringRef opStr) {
2998 mlir::Location loc = op.getLoc();
2999 cir::IntType operandTy = op.getLhs().getType();
3000 cir::IntType resultTy = op.getResult().getType();
3002 bool sign = operandTy.getIsSigned() || resultTy.getIsSigned();
3004 std::max(operandTy.getWidth() + (
sign && operandTy.isUnsigned()),
3005 resultTy.getWidth() + (
sign && resultTy.isUnsigned()));
3007 mlir::IntegerType encompassedLLVMTy = rewriter.getIntegerType(width);
3009 mlir::Value lhs = adaptor.getLhs();
3010 mlir::Value rhs = adaptor.getRhs();
3011 if (operandTy.getWidth() < width) {
3012 if (operandTy.isSigned()) {
3013 lhs = mlir::LLVM::SExtOp::create(rewriter, loc, encompassedLLVMTy, lhs);
3014 rhs = mlir::LLVM::SExtOp::create(rewriter, loc, encompassedLLVMTy, rhs);
3016 lhs = mlir::LLVM::ZExtOp::create(rewriter, loc, encompassedLLVMTy, lhs);
3017 rhs = mlir::LLVM::ZExtOp::create(rewriter, loc, encompassedLLVMTy, rhs);
3022 std::string intrinName = (
"llvm." + llvm::Twine(
sign ?
's' :
'u') + opStr +
3023 ".with.overflow.i" + llvm::Twine(width))
3025 auto intrinNameAttr = mlir::StringAttr::get(op.getContext(), intrinName);
3027 mlir::IntegerType overflowLLVMTy = rewriter.getI1Type();
3028 auto intrinRetTy = mlir::LLVM::LLVMStructType::getLiteral(
3029 rewriter.getContext(), {encompassedLLVMTy, overflowLLVMTy});
3031 auto callLLVMIntrinOp = mlir::LLVM::CallIntrinsicOp::create(
3032 rewriter, loc, intrinRetTy, intrinNameAttr, mlir::ValueRange{lhs, rhs});
3033 mlir::Value intrinRet = callLLVMIntrinOp.getResult(0);
3035 mlir::Value result = mlir::LLVM::ExtractValueOp::create(
3038 mlir::Value overflow = mlir::LLVM::ExtractValueOp::create(
3042 if (resultTy.getWidth() < width) {
3043 mlir::Type resultLLVMTy = typeConverter->convertType(resultTy);
3045 mlir::LLVM::TruncOp::create(rewriter, loc, resultLLVMTy, result);
3049 mlir::Value truncResultExt;
3050 if (resultTy.isSigned())
3051 truncResultExt = mlir::LLVM::SExtOp::create(
3052 rewriter, loc, encompassedLLVMTy, truncResult);
3054 truncResultExt = mlir::LLVM::ZExtOp::create(
3055 rewriter, loc, encompassedLLVMTy, truncResult);
3056 auto truncOverflow = mlir::LLVM::ICmpOp::create(
3057 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, truncResultExt, result);
3059 result = truncResult;
3060 overflow = mlir::LLVM::OrOp::create(rewriter, loc, overflow, truncOverflow);
3063 mlir::Type boolLLVMTy =
3064 typeConverter->convertType(op.getOverflow().getType());
3065 if (boolLLVMTy != rewriter.getI1Type())
3066 overflow = mlir::LLVM::ZExtOp::create(rewriter, loc, boolLLVMTy, overflow);
3068 rewriter.replaceOp(op, mlir::ValueRange{result, overflow});
3070 return mlir::success();
3073mlir::LogicalResult CIRToLLVMAddOverflowOpLowering::matchAndRewrite(
3074 cir::AddOverflowOp op, OpAdaptor adaptor,
3075 mlir::ConversionPatternRewriter &rewriter)
const {
3079mlir::LogicalResult CIRToLLVMSubOverflowOpLowering::matchAndRewrite(
3080 cir::SubOverflowOp op, OpAdaptor adaptor,
3081 mlir::ConversionPatternRewriter &rewriter)
const {
3085mlir::LogicalResult CIRToLLVMMulOverflowOpLowering::matchAndRewrite(
3086 cir::MulOverflowOp op, OpAdaptor adaptor,
3087 mlir::ConversionPatternRewriter &rewriter)
const {
3091mlir::LogicalResult CIRToLLVMFrexpOpLowering::matchAndRewrite(
3092 cir::FrexpOp op, OpAdaptor adaptor,
3093 mlir::ConversionPatternRewriter &rewriter)
const {
3094 mlir::Location loc = op.getLoc();
3095 mlir::Type fpLLVMTy =
3096 getTypeConverter()->convertType(op.getResult().getType());
3097 mlir::Type intLLVMTy = getTypeConverter()->convertType(op.getExp().getType());
3099 auto structTy = mlir::LLVM::LLVMStructType::getLiteral(rewriter.getContext(),
3100 {fpLLVMTy, intLLVMTy});
3104 mlir::Value result = callOp.getResult(0);
3106 mlir::Value mantissa =
3107 mlir::LLVM::ExtractValueOp::create(rewriter, loc, result, 0);
3108 mlir::Value exponent =
3109 mlir::LLVM::ExtractValueOp::create(rewriter, loc, result, 1);
3110 rewriter.replaceOp(op, mlir::ValueRange{mantissa, exponent});
3111 return mlir::success();
3114mlir::LogicalResult CIRToLLVMModfOpLowering::matchAndRewrite(
3115 cir::ModfOp op, OpAdaptor adaptor,
3116 mlir::ConversionPatternRewriter &rewriter)
const {
3117 mlir::Location loc = op.getLoc();
3118 mlir::Type fpLLVMTy =
3119 getTypeConverter()->convertType(op.getFractional().getType());
3121 auto structTy = mlir::LLVM::LLVMStructType::getLiteral(rewriter.getContext(),
3122 {fpLLVMTy, fpLLVMTy});
3126 mlir::Value result = callOp.getResult(0);
3128 mlir::Value fractional =
3129 mlir::LLVM::ExtractValueOp::create(rewriter, loc, result, 0);
3130 mlir::Value integral =
3131 mlir::LLVM::ExtractValueOp::create(rewriter, loc, result, 1);
3132 rewriter.replaceOp(op, mlir::ValueRange{fractional, integral});
3133 return mlir::success();
3136mlir::LogicalResult CIRToLLVMShiftOpLowering::matchAndRewrite(
3137 cir::ShiftOp op, OpAdaptor adaptor,
3138 mlir::ConversionPatternRewriter &rewriter)
const {
3139 assert((op.getValue().getType() == op.getType()) &&
3140 "inconsistent operands' types NYI");
3142 const mlir::Type llvmTy = getTypeConverter()->convertType(op.getType());
3143 mlir::Value amt = adaptor.getAmount();
3144 mlir::Value val = adaptor.getValue();
3146 auto cirAmtTy = mlir::dyn_cast<cir::IntType>(op.getAmount().getType());
3149 auto cirValTy = mlir::cast<cir::IntType>(op.getValue().getType());
3157 amt =
getLLVMIntCast(rewriter, amt, llvmTy,
true, cirAmtTy.getWidth(),
3158 cirValTy.getWidth());
3160 auto cirValVTy = mlir::cast<cir::VectorType>(op.getValue().getType());
3162 mlir::cast<cir::IntType>(cirValVTy.getElementType()).isUnsigned();
3166 if (op.getIsShiftleft()) {
3167 rewriter.replaceOpWithNewOp<mlir::LLVM::ShlOp>(op, llvmTy, val, amt);
3168 return mlir::success();
3172 rewriter.replaceOpWithNewOp<mlir::LLVM::LShrOp>(op, llvmTy, val, amt);
3174 rewriter.replaceOpWithNewOp<mlir::LLVM::AShrOp>(op, llvmTy, val, amt);
3175 return mlir::success();
3178mlir::LogicalResult CIRToLLVMSelectOpLowering::matchAndRewrite(
3179 cir::SelectOp op, OpAdaptor adaptor,
3180 mlir::ConversionPatternRewriter &rewriter)
const {
3181 auto getConstantBool = [](mlir::Value value) -> cir::BoolAttr {
3182 auto definingOp = value.getDefiningOp<cir::ConstantOp>();
3186 auto constValue = definingOp.getValueAttr<cir::BoolAttr>();
3196 if (mlir::isa<cir::BoolType>(op.getTrueValue().getType())) {
3197 cir::BoolAttr trueValue = getConstantBool(op.getTrueValue());
3198 cir::BoolAttr falseValue = getConstantBool(op.getFalseValue());
3199 if (falseValue && !falseValue.getValue()) {
3201 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(op, adaptor.getCondition(),
3202 adaptor.getTrueValue());
3203 return mlir::success();
3205 if (trueValue && trueValue.getValue()) {
3207 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(op, adaptor.getCondition(),
3208 adaptor.getFalseValue());
3209 return mlir::success();
3213 mlir::Value llvmCondition = adaptor.getCondition();
3214 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(
3215 op, llvmCondition, adaptor.getTrueValue(), adaptor.getFalseValue());
3217 return mlir::success();
3221 mlir::DataLayout &dataLayout) {
3222 converter.addConversion([&](cir::PointerType type) -> mlir::Type {
3223 mlir::ptr::MemorySpaceAttrInterface addrSpaceAttr = type.getAddrSpace();
3224 unsigned numericAS = 0;
3226 if (
auto targetAsAttr =
3227 mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
3229 numericAS = targetAsAttr.getValue();
3230 return mlir::LLVM::LLVMPointerType::get(type.getContext(), numericAS);
3232 converter.addConversion([&](cir::VPtrType type) -> mlir::Type {
3234 return mlir::LLVM::LLVMPointerType::get(type.getContext());
3236 converter.addConversion([&](cir::ArrayType type) -> mlir::Type {
3239 return mlir::LLVM::LLVMArrayType::get(ty, type.getSize());
3241 converter.addConversion([&](cir::VectorType type) -> mlir::Type {
3242 const mlir::Type ty = converter.convertType(type.getElementType());
3243 return mlir::VectorType::get(type.getSize(), ty, {type.getIsScalable()});
3245 converter.addConversion([&](cir::BoolType type) -> mlir::Type {
3246 return mlir::IntegerType::get(type.getContext(), 1,
3247 mlir::IntegerType::Signless);
3249 converter.addConversion([&](cir::IntType type) -> mlir::Type {
3251 return mlir::IntegerType::get(type.getContext(), type.getWidth());
3253 converter.addConversion([&](cir::SingleType type) -> mlir::Type {
3254 return mlir::Float32Type::get(type.getContext());
3256 converter.addConversion([&](cir::DoubleType type) -> mlir::Type {
3257 return mlir::Float64Type::get(type.getContext());
3259 converter.addConversion([&](cir::FP80Type type) -> mlir::Type {
3260 return mlir::Float80Type::get(type.getContext());
3262 converter.addConversion([&](cir::FP128Type type) -> mlir::Type {
3263 return mlir::Float128Type::get(type.getContext());
3265 converter.addConversion([&](cir::LongDoubleType type) -> mlir::Type {
3266 return converter.convertType(type.getUnderlying());
3268 converter.addConversion([&](cir::FP16Type type) -> mlir::Type {
3269 return mlir::Float16Type::get(type.getContext());
3271 converter.addConversion([&](cir::BF16Type type) -> mlir::Type {
3272 return mlir::BFloat16Type::get(type.getContext());
3274 converter.addConversion([&](cir::ComplexType type) -> mlir::Type {
3277 mlir::Type elementTy = converter.convertType(type.getElementType());
3278 mlir::Type structFields[2] = {elementTy, elementTy};
3279 return mlir::LLVM::LLVMStructType::getLiteral(type.getContext(),
3282 converter.addConversion([&](cir::FuncType type) -> std::optional<mlir::Type> {
3283 auto result = converter.convertType(type.getReturnType());
3285 arguments.reserve(type.getNumInputs());
3286 if (converter.convertTypes(type.getInputs(), arguments).failed())
3287 return std::nullopt;
3288 auto varArg = type.isVarArg();
3289 return mlir::LLVM::LLVMFunctionType::get(result, arguments, varArg);
3291 converter.addConversion([&](cir::RecordType type) -> mlir::Type {
3294 switch (type.getKind()) {
3295 case cir::RecordType::Class:
3296 case cir::RecordType::Struct:
3297 for (mlir::Type ty : type.getMembers())
3301 case cir::RecordType::Union:
3302 if (type.getMembers().empty())
3304 if (
auto largestMember = type.getLargestMember(dataLayout))
3305 llvmMembers.push_back(
3307 if (type.getPadded()) {
3308 auto last = *type.getMembers().rbegin();
3309 llvmMembers.push_back(
3316 mlir::LLVM::LLVMStructType llvmStruct;
3317 if (type.getName()) {
3318 llvmStruct = mlir::LLVM::LLVMStructType::getIdentified(
3319 type.getContext(), type.getPrefixedName());
3320 if (llvmStruct.setBody(llvmMembers, type.getPacked()).failed())
3321 llvm_unreachable(
"Failed to set body of record");
3323 llvmStruct = mlir::LLVM::LLVMStructType::getLiteral(
3324 type.getContext(), llvmMembers, type.getPacked());
3329 converter.addConversion([&](cir::VoidType type) -> mlir::Type {
3330 return mlir::LLVM::LLVMVoidType::get(type.getContext());
3335 mlir::ModuleOp module, StringRef globalXtorName, StringRef llvmXtorName,
3336 llvm::function_ref<std::pair<StringRef, int>(mlir::Attribute)> createXtor) {
3338 for (
const mlir::NamedAttribute namedAttr : module->getAttrs()) {
3339 if (namedAttr.getName() == globalXtorName) {
3340 for (
auto attr : mlir::cast<mlir::ArrayAttr>(namedAttr.getValue()))
3341 globalXtors.emplace_back(createXtor(attr));
3346 if (globalXtors.empty())
3349 mlir::OpBuilder builder(module.getContext());
3350 builder.setInsertionPointToEnd(&module.getBodyRegion().back());
3354 auto ctorPFTy = mlir::LLVM::LLVMPointerType::get(builder.getContext());
3356 ctorStructFields.push_back(builder.getI32Type());
3357 ctorStructFields.push_back(ctorPFTy);
3358 ctorStructFields.push_back(ctorPFTy);
3360 auto ctorStructTy = mlir::LLVM::LLVMStructType::getLiteral(
3361 builder.getContext(), ctorStructFields);
3362 auto ctorStructArrayTy =
3363 mlir::LLVM::LLVMArrayType::get(ctorStructTy, globalXtors.size());
3365 mlir::Location loc =
module.getLoc();
3366 auto newGlobalOp = mlir::LLVM::GlobalOp::create(
3367 builder, loc, ctorStructArrayTy,
false,
3368 mlir::LLVM::Linkage::Appending, llvmXtorName, mlir::Attribute());
3370 builder.createBlock(&newGlobalOp.getRegion());
3371 builder.setInsertionPointToEnd(newGlobalOp.getInitializerBlock());
3373 mlir::Value result =
3374 mlir::LLVM::UndefOp::create(builder, loc, ctorStructArrayTy);
3376 for (
auto [index, fn] : llvm::enumerate(globalXtors)) {
3377 mlir::Value structInit =
3378 mlir::LLVM::UndefOp::create(builder, loc, ctorStructTy);
3379 mlir::Value initPriority = mlir::LLVM::ConstantOp::create(
3380 builder, loc, ctorStructFields[0], fn.second);
3381 mlir::Value initFuncAddr = mlir::LLVM::AddressOfOp::create(
3382 builder, loc, ctorStructFields[1], fn.first);
3383 mlir::Value initAssociate =
3384 mlir::LLVM::ZeroOp::create(builder, loc, ctorStructFields[2]);
3387 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
3388 initPriority, zero);
3389 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
3392 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
3394 result = mlir::LLVM::InsertValueOp::create(builder, loc, result, structInit,
3398 mlir::LLVM::ReturnOp::create(builder, loc, result);
3401mlir::LogicalResult CIRToLLVMObjSizeOpLowering::matchAndRewrite(
3402 cir::ObjSizeOp op, OpAdaptor adaptor,
3403 mlir::ConversionPatternRewriter &rewriter)
const {
3404 mlir::Type llvmResTy = getTypeConverter()->convertType(op.getType());
3405 mlir::Location loc = op->getLoc();
3407 mlir::IntegerType i1Ty = rewriter.getI1Type();
3409 auto i1Val = [&rewriter, &loc, &i1Ty](
bool val) {
3410 return mlir::LLVM::ConstantOp::create(rewriter, loc, i1Ty, val);
3417 i1Val(op.getNullunknown()),
3418 i1Val(op.getDynamic()),
3421 return mlir::LogicalResult::success();
3429constexpr StringRef llvmMetadataSectionName =
"llvm.metadata";
3434getOrCreateAnnotationStringGlobal(mlir::OpBuilder &builder, mlir::Location loc,
3435 mlir::ModuleOp module, llvm::StringRef str,
3436 llvm::StringMap<mlir::LLVM::GlobalOp> &cache,
3438 auto it = cache.find(str);
3439 if (it != cache.end())
3442 auto i8Ty = mlir::IntegerType::get(module.getContext(), 8);
3443 auto arrayTy = mlir::LLVM::LLVMArrayType::get(i8Ty, str.size() + 1);
3444 std::string
name =
".str";
3446 name +=
"." + std::to_string(cache.size());
3447 name +=
".annotation";
3451 mlir::LLVM::GlobalOp strGlobal = mlir::LLVM::GlobalOp::create(
3452 builder, loc, arrayTy,
true, mlir::LLVM::Linkage::Private,
3453 name, mlir::StringAttr::get(module.getContext(), std::string(str) +
'\0'),
3456 strGlobal.setSection(llvmMetadataSectionName);
3457 strGlobal.setUnnamedAddr(mlir::LLVM::UnnamedAddr::Global);
3458 strGlobal.setDsoLocal(
true);
3459 cache[str] = strGlobal;
3465mlir::LLVM::GlobalOp getOrCreateAnnotationArgsVar(
3466 mlir::OpBuilder &builder, mlir::Location loc, mlir::ModuleOp module,
3467 mlir::ArrayAttr argsAttr,
3468 llvm::StringMap<mlir::LLVM::GlobalOp> &argStringCache,
3469 llvm::MapVector<mlir::ArrayAttr, mlir::LLVM::GlobalOp> &argsCache) {
3470 auto it = argsCache.find(argsAttr);
3471 if (it != argsCache.end())
3474 auto ptrTy = mlir::LLVM::LLVMPointerType::get(builder.getContext());
3476 llvm::SmallVector<mlir::Type> fieldTypes;
3477 for (mlir::Attribute arg : argsAttr) {
3478 if (mlir::isa<mlir::StringAttr>(arg))
3479 fieldTypes.push_back(ptrTy);
3480 else if (
auto intAttr = mlir::dyn_cast<mlir::IntegerAttr>(arg))
3481 fieldTypes.push_back(intAttr.getType());
3483 llvm_unreachable(
"Unsupported annotation arg type");
3487 mlir::LLVM::LLVMStructType::getLiteral(builder.getContext(), fieldTypes);
3488 std::string
name =
".args";
3489 if (!argsCache.empty())
3490 name +=
"." + std::to_string(argsCache.size());
3491 name +=
".annotation";
3493 mlir::LLVM::GlobalOp argsGlobal = mlir::LLVM::GlobalOp::create(
3494 builder, loc, structTy,
true, mlir::LLVM::Linkage::Private,
3495 name, mlir::Attribute());
3496 argsGlobal.setSection(llvmMetadataSectionName);
3497 argsGlobal.setUnnamedAddr(mlir::LLVM::UnnamedAddr::Global);
3498 argsGlobal.setDsoLocal(
true);
3501 argsGlobal.getRegion().push_back(
new mlir::Block());
3502 mlir::OpBuilder initBuilder(module.getContext());
3503 initBuilder.setInsertionPointToEnd(argsGlobal.getInitializerBlock());
3505 mlir::Value structInit =
3506 mlir::LLVM::UndefOp::create(initBuilder, loc, structTy);
3507 for (
auto [idx, arg] : llvm::enumerate(argsAttr)) {
3508 if (
auto strArg = mlir::dyn_cast<mlir::StringAttr>(arg)) {
3509 mlir::LLVM::GlobalOp strGlobal = getOrCreateAnnotationStringGlobal(
3510 builder, loc, module, strArg.getValue(), argStringCache,
3512 mlir::LLVM::AddressOfOp strAddr = mlir::LLVM::AddressOfOp::create(
3513 initBuilder, loc, ptrTy, strGlobal.getSymName());
3514 structInit = mlir::LLVM::InsertValueOp::create(initBuilder, loc,
3515 structInit, strAddr, idx);
3516 }
else if (
auto intArg = mlir::dyn_cast<mlir::IntegerAttr>(arg)) {
3517 mlir::LLVM::ConstantOp intConst = mlir::LLVM::ConstantOp::create(
3518 initBuilder, loc, intArg.getType(), intArg.getValue());
3519 structInit = mlir::LLVM::InsertValueOp::create(initBuilder, loc,
3520 structInit, intConst, idx);
3522 llvm_unreachable(
"Unsupported annotation arg type");
3525 mlir::LLVM::ReturnOp::create(initBuilder, loc, structInit);
3527 argsCache[argsAttr] = argsGlobal;
3533std::pair<llvm::StringRef, unsigned> extractFileLine(mlir::Location loc) {
3534 mlir::Location resolved = loc;
3535 if (
auto fused = mlir::dyn_cast<mlir::FusedLoc>(resolved)) {
3536 if (!fused.getLocations().empty())
3537 resolved = fused.getLocations()[0];
3539 if (
auto fl = mlir::dyn_cast<mlir::FileLineColLoc>(resolved))
3540 return {fl.getFilename().getValue(), fl.getLine()};
3546 auto handleArray = [&](mlir::StringAttr symName, mlir::ArrayAttr arr,
3547 mlir::Location loc) {
3550 for (mlir::Attribute a : arr)
3551 if (
auto annot = mlir::dyn_cast<cir::AnnotationAttr>(a))
3552 collectedAnnotations.emplace_back(symName, annot, loc);
3557 module.walk([&](cir::GlobalOp op) {
3558 handleArray(op.getSymNameAttr(), op.getAnnotationsAttr(), op.getLoc());
3560 module.walk([&](cir::FuncOp op) {
3561 handleArray(op.getSymNameAttr(), op.getAnnotationsAttr(), op.getLoc());
3566 if (collectedAnnotations.empty())
3569 mlir::MLIRContext *ctx =
module.getContext();
3570 mlir::OpBuilder builder(ctx);
3571 builder.setInsertionPointToEnd(&module.getBodyRegion().back());
3573 auto ptrTy = mlir::LLVM::LLVMPointerType::get(ctx);
3574 auto i32Ty = builder.getI32Type();
3577 auto entryTy = mlir::LLVM::LLVMStructType::getLiteral(
3578 ctx, {ptrTy, ptrTy, ptrTy, i32Ty, ptrTy});
3580 mlir::LLVM::LLVMArrayType::get(entryTy, collectedAnnotations.size());
3582 mlir::Location moduleLoc =
module.getLoc();
3583 auto annotationsGlobal = mlir::LLVM::GlobalOp::create(
3584 builder, moduleLoc, arrayTy,
false,
3585 mlir::LLVM::Linkage::Appending,
"llvm.global.annotations",
3587 annotationsGlobal.setSection(llvmMetadataSectionName);
3591 mlir::OpBuilder constsBuilder(ctx);
3592 constsBuilder.setInsertionPoint(annotationsGlobal);
3594 llvm::StringMap<mlir::LLVM::GlobalOp> stringCache;
3595 llvm::StringMap<mlir::LLVM::GlobalOp> argStringCache;
3596 llvm::MapVector<mlir::ArrayAttr, mlir::LLVM::GlobalOp> argsCache;
3599 annotationsGlobal.getRegion().push_back(
new mlir::Block());
3600 mlir::OpBuilder initBuilder(ctx);
3601 initBuilder.setInsertionPointToEnd(annotationsGlobal.getInitializerBlock());
3603 mlir::Value arrayVal =
3604 mlir::LLVM::UndefOp::create(initBuilder, moduleLoc, arrayTy);
3606 for (
auto [idx, entry] : llvm::enumerate(collectedAnnotations)) {
3607 mlir::Value entryVal =
3608 mlir::LLVM::UndefOp::create(initBuilder, moduleLoc, entryTy);
3613 mlir::LLVM::AddressOfOp symAddr = mlir::LLVM::AddressOfOp::create(
3614 initBuilder, moduleLoc, ptrTy, entry.symName.getValue());
3615 entryVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
3616 entryVal, symAddr, zero);
3619 mlir::LLVM::GlobalOp nameGlobal = getOrCreateAnnotationStringGlobal(
3620 constsBuilder, moduleLoc, module, entry.annotation.getName().getValue(),
3621 stringCache,
false);
3622 mlir::LLVM::AddressOfOp nameAddr = mlir::LLVM::AddressOfOp::create(
3623 initBuilder, moduleLoc, ptrTy, nameGlobal.getSymName());
3624 entryVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
3625 entryVal, nameAddr, 1);
3628 auto [filename, line] = extractFileLine(entry.loc);
3629 mlir::LLVM::GlobalOp fileGlobal = getOrCreateAnnotationStringGlobal(
3630 constsBuilder, moduleLoc, module, filename, stringCache,
3632 mlir::LLVM::AddressOfOp fileAddr = mlir::LLVM::AddressOfOp::create(
3633 initBuilder, moduleLoc, ptrTy, fileGlobal.getSymName());
3634 entryVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
3635 entryVal, fileAddr, 2);
3636 mlir::LLVM::ConstantOp lineConst =
3637 mlir::LLVM::ConstantOp::create(initBuilder, moduleLoc, i32Ty, line);
3638 entryVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
3639 entryVal, lineConst, 3);
3642 mlir::ArrayAttr args = entry.annotation.getArgs();
3643 mlir::Value argsField;
3644 if (!args || args.empty()) {
3645 argsField = mlir::LLVM::ZeroOp::create(initBuilder, moduleLoc, ptrTy);
3647 mlir::LLVM::GlobalOp argsGlobal = getOrCreateAnnotationArgsVar(
3648 constsBuilder, moduleLoc, module, args, argStringCache, argsCache);
3649 argsField = mlir::LLVM::AddressOfOp::create(initBuilder, moduleLoc, ptrTy,
3650 argsGlobal.getSymName());
3652 entryVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
3653 entryVal, argsField, 4);
3655 arrayVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
3656 arrayVal, entryVal, idx);
3659 mlir::LLVM::ReturnOp::create(initBuilder, moduleLoc, arrayVal);
3665 mlir::ModuleOp module = getOperation();
3666 mlir::OpBuilder opBuilder(module.getContext());
3667 for (
auto &[blockAddOp, blockInfo] :
3669 mlir::LLVM::BlockTagOp resolvedLabel =
3671 assert(resolvedLabel &&
"expected BlockTagOp to already be emitted");
3672 mlir::FlatSymbolRefAttr fnSym = blockInfo.getFunc();
3673 auto blkAddTag = mlir::LLVM::BlockAddressAttr::get(
3674 opBuilder.getContext(), fnSym, resolvedLabel.getTagAttr());
3675 blockAddOp.setBlockAddrAttr(blkAddTag);
3682 if (mlir::Attribute tripleAttr =
3683 module->getAttr(cir::CIRDialect::getTripleAttrName()))
3684 module->setAttr(mlir::LLVM::LLVMDialect::getTargetTripleAttrName(),
3687 if (mlir::Attribute asmAttr =
3688 module->getAttr(cir::CIRDialect::getModuleLevelAsmAttrName()))
3689 module->setAttr(mlir::LLVM::LLVMDialect::getModuleLevelAsmAttrName(),
3694 llvm::TimeTraceScope scope(
"Convert CIR to LLVM Pass");
3696 mlir::ModuleOp module = getOperation();
3697 mlir::DataLayout dl(module);
3698 mlir::LLVMTypeConverter converter(&getContext());
3708 mlir::SymbolTableCollection symbolTables;
3709 mlir::RewritePatternSet patterns(&getContext());
3710 patterns.add<CIRToLLVMBlockAddressOpLowering, CIRToLLVMLabelOpLowering>(
3711 converter, patterns.getContext(), dl, blockInfoAddr);
3712 patterns.add<CIRToLLVMCallOpLowering, CIRToLLVMTryCallOpLowering>(
3713 converter, patterns.getContext(), dl, symbolTables);
3716#define GET_LLVM_LOWERING_PATTERNS_LIST
3717#include "clang/CIR/Dialect/IR/CIRLowering.inc"
3718#undef GET_LLVM_LOWERING_PATTERNS_LIST
3719 >(converter, patterns.getContext(), dl);
3727 mlir::ConversionTarget target(getContext());
3728 target.addLegalOp<mlir::ModuleOp>();
3729 target.addLegalDialect<mlir::LLVM::LLVMDialect>();
3730 mlir::configureOpenMPToLLVMConversionLegality(target, converter);
3731 target.addLegalDialect<mlir::omp::OpenMPDialect>();
3732 mlir::populateOpenMPToLLVMConversionPatterns(converter, patterns);
3733 target.addIllegalDialect<mlir::BuiltinDialect, cir::CIRDialect,
3734 mlir::func::FuncDialect>();
3737 ops.push_back(module);
3740 if (failed(applyPartialConversion(ops, target, std::move(patterns))))
3741 signalPassFailure();
3745 "llvm.global_ctors", [](mlir::Attribute
attr) {
3746 auto ctorAttr = mlir::cast<cir::GlobalCtorAttr>(
attr);
3747 return std::make_pair(ctorAttr.getName(),
3748 ctorAttr.getPriority());
3752 "llvm.global_dtors", [](mlir::Attribute
attr) {
3753 auto dtorAttr = mlir::cast<cir::GlobalDtorAttr>(
attr);
3754 return std::make_pair(dtorAttr.getName(),
3755 dtorAttr.getPriority());
3763mlir::LogicalResult CIRToLLVMBrOpLowering::matchAndRewrite(
3764 cir::BrOp op, OpAdaptor adaptor,
3765 mlir::ConversionPatternRewriter &rewriter)
const {
3766 rewriter.replaceOpWithNewOp<mlir::LLVM::BrOp>(op, adaptor.getOperands(),
3768 return mlir::LogicalResult::success();
3771mlir::LogicalResult CIRToLLVMGetMemberOpLowering::matchAndRewrite(
3772 cir::GetMemberOp op, OpAdaptor adaptor,
3773 mlir::ConversionPatternRewriter &rewriter)
const {
3774 mlir::Type llResTy = getTypeConverter()->convertType(op.getType());
3775 const auto recordTy =
3776 mlir::cast<cir::RecordType>(op.getAddrTy().getPointee());
3777 assert(recordTy &&
"expected record type");
3779 switch (recordTy.getKind()) {
3780 case cir::RecordType::Class:
3781 case cir::RecordType::Struct: {
3785 const mlir::Type elementTy = getTypeConverter()->convertType(recordTy);
3790 mlir::LLVM::GEPNoWrapFlags flags =
3791 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
3792 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
3793 op, llResTy, elementTy, adaptor.getAddr(), offset, flags);
3794 return mlir::success();
3796 case cir::RecordType::Union:
3799 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(op, llResTy,
3801 return mlir::success();
3805mlir::LogicalResult CIRToLLVMExtractMemberOpLowering::matchAndRewrite(
3806 cir::ExtractMemberOp op, OpAdaptor adaptor,
3807 mlir::ConversionPatternRewriter &rewriter)
const {
3808 std::int64_t indices[1] = {
static_cast<std::int64_t
>(op.getIndex())};
3810 mlir::Type recordTy = op.getRecord().getType();
3811 auto cirRecordTy = mlir::cast<cir::RecordType>(recordTy);
3812 switch (cirRecordTy.getKind()) {
3813 case cir::RecordType::Struct:
3814 case cir::RecordType::Class:
3815 rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractValueOp>(
3816 op, adaptor.getRecord(), indices);
3817 return mlir::success();
3819 case cir::RecordType::Union:
3820 op.emitError(
"cir.extract_member cannot extract member from a union");
3821 return mlir::failure();
3823 llvm_unreachable(
"Unexpected record kind");
3826mlir::LogicalResult CIRToLLVMInsertMemberOpLowering::matchAndRewrite(
3827 cir::InsertMemberOp op, OpAdaptor adaptor,
3828 mlir::ConversionPatternRewriter &rewriter)
const {
3829 std::int64_t indecies[1] = {
static_cast<std::int64_t
>(op.getIndex())};
3830 mlir::Type recordTy = op.getRecord().getType();
3832 if (
auto cirRecordTy = mlir::dyn_cast<cir::RecordType>(recordTy)) {
3833 if (cirRecordTy.getKind() == cir::RecordType::Union) {
3834 op.emitError(
"cir.update_member cannot update member of a union");
3835 return mlir::failure();
3839 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
3840 op, adaptor.getRecord(), adaptor.getValue(), indecies);
3841 return mlir::success();
3844mlir::LogicalResult CIRToLLVMUnreachableOpLowering::matchAndRewrite(
3845 cir::UnreachableOp op, OpAdaptor adaptor,
3846 mlir::ConversionPatternRewriter &rewriter)
const {
3847 rewriter.replaceOpWithNewOp<mlir::LLVM::UnreachableOp>(op);
3848 return mlir::success();
3852 mlir::Operation *srcOp, llvm::StringRef fnName,
3854 mlir::ArrayAttr argAttrs =
nullptr,
3855 mlir::ArrayAttr resAttrs =
nullptr) {
3856 mlir::ModuleOp modOp = srcOp->getParentOfType<mlir::ModuleOp>();
3857 mlir::Operation *sourceSymbol =
3858 mlir::SymbolTable::lookupSymbolIn(modOp, fnName);
3859 if (!sourceSymbol) {
3860 mlir::OpBuilder::InsertionGuard guard(rewriter);
3861 auto enclosingFnOp = srcOp->getParentOfType<mlir::LLVM::LLVMFuncOp>();
3862 rewriter.setInsertionPoint(enclosingFnOp);
3864 mlir::LLVM::LLVMFuncOp::create(rewriter, srcOp->getLoc(), fnName, fnTy);
3866 fn.setArgAttrsAttr(argAttrs);
3868 fn.setResAttrsAttr(resAttrs);
3872mlir::LogicalResult CIRToLLVMThrowOpLowering::matchAndRewrite(
3873 cir::ThrowOp op, OpAdaptor adaptor,
3874 mlir::ConversionPatternRewriter &rewriter)
const {
3875 mlir::Location loc = op.getLoc();
3876 auto voidTy = mlir::LLVM::LLVMVoidType::get(getContext());
3878 if (op.rethrows()) {
3879 auto funcTy = mlir::LLVM::LLVMFunctionType::get(voidTy, {});
3882 const llvm::StringRef functionName =
"__cxa_rethrow";
3883 createLLVMFuncOpIfNotExist(rewriter, op, functionName, funcTy);
3885 auto cxaRethrow = mlir::LLVM::CallOp::create(
3886 rewriter, loc, mlir::TypeRange{}, functionName);
3888 rewriter.replaceOp(op, cxaRethrow);
3889 return mlir::success();
3892 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3893 auto fnTy = mlir::LLVM::LLVMFunctionType::get(
3894 voidTy, {llvmPtrTy, llvmPtrTy, llvmPtrTy});
3897 const llvm::StringRef fnName =
"__cxa_throw";
3900 mlir::Value typeInfo = mlir::LLVM::AddressOfOp::create(
3901 rewriter, loc, mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
3902 adaptor.getTypeInfoAttr());
3906 dtor = mlir::LLVM::AddressOfOp::create(rewriter, loc, llvmPtrTy,
3907 adaptor.getDtorAttr());
3909 dtor = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmPtrTy);
3912 auto cxaThrowCall = mlir::LLVM::CallOp::create(
3913 rewriter, loc, mlir::TypeRange{}, fnName,
3914 mlir::ValueRange{adaptor.getExceptionPtr(), typeInfo, dtor});
3916 rewriter.replaceOp(op, cxaThrowCall);
3917 return mlir::success();
3920mlir::LogicalResult CIRToLLVMAllocExceptionOpLowering::matchAndRewrite(
3921 cir::AllocExceptionOp op, OpAdaptor adaptor,
3922 mlir::ConversionPatternRewriter &rewriter)
const {
3924 StringRef fnName =
"__cxa_allocate_exception";
3925 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3926 auto int64Ty = mlir::IntegerType::get(rewriter.getContext(), 64);
3927 auto fnTy = mlir::LLVM::LLVMFunctionType::get(llvmPtrTy, {int64Ty});
3930 auto exceptionSize = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
3931 adaptor.getSizeAttr());
3933 auto allocaExceptionCall = mlir::LLVM::CallOp::create(
3934 rewriter, op.getLoc(), mlir::TypeRange{llvmPtrTy}, fnName,
3935 mlir::ValueRange{exceptionSize});
3937 rewriter.replaceOp(op, allocaExceptionCall);
3938 return mlir::success();
3941static mlir::LLVM::LLVMStructType
3944 mlir::MLIRContext *ctx = rewriter.getContext();
3945 auto llvmPtr = mlir::LLVM::LLVMPointerType::get(ctx);
3947 return mlir::LLVM::LLVMStructType::getLiteral(ctx, structFields);
3950mlir::LogicalResult CIRToLLVMEhInflightOpLowering::matchAndRewrite(
3951 cir::EhInflightOp op, OpAdaptor adaptor,
3952 mlir::ConversionPatternRewriter &rewriter)
const {
3953 auto llvmFn = op->getParentOfType<mlir::LLVM::LLVMFuncOp>();
3954 assert(llvmFn &&
"expected LLVM function parent");
3955 mlir::Block *entryBlock = &llvmFn.getRegion().front();
3956 assert(entryBlock->isEntryBlock());
3958 mlir::ArrayAttr catchListAttr = op.getCatchTypeListAttr();
3959 mlir::SmallVector<mlir::Value> catchSymAddrs;
3961 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3962 mlir::Location loc = op.getLoc();
3967 if (catchListAttr) {
3970 for (mlir::Attribute catchAttr : catchListAttr) {
3971 auto symAttr = cast<mlir::FlatSymbolRefAttr>(catchAttr);
3974 mlir::OpBuilder::InsertionGuard guard(rewriter);
3975 rewriter.setInsertionPointToStart(entryBlock);
3976 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
3977 rewriter, loc, llvmPtrTy, symAttr.getValue());
3978 catchSymAddrs.push_back(addrOp);
3985 if (op.getCatchAll() || (!catchListAttr && !op.getCleanup())) {
3986 mlir::OpBuilder::InsertionGuard guard(rewriter);
3987 rewriter.setInsertionPointToStart(entryBlock);
3988 mlir::Value nullOp = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmPtrTy);
3989 catchSymAddrs.push_back(nullOp);
3994 mlir::LLVM::LLVMStructType llvmLandingPadStructTy =
3996 auto landingPadOp = mlir::LLVM::LandingpadOp::create(
3997 rewriter, loc, llvmLandingPadStructTy, catchSymAddrs);
4002 if (op.getCleanup() && !op.getCatchAll())
4003 landingPadOp.setCleanup(
true);
4006 mlir::LLVM::ExtractValueOp::create(rewriter, loc, landingPadOp, 0);
4007 mlir::Value selector =
4008 mlir::LLVM::ExtractValueOp::create(rewriter, loc, landingPadOp, 1);
4009 rewriter.replaceOp(op, mlir::ValueRange{slot, selector});
4011 return mlir::success();
4014mlir::LogicalResult CIRToLLVMResumeFlatOpLowering::matchAndRewrite(
4015 cir::ResumeFlatOp op, OpAdaptor adaptor,
4016 mlir::ConversionPatternRewriter &rewriter)
const {
4021 mlir::Value poison = mlir::LLVM::PoisonOp::create(rewriter, op.getLoc(),
4022 llvmLandingPadStructTy);
4025 mlir::Value slot = mlir::LLVM::InsertValueOp::create(
4026 rewriter, op.getLoc(), poison, adaptor.getExceptionPtr(), slotIdx);
4029 mlir::Value selector = mlir::LLVM::InsertValueOp::create(
4030 rewriter, op.getLoc(), slot, adaptor.getTypeId(), selectorIdx);
4032 rewriter.replaceOpWithNewOp<mlir::LLVM::ResumeOp>(op, selector);
4033 return mlir::success();
4036mlir::LogicalResult CIRToLLVMEhTypeIdOpLowering::matchAndRewrite(
4037 cir::EhTypeIdOp op, OpAdaptor adaptor,
4038 mlir::ConversionPatternRewriter &rewriter)
const {
4039 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
4040 rewriter, op.getLoc(),
4041 mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
4042 op.getTypeSymAttr());
4043 rewriter.replaceOpWithNewOp<mlir::LLVM::EhTypeidForOp>(
4044 op, rewriter.getI32Type(), addrOp);
4045 return mlir::success();
4048mlir::LogicalResult CIRToLLVMEhSetjmpOpLowering::matchAndRewrite(
4049 cir::EhSetjmpOp op, OpAdaptor adaptor,
4050 mlir::ConversionPatternRewriter &rewriter)
const {
4051 mlir::Type returnType = typeConverter->convertType(op.getType());
4052 mlir::LLVM::CallIntrinsicOp newOp =
4054 returnType, adaptor.getEnv());
4055 rewriter.replaceOp(op, newOp);
4056 return mlir::success();
4059mlir::LogicalResult CIRToLLVMEhLongjmpOpLowering::matchAndRewrite(
4060 cir::EhLongjmpOp op, OpAdaptor adaptor,
4061 mlir::ConversionPatternRewriter &rewriter)
const {
4063 {}, adaptor.getOperands());
4064 return mlir::success();
4067mlir::LogicalResult CIRToLLVMTrapOpLowering::matchAndRewrite(
4068 cir::TrapOp op, OpAdaptor adaptor,
4069 mlir::ConversionPatternRewriter &rewriter)
const {
4070 mlir::Location loc = op->getLoc();
4071 rewriter.eraseOp(op);
4073 mlir::LLVM::Trap::create(rewriter, loc);
4078 mlir::LLVM::UnreachableOp::create(rewriter, loc);
4080 return mlir::success();
4085 mlir::ConversionPatternRewriter &rewriter,
4086 const mlir::TypeConverter *converter,
4087 mlir::FlatSymbolRefAttr nameAttr, mlir::Type &eltType) {
4088 auto module = op->getParentOfType<mlir::ModuleOp>();
4089 mlir::Operation *symbol = mlir::SymbolTable::lookupSymbolIn(module, nameAttr);
4090 if (
auto llvmSymbol = mlir::dyn_cast<mlir::LLVM::GlobalOp>(symbol)) {
4091 eltType = llvmSymbol.getType();
4092 }
else if (
auto cirSymbol = mlir::dyn_cast<cir::GlobalOp>(symbol)) {
4093 eltType = converter->convertType(cirSymbol.getSymType());
4095 op->emitError() <<
"unexpected symbol type for " << symbol;
4099 return mlir::LLVM::AddressOfOp::create(
4100 rewriter, op->getLoc(),
4101 mlir::LLVM::LLVMPointerType::get(op->getContext()), nameAttr.getValue());
4104mlir::LogicalResult CIRToLLVMVTableAddrPointOpLowering::matchAndRewrite(
4105 cir::VTableAddrPointOp op, OpAdaptor adaptor,
4106 mlir::ConversionPatternRewriter &rewriter)
const {
4107 const mlir::TypeConverter *converter = getTypeConverter();
4108 mlir::Type targetType = converter->convertType(op.getType());
4111 mlir::Value symAddr = getValueForVTableSymbol(op, rewriter, converter,
4112 op.getNameAttr(), eltType);
4114 return op.emitError() <<
"Unable to get value for vtable symbol";
4117 0, op.getAddressPointAttr().getIndex(),
4118 op.getAddressPointAttr().getOffset()};
4120 assert(eltType &&
"Shouldn't ever be missing an eltType here");
4121 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
4122 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
4123 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, targetType, eltType,
4124 symAddr, offsets, inboundsNuw);
4125 return mlir::success();
4128mlir::LogicalResult CIRToLLVMVTableGetVPtrOpLowering::matchAndRewrite(
4129 cir::VTableGetVPtrOp op, OpAdaptor adaptor,
4130 mlir::ConversionPatternRewriter &rewriter)
const {
4134 mlir::Value srcVal = adaptor.getSrc();
4135 rewriter.replaceOp(op, srcVal);
4136 return mlir::success();
4139mlir::LogicalResult CIRToLLVMVTableGetVirtualFnAddrOpLowering::matchAndRewrite(
4140 cir::VTableGetVirtualFnAddrOp op, OpAdaptor adaptor,
4141 mlir::ConversionPatternRewriter &rewriter)
const {
4142 mlir::Type targetType = getTypeConverter()->convertType(op.getType());
4143 auto eltType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4146 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
4147 op, targetType, eltType, adaptor.getVptr(), offsets,
4148 mlir::LLVM::GEPNoWrapFlags::inbounds);
4149 return mlir::success();
4152mlir::LogicalResult CIRToLLVMVTTAddrPointOpLowering::matchAndRewrite(
4153 cir::VTTAddrPointOp op, OpAdaptor adaptor,
4154 mlir::ConversionPatternRewriter &rewriter)
const {
4155 const mlir::Type resultType = getTypeConverter()->convertType(op.getType());
4158 mlir::Value llvmAddr = adaptor.getSymAddr();
4160 if (op.getSymAddr()) {
4161 if (op.getOffset() == 0) {
4162 rewriter.replaceOp(op, {llvmAddr});
4163 return mlir::success();
4166 offsets.push_back(adaptor.getOffset());
4167 eltType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4170 op.getNameAttr(), eltType);
4171 assert(eltType &&
"Shouldn't ever be missing an eltType here");
4172 offsets.push_back(0);
4173 offsets.push_back(adaptor.getOffset());
4175 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
4176 op, resultType, eltType, llvmAddr, offsets,
4177 mlir::LLVM::GEPNoWrapFlags::inbounds);
4178 return mlir::success();
4181mlir::LogicalResult CIRToLLVMStackSaveOpLowering::matchAndRewrite(
4182 cir::StackSaveOp op, OpAdaptor adaptor,
4183 mlir::ConversionPatternRewriter &rewriter)
const {
4184 const mlir::Type ptrTy = getTypeConverter()->convertType(op.getType());
4185 rewriter.replaceOpWithNewOp<mlir::LLVM::StackSaveOp>(op, ptrTy);
4186 return mlir::success();
4189mlir::LogicalResult CIRToLLVMStackRestoreOpLowering::matchAndRewrite(
4190 cir::StackRestoreOp op, OpAdaptor adaptor,
4191 mlir::ConversionPatternRewriter &rewriter)
const {
4192 rewriter.replaceOpWithNewOp<mlir::LLVM::StackRestoreOp>(op, adaptor.getPtr());
4193 return mlir::success();
4196mlir::LogicalResult CIRToLLVMVecCreateOpLowering::matchAndRewrite(
4197 cir::VecCreateOp op, OpAdaptor adaptor,
4198 mlir::ConversionPatternRewriter &rewriter)
const {
4201 const auto vecTy = mlir::cast<cir::VectorType>(op.getType());
4202 const mlir::Type llvmTy = typeConverter->convertType(vecTy);
4203 const mlir::Location loc = op.getLoc();
4204 mlir::Value result = mlir::LLVM::PoisonOp::create(rewriter, loc, llvmTy);
4205 assert(vecTy.getSize() == op.getElements().size() &&
4206 "cir.vec.create op count doesn't match vector type elements count");
4208 for (uint64_t i = 0; i < vecTy.getSize(); ++i) {
4209 const mlir::Value indexValue =
4210 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
4211 result = mlir::LLVM::InsertElementOp::create(
4212 rewriter, loc, result, adaptor.getElements()[i], indexValue);
4215 rewriter.replaceOp(op, result);
4216 return mlir::success();
4219mlir::LogicalResult CIRToLLVMVecExtractOpLowering::matchAndRewrite(
4220 cir::VecExtractOp op, OpAdaptor adaptor,
4221 mlir::ConversionPatternRewriter &rewriter)
const {
4222 rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractElementOp>(
4223 op, adaptor.getVec(), adaptor.getIndex());
4224 return mlir::success();
4227mlir::LogicalResult CIRToLLVMVecInsertOpLowering::matchAndRewrite(
4228 cir::VecInsertOp op, OpAdaptor adaptor,
4229 mlir::ConversionPatternRewriter &rewriter)
const {
4230 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertElementOp>(
4231 op, adaptor.getVec(), adaptor.getValue(), adaptor.getIndex());
4232 return mlir::success();
4235mlir::LogicalResult CIRToLLVMVecCmpOpLowering::matchAndRewrite(
4236 cir::VecCmpOp op, OpAdaptor adaptor,
4237 mlir::ConversionPatternRewriter &rewriter)
const {
4238 mlir::Type elementType = elementTypeIfVector(op.getLhs().getType());
4239 mlir::Value bitResult;
4240 if (
auto intType = mlir::dyn_cast<cir::IntType>(elementType)) {
4241 bitResult = mlir::LLVM::ICmpOp::create(
4242 rewriter, op.getLoc(),
4244 adaptor.getLhs(), adaptor.getRhs());
4245 }
else if (mlir::isa<cir::FPTypeInterface>(elementType)) {
4246 bitResult = mlir::LLVM::FCmpOp::create(
4248 adaptor.getLhs(), adaptor.getRhs());
4250 return op.emitError() <<
"unsupported type for VecCmpOp: " << elementType;
4256 if (cast<cir::IntType>(cast<cir::VectorType>(op.getType()).getElementType())
4258 rewriter.replaceOpWithNewOp<mlir::LLVM::SExtOp>(
4259 op, typeConverter->convertType(op.getType()), bitResult);
4261 rewriter.replaceOp(op, bitResult);
4262 return mlir::success();
4265mlir::LogicalResult CIRToLLVMVecSplatOpLowering::matchAndRewrite(
4266 cir::VecSplatOp op, OpAdaptor adaptor,
4267 mlir::ConversionPatternRewriter &rewriter)
const {
4273 cir::VectorType vecTy = op.getType();
4274 mlir::Type llvmTy = typeConverter->convertType(vecTy);
4275 mlir::Location loc = op.getLoc();
4276 mlir::Value poison = mlir::LLVM::PoisonOp::create(rewriter, loc, llvmTy);
4278 mlir::Value elementValue = adaptor.getValue();
4279 if (elementValue.getDefiningOp<mlir::LLVM::PoisonOp>()) {
4282 rewriter.replaceOp(op, poison);
4283 return mlir::success();
4286 if (
auto constValue = elementValue.getDefiningOp<mlir::LLVM::ConstantOp>()) {
4287 if (
auto intAttr = dyn_cast<mlir::IntegerAttr>(constValue.getValue())) {
4288 mlir::DenseIntElementsAttr denseVec = mlir::DenseIntElementsAttr::get(
4289 mlir::cast<mlir::ShapedType>(llvmTy), intAttr.getValue());
4290 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
4291 op, denseVec.getType(), denseVec);
4292 return mlir::success();
4295 if (
auto fpAttr = dyn_cast<mlir::FloatAttr>(constValue.getValue())) {
4296 mlir::DenseFPElementsAttr denseVec = mlir::DenseFPElementsAttr::get(
4297 mlir::cast<mlir::ShapedType>(llvmTy), fpAttr.getValue());
4298 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
4299 op, denseVec.getType(), denseVec);
4300 return mlir::success();
4304 mlir::Value indexValue =
4305 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), 0);
4306 mlir::Value oneElement = mlir::LLVM::InsertElementOp::create(
4307 rewriter, loc, poison, elementValue, indexValue);
4309 rewriter.replaceOpWithNewOp<mlir::LLVM::ShuffleVectorOp>(op, oneElement,
4310 poison, zeroValues);
4311 return mlir::success();
4314mlir::LogicalResult CIRToLLVMVecShuffleOpLowering::matchAndRewrite(
4315 cir::VecShuffleOp op, OpAdaptor adaptor,
4316 mlir::ConversionPatternRewriter &rewriter)
const {
4322 op.getIndices().begin(), op.getIndices().end(),
4323 std::back_inserter(indices), [](mlir::Attribute intAttr) {
4324 return mlir::cast<cir::IntAttr>(intAttr).getValue().getSExtValue();
4326 rewriter.replaceOpWithNewOp<mlir::LLVM::ShuffleVectorOp>(
4327 op, adaptor.getVec1(), adaptor.getVec2(), indices);
4328 return mlir::success();
4331mlir::LogicalResult CIRToLLVMVecShuffleDynamicOpLowering::matchAndRewrite(
4332 cir::VecShuffleDynamicOp op, OpAdaptor adaptor,
4333 mlir::ConversionPatternRewriter &rewriter)
const {
4345 mlir::Location loc = op.getLoc();
4346 mlir::Value input = adaptor.getVec();
4347 mlir::Type llvmIndexVecType =
4348 getTypeConverter()->convertType(op.getIndices().getType());
4349 mlir::Type llvmIndexType = getTypeConverter()->convertType(
4350 elementTypeIfVector(op.getIndices().getType()));
4351 uint64_t numElements =
4352 mlir::cast<cir::VectorType>(op.getVec().getType()).getSize();
4354 uint64_t maskBits = llvm::NextPowerOf2(numElements - 1) - 1;
4355 mlir::Value maskValue = mlir::LLVM::ConstantOp::create(
4356 rewriter, loc, llvmIndexType,
4357 rewriter.getIntegerAttr(llvmIndexType, maskBits));
4358 mlir::Value maskVector =
4359 mlir::LLVM::UndefOp::create(rewriter, loc, llvmIndexVecType);
4361 for (uint64_t i = 0; i < numElements; ++i) {
4362 mlir::Value idxValue =
4363 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
4364 maskVector = mlir::LLVM::InsertElementOp::create(rewriter, loc, maskVector,
4365 maskValue, idxValue);
4368 mlir::Value maskedIndices = mlir::LLVM::AndOp::create(
4369 rewriter, loc, llvmIndexVecType, adaptor.getIndices(), maskVector);
4370 mlir::Value result = mlir::LLVM::UndefOp::create(
4371 rewriter, loc, getTypeConverter()->convertType(op.getVec().getType()));
4372 for (uint64_t i = 0; i < numElements; ++i) {
4373 mlir::Value iValue =
4374 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
4375 mlir::Value indexValue = mlir::LLVM::ExtractElementOp::create(
4376 rewriter, loc, maskedIndices, iValue);
4377 mlir::Value valueAtIndex =
4378 mlir::LLVM::ExtractElementOp::create(rewriter, loc, input, indexValue);
4379 result = mlir::LLVM::InsertElementOp::create(rewriter, loc, result,
4380 valueAtIndex, iValue);
4382 rewriter.replaceOp(op, result);
4383 return mlir::success();
4386mlir::LogicalResult CIRToLLVMVecTernaryOpLowering::matchAndRewrite(
4387 cir::VecTernaryOp op, OpAdaptor adaptor,
4388 mlir::ConversionPatternRewriter &rewriter)
const {
4390 mlir::Value bitVec = mlir::LLVM::ICmpOp::create(
4391 rewriter, op.getLoc(), mlir::LLVM::ICmpPredicate::ne, adaptor.getCond(),
4392 mlir::LLVM::ZeroOp::create(
4393 rewriter, op.getCond().getLoc(),
4394 typeConverter->convertType(op.getCond().getType())));
4395 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(
4396 op, bitVec, adaptor.getLhs(), adaptor.getRhs());
4397 return mlir::success();
4400mlir::LogicalResult CIRToLLVMComplexAddOpLowering::matchAndRewrite(
4401 cir::ComplexAddOp op, OpAdaptor adaptor,
4402 mlir::ConversionPatternRewriter &rewriter)
const {
4403 mlir::Value lhs = adaptor.getLhs();
4404 mlir::Value rhs = adaptor.getRhs();
4405 mlir::Location loc = op.getLoc();
4407 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
4408 mlir::Type complexElemTy =
4409 getTypeConverter()->convertType(
complexType.getElementType());
4410 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
4411 rewriter, loc, complexElemTy, lhs,
ArrayRef(int64_t{0}));
4412 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
4413 rewriter, loc, complexElemTy, lhs,
ArrayRef(int64_t{1}));
4414 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
4415 rewriter, loc, complexElemTy, rhs,
ArrayRef(int64_t{0}));
4416 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
4417 rewriter, loc, complexElemTy, rhs,
ArrayRef(int64_t{1}));
4419 mlir::Value newReal;
4420 mlir::Value newImag;
4421 if (complexElemTy.isInteger()) {
4422 newReal = mlir::LLVM::AddOp::create(rewriter, loc, complexElemTy, lhsReal,
4424 newImag = mlir::LLVM::AddOp::create(rewriter, loc, complexElemTy, lhsImag,
4429 newReal = mlir::LLVM::FAddOp::create(rewriter, loc, complexElemTy, lhsReal,
4431 newImag = mlir::LLVM::FAddOp::create(rewriter, loc, complexElemTy, lhsImag,
4435 mlir::Type complexLLVMTy =
4436 getTypeConverter()->convertType(op.getResult().getType());
4437 auto initialComplex =
4438 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), complexLLVMTy);
4440 auto realComplex = mlir::LLVM::InsertValueOp::create(
4441 rewriter, op->getLoc(), initialComplex, newReal,
ArrayRef(int64_t{0}));
4443 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
4444 op, realComplex, newImag,
ArrayRef(int64_t{1}));
4446 return mlir::success();
4449mlir::LogicalResult CIRToLLVMComplexCreateOpLowering::matchAndRewrite(
4450 cir::ComplexCreateOp op, OpAdaptor adaptor,
4451 mlir::ConversionPatternRewriter &rewriter)
const {
4452 mlir::Type complexLLVMTy =
4453 getTypeConverter()->convertType(op.getResult().getType());
4454 auto initialComplex =
4455 mlir::LLVM::UndefOp::create(rewriter, op->getLoc(), complexLLVMTy);
4457 auto realComplex = mlir::LLVM::InsertValueOp::create(
4458 rewriter, op->getLoc(), initialComplex, adaptor.getReal(),
4461 auto complex = mlir::LLVM::InsertValueOp::create(
4462 rewriter, op->getLoc(), realComplex, adaptor.getImag(),
4465 rewriter.replaceOp(op, complex);
4466 return mlir::success();
4469mlir::LogicalResult CIRToLLVMComplexRealOpLowering::matchAndRewrite(
4470 cir::ComplexRealOp op, OpAdaptor adaptor,
4471 mlir::ConversionPatternRewriter &rewriter)
const {
4472 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
4473 mlir::Value operand = adaptor.getOperand();
4474 if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) {
4475 operand = mlir::LLVM::ExtractValueOp::create(
4476 rewriter, op.getLoc(), resultLLVMTy, operand,
4479 rewriter.replaceOp(op, operand);
4480 return mlir::success();
4483mlir::LogicalResult CIRToLLVMComplexSubOpLowering::matchAndRewrite(
4484 cir::ComplexSubOp op, OpAdaptor adaptor,
4485 mlir::ConversionPatternRewriter &rewriter)
const {
4486 mlir::Value lhs = adaptor.getLhs();
4487 mlir::Value rhs = adaptor.getRhs();
4488 mlir::Location loc = op.getLoc();
4490 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
4491 mlir::Type complexElemTy =
4492 getTypeConverter()->convertType(
complexType.getElementType());
4493 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
4494 rewriter, loc, complexElemTy, lhs,
ArrayRef(int64_t{0}));
4495 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
4496 rewriter, loc, complexElemTy, lhs,
ArrayRef(int64_t{1}));
4497 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
4498 rewriter, loc, complexElemTy, rhs,
ArrayRef(int64_t{0}));
4499 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
4500 rewriter, loc, complexElemTy, rhs,
ArrayRef(int64_t{1}));
4502 mlir::Value newReal;
4503 mlir::Value newImag;
4504 if (complexElemTy.isInteger()) {
4505 newReal = mlir::LLVM::SubOp::create(rewriter, loc, complexElemTy, lhsReal,
4507 newImag = mlir::LLVM::SubOp::create(rewriter, loc, complexElemTy, lhsImag,
4512 newReal = mlir::LLVM::FSubOp::create(rewriter, loc, complexElemTy, lhsReal,
4514 newImag = mlir::LLVM::FSubOp::create(rewriter, loc, complexElemTy, lhsImag,
4518 mlir::Type complexLLVMTy =
4519 getTypeConverter()->convertType(op.getResult().getType());
4520 auto initialComplex =
4521 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), complexLLVMTy);
4523 auto realComplex = mlir::LLVM::InsertValueOp::create(
4524 rewriter, op->getLoc(), initialComplex, newReal,
ArrayRef(int64_t{0}));
4526 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
4527 op, realComplex, newImag,
ArrayRef(int64_t{1}));
4529 return mlir::success();
4532mlir::LogicalResult CIRToLLVMComplexImagOpLowering::matchAndRewrite(
4533 cir::ComplexImagOp op, OpAdaptor adaptor,
4534 mlir::ConversionPatternRewriter &rewriter)
const {
4535 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
4536 mlir::Value operand = adaptor.getOperand();
4537 mlir::Location loc = op.getLoc();
4539 if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) {
4540 operand = mlir::LLVM::ExtractValueOp::create(
4543 mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(resultLLVMTy);
4545 mlir::LLVM::ConstantOp::create(rewriter, loc, resultLLVMTy, zeroAttr);
4548 rewriter.replaceOp(op, operand);
4549 return mlir::success();
4553 mlir::MLIRContext *context,
4554 unsigned &storageSize) {
4555 return TypeSwitch<mlir::Type, mlir::IntegerType>(storageType)
4556 .Case<cir::ArrayType>([&](cir::ArrayType atTy) {
4557 storageSize = atTy.getSize() * 8;
4558 return mlir::IntegerType::get(context, storageSize);
4560 .Case<cir::IntType>([&](cir::IntType intTy) {
4561 storageSize = intTy.getWidth();
4562 return mlir::IntegerType::get(context, storageSize);
4564 .Default([](mlir::Type) -> mlir::IntegerType {
4566 "Either ArrayType or IntType expected for bitfields storage");
4570mlir::LogicalResult CIRToLLVMSetBitfieldOpLowering::matchAndRewrite(
4571 cir::SetBitfieldOp op, OpAdaptor adaptor,
4572 mlir::ConversionPatternRewriter &rewriter)
const {
4573 mlir::OpBuilder::InsertionGuard guard(rewriter);
4574 rewriter.setInsertionPoint(op);
4576 cir::BitfieldInfoAttr info = op.getBitfieldInfo();
4577 uint64_t size = info.getSize();
4578 uint64_t offset = info.getOffset();
4579 mlir::Type storageType = info.getStorageType();
4580 mlir::MLIRContext *context = storageType.getContext();
4582 unsigned storageSize = 0;
4584 mlir::IntegerType intType =
4585 computeBitfieldIntType(storageType, context, storageSize);
4587 mlir::Value srcVal = createIntCast(rewriter, adaptor.getSrc(), intType);
4588 unsigned srcWidth = storageSize;
4589 mlir::Value resultVal = srcVal;
4591 if (storageSize != size) {
4592 assert(storageSize > size &&
"Invalid bitfield size.");
4594 mlir::Value val = mlir::LLVM::LoadOp::create(
4595 rewriter, op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(),
4596 op.getIsVolatile());
4599 createAnd(rewriter, srcVal, llvm::APInt::getLowBitsSet(srcWidth, size));
4601 srcVal =
createShL(rewriter, srcVal, offset);
4605 ~llvm::APInt::getBitsSet(srcWidth, offset, offset + size));
4608 srcVal = mlir::LLVM::OrOp::create(rewriter, op.getLoc(), val, srcVal);
4611 mlir::LLVM::StoreOp::create(rewriter, op.getLoc(), srcVal, adaptor.getAddr(),
4612 op.getAlignment(), op.getIsVolatile());
4614 mlir::Type resultTy = getTypeConverter()->convertType(op.getType());
4616 if (info.getIsSigned()) {
4617 assert(size <= storageSize);
4618 unsigned highBits = storageSize - size;
4621 resultVal =
createShL(rewriter, resultVal, highBits);
4622 resultVal =
createAShR(rewriter, resultVal, highBits);
4627 mlir::cast<mlir::IntegerType>(resultTy),
4628 info.getIsSigned());
4630 rewriter.replaceOp(op, resultVal);
4631 return mlir::success();
4634mlir::LogicalResult CIRToLLVMComplexImagPtrOpLowering::matchAndRewrite(
4635 cir::ComplexImagPtrOp op, OpAdaptor adaptor,
4636 mlir::ConversionPatternRewriter &rewriter)
const {
4637 cir::PointerType operandTy = op.getOperand().getType();
4638 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
4639 mlir::Type elementLLVMTy =
4640 getTypeConverter()->convertType(operandTy.getPointee());
4642 mlir::LLVM::GEPArg gepIndices[2] = {{0}, {1}};
4643 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
4644 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
4645 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
4646 op, resultLLVMTy, elementLLVMTy, adaptor.getOperand(), gepIndices,
4648 return mlir::success();
4651mlir::LogicalResult CIRToLLVMComplexRealPtrOpLowering::matchAndRewrite(
4652 cir::ComplexRealPtrOp op, OpAdaptor adaptor,
4653 mlir::ConversionPatternRewriter &rewriter)
const {
4654 cir::PointerType operandTy = op.getOperand().getType();
4655 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
4656 mlir::Type elementLLVMTy =
4657 getTypeConverter()->convertType(operandTy.getPointee());
4659 mlir::LLVM::GEPArg gepIndices[2] = {0, 0};
4660 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
4661 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
4662 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
4663 op, resultLLVMTy, elementLLVMTy, adaptor.getOperand(), gepIndices,
4665 return mlir::success();
4668mlir::LogicalResult CIRToLLVMGetBitfieldOpLowering::matchAndRewrite(
4669 cir::GetBitfieldOp op, OpAdaptor adaptor,
4670 mlir::ConversionPatternRewriter &rewriter)
const {
4672 mlir::OpBuilder::InsertionGuard guard(rewriter);
4673 rewriter.setInsertionPoint(op);
4675 cir::BitfieldInfoAttr info = op.getBitfieldInfo();
4676 uint64_t size = info.getSize();
4677 uint64_t offset = info.getOffset();
4678 mlir::Type storageType = info.getStorageType();
4679 mlir::MLIRContext *context = storageType.getContext();
4680 unsigned storageSize = 0;
4682 mlir::IntegerType intType =
4685 mlir::Value val = mlir::LLVM::LoadOp::create(
4686 rewriter, op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(),
4687 op.getIsVolatile());
4688 val = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), intType, val);
4690 if (info.getIsSigned()) {
4691 assert(
static_cast<unsigned>(offset + size) <= storageSize);
4692 unsigned highBits = storageSize - offset - size;
4693 val =
createShL(rewriter, val, highBits);
4694 val =
createAShR(rewriter, val, offset + highBits);
4698 if (
static_cast<unsigned>(offset) + size < storageSize)
4700 llvm::APInt::getLowBitsSet(storageSize, size));
4703 mlir::Type resTy = getTypeConverter()->convertType(op.getType());
4705 rewriter, val, mlir::cast<mlir::IntegerType>(resTy), info.getIsSigned());
4706 rewriter.replaceOp(op, newOp);
4707 return mlir::success();
4710mlir::LogicalResult CIRToLLVMIsConstantOpLowering::matchAndRewrite(
4711 cir::IsConstantOp op, OpAdaptor adaptor,
4712 mlir::ConversionPatternRewriter &rewriter)
const {
4713 rewriter.replaceOpWithNewOp<mlir::LLVM::IsConstantOp>(op, adaptor.getVal());
4714 return mlir::success();
4717mlir::LogicalResult CIRToLLVMInlineAsmOpLowering::matchAndRewrite(
4718 cir::InlineAsmOp op, OpAdaptor adaptor,
4719 mlir::ConversionPatternRewriter &rewriter)
const {
4721 if (op.getNumResults())
4722 llResTy = getTypeConverter()->convertType(op.getType(0));
4724 cir::AsmFlavor dialect = op.getAsmFlavor();
4725 mlir::LLVM::AsmDialect llDialect = dialect == cir::AsmFlavor::x86_att
4726 ? mlir::LLVM::AsmDialect::AD_ATT
4727 : mlir::LLVM::AsmDialect::AD_Intel;
4730 StringRef llvmAttrName = mlir::LLVM::InlineAsmOp::getElementTypeAttrName();
4736 if (!op.getNumResults())
4737 opAttrs.push_back(mlir::Attribute());
4741 for (
auto const &[llvmOp, cirOp] :
4742 zip(adaptor.getAsmOperands(), op.getAsmOperands())) {
4743 append_range(llvmOperands, llvmOp);
4744 append_range(cirOperands, cirOp);
4749 for (
auto const &[cirOpAttr, cirOp] :
4750 zip(op.getOperandAttrs(), cirOperands)) {
4751 if (!mlir::isa<mlir::UnitAttr>(cirOpAttr)) {
4752 opAttrs.push_back(mlir::Attribute());
4757 cir::PointerType typ = mlir::cast<cir::PointerType>(cirOp.getType());
4759 *getTypeConverter(), dataLayout, typ.getPointee()));
4761 attrs.push_back(rewriter.getNamedAttr(llvmAttrName, typAttr));
4762 mlir::DictionaryAttr newDict = rewriter.getDictionaryAttr(attrs);
4763 opAttrs.push_back(newDict);
4766 rewriter.replaceOpWithNewOp<mlir::LLVM::InlineAsmOp>(
4767 op, llResTy, llvmOperands, op.getAsmStringAttr(), op.getConstraintsAttr(),
4768 op.getSideEffectsAttr(),
4771 mlir::LLVM::TailCallKindAttr::get(
4772 getContext(), mlir::LLVM::tailcallkind::TailCallKind::None),
4773 mlir::LLVM::AsmDialectAttr::get(getContext(), llDialect),
4774 rewriter.getArrayAttr(opAttrs));
4776 return mlir::success();
4779mlir::LogicalResult CIRToLLVMVAStartOpLowering::matchAndRewrite(
4780 cir::VAStartOp op, OpAdaptor adaptor,
4781 mlir::ConversionPatternRewriter &rewriter)
const {
4782 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4783 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4784 adaptor.getArgList());
4785 rewriter.replaceOpWithNewOp<mlir::LLVM::VaStartOp>(op, vaList);
4786 return mlir::success();
4789mlir::LogicalResult CIRToLLVMVAEndOpLowering::matchAndRewrite(
4790 cir::VAEndOp op, OpAdaptor adaptor,
4791 mlir::ConversionPatternRewriter &rewriter)
const {
4792 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4793 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4794 adaptor.getArgList());
4795 rewriter.replaceOpWithNewOp<mlir::LLVM::VaEndOp>(op, vaList);
4796 return mlir::success();
4799mlir::LogicalResult CIRToLLVMVACopyOpLowering::matchAndRewrite(
4800 cir::VACopyOp op, OpAdaptor adaptor,
4801 mlir::ConversionPatternRewriter &rewriter)
const {
4802 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4803 auto dstList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4804 adaptor.getDstList());
4805 auto srcList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4806 adaptor.getSrcList());
4807 rewriter.replaceOpWithNewOp<mlir::LLVM::VaCopyOp>(op, dstList, srcList);
4808 return mlir::success();
4811mlir::LogicalResult CIRToLLVMVAArgOpLowering::matchAndRewrite(
4812 cir::VAArgOp op, OpAdaptor adaptor,
4813 mlir::ConversionPatternRewriter &rewriter)
const {
4815 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4816 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4817 adaptor.getArgList());
4819 mlir::Type llvmType =
4820 getTypeConverter()->convertType(op->getResultTypes().front());
4822 return mlir::failure();
4824 rewriter.replaceOpWithNewOp<mlir::LLVM::VaArgOp>(op, llvmType, vaList);
4825 return mlir::success();
4828mlir::LogicalResult CIRToLLVMLabelOpLowering::matchAndRewrite(
4829 cir::LabelOp op, OpAdaptor adaptor,
4830 mlir::ConversionPatternRewriter &rewriter)
const {
4831 mlir::MLIRContext *ctx = rewriter.getContext();
4832 mlir::Block *block = op->getBlock();
4835 if (block->isEntryBlock()) {
4836 mlir::Block *newBlock =
4837 rewriter.splitBlock(op->getBlock(), mlir::Block::iterator(op));
4838 rewriter.setInsertionPointToEnd(block);
4839 mlir::LLVM::BrOp::create(rewriter, op.getLoc(), newBlock);
4842 mlir::LLVM::BlockTagAttr::get(ctx, blockInfoAddr.getTagIndex());
4843 rewriter.setInsertionPoint(op);
4846 mlir::LLVM::BlockTagOp::create(rewriter, op->getLoc(), tagAttr);
4847 mlir::LLVM::LLVMFuncOp func = op->getParentOfType<mlir::LLVM::LLVMFuncOp>();
4848 auto blockInfoAttr =
4849 cir::BlockAddrInfoAttr::get(ctx, func.getSymName(), op.getLabel());
4850 blockInfoAddr.mapBlockTag(blockInfoAttr, blockTagOp);
4851 rewriter.eraseOp(op);
4853 return mlir::success();
4856mlir::LogicalResult CIRToLLVMBlockAddressOpLowering::matchAndRewrite(
4857 cir::BlockAddressOp op, OpAdaptor adaptor,
4858 mlir::ConversionPatternRewriter &rewriter)
const {
4859 mlir::MLIRContext *ctx = rewriter.getContext();
4861 mlir::LLVM::BlockTagOp matchLabel =
4862 blockInfoAddr.lookupBlockTag(op.getBlockAddrInfoAttr());
4863 mlir::LLVM::BlockTagAttr tagAttr;
4870 tagAttr = matchLabel.getTag();
4872 auto blkAddr = mlir::LLVM::BlockAddressAttr::get(
4873 rewriter.getContext(), op.getBlockAddrInfoAttr().getFunc(), tagAttr);
4874 rewriter.setInsertionPoint(op);
4875 auto newOp = mlir::LLVM::BlockAddressOp::create(
4876 rewriter, op.getLoc(), mlir::LLVM::LLVMPointerType::get(ctx), blkAddr);
4878 blockInfoAddr.addUnresolvedBlockAddress(newOp, op.getBlockAddrInfoAttr());
4879 rewriter.replaceOp(op, newOp);
4880 return mlir::success();
4883mlir::LogicalResult CIRToLLVMIndirectBrOpLowering::matchAndRewrite(
4884 cir::IndirectBrOp op, OpAdaptor adaptor,
4885 mlir::ConversionPatternRewriter &rewriter)
const {
4887 mlir::Value targetAddr = adaptor.getAddr();
4895 if (op.getPoison()) {
4896 auto llvmPtrType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4898 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), llvmPtrType);
4901 rewriter.replaceOpWithNewOp<mlir::LLVM::IndirectBrOp>(
4902 op, targetAddr, adaptor.getSuccOperands(), op.getSuccessors());
4903 return mlir::success();
4906mlir::LogicalResult CIRToLLVMAwaitOpLowering::matchAndRewrite(
4907 cir::AwaitOp op, OpAdaptor adaptor,
4908 mlir::ConversionPatternRewriter &rewriter)
const {
4909 return mlir::failure();
4912mlir::LogicalResult CIRToLLVMCpuIdOpLowering::matchAndRewrite(
4913 cir::CpuIdOp op, OpAdaptor adaptor,
4914 mlir::ConversionPatternRewriter &rewriter)
const {
4915 mlir::Type i32Ty = rewriter.getI32Type();
4916 mlir::Type i64Ty = rewriter.getI64Type();
4917 mlir::Type i32PtrTy = mlir::LLVM::LLVMPointerType::get(i32Ty.getContext(), 0);
4919 mlir::Type cpuidRetTy = mlir::LLVM::LLVMStructType::getLiteral(
4920 rewriter.getContext(), {i32Ty, i32Ty, i32Ty, i32Ty});
4922 mlir::Value functionId = adaptor.getFunctionId();
4923 mlir::Value subFunctionId = adaptor.getSubFunctionId();
4925 StringRef asmString, constraints;
4926 mlir::ModuleOp moduleOp = op->getParentOfType<mlir::ModuleOp>();
4927 llvm::Triple triple(
4928 mlir::cast<mlir::StringAttr>(
4929 moduleOp->getAttr(cir::CIRDialect::getTripleAttrName()))
4931 if (triple.getArch() == llvm::Triple::x86) {
4932 asmString =
"cpuid";
4933 constraints =
"={ax},={bx},={cx},={dx},{ax},{cx}";
4936 asmString =
"xchgq %rbx, ${1:q}\n"
4938 "xchgq %rbx, ${1:q}";
4939 constraints =
"={ax},=r,={cx},={dx},0,2";
4942 mlir::Value inlineAsm =
4943 mlir::LLVM::InlineAsmOp::create(
4944 rewriter, op.getLoc(), cpuidRetTy, {functionId, subFunctionId},
4945 rewriter.getStringAttr(asmString),
4946 rewriter.getStringAttr(constraints),
4949 mlir::LLVM::TailCallKindAttr{},
4950 mlir::LLVM::AsmDialectAttr{},
4954 mlir::Value basePtr = adaptor.getCpuInfo();
4956 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
4957 unsigned alignment = layout.getTypeABIAlignment(i32Ty);
4958 for (
unsigned i = 0; i < 4; i++) {
4959 mlir::Value extracted =
4960 mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(), inlineAsm, i)
4962 mlir::Value index = mlir::LLVM::ConstantOp::create(
4963 rewriter, op.getLoc(), i64Ty, rewriter.getI64IntegerAttr(i));
4965 mlir::Value storePtr = mlir::LLVM::GEPOp::create(
4966 rewriter, op.getLoc(), i32PtrTy, i32Ty, basePtr,
4967 gepIndices, mlir::LLVM::GEPNoWrapFlags::none)
4969 mlir::LLVM::StoreOp::create(rewriter, op.getLoc(), extracted, storePtr,
4973 rewriter.eraseOp(op);
4974 return mlir::success();
4977mlir::LogicalResult CIRToLLVMMemChrOpLowering::matchAndRewrite(
4978 cir::MemChrOp op, OpAdaptor adaptor,
4979 mlir::ConversionPatternRewriter &rewriter)
const {
4980 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4981 mlir::Type srcTy = getTypeConverter()->convertType(op.getSrc().getType());
4982 mlir::Type patternTy =
4983 getTypeConverter()->convertType(op.getPattern().getType());
4984 mlir::Type lenTy = getTypeConverter()->convertType(op.getLen().getType());
4986 mlir::LLVM::LLVMFunctionType::get(llvmPtrTy, {srcTy, patternTy, lenTy},
4988 llvm::StringRef fnName =
"memchr";
4990 mlir::Builder
b(rewriter.getContext());
4991 mlir::NamedAttribute noundefAttr =
4992 b.getNamedAttr(
"llvm.noundef",
b.getUnitAttr());
4993 mlir::DictionaryAttr noundefDict = mlir::DictionaryAttr::get(
4996 mlir::ArrayAttr argAttrs =
4997 mlir::ArrayAttr::get(rewriter.getContext(), argAttrVec);
5001 mlir::LLVM::CallOp newCall = rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(
5002 op, mlir::TypeRange{llvmPtrTy}, fnName,
5003 mlir::ValueRange{adaptor.getSrc(), adaptor.getPattern(),
5005 newCall.setArgAttrsAttr(argAttrs);
5006 return mlir::success();
5009mlir::LogicalResult CIRToLLVMLaunderOpLowering::matchAndRewrite(
5010 cir::LaunderOp op, OpAdaptor adaptor,
5011 mlir::ConversionPatternRewriter &rewriter)
const {
5012 rewriter.replaceOpWithNewOp<mlir::LLVM::LaunderInvariantGroupOp>(
5013 op, adaptor.getArg());
5014 return mlir::success();
5018 return std::make_unique<ConvertCIRToLLVMPass>();
5023 pm.addPass(mlir::omp::createMarkDeclareTargetPass());
5027std::unique_ptr<llvm::Module>
5029 StringRef mlirSaveTempsOutFile,
5030 llvm::vfs::FileSystem *fs) {
5031 llvm::TimeTraceScope scope(
"lower from CIR to LLVM directly");
5033 mlir::MLIRContext *mlirCtx = mlirModule.getContext();
5035 mlir::PassManager pm(mlirCtx);
5038 (void)mlir::applyPassManagerCLOptions(pm);
5040 if (mlir::failed(pm.run(mlirModule))) {
5043 "The pass manager failed to lower CIR to LLVMIR dialect!");
5046 if (!mlirSaveTempsOutFile.empty()) {
5048 llvm::raw_fd_ostream out(mlirSaveTempsOutFile, ec);
5050 mlirModule->print(out);
5053 mlir::registerBuiltinDialectTranslation(*mlirCtx);
5054 mlir::registerLLVMDialectTranslation(*mlirCtx);
5055 mlir::registerOpenMPDialectTranslation(*mlirCtx);
5058 llvm::TimeTraceScope translateScope(
"translateModuleToLLVMIR");
5060 StringRef moduleName = mlirModule.getName().value_or(
"CIRToLLVMModule");
5061 std::unique_ptr<llvm::Module> llvmModule = mlir::translateModuleToLLVMIR(
5062 mlirModule, llvmCtx, moduleName,
false, fs);
5066 report_fatal_error(
"Lowering from LLVMIR dialect to llvm IR failed!");
static bool isUnsigned(SValBuilder &SVB, NonLoc Value)
static llvm::StringRef getLinkageAttrNameString()
Returns the name used for the linkage attribute.
mlir::Value createLShR(mlir::OpBuilder &bld, mlir::Value lhs, unsigned rhs)
mlir::Value createShL(mlir::OpBuilder &bld, mlir::Value lhs, unsigned rhs)
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 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::LogicalResult rewriteCallOrInvoke(mlir::Operation *op, mlir::ValueRange callOperands, mlir::ConversionPatternRewriter &rewriter, const mlir::TypeConverter *converter, mlir::SymbolTableCollection &symbolTables, mlir::FlatSymbolRefAttr calleeAttr, mlir::Block *continueBlock=nullptr, mlir::Block *landingPadBlock=nullptr)
static 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.
std::unique_ptr< llvm::Module > lowerDirectlyFromCIRToLLVMIR(mlir::ModuleOp mlirModule, llvm::LLVMContext &llvmCtx, llvm::StringRef mlirSaveTempsOutFile={}, llvm::vfs::FileSystem *fs=nullptr)
static bool isIntTypeUnsigned(mlir::Type type)
void collectUnreachable(mlir::Operation *parent, llvm::SmallVectorImpl< mlir::Operation * > &ops)
Collect ops in blocks that are unreachable from their region's entry, appending them to ops.
llvm::Type * convertTypeForMemory(CodeGenModule &CGM, QualType T)
const internal::VariadicAllOfMatcher< Attr > attr
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const AstTypeMatcher< ComplexType > complexType
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()