19#include "mlir/Conversion/LLVMCommon/TypeConverter.h"
20#include "mlir/Conversion/OpenMPToLLVM/ConvertOpenMPToLLVM.h"
21#include "mlir/Dialect/DLTI/DLTI.h"
22#include "mlir/Dialect/Func/IR/FuncOps.h"
23#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
24#include "mlir/Dialect/LLVMIR/LLVMTypes.h"
25#include "mlir/Dialect/OpenMP/OpenMPDialect.h"
26#include "mlir/Dialect/OpenMP/Transforms/Passes.h"
27#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
28#include "mlir/IR/BuiltinAttributes.h"
29#include "mlir/IR/BuiltinDialect.h"
30#include "mlir/IR/BuiltinOps.h"
31#include "mlir/IR/Types.h"
32#include "mlir/Pass/Pass.h"
33#include "mlir/Pass/PassManager.h"
34#include "mlir/Support/LLVM.h"
35#include "mlir/Target/LLVMIR/Dialect/Builtin/BuiltinToLLVMIRTranslation.h"
36#include "mlir/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.h"
37#include "mlir/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.h"
38#include "mlir/Target/LLVMIR/Export.h"
39#include "mlir/Transforms/DialectConversion.h"
47#include "llvm/ADT/TypeSwitch.h"
48#include "llvm/IR/Module.h"
49#include "llvm/Support/Casting.h"
50#include "llvm/Support/ErrorHandling.h"
51#include "llvm/Support/TimeProfiler.h"
52#include "llvm/Support/raw_ostream.h"
67mlir::Type elementTypeIfVector(mlir::Type type) {
68 return llvm::TypeSwitch<mlir::Type, mlir::Type>(type)
69 .Case<cir::VectorType, mlir::VectorType>(
70 [](
auto p) {
return p.getElementType(); })
71 .
Default([](mlir::Type p) {
return p; });
79 mlir::DataLayout
const &dataLayout,
83 if (isa<cir::BoolType>(type)) {
84 return mlir::IntegerType::get(type.getContext(),
85 dataLayout.getTypeSizeInBits(type));
88 return converter.convertType(type);
92 mlir::IntegerType dstTy,
93 bool isSigned =
false) {
94 mlir::Type srcTy = src.getType();
95 assert(mlir::isa<mlir::IntegerType>(srcTy));
97 unsigned srcWidth = mlir::cast<mlir::IntegerType>(srcTy).getWidth();
98 unsigned dstWidth = mlir::cast<mlir::IntegerType>(dstTy).getWidth();
99 mlir::Location loc = src.getLoc();
101 if (dstWidth > srcWidth && isSigned)
102 return mlir::LLVM::SExtOp::create(bld, loc, dstTy, src);
103 if (dstWidth > srcWidth)
104 return mlir::LLVM::ZExtOp::create(bld, loc, dstTy, src);
105 if (dstWidth < srcWidth)
106 return mlir::LLVM::TruncOp::create(bld, loc, dstTy, src);
107 return mlir::LLVM::BitcastOp::create(bld, loc, dstTy, src);
110static mlir::LLVM::Visibility
112 switch (visibilityKind) {
113 case cir::VisibilityKind::Default:
114 return ::mlir::LLVM::Visibility::Default;
115 case cir::VisibilityKind::Hidden:
116 return ::mlir::LLVM::Visibility::Hidden;
117 case cir::VisibilityKind::Protected:
118 return ::mlir::LLVM::Visibility::Protected;
126 mlir::DataLayout
const &dataLayout,
127 cir::LoadOp op, mlir::Value value) {
130 if (
auto boolTy = mlir::dyn_cast<cir::BoolType>(op.getType())) {
132 assert(value.getType().isInteger(dataLayout.getTypeSizeInBits(boolTy)));
142static mlir::Value
emitToMemory(mlir::ConversionPatternRewriter &rewriter,
143 mlir::DataLayout
const &dataLayout,
144 mlir::Type origType, mlir::Value value) {
147 if (
auto boolTy = mlir::dyn_cast<cir::BoolType>(origType)) {
149 mlir::IntegerType memType =
150 rewriter.getIntegerType(dataLayout.getTypeSizeInBits(boolTy));
158 using CIR = cir::GlobalLinkageKind;
159 using LLVM = mlir::LLVM::Linkage;
162 case CIR::AppendingLinkage:
163 return LLVM::Appending;
164 case CIR::AvailableExternallyLinkage:
165 return LLVM::AvailableExternally;
166 case CIR::CommonLinkage:
168 case CIR::ExternalLinkage:
169 return LLVM::External;
170 case CIR::ExternalWeakLinkage:
171 return LLVM::ExternWeak;
172 case CIR::InternalLinkage:
173 return LLVM::Internal;
174 case CIR::LinkOnceAnyLinkage:
175 return LLVM::Linkonce;
176 case CIR::LinkOnceODRLinkage:
177 return LLVM::LinkonceODR;
178 case CIR::PrivateLinkage:
179 return LLVM::Private;
180 case CIR::WeakAnyLinkage:
182 case CIR::WeakODRLinkage:
183 return LLVM::WeakODR;
185 llvm_unreachable(
"Unknown CIR linkage type");
188mlir::LogicalResult CIRToLLVMCopyOpLowering::matchAndRewrite(
189 cir::CopyOp op, OpAdaptor adaptor,
190 mlir::ConversionPatternRewriter &rewriter)
const {
191 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
192 const mlir::Value
length = mlir::LLVM::ConstantOp::create(
193 rewriter, op.getLoc(), rewriter.getI64Type(),
194 op.getCopySizeInBytes(layout));
196 rewriter.replaceOpWithNewOp<mlir::LLVM::MemcpyOp>(
197 op, adaptor.getDst(), adaptor.getSrc(),
length, op.getIsVolatile());
198 return mlir::success();
201mlir::LogicalResult CIRToLLVMMemCpyOpLowering::matchAndRewrite(
202 cir::MemCpyOp op, OpAdaptor adaptor,
203 mlir::ConversionPatternRewriter &rewriter)
const {
204 rewriter.replaceOpWithNewOp<mlir::LLVM::MemcpyOp>(
205 op, adaptor.getDst(), adaptor.getSrc(), adaptor.getLen(),
207 return mlir::success();
210mlir::LogicalResult CIRToLLVMMemMoveOpLowering::matchAndRewrite(
211 cir::MemMoveOp op, OpAdaptor adaptor,
212 mlir::ConversionPatternRewriter &rewriter)
const {
213 rewriter.replaceOpWithNewOp<mlir::LLVM::MemmoveOp>(
214 op, adaptor.getDst(), adaptor.getSrc(), adaptor.getLen(),
216 return mlir::success();
219mlir::LogicalResult CIRToLLVMMemSetOpLowering::matchAndRewrite(
220 cir::MemSetOp op, OpAdaptor adaptor,
221 mlir::ConversionPatternRewriter &rewriter)
const {
223 auto memset = rewriter.replaceOpWithNewOp<mlir::LLVM::MemsetOp>(
224 op, adaptor.getDst(), adaptor.getVal(), adaptor.getLen(),
227 if (op.getAlignmentAttr()) {
229 llvm::SmallVector<mlir::Attribute> attrs{
memset.getNumOperands(),
230 rewriter.getDictionaryAttr({})};
231 llvm::SmallVector<mlir::NamedAttribute> destAttrs;
233 {mlir::LLVM::LLVMDialect::getAlignAttrName(), op.getAlignmentAttr()});
234 attrs[
memset.odsIndex_dst] = rewriter.getDictionaryAttr(destAttrs);
236 auto arrayAttr = rewriter.getArrayAttr(attrs);
237 memset.setArgAttrsAttr(arrayAttr);
240 return mlir::success();
244 mlir::Value llvmSrc, mlir::Type llvmDstIntTy,
246 uint64_t cirDstIntWidth) {
247 if (cirSrcWidth == cirDstIntWidth)
250 auto loc = llvmSrc.getLoc();
251 if (cirSrcWidth < cirDstIntWidth) {
253 return mlir::LLVM::ZExtOp::create(rewriter, loc, llvmDstIntTy, llvmSrc);
254 return mlir::LLVM::SExtOp::create(rewriter, loc, llvmDstIntTy, llvmSrc);
258 return mlir::LLVM::TruncOp::create(rewriter, loc, llvmDstIntTy, llvmSrc);
264 mlir::ConversionPatternRewriter &rewriter,
265 const mlir::TypeConverter *converter)
266 : parentOp(parentOp), rewriter(rewriter), converter(converter) {}
268#define GET_CIR_ATTR_TO_VALUE_VISITOR_DECLS
269#include "clang/CIR/Dialect/IR/CIRLowering.inc"
270#undef GET_CIR_ATTR_TO_VALUE_VISITOR_DECLS
273 mlir::Operation *parentOp;
274 mlir::ConversionPatternRewriter &rewriter;
275 const mlir::TypeConverter *converter;
280 const mlir::Attribute attr,
281 mlir::ConversionPatternRewriter &rewriter,
282 const mlir::TypeConverter *converter) {
284 mlir::Value value = valueConverter.visit(attr);
286 llvm_unreachable(
"unhandled attribute type");
291 cir::SideEffect sideEffect,
292 mlir::LLVM::MemoryEffectsAttr &memoryEffect,
293 bool &noUnwind,
bool &willReturn,
295 using mlir::LLVM::ModRefInfo;
297 switch (sideEffect) {
298 case cir::SideEffect::All:
300 noUnwind = isNothrow;
304 case cir::SideEffect::Pure:
305 memoryEffect = mlir::LLVM::MemoryEffectsAttr::get(
306 callOp->getContext(), ModRefInfo::Ref,
316 case cir::SideEffect::Const:
317 memoryEffect = mlir::LLVM::MemoryEffectsAttr::get(
318 callOp->getContext(), ModRefInfo::NoModRef,
319 ModRefInfo::NoModRef,
320 ModRefInfo::NoModRef,
321 ModRefInfo::NoModRef,
322 ModRefInfo::NoModRef,
323 ModRefInfo::NoModRef);
329 noReturn = callOp->hasAttr(CIRDialect::getNoReturnAttrName());
332static mlir::LLVM::CallIntrinsicOp
334 mlir::Location loc,
const llvm::Twine &intrinsicName,
335 mlir::Type resultTy, mlir::ValueRange operands) {
336 auto intrinsicNameAttr =
337 mlir::StringAttr::get(rewriter.getContext(), intrinsicName);
338 return mlir::LLVM::CallIntrinsicOp::create(rewriter, loc, resultTy,
339 intrinsicNameAttr, operands);
343 mlir::ConversionPatternRewriter &rewriter, mlir::Operation *op,
344 const llvm::Twine &intrinsicName, mlir::Type resultTy,
345 mlir::ValueRange operands) {
347 rewriter, op->getLoc(), intrinsicName, resultTy, operands);
348 rewriter.replaceOp(op, callIntrinOp.getOperation());
352mlir::LogicalResult CIRToLLVMLLVMIntrinsicCallOpLowering::matchAndRewrite(
353 cir::LLVMIntrinsicCallOp op, OpAdaptor adaptor,
354 mlir::ConversionPatternRewriter &rewriter)
const {
355 mlir::Type llvmResTy =
356 getTypeConverter()->convertType(op->getResultTypes()[0]);
358 return op.emitError(
"expected LLVM result type");
359 StringRef name = op.getIntrinsicName();
372 adaptor.getOperands());
373 return mlir::success();
377mlir::Value CIRAttrToValue::visitCirAttr(cir::BoolAttr boolAttr) {
378 mlir::Location loc = parentOp->getLoc();
379 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
380 mlir::Value boolVal = mlir::LLVM::ConstantOp::create(
381 rewriter, loc, converter->convertType(boolAttr.getType()),
382 boolAttr.getValue());
383 return emitToMemory(rewriter, layout, boolAttr.getType(), boolVal);
387mlir::Value CIRAttrToValue::visitCirAttr(cir::IntAttr intAttr) {
388 mlir::Location loc = parentOp->getLoc();
389 return mlir::LLVM::ConstantOp::create(
390 rewriter, loc, converter->convertType(intAttr.getType()),
395mlir::Value CIRAttrToValue::visitCirAttr(cir::FPAttr fltAttr) {
396 mlir::Location loc = parentOp->getLoc();
397 return mlir::LLVM::ConstantOp::create(
398 rewriter, loc, converter->convertType(fltAttr.getType()),
403mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstComplexAttr complexAttr) {
404 auto complexType = mlir::cast<cir::ComplexType>(complexAttr.getType());
405 mlir::Type complexElemTy =
complexType.getElementType();
406 mlir::Type complexElemLLVMTy = converter->convertType(complexElemTy);
408 mlir::Attribute components[2];
409 if (
const auto intType = mlir::dyn_cast<cir::IntType>(complexElemTy)) {
410 components[0] = rewriter.getIntegerAttr(
412 mlir::cast<cir::IntAttr>(complexAttr.getReal()).getValue());
413 components[1] = rewriter.getIntegerAttr(
415 mlir::cast<cir::IntAttr>(complexAttr.getImag()).getValue());
417 components[0] = rewriter.getFloatAttr(
419 mlir::cast<cir::FPAttr>(complexAttr.getReal()).getValue());
420 components[1] = rewriter.getFloatAttr(
422 mlir::cast<cir::FPAttr>(complexAttr.getImag()).getValue());
425 mlir::Location loc = parentOp->getLoc();
426 return mlir::LLVM::ConstantOp::create(
427 rewriter, loc, converter->convertType(complexAttr.getType()),
428 rewriter.getArrayAttr(components));
432mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstPtrAttr ptrAttr) {
433 mlir::Location loc = parentOp->getLoc();
434 if (ptrAttr.isNullValue()) {
435 return mlir::LLVM::ZeroOp::create(
436 rewriter, loc, converter->convertType(ptrAttr.getType()));
438 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
439 mlir::Value ptrVal = mlir::LLVM::ConstantOp::create(
441 rewriter.getIntegerType(layout.getTypeSizeInBits(ptrAttr.getType())),
442 ptrAttr.getValue().getInt());
443 return mlir::LLVM::IntToPtrOp::create(
444 rewriter, loc, converter->convertType(ptrAttr.getType()), ptrVal);
448mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstArrayAttr attr) {
449 mlir::Type llvmTy = converter->convertType(
attr.getType());
450 mlir::Location loc = parentOp->getLoc();
453 if (
attr.hasTrailingZeros()) {
454 mlir::Type arrayTy =
attr.getType();
455 result = mlir::LLVM::ZeroOp::create(rewriter, loc,
456 converter->convertType(arrayTy));
458 result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
462 if (
auto arrayAttr = mlir::dyn_cast<mlir::ArrayAttr>(
attr.getElts())) {
463 for (
auto [idx, elt] : llvm::enumerate(arrayAttr)) {
464 mlir::DataLayout dataLayout(parentOp->getParentOfType<mlir::ModuleOp>());
465 mlir::Value init = visit(elt);
467 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
469 }
else if (
auto strAttr = mlir::dyn_cast<mlir::StringAttr>(
attr.getElts())) {
472 auto arrayTy = mlir::dyn_cast<cir::ArrayType>(strAttr.getType());
473 assert(arrayTy &&
"String attribute must have an array type");
474 mlir::Type eltTy = arrayTy.getElementType();
475 for (
auto [idx, elt] : llvm::enumerate(strAttr)) {
476 auto init = mlir::LLVM::ConstantOp::create(
477 rewriter, loc, converter->convertType(eltTy), elt);
479 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
482 llvm_unreachable(
"unexpected ConstArrayAttr elements");
489mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstRecordAttr constRecord) {
490 const mlir::Type llvmTy = converter->convertType(constRecord.getType());
491 const mlir::Location loc = parentOp->getLoc();
492 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
495 for (
auto [idx, elt] : llvm::enumerate(constRecord.getMembers())) {
496 mlir::Value init = visit(elt);
498 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
505mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstVectorAttr attr) {
506 const mlir::Type llvmTy = converter->convertType(
attr.getType());
507 const mlir::Location loc = parentOp->getLoc();
509 SmallVector<mlir::Attribute> mlirValues;
510 for (
const mlir::Attribute elementAttr :
attr.getElts()) {
511 mlir::Attribute mlirAttr;
512 if (
auto intAttr = mlir::dyn_cast<cir::IntAttr>(elementAttr)) {
513 mlirAttr = rewriter.getIntegerAttr(
514 converter->convertType(intAttr.getType()), intAttr.getValue());
515 }
else if (
auto floatAttr = mlir::dyn_cast<cir::FPAttr>(elementAttr)) {
516 mlirAttr = rewriter.getFloatAttr(
517 converter->convertType(floatAttr.getType()), floatAttr.getValue());
520 "vector constant with an element that is neither an int nor a float");
522 mlirValues.push_back(mlirAttr);
525 return mlir::LLVM::ConstantOp::create(
526 rewriter, loc, llvmTy,
527 mlir::DenseElementsAttr::get(mlir::cast<mlir::ShapedType>(llvmTy),
532mlir::Value CIRAttrToValue::visitCirAttr(cir::GlobalViewAttr globalAttr) {
533 auto moduleOp = parentOp->getParentOfType<mlir::ModuleOp>();
534 mlir::DataLayout dataLayout(moduleOp);
535 mlir::Type sourceType;
536 unsigned sourceAddrSpace = 0;
537 llvm::StringRef symName;
538 mlir::Operation *sourceSymbol =
539 mlir::SymbolTable::lookupSymbolIn(moduleOp, globalAttr.getSymbol());
540 if (
auto llvmSymbol = dyn_cast<mlir::LLVM::GlobalOp>(sourceSymbol)) {
541 sourceType = llvmSymbol.getType();
542 symName = llvmSymbol.getSymName();
543 sourceAddrSpace = llvmSymbol.getAddrSpace();
544 }
else if (
auto cirSymbol = dyn_cast<cir::GlobalOp>(sourceSymbol)) {
547 symName = cirSymbol.getSymName();
548 if (
auto targetAS = mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
549 cirSymbol.getAddrSpaceAttr()))
550 sourceAddrSpace = targetAS.getValue();
551 }
else if (
auto llvmFun = dyn_cast<mlir::LLVM::LLVMFuncOp>(sourceSymbol)) {
552 sourceType = llvmFun.getFunctionType();
553 symName = llvmFun.getSymName();
554 }
else if (
auto fun = dyn_cast<cir::FuncOp>(sourceSymbol)) {
555 sourceType = converter->convertType(fun.getFunctionType());
556 symName = fun.getSymName();
557 }
else if (
auto alias = dyn_cast<mlir::LLVM::AliasOp>(sourceSymbol)) {
558 sourceType = alias.getType();
559 symName = alias.getSymName();
561 llvm_unreachable(
"Unexpected GlobalOp type");
564 mlir::Location loc = parentOp->getLoc();
565 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
567 mlir::LLVM::LLVMPointerType::get(rewriter.getContext(), sourceAddrSpace),
570 if (globalAttr.getIndices()) {
571 llvm::SmallVector<mlir::LLVM::GEPArg> indices;
573 if (mlir::isa<mlir::LLVM::LLVMArrayType, mlir::LLVM::LLVMStructType>(
575 indices.push_back(0);
577 for (mlir::Attribute idx : globalAttr.getIndices()) {
578 auto intAttr = mlir::cast<mlir::IntegerAttr>(idx);
579 indices.push_back(intAttr.getValue().getSExtValue());
581 mlir::Type resTy = addrOp.getType();
582 mlir::Type eltTy = converter->convertType(sourceType);
584 mlir::LLVM::GEPOp::create(rewriter, loc, resTy, eltTy, addrOp, indices,
585 mlir::LLVM::GEPNoWrapFlags::none);
592 if (
auto intTy = mlir::dyn_cast<cir::IntType>(globalAttr.getType())) {
593 mlir::Type llvmDstTy = converter->convertType(globalAttr.getType());
594 return mlir::LLVM::PtrToIntOp::create(rewriter, parentOp->getLoc(),
598 if (
auto ptrTy = mlir::dyn_cast<cir::PointerType>(globalAttr.getType())) {
599 auto llvmDstTy = converter->convertType<mlir::LLVM::LLVMPointerType>(ptrTy);
600 unsigned dstAddrSpace = llvmDstTy.getAddressSpace();
602 if (sourceAddrSpace != dstAddrSpace)
603 addrOp = mlir::LLVM::AddrSpaceCastOp::create(rewriter, parentOp->getLoc(),
606 mlir::Type llvmEltTy =
610 if (llvmEltTy == sourceType)
616 if (addrOp.getType() == llvmDstTy)
619 return mlir::LLVM::BitcastOp::create(rewriter, parentOp->getLoc(),
623 if (mlir::isa<cir::VPtrType>(globalAttr.getType()))
626 llvm_unreachable(
"Expecting pointer or integer type for GlobalViewAttr");
630mlir::Value CIRAttrToValue::visitCirAttr(cir::TypeInfoAttr typeInfoAttr) {
631 mlir::Type llvmTy = converter->convertType(typeInfoAttr.getType());
632 mlir::Location loc = parentOp->getLoc();
633 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
635 for (
auto [idx, elt] : llvm::enumerate(typeInfoAttr.getData())) {
636 mlir::Value init = visit(elt);
638 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
645mlir::Value CIRAttrToValue::visitCirAttr(cir::UndefAttr undefAttr) {
646 mlir::Location loc = parentOp->getLoc();
647 return mlir::LLVM::UndefOp::create(
648 rewriter, loc, converter->convertType(undefAttr.getType()));
652mlir::Value CIRAttrToValue::visitCirAttr(cir::PoisonAttr poisonAttr) {
653 mlir::Location loc = parentOp->getLoc();
654 return mlir::LLVM::PoisonOp::create(
655 rewriter, loc, converter->convertType(poisonAttr.getType()));
659mlir::Value CIRAttrToValue::visitCirAttr(cir::VTableAttr vtableArr) {
660 mlir::Type llvmTy = converter->convertType(vtableArr.getType());
661 mlir::Location loc = parentOp->getLoc();
662 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
664 for (
auto [idx, elt] : llvm::enumerate(vtableArr.getData())) {
665 mlir::Value init = visit(elt);
667 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
674mlir::Value CIRAttrToValue::visitCirAttr(cir::ZeroAttr attr) {
675 mlir::Location loc = parentOp->getLoc();
676 return mlir::LLVM::ZeroOp::create(rewriter, loc,
677 converter->convertType(
attr.getType()));
685 mlir::ConversionPatternRewriter &rewriter)
686 : llvmType(type), rewriter(rewriter) {}
689 return llvm::TypeSwitch<mlir::Attribute, mlir::Attribute>(
attr)
690 .Case<cir::IntAttr, cir::FPAttr, cir::BoolAttr>(
692 .
Default([&](
auto attrT) {
return mlir::Attribute(); });
696 return rewriter.getIntegerAttr(llvmType,
attr.getValue());
700 return rewriter.getFloatAttr(llvmType,
attr.getValue());
704 return rewriter.getBoolAttr(
attr.getValue());
709 mlir::ConversionPatternRewriter &rewriter;
717 :
public mlir::PassWrapper<ConvertCIRToLLVMPass,
718 mlir::OperationPass<mlir::ModuleOp>> {
720 registry.insert<mlir::BuiltinDialect, mlir::DLTIDialect,
721 mlir::LLVM::LLVMDialect, mlir::func::FuncDialect>();
730 return "Convert the prepared CIR dialect module to LLVM dialect";
733 StringRef
getArgument()
const override {
return "cir-flat-to-llvm"; }
736mlir::LogicalResult CIRToLLVMIsFPClassOpLowering::matchAndRewrite(
737 cir::IsFPClassOp op, OpAdaptor adaptor,
738 mlir::ConversionPatternRewriter &rewriter)
const {
739 mlir::Value src = adaptor.getSrc();
740 cir::FPClassTest flags = adaptor.getFlags();
741 mlir::IntegerType retTy = rewriter.getI1Type();
743 rewriter.replaceOpWithNewOp<mlir::LLVM::IsFPClass>(
744 op, retTy, src,
static_cast<uint32_t
>(flags));
745 return mlir::success();
748mlir::LogicalResult CIRToLLVMSignBitOpLowering::matchAndRewrite(
749 cir::SignBitOp op, OpAdaptor adaptor,
750 mlir::ConversionPatternRewriter &rewriter)
const {
753 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
754 int width = layout.getTypeSizeInBits(op.getInput().getType());
755 if (
auto longDoubleType =
756 mlir::dyn_cast<cir::LongDoubleType>(op.getInput().getType())) {
757 if (mlir::isa<cir::FP80Type>(longDoubleType.getUnderlying())) {
765 mlir::Type intTy = mlir::IntegerType::get(rewriter.getContext(), width);
766 auto bitcast = mlir::LLVM::BitcastOp::create(rewriter, op->getLoc(), intTy,
769 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op->getLoc(), intTy, 0);
770 auto cmpResult = mlir::LLVM::ICmpOp::create(rewriter, op.getLoc(),
771 mlir::LLVM::ICmpPredicate::slt,
772 bitcast.getResult(), zero);
773 rewriter.replaceOp(op, cmpResult);
774 return mlir::success();
777mlir::LogicalResult CIRToLLVMAssumeOpLowering::matchAndRewrite(
778 cir::AssumeOp op, OpAdaptor adaptor,
779 mlir::ConversionPatternRewriter &rewriter)
const {
780 auto cond = adaptor.getPredicate();
781 rewriter.replaceOpWithNewOp<mlir::LLVM::AssumeOp>(op, cond);
782 return mlir::success();
785mlir::LogicalResult CIRToLLVMAssumeAlignedOpLowering::matchAndRewrite(
786 cir::AssumeAlignedOp op, OpAdaptor adaptor,
787 mlir::ConversionPatternRewriter &rewriter)
const {
788 SmallVector<mlir::Value, 3> opBundleArgs{adaptor.getPointer()};
790 auto alignment = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
791 adaptor.getAlignmentAttr());
792 opBundleArgs.push_back(alignment);
794 if (mlir::Value offset = adaptor.getOffset())
795 opBundleArgs.push_back(offset);
797 auto cond = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
798 rewriter.getI1Type(), 1);
799 mlir::LLVM::AssumeOp::create(rewriter, op.getLoc(), cond,
"align",
804 rewriter.replaceOp(op, adaptor.getPointer());
805 return mlir::success();
808mlir::LogicalResult CIRToLLVMAssumeSepStorageOpLowering::matchAndRewrite(
809 cir::AssumeSepStorageOp op, OpAdaptor adaptor,
810 mlir::ConversionPatternRewriter &rewriter)
const {
811 auto cond = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
812 rewriter.getI1Type(), 1);
813 rewriter.replaceOpWithNewOp<mlir::LLVM::AssumeOp>(
814 op, cond, mlir::LLVM::AssumeSeparateStorageTag{}, adaptor.getPtr1(),
816 return mlir::success();
819static mlir::LLVM::AtomicOrdering
822 return mlir::LLVM::AtomicOrdering::not_atomic;
824 case cir::MemOrder::Relaxed:
825 return mlir::LLVM::AtomicOrdering::monotonic;
826 case cir::MemOrder::Consume:
827 case cir::MemOrder::Acquire:
828 return mlir::LLVM::AtomicOrdering::acquire;
829 case cir::MemOrder::Release:
830 return mlir::LLVM::AtomicOrdering::release;
831 case cir::MemOrder::AcquireRelease:
832 return mlir::LLVM::AtomicOrdering::acq_rel;
833 case cir::MemOrder::SequentiallyConsistent:
834 return mlir::LLVM::AtomicOrdering::seq_cst;
836 llvm_unreachable(
"unknown memory order");
840 return syncScope == cir::SyncScopeKind::SingleThread ?
"singlethread" :
"";
843static std::optional<llvm::StringRef>
845 if (syncScope.has_value())
850mlir::LogicalResult CIRToLLVMAtomicCmpXchgOpLowering::matchAndRewrite(
851 cir::AtomicCmpXchgOp op, OpAdaptor adaptor,
852 mlir::ConversionPatternRewriter &rewriter)
const {
853 mlir::Value expected = adaptor.getExpected();
854 mlir::Value desired = adaptor.getDesired();
856 auto cmpxchg = mlir::LLVM::AtomicCmpXchgOp::create(
857 rewriter, op.getLoc(), adaptor.getPtr(), expected, desired,
862 cmpxchg.setAlignment(adaptor.getAlignment());
863 cmpxchg.setWeak(adaptor.getWeak());
864 cmpxchg.setVolatile_(adaptor.getIsVolatile());
867 auto old = mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(),
868 cmpxchg.getResult(), 0);
869 auto cmp = mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(),
870 cmpxchg.getResult(), 1);
872 rewriter.replaceOp(op, {old, cmp});
873 return mlir::success();
876mlir::LogicalResult CIRToLLVMAtomicXchgOpLowering::matchAndRewrite(
877 cir::AtomicXchgOp op, OpAdaptor adaptor,
878 mlir::ConversionPatternRewriter &rewriter)
const {
880 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(adaptor.getMemOrder());
882 rewriter.replaceOpWithNewOp<mlir::LLVM::AtomicRMWOp>(
883 op, mlir::LLVM::AtomicBinOp::xchg, adaptor.getPtr(), adaptor.getVal(),
884 llvmOrder, llvmSyncScope);
885 return mlir::success();
888mlir::LogicalResult CIRToLLVMAtomicTestAndSetOpLowering::matchAndRewrite(
889 cir::AtomicTestAndSetOp op, OpAdaptor adaptor,
890 mlir::ConversionPatternRewriter &rewriter)
const {
893 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
895 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
896 rewriter.getI8Type(), 1);
897 auto rmw = mlir::LLVM::AtomicRMWOp::create(
898 rewriter, op.getLoc(), mlir::LLVM::AtomicBinOp::xchg, adaptor.getPtr(),
899 one, llvmOrder, llvm::StringRef(),
900 adaptor.getAlignment().value_or(0), op.getIsVolatile());
902 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
903 rewriter.getI8Type(), 0);
904 auto cmp = mlir::LLVM::ICmpOp::create(
905 rewriter, op.getLoc(), mlir::LLVM::ICmpPredicate::ne, rmw, zero);
907 rewriter.replaceOp(op, cmp);
908 return mlir::success();
911mlir::LogicalResult CIRToLLVMAtomicClearOpLowering::matchAndRewrite(
912 cir::AtomicClearOp op, OpAdaptor adaptor,
913 mlir::ConversionPatternRewriter &rewriter)
const {
916 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
917 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
918 rewriter.getI8Type(), 0);
919 auto store = mlir::LLVM::StoreOp::create(
920 rewriter, op.getLoc(), zero, adaptor.getPtr(),
921 adaptor.getAlignment().value_or(0), op.getIsVolatile(),
922 false,
false, llvmOrder);
924 rewriter.replaceOp(op, store);
925 return mlir::success();
928mlir::LogicalResult CIRToLLVMAtomicFenceOpLowering::matchAndRewrite(
929 cir::AtomicFenceOp op, OpAdaptor adaptor,
930 mlir::ConversionPatternRewriter &rewriter)
const {
931 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(adaptor.getOrdering());
933 auto fence = mlir::LLVM::FenceOp::create(rewriter, op.getLoc(), llvmOrder);
936 rewriter.replaceOp(op, fence);
938 return mlir::success();
941static mlir::LLVM::AtomicBinOp
944 case cir::AtomicFetchKind::Add:
945 return isInt ? mlir::LLVM::AtomicBinOp::add : mlir::LLVM::AtomicBinOp::fadd;
946 case cir::AtomicFetchKind::Sub:
947 return isInt ? mlir::LLVM::AtomicBinOp::sub : mlir::LLVM::AtomicBinOp::fsub;
948 case cir::AtomicFetchKind::And:
949 return mlir::LLVM::AtomicBinOp::_and;
950 case cir::AtomicFetchKind::Xor:
951 return mlir::LLVM::AtomicBinOp::_xor;
952 case cir::AtomicFetchKind::Or:
953 return mlir::LLVM::AtomicBinOp::_or;
954 case cir::AtomicFetchKind::Nand:
955 return mlir::LLVM::AtomicBinOp::nand;
956 case cir::AtomicFetchKind::Max: {
958 return mlir::LLVM::AtomicBinOp::fmax;
959 return isSignedInt ? mlir::LLVM::AtomicBinOp::max
960 : mlir::LLVM::AtomicBinOp::umax;
962 case cir::AtomicFetchKind::Min: {
964 return mlir::LLVM::AtomicBinOp::fmin;
965 return isSignedInt ? mlir::LLVM::AtomicBinOp::min
966 : mlir::LLVM::AtomicBinOp::umin;
968 case cir::AtomicFetchKind::UIncWrap:
969 return mlir::LLVM::AtomicBinOp::uinc_wrap;
970 case cir::AtomicFetchKind::UDecWrap:
971 return mlir::LLVM::AtomicBinOp::udec_wrap;
973 llvm_unreachable(
"Unknown atomic fetch opcode");
979 case cir::AtomicFetchKind::Add:
980 return isInt ? mlir::LLVM::AddOp::getOperationName()
981 : mlir::LLVM::FAddOp::getOperationName();
982 case cir::AtomicFetchKind::Sub:
983 return isInt ? mlir::LLVM::SubOp::getOperationName()
984 : mlir::LLVM::FSubOp::getOperationName();
985 case cir::AtomicFetchKind::And:
986 return mlir::LLVM::AndOp::getOperationName();
987 case cir::AtomicFetchKind::Xor:
988 return mlir::LLVM::XOrOp::getOperationName();
989 case cir::AtomicFetchKind::Or:
990 return mlir::LLVM::OrOp::getOperationName();
991 case cir::AtomicFetchKind::Nand:
993 return mlir::LLVM::AndOp::getOperationName();
994 case cir::AtomicFetchKind::Max:
995 case cir::AtomicFetchKind::Min:
996 llvm_unreachable(
"handled in buildMinMaxPostOp");
997 case cir::AtomicFetchKind::UIncWrap:
998 case cir::AtomicFetchKind::UDecWrap:
999 llvm_unreachable(
"uinc_wrap and udec_wrap are always fetch_first");
1001 llvm_unreachable(
"Unknown atomic fetch opcode");
1004mlir::Value CIRToLLVMAtomicFetchOpLowering::buildPostOp(
1005 cir::AtomicFetchOp op, OpAdaptor adaptor,
1006 mlir::ConversionPatternRewriter &rewriter, mlir::Value rmwVal,
1011 .create(op.getLoc(),
1012 rewriter.getStringAttr(
1014 atomicOperands, atomicResTys, {})
1018mlir::Value CIRToLLVMAtomicFetchOpLowering::buildMinMaxPostOp(
1019 cir::AtomicFetchOp op, OpAdaptor adaptor,
1020 mlir::ConversionPatternRewriter &rewriter, mlir::Value rmwVal,
bool isInt,
1021 bool isSigned)
const {
1022 mlir::Location loc = op.getLoc();
1025 if (op.getBinop() == cir::AtomicFetchKind::Max)
1026 return mlir::LLVM::MaxNumOp::create(rewriter, loc, rmwVal,
1028 return mlir::LLVM::MinNumOp::create(rewriter, loc, rmwVal,
1032 mlir::LLVM::ICmpPredicate pred;
1033 if (op.getBinop() == cir::AtomicFetchKind::Max) {
1034 pred = isSigned ? mlir::LLVM::ICmpPredicate::sgt
1035 : mlir::LLVM::ICmpPredicate::ugt;
1037 pred = isSigned ? mlir::LLVM::ICmpPredicate::slt
1038 : mlir::LLVM::ICmpPredicate::ult;
1040 mlir::Value cmp = mlir::LLVM::ICmpOp::create(
1042 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(), pred), rmwVal,
1044 return mlir::LLVM::SelectOp::create(rewriter, loc, cmp, rmwVal,
1048mlir::LogicalResult CIRToLLVMAtomicFetchOpLowering::matchAndRewrite(
1049 cir::AtomicFetchOp op, OpAdaptor adaptor,
1050 mlir::ConversionPatternRewriter &rewriter)
const {
1052 bool isSignedInt =
false;
1053 if (
auto intTy = mlir::dyn_cast<cir::IntType>(op.getVal().getType())) {
1055 isSignedInt = intTy.isSigned();
1056 }
else if (mlir::isa<cir::SingleType, cir::DoubleType>(
1057 op.getVal().getType())) {
1060 return op.emitError() <<
"Unsupported type: " << op.getVal().getType();
1063 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
1065 mlir::LLVM::AtomicBinOp llvmBinOp =
1067 auto rmwVal = mlir::LLVM::AtomicRMWOp::create(
1068 rewriter, op.getLoc(), llvmBinOp, adaptor.getPtr(), adaptor.getVal(),
1069 llvmOrder, llvmSyncScope);
1071 mlir::Value result = rmwVal.getResult();
1072 if (!op.getFetchFirst()) {
1073 if (op.getBinop() == cir::AtomicFetchKind::Max ||
1074 op.getBinop() == cir::AtomicFetchKind::Min)
1075 result = buildMinMaxPostOp(op, adaptor, rewriter, rmwVal.getRes(), isInt,
1078 result = buildPostOp(op, adaptor, rewriter, rmwVal.getRes(), isInt);
1081 if (op.getBinop() == cir::AtomicFetchKind::Nand) {
1082 auto negOne = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1083 result.getType(), -1);
1084 result = mlir::LLVM::XOrOp::create(rewriter, op.getLoc(), result, negOne);
1088 rewriter.replaceOp(op, result);
1089 return mlir::success();
1092mlir::LogicalResult CIRToLLVMBitClrsbOpLowering::matchAndRewrite(
1093 cir::BitClrsbOp op, OpAdaptor adaptor,
1094 mlir::ConversionPatternRewriter &rewriter)
const {
1095 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1096 adaptor.getInput().getType(), 0);
1097 auto isNeg = mlir::LLVM::ICmpOp::create(
1098 rewriter, op.getLoc(),
1099 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(),
1100 mlir::LLVM::ICmpPredicate::slt),
1101 adaptor.getInput(), zero);
1103 auto negOne = mlir::LLVM::ConstantOp::create(
1104 rewriter, op.getLoc(), adaptor.getInput().getType(), -1);
1105 auto flipped = mlir::LLVM::XOrOp::create(rewriter, op.getLoc(),
1106 adaptor.getInput(), negOne);
1108 auto select = mlir::LLVM::SelectOp::create(rewriter, op.getLoc(), isNeg,
1109 flipped, adaptor.getInput());
1111 auto resTy = getTypeConverter()->convertType(op.getType());
1112 auto clz = mlir::LLVM::CountLeadingZerosOp::create(
1113 rewriter, op.getLoc(), resTy,
select,
false);
1115 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1116 auto res = mlir::LLVM::SubOp::create(rewriter, op.getLoc(),
clz, one,
1117 mlir::LLVM::IntegerOverflowFlags::nuw);
1118 rewriter.replaceOp(op, res);
1120 return mlir::LogicalResult::success();
1123mlir::LogicalResult CIRToLLVMBitClzOpLowering::matchAndRewrite(
1124 cir::BitClzOp op, OpAdaptor adaptor,
1125 mlir::ConversionPatternRewriter &rewriter)
const {
1126 auto resTy = getTypeConverter()->convertType(op.getType());
1127 auto llvmOp = mlir::LLVM::CountLeadingZerosOp::create(
1128 rewriter, op.getLoc(), resTy, adaptor.getInput(), op.getPoisonZero());
1129 rewriter.replaceOp(op, llvmOp);
1130 return mlir::LogicalResult::success();
1133mlir::LogicalResult CIRToLLVMBitCtzOpLowering::matchAndRewrite(
1134 cir::BitCtzOp op, OpAdaptor adaptor,
1135 mlir::ConversionPatternRewriter &rewriter)
const {
1136 auto resTy = getTypeConverter()->convertType(op.getType());
1137 auto llvmOp = mlir::LLVM::CountTrailingZerosOp::create(
1138 rewriter, op.getLoc(), resTy, adaptor.getInput(), op.getPoisonZero());
1139 rewriter.replaceOp(op, llvmOp);
1140 return mlir::LogicalResult::success();
1143mlir::LogicalResult CIRToLLVMBitFfsOpLowering::matchAndRewrite(
1144 cir::BitFfsOp op, OpAdaptor adaptor,
1145 mlir::ConversionPatternRewriter &rewriter)
const {
1146 auto resTy = getTypeConverter()->convertType(op.getType());
1147 auto ctz = mlir::LLVM::CountTrailingZerosOp::create(rewriter, op.getLoc(),
1148 resTy, adaptor.getInput(),
1151 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1152 auto ctzAddOne = mlir::LLVM::AddOp::create(rewriter, op.getLoc(),
ctz, one);
1154 auto zeroInputTy = mlir::LLVM::ConstantOp::create(
1155 rewriter, op.getLoc(), adaptor.getInput().getType(), 0);
1156 auto isZero = mlir::LLVM::ICmpOp::create(
1157 rewriter, op.getLoc(),
1158 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(),
1159 mlir::LLVM::ICmpPredicate::eq),
1160 adaptor.getInput(), zeroInputTy);
1162 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 0);
1163 auto res = mlir::LLVM::SelectOp::create(rewriter, op.getLoc(), isZero, zero,
1165 rewriter.replaceOp(op, res);
1167 return mlir::LogicalResult::success();
1170mlir::LogicalResult CIRToLLVMBitParityOpLowering::matchAndRewrite(
1171 cir::BitParityOp op, OpAdaptor adaptor,
1172 mlir::ConversionPatternRewriter &rewriter)
const {
1173 auto resTy = getTypeConverter()->convertType(op.getType());
1174 auto popcnt = mlir::LLVM::CtPopOp::create(rewriter, op.getLoc(), resTy,
1175 adaptor.getInput());
1177 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1179 mlir::LLVM::AndOp::create(rewriter, op.getLoc(), popcnt, one);
1180 rewriter.replaceOp(op, popcntMod2);
1182 return mlir::LogicalResult::success();
1185mlir::LogicalResult CIRToLLVMBitPopcountOpLowering::matchAndRewrite(
1186 cir::BitPopcountOp op, OpAdaptor adaptor,
1187 mlir::ConversionPatternRewriter &rewriter)
const {
1188 auto resTy = getTypeConverter()->convertType(op.getType());
1189 auto llvmOp = mlir::LLVM::CtPopOp::create(rewriter, op.getLoc(), resTy,
1190 adaptor.getInput());
1191 rewriter.replaceOp(op, llvmOp);
1192 return mlir::LogicalResult::success();
1195mlir::LogicalResult CIRToLLVMBitReverseOpLowering::matchAndRewrite(
1196 cir::BitReverseOp op, OpAdaptor adaptor,
1197 mlir::ConversionPatternRewriter &rewriter)
const {
1198 rewriter.replaceOpWithNewOp<mlir::LLVM::BitReverseOp>(op, adaptor.getInput());
1199 return mlir::success();
1202mlir::LogicalResult CIRToLLVMBrCondOpLowering::matchAndRewrite(
1203 cir::BrCondOp brOp, OpAdaptor adaptor,
1204 mlir::ConversionPatternRewriter &rewriter)
const {
1209 mlir::Value i1Condition = adaptor.getCond();
1211 rewriter.replaceOpWithNewOp<mlir::LLVM::CondBrOp>(
1212 brOp, i1Condition, brOp.getDestTrue(), adaptor.getDestOperandsTrue(),
1213 brOp.getDestFalse(), adaptor.getDestOperandsFalse());
1215 return mlir::success();
1218mlir::LogicalResult CIRToLLVMByteSwapOpLowering::matchAndRewrite(
1219 cir::ByteSwapOp op, OpAdaptor adaptor,
1220 mlir::ConversionPatternRewriter &rewriter)
const {
1221 rewriter.replaceOpWithNewOp<mlir::LLVM::ByteSwapOp>(op, adaptor.getInput());
1222 return mlir::LogicalResult::success();
1225mlir::Type CIRToLLVMCastOpLowering::convertTy(mlir::Type ty)
const {
1226 return getTypeConverter()->convertType(ty);
1229mlir::LogicalResult CIRToLLVMCastOpLowering::matchAndRewrite(
1230 cir::CastOp castOp, OpAdaptor adaptor,
1231 mlir::ConversionPatternRewriter &rewriter)
const {
1236 switch (castOp.getKind()) {
1237 case cir::CastKind::array_to_ptrdecay: {
1238 const auto ptrTy = mlir::cast<cir::PointerType>(castOp.getType());
1239 mlir::Value sourceValue = adaptor.getSrc();
1240 mlir::Type targetType = convertTy(ptrTy);
1242 ptrTy.getPointee());
1243 llvm::SmallVector<mlir::LLVM::GEPArg> offset{0};
1244 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1245 castOp, targetType, elementTy, sourceValue, offset);
1248 case cir::CastKind::int_to_bool: {
1249 mlir::Value llvmSrcVal = adaptor.getSrc();
1250 mlir::Value zeroInt = mlir::LLVM::ConstantOp::create(
1251 rewriter, castOp.getLoc(), llvmSrcVal.getType(), 0);
1252 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
1253 castOp, mlir::LLVM::ICmpPredicate::ne, llvmSrcVal, zeroInt);
1256 case cir::CastKind::integral: {
1257 mlir::Type srcType = castOp.getSrc().getType();
1258 mlir::Type dstType = castOp.getType();
1259 mlir::Value llvmSrcVal = adaptor.getSrc();
1260 mlir::Type llvmDstType = getTypeConverter()->convertType(dstType);
1261 cir::IntType srcIntType =
1262 mlir::cast<cir::IntType>(elementTypeIfVector(srcType));
1263 cir::IntType dstIntType =
1264 mlir::cast<cir::IntType>(elementTypeIfVector(dstType));
1265 rewriter.replaceOp(castOp,
getLLVMIntCast(rewriter, llvmSrcVal, llvmDstType,
1266 srcIntType.isUnsigned(),
1267 srcIntType.getWidth(),
1268 dstIntType.getWidth()));
1271 case cir::CastKind::floating: {
1272 mlir::Value llvmSrcVal = adaptor.getSrc();
1273 mlir::Type llvmDstTy = getTypeConverter()->convertType(castOp.getType());
1275 mlir::Type srcTy = elementTypeIfVector(castOp.getSrc().getType());
1276 mlir::Type dstTy = elementTypeIfVector(castOp.getType());
1278 if (!mlir::isa<cir::FPTypeInterface>(dstTy) ||
1279 !mlir::isa<cir::FPTypeInterface>(srcTy))
1280 return castOp.emitError() <<
"NYI cast from " << srcTy <<
" to " << dstTy;
1282 auto getFloatWidth = [](mlir::Type ty) ->
unsigned {
1283 return mlir::cast<cir::FPTypeInterface>(ty).getWidth();
1286 if (getFloatWidth(srcTy) > getFloatWidth(dstTy))
1287 rewriter.replaceOpWithNewOp<mlir::LLVM::FPTruncOp>(castOp, llvmDstTy,
1290 rewriter.replaceOpWithNewOp<mlir::LLVM::FPExtOp>(castOp, llvmDstTy,
1292 return mlir::success();
1294 case cir::CastKind::int_to_ptr: {
1295 auto dstTy = mlir::cast<cir::PointerType>(castOp.getType());
1296 mlir::Value llvmSrcVal = adaptor.getSrc();
1297 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1298 rewriter.replaceOpWithNewOp<mlir::LLVM::IntToPtrOp>(castOp, llvmDstTy,
1300 return mlir::success();
1302 case cir::CastKind::ptr_to_int: {
1303 auto dstTy = mlir::cast<cir::IntType>(castOp.getType());
1304 mlir::Value llvmSrcVal = adaptor.getSrc();
1305 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1306 rewriter.replaceOpWithNewOp<mlir::LLVM::PtrToIntOp>(castOp, llvmDstTy,
1308 return mlir::success();
1310 case cir::CastKind::float_to_bool: {
1311 mlir::Value llvmSrcVal = adaptor.getSrc();
1312 auto kind = mlir::LLVM::FCmpPredicate::une;
1315 auto zeroFloat = mlir::LLVM::ConstantOp::create(
1316 rewriter, castOp.getLoc(), llvmSrcVal.getType(),
1317 mlir::FloatAttr::get(llvmSrcVal.getType(), 0.0));
1320 rewriter.replaceOpWithNewOp<mlir::LLVM::FCmpOp>(castOp,
kind, llvmSrcVal,
1323 return mlir::success();
1325 case cir::CastKind::bool_to_int: {
1326 auto dstTy = mlir::cast<cir::IntType>(castOp.getType());
1327 mlir::Value llvmSrcVal = adaptor.getSrc();
1328 auto llvmSrcTy = mlir::cast<mlir::IntegerType>(llvmSrcVal.getType());
1330 mlir::cast<mlir::IntegerType>(getTypeConverter()->convertType(dstTy));
1332 if (llvmSrcTy.getWidth() == llvmDstTy.getWidth())
1333 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(castOp, llvmDstTy,
1336 rewriter.replaceOpWithNewOp<mlir::LLVM::ZExtOp>(castOp, llvmDstTy,
1338 return mlir::success();
1340 case cir::CastKind::bool_to_float: {
1341 mlir::Type dstTy = castOp.getType();
1342 mlir::Value llvmSrcVal = adaptor.getSrc();
1343 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1344 rewriter.replaceOpWithNewOp<mlir::LLVM::UIToFPOp>(castOp, llvmDstTy,
1346 return mlir::success();
1348 case cir::CastKind::int_to_float: {
1349 mlir::Type dstTy = castOp.getType();
1350 mlir::Value llvmSrcVal = adaptor.getSrc();
1351 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1352 if (mlir::cast<cir::IntType>(elementTypeIfVector(castOp.getSrc().getType()))
1354 rewriter.replaceOpWithNewOp<mlir::LLVM::SIToFPOp>(castOp, llvmDstTy,
1357 rewriter.replaceOpWithNewOp<mlir::LLVM::UIToFPOp>(castOp, llvmDstTy,
1359 return mlir::success();
1361 case cir::CastKind::float_to_int: {
1362 mlir::Type dstTy = castOp.getType();
1363 mlir::Value llvmSrcVal = adaptor.getSrc();
1364 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1365 if (mlir::cast<cir::IntType>(elementTypeIfVector(castOp.getType()))
1367 rewriter.replaceOpWithNewOp<mlir::LLVM::FPToSIOp>(castOp, llvmDstTy,
1370 rewriter.replaceOpWithNewOp<mlir::LLVM::FPToUIOp>(castOp, llvmDstTy,
1372 return mlir::success();
1374 case cir::CastKind::bitcast: {
1375 mlir::Type dstTy = castOp.getType();
1376 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1381 mlir::Value llvmSrcVal = adaptor.getSrc();
1382 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(castOp, llvmDstTy,
1384 return mlir::success();
1386 case cir::CastKind::ptr_to_bool: {
1387 mlir::Value llvmSrcVal = adaptor.getSrc();
1388 mlir::Value zeroPtr = mlir::LLVM::ZeroOp::create(rewriter, castOp.getLoc(),
1389 llvmSrcVal.getType());
1390 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
1391 castOp, mlir::LLVM::ICmpPredicate::ne, llvmSrcVal, zeroPtr);
1394 case cir::CastKind::address_space: {
1395 mlir::Type dstTy = castOp.getType();
1396 mlir::Value llvmSrcVal = adaptor.getSrc();
1397 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1398 rewriter.replaceOpWithNewOp<mlir::LLVM::AddrSpaceCastOp>(castOp, llvmDstTy,
1402 case cir::CastKind::member_ptr_to_bool:
1407 return castOp.emitError(
"Unhandled cast kind: ")
1408 << castOp.getKindAttrName();
1412 return mlir::success();
1416 mlir::ModuleOp mod, mlir::Value index,
1417 mlir::Type baseTy, cir::IntType strideTy) {
1418 mlir::Operation *indexOp = index.getDefiningOp();
1422 auto indexType = mlir::cast<mlir::IntegerType>(index.getType());
1423 mlir::DataLayout llvmLayout(mod);
1424 std::optional<uint64_t> layoutWidth = llvmLayout.getTypeIndexBitwidth(baseTy);
1427 if (!layoutWidth || *layoutWidth == indexType.getWidth())
1433 auto sub = dyn_cast<mlir::LLVM::SubOp>(indexOp);
1434 bool rewriteSub =
false;
1437 dyn_cast<mlir::LLVM::ConstantOp>(sub.getLhs().getDefiningOp())) {
1438 auto lhsConstInt = mlir::dyn_cast<mlir::IntegerAttr>(lhsConst.getValue());
1439 if (lhsConstInt && lhsConstInt.getValue() == 0) {
1440 index = sub.getRhs();
1446 auto llvmDstType = rewriter.getIntegerType(*layoutWidth);
1447 bool isUnsigned = strideTy && strideTy.isUnsigned();
1449 indexType.getWidth(), *layoutWidth);
1452 index = mlir::LLVM::SubOp::create(
1453 rewriter, index.getLoc(),
1454 mlir::LLVM::ConstantOp::create(rewriter, index.getLoc(),
1455 index.getType(), 0),
1458 rewriter.eraseOp(sub);
1464mlir::LogicalResult CIRToLLVMPtrStrideOpLowering::matchAndRewrite(
1465 cir::PtrStrideOp ptrStrideOp, OpAdaptor adaptor,
1466 mlir::ConversionPatternRewriter &rewriter)
const {
1468 const mlir::TypeConverter *tc = getTypeConverter();
1469 const mlir::Type resultTy = tc->convertType(ptrStrideOp.getType());
1471 mlir::Type elementTy =
1476 if (mlir::isa<mlir::LLVM::LLVMVoidType>(elementTy) ||
1477 mlir::isa<mlir::LLVM::LLVMFunctionType>(elementTy))
1478 elementTy = mlir::IntegerType::get(elementTy.getContext(), 8,
1479 mlir::IntegerType::Signless);
1481 mlir::Value index = adaptor.getStride();
1483 rewriter, ptrStrideOp->getParentOfType<mlir::ModuleOp>(), index,
1484 adaptor.getBase().getType(),
1485 dyn_cast<cir::IntType>(ptrStrideOp.getOperand(1).getType()));
1487 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1488 ptrStrideOp, resultTy, elementTy, adaptor.getBase(), index);
1489 return mlir::success();
1492mlir::LogicalResult CIRToLLVMGetElementOpLowering::matchAndRewrite(
1493 cir::GetElementOp op, OpAdaptor adaptor,
1494 mlir::ConversionPatternRewriter &rewriter)
const {
1496 mlir::dyn_cast<cir::ArrayType>(op.getBaseType().getPointee())) {
1497 const mlir::TypeConverter *converter = getTypeConverter();
1498 const mlir::Type llArrayTy = converter->convertType(arrayTy);
1499 const mlir::Type llResultTy = converter->convertType(op.getType());
1500 mlir::Type elementTy =
1505 if (mlir::isa<mlir::LLVM::LLVMVoidType>(elementTy) ||
1506 mlir::isa<mlir::LLVM::LLVMFunctionType>(elementTy))
1507 elementTy = rewriter.getIntegerType(8);
1509 mlir::Value index = adaptor.getIndex();
1512 adaptor.getBase().getType(),
1513 dyn_cast<cir::IntType>(op.getOperand(1).getType()));
1518 std::array<mlir::LLVM::GEPArg, 2> offset{0, index};
1519 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, llResultTy, llArrayTy,
1520 adaptor.getBase(), offset);
1521 return mlir::success();
1524 op.emitError() <<
"NYI: GetElementOp lowering to LLVM for non-array";
1525 return mlir::failure();
1528mlir::LogicalResult CIRToLLVMBaseClassAddrOpLowering::matchAndRewrite(
1529 cir::BaseClassAddrOp baseClassOp, OpAdaptor adaptor,
1530 mlir::ConversionPatternRewriter &rewriter)
const {
1531 const mlir::Type resultType =
1532 getTypeConverter()->convertType(baseClassOp.getType());
1533 mlir::Value derivedAddr = adaptor.getDerivedAddr();
1534 llvm::SmallVector<mlir::LLVM::GEPArg, 1> offset = {
1535 adaptor.getOffset().getZExtValue()};
1536 mlir::Type byteType = mlir::IntegerType::get(resultType.getContext(), 8,
1537 mlir::IntegerType::Signless);
1538 if (adaptor.getOffset().getZExtValue() == 0) {
1539 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(
1540 baseClassOp, resultType, adaptor.getDerivedAddr());
1541 return mlir::success();
1544 if (baseClassOp.getAssumeNotNull()) {
1545 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1546 baseClassOp, resultType, byteType, derivedAddr, offset);
1548 auto loc = baseClassOp.getLoc();
1549 mlir::Value isNull = mlir::LLVM::ICmpOp::create(
1550 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, derivedAddr,
1551 mlir::LLVM::ZeroOp::create(rewriter, loc, derivedAddr.getType()));
1552 mlir::Value adjusted = mlir::LLVM::GEPOp::create(
1553 rewriter, loc, resultType, byteType, derivedAddr, offset);
1554 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(baseClassOp, isNull,
1555 derivedAddr, adjusted);
1557 return mlir::success();
1560mlir::LogicalResult CIRToLLVMDerivedClassAddrOpLowering::matchAndRewrite(
1561 cir::DerivedClassAddrOp derivedClassOp, OpAdaptor adaptor,
1562 mlir::ConversionPatternRewriter &rewriter)
const {
1563 const mlir::Type resultType =
1564 getTypeConverter()->convertType(derivedClassOp.getType());
1565 mlir::Value baseAddr = adaptor.getBaseAddr();
1568 int64_t offsetVal = -(adaptor.getOffset().getZExtValue());
1569 if (offsetVal == 0) {
1571 rewriter.replaceOp(derivedClassOp, baseAddr);
1572 return mlir::success();
1574 llvm::SmallVector<mlir::LLVM::GEPArg, 1> offset = {offsetVal};
1575 mlir::Type byteType = mlir::IntegerType::get(resultType.getContext(), 8,
1576 mlir::IntegerType::Signless);
1577 if (derivedClassOp.getAssumeNotNull()) {
1578 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1579 derivedClassOp, resultType, byteType, baseAddr, offset,
1580 mlir::LLVM::GEPNoWrapFlags::inbounds);
1582 mlir::Location loc = derivedClassOp.getLoc();
1583 mlir::Value isNull = mlir::LLVM::ICmpOp::create(
1584 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, baseAddr,
1585 mlir::LLVM::ZeroOp::create(rewriter, loc, baseAddr.getType()));
1586 mlir::Value adjusted =
1587 mlir::LLVM::GEPOp::create(rewriter, loc, resultType, byteType, baseAddr,
1588 offset, mlir::LLVM::GEPNoWrapFlags::inbounds);
1589 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(derivedClassOp, isNull,
1590 baseAddr, adjusted);
1592 return mlir::success();
1595mlir::LogicalResult CIRToLLVMFMaxNumOpLowering::matchAndRewrite(
1596 cir::FMaxNumOp op, OpAdaptor adaptor,
1597 mlir::ConversionPatternRewriter &rewriter)
const {
1598 mlir::Type resTy = typeConverter->convertType(op.getType());
1599 rewriter.replaceOpWithNewOp<mlir::LLVM::MaxNumOp>(
1600 op, resTy, adaptor.getLhs(), adaptor.getRhs(),
1601 mlir::LLVM::FastmathFlags::nsz);
1602 return mlir::success();
1605mlir::LogicalResult CIRToLLVMFMinNumOpLowering::matchAndRewrite(
1606 cir::FMinNumOp op, OpAdaptor adaptor,
1607 mlir::ConversionPatternRewriter &rewriter)
const {
1608 mlir::Type resTy = typeConverter->convertType(op.getType());
1609 rewriter.replaceOpWithNewOp<mlir::LLVM::MinNumOp>(
1610 op, resTy, adaptor.getLhs(), adaptor.getRhs(),
1611 mlir::LLVM::FastmathFlags::nsz);
1612 return mlir::success();
1615mlir::LogicalResult CIRToLLVMAllocaOpLowering::matchAndRewrite(
1616 cir::AllocaOp op, OpAdaptor adaptor,
1617 mlir::ConversionPatternRewriter &rewriter)
const {
1620 ? adaptor.getDynAllocSize()
1621 : mlir::LLVM::ConstantOp::create(
1622 rewriter, op.getLoc(),
1623 typeConverter->convertType(rewriter.getIndexType()), 1);
1624 mlir::Type elementTy =
1626 mlir::Type resultTy =
1632 rewriter.replaceOpWithNewOp<mlir::LLVM::AllocaOp>(op, resultTy, elementTy,
1633 size, op.getAlignment());
1635 return mlir::success();
1638mlir::LogicalResult CIRToLLVMReturnOpLowering::matchAndRewrite(
1639 cir::ReturnOp op, OpAdaptor adaptor,
1640 mlir::ConversionPatternRewriter &rewriter)
const {
1641 rewriter.replaceOpWithNewOp<mlir::LLVM::ReturnOp>(op, adaptor.getOperands());
1642 return mlir::LogicalResult::success();
1645mlir::LogicalResult CIRToLLVMRotateOpLowering::matchAndRewrite(
1646 cir::RotateOp op, OpAdaptor adaptor,
1647 mlir::ConversionPatternRewriter &rewriter)
const {
1650 mlir::Value input = adaptor.getInput();
1651 if (op.isRotateLeft())
1652 rewriter.replaceOpWithNewOp<mlir::LLVM::FshlOp>(op, input, input,
1653 adaptor.getAmount());
1655 rewriter.replaceOpWithNewOp<mlir::LLVM::FshrOp>(op, input, input,
1656 adaptor.getAmount());
1657 return mlir::LogicalResult::success();
1662 for (mlir::NamedAttribute attr : op->getAttrs()) {
1664 if (attr.getName() == CIRDialect::getCalleeAttrName() ||
1665 attr.getName() == CIRDialect::getSideEffectAttrName() ||
1666 attr.getName() == CIRDialect::getNoThrowAttrName() ||
1667 attr.getName() == CIRDialect::getNoUnwindAttrName() ||
1668 attr.getName() == CIRDialect::getNoReturnAttrName() ||
1669 attr.getName() == CIRDialect::getMustTailAttrName())
1673 result.push_back(attr);
1677static mlir::LogicalResult
1679 mlir::ConversionPatternRewriter &rewriter,
1680 const mlir::TypeConverter *converter,
1681 mlir::FlatSymbolRefAttr calleeAttr,
1682 mlir::Block *continueBlock =
nullptr,
1683 mlir::Block *landingPadBlock =
nullptr) {
1685 mlir::ValueTypeRange<mlir::ResultRange> cirResults = op->getResultTypes();
1686 auto call = cast<cir::CIRCallOpInterface>(op);
1688 if (converter->convertTypes(cirResults, llvmResults).failed())
1689 return mlir::failure();
1693 mlir::LLVM::MemoryEffectsAttr memoryEffects;
1694 bool noUnwind =
false;
1695 bool willReturn =
false;
1696 bool noReturn =
false;
1698 memoryEffects, noUnwind, willReturn, noReturn);
1703 mlir::LLVM::LLVMFunctionType llvmFnTy;
1710 mlir::Operation *callee =
1711 mlir::SymbolTable::lookupNearestSymbolFrom(op, calleeAttr);
1712 if (
auto fn = mlir::dyn_cast<mlir::FunctionOpInterface>(callee)) {
1713 llvmFnTy = converter->convertType<mlir::LLVM::LLVMFunctionType>(
1714 fn.getFunctionType());
1715 assert(llvmFnTy &&
"Failed to convert function type");
1716 }
else if (
auto alias = mlir::cast<mlir::LLVM::AliasOp>(callee)) {
1724 auto symAttr = mlir::cast<mlir::FlatSymbolRefAttr>(calleeAttr);
1726 mlir::LLVM::AddressOfOp::create(
1727 rewriter, op->getLoc(),
1728 mlir::LLVM::LLVMPointerType::get(rewriter.getContext()), symAttr)
1730 adjustedCallOperands.push_back(addrOfAlias);
1733 llvm::append_range(adjustedCallOperands, callOperands);
1734 callOperands = adjustedCallOperands;
1738 llvmFnTy = mlir::cast<mlir::LLVM::LLVMFunctionType>(alias.getType());
1741 return op->emitError(
"Unexpected callee type!");
1744 assert(!op->getOperands().empty() &&
1745 "operands list must no be empty for the indirect call");
1746 auto calleeTy = op->getOperands().front().getType();
1747 auto calleePtrTy = cast<cir::PointerType>(calleeTy);
1748 auto calleeFuncTy = cast<cir::FuncType>(calleePtrTy.getPointee());
1749 llvm::append_range(adjustedCallOperands, callOperands);
1750 llvmFnTy = cast<mlir::LLVM::LLVMFunctionType>(
1751 converter->convertType(calleeFuncTy));
1756 if (landingPadBlock) {
1757 auto newOp = rewriter.replaceOpWithNewOp<mlir::LLVM::InvokeOp>(
1758 op, llvmFnTy, calleeAttr, callOperands, continueBlock,
1759 mlir::ValueRange{}, landingPadBlock, mlir::ValueRange{});
1760 newOp->setAttrs(attributes);
1762 auto newOp = rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(
1763 op, llvmFnTy, calleeAttr, callOperands);
1764 newOp->setAttrs(attributes);
1766 newOp.setMemoryEffectsAttr(memoryEffects);
1767 newOp.setNoUnwind(noUnwind);
1768 newOp.setWillReturn(willReturn);
1769 newOp.setNoreturn(noReturn);
1770 if (op->hasAttr(CIRDialect::getMustTailAttrName()))
1771 newOp.setTailCallKind(mlir::LLVM::TailCallKind::MustTail);
1774 return mlir::success();
1777mlir::LogicalResult CIRToLLVMCallOpLowering::matchAndRewrite(
1778 cir::CallOp op, OpAdaptor adaptor,
1779 mlir::ConversionPatternRewriter &rewriter)
const {
1781 getTypeConverter(), op.getCalleeAttr());
1784mlir::LogicalResult CIRToLLVMTryCallOpLowering::matchAndRewrite(
1785 cir::TryCallOp op, OpAdaptor adaptor,
1786 mlir::ConversionPatternRewriter &rewriter)
const {
1789 getTypeConverter(), op.getCalleeAttr(),
1790 op.getNormalDest(), op.getUnwindDest());
1793mlir::LogicalResult CIRToLLVMReturnAddrOpLowering::matchAndRewrite(
1794 cir::ReturnAddrOp op, OpAdaptor adaptor,
1795 mlir::ConversionPatternRewriter &rewriter)
const {
1796 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
1798 llvmPtrTy, adaptor.getOperands());
1799 return mlir::success();
1802mlir::LogicalResult CIRToLLVMFrameAddrOpLowering::matchAndRewrite(
1803 cir::FrameAddrOp op, OpAdaptor adaptor,
1804 mlir::ConversionPatternRewriter &rewriter)
const {
1805 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
1807 adaptor.getOperands());
1808 return mlir::success();
1811mlir::LogicalResult CIRToLLVMClearCacheOpLowering::matchAndRewrite(
1812 cir::ClearCacheOp op, OpAdaptor adaptor,
1813 mlir::ConversionPatternRewriter &rewriter)
const {
1814 mlir::Value begin = adaptor.getBegin();
1815 mlir::Value end = adaptor.getEnd();
1816 auto intrinNameAttr =
1817 mlir::StringAttr::get(op.getContext(),
"llvm.clear_cache");
1818 rewriter.replaceOpWithNewOp<mlir::LLVM::CallIntrinsicOp>(
1819 op, mlir::Type{}, intrinNameAttr, mlir::ValueRange{begin, end});
1821 return mlir::success();
1824mlir::LogicalResult CIRToLLVMAddrOfReturnAddrOpLowering::matchAndRewrite(
1825 cir::AddrOfReturnAddrOp op, OpAdaptor adaptor,
1826 mlir::ConversionPatternRewriter &rewriter)
const {
1827 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
1829 llvmPtrTy, adaptor.getOperands());
1830 return mlir::success();
1833mlir::LogicalResult CIRToLLVMLoadOpLowering::matchAndRewrite(
1834 cir::LoadOp op, OpAdaptor adaptor,
1835 mlir::ConversionPatternRewriter &rewriter)
const {
1836 const mlir::Type llvmTy =
1838 mlir::LLVM::AtomicOrdering ordering =
getLLVMMemOrder(op.getMemOrder());
1839 std::optional<size_t> opAlign = op.getAlignment();
1840 unsigned alignment =
1841 (unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmTy));
1848 std::optional<llvm::StringRef> llvmSyncScope =
1851 mlir::LLVM::LoadOp newLoad = mlir::LLVM::LoadOp::create(
1852 rewriter, op->getLoc(), llvmTy, adaptor.getAddr(), alignment,
1853 op.getIsVolatile(),
false,
1854 false,
false, ordering,
1855 llvmSyncScope.value_or(std::string()));
1858 mlir::Value result =
1860 rewriter.replaceOp(op, result);
1862 return mlir::LogicalResult::success();
1866cir::direct::CIRToLLVMVecMaskedLoadOpLowering::matchAndRewrite(
1867 cir::VecMaskedLoadOp op, OpAdaptor adaptor,
1868 mlir::ConversionPatternRewriter &rewriter)
const {
1869 const mlir::Type llvmResTy =
1872 std::optional<size_t> opAlign = op.getAlignment();
1873 unsigned alignment =
1874 (unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmResTy));
1876 mlir::IntegerAttr alignAttr = rewriter.getI32IntegerAttr(alignment);
1878 auto newLoad = mlir::LLVM::MaskedLoadOp::create(
1879 rewriter, op.getLoc(), llvmResTy, adaptor.getAddr(), adaptor.getMask(),
1880 adaptor.getPassThru(), alignAttr);
1882 rewriter.replaceOp(op, newLoad.getResult());
1883 return mlir::success();
1886mlir::LogicalResult CIRToLLVMStoreOpLowering::matchAndRewrite(
1887 cir::StoreOp op, OpAdaptor adaptor,
1888 mlir::ConversionPatternRewriter &rewriter)
const {
1889 mlir::LLVM::AtomicOrdering memorder =
getLLVMMemOrder(op.getMemOrder());
1890 const mlir::Type llvmTy =
1891 getTypeConverter()->convertType(op.getValue().getType());
1892 std::optional<size_t> opAlign = op.getAlignment();
1893 unsigned alignment =
1894 (unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmTy));
1900 op.getValue().getType(), adaptor.getValue());
1905 std::optional<llvm::StringRef> llvmSyncScope =
1908 mlir::LLVM::StoreOp storeOp = mlir::LLVM::StoreOp::create(
1909 rewriter, op->getLoc(), value, adaptor.getAddr(), alignment,
1911 false,
false, memorder,
1912 llvmSyncScope.value_or(std::string()));
1913 rewriter.replaceOp(op, storeOp);
1915 return mlir::LogicalResult::success();
1919 auto array = mlir::dyn_cast<mlir::ArrayAttr>(attr.getElts());
1920 return attr.hasTrailingZeros() ||
1921 (array && std::count_if(array.begin(), array.end(), [](
auto elt) {
1922 auto ar = dyn_cast<cir::ConstArrayAttr>(elt);
1923 return ar && hasTrailingZeros(ar);
1927mlir::LogicalResult CIRToLLVMConstantOpLowering::matchAndRewrite(
1928 cir::ConstantOp op, OpAdaptor adaptor,
1929 mlir::ConversionPatternRewriter &rewriter)
const {
1930 mlir::Attribute attr = op.getValue();
1932 if (mlir::isa<cir::PoisonAttr>(attr)) {
1933 rewriter.replaceOpWithNewOp<mlir::LLVM::PoisonOp>(
1934 op, getTypeConverter()->convertType(op.getType()));
1935 return mlir::success();
1938 if (mlir::isa<mlir::IntegerType>(op.getType())) {
1943 attr = op.getValue();
1944 }
else if (mlir::isa<cir::BoolType>(op.getType())) {
1945 int value = mlir::cast<cir::BoolAttr>(op.getValue()).getValue();
1946 attr = rewriter.getIntegerAttr(typeConverter->convertType(op.getType()),
1948 }
else if (mlir::isa<cir::IntType>(op.getType())) {
1950 if (
auto ga = mlir::dyn_cast<cir::GlobalViewAttr>(op.getValue())) {
1956 op.emitError() <<
"global view with integer type";
1957 return mlir::failure();
1960 attr = rewriter.getIntegerAttr(
1961 typeConverter->convertType(op.getType()),
1962 mlir::cast<cir::IntAttr>(op.getValue()).getValue());
1963 }
else if (mlir::isa<cir::FPTypeInterface>(op.getType())) {
1964 attr = rewriter.getFloatAttr(
1965 typeConverter->convertType(op.getType()),
1966 mlir::cast<cir::FPAttr>(op.getValue()).getValue());
1967 }
else if (mlir::isa<cir::PointerType>(op.getType())) {
1969 if (mlir::isa<cir::ConstPtrAttr>(op.getValue())) {
1970 if (mlir::cast<cir::ConstPtrAttr>(op.getValue()).isNullValue()) {
1971 rewriter.replaceOpWithNewOp<mlir::LLVM::ZeroOp>(
1972 op, typeConverter->convertType(op.getType()));
1973 return mlir::success();
1977 if (
auto gv = mlir::dyn_cast<cir::GlobalViewAttr>(op.getValue())) {
1979 rewriter.replaceOp(op, newOp);
1980 return mlir::success();
1982 attr = op.getValue();
1983 }
else if (
const auto arrTy = mlir::dyn_cast<cir::ArrayType>(op.getType())) {
1984 const auto constArr = mlir::dyn_cast<cir::ConstArrayAttr>(op.getValue());
1985 if (!constArr && !isa<cir::ZeroAttr, cir::UndefAttr>(op.getValue()))
1986 return op.emitError() <<
"array does not have a constant initializer";
1988 std::optional<mlir::Attribute> denseAttr;
1990 const mlir::Value newOp =
1992 rewriter.replaceOp(op, newOp);
1993 return mlir::success();
1994 }
else if (constArr &&
1996 attr = denseAttr.value();
1998 const mlir::Value initVal =
2000 rewriter.replaceOp(op, initVal);
2001 return mlir::success();
2003 }
else if (
const auto recordAttr =
2004 mlir::dyn_cast<cir::ConstRecordAttr>(op.getValue())) {
2006 rewriter.replaceOp(op, initVal);
2007 return mlir::success();
2008 }
else if (
const auto vecTy = mlir::dyn_cast<cir::VectorType>(op.getType())) {
2010 getTypeConverter()));
2011 return mlir::success();
2012 }
else if (
auto recTy = mlir::dyn_cast<cir::RecordType>(op.getType())) {
2013 if (mlir::isa<cir::ZeroAttr, cir::UndefAttr>(attr)) {
2014 mlir::Value initVal =
2016 rewriter.replaceOp(op, initVal);
2017 return mlir::success();
2019 return op.emitError() <<
"unsupported lowering for record constant type "
2021 }
else if (
auto complexTy = mlir::dyn_cast<cir::ComplexType>(op.getType())) {
2022 mlir::Type complexElemTy = complexTy.getElementType();
2023 mlir::Type complexElemLLVMTy = typeConverter->convertType(complexElemTy);
2025 if (
auto zeroInitAttr = mlir::dyn_cast<cir::ZeroAttr>(op.getValue())) {
2026 mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(complexElemLLVMTy);
2027 mlir::ArrayAttr array = rewriter.getArrayAttr({zeroAttr, zeroAttr});
2028 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
2029 op, getTypeConverter()->convertType(op.getType()), array);
2030 return mlir::success();
2033 auto complexAttr = mlir::cast<cir::ConstComplexAttr>(op.getValue());
2035 mlir::Attribute components[2];
2036 if (mlir::isa<cir::IntType>(complexElemTy)) {
2037 components[0] = rewriter.getIntegerAttr(
2039 mlir::cast<cir::IntAttr>(complexAttr.getReal()).getValue());
2040 components[1] = rewriter.getIntegerAttr(
2042 mlir::cast<cir::IntAttr>(complexAttr.getImag()).getValue());
2044 components[0] = rewriter.getFloatAttr(
2046 mlir::cast<cir::FPAttr>(complexAttr.getReal()).getValue());
2047 components[1] = rewriter.getFloatAttr(
2049 mlir::cast<cir::FPAttr>(complexAttr.getImag()).getValue());
2052 attr = rewriter.getArrayAttr(components);
2054 return op.emitError() <<
"unsupported constant type " << op.getType();
2057 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
2058 op, getTypeConverter()->convertType(op.getType()),
attr);
2060 return mlir::success();
2064 mlir::DataLayout layout(op.getParentOfType<mlir::ModuleOp>());
2066 if (isa<cir::VoidType>(type))
2067 type = cir::IntType::get(type.getContext(), 8,
false);
2068 return llvm::divideCeil(layout.getTypeSizeInBits(type), 8);
2071mlir::LogicalResult CIRToLLVMPrefetchOpLowering::matchAndRewrite(
2072 cir::PrefetchOp op, OpAdaptor adaptor,
2073 mlir::ConversionPatternRewriter &rewriter)
const {
2074 rewriter.replaceOpWithNewOp<mlir::LLVM::Prefetch>(
2075 op, adaptor.getAddr(), adaptor.getIsWrite(), adaptor.getLocality(),
2077 return mlir::success();
2080mlir::LogicalResult CIRToLLVMPtrDiffOpLowering::matchAndRewrite(
2081 cir::PtrDiffOp op, OpAdaptor adaptor,
2082 mlir::ConversionPatternRewriter &rewriter)
const {
2083 auto dstTy = mlir::cast<cir::IntType>(op.getType());
2084 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
2086 auto lhs = mlir::LLVM::PtrToIntOp::create(rewriter, op.getLoc(), llvmDstTy,
2088 auto rhs = mlir::LLVM::PtrToIntOp::create(rewriter, op.getLoc(), llvmDstTy,
2092 mlir::LLVM::SubOp::create(rewriter, op.getLoc(), llvmDstTy, lhs, rhs);
2094 cir::PointerType ptrTy = op.getLhs().getType();
2096 uint64_t typeSize =
getTypeSize(ptrTy.getPointee(), *op);
2099 mlir::Value resultVal = diff.getResult();
2100 if (typeSize != 1) {
2101 auto typeSizeVal = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
2102 llvmDstTy, typeSize);
2104 if (dstTy.isUnsigned()) {
2106 mlir::LLVM::UDivOp::create(rewriter, op.getLoc(), diff, typeSizeVal);
2107 uDiv.setIsExact(
true);
2108 resultVal = uDiv.getResult();
2111 mlir::LLVM::SDivOp::create(rewriter, op.getLoc(), diff, typeSizeVal);
2112 sDiv.setIsExact(
true);
2113 resultVal = sDiv.getResult();
2116 rewriter.replaceOp(op, resultVal);
2117 return mlir::success();
2120mlir::LogicalResult CIRToLLVMExpectOpLowering::matchAndRewrite(
2121 cir::ExpectOp op, OpAdaptor adaptor,
2122 mlir::ConversionPatternRewriter &rewriter)
const {
2126 std::optional<llvm::APFloat> prob = op.getProb();
2128 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpectWithProbabilityOp>(
2129 op, adaptor.getVal(), adaptor.getExpected(), prob.value());
2131 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpectOp>(op, adaptor.getVal(),
2132 adaptor.getExpected());
2133 return mlir::success();
2136mlir::LogicalResult CIRToLLVMAbsOpLowering::matchAndRewrite(
2137 cir::AbsOp op, OpAdaptor adaptor,
2138 mlir::ConversionPatternRewriter &rewriter)
const {
2139 mlir::Type resTy = typeConverter->convertType(op.getType());
2140 auto absOp = mlir::LLVM::AbsOp::create(rewriter, op.getLoc(), resTy,
2141 adaptor.getOperands()[0],
2142 adaptor.getMinIsPoison());
2143 rewriter.replaceOp(op, absOp);
2144 return mlir::success();
2151void CIRToLLVMFuncOpLowering::lowerFuncAttributes(
2152 cir::FuncOp func,
bool filterArgAndResAttrs,
2153 SmallVectorImpl<mlir::NamedAttribute> &result)
const {
2155 for (mlir::NamedAttribute attr : func->getAttrs()) {
2157 if (
attr.getName() == mlir::SymbolTable::getSymbolAttrName() ||
2158 attr.getName() == func.getFunctionTypeAttrName() ||
2160 attr.getName() == func.getDsoLocalAttrName() ||
2161 attr.getName() == func.getInlineKindAttrName() ||
2162 attr.getName() == func.getSideEffectAttrName() ||
2163 attr.getName() == CIRDialect::getNoReturnAttrName() ||
2164 (filterArgAndResAttrs &&
2165 (
attr.getName() == func.getArgAttrsAttrName() ||
2166 attr.getName() == func.getResAttrsAttrName())))
2170 result.push_back(attr);
2174mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewriteAlias(
2175 cir::FuncOp op, llvm::StringRef aliasee, mlir::Type ty, OpAdaptor adaptor,
2176 mlir::ConversionPatternRewriter &rewriter)
const {
2177 SmallVector<mlir::NamedAttribute, 4> attributes;
2178 lowerFuncAttributes(op,
false, attributes);
2180 mlir::Location loc = op.getLoc();
2181 auto aliasOp = rewriter.replaceOpWithNewOp<mlir::LLVM::AliasOp>(
2182 op, ty,
convertLinkage(op.getLinkage()), op.getName(), op.getDsoLocal(),
2186 mlir::OpBuilder builder(op.getContext());
2187 mlir::Block *block = builder.createBlock(&aliasOp.getInitializerRegion());
2188 builder.setInsertionPointToStart(block);
2191 mlir::Type ptrTy = mlir::LLVM::LLVMPointerType::get(ty.getContext());
2192 auto addrOp = mlir::LLVM::AddressOfOp::create(builder, loc, ptrTy, aliasee);
2193 mlir::LLVM::ReturnOp::create(builder, loc, addrOp);
2195 return mlir::success();
2198mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewrite(
2199 cir::FuncOp op, OpAdaptor adaptor,
2200 mlir::ConversionPatternRewriter &rewriter)
const {
2202 cir::FuncType fnType = op.getFunctionType();
2203 bool isDsoLocal = op.getDsoLocal();
2204 mlir::TypeConverter::SignatureConversion signatureConversion(
2205 fnType.getNumInputs());
2207 for (
const auto &argType : llvm::enumerate(fnType.getInputs())) {
2208 mlir::Type convertedType = typeConverter->convertType(argType.value());
2210 return mlir::failure();
2211 signatureConversion.addInputs(argType.index(), convertedType);
2214 mlir::Type resultType =
2215 getTypeConverter()->convertType(fnType.getReturnType());
2218 mlir::Type llvmFnTy = mlir::LLVM::LLVMFunctionType::get(
2219 resultType ? resultType : mlir::LLVM::LLVMVoidType::get(getContext()),
2220 signatureConversion.getConvertedTypes(),
2224 if (std::optional<llvm::StringRef> aliasee = op.getAliasee())
2225 return matchAndRewriteAlias(op, *aliasee, llvmFnTy, adaptor, rewriter);
2229 mlir::Location loc = op.getLoc();
2230 if (mlir::FusedLoc fusedLoc = mlir::dyn_cast<mlir::FusedLoc>(loc))
2231 loc = fusedLoc.getLocations()[0];
2232 assert((mlir::isa<mlir::FileLineColLoc>(loc) ||
2233 mlir::isa<mlir::UnknownLoc>(loc)) &&
2234 "expected single location or unknown location here");
2238 mlir::LLVM::CConv cconv = mlir::LLVM::CConv::C;
2239 SmallVector<mlir::NamedAttribute, 4> attributes;
2240 lowerFuncAttributes(op,
false, attributes);
2242 mlir::LLVM::LLVMFuncOp fn = mlir::LLVM::LLVMFuncOp::create(
2243 rewriter, loc, op.getName(), llvmFnTy, linkage, isDsoLocal, cconv,
2244 mlir::SymbolRefAttr(), attributes);
2248 if (std::optional<cir::SideEffect> sideEffectKind = op.getSideEffect()) {
2249 switch (*sideEffectKind) {
2250 case cir::SideEffect::All:
2252 case cir::SideEffect::Pure:
2253 fn.setMemoryEffectsAttr(mlir::LLVM::MemoryEffectsAttr::get(
2255 mlir::LLVM::ModRefInfo::Ref,
2256 mlir::LLVM::ModRefInfo::Ref,
2257 mlir::LLVM::ModRefInfo::Ref,
2258 mlir::LLVM::ModRefInfo::Ref,
2259 mlir::LLVM::ModRefInfo::Ref,
2260 mlir::LLVM::ModRefInfo::Ref));
2261 fn.setNoUnwind(
true);
2262 fn.setWillReturn(
true);
2264 case cir::SideEffect::Const:
2265 fn.setMemoryEffectsAttr(mlir::LLVM::MemoryEffectsAttr::get(
2267 mlir::LLVM::ModRefInfo::NoModRef,
2268 mlir::LLVM::ModRefInfo::NoModRef,
2269 mlir::LLVM::ModRefInfo::NoModRef,
2270 mlir::LLVM::ModRefInfo::NoModRef,
2271 mlir::LLVM::ModRefInfo::NoModRef,
2272 mlir::LLVM::ModRefInfo::NoModRef));
2273 fn.setNoUnwind(
true);
2274 fn.setWillReturn(
true);
2279 if (op->hasAttr(CIRDialect::getNoReturnAttrName()))
2280 fn.setNoreturn(
true);
2282 if (std::optional<cir::InlineKind> inlineKind = op.getInlineKind()) {
2283 fn.setNoInline(*inlineKind == cir::InlineKind::NoInline);
2284 fn.setInlineHint(*inlineKind == cir::InlineKind::InlineHint);
2285 fn.setAlwaysInline(*inlineKind == cir::InlineKind::AlwaysInline);
2288 if (std::optional<llvm::StringRef> personality = op.getPersonality())
2289 fn.setPersonality(*personality);
2294 rewriter.inlineRegionBefore(op.getBody(), fn.getBody(), fn.end());
2295 if (failed(rewriter.convertRegionTypes(&fn.getBody(), *typeConverter,
2296 &signatureConversion)))
2297 return mlir::failure();
2299 rewriter.eraseOp(op);
2301 return mlir::LogicalResult::success();
2304mlir::LogicalResult CIRToLLVMGetGlobalOpLowering::matchAndRewrite(
2305 cir::GetGlobalOp op, OpAdaptor adaptor,
2306 mlir::ConversionPatternRewriter &rewriter)
const {
2309 if (op->getUses().empty()) {
2310 rewriter.eraseOp(op);
2311 return mlir::success();
2314 mlir::Type
type = getTypeConverter()->convertType(op.getType());
2315 mlir::Operation *newop = mlir::LLVM::AddressOfOp::create(
2316 rewriter, op.getLoc(), type, op.getName());
2320 newop = mlir::LLVM::ThreadlocalAddressOp::create(rewriter, op.getLoc(),
2321 type, newop->getResult(0));
2324 rewriter.replaceOp(op, newop);
2325 return mlir::success();
2328llvm::SmallVector<mlir::NamedAttribute>
2329CIRToLLVMGlobalOpLowering::lowerGlobalAttributes(
2330 cir::GlobalOp op, mlir::ConversionPatternRewriter &rewriter)
const {
2331 SmallVector<mlir::NamedAttribute> attributes;
2333 if (mlir::StringAttr sectionAttr = op.getSectionAttr())
2334 attributes.push_back(rewriter.getNamedAttr(
"section", sectionAttr));
2336 mlir::LLVM::VisibilityAttr visibility = mlir::LLVM::VisibilityAttr::get(
2339 attributes.push_back(rewriter.getNamedAttr(
"visibility_", visibility));
2341 if (op->getAttr(CUDAExternallyInitializedAttr::getMnemonic()))
2342 attributes.push_back(rewriter.getNamedAttr(
"externally_initialized",
2343 rewriter.getUnitAttr()));
2350void CIRToLLVMGlobalOpLowering::setupRegionInitializedLLVMGlobalOp(
2351 cir::GlobalOp op, mlir::ConversionPatternRewriter &rewriter)
const {
2352 const mlir::Type llvmType =
2359 const bool isConst = op.getConstant();
2360 unsigned addrSpace = 0;
2361 if (
auto targetAS = mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
2362 op.getAddrSpaceAttr()))
2363 addrSpace = targetAS.getValue();
2364 const bool isDsoLocal = op.getDsoLocal();
2365 const bool isThreadLocal = (
bool)op.getTlsModelAttr();
2366 const uint64_t alignment = op.getAlignment().value_or(0);
2367 const mlir::LLVM::Linkage linkage =
convertLinkage(op.getLinkage());
2368 const StringRef symbol = op.getSymName();
2369 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
2371 SmallVector<mlir::NamedAttribute> attributes =
2372 lowerGlobalAttributes(op, rewriter);
2374 mlir::LLVM::GlobalOp newGlobalOp =
2375 rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
2376 op, llvmType, isConst, linkage, symbol,
nullptr, alignment, addrSpace,
2377 isDsoLocal, isThreadLocal, comdatAttr, attributes);
2378 newGlobalOp.getRegion().emplaceBlock();
2379 rewriter.setInsertionPointToEnd(newGlobalOp.getInitializerBlock());
2383CIRToLLVMGlobalOpLowering::matchAndRewriteRegionInitializedGlobal(
2384 cir::GlobalOp op, mlir::Attribute init,
2385 mlir::ConversionPatternRewriter &rewriter)
const {
2387 assert((isa<cir::ConstArrayAttr, cir::ConstRecordAttr, cir::ConstVectorAttr,
2388 cir::ConstPtrAttr, cir::ConstComplexAttr, cir::GlobalViewAttr,
2389 cir::TypeInfoAttr, cir::UndefAttr, cir::PoisonAttr,
2390 cir::VTableAttr, cir::ZeroAttr>(init)));
2395 const mlir::Location loc = op.getLoc();
2396 setupRegionInitializedLLVMGlobalOp(op, rewriter);
2398 mlir::Value value = valueConverter.visit(init);
2399 mlir::LLVM::ReturnOp::create(rewriter, loc, value);
2400 return mlir::success();
2403mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite(
2404 cir::GlobalOp op, OpAdaptor adaptor,
2405 mlir::ConversionPatternRewriter &rewriter)
const {
2408 if (!op.getCtorRegion().empty() || !op.getDtorRegion().empty())
2409 return op.emitError() <<
"GlobalOp ctor and dtor regions should be removed "
2410 "in LoweringPrepare";
2412 std::optional<mlir::Attribute> init = op.getInitialValue();
2415 const mlir::Type cirSymType = op.getSymType();
2418 const mlir::Type llvmType =
2423 const bool isConst = op.getConstant();
2424 unsigned addrSpace = 0;
2425 if (
auto targetAS = mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
2426 op.getAddrSpaceAttr()))
2427 addrSpace = targetAS.getValue();
2428 const bool isDsoLocal = op.getDsoLocal();
2429 const bool isThreadLocal = (
bool)op.getTlsModelAttr();
2430 const uint64_t alignment = op.getAlignment().value_or(0);
2431 const mlir::LLVM::Linkage linkage =
convertLinkage(op.getLinkage());
2432 const StringRef symbol = op.getSymName();
2433 SmallVector<mlir::NamedAttribute> attributes =
2434 lowerGlobalAttributes(op, rewriter);
2436 if (init.has_value()) {
2437 if (mlir::isa<cir::FPAttr, cir::IntAttr, cir::BoolAttr>(init.value())) {
2439 init = initRewriter.visit(init.value());
2444 if (!init.value()) {
2445 op.emitError() <<
"unsupported initializer '" << init.value() <<
"'";
2446 return mlir::failure();
2448 }
else if (mlir::isa<cir::ConstArrayAttr, cir::ConstVectorAttr,
2449 cir::ConstRecordAttr, cir::ConstPtrAttr,
2450 cir::ConstComplexAttr, cir::GlobalViewAttr,
2451 cir::TypeInfoAttr, cir::UndefAttr, cir::PoisonAttr,
2452 cir::VTableAttr, cir::ZeroAttr>(init.value())) {
2456 return matchAndRewriteRegionInitializedGlobal(op, init.value(), rewriter);
2460 op.emitError() <<
"unsupported initializer '" << init.value() <<
"'";
2461 return mlir::failure();
2465 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
2466 rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
2467 op, llvmType, isConst, linkage, symbol, init.value_or(mlir::Attribute()),
2468 alignment, addrSpace, isDsoLocal, isThreadLocal, comdatAttr, attributes);
2470 return mlir::success();
2474CIRToLLVMGlobalOpLowering::getComdatAttr(cir::GlobalOp &op,
2475 mlir::OpBuilder &builder)
const {
2476 if (!op.getComdat())
2477 return mlir::SymbolRefAttr{};
2479 mlir::ModuleOp module = op->getParentOfType<mlir::ModuleOp>();
2480 mlir::OpBuilder::InsertionGuard guard(builder);
2481 StringRef comdatName(
"__llvm_comdat_globals");
2483 builder.setInsertionPointToStart(module.getBody());
2485 mlir::LLVM::ComdatOp::create(builder, module.getLoc(), comdatName);
2488 if (
auto comdatSelector = comdatOp.lookupSymbol<mlir::LLVM::ComdatSelectorOp>(
2490 return mlir::SymbolRefAttr::get(
2491 builder.getContext(), comdatName,
2492 mlir::FlatSymbolRefAttr::get(comdatSelector.getSymNameAttr()));
2495 builder.setInsertionPointToStart(&comdatOp.getBody().back());
2496 auto selectorOp = mlir::LLVM::ComdatSelectorOp::create(
2497 builder, comdatOp.getLoc(), op.getSymName(),
2498 mlir::LLVM::comdat::Comdat::Any);
2499 return mlir::SymbolRefAttr::get(
2500 builder.getContext(), comdatName,
2501 mlir::FlatSymbolRefAttr::get(selectorOp.getSymNameAttr()));
2504mlir::LogicalResult CIRToLLVMSwitchFlatOpLowering::matchAndRewrite(
2505 cir::SwitchFlatOp op, OpAdaptor adaptor,
2506 mlir::ConversionPatternRewriter &rewriter)
const {
2508 llvm::SmallVector<mlir::APInt, 8> caseValues;
2509 for (mlir::Attribute val : op.getCaseValues()) {
2510 auto intAttr = cast<cir::IntAttr>(val);
2511 caseValues.push_back(intAttr.getValue());
2514 llvm::SmallVector<mlir::Block *, 8> caseDestinations;
2515 llvm::SmallVector<mlir::ValueRange, 8> caseOperands;
2517 for (mlir::Block *x : op.getCaseDestinations())
2518 caseDestinations.push_back(x);
2520 for (mlir::OperandRange x : op.getCaseOperands())
2521 caseOperands.push_back(x);
2524 rewriter.setInsertionPoint(op);
2525 rewriter.replaceOpWithNewOp<mlir::LLVM::SwitchOp>(
2526 op, adaptor.getCondition(), op.getDefaultDestination(),
2527 op.getDefaultOperands(), caseValues, caseDestinations, caseOperands);
2528 return mlir::success();
2531static mlir::LLVM::IntegerOverflowFlags
nswFlag(
bool nsw) {
2532 return nsw ? mlir::LLVM::IntegerOverflowFlags::nsw
2533 : mlir::LLVM::IntegerOverflowFlags::none;
2536template <
typename CIROp,
typename LLVMIntOp>
2537static mlir::LogicalResult
2539 mlir::ConversionPatternRewriter &rewriter,
double fpConstant) {
2540 mlir::Type elementType = elementTypeIfVector(op.getType());
2541 mlir::Type llvmType = adaptor.getInput().getType();
2542 mlir::Location loc = op.getLoc();
2544 if (mlir::isa<cir::IntType>(elementType)) {
2545 auto maybeNSW =
nswFlag(op.getNoSignedWrap());
2546 auto one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
2547 rewriter.replaceOpWithNewOp<LLVMIntOp>(op, adaptor.getInput(), one,
2549 return mlir::success();
2551 if (mlir::isa<cir::FPTypeInterface>(elementType)) {
2552 auto fpConst = mlir::LLVM::ConstantOp::create(
2553 rewriter, loc, rewriter.getFloatAttr(llvmType, fpConstant));
2554 rewriter.replaceOpWithNewOp<mlir::LLVM::FAddOp>(op, fpConst,
2555 adaptor.getInput());
2556 return mlir::success();
2558 return op.emitError() <<
"Unsupported type for IncOp/DecOp";
2561mlir::LogicalResult CIRToLLVMIncOpLowering::matchAndRewrite(
2562 cir::IncOp op, OpAdaptor adaptor,
2563 mlir::ConversionPatternRewriter &rewriter)
const {
2568mlir::LogicalResult CIRToLLVMDecOpLowering::matchAndRewrite(
2569 cir::DecOp op, OpAdaptor adaptor,
2570 mlir::ConversionPatternRewriter &rewriter)
const {
2575mlir::LogicalResult CIRToLLVMMinusOpLowering::matchAndRewrite(
2576 cir::MinusOp op, OpAdaptor adaptor,
2577 mlir::ConversionPatternRewriter &rewriter)
const {
2578 mlir::Type elementType = elementTypeIfVector(op.getType());
2579 bool isVector = mlir::isa<cir::VectorType>(op.getType());
2580 mlir::Type llvmType = adaptor.getInput().getType();
2581 mlir::Location loc = op.getLoc();
2583 if (mlir::isa<cir::IntType>(elementType)) {
2584 auto maybeNSW =
nswFlag(op.getNoSignedWrap());
2587 zero = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmType);
2589 zero = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 0);
2590 rewriter.replaceOpWithNewOp<mlir::LLVM::SubOp>(op, zero, adaptor.getInput(),
2592 return mlir::success();
2594 if (mlir::isa<cir::FPTypeInterface>(elementType)) {
2595 rewriter.replaceOpWithNewOp<mlir::LLVM::FNegOp>(op, adaptor.getInput());
2596 return mlir::success();
2598 return op.emitError() <<
"Unsupported type for unary minus";
2601mlir::LogicalResult CIRToLLVMNotOpLowering::matchAndRewrite(
2602 cir::NotOp op, OpAdaptor adaptor,
2603 mlir::ConversionPatternRewriter &rewriter)
const {
2604 mlir::Type elementType = elementTypeIfVector(op.getType());
2605 bool isVector = mlir::isa<cir::VectorType>(op.getType());
2606 mlir::Type llvmType = adaptor.getInput().getType();
2607 mlir::Location loc = op.getLoc();
2609 if (mlir::isa<cir::IntType>(elementType)) {
2610 mlir::Value minusOne;
2613 mlir::dyn_cast<cir::VectorType>(op.getType()).getSize();
2614 SmallVector<int32_t> values(numElements, -1);
2615 mlir::DenseIntElementsAttr denseVec = rewriter.getI32VectorAttr(values);
2617 mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, denseVec);
2619 minusOne = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, -1);
2621 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getInput(),
2623 return mlir::success();
2625 if (mlir::isa<cir::BoolType>(elementType)) {
2626 auto one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
2627 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getInput(), one);
2628 return mlir::success();
2630 return op.emitError() <<
"Unsupported type for bitwise NOT";
2635 return mlir::isa<cir::IntType>(type)
2636 ? mlir::cast<cir::IntType>(type).isUnsigned()
2637 : mlir::cast<mlir::IntegerType>(type).isUnsigned();
2644template <
typename BinOp>
2646 if (op.getNoUnsignedWrap())
2647 return mlir::LLVM::IntegerOverflowFlags::nuw;
2648 if (op.getNoSignedWrap())
2649 return mlir::LLVM::IntegerOverflowFlags::nsw;
2650 return mlir::LLVM::IntegerOverflowFlags::none;
2655template <
typename UIntSatOp,
typename SIntSatOp,
typename IntOp,
typename FPOp,
2657static mlir::LogicalResult
2659 mlir::ConversionPatternRewriter &rewriter) {
2660 const mlir::Type eltType = elementTypeIfVector(op.getRhs().getType());
2661 if (cir::isIntOrBoolType(eltType)) {
2662 if (op.getSaturated()) {
2664 rewriter.replaceOpWithNewOp<UIntSatOp>(op, lhs, rhs);
2666 rewriter.replaceOpWithNewOp<SIntSatOp>(op, lhs, rhs);
2667 return mlir::success();
2669 rewriter.replaceOpWithNewOp<IntOp>(op, lhs, rhs,
intOverflowFlag(op));
2671 rewriter.replaceOpWithNewOp<FPOp>(op, lhs, rhs);
2673 return mlir::success();
2676mlir::LogicalResult CIRToLLVMAddOpLowering::matchAndRewrite(
2677 cir::AddOp op, OpAdaptor adaptor,
2678 mlir::ConversionPatternRewriter &rewriter)
const {
2680 mlir::LLVM::AddOp, mlir::LLVM::FAddOp>(
2681 op, adaptor.getLhs(), adaptor.getRhs(), rewriter);
2684mlir::LogicalResult CIRToLLVMSubOpLowering::matchAndRewrite(
2685 cir::SubOp op, OpAdaptor adaptor,
2686 mlir::ConversionPatternRewriter &rewriter)
const {
2688 mlir::LLVM::SubOp, mlir::LLVM::FSubOp>(
2689 op, adaptor.getLhs(), adaptor.getRhs(), rewriter);
2692mlir::LogicalResult CIRToLLVMMulOpLowering::matchAndRewrite(
2693 cir::MulOp op, OpAdaptor adaptor,
2694 mlir::ConversionPatternRewriter &rewriter)
const {
2695 const mlir::Value lhs = adaptor.getLhs();
2696 const mlir::Value rhs = adaptor.getRhs();
2697 if (cir::isIntOrBoolType(elementTypeIfVector(op.getRhs().getType()))) {
2698 rewriter.replaceOpWithNewOp<mlir::LLVM::MulOp>(op, lhs, rhs,
2701 rewriter.replaceOpWithNewOp<mlir::LLVM::FMulOp>(op, lhs, rhs);
2703 return mlir::success();
2708template <
typename UIntOp,
typename SIntOp,
typename FPOp,
typename CIROp>
2709static mlir::LogicalResult
2711 mlir::ConversionPatternRewriter &rewriter) {
2712 const mlir::Type eltType = elementTypeIfVector(op.getRhs().getType());
2713 if (cir::isIntOrBoolType(eltType)) {
2715 rewriter.replaceOpWithNewOp<UIntOp>(op, lhs, rhs);
2717 rewriter.replaceOpWithNewOp<SIntOp>(op, lhs, rhs);
2719 rewriter.replaceOpWithNewOp<FPOp>(op, lhs, rhs);
2721 return mlir::success();
2724mlir::LogicalResult CIRToLLVMDivOpLowering::matchAndRewrite(
2725 cir::DivOp op, OpAdaptor adaptor,
2726 mlir::ConversionPatternRewriter &rewriter)
const {
2728 mlir::LLVM::FDivOp>(op, adaptor.getLhs(),
2729 adaptor.getRhs(), rewriter);
2732mlir::LogicalResult CIRToLLVMRemOpLowering::matchAndRewrite(
2733 cir::RemOp op, OpAdaptor adaptor,
2734 mlir::ConversionPatternRewriter &rewriter)
const {
2736 mlir::LLVM::FRemOp>(op, adaptor.getLhs(),
2737 adaptor.getRhs(), rewriter);
2740mlir::LogicalResult CIRToLLVMAndOpLowering::matchAndRewrite(
2741 cir::AndOp op, OpAdaptor adaptor,
2742 mlir::ConversionPatternRewriter &rewriter)
const {
2743 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(op, adaptor.getLhs(),
2745 return mlir::success();
2748mlir::LogicalResult CIRToLLVMOrOpLowering::matchAndRewrite(
2749 cir::OrOp op, OpAdaptor adaptor,
2750 mlir::ConversionPatternRewriter &rewriter)
const {
2751 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(op, adaptor.getLhs(),
2753 return mlir::success();
2756mlir::LogicalResult CIRToLLVMXorOpLowering::matchAndRewrite(
2757 cir::XorOp op, OpAdaptor adaptor,
2758 mlir::ConversionPatternRewriter &rewriter)
const {
2759 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getLhs(),
2761 return mlir::success();
2764template <
typename CIROp,
typename UIntOp,
typename SIntOp>
2765static mlir::LogicalResult
2767 mlir::ConversionPatternRewriter &rewriter) {
2768 const mlir::Value lhs = adaptor.getLhs();
2769 const mlir::Value rhs = adaptor.getRhs();
2771 rewriter.replaceOpWithNewOp<UIntOp>(op, lhs, rhs);
2773 rewriter.replaceOpWithNewOp<SIntOp>(op, lhs, rhs);
2774 return mlir::success();
2777mlir::LogicalResult CIRToLLVMMaxOpLowering::matchAndRewrite(
2778 cir::MaxOp op, OpAdaptor adaptor,
2779 mlir::ConversionPatternRewriter &rewriter)
const {
2781 op, adaptor, rewriter);
2784mlir::LogicalResult CIRToLLVMMinOpLowering::matchAndRewrite(
2785 cir::MinOp op, OpAdaptor adaptor,
2786 mlir::ConversionPatternRewriter &rewriter)
const {
2788 op, adaptor, rewriter);
2792static mlir::LLVM::ICmpPredicate
2794 using CIR = cir::CmpOpKind;
2795 using LLVMICmp = mlir::LLVM::ICmpPredicate;
2798 return LLVMICmp::eq;
2800 return LLVMICmp::ne;
2802 return (isSigned ? LLVMICmp::slt : LLVMICmp::ult);
2804 return (isSigned ? LLVMICmp::sle : LLVMICmp::ule);
2806 return (isSigned ? LLVMICmp::sgt : LLVMICmp::ugt);
2808 return (isSigned ? LLVMICmp::sge : LLVMICmp::uge);
2810 llvm_unreachable(
"Unknown CmpOpKind");
2815static mlir::LLVM::FCmpPredicate
2817 using CIR = cir::CmpOpKind;
2818 using LLVMFCmp = mlir::LLVM::FCmpPredicate;
2821 return LLVMFCmp::oeq;
2823 return LLVMFCmp::une;
2825 return LLVMFCmp::olt;
2827 return LLVMFCmp::ole;
2829 return LLVMFCmp::ogt;
2831 return LLVMFCmp::oge;
2833 llvm_unreachable(
"Unknown CmpOpKind");
2836mlir::LogicalResult CIRToLLVMCmpOpLowering::matchAndRewrite(
2837 cir::CmpOp cmpOp, OpAdaptor adaptor,
2838 mlir::ConversionPatternRewriter &rewriter)
const {
2839 mlir::Type type = cmpOp.getLhs().getType();
2841 if (mlir::isa<cir::IntType, mlir::IntegerType>(type)) {
2842 bool isSigned = mlir::isa<cir::IntType>(type)
2843 ? mlir::cast<cir::IntType>(type).isSigned()
2844 : mlir::cast<mlir::IntegerType>(type).isSigned();
2845 mlir::LLVM::ICmpPredicate
kind =
2847 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
2848 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
2849 return mlir::success();
2852 if (
auto ptrTy = mlir::dyn_cast<cir::PointerType>(type)) {
2853 mlir::LLVM::ICmpPredicate
kind =
2856 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
2857 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
2858 return mlir::success();
2861 if (
auto vptrTy = mlir::dyn_cast<cir::VPtrType>(type)) {
2865 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
2866 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
2867 return mlir::success();
2870 if (mlir::isa<cir::FPTypeInterface>(type)) {
2871 mlir::LLVM::FCmpPredicate
kind =
2873 rewriter.replaceOpWithNewOp<mlir::LLVM::FCmpOp>(
2874 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
2875 return mlir::success();
2878 if (mlir::isa<cir::ComplexType>(type)) {
2879 mlir::Value lhs = adaptor.getLhs();
2880 mlir::Value rhs = adaptor.getRhs();
2881 mlir::Location loc = cmpOp.getLoc();
2883 auto complexType = mlir::cast<cir::ComplexType>(cmpOp.getLhs().getType());
2884 mlir::Type complexElemTy =
2885 getTypeConverter()->convertType(
complexType.getElementType());
2887 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
2888 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{0}));
2889 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
2890 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{1}));
2891 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
2892 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{0}));
2893 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
2894 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{1}));
2896 if (cmpOp.getKind() == cir::CmpOpKind::eq) {
2897 if (complexElemTy.isInteger()) {
2898 auto realCmp = mlir::LLVM::ICmpOp::create(
2899 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, lhsReal, rhsReal);
2900 auto imagCmp = mlir::LLVM::ICmpOp::create(
2901 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, lhsImag, rhsImag);
2902 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, imagCmp);
2903 return mlir::success();
2906 auto realCmp = mlir::LLVM::FCmpOp::create(
2907 rewriter, loc, mlir::LLVM::FCmpPredicate::oeq, lhsReal, rhsReal);
2908 auto imagCmp = mlir::LLVM::FCmpOp::create(
2909 rewriter, loc, mlir::LLVM::FCmpPredicate::oeq, lhsImag, rhsImag);
2910 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, imagCmp);
2911 return mlir::success();
2914 if (cmpOp.getKind() == cir::CmpOpKind::ne) {
2915 if (complexElemTy.isInteger()) {
2916 auto realCmp = mlir::LLVM::ICmpOp::create(
2917 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, lhsReal, rhsReal);
2918 auto imagCmp = mlir::LLVM::ICmpOp::create(
2919 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, lhsImag, rhsImag);
2920 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp);
2921 return mlir::success();
2924 auto realCmp = mlir::LLVM::FCmpOp::create(
2925 rewriter, loc, mlir::LLVM::FCmpPredicate::une, lhsReal, rhsReal);
2926 auto imagCmp = mlir::LLVM::FCmpOp::create(
2927 rewriter, loc, mlir::LLVM::FCmpPredicate::une, lhsImag, rhsImag);
2928 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp);
2929 return mlir::success();
2933 return cmpOp.emitError() <<
"unsupported type for CmpOp: " <<
type;
2939template <
typename OpTy>
2940static mlir::LogicalResult
2942 mlir::ConversionPatternRewriter &rewriter,
2943 const mlir::TypeConverter *typeConverter,
2944 llvm::StringRef opStr) {
2945 mlir::Location loc = op.getLoc();
2946 cir::IntType operandTy = op.getLhs().getType();
2947 cir::IntType resultTy = op.getResult().getType();
2949 bool sign = operandTy.getIsSigned() || resultTy.getIsSigned();
2951 std::max(operandTy.getWidth() + (
sign && operandTy.isUnsigned()),
2952 resultTy.getWidth() + (
sign && resultTy.isUnsigned()));
2954 mlir::IntegerType encompassedLLVMTy = rewriter.getIntegerType(width);
2956 mlir::Value lhs = adaptor.getLhs();
2957 mlir::Value rhs = adaptor.getRhs();
2958 if (operandTy.getWidth() < width) {
2959 if (operandTy.isSigned()) {
2960 lhs = mlir::LLVM::SExtOp::create(rewriter, loc, encompassedLLVMTy, lhs);
2961 rhs = mlir::LLVM::SExtOp::create(rewriter, loc, encompassedLLVMTy, rhs);
2963 lhs = mlir::LLVM::ZExtOp::create(rewriter, loc, encompassedLLVMTy, lhs);
2964 rhs = mlir::LLVM::ZExtOp::create(rewriter, loc, encompassedLLVMTy, rhs);
2969 std::string intrinName = (
"llvm." + llvm::Twine(
sign ?
's' :
'u') + opStr +
2970 ".with.overflow.i" + llvm::Twine(width))
2972 auto intrinNameAttr = mlir::StringAttr::get(op.getContext(), intrinName);
2974 mlir::IntegerType overflowLLVMTy = rewriter.getI1Type();
2975 auto intrinRetTy = mlir::LLVM::LLVMStructType::getLiteral(
2976 rewriter.getContext(), {encompassedLLVMTy, overflowLLVMTy});
2978 auto callLLVMIntrinOp = mlir::LLVM::CallIntrinsicOp::create(
2979 rewriter, loc, intrinRetTy, intrinNameAttr, mlir::ValueRange{lhs, rhs});
2980 mlir::Value intrinRet = callLLVMIntrinOp.getResult(0);
2982 mlir::Value result = mlir::LLVM::ExtractValueOp::create(
2985 mlir::Value overflow = mlir::LLVM::ExtractValueOp::create(
2989 if (resultTy.getWidth() < width) {
2990 mlir::Type resultLLVMTy = typeConverter->convertType(resultTy);
2992 mlir::LLVM::TruncOp::create(rewriter, loc, resultLLVMTy, result);
2996 mlir::Value truncResultExt;
2997 if (resultTy.isSigned())
2998 truncResultExt = mlir::LLVM::SExtOp::create(
2999 rewriter, loc, encompassedLLVMTy, truncResult);
3001 truncResultExt = mlir::LLVM::ZExtOp::create(
3002 rewriter, loc, encompassedLLVMTy, truncResult);
3003 auto truncOverflow = mlir::LLVM::ICmpOp::create(
3004 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, truncResultExt, result);
3006 result = truncResult;
3007 overflow = mlir::LLVM::OrOp::create(rewriter, loc, overflow, truncOverflow);
3010 mlir::Type boolLLVMTy =
3011 typeConverter->convertType(op.getOverflow().getType());
3012 if (boolLLVMTy != rewriter.getI1Type())
3013 overflow = mlir::LLVM::ZExtOp::create(rewriter, loc, boolLLVMTy, overflow);
3015 rewriter.replaceOp(op, mlir::ValueRange{result, overflow});
3017 return mlir::success();
3020mlir::LogicalResult CIRToLLVMAddOverflowOpLowering::matchAndRewrite(
3021 cir::AddOverflowOp op, OpAdaptor adaptor,
3022 mlir::ConversionPatternRewriter &rewriter)
const {
3026mlir::LogicalResult CIRToLLVMSubOverflowOpLowering::matchAndRewrite(
3027 cir::SubOverflowOp op, OpAdaptor adaptor,
3028 mlir::ConversionPatternRewriter &rewriter)
const {
3032mlir::LogicalResult CIRToLLVMMulOverflowOpLowering::matchAndRewrite(
3033 cir::MulOverflowOp op, OpAdaptor adaptor,
3034 mlir::ConversionPatternRewriter &rewriter)
const {
3038mlir::LogicalResult CIRToLLVMShiftOpLowering::matchAndRewrite(
3039 cir::ShiftOp op, OpAdaptor adaptor,
3040 mlir::ConversionPatternRewriter &rewriter)
const {
3041 assert((op.getValue().getType() == op.getType()) &&
3042 "inconsistent operands' types NYI");
3044 const mlir::Type llvmTy = getTypeConverter()->convertType(op.getType());
3045 mlir::Value amt = adaptor.getAmount();
3046 mlir::Value val = adaptor.getValue();
3048 auto cirAmtTy = mlir::dyn_cast<cir::IntType>(op.getAmount().getType());
3051 auto cirValTy = mlir::cast<cir::IntType>(op.getValue().getType());
3059 amt =
getLLVMIntCast(rewriter, amt, llvmTy,
true, cirAmtTy.getWidth(),
3060 cirValTy.getWidth());
3062 auto cirValVTy = mlir::cast<cir::VectorType>(op.getValue().getType());
3064 mlir::cast<cir::IntType>(cirValVTy.getElementType()).isUnsigned();
3068 if (op.getIsShiftleft()) {
3069 rewriter.replaceOpWithNewOp<mlir::LLVM::ShlOp>(op, llvmTy, val, amt);
3070 return mlir::success();
3074 rewriter.replaceOpWithNewOp<mlir::LLVM::LShrOp>(op, llvmTy, val, amt);
3076 rewriter.replaceOpWithNewOp<mlir::LLVM::AShrOp>(op, llvmTy, val, amt);
3077 return mlir::success();
3080mlir::LogicalResult CIRToLLVMSelectOpLowering::matchAndRewrite(
3081 cir::SelectOp op, OpAdaptor adaptor,
3082 mlir::ConversionPatternRewriter &rewriter)
const {
3083 auto getConstantBool = [](mlir::Value value) -> cir::BoolAttr {
3084 auto definingOp = value.getDefiningOp<cir::ConstantOp>();
3088 auto constValue = definingOp.getValueAttr<cir::BoolAttr>();
3098 if (mlir::isa<cir::BoolType>(op.getTrueValue().getType())) {
3099 cir::BoolAttr trueValue = getConstantBool(op.getTrueValue());
3100 cir::BoolAttr falseValue = getConstantBool(op.getFalseValue());
3101 if (falseValue && !falseValue.getValue()) {
3103 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(op, adaptor.getCondition(),
3104 adaptor.getTrueValue());
3105 return mlir::success();
3107 if (trueValue && trueValue.getValue()) {
3109 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(op, adaptor.getCondition(),
3110 adaptor.getFalseValue());
3111 return mlir::success();
3115 mlir::Value llvmCondition = adaptor.getCondition();
3116 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(
3117 op, llvmCondition, adaptor.getTrueValue(), adaptor.getFalseValue());
3119 return mlir::success();
3123 mlir::DataLayout &dataLayout) {
3124 converter.addConversion([&](cir::PointerType type) -> mlir::Type {
3125 mlir::ptr::MemorySpaceAttrInterface addrSpaceAttr = type.getAddrSpace();
3126 unsigned numericAS = 0;
3128 if (
auto targetAsAttr =
3129 mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
3131 numericAS = targetAsAttr.getValue();
3132 return mlir::LLVM::LLVMPointerType::get(type.getContext(), numericAS);
3134 converter.addConversion([&](cir::VPtrType type) -> mlir::Type {
3136 return mlir::LLVM::LLVMPointerType::get(type.getContext());
3138 converter.addConversion([&](cir::ArrayType type) -> mlir::Type {
3141 return mlir::LLVM::LLVMArrayType::get(ty, type.getSize());
3143 converter.addConversion([&](cir::VectorType type) -> mlir::Type {
3144 const mlir::Type ty = converter.convertType(type.getElementType());
3145 return mlir::VectorType::get(type.getSize(), ty, {type.getIsScalable()});
3147 converter.addConversion([&](cir::BoolType type) -> mlir::Type {
3148 return mlir::IntegerType::get(type.getContext(), 1,
3149 mlir::IntegerType::Signless);
3151 converter.addConversion([&](cir::IntType type) -> mlir::Type {
3153 return mlir::IntegerType::get(type.getContext(), type.getWidth());
3155 converter.addConversion([&](cir::SingleType type) -> mlir::Type {
3156 return mlir::Float32Type::get(type.getContext());
3158 converter.addConversion([&](cir::DoubleType type) -> mlir::Type {
3159 return mlir::Float64Type::get(type.getContext());
3161 converter.addConversion([&](cir::FP80Type type) -> mlir::Type {
3162 return mlir::Float80Type::get(type.getContext());
3164 converter.addConversion([&](cir::FP128Type type) -> mlir::Type {
3165 return mlir::Float128Type::get(type.getContext());
3167 converter.addConversion([&](cir::LongDoubleType type) -> mlir::Type {
3168 return converter.convertType(type.getUnderlying());
3170 converter.addConversion([&](cir::FP16Type type) -> mlir::Type {
3171 return mlir::Float16Type::get(type.getContext());
3173 converter.addConversion([&](cir::BF16Type type) -> mlir::Type {
3174 return mlir::BFloat16Type::get(type.getContext());
3176 converter.addConversion([&](cir::ComplexType type) -> mlir::Type {
3179 mlir::Type elementTy = converter.convertType(type.getElementType());
3180 mlir::Type structFields[2] = {elementTy, elementTy};
3181 return mlir::LLVM::LLVMStructType::getLiteral(type.getContext(),
3184 converter.addConversion([&](cir::FuncType type) -> std::optional<mlir::Type> {
3185 auto result = converter.convertType(type.getReturnType());
3187 arguments.reserve(type.getNumInputs());
3188 if (converter.convertTypes(type.getInputs(), arguments).failed())
3189 return std::nullopt;
3190 auto varArg = type.isVarArg();
3191 return mlir::LLVM::LLVMFunctionType::get(result, arguments, varArg);
3193 converter.addConversion([&](cir::RecordType type) -> mlir::Type {
3196 switch (type.getKind()) {
3197 case cir::RecordType::Class:
3198 case cir::RecordType::Struct:
3199 for (mlir::Type ty : type.getMembers())
3203 case cir::RecordType::Union:
3204 if (type.getMembers().empty())
3206 if (
auto largestMember = type.getLargestMember(dataLayout))
3207 llvmMembers.push_back(
3209 if (type.getPadded()) {
3210 auto last = *type.getMembers().rbegin();
3211 llvmMembers.push_back(
3218 mlir::LLVM::LLVMStructType llvmStruct;
3219 if (type.getName()) {
3220 llvmStruct = mlir::LLVM::LLVMStructType::getIdentified(
3221 type.getContext(), type.getPrefixedName());
3222 if (llvmStruct.setBody(llvmMembers, type.getPacked()).failed())
3223 llvm_unreachable(
"Failed to set body of record");
3225 llvmStruct = mlir::LLVM::LLVMStructType::getLiteral(
3226 type.getContext(), llvmMembers, type.getPacked());
3231 converter.addConversion([&](cir::VoidType type) -> mlir::Type {
3232 return mlir::LLVM::LLVMVoidType::get(type.getContext());
3237 mlir::ModuleOp module, StringRef globalXtorName, StringRef llvmXtorName,
3238 llvm::function_ref<std::pair<StringRef, int>(mlir::Attribute)> createXtor) {
3240 for (
const mlir::NamedAttribute namedAttr : module->getAttrs()) {
3241 if (namedAttr.getName() == globalXtorName) {
3242 for (
auto attr : mlir::cast<mlir::ArrayAttr>(namedAttr.getValue()))
3243 globalXtors.emplace_back(createXtor(attr));
3248 if (globalXtors.empty())
3251 mlir::OpBuilder builder(module.getContext());
3252 builder.setInsertionPointToEnd(&module.getBodyRegion().back());
3256 auto ctorPFTy = mlir::LLVM::LLVMPointerType::get(builder.getContext());
3258 ctorStructFields.push_back(builder.getI32Type());
3259 ctorStructFields.push_back(ctorPFTy);
3260 ctorStructFields.push_back(ctorPFTy);
3262 auto ctorStructTy = mlir::LLVM::LLVMStructType::getLiteral(
3263 builder.getContext(), ctorStructFields);
3264 auto ctorStructArrayTy =
3265 mlir::LLVM::LLVMArrayType::get(ctorStructTy, globalXtors.size());
3267 mlir::Location loc =
module.getLoc();
3268 auto newGlobalOp = mlir::LLVM::GlobalOp::create(
3269 builder, loc, ctorStructArrayTy,
false,
3270 mlir::LLVM::Linkage::Appending, llvmXtorName, mlir::Attribute());
3272 builder.createBlock(&newGlobalOp.getRegion());
3273 builder.setInsertionPointToEnd(newGlobalOp.getInitializerBlock());
3275 mlir::Value result =
3276 mlir::LLVM::UndefOp::create(builder, loc, ctorStructArrayTy);
3278 for (
auto [index, fn] : llvm::enumerate(globalXtors)) {
3279 mlir::Value structInit =
3280 mlir::LLVM::UndefOp::create(builder, loc, ctorStructTy);
3281 mlir::Value initPriority = mlir::LLVM::ConstantOp::create(
3282 builder, loc, ctorStructFields[0], fn.second);
3283 mlir::Value initFuncAddr = mlir::LLVM::AddressOfOp::create(
3284 builder, loc, ctorStructFields[1], fn.first);
3285 mlir::Value initAssociate =
3286 mlir::LLVM::ZeroOp::create(builder, loc, ctorStructFields[2]);
3289 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
3290 initPriority, zero);
3291 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
3294 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
3296 result = mlir::LLVM::InsertValueOp::create(builder, loc, result, structInit,
3300 mlir::LLVM::ReturnOp::create(builder, loc, result);
3338 parent->walk([&](mlir::Block *blk) {
3339 if (blk->hasNoPredecessors() && !blk->isEntryBlock())
3340 unreachableBlocks.push_back(blk);
3343 std::set<mlir::Block *> visited;
3344 for (mlir::Block *root : unreachableBlocks) {
3347 std::deque<mlir::Block *> workList;
3348 workList.push_back(root);
3350 while (!workList.empty()) {
3351 mlir::Block *blk = workList.back();
3352 workList.pop_back();
3353 if (visited.count(blk))
3355 visited.emplace(blk);
3357 for (mlir::Operation &op : *blk)
3360 for (mlir::Block *succ : blk->getSuccessors())
3361 workList.push_back(succ);
3366mlir::LogicalResult CIRToLLVMObjSizeOpLowering::matchAndRewrite(
3367 cir::ObjSizeOp op, OpAdaptor adaptor,
3368 mlir::ConversionPatternRewriter &rewriter)
const {
3369 mlir::Type llvmResTy = getTypeConverter()->convertType(op.getType());
3370 mlir::Location loc = op->getLoc();
3372 mlir::IntegerType i1Ty = rewriter.getI1Type();
3374 auto i1Val = [&rewriter, &loc, &i1Ty](
bool val) {
3375 return mlir::LLVM::ConstantOp::create(rewriter, loc, i1Ty, val);
3382 i1Val(op.getNullunknown()),
3383 i1Val(op.getDynamic()),
3386 return mlir::LogicalResult::success();
3392 mlir::ModuleOp module = getOperation();
3393 mlir::OpBuilder opBuilder(module.getContext());
3394 for (
auto &[blockAddOp, blockInfo] :
3396 mlir::LLVM::BlockTagOp resolvedLabel =
3398 assert(resolvedLabel &&
"expected BlockTagOp to already be emitted");
3399 mlir::FlatSymbolRefAttr fnSym = blockInfo.getFunc();
3400 auto blkAddTag = mlir::LLVM::BlockAddressAttr::get(
3401 opBuilder.getContext(), fnSym, resolvedLabel.getTagAttr());
3402 blockAddOp.setBlockAddrAttr(blkAddTag);
3409 if (mlir::Attribute tripleAttr =
3410 module->getAttr(cir::CIRDialect::getTripleAttrName()))
3411 module->setAttr(mlir::LLVM::LLVMDialect::getTargetTripleAttrName(),
3414 if (mlir::Attribute asmAttr =
3415 module->getAttr(cir::CIRDialect::getModuleLevelAsmAttrName()))
3416 module->setAttr(mlir::LLVM::LLVMDialect::getModuleLevelAsmAttrName(),
3421 llvm::TimeTraceScope scope(
"Convert CIR to LLVM Pass");
3423 mlir::ModuleOp module = getOperation();
3424 mlir::DataLayout dl(module);
3425 mlir::LLVMTypeConverter converter(&getContext());
3433 mlir::RewritePatternSet patterns(&getContext());
3434 patterns.add<CIRToLLVMBlockAddressOpLowering, CIRToLLVMLabelOpLowering>(
3435 converter, patterns.getContext(), dl, blockInfoAddr);
3438#define GET_LLVM_LOWERING_PATTERNS_LIST
3439#include "clang/CIR/Dialect/IR/CIRLowering.inc"
3440#undef GET_LLVM_LOWERING_PATTERNS_LIST
3441 >(converter, patterns.getContext(), dl);
3445 mlir::ConversionTarget target(getContext());
3446 target.addLegalOp<mlir::ModuleOp>();
3447 target.addLegalDialect<mlir::LLVM::LLVMDialect>();
3448 mlir::configureOpenMPToLLVMConversionLegality(target, converter);
3449 target.addLegalDialect<mlir::omp::OpenMPDialect>();
3450 mlir::populateOpenMPToLLVMConversionPatterns(converter, patterns);
3451 target.addIllegalDialect<mlir::BuiltinDialect, cir::CIRDialect,
3452 mlir::func::FuncDialect>();
3455 ops.push_back(module);
3458 if (failed(applyPartialConversion(ops, target, std::move(patterns))))
3459 signalPassFailure();
3463 "llvm.global_ctors", [](mlir::Attribute
attr) {
3464 auto ctorAttr = mlir::cast<cir::GlobalCtorAttr>(
attr);
3465 return std::make_pair(ctorAttr.getName(),
3466 ctorAttr.getPriority());
3470 "llvm.global_dtors", [](mlir::Attribute
attr) {
3471 auto dtorAttr = mlir::cast<cir::GlobalDtorAttr>(
attr);
3472 return std::make_pair(dtorAttr.getName(),
3473 dtorAttr.getPriority());
3478mlir::LogicalResult CIRToLLVMBrOpLowering::matchAndRewrite(
3479 cir::BrOp op, OpAdaptor adaptor,
3480 mlir::ConversionPatternRewriter &rewriter)
const {
3481 rewriter.replaceOpWithNewOp<mlir::LLVM::BrOp>(op, adaptor.getOperands(),
3483 return mlir::LogicalResult::success();
3486mlir::LogicalResult CIRToLLVMGetMemberOpLowering::matchAndRewrite(
3487 cir::GetMemberOp op, OpAdaptor adaptor,
3488 mlir::ConversionPatternRewriter &rewriter)
const {
3489 mlir::Type llResTy = getTypeConverter()->convertType(op.getType());
3490 const auto recordTy =
3491 mlir::cast<cir::RecordType>(op.getAddrTy().getPointee());
3492 assert(recordTy &&
"expected record type");
3494 switch (recordTy.getKind()) {
3495 case cir::RecordType::Class:
3496 case cir::RecordType::Struct: {
3500 const mlir::Type elementTy = getTypeConverter()->convertType(recordTy);
3501 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, llResTy, elementTy,
3502 adaptor.getAddr(), offset);
3503 return mlir::success();
3505 case cir::RecordType::Union:
3508 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(op, llResTy,
3510 return mlir::success();
3514mlir::LogicalResult CIRToLLVMExtractMemberOpLowering::matchAndRewrite(
3515 cir::ExtractMemberOp op, OpAdaptor adaptor,
3516 mlir::ConversionPatternRewriter &rewriter)
const {
3517 std::int64_t indices[1] = {
static_cast<std::int64_t
>(op.getIndex())};
3519 mlir::Type recordTy = op.getRecord().getType();
3520 auto cirRecordTy = mlir::cast<cir::RecordType>(recordTy);
3521 switch (cirRecordTy.getKind()) {
3522 case cir::RecordType::Struct:
3523 case cir::RecordType::Class:
3524 rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractValueOp>(
3525 op, adaptor.getRecord(), indices);
3526 return mlir::success();
3528 case cir::RecordType::Union:
3529 op.emitError(
"cir.extract_member cannot extract member from a union");
3530 return mlir::failure();
3532 llvm_unreachable(
"Unexpected record kind");
3535mlir::LogicalResult CIRToLLVMInsertMemberOpLowering::matchAndRewrite(
3536 cir::InsertMemberOp op, OpAdaptor adaptor,
3537 mlir::ConversionPatternRewriter &rewriter)
const {
3538 std::int64_t indecies[1] = {
static_cast<std::int64_t
>(op.getIndex())};
3539 mlir::Type recordTy = op.getRecord().getType();
3541 if (
auto cirRecordTy = mlir::dyn_cast<cir::RecordType>(recordTy)) {
3542 if (cirRecordTy.getKind() == cir::RecordType::Union) {
3543 op.emitError(
"cir.update_member cannot update member of a union");
3544 return mlir::failure();
3548 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
3549 op, adaptor.getRecord(), adaptor.getValue(), indecies);
3550 return mlir::success();
3553mlir::LogicalResult CIRToLLVMUnreachableOpLowering::matchAndRewrite(
3554 cir::UnreachableOp op, OpAdaptor adaptor,
3555 mlir::ConversionPatternRewriter &rewriter)
const {
3556 rewriter.replaceOpWithNewOp<mlir::LLVM::UnreachableOp>(op);
3557 return mlir::success();
3561 mlir::Operation *srcOp, llvm::StringRef fnName,
3563 mlir::ArrayAttr argAttrs =
nullptr,
3564 mlir::ArrayAttr resAttrs =
nullptr) {
3565 mlir::ModuleOp modOp = srcOp->getParentOfType<mlir::ModuleOp>();
3566 mlir::Operation *sourceSymbol =
3567 mlir::SymbolTable::lookupSymbolIn(modOp, fnName);
3568 if (!sourceSymbol) {
3569 mlir::OpBuilder::InsertionGuard guard(rewriter);
3570 auto enclosingFnOp = srcOp->getParentOfType<mlir::LLVM::LLVMFuncOp>();
3571 rewriter.setInsertionPoint(enclosingFnOp);
3573 mlir::LLVM::LLVMFuncOp::create(rewriter, srcOp->getLoc(), fnName, fnTy);
3575 fn.setArgAttrsAttr(argAttrs);
3577 fn.setResAttrsAttr(resAttrs);
3581mlir::LogicalResult CIRToLLVMThrowOpLowering::matchAndRewrite(
3582 cir::ThrowOp op, OpAdaptor adaptor,
3583 mlir::ConversionPatternRewriter &rewriter)
const {
3584 mlir::Location loc = op.getLoc();
3585 auto voidTy = mlir::LLVM::LLVMVoidType::get(getContext());
3587 if (op.rethrows()) {
3588 auto funcTy = mlir::LLVM::LLVMFunctionType::get(voidTy, {});
3591 const llvm::StringRef functionName =
"__cxa_rethrow";
3594 auto cxaRethrow = mlir::LLVM::CallOp::create(
3595 rewriter, loc, mlir::TypeRange{}, functionName);
3597 rewriter.replaceOp(op, cxaRethrow);
3598 return mlir::success();
3601 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3602 auto fnTy = mlir::LLVM::LLVMFunctionType::get(
3603 voidTy, {llvmPtrTy, llvmPtrTy, llvmPtrTy});
3606 const llvm::StringRef fnName =
"__cxa_throw";
3609 mlir::Value typeInfo = mlir::LLVM::AddressOfOp::create(
3610 rewriter, loc, mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
3611 adaptor.getTypeInfoAttr());
3615 dtor = mlir::LLVM::AddressOfOp::create(rewriter, loc, llvmPtrTy,
3616 adaptor.getDtorAttr());
3618 dtor = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmPtrTy);
3621 auto cxaThrowCall = mlir::LLVM::CallOp::create(
3622 rewriter, loc, mlir::TypeRange{}, fnName,
3623 mlir::ValueRange{adaptor.getExceptionPtr(), typeInfo, dtor});
3625 rewriter.replaceOp(op, cxaThrowCall);
3626 return mlir::success();
3629mlir::LogicalResult CIRToLLVMAllocExceptionOpLowering::matchAndRewrite(
3630 cir::AllocExceptionOp op, OpAdaptor adaptor,
3631 mlir::ConversionPatternRewriter &rewriter)
const {
3633 StringRef fnName =
"__cxa_allocate_exception";
3634 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3635 auto int64Ty = mlir::IntegerType::get(rewriter.getContext(), 64);
3636 auto fnTy = mlir::LLVM::LLVMFunctionType::get(llvmPtrTy, {int64Ty});
3639 auto exceptionSize = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
3640 adaptor.getSizeAttr());
3642 auto allocaExceptionCall = mlir::LLVM::CallOp::create(
3643 rewriter, op.getLoc(), mlir::TypeRange{llvmPtrTy}, fnName,
3644 mlir::ValueRange{exceptionSize});
3646 rewriter.replaceOp(op, allocaExceptionCall);
3647 return mlir::success();
3650static mlir::LLVM::LLVMStructType
3653 mlir::MLIRContext *ctx = rewriter.getContext();
3654 auto llvmPtr = mlir::LLVM::LLVMPointerType::get(ctx);
3656 return mlir::LLVM::LLVMStructType::getLiteral(ctx, structFields);
3659mlir::LogicalResult CIRToLLVMEhInflightOpLowering::matchAndRewrite(
3660 cir::EhInflightOp op, OpAdaptor adaptor,
3661 mlir::ConversionPatternRewriter &rewriter)
const {
3662 auto llvmFn = op->getParentOfType<mlir::LLVM::LLVMFuncOp>();
3663 assert(llvmFn &&
"expected LLVM function parent");
3664 mlir::Block *entryBlock = &llvmFn.getRegion().front();
3665 assert(entryBlock->isEntryBlock());
3667 mlir::ArrayAttr catchListAttr = op.getCatchTypeListAttr();
3668 mlir::SmallVector<mlir::Value> catchSymAddrs;
3670 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3671 mlir::Location loc = op.getLoc();
3676 if (catchListAttr) {
3679 for (mlir::Attribute catchAttr : catchListAttr) {
3680 auto symAttr = cast<mlir::FlatSymbolRefAttr>(catchAttr);
3683 mlir::OpBuilder::InsertionGuard guard(rewriter);
3684 rewriter.setInsertionPointToStart(entryBlock);
3685 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
3686 rewriter, loc, llvmPtrTy, symAttr.getValue());
3687 catchSymAddrs.push_back(addrOp);
3694 if (op.getCatchAll() || (!catchListAttr && !op.getCleanup())) {
3695 mlir::OpBuilder::InsertionGuard guard(rewriter);
3696 rewriter.setInsertionPointToStart(entryBlock);
3697 mlir::Value nullOp = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmPtrTy);
3698 catchSymAddrs.push_back(nullOp);
3703 mlir::LLVM::LLVMStructType llvmLandingPadStructTy =
3705 auto landingPadOp = mlir::LLVM::LandingpadOp::create(
3706 rewriter, loc, llvmLandingPadStructTy, catchSymAddrs);
3711 if (op.getCleanup() && !op.getCatchAll())
3712 landingPadOp.setCleanup(
true);
3715 mlir::LLVM::ExtractValueOp::create(rewriter, loc, landingPadOp, 0);
3716 mlir::Value selector =
3717 mlir::LLVM::ExtractValueOp::create(rewriter, loc, landingPadOp, 1);
3718 rewriter.replaceOp(op, mlir::ValueRange{slot, selector});
3720 return mlir::success();
3723mlir::LogicalResult CIRToLLVMResumeFlatOpLowering::matchAndRewrite(
3724 cir::ResumeFlatOp op, OpAdaptor adaptor,
3725 mlir::ConversionPatternRewriter &rewriter)
const {
3730 mlir::Value poison = mlir::LLVM::PoisonOp::create(rewriter, op.getLoc(),
3731 llvmLandingPadStructTy);
3733 SmallVector<int64_t> slotIdx = {0};
3734 mlir::Value slot = mlir::LLVM::InsertValueOp::create(
3735 rewriter, op.getLoc(), poison, adaptor.getExceptionPtr(), slotIdx);
3737 SmallVector<int64_t> selectorIdx = {1};
3738 mlir::Value selector = mlir::LLVM::InsertValueOp::create(
3739 rewriter, op.getLoc(), slot, adaptor.getTypeId(), selectorIdx);
3741 rewriter.replaceOpWithNewOp<mlir::LLVM::ResumeOp>(op, selector);
3742 return mlir::success();
3745mlir::LogicalResult CIRToLLVMEhTypeIdOpLowering::matchAndRewrite(
3746 cir::EhTypeIdOp op, OpAdaptor adaptor,
3747 mlir::ConversionPatternRewriter &rewriter)
const {
3748 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
3749 rewriter, op.getLoc(),
3750 mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
3751 op.getTypeSymAttr());
3752 rewriter.replaceOpWithNewOp<mlir::LLVM::EhTypeidForOp>(
3753 op, rewriter.getI32Type(), addrOp);
3754 return mlir::success();
3757mlir::LogicalResult CIRToLLVMEhSetjmpOpLowering::matchAndRewrite(
3758 cir::EhSetjmpOp op, OpAdaptor adaptor,
3759 mlir::ConversionPatternRewriter &rewriter)
const {
3760 mlir::Type returnType = typeConverter->convertType(op.getType());
3761 mlir::LLVM::CallIntrinsicOp newOp =
3763 returnType, adaptor.getEnv());
3764 rewriter.replaceOp(op, newOp);
3765 return mlir::success();
3768mlir::LogicalResult CIRToLLVMEhLongjmpOpLowering::matchAndRewrite(
3769 cir::EhLongjmpOp op, OpAdaptor adaptor,
3770 mlir::ConversionPatternRewriter &rewriter)
const {
3772 {}, adaptor.getOperands());
3773 return mlir::success();
3776mlir::LogicalResult CIRToLLVMTrapOpLowering::matchAndRewrite(
3777 cir::TrapOp op, OpAdaptor adaptor,
3778 mlir::ConversionPatternRewriter &rewriter)
const {
3779 mlir::Location loc = op->getLoc();
3780 rewriter.eraseOp(op);
3782 mlir::LLVM::Trap::create(rewriter, loc);
3787 mlir::LLVM::UnreachableOp::create(rewriter, loc);
3789 return mlir::success();
3794 mlir::ConversionPatternRewriter &rewriter,
3795 const mlir::TypeConverter *converter,
3796 mlir::FlatSymbolRefAttr nameAttr, mlir::Type &eltType) {
3797 auto module = op->getParentOfType<mlir::ModuleOp>();
3798 mlir::Operation *symbol = mlir::SymbolTable::lookupSymbolIn(module, nameAttr);
3799 if (
auto llvmSymbol = mlir::dyn_cast<mlir::LLVM::GlobalOp>(symbol)) {
3800 eltType = llvmSymbol.getType();
3801 }
else if (
auto cirSymbol = mlir::dyn_cast<cir::GlobalOp>(symbol)) {
3802 eltType = converter->convertType(cirSymbol.getSymType());
3804 op->emitError() <<
"unexpected symbol type for " << symbol;
3808 return mlir::LLVM::AddressOfOp::create(
3809 rewriter, op->getLoc(),
3810 mlir::LLVM::LLVMPointerType::get(op->getContext()), nameAttr.getValue());
3813mlir::LogicalResult CIRToLLVMVTableAddrPointOpLowering::matchAndRewrite(
3814 cir::VTableAddrPointOp op, OpAdaptor adaptor,
3815 mlir::ConversionPatternRewriter &rewriter)
const {
3816 const mlir::TypeConverter *converter = getTypeConverter();
3817 mlir::Type targetType = converter->convertType(op.getType());
3821 op.getNameAttr(), eltType);
3823 return op.emitError() <<
"Unable to get value for vtable symbol";
3826 0, op.getAddressPointAttr().getIndex(),
3827 op.getAddressPointAttr().getOffset()};
3829 assert(eltType &&
"Shouldn't ever be missing an eltType here");
3830 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
3831 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
3832 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, targetType, eltType,
3833 symAddr, offsets, inboundsNuw);
3834 return mlir::success();
3837mlir::LogicalResult CIRToLLVMVTableGetVPtrOpLowering::matchAndRewrite(
3838 cir::VTableGetVPtrOp op, OpAdaptor adaptor,
3839 mlir::ConversionPatternRewriter &rewriter)
const {
3843 mlir::Value srcVal = adaptor.getSrc();
3844 rewriter.replaceOp(op, srcVal);
3845 return mlir::success();
3848mlir::LogicalResult CIRToLLVMVTableGetVirtualFnAddrOpLowering::matchAndRewrite(
3849 cir::VTableGetVirtualFnAddrOp op, OpAdaptor adaptor,
3850 mlir::ConversionPatternRewriter &rewriter)
const {
3851 mlir::Type targetType = getTypeConverter()->convertType(op.getType());
3852 auto eltType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3853 llvm::SmallVector<mlir::LLVM::GEPArg> offsets =
3854 llvm::SmallVector<mlir::LLVM::GEPArg>{op.getIndex()};
3855 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
3856 op, targetType, eltType, adaptor.getVptr(), offsets,
3857 mlir::LLVM::GEPNoWrapFlags::inbounds);
3858 return mlir::success();
3861mlir::LogicalResult CIRToLLVMVTTAddrPointOpLowering::matchAndRewrite(
3862 cir::VTTAddrPointOp op, OpAdaptor adaptor,
3863 mlir::ConversionPatternRewriter &rewriter)
const {
3864 const mlir::Type resultType = getTypeConverter()->convertType(op.getType());
3865 llvm::SmallVector<mlir::LLVM::GEPArg> offsets;
3867 mlir::Value llvmAddr = adaptor.getSymAddr();
3869 if (op.getSymAddr()) {
3870 if (op.getOffset() == 0) {
3871 rewriter.replaceOp(op, {llvmAddr});
3872 return mlir::success();
3875 offsets.push_back(adaptor.getOffset());
3876 eltType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3879 op.getNameAttr(), eltType);
3880 assert(eltType &&
"Shouldn't ever be missing an eltType here");
3881 offsets.push_back(0);
3882 offsets.push_back(adaptor.getOffset());
3884 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
3885 op, resultType, eltType, llvmAddr, offsets,
3886 mlir::LLVM::GEPNoWrapFlags::inbounds);
3887 return mlir::success();
3890mlir::LogicalResult CIRToLLVMStackSaveOpLowering::matchAndRewrite(
3891 cir::StackSaveOp op, OpAdaptor adaptor,
3892 mlir::ConversionPatternRewriter &rewriter)
const {
3893 const mlir::Type ptrTy = getTypeConverter()->convertType(op.getType());
3894 rewriter.replaceOpWithNewOp<mlir::LLVM::StackSaveOp>(op, ptrTy);
3895 return mlir::success();
3898mlir::LogicalResult CIRToLLVMStackRestoreOpLowering::matchAndRewrite(
3899 cir::StackRestoreOp op, OpAdaptor adaptor,
3900 mlir::ConversionPatternRewriter &rewriter)
const {
3901 rewriter.replaceOpWithNewOp<mlir::LLVM::StackRestoreOp>(op, adaptor.getPtr());
3902 return mlir::success();
3905mlir::LogicalResult CIRToLLVMVecCreateOpLowering::matchAndRewrite(
3906 cir::VecCreateOp op, OpAdaptor adaptor,
3907 mlir::ConversionPatternRewriter &rewriter)
const {
3910 const auto vecTy = mlir::cast<cir::VectorType>(op.getType());
3911 const mlir::Type llvmTy = typeConverter->convertType(vecTy);
3912 const mlir::Location loc = op.getLoc();
3913 mlir::Value result = mlir::LLVM::PoisonOp::create(rewriter, loc, llvmTy);
3914 assert(vecTy.getSize() == op.getElements().size() &&
3915 "cir.vec.create op count doesn't match vector type elements count");
3917 for (uint64_t i = 0; i < vecTy.getSize(); ++i) {
3918 const mlir::Value indexValue =
3919 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
3920 result = mlir::LLVM::InsertElementOp::create(
3921 rewriter, loc, result, adaptor.getElements()[i], indexValue);
3924 rewriter.replaceOp(op, result);
3925 return mlir::success();
3928mlir::LogicalResult CIRToLLVMVecExtractOpLowering::matchAndRewrite(
3929 cir::VecExtractOp op, OpAdaptor adaptor,
3930 mlir::ConversionPatternRewriter &rewriter)
const {
3931 rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractElementOp>(
3932 op, adaptor.getVec(), adaptor.getIndex());
3933 return mlir::success();
3936mlir::LogicalResult CIRToLLVMVecInsertOpLowering::matchAndRewrite(
3937 cir::VecInsertOp op, OpAdaptor adaptor,
3938 mlir::ConversionPatternRewriter &rewriter)
const {
3939 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertElementOp>(
3940 op, adaptor.getVec(), adaptor.getValue(), adaptor.getIndex());
3941 return mlir::success();
3944mlir::LogicalResult CIRToLLVMVecCmpOpLowering::matchAndRewrite(
3945 cir::VecCmpOp op, OpAdaptor adaptor,
3946 mlir::ConversionPatternRewriter &rewriter)
const {
3947 mlir::Type elementType = elementTypeIfVector(op.getLhs().getType());
3948 mlir::Value bitResult;
3949 if (
auto intType = mlir::dyn_cast<cir::IntType>(elementType)) {
3950 bitResult = mlir::LLVM::ICmpOp::create(
3951 rewriter, op.getLoc(),
3953 adaptor.getLhs(), adaptor.getRhs());
3954 }
else if (mlir::isa<cir::FPTypeInterface>(elementType)) {
3955 bitResult = mlir::LLVM::FCmpOp::create(
3957 adaptor.getLhs(), adaptor.getRhs());
3959 return op.emitError() <<
"unsupported type for VecCmpOp: " << elementType;
3965 if (cast<cir::IntType>(cast<cir::VectorType>(op.getType()).getElementType())
3967 rewriter.replaceOpWithNewOp<mlir::LLVM::SExtOp>(
3968 op, typeConverter->convertType(op.getType()), bitResult);
3970 rewriter.replaceOp(op, bitResult);
3971 return mlir::success();
3974mlir::LogicalResult CIRToLLVMVecSplatOpLowering::matchAndRewrite(
3975 cir::VecSplatOp op, OpAdaptor adaptor,
3976 mlir::ConversionPatternRewriter &rewriter)
const {
3982 cir::VectorType vecTy = op.getType();
3983 mlir::Type llvmTy = typeConverter->convertType(vecTy);
3984 mlir::Location loc = op.getLoc();
3985 mlir::Value poison = mlir::LLVM::PoisonOp::create(rewriter, loc, llvmTy);
3987 mlir::Value elementValue = adaptor.getValue();
3988 if (elementValue.getDefiningOp<mlir::LLVM::PoisonOp>()) {
3991 rewriter.replaceOp(op, poison);
3992 return mlir::success();
3995 if (
auto constValue = elementValue.getDefiningOp<mlir::LLVM::ConstantOp>()) {
3996 if (
auto intAttr = dyn_cast<mlir::IntegerAttr>(constValue.getValue())) {
3997 mlir::DenseIntElementsAttr denseVec = mlir::DenseIntElementsAttr::get(
3998 mlir::cast<mlir::ShapedType>(llvmTy), intAttr.getValue());
3999 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
4000 op, denseVec.getType(), denseVec);
4001 return mlir::success();
4004 if (
auto fpAttr = dyn_cast<mlir::FloatAttr>(constValue.getValue())) {
4005 mlir::DenseFPElementsAttr denseVec = mlir::DenseFPElementsAttr::get(
4006 mlir::cast<mlir::ShapedType>(llvmTy), fpAttr.getValue());
4007 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
4008 op, denseVec.getType(), denseVec);
4009 return mlir::success();
4013 mlir::Value indexValue =
4014 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), 0);
4015 mlir::Value oneElement = mlir::LLVM::InsertElementOp::create(
4016 rewriter, loc, poison, elementValue, indexValue);
4017 SmallVector<int32_t> zeroValues(vecTy.getSize(), 0);
4018 rewriter.replaceOpWithNewOp<mlir::LLVM::ShuffleVectorOp>(op, oneElement,
4019 poison, zeroValues);
4020 return mlir::success();
4023mlir::LogicalResult CIRToLLVMVecShuffleOpLowering::matchAndRewrite(
4024 cir::VecShuffleOp op, OpAdaptor adaptor,
4025 mlir::ConversionPatternRewriter &rewriter)
const {
4029 SmallVector<int, 8> indices;
4031 op.getIndices().begin(), op.getIndices().end(),
4032 std::back_inserter(indices), [](mlir::Attribute intAttr) {
4033 return mlir::cast<cir::IntAttr>(intAttr).getValue().getSExtValue();
4035 rewriter.replaceOpWithNewOp<mlir::LLVM::ShuffleVectorOp>(
4036 op, adaptor.getVec1(), adaptor.getVec2(), indices);
4037 return mlir::success();
4040mlir::LogicalResult CIRToLLVMVecShuffleDynamicOpLowering::matchAndRewrite(
4041 cir::VecShuffleDynamicOp op, OpAdaptor adaptor,
4042 mlir::ConversionPatternRewriter &rewriter)
const {
4054 mlir::Location loc = op.getLoc();
4055 mlir::Value input = adaptor.getVec();
4056 mlir::Type llvmIndexVecType =
4057 getTypeConverter()->convertType(op.getIndices().getType());
4058 mlir::Type llvmIndexType = getTypeConverter()->convertType(
4059 elementTypeIfVector(op.getIndices().getType()));
4061 mlir::cast<cir::VectorType>(op.getVec().getType()).getSize();
4063 uint64_t maskBits = llvm::NextPowerOf2(numElements - 1) - 1;
4064 mlir::Value maskValue = mlir::LLVM::ConstantOp::create(
4065 rewriter, loc, llvmIndexType,
4066 rewriter.getIntegerAttr(llvmIndexType, maskBits));
4067 mlir::Value maskVector =
4068 mlir::LLVM::UndefOp::create(rewriter, loc, llvmIndexVecType);
4070 for (uint64_t i = 0; i < numElements; ++i) {
4071 mlir::Value idxValue =
4072 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
4073 maskVector = mlir::LLVM::InsertElementOp::create(rewriter, loc, maskVector,
4074 maskValue, idxValue);
4077 mlir::Value maskedIndices = mlir::LLVM::AndOp::create(
4078 rewriter, loc, llvmIndexVecType, adaptor.getIndices(), maskVector);
4079 mlir::Value result = mlir::LLVM::UndefOp::create(
4080 rewriter, loc, getTypeConverter()->convertType(op.getVec().getType()));
4081 for (uint64_t i = 0; i < numElements; ++i) {
4082 mlir::Value iValue =
4083 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
4084 mlir::Value indexValue = mlir::LLVM::ExtractElementOp::create(
4085 rewriter, loc, maskedIndices, iValue);
4086 mlir::Value valueAtIndex =
4087 mlir::LLVM::ExtractElementOp::create(rewriter, loc, input, indexValue);
4088 result = mlir::LLVM::InsertElementOp::create(rewriter, loc, result,
4089 valueAtIndex, iValue);
4091 rewriter.replaceOp(op, result);
4092 return mlir::success();
4095mlir::LogicalResult CIRToLLVMVecTernaryOpLowering::matchAndRewrite(
4096 cir::VecTernaryOp op, OpAdaptor adaptor,
4097 mlir::ConversionPatternRewriter &rewriter)
const {
4099 mlir::Value bitVec = mlir::LLVM::ICmpOp::create(
4100 rewriter, op.getLoc(), mlir::LLVM::ICmpPredicate::ne, adaptor.getCond(),
4101 mlir::LLVM::ZeroOp::create(
4102 rewriter, op.getCond().getLoc(),
4103 typeConverter->convertType(op.getCond().getType())));
4104 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(
4105 op, bitVec, adaptor.getLhs(), adaptor.getRhs());
4106 return mlir::success();
4109mlir::LogicalResult CIRToLLVMComplexAddOpLowering::matchAndRewrite(
4110 cir::ComplexAddOp op, OpAdaptor adaptor,
4111 mlir::ConversionPatternRewriter &rewriter)
const {
4112 mlir::Value lhs = adaptor.getLhs();
4113 mlir::Value rhs = adaptor.getRhs();
4114 mlir::Location loc = op.getLoc();
4116 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
4117 mlir::Type complexElemTy =
4118 getTypeConverter()->convertType(
complexType.getElementType());
4119 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
4120 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{0}));
4121 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
4122 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{1}));
4123 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
4124 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{0}));
4125 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
4126 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{1}));
4128 mlir::Value newReal;
4129 mlir::Value newImag;
4130 if (complexElemTy.isInteger()) {
4131 newReal = mlir::LLVM::AddOp::create(rewriter, loc, complexElemTy, lhsReal,
4133 newImag = mlir::LLVM::AddOp::create(rewriter, loc, complexElemTy, lhsImag,
4138 newReal = mlir::LLVM::FAddOp::create(rewriter, loc, complexElemTy, lhsReal,
4140 newImag = mlir::LLVM::FAddOp::create(rewriter, loc, complexElemTy, lhsImag,
4144 mlir::Type complexLLVMTy =
4145 getTypeConverter()->convertType(op.getResult().getType());
4146 auto initialComplex =
4147 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), complexLLVMTy);
4149 auto realComplex = mlir::LLVM::InsertValueOp::create(
4150 rewriter, op->getLoc(), initialComplex, newReal, ArrayRef(int64_t{0}));
4152 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
4153 op, realComplex, newImag, ArrayRef(int64_t{1}));
4155 return mlir::success();
4158mlir::LogicalResult CIRToLLVMComplexCreateOpLowering::matchAndRewrite(
4159 cir::ComplexCreateOp op, OpAdaptor adaptor,
4160 mlir::ConversionPatternRewriter &rewriter)
const {
4161 mlir::Type complexLLVMTy =
4162 getTypeConverter()->convertType(op.getResult().getType());
4163 auto initialComplex =
4164 mlir::LLVM::UndefOp::create(rewriter, op->getLoc(), complexLLVMTy);
4166 auto realComplex = mlir::LLVM::InsertValueOp::create(
4167 rewriter, op->getLoc(), initialComplex, adaptor.getReal(),
4168 ArrayRef(int64_t{0}));
4170 auto complex = mlir::LLVM::InsertValueOp::create(
4171 rewriter, op->getLoc(), realComplex, adaptor.getImag(),
4172 ArrayRef(int64_t{1}));
4174 rewriter.replaceOp(op, complex);
4175 return mlir::success();
4178mlir::LogicalResult CIRToLLVMComplexRealOpLowering::matchAndRewrite(
4179 cir::ComplexRealOp op, OpAdaptor adaptor,
4180 mlir::ConversionPatternRewriter &rewriter)
const {
4181 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
4182 mlir::Value operand = adaptor.getOperand();
4183 if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) {
4184 operand = mlir::LLVM::ExtractValueOp::create(
4185 rewriter, op.getLoc(), resultLLVMTy, operand,
4186 llvm::ArrayRef<std::int64_t>{0});
4188 rewriter.replaceOp(op, operand);
4189 return mlir::success();
4192mlir::LogicalResult CIRToLLVMComplexSubOpLowering::matchAndRewrite(
4193 cir::ComplexSubOp op, OpAdaptor adaptor,
4194 mlir::ConversionPatternRewriter &rewriter)
const {
4195 mlir::Value lhs = adaptor.getLhs();
4196 mlir::Value rhs = adaptor.getRhs();
4197 mlir::Location loc = op.getLoc();
4199 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
4200 mlir::Type complexElemTy =
4201 getTypeConverter()->convertType(
complexType.getElementType());
4202 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
4203 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{0}));
4204 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
4205 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{1}));
4206 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
4207 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{0}));
4208 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
4209 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{1}));
4211 mlir::Value newReal;
4212 mlir::Value newImag;
4213 if (complexElemTy.isInteger()) {
4214 newReal = mlir::LLVM::SubOp::create(rewriter, loc, complexElemTy, lhsReal,
4216 newImag = mlir::LLVM::SubOp::create(rewriter, loc, complexElemTy, lhsImag,
4221 newReal = mlir::LLVM::FSubOp::create(rewriter, loc, complexElemTy, lhsReal,
4223 newImag = mlir::LLVM::FSubOp::create(rewriter, loc, complexElemTy, lhsImag,
4227 mlir::Type complexLLVMTy =
4228 getTypeConverter()->convertType(op.getResult().getType());
4229 auto initialComplex =
4230 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), complexLLVMTy);
4232 auto realComplex = mlir::LLVM::InsertValueOp::create(
4233 rewriter, op->getLoc(), initialComplex, newReal, ArrayRef(int64_t{0}));
4235 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
4236 op, realComplex, newImag, ArrayRef(int64_t{1}));
4238 return mlir::success();
4241mlir::LogicalResult CIRToLLVMComplexImagOpLowering::matchAndRewrite(
4242 cir::ComplexImagOp op, OpAdaptor adaptor,
4243 mlir::ConversionPatternRewriter &rewriter)
const {
4244 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
4245 mlir::Value operand = adaptor.getOperand();
4246 mlir::Location loc = op.getLoc();
4248 if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) {
4249 operand = mlir::LLVM::ExtractValueOp::create(
4250 rewriter, loc, resultLLVMTy, operand, llvm::ArrayRef<std::int64_t>{1});
4252 mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(resultLLVMTy);
4254 mlir::LLVM::ConstantOp::create(rewriter, loc, resultLLVMTy, zeroAttr);
4257 rewriter.replaceOp(op, operand);
4258 return mlir::success();
4262 mlir::MLIRContext *context,
4263 unsigned &storageSize) {
4264 return TypeSwitch<mlir::Type, mlir::IntegerType>(storageType)
4265 .Case<cir::ArrayType>([&](cir::ArrayType atTy) {
4266 storageSize = atTy.getSize() * 8;
4267 return mlir::IntegerType::get(context, storageSize);
4269 .Case<cir::IntType>([&](cir::IntType intTy) {
4270 storageSize = intTy.getWidth();
4271 return mlir::IntegerType::get(context, storageSize);
4273 .Default([](mlir::Type) -> mlir::IntegerType {
4275 "Either ArrayType or IntType expected for bitfields storage");
4279mlir::LogicalResult CIRToLLVMSetBitfieldOpLowering::matchAndRewrite(
4280 cir::SetBitfieldOp op, OpAdaptor adaptor,
4281 mlir::ConversionPatternRewriter &rewriter)
const {
4282 mlir::OpBuilder::InsertionGuard guard(rewriter);
4283 rewriter.setInsertionPoint(op);
4285 cir::BitfieldInfoAttr info = op.getBitfieldInfo();
4286 uint64_t size = info.getSize();
4287 uint64_t offset = info.getOffset();
4288 mlir::Type storageType = info.getStorageType();
4289 mlir::MLIRContext *context = storageType.getContext();
4291 unsigned storageSize = 0;
4293 mlir::IntegerType intType =
4296 mlir::Value srcVal =
createIntCast(rewriter, adaptor.getSrc(), intType);
4297 unsigned srcWidth = storageSize;
4298 mlir::Value resultVal = srcVal;
4300 if (storageSize != size) {
4301 assert(storageSize > size &&
"Invalid bitfield size.");
4303 mlir::Value val = mlir::LLVM::LoadOp::create(
4304 rewriter, op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(),
4305 op.getIsVolatile());
4308 createAnd(rewriter, srcVal, llvm::APInt::getLowBitsSet(srcWidth, size));
4310 srcVal =
createShL(rewriter, srcVal, offset);
4314 ~llvm::APInt::getBitsSet(srcWidth, offset, offset + size));
4317 srcVal = mlir::LLVM::OrOp::create(rewriter, op.getLoc(), val, srcVal);
4320 mlir::LLVM::StoreOp::create(rewriter, op.getLoc(), srcVal, adaptor.getAddr(),
4321 op.getAlignment(), op.getIsVolatile());
4323 mlir::Type resultTy = getTypeConverter()->convertType(op.getType());
4325 if (info.getIsSigned()) {
4326 assert(size <= storageSize);
4327 unsigned highBits = storageSize - size;
4330 resultVal =
createShL(rewriter, resultVal, highBits);
4331 resultVal =
createAShR(rewriter, resultVal, highBits);
4336 mlir::cast<mlir::IntegerType>(resultTy),
4337 info.getIsSigned());
4339 rewriter.replaceOp(op, resultVal);
4340 return mlir::success();
4343mlir::LogicalResult CIRToLLVMComplexImagPtrOpLowering::matchAndRewrite(
4344 cir::ComplexImagPtrOp op, OpAdaptor adaptor,
4345 mlir::ConversionPatternRewriter &rewriter)
const {
4346 cir::PointerType operandTy = op.getOperand().getType();
4347 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
4348 mlir::Type elementLLVMTy =
4349 getTypeConverter()->convertType(operandTy.getPointee());
4351 mlir::LLVM::GEPArg gepIndices[2] = {{0}, {1}};
4352 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
4353 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
4354 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
4355 op, resultLLVMTy, elementLLVMTy, adaptor.getOperand(), gepIndices,
4357 return mlir::success();
4360mlir::LogicalResult CIRToLLVMComplexRealPtrOpLowering::matchAndRewrite(
4361 cir::ComplexRealPtrOp op, OpAdaptor adaptor,
4362 mlir::ConversionPatternRewriter &rewriter)
const {
4363 cir::PointerType operandTy = op.getOperand().getType();
4364 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
4365 mlir::Type elementLLVMTy =
4366 getTypeConverter()->convertType(operandTy.getPointee());
4368 mlir::LLVM::GEPArg gepIndices[2] = {0, 0};
4369 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
4370 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
4371 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
4372 op, resultLLVMTy, elementLLVMTy, adaptor.getOperand(), gepIndices,
4374 return mlir::success();
4377mlir::LogicalResult CIRToLLVMGetBitfieldOpLowering::matchAndRewrite(
4378 cir::GetBitfieldOp op, OpAdaptor adaptor,
4379 mlir::ConversionPatternRewriter &rewriter)
const {
4381 mlir::OpBuilder::InsertionGuard guard(rewriter);
4382 rewriter.setInsertionPoint(op);
4384 cir::BitfieldInfoAttr info = op.getBitfieldInfo();
4386 uint64_t offset = info.getOffset();
4387 mlir::Type storageType = info.getStorageType();
4388 mlir::MLIRContext *context = storageType.getContext();
4389 unsigned storageSize = 0;
4391 mlir::IntegerType intType =
4394 mlir::Value val = mlir::LLVM::LoadOp::create(
4395 rewriter, op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(),
4396 op.getIsVolatile());
4397 val = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), intType, val);
4399 if (info.getIsSigned()) {
4400 assert(
static_cast<unsigned>(offset + size) <= storageSize);
4401 unsigned highBits = storageSize - offset - size;
4402 val =
createShL(rewriter, val, highBits);
4403 val =
createAShR(rewriter, val, offset + highBits);
4407 if (
static_cast<unsigned>(offset) + size < storageSize)
4409 llvm::APInt::getLowBitsSet(storageSize, size));
4412 mlir::Type resTy = getTypeConverter()->convertType(op.getType());
4414 rewriter, val, mlir::cast<mlir::IntegerType>(resTy), info.getIsSigned());
4415 rewriter.replaceOp(op, newOp);
4416 return mlir::success();
4419mlir::LogicalResult CIRToLLVMIsConstantOpLowering::matchAndRewrite(
4420 cir::IsConstantOp op, OpAdaptor adaptor,
4421 mlir::ConversionPatternRewriter &rewriter)
const {
4422 rewriter.replaceOpWithNewOp<mlir::LLVM::IsConstantOp>(op, adaptor.getVal());
4423 return mlir::success();
4426mlir::LogicalResult CIRToLLVMInlineAsmOpLowering::matchAndRewrite(
4427 cir::InlineAsmOp op, OpAdaptor adaptor,
4428 mlir::ConversionPatternRewriter &rewriter)
const {
4430 if (op.getNumResults())
4431 llResTy = getTypeConverter()->convertType(op.getType(0));
4433 cir::AsmFlavor dialect = op.getAsmFlavor();
4434 mlir::LLVM::AsmDialect llDialect = dialect == cir::AsmFlavor::x86_att
4435 ? mlir::LLVM::AsmDialect::AD_ATT
4436 : mlir::LLVM::AsmDialect::AD_Intel;
4438 SmallVector<mlir::Attribute> opAttrs;
4439 StringRef llvmAttrName = mlir::LLVM::InlineAsmOp::getElementTypeAttrName();
4445 if (!op.getNumResults())
4446 opAttrs.push_back(mlir::Attribute());
4448 SmallVector<mlir::Value> llvmOperands;
4449 SmallVector<mlir::Value> cirOperands;
4450 for (
auto const &[llvmOp, cirOp] :
4451 zip(adaptor.getAsmOperands(), op.getAsmOperands())) {
4452 append_range(llvmOperands, llvmOp);
4453 append_range(cirOperands, cirOp);
4458 for (
auto const &[cirOpAttr, cirOp] :
4459 zip(op.getOperandAttrs(), cirOperands)) {
4460 if (!mlir::isa<mlir::UnitAttr>(cirOpAttr)) {
4461 opAttrs.push_back(mlir::Attribute());
4465 llvm::SmallVector<mlir::NamedAttribute, 1> attrs;
4466 cir::PointerType typ = mlir::cast<cir::PointerType>(cirOp.getType());
4468 *getTypeConverter(), dataLayout, typ.getPointee()));
4470 attrs.push_back(rewriter.getNamedAttr(llvmAttrName, typAttr));
4471 mlir::DictionaryAttr newDict = rewriter.getDictionaryAttr(attrs);
4472 opAttrs.push_back(newDict);
4475 rewriter.replaceOpWithNewOp<mlir::LLVM::InlineAsmOp>(
4476 op, llResTy, llvmOperands, op.getAsmStringAttr(), op.getConstraintsAttr(),
4477 op.getSideEffectsAttr(),
4480 mlir::LLVM::TailCallKindAttr::get(
4481 getContext(), mlir::LLVM::tailcallkind::TailCallKind::None),
4482 mlir::LLVM::AsmDialectAttr::get(getContext(), llDialect),
4483 rewriter.getArrayAttr(opAttrs));
4485 return mlir::success();
4488mlir::LogicalResult CIRToLLVMVAStartOpLowering::matchAndRewrite(
4489 cir::VAStartOp op, OpAdaptor adaptor,
4490 mlir::ConversionPatternRewriter &rewriter)
const {
4491 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4492 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4493 adaptor.getArgList());
4494 rewriter.replaceOpWithNewOp<mlir::LLVM::VaStartOp>(op, vaList);
4495 return mlir::success();
4498mlir::LogicalResult CIRToLLVMVAEndOpLowering::matchAndRewrite(
4499 cir::VAEndOp op, OpAdaptor adaptor,
4500 mlir::ConversionPatternRewriter &rewriter)
const {
4501 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4502 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4503 adaptor.getArgList());
4504 rewriter.replaceOpWithNewOp<mlir::LLVM::VaEndOp>(op, vaList);
4505 return mlir::success();
4508mlir::LogicalResult CIRToLLVMVACopyOpLowering::matchAndRewrite(
4509 cir::VACopyOp op, OpAdaptor adaptor,
4510 mlir::ConversionPatternRewriter &rewriter)
const {
4511 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4512 auto dstList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4513 adaptor.getDstList());
4514 auto srcList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4515 adaptor.getSrcList());
4516 rewriter.replaceOpWithNewOp<mlir::LLVM::VaCopyOp>(op, dstList, srcList);
4517 return mlir::success();
4520mlir::LogicalResult CIRToLLVMVAArgOpLowering::matchAndRewrite(
4521 cir::VAArgOp op, OpAdaptor adaptor,
4522 mlir::ConversionPatternRewriter &rewriter)
const {
4524 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4525 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4526 adaptor.getArgList());
4528 mlir::Type llvmType =
4529 getTypeConverter()->convertType(op->getResultTypes().front());
4531 return mlir::failure();
4533 rewriter.replaceOpWithNewOp<mlir::LLVM::VaArgOp>(op, llvmType, vaList);
4534 return mlir::success();
4537mlir::LogicalResult CIRToLLVMLabelOpLowering::matchAndRewrite(
4538 cir::LabelOp op, OpAdaptor adaptor,
4539 mlir::ConversionPatternRewriter &rewriter)
const {
4540 mlir::MLIRContext *ctx = rewriter.getContext();
4541 mlir::Block *block = op->getBlock();
4544 if (block->isEntryBlock()) {
4545 mlir::Block *newBlock =
4546 rewriter.splitBlock(op->getBlock(), mlir::Block::iterator(op));
4547 rewriter.setInsertionPointToEnd(block);
4548 mlir::LLVM::BrOp::create(rewriter, op.getLoc(), newBlock);
4551 mlir::LLVM::BlockTagAttr::get(ctx, blockInfoAddr.getTagIndex());
4552 rewriter.setInsertionPoint(op);
4555 mlir::LLVM::BlockTagOp::create(rewriter, op->getLoc(), tagAttr);
4556 mlir::LLVM::LLVMFuncOp func = op->getParentOfType<mlir::LLVM::LLVMFuncOp>();
4557 auto blockInfoAttr =
4558 cir::BlockAddrInfoAttr::get(ctx, func.getSymName(), op.getLabel());
4559 blockInfoAddr.mapBlockTag(blockInfoAttr, blockTagOp);
4560 rewriter.eraseOp(op);
4562 return mlir::success();
4565mlir::LogicalResult CIRToLLVMBlockAddressOpLowering::matchAndRewrite(
4566 cir::BlockAddressOp op, OpAdaptor adaptor,
4567 mlir::ConversionPatternRewriter &rewriter)
const {
4568 mlir::MLIRContext *ctx = rewriter.getContext();
4570 mlir::LLVM::BlockTagOp matchLabel =
4571 blockInfoAddr.lookupBlockTag(op.getBlockAddrInfoAttr());
4572 mlir::LLVM::BlockTagAttr tagAttr;
4579 tagAttr = matchLabel.getTag();
4581 auto blkAddr = mlir::LLVM::BlockAddressAttr::get(
4582 rewriter.getContext(), op.getBlockAddrInfoAttr().getFunc(), tagAttr);
4583 rewriter.setInsertionPoint(op);
4584 auto newOp = mlir::LLVM::BlockAddressOp::create(
4585 rewriter, op.getLoc(), mlir::LLVM::LLVMPointerType::get(ctx), blkAddr);
4587 blockInfoAddr.addUnresolvedBlockAddress(newOp, op.getBlockAddrInfoAttr());
4588 rewriter.replaceOp(op, newOp);
4589 return mlir::success();
4592mlir::LogicalResult CIRToLLVMIndirectBrOpLowering::matchAndRewrite(
4593 cir::IndirectBrOp op, OpAdaptor adaptor,
4594 mlir::ConversionPatternRewriter &rewriter)
const {
4596 mlir::Value targetAddr = adaptor.getAddr();
4604 if (op.getPoison()) {
4605 auto llvmPtrType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4607 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), llvmPtrType);
4610 rewriter.replaceOpWithNewOp<mlir::LLVM::IndirectBrOp>(
4611 op, targetAddr, adaptor.getSuccOperands(), op.getSuccessors());
4612 return mlir::success();
4615mlir::LogicalResult CIRToLLVMAwaitOpLowering::matchAndRewrite(
4616 cir::AwaitOp op, OpAdaptor adaptor,
4617 mlir::ConversionPatternRewriter &rewriter)
const {
4618 return mlir::failure();
4621mlir::LogicalResult CIRToLLVMCpuIdOpLowering::matchAndRewrite(
4622 cir::CpuIdOp op, OpAdaptor adaptor,
4623 mlir::ConversionPatternRewriter &rewriter)
const {
4624 mlir::Type i32Ty = rewriter.getI32Type();
4625 mlir::Type i64Ty = rewriter.getI64Type();
4626 mlir::Type i32PtrTy = mlir::LLVM::LLVMPointerType::get(i32Ty.getContext(), 0);
4628 mlir::Type cpuidRetTy = mlir::LLVM::LLVMStructType::getLiteral(
4629 rewriter.getContext(), {i32Ty, i32Ty, i32Ty, i32Ty});
4631 mlir::Value functionId = adaptor.getFunctionId();
4632 mlir::Value subFunctionId = adaptor.getSubFunctionId();
4634 StringRef asmString, constraints;
4635 mlir::ModuleOp moduleOp = op->getParentOfType<mlir::ModuleOp>();
4636 llvm::Triple triple(
4637 mlir::cast<mlir::StringAttr>(
4638 moduleOp->getAttr(cir::CIRDialect::getTripleAttrName()))
4640 if (triple.getArch() == llvm::Triple::x86) {
4641 asmString =
"cpuid";
4642 constraints =
"={ax},={bx},={cx},={dx},{ax},{cx}";
4645 asmString =
"xchgq %rbx, ${1:q}\n"
4647 "xchgq %rbx, ${1:q}";
4648 constraints =
"={ax},=r,={cx},={dx},0,2";
4651 mlir::Value inlineAsm =
4652 mlir::LLVM::InlineAsmOp::create(
4653 rewriter, op.getLoc(), cpuidRetTy, {functionId, subFunctionId},
4654 rewriter.getStringAttr(asmString),
4655 rewriter.getStringAttr(constraints),
4658 mlir::LLVM::TailCallKindAttr{},
4659 mlir::LLVM::AsmDialectAttr{},
4663 mlir::Value basePtr = adaptor.getCpuInfo();
4665 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
4666 unsigned alignment = layout.getTypeABIAlignment(i32Ty);
4667 for (
unsigned i = 0; i < 4; i++) {
4668 mlir::Value extracted =
4669 mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(), inlineAsm, i)
4671 mlir::Value index = mlir::LLVM::ConstantOp::create(
4672 rewriter, op.getLoc(), i64Ty, rewriter.getI64IntegerAttr(i));
4673 llvm::SmallVector<mlir::Value, 1> gepIndices = {index};
4674 mlir::Value storePtr = mlir::LLVM::GEPOp::create(
4675 rewriter, op.getLoc(), i32PtrTy, i32Ty, basePtr,
4676 gepIndices, mlir::LLVM::GEPNoWrapFlags::none)
4678 mlir::LLVM::StoreOp::create(rewriter, op.getLoc(), extracted, storePtr,
4682 rewriter.eraseOp(op);
4683 return mlir::success();
4686mlir::LogicalResult CIRToLLVMMemChrOpLowering::matchAndRewrite(
4687 cir::MemChrOp op, OpAdaptor adaptor,
4688 mlir::ConversionPatternRewriter &rewriter)
const {
4689 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4690 mlir::Type srcTy = getTypeConverter()->convertType(op.getSrc().getType());
4691 mlir::Type patternTy =
4692 getTypeConverter()->convertType(op.getPattern().getType());
4693 mlir::Type lenTy = getTypeConverter()->convertType(op.getLen().getType());
4695 mlir::LLVM::LLVMFunctionType::get(llvmPtrTy, {srcTy, patternTy, lenTy},
4697 llvm::StringRef fnName =
"memchr";
4699 mlir::Builder
b(rewriter.getContext());
4700 mlir::NamedAttribute noundefAttr =
4701 b.getNamedAttr(
"llvm.noundef",
b.getUnitAttr());
4702 mlir::DictionaryAttr noundefDict = mlir::DictionaryAttr::get(
4703 rewriter.getContext(), llvm::ArrayRef(noundefAttr));
4704 SmallVector<mlir::Attribute> argAttrVec(3, noundefDict);
4705 mlir::ArrayAttr argAttrs =
4706 mlir::ArrayAttr::get(rewriter.getContext(), argAttrVec);
4710 mlir::LLVM::CallOp newCall = rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(
4711 op, mlir::TypeRange{llvmPtrTy}, fnName,
4712 mlir::ValueRange{adaptor.getSrc(), adaptor.getPattern(),
4714 newCall.setArgAttrsAttr(argAttrs);
4715 return mlir::success();
4719 return std::make_unique<ConvertCIRToLLVMPass>();
4724 pm.addPass(mlir::omp::createMarkDeclareTargetPass());
4728std::unique_ptr<llvm::Module>
4730 StringRef mlirSaveTempsOutFile) {
4731 llvm::TimeTraceScope scope(
"lower from CIR to LLVM directly");
4733 mlir::MLIRContext *mlirCtx = mlirModule.getContext();
4735 mlir::PassManager pm(mlirCtx);
4738 (void)mlir::applyPassManagerCLOptions(pm);
4740 if (mlir::failed(pm.run(mlirModule))) {
4743 "The pass manager failed to lower CIR to LLVMIR dialect!");
4746 if (!mlirSaveTempsOutFile.empty()) {
4748 llvm::raw_fd_ostream out(mlirSaveTempsOutFile, ec);
4750 mlirModule->print(out);
4753 mlir::registerBuiltinDialectTranslation(*mlirCtx);
4754 mlir::registerLLVMDialectTranslation(*mlirCtx);
4755 mlir::registerOpenMPDialectTranslation(*mlirCtx);
4758 llvm::TimeTraceScope translateScope(
"translateModuleToLLVMIR");
4760 StringRef moduleName = mlirModule.getName().value_or(
"CIRToLLVMModule");
4761 std::unique_ptr<llvm::Module> llvmModule =
4762 mlir::translateModuleToLLVMIR(mlirModule, llvmCtx, moduleName);
4766 report_fatal_error(
"Lowering from LLVMIR dialect to llvm IR failed!");
static bool isUnsigned(SValBuilder &SVB, NonLoc Value)
static llvm::StringRef getLinkageAttrNameString()
Returns the name used for the linkage attribute.
mlir::Value createLShR(mlir::OpBuilder &bld, mlir::Value lhs, unsigned rhs)
mlir::Value createShL(mlir::OpBuilder &bld, mlir::Value lhs, unsigned rhs)
std::optional< mlir::Attribute > lowerConstArrayAttr(cir::ConstArrayAttr constArr, const mlir::TypeConverter *converter)
mlir::Value createAShR(mlir::OpBuilder &bld, mlir::Value lhs, unsigned rhs)
mlir::Value createAnd(mlir::OpBuilder &bld, mlir::Value lhs, const llvm::APInt &rhs)
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
static bool isVector(QualType QT, QualType ElementType)
This helper function returns true if QT is a vector type that has element type ElementType.
__DEVICE__ void * memset(void *__a, int __b, size_t __c)
CIRAttrToValue(mlir::Operation *parentOp, mlir::ConversionPatternRewriter &rewriter, const mlir::TypeConverter *converter)
mlir::Attribute visit(mlir::Attribute attr)
mlir::Attribute visitCirAttr(cir::FPAttr attr)
mlir::Attribute visitCirAttr(cir::BoolAttr attr)
GlobalInitAttrRewriter(mlir::Type type, mlir::ConversionPatternRewriter &rewriter)
mlir::Attribute visitCirAttr(cir::IntAttr attr)
static void collectUnreachable(mlir::Operation *parent, llvm::SmallVector< mlir::Operation * > &ops)
static mlir::LLVM::AtomicBinOp getLLVMAtomicBinOp(cir::AtomicFetchKind k, bool isInt, bool isSignedInt)
static mlir::LLVM::ICmpPredicate convertCmpKindToICmpPredicate(cir::CmpOpKind kind, bool isSigned)
Convert from a CIR comparison kind to an LLVM IR integral comparison kind.
void convertSideEffectForCall(mlir::Operation *callOp, bool isNothrow, cir::SideEffect sideEffect, mlir::LLVM::MemoryEffectsAttr &memoryEffect, bool &noUnwind, bool &willReturn, bool &noReturn)
static mlir::LogicalResult lowerIncDecOp(CIROp op, typename CIROp::Adaptor adaptor, mlir::ConversionPatternRewriter &rewriter, double fpConstant)
static mlir::LLVM::IntegerOverflowFlags intOverflowFlag(BinOp op)
static mlir::LogicalResult lowerIntFPBinaryOp(CIROp op, mlir::Value lhs, mlir::Value rhs, mlir::ConversionPatternRewriter &rewriter)
Lower a binary op that maps to unsigned/signed/FP LLVM ops depending on operand type.
std::unique_ptr< llvm::Module > lowerDirectlyFromCIRToLLVMIR(mlir::ModuleOp mlirModule, llvm::LLVMContext &llvmCtx, llvm::StringRef mlirSaveTempsOutFile={})
void createLLVMFuncOpIfNotExist(mlir::ConversionPatternRewriter &rewriter, mlir::Operation *srcOp, llvm::StringRef fnName, mlir::Type fnTy, mlir::ArrayAttr argAttrs=nullptr, mlir::ArrayAttr resAttrs=nullptr)
static mlir::Value getLLVMIntCast(mlir::ConversionPatternRewriter &rewriter, mlir::Value llvmSrc, mlir::Type llvmDstIntTy, bool isUnsigned, uint64_t cirSrcWidth, uint64_t cirDstIntWidth)
static mlir::Value emitFromMemory(mlir::ConversionPatternRewriter &rewriter, mlir::DataLayout const &dataLayout, cir::LoadOp op, mlir::Value value)
Emits the value from memory as expected by its users.
mlir::IntegerType computeBitfieldIntType(mlir::Type storageType, mlir::MLIRContext *context, unsigned &storageSize)
static mlir::LLVM::CallIntrinsicOp createCallLLVMIntrinsicOp(mlir::ConversionPatternRewriter &rewriter, mlir::Location loc, const llvm::Twine &intrinsicName, mlir::Type resultTy, mlir::ValueRange operands)
bool hasTrailingZeros(cir::ConstArrayAttr attr)
static mlir::LogicalResult lowerMinMaxOp(CIROp op, typename CIROp::Adaptor adaptor, mlir::ConversionPatternRewriter &rewriter)
static mlir::LLVM::LLVMStructType getLLVMLandingPadStructTy(mlir::ConversionPatternRewriter &rewriter)
mlir::Value lowerCirAttrAsValue(mlir::Operation *parentOp, const mlir::Attribute attr, mlir::ConversionPatternRewriter &rewriter, const mlir::TypeConverter *converter)
Switches on the type of attribute and calls the appropriate conversion.
static mlir::Value convertToIndexTy(mlir::ConversionPatternRewriter &rewriter, mlir::ModuleOp mod, mlir::Value index, mlir::Type baseTy, cir::IntType strideTy)
static mlir::LogicalResult lowerSaturatableArithOp(CIROp op, mlir::Value lhs, mlir::Value rhs, mlir::ConversionPatternRewriter &rewriter)
Lower an arithmetic op that supports saturation, overflow flags, and an FP variant.
static mlir::LLVM::CallIntrinsicOp replaceOpWithCallLLVMIntrinsicOp(mlir::ConversionPatternRewriter &rewriter, mlir::Operation *op, const llvm::Twine &intrinsicName, mlir::Type resultTy, mlir::ValueRange operands)
static void prepareTypeConverter(mlir::LLVMTypeConverter &converter, mlir::DataLayout &dataLayout)
static mlir::LLVM::AtomicOrdering getLLVMMemOrder(std::optional< cir::MemOrder > memorder)
std::unique_ptr< mlir::Pass > createConvertCIRToLLVMPass()
Create a pass that fully lowers CIR to the LLVMIR dialect.
static llvm::StringRef getLLVMSyncScope(cir::SyncScopeKind syncScope)
static mlir::LLVM::FCmpPredicate convertCmpKindToFCmpPredicate(cir::CmpOpKind kind)
Convert from a CIR comparison kind to an LLVM IR floating-point comparison kind.
static mlir::LLVM::Visibility lowerCIRVisibilityToLLVMVisibility(cir::VisibilityKind visibilityKind)
static void lowerCallAttributes(cir::CIRCallOpInterface op, SmallVectorImpl< mlir::NamedAttribute > &result)
static uint64_t getTypeSize(mlir::Type type, mlir::Operation &op)
void populateCIRToLLVMPasses(mlir::OpPassManager &pm)
Adds passes that fully lower CIR to the LLVMIR dialect.
static llvm::StringLiteral getLLVMBinopForPostAtomic(cir::AtomicFetchKind k, bool isInt)
mlir::LLVM::Linkage convertLinkage(cir::GlobalLinkageKind linkage)
static void buildCtorDtorList(mlir::ModuleOp module, StringRef globalXtorName, StringRef llvmXtorName, llvm::function_ref< std::pair< StringRef, int >(mlir::Attribute)> createXtor)
static mlir::LogicalResult lowerBinOpOverflow(OpTy op, typename OpTy::Adaptor adaptor, mlir::ConversionPatternRewriter &rewriter, const mlir::TypeConverter *typeConverter, llvm::StringRef opStr)
Shared lowering logic for checked binary arithmetic overflow operations.
static mlir::Type convertTypeForMemory(const mlir::TypeConverter &converter, mlir::DataLayout const &dataLayout, mlir::Type type)
Given a type convertor and a data layout, convert the given type to a type that is suitable for memor...
static mlir::Value createIntCast(mlir::OpBuilder &bld, mlir::Value src, mlir::IntegerType dstTy, bool isSigned=false)
static mlir::LLVM::IntegerOverflowFlags nswFlag(bool nsw)
static mlir::Value getValueForVTableSymbol(mlir::Operation *op, mlir::ConversionPatternRewriter &rewriter, const mlir::TypeConverter *converter, mlir::FlatSymbolRefAttr nameAttr, mlir::Type &eltType)
static mlir::Value emitToMemory(mlir::ConversionPatternRewriter &rewriter, mlir::DataLayout const &dataLayout, mlir::Type origType, mlir::Value value)
Emits a value to memory with the expected scalar type.
static mlir::LogicalResult rewriteCallOrInvoke(mlir::Operation *op, mlir::ValueRange callOperands, mlir::ConversionPatternRewriter &rewriter, const mlir::TypeConverter *converter, mlir::FlatSymbolRefAttr calleeAttr, mlir::Block *continueBlock=nullptr, mlir::Block *landingPadBlock=nullptr)
static bool isIntTypeUnsigned(mlir::Type type)
const internal::VariadicAllOfMatcher< Attr > attr
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const AstTypeMatcher< ComplexType > complexType
Diagnostic wrappers for TextAPI types for error reporting.
void populateCIRPreLoweringPasses(mlir::OpPassManager &pm)
void registerCIRDialectTranslation(mlir::MLIRContext &context)
char __ovld __cnfn clz(char)
Returns the number of leading 0-bits in x, starting at the most significant bit position.
char __ovld __cnfn ctz(char)
Returns the count of trailing 0-bits in x.
float __ovld __cnfn sign(float)
Returns 1.0 if x > 0, -0.0 if x = -0.0, +0.0 if x = +0.0, or -1.0 if x < 0.
float __ovld __cnfn length(float)
Return the length of vector p, i.e., sqrt(p.x2 + p.y 2 + ...)
char __ovld __cnfn select(char, char, char)
For each component of a vector type, result[i] = if MSB of c[i] is set ?
static bool dataMemberType()
static bool addressSpace()
static bool globalViewIntLowering()
static bool opAllocaAnnotations()
static bool opLoadStoreTbaa()
static bool optInfoAttr()
static bool opFuncExtraAttrs()
static bool isPPC_FP128Ty()
static bool vaArgABILowering()
static bool fpConstraints()
static bool intrinsicElementTypeSupport()
static bool lowerModeOptLevel()
static bool opCallCallConv()
static bool opFuncCallingConv()
static bool aggValueSlotVolatile()
static bool fastMathFlags()
static bool llvmLoweringPtrDiffConsidersPointee()
static bool opLoadStoreNontemporal()
static bool atomicSyncScopeID()
static bool opFuncMultipleReturnVals()
void runOnOperation() final
StringRef getDescription() const override
StringRef getArgument() const override
void getDependentDialects(mlir::DialectRegistry ®istry) const override
void resolveBlockAddressOp(LLVMBlockAddressInfo &blockInfoAddr)
void processCIRAttrs(mlir::ModuleOp module)
mlir::LLVM::BlockTagOp lookupBlockTag(cir::BlockAddrInfoAttr info) const
void clearUnresolvedMap()
llvm::DenseMap< mlir::LLVM::BlockAddressOp, cir::BlockAddrInfoAttr > & getUnresolvedBlockAddress()