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>();
712 return "Convert the prepared CIR dialect module to LLVM dialect";
715 StringRef
getArgument()
const override {
return "cir-flat-to-llvm"; }
718mlir::LogicalResult CIRToLLVMACosOpLowering::matchAndRewrite(
719 cir::ACosOp op, OpAdaptor adaptor,
720 mlir::ConversionPatternRewriter &rewriter)
const {
721 mlir::Type resTy = typeConverter->convertType(op.getType());
722 rewriter.replaceOpWithNewOp<mlir::LLVM::ACosOp>(op, resTy,
723 adaptor.getOperands()[0]);
724 return mlir::success();
727mlir::LogicalResult CIRToLLVMASinOpLowering::matchAndRewrite(
728 cir::ASinOp op, OpAdaptor adaptor,
729 mlir::ConversionPatternRewriter &rewriter)
const {
730 mlir::Type resTy = typeConverter->convertType(op.getType());
731 rewriter.replaceOpWithNewOp<mlir::LLVM::ASinOp>(op, resTy, adaptor.getSrc());
732 return mlir::success();
735mlir::LogicalResult CIRToLLVMIsFPClassOpLowering::matchAndRewrite(
736 cir::IsFPClassOp op, OpAdaptor adaptor,
737 mlir::ConversionPatternRewriter &rewriter)
const {
738 mlir::Value src = adaptor.getSrc();
739 cir::FPClassTest flags = adaptor.getFlags();
740 mlir::IntegerType retTy = rewriter.getI1Type();
742 rewriter.replaceOpWithNewOp<mlir::LLVM::IsFPClass>(
743 op, retTy, src,
static_cast<uint32_t>(flags));
744 return mlir::success();
747mlir::LogicalResult CIRToLLVMAssumeOpLowering::matchAndRewrite(
748 cir::AssumeOp op, OpAdaptor adaptor,
749 mlir::ConversionPatternRewriter &rewriter)
const {
750 auto cond = adaptor.getPredicate();
751 rewriter.replaceOpWithNewOp<mlir::LLVM::AssumeOp>(op, cond);
752 return mlir::success();
755mlir::LogicalResult CIRToLLVMAssumeAlignedOpLowering::matchAndRewrite(
756 cir::AssumeAlignedOp op, OpAdaptor adaptor,
757 mlir::ConversionPatternRewriter &rewriter)
const {
758 SmallVector<mlir::Value, 3> opBundleArgs{adaptor.getPointer()};
760 auto alignment = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
761 adaptor.getAlignmentAttr());
762 opBundleArgs.push_back(alignment);
764 if (mlir::Value offset = adaptor.getOffset())
765 opBundleArgs.push_back(offset);
767 auto cond = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
768 rewriter.getI1Type(), 1);
769 mlir::LLVM::AssumeOp::create(rewriter, op.getLoc(), cond,
"align",
774 rewriter.replaceOp(op, adaptor.getPointer());
775 return mlir::success();
778mlir::LogicalResult CIRToLLVMAssumeSepStorageOpLowering::matchAndRewrite(
779 cir::AssumeSepStorageOp op, OpAdaptor adaptor,
780 mlir::ConversionPatternRewriter &rewriter)
const {
781 auto cond = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
782 rewriter.getI1Type(), 1);
783 rewriter.replaceOpWithNewOp<mlir::LLVM::AssumeOp>(
784 op, cond, mlir::LLVM::AssumeSeparateStorageTag{}, adaptor.getPtr1(),
786 return mlir::success();
789static mlir::LLVM::AtomicOrdering
792 return mlir::LLVM::AtomicOrdering::not_atomic;
794 case cir::MemOrder::Relaxed:
795 return mlir::LLVM::AtomicOrdering::monotonic;
796 case cir::MemOrder::Consume:
797 case cir::MemOrder::Acquire:
798 return mlir::LLVM::AtomicOrdering::acquire;
799 case cir::MemOrder::Release:
800 return mlir::LLVM::AtomicOrdering::release;
801 case cir::MemOrder::AcquireRelease:
802 return mlir::LLVM::AtomicOrdering::acq_rel;
803 case cir::MemOrder::SequentiallyConsistent:
804 return mlir::LLVM::AtomicOrdering::seq_cst;
806 llvm_unreachable(
"unknown memory order");
809static std::optional<llvm::StringRef>
811 if (syncScope.has_value())
812 return syncScope.value() == cir::SyncScopeKind::SingleThread
818mlir::LogicalResult CIRToLLVMAtomicCmpXchgOpLowering::matchAndRewrite(
819 cir::AtomicCmpXchgOp op, OpAdaptor adaptor,
820 mlir::ConversionPatternRewriter &rewriter)
const {
821 mlir::Value expected = adaptor.getExpected();
822 mlir::Value desired = adaptor.getDesired();
824 auto cmpxchg = mlir::LLVM::AtomicCmpXchgOp::create(
825 rewriter, op.getLoc(), adaptor.getPtr(), expected, desired,
829 cmpxchg.setAlignment(adaptor.getAlignment());
830 cmpxchg.setWeak(adaptor.getWeak());
831 cmpxchg.setVolatile_(adaptor.getIsVolatile());
834 auto old = mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(),
835 cmpxchg.getResult(), 0);
836 auto cmp = mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(),
837 cmpxchg.getResult(), 1);
839 rewriter.replaceOp(op, {old, cmp});
840 return mlir::success();
843mlir::LogicalResult CIRToLLVMAtomicXchgOpLowering::matchAndRewrite(
844 cir::AtomicXchgOp op, OpAdaptor adaptor,
845 mlir::ConversionPatternRewriter &rewriter)
const {
847 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(adaptor.getMemOrder());
848 rewriter.replaceOpWithNewOp<mlir::LLVM::AtomicRMWOp>(
849 op, mlir::LLVM::AtomicBinOp::xchg, adaptor.getPtr(), adaptor.getVal(),
851 return mlir::success();
854mlir::LogicalResult CIRToLLVMAtomicTestAndSetOpLowering::matchAndRewrite(
855 cir::AtomicTestAndSetOp op, OpAdaptor adaptor,
856 mlir::ConversionPatternRewriter &rewriter)
const {
859 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
861 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
862 rewriter.getI8Type(), 1);
863 auto rmw = mlir::LLVM::AtomicRMWOp::create(
864 rewriter, op.getLoc(), mlir::LLVM::AtomicBinOp::xchg, adaptor.getPtr(),
865 one, llvmOrder, llvm::StringRef(),
866 adaptor.getAlignment().value_or(0), op.getIsVolatile());
868 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
869 rewriter.getI8Type(), 0);
870 auto cmp = mlir::LLVM::ICmpOp::create(
871 rewriter, op.getLoc(), mlir::LLVM::ICmpPredicate::ne, rmw, zero);
873 rewriter.replaceOp(op, cmp);
874 return mlir::success();
877mlir::LogicalResult CIRToLLVMAtomicClearOpLowering::matchAndRewrite(
878 cir::AtomicClearOp op, OpAdaptor adaptor,
879 mlir::ConversionPatternRewriter &rewriter)
const {
882 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
883 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
884 rewriter.getI8Type(), 0);
885 auto store = mlir::LLVM::StoreOp::create(
886 rewriter, op.getLoc(), zero, adaptor.getPtr(),
887 adaptor.getAlignment().value_or(0), op.getIsVolatile(),
888 false,
false, llvmOrder);
890 rewriter.replaceOp(op, store);
891 return mlir::success();
894mlir::LogicalResult CIRToLLVMAtomicFenceOpLowering::matchAndRewrite(
895 cir::AtomicFenceOp op, OpAdaptor adaptor,
896 mlir::ConversionPatternRewriter &rewriter)
const {
897 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(adaptor.getOrdering());
899 auto fence = mlir::LLVM::FenceOp::create(rewriter, op.getLoc(), llvmOrder);
902 rewriter.replaceOp(op, fence);
904 return mlir::success();
907static mlir::LLVM::AtomicBinOp
910 case cir::AtomicFetchKind::Add:
911 return isInt ? mlir::LLVM::AtomicBinOp::add : mlir::LLVM::AtomicBinOp::fadd;
912 case cir::AtomicFetchKind::Sub:
913 return isInt ? mlir::LLVM::AtomicBinOp::sub : mlir::LLVM::AtomicBinOp::fsub;
914 case cir::AtomicFetchKind::And:
915 return mlir::LLVM::AtomicBinOp::_and;
916 case cir::AtomicFetchKind::Xor:
917 return mlir::LLVM::AtomicBinOp::_xor;
918 case cir::AtomicFetchKind::Or:
919 return mlir::LLVM::AtomicBinOp::_or;
920 case cir::AtomicFetchKind::Nand:
921 return mlir::LLVM::AtomicBinOp::nand;
922 case cir::AtomicFetchKind::Max: {
924 return mlir::LLVM::AtomicBinOp::fmax;
925 return isSignedInt ? mlir::LLVM::AtomicBinOp::max
926 : mlir::LLVM::AtomicBinOp::umax;
928 case cir::AtomicFetchKind::Min: {
930 return mlir::LLVM::AtomicBinOp::fmin;
931 return isSignedInt ? mlir::LLVM::AtomicBinOp::min
932 : mlir::LLVM::AtomicBinOp::umin;
935 llvm_unreachable(
"Unknown atomic fetch opcode");
938static llvm::StringLiteral
getLLVMBinop(cir::AtomicFetchKind k,
bool isInt) {
940 case cir::AtomicFetchKind::Add:
941 return isInt ? mlir::LLVM::AddOp::getOperationName()
942 : mlir::LLVM::FAddOp::getOperationName();
943 case cir::AtomicFetchKind::Sub:
944 return isInt ? mlir::LLVM::SubOp::getOperationName()
945 : mlir::LLVM::FSubOp::getOperationName();
946 case cir::AtomicFetchKind::And:
947 return mlir::LLVM::AndOp::getOperationName();
948 case cir::AtomicFetchKind::Xor:
949 return mlir::LLVM::XOrOp::getOperationName();
950 case cir::AtomicFetchKind::Or:
951 return mlir::LLVM::OrOp::getOperationName();
952 case cir::AtomicFetchKind::Nand:
954 return mlir::LLVM::AndOp::getOperationName();
955 case cir::AtomicFetchKind::Max:
956 case cir::AtomicFetchKind::Min:
957 llvm_unreachable(
"handled in buildMinMaxPostOp");
959 llvm_unreachable(
"Unknown atomic fetch opcode");
962mlir::Value CIRToLLVMAtomicFetchOpLowering::buildPostOp(
963 cir::AtomicFetchOp op, OpAdaptor adaptor,
964 mlir::ConversionPatternRewriter &rewriter, mlir::Value rmwVal,
970 rewriter.getStringAttr(
getLLVMBinop(op.getBinop(), isInt)),
971 atomicOperands, atomicResTys, {})
975mlir::Value CIRToLLVMAtomicFetchOpLowering::buildMinMaxPostOp(
976 cir::AtomicFetchOp op, OpAdaptor adaptor,
977 mlir::ConversionPatternRewriter &rewriter, mlir::Value rmwVal,
bool isInt,
978 bool isSigned)
const {
979 mlir::Location loc = op.getLoc();
982 if (op.getBinop() == cir::AtomicFetchKind::Max)
983 return mlir::LLVM::MaxNumOp::create(rewriter, loc, rmwVal,
985 return mlir::LLVM::MinNumOp::create(rewriter, loc, rmwVal,
989 mlir::LLVM::ICmpPredicate pred;
990 if (op.getBinop() == cir::AtomicFetchKind::Max) {
991 pred = isSigned ? mlir::LLVM::ICmpPredicate::sgt
992 : mlir::LLVM::ICmpPredicate::ugt;
994 pred = isSigned ? mlir::LLVM::ICmpPredicate::slt
995 : mlir::LLVM::ICmpPredicate::ult;
997 mlir::Value cmp = mlir::LLVM::ICmpOp::create(
999 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(), pred), rmwVal,
1001 return mlir::LLVM::SelectOp::create(rewriter, loc, cmp, rmwVal,
1005mlir::LogicalResult CIRToLLVMAtomicFetchOpLowering::matchAndRewrite(
1006 cir::AtomicFetchOp op, OpAdaptor adaptor,
1007 mlir::ConversionPatternRewriter &rewriter)
const {
1009 bool isSignedInt =
false;
1010 if (
auto intTy = mlir::dyn_cast<cir::IntType>(op.getVal().getType())) {
1012 isSignedInt = intTy.isSigned();
1013 }
else if (mlir::isa<cir::SingleType, cir::DoubleType>(
1014 op.getVal().getType())) {
1017 return op.emitError() <<
"Unsupported type: " << op.getVal().getType();
1020 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
1021 mlir::LLVM::AtomicBinOp llvmBinOp =
1023 auto rmwVal = mlir::LLVM::AtomicRMWOp::create(rewriter, op.getLoc(),
1024 llvmBinOp, adaptor.getPtr(),
1025 adaptor.getVal(), llvmOrder);
1027 mlir::Value result = rmwVal.getResult();
1028 if (!op.getFetchFirst()) {
1029 if (op.getBinop() == cir::AtomicFetchKind::Max ||
1030 op.getBinop() == cir::AtomicFetchKind::Min)
1031 result = buildMinMaxPostOp(op, adaptor, rewriter, rmwVal.getRes(), isInt,
1034 result = buildPostOp(op, adaptor, rewriter, rmwVal.getRes(), isInt);
1037 if (op.getBinop() == cir::AtomicFetchKind::Nand) {
1038 auto negOne = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1039 result.getType(), -1);
1040 result = mlir::LLVM::XOrOp::create(rewriter, op.getLoc(), result, negOne);
1044 rewriter.replaceOp(op, result);
1045 return mlir::success();
1048mlir::LogicalResult CIRToLLVMBitClrsbOpLowering::matchAndRewrite(
1049 cir::BitClrsbOp op, OpAdaptor adaptor,
1050 mlir::ConversionPatternRewriter &rewriter)
const {
1051 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1052 adaptor.getInput().getType(), 0);
1053 auto isNeg = mlir::LLVM::ICmpOp::create(
1054 rewriter, op.getLoc(),
1055 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(),
1056 mlir::LLVM::ICmpPredicate::slt),
1057 adaptor.getInput(), zero);
1059 auto negOne = mlir::LLVM::ConstantOp::create(
1060 rewriter, op.getLoc(), adaptor.getInput().getType(), -1);
1061 auto flipped = mlir::LLVM::XOrOp::create(rewriter, op.getLoc(),
1062 adaptor.getInput(), negOne);
1064 auto select = mlir::LLVM::SelectOp::create(rewriter, op.getLoc(), isNeg,
1065 flipped, adaptor.getInput());
1067 auto resTy = getTypeConverter()->convertType(op.getType());
1068 auto clz = mlir::LLVM::CountLeadingZerosOp::create(
1069 rewriter, op.getLoc(), resTy,
select,
false);
1071 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1072 auto res = mlir::LLVM::SubOp::create(rewriter, op.getLoc(),
clz, one,
1073 mlir::LLVM::IntegerOverflowFlags::nuw);
1074 rewriter.replaceOp(op, res);
1076 return mlir::LogicalResult::success();
1079mlir::LogicalResult CIRToLLVMBitClzOpLowering::matchAndRewrite(
1080 cir::BitClzOp op, OpAdaptor adaptor,
1081 mlir::ConversionPatternRewriter &rewriter)
const {
1082 auto resTy = getTypeConverter()->convertType(op.getType());
1083 auto llvmOp = mlir::LLVM::CountLeadingZerosOp::create(
1084 rewriter, op.getLoc(), resTy, adaptor.getInput(), op.getPoisonZero());
1085 rewriter.replaceOp(op, llvmOp);
1086 return mlir::LogicalResult::success();
1089mlir::LogicalResult CIRToLLVMBitCtzOpLowering::matchAndRewrite(
1090 cir::BitCtzOp op, OpAdaptor adaptor,
1091 mlir::ConversionPatternRewriter &rewriter)
const {
1092 auto resTy = getTypeConverter()->convertType(op.getType());
1093 auto llvmOp = mlir::LLVM::CountTrailingZerosOp::create(
1094 rewriter, op.getLoc(), resTy, adaptor.getInput(), op.getPoisonZero());
1095 rewriter.replaceOp(op, llvmOp);
1096 return mlir::LogicalResult::success();
1099mlir::LogicalResult CIRToLLVMBitFfsOpLowering::matchAndRewrite(
1100 cir::BitFfsOp op, OpAdaptor adaptor,
1101 mlir::ConversionPatternRewriter &rewriter)
const {
1102 auto resTy = getTypeConverter()->convertType(op.getType());
1103 auto ctz = mlir::LLVM::CountTrailingZerosOp::create(rewriter, op.getLoc(),
1104 resTy, adaptor.getInput(),
1107 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1108 auto ctzAddOne = mlir::LLVM::AddOp::create(rewriter, op.getLoc(),
ctz, one);
1110 auto zeroInputTy = mlir::LLVM::ConstantOp::create(
1111 rewriter, op.getLoc(), adaptor.getInput().getType(), 0);
1112 auto isZero = mlir::LLVM::ICmpOp::create(
1113 rewriter, op.getLoc(),
1114 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(),
1115 mlir::LLVM::ICmpPredicate::eq),
1116 adaptor.getInput(), zeroInputTy);
1118 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 0);
1119 auto res = mlir::LLVM::SelectOp::create(rewriter, op.getLoc(), isZero, zero,
1121 rewriter.replaceOp(op, res);
1123 return mlir::LogicalResult::success();
1126mlir::LogicalResult CIRToLLVMBitParityOpLowering::matchAndRewrite(
1127 cir::BitParityOp op, OpAdaptor adaptor,
1128 mlir::ConversionPatternRewriter &rewriter)
const {
1129 auto resTy = getTypeConverter()->convertType(op.getType());
1130 auto popcnt = mlir::LLVM::CtPopOp::create(rewriter, op.getLoc(), resTy,
1131 adaptor.getInput());
1133 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1135 mlir::LLVM::AndOp::create(rewriter, op.getLoc(), popcnt, one);
1136 rewriter.replaceOp(op, popcntMod2);
1138 return mlir::LogicalResult::success();
1141mlir::LogicalResult CIRToLLVMBitPopcountOpLowering::matchAndRewrite(
1142 cir::BitPopcountOp op, OpAdaptor adaptor,
1143 mlir::ConversionPatternRewriter &rewriter)
const {
1144 auto resTy = getTypeConverter()->convertType(op.getType());
1145 auto llvmOp = mlir::LLVM::CtPopOp::create(rewriter, op.getLoc(), resTy,
1146 adaptor.getInput());
1147 rewriter.replaceOp(op, llvmOp);
1148 return mlir::LogicalResult::success();
1151mlir::LogicalResult CIRToLLVMBitReverseOpLowering::matchAndRewrite(
1152 cir::BitReverseOp op, OpAdaptor adaptor,
1153 mlir::ConversionPatternRewriter &rewriter)
const {
1154 rewriter.replaceOpWithNewOp<mlir::LLVM::BitReverseOp>(op, adaptor.getInput());
1155 return mlir::success();
1158mlir::LogicalResult CIRToLLVMBrCondOpLowering::matchAndRewrite(
1159 cir::BrCondOp brOp, OpAdaptor adaptor,
1160 mlir::ConversionPatternRewriter &rewriter)
const {
1165 mlir::Value i1Condition = adaptor.getCond();
1167 rewriter.replaceOpWithNewOp<mlir::LLVM::CondBrOp>(
1168 brOp, i1Condition, brOp.getDestTrue(), adaptor.getDestOperandsTrue(),
1169 brOp.getDestFalse(), adaptor.getDestOperandsFalse());
1171 return mlir::success();
1174mlir::LogicalResult CIRToLLVMByteSwapOpLowering::matchAndRewrite(
1175 cir::ByteSwapOp op, OpAdaptor adaptor,
1176 mlir::ConversionPatternRewriter &rewriter)
const {
1177 rewriter.replaceOpWithNewOp<mlir::LLVM::ByteSwapOp>(op, adaptor.getInput());
1178 return mlir::LogicalResult::success();
1181mlir::Type CIRToLLVMCastOpLowering::convertTy(mlir::Type ty)
const {
1182 return getTypeConverter()->convertType(ty);
1185mlir::LogicalResult CIRToLLVMCastOpLowering::matchAndRewrite(
1186 cir::CastOp castOp, OpAdaptor adaptor,
1187 mlir::ConversionPatternRewriter &rewriter)
const {
1192 switch (castOp.getKind()) {
1193 case cir::CastKind::array_to_ptrdecay: {
1194 const auto ptrTy = mlir::cast<cir::PointerType>(castOp.getType());
1195 mlir::Value sourceValue = adaptor.getSrc();
1196 mlir::Type targetType = convertTy(ptrTy);
1198 ptrTy.getPointee());
1199 llvm::SmallVector<mlir::LLVM::GEPArg> offset{0};
1200 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1201 castOp, targetType, elementTy, sourceValue, offset);
1204 case cir::CastKind::int_to_bool: {
1205 mlir::Value llvmSrcVal = adaptor.getSrc();
1206 mlir::Value zeroInt = mlir::LLVM::ConstantOp::create(
1207 rewriter, castOp.getLoc(), llvmSrcVal.getType(), 0);
1208 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
1209 castOp, mlir::LLVM::ICmpPredicate::ne, llvmSrcVal, zeroInt);
1212 case cir::CastKind::integral: {
1213 mlir::Type srcType = castOp.getSrc().getType();
1214 mlir::Type dstType = castOp.getType();
1215 mlir::Value llvmSrcVal = adaptor.getSrc();
1216 mlir::Type llvmDstType = getTypeConverter()->convertType(dstType);
1217 cir::IntType srcIntType =
1218 mlir::cast<cir::IntType>(elementTypeIfVector(srcType));
1219 cir::IntType dstIntType =
1220 mlir::cast<cir::IntType>(elementTypeIfVector(dstType));
1221 rewriter.replaceOp(castOp,
getLLVMIntCast(rewriter, llvmSrcVal, llvmDstType,
1222 srcIntType.isUnsigned(),
1223 srcIntType.getWidth(),
1224 dstIntType.getWidth()));
1227 case cir::CastKind::floating: {
1228 mlir::Value llvmSrcVal = adaptor.getSrc();
1229 mlir::Type llvmDstTy = getTypeConverter()->convertType(castOp.getType());
1231 mlir::Type srcTy = elementTypeIfVector(castOp.getSrc().getType());
1232 mlir::Type dstTy = elementTypeIfVector(castOp.getType());
1234 if (!mlir::isa<cir::FPTypeInterface>(dstTy) ||
1235 !mlir::isa<cir::FPTypeInterface>(srcTy))
1236 return castOp.emitError() <<
"NYI cast from " << srcTy <<
" to " << dstTy;
1238 auto getFloatWidth = [](mlir::Type ty) ->
unsigned {
1239 return mlir::cast<cir::FPTypeInterface>(ty).getWidth();
1242 if (getFloatWidth(srcTy) > getFloatWidth(dstTy))
1243 rewriter.replaceOpWithNewOp<mlir::LLVM::FPTruncOp>(castOp, llvmDstTy,
1246 rewriter.replaceOpWithNewOp<mlir::LLVM::FPExtOp>(castOp, llvmDstTy,
1248 return mlir::success();
1250 case cir::CastKind::int_to_ptr: {
1251 auto dstTy = mlir::cast<cir::PointerType>(castOp.getType());
1252 mlir::Value llvmSrcVal = adaptor.getSrc();
1253 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1254 rewriter.replaceOpWithNewOp<mlir::LLVM::IntToPtrOp>(castOp, llvmDstTy,
1256 return mlir::success();
1258 case cir::CastKind::ptr_to_int: {
1259 auto dstTy = mlir::cast<cir::IntType>(castOp.getType());
1260 mlir::Value llvmSrcVal = adaptor.getSrc();
1261 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1262 rewriter.replaceOpWithNewOp<mlir::LLVM::PtrToIntOp>(castOp, llvmDstTy,
1264 return mlir::success();
1266 case cir::CastKind::float_to_bool: {
1267 mlir::Value llvmSrcVal = adaptor.getSrc();
1268 auto kind = mlir::LLVM::FCmpPredicate::une;
1271 auto zeroFloat = mlir::LLVM::ConstantOp::create(
1272 rewriter, castOp.getLoc(), llvmSrcVal.getType(),
1273 mlir::FloatAttr::get(llvmSrcVal.getType(), 0.0));
1276 rewriter.replaceOpWithNewOp<mlir::LLVM::FCmpOp>(castOp,
kind, llvmSrcVal,
1279 return mlir::success();
1281 case cir::CastKind::bool_to_int: {
1282 auto dstTy = mlir::cast<cir::IntType>(castOp.getType());
1283 mlir::Value llvmSrcVal = adaptor.getSrc();
1284 auto llvmSrcTy = mlir::cast<mlir::IntegerType>(llvmSrcVal.getType());
1286 mlir::cast<mlir::IntegerType>(getTypeConverter()->convertType(dstTy));
1287 if (llvmSrcTy.getWidth() == llvmDstTy.getWidth())
1288 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(castOp, llvmDstTy,
1291 rewriter.replaceOpWithNewOp<mlir::LLVM::ZExtOp>(castOp, llvmDstTy,
1293 return mlir::success();
1295 case cir::CastKind::bool_to_float: {
1296 mlir::Type dstTy = castOp.getType();
1297 mlir::Value llvmSrcVal = adaptor.getSrc();
1298 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1299 rewriter.replaceOpWithNewOp<mlir::LLVM::UIToFPOp>(castOp, llvmDstTy,
1301 return mlir::success();
1303 case cir::CastKind::int_to_float: {
1304 mlir::Type dstTy = castOp.getType();
1305 mlir::Value llvmSrcVal = adaptor.getSrc();
1306 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1307 if (mlir::cast<cir::IntType>(elementTypeIfVector(castOp.getSrc().getType()))
1309 rewriter.replaceOpWithNewOp<mlir::LLVM::SIToFPOp>(castOp, llvmDstTy,
1312 rewriter.replaceOpWithNewOp<mlir::LLVM::UIToFPOp>(castOp, llvmDstTy,
1314 return mlir::success();
1316 case cir::CastKind::float_to_int: {
1317 mlir::Type dstTy = castOp.getType();
1318 mlir::Value llvmSrcVal = adaptor.getSrc();
1319 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1320 if (mlir::cast<cir::IntType>(elementTypeIfVector(castOp.getType()))
1322 rewriter.replaceOpWithNewOp<mlir::LLVM::FPToSIOp>(castOp, llvmDstTy,
1325 rewriter.replaceOpWithNewOp<mlir::LLVM::FPToUIOp>(castOp, llvmDstTy,
1327 return mlir::success();
1329 case cir::CastKind::bitcast: {
1330 mlir::Type dstTy = castOp.getType();
1331 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1336 mlir::Value llvmSrcVal = adaptor.getSrc();
1337 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(castOp, llvmDstTy,
1339 return mlir::success();
1341 case cir::CastKind::ptr_to_bool: {
1342 mlir::Value llvmSrcVal = adaptor.getSrc();
1343 mlir::Value zeroPtr = mlir::LLVM::ZeroOp::create(rewriter, castOp.getLoc(),
1344 llvmSrcVal.getType());
1345 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
1346 castOp, mlir::LLVM::ICmpPredicate::ne, llvmSrcVal, zeroPtr);
1349 case cir::CastKind::address_space: {
1350 mlir::Type dstTy = castOp.getType();
1351 mlir::Value llvmSrcVal = adaptor.getSrc();
1352 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1353 rewriter.replaceOpWithNewOp<mlir::LLVM::AddrSpaceCastOp>(castOp, llvmDstTy,
1357 case cir::CastKind::member_ptr_to_bool:
1362 return castOp.emitError(
"Unhandled cast kind: ")
1363 << castOp.getKindAttrName();
1367 return mlir::success();
1371 mlir::ModuleOp mod, mlir::Value index,
1372 mlir::Type baseTy, cir::IntType strideTy) {
1373 mlir::Operation *indexOp = index.getDefiningOp();
1377 auto indexType = mlir::cast<mlir::IntegerType>(index.getType());
1378 mlir::DataLayout llvmLayout(mod);
1379 std::optional<uint64_t> layoutWidth = llvmLayout.getTypeIndexBitwidth(baseTy);
1382 if (!layoutWidth || *layoutWidth == indexType.getWidth())
1388 auto sub = dyn_cast<mlir::LLVM::SubOp>(indexOp);
1389 bool rewriteSub =
false;
1392 dyn_cast<mlir::LLVM::ConstantOp>(sub.getLhs().getDefiningOp())) {
1393 auto lhsConstInt = mlir::dyn_cast<mlir::IntegerAttr>(lhsConst.getValue());
1394 if (lhsConstInt && lhsConstInt.getValue() == 0) {
1395 index = sub.getRhs();
1401 auto llvmDstType = rewriter.getIntegerType(*layoutWidth);
1402 bool isUnsigned = strideTy && strideTy.isUnsigned();
1404 indexType.getWidth(), *layoutWidth);
1407 index = mlir::LLVM::SubOp::create(
1408 rewriter, index.getLoc(),
1409 mlir::LLVM::ConstantOp::create(rewriter, index.getLoc(),
1410 index.getType(), 0),
1413 rewriter.eraseOp(sub);
1419mlir::LogicalResult CIRToLLVMPtrStrideOpLowering::matchAndRewrite(
1420 cir::PtrStrideOp ptrStrideOp, OpAdaptor adaptor,
1421 mlir::ConversionPatternRewriter &rewriter)
const {
1423 const mlir::TypeConverter *tc = getTypeConverter();
1424 const mlir::Type resultTy = tc->convertType(ptrStrideOp.getType());
1426 mlir::Type elementTy =
1431 if (mlir::isa<mlir::LLVM::LLVMVoidType>(elementTy) ||
1432 mlir::isa<mlir::LLVM::LLVMFunctionType>(elementTy))
1433 elementTy = mlir::IntegerType::get(elementTy.getContext(), 8,
1434 mlir::IntegerType::Signless);
1436 mlir::Value index = adaptor.getStride();
1438 rewriter, ptrStrideOp->getParentOfType<mlir::ModuleOp>(), index,
1439 adaptor.getBase().getType(),
1440 dyn_cast<cir::IntType>(ptrStrideOp.getOperand(1).getType()));
1442 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1443 ptrStrideOp, resultTy, elementTy, adaptor.getBase(), index);
1444 return mlir::success();
1447mlir::LogicalResult CIRToLLVMGetElementOpLowering::matchAndRewrite(
1448 cir::GetElementOp op, OpAdaptor adaptor,
1449 mlir::ConversionPatternRewriter &rewriter)
const {
1451 mlir::dyn_cast<cir::ArrayType>(op.getBaseType().getPointee())) {
1452 const mlir::TypeConverter *converter = getTypeConverter();
1453 const mlir::Type llArrayTy = converter->convertType(arrayTy);
1454 const mlir::Type llResultTy = converter->convertType(op.getType());
1455 mlir::Type elementTy =
1460 if (mlir::isa<mlir::LLVM::LLVMVoidType>(elementTy) ||
1461 mlir::isa<mlir::LLVM::LLVMFunctionType>(elementTy))
1462 elementTy = rewriter.getIntegerType(8);
1464 mlir::Value index = adaptor.getIndex();
1467 adaptor.getBase().getType(),
1468 dyn_cast<cir::IntType>(op.getOperand(1).getType()));
1473 std::array<mlir::LLVM::GEPArg, 2> offset{0, index};
1474 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, llResultTy, llArrayTy,
1475 adaptor.getBase(), offset);
1476 return mlir::success();
1479 op.emitError() <<
"NYI: GetElementOp lowering to LLVM for non-array";
1480 return mlir::failure();
1483mlir::LogicalResult CIRToLLVMBaseClassAddrOpLowering::matchAndRewrite(
1484 cir::BaseClassAddrOp baseClassOp, OpAdaptor adaptor,
1485 mlir::ConversionPatternRewriter &rewriter)
const {
1486 const mlir::Type resultType =
1487 getTypeConverter()->convertType(baseClassOp.getType());
1488 mlir::Value derivedAddr = adaptor.getDerivedAddr();
1489 llvm::SmallVector<mlir::LLVM::GEPArg, 1> offset = {
1490 adaptor.getOffset().getZExtValue()};
1491 mlir::Type byteType = mlir::IntegerType::get(resultType.getContext(), 8,
1492 mlir::IntegerType::Signless);
1493 if (adaptor.getOffset().getZExtValue() == 0) {
1494 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(
1495 baseClassOp, resultType, adaptor.getDerivedAddr());
1496 return mlir::success();
1499 if (baseClassOp.getAssumeNotNull()) {
1500 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1501 baseClassOp, resultType, byteType, derivedAddr, offset);
1503 auto loc = baseClassOp.getLoc();
1504 mlir::Value isNull = mlir::LLVM::ICmpOp::create(
1505 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, derivedAddr,
1506 mlir::LLVM::ZeroOp::create(rewriter, loc, derivedAddr.getType()));
1507 mlir::Value adjusted = mlir::LLVM::GEPOp::create(
1508 rewriter, loc, resultType, byteType, derivedAddr, offset);
1509 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(baseClassOp, isNull,
1510 derivedAddr, adjusted);
1512 return mlir::success();
1515mlir::LogicalResult CIRToLLVMDerivedClassAddrOpLowering::matchAndRewrite(
1516 cir::DerivedClassAddrOp derivedClassOp, OpAdaptor adaptor,
1517 mlir::ConversionPatternRewriter &rewriter)
const {
1518 const mlir::Type resultType =
1519 getTypeConverter()->convertType(derivedClassOp.getType());
1520 mlir::Value baseAddr = adaptor.getBaseAddr();
1523 int64_t offsetVal = -(adaptor.getOffset().getZExtValue());
1524 if (offsetVal == 0) {
1526 rewriter.replaceOp(derivedClassOp, baseAddr);
1527 return mlir::success();
1529 llvm::SmallVector<mlir::LLVM::GEPArg, 1> offset = {offsetVal};
1530 mlir::Type byteType = mlir::IntegerType::get(resultType.getContext(), 8,
1531 mlir::IntegerType::Signless);
1532 if (derivedClassOp.getAssumeNotNull()) {
1533 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1534 derivedClassOp, resultType, byteType, baseAddr, offset,
1535 mlir::LLVM::GEPNoWrapFlags::inbounds);
1537 mlir::Location loc = derivedClassOp.getLoc();
1538 mlir::Value isNull = mlir::LLVM::ICmpOp::create(
1539 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, baseAddr,
1540 mlir::LLVM::ZeroOp::create(rewriter, loc, baseAddr.getType()));
1541 mlir::Value adjusted =
1542 mlir::LLVM::GEPOp::create(rewriter, loc, resultType, byteType, baseAddr,
1543 offset, mlir::LLVM::GEPNoWrapFlags::inbounds);
1544 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(derivedClassOp, isNull,
1545 baseAddr, adjusted);
1547 return mlir::success();
1550mlir::LogicalResult CIRToLLVMATanOpLowering::matchAndRewrite(
1551 cir::ATanOp op, OpAdaptor adaptor,
1552 mlir::ConversionPatternRewriter &rewriter)
const {
1553 mlir::Type resTy = typeConverter->convertType(op.getType());
1554 rewriter.replaceOpWithNewOp<mlir::LLVM::ATanOp>(op, resTy, adaptor.getSrc());
1555 return mlir::success();
1558mlir::LogicalResult CIRToLLVMCeilOpLowering::matchAndRewrite(
1559 cir::CeilOp op, OpAdaptor adaptor,
1560 mlir::ConversionPatternRewriter &rewriter)
const {
1561 mlir::Type resTy = typeConverter->convertType(op.getType());
1562 rewriter.replaceOpWithNewOp<mlir::LLVM::FCeilOp>(op, resTy, adaptor.getSrc());
1563 return mlir::success();
1566mlir::LogicalResult CIRToLLVMAllocaOpLowering::matchAndRewrite(
1567 cir::AllocaOp op, OpAdaptor adaptor,
1568 mlir::ConversionPatternRewriter &rewriter)
const {
1571 ? adaptor.getDynAllocSize()
1572 : mlir::LLVM::ConstantOp::create(
1573 rewriter, op.getLoc(),
1574 typeConverter->convertType(rewriter.getIndexType()), 1);
1575 mlir::Type elementTy =
1577 mlir::Type resultTy =
1583 rewriter.replaceOpWithNewOp<mlir::LLVM::AllocaOp>(op, resultTy, elementTy,
1584 size, op.getAlignment());
1586 return mlir::success();
1589mlir::LogicalResult CIRToLLVMReturnOpLowering::matchAndRewrite(
1590 cir::ReturnOp op, OpAdaptor adaptor,
1591 mlir::ConversionPatternRewriter &rewriter)
const {
1592 rewriter.replaceOpWithNewOp<mlir::LLVM::ReturnOp>(op, adaptor.getOperands());
1593 return mlir::LogicalResult::success();
1596mlir::LogicalResult CIRToLLVMRotateOpLowering::matchAndRewrite(
1597 cir::RotateOp op, OpAdaptor adaptor,
1598 mlir::ConversionPatternRewriter &rewriter)
const {
1601 mlir::Value input = adaptor.getInput();
1602 if (op.isRotateLeft())
1603 rewriter.replaceOpWithNewOp<mlir::LLVM::FshlOp>(op, input, input,
1604 adaptor.getAmount());
1606 rewriter.replaceOpWithNewOp<mlir::LLVM::FshrOp>(op, input, input,
1607 adaptor.getAmount());
1608 return mlir::LogicalResult::success();
1613 for (mlir::NamedAttribute attr : op->getAttrs()) {
1615 if (attr.getName() == CIRDialect::getCalleeAttrName() ||
1616 attr.getName() == CIRDialect::getSideEffectAttrName() ||
1617 attr.getName() == CIRDialect::getNoThrowAttrName() ||
1618 attr.getName() == CIRDialect::getNoUnwindAttrName() ||
1619 attr.getName() == CIRDialect::getNoReturnAttrName())
1623 result.push_back(attr);
1627static mlir::LogicalResult
1629 mlir::ConversionPatternRewriter &rewriter,
1630 const mlir::TypeConverter *converter,
1631 mlir::FlatSymbolRefAttr calleeAttr) {
1633 mlir::ValueTypeRange<mlir::ResultRange> cirResults = op->getResultTypes();
1634 auto call = cast<cir::CIRCallOpInterface>(op);
1636 if (converter->convertTypes(cirResults, llvmResults).failed())
1637 return mlir::failure();
1641 mlir::LLVM::MemoryEffectsAttr memoryEffects;
1642 bool noUnwind =
false;
1643 bool willReturn =
false;
1644 bool noReturn =
false;
1646 memoryEffects, noUnwind, willReturn, noReturn);
1651 mlir::LLVM::LLVMFunctionType llvmFnTy;
1658 mlir::Operation *callee =
1659 mlir::SymbolTable::lookupNearestSymbolFrom(op, calleeAttr);
1660 if (
auto fn = mlir::dyn_cast<mlir::FunctionOpInterface>(callee)) {
1661 llvmFnTy = converter->convertType<mlir::LLVM::LLVMFunctionType>(
1662 fn.getFunctionType());
1663 assert(llvmFnTy &&
"Failed to convert function type");
1664 }
else if (
auto alias = mlir::cast<mlir::LLVM::AliasOp>(callee)) {
1672 auto symAttr = mlir::cast<mlir::FlatSymbolRefAttr>(calleeAttr);
1674 mlir::LLVM::AddressOfOp::create(
1675 rewriter, op->getLoc(),
1676 mlir::LLVM::LLVMPointerType::get(rewriter.getContext()), symAttr)
1678 adjustedCallOperands.push_back(addrOfAlias);
1681 llvm::append_range(adjustedCallOperands, callOperands);
1682 callOperands = adjustedCallOperands;
1686 llvmFnTy = mlir::cast<mlir::LLVM::LLVMFunctionType>(alias.getType());
1689 return op->emitError(
"Unexpected callee type!");
1692 assert(!op->getOperands().empty() &&
1693 "operands list must no be empty for the indirect call");
1694 auto calleeTy = op->getOperands().front().getType();
1695 auto calleePtrTy = cast<cir::PointerType>(calleeTy);
1696 auto calleeFuncTy = cast<cir::FuncType>(calleePtrTy.getPointee());
1697 llvm::append_range(adjustedCallOperands, callOperands);
1698 llvmFnTy = cast<mlir::LLVM::LLVMFunctionType>(
1699 converter->convertType(calleeFuncTy));
1706 auto newOp = rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(
1707 op, llvmFnTy, calleeAttr, callOperands);
1708 newOp->setAttrs(attributes);
1710 newOp.setMemoryEffectsAttr(memoryEffects);
1711 newOp.setNoUnwind(noUnwind);
1712 newOp.setWillReturn(willReturn);
1713 newOp.setNoreturn(noReturn);
1715 return mlir::success();
1718mlir::LogicalResult CIRToLLVMCallOpLowering::matchAndRewrite(
1719 cir::CallOp op, OpAdaptor adaptor,
1720 mlir::ConversionPatternRewriter &rewriter)
const {
1722 getTypeConverter(), op.getCalleeAttr());
1725mlir::LogicalResult CIRToLLVMReturnAddrOpLowering::matchAndRewrite(
1726 cir::ReturnAddrOp op, OpAdaptor adaptor,
1727 mlir::ConversionPatternRewriter &rewriter)
const {
1728 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
1730 llvmPtrTy, adaptor.getOperands());
1731 return mlir::success();
1734mlir::LogicalResult CIRToLLVMFrameAddrOpLowering::matchAndRewrite(
1735 cir::FrameAddrOp op, OpAdaptor adaptor,
1736 mlir::ConversionPatternRewriter &rewriter)
const {
1737 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
1739 adaptor.getOperands());
1740 return mlir::success();
1743mlir::LogicalResult CIRToLLVMClearCacheOpLowering::matchAndRewrite(
1744 cir::ClearCacheOp op, OpAdaptor adaptor,
1745 mlir::ConversionPatternRewriter &rewriter)
const {
1746 mlir::Value begin = adaptor.getBegin();
1747 mlir::Value end = adaptor.getEnd();
1748 auto intrinNameAttr =
1749 mlir::StringAttr::get(op.getContext(),
"llvm.clear_cache");
1750 rewriter.replaceOpWithNewOp<mlir::LLVM::CallIntrinsicOp>(
1751 op, mlir::Type{}, intrinNameAttr, mlir::ValueRange{begin, end});
1753 return mlir::success();
1756mlir::LogicalResult CIRToLLVMAddrOfReturnAddrOpLowering::matchAndRewrite(
1757 cir::AddrOfReturnAddrOp op, OpAdaptor adaptor,
1758 mlir::ConversionPatternRewriter &rewriter)
const {
1759 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
1761 llvmPtrTy, adaptor.getOperands());
1762 return mlir::success();
1765mlir::LogicalResult CIRToLLVMLoadOpLowering::matchAndRewrite(
1766 cir::LoadOp op, OpAdaptor adaptor,
1767 mlir::ConversionPatternRewriter &rewriter)
const {
1768 const mlir::Type llvmTy =
1770 mlir::LLVM::AtomicOrdering ordering =
getLLVMMemOrder(op.getMemOrder());
1771 std::optional<size_t> opAlign = op.getAlignment();
1772 unsigned alignment =
1773 (unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmTy));
1780 std::optional<std::string> llvmSyncScope;
1781 if (std::optional<cir::SyncScopeKind> syncScope = op.getSyncScope())
1783 lowerMod->getTargetLoweringInfo().getLLVMSyncScope(*syncScope);
1785 mlir::LLVM::LoadOp newLoad = mlir::LLVM::LoadOp::create(
1786 rewriter, op->getLoc(), llvmTy, adaptor.getAddr(), alignment,
1787 op.getIsVolatile(),
false,
1788 false,
false, ordering,
1789 llvmSyncScope.value_or(std::string()));
1792 mlir::Value result =
1794 rewriter.replaceOp(op, result);
1796 return mlir::LogicalResult::success();
1799mlir::LogicalResult CIRToLLVMStoreOpLowering::matchAndRewrite(
1800 cir::StoreOp op, OpAdaptor adaptor,
1801 mlir::ConversionPatternRewriter &rewriter)
const {
1802 mlir::LLVM::AtomicOrdering memorder =
getLLVMMemOrder(op.getMemOrder());
1803 const mlir::Type llvmTy =
1804 getTypeConverter()->convertType(op.getValue().getType());
1805 std::optional<size_t> opAlign = op.getAlignment();
1806 unsigned alignment =
1807 (unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmTy));
1813 op.getValue().getType(), adaptor.getValue());
1818 std::optional<std::string> llvmSyncScope;
1819 if (std::optional<cir::SyncScopeKind> syncScope = op.getSyncScope())
1821 lowerMod->getTargetLoweringInfo().getLLVMSyncScope(*syncScope);
1823 mlir::LLVM::StoreOp storeOp = mlir::LLVM::StoreOp::create(
1824 rewriter, op->getLoc(), value, adaptor.getAddr(), alignment,
1826 false,
false, memorder,
1827 llvmSyncScope.value_or(std::string()));
1828 rewriter.replaceOp(op, storeOp);
1830 return mlir::LogicalResult::success();
1834 auto array = mlir::dyn_cast<mlir::ArrayAttr>(attr.getElts());
1835 return attr.hasTrailingZeros() ||
1836 (array && std::count_if(array.begin(), array.end(), [](
auto elt) {
1837 auto ar = dyn_cast<cir::ConstArrayAttr>(elt);
1838 return ar && hasTrailingZeros(ar);
1842mlir::LogicalResult CIRToLLVMConstantOpLowering::matchAndRewrite(
1843 cir::ConstantOp op, OpAdaptor adaptor,
1844 mlir::ConversionPatternRewriter &rewriter)
const {
1845 mlir::Attribute attr = op.getValue();
1847 if (mlir::isa<cir::PoisonAttr>(attr)) {
1848 rewriter.replaceOpWithNewOp<mlir::LLVM::PoisonOp>(
1849 op, getTypeConverter()->convertType(op.getType()));
1850 return mlir::success();
1853 if (mlir::isa<mlir::IntegerType>(op.getType())) {
1858 attr = op.getValue();
1859 }
else if (mlir::isa<cir::BoolType>(op.getType())) {
1860 int value = mlir::cast<cir::BoolAttr>(op.getValue()).getValue();
1861 attr = rewriter.getIntegerAttr(typeConverter->convertType(op.getType()),
1863 }
else if (mlir::isa<cir::IntType>(op.getType())) {
1865 if (
auto ga = mlir::dyn_cast<cir::GlobalViewAttr>(op.getValue())) {
1871 op.emitError() <<
"global view with integer type";
1872 return mlir::failure();
1875 attr = rewriter.getIntegerAttr(
1876 typeConverter->convertType(op.getType()),
1877 mlir::cast<cir::IntAttr>(op.getValue()).getValue());
1878 }
else if (mlir::isa<cir::FPTypeInterface>(op.getType())) {
1879 attr = rewriter.getFloatAttr(
1880 typeConverter->convertType(op.getType()),
1881 mlir::cast<cir::FPAttr>(op.getValue()).getValue());
1882 }
else if (mlir::isa<cir::PointerType>(op.getType())) {
1884 if (mlir::isa<cir::ConstPtrAttr>(op.getValue())) {
1885 if (mlir::cast<cir::ConstPtrAttr>(op.getValue()).isNullValue()) {
1886 rewriter.replaceOpWithNewOp<mlir::LLVM::ZeroOp>(
1887 op, typeConverter->convertType(op.getType()));
1888 return mlir::success();
1892 if (
auto gv = mlir::dyn_cast<cir::GlobalViewAttr>(op.getValue())) {
1895 rewriter.replaceOp(op, newOp);
1896 return mlir::success();
1898 attr = op.getValue();
1899 }
else if (
const auto arrTy = mlir::dyn_cast<cir::ArrayType>(op.getType())) {
1900 const auto constArr = mlir::dyn_cast<cir::ConstArrayAttr>(op.getValue());
1901 if (!constArr && !isa<cir::ZeroAttr, cir::UndefAttr>(op.getValue()))
1902 return op.emitError() <<
"array does not have a constant initializer";
1904 std::optional<mlir::Attribute> denseAttr;
1907 op, constArr, rewriter, getTypeConverter(), lowerMod);
1908 rewriter.replaceOp(op, newOp);
1909 return mlir::success();
1910 }
else if (constArr &&
1912 attr = denseAttr.value();
1915 op, op.getValue(), rewriter, typeConverter, lowerMod);
1916 rewriter.replaceOp(op, initVal);
1917 return mlir::success();
1919 }
else if (
const auto recordAttr =
1920 mlir::dyn_cast<cir::ConstRecordAttr>(op.getValue())) {
1923 rewriter.replaceOp(op, initVal);
1924 return mlir::success();
1925 }
else if (
const auto vecTy = mlir::dyn_cast<cir::VectorType>(op.getType())) {
1927 getTypeConverter(), lowerMod));
1928 return mlir::success();
1929 }
else if (
auto recTy = mlir::dyn_cast<cir::RecordType>(op.getType())) {
1930 if (mlir::isa<cir::ZeroAttr, cir::UndefAttr>(attr)) {
1931 mlir::Value initVal =
1933 rewriter.replaceOp(op, initVal);
1934 return mlir::success();
1936 return op.emitError() <<
"unsupported lowering for record constant type "
1938 }
else if (
auto complexTy = mlir::dyn_cast<cir::ComplexType>(op.getType())) {
1939 mlir::Type complexElemTy = complexTy.getElementType();
1940 mlir::Type complexElemLLVMTy = typeConverter->convertType(complexElemTy);
1942 if (
auto zeroInitAttr = mlir::dyn_cast<cir::ZeroAttr>(op.getValue())) {
1943 mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(complexElemLLVMTy);
1944 mlir::ArrayAttr array = rewriter.getArrayAttr({zeroAttr, zeroAttr});
1945 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
1946 op, getTypeConverter()->convertType(op.getType()), array);
1947 return mlir::success();
1950 auto complexAttr = mlir::cast<cir::ConstComplexAttr>(op.getValue());
1952 mlir::Attribute components[2];
1953 if (mlir::isa<cir::IntType>(complexElemTy)) {
1954 components[0] = rewriter.getIntegerAttr(
1956 mlir::cast<cir::IntAttr>(complexAttr.getReal()).getValue());
1957 components[1] = rewriter.getIntegerAttr(
1959 mlir::cast<cir::IntAttr>(complexAttr.getImag()).getValue());
1961 components[0] = rewriter.getFloatAttr(
1963 mlir::cast<cir::FPAttr>(complexAttr.getReal()).getValue());
1964 components[1] = rewriter.getFloatAttr(
1966 mlir::cast<cir::FPAttr>(complexAttr.getImag()).getValue());
1969 attr = rewriter.getArrayAttr(components);
1971 return op.emitError() <<
"unsupported constant type " << op.getType();
1974 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
1975 op, getTypeConverter()->convertType(op.getType()),
attr);
1977 return mlir::success();
1981 mlir::DataLayout layout(op.getParentOfType<mlir::ModuleOp>());
1983 if (isa<cir::VoidType>(type))
1984 type = cir::IntType::get(type.getContext(), 8,
false);
1985 return llvm::divideCeil(layout.getTypeSizeInBits(type), 8);
1988mlir::LogicalResult CIRToLLVMPrefetchOpLowering::matchAndRewrite(
1989 cir::PrefetchOp op, OpAdaptor adaptor,
1990 mlir::ConversionPatternRewriter &rewriter)
const {
1991 rewriter.replaceOpWithNewOp<mlir::LLVM::Prefetch>(
1992 op, adaptor.getAddr(), adaptor.getIsWrite(), adaptor.getLocality(),
1994 return mlir::success();
1997mlir::LogicalResult CIRToLLVMPtrDiffOpLowering::matchAndRewrite(
1998 cir::PtrDiffOp op, OpAdaptor adaptor,
1999 mlir::ConversionPatternRewriter &rewriter)
const {
2000 auto dstTy = mlir::cast<cir::IntType>(op.getType());
2001 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
2003 auto lhs = mlir::LLVM::PtrToIntOp::create(rewriter, op.getLoc(), llvmDstTy,
2005 auto rhs = mlir::LLVM::PtrToIntOp::create(rewriter, op.getLoc(), llvmDstTy,
2009 mlir::LLVM::SubOp::create(rewriter, op.getLoc(), llvmDstTy, lhs, rhs);
2011 cir::PointerType ptrTy = op.getLhs().getType();
2013 uint64_t typeSize =
getTypeSize(ptrTy.getPointee(), *op);
2016 mlir::Value resultVal = diff.getResult();
2017 if (typeSize != 1) {
2018 auto typeSizeVal = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
2019 llvmDstTy, typeSize);
2021 if (dstTy.isUnsigned()) {
2023 mlir::LLVM::UDivOp::create(rewriter, op.getLoc(), diff, typeSizeVal);
2024 uDiv.setIsExact(
true);
2025 resultVal = uDiv.getResult();
2028 mlir::LLVM::SDivOp::create(rewriter, op.getLoc(), diff, typeSizeVal);
2029 sDiv.setIsExact(
true);
2030 resultVal = sDiv.getResult();
2033 rewriter.replaceOp(op, resultVal);
2034 return mlir::success();
2037mlir::LogicalResult CIRToLLVMExpectOpLowering::matchAndRewrite(
2038 cir::ExpectOp op, OpAdaptor adaptor,
2039 mlir::ConversionPatternRewriter &rewriter)
const {
2043 std::optional<llvm::APFloat> prob = op.getProb();
2045 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpectWithProbabilityOp>(
2046 op, adaptor.getVal(), adaptor.getExpected(), prob.value());
2048 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpectOp>(op, adaptor.getVal(),
2049 adaptor.getExpected());
2050 return mlir::success();
2053mlir::LogicalResult CIRToLLVMFAbsOpLowering::matchAndRewrite(
2054 cir::FAbsOp op, OpAdaptor adaptor,
2055 mlir::ConversionPatternRewriter &rewriter)
const {
2056 mlir::Type resTy = typeConverter->convertType(op.getType());
2057 rewriter.replaceOpWithNewOp<mlir::LLVM::FAbsOp>(op, resTy,
2058 adaptor.getOperands()[0]);
2059 return mlir::success();
2066void CIRToLLVMFuncOpLowering::lowerFuncAttributes(
2067 cir::FuncOp func,
bool filterArgAndResAttrs,
2068 SmallVectorImpl<mlir::NamedAttribute> &result)
const {
2070 for (mlir::NamedAttribute attr : func->getAttrs()) {
2072 if (
attr.getName() == mlir::SymbolTable::getSymbolAttrName() ||
2073 attr.getName() == func.getFunctionTypeAttrName() ||
2075 attr.getName() == func.getGlobalVisibilityAttrName() ||
2076 attr.getName() == func.getDsoLocalAttrName() ||
2077 attr.getName() == func.getInlineKindAttrName() ||
2078 attr.getName() == func.getSideEffectAttrName() ||
2079 attr.getName() == CIRDialect::getNoReturnAttrName() ||
2080 (filterArgAndResAttrs &&
2081 (
attr.getName() == func.getArgAttrsAttrName() ||
2082 attr.getName() == func.getResAttrsAttrName())))
2086 result.push_back(attr);
2090mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewriteAlias(
2091 cir::FuncOp op, llvm::StringRef aliasee, mlir::Type ty, OpAdaptor adaptor,
2092 mlir::ConversionPatternRewriter &rewriter)
const {
2093 SmallVector<mlir::NamedAttribute, 4> attributes;
2094 lowerFuncAttributes(op,
false, attributes);
2096 mlir::Location loc = op.getLoc();
2097 auto aliasOp = rewriter.replaceOpWithNewOp<mlir::LLVM::AliasOp>(
2098 op, ty,
convertLinkage(op.getLinkage()), op.getName(), op.getDsoLocal(),
2102 mlir::OpBuilder builder(op.getContext());
2103 mlir::Block *block = builder.createBlock(&aliasOp.getInitializerRegion());
2104 builder.setInsertionPointToStart(block);
2107 mlir::Type ptrTy = mlir::LLVM::LLVMPointerType::get(ty.getContext());
2108 auto addrOp = mlir::LLVM::AddressOfOp::create(builder, loc, ptrTy, aliasee);
2109 mlir::LLVM::ReturnOp::create(builder, loc, addrOp);
2111 return mlir::success();
2114mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewrite(
2115 cir::FuncOp op, OpAdaptor adaptor,
2116 mlir::ConversionPatternRewriter &rewriter)
const {
2118 cir::FuncType fnType = op.getFunctionType();
2119 bool isDsoLocal = op.getDsoLocal();
2120 mlir::TypeConverter::SignatureConversion signatureConversion(
2121 fnType.getNumInputs());
2123 for (
const auto &argType : llvm::enumerate(fnType.getInputs())) {
2124 mlir::Type convertedType = typeConverter->convertType(argType.value());
2126 return mlir::failure();
2127 signatureConversion.addInputs(argType.index(), convertedType);
2130 mlir::Type resultType =
2131 getTypeConverter()->convertType(fnType.getReturnType());
2134 mlir::Type llvmFnTy = mlir::LLVM::LLVMFunctionType::get(
2135 resultType ? resultType : mlir::LLVM::LLVMVoidType::get(getContext()),
2136 signatureConversion.getConvertedTypes(),
2140 if (std::optional<llvm::StringRef> aliasee = op.getAliasee())
2141 return matchAndRewriteAlias(op, *aliasee, llvmFnTy, adaptor, rewriter);
2145 mlir::Location loc = op.getLoc();
2146 if (mlir::FusedLoc fusedLoc = mlir::dyn_cast<mlir::FusedLoc>(loc))
2147 loc = fusedLoc.getLocations()[0];
2148 assert((mlir::isa<mlir::FileLineColLoc>(loc) ||
2149 mlir::isa<mlir::UnknownLoc>(loc)) &&
2150 "expected single location or unknown location here");
2154 mlir::LLVM::CConv cconv = mlir::LLVM::CConv::C;
2155 SmallVector<mlir::NamedAttribute, 4> attributes;
2156 lowerFuncAttributes(op,
false, attributes);
2158 mlir::LLVM::LLVMFuncOp fn = mlir::LLVM::LLVMFuncOp::create(
2159 rewriter, loc, op.getName(), llvmFnTy, linkage, isDsoLocal, cconv,
2160 mlir::SymbolRefAttr(), attributes);
2164 if (std::optional<cir::SideEffect> sideEffectKind = op.getSideEffect()) {
2165 switch (*sideEffectKind) {
2166 case cir::SideEffect::All:
2168 case cir::SideEffect::Pure:
2169 fn.setMemoryEffectsAttr(mlir::LLVM::MemoryEffectsAttr::get(
2171 mlir::LLVM::ModRefInfo::Ref,
2172 mlir::LLVM::ModRefInfo::Ref,
2173 mlir::LLVM::ModRefInfo::Ref,
2174 mlir::LLVM::ModRefInfo::Ref,
2175 mlir::LLVM::ModRefInfo::Ref,
2176 mlir::LLVM::ModRefInfo::Ref));
2177 fn.setNoUnwind(
true);
2178 fn.setWillReturn(
true);
2180 case cir::SideEffect::Const:
2181 fn.setMemoryEffectsAttr(mlir::LLVM::MemoryEffectsAttr::get(
2183 mlir::LLVM::ModRefInfo::NoModRef,
2184 mlir::LLVM::ModRefInfo::NoModRef,
2185 mlir::LLVM::ModRefInfo::NoModRef,
2186 mlir::LLVM::ModRefInfo::NoModRef,
2187 mlir::LLVM::ModRefInfo::NoModRef,
2188 mlir::LLVM::ModRefInfo::NoModRef));
2189 fn.setNoUnwind(
true);
2190 fn.setWillReturn(
true);
2195 if (op->hasAttr(CIRDialect::getNoReturnAttrName()))
2196 fn.setNoreturn(
true);
2198 if (std::optional<cir::InlineKind> inlineKind = op.getInlineKind()) {
2199 fn.setNoInline(*inlineKind == cir::InlineKind::NoInline);
2200 fn.setInlineHint(*inlineKind == cir::InlineKind::InlineHint);
2201 fn.setAlwaysInline(*inlineKind == cir::InlineKind::AlwaysInline);
2204 if (std::optional<llvm::StringRef> personality = op.getPersonality())
2205 fn.setPersonality(*personality);
2210 rewriter.inlineRegionBefore(op.getBody(), fn.getBody(), fn.end());
2211 if (failed(rewriter.convertRegionTypes(&fn.getBody(), *typeConverter,
2212 &signatureConversion)))
2213 return mlir::failure();
2215 rewriter.eraseOp(op);
2217 return mlir::LogicalResult::success();
2220mlir::LogicalResult CIRToLLVMGetGlobalOpLowering::matchAndRewrite(
2221 cir::GetGlobalOp op, OpAdaptor adaptor,
2222 mlir::ConversionPatternRewriter &rewriter)
const {
2225 if (op->getUses().empty()) {
2226 rewriter.eraseOp(op);
2227 return mlir::success();
2230 mlir::Type
type = getTypeConverter()->convertType(op.getType());
2231 mlir::Operation *newop = mlir::LLVM::AddressOfOp::create(
2232 rewriter, op.getLoc(), type, op.getName());
2236 newop = mlir::LLVM::ThreadlocalAddressOp::create(rewriter, op.getLoc(),
2237 type, newop->getResult(0));
2240 rewriter.replaceOp(op, newop);
2241 return mlir::success();
2246void CIRToLLVMGlobalOpLowering::setupRegionInitializedLLVMGlobalOp(
2247 cir::GlobalOp op, mlir::ConversionPatternRewriter &rewriter)
const {
2248 const mlir::Type llvmType =
2255 const bool isConst = op.getConstant();
2257 const unsigned addrSpace = 0;
2258 const bool isDsoLocal = op.getDsoLocal();
2259 const bool isThreadLocal = (
bool)op.getTlsModelAttr();
2260 const uint64_t alignment = op.getAlignment().value_or(0);
2261 const mlir::LLVM::Linkage linkage =
convertLinkage(op.getLinkage());
2262 const StringRef symbol = op.getSymName();
2263 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
2265 SmallVector<mlir::NamedAttribute> attributes;
2266 mlir::LLVM::GlobalOp newGlobalOp =
2267 rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
2268 op, llvmType, isConst, linkage, symbol,
nullptr, alignment, addrSpace,
2269 isDsoLocal, isThreadLocal, comdatAttr, attributes);
2270 newGlobalOp.getRegion().emplaceBlock();
2271 rewriter.setInsertionPointToEnd(newGlobalOp.getInitializerBlock());
2275CIRToLLVMGlobalOpLowering::matchAndRewriteRegionInitializedGlobal(
2276 cir::GlobalOp op, mlir::Attribute init,
2277 mlir::ConversionPatternRewriter &rewriter)
const {
2280 (isa<cir::ConstArrayAttr, cir::ConstRecordAttr, cir::ConstVectorAttr,
2281 cir::ConstPtrAttr, cir::ConstComplexAttr, cir::GlobalViewAttr,
2282 cir::TypeInfoAttr, cir::UndefAttr, cir::VTableAttr, cir::ZeroAttr>(
2288 const mlir::Location loc = op.getLoc();
2289 setupRegionInitializedLLVMGlobalOp(op, rewriter);
2290 CIRAttrToValue valueConverter(op, rewriter, typeConverter, lowerMod);
2291 mlir::Value value = valueConverter.visit(init);
2292 mlir::LLVM::ReturnOp::create(rewriter, loc, value);
2293 return mlir::success();
2296mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite(
2297 cir::GlobalOp op, OpAdaptor adaptor,
2298 mlir::ConversionPatternRewriter &rewriter)
const {
2301 if (!op.getCtorRegion().empty() || !op.getDtorRegion().empty())
2302 return op.emitError() <<
"GlobalOp ctor and dtor regions should be removed "
2303 "in LoweringPrepare";
2305 std::optional<mlir::Attribute> init = op.getInitialValue();
2308 const mlir::Type cirSymType = op.getSymType();
2311 const mlir::Type llvmType =
2315 const bool isConst = op.getConstant();
2317 const unsigned addrSpace = 0;
2318 const bool isDsoLocal = op.getDsoLocal();
2319 const bool isThreadLocal = (
bool)op.getTlsModelAttr();
2320 const uint64_t alignment = op.getAlignment().value_or(0);
2321 const mlir::LLVM::Linkage linkage =
convertLinkage(op.getLinkage());
2322 const StringRef symbol = op.getSymName();
2323 SmallVector<mlir::NamedAttribute> attributes;
2325 if (init.has_value()) {
2326 if (mlir::isa<cir::FPAttr, cir::IntAttr, cir::BoolAttr>(init.value())) {
2328 init = initRewriter.visit(init.value());
2333 if (!init.value()) {
2334 op.emitError() <<
"unsupported initializer '" << init.value() <<
"'";
2335 return mlir::failure();
2337 }
else if (mlir::isa<cir::ConstArrayAttr, cir::ConstVectorAttr,
2338 cir::ConstRecordAttr, cir::ConstPtrAttr,
2339 cir::ConstComplexAttr, cir::GlobalViewAttr,
2340 cir::TypeInfoAttr, cir::UndefAttr, cir::VTableAttr,
2341 cir::ZeroAttr>(init.value())) {
2345 return matchAndRewriteRegionInitializedGlobal(op, init.value(), rewriter);
2349 op.emitError() <<
"unsupported initializer '" << init.value() <<
"'";
2350 return mlir::failure();
2354 mlir::LLVM::Visibility visibility =
2356 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
2357 auto newOp = rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
2358 op, llvmType, isConst, linkage, symbol, init.value_or(mlir::Attribute()),
2359 alignment, addrSpace, isDsoLocal, isThreadLocal, comdatAttr, attributes);
2360 newOp.setVisibility_(visibility);
2362 return mlir::success();
2366CIRToLLVMGlobalOpLowering::getComdatAttr(cir::GlobalOp &op,
2367 mlir::OpBuilder &builder)
const {
2368 if (!op.getComdat())
2369 return mlir::SymbolRefAttr{};
2371 mlir::ModuleOp module = op->getParentOfType<mlir::ModuleOp>();
2372 mlir::OpBuilder::InsertionGuard guard(builder);
2373 StringRef comdatName(
"__llvm_comdat_globals");
2375 builder.setInsertionPointToStart(module.getBody());
2377 mlir::LLVM::ComdatOp::create(builder, module.getLoc(), comdatName);
2380 if (
auto comdatSelector = comdatOp.lookupSymbol<mlir::LLVM::ComdatSelectorOp>(
2382 return mlir::SymbolRefAttr::get(
2383 builder.getContext(), comdatName,
2384 mlir::FlatSymbolRefAttr::get(comdatSelector.getSymNameAttr()));
2387 builder.setInsertionPointToStart(&comdatOp.getBody().back());
2388 auto selectorOp = mlir::LLVM::ComdatSelectorOp::create(
2389 builder, comdatOp.getLoc(), op.getSymName(),
2390 mlir::LLVM::comdat::Comdat::Any);
2391 return mlir::SymbolRefAttr::get(
2392 builder.getContext(), comdatName,
2393 mlir::FlatSymbolRefAttr::get(selectorOp.getSymNameAttr()));
2396mlir::LogicalResult CIRToLLVMSwitchFlatOpLowering::matchAndRewrite(
2397 cir::SwitchFlatOp op, OpAdaptor adaptor,
2398 mlir::ConversionPatternRewriter &rewriter)
const {
2400 llvm::SmallVector<mlir::APInt, 8> caseValues;
2401 for (mlir::Attribute val : op.getCaseValues()) {
2402 auto intAttr = cast<cir::IntAttr>(val);
2403 caseValues.push_back(intAttr.getValue());
2406 llvm::SmallVector<mlir::Block *, 8> caseDestinations;
2407 llvm::SmallVector<mlir::ValueRange, 8> caseOperands;
2409 for (mlir::Block *x : op.getCaseDestinations())
2410 caseDestinations.push_back(x);
2412 for (mlir::OperandRange x : op.getCaseOperands())
2413 caseOperands.push_back(x);
2416 rewriter.setInsertionPoint(op);
2417 rewriter.replaceOpWithNewOp<mlir::LLVM::SwitchOp>(
2418 op, adaptor.getCondition(), op.getDefaultDestination(),
2419 op.getDefaultOperands(), caseValues, caseDestinations, caseOperands);
2420 return mlir::success();
2423mlir::LogicalResult CIRToLLVMUnaryOpLowering::matchAndRewrite(
2424 cir::UnaryOp op, OpAdaptor adaptor,
2425 mlir::ConversionPatternRewriter &rewriter)
const {
2426 assert(op.getType() == op.getInput().getType() &&
2427 "Unary operation's operand type and result type are different");
2428 mlir::Type
type = op.getType();
2429 mlir::Type elementType = elementTypeIfVector(type);
2430 bool isVector = mlir::isa<cir::VectorType>(type);
2431 mlir::Type llvmType = getTypeConverter()->convertType(type);
2432 mlir::Location loc = op.getLoc();
2435 if (mlir::isa<cir::IntType>(elementType)) {
2436 mlir::LLVM::IntegerOverflowFlags maybeNSW =
2437 op.getNoSignedWrap() ? mlir::LLVM::IntegerOverflowFlags::nsw
2438 : mlir::LLVM::IntegerOverflowFlags::none;
2439 switch (op.getKind()) {
2440 case cir::UnaryOpKind::Inc: {
2441 assert(!
isVector &&
"++ not allowed on vector types");
2442 auto one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
2443 rewriter.replaceOpWithNewOp<mlir::LLVM::AddOp>(
2444 op, llvmType, adaptor.getInput(), one, maybeNSW);
2445 return mlir::success();
2447 case cir::UnaryOpKind::Dec: {
2448 assert(!
isVector &&
"-- not allowed on vector types");
2449 auto one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
2450 rewriter.replaceOpWithNewOp<mlir::LLVM::SubOp>(op, adaptor.getInput(),
2452 return mlir::success();
2454 case cir::UnaryOpKind::Plus:
2455 rewriter.replaceOp(op, adaptor.getInput());
2456 return mlir::success();
2457 case cir::UnaryOpKind::Minus: {
2460 zero = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmType);
2462 zero = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 0);
2463 rewriter.replaceOpWithNewOp<mlir::LLVM::SubOp>(
2464 op, zero, adaptor.getInput(), maybeNSW);
2465 return mlir::success();
2467 case cir::UnaryOpKind::Not: {
2469 mlir::Value minusOne;
2472 mlir::dyn_cast<cir::VectorType>(type).getSize();
2473 std::vector<int32_t> values(numElements, -1);
2474 mlir::DenseIntElementsAttr denseVec = rewriter.getI32VectorAttr(values);
2476 mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, denseVec);
2478 minusOne = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, -1);
2480 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getInput(),
2482 return mlir::success();
2485 llvm_unreachable(
"Unexpected unary op for int");
2489 if (mlir::isa<cir::FPTypeInterface>(elementType)) {
2490 switch (op.getKind()) {
2491 case cir::UnaryOpKind::Inc: {
2492 assert(!
isVector &&
"++ not allowed on vector types");
2493 mlir::LLVM::ConstantOp one = mlir::LLVM::ConstantOp::create(
2494 rewriter, loc, llvmType, rewriter.getFloatAttr(llvmType, 1.0));
2495 rewriter.replaceOpWithNewOp<mlir::LLVM::FAddOp>(op, llvmType, one,
2496 adaptor.getInput());
2497 return mlir::success();
2499 case cir::UnaryOpKind::Dec: {
2500 assert(!
isVector &&
"-- not allowed on vector types");
2501 mlir::LLVM::ConstantOp minusOne = mlir::LLVM::ConstantOp::create(
2502 rewriter, loc, llvmType, rewriter.getFloatAttr(llvmType, -1.0));
2503 rewriter.replaceOpWithNewOp<mlir::LLVM::FAddOp>(op, llvmType, minusOne,
2504 adaptor.getInput());
2505 return mlir::success();
2507 case cir::UnaryOpKind::Plus:
2508 rewriter.replaceOp(op, adaptor.getInput());
2509 return mlir::success();
2510 case cir::UnaryOpKind::Minus:
2511 rewriter.replaceOpWithNewOp<mlir::LLVM::FNegOp>(op, llvmType,
2512 adaptor.getInput());
2513 return mlir::success();
2514 case cir::UnaryOpKind::Not:
2515 return op.emitError() <<
"Unary not is invalid for floating-point types";
2517 llvm_unreachable(
"Unexpected unary op for float");
2522 if (mlir::isa<cir::BoolType>(elementType)) {
2523 switch (op.getKind()) {
2524 case cir::UnaryOpKind::Inc:
2525 case cir::UnaryOpKind::Dec:
2526 case cir::UnaryOpKind::Plus:
2527 case cir::UnaryOpKind::Minus:
2530 return op.emitError() <<
"Unsupported unary operation on boolean type";
2531 case cir::UnaryOpKind::Not: {
2532 assert(!
isVector &&
"NYI: op! on vector mask");
2533 auto one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
2534 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getInput(),
2536 return mlir::success();
2539 llvm_unreachable(
"Unexpected unary op for bool");
2544 if (mlir::isa<cir::PointerType>(elementType)) {
2545 switch (op.getKind()) {
2546 case cir::UnaryOpKind::Plus:
2547 rewriter.replaceOp(op, adaptor.getInput());
2548 return mlir::success();
2550 op.emitError() <<
"Unknown pointer unary operation during CIR lowering";
2551 return mlir::failure();
2555 return op.emitError() <<
"Unary operation has unsupported type: "
2559mlir::LLVM::IntegerOverflowFlags
2560CIRToLLVMBinOpLowering::getIntOverflowFlag(cir::BinOp op)
const {
2561 if (op.getNoUnsignedWrap())
2562 return mlir::LLVM::IntegerOverflowFlags::nuw;
2564 if (op.getNoSignedWrap())
2565 return mlir::LLVM::IntegerOverflowFlags::nsw;
2567 return mlir::LLVM::IntegerOverflowFlags::none;
2572 return mlir::isa<cir::IntType>(type)
2573 ? mlir::cast<cir::IntType>(type).isUnsigned()
2574 : mlir::cast<mlir::IntegerType>(type).isUnsigned();
2577mlir::LogicalResult CIRToLLVMBinOpLowering::matchAndRewrite(
2578 cir::BinOp op, OpAdaptor adaptor,
2579 mlir::ConversionPatternRewriter &rewriter)
const {
2580 if (adaptor.getLhs().getType() != adaptor.getRhs().getType())
2581 return op.emitError() <<
"inconsistent operands' types not supported yet";
2583 mlir::Type type = op.getRhs().getType();
2584 if (!mlir::isa<cir::IntType, cir::BoolType, cir::FPTypeInterface,
2585 mlir::IntegerType, cir::VectorType>(type))
2586 return op.emitError() <<
"operand type not supported yet";
2588 const mlir::Type llvmTy = getTypeConverter()->convertType(op.getType());
2589 const mlir::Type llvmEltTy = elementTypeIfVector(llvmTy);
2591 const mlir::Value rhs = adaptor.getRhs();
2592 const mlir::Value lhs = adaptor.getLhs();
2593 type = elementTypeIfVector(type);
2595 switch (op.getKind()) {
2596 case cir::BinOpKind::Add:
2597 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
2598 if (op.getSaturated()) {
2600 rewriter.replaceOpWithNewOp<mlir::LLVM::UAddSat>(op, lhs, rhs);
2603 rewriter.replaceOpWithNewOp<mlir::LLVM::SAddSat>(op, lhs, rhs);
2606 rewriter.replaceOpWithNewOp<mlir::LLVM::AddOp>(op, llvmTy, lhs, rhs,
2607 getIntOverflowFlag(op));
2609 rewriter.replaceOpWithNewOp<mlir::LLVM::FAddOp>(op, lhs, rhs);
2612 case cir::BinOpKind::Sub:
2613 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
2614 if (op.getSaturated()) {
2616 rewriter.replaceOpWithNewOp<mlir::LLVM::USubSat>(op, lhs, rhs);
2619 rewriter.replaceOpWithNewOp<mlir::LLVM::SSubSat>(op, lhs, rhs);
2622 rewriter.replaceOpWithNewOp<mlir::LLVM::SubOp>(op, llvmTy, lhs, rhs,
2623 getIntOverflowFlag(op));
2625 rewriter.replaceOpWithNewOp<mlir::LLVM::FSubOp>(op, lhs, rhs);
2628 case cir::BinOpKind::Mul:
2629 if (mlir::isa<mlir::IntegerType>(llvmEltTy))
2630 rewriter.replaceOpWithNewOp<mlir::LLVM::MulOp>(op, llvmTy, lhs, rhs,
2631 getIntOverflowFlag(op));
2633 rewriter.replaceOpWithNewOp<mlir::LLVM::FMulOp>(op, lhs, rhs);
2635 case cir::BinOpKind::Div:
2636 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
2639 rewriter.replaceOpWithNewOp<mlir::LLVM::UDivOp>(op, lhs, rhs);
2641 rewriter.replaceOpWithNewOp<mlir::LLVM::SDivOp>(op, lhs, rhs);
2643 rewriter.replaceOpWithNewOp<mlir::LLVM::FDivOp>(op, lhs, rhs);
2646 case cir::BinOpKind::Rem:
2647 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
2650 rewriter.replaceOpWithNewOp<mlir::LLVM::URemOp>(op, lhs, rhs);
2652 rewriter.replaceOpWithNewOp<mlir::LLVM::SRemOp>(op, lhs, rhs);
2654 rewriter.replaceOpWithNewOp<mlir::LLVM::FRemOp>(op, lhs, rhs);
2657 case cir::BinOpKind::And:
2658 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(op, lhs, rhs);
2660 case cir::BinOpKind::Or:
2661 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(op, lhs, rhs);
2663 case cir::BinOpKind::Xor:
2664 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, lhs, rhs);
2666 case cir::BinOpKind::Max:
2667 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
2670 rewriter.replaceOpWithNewOp<mlir::LLVM::UMaxOp>(op, llvmTy, lhs, rhs);
2672 rewriter.replaceOpWithNewOp<mlir::LLVM::SMaxOp>(op, llvmTy, lhs, rhs);
2676 return mlir::LogicalResult::success();
2680static mlir::LLVM::ICmpPredicate
2682 using CIR = cir::CmpOpKind;
2683 using LLVMICmp = mlir::LLVM::ICmpPredicate;
2686 return LLVMICmp::eq;
2688 return LLVMICmp::ne;
2690 return (isSigned ? LLVMICmp::slt : LLVMICmp::ult);
2692 return (isSigned ? LLVMICmp::sle : LLVMICmp::ule);
2694 return (isSigned ? LLVMICmp::sgt : LLVMICmp::ugt);
2696 return (isSigned ? LLVMICmp::sge : LLVMICmp::uge);
2698 llvm_unreachable(
"Unknown CmpOpKind");
2703static mlir::LLVM::FCmpPredicate
2705 using CIR = cir::CmpOpKind;
2706 using LLVMFCmp = mlir::LLVM::FCmpPredicate;
2709 return LLVMFCmp::oeq;
2711 return LLVMFCmp::une;
2713 return LLVMFCmp::olt;
2715 return LLVMFCmp::ole;
2717 return LLVMFCmp::ogt;
2719 return LLVMFCmp::oge;
2721 llvm_unreachable(
"Unknown CmpOpKind");
2724mlir::LogicalResult CIRToLLVMCmpOpLowering::matchAndRewrite(
2725 cir::CmpOp cmpOp, OpAdaptor adaptor,
2726 mlir::ConversionPatternRewriter &rewriter)
const {
2727 mlir::Type type = cmpOp.getLhs().getType();
2729 if (mlir::isa<cir::IntType, mlir::IntegerType>(type)) {
2730 bool isSigned = mlir::isa<cir::IntType>(type)
2731 ? mlir::cast<cir::IntType>(type).isSigned()
2732 : mlir::cast<mlir::IntegerType>(type).isSigned();
2733 mlir::LLVM::ICmpPredicate
kind =
2735 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
2736 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
2737 return mlir::success();
2740 if (
auto ptrTy = mlir::dyn_cast<cir::PointerType>(type)) {
2741 mlir::LLVM::ICmpPredicate
kind =
2744 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
2745 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
2746 return mlir::success();
2749 if (
auto vptrTy = mlir::dyn_cast<cir::VPtrType>(type)) {
2753 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
2754 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
2755 return mlir::success();
2758 if (mlir::isa<cir::FPTypeInterface>(type)) {
2759 mlir::LLVM::FCmpPredicate
kind =
2761 rewriter.replaceOpWithNewOp<mlir::LLVM::FCmpOp>(
2762 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
2763 return mlir::success();
2766 if (mlir::isa<cir::ComplexType>(type)) {
2767 mlir::Value lhs = adaptor.getLhs();
2768 mlir::Value rhs = adaptor.getRhs();
2769 mlir::Location loc = cmpOp.getLoc();
2771 auto complexType = mlir::cast<cir::ComplexType>(cmpOp.getLhs().getType());
2772 mlir::Type complexElemTy =
2773 getTypeConverter()->convertType(
complexType.getElementType());
2775 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
2776 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{0}));
2777 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
2778 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{1}));
2779 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
2780 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{0}));
2781 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
2782 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{1}));
2784 if (cmpOp.getKind() == cir::CmpOpKind::eq) {
2785 if (complexElemTy.isInteger()) {
2786 auto realCmp = mlir::LLVM::ICmpOp::create(
2787 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, lhsReal, rhsReal);
2788 auto imagCmp = mlir::LLVM::ICmpOp::create(
2789 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, lhsImag, rhsImag);
2790 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, imagCmp);
2791 return mlir::success();
2794 auto realCmp = mlir::LLVM::FCmpOp::create(
2795 rewriter, loc, mlir::LLVM::FCmpPredicate::oeq, lhsReal, rhsReal);
2796 auto imagCmp = mlir::LLVM::FCmpOp::create(
2797 rewriter, loc, mlir::LLVM::FCmpPredicate::oeq, lhsImag, rhsImag);
2798 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, imagCmp);
2799 return mlir::success();
2802 if (cmpOp.getKind() == cir::CmpOpKind::ne) {
2803 if (complexElemTy.isInteger()) {
2804 auto realCmp = mlir::LLVM::ICmpOp::create(
2805 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, lhsReal, rhsReal);
2806 auto imagCmp = mlir::LLVM::ICmpOp::create(
2807 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, lhsImag, rhsImag);
2808 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp);
2809 return mlir::success();
2812 auto realCmp = mlir::LLVM::FCmpOp::create(
2813 rewriter, loc, mlir::LLVM::FCmpPredicate::une, lhsReal, rhsReal);
2814 auto imagCmp = mlir::LLVM::FCmpOp::create(
2815 rewriter, loc, mlir::LLVM::FCmpPredicate::une, lhsImag, rhsImag);
2816 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp);
2817 return mlir::success();
2821 return cmpOp.emitError() <<
"unsupported type for CmpOp: " <<
type;
2824mlir::LogicalResult CIRToLLVMBinOpOverflowOpLowering::matchAndRewrite(
2825 cir::BinOpOverflowOp op, OpAdaptor adaptor,
2826 mlir::ConversionPatternRewriter &rewriter)
const {
2827 mlir::Location loc = op.getLoc();
2828 cir::BinOpOverflowKind arithKind = op.getKind();
2829 cir::IntType operandTy = op.getLhs().getType();
2830 cir::IntType resultTy = op.getResult().getType();
2832 EncompassedTypeInfo encompassedTyInfo =
2833 computeEncompassedTypeWidth(operandTy, resultTy);
2834 mlir::IntegerType encompassedLLVMTy =
2835 rewriter.getIntegerType(encompassedTyInfo.width);
2837 mlir::Value lhs = adaptor.getLhs();
2838 mlir::Value rhs = adaptor.getRhs();
2839 if (operandTy.getWidth() < encompassedTyInfo.width) {
2840 if (operandTy.isSigned()) {
2841 lhs = mlir::LLVM::SExtOp::create(rewriter, loc, encompassedLLVMTy, lhs);
2842 rhs = mlir::LLVM::SExtOp::create(rewriter, loc, encompassedLLVMTy, rhs);
2844 lhs = mlir::LLVM::ZExtOp::create(rewriter, loc, encompassedLLVMTy, lhs);
2845 rhs = mlir::LLVM::ZExtOp::create(rewriter, loc, encompassedLLVMTy, rhs);
2849 std::string intrinName = getLLVMIntrinName(arithKind, encompassedTyInfo.sign,
2850 encompassedTyInfo.width);
2851 auto intrinNameAttr = mlir::StringAttr::get(op.getContext(), intrinName);
2853 mlir::IntegerType overflowLLVMTy = rewriter.getI1Type();
2854 auto intrinRetTy = mlir::LLVM::LLVMStructType::getLiteral(
2855 rewriter.getContext(), {encompassedLLVMTy, overflowLLVMTy});
2857 auto callLLVMIntrinOp = mlir::LLVM::CallIntrinsicOp::create(
2858 rewriter, loc, intrinRetTy, intrinNameAttr, mlir::ValueRange{lhs, rhs});
2859 mlir::Value intrinRet = callLLVMIntrinOp.getResult(0);
2861 mlir::Value result = mlir::LLVM::ExtractValueOp::create(
2862 rewriter, loc, intrinRet, ArrayRef<int64_t>{0})
2864 mlir::Value overflow = mlir::LLVM::ExtractValueOp::create(
2865 rewriter, loc, intrinRet, ArrayRef<int64_t>{1})
2868 if (resultTy.getWidth() < encompassedTyInfo.width) {
2869 mlir::Type resultLLVMTy = getTypeConverter()->convertType(resultTy);
2871 mlir::LLVM::TruncOp::create(rewriter, loc, resultLLVMTy, result);
2875 mlir::Value truncResultExt;
2876 if (resultTy.isSigned())
2877 truncResultExt = mlir::LLVM::SExtOp::create(
2878 rewriter, loc, encompassedLLVMTy, truncResult);
2880 truncResultExt = mlir::LLVM::ZExtOp::create(
2881 rewriter, loc, encompassedLLVMTy, truncResult);
2882 auto truncOverflow = mlir::LLVM::ICmpOp::create(
2883 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, truncResultExt, result);
2885 result = truncResult;
2886 overflow = mlir::LLVM::OrOp::create(rewriter, loc, overflow, truncOverflow);
2889 mlir::Type boolLLVMTy =
2890 getTypeConverter()->convertType(op.getOverflow().getType());
2891 if (boolLLVMTy != rewriter.getI1Type())
2892 overflow = mlir::LLVM::ZExtOp::create(rewriter, loc, boolLLVMTy, overflow);
2894 rewriter.replaceOp(op, mlir::ValueRange{result, overflow});
2896 return mlir::success();
2899std::string CIRToLLVMBinOpOverflowOpLowering::getLLVMIntrinName(
2900 cir::BinOpOverflowKind opKind,
bool isSigned,
unsigned width) {
2903 std::string
name =
"llvm.";
2906 name.push_back(
's');
2908 name.push_back(
'u');
2911 case cir::BinOpOverflowKind::Add:
2912 name.append(
"add.");
2914 case cir::BinOpOverflowKind::Sub:
2915 name.append(
"sub.");
2917 case cir::BinOpOverflowKind::Mul:
2918 name.append(
"mul.");
2922 name.append(
"with.overflow.i");
2923 name.append(std::to_string(width));
2928CIRToLLVMBinOpOverflowOpLowering::EncompassedTypeInfo
2929CIRToLLVMBinOpOverflowOpLowering::computeEncompassedTypeWidth(
2930 cir::IntType operandTy, cir::IntType resultTy) {
2931 bool sign = operandTy.getIsSigned() || resultTy.getIsSigned();
2933 std::max(operandTy.getWidth() + (
sign && operandTy.isUnsigned()),
2934 resultTy.getWidth() + (
sign && resultTy.isUnsigned()));
2935 return {
sign, width};
2938mlir::LogicalResult CIRToLLVMShiftOpLowering::matchAndRewrite(
2939 cir::ShiftOp op, OpAdaptor adaptor,
2940 mlir::ConversionPatternRewriter &rewriter)
const {
2941 assert((op.getValue().getType() == op.getType()) &&
2942 "inconsistent operands' types NYI");
2944 const mlir::Type llvmTy = getTypeConverter()->convertType(op.getType());
2945 mlir::Value amt = adaptor.getAmount();
2946 mlir::Value val = adaptor.getValue();
2948 auto cirAmtTy = mlir::dyn_cast<cir::IntType>(op.getAmount().getType());
2951 auto cirValTy = mlir::cast<cir::IntType>(op.getValue().getType());
2959 amt =
getLLVMIntCast(rewriter, amt, llvmTy,
true, cirAmtTy.getWidth(),
2960 cirValTy.getWidth());
2962 auto cirValVTy = mlir::cast<cir::VectorType>(op.getValue().getType());
2964 mlir::cast<cir::IntType>(cirValVTy.getElementType()).isUnsigned();
2968 if (op.getIsShiftleft()) {
2969 rewriter.replaceOpWithNewOp<mlir::LLVM::ShlOp>(op, llvmTy, val, amt);
2970 return mlir::success();
2974 rewriter.replaceOpWithNewOp<mlir::LLVM::LShrOp>(op, llvmTy, val, amt);
2976 rewriter.replaceOpWithNewOp<mlir::LLVM::AShrOp>(op, llvmTy, val, amt);
2977 return mlir::success();
2980mlir::LogicalResult CIRToLLVMSelectOpLowering::matchAndRewrite(
2981 cir::SelectOp op, OpAdaptor adaptor,
2982 mlir::ConversionPatternRewriter &rewriter)
const {
2983 auto getConstantBool = [](mlir::Value value) -> cir::BoolAttr {
2984 auto definingOp = value.getDefiningOp<cir::ConstantOp>();
2988 auto constValue = definingOp.getValueAttr<cir::BoolAttr>();
2998 if (mlir::isa<cir::BoolType>(op.getTrueValue().getType())) {
2999 cir::BoolAttr trueValue = getConstantBool(op.getTrueValue());
3000 cir::BoolAttr falseValue = getConstantBool(op.getFalseValue());
3001 if (falseValue && !falseValue.getValue()) {
3003 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(op, adaptor.getCondition(),
3004 adaptor.getTrueValue());
3005 return mlir::success();
3007 if (trueValue && trueValue.getValue()) {
3009 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(op, adaptor.getCondition(),
3010 adaptor.getFalseValue());
3011 return mlir::success();
3015 mlir::Value llvmCondition = adaptor.getCondition();
3016 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(
3017 op, llvmCondition, adaptor.getTrueValue(), adaptor.getFalseValue());
3019 return mlir::success();
3023 mlir::PatternRewriter rewriter{
module->getContext()};
3028 if (!module->hasAttr(cir::CIRDialect::getTripleAttrName()))
3034 mlir::DataLayout &dataLayout,
3036 converter.addConversion([&](cir::PointerType type) -> mlir::Type {
3037 unsigned addrSpace =
3038 type.getAddrSpace() ? type.getAddrSpace().getValue().getUInt() : 0;
3039 return mlir::LLVM::LLVMPointerType::get(type.getContext(), addrSpace);
3041 converter.addConversion([&](cir::VPtrType type) -> mlir::Type {
3043 return mlir::LLVM::LLVMPointerType::get(type.getContext());
3045 converter.addConversion([&](cir::ArrayType type) -> mlir::Type {
3048 return mlir::LLVM::LLVMArrayType::get(ty, type.getSize());
3050 converter.addConversion([&](cir::VectorType type) -> mlir::Type {
3051 const mlir::Type ty = converter.convertType(type.getElementType());
3052 return mlir::VectorType::get(type.getSize(), ty, {type.getIsScalable()});
3054 converter.addConversion([&](cir::BoolType type) -> mlir::Type {
3055 return mlir::IntegerType::get(type.getContext(), 1,
3056 mlir::IntegerType::Signless);
3058 converter.addConversion([&](cir::IntType type) -> mlir::Type {
3060 return mlir::IntegerType::get(type.getContext(), type.getWidth());
3062 converter.addConversion([&](cir::SingleType type) -> mlir::Type {
3063 return mlir::Float32Type::get(type.getContext());
3065 converter.addConversion([&](cir::DoubleType type) -> mlir::Type {
3066 return mlir::Float64Type::get(type.getContext());
3068 converter.addConversion([&](cir::FP80Type type) -> mlir::Type {
3069 return mlir::Float80Type::get(type.getContext());
3071 converter.addConversion([&](cir::FP128Type type) -> mlir::Type {
3072 return mlir::Float128Type::get(type.getContext());
3074 converter.addConversion([&](cir::LongDoubleType type) -> mlir::Type {
3075 return converter.convertType(type.getUnderlying());
3077 converter.addConversion([&](cir::FP16Type type) -> mlir::Type {
3078 return mlir::Float16Type::get(type.getContext());
3080 converter.addConversion([&](cir::BF16Type type) -> mlir::Type {
3081 return mlir::BFloat16Type::get(type.getContext());
3083 converter.addConversion([&](cir::ComplexType type) -> mlir::Type {
3086 mlir::Type elementTy = converter.convertType(type.getElementType());
3087 mlir::Type structFields[2] = {elementTy, elementTy};
3088 return mlir::LLVM::LLVMStructType::getLiteral(type.getContext(),
3091 converter.addConversion([&](cir::FuncType type) -> std::optional<mlir::Type> {
3092 auto result = converter.convertType(type.getReturnType());
3094 arguments.reserve(type.getNumInputs());
3095 if (converter.convertTypes(type.getInputs(), arguments).failed())
3096 return std::nullopt;
3097 auto varArg = type.isVarArg();
3098 return mlir::LLVM::LLVMFunctionType::get(result, arguments, varArg);
3100 converter.addConversion([&](cir::RecordType type) -> mlir::Type {
3103 switch (type.getKind()) {
3104 case cir::RecordType::Class:
3105 case cir::RecordType::Struct:
3106 for (mlir::Type ty : type.getMembers())
3110 case cir::RecordType::Union:
3111 if (type.getMembers().empty())
3113 if (
auto largestMember = type.getLargestMember(dataLayout))
3114 llvmMembers.push_back(
3116 if (type.getPadded()) {
3117 auto last = *type.getMembers().rbegin();
3118 llvmMembers.push_back(
3125 mlir::LLVM::LLVMStructType llvmStruct;
3126 if (type.getName()) {
3127 llvmStruct = mlir::LLVM::LLVMStructType::getIdentified(
3128 type.getContext(), type.getPrefixedName());
3129 if (llvmStruct.setBody(llvmMembers, type.getPacked()).failed())
3130 llvm_unreachable(
"Failed to set body of record");
3132 llvmStruct = mlir::LLVM::LLVMStructType::getLiteral(
3133 type.getContext(), llvmMembers, type.getPacked());
3138 converter.addConversion([&](cir::VoidType type) -> mlir::Type {
3139 return mlir::LLVM::LLVMVoidType::get(type.getContext());
3144 mlir::ModuleOp module, StringRef globalXtorName, StringRef llvmXtorName,
3145 llvm::function_ref<std::pair<StringRef, int>(mlir::Attribute)> createXtor) {
3147 for (
const mlir::NamedAttribute namedAttr : module->getAttrs()) {
3148 if (namedAttr.getName() == globalXtorName) {
3149 for (
auto attr : mlir::cast<mlir::ArrayAttr>(namedAttr.getValue()))
3150 globalXtors.emplace_back(createXtor(attr));
3155 if (globalXtors.empty())
3158 mlir::OpBuilder builder(module.getContext());
3159 builder.setInsertionPointToEnd(&module.getBodyRegion().back());
3163 auto ctorPFTy = mlir::LLVM::LLVMPointerType::get(builder.getContext());
3165 ctorStructFields.push_back(builder.getI32Type());
3166 ctorStructFields.push_back(ctorPFTy);
3167 ctorStructFields.push_back(ctorPFTy);
3169 auto ctorStructTy = mlir::LLVM::LLVMStructType::getLiteral(
3170 builder.getContext(), ctorStructFields);
3171 auto ctorStructArrayTy =
3172 mlir::LLVM::LLVMArrayType::get(ctorStructTy, globalXtors.size());
3174 mlir::Location loc =
module.getLoc();
3175 auto newGlobalOp = mlir::LLVM::GlobalOp::create(
3176 builder, loc, ctorStructArrayTy,
false,
3177 mlir::LLVM::Linkage::Appending, llvmXtorName, mlir::Attribute());
3179 builder.createBlock(&newGlobalOp.getRegion());
3180 builder.setInsertionPointToEnd(newGlobalOp.getInitializerBlock());
3182 mlir::Value result =
3183 mlir::LLVM::UndefOp::create(builder, loc, ctorStructArrayTy);
3185 for (
auto [index, fn] : llvm::enumerate(globalXtors)) {
3186 mlir::Value structInit =
3187 mlir::LLVM::UndefOp::create(builder, loc, ctorStructTy);
3188 mlir::Value initPriority = mlir::LLVM::ConstantOp::create(
3189 builder, loc, ctorStructFields[0], fn.second);
3190 mlir::Value initFuncAddr = mlir::LLVM::AddressOfOp::create(
3191 builder, loc, ctorStructFields[1], fn.first);
3192 mlir::Value initAssociate =
3193 mlir::LLVM::ZeroOp::create(builder, loc, ctorStructFields[2]);
3196 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
3197 initPriority, zero);
3198 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
3201 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
3203 result = mlir::LLVM::InsertValueOp::create(builder, loc, result, structInit,
3207 mlir::LLVM::ReturnOp::create(builder, loc, result);
3245 parent->walk([&](mlir::Block *blk) {
3246 if (blk->hasNoPredecessors() && !blk->isEntryBlock())
3247 unreachableBlocks.push_back(blk);
3250 std::set<mlir::Block *> visited;
3251 for (mlir::Block *root : unreachableBlocks) {
3254 std::deque<mlir::Block *> workList;
3255 workList.push_back(root);
3257 while (!workList.empty()) {
3258 mlir::Block *blk = workList.back();
3259 workList.pop_back();
3260 if (visited.count(blk))
3262 visited.emplace(blk);
3264 for (mlir::Operation &op : *blk)
3267 for (mlir::Block *succ : blk->getSuccessors())
3268 workList.push_back(succ);
3273mlir::LogicalResult CIRToLLVMObjSizeOpLowering::matchAndRewrite(
3274 cir::ObjSizeOp op, OpAdaptor adaptor,
3275 mlir::ConversionPatternRewriter &rewriter)
const {
3276 mlir::Type llvmResTy = getTypeConverter()->convertType(op.getType());
3277 mlir::Location loc = op->getLoc();
3279 mlir::IntegerType i1Ty = rewriter.getI1Type();
3281 auto i1Val = [&rewriter, &loc, &i1Ty](
bool val) {
3282 return mlir::LLVM::ConstantOp::create(rewriter, loc, i1Ty, val);
3289 i1Val(op.getNullunknown()),
3290 i1Val(op.getDynamic()),
3293 return mlir::LogicalResult::success();
3299 mlir::ModuleOp module = getOperation();
3300 mlir::OpBuilder opBuilder(module.getContext());
3301 for (
auto &[blockAddOp, blockInfo] :
3303 mlir::LLVM::BlockTagOp resolvedLabel =
3305 assert(resolvedLabel &&
"expected BlockTagOp to already be emitted");
3306 mlir::FlatSymbolRefAttr fnSym = blockInfo.getFunc();
3307 auto blkAddTag = mlir::LLVM::BlockAddressAttr::get(
3308 opBuilder.getContext(), fnSym, resolvedLabel.getTagAttr());
3309 blockAddOp.setBlockAddrAttr(blkAddTag);
3316 if (mlir::Attribute tripleAttr =
3317 module->getAttr(cir::CIRDialect::getTripleAttrName()))
3318 module->setAttr(mlir::LLVM::LLVMDialect::getTargetTripleAttrName(),
3321 if (mlir::Attribute asmAttr =
3322 module->getAttr(cir::CIRDialect::getModuleLevelAsmAttrName()))
3323 module->setAttr(mlir::LLVM::LLVMDialect::getModuleLevelAsmAttrName(),
3328 llvm::TimeTraceScope scope(
"Convert CIR to LLVM Pass");
3330 mlir::ModuleOp module = getOperation();
3331 mlir::DataLayout dl(module);
3332 mlir::LLVMTypeConverter converter(&getContext());
3341 mlir::RewritePatternSet patterns(&getContext());
3342 patterns.add<CIRToLLVMBlockAddressOpLowering, CIRToLLVMLabelOpLowering>(
3343 converter, patterns.getContext(), lowerModule.get(), dl, blockInfoAddr);
3346#define GET_LLVM_LOWERING_PATTERNS_LIST
3347#include "clang/CIR/Dialect/IR/CIRLowering.inc"
3348#undef GET_LLVM_LOWERING_PATTERNS_LIST
3349 >(converter, patterns.getContext(), lowerModule.get(), dl);
3353 mlir::ConversionTarget target(getContext());
3354 target.addLegalOp<mlir::ModuleOp>();
3355 target.addLegalDialect<mlir::LLVM::LLVMDialect>();
3356 target.addIllegalDialect<mlir::BuiltinDialect, cir::CIRDialect,
3357 mlir::func::FuncDialect>();
3360 ops.push_back(module);
3363 if (failed(applyPartialConversion(ops, target, std::move(patterns))))
3364 signalPassFailure();
3368 "llvm.global_ctors", [](mlir::Attribute attr) {
3369 auto ctorAttr = mlir::cast<cir::GlobalCtorAttr>(attr);
3370 return std::make_pair(ctorAttr.getName(),
3371 ctorAttr.getPriority());
3375 "llvm.global_dtors", [](mlir::Attribute attr) {
3376 auto dtorAttr = mlir::cast<cir::GlobalDtorAttr>(attr);
3377 return std::make_pair(dtorAttr.getName(),
3378 dtorAttr.getPriority());
3383mlir::LogicalResult CIRToLLVMBrOpLowering::matchAndRewrite(
3384 cir::BrOp op, OpAdaptor adaptor,
3385 mlir::ConversionPatternRewriter &rewriter)
const {
3386 rewriter.replaceOpWithNewOp<mlir::LLVM::BrOp>(op, adaptor.getOperands(),
3388 return mlir::LogicalResult::success();
3391mlir::LogicalResult CIRToLLVMGetMemberOpLowering::matchAndRewrite(
3392 cir::GetMemberOp op, OpAdaptor adaptor,
3393 mlir::ConversionPatternRewriter &rewriter)
const {
3394 mlir::Type llResTy = getTypeConverter()->convertType(op.getType());
3395 const auto recordTy =
3396 mlir::cast<cir::RecordType>(op.getAddrTy().getPointee());
3397 assert(recordTy &&
"expected record type");
3399 switch (recordTy.getKind()) {
3400 case cir::RecordType::Class:
3401 case cir::RecordType::Struct: {
3405 const mlir::Type elementTy = getTypeConverter()->convertType(recordTy);
3406 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, llResTy, elementTy,
3407 adaptor.getAddr(), offset);
3408 return mlir::success();
3410 case cir::RecordType::Union:
3413 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(op, llResTy,
3415 return mlir::success();
3419mlir::LogicalResult CIRToLLVMExtractMemberOpLowering::matchAndRewrite(
3420 cir::ExtractMemberOp op, OpAdaptor adaptor,
3421 mlir::ConversionPatternRewriter &rewriter)
const {
3422 std::int64_t indices[1] = {
static_cast<std::int64_t
>(op.getIndex())};
3424 mlir::Type recordTy = op.getRecord().getType();
3425 auto cirRecordTy = mlir::cast<cir::RecordType>(recordTy);
3426 switch (cirRecordTy.getKind()) {
3427 case cir::RecordType::Struct:
3428 case cir::RecordType::Class:
3429 rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractValueOp>(
3430 op, adaptor.getRecord(), indices);
3431 return mlir::success();
3433 case cir::RecordType::Union:
3434 op.emitError(
"cir.extract_member cannot extract member from a union");
3435 return mlir::failure();
3437 llvm_unreachable(
"Unexpected record kind");
3440mlir::LogicalResult CIRToLLVMInsertMemberOpLowering::matchAndRewrite(
3441 cir::InsertMemberOp op, OpAdaptor adaptor,
3442 mlir::ConversionPatternRewriter &rewriter)
const {
3443 std::int64_t indecies[1] = {
static_cast<std::int64_t
>(op.getIndex())};
3444 mlir::Type recordTy = op.getRecord().getType();
3446 if (
auto cirRecordTy = mlir::dyn_cast<cir::RecordType>(recordTy)) {
3447 if (cirRecordTy.getKind() == cir::RecordType::Union) {
3448 op.emitError(
"cir.update_member cannot update member of a union");
3449 return mlir::failure();
3453 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
3454 op, adaptor.getRecord(), adaptor.getValue(), indecies);
3455 return mlir::success();
3458mlir::LogicalResult CIRToLLVMUnreachableOpLowering::matchAndRewrite(
3459 cir::UnreachableOp op, OpAdaptor adaptor,
3460 mlir::ConversionPatternRewriter &rewriter)
const {
3461 rewriter.replaceOpWithNewOp<mlir::LLVM::UnreachableOp>(op);
3462 return mlir::success();
3466 mlir::Operation *srcOp, llvm::StringRef fnName,
3468 auto modOp = srcOp->getParentOfType<mlir::ModuleOp>();
3469 auto enclosingFnOp = srcOp->getParentOfType<mlir::LLVM::LLVMFuncOp>();
3470 mlir::Operation *sourceSymbol =
3471 mlir::SymbolTable::lookupSymbolIn(modOp, fnName);
3472 if (!sourceSymbol) {
3473 mlir::OpBuilder::InsertionGuard guard(rewriter);
3474 rewriter.setInsertionPoint(enclosingFnOp);
3475 mlir::LLVM::LLVMFuncOp::create(rewriter, srcOp->getLoc(), fnName, fnTy);
3479mlir::LogicalResult CIRToLLVMThrowOpLowering::matchAndRewrite(
3480 cir::ThrowOp op, OpAdaptor adaptor,
3481 mlir::ConversionPatternRewriter &rewriter)
const {
3482 mlir::Location loc = op.getLoc();
3483 auto voidTy = mlir::LLVM::LLVMVoidType::get(getContext());
3485 if (op.rethrows()) {
3486 auto funcTy = mlir::LLVM::LLVMFunctionType::get(voidTy, {});
3489 const llvm::StringRef functionName =
"__cxa_rethrow";
3492 auto cxaRethrow = mlir::LLVM::CallOp::create(
3493 rewriter, loc, mlir::TypeRange{}, functionName);
3495 rewriter.replaceOp(op, cxaRethrow);
3496 return mlir::success();
3499 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3500 auto fnTy = mlir::LLVM::LLVMFunctionType::get(
3501 voidTy, {llvmPtrTy, llvmPtrTy, llvmPtrTy});
3504 const llvm::StringRef fnName =
"__cxa_throw";
3507 mlir::Value typeInfo = mlir::LLVM::AddressOfOp::create(
3508 rewriter, loc, mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
3509 adaptor.getTypeInfoAttr());
3513 dtor = mlir::LLVM::AddressOfOp::create(rewriter, loc, llvmPtrTy,
3514 adaptor.getDtorAttr());
3516 dtor = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmPtrTy);
3519 auto cxaThrowCall = mlir::LLVM::CallOp::create(
3520 rewriter, loc, mlir::TypeRange{}, fnName,
3521 mlir::ValueRange{adaptor.getExceptionPtr(), typeInfo, dtor});
3523 rewriter.replaceOp(op, cxaThrowCall);
3524 return mlir::success();
3527mlir::LogicalResult CIRToLLVMAllocExceptionOpLowering::matchAndRewrite(
3528 cir::AllocExceptionOp op, OpAdaptor adaptor,
3529 mlir::ConversionPatternRewriter &rewriter)
const {
3531 StringRef fnName =
"__cxa_allocate_exception";
3532 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3533 auto int64Ty = mlir::IntegerType::get(rewriter.getContext(), 64);
3534 auto fnTy = mlir::LLVM::LLVMFunctionType::get(llvmPtrTy, {int64Ty});
3537 auto exceptionSize = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
3538 adaptor.getSizeAttr());
3540 auto allocaExceptionCall = mlir::LLVM::CallOp::create(
3541 rewriter, op.getLoc(), mlir::TypeRange{llvmPtrTy}, fnName,
3542 mlir::ValueRange{exceptionSize});
3544 rewriter.replaceOp(op, allocaExceptionCall);
3545 return mlir::success();
3548static mlir::LLVM::LLVMStructType
3551 mlir::MLIRContext *ctx = rewriter.getContext();
3552 auto llvmPtr = mlir::LLVM::LLVMPointerType::get(ctx);
3554 return mlir::LLVM::LLVMStructType::getLiteral(ctx, structFields);
3557mlir::LogicalResult CIRToLLVMEhInflightOpLowering::matchAndRewrite(
3558 cir::EhInflightOp op, OpAdaptor adaptor,
3559 mlir::ConversionPatternRewriter &rewriter)
const {
3560 auto llvmFn = op->getParentOfType<mlir::LLVM::LLVMFuncOp>();
3561 assert(llvmFn &&
"expected LLVM function parent");
3562 mlir::Block *entryBlock = &llvmFn.getRegion().front();
3563 assert(entryBlock->isEntryBlock());
3565 mlir::ArrayAttr catchListAttr = op.getCatchTypeListAttr();
3566 mlir::SmallVector<mlir::Value> catchSymAddrs;
3568 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3569 mlir::Location loc = op.getLoc();
3574 if (catchListAttr) {
3577 for (mlir::Attribute catchAttr : catchListAttr) {
3578 auto symAttr = cast<mlir::FlatSymbolRefAttr>(catchAttr);
3581 mlir::OpBuilder::InsertionGuard guard(rewriter);
3582 rewriter.setInsertionPointToStart(entryBlock);
3583 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
3584 rewriter, loc, llvmPtrTy, symAttr.getValue());
3585 catchSymAddrs.push_back(addrOp);
3587 }
else if (!op.getCleanup()) {
3591 mlir::OpBuilder::InsertionGuard guard(rewriter);
3592 rewriter.setInsertionPointToStart(entryBlock);
3593 mlir::Value nullOp = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmPtrTy);
3594 catchSymAddrs.push_back(nullOp);
3599 mlir::LLVM::LLVMStructType llvmLandingPadStructTy =
3601 auto landingPadOp = mlir::LLVM::LandingpadOp::create(
3602 rewriter, loc, llvmLandingPadStructTy, catchSymAddrs);
3604 if (op.getCleanup())
3605 landingPadOp.setCleanup(
true);
3608 mlir::LLVM::ExtractValueOp::create(rewriter, loc, landingPadOp, 0);
3609 mlir::Value selector =
3610 mlir::LLVM::ExtractValueOp::create(rewriter, loc, landingPadOp, 1);
3611 rewriter.replaceOp(op, mlir::ValueRange{slot, selector});
3613 return mlir::success();
3616mlir::LogicalResult CIRToLLVMResumeFlatOpLowering::matchAndRewrite(
3617 cir::ResumeFlatOp op, OpAdaptor adaptor,
3618 mlir::ConversionPatternRewriter &rewriter)
const {
3623 mlir::Value poison = mlir::LLVM::PoisonOp::create(rewriter, op.getLoc(),
3624 llvmLandingPadStructTy);
3626 SmallVector<int64_t> slotIdx = {0};
3627 mlir::Value slot = mlir::LLVM::InsertValueOp::create(
3628 rewriter, op.getLoc(), poison, adaptor.getExceptionPtr(), slotIdx);
3630 SmallVector<int64_t> selectorIdx = {1};
3631 mlir::Value selector = mlir::LLVM::InsertValueOp::create(
3632 rewriter, op.getLoc(), slot, adaptor.getTypeId(), selectorIdx);
3634 rewriter.replaceOpWithNewOp<mlir::LLVM::ResumeOp>(op, selector);
3635 return mlir::success();
3638mlir::LogicalResult CIRToLLVMEhTypeIdOpLowering::matchAndRewrite(
3639 cir::EhTypeIdOp op, OpAdaptor adaptor,
3640 mlir::ConversionPatternRewriter &rewriter)
const {
3641 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
3642 rewriter, op.getLoc(),
3643 mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
3644 op.getTypeSymAttr());
3645 rewriter.replaceOpWithNewOp<mlir::LLVM::EhTypeidForOp>(
3646 op, rewriter.getI32Type(), addrOp);
3647 return mlir::success();
3650mlir::LogicalResult CIRToLLVMTrapOpLowering::matchAndRewrite(
3651 cir::TrapOp op, OpAdaptor adaptor,
3652 mlir::ConversionPatternRewriter &rewriter)
const {
3653 mlir::Location loc = op->getLoc();
3654 rewriter.eraseOp(op);
3656 mlir::LLVM::Trap::create(rewriter, loc);
3661 mlir::LLVM::UnreachableOp::create(rewriter, loc);
3663 return mlir::success();
3668 mlir::ConversionPatternRewriter &rewriter,
3669 const mlir::TypeConverter *converter,
3670 mlir::FlatSymbolRefAttr nameAttr, mlir::Type &eltType) {
3671 auto module = op->getParentOfType<mlir::ModuleOp>();
3672 mlir::Operation *symbol = mlir::SymbolTable::lookupSymbolIn(module, nameAttr);
3673 if (
auto llvmSymbol = mlir::dyn_cast<mlir::LLVM::GlobalOp>(symbol)) {
3674 eltType = llvmSymbol.getType();
3675 }
else if (
auto cirSymbol = mlir::dyn_cast<cir::GlobalOp>(symbol)) {
3676 eltType = converter->convertType(cirSymbol.getSymType());
3678 op->emitError() <<
"unexpected symbol type for " << symbol;
3682 return mlir::LLVM::AddressOfOp::create(
3683 rewriter, op->getLoc(),
3684 mlir::LLVM::LLVMPointerType::get(op->getContext()), nameAttr.getValue());
3687mlir::LogicalResult CIRToLLVMVTableAddrPointOpLowering::matchAndRewrite(
3688 cir::VTableAddrPointOp op, OpAdaptor adaptor,
3689 mlir::ConversionPatternRewriter &rewriter)
const {
3690 const mlir::TypeConverter *converter = getTypeConverter();
3691 mlir::Type targetType = converter->convertType(op.getType());
3695 op.getNameAttr(), eltType);
3697 return op.emitError() <<
"Unable to get value for vtable symbol";
3700 0, op.getAddressPointAttr().getIndex(),
3701 op.getAddressPointAttr().getOffset()};
3703 assert(eltType &&
"Shouldn't ever be missing an eltType here");
3704 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
3705 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
3706 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, targetType, eltType,
3707 symAddr, offsets, inboundsNuw);
3708 return mlir::success();
3711mlir::LogicalResult CIRToLLVMVTableGetVPtrOpLowering::matchAndRewrite(
3712 cir::VTableGetVPtrOp op, OpAdaptor adaptor,
3713 mlir::ConversionPatternRewriter &rewriter)
const {
3717 mlir::Value srcVal = adaptor.getSrc();
3718 rewriter.replaceOp(op, srcVal);
3719 return mlir::success();
3722mlir::LogicalResult CIRToLLVMVTableGetVirtualFnAddrOpLowering::matchAndRewrite(
3723 cir::VTableGetVirtualFnAddrOp op, OpAdaptor adaptor,
3724 mlir::ConversionPatternRewriter &rewriter)
const {
3725 mlir::Type targetType = getTypeConverter()->convertType(op.getType());
3726 auto eltType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3727 llvm::SmallVector<mlir::LLVM::GEPArg> offsets =
3728 llvm::SmallVector<mlir::LLVM::GEPArg>{op.getIndex()};
3729 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
3730 op, targetType, eltType, adaptor.getVptr(), offsets,
3731 mlir::LLVM::GEPNoWrapFlags::inbounds);
3732 return mlir::success();
3735mlir::LogicalResult CIRToLLVMVTTAddrPointOpLowering::matchAndRewrite(
3736 cir::VTTAddrPointOp op, OpAdaptor adaptor,
3737 mlir::ConversionPatternRewriter &rewriter)
const {
3738 const mlir::Type resultType = getTypeConverter()->convertType(op.getType());
3739 llvm::SmallVector<mlir::LLVM::GEPArg> offsets;
3741 mlir::Value llvmAddr = adaptor.getSymAddr();
3743 if (op.getSymAddr()) {
3744 if (op.getOffset() == 0) {
3745 rewriter.replaceOp(op, {llvmAddr});
3746 return mlir::success();
3749 offsets.push_back(adaptor.getOffset());
3750 eltType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3753 op.getNameAttr(), eltType);
3754 assert(eltType &&
"Shouldn't ever be missing an eltType here");
3755 offsets.push_back(0);
3756 offsets.push_back(adaptor.getOffset());
3758 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
3759 op, resultType, eltType, llvmAddr, offsets,
3760 mlir::LLVM::GEPNoWrapFlags::inbounds);
3761 return mlir::success();
3764mlir::LogicalResult CIRToLLVMStackSaveOpLowering::matchAndRewrite(
3765 cir::StackSaveOp op, OpAdaptor adaptor,
3766 mlir::ConversionPatternRewriter &rewriter)
const {
3767 const mlir::Type ptrTy = getTypeConverter()->convertType(op.getType());
3768 rewriter.replaceOpWithNewOp<mlir::LLVM::StackSaveOp>(op, ptrTy);
3769 return mlir::success();
3772mlir::LogicalResult CIRToLLVMStackRestoreOpLowering::matchAndRewrite(
3773 cir::StackRestoreOp op, OpAdaptor adaptor,
3774 mlir::ConversionPatternRewriter &rewriter)
const {
3775 rewriter.replaceOpWithNewOp<mlir::LLVM::StackRestoreOp>(op, adaptor.getPtr());
3776 return mlir::success();
3779mlir::LogicalResult CIRToLLVMVecCreateOpLowering::matchAndRewrite(
3780 cir::VecCreateOp op, OpAdaptor adaptor,
3781 mlir::ConversionPatternRewriter &rewriter)
const {
3784 const auto vecTy = mlir::cast<cir::VectorType>(op.getType());
3785 const mlir::Type llvmTy = typeConverter->convertType(vecTy);
3786 const mlir::Location loc = op.getLoc();
3787 mlir::Value result = mlir::LLVM::PoisonOp::create(rewriter, loc, llvmTy);
3788 assert(vecTy.getSize() == op.getElements().size() &&
3789 "cir.vec.create op count doesn't match vector type elements count");
3791 for (uint64_t i = 0; i < vecTy.getSize(); ++i) {
3792 const mlir::Value indexValue =
3793 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
3794 result = mlir::LLVM::InsertElementOp::create(
3795 rewriter, loc, result, adaptor.getElements()[i], indexValue);
3798 rewriter.replaceOp(op, result);
3799 return mlir::success();
3802mlir::LogicalResult CIRToLLVMVecExtractOpLowering::matchAndRewrite(
3803 cir::VecExtractOp op, OpAdaptor adaptor,
3804 mlir::ConversionPatternRewriter &rewriter)
const {
3805 rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractElementOp>(
3806 op, adaptor.getVec(), adaptor.getIndex());
3807 return mlir::success();
3810mlir::LogicalResult CIRToLLVMVecInsertOpLowering::matchAndRewrite(
3811 cir::VecInsertOp op, OpAdaptor adaptor,
3812 mlir::ConversionPatternRewriter &rewriter)
const {
3813 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertElementOp>(
3814 op, adaptor.getVec(), adaptor.getValue(), adaptor.getIndex());
3815 return mlir::success();
3818mlir::LogicalResult CIRToLLVMVecCmpOpLowering::matchAndRewrite(
3819 cir::VecCmpOp op, OpAdaptor adaptor,
3820 mlir::ConversionPatternRewriter &rewriter)
const {
3821 mlir::Type elementType = elementTypeIfVector(op.getLhs().getType());
3822 mlir::Value bitResult;
3823 if (
auto intType = mlir::dyn_cast<cir::IntType>(elementType)) {
3824 bitResult = mlir::LLVM::ICmpOp::create(
3825 rewriter, op.getLoc(),
3827 adaptor.getLhs(), adaptor.getRhs());
3828 }
else if (mlir::isa<cir::FPTypeInterface>(elementType)) {
3829 bitResult = mlir::LLVM::FCmpOp::create(
3831 adaptor.getLhs(), adaptor.getRhs());
3833 return op.emitError() <<
"unsupported type for VecCmpOp: " << elementType;
3839 if (cast<cir::IntType>(cast<cir::VectorType>(op.getType()).getElementType())
3841 rewriter.replaceOpWithNewOp<mlir::LLVM::SExtOp>(
3842 op, typeConverter->convertType(op.getType()), bitResult);
3844 rewriter.replaceOp(op, bitResult);
3845 return mlir::success();
3848mlir::LogicalResult CIRToLLVMVecSplatOpLowering::matchAndRewrite(
3849 cir::VecSplatOp op, OpAdaptor adaptor,
3850 mlir::ConversionPatternRewriter &rewriter)
const {
3856 cir::VectorType vecTy = op.getType();
3857 mlir::Type llvmTy = typeConverter->convertType(vecTy);
3858 mlir::Location loc = op.getLoc();
3859 mlir::Value poison = mlir::LLVM::PoisonOp::create(rewriter, loc, llvmTy);
3861 mlir::Value elementValue = adaptor.getValue();
3862 if (elementValue.getDefiningOp<mlir::LLVM::PoisonOp>()) {
3865 rewriter.replaceOp(op, poison);
3866 return mlir::success();
3869 if (
auto constValue = elementValue.getDefiningOp<mlir::LLVM::ConstantOp>()) {
3870 if (
auto intAttr = dyn_cast<mlir::IntegerAttr>(constValue.getValue())) {
3871 mlir::DenseIntElementsAttr denseVec = mlir::DenseIntElementsAttr::get(
3872 mlir::cast<mlir::ShapedType>(llvmTy), intAttr.getValue());
3873 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
3874 op, denseVec.getType(), denseVec);
3875 return mlir::success();
3878 if (
auto fpAttr = dyn_cast<mlir::FloatAttr>(constValue.getValue())) {
3879 mlir::DenseFPElementsAttr denseVec = mlir::DenseFPElementsAttr::get(
3880 mlir::cast<mlir::ShapedType>(llvmTy), fpAttr.getValue());
3881 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
3882 op, denseVec.getType(), denseVec);
3883 return mlir::success();
3887 mlir::Value indexValue =
3888 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), 0);
3889 mlir::Value oneElement = mlir::LLVM::InsertElementOp::create(
3890 rewriter, loc, poison, elementValue, indexValue);
3891 SmallVector<int32_t> zeroValues(vecTy.getSize(), 0);
3892 rewriter.replaceOpWithNewOp<mlir::LLVM::ShuffleVectorOp>(op, oneElement,
3893 poison, zeroValues);
3894 return mlir::success();
3897mlir::LogicalResult CIRToLLVMVecShuffleOpLowering::matchAndRewrite(
3898 cir::VecShuffleOp op, OpAdaptor adaptor,
3899 mlir::ConversionPatternRewriter &rewriter)
const {
3903 SmallVector<int, 8> indices;
3905 op.getIndices().begin(), op.getIndices().end(),
3906 std::back_inserter(indices), [](mlir::Attribute intAttr) {
3907 return mlir::cast<cir::IntAttr>(intAttr).getValue().getSExtValue();
3909 rewriter.replaceOpWithNewOp<mlir::LLVM::ShuffleVectorOp>(
3910 op, adaptor.getVec1(), adaptor.getVec2(), indices);
3911 return mlir::success();
3914mlir::LogicalResult CIRToLLVMVecShuffleDynamicOpLowering::matchAndRewrite(
3915 cir::VecShuffleDynamicOp op, OpAdaptor adaptor,
3916 mlir::ConversionPatternRewriter &rewriter)
const {
3928 mlir::Location loc = op.getLoc();
3929 mlir::Value input = adaptor.getVec();
3930 mlir::Type llvmIndexVecType =
3931 getTypeConverter()->convertType(op.getIndices().getType());
3932 mlir::Type llvmIndexType = getTypeConverter()->convertType(
3933 elementTypeIfVector(op.getIndices().getType()));
3935 mlir::cast<cir::VectorType>(op.getVec().getType()).getSize();
3937 uint64_t maskBits = llvm::NextPowerOf2(numElements - 1) - 1;
3938 mlir::Value maskValue = mlir::LLVM::ConstantOp::create(
3939 rewriter, loc, llvmIndexType,
3940 rewriter.getIntegerAttr(llvmIndexType, maskBits));
3941 mlir::Value maskVector =
3942 mlir::LLVM::UndefOp::create(rewriter, loc, llvmIndexVecType);
3944 for (uint64_t i = 0; i < numElements; ++i) {
3945 mlir::Value idxValue =
3946 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
3947 maskVector = mlir::LLVM::InsertElementOp::create(rewriter, loc, maskVector,
3948 maskValue, idxValue);
3951 mlir::Value maskedIndices = mlir::LLVM::AndOp::create(
3952 rewriter, loc, llvmIndexVecType, adaptor.getIndices(), maskVector);
3953 mlir::Value result = mlir::LLVM::UndefOp::create(
3954 rewriter, loc, getTypeConverter()->convertType(op.getVec().getType()));
3955 for (uint64_t i = 0; i < numElements; ++i) {
3956 mlir::Value iValue =
3957 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
3958 mlir::Value indexValue = mlir::LLVM::ExtractElementOp::create(
3959 rewriter, loc, maskedIndices, iValue);
3960 mlir::Value valueAtIndex =
3961 mlir::LLVM::ExtractElementOp::create(rewriter, loc, input, indexValue);
3962 result = mlir::LLVM::InsertElementOp::create(rewriter, loc, result,
3963 valueAtIndex, iValue);
3965 rewriter.replaceOp(op, result);
3966 return mlir::success();
3969mlir::LogicalResult CIRToLLVMVecTernaryOpLowering::matchAndRewrite(
3970 cir::VecTernaryOp op, OpAdaptor adaptor,
3971 mlir::ConversionPatternRewriter &rewriter)
const {
3973 mlir::Value bitVec = mlir::LLVM::ICmpOp::create(
3974 rewriter, op.getLoc(), mlir::LLVM::ICmpPredicate::ne, adaptor.getCond(),
3975 mlir::LLVM::ZeroOp::create(
3976 rewriter, op.getCond().getLoc(),
3977 typeConverter->convertType(op.getCond().getType())));
3978 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(
3979 op, bitVec, adaptor.getLhs(), adaptor.getRhs());
3980 return mlir::success();
3983mlir::LogicalResult CIRToLLVMComplexAddOpLowering::matchAndRewrite(
3984 cir::ComplexAddOp op, OpAdaptor adaptor,
3985 mlir::ConversionPatternRewriter &rewriter)
const {
3986 mlir::Value lhs = adaptor.getLhs();
3987 mlir::Value rhs = adaptor.getRhs();
3988 mlir::Location loc = op.getLoc();
3990 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
3991 mlir::Type complexElemTy =
3992 getTypeConverter()->convertType(
complexType.getElementType());
3993 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
3994 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{0}));
3995 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
3996 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{1}));
3997 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
3998 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{0}));
3999 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
4000 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{1}));
4002 mlir::Value newReal;
4003 mlir::Value newImag;
4004 if (complexElemTy.isInteger()) {
4005 newReal = mlir::LLVM::AddOp::create(rewriter, loc, complexElemTy, lhsReal,
4007 newImag = mlir::LLVM::AddOp::create(rewriter, loc, complexElemTy, lhsImag,
4012 newReal = mlir::LLVM::FAddOp::create(rewriter, loc, complexElemTy, lhsReal,
4014 newImag = mlir::LLVM::FAddOp::create(rewriter, loc, complexElemTy, lhsImag,
4018 mlir::Type complexLLVMTy =
4019 getTypeConverter()->convertType(op.getResult().getType());
4020 auto initialComplex =
4021 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), complexLLVMTy);
4023 auto realComplex = mlir::LLVM::InsertValueOp::create(
4024 rewriter, op->getLoc(), initialComplex, newReal, ArrayRef(int64_t{0}));
4026 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
4027 op, realComplex, newImag, ArrayRef(int64_t{1}));
4029 return mlir::success();
4032mlir::LogicalResult CIRToLLVMComplexCreateOpLowering::matchAndRewrite(
4033 cir::ComplexCreateOp op, OpAdaptor adaptor,
4034 mlir::ConversionPatternRewriter &rewriter)
const {
4035 mlir::Type complexLLVMTy =
4036 getTypeConverter()->convertType(op.getResult().getType());
4037 auto initialComplex =
4038 mlir::LLVM::UndefOp::create(rewriter, op->getLoc(), complexLLVMTy);
4040 auto realComplex = mlir::LLVM::InsertValueOp::create(
4041 rewriter, op->getLoc(), initialComplex, adaptor.getReal(),
4042 ArrayRef(int64_t{0}));
4044 auto complex = mlir::LLVM::InsertValueOp::create(
4045 rewriter, op->getLoc(), realComplex, adaptor.getImag(),
4046 ArrayRef(int64_t{1}));
4048 rewriter.replaceOp(op, complex);
4049 return mlir::success();
4052mlir::LogicalResult CIRToLLVMComplexRealOpLowering::matchAndRewrite(
4053 cir::ComplexRealOp op, OpAdaptor adaptor,
4054 mlir::ConversionPatternRewriter &rewriter)
const {
4055 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
4056 mlir::Value operand = adaptor.getOperand();
4057 if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) {
4058 operand = mlir::LLVM::ExtractValueOp::create(
4059 rewriter, op.getLoc(), resultLLVMTy, operand,
4060 llvm::ArrayRef<std::int64_t>{0});
4062 rewriter.replaceOp(op, operand);
4063 return mlir::success();
4066mlir::LogicalResult CIRToLLVMComplexSubOpLowering::matchAndRewrite(
4067 cir::ComplexSubOp op, OpAdaptor adaptor,
4068 mlir::ConversionPatternRewriter &rewriter)
const {
4069 mlir::Value lhs = adaptor.getLhs();
4070 mlir::Value rhs = adaptor.getRhs();
4071 mlir::Location loc = op.getLoc();
4073 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
4074 mlir::Type complexElemTy =
4075 getTypeConverter()->convertType(
complexType.getElementType());
4076 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
4077 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{0}));
4078 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
4079 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{1}));
4080 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
4081 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{0}));
4082 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
4083 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{1}));
4085 mlir::Value newReal;
4086 mlir::Value newImag;
4087 if (complexElemTy.isInteger()) {
4088 newReal = mlir::LLVM::SubOp::create(rewriter, loc, complexElemTy, lhsReal,
4090 newImag = mlir::LLVM::SubOp::create(rewriter, loc, complexElemTy, lhsImag,
4095 newReal = mlir::LLVM::FSubOp::create(rewriter, loc, complexElemTy, lhsReal,
4097 newImag = mlir::LLVM::FSubOp::create(rewriter, loc, complexElemTy, lhsImag,
4101 mlir::Type complexLLVMTy =
4102 getTypeConverter()->convertType(op.getResult().getType());
4103 auto initialComplex =
4104 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), complexLLVMTy);
4106 auto realComplex = mlir::LLVM::InsertValueOp::create(
4107 rewriter, op->getLoc(), initialComplex, newReal, ArrayRef(int64_t{0}));
4109 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
4110 op, realComplex, newImag, ArrayRef(int64_t{1}));
4112 return mlir::success();
4115mlir::LogicalResult CIRToLLVMComplexImagOpLowering::matchAndRewrite(
4116 cir::ComplexImagOp op, OpAdaptor adaptor,
4117 mlir::ConversionPatternRewriter &rewriter)
const {
4118 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
4119 mlir::Value operand = adaptor.getOperand();
4120 mlir::Location loc = op.getLoc();
4122 if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) {
4123 operand = mlir::LLVM::ExtractValueOp::create(
4124 rewriter, loc, resultLLVMTy, operand, llvm::ArrayRef<std::int64_t>{1});
4126 mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(resultLLVMTy);
4128 mlir::LLVM::ConstantOp::create(rewriter, loc, resultLLVMTy, zeroAttr);
4131 rewriter.replaceOp(op, operand);
4132 return mlir::success();
4136 mlir::MLIRContext *context,
4137 unsigned &storageSize) {
4138 return TypeSwitch<mlir::Type, mlir::IntegerType>(storageType)
4139 .Case<cir::ArrayType>([&](cir::ArrayType atTy) {
4140 storageSize = atTy.getSize() * 8;
4141 return mlir::IntegerType::get(context, storageSize);
4143 .Case<cir::IntType>([&](cir::IntType intTy) {
4144 storageSize = intTy.getWidth();
4145 return mlir::IntegerType::get(context, storageSize);
4147 .Default([](mlir::Type) -> mlir::IntegerType {
4149 "Either ArrayType or IntType expected for bitfields storage");
4153mlir::LogicalResult CIRToLLVMSetBitfieldOpLowering::matchAndRewrite(
4154 cir::SetBitfieldOp op, OpAdaptor adaptor,
4155 mlir::ConversionPatternRewriter &rewriter)
const {
4156 mlir::OpBuilder::InsertionGuard guard(rewriter);
4157 rewriter.setInsertionPoint(op);
4159 cir::BitfieldInfoAttr info = op.getBitfieldInfo();
4160 uint64_t size = info.getSize();
4161 uint64_t offset = info.getOffset();
4162 mlir::Type storageType = info.getStorageType();
4163 mlir::MLIRContext *context = storageType.getContext();
4165 unsigned storageSize = 0;
4167 mlir::IntegerType intType =
4170 mlir::Value srcVal =
createIntCast(rewriter, adaptor.getSrc(), intType);
4171 unsigned srcWidth = storageSize;
4172 mlir::Value resultVal = srcVal;
4174 if (storageSize != size) {
4175 assert(storageSize > size &&
"Invalid bitfield size.");
4177 mlir::Value val = mlir::LLVM::LoadOp::create(
4178 rewriter, op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(),
4179 op.getIsVolatile());
4182 createAnd(rewriter, srcVal, llvm::APInt::getLowBitsSet(srcWidth, size));
4184 srcVal =
createShL(rewriter, srcVal, offset);
4188 ~llvm::APInt::getBitsSet(srcWidth, offset, offset + size));
4191 srcVal = mlir::LLVM::OrOp::create(rewriter, op.getLoc(), val, srcVal);
4194 mlir::LLVM::StoreOp::create(rewriter, op.getLoc(), srcVal, adaptor.getAddr(),
4195 op.getAlignment(), op.getIsVolatile());
4197 mlir::Type resultTy = getTypeConverter()->convertType(op.getType());
4199 if (info.getIsSigned()) {
4200 assert(size <= storageSize);
4201 unsigned highBits = storageSize - size;
4204 resultVal =
createShL(rewriter, resultVal, highBits);
4205 resultVal =
createAShR(rewriter, resultVal, highBits);
4210 mlir::cast<mlir::IntegerType>(resultTy),
4211 info.getIsSigned());
4213 rewriter.replaceOp(op, resultVal);
4214 return mlir::success();
4217mlir::LogicalResult CIRToLLVMComplexImagPtrOpLowering::matchAndRewrite(
4218 cir::ComplexImagPtrOp op, OpAdaptor adaptor,
4219 mlir::ConversionPatternRewriter &rewriter)
const {
4220 cir::PointerType operandTy = op.getOperand().getType();
4221 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
4222 mlir::Type elementLLVMTy =
4223 getTypeConverter()->convertType(operandTy.getPointee());
4225 mlir::LLVM::GEPArg gepIndices[2] = {{0}, {1}};
4226 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
4227 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
4228 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
4229 op, resultLLVMTy, elementLLVMTy, adaptor.getOperand(), gepIndices,
4231 return mlir::success();
4234mlir::LogicalResult CIRToLLVMComplexRealPtrOpLowering::matchAndRewrite(
4235 cir::ComplexRealPtrOp op, OpAdaptor adaptor,
4236 mlir::ConversionPatternRewriter &rewriter)
const {
4237 cir::PointerType operandTy = op.getOperand().getType();
4238 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
4239 mlir::Type elementLLVMTy =
4240 getTypeConverter()->convertType(operandTy.getPointee());
4242 mlir::LLVM::GEPArg gepIndices[2] = {0, 0};
4243 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
4244 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
4245 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
4246 op, resultLLVMTy, elementLLVMTy, adaptor.getOperand(), gepIndices,
4248 return mlir::success();
4251mlir::LogicalResult CIRToLLVMGetBitfieldOpLowering::matchAndRewrite(
4252 cir::GetBitfieldOp op, OpAdaptor adaptor,
4253 mlir::ConversionPatternRewriter &rewriter)
const {
4255 mlir::OpBuilder::InsertionGuard guard(rewriter);
4256 rewriter.setInsertionPoint(op);
4258 cir::BitfieldInfoAttr info = op.getBitfieldInfo();
4260 uint64_t offset = info.getOffset();
4261 mlir::Type storageType = info.getStorageType();
4262 mlir::MLIRContext *context = storageType.getContext();
4263 unsigned storageSize = 0;
4265 mlir::IntegerType intType =
4268 mlir::Value val = mlir::LLVM::LoadOp::create(
4269 rewriter, op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(),
4270 op.getIsVolatile());
4271 val = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), intType, val);
4273 if (info.getIsSigned()) {
4274 assert(
static_cast<unsigned>(offset + size) <= storageSize);
4275 unsigned highBits = storageSize - offset - size;
4276 val =
createShL(rewriter, val, highBits);
4277 val =
createAShR(rewriter, val, offset + highBits);
4281 if (
static_cast<unsigned>(offset) + size < storageSize)
4283 llvm::APInt::getLowBitsSet(storageSize, size));
4286 mlir::Type resTy = getTypeConverter()->convertType(op.getType());
4288 rewriter, val, mlir::cast<mlir::IntegerType>(resTy), info.getIsSigned());
4289 rewriter.replaceOp(op, newOp);
4290 return mlir::success();
4293mlir::LogicalResult CIRToLLVMIsConstantOpLowering::matchAndRewrite(
4294 cir::IsConstantOp op, OpAdaptor adaptor,
4295 mlir::ConversionPatternRewriter &rewriter)
const {
4296 rewriter.replaceOpWithNewOp<mlir::LLVM::IsConstantOp>(op, adaptor.getVal());
4297 return mlir::success();
4300mlir::LogicalResult CIRToLLVMInlineAsmOpLowering::matchAndRewrite(
4301 cir::InlineAsmOp op, OpAdaptor adaptor,
4302 mlir::ConversionPatternRewriter &rewriter)
const {
4304 if (op.getNumResults())
4305 llResTy = getTypeConverter()->convertType(op.getType(0));
4307 cir::AsmFlavor dialect = op.getAsmFlavor();
4308 mlir::LLVM::AsmDialect llDialect = dialect == cir::AsmFlavor::x86_att
4309 ? mlir::LLVM::AsmDialect::AD_ATT
4310 : mlir::LLVM::AsmDialect::AD_Intel;
4312 SmallVector<mlir::Attribute> opAttrs;
4313 StringRef llvmAttrName = mlir::LLVM::InlineAsmOp::getElementTypeAttrName();
4319 if (!op.getNumResults())
4320 opAttrs.push_back(mlir::Attribute());
4322 SmallVector<mlir::Value> llvmOperands;
4323 SmallVector<mlir::Value> cirOperands;
4324 for (
auto const &[llvmOp, cirOp] :
4325 zip(adaptor.getAsmOperands(), op.getAsmOperands())) {
4326 append_range(llvmOperands, llvmOp);
4327 append_range(cirOperands, cirOp);
4332 for (
auto const &[cirOpAttr, cirOp] :
4333 zip(op.getOperandAttrs(), cirOperands)) {
4335 opAttrs.push_back(mlir::Attribute());
4339 llvm::SmallVector<mlir::NamedAttribute, 1> attrs;
4340 cir::PointerType typ = mlir::cast<cir::PointerType>(cirOp.getType());
4342 *getTypeConverter(), dataLayout, typ.getPointee()));
4344 attrs.push_back(rewriter.getNamedAttr(llvmAttrName, typAttr));
4345 mlir::DictionaryAttr newDict = rewriter.getDictionaryAttr(attrs);
4346 opAttrs.push_back(newDict);
4349 rewriter.replaceOpWithNewOp<mlir::LLVM::InlineAsmOp>(
4350 op, llResTy, llvmOperands, op.getAsmStringAttr(), op.getConstraintsAttr(),
4351 op.getSideEffectsAttr(),
4354 mlir::LLVM::TailCallKindAttr::get(
4355 getContext(), mlir::LLVM::tailcallkind::TailCallKind::None),
4356 mlir::LLVM::AsmDialectAttr::get(getContext(), llDialect),
4357 rewriter.getArrayAttr(opAttrs));
4359 return mlir::success();
4362mlir::LogicalResult CIRToLLVMVAStartOpLowering::matchAndRewrite(
4363 cir::VAStartOp op, OpAdaptor adaptor,
4364 mlir::ConversionPatternRewriter &rewriter)
const {
4365 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4366 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4367 adaptor.getArgList());
4368 rewriter.replaceOpWithNewOp<mlir::LLVM::VaStartOp>(op, vaList);
4369 return mlir::success();
4372mlir::LogicalResult CIRToLLVMVAEndOpLowering::matchAndRewrite(
4373 cir::VAEndOp op, OpAdaptor adaptor,
4374 mlir::ConversionPatternRewriter &rewriter)
const {
4375 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4376 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4377 adaptor.getArgList());
4378 rewriter.replaceOpWithNewOp<mlir::LLVM::VaEndOp>(op, vaList);
4379 return mlir::success();
4382mlir::LogicalResult CIRToLLVMVACopyOpLowering::matchAndRewrite(
4383 cir::VACopyOp op, OpAdaptor adaptor,
4384 mlir::ConversionPatternRewriter &rewriter)
const {
4385 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4386 auto dstList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4387 adaptor.getDstList());
4388 auto srcList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4389 adaptor.getSrcList());
4390 rewriter.replaceOpWithNewOp<mlir::LLVM::VaCopyOp>(op, dstList, srcList);
4391 return mlir::success();
4394mlir::LogicalResult CIRToLLVMVAArgOpLowering::matchAndRewrite(
4395 cir::VAArgOp op, OpAdaptor adaptor,
4396 mlir::ConversionPatternRewriter &rewriter)
const {
4398 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4399 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4400 adaptor.getArgList());
4402 mlir::Type llvmType =
4403 getTypeConverter()->convertType(op->getResultTypes().front());
4405 return mlir::failure();
4407 rewriter.replaceOpWithNewOp<mlir::LLVM::VaArgOp>(op, llvmType, vaList);
4408 return mlir::success();
4411mlir::LogicalResult CIRToLLVMLabelOpLowering::matchAndRewrite(
4412 cir::LabelOp op, OpAdaptor adaptor,
4413 mlir::ConversionPatternRewriter &rewriter)
const {
4414 mlir::MLIRContext *ctx = rewriter.getContext();
4415 mlir::Block *block = op->getBlock();
4418 if (block->isEntryBlock()) {
4419 mlir::Block *newBlock =
4420 rewriter.splitBlock(op->getBlock(), mlir::Block::iterator(op));
4421 rewriter.setInsertionPointToEnd(block);
4422 mlir::LLVM::BrOp::create(rewriter, op.getLoc(), newBlock);
4425 mlir::LLVM::BlockTagAttr::get(ctx, blockInfoAddr.getTagIndex());
4426 rewriter.setInsertionPoint(op);
4429 mlir::LLVM::BlockTagOp::create(rewriter, op->getLoc(), tagAttr);
4430 mlir::LLVM::LLVMFuncOp func = op->getParentOfType<mlir::LLVM::LLVMFuncOp>();
4431 auto blockInfoAttr =
4432 cir::BlockAddrInfoAttr::get(ctx, func.getSymName(), op.getLabel());
4433 blockInfoAddr.mapBlockTag(blockInfoAttr, blockTagOp);
4434 rewriter.eraseOp(op);
4436 return mlir::success();
4439mlir::LogicalResult CIRToLLVMBlockAddressOpLowering::matchAndRewrite(
4440 cir::BlockAddressOp op, OpAdaptor adaptor,
4441 mlir::ConversionPatternRewriter &rewriter)
const {
4442 mlir::MLIRContext *ctx = rewriter.getContext();
4444 mlir::LLVM::BlockTagOp matchLabel =
4445 blockInfoAddr.lookupBlockTag(op.getBlockAddrInfoAttr());
4446 mlir::LLVM::BlockTagAttr tagAttr;
4453 tagAttr = matchLabel.getTag();
4455 auto blkAddr = mlir::LLVM::BlockAddressAttr::get(
4456 rewriter.getContext(), op.getBlockAddrInfoAttr().getFunc(), tagAttr);
4457 rewriter.setInsertionPoint(op);
4458 auto newOp = mlir::LLVM::BlockAddressOp::create(
4459 rewriter, op.getLoc(), mlir::LLVM::LLVMPointerType::get(ctx), blkAddr);
4461 blockInfoAddr.addUnresolvedBlockAddress(newOp, op.getBlockAddrInfoAttr());
4462 rewriter.replaceOp(op, newOp);
4463 return mlir::success();
4466mlir::LogicalResult CIRToLLVMIndirectBrOpLowering::matchAndRewrite(
4467 cir::IndirectBrOp op, OpAdaptor adaptor,
4468 mlir::ConversionPatternRewriter &rewriter)
const {
4470 llvm::SmallVector<mlir::Block *, 8> successors;
4471 llvm::SmallVector<mlir::ValueRange, 8> succOperands;
4472 bool poison = op.getPoison();
4473 for (mlir::Block *succ : op->getSuccessors())
4474 successors.push_back(succ);
4476 for (mlir::ValueRange operand : op.getSuccOperands()) {
4477 succOperands.push_back(operand);
4480 auto llvmPtrType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4481 mlir::Value targetAddr;
4483 targetAddr = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(),
4484 llvmPtrType, adaptor.getAddr());
4487 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), llvmPtrType);
4490 op->getBlock()->eraseArgument(0);
4493 auto newOp = mlir::LLVM::IndirectBrOp::create(
4494 rewriter, op.getLoc(), targetAddr, succOperands, successors);
4495 rewriter.replaceOp(op, newOp);
4496 return mlir::success();
4499mlir::LogicalResult CIRToLLVMAwaitOpLowering::matchAndRewrite(
4500 cir::AwaitOp op, OpAdaptor adaptor,
4501 mlir::ConversionPatternRewriter &rewriter)
const {
4502 return mlir::failure();
4505mlir::LogicalResult CIRToLLVMCpuIdOpLowering::matchAndRewrite(
4506 cir::CpuIdOp op, OpAdaptor adaptor,
4507 mlir::ConversionPatternRewriter &rewriter)
const {
4508 mlir::Type i32Ty = rewriter.getI32Type();
4509 mlir::Type i64Ty = rewriter.getI64Type();
4510 mlir::Type i32PtrTy = mlir::LLVM::LLVMPointerType::get(i32Ty.getContext(), 0);
4512 mlir::Type cpuidRetTy = mlir::LLVM::LLVMStructType::getLiteral(
4513 rewriter.getContext(), {i32Ty, i32Ty, i32Ty, i32Ty});
4515 mlir::Value functionId = adaptor.getFunctionId();
4516 mlir::Value subFunctionId = adaptor.getSubFunctionId();
4518 StringRef asmString, constraints;
4519 mlir::ModuleOp moduleOp = op->getParentOfType<mlir::ModuleOp>();
4520 llvm::Triple triple(
4521 mlir::cast<mlir::StringAttr>(
4522 moduleOp->getAttr(cir::CIRDialect::getTripleAttrName()))
4524 if (triple.getArch() == llvm::Triple::x86) {
4525 asmString =
"cpuid";
4526 constraints =
"={ax},={bx},={cx},={dx},{ax},{cx}";
4529 asmString =
"xchgq %rbx, ${1:q}\n"
4531 "xchgq %rbx, ${1:q}";
4532 constraints =
"={ax},=r,={cx},={dx},0,2";
4535 mlir::Value inlineAsm =
4536 mlir::LLVM::InlineAsmOp::create(
4537 rewriter, op.getLoc(), cpuidRetTy, {functionId, subFunctionId},
4538 rewriter.getStringAttr(asmString),
4539 rewriter.getStringAttr(constraints),
4542 mlir::LLVM::TailCallKindAttr{},
4543 mlir::LLVM::AsmDialectAttr{},
4547 mlir::Value basePtr = adaptor.getCpuInfo();
4549 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
4550 unsigned alignment = layout.getTypeABIAlignment(i32Ty);
4551 for (
unsigned i = 0; i < 4; i++) {
4552 mlir::Value extracted =
4553 mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(), inlineAsm, i)
4555 mlir::Value index = mlir::LLVM::ConstantOp::create(
4556 rewriter, op.getLoc(), i64Ty, rewriter.getI64IntegerAttr(i));
4557 llvm::SmallVector<mlir::Value, 1> gepIndices = {index};
4558 mlir::Value storePtr = mlir::LLVM::GEPOp::create(
4559 rewriter, op.getLoc(), i32PtrTy, i32Ty, basePtr,
4560 gepIndices, mlir::LLVM::GEPNoWrapFlags::none)
4562 mlir::LLVM::StoreOp::create(rewriter, op.getLoc(), extracted, storePtr,
4566 rewriter.eraseOp(op);
4567 return mlir::success();
4570mlir::LogicalResult CIRToLLVMMemChrOpLowering::matchAndRewrite(
4571 cir::MemChrOp op, OpAdaptor adaptor,
4572 mlir::ConversionPatternRewriter &rewriter)
const {
4573 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4574 mlir::Type srcTy = getTypeConverter()->convertType(op.getSrc().getType());
4575 mlir::Type patternTy =
4576 getTypeConverter()->convertType(op.getPattern().getType());
4577 mlir::Type lenTy = getTypeConverter()->convertType(op.getLen().getType());
4579 mlir::LLVM::LLVMFunctionType::get(llvmPtrTy, {srcTy, patternTy, lenTy},
4581 llvm::StringRef fnName =
"memchr";
4583 rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(
4584 op, mlir::TypeRange{llvmPtrTy}, fnName,
4585 mlir::ValueRange{adaptor.getSrc(), adaptor.getPattern(),
4587 return mlir::success();
4591 return std::make_unique<ConvertCIRToLLVMPass>();
4599std::unique_ptr<llvm::Module>
4601 llvm::TimeTraceScope scope(
"lower from CIR to LLVM directly");
4603 mlir::MLIRContext *mlirCtx = mlirModule.getContext();
4605 mlir::PassManager pm(mlirCtx);
4608 (void)mlir::applyPassManagerCLOptions(pm);
4610 if (mlir::failed(pm.run(mlirModule))) {
4613 "The pass manager failed to lower CIR to LLVMIR dialect!");
4616 mlir::registerBuiltinDialectTranslation(*mlirCtx);
4617 mlir::registerLLVMDialectTranslation(*mlirCtx);
4620 llvm::TimeTraceScope translateScope(
"translateModuleToLLVMIR");
4622 StringRef moduleName = mlirModule.getName().value_or(
"CIRToLLVMModule");
4623 std::unique_ptr<llvm::Module> llvmModule =
4624 mlir::translateModuleToLLVMIR(mlirModule, llvmCtx, moduleName);
4628 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 void lowerCallAttributes(cir::CIRCallOpInterface op, SmallVectorImpl< mlir::NamedAttribute > &result)
static uint64_t getTypeSize(mlir::Type type, mlir::Operation &op)
void populateCIRToLLVMPasses(mlir::OpPassManager &pm)
Adds passes that fully lower CIR to the LLVMIR dialect.
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 resolveBlockAddressOp(LLVMBlockAddressInfo &blockInfoAddr)
void processCIRAttrs(mlir::ModuleOp module)
mlir::LLVM::BlockTagOp lookupBlockTag(cir::BlockAddrInfoAttr info) const
void clearUnresolvedMap()
llvm::DenseMap< mlir::LLVM::BlockAddressOp, cir::BlockAddrInfoAttr > & getUnresolvedBlockAddress()