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");
176mlir::LogicalResult CIRToLLVMCopyOpLowering::matchAndRewrite(
177 cir::CopyOp op, OpAdaptor adaptor,
178 mlir::ConversionPatternRewriter &rewriter)
const {
179 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
180 const mlir::Value
length = mlir::LLVM::ConstantOp::create(
181 rewriter, op.getLoc(), rewriter.getI32Type(), op.getLength(layout));
183 rewriter.replaceOpWithNewOp<mlir::LLVM::MemcpyOp>(
184 op, adaptor.getDst(), adaptor.getSrc(),
length,
false);
185 return mlir::success();
188mlir::LogicalResult CIRToLLVMCosOpLowering::matchAndRewrite(
189 cir::CosOp op, OpAdaptor adaptor,
190 mlir::ConversionPatternRewriter &rewriter)
const {
191 mlir::Type resTy = typeConverter->convertType(op.getType());
192 rewriter.replaceOpWithNewOp<mlir::LLVM::CosOp>(op, resTy, adaptor.getSrc());
193 return mlir::success();
197 mlir::Value llvmSrc, mlir::Type llvmDstIntTy,
199 uint64_t cirDstIntWidth) {
200 if (cirSrcWidth == cirDstIntWidth)
203 auto loc = llvmSrc.getLoc();
204 if (cirSrcWidth < cirDstIntWidth) {
206 return rewriter.create<mlir::LLVM::ZExtOp>(loc, llvmDstIntTy, llvmSrc);
207 return rewriter.create<mlir::LLVM::SExtOp>(loc, llvmDstIntTy, llvmSrc);
211 return rewriter.create<mlir::LLVM::TruncOp>(loc, llvmDstIntTy, llvmSrc);
217 mlir::ConversionPatternRewriter &rewriter,
218 const mlir::TypeConverter *converter)
219 : parentOp(parentOp), rewriter(rewriter), converter(converter) {}
221 mlir::Value
visit(mlir::Attribute attr) {
222 return llvm::TypeSwitch<mlir::Attribute, mlir::Value>(attr)
223 .Case<cir::IntAttr, cir::FPAttr, cir::ConstComplexAttr,
224 cir::ConstArrayAttr, cir::ConstRecordAttr, cir::ConstVectorAttr,
225 cir::ConstPtrAttr, cir::GlobalViewAttr, cir::TypeInfoAttr,
226 cir::VTableAttr, cir::ZeroAttr>(
228 .Default([&](
auto attrT) {
return mlir::Value(); });
233 mlir::Value
visitCirAttr(cir::ConstComplexAttr complexAttr);
244 mlir::Operation *parentOp;
245 mlir::ConversionPatternRewriter &rewriter;
246 const mlir::TypeConverter *converter;
251 const mlir::Attribute attr,
252 mlir::ConversionPatternRewriter &rewriter,
253 const mlir::TypeConverter *converter) {
255 mlir::Value value = valueConverter.
visit(attr);
257 llvm_unreachable(
"unhandled attribute type");
262 cir::SideEffect sideEffect,
263 mlir::LLVM::MemoryEffectsAttr &memoryEffect,
264 bool &noUnwind,
bool &willReturn) {
265 using mlir::LLVM::ModRefInfo;
267 switch (sideEffect) {
268 case cir::SideEffect::All:
270 noUnwind = isNothrow;
274 case cir::SideEffect::Pure:
275 memoryEffect = mlir::LLVM::MemoryEffectsAttr::get(
276 callOp->getContext(), ModRefInfo::Ref,
283 case cir::SideEffect::Const:
284 memoryEffect = mlir::LLVM::MemoryEffectsAttr::get(
285 callOp->getContext(), ModRefInfo::NoModRef,
286 ModRefInfo::NoModRef,
287 ModRefInfo::NoModRef);
294static mlir::LLVM::CallIntrinsicOp
296 mlir::Location loc,
const llvm::Twine &intrinsicName,
297 mlir::Type resultTy, mlir::ValueRange operands) {
298 auto intrinsicNameAttr =
299 mlir::StringAttr::get(rewriter.getContext(), intrinsicName);
300 return mlir::LLVM::CallIntrinsicOp::create(rewriter, loc, resultTy,
301 intrinsicNameAttr, operands);
305 mlir::ConversionPatternRewriter &rewriter, mlir::Operation *op,
306 const llvm::Twine &intrinsicName, mlir::Type resultTy,
307 mlir::ValueRange operands) {
309 rewriter, op->getLoc(), intrinsicName, resultTy, operands);
310 rewriter.replaceOp(op, callIntrinOp.getOperation());
316 mlir::Location loc = parentOp->getLoc();
317 return rewriter.create<mlir::LLVM::ConstantOp>(
318 loc, converter->convertType(intAttr.getType()), intAttr.getValue());
323 mlir::Location loc = parentOp->getLoc();
324 return rewriter.create<mlir::LLVM::ConstantOp>(
325 loc, converter->convertType(fltAttr.getType()), fltAttr.getValue());
330 auto complexType = mlir::cast<cir::ComplexType>(complexAttr.getType());
331 mlir::Type complexElemTy = complexType.getElementType();
332 mlir::Type complexElemLLVMTy = converter->convertType(complexElemTy);
334 mlir::Attribute components[2];
335 if (
const auto intType = mlir::dyn_cast<cir::IntType>(complexElemTy)) {
336 components[0] = rewriter.getIntegerAttr(
338 mlir::cast<cir::IntAttr>(complexAttr.getReal()).getValue());
339 components[1] = rewriter.getIntegerAttr(
341 mlir::cast<cir::IntAttr>(complexAttr.getImag()).getValue());
343 components[0] = rewriter.getFloatAttr(
345 mlir::cast<cir::FPAttr>(complexAttr.getReal()).getValue());
346 components[1] = rewriter.getFloatAttr(
348 mlir::cast<cir::FPAttr>(complexAttr.getImag()).getValue());
351 mlir::Location loc = parentOp->getLoc();
352 return rewriter.create<mlir::LLVM::ConstantOp>(
353 loc, converter->convertType(complexAttr.getType()),
354 rewriter.getArrayAttr(components));
359 mlir::Location loc = parentOp->getLoc();
360 if (ptrAttr.isNullValue()) {
361 return rewriter.create<mlir::LLVM::ZeroOp>(
362 loc, converter->convertType(ptrAttr.getType()));
364 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
365 mlir::Value ptrVal = rewriter.create<mlir::LLVM::ConstantOp>(
366 loc, rewriter.getIntegerType(layout.getTypeSizeInBits(ptrAttr.getType())),
367 ptrAttr.getValue().getInt());
368 return rewriter.create<mlir::LLVM::IntToPtrOp>(
369 loc, converter->convertType(ptrAttr.getType()), ptrVal);
374 mlir::Type llvmTy = converter->convertType(attr.getType());
375 mlir::Location loc = parentOp->getLoc();
378 if (attr.hasTrailingZeros()) {
379 mlir::Type arrayTy = attr.getType();
380 result = rewriter.create<mlir::LLVM::ZeroOp>(
381 loc, converter->convertType(arrayTy));
383 result = rewriter.create<mlir::LLVM::UndefOp>(loc, llvmTy);
387 if (
auto arrayAttr = mlir::dyn_cast<mlir::ArrayAttr>(attr.getElts())) {
388 for (
auto [idx, elt] : llvm::enumerate(arrayAttr)) {
389 mlir::DataLayout dataLayout(parentOp->getParentOfType<mlir::ModuleOp>());
390 mlir::Value init =
visit(elt);
392 rewriter.create<mlir::LLVM::InsertValueOp>(loc, result, init, idx);
394 }
else if (
auto strAttr = mlir::dyn_cast<mlir::StringAttr>(attr.getElts())) {
397 auto arrayTy = mlir::dyn_cast<cir::ArrayType>(strAttr.getType());
398 assert(arrayTy &&
"String attribute must have an array type");
399 mlir::Type eltTy = arrayTy.getElementType();
400 for (
auto [idx, elt] : llvm::enumerate(strAttr)) {
401 auto init = rewriter.create<mlir::LLVM::ConstantOp>(
402 loc, converter->convertType(eltTy), elt);
404 rewriter.create<mlir::LLVM::InsertValueOp>(loc, result, init, idx);
407 llvm_unreachable(
"unexpected ConstArrayAttr elements");
415 const mlir::Type llvmTy = converter->convertType(constRecord.getType());
416 const mlir::Location loc = parentOp->getLoc();
417 mlir::Value result = rewriter.create<mlir::LLVM::UndefOp>(loc, llvmTy);
420 for (
auto [idx, elt] : llvm::enumerate(constRecord.getMembers())) {
421 mlir::Value init =
visit(elt);
422 result = rewriter.create<mlir::LLVM::InsertValueOp>(loc, result, init, idx);
430 const mlir::Type llvmTy = converter->convertType(attr.getType());
431 const mlir::Location loc = parentOp->getLoc();
434 for (
const mlir::Attribute elementAttr : attr.getElts()) {
435 mlir::Attribute mlirAttr;
436 if (
auto intAttr = mlir::dyn_cast<cir::IntAttr>(elementAttr)) {
437 mlirAttr = rewriter.getIntegerAttr(
438 converter->convertType(intAttr.getType()), intAttr.getValue());
439 }
else if (
auto floatAttr = mlir::dyn_cast<cir::FPAttr>(elementAttr)) {
440 mlirAttr = rewriter.getFloatAttr(
441 converter->convertType(floatAttr.getType()), floatAttr.getValue());
444 "vector constant with an element that is neither an int nor a float");
446 mlirValues.push_back(mlirAttr);
449 return rewriter.create<mlir::LLVM::ConstantOp>(
451 mlir::DenseElementsAttr::get(mlir::cast<mlir::ShapedType>(llvmTy),
457 auto moduleOp = parentOp->getParentOfType<mlir::ModuleOp>();
458 mlir::DataLayout dataLayout(moduleOp);
459 mlir::Type sourceType;
461 llvm::StringRef symName;
462 mlir::Operation *sourceSymbol =
463 mlir::SymbolTable::lookupSymbolIn(moduleOp, globalAttr.getSymbol());
464 if (
auto llvmSymbol = dyn_cast<mlir::LLVM::GlobalOp>(sourceSymbol)) {
465 sourceType = llvmSymbol.getType();
466 symName = llvmSymbol.getSymName();
467 }
else if (
auto cirSymbol = dyn_cast<cir::GlobalOp>(sourceSymbol)) {
470 symName = cirSymbol.getSymName();
471 }
else if (
auto llvmFun = dyn_cast<mlir::LLVM::LLVMFuncOp>(sourceSymbol)) {
472 sourceType = llvmFun.getFunctionType();
473 symName = llvmFun.getSymName();
474 }
else if (
auto fun = dyn_cast<cir::FuncOp>(sourceSymbol)) {
475 sourceType = converter->convertType(fun.getFunctionType());
476 symName = fun.getSymName();
477 }
else if (
auto alias = dyn_cast<mlir::LLVM::AliasOp>(sourceSymbol)) {
478 sourceType = alias.getType();
479 symName = alias.getSymName();
481 llvm_unreachable(
"Unexpected GlobalOp type");
484 mlir::Location loc = parentOp->getLoc();
485 mlir::Value addrOp = rewriter.create<mlir::LLVM::AddressOfOp>(
486 loc, mlir::LLVM::LLVMPointerType::get(rewriter.getContext()), symName);
488 if (globalAttr.getIndices()) {
491 if (mlir::isa<mlir::LLVM::LLVMArrayType, mlir::LLVM::LLVMStructType>(
493 indices.push_back(0);
495 for (mlir::Attribute idx : globalAttr.getIndices()) {
496 auto intAttr = mlir::cast<mlir::IntegerAttr>(idx);
497 indices.push_back(intAttr.getValue().getSExtValue());
499 mlir::Type resTy = addrOp.getType();
500 mlir::Type eltTy = converter->convertType(sourceType);
501 addrOp = rewriter.create<mlir::LLVM::GEPOp>(
502 loc, resTy, eltTy, addrOp, indices, mlir::LLVM::GEPNoWrapFlags::none);
511 if (
auto ptrTy = mlir::dyn_cast<cir::PointerType>(globalAttr.getType())) {
512 mlir::Type llvmEltTy =
515 if (llvmEltTy == sourceType)
518 mlir::Type llvmDstTy = converter->convertType(globalAttr.getType());
519 return rewriter.create<mlir::LLVM::BitcastOp>(parentOp->getLoc(), llvmDstTy,
523 llvm_unreachable(
"Expecting pointer or integer type for GlobalViewAttr");
528 mlir::Type llvmTy = converter->convertType(typeInfoAttr.getType());
529 mlir::Location loc = parentOp->getLoc();
530 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
532 for (
auto [idx, elt] : llvm::enumerate(typeInfoAttr.getData())) {
533 mlir::Value init =
visit(elt);
535 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
543 mlir::Type llvmTy = converter->convertType(vtableArr.getType());
544 mlir::Location loc = parentOp->getLoc();
545 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
547 for (
auto [idx, elt] : llvm::enumerate(vtableArr.getData())) {
548 mlir::Value init =
visit(elt);
550 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
558 mlir::Location loc = parentOp->getLoc();
559 return rewriter.create<mlir::LLVM::ZeroOp>(
560 loc, converter->convertType(attr.getType()));
568 mlir::ConversionPatternRewriter &rewriter)
569 : llvmType(type), rewriter(rewriter) {}
571 mlir::Attribute
visit(mlir::Attribute attr) {
572 return llvm::TypeSwitch<mlir::Attribute, mlir::Attribute>(attr)
573 .Case<cir::IntAttr, cir::FPAttr, cir::BoolAttr>(
575 .Default([&](
auto attrT) {
return mlir::Attribute(); });
579 return rewriter.getIntegerAttr(llvmType, attr.getValue());
583 return rewriter.getFloatAttr(llvmType, attr.getValue());
587 return rewriter.getBoolAttr(attr.getValue());
592 mlir::ConversionPatternRewriter &rewriter;
600 :
public mlir::PassWrapper<ConvertCIRToLLVMPass,
601 mlir::OperationPass<mlir::ModuleOp>> {
603 registry.insert<mlir::BuiltinDialect, mlir::DLTIDialect,
604 mlir::LLVM::LLVMDialect, mlir::func::FuncDialect>();
611 return "Convert the prepared CIR dialect module to LLVM dialect";
614 StringRef
getArgument()
const override {
return "cir-flat-to-llvm"; }
617mlir::LogicalResult CIRToLLVMACosOpLowering::matchAndRewrite(
618 cir::ACosOp op, OpAdaptor adaptor,
619 mlir::ConversionPatternRewriter &rewriter)
const {
620 mlir::Type resTy = typeConverter->convertType(op.getType());
621 rewriter.replaceOpWithNewOp<mlir::LLVM::ACosOp>(op, resTy,
622 adaptor.getOperands()[0]);
623 return mlir::success();
626mlir::LogicalResult CIRToLLVMASinOpLowering::matchAndRewrite(
627 cir::ASinOp op, OpAdaptor adaptor,
628 mlir::ConversionPatternRewriter &rewriter)
const {
629 mlir::Type resTy = typeConverter->convertType(op.getType());
630 rewriter.replaceOpWithNewOp<mlir::LLVM::ASinOp>(op, resTy, adaptor.getSrc());
631 return mlir::success();
634mlir::LogicalResult CIRToLLVMAssumeOpLowering::matchAndRewrite(
635 cir::AssumeOp op, OpAdaptor adaptor,
636 mlir::ConversionPatternRewriter &rewriter)
const {
637 auto cond = adaptor.getPredicate();
638 rewriter.replaceOpWithNewOp<mlir::LLVM::AssumeOp>(op, cond);
639 return mlir::success();
642mlir::LogicalResult CIRToLLVMAssumeAlignedOpLowering::matchAndRewrite(
643 cir::AssumeAlignedOp op, OpAdaptor adaptor,
644 mlir::ConversionPatternRewriter &rewriter)
const {
645 SmallVector<mlir::Value, 3> opBundleArgs{adaptor.getPointer()};
647 auto alignment = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
648 adaptor.getAlignmentAttr());
649 opBundleArgs.push_back(alignment);
651 if (mlir::Value offset = adaptor.getOffset())
652 opBundleArgs.push_back(offset);
654 auto cond = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
655 rewriter.getI1Type(), 1);
656 mlir::LLVM::AssumeOp::create(rewriter, op.getLoc(), cond,
"align",
661 rewriter.replaceOp(op, adaptor.getPointer());
662 return mlir::success();
665mlir::LogicalResult CIRToLLVMAssumeSepStorageOpLowering::matchAndRewrite(
666 cir::AssumeSepStorageOp op, OpAdaptor adaptor,
667 mlir::ConversionPatternRewriter &rewriter)
const {
668 auto cond = rewriter.create<mlir::LLVM::ConstantOp>(op.getLoc(),
669 rewriter.getI1Type(), 1);
670 rewriter.replaceOpWithNewOp<mlir::LLVM::AssumeOp>(
671 op, cond, mlir::LLVM::AssumeSeparateStorageTag{}, adaptor.getPtr1(),
673 return mlir::success();
676static mlir::LLVM::AtomicOrdering
679 return mlir::LLVM::AtomicOrdering::not_atomic;
681 case cir::MemOrder::Relaxed:
682 return mlir::LLVM::AtomicOrdering::monotonic;
683 case cir::MemOrder::Consume:
684 case cir::MemOrder::Acquire:
685 return mlir::LLVM::AtomicOrdering::acquire;
686 case cir::MemOrder::Release:
687 return mlir::LLVM::AtomicOrdering::release;
688 case cir::MemOrder::AcquireRelease:
689 return mlir::LLVM::AtomicOrdering::acq_rel;
690 case cir::MemOrder::SequentiallyConsistent:
691 return mlir::LLVM::AtomicOrdering::seq_cst;
693 llvm_unreachable(
"unknown memory order");
696mlir::LogicalResult CIRToLLVMAtomicCmpXchgLowering::matchAndRewrite(
697 cir::AtomicCmpXchg op, OpAdaptor adaptor,
698 mlir::ConversionPatternRewriter &rewriter)
const {
699 mlir::Value expected = adaptor.getExpected();
700 mlir::Value desired = adaptor.getDesired();
702 auto cmpxchg = mlir::LLVM::AtomicCmpXchgOp::create(
703 rewriter, op.getLoc(), adaptor.getPtr(), expected, desired,
707 cmpxchg.setAlignment(adaptor.getAlignment());
708 cmpxchg.setWeak(adaptor.getWeak());
709 cmpxchg.setVolatile_(adaptor.getIsVolatile());
712 auto old = mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(),
713 cmpxchg.getResult(), 0);
714 auto cmp = mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(),
715 cmpxchg.getResult(), 1);
717 rewriter.replaceOp(op, {old, cmp});
718 return mlir::success();
721mlir::LogicalResult CIRToLLVMAtomicXchgLowering::matchAndRewrite(
722 cir::AtomicXchg op, OpAdaptor adaptor,
723 mlir::ConversionPatternRewriter &rewriter)
const {
725 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(adaptor.getMemOrder());
726 rewriter.replaceOpWithNewOp<mlir::LLVM::AtomicRMWOp>(
727 op, mlir::LLVM::AtomicBinOp::xchg, adaptor.getPtr(), adaptor.getVal(),
729 return mlir::success();
732mlir::LogicalResult CIRToLLVMBitClrsbOpLowering::matchAndRewrite(
733 cir::BitClrsbOp op, OpAdaptor adaptor,
734 mlir::ConversionPatternRewriter &rewriter)
const {
735 auto zero = rewriter.create<mlir::LLVM::ConstantOp>(
736 op.getLoc(), adaptor.getInput().getType(), 0);
737 auto isNeg = rewriter.create<mlir::LLVM::ICmpOp>(
739 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(),
740 mlir::LLVM::ICmpPredicate::slt),
741 adaptor.getInput(), zero);
743 auto negOne = rewriter.create<mlir::LLVM::ConstantOp>(
744 op.getLoc(), adaptor.getInput().getType(), -1);
745 auto flipped = rewriter.create<mlir::LLVM::XOrOp>(op.getLoc(),
746 adaptor.getInput(), negOne);
748 auto select = rewriter.create<mlir::LLVM::SelectOp>(
749 op.getLoc(), isNeg, flipped, adaptor.getInput());
751 auto resTy = getTypeConverter()->convertType(op.getType());
752 auto clz = rewriter.create<mlir::LLVM::CountLeadingZerosOp>(
753 op.getLoc(), resTy,
select,
false);
755 auto one = rewriter.create<mlir::LLVM::ConstantOp>(op.getLoc(), resTy, 1);
756 auto res = rewriter.create<mlir::LLVM::SubOp>(op.getLoc(),
clz, one);
757 rewriter.replaceOp(op, res);
759 return mlir::LogicalResult::success();
762mlir::LogicalResult CIRToLLVMBitClzOpLowering::matchAndRewrite(
763 cir::BitClzOp op, OpAdaptor adaptor,
764 mlir::ConversionPatternRewriter &rewriter)
const {
765 auto resTy = getTypeConverter()->convertType(op.getType());
766 auto llvmOp = rewriter.create<mlir::LLVM::CountLeadingZerosOp>(
767 op.getLoc(), resTy, adaptor.getInput(), op.getPoisonZero());
768 rewriter.replaceOp(op, llvmOp);
769 return mlir::LogicalResult::success();
772mlir::LogicalResult CIRToLLVMBitCtzOpLowering::matchAndRewrite(
773 cir::BitCtzOp op, OpAdaptor adaptor,
774 mlir::ConversionPatternRewriter &rewriter)
const {
775 auto resTy = getTypeConverter()->convertType(op.getType());
776 auto llvmOp = rewriter.create<mlir::LLVM::CountTrailingZerosOp>(
777 op.getLoc(), resTy, adaptor.getInput(), op.getPoisonZero());
778 rewriter.replaceOp(op, llvmOp);
779 return mlir::LogicalResult::success();
782mlir::LogicalResult CIRToLLVMBitFfsOpLowering::matchAndRewrite(
783 cir::BitFfsOp op, OpAdaptor adaptor,
784 mlir::ConversionPatternRewriter &rewriter)
const {
785 auto resTy = getTypeConverter()->convertType(op.getType());
786 auto ctz = rewriter.create<mlir::LLVM::CountTrailingZerosOp>(
787 op.getLoc(), resTy, adaptor.getInput(),
true);
789 auto one = rewriter.create<mlir::LLVM::ConstantOp>(op.getLoc(), resTy, 1);
790 auto ctzAddOne = rewriter.create<mlir::LLVM::AddOp>(op.getLoc(),
ctz, one);
792 auto zeroInputTy = rewriter.create<mlir::LLVM::ConstantOp>(
793 op.getLoc(), adaptor.getInput().getType(), 0);
794 auto isZero = rewriter.create<mlir::LLVM::ICmpOp>(
796 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(),
797 mlir::LLVM::ICmpPredicate::eq),
798 adaptor.getInput(), zeroInputTy);
800 auto zero = rewriter.create<mlir::LLVM::ConstantOp>(op.getLoc(), resTy, 0);
801 auto res = rewriter.create<mlir::LLVM::SelectOp>(op.getLoc(), isZero, zero,
803 rewriter.replaceOp(op, res);
805 return mlir::LogicalResult::success();
808mlir::LogicalResult CIRToLLVMBitParityOpLowering::matchAndRewrite(
809 cir::BitParityOp op, OpAdaptor adaptor,
810 mlir::ConversionPatternRewriter &rewriter)
const {
811 auto resTy = getTypeConverter()->convertType(op.getType());
812 auto popcnt = rewriter.create<mlir::LLVM::CtPopOp>(op.getLoc(), resTy,
815 auto one = rewriter.create<mlir::LLVM::ConstantOp>(op.getLoc(), resTy, 1);
817 rewriter.create<mlir::LLVM::AndOp>(op.getLoc(), popcnt, one);
818 rewriter.replaceOp(op, popcntMod2);
820 return mlir::LogicalResult::success();
823mlir::LogicalResult CIRToLLVMBitPopcountOpLowering::matchAndRewrite(
824 cir::BitPopcountOp op, OpAdaptor adaptor,
825 mlir::ConversionPatternRewriter &rewriter)
const {
826 auto resTy = getTypeConverter()->convertType(op.getType());
827 auto llvmOp = rewriter.create<mlir::LLVM::CtPopOp>(op.getLoc(), resTy,
829 rewriter.replaceOp(op, llvmOp);
830 return mlir::LogicalResult::success();
833mlir::LogicalResult CIRToLLVMBitReverseOpLowering::matchAndRewrite(
834 cir::BitReverseOp op, OpAdaptor adaptor,
835 mlir::ConversionPatternRewriter &rewriter)
const {
836 rewriter.replaceOpWithNewOp<mlir::LLVM::BitReverseOp>(op, adaptor.getInput());
837 return mlir::success();
840mlir::LogicalResult CIRToLLVMBrCondOpLowering::matchAndRewrite(
841 cir::BrCondOp brOp, OpAdaptor adaptor,
842 mlir::ConversionPatternRewriter &rewriter)
const {
847 mlir::Value i1Condition = adaptor.getCond();
849 rewriter.replaceOpWithNewOp<mlir::LLVM::CondBrOp>(
850 brOp, i1Condition, brOp.getDestTrue(), adaptor.getDestOperandsTrue(),
851 brOp.getDestFalse(), adaptor.getDestOperandsFalse());
853 return mlir::success();
856mlir::LogicalResult CIRToLLVMByteSwapOpLowering::matchAndRewrite(
857 cir::ByteSwapOp op, OpAdaptor adaptor,
858 mlir::ConversionPatternRewriter &rewriter)
const {
859 rewriter.replaceOpWithNewOp<mlir::LLVM::ByteSwapOp>(op, adaptor.getInput());
860 return mlir::LogicalResult::success();
863mlir::Type CIRToLLVMCastOpLowering::convertTy(mlir::Type ty)
const {
864 return getTypeConverter()->convertType(ty);
867mlir::LogicalResult CIRToLLVMCastOpLowering::matchAndRewrite(
868 cir::CastOp castOp, OpAdaptor adaptor,
869 mlir::ConversionPatternRewriter &rewriter)
const {
874 switch (castOp.getKind()) {
875 case cir::CastKind::array_to_ptrdecay: {
876 const auto ptrTy = mlir::cast<cir::PointerType>(castOp.getType());
877 mlir::Value sourceValue = adaptor.getSrc();
878 mlir::Type targetType = convertTy(ptrTy);
881 llvm::SmallVector<mlir::LLVM::GEPArg> offset{0};
882 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
883 castOp, targetType, elementTy, sourceValue, offset);
886 case cir::CastKind::int_to_bool: {
887 mlir::Value llvmSrcVal = adaptor.getSrc();
888 mlir::Value zeroInt = rewriter.create<mlir::LLVM::ConstantOp>(
889 castOp.getLoc(), llvmSrcVal.getType(), 0);
890 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
891 castOp, mlir::LLVM::ICmpPredicate::ne, llvmSrcVal, zeroInt);
894 case cir::CastKind::integral: {
895 mlir::Type srcType = castOp.getSrc().getType();
896 mlir::Type dstType = castOp.getType();
897 mlir::Value llvmSrcVal = adaptor.getSrc();
898 mlir::Type llvmDstType = getTypeConverter()->convertType(dstType);
899 cir::IntType srcIntType =
900 mlir::cast<cir::IntType>(elementTypeIfVector(srcType));
901 cir::IntType dstIntType =
902 mlir::cast<cir::IntType>(elementTypeIfVector(dstType));
903 rewriter.replaceOp(castOp,
getLLVMIntCast(rewriter, llvmSrcVal, llvmDstType,
904 srcIntType.isUnsigned(),
905 srcIntType.getWidth(),
906 dstIntType.getWidth()));
909 case cir::CastKind::floating: {
910 mlir::Value llvmSrcVal = adaptor.getSrc();
911 mlir::Type llvmDstTy = getTypeConverter()->convertType(castOp.getType());
913 mlir::Type srcTy = elementTypeIfVector(castOp.getSrc().getType());
914 mlir::Type dstTy = elementTypeIfVector(castOp.getType());
916 if (!mlir::isa<cir::FPTypeInterface>(dstTy) ||
917 !mlir::isa<cir::FPTypeInterface>(srcTy))
918 return castOp.emitError() <<
"NYI cast from " << srcTy <<
" to " << dstTy;
920 auto getFloatWidth = [](mlir::Type ty) ->
unsigned {
921 return mlir::cast<cir::FPTypeInterface>(ty).getWidth();
924 if (getFloatWidth(srcTy) > getFloatWidth(dstTy))
925 rewriter.replaceOpWithNewOp<mlir::LLVM::FPTruncOp>(castOp, llvmDstTy,
928 rewriter.replaceOpWithNewOp<mlir::LLVM::FPExtOp>(castOp, llvmDstTy,
930 return mlir::success();
932 case cir::CastKind::int_to_ptr: {
933 auto dstTy = mlir::cast<cir::PointerType>(castOp.getType());
934 mlir::Value llvmSrcVal = adaptor.getSrc();
935 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
936 rewriter.replaceOpWithNewOp<mlir::LLVM::IntToPtrOp>(castOp, llvmDstTy,
938 return mlir::success();
940 case cir::CastKind::ptr_to_int: {
941 auto dstTy = mlir::cast<cir::IntType>(castOp.getType());
942 mlir::Value llvmSrcVal = adaptor.getSrc();
943 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
944 rewriter.replaceOpWithNewOp<mlir::LLVM::PtrToIntOp>(castOp, llvmDstTy,
946 return mlir::success();
948 case cir::CastKind::float_to_bool: {
949 mlir::Value llvmSrcVal = adaptor.getSrc();
950 auto kind = mlir::LLVM::FCmpPredicate::une;
953 auto zeroFloat = rewriter.create<mlir::LLVM::ConstantOp>(
954 castOp.getLoc(), llvmSrcVal.getType(),
955 mlir::FloatAttr::get(llvmSrcVal.getType(), 0.0));
958 rewriter.replaceOpWithNewOp<mlir::LLVM::FCmpOp>(castOp,
kind, llvmSrcVal,
961 return mlir::success();
963 case cir::CastKind::bool_to_int: {
964 auto dstTy = mlir::cast<cir::IntType>(castOp.getType());
965 mlir::Value llvmSrcVal = adaptor.getSrc();
966 auto llvmSrcTy = mlir::cast<mlir::IntegerType>(llvmSrcVal.getType());
968 mlir::cast<mlir::IntegerType>(getTypeConverter()->convertType(dstTy));
969 if (llvmSrcTy.getWidth() == llvmDstTy.getWidth())
970 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(castOp, llvmDstTy,
973 rewriter.replaceOpWithNewOp<mlir::LLVM::ZExtOp>(castOp, llvmDstTy,
975 return mlir::success();
977 case cir::CastKind::bool_to_float: {
978 mlir::Type dstTy = castOp.getType();
979 mlir::Value llvmSrcVal = adaptor.getSrc();
980 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
981 rewriter.replaceOpWithNewOp<mlir::LLVM::UIToFPOp>(castOp, llvmDstTy,
983 return mlir::success();
985 case cir::CastKind::int_to_float: {
986 mlir::Type dstTy = castOp.getType();
987 mlir::Value llvmSrcVal = adaptor.getSrc();
988 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
989 if (mlir::cast<cir::IntType>(elementTypeIfVector(castOp.getSrc().getType()))
991 rewriter.replaceOpWithNewOp<mlir::LLVM::SIToFPOp>(castOp, llvmDstTy,
994 rewriter.replaceOpWithNewOp<mlir::LLVM::UIToFPOp>(castOp, llvmDstTy,
996 return mlir::success();
998 case cir::CastKind::float_to_int: {
999 mlir::Type dstTy = castOp.getType();
1000 mlir::Value llvmSrcVal = adaptor.getSrc();
1001 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1002 if (mlir::cast<cir::IntType>(elementTypeIfVector(castOp.getType()))
1004 rewriter.replaceOpWithNewOp<mlir::LLVM::FPToSIOp>(castOp, llvmDstTy,
1007 rewriter.replaceOpWithNewOp<mlir::LLVM::FPToUIOp>(castOp, llvmDstTy,
1009 return mlir::success();
1011 case cir::CastKind::bitcast: {
1012 mlir::Type dstTy = castOp.getType();
1013 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1018 mlir::Value llvmSrcVal = adaptor.getSrc();
1019 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(castOp, llvmDstTy,
1021 return mlir::success();
1023 case cir::CastKind::ptr_to_bool: {
1024 mlir::Value llvmSrcVal = adaptor.getSrc();
1025 mlir::Value zeroPtr = rewriter.create<mlir::LLVM::ZeroOp>(
1026 castOp.getLoc(), llvmSrcVal.getType());
1027 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
1028 castOp, mlir::LLVM::ICmpPredicate::ne, llvmSrcVal, zeroPtr);
1031 case cir::CastKind::address_space: {
1032 mlir::Type dstTy = castOp.getType();
1033 mlir::Value llvmSrcVal = adaptor.getSrc();
1034 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1035 rewriter.replaceOpWithNewOp<mlir::LLVM::AddrSpaceCastOp>(castOp, llvmDstTy,
1039 case cir::CastKind::member_ptr_to_bool:
1044 return castOp.emitError(
"Unhandled cast kind: ")
1045 << castOp.getKindAttrName();
1049 return mlir::success();
1052mlir::LogicalResult CIRToLLVMPtrStrideOpLowering::matchAndRewrite(
1053 cir::PtrStrideOp ptrStrideOp, OpAdaptor adaptor,
1054 mlir::ConversionPatternRewriter &rewriter)
const {
1056 const mlir::TypeConverter *tc = getTypeConverter();
1057 const mlir::Type resultTy = tc->convertType(ptrStrideOp.getType());
1059 mlir::Type elementTy =
1061 mlir::MLIRContext *ctx = elementTy.getContext();
1065 if (mlir::isa<mlir::LLVM::LLVMVoidType>(elementTy) ||
1066 mlir::isa<mlir::LLVM::LLVMFunctionType>(elementTy))
1067 elementTy = mlir::IntegerType::get(elementTy.getContext(), 8,
1068 mlir::IntegerType::Signless);
1070 mlir::Value index = adaptor.getStride();
1071 const unsigned width =
1072 mlir::cast<mlir::IntegerType>(index.getType()).getWidth();
1073 const std::optional<std::uint64_t> layoutWidth =
1074 dataLayout.getTypeIndexBitwidth(adaptor.getBase().getType());
1076 mlir::Operation *indexOp = index.getDefiningOp();
1077 if (indexOp && layoutWidth && width != *layoutWidth) {
1081 const auto sub = dyn_cast<mlir::LLVM::SubOp>(indexOp);
1082 auto unary = ptrStrideOp.getStride().getDefiningOp<cir::UnaryOp>();
1084 unary && unary.getKind() == cir::UnaryOpKind::Minus && sub;
1086 index = indexOp->getOperand(1);
1089 const auto llvmDstType = mlir::IntegerType::get(ctx, *layoutWidth);
1091 ptrStrideOp.getStride().getType().isUnsigned(),
1092 width, *layoutWidth);
1096 index = rewriter.create<mlir::LLVM::SubOp>(
1097 index.getLoc(), index.getType(),
1098 rewriter.create<mlir::LLVM::ConstantOp>(index.getLoc(),
1099 index.getType(), 0),
1101 rewriter.eraseOp(sub);
1105 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1106 ptrStrideOp, resultTy, elementTy, adaptor.getBase(), index);
1107 return mlir::success();
1110mlir::LogicalResult CIRToLLVMBaseClassAddrOpLowering::matchAndRewrite(
1111 cir::BaseClassAddrOp baseClassOp, OpAdaptor adaptor,
1112 mlir::ConversionPatternRewriter &rewriter)
const {
1113 const mlir::Type resultType =
1114 getTypeConverter()->convertType(baseClassOp.getType());
1115 mlir::Value derivedAddr = adaptor.getDerivedAddr();
1116 llvm::SmallVector<mlir::LLVM::GEPArg, 1> offset = {
1117 adaptor.getOffset().getZExtValue()};
1118 mlir::Type byteType = mlir::IntegerType::get(resultType.getContext(), 8,
1119 mlir::IntegerType::Signless);
1120 if (adaptor.getOffset().getZExtValue() == 0) {
1121 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(
1122 baseClassOp, resultType, adaptor.getDerivedAddr());
1123 return mlir::success();
1126 if (baseClassOp.getAssumeNotNull()) {
1127 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1128 baseClassOp, resultType, byteType, derivedAddr, offset);
1130 auto loc = baseClassOp.getLoc();
1131 mlir::Value isNull = rewriter.create<mlir::LLVM::ICmpOp>(
1132 loc, mlir::LLVM::ICmpPredicate::eq, derivedAddr,
1133 rewriter.create<mlir::LLVM::ZeroOp>(loc, derivedAddr.getType()));
1134 mlir::Value adjusted = rewriter.create<mlir::LLVM::GEPOp>(
1135 loc, resultType, byteType, derivedAddr, offset);
1136 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(baseClassOp, isNull,
1137 derivedAddr, adjusted);
1139 return mlir::success();
1142mlir::LogicalResult CIRToLLVMATanOpLowering::matchAndRewrite(
1143 cir::ATanOp op, OpAdaptor adaptor,
1144 mlir::ConversionPatternRewriter &rewriter)
const {
1145 mlir::Type resTy = typeConverter->convertType(op.getType());
1146 rewriter.replaceOpWithNewOp<mlir::LLVM::ATanOp>(op, resTy, adaptor.getSrc());
1147 return mlir::success();
1150mlir::LogicalResult CIRToLLVMAllocaOpLowering::matchAndRewrite(
1151 cir::AllocaOp op, OpAdaptor adaptor,
1152 mlir::ConversionPatternRewriter &rewriter)
const {
1155 ? adaptor.getDynAllocSize()
1156 : rewriter.create<mlir::LLVM::ConstantOp>(
1158 typeConverter->convertType(rewriter.getIndexType()), 1);
1159 mlir::Type elementTy =
1161 mlir::Type resultTy =
1167 rewriter.replaceOpWithNewOp<mlir::LLVM::AllocaOp>(
1168 op, resultTy, elementTy, size, op.getAlignmentAttr().getInt());
1170 return mlir::success();
1173mlir::LogicalResult CIRToLLVMReturnOpLowering::matchAndRewrite(
1174 cir::ReturnOp op, OpAdaptor adaptor,
1175 mlir::ConversionPatternRewriter &rewriter)
const {
1176 rewriter.replaceOpWithNewOp<mlir::LLVM::ReturnOp>(op, adaptor.getOperands());
1177 return mlir::LogicalResult::success();
1180mlir::LogicalResult CIRToLLVMRotateOpLowering::matchAndRewrite(
1181 cir::RotateOp op, OpAdaptor adaptor,
1182 mlir::ConversionPatternRewriter &rewriter)
const {
1185 mlir::Value input = adaptor.getInput();
1186 if (op.isRotateLeft())
1187 rewriter.replaceOpWithNewOp<mlir::LLVM::FshlOp>(op, input, input,
1188 adaptor.getAmount());
1190 rewriter.replaceOpWithNewOp<mlir::LLVM::FshrOp>(op, input, input,
1191 adaptor.getAmount());
1192 return mlir::LogicalResult::success();
1195static mlir::LogicalResult
1197 mlir::ConversionPatternRewriter &rewriter,
1198 const mlir::TypeConverter *converter,
1199 mlir::FlatSymbolRefAttr calleeAttr) {
1201 mlir::ValueTypeRange<mlir::ResultRange> cirResults = op->getResultTypes();
1202 auto call = cast<cir::CIRCallOpInterface>(op);
1204 if (converter->convertTypes(cirResults, llvmResults).failed())
1205 return mlir::failure();
1209 mlir::LLVM::MemoryEffectsAttr memoryEffects;
1210 bool noUnwind =
false;
1211 bool willReturn =
false;
1213 memoryEffects, noUnwind, willReturn);
1215 mlir::LLVM::LLVMFunctionType llvmFnTy;
1222 mlir::Operation *callee =
1223 mlir::SymbolTable::lookupNearestSymbolFrom(op, calleeAttr);
1224 if (
auto fn = mlir::dyn_cast<mlir::FunctionOpInterface>(callee)) {
1225 llvmFnTy = converter->convertType<mlir::LLVM::LLVMFunctionType>(
1226 fn.getFunctionType());
1227 assert(llvmFnTy &&
"Failed to convert function type");
1228 }
else if (
auto alias = mlir::cast<mlir::LLVM::AliasOp>(callee)) {
1236 auto symAttr = mlir::cast<mlir::FlatSymbolRefAttr>(calleeAttr);
1238 mlir::LLVM::AddressOfOp::create(
1239 rewriter, op->getLoc(),
1240 mlir::LLVM::LLVMPointerType::get(rewriter.getContext()), symAttr)
1242 adjustedCallOperands.push_back(addrOfAlias);
1245 llvm::append_range(adjustedCallOperands, callOperands);
1246 callOperands = adjustedCallOperands;
1250 llvmFnTy = mlir::cast<mlir::LLVM::LLVMFunctionType>(alias.getType());
1253 return op->emitError(
"Unexpected callee type!");
1256 assert(!op->getOperands().empty() &&
1257 "operands list must no be empty for the indirect call");
1258 auto calleeTy = op->getOperands().front().getType();
1259 auto calleePtrTy = cast<cir::PointerType>(calleeTy);
1260 auto calleeFuncTy = cast<cir::FuncType>(calleePtrTy.getPointee());
1261 llvm::append_range(adjustedCallOperands, callOperands);
1262 llvmFnTy = cast<mlir::LLVM::LLVMFunctionType>(
1263 converter->convertType(calleeFuncTy));
1270 auto newOp = rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(
1271 op, llvmFnTy, calleeAttr, callOperands);
1273 newOp.setMemoryEffectsAttr(memoryEffects);
1274 newOp.setNoUnwind(noUnwind);
1275 newOp.setWillReturn(willReturn);
1277 return mlir::success();
1280mlir::LogicalResult CIRToLLVMCallOpLowering::matchAndRewrite(
1281 cir::CallOp op, OpAdaptor adaptor,
1282 mlir::ConversionPatternRewriter &rewriter)
const {
1284 getTypeConverter(), op.getCalleeAttr());
1287mlir::LogicalResult CIRToLLVMReturnAddrOpLowering::matchAndRewrite(
1288 cir::ReturnAddrOp op, OpAdaptor adaptor,
1289 mlir::ConversionPatternRewriter &rewriter)
const {
1290 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
1292 llvmPtrTy, adaptor.getOperands());
1293 return mlir::success();
1296mlir::LogicalResult CIRToLLVMFrameAddrOpLowering::matchAndRewrite(
1297 cir::FrameAddrOp op, OpAdaptor adaptor,
1298 mlir::ConversionPatternRewriter &rewriter)
const {
1299 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
1301 adaptor.getOperands());
1302 return mlir::success();
1305mlir::LogicalResult CIRToLLVMLoadOpLowering::matchAndRewrite(
1306 cir::LoadOp op, OpAdaptor adaptor,
1307 mlir::ConversionPatternRewriter &rewriter)
const {
1308 const mlir::Type llvmTy =
1310 mlir::LLVM::AtomicOrdering ordering =
getLLVMMemOrder(op.getMemOrder());
1311 std::optional<size_t> opAlign = op.getAlignment();
1312 unsigned alignment =
1313 (unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmTy));
1319 mlir::LLVM::LoadOp newLoad = mlir::LLVM::LoadOp::create(
1320 rewriter, op->getLoc(), llvmTy, adaptor.getAddr(), alignment,
1321 op.getIsVolatile(),
false,
1322 false,
false, ordering);
1325 mlir::Value result =
1327 rewriter.replaceOp(op, result);
1329 return mlir::LogicalResult::success();
1332mlir::LogicalResult CIRToLLVMStoreOpLowering::matchAndRewrite(
1333 cir::StoreOp op, OpAdaptor adaptor,
1334 mlir::ConversionPatternRewriter &rewriter)
const {
1335 mlir::LLVM::AtomicOrdering memorder =
getLLVMMemOrder(op.getMemOrder());
1336 const mlir::Type llvmTy =
1337 getTypeConverter()->convertType(op.getValue().getType());
1338 std::optional<size_t> opAlign = op.getAlignment();
1339 unsigned alignment =
1340 (unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmTy));
1346 op.getValue().getType(), adaptor.getValue());
1350 mlir::LLVM::StoreOp storeOp = mlir::LLVM::StoreOp::create(
1351 rewriter, op->getLoc(), value, adaptor.getAddr(), alignment,
1353 false,
false, memorder);
1354 rewriter.replaceOp(op, storeOp);
1356 return mlir::LogicalResult::success();
1360 auto array = mlir::dyn_cast<mlir::ArrayAttr>(attr.getElts());
1361 return attr.hasTrailingZeros() ||
1362 (array && std::count_if(array.begin(), array.end(), [](
auto elt) {
1363 auto ar = dyn_cast<cir::ConstArrayAttr>(elt);
1364 return ar && hasTrailingZeros(ar);
1368mlir::LogicalResult CIRToLLVMConstantOpLowering::matchAndRewrite(
1369 cir::ConstantOp op, OpAdaptor adaptor,
1370 mlir::ConversionPatternRewriter &rewriter)
const {
1371 mlir::Attribute attr = op.getValue();
1373 if (mlir::isa<cir::PoisonAttr>(attr)) {
1374 rewriter.replaceOpWithNewOp<mlir::LLVM::PoisonOp>(
1375 op, getTypeConverter()->convertType(op.getType()));
1376 return mlir::success();
1379 if (mlir::isa<mlir::IntegerType>(op.getType())) {
1384 attr = op.getValue();
1385 }
else if (mlir::isa<cir::BoolType>(op.getType())) {
1386 int value = mlir::cast<cir::BoolAttr>(op.getValue()).getValue();
1387 attr = rewriter.getIntegerAttr(typeConverter->convertType(op.getType()),
1389 }
else if (mlir::isa<cir::IntType>(op.getType())) {
1391 if (
auto ga = mlir::dyn_cast<cir::GlobalViewAttr>(op.getValue())) {
1394 op.emitError() <<
"global view with integer type";
1395 return mlir::failure();
1398 attr = rewriter.getIntegerAttr(
1399 typeConverter->convertType(op.getType()),
1400 mlir::cast<cir::IntAttr>(op.getValue()).getValue());
1401 }
else if (mlir::isa<cir::FPTypeInterface>(op.getType())) {
1402 attr = rewriter.getFloatAttr(
1403 typeConverter->convertType(op.getType()),
1404 mlir::cast<cir::FPAttr>(op.getValue()).getValue());
1405 }
else if (mlir::isa<cir::PointerType>(op.getType())) {
1407 if (mlir::isa<cir::ConstPtrAttr>(op.getValue())) {
1408 if (mlir::cast<cir::ConstPtrAttr>(op.getValue()).isNullValue()) {
1409 rewriter.replaceOpWithNewOp<mlir::LLVM::ZeroOp>(
1410 op, typeConverter->convertType(op.getType()));
1411 return mlir::success();
1415 if (
auto gv = mlir::dyn_cast<cir::GlobalViewAttr>(op.getValue())) {
1417 rewriter.replaceOp(op, newOp);
1418 return mlir::success();
1420 attr = op.getValue();
1421 }
else if (
const auto arrTy = mlir::dyn_cast<cir::ArrayType>(op.getType())) {
1422 const auto constArr = mlir::dyn_cast<cir::ConstArrayAttr>(op.getValue());
1423 if (!constArr && !isa<cir::ZeroAttr, cir::UndefAttr>(op.getValue()))
1424 return op.emitError() <<
"array does not have a constant initializer";
1426 std::optional<mlir::Attribute> denseAttr;
1428 const mlir::Value newOp =
1430 rewriter.replaceOp(op, newOp);
1431 return mlir::success();
1432 }
else if (constArr &&
1434 attr = denseAttr.value();
1436 const mlir::Value initVal =
1438 rewriter.replaceOp(op, initVal);
1439 return mlir::success();
1441 }
else if (
const auto recordAttr =
1442 mlir::dyn_cast<cir::ConstRecordAttr>(op.getValue())) {
1444 rewriter.replaceOp(op, initVal);
1445 return mlir::success();
1446 }
else if (
const auto vecTy = mlir::dyn_cast<cir::VectorType>(op.getType())) {
1448 getTypeConverter()));
1449 return mlir::success();
1450 }
else if (
auto recTy = mlir::dyn_cast<cir::RecordType>(op.getType())) {
1451 if (mlir::isa<cir::ZeroAttr, cir::UndefAttr>(attr)) {
1452 mlir::Value initVal =
1454 rewriter.replaceOp(op, initVal);
1455 return mlir::success();
1457 return op.emitError() <<
"unsupported lowering for record constant type "
1459 }
else if (
auto complexTy = mlir::dyn_cast<cir::ComplexType>(op.getType())) {
1460 mlir::Type complexElemTy = complexTy.getElementType();
1461 mlir::Type complexElemLLVMTy = typeConverter->convertType(complexElemTy);
1463 if (
auto zeroInitAttr = mlir::dyn_cast<cir::ZeroAttr>(op.getValue())) {
1464 mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(complexElemLLVMTy);
1465 mlir::ArrayAttr array = rewriter.getArrayAttr({zeroAttr, zeroAttr});
1466 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
1467 op, getTypeConverter()->convertType(op.getType()), array);
1468 return mlir::success();
1471 auto complexAttr = mlir::cast<cir::ConstComplexAttr>(op.getValue());
1473 mlir::Attribute components[2];
1474 if (mlir::isa<cir::IntType>(complexElemTy)) {
1475 components[0] = rewriter.getIntegerAttr(
1477 mlir::cast<cir::IntAttr>(complexAttr.getReal()).getValue());
1478 components[1] = rewriter.getIntegerAttr(
1480 mlir::cast<cir::IntAttr>(complexAttr.getImag()).getValue());
1482 components[0] = rewriter.getFloatAttr(
1484 mlir::cast<cir::FPAttr>(complexAttr.getReal()).getValue());
1485 components[1] = rewriter.getFloatAttr(
1487 mlir::cast<cir::FPAttr>(complexAttr.getImag()).getValue());
1490 attr = rewriter.getArrayAttr(components);
1492 return op.emitError() <<
"unsupported constant type " << op.getType();
1495 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
1496 op, getTypeConverter()->convertType(op.getType()),
attr);
1498 return mlir::success();
1501mlir::LogicalResult CIRToLLVMExpectOpLowering::matchAndRewrite(
1502 cir::ExpectOp op, OpAdaptor adaptor,
1503 mlir::ConversionPatternRewriter &rewriter)
const {
1507 std::optional<llvm::APFloat> prob = op.getProb();
1509 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpectWithProbabilityOp>(
1510 op, adaptor.getVal(), adaptor.getExpected(), prob.value());
1512 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpectOp>(op, adaptor.getVal(),
1513 adaptor.getExpected());
1514 return mlir::success();
1517mlir::LogicalResult CIRToLLVMFAbsOpLowering::matchAndRewrite(
1518 cir::FAbsOp op, OpAdaptor adaptor,
1519 mlir::ConversionPatternRewriter &rewriter)
const {
1520 mlir::Type resTy = typeConverter->convertType(op.getType());
1521 rewriter.replaceOpWithNewOp<mlir::LLVM::FAbsOp>(op, resTy,
1522 adaptor.getOperands()[0]);
1523 return mlir::success();
1530void CIRToLLVMFuncOpLowering::lowerFuncAttributes(
1531 cir::FuncOp func,
bool filterArgAndResAttrs,
1532 SmallVectorImpl<mlir::NamedAttribute> &result)
const {
1534 for (mlir::NamedAttribute attr : func->getAttrs()) {
1536 if (
attr.getName() == mlir::SymbolTable::getSymbolAttrName() ||
1537 attr.getName() == func.getFunctionTypeAttrName() ||
1539 attr.getName() == func.getGlobalVisibilityAttrName() ||
1540 attr.getName() == func.getDsoLocalAttrName() ||
1541 (filterArgAndResAttrs &&
1542 (
attr.getName() == func.getArgAttrsAttrName() ||
1543 attr.getName() == func.getResAttrsAttrName())))
1547 result.push_back(attr);
1551mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewriteAlias(
1552 cir::FuncOp op, llvm::StringRef aliasee, mlir::Type ty, OpAdaptor adaptor,
1553 mlir::ConversionPatternRewriter &rewriter)
const {
1554 SmallVector<mlir::NamedAttribute, 4> attributes;
1555 lowerFuncAttributes(op,
false, attributes);
1557 mlir::Location loc = op.getLoc();
1558 auto aliasOp = rewriter.replaceOpWithNewOp<mlir::LLVM::AliasOp>(
1559 op, ty,
convertLinkage(op.getLinkage()), op.getName(), op.getDsoLocal(),
1563 mlir::OpBuilder builder(op.getContext());
1564 mlir::Block *block = builder.createBlock(&aliasOp.getInitializerRegion());
1565 builder.setInsertionPointToStart(block);
1568 mlir::Type ptrTy = mlir::LLVM::LLVMPointerType::get(ty.getContext());
1569 auto addrOp = mlir::LLVM::AddressOfOp::create(builder, loc, ptrTy, aliasee);
1570 mlir::LLVM::ReturnOp::create(builder, loc, addrOp);
1572 return mlir::success();
1575mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewrite(
1576 cir::FuncOp op, OpAdaptor adaptor,
1577 mlir::ConversionPatternRewriter &rewriter)
const {
1579 cir::FuncType fnType = op.getFunctionType();
1580 bool isDsoLocal = op.getDsoLocal();
1581 mlir::TypeConverter::SignatureConversion signatureConversion(
1582 fnType.getNumInputs());
1584 for (
const auto &argType : llvm::enumerate(fnType.getInputs())) {
1585 mlir::Type convertedType = typeConverter->convertType(argType.value());
1587 return mlir::failure();
1588 signatureConversion.addInputs(argType.index(), convertedType);
1591 mlir::Type resultType =
1592 getTypeConverter()->convertType(fnType.getReturnType());
1595 mlir::Type llvmFnTy = mlir::LLVM::LLVMFunctionType::get(
1596 resultType ? resultType : mlir::LLVM::LLVMVoidType::get(getContext()),
1597 signatureConversion.getConvertedTypes(),
1601 if (std::optional<llvm::StringRef> aliasee = op.getAliasee())
1602 return matchAndRewriteAlias(op, *aliasee, llvmFnTy, adaptor, rewriter);
1606 mlir::Location loc = op.getLoc();
1607 if (mlir::FusedLoc fusedLoc = mlir::dyn_cast<mlir::FusedLoc>(loc))
1608 loc = fusedLoc.getLocations()[0];
1609 assert((mlir::isa<mlir::FileLineColLoc>(loc) ||
1610 mlir::isa<mlir::UnknownLoc>(loc)) &&
1611 "expected single location or unknown location here");
1615 mlir::LLVM::CConv cconv = mlir::LLVM::CConv::C;
1616 SmallVector<mlir::NamedAttribute, 4> attributes;
1617 lowerFuncAttributes(op,
false, attributes);
1619 mlir::LLVM::LLVMFuncOp fn = rewriter.create<mlir::LLVM::LLVMFuncOp>(
1620 loc, op.getName(), llvmFnTy, linkage, isDsoLocal, cconv,
1621 mlir::SymbolRefAttr(), attributes);
1625 fn.setVisibility_Attr(mlir::LLVM::VisibilityAttr::get(
1627 op.getGlobalVisibilityAttr().getValue())));
1629 rewriter.inlineRegionBefore(op.getBody(), fn.getBody(), fn.end());
1630 if (failed(rewriter.convertRegionTypes(&fn.getBody(), *typeConverter,
1631 &signatureConversion)))
1632 return mlir::failure();
1634 rewriter.eraseOp(op);
1636 return mlir::LogicalResult::success();
1639mlir::LogicalResult CIRToLLVMGetGlobalOpLowering::matchAndRewrite(
1640 cir::GetGlobalOp op, OpAdaptor adaptor,
1641 mlir::ConversionPatternRewriter &rewriter)
const {
1644 if (op->getUses().empty()) {
1645 rewriter.eraseOp(op);
1646 return mlir::success();
1649 mlir::Type
type = getTypeConverter()->convertType(op.getType());
1650 mlir::Operation *newop =
1651 rewriter.create<mlir::LLVM::AddressOfOp>(op.getLoc(), type, op.getName());
1655 rewriter.replaceOp(op, newop);
1656 return mlir::success();
1661void CIRToLLVMGlobalOpLowering::setupRegionInitializedLLVMGlobalOp(
1662 cir::GlobalOp op, mlir::ConversionPatternRewriter &rewriter)
const {
1663 const mlir::Type llvmType =
1671 const bool isConst = op.getConstant();
1673 const unsigned addrSpace = 0;
1674 const bool isDsoLocal = op.getDsoLocal();
1676 const bool isThreadLocal =
false;
1677 const uint64_t alignment = op.getAlignment().value_or(0);
1678 const mlir::LLVM::Linkage linkage =
convertLinkage(op.getLinkage());
1679 const StringRef symbol = op.getSymName();
1680 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
1682 SmallVector<mlir::NamedAttribute> attributes;
1683 mlir::LLVM::GlobalOp newGlobalOp =
1684 rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
1685 op, llvmType, isConst, linkage, symbol,
nullptr, alignment, addrSpace,
1686 isDsoLocal, isThreadLocal, comdatAttr, attributes);
1687 newGlobalOp.getRegion().emplaceBlock();
1688 rewriter.setInsertionPointToEnd(newGlobalOp.getInitializerBlock());
1692CIRToLLVMGlobalOpLowering::matchAndRewriteRegionInitializedGlobal(
1693 cir::GlobalOp op, mlir::Attribute init,
1694 mlir::ConversionPatternRewriter &rewriter)
const {
1696 assert((isa<cir::ConstArrayAttr, cir::ConstRecordAttr, cir::ConstVectorAttr,
1697 cir::ConstPtrAttr, cir::ConstComplexAttr, cir::GlobalViewAttr,
1698 cir::TypeInfoAttr, cir::VTableAttr, cir::ZeroAttr>(init)));
1703 const mlir::Location loc = op.getLoc();
1704 setupRegionInitializedLLVMGlobalOp(op, rewriter);
1706 mlir::Value value = valueConverter.visit(init);
1707 rewriter.create<mlir::LLVM::ReturnOp>(loc, value);
1708 return mlir::success();
1711mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite(
1712 cir::GlobalOp op, OpAdaptor adaptor,
1713 mlir::ConversionPatternRewriter &rewriter)
const {
1716 if (!op.getCtorRegion().empty() || !op.getDtorRegion().empty())
1717 return op.emitError() <<
"GlobalOp ctor and dtor regions should be removed "
1718 "in LoweringPrepare";
1720 std::optional<mlir::Attribute> init = op.getInitialValue();
1723 const mlir::Type cirSymType = op.getSymType();
1726 const mlir::Type llvmType =
1731 const bool isConst =
false;
1733 const unsigned addrSpace = 0;
1734 const bool isDsoLocal = op.getDsoLocal();
1736 const bool isThreadLocal =
false;
1737 const uint64_t alignment = op.getAlignment().value_or(0);
1738 const mlir::LLVM::Linkage linkage =
convertLinkage(op.getLinkage());
1739 const StringRef symbol = op.getSymName();
1740 SmallVector<mlir::NamedAttribute> attributes;
1741 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
1743 if (init.has_value()) {
1744 if (mlir::isa<cir::FPAttr, cir::IntAttr, cir::BoolAttr>(init.value())) {
1746 init = initRewriter.visit(init.value());
1751 if (!init.value()) {
1752 op.emitError() <<
"unsupported initializer '" << init.value() <<
"'";
1753 return mlir::failure();
1755 }
else if (mlir::isa<cir::ConstArrayAttr, cir::ConstVectorAttr,
1756 cir::ConstRecordAttr, cir::ConstPtrAttr,
1757 cir::ConstComplexAttr, cir::GlobalViewAttr,
1758 cir::TypeInfoAttr, cir::VTableAttr, cir::ZeroAttr>(
1763 return matchAndRewriteRegionInitializedGlobal(op, init.value(), rewriter);
1767 op.emitError() <<
"unsupported initializer '" << init.value() <<
"'";
1768 return mlir::failure();
1773 rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
1774 op, llvmType, isConst, linkage, symbol, init.value_or(mlir::Attribute()),
1775 alignment, addrSpace, isDsoLocal, isThreadLocal, comdatAttr, attributes);
1776 return mlir::success();
1780CIRToLLVMGlobalOpLowering::getComdatAttr(cir::GlobalOp &op,
1781 mlir::OpBuilder &builder)
const {
1782 if (!op.getComdat())
1783 return mlir::SymbolRefAttr{};
1785 mlir::ModuleOp module = op->getParentOfType<mlir::ModuleOp>();
1786 mlir::OpBuilder::InsertionGuard guard(builder);
1787 StringRef comdatName(
"__llvm_comdat_globals");
1789 builder.setInsertionPointToStart(module.getBody());
1791 builder.create<mlir::LLVM::ComdatOp>(module.getLoc(), comdatName);
1794 builder.setInsertionPointToStart(&comdatOp.getBody().back());
1795 auto selectorOp = builder.create<mlir::LLVM::ComdatSelectorOp>(
1796 comdatOp.getLoc(), op.getSymName(), mlir::LLVM::comdat::Comdat::Any);
1797 return mlir::SymbolRefAttr::get(
1798 builder.getContext(), comdatName,
1799 mlir::FlatSymbolRefAttr::get(selectorOp.getSymNameAttr()));
1802mlir::LogicalResult CIRToLLVMSwitchFlatOpLowering::matchAndRewrite(
1803 cir::SwitchFlatOp op, OpAdaptor adaptor,
1804 mlir::ConversionPatternRewriter &rewriter)
const {
1806 llvm::SmallVector<mlir::APInt, 8> caseValues;
1807 for (mlir::Attribute val : op.getCaseValues()) {
1808 auto intAttr = cast<cir::IntAttr>(val);
1809 caseValues.push_back(intAttr.getValue());
1812 llvm::SmallVector<mlir::Block *, 8> caseDestinations;
1813 llvm::SmallVector<mlir::ValueRange, 8> caseOperands;
1815 for (mlir::Block *x : op.getCaseDestinations())
1816 caseDestinations.push_back(x);
1818 for (mlir::OperandRange x : op.getCaseOperands())
1819 caseOperands.push_back(x);
1822 rewriter.setInsertionPoint(op);
1823 rewriter.replaceOpWithNewOp<mlir::LLVM::SwitchOp>(
1824 op, adaptor.getCondition(), op.getDefaultDestination(),
1825 op.getDefaultOperands(), caseValues, caseDestinations, caseOperands);
1826 return mlir::success();
1829mlir::LogicalResult CIRToLLVMUnaryOpLowering::matchAndRewrite(
1830 cir::UnaryOp op, OpAdaptor adaptor,
1831 mlir::ConversionPatternRewriter &rewriter)
const {
1832 assert(op.getType() == op.getInput().getType() &&
1833 "Unary operation's operand type and result type are different");
1834 mlir::Type
type = op.getType();
1835 mlir::Type elementType = elementTypeIfVector(type);
1836 bool isVector = mlir::isa<cir::VectorType>(type);
1837 mlir::Type llvmType = getTypeConverter()->convertType(type);
1838 mlir::Location loc = op.getLoc();
1841 if (mlir::isa<cir::IntType>(elementType)) {
1842 mlir::LLVM::IntegerOverflowFlags maybeNSW =
1843 op.getNoSignedWrap() ? mlir::LLVM::IntegerOverflowFlags::nsw
1844 : mlir::LLVM::IntegerOverflowFlags::none;
1845 switch (op.getKind()) {
1846 case cir::UnaryOpKind::Inc: {
1847 assert(!
isVector &&
"++ not allowed on vector types");
1848 auto one = rewriter.create<mlir::LLVM::ConstantOp>(loc, llvmType, 1);
1849 rewriter.replaceOpWithNewOp<mlir::LLVM::AddOp>(
1850 op, llvmType, adaptor.getInput(), one, maybeNSW);
1851 return mlir::success();
1853 case cir::UnaryOpKind::Dec: {
1854 assert(!
isVector &&
"-- not allowed on vector types");
1855 auto one = rewriter.create<mlir::LLVM::ConstantOp>(loc, llvmType, 1);
1856 rewriter.replaceOpWithNewOp<mlir::LLVM::SubOp>(op, adaptor.getInput(),
1858 return mlir::success();
1860 case cir::UnaryOpKind::Plus:
1861 rewriter.replaceOp(op, adaptor.getInput());
1862 return mlir::success();
1863 case cir::UnaryOpKind::Minus: {
1866 zero = rewriter.create<mlir::LLVM::ZeroOp>(loc, llvmType);
1868 zero = rewriter.create<mlir::LLVM::ConstantOp>(loc, llvmType, 0);
1869 rewriter.replaceOpWithNewOp<mlir::LLVM::SubOp>(
1870 op, zero, adaptor.getInput(), maybeNSW);
1871 return mlir::success();
1873 case cir::UnaryOpKind::Not: {
1875 mlir::Value minusOne;
1878 mlir::dyn_cast<cir::VectorType>(type).getSize();
1879 std::vector<int32_t> values(numElements, -1);
1880 mlir::DenseIntElementsAttr denseVec = rewriter.getI32VectorAttr(values);
1882 rewriter.create<mlir::LLVM::ConstantOp>(loc, llvmType, denseVec);
1884 minusOne = rewriter.create<mlir::LLVM::ConstantOp>(loc, llvmType, -1);
1886 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getInput(),
1888 return mlir::success();
1891 llvm_unreachable(
"Unexpected unary op for int");
1895 if (mlir::isa<cir::FPTypeInterface>(elementType)) {
1896 switch (op.getKind()) {
1897 case cir::UnaryOpKind::Inc: {
1898 assert(!
isVector &&
"++ not allowed on vector types");
1899 mlir::LLVM::ConstantOp one = rewriter.create<mlir::LLVM::ConstantOp>(
1900 loc, llvmType, rewriter.getFloatAttr(llvmType, 1.0));
1901 rewriter.replaceOpWithNewOp<mlir::LLVM::FAddOp>(op, llvmType, one,
1902 adaptor.getInput());
1903 return mlir::success();
1905 case cir::UnaryOpKind::Dec: {
1906 assert(!
isVector &&
"-- not allowed on vector types");
1907 mlir::LLVM::ConstantOp minusOne = rewriter.create<mlir::LLVM::ConstantOp>(
1908 loc, llvmType, rewriter.getFloatAttr(llvmType, -1.0));
1909 rewriter.replaceOpWithNewOp<mlir::LLVM::FAddOp>(op, llvmType, minusOne,
1910 adaptor.getInput());
1911 return mlir::success();
1913 case cir::UnaryOpKind::Plus:
1914 rewriter.replaceOp(op, adaptor.getInput());
1915 return mlir::success();
1916 case cir::UnaryOpKind::Minus:
1917 rewriter.replaceOpWithNewOp<mlir::LLVM::FNegOp>(op, llvmType,
1918 adaptor.getInput());
1919 return mlir::success();
1920 case cir::UnaryOpKind::Not:
1921 return op.emitError() <<
"Unary not is invalid for floating-point types";
1923 llvm_unreachable(
"Unexpected unary op for float");
1928 if (mlir::isa<cir::BoolType>(elementType)) {
1929 switch (op.getKind()) {
1930 case cir::UnaryOpKind::Inc:
1931 case cir::UnaryOpKind::Dec:
1932 case cir::UnaryOpKind::Plus:
1933 case cir::UnaryOpKind::Minus:
1936 return op.emitError() <<
"Unsupported unary operation on boolean type";
1937 case cir::UnaryOpKind::Not: {
1938 assert(!
isVector &&
"NYI: op! on vector mask");
1939 auto one = rewriter.create<mlir::LLVM::ConstantOp>(loc, llvmType, 1);
1940 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getInput(),
1942 return mlir::success();
1945 llvm_unreachable(
"Unexpected unary op for bool");
1950 if (mlir::isa<cir::PointerType>(elementType)) {
1951 switch (op.getKind()) {
1952 case cir::UnaryOpKind::Plus:
1953 rewriter.replaceOp(op, adaptor.getInput());
1954 return mlir::success();
1956 op.emitError() <<
"Unknown pointer unary operation during CIR lowering";
1957 return mlir::failure();
1961 return op.emitError() <<
"Unary operation has unsupported type: "
1965mlir::LLVM::IntegerOverflowFlags
1966CIRToLLVMBinOpLowering::getIntOverflowFlag(cir::BinOp op)
const {
1967 if (op.getNoUnsignedWrap())
1968 return mlir::LLVM::IntegerOverflowFlags::nuw;
1970 if (op.getNoSignedWrap())
1971 return mlir::LLVM::IntegerOverflowFlags::nsw;
1973 return mlir::LLVM::IntegerOverflowFlags::none;
1978 return mlir::isa<cir::IntType>(type)
1979 ? mlir::cast<cir::IntType>(type).isUnsigned()
1980 : mlir::cast<mlir::IntegerType>(type).isUnsigned();
1983mlir::LogicalResult CIRToLLVMBinOpLowering::matchAndRewrite(
1984 cir::BinOp op, OpAdaptor adaptor,
1985 mlir::ConversionPatternRewriter &rewriter)
const {
1986 if (adaptor.getLhs().getType() != adaptor.getRhs().getType())
1987 return op.emitError() <<
"inconsistent operands' types not supported yet";
1989 mlir::Type type = op.getRhs().getType();
1990 if (!mlir::isa<cir::IntType, cir::BoolType, cir::FPTypeInterface,
1991 mlir::IntegerType, cir::VectorType>(type))
1992 return op.emitError() <<
"operand type not supported yet";
1994 const mlir::Type llvmTy = getTypeConverter()->convertType(op.getType());
1995 const mlir::Type llvmEltTy = elementTypeIfVector(llvmTy);
1997 const mlir::Value rhs = adaptor.getRhs();
1998 const mlir::Value lhs = adaptor.getLhs();
1999 type = elementTypeIfVector(type);
2001 switch (op.getKind()) {
2002 case cir::BinOpKind::Add:
2003 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
2004 if (op.getSaturated()) {
2006 rewriter.replaceOpWithNewOp<mlir::LLVM::UAddSat>(op, lhs, rhs);
2009 rewriter.replaceOpWithNewOp<mlir::LLVM::SAddSat>(op, lhs, rhs);
2012 rewriter.replaceOpWithNewOp<mlir::LLVM::AddOp>(op, llvmTy, lhs, rhs,
2013 getIntOverflowFlag(op));
2015 rewriter.replaceOpWithNewOp<mlir::LLVM::FAddOp>(op, lhs, rhs);
2018 case cir::BinOpKind::Sub:
2019 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
2020 if (op.getSaturated()) {
2022 rewriter.replaceOpWithNewOp<mlir::LLVM::USubSat>(op, lhs, rhs);
2025 rewriter.replaceOpWithNewOp<mlir::LLVM::SSubSat>(op, lhs, rhs);
2028 rewriter.replaceOpWithNewOp<mlir::LLVM::SubOp>(op, llvmTy, lhs, rhs,
2029 getIntOverflowFlag(op));
2031 rewriter.replaceOpWithNewOp<mlir::LLVM::FSubOp>(op, lhs, rhs);
2034 case cir::BinOpKind::Mul:
2035 if (mlir::isa<mlir::IntegerType>(llvmEltTy))
2036 rewriter.replaceOpWithNewOp<mlir::LLVM::MulOp>(op, llvmTy, lhs, rhs,
2037 getIntOverflowFlag(op));
2039 rewriter.replaceOpWithNewOp<mlir::LLVM::FMulOp>(op, lhs, rhs);
2041 case cir::BinOpKind::Div:
2042 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
2045 rewriter.replaceOpWithNewOp<mlir::LLVM::UDivOp>(op, lhs, rhs);
2047 rewriter.replaceOpWithNewOp<mlir::LLVM::SDivOp>(op, lhs, rhs);
2049 rewriter.replaceOpWithNewOp<mlir::LLVM::FDivOp>(op, lhs, rhs);
2052 case cir::BinOpKind::Rem:
2053 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
2056 rewriter.replaceOpWithNewOp<mlir::LLVM::URemOp>(op, lhs, rhs);
2058 rewriter.replaceOpWithNewOp<mlir::LLVM::SRemOp>(op, lhs, rhs);
2060 rewriter.replaceOpWithNewOp<mlir::LLVM::FRemOp>(op, lhs, rhs);
2063 case cir::BinOpKind::And:
2064 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(op, lhs, rhs);
2066 case cir::BinOpKind::Or:
2067 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(op, lhs, rhs);
2069 case cir::BinOpKind::Xor:
2070 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, lhs, rhs);
2072 case cir::BinOpKind::Max:
2073 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
2076 rewriter.replaceOpWithNewOp<mlir::LLVM::UMaxOp>(op, llvmTy, lhs, rhs);
2078 rewriter.replaceOpWithNewOp<mlir::LLVM::SMaxOp>(op, llvmTy, lhs, rhs);
2082 return mlir::LogicalResult::success();
2086static mlir::LLVM::ICmpPredicate
2088 using CIR = cir::CmpOpKind;
2089 using LLVMICmp = mlir::LLVM::ICmpPredicate;
2092 return LLVMICmp::eq;
2094 return LLVMICmp::ne;
2096 return (isSigned ? LLVMICmp::slt : LLVMICmp::ult);
2098 return (isSigned ? LLVMICmp::sle : LLVMICmp::ule);
2100 return (isSigned ? LLVMICmp::sgt : LLVMICmp::ugt);
2102 return (isSigned ? LLVMICmp::sge : LLVMICmp::uge);
2104 llvm_unreachable(
"Unknown CmpOpKind");
2109static mlir::LLVM::FCmpPredicate
2111 using CIR = cir::CmpOpKind;
2112 using LLVMFCmp = mlir::LLVM::FCmpPredicate;
2115 return LLVMFCmp::oeq;
2117 return LLVMFCmp::une;
2119 return LLVMFCmp::olt;
2121 return LLVMFCmp::ole;
2123 return LLVMFCmp::ogt;
2125 return LLVMFCmp::oge;
2127 llvm_unreachable(
"Unknown CmpOpKind");
2130mlir::LogicalResult CIRToLLVMCmpOpLowering::matchAndRewrite(
2131 cir::CmpOp cmpOp, OpAdaptor adaptor,
2132 mlir::ConversionPatternRewriter &rewriter)
const {
2133 mlir::Type type = cmpOp.getLhs().getType();
2138 if (mlir::isa<cir::IntType, mlir::IntegerType>(type)) {
2139 bool isSigned = mlir::isa<cir::IntType>(type)
2140 ? mlir::cast<cir::IntType>(type).isSigned()
2141 : mlir::cast<mlir::IntegerType>(type).isSigned();
2142 mlir::LLVM::ICmpPredicate kind =
2144 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
2145 cmpOp, kind, adaptor.getLhs(), adaptor.getRhs());
2146 return mlir::success();
2149 if (
auto ptrTy = mlir::dyn_cast<cir::PointerType>(type)) {
2150 mlir::LLVM::ICmpPredicate kind =
2153 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
2154 cmpOp, kind, adaptor.getLhs(), adaptor.getRhs());
2155 return mlir::success();
2158 if (mlir::isa<cir::FPTypeInterface>(type)) {
2159 mlir::LLVM::FCmpPredicate
kind =
2161 rewriter.replaceOpWithNewOp<mlir::LLVM::FCmpOp>(
2162 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
2163 return mlir::success();
2166 if (mlir::isa<cir::ComplexType>(type)) {
2167 mlir::Value lhs = adaptor.getLhs();
2168 mlir::Value rhs = adaptor.getRhs();
2169 mlir::Location loc = cmpOp.getLoc();
2171 auto complexType = mlir::cast<cir::ComplexType>(cmpOp.getLhs().getType());
2172 mlir::Type complexElemTy =
2173 getTypeConverter()->convertType(
complexType.getElementType());
2176 rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, lhs, 0);
2178 rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, lhs, 1);
2180 rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, rhs, 0);
2182 rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, rhs, 1);
2184 if (cmpOp.getKind() == cir::CmpOpKind::eq) {
2185 if (complexElemTy.isInteger()) {
2186 auto realCmp = rewriter.create<mlir::LLVM::ICmpOp>(
2187 loc, mlir::LLVM::ICmpPredicate::eq, lhsReal, rhsReal);
2188 auto imagCmp = rewriter.create<mlir::LLVM::ICmpOp>(
2189 loc, mlir::LLVM::ICmpPredicate::eq, lhsImag, rhsImag);
2190 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, imagCmp);
2191 return mlir::success();
2194 auto realCmp = rewriter.create<mlir::LLVM::FCmpOp>(
2195 loc, mlir::LLVM::FCmpPredicate::oeq, lhsReal, rhsReal);
2196 auto imagCmp = rewriter.create<mlir::LLVM::FCmpOp>(
2197 loc, mlir::LLVM::FCmpPredicate::oeq, lhsImag, rhsImag);
2198 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, imagCmp);
2199 return mlir::success();
2202 if (cmpOp.getKind() == cir::CmpOpKind::ne) {
2203 if (complexElemTy.isInteger()) {
2204 auto realCmp = rewriter.create<mlir::LLVM::ICmpOp>(
2205 loc, mlir::LLVM::ICmpPredicate::ne, lhsReal, rhsReal);
2206 auto imagCmp = rewriter.create<mlir::LLVM::ICmpOp>(
2207 loc, mlir::LLVM::ICmpPredicate::ne, lhsImag, rhsImag);
2208 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp);
2209 return mlir::success();
2212 auto realCmp = rewriter.create<mlir::LLVM::FCmpOp>(
2213 loc, mlir::LLVM::FCmpPredicate::une, lhsReal, rhsReal);
2214 auto imagCmp = rewriter.create<mlir::LLVM::FCmpOp>(
2215 loc, mlir::LLVM::FCmpPredicate::une, lhsImag, rhsImag);
2216 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp);
2217 return mlir::success();
2221 return cmpOp.emitError() <<
"unsupported type for CmpOp: " <<
type;
2224mlir::LogicalResult CIRToLLVMShiftOpLowering::matchAndRewrite(
2225 cir::ShiftOp op, OpAdaptor adaptor,
2226 mlir::ConversionPatternRewriter &rewriter)
const {
2227 assert((op.getValue().getType() == op.getType()) &&
2228 "inconsistent operands' types NYI");
2230 const mlir::Type llvmTy = getTypeConverter()->convertType(op.getType());
2231 mlir::Value amt = adaptor.getAmount();
2232 mlir::Value val = adaptor.getValue();
2234 auto cirAmtTy = mlir::dyn_cast<cir::IntType>(op.getAmount().getType());
2237 auto cirValTy = mlir::cast<cir::IntType>(op.getValue().getType());
2245 amt =
getLLVMIntCast(rewriter, amt, llvmTy,
true, cirAmtTy.getWidth(),
2246 cirValTy.getWidth());
2248 auto cirValVTy = mlir::cast<cir::VectorType>(op.getValue().getType());
2250 mlir::cast<cir::IntType>(cirValVTy.getElementType()).isUnsigned();
2254 if (op.getIsShiftleft()) {
2255 rewriter.replaceOpWithNewOp<mlir::LLVM::ShlOp>(op, llvmTy, val, amt);
2256 return mlir::success();
2260 rewriter.replaceOpWithNewOp<mlir::LLVM::LShrOp>(op, llvmTy, val, amt);
2262 rewriter.replaceOpWithNewOp<mlir::LLVM::AShrOp>(op, llvmTy, val, amt);
2263 return mlir::success();
2266mlir::LogicalResult CIRToLLVMSelectOpLowering::matchAndRewrite(
2267 cir::SelectOp op, OpAdaptor adaptor,
2268 mlir::ConversionPatternRewriter &rewriter)
const {
2269 auto getConstantBool = [](mlir::Value value) -> cir::BoolAttr {
2270 auto definingOp = value.getDefiningOp<cir::ConstantOp>();
2274 auto constValue = definingOp.getValueAttr<cir::BoolAttr>();
2284 if (mlir::isa<cir::BoolType>(op.getTrueValue().getType())) {
2285 cir::BoolAttr trueValue = getConstantBool(op.getTrueValue());
2286 cir::BoolAttr falseValue = getConstantBool(op.getFalseValue());
2287 if (falseValue && !falseValue.getValue()) {
2289 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(op, adaptor.getCondition(),
2290 adaptor.getTrueValue());
2291 return mlir::success();
2293 if (trueValue && trueValue.getValue()) {
2295 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(op, adaptor.getCondition(),
2296 adaptor.getFalseValue());
2297 return mlir::success();
2301 mlir::Value llvmCondition = adaptor.getCondition();
2302 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(
2303 op, llvmCondition, adaptor.getTrueValue(), adaptor.getFalseValue());
2305 return mlir::success();
2309 mlir::DataLayout &dataLayout) {
2310 converter.addConversion([&](cir::PointerType type) -> mlir::Type {
2313 unsigned targetAS = 0;
2315 return mlir::LLVM::LLVMPointerType::get(type.getContext(), targetAS);
2317 converter.addConversion([&](cir::VPtrType type) -> mlir::Type {
2319 return mlir::LLVM::LLVMPointerType::get(type.getContext());
2321 converter.addConversion([&](cir::ArrayType type) -> mlir::Type {
2324 return mlir::LLVM::LLVMArrayType::get(ty, type.getSize());
2326 converter.addConversion([&](cir::VectorType type) -> mlir::Type {
2327 const mlir::Type ty = converter.convertType(type.getElementType());
2328 return mlir::VectorType::get(type.getSize(), ty);
2330 converter.addConversion([&](cir::BoolType type) -> mlir::Type {
2331 return mlir::IntegerType::get(type.getContext(), 1,
2332 mlir::IntegerType::Signless);
2334 converter.addConversion([&](cir::IntType type) -> mlir::Type {
2336 return mlir::IntegerType::get(type.getContext(), type.getWidth());
2338 converter.addConversion([&](cir::SingleType type) -> mlir::Type {
2339 return mlir::Float32Type::get(type.getContext());
2341 converter.addConversion([&](cir::DoubleType type) -> mlir::Type {
2342 return mlir::Float64Type::get(type.getContext());
2344 converter.addConversion([&](cir::FP80Type type) -> mlir::Type {
2345 return mlir::Float80Type::get(type.getContext());
2347 converter.addConversion([&](cir::FP128Type type) -> mlir::Type {
2348 return mlir::Float128Type::get(type.getContext());
2350 converter.addConversion([&](cir::LongDoubleType type) -> mlir::Type {
2351 return converter.convertType(type.getUnderlying());
2353 converter.addConversion([&](cir::FP16Type type) -> mlir::Type {
2354 return mlir::Float16Type::get(type.getContext());
2356 converter.addConversion([&](cir::BF16Type type) -> mlir::Type {
2357 return mlir::BFloat16Type::get(type.getContext());
2359 converter.addConversion([&](cir::ComplexType type) -> mlir::Type {
2362 mlir::Type elementTy = converter.convertType(type.getElementType());
2363 mlir::Type structFields[2] = {elementTy, elementTy};
2364 return mlir::LLVM::LLVMStructType::getLiteral(type.getContext(),
2367 converter.addConversion([&](cir::FuncType type) -> std::optional<mlir::Type> {
2368 auto result = converter.convertType(type.getReturnType());
2370 arguments.reserve(type.getNumInputs());
2371 if (converter.convertTypes(type.getInputs(), arguments).failed())
2372 return std::nullopt;
2373 auto varArg = type.isVarArg();
2374 return mlir::LLVM::LLVMFunctionType::get(result, arguments, varArg);
2376 converter.addConversion([&](cir::RecordType type) -> mlir::Type {
2379 switch (type.getKind()) {
2380 case cir::RecordType::Class:
2381 case cir::RecordType::Struct:
2382 for (mlir::Type ty : type.getMembers())
2386 case cir::RecordType::Union:
2387 if (
auto largestMember = type.getLargestMember(dataLayout))
2388 llvmMembers.push_back(
2390 if (type.getPadded()) {
2391 auto last = *type.getMembers().rbegin();
2392 llvmMembers.push_back(
2399 mlir::LLVM::LLVMStructType llvmStruct;
2400 if (type.getName()) {
2401 llvmStruct = mlir::LLVM::LLVMStructType::getIdentified(
2402 type.getContext(), type.getPrefixedName());
2403 if (llvmStruct.setBody(llvmMembers, type.getPacked()).failed())
2404 llvm_unreachable(
"Failed to set body of record");
2406 llvmStruct = mlir::LLVM::LLVMStructType::getLiteral(
2407 type.getContext(), llvmMembers, type.getPacked());
2412 converter.addConversion([&](cir::VoidType type) -> mlir::Type {
2413 return mlir::LLVM::LLVMVoidType::get(type.getContext());
2452 parent->walk([&](mlir::Block *blk) {
2453 if (blk->hasNoPredecessors() && !blk->isEntryBlock())
2454 unreachableBlocks.push_back(blk);
2457 std::set<mlir::Block *> visited;
2458 for (mlir::Block *root : unreachableBlocks) {
2461 std::deque<mlir::Block *> workList;
2462 workList.push_back(root);
2464 while (!workList.empty()) {
2465 mlir::Block *blk = workList.back();
2466 workList.pop_back();
2467 if (visited.count(blk))
2469 visited.emplace(blk);
2471 for (mlir::Operation &op : *blk)
2474 for (mlir::Block *succ : blk->getSuccessors())
2475 workList.push_back(succ);
2482 if (mlir::Attribute tripleAttr =
2483 module->getAttr(cir::CIRDialect::getTripleAttrName()))
2484 module->setAttr(mlir::LLVM::LLVMDialect::getTargetTripleAttrName(),
2487 if (mlir::Attribute asmAttr =
2488 module->getAttr(cir::CIRDialect::getModuleLevelAsmAttrName()))
2489 module->setAttr(mlir::LLVM::LLVMDialect::getModuleLevelAsmAttrName(),
2494 llvm::TimeTraceScope scope(
"Convert CIR to LLVM Pass");
2496 mlir::ModuleOp module = getOperation();
2497 mlir::DataLayout dl(module);
2498 mlir::LLVMTypeConverter converter(&getContext());
2501 mlir::RewritePatternSet patterns(&getContext());
2504#define GET_LLVM_LOWERING_PATTERNS_LIST
2505#include "clang/CIR/Dialect/IR/CIRLowering.inc"
2506#undef GET_LLVM_LOWERING_PATTERNS_LIST
2507 >(converter, patterns.getContext(), dl);
2511 mlir::ConversionTarget target(getContext());
2512 target.addLegalOp<mlir::ModuleOp>();
2513 target.addLegalDialect<mlir::LLVM::LLVMDialect>();
2514 target.addIllegalDialect<mlir::BuiltinDialect, cir::CIRDialect,
2515 mlir::func::FuncDialect>();
2518 ops.push_back(module);
2521 if (failed(applyPartialConversion(ops, target, std::move(patterns))))
2522 signalPassFailure();
2525mlir::LogicalResult CIRToLLVMBrOpLowering::matchAndRewrite(
2526 cir::BrOp op, OpAdaptor adaptor,
2527 mlir::ConversionPatternRewriter &rewriter)
const {
2528 rewriter.replaceOpWithNewOp<mlir::LLVM::BrOp>(op, adaptor.getOperands(),
2530 return mlir::LogicalResult::success();
2533mlir::LogicalResult CIRToLLVMGetMemberOpLowering::matchAndRewrite(
2534 cir::GetMemberOp op, OpAdaptor adaptor,
2535 mlir::ConversionPatternRewriter &rewriter)
const {
2536 mlir::Type llResTy = getTypeConverter()->convertType(op.getType());
2537 const auto recordTy =
2538 mlir::cast<cir::RecordType>(op.getAddrTy().getPointee());
2539 assert(recordTy &&
"expected record type");
2541 switch (recordTy.getKind()) {
2542 case cir::RecordType::Class:
2543 case cir::RecordType::Struct: {
2547 const mlir::Type elementTy = getTypeConverter()->convertType(recordTy);
2548 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, llResTy, elementTy,
2549 adaptor.getAddr(), offset);
2550 return mlir::success();
2552 case cir::RecordType::Union:
2555 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(op, llResTy,
2557 return mlir::success();
2561mlir::LogicalResult CIRToLLVMUnreachableOpLowering::matchAndRewrite(
2562 cir::UnreachableOp op, OpAdaptor adaptor,
2563 mlir::ConversionPatternRewriter &rewriter)
const {
2564 rewriter.replaceOpWithNewOp<mlir::LLVM::UnreachableOp>(op);
2565 return mlir::success();
2569 mlir::Operation *srcOp, llvm::StringRef fnName,
2571 auto modOp = srcOp->getParentOfType<mlir::ModuleOp>();
2572 auto enclosingFnOp = srcOp->getParentOfType<mlir::LLVM::LLVMFuncOp>();
2573 mlir::Operation *sourceSymbol =
2574 mlir::SymbolTable::lookupSymbolIn(modOp, fnName);
2575 if (!sourceSymbol) {
2576 mlir::OpBuilder::InsertionGuard guard(rewriter);
2577 rewriter.setInsertionPoint(enclosingFnOp);
2578 rewriter.create<mlir::LLVM::LLVMFuncOp>(srcOp->getLoc(), fnName, fnTy);
2582mlir::LogicalResult CIRToLLVMThrowOpLowering::matchAndRewrite(
2583 cir::ThrowOp op, OpAdaptor adaptor,
2584 mlir::ConversionPatternRewriter &rewriter)
const {
2585 if (op.rethrows()) {
2586 auto voidTy = mlir::LLVM::LLVMVoidType::get(getContext());
2588 mlir::LLVM::LLVMFunctionType::get(getContext(), voidTy, {},
false);
2590 auto mlirModule = op->getParentOfType<mlir::ModuleOp>();
2591 rewriter.setInsertionPointToStart(&mlirModule.getBodyRegion().front());
2593 const llvm::StringRef functionName =
"__cxa_rethrow";
2596 rewriter.setInsertionPointAfter(op.getOperation());
2597 rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(
2598 op, mlir::TypeRange{}, functionName, mlir::ValueRange{});
2601 return mlir::success();
2604mlir::LogicalResult CIRToLLVMTrapOpLowering::matchAndRewrite(
2605 cir::TrapOp op, OpAdaptor adaptor,
2606 mlir::ConversionPatternRewriter &rewriter)
const {
2607 mlir::Location loc = op->getLoc();
2608 rewriter.eraseOp(op);
2610 rewriter.create<mlir::LLVM::Trap>(loc);
2615 rewriter.create<mlir::LLVM::UnreachableOp>(loc);
2617 return mlir::success();
2622 mlir::ConversionPatternRewriter &rewriter,
2623 const mlir::TypeConverter *converter,
2624 mlir::FlatSymbolRefAttr nameAttr, mlir::Type &eltType) {
2625 auto module = op->getParentOfType<mlir::ModuleOp>();
2626 mlir::Operation *symbol = mlir::SymbolTable::lookupSymbolIn(module, nameAttr);
2627 if (
auto llvmSymbol = mlir::dyn_cast<mlir::LLVM::GlobalOp>(symbol)) {
2628 eltType = llvmSymbol.getType();
2629 }
else if (
auto cirSymbol = mlir::dyn_cast<cir::GlobalOp>(symbol)) {
2630 eltType = converter->convertType(cirSymbol.getSymType());
2632 op->emitError() <<
"unexpected symbol type for " << symbol;
2636 return mlir::LLVM::AddressOfOp::create(
2637 rewriter, op->getLoc(),
2638 mlir::LLVM::LLVMPointerType::get(op->getContext()), nameAttr.getValue());
2641mlir::LogicalResult CIRToLLVMVTableAddrPointOpLowering::matchAndRewrite(
2642 cir::VTableAddrPointOp op, OpAdaptor adaptor,
2643 mlir::ConversionPatternRewriter &rewriter)
const {
2644 const mlir::TypeConverter *converter = getTypeConverter();
2645 mlir::Type targetType = converter->convertType(op.getType());
2649 op.getNameAttr(), eltType);
2651 return op.emitError() <<
"Unable to get value for vtable symbol";
2654 0, op.getAddressPointAttr().getIndex(),
2655 op.getAddressPointAttr().getOffset()};
2657 assert(eltType &&
"Shouldn't ever be missing an eltType here");
2658 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
2659 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
2660 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, targetType, eltType,
2661 symAddr, offsets, inboundsNuw);
2662 return mlir::success();
2665mlir::LogicalResult CIRToLLVMVTableGetVPtrOpLowering::matchAndRewrite(
2666 cir::VTableGetVPtrOp op, OpAdaptor adaptor,
2667 mlir::ConversionPatternRewriter &rewriter)
const {
2671 mlir::Value srcVal = adaptor.getSrc();
2672 rewriter.replaceOp(op, srcVal);
2673 return mlir::success();
2676mlir::LogicalResult CIRToLLVMVTableGetVirtualFnAddrOpLowering::matchAndRewrite(
2677 cir::VTableGetVirtualFnAddrOp op, OpAdaptor adaptor,
2678 mlir::ConversionPatternRewriter &rewriter)
const {
2679 mlir::Type targetType = getTypeConverter()->convertType(op.getType());
2680 auto eltType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
2681 llvm::SmallVector<mlir::LLVM::GEPArg> offsets =
2682 llvm::SmallVector<mlir::LLVM::GEPArg>{op.getIndex()};
2683 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
2684 op, targetType, eltType, adaptor.getVptr(), offsets,
2685 mlir::LLVM::GEPNoWrapFlags::inbounds);
2686 return mlir::success();
2689mlir::LogicalResult CIRToLLVMVTTAddrPointOpLowering::matchAndRewrite(
2690 cir::VTTAddrPointOp op, OpAdaptor adaptor,
2691 mlir::ConversionPatternRewriter &rewriter)
const {
2692 const mlir::Type resultType = getTypeConverter()->convertType(op.getType());
2693 llvm::SmallVector<mlir::LLVM::GEPArg> offsets;
2695 mlir::Value llvmAddr = adaptor.getSymAddr();
2697 if (op.getSymAddr()) {
2698 if (op.getOffset() == 0) {
2699 rewriter.replaceOp(op, {llvmAddr});
2700 return mlir::success();
2703 offsets.push_back(adaptor.getOffset());
2704 eltType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
2707 op.getNameAttr(), eltType);
2708 assert(eltType &&
"Shouldn't ever be missing an eltType here");
2709 offsets.push_back(0);
2710 offsets.push_back(adaptor.getOffset());
2712 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
2713 op, resultType, eltType, llvmAddr, offsets,
2714 mlir::LLVM::GEPNoWrapFlags::inbounds);
2715 return mlir::success();
2718mlir::LogicalResult CIRToLLVMStackSaveOpLowering::matchAndRewrite(
2719 cir::StackSaveOp op, OpAdaptor adaptor,
2720 mlir::ConversionPatternRewriter &rewriter)
const {
2721 const mlir::Type ptrTy = getTypeConverter()->convertType(op.getType());
2722 rewriter.replaceOpWithNewOp<mlir::LLVM::StackSaveOp>(op, ptrTy);
2723 return mlir::success();
2726mlir::LogicalResult CIRToLLVMStackRestoreOpLowering::matchAndRewrite(
2727 cir::StackRestoreOp op, OpAdaptor adaptor,
2728 mlir::ConversionPatternRewriter &rewriter)
const {
2729 rewriter.replaceOpWithNewOp<mlir::LLVM::StackRestoreOp>(op, adaptor.getPtr());
2730 return mlir::success();
2733mlir::LogicalResult CIRToLLVMVecCreateOpLowering::matchAndRewrite(
2734 cir::VecCreateOp op, OpAdaptor adaptor,
2735 mlir::ConversionPatternRewriter &rewriter)
const {
2738 const auto vecTy = mlir::cast<cir::VectorType>(op.getType());
2739 const mlir::Type llvmTy = typeConverter->convertType(vecTy);
2740 const mlir::Location loc = op.getLoc();
2741 mlir::Value result = rewriter.create<mlir::LLVM::PoisonOp>(loc, llvmTy);
2742 assert(vecTy.getSize() == op.getElements().size() &&
2743 "cir.vec.create op count doesn't match vector type elements count");
2745 for (uint64_t i = 0; i < vecTy.getSize(); ++i) {
2746 const mlir::Value indexValue =
2747 rewriter.create<mlir::LLVM::ConstantOp>(loc, rewriter.getI64Type(), i);
2748 result = rewriter.create<mlir::LLVM::InsertElementOp>(
2749 loc, result, adaptor.getElements()[i], indexValue);
2752 rewriter.replaceOp(op, result);
2753 return mlir::success();
2756mlir::LogicalResult CIRToLLVMVecExtractOpLowering::matchAndRewrite(
2757 cir::VecExtractOp op, OpAdaptor adaptor,
2758 mlir::ConversionPatternRewriter &rewriter)
const {
2759 rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractElementOp>(
2760 op, adaptor.getVec(), adaptor.getIndex());
2761 return mlir::success();
2764mlir::LogicalResult CIRToLLVMVecInsertOpLowering::matchAndRewrite(
2765 cir::VecInsertOp op, OpAdaptor adaptor,
2766 mlir::ConversionPatternRewriter &rewriter)
const {
2767 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertElementOp>(
2768 op, adaptor.getVec(), adaptor.getValue(), adaptor.getIndex());
2769 return mlir::success();
2772mlir::LogicalResult CIRToLLVMVecCmpOpLowering::matchAndRewrite(
2773 cir::VecCmpOp op, OpAdaptor adaptor,
2774 mlir::ConversionPatternRewriter &rewriter)
const {
2775 mlir::Type elementType = elementTypeIfVector(op.getLhs().getType());
2776 mlir::Value bitResult;
2777 if (
auto intType = mlir::dyn_cast<cir::IntType>(elementType)) {
2778 bitResult = rewriter.create<mlir::LLVM::ICmpOp>(
2781 adaptor.getLhs(), adaptor.getRhs());
2782 }
else if (mlir::isa<cir::FPTypeInterface>(elementType)) {
2783 bitResult = rewriter.create<mlir::LLVM::FCmpOp>(
2785 adaptor.getLhs(), adaptor.getRhs());
2787 return op.emitError() <<
"unsupported type for VecCmpOp: " << elementType;
2792 rewriter.replaceOpWithNewOp<mlir::LLVM::SExtOp>(
2793 op, typeConverter->convertType(op.getType()), bitResult);
2794 return mlir::success();
2797mlir::LogicalResult CIRToLLVMVecSplatOpLowering::matchAndRewrite(
2798 cir::VecSplatOp op, OpAdaptor adaptor,
2799 mlir::ConversionPatternRewriter &rewriter)
const {
2805 cir::VectorType vecTy = op.getType();
2806 mlir::Type llvmTy = typeConverter->convertType(vecTy);
2807 mlir::Location loc = op.getLoc();
2808 mlir::Value poison = rewriter.create<mlir::LLVM::PoisonOp>(loc, llvmTy);
2810 mlir::Value elementValue = adaptor.getValue();
2811 if (elementValue.getDefiningOp<mlir::LLVM::PoisonOp>()) {
2814 rewriter.replaceOp(op, poison);
2815 return mlir::success();
2818 if (
auto constValue = elementValue.getDefiningOp<mlir::LLVM::ConstantOp>()) {
2819 if (
auto intAttr = dyn_cast<mlir::IntegerAttr>(constValue.getValue())) {
2820 mlir::DenseIntElementsAttr denseVec = mlir::DenseIntElementsAttr::get(
2821 mlir::cast<mlir::ShapedType>(llvmTy), intAttr.getValue());
2822 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
2823 op, denseVec.getType(), denseVec);
2824 return mlir::success();
2827 if (
auto fpAttr = dyn_cast<mlir::FloatAttr>(constValue.getValue())) {
2828 mlir::DenseFPElementsAttr denseVec = mlir::DenseFPElementsAttr::get(
2829 mlir::cast<mlir::ShapedType>(llvmTy), fpAttr.getValue());
2830 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
2831 op, denseVec.getType(), denseVec);
2832 return mlir::success();
2836 mlir::Value indexValue =
2837 rewriter.create<mlir::LLVM::ConstantOp>(loc, rewriter.getI64Type(), 0);
2838 mlir::Value oneElement = rewriter.create<mlir::LLVM::InsertElementOp>(
2839 loc, poison, elementValue, indexValue);
2840 SmallVector<int32_t> zeroValues(vecTy.getSize(), 0);
2841 rewriter.replaceOpWithNewOp<mlir::LLVM::ShuffleVectorOp>(op, oneElement,
2842 poison, zeroValues);
2843 return mlir::success();
2846mlir::LogicalResult CIRToLLVMVecShuffleOpLowering::matchAndRewrite(
2847 cir::VecShuffleOp op, OpAdaptor adaptor,
2848 mlir::ConversionPatternRewriter &rewriter)
const {
2852 SmallVector<int, 8> indices;
2854 op.getIndices().begin(), op.getIndices().end(),
2855 std::back_inserter(indices), [](mlir::Attribute intAttr) {
2856 return mlir::cast<cir::IntAttr>(intAttr).getValue().getSExtValue();
2858 rewriter.replaceOpWithNewOp<mlir::LLVM::ShuffleVectorOp>(
2859 op, adaptor.getVec1(), adaptor.getVec2(), indices);
2860 return mlir::success();
2863mlir::LogicalResult CIRToLLVMVecShuffleDynamicOpLowering::matchAndRewrite(
2864 cir::VecShuffleDynamicOp op, OpAdaptor adaptor,
2865 mlir::ConversionPatternRewriter &rewriter)
const {
2877 mlir::Location loc = op.getLoc();
2878 mlir::Value input = adaptor.getVec();
2879 mlir::Type llvmIndexVecType =
2880 getTypeConverter()->convertType(op.getIndices().getType());
2881 mlir::Type llvmIndexType = getTypeConverter()->convertType(
2882 elementTypeIfVector(op.getIndices().getType()));
2884 mlir::cast<cir::VectorType>(op.getVec().getType()).getSize();
2886 uint64_t maskBits = llvm::NextPowerOf2(numElements - 1) - 1;
2887 mlir::Value maskValue = rewriter.create<mlir::LLVM::ConstantOp>(
2888 loc, llvmIndexType, rewriter.getIntegerAttr(llvmIndexType, maskBits));
2889 mlir::Value maskVector =
2890 rewriter.create<mlir::LLVM::UndefOp>(loc, llvmIndexVecType);
2892 for (uint64_t i = 0; i < numElements; ++i) {
2893 mlir::Value idxValue =
2894 rewriter.create<mlir::LLVM::ConstantOp>(loc, rewriter.getI64Type(), i);
2895 maskVector = rewriter.create<mlir::LLVM::InsertElementOp>(
2896 loc, maskVector, maskValue, idxValue);
2899 mlir::Value maskedIndices = rewriter.create<mlir::LLVM::AndOp>(
2900 loc, llvmIndexVecType, adaptor.getIndices(), maskVector);
2901 mlir::Value result = rewriter.create<mlir::LLVM::UndefOp>(
2902 loc, getTypeConverter()->convertType(op.getVec().getType()));
2903 for (uint64_t i = 0; i < numElements; ++i) {
2904 mlir::Value iValue =
2905 rewriter.create<mlir::LLVM::ConstantOp>(loc, rewriter.getI64Type(), i);
2906 mlir::Value indexValue = rewriter.create<mlir::LLVM::ExtractElementOp>(
2907 loc, maskedIndices, iValue);
2908 mlir::Value valueAtIndex =
2909 rewriter.create<mlir::LLVM::ExtractElementOp>(loc, input, indexValue);
2910 result = rewriter.create<mlir::LLVM::InsertElementOp>(loc, result,
2911 valueAtIndex, iValue);
2913 rewriter.replaceOp(op, result);
2914 return mlir::success();
2917mlir::LogicalResult CIRToLLVMVecTernaryOpLowering::matchAndRewrite(
2918 cir::VecTernaryOp op, OpAdaptor adaptor,
2919 mlir::ConversionPatternRewriter &rewriter)
const {
2921 mlir::Value bitVec = rewriter.create<mlir::LLVM::ICmpOp>(
2922 op.getLoc(), mlir::LLVM::ICmpPredicate::ne, adaptor.getCond(),
2923 rewriter.create<mlir::LLVM::ZeroOp>(
2924 op.getCond().getLoc(),
2925 typeConverter->convertType(op.getCond().getType())));
2926 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(
2927 op, bitVec, adaptor.getLhs(), adaptor.getRhs());
2928 return mlir::success();
2931mlir::LogicalResult CIRToLLVMComplexAddOpLowering::matchAndRewrite(
2932 cir::ComplexAddOp op, OpAdaptor adaptor,
2933 mlir::ConversionPatternRewriter &rewriter)
const {
2934 mlir::Value lhs = adaptor.getLhs();
2935 mlir::Value rhs = adaptor.getRhs();
2936 mlir::Location loc = op.getLoc();
2938 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
2939 mlir::Type complexElemTy =
2940 getTypeConverter()->convertType(
complexType.getElementType());
2942 rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, lhs, 0);
2944 rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, lhs, 1);
2946 rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, rhs, 0);
2948 rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, rhs, 1);
2950 mlir::Value newReal;
2951 mlir::Value newImag;
2952 if (complexElemTy.isInteger()) {
2953 newReal = rewriter.create<mlir::LLVM::AddOp>(loc, complexElemTy, lhsReal,
2955 newImag = rewriter.create<mlir::LLVM::AddOp>(loc, complexElemTy, lhsImag,
2960 newReal = rewriter.create<mlir::LLVM::FAddOp>(loc, complexElemTy, lhsReal,
2962 newImag = rewriter.create<mlir::LLVM::FAddOp>(loc, complexElemTy, lhsImag,
2966 mlir::Type complexLLVMTy =
2967 getTypeConverter()->convertType(op.getResult().getType());
2968 auto initialComplex =
2969 rewriter.create<mlir::LLVM::PoisonOp>(op->getLoc(), complexLLVMTy);
2971 auto realComplex = rewriter.create<mlir::LLVM::InsertValueOp>(
2972 op->getLoc(), initialComplex, newReal, 0);
2974 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(op, realComplex,
2977 return mlir::success();
2980mlir::LogicalResult CIRToLLVMComplexCreateOpLowering::matchAndRewrite(
2981 cir::ComplexCreateOp op, OpAdaptor adaptor,
2982 mlir::ConversionPatternRewriter &rewriter)
const {
2983 mlir::Type complexLLVMTy =
2984 getTypeConverter()->convertType(op.getResult().getType());
2985 auto initialComplex =
2986 rewriter.create<mlir::LLVM::UndefOp>(op->getLoc(), complexLLVMTy);
2988 auto realComplex = rewriter.create<mlir::LLVM::InsertValueOp>(
2989 op->getLoc(), initialComplex, adaptor.getReal(), 0);
2991 auto complex = rewriter.create<mlir::LLVM::InsertValueOp>(
2992 op->getLoc(), realComplex, adaptor.getImag(), 1);
2994 rewriter.replaceOp(op, complex);
2995 return mlir::success();
2998mlir::LogicalResult CIRToLLVMComplexRealOpLowering::matchAndRewrite(
2999 cir::ComplexRealOp op, OpAdaptor adaptor,
3000 mlir::ConversionPatternRewriter &rewriter)
const {
3001 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
3002 mlir::Value operand = adaptor.getOperand();
3003 if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) {
3004 operand = mlir::LLVM::ExtractValueOp::create(
3005 rewriter, op.getLoc(), resultLLVMTy, operand,
3006 llvm::ArrayRef<std::int64_t>{0});
3008 rewriter.replaceOp(op, operand);
3009 return mlir::success();
3012mlir::LogicalResult CIRToLLVMComplexSubOpLowering::matchAndRewrite(
3013 cir::ComplexSubOp op, OpAdaptor adaptor,
3014 mlir::ConversionPatternRewriter &rewriter)
const {
3015 mlir::Value lhs = adaptor.getLhs();
3016 mlir::Value rhs = adaptor.getRhs();
3017 mlir::Location loc = op.getLoc();
3019 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
3020 mlir::Type complexElemTy =
3021 getTypeConverter()->convertType(
complexType.getElementType());
3023 rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, lhs, 0);
3025 rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, lhs, 1);
3027 rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, rhs, 0);
3029 rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, rhs, 1);
3031 mlir::Value newReal;
3032 mlir::Value newImag;
3033 if (complexElemTy.isInteger()) {
3034 newReal = rewriter.create<mlir::LLVM::SubOp>(loc, complexElemTy, lhsReal,
3036 newImag = rewriter.create<mlir::LLVM::SubOp>(loc, complexElemTy, lhsImag,
3041 newReal = rewriter.create<mlir::LLVM::FSubOp>(loc, complexElemTy, lhsReal,
3043 newImag = rewriter.create<mlir::LLVM::FSubOp>(loc, complexElemTy, lhsImag,
3047 mlir::Type complexLLVMTy =
3048 getTypeConverter()->convertType(op.getResult().getType());
3049 auto initialComplex =
3050 rewriter.create<mlir::LLVM::PoisonOp>(op->getLoc(), complexLLVMTy);
3052 auto realComplex = rewriter.create<mlir::LLVM::InsertValueOp>(
3053 op->getLoc(), initialComplex, newReal, 0);
3055 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(op, realComplex,
3058 return mlir::success();
3061mlir::LogicalResult CIRToLLVMComplexImagOpLowering::matchAndRewrite(
3062 cir::ComplexImagOp op, OpAdaptor adaptor,
3063 mlir::ConversionPatternRewriter &rewriter)
const {
3064 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
3065 rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractValueOp>(
3066 op, resultLLVMTy, adaptor.getOperand(), llvm::ArrayRef<std::int64_t>{1});
3067 return mlir::success();
3071 mlir::MLIRContext *context,
3072 unsigned &storageSize) {
3073 return TypeSwitch<mlir::Type, mlir::IntegerType>(storageType)
3074 .Case<cir::ArrayType>([&](cir::ArrayType atTy) {
3075 storageSize = atTy.getSize() * 8;
3076 return mlir::IntegerType::get(context, storageSize);
3078 .Case<cir::IntType>([&](cir::IntType intTy) {
3079 storageSize = intTy.getWidth();
3080 return mlir::IntegerType::get(context, storageSize);
3082 .Default([](mlir::Type) -> mlir::IntegerType {
3084 "Either ArrayType or IntType expected for bitfields storage");
3088mlir::LogicalResult CIRToLLVMSetBitfieldOpLowering::matchAndRewrite(
3089 cir::SetBitfieldOp op, OpAdaptor adaptor,
3090 mlir::ConversionPatternRewriter &rewriter)
const {
3091 mlir::OpBuilder::InsertionGuard guard(rewriter);
3092 rewriter.setInsertionPoint(op);
3094 cir::BitfieldInfoAttr info = op.getBitfieldInfo();
3095 uint64_t size = info.getSize();
3096 uint64_t offset = info.getOffset();
3097 mlir::Type storageType = info.getStorageType();
3098 mlir::MLIRContext *context = storageType.getContext();
3100 unsigned storageSize = 0;
3102 mlir::IntegerType intType =
3105 mlir::Value srcVal =
createIntCast(rewriter, adaptor.getSrc(), intType);
3106 unsigned srcWidth = storageSize;
3107 mlir::Value resultVal = srcVal;
3109 if (storageSize != size) {
3110 assert(storageSize > size &&
"Invalid bitfield size.");
3112 mlir::Value val = rewriter.create<mlir::LLVM::LoadOp>(
3113 op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(),
3114 op.getIsVolatile());
3117 createAnd(rewriter, srcVal, llvm::APInt::getLowBitsSet(srcWidth, size));
3119 srcVal =
createShL(rewriter, srcVal, offset);
3123 ~llvm::APInt::getBitsSet(srcWidth, offset, offset + size));
3126 srcVal = rewriter.create<mlir::LLVM::OrOp>(op.getLoc(), val, srcVal);
3129 rewriter.create<mlir::LLVM::StoreOp>(op.getLoc(), srcVal, adaptor.getAddr(),
3130 op.getAlignment(), op.getIsVolatile());
3132 mlir::Type resultTy = getTypeConverter()->convertType(op.getType());
3134 if (info.getIsSigned()) {
3135 assert(size <= storageSize);
3136 unsigned highBits = storageSize - size;
3139 resultVal =
createShL(rewriter, resultVal, highBits);
3140 resultVal =
createAShR(rewriter, resultVal, highBits);
3145 mlir::cast<mlir::IntegerType>(resultTy),
3146 info.getIsSigned());
3148 rewriter.replaceOp(op, resultVal);
3149 return mlir::success();
3152mlir::LogicalResult CIRToLLVMComplexImagPtrOpLowering::matchAndRewrite(
3153 cir::ComplexImagPtrOp op, OpAdaptor adaptor,
3154 mlir::ConversionPatternRewriter &rewriter)
const {
3155 cir::PointerType operandTy = op.getOperand().getType();
3156 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
3157 mlir::Type elementLLVMTy =
3158 getTypeConverter()->convertType(operandTy.getPointee());
3160 mlir::LLVM::GEPArg gepIndices[2] = {{0}, {1}};
3161 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
3162 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
3163 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
3164 op, resultLLVMTy, elementLLVMTy, adaptor.getOperand(), gepIndices,
3166 return mlir::success();
3169mlir::LogicalResult CIRToLLVMComplexRealPtrOpLowering::matchAndRewrite(
3170 cir::ComplexRealPtrOp op, OpAdaptor adaptor,
3171 mlir::ConversionPatternRewriter &rewriter)
const {
3172 cir::PointerType operandTy = op.getOperand().getType();
3173 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
3174 mlir::Type elementLLVMTy =
3175 getTypeConverter()->convertType(operandTy.getPointee());
3177 mlir::LLVM::GEPArg gepIndices[2] = {0, 0};
3178 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
3179 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
3180 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
3181 op, resultLLVMTy, elementLLVMTy, adaptor.getOperand(), gepIndices,
3183 return mlir::success();
3186mlir::LogicalResult CIRToLLVMGetBitfieldOpLowering::matchAndRewrite(
3187 cir::GetBitfieldOp op, OpAdaptor adaptor,
3188 mlir::ConversionPatternRewriter &rewriter)
const {
3190 mlir::OpBuilder::InsertionGuard guard(rewriter);
3191 rewriter.setInsertionPoint(op);
3193 cir::BitfieldInfoAttr info = op.getBitfieldInfo();
3195 uint64_t offset = info.getOffset();
3196 mlir::Type storageType = info.getStorageType();
3197 mlir::MLIRContext *context = storageType.getContext();
3198 unsigned storageSize = 0;
3200 mlir::IntegerType intType =
3203 mlir::Value val = rewriter.create<mlir::LLVM::LoadOp>(
3204 op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(),
3205 op.getIsVolatile());
3206 val = rewriter.create<mlir::LLVM::BitcastOp>(op.getLoc(), intType, val);
3208 if (info.getIsSigned()) {
3209 assert(
static_cast<unsigned>(offset + size) <= storageSize);
3210 unsigned highBits = storageSize - offset - size;
3211 val =
createShL(rewriter, val, highBits);
3212 val =
createAShR(rewriter, val, offset + highBits);
3216 if (
static_cast<unsigned>(offset) + size < storageSize)
3218 llvm::APInt::getLowBitsSet(storageSize, size));
3221 mlir::Type resTy = getTypeConverter()->convertType(op.getType());
3223 rewriter, val, mlir::cast<mlir::IntegerType>(resTy), info.getIsSigned());
3224 rewriter.replaceOp(op, newOp);
3225 return mlir::success();
3228mlir::LogicalResult CIRToLLVMInlineAsmOpLowering::matchAndRewrite(
3229 cir::InlineAsmOp op, OpAdaptor adaptor,
3230 mlir::ConversionPatternRewriter &rewriter)
const {
3232 if (op.getNumResults())
3233 llResTy = getTypeConverter()->convertType(op.getType(0));
3235 cir::AsmFlavor dialect = op.getAsmFlavor();
3236 mlir::LLVM::AsmDialect llDialect = dialect == cir::AsmFlavor::x86_att
3237 ? mlir::LLVM::AsmDialect::AD_ATT
3238 : mlir::LLVM::AsmDialect::AD_Intel;
3240 SmallVector<mlir::Attribute> opAttrs;
3241 StringRef llvmAttrName = mlir::LLVM::InlineAsmOp::getElementTypeAttrName();
3247 if (!op.getNumResults())
3248 opAttrs.push_back(mlir::Attribute());
3250 SmallVector<mlir::Value> llvmOperands;
3251 SmallVector<mlir::Value> cirOperands;
3252 for (
auto const &[llvmOp, cirOp] :
3253 zip(adaptor.getAsmOperands(), op.getAsmOperands())) {
3254 append_range(llvmOperands, llvmOp);
3255 append_range(cirOperands, cirOp);
3260 for (
auto const &[cirOpAttr, cirOp] :
3261 zip(op.getOperandAttrs(), cirOperands)) {
3263 opAttrs.push_back(mlir::Attribute());
3267 llvm::SmallVector<mlir::NamedAttribute, 1> attrs;
3268 cir::PointerType typ = mlir::cast<cir::PointerType>(cirOp.getType());
3270 *getTypeConverter(), dataLayout, typ.getPointee()));
3272 attrs.push_back(rewriter.getNamedAttr(llvmAttrName, typAttr));
3273 mlir::DictionaryAttr newDict = rewriter.getDictionaryAttr(attrs);
3274 opAttrs.push_back(newDict);
3277 rewriter.replaceOpWithNewOp<mlir::LLVM::InlineAsmOp>(
3278 op, llResTy, llvmOperands, op.getAsmStringAttr(), op.getConstraintsAttr(),
3279 op.getSideEffectsAttr(),
3282 mlir::LLVM::TailCallKindAttr::get(
3283 getContext(), mlir::LLVM::tailcallkind::TailCallKind::None),
3284 mlir::LLVM::AsmDialectAttr::get(getContext(), llDialect),
3285 rewriter.getArrayAttr(opAttrs));
3287 return mlir::success();
3290mlir::LogicalResult CIRToLLVMVAStartOpLowering::matchAndRewrite(
3291 cir::VAStartOp op, OpAdaptor adaptor,
3292 mlir::ConversionPatternRewriter &rewriter)
const {
3293 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
3294 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
3295 adaptor.getArgList());
3296 rewriter.replaceOpWithNewOp<mlir::LLVM::VaStartOp>(op, vaList);
3297 return mlir::success();
3300mlir::LogicalResult CIRToLLVMVAEndOpLowering::matchAndRewrite(
3301 cir::VAEndOp op, OpAdaptor adaptor,
3302 mlir::ConversionPatternRewriter &rewriter)
const {
3303 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
3304 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
3305 adaptor.getArgList());
3306 rewriter.replaceOpWithNewOp<mlir::LLVM::VaEndOp>(op, vaList);
3307 return mlir::success();
3310mlir::LogicalResult CIRToLLVMVAArgOpLowering::matchAndRewrite(
3311 cir::VAArgOp op, OpAdaptor adaptor,
3312 mlir::ConversionPatternRewriter &rewriter)
const {
3314 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
3315 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
3316 adaptor.getArgList());
3318 mlir::Type llvmType =
3319 getTypeConverter()->convertType(op->getResultTypes().front());
3321 return mlir::failure();
3323 rewriter.replaceOpWithNewOp<mlir::LLVM::VaArgOp>(op, llvmType, vaList);
3324 return mlir::success();
3328 return std::make_unique<ConvertCIRToLLVMPass>();
3336std::unique_ptr<llvm::Module>
3338 llvm::TimeTraceScope scope(
"lower from CIR to LLVM directly");
3340 mlir::MLIRContext *mlirCtx = mlirModule.getContext();
3342 mlir::PassManager pm(mlirCtx);
3345 (void)mlir::applyPassManagerCLOptions(pm);
3347 if (mlir::failed(pm.run(mlirModule))) {
3350 "The pass manager failed to lower CIR to LLVMIR dialect!");
3353 mlir::registerBuiltinDialectTranslation(*mlirCtx);
3354 mlir::registerLLVMDialectTranslation(*mlirCtx);
3357 llvm::TimeTraceScope translateScope(
"translateModuleToLLVMIR");
3359 StringRef moduleName = mlirModule.getName().value_or(
"CIRToLLVMModule");
3360 std::unique_ptr<llvm::Module> llvmModule =
3361 mlir::translateModuleToLLVMIR(mlirModule, llvmCtx, moduleName);
3365 report_fatal_error(
"Lowering from LLVMIR dialect to llvm IR failed!");
static bool isUnsigned(SValBuilder &SVB, NonLoc Value)
static llvm::StringRef getLinkageAttrNameString()
Returns the name used for the linkage attribute.
mlir::Value createLShR(mlir::OpBuilder &bld, mlir::Value lhs, unsigned rhs)
mlir::Value createShL(mlir::OpBuilder &bld, mlir::Value lhs, unsigned rhs)
std::optional< mlir::Attribute > lowerConstArrayAttr(cir::ConstArrayAttr constArr, const mlir::TypeConverter *converter)
mlir::Value createAShR(mlir::OpBuilder &bld, mlir::Value lhs, unsigned rhs)
mlir::Value createAnd(mlir::OpBuilder &bld, mlir::Value lhs, const llvm::APInt &rhs)
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::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)
const internal::VariadicAllOfMatcher< Attr > attr
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const AstTypeMatcher< ComplexType > complexType
unsigned kind
All of the diagnostics that can be emitted by the frontend.
Diagnostic wrappers for TextAPI types for error reporting.
void populateCIRPreLoweringPasses(mlir::OpPassManager &pm)
void registerCIRDialectTranslation(mlir::MLIRContext &context)
char __ovld __cnfn clz(char)
Returns the number of leading 0-bits in x, starting at the most significant bit position.
char __ovld __cnfn ctz(char)
Returns the count of trailing 0-bits in x.
float __ovld __cnfn length(float)
Return the length of vector p, i.e., sqrt(p.x2 + p.y 2 + ...)
char __ovld __cnfn select(char, char, char)
For each component of a vector type, result[i] = if MSB of c[i] is set ?
static bool dataMemberType()
static bool opGlobalConstant()
static bool addressSpace()
static bool opGlobalThreadLocal()
static bool globalViewIntLowering()
static bool opAllocaAnnotations()
static bool atomicScope()
static bool opLoadStoreTbaa()
static bool optInfoAttr()
static bool opFuncExtraAttrs()
static bool opCallLandingPad()
static bool vaArgABILowering()
static bool fpConstraints()
static bool lowerModeOptLevel()
static bool opCallCallConv()
static bool opFuncCallingConv()
static bool aggValueSlotVolatile()
static bool fastMathFlags()
static bool opCallContinueBlock()
static bool opLoadStoreNontemporal()
static bool atomicSyncScopeID()
static bool opFuncMultipleReturnVals()
void runOnOperation() final
StringRef getDescription() const override
StringRef getArgument() const override
void getDependentDialects(mlir::DialectRegistry ®istry) const override
void processCIRAttrs(mlir::ModuleOp module)