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 rewriter.replaceOp(op, res);
1056 return mlir::LogicalResult::success();
1059mlir::LogicalResult CIRToLLVMBitClzOpLowering::matchAndRewrite(
1060 cir::BitClzOp op, OpAdaptor adaptor,
1061 mlir::ConversionPatternRewriter &rewriter)
const {
1062 auto resTy = getTypeConverter()->convertType(op.getType());
1063 auto llvmOp = mlir::LLVM::CountLeadingZerosOp::create(
1064 rewriter, op.getLoc(), resTy, adaptor.getInput(), op.getPoisonZero());
1065 rewriter.replaceOp(op, llvmOp);
1066 return mlir::LogicalResult::success();
1069mlir::LogicalResult CIRToLLVMBitCtzOpLowering::matchAndRewrite(
1070 cir::BitCtzOp op, OpAdaptor adaptor,
1071 mlir::ConversionPatternRewriter &rewriter)
const {
1072 auto resTy = getTypeConverter()->convertType(op.getType());
1073 auto llvmOp = mlir::LLVM::CountTrailingZerosOp::create(
1074 rewriter, op.getLoc(), resTy, adaptor.getInput(), op.getPoisonZero());
1075 rewriter.replaceOp(op, llvmOp);
1076 return mlir::LogicalResult::success();
1079mlir::LogicalResult CIRToLLVMBitFfsOpLowering::matchAndRewrite(
1080 cir::BitFfsOp op, OpAdaptor adaptor,
1081 mlir::ConversionPatternRewriter &rewriter)
const {
1082 auto resTy = getTypeConverter()->convertType(op.getType());
1083 auto ctz = mlir::LLVM::CountTrailingZerosOp::create(rewriter, op.getLoc(),
1084 resTy, adaptor.getInput(),
1087 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1088 auto ctzAddOne = mlir::LLVM::AddOp::create(rewriter, op.getLoc(),
ctz, one);
1090 auto zeroInputTy = mlir::LLVM::ConstantOp::create(
1091 rewriter, op.getLoc(), adaptor.getInput().getType(), 0);
1092 auto isZero = mlir::LLVM::ICmpOp::create(
1093 rewriter, op.getLoc(),
1094 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(),
1095 mlir::LLVM::ICmpPredicate::eq),
1096 adaptor.getInput(), zeroInputTy);
1098 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 0);
1099 auto res = mlir::LLVM::SelectOp::create(rewriter, op.getLoc(), isZero, zero,
1101 rewriter.replaceOp(op, res);
1103 return mlir::LogicalResult::success();
1106mlir::LogicalResult CIRToLLVMBitParityOpLowering::matchAndRewrite(
1107 cir::BitParityOp op, OpAdaptor adaptor,
1108 mlir::ConversionPatternRewriter &rewriter)
const {
1109 auto resTy = getTypeConverter()->convertType(op.getType());
1110 auto popcnt = mlir::LLVM::CtPopOp::create(rewriter, op.getLoc(), resTy,
1111 adaptor.getInput());
1113 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1115 mlir::LLVM::AndOp::create(rewriter, op.getLoc(), popcnt, one);
1116 rewriter.replaceOp(op, popcntMod2);
1118 return mlir::LogicalResult::success();
1121mlir::LogicalResult CIRToLLVMBitPopcountOpLowering::matchAndRewrite(
1122 cir::BitPopcountOp op, OpAdaptor adaptor,
1123 mlir::ConversionPatternRewriter &rewriter)
const {
1124 auto resTy = getTypeConverter()->convertType(op.getType());
1125 auto llvmOp = mlir::LLVM::CtPopOp::create(rewriter, op.getLoc(), resTy,
1126 adaptor.getInput());
1127 rewriter.replaceOp(op, llvmOp);
1128 return mlir::LogicalResult::success();
1131mlir::LogicalResult CIRToLLVMBitReverseOpLowering::matchAndRewrite(
1132 cir::BitReverseOp op, OpAdaptor adaptor,
1133 mlir::ConversionPatternRewriter &rewriter)
const {
1134 rewriter.replaceOpWithNewOp<mlir::LLVM::BitReverseOp>(op, adaptor.getInput());
1135 return mlir::success();
1138mlir::LogicalResult CIRToLLVMBrCondOpLowering::matchAndRewrite(
1139 cir::BrCondOp brOp, OpAdaptor adaptor,
1140 mlir::ConversionPatternRewriter &rewriter)
const {
1145 mlir::Value i1Condition = adaptor.getCond();
1147 rewriter.replaceOpWithNewOp<mlir::LLVM::CondBrOp>(
1148 brOp, i1Condition, brOp.getDestTrue(), adaptor.getDestOperandsTrue(),
1149 brOp.getDestFalse(), adaptor.getDestOperandsFalse());
1151 return mlir::success();
1154mlir::LogicalResult CIRToLLVMByteSwapOpLowering::matchAndRewrite(
1155 cir::ByteSwapOp op, OpAdaptor adaptor,
1156 mlir::ConversionPatternRewriter &rewriter)
const {
1157 rewriter.replaceOpWithNewOp<mlir::LLVM::ByteSwapOp>(op, adaptor.getInput());
1158 return mlir::LogicalResult::success();
1161mlir::Type CIRToLLVMCastOpLowering::convertTy(mlir::Type ty)
const {
1162 return getTypeConverter()->convertType(ty);
1165mlir::LogicalResult CIRToLLVMCastOpLowering::matchAndRewrite(
1166 cir::CastOp castOp, OpAdaptor adaptor,
1167 mlir::ConversionPatternRewriter &rewriter)
const {
1172 switch (castOp.getKind()) {
1173 case cir::CastKind::array_to_ptrdecay: {
1174 const auto ptrTy = mlir::cast<cir::PointerType>(castOp.getType());
1175 mlir::Value sourceValue = adaptor.getSrc();
1176 mlir::Type targetType = convertTy(ptrTy);
1178 ptrTy.getPointee());
1179 llvm::SmallVector<mlir::LLVM::GEPArg> offset{0};
1180 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1181 castOp, targetType, elementTy, sourceValue, offset);
1184 case cir::CastKind::int_to_bool: {
1185 mlir::Value llvmSrcVal = adaptor.getSrc();
1186 mlir::Value zeroInt = mlir::LLVM::ConstantOp::create(
1187 rewriter, castOp.getLoc(), llvmSrcVal.getType(), 0);
1188 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
1189 castOp, mlir::LLVM::ICmpPredicate::ne, llvmSrcVal, zeroInt);
1192 case cir::CastKind::integral: {
1193 mlir::Type srcType = castOp.getSrc().getType();
1194 mlir::Type dstType = castOp.getType();
1195 mlir::Value llvmSrcVal = adaptor.getSrc();
1196 mlir::Type llvmDstType = getTypeConverter()->convertType(dstType);
1197 cir::IntType srcIntType =
1198 mlir::cast<cir::IntType>(elementTypeIfVector(srcType));
1199 cir::IntType dstIntType =
1200 mlir::cast<cir::IntType>(elementTypeIfVector(dstType));
1201 rewriter.replaceOp(castOp,
getLLVMIntCast(rewriter, llvmSrcVal, llvmDstType,
1202 srcIntType.isUnsigned(),
1203 srcIntType.getWidth(),
1204 dstIntType.getWidth()));
1207 case cir::CastKind::floating: {
1208 mlir::Value llvmSrcVal = adaptor.getSrc();
1209 mlir::Type llvmDstTy = getTypeConverter()->convertType(castOp.getType());
1211 mlir::Type srcTy = elementTypeIfVector(castOp.getSrc().getType());
1212 mlir::Type dstTy = elementTypeIfVector(castOp.getType());
1214 if (!mlir::isa<cir::FPTypeInterface>(dstTy) ||
1215 !mlir::isa<cir::FPTypeInterface>(srcTy))
1216 return castOp.emitError() <<
"NYI cast from " << srcTy <<
" to " << dstTy;
1218 auto getFloatWidth = [](mlir::Type ty) ->
unsigned {
1219 return mlir::cast<cir::FPTypeInterface>(ty).getWidth();
1222 if (getFloatWidth(srcTy) > getFloatWidth(dstTy))
1223 rewriter.replaceOpWithNewOp<mlir::LLVM::FPTruncOp>(castOp, llvmDstTy,
1226 rewriter.replaceOpWithNewOp<mlir::LLVM::FPExtOp>(castOp, llvmDstTy,
1228 return mlir::success();
1230 case cir::CastKind::int_to_ptr: {
1231 auto dstTy = mlir::cast<cir::PointerType>(castOp.getType());
1232 mlir::Value llvmSrcVal = adaptor.getSrc();
1233 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1234 rewriter.replaceOpWithNewOp<mlir::LLVM::IntToPtrOp>(castOp, llvmDstTy,
1236 return mlir::success();
1238 case cir::CastKind::ptr_to_int: {
1239 auto dstTy = mlir::cast<cir::IntType>(castOp.getType());
1240 mlir::Value llvmSrcVal = adaptor.getSrc();
1241 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1242 rewriter.replaceOpWithNewOp<mlir::LLVM::PtrToIntOp>(castOp, llvmDstTy,
1244 return mlir::success();
1246 case cir::CastKind::float_to_bool: {
1247 mlir::Value llvmSrcVal = adaptor.getSrc();
1248 auto kind = mlir::LLVM::FCmpPredicate::une;
1251 auto zeroFloat = mlir::LLVM::ConstantOp::create(
1252 rewriter, castOp.getLoc(), llvmSrcVal.getType(),
1253 mlir::FloatAttr::get(llvmSrcVal.getType(), 0.0));
1256 rewriter.replaceOpWithNewOp<mlir::LLVM::FCmpOp>(castOp,
kind, llvmSrcVal,
1259 return mlir::success();
1261 case cir::CastKind::bool_to_int: {
1262 auto dstTy = mlir::cast<cir::IntType>(castOp.getType());
1263 mlir::Value llvmSrcVal = adaptor.getSrc();
1264 auto llvmSrcTy = mlir::cast<mlir::IntegerType>(llvmSrcVal.getType());
1266 mlir::cast<mlir::IntegerType>(getTypeConverter()->convertType(dstTy));
1267 if (llvmSrcTy.getWidth() == llvmDstTy.getWidth())
1268 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(castOp, llvmDstTy,
1271 rewriter.replaceOpWithNewOp<mlir::LLVM::ZExtOp>(castOp, llvmDstTy,
1273 return mlir::success();
1275 case cir::CastKind::bool_to_float: {
1276 mlir::Type dstTy = castOp.getType();
1277 mlir::Value llvmSrcVal = adaptor.getSrc();
1278 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1279 rewriter.replaceOpWithNewOp<mlir::LLVM::UIToFPOp>(castOp, llvmDstTy,
1281 return mlir::success();
1283 case cir::CastKind::int_to_float: {
1284 mlir::Type dstTy = castOp.getType();
1285 mlir::Value llvmSrcVal = adaptor.getSrc();
1286 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1287 if (mlir::cast<cir::IntType>(elementTypeIfVector(castOp.getSrc().getType()))
1289 rewriter.replaceOpWithNewOp<mlir::LLVM::SIToFPOp>(castOp, llvmDstTy,
1292 rewriter.replaceOpWithNewOp<mlir::LLVM::UIToFPOp>(castOp, llvmDstTy,
1294 return mlir::success();
1296 case cir::CastKind::float_to_int: {
1297 mlir::Type dstTy = castOp.getType();
1298 mlir::Value llvmSrcVal = adaptor.getSrc();
1299 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1300 if (mlir::cast<cir::IntType>(elementTypeIfVector(castOp.getType()))
1302 rewriter.replaceOpWithNewOp<mlir::LLVM::FPToSIOp>(castOp, llvmDstTy,
1305 rewriter.replaceOpWithNewOp<mlir::LLVM::FPToUIOp>(castOp, llvmDstTy,
1307 return mlir::success();
1309 case cir::CastKind::bitcast: {
1310 mlir::Type dstTy = castOp.getType();
1311 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1316 mlir::Value llvmSrcVal = adaptor.getSrc();
1317 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(castOp, llvmDstTy,
1319 return mlir::success();
1321 case cir::CastKind::ptr_to_bool: {
1322 mlir::Value llvmSrcVal = adaptor.getSrc();
1323 mlir::Value zeroPtr = mlir::LLVM::ZeroOp::create(rewriter, castOp.getLoc(),
1324 llvmSrcVal.getType());
1325 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
1326 castOp, mlir::LLVM::ICmpPredicate::ne, llvmSrcVal, zeroPtr);
1329 case cir::CastKind::address_space: {
1330 mlir::Type dstTy = castOp.getType();
1331 mlir::Value llvmSrcVal = adaptor.getSrc();
1332 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1333 rewriter.replaceOpWithNewOp<mlir::LLVM::AddrSpaceCastOp>(castOp, llvmDstTy,
1337 case cir::CastKind::member_ptr_to_bool:
1342 return castOp.emitError(
"Unhandled cast kind: ")
1343 << castOp.getKindAttrName();
1347 return mlir::success();
1351 mlir::ModuleOp mod, mlir::Value index,
1352 mlir::Type baseTy, cir::IntType strideTy) {
1353 mlir::Operation *indexOp = index.getDefiningOp();
1357 auto indexType = mlir::cast<mlir::IntegerType>(index.getType());
1358 mlir::DataLayout llvmLayout(mod);
1359 std::optional<uint64_t> layoutWidth = llvmLayout.getTypeIndexBitwidth(baseTy);
1362 if (!layoutWidth || *layoutWidth == indexType.getWidth())
1368 auto sub = dyn_cast<mlir::LLVM::SubOp>(indexOp);
1369 bool rewriteSub =
false;
1372 dyn_cast<mlir::LLVM::ConstantOp>(sub.getLhs().getDefiningOp())) {
1373 auto lhsConstInt = mlir::dyn_cast<mlir::IntegerAttr>(lhsConst.getValue());
1374 if (lhsConstInt && lhsConstInt.getValue() == 0) {
1375 index = sub.getRhs();
1381 auto llvmDstType = rewriter.getIntegerType(*layoutWidth);
1382 bool isUnsigned = strideTy && strideTy.isUnsigned();
1384 indexType.getWidth(), *layoutWidth);
1387 index = mlir::LLVM::SubOp::create(
1388 rewriter, index.getLoc(),
1389 mlir::LLVM::ConstantOp::create(rewriter, index.getLoc(),
1390 index.getType(), 0),
1393 rewriter.eraseOp(sub);
1399mlir::LogicalResult CIRToLLVMPtrStrideOpLowering::matchAndRewrite(
1400 cir::PtrStrideOp ptrStrideOp, OpAdaptor adaptor,
1401 mlir::ConversionPatternRewriter &rewriter)
const {
1403 const mlir::TypeConverter *tc = getTypeConverter();
1404 const mlir::Type resultTy = tc->convertType(ptrStrideOp.getType());
1406 mlir::Type elementTy =
1411 if (mlir::isa<mlir::LLVM::LLVMVoidType>(elementTy) ||
1412 mlir::isa<mlir::LLVM::LLVMFunctionType>(elementTy))
1413 elementTy = mlir::IntegerType::get(elementTy.getContext(), 8,
1414 mlir::IntegerType::Signless);
1416 mlir::Value index = adaptor.getStride();
1418 rewriter, ptrStrideOp->getParentOfType<mlir::ModuleOp>(), index,
1419 adaptor.getBase().getType(),
1420 dyn_cast<cir::IntType>(ptrStrideOp.getOperand(1).getType()));
1422 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1423 ptrStrideOp, resultTy, elementTy, adaptor.getBase(), index);
1424 return mlir::success();
1427mlir::LogicalResult CIRToLLVMGetElementOpLowering::matchAndRewrite(
1428 cir::GetElementOp op, OpAdaptor adaptor,
1429 mlir::ConversionPatternRewriter &rewriter)
const {
1431 mlir::dyn_cast<cir::ArrayType>(op.getBaseType().getPointee())) {
1432 const mlir::TypeConverter *converter = getTypeConverter();
1433 const mlir::Type llArrayTy = converter->convertType(arrayTy);
1434 const mlir::Type llResultTy = converter->convertType(op.getType());
1435 mlir::Type elementTy =
1440 if (mlir::isa<mlir::LLVM::LLVMVoidType>(elementTy) ||
1441 mlir::isa<mlir::LLVM::LLVMFunctionType>(elementTy))
1442 elementTy = rewriter.getIntegerType(8);
1444 mlir::Value index = adaptor.getIndex();
1447 adaptor.getBase().getType(),
1448 dyn_cast<cir::IntType>(op.getOperand(1).getType()));
1453 std::array<mlir::LLVM::GEPArg, 2> offset{0, index};
1454 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, llResultTy, llArrayTy,
1455 adaptor.getBase(), offset);
1456 return mlir::success();
1459 op.emitError() <<
"NYI: GetElementOp lowering to LLVM for non-array";
1460 return mlir::failure();
1463mlir::LogicalResult CIRToLLVMBaseClassAddrOpLowering::matchAndRewrite(
1464 cir::BaseClassAddrOp baseClassOp, OpAdaptor adaptor,
1465 mlir::ConversionPatternRewriter &rewriter)
const {
1466 const mlir::Type resultType =
1467 getTypeConverter()->convertType(baseClassOp.getType());
1468 mlir::Value derivedAddr = adaptor.getDerivedAddr();
1469 llvm::SmallVector<mlir::LLVM::GEPArg, 1> offset = {
1470 adaptor.getOffset().getZExtValue()};
1471 mlir::Type byteType = mlir::IntegerType::get(resultType.getContext(), 8,
1472 mlir::IntegerType::Signless);
1473 if (adaptor.getOffset().getZExtValue() == 0) {
1474 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(
1475 baseClassOp, resultType, adaptor.getDerivedAddr());
1476 return mlir::success();
1479 if (baseClassOp.getAssumeNotNull()) {
1480 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1481 baseClassOp, resultType, byteType, derivedAddr, offset);
1483 auto loc = baseClassOp.getLoc();
1484 mlir::Value isNull = mlir::LLVM::ICmpOp::create(
1485 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, derivedAddr,
1486 mlir::LLVM::ZeroOp::create(rewriter, loc, derivedAddr.getType()));
1487 mlir::Value adjusted = mlir::LLVM::GEPOp::create(
1488 rewriter, loc, resultType, byteType, derivedAddr, offset);
1489 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(baseClassOp, isNull,
1490 derivedAddr, adjusted);
1492 return mlir::success();
1495mlir::LogicalResult CIRToLLVMDerivedClassAddrOpLowering::matchAndRewrite(
1496 cir::DerivedClassAddrOp derivedClassOp, OpAdaptor adaptor,
1497 mlir::ConversionPatternRewriter &rewriter)
const {
1498 const mlir::Type resultType =
1499 getTypeConverter()->convertType(derivedClassOp.getType());
1500 mlir::Value baseAddr = adaptor.getBaseAddr();
1503 int64_t offsetVal = -(adaptor.getOffset().getZExtValue());
1504 if (offsetVal == 0) {
1506 rewriter.replaceOp(derivedClassOp, baseAddr);
1507 return mlir::success();
1509 llvm::SmallVector<mlir::LLVM::GEPArg, 1> offset = {offsetVal};
1510 mlir::Type byteType = mlir::IntegerType::get(resultType.getContext(), 8,
1511 mlir::IntegerType::Signless);
1512 if (derivedClassOp.getAssumeNotNull()) {
1513 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1514 derivedClassOp, resultType, byteType, baseAddr, offset,
1515 mlir::LLVM::GEPNoWrapFlags::inbounds);
1517 mlir::Location loc = derivedClassOp.getLoc();
1518 mlir::Value isNull = mlir::LLVM::ICmpOp::create(
1519 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, baseAddr,
1520 mlir::LLVM::ZeroOp::create(rewriter, loc, baseAddr.getType()));
1521 mlir::Value adjusted =
1522 mlir::LLVM::GEPOp::create(rewriter, loc, resultType, byteType, baseAddr,
1523 offset, mlir::LLVM::GEPNoWrapFlags::inbounds);
1524 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(derivedClassOp, isNull,
1525 baseAddr, adjusted);
1527 return mlir::success();
1530mlir::LogicalResult CIRToLLVMATanOpLowering::matchAndRewrite(
1531 cir::ATanOp op, OpAdaptor adaptor,
1532 mlir::ConversionPatternRewriter &rewriter)
const {
1533 mlir::Type resTy = typeConverter->convertType(op.getType());
1534 rewriter.replaceOpWithNewOp<mlir::LLVM::ATanOp>(op, resTy, adaptor.getSrc());
1535 return mlir::success();
1538mlir::LogicalResult CIRToLLVMCeilOpLowering::matchAndRewrite(
1539 cir::CeilOp op, OpAdaptor adaptor,
1540 mlir::ConversionPatternRewriter &rewriter)
const {
1541 mlir::Type resTy = typeConverter->convertType(op.getType());
1542 rewriter.replaceOpWithNewOp<mlir::LLVM::FCeilOp>(op, resTy, adaptor.getSrc());
1543 return mlir::success();
1546mlir::LogicalResult CIRToLLVMAllocaOpLowering::matchAndRewrite(
1547 cir::AllocaOp op, OpAdaptor adaptor,
1548 mlir::ConversionPatternRewriter &rewriter)
const {
1551 ? adaptor.getDynAllocSize()
1552 : mlir::LLVM::ConstantOp::create(
1553 rewriter, op.getLoc(),
1554 typeConverter->convertType(rewriter.getIndexType()), 1);
1555 mlir::Type elementTy =
1557 mlir::Type resultTy =
1563 rewriter.replaceOpWithNewOp<mlir::LLVM::AllocaOp>(
1564 op, resultTy, elementTy, size, op.getAlignmentAttr().getInt());
1566 return mlir::success();
1569mlir::LogicalResult CIRToLLVMReturnOpLowering::matchAndRewrite(
1570 cir::ReturnOp op, OpAdaptor adaptor,
1571 mlir::ConversionPatternRewriter &rewriter)
const {
1572 rewriter.replaceOpWithNewOp<mlir::LLVM::ReturnOp>(op, adaptor.getOperands());
1573 return mlir::LogicalResult::success();
1576mlir::LogicalResult CIRToLLVMRotateOpLowering::matchAndRewrite(
1577 cir::RotateOp op, OpAdaptor adaptor,
1578 mlir::ConversionPatternRewriter &rewriter)
const {
1581 mlir::Value input = adaptor.getInput();
1582 if (op.isRotateLeft())
1583 rewriter.replaceOpWithNewOp<mlir::LLVM::FshlOp>(op, input, input,
1584 adaptor.getAmount());
1586 rewriter.replaceOpWithNewOp<mlir::LLVM::FshrOp>(op, input, input,
1587 adaptor.getAmount());
1588 return mlir::LogicalResult::success();
1591static mlir::LogicalResult
1593 mlir::ConversionPatternRewriter &rewriter,
1594 const mlir::TypeConverter *converter,
1595 mlir::FlatSymbolRefAttr calleeAttr) {
1597 mlir::ValueTypeRange<mlir::ResultRange> cirResults = op->getResultTypes();
1598 auto call = cast<cir::CIRCallOpInterface>(op);
1600 if (converter->convertTypes(cirResults, llvmResults).failed())
1601 return mlir::failure();
1605 mlir::LLVM::MemoryEffectsAttr memoryEffects;
1606 bool noUnwind =
false;
1607 bool willReturn =
false;
1609 memoryEffects, noUnwind, willReturn);
1611 mlir::LLVM::LLVMFunctionType llvmFnTy;
1618 mlir::Operation *callee =
1619 mlir::SymbolTable::lookupNearestSymbolFrom(op, calleeAttr);
1620 if (
auto fn = mlir::dyn_cast<mlir::FunctionOpInterface>(callee)) {
1621 llvmFnTy = converter->convertType<mlir::LLVM::LLVMFunctionType>(
1622 fn.getFunctionType());
1623 assert(llvmFnTy &&
"Failed to convert function type");
1624 }
else if (
auto alias = mlir::cast<mlir::LLVM::AliasOp>(callee)) {
1632 auto symAttr = mlir::cast<mlir::FlatSymbolRefAttr>(calleeAttr);
1634 mlir::LLVM::AddressOfOp::create(
1635 rewriter, op->getLoc(),
1636 mlir::LLVM::LLVMPointerType::get(rewriter.getContext()), symAttr)
1638 adjustedCallOperands.push_back(addrOfAlias);
1641 llvm::append_range(adjustedCallOperands, callOperands);
1642 callOperands = adjustedCallOperands;
1646 llvmFnTy = mlir::cast<mlir::LLVM::LLVMFunctionType>(alias.getType());
1649 return op->emitError(
"Unexpected callee type!");
1652 assert(!op->getOperands().empty() &&
1653 "operands list must no be empty for the indirect call");
1654 auto calleeTy = op->getOperands().front().getType();
1655 auto calleePtrTy = cast<cir::PointerType>(calleeTy);
1656 auto calleeFuncTy = cast<cir::FuncType>(calleePtrTy.getPointee());
1657 llvm::append_range(adjustedCallOperands, callOperands);
1658 llvmFnTy = cast<mlir::LLVM::LLVMFunctionType>(
1659 converter->convertType(calleeFuncTy));
1666 auto newOp = rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(
1667 op, llvmFnTy, calleeAttr, callOperands);
1669 newOp.setMemoryEffectsAttr(memoryEffects);
1670 newOp.setNoUnwind(noUnwind);
1671 newOp.setWillReturn(willReturn);
1673 return mlir::success();
1676mlir::LogicalResult CIRToLLVMCallOpLowering::matchAndRewrite(
1677 cir::CallOp op, OpAdaptor adaptor,
1678 mlir::ConversionPatternRewriter &rewriter)
const {
1680 getTypeConverter(), op.getCalleeAttr());
1683mlir::LogicalResult CIRToLLVMReturnAddrOpLowering::matchAndRewrite(
1684 cir::ReturnAddrOp op, OpAdaptor adaptor,
1685 mlir::ConversionPatternRewriter &rewriter)
const {
1686 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
1688 llvmPtrTy, adaptor.getOperands());
1689 return mlir::success();
1692mlir::LogicalResult CIRToLLVMFrameAddrOpLowering::matchAndRewrite(
1693 cir::FrameAddrOp op, OpAdaptor adaptor,
1694 mlir::ConversionPatternRewriter &rewriter)
const {
1695 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
1697 adaptor.getOperands());
1698 return mlir::success();
1701mlir::LogicalResult CIRToLLVMAddrOfReturnAddrOpLowering::matchAndRewrite(
1702 cir::AddrOfReturnAddrOp op, OpAdaptor adaptor,
1703 mlir::ConversionPatternRewriter &rewriter)
const {
1704 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
1706 llvmPtrTy, adaptor.getOperands());
1707 return mlir::success();
1710mlir::LogicalResult CIRToLLVMLoadOpLowering::matchAndRewrite(
1711 cir::LoadOp op, OpAdaptor adaptor,
1712 mlir::ConversionPatternRewriter &rewriter)
const {
1713 const mlir::Type llvmTy =
1715 mlir::LLVM::AtomicOrdering ordering =
getLLVMMemOrder(op.getMemOrder());
1716 std::optional<size_t> opAlign = op.getAlignment();
1717 unsigned alignment =
1718 (unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmTy));
1724 std::optional<llvm::StringRef> syncScope =
1726 mlir::LLVM::LoadOp newLoad = mlir::LLVM::LoadOp::create(
1727 rewriter, op->getLoc(), llvmTy, adaptor.getAddr(), alignment,
1728 op.getIsVolatile(),
false,
1729 false,
false, ordering,
1730 syncScope.value_or(llvm::StringRef()));
1733 mlir::Value result =
1735 rewriter.replaceOp(op, result);
1737 return mlir::LogicalResult::success();
1740mlir::LogicalResult CIRToLLVMStoreOpLowering::matchAndRewrite(
1741 cir::StoreOp op, OpAdaptor adaptor,
1742 mlir::ConversionPatternRewriter &rewriter)
const {
1743 mlir::LLVM::AtomicOrdering memorder =
getLLVMMemOrder(op.getMemOrder());
1744 const mlir::Type llvmTy =
1745 getTypeConverter()->convertType(op.getValue().getType());
1746 std::optional<size_t> opAlign = op.getAlignment();
1747 unsigned alignment =
1748 (unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmTy));
1754 op.getValue().getType(), adaptor.getValue());
1758 std::optional<llvm::StringRef> syncScope =
1760 mlir::LLVM::StoreOp storeOp = mlir::LLVM::StoreOp::create(
1761 rewriter, op->getLoc(), value, adaptor.getAddr(), alignment,
1763 false,
false, memorder,
1764 syncScope.value_or(llvm::StringRef()));
1765 rewriter.replaceOp(op, storeOp);
1767 return mlir::LogicalResult::success();
1771 auto array = mlir::dyn_cast<mlir::ArrayAttr>(attr.getElts());
1772 return attr.hasTrailingZeros() ||
1773 (array && std::count_if(array.begin(), array.end(), [](
auto elt) {
1774 auto ar = dyn_cast<cir::ConstArrayAttr>(elt);
1775 return ar && hasTrailingZeros(ar);
1779mlir::LogicalResult CIRToLLVMConstantOpLowering::matchAndRewrite(
1780 cir::ConstantOp op, OpAdaptor adaptor,
1781 mlir::ConversionPatternRewriter &rewriter)
const {
1782 mlir::Attribute attr = op.getValue();
1784 if (mlir::isa<cir::PoisonAttr>(attr)) {
1785 rewriter.replaceOpWithNewOp<mlir::LLVM::PoisonOp>(
1786 op, getTypeConverter()->convertType(op.getType()));
1787 return mlir::success();
1790 if (mlir::isa<mlir::IntegerType>(op.getType())) {
1795 attr = op.getValue();
1796 }
else if (mlir::isa<cir::BoolType>(op.getType())) {
1797 int value = mlir::cast<cir::BoolAttr>(op.getValue()).getValue();
1798 attr = rewriter.getIntegerAttr(typeConverter->convertType(op.getType()),
1800 }
else if (mlir::isa<cir::IntType>(op.getType())) {
1802 if (
auto ga = mlir::dyn_cast<cir::GlobalViewAttr>(op.getValue())) {
1805 op.emitError() <<
"global view with integer type";
1806 return mlir::failure();
1809 attr = rewriter.getIntegerAttr(
1810 typeConverter->convertType(op.getType()),
1811 mlir::cast<cir::IntAttr>(op.getValue()).getValue());
1812 }
else if (mlir::isa<cir::FPTypeInterface>(op.getType())) {
1813 attr = rewriter.getFloatAttr(
1814 typeConverter->convertType(op.getType()),
1815 mlir::cast<cir::FPAttr>(op.getValue()).getValue());
1816 }
else if (mlir::isa<cir::PointerType>(op.getType())) {
1818 if (mlir::isa<cir::ConstPtrAttr>(op.getValue())) {
1819 if (mlir::cast<cir::ConstPtrAttr>(op.getValue()).isNullValue()) {
1820 rewriter.replaceOpWithNewOp<mlir::LLVM::ZeroOp>(
1821 op, typeConverter->convertType(op.getType()));
1822 return mlir::success();
1826 if (
auto gv = mlir::dyn_cast<cir::GlobalViewAttr>(op.getValue())) {
1829 rewriter.replaceOp(op, newOp);
1830 return mlir::success();
1832 attr = op.getValue();
1833 }
else if (
const auto arrTy = mlir::dyn_cast<cir::ArrayType>(op.getType())) {
1834 const auto constArr = mlir::dyn_cast<cir::ConstArrayAttr>(op.getValue());
1835 if (!constArr && !isa<cir::ZeroAttr, cir::UndefAttr>(op.getValue()))
1836 return op.emitError() <<
"array does not have a constant initializer";
1838 std::optional<mlir::Attribute> denseAttr;
1841 op, constArr, rewriter, getTypeConverter(), lowerMod);
1842 rewriter.replaceOp(op, newOp);
1843 return mlir::success();
1844 }
else if (constArr &&
1846 attr = denseAttr.value();
1849 op, op.getValue(), rewriter, typeConverter, lowerMod);
1850 rewriter.replaceOp(op, initVal);
1851 return mlir::success();
1853 }
else if (
const auto recordAttr =
1854 mlir::dyn_cast<cir::ConstRecordAttr>(op.getValue())) {
1857 rewriter.replaceOp(op, initVal);
1858 return mlir::success();
1859 }
else if (
const auto vecTy = mlir::dyn_cast<cir::VectorType>(op.getType())) {
1861 getTypeConverter(), lowerMod));
1862 return mlir::success();
1863 }
else if (
auto recTy = mlir::dyn_cast<cir::RecordType>(op.getType())) {
1864 if (mlir::isa<cir::ZeroAttr, cir::UndefAttr>(attr)) {
1865 mlir::Value initVal =
1867 rewriter.replaceOp(op, initVal);
1868 return mlir::success();
1870 return op.emitError() <<
"unsupported lowering for record constant type "
1872 }
else if (
auto complexTy = mlir::dyn_cast<cir::ComplexType>(op.getType())) {
1873 mlir::Type complexElemTy = complexTy.getElementType();
1874 mlir::Type complexElemLLVMTy = typeConverter->convertType(complexElemTy);
1876 if (
auto zeroInitAttr = mlir::dyn_cast<cir::ZeroAttr>(op.getValue())) {
1877 mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(complexElemLLVMTy);
1878 mlir::ArrayAttr array = rewriter.getArrayAttr({zeroAttr, zeroAttr});
1879 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
1880 op, getTypeConverter()->convertType(op.getType()), array);
1881 return mlir::success();
1884 auto complexAttr = mlir::cast<cir::ConstComplexAttr>(op.getValue());
1886 mlir::Attribute components[2];
1887 if (mlir::isa<cir::IntType>(complexElemTy)) {
1888 components[0] = rewriter.getIntegerAttr(
1890 mlir::cast<cir::IntAttr>(complexAttr.getReal()).getValue());
1891 components[1] = rewriter.getIntegerAttr(
1893 mlir::cast<cir::IntAttr>(complexAttr.getImag()).getValue());
1895 components[0] = rewriter.getFloatAttr(
1897 mlir::cast<cir::FPAttr>(complexAttr.getReal()).getValue());
1898 components[1] = rewriter.getFloatAttr(
1900 mlir::cast<cir::FPAttr>(complexAttr.getImag()).getValue());
1903 attr = rewriter.getArrayAttr(components);
1905 return op.emitError() <<
"unsupported constant type " << op.getType();
1908 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
1909 op, getTypeConverter()->convertType(op.getType()),
attr);
1911 return mlir::success();
1915 mlir::DataLayout layout(op.getParentOfType<mlir::ModuleOp>());
1917 if (isa<cir::VoidType>(type))
1918 type = cir::IntType::get(type.getContext(), 8,
false);
1919 return llvm::divideCeil(layout.getTypeSizeInBits(type), 8);
1922mlir::LogicalResult CIRToLLVMPrefetchOpLowering::matchAndRewrite(
1923 cir::PrefetchOp op, OpAdaptor adaptor,
1924 mlir::ConversionPatternRewriter &rewriter)
const {
1925 rewriter.replaceOpWithNewOp<mlir::LLVM::Prefetch>(
1926 op, adaptor.getAddr(), adaptor.getIsWrite(), adaptor.getLocality(),
1928 return mlir::success();
1931mlir::LogicalResult CIRToLLVMPtrDiffOpLowering::matchAndRewrite(
1932 cir::PtrDiffOp op, OpAdaptor adaptor,
1933 mlir::ConversionPatternRewriter &rewriter)
const {
1934 auto dstTy = mlir::cast<cir::IntType>(op.getType());
1935 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1937 auto lhs = mlir::LLVM::PtrToIntOp::create(rewriter, op.getLoc(), llvmDstTy,
1939 auto rhs = mlir::LLVM::PtrToIntOp::create(rewriter, op.getLoc(), llvmDstTy,
1943 mlir::LLVM::SubOp::create(rewriter, op.getLoc(), llvmDstTy, lhs, rhs);
1945 cir::PointerType ptrTy = op.getLhs().getType();
1947 uint64_t typeSize =
getTypeSize(ptrTy.getPointee(), *op);
1950 mlir::Value resultVal = diff.getResult();
1951 if (typeSize != 1) {
1952 auto typeSizeVal = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1953 llvmDstTy, typeSize);
1955 if (dstTy.isUnsigned()) {
1957 mlir::LLVM::UDivOp::create(rewriter, op.getLoc(), diff, typeSizeVal);
1958 uDiv.setIsExact(
true);
1959 resultVal = uDiv.getResult();
1962 mlir::LLVM::SDivOp::create(rewriter, op.getLoc(), diff, typeSizeVal);
1963 sDiv.setIsExact(
true);
1964 resultVal = sDiv.getResult();
1967 rewriter.replaceOp(op, resultVal);
1968 return mlir::success();
1971mlir::LogicalResult CIRToLLVMExpectOpLowering::matchAndRewrite(
1972 cir::ExpectOp op, OpAdaptor adaptor,
1973 mlir::ConversionPatternRewriter &rewriter)
const {
1977 std::optional<llvm::APFloat> prob = op.getProb();
1979 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpectWithProbabilityOp>(
1980 op, adaptor.getVal(), adaptor.getExpected(), prob.value());
1982 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpectOp>(op, adaptor.getVal(),
1983 adaptor.getExpected());
1984 return mlir::success();
1987mlir::LogicalResult CIRToLLVMFAbsOpLowering::matchAndRewrite(
1988 cir::FAbsOp op, OpAdaptor adaptor,
1989 mlir::ConversionPatternRewriter &rewriter)
const {
1990 mlir::Type resTy = typeConverter->convertType(op.getType());
1991 rewriter.replaceOpWithNewOp<mlir::LLVM::FAbsOp>(op, resTy,
1992 adaptor.getOperands()[0]);
1993 return mlir::success();
2000void CIRToLLVMFuncOpLowering::lowerFuncAttributes(
2001 cir::FuncOp func,
bool filterArgAndResAttrs,
2002 SmallVectorImpl<mlir::NamedAttribute> &result)
const {
2004 for (mlir::NamedAttribute attr : func->getAttrs()) {
2006 if (
attr.getName() == mlir::SymbolTable::getSymbolAttrName() ||
2007 attr.getName() == func.getFunctionTypeAttrName() ||
2009 attr.getName() == func.getGlobalVisibilityAttrName() ||
2010 attr.getName() == func.getDsoLocalAttrName() ||
2011 attr.getName() == func.getInlineKindAttrName() ||
2012 (filterArgAndResAttrs &&
2013 (
attr.getName() == func.getArgAttrsAttrName() ||
2014 attr.getName() == func.getResAttrsAttrName())))
2018 result.push_back(attr);
2022mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewriteAlias(
2023 cir::FuncOp op, llvm::StringRef aliasee, mlir::Type ty, OpAdaptor adaptor,
2024 mlir::ConversionPatternRewriter &rewriter)
const {
2025 SmallVector<mlir::NamedAttribute, 4> attributes;
2026 lowerFuncAttributes(op,
false, attributes);
2028 mlir::Location loc = op.getLoc();
2029 auto aliasOp = rewriter.replaceOpWithNewOp<mlir::LLVM::AliasOp>(
2030 op, ty,
convertLinkage(op.getLinkage()), op.getName(), op.getDsoLocal(),
2034 mlir::OpBuilder builder(op.getContext());
2035 mlir::Block *block = builder.createBlock(&aliasOp.getInitializerRegion());
2036 builder.setInsertionPointToStart(block);
2039 mlir::Type ptrTy = mlir::LLVM::LLVMPointerType::get(ty.getContext());
2040 auto addrOp = mlir::LLVM::AddressOfOp::create(builder, loc, ptrTy, aliasee);
2041 mlir::LLVM::ReturnOp::create(builder, loc, addrOp);
2043 return mlir::success();
2046mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewrite(
2047 cir::FuncOp op, OpAdaptor adaptor,
2048 mlir::ConversionPatternRewriter &rewriter)
const {
2050 cir::FuncType fnType = op.getFunctionType();
2051 bool isDsoLocal = op.getDsoLocal();
2052 mlir::TypeConverter::SignatureConversion signatureConversion(
2053 fnType.getNumInputs());
2055 for (
const auto &argType : llvm::enumerate(fnType.getInputs())) {
2056 mlir::Type convertedType = typeConverter->convertType(argType.value());
2058 return mlir::failure();
2059 signatureConversion.addInputs(argType.index(), convertedType);
2062 mlir::Type resultType =
2063 getTypeConverter()->convertType(fnType.getReturnType());
2066 mlir::Type llvmFnTy = mlir::LLVM::LLVMFunctionType::get(
2067 resultType ? resultType : mlir::LLVM::LLVMVoidType::get(getContext()),
2068 signatureConversion.getConvertedTypes(),
2072 if (std::optional<llvm::StringRef> aliasee = op.getAliasee())
2073 return matchAndRewriteAlias(op, *aliasee, llvmFnTy, adaptor, rewriter);
2077 mlir::Location loc = op.getLoc();
2078 if (mlir::FusedLoc fusedLoc = mlir::dyn_cast<mlir::FusedLoc>(loc))
2079 loc = fusedLoc.getLocations()[0];
2080 assert((mlir::isa<mlir::FileLineColLoc>(loc) ||
2081 mlir::isa<mlir::UnknownLoc>(loc)) &&
2082 "expected single location or unknown location here");
2086 mlir::LLVM::CConv cconv = mlir::LLVM::CConv::C;
2087 SmallVector<mlir::NamedAttribute, 4> attributes;
2088 lowerFuncAttributes(op,
false, attributes);
2090 mlir::LLVM::LLVMFuncOp fn = mlir::LLVM::LLVMFuncOp::create(
2091 rewriter, loc, op.getName(), llvmFnTy, linkage, isDsoLocal, cconv,
2092 mlir::SymbolRefAttr(), attributes);
2096 if (std::optional<cir::InlineKind> inlineKind = op.getInlineKind()) {
2097 fn.setNoInline(*inlineKind == cir::InlineKind::NoInline);
2098 fn.setInlineHint(*inlineKind == cir::InlineKind::InlineHint);
2099 fn.setAlwaysInline(*inlineKind == cir::InlineKind::AlwaysInline);
2102 if (std::optional<llvm::StringRef> personality = op.getPersonality())
2103 fn.setPersonality(*personality);
2108 rewriter.inlineRegionBefore(op.getBody(), fn.getBody(), fn.end());
2109 if (failed(rewriter.convertRegionTypes(&fn.getBody(), *typeConverter,
2110 &signatureConversion)))
2111 return mlir::failure();
2113 rewriter.eraseOp(op);
2115 return mlir::LogicalResult::success();
2118mlir::LogicalResult CIRToLLVMGetGlobalOpLowering::matchAndRewrite(
2119 cir::GetGlobalOp op, OpAdaptor adaptor,
2120 mlir::ConversionPatternRewriter &rewriter)
const {
2123 if (op->getUses().empty()) {
2124 rewriter.eraseOp(op);
2125 return mlir::success();
2128 mlir::Type
type = getTypeConverter()->convertType(op.getType());
2129 mlir::Operation *newop = mlir::LLVM::AddressOfOp::create(
2130 rewriter, op.getLoc(), type, op.getName());
2134 newop = mlir::LLVM::ThreadlocalAddressOp::create(rewriter, op.getLoc(),
2135 type, newop->getResult(0));
2138 rewriter.replaceOp(op, newop);
2139 return mlir::success();
2144void CIRToLLVMGlobalOpLowering::setupRegionInitializedLLVMGlobalOp(
2145 cir::GlobalOp op, mlir::ConversionPatternRewriter &rewriter)
const {
2146 const mlir::Type llvmType =
2153 const bool isConst = op.getConstant();
2155 const unsigned addrSpace = 0;
2156 const bool isDsoLocal = op.getDsoLocal();
2157 const bool isThreadLocal = (
bool)op.getTlsModelAttr();
2158 const uint64_t alignment = op.getAlignment().value_or(0);
2159 const mlir::LLVM::Linkage linkage =
convertLinkage(op.getLinkage());
2160 const StringRef symbol = op.getSymName();
2161 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
2163 SmallVector<mlir::NamedAttribute> attributes;
2164 mlir::LLVM::GlobalOp newGlobalOp =
2165 rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
2166 op, llvmType, isConst, linkage, symbol,
nullptr, alignment, addrSpace,
2167 isDsoLocal, isThreadLocal, comdatAttr, attributes);
2168 newGlobalOp.getRegion().emplaceBlock();
2169 rewriter.setInsertionPointToEnd(newGlobalOp.getInitializerBlock());
2173CIRToLLVMGlobalOpLowering::matchAndRewriteRegionInitializedGlobal(
2174 cir::GlobalOp op, mlir::Attribute init,
2175 mlir::ConversionPatternRewriter &rewriter)
const {
2178 (isa<cir::ConstArrayAttr, cir::ConstRecordAttr, cir::ConstVectorAttr,
2179 cir::ConstPtrAttr, cir::ConstComplexAttr, cir::GlobalViewAttr,
2180 cir::TypeInfoAttr, cir::UndefAttr, cir::VTableAttr, cir::ZeroAttr>(
2186 const mlir::Location loc = op.getLoc();
2187 setupRegionInitializedLLVMGlobalOp(op, rewriter);
2188 CIRAttrToValue valueConverter(op, rewriter, typeConverter, lowerMod);
2189 mlir::Value value = valueConverter.visit(init);
2190 mlir::LLVM::ReturnOp::create(rewriter, loc, value);
2191 return mlir::success();
2194mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite(
2195 cir::GlobalOp op, OpAdaptor adaptor,
2196 mlir::ConversionPatternRewriter &rewriter)
const {
2199 if (!op.getCtorRegion().empty() || !op.getDtorRegion().empty())
2200 return op.emitError() <<
"GlobalOp ctor and dtor regions should be removed "
2201 "in LoweringPrepare";
2203 std::optional<mlir::Attribute> init = op.getInitialValue();
2206 const mlir::Type cirSymType = op.getSymType();
2209 const mlir::Type llvmType =
2213 const bool isConst = op.getConstant();
2215 const unsigned addrSpace = 0;
2216 const bool isDsoLocal = op.getDsoLocal();
2217 const bool isThreadLocal = (
bool)op.getTlsModelAttr();
2218 const uint64_t alignment = op.getAlignment().value_or(0);
2219 const mlir::LLVM::Linkage linkage =
convertLinkage(op.getLinkage());
2220 const StringRef symbol = op.getSymName();
2221 SmallVector<mlir::NamedAttribute> attributes;
2223 if (init.has_value()) {
2224 if (mlir::isa<cir::FPAttr, cir::IntAttr, cir::BoolAttr>(init.value())) {
2226 init = initRewriter.visit(init.value());
2231 if (!init.value()) {
2232 op.emitError() <<
"unsupported initializer '" << init.value() <<
"'";
2233 return mlir::failure();
2235 }
else if (mlir::isa<cir::ConstArrayAttr, cir::ConstVectorAttr,
2236 cir::ConstRecordAttr, cir::ConstPtrAttr,
2237 cir::ConstComplexAttr, cir::GlobalViewAttr,
2238 cir::TypeInfoAttr, cir::UndefAttr, cir::VTableAttr,
2239 cir::ZeroAttr>(init.value())) {
2243 return matchAndRewriteRegionInitializedGlobal(op, init.value(), rewriter);
2247 op.emitError() <<
"unsupported initializer '" << init.value() <<
"'";
2248 return mlir::failure();
2252 mlir::LLVM::Visibility visibility =
2254 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
2255 auto newOp = rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
2256 op, llvmType, isConst, linkage, symbol, init.value_or(mlir::Attribute()),
2257 alignment, addrSpace, isDsoLocal, isThreadLocal, comdatAttr, attributes);
2258 newOp.setVisibility_(visibility);
2260 return mlir::success();
2264CIRToLLVMGlobalOpLowering::getComdatAttr(cir::GlobalOp &op,
2265 mlir::OpBuilder &builder)
const {
2266 if (!op.getComdat())
2267 return mlir::SymbolRefAttr{};
2269 mlir::ModuleOp module = op->getParentOfType<mlir::ModuleOp>();
2270 mlir::OpBuilder::InsertionGuard guard(builder);
2271 StringRef comdatName(
"__llvm_comdat_globals");
2273 builder.setInsertionPointToStart(module.getBody());
2275 mlir::LLVM::ComdatOp::create(builder, module.getLoc(), comdatName);
2278 if (
auto comdatSelector = comdatOp.lookupSymbol<mlir::LLVM::ComdatSelectorOp>(
2280 return mlir::SymbolRefAttr::get(
2281 builder.getContext(), comdatName,
2282 mlir::FlatSymbolRefAttr::get(comdatSelector.getSymNameAttr()));
2285 builder.setInsertionPointToStart(&comdatOp.getBody().back());
2286 auto selectorOp = mlir::LLVM::ComdatSelectorOp::create(
2287 builder, comdatOp.getLoc(), op.getSymName(),
2288 mlir::LLVM::comdat::Comdat::Any);
2289 return mlir::SymbolRefAttr::get(
2290 builder.getContext(), comdatName,
2291 mlir::FlatSymbolRefAttr::get(selectorOp.getSymNameAttr()));
2294mlir::LogicalResult CIRToLLVMSwitchFlatOpLowering::matchAndRewrite(
2295 cir::SwitchFlatOp op, OpAdaptor adaptor,
2296 mlir::ConversionPatternRewriter &rewriter)
const {
2298 llvm::SmallVector<mlir::APInt, 8> caseValues;
2299 for (mlir::Attribute val : op.getCaseValues()) {
2300 auto intAttr = cast<cir::IntAttr>(val);
2301 caseValues.push_back(intAttr.getValue());
2304 llvm::SmallVector<mlir::Block *, 8> caseDestinations;
2305 llvm::SmallVector<mlir::ValueRange, 8> caseOperands;
2307 for (mlir::Block *x : op.getCaseDestinations())
2308 caseDestinations.push_back(x);
2310 for (mlir::OperandRange x : op.getCaseOperands())
2311 caseOperands.push_back(x);
2314 rewriter.setInsertionPoint(op);
2315 rewriter.replaceOpWithNewOp<mlir::LLVM::SwitchOp>(
2316 op, adaptor.getCondition(), op.getDefaultDestination(),
2317 op.getDefaultOperands(), caseValues, caseDestinations, caseOperands);
2318 return mlir::success();
2321mlir::LogicalResult CIRToLLVMUnaryOpLowering::matchAndRewrite(
2322 cir::UnaryOp op, OpAdaptor adaptor,
2323 mlir::ConversionPatternRewriter &rewriter)
const {
2324 assert(op.getType() == op.getInput().getType() &&
2325 "Unary operation's operand type and result type are different");
2326 mlir::Type
type = op.getType();
2327 mlir::Type elementType = elementTypeIfVector(type);
2328 bool isVector = mlir::isa<cir::VectorType>(type);
2329 mlir::Type llvmType = getTypeConverter()->convertType(type);
2330 mlir::Location loc = op.getLoc();
2333 if (mlir::isa<cir::IntType>(elementType)) {
2334 mlir::LLVM::IntegerOverflowFlags maybeNSW =
2335 op.getNoSignedWrap() ? mlir::LLVM::IntegerOverflowFlags::nsw
2336 : mlir::LLVM::IntegerOverflowFlags::none;
2337 switch (op.getKind()) {
2338 case cir::UnaryOpKind::Inc: {
2339 assert(!
isVector &&
"++ not allowed on vector types");
2340 auto one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
2341 rewriter.replaceOpWithNewOp<mlir::LLVM::AddOp>(
2342 op, llvmType, adaptor.getInput(), one, maybeNSW);
2343 return mlir::success();
2345 case cir::UnaryOpKind::Dec: {
2346 assert(!
isVector &&
"-- not allowed on vector types");
2347 auto one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
2348 rewriter.replaceOpWithNewOp<mlir::LLVM::SubOp>(op, adaptor.getInput(),
2350 return mlir::success();
2352 case cir::UnaryOpKind::Plus:
2353 rewriter.replaceOp(op, adaptor.getInput());
2354 return mlir::success();
2355 case cir::UnaryOpKind::Minus: {
2358 zero = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmType);
2360 zero = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 0);
2361 rewriter.replaceOpWithNewOp<mlir::LLVM::SubOp>(
2362 op, zero, adaptor.getInput(), maybeNSW);
2363 return mlir::success();
2365 case cir::UnaryOpKind::Not: {
2367 mlir::Value minusOne;
2370 mlir::dyn_cast<cir::VectorType>(type).getSize();
2371 std::vector<int32_t> values(numElements, -1);
2372 mlir::DenseIntElementsAttr denseVec = rewriter.getI32VectorAttr(values);
2374 mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, denseVec);
2376 minusOne = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, -1);
2378 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getInput(),
2380 return mlir::success();
2383 llvm_unreachable(
"Unexpected unary op for int");
2387 if (mlir::isa<cir::FPTypeInterface>(elementType)) {
2388 switch (op.getKind()) {
2389 case cir::UnaryOpKind::Inc: {
2390 assert(!
isVector &&
"++ not allowed on vector types");
2391 mlir::LLVM::ConstantOp one = mlir::LLVM::ConstantOp::create(
2392 rewriter, loc, llvmType, rewriter.getFloatAttr(llvmType, 1.0));
2393 rewriter.replaceOpWithNewOp<mlir::LLVM::FAddOp>(op, llvmType, one,
2394 adaptor.getInput());
2395 return mlir::success();
2397 case cir::UnaryOpKind::Dec: {
2398 assert(!
isVector &&
"-- not allowed on vector types");
2399 mlir::LLVM::ConstantOp minusOne = mlir::LLVM::ConstantOp::create(
2400 rewriter, loc, llvmType, rewriter.getFloatAttr(llvmType, -1.0));
2401 rewriter.replaceOpWithNewOp<mlir::LLVM::FAddOp>(op, llvmType, minusOne,
2402 adaptor.getInput());
2403 return mlir::success();
2405 case cir::UnaryOpKind::Plus:
2406 rewriter.replaceOp(op, adaptor.getInput());
2407 return mlir::success();
2408 case cir::UnaryOpKind::Minus:
2409 rewriter.replaceOpWithNewOp<mlir::LLVM::FNegOp>(op, llvmType,
2410 adaptor.getInput());
2411 return mlir::success();
2412 case cir::UnaryOpKind::Not:
2413 return op.emitError() <<
"Unary not is invalid for floating-point types";
2415 llvm_unreachable(
"Unexpected unary op for float");
2420 if (mlir::isa<cir::BoolType>(elementType)) {
2421 switch (op.getKind()) {
2422 case cir::UnaryOpKind::Inc:
2423 case cir::UnaryOpKind::Dec:
2424 case cir::UnaryOpKind::Plus:
2425 case cir::UnaryOpKind::Minus:
2428 return op.emitError() <<
"Unsupported unary operation on boolean type";
2429 case cir::UnaryOpKind::Not: {
2430 assert(!
isVector &&
"NYI: op! on vector mask");
2431 auto one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
2432 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getInput(),
2434 return mlir::success();
2437 llvm_unreachable(
"Unexpected unary op for bool");
2442 if (mlir::isa<cir::PointerType>(elementType)) {
2443 switch (op.getKind()) {
2444 case cir::UnaryOpKind::Plus:
2445 rewriter.replaceOp(op, adaptor.getInput());
2446 return mlir::success();
2448 op.emitError() <<
"Unknown pointer unary operation during CIR lowering";
2449 return mlir::failure();
2453 return op.emitError() <<
"Unary operation has unsupported type: "
2457mlir::LLVM::IntegerOverflowFlags
2458CIRToLLVMBinOpLowering::getIntOverflowFlag(cir::BinOp op)
const {
2459 if (op.getNoUnsignedWrap())
2460 return mlir::LLVM::IntegerOverflowFlags::nuw;
2462 if (op.getNoSignedWrap())
2463 return mlir::LLVM::IntegerOverflowFlags::nsw;
2465 return mlir::LLVM::IntegerOverflowFlags::none;
2470 return mlir::isa<cir::IntType>(type)
2471 ? mlir::cast<cir::IntType>(type).isUnsigned()
2472 : mlir::cast<mlir::IntegerType>(type).isUnsigned();
2475mlir::LogicalResult CIRToLLVMBinOpLowering::matchAndRewrite(
2476 cir::BinOp op, OpAdaptor adaptor,
2477 mlir::ConversionPatternRewriter &rewriter)
const {
2478 if (adaptor.getLhs().getType() != adaptor.getRhs().getType())
2479 return op.emitError() <<
"inconsistent operands' types not supported yet";
2481 mlir::Type type = op.getRhs().getType();
2482 if (!mlir::isa<cir::IntType, cir::BoolType, cir::FPTypeInterface,
2483 mlir::IntegerType, cir::VectorType>(type))
2484 return op.emitError() <<
"operand type not supported yet";
2486 const mlir::Type llvmTy = getTypeConverter()->convertType(op.getType());
2487 const mlir::Type llvmEltTy = elementTypeIfVector(llvmTy);
2489 const mlir::Value rhs = adaptor.getRhs();
2490 const mlir::Value lhs = adaptor.getLhs();
2491 type = elementTypeIfVector(type);
2493 switch (op.getKind()) {
2494 case cir::BinOpKind::Add:
2495 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
2496 if (op.getSaturated()) {
2498 rewriter.replaceOpWithNewOp<mlir::LLVM::UAddSat>(op, lhs, rhs);
2501 rewriter.replaceOpWithNewOp<mlir::LLVM::SAddSat>(op, lhs, rhs);
2504 rewriter.replaceOpWithNewOp<mlir::LLVM::AddOp>(op, llvmTy, lhs, rhs,
2505 getIntOverflowFlag(op));
2507 rewriter.replaceOpWithNewOp<mlir::LLVM::FAddOp>(op, lhs, rhs);
2510 case cir::BinOpKind::Sub:
2511 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
2512 if (op.getSaturated()) {
2514 rewriter.replaceOpWithNewOp<mlir::LLVM::USubSat>(op, lhs, rhs);
2517 rewriter.replaceOpWithNewOp<mlir::LLVM::SSubSat>(op, lhs, rhs);
2520 rewriter.replaceOpWithNewOp<mlir::LLVM::SubOp>(op, llvmTy, lhs, rhs,
2521 getIntOverflowFlag(op));
2523 rewriter.replaceOpWithNewOp<mlir::LLVM::FSubOp>(op, lhs, rhs);
2526 case cir::BinOpKind::Mul:
2527 if (mlir::isa<mlir::IntegerType>(llvmEltTy))
2528 rewriter.replaceOpWithNewOp<mlir::LLVM::MulOp>(op, llvmTy, lhs, rhs,
2529 getIntOverflowFlag(op));
2531 rewriter.replaceOpWithNewOp<mlir::LLVM::FMulOp>(op, lhs, rhs);
2533 case cir::BinOpKind::Div:
2534 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
2537 rewriter.replaceOpWithNewOp<mlir::LLVM::UDivOp>(op, lhs, rhs);
2539 rewriter.replaceOpWithNewOp<mlir::LLVM::SDivOp>(op, lhs, rhs);
2541 rewriter.replaceOpWithNewOp<mlir::LLVM::FDivOp>(op, lhs, rhs);
2544 case cir::BinOpKind::Rem:
2545 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
2548 rewriter.replaceOpWithNewOp<mlir::LLVM::URemOp>(op, lhs, rhs);
2550 rewriter.replaceOpWithNewOp<mlir::LLVM::SRemOp>(op, lhs, rhs);
2552 rewriter.replaceOpWithNewOp<mlir::LLVM::FRemOp>(op, lhs, rhs);
2555 case cir::BinOpKind::And:
2556 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(op, lhs, rhs);
2558 case cir::BinOpKind::Or:
2559 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(op, lhs, rhs);
2561 case cir::BinOpKind::Xor:
2562 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, lhs, rhs);
2564 case cir::BinOpKind::Max:
2565 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
2568 rewriter.replaceOpWithNewOp<mlir::LLVM::UMaxOp>(op, llvmTy, lhs, rhs);
2570 rewriter.replaceOpWithNewOp<mlir::LLVM::SMaxOp>(op, llvmTy, lhs, rhs);
2574 return mlir::LogicalResult::success();
2578static mlir::LLVM::ICmpPredicate
2580 using CIR = cir::CmpOpKind;
2581 using LLVMICmp = mlir::LLVM::ICmpPredicate;
2584 return LLVMICmp::eq;
2586 return LLVMICmp::ne;
2588 return (isSigned ? LLVMICmp::slt : LLVMICmp::ult);
2590 return (isSigned ? LLVMICmp::sle : LLVMICmp::ule);
2592 return (isSigned ? LLVMICmp::sgt : LLVMICmp::ugt);
2594 return (isSigned ? LLVMICmp::sge : LLVMICmp::uge);
2596 llvm_unreachable(
"Unknown CmpOpKind");
2601static mlir::LLVM::FCmpPredicate
2603 using CIR = cir::CmpOpKind;
2604 using LLVMFCmp = mlir::LLVM::FCmpPredicate;
2607 return LLVMFCmp::oeq;
2609 return LLVMFCmp::une;
2611 return LLVMFCmp::olt;
2613 return LLVMFCmp::ole;
2615 return LLVMFCmp::ogt;
2617 return LLVMFCmp::oge;
2619 llvm_unreachable(
"Unknown CmpOpKind");
2622mlir::LogicalResult CIRToLLVMCmpOpLowering::matchAndRewrite(
2623 cir::CmpOp cmpOp, OpAdaptor adaptor,
2624 mlir::ConversionPatternRewriter &rewriter)
const {
2625 mlir::Type type = cmpOp.getLhs().getType();
2630 if (mlir::isa<cir::IntType, mlir::IntegerType>(type)) {
2631 bool isSigned = mlir::isa<cir::IntType>(type)
2632 ? mlir::cast<cir::IntType>(type).isSigned()
2633 : mlir::cast<mlir::IntegerType>(type).isSigned();
2634 mlir::LLVM::ICmpPredicate kind =
2636 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
2637 cmpOp, kind, adaptor.getLhs(), adaptor.getRhs());
2638 return mlir::success();
2641 if (
auto ptrTy = mlir::dyn_cast<cir::PointerType>(type)) {
2642 mlir::LLVM::ICmpPredicate kind =
2645 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
2646 cmpOp, kind, adaptor.getLhs(), adaptor.getRhs());
2647 return mlir::success();
2650 if (
auto vptrTy = mlir::dyn_cast<cir::VPtrType>(type)) {
2654 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
2655 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
2656 return mlir::success();
2659 if (mlir::isa<cir::FPTypeInterface>(type)) {
2660 mlir::LLVM::FCmpPredicate
kind =
2662 rewriter.replaceOpWithNewOp<mlir::LLVM::FCmpOp>(
2663 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
2664 return mlir::success();
2667 if (mlir::isa<cir::ComplexType>(type)) {
2668 mlir::Value lhs = adaptor.getLhs();
2669 mlir::Value rhs = adaptor.getRhs();
2670 mlir::Location loc = cmpOp.getLoc();
2672 auto complexType = mlir::cast<cir::ComplexType>(cmpOp.getLhs().getType());
2673 mlir::Type complexElemTy =
2674 getTypeConverter()->convertType(
complexType.getElementType());
2676 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
2677 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{0}));
2678 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
2679 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{1}));
2680 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
2681 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{0}));
2682 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
2683 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{1}));
2685 if (cmpOp.getKind() == cir::CmpOpKind::eq) {
2686 if (complexElemTy.isInteger()) {
2687 auto realCmp = mlir::LLVM::ICmpOp::create(
2688 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, lhsReal, rhsReal);
2689 auto imagCmp = mlir::LLVM::ICmpOp::create(
2690 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, lhsImag, rhsImag);
2691 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, imagCmp);
2692 return mlir::success();
2695 auto realCmp = mlir::LLVM::FCmpOp::create(
2696 rewriter, loc, mlir::LLVM::FCmpPredicate::oeq, lhsReal, rhsReal);
2697 auto imagCmp = mlir::LLVM::FCmpOp::create(
2698 rewriter, loc, mlir::LLVM::FCmpPredicate::oeq, lhsImag, rhsImag);
2699 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, imagCmp);
2700 return mlir::success();
2703 if (cmpOp.getKind() == cir::CmpOpKind::ne) {
2704 if (complexElemTy.isInteger()) {
2705 auto realCmp = mlir::LLVM::ICmpOp::create(
2706 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, lhsReal, rhsReal);
2707 auto imagCmp = mlir::LLVM::ICmpOp::create(
2708 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, lhsImag, rhsImag);
2709 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp);
2710 return mlir::success();
2713 auto realCmp = mlir::LLVM::FCmpOp::create(
2714 rewriter, loc, mlir::LLVM::FCmpPredicate::une, lhsReal, rhsReal);
2715 auto imagCmp = mlir::LLVM::FCmpOp::create(
2716 rewriter, loc, mlir::LLVM::FCmpPredicate::une, lhsImag, rhsImag);
2717 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp);
2718 return mlir::success();
2722 return cmpOp.emitError() <<
"unsupported type for CmpOp: " <<
type;
2725mlir::LogicalResult CIRToLLVMBinOpOverflowOpLowering::matchAndRewrite(
2726 cir::BinOpOverflowOp op, OpAdaptor adaptor,
2727 mlir::ConversionPatternRewriter &rewriter)
const {
2728 mlir::Location loc = op.getLoc();
2729 cir::BinOpOverflowKind arithKind = op.getKind();
2730 cir::IntType operandTy = op.getLhs().getType();
2731 cir::IntType resultTy = op.getResult().getType();
2733 EncompassedTypeInfo encompassedTyInfo =
2734 computeEncompassedTypeWidth(operandTy, resultTy);
2735 mlir::IntegerType encompassedLLVMTy =
2736 rewriter.getIntegerType(encompassedTyInfo.width);
2738 mlir::Value lhs = adaptor.getLhs();
2739 mlir::Value rhs = adaptor.getRhs();
2740 if (operandTy.getWidth() < encompassedTyInfo.width) {
2741 if (operandTy.isSigned()) {
2742 lhs = mlir::LLVM::SExtOp::create(rewriter, loc, encompassedLLVMTy, lhs);
2743 rhs = mlir::LLVM::SExtOp::create(rewriter, loc, encompassedLLVMTy, rhs);
2745 lhs = mlir::LLVM::ZExtOp::create(rewriter, loc, encompassedLLVMTy, lhs);
2746 rhs = mlir::LLVM::ZExtOp::create(rewriter, loc, encompassedLLVMTy, rhs);
2750 std::string intrinName = getLLVMIntrinName(arithKind, encompassedTyInfo.sign,
2751 encompassedTyInfo.width);
2752 auto intrinNameAttr = mlir::StringAttr::get(op.getContext(), intrinName);
2754 mlir::IntegerType overflowLLVMTy = rewriter.getI1Type();
2755 auto intrinRetTy = mlir::LLVM::LLVMStructType::getLiteral(
2756 rewriter.getContext(), {encompassedLLVMTy, overflowLLVMTy});
2758 auto callLLVMIntrinOp = mlir::LLVM::CallIntrinsicOp::create(
2759 rewriter, loc, intrinRetTy, intrinNameAttr, mlir::ValueRange{lhs, rhs});
2760 mlir::Value intrinRet = callLLVMIntrinOp.getResult(0);
2762 mlir::Value result = mlir::LLVM::ExtractValueOp::create(
2763 rewriter, loc, intrinRet, ArrayRef<int64_t>{0})
2765 mlir::Value overflow = mlir::LLVM::ExtractValueOp::create(
2766 rewriter, loc, intrinRet, ArrayRef<int64_t>{1})
2769 if (resultTy.getWidth() < encompassedTyInfo.width) {
2770 mlir::Type resultLLVMTy = getTypeConverter()->convertType(resultTy);
2772 mlir::LLVM::TruncOp::create(rewriter, loc, resultLLVMTy, result);
2776 mlir::Value truncResultExt;
2777 if (resultTy.isSigned())
2778 truncResultExt = mlir::LLVM::SExtOp::create(
2779 rewriter, loc, encompassedLLVMTy, truncResult);
2781 truncResultExt = mlir::LLVM::ZExtOp::create(
2782 rewriter, loc, encompassedLLVMTy, truncResult);
2783 auto truncOverflow = mlir::LLVM::ICmpOp::create(
2784 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, truncResultExt, result);
2786 result = truncResult;
2787 overflow = mlir::LLVM::OrOp::create(rewriter, loc, overflow, truncOverflow);
2790 mlir::Type boolLLVMTy =
2791 getTypeConverter()->convertType(op.getOverflow().getType());
2792 if (boolLLVMTy != rewriter.getI1Type())
2793 overflow = mlir::LLVM::ZExtOp::create(rewriter, loc, boolLLVMTy, overflow);
2795 rewriter.replaceOp(op, mlir::ValueRange{result, overflow});
2797 return mlir::success();
2800std::string CIRToLLVMBinOpOverflowOpLowering::getLLVMIntrinName(
2801 cir::BinOpOverflowKind opKind,
bool isSigned,
unsigned width) {
2804 std::string
name =
"llvm.";
2807 name.push_back(
's');
2809 name.push_back(
'u');
2812 case cir::BinOpOverflowKind::Add:
2813 name.append(
"add.");
2815 case cir::BinOpOverflowKind::Sub:
2816 name.append(
"sub.");
2818 case cir::BinOpOverflowKind::Mul:
2819 name.append(
"mul.");
2823 name.append(
"with.overflow.i");
2824 name.append(std::to_string(width));
2829CIRToLLVMBinOpOverflowOpLowering::EncompassedTypeInfo
2830CIRToLLVMBinOpOverflowOpLowering::computeEncompassedTypeWidth(
2831 cir::IntType operandTy, cir::IntType resultTy) {
2832 bool sign = operandTy.getIsSigned() || resultTy.getIsSigned();
2834 std::max(operandTy.getWidth() + (
sign && operandTy.isUnsigned()),
2835 resultTy.getWidth() + (
sign && resultTy.isUnsigned()));
2836 return {
sign, width};
2839mlir::LogicalResult CIRToLLVMShiftOpLowering::matchAndRewrite(
2840 cir::ShiftOp op, OpAdaptor adaptor,
2841 mlir::ConversionPatternRewriter &rewriter)
const {
2842 assert((op.getValue().getType() == op.getType()) &&
2843 "inconsistent operands' types NYI");
2845 const mlir::Type llvmTy = getTypeConverter()->convertType(op.getType());
2846 mlir::Value amt = adaptor.getAmount();
2847 mlir::Value val = adaptor.getValue();
2849 auto cirAmtTy = mlir::dyn_cast<cir::IntType>(op.getAmount().getType());
2852 auto cirValTy = mlir::cast<cir::IntType>(op.getValue().getType());
2860 amt =
getLLVMIntCast(rewriter, amt, llvmTy,
true, cirAmtTy.getWidth(),
2861 cirValTy.getWidth());
2863 auto cirValVTy = mlir::cast<cir::VectorType>(op.getValue().getType());
2865 mlir::cast<cir::IntType>(cirValVTy.getElementType()).isUnsigned();
2869 if (op.getIsShiftleft()) {
2870 rewriter.replaceOpWithNewOp<mlir::LLVM::ShlOp>(op, llvmTy, val, amt);
2871 return mlir::success();
2875 rewriter.replaceOpWithNewOp<mlir::LLVM::LShrOp>(op, llvmTy, val, amt);
2877 rewriter.replaceOpWithNewOp<mlir::LLVM::AShrOp>(op, llvmTy, val, amt);
2878 return mlir::success();
2881mlir::LogicalResult CIRToLLVMSelectOpLowering::matchAndRewrite(
2882 cir::SelectOp op, OpAdaptor adaptor,
2883 mlir::ConversionPatternRewriter &rewriter)
const {
2884 auto getConstantBool = [](mlir::Value value) -> cir::BoolAttr {
2885 auto definingOp = value.getDefiningOp<cir::ConstantOp>();
2889 auto constValue = definingOp.getValueAttr<cir::BoolAttr>();
2899 if (mlir::isa<cir::BoolType>(op.getTrueValue().getType())) {
2900 cir::BoolAttr trueValue = getConstantBool(op.getTrueValue());
2901 cir::BoolAttr falseValue = getConstantBool(op.getFalseValue());
2902 if (falseValue && !falseValue.getValue()) {
2904 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(op, adaptor.getCondition(),
2905 adaptor.getTrueValue());
2906 return mlir::success();
2908 if (trueValue && trueValue.getValue()) {
2910 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(op, adaptor.getCondition(),
2911 adaptor.getFalseValue());
2912 return mlir::success();
2916 mlir::Value llvmCondition = adaptor.getCondition();
2917 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(
2918 op, llvmCondition, adaptor.getTrueValue(), adaptor.getFalseValue());
2920 return mlir::success();
2924 mlir::PatternRewriter rewriter{
module->getContext()};
2929 if (!module->hasAttr(cir::CIRDialect::getTripleAttrName()))
2935 mlir::DataLayout &dataLayout,
2937 converter.addConversion([&](cir::PointerType type) -> mlir::Type {
2938 unsigned addrSpace =
2939 type.getAddrSpace() ? type.getAddrSpace().getValue().getUInt() : 0;
2940 return mlir::LLVM::LLVMPointerType::get(type.getContext(), addrSpace);
2942 converter.addConversion([&](cir::VPtrType type) -> mlir::Type {
2944 return mlir::LLVM::LLVMPointerType::get(type.getContext());
2946 converter.addConversion([&](cir::ArrayType type) -> mlir::Type {
2949 return mlir::LLVM::LLVMArrayType::get(ty, type.getSize());
2951 converter.addConversion([&](cir::VectorType type) -> mlir::Type {
2952 const mlir::Type ty = converter.convertType(type.getElementType());
2953 return mlir::VectorType::get(type.getSize(), ty, {type.getIsScalable()});
2955 converter.addConversion([&](cir::BoolType type) -> mlir::Type {
2956 return mlir::IntegerType::get(type.getContext(), 1,
2957 mlir::IntegerType::Signless);
2959 converter.addConversion([&](cir::IntType type) -> mlir::Type {
2961 return mlir::IntegerType::get(type.getContext(), type.getWidth());
2963 converter.addConversion([&](cir::SingleType type) -> mlir::Type {
2964 return mlir::Float32Type::get(type.getContext());
2966 converter.addConversion([&](cir::DoubleType type) -> mlir::Type {
2967 return mlir::Float64Type::get(type.getContext());
2969 converter.addConversion([&](cir::FP80Type type) -> mlir::Type {
2970 return mlir::Float80Type::get(type.getContext());
2972 converter.addConversion([&](cir::FP128Type type) -> mlir::Type {
2973 return mlir::Float128Type::get(type.getContext());
2975 converter.addConversion([&](cir::LongDoubleType type) -> mlir::Type {
2976 return converter.convertType(type.getUnderlying());
2978 converter.addConversion([&](cir::FP16Type type) -> mlir::Type {
2979 return mlir::Float16Type::get(type.getContext());
2981 converter.addConversion([&](cir::BF16Type type) -> mlir::Type {
2982 return mlir::BFloat16Type::get(type.getContext());
2984 converter.addConversion([&](cir::ComplexType type) -> mlir::Type {
2987 mlir::Type elementTy = converter.convertType(type.getElementType());
2988 mlir::Type structFields[2] = {elementTy, elementTy};
2989 return mlir::LLVM::LLVMStructType::getLiteral(type.getContext(),
2992 converter.addConversion([&](cir::FuncType type) -> std::optional<mlir::Type> {
2993 auto result = converter.convertType(type.getReturnType());
2995 arguments.reserve(type.getNumInputs());
2996 if (converter.convertTypes(type.getInputs(), arguments).failed())
2997 return std::nullopt;
2998 auto varArg = type.isVarArg();
2999 return mlir::LLVM::LLVMFunctionType::get(result, arguments, varArg);
3001 converter.addConversion([&](cir::RecordType type) -> mlir::Type {
3004 switch (type.getKind()) {
3005 case cir::RecordType::Class:
3006 case cir::RecordType::Struct:
3007 for (mlir::Type ty : type.getMembers())
3011 case cir::RecordType::Union:
3012 if (
auto largestMember = type.getLargestMember(dataLayout))
3013 llvmMembers.push_back(
3015 if (type.getPadded()) {
3016 auto last = *type.getMembers().rbegin();
3017 llvmMembers.push_back(
3024 mlir::LLVM::LLVMStructType llvmStruct;
3025 if (type.getName()) {
3026 llvmStruct = mlir::LLVM::LLVMStructType::getIdentified(
3027 type.getContext(), type.getPrefixedName());
3028 if (llvmStruct.setBody(llvmMembers, type.getPacked()).failed())
3029 llvm_unreachable(
"Failed to set body of record");
3031 llvmStruct = mlir::LLVM::LLVMStructType::getLiteral(
3032 type.getContext(), llvmMembers, type.getPacked());
3037 converter.addConversion([&](cir::VoidType type) -> mlir::Type {
3038 return mlir::LLVM::LLVMVoidType::get(type.getContext());
3043 mlir::ModuleOp module, StringRef globalXtorName, StringRef llvmXtorName,
3044 llvm::function_ref<std::pair<StringRef, int>(mlir::Attribute)> createXtor) {
3046 for (
const mlir::NamedAttribute namedAttr : module->getAttrs()) {
3047 if (namedAttr.getName() == globalXtorName) {
3048 for (
auto attr : mlir::cast<mlir::ArrayAttr>(namedAttr.getValue()))
3049 globalXtors.emplace_back(createXtor(attr));
3054 if (globalXtors.empty())
3057 mlir::OpBuilder builder(module.getContext());
3058 builder.setInsertionPointToEnd(&module.getBodyRegion().back());
3062 auto ctorPFTy = mlir::LLVM::LLVMPointerType::get(builder.getContext());
3064 ctorStructFields.push_back(builder.getI32Type());
3065 ctorStructFields.push_back(ctorPFTy);
3066 ctorStructFields.push_back(ctorPFTy);
3068 auto ctorStructTy = mlir::LLVM::LLVMStructType::getLiteral(
3069 builder.getContext(), ctorStructFields);
3070 auto ctorStructArrayTy =
3071 mlir::LLVM::LLVMArrayType::get(ctorStructTy, globalXtors.size());
3073 mlir::Location loc =
module.getLoc();
3074 auto newGlobalOp = mlir::LLVM::GlobalOp::create(
3075 builder, loc, ctorStructArrayTy,
false,
3076 mlir::LLVM::Linkage::Appending, llvmXtorName, mlir::Attribute());
3078 builder.createBlock(&newGlobalOp.getRegion());
3079 builder.setInsertionPointToEnd(newGlobalOp.getInitializerBlock());
3081 mlir::Value result =
3082 mlir::LLVM::UndefOp::create(builder, loc, ctorStructArrayTy);
3084 for (
auto [index, fn] : llvm::enumerate(globalXtors)) {
3085 mlir::Value structInit =
3086 mlir::LLVM::UndefOp::create(builder, loc, ctorStructTy);
3087 mlir::Value initPriority = mlir::LLVM::ConstantOp::create(
3088 builder, loc, ctorStructFields[0], fn.second);
3089 mlir::Value initFuncAddr = mlir::LLVM::AddressOfOp::create(
3090 builder, loc, ctorStructFields[1], fn.first);
3091 mlir::Value initAssociate =
3092 mlir::LLVM::ZeroOp::create(builder, loc, ctorStructFields[2]);
3095 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
3096 initPriority, zero);
3097 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
3100 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
3102 result = mlir::LLVM::InsertValueOp::create(builder, loc, result, structInit,
3106 mlir::LLVM::ReturnOp::create(builder, loc, result);
3144 parent->walk([&](mlir::Block *blk) {
3145 if (blk->hasNoPredecessors() && !blk->isEntryBlock())
3146 unreachableBlocks.push_back(blk);
3149 std::set<mlir::Block *> visited;
3150 for (mlir::Block *root : unreachableBlocks) {
3153 std::deque<mlir::Block *> workList;
3154 workList.push_back(root);
3156 while (!workList.empty()) {
3157 mlir::Block *blk = workList.back();
3158 workList.pop_back();
3159 if (visited.count(blk))
3161 visited.emplace(blk);
3163 for (mlir::Operation &op : *blk)
3166 for (mlir::Block *succ : blk->getSuccessors())
3167 workList.push_back(succ);
3172mlir::LogicalResult CIRToLLVMObjSizeOpLowering::matchAndRewrite(
3173 cir::ObjSizeOp op, OpAdaptor adaptor,
3174 mlir::ConversionPatternRewriter &rewriter)
const {
3175 mlir::Type llvmResTy = getTypeConverter()->convertType(op.getType());
3176 mlir::Location loc = op->getLoc();
3178 mlir::IntegerType i1Ty = rewriter.getI1Type();
3180 auto i1Val = [&rewriter, &loc, &i1Ty](
bool val) {
3181 return mlir::LLVM::ConstantOp::create(rewriter, loc, i1Ty, val);
3188 i1Val(op.getNullunknown()),
3189 i1Val(op.getDynamic()),
3192 return mlir::LogicalResult::success();
3197 if (mlir::Attribute tripleAttr =
3198 module->getAttr(cir::CIRDialect::getTripleAttrName()))
3199 module->setAttr(mlir::LLVM::LLVMDialect::getTargetTripleAttrName(),
3202 if (mlir::Attribute asmAttr =
3203 module->getAttr(cir::CIRDialect::getModuleLevelAsmAttrName()))
3204 module->setAttr(mlir::LLVM::LLVMDialect::getModuleLevelAsmAttrName(),
3209 llvm::TimeTraceScope scope(
"Convert CIR to LLVM Pass");
3211 mlir::ModuleOp module = getOperation();
3212 mlir::DataLayout dl(module);
3213 mlir::LLVMTypeConverter converter(&getContext());
3217 mlir::RewritePatternSet patterns(&getContext());
3220#define GET_LLVM_LOWERING_PATTERNS_LIST
3221#include "clang/CIR/Dialect/IR/CIRLowering.inc"
3222#undef GET_LLVM_LOWERING_PATTERNS_LIST
3223 >(converter, patterns.getContext(), lowerModule.get(), dl);
3227 mlir::ConversionTarget target(getContext());
3228 target.addLegalOp<mlir::ModuleOp>();
3229 target.addLegalDialect<mlir::LLVM::LLVMDialect>();
3230 target.addIllegalDialect<mlir::BuiltinDialect, cir::CIRDialect,
3231 mlir::func::FuncDialect>();
3234 ops.push_back(module);
3237 if (failed(applyPartialConversion(ops, target, std::move(patterns))))
3238 signalPassFailure();
3242 "llvm.global_ctors", [](mlir::Attribute attr) {
3243 auto ctorAttr = mlir::cast<cir::GlobalCtorAttr>(attr);
3244 return std::make_pair(ctorAttr.getName(),
3245 ctorAttr.getPriority());
3249 "llvm.global_dtors", [](mlir::Attribute attr) {
3250 auto dtorAttr = mlir::cast<cir::GlobalDtorAttr>(attr);
3251 return std::make_pair(dtorAttr.getName(),
3252 dtorAttr.getPriority());
3256mlir::LogicalResult CIRToLLVMBrOpLowering::matchAndRewrite(
3257 cir::BrOp op, OpAdaptor adaptor,
3258 mlir::ConversionPatternRewriter &rewriter)
const {
3259 rewriter.replaceOpWithNewOp<mlir::LLVM::BrOp>(op, adaptor.getOperands(),
3261 return mlir::LogicalResult::success();
3264mlir::LogicalResult CIRToLLVMGetMemberOpLowering::matchAndRewrite(
3265 cir::GetMemberOp op, OpAdaptor adaptor,
3266 mlir::ConversionPatternRewriter &rewriter)
const {
3267 mlir::Type llResTy = getTypeConverter()->convertType(op.getType());
3268 const auto recordTy =
3269 mlir::cast<cir::RecordType>(op.getAddrTy().getPointee());
3270 assert(recordTy &&
"expected record type");
3272 switch (recordTy.getKind()) {
3273 case cir::RecordType::Class:
3274 case cir::RecordType::Struct: {
3278 const mlir::Type elementTy = getTypeConverter()->convertType(recordTy);
3279 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, llResTy, elementTy,
3280 adaptor.getAddr(), offset);
3281 return mlir::success();
3283 case cir::RecordType::Union:
3286 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(op, llResTy,
3288 return mlir::success();
3292mlir::LogicalResult CIRToLLVMUnreachableOpLowering::matchAndRewrite(
3293 cir::UnreachableOp op, OpAdaptor adaptor,
3294 mlir::ConversionPatternRewriter &rewriter)
const {
3295 rewriter.replaceOpWithNewOp<mlir::LLVM::UnreachableOp>(op);
3296 return mlir::success();
3300 mlir::Operation *srcOp, llvm::StringRef fnName,
3302 auto modOp = srcOp->getParentOfType<mlir::ModuleOp>();
3303 auto enclosingFnOp = srcOp->getParentOfType<mlir::LLVM::LLVMFuncOp>();
3304 mlir::Operation *sourceSymbol =
3305 mlir::SymbolTable::lookupSymbolIn(modOp, fnName);
3306 if (!sourceSymbol) {
3307 mlir::OpBuilder::InsertionGuard guard(rewriter);
3308 rewriter.setInsertionPoint(enclosingFnOp);
3309 mlir::LLVM::LLVMFuncOp::create(rewriter, srcOp->getLoc(), fnName, fnTy);
3313mlir::LogicalResult CIRToLLVMThrowOpLowering::matchAndRewrite(
3314 cir::ThrowOp op, OpAdaptor adaptor,
3315 mlir::ConversionPatternRewriter &rewriter)
const {
3316 mlir::Location loc = op.getLoc();
3317 auto voidTy = mlir::LLVM::LLVMVoidType::get(getContext());
3319 if (op.rethrows()) {
3320 auto funcTy = mlir::LLVM::LLVMFunctionType::get(voidTy, {});
3323 const llvm::StringRef functionName =
"__cxa_rethrow";
3326 auto cxaRethrow = mlir::LLVM::CallOp::create(
3327 rewriter, loc, mlir::TypeRange{}, functionName);
3329 rewriter.replaceOp(op, cxaRethrow);
3330 return mlir::success();
3333 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3334 auto fnTy = mlir::LLVM::LLVMFunctionType::get(
3335 voidTy, {llvmPtrTy, llvmPtrTy, llvmPtrTy});
3338 const llvm::StringRef fnName =
"__cxa_throw";
3341 mlir::Value typeInfo = mlir::LLVM::AddressOfOp::create(
3342 rewriter, loc, mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
3343 adaptor.getTypeInfoAttr());
3347 dtor = mlir::LLVM::AddressOfOp::create(rewriter, loc, llvmPtrTy,
3348 adaptor.getDtorAttr());
3350 dtor = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmPtrTy);
3353 auto cxaThrowCall = mlir::LLVM::CallOp::create(
3354 rewriter, loc, mlir::TypeRange{}, fnName,
3355 mlir::ValueRange{adaptor.getExceptionPtr(), typeInfo, dtor});
3357 rewriter.replaceOp(op, cxaThrowCall);
3358 return mlir::success();
3361mlir::LogicalResult CIRToLLVMAllocExceptionOpLowering::matchAndRewrite(
3362 cir::AllocExceptionOp op, OpAdaptor adaptor,
3363 mlir::ConversionPatternRewriter &rewriter)
const {
3365 StringRef fnName =
"__cxa_allocate_exception";
3366 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3367 auto int64Ty = mlir::IntegerType::get(rewriter.getContext(), 64);
3368 auto fnTy = mlir::LLVM::LLVMFunctionType::get(llvmPtrTy, {int64Ty});
3371 auto exceptionSize = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
3372 adaptor.getSizeAttr());
3374 auto allocaExceptionCall = mlir::LLVM::CallOp::create(
3375 rewriter, op.getLoc(), mlir::TypeRange{llvmPtrTy}, fnName,
3376 mlir::ValueRange{exceptionSize});
3378 rewriter.replaceOp(op, allocaExceptionCall);
3379 return mlir::success();
3382static mlir::LLVM::LLVMStructType
3385 mlir::MLIRContext *ctx = rewriter.getContext();
3386 auto llvmPtr = mlir::LLVM::LLVMPointerType::get(ctx);
3388 return mlir::LLVM::LLVMStructType::getLiteral(ctx, structFields);
3391mlir::LogicalResult CIRToLLVMEhInflightOpLowering::matchAndRewrite(
3392 cir::EhInflightOp op, OpAdaptor adaptor,
3393 mlir::ConversionPatternRewriter &rewriter)
const {
3394 auto llvmFn = op->getParentOfType<mlir::LLVM::LLVMFuncOp>();
3395 assert(llvmFn &&
"expected LLVM function parent");
3396 mlir::Block *entryBlock = &llvmFn.getRegion().front();
3397 assert(entryBlock->isEntryBlock());
3399 mlir::ArrayAttr catchListAttr = op.getCatchTypeListAttr();
3400 mlir::SmallVector<mlir::Value> catchSymAddrs;
3402 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3403 mlir::Location loc = op.getLoc();
3408 if (catchListAttr) {
3411 for (mlir::Attribute catchAttr : catchListAttr) {
3412 auto symAttr = cast<mlir::FlatSymbolRefAttr>(catchAttr);
3415 mlir::OpBuilder::InsertionGuard guard(rewriter);
3416 rewriter.setInsertionPointToStart(entryBlock);
3417 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
3418 rewriter, loc, llvmPtrTy, symAttr.getValue());
3419 catchSymAddrs.push_back(addrOp);
3421 }
else if (!op.getCleanup()) {
3425 mlir::OpBuilder::InsertionGuard guard(rewriter);
3426 rewriter.setInsertionPointToStart(entryBlock);
3427 mlir::Value nullOp = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmPtrTy);
3428 catchSymAddrs.push_back(nullOp);
3433 mlir::LLVM::LLVMStructType llvmLandingPadStructTy =
3435 auto landingPadOp = mlir::LLVM::LandingpadOp::create(
3436 rewriter, loc, llvmLandingPadStructTy, catchSymAddrs);
3438 if (op.getCleanup())
3439 landingPadOp.setCleanup(
true);
3442 mlir::LLVM::ExtractValueOp::create(rewriter, loc, landingPadOp, 0);
3443 mlir::Value selector =
3444 mlir::LLVM::ExtractValueOp::create(rewriter, loc, landingPadOp, 1);
3445 rewriter.replaceOp(op, mlir::ValueRange{slot, selector});
3447 return mlir::success();
3450mlir::LogicalResult CIRToLLVMResumeFlatOpLowering::matchAndRewrite(
3451 cir::ResumeFlatOp op, OpAdaptor adaptor,
3452 mlir::ConversionPatternRewriter &rewriter)
const {
3457 mlir::Value poison = mlir::LLVM::PoisonOp::create(rewriter, op.getLoc(),
3458 llvmLandingPadStructTy);
3460 SmallVector<int64_t> slotIdx = {0};
3461 mlir::Value slot = mlir::LLVM::InsertValueOp::create(
3462 rewriter, op.getLoc(), poison, adaptor.getExceptionPtr(), slotIdx);
3464 SmallVector<int64_t> selectorIdx = {1};
3465 mlir::Value selector = mlir::LLVM::InsertValueOp::create(
3466 rewriter, op.getLoc(), slot, adaptor.getTypeId(), selectorIdx);
3468 rewriter.replaceOpWithNewOp<mlir::LLVM::ResumeOp>(op, selector);
3469 return mlir::success();
3472mlir::LogicalResult CIRToLLVMTrapOpLowering::matchAndRewrite(
3473 cir::TrapOp op, OpAdaptor adaptor,
3474 mlir::ConversionPatternRewriter &rewriter)
const {
3475 mlir::Location loc = op->getLoc();
3476 rewriter.eraseOp(op);
3478 mlir::LLVM::Trap::create(rewriter, loc);
3483 mlir::LLVM::UnreachableOp::create(rewriter, loc);
3485 return mlir::success();
3490 mlir::ConversionPatternRewriter &rewriter,
3491 const mlir::TypeConverter *converter,
3492 mlir::FlatSymbolRefAttr nameAttr, mlir::Type &eltType) {
3493 auto module = op->getParentOfType<mlir::ModuleOp>();
3494 mlir::Operation *symbol = mlir::SymbolTable::lookupSymbolIn(module, nameAttr);
3495 if (
auto llvmSymbol = mlir::dyn_cast<mlir::LLVM::GlobalOp>(symbol)) {
3496 eltType = llvmSymbol.getType();
3497 }
else if (
auto cirSymbol = mlir::dyn_cast<cir::GlobalOp>(symbol)) {
3498 eltType = converter->convertType(cirSymbol.getSymType());
3500 op->emitError() <<
"unexpected symbol type for " << symbol;
3504 return mlir::LLVM::AddressOfOp::create(
3505 rewriter, op->getLoc(),
3506 mlir::LLVM::LLVMPointerType::get(op->getContext()), nameAttr.getValue());
3509mlir::LogicalResult CIRToLLVMVTableAddrPointOpLowering::matchAndRewrite(
3510 cir::VTableAddrPointOp op, OpAdaptor adaptor,
3511 mlir::ConversionPatternRewriter &rewriter)
const {
3512 const mlir::TypeConverter *converter = getTypeConverter();
3513 mlir::Type targetType = converter->convertType(op.getType());
3517 op.getNameAttr(), eltType);
3519 return op.emitError() <<
"Unable to get value for vtable symbol";
3522 0, op.getAddressPointAttr().getIndex(),
3523 op.getAddressPointAttr().getOffset()};
3525 assert(eltType &&
"Shouldn't ever be missing an eltType here");
3526 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
3527 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
3528 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, targetType, eltType,
3529 symAddr, offsets, inboundsNuw);
3530 return mlir::success();
3533mlir::LogicalResult CIRToLLVMVTableGetVPtrOpLowering::matchAndRewrite(
3534 cir::VTableGetVPtrOp op, OpAdaptor adaptor,
3535 mlir::ConversionPatternRewriter &rewriter)
const {
3539 mlir::Value srcVal = adaptor.getSrc();
3540 rewriter.replaceOp(op, srcVal);
3541 return mlir::success();
3544mlir::LogicalResult CIRToLLVMVTableGetVirtualFnAddrOpLowering::matchAndRewrite(
3545 cir::VTableGetVirtualFnAddrOp op, OpAdaptor adaptor,
3546 mlir::ConversionPatternRewriter &rewriter)
const {
3547 mlir::Type targetType = getTypeConverter()->convertType(op.getType());
3548 auto eltType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3549 llvm::SmallVector<mlir::LLVM::GEPArg> offsets =
3550 llvm::SmallVector<mlir::LLVM::GEPArg>{op.getIndex()};
3551 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
3552 op, targetType, eltType, adaptor.getVptr(), offsets,
3553 mlir::LLVM::GEPNoWrapFlags::inbounds);
3554 return mlir::success();
3557mlir::LogicalResult CIRToLLVMVTTAddrPointOpLowering::matchAndRewrite(
3558 cir::VTTAddrPointOp op, OpAdaptor adaptor,
3559 mlir::ConversionPatternRewriter &rewriter)
const {
3560 const mlir::Type resultType = getTypeConverter()->convertType(op.getType());
3561 llvm::SmallVector<mlir::LLVM::GEPArg> offsets;
3563 mlir::Value llvmAddr = adaptor.getSymAddr();
3565 if (op.getSymAddr()) {
3566 if (op.getOffset() == 0) {
3567 rewriter.replaceOp(op, {llvmAddr});
3568 return mlir::success();
3571 offsets.push_back(adaptor.getOffset());
3572 eltType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3575 op.getNameAttr(), eltType);
3576 assert(eltType &&
"Shouldn't ever be missing an eltType here");
3577 offsets.push_back(0);
3578 offsets.push_back(adaptor.getOffset());
3580 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
3581 op, resultType, eltType, llvmAddr, offsets,
3582 mlir::LLVM::GEPNoWrapFlags::inbounds);
3583 return mlir::success();
3586mlir::LogicalResult CIRToLLVMStackSaveOpLowering::matchAndRewrite(
3587 cir::StackSaveOp op, OpAdaptor adaptor,
3588 mlir::ConversionPatternRewriter &rewriter)
const {
3589 const mlir::Type ptrTy = getTypeConverter()->convertType(op.getType());
3590 rewriter.replaceOpWithNewOp<mlir::LLVM::StackSaveOp>(op, ptrTy);
3591 return mlir::success();
3594mlir::LogicalResult CIRToLLVMStackRestoreOpLowering::matchAndRewrite(
3595 cir::StackRestoreOp op, OpAdaptor adaptor,
3596 mlir::ConversionPatternRewriter &rewriter)
const {
3597 rewriter.replaceOpWithNewOp<mlir::LLVM::StackRestoreOp>(op, adaptor.getPtr());
3598 return mlir::success();
3601mlir::LogicalResult CIRToLLVMVecCreateOpLowering::matchAndRewrite(
3602 cir::VecCreateOp op, OpAdaptor adaptor,
3603 mlir::ConversionPatternRewriter &rewriter)
const {
3606 const auto vecTy = mlir::cast<cir::VectorType>(op.getType());
3607 const mlir::Type llvmTy = typeConverter->convertType(vecTy);
3608 const mlir::Location loc = op.getLoc();
3609 mlir::Value result = mlir::LLVM::PoisonOp::create(rewriter, loc, llvmTy);
3610 assert(vecTy.getSize() == op.getElements().size() &&
3611 "cir.vec.create op count doesn't match vector type elements count");
3613 for (uint64_t i = 0; i < vecTy.getSize(); ++i) {
3614 const mlir::Value indexValue =
3615 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
3616 result = mlir::LLVM::InsertElementOp::create(
3617 rewriter, loc, result, adaptor.getElements()[i], indexValue);
3620 rewriter.replaceOp(op, result);
3621 return mlir::success();
3624mlir::LogicalResult CIRToLLVMVecExtractOpLowering::matchAndRewrite(
3625 cir::VecExtractOp op, OpAdaptor adaptor,
3626 mlir::ConversionPatternRewriter &rewriter)
const {
3627 rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractElementOp>(
3628 op, adaptor.getVec(), adaptor.getIndex());
3629 return mlir::success();
3632mlir::LogicalResult CIRToLLVMVecInsertOpLowering::matchAndRewrite(
3633 cir::VecInsertOp op, OpAdaptor adaptor,
3634 mlir::ConversionPatternRewriter &rewriter)
const {
3635 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertElementOp>(
3636 op, adaptor.getVec(), adaptor.getValue(), adaptor.getIndex());
3637 return mlir::success();
3640mlir::LogicalResult CIRToLLVMVecCmpOpLowering::matchAndRewrite(
3641 cir::VecCmpOp op, OpAdaptor adaptor,
3642 mlir::ConversionPatternRewriter &rewriter)
const {
3643 mlir::Type elementType = elementTypeIfVector(op.getLhs().getType());
3644 mlir::Value bitResult;
3645 if (
auto intType = mlir::dyn_cast<cir::IntType>(elementType)) {
3646 bitResult = mlir::LLVM::ICmpOp::create(
3647 rewriter, op.getLoc(),
3649 adaptor.getLhs(), adaptor.getRhs());
3650 }
else if (mlir::isa<cir::FPTypeInterface>(elementType)) {
3651 bitResult = mlir::LLVM::FCmpOp::create(
3653 adaptor.getLhs(), adaptor.getRhs());
3655 return op.emitError() <<
"unsupported type for VecCmpOp: " << elementType;
3661 if (cast<cir::IntType>(cast<cir::VectorType>(op.getType()).getElementType())
3663 rewriter.replaceOpWithNewOp<mlir::LLVM::SExtOp>(
3664 op, typeConverter->convertType(op.getType()), bitResult);
3666 rewriter.replaceOp(op, bitResult);
3667 return mlir::success();
3670mlir::LogicalResult CIRToLLVMVecSplatOpLowering::matchAndRewrite(
3671 cir::VecSplatOp op, OpAdaptor adaptor,
3672 mlir::ConversionPatternRewriter &rewriter)
const {
3678 cir::VectorType vecTy = op.getType();
3679 mlir::Type llvmTy = typeConverter->convertType(vecTy);
3680 mlir::Location loc = op.getLoc();
3681 mlir::Value poison = mlir::LLVM::PoisonOp::create(rewriter, loc, llvmTy);
3683 mlir::Value elementValue = adaptor.getValue();
3684 if (elementValue.getDefiningOp<mlir::LLVM::PoisonOp>()) {
3687 rewriter.replaceOp(op, poison);
3688 return mlir::success();
3691 if (
auto constValue = elementValue.getDefiningOp<mlir::LLVM::ConstantOp>()) {
3692 if (
auto intAttr = dyn_cast<mlir::IntegerAttr>(constValue.getValue())) {
3693 mlir::DenseIntElementsAttr denseVec = mlir::DenseIntElementsAttr::get(
3694 mlir::cast<mlir::ShapedType>(llvmTy), intAttr.getValue());
3695 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
3696 op, denseVec.getType(), denseVec);
3697 return mlir::success();
3700 if (
auto fpAttr = dyn_cast<mlir::FloatAttr>(constValue.getValue())) {
3701 mlir::DenseFPElementsAttr denseVec = mlir::DenseFPElementsAttr::get(
3702 mlir::cast<mlir::ShapedType>(llvmTy), fpAttr.getValue());
3703 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
3704 op, denseVec.getType(), denseVec);
3705 return mlir::success();
3709 mlir::Value indexValue =
3710 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), 0);
3711 mlir::Value oneElement = mlir::LLVM::InsertElementOp::create(
3712 rewriter, loc, poison, elementValue, indexValue);
3713 SmallVector<int32_t> zeroValues(vecTy.getSize(), 0);
3714 rewriter.replaceOpWithNewOp<mlir::LLVM::ShuffleVectorOp>(op, oneElement,
3715 poison, zeroValues);
3716 return mlir::success();
3719mlir::LogicalResult CIRToLLVMVecShuffleOpLowering::matchAndRewrite(
3720 cir::VecShuffleOp op, OpAdaptor adaptor,
3721 mlir::ConversionPatternRewriter &rewriter)
const {
3725 SmallVector<int, 8> indices;
3727 op.getIndices().begin(), op.getIndices().end(),
3728 std::back_inserter(indices), [](mlir::Attribute intAttr) {
3729 return mlir::cast<cir::IntAttr>(intAttr).getValue().getSExtValue();
3731 rewriter.replaceOpWithNewOp<mlir::LLVM::ShuffleVectorOp>(
3732 op, adaptor.getVec1(), adaptor.getVec2(), indices);
3733 return mlir::success();
3736mlir::LogicalResult CIRToLLVMVecShuffleDynamicOpLowering::matchAndRewrite(
3737 cir::VecShuffleDynamicOp op, OpAdaptor adaptor,
3738 mlir::ConversionPatternRewriter &rewriter)
const {
3750 mlir::Location loc = op.getLoc();
3751 mlir::Value input = adaptor.getVec();
3752 mlir::Type llvmIndexVecType =
3753 getTypeConverter()->convertType(op.getIndices().getType());
3754 mlir::Type llvmIndexType = getTypeConverter()->convertType(
3755 elementTypeIfVector(op.getIndices().getType()));
3757 mlir::cast<cir::VectorType>(op.getVec().getType()).getSize();
3759 uint64_t maskBits = llvm::NextPowerOf2(numElements - 1) - 1;
3760 mlir::Value maskValue = mlir::LLVM::ConstantOp::create(
3761 rewriter, loc, llvmIndexType,
3762 rewriter.getIntegerAttr(llvmIndexType, maskBits));
3763 mlir::Value maskVector =
3764 mlir::LLVM::UndefOp::create(rewriter, loc, llvmIndexVecType);
3766 for (uint64_t i = 0; i < numElements; ++i) {
3767 mlir::Value idxValue =
3768 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
3769 maskVector = mlir::LLVM::InsertElementOp::create(rewriter, loc, maskVector,
3770 maskValue, idxValue);
3773 mlir::Value maskedIndices = mlir::LLVM::AndOp::create(
3774 rewriter, loc, llvmIndexVecType, adaptor.getIndices(), maskVector);
3775 mlir::Value result = mlir::LLVM::UndefOp::create(
3776 rewriter, loc, getTypeConverter()->convertType(op.getVec().getType()));
3777 for (uint64_t i = 0; i < numElements; ++i) {
3778 mlir::Value iValue =
3779 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
3780 mlir::Value indexValue = mlir::LLVM::ExtractElementOp::create(
3781 rewriter, loc, maskedIndices, iValue);
3782 mlir::Value valueAtIndex =
3783 mlir::LLVM::ExtractElementOp::create(rewriter, loc, input, indexValue);
3784 result = mlir::LLVM::InsertElementOp::create(rewriter, loc, result,
3785 valueAtIndex, iValue);
3787 rewriter.replaceOp(op, result);
3788 return mlir::success();
3791mlir::LogicalResult CIRToLLVMVecTernaryOpLowering::matchAndRewrite(
3792 cir::VecTernaryOp op, OpAdaptor adaptor,
3793 mlir::ConversionPatternRewriter &rewriter)
const {
3795 mlir::Value bitVec = mlir::LLVM::ICmpOp::create(
3796 rewriter, op.getLoc(), mlir::LLVM::ICmpPredicate::ne, adaptor.getCond(),
3797 mlir::LLVM::ZeroOp::create(
3798 rewriter, op.getCond().getLoc(),
3799 typeConverter->convertType(op.getCond().getType())));
3800 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(
3801 op, bitVec, adaptor.getLhs(), adaptor.getRhs());
3802 return mlir::success();
3805mlir::LogicalResult CIRToLLVMComplexAddOpLowering::matchAndRewrite(
3806 cir::ComplexAddOp op, OpAdaptor adaptor,
3807 mlir::ConversionPatternRewriter &rewriter)
const {
3808 mlir::Value lhs = adaptor.getLhs();
3809 mlir::Value rhs = adaptor.getRhs();
3810 mlir::Location loc = op.getLoc();
3812 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
3813 mlir::Type complexElemTy =
3814 getTypeConverter()->convertType(
complexType.getElementType());
3815 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
3816 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{0}));
3817 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
3818 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{1}));
3819 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
3820 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{0}));
3821 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
3822 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{1}));
3824 mlir::Value newReal;
3825 mlir::Value newImag;
3826 if (complexElemTy.isInteger()) {
3827 newReal = mlir::LLVM::AddOp::create(rewriter, loc, complexElemTy, lhsReal,
3829 newImag = mlir::LLVM::AddOp::create(rewriter, loc, complexElemTy, lhsImag,
3834 newReal = mlir::LLVM::FAddOp::create(rewriter, loc, complexElemTy, lhsReal,
3836 newImag = mlir::LLVM::FAddOp::create(rewriter, loc, complexElemTy, lhsImag,
3840 mlir::Type complexLLVMTy =
3841 getTypeConverter()->convertType(op.getResult().getType());
3842 auto initialComplex =
3843 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), complexLLVMTy);
3845 auto realComplex = mlir::LLVM::InsertValueOp::create(
3846 rewriter, op->getLoc(), initialComplex, newReal, ArrayRef(int64_t{0}));
3848 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
3849 op, realComplex, newImag, ArrayRef(int64_t{1}));
3851 return mlir::success();
3854mlir::LogicalResult CIRToLLVMComplexCreateOpLowering::matchAndRewrite(
3855 cir::ComplexCreateOp op, OpAdaptor adaptor,
3856 mlir::ConversionPatternRewriter &rewriter)
const {
3857 mlir::Type complexLLVMTy =
3858 getTypeConverter()->convertType(op.getResult().getType());
3859 auto initialComplex =
3860 mlir::LLVM::UndefOp::create(rewriter, op->getLoc(), complexLLVMTy);
3862 auto realComplex = mlir::LLVM::InsertValueOp::create(
3863 rewriter, op->getLoc(), initialComplex, adaptor.getReal(),
3864 ArrayRef(int64_t{0}));
3866 auto complex = mlir::LLVM::InsertValueOp::create(
3867 rewriter, op->getLoc(), realComplex, adaptor.getImag(),
3868 ArrayRef(int64_t{1}));
3870 rewriter.replaceOp(op, complex);
3871 return mlir::success();
3874mlir::LogicalResult CIRToLLVMComplexRealOpLowering::matchAndRewrite(
3875 cir::ComplexRealOp op, OpAdaptor adaptor,
3876 mlir::ConversionPatternRewriter &rewriter)
const {
3877 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
3878 mlir::Value operand = adaptor.getOperand();
3879 if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) {
3880 operand = mlir::LLVM::ExtractValueOp::create(
3881 rewriter, op.getLoc(), resultLLVMTy, operand,
3882 llvm::ArrayRef<std::int64_t>{0});
3884 rewriter.replaceOp(op, operand);
3885 return mlir::success();
3888mlir::LogicalResult CIRToLLVMComplexSubOpLowering::matchAndRewrite(
3889 cir::ComplexSubOp op, OpAdaptor adaptor,
3890 mlir::ConversionPatternRewriter &rewriter)
const {
3891 mlir::Value lhs = adaptor.getLhs();
3892 mlir::Value rhs = adaptor.getRhs();
3893 mlir::Location loc = op.getLoc();
3895 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
3896 mlir::Type complexElemTy =
3897 getTypeConverter()->convertType(
complexType.getElementType());
3898 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
3899 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{0}));
3900 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
3901 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{1}));
3902 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
3903 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{0}));
3904 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
3905 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{1}));
3907 mlir::Value newReal;
3908 mlir::Value newImag;
3909 if (complexElemTy.isInteger()) {
3910 newReal = mlir::LLVM::SubOp::create(rewriter, loc, complexElemTy, lhsReal,
3912 newImag = mlir::LLVM::SubOp::create(rewriter, loc, complexElemTy, lhsImag,
3917 newReal = mlir::LLVM::FSubOp::create(rewriter, loc, complexElemTy, lhsReal,
3919 newImag = mlir::LLVM::FSubOp::create(rewriter, loc, complexElemTy, lhsImag,
3923 mlir::Type complexLLVMTy =
3924 getTypeConverter()->convertType(op.getResult().getType());
3925 auto initialComplex =
3926 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), complexLLVMTy);
3928 auto realComplex = mlir::LLVM::InsertValueOp::create(
3929 rewriter, op->getLoc(), initialComplex, newReal, ArrayRef(int64_t{0}));
3931 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
3932 op, realComplex, newImag, ArrayRef(int64_t{1}));
3934 return mlir::success();
3937mlir::LogicalResult CIRToLLVMComplexImagOpLowering::matchAndRewrite(
3938 cir::ComplexImagOp op, OpAdaptor adaptor,
3939 mlir::ConversionPatternRewriter &rewriter)
const {
3940 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
3941 mlir::Value operand = adaptor.getOperand();
3942 mlir::Location loc = op.getLoc();
3944 if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) {
3945 operand = mlir::LLVM::ExtractValueOp::create(
3946 rewriter, loc, resultLLVMTy, operand, llvm::ArrayRef<std::int64_t>{1});
3948 mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(resultLLVMTy);
3950 mlir::LLVM::ConstantOp::create(rewriter, loc, resultLLVMTy, zeroAttr);
3953 rewriter.replaceOp(op, operand);
3954 return mlir::success();
3958 mlir::MLIRContext *context,
3959 unsigned &storageSize) {
3960 return TypeSwitch<mlir::Type, mlir::IntegerType>(storageType)
3961 .Case<cir::ArrayType>([&](cir::ArrayType atTy) {
3962 storageSize = atTy.getSize() * 8;
3963 return mlir::IntegerType::get(context, storageSize);
3965 .Case<cir::IntType>([&](cir::IntType intTy) {
3966 storageSize = intTy.getWidth();
3967 return mlir::IntegerType::get(context, storageSize);
3969 .Default([](mlir::Type) -> mlir::IntegerType {
3971 "Either ArrayType or IntType expected for bitfields storage");
3975mlir::LogicalResult CIRToLLVMSetBitfieldOpLowering::matchAndRewrite(
3976 cir::SetBitfieldOp op, OpAdaptor adaptor,
3977 mlir::ConversionPatternRewriter &rewriter)
const {
3978 mlir::OpBuilder::InsertionGuard guard(rewriter);
3979 rewriter.setInsertionPoint(op);
3981 cir::BitfieldInfoAttr info = op.getBitfieldInfo();
3982 uint64_t size = info.getSize();
3983 uint64_t offset = info.getOffset();
3984 mlir::Type storageType = info.getStorageType();
3985 mlir::MLIRContext *context = storageType.getContext();
3987 unsigned storageSize = 0;
3989 mlir::IntegerType intType =
3992 mlir::Value srcVal =
createIntCast(rewriter, adaptor.getSrc(), intType);
3993 unsigned srcWidth = storageSize;
3994 mlir::Value resultVal = srcVal;
3996 if (storageSize != size) {
3997 assert(storageSize > size &&
"Invalid bitfield size.");
3999 mlir::Value val = mlir::LLVM::LoadOp::create(
4000 rewriter, op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(),
4001 op.getIsVolatile());
4004 createAnd(rewriter, srcVal, llvm::APInt::getLowBitsSet(srcWidth, size));
4006 srcVal =
createShL(rewriter, srcVal, offset);
4010 ~llvm::APInt::getBitsSet(srcWidth, offset, offset + size));
4013 srcVal = mlir::LLVM::OrOp::create(rewriter, op.getLoc(), val, srcVal);
4016 mlir::LLVM::StoreOp::create(rewriter, op.getLoc(), srcVal, adaptor.getAddr(),
4017 op.getAlignment(), op.getIsVolatile());
4019 mlir::Type resultTy = getTypeConverter()->convertType(op.getType());
4021 if (info.getIsSigned()) {
4022 assert(size <= storageSize);
4023 unsigned highBits = storageSize - size;
4026 resultVal =
createShL(rewriter, resultVal, highBits);
4027 resultVal =
createAShR(rewriter, resultVal, highBits);
4032 mlir::cast<mlir::IntegerType>(resultTy),
4033 info.getIsSigned());
4035 rewriter.replaceOp(op, resultVal);
4036 return mlir::success();
4039mlir::LogicalResult CIRToLLVMComplexImagPtrOpLowering::matchAndRewrite(
4040 cir::ComplexImagPtrOp op, OpAdaptor adaptor,
4041 mlir::ConversionPatternRewriter &rewriter)
const {
4042 cir::PointerType operandTy = op.getOperand().getType();
4043 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
4044 mlir::Type elementLLVMTy =
4045 getTypeConverter()->convertType(operandTy.getPointee());
4047 mlir::LLVM::GEPArg gepIndices[2] = {{0}, {1}};
4048 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
4049 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
4050 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
4051 op, resultLLVMTy, elementLLVMTy, adaptor.getOperand(), gepIndices,
4053 return mlir::success();
4056mlir::LogicalResult CIRToLLVMComplexRealPtrOpLowering::matchAndRewrite(
4057 cir::ComplexRealPtrOp op, OpAdaptor adaptor,
4058 mlir::ConversionPatternRewriter &rewriter)
const {
4059 cir::PointerType operandTy = op.getOperand().getType();
4060 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
4061 mlir::Type elementLLVMTy =
4062 getTypeConverter()->convertType(operandTy.getPointee());
4064 mlir::LLVM::GEPArg gepIndices[2] = {0, 0};
4065 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
4066 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
4067 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
4068 op, resultLLVMTy, elementLLVMTy, adaptor.getOperand(), gepIndices,
4070 return mlir::success();
4073mlir::LogicalResult CIRToLLVMGetBitfieldOpLowering::matchAndRewrite(
4074 cir::GetBitfieldOp op, OpAdaptor adaptor,
4075 mlir::ConversionPatternRewriter &rewriter)
const {
4077 mlir::OpBuilder::InsertionGuard guard(rewriter);
4078 rewriter.setInsertionPoint(op);
4080 cir::BitfieldInfoAttr info = op.getBitfieldInfo();
4082 uint64_t offset = info.getOffset();
4083 mlir::Type storageType = info.getStorageType();
4084 mlir::MLIRContext *context = storageType.getContext();
4085 unsigned storageSize = 0;
4087 mlir::IntegerType intType =
4090 mlir::Value val = mlir::LLVM::LoadOp::create(
4091 rewriter, op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(),
4092 op.getIsVolatile());
4093 val = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), intType, val);
4095 if (info.getIsSigned()) {
4096 assert(
static_cast<unsigned>(offset + size) <= storageSize);
4097 unsigned highBits = storageSize - offset - size;
4098 val =
createShL(rewriter, val, highBits);
4099 val =
createAShR(rewriter, val, offset + highBits);
4103 if (
static_cast<unsigned>(offset) + size < storageSize)
4105 llvm::APInt::getLowBitsSet(storageSize, size));
4108 mlir::Type resTy = getTypeConverter()->convertType(op.getType());
4110 rewriter, val, mlir::cast<mlir::IntegerType>(resTy), info.getIsSigned());
4111 rewriter.replaceOp(op, newOp);
4112 return mlir::success();
4115mlir::LogicalResult CIRToLLVMIsConstantOpLowering::matchAndRewrite(
4116 cir::IsConstantOp op, OpAdaptor adaptor,
4117 mlir::ConversionPatternRewriter &rewriter)
const {
4118 rewriter.replaceOpWithNewOp<mlir::LLVM::IsConstantOp>(op, adaptor.getVal());
4119 return mlir::success();
4122mlir::LogicalResult CIRToLLVMInlineAsmOpLowering::matchAndRewrite(
4123 cir::InlineAsmOp op, OpAdaptor adaptor,
4124 mlir::ConversionPatternRewriter &rewriter)
const {
4126 if (op.getNumResults())
4127 llResTy = getTypeConverter()->convertType(op.getType(0));
4129 cir::AsmFlavor dialect = op.getAsmFlavor();
4130 mlir::LLVM::AsmDialect llDialect = dialect == cir::AsmFlavor::x86_att
4131 ? mlir::LLVM::AsmDialect::AD_ATT
4132 : mlir::LLVM::AsmDialect::AD_Intel;
4134 SmallVector<mlir::Attribute> opAttrs;
4135 StringRef llvmAttrName = mlir::LLVM::InlineAsmOp::getElementTypeAttrName();
4141 if (!op.getNumResults())
4142 opAttrs.push_back(mlir::Attribute());
4144 SmallVector<mlir::Value> llvmOperands;
4145 SmallVector<mlir::Value> cirOperands;
4146 for (
auto const &[llvmOp, cirOp] :
4147 zip(adaptor.getAsmOperands(), op.getAsmOperands())) {
4148 append_range(llvmOperands, llvmOp);
4149 append_range(cirOperands, cirOp);
4154 for (
auto const &[cirOpAttr, cirOp] :
4155 zip(op.getOperandAttrs(), cirOperands)) {
4157 opAttrs.push_back(mlir::Attribute());
4161 llvm::SmallVector<mlir::NamedAttribute, 1> attrs;
4162 cir::PointerType typ = mlir::cast<cir::PointerType>(cirOp.getType());
4164 *getTypeConverter(), dataLayout, typ.getPointee()));
4166 attrs.push_back(rewriter.getNamedAttr(llvmAttrName, typAttr));
4167 mlir::DictionaryAttr newDict = rewriter.getDictionaryAttr(attrs);
4168 opAttrs.push_back(newDict);
4171 rewriter.replaceOpWithNewOp<mlir::LLVM::InlineAsmOp>(
4172 op, llResTy, llvmOperands, op.getAsmStringAttr(), op.getConstraintsAttr(),
4173 op.getSideEffectsAttr(),
4176 mlir::LLVM::TailCallKindAttr::get(
4177 getContext(), mlir::LLVM::tailcallkind::TailCallKind::None),
4178 mlir::LLVM::AsmDialectAttr::get(getContext(), llDialect),
4179 rewriter.getArrayAttr(opAttrs));
4181 return mlir::success();
4184mlir::LogicalResult CIRToLLVMVAStartOpLowering::matchAndRewrite(
4185 cir::VAStartOp op, OpAdaptor adaptor,
4186 mlir::ConversionPatternRewriter &rewriter)
const {
4187 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4188 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4189 adaptor.getArgList());
4190 rewriter.replaceOpWithNewOp<mlir::LLVM::VaStartOp>(op, vaList);
4191 return mlir::success();
4194mlir::LogicalResult CIRToLLVMVAEndOpLowering::matchAndRewrite(
4195 cir::VAEndOp op, OpAdaptor adaptor,
4196 mlir::ConversionPatternRewriter &rewriter)
const {
4197 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4198 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4199 adaptor.getArgList());
4200 rewriter.replaceOpWithNewOp<mlir::LLVM::VaEndOp>(op, vaList);
4201 return mlir::success();
4204mlir::LogicalResult CIRToLLVMVACopyOpLowering::matchAndRewrite(
4205 cir::VACopyOp op, OpAdaptor adaptor,
4206 mlir::ConversionPatternRewriter &rewriter)
const {
4207 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4208 auto dstList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4209 adaptor.getDstList());
4210 auto srcList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4211 adaptor.getSrcList());
4212 rewriter.replaceOpWithNewOp<mlir::LLVM::VaCopyOp>(op, dstList, srcList);
4213 return mlir::success();
4216mlir::LogicalResult CIRToLLVMVAArgOpLowering::matchAndRewrite(
4217 cir::VAArgOp op, OpAdaptor adaptor,
4218 mlir::ConversionPatternRewriter &rewriter)
const {
4220 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4221 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4222 adaptor.getArgList());
4224 mlir::Type llvmType =
4225 getTypeConverter()->convertType(op->getResultTypes().front());
4227 return mlir::failure();
4229 rewriter.replaceOpWithNewOp<mlir::LLVM::VaArgOp>(op, llvmType, vaList);
4230 return mlir::success();
4233mlir::LogicalResult CIRToLLVMBlockAddressOpLowering::matchAndRewrite(
4234 cir::BlockAddressOp op, OpAdaptor adaptor,
4235 mlir::ConversionPatternRewriter &rewriter)
const {
4236 return mlir::failure();
4239mlir::LogicalResult CIRToLLVMIndirectBrOpLowering::matchAndRewrite(
4240 cir::IndirectBrOp op, OpAdaptor adaptor,
4241 mlir::ConversionPatternRewriter &rewriter)
const {
4242 return mlir::failure();
4245mlir::LogicalResult CIRToLLVMAwaitOpLowering::matchAndRewrite(
4246 cir::AwaitOp op, OpAdaptor adaptor,
4247 mlir::ConversionPatternRewriter &rewriter)
const {
4248 return mlir::failure();
4252 return std::make_unique<ConvertCIRToLLVMPass>();
4260std::unique_ptr<llvm::Module>
4262 llvm::TimeTraceScope scope(
"lower from CIR to LLVM directly");
4264 mlir::MLIRContext *mlirCtx = mlirModule.getContext();
4266 mlir::PassManager pm(mlirCtx);
4269 (void)mlir::applyPassManagerCLOptions(pm);
4271 if (mlir::failed(pm.run(mlirModule))) {
4274 "The pass manager failed to lower CIR to LLVMIR dialect!");
4277 mlir::registerBuiltinDialectTranslation(*mlirCtx);
4278 mlir::registerLLVMDialectTranslation(*mlirCtx);
4281 llvm::TimeTraceScope translateScope(
"translateModuleToLLVMIR");
4283 StringRef moduleName = mlirModule.getName().value_or(
"CIRToLLVMModule");
4284 std::unique_ptr<llvm::Module> llvmModule =
4285 mlir::translateModuleToLLVMIR(mlirModule, llvmCtx, moduleName);
4289 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)