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"
40#include "llvm/ADT/TypeSwitch.h"
41#include "llvm/IR/Module.h"
42#include "llvm/Support/ErrorHandling.h"
43#include "llvm/Support/TimeProfiler.h"
58mlir::Type elementTypeIfVector(mlir::Type type) {
59 return llvm::TypeSwitch<mlir::Type, mlir::Type>(type)
60 .Case<cir::VectorType, mlir::VectorType>(
61 [](
auto p) {
return p.getElementType(); })
62 .
Default([](mlir::Type p) {
return p; });
70 mlir::DataLayout
const &dataLayout,
74 if (isa<cir::BoolType>(type)) {
75 return mlir::IntegerType::get(type.getContext(),
76 dataLayout.getTypeSizeInBits(type));
79 return converter.convertType(type);
83 mlir::IntegerType dstTy,
84 bool isSigned =
false) {
85 mlir::Type srcTy = src.getType();
86 assert(mlir::isa<mlir::IntegerType>(srcTy));
88 unsigned srcWidth = mlir::cast<mlir::IntegerType>(srcTy).getWidth();
89 unsigned dstWidth = mlir::cast<mlir::IntegerType>(dstTy).getWidth();
90 mlir::Location loc = src.getLoc();
92 if (dstWidth > srcWidth && isSigned)
93 return mlir::LLVM::SExtOp::create(bld, loc, dstTy, src);
94 if (dstWidth > srcWidth)
95 return mlir::LLVM::ZExtOp::create(bld, loc, dstTy, src);
96 if (dstWidth < srcWidth)
97 return mlir::LLVM::TruncOp::create(bld, loc, dstTy, src);
98 return mlir::LLVM::BitcastOp::create(bld, loc, dstTy, src);
101static mlir::LLVM::Visibility
103 switch (visibilityKind) {
104 case cir::VisibilityKind::Default:
105 return ::mlir::LLVM::Visibility::Default;
106 case cir::VisibilityKind::Hidden:
107 return ::mlir::LLVM::Visibility::Hidden;
108 case cir::VisibilityKind::Protected:
109 return ::mlir::LLVM::Visibility::Protected;
117 mlir::DataLayout
const &dataLayout,
118 cir::LoadOp op, mlir::Value value) {
121 if (
auto boolTy = mlir::dyn_cast<cir::BoolType>(op.getType())) {
123 assert(value.getType().isInteger(dataLayout.getTypeSizeInBits(boolTy)));
133static mlir::Value
emitToMemory(mlir::ConversionPatternRewriter &rewriter,
134 mlir::DataLayout
const &dataLayout,
135 mlir::Type origType, mlir::Value value) {
138 if (
auto boolTy = mlir::dyn_cast<cir::BoolType>(origType)) {
140 mlir::IntegerType memType =
141 rewriter.getIntegerType(dataLayout.getTypeSizeInBits(boolTy));
149 using CIR = cir::GlobalLinkageKind;
150 using LLVM = mlir::LLVM::Linkage;
153 case CIR::AvailableExternallyLinkage:
154 return LLVM::AvailableExternally;
155 case CIR::CommonLinkage:
157 case CIR::ExternalLinkage:
158 return LLVM::External;
159 case CIR::ExternalWeakLinkage:
160 return LLVM::ExternWeak;
161 case CIR::InternalLinkage:
162 return LLVM::Internal;
163 case CIR::LinkOnceAnyLinkage:
164 return LLVM::Linkonce;
165 case CIR::LinkOnceODRLinkage:
166 return LLVM::LinkonceODR;
167 case CIR::PrivateLinkage:
168 return LLVM::Private;
169 case CIR::WeakAnyLinkage:
171 case CIR::WeakODRLinkage:
172 return LLVM::WeakODR;
174 llvm_unreachable(
"Unknown CIR linkage type");
177mlir::LogicalResult CIRToLLVMCopyOpLowering::matchAndRewrite(
178 cir::CopyOp op, OpAdaptor adaptor,
179 mlir::ConversionPatternRewriter &rewriter)
const {
180 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
181 const mlir::Value
length = mlir::LLVM::ConstantOp::create(
182 rewriter, op.getLoc(), rewriter.getI32Type(), op.getLength(layout));
184 rewriter.replaceOpWithNewOp<mlir::LLVM::MemcpyOp>(
185 op, adaptor.getDst(), adaptor.getSrc(),
length, op.getIsVolatile());
186 return mlir::success();
189mlir::LogicalResult CIRToLLVMSqrtOpLowering::matchAndRewrite(
190 cir::SqrtOp op, OpAdaptor adaptor,
191 mlir::ConversionPatternRewriter &rewriter)
const {
192 mlir::Type resTy = typeConverter->convertType(op.getType());
193 rewriter.replaceOpWithNewOp<mlir::LLVM::SqrtOp>(op, resTy, adaptor.getSrc());
194 return mlir::success();
197mlir::LogicalResult CIRToLLVMCosOpLowering::matchAndRewrite(
198 cir::CosOp op, OpAdaptor adaptor,
199 mlir::ConversionPatternRewriter &rewriter)
const {
200 mlir::Type resTy = typeConverter->convertType(op.getType());
201 rewriter.replaceOpWithNewOp<mlir::LLVM::CosOp>(op, resTy, adaptor.getSrc());
202 return mlir::success();
205mlir::LogicalResult CIRToLLVMExpOpLowering::matchAndRewrite(
206 cir::ExpOp op, OpAdaptor adaptor,
207 mlir::ConversionPatternRewriter &rewriter)
const {
208 mlir::Type resTy = typeConverter->convertType(op.getType());
209 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpOp>(op, resTy, adaptor.getSrc());
210 return mlir::success();
213mlir::LogicalResult CIRToLLVMExp2OpLowering::matchAndRewrite(
214 cir::Exp2Op op, OpAdaptor adaptor,
215 mlir::ConversionPatternRewriter &rewriter)
const {
216 mlir::Type resTy = typeConverter->convertType(op.getType());
217 rewriter.replaceOpWithNewOp<mlir::LLVM::Exp2Op>(op, resTy, adaptor.getSrc());
218 return mlir::success();
221mlir::LogicalResult CIRToLLVMFloorOpLowering::matchAndRewrite(
222 cir::FloorOp op, OpAdaptor adaptor,
223 mlir::ConversionPatternRewriter &rewriter)
const {
224 mlir::Type resTy = typeConverter->convertType(op.getType());
225 rewriter.replaceOpWithNewOp<mlir::LLVM::FFloorOp>(op, resTy,
227 return mlir::success();
231 mlir::Value llvmSrc, mlir::Type llvmDstIntTy,
233 uint64_t cirDstIntWidth) {
234 if (cirSrcWidth == cirDstIntWidth)
237 auto loc = llvmSrc.getLoc();
238 if (cirSrcWidth < cirDstIntWidth) {
240 return mlir::LLVM::ZExtOp::create(rewriter, loc, llvmDstIntTy, llvmSrc);
241 return mlir::LLVM::SExtOp::create(rewriter, loc, llvmDstIntTy, llvmSrc);
245 return mlir::LLVM::TruncOp::create(rewriter, loc, llvmDstIntTy, llvmSrc);
251 mlir::ConversionPatternRewriter &rewriter,
252 const mlir::TypeConverter *converter,
254 : parentOp(parentOp), rewriter(rewriter), converter(converter),
255 lowerMod(lowerMod) {}
257 mlir::Value
visit(mlir::Attribute attr) {
258 return llvm::TypeSwitch<mlir::Attribute, mlir::Value>(attr)
259 .Case<cir::IntAttr, cir::FPAttr, cir::ConstComplexAttr,
260 cir::ConstArrayAttr, cir::ConstRecordAttr, cir::ConstVectorAttr,
261 cir::ConstPtrAttr, cir::GlobalViewAttr, cir::TypeInfoAttr,
262 cir::UndefAttr, cir::VTableAttr, cir::ZeroAttr>(
264 .Default([&](
auto attrT) {
return mlir::Value(); });
269 mlir::Value
visitCirAttr(cir::ConstComplexAttr complexAttr);
281 mlir::Operation *parentOp;
282 mlir::ConversionPatternRewriter &rewriter;
283 const mlir::TypeConverter *converter;
289 const mlir::Attribute attr,
290 mlir::ConversionPatternRewriter &rewriter,
291 const mlir::TypeConverter *converter,
293 CIRAttrToValue valueConverter(parentOp, rewriter, converter, lowerMod);
294 mlir::Value value = valueConverter.
visit(attr);
296 llvm_unreachable(
"unhandled attribute type");
301 cir::SideEffect sideEffect,
302 mlir::LLVM::MemoryEffectsAttr &memoryEffect,
303 bool &noUnwind,
bool &willReturn) {
304 using mlir::LLVM::ModRefInfo;
306 switch (sideEffect) {
307 case cir::SideEffect::All:
309 noUnwind = isNothrow;
313 case cir::SideEffect::Pure:
314 memoryEffect = mlir::LLVM::MemoryEffectsAttr::get(
315 callOp->getContext(), ModRefInfo::Ref,
325 case cir::SideEffect::Const:
326 memoryEffect = mlir::LLVM::MemoryEffectsAttr::get(
327 callOp->getContext(), ModRefInfo::NoModRef,
328 ModRefInfo::NoModRef,
329 ModRefInfo::NoModRef,
330 ModRefInfo::NoModRef,
331 ModRefInfo::NoModRef,
332 ModRefInfo::NoModRef);
339static mlir::LLVM::CallIntrinsicOp
341 mlir::Location loc,
const llvm::Twine &intrinsicName,
342 mlir::Type resultTy, mlir::ValueRange operands) {
343 auto intrinsicNameAttr =
344 mlir::StringAttr::get(rewriter.getContext(), intrinsicName);
345 return mlir::LLVM::CallIntrinsicOp::create(rewriter, loc, resultTy,
346 intrinsicNameAttr, operands);
350 mlir::ConversionPatternRewriter &rewriter, mlir::Operation *op,
351 const llvm::Twine &intrinsicName, mlir::Type resultTy,
352 mlir::ValueRange operands) {
354 rewriter, op->getLoc(), intrinsicName, resultTy, operands);
355 rewriter.replaceOp(op, callIntrinOp.getOperation());
359mlir::LogicalResult CIRToLLVMLLVMIntrinsicCallOpLowering::matchAndRewrite(
360 cir::LLVMIntrinsicCallOp op, OpAdaptor adaptor,
361 mlir::ConversionPatternRewriter &rewriter)
const {
362 mlir::Type llvmResTy =
363 getTypeConverter()->convertType(op->getResultTypes()[0]);
365 return op.emitError(
"expected LLVM result type");
366 StringRef name = op.getIntrinsicName();
379 adaptor.getOperands());
380 return mlir::success();
385 mlir::Location loc = parentOp->getLoc();
386 return mlir::LLVM::ConstantOp::create(
387 rewriter, loc, converter->convertType(intAttr.getType()),
393 mlir::Location loc = parentOp->getLoc();
394 return mlir::LLVM::ConstantOp::create(
395 rewriter, loc, converter->convertType(fltAttr.getType()),
401 auto complexType = mlir::cast<cir::ComplexType>(complexAttr.getType());
402 mlir::Type complexElemTy = complexType.getElementType();
403 mlir::Type complexElemLLVMTy = converter->convertType(complexElemTy);
405 mlir::Attribute components[2];
406 if (
const auto intType = mlir::dyn_cast<cir::IntType>(complexElemTy)) {
407 components[0] = rewriter.getIntegerAttr(
409 mlir::cast<cir::IntAttr>(complexAttr.getReal()).getValue());
410 components[1] = rewriter.getIntegerAttr(
412 mlir::cast<cir::IntAttr>(complexAttr.getImag()).getValue());
414 components[0] = rewriter.getFloatAttr(
416 mlir::cast<cir::FPAttr>(complexAttr.getReal()).getValue());
417 components[1] = rewriter.getFloatAttr(
419 mlir::cast<cir::FPAttr>(complexAttr.getImag()).getValue());
422 mlir::Location loc = parentOp->getLoc();
423 return mlir::LLVM::ConstantOp::create(
424 rewriter, loc, converter->convertType(complexAttr.getType()),
425 rewriter.getArrayAttr(components));
430 mlir::Location loc = parentOp->getLoc();
431 if (ptrAttr.isNullValue()) {
432 return mlir::LLVM::ZeroOp::create(
433 rewriter, loc, converter->convertType(ptrAttr.getType()));
435 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
436 mlir::Value ptrVal = mlir::LLVM::ConstantOp::create(
438 rewriter.getIntegerType(layout.getTypeSizeInBits(ptrAttr.getType())),
439 ptrAttr.getValue().getInt());
440 return mlir::LLVM::IntToPtrOp::create(
441 rewriter, loc, converter->convertType(ptrAttr.getType()), ptrVal);
446 mlir::Type llvmTy = converter->convertType(attr.getType());
447 mlir::Location loc = parentOp->getLoc();
450 if (attr.hasTrailingZeros()) {
451 mlir::Type arrayTy = attr.getType();
452 result = mlir::LLVM::ZeroOp::create(rewriter, loc,
453 converter->convertType(arrayTy));
455 result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
459 if (
auto arrayAttr = mlir::dyn_cast<mlir::ArrayAttr>(attr.getElts())) {
460 for (
auto [idx, elt] : llvm::enumerate(arrayAttr)) {
461 mlir::DataLayout dataLayout(parentOp->getParentOfType<mlir::ModuleOp>());
462 mlir::Value init =
visit(elt);
464 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
466 }
else if (
auto strAttr = mlir::dyn_cast<mlir::StringAttr>(attr.getElts())) {
469 auto arrayTy = mlir::dyn_cast<cir::ArrayType>(strAttr.getType());
470 assert(arrayTy &&
"String attribute must have an array type");
471 mlir::Type eltTy = arrayTy.getElementType();
472 for (
auto [idx, elt] : llvm::enumerate(strAttr)) {
473 auto init = mlir::LLVM::ConstantOp::create(
474 rewriter, loc, converter->convertType(eltTy), elt);
476 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
479 llvm_unreachable(
"unexpected ConstArrayAttr elements");
487 const mlir::Type llvmTy = converter->convertType(constRecord.getType());
488 const mlir::Location loc = parentOp->getLoc();
489 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
492 for (
auto [idx, elt] : llvm::enumerate(constRecord.getMembers())) {
493 mlir::Value init =
visit(elt);
495 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
503 const mlir::Type llvmTy = converter->convertType(attr.getType());
504 const mlir::Location loc = parentOp->getLoc();
507 for (
const mlir::Attribute elementAttr : attr.getElts()) {
508 mlir::Attribute mlirAttr;
509 if (
auto intAttr = mlir::dyn_cast<cir::IntAttr>(elementAttr)) {
510 mlirAttr = rewriter.getIntegerAttr(
511 converter->convertType(intAttr.getType()), intAttr.getValue());
512 }
else if (
auto floatAttr = mlir::dyn_cast<cir::FPAttr>(elementAttr)) {
513 mlirAttr = rewriter.getFloatAttr(
514 converter->convertType(floatAttr.getType()), floatAttr.getValue());
517 "vector constant with an element that is neither an int nor a float");
519 mlirValues.push_back(mlirAttr);
522 return mlir::LLVM::ConstantOp::create(
523 rewriter, loc, llvmTy,
524 mlir::DenseElementsAttr::get(mlir::cast<mlir::ShapedType>(llvmTy),
530 auto moduleOp = parentOp->getParentOfType<mlir::ModuleOp>();
531 mlir::DataLayout dataLayout(moduleOp);
532 mlir::Type sourceType;
534 llvm::StringRef symName;
535 mlir::Operation *sourceSymbol =
536 mlir::SymbolTable::lookupSymbolIn(moduleOp, globalAttr.getSymbol());
537 if (
auto llvmSymbol = dyn_cast<mlir::LLVM::GlobalOp>(sourceSymbol)) {
538 sourceType = llvmSymbol.getType();
539 symName = llvmSymbol.getSymName();
540 }
else if (
auto cirSymbol = dyn_cast<cir::GlobalOp>(sourceSymbol)) {
543 symName = cirSymbol.getSymName();
544 }
else if (
auto llvmFun = dyn_cast<mlir::LLVM::LLVMFuncOp>(sourceSymbol)) {
545 sourceType = llvmFun.getFunctionType();
546 symName = llvmFun.getSymName();
547 }
else if (
auto fun = dyn_cast<cir::FuncOp>(sourceSymbol)) {
548 sourceType = converter->convertType(fun.getFunctionType());
549 symName = fun.getSymName();
550 }
else if (
auto alias = dyn_cast<mlir::LLVM::AliasOp>(sourceSymbol)) {
551 sourceType = alias.getType();
552 symName = alias.getSymName();
554 llvm_unreachable(
"Unexpected GlobalOp type");
557 mlir::Location loc = parentOp->getLoc();
558 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
559 rewriter, loc, mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
562 if (globalAttr.getIndices()) {
565 if (mlir::isa<mlir::LLVM::LLVMArrayType, mlir::LLVM::LLVMStructType>(
567 indices.push_back(0);
569 for (mlir::Attribute idx : globalAttr.getIndices()) {
570 auto intAttr = mlir::cast<mlir::IntegerAttr>(idx);
571 indices.push_back(intAttr.getValue().getSExtValue());
573 mlir::Type resTy = addrOp.getType();
574 mlir::Type eltTy = converter->convertType(sourceType);
576 mlir::LLVM::GEPOp::create(rewriter, loc, resTy, eltTy, addrOp, indices,
577 mlir::LLVM::GEPNoWrapFlags::none);
586 if (
auto ptrTy = mlir::dyn_cast<cir::PointerType>(globalAttr.getType())) {
587 mlir::Type llvmEltTy =
590 if (llvmEltTy == sourceType)
593 mlir::Type llvmDstTy = converter->convertType(globalAttr.getType());
594 return mlir::LLVM::BitcastOp::create(rewriter, parentOp->getLoc(),
598 llvm_unreachable(
"Expecting pointer or integer type for GlobalViewAttr");
603 mlir::Type llvmTy = converter->convertType(typeInfoAttr.getType());
604 mlir::Location loc = parentOp->getLoc();
605 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
607 for (
auto [idx, elt] : llvm::enumerate(typeInfoAttr.getData())) {
608 mlir::Value init =
visit(elt);
610 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
618 mlir::Location loc = parentOp->getLoc();
619 return mlir::LLVM::UndefOp::create(
620 rewriter, loc, converter->convertType(undefAttr.getType()));
625 mlir::Type llvmTy = converter->convertType(vtableArr.getType());
626 mlir::Location loc = parentOp->getLoc();
627 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
629 for (
auto [idx, elt] : llvm::enumerate(vtableArr.getData())) {
630 mlir::Value init =
visit(elt);
632 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
640 mlir::Location loc = parentOp->getLoc();
641 return mlir::LLVM::ZeroOp::create(rewriter, loc,
642 converter->convertType(attr.getType()));
650 mlir::ConversionPatternRewriter &rewriter)
651 : llvmType(type), rewriter(rewriter) {}
653 mlir::Attribute
visit(mlir::Attribute attr) {
654 return llvm::TypeSwitch<mlir::Attribute, mlir::Attribute>(attr)
655 .Case<cir::IntAttr, cir::FPAttr, cir::BoolAttr>(
657 .Default([&](
auto attrT) {
return mlir::Attribute(); });
661 return rewriter.getIntegerAttr(llvmType, attr.getValue());
665 return rewriter.getFloatAttr(llvmType, attr.getValue());
669 return rewriter.getBoolAttr(attr.getValue());
674 mlir::ConversionPatternRewriter &rewriter;
682 :
public mlir::PassWrapper<ConvertCIRToLLVMPass,
683 mlir::OperationPass<mlir::ModuleOp>> {
685 registry.insert<mlir::BuiltinDialect, mlir::DLTIDialect,
686 mlir::LLVM::LLVMDialect, mlir::func::FuncDialect>();
693 return "Convert the prepared CIR dialect module to LLVM dialect";
696 StringRef
getArgument()
const override {
return "cir-flat-to-llvm"; }
699mlir::LogicalResult CIRToLLVMACosOpLowering::matchAndRewrite(
700 cir::ACosOp op, OpAdaptor adaptor,
701 mlir::ConversionPatternRewriter &rewriter)
const {
702 mlir::Type resTy = typeConverter->convertType(op.getType());
703 rewriter.replaceOpWithNewOp<mlir::LLVM::ACosOp>(op, resTy,
704 adaptor.getOperands()[0]);
705 return mlir::success();
708mlir::LogicalResult CIRToLLVMASinOpLowering::matchAndRewrite(
709 cir::ASinOp op, OpAdaptor adaptor,
710 mlir::ConversionPatternRewriter &rewriter)
const {
711 mlir::Type resTy = typeConverter->convertType(op.getType());
712 rewriter.replaceOpWithNewOp<mlir::LLVM::ASinOp>(op, resTy, adaptor.getSrc());
713 return mlir::success();
716mlir::LogicalResult CIRToLLVMIsFPClassOpLowering::matchAndRewrite(
717 cir::IsFPClassOp op, OpAdaptor adaptor,
718 mlir::ConversionPatternRewriter &rewriter)
const {
719 mlir::Value src = adaptor.getSrc();
720 cir::FPClassTest flags = adaptor.getFlags();
721 mlir::IntegerType retTy = rewriter.getI1Type();
723 rewriter.replaceOpWithNewOp<mlir::LLVM::IsFPClass>(
724 op, retTy, src,
static_cast<uint32_t>(flags));
725 return mlir::success();
728mlir::LogicalResult CIRToLLVMAssumeOpLowering::matchAndRewrite(
729 cir::AssumeOp op, OpAdaptor adaptor,
730 mlir::ConversionPatternRewriter &rewriter)
const {
731 auto cond = adaptor.getPredicate();
732 rewriter.replaceOpWithNewOp<mlir::LLVM::AssumeOp>(op, cond);
733 return mlir::success();
736mlir::LogicalResult CIRToLLVMAssumeAlignedOpLowering::matchAndRewrite(
737 cir::AssumeAlignedOp op, OpAdaptor adaptor,
738 mlir::ConversionPatternRewriter &rewriter)
const {
739 SmallVector<mlir::Value, 3> opBundleArgs{adaptor.getPointer()};
741 auto alignment = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
742 adaptor.getAlignmentAttr());
743 opBundleArgs.push_back(alignment);
745 if (mlir::Value offset = adaptor.getOffset())
746 opBundleArgs.push_back(offset);
748 auto cond = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
749 rewriter.getI1Type(), 1);
750 mlir::LLVM::AssumeOp::create(rewriter, op.getLoc(), cond,
"align",
755 rewriter.replaceOp(op, adaptor.getPointer());
756 return mlir::success();
759mlir::LogicalResult CIRToLLVMAssumeSepStorageOpLowering::matchAndRewrite(
760 cir::AssumeSepStorageOp op, OpAdaptor adaptor,
761 mlir::ConversionPatternRewriter &rewriter)
const {
762 auto cond = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
763 rewriter.getI1Type(), 1);
764 rewriter.replaceOpWithNewOp<mlir::LLVM::AssumeOp>(
765 op, cond, mlir::LLVM::AssumeSeparateStorageTag{}, adaptor.getPtr1(),
767 return mlir::success();
770static mlir::LLVM::AtomicOrdering
773 return mlir::LLVM::AtomicOrdering::not_atomic;
775 case cir::MemOrder::Relaxed:
776 return mlir::LLVM::AtomicOrdering::monotonic;
777 case cir::MemOrder::Consume:
778 case cir::MemOrder::Acquire:
779 return mlir::LLVM::AtomicOrdering::acquire;
780 case cir::MemOrder::Release:
781 return mlir::LLVM::AtomicOrdering::release;
782 case cir::MemOrder::AcquireRelease:
783 return mlir::LLVM::AtomicOrdering::acq_rel;
784 case cir::MemOrder::SequentiallyConsistent:
785 return mlir::LLVM::AtomicOrdering::seq_cst;
787 llvm_unreachable(
"unknown memory order");
790static std::optional<llvm::StringRef>
792 if (syncScope.has_value())
793 return syncScope.value() == cir::SyncScopeKind::SingleThread
799mlir::LogicalResult CIRToLLVMAtomicCmpXchgOpLowering::matchAndRewrite(
800 cir::AtomicCmpXchgOp op, OpAdaptor adaptor,
801 mlir::ConversionPatternRewriter &rewriter)
const {
802 mlir::Value expected = adaptor.getExpected();
803 mlir::Value desired = adaptor.getDesired();
805 auto cmpxchg = mlir::LLVM::AtomicCmpXchgOp::create(
806 rewriter, op.getLoc(), adaptor.getPtr(), expected, desired,
810 cmpxchg.setAlignment(adaptor.getAlignment());
811 cmpxchg.setWeak(adaptor.getWeak());
812 cmpxchg.setVolatile_(adaptor.getIsVolatile());
815 auto old = mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(),
816 cmpxchg.getResult(), 0);
817 auto cmp = mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(),
818 cmpxchg.getResult(), 1);
820 rewriter.replaceOp(op, {old, cmp});
821 return mlir::success();
824mlir::LogicalResult CIRToLLVMAtomicXchgOpLowering::matchAndRewrite(
825 cir::AtomicXchgOp op, OpAdaptor adaptor,
826 mlir::ConversionPatternRewriter &rewriter)
const {
828 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(adaptor.getMemOrder());
829 rewriter.replaceOpWithNewOp<mlir::LLVM::AtomicRMWOp>(
830 op, mlir::LLVM::AtomicBinOp::xchg, adaptor.getPtr(), adaptor.getVal(),
832 return mlir::success();
835mlir::LogicalResult CIRToLLVMAtomicTestAndSetOpLowering::matchAndRewrite(
836 cir::AtomicTestAndSetOp op, OpAdaptor adaptor,
837 mlir::ConversionPatternRewriter &rewriter)
const {
840 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
842 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
843 rewriter.getI8Type(), 1);
844 auto rmw = mlir::LLVM::AtomicRMWOp::create(
845 rewriter, op.getLoc(), mlir::LLVM::AtomicBinOp::xchg, adaptor.getPtr(),
846 one, llvmOrder, llvm::StringRef(),
847 adaptor.getAlignment().value_or(0), op.getIsVolatile());
849 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
850 rewriter.getI8Type(), 0);
851 auto cmp = mlir::LLVM::ICmpOp::create(
852 rewriter, op.getLoc(), mlir::LLVM::ICmpPredicate::ne, rmw, zero);
854 rewriter.replaceOp(op, cmp);
855 return mlir::success();
858mlir::LogicalResult CIRToLLVMAtomicClearOpLowering::matchAndRewrite(
859 cir::AtomicClearOp op, OpAdaptor adaptor,
860 mlir::ConversionPatternRewriter &rewriter)
const {
863 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
864 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
865 rewriter.getI8Type(), 0);
866 auto store = mlir::LLVM::StoreOp::create(
867 rewriter, op.getLoc(), zero, adaptor.getPtr(),
868 adaptor.getAlignment().value_or(0), op.getIsVolatile(),
869 false,
false, llvmOrder);
871 rewriter.replaceOp(op, store);
872 return mlir::success();
875mlir::LogicalResult CIRToLLVMAtomicFenceOpLowering::matchAndRewrite(
876 cir::AtomicFenceOp op, OpAdaptor adaptor,
877 mlir::ConversionPatternRewriter &rewriter)
const {
878 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(adaptor.getOrdering());
880 auto fence = mlir::LLVM::FenceOp::create(rewriter, op.getLoc(), llvmOrder);
883 rewriter.replaceOp(op, fence);
885 return mlir::success();
888static mlir::LLVM::AtomicBinOp
891 case cir::AtomicFetchKind::Add:
892 return isInt ? mlir::LLVM::AtomicBinOp::add : mlir::LLVM::AtomicBinOp::fadd;
893 case cir::AtomicFetchKind::Sub:
894 return isInt ? mlir::LLVM::AtomicBinOp::sub : mlir::LLVM::AtomicBinOp::fsub;
895 case cir::AtomicFetchKind::And:
896 return mlir::LLVM::AtomicBinOp::_and;
897 case cir::AtomicFetchKind::Xor:
898 return mlir::LLVM::AtomicBinOp::_xor;
899 case cir::AtomicFetchKind::Or:
900 return mlir::LLVM::AtomicBinOp::_or;
901 case cir::AtomicFetchKind::Nand:
902 return mlir::LLVM::AtomicBinOp::nand;
903 case cir::AtomicFetchKind::Max: {
905 return mlir::LLVM::AtomicBinOp::fmax;
906 return isSignedInt ? mlir::LLVM::AtomicBinOp::max
907 : mlir::LLVM::AtomicBinOp::umax;
909 case cir::AtomicFetchKind::Min: {
911 return mlir::LLVM::AtomicBinOp::fmin;
912 return isSignedInt ? mlir::LLVM::AtomicBinOp::min
913 : mlir::LLVM::AtomicBinOp::umin;
916 llvm_unreachable(
"Unknown atomic fetch opcode");
919static llvm::StringLiteral
getLLVMBinop(cir::AtomicFetchKind k,
bool isInt) {
921 case cir::AtomicFetchKind::Add:
922 return isInt ? mlir::LLVM::AddOp::getOperationName()
923 : mlir::LLVM::FAddOp::getOperationName();
924 case cir::AtomicFetchKind::Sub:
925 return isInt ? mlir::LLVM::SubOp::getOperationName()
926 : mlir::LLVM::FSubOp::getOperationName();
927 case cir::AtomicFetchKind::And:
928 return mlir::LLVM::AndOp::getOperationName();
929 case cir::AtomicFetchKind::Xor:
930 return mlir::LLVM::XOrOp::getOperationName();
931 case cir::AtomicFetchKind::Or:
932 return mlir::LLVM::OrOp::getOperationName();
933 case cir::AtomicFetchKind::Nand:
935 return mlir::LLVM::AndOp::getOperationName();
936 case cir::AtomicFetchKind::Max:
937 case cir::AtomicFetchKind::Min:
938 llvm_unreachable(
"handled in buildMinMaxPostOp");
940 llvm_unreachable(
"Unknown atomic fetch opcode");
943mlir::Value CIRToLLVMAtomicFetchOpLowering::buildPostOp(
944 cir::AtomicFetchOp op, OpAdaptor adaptor,
945 mlir::ConversionPatternRewriter &rewriter, mlir::Value rmwVal,
951 rewriter.getStringAttr(
getLLVMBinop(op.getBinop(), isInt)),
952 atomicOperands, atomicResTys, {})
956mlir::Value CIRToLLVMAtomicFetchOpLowering::buildMinMaxPostOp(
957 cir::AtomicFetchOp op, OpAdaptor adaptor,
958 mlir::ConversionPatternRewriter &rewriter, mlir::Value rmwVal,
bool isInt,
959 bool isSigned)
const {
960 mlir::Location loc = op.getLoc();
963 if (op.getBinop() == cir::AtomicFetchKind::Max)
964 return mlir::LLVM::MaxNumOp::create(rewriter, loc, rmwVal,
966 return mlir::LLVM::MinNumOp::create(rewriter, loc, rmwVal,
970 mlir::LLVM::ICmpPredicate pred;
971 if (op.getBinop() == cir::AtomicFetchKind::Max) {
972 pred = isSigned ? mlir::LLVM::ICmpPredicate::sgt
973 : mlir::LLVM::ICmpPredicate::ugt;
975 pred = isSigned ? mlir::LLVM::ICmpPredicate::slt
976 : mlir::LLVM::ICmpPredicate::ult;
978 mlir::Value cmp = mlir::LLVM::ICmpOp::create(
980 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(), pred), rmwVal,
982 return mlir::LLVM::SelectOp::create(rewriter, loc, cmp, rmwVal,
986mlir::LogicalResult CIRToLLVMAtomicFetchOpLowering::matchAndRewrite(
987 cir::AtomicFetchOp op, OpAdaptor adaptor,
988 mlir::ConversionPatternRewriter &rewriter)
const {
990 bool isSignedInt =
false;
991 if (
auto intTy = mlir::dyn_cast<cir::IntType>(op.getVal().getType())) {
993 isSignedInt = intTy.isSigned();
994 }
else if (mlir::isa<cir::SingleType, cir::DoubleType>(
995 op.getVal().getType())) {
998 return op.emitError() <<
"Unsupported type: " << op.getVal().getType();
1001 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
1002 mlir::LLVM::AtomicBinOp llvmBinOp =
1004 auto rmwVal = mlir::LLVM::AtomicRMWOp::create(rewriter, op.getLoc(),
1005 llvmBinOp, adaptor.getPtr(),
1006 adaptor.getVal(), llvmOrder);
1008 mlir::Value result = rmwVal.getResult();
1009 if (!op.getFetchFirst()) {
1010 if (op.getBinop() == cir::AtomicFetchKind::Max ||
1011 op.getBinop() == cir::AtomicFetchKind::Min)
1012 result = buildMinMaxPostOp(op, adaptor, rewriter, rmwVal.getRes(), isInt,
1015 result = buildPostOp(op, adaptor, rewriter, rmwVal.getRes(), isInt);
1018 if (op.getBinop() == cir::AtomicFetchKind::Nand) {
1019 auto negOne = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1020 result.getType(), -1);
1021 result = mlir::LLVM::XOrOp::create(rewriter, op.getLoc(), result, negOne);
1025 rewriter.replaceOp(op, result);
1026 return mlir::success();
1029mlir::LogicalResult CIRToLLVMBitClrsbOpLowering::matchAndRewrite(
1030 cir::BitClrsbOp op, OpAdaptor adaptor,
1031 mlir::ConversionPatternRewriter &rewriter)
const {
1032 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1033 adaptor.getInput().getType(), 0);
1034 auto isNeg = mlir::LLVM::ICmpOp::create(
1035 rewriter, op.getLoc(),
1036 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(),
1037 mlir::LLVM::ICmpPredicate::slt),
1038 adaptor.getInput(), zero);
1040 auto negOne = mlir::LLVM::ConstantOp::create(
1041 rewriter, op.getLoc(), adaptor.getInput().getType(), -1);
1042 auto flipped = mlir::LLVM::XOrOp::create(rewriter, op.getLoc(),
1043 adaptor.getInput(), negOne);
1045 auto select = mlir::LLVM::SelectOp::create(rewriter, op.getLoc(), isNeg,
1046 flipped, adaptor.getInput());
1048 auto resTy = getTypeConverter()->convertType(op.getType());
1049 auto clz = mlir::LLVM::CountLeadingZerosOp::create(
1050 rewriter, op.getLoc(), resTy,
select,
false);
1052 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1053 auto res = mlir::LLVM::SubOp::create(rewriter, op.getLoc(),
clz, one,
1054 mlir::LLVM::IntegerOverflowFlags::nuw);
1055 rewriter.replaceOp(op, res);
1057 return mlir::LogicalResult::success();
1060mlir::LogicalResult CIRToLLVMBitClzOpLowering::matchAndRewrite(
1061 cir::BitClzOp op, OpAdaptor adaptor,
1062 mlir::ConversionPatternRewriter &rewriter)
const {
1063 auto resTy = getTypeConverter()->convertType(op.getType());
1064 auto llvmOp = mlir::LLVM::CountLeadingZerosOp::create(
1065 rewriter, op.getLoc(), resTy, adaptor.getInput(), op.getPoisonZero());
1066 rewriter.replaceOp(op, llvmOp);
1067 return mlir::LogicalResult::success();
1070mlir::LogicalResult CIRToLLVMBitCtzOpLowering::matchAndRewrite(
1071 cir::BitCtzOp op, OpAdaptor adaptor,
1072 mlir::ConversionPatternRewriter &rewriter)
const {
1073 auto resTy = getTypeConverter()->convertType(op.getType());
1074 auto llvmOp = mlir::LLVM::CountTrailingZerosOp::create(
1075 rewriter, op.getLoc(), resTy, adaptor.getInput(), op.getPoisonZero());
1076 rewriter.replaceOp(op, llvmOp);
1077 return mlir::LogicalResult::success();
1080mlir::LogicalResult CIRToLLVMBitFfsOpLowering::matchAndRewrite(
1081 cir::BitFfsOp op, OpAdaptor adaptor,
1082 mlir::ConversionPatternRewriter &rewriter)
const {
1083 auto resTy = getTypeConverter()->convertType(op.getType());
1084 auto ctz = mlir::LLVM::CountTrailingZerosOp::create(rewriter, op.getLoc(),
1085 resTy, adaptor.getInput(),
1088 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1089 auto ctzAddOne = mlir::LLVM::AddOp::create(rewriter, op.getLoc(),
ctz, one);
1091 auto zeroInputTy = mlir::LLVM::ConstantOp::create(
1092 rewriter, op.getLoc(), adaptor.getInput().getType(), 0);
1093 auto isZero = mlir::LLVM::ICmpOp::create(
1094 rewriter, op.getLoc(),
1095 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(),
1096 mlir::LLVM::ICmpPredicate::eq),
1097 adaptor.getInput(), zeroInputTy);
1099 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 0);
1100 auto res = mlir::LLVM::SelectOp::create(rewriter, op.getLoc(), isZero, zero,
1102 rewriter.replaceOp(op, res);
1104 return mlir::LogicalResult::success();
1107mlir::LogicalResult CIRToLLVMBitParityOpLowering::matchAndRewrite(
1108 cir::BitParityOp op, OpAdaptor adaptor,
1109 mlir::ConversionPatternRewriter &rewriter)
const {
1110 auto resTy = getTypeConverter()->convertType(op.getType());
1111 auto popcnt = mlir::LLVM::CtPopOp::create(rewriter, op.getLoc(), resTy,
1112 adaptor.getInput());
1114 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1116 mlir::LLVM::AndOp::create(rewriter, op.getLoc(), popcnt, one);
1117 rewriter.replaceOp(op, popcntMod2);
1119 return mlir::LogicalResult::success();
1122mlir::LogicalResult CIRToLLVMBitPopcountOpLowering::matchAndRewrite(
1123 cir::BitPopcountOp op, OpAdaptor adaptor,
1124 mlir::ConversionPatternRewriter &rewriter)
const {
1125 auto resTy = getTypeConverter()->convertType(op.getType());
1126 auto llvmOp = mlir::LLVM::CtPopOp::create(rewriter, op.getLoc(), resTy,
1127 adaptor.getInput());
1128 rewriter.replaceOp(op, llvmOp);
1129 return mlir::LogicalResult::success();
1132mlir::LogicalResult CIRToLLVMBitReverseOpLowering::matchAndRewrite(
1133 cir::BitReverseOp op, OpAdaptor adaptor,
1134 mlir::ConversionPatternRewriter &rewriter)
const {
1135 rewriter.replaceOpWithNewOp<mlir::LLVM::BitReverseOp>(op, adaptor.getInput());
1136 return mlir::success();
1139mlir::LogicalResult CIRToLLVMBrCondOpLowering::matchAndRewrite(
1140 cir::BrCondOp brOp, OpAdaptor adaptor,
1141 mlir::ConversionPatternRewriter &rewriter)
const {
1146 mlir::Value i1Condition = adaptor.getCond();
1148 rewriter.replaceOpWithNewOp<mlir::LLVM::CondBrOp>(
1149 brOp, i1Condition, brOp.getDestTrue(), adaptor.getDestOperandsTrue(),
1150 brOp.getDestFalse(), adaptor.getDestOperandsFalse());
1152 return mlir::success();
1155mlir::LogicalResult CIRToLLVMByteSwapOpLowering::matchAndRewrite(
1156 cir::ByteSwapOp op, OpAdaptor adaptor,
1157 mlir::ConversionPatternRewriter &rewriter)
const {
1158 rewriter.replaceOpWithNewOp<mlir::LLVM::ByteSwapOp>(op, adaptor.getInput());
1159 return mlir::LogicalResult::success();
1162mlir::Type CIRToLLVMCastOpLowering::convertTy(mlir::Type ty)
const {
1163 return getTypeConverter()->convertType(ty);
1166mlir::LogicalResult CIRToLLVMCastOpLowering::matchAndRewrite(
1167 cir::CastOp castOp, OpAdaptor adaptor,
1168 mlir::ConversionPatternRewriter &rewriter)
const {
1173 switch (castOp.getKind()) {
1174 case cir::CastKind::array_to_ptrdecay: {
1175 const auto ptrTy = mlir::cast<cir::PointerType>(castOp.getType());
1176 mlir::Value sourceValue = adaptor.getSrc();
1177 mlir::Type targetType = convertTy(ptrTy);
1179 ptrTy.getPointee());
1180 llvm::SmallVector<mlir::LLVM::GEPArg> offset{0};
1181 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1182 castOp, targetType, elementTy, sourceValue, offset);
1185 case cir::CastKind::int_to_bool: {
1186 mlir::Value llvmSrcVal = adaptor.getSrc();
1187 mlir::Value zeroInt = mlir::LLVM::ConstantOp::create(
1188 rewriter, castOp.getLoc(), llvmSrcVal.getType(), 0);
1189 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
1190 castOp, mlir::LLVM::ICmpPredicate::ne, llvmSrcVal, zeroInt);
1193 case cir::CastKind::integral: {
1194 mlir::Type srcType = castOp.getSrc().getType();
1195 mlir::Type dstType = castOp.getType();
1196 mlir::Value llvmSrcVal = adaptor.getSrc();
1197 mlir::Type llvmDstType = getTypeConverter()->convertType(dstType);
1198 cir::IntType srcIntType =
1199 mlir::cast<cir::IntType>(elementTypeIfVector(srcType));
1200 cir::IntType dstIntType =
1201 mlir::cast<cir::IntType>(elementTypeIfVector(dstType));
1202 rewriter.replaceOp(castOp,
getLLVMIntCast(rewriter, llvmSrcVal, llvmDstType,
1203 srcIntType.isUnsigned(),
1204 srcIntType.getWidth(),
1205 dstIntType.getWidth()));
1208 case cir::CastKind::floating: {
1209 mlir::Value llvmSrcVal = adaptor.getSrc();
1210 mlir::Type llvmDstTy = getTypeConverter()->convertType(castOp.getType());
1212 mlir::Type srcTy = elementTypeIfVector(castOp.getSrc().getType());
1213 mlir::Type dstTy = elementTypeIfVector(castOp.getType());
1215 if (!mlir::isa<cir::FPTypeInterface>(dstTy) ||
1216 !mlir::isa<cir::FPTypeInterface>(srcTy))
1217 return castOp.emitError() <<
"NYI cast from " << srcTy <<
" to " << dstTy;
1219 auto getFloatWidth = [](mlir::Type ty) ->
unsigned {
1220 return mlir::cast<cir::FPTypeInterface>(ty).getWidth();
1223 if (getFloatWidth(srcTy) > getFloatWidth(dstTy))
1224 rewriter.replaceOpWithNewOp<mlir::LLVM::FPTruncOp>(castOp, llvmDstTy,
1227 rewriter.replaceOpWithNewOp<mlir::LLVM::FPExtOp>(castOp, llvmDstTy,
1229 return mlir::success();
1231 case cir::CastKind::int_to_ptr: {
1232 auto dstTy = mlir::cast<cir::PointerType>(castOp.getType());
1233 mlir::Value llvmSrcVal = adaptor.getSrc();
1234 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1235 rewriter.replaceOpWithNewOp<mlir::LLVM::IntToPtrOp>(castOp, llvmDstTy,
1237 return mlir::success();
1239 case cir::CastKind::ptr_to_int: {
1240 auto dstTy = mlir::cast<cir::IntType>(castOp.getType());
1241 mlir::Value llvmSrcVal = adaptor.getSrc();
1242 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1243 rewriter.replaceOpWithNewOp<mlir::LLVM::PtrToIntOp>(castOp, llvmDstTy,
1245 return mlir::success();
1247 case cir::CastKind::float_to_bool: {
1248 mlir::Value llvmSrcVal = adaptor.getSrc();
1249 auto kind = mlir::LLVM::FCmpPredicate::une;
1252 auto zeroFloat = mlir::LLVM::ConstantOp::create(
1253 rewriter, castOp.getLoc(), llvmSrcVal.getType(),
1254 mlir::FloatAttr::get(llvmSrcVal.getType(), 0.0));
1257 rewriter.replaceOpWithNewOp<mlir::LLVM::FCmpOp>(castOp,
kind, llvmSrcVal,
1260 return mlir::success();
1262 case cir::CastKind::bool_to_int: {
1263 auto dstTy = mlir::cast<cir::IntType>(castOp.getType());
1264 mlir::Value llvmSrcVal = adaptor.getSrc();
1265 auto llvmSrcTy = mlir::cast<mlir::IntegerType>(llvmSrcVal.getType());
1267 mlir::cast<mlir::IntegerType>(getTypeConverter()->convertType(dstTy));
1268 if (llvmSrcTy.getWidth() == llvmDstTy.getWidth())
1269 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(castOp, llvmDstTy,
1272 rewriter.replaceOpWithNewOp<mlir::LLVM::ZExtOp>(castOp, llvmDstTy,
1274 return mlir::success();
1276 case cir::CastKind::bool_to_float: {
1277 mlir::Type dstTy = castOp.getType();
1278 mlir::Value llvmSrcVal = adaptor.getSrc();
1279 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1280 rewriter.replaceOpWithNewOp<mlir::LLVM::UIToFPOp>(castOp, llvmDstTy,
1282 return mlir::success();
1284 case cir::CastKind::int_to_float: {
1285 mlir::Type dstTy = castOp.getType();
1286 mlir::Value llvmSrcVal = adaptor.getSrc();
1287 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1288 if (mlir::cast<cir::IntType>(elementTypeIfVector(castOp.getSrc().getType()))
1290 rewriter.replaceOpWithNewOp<mlir::LLVM::SIToFPOp>(castOp, llvmDstTy,
1293 rewriter.replaceOpWithNewOp<mlir::LLVM::UIToFPOp>(castOp, llvmDstTy,
1295 return mlir::success();
1297 case cir::CastKind::float_to_int: {
1298 mlir::Type dstTy = castOp.getType();
1299 mlir::Value llvmSrcVal = adaptor.getSrc();
1300 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1301 if (mlir::cast<cir::IntType>(elementTypeIfVector(castOp.getType()))
1303 rewriter.replaceOpWithNewOp<mlir::LLVM::FPToSIOp>(castOp, llvmDstTy,
1306 rewriter.replaceOpWithNewOp<mlir::LLVM::FPToUIOp>(castOp, llvmDstTy,
1308 return mlir::success();
1310 case cir::CastKind::bitcast: {
1311 mlir::Type dstTy = castOp.getType();
1312 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1317 mlir::Value llvmSrcVal = adaptor.getSrc();
1318 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(castOp, llvmDstTy,
1320 return mlir::success();
1322 case cir::CastKind::ptr_to_bool: {
1323 mlir::Value llvmSrcVal = adaptor.getSrc();
1324 mlir::Value zeroPtr = mlir::LLVM::ZeroOp::create(rewriter, castOp.getLoc(),
1325 llvmSrcVal.getType());
1326 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
1327 castOp, mlir::LLVM::ICmpPredicate::ne, llvmSrcVal, zeroPtr);
1330 case cir::CastKind::address_space: {
1331 mlir::Type dstTy = castOp.getType();
1332 mlir::Value llvmSrcVal = adaptor.getSrc();
1333 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1334 rewriter.replaceOpWithNewOp<mlir::LLVM::AddrSpaceCastOp>(castOp, llvmDstTy,
1338 case cir::CastKind::member_ptr_to_bool:
1343 return castOp.emitError(
"Unhandled cast kind: ")
1344 << castOp.getKindAttrName();
1348 return mlir::success();
1352 mlir::ModuleOp mod, mlir::Value index,
1353 mlir::Type baseTy, cir::IntType strideTy) {
1354 mlir::Operation *indexOp = index.getDefiningOp();
1358 auto indexType = mlir::cast<mlir::IntegerType>(index.getType());
1359 mlir::DataLayout llvmLayout(mod);
1360 std::optional<uint64_t> layoutWidth = llvmLayout.getTypeIndexBitwidth(baseTy);
1363 if (!layoutWidth || *layoutWidth == indexType.getWidth())
1369 auto sub = dyn_cast<mlir::LLVM::SubOp>(indexOp);
1370 bool rewriteSub =
false;
1373 dyn_cast<mlir::LLVM::ConstantOp>(sub.getLhs().getDefiningOp())) {
1374 auto lhsConstInt = mlir::dyn_cast<mlir::IntegerAttr>(lhsConst.getValue());
1375 if (lhsConstInt && lhsConstInt.getValue() == 0) {
1376 index = sub.getRhs();
1382 auto llvmDstType = rewriter.getIntegerType(*layoutWidth);
1383 bool isUnsigned = strideTy && strideTy.isUnsigned();
1385 indexType.getWidth(), *layoutWidth);
1388 index = mlir::LLVM::SubOp::create(
1389 rewriter, index.getLoc(),
1390 mlir::LLVM::ConstantOp::create(rewriter, index.getLoc(),
1391 index.getType(), 0),
1394 rewriter.eraseOp(sub);
1400mlir::LogicalResult CIRToLLVMPtrStrideOpLowering::matchAndRewrite(
1401 cir::PtrStrideOp ptrStrideOp, OpAdaptor adaptor,
1402 mlir::ConversionPatternRewriter &rewriter)
const {
1404 const mlir::TypeConverter *tc = getTypeConverter();
1405 const mlir::Type resultTy = tc->convertType(ptrStrideOp.getType());
1407 mlir::Type elementTy =
1412 if (mlir::isa<mlir::LLVM::LLVMVoidType>(elementTy) ||
1413 mlir::isa<mlir::LLVM::LLVMFunctionType>(elementTy))
1414 elementTy = mlir::IntegerType::get(elementTy.getContext(), 8,
1415 mlir::IntegerType::Signless);
1417 mlir::Value index = adaptor.getStride();
1419 rewriter, ptrStrideOp->getParentOfType<mlir::ModuleOp>(), index,
1420 adaptor.getBase().getType(),
1421 dyn_cast<cir::IntType>(ptrStrideOp.getOperand(1).getType()));
1423 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1424 ptrStrideOp, resultTy, elementTy, adaptor.getBase(), index);
1425 return mlir::success();
1428mlir::LogicalResult CIRToLLVMGetElementOpLowering::matchAndRewrite(
1429 cir::GetElementOp op, OpAdaptor adaptor,
1430 mlir::ConversionPatternRewriter &rewriter)
const {
1432 mlir::dyn_cast<cir::ArrayType>(op.getBaseType().getPointee())) {
1433 const mlir::TypeConverter *converter = getTypeConverter();
1434 const mlir::Type llArrayTy = converter->convertType(arrayTy);
1435 const mlir::Type llResultTy = converter->convertType(op.getType());
1436 mlir::Type elementTy =
1441 if (mlir::isa<mlir::LLVM::LLVMVoidType>(elementTy) ||
1442 mlir::isa<mlir::LLVM::LLVMFunctionType>(elementTy))
1443 elementTy = rewriter.getIntegerType(8);
1445 mlir::Value index = adaptor.getIndex();
1448 adaptor.getBase().getType(),
1449 dyn_cast<cir::IntType>(op.getOperand(1).getType()));
1454 std::array<mlir::LLVM::GEPArg, 2> offset{0, index};
1455 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, llResultTy, llArrayTy,
1456 adaptor.getBase(), offset);
1457 return mlir::success();
1460 op.emitError() <<
"NYI: GetElementOp lowering to LLVM for non-array";
1461 return mlir::failure();
1464mlir::LogicalResult CIRToLLVMBaseClassAddrOpLowering::matchAndRewrite(
1465 cir::BaseClassAddrOp baseClassOp, OpAdaptor adaptor,
1466 mlir::ConversionPatternRewriter &rewriter)
const {
1467 const mlir::Type resultType =
1468 getTypeConverter()->convertType(baseClassOp.getType());
1469 mlir::Value derivedAddr = adaptor.getDerivedAddr();
1470 llvm::SmallVector<mlir::LLVM::GEPArg, 1> offset = {
1471 adaptor.getOffset().getZExtValue()};
1472 mlir::Type byteType = mlir::IntegerType::get(resultType.getContext(), 8,
1473 mlir::IntegerType::Signless);
1474 if (adaptor.getOffset().getZExtValue() == 0) {
1475 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(
1476 baseClassOp, resultType, adaptor.getDerivedAddr());
1477 return mlir::success();
1480 if (baseClassOp.getAssumeNotNull()) {
1481 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1482 baseClassOp, resultType, byteType, derivedAddr, offset);
1484 auto loc = baseClassOp.getLoc();
1485 mlir::Value isNull = mlir::LLVM::ICmpOp::create(
1486 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, derivedAddr,
1487 mlir::LLVM::ZeroOp::create(rewriter, loc, derivedAddr.getType()));
1488 mlir::Value adjusted = mlir::LLVM::GEPOp::create(
1489 rewriter, loc, resultType, byteType, derivedAddr, offset);
1490 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(baseClassOp, isNull,
1491 derivedAddr, adjusted);
1493 return mlir::success();
1496mlir::LogicalResult CIRToLLVMDerivedClassAddrOpLowering::matchAndRewrite(
1497 cir::DerivedClassAddrOp derivedClassOp, OpAdaptor adaptor,
1498 mlir::ConversionPatternRewriter &rewriter)
const {
1499 const mlir::Type resultType =
1500 getTypeConverter()->convertType(derivedClassOp.getType());
1501 mlir::Value baseAddr = adaptor.getBaseAddr();
1504 int64_t offsetVal = -(adaptor.getOffset().getZExtValue());
1505 if (offsetVal == 0) {
1507 rewriter.replaceOp(derivedClassOp, baseAddr);
1508 return mlir::success();
1510 llvm::SmallVector<mlir::LLVM::GEPArg, 1> offset = {offsetVal};
1511 mlir::Type byteType = mlir::IntegerType::get(resultType.getContext(), 8,
1512 mlir::IntegerType::Signless);
1513 if (derivedClassOp.getAssumeNotNull()) {
1514 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1515 derivedClassOp, resultType, byteType, baseAddr, offset,
1516 mlir::LLVM::GEPNoWrapFlags::inbounds);
1518 mlir::Location loc = derivedClassOp.getLoc();
1519 mlir::Value isNull = mlir::LLVM::ICmpOp::create(
1520 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, baseAddr,
1521 mlir::LLVM::ZeroOp::create(rewriter, loc, baseAddr.getType()));
1522 mlir::Value adjusted =
1523 mlir::LLVM::GEPOp::create(rewriter, loc, resultType, byteType, baseAddr,
1524 offset, mlir::LLVM::GEPNoWrapFlags::inbounds);
1525 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(derivedClassOp, isNull,
1526 baseAddr, adjusted);
1528 return mlir::success();
1531mlir::LogicalResult CIRToLLVMATanOpLowering::matchAndRewrite(
1532 cir::ATanOp op, OpAdaptor adaptor,
1533 mlir::ConversionPatternRewriter &rewriter)
const {
1534 mlir::Type resTy = typeConverter->convertType(op.getType());
1535 rewriter.replaceOpWithNewOp<mlir::LLVM::ATanOp>(op, resTy, adaptor.getSrc());
1536 return mlir::success();
1539mlir::LogicalResult CIRToLLVMCeilOpLowering::matchAndRewrite(
1540 cir::CeilOp op, OpAdaptor adaptor,
1541 mlir::ConversionPatternRewriter &rewriter)
const {
1542 mlir::Type resTy = typeConverter->convertType(op.getType());
1543 rewriter.replaceOpWithNewOp<mlir::LLVM::FCeilOp>(op, resTy, adaptor.getSrc());
1544 return mlir::success();
1547mlir::LogicalResult CIRToLLVMAllocaOpLowering::matchAndRewrite(
1548 cir::AllocaOp op, OpAdaptor adaptor,
1549 mlir::ConversionPatternRewriter &rewriter)
const {
1552 ? adaptor.getDynAllocSize()
1553 : mlir::LLVM::ConstantOp::create(
1554 rewriter, op.getLoc(),
1555 typeConverter->convertType(rewriter.getIndexType()), 1);
1556 mlir::Type elementTy =
1558 mlir::Type resultTy =
1564 rewriter.replaceOpWithNewOp<mlir::LLVM::AllocaOp>(
1565 op, resultTy, elementTy, size, op.getAlignmentAttr().getInt());
1567 return mlir::success();
1570mlir::LogicalResult CIRToLLVMReturnOpLowering::matchAndRewrite(
1571 cir::ReturnOp op, OpAdaptor adaptor,
1572 mlir::ConversionPatternRewriter &rewriter)
const {
1573 rewriter.replaceOpWithNewOp<mlir::LLVM::ReturnOp>(op, adaptor.getOperands());
1574 return mlir::LogicalResult::success();
1577mlir::LogicalResult CIRToLLVMRotateOpLowering::matchAndRewrite(
1578 cir::RotateOp op, OpAdaptor adaptor,
1579 mlir::ConversionPatternRewriter &rewriter)
const {
1582 mlir::Value input = adaptor.getInput();
1583 if (op.isRotateLeft())
1584 rewriter.replaceOpWithNewOp<mlir::LLVM::FshlOp>(op, input, input,
1585 adaptor.getAmount());
1587 rewriter.replaceOpWithNewOp<mlir::LLVM::FshrOp>(op, input, input,
1588 adaptor.getAmount());
1589 return mlir::LogicalResult::success();
1592static mlir::LogicalResult
1594 mlir::ConversionPatternRewriter &rewriter,
1595 const mlir::TypeConverter *converter,
1596 mlir::FlatSymbolRefAttr calleeAttr) {
1598 mlir::ValueTypeRange<mlir::ResultRange> cirResults = op->getResultTypes();
1599 auto call = cast<cir::CIRCallOpInterface>(op);
1601 if (converter->convertTypes(cirResults, llvmResults).failed())
1602 return mlir::failure();
1606 mlir::LLVM::MemoryEffectsAttr memoryEffects;
1607 bool noUnwind =
false;
1608 bool willReturn =
false;
1610 memoryEffects, noUnwind, willReturn);
1612 mlir::LLVM::LLVMFunctionType llvmFnTy;
1619 mlir::Operation *callee =
1620 mlir::SymbolTable::lookupNearestSymbolFrom(op, calleeAttr);
1621 if (
auto fn = mlir::dyn_cast<mlir::FunctionOpInterface>(callee)) {
1622 llvmFnTy = converter->convertType<mlir::LLVM::LLVMFunctionType>(
1623 fn.getFunctionType());
1624 assert(llvmFnTy &&
"Failed to convert function type");
1625 }
else if (
auto alias = mlir::cast<mlir::LLVM::AliasOp>(callee)) {
1633 auto symAttr = mlir::cast<mlir::FlatSymbolRefAttr>(calleeAttr);
1635 mlir::LLVM::AddressOfOp::create(
1636 rewriter, op->getLoc(),
1637 mlir::LLVM::LLVMPointerType::get(rewriter.getContext()), symAttr)
1639 adjustedCallOperands.push_back(addrOfAlias);
1642 llvm::append_range(adjustedCallOperands, callOperands);
1643 callOperands = adjustedCallOperands;
1647 llvmFnTy = mlir::cast<mlir::LLVM::LLVMFunctionType>(alias.getType());
1650 return op->emitError(
"Unexpected callee type!");
1653 assert(!op->getOperands().empty() &&
1654 "operands list must no be empty for the indirect call");
1655 auto calleeTy = op->getOperands().front().getType();
1656 auto calleePtrTy = cast<cir::PointerType>(calleeTy);
1657 auto calleeFuncTy = cast<cir::FuncType>(calleePtrTy.getPointee());
1658 llvm::append_range(adjustedCallOperands, callOperands);
1659 llvmFnTy = cast<mlir::LLVM::LLVMFunctionType>(
1660 converter->convertType(calleeFuncTy));
1667 auto newOp = rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(
1668 op, llvmFnTy, calleeAttr, callOperands);
1670 newOp.setMemoryEffectsAttr(memoryEffects);
1671 newOp.setNoUnwind(noUnwind);
1672 newOp.setWillReturn(willReturn);
1674 return mlir::success();
1677mlir::LogicalResult CIRToLLVMCallOpLowering::matchAndRewrite(
1678 cir::CallOp op, OpAdaptor adaptor,
1679 mlir::ConversionPatternRewriter &rewriter)
const {
1681 getTypeConverter(), op.getCalleeAttr());
1684mlir::LogicalResult CIRToLLVMReturnAddrOpLowering::matchAndRewrite(
1685 cir::ReturnAddrOp op, OpAdaptor adaptor,
1686 mlir::ConversionPatternRewriter &rewriter)
const {
1687 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
1689 llvmPtrTy, adaptor.getOperands());
1690 return mlir::success();
1693mlir::LogicalResult CIRToLLVMFrameAddrOpLowering::matchAndRewrite(
1694 cir::FrameAddrOp op, OpAdaptor adaptor,
1695 mlir::ConversionPatternRewriter &rewriter)
const {
1696 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
1698 adaptor.getOperands());
1699 return mlir::success();
1702mlir::LogicalResult CIRToLLVMAddrOfReturnAddrOpLowering::matchAndRewrite(
1703 cir::AddrOfReturnAddrOp op, OpAdaptor adaptor,
1704 mlir::ConversionPatternRewriter &rewriter)
const {
1705 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
1707 llvmPtrTy, adaptor.getOperands());
1708 return mlir::success();
1711mlir::LogicalResult CIRToLLVMLoadOpLowering::matchAndRewrite(
1712 cir::LoadOp op, OpAdaptor adaptor,
1713 mlir::ConversionPatternRewriter &rewriter)
const {
1714 const mlir::Type llvmTy =
1716 mlir::LLVM::AtomicOrdering ordering =
getLLVMMemOrder(op.getMemOrder());
1717 std::optional<size_t> opAlign = op.getAlignment();
1718 unsigned alignment =
1719 (unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmTy));
1725 std::optional<llvm::StringRef> syncScope =
1727 mlir::LLVM::LoadOp newLoad = mlir::LLVM::LoadOp::create(
1728 rewriter, op->getLoc(), llvmTy, adaptor.getAddr(), alignment,
1729 op.getIsVolatile(),
false,
1730 false,
false, ordering,
1731 syncScope.value_or(llvm::StringRef()));
1734 mlir::Value result =
1736 rewriter.replaceOp(op, result);
1738 return mlir::LogicalResult::success();
1741mlir::LogicalResult CIRToLLVMStoreOpLowering::matchAndRewrite(
1742 cir::StoreOp op, OpAdaptor adaptor,
1743 mlir::ConversionPatternRewriter &rewriter)
const {
1744 mlir::LLVM::AtomicOrdering memorder =
getLLVMMemOrder(op.getMemOrder());
1745 const mlir::Type llvmTy =
1746 getTypeConverter()->convertType(op.getValue().getType());
1747 std::optional<size_t> opAlign = op.getAlignment();
1748 unsigned alignment =
1749 (unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmTy));
1755 op.getValue().getType(), adaptor.getValue());
1759 std::optional<llvm::StringRef> syncScope =
1761 mlir::LLVM::StoreOp storeOp = mlir::LLVM::StoreOp::create(
1762 rewriter, op->getLoc(), value, adaptor.getAddr(), alignment,
1764 false,
false, memorder,
1765 syncScope.value_or(llvm::StringRef()));
1766 rewriter.replaceOp(op, storeOp);
1768 return mlir::LogicalResult::success();
1772 auto array = mlir::dyn_cast<mlir::ArrayAttr>(attr.getElts());
1773 return attr.hasTrailingZeros() ||
1774 (array && std::count_if(array.begin(), array.end(), [](
auto elt) {
1775 auto ar = dyn_cast<cir::ConstArrayAttr>(elt);
1776 return ar && hasTrailingZeros(ar);
1780mlir::LogicalResult CIRToLLVMConstantOpLowering::matchAndRewrite(
1781 cir::ConstantOp op, OpAdaptor adaptor,
1782 mlir::ConversionPatternRewriter &rewriter)
const {
1783 mlir::Attribute attr = op.getValue();
1785 if (mlir::isa<cir::PoisonAttr>(attr)) {
1786 rewriter.replaceOpWithNewOp<mlir::LLVM::PoisonOp>(
1787 op, getTypeConverter()->convertType(op.getType()));
1788 return mlir::success();
1791 if (mlir::isa<mlir::IntegerType>(op.getType())) {
1796 attr = op.getValue();
1797 }
else if (mlir::isa<cir::BoolType>(op.getType())) {
1798 int value = mlir::cast<cir::BoolAttr>(op.getValue()).getValue();
1799 attr = rewriter.getIntegerAttr(typeConverter->convertType(op.getType()),
1801 }
else if (mlir::isa<cir::IntType>(op.getType())) {
1803 if (
auto ga = mlir::dyn_cast<cir::GlobalViewAttr>(op.getValue())) {
1806 op.emitError() <<
"global view with integer type";
1807 return mlir::failure();
1810 attr = rewriter.getIntegerAttr(
1811 typeConverter->convertType(op.getType()),
1812 mlir::cast<cir::IntAttr>(op.getValue()).getValue());
1813 }
else if (mlir::isa<cir::FPTypeInterface>(op.getType())) {
1814 attr = rewriter.getFloatAttr(
1815 typeConverter->convertType(op.getType()),
1816 mlir::cast<cir::FPAttr>(op.getValue()).getValue());
1817 }
else if (mlir::isa<cir::PointerType>(op.getType())) {
1819 if (mlir::isa<cir::ConstPtrAttr>(op.getValue())) {
1820 if (mlir::cast<cir::ConstPtrAttr>(op.getValue()).isNullValue()) {
1821 rewriter.replaceOpWithNewOp<mlir::LLVM::ZeroOp>(
1822 op, typeConverter->convertType(op.getType()));
1823 return mlir::success();
1827 if (
auto gv = mlir::dyn_cast<cir::GlobalViewAttr>(op.getValue())) {
1830 rewriter.replaceOp(op, newOp);
1831 return mlir::success();
1833 attr = op.getValue();
1834 }
else if (
const auto arrTy = mlir::dyn_cast<cir::ArrayType>(op.getType())) {
1835 const auto constArr = mlir::dyn_cast<cir::ConstArrayAttr>(op.getValue());
1836 if (!constArr && !isa<cir::ZeroAttr, cir::UndefAttr>(op.getValue()))
1837 return op.emitError() <<
"array does not have a constant initializer";
1839 std::optional<mlir::Attribute> denseAttr;
1842 op, constArr, rewriter, getTypeConverter(), lowerMod);
1843 rewriter.replaceOp(op, newOp);
1844 return mlir::success();
1845 }
else if (constArr &&
1847 attr = denseAttr.value();
1850 op, op.getValue(), rewriter, typeConverter, lowerMod);
1851 rewriter.replaceOp(op, initVal);
1852 return mlir::success();
1854 }
else if (
const auto recordAttr =
1855 mlir::dyn_cast<cir::ConstRecordAttr>(op.getValue())) {
1858 rewriter.replaceOp(op, initVal);
1859 return mlir::success();
1860 }
else if (
const auto vecTy = mlir::dyn_cast<cir::VectorType>(op.getType())) {
1862 getTypeConverter(), lowerMod));
1863 return mlir::success();
1864 }
else if (
auto recTy = mlir::dyn_cast<cir::RecordType>(op.getType())) {
1865 if (mlir::isa<cir::ZeroAttr, cir::UndefAttr>(attr)) {
1866 mlir::Value initVal =
1868 rewriter.replaceOp(op, initVal);
1869 return mlir::success();
1871 return op.emitError() <<
"unsupported lowering for record constant type "
1873 }
else if (
auto complexTy = mlir::dyn_cast<cir::ComplexType>(op.getType())) {
1874 mlir::Type complexElemTy = complexTy.getElementType();
1875 mlir::Type complexElemLLVMTy = typeConverter->convertType(complexElemTy);
1877 if (
auto zeroInitAttr = mlir::dyn_cast<cir::ZeroAttr>(op.getValue())) {
1878 mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(complexElemLLVMTy);
1879 mlir::ArrayAttr array = rewriter.getArrayAttr({zeroAttr, zeroAttr});
1880 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
1881 op, getTypeConverter()->convertType(op.getType()), array);
1882 return mlir::success();
1885 auto complexAttr = mlir::cast<cir::ConstComplexAttr>(op.getValue());
1887 mlir::Attribute components[2];
1888 if (mlir::isa<cir::IntType>(complexElemTy)) {
1889 components[0] = rewriter.getIntegerAttr(
1891 mlir::cast<cir::IntAttr>(complexAttr.getReal()).getValue());
1892 components[1] = rewriter.getIntegerAttr(
1894 mlir::cast<cir::IntAttr>(complexAttr.getImag()).getValue());
1896 components[0] = rewriter.getFloatAttr(
1898 mlir::cast<cir::FPAttr>(complexAttr.getReal()).getValue());
1899 components[1] = rewriter.getFloatAttr(
1901 mlir::cast<cir::FPAttr>(complexAttr.getImag()).getValue());
1904 attr = rewriter.getArrayAttr(components);
1906 return op.emitError() <<
"unsupported constant type " << op.getType();
1909 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
1910 op, getTypeConverter()->convertType(op.getType()),
attr);
1912 return mlir::success();
1916 mlir::DataLayout layout(op.getParentOfType<mlir::ModuleOp>());
1918 if (isa<cir::VoidType>(type))
1919 type = cir::IntType::get(type.getContext(), 8,
false);
1920 return llvm::divideCeil(layout.getTypeSizeInBits(type), 8);
1923mlir::LogicalResult CIRToLLVMPrefetchOpLowering::matchAndRewrite(
1924 cir::PrefetchOp op, OpAdaptor adaptor,
1925 mlir::ConversionPatternRewriter &rewriter)
const {
1926 rewriter.replaceOpWithNewOp<mlir::LLVM::Prefetch>(
1927 op, adaptor.getAddr(), adaptor.getIsWrite(), adaptor.getLocality(),
1929 return mlir::success();
1932mlir::LogicalResult CIRToLLVMPtrDiffOpLowering::matchAndRewrite(
1933 cir::PtrDiffOp op, OpAdaptor adaptor,
1934 mlir::ConversionPatternRewriter &rewriter)
const {
1935 auto dstTy = mlir::cast<cir::IntType>(op.getType());
1936 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1938 auto lhs = mlir::LLVM::PtrToIntOp::create(rewriter, op.getLoc(), llvmDstTy,
1940 auto rhs = mlir::LLVM::PtrToIntOp::create(rewriter, op.getLoc(), llvmDstTy,
1944 mlir::LLVM::SubOp::create(rewriter, op.getLoc(), llvmDstTy, lhs, rhs);
1946 cir::PointerType ptrTy = op.getLhs().getType();
1948 uint64_t typeSize =
getTypeSize(ptrTy.getPointee(), *op);
1951 mlir::Value resultVal = diff.getResult();
1952 if (typeSize != 1) {
1953 auto typeSizeVal = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1954 llvmDstTy, typeSize);
1956 if (dstTy.isUnsigned()) {
1958 mlir::LLVM::UDivOp::create(rewriter, op.getLoc(), diff, typeSizeVal);
1959 uDiv.setIsExact(
true);
1960 resultVal = uDiv.getResult();
1963 mlir::LLVM::SDivOp::create(rewriter, op.getLoc(), diff, typeSizeVal);
1964 sDiv.setIsExact(
true);
1965 resultVal = sDiv.getResult();
1968 rewriter.replaceOp(op, resultVal);
1969 return mlir::success();
1972mlir::LogicalResult CIRToLLVMExpectOpLowering::matchAndRewrite(
1973 cir::ExpectOp op, OpAdaptor adaptor,
1974 mlir::ConversionPatternRewriter &rewriter)
const {
1978 std::optional<llvm::APFloat> prob = op.getProb();
1980 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpectWithProbabilityOp>(
1981 op, adaptor.getVal(), adaptor.getExpected(), prob.value());
1983 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpectOp>(op, adaptor.getVal(),
1984 adaptor.getExpected());
1985 return mlir::success();
1988mlir::LogicalResult CIRToLLVMFAbsOpLowering::matchAndRewrite(
1989 cir::FAbsOp op, OpAdaptor adaptor,
1990 mlir::ConversionPatternRewriter &rewriter)
const {
1991 mlir::Type resTy = typeConverter->convertType(op.getType());
1992 rewriter.replaceOpWithNewOp<mlir::LLVM::FAbsOp>(op, resTy,
1993 adaptor.getOperands()[0]);
1994 return mlir::success();
2001void CIRToLLVMFuncOpLowering::lowerFuncAttributes(
2002 cir::FuncOp func,
bool filterArgAndResAttrs,
2003 SmallVectorImpl<mlir::NamedAttribute> &result)
const {
2005 for (mlir::NamedAttribute attr : func->getAttrs()) {
2007 if (
attr.getName() == mlir::SymbolTable::getSymbolAttrName() ||
2008 attr.getName() == func.getFunctionTypeAttrName() ||
2010 attr.getName() == func.getGlobalVisibilityAttrName() ||
2011 attr.getName() == func.getDsoLocalAttrName() ||
2012 attr.getName() == func.getInlineKindAttrName() ||
2013 (filterArgAndResAttrs &&
2014 (
attr.getName() == func.getArgAttrsAttrName() ||
2015 attr.getName() == func.getResAttrsAttrName())))
2019 result.push_back(attr);
2023mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewriteAlias(
2024 cir::FuncOp op, llvm::StringRef aliasee, mlir::Type ty, OpAdaptor adaptor,
2025 mlir::ConversionPatternRewriter &rewriter)
const {
2026 SmallVector<mlir::NamedAttribute, 4> attributes;
2027 lowerFuncAttributes(op,
false, attributes);
2029 mlir::Location loc = op.getLoc();
2030 auto aliasOp = rewriter.replaceOpWithNewOp<mlir::LLVM::AliasOp>(
2031 op, ty,
convertLinkage(op.getLinkage()), op.getName(), op.getDsoLocal(),
2035 mlir::OpBuilder builder(op.getContext());
2036 mlir::Block *block = builder.createBlock(&aliasOp.getInitializerRegion());
2037 builder.setInsertionPointToStart(block);
2040 mlir::Type ptrTy = mlir::LLVM::LLVMPointerType::get(ty.getContext());
2041 auto addrOp = mlir::LLVM::AddressOfOp::create(builder, loc, ptrTy, aliasee);
2042 mlir::LLVM::ReturnOp::create(builder, loc, addrOp);
2044 return mlir::success();
2047mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewrite(
2048 cir::FuncOp op, OpAdaptor adaptor,
2049 mlir::ConversionPatternRewriter &rewriter)
const {
2051 cir::FuncType fnType = op.getFunctionType();
2052 bool isDsoLocal = op.getDsoLocal();
2053 mlir::TypeConverter::SignatureConversion signatureConversion(
2054 fnType.getNumInputs());
2056 for (
const auto &argType : llvm::enumerate(fnType.getInputs())) {
2057 mlir::Type convertedType = typeConverter->convertType(argType.value());
2059 return mlir::failure();
2060 signatureConversion.addInputs(argType.index(), convertedType);
2063 mlir::Type resultType =
2064 getTypeConverter()->convertType(fnType.getReturnType());
2067 mlir::Type llvmFnTy = mlir::LLVM::LLVMFunctionType::get(
2068 resultType ? resultType : mlir::LLVM::LLVMVoidType::get(getContext()),
2069 signatureConversion.getConvertedTypes(),
2073 if (std::optional<llvm::StringRef> aliasee = op.getAliasee())
2074 return matchAndRewriteAlias(op, *aliasee, llvmFnTy, adaptor, rewriter);
2078 mlir::Location loc = op.getLoc();
2079 if (mlir::FusedLoc fusedLoc = mlir::dyn_cast<mlir::FusedLoc>(loc))
2080 loc = fusedLoc.getLocations()[0];
2081 assert((mlir::isa<mlir::FileLineColLoc>(loc) ||
2082 mlir::isa<mlir::UnknownLoc>(loc)) &&
2083 "expected single location or unknown location here");
2087 mlir::LLVM::CConv cconv = mlir::LLVM::CConv::C;
2088 SmallVector<mlir::NamedAttribute, 4> attributes;
2089 lowerFuncAttributes(op,
false, attributes);
2091 mlir::LLVM::LLVMFuncOp fn = mlir::LLVM::LLVMFuncOp::create(
2092 rewriter, loc, op.getName(), llvmFnTy, linkage, isDsoLocal, cconv,
2093 mlir::SymbolRefAttr(), attributes);
2097 if (std::optional<cir::InlineKind> inlineKind = op.getInlineKind()) {
2098 fn.setNoInline(*inlineKind == cir::InlineKind::NoInline);
2099 fn.setInlineHint(*inlineKind == cir::InlineKind::InlineHint);
2100 fn.setAlwaysInline(*inlineKind == cir::InlineKind::AlwaysInline);
2103 if (std::optional<llvm::StringRef> personality = op.getPersonality())
2104 fn.setPersonality(*personality);
2109 rewriter.inlineRegionBefore(op.getBody(), fn.getBody(), fn.end());
2110 if (failed(rewriter.convertRegionTypes(&fn.getBody(), *typeConverter,
2111 &signatureConversion)))
2112 return mlir::failure();
2114 rewriter.eraseOp(op);
2116 return mlir::LogicalResult::success();
2119mlir::LogicalResult CIRToLLVMGetGlobalOpLowering::matchAndRewrite(
2120 cir::GetGlobalOp op, OpAdaptor adaptor,
2121 mlir::ConversionPatternRewriter &rewriter)
const {
2124 if (op->getUses().empty()) {
2125 rewriter.eraseOp(op);
2126 return mlir::success();
2129 mlir::Type
type = getTypeConverter()->convertType(op.getType());
2130 mlir::Operation *newop = mlir::LLVM::AddressOfOp::create(
2131 rewriter, op.getLoc(), type, op.getName());
2135 newop = mlir::LLVM::ThreadlocalAddressOp::create(rewriter, op.getLoc(),
2136 type, newop->getResult(0));
2139 rewriter.replaceOp(op, newop);
2140 return mlir::success();
2145void CIRToLLVMGlobalOpLowering::setupRegionInitializedLLVMGlobalOp(
2146 cir::GlobalOp op, mlir::ConversionPatternRewriter &rewriter)
const {
2147 const mlir::Type llvmType =
2154 const bool isConst = op.getConstant();
2156 const unsigned addrSpace = 0;
2157 const bool isDsoLocal = op.getDsoLocal();
2158 const bool isThreadLocal = (
bool)op.getTlsModelAttr();
2159 const uint64_t alignment = op.getAlignment().value_or(0);
2160 const mlir::LLVM::Linkage linkage =
convertLinkage(op.getLinkage());
2161 const StringRef symbol = op.getSymName();
2162 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
2164 SmallVector<mlir::NamedAttribute> attributes;
2165 mlir::LLVM::GlobalOp newGlobalOp =
2166 rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
2167 op, llvmType, isConst, linkage, symbol,
nullptr, alignment, addrSpace,
2168 isDsoLocal, isThreadLocal, comdatAttr, attributes);
2169 newGlobalOp.getRegion().emplaceBlock();
2170 rewriter.setInsertionPointToEnd(newGlobalOp.getInitializerBlock());
2174CIRToLLVMGlobalOpLowering::matchAndRewriteRegionInitializedGlobal(
2175 cir::GlobalOp op, mlir::Attribute init,
2176 mlir::ConversionPatternRewriter &rewriter)
const {
2179 (isa<cir::ConstArrayAttr, cir::ConstRecordAttr, cir::ConstVectorAttr,
2180 cir::ConstPtrAttr, cir::ConstComplexAttr, cir::GlobalViewAttr,
2181 cir::TypeInfoAttr, cir::UndefAttr, cir::VTableAttr, cir::ZeroAttr>(
2187 const mlir::Location loc = op.getLoc();
2188 setupRegionInitializedLLVMGlobalOp(op, rewriter);
2189 CIRAttrToValue valueConverter(op, rewriter, typeConverter, lowerMod);
2190 mlir::Value value = valueConverter.visit(init);
2191 mlir::LLVM::ReturnOp::create(rewriter, loc, value);
2192 return mlir::success();
2195mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite(
2196 cir::GlobalOp op, OpAdaptor adaptor,
2197 mlir::ConversionPatternRewriter &rewriter)
const {
2200 if (!op.getCtorRegion().empty() || !op.getDtorRegion().empty())
2201 return op.emitError() <<
"GlobalOp ctor and dtor regions should be removed "
2202 "in LoweringPrepare";
2204 std::optional<mlir::Attribute> init = op.getInitialValue();
2207 const mlir::Type cirSymType = op.getSymType();
2210 const mlir::Type llvmType =
2214 const bool isConst = op.getConstant();
2216 const unsigned addrSpace = 0;
2217 const bool isDsoLocal = op.getDsoLocal();
2218 const bool isThreadLocal = (
bool)op.getTlsModelAttr();
2219 const uint64_t alignment = op.getAlignment().value_or(0);
2220 const mlir::LLVM::Linkage linkage =
convertLinkage(op.getLinkage());
2221 const StringRef symbol = op.getSymName();
2222 SmallVector<mlir::NamedAttribute> attributes;
2224 if (init.has_value()) {
2225 if (mlir::isa<cir::FPAttr, cir::IntAttr, cir::BoolAttr>(init.value())) {
2227 init = initRewriter.visit(init.value());
2232 if (!init.value()) {
2233 op.emitError() <<
"unsupported initializer '" << init.value() <<
"'";
2234 return mlir::failure();
2236 }
else if (mlir::isa<cir::ConstArrayAttr, cir::ConstVectorAttr,
2237 cir::ConstRecordAttr, cir::ConstPtrAttr,
2238 cir::ConstComplexAttr, cir::GlobalViewAttr,
2239 cir::TypeInfoAttr, cir::UndefAttr, cir::VTableAttr,
2240 cir::ZeroAttr>(init.value())) {
2244 return matchAndRewriteRegionInitializedGlobal(op, init.value(), rewriter);
2248 op.emitError() <<
"unsupported initializer '" << init.value() <<
"'";
2249 return mlir::failure();
2253 mlir::LLVM::Visibility visibility =
2255 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
2256 auto newOp = rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
2257 op, llvmType, isConst, linkage, symbol, init.value_or(mlir::Attribute()),
2258 alignment, addrSpace, isDsoLocal, isThreadLocal, comdatAttr, attributes);
2259 newOp.setVisibility_(visibility);
2261 return mlir::success();
2265CIRToLLVMGlobalOpLowering::getComdatAttr(cir::GlobalOp &op,
2266 mlir::OpBuilder &builder)
const {
2267 if (!op.getComdat())
2268 return mlir::SymbolRefAttr{};
2270 mlir::ModuleOp module = op->getParentOfType<mlir::ModuleOp>();
2271 mlir::OpBuilder::InsertionGuard guard(builder);
2272 StringRef comdatName(
"__llvm_comdat_globals");
2274 builder.setInsertionPointToStart(module.getBody());
2276 mlir::LLVM::ComdatOp::create(builder, module.getLoc(), comdatName);
2279 if (
auto comdatSelector = comdatOp.lookupSymbol<mlir::LLVM::ComdatSelectorOp>(
2281 return mlir::SymbolRefAttr::get(
2282 builder.getContext(), comdatName,
2283 mlir::FlatSymbolRefAttr::get(comdatSelector.getSymNameAttr()));
2286 builder.setInsertionPointToStart(&comdatOp.getBody().back());
2287 auto selectorOp = mlir::LLVM::ComdatSelectorOp::create(
2288 builder, comdatOp.getLoc(), op.getSymName(),
2289 mlir::LLVM::comdat::Comdat::Any);
2290 return mlir::SymbolRefAttr::get(
2291 builder.getContext(), comdatName,
2292 mlir::FlatSymbolRefAttr::get(selectorOp.getSymNameAttr()));
2295mlir::LogicalResult CIRToLLVMSwitchFlatOpLowering::matchAndRewrite(
2296 cir::SwitchFlatOp op, OpAdaptor adaptor,
2297 mlir::ConversionPatternRewriter &rewriter)
const {
2299 llvm::SmallVector<mlir::APInt, 8> caseValues;
2300 for (mlir::Attribute val : op.getCaseValues()) {
2301 auto intAttr = cast<cir::IntAttr>(val);
2302 caseValues.push_back(intAttr.getValue());
2305 llvm::SmallVector<mlir::Block *, 8> caseDestinations;
2306 llvm::SmallVector<mlir::ValueRange, 8> caseOperands;
2308 for (mlir::Block *x : op.getCaseDestinations())
2309 caseDestinations.push_back(x);
2311 for (mlir::OperandRange x : op.getCaseOperands())
2312 caseOperands.push_back(x);
2315 rewriter.setInsertionPoint(op);
2316 rewriter.replaceOpWithNewOp<mlir::LLVM::SwitchOp>(
2317 op, adaptor.getCondition(), op.getDefaultDestination(),
2318 op.getDefaultOperands(), caseValues, caseDestinations, caseOperands);
2319 return mlir::success();
2322mlir::LogicalResult CIRToLLVMUnaryOpLowering::matchAndRewrite(
2323 cir::UnaryOp op, OpAdaptor adaptor,
2324 mlir::ConversionPatternRewriter &rewriter)
const {
2325 assert(op.getType() == op.getInput().getType() &&
2326 "Unary operation's operand type and result type are different");
2327 mlir::Type
type = op.getType();
2328 mlir::Type elementType = elementTypeIfVector(type);
2329 bool isVector = mlir::isa<cir::VectorType>(type);
2330 mlir::Type llvmType = getTypeConverter()->convertType(type);
2331 mlir::Location loc = op.getLoc();
2334 if (mlir::isa<cir::IntType>(elementType)) {
2335 mlir::LLVM::IntegerOverflowFlags maybeNSW =
2336 op.getNoSignedWrap() ? mlir::LLVM::IntegerOverflowFlags::nsw
2337 : mlir::LLVM::IntegerOverflowFlags::none;
2338 switch (op.getKind()) {
2339 case cir::UnaryOpKind::Inc: {
2340 assert(!
isVector &&
"++ not allowed on vector types");
2341 auto one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
2342 rewriter.replaceOpWithNewOp<mlir::LLVM::AddOp>(
2343 op, llvmType, adaptor.getInput(), one, maybeNSW);
2344 return mlir::success();
2346 case cir::UnaryOpKind::Dec: {
2347 assert(!
isVector &&
"-- not allowed on vector types");
2348 auto one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
2349 rewriter.replaceOpWithNewOp<mlir::LLVM::SubOp>(op, adaptor.getInput(),
2351 return mlir::success();
2353 case cir::UnaryOpKind::Plus:
2354 rewriter.replaceOp(op, adaptor.getInput());
2355 return mlir::success();
2356 case cir::UnaryOpKind::Minus: {
2359 zero = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmType);
2361 zero = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 0);
2362 rewriter.replaceOpWithNewOp<mlir::LLVM::SubOp>(
2363 op, zero, adaptor.getInput(), maybeNSW);
2364 return mlir::success();
2366 case cir::UnaryOpKind::Not: {
2368 mlir::Value minusOne;
2371 mlir::dyn_cast<cir::VectorType>(type).getSize();
2372 std::vector<int32_t> values(numElements, -1);
2373 mlir::DenseIntElementsAttr denseVec = rewriter.getI32VectorAttr(values);
2375 mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, denseVec);
2377 minusOne = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, -1);
2379 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getInput(),
2381 return mlir::success();
2384 llvm_unreachable(
"Unexpected unary op for int");
2388 if (mlir::isa<cir::FPTypeInterface>(elementType)) {
2389 switch (op.getKind()) {
2390 case cir::UnaryOpKind::Inc: {
2391 assert(!
isVector &&
"++ not allowed on vector types");
2392 mlir::LLVM::ConstantOp one = mlir::LLVM::ConstantOp::create(
2393 rewriter, loc, llvmType, rewriter.getFloatAttr(llvmType, 1.0));
2394 rewriter.replaceOpWithNewOp<mlir::LLVM::FAddOp>(op, llvmType, one,
2395 adaptor.getInput());
2396 return mlir::success();
2398 case cir::UnaryOpKind::Dec: {
2399 assert(!
isVector &&
"-- not allowed on vector types");
2400 mlir::LLVM::ConstantOp minusOne = mlir::LLVM::ConstantOp::create(
2401 rewriter, loc, llvmType, rewriter.getFloatAttr(llvmType, -1.0));
2402 rewriter.replaceOpWithNewOp<mlir::LLVM::FAddOp>(op, llvmType, minusOne,
2403 adaptor.getInput());
2404 return mlir::success();
2406 case cir::UnaryOpKind::Plus:
2407 rewriter.replaceOp(op, adaptor.getInput());
2408 return mlir::success();
2409 case cir::UnaryOpKind::Minus:
2410 rewriter.replaceOpWithNewOp<mlir::LLVM::FNegOp>(op, llvmType,
2411 adaptor.getInput());
2412 return mlir::success();
2413 case cir::UnaryOpKind::Not:
2414 return op.emitError() <<
"Unary not is invalid for floating-point types";
2416 llvm_unreachable(
"Unexpected unary op for float");
2421 if (mlir::isa<cir::BoolType>(elementType)) {
2422 switch (op.getKind()) {
2423 case cir::UnaryOpKind::Inc:
2424 case cir::UnaryOpKind::Dec:
2425 case cir::UnaryOpKind::Plus:
2426 case cir::UnaryOpKind::Minus:
2429 return op.emitError() <<
"Unsupported unary operation on boolean type";
2430 case cir::UnaryOpKind::Not: {
2431 assert(!
isVector &&
"NYI: op! on vector mask");
2432 auto one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
2433 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getInput(),
2435 return mlir::success();
2438 llvm_unreachable(
"Unexpected unary op for bool");
2443 if (mlir::isa<cir::PointerType>(elementType)) {
2444 switch (op.getKind()) {
2445 case cir::UnaryOpKind::Plus:
2446 rewriter.replaceOp(op, adaptor.getInput());
2447 return mlir::success();
2449 op.emitError() <<
"Unknown pointer unary operation during CIR lowering";
2450 return mlir::failure();
2454 return op.emitError() <<
"Unary operation has unsupported type: "
2458mlir::LLVM::IntegerOverflowFlags
2459CIRToLLVMBinOpLowering::getIntOverflowFlag(cir::BinOp op)
const {
2460 if (op.getNoUnsignedWrap())
2461 return mlir::LLVM::IntegerOverflowFlags::nuw;
2463 if (op.getNoSignedWrap())
2464 return mlir::LLVM::IntegerOverflowFlags::nsw;
2466 return mlir::LLVM::IntegerOverflowFlags::none;
2471 return mlir::isa<cir::IntType>(type)
2472 ? mlir::cast<cir::IntType>(type).isUnsigned()
2473 : mlir::cast<mlir::IntegerType>(type).isUnsigned();
2476mlir::LogicalResult CIRToLLVMBinOpLowering::matchAndRewrite(
2477 cir::BinOp op, OpAdaptor adaptor,
2478 mlir::ConversionPatternRewriter &rewriter)
const {
2479 if (adaptor.getLhs().getType() != adaptor.getRhs().getType())
2480 return op.emitError() <<
"inconsistent operands' types not supported yet";
2482 mlir::Type type = op.getRhs().getType();
2483 if (!mlir::isa<cir::IntType, cir::BoolType, cir::FPTypeInterface,
2484 mlir::IntegerType, cir::VectorType>(type))
2485 return op.emitError() <<
"operand type not supported yet";
2487 const mlir::Type llvmTy = getTypeConverter()->convertType(op.getType());
2488 const mlir::Type llvmEltTy = elementTypeIfVector(llvmTy);
2490 const mlir::Value rhs = adaptor.getRhs();
2491 const mlir::Value lhs = adaptor.getLhs();
2492 type = elementTypeIfVector(type);
2494 switch (op.getKind()) {
2495 case cir::BinOpKind::Add:
2496 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
2497 if (op.getSaturated()) {
2499 rewriter.replaceOpWithNewOp<mlir::LLVM::UAddSat>(op, lhs, rhs);
2502 rewriter.replaceOpWithNewOp<mlir::LLVM::SAddSat>(op, lhs, rhs);
2505 rewriter.replaceOpWithNewOp<mlir::LLVM::AddOp>(op, llvmTy, lhs, rhs,
2506 getIntOverflowFlag(op));
2508 rewriter.replaceOpWithNewOp<mlir::LLVM::FAddOp>(op, lhs, rhs);
2511 case cir::BinOpKind::Sub:
2512 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
2513 if (op.getSaturated()) {
2515 rewriter.replaceOpWithNewOp<mlir::LLVM::USubSat>(op, lhs, rhs);
2518 rewriter.replaceOpWithNewOp<mlir::LLVM::SSubSat>(op, lhs, rhs);
2521 rewriter.replaceOpWithNewOp<mlir::LLVM::SubOp>(op, llvmTy, lhs, rhs,
2522 getIntOverflowFlag(op));
2524 rewriter.replaceOpWithNewOp<mlir::LLVM::FSubOp>(op, lhs, rhs);
2527 case cir::BinOpKind::Mul:
2528 if (mlir::isa<mlir::IntegerType>(llvmEltTy))
2529 rewriter.replaceOpWithNewOp<mlir::LLVM::MulOp>(op, llvmTy, lhs, rhs,
2530 getIntOverflowFlag(op));
2532 rewriter.replaceOpWithNewOp<mlir::LLVM::FMulOp>(op, lhs, rhs);
2534 case cir::BinOpKind::Div:
2535 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
2538 rewriter.replaceOpWithNewOp<mlir::LLVM::UDivOp>(op, lhs, rhs);
2540 rewriter.replaceOpWithNewOp<mlir::LLVM::SDivOp>(op, lhs, rhs);
2542 rewriter.replaceOpWithNewOp<mlir::LLVM::FDivOp>(op, lhs, rhs);
2545 case cir::BinOpKind::Rem:
2546 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
2549 rewriter.replaceOpWithNewOp<mlir::LLVM::URemOp>(op, lhs, rhs);
2551 rewriter.replaceOpWithNewOp<mlir::LLVM::SRemOp>(op, lhs, rhs);
2553 rewriter.replaceOpWithNewOp<mlir::LLVM::FRemOp>(op, lhs, rhs);
2556 case cir::BinOpKind::And:
2557 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(op, lhs, rhs);
2559 case cir::BinOpKind::Or:
2560 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(op, lhs, rhs);
2562 case cir::BinOpKind::Xor:
2563 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, lhs, rhs);
2565 case cir::BinOpKind::Max:
2566 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
2569 rewriter.replaceOpWithNewOp<mlir::LLVM::UMaxOp>(op, llvmTy, lhs, rhs);
2571 rewriter.replaceOpWithNewOp<mlir::LLVM::SMaxOp>(op, llvmTy, lhs, rhs);
2575 return mlir::LogicalResult::success();
2579static mlir::LLVM::ICmpPredicate
2581 using CIR = cir::CmpOpKind;
2582 using LLVMICmp = mlir::LLVM::ICmpPredicate;
2585 return LLVMICmp::eq;
2587 return LLVMICmp::ne;
2589 return (isSigned ? LLVMICmp::slt : LLVMICmp::ult);
2591 return (isSigned ? LLVMICmp::sle : LLVMICmp::ule);
2593 return (isSigned ? LLVMICmp::sgt : LLVMICmp::ugt);
2595 return (isSigned ? LLVMICmp::sge : LLVMICmp::uge);
2597 llvm_unreachable(
"Unknown CmpOpKind");
2602static mlir::LLVM::FCmpPredicate
2604 using CIR = cir::CmpOpKind;
2605 using LLVMFCmp = mlir::LLVM::FCmpPredicate;
2608 return LLVMFCmp::oeq;
2610 return LLVMFCmp::une;
2612 return LLVMFCmp::olt;
2614 return LLVMFCmp::ole;
2616 return LLVMFCmp::ogt;
2618 return LLVMFCmp::oge;
2620 llvm_unreachable(
"Unknown CmpOpKind");
2623mlir::LogicalResult CIRToLLVMCmpOpLowering::matchAndRewrite(
2624 cir::CmpOp cmpOp, OpAdaptor adaptor,
2625 mlir::ConversionPatternRewriter &rewriter)
const {
2626 mlir::Type type = cmpOp.getLhs().getType();
2631 if (mlir::isa<cir::IntType, mlir::IntegerType>(type)) {
2632 bool isSigned = mlir::isa<cir::IntType>(type)
2633 ? mlir::cast<cir::IntType>(type).isSigned()
2634 : mlir::cast<mlir::IntegerType>(type).isSigned();
2635 mlir::LLVM::ICmpPredicate kind =
2637 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
2638 cmpOp, kind, adaptor.getLhs(), adaptor.getRhs());
2639 return mlir::success();
2642 if (
auto ptrTy = mlir::dyn_cast<cir::PointerType>(type)) {
2643 mlir::LLVM::ICmpPredicate kind =
2646 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
2647 cmpOp, kind, adaptor.getLhs(), adaptor.getRhs());
2648 return mlir::success();
2651 if (
auto vptrTy = mlir::dyn_cast<cir::VPtrType>(type)) {
2655 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
2656 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
2657 return mlir::success();
2660 if (mlir::isa<cir::FPTypeInterface>(type)) {
2661 mlir::LLVM::FCmpPredicate
kind =
2663 rewriter.replaceOpWithNewOp<mlir::LLVM::FCmpOp>(
2664 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
2665 return mlir::success();
2668 if (mlir::isa<cir::ComplexType>(type)) {
2669 mlir::Value lhs = adaptor.getLhs();
2670 mlir::Value rhs = adaptor.getRhs();
2671 mlir::Location loc = cmpOp.getLoc();
2673 auto complexType = mlir::cast<cir::ComplexType>(cmpOp.getLhs().getType());
2674 mlir::Type complexElemTy =
2675 getTypeConverter()->convertType(
complexType.getElementType());
2677 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
2678 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{0}));
2679 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
2680 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{1}));
2681 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
2682 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{0}));
2683 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
2684 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{1}));
2686 if (cmpOp.getKind() == cir::CmpOpKind::eq) {
2687 if (complexElemTy.isInteger()) {
2688 auto realCmp = mlir::LLVM::ICmpOp::create(
2689 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, lhsReal, rhsReal);
2690 auto imagCmp = mlir::LLVM::ICmpOp::create(
2691 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, lhsImag, rhsImag);
2692 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, imagCmp);
2693 return mlir::success();
2696 auto realCmp = mlir::LLVM::FCmpOp::create(
2697 rewriter, loc, mlir::LLVM::FCmpPredicate::oeq, lhsReal, rhsReal);
2698 auto imagCmp = mlir::LLVM::FCmpOp::create(
2699 rewriter, loc, mlir::LLVM::FCmpPredicate::oeq, lhsImag, rhsImag);
2700 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, imagCmp);
2701 return mlir::success();
2704 if (cmpOp.getKind() == cir::CmpOpKind::ne) {
2705 if (complexElemTy.isInteger()) {
2706 auto realCmp = mlir::LLVM::ICmpOp::create(
2707 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, lhsReal, rhsReal);
2708 auto imagCmp = mlir::LLVM::ICmpOp::create(
2709 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, lhsImag, rhsImag);
2710 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp);
2711 return mlir::success();
2714 auto realCmp = mlir::LLVM::FCmpOp::create(
2715 rewriter, loc, mlir::LLVM::FCmpPredicate::une, lhsReal, rhsReal);
2716 auto imagCmp = mlir::LLVM::FCmpOp::create(
2717 rewriter, loc, mlir::LLVM::FCmpPredicate::une, lhsImag, rhsImag);
2718 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp);
2719 return mlir::success();
2723 return cmpOp.emitError() <<
"unsupported type for CmpOp: " <<
type;
2726mlir::LogicalResult CIRToLLVMBinOpOverflowOpLowering::matchAndRewrite(
2727 cir::BinOpOverflowOp op, OpAdaptor adaptor,
2728 mlir::ConversionPatternRewriter &rewriter)
const {
2729 mlir::Location loc = op.getLoc();
2730 cir::BinOpOverflowKind arithKind = op.getKind();
2731 cir::IntType operandTy = op.getLhs().getType();
2732 cir::IntType resultTy = op.getResult().getType();
2734 EncompassedTypeInfo encompassedTyInfo =
2735 computeEncompassedTypeWidth(operandTy, resultTy);
2736 mlir::IntegerType encompassedLLVMTy =
2737 rewriter.getIntegerType(encompassedTyInfo.width);
2739 mlir::Value lhs = adaptor.getLhs();
2740 mlir::Value rhs = adaptor.getRhs();
2741 if (operandTy.getWidth() < encompassedTyInfo.width) {
2742 if (operandTy.isSigned()) {
2743 lhs = mlir::LLVM::SExtOp::create(rewriter, loc, encompassedLLVMTy, lhs);
2744 rhs = mlir::LLVM::SExtOp::create(rewriter, loc, encompassedLLVMTy, rhs);
2746 lhs = mlir::LLVM::ZExtOp::create(rewriter, loc, encompassedLLVMTy, lhs);
2747 rhs = mlir::LLVM::ZExtOp::create(rewriter, loc, encompassedLLVMTy, rhs);
2751 std::string intrinName = getLLVMIntrinName(arithKind, encompassedTyInfo.sign,
2752 encompassedTyInfo.width);
2753 auto intrinNameAttr = mlir::StringAttr::get(op.getContext(), intrinName);
2755 mlir::IntegerType overflowLLVMTy = rewriter.getI1Type();
2756 auto intrinRetTy = mlir::LLVM::LLVMStructType::getLiteral(
2757 rewriter.getContext(), {encompassedLLVMTy, overflowLLVMTy});
2759 auto callLLVMIntrinOp = mlir::LLVM::CallIntrinsicOp::create(
2760 rewriter, loc, intrinRetTy, intrinNameAttr, mlir::ValueRange{lhs, rhs});
2761 mlir::Value intrinRet = callLLVMIntrinOp.getResult(0);
2763 mlir::Value result = mlir::LLVM::ExtractValueOp::create(
2764 rewriter, loc, intrinRet, ArrayRef<int64_t>{0})
2766 mlir::Value overflow = mlir::LLVM::ExtractValueOp::create(
2767 rewriter, loc, intrinRet, ArrayRef<int64_t>{1})
2770 if (resultTy.getWidth() < encompassedTyInfo.width) {
2771 mlir::Type resultLLVMTy = getTypeConverter()->convertType(resultTy);
2773 mlir::LLVM::TruncOp::create(rewriter, loc, resultLLVMTy, result);
2777 mlir::Value truncResultExt;
2778 if (resultTy.isSigned())
2779 truncResultExt = mlir::LLVM::SExtOp::create(
2780 rewriter, loc, encompassedLLVMTy, truncResult);
2782 truncResultExt = mlir::LLVM::ZExtOp::create(
2783 rewriter, loc, encompassedLLVMTy, truncResult);
2784 auto truncOverflow = mlir::LLVM::ICmpOp::create(
2785 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, truncResultExt, result);
2787 result = truncResult;
2788 overflow = mlir::LLVM::OrOp::create(rewriter, loc, overflow, truncOverflow);
2791 mlir::Type boolLLVMTy =
2792 getTypeConverter()->convertType(op.getOverflow().getType());
2793 if (boolLLVMTy != rewriter.getI1Type())
2794 overflow = mlir::LLVM::ZExtOp::create(rewriter, loc, boolLLVMTy, overflow);
2796 rewriter.replaceOp(op, mlir::ValueRange{result, overflow});
2798 return mlir::success();
2801std::string CIRToLLVMBinOpOverflowOpLowering::getLLVMIntrinName(
2802 cir::BinOpOverflowKind opKind,
bool isSigned,
unsigned width) {
2805 std::string
name =
"llvm.";
2808 name.push_back(
's');
2810 name.push_back(
'u');
2813 case cir::BinOpOverflowKind::Add:
2814 name.append(
"add.");
2816 case cir::BinOpOverflowKind::Sub:
2817 name.append(
"sub.");
2819 case cir::BinOpOverflowKind::Mul:
2820 name.append(
"mul.");
2824 name.append(
"with.overflow.i");
2825 name.append(std::to_string(width));
2830CIRToLLVMBinOpOverflowOpLowering::EncompassedTypeInfo
2831CIRToLLVMBinOpOverflowOpLowering::computeEncompassedTypeWidth(
2832 cir::IntType operandTy, cir::IntType resultTy) {
2833 bool sign = operandTy.getIsSigned() || resultTy.getIsSigned();
2835 std::max(operandTy.getWidth() + (
sign && operandTy.isUnsigned()),
2836 resultTy.getWidth() + (
sign && resultTy.isUnsigned()));
2837 return {
sign, width};
2840mlir::LogicalResult CIRToLLVMShiftOpLowering::matchAndRewrite(
2841 cir::ShiftOp op, OpAdaptor adaptor,
2842 mlir::ConversionPatternRewriter &rewriter)
const {
2843 assert((op.getValue().getType() == op.getType()) &&
2844 "inconsistent operands' types NYI");
2846 const mlir::Type llvmTy = getTypeConverter()->convertType(op.getType());
2847 mlir::Value amt = adaptor.getAmount();
2848 mlir::Value val = adaptor.getValue();
2850 auto cirAmtTy = mlir::dyn_cast<cir::IntType>(op.getAmount().getType());
2853 auto cirValTy = mlir::cast<cir::IntType>(op.getValue().getType());
2861 amt =
getLLVMIntCast(rewriter, amt, llvmTy,
true, cirAmtTy.getWidth(),
2862 cirValTy.getWidth());
2864 auto cirValVTy = mlir::cast<cir::VectorType>(op.getValue().getType());
2866 mlir::cast<cir::IntType>(cirValVTy.getElementType()).isUnsigned();
2870 if (op.getIsShiftleft()) {
2871 rewriter.replaceOpWithNewOp<mlir::LLVM::ShlOp>(op, llvmTy, val, amt);
2872 return mlir::success();
2876 rewriter.replaceOpWithNewOp<mlir::LLVM::LShrOp>(op, llvmTy, val, amt);
2878 rewriter.replaceOpWithNewOp<mlir::LLVM::AShrOp>(op, llvmTy, val, amt);
2879 return mlir::success();
2882mlir::LogicalResult CIRToLLVMSelectOpLowering::matchAndRewrite(
2883 cir::SelectOp op, OpAdaptor adaptor,
2884 mlir::ConversionPatternRewriter &rewriter)
const {
2885 auto getConstantBool = [](mlir::Value value) -> cir::BoolAttr {
2886 auto definingOp = value.getDefiningOp<cir::ConstantOp>();
2890 auto constValue = definingOp.getValueAttr<cir::BoolAttr>();
2900 if (mlir::isa<cir::BoolType>(op.getTrueValue().getType())) {
2901 cir::BoolAttr trueValue = getConstantBool(op.getTrueValue());
2902 cir::BoolAttr falseValue = getConstantBool(op.getFalseValue());
2903 if (falseValue && !falseValue.getValue()) {
2905 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(op, adaptor.getCondition(),
2906 adaptor.getTrueValue());
2907 return mlir::success();
2909 if (trueValue && trueValue.getValue()) {
2911 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(op, adaptor.getCondition(),
2912 adaptor.getFalseValue());
2913 return mlir::success();
2917 mlir::Value llvmCondition = adaptor.getCondition();
2918 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(
2919 op, llvmCondition, adaptor.getTrueValue(), adaptor.getFalseValue());
2921 return mlir::success();
2925 mlir::PatternRewriter rewriter{
module->getContext()};
2930 if (!module->hasAttr(cir::CIRDialect::getTripleAttrName()))
2936 mlir::DataLayout &dataLayout,
2938 converter.addConversion([&](cir::PointerType type) -> mlir::Type {
2939 unsigned addrSpace =
2940 type.getAddrSpace() ? type.getAddrSpace().getValue().getUInt() : 0;
2941 return mlir::LLVM::LLVMPointerType::get(type.getContext(), addrSpace);
2943 converter.addConversion([&](cir::VPtrType type) -> mlir::Type {
2945 return mlir::LLVM::LLVMPointerType::get(type.getContext());
2947 converter.addConversion([&](cir::ArrayType type) -> mlir::Type {
2950 return mlir::LLVM::LLVMArrayType::get(ty, type.getSize());
2952 converter.addConversion([&](cir::VectorType type) -> mlir::Type {
2953 const mlir::Type ty = converter.convertType(type.getElementType());
2954 return mlir::VectorType::get(type.getSize(), ty, {type.getIsScalable()});
2956 converter.addConversion([&](cir::BoolType type) -> mlir::Type {
2957 return mlir::IntegerType::get(type.getContext(), 1,
2958 mlir::IntegerType::Signless);
2960 converter.addConversion([&](cir::IntType type) -> mlir::Type {
2962 return mlir::IntegerType::get(type.getContext(), type.getWidth());
2964 converter.addConversion([&](cir::SingleType type) -> mlir::Type {
2965 return mlir::Float32Type::get(type.getContext());
2967 converter.addConversion([&](cir::DoubleType type) -> mlir::Type {
2968 return mlir::Float64Type::get(type.getContext());
2970 converter.addConversion([&](cir::FP80Type type) -> mlir::Type {
2971 return mlir::Float80Type::get(type.getContext());
2973 converter.addConversion([&](cir::FP128Type type) -> mlir::Type {
2974 return mlir::Float128Type::get(type.getContext());
2976 converter.addConversion([&](cir::LongDoubleType type) -> mlir::Type {
2977 return converter.convertType(type.getUnderlying());
2979 converter.addConversion([&](cir::FP16Type type) -> mlir::Type {
2980 return mlir::Float16Type::get(type.getContext());
2982 converter.addConversion([&](cir::BF16Type type) -> mlir::Type {
2983 return mlir::BFloat16Type::get(type.getContext());
2985 converter.addConversion([&](cir::ComplexType type) -> mlir::Type {
2988 mlir::Type elementTy = converter.convertType(type.getElementType());
2989 mlir::Type structFields[2] = {elementTy, elementTy};
2990 return mlir::LLVM::LLVMStructType::getLiteral(type.getContext(),
2993 converter.addConversion([&](cir::FuncType type) -> std::optional<mlir::Type> {
2994 auto result = converter.convertType(type.getReturnType());
2996 arguments.reserve(type.getNumInputs());
2997 if (converter.convertTypes(type.getInputs(), arguments).failed())
2998 return std::nullopt;
2999 auto varArg = type.isVarArg();
3000 return mlir::LLVM::LLVMFunctionType::get(result, arguments, varArg);
3002 converter.addConversion([&](cir::RecordType type) -> mlir::Type {
3005 switch (type.getKind()) {
3006 case cir::RecordType::Class:
3007 case cir::RecordType::Struct:
3008 for (mlir::Type ty : type.getMembers())
3012 case cir::RecordType::Union:
3013 if (
auto largestMember = type.getLargestMember(dataLayout))
3014 llvmMembers.push_back(
3016 if (type.getPadded()) {
3017 auto last = *type.getMembers().rbegin();
3018 llvmMembers.push_back(
3025 mlir::LLVM::LLVMStructType llvmStruct;
3026 if (type.getName()) {
3027 llvmStruct = mlir::LLVM::LLVMStructType::getIdentified(
3028 type.getContext(), type.getPrefixedName());
3029 if (llvmStruct.setBody(llvmMembers, type.getPacked()).failed())
3030 llvm_unreachable(
"Failed to set body of record");
3032 llvmStruct = mlir::LLVM::LLVMStructType::getLiteral(
3033 type.getContext(), llvmMembers, type.getPacked());
3038 converter.addConversion([&](cir::VoidType type) -> mlir::Type {
3039 return mlir::LLVM::LLVMVoidType::get(type.getContext());
3044 mlir::ModuleOp module, StringRef globalXtorName, StringRef llvmXtorName,
3045 llvm::function_ref<std::pair<StringRef, int>(mlir::Attribute)> createXtor) {
3047 for (
const mlir::NamedAttribute namedAttr : module->getAttrs()) {
3048 if (namedAttr.getName() == globalXtorName) {
3049 for (
auto attr : mlir::cast<mlir::ArrayAttr>(namedAttr.getValue()))
3050 globalXtors.emplace_back(createXtor(attr));
3055 if (globalXtors.empty())
3058 mlir::OpBuilder builder(module.getContext());
3059 builder.setInsertionPointToEnd(&module.getBodyRegion().back());
3063 auto ctorPFTy = mlir::LLVM::LLVMPointerType::get(builder.getContext());
3065 ctorStructFields.push_back(builder.getI32Type());
3066 ctorStructFields.push_back(ctorPFTy);
3067 ctorStructFields.push_back(ctorPFTy);
3069 auto ctorStructTy = mlir::LLVM::LLVMStructType::getLiteral(
3070 builder.getContext(), ctorStructFields);
3071 auto ctorStructArrayTy =
3072 mlir::LLVM::LLVMArrayType::get(ctorStructTy, globalXtors.size());
3074 mlir::Location loc =
module.getLoc();
3075 auto newGlobalOp = mlir::LLVM::GlobalOp::create(
3076 builder, loc, ctorStructArrayTy,
false,
3077 mlir::LLVM::Linkage::Appending, llvmXtorName, mlir::Attribute());
3079 builder.createBlock(&newGlobalOp.getRegion());
3080 builder.setInsertionPointToEnd(newGlobalOp.getInitializerBlock());
3082 mlir::Value result =
3083 mlir::LLVM::UndefOp::create(builder, loc, ctorStructArrayTy);
3085 for (
auto [index, fn] : llvm::enumerate(globalXtors)) {
3086 mlir::Value structInit =
3087 mlir::LLVM::UndefOp::create(builder, loc, ctorStructTy);
3088 mlir::Value initPriority = mlir::LLVM::ConstantOp::create(
3089 builder, loc, ctorStructFields[0], fn.second);
3090 mlir::Value initFuncAddr = mlir::LLVM::AddressOfOp::create(
3091 builder, loc, ctorStructFields[1], fn.first);
3092 mlir::Value initAssociate =
3093 mlir::LLVM::ZeroOp::create(builder, loc, ctorStructFields[2]);
3096 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
3097 initPriority, zero);
3098 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
3101 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
3103 result = mlir::LLVM::InsertValueOp::create(builder, loc, result, structInit,
3107 mlir::LLVM::ReturnOp::create(builder, loc, result);
3145 parent->walk([&](mlir::Block *blk) {
3146 if (blk->hasNoPredecessors() && !blk->isEntryBlock())
3147 unreachableBlocks.push_back(blk);
3150 std::set<mlir::Block *> visited;
3151 for (mlir::Block *root : unreachableBlocks) {
3154 std::deque<mlir::Block *> workList;
3155 workList.push_back(root);
3157 while (!workList.empty()) {
3158 mlir::Block *blk = workList.back();
3159 workList.pop_back();
3160 if (visited.count(blk))
3162 visited.emplace(blk);
3164 for (mlir::Operation &op : *blk)
3167 for (mlir::Block *succ : blk->getSuccessors())
3168 workList.push_back(succ);
3173mlir::LogicalResult CIRToLLVMObjSizeOpLowering::matchAndRewrite(
3174 cir::ObjSizeOp op, OpAdaptor adaptor,
3175 mlir::ConversionPatternRewriter &rewriter)
const {
3176 mlir::Type llvmResTy = getTypeConverter()->convertType(op.getType());
3177 mlir::Location loc = op->getLoc();
3179 mlir::IntegerType i1Ty = rewriter.getI1Type();
3181 auto i1Val = [&rewriter, &loc, &i1Ty](
bool val) {
3182 return mlir::LLVM::ConstantOp::create(rewriter, loc, i1Ty, val);
3189 i1Val(op.getNullunknown()),
3190 i1Val(op.getDynamic()),
3193 return mlir::LogicalResult::success();
3198 if (mlir::Attribute tripleAttr =
3199 module->getAttr(cir::CIRDialect::getTripleAttrName()))
3200 module->setAttr(mlir::LLVM::LLVMDialect::getTargetTripleAttrName(),
3203 if (mlir::Attribute asmAttr =
3204 module->getAttr(cir::CIRDialect::getModuleLevelAsmAttrName()))
3205 module->setAttr(mlir::LLVM::LLVMDialect::getModuleLevelAsmAttrName(),
3210 llvm::TimeTraceScope scope(
"Convert CIR to LLVM Pass");
3212 mlir::ModuleOp module = getOperation();
3213 mlir::DataLayout dl(module);
3214 mlir::LLVMTypeConverter converter(&getContext());
3218 mlir::RewritePatternSet patterns(&getContext());
3221#define GET_LLVM_LOWERING_PATTERNS_LIST
3222#include "clang/CIR/Dialect/IR/CIRLowering.inc"
3223#undef GET_LLVM_LOWERING_PATTERNS_LIST
3224 >(converter, patterns.getContext(), lowerModule.get(), dl);
3228 mlir::ConversionTarget target(getContext());
3229 target.addLegalOp<mlir::ModuleOp>();
3230 target.addLegalDialect<mlir::LLVM::LLVMDialect>();
3231 target.addIllegalDialect<mlir::BuiltinDialect, cir::CIRDialect,
3232 mlir::func::FuncDialect>();
3235 ops.push_back(module);
3238 if (failed(applyPartialConversion(ops, target, std::move(patterns))))
3239 signalPassFailure();
3243 "llvm.global_ctors", [](mlir::Attribute attr) {
3244 auto ctorAttr = mlir::cast<cir::GlobalCtorAttr>(attr);
3245 return std::make_pair(ctorAttr.getName(),
3246 ctorAttr.getPriority());
3250 "llvm.global_dtors", [](mlir::Attribute attr) {
3251 auto dtorAttr = mlir::cast<cir::GlobalDtorAttr>(attr);
3252 return std::make_pair(dtorAttr.getName(),
3253 dtorAttr.getPriority());
3257mlir::LogicalResult CIRToLLVMBrOpLowering::matchAndRewrite(
3258 cir::BrOp op, OpAdaptor adaptor,
3259 mlir::ConversionPatternRewriter &rewriter)
const {
3260 rewriter.replaceOpWithNewOp<mlir::LLVM::BrOp>(op, adaptor.getOperands(),
3262 return mlir::LogicalResult::success();
3265mlir::LogicalResult CIRToLLVMGetMemberOpLowering::matchAndRewrite(
3266 cir::GetMemberOp op, OpAdaptor adaptor,
3267 mlir::ConversionPatternRewriter &rewriter)
const {
3268 mlir::Type llResTy = getTypeConverter()->convertType(op.getType());
3269 const auto recordTy =
3270 mlir::cast<cir::RecordType>(op.getAddrTy().getPointee());
3271 assert(recordTy &&
"expected record type");
3273 switch (recordTy.getKind()) {
3274 case cir::RecordType::Class:
3275 case cir::RecordType::Struct: {
3279 const mlir::Type elementTy = getTypeConverter()->convertType(recordTy);
3280 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, llResTy, elementTy,
3281 adaptor.getAddr(), offset);
3282 return mlir::success();
3284 case cir::RecordType::Union:
3287 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(op, llResTy,
3289 return mlir::success();
3293mlir::LogicalResult CIRToLLVMExtractMemberOpLowering::matchAndRewrite(
3294 cir::ExtractMemberOp op, OpAdaptor adaptor,
3295 mlir::ConversionPatternRewriter &rewriter)
const {
3296 std::int64_t indices[1] = {
static_cast<std::int64_t
>(op.getIndex())};
3298 mlir::Type recordTy = op.getRecord().getType();
3299 auto cirRecordTy = mlir::cast<cir::RecordType>(recordTy);
3300 switch (cirRecordTy.getKind()) {
3301 case cir::RecordType::Struct:
3302 case cir::RecordType::Class:
3303 rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractValueOp>(
3304 op, adaptor.getRecord(), indices);
3305 return mlir::success();
3307 case cir::RecordType::Union:
3308 op.emitError(
"cir.extract_member cannot extract member from a union");
3309 return mlir::failure();
3311 llvm_unreachable(
"Unexpected record kind");
3314mlir::LogicalResult CIRToLLVMUnreachableOpLowering::matchAndRewrite(
3315 cir::UnreachableOp op, OpAdaptor adaptor,
3316 mlir::ConversionPatternRewriter &rewriter)
const {
3317 rewriter.replaceOpWithNewOp<mlir::LLVM::UnreachableOp>(op);
3318 return mlir::success();
3322 mlir::Operation *srcOp, llvm::StringRef fnName,
3324 auto modOp = srcOp->getParentOfType<mlir::ModuleOp>();
3325 auto enclosingFnOp = srcOp->getParentOfType<mlir::LLVM::LLVMFuncOp>();
3326 mlir::Operation *sourceSymbol =
3327 mlir::SymbolTable::lookupSymbolIn(modOp, fnName);
3328 if (!sourceSymbol) {
3329 mlir::OpBuilder::InsertionGuard guard(rewriter);
3330 rewriter.setInsertionPoint(enclosingFnOp);
3331 mlir::LLVM::LLVMFuncOp::create(rewriter, srcOp->getLoc(), fnName, fnTy);
3335mlir::LogicalResult CIRToLLVMThrowOpLowering::matchAndRewrite(
3336 cir::ThrowOp op, OpAdaptor adaptor,
3337 mlir::ConversionPatternRewriter &rewriter)
const {
3338 mlir::Location loc = op.getLoc();
3339 auto voidTy = mlir::LLVM::LLVMVoidType::get(getContext());
3341 if (op.rethrows()) {
3342 auto funcTy = mlir::LLVM::LLVMFunctionType::get(voidTy, {});
3345 const llvm::StringRef functionName =
"__cxa_rethrow";
3348 auto cxaRethrow = mlir::LLVM::CallOp::create(
3349 rewriter, loc, mlir::TypeRange{}, functionName);
3351 rewriter.replaceOp(op, cxaRethrow);
3352 return mlir::success();
3355 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3356 auto fnTy = mlir::LLVM::LLVMFunctionType::get(
3357 voidTy, {llvmPtrTy, llvmPtrTy, llvmPtrTy});
3360 const llvm::StringRef fnName =
"__cxa_throw";
3363 mlir::Value typeInfo = mlir::LLVM::AddressOfOp::create(
3364 rewriter, loc, mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
3365 adaptor.getTypeInfoAttr());
3369 dtor = mlir::LLVM::AddressOfOp::create(rewriter, loc, llvmPtrTy,
3370 adaptor.getDtorAttr());
3372 dtor = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmPtrTy);
3375 auto cxaThrowCall = mlir::LLVM::CallOp::create(
3376 rewriter, loc, mlir::TypeRange{}, fnName,
3377 mlir::ValueRange{adaptor.getExceptionPtr(), typeInfo, dtor});
3379 rewriter.replaceOp(op, cxaThrowCall);
3380 return mlir::success();
3383mlir::LogicalResult CIRToLLVMAllocExceptionOpLowering::matchAndRewrite(
3384 cir::AllocExceptionOp op, OpAdaptor adaptor,
3385 mlir::ConversionPatternRewriter &rewriter)
const {
3387 StringRef fnName =
"__cxa_allocate_exception";
3388 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3389 auto int64Ty = mlir::IntegerType::get(rewriter.getContext(), 64);
3390 auto fnTy = mlir::LLVM::LLVMFunctionType::get(llvmPtrTy, {int64Ty});
3393 auto exceptionSize = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
3394 adaptor.getSizeAttr());
3396 auto allocaExceptionCall = mlir::LLVM::CallOp::create(
3397 rewriter, op.getLoc(), mlir::TypeRange{llvmPtrTy}, fnName,
3398 mlir::ValueRange{exceptionSize});
3400 rewriter.replaceOp(op, allocaExceptionCall);
3401 return mlir::success();
3404static mlir::LLVM::LLVMStructType
3407 mlir::MLIRContext *ctx = rewriter.getContext();
3408 auto llvmPtr = mlir::LLVM::LLVMPointerType::get(ctx);
3410 return mlir::LLVM::LLVMStructType::getLiteral(ctx, structFields);
3413mlir::LogicalResult CIRToLLVMEhInflightOpLowering::matchAndRewrite(
3414 cir::EhInflightOp op, OpAdaptor adaptor,
3415 mlir::ConversionPatternRewriter &rewriter)
const {
3416 auto llvmFn = op->getParentOfType<mlir::LLVM::LLVMFuncOp>();
3417 assert(llvmFn &&
"expected LLVM function parent");
3418 mlir::Block *entryBlock = &llvmFn.getRegion().front();
3419 assert(entryBlock->isEntryBlock());
3421 mlir::ArrayAttr catchListAttr = op.getCatchTypeListAttr();
3422 mlir::SmallVector<mlir::Value> catchSymAddrs;
3424 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3425 mlir::Location loc = op.getLoc();
3430 if (catchListAttr) {
3433 for (mlir::Attribute catchAttr : catchListAttr) {
3434 auto symAttr = cast<mlir::FlatSymbolRefAttr>(catchAttr);
3437 mlir::OpBuilder::InsertionGuard guard(rewriter);
3438 rewriter.setInsertionPointToStart(entryBlock);
3439 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
3440 rewriter, loc, llvmPtrTy, symAttr.getValue());
3441 catchSymAddrs.push_back(addrOp);
3443 }
else if (!op.getCleanup()) {
3447 mlir::OpBuilder::InsertionGuard guard(rewriter);
3448 rewriter.setInsertionPointToStart(entryBlock);
3449 mlir::Value nullOp = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmPtrTy);
3450 catchSymAddrs.push_back(nullOp);
3455 mlir::LLVM::LLVMStructType llvmLandingPadStructTy =
3457 auto landingPadOp = mlir::LLVM::LandingpadOp::create(
3458 rewriter, loc, llvmLandingPadStructTy, catchSymAddrs);
3460 if (op.getCleanup())
3461 landingPadOp.setCleanup(
true);
3464 mlir::LLVM::ExtractValueOp::create(rewriter, loc, landingPadOp, 0);
3465 mlir::Value selector =
3466 mlir::LLVM::ExtractValueOp::create(rewriter, loc, landingPadOp, 1);
3467 rewriter.replaceOp(op, mlir::ValueRange{slot, selector});
3469 return mlir::success();
3472mlir::LogicalResult CIRToLLVMResumeFlatOpLowering::matchAndRewrite(
3473 cir::ResumeFlatOp op, OpAdaptor adaptor,
3474 mlir::ConversionPatternRewriter &rewriter)
const {
3479 mlir::Value poison = mlir::LLVM::PoisonOp::create(rewriter, op.getLoc(),
3480 llvmLandingPadStructTy);
3482 SmallVector<int64_t> slotIdx = {0};
3483 mlir::Value slot = mlir::LLVM::InsertValueOp::create(
3484 rewriter, op.getLoc(), poison, adaptor.getExceptionPtr(), slotIdx);
3486 SmallVector<int64_t> selectorIdx = {1};
3487 mlir::Value selector = mlir::LLVM::InsertValueOp::create(
3488 rewriter, op.getLoc(), slot, adaptor.getTypeId(), selectorIdx);
3490 rewriter.replaceOpWithNewOp<mlir::LLVM::ResumeOp>(op, selector);
3491 return mlir::success();
3494mlir::LogicalResult CIRToLLVMEhTypeIdOpLowering::matchAndRewrite(
3495 cir::EhTypeIdOp op, OpAdaptor adaptor,
3496 mlir::ConversionPatternRewriter &rewriter)
const {
3497 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
3498 rewriter, op.getLoc(),
3499 mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
3500 op.getTypeSymAttr());
3501 rewriter.replaceOpWithNewOp<mlir::LLVM::EhTypeidForOp>(
3502 op, rewriter.getI32Type(), addrOp);
3503 return mlir::success();
3506mlir::LogicalResult CIRToLLVMTrapOpLowering::matchAndRewrite(
3507 cir::TrapOp op, OpAdaptor adaptor,
3508 mlir::ConversionPatternRewriter &rewriter)
const {
3509 mlir::Location loc = op->getLoc();
3510 rewriter.eraseOp(op);
3512 mlir::LLVM::Trap::create(rewriter, loc);
3517 mlir::LLVM::UnreachableOp::create(rewriter, loc);
3519 return mlir::success();
3524 mlir::ConversionPatternRewriter &rewriter,
3525 const mlir::TypeConverter *converter,
3526 mlir::FlatSymbolRefAttr nameAttr, mlir::Type &eltType) {
3527 auto module = op->getParentOfType<mlir::ModuleOp>();
3528 mlir::Operation *symbol = mlir::SymbolTable::lookupSymbolIn(module, nameAttr);
3529 if (
auto llvmSymbol = mlir::dyn_cast<mlir::LLVM::GlobalOp>(symbol)) {
3530 eltType = llvmSymbol.getType();
3531 }
else if (
auto cirSymbol = mlir::dyn_cast<cir::GlobalOp>(symbol)) {
3532 eltType = converter->convertType(cirSymbol.getSymType());
3534 op->emitError() <<
"unexpected symbol type for " << symbol;
3538 return mlir::LLVM::AddressOfOp::create(
3539 rewriter, op->getLoc(),
3540 mlir::LLVM::LLVMPointerType::get(op->getContext()), nameAttr.getValue());
3543mlir::LogicalResult CIRToLLVMVTableAddrPointOpLowering::matchAndRewrite(
3544 cir::VTableAddrPointOp op, OpAdaptor adaptor,
3545 mlir::ConversionPatternRewriter &rewriter)
const {
3546 const mlir::TypeConverter *converter = getTypeConverter();
3547 mlir::Type targetType = converter->convertType(op.getType());
3551 op.getNameAttr(), eltType);
3553 return op.emitError() <<
"Unable to get value for vtable symbol";
3556 0, op.getAddressPointAttr().getIndex(),
3557 op.getAddressPointAttr().getOffset()};
3559 assert(eltType &&
"Shouldn't ever be missing an eltType here");
3560 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
3561 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
3562 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, targetType, eltType,
3563 symAddr, offsets, inboundsNuw);
3564 return mlir::success();
3567mlir::LogicalResult CIRToLLVMVTableGetVPtrOpLowering::matchAndRewrite(
3568 cir::VTableGetVPtrOp op, OpAdaptor adaptor,
3569 mlir::ConversionPatternRewriter &rewriter)
const {
3573 mlir::Value srcVal = adaptor.getSrc();
3574 rewriter.replaceOp(op, srcVal);
3575 return mlir::success();
3578mlir::LogicalResult CIRToLLVMVTableGetVirtualFnAddrOpLowering::matchAndRewrite(
3579 cir::VTableGetVirtualFnAddrOp op, OpAdaptor adaptor,
3580 mlir::ConversionPatternRewriter &rewriter)
const {
3581 mlir::Type targetType = getTypeConverter()->convertType(op.getType());
3582 auto eltType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3583 llvm::SmallVector<mlir::LLVM::GEPArg> offsets =
3584 llvm::SmallVector<mlir::LLVM::GEPArg>{op.getIndex()};
3585 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
3586 op, targetType, eltType, adaptor.getVptr(), offsets,
3587 mlir::LLVM::GEPNoWrapFlags::inbounds);
3588 return mlir::success();
3591mlir::LogicalResult CIRToLLVMVTTAddrPointOpLowering::matchAndRewrite(
3592 cir::VTTAddrPointOp op, OpAdaptor adaptor,
3593 mlir::ConversionPatternRewriter &rewriter)
const {
3594 const mlir::Type resultType = getTypeConverter()->convertType(op.getType());
3595 llvm::SmallVector<mlir::LLVM::GEPArg> offsets;
3597 mlir::Value llvmAddr = adaptor.getSymAddr();
3599 if (op.getSymAddr()) {
3600 if (op.getOffset() == 0) {
3601 rewriter.replaceOp(op, {llvmAddr});
3602 return mlir::success();
3605 offsets.push_back(adaptor.getOffset());
3606 eltType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3609 op.getNameAttr(), eltType);
3610 assert(eltType &&
"Shouldn't ever be missing an eltType here");
3611 offsets.push_back(0);
3612 offsets.push_back(adaptor.getOffset());
3614 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
3615 op, resultType, eltType, llvmAddr, offsets,
3616 mlir::LLVM::GEPNoWrapFlags::inbounds);
3617 return mlir::success();
3620mlir::LogicalResult CIRToLLVMStackSaveOpLowering::matchAndRewrite(
3621 cir::StackSaveOp op, OpAdaptor adaptor,
3622 mlir::ConversionPatternRewriter &rewriter)
const {
3623 const mlir::Type ptrTy = getTypeConverter()->convertType(op.getType());
3624 rewriter.replaceOpWithNewOp<mlir::LLVM::StackSaveOp>(op, ptrTy);
3625 return mlir::success();
3628mlir::LogicalResult CIRToLLVMStackRestoreOpLowering::matchAndRewrite(
3629 cir::StackRestoreOp op, OpAdaptor adaptor,
3630 mlir::ConversionPatternRewriter &rewriter)
const {
3631 rewriter.replaceOpWithNewOp<mlir::LLVM::StackRestoreOp>(op, adaptor.getPtr());
3632 return mlir::success();
3635mlir::LogicalResult CIRToLLVMVecCreateOpLowering::matchAndRewrite(
3636 cir::VecCreateOp op, OpAdaptor adaptor,
3637 mlir::ConversionPatternRewriter &rewriter)
const {
3640 const auto vecTy = mlir::cast<cir::VectorType>(op.getType());
3641 const mlir::Type llvmTy = typeConverter->convertType(vecTy);
3642 const mlir::Location loc = op.getLoc();
3643 mlir::Value result = mlir::LLVM::PoisonOp::create(rewriter, loc, llvmTy);
3644 assert(vecTy.getSize() == op.getElements().size() &&
3645 "cir.vec.create op count doesn't match vector type elements count");
3647 for (uint64_t i = 0; i < vecTy.getSize(); ++i) {
3648 const mlir::Value indexValue =
3649 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
3650 result = mlir::LLVM::InsertElementOp::create(
3651 rewriter, loc, result, adaptor.getElements()[i], indexValue);
3654 rewriter.replaceOp(op, result);
3655 return mlir::success();
3658mlir::LogicalResult CIRToLLVMVecExtractOpLowering::matchAndRewrite(
3659 cir::VecExtractOp op, OpAdaptor adaptor,
3660 mlir::ConversionPatternRewriter &rewriter)
const {
3661 rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractElementOp>(
3662 op, adaptor.getVec(), adaptor.getIndex());
3663 return mlir::success();
3666mlir::LogicalResult CIRToLLVMVecInsertOpLowering::matchAndRewrite(
3667 cir::VecInsertOp op, OpAdaptor adaptor,
3668 mlir::ConversionPatternRewriter &rewriter)
const {
3669 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertElementOp>(
3670 op, adaptor.getVec(), adaptor.getValue(), adaptor.getIndex());
3671 return mlir::success();
3674mlir::LogicalResult CIRToLLVMVecCmpOpLowering::matchAndRewrite(
3675 cir::VecCmpOp op, OpAdaptor adaptor,
3676 mlir::ConversionPatternRewriter &rewriter)
const {
3677 mlir::Type elementType = elementTypeIfVector(op.getLhs().getType());
3678 mlir::Value bitResult;
3679 if (
auto intType = mlir::dyn_cast<cir::IntType>(elementType)) {
3680 bitResult = mlir::LLVM::ICmpOp::create(
3681 rewriter, op.getLoc(),
3683 adaptor.getLhs(), adaptor.getRhs());
3684 }
else if (mlir::isa<cir::FPTypeInterface>(elementType)) {
3685 bitResult = mlir::LLVM::FCmpOp::create(
3687 adaptor.getLhs(), adaptor.getRhs());
3689 return op.emitError() <<
"unsupported type for VecCmpOp: " << elementType;
3695 if (cast<cir::IntType>(cast<cir::VectorType>(op.getType()).getElementType())
3697 rewriter.replaceOpWithNewOp<mlir::LLVM::SExtOp>(
3698 op, typeConverter->convertType(op.getType()), bitResult);
3700 rewriter.replaceOp(op, bitResult);
3701 return mlir::success();
3704mlir::LogicalResult CIRToLLVMVecSplatOpLowering::matchAndRewrite(
3705 cir::VecSplatOp op, OpAdaptor adaptor,
3706 mlir::ConversionPatternRewriter &rewriter)
const {
3712 cir::VectorType vecTy = op.getType();
3713 mlir::Type llvmTy = typeConverter->convertType(vecTy);
3714 mlir::Location loc = op.getLoc();
3715 mlir::Value poison = mlir::LLVM::PoisonOp::create(rewriter, loc, llvmTy);
3717 mlir::Value elementValue = adaptor.getValue();
3718 if (elementValue.getDefiningOp<mlir::LLVM::PoisonOp>()) {
3721 rewriter.replaceOp(op, poison);
3722 return mlir::success();
3725 if (
auto constValue = elementValue.getDefiningOp<mlir::LLVM::ConstantOp>()) {
3726 if (
auto intAttr = dyn_cast<mlir::IntegerAttr>(constValue.getValue())) {
3727 mlir::DenseIntElementsAttr denseVec = mlir::DenseIntElementsAttr::get(
3728 mlir::cast<mlir::ShapedType>(llvmTy), intAttr.getValue());
3729 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
3730 op, denseVec.getType(), denseVec);
3731 return mlir::success();
3734 if (
auto fpAttr = dyn_cast<mlir::FloatAttr>(constValue.getValue())) {
3735 mlir::DenseFPElementsAttr denseVec = mlir::DenseFPElementsAttr::get(
3736 mlir::cast<mlir::ShapedType>(llvmTy), fpAttr.getValue());
3737 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
3738 op, denseVec.getType(), denseVec);
3739 return mlir::success();
3743 mlir::Value indexValue =
3744 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), 0);
3745 mlir::Value oneElement = mlir::LLVM::InsertElementOp::create(
3746 rewriter, loc, poison, elementValue, indexValue);
3747 SmallVector<int32_t> zeroValues(vecTy.getSize(), 0);
3748 rewriter.replaceOpWithNewOp<mlir::LLVM::ShuffleVectorOp>(op, oneElement,
3749 poison, zeroValues);
3750 return mlir::success();
3753mlir::LogicalResult CIRToLLVMVecShuffleOpLowering::matchAndRewrite(
3754 cir::VecShuffleOp op, OpAdaptor adaptor,
3755 mlir::ConversionPatternRewriter &rewriter)
const {
3759 SmallVector<int, 8> indices;
3761 op.getIndices().begin(), op.getIndices().end(),
3762 std::back_inserter(indices), [](mlir::Attribute intAttr) {
3763 return mlir::cast<cir::IntAttr>(intAttr).getValue().getSExtValue();
3765 rewriter.replaceOpWithNewOp<mlir::LLVM::ShuffleVectorOp>(
3766 op, adaptor.getVec1(), adaptor.getVec2(), indices);
3767 return mlir::success();
3770mlir::LogicalResult CIRToLLVMVecShuffleDynamicOpLowering::matchAndRewrite(
3771 cir::VecShuffleDynamicOp op, OpAdaptor adaptor,
3772 mlir::ConversionPatternRewriter &rewriter)
const {
3784 mlir::Location loc = op.getLoc();
3785 mlir::Value input = adaptor.getVec();
3786 mlir::Type llvmIndexVecType =
3787 getTypeConverter()->convertType(op.getIndices().getType());
3788 mlir::Type llvmIndexType = getTypeConverter()->convertType(
3789 elementTypeIfVector(op.getIndices().getType()));
3791 mlir::cast<cir::VectorType>(op.getVec().getType()).getSize();
3793 uint64_t maskBits = llvm::NextPowerOf2(numElements - 1) - 1;
3794 mlir::Value maskValue = mlir::LLVM::ConstantOp::create(
3795 rewriter, loc, llvmIndexType,
3796 rewriter.getIntegerAttr(llvmIndexType, maskBits));
3797 mlir::Value maskVector =
3798 mlir::LLVM::UndefOp::create(rewriter, loc, llvmIndexVecType);
3800 for (uint64_t i = 0; i < numElements; ++i) {
3801 mlir::Value idxValue =
3802 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
3803 maskVector = mlir::LLVM::InsertElementOp::create(rewriter, loc, maskVector,
3804 maskValue, idxValue);
3807 mlir::Value maskedIndices = mlir::LLVM::AndOp::create(
3808 rewriter, loc, llvmIndexVecType, adaptor.getIndices(), maskVector);
3809 mlir::Value result = mlir::LLVM::UndefOp::create(
3810 rewriter, loc, getTypeConverter()->convertType(op.getVec().getType()));
3811 for (uint64_t i = 0; i < numElements; ++i) {
3812 mlir::Value iValue =
3813 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
3814 mlir::Value indexValue = mlir::LLVM::ExtractElementOp::create(
3815 rewriter, loc, maskedIndices, iValue);
3816 mlir::Value valueAtIndex =
3817 mlir::LLVM::ExtractElementOp::create(rewriter, loc, input, indexValue);
3818 result = mlir::LLVM::InsertElementOp::create(rewriter, loc, result,
3819 valueAtIndex, iValue);
3821 rewriter.replaceOp(op, result);
3822 return mlir::success();
3825mlir::LogicalResult CIRToLLVMVecTernaryOpLowering::matchAndRewrite(
3826 cir::VecTernaryOp op, OpAdaptor adaptor,
3827 mlir::ConversionPatternRewriter &rewriter)
const {
3829 mlir::Value bitVec = mlir::LLVM::ICmpOp::create(
3830 rewriter, op.getLoc(), mlir::LLVM::ICmpPredicate::ne, adaptor.getCond(),
3831 mlir::LLVM::ZeroOp::create(
3832 rewriter, op.getCond().getLoc(),
3833 typeConverter->convertType(op.getCond().getType())));
3834 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(
3835 op, bitVec, adaptor.getLhs(), adaptor.getRhs());
3836 return mlir::success();
3839mlir::LogicalResult CIRToLLVMComplexAddOpLowering::matchAndRewrite(
3840 cir::ComplexAddOp op, OpAdaptor adaptor,
3841 mlir::ConversionPatternRewriter &rewriter)
const {
3842 mlir::Value lhs = adaptor.getLhs();
3843 mlir::Value rhs = adaptor.getRhs();
3844 mlir::Location loc = op.getLoc();
3846 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
3847 mlir::Type complexElemTy =
3848 getTypeConverter()->convertType(
complexType.getElementType());
3849 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
3850 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{0}));
3851 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
3852 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{1}));
3853 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
3854 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{0}));
3855 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
3856 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{1}));
3858 mlir::Value newReal;
3859 mlir::Value newImag;
3860 if (complexElemTy.isInteger()) {
3861 newReal = mlir::LLVM::AddOp::create(rewriter, loc, complexElemTy, lhsReal,
3863 newImag = mlir::LLVM::AddOp::create(rewriter, loc, complexElemTy, lhsImag,
3868 newReal = mlir::LLVM::FAddOp::create(rewriter, loc, complexElemTy, lhsReal,
3870 newImag = mlir::LLVM::FAddOp::create(rewriter, loc, complexElemTy, lhsImag,
3874 mlir::Type complexLLVMTy =
3875 getTypeConverter()->convertType(op.getResult().getType());
3876 auto initialComplex =
3877 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), complexLLVMTy);
3879 auto realComplex = mlir::LLVM::InsertValueOp::create(
3880 rewriter, op->getLoc(), initialComplex, newReal, ArrayRef(int64_t{0}));
3882 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
3883 op, realComplex, newImag, ArrayRef(int64_t{1}));
3885 return mlir::success();
3888mlir::LogicalResult CIRToLLVMComplexCreateOpLowering::matchAndRewrite(
3889 cir::ComplexCreateOp op, OpAdaptor adaptor,
3890 mlir::ConversionPatternRewriter &rewriter)
const {
3891 mlir::Type complexLLVMTy =
3892 getTypeConverter()->convertType(op.getResult().getType());
3893 auto initialComplex =
3894 mlir::LLVM::UndefOp::create(rewriter, op->getLoc(), complexLLVMTy);
3896 auto realComplex = mlir::LLVM::InsertValueOp::create(
3897 rewriter, op->getLoc(), initialComplex, adaptor.getReal(),
3898 ArrayRef(int64_t{0}));
3900 auto complex = mlir::LLVM::InsertValueOp::create(
3901 rewriter, op->getLoc(), realComplex, adaptor.getImag(),
3902 ArrayRef(int64_t{1}));
3904 rewriter.replaceOp(op, complex);
3905 return mlir::success();
3908mlir::LogicalResult CIRToLLVMComplexRealOpLowering::matchAndRewrite(
3909 cir::ComplexRealOp op, OpAdaptor adaptor,
3910 mlir::ConversionPatternRewriter &rewriter)
const {
3911 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
3912 mlir::Value operand = adaptor.getOperand();
3913 if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) {
3914 operand = mlir::LLVM::ExtractValueOp::create(
3915 rewriter, op.getLoc(), resultLLVMTy, operand,
3916 llvm::ArrayRef<std::int64_t>{0});
3918 rewriter.replaceOp(op, operand);
3919 return mlir::success();
3922mlir::LogicalResult CIRToLLVMComplexSubOpLowering::matchAndRewrite(
3923 cir::ComplexSubOp op, OpAdaptor adaptor,
3924 mlir::ConversionPatternRewriter &rewriter)
const {
3925 mlir::Value lhs = adaptor.getLhs();
3926 mlir::Value rhs = adaptor.getRhs();
3927 mlir::Location loc = op.getLoc();
3929 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
3930 mlir::Type complexElemTy =
3931 getTypeConverter()->convertType(
complexType.getElementType());
3932 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
3933 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{0}));
3934 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
3935 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{1}));
3936 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
3937 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{0}));
3938 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
3939 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{1}));
3941 mlir::Value newReal;
3942 mlir::Value newImag;
3943 if (complexElemTy.isInteger()) {
3944 newReal = mlir::LLVM::SubOp::create(rewriter, loc, complexElemTy, lhsReal,
3946 newImag = mlir::LLVM::SubOp::create(rewriter, loc, complexElemTy, lhsImag,
3951 newReal = mlir::LLVM::FSubOp::create(rewriter, loc, complexElemTy, lhsReal,
3953 newImag = mlir::LLVM::FSubOp::create(rewriter, loc, complexElemTy, lhsImag,
3957 mlir::Type complexLLVMTy =
3958 getTypeConverter()->convertType(op.getResult().getType());
3959 auto initialComplex =
3960 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), complexLLVMTy);
3962 auto realComplex = mlir::LLVM::InsertValueOp::create(
3963 rewriter, op->getLoc(), initialComplex, newReal, ArrayRef(int64_t{0}));
3965 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
3966 op, realComplex, newImag, ArrayRef(int64_t{1}));
3968 return mlir::success();
3971mlir::LogicalResult CIRToLLVMComplexImagOpLowering::matchAndRewrite(
3972 cir::ComplexImagOp op, OpAdaptor adaptor,
3973 mlir::ConversionPatternRewriter &rewriter)
const {
3974 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
3975 mlir::Value operand = adaptor.getOperand();
3976 mlir::Location loc = op.getLoc();
3978 if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) {
3979 operand = mlir::LLVM::ExtractValueOp::create(
3980 rewriter, loc, resultLLVMTy, operand, llvm::ArrayRef<std::int64_t>{1});
3982 mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(resultLLVMTy);
3984 mlir::LLVM::ConstantOp::create(rewriter, loc, resultLLVMTy, zeroAttr);
3987 rewriter.replaceOp(op, operand);
3988 return mlir::success();
3992 mlir::MLIRContext *context,
3993 unsigned &storageSize) {
3994 return TypeSwitch<mlir::Type, mlir::IntegerType>(storageType)
3995 .Case<cir::ArrayType>([&](cir::ArrayType atTy) {
3996 storageSize = atTy.getSize() * 8;
3997 return mlir::IntegerType::get(context, storageSize);
3999 .Case<cir::IntType>([&](cir::IntType intTy) {
4000 storageSize = intTy.getWidth();
4001 return mlir::IntegerType::get(context, storageSize);
4003 .Default([](mlir::Type) -> mlir::IntegerType {
4005 "Either ArrayType or IntType expected for bitfields storage");
4009mlir::LogicalResult CIRToLLVMSetBitfieldOpLowering::matchAndRewrite(
4010 cir::SetBitfieldOp op, OpAdaptor adaptor,
4011 mlir::ConversionPatternRewriter &rewriter)
const {
4012 mlir::OpBuilder::InsertionGuard guard(rewriter);
4013 rewriter.setInsertionPoint(op);
4015 cir::BitfieldInfoAttr info = op.getBitfieldInfo();
4016 uint64_t size = info.getSize();
4017 uint64_t offset = info.getOffset();
4018 mlir::Type storageType = info.getStorageType();
4019 mlir::MLIRContext *context = storageType.getContext();
4021 unsigned storageSize = 0;
4023 mlir::IntegerType intType =
4026 mlir::Value srcVal =
createIntCast(rewriter, adaptor.getSrc(), intType);
4027 unsigned srcWidth = storageSize;
4028 mlir::Value resultVal = srcVal;
4030 if (storageSize != size) {
4031 assert(storageSize > size &&
"Invalid bitfield size.");
4033 mlir::Value val = mlir::LLVM::LoadOp::create(
4034 rewriter, op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(),
4035 op.getIsVolatile());
4038 createAnd(rewriter, srcVal, llvm::APInt::getLowBitsSet(srcWidth, size));
4040 srcVal =
createShL(rewriter, srcVal, offset);
4044 ~llvm::APInt::getBitsSet(srcWidth, offset, offset + size));
4047 srcVal = mlir::LLVM::OrOp::create(rewriter, op.getLoc(), val, srcVal);
4050 mlir::LLVM::StoreOp::create(rewriter, op.getLoc(), srcVal, adaptor.getAddr(),
4051 op.getAlignment(), op.getIsVolatile());
4053 mlir::Type resultTy = getTypeConverter()->convertType(op.getType());
4055 if (info.getIsSigned()) {
4056 assert(size <= storageSize);
4057 unsigned highBits = storageSize - size;
4060 resultVal =
createShL(rewriter, resultVal, highBits);
4061 resultVal =
createAShR(rewriter, resultVal, highBits);
4066 mlir::cast<mlir::IntegerType>(resultTy),
4067 info.getIsSigned());
4069 rewriter.replaceOp(op, resultVal);
4070 return mlir::success();
4073mlir::LogicalResult CIRToLLVMComplexImagPtrOpLowering::matchAndRewrite(
4074 cir::ComplexImagPtrOp op, OpAdaptor adaptor,
4075 mlir::ConversionPatternRewriter &rewriter)
const {
4076 cir::PointerType operandTy = op.getOperand().getType();
4077 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
4078 mlir::Type elementLLVMTy =
4079 getTypeConverter()->convertType(operandTy.getPointee());
4081 mlir::LLVM::GEPArg gepIndices[2] = {{0}, {1}};
4082 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
4083 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
4084 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
4085 op, resultLLVMTy, elementLLVMTy, adaptor.getOperand(), gepIndices,
4087 return mlir::success();
4090mlir::LogicalResult CIRToLLVMComplexRealPtrOpLowering::matchAndRewrite(
4091 cir::ComplexRealPtrOp op, OpAdaptor adaptor,
4092 mlir::ConversionPatternRewriter &rewriter)
const {
4093 cir::PointerType operandTy = op.getOperand().getType();
4094 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
4095 mlir::Type elementLLVMTy =
4096 getTypeConverter()->convertType(operandTy.getPointee());
4098 mlir::LLVM::GEPArg gepIndices[2] = {0, 0};
4099 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
4100 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
4101 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
4102 op, resultLLVMTy, elementLLVMTy, adaptor.getOperand(), gepIndices,
4104 return mlir::success();
4107mlir::LogicalResult CIRToLLVMGetBitfieldOpLowering::matchAndRewrite(
4108 cir::GetBitfieldOp op, OpAdaptor adaptor,
4109 mlir::ConversionPatternRewriter &rewriter)
const {
4111 mlir::OpBuilder::InsertionGuard guard(rewriter);
4112 rewriter.setInsertionPoint(op);
4114 cir::BitfieldInfoAttr info = op.getBitfieldInfo();
4116 uint64_t offset = info.getOffset();
4117 mlir::Type storageType = info.getStorageType();
4118 mlir::MLIRContext *context = storageType.getContext();
4119 unsigned storageSize = 0;
4121 mlir::IntegerType intType =
4124 mlir::Value val = mlir::LLVM::LoadOp::create(
4125 rewriter, op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(),
4126 op.getIsVolatile());
4127 val = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), intType, val);
4129 if (info.getIsSigned()) {
4130 assert(
static_cast<unsigned>(offset + size) <= storageSize);
4131 unsigned highBits = storageSize - offset - size;
4132 val =
createShL(rewriter, val, highBits);
4133 val =
createAShR(rewriter, val, offset + highBits);
4137 if (
static_cast<unsigned>(offset) + size < storageSize)
4139 llvm::APInt::getLowBitsSet(storageSize, size));
4142 mlir::Type resTy = getTypeConverter()->convertType(op.getType());
4144 rewriter, val, mlir::cast<mlir::IntegerType>(resTy), info.getIsSigned());
4145 rewriter.replaceOp(op, newOp);
4146 return mlir::success();
4149mlir::LogicalResult CIRToLLVMIsConstantOpLowering::matchAndRewrite(
4150 cir::IsConstantOp op, OpAdaptor adaptor,
4151 mlir::ConversionPatternRewriter &rewriter)
const {
4152 rewriter.replaceOpWithNewOp<mlir::LLVM::IsConstantOp>(op, adaptor.getVal());
4153 return mlir::success();
4156mlir::LogicalResult CIRToLLVMInlineAsmOpLowering::matchAndRewrite(
4157 cir::InlineAsmOp op, OpAdaptor adaptor,
4158 mlir::ConversionPatternRewriter &rewriter)
const {
4160 if (op.getNumResults())
4161 llResTy = getTypeConverter()->convertType(op.getType(0));
4163 cir::AsmFlavor dialect = op.getAsmFlavor();
4164 mlir::LLVM::AsmDialect llDialect = dialect == cir::AsmFlavor::x86_att
4165 ? mlir::LLVM::AsmDialect::AD_ATT
4166 : mlir::LLVM::AsmDialect::AD_Intel;
4168 SmallVector<mlir::Attribute> opAttrs;
4169 StringRef llvmAttrName = mlir::LLVM::InlineAsmOp::getElementTypeAttrName();
4175 if (!op.getNumResults())
4176 opAttrs.push_back(mlir::Attribute());
4178 SmallVector<mlir::Value> llvmOperands;
4179 SmallVector<mlir::Value> cirOperands;
4180 for (
auto const &[llvmOp, cirOp] :
4181 zip(adaptor.getAsmOperands(), op.getAsmOperands())) {
4182 append_range(llvmOperands, llvmOp);
4183 append_range(cirOperands, cirOp);
4188 for (
auto const &[cirOpAttr, cirOp] :
4189 zip(op.getOperandAttrs(), cirOperands)) {
4191 opAttrs.push_back(mlir::Attribute());
4195 llvm::SmallVector<mlir::NamedAttribute, 1> attrs;
4196 cir::PointerType typ = mlir::cast<cir::PointerType>(cirOp.getType());
4198 *getTypeConverter(), dataLayout, typ.getPointee()));
4200 attrs.push_back(rewriter.getNamedAttr(llvmAttrName, typAttr));
4201 mlir::DictionaryAttr newDict = rewriter.getDictionaryAttr(attrs);
4202 opAttrs.push_back(newDict);
4205 rewriter.replaceOpWithNewOp<mlir::LLVM::InlineAsmOp>(
4206 op, llResTy, llvmOperands, op.getAsmStringAttr(), op.getConstraintsAttr(),
4207 op.getSideEffectsAttr(),
4210 mlir::LLVM::TailCallKindAttr::get(
4211 getContext(), mlir::LLVM::tailcallkind::TailCallKind::None),
4212 mlir::LLVM::AsmDialectAttr::get(getContext(), llDialect),
4213 rewriter.getArrayAttr(opAttrs));
4215 return mlir::success();
4218mlir::LogicalResult CIRToLLVMVAStartOpLowering::matchAndRewrite(
4219 cir::VAStartOp op, OpAdaptor adaptor,
4220 mlir::ConversionPatternRewriter &rewriter)
const {
4221 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4222 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4223 adaptor.getArgList());
4224 rewriter.replaceOpWithNewOp<mlir::LLVM::VaStartOp>(op, vaList);
4225 return mlir::success();
4228mlir::LogicalResult CIRToLLVMVAEndOpLowering::matchAndRewrite(
4229 cir::VAEndOp op, OpAdaptor adaptor,
4230 mlir::ConversionPatternRewriter &rewriter)
const {
4231 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4232 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4233 adaptor.getArgList());
4234 rewriter.replaceOpWithNewOp<mlir::LLVM::VaEndOp>(op, vaList);
4235 return mlir::success();
4238mlir::LogicalResult CIRToLLVMVACopyOpLowering::matchAndRewrite(
4239 cir::VACopyOp op, OpAdaptor adaptor,
4240 mlir::ConversionPatternRewriter &rewriter)
const {
4241 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4242 auto dstList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4243 adaptor.getDstList());
4244 auto srcList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4245 adaptor.getSrcList());
4246 rewriter.replaceOpWithNewOp<mlir::LLVM::VaCopyOp>(op, dstList, srcList);
4247 return mlir::success();
4250mlir::LogicalResult CIRToLLVMVAArgOpLowering::matchAndRewrite(
4251 cir::VAArgOp op, OpAdaptor adaptor,
4252 mlir::ConversionPatternRewriter &rewriter)
const {
4254 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4255 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4256 adaptor.getArgList());
4258 mlir::Type llvmType =
4259 getTypeConverter()->convertType(op->getResultTypes().front());
4261 return mlir::failure();
4263 rewriter.replaceOpWithNewOp<mlir::LLVM::VaArgOp>(op, llvmType, vaList);
4264 return mlir::success();
4267mlir::LogicalResult CIRToLLVMBlockAddressOpLowering::matchAndRewrite(
4268 cir::BlockAddressOp op, OpAdaptor adaptor,
4269 mlir::ConversionPatternRewriter &rewriter)
const {
4270 return mlir::failure();
4273mlir::LogicalResult CIRToLLVMIndirectBrOpLowering::matchAndRewrite(
4274 cir::IndirectBrOp op, OpAdaptor adaptor,
4275 mlir::ConversionPatternRewriter &rewriter)
const {
4276 return mlir::failure();
4279mlir::LogicalResult CIRToLLVMAwaitOpLowering::matchAndRewrite(
4280 cir::AwaitOp op, OpAdaptor adaptor,
4281 mlir::ConversionPatternRewriter &rewriter)
const {
4282 return mlir::failure();
4286 return std::make_unique<ConvertCIRToLLVMPass>();
4294std::unique_ptr<llvm::Module>
4296 llvm::TimeTraceScope scope(
"lower from CIR to LLVM directly");
4298 mlir::MLIRContext *mlirCtx = mlirModule.getContext();
4300 mlir::PassManager pm(mlirCtx);
4303 (void)mlir::applyPassManagerCLOptions(pm);
4305 if (mlir::failed(pm.run(mlirModule))) {
4308 "The pass manager failed to lower CIR to LLVMIR dialect!");
4311 mlir::registerBuiltinDialectTranslation(*mlirCtx);
4312 mlir::registerLLVMDialectTranslation(*mlirCtx);
4315 llvm::TimeTraceScope translateScope(
"translateModuleToLLVMIR");
4317 StringRef moduleName = mlirModule.getName().value_or(
"CIRToLLVMModule");
4318 std::unique_ptr<llvm::Module> llvmModule =
4319 mlir::translateModuleToLLVMIR(mlirModule, llvmCtx, moduleName);
4323 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, cir::LowerModule *lowerMod)
mlir::Attribute visit(mlir::Attribute attr)
mlir::Attribute visitCirAttr(cir::FPAttr attr)
mlir::Attribute visitCirAttr(cir::BoolAttr attr)
GlobalInitAttrRewriter(mlir::Type type, mlir::ConversionPatternRewriter &rewriter)
mlir::Attribute visitCirAttr(cir::IntAttr attr)
std::unique_ptr< cir::LowerModule > prepareLowerModule(mlir::ModuleOp module)
void createLLVMFuncOpIfNotExist(mlir::ConversionPatternRewriter &rewriter, mlir::Operation *srcOp, llvm::StringRef fnName, mlir::Type fnTy)
static void collectUnreachable(mlir::Operation *parent, llvm::SmallVector< mlir::Operation * > &ops)
static mlir::LLVM::AtomicBinOp getLLVMAtomicBinOp(cir::AtomicFetchKind k, bool isInt, bool isSignedInt)
static mlir::LLVM::ICmpPredicate convertCmpKindToICmpPredicate(cir::CmpOpKind kind, bool isSigned)
Convert from a CIR comparison kind to an LLVM IR integral comparison kind.
mlir::Value lowerCirAttrAsValue(mlir::Operation *parentOp, const mlir::Attribute attr, mlir::ConversionPatternRewriter &rewriter, const mlir::TypeConverter *converter, cir::LowerModule *lowerMod)
Switches on the type of attribute and calls the appropriate conversion.
static mlir::Value getLLVMIntCast(mlir::ConversionPatternRewriter &rewriter, mlir::Value llvmSrc, mlir::Type llvmDstIntTy, bool isUnsigned, uint64_t cirSrcWidth, uint64_t cirDstIntWidth)
static std::optional< llvm::StringRef > getLLVMSyncScope(std::optional< cir::SyncScopeKind > syncScope)
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 void prepareTypeConverter(mlir::LLVMTypeConverter &converter, mlir::DataLayout &dataLayout, cir::LowerModule *lowerModule)
static mlir::LogicalResult rewriteCallOrInvoke(mlir::Operation *op, mlir::ValueRange callOperands, mlir::ConversionPatternRewriter &rewriter, const mlir::TypeConverter *converter, mlir::FlatSymbolRefAttr calleeAttr)
static mlir::LLVM::LLVMStructType getLLVMLandingPadStructTy(mlir::ConversionPatternRewriter &rewriter)
std::unique_ptr< llvm::Module > lowerDirectlyFromCIRToLLVMIR(mlir::ModuleOp mlirModule, llvm::LLVMContext &llvmCtx)
static llvm::StringLiteral getLLVMBinop(cir::AtomicFetchKind k, bool isInt)
static mlir::Value convertToIndexTy(mlir::ConversionPatternRewriter &rewriter, mlir::ModuleOp mod, mlir::Value index, mlir::Type baseTy, cir::IntType strideTy)
static mlir::LLVM::CallIntrinsicOp replaceOpWithCallLLVMIntrinsicOp(mlir::ConversionPatternRewriter &rewriter, mlir::Operation *op, const llvm::Twine &intrinsicName, mlir::Type resultTy, mlir::ValueRange operands)
static mlir::LLVM::AtomicOrdering getLLVMMemOrder(std::optional< cir::MemOrder > memorder)
std::unique_ptr< mlir::Pass > createConvertCIRToLLVMPass()
Create a pass that fully lowers CIR to the LLVMIR dialect.
static mlir::LLVM::FCmpPredicate convertCmpKindToFCmpPredicate(cir::CmpOpKind kind)
Convert from a CIR comparison kind to an LLVM IR floating-point comparison kind.
static mlir::LLVM::Visibility lowerCIRVisibilityToLLVMVisibility(cir::VisibilityKind visibilityKind)
static uint64_t getTypeSize(mlir::Type type, mlir::Operation &op)
void populateCIRToLLVMPasses(mlir::OpPassManager &pm)
Adds passes that fully lower CIR to the LLVMIR dialect.
mlir::LLVM::Linkage convertLinkage(cir::GlobalLinkageKind linkage)
static void buildCtorDtorList(mlir::ModuleOp module, StringRef globalXtorName, StringRef llvmXtorName, llvm::function_ref< std::pair< StringRef, int >(mlir::Attribute)> createXtor)
static mlir::Type convertTypeForMemory(const mlir::TypeConverter &converter, mlir::DataLayout const &dataLayout, mlir::Type type)
Given a type convertor and a data layout, convert the given type to a type that is suitable for memor...
static mlir::Value createIntCast(mlir::OpBuilder &bld, mlir::Value src, mlir::IntegerType dstTy, bool isSigned=false)
static mlir::Value getValueForVTableSymbol(mlir::Operation *op, mlir::ConversionPatternRewriter &rewriter, const mlir::TypeConverter *converter, mlir::FlatSymbolRefAttr nameAttr, mlir::Type &eltType)
static mlir::Value emitToMemory(mlir::ConversionPatternRewriter &rewriter, mlir::DataLayout const &dataLayout, mlir::Type origType, mlir::Value value)
Emits a value to memory with the expected scalar type.
static bool isIntTypeUnsigned(mlir::Type type)
std::unique_ptr< LowerModule > createLowerModule(mlir::ModuleOp module, mlir::PatternRewriter &rewriter)
const internal::VariadicAllOfMatcher< Attr > attr
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const AstTypeMatcher< ComplexType > complexType
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 sign(float)
Returns 1.0 if x > 0, -0.0 if x = -0.0, +0.0 if x = +0.0, or -1.0 if x < 0.
float __ovld __cnfn length(float)
Return the length of vector p, i.e., sqrt(p.x2 + p.y 2 + ...)
char __ovld __cnfn select(char, char, char)
For each component of a vector type, result[i] = if MSB of c[i] is set ?
static bool dataMemberType()
static bool addressSpace()
static bool globalViewIntLowering()
static bool opAllocaAnnotations()
static bool atomicScope()
static bool opLoadStoreTbaa()
static bool optInfoAttr()
static bool opFuncExtraAttrs()
static bool opCallLandingPad()
static bool vaArgABILowering()
static bool fpConstraints()
static bool intrinsicElementTypeSupport()
static bool lowerModeOptLevel()
static bool opCallCallConv()
static bool opFuncCallingConv()
static bool aggValueSlotVolatile()
static bool fastMathFlags()
static bool opCallContinueBlock()
static bool llvmLoweringPtrDiffConsidersPointee()
static bool opLoadStoreNontemporal()
static bool makeTripleAlwaysPresent()
static bool atomicSyncScopeID()
static bool opFuncMultipleReturnVals()
void runOnOperation() final
StringRef getDescription() const override
StringRef getArgument() const override
void getDependentDialects(mlir::DialectRegistry ®istry) const override
void processCIRAttrs(mlir::ModuleOp module)