19#include "mlir/Conversion/LLVMCommon/TypeConverter.h"
20#include "mlir/Dialect/DLTI/DLTI.h"
21#include "mlir/Dialect/Func/IR/FuncOps.h"
22#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
23#include "mlir/Dialect/LLVMIR/LLVMTypes.h"
24#include "mlir/IR/BuiltinAttributes.h"
25#include "mlir/IR/BuiltinDialect.h"
26#include "mlir/IR/BuiltinOps.h"
27#include "mlir/IR/Types.h"
28#include "mlir/Pass/Pass.h"
29#include "mlir/Pass/PassManager.h"
30#include "mlir/Target/LLVMIR/Dialect/Builtin/BuiltinToLLVMIRTranslation.h"
31#include "mlir/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.h"
32#include "mlir/Target/LLVMIR/Export.h"
33#include "mlir/Transforms/DialectConversion.h"
41#include "llvm/ADT/TypeSwitch.h"
42#include "llvm/IR/Module.h"
43#include "llvm/Support/ErrorHandling.h"
44#include "llvm/Support/TimeProfiler.h"
59mlir::Type elementTypeIfVector(mlir::Type type) {
60 return llvm::TypeSwitch<mlir::Type, mlir::Type>(type)
61 .Case<cir::VectorType, mlir::VectorType>(
62 [](
auto p) {
return p.getElementType(); })
63 .
Default([](mlir::Type p) {
return p; });
71 mlir::DataLayout
const &dataLayout,
75 if (isa<cir::BoolType>(type)) {
76 return mlir::IntegerType::get(type.getContext(),
77 dataLayout.getTypeSizeInBits(type));
80 return converter.convertType(type);
84 mlir::IntegerType dstTy,
85 bool isSigned =
false) {
86 mlir::Type srcTy = src.getType();
87 assert(mlir::isa<mlir::IntegerType>(srcTy));
89 unsigned srcWidth = mlir::cast<mlir::IntegerType>(srcTy).getWidth();
90 unsigned dstWidth = mlir::cast<mlir::IntegerType>(dstTy).getWidth();
91 mlir::Location loc = src.getLoc();
93 if (dstWidth > srcWidth && isSigned)
94 return mlir::LLVM::SExtOp::create(bld, loc, dstTy, src);
95 if (dstWidth > srcWidth)
96 return mlir::LLVM::ZExtOp::create(bld, loc, dstTy, src);
97 if (dstWidth < srcWidth)
98 return mlir::LLVM::TruncOp::create(bld, loc, dstTy, src);
99 return mlir::LLVM::BitcastOp::create(bld, loc, dstTy, src);
102static mlir::LLVM::Visibility
104 switch (visibilityKind) {
105 case cir::VisibilityKind::Default:
106 return ::mlir::LLVM::Visibility::Default;
107 case cir::VisibilityKind::Hidden:
108 return ::mlir::LLVM::Visibility::Hidden;
109 case cir::VisibilityKind::Protected:
110 return ::mlir::LLVM::Visibility::Protected;
118 mlir::DataLayout
const &dataLayout,
119 cir::LoadOp op, mlir::Value value) {
122 if (
auto boolTy = mlir::dyn_cast<cir::BoolType>(op.getType())) {
124 assert(value.getType().isInteger(dataLayout.getTypeSizeInBits(boolTy)));
134static mlir::Value
emitToMemory(mlir::ConversionPatternRewriter &rewriter,
135 mlir::DataLayout
const &dataLayout,
136 mlir::Type origType, mlir::Value value) {
139 if (
auto boolTy = mlir::dyn_cast<cir::BoolType>(origType)) {
141 mlir::IntegerType memType =
142 rewriter.getIntegerType(dataLayout.getTypeSizeInBits(boolTy));
150 using CIR = cir::GlobalLinkageKind;
151 using LLVM = mlir::LLVM::Linkage;
154 case CIR::AvailableExternallyLinkage:
155 return LLVM::AvailableExternally;
156 case CIR::CommonLinkage:
158 case CIR::ExternalLinkage:
159 return LLVM::External;
160 case CIR::ExternalWeakLinkage:
161 return LLVM::ExternWeak;
162 case CIR::InternalLinkage:
163 return LLVM::Internal;
164 case CIR::LinkOnceAnyLinkage:
165 return LLVM::Linkonce;
166 case CIR::LinkOnceODRLinkage:
167 return LLVM::LinkonceODR;
168 case CIR::PrivateLinkage:
169 return LLVM::Private;
170 case CIR::WeakAnyLinkage:
172 case CIR::WeakODRLinkage:
173 return LLVM::WeakODR;
175 llvm_unreachable(
"Unknown CIR linkage type");
178mlir::LogicalResult CIRToLLVMCopyOpLowering::matchAndRewrite(
179 cir::CopyOp op, OpAdaptor adaptor,
180 mlir::ConversionPatternRewriter &rewriter)
const {
181 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
182 const mlir::Value
length = mlir::LLVM::ConstantOp::create(
183 rewriter, op.getLoc(), rewriter.getI32Type(), op.getLength(layout));
185 rewriter.replaceOpWithNewOp<mlir::LLVM::MemcpyOp>(
186 op, adaptor.getDst(), adaptor.getSrc(),
length, op.getIsVolatile());
187 return mlir::success();
190mlir::LogicalResult CIRToLLVMMemCpyOpLowering::matchAndRewrite(
191 cir::MemCpyOp op, OpAdaptor adaptor,
192 mlir::ConversionPatternRewriter &rewriter)
const {
193 rewriter.replaceOpWithNewOp<mlir::LLVM::MemcpyOp>(
194 op, adaptor.getDst(), adaptor.getSrc(), adaptor.getLen(),
196 return mlir::success();
199mlir::LogicalResult CIRToLLVMSqrtOpLowering::matchAndRewrite(
200 cir::SqrtOp op, OpAdaptor adaptor,
201 mlir::ConversionPatternRewriter &rewriter)
const {
202 mlir::Type resTy = typeConverter->convertType(op.getType());
203 rewriter.replaceOpWithNewOp<mlir::LLVM::SqrtOp>(op, resTy, adaptor.getSrc());
204 return mlir::success();
207mlir::LogicalResult CIRToLLVMCosOpLowering::matchAndRewrite(
208 cir::CosOp op, OpAdaptor adaptor,
209 mlir::ConversionPatternRewriter &rewriter)
const {
210 mlir::Type resTy = typeConverter->convertType(op.getType());
211 rewriter.replaceOpWithNewOp<mlir::LLVM::CosOp>(op, resTy, adaptor.getSrc());
212 return mlir::success();
215mlir::LogicalResult CIRToLLVMExpOpLowering::matchAndRewrite(
216 cir::ExpOp op, OpAdaptor adaptor,
217 mlir::ConversionPatternRewriter &rewriter)
const {
218 mlir::Type resTy = typeConverter->convertType(op.getType());
219 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpOp>(op, resTy, adaptor.getSrc());
220 return mlir::success();
223mlir::LogicalResult CIRToLLVMExp2OpLowering::matchAndRewrite(
224 cir::Exp2Op op, OpAdaptor adaptor,
225 mlir::ConversionPatternRewriter &rewriter)
const {
226 mlir::Type resTy = typeConverter->convertType(op.getType());
227 rewriter.replaceOpWithNewOp<mlir::LLVM::Exp2Op>(op, resTy, adaptor.getSrc());
228 return mlir::success();
231mlir::LogicalResult CIRToLLVMFloorOpLowering::matchAndRewrite(
232 cir::FloorOp op, OpAdaptor adaptor,
233 mlir::ConversionPatternRewriter &rewriter)
const {
234 mlir::Type resTy = typeConverter->convertType(op.getType());
235 rewriter.replaceOpWithNewOp<mlir::LLVM::FFloorOp>(op, resTy,
237 return mlir::success();
241 mlir::Value llvmSrc, mlir::Type llvmDstIntTy,
243 uint64_t cirDstIntWidth) {
244 if (cirSrcWidth == cirDstIntWidth)
247 auto loc = llvmSrc.getLoc();
248 if (cirSrcWidth < cirDstIntWidth) {
250 return mlir::LLVM::ZExtOp::create(rewriter, loc, llvmDstIntTy, llvmSrc);
251 return mlir::LLVM::SExtOp::create(rewriter, loc, llvmDstIntTy, llvmSrc);
255 return mlir::LLVM::TruncOp::create(rewriter, loc, llvmDstIntTy, llvmSrc);
261 mlir::ConversionPatternRewriter &rewriter,
262 const mlir::TypeConverter *converter,
264 : parentOp(parentOp), rewriter(rewriter), converter(converter),
265 lowerMod(lowerMod) {}
267 mlir::Value
visit(mlir::Attribute attr) {
268 return llvm::TypeSwitch<mlir::Attribute, mlir::Value>(attr)
269 .Case<cir::IntAttr, cir::FPAttr, cir::ConstComplexAttr,
270 cir::ConstArrayAttr, cir::ConstRecordAttr, cir::ConstVectorAttr,
271 cir::ConstPtrAttr, cir::GlobalViewAttr, cir::TypeInfoAttr,
272 cir::UndefAttr, cir::VTableAttr, cir::ZeroAttr>(
274 .Default([&](
auto attrT) {
return mlir::Value(); });
279 mlir::Value
visitCirAttr(cir::ConstComplexAttr complexAttr);
291 mlir::Operation *parentOp;
292 mlir::ConversionPatternRewriter &rewriter;
293 const mlir::TypeConverter *converter;
299 const mlir::Attribute attr,
300 mlir::ConversionPatternRewriter &rewriter,
301 const mlir::TypeConverter *converter,
303 CIRAttrToValue valueConverter(parentOp, rewriter, converter, lowerMod);
304 mlir::Value value = valueConverter.
visit(attr);
306 llvm_unreachable(
"unhandled attribute type");
311 cir::SideEffect sideEffect,
312 mlir::LLVM::MemoryEffectsAttr &memoryEffect,
313 bool &noUnwind,
bool &willReturn,
315 using mlir::LLVM::ModRefInfo;
317 switch (sideEffect) {
318 case cir::SideEffect::All:
320 noUnwind = isNothrow;
324 case cir::SideEffect::Pure:
325 memoryEffect = mlir::LLVM::MemoryEffectsAttr::get(
326 callOp->getContext(), ModRefInfo::Ref,
336 case cir::SideEffect::Const:
337 memoryEffect = mlir::LLVM::MemoryEffectsAttr::get(
338 callOp->getContext(), ModRefInfo::NoModRef,
339 ModRefInfo::NoModRef,
340 ModRefInfo::NoModRef,
341 ModRefInfo::NoModRef,
342 ModRefInfo::NoModRef,
343 ModRefInfo::NoModRef);
349 noReturn = callOp->hasAttr(CIRDialect::getNoReturnAttrName());
352static mlir::LLVM::CallIntrinsicOp
354 mlir::Location loc,
const llvm::Twine &intrinsicName,
355 mlir::Type resultTy, mlir::ValueRange operands) {
356 auto intrinsicNameAttr =
357 mlir::StringAttr::get(rewriter.getContext(), intrinsicName);
358 return mlir::LLVM::CallIntrinsicOp::create(rewriter, loc, resultTy,
359 intrinsicNameAttr, operands);
363 mlir::ConversionPatternRewriter &rewriter, mlir::Operation *op,
364 const llvm::Twine &intrinsicName, mlir::Type resultTy,
365 mlir::ValueRange operands) {
367 rewriter, op->getLoc(), intrinsicName, resultTy, operands);
368 rewriter.replaceOp(op, callIntrinOp.getOperation());
372mlir::LogicalResult CIRToLLVMLLVMIntrinsicCallOpLowering::matchAndRewrite(
373 cir::LLVMIntrinsicCallOp op, OpAdaptor adaptor,
374 mlir::ConversionPatternRewriter &rewriter)
const {
375 mlir::Type llvmResTy =
376 getTypeConverter()->convertType(op->getResultTypes()[0]);
378 return op.emitError(
"expected LLVM result type");
379 StringRef name = op.getIntrinsicName();
392 adaptor.getOperands());
393 return mlir::success();
398 mlir::Location loc = parentOp->getLoc();
399 return mlir::LLVM::ConstantOp::create(
400 rewriter, loc, converter->convertType(intAttr.getType()),
406 mlir::Location loc = parentOp->getLoc();
407 return mlir::LLVM::ConstantOp::create(
408 rewriter, loc, converter->convertType(fltAttr.getType()),
414 auto complexType = mlir::cast<cir::ComplexType>(complexAttr.getType());
415 mlir::Type complexElemTy = complexType.getElementType();
416 mlir::Type complexElemLLVMTy = converter->convertType(complexElemTy);
418 mlir::Attribute components[2];
419 if (
const auto intType = mlir::dyn_cast<cir::IntType>(complexElemTy)) {
420 components[0] = rewriter.getIntegerAttr(
422 mlir::cast<cir::IntAttr>(complexAttr.getReal()).getValue());
423 components[1] = rewriter.getIntegerAttr(
425 mlir::cast<cir::IntAttr>(complexAttr.getImag()).getValue());
427 components[0] = rewriter.getFloatAttr(
429 mlir::cast<cir::FPAttr>(complexAttr.getReal()).getValue());
430 components[1] = rewriter.getFloatAttr(
432 mlir::cast<cir::FPAttr>(complexAttr.getImag()).getValue());
435 mlir::Location loc = parentOp->getLoc();
436 return mlir::LLVM::ConstantOp::create(
437 rewriter, loc, converter->convertType(complexAttr.getType()),
438 rewriter.getArrayAttr(components));
443 mlir::Location loc = parentOp->getLoc();
444 if (ptrAttr.isNullValue()) {
445 return mlir::LLVM::ZeroOp::create(
446 rewriter, loc, converter->convertType(ptrAttr.getType()));
448 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
449 mlir::Value ptrVal = mlir::LLVM::ConstantOp::create(
451 rewriter.getIntegerType(layout.getTypeSizeInBits(ptrAttr.getType())),
452 ptrAttr.getValue().getInt());
453 return mlir::LLVM::IntToPtrOp::create(
454 rewriter, loc, converter->convertType(ptrAttr.getType()), ptrVal);
459 mlir::Type llvmTy = converter->convertType(attr.getType());
460 mlir::Location loc = parentOp->getLoc();
463 if (attr.hasTrailingZeros()) {
464 mlir::Type arrayTy = attr.getType();
465 result = mlir::LLVM::ZeroOp::create(rewriter, loc,
466 converter->convertType(arrayTy));
468 result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
472 if (
auto arrayAttr = mlir::dyn_cast<mlir::ArrayAttr>(attr.getElts())) {
473 for (
auto [idx, elt] : llvm::enumerate(arrayAttr)) {
474 mlir::DataLayout dataLayout(parentOp->getParentOfType<mlir::ModuleOp>());
475 mlir::Value init =
visit(elt);
477 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
479 }
else if (
auto strAttr = mlir::dyn_cast<mlir::StringAttr>(attr.getElts())) {
482 auto arrayTy = mlir::dyn_cast<cir::ArrayType>(strAttr.getType());
483 assert(arrayTy &&
"String attribute must have an array type");
484 mlir::Type eltTy = arrayTy.getElementType();
485 for (
auto [idx, elt] : llvm::enumerate(strAttr)) {
486 auto init = mlir::LLVM::ConstantOp::create(
487 rewriter, loc, converter->convertType(eltTy), elt);
489 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
492 llvm_unreachable(
"unexpected ConstArrayAttr elements");
500 const mlir::Type llvmTy = converter->convertType(constRecord.getType());
501 const mlir::Location loc = parentOp->getLoc();
502 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
505 for (
auto [idx, elt] : llvm::enumerate(constRecord.getMembers())) {
506 mlir::Value init =
visit(elt);
508 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
516 const mlir::Type llvmTy = converter->convertType(attr.getType());
517 const mlir::Location loc = parentOp->getLoc();
520 for (
const mlir::Attribute elementAttr : attr.getElts()) {
521 mlir::Attribute mlirAttr;
522 if (
auto intAttr = mlir::dyn_cast<cir::IntAttr>(elementAttr)) {
523 mlirAttr = rewriter.getIntegerAttr(
524 converter->convertType(intAttr.getType()), intAttr.getValue());
525 }
else if (
auto floatAttr = mlir::dyn_cast<cir::FPAttr>(elementAttr)) {
526 mlirAttr = rewriter.getFloatAttr(
527 converter->convertType(floatAttr.getType()), floatAttr.getValue());
530 "vector constant with an element that is neither an int nor a float");
532 mlirValues.push_back(mlirAttr);
535 return mlir::LLVM::ConstantOp::create(
536 rewriter, loc, llvmTy,
537 mlir::DenseElementsAttr::get(mlir::cast<mlir::ShapedType>(llvmTy),
543 auto moduleOp = parentOp->getParentOfType<mlir::ModuleOp>();
544 mlir::DataLayout dataLayout(moduleOp);
545 mlir::Type sourceType;
547 llvm::StringRef symName;
548 mlir::Operation *sourceSymbol =
549 mlir::SymbolTable::lookupSymbolIn(moduleOp, globalAttr.getSymbol());
550 if (
auto llvmSymbol = dyn_cast<mlir::LLVM::GlobalOp>(sourceSymbol)) {
551 sourceType = llvmSymbol.getType();
552 symName = llvmSymbol.getSymName();
553 }
else if (
auto cirSymbol = dyn_cast<cir::GlobalOp>(sourceSymbol)) {
556 symName = cirSymbol.getSymName();
557 }
else if (
auto llvmFun = dyn_cast<mlir::LLVM::LLVMFuncOp>(sourceSymbol)) {
558 sourceType = llvmFun.getFunctionType();
559 symName = llvmFun.getSymName();
560 }
else if (
auto fun = dyn_cast<cir::FuncOp>(sourceSymbol)) {
561 sourceType = converter->convertType(fun.getFunctionType());
562 symName = fun.getSymName();
563 }
else if (
auto alias = dyn_cast<mlir::LLVM::AliasOp>(sourceSymbol)) {
564 sourceType = alias.getType();
565 symName = alias.getSymName();
567 llvm_unreachable(
"Unexpected GlobalOp type");
570 mlir::Location loc = parentOp->getLoc();
571 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
572 rewriter, loc, mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
575 if (globalAttr.getIndices()) {
578 if (mlir::isa<mlir::LLVM::LLVMArrayType, mlir::LLVM::LLVMStructType>(
580 indices.push_back(0);
582 for (mlir::Attribute idx : globalAttr.getIndices()) {
583 auto intAttr = mlir::cast<mlir::IntegerAttr>(idx);
584 indices.push_back(intAttr.getValue().getSExtValue());
586 mlir::Type resTy = addrOp.getType();
587 mlir::Type eltTy = converter->convertType(sourceType);
589 mlir::LLVM::GEPOp::create(rewriter, loc, resTy, eltTy, addrOp, indices,
590 mlir::LLVM::GEPNoWrapFlags::none);
597 if (
auto intTy = mlir::dyn_cast<cir::IntType>(globalAttr.getType())) {
598 mlir::Type llvmDstTy = converter->convertType(globalAttr.getType());
599 return mlir::LLVM::PtrToIntOp::create(rewriter, parentOp->getLoc(),
603 if (
auto ptrTy = mlir::dyn_cast<cir::PointerType>(globalAttr.getType())) {
604 mlir::Type llvmEltTy =
607 if (llvmEltTy == sourceType)
610 mlir::Type llvmDstTy = converter->convertType(globalAttr.getType());
611 return mlir::LLVM::BitcastOp::create(rewriter, parentOp->getLoc(),
615 llvm_unreachable(
"Expecting pointer or integer type for GlobalViewAttr");
620 mlir::Type llvmTy = converter->convertType(typeInfoAttr.getType());
621 mlir::Location loc = parentOp->getLoc();
622 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
624 for (
auto [idx, elt] : llvm::enumerate(typeInfoAttr.getData())) {
625 mlir::Value init =
visit(elt);
627 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
635 mlir::Location loc = parentOp->getLoc();
636 return mlir::LLVM::UndefOp::create(
637 rewriter, loc, converter->convertType(undefAttr.getType()));
642 mlir::Type llvmTy = converter->convertType(vtableArr.getType());
643 mlir::Location loc = parentOp->getLoc();
644 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
646 for (
auto [idx, elt] : llvm::enumerate(vtableArr.getData())) {
647 mlir::Value init =
visit(elt);
649 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
657 mlir::Location loc = parentOp->getLoc();
658 return mlir::LLVM::ZeroOp::create(rewriter, loc,
659 converter->convertType(attr.getType()));
667 mlir::ConversionPatternRewriter &rewriter)
668 : llvmType(type), rewriter(rewriter) {}
670 mlir::Attribute
visit(mlir::Attribute attr) {
671 return llvm::TypeSwitch<mlir::Attribute, mlir::Attribute>(attr)
672 .Case<cir::IntAttr, cir::FPAttr, cir::BoolAttr>(
674 .Default([&](
auto attrT) {
return mlir::Attribute(); });
678 return rewriter.getIntegerAttr(llvmType, attr.getValue());
682 return rewriter.getFloatAttr(llvmType, attr.getValue());
686 return rewriter.getBoolAttr(attr.getValue());
691 mlir::ConversionPatternRewriter &rewriter;
699 :
public mlir::PassWrapper<ConvertCIRToLLVMPass,
700 mlir::OperationPass<mlir::ModuleOp>> {
702 registry.insert<mlir::BuiltinDialect, mlir::DLTIDialect,
703 mlir::LLVM::LLVMDialect, mlir::func::FuncDialect>();
710 return "Convert the prepared CIR dialect module to LLVM dialect";
713 StringRef
getArgument()
const override {
return "cir-flat-to-llvm"; }
716mlir::LogicalResult CIRToLLVMACosOpLowering::matchAndRewrite(
717 cir::ACosOp op, OpAdaptor adaptor,
718 mlir::ConversionPatternRewriter &rewriter)
const {
719 mlir::Type resTy = typeConverter->convertType(op.getType());
720 rewriter.replaceOpWithNewOp<mlir::LLVM::ACosOp>(op, resTy,
721 adaptor.getOperands()[0]);
722 return mlir::success();
725mlir::LogicalResult CIRToLLVMASinOpLowering::matchAndRewrite(
726 cir::ASinOp op, OpAdaptor adaptor,
727 mlir::ConversionPatternRewriter &rewriter)
const {
728 mlir::Type resTy = typeConverter->convertType(op.getType());
729 rewriter.replaceOpWithNewOp<mlir::LLVM::ASinOp>(op, resTy, adaptor.getSrc());
730 return mlir::success();
733mlir::LogicalResult CIRToLLVMIsFPClassOpLowering::matchAndRewrite(
734 cir::IsFPClassOp op, OpAdaptor adaptor,
735 mlir::ConversionPatternRewriter &rewriter)
const {
736 mlir::Value src = adaptor.getSrc();
737 cir::FPClassTest flags = adaptor.getFlags();
738 mlir::IntegerType retTy = rewriter.getI1Type();
740 rewriter.replaceOpWithNewOp<mlir::LLVM::IsFPClass>(
741 op, retTy, src,
static_cast<uint32_t>(flags));
742 return mlir::success();
745mlir::LogicalResult CIRToLLVMAssumeOpLowering::matchAndRewrite(
746 cir::AssumeOp op, OpAdaptor adaptor,
747 mlir::ConversionPatternRewriter &rewriter)
const {
748 auto cond = adaptor.getPredicate();
749 rewriter.replaceOpWithNewOp<mlir::LLVM::AssumeOp>(op, cond);
750 return mlir::success();
753mlir::LogicalResult CIRToLLVMAssumeAlignedOpLowering::matchAndRewrite(
754 cir::AssumeAlignedOp op, OpAdaptor adaptor,
755 mlir::ConversionPatternRewriter &rewriter)
const {
756 SmallVector<mlir::Value, 3> opBundleArgs{adaptor.getPointer()};
758 auto alignment = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
759 adaptor.getAlignmentAttr());
760 opBundleArgs.push_back(alignment);
762 if (mlir::Value offset = adaptor.getOffset())
763 opBundleArgs.push_back(offset);
765 auto cond = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
766 rewriter.getI1Type(), 1);
767 mlir::LLVM::AssumeOp::create(rewriter, op.getLoc(), cond,
"align",
772 rewriter.replaceOp(op, adaptor.getPointer());
773 return mlir::success();
776mlir::LogicalResult CIRToLLVMAssumeSepStorageOpLowering::matchAndRewrite(
777 cir::AssumeSepStorageOp op, OpAdaptor adaptor,
778 mlir::ConversionPatternRewriter &rewriter)
const {
779 auto cond = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
780 rewriter.getI1Type(), 1);
781 rewriter.replaceOpWithNewOp<mlir::LLVM::AssumeOp>(
782 op, cond, mlir::LLVM::AssumeSeparateStorageTag{}, adaptor.getPtr1(),
784 return mlir::success();
787static mlir::LLVM::AtomicOrdering
790 return mlir::LLVM::AtomicOrdering::not_atomic;
792 case cir::MemOrder::Relaxed:
793 return mlir::LLVM::AtomicOrdering::monotonic;
794 case cir::MemOrder::Consume:
795 case cir::MemOrder::Acquire:
796 return mlir::LLVM::AtomicOrdering::acquire;
797 case cir::MemOrder::Release:
798 return mlir::LLVM::AtomicOrdering::release;
799 case cir::MemOrder::AcquireRelease:
800 return mlir::LLVM::AtomicOrdering::acq_rel;
801 case cir::MemOrder::SequentiallyConsistent:
802 return mlir::LLVM::AtomicOrdering::seq_cst;
804 llvm_unreachable(
"unknown memory order");
807static std::optional<llvm::StringRef>
809 if (syncScope.has_value())
810 return syncScope.value() == cir::SyncScopeKind::SingleThread
816mlir::LogicalResult CIRToLLVMAtomicCmpXchgOpLowering::matchAndRewrite(
817 cir::AtomicCmpXchgOp op, OpAdaptor adaptor,
818 mlir::ConversionPatternRewriter &rewriter)
const {
819 mlir::Value expected = adaptor.getExpected();
820 mlir::Value desired = adaptor.getDesired();
822 auto cmpxchg = mlir::LLVM::AtomicCmpXchgOp::create(
823 rewriter, op.getLoc(), adaptor.getPtr(), expected, desired,
827 cmpxchg.setAlignment(adaptor.getAlignment());
828 cmpxchg.setWeak(adaptor.getWeak());
829 cmpxchg.setVolatile_(adaptor.getIsVolatile());
832 auto old = mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(),
833 cmpxchg.getResult(), 0);
834 auto cmp = mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(),
835 cmpxchg.getResult(), 1);
837 rewriter.replaceOp(op, {old, cmp});
838 return mlir::success();
841mlir::LogicalResult CIRToLLVMAtomicXchgOpLowering::matchAndRewrite(
842 cir::AtomicXchgOp op, OpAdaptor adaptor,
843 mlir::ConversionPatternRewriter &rewriter)
const {
845 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(adaptor.getMemOrder());
846 rewriter.replaceOpWithNewOp<mlir::LLVM::AtomicRMWOp>(
847 op, mlir::LLVM::AtomicBinOp::xchg, adaptor.getPtr(), adaptor.getVal(),
849 return mlir::success();
852mlir::LogicalResult CIRToLLVMAtomicTestAndSetOpLowering::matchAndRewrite(
853 cir::AtomicTestAndSetOp op, OpAdaptor adaptor,
854 mlir::ConversionPatternRewriter &rewriter)
const {
857 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
859 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
860 rewriter.getI8Type(), 1);
861 auto rmw = mlir::LLVM::AtomicRMWOp::create(
862 rewriter, op.getLoc(), mlir::LLVM::AtomicBinOp::xchg, adaptor.getPtr(),
863 one, llvmOrder, llvm::StringRef(),
864 adaptor.getAlignment().value_or(0), op.getIsVolatile());
866 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
867 rewriter.getI8Type(), 0);
868 auto cmp = mlir::LLVM::ICmpOp::create(
869 rewriter, op.getLoc(), mlir::LLVM::ICmpPredicate::ne, rmw, zero);
871 rewriter.replaceOp(op, cmp);
872 return mlir::success();
875mlir::LogicalResult CIRToLLVMAtomicClearOpLowering::matchAndRewrite(
876 cir::AtomicClearOp op, OpAdaptor adaptor,
877 mlir::ConversionPatternRewriter &rewriter)
const {
880 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
881 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
882 rewriter.getI8Type(), 0);
883 auto store = mlir::LLVM::StoreOp::create(
884 rewriter, op.getLoc(), zero, adaptor.getPtr(),
885 adaptor.getAlignment().value_or(0), op.getIsVolatile(),
886 false,
false, llvmOrder);
888 rewriter.replaceOp(op, store);
889 return mlir::success();
892mlir::LogicalResult CIRToLLVMAtomicFenceOpLowering::matchAndRewrite(
893 cir::AtomicFenceOp op, OpAdaptor adaptor,
894 mlir::ConversionPatternRewriter &rewriter)
const {
895 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(adaptor.getOrdering());
897 auto fence = mlir::LLVM::FenceOp::create(rewriter, op.getLoc(), llvmOrder);
900 rewriter.replaceOp(op, fence);
902 return mlir::success();
905static mlir::LLVM::AtomicBinOp
908 case cir::AtomicFetchKind::Add:
909 return isInt ? mlir::LLVM::AtomicBinOp::add : mlir::LLVM::AtomicBinOp::fadd;
910 case cir::AtomicFetchKind::Sub:
911 return isInt ? mlir::LLVM::AtomicBinOp::sub : mlir::LLVM::AtomicBinOp::fsub;
912 case cir::AtomicFetchKind::And:
913 return mlir::LLVM::AtomicBinOp::_and;
914 case cir::AtomicFetchKind::Xor:
915 return mlir::LLVM::AtomicBinOp::_xor;
916 case cir::AtomicFetchKind::Or:
917 return mlir::LLVM::AtomicBinOp::_or;
918 case cir::AtomicFetchKind::Nand:
919 return mlir::LLVM::AtomicBinOp::nand;
920 case cir::AtomicFetchKind::Max: {
922 return mlir::LLVM::AtomicBinOp::fmax;
923 return isSignedInt ? mlir::LLVM::AtomicBinOp::max
924 : mlir::LLVM::AtomicBinOp::umax;
926 case cir::AtomicFetchKind::Min: {
928 return mlir::LLVM::AtomicBinOp::fmin;
929 return isSignedInt ? mlir::LLVM::AtomicBinOp::min
930 : mlir::LLVM::AtomicBinOp::umin;
933 llvm_unreachable(
"Unknown atomic fetch opcode");
936static llvm::StringLiteral
getLLVMBinop(cir::AtomicFetchKind k,
bool isInt) {
938 case cir::AtomicFetchKind::Add:
939 return isInt ? mlir::LLVM::AddOp::getOperationName()
940 : mlir::LLVM::FAddOp::getOperationName();
941 case cir::AtomicFetchKind::Sub:
942 return isInt ? mlir::LLVM::SubOp::getOperationName()
943 : mlir::LLVM::FSubOp::getOperationName();
944 case cir::AtomicFetchKind::And:
945 return mlir::LLVM::AndOp::getOperationName();
946 case cir::AtomicFetchKind::Xor:
947 return mlir::LLVM::XOrOp::getOperationName();
948 case cir::AtomicFetchKind::Or:
949 return mlir::LLVM::OrOp::getOperationName();
950 case cir::AtomicFetchKind::Nand:
952 return mlir::LLVM::AndOp::getOperationName();
953 case cir::AtomicFetchKind::Max:
954 case cir::AtomicFetchKind::Min:
955 llvm_unreachable(
"handled in buildMinMaxPostOp");
957 llvm_unreachable(
"Unknown atomic fetch opcode");
960mlir::Value CIRToLLVMAtomicFetchOpLowering::buildPostOp(
961 cir::AtomicFetchOp op, OpAdaptor adaptor,
962 mlir::ConversionPatternRewriter &rewriter, mlir::Value rmwVal,
968 rewriter.getStringAttr(
getLLVMBinop(op.getBinop(), isInt)),
969 atomicOperands, atomicResTys, {})
973mlir::Value CIRToLLVMAtomicFetchOpLowering::buildMinMaxPostOp(
974 cir::AtomicFetchOp op, OpAdaptor adaptor,
975 mlir::ConversionPatternRewriter &rewriter, mlir::Value rmwVal,
bool isInt,
976 bool isSigned)
const {
977 mlir::Location loc = op.getLoc();
980 if (op.getBinop() == cir::AtomicFetchKind::Max)
981 return mlir::LLVM::MaxNumOp::create(rewriter, loc, rmwVal,
983 return mlir::LLVM::MinNumOp::create(rewriter, loc, rmwVal,
987 mlir::LLVM::ICmpPredicate pred;
988 if (op.getBinop() == cir::AtomicFetchKind::Max) {
989 pred = isSigned ? mlir::LLVM::ICmpPredicate::sgt
990 : mlir::LLVM::ICmpPredicate::ugt;
992 pred = isSigned ? mlir::LLVM::ICmpPredicate::slt
993 : mlir::LLVM::ICmpPredicate::ult;
995 mlir::Value cmp = mlir::LLVM::ICmpOp::create(
997 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(), pred), rmwVal,
999 return mlir::LLVM::SelectOp::create(rewriter, loc, cmp, rmwVal,
1003mlir::LogicalResult CIRToLLVMAtomicFetchOpLowering::matchAndRewrite(
1004 cir::AtomicFetchOp op, OpAdaptor adaptor,
1005 mlir::ConversionPatternRewriter &rewriter)
const {
1007 bool isSignedInt =
false;
1008 if (
auto intTy = mlir::dyn_cast<cir::IntType>(op.getVal().getType())) {
1010 isSignedInt = intTy.isSigned();
1011 }
else if (mlir::isa<cir::SingleType, cir::DoubleType>(
1012 op.getVal().getType())) {
1015 return op.emitError() <<
"Unsupported type: " << op.getVal().getType();
1018 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
1019 mlir::LLVM::AtomicBinOp llvmBinOp =
1021 auto rmwVal = mlir::LLVM::AtomicRMWOp::create(rewriter, op.getLoc(),
1022 llvmBinOp, adaptor.getPtr(),
1023 adaptor.getVal(), llvmOrder);
1025 mlir::Value result = rmwVal.getResult();
1026 if (!op.getFetchFirst()) {
1027 if (op.getBinop() == cir::AtomicFetchKind::Max ||
1028 op.getBinop() == cir::AtomicFetchKind::Min)
1029 result = buildMinMaxPostOp(op, adaptor, rewriter, rmwVal.getRes(), isInt,
1032 result = buildPostOp(op, adaptor, rewriter, rmwVal.getRes(), isInt);
1035 if (op.getBinop() == cir::AtomicFetchKind::Nand) {
1036 auto negOne = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1037 result.getType(), -1);
1038 result = mlir::LLVM::XOrOp::create(rewriter, op.getLoc(), result, negOne);
1042 rewriter.replaceOp(op, result);
1043 return mlir::success();
1046mlir::LogicalResult CIRToLLVMBitClrsbOpLowering::matchAndRewrite(
1047 cir::BitClrsbOp op, OpAdaptor adaptor,
1048 mlir::ConversionPatternRewriter &rewriter)
const {
1049 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1050 adaptor.getInput().getType(), 0);
1051 auto isNeg = mlir::LLVM::ICmpOp::create(
1052 rewriter, op.getLoc(),
1053 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(),
1054 mlir::LLVM::ICmpPredicate::slt),
1055 adaptor.getInput(), zero);
1057 auto negOne = mlir::LLVM::ConstantOp::create(
1058 rewriter, op.getLoc(), adaptor.getInput().getType(), -1);
1059 auto flipped = mlir::LLVM::XOrOp::create(rewriter, op.getLoc(),
1060 adaptor.getInput(), negOne);
1062 auto select = mlir::LLVM::SelectOp::create(rewriter, op.getLoc(), isNeg,
1063 flipped, adaptor.getInput());
1065 auto resTy = getTypeConverter()->convertType(op.getType());
1066 auto clz = mlir::LLVM::CountLeadingZerosOp::create(
1067 rewriter, op.getLoc(), resTy,
select,
false);
1069 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1070 auto res = mlir::LLVM::SubOp::create(rewriter, op.getLoc(),
clz, one,
1071 mlir::LLVM::IntegerOverflowFlags::nuw);
1072 rewriter.replaceOp(op, res);
1074 return mlir::LogicalResult::success();
1077mlir::LogicalResult CIRToLLVMBitClzOpLowering::matchAndRewrite(
1078 cir::BitClzOp op, OpAdaptor adaptor,
1079 mlir::ConversionPatternRewriter &rewriter)
const {
1080 auto resTy = getTypeConverter()->convertType(op.getType());
1081 auto llvmOp = mlir::LLVM::CountLeadingZerosOp::create(
1082 rewriter, op.getLoc(), resTy, adaptor.getInput(), op.getPoisonZero());
1083 rewriter.replaceOp(op, llvmOp);
1084 return mlir::LogicalResult::success();
1087mlir::LogicalResult CIRToLLVMBitCtzOpLowering::matchAndRewrite(
1088 cir::BitCtzOp op, OpAdaptor adaptor,
1089 mlir::ConversionPatternRewriter &rewriter)
const {
1090 auto resTy = getTypeConverter()->convertType(op.getType());
1091 auto llvmOp = mlir::LLVM::CountTrailingZerosOp::create(
1092 rewriter, op.getLoc(), resTy, adaptor.getInput(), op.getPoisonZero());
1093 rewriter.replaceOp(op, llvmOp);
1094 return mlir::LogicalResult::success();
1097mlir::LogicalResult CIRToLLVMBitFfsOpLowering::matchAndRewrite(
1098 cir::BitFfsOp op, OpAdaptor adaptor,
1099 mlir::ConversionPatternRewriter &rewriter)
const {
1100 auto resTy = getTypeConverter()->convertType(op.getType());
1101 auto ctz = mlir::LLVM::CountTrailingZerosOp::create(rewriter, op.getLoc(),
1102 resTy, adaptor.getInput(),
1105 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1106 auto ctzAddOne = mlir::LLVM::AddOp::create(rewriter, op.getLoc(),
ctz, one);
1108 auto zeroInputTy = mlir::LLVM::ConstantOp::create(
1109 rewriter, op.getLoc(), adaptor.getInput().getType(), 0);
1110 auto isZero = mlir::LLVM::ICmpOp::create(
1111 rewriter, op.getLoc(),
1112 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(),
1113 mlir::LLVM::ICmpPredicate::eq),
1114 adaptor.getInput(), zeroInputTy);
1116 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 0);
1117 auto res = mlir::LLVM::SelectOp::create(rewriter, op.getLoc(), isZero, zero,
1119 rewriter.replaceOp(op, res);
1121 return mlir::LogicalResult::success();
1124mlir::LogicalResult CIRToLLVMBitParityOpLowering::matchAndRewrite(
1125 cir::BitParityOp op, OpAdaptor adaptor,
1126 mlir::ConversionPatternRewriter &rewriter)
const {
1127 auto resTy = getTypeConverter()->convertType(op.getType());
1128 auto popcnt = mlir::LLVM::CtPopOp::create(rewriter, op.getLoc(), resTy,
1129 adaptor.getInput());
1131 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1133 mlir::LLVM::AndOp::create(rewriter, op.getLoc(), popcnt, one);
1134 rewriter.replaceOp(op, popcntMod2);
1136 return mlir::LogicalResult::success();
1139mlir::LogicalResult CIRToLLVMBitPopcountOpLowering::matchAndRewrite(
1140 cir::BitPopcountOp op, OpAdaptor adaptor,
1141 mlir::ConversionPatternRewriter &rewriter)
const {
1142 auto resTy = getTypeConverter()->convertType(op.getType());
1143 auto llvmOp = mlir::LLVM::CtPopOp::create(rewriter, op.getLoc(), resTy,
1144 adaptor.getInput());
1145 rewriter.replaceOp(op, llvmOp);
1146 return mlir::LogicalResult::success();
1149mlir::LogicalResult CIRToLLVMBitReverseOpLowering::matchAndRewrite(
1150 cir::BitReverseOp op, OpAdaptor adaptor,
1151 mlir::ConversionPatternRewriter &rewriter)
const {
1152 rewriter.replaceOpWithNewOp<mlir::LLVM::BitReverseOp>(op, adaptor.getInput());
1153 return mlir::success();
1156mlir::LogicalResult CIRToLLVMBrCondOpLowering::matchAndRewrite(
1157 cir::BrCondOp brOp, OpAdaptor adaptor,
1158 mlir::ConversionPatternRewriter &rewriter)
const {
1163 mlir::Value i1Condition = adaptor.getCond();
1165 rewriter.replaceOpWithNewOp<mlir::LLVM::CondBrOp>(
1166 brOp, i1Condition, brOp.getDestTrue(), adaptor.getDestOperandsTrue(),
1167 brOp.getDestFalse(), adaptor.getDestOperandsFalse());
1169 return mlir::success();
1172mlir::LogicalResult CIRToLLVMByteSwapOpLowering::matchAndRewrite(
1173 cir::ByteSwapOp op, OpAdaptor adaptor,
1174 mlir::ConversionPatternRewriter &rewriter)
const {
1175 rewriter.replaceOpWithNewOp<mlir::LLVM::ByteSwapOp>(op, adaptor.getInput());
1176 return mlir::LogicalResult::success();
1179mlir::Type CIRToLLVMCastOpLowering::convertTy(mlir::Type ty)
const {
1180 return getTypeConverter()->convertType(ty);
1183mlir::LogicalResult CIRToLLVMCastOpLowering::matchAndRewrite(
1184 cir::CastOp castOp, OpAdaptor adaptor,
1185 mlir::ConversionPatternRewriter &rewriter)
const {
1190 switch (castOp.getKind()) {
1191 case cir::CastKind::array_to_ptrdecay: {
1192 const auto ptrTy = mlir::cast<cir::PointerType>(castOp.getType());
1193 mlir::Value sourceValue = adaptor.getSrc();
1194 mlir::Type targetType = convertTy(ptrTy);
1196 ptrTy.getPointee());
1197 llvm::SmallVector<mlir::LLVM::GEPArg> offset{0};
1198 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1199 castOp, targetType, elementTy, sourceValue, offset);
1202 case cir::CastKind::int_to_bool: {
1203 mlir::Value llvmSrcVal = adaptor.getSrc();
1204 mlir::Value zeroInt = mlir::LLVM::ConstantOp::create(
1205 rewriter, castOp.getLoc(), llvmSrcVal.getType(), 0);
1206 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
1207 castOp, mlir::LLVM::ICmpPredicate::ne, llvmSrcVal, zeroInt);
1210 case cir::CastKind::integral: {
1211 mlir::Type srcType = castOp.getSrc().getType();
1212 mlir::Type dstType = castOp.getType();
1213 mlir::Value llvmSrcVal = adaptor.getSrc();
1214 mlir::Type llvmDstType = getTypeConverter()->convertType(dstType);
1215 cir::IntType srcIntType =
1216 mlir::cast<cir::IntType>(elementTypeIfVector(srcType));
1217 cir::IntType dstIntType =
1218 mlir::cast<cir::IntType>(elementTypeIfVector(dstType));
1219 rewriter.replaceOp(castOp,
getLLVMIntCast(rewriter, llvmSrcVal, llvmDstType,
1220 srcIntType.isUnsigned(),
1221 srcIntType.getWidth(),
1222 dstIntType.getWidth()));
1225 case cir::CastKind::floating: {
1226 mlir::Value llvmSrcVal = adaptor.getSrc();
1227 mlir::Type llvmDstTy = getTypeConverter()->convertType(castOp.getType());
1229 mlir::Type srcTy = elementTypeIfVector(castOp.getSrc().getType());
1230 mlir::Type dstTy = elementTypeIfVector(castOp.getType());
1232 if (!mlir::isa<cir::FPTypeInterface>(dstTy) ||
1233 !mlir::isa<cir::FPTypeInterface>(srcTy))
1234 return castOp.emitError() <<
"NYI cast from " << srcTy <<
" to " << dstTy;
1236 auto getFloatWidth = [](mlir::Type ty) ->
unsigned {
1237 return mlir::cast<cir::FPTypeInterface>(ty).getWidth();
1240 if (getFloatWidth(srcTy) > getFloatWidth(dstTy))
1241 rewriter.replaceOpWithNewOp<mlir::LLVM::FPTruncOp>(castOp, llvmDstTy,
1244 rewriter.replaceOpWithNewOp<mlir::LLVM::FPExtOp>(castOp, llvmDstTy,
1246 return mlir::success();
1248 case cir::CastKind::int_to_ptr: {
1249 auto dstTy = mlir::cast<cir::PointerType>(castOp.getType());
1250 mlir::Value llvmSrcVal = adaptor.getSrc();
1251 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1252 rewriter.replaceOpWithNewOp<mlir::LLVM::IntToPtrOp>(castOp, llvmDstTy,
1254 return mlir::success();
1256 case cir::CastKind::ptr_to_int: {
1257 auto dstTy = mlir::cast<cir::IntType>(castOp.getType());
1258 mlir::Value llvmSrcVal = adaptor.getSrc();
1259 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1260 rewriter.replaceOpWithNewOp<mlir::LLVM::PtrToIntOp>(castOp, llvmDstTy,
1262 return mlir::success();
1264 case cir::CastKind::float_to_bool: {
1265 mlir::Value llvmSrcVal = adaptor.getSrc();
1266 auto kind = mlir::LLVM::FCmpPredicate::une;
1269 auto zeroFloat = mlir::LLVM::ConstantOp::create(
1270 rewriter, castOp.getLoc(), llvmSrcVal.getType(),
1271 mlir::FloatAttr::get(llvmSrcVal.getType(), 0.0));
1274 rewriter.replaceOpWithNewOp<mlir::LLVM::FCmpOp>(castOp,
kind, llvmSrcVal,
1277 return mlir::success();
1279 case cir::CastKind::bool_to_int: {
1280 auto dstTy = mlir::cast<cir::IntType>(castOp.getType());
1281 mlir::Value llvmSrcVal = adaptor.getSrc();
1282 auto llvmSrcTy = mlir::cast<mlir::IntegerType>(llvmSrcVal.getType());
1284 mlir::cast<mlir::IntegerType>(getTypeConverter()->convertType(dstTy));
1285 if (llvmSrcTy.getWidth() == llvmDstTy.getWidth())
1286 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(castOp, llvmDstTy,
1289 rewriter.replaceOpWithNewOp<mlir::LLVM::ZExtOp>(castOp, llvmDstTy,
1291 return mlir::success();
1293 case cir::CastKind::bool_to_float: {
1294 mlir::Type dstTy = castOp.getType();
1295 mlir::Value llvmSrcVal = adaptor.getSrc();
1296 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1297 rewriter.replaceOpWithNewOp<mlir::LLVM::UIToFPOp>(castOp, llvmDstTy,
1299 return mlir::success();
1301 case cir::CastKind::int_to_float: {
1302 mlir::Type dstTy = castOp.getType();
1303 mlir::Value llvmSrcVal = adaptor.getSrc();
1304 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1305 if (mlir::cast<cir::IntType>(elementTypeIfVector(castOp.getSrc().getType()))
1307 rewriter.replaceOpWithNewOp<mlir::LLVM::SIToFPOp>(castOp, llvmDstTy,
1310 rewriter.replaceOpWithNewOp<mlir::LLVM::UIToFPOp>(castOp, llvmDstTy,
1312 return mlir::success();
1314 case cir::CastKind::float_to_int: {
1315 mlir::Type dstTy = castOp.getType();
1316 mlir::Value llvmSrcVal = adaptor.getSrc();
1317 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1318 if (mlir::cast<cir::IntType>(elementTypeIfVector(castOp.getType()))
1320 rewriter.replaceOpWithNewOp<mlir::LLVM::FPToSIOp>(castOp, llvmDstTy,
1323 rewriter.replaceOpWithNewOp<mlir::LLVM::FPToUIOp>(castOp, llvmDstTy,
1325 return mlir::success();
1327 case cir::CastKind::bitcast: {
1328 mlir::Type dstTy = castOp.getType();
1329 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1334 mlir::Value llvmSrcVal = adaptor.getSrc();
1335 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(castOp, llvmDstTy,
1337 return mlir::success();
1339 case cir::CastKind::ptr_to_bool: {
1340 mlir::Value llvmSrcVal = adaptor.getSrc();
1341 mlir::Value zeroPtr = mlir::LLVM::ZeroOp::create(rewriter, castOp.getLoc(),
1342 llvmSrcVal.getType());
1343 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
1344 castOp, mlir::LLVM::ICmpPredicate::ne, llvmSrcVal, zeroPtr);
1347 case cir::CastKind::address_space: {
1348 mlir::Type dstTy = castOp.getType();
1349 mlir::Value llvmSrcVal = adaptor.getSrc();
1350 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1351 rewriter.replaceOpWithNewOp<mlir::LLVM::AddrSpaceCastOp>(castOp, llvmDstTy,
1355 case cir::CastKind::member_ptr_to_bool:
1360 return castOp.emitError(
"Unhandled cast kind: ")
1361 << castOp.getKindAttrName();
1365 return mlir::success();
1369 mlir::ModuleOp mod, mlir::Value index,
1370 mlir::Type baseTy, cir::IntType strideTy) {
1371 mlir::Operation *indexOp = index.getDefiningOp();
1375 auto indexType = mlir::cast<mlir::IntegerType>(index.getType());
1376 mlir::DataLayout llvmLayout(mod);
1377 std::optional<uint64_t> layoutWidth = llvmLayout.getTypeIndexBitwidth(baseTy);
1380 if (!layoutWidth || *layoutWidth == indexType.getWidth())
1386 auto sub = dyn_cast<mlir::LLVM::SubOp>(indexOp);
1387 bool rewriteSub =
false;
1390 dyn_cast<mlir::LLVM::ConstantOp>(sub.getLhs().getDefiningOp())) {
1391 auto lhsConstInt = mlir::dyn_cast<mlir::IntegerAttr>(lhsConst.getValue());
1392 if (lhsConstInt && lhsConstInt.getValue() == 0) {
1393 index = sub.getRhs();
1399 auto llvmDstType = rewriter.getIntegerType(*layoutWidth);
1400 bool isUnsigned = strideTy && strideTy.isUnsigned();
1402 indexType.getWidth(), *layoutWidth);
1405 index = mlir::LLVM::SubOp::create(
1406 rewriter, index.getLoc(),
1407 mlir::LLVM::ConstantOp::create(rewriter, index.getLoc(),
1408 index.getType(), 0),
1411 rewriter.eraseOp(sub);
1417mlir::LogicalResult CIRToLLVMPtrStrideOpLowering::matchAndRewrite(
1418 cir::PtrStrideOp ptrStrideOp, OpAdaptor adaptor,
1419 mlir::ConversionPatternRewriter &rewriter)
const {
1421 const mlir::TypeConverter *tc = getTypeConverter();
1422 const mlir::Type resultTy = tc->convertType(ptrStrideOp.getType());
1424 mlir::Type elementTy =
1429 if (mlir::isa<mlir::LLVM::LLVMVoidType>(elementTy) ||
1430 mlir::isa<mlir::LLVM::LLVMFunctionType>(elementTy))
1431 elementTy = mlir::IntegerType::get(elementTy.getContext(), 8,
1432 mlir::IntegerType::Signless);
1434 mlir::Value index = adaptor.getStride();
1436 rewriter, ptrStrideOp->getParentOfType<mlir::ModuleOp>(), index,
1437 adaptor.getBase().getType(),
1438 dyn_cast<cir::IntType>(ptrStrideOp.getOperand(1).getType()));
1440 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1441 ptrStrideOp, resultTy, elementTy, adaptor.getBase(), index);
1442 return mlir::success();
1445mlir::LogicalResult CIRToLLVMGetElementOpLowering::matchAndRewrite(
1446 cir::GetElementOp op, OpAdaptor adaptor,
1447 mlir::ConversionPatternRewriter &rewriter)
const {
1449 mlir::dyn_cast<cir::ArrayType>(op.getBaseType().getPointee())) {
1450 const mlir::TypeConverter *converter = getTypeConverter();
1451 const mlir::Type llArrayTy = converter->convertType(arrayTy);
1452 const mlir::Type llResultTy = converter->convertType(op.getType());
1453 mlir::Type elementTy =
1458 if (mlir::isa<mlir::LLVM::LLVMVoidType>(elementTy) ||
1459 mlir::isa<mlir::LLVM::LLVMFunctionType>(elementTy))
1460 elementTy = rewriter.getIntegerType(8);
1462 mlir::Value index = adaptor.getIndex();
1465 adaptor.getBase().getType(),
1466 dyn_cast<cir::IntType>(op.getOperand(1).getType()));
1471 std::array<mlir::LLVM::GEPArg, 2> offset{0, index};
1472 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, llResultTy, llArrayTy,
1473 adaptor.getBase(), offset);
1474 return mlir::success();
1477 op.emitError() <<
"NYI: GetElementOp lowering to LLVM for non-array";
1478 return mlir::failure();
1481mlir::LogicalResult CIRToLLVMBaseClassAddrOpLowering::matchAndRewrite(
1482 cir::BaseClassAddrOp baseClassOp, OpAdaptor adaptor,
1483 mlir::ConversionPatternRewriter &rewriter)
const {
1484 const mlir::Type resultType =
1485 getTypeConverter()->convertType(baseClassOp.getType());
1486 mlir::Value derivedAddr = adaptor.getDerivedAddr();
1487 llvm::SmallVector<mlir::LLVM::GEPArg, 1> offset = {
1488 adaptor.getOffset().getZExtValue()};
1489 mlir::Type byteType = mlir::IntegerType::get(resultType.getContext(), 8,
1490 mlir::IntegerType::Signless);
1491 if (adaptor.getOffset().getZExtValue() == 0) {
1492 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(
1493 baseClassOp, resultType, adaptor.getDerivedAddr());
1494 return mlir::success();
1497 if (baseClassOp.getAssumeNotNull()) {
1498 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1499 baseClassOp, resultType, byteType, derivedAddr, offset);
1501 auto loc = baseClassOp.getLoc();
1502 mlir::Value isNull = mlir::LLVM::ICmpOp::create(
1503 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, derivedAddr,
1504 mlir::LLVM::ZeroOp::create(rewriter, loc, derivedAddr.getType()));
1505 mlir::Value adjusted = mlir::LLVM::GEPOp::create(
1506 rewriter, loc, resultType, byteType, derivedAddr, offset);
1507 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(baseClassOp, isNull,
1508 derivedAddr, adjusted);
1510 return mlir::success();
1513mlir::LogicalResult CIRToLLVMDerivedClassAddrOpLowering::matchAndRewrite(
1514 cir::DerivedClassAddrOp derivedClassOp, OpAdaptor adaptor,
1515 mlir::ConversionPatternRewriter &rewriter)
const {
1516 const mlir::Type resultType =
1517 getTypeConverter()->convertType(derivedClassOp.getType());
1518 mlir::Value baseAddr = adaptor.getBaseAddr();
1521 int64_t offsetVal = -(adaptor.getOffset().getZExtValue());
1522 if (offsetVal == 0) {
1524 rewriter.replaceOp(derivedClassOp, baseAddr);
1525 return mlir::success();
1527 llvm::SmallVector<mlir::LLVM::GEPArg, 1> offset = {offsetVal};
1528 mlir::Type byteType = mlir::IntegerType::get(resultType.getContext(), 8,
1529 mlir::IntegerType::Signless);
1530 if (derivedClassOp.getAssumeNotNull()) {
1531 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1532 derivedClassOp, resultType, byteType, baseAddr, offset,
1533 mlir::LLVM::GEPNoWrapFlags::inbounds);
1535 mlir::Location loc = derivedClassOp.getLoc();
1536 mlir::Value isNull = mlir::LLVM::ICmpOp::create(
1537 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, baseAddr,
1538 mlir::LLVM::ZeroOp::create(rewriter, loc, baseAddr.getType()));
1539 mlir::Value adjusted =
1540 mlir::LLVM::GEPOp::create(rewriter, loc, resultType, byteType, baseAddr,
1541 offset, mlir::LLVM::GEPNoWrapFlags::inbounds);
1542 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(derivedClassOp, isNull,
1543 baseAddr, adjusted);
1545 return mlir::success();
1548mlir::LogicalResult CIRToLLVMATanOpLowering::matchAndRewrite(
1549 cir::ATanOp op, OpAdaptor adaptor,
1550 mlir::ConversionPatternRewriter &rewriter)
const {
1551 mlir::Type resTy = typeConverter->convertType(op.getType());
1552 rewriter.replaceOpWithNewOp<mlir::LLVM::ATanOp>(op, resTy, adaptor.getSrc());
1553 return mlir::success();
1556mlir::LogicalResult CIRToLLVMCeilOpLowering::matchAndRewrite(
1557 cir::CeilOp op, OpAdaptor adaptor,
1558 mlir::ConversionPatternRewriter &rewriter)
const {
1559 mlir::Type resTy = typeConverter->convertType(op.getType());
1560 rewriter.replaceOpWithNewOp<mlir::LLVM::FCeilOp>(op, resTy, adaptor.getSrc());
1561 return mlir::success();
1564mlir::LogicalResult CIRToLLVMAllocaOpLowering::matchAndRewrite(
1565 cir::AllocaOp op, OpAdaptor adaptor,
1566 mlir::ConversionPatternRewriter &rewriter)
const {
1569 ? adaptor.getDynAllocSize()
1570 : mlir::LLVM::ConstantOp::create(
1571 rewriter, op.getLoc(),
1572 typeConverter->convertType(rewriter.getIndexType()), 1);
1573 mlir::Type elementTy =
1575 mlir::Type resultTy =
1581 rewriter.replaceOpWithNewOp<mlir::LLVM::AllocaOp>(op, resultTy, elementTy,
1582 size, op.getAlignment());
1584 return mlir::success();
1587mlir::LogicalResult CIRToLLVMReturnOpLowering::matchAndRewrite(
1588 cir::ReturnOp op, OpAdaptor adaptor,
1589 mlir::ConversionPatternRewriter &rewriter)
const {
1590 rewriter.replaceOpWithNewOp<mlir::LLVM::ReturnOp>(op, adaptor.getOperands());
1591 return mlir::LogicalResult::success();
1594mlir::LogicalResult CIRToLLVMRotateOpLowering::matchAndRewrite(
1595 cir::RotateOp op, OpAdaptor adaptor,
1596 mlir::ConversionPatternRewriter &rewriter)
const {
1599 mlir::Value input = adaptor.getInput();
1600 if (op.isRotateLeft())
1601 rewriter.replaceOpWithNewOp<mlir::LLVM::FshlOp>(op, input, input,
1602 adaptor.getAmount());
1604 rewriter.replaceOpWithNewOp<mlir::LLVM::FshrOp>(op, input, input,
1605 adaptor.getAmount());
1606 return mlir::LogicalResult::success();
1609static mlir::LogicalResult
1611 mlir::ConversionPatternRewriter &rewriter,
1612 const mlir::TypeConverter *converter,
1613 mlir::FlatSymbolRefAttr calleeAttr) {
1615 mlir::ValueTypeRange<mlir::ResultRange> cirResults = op->getResultTypes();
1616 auto call = cast<cir::CIRCallOpInterface>(op);
1618 if (converter->convertTypes(cirResults, llvmResults).failed())
1619 return mlir::failure();
1623 mlir::LLVM::MemoryEffectsAttr memoryEffects;
1624 bool noUnwind =
false;
1625 bool willReturn =
false;
1626 bool noReturn =
false;
1628 memoryEffects, noUnwind, willReturn, noReturn);
1630 mlir::LLVM::LLVMFunctionType llvmFnTy;
1637 mlir::Operation *callee =
1638 mlir::SymbolTable::lookupNearestSymbolFrom(op, calleeAttr);
1639 if (
auto fn = mlir::dyn_cast<mlir::FunctionOpInterface>(callee)) {
1640 llvmFnTy = converter->convertType<mlir::LLVM::LLVMFunctionType>(
1641 fn.getFunctionType());
1642 assert(llvmFnTy &&
"Failed to convert function type");
1643 }
else if (
auto alias = mlir::cast<mlir::LLVM::AliasOp>(callee)) {
1651 auto symAttr = mlir::cast<mlir::FlatSymbolRefAttr>(calleeAttr);
1653 mlir::LLVM::AddressOfOp::create(
1654 rewriter, op->getLoc(),
1655 mlir::LLVM::LLVMPointerType::get(rewriter.getContext()), symAttr)
1657 adjustedCallOperands.push_back(addrOfAlias);
1660 llvm::append_range(adjustedCallOperands, callOperands);
1661 callOperands = adjustedCallOperands;
1665 llvmFnTy = mlir::cast<mlir::LLVM::LLVMFunctionType>(alias.getType());
1668 return op->emitError(
"Unexpected callee type!");
1671 assert(!op->getOperands().empty() &&
1672 "operands list must no be empty for the indirect call");
1673 auto calleeTy = op->getOperands().front().getType();
1674 auto calleePtrTy = cast<cir::PointerType>(calleeTy);
1675 auto calleeFuncTy = cast<cir::FuncType>(calleePtrTy.getPointee());
1676 llvm::append_range(adjustedCallOperands, callOperands);
1677 llvmFnTy = cast<mlir::LLVM::LLVMFunctionType>(
1678 converter->convertType(calleeFuncTy));
1685 auto newOp = rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(
1686 op, llvmFnTy, calleeAttr, callOperands);
1688 newOp.setMemoryEffectsAttr(memoryEffects);
1689 newOp.setNoUnwind(noUnwind);
1690 newOp.setWillReturn(willReturn);
1691 newOp.setNoreturn(noReturn);
1693 return mlir::success();
1696mlir::LogicalResult CIRToLLVMCallOpLowering::matchAndRewrite(
1697 cir::CallOp op, OpAdaptor adaptor,
1698 mlir::ConversionPatternRewriter &rewriter)
const {
1700 getTypeConverter(), op.getCalleeAttr());
1703mlir::LogicalResult CIRToLLVMReturnAddrOpLowering::matchAndRewrite(
1704 cir::ReturnAddrOp op, OpAdaptor adaptor,
1705 mlir::ConversionPatternRewriter &rewriter)
const {
1706 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
1708 llvmPtrTy, adaptor.getOperands());
1709 return mlir::success();
1712mlir::LogicalResult CIRToLLVMFrameAddrOpLowering::matchAndRewrite(
1713 cir::FrameAddrOp op, OpAdaptor adaptor,
1714 mlir::ConversionPatternRewriter &rewriter)
const {
1715 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
1717 adaptor.getOperands());
1718 return mlir::success();
1721mlir::LogicalResult CIRToLLVMAddrOfReturnAddrOpLowering::matchAndRewrite(
1722 cir::AddrOfReturnAddrOp op, OpAdaptor adaptor,
1723 mlir::ConversionPatternRewriter &rewriter)
const {
1724 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
1726 llvmPtrTy, adaptor.getOperands());
1727 return mlir::success();
1730mlir::LogicalResult CIRToLLVMLoadOpLowering::matchAndRewrite(
1731 cir::LoadOp op, OpAdaptor adaptor,
1732 mlir::ConversionPatternRewriter &rewriter)
const {
1733 const mlir::Type llvmTy =
1735 mlir::LLVM::AtomicOrdering ordering =
getLLVMMemOrder(op.getMemOrder());
1736 std::optional<size_t> opAlign = op.getAlignment();
1737 unsigned alignment =
1738 (unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmTy));
1745 std::optional<std::string> llvmSyncScope;
1746 if (std::optional<cir::SyncScopeKind> syncScope = op.getSyncScope())
1748 lowerMod->getTargetLoweringInfo().getLLVMSyncScope(*syncScope);
1750 mlir::LLVM::LoadOp newLoad = mlir::LLVM::LoadOp::create(
1751 rewriter, op->getLoc(), llvmTy, adaptor.getAddr(), alignment,
1752 op.getIsVolatile(),
false,
1753 false,
false, ordering,
1754 llvmSyncScope.value_or(std::string()));
1757 mlir::Value result =
1759 rewriter.replaceOp(op, result);
1761 return mlir::LogicalResult::success();
1764mlir::LogicalResult CIRToLLVMStoreOpLowering::matchAndRewrite(
1765 cir::StoreOp op, OpAdaptor adaptor,
1766 mlir::ConversionPatternRewriter &rewriter)
const {
1767 mlir::LLVM::AtomicOrdering memorder =
getLLVMMemOrder(op.getMemOrder());
1768 const mlir::Type llvmTy =
1769 getTypeConverter()->convertType(op.getValue().getType());
1770 std::optional<size_t> opAlign = op.getAlignment();
1771 unsigned alignment =
1772 (unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmTy));
1778 op.getValue().getType(), adaptor.getValue());
1783 std::optional<std::string> llvmSyncScope;
1784 if (std::optional<cir::SyncScopeKind> syncScope = op.getSyncScope())
1786 lowerMod->getTargetLoweringInfo().getLLVMSyncScope(*syncScope);
1788 mlir::LLVM::StoreOp storeOp = mlir::LLVM::StoreOp::create(
1789 rewriter, op->getLoc(), value, adaptor.getAddr(), alignment,
1791 false,
false, memorder,
1792 llvmSyncScope.value_or(std::string()));
1793 rewriter.replaceOp(op, storeOp);
1795 return mlir::LogicalResult::success();
1799 auto array = mlir::dyn_cast<mlir::ArrayAttr>(attr.getElts());
1800 return attr.hasTrailingZeros() ||
1801 (array && std::count_if(array.begin(), array.end(), [](
auto elt) {
1802 auto ar = dyn_cast<cir::ConstArrayAttr>(elt);
1803 return ar && hasTrailingZeros(ar);
1807mlir::LogicalResult CIRToLLVMConstantOpLowering::matchAndRewrite(
1808 cir::ConstantOp op, OpAdaptor adaptor,
1809 mlir::ConversionPatternRewriter &rewriter)
const {
1810 mlir::Attribute attr = op.getValue();
1812 if (mlir::isa<cir::PoisonAttr>(attr)) {
1813 rewriter.replaceOpWithNewOp<mlir::LLVM::PoisonOp>(
1814 op, getTypeConverter()->convertType(op.getType()));
1815 return mlir::success();
1818 if (mlir::isa<mlir::IntegerType>(op.getType())) {
1823 attr = op.getValue();
1824 }
else if (mlir::isa<cir::BoolType>(op.getType())) {
1825 int value = mlir::cast<cir::BoolAttr>(op.getValue()).getValue();
1826 attr = rewriter.getIntegerAttr(typeConverter->convertType(op.getType()),
1828 }
else if (mlir::isa<cir::IntType>(op.getType())) {
1830 if (
auto ga = mlir::dyn_cast<cir::GlobalViewAttr>(op.getValue())) {
1836 op.emitError() <<
"global view with integer type";
1837 return mlir::failure();
1840 attr = rewriter.getIntegerAttr(
1841 typeConverter->convertType(op.getType()),
1842 mlir::cast<cir::IntAttr>(op.getValue()).getValue());
1843 }
else if (mlir::isa<cir::FPTypeInterface>(op.getType())) {
1844 attr = rewriter.getFloatAttr(
1845 typeConverter->convertType(op.getType()),
1846 mlir::cast<cir::FPAttr>(op.getValue()).getValue());
1847 }
else if (mlir::isa<cir::PointerType>(op.getType())) {
1849 if (mlir::isa<cir::ConstPtrAttr>(op.getValue())) {
1850 if (mlir::cast<cir::ConstPtrAttr>(op.getValue()).isNullValue()) {
1851 rewriter.replaceOpWithNewOp<mlir::LLVM::ZeroOp>(
1852 op, typeConverter->convertType(op.getType()));
1853 return mlir::success();
1857 if (
auto gv = mlir::dyn_cast<cir::GlobalViewAttr>(op.getValue())) {
1860 rewriter.replaceOp(op, newOp);
1861 return mlir::success();
1863 attr = op.getValue();
1864 }
else if (
const auto arrTy = mlir::dyn_cast<cir::ArrayType>(op.getType())) {
1865 const auto constArr = mlir::dyn_cast<cir::ConstArrayAttr>(op.getValue());
1866 if (!constArr && !isa<cir::ZeroAttr, cir::UndefAttr>(op.getValue()))
1867 return op.emitError() <<
"array does not have a constant initializer";
1869 std::optional<mlir::Attribute> denseAttr;
1872 op, constArr, rewriter, getTypeConverter(), lowerMod);
1873 rewriter.replaceOp(op, newOp);
1874 return mlir::success();
1875 }
else if (constArr &&
1877 attr = denseAttr.value();
1880 op, op.getValue(), rewriter, typeConverter, lowerMod);
1881 rewriter.replaceOp(op, initVal);
1882 return mlir::success();
1884 }
else if (
const auto recordAttr =
1885 mlir::dyn_cast<cir::ConstRecordAttr>(op.getValue())) {
1888 rewriter.replaceOp(op, initVal);
1889 return mlir::success();
1890 }
else if (
const auto vecTy = mlir::dyn_cast<cir::VectorType>(op.getType())) {
1892 getTypeConverter(), lowerMod));
1893 return mlir::success();
1894 }
else if (
auto recTy = mlir::dyn_cast<cir::RecordType>(op.getType())) {
1895 if (mlir::isa<cir::ZeroAttr, cir::UndefAttr>(attr)) {
1896 mlir::Value initVal =
1898 rewriter.replaceOp(op, initVal);
1899 return mlir::success();
1901 return op.emitError() <<
"unsupported lowering for record constant type "
1903 }
else if (
auto complexTy = mlir::dyn_cast<cir::ComplexType>(op.getType())) {
1904 mlir::Type complexElemTy = complexTy.getElementType();
1905 mlir::Type complexElemLLVMTy = typeConverter->convertType(complexElemTy);
1907 if (
auto zeroInitAttr = mlir::dyn_cast<cir::ZeroAttr>(op.getValue())) {
1908 mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(complexElemLLVMTy);
1909 mlir::ArrayAttr array = rewriter.getArrayAttr({zeroAttr, zeroAttr});
1910 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
1911 op, getTypeConverter()->convertType(op.getType()), array);
1912 return mlir::success();
1915 auto complexAttr = mlir::cast<cir::ConstComplexAttr>(op.getValue());
1917 mlir::Attribute components[2];
1918 if (mlir::isa<cir::IntType>(complexElemTy)) {
1919 components[0] = rewriter.getIntegerAttr(
1921 mlir::cast<cir::IntAttr>(complexAttr.getReal()).getValue());
1922 components[1] = rewriter.getIntegerAttr(
1924 mlir::cast<cir::IntAttr>(complexAttr.getImag()).getValue());
1926 components[0] = rewriter.getFloatAttr(
1928 mlir::cast<cir::FPAttr>(complexAttr.getReal()).getValue());
1929 components[1] = rewriter.getFloatAttr(
1931 mlir::cast<cir::FPAttr>(complexAttr.getImag()).getValue());
1934 attr = rewriter.getArrayAttr(components);
1936 return op.emitError() <<
"unsupported constant type " << op.getType();
1939 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
1940 op, getTypeConverter()->convertType(op.getType()),
attr);
1942 return mlir::success();
1946 mlir::DataLayout layout(op.getParentOfType<mlir::ModuleOp>());
1948 if (isa<cir::VoidType>(type))
1949 type = cir::IntType::get(type.getContext(), 8,
false);
1950 return llvm::divideCeil(layout.getTypeSizeInBits(type), 8);
1953mlir::LogicalResult CIRToLLVMPrefetchOpLowering::matchAndRewrite(
1954 cir::PrefetchOp op, OpAdaptor adaptor,
1955 mlir::ConversionPatternRewriter &rewriter)
const {
1956 rewriter.replaceOpWithNewOp<mlir::LLVM::Prefetch>(
1957 op, adaptor.getAddr(), adaptor.getIsWrite(), adaptor.getLocality(),
1959 return mlir::success();
1962mlir::LogicalResult CIRToLLVMPtrDiffOpLowering::matchAndRewrite(
1963 cir::PtrDiffOp op, OpAdaptor adaptor,
1964 mlir::ConversionPatternRewriter &rewriter)
const {
1965 auto dstTy = mlir::cast<cir::IntType>(op.getType());
1966 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1968 auto lhs = mlir::LLVM::PtrToIntOp::create(rewriter, op.getLoc(), llvmDstTy,
1970 auto rhs = mlir::LLVM::PtrToIntOp::create(rewriter, op.getLoc(), llvmDstTy,
1974 mlir::LLVM::SubOp::create(rewriter, op.getLoc(), llvmDstTy, lhs, rhs);
1976 cir::PointerType ptrTy = op.getLhs().getType();
1978 uint64_t typeSize =
getTypeSize(ptrTy.getPointee(), *op);
1981 mlir::Value resultVal = diff.getResult();
1982 if (typeSize != 1) {
1983 auto typeSizeVal = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1984 llvmDstTy, typeSize);
1986 if (dstTy.isUnsigned()) {
1988 mlir::LLVM::UDivOp::create(rewriter, op.getLoc(), diff, typeSizeVal);
1989 uDiv.setIsExact(
true);
1990 resultVal = uDiv.getResult();
1993 mlir::LLVM::SDivOp::create(rewriter, op.getLoc(), diff, typeSizeVal);
1994 sDiv.setIsExact(
true);
1995 resultVal = sDiv.getResult();
1998 rewriter.replaceOp(op, resultVal);
1999 return mlir::success();
2002mlir::LogicalResult CIRToLLVMExpectOpLowering::matchAndRewrite(
2003 cir::ExpectOp op, OpAdaptor adaptor,
2004 mlir::ConversionPatternRewriter &rewriter)
const {
2008 std::optional<llvm::APFloat> prob = op.getProb();
2010 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpectWithProbabilityOp>(
2011 op, adaptor.getVal(), adaptor.getExpected(), prob.value());
2013 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpectOp>(op, adaptor.getVal(),
2014 adaptor.getExpected());
2015 return mlir::success();
2018mlir::LogicalResult CIRToLLVMFAbsOpLowering::matchAndRewrite(
2019 cir::FAbsOp op, OpAdaptor adaptor,
2020 mlir::ConversionPatternRewriter &rewriter)
const {
2021 mlir::Type resTy = typeConverter->convertType(op.getType());
2022 rewriter.replaceOpWithNewOp<mlir::LLVM::FAbsOp>(op, resTy,
2023 adaptor.getOperands()[0]);
2024 return mlir::success();
2031void CIRToLLVMFuncOpLowering::lowerFuncAttributes(
2032 cir::FuncOp func,
bool filterArgAndResAttrs,
2033 SmallVectorImpl<mlir::NamedAttribute> &result)
const {
2035 for (mlir::NamedAttribute attr : func->getAttrs()) {
2037 if (
attr.getName() == mlir::SymbolTable::getSymbolAttrName() ||
2038 attr.getName() == func.getFunctionTypeAttrName() ||
2040 attr.getName() == func.getGlobalVisibilityAttrName() ||
2041 attr.getName() == func.getDsoLocalAttrName() ||
2042 attr.getName() == func.getInlineKindAttrName() ||
2043 attr.getName() == func.getSideEffectAttrName() ||
2044 attr.getName() == CIRDialect::getNoReturnAttrName() ||
2045 (filterArgAndResAttrs &&
2046 (
attr.getName() == func.getArgAttrsAttrName() ||
2047 attr.getName() == func.getResAttrsAttrName())))
2051 result.push_back(attr);
2055mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewriteAlias(
2056 cir::FuncOp op, llvm::StringRef aliasee, mlir::Type ty, OpAdaptor adaptor,
2057 mlir::ConversionPatternRewriter &rewriter)
const {
2058 SmallVector<mlir::NamedAttribute, 4> attributes;
2059 lowerFuncAttributes(op,
false, attributes);
2061 mlir::Location loc = op.getLoc();
2062 auto aliasOp = rewriter.replaceOpWithNewOp<mlir::LLVM::AliasOp>(
2063 op, ty,
convertLinkage(op.getLinkage()), op.getName(), op.getDsoLocal(),
2067 mlir::OpBuilder builder(op.getContext());
2068 mlir::Block *block = builder.createBlock(&aliasOp.getInitializerRegion());
2069 builder.setInsertionPointToStart(block);
2072 mlir::Type ptrTy = mlir::LLVM::LLVMPointerType::get(ty.getContext());
2073 auto addrOp = mlir::LLVM::AddressOfOp::create(builder, loc, ptrTy, aliasee);
2074 mlir::LLVM::ReturnOp::create(builder, loc, addrOp);
2076 return mlir::success();
2079mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewrite(
2080 cir::FuncOp op, OpAdaptor adaptor,
2081 mlir::ConversionPatternRewriter &rewriter)
const {
2083 cir::FuncType fnType = op.getFunctionType();
2084 bool isDsoLocal = op.getDsoLocal();
2085 mlir::TypeConverter::SignatureConversion signatureConversion(
2086 fnType.getNumInputs());
2088 for (
const auto &argType : llvm::enumerate(fnType.getInputs())) {
2089 mlir::Type convertedType = typeConverter->convertType(argType.value());
2091 return mlir::failure();
2092 signatureConversion.addInputs(argType.index(), convertedType);
2095 mlir::Type resultType =
2096 getTypeConverter()->convertType(fnType.getReturnType());
2099 mlir::Type llvmFnTy = mlir::LLVM::LLVMFunctionType::get(
2100 resultType ? resultType : mlir::LLVM::LLVMVoidType::get(getContext()),
2101 signatureConversion.getConvertedTypes(),
2105 if (std::optional<llvm::StringRef> aliasee = op.getAliasee())
2106 return matchAndRewriteAlias(op, *aliasee, llvmFnTy, adaptor, rewriter);
2110 mlir::Location loc = op.getLoc();
2111 if (mlir::FusedLoc fusedLoc = mlir::dyn_cast<mlir::FusedLoc>(loc))
2112 loc = fusedLoc.getLocations()[0];
2113 assert((mlir::isa<mlir::FileLineColLoc>(loc) ||
2114 mlir::isa<mlir::UnknownLoc>(loc)) &&
2115 "expected single location or unknown location here");
2119 mlir::LLVM::CConv cconv = mlir::LLVM::CConv::C;
2120 SmallVector<mlir::NamedAttribute, 4> attributes;
2121 lowerFuncAttributes(op,
false, attributes);
2123 mlir::LLVM::LLVMFuncOp fn = mlir::LLVM::LLVMFuncOp::create(
2124 rewriter, loc, op.getName(), llvmFnTy, linkage, isDsoLocal, cconv,
2125 mlir::SymbolRefAttr(), attributes);
2129 if (std::optional<cir::SideEffect> sideEffectKind = op.getSideEffect()) {
2130 switch (*sideEffectKind) {
2131 case cir::SideEffect::All:
2133 case cir::SideEffect::Pure:
2134 fn.setMemoryEffectsAttr(mlir::LLVM::MemoryEffectsAttr::get(
2136 mlir::LLVM::ModRefInfo::Ref,
2137 mlir::LLVM::ModRefInfo::Ref,
2138 mlir::LLVM::ModRefInfo::Ref,
2139 mlir::LLVM::ModRefInfo::Ref,
2140 mlir::LLVM::ModRefInfo::Ref,
2141 mlir::LLVM::ModRefInfo::Ref));
2142 fn.setNoUnwind(
true);
2143 fn.setWillReturn(
true);
2145 case cir::SideEffect::Const:
2146 fn.setMemoryEffectsAttr(mlir::LLVM::MemoryEffectsAttr::get(
2148 mlir::LLVM::ModRefInfo::NoModRef,
2149 mlir::LLVM::ModRefInfo::NoModRef,
2150 mlir::LLVM::ModRefInfo::NoModRef,
2151 mlir::LLVM::ModRefInfo::NoModRef,
2152 mlir::LLVM::ModRefInfo::NoModRef,
2153 mlir::LLVM::ModRefInfo::NoModRef));
2154 fn.setNoUnwind(
true);
2155 fn.setWillReturn(
true);
2160 if (op->hasAttr(CIRDialect::getNoReturnAttrName()))
2161 fn.setNoreturn(
true);
2163 if (std::optional<cir::InlineKind> inlineKind = op.getInlineKind()) {
2164 fn.setNoInline(*inlineKind == cir::InlineKind::NoInline);
2165 fn.setInlineHint(*inlineKind == cir::InlineKind::InlineHint);
2166 fn.setAlwaysInline(*inlineKind == cir::InlineKind::AlwaysInline);
2169 if (std::optional<llvm::StringRef> personality = op.getPersonality())
2170 fn.setPersonality(*personality);
2175 rewriter.inlineRegionBefore(op.getBody(), fn.getBody(), fn.end());
2176 if (failed(rewriter.convertRegionTypes(&fn.getBody(), *typeConverter,
2177 &signatureConversion)))
2178 return mlir::failure();
2180 rewriter.eraseOp(op);
2182 return mlir::LogicalResult::success();
2185mlir::LogicalResult CIRToLLVMGetGlobalOpLowering::matchAndRewrite(
2186 cir::GetGlobalOp op, OpAdaptor adaptor,
2187 mlir::ConversionPatternRewriter &rewriter)
const {
2190 if (op->getUses().empty()) {
2191 rewriter.eraseOp(op);
2192 return mlir::success();
2195 mlir::Type
type = getTypeConverter()->convertType(op.getType());
2196 mlir::Operation *newop = mlir::LLVM::AddressOfOp::create(
2197 rewriter, op.getLoc(), type, op.getName());
2201 newop = mlir::LLVM::ThreadlocalAddressOp::create(rewriter, op.getLoc(),
2202 type, newop->getResult(0));
2205 rewriter.replaceOp(op, newop);
2206 return mlir::success();
2211void CIRToLLVMGlobalOpLowering::setupRegionInitializedLLVMGlobalOp(
2212 cir::GlobalOp op, mlir::ConversionPatternRewriter &rewriter)
const {
2213 const mlir::Type llvmType =
2220 const bool isConst = op.getConstant();
2222 const unsigned addrSpace = 0;
2223 const bool isDsoLocal = op.getDsoLocal();
2224 const bool isThreadLocal = (
bool)op.getTlsModelAttr();
2225 const uint64_t alignment = op.getAlignment().value_or(0);
2226 const mlir::LLVM::Linkage linkage =
convertLinkage(op.getLinkage());
2227 const StringRef symbol = op.getSymName();
2228 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
2230 SmallVector<mlir::NamedAttribute> attributes;
2231 mlir::LLVM::GlobalOp newGlobalOp =
2232 rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
2233 op, llvmType, isConst, linkage, symbol,
nullptr, alignment, addrSpace,
2234 isDsoLocal, isThreadLocal, comdatAttr, attributes);
2235 newGlobalOp.getRegion().emplaceBlock();
2236 rewriter.setInsertionPointToEnd(newGlobalOp.getInitializerBlock());
2240CIRToLLVMGlobalOpLowering::matchAndRewriteRegionInitializedGlobal(
2241 cir::GlobalOp op, mlir::Attribute init,
2242 mlir::ConversionPatternRewriter &rewriter)
const {
2245 (isa<cir::ConstArrayAttr, cir::ConstRecordAttr, cir::ConstVectorAttr,
2246 cir::ConstPtrAttr, cir::ConstComplexAttr, cir::GlobalViewAttr,
2247 cir::TypeInfoAttr, cir::UndefAttr, cir::VTableAttr, cir::ZeroAttr>(
2253 const mlir::Location loc = op.getLoc();
2254 setupRegionInitializedLLVMGlobalOp(op, rewriter);
2255 CIRAttrToValue valueConverter(op, rewriter, typeConverter, lowerMod);
2256 mlir::Value value = valueConverter.visit(init);
2257 mlir::LLVM::ReturnOp::create(rewriter, loc, value);
2258 return mlir::success();
2261mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite(
2262 cir::GlobalOp op, OpAdaptor adaptor,
2263 mlir::ConversionPatternRewriter &rewriter)
const {
2266 if (!op.getCtorRegion().empty() || !op.getDtorRegion().empty())
2267 return op.emitError() <<
"GlobalOp ctor and dtor regions should be removed "
2268 "in LoweringPrepare";
2270 std::optional<mlir::Attribute> init = op.getInitialValue();
2273 const mlir::Type cirSymType = op.getSymType();
2276 const mlir::Type llvmType =
2280 const bool isConst = op.getConstant();
2282 const unsigned addrSpace = 0;
2283 const bool isDsoLocal = op.getDsoLocal();
2284 const bool isThreadLocal = (
bool)op.getTlsModelAttr();
2285 const uint64_t alignment = op.getAlignment().value_or(0);
2286 const mlir::LLVM::Linkage linkage =
convertLinkage(op.getLinkage());
2287 const StringRef symbol = op.getSymName();
2288 SmallVector<mlir::NamedAttribute> attributes;
2290 if (init.has_value()) {
2291 if (mlir::isa<cir::FPAttr, cir::IntAttr, cir::BoolAttr>(init.value())) {
2293 init = initRewriter.visit(init.value());
2298 if (!init.value()) {
2299 op.emitError() <<
"unsupported initializer '" << init.value() <<
"'";
2300 return mlir::failure();
2302 }
else if (mlir::isa<cir::ConstArrayAttr, cir::ConstVectorAttr,
2303 cir::ConstRecordAttr, cir::ConstPtrAttr,
2304 cir::ConstComplexAttr, cir::GlobalViewAttr,
2305 cir::TypeInfoAttr, cir::UndefAttr, cir::VTableAttr,
2306 cir::ZeroAttr>(init.value())) {
2310 return matchAndRewriteRegionInitializedGlobal(op, init.value(), rewriter);
2314 op.emitError() <<
"unsupported initializer '" << init.value() <<
"'";
2315 return mlir::failure();
2319 mlir::LLVM::Visibility visibility =
2321 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
2322 auto newOp = rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
2323 op, llvmType, isConst, linkage, symbol, init.value_or(mlir::Attribute()),
2324 alignment, addrSpace, isDsoLocal, isThreadLocal, comdatAttr, attributes);
2325 newOp.setVisibility_(visibility);
2327 return mlir::success();
2331CIRToLLVMGlobalOpLowering::getComdatAttr(cir::GlobalOp &op,
2332 mlir::OpBuilder &builder)
const {
2333 if (!op.getComdat())
2334 return mlir::SymbolRefAttr{};
2336 mlir::ModuleOp module = op->getParentOfType<mlir::ModuleOp>();
2337 mlir::OpBuilder::InsertionGuard guard(builder);
2338 StringRef comdatName(
"__llvm_comdat_globals");
2340 builder.setInsertionPointToStart(module.getBody());
2342 mlir::LLVM::ComdatOp::create(builder, module.getLoc(), comdatName);
2345 if (
auto comdatSelector = comdatOp.lookupSymbol<mlir::LLVM::ComdatSelectorOp>(
2347 return mlir::SymbolRefAttr::get(
2348 builder.getContext(), comdatName,
2349 mlir::FlatSymbolRefAttr::get(comdatSelector.getSymNameAttr()));
2352 builder.setInsertionPointToStart(&comdatOp.getBody().back());
2353 auto selectorOp = mlir::LLVM::ComdatSelectorOp::create(
2354 builder, comdatOp.getLoc(), op.getSymName(),
2355 mlir::LLVM::comdat::Comdat::Any);
2356 return mlir::SymbolRefAttr::get(
2357 builder.getContext(), comdatName,
2358 mlir::FlatSymbolRefAttr::get(selectorOp.getSymNameAttr()));
2361mlir::LogicalResult CIRToLLVMSwitchFlatOpLowering::matchAndRewrite(
2362 cir::SwitchFlatOp op, OpAdaptor adaptor,
2363 mlir::ConversionPatternRewriter &rewriter)
const {
2365 llvm::SmallVector<mlir::APInt, 8> caseValues;
2366 for (mlir::Attribute val : op.getCaseValues()) {
2367 auto intAttr = cast<cir::IntAttr>(val);
2368 caseValues.push_back(intAttr.getValue());
2371 llvm::SmallVector<mlir::Block *, 8> caseDestinations;
2372 llvm::SmallVector<mlir::ValueRange, 8> caseOperands;
2374 for (mlir::Block *x : op.getCaseDestinations())
2375 caseDestinations.push_back(x);
2377 for (mlir::OperandRange x : op.getCaseOperands())
2378 caseOperands.push_back(x);
2381 rewriter.setInsertionPoint(op);
2382 rewriter.replaceOpWithNewOp<mlir::LLVM::SwitchOp>(
2383 op, adaptor.getCondition(), op.getDefaultDestination(),
2384 op.getDefaultOperands(), caseValues, caseDestinations, caseOperands);
2385 return mlir::success();
2388mlir::LogicalResult CIRToLLVMUnaryOpLowering::matchAndRewrite(
2389 cir::UnaryOp op, OpAdaptor adaptor,
2390 mlir::ConversionPatternRewriter &rewriter)
const {
2391 assert(op.getType() == op.getInput().getType() &&
2392 "Unary operation's operand type and result type are different");
2393 mlir::Type
type = op.getType();
2394 mlir::Type elementType = elementTypeIfVector(type);
2395 bool isVector = mlir::isa<cir::VectorType>(type);
2396 mlir::Type llvmType = getTypeConverter()->convertType(type);
2397 mlir::Location loc = op.getLoc();
2400 if (mlir::isa<cir::IntType>(elementType)) {
2401 mlir::LLVM::IntegerOverflowFlags maybeNSW =
2402 op.getNoSignedWrap() ? mlir::LLVM::IntegerOverflowFlags::nsw
2403 : mlir::LLVM::IntegerOverflowFlags::none;
2404 switch (op.getKind()) {
2405 case cir::UnaryOpKind::Inc: {
2406 assert(!
isVector &&
"++ not allowed on vector types");
2407 auto one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
2408 rewriter.replaceOpWithNewOp<mlir::LLVM::AddOp>(
2409 op, llvmType, adaptor.getInput(), one, maybeNSW);
2410 return mlir::success();
2412 case cir::UnaryOpKind::Dec: {
2413 assert(!
isVector &&
"-- not allowed on vector types");
2414 auto one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
2415 rewriter.replaceOpWithNewOp<mlir::LLVM::SubOp>(op, adaptor.getInput(),
2417 return mlir::success();
2419 case cir::UnaryOpKind::Plus:
2420 rewriter.replaceOp(op, adaptor.getInput());
2421 return mlir::success();
2422 case cir::UnaryOpKind::Minus: {
2425 zero = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmType);
2427 zero = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 0);
2428 rewriter.replaceOpWithNewOp<mlir::LLVM::SubOp>(
2429 op, zero, adaptor.getInput(), maybeNSW);
2430 return mlir::success();
2432 case cir::UnaryOpKind::Not: {
2434 mlir::Value minusOne;
2437 mlir::dyn_cast<cir::VectorType>(type).getSize();
2438 std::vector<int32_t> values(numElements, -1);
2439 mlir::DenseIntElementsAttr denseVec = rewriter.getI32VectorAttr(values);
2441 mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, denseVec);
2443 minusOne = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, -1);
2445 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getInput(),
2447 return mlir::success();
2450 llvm_unreachable(
"Unexpected unary op for int");
2454 if (mlir::isa<cir::FPTypeInterface>(elementType)) {
2455 switch (op.getKind()) {
2456 case cir::UnaryOpKind::Inc: {
2457 assert(!
isVector &&
"++ not allowed on vector types");
2458 mlir::LLVM::ConstantOp one = mlir::LLVM::ConstantOp::create(
2459 rewriter, loc, llvmType, rewriter.getFloatAttr(llvmType, 1.0));
2460 rewriter.replaceOpWithNewOp<mlir::LLVM::FAddOp>(op, llvmType, one,
2461 adaptor.getInput());
2462 return mlir::success();
2464 case cir::UnaryOpKind::Dec: {
2465 assert(!
isVector &&
"-- not allowed on vector types");
2466 mlir::LLVM::ConstantOp minusOne = mlir::LLVM::ConstantOp::create(
2467 rewriter, loc, llvmType, rewriter.getFloatAttr(llvmType, -1.0));
2468 rewriter.replaceOpWithNewOp<mlir::LLVM::FAddOp>(op, llvmType, minusOne,
2469 adaptor.getInput());
2470 return mlir::success();
2472 case cir::UnaryOpKind::Plus:
2473 rewriter.replaceOp(op, adaptor.getInput());
2474 return mlir::success();
2475 case cir::UnaryOpKind::Minus:
2476 rewriter.replaceOpWithNewOp<mlir::LLVM::FNegOp>(op, llvmType,
2477 adaptor.getInput());
2478 return mlir::success();
2479 case cir::UnaryOpKind::Not:
2480 return op.emitError() <<
"Unary not is invalid for floating-point types";
2482 llvm_unreachable(
"Unexpected unary op for float");
2487 if (mlir::isa<cir::BoolType>(elementType)) {
2488 switch (op.getKind()) {
2489 case cir::UnaryOpKind::Inc:
2490 case cir::UnaryOpKind::Dec:
2491 case cir::UnaryOpKind::Plus:
2492 case cir::UnaryOpKind::Minus:
2495 return op.emitError() <<
"Unsupported unary operation on boolean type";
2496 case cir::UnaryOpKind::Not: {
2497 assert(!
isVector &&
"NYI: op! on vector mask");
2498 auto one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
2499 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getInput(),
2501 return mlir::success();
2504 llvm_unreachable(
"Unexpected unary op for bool");
2509 if (mlir::isa<cir::PointerType>(elementType)) {
2510 switch (op.getKind()) {
2511 case cir::UnaryOpKind::Plus:
2512 rewriter.replaceOp(op, adaptor.getInput());
2513 return mlir::success();
2515 op.emitError() <<
"Unknown pointer unary operation during CIR lowering";
2516 return mlir::failure();
2520 return op.emitError() <<
"Unary operation has unsupported type: "
2524mlir::LLVM::IntegerOverflowFlags
2525CIRToLLVMBinOpLowering::getIntOverflowFlag(cir::BinOp op)
const {
2526 if (op.getNoUnsignedWrap())
2527 return mlir::LLVM::IntegerOverflowFlags::nuw;
2529 if (op.getNoSignedWrap())
2530 return mlir::LLVM::IntegerOverflowFlags::nsw;
2532 return mlir::LLVM::IntegerOverflowFlags::none;
2537 return mlir::isa<cir::IntType>(type)
2538 ? mlir::cast<cir::IntType>(type).isUnsigned()
2539 : mlir::cast<mlir::IntegerType>(type).isUnsigned();
2542mlir::LogicalResult CIRToLLVMBinOpLowering::matchAndRewrite(
2543 cir::BinOp op, OpAdaptor adaptor,
2544 mlir::ConversionPatternRewriter &rewriter)
const {
2545 if (adaptor.getLhs().getType() != adaptor.getRhs().getType())
2546 return op.emitError() <<
"inconsistent operands' types not supported yet";
2548 mlir::Type type = op.getRhs().getType();
2549 if (!mlir::isa<cir::IntType, cir::BoolType, cir::FPTypeInterface,
2550 mlir::IntegerType, cir::VectorType>(type))
2551 return op.emitError() <<
"operand type not supported yet";
2553 const mlir::Type llvmTy = getTypeConverter()->convertType(op.getType());
2554 const mlir::Type llvmEltTy = elementTypeIfVector(llvmTy);
2556 const mlir::Value rhs = adaptor.getRhs();
2557 const mlir::Value lhs = adaptor.getLhs();
2558 type = elementTypeIfVector(type);
2560 switch (op.getKind()) {
2561 case cir::BinOpKind::Add:
2562 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
2563 if (op.getSaturated()) {
2565 rewriter.replaceOpWithNewOp<mlir::LLVM::UAddSat>(op, lhs, rhs);
2568 rewriter.replaceOpWithNewOp<mlir::LLVM::SAddSat>(op, lhs, rhs);
2571 rewriter.replaceOpWithNewOp<mlir::LLVM::AddOp>(op, llvmTy, lhs, rhs,
2572 getIntOverflowFlag(op));
2574 rewriter.replaceOpWithNewOp<mlir::LLVM::FAddOp>(op, lhs, rhs);
2577 case cir::BinOpKind::Sub:
2578 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
2579 if (op.getSaturated()) {
2581 rewriter.replaceOpWithNewOp<mlir::LLVM::USubSat>(op, lhs, rhs);
2584 rewriter.replaceOpWithNewOp<mlir::LLVM::SSubSat>(op, lhs, rhs);
2587 rewriter.replaceOpWithNewOp<mlir::LLVM::SubOp>(op, llvmTy, lhs, rhs,
2588 getIntOverflowFlag(op));
2590 rewriter.replaceOpWithNewOp<mlir::LLVM::FSubOp>(op, lhs, rhs);
2593 case cir::BinOpKind::Mul:
2594 if (mlir::isa<mlir::IntegerType>(llvmEltTy))
2595 rewriter.replaceOpWithNewOp<mlir::LLVM::MulOp>(op, llvmTy, lhs, rhs,
2596 getIntOverflowFlag(op));
2598 rewriter.replaceOpWithNewOp<mlir::LLVM::FMulOp>(op, lhs, rhs);
2600 case cir::BinOpKind::Div:
2601 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
2604 rewriter.replaceOpWithNewOp<mlir::LLVM::UDivOp>(op, lhs, rhs);
2606 rewriter.replaceOpWithNewOp<mlir::LLVM::SDivOp>(op, lhs, rhs);
2608 rewriter.replaceOpWithNewOp<mlir::LLVM::FDivOp>(op, lhs, rhs);
2611 case cir::BinOpKind::Rem:
2612 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
2615 rewriter.replaceOpWithNewOp<mlir::LLVM::URemOp>(op, lhs, rhs);
2617 rewriter.replaceOpWithNewOp<mlir::LLVM::SRemOp>(op, lhs, rhs);
2619 rewriter.replaceOpWithNewOp<mlir::LLVM::FRemOp>(op, lhs, rhs);
2622 case cir::BinOpKind::And:
2623 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(op, lhs, rhs);
2625 case cir::BinOpKind::Or:
2626 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(op, lhs, rhs);
2628 case cir::BinOpKind::Xor:
2629 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, lhs, rhs);
2631 case cir::BinOpKind::Max:
2632 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
2635 rewriter.replaceOpWithNewOp<mlir::LLVM::UMaxOp>(op, llvmTy, lhs, rhs);
2637 rewriter.replaceOpWithNewOp<mlir::LLVM::SMaxOp>(op, llvmTy, lhs, rhs);
2641 return mlir::LogicalResult::success();
2645static mlir::LLVM::ICmpPredicate
2647 using CIR = cir::CmpOpKind;
2648 using LLVMICmp = mlir::LLVM::ICmpPredicate;
2651 return LLVMICmp::eq;
2653 return LLVMICmp::ne;
2655 return (isSigned ? LLVMICmp::slt : LLVMICmp::ult);
2657 return (isSigned ? LLVMICmp::sle : LLVMICmp::ule);
2659 return (isSigned ? LLVMICmp::sgt : LLVMICmp::ugt);
2661 return (isSigned ? LLVMICmp::sge : LLVMICmp::uge);
2663 llvm_unreachable(
"Unknown CmpOpKind");
2668static mlir::LLVM::FCmpPredicate
2670 using CIR = cir::CmpOpKind;
2671 using LLVMFCmp = mlir::LLVM::FCmpPredicate;
2674 return LLVMFCmp::oeq;
2676 return LLVMFCmp::une;
2678 return LLVMFCmp::olt;
2680 return LLVMFCmp::ole;
2682 return LLVMFCmp::ogt;
2684 return LLVMFCmp::oge;
2686 llvm_unreachable(
"Unknown CmpOpKind");
2689mlir::LogicalResult CIRToLLVMCmpOpLowering::matchAndRewrite(
2690 cir::CmpOp cmpOp, OpAdaptor adaptor,
2691 mlir::ConversionPatternRewriter &rewriter)
const {
2692 mlir::Type type = cmpOp.getLhs().getType();
2694 if (mlir::isa<cir::IntType, mlir::IntegerType>(type)) {
2695 bool isSigned = mlir::isa<cir::IntType>(type)
2696 ? mlir::cast<cir::IntType>(type).isSigned()
2697 : mlir::cast<mlir::IntegerType>(type).isSigned();
2698 mlir::LLVM::ICmpPredicate
kind =
2700 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
2701 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
2702 return mlir::success();
2705 if (
auto ptrTy = mlir::dyn_cast<cir::PointerType>(type)) {
2706 mlir::LLVM::ICmpPredicate
kind =
2709 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
2710 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
2711 return mlir::success();
2714 if (
auto vptrTy = mlir::dyn_cast<cir::VPtrType>(type)) {
2718 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
2719 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
2720 return mlir::success();
2723 if (mlir::isa<cir::FPTypeInterface>(type)) {
2724 mlir::LLVM::FCmpPredicate
kind =
2726 rewriter.replaceOpWithNewOp<mlir::LLVM::FCmpOp>(
2727 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
2728 return mlir::success();
2731 if (mlir::isa<cir::ComplexType>(type)) {
2732 mlir::Value lhs = adaptor.getLhs();
2733 mlir::Value rhs = adaptor.getRhs();
2734 mlir::Location loc = cmpOp.getLoc();
2736 auto complexType = mlir::cast<cir::ComplexType>(cmpOp.getLhs().getType());
2737 mlir::Type complexElemTy =
2738 getTypeConverter()->convertType(
complexType.getElementType());
2740 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
2741 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{0}));
2742 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
2743 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{1}));
2744 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
2745 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{0}));
2746 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
2747 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{1}));
2749 if (cmpOp.getKind() == cir::CmpOpKind::eq) {
2750 if (complexElemTy.isInteger()) {
2751 auto realCmp = mlir::LLVM::ICmpOp::create(
2752 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, lhsReal, rhsReal);
2753 auto imagCmp = mlir::LLVM::ICmpOp::create(
2754 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, lhsImag, rhsImag);
2755 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, imagCmp);
2756 return mlir::success();
2759 auto realCmp = mlir::LLVM::FCmpOp::create(
2760 rewriter, loc, mlir::LLVM::FCmpPredicate::oeq, lhsReal, rhsReal);
2761 auto imagCmp = mlir::LLVM::FCmpOp::create(
2762 rewriter, loc, mlir::LLVM::FCmpPredicate::oeq, lhsImag, rhsImag);
2763 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, imagCmp);
2764 return mlir::success();
2767 if (cmpOp.getKind() == cir::CmpOpKind::ne) {
2768 if (complexElemTy.isInteger()) {
2769 auto realCmp = mlir::LLVM::ICmpOp::create(
2770 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, lhsReal, rhsReal);
2771 auto imagCmp = mlir::LLVM::ICmpOp::create(
2772 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, lhsImag, rhsImag);
2773 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp);
2774 return mlir::success();
2777 auto realCmp = mlir::LLVM::FCmpOp::create(
2778 rewriter, loc, mlir::LLVM::FCmpPredicate::une, lhsReal, rhsReal);
2779 auto imagCmp = mlir::LLVM::FCmpOp::create(
2780 rewriter, loc, mlir::LLVM::FCmpPredicate::une, lhsImag, rhsImag);
2781 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp);
2782 return mlir::success();
2786 return cmpOp.emitError() <<
"unsupported type for CmpOp: " <<
type;
2789mlir::LogicalResult CIRToLLVMBinOpOverflowOpLowering::matchAndRewrite(
2790 cir::BinOpOverflowOp op, OpAdaptor adaptor,
2791 mlir::ConversionPatternRewriter &rewriter)
const {
2792 mlir::Location loc = op.getLoc();
2793 cir::BinOpOverflowKind arithKind = op.getKind();
2794 cir::IntType operandTy = op.getLhs().getType();
2795 cir::IntType resultTy = op.getResult().getType();
2797 EncompassedTypeInfo encompassedTyInfo =
2798 computeEncompassedTypeWidth(operandTy, resultTy);
2799 mlir::IntegerType encompassedLLVMTy =
2800 rewriter.getIntegerType(encompassedTyInfo.width);
2802 mlir::Value lhs = adaptor.getLhs();
2803 mlir::Value rhs = adaptor.getRhs();
2804 if (operandTy.getWidth() < encompassedTyInfo.width) {
2805 if (operandTy.isSigned()) {
2806 lhs = mlir::LLVM::SExtOp::create(rewriter, loc, encompassedLLVMTy, lhs);
2807 rhs = mlir::LLVM::SExtOp::create(rewriter, loc, encompassedLLVMTy, rhs);
2809 lhs = mlir::LLVM::ZExtOp::create(rewriter, loc, encompassedLLVMTy, lhs);
2810 rhs = mlir::LLVM::ZExtOp::create(rewriter, loc, encompassedLLVMTy, rhs);
2814 std::string intrinName = getLLVMIntrinName(arithKind, encompassedTyInfo.sign,
2815 encompassedTyInfo.width);
2816 auto intrinNameAttr = mlir::StringAttr::get(op.getContext(), intrinName);
2818 mlir::IntegerType overflowLLVMTy = rewriter.getI1Type();
2819 auto intrinRetTy = mlir::LLVM::LLVMStructType::getLiteral(
2820 rewriter.getContext(), {encompassedLLVMTy, overflowLLVMTy});
2822 auto callLLVMIntrinOp = mlir::LLVM::CallIntrinsicOp::create(
2823 rewriter, loc, intrinRetTy, intrinNameAttr, mlir::ValueRange{lhs, rhs});
2824 mlir::Value intrinRet = callLLVMIntrinOp.getResult(0);
2826 mlir::Value result = mlir::LLVM::ExtractValueOp::create(
2827 rewriter, loc, intrinRet, ArrayRef<int64_t>{0})
2829 mlir::Value overflow = mlir::LLVM::ExtractValueOp::create(
2830 rewriter, loc, intrinRet, ArrayRef<int64_t>{1})
2833 if (resultTy.getWidth() < encompassedTyInfo.width) {
2834 mlir::Type resultLLVMTy = getTypeConverter()->convertType(resultTy);
2836 mlir::LLVM::TruncOp::create(rewriter, loc, resultLLVMTy, result);
2840 mlir::Value truncResultExt;
2841 if (resultTy.isSigned())
2842 truncResultExt = mlir::LLVM::SExtOp::create(
2843 rewriter, loc, encompassedLLVMTy, truncResult);
2845 truncResultExt = mlir::LLVM::ZExtOp::create(
2846 rewriter, loc, encompassedLLVMTy, truncResult);
2847 auto truncOverflow = mlir::LLVM::ICmpOp::create(
2848 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, truncResultExt, result);
2850 result = truncResult;
2851 overflow = mlir::LLVM::OrOp::create(rewriter, loc, overflow, truncOverflow);
2854 mlir::Type boolLLVMTy =
2855 getTypeConverter()->convertType(op.getOverflow().getType());
2856 if (boolLLVMTy != rewriter.getI1Type())
2857 overflow = mlir::LLVM::ZExtOp::create(rewriter, loc, boolLLVMTy, overflow);
2859 rewriter.replaceOp(op, mlir::ValueRange{result, overflow});
2861 return mlir::success();
2864std::string CIRToLLVMBinOpOverflowOpLowering::getLLVMIntrinName(
2865 cir::BinOpOverflowKind opKind,
bool isSigned,
unsigned width) {
2868 std::string
name =
"llvm.";
2871 name.push_back(
's');
2873 name.push_back(
'u');
2876 case cir::BinOpOverflowKind::Add:
2877 name.append(
"add.");
2879 case cir::BinOpOverflowKind::Sub:
2880 name.append(
"sub.");
2882 case cir::BinOpOverflowKind::Mul:
2883 name.append(
"mul.");
2887 name.append(
"with.overflow.i");
2888 name.append(std::to_string(width));
2893CIRToLLVMBinOpOverflowOpLowering::EncompassedTypeInfo
2894CIRToLLVMBinOpOverflowOpLowering::computeEncompassedTypeWidth(
2895 cir::IntType operandTy, cir::IntType resultTy) {
2896 bool sign = operandTy.getIsSigned() || resultTy.getIsSigned();
2898 std::max(operandTy.getWidth() + (
sign && operandTy.isUnsigned()),
2899 resultTy.getWidth() + (
sign && resultTy.isUnsigned()));
2900 return {
sign, width};
2903mlir::LogicalResult CIRToLLVMShiftOpLowering::matchAndRewrite(
2904 cir::ShiftOp op, OpAdaptor adaptor,
2905 mlir::ConversionPatternRewriter &rewriter)
const {
2906 assert((op.getValue().getType() == op.getType()) &&
2907 "inconsistent operands' types NYI");
2909 const mlir::Type llvmTy = getTypeConverter()->convertType(op.getType());
2910 mlir::Value amt = adaptor.getAmount();
2911 mlir::Value val = adaptor.getValue();
2913 auto cirAmtTy = mlir::dyn_cast<cir::IntType>(op.getAmount().getType());
2916 auto cirValTy = mlir::cast<cir::IntType>(op.getValue().getType());
2924 amt =
getLLVMIntCast(rewriter, amt, llvmTy,
true, cirAmtTy.getWidth(),
2925 cirValTy.getWidth());
2927 auto cirValVTy = mlir::cast<cir::VectorType>(op.getValue().getType());
2929 mlir::cast<cir::IntType>(cirValVTy.getElementType()).isUnsigned();
2933 if (op.getIsShiftleft()) {
2934 rewriter.replaceOpWithNewOp<mlir::LLVM::ShlOp>(op, llvmTy, val, amt);
2935 return mlir::success();
2939 rewriter.replaceOpWithNewOp<mlir::LLVM::LShrOp>(op, llvmTy, val, amt);
2941 rewriter.replaceOpWithNewOp<mlir::LLVM::AShrOp>(op, llvmTy, val, amt);
2942 return mlir::success();
2945mlir::LogicalResult CIRToLLVMSelectOpLowering::matchAndRewrite(
2946 cir::SelectOp op, OpAdaptor adaptor,
2947 mlir::ConversionPatternRewriter &rewriter)
const {
2948 auto getConstantBool = [](mlir::Value value) -> cir::BoolAttr {
2949 auto definingOp = value.getDefiningOp<cir::ConstantOp>();
2953 auto constValue = definingOp.getValueAttr<cir::BoolAttr>();
2963 if (mlir::isa<cir::BoolType>(op.getTrueValue().getType())) {
2964 cir::BoolAttr trueValue = getConstantBool(op.getTrueValue());
2965 cir::BoolAttr falseValue = getConstantBool(op.getFalseValue());
2966 if (falseValue && !falseValue.getValue()) {
2968 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(op, adaptor.getCondition(),
2969 adaptor.getTrueValue());
2970 return mlir::success();
2972 if (trueValue && trueValue.getValue()) {
2974 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(op, adaptor.getCondition(),
2975 adaptor.getFalseValue());
2976 return mlir::success();
2980 mlir::Value llvmCondition = adaptor.getCondition();
2981 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(
2982 op, llvmCondition, adaptor.getTrueValue(), adaptor.getFalseValue());
2984 return mlir::success();
2988 mlir::PatternRewriter rewriter{
module->getContext()};
2993 if (!module->hasAttr(cir::CIRDialect::getTripleAttrName()))
2999 mlir::DataLayout &dataLayout,
3001 converter.addConversion([&](cir::PointerType type) -> mlir::Type {
3002 unsigned addrSpace =
3003 type.getAddrSpace() ? type.getAddrSpace().getValue().getUInt() : 0;
3004 return mlir::LLVM::LLVMPointerType::get(type.getContext(), addrSpace);
3006 converter.addConversion([&](cir::VPtrType type) -> mlir::Type {
3008 return mlir::LLVM::LLVMPointerType::get(type.getContext());
3010 converter.addConversion([&](cir::ArrayType type) -> mlir::Type {
3013 return mlir::LLVM::LLVMArrayType::get(ty, type.getSize());
3015 converter.addConversion([&](cir::VectorType type) -> mlir::Type {
3016 const mlir::Type ty = converter.convertType(type.getElementType());
3017 return mlir::VectorType::get(type.getSize(), ty, {type.getIsScalable()});
3019 converter.addConversion([&](cir::BoolType type) -> mlir::Type {
3020 return mlir::IntegerType::get(type.getContext(), 1,
3021 mlir::IntegerType::Signless);
3023 converter.addConversion([&](cir::IntType type) -> mlir::Type {
3025 return mlir::IntegerType::get(type.getContext(), type.getWidth());
3027 converter.addConversion([&](cir::SingleType type) -> mlir::Type {
3028 return mlir::Float32Type::get(type.getContext());
3030 converter.addConversion([&](cir::DoubleType type) -> mlir::Type {
3031 return mlir::Float64Type::get(type.getContext());
3033 converter.addConversion([&](cir::FP80Type type) -> mlir::Type {
3034 return mlir::Float80Type::get(type.getContext());
3036 converter.addConversion([&](cir::FP128Type type) -> mlir::Type {
3037 return mlir::Float128Type::get(type.getContext());
3039 converter.addConversion([&](cir::LongDoubleType type) -> mlir::Type {
3040 return converter.convertType(type.getUnderlying());
3042 converter.addConversion([&](cir::FP16Type type) -> mlir::Type {
3043 return mlir::Float16Type::get(type.getContext());
3045 converter.addConversion([&](cir::BF16Type type) -> mlir::Type {
3046 return mlir::BFloat16Type::get(type.getContext());
3048 converter.addConversion([&](cir::ComplexType type) -> mlir::Type {
3051 mlir::Type elementTy = converter.convertType(type.getElementType());
3052 mlir::Type structFields[2] = {elementTy, elementTy};
3053 return mlir::LLVM::LLVMStructType::getLiteral(type.getContext(),
3056 converter.addConversion([&](cir::FuncType type) -> std::optional<mlir::Type> {
3057 auto result = converter.convertType(type.getReturnType());
3059 arguments.reserve(type.getNumInputs());
3060 if (converter.convertTypes(type.getInputs(), arguments).failed())
3061 return std::nullopt;
3062 auto varArg = type.isVarArg();
3063 return mlir::LLVM::LLVMFunctionType::get(result, arguments, varArg);
3065 converter.addConversion([&](cir::RecordType type) -> mlir::Type {
3068 switch (type.getKind()) {
3069 case cir::RecordType::Class:
3070 case cir::RecordType::Struct:
3071 for (mlir::Type ty : type.getMembers())
3075 case cir::RecordType::Union:
3076 if (type.getMembers().empty())
3078 if (
auto largestMember = type.getLargestMember(dataLayout))
3079 llvmMembers.push_back(
3081 if (type.getPadded()) {
3082 auto last = *type.getMembers().rbegin();
3083 llvmMembers.push_back(
3090 mlir::LLVM::LLVMStructType llvmStruct;
3091 if (type.getName()) {
3092 llvmStruct = mlir::LLVM::LLVMStructType::getIdentified(
3093 type.getContext(), type.getPrefixedName());
3094 if (llvmStruct.setBody(llvmMembers, type.getPacked()).failed())
3095 llvm_unreachable(
"Failed to set body of record");
3097 llvmStruct = mlir::LLVM::LLVMStructType::getLiteral(
3098 type.getContext(), llvmMembers, type.getPacked());
3103 converter.addConversion([&](cir::VoidType type) -> mlir::Type {
3104 return mlir::LLVM::LLVMVoidType::get(type.getContext());
3109 mlir::ModuleOp module, StringRef globalXtorName, StringRef llvmXtorName,
3110 llvm::function_ref<std::pair<StringRef, int>(mlir::Attribute)> createXtor) {
3112 for (
const mlir::NamedAttribute namedAttr : module->getAttrs()) {
3113 if (namedAttr.getName() == globalXtorName) {
3114 for (
auto attr : mlir::cast<mlir::ArrayAttr>(namedAttr.getValue()))
3115 globalXtors.emplace_back(createXtor(attr));
3120 if (globalXtors.empty())
3123 mlir::OpBuilder builder(module.getContext());
3124 builder.setInsertionPointToEnd(&module.getBodyRegion().back());
3128 auto ctorPFTy = mlir::LLVM::LLVMPointerType::get(builder.getContext());
3130 ctorStructFields.push_back(builder.getI32Type());
3131 ctorStructFields.push_back(ctorPFTy);
3132 ctorStructFields.push_back(ctorPFTy);
3134 auto ctorStructTy = mlir::LLVM::LLVMStructType::getLiteral(
3135 builder.getContext(), ctorStructFields);
3136 auto ctorStructArrayTy =
3137 mlir::LLVM::LLVMArrayType::get(ctorStructTy, globalXtors.size());
3139 mlir::Location loc =
module.getLoc();
3140 auto newGlobalOp = mlir::LLVM::GlobalOp::create(
3141 builder, loc, ctorStructArrayTy,
false,
3142 mlir::LLVM::Linkage::Appending, llvmXtorName, mlir::Attribute());
3144 builder.createBlock(&newGlobalOp.getRegion());
3145 builder.setInsertionPointToEnd(newGlobalOp.getInitializerBlock());
3147 mlir::Value result =
3148 mlir::LLVM::UndefOp::create(builder, loc, ctorStructArrayTy);
3150 for (
auto [index, fn] : llvm::enumerate(globalXtors)) {
3151 mlir::Value structInit =
3152 mlir::LLVM::UndefOp::create(builder, loc, ctorStructTy);
3153 mlir::Value initPriority = mlir::LLVM::ConstantOp::create(
3154 builder, loc, ctorStructFields[0], fn.second);
3155 mlir::Value initFuncAddr = mlir::LLVM::AddressOfOp::create(
3156 builder, loc, ctorStructFields[1], fn.first);
3157 mlir::Value initAssociate =
3158 mlir::LLVM::ZeroOp::create(builder, loc, ctorStructFields[2]);
3161 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
3162 initPriority, zero);
3163 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
3166 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
3168 result = mlir::LLVM::InsertValueOp::create(builder, loc, result, structInit,
3172 mlir::LLVM::ReturnOp::create(builder, loc, result);
3210 parent->walk([&](mlir::Block *blk) {
3211 if (blk->hasNoPredecessors() && !blk->isEntryBlock())
3212 unreachableBlocks.push_back(blk);
3215 std::set<mlir::Block *> visited;
3216 for (mlir::Block *root : unreachableBlocks) {
3219 std::deque<mlir::Block *> workList;
3220 workList.push_back(root);
3222 while (!workList.empty()) {
3223 mlir::Block *blk = workList.back();
3224 workList.pop_back();
3225 if (visited.count(blk))
3227 visited.emplace(blk);
3229 for (mlir::Operation &op : *blk)
3232 for (mlir::Block *succ : blk->getSuccessors())
3233 workList.push_back(succ);
3238mlir::LogicalResult CIRToLLVMObjSizeOpLowering::matchAndRewrite(
3239 cir::ObjSizeOp op, OpAdaptor adaptor,
3240 mlir::ConversionPatternRewriter &rewriter)
const {
3241 mlir::Type llvmResTy = getTypeConverter()->convertType(op.getType());
3242 mlir::Location loc = op->getLoc();
3244 mlir::IntegerType i1Ty = rewriter.getI1Type();
3246 auto i1Val = [&rewriter, &loc, &i1Ty](
bool val) {
3247 return mlir::LLVM::ConstantOp::create(rewriter, loc, i1Ty, val);
3254 i1Val(op.getNullunknown()),
3255 i1Val(op.getDynamic()),
3258 return mlir::LogicalResult::success();
3263 if (mlir::Attribute tripleAttr =
3264 module->getAttr(cir::CIRDialect::getTripleAttrName()))
3265 module->setAttr(mlir::LLVM::LLVMDialect::getTargetTripleAttrName(),
3268 if (mlir::Attribute asmAttr =
3269 module->getAttr(cir::CIRDialect::getModuleLevelAsmAttrName()))
3270 module->setAttr(mlir::LLVM::LLVMDialect::getModuleLevelAsmAttrName(),
3275 llvm::TimeTraceScope scope(
"Convert CIR to LLVM Pass");
3277 mlir::ModuleOp module = getOperation();
3278 mlir::DataLayout dl(module);
3279 mlir::LLVMTypeConverter converter(&getContext());
3288 mlir::RewritePatternSet patterns(&getContext());
3289 patterns.add<CIRToLLVMBlockAddressOpLowering, CIRToLLVMLabelOpLowering>(
3290 converter, patterns.getContext(), lowerModule.get(), dl, blockInfoAddr);
3293#define GET_LLVM_LOWERING_PATTERNS_LIST
3294#include "clang/CIR/Dialect/IR/CIRLowering.inc"
3295#undef GET_LLVM_LOWERING_PATTERNS_LIST
3296 >(converter, patterns.getContext(), lowerModule.get(), dl);
3300 mlir::ConversionTarget target(getContext());
3301 target.addLegalOp<mlir::ModuleOp>();
3302 target.addLegalDialect<mlir::LLVM::LLVMDialect>();
3303 target.addIllegalDialect<mlir::BuiltinDialect, cir::CIRDialect,
3304 mlir::func::FuncDialect>();
3307 ops.push_back(module);
3310 if (failed(applyPartialConversion(ops, target, std::move(patterns))))
3311 signalPassFailure();
3315 "llvm.global_ctors", [](mlir::Attribute attr) {
3316 auto ctorAttr = mlir::cast<cir::GlobalCtorAttr>(attr);
3317 return std::make_pair(ctorAttr.getName(),
3318 ctorAttr.getPriority());
3322 "llvm.global_dtors", [](mlir::Attribute attr) {
3323 auto dtorAttr = mlir::cast<cir::GlobalDtorAttr>(attr);
3324 return std::make_pair(dtorAttr.getName(),
3325 dtorAttr.getPriority());
3329mlir::LogicalResult CIRToLLVMBrOpLowering::matchAndRewrite(
3330 cir::BrOp op, OpAdaptor adaptor,
3331 mlir::ConversionPatternRewriter &rewriter)
const {
3332 rewriter.replaceOpWithNewOp<mlir::LLVM::BrOp>(op, adaptor.getOperands(),
3334 return mlir::LogicalResult::success();
3337mlir::LogicalResult CIRToLLVMGetMemberOpLowering::matchAndRewrite(
3338 cir::GetMemberOp op, OpAdaptor adaptor,
3339 mlir::ConversionPatternRewriter &rewriter)
const {
3340 mlir::Type llResTy = getTypeConverter()->convertType(op.getType());
3341 const auto recordTy =
3342 mlir::cast<cir::RecordType>(op.getAddrTy().getPointee());
3343 assert(recordTy &&
"expected record type");
3345 switch (recordTy.getKind()) {
3346 case cir::RecordType::Class:
3347 case cir::RecordType::Struct: {
3351 const mlir::Type elementTy = getTypeConverter()->convertType(recordTy);
3352 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, llResTy, elementTy,
3353 adaptor.getAddr(), offset);
3354 return mlir::success();
3356 case cir::RecordType::Union:
3359 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(op, llResTy,
3361 return mlir::success();
3365mlir::LogicalResult CIRToLLVMExtractMemberOpLowering::matchAndRewrite(
3366 cir::ExtractMemberOp op, OpAdaptor adaptor,
3367 mlir::ConversionPatternRewriter &rewriter)
const {
3368 std::int64_t indices[1] = {
static_cast<std::int64_t
>(op.getIndex())};
3370 mlir::Type recordTy = op.getRecord().getType();
3371 auto cirRecordTy = mlir::cast<cir::RecordType>(recordTy);
3372 switch (cirRecordTy.getKind()) {
3373 case cir::RecordType::Struct:
3374 case cir::RecordType::Class:
3375 rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractValueOp>(
3376 op, adaptor.getRecord(), indices);
3377 return mlir::success();
3379 case cir::RecordType::Union:
3380 op.emitError(
"cir.extract_member cannot extract member from a union");
3381 return mlir::failure();
3383 llvm_unreachable(
"Unexpected record kind");
3386mlir::LogicalResult CIRToLLVMInsertMemberOpLowering::matchAndRewrite(
3387 cir::InsertMemberOp op, OpAdaptor adaptor,
3388 mlir::ConversionPatternRewriter &rewriter)
const {
3389 std::int64_t indecies[1] = {
static_cast<std::int64_t
>(op.getIndex())};
3390 mlir::Type recordTy = op.getRecord().getType();
3392 if (
auto cirRecordTy = mlir::dyn_cast<cir::RecordType>(recordTy)) {
3393 if (cirRecordTy.getKind() == cir::RecordType::Union) {
3394 op.emitError(
"cir.update_member cannot update member of a union");
3395 return mlir::failure();
3399 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
3400 op, adaptor.getRecord(), adaptor.getValue(), indecies);
3401 return mlir::success();
3404mlir::LogicalResult CIRToLLVMUnreachableOpLowering::matchAndRewrite(
3405 cir::UnreachableOp op, OpAdaptor adaptor,
3406 mlir::ConversionPatternRewriter &rewriter)
const {
3407 rewriter.replaceOpWithNewOp<mlir::LLVM::UnreachableOp>(op);
3408 return mlir::success();
3412 mlir::Operation *srcOp, llvm::StringRef fnName,
3414 auto modOp = srcOp->getParentOfType<mlir::ModuleOp>();
3415 auto enclosingFnOp = srcOp->getParentOfType<mlir::LLVM::LLVMFuncOp>();
3416 mlir::Operation *sourceSymbol =
3417 mlir::SymbolTable::lookupSymbolIn(modOp, fnName);
3418 if (!sourceSymbol) {
3419 mlir::OpBuilder::InsertionGuard guard(rewriter);
3420 rewriter.setInsertionPoint(enclosingFnOp);
3421 mlir::LLVM::LLVMFuncOp::create(rewriter, srcOp->getLoc(), fnName, fnTy);
3425mlir::LogicalResult CIRToLLVMThrowOpLowering::matchAndRewrite(
3426 cir::ThrowOp op, OpAdaptor adaptor,
3427 mlir::ConversionPatternRewriter &rewriter)
const {
3428 mlir::Location loc = op.getLoc();
3429 auto voidTy = mlir::LLVM::LLVMVoidType::get(getContext());
3431 if (op.rethrows()) {
3432 auto funcTy = mlir::LLVM::LLVMFunctionType::get(voidTy, {});
3435 const llvm::StringRef functionName =
"__cxa_rethrow";
3438 auto cxaRethrow = mlir::LLVM::CallOp::create(
3439 rewriter, loc, mlir::TypeRange{}, functionName);
3441 rewriter.replaceOp(op, cxaRethrow);
3442 return mlir::success();
3445 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3446 auto fnTy = mlir::LLVM::LLVMFunctionType::get(
3447 voidTy, {llvmPtrTy, llvmPtrTy, llvmPtrTy});
3450 const llvm::StringRef fnName =
"__cxa_throw";
3453 mlir::Value typeInfo = mlir::LLVM::AddressOfOp::create(
3454 rewriter, loc, mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
3455 adaptor.getTypeInfoAttr());
3459 dtor = mlir::LLVM::AddressOfOp::create(rewriter, loc, llvmPtrTy,
3460 adaptor.getDtorAttr());
3462 dtor = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmPtrTy);
3465 auto cxaThrowCall = mlir::LLVM::CallOp::create(
3466 rewriter, loc, mlir::TypeRange{}, fnName,
3467 mlir::ValueRange{adaptor.getExceptionPtr(), typeInfo, dtor});
3469 rewriter.replaceOp(op, cxaThrowCall);
3470 return mlir::success();
3473mlir::LogicalResult CIRToLLVMAllocExceptionOpLowering::matchAndRewrite(
3474 cir::AllocExceptionOp op, OpAdaptor adaptor,
3475 mlir::ConversionPatternRewriter &rewriter)
const {
3477 StringRef fnName =
"__cxa_allocate_exception";
3478 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3479 auto int64Ty = mlir::IntegerType::get(rewriter.getContext(), 64);
3480 auto fnTy = mlir::LLVM::LLVMFunctionType::get(llvmPtrTy, {int64Ty});
3483 auto exceptionSize = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
3484 adaptor.getSizeAttr());
3486 auto allocaExceptionCall = mlir::LLVM::CallOp::create(
3487 rewriter, op.getLoc(), mlir::TypeRange{llvmPtrTy}, fnName,
3488 mlir::ValueRange{exceptionSize});
3490 rewriter.replaceOp(op, allocaExceptionCall);
3491 return mlir::success();
3494static mlir::LLVM::LLVMStructType
3497 mlir::MLIRContext *ctx = rewriter.getContext();
3498 auto llvmPtr = mlir::LLVM::LLVMPointerType::get(ctx);
3500 return mlir::LLVM::LLVMStructType::getLiteral(ctx, structFields);
3503mlir::LogicalResult CIRToLLVMEhInflightOpLowering::matchAndRewrite(
3504 cir::EhInflightOp op, OpAdaptor adaptor,
3505 mlir::ConversionPatternRewriter &rewriter)
const {
3506 auto llvmFn = op->getParentOfType<mlir::LLVM::LLVMFuncOp>();
3507 assert(llvmFn &&
"expected LLVM function parent");
3508 mlir::Block *entryBlock = &llvmFn.getRegion().front();
3509 assert(entryBlock->isEntryBlock());
3511 mlir::ArrayAttr catchListAttr = op.getCatchTypeListAttr();
3512 mlir::SmallVector<mlir::Value> catchSymAddrs;
3514 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3515 mlir::Location loc = op.getLoc();
3520 if (catchListAttr) {
3523 for (mlir::Attribute catchAttr : catchListAttr) {
3524 auto symAttr = cast<mlir::FlatSymbolRefAttr>(catchAttr);
3527 mlir::OpBuilder::InsertionGuard guard(rewriter);
3528 rewriter.setInsertionPointToStart(entryBlock);
3529 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
3530 rewriter, loc, llvmPtrTy, symAttr.getValue());
3531 catchSymAddrs.push_back(addrOp);
3533 }
else if (!op.getCleanup()) {
3537 mlir::OpBuilder::InsertionGuard guard(rewriter);
3538 rewriter.setInsertionPointToStart(entryBlock);
3539 mlir::Value nullOp = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmPtrTy);
3540 catchSymAddrs.push_back(nullOp);
3545 mlir::LLVM::LLVMStructType llvmLandingPadStructTy =
3547 auto landingPadOp = mlir::LLVM::LandingpadOp::create(
3548 rewriter, loc, llvmLandingPadStructTy, catchSymAddrs);
3550 if (op.getCleanup())
3551 landingPadOp.setCleanup(
true);
3554 mlir::LLVM::ExtractValueOp::create(rewriter, loc, landingPadOp, 0);
3555 mlir::Value selector =
3556 mlir::LLVM::ExtractValueOp::create(rewriter, loc, landingPadOp, 1);
3557 rewriter.replaceOp(op, mlir::ValueRange{slot, selector});
3559 return mlir::success();
3562mlir::LogicalResult CIRToLLVMResumeFlatOpLowering::matchAndRewrite(
3563 cir::ResumeFlatOp op, OpAdaptor adaptor,
3564 mlir::ConversionPatternRewriter &rewriter)
const {
3569 mlir::Value poison = mlir::LLVM::PoisonOp::create(rewriter, op.getLoc(),
3570 llvmLandingPadStructTy);
3572 SmallVector<int64_t> slotIdx = {0};
3573 mlir::Value slot = mlir::LLVM::InsertValueOp::create(
3574 rewriter, op.getLoc(), poison, adaptor.getExceptionPtr(), slotIdx);
3576 SmallVector<int64_t> selectorIdx = {1};
3577 mlir::Value selector = mlir::LLVM::InsertValueOp::create(
3578 rewriter, op.getLoc(), slot, adaptor.getTypeId(), selectorIdx);
3580 rewriter.replaceOpWithNewOp<mlir::LLVM::ResumeOp>(op, selector);
3581 return mlir::success();
3584mlir::LogicalResult CIRToLLVMEhTypeIdOpLowering::matchAndRewrite(
3585 cir::EhTypeIdOp op, OpAdaptor adaptor,
3586 mlir::ConversionPatternRewriter &rewriter)
const {
3587 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
3588 rewriter, op.getLoc(),
3589 mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
3590 op.getTypeSymAttr());
3591 rewriter.replaceOpWithNewOp<mlir::LLVM::EhTypeidForOp>(
3592 op, rewriter.getI32Type(), addrOp);
3593 return mlir::success();
3596mlir::LogicalResult CIRToLLVMTrapOpLowering::matchAndRewrite(
3597 cir::TrapOp op, OpAdaptor adaptor,
3598 mlir::ConversionPatternRewriter &rewriter)
const {
3599 mlir::Location loc = op->getLoc();
3600 rewriter.eraseOp(op);
3602 mlir::LLVM::Trap::create(rewriter, loc);
3607 mlir::LLVM::UnreachableOp::create(rewriter, loc);
3609 return mlir::success();
3614 mlir::ConversionPatternRewriter &rewriter,
3615 const mlir::TypeConverter *converter,
3616 mlir::FlatSymbolRefAttr nameAttr, mlir::Type &eltType) {
3617 auto module = op->getParentOfType<mlir::ModuleOp>();
3618 mlir::Operation *symbol = mlir::SymbolTable::lookupSymbolIn(module, nameAttr);
3619 if (
auto llvmSymbol = mlir::dyn_cast<mlir::LLVM::GlobalOp>(symbol)) {
3620 eltType = llvmSymbol.getType();
3621 }
else if (
auto cirSymbol = mlir::dyn_cast<cir::GlobalOp>(symbol)) {
3622 eltType = converter->convertType(cirSymbol.getSymType());
3624 op->emitError() <<
"unexpected symbol type for " << symbol;
3628 return mlir::LLVM::AddressOfOp::create(
3629 rewriter, op->getLoc(),
3630 mlir::LLVM::LLVMPointerType::get(op->getContext()), nameAttr.getValue());
3633mlir::LogicalResult CIRToLLVMVTableAddrPointOpLowering::matchAndRewrite(
3634 cir::VTableAddrPointOp op, OpAdaptor adaptor,
3635 mlir::ConversionPatternRewriter &rewriter)
const {
3636 const mlir::TypeConverter *converter = getTypeConverter();
3637 mlir::Type targetType = converter->convertType(op.getType());
3641 op.getNameAttr(), eltType);
3643 return op.emitError() <<
"Unable to get value for vtable symbol";
3646 0, op.getAddressPointAttr().getIndex(),
3647 op.getAddressPointAttr().getOffset()};
3649 assert(eltType &&
"Shouldn't ever be missing an eltType here");
3650 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
3651 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
3652 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, targetType, eltType,
3653 symAddr, offsets, inboundsNuw);
3654 return mlir::success();
3657mlir::LogicalResult CIRToLLVMVTableGetVPtrOpLowering::matchAndRewrite(
3658 cir::VTableGetVPtrOp op, OpAdaptor adaptor,
3659 mlir::ConversionPatternRewriter &rewriter)
const {
3663 mlir::Value srcVal = adaptor.getSrc();
3664 rewriter.replaceOp(op, srcVal);
3665 return mlir::success();
3668mlir::LogicalResult CIRToLLVMVTableGetVirtualFnAddrOpLowering::matchAndRewrite(
3669 cir::VTableGetVirtualFnAddrOp op, OpAdaptor adaptor,
3670 mlir::ConversionPatternRewriter &rewriter)
const {
3671 mlir::Type targetType = getTypeConverter()->convertType(op.getType());
3672 auto eltType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3673 llvm::SmallVector<mlir::LLVM::GEPArg> offsets =
3674 llvm::SmallVector<mlir::LLVM::GEPArg>{op.getIndex()};
3675 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
3676 op, targetType, eltType, adaptor.getVptr(), offsets,
3677 mlir::LLVM::GEPNoWrapFlags::inbounds);
3678 return mlir::success();
3681mlir::LogicalResult CIRToLLVMVTTAddrPointOpLowering::matchAndRewrite(
3682 cir::VTTAddrPointOp op, OpAdaptor adaptor,
3683 mlir::ConversionPatternRewriter &rewriter)
const {
3684 const mlir::Type resultType = getTypeConverter()->convertType(op.getType());
3685 llvm::SmallVector<mlir::LLVM::GEPArg> offsets;
3687 mlir::Value llvmAddr = adaptor.getSymAddr();
3689 if (op.getSymAddr()) {
3690 if (op.getOffset() == 0) {
3691 rewriter.replaceOp(op, {llvmAddr});
3692 return mlir::success();
3695 offsets.push_back(adaptor.getOffset());
3696 eltType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3699 op.getNameAttr(), eltType);
3700 assert(eltType &&
"Shouldn't ever be missing an eltType here");
3701 offsets.push_back(0);
3702 offsets.push_back(adaptor.getOffset());
3704 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
3705 op, resultType, eltType, llvmAddr, offsets,
3706 mlir::LLVM::GEPNoWrapFlags::inbounds);
3707 return mlir::success();
3710mlir::LogicalResult CIRToLLVMStackSaveOpLowering::matchAndRewrite(
3711 cir::StackSaveOp op, OpAdaptor adaptor,
3712 mlir::ConversionPatternRewriter &rewriter)
const {
3713 const mlir::Type ptrTy = getTypeConverter()->convertType(op.getType());
3714 rewriter.replaceOpWithNewOp<mlir::LLVM::StackSaveOp>(op, ptrTy);
3715 return mlir::success();
3718mlir::LogicalResult CIRToLLVMStackRestoreOpLowering::matchAndRewrite(
3719 cir::StackRestoreOp op, OpAdaptor adaptor,
3720 mlir::ConversionPatternRewriter &rewriter)
const {
3721 rewriter.replaceOpWithNewOp<mlir::LLVM::StackRestoreOp>(op, adaptor.getPtr());
3722 return mlir::success();
3725mlir::LogicalResult CIRToLLVMVecCreateOpLowering::matchAndRewrite(
3726 cir::VecCreateOp op, OpAdaptor adaptor,
3727 mlir::ConversionPatternRewriter &rewriter)
const {
3730 const auto vecTy = mlir::cast<cir::VectorType>(op.getType());
3731 const mlir::Type llvmTy = typeConverter->convertType(vecTy);
3732 const mlir::Location loc = op.getLoc();
3733 mlir::Value result = mlir::LLVM::PoisonOp::create(rewriter, loc, llvmTy);
3734 assert(vecTy.getSize() == op.getElements().size() &&
3735 "cir.vec.create op count doesn't match vector type elements count");
3737 for (uint64_t i = 0; i < vecTy.getSize(); ++i) {
3738 const mlir::Value indexValue =
3739 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
3740 result = mlir::LLVM::InsertElementOp::create(
3741 rewriter, loc, result, adaptor.getElements()[i], indexValue);
3744 rewriter.replaceOp(op, result);
3745 return mlir::success();
3748mlir::LogicalResult CIRToLLVMVecExtractOpLowering::matchAndRewrite(
3749 cir::VecExtractOp op, OpAdaptor adaptor,
3750 mlir::ConversionPatternRewriter &rewriter)
const {
3751 rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractElementOp>(
3752 op, adaptor.getVec(), adaptor.getIndex());
3753 return mlir::success();
3756mlir::LogicalResult CIRToLLVMVecInsertOpLowering::matchAndRewrite(
3757 cir::VecInsertOp op, OpAdaptor adaptor,
3758 mlir::ConversionPatternRewriter &rewriter)
const {
3759 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertElementOp>(
3760 op, adaptor.getVec(), adaptor.getValue(), adaptor.getIndex());
3761 return mlir::success();
3764mlir::LogicalResult CIRToLLVMVecCmpOpLowering::matchAndRewrite(
3765 cir::VecCmpOp op, OpAdaptor adaptor,
3766 mlir::ConversionPatternRewriter &rewriter)
const {
3767 mlir::Type elementType = elementTypeIfVector(op.getLhs().getType());
3768 mlir::Value bitResult;
3769 if (
auto intType = mlir::dyn_cast<cir::IntType>(elementType)) {
3770 bitResult = mlir::LLVM::ICmpOp::create(
3771 rewriter, op.getLoc(),
3773 adaptor.getLhs(), adaptor.getRhs());
3774 }
else if (mlir::isa<cir::FPTypeInterface>(elementType)) {
3775 bitResult = mlir::LLVM::FCmpOp::create(
3777 adaptor.getLhs(), adaptor.getRhs());
3779 return op.emitError() <<
"unsupported type for VecCmpOp: " << elementType;
3785 if (cast<cir::IntType>(cast<cir::VectorType>(op.getType()).getElementType())
3787 rewriter.replaceOpWithNewOp<mlir::LLVM::SExtOp>(
3788 op, typeConverter->convertType(op.getType()), bitResult);
3790 rewriter.replaceOp(op, bitResult);
3791 return mlir::success();
3794mlir::LogicalResult CIRToLLVMVecSplatOpLowering::matchAndRewrite(
3795 cir::VecSplatOp op, OpAdaptor adaptor,
3796 mlir::ConversionPatternRewriter &rewriter)
const {
3802 cir::VectorType vecTy = op.getType();
3803 mlir::Type llvmTy = typeConverter->convertType(vecTy);
3804 mlir::Location loc = op.getLoc();
3805 mlir::Value poison = mlir::LLVM::PoisonOp::create(rewriter, loc, llvmTy);
3807 mlir::Value elementValue = adaptor.getValue();
3808 if (elementValue.getDefiningOp<mlir::LLVM::PoisonOp>()) {
3811 rewriter.replaceOp(op, poison);
3812 return mlir::success();
3815 if (
auto constValue = elementValue.getDefiningOp<mlir::LLVM::ConstantOp>()) {
3816 if (
auto intAttr = dyn_cast<mlir::IntegerAttr>(constValue.getValue())) {
3817 mlir::DenseIntElementsAttr denseVec = mlir::DenseIntElementsAttr::get(
3818 mlir::cast<mlir::ShapedType>(llvmTy), intAttr.getValue());
3819 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
3820 op, denseVec.getType(), denseVec);
3821 return mlir::success();
3824 if (
auto fpAttr = dyn_cast<mlir::FloatAttr>(constValue.getValue())) {
3825 mlir::DenseFPElementsAttr denseVec = mlir::DenseFPElementsAttr::get(
3826 mlir::cast<mlir::ShapedType>(llvmTy), fpAttr.getValue());
3827 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
3828 op, denseVec.getType(), denseVec);
3829 return mlir::success();
3833 mlir::Value indexValue =
3834 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), 0);
3835 mlir::Value oneElement = mlir::LLVM::InsertElementOp::create(
3836 rewriter, loc, poison, elementValue, indexValue);
3837 SmallVector<int32_t> zeroValues(vecTy.getSize(), 0);
3838 rewriter.replaceOpWithNewOp<mlir::LLVM::ShuffleVectorOp>(op, oneElement,
3839 poison, zeroValues);
3840 return mlir::success();
3843mlir::LogicalResult CIRToLLVMVecShuffleOpLowering::matchAndRewrite(
3844 cir::VecShuffleOp op, OpAdaptor adaptor,
3845 mlir::ConversionPatternRewriter &rewriter)
const {
3849 SmallVector<int, 8> indices;
3851 op.getIndices().begin(), op.getIndices().end(),
3852 std::back_inserter(indices), [](mlir::Attribute intAttr) {
3853 return mlir::cast<cir::IntAttr>(intAttr).getValue().getSExtValue();
3855 rewriter.replaceOpWithNewOp<mlir::LLVM::ShuffleVectorOp>(
3856 op, adaptor.getVec1(), adaptor.getVec2(), indices);
3857 return mlir::success();
3860mlir::LogicalResult CIRToLLVMVecShuffleDynamicOpLowering::matchAndRewrite(
3861 cir::VecShuffleDynamicOp op, OpAdaptor adaptor,
3862 mlir::ConversionPatternRewriter &rewriter)
const {
3874 mlir::Location loc = op.getLoc();
3875 mlir::Value input = adaptor.getVec();
3876 mlir::Type llvmIndexVecType =
3877 getTypeConverter()->convertType(op.getIndices().getType());
3878 mlir::Type llvmIndexType = getTypeConverter()->convertType(
3879 elementTypeIfVector(op.getIndices().getType()));
3881 mlir::cast<cir::VectorType>(op.getVec().getType()).getSize();
3883 uint64_t maskBits = llvm::NextPowerOf2(numElements - 1) - 1;
3884 mlir::Value maskValue = mlir::LLVM::ConstantOp::create(
3885 rewriter, loc, llvmIndexType,
3886 rewriter.getIntegerAttr(llvmIndexType, maskBits));
3887 mlir::Value maskVector =
3888 mlir::LLVM::UndefOp::create(rewriter, loc, llvmIndexVecType);
3890 for (uint64_t i = 0; i < numElements; ++i) {
3891 mlir::Value idxValue =
3892 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
3893 maskVector = mlir::LLVM::InsertElementOp::create(rewriter, loc, maskVector,
3894 maskValue, idxValue);
3897 mlir::Value maskedIndices = mlir::LLVM::AndOp::create(
3898 rewriter, loc, llvmIndexVecType, adaptor.getIndices(), maskVector);
3899 mlir::Value result = mlir::LLVM::UndefOp::create(
3900 rewriter, loc, getTypeConverter()->convertType(op.getVec().getType()));
3901 for (uint64_t i = 0; i < numElements; ++i) {
3902 mlir::Value iValue =
3903 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
3904 mlir::Value indexValue = mlir::LLVM::ExtractElementOp::create(
3905 rewriter, loc, maskedIndices, iValue);
3906 mlir::Value valueAtIndex =
3907 mlir::LLVM::ExtractElementOp::create(rewriter, loc, input, indexValue);
3908 result = mlir::LLVM::InsertElementOp::create(rewriter, loc, result,
3909 valueAtIndex, iValue);
3911 rewriter.replaceOp(op, result);
3912 return mlir::success();
3915mlir::LogicalResult CIRToLLVMVecTernaryOpLowering::matchAndRewrite(
3916 cir::VecTernaryOp op, OpAdaptor adaptor,
3917 mlir::ConversionPatternRewriter &rewriter)
const {
3919 mlir::Value bitVec = mlir::LLVM::ICmpOp::create(
3920 rewriter, op.getLoc(), mlir::LLVM::ICmpPredicate::ne, adaptor.getCond(),
3921 mlir::LLVM::ZeroOp::create(
3922 rewriter, op.getCond().getLoc(),
3923 typeConverter->convertType(op.getCond().getType())));
3924 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(
3925 op, bitVec, adaptor.getLhs(), adaptor.getRhs());
3926 return mlir::success();
3929mlir::LogicalResult CIRToLLVMComplexAddOpLowering::matchAndRewrite(
3930 cir::ComplexAddOp op, OpAdaptor adaptor,
3931 mlir::ConversionPatternRewriter &rewriter)
const {
3932 mlir::Value lhs = adaptor.getLhs();
3933 mlir::Value rhs = adaptor.getRhs();
3934 mlir::Location loc = op.getLoc();
3936 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
3937 mlir::Type complexElemTy =
3938 getTypeConverter()->convertType(
complexType.getElementType());
3939 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
3940 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{0}));
3941 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
3942 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{1}));
3943 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
3944 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{0}));
3945 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
3946 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{1}));
3948 mlir::Value newReal;
3949 mlir::Value newImag;
3950 if (complexElemTy.isInteger()) {
3951 newReal = mlir::LLVM::AddOp::create(rewriter, loc, complexElemTy, lhsReal,
3953 newImag = mlir::LLVM::AddOp::create(rewriter, loc, complexElemTy, lhsImag,
3958 newReal = mlir::LLVM::FAddOp::create(rewriter, loc, complexElemTy, lhsReal,
3960 newImag = mlir::LLVM::FAddOp::create(rewriter, loc, complexElemTy, lhsImag,
3964 mlir::Type complexLLVMTy =
3965 getTypeConverter()->convertType(op.getResult().getType());
3966 auto initialComplex =
3967 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), complexLLVMTy);
3969 auto realComplex = mlir::LLVM::InsertValueOp::create(
3970 rewriter, op->getLoc(), initialComplex, newReal, ArrayRef(int64_t{0}));
3972 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
3973 op, realComplex, newImag, ArrayRef(int64_t{1}));
3975 return mlir::success();
3978mlir::LogicalResult CIRToLLVMComplexCreateOpLowering::matchAndRewrite(
3979 cir::ComplexCreateOp op, OpAdaptor adaptor,
3980 mlir::ConversionPatternRewriter &rewriter)
const {
3981 mlir::Type complexLLVMTy =
3982 getTypeConverter()->convertType(op.getResult().getType());
3983 auto initialComplex =
3984 mlir::LLVM::UndefOp::create(rewriter, op->getLoc(), complexLLVMTy);
3986 auto realComplex = mlir::LLVM::InsertValueOp::create(
3987 rewriter, op->getLoc(), initialComplex, adaptor.getReal(),
3988 ArrayRef(int64_t{0}));
3990 auto complex = mlir::LLVM::InsertValueOp::create(
3991 rewriter, op->getLoc(), realComplex, adaptor.getImag(),
3992 ArrayRef(int64_t{1}));
3994 rewriter.replaceOp(op, complex);
3995 return mlir::success();
3998mlir::LogicalResult CIRToLLVMComplexRealOpLowering::matchAndRewrite(
3999 cir::ComplexRealOp op, OpAdaptor adaptor,
4000 mlir::ConversionPatternRewriter &rewriter)
const {
4001 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
4002 mlir::Value operand = adaptor.getOperand();
4003 if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) {
4004 operand = mlir::LLVM::ExtractValueOp::create(
4005 rewriter, op.getLoc(), resultLLVMTy, operand,
4006 llvm::ArrayRef<std::int64_t>{0});
4008 rewriter.replaceOp(op, operand);
4009 return mlir::success();
4012mlir::LogicalResult CIRToLLVMComplexSubOpLowering::matchAndRewrite(
4013 cir::ComplexSubOp op, OpAdaptor adaptor,
4014 mlir::ConversionPatternRewriter &rewriter)
const {
4015 mlir::Value lhs = adaptor.getLhs();
4016 mlir::Value rhs = adaptor.getRhs();
4017 mlir::Location loc = op.getLoc();
4019 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
4020 mlir::Type complexElemTy =
4021 getTypeConverter()->convertType(
complexType.getElementType());
4022 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
4023 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{0}));
4024 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
4025 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{1}));
4026 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
4027 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{0}));
4028 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
4029 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{1}));
4031 mlir::Value newReal;
4032 mlir::Value newImag;
4033 if (complexElemTy.isInteger()) {
4034 newReal = mlir::LLVM::SubOp::create(rewriter, loc, complexElemTy, lhsReal,
4036 newImag = mlir::LLVM::SubOp::create(rewriter, loc, complexElemTy, lhsImag,
4041 newReal = mlir::LLVM::FSubOp::create(rewriter, loc, complexElemTy, lhsReal,
4043 newImag = mlir::LLVM::FSubOp::create(rewriter, loc, complexElemTy, lhsImag,
4047 mlir::Type complexLLVMTy =
4048 getTypeConverter()->convertType(op.getResult().getType());
4049 auto initialComplex =
4050 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), complexLLVMTy);
4052 auto realComplex = mlir::LLVM::InsertValueOp::create(
4053 rewriter, op->getLoc(), initialComplex, newReal, ArrayRef(int64_t{0}));
4055 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
4056 op, realComplex, newImag, ArrayRef(int64_t{1}));
4058 return mlir::success();
4061mlir::LogicalResult CIRToLLVMComplexImagOpLowering::matchAndRewrite(
4062 cir::ComplexImagOp op, OpAdaptor adaptor,
4063 mlir::ConversionPatternRewriter &rewriter)
const {
4064 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
4065 mlir::Value operand = adaptor.getOperand();
4066 mlir::Location loc = op.getLoc();
4068 if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) {
4069 operand = mlir::LLVM::ExtractValueOp::create(
4070 rewriter, loc, resultLLVMTy, operand, llvm::ArrayRef<std::int64_t>{1});
4072 mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(resultLLVMTy);
4074 mlir::LLVM::ConstantOp::create(rewriter, loc, resultLLVMTy, zeroAttr);
4077 rewriter.replaceOp(op, operand);
4078 return mlir::success();
4082 mlir::MLIRContext *context,
4083 unsigned &storageSize) {
4084 return TypeSwitch<mlir::Type, mlir::IntegerType>(storageType)
4085 .Case<cir::ArrayType>([&](cir::ArrayType atTy) {
4086 storageSize = atTy.getSize() * 8;
4087 return mlir::IntegerType::get(context, storageSize);
4089 .Case<cir::IntType>([&](cir::IntType intTy) {
4090 storageSize = intTy.getWidth();
4091 return mlir::IntegerType::get(context, storageSize);
4093 .Default([](mlir::Type) -> mlir::IntegerType {
4095 "Either ArrayType or IntType expected for bitfields storage");
4099mlir::LogicalResult CIRToLLVMSetBitfieldOpLowering::matchAndRewrite(
4100 cir::SetBitfieldOp op, OpAdaptor adaptor,
4101 mlir::ConversionPatternRewriter &rewriter)
const {
4102 mlir::OpBuilder::InsertionGuard guard(rewriter);
4103 rewriter.setInsertionPoint(op);
4105 cir::BitfieldInfoAttr info = op.getBitfieldInfo();
4106 uint64_t size = info.getSize();
4107 uint64_t offset = info.getOffset();
4108 mlir::Type storageType = info.getStorageType();
4109 mlir::MLIRContext *context = storageType.getContext();
4111 unsigned storageSize = 0;
4113 mlir::IntegerType intType =
4116 mlir::Value srcVal =
createIntCast(rewriter, adaptor.getSrc(), intType);
4117 unsigned srcWidth = storageSize;
4118 mlir::Value resultVal = srcVal;
4120 if (storageSize != size) {
4121 assert(storageSize > size &&
"Invalid bitfield size.");
4123 mlir::Value val = mlir::LLVM::LoadOp::create(
4124 rewriter, op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(),
4125 op.getIsVolatile());
4128 createAnd(rewriter, srcVal, llvm::APInt::getLowBitsSet(srcWidth, size));
4130 srcVal =
createShL(rewriter, srcVal, offset);
4134 ~llvm::APInt::getBitsSet(srcWidth, offset, offset + size));
4137 srcVal = mlir::LLVM::OrOp::create(rewriter, op.getLoc(), val, srcVal);
4140 mlir::LLVM::StoreOp::create(rewriter, op.getLoc(), srcVal, adaptor.getAddr(),
4141 op.getAlignment(), op.getIsVolatile());
4143 mlir::Type resultTy = getTypeConverter()->convertType(op.getType());
4145 if (info.getIsSigned()) {
4146 assert(size <= storageSize);
4147 unsigned highBits = storageSize - size;
4150 resultVal =
createShL(rewriter, resultVal, highBits);
4151 resultVal =
createAShR(rewriter, resultVal, highBits);
4156 mlir::cast<mlir::IntegerType>(resultTy),
4157 info.getIsSigned());
4159 rewriter.replaceOp(op, resultVal);
4160 return mlir::success();
4163mlir::LogicalResult CIRToLLVMComplexImagPtrOpLowering::matchAndRewrite(
4164 cir::ComplexImagPtrOp op, OpAdaptor adaptor,
4165 mlir::ConversionPatternRewriter &rewriter)
const {
4166 cir::PointerType operandTy = op.getOperand().getType();
4167 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
4168 mlir::Type elementLLVMTy =
4169 getTypeConverter()->convertType(operandTy.getPointee());
4171 mlir::LLVM::GEPArg gepIndices[2] = {{0}, {1}};
4172 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
4173 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
4174 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
4175 op, resultLLVMTy, elementLLVMTy, adaptor.getOperand(), gepIndices,
4177 return mlir::success();
4180mlir::LogicalResult CIRToLLVMComplexRealPtrOpLowering::matchAndRewrite(
4181 cir::ComplexRealPtrOp op, OpAdaptor adaptor,
4182 mlir::ConversionPatternRewriter &rewriter)
const {
4183 cir::PointerType operandTy = op.getOperand().getType();
4184 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
4185 mlir::Type elementLLVMTy =
4186 getTypeConverter()->convertType(operandTy.getPointee());
4188 mlir::LLVM::GEPArg gepIndices[2] = {0, 0};
4189 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
4190 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
4191 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
4192 op, resultLLVMTy, elementLLVMTy, adaptor.getOperand(), gepIndices,
4194 return mlir::success();
4197mlir::LogicalResult CIRToLLVMGetBitfieldOpLowering::matchAndRewrite(
4198 cir::GetBitfieldOp op, OpAdaptor adaptor,
4199 mlir::ConversionPatternRewriter &rewriter)
const {
4201 mlir::OpBuilder::InsertionGuard guard(rewriter);
4202 rewriter.setInsertionPoint(op);
4204 cir::BitfieldInfoAttr info = op.getBitfieldInfo();
4206 uint64_t offset = info.getOffset();
4207 mlir::Type storageType = info.getStorageType();
4208 mlir::MLIRContext *context = storageType.getContext();
4209 unsigned storageSize = 0;
4211 mlir::IntegerType intType =
4214 mlir::Value val = mlir::LLVM::LoadOp::create(
4215 rewriter, op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(),
4216 op.getIsVolatile());
4217 val = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), intType, val);
4219 if (info.getIsSigned()) {
4220 assert(
static_cast<unsigned>(offset + size) <= storageSize);
4221 unsigned highBits = storageSize - offset - size;
4222 val =
createShL(rewriter, val, highBits);
4223 val =
createAShR(rewriter, val, offset + highBits);
4227 if (
static_cast<unsigned>(offset) + size < storageSize)
4229 llvm::APInt::getLowBitsSet(storageSize, size));
4232 mlir::Type resTy = getTypeConverter()->convertType(op.getType());
4234 rewriter, val, mlir::cast<mlir::IntegerType>(resTy), info.getIsSigned());
4235 rewriter.replaceOp(op, newOp);
4236 return mlir::success();
4239mlir::LogicalResult CIRToLLVMIsConstantOpLowering::matchAndRewrite(
4240 cir::IsConstantOp op, OpAdaptor adaptor,
4241 mlir::ConversionPatternRewriter &rewriter)
const {
4242 rewriter.replaceOpWithNewOp<mlir::LLVM::IsConstantOp>(op, adaptor.getVal());
4243 return mlir::success();
4246mlir::LogicalResult CIRToLLVMInlineAsmOpLowering::matchAndRewrite(
4247 cir::InlineAsmOp op, OpAdaptor adaptor,
4248 mlir::ConversionPatternRewriter &rewriter)
const {
4250 if (op.getNumResults())
4251 llResTy = getTypeConverter()->convertType(op.getType(0));
4253 cir::AsmFlavor dialect = op.getAsmFlavor();
4254 mlir::LLVM::AsmDialect llDialect = dialect == cir::AsmFlavor::x86_att
4255 ? mlir::LLVM::AsmDialect::AD_ATT
4256 : mlir::LLVM::AsmDialect::AD_Intel;
4258 SmallVector<mlir::Attribute> opAttrs;
4259 StringRef llvmAttrName = mlir::LLVM::InlineAsmOp::getElementTypeAttrName();
4265 if (!op.getNumResults())
4266 opAttrs.push_back(mlir::Attribute());
4268 SmallVector<mlir::Value> llvmOperands;
4269 SmallVector<mlir::Value> cirOperands;
4270 for (
auto const &[llvmOp, cirOp] :
4271 zip(adaptor.getAsmOperands(), op.getAsmOperands())) {
4272 append_range(llvmOperands, llvmOp);
4273 append_range(cirOperands, cirOp);
4278 for (
auto const &[cirOpAttr, cirOp] :
4279 zip(op.getOperandAttrs(), cirOperands)) {
4281 opAttrs.push_back(mlir::Attribute());
4285 llvm::SmallVector<mlir::NamedAttribute, 1> attrs;
4286 cir::PointerType typ = mlir::cast<cir::PointerType>(cirOp.getType());
4288 *getTypeConverter(), dataLayout, typ.getPointee()));
4290 attrs.push_back(rewriter.getNamedAttr(llvmAttrName, typAttr));
4291 mlir::DictionaryAttr newDict = rewriter.getDictionaryAttr(attrs);
4292 opAttrs.push_back(newDict);
4295 rewriter.replaceOpWithNewOp<mlir::LLVM::InlineAsmOp>(
4296 op, llResTy, llvmOperands, op.getAsmStringAttr(), op.getConstraintsAttr(),
4297 op.getSideEffectsAttr(),
4300 mlir::LLVM::TailCallKindAttr::get(
4301 getContext(), mlir::LLVM::tailcallkind::TailCallKind::None),
4302 mlir::LLVM::AsmDialectAttr::get(getContext(), llDialect),
4303 rewriter.getArrayAttr(opAttrs));
4305 return mlir::success();
4308mlir::LogicalResult CIRToLLVMVAStartOpLowering::matchAndRewrite(
4309 cir::VAStartOp op, OpAdaptor adaptor,
4310 mlir::ConversionPatternRewriter &rewriter)
const {
4311 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4312 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4313 adaptor.getArgList());
4314 rewriter.replaceOpWithNewOp<mlir::LLVM::VaStartOp>(op, vaList);
4315 return mlir::success();
4318mlir::LogicalResult CIRToLLVMVAEndOpLowering::matchAndRewrite(
4319 cir::VAEndOp op, OpAdaptor adaptor,
4320 mlir::ConversionPatternRewriter &rewriter)
const {
4321 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4322 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4323 adaptor.getArgList());
4324 rewriter.replaceOpWithNewOp<mlir::LLVM::VaEndOp>(op, vaList);
4325 return mlir::success();
4328mlir::LogicalResult CIRToLLVMVACopyOpLowering::matchAndRewrite(
4329 cir::VACopyOp op, OpAdaptor adaptor,
4330 mlir::ConversionPatternRewriter &rewriter)
const {
4331 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4332 auto dstList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4333 adaptor.getDstList());
4334 auto srcList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4335 adaptor.getSrcList());
4336 rewriter.replaceOpWithNewOp<mlir::LLVM::VaCopyOp>(op, dstList, srcList);
4337 return mlir::success();
4340mlir::LogicalResult CIRToLLVMVAArgOpLowering::matchAndRewrite(
4341 cir::VAArgOp op, OpAdaptor adaptor,
4342 mlir::ConversionPatternRewriter &rewriter)
const {
4344 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4345 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4346 adaptor.getArgList());
4348 mlir::Type llvmType =
4349 getTypeConverter()->convertType(op->getResultTypes().front());
4351 return mlir::failure();
4353 rewriter.replaceOpWithNewOp<mlir::LLVM::VaArgOp>(op, llvmType, vaList);
4354 return mlir::success();
4357mlir::LogicalResult CIRToLLVMLabelOpLowering::matchAndRewrite(
4358 cir::LabelOp op, OpAdaptor adaptor,
4359 mlir::ConversionPatternRewriter &rewriter)
const {
4360 return mlir::failure();
4363mlir::LogicalResult CIRToLLVMBlockAddressOpLowering::matchAndRewrite(
4364 cir::BlockAddressOp op, OpAdaptor adaptor,
4365 mlir::ConversionPatternRewriter &rewriter)
const {
4366 return mlir::failure();
4369mlir::LogicalResult CIRToLLVMIndirectBrOpLowering::matchAndRewrite(
4370 cir::IndirectBrOp op, OpAdaptor adaptor,
4371 mlir::ConversionPatternRewriter &rewriter)
const {
4372 return mlir::failure();
4375mlir::LogicalResult CIRToLLVMAwaitOpLowering::matchAndRewrite(
4376 cir::AwaitOp op, OpAdaptor adaptor,
4377 mlir::ConversionPatternRewriter &rewriter)
const {
4378 return mlir::failure();
4381mlir::LogicalResult CIRToLLVMCpuIdOpLowering::matchAndRewrite(
4382 cir::CpuIdOp op, OpAdaptor adaptor,
4383 mlir::ConversionPatternRewriter &rewriter)
const {
4384 mlir::Type i32Ty = rewriter.getI32Type();
4385 mlir::Type i64Ty = rewriter.getI64Type();
4386 mlir::Type i32PtrTy = mlir::LLVM::LLVMPointerType::get(i32Ty.getContext(), 0);
4388 mlir::Type cpuidRetTy = mlir::LLVM::LLVMStructType::getLiteral(
4389 rewriter.getContext(), {i32Ty, i32Ty, i32Ty, i32Ty});
4391 mlir::Value functionId = adaptor.getFunctionId();
4392 mlir::Value subFunctionId = adaptor.getSubFunctionId();
4394 StringRef asmString, constraints;
4395 mlir::ModuleOp moduleOp = op->getParentOfType<mlir::ModuleOp>();
4396 llvm::Triple triple(
4397 mlir::cast<mlir::StringAttr>(
4398 moduleOp->getAttr(cir::CIRDialect::getTripleAttrName()))
4400 if (triple.getArch() == llvm::Triple::x86) {
4401 asmString =
"cpuid";
4402 constraints =
"={ax},={bx},={cx},={dx},{ax},{cx}";
4405 asmString =
"xchgq %rbx, ${1:q}\n"
4407 "xchgq %rbx, ${1:q}";
4408 constraints =
"={ax},=r,={cx},={dx},0,2";
4411 mlir::Value inlineAsm =
4412 mlir::LLVM::InlineAsmOp::create(
4413 rewriter, op.getLoc(), cpuidRetTy, {functionId, subFunctionId},
4414 rewriter.getStringAttr(asmString),
4415 rewriter.getStringAttr(constraints),
4418 mlir::LLVM::TailCallKindAttr{},
4419 mlir::LLVM::AsmDialectAttr{},
4423 mlir::Value basePtr = adaptor.getCpuInfo();
4425 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
4426 unsigned alignment = layout.getTypeABIAlignment(i32Ty);
4427 for (
unsigned i = 0; i < 4; i++) {
4428 mlir::Value extracted =
4429 mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(), inlineAsm, i)
4431 mlir::Value index = mlir::LLVM::ConstantOp::create(
4432 rewriter, op.getLoc(), i64Ty, rewriter.getI64IntegerAttr(i));
4433 llvm::SmallVector<mlir::Value, 1> gepIndices = {index};
4434 mlir::Value storePtr = mlir::LLVM::GEPOp::create(
4435 rewriter, op.getLoc(), i32PtrTy, i32Ty, basePtr,
4436 gepIndices, mlir::LLVM::GEPNoWrapFlags::none)
4438 mlir::LLVM::StoreOp::create(rewriter, op.getLoc(), extracted, storePtr,
4442 rewriter.eraseOp(op);
4443 return mlir::success();
4447 return std::make_unique<ConvertCIRToLLVMPass>();
4455std::unique_ptr<llvm::Module>
4457 llvm::TimeTraceScope scope(
"lower from CIR to LLVM directly");
4459 mlir::MLIRContext *mlirCtx = mlirModule.getContext();
4461 mlir::PassManager pm(mlirCtx);
4464 (void)mlir::applyPassManagerCLOptions(pm);
4466 if (mlir::failed(pm.run(mlirModule))) {
4469 "The pass manager failed to lower CIR to LLVMIR dialect!");
4472 mlir::registerBuiltinDialectTranslation(*mlirCtx);
4473 mlir::registerLLVMDialectTranslation(*mlirCtx);
4476 llvm::TimeTraceScope translateScope(
"translateModuleToLLVMIR");
4478 StringRef moduleName = mlirModule.getName().value_or(
"CIRToLLVMModule");
4479 std::unique_ptr<llvm::Module> llvmModule =
4480 mlir::translateModuleToLLVMIR(mlirModule, llvmCtx, moduleName);
4484 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.
mlir::Value visitCirAttr(cir::IntAttr intAttr)
IntAttr visitor.
mlir::Value visit(mlir::Attribute attr)
CIRAttrToValue(mlir::Operation *parentOp, mlir::ConversionPatternRewriter &rewriter, const mlir::TypeConverter *converter, cir::LowerModule *lowerMod)
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)
std::unique_ptr< cir::LowerModule > prepareLowerModule(mlir::ModuleOp module)
void createLLVMFuncOpIfNotExist(mlir::ConversionPatternRewriter &rewriter, mlir::Operation *srcOp, llvm::StringRef fnName, mlir::Type fnTy)
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)
mlir::Value lowerCirAttrAsValue(mlir::Operation *parentOp, const mlir::Attribute attr, mlir::ConversionPatternRewriter &rewriter, const mlir::TypeConverter *converter, cir::LowerModule *lowerMod)
Switches on the type of attribute and calls the appropriate conversion.
static mlir::Value getLLVMIntCast(mlir::ConversionPatternRewriter &rewriter, mlir::Value llvmSrc, mlir::Type llvmDstIntTy, bool isUnsigned, uint64_t cirSrcWidth, uint64_t cirDstIntWidth)
static std::optional< llvm::StringRef > getLLVMSyncScope(std::optional< cir::SyncScopeKind > syncScope)
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 void prepareTypeConverter(mlir::LLVMTypeConverter &converter, mlir::DataLayout &dataLayout, cir::LowerModule *lowerModule)
static mlir::LogicalResult rewriteCallOrInvoke(mlir::Operation *op, mlir::ValueRange callOperands, mlir::ConversionPatternRewriter &rewriter, const mlir::TypeConverter *converter, mlir::FlatSymbolRefAttr calleeAttr)
static mlir::LLVM::LLVMStructType getLLVMLandingPadStructTy(mlir::ConversionPatternRewriter &rewriter)
std::unique_ptr< llvm::Module > lowerDirectlyFromCIRToLLVMIR(mlir::ModuleOp mlirModule, llvm::LLVMContext &llvmCtx)
static llvm::StringLiteral getLLVMBinop(cir::AtomicFetchKind k, bool isInt)
static mlir::Value convertToIndexTy(mlir::ConversionPatternRewriter &rewriter, mlir::ModuleOp mod, mlir::Value index, mlir::Type baseTy, cir::IntType strideTy)
static mlir::LLVM::CallIntrinsicOp replaceOpWithCallLLVMIntrinsicOp(mlir::ConversionPatternRewriter &rewriter, mlir::Operation *op, const llvm::Twine &intrinsicName, mlir::Type resultTy, mlir::ValueRange operands)
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 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 uint64_t getTypeSize(mlir::Type type, mlir::Operation &op)
void populateCIRToLLVMPasses(mlir::OpPassManager &pm)
Adds passes that fully lower CIR to the LLVMIR dialect.
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::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::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 bool isIntTypeUnsigned(mlir::Type type)
std::unique_ptr< LowerModule > createLowerModule(mlir::ModuleOp module, mlir::PatternRewriter &rewriter)
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 atomicScope()
static bool opLoadStoreTbaa()
static bool optInfoAttr()
static bool opFuncExtraAttrs()
static bool opCallLandingPad()
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 opCallContinueBlock()
static bool llvmLoweringPtrDiffConsidersPointee()
static bool opLoadStoreNontemporal()
static bool makeTripleAlwaysPresent()
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 processCIRAttrs(mlir::ModuleOp module)