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);
363 return mlir::LLVM::CallIntrinsicOp::create(rewriter, loc, resultTy,
364 intrinsicNameAttr, operands);
365 return mlir::LLVM::CallIntrinsicOp::create(rewriter, loc, intrinsicNameAttr,
370 mlir::ConversionPatternRewriter &rewriter, mlir::Operation *op,
371 const llvm::Twine &intrinsicName, mlir::Type resultTy,
372 mlir::ValueRange operands) {
374 rewriter, op->getLoc(), intrinsicName, resultTy, operands);
375 rewriter.replaceOp(op, callIntrinOp.getOperation());
379mlir::LogicalResult CIRToLLVMLLVMIntrinsicCallOpLowering::matchAndRewrite(
380 cir::LLVMIntrinsicCallOp op, OpAdaptor adaptor,
381 mlir::ConversionPatternRewriter &rewriter)
const {
384 mlir::Type llvmResTy;
385 if (op->getNumResults() != 0) {
386 llvmResTy = getTypeConverter()->convertType(op->getResultTypes()[0]);
388 return op.emitError(
"expected LLVM result type");
390 StringRef name = op.getIntrinsicName();
403 adaptor.getOperands());
404 return mlir::success();
408mlir::Value CIRAttrToValue::visitCirAttr(cir::BoolAttr boolAttr) {
409 mlir::Location loc = parentOp->getLoc();
410 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
411 mlir::Value boolVal = mlir::LLVM::ConstantOp::create(
412 rewriter, loc, converter->convertType(boolAttr.getType()),
413 boolAttr.getValue());
414 return emitToMemory(rewriter, layout, boolAttr.getType(), boolVal);
418mlir::Value CIRAttrToValue::visitCirAttr(cir::IntAttr intAttr) {
419 mlir::Location loc = parentOp->getLoc();
420 return mlir::LLVM::ConstantOp::create(
421 rewriter, loc, converter->convertType(intAttr.getType()),
426mlir::Value CIRAttrToValue::visitCirAttr(cir::FPAttr fltAttr) {
427 mlir::Location loc = parentOp->getLoc();
428 return mlir::LLVM::ConstantOp::create(
429 rewriter, loc, converter->convertType(fltAttr.getType()),
434mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstComplexAttr complexAttr) {
435 auto complexType = mlir::cast<cir::ComplexType>(complexAttr.getType());
436 mlir::Type complexElemTy =
complexType.getElementType();
437 mlir::Type complexElemLLVMTy = converter->convertType(complexElemTy);
439 mlir::Attribute components[2];
440 if (
const auto intType = mlir::dyn_cast<cir::IntType>(complexElemTy)) {
441 components[0] = rewriter.getIntegerAttr(
443 mlir::cast<cir::IntAttr>(complexAttr.getReal()).getValue());
444 components[1] = rewriter.getIntegerAttr(
446 mlir::cast<cir::IntAttr>(complexAttr.getImag()).getValue());
448 components[0] = rewriter.getFloatAttr(
450 mlir::cast<cir::FPAttr>(complexAttr.getReal()).getValue());
451 components[1] = rewriter.getFloatAttr(
453 mlir::cast<cir::FPAttr>(complexAttr.getImag()).getValue());
456 mlir::Location loc = parentOp->getLoc();
457 return mlir::LLVM::ConstantOp::create(
458 rewriter, loc, converter->convertType(complexAttr.getType()),
459 rewriter.getArrayAttr(components));
463mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstPtrAttr ptrAttr) {
464 mlir::Location loc = parentOp->getLoc();
465 if (ptrAttr.isNullValue()) {
466 return mlir::LLVM::ZeroOp::create(
467 rewriter, loc, converter->convertType(ptrAttr.getType()));
469 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
470 mlir::Value ptrVal = mlir::LLVM::ConstantOp::create(
472 rewriter.getIntegerType(layout.getTypeSizeInBits(ptrAttr.getType())),
473 ptrAttr.getValue().getInt());
474 return mlir::LLVM::IntToPtrOp::create(
475 rewriter, loc, converter->convertType(ptrAttr.getType()), ptrVal);
479mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstArrayAttr attr) {
480 mlir::Type llvmTy = converter->convertType(
attr.getType());
481 mlir::Location loc = parentOp->getLoc();
484 if (
attr.hasTrailingZeros()) {
485 mlir::Type arrayTy =
attr.getType();
486 result = mlir::LLVM::ZeroOp::create(rewriter, loc,
487 converter->convertType(arrayTy));
489 result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
493 if (
auto arrayAttr = mlir::dyn_cast<mlir::ArrayAttr>(
attr.getElts())) {
494 for (
auto [idx, elt] : llvm::enumerate(arrayAttr)) {
495 mlir::Value init = visit(elt);
497 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
499 }
else if (
auto strAttr = mlir::dyn_cast<mlir::StringAttr>(
attr.getElts())) {
502 auto arrayTy = mlir::dyn_cast<cir::ArrayType>(strAttr.getType());
503 assert(arrayTy &&
"String attribute must have an array type");
504 mlir::Type eltTy = arrayTy.getElementType();
505 for (
auto [idx, elt] : llvm::enumerate(strAttr)) {
506 auto init = mlir::LLVM::ConstantOp::create(
507 rewriter, loc, converter->convertType(eltTy), elt);
509 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
512 llvm_unreachable(
"unexpected ConstArrayAttr elements");
519mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstRecordAttr constRecord) {
520 const mlir::Type llvmTy = converter->convertType(constRecord.getType());
521 const mlir::Location loc = parentOp->getLoc();
522 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
525 for (
auto [idx, elt] : llvm::enumerate(constRecord.getMembers())) {
526 mlir::Value init = visit(elt);
528 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
535mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstVectorAttr attr) {
536 const mlir::Type llvmTy = converter->convertType(
attr.getType());
537 const mlir::Location loc = parentOp->getLoc();
539 SmallVector<mlir::Attribute> mlirValues;
540 for (
const mlir::Attribute elementAttr :
attr.getElts()) {
541 mlir::Attribute mlirAttr;
542 if (
auto intAttr = mlir::dyn_cast<cir::IntAttr>(elementAttr)) {
543 mlirAttr = rewriter.getIntegerAttr(
544 converter->convertType(intAttr.getType()), intAttr.getValue());
545 }
else if (
auto floatAttr = mlir::dyn_cast<cir::FPAttr>(elementAttr)) {
546 mlirAttr = rewriter.getFloatAttr(
547 converter->convertType(floatAttr.getType()), floatAttr.getValue());
550 "vector constant with an element that is neither an int nor a float");
552 mlirValues.push_back(mlirAttr);
555 return mlir::LLVM::ConstantOp::create(
556 rewriter, loc, llvmTy,
557 mlir::DenseElementsAttr::get(mlir::cast<mlir::ShapedType>(llvmTy),
562mlir::Value CIRAttrToValue::visitCirAttr(cir::GlobalViewAttr globalAttr) {
563 auto moduleOp = parentOp->getParentOfType<mlir::ModuleOp>();
564 mlir::DataLayout dataLayout(moduleOp);
565 mlir::Type sourceType;
566 unsigned sourceAddrSpace = 0;
567 llvm::StringRef symName;
568 mlir::Operation *sourceSymbol =
569 mlir::SymbolTable::lookupSymbolIn(moduleOp, globalAttr.getSymbol());
570 if (
auto llvmSymbol = dyn_cast<mlir::LLVM::GlobalOp>(sourceSymbol)) {
571 sourceType = llvmSymbol.getType();
572 symName = llvmSymbol.getSymName();
573 sourceAddrSpace = llvmSymbol.getAddrSpace();
574 }
else if (
auto cirSymbol = dyn_cast<cir::GlobalOp>(sourceSymbol)) {
577 symName = cirSymbol.getSymName();
578 if (
auto targetAS = mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
579 cirSymbol.getAddrSpaceAttr()))
580 sourceAddrSpace = targetAS.getValue();
581 }
else if (
auto llvmFun = dyn_cast<mlir::LLVM::LLVMFuncOp>(sourceSymbol)) {
582 sourceType = llvmFun.getFunctionType();
583 symName = llvmFun.getSymName();
584 }
else if (
auto fun = dyn_cast<cir::FuncOp>(sourceSymbol)) {
585 sourceType = converter->convertType(fun.getFunctionType());
586 symName = fun.getSymName();
587 }
else if (
auto alias = dyn_cast<mlir::LLVM::AliasOp>(sourceSymbol)) {
588 sourceType = alias.getType();
589 symName = alias.getSymName();
591 llvm_unreachable(
"Unexpected GlobalOp type");
594 mlir::Location loc = parentOp->getLoc();
595 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
597 mlir::LLVM::LLVMPointerType::get(rewriter.getContext(), sourceAddrSpace),
600 if (globalAttr.getIndices()) {
601 llvm::SmallVector<mlir::LLVM::GEPArg> indices;
603 if (mlir::isa<mlir::LLVM::LLVMArrayType, mlir::LLVM::LLVMStructType>(
605 indices.push_back(0);
607 for (mlir::Attribute idx : globalAttr.getIndices()) {
608 auto intAttr = mlir::cast<mlir::IntegerAttr>(idx);
609 indices.push_back(intAttr.getValue().getSExtValue());
611 mlir::Type resTy = addrOp.getType();
612 mlir::Type eltTy = converter->convertType(sourceType);
614 mlir::LLVM::GEPOp::create(rewriter, loc, resTy, eltTy, addrOp, indices,
615 mlir::LLVM::GEPNoWrapFlags::none);
622 if (
auto intTy = mlir::dyn_cast<cir::IntType>(globalAttr.getType())) {
623 mlir::Type llvmDstTy = converter->convertType(globalAttr.getType());
624 return mlir::LLVM::PtrToIntOp::create(rewriter, parentOp->getLoc(),
628 if (
auto ptrTy = mlir::dyn_cast<cir::PointerType>(globalAttr.getType())) {
629 auto llvmDstTy = converter->convertType<mlir::LLVM::LLVMPointerType>(ptrTy);
630 unsigned dstAddrSpace = llvmDstTy.getAddressSpace();
632 if (sourceAddrSpace != dstAddrSpace)
633 addrOp = mlir::LLVM::AddrSpaceCastOp::create(rewriter, parentOp->getLoc(),
636 mlir::Type llvmEltTy =
640 if (llvmEltTy == sourceType)
646 if (addrOp.getType() == llvmDstTy)
649 return mlir::LLVM::BitcastOp::create(rewriter, parentOp->getLoc(),
653 if (mlir::isa<cir::VPtrType>(globalAttr.getType()))
656 llvm_unreachable(
"Expecting pointer or integer type for GlobalViewAttr");
660mlir::Value CIRAttrToValue::visitCirAttr(cir::TypeInfoAttr typeInfoAttr) {
661 mlir::Type llvmTy = converter->convertType(typeInfoAttr.getType());
662 mlir::Location loc = parentOp->getLoc();
663 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
665 for (
auto [idx, elt] : llvm::enumerate(typeInfoAttr.getData())) {
666 mlir::Value init = visit(elt);
668 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
675mlir::Value CIRAttrToValue::visitCirAttr(cir::UndefAttr undefAttr) {
676 mlir::Location loc = parentOp->getLoc();
677 return mlir::LLVM::UndefOp::create(
678 rewriter, loc, converter->convertType(undefAttr.getType()));
682mlir::Value CIRAttrToValue::visitCirAttr(cir::PoisonAttr poisonAttr) {
683 mlir::Location loc = parentOp->getLoc();
684 return mlir::LLVM::PoisonOp::create(
685 rewriter, loc, converter->convertType(poisonAttr.getType()));
689mlir::Value CIRAttrToValue::visitCirAttr(cir::VTableAttr vtableArr) {
690 mlir::Type llvmTy = converter->convertType(vtableArr.getType());
691 mlir::Location loc = parentOp->getLoc();
692 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
694 for (
auto [idx, elt] : llvm::enumerate(vtableArr.getData())) {
695 mlir::Value init = visit(elt);
697 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
704mlir::Value CIRAttrToValue::visitCirAttr(cir::ZeroAttr attr) {
705 mlir::Location loc = parentOp->getLoc();
706 return mlir::LLVM::ZeroOp::create(rewriter, loc,
707 converter->convertType(
attr.getType()));
715 mlir::ConversionPatternRewriter &rewriter)
716 : llvmType(type), rewriter(rewriter) {}
719 return llvm::TypeSwitch<mlir::Attribute, mlir::Attribute>(
attr)
720 .Case<cir::IntAttr, cir::FPAttr, cir::BoolAttr>(
722 .
Default([&](
auto attrT) {
return mlir::Attribute(); });
726 return rewriter.getIntegerAttr(llvmType,
attr.getValue());
730 return rewriter.getFloatAttr(llvmType,
attr.getValue());
734 return rewriter.getBoolAttr(
attr.getValue());
739 mlir::ConversionPatternRewriter &rewriter;
747 :
public mlir::PassWrapper<ConvertCIRToLLVMPass,
748 mlir::OperationPass<mlir::ModuleOp>> {
750 registry.insert<mlir::BuiltinDialect, mlir::DLTIDialect,
751 mlir::LLVM::LLVMDialect, mlir::func::FuncDialect>();
769 return "Convert the prepared CIR dialect module to LLVM dialect";
772 StringRef
getArgument()
const override {
return "cir-flat-to-llvm"; }
776 struct CollectedAnnotation {
777 mlir::StringAttr symName;
778 cir::AnnotationAttr annotation;
780 CollectedAnnotation(mlir::StringAttr symName,
781 cir::AnnotationAttr annotation, mlir::Location loc)
782 : symName(symName), annotation(annotation), loc(loc) {}
787mlir::LogicalResult CIRToLLVMIsFPClassOpLowering::matchAndRewrite(
788 cir::IsFPClassOp op, OpAdaptor adaptor,
789 mlir::ConversionPatternRewriter &rewriter)
const {
790 mlir::Value src = adaptor.getSrc();
791 cir::FPClassTest flags = adaptor.getFlags();
792 mlir::IntegerType retTy = rewriter.getI1Type();
794 rewriter.replaceOpWithNewOp<mlir::LLVM::IsFPClass>(
795 op, retTy, src,
static_cast<uint32_t>(flags));
796 return mlir::success();
799mlir::LogicalResult CIRToLLVMSignBitOpLowering::matchAndRewrite(
800 cir::SignBitOp op, OpAdaptor adaptor,
801 mlir::ConversionPatternRewriter &rewriter)
const {
804 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
805 int width = layout.getTypeSizeInBits(op.getInput().getType());
806 if (
auto longDoubleType =
807 mlir::dyn_cast<cir::LongDoubleType>(op.getInput().getType())) {
808 if (mlir::isa<cir::FP80Type>(longDoubleType.getUnderlying())) {
816 mlir::Type intTy = mlir::IntegerType::get(rewriter.getContext(), width);
817 auto bitcast = mlir::LLVM::BitcastOp::create(rewriter, op->getLoc(), intTy,
820 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op->getLoc(), intTy, 0);
821 auto cmpResult = mlir::LLVM::ICmpOp::create(rewriter, op.getLoc(),
822 mlir::LLVM::ICmpPredicate::slt,
823 bitcast.getResult(), zero);
824 rewriter.replaceOp(op, cmpResult);
825 return mlir::success();
828mlir::LogicalResult CIRToLLVMAssumeOpLowering::matchAndRewrite(
829 cir::AssumeOp op, OpAdaptor adaptor,
830 mlir::ConversionPatternRewriter &rewriter)
const {
831 mlir::Value cond = adaptor.getPredicate();
832 if (op.getBundleKind() == cir::AssumeBundleKind::None) {
833 rewriter.replaceOpWithNewOp<mlir::LLVM::AssumeOp>(op, cond);
834 return mlir::success();
837 llvm::StringRef tag = cir::stringifyAssumeBundleKind(op.getBundleKind());
838 rewriter.replaceOpWithNewOp<mlir::LLVM::AssumeOp>(op, cond, tag,
839 adaptor.getBundleArgs());
840 return mlir::success();
843static mlir::LLVM::AtomicOrdering
846 return mlir::LLVM::AtomicOrdering::not_atomic;
848 case cir::MemOrder::Relaxed:
849 return mlir::LLVM::AtomicOrdering::monotonic;
850 case cir::MemOrder::Consume:
851 case cir::MemOrder::Acquire:
852 return mlir::LLVM::AtomicOrdering::acquire;
853 case cir::MemOrder::Release:
854 return mlir::LLVM::AtomicOrdering::release;
855 case cir::MemOrder::AcquireRelease:
856 return mlir::LLVM::AtomicOrdering::acq_rel;
857 case cir::MemOrder::SequentiallyConsistent:
858 return mlir::LLVM::AtomicOrdering::seq_cst;
860 llvm_unreachable(
"unknown memory order");
864 return syncScope == cir::SyncScopeKind::SingleThread ?
"singlethread" :
"";
867static std::optional<llvm::StringRef>
869 if (syncScope.has_value())
874mlir::LogicalResult CIRToLLVMAtomicCmpXchgOpLowering::matchAndRewrite(
875 cir::AtomicCmpXchgOp op, OpAdaptor adaptor,
876 mlir::ConversionPatternRewriter &rewriter)
const {
877 mlir::Value expected = adaptor.getExpected();
878 mlir::Value desired = adaptor.getDesired();
880 auto cmpxchg = mlir::LLVM::AtomicCmpXchgOp::create(
881 rewriter, op.getLoc(), adaptor.getPtr(), expected, desired,
886 cmpxchg.setAlignment(adaptor.getAlignment());
887 cmpxchg.setWeak(adaptor.getWeak());
888 cmpxchg.setVolatile_(adaptor.getIsVolatile());
891 auto old = mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(),
892 cmpxchg.getResult(), 0);
893 auto cmp = mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(),
894 cmpxchg.getResult(), 1);
896 rewriter.replaceOp(op, {old, cmp});
897 return mlir::success();
900mlir::LogicalResult CIRToLLVMAtomicXchgOpLowering::matchAndRewrite(
901 cir::AtomicXchgOp op, OpAdaptor adaptor,
902 mlir::ConversionPatternRewriter &rewriter)
const {
904 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(adaptor.getMemOrder());
906 rewriter.replaceOpWithNewOp<mlir::LLVM::AtomicRMWOp>(
907 op, mlir::LLVM::AtomicBinOp::xchg, adaptor.getPtr(), adaptor.getVal(),
908 llvmOrder, llvmSyncScope);
909 return mlir::success();
912mlir::LogicalResult CIRToLLVMAtomicTestAndSetOpLowering::matchAndRewrite(
913 cir::AtomicTestAndSetOp op, OpAdaptor adaptor,
914 mlir::ConversionPatternRewriter &rewriter)
const {
917 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
919 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
920 rewriter.getI8Type(), 1);
921 auto rmw = mlir::LLVM::AtomicRMWOp::create(
922 rewriter, op.getLoc(), mlir::LLVM::AtomicBinOp::xchg, adaptor.getPtr(),
923 one, llvmOrder, llvm::StringRef(),
924 adaptor.getAlignment().value_or(0), op.getIsVolatile());
926 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
927 rewriter.getI8Type(), 0);
928 auto cmp = mlir::LLVM::ICmpOp::create(
929 rewriter, op.getLoc(), mlir::LLVM::ICmpPredicate::ne, rmw, zero);
931 rewriter.replaceOp(op, cmp);
932 return mlir::success();
935mlir::LogicalResult CIRToLLVMAtomicClearOpLowering::matchAndRewrite(
936 cir::AtomicClearOp op, OpAdaptor adaptor,
937 mlir::ConversionPatternRewriter &rewriter)
const {
940 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
941 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
942 rewriter.getI8Type(), 0);
943 auto store = mlir::LLVM::StoreOp::create(
944 rewriter, op.getLoc(), zero, adaptor.getPtr(),
945 adaptor.getAlignment().value_or(0), op.getIsVolatile(),
946 false,
false, llvmOrder);
948 rewriter.replaceOp(op, store);
949 return mlir::success();
952mlir::LogicalResult CIRToLLVMAtomicFenceOpLowering::matchAndRewrite(
953 cir::AtomicFenceOp op, OpAdaptor adaptor,
954 mlir::ConversionPatternRewriter &rewriter)
const {
955 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(adaptor.getOrdering());
957 auto fence = mlir::LLVM::FenceOp::create(rewriter, op.getLoc(), llvmOrder);
960 rewriter.replaceOp(op, fence);
962 return mlir::success();
965static mlir::LLVM::AtomicBinOp
968 case cir::AtomicFetchKind::Add:
969 return isInt ? mlir::LLVM::AtomicBinOp::add : mlir::LLVM::AtomicBinOp::fadd;
970 case cir::AtomicFetchKind::Sub:
971 return isInt ? mlir::LLVM::AtomicBinOp::sub : mlir::LLVM::AtomicBinOp::fsub;
972 case cir::AtomicFetchKind::And:
973 return mlir::LLVM::AtomicBinOp::_and;
974 case cir::AtomicFetchKind::Xor:
975 return mlir::LLVM::AtomicBinOp::_xor;
976 case cir::AtomicFetchKind::Or:
977 return mlir::LLVM::AtomicBinOp::_or;
978 case cir::AtomicFetchKind::Nand:
979 return mlir::LLVM::AtomicBinOp::nand;
980 case cir::AtomicFetchKind::Max: {
982 return mlir::LLVM::AtomicBinOp::fmax;
983 return isSignedInt ? mlir::LLVM::AtomicBinOp::max
984 : mlir::LLVM::AtomicBinOp::umax;
986 case cir::AtomicFetchKind::Min: {
988 return mlir::LLVM::AtomicBinOp::fmin;
989 return isSignedInt ? mlir::LLVM::AtomicBinOp::min
990 : mlir::LLVM::AtomicBinOp::umin;
992 case cir::AtomicFetchKind::UIncWrap:
993 return mlir::LLVM::AtomicBinOp::uinc_wrap;
994 case cir::AtomicFetchKind::UDecWrap:
995 return mlir::LLVM::AtomicBinOp::udec_wrap;
997 llvm_unreachable(
"Unknown atomic fetch opcode");
1003 case cir::AtomicFetchKind::Add:
1004 return isInt ? mlir::LLVM::AddOp::getOperationName()
1005 : mlir::LLVM::FAddOp::getOperationName();
1006 case cir::AtomicFetchKind::Sub:
1007 return isInt ? mlir::LLVM::SubOp::getOperationName()
1008 : mlir::LLVM::FSubOp::getOperationName();
1009 case cir::AtomicFetchKind::And:
1010 return mlir::LLVM::AndOp::getOperationName();
1011 case cir::AtomicFetchKind::Xor:
1012 return mlir::LLVM::XOrOp::getOperationName();
1013 case cir::AtomicFetchKind::Or:
1014 return mlir::LLVM::OrOp::getOperationName();
1015 case cir::AtomicFetchKind::Nand:
1017 return mlir::LLVM::AndOp::getOperationName();
1018 case cir::AtomicFetchKind::Max:
1019 case cir::AtomicFetchKind::Min:
1020 llvm_unreachable(
"handled in buildMinMaxPostOp");
1021 case cir::AtomicFetchKind::UIncWrap:
1022 case cir::AtomicFetchKind::UDecWrap:
1023 llvm_unreachable(
"uinc_wrap and udec_wrap are always fetch_first");
1025 llvm_unreachable(
"Unknown atomic fetch opcode");
1028mlir::Value CIRToLLVMAtomicFetchOpLowering::buildPostOp(
1029 cir::AtomicFetchOp op, OpAdaptor adaptor,
1030 mlir::ConversionPatternRewriter &rewriter, mlir::Value rmwVal,
1035 .create(op.getLoc(),
1036 rewriter.getStringAttr(
1038 atomicOperands, atomicResTys, {})
1042mlir::Value CIRToLLVMAtomicFetchOpLowering::buildMinMaxPostOp(
1043 cir::AtomicFetchOp op, OpAdaptor adaptor,
1044 mlir::ConversionPatternRewriter &rewriter, mlir::Value rmwVal,
bool isInt,
1045 bool isSigned)
const {
1046 mlir::Location loc = op.getLoc();
1049 if (op.getBinop() == cir::AtomicFetchKind::Max)
1050 return mlir::LLVM::MaxNumOp::create(rewriter, loc, rmwVal,
1052 return mlir::LLVM::MinNumOp::create(rewriter, loc, rmwVal,
1056 mlir::LLVM::ICmpPredicate pred;
1057 if (op.getBinop() == cir::AtomicFetchKind::Max) {
1058 pred = isSigned ? mlir::LLVM::ICmpPredicate::sgt
1059 : mlir::LLVM::ICmpPredicate::ugt;
1061 pred = isSigned ? mlir::LLVM::ICmpPredicate::slt
1062 : mlir::LLVM::ICmpPredicate::ult;
1064 mlir::Value cmp = mlir::LLVM::ICmpOp::create(
1066 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(), pred), rmwVal,
1068 return mlir::LLVM::SelectOp::create(rewriter, loc, cmp, rmwVal,
1072mlir::LogicalResult CIRToLLVMAtomicFetchOpLowering::matchAndRewrite(
1073 cir::AtomicFetchOp op, OpAdaptor adaptor,
1074 mlir::ConversionPatternRewriter &rewriter)
const {
1076 bool isSignedInt =
false;
1077 if (
auto intTy = mlir::dyn_cast<cir::IntType>(op.getVal().getType())) {
1079 isSignedInt = intTy.isSigned();
1080 }
else if (mlir::isa<cir::SingleType, cir::DoubleType>(
1081 op.getVal().getType())) {
1084 return op.emitError() <<
"Unsupported type: " << op.getVal().getType();
1087 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
1089 mlir::LLVM::AtomicBinOp llvmBinOp =
1091 auto rmwVal = mlir::LLVM::AtomicRMWOp::create(
1092 rewriter, op.getLoc(), llvmBinOp, adaptor.getPtr(), adaptor.getVal(),
1093 llvmOrder, llvmSyncScope);
1095 mlir::Value result = rmwVal.getResult();
1096 if (!op.getFetchFirst()) {
1097 if (op.getBinop() == cir::AtomicFetchKind::Max ||
1098 op.getBinop() == cir::AtomicFetchKind::Min)
1099 result = buildMinMaxPostOp(op, adaptor, rewriter, rmwVal.getRes(), isInt,
1102 result = buildPostOp(op, adaptor, rewriter, rmwVal.getRes(), isInt);
1105 if (op.getBinop() == cir::AtomicFetchKind::Nand) {
1106 auto negOne = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1107 result.getType(), -1);
1108 result = mlir::LLVM::XOrOp::create(rewriter, op.getLoc(), result, negOne);
1112 rewriter.replaceOp(op, result);
1113 return mlir::success();
1116mlir::LogicalResult CIRToLLVMBitClrsbOpLowering::matchAndRewrite(
1117 cir::BitClrsbOp op, OpAdaptor adaptor,
1118 mlir::ConversionPatternRewriter &rewriter)
const {
1119 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1120 adaptor.getInput().getType(), 0);
1121 auto isNeg = mlir::LLVM::ICmpOp::create(
1122 rewriter, op.getLoc(),
1123 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(),
1124 mlir::LLVM::ICmpPredicate::slt),
1125 adaptor.getInput(), zero);
1127 auto negOne = mlir::LLVM::ConstantOp::create(
1128 rewriter, op.getLoc(), adaptor.getInput().getType(), -1);
1129 auto flipped = mlir::LLVM::XOrOp::create(rewriter, op.getLoc(),
1130 adaptor.getInput(), negOne);
1132 auto select = mlir::LLVM::SelectOp::create(rewriter, op.getLoc(), isNeg,
1133 flipped, adaptor.getInput());
1135 auto resTy = getTypeConverter()->convertType(op.getType());
1136 auto clz = mlir::LLVM::CountLeadingZerosOp::create(
1137 rewriter, op.getLoc(), resTy,
select,
false);
1139 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1140 auto res = mlir::LLVM::SubOp::create(rewriter, op.getLoc(),
clz, one,
1141 mlir::LLVM::IntegerOverflowFlags::nuw);
1142 rewriter.replaceOp(op, res);
1144 return mlir::LogicalResult::success();
1147mlir::LogicalResult CIRToLLVMBitClzOpLowering::matchAndRewrite(
1148 cir::BitClzOp op, OpAdaptor adaptor,
1149 mlir::ConversionPatternRewriter &rewriter)
const {
1150 auto resTy = getTypeConverter()->convertType(op.getType());
1151 auto llvmOp = mlir::LLVM::CountLeadingZerosOp::create(
1152 rewriter, op.getLoc(), resTy, adaptor.getInput(), op.getPoisonZero());
1153 rewriter.replaceOp(op, llvmOp);
1154 return mlir::LogicalResult::success();
1157mlir::LogicalResult CIRToLLVMBitCtzOpLowering::matchAndRewrite(
1158 cir::BitCtzOp op, OpAdaptor adaptor,
1159 mlir::ConversionPatternRewriter &rewriter)
const {
1160 auto resTy = getTypeConverter()->convertType(op.getType());
1161 auto llvmOp = mlir::LLVM::CountTrailingZerosOp::create(
1162 rewriter, op.getLoc(), resTy, adaptor.getInput(), op.getPoisonZero());
1163 rewriter.replaceOp(op, llvmOp);
1164 return mlir::LogicalResult::success();
1167mlir::LogicalResult CIRToLLVMBitFfsOpLowering::matchAndRewrite(
1168 cir::BitFfsOp op, OpAdaptor adaptor,
1169 mlir::ConversionPatternRewriter &rewriter)
const {
1170 auto resTy = getTypeConverter()->convertType(op.getType());
1171 auto ctz = mlir::LLVM::CountTrailingZerosOp::create(rewriter, op.getLoc(),
1172 resTy, adaptor.getInput(),
1175 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1176 auto ctzAddOne = mlir::LLVM::AddOp::create(rewriter, op.getLoc(),
ctz, one);
1178 auto zeroInputTy = mlir::LLVM::ConstantOp::create(
1179 rewriter, op.getLoc(), adaptor.getInput().getType(), 0);
1180 auto isZero = mlir::LLVM::ICmpOp::create(
1181 rewriter, op.getLoc(),
1182 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(),
1183 mlir::LLVM::ICmpPredicate::eq),
1184 adaptor.getInput(), zeroInputTy);
1186 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 0);
1187 auto res = mlir::LLVM::SelectOp::create(rewriter, op.getLoc(), isZero, zero,
1189 rewriter.replaceOp(op, res);
1191 return mlir::LogicalResult::success();
1194mlir::LogicalResult CIRToLLVMBitParityOpLowering::matchAndRewrite(
1195 cir::BitParityOp op, OpAdaptor adaptor,
1196 mlir::ConversionPatternRewriter &rewriter)
const {
1197 auto resTy = getTypeConverter()->convertType(op.getType());
1198 auto popcnt = mlir::LLVM::CtPopOp::create(rewriter, op.getLoc(), resTy,
1199 adaptor.getInput());
1201 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1203 mlir::LLVM::AndOp::create(rewriter, op.getLoc(), popcnt, one);
1204 rewriter.replaceOp(op, popcntMod2);
1206 return mlir::LogicalResult::success();
1209mlir::LogicalResult CIRToLLVMBitPopcountOpLowering::matchAndRewrite(
1210 cir::BitPopcountOp op, OpAdaptor adaptor,
1211 mlir::ConversionPatternRewriter &rewriter)
const {
1212 auto resTy = getTypeConverter()->convertType(op.getType());
1213 auto llvmOp = mlir::LLVM::CtPopOp::create(rewriter, op.getLoc(), resTy,
1214 adaptor.getInput());
1215 rewriter.replaceOp(op, llvmOp);
1216 return mlir::LogicalResult::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::Type CIRToLLVMCastOpLowering::convertTy(mlir::Type ty)
const {
1236 return getTypeConverter()->convertType(ty);
1239mlir::LogicalResult CIRToLLVMCastOpLowering::matchAndRewrite(
1240 cir::CastOp castOp, OpAdaptor adaptor,
1241 mlir::ConversionPatternRewriter &rewriter)
const {
1246 switch (castOp.getKind()) {
1247 case cir::CastKind::array_to_ptrdecay: {
1248 const auto ptrTy = mlir::cast<cir::PointerType>(castOp.getType());
1249 mlir::Value sourceValue = adaptor.getSrc();
1250 mlir::Type targetType = convertTy(ptrTy);
1252 ptrTy.getPointee());
1253 llvm::SmallVector<mlir::LLVM::GEPArg> offset{0};
1254 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1255 castOp, targetType, elementTy, sourceValue, offset);
1258 case cir::CastKind::int_to_bool: {
1259 mlir::Value llvmSrcVal = adaptor.getSrc();
1263 mlir::Value zeroInt = mlir::LLVM::ConstantOp::create(
1264 rewriter, castOp.getLoc(), llvmSrcVal.getType(),
1265 rewriter.getZeroAttr(llvmSrcVal.getType()));
1266 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
1267 castOp, mlir::LLVM::ICmpPredicate::ne, llvmSrcVal, zeroInt);
1270 case cir::CastKind::integral: {
1271 mlir::Type srcType = castOp.getSrc().getType();
1272 mlir::Type dstType = castOp.getType();
1273 mlir::Value llvmSrcVal = adaptor.getSrc();
1274 mlir::Type llvmDstType = getTypeConverter()->convertType(dstType);
1275 cir::IntType srcIntType =
1276 mlir::cast<cir::IntType>(elementTypeIfVector(srcType));
1277 cir::IntType dstIntType =
1278 mlir::cast<cir::IntType>(elementTypeIfVector(dstType));
1279 rewriter.replaceOp(castOp,
getLLVMIntCast(rewriter, llvmSrcVal, llvmDstType,
1280 srcIntType.isUnsigned(),
1281 srcIntType.getWidth(),
1282 dstIntType.getWidth()));
1285 case cir::CastKind::floating: {
1286 mlir::Value llvmSrcVal = adaptor.getSrc();
1287 mlir::Type llvmDstTy = getTypeConverter()->convertType(castOp.getType());
1289 mlir::Type srcTy = elementTypeIfVector(castOp.getSrc().getType());
1290 mlir::Type dstTy = elementTypeIfVector(castOp.getType());
1292 if (!mlir::isa<cir::FPTypeInterface>(dstTy) ||
1293 !mlir::isa<cir::FPTypeInterface>(srcTy))
1294 return castOp.emitError() <<
"NYI cast from " << srcTy <<
" to " << dstTy;
1296 auto getFloatWidth = [](mlir::Type ty) ->
unsigned {
1297 return mlir::cast<cir::FPTypeInterface>(ty).getWidth();
1300 if (getFloatWidth(srcTy) > getFloatWidth(dstTy))
1301 rewriter.replaceOpWithNewOp<mlir::LLVM::FPTruncOp>(castOp, llvmDstTy,
1304 rewriter.replaceOpWithNewOp<mlir::LLVM::FPExtOp>(castOp, llvmDstTy,
1306 return mlir::success();
1308 case cir::CastKind::int_to_ptr: {
1309 auto dstTy = mlir::cast<cir::PointerType>(castOp.getType());
1310 mlir::Value llvmSrcVal = adaptor.getSrc();
1311 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1312 rewriter.replaceOpWithNewOp<mlir::LLVM::IntToPtrOp>(castOp, llvmDstTy,
1314 return mlir::success();
1316 case cir::CastKind::ptr_to_int: {
1317 auto dstTy = mlir::cast<cir::IntType>(castOp.getType());
1318 mlir::Value llvmSrcVal = adaptor.getSrc();
1319 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1320 rewriter.replaceOpWithNewOp<mlir::LLVM::PtrToIntOp>(castOp, llvmDstTy,
1322 return mlir::success();
1324 case cir::CastKind::float_to_bool: {
1325 mlir::Value llvmSrcVal = adaptor.getSrc();
1326 auto kind = mlir::LLVM::FCmpPredicate::une;
1331 auto zeroFloat = mlir::LLVM::ConstantOp::create(
1332 rewriter, castOp.getLoc(), llvmSrcVal.getType(),
1333 rewriter.getZeroAttr(llvmSrcVal.getType()));
1336 rewriter.replaceOpWithNewOp<mlir::LLVM::FCmpOp>(castOp,
kind, llvmSrcVal,
1339 return mlir::success();
1341 case cir::CastKind::bool_to_int: {
1342 mlir::Type dstTy = castOp.getType();
1343 mlir::Value llvmSrcVal = adaptor.getSrc();
1344 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1346 auto srcElemTy = mlir::cast<mlir::IntegerType>(
1347 elementTypeIfVector(llvmSrcVal.getType()));
1348 auto dstElemTy = mlir::cast<cir::IntType>(elementTypeIfVector(dstTy));
1350 if (srcElemTy.getWidth() == dstElemTy.getWidth())
1351 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(castOp, llvmDstTy,
1354 rewriter.replaceOpWithNewOp<mlir::LLVM::ZExtOp>(castOp, llvmDstTy,
1356 return mlir::success();
1358 case cir::CastKind::bool_to_float: {
1359 mlir::Type dstTy = castOp.getType();
1360 mlir::Value llvmSrcVal = adaptor.getSrc();
1361 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1362 rewriter.replaceOpWithNewOp<mlir::LLVM::UIToFPOp>(castOp, llvmDstTy,
1364 return mlir::success();
1366 case cir::CastKind::int_to_float: {
1367 mlir::Type dstTy = castOp.getType();
1368 mlir::Value llvmSrcVal = adaptor.getSrc();
1369 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1370 if (mlir::cast<cir::IntType>(elementTypeIfVector(castOp.getSrc().getType()))
1372 rewriter.replaceOpWithNewOp<mlir::LLVM::SIToFPOp>(castOp, llvmDstTy,
1375 rewriter.replaceOpWithNewOp<mlir::LLVM::UIToFPOp>(castOp, llvmDstTy,
1377 return mlir::success();
1379 case cir::CastKind::float_to_int: {
1380 mlir::Type dstTy = castOp.getType();
1381 mlir::Value llvmSrcVal = adaptor.getSrc();
1382 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1383 if (mlir::cast<cir::IntType>(elementTypeIfVector(castOp.getType()))
1385 rewriter.replaceOpWithNewOp<mlir::LLVM::FPToSIOp>(castOp, llvmDstTy,
1388 rewriter.replaceOpWithNewOp<mlir::LLVM::FPToUIOp>(castOp, llvmDstTy,
1390 return mlir::success();
1392 case cir::CastKind::bitcast: {
1393 mlir::Type dstTy = castOp.getType();
1394 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1399 mlir::Value llvmSrcVal = adaptor.getSrc();
1400 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(castOp, llvmDstTy,
1402 return mlir::success();
1404 case cir::CastKind::ptr_to_bool: {
1405 mlir::Value llvmSrcVal = adaptor.getSrc();
1406 mlir::Value zeroPtr = mlir::LLVM::ZeroOp::create(rewriter, castOp.getLoc(),
1407 llvmSrcVal.getType());
1408 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
1409 castOp, mlir::LLVM::ICmpPredicate::ne, llvmSrcVal, zeroPtr);
1412 case cir::CastKind::address_space: {
1413 mlir::Type dstTy = castOp.getType();
1414 mlir::Value llvmSrcVal = adaptor.getSrc();
1415 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1416 rewriter.replaceOpWithNewOp<mlir::LLVM::AddrSpaceCastOp>(castOp, llvmDstTy,
1420 case cir::CastKind::member_ptr_to_bool:
1425 return castOp.emitError(
"Unhandled cast kind: ")
1426 << castOp.getKindAttrName();
1430 return mlir::success();
1434 mlir::ModuleOp mod, mlir::Value index,
1435 mlir::Type baseTy, cir::IntType strideTy) {
1436 mlir::Operation *indexOp = index.getDefiningOp();
1440 auto indexType = mlir::cast<mlir::IntegerType>(index.getType());
1441 mlir::DataLayout llvmLayout(mod);
1442 std::optional<uint64_t> layoutWidth = llvmLayout.getTypeIndexBitwidth(baseTy);
1445 if (!layoutWidth || *layoutWidth == indexType.getWidth())
1451 auto sub = dyn_cast<mlir::LLVM::SubOp>(indexOp);
1452 bool rewriteSub =
false;
1455 dyn_cast<mlir::LLVM::ConstantOp>(sub.getLhs().getDefiningOp())) {
1456 auto lhsConstInt = mlir::dyn_cast<mlir::IntegerAttr>(lhsConst.getValue());
1457 if (lhsConstInt && lhsConstInt.getValue() == 0) {
1458 index = sub.getRhs();
1464 auto llvmDstType = rewriter.getIntegerType(*layoutWidth);
1465 bool isUnsigned = strideTy && strideTy.isUnsigned();
1467 indexType.getWidth(), *layoutWidth);
1470 index = mlir::LLVM::SubOp::create(
1471 rewriter, index.getLoc(),
1472 mlir::LLVM::ConstantOp::create(rewriter, index.getLoc(),
1473 index.getType(), 0),
1476 rewriter.eraseOp(sub);
1482mlir::LogicalResult CIRToLLVMPtrStrideOpLowering::matchAndRewrite(
1483 cir::PtrStrideOp ptrStrideOp, OpAdaptor adaptor,
1484 mlir::ConversionPatternRewriter &rewriter)
const {
1486 const mlir::TypeConverter *tc = getTypeConverter();
1487 const mlir::Type resultTy = tc->convertType(ptrStrideOp.getType());
1489 mlir::Type elementTy =
1494 if (mlir::isa<mlir::LLVM::LLVMVoidType>(elementTy) ||
1495 mlir::isa<mlir::LLVM::LLVMFunctionType>(elementTy))
1496 elementTy = mlir::IntegerType::get(elementTy.getContext(), 8,
1497 mlir::IntegerType::Signless);
1499 mlir::Value index = adaptor.getStride();
1501 rewriter, ptrStrideOp->getParentOfType<mlir::ModuleOp>(), index,
1502 adaptor.getBase().getType(),
1503 dyn_cast<cir::IntType>(ptrStrideOp.getOperand(1).getType()));
1505 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1506 ptrStrideOp, resultTy, elementTy, adaptor.getBase(), index);
1507 return mlir::success();
1510mlir::LogicalResult CIRToLLVMGetElementOpLowering::matchAndRewrite(
1511 cir::GetElementOp op, OpAdaptor adaptor,
1512 mlir::ConversionPatternRewriter &rewriter)
const {
1514 mlir::dyn_cast<cir::ArrayType>(op.getBaseType().getPointee())) {
1515 const mlir::TypeConverter *converter = getTypeConverter();
1516 const mlir::Type llArrayTy = converter->convertType(arrayTy);
1517 const mlir::Type llResultTy = converter->convertType(op.getType());
1518 mlir::Type elementTy =
1523 if (mlir::isa<mlir::LLVM::LLVMVoidType>(elementTy) ||
1524 mlir::isa<mlir::LLVM::LLVMFunctionType>(elementTy))
1525 elementTy = rewriter.getIntegerType(8);
1527 mlir::Value index = adaptor.getIndex();
1530 adaptor.getBase().getType(),
1531 dyn_cast<cir::IntType>(op.getOperand(1).getType()));
1536 std::array<mlir::LLVM::GEPArg, 2> offset{0, index};
1537 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, llResultTy, llArrayTy,
1538 adaptor.getBase(), offset);
1539 return mlir::success();
1542 op.emitError() <<
"NYI: GetElementOp lowering to LLVM for non-array";
1543 return mlir::failure();
1546mlir::LogicalResult CIRToLLVMBaseClassAddrOpLowering::matchAndRewrite(
1547 cir::BaseClassAddrOp baseClassOp, OpAdaptor adaptor,
1548 mlir::ConversionPatternRewriter &rewriter)
const {
1549 const mlir::Type resultType =
1550 getTypeConverter()->convertType(baseClassOp.getType());
1551 mlir::Value derivedAddr = adaptor.getDerivedAddr();
1552 llvm::SmallVector<mlir::LLVM::GEPArg, 1> offset = {
1553 adaptor.getOffset().getZExtValue()};
1554 mlir::Type byteType = mlir::IntegerType::get(resultType.getContext(), 8,
1555 mlir::IntegerType::Signless);
1556 if (adaptor.getOffset().getZExtValue() == 0) {
1557 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(
1558 baseClassOp, resultType, adaptor.getDerivedAddr());
1559 return mlir::success();
1562 if (baseClassOp.getAssumeNotNull()) {
1563 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1564 baseClassOp, resultType, byteType, derivedAddr, offset);
1566 auto loc = baseClassOp.getLoc();
1567 mlir::Value isNull = mlir::LLVM::ICmpOp::create(
1568 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, derivedAddr,
1569 mlir::LLVM::ZeroOp::create(rewriter, loc, derivedAddr.getType()));
1570 mlir::Value adjusted = mlir::LLVM::GEPOp::create(
1571 rewriter, loc, resultType, byteType, derivedAddr, offset);
1572 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(baseClassOp, isNull,
1573 derivedAddr, adjusted);
1575 return mlir::success();
1578mlir::LogicalResult CIRToLLVMDerivedClassAddrOpLowering::matchAndRewrite(
1579 cir::DerivedClassAddrOp derivedClassOp, OpAdaptor adaptor,
1580 mlir::ConversionPatternRewriter &rewriter)
const {
1581 const mlir::Type resultType =
1582 getTypeConverter()->convertType(derivedClassOp.getType());
1583 mlir::Value baseAddr = adaptor.getBaseAddr();
1586 int64_t offsetVal = -(adaptor.getOffset().getZExtValue());
1587 if (offsetVal == 0) {
1589 rewriter.replaceOp(derivedClassOp, baseAddr);
1590 return mlir::success();
1592 llvm::SmallVector<mlir::LLVM::GEPArg, 1> offset = {offsetVal};
1593 mlir::Type byteType = mlir::IntegerType::get(resultType.getContext(), 8,
1594 mlir::IntegerType::Signless);
1595 if (derivedClassOp.getAssumeNotNull()) {
1596 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1597 derivedClassOp, resultType, byteType, baseAddr, offset,
1598 mlir::LLVM::GEPNoWrapFlags::inbounds);
1600 mlir::Location loc = derivedClassOp.getLoc();
1601 mlir::Value isNull = mlir::LLVM::ICmpOp::create(
1602 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, baseAddr,
1603 mlir::LLVM::ZeroOp::create(rewriter, loc, baseAddr.getType()));
1604 mlir::Value adjusted =
1605 mlir::LLVM::GEPOp::create(rewriter, loc, resultType, byteType, baseAddr,
1606 offset, mlir::LLVM::GEPNoWrapFlags::inbounds);
1607 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(derivedClassOp, isNull,
1608 baseAddr, adjusted);
1610 return mlir::success();
1613mlir::LogicalResult CIRToLLVMFMaxNumOpLowering::matchAndRewrite(
1614 cir::FMaxNumOp op, OpAdaptor adaptor,
1615 mlir::ConversionPatternRewriter &rewriter)
const {
1616 mlir::Type resTy = typeConverter->convertType(op.getType());
1617 rewriter.replaceOpWithNewOp<mlir::LLVM::MaxNumOp>(
1618 op, resTy, adaptor.getLhs(), adaptor.getRhs(),
1619 mlir::LLVM::FastmathFlags::nsz);
1620 return mlir::success();
1623mlir::LogicalResult CIRToLLVMFMinNumOpLowering::matchAndRewrite(
1624 cir::FMinNumOp op, OpAdaptor adaptor,
1625 mlir::ConversionPatternRewriter &rewriter)
const {
1626 mlir::Type resTy = typeConverter->convertType(op.getType());
1627 rewriter.replaceOpWithNewOp<mlir::LLVM::MinNumOp>(
1628 op, resTy, adaptor.getLhs(), adaptor.getRhs(),
1629 mlir::LLVM::FastmathFlags::nsz);
1630 return mlir::success();
1633mlir::LogicalResult CIRToLLVMAllocaOpLowering::matchAndRewrite(
1634 cir::AllocaOp op, OpAdaptor adaptor,
1635 mlir::ConversionPatternRewriter &rewriter)
const {
1638 ? adaptor.getDynAllocSize()
1639 : mlir::LLVM::ConstantOp::create(
1640 rewriter, op.getLoc(),
1641 typeConverter->convertType(rewriter.getIndexType()), 1);
1642 mlir::Type elementTy =
1644 mlir::Type resultTy =
1650 rewriter.replaceOpWithNewOp<mlir::LLVM::AllocaOp>(op, resultTy, elementTy,
1651 size, op.getAlignment());
1653 return mlir::success();
1656mlir::LogicalResult CIRToLLVMRotateOpLowering::matchAndRewrite(
1657 cir::RotateOp op, OpAdaptor adaptor,
1658 mlir::ConversionPatternRewriter &rewriter)
const {
1661 mlir::Value input = adaptor.getInput();
1662 if (op.isRotateLeft())
1663 rewriter.replaceOpWithNewOp<mlir::LLVM::FshlOp>(op, input, input,
1664 adaptor.getAmount());
1666 rewriter.replaceOpWithNewOp<mlir::LLVM::FshrOp>(op, input, input,
1667 adaptor.getAmount());
1668 return mlir::LogicalResult::success();
1673 for (mlir::NamedAttribute attr : op->getAttrs()) {
1674 if (attr.getName() == CIRDialect::getCalleeAttrName() ||
1675 attr.getName() == CIRDialect::getSideEffectAttrName() ||
1676 attr.getName() == CIRDialect::getNoThrowAttrName() ||
1677 attr.getName() == CIRDialect::getNoUnwindAttrName() ||
1678 attr.getName() == CIRDialect::getNoReturnAttrName() ||
1679 attr.getName() == CIRDialect::getMustTailAttrName())
1683 result.push_back(attr);
1687static mlir::LogicalResult
1689 mlir::ConversionPatternRewriter &rewriter,
1690 const mlir::TypeConverter *converter,
1691 mlir::SymbolTableCollection &symbolTables,
1692 mlir::FlatSymbolRefAttr calleeAttr,
1693 mlir::Block *continueBlock =
nullptr,
1694 mlir::Block *landingPadBlock =
nullptr) {
1696 mlir::ValueTypeRange<mlir::ResultRange> cirResults = op->getResultTypes();
1697 auto call = cast<cir::CIRCallOpInterface>(op);
1699 if (converter->convertTypes(cirResults, llvmResults).failed())
1700 return mlir::failure();
1704 mlir::LLVM::MemoryEffectsAttr memoryEffects;
1705 bool noUnwind =
false;
1706 bool willReturn =
false;
1707 bool noReturn =
false;
1709 memoryEffects, noUnwind, willReturn, noReturn);
1714 mlir::LLVM::LLVMFunctionType llvmFnTy;
1721 mlir::Operation *callee =
1722 symbolTables.lookupNearestSymbolFrom(op, calleeAttr);
1723 if (
auto fn = mlir::dyn_cast<mlir::FunctionOpInterface>(callee)) {
1724 llvmFnTy = converter->convertType<mlir::LLVM::LLVMFunctionType>(
1725 fn.getFunctionType());
1726 assert(llvmFnTy &&
"Failed to convert function type");
1727 }
else if (
auto alias = mlir::cast<mlir::LLVM::AliasOp>(callee)) {
1735 auto symAttr = mlir::cast<mlir::FlatSymbolRefAttr>(calleeAttr);
1737 mlir::LLVM::AddressOfOp::create(
1738 rewriter, op->getLoc(),
1739 mlir::LLVM::LLVMPointerType::get(rewriter.getContext()), symAttr)
1741 adjustedCallOperands.push_back(addrOfAlias);
1744 llvm::append_range(adjustedCallOperands, callOperands);
1745 callOperands = adjustedCallOperands;
1749 llvmFnTy = mlir::cast<mlir::LLVM::LLVMFunctionType>(alias.getType());
1752 return op->emitError(
"Unexpected callee type!");
1755 assert(!op->getOperands().empty() &&
1756 "operands list must no be empty for the indirect call");
1757 auto calleeTy = op->getOperands().front().getType();
1758 auto calleePtrTy = cast<cir::PointerType>(calleeTy);
1759 auto calleeFuncTy = cast<cir::FuncType>(calleePtrTy.getPointee());
1760 llvm::append_range(adjustedCallOperands, callOperands);
1761 llvmFnTy = cast<mlir::LLVM::LLVMFunctionType>(
1762 converter->convertType(calleeFuncTy));
1767 if (landingPadBlock) {
1768 auto newOp = rewriter.replaceOpWithNewOp<mlir::LLVM::InvokeOp>(
1769 op, llvmFnTy, calleeAttr, callOperands, continueBlock,
1770 mlir::ValueRange{}, landingPadBlock, mlir::ValueRange{});
1771 newOp->setAttrs(attributes);
1773 auto newOp = rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(
1774 op, llvmFnTy, calleeAttr, callOperands);
1775 newOp->setAttrs(attributes);
1777 newOp.setMemoryEffectsAttr(memoryEffects);
1778 newOp.setNoUnwind(noUnwind);
1779 newOp.setWillReturn(willReturn);
1780 newOp.setNoreturn(noReturn);
1781 if (op->hasAttr(CIRDialect::getMustTailAttrName()))
1782 newOp.setTailCallKind(mlir::LLVM::TailCallKind::MustTail);
1785 return mlir::success();
1788mlir::LogicalResult CIRToLLVMCallOpLowering::matchAndRewrite(
1789 cir::CallOp op, OpAdaptor adaptor,
1790 mlir::ConversionPatternRewriter &rewriter)
const {
1792 getTypeConverter(), symbolTables,
1793 op.getCalleeAttr());
1796mlir::LogicalResult CIRToLLVMTryCallOpLowering::matchAndRewrite(
1797 cir::TryCallOp op, OpAdaptor adaptor,
1798 mlir::ConversionPatternRewriter &rewriter)
const {
1801 op.getOperation(), adaptor.getOperands(), rewriter, getTypeConverter(),
1802 symbolTables, op.getCalleeAttr(), op.getNormalDest(), op.getUnwindDest());
1805mlir::LogicalResult CIRToLLVMReturnAddrOpLowering::matchAndRewrite(
1806 cir::ReturnAddrOp op, OpAdaptor adaptor,
1807 mlir::ConversionPatternRewriter &rewriter)
const {
1808 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
1810 llvmPtrTy, adaptor.getOperands());
1811 return mlir::success();
1814mlir::LogicalResult CIRToLLVMFrameAddrOpLowering::matchAndRewrite(
1815 cir::FrameAddrOp op, OpAdaptor adaptor,
1816 mlir::ConversionPatternRewriter &rewriter)
const {
1817 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
1819 adaptor.getOperands());
1820 return mlir::success();
1823mlir::LogicalResult CIRToLLVMClearCacheOpLowering::matchAndRewrite(
1824 cir::ClearCacheOp op, OpAdaptor adaptor,
1825 mlir::ConversionPatternRewriter &rewriter)
const {
1826 mlir::Value begin = adaptor.getBegin();
1827 mlir::Value end = adaptor.getEnd();
1828 auto intrinNameAttr =
1829 mlir::StringAttr::get(op.getContext(),
"llvm.clear_cache");
1830 rewriter.replaceOpWithNewOp<mlir::LLVM::CallIntrinsicOp>(
1831 op, mlir::Type{}, intrinNameAttr, mlir::ValueRange{begin, end});
1833 return mlir::success();
1836mlir::LogicalResult CIRToLLVMAddrOfReturnAddrOpLowering::matchAndRewrite(
1837 cir::AddrOfReturnAddrOp op, OpAdaptor adaptor,
1838 mlir::ConversionPatternRewriter &rewriter)
const {
1839 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
1841 llvmPtrTy, adaptor.getOperands());
1842 return mlir::success();
1845mlir::LogicalResult CIRToLLVMLoadOpLowering::matchAndRewrite(
1846 cir::LoadOp op, OpAdaptor adaptor,
1847 mlir::ConversionPatternRewriter &rewriter)
const {
1848 const mlir::Type llvmTy =
1850 mlir::LLVM::AtomicOrdering ordering =
getLLVMMemOrder(op.getMemOrder());
1851 std::optional<size_t> opAlign = op.getAlignment();
1852 unsigned alignment =
1853 (unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmTy));
1860 std::optional<llvm::StringRef> llvmSyncScope =
1863 mlir::LLVM::LoadOp newLoad = mlir::LLVM::LoadOp::create(
1864 rewriter, op->getLoc(), llvmTy, adaptor.getAddr(), alignment,
1865 op.getIsVolatile(),
false,
1866 false,
false, ordering,
1867 llvmSyncScope.value_or(std::string()));
1870 mlir::Value result =
1872 rewriter.replaceOp(op, result);
1874 return mlir::LogicalResult::success();
1878cir::direct::CIRToLLVMVecMaskedLoadOpLowering::matchAndRewrite(
1879 cir::VecMaskedLoadOp op, OpAdaptor adaptor,
1880 mlir::ConversionPatternRewriter &rewriter)
const {
1881 const mlir::Type llvmResTy =
1884 std::optional<size_t> opAlign = op.getAlignment();
1885 unsigned alignment =
1886 (unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmResTy));
1888 mlir::IntegerAttr alignAttr = rewriter.getI32IntegerAttr(alignment);
1890 auto newLoad = mlir::LLVM::MaskedLoadOp::create(
1891 rewriter, op.getLoc(), llvmResTy, adaptor.getAddr(), adaptor.getMask(),
1892 adaptor.getPassThru(), alignAttr);
1894 rewriter.replaceOp(op, newLoad.getResult());
1895 return mlir::success();
1898mlir::LogicalResult CIRToLLVMStoreOpLowering::matchAndRewrite(
1899 cir::StoreOp op, OpAdaptor adaptor,
1900 mlir::ConversionPatternRewriter &rewriter)
const {
1901 mlir::LLVM::AtomicOrdering memorder =
getLLVMMemOrder(op.getMemOrder());
1902 const mlir::Type llvmTy =
1903 getTypeConverter()->convertType(op.getValue().getType());
1904 std::optional<size_t> opAlign = op.getAlignment();
1905 unsigned alignment =
1906 (unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmTy));
1912 op.getValue().getType(), adaptor.getValue());
1917 std::optional<llvm::StringRef> llvmSyncScope =
1920 mlir::LLVM::StoreOp storeOp = mlir::LLVM::StoreOp::create(
1921 rewriter, op->getLoc(), value, adaptor.getAddr(), alignment,
1923 false,
false, memorder,
1924 llvmSyncScope.value_or(std::string()));
1925 rewriter.replaceOp(op, storeOp);
1927 return mlir::LogicalResult::success();
1931 while (
auto arrTy = mlir::dyn_cast<cir::ArrayType>(ty))
1932 ty = arrTy.getElementType();
1937 return mlir::isa<cir::PointerType, cir::IntType, cir::BoolType,
1938 cir::FPTypeInterface>(baseElemTy);
1941mlir::LogicalResult CIRToLLVMConstantOpLowering::matchAndRewrite(
1942 cir::ConstantOp op, OpAdaptor adaptor,
1943 mlir::ConversionPatternRewriter &rewriter)
const {
1944 mlir::Attribute attr = op.getValue();
1946 if (mlir::isa<cir::PoisonAttr>(attr)) {
1947 rewriter.replaceOpWithNewOp<mlir::LLVM::PoisonOp>(
1948 op, getTypeConverter()->convertType(op.getType()));
1949 return mlir::success();
1952 if (mlir::isa<cir::UndefAttr>(attr)) {
1953 rewriter.replaceOpWithNewOp<mlir::LLVM::UndefOp>(
1954 op, getTypeConverter()->convertType(op.getType()));
1955 return mlir::success();
1958 if (mlir::isa<mlir::IntegerType>(op.getType())) {
1963 attr = op.getValue();
1964 }
else if (mlir::isa<cir::BoolType>(op.getType())) {
1965 int value = mlir::cast<cir::BoolAttr>(op.getValue()).getValue();
1966 attr = rewriter.getIntegerAttr(typeConverter->convertType(op.getType()),
1968 }
else if (mlir::isa<cir::IntType>(op.getType())) {
1970 if (
auto ga = mlir::dyn_cast<cir::GlobalViewAttr>(op.getValue())) {
1976 op.emitError() <<
"global view with integer type";
1977 return mlir::failure();
1980 attr = rewriter.getIntegerAttr(
1981 typeConverter->convertType(op.getType()),
1982 mlir::cast<cir::IntAttr>(op.getValue()).getValue());
1983 }
else if (mlir::isa<cir::FPTypeInterface>(op.getType())) {
1984 attr = rewriter.getFloatAttr(
1985 typeConverter->convertType(op.getType()),
1986 mlir::cast<cir::FPAttr>(op.getValue()).getValue());
1987 }
else if (mlir::isa<cir::PointerType>(op.getType())) {
1989 if (mlir::isa<cir::ConstPtrAttr>(op.getValue())) {
1990 if (mlir::cast<cir::ConstPtrAttr>(op.getValue()).isNullValue()) {
1991 rewriter.replaceOpWithNewOp<mlir::LLVM::ZeroOp>(
1992 op, typeConverter->convertType(op.getType()));
1993 return mlir::success();
1997 if (
auto gv = mlir::dyn_cast<cir::GlobalViewAttr>(op.getValue())) {
1999 rewriter.replaceOp(op, newOp);
2000 return mlir::success();
2002 attr = op.getValue();
2003 }
else if (
const auto arrTy = mlir::dyn_cast<cir::ArrayType>(op.getType())) {
2004 const auto constArr = mlir::dyn_cast<cir::ConstArrayAttr>(op.getValue());
2005 if (!constArr && !isa<cir::ZeroAttr, cir::UndefAttr>(op.getValue()))
2006 return op.emitError() <<
"array does not have a constant initializer";
2008 std::optional<mlir::Attribute> denseAttr;
2011 attr = denseAttr.value();
2013 const mlir::Value initVal =
2015 rewriter.replaceOp(op, initVal);
2016 return mlir::success();
2018 }
else if (
const auto recordAttr =
2019 mlir::dyn_cast<cir::ConstRecordAttr>(op.getValue())) {
2021 rewriter.replaceOp(op, initVal);
2022 return mlir::success();
2023 }
else if (
const auto vecTy = mlir::dyn_cast<cir::VectorType>(op.getType())) {
2025 getTypeConverter()));
2026 return mlir::success();
2027 }
else if (mlir::isa<cir::RecordType>(op.getType())) {
2028 if (mlir::isa<cir::ZeroAttr, cir::UndefAttr>(attr)) {
2029 mlir::Value initVal =
2031 rewriter.replaceOp(op, initVal);
2032 return mlir::success();
2034 return op.emitError() <<
"unsupported lowering for record constant type "
2036 }
else if (
auto complexTy = mlir::dyn_cast<cir::ComplexType>(op.getType())) {
2037 mlir::Type complexElemTy = complexTy.getElementType();
2038 mlir::Type complexElemLLVMTy = typeConverter->convertType(complexElemTy);
2040 if (
auto zeroInitAttr = mlir::dyn_cast<cir::ZeroAttr>(op.getValue())) {
2041 mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(complexElemLLVMTy);
2042 mlir::ArrayAttr array = rewriter.getArrayAttr({zeroAttr, zeroAttr});
2043 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
2044 op, getTypeConverter()->convertType(op.getType()), array);
2045 return mlir::success();
2048 if (mlir::isa<cir::UndefAttr>(op.getValue())) {
2049 rewriter.replaceOpWithNewOp<mlir::LLVM::UndefOp>(
2050 op, getTypeConverter()->convertType(op.getType()));
2051 return mlir::success();
2054 auto complexAttr = mlir::cast<cir::ConstComplexAttr>(op.getValue());
2056 mlir::Attribute components[2];
2057 if (mlir::isa<cir::IntType>(complexElemTy)) {
2058 components[0] = rewriter.getIntegerAttr(
2060 mlir::cast<cir::IntAttr>(complexAttr.getReal()).getValue());
2061 components[1] = rewriter.getIntegerAttr(
2063 mlir::cast<cir::IntAttr>(complexAttr.getImag()).getValue());
2065 components[0] = rewriter.getFloatAttr(
2067 mlir::cast<cir::FPAttr>(complexAttr.getReal()).getValue());
2068 components[1] = rewriter.getFloatAttr(
2070 mlir::cast<cir::FPAttr>(complexAttr.getImag()).getValue());
2073 attr = rewriter.getArrayAttr(components);
2075 return op.emitError() <<
"unsupported constant type " << op.getType();
2078 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
2079 op, getTypeConverter()->convertType(op.getType()),
attr);
2081 return mlir::success();
2085 mlir::DataLayout layout(op.getParentOfType<mlir::ModuleOp>());
2087 if (isa<cir::VoidType>(type))
2088 type = cir::IntType::get(type.getContext(), 8,
false);
2089 return llvm::divideCeil(layout.getTypeSizeInBits(type), 8);
2092mlir::LogicalResult CIRToLLVMPrefetchOpLowering::matchAndRewrite(
2093 cir::PrefetchOp op, OpAdaptor adaptor,
2094 mlir::ConversionPatternRewriter &rewriter)
const {
2095 rewriter.replaceOpWithNewOp<mlir::LLVM::Prefetch>(
2096 op, adaptor.getAddr(), adaptor.getIsWrite(), adaptor.getLocality(),
2098 return mlir::success();
2101mlir::LogicalResult CIRToLLVMPtrDiffOpLowering::matchAndRewrite(
2102 cir::PtrDiffOp op, OpAdaptor adaptor,
2103 mlir::ConversionPatternRewriter &rewriter)
const {
2104 auto dstTy = mlir::cast<cir::IntType>(op.getType());
2105 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
2107 auto lhs = mlir::LLVM::PtrToIntOp::create(rewriter, op.getLoc(), llvmDstTy,
2109 auto rhs = mlir::LLVM::PtrToIntOp::create(rewriter, op.getLoc(), llvmDstTy,
2113 mlir::LLVM::SubOp::create(rewriter, op.getLoc(), llvmDstTy, lhs, rhs);
2115 cir::PointerType ptrTy = op.getLhs().getType();
2117 uint64_t typeSize =
getTypeSize(ptrTy.getPointee(), *op);
2120 mlir::Value resultVal = diff.getResult();
2121 if (typeSize != 1) {
2122 auto typeSizeVal = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
2123 llvmDstTy, typeSize);
2125 if (dstTy.isUnsigned()) {
2127 mlir::LLVM::UDivOp::create(rewriter, op.getLoc(), diff, typeSizeVal);
2128 uDiv.setIsExact(
true);
2129 resultVal = uDiv.getResult();
2132 mlir::LLVM::SDivOp::create(rewriter, op.getLoc(), diff, typeSizeVal);
2133 sDiv.setIsExact(
true);
2134 resultVal = sDiv.getResult();
2137 rewriter.replaceOp(op, resultVal);
2138 return mlir::success();
2141mlir::LogicalResult CIRToLLVMExpectOpLowering::matchAndRewrite(
2142 cir::ExpectOp op, OpAdaptor adaptor,
2143 mlir::ConversionPatternRewriter &rewriter)
const {
2147 std::optional<llvm::APFloat> prob = op.getProb();
2149 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpectWithProbabilityOp>(
2150 op, adaptor.getVal(), adaptor.getExpected(), prob.value());
2152 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpectOp>(op, adaptor.getVal(),
2153 adaptor.getExpected());
2154 return mlir::success();
2157mlir::LogicalResult CIRToLLVMAbsOpLowering::matchAndRewrite(
2158 cir::AbsOp op, OpAdaptor adaptor,
2159 mlir::ConversionPatternRewriter &rewriter)
const {
2160 mlir::Type resTy = typeConverter->convertType(op.getType());
2161 auto absOp = mlir::LLVM::AbsOp::create(rewriter, op.getLoc(), resTy,
2162 adaptor.getOperands()[0],
2163 adaptor.getMinIsPoison());
2164 rewriter.replaceOp(op, absOp);
2165 return mlir::success();
2172void CIRToLLVMFuncOpLowering::lowerFuncAttributes(
2173 cir::FuncOp func,
bool filterArgAndResAttrs,
2174 SmallVectorImpl<mlir::NamedAttribute> &result)
const {
2175 for (mlir::NamedAttribute attr : func->getAttrs()) {
2176 if (
attr.getName() == mlir::SymbolTable::getSymbolAttrName() ||
2177 attr.getName() == func.getFunctionTypeAttrName() ||
2179 attr.getName() == func.getCallingConvAttrName() ||
2180 attr.getName() == func.getDsoLocalAttrName() ||
2181 attr.getName() == func.getInlineKindAttrName() ||
2182 attr.getName() == func.getSideEffectAttrName() ||
2183 attr.getName() == CIRDialect::getNoReturnAttrName() ||
2184 attr.getName() == func.getAnnotationsAttrName() ||
2185 (filterArgAndResAttrs &&
2186 (
attr.getName() == func.getArgAttrsAttrName() ||
2187 attr.getName() == func.getResAttrsAttrName())))
2191 result.push_back(attr);
2195mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewriteAlias(
2196 cir::FuncOp op, llvm::StringRef aliasee, mlir::Type ty, OpAdaptor adaptor,
2197 mlir::ConversionPatternRewriter &rewriter)
const {
2198 SmallVector<mlir::NamedAttribute, 4> attributes;
2199 lowerFuncAttributes(op,
false, attributes);
2201 mlir::Location loc = op.getLoc();
2202 auto aliasOp = rewriter.replaceOpWithNewOp<mlir::LLVM::AliasOp>(
2203 op, ty,
convertLinkage(op.getLinkage()), op.getName(), op.getDsoLocal(),
2207 mlir::OpBuilder builder(op.getContext());
2208 mlir::Block *block = builder.createBlock(&aliasOp.getInitializerRegion());
2209 builder.setInsertionPointToStart(block);
2212 mlir::Type ptrTy = mlir::LLVM::LLVMPointerType::get(ty.getContext());
2213 auto addrOp = mlir::LLVM::AddressOfOp::create(builder, loc, ptrTy, aliasee);
2214 mlir::LLVM::ReturnOp::create(builder, loc, addrOp);
2216 return mlir::success();
2219mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewrite(
2220 cir::FuncOp op, OpAdaptor adaptor,
2221 mlir::ConversionPatternRewriter &rewriter)
const {
2223 cir::FuncType fnType = op.getFunctionType();
2224 bool isDsoLocal = op.getDsoLocal();
2225 mlir::TypeConverter::SignatureConversion signatureConversion(
2226 fnType.getNumInputs());
2228 for (
const auto &argType : llvm::enumerate(fnType.getInputs())) {
2229 mlir::Type convertedType = typeConverter->convertType(argType.value());
2231 return mlir::failure();
2232 signatureConversion.addInputs(argType.index(), convertedType);
2235 mlir::Type resultType =
2236 getTypeConverter()->convertType(fnType.getReturnType());
2239 mlir::Type llvmFnTy = mlir::LLVM::LLVMFunctionType::get(
2240 resultType ? resultType : mlir::LLVM::LLVMVoidType::get(getContext()),
2241 signatureConversion.getConvertedTypes(),
2245 if (std::optional<llvm::StringRef> aliasee = op.getAliasee())
2246 return matchAndRewriteAlias(op, *aliasee, llvmFnTy, adaptor, rewriter);
2250 mlir::Location loc = op.getLoc();
2251 if (mlir::FusedLoc fusedLoc = mlir::dyn_cast<mlir::FusedLoc>(loc))
2252 loc = fusedLoc.getLocations()[0];
2253 assert((mlir::isa<mlir::FileLineColLoc>(loc) ||
2254 mlir::isa<mlir::UnknownLoc>(loc)) &&
2255 "expected single location or unknown location here");
2259 SmallVector<mlir::NamedAttribute, 4> attributes;
2260 lowerFuncAttributes(op,
false, attributes);
2262 mlir::LLVM::LLVMFuncOp fn = mlir::LLVM::LLVMFuncOp::create(
2263 rewriter, loc, op.getName(), llvmFnTy, linkage, isDsoLocal, cconv,
2264 mlir::SymbolRefAttr(), attributes);
2268 if (std::optional<cir::SideEffect> sideEffectKind = op.getSideEffect()) {
2269 switch (*sideEffectKind) {
2270 case cir::SideEffect::All:
2272 case cir::SideEffect::Pure:
2273 fn.setMemoryEffectsAttr(mlir::LLVM::MemoryEffectsAttr::get(
2275 mlir::LLVM::ModRefInfo::Ref,
2276 mlir::LLVM::ModRefInfo::Ref,
2277 mlir::LLVM::ModRefInfo::Ref,
2278 mlir::LLVM::ModRefInfo::Ref,
2279 mlir::LLVM::ModRefInfo::Ref,
2280 mlir::LLVM::ModRefInfo::Ref));
2281 fn.setNoUnwind(
true);
2282 fn.setWillReturn(
true);
2284 case cir::SideEffect::Const:
2285 fn.setMemoryEffectsAttr(mlir::LLVM::MemoryEffectsAttr::get(
2287 mlir::LLVM::ModRefInfo::NoModRef,
2288 mlir::LLVM::ModRefInfo::NoModRef,
2289 mlir::LLVM::ModRefInfo::NoModRef,
2290 mlir::LLVM::ModRefInfo::NoModRef,
2291 mlir::LLVM::ModRefInfo::NoModRef,
2292 mlir::LLVM::ModRefInfo::NoModRef));
2293 fn.setNoUnwind(
true);
2294 fn.setWillReturn(
true);
2299 if (op->hasAttr(CIRDialect::getNoReturnAttrName()))
2300 fn.setNoreturn(
true);
2302 if (std::optional<cir::InlineKind> inlineKind = op.getInlineKind()) {
2303 fn.setNoInline(*inlineKind == cir::InlineKind::NoInline);
2304 fn.setInlineHint(*inlineKind == cir::InlineKind::InlineHint);
2305 fn.setAlwaysInline(*inlineKind == cir::InlineKind::AlwaysInline);
2308 if (std::optional<llvm::StringRef> personality = op.getPersonality())
2309 fn.setPersonality(*personality);
2314 rewriter.inlineRegionBefore(op.getBody(), fn.getBody(), fn.end());
2315 if (failed(rewriter.convertRegionTypes(&fn.getBody(), *typeConverter,
2316 &signatureConversion)))
2317 return mlir::failure();
2319 rewriter.eraseOp(op);
2321 return mlir::LogicalResult::success();
2324mlir::LogicalResult CIRToLLVMGetGlobalOpLowering::matchAndRewrite(
2325 cir::GetGlobalOp op, OpAdaptor adaptor,
2326 mlir::ConversionPatternRewriter &rewriter)
const {
2329 if (op->getUses().empty()) {
2330 rewriter.eraseOp(op);
2331 return mlir::success();
2334 mlir::Type
type = getTypeConverter()->convertType(op.getType());
2335 mlir::Operation *newop = mlir::LLVM::AddressOfOp::create(
2336 rewriter, op.getLoc(), type, op.getName());
2340 newop = mlir::LLVM::ThreadlocalAddressOp::create(rewriter, op.getLoc(),
2341 type, newop->getResult(0));
2344 rewriter.replaceOp(op, newop);
2345 return mlir::success();
2348llvm::SmallVector<mlir::NamedAttribute>
2349CIRToLLVMGlobalOpLowering::lowerGlobalAttributes(
2350 cir::GlobalOp op, mlir::ConversionPatternRewriter &rewriter)
const {
2351 SmallVector<mlir::NamedAttribute> attributes;
2353 if (mlir::StringAttr sectionAttr = op.getSectionAttr())
2354 attributes.push_back(rewriter.getNamedAttr(
"section", sectionAttr));
2356 mlir::LLVM::VisibilityAttr visibility = mlir::LLVM::VisibilityAttr::get(
2359 attributes.push_back(rewriter.getNamedAttr(
"visibility_", visibility));
2361 if (op->getAttr(CUDAExternallyInitializedAttr::getMnemonic()))
2362 attributes.push_back(rewriter.getNamedAttr(
"externally_initialized",
2363 rewriter.getUnitAttr()));
2370void CIRToLLVMGlobalOpLowering::setupRegionInitializedLLVMGlobalOp(
2371 cir::GlobalOp op, mlir::ConversionPatternRewriter &rewriter)
const {
2372 const mlir::Type llvmType =
2379 const bool isConst = op.getConstant();
2380 unsigned addrSpace = 0;
2381 if (
auto targetAS = mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
2382 op.getAddrSpaceAttr()))
2383 addrSpace = targetAS.getValue();
2384 const bool isDsoLocal = op.getDsoLocal();
2385 const bool isThreadLocal = (
bool)op.getTlsModelAttr();
2386 const uint64_t alignment = op.getAlignment().value_or(0);
2387 const mlir::LLVM::Linkage linkage =
convertLinkage(op.getLinkage());
2388 const StringRef symbol = op.getSymName();
2389 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
2391 SmallVector<mlir::NamedAttribute> attributes =
2392 lowerGlobalAttributes(op, rewriter);
2394 mlir::LLVM::GlobalOp newGlobalOp =
2395 rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
2396 op, llvmType, isConst, linkage, symbol,
nullptr, alignment, addrSpace,
2397 isDsoLocal, isThreadLocal, comdatAttr, attributes);
2398 newGlobalOp.getRegion().emplaceBlock();
2399 rewriter.setInsertionPointToEnd(newGlobalOp.getInitializerBlock());
2403CIRToLLVMGlobalOpLowering::matchAndRewriteRegionInitializedGlobal(
2404 cir::GlobalOp op, mlir::Attribute init,
2405 mlir::ConversionPatternRewriter &rewriter)
const {
2407 assert((isa<cir::ConstArrayAttr, cir::ConstRecordAttr, cir::ConstVectorAttr,
2408 cir::ConstPtrAttr, cir::ConstComplexAttr, cir::GlobalViewAttr,
2409 cir::TypeInfoAttr, cir::UndefAttr, cir::PoisonAttr,
2410 cir::VTableAttr, cir::ZeroAttr>(init)));
2415 const mlir::Location loc = op.getLoc();
2416 setupRegionInitializedLLVMGlobalOp(op, rewriter);
2418 mlir::Value value = valueConverter.visit(init);
2419 mlir::LLVM::ReturnOp::create(rewriter, loc, value);
2420 return mlir::success();
2423mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite(
2424 cir::GlobalOp op, OpAdaptor adaptor,
2425 mlir::ConversionPatternRewriter &rewriter)
const {
2428 if (!op.getCtorRegion().empty() || !op.getDtorRegion().empty())
2429 return op.emitError() <<
"GlobalOp ctor and dtor regions should be removed "
2430 "in LoweringPrepare";
2432 std::optional<mlir::Attribute> init = op.getInitialValue();
2435 const mlir::Type cirSymType = op.getSymType();
2438 const mlir::Type llvmType =
2443 const bool isConst = op.getConstant();
2444 unsigned addrSpace = 0;
2445 if (
auto targetAS = mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
2446 op.getAddrSpaceAttr()))
2447 addrSpace = targetAS.getValue();
2448 const bool isDsoLocal = op.getDsoLocal();
2449 const bool isThreadLocal = (
bool)op.getTlsModelAttr();
2450 const uint64_t alignment = op.getAlignment().value_or(0);
2451 const mlir::LLVM::Linkage linkage =
convertLinkage(op.getLinkage());
2452 const StringRef symbol = op.getSymName();
2453 SmallVector<mlir::NamedAttribute> attributes =
2454 lowerGlobalAttributes(op, rewriter);
2457 if (std::optional<llvm::StringRef> aliasee = op.getAliasee()) {
2458 mlir::Location loc = op.getLoc();
2459 auto aliasOp = rewriter.replaceOpWithNewOp<mlir::LLVM::AliasOp>(
2460 op, llvmType, linkage, symbol, isDsoLocal, isThreadLocal, attributes);
2462 mlir::OpBuilder builder(op.getContext());
2463 mlir::Block *block = builder.createBlock(&aliasOp.getInitializerRegion());
2464 builder.setInsertionPointToStart(block);
2466 mlir::LLVM::LLVMPointerType::get(getContext(), addrSpace);
2468 mlir::LLVM::AddressOfOp::create(builder, loc, ptrTy, *aliasee);
2469 mlir::LLVM::ReturnOp::create(builder, loc, addrOp);
2470 return mlir::success();
2473 if (init.has_value()) {
2474 if (mlir::isa<cir::FPAttr, cir::IntAttr, cir::BoolAttr>(init.value())) {
2476 init = initRewriter.visit(init.value());
2481 if (!init.value()) {
2482 op.emitError() <<
"unsupported initializer '" << init.value() <<
"'";
2483 return mlir::failure();
2485 }
else if (
auto constArr =
2486 mlir::dyn_cast<cir::ConstArrayAttr>(init.value())) {
2494 mlir::ModuleOp modOp = op->getParentOfType<mlir::ModuleOp>();
2495 if (std::optional<mlir::Attribute> bulkInit =
2497 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
2498 rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
2499 op, llvmType, isConst, linkage, symbol, bulkInit.value(),
2500 alignment, addrSpace, isDsoLocal, isThreadLocal, comdatAttr,
2502 return mlir::success();
2505 return matchAndRewriteRegionInitializedGlobal(op, init.value(), rewriter);
2506 }
else if (mlir::isa<cir::ConstVectorAttr, cir::ConstRecordAttr,
2507 cir::ConstPtrAttr, cir::ConstComplexAttr,
2508 cir::GlobalViewAttr, cir::TypeInfoAttr, cir::UndefAttr,
2509 cir::PoisonAttr, cir::VTableAttr, cir::ZeroAttr>(
2514 return matchAndRewriteRegionInitializedGlobal(op, init.value(), rewriter);
2518 op.emitError() <<
"unsupported initializer '" << init.value() <<
"'";
2519 return mlir::failure();
2523 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
2524 rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
2525 op, llvmType, isConst, linkage, symbol, init.value_or(mlir::Attribute()),
2526 alignment, addrSpace, isDsoLocal, isThreadLocal, comdatAttr, attributes);
2528 return mlir::success();
2532CIRToLLVMGlobalOpLowering::getComdatAttr(cir::GlobalOp &op,
2533 mlir::OpBuilder &builder)
const {
2534 if (!op.getComdat())
2535 return mlir::SymbolRefAttr{};
2537 mlir::ModuleOp modOp = op->getParentOfType<mlir::ModuleOp>();
2538 mlir::OpBuilder::InsertionGuard guard(builder);
2539 StringRef comdatName(
"__llvm_comdat_globals");
2541 builder.setInsertionPointToStart(modOp.getBody());
2543 mlir::LLVM::ComdatOp::create(builder, modOp.getLoc(), comdatName);
2546 if (
auto comdatSelector = comdatOp.lookupSymbol<mlir::LLVM::ComdatSelectorOp>(
2548 return mlir::SymbolRefAttr::get(
2549 builder.getContext(), comdatName,
2550 mlir::FlatSymbolRefAttr::get(comdatSelector.getSymNameAttr()));
2553 builder.setInsertionPointToStart(&comdatOp.getBody().back());
2554 auto selectorOp = mlir::LLVM::ComdatSelectorOp::create(
2555 builder, comdatOp.getLoc(), op.getSymName(),
2556 mlir::LLVM::comdat::Comdat::Any);
2557 return mlir::SymbolRefAttr::get(
2558 builder.getContext(), comdatName,
2559 mlir::FlatSymbolRefAttr::get(selectorOp.getSymNameAttr()));
2562mlir::LogicalResult CIRToLLVMSwitchFlatOpLowering::matchAndRewrite(
2563 cir::SwitchFlatOp op, OpAdaptor adaptor,
2564 mlir::ConversionPatternRewriter &rewriter)
const {
2566 llvm::SmallVector<mlir::APInt, 8> caseValues;
2567 for (mlir::Attribute val : op.getCaseValues()) {
2568 auto intAttr = cast<cir::IntAttr>(val);
2569 caseValues.push_back(intAttr.getValue());
2572 llvm::SmallVector<mlir::Block *, 8> caseDestinations;
2573 llvm::SmallVector<mlir::ValueRange, 8> caseOperands;
2575 for (mlir::Block *x : op.getCaseDestinations())
2576 caseDestinations.push_back(x);
2578 for (mlir::OperandRange x : op.getCaseOperands())
2579 caseOperands.push_back(x);
2582 rewriter.setInsertionPoint(op);
2583 rewriter.replaceOpWithNewOp<mlir::LLVM::SwitchOp>(
2584 op, adaptor.getCondition(), op.getDefaultDestination(),
2585 op.getDefaultOperands(), caseValues, caseDestinations, caseOperands);
2586 return mlir::success();
2589static mlir::LLVM::IntegerOverflowFlags
nswFlag(
bool nsw) {
2590 return nsw ? mlir::LLVM::IntegerOverflowFlags::nsw
2591 : mlir::LLVM::IntegerOverflowFlags::none;
2594template <
typename CIROp,
typename LLVMIntOp>
2595static mlir::LogicalResult
2597 mlir::ConversionPatternRewriter &rewriter) {
2598 mlir::Type llvmType = adaptor.getInput().getType();
2599 mlir::Location loc = op.getLoc();
2601 auto maybeNSW =
nswFlag(op.getNoSignedWrap());
2602 mlir::LLVM::ConstantOp one;
2603 if (mlir::isa<cir::VectorType>(op.getType())) {
2604 mlir::DenseIntElementsAttr oneVec = mlir::DenseIntElementsAttr::get(
2605 mlir::cast<mlir::ShapedType>(llvmType), 1);
2606 one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, oneVec);
2608 one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
2610 rewriter.replaceOpWithNewOp<LLVMIntOp>(op, adaptor.getInput(), one, maybeNSW);
2611 return mlir::success();
2614mlir::LogicalResult CIRToLLVMIncOpLowering::matchAndRewrite(
2615 cir::IncOp op, OpAdaptor adaptor,
2616 mlir::ConversionPatternRewriter &rewriter)
const {
2620mlir::LogicalResult CIRToLLVMDecOpLowering::matchAndRewrite(
2621 cir::DecOp op, OpAdaptor adaptor,
2622 mlir::ConversionPatternRewriter &rewriter)
const {
2626mlir::LogicalResult CIRToLLVMMinusOpLowering::matchAndRewrite(
2627 cir::MinusOp op, OpAdaptor adaptor,
2628 mlir::ConversionPatternRewriter &rewriter)
const {
2629 bool isVector = mlir::isa<cir::VectorType>(op.getType());
2630 mlir::Type llvmType = adaptor.getInput().getType();
2631 mlir::Location loc = op.getLoc();
2633 auto maybeNSW =
nswFlag(op.getNoSignedWrap());
2636 zero = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmType);
2638 zero = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 0);
2639 rewriter.replaceOpWithNewOp<mlir::LLVM::SubOp>(op, zero, adaptor.getInput(),
2641 return mlir::success();
2644mlir::LogicalResult CIRToLLVMNotOpLowering::matchAndRewrite(
2645 cir::NotOp op, OpAdaptor adaptor,
2646 mlir::ConversionPatternRewriter &rewriter)
const {
2647 mlir::Type elementType = elementTypeIfVector(op.getType());
2648 bool isVector = mlir::isa<cir::VectorType>(op.getType());
2649 mlir::Type llvmType = adaptor.getInput().getType();
2650 mlir::Location loc = op.getLoc();
2652 if (mlir::isa<cir::IntType>(elementType)) {
2653 mlir::Value minusOne;
2656 mlir::dyn_cast<cir::VectorType>(op.getType()).getSize();
2657 SmallVector<int32_t> values(numElements, -1);
2658 mlir::DenseIntElementsAttr denseVec = rewriter.getI32VectorAttr(values);
2660 mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, denseVec);
2662 minusOne = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, -1);
2664 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getInput(),
2666 return mlir::success();
2668 if (mlir::isa<cir::BoolType>(elementType)) {
2669 auto one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
2670 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getInput(), one);
2671 return mlir::success();
2673 return op.emitError() <<
"Unsupported type for bitwise NOT";
2678 return mlir::isa<cir::IntType>(type)
2679 ? mlir::cast<cir::IntType>(type).isUnsigned()
2680 : mlir::cast<mlir::IntegerType>(type).isUnsigned();
2687template <
typename BinOp>
2689 if (op.getNoUnsignedWrap())
2690 return mlir::LLVM::IntegerOverflowFlags::nuw;
2691 if (op.getNoSignedWrap())
2692 return mlir::LLVM::IntegerOverflowFlags::nsw;
2693 return mlir::LLVM::IntegerOverflowFlags::none;
2698template <
typename UIntSatOp,
typename SIntSatOp,
typename IntOp,
2700static mlir::LogicalResult
2702 mlir::ConversionPatternRewriter &rewriter) {
2703 const mlir::Type eltType = elementTypeIfVector(op.getRhs().getType());
2704 assert(cir::isIntOrBoolType(eltType) &&
2705 "saturatable arith op expects integer operand types");
2706 if (op.getSaturated()) {
2708 rewriter.replaceOpWithNewOp<UIntSatOp>(op, lhs, rhs);
2710 rewriter.replaceOpWithNewOp<SIntSatOp>(op, lhs, rhs);
2711 return mlir::success();
2713 rewriter.replaceOpWithNewOp<IntOp>(op, lhs, rhs,
intOverflowFlag(op));
2714 return mlir::success();
2717mlir::LogicalResult CIRToLLVMAddOpLowering::matchAndRewrite(
2718 cir::AddOp op, OpAdaptor adaptor,
2719 mlir::ConversionPatternRewriter &rewriter)
const {
2721 mlir::LLVM::AddOp>(op, adaptor.getLhs(),
2722 adaptor.getRhs(), rewriter);
2725mlir::LogicalResult CIRToLLVMSubOpLowering::matchAndRewrite(
2726 cir::SubOp op, OpAdaptor adaptor,
2727 mlir::ConversionPatternRewriter &rewriter)
const {
2729 mlir::LLVM::SubOp>(op, adaptor.getLhs(),
2730 adaptor.getRhs(), rewriter);
2733mlir::LogicalResult CIRToLLVMMulOpLowering::matchAndRewrite(
2734 cir::MulOp op, OpAdaptor adaptor,
2735 mlir::ConversionPatternRewriter &rewriter)
const {
2736 assert(cir::isIntOrBoolType(elementTypeIfVector(op.getRhs().getType())) &&
2737 "cir.mul expects integer operand types");
2738 rewriter.replaceOpWithNewOp<mlir::LLVM::MulOp>(
2740 return mlir::success();
2744template <
typename UIntOp,
typename SIntOp,
typename CIROp>
2745static mlir::LogicalResult
2747 mlir::ConversionPatternRewriter &rewriter) {
2748 const mlir::Type eltType = elementTypeIfVector(op.getRhs().getType());
2749 assert(cir::isIntOrBoolType(eltType) &&
2750 "integer binary op expects integer operand types");
2752 rewriter.replaceOpWithNewOp<UIntOp>(op, lhs, rhs);
2754 rewriter.replaceOpWithNewOp<SIntOp>(op, lhs, rhs);
2755 return mlir::success();
2758mlir::LogicalResult CIRToLLVMDivOpLowering::matchAndRewrite(
2759 cir::DivOp op, OpAdaptor adaptor,
2760 mlir::ConversionPatternRewriter &rewriter)
const {
2762 op, adaptor.getLhs(), adaptor.getRhs(), rewriter);
2765mlir::LogicalResult CIRToLLVMRemOpLowering::matchAndRewrite(
2766 cir::RemOp op, OpAdaptor adaptor,
2767 mlir::ConversionPatternRewriter &rewriter)
const {
2769 op, adaptor.getLhs(), adaptor.getRhs(), rewriter);
2772template <
typename CIROp,
typename UIntOp,
typename SIntOp>
2773static mlir::LogicalResult
2775 mlir::ConversionPatternRewriter &rewriter) {
2776 const mlir::Value lhs = adaptor.getLhs();
2777 const mlir::Value rhs = adaptor.getRhs();
2779 rewriter.replaceOpWithNewOp<UIntOp>(op, lhs, rhs);
2781 rewriter.replaceOpWithNewOp<SIntOp>(op, lhs, rhs);
2782 return mlir::success();
2785mlir::LogicalResult CIRToLLVMMaxOpLowering::matchAndRewrite(
2786 cir::MaxOp op, OpAdaptor adaptor,
2787 mlir::ConversionPatternRewriter &rewriter)
const {
2789 op, adaptor, rewriter);
2792mlir::LogicalResult CIRToLLVMMinOpLowering::matchAndRewrite(
2793 cir::MinOp op, OpAdaptor adaptor,
2794 mlir::ConversionPatternRewriter &rewriter)
const {
2796 op, adaptor, rewriter);
2800static mlir::LLVM::ICmpPredicate
2802 using CIR = cir::CmpOpKind;
2803 using LLVMICmp = mlir::LLVM::ICmpPredicate;
2806 return LLVMICmp::eq;
2808 return LLVMICmp::ne;
2810 return (isSigned ? LLVMICmp::slt : LLVMICmp::ult);
2812 return (isSigned ? LLVMICmp::sle : LLVMICmp::ule);
2814 return (isSigned ? LLVMICmp::sgt : LLVMICmp::ugt);
2816 return (isSigned ? LLVMICmp::sge : LLVMICmp::uge);
2819 llvm_unreachable(
"FP-only comparison used with integer type");
2821 llvm_unreachable(
"Unknown CmpOpKind");
2826static mlir::LLVM::FCmpPredicate
2828 using CIR = cir::CmpOpKind;
2829 using LLVMFCmp = mlir::LLVM::FCmpPredicate;
2832 return LLVMFCmp::oeq;
2834 return LLVMFCmp::une;
2836 return LLVMFCmp::olt;
2838 return LLVMFCmp::ole;
2840 return LLVMFCmp::ogt;
2842 return LLVMFCmp::oge;
2844 return LLVMFCmp::one;
2846 return LLVMFCmp::uno;
2848 llvm_unreachable(
"Unknown CmpOpKind");
2851mlir::LogicalResult CIRToLLVMCmpOpLowering::matchAndRewrite(
2852 cir::CmpOp cmpOp, OpAdaptor adaptor,
2853 mlir::ConversionPatternRewriter &rewriter)
const {
2854 mlir::Type type = cmpOp.getLhs().getType();
2856 if (mlir::isa<cir::IntType, mlir::IntegerType>(type)) {
2857 bool isSigned = mlir::isa<cir::IntType>(type)
2858 ? mlir::cast<cir::IntType>(type).isSigned()
2859 : mlir::cast<mlir::IntegerType>(type).isSigned();
2860 mlir::LLVM::ICmpPredicate
kind =
2862 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
2863 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
2864 return mlir::success();
2867 if (
auto ptrTy = mlir::dyn_cast<cir::PointerType>(type)) {
2868 mlir::LLVM::ICmpPredicate
kind =
2871 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
2872 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
2873 return mlir::success();
2876 if (
auto vptrTy = mlir::dyn_cast<cir::VPtrType>(type)) {
2880 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
2881 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
2882 return mlir::success();
2885 if (mlir::isa<cir::FPTypeInterface>(type)) {
2886 mlir::LLVM::FCmpPredicate
kind =
2888 rewriter.replaceOpWithNewOp<mlir::LLVM::FCmpOp>(
2889 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
2890 return mlir::success();
2893 if (mlir::isa<cir::ComplexType>(type)) {
2894 mlir::Value lhs = adaptor.getLhs();
2895 mlir::Value rhs = adaptor.getRhs();
2896 mlir::Location loc = cmpOp.getLoc();
2898 auto complexType = mlir::cast<cir::ComplexType>(cmpOp.getLhs().getType());
2899 mlir::Type complexElemTy =
2900 getTypeConverter()->convertType(
complexType.getElementType());
2902 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
2903 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{0}));
2904 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
2905 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{1}));
2906 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
2907 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{0}));
2908 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
2909 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{1}));
2911 if (cmpOp.getKind() == cir::CmpOpKind::eq) {
2912 if (complexElemTy.isInteger()) {
2913 auto realCmp = mlir::LLVM::ICmpOp::create(
2914 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, lhsReal, rhsReal);
2915 auto imagCmp = mlir::LLVM::ICmpOp::create(
2916 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, lhsImag, rhsImag);
2917 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, imagCmp);
2918 return mlir::success();
2921 auto realCmp = mlir::LLVM::FCmpOp::create(
2922 rewriter, loc, mlir::LLVM::FCmpPredicate::oeq, lhsReal, rhsReal);
2923 auto imagCmp = mlir::LLVM::FCmpOp::create(
2924 rewriter, loc, mlir::LLVM::FCmpPredicate::oeq, lhsImag, rhsImag);
2925 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, imagCmp);
2926 return mlir::success();
2929 if (cmpOp.getKind() == cir::CmpOpKind::ne) {
2930 if (complexElemTy.isInteger()) {
2931 auto realCmp = mlir::LLVM::ICmpOp::create(
2932 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, lhsReal, rhsReal);
2933 auto imagCmp = mlir::LLVM::ICmpOp::create(
2934 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, lhsImag, rhsImag);
2935 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp);
2936 return mlir::success();
2939 auto realCmp = mlir::LLVM::FCmpOp::create(
2940 rewriter, loc, mlir::LLVM::FCmpPredicate::une, lhsReal, rhsReal);
2941 auto imagCmp = mlir::LLVM::FCmpOp::create(
2942 rewriter, loc, mlir::LLVM::FCmpPredicate::une, lhsImag, rhsImag);
2943 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp);
2944 return mlir::success();
2948 return cmpOp.emitError() <<
"unsupported type for CmpOp: " <<
type;
2954template <
typename OpTy>
2955static mlir::LogicalResult
2957 mlir::ConversionPatternRewriter &rewriter,
2958 const mlir::TypeConverter *typeConverter,
2959 llvm::StringRef opStr) {
2960 mlir::Location loc = op.getLoc();
2961 cir::IntType operandTy = op.getLhs().getType();
2962 cir::IntType resultTy = op.getResult().getType();
2964 bool sign = operandTy.getIsSigned() || resultTy.getIsSigned();
2966 std::max(operandTy.getWidth() + (
sign && operandTy.isUnsigned()),
2967 resultTy.getWidth() + (
sign && resultTy.isUnsigned()));
2969 mlir::IntegerType encompassedLLVMTy = rewriter.getIntegerType(width);
2971 mlir::Value lhs = adaptor.getLhs();
2972 mlir::Value rhs = adaptor.getRhs();
2973 if (operandTy.getWidth() < width) {
2974 if (operandTy.isSigned()) {
2975 lhs = mlir::LLVM::SExtOp::create(rewriter, loc, encompassedLLVMTy, lhs);
2976 rhs = mlir::LLVM::SExtOp::create(rewriter, loc, encompassedLLVMTy, rhs);
2978 lhs = mlir::LLVM::ZExtOp::create(rewriter, loc, encompassedLLVMTy, lhs);
2979 rhs = mlir::LLVM::ZExtOp::create(rewriter, loc, encompassedLLVMTy, rhs);
2984 std::string intrinName = (
"llvm." + llvm::Twine(
sign ?
's' :
'u') + opStr +
2985 ".with.overflow.i" + llvm::Twine(width))
2987 auto intrinNameAttr = mlir::StringAttr::get(op.getContext(), intrinName);
2989 mlir::IntegerType overflowLLVMTy = rewriter.getI1Type();
2990 auto intrinRetTy = mlir::LLVM::LLVMStructType::getLiteral(
2991 rewriter.getContext(), {encompassedLLVMTy, overflowLLVMTy});
2993 auto callLLVMIntrinOp = mlir::LLVM::CallIntrinsicOp::create(
2994 rewriter, loc, intrinRetTy, intrinNameAttr, mlir::ValueRange{lhs, rhs});
2995 mlir::Value intrinRet = callLLVMIntrinOp.getResult(0);
2997 mlir::Value result = mlir::LLVM::ExtractValueOp::create(
3000 mlir::Value overflow = mlir::LLVM::ExtractValueOp::create(
3004 if (resultTy.getWidth() < width) {
3005 mlir::Type resultLLVMTy = typeConverter->convertType(resultTy);
3007 mlir::LLVM::TruncOp::create(rewriter, loc, resultLLVMTy, result);
3011 mlir::Value truncResultExt;
3012 if (resultTy.isSigned())
3013 truncResultExt = mlir::LLVM::SExtOp::create(
3014 rewriter, loc, encompassedLLVMTy, truncResult);
3016 truncResultExt = mlir::LLVM::ZExtOp::create(
3017 rewriter, loc, encompassedLLVMTy, truncResult);
3018 auto truncOverflow = mlir::LLVM::ICmpOp::create(
3019 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, truncResultExt, result);
3021 result = truncResult;
3022 overflow = mlir::LLVM::OrOp::create(rewriter, loc, overflow, truncOverflow);
3025 mlir::Type boolLLVMTy =
3026 typeConverter->convertType(op.getOverflow().getType());
3027 if (boolLLVMTy != rewriter.getI1Type())
3028 overflow = mlir::LLVM::ZExtOp::create(rewriter, loc, boolLLVMTy, overflow);
3030 rewriter.replaceOp(op, mlir::ValueRange{result, overflow});
3032 return mlir::success();
3035mlir::LogicalResult CIRToLLVMAddOverflowOpLowering::matchAndRewrite(
3036 cir::AddOverflowOp op, OpAdaptor adaptor,
3037 mlir::ConversionPatternRewriter &rewriter)
const {
3041mlir::LogicalResult CIRToLLVMSubOverflowOpLowering::matchAndRewrite(
3042 cir::SubOverflowOp op, OpAdaptor adaptor,
3043 mlir::ConversionPatternRewriter &rewriter)
const {
3047mlir::LogicalResult CIRToLLVMMulOverflowOpLowering::matchAndRewrite(
3048 cir::MulOverflowOp op, OpAdaptor adaptor,
3049 mlir::ConversionPatternRewriter &rewriter)
const {
3053mlir::LogicalResult CIRToLLVMFrexpOpLowering::matchAndRewrite(
3054 cir::FrexpOp op, OpAdaptor adaptor,
3055 mlir::ConversionPatternRewriter &rewriter)
const {
3056 mlir::Location loc = op.getLoc();
3057 mlir::Type fpLLVMTy =
3058 getTypeConverter()->convertType(op.getResult().getType());
3059 mlir::Type intLLVMTy = getTypeConverter()->convertType(op.getExp().getType());
3061 auto structTy = mlir::LLVM::LLVMStructType::getLiteral(rewriter.getContext(),
3062 {fpLLVMTy, intLLVMTy});
3066 mlir::Value result = callOp.getResult(0);
3068 mlir::Value mantissa =
3069 mlir::LLVM::ExtractValueOp::create(rewriter, loc, result, 0);
3070 mlir::Value exponent =
3071 mlir::LLVM::ExtractValueOp::create(rewriter, loc, result, 1);
3072 rewriter.replaceOp(op, mlir::ValueRange{mantissa, exponent});
3073 return mlir::success();
3076mlir::LogicalResult CIRToLLVMModfOpLowering::matchAndRewrite(
3077 cir::ModfOp op, OpAdaptor adaptor,
3078 mlir::ConversionPatternRewriter &rewriter)
const {
3079 mlir::Location loc = op.getLoc();
3080 mlir::Type fpLLVMTy =
3081 getTypeConverter()->convertType(op.getFractional().getType());
3083 auto structTy = mlir::LLVM::LLVMStructType::getLiteral(rewriter.getContext(),
3084 {fpLLVMTy, fpLLVMTy});
3088 mlir::Value result = callOp.getResult(0);
3090 mlir::Value fractional =
3091 mlir::LLVM::ExtractValueOp::create(rewriter, loc, result, 0);
3092 mlir::Value integral =
3093 mlir::LLVM::ExtractValueOp::create(rewriter, loc, result, 1);
3094 rewriter.replaceOp(op, mlir::ValueRange{fractional, integral});
3095 return mlir::success();
3098mlir::LogicalResult CIRToLLVMShiftOpLowering::matchAndRewrite(
3099 cir::ShiftOp op, OpAdaptor adaptor,
3100 mlir::ConversionPatternRewriter &rewriter)
const {
3101 assert((op.getValue().getType() == op.getType()) &&
3102 "inconsistent operands' types NYI");
3104 const mlir::Type llvmTy = getTypeConverter()->convertType(op.getType());
3105 mlir::Value amt = adaptor.getAmount();
3106 mlir::Value val = adaptor.getValue();
3108 auto cirAmtTy = mlir::dyn_cast<cir::IntType>(op.getAmount().getType());
3111 auto cirValTy = mlir::cast<cir::IntType>(op.getValue().getType());
3119 amt =
getLLVMIntCast(rewriter, amt, llvmTy,
true, cirAmtTy.getWidth(),
3120 cirValTy.getWidth());
3122 auto cirValVTy = mlir::cast<cir::VectorType>(op.getValue().getType());
3124 mlir::cast<cir::IntType>(cirValVTy.getElementType()).isUnsigned();
3128 if (op.getIsShiftleft()) {
3129 rewriter.replaceOpWithNewOp<mlir::LLVM::ShlOp>(op, llvmTy, val, amt);
3130 return mlir::success();
3134 rewriter.replaceOpWithNewOp<mlir::LLVM::LShrOp>(op, llvmTy, val, amt);
3136 rewriter.replaceOpWithNewOp<mlir::LLVM::AShrOp>(op, llvmTy, val, amt);
3137 return mlir::success();
3140mlir::LogicalResult CIRToLLVMSelectOpLowering::matchAndRewrite(
3141 cir::SelectOp op, OpAdaptor adaptor,
3142 mlir::ConversionPatternRewriter &rewriter)
const {
3143 auto getConstantBool = [](mlir::Value value) -> cir::BoolAttr {
3144 auto definingOp = value.getDefiningOp<cir::ConstantOp>();
3148 auto constValue = definingOp.getValueAttr<cir::BoolAttr>();
3158 if (mlir::isa<cir::BoolType>(op.getTrueValue().getType())) {
3159 cir::BoolAttr trueValue = getConstantBool(op.getTrueValue());
3160 cir::BoolAttr falseValue = getConstantBool(op.getFalseValue());
3161 if (falseValue && !falseValue.getValue()) {
3163 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(op, adaptor.getCondition(),
3164 adaptor.getTrueValue());
3165 return mlir::success();
3167 if (trueValue && trueValue.getValue()) {
3169 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(op, adaptor.getCondition(),
3170 adaptor.getFalseValue());
3171 return mlir::success();
3175 mlir::Value llvmCondition = adaptor.getCondition();
3176 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(
3177 op, llvmCondition, adaptor.getTrueValue(), adaptor.getFalseValue());
3179 return mlir::success();
3183 mlir::DataLayout &dataLayout) {
3184 converter.addConversion([&](cir::PointerType type) -> mlir::Type {
3185 mlir::ptr::MemorySpaceAttrInterface addrSpaceAttr = type.getAddrSpace();
3186 unsigned numericAS = 0;
3188 if (
auto targetAsAttr =
3189 mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
3191 numericAS = targetAsAttr.getValue();
3192 return mlir::LLVM::LLVMPointerType::get(type.getContext(), numericAS);
3194 converter.addConversion([&](cir::VPtrType type) -> mlir::Type {
3196 return mlir::LLVM::LLVMPointerType::get(type.getContext());
3198 converter.addConversion([&](cir::ArrayType type) -> mlir::Type {
3201 return mlir::LLVM::LLVMArrayType::get(ty, type.getSize());
3203 converter.addConversion([&](cir::VectorType type) -> mlir::Type {
3204 const mlir::Type ty = converter.convertType(type.getElementType());
3205 return mlir::VectorType::get(type.getSize(), ty, {type.getIsScalable()});
3207 converter.addConversion([&](cir::BoolType type) -> mlir::Type {
3208 return mlir::IntegerType::get(type.getContext(), 1,
3209 mlir::IntegerType::Signless);
3211 converter.addConversion([&](cir::IntType type) -> mlir::Type {
3213 return mlir::IntegerType::get(type.getContext(), type.getWidth());
3215 converter.addConversion([&](cir::SingleType type) -> mlir::Type {
3216 return mlir::Float32Type::get(type.getContext());
3218 converter.addConversion([&](cir::DoubleType type) -> mlir::Type {
3219 return mlir::Float64Type::get(type.getContext());
3221 converter.addConversion([&](cir::FP80Type type) -> mlir::Type {
3222 return mlir::Float80Type::get(type.getContext());
3224 converter.addConversion([&](cir::FP128Type type) -> mlir::Type {
3225 return mlir::Float128Type::get(type.getContext());
3227 converter.addConversion([&](cir::LongDoubleType type) -> mlir::Type {
3228 return converter.convertType(type.getUnderlying());
3230 converter.addConversion([&](cir::FP16Type type) -> mlir::Type {
3231 return mlir::Float16Type::get(type.getContext());
3233 converter.addConversion([&](cir::BF16Type type) -> mlir::Type {
3234 return mlir::BFloat16Type::get(type.getContext());
3236 converter.addConversion([&](cir::ComplexType type) -> mlir::Type {
3239 mlir::Type elementTy = converter.convertType(type.getElementType());
3240 mlir::Type structFields[2] = {elementTy, elementTy};
3241 return mlir::LLVM::LLVMStructType::getLiteral(type.getContext(),
3244 converter.addConversion([&](cir::FuncType type) -> std::optional<mlir::Type> {
3245 auto result = converter.convertType(type.getReturnType());
3247 arguments.reserve(type.getNumInputs());
3248 if (converter.convertTypes(type.getInputs(), arguments).failed())
3249 return std::nullopt;
3250 auto varArg = type.isVarArg();
3251 return mlir::LLVM::LLVMFunctionType::get(result, arguments, varArg);
3253 converter.addConversion([&](cir::StructType type) -> mlir::Type {
3255 for (mlir::Type ty : type.getMembers())
3258 mlir::LLVM::LLVMStructType llvmStruct;
3259 if (type.getName()) {
3260 llvmStruct = mlir::LLVM::LLVMStructType::getIdentified(
3261 type.getContext(), type.getPrefixedName());
3262 if (llvmStruct.setBody(llvmMembers, type.getPacked()).failed())
3263 llvm_unreachable(
"Failed to set body of record");
3265 llvmStruct = mlir::LLVM::LLVMStructType::getLiteral(
3266 type.getContext(), llvmMembers, type.getPacked());
3271 converter.addConversion([&](cir::UnionType type) -> mlir::Type {
3273 if (!type.getMembers().empty())
3274 if (
auto storage = type.getUnionStorageType(dataLayout))
3275 llvmMembers.push_back(
3277 if (mlir::Type pad = type.getPadding())
3280 mlir::LLVM::LLVMStructType llvmStruct;
3281 if (type.getName()) {
3282 llvmStruct = mlir::LLVM::LLVMStructType::getIdentified(
3283 type.getContext(), type.getPrefixedName());
3284 if (llvmStruct.setBody(llvmMembers, type.getPacked()).failed())
3285 llvm_unreachable(
"Failed to set body of record");
3287 llvmStruct = mlir::LLVM::LLVMStructType::getLiteral(
3288 type.getContext(), llvmMembers, type.getPacked());
3292 converter.addConversion([&](cir::VoidType type) -> mlir::Type {
3293 return mlir::LLVM::LLVMVoidType::get(type.getContext());
3298 mlir::ModuleOp module, StringRef globalXtorName, StringRef llvmXtorName,
3299 llvm::function_ref<std::pair<StringRef, int>(mlir::Attribute)> createXtor) {
3301 for (
const mlir::NamedAttribute namedAttr : module->getAttrs()) {
3302 if (namedAttr.getName() == globalXtorName) {
3303 for (
auto attr : mlir::cast<mlir::ArrayAttr>(namedAttr.getValue()))
3304 globalXtors.emplace_back(createXtor(attr));
3309 if (globalXtors.empty())
3312 mlir::OpBuilder builder(module.getContext());
3313 builder.setInsertionPointToEnd(&module.getBodyRegion().back());
3317 auto ctorPFTy = mlir::LLVM::LLVMPointerType::get(builder.getContext());
3319 ctorStructFields.push_back(builder.getI32Type());
3320 ctorStructFields.push_back(ctorPFTy);
3321 ctorStructFields.push_back(ctorPFTy);
3323 auto ctorStructTy = mlir::LLVM::LLVMStructType::getLiteral(
3324 builder.getContext(), ctorStructFields);
3325 auto ctorStructArrayTy =
3326 mlir::LLVM::LLVMArrayType::get(ctorStructTy, globalXtors.size());
3328 mlir::Location loc =
module.getLoc();
3329 auto newGlobalOp = mlir::LLVM::GlobalOp::create(
3330 builder, loc, ctorStructArrayTy,
false,
3331 mlir::LLVM::Linkage::Appending, llvmXtorName, mlir::Attribute());
3333 builder.createBlock(&newGlobalOp.getRegion());
3334 builder.setInsertionPointToEnd(newGlobalOp.getInitializerBlock());
3336 mlir::Value result =
3337 mlir::LLVM::UndefOp::create(builder, loc, ctorStructArrayTy);
3339 for (
auto [index, fn] : llvm::enumerate(globalXtors)) {
3340 mlir::Value structInit =
3341 mlir::LLVM::UndefOp::create(builder, loc, ctorStructTy);
3342 mlir::Value initPriority = mlir::LLVM::ConstantOp::create(
3343 builder, loc, ctorStructFields[0], fn.second);
3344 mlir::Value initFuncAddr = mlir::LLVM::AddressOfOp::create(
3345 builder, loc, ctorStructFields[1], fn.first);
3346 mlir::Value initAssociate =
3347 mlir::LLVM::ZeroOp::create(builder, loc, ctorStructFields[2]);
3350 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
3351 initPriority, zero);
3352 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
3355 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
3357 result = mlir::LLVM::InsertValueOp::create(builder, loc, result, structInit,
3361 mlir::LLVM::ReturnOp::create(builder, loc, result);
3364mlir::LogicalResult CIRToLLVMObjSizeOpLowering::matchAndRewrite(
3365 cir::ObjSizeOp op, OpAdaptor adaptor,
3366 mlir::ConversionPatternRewriter &rewriter)
const {
3367 mlir::Type llvmResTy = getTypeConverter()->convertType(op.getType());
3368 mlir::Location loc = op->getLoc();
3370 mlir::IntegerType i1Ty = rewriter.getI1Type();
3372 auto i1Val = [&rewriter, &loc, &i1Ty](
bool val) {
3373 return mlir::LLVM::ConstantOp::create(rewriter, loc, i1Ty, val);
3380 i1Val(op.getNullunknown()),
3381 i1Val(op.getDynamic()),
3384 return mlir::LogicalResult::success();
3392constexpr StringRef llvmMetadataSectionName =
"llvm.metadata";
3397getOrCreateAnnotationStringGlobal(mlir::OpBuilder &builder, mlir::Location loc,
3398 mlir::ModuleOp module, llvm::StringRef str,
3399 llvm::StringMap<mlir::LLVM::GlobalOp> &cache,
3401 auto it = cache.find(str);
3402 if (it != cache.end())
3405 auto i8Ty = mlir::IntegerType::get(module.getContext(), 8);
3406 auto arrayTy = mlir::LLVM::LLVMArrayType::get(i8Ty, str.size() + 1);
3407 std::string
name =
".str";
3409 name +=
"." + std::to_string(cache.size());
3410 name +=
".annotation";
3414 mlir::LLVM::GlobalOp strGlobal = mlir::LLVM::GlobalOp::create(
3415 builder, loc, arrayTy,
true, mlir::LLVM::Linkage::Private,
3416 name, mlir::StringAttr::get(module.getContext(), std::string(str) +
'\0'),
3419 strGlobal.setSection(llvmMetadataSectionName);
3420 strGlobal.setUnnamedAddr(mlir::LLVM::UnnamedAddr::Global);
3421 strGlobal.setDsoLocal(
true);
3422 cache[str] = strGlobal;
3428mlir::LLVM::GlobalOp getOrCreateAnnotationArgsVar(
3429 mlir::OpBuilder &builder, mlir::Location loc, mlir::ModuleOp module,
3430 mlir::ArrayAttr argsAttr,
3431 llvm::StringMap<mlir::LLVM::GlobalOp> &argStringCache,
3432 llvm::MapVector<mlir::ArrayAttr, mlir::LLVM::GlobalOp> &argsCache) {
3433 auto it = argsCache.find(argsAttr);
3434 if (it != argsCache.end())
3437 auto ptrTy = mlir::LLVM::LLVMPointerType::get(builder.getContext());
3439 llvm::SmallVector<mlir::Type> fieldTypes;
3440 for (mlir::Attribute arg : argsAttr) {
3441 if (mlir::isa<mlir::StringAttr>(arg))
3442 fieldTypes.push_back(ptrTy);
3443 else if (
auto intAttr = mlir::dyn_cast<mlir::IntegerAttr>(arg))
3444 fieldTypes.push_back(intAttr.getType());
3446 llvm_unreachable(
"Unsupported annotation arg type");
3450 mlir::LLVM::LLVMStructType::getLiteral(builder.getContext(), fieldTypes);
3451 std::string
name =
".args";
3452 if (!argsCache.empty())
3453 name +=
"." + std::to_string(argsCache.size());
3454 name +=
".annotation";
3456 mlir::LLVM::GlobalOp argsGlobal = mlir::LLVM::GlobalOp::create(
3457 builder, loc, structTy,
true, mlir::LLVM::Linkage::Private,
3458 name, mlir::Attribute());
3459 argsGlobal.setSection(llvmMetadataSectionName);
3460 argsGlobal.setUnnamedAddr(mlir::LLVM::UnnamedAddr::Global);
3461 argsGlobal.setDsoLocal(
true);
3464 argsGlobal.getRegion().push_back(
new mlir::Block());
3465 mlir::OpBuilder initBuilder(module.getContext());
3466 initBuilder.setInsertionPointToEnd(argsGlobal.getInitializerBlock());
3468 mlir::Value structInit =
3469 mlir::LLVM::UndefOp::create(initBuilder, loc, structTy);
3470 for (
auto [idx, arg] : llvm::enumerate(argsAttr)) {
3471 if (
auto strArg = mlir::dyn_cast<mlir::StringAttr>(arg)) {
3472 mlir::LLVM::GlobalOp strGlobal = getOrCreateAnnotationStringGlobal(
3473 builder, loc, module, strArg.getValue(), argStringCache,
3475 mlir::LLVM::AddressOfOp strAddr = mlir::LLVM::AddressOfOp::create(
3476 initBuilder, loc, ptrTy, strGlobal.getSymName());
3477 structInit = mlir::LLVM::InsertValueOp::create(initBuilder, loc,
3478 structInit, strAddr, idx);
3479 }
else if (
auto intArg = mlir::dyn_cast<mlir::IntegerAttr>(arg)) {
3480 mlir::LLVM::ConstantOp intConst = mlir::LLVM::ConstantOp::create(
3481 initBuilder, loc, intArg.getType(), intArg.getValue());
3482 structInit = mlir::LLVM::InsertValueOp::create(initBuilder, loc,
3483 structInit, intConst, idx);
3485 llvm_unreachable(
"Unsupported annotation arg type");
3488 mlir::LLVM::ReturnOp::create(initBuilder, loc, structInit);
3490 argsCache[argsAttr] = argsGlobal;
3496std::pair<llvm::StringRef, unsigned> extractFileLine(mlir::Location loc) {
3497 mlir::Location resolved = loc;
3498 if (
auto fused = mlir::dyn_cast<mlir::FusedLoc>(resolved)) {
3499 if (!fused.getLocations().empty())
3500 resolved = fused.getLocations()[0];
3502 if (
auto fl = mlir::dyn_cast<mlir::FileLineColLoc>(resolved))
3503 return {fl.getFilename().getValue(), fl.getLine()};
3509 auto handleArray = [&](mlir::StringAttr symName, mlir::ArrayAttr arr,
3510 mlir::Location loc) {
3513 for (mlir::Attribute a : arr)
3514 if (
auto annot = mlir::dyn_cast<cir::AnnotationAttr>(a))
3515 collectedAnnotations.emplace_back(symName, annot, loc);
3520 module.walk([&](cir::GlobalOp op) {
3521 handleArray(op.getSymNameAttr(), op.getAnnotationsAttr(), op.getLoc());
3523 module.walk([&](cir::FuncOp op) {
3524 handleArray(op.getSymNameAttr(), op.getAnnotationsAttr(), op.getLoc());
3529 if (collectedAnnotations.empty())
3532 mlir::MLIRContext *ctx =
module.getContext();
3533 mlir::OpBuilder builder(ctx);
3534 builder.setInsertionPointToEnd(&module.getBodyRegion().back());
3536 auto ptrTy = mlir::LLVM::LLVMPointerType::get(ctx);
3537 auto i32Ty = builder.getI32Type();
3540 auto entryTy = mlir::LLVM::LLVMStructType::getLiteral(
3541 ctx, {ptrTy, ptrTy, ptrTy, i32Ty, ptrTy});
3543 mlir::LLVM::LLVMArrayType::get(entryTy, collectedAnnotations.size());
3545 mlir::Location moduleLoc =
module.getLoc();
3546 auto annotationsGlobal = mlir::LLVM::GlobalOp::create(
3547 builder, moduleLoc, arrayTy,
false,
3548 mlir::LLVM::Linkage::Appending,
"llvm.global.annotations",
3550 annotationsGlobal.setSection(llvmMetadataSectionName);
3554 mlir::OpBuilder constsBuilder(ctx);
3555 constsBuilder.setInsertionPoint(annotationsGlobal);
3557 llvm::StringMap<mlir::LLVM::GlobalOp> stringCache;
3558 llvm::StringMap<mlir::LLVM::GlobalOp> argStringCache;
3559 llvm::MapVector<mlir::ArrayAttr, mlir::LLVM::GlobalOp> argsCache;
3562 annotationsGlobal.getRegion().push_back(
new mlir::Block());
3563 mlir::OpBuilder initBuilder(ctx);
3564 initBuilder.setInsertionPointToEnd(annotationsGlobal.getInitializerBlock());
3566 mlir::Value arrayVal =
3567 mlir::LLVM::UndefOp::create(initBuilder, moduleLoc, arrayTy);
3569 for (
auto [idx, entry] : llvm::enumerate(collectedAnnotations)) {
3570 mlir::Value entryVal =
3571 mlir::LLVM::UndefOp::create(initBuilder, moduleLoc, entryTy);
3576 mlir::LLVM::AddressOfOp symAddr = mlir::LLVM::AddressOfOp::create(
3577 initBuilder, moduleLoc, ptrTy, entry.symName.getValue());
3578 entryVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
3579 entryVal, symAddr, zero);
3582 mlir::LLVM::GlobalOp nameGlobal = getOrCreateAnnotationStringGlobal(
3583 constsBuilder, moduleLoc, module, entry.annotation.getName().getValue(),
3584 stringCache,
false);
3585 mlir::LLVM::AddressOfOp nameAddr = mlir::LLVM::AddressOfOp::create(
3586 initBuilder, moduleLoc, ptrTy, nameGlobal.getSymName());
3587 entryVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
3588 entryVal, nameAddr, 1);
3591 auto [filename, line] = extractFileLine(entry.loc);
3592 mlir::LLVM::GlobalOp fileGlobal = getOrCreateAnnotationStringGlobal(
3593 constsBuilder, moduleLoc, module, filename, stringCache,
3595 mlir::LLVM::AddressOfOp fileAddr = mlir::LLVM::AddressOfOp::create(
3596 initBuilder, moduleLoc, ptrTy, fileGlobal.getSymName());
3597 entryVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
3598 entryVal, fileAddr, 2);
3599 mlir::LLVM::ConstantOp lineConst =
3600 mlir::LLVM::ConstantOp::create(initBuilder, moduleLoc, i32Ty, line);
3601 entryVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
3602 entryVal, lineConst, 3);
3605 mlir::ArrayAttr args = entry.annotation.getArgs();
3606 mlir::Value argsField;
3607 if (!args || args.empty()) {
3608 argsField = mlir::LLVM::ZeroOp::create(initBuilder, moduleLoc, ptrTy);
3610 mlir::LLVM::GlobalOp argsGlobal = getOrCreateAnnotationArgsVar(
3611 constsBuilder, moduleLoc, module, args, argStringCache, argsCache);
3612 argsField = mlir::LLVM::AddressOfOp::create(initBuilder, moduleLoc, ptrTy,
3613 argsGlobal.getSymName());
3615 entryVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
3616 entryVal, argsField, 4);
3618 arrayVal = mlir::LLVM::InsertValueOp::create(initBuilder, moduleLoc,
3619 arrayVal, entryVal, idx);
3622 mlir::LLVM::ReturnOp::create(initBuilder, moduleLoc, arrayVal);
3628 mlir::ModuleOp module = getOperation();
3629 mlir::OpBuilder opBuilder(module.getContext());
3630 for (
auto &[blockAddOp, blockInfo] :
3632 mlir::LLVM::BlockTagOp resolvedLabel =
3634 assert(resolvedLabel &&
"expected BlockTagOp to already be emitted");
3635 mlir::FlatSymbolRefAttr fnSym = blockInfo.getFunc();
3636 auto blkAddTag = mlir::LLVM::BlockAddressAttr::get(
3637 opBuilder.getContext(), fnSym, resolvedLabel.getTagAttr());
3638 blockAddOp.setBlockAddrAttr(blkAddTag);
3645 if (mlir::Attribute tripleAttr =
3646 module->getAttr(cir::CIRDialect::getTripleAttrName()))
3647 module->setAttr(mlir::LLVM::LLVMDialect::getTargetTripleAttrName(),
3650 if (mlir::Attribute asmAttr =
3651 module->getAttr(cir::CIRDialect::getModuleLevelAsmAttrName()))
3652 module->setAttr(mlir::LLVM::LLVMDialect::getModuleLevelAsmAttrName(),
3657 llvm::TimeTraceScope scope(
"Convert CIR to LLVM Pass");
3659 mlir::ModuleOp module = getOperation();
3660 mlir::DataLayout dl(module);
3661 mlir::LLVMTypeConverter converter(&getContext());
3671 mlir::SymbolTableCollection symbolTables;
3672 mlir::RewritePatternSet patterns(&getContext());
3673 patterns.add<CIRToLLVMBlockAddressOpLowering, CIRToLLVMLabelOpLowering>(
3674 converter, patterns.getContext(), dl, blockInfoAddr);
3675 patterns.add<CIRToLLVMCallOpLowering, CIRToLLVMTryCallOpLowering>(
3676 converter, patterns.getContext(), dl, symbolTables);
3679#define GET_LLVM_LOWERING_PATTERNS_LIST
3680#include "clang/CIR/Dialect/IR/CIRLowering.inc"
3681#undef GET_LLVM_LOWERING_PATTERNS_LIST
3682 >(converter, patterns.getContext(), dl);
3690 mlir::ConversionTarget target(getContext());
3691 target.addLegalOp<mlir::ModuleOp>();
3692 target.addLegalDialect<mlir::LLVM::LLVMDialect>();
3693 mlir::configureOpenMPToLLVMConversionLegality(target, converter);
3694 target.addLegalDialect<mlir::omp::OpenMPDialect>();
3695 mlir::populateOpenMPToLLVMConversionPatterns(converter, patterns);
3696 target.addIllegalDialect<mlir::BuiltinDialect, cir::CIRDialect,
3697 mlir::func::FuncDialect>();
3700 ops.push_back(module);
3703 if (failed(applyPartialConversion(ops, target, std::move(patterns))))
3704 signalPassFailure();
3708 "llvm.global_ctors", [](mlir::Attribute
attr) {
3709 auto ctorAttr = mlir::cast<cir::GlobalCtorAttr>(
attr);
3710 return std::make_pair(ctorAttr.getName(),
3711 ctorAttr.getPriority());
3715 "llvm.global_dtors", [](mlir::Attribute
attr) {
3716 auto dtorAttr = mlir::cast<cir::GlobalDtorAttr>(
attr);
3717 return std::make_pair(dtorAttr.getName(),
3718 dtorAttr.getPriority());
3726mlir::LogicalResult CIRToLLVMBrOpLowering::matchAndRewrite(
3727 cir::BrOp op, OpAdaptor adaptor,
3728 mlir::ConversionPatternRewriter &rewriter)
const {
3729 rewriter.replaceOpWithNewOp<mlir::LLVM::BrOp>(op, adaptor.getOperands(),
3731 return mlir::LogicalResult::success();
3734mlir::LogicalResult CIRToLLVMGetMemberOpLowering::matchAndRewrite(
3735 cir::GetMemberOp op, OpAdaptor adaptor,
3736 mlir::ConversionPatternRewriter &rewriter)
const {
3737 mlir::Type llResTy = getTypeConverter()->convertType(op.getType());
3738 mlir::Type pointee = op.getAddrTy().getPointee();
3740 if (mlir::isa<cir::UnionType>(pointee)) {
3743 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(op, llResTy,
3745 return mlir::success();
3748 auto structTy = mlir::cast<cir::StructType>(pointee);
3752 const mlir::Type elementTy = getTypeConverter()->convertType(structTy);
3757 mlir::LLVM::GEPNoWrapFlags flags =
3758 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
3759 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
3760 op, llResTy, elementTy, adaptor.getAddr(), offset, flags);
3761 return mlir::success();
3764mlir::LogicalResult CIRToLLVMExtractMemberOpLowering::matchAndRewrite(
3765 cir::ExtractMemberOp op, OpAdaptor adaptor,
3766 mlir::ConversionPatternRewriter &rewriter)
const {
3767 std::int64_t indices[1] = {
static_cast<std::int64_t
>(op.getIndex())};
3769 if (mlir::isa<cir::UnionType>(op.getRecord().getType())) {
3770 op.emitError(
"cir.extract_member cannot extract member from a union");
3771 return mlir::failure();
3774 rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractValueOp>(
3775 op, adaptor.getRecord(), indices);
3776 return mlir::success();
3779mlir::LogicalResult CIRToLLVMInsertMemberOpLowering::matchAndRewrite(
3780 cir::InsertMemberOp op, OpAdaptor adaptor,
3781 mlir::ConversionPatternRewriter &rewriter)
const {
3782 std::int64_t indecies[1] = {
static_cast<std::int64_t
>(op.getIndex())};
3784 if (mlir::isa<cir::UnionType>(op.getRecord().getType())) {
3785 op.emitError(
"cir.update_member cannot update member of a union");
3786 return mlir::failure();
3789 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
3790 op, adaptor.getRecord(), adaptor.getValue(), indecies);
3791 return mlir::success();
3795 mlir::Operation *srcOp, llvm::StringRef fnName,
3797 mlir::ArrayAttr argAttrs =
nullptr,
3798 mlir::ArrayAttr resAttrs =
nullptr) {
3799 mlir::ModuleOp modOp = srcOp->getParentOfType<mlir::ModuleOp>();
3800 mlir::Operation *sourceSymbol =
3801 mlir::SymbolTable::lookupSymbolIn(modOp, fnName);
3802 if (!sourceSymbol) {
3803 mlir::OpBuilder::InsertionGuard guard(rewriter);
3804 auto enclosingFnOp = srcOp->getParentOfType<mlir::LLVM::LLVMFuncOp>();
3805 rewriter.setInsertionPoint(enclosingFnOp);
3807 mlir::LLVM::LLVMFuncOp::create(rewriter, srcOp->getLoc(), fnName, fnTy);
3809 fn.setArgAttrsAttr(argAttrs);
3811 fn.setResAttrsAttr(resAttrs);
3815mlir::LogicalResult CIRToLLVMThrowOpLowering::matchAndRewrite(
3816 cir::ThrowOp op, OpAdaptor adaptor,
3817 mlir::ConversionPatternRewriter &rewriter)
const {
3818 mlir::Location loc = op.getLoc();
3819 auto voidTy = mlir::LLVM::LLVMVoidType::get(getContext());
3821 if (op.rethrows()) {
3822 auto funcTy = mlir::LLVM::LLVMFunctionType::get(voidTy, {});
3825 const llvm::StringRef functionName =
"__cxa_rethrow";
3826 createLLVMFuncOpIfNotExist(rewriter, op, functionName, funcTy);
3828 auto cxaRethrow = mlir::LLVM::CallOp::create(
3829 rewriter, loc, mlir::TypeRange{}, functionName);
3831 rewriter.replaceOp(op, cxaRethrow);
3832 return mlir::success();
3835 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3836 auto fnTy = mlir::LLVM::LLVMFunctionType::get(
3837 voidTy, {llvmPtrTy, llvmPtrTy, llvmPtrTy});
3840 const llvm::StringRef fnName =
"__cxa_throw";
3843 mlir::Value typeInfo = mlir::LLVM::AddressOfOp::create(
3844 rewriter, loc, mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
3845 adaptor.getTypeInfoAttr());
3849 dtor = mlir::LLVM::AddressOfOp::create(rewriter, loc, llvmPtrTy,
3850 adaptor.getDtorAttr());
3852 dtor = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmPtrTy);
3855 auto cxaThrowCall = mlir::LLVM::CallOp::create(
3856 rewriter, loc, mlir::TypeRange{}, fnName,
3857 mlir::ValueRange{adaptor.getExceptionPtr(), typeInfo, dtor});
3859 rewriter.replaceOp(op, cxaThrowCall);
3860 return mlir::success();
3863mlir::LogicalResult CIRToLLVMAllocExceptionOpLowering::matchAndRewrite(
3864 cir::AllocExceptionOp op, OpAdaptor adaptor,
3865 mlir::ConversionPatternRewriter &rewriter)
const {
3867 StringRef fnName =
"__cxa_allocate_exception";
3868 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3869 auto int64Ty = mlir::IntegerType::get(rewriter.getContext(), 64);
3870 auto fnTy = mlir::LLVM::LLVMFunctionType::get(llvmPtrTy, {int64Ty});
3873 auto exceptionSize = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
3874 adaptor.getSizeAttr());
3876 auto allocaExceptionCall = mlir::LLVM::CallOp::create(
3877 rewriter, op.getLoc(), mlir::TypeRange{llvmPtrTy}, fnName,
3878 mlir::ValueRange{exceptionSize});
3880 rewriter.replaceOp(op, allocaExceptionCall);
3881 return mlir::success();
3884static mlir::LLVM::LLVMStructType
3887 mlir::MLIRContext *ctx = rewriter.getContext();
3888 auto llvmPtr = mlir::LLVM::LLVMPointerType::get(ctx);
3890 return mlir::LLVM::LLVMStructType::getLiteral(ctx, structFields);
3893mlir::LogicalResult CIRToLLVMEhInflightOpLowering::matchAndRewrite(
3894 cir::EhInflightOp op, OpAdaptor adaptor,
3895 mlir::ConversionPatternRewriter &rewriter)
const {
3896 auto llvmFn = op->getParentOfType<mlir::LLVM::LLVMFuncOp>();
3897 assert(llvmFn &&
"expected LLVM function parent");
3898 mlir::Block *entryBlock = &llvmFn.getRegion().front();
3899 assert(entryBlock->isEntryBlock());
3901 mlir::ArrayAttr catchListAttr = op.getCatchTypeListAttr();
3902 mlir::SmallVector<mlir::Value> catchSymAddrs;
3904 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3905 mlir::Location loc = op.getLoc();
3910 if (catchListAttr) {
3913 for (mlir::Attribute catchAttr : catchListAttr) {
3914 auto symAttr = cast<mlir::FlatSymbolRefAttr>(catchAttr);
3917 mlir::OpBuilder::InsertionGuard guard(rewriter);
3918 rewriter.setInsertionPointToStart(entryBlock);
3919 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
3920 rewriter, loc, llvmPtrTy, symAttr.getValue());
3921 catchSymAddrs.push_back(addrOp);
3928 if (op.getCatchAll() || (!catchListAttr && !op.getCleanup())) {
3929 mlir::OpBuilder::InsertionGuard guard(rewriter);
3930 rewriter.setInsertionPointToStart(entryBlock);
3931 mlir::Value nullOp = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmPtrTy);
3932 catchSymAddrs.push_back(nullOp);
3937 mlir::LLVM::LLVMStructType llvmLandingPadStructTy =
3939 auto landingPadOp = mlir::LLVM::LandingpadOp::create(
3940 rewriter, loc, llvmLandingPadStructTy, catchSymAddrs);
3945 if (op.getCleanup() && !op.getCatchAll())
3946 landingPadOp.setCleanup(
true);
3949 mlir::LLVM::ExtractValueOp::create(rewriter, loc, landingPadOp, 0);
3950 mlir::Value selector =
3951 mlir::LLVM::ExtractValueOp::create(rewriter, loc, landingPadOp, 1);
3952 rewriter.replaceOp(op, mlir::ValueRange{slot, selector});
3954 return mlir::success();
3957mlir::LogicalResult CIRToLLVMResumeFlatOpLowering::matchAndRewrite(
3958 cir::ResumeFlatOp op, OpAdaptor adaptor,
3959 mlir::ConversionPatternRewriter &rewriter)
const {
3964 mlir::Value poison = mlir::LLVM::PoisonOp::create(rewriter, op.getLoc(),
3965 llvmLandingPadStructTy);
3968 mlir::Value slot = mlir::LLVM::InsertValueOp::create(
3969 rewriter, op.getLoc(), poison, adaptor.getExceptionPtr(), slotIdx);
3972 mlir::Value selector = mlir::LLVM::InsertValueOp::create(
3973 rewriter, op.getLoc(), slot, adaptor.getTypeId(), selectorIdx);
3975 rewriter.replaceOpWithNewOp<mlir::LLVM::ResumeOp>(op, selector);
3976 return mlir::success();
3979mlir::LogicalResult CIRToLLVMEhTypeIdOpLowering::matchAndRewrite(
3980 cir::EhTypeIdOp op, OpAdaptor adaptor,
3981 mlir::ConversionPatternRewriter &rewriter)
const {
3982 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
3983 rewriter, op.getLoc(),
3984 mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
3985 op.getTypeSymAttr());
3986 rewriter.replaceOpWithNewOp<mlir::LLVM::EhTypeidForOp>(
3987 op, rewriter.getI32Type(), addrOp);
3988 return mlir::success();
3991mlir::LogicalResult CIRToLLVMEhSetjmpOpLowering::matchAndRewrite(
3992 cir::EhSetjmpOp op, OpAdaptor adaptor,
3993 mlir::ConversionPatternRewriter &rewriter)
const {
3994 mlir::Type returnType = typeConverter->convertType(op.getType());
3995 mlir::LLVM::CallIntrinsicOp newOp =
3997 returnType, adaptor.getEnv());
3998 rewriter.replaceOp(op, newOp);
3999 return mlir::success();
4002mlir::LogicalResult CIRToLLVMEhLongjmpOpLowering::matchAndRewrite(
4003 cir::EhLongjmpOp op, OpAdaptor adaptor,
4004 mlir::ConversionPatternRewriter &rewriter)
const {
4006 {}, adaptor.getOperands());
4007 return mlir::success();
4010mlir::LogicalResult CIRToLLVMTrapOpLowering::matchAndRewrite(
4011 cir::TrapOp op, OpAdaptor adaptor,
4012 mlir::ConversionPatternRewriter &rewriter)
const {
4013 mlir::Location loc = op->getLoc();
4014 rewriter.eraseOp(op);
4016 mlir::LLVM::Trap::create(rewriter, loc);
4021 mlir::LLVM::UnreachableOp::create(rewriter, loc);
4023 return mlir::success();
4028 mlir::ConversionPatternRewriter &rewriter,
4029 const mlir::TypeConverter *converter,
4030 mlir::FlatSymbolRefAttr nameAttr, mlir::Type &eltType) {
4031 auto module = op->getParentOfType<mlir::ModuleOp>();
4032 mlir::Operation *symbol = mlir::SymbolTable::lookupSymbolIn(module, nameAttr);
4033 if (
auto llvmSymbol = mlir::dyn_cast<mlir::LLVM::GlobalOp>(symbol)) {
4034 eltType = llvmSymbol.getType();
4035 }
else if (
auto cirSymbol = mlir::dyn_cast<cir::GlobalOp>(symbol)) {
4036 eltType = converter->convertType(cirSymbol.getSymType());
4038 op->emitError() <<
"unexpected symbol type for " << symbol;
4042 return mlir::LLVM::AddressOfOp::create(
4043 rewriter, op->getLoc(),
4044 mlir::LLVM::LLVMPointerType::get(op->getContext()), nameAttr.getValue());
4047mlir::LogicalResult CIRToLLVMVTableAddrPointOpLowering::matchAndRewrite(
4048 cir::VTableAddrPointOp op, OpAdaptor adaptor,
4049 mlir::ConversionPatternRewriter &rewriter)
const {
4050 const mlir::TypeConverter *converter = getTypeConverter();
4051 mlir::Type targetType = converter->convertType(op.getType());
4054 mlir::Value symAddr = getValueForVTableSymbol(op, rewriter, converter,
4055 op.getNameAttr(), eltType);
4057 return op.emitError() <<
"Unable to get value for vtable symbol";
4060 0, op.getAddressPointAttr().getIndex(),
4061 op.getAddressPointAttr().getOffset()};
4063 assert(eltType &&
"Shouldn't ever be missing an eltType here");
4064 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
4065 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
4066 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, targetType, eltType,
4067 symAddr, offsets, inboundsNuw);
4068 return mlir::success();
4071mlir::LogicalResult CIRToLLVMVTableGetVPtrOpLowering::matchAndRewrite(
4072 cir::VTableGetVPtrOp op, OpAdaptor adaptor,
4073 mlir::ConversionPatternRewriter &rewriter)
const {
4077 mlir::Value srcVal = adaptor.getSrc();
4078 rewriter.replaceOp(op, srcVal);
4079 return mlir::success();
4082mlir::LogicalResult CIRToLLVMVTableGetVirtualFnAddrOpLowering::matchAndRewrite(
4083 cir::VTableGetVirtualFnAddrOp op, OpAdaptor adaptor,
4084 mlir::ConversionPatternRewriter &rewriter)
const {
4085 mlir::Type targetType = getTypeConverter()->convertType(op.getType());
4086 auto eltType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4089 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
4090 op, targetType, eltType, adaptor.getVptr(), offsets,
4091 mlir::LLVM::GEPNoWrapFlags::inbounds);
4092 return mlir::success();
4095mlir::LogicalResult CIRToLLVMVTTAddrPointOpLowering::matchAndRewrite(
4096 cir::VTTAddrPointOp op, OpAdaptor adaptor,
4097 mlir::ConversionPatternRewriter &rewriter)
const {
4098 const mlir::Type resultType = getTypeConverter()->convertType(op.getType());
4101 mlir::Value llvmAddr = adaptor.getSymAddr();
4103 if (op.getSymAddr()) {
4104 if (op.getOffset() == 0) {
4105 rewriter.replaceOp(op, {llvmAddr});
4106 return mlir::success();
4109 offsets.push_back(adaptor.getOffset());
4110 eltType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4113 op.getNameAttr(), eltType);
4114 assert(eltType &&
"Shouldn't ever be missing an eltType here");
4115 offsets.push_back(0);
4116 offsets.push_back(adaptor.getOffset());
4118 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
4119 op, resultType, eltType, llvmAddr, offsets,
4120 mlir::LLVM::GEPNoWrapFlags::inbounds);
4121 return mlir::success();
4124mlir::LogicalResult CIRToLLVMVecCreateOpLowering::matchAndRewrite(
4125 cir::VecCreateOp op, OpAdaptor adaptor,
4126 mlir::ConversionPatternRewriter &rewriter)
const {
4129 const auto vecTy = mlir::cast<cir::VectorType>(op.getType());
4130 const mlir::Type llvmTy = typeConverter->convertType(vecTy);
4131 const mlir::Location loc = op.getLoc();
4132 mlir::Value result = mlir::LLVM::PoisonOp::create(rewriter, loc, llvmTy);
4133 assert(vecTy.getSize() == op.getElements().size() &&
4134 "cir.vec.create op count doesn't match vector type elements count");
4136 for (uint64_t i = 0; i < vecTy.getSize(); ++i) {
4137 const mlir::Value indexValue =
4138 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
4139 result = mlir::LLVM::InsertElementOp::create(
4140 rewriter, loc, result, adaptor.getElements()[i], indexValue);
4143 rewriter.replaceOp(op, result);
4144 return mlir::success();
4147mlir::LogicalResult CIRToLLVMVecExtractOpLowering::matchAndRewrite(
4148 cir::VecExtractOp op, OpAdaptor adaptor,
4149 mlir::ConversionPatternRewriter &rewriter)
const {
4150 rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractElementOp>(
4151 op, adaptor.getVec(), adaptor.getIndex());
4152 return mlir::success();
4155mlir::LogicalResult CIRToLLVMVecInsertOpLowering::matchAndRewrite(
4156 cir::VecInsertOp op, OpAdaptor adaptor,
4157 mlir::ConversionPatternRewriter &rewriter)
const {
4158 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertElementOp>(
4159 op, adaptor.getVec(), adaptor.getValue(), adaptor.getIndex());
4160 return mlir::success();
4163mlir::LogicalResult CIRToLLVMVecCmpOpLowering::matchAndRewrite(
4164 cir::VecCmpOp op, OpAdaptor adaptor,
4165 mlir::ConversionPatternRewriter &rewriter)
const {
4166 mlir::Type elementType = elementTypeIfVector(op.getLhs().getType());
4167 mlir::Value bitResult;
4168 if (
auto intType = mlir::dyn_cast<cir::IntType>(elementType)) {
4169 bitResult = mlir::LLVM::ICmpOp::create(
4170 rewriter, op.getLoc(),
4172 adaptor.getLhs(), adaptor.getRhs());
4173 }
else if (mlir::isa<cir::FPTypeInterface>(elementType)) {
4174 bitResult = mlir::LLVM::FCmpOp::create(
4176 adaptor.getLhs(), adaptor.getRhs());
4178 return op.emitError() <<
"unsupported type for VecCmpOp: " << elementType;
4184 if (cast<cir::IntType>(cast<cir::VectorType>(op.getType()).getElementType())
4186 rewriter.replaceOpWithNewOp<mlir::LLVM::SExtOp>(
4187 op, typeConverter->convertType(op.getType()), bitResult);
4189 rewriter.replaceOp(op, bitResult);
4190 return mlir::success();
4193mlir::LogicalResult CIRToLLVMVecSplatOpLowering::matchAndRewrite(
4194 cir::VecSplatOp op, OpAdaptor adaptor,
4195 mlir::ConversionPatternRewriter &rewriter)
const {
4201 cir::VectorType vecTy = op.getType();
4202 mlir::Type llvmTy = typeConverter->convertType(vecTy);
4203 mlir::Location loc = op.getLoc();
4204 mlir::Value poison = mlir::LLVM::PoisonOp::create(rewriter, loc, llvmTy);
4206 mlir::Value elementValue = adaptor.getValue();
4207 if (elementValue.getDefiningOp<mlir::LLVM::PoisonOp>()) {
4210 rewriter.replaceOp(op, poison);
4211 return mlir::success();
4214 if (
auto constValue = elementValue.getDefiningOp<mlir::LLVM::ConstantOp>()) {
4215 if (
auto intAttr = dyn_cast<mlir::IntegerAttr>(constValue.getValue())) {
4216 mlir::DenseIntElementsAttr denseVec = mlir::DenseIntElementsAttr::get(
4217 mlir::cast<mlir::ShapedType>(llvmTy), intAttr.getValue());
4218 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
4219 op, denseVec.getType(), denseVec);
4220 return mlir::success();
4223 if (
auto fpAttr = dyn_cast<mlir::FloatAttr>(constValue.getValue())) {
4224 mlir::DenseFPElementsAttr denseVec = mlir::DenseFPElementsAttr::get(
4225 mlir::cast<mlir::ShapedType>(llvmTy), fpAttr.getValue());
4226 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
4227 op, denseVec.getType(), denseVec);
4228 return mlir::success();
4232 mlir::Value indexValue =
4233 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), 0);
4234 mlir::Value oneElement = mlir::LLVM::InsertElementOp::create(
4235 rewriter, loc, poison, elementValue, indexValue);
4237 rewriter.replaceOpWithNewOp<mlir::LLVM::ShuffleVectorOp>(op, oneElement,
4238 poison, zeroValues);
4239 return mlir::success();
4242mlir::LogicalResult CIRToLLVMVecShuffleOpLowering::matchAndRewrite(
4243 cir::VecShuffleOp op, OpAdaptor adaptor,
4244 mlir::ConversionPatternRewriter &rewriter)
const {
4250 op.getIndices().begin(), op.getIndices().end(),
4251 std::back_inserter(indices), [](mlir::Attribute intAttr) {
4252 return mlir::cast<cir::IntAttr>(intAttr).getValue().getSExtValue();
4254 rewriter.replaceOpWithNewOp<mlir::LLVM::ShuffleVectorOp>(
4255 op, adaptor.getVec1(), adaptor.getVec2(), indices);
4256 return mlir::success();
4259mlir::LogicalResult CIRToLLVMVecShuffleDynamicOpLowering::matchAndRewrite(
4260 cir::VecShuffleDynamicOp op, OpAdaptor adaptor,
4261 mlir::ConversionPatternRewriter &rewriter)
const {
4273 mlir::Location loc = op.getLoc();
4274 mlir::Value input = adaptor.getVec();
4275 mlir::Type llvmIndexVecType =
4276 getTypeConverter()->convertType(op.getIndices().getType());
4277 mlir::Type llvmIndexType = getTypeConverter()->convertType(
4278 elementTypeIfVector(op.getIndices().getType()));
4279 uint64_t numElements =
4280 mlir::cast<cir::VectorType>(op.getVec().getType()).getSize();
4282 uint64_t maskBits = llvm::NextPowerOf2(numElements - 1) - 1;
4283 mlir::Value maskValue = mlir::LLVM::ConstantOp::create(
4284 rewriter, loc, llvmIndexType,
4285 rewriter.getIntegerAttr(llvmIndexType, maskBits));
4286 mlir::Value maskVector =
4287 mlir::LLVM::UndefOp::create(rewriter, loc, llvmIndexVecType);
4289 for (uint64_t i = 0; i < numElements; ++i) {
4290 mlir::Value idxValue =
4291 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
4292 maskVector = mlir::LLVM::InsertElementOp::create(rewriter, loc, maskVector,
4293 maskValue, idxValue);
4296 mlir::Value maskedIndices = mlir::LLVM::AndOp::create(
4297 rewriter, loc, llvmIndexVecType, adaptor.getIndices(), maskVector);
4298 mlir::Value result = mlir::LLVM::UndefOp::create(
4299 rewriter, loc, getTypeConverter()->convertType(op.getVec().getType()));
4300 for (uint64_t i = 0; i < numElements; ++i) {
4301 mlir::Value iValue =
4302 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
4303 mlir::Value indexValue = mlir::LLVM::ExtractElementOp::create(
4304 rewriter, loc, maskedIndices, iValue);
4305 mlir::Value valueAtIndex =
4306 mlir::LLVM::ExtractElementOp::create(rewriter, loc, input, indexValue);
4307 result = mlir::LLVM::InsertElementOp::create(rewriter, loc, result,
4308 valueAtIndex, iValue);
4310 rewriter.replaceOp(op, result);
4311 return mlir::success();
4314mlir::LogicalResult CIRToLLVMVecTernaryOpLowering::matchAndRewrite(
4315 cir::VecTernaryOp op, OpAdaptor adaptor,
4316 mlir::ConversionPatternRewriter &rewriter)
const {
4318 mlir::Value bitVec = mlir::LLVM::ICmpOp::create(
4319 rewriter, op.getLoc(), mlir::LLVM::ICmpPredicate::ne, adaptor.getCond(),
4320 mlir::LLVM::ZeroOp::create(
4321 rewriter, op.getCond().getLoc(),
4322 typeConverter->convertType(op.getCond().getType())));
4323 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(
4324 op, bitVec, adaptor.getLhs(), adaptor.getRhs());
4325 return mlir::success();
4328mlir::LogicalResult CIRToLLVMComplexAddOpLowering::matchAndRewrite(
4329 cir::ComplexAddOp op, OpAdaptor adaptor,
4330 mlir::ConversionPatternRewriter &rewriter)
const {
4331 mlir::Value lhs = adaptor.getLhs();
4332 mlir::Value rhs = adaptor.getRhs();
4333 mlir::Location loc = op.getLoc();
4335 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
4336 mlir::Type complexElemTy =
4337 getTypeConverter()->convertType(
complexType.getElementType());
4338 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
4339 rewriter, loc, complexElemTy, lhs,
ArrayRef(int64_t{0}));
4340 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
4341 rewriter, loc, complexElemTy, lhs,
ArrayRef(int64_t{1}));
4342 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
4343 rewriter, loc, complexElemTy, rhs,
ArrayRef(int64_t{0}));
4344 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
4345 rewriter, loc, complexElemTy, rhs,
ArrayRef(int64_t{1}));
4347 mlir::Value newReal;
4348 mlir::Value newImag;
4349 if (complexElemTy.isInteger()) {
4350 newReal = mlir::LLVM::AddOp::create(rewriter, loc, complexElemTy, lhsReal,
4352 newImag = mlir::LLVM::AddOp::create(rewriter, loc, complexElemTy, lhsImag,
4357 newReal = mlir::LLVM::FAddOp::create(rewriter, loc, complexElemTy, lhsReal,
4359 newImag = mlir::LLVM::FAddOp::create(rewriter, loc, complexElemTy, lhsImag,
4363 mlir::Type complexLLVMTy =
4364 getTypeConverter()->convertType(op.getResult().getType());
4365 auto initialComplex =
4366 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), complexLLVMTy);
4368 auto realComplex = mlir::LLVM::InsertValueOp::create(
4369 rewriter, op->getLoc(), initialComplex, newReal,
ArrayRef(int64_t{0}));
4371 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
4372 op, realComplex, newImag,
ArrayRef(int64_t{1}));
4374 return mlir::success();
4377mlir::LogicalResult CIRToLLVMComplexCreateOpLowering::matchAndRewrite(
4378 cir::ComplexCreateOp op, OpAdaptor adaptor,
4379 mlir::ConversionPatternRewriter &rewriter)
const {
4380 mlir::Type complexLLVMTy =
4381 getTypeConverter()->convertType(op.getResult().getType());
4382 auto initialComplex =
4383 mlir::LLVM::UndefOp::create(rewriter, op->getLoc(), complexLLVMTy);
4385 auto realComplex = mlir::LLVM::InsertValueOp::create(
4386 rewriter, op->getLoc(), initialComplex, adaptor.getReal(),
4389 auto complex = mlir::LLVM::InsertValueOp::create(
4390 rewriter, op->getLoc(), realComplex, adaptor.getImag(),
4393 rewriter.replaceOp(op, complex);
4394 return mlir::success();
4397mlir::LogicalResult CIRToLLVMComplexRealOpLowering::matchAndRewrite(
4398 cir::ComplexRealOp op, OpAdaptor adaptor,
4399 mlir::ConversionPatternRewriter &rewriter)
const {
4400 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
4401 mlir::Value operand = adaptor.getOperand();
4402 if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) {
4403 operand = mlir::LLVM::ExtractValueOp::create(
4404 rewriter, op.getLoc(), resultLLVMTy, operand,
4407 rewriter.replaceOp(op, operand);
4408 return mlir::success();
4411mlir::LogicalResult CIRToLLVMComplexSubOpLowering::matchAndRewrite(
4412 cir::ComplexSubOp op, OpAdaptor adaptor,
4413 mlir::ConversionPatternRewriter &rewriter)
const {
4414 mlir::Value lhs = adaptor.getLhs();
4415 mlir::Value rhs = adaptor.getRhs();
4416 mlir::Location loc = op.getLoc();
4418 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
4419 mlir::Type complexElemTy =
4420 getTypeConverter()->convertType(
complexType.getElementType());
4421 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
4422 rewriter, loc, complexElemTy, lhs,
ArrayRef(int64_t{0}));
4423 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
4424 rewriter, loc, complexElemTy, lhs,
ArrayRef(int64_t{1}));
4425 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
4426 rewriter, loc, complexElemTy, rhs,
ArrayRef(int64_t{0}));
4427 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
4428 rewriter, loc, complexElemTy, rhs,
ArrayRef(int64_t{1}));
4430 mlir::Value newReal;
4431 mlir::Value newImag;
4432 if (complexElemTy.isInteger()) {
4433 newReal = mlir::LLVM::SubOp::create(rewriter, loc, complexElemTy, lhsReal,
4435 newImag = mlir::LLVM::SubOp::create(rewriter, loc, complexElemTy, lhsImag,
4440 newReal = mlir::LLVM::FSubOp::create(rewriter, loc, complexElemTy, lhsReal,
4442 newImag = mlir::LLVM::FSubOp::create(rewriter, loc, complexElemTy, lhsImag,
4446 mlir::Type complexLLVMTy =
4447 getTypeConverter()->convertType(op.getResult().getType());
4448 auto initialComplex =
4449 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), complexLLVMTy);
4451 auto realComplex = mlir::LLVM::InsertValueOp::create(
4452 rewriter, op->getLoc(), initialComplex, newReal,
ArrayRef(int64_t{0}));
4454 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
4455 op, realComplex, newImag,
ArrayRef(int64_t{1}));
4457 return mlir::success();
4460mlir::LogicalResult CIRToLLVMComplexImagOpLowering::matchAndRewrite(
4461 cir::ComplexImagOp op, OpAdaptor adaptor,
4462 mlir::ConversionPatternRewriter &rewriter)
const {
4463 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
4464 mlir::Value operand = adaptor.getOperand();
4465 mlir::Location loc = op.getLoc();
4467 if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) {
4468 operand = mlir::LLVM::ExtractValueOp::create(
4471 mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(resultLLVMTy);
4473 mlir::LLVM::ConstantOp::create(rewriter, loc, resultLLVMTy, zeroAttr);
4476 rewriter.replaceOp(op, operand);
4477 return mlir::success();
4481 mlir::MLIRContext *context,
4482 unsigned &storageSize) {
4483 return TypeSwitch<mlir::Type, mlir::IntegerType>(storageType)
4484 .Case<cir::ArrayType>([&](cir::ArrayType atTy) {
4485 storageSize = atTy.getSize() * 8;
4486 return mlir::IntegerType::get(context, storageSize);
4488 .Case<cir::IntType>([&](cir::IntType intTy) {
4489 storageSize = intTy.getWidth();
4490 return mlir::IntegerType::get(context, storageSize);
4492 .Default([](mlir::Type) -> mlir::IntegerType {
4494 "Either ArrayType or IntType expected for bitfields storage");
4498mlir::LogicalResult CIRToLLVMSetBitfieldOpLowering::matchAndRewrite(
4499 cir::SetBitfieldOp op, OpAdaptor adaptor,
4500 mlir::ConversionPatternRewriter &rewriter)
const {
4501 mlir::OpBuilder::InsertionGuard guard(rewriter);
4502 rewriter.setInsertionPoint(op);
4504 cir::BitfieldInfoAttr info = op.getBitfieldInfo();
4505 uint64_t size = info.getSize();
4506 uint64_t offset = info.getOffset();
4507 mlir::Type storageType = info.getStorageType();
4508 mlir::MLIRContext *context = storageType.getContext();
4510 unsigned storageSize = 0;
4512 mlir::IntegerType intType =
4513 computeBitfieldIntType(storageType, context, storageSize);
4515 mlir::Value srcVal = createIntCast(rewriter, adaptor.getSrc(), intType);
4516 unsigned srcWidth = storageSize;
4517 mlir::Value resultVal = srcVal;
4519 if (storageSize != size) {
4520 assert(storageSize > size &&
"Invalid bitfield size.");
4522 mlir::Value val = mlir::LLVM::LoadOp::create(
4523 rewriter, op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(),
4524 op.getIsVolatile());
4527 createAnd(rewriter, srcVal, llvm::APInt::getLowBitsSet(srcWidth, size));
4529 srcVal =
createShL(rewriter, srcVal, offset);
4533 ~llvm::APInt::getBitsSet(srcWidth, offset, offset + size));
4536 srcVal = mlir::LLVM::OrOp::create(rewriter, op.getLoc(), val, srcVal);
4539 mlir::LLVM::StoreOp::create(rewriter, op.getLoc(), srcVal, adaptor.getAddr(),
4540 op.getAlignment(), op.getIsVolatile());
4542 mlir::Type resultTy = getTypeConverter()->convertType(op.getType());
4544 if (info.getIsSigned()) {
4545 assert(size <= storageSize);
4546 unsigned highBits = storageSize - size;
4549 resultVal =
createShL(rewriter, resultVal, highBits);
4550 resultVal =
createAShR(rewriter, resultVal, highBits);
4555 mlir::cast<mlir::IntegerType>(resultTy),
4556 info.getIsSigned());
4558 rewriter.replaceOp(op, resultVal);
4559 return mlir::success();
4562mlir::LogicalResult CIRToLLVMComplexImagPtrOpLowering::matchAndRewrite(
4563 cir::ComplexImagPtrOp op, OpAdaptor adaptor,
4564 mlir::ConversionPatternRewriter &rewriter)
const {
4565 cir::PointerType operandTy = op.getOperand().getType();
4566 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
4567 mlir::Type elementLLVMTy =
4568 getTypeConverter()->convertType(operandTy.getPointee());
4570 mlir::LLVM::GEPArg gepIndices[2] = {{0}, {1}};
4571 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
4572 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
4573 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
4574 op, resultLLVMTy, elementLLVMTy, adaptor.getOperand(), gepIndices,
4576 return mlir::success();
4579mlir::LogicalResult CIRToLLVMComplexRealPtrOpLowering::matchAndRewrite(
4580 cir::ComplexRealPtrOp op, OpAdaptor adaptor,
4581 mlir::ConversionPatternRewriter &rewriter)
const {
4582 cir::PointerType operandTy = op.getOperand().getType();
4583 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
4584 mlir::Type elementLLVMTy =
4585 getTypeConverter()->convertType(operandTy.getPointee());
4587 mlir::LLVM::GEPArg gepIndices[2] = {0, 0};
4588 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
4589 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
4590 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
4591 op, resultLLVMTy, elementLLVMTy, adaptor.getOperand(), gepIndices,
4593 return mlir::success();
4596mlir::LogicalResult CIRToLLVMGetBitfieldOpLowering::matchAndRewrite(
4597 cir::GetBitfieldOp op, OpAdaptor adaptor,
4598 mlir::ConversionPatternRewriter &rewriter)
const {
4600 mlir::OpBuilder::InsertionGuard guard(rewriter);
4601 rewriter.setInsertionPoint(op);
4603 cir::BitfieldInfoAttr info = op.getBitfieldInfo();
4604 uint64_t size = info.getSize();
4605 uint64_t offset = info.getOffset();
4606 mlir::Type storageType = info.getStorageType();
4607 mlir::MLIRContext *context = storageType.getContext();
4608 unsigned storageSize = 0;
4610 mlir::IntegerType intType =
4613 mlir::Value val = mlir::LLVM::LoadOp::create(
4614 rewriter, op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(),
4615 op.getIsVolatile());
4616 val = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), intType, val);
4618 if (info.getIsSigned()) {
4619 assert(
static_cast<unsigned>(offset + size) <= storageSize);
4620 unsigned highBits = storageSize - offset - size;
4621 val =
createShL(rewriter, val, highBits);
4622 val =
createAShR(rewriter, val, offset + highBits);
4626 if (
static_cast<unsigned>(offset) + size < storageSize)
4628 llvm::APInt::getLowBitsSet(storageSize, size));
4631 mlir::Type resTy = getTypeConverter()->convertType(op.getType());
4633 rewriter, val, mlir::cast<mlir::IntegerType>(resTy), info.getIsSigned());
4634 rewriter.replaceOp(op, newOp);
4635 return mlir::success();
4638mlir::LogicalResult CIRToLLVMInlineAsmOpLowering::matchAndRewrite(
4639 cir::InlineAsmOp op, OpAdaptor adaptor,
4640 mlir::ConversionPatternRewriter &rewriter)
const {
4642 if (op.getNumResults())
4643 llResTy = getTypeConverter()->convertType(op.getType(0));
4645 cir::AsmFlavor dialect = op.getAsmFlavor();
4646 mlir::LLVM::AsmDialect llDialect = dialect == cir::AsmFlavor::x86_att
4647 ? mlir::LLVM::AsmDialect::AD_ATT
4648 : mlir::LLVM::AsmDialect::AD_Intel;
4651 StringRef llvmAttrName = mlir::LLVM::InlineAsmOp::getElementTypeAttrName();
4657 if (!op.getNumResults())
4658 opAttrs.push_back(mlir::Attribute());
4662 for (
auto const &[llvmOp, cirOp] :
4663 zip(adaptor.getAsmOperands(), op.getAsmOperands())) {
4664 append_range(llvmOperands, llvmOp);
4665 append_range(cirOperands, cirOp);
4670 for (
auto const &[cirOpAttr, cirOp] :
4671 zip(op.getOperandAttrs(), cirOperands)) {
4672 if (!mlir::isa<mlir::UnitAttr>(cirOpAttr)) {
4673 opAttrs.push_back(mlir::Attribute());
4678 cir::PointerType typ = mlir::cast<cir::PointerType>(cirOp.getType());
4680 *getTypeConverter(), dataLayout, typ.getPointee()));
4682 attrs.push_back(rewriter.getNamedAttr(llvmAttrName, typAttr));
4683 mlir::DictionaryAttr newDict = rewriter.getDictionaryAttr(attrs);
4684 opAttrs.push_back(newDict);
4687 rewriter.replaceOpWithNewOp<mlir::LLVM::InlineAsmOp>(
4688 op, llResTy, llvmOperands, op.getAsmStringAttr(), op.getConstraintsAttr(),
4689 op.getSideEffectsAttr(),
4692 mlir::LLVM::TailCallKindAttr::get(
4693 getContext(), mlir::LLVM::tailcallkind::TailCallKind::None),
4694 mlir::LLVM::AsmDialectAttr::get(getContext(), llDialect),
4695 rewriter.getArrayAttr(opAttrs));
4697 return mlir::success();
4700mlir::LogicalResult CIRToLLVMVAStartOpLowering::matchAndRewrite(
4701 cir::VAStartOp op, OpAdaptor adaptor,
4702 mlir::ConversionPatternRewriter &rewriter)
const {
4703 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4704 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4705 adaptor.getArgList());
4706 rewriter.replaceOpWithNewOp<mlir::LLVM::VaStartOp>(op, vaList);
4707 return mlir::success();
4710mlir::LogicalResult CIRToLLVMVAEndOpLowering::matchAndRewrite(
4711 cir::VAEndOp op, OpAdaptor adaptor,
4712 mlir::ConversionPatternRewriter &rewriter)
const {
4713 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4714 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4715 adaptor.getArgList());
4716 rewriter.replaceOpWithNewOp<mlir::LLVM::VaEndOp>(op, vaList);
4717 return mlir::success();
4720mlir::LogicalResult CIRToLLVMVACopyOpLowering::matchAndRewrite(
4721 cir::VACopyOp op, OpAdaptor adaptor,
4722 mlir::ConversionPatternRewriter &rewriter)
const {
4723 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4724 auto dstList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4725 adaptor.getDstList());
4726 auto srcList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4727 adaptor.getSrcList());
4728 rewriter.replaceOpWithNewOp<mlir::LLVM::VaCopyOp>(op, dstList, srcList);
4729 return mlir::success();
4732mlir::LogicalResult CIRToLLVMVAArgOpLowering::matchAndRewrite(
4733 cir::VAArgOp op, OpAdaptor adaptor,
4734 mlir::ConversionPatternRewriter &rewriter)
const {
4736 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4737 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4738 adaptor.getArgList());
4740 mlir::Type llvmType =
4741 getTypeConverter()->convertType(op->getResultTypes().front());
4743 return mlir::failure();
4745 rewriter.replaceOpWithNewOp<mlir::LLVM::VaArgOp>(op, llvmType, vaList);
4746 return mlir::success();
4749mlir::LogicalResult CIRToLLVMLabelOpLowering::matchAndRewrite(
4750 cir::LabelOp op, OpAdaptor adaptor,
4751 mlir::ConversionPatternRewriter &rewriter)
const {
4752 mlir::MLIRContext *ctx = rewriter.getContext();
4753 mlir::Block *block = op->getBlock();
4756 if (block->isEntryBlock()) {
4757 mlir::Block *newBlock =
4758 rewriter.splitBlock(op->getBlock(), mlir::Block::iterator(op));
4759 rewriter.setInsertionPointToEnd(block);
4760 mlir::LLVM::BrOp::create(rewriter, op.getLoc(), newBlock);
4763 mlir::LLVM::BlockTagAttr::get(ctx, blockInfoAddr.getTagIndex());
4764 rewriter.setInsertionPoint(op);
4767 mlir::LLVM::BlockTagOp::create(rewriter, op->getLoc(), tagAttr);
4768 mlir::LLVM::LLVMFuncOp func = op->getParentOfType<mlir::LLVM::LLVMFuncOp>();
4769 auto blockInfoAttr =
4770 cir::BlockAddrInfoAttr::get(ctx, func.getSymName(), op.getLabel());
4771 blockInfoAddr.mapBlockTag(blockInfoAttr, blockTagOp);
4772 rewriter.eraseOp(op);
4774 return mlir::success();
4777mlir::LogicalResult CIRToLLVMBlockAddressOpLowering::matchAndRewrite(
4778 cir::BlockAddressOp op, OpAdaptor adaptor,
4779 mlir::ConversionPatternRewriter &rewriter)
const {
4780 mlir::MLIRContext *ctx = rewriter.getContext();
4782 mlir::LLVM::BlockTagOp matchLabel =
4783 blockInfoAddr.lookupBlockTag(op.getBlockAddrInfoAttr());
4784 mlir::LLVM::BlockTagAttr tagAttr;
4791 tagAttr = matchLabel.getTag();
4793 auto blkAddr = mlir::LLVM::BlockAddressAttr::get(
4794 rewriter.getContext(), op.getBlockAddrInfoAttr().getFunc(), tagAttr);
4795 rewriter.setInsertionPoint(op);
4796 auto newOp = mlir::LLVM::BlockAddressOp::create(
4797 rewriter, op.getLoc(), mlir::LLVM::LLVMPointerType::get(ctx), blkAddr);
4799 blockInfoAddr.addUnresolvedBlockAddress(newOp, op.getBlockAddrInfoAttr());
4800 rewriter.replaceOp(op, newOp);
4801 return mlir::success();
4804mlir::LogicalResult CIRToLLVMIndirectBrOpLowering::matchAndRewrite(
4805 cir::IndirectBrOp op, OpAdaptor adaptor,
4806 mlir::ConversionPatternRewriter &rewriter)
const {
4808 mlir::Value targetAddr = adaptor.getAddr();
4816 if (op.getPoison()) {
4817 auto llvmPtrType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4819 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), llvmPtrType);
4822 rewriter.replaceOpWithNewOp<mlir::LLVM::IndirectBrOp>(
4823 op, targetAddr, adaptor.getSuccOperands(), op.getSuccessors());
4824 return mlir::success();
4827mlir::LogicalResult CIRToLLVMAwaitOpLowering::matchAndRewrite(
4828 cir::AwaitOp op, OpAdaptor adaptor,
4829 mlir::ConversionPatternRewriter &rewriter)
const {
4830 return mlir::failure();
4833mlir::LogicalResult CIRToLLVMCpuIdOpLowering::matchAndRewrite(
4834 cir::CpuIdOp op, OpAdaptor adaptor,
4835 mlir::ConversionPatternRewriter &rewriter)
const {
4836 mlir::Type i32Ty = rewriter.getI32Type();
4837 mlir::Type i64Ty = rewriter.getI64Type();
4838 mlir::Type i32PtrTy = mlir::LLVM::LLVMPointerType::get(i32Ty.getContext(), 0);
4840 mlir::Type cpuidRetTy = mlir::LLVM::LLVMStructType::getLiteral(
4841 rewriter.getContext(), {i32Ty, i32Ty, i32Ty, i32Ty});
4843 mlir::Value functionId = adaptor.getFunctionId();
4844 mlir::Value subFunctionId = adaptor.getSubFunctionId();
4846 StringRef asmString, constraints;
4847 mlir::ModuleOp moduleOp = op->getParentOfType<mlir::ModuleOp>();
4848 llvm::Triple triple(
4849 mlir::cast<mlir::StringAttr>(
4850 moduleOp->getAttr(cir::CIRDialect::getTripleAttrName()))
4852 if (triple.getArch() == llvm::Triple::x86) {
4853 asmString =
"cpuid";
4854 constraints =
"={ax},={bx},={cx},={dx},{ax},{cx}";
4857 asmString =
"xchgq %rbx, ${1:q}\n"
4859 "xchgq %rbx, ${1:q}";
4860 constraints =
"={ax},=r,={cx},={dx},0,2";
4863 mlir::Value inlineAsm =
4864 mlir::LLVM::InlineAsmOp::create(
4865 rewriter, op.getLoc(), cpuidRetTy, {functionId, subFunctionId},
4866 rewriter.getStringAttr(asmString),
4867 rewriter.getStringAttr(constraints),
4870 mlir::LLVM::TailCallKindAttr{},
4871 mlir::LLVM::AsmDialectAttr{},
4875 mlir::Value basePtr = adaptor.getCpuInfo();
4877 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
4878 unsigned alignment = layout.getTypeABIAlignment(i32Ty);
4879 for (
unsigned i = 0; i < 4; i++) {
4880 mlir::Value extracted =
4881 mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(), inlineAsm, i)
4883 mlir::Value index = mlir::LLVM::ConstantOp::create(
4884 rewriter, op.getLoc(), i64Ty, rewriter.getI64IntegerAttr(i));
4886 mlir::Value storePtr = mlir::LLVM::GEPOp::create(
4887 rewriter, op.getLoc(), i32PtrTy, i32Ty, basePtr,
4888 gepIndices, mlir::LLVM::GEPNoWrapFlags::none)
4890 mlir::LLVM::StoreOp::create(rewriter, op.getLoc(), extracted, storePtr,
4894 rewriter.eraseOp(op);
4895 return mlir::success();
4898mlir::LogicalResult CIRToLLVMMemChrOpLowering::matchAndRewrite(
4899 cir::MemChrOp op, OpAdaptor adaptor,
4900 mlir::ConversionPatternRewriter &rewriter)
const {
4901 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4902 mlir::Type srcTy = getTypeConverter()->convertType(op.getSrc().getType());
4903 mlir::Type patternTy =
4904 getTypeConverter()->convertType(op.getPattern().getType());
4905 mlir::Type lenTy = getTypeConverter()->convertType(op.getLen().getType());
4907 mlir::LLVM::LLVMFunctionType::get(llvmPtrTy, {srcTy, patternTy, lenTy},
4909 llvm::StringRef fnName =
"memchr";
4911 mlir::Builder b(rewriter.getContext());
4912 mlir::NamedAttribute noundefAttr =
4913 b.getNamedAttr(
"llvm.noundef", b.getUnitAttr());
4914 mlir::DictionaryAttr noundefDict = mlir::DictionaryAttr::get(
4917 mlir::ArrayAttr argAttrs =
4918 mlir::ArrayAttr::get(rewriter.getContext(), argAttrVec);
4922 mlir::LLVM::CallOp newCall = rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(
4923 op, mlir::TypeRange{llvmPtrTy}, fnName,
4924 mlir::ValueRange{adaptor.getSrc(), adaptor.getPattern(),
4926 newCall.setArgAttrsAttr(argAttrs);
4927 return mlir::success();
4931 return std::make_unique<ConvertCIRToLLVMPass>();
4936 pm.addPass(mlir::omp::createMarkDeclareTargetPass());
4940std::unique_ptr<llvm::Module>
4942 StringRef mlirSaveTempsOutFile,
4943 llvm::vfs::FileSystem *fs) {
4944 llvm::TimeTraceScope scope(
"lower from CIR to LLVM directly");
4946 mlir::MLIRContext *mlirCtx = mlirModule.getContext();
4948 mlir::PassManager pm(mlirCtx);
4951 (void)mlir::applyPassManagerCLOptions(pm);
4953 if (mlir::failed(pm.run(mlirModule))) {
4956 "The pass manager failed to lower CIR to LLVMIR dialect!");
4959 if (!mlirSaveTempsOutFile.empty()) {
4961 llvm::raw_fd_ostream out(mlirSaveTempsOutFile, ec);
4963 mlirModule->print(out);
4966 mlir::registerBuiltinDialectTranslation(*mlirCtx);
4967 mlir::registerLLVMDialectTranslation(*mlirCtx);
4968 mlir::registerOpenMPDialectTranslation(*mlirCtx);
4971 llvm::TimeTraceScope translateScope(
"translateModuleToLLVMIR");
4973 StringRef moduleName = mlirModule.getName().value_or(
"CIRToLLVMModule");
4974 std::unique_ptr<llvm::Module> llvmModule = mlir::translateModuleToLLVMIR(
4975 mlirModule, llvmCtx, moduleName,
false, fs);
4979 report_fatal_error(
"Lowering from LLVMIR dialect to llvm IR failed!");
static bool isUnsigned(SValBuilder &SVB, NonLoc Value)
static llvm::StringRef getLinkageAttrNameString()
Returns the name used for the linkage attribute.
mlir::Value createLShR(mlir::OpBuilder &bld, mlir::Value lhs, unsigned rhs)
mlir::Value createShL(mlir::OpBuilder &bld, mlir::Value lhs, unsigned rhs)
mlir::Value createAShR(mlir::OpBuilder &bld, mlir::Value lhs, unsigned rhs)
mlir::Value createAnd(mlir::OpBuilder &bld, mlir::Value lhs, const llvm::APInt &rhs)
std::optional< mlir::Attribute > lowerConstArrayAttr(cir::ConstArrayAttr constArr, const mlir::TypeConverter *converter, mlir::ModuleOp moduleOp={})
*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::LogicalResult lowerIncDecOp(CIROp op, typename CIROp::Adaptor adaptor, mlir::ConversionPatternRewriter &rewriter)
static mlir::LLVM::AtomicBinOp getLLVMAtomicBinOp(cir::AtomicFetchKind k, bool isInt, bool isSignedInt)
static mlir::LLVM::ICmpPredicate convertCmpKindToICmpPredicate(cir::CmpOpKind kind, bool isSigned)
Convert from a CIR comparison kind to an LLVM IR integral comparison kind.
void convertSideEffectForCall(mlir::Operation *callOp, bool isNothrow, cir::SideEffect sideEffect, mlir::LLVM::MemoryEffectsAttr &memoryEffect, bool &noUnwind, bool &willReturn, bool &noReturn)
static bool isBulkLowerableConstArrayBaseElement(mlir::Type baseElemTy)
static mlir::LLVM::IntegerOverflowFlags intOverflowFlag(BinOp op)
void createLLVMFuncOpIfNotExist(mlir::ConversionPatternRewriter &rewriter, mlir::Operation *srcOp, llvm::StringRef fnName, mlir::Type fnTy, mlir::ArrayAttr argAttrs=nullptr, mlir::ArrayAttr resAttrs=nullptr)
static mlir::Value getLLVMIntCast(mlir::ConversionPatternRewriter &rewriter, mlir::Value llvmSrc, mlir::Type llvmDstIntTy, bool isUnsigned, uint64_t cirSrcWidth, uint64_t cirDstIntWidth)
static mlir::Value emitFromMemory(mlir::ConversionPatternRewriter &rewriter, mlir::DataLayout const &dataLayout, cir::LoadOp op, mlir::Value value)
Emits the value from memory as expected by its users.
mlir::IntegerType computeBitfieldIntType(mlir::Type storageType, mlir::MLIRContext *context, unsigned &storageSize)
static mlir::LLVM::CallIntrinsicOp createCallLLVMIntrinsicOp(mlir::ConversionPatternRewriter &rewriter, mlir::Location loc, const llvm::Twine &intrinsicName, mlir::Type resultTy, mlir::ValueRange operands)
static mlir::LogicalResult lowerMinMaxOp(CIROp op, typename CIROp::Adaptor adaptor, mlir::ConversionPatternRewriter &rewriter)
static mlir::LLVM::LLVMStructType getLLVMLandingPadStructTy(mlir::ConversionPatternRewriter &rewriter)
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 lowerIntBinaryOp(CIROp op, mlir::Value lhs, mlir::Value rhs, mlir::ConversionPatternRewriter &rewriter)
Lower an integer Div/Rem op to its signed or unsigned LLVM counterpart.
static mlir::LLVM::CallIntrinsicOp replaceOpWithCallLLVMIntrinsicOp(mlir::ConversionPatternRewriter &rewriter, mlir::Operation *op, const llvm::Twine &intrinsicName, mlir::Type resultTy, mlir::ValueRange operands)
static void prepareTypeConverter(mlir::LLVMTypeConverter &converter, mlir::DataLayout &dataLayout)
static mlir::LLVM::AtomicOrdering getLLVMMemOrder(std::optional< cir::MemOrder > memorder)
std::unique_ptr< mlir::Pass > createConvertCIRToLLVMPass()
Create a pass that fully lowers CIR to the LLVMIR dialect.
static llvm::StringRef getLLVMSyncScope(cir::SyncScopeKind syncScope)
static mlir::LogicalResult lowerSaturatableArithOp(CIROp op, mlir::Value lhs, mlir::Value rhs, mlir::ConversionPatternRewriter &rewriter)
Lower an arithmetic op that supports saturation, overflow flags, and an FP Lower an integer Add/Sub o...
static mlir::Type getConstArrayBaseElementType(mlir::Type ty)
static mlir::LLVM::FCmpPredicate convertCmpKindToFCmpPredicate(cir::CmpOpKind kind)
Convert from a CIR comparison kind to an LLVM IR floating-point comparison kind.
static mlir::LogicalResult rewriteCallOrInvoke(mlir::Operation *op, mlir::ValueRange callOperands, mlir::ConversionPatternRewriter &rewriter, const mlir::TypeConverter *converter, mlir::SymbolTableCollection &symbolTables, mlir::FlatSymbolRefAttr calleeAttr, mlir::Block *continueBlock=nullptr, mlir::Block *landingPadBlock=nullptr)
static 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
@ Default
Set to the current date and time.
Diagnostic wrappers for TextAPI types for error reporting.
void populateCIRPreLoweringPasses(mlir::OpPassManager &pm)
void registerCIRDialectTranslation(mlir::MLIRContext &context)
char __ovld __cnfn clz(char)
Returns the number of leading 0-bits in x, starting at the most significant bit position.
char __ovld __cnfn ctz(char)
Returns the count of trailing 0-bits in x.
float __ovld __cnfn sign(float)
Returns 1.0 if x > 0, -0.0 if x = -0.0, +0.0 if x = +0.0, or -1.0 if x < 0.
float __ovld __cnfn length(float)
Return the length of vector p, i.e., sqrt(p.x2 + p.y 2 + ...)
char __ovld __cnfn select(char, char, char)
For each component of a vector type, result[i] = if MSB of c[i] is set ?
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 __packed_splat2 __packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 uint32_t
static bool dataMemberType()
static bool addressSpace()
static bool globalViewIntLowering()
static bool opAllocaAnnotations()
static bool opLoadStoreTbaa()
static bool optInfoAttr()
static bool opFuncExtraAttrs()
static bool isPPC_FP128Ty()
static bool vaArgABILowering()
static bool fpConstraints()
static bool intrinsicElementTypeSupport()
static bool lowerModeOptLevel()
static bool opCallCallConv()
static bool aggValueSlotVolatile()
static bool fastMathFlags()
static bool llvmLoweringPtrDiffConsidersPointee()
static bool 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()