18#include "mlir/Conversion/LLVMCommon/TypeConverter.h"
19#include "mlir/Dialect/DLTI/DLTI.h"
20#include "mlir/Dialect/Func/IR/FuncOps.h"
21#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
22#include "mlir/Dialect/LLVMIR/LLVMTypes.h"
23#include "mlir/IR/BuiltinAttributes.h"
24#include "mlir/IR/BuiltinDialect.h"
25#include "mlir/IR/BuiltinOps.h"
26#include "mlir/IR/Types.h"
27#include "mlir/Pass/Pass.h"
28#include "mlir/Pass/PassManager.h"
29#include "mlir/Target/LLVMIR/Dialect/Builtin/BuiltinToLLVMIRTranslation.h"
30#include "mlir/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.h"
31#include "mlir/Target/LLVMIR/Export.h"
32#include "mlir/Transforms/DialectConversion.h"
39#include "llvm/ADT/TypeSwitch.h"
40#include "llvm/IR/Module.h"
41#include "llvm/Support/ErrorHandling.h"
42#include "llvm/Support/TimeProfiler.h"
57mlir::Type elementTypeIfVector(mlir::Type type) {
58 return llvm::TypeSwitch<mlir::Type, mlir::Type>(type)
59 .Case<cir::VectorType, mlir::VectorType>(
60 [](
auto p) {
return p.getElementType(); })
61 .
Default([](mlir::Type p) {
return p; });
69 mlir::DataLayout
const &dataLayout,
73 if (isa<cir::BoolType>(type)) {
74 return mlir::IntegerType::get(type.getContext(),
75 dataLayout.getTypeSizeInBits(type));
78 return converter.convertType(type);
82 mlir::IntegerType dstTy,
83 bool isSigned =
false) {
84 mlir::Type srcTy = src.getType();
85 assert(mlir::isa<mlir::IntegerType>(srcTy));
87 unsigned srcWidth = mlir::cast<mlir::IntegerType>(srcTy).getWidth();
88 unsigned dstWidth = mlir::cast<mlir::IntegerType>(dstTy).getWidth();
89 mlir::Location loc = src.getLoc();
91 if (dstWidth > srcWidth && isSigned)
92 return bld.create<mlir::LLVM::SExtOp>(loc, dstTy, src);
93 if (dstWidth > srcWidth)
94 return bld.create<mlir::LLVM::ZExtOp>(loc, dstTy, src);
95 if (dstWidth < srcWidth)
96 return bld.create<mlir::LLVM::TruncOp>(loc, dstTy, src);
97 return bld.create<mlir::LLVM::BitcastOp>(loc, dstTy, src);
100static mlir::LLVM::Visibility
102 switch (visibilityKind) {
103 case cir::VisibilityKind::Default:
104 return ::mlir::LLVM::Visibility::Default;
105 case cir::VisibilityKind::Hidden:
106 return ::mlir::LLVM::Visibility::Hidden;
107 case cir::VisibilityKind::Protected:
108 return ::mlir::LLVM::Visibility::Protected;
116 mlir::DataLayout
const &dataLayout,
117 cir::LoadOp op, mlir::Value value) {
120 if (
auto boolTy = mlir::dyn_cast<cir::BoolType>(op.getType())) {
122 assert(value.getType().isInteger(dataLayout.getTypeSizeInBits(boolTy)));
132static mlir::Value
emitToMemory(mlir::ConversionPatternRewriter &rewriter,
133 mlir::DataLayout
const &dataLayout,
134 mlir::Type origType, mlir::Value value) {
137 if (
auto boolTy = mlir::dyn_cast<cir::BoolType>(origType)) {
139 mlir::IntegerType memType =
140 rewriter.getIntegerType(dataLayout.getTypeSizeInBits(boolTy));
148 using CIR = cir::GlobalLinkageKind;
149 using LLVM = mlir::LLVM::Linkage;
152 case CIR::AvailableExternallyLinkage:
153 return LLVM::AvailableExternally;
154 case CIR::CommonLinkage:
156 case CIR::ExternalLinkage:
157 return LLVM::External;
158 case CIR::ExternalWeakLinkage:
159 return LLVM::ExternWeak;
160 case CIR::InternalLinkage:
161 return LLVM::Internal;
162 case CIR::LinkOnceAnyLinkage:
163 return LLVM::Linkonce;
164 case CIR::LinkOnceODRLinkage:
165 return LLVM::LinkonceODR;
166 case CIR::PrivateLinkage:
167 return LLVM::Private;
168 case CIR::WeakAnyLinkage:
170 case CIR::WeakODRLinkage:
171 return LLVM::WeakODR;
173 llvm_unreachable(
"Unknown CIR linkage type");
177 mlir::Value llvmSrc, mlir::Type llvmDstIntTy,
179 uint64_t cirDstIntWidth) {
180 if (cirSrcWidth == cirDstIntWidth)
183 auto loc = llvmSrc.getLoc();
184 if (cirSrcWidth < cirDstIntWidth) {
186 return rewriter.create<mlir::LLVM::ZExtOp>(loc, llvmDstIntTy, llvmSrc);
187 return rewriter.create<mlir::LLVM::SExtOp>(loc, llvmDstIntTy, llvmSrc);
191 return rewriter.create<mlir::LLVM::TruncOp>(loc, llvmDstIntTy, llvmSrc);
197 mlir::ConversionPatternRewriter &rewriter,
198 const mlir::TypeConverter *converter)
199 : parentOp(parentOp), rewriter(rewriter), converter(converter) {}
201 mlir::Value
visit(mlir::Attribute attr) {
202 return llvm::TypeSwitch<mlir::Attribute, mlir::Value>(attr)
203 .Case<cir::IntAttr, cir::FPAttr, cir::ConstComplexAttr,
204 cir::ConstArrayAttr, cir::ConstRecordAttr, cir::ConstVectorAttr,
205 cir::ConstPtrAttr, cir::GlobalViewAttr, cir::VTableAttr,
206 cir::ZeroAttr>([&](
auto attrT) {
return visitCirAttr(attrT); })
207 .Default([&](
auto attrT) {
return mlir::Value(); });
212 mlir::Value
visitCirAttr(cir::ConstComplexAttr complexAttr);
222 mlir::Operation *parentOp;
223 mlir::ConversionPatternRewriter &rewriter;
224 const mlir::TypeConverter *converter;
229 const mlir::Attribute attr,
230 mlir::ConversionPatternRewriter &rewriter,
231 const mlir::TypeConverter *converter) {
233 mlir::Value value = valueConverter.
visit(attr);
235 llvm_unreachable(
"unhandled attribute type");
240 cir::SideEffect sideEffect,
241 mlir::LLVM::MemoryEffectsAttr &memoryEffect,
242 bool &noUnwind,
bool &willReturn) {
243 using mlir::LLVM::ModRefInfo;
245 switch (sideEffect) {
246 case cir::SideEffect::All:
248 noUnwind = isNothrow;
252 case cir::SideEffect::Pure:
253 memoryEffect = mlir::LLVM::MemoryEffectsAttr::get(
254 callOp->getContext(), ModRefInfo::Ref,
261 case cir::SideEffect::Const:
262 memoryEffect = mlir::LLVM::MemoryEffectsAttr::get(
263 callOp->getContext(), ModRefInfo::NoModRef,
264 ModRefInfo::NoModRef,
265 ModRefInfo::NoModRef);
272static mlir::LLVM::CallIntrinsicOp
274 mlir::Location loc,
const llvm::Twine &intrinsicName,
275 mlir::Type resultTy, mlir::ValueRange operands) {
276 auto intrinsicNameAttr =
277 mlir::StringAttr::get(rewriter.getContext(), intrinsicName);
278 return mlir::LLVM::CallIntrinsicOp::create(rewriter, loc, resultTy,
279 intrinsicNameAttr, operands);
283 mlir::ConversionPatternRewriter &rewriter, mlir::Operation *op,
284 const llvm::Twine &intrinsicName, mlir::Type resultTy,
285 mlir::ValueRange operands) {
287 rewriter, op->getLoc(), intrinsicName, resultTy, operands);
288 rewriter.replaceOp(op, callIntrinOp.getOperation());
294 mlir::Location loc = parentOp->getLoc();
295 return rewriter.create<mlir::LLVM::ConstantOp>(
296 loc, converter->convertType(intAttr.getType()), intAttr.getValue());
301 mlir::Location loc = parentOp->getLoc();
302 return rewriter.create<mlir::LLVM::ConstantOp>(
303 loc, converter->convertType(fltAttr.getType()), fltAttr.getValue());
308 auto complexType = mlir::cast<cir::ComplexType>(complexAttr.getType());
309 mlir::Type complexElemTy = complexType.getElementType();
310 mlir::Type complexElemLLVMTy = converter->convertType(complexElemTy);
312 mlir::Attribute components[2];
313 if (
const auto intType = mlir::dyn_cast<cir::IntType>(complexElemTy)) {
314 components[0] = rewriter.getIntegerAttr(
316 mlir::cast<cir::IntAttr>(complexAttr.getReal()).getValue());
317 components[1] = rewriter.getIntegerAttr(
319 mlir::cast<cir::IntAttr>(complexAttr.getImag()).getValue());
321 components[0] = rewriter.getFloatAttr(
323 mlir::cast<cir::FPAttr>(complexAttr.getReal()).getValue());
324 components[1] = rewriter.getFloatAttr(
326 mlir::cast<cir::FPAttr>(complexAttr.getImag()).getValue());
329 mlir::Location loc = parentOp->getLoc();
330 return rewriter.create<mlir::LLVM::ConstantOp>(
331 loc, converter->convertType(complexAttr.getType()),
332 rewriter.getArrayAttr(components));
337 mlir::Location loc = parentOp->getLoc();
338 if (ptrAttr.isNullValue()) {
339 return rewriter.create<mlir::LLVM::ZeroOp>(
340 loc, converter->convertType(ptrAttr.getType()));
342 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
343 mlir::Value ptrVal = rewriter.create<mlir::LLVM::ConstantOp>(
344 loc, rewriter.getIntegerType(layout.getTypeSizeInBits(ptrAttr.getType())),
345 ptrAttr.getValue().getInt());
346 return rewriter.create<mlir::LLVM::IntToPtrOp>(
347 loc, converter->convertType(ptrAttr.getType()), ptrVal);
352 mlir::Type llvmTy = converter->convertType(attr.getType());
353 mlir::Location loc = parentOp->getLoc();
356 if (attr.hasTrailingZeros()) {
357 mlir::Type arrayTy = attr.getType();
358 result = rewriter.create<mlir::LLVM::ZeroOp>(
359 loc, converter->convertType(arrayTy));
361 result = rewriter.create<mlir::LLVM::UndefOp>(loc, llvmTy);
365 if (
auto arrayAttr = mlir::dyn_cast<mlir::ArrayAttr>(attr.getElts())) {
366 for (
auto [idx, elt] : llvm::enumerate(arrayAttr)) {
367 mlir::DataLayout dataLayout(parentOp->getParentOfType<mlir::ModuleOp>());
368 mlir::Value init =
visit(elt);
370 rewriter.create<mlir::LLVM::InsertValueOp>(loc, result, init, idx);
372 }
else if (
auto strAttr = mlir::dyn_cast<mlir::StringAttr>(attr.getElts())) {
375 auto arrayTy = mlir::dyn_cast<cir::ArrayType>(strAttr.getType());
376 assert(arrayTy &&
"String attribute must have an array type");
377 mlir::Type eltTy = arrayTy.getElementType();
378 for (
auto [idx, elt] : llvm::enumerate(strAttr)) {
379 auto init = rewriter.create<mlir::LLVM::ConstantOp>(
380 loc, converter->convertType(eltTy), elt);
382 rewriter.create<mlir::LLVM::InsertValueOp>(loc, result, init, idx);
385 llvm_unreachable(
"unexpected ConstArrayAttr elements");
393 const mlir::Type llvmTy = converter->convertType(constRecord.getType());
394 const mlir::Location loc = parentOp->getLoc();
395 mlir::Value result = rewriter.create<mlir::LLVM::UndefOp>(loc, llvmTy);
398 for (
auto [idx, elt] : llvm::enumerate(constRecord.getMembers())) {
399 mlir::Value init =
visit(elt);
400 result = rewriter.create<mlir::LLVM::InsertValueOp>(loc, result, init, idx);
408 const mlir::Type llvmTy = converter->convertType(attr.getType());
409 const mlir::Location loc = parentOp->getLoc();
412 for (
const mlir::Attribute elementAttr : attr.getElts()) {
413 mlir::Attribute mlirAttr;
414 if (
auto intAttr = mlir::dyn_cast<cir::IntAttr>(elementAttr)) {
415 mlirAttr = rewriter.getIntegerAttr(
416 converter->convertType(intAttr.getType()), intAttr.getValue());
417 }
else if (
auto floatAttr = mlir::dyn_cast<cir::FPAttr>(elementAttr)) {
418 mlirAttr = rewriter.getFloatAttr(
419 converter->convertType(floatAttr.getType()), floatAttr.getValue());
422 "vector constant with an element that is neither an int nor a float");
424 mlirValues.push_back(mlirAttr);
427 return rewriter.create<mlir::LLVM::ConstantOp>(
429 mlir::DenseElementsAttr::get(mlir::cast<mlir::ShapedType>(llvmTy),
435 auto moduleOp = parentOp->getParentOfType<mlir::ModuleOp>();
436 mlir::DataLayout dataLayout(moduleOp);
437 mlir::Type sourceType;
439 llvm::StringRef symName;
440 mlir::Operation *sourceSymbol =
441 mlir::SymbolTable::lookupSymbolIn(moduleOp, globalAttr.getSymbol());
442 if (
auto llvmSymbol = dyn_cast<mlir::LLVM::GlobalOp>(sourceSymbol)) {
443 sourceType = llvmSymbol.getType();
444 symName = llvmSymbol.getSymName();
445 }
else if (
auto cirSymbol = dyn_cast<cir::GlobalOp>(sourceSymbol)) {
448 symName = cirSymbol.getSymName();
449 }
else if (
auto llvmFun = dyn_cast<mlir::LLVM::LLVMFuncOp>(sourceSymbol)) {
450 sourceType = llvmFun.getFunctionType();
451 symName = llvmFun.getSymName();
452 }
else if (
auto fun = dyn_cast<cir::FuncOp>(sourceSymbol)) {
453 sourceType = converter->convertType(fun.getFunctionType());
454 symName = fun.getSymName();
455 }
else if (
auto alias = dyn_cast<mlir::LLVM::AliasOp>(sourceSymbol)) {
456 sourceType = alias.getType();
457 symName = alias.getSymName();
459 llvm_unreachable(
"Unexpected GlobalOp type");
462 mlir::Location loc = parentOp->getLoc();
463 mlir::Value addrOp = rewriter.create<mlir::LLVM::AddressOfOp>(
464 loc, mlir::LLVM::LLVMPointerType::get(rewriter.getContext()), symName);
466 if (globalAttr.getIndices()) {
469 if (mlir::isa<mlir::LLVM::LLVMArrayType, mlir::LLVM::LLVMStructType>(
471 indices.push_back(0);
473 for (mlir::Attribute idx : globalAttr.getIndices()) {
474 auto intAttr = mlir::cast<mlir::IntegerAttr>(idx);
475 indices.push_back(intAttr.getValue().getSExtValue());
477 mlir::Type resTy = addrOp.getType();
478 mlir::Type eltTy = converter->convertType(sourceType);
479 addrOp = rewriter.create<mlir::LLVM::GEPOp>(
480 loc, resTy, eltTy, addrOp, indices, mlir::LLVM::GEPNoWrapFlags::none);
489 if (
auto ptrTy = mlir::dyn_cast<cir::PointerType>(globalAttr.getType())) {
490 mlir::Type llvmEltTy =
493 if (llvmEltTy == sourceType)
496 mlir::Type llvmDstTy = converter->convertType(globalAttr.getType());
497 return rewriter.create<mlir::LLVM::BitcastOp>(parentOp->getLoc(), llvmDstTy,
501 llvm_unreachable(
"Expecting pointer or integer type for GlobalViewAttr");
506 mlir::Type llvmTy = converter->convertType(vtableArr.getType());
507 mlir::Location loc = parentOp->getLoc();
508 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
510 for (
auto [idx, elt] : llvm::enumerate(vtableArr.getData())) {
511 mlir::Value init =
visit(elt);
513 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
521 mlir::Location loc = parentOp->getLoc();
522 return rewriter.create<mlir::LLVM::ZeroOp>(
523 loc, converter->convertType(attr.getType()));
531 mlir::ConversionPatternRewriter &rewriter)
532 : llvmType(type), rewriter(rewriter) {}
534 mlir::Attribute
visit(mlir::Attribute attr) {
535 return llvm::TypeSwitch<mlir::Attribute, mlir::Attribute>(attr)
536 .Case<cir::IntAttr, cir::FPAttr, cir::BoolAttr>(
538 .Default([&](
auto attrT) {
return mlir::Attribute(); });
542 return rewriter.getIntegerAttr(llvmType, attr.getValue());
546 return rewriter.getFloatAttr(llvmType, attr.getValue());
550 return rewriter.getBoolAttr(attr.getValue());
555 mlir::ConversionPatternRewriter &rewriter;
563 :
public mlir::PassWrapper<ConvertCIRToLLVMPass,
564 mlir::OperationPass<mlir::ModuleOp>> {
566 registry.insert<mlir::BuiltinDialect, mlir::DLTIDialect,
567 mlir::LLVM::LLVMDialect, mlir::func::FuncDialect>();
574 return "Convert the prepared CIR dialect module to LLVM dialect";
577 StringRef
getArgument()
const override {
return "cir-flat-to-llvm"; }
581 cir::AssumeOp op, OpAdaptor adaptor,
582 mlir::ConversionPatternRewriter &rewriter)
const {
583 auto cond = adaptor.getPredicate();
584 rewriter.replaceOpWithNewOp<mlir::LLVM::AssumeOp>(op, cond);
585 return mlir::success();
589 cir::AssumeAlignedOp op, OpAdaptor adaptor,
590 mlir::ConversionPatternRewriter &rewriter)
const {
593 auto alignment = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
594 adaptor.getAlignmentAttr());
595 opBundleArgs.push_back(alignment);
597 if (mlir::Value offset = adaptor.getOffset())
598 opBundleArgs.push_back(offset);
600 auto cond = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
601 rewriter.getI1Type(), 1);
602 mlir::LLVM::AssumeOp::create(rewriter, op.getLoc(), cond,
"align",
607 rewriter.replaceOp(op, adaptor.getPointer());
608 return mlir::success();
612 cir::AssumeSepStorageOp op, OpAdaptor adaptor,
613 mlir::ConversionPatternRewriter &rewriter)
const {
614 auto cond = rewriter.create<mlir::LLVM::ConstantOp>(op.getLoc(),
615 rewriter.getI1Type(), 1);
616 rewriter.replaceOpWithNewOp<mlir::LLVM::AssumeOp>(
617 op, cond, mlir::LLVM::AssumeSeparateStorageTag{}, adaptor.getPtr1(),
619 return mlir::success();
623 cir::BitClrsbOp op, OpAdaptor adaptor,
624 mlir::ConversionPatternRewriter &rewriter)
const {
625 auto zero = rewriter.create<mlir::LLVM::ConstantOp>(
626 op.getLoc(), adaptor.getInput().getType(), 0);
627 auto isNeg = rewriter.create<mlir::LLVM::ICmpOp>(
629 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(),
630 mlir::LLVM::ICmpPredicate::slt),
631 adaptor.getInput(), zero);
633 auto negOne = rewriter.create<mlir::LLVM::ConstantOp>(
634 op.getLoc(), adaptor.getInput().getType(), -1);
635 auto flipped = rewriter.create<mlir::LLVM::XOrOp>(op.getLoc(),
636 adaptor.getInput(), negOne);
638 auto select = rewriter.create<mlir::LLVM::SelectOp>(
639 op.getLoc(), isNeg, flipped, adaptor.getInput());
641 auto resTy = getTypeConverter()->convertType(op.getType());
642 auto clz = rewriter.create<mlir::LLVM::CountLeadingZerosOp>(
643 op.getLoc(), resTy,
select,
false);
645 auto one = rewriter.create<mlir::LLVM::ConstantOp>(op.getLoc(), resTy, 1);
646 auto res = rewriter.create<mlir::LLVM::SubOp>(op.getLoc(),
clz, one);
647 rewriter.replaceOp(op, res);
649 return mlir::LogicalResult::success();
653 cir::BitClzOp op, OpAdaptor adaptor,
654 mlir::ConversionPatternRewriter &rewriter)
const {
655 auto resTy = getTypeConverter()->convertType(op.getType());
656 auto llvmOp = rewriter.create<mlir::LLVM::CountLeadingZerosOp>(
657 op.getLoc(), resTy, adaptor.getInput(), op.getPoisonZero());
658 rewriter.replaceOp(op, llvmOp);
659 return mlir::LogicalResult::success();
663 cir::BitCtzOp op, OpAdaptor adaptor,
664 mlir::ConversionPatternRewriter &rewriter)
const {
665 auto resTy = getTypeConverter()->convertType(op.getType());
666 auto llvmOp = rewriter.create<mlir::LLVM::CountTrailingZerosOp>(
667 op.getLoc(), resTy, adaptor.getInput(), op.getPoisonZero());
668 rewriter.replaceOp(op, llvmOp);
669 return mlir::LogicalResult::success();
673 cir::BitFfsOp op, OpAdaptor adaptor,
674 mlir::ConversionPatternRewriter &rewriter)
const {
675 auto resTy = getTypeConverter()->convertType(op.getType());
676 auto ctz = rewriter.create<mlir::LLVM::CountTrailingZerosOp>(
677 op.getLoc(), resTy, adaptor.getInput(),
true);
679 auto one = rewriter.create<mlir::LLVM::ConstantOp>(op.getLoc(), resTy, 1);
680 auto ctzAddOne = rewriter.create<mlir::LLVM::AddOp>(op.getLoc(),
ctz, one);
682 auto zeroInputTy = rewriter.create<mlir::LLVM::ConstantOp>(
683 op.getLoc(), adaptor.getInput().getType(), 0);
684 auto isZero = rewriter.create<mlir::LLVM::ICmpOp>(
686 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(),
687 mlir::LLVM::ICmpPredicate::eq),
688 adaptor.getInput(), zeroInputTy);
690 auto zero = rewriter.create<mlir::LLVM::ConstantOp>(op.getLoc(), resTy, 0);
691 auto res = rewriter.create<mlir::LLVM::SelectOp>(op.getLoc(), isZero, zero,
693 rewriter.replaceOp(op, res);
695 return mlir::LogicalResult::success();
699 cir::BitParityOp op, OpAdaptor adaptor,
700 mlir::ConversionPatternRewriter &rewriter)
const {
701 auto resTy = getTypeConverter()->convertType(op.getType());
702 auto popcnt = rewriter.create<mlir::LLVM::CtPopOp>(op.getLoc(), resTy,
705 auto one = rewriter.create<mlir::LLVM::ConstantOp>(op.getLoc(), resTy, 1);
707 rewriter.create<mlir::LLVM::AndOp>(op.getLoc(), popcnt, one);
708 rewriter.replaceOp(op, popcntMod2);
710 return mlir::LogicalResult::success();
714 cir::BitPopcountOp op, OpAdaptor adaptor,
715 mlir::ConversionPatternRewriter &rewriter)
const {
716 auto resTy = getTypeConverter()->convertType(op.getType());
717 auto llvmOp = rewriter.create<mlir::LLVM::CtPopOp>(op.getLoc(), resTy,
719 rewriter.replaceOp(op, llvmOp);
720 return mlir::LogicalResult::success();
724 cir::BitReverseOp op, OpAdaptor adaptor,
725 mlir::ConversionPatternRewriter &rewriter)
const {
726 rewriter.replaceOpWithNewOp<mlir::LLVM::BitReverseOp>(op, adaptor.getInput());
727 return mlir::success();
731 cir::BrCondOp brOp, OpAdaptor adaptor,
732 mlir::ConversionPatternRewriter &rewriter)
const {
737 mlir::Value i1Condition = adaptor.getCond();
739 rewriter.replaceOpWithNewOp<mlir::LLVM::CondBrOp>(
740 brOp, i1Condition, brOp.getDestTrue(), adaptor.getDestOperandsTrue(),
741 brOp.getDestFalse(), adaptor.getDestOperandsFalse());
743 return mlir::success();
747 cir::ByteSwapOp op, OpAdaptor adaptor,
748 mlir::ConversionPatternRewriter &rewriter)
const {
749 rewriter.replaceOpWithNewOp<mlir::LLVM::ByteSwapOp>(op, adaptor.getInput());
750 return mlir::LogicalResult::success();
753mlir::Type CIRToLLVMCastOpLowering::convertTy(mlir::Type ty)
const {
754 return getTypeConverter()->convertType(ty);
758 cir::CastOp castOp, OpAdaptor adaptor,
759 mlir::ConversionPatternRewriter &rewriter)
const {
764 switch (castOp.getKind()) {
765 case cir::CastKind::array_to_ptrdecay: {
766 const auto ptrTy = mlir::cast<cir::PointerType>(castOp.getType());
767 mlir::Value sourceValue = adaptor.getSrc();
768 mlir::Type targetType = convertTy(ptrTy);
772 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
773 castOp, targetType, elementTy, sourceValue, offset);
776 case cir::CastKind::int_to_bool: {
777 mlir::Value llvmSrcVal = adaptor.getSrc();
778 mlir::Value zeroInt = rewriter.create<mlir::LLVM::ConstantOp>(
779 castOp.getLoc(), llvmSrcVal.getType(), 0);
780 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
781 castOp, mlir::LLVM::ICmpPredicate::ne, llvmSrcVal, zeroInt);
784 case cir::CastKind::integral: {
785 mlir::Type srcType = castOp.getSrc().getType();
786 mlir::Type dstType = castOp.getType();
787 mlir::Value llvmSrcVal = adaptor.getSrc();
788 mlir::Type llvmDstType = getTypeConverter()->convertType(dstType);
789 cir::IntType srcIntType =
790 mlir::cast<cir::IntType>(elementTypeIfVector(srcType));
791 cir::IntType dstIntType =
792 mlir::cast<cir::IntType>(elementTypeIfVector(dstType));
793 rewriter.replaceOp(castOp,
getLLVMIntCast(rewriter, llvmSrcVal, llvmDstType,
794 srcIntType.isUnsigned(),
795 srcIntType.getWidth(),
796 dstIntType.getWidth()));
799 case cir::CastKind::floating: {
800 mlir::Value llvmSrcVal = adaptor.getSrc();
801 mlir::Type llvmDstTy = getTypeConverter()->convertType(castOp.getType());
803 mlir::Type srcTy = elementTypeIfVector(castOp.getSrc().getType());
804 mlir::Type dstTy = elementTypeIfVector(castOp.getType());
806 if (!mlir::isa<cir::FPTypeInterface>(dstTy) ||
807 !mlir::isa<cir::FPTypeInterface>(srcTy))
808 return castOp.emitError() <<
"NYI cast from " << srcTy <<
" to " << dstTy;
810 auto getFloatWidth = [](mlir::Type ty) ->
unsigned {
811 return mlir::cast<cir::FPTypeInterface>(ty).getWidth();
814 if (getFloatWidth(srcTy) > getFloatWidth(dstTy))
815 rewriter.replaceOpWithNewOp<mlir::LLVM::FPTruncOp>(castOp, llvmDstTy,
818 rewriter.replaceOpWithNewOp<mlir::LLVM::FPExtOp>(castOp, llvmDstTy,
820 return mlir::success();
822 case cir::CastKind::int_to_ptr: {
823 auto dstTy = mlir::cast<cir::PointerType>(castOp.getType());
824 mlir::Value llvmSrcVal = adaptor.getSrc();
825 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
826 rewriter.replaceOpWithNewOp<mlir::LLVM::IntToPtrOp>(castOp, llvmDstTy,
828 return mlir::success();
830 case cir::CastKind::ptr_to_int: {
831 auto dstTy = mlir::cast<cir::IntType>(castOp.getType());
832 mlir::Value llvmSrcVal = adaptor.getSrc();
833 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
834 rewriter.replaceOpWithNewOp<mlir::LLVM::PtrToIntOp>(castOp, llvmDstTy,
836 return mlir::success();
838 case cir::CastKind::float_to_bool: {
839 mlir::Value llvmSrcVal = adaptor.getSrc();
840 auto kind = mlir::LLVM::FCmpPredicate::une;
843 auto zeroFloat = rewriter.create<mlir::LLVM::ConstantOp>(
844 castOp.getLoc(), llvmSrcVal.getType(),
845 mlir::FloatAttr::get(llvmSrcVal.getType(), 0.0));
848 rewriter.replaceOpWithNewOp<mlir::LLVM::FCmpOp>(castOp, kind, llvmSrcVal,
851 return mlir::success();
853 case cir::CastKind::bool_to_int: {
854 auto dstTy = mlir::cast<cir::IntType>(castOp.getType());
855 mlir::Value llvmSrcVal = adaptor.getSrc();
856 auto llvmSrcTy = mlir::cast<mlir::IntegerType>(llvmSrcVal.getType());
858 mlir::cast<mlir::IntegerType>(getTypeConverter()->convertType(dstTy));
859 if (llvmSrcTy.getWidth() == llvmDstTy.getWidth())
860 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(castOp, llvmDstTy,
863 rewriter.replaceOpWithNewOp<mlir::LLVM::ZExtOp>(castOp, llvmDstTy,
865 return mlir::success();
867 case cir::CastKind::bool_to_float: {
868 mlir::Type dstTy = castOp.getType();
869 mlir::Value llvmSrcVal = adaptor.getSrc();
870 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
871 rewriter.replaceOpWithNewOp<mlir::LLVM::UIToFPOp>(castOp, llvmDstTy,
873 return mlir::success();
875 case cir::CastKind::int_to_float: {
876 mlir::Type dstTy = castOp.getType();
877 mlir::Value llvmSrcVal = adaptor.getSrc();
878 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
879 if (mlir::cast<cir::IntType>(elementTypeIfVector(castOp.getSrc().getType()))
881 rewriter.replaceOpWithNewOp<mlir::LLVM::SIToFPOp>(castOp, llvmDstTy,
884 rewriter.replaceOpWithNewOp<mlir::LLVM::UIToFPOp>(castOp, llvmDstTy,
886 return mlir::success();
888 case cir::CastKind::float_to_int: {
889 mlir::Type dstTy = castOp.getType();
890 mlir::Value llvmSrcVal = adaptor.getSrc();
891 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
892 if (mlir::cast<cir::IntType>(elementTypeIfVector(castOp.getType()))
894 rewriter.replaceOpWithNewOp<mlir::LLVM::FPToSIOp>(castOp, llvmDstTy,
897 rewriter.replaceOpWithNewOp<mlir::LLVM::FPToUIOp>(castOp, llvmDstTy,
899 return mlir::success();
901 case cir::CastKind::bitcast: {
902 mlir::Type dstTy = castOp.getType();
903 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
908 mlir::Value llvmSrcVal = adaptor.getSrc();
909 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(castOp, llvmDstTy,
911 return mlir::success();
913 case cir::CastKind::ptr_to_bool: {
914 mlir::Value llvmSrcVal = adaptor.getSrc();
915 mlir::Value zeroPtr = rewriter.create<mlir::LLVM::ZeroOp>(
916 castOp.getLoc(), llvmSrcVal.getType());
917 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
918 castOp, mlir::LLVM::ICmpPredicate::ne, llvmSrcVal, zeroPtr);
921 case cir::CastKind::address_space: {
922 mlir::Type dstTy = castOp.getType();
923 mlir::Value llvmSrcVal = adaptor.getSrc();
924 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
925 rewriter.replaceOpWithNewOp<mlir::LLVM::AddrSpaceCastOp>(castOp, llvmDstTy,
929 case cir::CastKind::member_ptr_to_bool:
934 return castOp.emitError(
"Unhandled cast kind: ")
935 << castOp.getKindAttrName();
939 return mlir::success();
943 cir::PtrStrideOp ptrStrideOp, OpAdaptor adaptor,
944 mlir::ConversionPatternRewriter &rewriter)
const {
946 const mlir::TypeConverter *tc = getTypeConverter();
947 const mlir::Type resultTy = tc->convertType(ptrStrideOp.getType());
949 mlir::Type elementTy =
951 mlir::MLIRContext *ctx = elementTy.getContext();
955 if (mlir::isa<mlir::LLVM::LLVMVoidType>(elementTy) ||
956 mlir::isa<mlir::LLVM::LLVMFunctionType>(elementTy))
957 elementTy = mlir::IntegerType::get(elementTy.getContext(), 8,
958 mlir::IntegerType::Signless);
960 mlir::Value index = adaptor.getStride();
961 const unsigned width =
962 mlir::cast<mlir::IntegerType>(index.getType()).getWidth();
963 const std::optional<std::uint64_t> layoutWidth =
964 dataLayout.getTypeIndexBitwidth(adaptor.getBase().getType());
966 mlir::Operation *indexOp = index.getDefiningOp();
967 if (indexOp && layoutWidth && width != *layoutWidth) {
971 const auto sub = dyn_cast<mlir::LLVM::SubOp>(indexOp);
972 auto unary = ptrStrideOp.getStride().getDefiningOp<cir::UnaryOp>();
974 unary && unary.getKind() == cir::UnaryOpKind::Minus && sub;
976 index = indexOp->getOperand(1);
979 const auto llvmDstType = mlir::IntegerType::get(ctx, *layoutWidth);
981 ptrStrideOp.getStride().getType().isUnsigned(),
982 width, *layoutWidth);
986 index = rewriter.create<mlir::LLVM::SubOp>(
987 index.getLoc(), index.getType(),
988 rewriter.create<mlir::LLVM::ConstantOp>(index.getLoc(),
991 rewriter.eraseOp(sub);
995 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
996 ptrStrideOp, resultTy, elementTy, adaptor.getBase(), index);
997 return mlir::success();
1001 cir::BaseClassAddrOp baseClassOp, OpAdaptor adaptor,
1002 mlir::ConversionPatternRewriter &rewriter)
const {
1003 const mlir::Type resultType =
1004 getTypeConverter()->convertType(baseClassOp.getType());
1005 mlir::Value derivedAddr = adaptor.getDerivedAddr();
1007 adaptor.getOffset().getZExtValue()};
1008 mlir::Type byteType = mlir::IntegerType::get(resultType.getContext(), 8,
1009 mlir::IntegerType::Signless);
1010 if (adaptor.getOffset().getZExtValue() == 0) {
1011 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(
1012 baseClassOp, resultType, adaptor.getDerivedAddr());
1013 return mlir::success();
1016 if (baseClassOp.getAssumeNotNull()) {
1017 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1018 baseClassOp, resultType, byteType, derivedAddr, offset);
1020 auto loc = baseClassOp.getLoc();
1021 mlir::Value isNull = rewriter.create<mlir::LLVM::ICmpOp>(
1022 loc, mlir::LLVM::ICmpPredicate::eq, derivedAddr,
1023 rewriter.create<mlir::LLVM::ZeroOp>(loc, derivedAddr.getType()));
1024 mlir::Value adjusted = rewriter.create<mlir::LLVM::GEPOp>(
1025 loc, resultType, byteType, derivedAddr, offset);
1026 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(baseClassOp, isNull,
1027 derivedAddr, adjusted);
1029 return mlir::success();
1033 cir::AllocaOp op, OpAdaptor adaptor,
1034 mlir::ConversionPatternRewriter &rewriter)
const {
1036 mlir::Value size = rewriter.create<mlir::LLVM::ConstantOp>(
1037 op.getLoc(), typeConverter->convertType(rewriter.getIndexType()), 1);
1038 mlir::Type elementTy =
1040 mlir::Type resultTy =
1046 rewriter.replaceOpWithNewOp<mlir::LLVM::AllocaOp>(
1047 op, resultTy, elementTy, size, op.getAlignmentAttr().getInt());
1049 return mlir::success();
1053 cir::ReturnOp op, OpAdaptor adaptor,
1054 mlir::ConversionPatternRewriter &rewriter)
const {
1055 rewriter.replaceOpWithNewOp<mlir::LLVM::ReturnOp>(op, adaptor.getOperands());
1056 return mlir::LogicalResult::success();
1060 cir::RotateOp op, OpAdaptor adaptor,
1061 mlir::ConversionPatternRewriter &rewriter)
const {
1064 mlir::Value input = adaptor.getInput();
1065 if (op.isRotateLeft())
1066 rewriter.replaceOpWithNewOp<mlir::LLVM::FshlOp>(op, input, input,
1067 adaptor.getAmount());
1069 rewriter.replaceOpWithNewOp<mlir::LLVM::FshrOp>(op, input, input,
1070 adaptor.getAmount());
1071 return mlir::LogicalResult::success();
1074static mlir::LogicalResult
1076 mlir::ConversionPatternRewriter &rewriter,
1077 const mlir::TypeConverter *converter,
1078 mlir::FlatSymbolRefAttr calleeAttr) {
1080 mlir::ValueTypeRange<mlir::ResultRange> cirResults = op->getResultTypes();
1081 auto call = cast<cir::CIRCallOpInterface>(op);
1083 if (converter->convertTypes(cirResults, llvmResults).failed())
1084 return mlir::failure();
1088 mlir::LLVM::MemoryEffectsAttr memoryEffects;
1089 bool noUnwind =
false;
1090 bool willReturn =
false;
1092 memoryEffects, noUnwind, willReturn);
1094 mlir::LLVM::LLVMFunctionType llvmFnTy;
1101 mlir::Operation *callee =
1102 mlir::SymbolTable::lookupNearestSymbolFrom(op, calleeAttr);
1103 if (
auto fn = mlir::dyn_cast<mlir::FunctionOpInterface>(callee)) {
1104 llvmFnTy = converter->convertType<mlir::LLVM::LLVMFunctionType>(
1105 fn.getFunctionType());
1106 assert(llvmFnTy &&
"Failed to convert function type");
1107 }
else if (
auto alias = mlir::cast<mlir::LLVM::AliasOp>(callee)) {
1115 auto symAttr = mlir::cast<mlir::FlatSymbolRefAttr>(calleeAttr);
1117 mlir::LLVM::AddressOfOp::create(
1118 rewriter, op->getLoc(),
1119 mlir::LLVM::LLVMPointerType::get(rewriter.getContext()), symAttr)
1121 adjustedCallOperands.push_back(addrOfAlias);
1124 llvm::append_range(adjustedCallOperands, callOperands);
1125 callOperands = adjustedCallOperands;
1129 llvmFnTy = mlir::cast<mlir::LLVM::LLVMFunctionType>(alias.getType());
1132 return op->emitError(
"Unexpected callee type!");
1135 assert(!op->getOperands().empty() &&
1136 "operands list must no be empty for the indirect call");
1137 auto calleeTy = op->getOperands().front().getType();
1138 auto calleePtrTy = cast<cir::PointerType>(calleeTy);
1139 auto calleeFuncTy = cast<cir::FuncType>(calleePtrTy.getPointee());
1140 llvm::append_range(adjustedCallOperands, callOperands);
1141 llvmFnTy = cast<mlir::LLVM::LLVMFunctionType>(
1142 converter->convertType(calleeFuncTy));
1149 auto newOp = rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(
1150 op, llvmFnTy, calleeAttr, callOperands);
1152 newOp.setMemoryEffectsAttr(memoryEffects);
1153 newOp.setNoUnwind(noUnwind);
1154 newOp.setWillReturn(willReturn);
1156 return mlir::success();
1160 cir::CallOp op, OpAdaptor adaptor,
1161 mlir::ConversionPatternRewriter &rewriter)
const {
1163 getTypeConverter(), op.getCalleeAttr());
1167 cir::ReturnAddrOp op, OpAdaptor adaptor,
1168 mlir::ConversionPatternRewriter &rewriter)
const {
1169 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
1171 llvmPtrTy, adaptor.getOperands());
1172 return mlir::success();
1176 cir::FrameAddrOp op, OpAdaptor adaptor,
1177 mlir::ConversionPatternRewriter &rewriter)
const {
1178 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
1180 adaptor.getOperands());
1181 return mlir::success();
1184static mlir::LLVM::AtomicOrdering
1187 return mlir::LLVM::AtomicOrdering::not_atomic;
1188 switch (*memorder) {
1189 case cir::MemOrder::Relaxed:
1190 return mlir::LLVM::AtomicOrdering::monotonic;
1191 case cir::MemOrder::Consume:
1192 case cir::MemOrder::Acquire:
1193 return mlir::LLVM::AtomicOrdering::acquire;
1194 case cir::MemOrder::Release:
1195 return mlir::LLVM::AtomicOrdering::release;
1196 case cir::MemOrder::AcquireRelease:
1197 return mlir::LLVM::AtomicOrdering::acq_rel;
1198 case cir::MemOrder::SequentiallyConsistent:
1199 return mlir::LLVM::AtomicOrdering::seq_cst;
1201 llvm_unreachable(
"unknown memory order");
1205 cir::LoadOp op, OpAdaptor adaptor,
1206 mlir::ConversionPatternRewriter &rewriter)
const {
1207 const mlir::Type llvmTy =
1209 mlir::LLVM::AtomicOrdering ordering =
getLLVMMemOrder(op.getMemOrder());
1210 std::optional<size_t> opAlign = op.getAlignment();
1211 unsigned alignment =
1212 (
unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmTy));
1218 mlir::LLVM::LoadOp newLoad = mlir::LLVM::LoadOp::create(
1219 rewriter, op->getLoc(), llvmTy, adaptor.getAddr(), alignment,
1220 op.getIsVolatile(),
false,
1221 false,
false, ordering);
1224 mlir::Value result =
1226 rewriter.replaceOp(op, result);
1228 return mlir::LogicalResult::success();
1232 cir::StoreOp op, OpAdaptor adaptor,
1233 mlir::ConversionPatternRewriter &rewriter)
const {
1234 mlir::LLVM::AtomicOrdering memorder =
getLLVMMemOrder(op.getMemOrder());
1235 const mlir::Type llvmTy =
1236 getTypeConverter()->convertType(op.getValue().getType());
1237 std::optional<size_t> opAlign = op.getAlignment();
1238 unsigned alignment =
1239 (
unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmTy));
1245 op.getValue().getType(), adaptor.getValue());
1249 mlir::LLVM::StoreOp storeOp = mlir::LLVM::StoreOp::create(
1250 rewriter, op->getLoc(), value, adaptor.getAddr(), alignment,
1252 false,
false, memorder);
1253 rewriter.replaceOp(op, storeOp);
1255 return mlir::LogicalResult::success();
1259 auto array = mlir::dyn_cast<mlir::ArrayAttr>(attr.getElts());
1260 return attr.hasTrailingZeros() ||
1261 (array && std::count_if(array.begin(), array.end(), [](
auto elt) {
1262 auto ar = dyn_cast<cir::ConstArrayAttr>(elt);
1263 return ar && hasTrailingZeros(ar);
1268 cir::ConstantOp op, OpAdaptor adaptor,
1269 mlir::ConversionPatternRewriter &rewriter)
const {
1270 mlir::Attribute attr = op.getValue();
1272 if (mlir::isa<cir::PoisonAttr>(attr)) {
1273 rewriter.replaceOpWithNewOp<mlir::LLVM::PoisonOp>(
1274 op, getTypeConverter()->convertType(op.getType()));
1275 return mlir::success();
1278 if (mlir::isa<mlir::IntegerType>(op.getType())) {
1283 attr = op.getValue();
1284 }
else if (mlir::isa<cir::BoolType>(op.getType())) {
1285 int value = mlir::cast<cir::BoolAttr>(op.getValue()).getValue();
1286 attr = rewriter.getIntegerAttr(typeConverter->convertType(op.getType()),
1288 }
else if (mlir::isa<cir::IntType>(op.getType())) {
1290 if (
auto ga = mlir::dyn_cast<cir::GlobalViewAttr>(op.getValue())) {
1293 op.emitError() <<
"global view with integer type";
1294 return mlir::failure();
1297 attr = rewriter.getIntegerAttr(
1298 typeConverter->convertType(op.getType()),
1299 mlir::cast<cir::IntAttr>(op.getValue()).getValue());
1300 }
else if (mlir::isa<cir::FPTypeInterface>(op.getType())) {
1301 attr = rewriter.getFloatAttr(
1302 typeConverter->convertType(op.getType()),
1303 mlir::cast<cir::FPAttr>(op.getValue()).getValue());
1304 }
else if (mlir::isa<cir::PointerType>(op.getType())) {
1306 if (mlir::isa<cir::ConstPtrAttr>(op.getValue())) {
1307 if (mlir::cast<cir::ConstPtrAttr>(op.getValue()).isNullValue()) {
1308 rewriter.replaceOpWithNewOp<mlir::LLVM::ZeroOp>(
1309 op, typeConverter->convertType(op.getType()));
1310 return mlir::success();
1314 if (
auto gv = mlir::dyn_cast<cir::GlobalViewAttr>(op.getValue())) {
1316 rewriter.replaceOp(op, newOp);
1317 return mlir::success();
1319 attr = op.getValue();
1320 }
else if (
const auto arrTy = mlir::dyn_cast<cir::ArrayType>(op.getType())) {
1321 const auto constArr = mlir::dyn_cast<cir::ConstArrayAttr>(op.getValue());
1322 if (!constArr && !isa<cir::ZeroAttr, cir::UndefAttr>(op.getValue()))
1323 return op.emitError() <<
"array does not have a constant initializer";
1325 std::optional<mlir::Attribute> denseAttr;
1327 const mlir::Value newOp =
1329 rewriter.replaceOp(op, newOp);
1330 return mlir::success();
1331 }
else if (constArr &&
1333 attr = denseAttr.value();
1335 const mlir::Value initVal =
1337 rewriter.replaceAllUsesWith(op, initVal);
1338 rewriter.eraseOp(op);
1339 return mlir::success();
1341 }
else if (
const auto recordAttr =
1342 mlir::dyn_cast<cir::ConstRecordAttr>(op.getValue())) {
1344 rewriter.replaceOp(op, initVal);
1345 return mlir::success();
1346 }
else if (
const auto vecTy = mlir::dyn_cast<cir::VectorType>(op.getType())) {
1348 getTypeConverter()));
1349 return mlir::success();
1350 }
else if (
auto complexTy = mlir::dyn_cast<cir::ComplexType>(op.getType())) {
1351 mlir::Type complexElemTy = complexTy.getElementType();
1352 mlir::Type complexElemLLVMTy = typeConverter->convertType(complexElemTy);
1354 if (
auto zeroInitAttr = mlir::dyn_cast<cir::ZeroAttr>(op.getValue())) {
1355 mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(complexElemLLVMTy);
1356 mlir::ArrayAttr array = rewriter.getArrayAttr({zeroAttr, zeroAttr});
1357 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
1358 op, getTypeConverter()->convertType(op.getType()), array);
1359 return mlir::success();
1362 auto complexAttr = mlir::cast<cir::ConstComplexAttr>(op.getValue());
1364 mlir::Attribute components[2];
1365 if (mlir::isa<cir::IntType>(complexElemTy)) {
1366 components[0] = rewriter.getIntegerAttr(
1368 mlir::cast<cir::IntAttr>(complexAttr.getReal()).getValue());
1369 components[1] = rewriter.getIntegerAttr(
1371 mlir::cast<cir::IntAttr>(complexAttr.getImag()).getValue());
1373 components[0] = rewriter.getFloatAttr(
1375 mlir::cast<cir::FPAttr>(complexAttr.getReal()).getValue());
1376 components[1] = rewriter.getFloatAttr(
1378 mlir::cast<cir::FPAttr>(complexAttr.getImag()).getValue());
1381 attr = rewriter.getArrayAttr(components);
1383 return op.emitError() <<
"unsupported constant type " << op.getType();
1386 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
1387 op, getTypeConverter()->convertType(op.getType()), attr);
1389 return mlir::success();
1393 cir::ExpectOp op, OpAdaptor adaptor,
1394 mlir::ConversionPatternRewriter &rewriter)
const {
1398 std::optional<llvm::APFloat> prob = op.getProb();
1400 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpectWithProbabilityOp>(
1401 op, adaptor.getVal(), adaptor.getExpected(), prob.value());
1403 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpectOp>(op, adaptor.getVal(),
1404 adaptor.getExpected());
1405 return mlir::success();
1409 cir::FAbsOp op, OpAdaptor adaptor,
1410 mlir::ConversionPatternRewriter &rewriter)
const {
1411 mlir::Type resTy = typeConverter->convertType(op.getType());
1412 rewriter.replaceOpWithNewOp<mlir::LLVM::FAbsOp>(op, resTy,
1413 adaptor.getOperands()[0]);
1414 return mlir::success();
1421void CIRToLLVMFuncOpLowering::lowerFuncAttributes(
1422 cir::FuncOp func,
bool filterArgAndResAttrs,
1425 for (mlir::NamedAttribute attr : func->getAttrs()) {
1427 if (attr.getName() == mlir::SymbolTable::getSymbolAttrName() ||
1428 attr.getName() == func.getFunctionTypeAttrName() ||
1429 attr.getName() == getLinkageAttrNameString() ||
1430 attr.getName() == func.getGlobalVisibilityAttrName() ||
1431 attr.getName() == func.getDsoLocalAttrName() ||
1432 (filterArgAndResAttrs &&
1433 (attr.getName() == func.getArgAttrsAttrName() ||
1434 attr.getName() == func.getResAttrsAttrName())))
1438 result.push_back(attr);
1442mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewriteAlias(
1443 cir::FuncOp op, llvm::StringRef aliasee, mlir::Type ty, OpAdaptor adaptor,
1444 mlir::ConversionPatternRewriter &rewriter)
const {
1446 lowerFuncAttributes(op,
false, attributes);
1448 mlir::Location loc = op.getLoc();
1449 auto aliasOp = rewriter.replaceOpWithNewOp<mlir::LLVM::AliasOp>(
1450 op, ty,
convertLinkage(op.getLinkage()), op.getName(), op.getDsoLocal(),
1454 mlir::OpBuilder builder(op.getContext());
1455 mlir::Block *block = builder.createBlock(&aliasOp.getInitializerRegion());
1456 builder.setInsertionPointToStart(block);
1459 mlir::Type ptrTy = mlir::LLVM::LLVMPointerType::get(ty.getContext());
1460 auto addrOp = mlir::LLVM::AddressOfOp::create(builder, loc, ptrTy, aliasee);
1461 mlir::LLVM::ReturnOp::create(builder, loc, addrOp);
1463 return mlir::success();
1467 cir::FuncOp op, OpAdaptor adaptor,
1468 mlir::ConversionPatternRewriter &rewriter)
const {
1470 cir::FuncType fnType = op.getFunctionType();
1471 bool isDsoLocal = op.getDsoLocal();
1472 mlir::TypeConverter::SignatureConversion signatureConversion(
1473 fnType.getNumInputs());
1475 for (
const auto &argType : llvm::enumerate(fnType.getInputs())) {
1476 mlir::Type convertedType = typeConverter->convertType(argType.value());
1478 return mlir::failure();
1479 signatureConversion.addInputs(argType.index(), convertedType);
1482 mlir::Type resultType =
1483 getTypeConverter()->convertType(fnType.getReturnType());
1486 mlir::Type llvmFnTy = mlir::LLVM::LLVMFunctionType::get(
1487 resultType ? resultType : mlir::LLVM::LLVMVoidType::get(getContext()),
1488 signatureConversion.getConvertedTypes(),
1492 if (std::optional<llvm::StringRef> aliasee = op.getAliasee())
1493 return matchAndRewriteAlias(op, *aliasee, llvmFnTy, adaptor, rewriter);
1497 mlir::Location loc = op.getLoc();
1498 if (mlir::FusedLoc fusedLoc = mlir::dyn_cast<mlir::FusedLoc>(loc))
1499 loc = fusedLoc.getLocations()[0];
1500 assert((mlir::isa<mlir::FileLineColLoc>(loc) ||
1501 mlir::isa<mlir::UnknownLoc>(loc)) &&
1502 "expected single location or unknown location here");
1506 mlir::LLVM::CConv cconv = mlir::LLVM::CConv::C;
1508 lowerFuncAttributes(op,
false, attributes);
1510 mlir::LLVM::LLVMFuncOp fn = rewriter.create<mlir::LLVM::LLVMFuncOp>(
1511 loc, op.getName(), llvmFnTy, linkage, isDsoLocal, cconv,
1512 mlir::SymbolRefAttr(), attributes);
1516 fn.setVisibility_Attr(mlir::LLVM::VisibilityAttr::get(
1518 op.getGlobalVisibilityAttr().getValue())));
1520 rewriter.inlineRegionBefore(op.getBody(), fn.getBody(), fn.end());
1521 if (failed(rewriter.convertRegionTypes(&fn.getBody(), *typeConverter,
1522 &signatureConversion)))
1523 return mlir::failure();
1525 rewriter.eraseOp(op);
1527 return mlir::LogicalResult::success();
1531 cir::GetGlobalOp op, OpAdaptor adaptor,
1532 mlir::ConversionPatternRewriter &rewriter)
const {
1535 if (op->getUses().empty()) {
1536 rewriter.eraseOp(op);
1537 return mlir::success();
1540 mlir::Type type = getTypeConverter()->convertType(op.getType());
1541 mlir::Operation *newop =
1542 rewriter.create<mlir::LLVM::AddressOfOp>(op.getLoc(), type, op.getName());
1546 rewriter.replaceOp(op, newop);
1547 return mlir::success();
1552void CIRToLLVMGlobalOpLowering::setupRegionInitializedLLVMGlobalOp(
1553 cir::GlobalOp op, mlir::ConversionPatternRewriter &rewriter)
const {
1554 const mlir::Type llvmType =
1562 const bool isConst = op.getConstant();
1564 const unsigned addrSpace = 0;
1565 const bool isDsoLocal = op.getDsoLocal();
1567 const bool isThreadLocal =
false;
1568 const uint64_t alignment = op.getAlignment().value_or(0);
1569 const mlir::LLVM::Linkage linkage =
convertLinkage(op.getLinkage());
1570 const StringRef symbol = op.getSymName();
1571 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
1574 mlir::LLVM::GlobalOp newGlobalOp =
1575 rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
1576 op, llvmType, isConst, linkage, symbol,
nullptr, alignment, addrSpace,
1577 isDsoLocal, isThreadLocal, comdatAttr, attributes);
1578 newGlobalOp.getRegion().emplaceBlock();
1579 rewriter.setInsertionPointToEnd(newGlobalOp.getInitializerBlock());
1583CIRToLLVMGlobalOpLowering::matchAndRewriteRegionInitializedGlobal(
1584 cir::GlobalOp op, mlir::Attribute init,
1585 mlir::ConversionPatternRewriter &rewriter)
const {
1587 assert((isa<cir::ConstArrayAttr, cir::ConstRecordAttr, cir::ConstVectorAttr,
1588 cir::ConstPtrAttr, cir::ConstComplexAttr, cir::GlobalViewAttr,
1589 cir::VTableAttr, cir::ZeroAttr>(init)));
1594 const mlir::Location loc = op.getLoc();
1595 setupRegionInitializedLLVMGlobalOp(op, rewriter);
1596 CIRAttrToValue valueConverter(op, rewriter, typeConverter);
1597 mlir::Value value = valueConverter.visit(init);
1598 rewriter.create<mlir::LLVM::ReturnOp>(loc, value);
1599 return mlir::success();
1603 cir::GlobalOp op, OpAdaptor adaptor,
1604 mlir::ConversionPatternRewriter &rewriter)
const {
1606 std::optional<mlir::Attribute> init = op.getInitialValue();
1609 const mlir::Type cirSymType = op.getSymType();
1612 const mlir::Type llvmType =
1617 const bool isConst =
false;
1619 const unsigned addrSpace = 0;
1620 const bool isDsoLocal = op.getDsoLocal();
1622 const bool isThreadLocal =
false;
1623 const uint64_t alignment = op.getAlignment().value_or(0);
1624 const mlir::LLVM::Linkage linkage =
convertLinkage(op.getLinkage());
1625 const StringRef symbol = op.getSymName();
1627 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
1629 if (init.has_value()) {
1630 if (mlir::isa<cir::FPAttr, cir::IntAttr, cir::BoolAttr>(init.value())) {
1632 init = initRewriter.
visit(init.value());
1637 if (!init.value()) {
1638 op.emitError() <<
"unsupported initializer '" << init.value() <<
"'";
1639 return mlir::failure();
1641 }
else if (mlir::isa<cir::ConstArrayAttr, cir::ConstVectorAttr,
1642 cir::ConstRecordAttr, cir::ConstPtrAttr,
1643 cir::ConstComplexAttr, cir::GlobalViewAttr,
1644 cir::VTableAttr, cir::ZeroAttr>(init.value())) {
1648 return matchAndRewriteRegionInitializedGlobal(op, init.value(), rewriter);
1652 op.emitError() <<
"unsupported initializer '" << init.value() <<
"'";
1653 return mlir::failure();
1658 rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
1659 op, llvmType, isConst, linkage, symbol, init.value_or(mlir::Attribute()),
1660 alignment, addrSpace, isDsoLocal, isThreadLocal, comdatAttr, attributes);
1661 return mlir::success();
1665CIRToLLVMGlobalOpLowering::getComdatAttr(cir::GlobalOp &op,
1666 mlir::OpBuilder &builder)
const {
1667 if (!op.getComdat())
1668 return mlir::SymbolRefAttr{};
1670 mlir::ModuleOp module = op->getParentOfType<mlir::ModuleOp>();
1671 mlir::OpBuilder::InsertionGuard guard(builder);
1672 StringRef comdatName(
"__llvm_comdat_globals");
1674 builder.setInsertionPointToStart(module.getBody());
1676 builder.create<mlir::LLVM::ComdatOp>(module.getLoc(), comdatName);
1679 builder.setInsertionPointToStart(&comdatOp.getBody().back());
1680 auto selectorOp = builder.create<mlir::LLVM::ComdatSelectorOp>(
1681 comdatOp.getLoc(), op.getSymName(), mlir::LLVM::comdat::Comdat::Any);
1682 return mlir::SymbolRefAttr::get(
1683 builder.getContext(), comdatName,
1684 mlir::FlatSymbolRefAttr::get(selectorOp.getSymNameAttr()));
1688 cir::SwitchFlatOp op, OpAdaptor adaptor,
1689 mlir::ConversionPatternRewriter &rewriter)
const {
1692 for (mlir::Attribute val : op.getCaseValues()) {
1693 auto intAttr = cast<cir::IntAttr>(val);
1694 caseValues.push_back(intAttr.getValue());
1700 for (mlir::Block *x : op.getCaseDestinations())
1701 caseDestinations.push_back(x);
1703 for (mlir::OperandRange x : op.getCaseOperands())
1704 caseOperands.push_back(x);
1707 rewriter.setInsertionPoint(op);
1708 rewriter.replaceOpWithNewOp<mlir::LLVM::SwitchOp>(
1709 op, adaptor.getCondition(), op.getDefaultDestination(),
1710 op.getDefaultOperands(), caseValues, caseDestinations, caseOperands);
1711 return mlir::success();
1715 cir::UnaryOp op, OpAdaptor adaptor,
1716 mlir::ConversionPatternRewriter &rewriter)
const {
1717 assert(op.getType() == op.getInput().getType() &&
1718 "Unary operation's operand type and result type are different");
1719 mlir::Type type = op.getType();
1720 mlir::Type elementType = elementTypeIfVector(type);
1721 bool isVector = mlir::isa<cir::VectorType>(type);
1722 mlir::Type llvmType = getTypeConverter()->convertType(type);
1723 mlir::Location loc = op.getLoc();
1726 if (mlir::isa<cir::IntType>(elementType)) {
1727 mlir::LLVM::IntegerOverflowFlags maybeNSW =
1728 op.getNoSignedWrap() ? mlir::LLVM::IntegerOverflowFlags::nsw
1729 : mlir::LLVM::IntegerOverflowFlags::none;
1730 switch (op.getKind()) {
1731 case cir::UnaryOpKind::Inc: {
1732 assert(!
isVector &&
"++ not allowed on vector types");
1733 auto one = rewriter.create<mlir::LLVM::ConstantOp>(loc, llvmType, 1);
1734 rewriter.replaceOpWithNewOp<mlir::LLVM::AddOp>(
1735 op, llvmType, adaptor.getInput(), one, maybeNSW);
1736 return mlir::success();
1738 case cir::UnaryOpKind::Dec: {
1739 assert(!
isVector &&
"-- not allowed on vector types");
1740 auto one = rewriter.create<mlir::LLVM::ConstantOp>(loc, llvmType, 1);
1741 rewriter.replaceOpWithNewOp<mlir::LLVM::SubOp>(op, adaptor.getInput(),
1743 return mlir::success();
1745 case cir::UnaryOpKind::Plus:
1746 rewriter.replaceOp(op, adaptor.getInput());
1747 return mlir::success();
1748 case cir::UnaryOpKind::Minus: {
1751 zero = rewriter.create<mlir::LLVM::ZeroOp>(loc, llvmType);
1753 zero = rewriter.create<mlir::LLVM::ConstantOp>(loc, llvmType, 0);
1754 rewriter.replaceOpWithNewOp<mlir::LLVM::SubOp>(
1755 op, zero, adaptor.getInput(), maybeNSW);
1756 return mlir::success();
1758 case cir::UnaryOpKind::Not: {
1760 mlir::Value minusOne;
1762 const uint64_t numElements =
1763 mlir::dyn_cast<cir::VectorType>(type).getSize();
1764 std::vector<int32_t> values(numElements, -1);
1765 mlir::DenseIntElementsAttr denseVec = rewriter.getI32VectorAttr(values);
1767 rewriter.create<mlir::LLVM::ConstantOp>(loc, llvmType, denseVec);
1769 minusOne = rewriter.create<mlir::LLVM::ConstantOp>(loc, llvmType, -1);
1771 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getInput(),
1773 return mlir::success();
1776 llvm_unreachable(
"Unexpected unary op for int");
1780 if (mlir::isa<cir::FPTypeInterface>(elementType)) {
1781 switch (op.getKind()) {
1782 case cir::UnaryOpKind::Inc: {
1783 assert(!
isVector &&
"++ not allowed on vector types");
1784 mlir::LLVM::ConstantOp one = rewriter.create<mlir::LLVM::ConstantOp>(
1785 loc, llvmType, rewriter.getFloatAttr(llvmType, 1.0));
1786 rewriter.replaceOpWithNewOp<mlir::LLVM::FAddOp>(op, llvmType, one,
1787 adaptor.getInput());
1788 return mlir::success();
1790 case cir::UnaryOpKind::Dec: {
1791 assert(!
isVector &&
"-- not allowed on vector types");
1792 mlir::LLVM::ConstantOp minusOne = rewriter.create<mlir::LLVM::ConstantOp>(
1793 loc, llvmType, rewriter.getFloatAttr(llvmType, -1.0));
1794 rewriter.replaceOpWithNewOp<mlir::LLVM::FAddOp>(op, llvmType, minusOne,
1795 adaptor.getInput());
1796 return mlir::success();
1798 case cir::UnaryOpKind::Plus:
1799 rewriter.replaceOp(op, adaptor.getInput());
1800 return mlir::success();
1801 case cir::UnaryOpKind::Minus:
1802 rewriter.replaceOpWithNewOp<mlir::LLVM::FNegOp>(op, llvmType,
1803 adaptor.getInput());
1804 return mlir::success();
1805 case cir::UnaryOpKind::Not:
1806 return op.emitError() <<
"Unary not is invalid for floating-point types";
1808 llvm_unreachable(
"Unexpected unary op for float");
1813 if (mlir::isa<cir::BoolType>(elementType)) {
1814 switch (op.getKind()) {
1815 case cir::UnaryOpKind::Inc:
1816 case cir::UnaryOpKind::Dec:
1817 case cir::UnaryOpKind::Plus:
1818 case cir::UnaryOpKind::Minus:
1821 return op.emitError() <<
"Unsupported unary operation on boolean type";
1822 case cir::UnaryOpKind::Not: {
1823 assert(!
isVector &&
"NYI: op! on vector mask");
1824 auto one = rewriter.create<mlir::LLVM::ConstantOp>(loc, llvmType, 1);
1825 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getInput(),
1827 return mlir::success();
1830 llvm_unreachable(
"Unexpected unary op for bool");
1835 if (mlir::isa<cir::PointerType>(elementType)) {
1836 return op.emitError()
1837 <<
"Unary operation on pointer types is not yet implemented";
1840 return op.emitError() <<
"Unary operation has unsupported type: "
1844mlir::LLVM::IntegerOverflowFlags
1845CIRToLLVMBinOpLowering::getIntOverflowFlag(cir::BinOp op)
const {
1846 if (op.getNoUnsignedWrap())
1847 return mlir::LLVM::IntegerOverflowFlags::nuw;
1849 if (op.getNoSignedWrap())
1850 return mlir::LLVM::IntegerOverflowFlags::nsw;
1852 return mlir::LLVM::IntegerOverflowFlags::none;
1857 return mlir::isa<cir::IntType>(type)
1858 ? mlir::cast<cir::IntType>(type).isUnsigned()
1859 : mlir::cast<mlir::IntegerType>(type).isUnsigned();
1863 cir::BinOp op, OpAdaptor adaptor,
1864 mlir::ConversionPatternRewriter &rewriter)
const {
1865 if (adaptor.getLhs().getType() != adaptor.getRhs().getType())
1866 return op.emitError() <<
"inconsistent operands' types not supported yet";
1868 mlir::Type type = op.getRhs().getType();
1869 if (!mlir::isa<cir::IntType, cir::BoolType, cir::FPTypeInterface,
1870 mlir::IntegerType, cir::VectorType>(type))
1871 return op.emitError() <<
"operand type not supported yet";
1873 const mlir::Type llvmTy = getTypeConverter()->convertType(op.getType());
1874 const mlir::Type llvmEltTy = elementTypeIfVector(llvmTy);
1876 const mlir::Value rhs = adaptor.getRhs();
1877 const mlir::Value lhs = adaptor.getLhs();
1878 type = elementTypeIfVector(type);
1880 switch (op.getKind()) {
1881 case cir::BinOpKind::Add:
1882 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
1883 if (op.getSaturated()) {
1885 rewriter.replaceOpWithNewOp<mlir::LLVM::UAddSat>(op, lhs, rhs);
1888 rewriter.replaceOpWithNewOp<mlir::LLVM::SAddSat>(op, lhs, rhs);
1891 rewriter.replaceOpWithNewOp<mlir::LLVM::AddOp>(op, llvmTy, lhs, rhs,
1892 getIntOverflowFlag(op));
1894 rewriter.replaceOpWithNewOp<mlir::LLVM::FAddOp>(op, lhs, rhs);
1897 case cir::BinOpKind::Sub:
1898 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
1899 if (op.getSaturated()) {
1901 rewriter.replaceOpWithNewOp<mlir::LLVM::USubSat>(op, lhs, rhs);
1904 rewriter.replaceOpWithNewOp<mlir::LLVM::SSubSat>(op, lhs, rhs);
1907 rewriter.replaceOpWithNewOp<mlir::LLVM::SubOp>(op, llvmTy, lhs, rhs,
1908 getIntOverflowFlag(op));
1910 rewriter.replaceOpWithNewOp<mlir::LLVM::FSubOp>(op, lhs, rhs);
1913 case cir::BinOpKind::Mul:
1914 if (mlir::isa<mlir::IntegerType>(llvmEltTy))
1915 rewriter.replaceOpWithNewOp<mlir::LLVM::MulOp>(op, llvmTy, lhs, rhs,
1916 getIntOverflowFlag(op));
1918 rewriter.replaceOpWithNewOp<mlir::LLVM::FMulOp>(op, lhs, rhs);
1920 case cir::BinOpKind::Div:
1921 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
1924 rewriter.replaceOpWithNewOp<mlir::LLVM::UDivOp>(op, lhs, rhs);
1926 rewriter.replaceOpWithNewOp<mlir::LLVM::SDivOp>(op, lhs, rhs);
1928 rewriter.replaceOpWithNewOp<mlir::LLVM::FDivOp>(op, lhs, rhs);
1931 case cir::BinOpKind::Rem:
1932 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
1935 rewriter.replaceOpWithNewOp<mlir::LLVM::URemOp>(op, lhs, rhs);
1937 rewriter.replaceOpWithNewOp<mlir::LLVM::SRemOp>(op, lhs, rhs);
1939 rewriter.replaceOpWithNewOp<mlir::LLVM::FRemOp>(op, lhs, rhs);
1942 case cir::BinOpKind::And:
1943 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(op, lhs, rhs);
1945 case cir::BinOpKind::Or:
1946 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(op, lhs, rhs);
1948 case cir::BinOpKind::Xor:
1949 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, lhs, rhs);
1951 case cir::BinOpKind::Max:
1952 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
1955 rewriter.replaceOpWithNewOp<mlir::LLVM::UMaxOp>(op, llvmTy, lhs, rhs);
1957 rewriter.replaceOpWithNewOp<mlir::LLVM::SMaxOp>(op, llvmTy, lhs, rhs);
1961 return mlir::LogicalResult::success();
1965static mlir::LLVM::ICmpPredicate
1967 using CIR = cir::CmpOpKind;
1968 using LLVMICmp = mlir::LLVM::ICmpPredicate;
1971 return LLVMICmp::eq;
1973 return LLVMICmp::ne;
1975 return (isSigned ? LLVMICmp::slt : LLVMICmp::ult);
1977 return (isSigned ? LLVMICmp::sle : LLVMICmp::ule);
1979 return (isSigned ? LLVMICmp::sgt : LLVMICmp::ugt);
1981 return (isSigned ? LLVMICmp::sge : LLVMICmp::uge);
1983 llvm_unreachable(
"Unknown CmpOpKind");
1988static mlir::LLVM::FCmpPredicate
1990 using CIR = cir::CmpOpKind;
1991 using LLVMFCmp = mlir::LLVM::FCmpPredicate;
1994 return LLVMFCmp::oeq;
1996 return LLVMFCmp::une;
1998 return LLVMFCmp::olt;
2000 return LLVMFCmp::ole;
2002 return LLVMFCmp::ogt;
2004 return LLVMFCmp::oge;
2006 llvm_unreachable(
"Unknown CmpOpKind");
2010 cir::CmpOp cmpOp, OpAdaptor adaptor,
2011 mlir::ConversionPatternRewriter &rewriter)
const {
2012 mlir::Type type = cmpOp.getLhs().getType();
2017 if (mlir::isa<cir::IntType, mlir::IntegerType>(type)) {
2018 bool isSigned = mlir::isa<cir::IntType>(type)
2019 ? mlir::cast<cir::IntType>(type).isSigned()
2020 : mlir::cast<mlir::IntegerType>(type).isSigned();
2021 mlir::LLVM::ICmpPredicate kind =
2023 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
2024 cmpOp, kind, adaptor.getLhs(), adaptor.getRhs());
2025 return mlir::success();
2028 if (
auto ptrTy = mlir::dyn_cast<cir::PointerType>(type)) {
2029 mlir::LLVM::ICmpPredicate kind =
2032 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
2033 cmpOp, kind, adaptor.getLhs(), adaptor.getRhs());
2034 return mlir::success();
2037 if (mlir::isa<cir::FPTypeInterface>(type)) {
2038 mlir::LLVM::FCmpPredicate kind =
2040 rewriter.replaceOpWithNewOp<mlir::LLVM::FCmpOp>(
2041 cmpOp, kind, adaptor.getLhs(), adaptor.getRhs());
2042 return mlir::success();
2045 if (mlir::isa<cir::ComplexType>(type)) {
2046 mlir::Value lhs = adaptor.getLhs();
2047 mlir::Value rhs = adaptor.getRhs();
2048 mlir::Location loc = cmpOp.getLoc();
2050 auto complexType = mlir::cast<cir::ComplexType>(cmpOp.getLhs().getType());
2051 mlir::Type complexElemTy =
2052 getTypeConverter()->convertType(complexType.getElementType());
2055 rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, lhs, 0);
2057 rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, lhs, 1);
2059 rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, rhs, 0);
2061 rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, rhs, 1);
2063 if (cmpOp.getKind() == cir::CmpOpKind::eq) {
2064 if (complexElemTy.isInteger()) {
2065 auto realCmp = rewriter.create<mlir::LLVM::ICmpOp>(
2066 loc, mlir::LLVM::ICmpPredicate::eq, lhsReal, rhsReal);
2067 auto imagCmp = rewriter.create<mlir::LLVM::ICmpOp>(
2068 loc, mlir::LLVM::ICmpPredicate::eq, lhsImag, rhsImag);
2069 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, imagCmp);
2070 return mlir::success();
2073 auto realCmp = rewriter.create<mlir::LLVM::FCmpOp>(
2074 loc, mlir::LLVM::FCmpPredicate::oeq, lhsReal, rhsReal);
2075 auto imagCmp = rewriter.create<mlir::LLVM::FCmpOp>(
2076 loc, mlir::LLVM::FCmpPredicate::oeq, lhsImag, rhsImag);
2077 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, imagCmp);
2078 return mlir::success();
2081 if (cmpOp.getKind() == cir::CmpOpKind::ne) {
2082 if (complexElemTy.isInteger()) {
2083 auto realCmp = rewriter.create<mlir::LLVM::ICmpOp>(
2084 loc, mlir::LLVM::ICmpPredicate::ne, lhsReal, rhsReal);
2085 auto imagCmp = rewriter.create<mlir::LLVM::ICmpOp>(
2086 loc, mlir::LLVM::ICmpPredicate::ne, lhsImag, rhsImag);
2087 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp);
2088 return mlir::success();
2091 auto realCmp = rewriter.create<mlir::LLVM::FCmpOp>(
2092 loc, mlir::LLVM::FCmpPredicate::une, lhsReal, rhsReal);
2093 auto imagCmp = rewriter.create<mlir::LLVM::FCmpOp>(
2094 loc, mlir::LLVM::FCmpPredicate::une, lhsImag, rhsImag);
2095 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp);
2096 return mlir::success();
2100 return cmpOp.emitError() <<
"unsupported type for CmpOp: " << type;
2104 cir::ShiftOp op, OpAdaptor adaptor,
2105 mlir::ConversionPatternRewriter &rewriter)
const {
2106 assert((op.getValue().getType() == op.getType()) &&
2107 "inconsistent operands' types NYI");
2109 const mlir::Type llvmTy = getTypeConverter()->convertType(op.getType());
2110 mlir::Value amt = adaptor.getAmount();
2111 mlir::Value val = adaptor.getValue();
2113 auto cirAmtTy = mlir::dyn_cast<cir::IntType>(op.getAmount().getType());
2116 auto cirValTy = mlir::cast<cir::IntType>(op.getValue().getType());
2124 amt =
getLLVMIntCast(rewriter, amt, llvmTy,
true, cirAmtTy.getWidth(),
2125 cirValTy.getWidth());
2127 auto cirValVTy = mlir::cast<cir::VectorType>(op.getValue().getType());
2129 mlir::cast<cir::IntType>(cirValVTy.getElementType()).isUnsigned();
2133 if (op.getIsShiftleft()) {
2134 rewriter.replaceOpWithNewOp<mlir::LLVM::ShlOp>(op, llvmTy, val, amt);
2135 return mlir::success();
2139 rewriter.replaceOpWithNewOp<mlir::LLVM::LShrOp>(op, llvmTy, val, amt);
2141 rewriter.replaceOpWithNewOp<mlir::LLVM::AShrOp>(op, llvmTy, val, amt);
2142 return mlir::success();
2146 cir::SelectOp op, OpAdaptor adaptor,
2147 mlir::ConversionPatternRewriter &rewriter)
const {
2148 auto getConstantBool = [](mlir::Value value) -> cir::BoolAttr {
2149 auto definingOp = value.getDefiningOp<cir::ConstantOp>();
2153 auto constValue = definingOp.getValueAttr<cir::BoolAttr>();
2163 if (mlir::isa<cir::BoolType>(op.getTrueValue().getType())) {
2164 cir::BoolAttr trueValue = getConstantBool(op.getTrueValue());
2165 cir::BoolAttr falseValue = getConstantBool(op.getFalseValue());
2166 if (falseValue && !falseValue.getValue()) {
2168 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(op, adaptor.getCondition(),
2169 adaptor.getTrueValue());
2170 return mlir::success();
2172 if (trueValue && trueValue.getValue()) {
2174 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(op, adaptor.getCondition(),
2175 adaptor.getFalseValue());
2176 return mlir::success();
2180 mlir::Value llvmCondition = adaptor.getCondition();
2181 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(
2182 op, llvmCondition, adaptor.getTrueValue(), adaptor.getFalseValue());
2184 return mlir::success();
2188 mlir::DataLayout &dataLayout) {
2189 converter.addConversion([&](cir::PointerType type) -> mlir::Type {
2192 unsigned targetAS = 0;
2194 return mlir::LLVM::LLVMPointerType::get(type.getContext(), targetAS);
2196 converter.addConversion([&](cir::VPtrType type) -> mlir::Type {
2198 return mlir::LLVM::LLVMPointerType::get(type.getContext());
2200 converter.addConversion([&](cir::ArrayType type) -> mlir::Type {
2203 return mlir::LLVM::LLVMArrayType::get(ty, type.getSize());
2205 converter.addConversion([&](cir::VectorType type) -> mlir::Type {
2206 const mlir::Type ty = converter.convertType(type.getElementType());
2207 return mlir::VectorType::get(type.getSize(), ty);
2209 converter.addConversion([&](cir::BoolType type) -> mlir::Type {
2210 return mlir::IntegerType::get(type.getContext(), 1,
2211 mlir::IntegerType::Signless);
2213 converter.addConversion([&](cir::IntType type) -> mlir::Type {
2215 return mlir::IntegerType::get(type.getContext(), type.getWidth());
2217 converter.addConversion([&](cir::SingleType type) -> mlir::Type {
2218 return mlir::Float32Type::get(type.getContext());
2220 converter.addConversion([&](cir::DoubleType type) -> mlir::Type {
2221 return mlir::Float64Type::get(type.getContext());
2223 converter.addConversion([&](cir::FP80Type type) -> mlir::Type {
2224 return mlir::Float80Type::get(type.getContext());
2226 converter.addConversion([&](cir::FP128Type type) -> mlir::Type {
2227 return mlir::Float128Type::get(type.getContext());
2229 converter.addConversion([&](cir::LongDoubleType type) -> mlir::Type {
2230 return converter.convertType(type.getUnderlying());
2232 converter.addConversion([&](cir::FP16Type type) -> mlir::Type {
2233 return mlir::Float16Type::get(type.getContext());
2235 converter.addConversion([&](cir::BF16Type type) -> mlir::Type {
2236 return mlir::BFloat16Type::get(type.getContext());
2238 converter.addConversion([&](cir::ComplexType type) -> mlir::Type {
2241 mlir::Type elementTy = converter.convertType(type.getElementType());
2242 mlir::Type structFields[2] = {elementTy, elementTy};
2243 return mlir::LLVM::LLVMStructType::getLiteral(type.getContext(),
2246 converter.addConversion([&](cir::FuncType type) -> std::optional<mlir::Type> {
2247 auto result = converter.convertType(type.getReturnType());
2249 arguments.reserve(type.getNumInputs());
2250 if (converter.convertTypes(type.getInputs(), arguments).failed())
2251 return std::nullopt;
2252 auto varArg = type.isVarArg();
2253 return mlir::LLVM::LLVMFunctionType::get(result, arguments, varArg);
2255 converter.addConversion([&](cir::RecordType type) -> mlir::Type {
2258 switch (type.getKind()) {
2259 case cir::RecordType::Class:
2260 case cir::RecordType::Struct:
2261 for (mlir::Type ty : type.getMembers())
2265 case cir::RecordType::Union:
2266 if (
auto largestMember = type.getLargestMember(dataLayout))
2267 llvmMembers.push_back(
2269 if (type.getPadded()) {
2270 auto last = *type.getMembers().rbegin();
2271 llvmMembers.push_back(
2276 converter.addConversion([&](cir::VoidType type) -> mlir::Type {
2277 return mlir::LLVM::LLVMVoidType::get(type.getContext());
2281 mlir::LLVM::LLVMStructType llvmStruct;
2282 if (type.getName()) {
2283 llvmStruct = mlir::LLVM::LLVMStructType::getIdentified(
2284 type.getContext(), type.getPrefixedName());
2285 if (llvmStruct.setBody(llvmMembers, type.getPacked()).failed())
2286 llvm_unreachable(
"Failed to set body of record");
2288 llvmStruct = mlir::LLVM::LLVMStructType::getLiteral(
2289 type.getContext(), llvmMembers, type.getPacked());
2294 converter.addConversion([&](cir::VoidType type) -> mlir::Type {
2295 return mlir::LLVM::LLVMVoidType::get(type.getContext());
2334 parent->walk([&](mlir::Block *blk) {
2335 if (blk->hasNoPredecessors() && !blk->isEntryBlock())
2336 unreachableBlocks.push_back(blk);
2339 std::set<mlir::Block *> visited;
2340 for (mlir::Block *root : unreachableBlocks) {
2343 std::deque<mlir::Block *> workList;
2344 workList.push_back(root);
2346 while (!workList.empty()) {
2347 mlir::Block *blk = workList.back();
2348 workList.pop_back();
2349 if (visited.count(blk))
2351 visited.emplace(blk);
2353 for (mlir::Operation &op : *blk)
2356 for (mlir::Block *succ : blk->getSuccessors())
2357 workList.push_back(succ);
2364 if (mlir::Attribute tripleAttr =
2365 module->getAttr(cir::CIRDialect::getTripleAttrName()))
2366 module->setAttr(mlir::LLVM::LLVMDialect::getTargetTripleAttrName(),
2369 if (mlir::Attribute asmAttr =
2370 module->getAttr(cir::CIRDialect::getModuleLevelAsmAttrName()))
2371 module->setAttr(mlir::LLVM::LLVMDialect::getModuleLevelAsmAttrName(),
2376 llvm::TimeTraceScope scope(
"Convert CIR to LLVM Pass");
2378 mlir::ModuleOp module = getOperation();
2379 mlir::DataLayout dl(module);
2380 mlir::LLVMTypeConverter converter(&getContext());
2383 mlir::RewritePatternSet patterns(&getContext());
2459 >(converter, patterns.getContext());
2463 mlir::ConversionTarget target(getContext());
2464 target.addLegalOp<mlir::ModuleOp>();
2465 target.addLegalDialect<mlir::LLVM::LLVMDialect>();
2466 target.addIllegalDialect<mlir::BuiltinDialect, cir::CIRDialect,
2467 mlir::func::FuncDialect>();
2470 ops.push_back(module);
2473 if (failed(applyPartialConversion(ops, target, std::move(patterns))))
2474 signalPassFailure();
2478 cir::BrOp op, OpAdaptor adaptor,
2479 mlir::ConversionPatternRewriter &rewriter)
const {
2480 rewriter.replaceOpWithNewOp<mlir::LLVM::BrOp>(op, adaptor.getOperands(),
2482 return mlir::LogicalResult::success();
2486 cir::GetMemberOp op, OpAdaptor adaptor,
2487 mlir::ConversionPatternRewriter &rewriter)
const {
2488 mlir::Type llResTy = getTypeConverter()->convertType(op.getType());
2489 const auto recordTy =
2490 mlir::cast<cir::RecordType>(op.getAddrTy().getPointee());
2491 assert(recordTy &&
"expected record type");
2493 switch (recordTy.getKind()) {
2494 case cir::RecordType::Class:
2495 case cir::RecordType::Struct: {
2499 const mlir::Type elementTy = getTypeConverter()->convertType(recordTy);
2500 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, llResTy, elementTy,
2501 adaptor.getAddr(), offset);
2502 return mlir::success();
2504 case cir::RecordType::Union:
2507 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(op, llResTy,
2509 return mlir::success();
2514 cir::UnreachableOp op, OpAdaptor adaptor,
2515 mlir::ConversionPatternRewriter &rewriter)
const {
2516 rewriter.replaceOpWithNewOp<mlir::LLVM::UnreachableOp>(op);
2517 return mlir::success();
2521 mlir::Operation *srcOp, llvm::StringRef fnName,
2523 auto modOp = srcOp->getParentOfType<mlir::ModuleOp>();
2524 auto enclosingFnOp = srcOp->getParentOfType<mlir::LLVM::LLVMFuncOp>();
2525 mlir::Operation *sourceSymbol =
2526 mlir::SymbolTable::lookupSymbolIn(modOp, fnName);
2527 if (!sourceSymbol) {
2528 mlir::OpBuilder::InsertionGuard guard(rewriter);
2529 rewriter.setInsertionPoint(enclosingFnOp);
2530 rewriter.create<mlir::LLVM::LLVMFuncOp>(srcOp->getLoc(), fnName, fnTy);
2535 cir::ThrowOp op, OpAdaptor adaptor,
2536 mlir::ConversionPatternRewriter &rewriter)
const {
2537 if (op.rethrows()) {
2538 auto voidTy = mlir::LLVM::LLVMVoidType::get(getContext());
2540 mlir::LLVM::LLVMFunctionType::get(getContext(), voidTy, {},
false);
2542 auto mlirModule = op->getParentOfType<mlir::ModuleOp>();
2543 rewriter.setInsertionPointToStart(&mlirModule.getBodyRegion().front());
2545 const llvm::StringRef functionName =
"__cxa_rethrow";
2548 rewriter.setInsertionPointAfter(op.getOperation());
2549 rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(
2550 op, mlir::TypeRange{}, functionName, mlir::ValueRange{});
2553 return mlir::success();
2557 cir::TrapOp op, OpAdaptor adaptor,
2558 mlir::ConversionPatternRewriter &rewriter)
const {
2559 mlir::Location loc = op->getLoc();
2560 rewriter.eraseOp(op);
2562 rewriter.create<mlir::LLVM::Trap>(loc);
2567 rewriter.create<mlir::LLVM::UnreachableOp>(loc);
2569 return mlir::success();
2574 mlir::ConversionPatternRewriter &rewriter,
2575 const mlir::TypeConverter *converter,
2576 mlir::FlatSymbolRefAttr nameAttr, mlir::Type &eltType) {
2577 auto module = op->getParentOfType<mlir::ModuleOp>();
2578 mlir::Operation *symbol = mlir::SymbolTable::lookupSymbolIn(module, nameAttr);
2579 if (
auto llvmSymbol = mlir::dyn_cast<mlir::LLVM::GlobalOp>(symbol)) {
2580 eltType = llvmSymbol.getType();
2581 }
else if (
auto cirSymbol = mlir::dyn_cast<cir::GlobalOp>(symbol)) {
2582 eltType = converter->convertType(cirSymbol.getSymType());
2584 op->emitError() <<
"unexpected symbol type for " << symbol;
2588 return mlir::LLVM::AddressOfOp::create(
2589 rewriter, op->getLoc(),
2590 mlir::LLVM::LLVMPointerType::get(op->getContext()), nameAttr.getValue());
2594 cir::VTableAddrPointOp op, OpAdaptor adaptor,
2595 mlir::ConversionPatternRewriter &rewriter)
const {
2596 const mlir::TypeConverter *converter = getTypeConverter();
2597 mlir::Type targetType = converter->convertType(op.getType());
2601 op.getNameAttr(), eltType);
2603 return op.emitError() <<
"Unable to get value for vtable symbol";
2606 0, op.getAddressPointAttr().getIndex(),
2607 op.getAddressPointAttr().getOffset()};
2609 assert(eltType &&
"Shouldn't ever be missing an eltType here");
2610 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
2611 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
2612 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, targetType, eltType,
2613 symAddr, offsets, inboundsNuw);
2614 return mlir::success();
2618 cir::VTableGetVPtrOp op, OpAdaptor adaptor,
2619 mlir::ConversionPatternRewriter &rewriter)
const {
2623 mlir::Value srcVal = adaptor.getSrc();
2624 rewriter.replaceAllUsesWith(op, srcVal);
2625 rewriter.eraseOp(op);
2626 return mlir::success();
2630 cir::VTableGetVirtualFnAddrOp op, OpAdaptor adaptor,
2631 mlir::ConversionPatternRewriter &rewriter)
const {
2632 mlir::Type targetType = getTypeConverter()->convertType(op.getType());
2633 auto eltType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
2636 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
2637 op, targetType, eltType, adaptor.getVptr(), offsets,
2638 mlir::LLVM::GEPNoWrapFlags::inbounds);
2639 return mlir::success();
2643 cir::VTTAddrPointOp op, OpAdaptor adaptor,
2644 mlir::ConversionPatternRewriter &rewriter)
const {
2645 const mlir::Type resultType = getTypeConverter()->convertType(op.getType());
2648 mlir::Value llvmAddr = adaptor.getSymAddr();
2650 if (op.getSymAddr()) {
2651 if (op.getOffset() == 0) {
2652 rewriter.replaceOp(op, {llvmAddr});
2653 return mlir::success();
2656 offsets.push_back(adaptor.getOffset());
2657 eltType = mlir::IntegerType::get(resultType.getContext(), 8,
2658 mlir::IntegerType::Signless);
2661 op.getNameAttr(), eltType);
2662 assert(eltType &&
"Shouldn't ever be missing an eltType here");
2663 offsets.push_back(0);
2664 offsets.push_back(adaptor.getOffset());
2666 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
2667 op, resultType, eltType, llvmAddr, offsets,
2668 mlir::LLVM::GEPNoWrapFlags::inbounds);
2669 return mlir::success();
2673 cir::StackSaveOp op, OpAdaptor adaptor,
2674 mlir::ConversionPatternRewriter &rewriter)
const {
2675 const mlir::Type ptrTy = getTypeConverter()->convertType(op.getType());
2676 rewriter.replaceOpWithNewOp<mlir::LLVM::StackSaveOp>(op, ptrTy);
2677 return mlir::success();
2681 cir::StackRestoreOp op, OpAdaptor adaptor,
2682 mlir::ConversionPatternRewriter &rewriter)
const {
2683 rewriter.replaceOpWithNewOp<mlir::LLVM::StackRestoreOp>(op, adaptor.getPtr());
2684 return mlir::success();
2688 cir::VecCreateOp op, OpAdaptor adaptor,
2689 mlir::ConversionPatternRewriter &rewriter)
const {
2692 const auto vecTy = mlir::cast<cir::VectorType>(op.getType());
2693 const mlir::Type llvmTy = typeConverter->convertType(vecTy);
2694 const mlir::Location loc = op.getLoc();
2695 mlir::Value result = rewriter.create<mlir::LLVM::PoisonOp>(loc, llvmTy);
2696 assert(vecTy.getSize() == op.getElements().size() &&
2697 "cir.vec.create op count doesn't match vector type elements count");
2699 for (uint64_t i = 0; i < vecTy.getSize(); ++i) {
2700 const mlir::Value indexValue =
2701 rewriter.create<mlir::LLVM::ConstantOp>(loc, rewriter.getI64Type(), i);
2702 result = rewriter.create<mlir::LLVM::InsertElementOp>(
2703 loc, result, adaptor.getElements()[i], indexValue);
2706 rewriter.replaceOp(op, result);
2707 return mlir::success();
2711 cir::VecExtractOp op, OpAdaptor adaptor,
2712 mlir::ConversionPatternRewriter &rewriter)
const {
2713 rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractElementOp>(
2714 op, adaptor.getVec(), adaptor.getIndex());
2715 return mlir::success();
2719 cir::VecInsertOp op, OpAdaptor adaptor,
2720 mlir::ConversionPatternRewriter &rewriter)
const {
2721 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertElementOp>(
2722 op, adaptor.getVec(), adaptor.getValue(), adaptor.getIndex());
2723 return mlir::success();
2727 cir::VecCmpOp op, OpAdaptor adaptor,
2728 mlir::ConversionPatternRewriter &rewriter)
const {
2729 mlir::Type elementType = elementTypeIfVector(op.getLhs().getType());
2730 mlir::Value bitResult;
2731 if (
auto intType = mlir::dyn_cast<cir::IntType>(elementType)) {
2732 bitResult = rewriter.create<mlir::LLVM::ICmpOp>(
2735 adaptor.getLhs(), adaptor.getRhs());
2736 }
else if (mlir::isa<cir::FPTypeInterface>(elementType)) {
2737 bitResult = rewriter.create<mlir::LLVM::FCmpOp>(
2739 adaptor.getLhs(), adaptor.getRhs());
2741 return op.emitError() <<
"unsupported type for VecCmpOp: " << elementType;
2746 rewriter.replaceOpWithNewOp<mlir::LLVM::SExtOp>(
2747 op, typeConverter->convertType(op.getType()), bitResult);
2748 return mlir::success();
2752 cir::VecSplatOp op, OpAdaptor adaptor,
2753 mlir::ConversionPatternRewriter &rewriter)
const {
2759 cir::VectorType vecTy = op.getType();
2760 mlir::Type llvmTy = typeConverter->convertType(vecTy);
2761 mlir::Location loc = op.getLoc();
2762 mlir::Value poison = rewriter.create<mlir::LLVM::PoisonOp>(loc, llvmTy);
2764 mlir::Value elementValue = adaptor.getValue();
2765 if (elementValue.getDefiningOp<mlir::LLVM::PoisonOp>()) {
2768 rewriter.replaceOp(op, poison);
2769 return mlir::success();
2772 if (
auto constValue = elementValue.getDefiningOp<mlir::LLVM::ConstantOp>()) {
2773 if (
auto intAttr = dyn_cast<mlir::IntegerAttr>(constValue.getValue())) {
2774 mlir::DenseIntElementsAttr denseVec = mlir::DenseIntElementsAttr::get(
2775 mlir::cast<mlir::ShapedType>(llvmTy), intAttr.getValue());
2776 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
2777 op, denseVec.getType(), denseVec);
2778 return mlir::success();
2781 if (
auto fpAttr = dyn_cast<mlir::FloatAttr>(constValue.getValue())) {
2782 mlir::DenseFPElementsAttr denseVec = mlir::DenseFPElementsAttr::get(
2783 mlir::cast<mlir::ShapedType>(llvmTy), fpAttr.getValue());
2784 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
2785 op, denseVec.getType(), denseVec);
2786 return mlir::success();
2790 mlir::Value indexValue =
2791 rewriter.create<mlir::LLVM::ConstantOp>(loc, rewriter.getI64Type(), 0);
2792 mlir::Value oneElement = rewriter.create<mlir::LLVM::InsertElementOp>(
2793 loc, poison, elementValue, indexValue);
2795 rewriter.replaceOpWithNewOp<mlir::LLVM::ShuffleVectorOp>(op, oneElement,
2796 poison, zeroValues);
2797 return mlir::success();
2801 cir::VecShuffleOp op, OpAdaptor adaptor,
2802 mlir::ConversionPatternRewriter &rewriter)
const {
2808 op.getIndices().begin(), op.getIndices().end(),
2809 std::back_inserter(indices), [](mlir::Attribute intAttr) {
2810 return mlir::cast<cir::IntAttr>(intAttr).getValue().getSExtValue();
2812 rewriter.replaceOpWithNewOp<mlir::LLVM::ShuffleVectorOp>(
2813 op, adaptor.getVec1(), adaptor.getVec2(), indices);
2814 return mlir::success();
2818 cir::VecShuffleDynamicOp op, OpAdaptor adaptor,
2819 mlir::ConversionPatternRewriter &rewriter)
const {
2831 mlir::Location loc = op.getLoc();
2832 mlir::Value input = adaptor.getVec();
2833 mlir::Type llvmIndexVecType =
2834 getTypeConverter()->convertType(op.getIndices().getType());
2835 mlir::Type llvmIndexType = getTypeConverter()->convertType(
2836 elementTypeIfVector(op.getIndices().getType()));
2837 uint64_t numElements =
2838 mlir::cast<cir::VectorType>(op.getVec().getType()).getSize();
2840 uint64_t maskBits = llvm::NextPowerOf2(numElements - 1) - 1;
2841 mlir::Value maskValue = rewriter.create<mlir::LLVM::ConstantOp>(
2842 loc, llvmIndexType, rewriter.getIntegerAttr(llvmIndexType, maskBits));
2843 mlir::Value maskVector =
2844 rewriter.create<mlir::LLVM::UndefOp>(loc, llvmIndexVecType);
2846 for (uint64_t i = 0; i < numElements; ++i) {
2847 mlir::Value idxValue =
2848 rewriter.create<mlir::LLVM::ConstantOp>(loc, rewriter.getI64Type(), i);
2849 maskVector = rewriter.create<mlir::LLVM::InsertElementOp>(
2850 loc, maskVector, maskValue, idxValue);
2853 mlir::Value maskedIndices = rewriter.create<mlir::LLVM::AndOp>(
2854 loc, llvmIndexVecType, adaptor.getIndices(), maskVector);
2855 mlir::Value result = rewriter.create<mlir::LLVM::UndefOp>(
2856 loc, getTypeConverter()->convertType(op.getVec().getType()));
2857 for (uint64_t i = 0; i < numElements; ++i) {
2858 mlir::Value iValue =
2859 rewriter.create<mlir::LLVM::ConstantOp>(loc, rewriter.getI64Type(), i);
2860 mlir::Value indexValue = rewriter.create<mlir::LLVM::ExtractElementOp>(
2861 loc, maskedIndices, iValue);
2862 mlir::Value valueAtIndex =
2863 rewriter.create<mlir::LLVM::ExtractElementOp>(loc, input, indexValue);
2864 result = rewriter.create<mlir::LLVM::InsertElementOp>(loc, result,
2865 valueAtIndex, iValue);
2867 rewriter.replaceOp(op, result);
2868 return mlir::success();
2872 cir::VecTernaryOp op, OpAdaptor adaptor,
2873 mlir::ConversionPatternRewriter &rewriter)
const {
2875 mlir::Value bitVec = rewriter.create<mlir::LLVM::ICmpOp>(
2876 op.getLoc(), mlir::LLVM::ICmpPredicate::ne, adaptor.getCond(),
2877 rewriter.create<mlir::LLVM::ZeroOp>(
2878 op.getCond().getLoc(),
2879 typeConverter->convertType(op.getCond().getType())));
2880 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(
2881 op, bitVec, adaptor.getLhs(), adaptor.getRhs());
2882 return mlir::success();
2886 cir::ComplexAddOp op, OpAdaptor adaptor,
2887 mlir::ConversionPatternRewriter &rewriter)
const {
2888 mlir::Value lhs = adaptor.getLhs();
2889 mlir::Value rhs = adaptor.getRhs();
2890 mlir::Location loc = op.getLoc();
2892 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
2893 mlir::Type complexElemTy =
2894 getTypeConverter()->convertType(complexType.getElementType());
2896 rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, lhs, 0);
2898 rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, lhs, 1);
2900 rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, rhs, 0);
2902 rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, rhs, 1);
2904 mlir::Value newReal;
2905 mlir::Value newImag;
2906 if (complexElemTy.isInteger()) {
2907 newReal = rewriter.create<mlir::LLVM::AddOp>(loc, complexElemTy, lhsReal,
2909 newImag = rewriter.create<mlir::LLVM::AddOp>(loc, complexElemTy, lhsImag,
2914 newReal = rewriter.create<mlir::LLVM::FAddOp>(loc, complexElemTy, lhsReal,
2916 newImag = rewriter.create<mlir::LLVM::FAddOp>(loc, complexElemTy, lhsImag,
2920 mlir::Type complexLLVMTy =
2921 getTypeConverter()->convertType(op.getResult().getType());
2922 auto initialComplex =
2923 rewriter.create<mlir::LLVM::PoisonOp>(op->getLoc(), complexLLVMTy);
2925 auto realComplex = rewriter.create<mlir::LLVM::InsertValueOp>(
2926 op->getLoc(), initialComplex, newReal, 0);
2928 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(op, realComplex,
2931 return mlir::success();
2935 cir::ComplexCreateOp op, OpAdaptor adaptor,
2936 mlir::ConversionPatternRewriter &rewriter)
const {
2937 mlir::Type complexLLVMTy =
2938 getTypeConverter()->convertType(op.getResult().getType());
2939 auto initialComplex =
2940 rewriter.create<mlir::LLVM::UndefOp>(op->getLoc(), complexLLVMTy);
2942 auto realComplex = rewriter.create<mlir::LLVM::InsertValueOp>(
2943 op->getLoc(), initialComplex, adaptor.getReal(), 0);
2945 auto complex = rewriter.create<mlir::LLVM::InsertValueOp>(
2946 op->getLoc(), realComplex, adaptor.getImag(), 1);
2948 rewriter.replaceOp(op, complex);
2949 return mlir::success();
2953 cir::ComplexRealOp op, OpAdaptor adaptor,
2954 mlir::ConversionPatternRewriter &rewriter)
const {
2955 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
2956 rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractValueOp>(
2958 return mlir::success();
2962 cir::ComplexSubOp op, OpAdaptor adaptor,
2963 mlir::ConversionPatternRewriter &rewriter)
const {
2964 mlir::Value lhs = adaptor.getLhs();
2965 mlir::Value rhs = adaptor.getRhs();
2966 mlir::Location loc = op.getLoc();
2968 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
2969 mlir::Type complexElemTy =
2970 getTypeConverter()->convertType(complexType.getElementType());
2972 rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, lhs, 0);
2974 rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, lhs, 1);
2976 rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, rhs, 0);
2978 rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, rhs, 1);
2980 mlir::Value newReal;
2981 mlir::Value newImag;
2982 if (complexElemTy.isInteger()) {
2983 newReal = rewriter.create<mlir::LLVM::SubOp>(loc, complexElemTy, lhsReal,
2985 newImag = rewriter.create<mlir::LLVM::SubOp>(loc, complexElemTy, lhsImag,
2990 newReal = rewriter.create<mlir::LLVM::FSubOp>(loc, complexElemTy, lhsReal,
2992 newImag = rewriter.create<mlir::LLVM::FSubOp>(loc, complexElemTy, lhsImag,
2996 mlir::Type complexLLVMTy =
2997 getTypeConverter()->convertType(op.getResult().getType());
2998 auto initialComplex =
2999 rewriter.create<mlir::LLVM::PoisonOp>(op->getLoc(), complexLLVMTy);
3001 auto realComplex = rewriter.create<mlir::LLVM::InsertValueOp>(
3002 op->getLoc(), initialComplex, newReal, 0);
3004 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(op, realComplex,
3007 return mlir::success();
3011 cir::ComplexImagOp op, OpAdaptor adaptor,
3012 mlir::ConversionPatternRewriter &rewriter)
const {
3013 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
3014 rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractValueOp>(
3016 return mlir::success();
3020 mlir::MLIRContext *context,
3021 unsigned &storageSize) {
3022 return TypeSwitch<mlir::Type, mlir::IntegerType>(storageType)
3023 .Case<cir::ArrayType>([&](cir::ArrayType atTy) {
3024 storageSize = atTy.getSize() * 8;
3025 return mlir::IntegerType::get(context, storageSize);
3027 .Case<cir::IntType>([&](cir::IntType intTy) {
3028 storageSize = intTy.getWidth();
3029 return mlir::IntegerType::get(context, storageSize);
3031 .Default([](mlir::Type) -> mlir::IntegerType {
3033 "Either ArrayType or IntType expected for bitfields storage");
3038 cir::SetBitfieldOp op, OpAdaptor adaptor,
3039 mlir::ConversionPatternRewriter &rewriter)
const {
3040 mlir::OpBuilder::InsertionGuard guard(rewriter);
3041 rewriter.setInsertionPoint(op);
3043 cir::BitfieldInfoAttr info = op.getBitfieldInfo();
3044 uint64_t size = info.getSize();
3045 uint64_t offset = info.getOffset();
3046 mlir::Type storageType = info.getStorageType();
3047 mlir::MLIRContext *context = storageType.getContext();
3049 unsigned storageSize = 0;
3051 mlir::IntegerType intType =
3054 mlir::Value srcVal =
createIntCast(rewriter, adaptor.getSrc(), intType);
3055 unsigned srcWidth = storageSize;
3056 mlir::Value resultVal = srcVal;
3058 if (storageSize != size) {
3059 assert(storageSize > size &&
"Invalid bitfield size.");
3061 mlir::Value val = rewriter.create<mlir::LLVM::LoadOp>(
3062 op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(),
3063 op.getIsVolatile());
3066 createAnd(rewriter, srcVal, llvm::APInt::getLowBitsSet(srcWidth, size));
3068 srcVal =
createShL(rewriter, srcVal, offset);
3072 ~llvm::APInt::getBitsSet(srcWidth, offset, offset + size));
3075 srcVal = rewriter.create<mlir::LLVM::OrOp>(op.getLoc(), val, srcVal);
3078 rewriter.create<mlir::LLVM::StoreOp>(op.getLoc(), srcVal, adaptor.getAddr(),
3079 op.getAlignment(), op.getIsVolatile());
3081 mlir::Type resultTy = getTypeConverter()->convertType(op.getType());
3083 if (info.getIsSigned()) {
3084 assert(size <= storageSize);
3085 unsigned highBits = storageSize - size;
3088 resultVal =
createShL(rewriter, resultVal, highBits);
3089 resultVal =
createAShR(rewriter, resultVal, highBits);
3094 mlir::cast<mlir::IntegerType>(resultTy),
3095 info.getIsSigned());
3097 rewriter.replaceOp(op, resultVal);
3098 return mlir::success();
3102 cir::ComplexImagPtrOp op, OpAdaptor adaptor,
3103 mlir::ConversionPatternRewriter &rewriter)
const {
3104 cir::PointerType operandTy = op.getOperand().getType();
3105 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
3106 mlir::Type elementLLVMTy =
3107 getTypeConverter()->convertType(operandTy.getPointee());
3109 mlir::LLVM::GEPArg gepIndices[2] = {{0}, {1}};
3110 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
3111 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
3112 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
3113 op, resultLLVMTy, elementLLVMTy, adaptor.getOperand(), gepIndices,
3115 return mlir::success();
3119 cir::ComplexRealPtrOp op, OpAdaptor adaptor,
3120 mlir::ConversionPatternRewriter &rewriter)
const {
3121 cir::PointerType operandTy = op.getOperand().getType();
3122 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
3123 mlir::Type elementLLVMTy =
3124 getTypeConverter()->convertType(operandTy.getPointee());
3126 mlir::LLVM::GEPArg gepIndices[2] = {0, 0};
3127 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
3128 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
3129 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
3130 op, resultLLVMTy, elementLLVMTy, adaptor.getOperand(), gepIndices,
3132 return mlir::success();
3136 cir::GetBitfieldOp op, OpAdaptor adaptor,
3137 mlir::ConversionPatternRewriter &rewriter)
const {
3139 mlir::OpBuilder::InsertionGuard guard(rewriter);
3140 rewriter.setInsertionPoint(op);
3142 cir::BitfieldInfoAttr info = op.getBitfieldInfo();
3143 uint64_t size = info.getSize();
3144 uint64_t offset = info.getOffset();
3145 mlir::Type storageType = info.getStorageType();
3146 mlir::MLIRContext *context = storageType.getContext();
3147 unsigned storageSize = 0;
3149 mlir::IntegerType intType =
3152 mlir::Value val = rewriter.create<mlir::LLVM::LoadOp>(
3153 op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(),
3154 op.getIsVolatile());
3155 val = rewriter.create<mlir::LLVM::BitcastOp>(op.getLoc(), intType, val);
3157 if (info.getIsSigned()) {
3158 assert(
static_cast<unsigned>(offset + size) <= storageSize);
3159 unsigned highBits = storageSize - offset - size;
3160 val =
createShL(rewriter, val, highBits);
3161 val =
createAShR(rewriter, val, offset + highBits);
3165 if (
static_cast<unsigned>(offset) + size < storageSize)
3167 llvm::APInt::getLowBitsSet(storageSize, size));
3170 mlir::Type resTy = getTypeConverter()->convertType(op.getType());
3172 rewriter, val, mlir::cast<mlir::IntegerType>(resTy), info.getIsSigned());
3173 rewriter.replaceOp(op, newOp);
3174 return mlir::success();
3178 cir::InlineAsmOp op, OpAdaptor adaptor,
3179 mlir::ConversionPatternRewriter &rewriter)
const {
3181 if (op.getNumResults())
3182 llResTy = getTypeConverter()->convertType(op.getType(0));
3184 cir::AsmFlavor dialect = op.getAsmFlavor();
3185 mlir::LLVM::AsmDialect llDialect = dialect == cir::AsmFlavor::x86_att
3186 ? mlir::LLVM::AsmDialect::AD_ATT
3187 : mlir::LLVM::AsmDialect::AD_Intel;
3190 StringRef llvmAttrName = mlir::LLVM::InlineAsmOp::getElementTypeAttrName();
3196 if (!op.getNumResults())
3197 opAttrs.push_back(mlir::Attribute());
3201 for (
auto const &[llvmOp, cirOp] :
3202 zip(adaptor.getAsmOperands(), op.getAsmOperands())) {
3203 append_range(llvmOperands, llvmOp);
3204 append_range(cirOperands, cirOp);
3209 for (
auto const &[cirOpAttr, cirOp] :
3210 zip(op.getOperandAttrs(), cirOperands)) {
3212 opAttrs.push_back(mlir::Attribute());
3217 cir::PointerType typ = mlir::cast<cir::PointerType>(cirOp.getType());
3219 *getTypeConverter(), dataLayout, typ.getPointee()));
3221 attrs.push_back(rewriter.getNamedAttr(llvmAttrName, typAttr));
3222 mlir::DictionaryAttr newDict = rewriter.getDictionaryAttr(attrs);
3223 opAttrs.push_back(newDict);
3226 rewriter.replaceOpWithNewOp<mlir::LLVM::InlineAsmOp>(
3227 op, llResTy, llvmOperands, op.getAsmStringAttr(), op.getConstraintsAttr(),
3228 op.getSideEffectsAttr(),
3231 mlir::LLVM::TailCallKindAttr::get(
3232 getContext(), mlir::LLVM::tailcallkind::TailCallKind::None),
3233 mlir::LLVM::AsmDialectAttr::get(getContext(), llDialect),
3234 rewriter.getArrayAttr(opAttrs));
3236 return mlir::success();
3240 cir::VAStartOp op, OpAdaptor adaptor,
3241 mlir::ConversionPatternRewriter &rewriter)
const {
3242 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
3243 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
3244 adaptor.getArgList());
3245 rewriter.replaceOpWithNewOp<mlir::LLVM::VaStartOp>(op, vaList);
3246 return mlir::success();
3250 cir::VAEndOp op, OpAdaptor adaptor,
3251 mlir::ConversionPatternRewriter &rewriter)
const {
3252 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
3253 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
3254 adaptor.getArgList());
3255 rewriter.replaceOpWithNewOp<mlir::LLVM::VaEndOp>(op, vaList);
3256 return mlir::success();
3260 cir::VAArgOp op, OpAdaptor adaptor,
3261 mlir::ConversionPatternRewriter &rewriter)
const {
3263 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
3264 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
3265 adaptor.getArgList());
3267 mlir::Type llvmType =
3268 getTypeConverter()->convertType(op->getResultTypes().front());
3270 return mlir::failure();
3272 rewriter.replaceOpWithNewOp<mlir::LLVM::VaArgOp>(op, llvmType, vaList);
3273 return mlir::success();
3277 return std::make_unique<ConvertCIRToLLVMPass>();
3285std::unique_ptr<llvm::Module>
3287 llvm::TimeTraceScope scope(
"lower from CIR to LLVM directly");
3289 mlir::MLIRContext *mlirCtx = mlirModule.getContext();
3291 mlir::PassManager pm(mlirCtx);
3294 (void)mlir::applyPassManagerCLOptions(pm);
3296 if (mlir::failed(pm.run(mlirModule))) {
3299 "The pass manager failed to lower CIR to LLVMIR dialect!");
3302 mlir::registerBuiltinDialectTranslation(*mlirCtx);
3303 mlir::registerLLVMDialectTranslation(*mlirCtx);
3306 llvm::TimeTraceScope translateScope(
"translateModuleToLLVMIR");
3308 StringRef moduleName = mlirModule.getName().value_or(
"CIRToLLVMModule");
3309 std::unique_ptr<llvm::Module> llvmModule =
3310 mlir::translateModuleToLLVMIR(mlirModule, llvmCtx, moduleName);
3314 report_fatal_error(
"Lowering from LLVMIR dialect to llvm IR failed!");
static bool isUnsigned(SValBuilder &SVB, NonLoc Value)
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)
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)
mlir::LogicalResult matchAndRewrite(cir::AllocaOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::AssumeAlignedOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::AssumeOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::AssumeSepStorageOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::BaseClassAddrOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::BinOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::BitClrsbOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::BitClzOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::BitCtzOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::BitFfsOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::BitParityOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::BitPopcountOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::BitReverseOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::BrCondOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::BrOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::ByteSwapOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::CallOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const override
mlir::LogicalResult matchAndRewrite(cir::CastOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::CmpOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::ComplexAddOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::ComplexCreateOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::ComplexImagOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::ComplexImagPtrOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::ComplexRealOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::ComplexRealPtrOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::ComplexSubOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::ConstantOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::ExpectOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::FAbsOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::FrameAddrOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::FuncOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::GetBitfieldOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::GetGlobalOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::GetMemberOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::GlobalOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const override
mlir::LogicalResult matchAndRewrite(cir::InlineAsmOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::LoadOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::PtrStrideOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::ReturnAddrOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::ReturnOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::RotateOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::SelectOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::SetBitfieldOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::ShiftOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::StackRestoreOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const override
mlir::LogicalResult matchAndRewrite(cir::StackSaveOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::StoreOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::SwitchFlatOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::ThrowOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::TrapOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::UnaryOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::UnreachableOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::VAArgOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::VAEndOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::VAStartOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::VTTAddrPointOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::VTableAddrPointOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::VTableGetVPtrOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::VTableGetVirtualFnAddrOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::VecCmpOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::VecCreateOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::VecInsertOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::VecShuffleDynamicOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::VecShuffleOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::VecSplatOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
mlir::LogicalResult matchAndRewrite(cir::VecTernaryOp op, OpAdaptor, mlir::ConversionPatternRewriter &) const override
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)
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::ICmpPredicate convertCmpKindToICmpPredicate(cir::CmpOpKind kind, bool isSigned)
Convert from a CIR comparison kind to an LLVM IR integral comparison kind.
static mlir::Value getLLVMIntCast(mlir::ConversionPatternRewriter &rewriter, mlir::Value llvmSrc, mlir::Type llvmDstIntTy, bool isUnsigned, uint64_t cirSrcWidth, uint64_t cirDstIntWidth)
void convertSideEffectForCall(mlir::Operation *callOp, bool isNothrow, cir::SideEffect sideEffect, mlir::LLVM::MemoryEffectsAttr &memoryEffect, bool &noUnwind, bool &willReturn)
static mlir::Value emitFromMemory(mlir::ConversionPatternRewriter &rewriter, mlir::DataLayout const &dataLayout, cir::LoadOp op, mlir::Value value)
Emits the value from memory as expected by its users.
mlir::IntegerType computeBitfieldIntType(mlir::Type storageType, mlir::MLIRContext *context, unsigned &storageSize)
static mlir::LLVM::CallIntrinsicOp createCallLLVMIntrinsicOp(mlir::ConversionPatternRewriter &rewriter, mlir::Location loc, const llvm::Twine &intrinsicName, mlir::Type resultTy, mlir::ValueRange operands)
bool hasTrailingZeros(cir::ConstArrayAttr attr)
static mlir::LogicalResult rewriteCallOrInvoke(mlir::Operation *op, mlir::ValueRange callOperands, mlir::ConversionPatternRewriter &rewriter, const mlir::TypeConverter *converter, mlir::FlatSymbolRefAttr calleeAttr)
std::unique_ptr< llvm::Module > lowerDirectlyFromCIRToLLVMIR(mlir::ModuleOp mlirModule, llvm::LLVMContext &llvmCtx)
mlir::Value lowerCirAttrAsValue(mlir::Operation *parentOp, const mlir::Attribute attr, mlir::ConversionPatternRewriter &rewriter, const mlir::TypeConverter *converter)
Switches on the type of attribute and calls the appropriate conversion.
static mlir::LLVM::CallIntrinsicOp replaceOpWithCallLLVMIntrinsicOp(mlir::ConversionPatternRewriter &rewriter, mlir::Operation *op, const llvm::Twine &intrinsicName, mlir::Type resultTy, mlir::ValueRange operands)
static void prepareTypeConverter(mlir::LLVMTypeConverter &converter, mlir::DataLayout &dataLayout)
static mlir::LLVM::AtomicOrdering getLLVMMemOrder(std::optional< cir::MemOrder > memorder)
std::unique_ptr< mlir::Pass > createConvertCIRToLLVMPass()
Create a pass that fully lowers CIR to the LLVMIR dialect.
static 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)
void populateCIRToLLVMPasses(mlir::OpPassManager &pm)
Adds passes that fully lower CIR to the LLVMIR dialect.
mlir::LLVM::Linkage convertLinkage(cir::GlobalLinkageKind linkage)
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)
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.
char __ovld __cnfn select(char, char, char)
For each component of a vector type, result[i] = if MSB of c[i] is set ? b[i] : a[i].
static bool dataMemberType()
static bool opGlobalConstant()
static bool addressSpace()
static bool opGlobalThreadLocal()
static bool globalViewIntLowering()
static bool opAllocaAnnotations()
static bool opLoadStoreTbaa()
static bool optInfoAttr()
static bool opFuncExtraAttrs()
static bool opCallLandingPad()
static bool vaArgABILowering()
static bool fpConstraints()
static bool lowerModeOptLevel()
static bool opCallCallConv()
static bool opFuncCallingConv()
static bool fastMathFlags()
static bool opCallContinueBlock()
static bool opLoadStoreNontemporal()
static bool opFuncMultipleReturnVals()
static bool opAllocaDynAllocSize()
void runOnOperation() final
StringRef getDescription() const override
StringRef getArgument() const override
void getDependentDialects(mlir::DialectRegistry ®istry) const override
void processCIRAttrs(mlir::ModuleOp module)