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::DataMemberAttr, cir::GlobalViewAttr,
262 cir::TypeInfoAttr, cir::UndefAttr, cir::VTableAttr,
263 cir::ZeroAttr>([&](
auto attrT) {
return visitCirAttr(attrT); })
264 .Default([&](
auto attrT) {
return mlir::Value(); });
269 mlir::Value
visitCirAttr(cir::ConstComplexAttr complexAttr);
282 mlir::Operation *parentOp;
283 mlir::ConversionPatternRewriter &rewriter;
284 const mlir::TypeConverter *converter;
290 const mlir::Attribute attr,
291 mlir::ConversionPatternRewriter &rewriter,
292 const mlir::TypeConverter *converter,
294 CIRAttrToValue valueConverter(parentOp, rewriter, converter, lowerMod);
295 mlir::Value value = valueConverter.
visit(attr);
297 llvm_unreachable(
"unhandled attribute type");
302 cir::SideEffect sideEffect,
303 mlir::LLVM::MemoryEffectsAttr &memoryEffect,
304 bool &noUnwind,
bool &willReturn) {
305 using mlir::LLVM::ModRefInfo;
307 switch (sideEffect) {
308 case cir::SideEffect::All:
310 noUnwind = isNothrow;
314 case cir::SideEffect::Pure:
315 memoryEffect = mlir::LLVM::MemoryEffectsAttr::get(
316 callOp->getContext(), ModRefInfo::Ref,
326 case cir::SideEffect::Const:
327 memoryEffect = mlir::LLVM::MemoryEffectsAttr::get(
328 callOp->getContext(), ModRefInfo::NoModRef,
329 ModRefInfo::NoModRef,
330 ModRefInfo::NoModRef,
331 ModRefInfo::NoModRef,
332 ModRefInfo::NoModRef,
333 ModRefInfo::NoModRef);
340static mlir::LLVM::CallIntrinsicOp
342 mlir::Location loc,
const llvm::Twine &intrinsicName,
343 mlir::Type resultTy, mlir::ValueRange operands) {
344 auto intrinsicNameAttr =
345 mlir::StringAttr::get(rewriter.getContext(), intrinsicName);
346 return mlir::LLVM::CallIntrinsicOp::create(rewriter, loc, resultTy,
347 intrinsicNameAttr, operands);
351 mlir::ConversionPatternRewriter &rewriter, mlir::Operation *op,
352 const llvm::Twine &intrinsicName, mlir::Type resultTy,
353 mlir::ValueRange operands) {
355 rewriter, op->getLoc(), intrinsicName, resultTy, operands);
356 rewriter.replaceOp(op, callIntrinOp.getOperation());
360mlir::LogicalResult CIRToLLVMLLVMIntrinsicCallOpLowering::matchAndRewrite(
361 cir::LLVMIntrinsicCallOp op, OpAdaptor adaptor,
362 mlir::ConversionPatternRewriter &rewriter)
const {
363 mlir::Type llvmResTy =
364 getTypeConverter()->convertType(op->getResultTypes()[0]);
366 return op.emitError(
"expected LLVM result type");
367 StringRef name = op.getIntrinsicName();
380 adaptor.getOperands());
381 return mlir::success();
386 mlir::Location loc = parentOp->getLoc();
387 return mlir::LLVM::ConstantOp::create(
388 rewriter, loc, converter->convertType(intAttr.getType()),
394 mlir::Location loc = parentOp->getLoc();
395 return mlir::LLVM::ConstantOp::create(
396 rewriter, loc, converter->convertType(fltAttr.getType()),
402 auto complexType = mlir::cast<cir::ComplexType>(complexAttr.getType());
403 mlir::Type complexElemTy = complexType.getElementType();
404 mlir::Type complexElemLLVMTy = converter->convertType(complexElemTy);
406 mlir::Attribute components[2];
407 if (
const auto intType = mlir::dyn_cast<cir::IntType>(complexElemTy)) {
408 components[0] = rewriter.getIntegerAttr(
410 mlir::cast<cir::IntAttr>(complexAttr.getReal()).getValue());
411 components[1] = rewriter.getIntegerAttr(
413 mlir::cast<cir::IntAttr>(complexAttr.getImag()).getValue());
415 components[0] = rewriter.getFloatAttr(
417 mlir::cast<cir::FPAttr>(complexAttr.getReal()).getValue());
418 components[1] = rewriter.getFloatAttr(
420 mlir::cast<cir::FPAttr>(complexAttr.getImag()).getValue());
423 mlir::Location loc = parentOp->getLoc();
424 return mlir::LLVM::ConstantOp::create(
425 rewriter, loc, converter->convertType(complexAttr.getType()),
426 rewriter.getArrayAttr(components));
431 mlir::Location loc = parentOp->getLoc();
432 if (ptrAttr.isNullValue()) {
433 return mlir::LLVM::ZeroOp::create(
434 rewriter, loc, converter->convertType(ptrAttr.getType()));
436 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
437 mlir::Value ptrVal = mlir::LLVM::ConstantOp::create(
439 rewriter.getIntegerType(layout.getTypeSizeInBits(ptrAttr.getType())),
440 ptrAttr.getValue().getInt());
441 return mlir::LLVM::IntToPtrOp::create(
442 rewriter, loc, converter->convertType(ptrAttr.getType()), ptrVal);
447 mlir::Type llvmTy = converter->convertType(attr.getType());
448 mlir::Location loc = parentOp->getLoc();
451 if (attr.hasTrailingZeros()) {
452 mlir::Type arrayTy = attr.getType();
453 result = mlir::LLVM::ZeroOp::create(rewriter, loc,
454 converter->convertType(arrayTy));
456 result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
460 if (
auto arrayAttr = mlir::dyn_cast<mlir::ArrayAttr>(attr.getElts())) {
461 for (
auto [idx, elt] : llvm::enumerate(arrayAttr)) {
462 mlir::DataLayout dataLayout(parentOp->getParentOfType<mlir::ModuleOp>());
463 mlir::Value init =
visit(elt);
465 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
467 }
else if (
auto strAttr = mlir::dyn_cast<mlir::StringAttr>(attr.getElts())) {
470 auto arrayTy = mlir::dyn_cast<cir::ArrayType>(strAttr.getType());
471 assert(arrayTy &&
"String attribute must have an array type");
472 mlir::Type eltTy = arrayTy.getElementType();
473 for (
auto [idx, elt] : llvm::enumerate(strAttr)) {
474 auto init = mlir::LLVM::ConstantOp::create(
475 rewriter, loc, converter->convertType(eltTy), elt);
477 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
480 llvm_unreachable(
"unexpected ConstArrayAttr elements");
488 const mlir::Type llvmTy = converter->convertType(constRecord.getType());
489 const mlir::Location loc = parentOp->getLoc();
490 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
493 for (
auto [idx, elt] : llvm::enumerate(constRecord.getMembers())) {
494 mlir::Value init =
visit(elt);
496 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
504 const mlir::Type llvmTy = converter->convertType(attr.getType());
505 const mlir::Location loc = parentOp->getLoc();
508 for (
const mlir::Attribute elementAttr : attr.getElts()) {
509 mlir::Attribute mlirAttr;
510 if (
auto intAttr = mlir::dyn_cast<cir::IntAttr>(elementAttr)) {
511 mlirAttr = rewriter.getIntegerAttr(
512 converter->convertType(intAttr.getType()), intAttr.getValue());
513 }
else if (
auto floatAttr = mlir::dyn_cast<cir::FPAttr>(elementAttr)) {
514 mlirAttr = rewriter.getFloatAttr(
515 converter->convertType(floatAttr.getType()), floatAttr.getValue());
518 "vector constant with an element that is neither an int nor a float");
520 mlirValues.push_back(mlirAttr);
523 return mlir::LLVM::ConstantOp::create(
524 rewriter, loc, llvmTy,
525 mlir::DenseElementsAttr::get(mlir::cast<mlir::ShapedType>(llvmTy),
530 assert(lowerMod &&
"lower module is not available");
531 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
532 mlir::TypedAttr init =
533 lowerMod->getCXXABI().lowerDataMemberConstant(attr, layout, *converter);
540 auto moduleOp = parentOp->getParentOfType<mlir::ModuleOp>();
541 mlir::DataLayout dataLayout(moduleOp);
542 mlir::Type sourceType;
544 llvm::StringRef symName;
545 mlir::Operation *sourceSymbol =
546 mlir::SymbolTable::lookupSymbolIn(moduleOp, globalAttr.getSymbol());
547 if (
auto llvmSymbol = dyn_cast<mlir::LLVM::GlobalOp>(sourceSymbol)) {
548 sourceType = llvmSymbol.getType();
549 symName = llvmSymbol.getSymName();
550 }
else if (
auto cirSymbol = dyn_cast<cir::GlobalOp>(sourceSymbol)) {
553 symName = cirSymbol.getSymName();
554 }
else if (
auto llvmFun = dyn_cast<mlir::LLVM::LLVMFuncOp>(sourceSymbol)) {
555 sourceType = llvmFun.getFunctionType();
556 symName = llvmFun.getSymName();
557 }
else if (
auto fun = dyn_cast<cir::FuncOp>(sourceSymbol)) {
558 sourceType = converter->convertType(fun.getFunctionType());
559 symName = fun.getSymName();
560 }
else if (
auto alias = dyn_cast<mlir::LLVM::AliasOp>(sourceSymbol)) {
561 sourceType = alias.getType();
562 symName = alias.getSymName();
564 llvm_unreachable(
"Unexpected GlobalOp type");
567 mlir::Location loc = parentOp->getLoc();
568 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
569 rewriter, loc, mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
572 if (globalAttr.getIndices()) {
575 if (mlir::isa<mlir::LLVM::LLVMArrayType, mlir::LLVM::LLVMStructType>(
577 indices.push_back(0);
579 for (mlir::Attribute idx : globalAttr.getIndices()) {
580 auto intAttr = mlir::cast<mlir::IntegerAttr>(idx);
581 indices.push_back(intAttr.getValue().getSExtValue());
583 mlir::Type resTy = addrOp.getType();
584 mlir::Type eltTy = converter->convertType(sourceType);
586 mlir::LLVM::GEPOp::create(rewriter, loc, resTy, eltTy, addrOp, indices,
587 mlir::LLVM::GEPNoWrapFlags::none);
596 if (
auto ptrTy = mlir::dyn_cast<cir::PointerType>(globalAttr.getType())) {
597 mlir::Type llvmEltTy =
600 if (llvmEltTy == sourceType)
603 mlir::Type llvmDstTy = converter->convertType(globalAttr.getType());
604 return mlir::LLVM::BitcastOp::create(rewriter, parentOp->getLoc(),
608 llvm_unreachable(
"Expecting pointer or integer type for GlobalViewAttr");
613 mlir::Type llvmTy = converter->convertType(typeInfoAttr.getType());
614 mlir::Location loc = parentOp->getLoc();
615 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
617 for (
auto [idx, elt] : llvm::enumerate(typeInfoAttr.getData())) {
618 mlir::Value init =
visit(elt);
620 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
628 mlir::Location loc = parentOp->getLoc();
629 return mlir::LLVM::UndefOp::create(
630 rewriter, loc, converter->convertType(undefAttr.getType()));
635 mlir::Type llvmTy = converter->convertType(vtableArr.getType());
636 mlir::Location loc = parentOp->getLoc();
637 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
639 for (
auto [idx, elt] : llvm::enumerate(vtableArr.getData())) {
640 mlir::Value init =
visit(elt);
642 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
650 mlir::Location loc = parentOp->getLoc();
651 return mlir::LLVM::ZeroOp::create(rewriter, loc,
652 converter->convertType(attr.getType()));
660 mlir::ConversionPatternRewriter &rewriter)
661 : llvmType(type), rewriter(rewriter) {}
663 mlir::Attribute
visit(mlir::Attribute attr) {
664 return llvm::TypeSwitch<mlir::Attribute, mlir::Attribute>(attr)
665 .Case<cir::IntAttr, cir::FPAttr, cir::BoolAttr>(
667 .Default([&](
auto attrT) {
return mlir::Attribute(); });
671 return rewriter.getIntegerAttr(llvmType, attr.getValue());
675 return rewriter.getFloatAttr(llvmType, attr.getValue());
679 return rewriter.getBoolAttr(attr.getValue());
684 mlir::ConversionPatternRewriter &rewriter;
692 :
public mlir::PassWrapper<ConvertCIRToLLVMPass,
693 mlir::OperationPass<mlir::ModuleOp>> {
695 registry.insert<mlir::BuiltinDialect, mlir::DLTIDialect,
696 mlir::LLVM::LLVMDialect, mlir::func::FuncDialect>();
703 return "Convert the prepared CIR dialect module to LLVM dialect";
706 StringRef
getArgument()
const override {
return "cir-flat-to-llvm"; }
709mlir::LogicalResult CIRToLLVMACosOpLowering::matchAndRewrite(
710 cir::ACosOp op, OpAdaptor adaptor,
711 mlir::ConversionPatternRewriter &rewriter)
const {
712 mlir::Type resTy = typeConverter->convertType(op.getType());
713 rewriter.replaceOpWithNewOp<mlir::LLVM::ACosOp>(op, resTy,
714 adaptor.getOperands()[0]);
715 return mlir::success();
718mlir::LogicalResult CIRToLLVMASinOpLowering::matchAndRewrite(
719 cir::ASinOp op, OpAdaptor adaptor,
720 mlir::ConversionPatternRewriter &rewriter)
const {
721 mlir::Type resTy = typeConverter->convertType(op.getType());
722 rewriter.replaceOpWithNewOp<mlir::LLVM::ASinOp>(op, resTy, adaptor.getSrc());
723 return mlir::success();
726mlir::LogicalResult CIRToLLVMIsFPClassOpLowering::matchAndRewrite(
727 cir::IsFPClassOp op, OpAdaptor adaptor,
728 mlir::ConversionPatternRewriter &rewriter)
const {
729 mlir::Value src = adaptor.getSrc();
730 cir::FPClassTest flags = adaptor.getFlags();
731 mlir::IntegerType retTy = rewriter.getI1Type();
733 rewriter.replaceOpWithNewOp<mlir::LLVM::IsFPClass>(
734 op, retTy, src,
static_cast<uint32_t>(flags));
735 return mlir::success();
738mlir::LogicalResult CIRToLLVMAssumeOpLowering::matchAndRewrite(
739 cir::AssumeOp op, OpAdaptor adaptor,
740 mlir::ConversionPatternRewriter &rewriter)
const {
741 auto cond = adaptor.getPredicate();
742 rewriter.replaceOpWithNewOp<mlir::LLVM::AssumeOp>(op, cond);
743 return mlir::success();
746mlir::LogicalResult CIRToLLVMAssumeAlignedOpLowering::matchAndRewrite(
747 cir::AssumeAlignedOp op, OpAdaptor adaptor,
748 mlir::ConversionPatternRewriter &rewriter)
const {
749 SmallVector<mlir::Value, 3> opBundleArgs{adaptor.getPointer()};
751 auto alignment = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
752 adaptor.getAlignmentAttr());
753 opBundleArgs.push_back(alignment);
755 if (mlir::Value offset = adaptor.getOffset())
756 opBundleArgs.push_back(offset);
758 auto cond = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
759 rewriter.getI1Type(), 1);
760 mlir::LLVM::AssumeOp::create(rewriter, op.getLoc(), cond,
"align",
765 rewriter.replaceOp(op, adaptor.getPointer());
766 return mlir::success();
769mlir::LogicalResult CIRToLLVMAssumeSepStorageOpLowering::matchAndRewrite(
770 cir::AssumeSepStorageOp op, OpAdaptor adaptor,
771 mlir::ConversionPatternRewriter &rewriter)
const {
772 auto cond = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
773 rewriter.getI1Type(), 1);
774 rewriter.replaceOpWithNewOp<mlir::LLVM::AssumeOp>(
775 op, cond, mlir::LLVM::AssumeSeparateStorageTag{}, adaptor.getPtr1(),
777 return mlir::success();
780static mlir::LLVM::AtomicOrdering
783 return mlir::LLVM::AtomicOrdering::not_atomic;
785 case cir::MemOrder::Relaxed:
786 return mlir::LLVM::AtomicOrdering::monotonic;
787 case cir::MemOrder::Consume:
788 case cir::MemOrder::Acquire:
789 return mlir::LLVM::AtomicOrdering::acquire;
790 case cir::MemOrder::Release:
791 return mlir::LLVM::AtomicOrdering::release;
792 case cir::MemOrder::AcquireRelease:
793 return mlir::LLVM::AtomicOrdering::acq_rel;
794 case cir::MemOrder::SequentiallyConsistent:
795 return mlir::LLVM::AtomicOrdering::seq_cst;
797 llvm_unreachable(
"unknown memory order");
800static std::optional<llvm::StringRef>
802 if (syncScope.has_value())
803 return syncScope.value() == cir::SyncScopeKind::SingleThread
809mlir::LogicalResult CIRToLLVMAtomicCmpXchgOpLowering::matchAndRewrite(
810 cir::AtomicCmpXchgOp op, OpAdaptor adaptor,
811 mlir::ConversionPatternRewriter &rewriter)
const {
812 mlir::Value expected = adaptor.getExpected();
813 mlir::Value desired = adaptor.getDesired();
815 auto cmpxchg = mlir::LLVM::AtomicCmpXchgOp::create(
816 rewriter, op.getLoc(), adaptor.getPtr(), expected, desired,
820 cmpxchg.setAlignment(adaptor.getAlignment());
821 cmpxchg.setWeak(adaptor.getWeak());
822 cmpxchg.setVolatile_(adaptor.getIsVolatile());
825 auto old = mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(),
826 cmpxchg.getResult(), 0);
827 auto cmp = mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(),
828 cmpxchg.getResult(), 1);
830 rewriter.replaceOp(op, {old, cmp});
831 return mlir::success();
834mlir::LogicalResult CIRToLLVMAtomicXchgOpLowering::matchAndRewrite(
835 cir::AtomicXchgOp op, OpAdaptor adaptor,
836 mlir::ConversionPatternRewriter &rewriter)
const {
838 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(adaptor.getMemOrder());
839 rewriter.replaceOpWithNewOp<mlir::LLVM::AtomicRMWOp>(
840 op, mlir::LLVM::AtomicBinOp::xchg, adaptor.getPtr(), adaptor.getVal(),
842 return mlir::success();
845mlir::LogicalResult CIRToLLVMAtomicTestAndSetOpLowering::matchAndRewrite(
846 cir::AtomicTestAndSetOp op, OpAdaptor adaptor,
847 mlir::ConversionPatternRewriter &rewriter)
const {
850 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
852 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
853 rewriter.getI8Type(), 1);
854 auto rmw = mlir::LLVM::AtomicRMWOp::create(
855 rewriter, op.getLoc(), mlir::LLVM::AtomicBinOp::xchg, adaptor.getPtr(),
856 one, llvmOrder, llvm::StringRef(),
857 adaptor.getAlignment().value_or(0), op.getIsVolatile());
859 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
860 rewriter.getI8Type(), 0);
861 auto cmp = mlir::LLVM::ICmpOp::create(
862 rewriter, op.getLoc(), mlir::LLVM::ICmpPredicate::ne, rmw, zero);
864 rewriter.replaceOp(op, cmp);
865 return mlir::success();
868mlir::LogicalResult CIRToLLVMAtomicClearOpLowering::matchAndRewrite(
869 cir::AtomicClearOp op, OpAdaptor adaptor,
870 mlir::ConversionPatternRewriter &rewriter)
const {
873 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
874 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
875 rewriter.getI8Type(), 0);
876 auto store = mlir::LLVM::StoreOp::create(
877 rewriter, op.getLoc(), zero, adaptor.getPtr(),
878 adaptor.getAlignment().value_or(0), op.getIsVolatile(),
879 false,
false, llvmOrder);
881 rewriter.replaceOp(op, store);
882 return mlir::success();
885mlir::LogicalResult CIRToLLVMAtomicFenceOpLowering::matchAndRewrite(
886 cir::AtomicFenceOp op, OpAdaptor adaptor,
887 mlir::ConversionPatternRewriter &rewriter)
const {
888 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(adaptor.getOrdering());
890 auto fence = mlir::LLVM::FenceOp::create(rewriter, op.getLoc(), llvmOrder);
893 rewriter.replaceOp(op, fence);
895 return mlir::success();
898static mlir::LLVM::AtomicBinOp
901 case cir::AtomicFetchKind::Add:
902 return isInt ? mlir::LLVM::AtomicBinOp::add : mlir::LLVM::AtomicBinOp::fadd;
903 case cir::AtomicFetchKind::Sub:
904 return isInt ? mlir::LLVM::AtomicBinOp::sub : mlir::LLVM::AtomicBinOp::fsub;
905 case cir::AtomicFetchKind::And:
906 return mlir::LLVM::AtomicBinOp::_and;
907 case cir::AtomicFetchKind::Xor:
908 return mlir::LLVM::AtomicBinOp::_xor;
909 case cir::AtomicFetchKind::Or:
910 return mlir::LLVM::AtomicBinOp::_or;
911 case cir::AtomicFetchKind::Nand:
912 return mlir::LLVM::AtomicBinOp::nand;
913 case cir::AtomicFetchKind::Max: {
915 return mlir::LLVM::AtomicBinOp::fmax;
916 return isSignedInt ? mlir::LLVM::AtomicBinOp::max
917 : mlir::LLVM::AtomicBinOp::umax;
919 case cir::AtomicFetchKind::Min: {
921 return mlir::LLVM::AtomicBinOp::fmin;
922 return isSignedInt ? mlir::LLVM::AtomicBinOp::min
923 : mlir::LLVM::AtomicBinOp::umin;
926 llvm_unreachable(
"Unknown atomic fetch opcode");
929static llvm::StringLiteral
getLLVMBinop(cir::AtomicFetchKind k,
bool isInt) {
931 case cir::AtomicFetchKind::Add:
932 return isInt ? mlir::LLVM::AddOp::getOperationName()
933 : mlir::LLVM::FAddOp::getOperationName();
934 case cir::AtomicFetchKind::Sub:
935 return isInt ? mlir::LLVM::SubOp::getOperationName()
936 : mlir::LLVM::FSubOp::getOperationName();
937 case cir::AtomicFetchKind::And:
938 return mlir::LLVM::AndOp::getOperationName();
939 case cir::AtomicFetchKind::Xor:
940 return mlir::LLVM::XOrOp::getOperationName();
941 case cir::AtomicFetchKind::Or:
942 return mlir::LLVM::OrOp::getOperationName();
943 case cir::AtomicFetchKind::Nand:
945 return mlir::LLVM::AndOp::getOperationName();
946 case cir::AtomicFetchKind::Max:
947 case cir::AtomicFetchKind::Min:
948 llvm_unreachable(
"handled in buildMinMaxPostOp");
950 llvm_unreachable(
"Unknown atomic fetch opcode");
953mlir::Value CIRToLLVMAtomicFetchOpLowering::buildPostOp(
954 cir::AtomicFetchOp op, OpAdaptor adaptor,
955 mlir::ConversionPatternRewriter &rewriter, mlir::Value rmwVal,
961 rewriter.getStringAttr(
getLLVMBinop(op.getBinop(), isInt)),
962 atomicOperands, atomicResTys, {})
966mlir::Value CIRToLLVMAtomicFetchOpLowering::buildMinMaxPostOp(
967 cir::AtomicFetchOp op, OpAdaptor adaptor,
968 mlir::ConversionPatternRewriter &rewriter, mlir::Value rmwVal,
bool isInt,
969 bool isSigned)
const {
970 mlir::Location loc = op.getLoc();
973 if (op.getBinop() == cir::AtomicFetchKind::Max)
974 return mlir::LLVM::MaxNumOp::create(rewriter, loc, rmwVal,
976 return mlir::LLVM::MinNumOp::create(rewriter, loc, rmwVal,
980 mlir::LLVM::ICmpPredicate pred;
981 if (op.getBinop() == cir::AtomicFetchKind::Max) {
982 pred = isSigned ? mlir::LLVM::ICmpPredicate::sgt
983 : mlir::LLVM::ICmpPredicate::ugt;
985 pred = isSigned ? mlir::LLVM::ICmpPredicate::slt
986 : mlir::LLVM::ICmpPredicate::ult;
988 mlir::Value cmp = mlir::LLVM::ICmpOp::create(
990 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(), pred), rmwVal,
992 return mlir::LLVM::SelectOp::create(rewriter, loc, cmp, rmwVal,
996mlir::LogicalResult CIRToLLVMAtomicFetchOpLowering::matchAndRewrite(
997 cir::AtomicFetchOp op, OpAdaptor adaptor,
998 mlir::ConversionPatternRewriter &rewriter)
const {
1000 bool isSignedInt =
false;
1001 if (
auto intTy = mlir::dyn_cast<cir::IntType>(op.getVal().getType())) {
1003 isSignedInt = intTy.isSigned();
1004 }
else if (mlir::isa<cir::SingleType, cir::DoubleType>(
1005 op.getVal().getType())) {
1008 return op.emitError() <<
"Unsupported type: " << op.getVal().getType();
1011 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
1012 mlir::LLVM::AtomicBinOp llvmBinOp =
1014 auto rmwVal = mlir::LLVM::AtomicRMWOp::create(rewriter, op.getLoc(),
1015 llvmBinOp, adaptor.getPtr(),
1016 adaptor.getVal(), llvmOrder);
1018 mlir::Value result = rmwVal.getResult();
1019 if (!op.getFetchFirst()) {
1020 if (op.getBinop() == cir::AtomicFetchKind::Max ||
1021 op.getBinop() == cir::AtomicFetchKind::Min)
1022 result = buildMinMaxPostOp(op, adaptor, rewriter, rmwVal.getRes(), isInt,
1025 result = buildPostOp(op, adaptor, rewriter, rmwVal.getRes(), isInt);
1028 if (op.getBinop() == cir::AtomicFetchKind::Nand) {
1029 auto negOne = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1030 result.getType(), -1);
1031 result = mlir::LLVM::XOrOp::create(rewriter, op.getLoc(), result, negOne);
1035 rewriter.replaceOp(op, result);
1036 return mlir::success();
1039mlir::LogicalResult CIRToLLVMBitClrsbOpLowering::matchAndRewrite(
1040 cir::BitClrsbOp op, OpAdaptor adaptor,
1041 mlir::ConversionPatternRewriter &rewriter)
const {
1042 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1043 adaptor.getInput().getType(), 0);
1044 auto isNeg = mlir::LLVM::ICmpOp::create(
1045 rewriter, op.getLoc(),
1046 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(),
1047 mlir::LLVM::ICmpPredicate::slt),
1048 adaptor.getInput(), zero);
1050 auto negOne = mlir::LLVM::ConstantOp::create(
1051 rewriter, op.getLoc(), adaptor.getInput().getType(), -1);
1052 auto flipped = mlir::LLVM::XOrOp::create(rewriter, op.getLoc(),
1053 adaptor.getInput(), negOne);
1055 auto select = mlir::LLVM::SelectOp::create(rewriter, op.getLoc(), isNeg,
1056 flipped, adaptor.getInput());
1058 auto resTy = getTypeConverter()->convertType(op.getType());
1059 auto clz = mlir::LLVM::CountLeadingZerosOp::create(
1060 rewriter, op.getLoc(), resTy,
select,
false);
1062 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1063 auto res = mlir::LLVM::SubOp::create(rewriter, op.getLoc(),
clz, one);
1064 rewriter.replaceOp(op, res);
1066 return mlir::LogicalResult::success();
1069mlir::LogicalResult CIRToLLVMBitClzOpLowering::matchAndRewrite(
1070 cir::BitClzOp op, OpAdaptor adaptor,
1071 mlir::ConversionPatternRewriter &rewriter)
const {
1072 auto resTy = getTypeConverter()->convertType(op.getType());
1073 auto llvmOp = mlir::LLVM::CountLeadingZerosOp::create(
1074 rewriter, op.getLoc(), resTy, adaptor.getInput(), op.getPoisonZero());
1075 rewriter.replaceOp(op, llvmOp);
1076 return mlir::LogicalResult::success();
1079mlir::LogicalResult CIRToLLVMBitCtzOpLowering::matchAndRewrite(
1080 cir::BitCtzOp op, OpAdaptor adaptor,
1081 mlir::ConversionPatternRewriter &rewriter)
const {
1082 auto resTy = getTypeConverter()->convertType(op.getType());
1083 auto llvmOp = mlir::LLVM::CountTrailingZerosOp::create(
1084 rewriter, op.getLoc(), resTy, adaptor.getInput(), op.getPoisonZero());
1085 rewriter.replaceOp(op, llvmOp);
1086 return mlir::LogicalResult::success();
1089mlir::LogicalResult CIRToLLVMBitFfsOpLowering::matchAndRewrite(
1090 cir::BitFfsOp op, OpAdaptor adaptor,
1091 mlir::ConversionPatternRewriter &rewriter)
const {
1092 auto resTy = getTypeConverter()->convertType(op.getType());
1093 auto ctz = mlir::LLVM::CountTrailingZerosOp::create(rewriter, op.getLoc(),
1094 resTy, adaptor.getInput(),
1097 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1098 auto ctzAddOne = mlir::LLVM::AddOp::create(rewriter, op.getLoc(),
ctz, one);
1100 auto zeroInputTy = mlir::LLVM::ConstantOp::create(
1101 rewriter, op.getLoc(), adaptor.getInput().getType(), 0);
1102 auto isZero = mlir::LLVM::ICmpOp::create(
1103 rewriter, op.getLoc(),
1104 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(),
1105 mlir::LLVM::ICmpPredicate::eq),
1106 adaptor.getInput(), zeroInputTy);
1108 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 0);
1109 auto res = mlir::LLVM::SelectOp::create(rewriter, op.getLoc(), isZero, zero,
1111 rewriter.replaceOp(op, res);
1113 return mlir::LogicalResult::success();
1116mlir::LogicalResult CIRToLLVMBitParityOpLowering::matchAndRewrite(
1117 cir::BitParityOp op, OpAdaptor adaptor,
1118 mlir::ConversionPatternRewriter &rewriter)
const {
1119 auto resTy = getTypeConverter()->convertType(op.getType());
1120 auto popcnt = mlir::LLVM::CtPopOp::create(rewriter, op.getLoc(), resTy,
1121 adaptor.getInput());
1123 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1125 mlir::LLVM::AndOp::create(rewriter, op.getLoc(), popcnt, one);
1126 rewriter.replaceOp(op, popcntMod2);
1128 return mlir::LogicalResult::success();
1131mlir::LogicalResult CIRToLLVMBitPopcountOpLowering::matchAndRewrite(
1132 cir::BitPopcountOp op, OpAdaptor adaptor,
1133 mlir::ConversionPatternRewriter &rewriter)
const {
1134 auto resTy = getTypeConverter()->convertType(op.getType());
1135 auto llvmOp = mlir::LLVM::CtPopOp::create(rewriter, op.getLoc(), resTy,
1136 adaptor.getInput());
1137 rewriter.replaceOp(op, llvmOp);
1138 return mlir::LogicalResult::success();
1141mlir::LogicalResult CIRToLLVMBitReverseOpLowering::matchAndRewrite(
1142 cir::BitReverseOp op, OpAdaptor adaptor,
1143 mlir::ConversionPatternRewriter &rewriter)
const {
1144 rewriter.replaceOpWithNewOp<mlir::LLVM::BitReverseOp>(op, adaptor.getInput());
1145 return mlir::success();
1148mlir::LogicalResult CIRToLLVMBrCondOpLowering::matchAndRewrite(
1149 cir::BrCondOp brOp, OpAdaptor adaptor,
1150 mlir::ConversionPatternRewriter &rewriter)
const {
1155 mlir::Value i1Condition = adaptor.getCond();
1157 rewriter.replaceOpWithNewOp<mlir::LLVM::CondBrOp>(
1158 brOp, i1Condition, brOp.getDestTrue(), adaptor.getDestOperandsTrue(),
1159 brOp.getDestFalse(), adaptor.getDestOperandsFalse());
1161 return mlir::success();
1164mlir::LogicalResult CIRToLLVMByteSwapOpLowering::matchAndRewrite(
1165 cir::ByteSwapOp op, OpAdaptor adaptor,
1166 mlir::ConversionPatternRewriter &rewriter)
const {
1167 rewriter.replaceOpWithNewOp<mlir::LLVM::ByteSwapOp>(op, adaptor.getInput());
1168 return mlir::LogicalResult::success();
1171mlir::Type CIRToLLVMCastOpLowering::convertTy(mlir::Type ty)
const {
1172 return getTypeConverter()->convertType(ty);
1175mlir::LogicalResult CIRToLLVMCastOpLowering::matchAndRewrite(
1176 cir::CastOp castOp, OpAdaptor adaptor,
1177 mlir::ConversionPatternRewriter &rewriter)
const {
1182 switch (castOp.getKind()) {
1183 case cir::CastKind::array_to_ptrdecay: {
1184 const auto ptrTy = mlir::cast<cir::PointerType>(castOp.getType());
1185 mlir::Value sourceValue = adaptor.getSrc();
1186 mlir::Type targetType = convertTy(ptrTy);
1188 ptrTy.getPointee());
1189 llvm::SmallVector<mlir::LLVM::GEPArg> offset{0};
1190 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1191 castOp, targetType, elementTy, sourceValue, offset);
1194 case cir::CastKind::int_to_bool: {
1195 mlir::Value llvmSrcVal = adaptor.getSrc();
1196 mlir::Value zeroInt = mlir::LLVM::ConstantOp::create(
1197 rewriter, castOp.getLoc(), llvmSrcVal.getType(), 0);
1198 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
1199 castOp, mlir::LLVM::ICmpPredicate::ne, llvmSrcVal, zeroInt);
1202 case cir::CastKind::integral: {
1203 mlir::Type srcType = castOp.getSrc().getType();
1204 mlir::Type dstType = castOp.getType();
1205 mlir::Value llvmSrcVal = adaptor.getSrc();
1206 mlir::Type llvmDstType = getTypeConverter()->convertType(dstType);
1207 cir::IntType srcIntType =
1208 mlir::cast<cir::IntType>(elementTypeIfVector(srcType));
1209 cir::IntType dstIntType =
1210 mlir::cast<cir::IntType>(elementTypeIfVector(dstType));
1211 rewriter.replaceOp(castOp,
getLLVMIntCast(rewriter, llvmSrcVal, llvmDstType,
1212 srcIntType.isUnsigned(),
1213 srcIntType.getWidth(),
1214 dstIntType.getWidth()));
1217 case cir::CastKind::floating: {
1218 mlir::Value llvmSrcVal = adaptor.getSrc();
1219 mlir::Type llvmDstTy = getTypeConverter()->convertType(castOp.getType());
1221 mlir::Type srcTy = elementTypeIfVector(castOp.getSrc().getType());
1222 mlir::Type dstTy = elementTypeIfVector(castOp.getType());
1224 if (!mlir::isa<cir::FPTypeInterface>(dstTy) ||
1225 !mlir::isa<cir::FPTypeInterface>(srcTy))
1226 return castOp.emitError() <<
"NYI cast from " << srcTy <<
" to " << dstTy;
1228 auto getFloatWidth = [](mlir::Type ty) ->
unsigned {
1229 return mlir::cast<cir::FPTypeInterface>(ty).getWidth();
1232 if (getFloatWidth(srcTy) > getFloatWidth(dstTy))
1233 rewriter.replaceOpWithNewOp<mlir::LLVM::FPTruncOp>(castOp, llvmDstTy,
1236 rewriter.replaceOpWithNewOp<mlir::LLVM::FPExtOp>(castOp, llvmDstTy,
1238 return mlir::success();
1240 case cir::CastKind::int_to_ptr: {
1241 auto dstTy = mlir::cast<cir::PointerType>(castOp.getType());
1242 mlir::Value llvmSrcVal = adaptor.getSrc();
1243 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1244 rewriter.replaceOpWithNewOp<mlir::LLVM::IntToPtrOp>(castOp, llvmDstTy,
1246 return mlir::success();
1248 case cir::CastKind::ptr_to_int: {
1249 auto dstTy = mlir::cast<cir::IntType>(castOp.getType());
1250 mlir::Value llvmSrcVal = adaptor.getSrc();
1251 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1252 rewriter.replaceOpWithNewOp<mlir::LLVM::PtrToIntOp>(castOp, llvmDstTy,
1254 return mlir::success();
1256 case cir::CastKind::float_to_bool: {
1257 mlir::Value llvmSrcVal = adaptor.getSrc();
1258 auto kind = mlir::LLVM::FCmpPredicate::une;
1261 auto zeroFloat = mlir::LLVM::ConstantOp::create(
1262 rewriter, castOp.getLoc(), llvmSrcVal.getType(),
1263 mlir::FloatAttr::get(llvmSrcVal.getType(), 0.0));
1266 rewriter.replaceOpWithNewOp<mlir::LLVM::FCmpOp>(castOp,
kind, llvmSrcVal,
1269 return mlir::success();
1271 case cir::CastKind::bool_to_int: {
1272 auto dstTy = mlir::cast<cir::IntType>(castOp.getType());
1273 mlir::Value llvmSrcVal = adaptor.getSrc();
1274 auto llvmSrcTy = mlir::cast<mlir::IntegerType>(llvmSrcVal.getType());
1276 mlir::cast<mlir::IntegerType>(getTypeConverter()->convertType(dstTy));
1277 if (llvmSrcTy.getWidth() == llvmDstTy.getWidth())
1278 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(castOp, llvmDstTy,
1281 rewriter.replaceOpWithNewOp<mlir::LLVM::ZExtOp>(castOp, llvmDstTy,
1283 return mlir::success();
1285 case cir::CastKind::bool_to_float: {
1286 mlir::Type dstTy = castOp.getType();
1287 mlir::Value llvmSrcVal = adaptor.getSrc();
1288 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1289 rewriter.replaceOpWithNewOp<mlir::LLVM::UIToFPOp>(castOp, llvmDstTy,
1291 return mlir::success();
1293 case cir::CastKind::int_to_float: {
1294 mlir::Type dstTy = castOp.getType();
1295 mlir::Value llvmSrcVal = adaptor.getSrc();
1296 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1297 if (mlir::cast<cir::IntType>(elementTypeIfVector(castOp.getSrc().getType()))
1299 rewriter.replaceOpWithNewOp<mlir::LLVM::SIToFPOp>(castOp, llvmDstTy,
1302 rewriter.replaceOpWithNewOp<mlir::LLVM::UIToFPOp>(castOp, llvmDstTy,
1304 return mlir::success();
1306 case cir::CastKind::float_to_int: {
1307 mlir::Type dstTy = castOp.getType();
1308 mlir::Value llvmSrcVal = adaptor.getSrc();
1309 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1310 if (mlir::cast<cir::IntType>(elementTypeIfVector(castOp.getType()))
1312 rewriter.replaceOpWithNewOp<mlir::LLVM::FPToSIOp>(castOp, llvmDstTy,
1315 rewriter.replaceOpWithNewOp<mlir::LLVM::FPToUIOp>(castOp, llvmDstTy,
1317 return mlir::success();
1319 case cir::CastKind::bitcast: {
1320 mlir::Type dstTy = castOp.getType();
1321 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1326 mlir::Value llvmSrcVal = adaptor.getSrc();
1327 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(castOp, llvmDstTy,
1329 return mlir::success();
1331 case cir::CastKind::ptr_to_bool: {
1332 mlir::Value llvmSrcVal = adaptor.getSrc();
1333 mlir::Value zeroPtr = mlir::LLVM::ZeroOp::create(rewriter, castOp.getLoc(),
1334 llvmSrcVal.getType());
1335 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
1336 castOp, mlir::LLVM::ICmpPredicate::ne, llvmSrcVal, zeroPtr);
1339 case cir::CastKind::address_space: {
1340 mlir::Type dstTy = castOp.getType();
1341 mlir::Value llvmSrcVal = adaptor.getSrc();
1342 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1343 rewriter.replaceOpWithNewOp<mlir::LLVM::AddrSpaceCastOp>(castOp, llvmDstTy,
1347 case cir::CastKind::member_ptr_to_bool:
1352 return castOp.emitError(
"Unhandled cast kind: ")
1353 << castOp.getKindAttrName();
1357 return mlir::success();
1360mlir::LogicalResult CIRToLLVMPtrStrideOpLowering::matchAndRewrite(
1361 cir::PtrStrideOp ptrStrideOp, OpAdaptor adaptor,
1362 mlir::ConversionPatternRewriter &rewriter)
const {
1364 const mlir::TypeConverter *tc = getTypeConverter();
1365 const mlir::Type resultTy = tc->convertType(ptrStrideOp.getType());
1367 mlir::Type elementTy =
1369 mlir::MLIRContext *ctx = elementTy.getContext();
1373 if (mlir::isa<mlir::LLVM::LLVMVoidType>(elementTy) ||
1374 mlir::isa<mlir::LLVM::LLVMFunctionType>(elementTy))
1375 elementTy = mlir::IntegerType::get(elementTy.getContext(), 8,
1376 mlir::IntegerType::Signless);
1378 mlir::Value index = adaptor.getStride();
1379 const unsigned width =
1380 mlir::cast<mlir::IntegerType>(index.getType()).getWidth();
1381 const std::optional<std::uint64_t> layoutWidth =
1382 dataLayout.getTypeIndexBitwidth(adaptor.getBase().getType());
1384 mlir::Operation *indexOp = index.getDefiningOp();
1385 if (indexOp && layoutWidth && width != *layoutWidth) {
1389 const auto sub = dyn_cast<mlir::LLVM::SubOp>(indexOp);
1390 auto unary = ptrStrideOp.getStride().getDefiningOp<cir::UnaryOp>();
1392 unary && unary.getKind() == cir::UnaryOpKind::Minus && sub;
1394 index = indexOp->getOperand(1);
1397 const auto llvmDstType = mlir::IntegerType::get(ctx, *layoutWidth);
1399 ptrStrideOp.getStride().getType().isUnsigned(),
1400 width, *layoutWidth);
1404 index = mlir::LLVM::SubOp::create(
1405 rewriter, index.getLoc(), index.getType(),
1406 mlir::LLVM::ConstantOp::create(rewriter, index.getLoc(),
1407 index.getType(), 0),
1409 rewriter.eraseOp(sub);
1413 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1414 ptrStrideOp, resultTy, elementTy, adaptor.getBase(), index);
1415 return mlir::success();
1418mlir::LogicalResult CIRToLLVMBaseClassAddrOpLowering::matchAndRewrite(
1419 cir::BaseClassAddrOp baseClassOp, OpAdaptor adaptor,
1420 mlir::ConversionPatternRewriter &rewriter)
const {
1421 const mlir::Type resultType =
1422 getTypeConverter()->convertType(baseClassOp.getType());
1423 mlir::Value derivedAddr = adaptor.getDerivedAddr();
1424 llvm::SmallVector<mlir::LLVM::GEPArg, 1> offset = {
1425 adaptor.getOffset().getZExtValue()};
1426 mlir::Type byteType = mlir::IntegerType::get(resultType.getContext(), 8,
1427 mlir::IntegerType::Signless);
1428 if (adaptor.getOffset().getZExtValue() == 0) {
1429 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(
1430 baseClassOp, resultType, adaptor.getDerivedAddr());
1431 return mlir::success();
1434 if (baseClassOp.getAssumeNotNull()) {
1435 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1436 baseClassOp, resultType, byteType, derivedAddr, offset);
1438 auto loc = baseClassOp.getLoc();
1439 mlir::Value isNull = mlir::LLVM::ICmpOp::create(
1440 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, derivedAddr,
1441 mlir::LLVM::ZeroOp::create(rewriter, loc, derivedAddr.getType()));
1442 mlir::Value adjusted = mlir::LLVM::GEPOp::create(
1443 rewriter, loc, resultType, byteType, derivedAddr, offset);
1444 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(baseClassOp, isNull,
1445 derivedAddr, adjusted);
1447 return mlir::success();
1450mlir::LogicalResult CIRToLLVMDerivedClassAddrOpLowering::matchAndRewrite(
1451 cir::DerivedClassAddrOp derivedClassOp, OpAdaptor adaptor,
1452 mlir::ConversionPatternRewriter &rewriter)
const {
1453 const mlir::Type resultType =
1454 getTypeConverter()->convertType(derivedClassOp.getType());
1455 mlir::Value baseAddr = adaptor.getBaseAddr();
1458 int64_t offsetVal = -(adaptor.getOffset().getZExtValue());
1459 if (offsetVal == 0) {
1461 rewriter.replaceOp(derivedClassOp, baseAddr);
1462 return mlir::success();
1464 llvm::SmallVector<mlir::LLVM::GEPArg, 1> offset = {offsetVal};
1465 mlir::Type byteType = mlir::IntegerType::get(resultType.getContext(), 8,
1466 mlir::IntegerType::Signless);
1467 if (derivedClassOp.getAssumeNotNull()) {
1468 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1469 derivedClassOp, resultType, byteType, baseAddr, offset,
1470 mlir::LLVM::GEPNoWrapFlags::inbounds);
1472 mlir::Location loc = derivedClassOp.getLoc();
1473 mlir::Value isNull = mlir::LLVM::ICmpOp::create(
1474 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, baseAddr,
1475 mlir::LLVM::ZeroOp::create(rewriter, loc, baseAddr.getType()));
1476 mlir::Value adjusted =
1477 mlir::LLVM::GEPOp::create(rewriter, loc, resultType, byteType, baseAddr,
1478 offset, mlir::LLVM::GEPNoWrapFlags::inbounds);
1479 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(derivedClassOp, isNull,
1480 baseAddr, adjusted);
1482 return mlir::success();
1485mlir::LogicalResult CIRToLLVMATanOpLowering::matchAndRewrite(
1486 cir::ATanOp op, OpAdaptor adaptor,
1487 mlir::ConversionPatternRewriter &rewriter)
const {
1488 mlir::Type resTy = typeConverter->convertType(op.getType());
1489 rewriter.replaceOpWithNewOp<mlir::LLVM::ATanOp>(op, resTy, adaptor.getSrc());
1490 return mlir::success();
1493mlir::LogicalResult CIRToLLVMCeilOpLowering::matchAndRewrite(
1494 cir::CeilOp op, OpAdaptor adaptor,
1495 mlir::ConversionPatternRewriter &rewriter)
const {
1496 mlir::Type resTy = typeConverter->convertType(op.getType());
1497 rewriter.replaceOpWithNewOp<mlir::LLVM::FCeilOp>(op, resTy, adaptor.getSrc());
1498 return mlir::success();
1501mlir::LogicalResult CIRToLLVMAllocaOpLowering::matchAndRewrite(
1502 cir::AllocaOp op, OpAdaptor adaptor,
1503 mlir::ConversionPatternRewriter &rewriter)
const {
1506 ? adaptor.getDynAllocSize()
1507 : mlir::LLVM::ConstantOp::create(
1508 rewriter, op.getLoc(),
1509 typeConverter->convertType(rewriter.getIndexType()), 1);
1510 mlir::Type elementTy =
1512 mlir::Type resultTy =
1518 rewriter.replaceOpWithNewOp<mlir::LLVM::AllocaOp>(
1519 op, resultTy, elementTy, size, op.getAlignmentAttr().getInt());
1521 return mlir::success();
1524mlir::LogicalResult CIRToLLVMReturnOpLowering::matchAndRewrite(
1525 cir::ReturnOp op, OpAdaptor adaptor,
1526 mlir::ConversionPatternRewriter &rewriter)
const {
1527 rewriter.replaceOpWithNewOp<mlir::LLVM::ReturnOp>(op, adaptor.getOperands());
1528 return mlir::LogicalResult::success();
1531mlir::LogicalResult CIRToLLVMRotateOpLowering::matchAndRewrite(
1532 cir::RotateOp op, OpAdaptor adaptor,
1533 mlir::ConversionPatternRewriter &rewriter)
const {
1536 mlir::Value input = adaptor.getInput();
1537 if (op.isRotateLeft())
1538 rewriter.replaceOpWithNewOp<mlir::LLVM::FshlOp>(op, input, input,
1539 adaptor.getAmount());
1541 rewriter.replaceOpWithNewOp<mlir::LLVM::FshrOp>(op, input, input,
1542 adaptor.getAmount());
1543 return mlir::LogicalResult::success();
1546static mlir::LogicalResult
1548 mlir::ConversionPatternRewriter &rewriter,
1549 const mlir::TypeConverter *converter,
1550 mlir::FlatSymbolRefAttr calleeAttr) {
1552 mlir::ValueTypeRange<mlir::ResultRange> cirResults = op->getResultTypes();
1553 auto call = cast<cir::CIRCallOpInterface>(op);
1555 if (converter->convertTypes(cirResults, llvmResults).failed())
1556 return mlir::failure();
1560 mlir::LLVM::MemoryEffectsAttr memoryEffects;
1561 bool noUnwind =
false;
1562 bool willReturn =
false;
1564 memoryEffects, noUnwind, willReturn);
1566 mlir::LLVM::LLVMFunctionType llvmFnTy;
1573 mlir::Operation *callee =
1574 mlir::SymbolTable::lookupNearestSymbolFrom(op, calleeAttr);
1575 if (
auto fn = mlir::dyn_cast<mlir::FunctionOpInterface>(callee)) {
1576 llvmFnTy = converter->convertType<mlir::LLVM::LLVMFunctionType>(
1577 fn.getFunctionType());
1578 assert(llvmFnTy &&
"Failed to convert function type");
1579 }
else if (
auto alias = mlir::cast<mlir::LLVM::AliasOp>(callee)) {
1587 auto symAttr = mlir::cast<mlir::FlatSymbolRefAttr>(calleeAttr);
1589 mlir::LLVM::AddressOfOp::create(
1590 rewriter, op->getLoc(),
1591 mlir::LLVM::LLVMPointerType::get(rewriter.getContext()), symAttr)
1593 adjustedCallOperands.push_back(addrOfAlias);
1596 llvm::append_range(adjustedCallOperands, callOperands);
1597 callOperands = adjustedCallOperands;
1601 llvmFnTy = mlir::cast<mlir::LLVM::LLVMFunctionType>(alias.getType());
1604 return op->emitError(
"Unexpected callee type!");
1607 assert(!op->getOperands().empty() &&
1608 "operands list must no be empty for the indirect call");
1609 auto calleeTy = op->getOperands().front().getType();
1610 auto calleePtrTy = cast<cir::PointerType>(calleeTy);
1611 auto calleeFuncTy = cast<cir::FuncType>(calleePtrTy.getPointee());
1612 llvm::append_range(adjustedCallOperands, callOperands);
1613 llvmFnTy = cast<mlir::LLVM::LLVMFunctionType>(
1614 converter->convertType(calleeFuncTy));
1621 auto newOp = rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(
1622 op, llvmFnTy, calleeAttr, callOperands);
1624 newOp.setMemoryEffectsAttr(memoryEffects);
1625 newOp.setNoUnwind(noUnwind);
1626 newOp.setWillReturn(willReturn);
1628 return mlir::success();
1631mlir::LogicalResult CIRToLLVMCallOpLowering::matchAndRewrite(
1632 cir::CallOp op, OpAdaptor adaptor,
1633 mlir::ConversionPatternRewriter &rewriter)
const {
1635 getTypeConverter(), op.getCalleeAttr());
1638mlir::LogicalResult CIRToLLVMReturnAddrOpLowering::matchAndRewrite(
1639 cir::ReturnAddrOp op, OpAdaptor adaptor,
1640 mlir::ConversionPatternRewriter &rewriter)
const {
1641 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
1643 llvmPtrTy, adaptor.getOperands());
1644 return mlir::success();
1647mlir::LogicalResult CIRToLLVMFrameAddrOpLowering::matchAndRewrite(
1648 cir::FrameAddrOp op, OpAdaptor adaptor,
1649 mlir::ConversionPatternRewriter &rewriter)
const {
1650 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
1652 adaptor.getOperands());
1653 return mlir::success();
1656mlir::LogicalResult CIRToLLVMLoadOpLowering::matchAndRewrite(
1657 cir::LoadOp op, OpAdaptor adaptor,
1658 mlir::ConversionPatternRewriter &rewriter)
const {
1659 const mlir::Type llvmTy =
1661 mlir::LLVM::AtomicOrdering ordering =
getLLVMMemOrder(op.getMemOrder());
1662 std::optional<size_t> opAlign = op.getAlignment();
1663 unsigned alignment =
1664 (unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmTy));
1670 std::optional<llvm::StringRef> syncScope =
1672 mlir::LLVM::LoadOp newLoad = mlir::LLVM::LoadOp::create(
1673 rewriter, op->getLoc(), llvmTy, adaptor.getAddr(), alignment,
1674 op.getIsVolatile(),
false,
1675 false,
false, ordering,
1676 syncScope.value_or(llvm::StringRef()));
1679 mlir::Value result =
1681 rewriter.replaceOp(op, result);
1683 return mlir::LogicalResult::success();
1686mlir::LogicalResult CIRToLLVMStoreOpLowering::matchAndRewrite(
1687 cir::StoreOp op, OpAdaptor adaptor,
1688 mlir::ConversionPatternRewriter &rewriter)
const {
1689 mlir::LLVM::AtomicOrdering memorder =
getLLVMMemOrder(op.getMemOrder());
1690 const mlir::Type llvmTy =
1691 getTypeConverter()->convertType(op.getValue().getType());
1692 std::optional<size_t> opAlign = op.getAlignment();
1693 unsigned alignment =
1694 (unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmTy));
1700 op.getValue().getType(), adaptor.getValue());
1704 std::optional<llvm::StringRef> syncScope =
1706 mlir::LLVM::StoreOp storeOp = mlir::LLVM::StoreOp::create(
1707 rewriter, op->getLoc(), value, adaptor.getAddr(), alignment,
1709 false,
false, memorder,
1710 syncScope.value_or(llvm::StringRef()));
1711 rewriter.replaceOp(op, storeOp);
1713 return mlir::LogicalResult::success();
1717 auto array = mlir::dyn_cast<mlir::ArrayAttr>(attr.getElts());
1718 return attr.hasTrailingZeros() ||
1719 (array && std::count_if(array.begin(), array.end(), [](
auto elt) {
1720 auto ar = dyn_cast<cir::ConstArrayAttr>(elt);
1721 return ar && hasTrailingZeros(ar);
1725mlir::LogicalResult CIRToLLVMConstantOpLowering::matchAndRewrite(
1726 cir::ConstantOp op, OpAdaptor adaptor,
1727 mlir::ConversionPatternRewriter &rewriter)
const {
1728 mlir::Attribute attr = op.getValue();
1730 if (mlir::isa<cir::PoisonAttr>(attr)) {
1731 rewriter.replaceOpWithNewOp<mlir::LLVM::PoisonOp>(
1732 op, getTypeConverter()->convertType(op.getType()));
1733 return mlir::success();
1736 if (mlir::isa<mlir::IntegerType>(op.getType())) {
1741 attr = op.getValue();
1742 }
else if (mlir::isa<cir::BoolType>(op.getType())) {
1743 int value = mlir::cast<cir::BoolAttr>(op.getValue()).getValue();
1744 attr = rewriter.getIntegerAttr(typeConverter->convertType(op.getType()),
1746 }
else if (mlir::isa<cir::IntType>(op.getType())) {
1748 if (
auto ga = mlir::dyn_cast<cir::GlobalViewAttr>(op.getValue())) {
1751 op.emitError() <<
"global view with integer type";
1752 return mlir::failure();
1755 attr = rewriter.getIntegerAttr(
1756 typeConverter->convertType(op.getType()),
1757 mlir::cast<cir::IntAttr>(op.getValue()).getValue());
1758 }
else if (mlir::isa<cir::FPTypeInterface>(op.getType())) {
1759 attr = rewriter.getFloatAttr(
1760 typeConverter->convertType(op.getType()),
1761 mlir::cast<cir::FPAttr>(op.getValue()).getValue());
1762 }
else if (mlir::isa<cir::PointerType>(op.getType())) {
1764 if (mlir::isa<cir::ConstPtrAttr>(op.getValue())) {
1765 if (mlir::cast<cir::ConstPtrAttr>(op.getValue()).isNullValue()) {
1766 rewriter.replaceOpWithNewOp<mlir::LLVM::ZeroOp>(
1767 op, typeConverter->convertType(op.getType()));
1768 return mlir::success();
1772 if (
auto gv = mlir::dyn_cast<cir::GlobalViewAttr>(op.getValue())) {
1775 rewriter.replaceOp(op, newOp);
1776 return mlir::success();
1778 attr = op.getValue();
1779 }
else if (mlir::isa<cir::DataMemberType>(op.getType())) {
1780 assert(lowerMod &&
"lower module is not available");
1781 auto dataMember = mlir::cast<cir::DataMemberAttr>(op.getValue());
1782 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
1783 mlir::TypedAttr abiValue = lowerMod->getCXXABI().lowerDataMemberConstant(
1784 dataMember, layout, *typeConverter);
1785 rewriter.replaceOpWithNewOp<ConstantOp>(op, abiValue);
1786 return mlir::success();
1787 }
else if (
const auto arrTy = mlir::dyn_cast<cir::ArrayType>(op.getType())) {
1788 const auto constArr = mlir::dyn_cast<cir::ConstArrayAttr>(op.getValue());
1789 if (!constArr && !isa<cir::ZeroAttr, cir::UndefAttr>(op.getValue()))
1790 return op.emitError() <<
"array does not have a constant initializer";
1792 std::optional<mlir::Attribute> denseAttr;
1795 op, constArr, rewriter, getTypeConverter(), lowerMod);
1796 rewriter.replaceOp(op, newOp);
1797 return mlir::success();
1798 }
else if (constArr &&
1800 attr = denseAttr.value();
1803 op, op.getValue(), rewriter, typeConverter, lowerMod);
1804 rewriter.replaceOp(op, initVal);
1805 return mlir::success();
1807 }
else if (
const auto recordAttr =
1808 mlir::dyn_cast<cir::ConstRecordAttr>(op.getValue())) {
1811 rewriter.replaceOp(op, initVal);
1812 return mlir::success();
1813 }
else if (
const auto vecTy = mlir::dyn_cast<cir::VectorType>(op.getType())) {
1815 getTypeConverter(), lowerMod));
1816 return mlir::success();
1817 }
else if (
auto recTy = mlir::dyn_cast<cir::RecordType>(op.getType())) {
1818 if (mlir::isa<cir::ZeroAttr, cir::UndefAttr>(attr)) {
1819 mlir::Value initVal =
1821 rewriter.replaceOp(op, initVal);
1822 return mlir::success();
1824 return op.emitError() <<
"unsupported lowering for record constant type "
1826 }
else if (
auto complexTy = mlir::dyn_cast<cir::ComplexType>(op.getType())) {
1827 mlir::Type complexElemTy = complexTy.getElementType();
1828 mlir::Type complexElemLLVMTy = typeConverter->convertType(complexElemTy);
1830 if (
auto zeroInitAttr = mlir::dyn_cast<cir::ZeroAttr>(op.getValue())) {
1831 mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(complexElemLLVMTy);
1832 mlir::ArrayAttr array = rewriter.getArrayAttr({zeroAttr, zeroAttr});
1833 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
1834 op, getTypeConverter()->convertType(op.getType()), array);
1835 return mlir::success();
1838 auto complexAttr = mlir::cast<cir::ConstComplexAttr>(op.getValue());
1840 mlir::Attribute components[2];
1841 if (mlir::isa<cir::IntType>(complexElemTy)) {
1842 components[0] = rewriter.getIntegerAttr(
1844 mlir::cast<cir::IntAttr>(complexAttr.getReal()).getValue());
1845 components[1] = rewriter.getIntegerAttr(
1847 mlir::cast<cir::IntAttr>(complexAttr.getImag()).getValue());
1849 components[0] = rewriter.getFloatAttr(
1851 mlir::cast<cir::FPAttr>(complexAttr.getReal()).getValue());
1852 components[1] = rewriter.getFloatAttr(
1854 mlir::cast<cir::FPAttr>(complexAttr.getImag()).getValue());
1857 attr = rewriter.getArrayAttr(components);
1859 return op.emitError() <<
"unsupported constant type " << op.getType();
1862 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
1863 op, getTypeConverter()->convertType(op.getType()),
attr);
1865 return mlir::success();
1869 mlir::DataLayout layout(op.getParentOfType<mlir::ModuleOp>());
1871 if (isa<cir::VoidType>(type))
1872 type = cir::IntType::get(type.getContext(), 8,
false);
1873 return llvm::divideCeil(layout.getTypeSizeInBits(type), 8);
1876mlir::LogicalResult CIRToLLVMPrefetchOpLowering::matchAndRewrite(
1877 cir::PrefetchOp op, OpAdaptor adaptor,
1878 mlir::ConversionPatternRewriter &rewriter)
const {
1879 rewriter.replaceOpWithNewOp<mlir::LLVM::Prefetch>(
1880 op, adaptor.getAddr(), adaptor.getIsWrite(), adaptor.getLocality(),
1882 return mlir::success();
1885mlir::LogicalResult CIRToLLVMPtrDiffOpLowering::matchAndRewrite(
1886 cir::PtrDiffOp op, OpAdaptor adaptor,
1887 mlir::ConversionPatternRewriter &rewriter)
const {
1888 auto dstTy = mlir::cast<cir::IntType>(op.getType());
1889 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1891 auto lhs = mlir::LLVM::PtrToIntOp::create(rewriter, op.getLoc(), llvmDstTy,
1893 auto rhs = mlir::LLVM::PtrToIntOp::create(rewriter, op.getLoc(), llvmDstTy,
1897 mlir::LLVM::SubOp::create(rewriter, op.getLoc(), llvmDstTy, lhs, rhs);
1899 cir::PointerType ptrTy = op.getLhs().getType();
1901 uint64_t typeSize =
getTypeSize(ptrTy.getPointee(), *op);
1904 mlir::Value resultVal = diff.getResult();
1905 if (typeSize != 1) {
1906 auto typeSizeVal = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1907 llvmDstTy, typeSize);
1909 if (dstTy.isUnsigned()) {
1911 mlir::LLVM::UDivOp::create(rewriter, op.getLoc(), diff, typeSizeVal);
1912 uDiv.setIsExact(
true);
1913 resultVal = uDiv.getResult();
1916 mlir::LLVM::SDivOp::create(rewriter, op.getLoc(), diff, typeSizeVal);
1917 sDiv.setIsExact(
true);
1918 resultVal = sDiv.getResult();
1921 rewriter.replaceOp(op, resultVal);
1922 return mlir::success();
1925mlir::LogicalResult CIRToLLVMExpectOpLowering::matchAndRewrite(
1926 cir::ExpectOp op, OpAdaptor adaptor,
1927 mlir::ConversionPatternRewriter &rewriter)
const {
1931 std::optional<llvm::APFloat> prob = op.getProb();
1933 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpectWithProbabilityOp>(
1934 op, adaptor.getVal(), adaptor.getExpected(), prob.value());
1936 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpectOp>(op, adaptor.getVal(),
1937 adaptor.getExpected());
1938 return mlir::success();
1941mlir::LogicalResult CIRToLLVMFAbsOpLowering::matchAndRewrite(
1942 cir::FAbsOp op, OpAdaptor adaptor,
1943 mlir::ConversionPatternRewriter &rewriter)
const {
1944 mlir::Type resTy = typeConverter->convertType(op.getType());
1945 rewriter.replaceOpWithNewOp<mlir::LLVM::FAbsOp>(op, resTy,
1946 adaptor.getOperands()[0]);
1947 return mlir::success();
1954void CIRToLLVMFuncOpLowering::lowerFuncAttributes(
1955 cir::FuncOp func,
bool filterArgAndResAttrs,
1956 SmallVectorImpl<mlir::NamedAttribute> &result)
const {
1958 for (mlir::NamedAttribute attr : func->getAttrs()) {
1960 if (
attr.getName() == mlir::SymbolTable::getSymbolAttrName() ||
1961 attr.getName() == func.getFunctionTypeAttrName() ||
1963 attr.getName() == func.getGlobalVisibilityAttrName() ||
1964 attr.getName() == func.getDsoLocalAttrName() ||
1965 attr.getName() == func.getInlineKindAttrName() ||
1966 (filterArgAndResAttrs &&
1967 (
attr.getName() == func.getArgAttrsAttrName() ||
1968 attr.getName() == func.getResAttrsAttrName())))
1972 result.push_back(attr);
1976mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewriteAlias(
1977 cir::FuncOp op, llvm::StringRef aliasee, mlir::Type ty, OpAdaptor adaptor,
1978 mlir::ConversionPatternRewriter &rewriter)
const {
1979 SmallVector<mlir::NamedAttribute, 4> attributes;
1980 lowerFuncAttributes(op,
false, attributes);
1982 mlir::Location loc = op.getLoc();
1983 auto aliasOp = rewriter.replaceOpWithNewOp<mlir::LLVM::AliasOp>(
1984 op, ty,
convertLinkage(op.getLinkage()), op.getName(), op.getDsoLocal(),
1988 mlir::OpBuilder builder(op.getContext());
1989 mlir::Block *block = builder.createBlock(&aliasOp.getInitializerRegion());
1990 builder.setInsertionPointToStart(block);
1993 mlir::Type ptrTy = mlir::LLVM::LLVMPointerType::get(ty.getContext());
1994 auto addrOp = mlir::LLVM::AddressOfOp::create(builder, loc, ptrTy, aliasee);
1995 mlir::LLVM::ReturnOp::create(builder, loc, addrOp);
1997 return mlir::success();
2000mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewrite(
2001 cir::FuncOp op, OpAdaptor adaptor,
2002 mlir::ConversionPatternRewriter &rewriter)
const {
2004 cir::FuncType fnType = op.getFunctionType();
2005 bool isDsoLocal = op.getDsoLocal();
2006 mlir::TypeConverter::SignatureConversion signatureConversion(
2007 fnType.getNumInputs());
2009 for (
const auto &argType : llvm::enumerate(fnType.getInputs())) {
2010 mlir::Type convertedType = typeConverter->convertType(argType.value());
2012 return mlir::failure();
2013 signatureConversion.addInputs(argType.index(), convertedType);
2016 mlir::Type resultType =
2017 getTypeConverter()->convertType(fnType.getReturnType());
2020 mlir::Type llvmFnTy = mlir::LLVM::LLVMFunctionType::get(
2021 resultType ? resultType : mlir::LLVM::LLVMVoidType::get(getContext()),
2022 signatureConversion.getConvertedTypes(),
2026 if (std::optional<llvm::StringRef> aliasee = op.getAliasee())
2027 return matchAndRewriteAlias(op, *aliasee, llvmFnTy, adaptor, rewriter);
2031 mlir::Location loc = op.getLoc();
2032 if (mlir::FusedLoc fusedLoc = mlir::dyn_cast<mlir::FusedLoc>(loc))
2033 loc = fusedLoc.getLocations()[0];
2034 assert((mlir::isa<mlir::FileLineColLoc>(loc) ||
2035 mlir::isa<mlir::UnknownLoc>(loc)) &&
2036 "expected single location or unknown location here");
2040 mlir::LLVM::CConv cconv = mlir::LLVM::CConv::C;
2041 SmallVector<mlir::NamedAttribute, 4> attributes;
2042 lowerFuncAttributes(op,
false, attributes);
2044 mlir::LLVM::LLVMFuncOp fn = mlir::LLVM::LLVMFuncOp::create(
2045 rewriter, loc, op.getName(), llvmFnTy, linkage, isDsoLocal, cconv,
2046 mlir::SymbolRefAttr(), attributes);
2050 if (std::optional<cir::InlineKind> inlineKind = op.getInlineKind()) {
2051 fn.setNoInline(*inlineKind == cir::InlineKind::NoInline);
2052 fn.setInlineHint(*inlineKind == cir::InlineKind::InlineHint);
2053 fn.setAlwaysInline(*inlineKind == cir::InlineKind::AlwaysInline);
2056 if (std::optional<llvm::StringRef> personality = op.getPersonality())
2057 fn.setPersonality(*personality);
2062 rewriter.inlineRegionBefore(op.getBody(), fn.getBody(), fn.end());
2063 if (failed(rewriter.convertRegionTypes(&fn.getBody(), *typeConverter,
2064 &signatureConversion)))
2065 return mlir::failure();
2067 rewriter.eraseOp(op);
2069 return mlir::LogicalResult::success();
2072mlir::LogicalResult CIRToLLVMGetGlobalOpLowering::matchAndRewrite(
2073 cir::GetGlobalOp op, OpAdaptor adaptor,
2074 mlir::ConversionPatternRewriter &rewriter)
const {
2077 if (op->getUses().empty()) {
2078 rewriter.eraseOp(op);
2079 return mlir::success();
2082 mlir::Type
type = getTypeConverter()->convertType(op.getType());
2083 mlir::Operation *newop = mlir::LLVM::AddressOfOp::create(
2084 rewriter, op.getLoc(), type, op.getName());
2088 newop = mlir::LLVM::ThreadlocalAddressOp::create(rewriter, op.getLoc(),
2089 type, newop->getResult(0));
2092 rewriter.replaceOp(op, newop);
2093 return mlir::success();
2098void CIRToLLVMGlobalOpLowering::setupRegionInitializedLLVMGlobalOp(
2099 cir::GlobalOp op, mlir::ConversionPatternRewriter &rewriter)
const {
2100 const mlir::Type llvmType =
2107 const bool isConst = op.getConstant();
2109 const unsigned addrSpace = 0;
2110 const bool isDsoLocal = op.getDsoLocal();
2111 const bool isThreadLocal = (
bool)op.getTlsModelAttr();
2112 const uint64_t alignment = op.getAlignment().value_or(0);
2113 const mlir::LLVM::Linkage linkage =
convertLinkage(op.getLinkage());
2114 const StringRef symbol = op.getSymName();
2115 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
2117 SmallVector<mlir::NamedAttribute> attributes;
2118 mlir::LLVM::GlobalOp newGlobalOp =
2119 rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
2120 op, llvmType, isConst, linkage, symbol,
nullptr, alignment, addrSpace,
2121 isDsoLocal, isThreadLocal, comdatAttr, attributes);
2122 newGlobalOp.getRegion().emplaceBlock();
2123 rewriter.setInsertionPointToEnd(newGlobalOp.getInitializerBlock());
2127CIRToLLVMGlobalOpLowering::matchAndRewriteRegionInitializedGlobal(
2128 cir::GlobalOp op, mlir::Attribute init,
2129 mlir::ConversionPatternRewriter &rewriter)
const {
2131 assert((isa<cir::ConstArrayAttr, cir::ConstRecordAttr, cir::ConstVectorAttr,
2132 cir::ConstPtrAttr, cir::ConstComplexAttr, cir::DataMemberAttr,
2133 cir::GlobalViewAttr, cir::TypeInfoAttr, cir::UndefAttr,
2134 cir::VTableAttr, cir::ZeroAttr>(init)));
2139 const mlir::Location loc = op.getLoc();
2140 setupRegionInitializedLLVMGlobalOp(op, rewriter);
2141 CIRAttrToValue valueConverter(op, rewriter, typeConverter, lowerMod);
2142 mlir::Value value = valueConverter.visit(init);
2143 mlir::LLVM::ReturnOp::create(rewriter, loc, value);
2144 return mlir::success();
2147mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite(
2148 cir::GlobalOp op, OpAdaptor adaptor,
2149 mlir::ConversionPatternRewriter &rewriter)
const {
2152 if (!op.getCtorRegion().empty() || !op.getDtorRegion().empty())
2153 return op.emitError() <<
"GlobalOp ctor and dtor regions should be removed "
2154 "in LoweringPrepare";
2156 std::optional<mlir::Attribute> init = op.getInitialValue();
2159 const mlir::Type cirSymType = op.getSymType();
2162 const mlir::Type llvmType =
2166 const bool isConst = op.getConstant();
2168 const unsigned addrSpace = 0;
2169 const bool isDsoLocal = op.getDsoLocal();
2170 const bool isThreadLocal = (
bool)op.getTlsModelAttr();
2171 const uint64_t alignment = op.getAlignment().value_or(0);
2172 const mlir::LLVM::Linkage linkage =
convertLinkage(op.getLinkage());
2173 const StringRef symbol = op.getSymName();
2174 SmallVector<mlir::NamedAttribute> attributes;
2176 if (init.has_value()) {
2177 if (mlir::isa<cir::FPAttr, cir::IntAttr, cir::BoolAttr>(init.value())) {
2179 init = initRewriter.visit(init.value());
2184 if (!init.value()) {
2185 op.emitError() <<
"unsupported initializer '" << init.value() <<
"'";
2186 return mlir::failure();
2188 }
else if (mlir::isa<cir::ConstArrayAttr, cir::ConstVectorAttr,
2189 cir::ConstRecordAttr, cir::ConstPtrAttr,
2190 cir::ConstComplexAttr, cir::DataMemberAttr,
2191 cir::GlobalViewAttr, cir::TypeInfoAttr, cir::UndefAttr,
2192 cir::VTableAttr, cir::ZeroAttr>(init.value())) {
2196 return matchAndRewriteRegionInitializedGlobal(op, init.value(), rewriter);
2200 op.emitError() <<
"unsupported initializer '" << init.value() <<
"'";
2201 return mlir::failure();
2205 mlir::LLVM::Visibility visibility =
2207 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
2208 auto newOp = rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
2209 op, llvmType, isConst, linkage, symbol, init.value_or(mlir::Attribute()),
2210 alignment, addrSpace, isDsoLocal, isThreadLocal, comdatAttr, attributes);
2211 newOp.setVisibility_(visibility);
2213 return mlir::success();
2217CIRToLLVMGlobalOpLowering::getComdatAttr(cir::GlobalOp &op,
2218 mlir::OpBuilder &builder)
const {
2219 if (!op.getComdat())
2220 return mlir::SymbolRefAttr{};
2222 mlir::ModuleOp module = op->getParentOfType<mlir::ModuleOp>();
2223 mlir::OpBuilder::InsertionGuard guard(builder);
2224 StringRef comdatName(
"__llvm_comdat_globals");
2226 builder.setInsertionPointToStart(module.getBody());
2228 mlir::LLVM::ComdatOp::create(builder, module.getLoc(), comdatName);
2231 if (
auto comdatSelector = comdatOp.lookupSymbol<mlir::LLVM::ComdatSelectorOp>(
2233 return mlir::SymbolRefAttr::get(
2234 builder.getContext(), comdatName,
2235 mlir::FlatSymbolRefAttr::get(comdatSelector.getSymNameAttr()));
2238 builder.setInsertionPointToStart(&comdatOp.getBody().back());
2239 auto selectorOp = mlir::LLVM::ComdatSelectorOp::create(
2240 builder, comdatOp.getLoc(), op.getSymName(),
2241 mlir::LLVM::comdat::Comdat::Any);
2242 return mlir::SymbolRefAttr::get(
2243 builder.getContext(), comdatName,
2244 mlir::FlatSymbolRefAttr::get(selectorOp.getSymNameAttr()));
2247mlir::LogicalResult CIRToLLVMSwitchFlatOpLowering::matchAndRewrite(
2248 cir::SwitchFlatOp op, OpAdaptor adaptor,
2249 mlir::ConversionPatternRewriter &rewriter)
const {
2251 llvm::SmallVector<mlir::APInt, 8> caseValues;
2252 for (mlir::Attribute val : op.getCaseValues()) {
2253 auto intAttr = cast<cir::IntAttr>(val);
2254 caseValues.push_back(intAttr.getValue());
2257 llvm::SmallVector<mlir::Block *, 8> caseDestinations;
2258 llvm::SmallVector<mlir::ValueRange, 8> caseOperands;
2260 for (mlir::Block *x : op.getCaseDestinations())
2261 caseDestinations.push_back(x);
2263 for (mlir::OperandRange x : op.getCaseOperands())
2264 caseOperands.push_back(x);
2267 rewriter.setInsertionPoint(op);
2268 rewriter.replaceOpWithNewOp<mlir::LLVM::SwitchOp>(
2269 op, adaptor.getCondition(), op.getDefaultDestination(),
2270 op.getDefaultOperands(), caseValues, caseDestinations, caseOperands);
2271 return mlir::success();
2274mlir::LogicalResult CIRToLLVMUnaryOpLowering::matchAndRewrite(
2275 cir::UnaryOp op, OpAdaptor adaptor,
2276 mlir::ConversionPatternRewriter &rewriter)
const {
2277 assert(op.getType() == op.getInput().getType() &&
2278 "Unary operation's operand type and result type are different");
2279 mlir::Type
type = op.getType();
2280 mlir::Type elementType = elementTypeIfVector(type);
2281 bool isVector = mlir::isa<cir::VectorType>(type);
2282 mlir::Type llvmType = getTypeConverter()->convertType(type);
2283 mlir::Location loc = op.getLoc();
2286 if (mlir::isa<cir::IntType>(elementType)) {
2287 mlir::LLVM::IntegerOverflowFlags maybeNSW =
2288 op.getNoSignedWrap() ? mlir::LLVM::IntegerOverflowFlags::nsw
2289 : mlir::LLVM::IntegerOverflowFlags::none;
2290 switch (op.getKind()) {
2291 case cir::UnaryOpKind::Inc: {
2292 assert(!
isVector &&
"++ not allowed on vector types");
2293 auto one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
2294 rewriter.replaceOpWithNewOp<mlir::LLVM::AddOp>(
2295 op, llvmType, adaptor.getInput(), one, maybeNSW);
2296 return mlir::success();
2298 case cir::UnaryOpKind::Dec: {
2299 assert(!
isVector &&
"-- not allowed on vector types");
2300 auto one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
2301 rewriter.replaceOpWithNewOp<mlir::LLVM::SubOp>(op, adaptor.getInput(),
2303 return mlir::success();
2305 case cir::UnaryOpKind::Plus:
2306 rewriter.replaceOp(op, adaptor.getInput());
2307 return mlir::success();
2308 case cir::UnaryOpKind::Minus: {
2311 zero = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmType);
2313 zero = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 0);
2314 rewriter.replaceOpWithNewOp<mlir::LLVM::SubOp>(
2315 op, zero, adaptor.getInput(), maybeNSW);
2316 return mlir::success();
2318 case cir::UnaryOpKind::Not: {
2320 mlir::Value minusOne;
2323 mlir::dyn_cast<cir::VectorType>(type).getSize();
2324 std::vector<int32_t> values(numElements, -1);
2325 mlir::DenseIntElementsAttr denseVec = rewriter.getI32VectorAttr(values);
2327 mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, denseVec);
2329 minusOne = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, -1);
2331 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getInput(),
2333 return mlir::success();
2336 llvm_unreachable(
"Unexpected unary op for int");
2340 if (mlir::isa<cir::FPTypeInterface>(elementType)) {
2341 switch (op.getKind()) {
2342 case cir::UnaryOpKind::Inc: {
2343 assert(!
isVector &&
"++ not allowed on vector types");
2344 mlir::LLVM::ConstantOp one = mlir::LLVM::ConstantOp::create(
2345 rewriter, loc, llvmType, rewriter.getFloatAttr(llvmType, 1.0));
2346 rewriter.replaceOpWithNewOp<mlir::LLVM::FAddOp>(op, llvmType, one,
2347 adaptor.getInput());
2348 return mlir::success();
2350 case cir::UnaryOpKind::Dec: {
2351 assert(!
isVector &&
"-- not allowed on vector types");
2352 mlir::LLVM::ConstantOp minusOne = mlir::LLVM::ConstantOp::create(
2353 rewriter, loc, llvmType, rewriter.getFloatAttr(llvmType, -1.0));
2354 rewriter.replaceOpWithNewOp<mlir::LLVM::FAddOp>(op, llvmType, minusOne,
2355 adaptor.getInput());
2356 return mlir::success();
2358 case cir::UnaryOpKind::Plus:
2359 rewriter.replaceOp(op, adaptor.getInput());
2360 return mlir::success();
2361 case cir::UnaryOpKind::Minus:
2362 rewriter.replaceOpWithNewOp<mlir::LLVM::FNegOp>(op, llvmType,
2363 adaptor.getInput());
2364 return mlir::success();
2365 case cir::UnaryOpKind::Not:
2366 return op.emitError() <<
"Unary not is invalid for floating-point types";
2368 llvm_unreachable(
"Unexpected unary op for float");
2373 if (mlir::isa<cir::BoolType>(elementType)) {
2374 switch (op.getKind()) {
2375 case cir::UnaryOpKind::Inc:
2376 case cir::UnaryOpKind::Dec:
2377 case cir::UnaryOpKind::Plus:
2378 case cir::UnaryOpKind::Minus:
2381 return op.emitError() <<
"Unsupported unary operation on boolean type";
2382 case cir::UnaryOpKind::Not: {
2383 assert(!
isVector &&
"NYI: op! on vector mask");
2384 auto one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
2385 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getInput(),
2387 return mlir::success();
2390 llvm_unreachable(
"Unexpected unary op for bool");
2395 if (mlir::isa<cir::PointerType>(elementType)) {
2396 switch (op.getKind()) {
2397 case cir::UnaryOpKind::Plus:
2398 rewriter.replaceOp(op, adaptor.getInput());
2399 return mlir::success();
2401 op.emitError() <<
"Unknown pointer unary operation during CIR lowering";
2402 return mlir::failure();
2406 return op.emitError() <<
"Unary operation has unsupported type: "
2410mlir::LLVM::IntegerOverflowFlags
2411CIRToLLVMBinOpLowering::getIntOverflowFlag(cir::BinOp op)
const {
2412 if (op.getNoUnsignedWrap())
2413 return mlir::LLVM::IntegerOverflowFlags::nuw;
2415 if (op.getNoSignedWrap())
2416 return mlir::LLVM::IntegerOverflowFlags::nsw;
2418 return mlir::LLVM::IntegerOverflowFlags::none;
2423 return mlir::isa<cir::IntType>(type)
2424 ? mlir::cast<cir::IntType>(type).isUnsigned()
2425 : mlir::cast<mlir::IntegerType>(type).isUnsigned();
2428mlir::LogicalResult CIRToLLVMBinOpLowering::matchAndRewrite(
2429 cir::BinOp op, OpAdaptor adaptor,
2430 mlir::ConversionPatternRewriter &rewriter)
const {
2431 if (adaptor.getLhs().getType() != adaptor.getRhs().getType())
2432 return op.emitError() <<
"inconsistent operands' types not supported yet";
2434 mlir::Type type = op.getRhs().getType();
2435 if (!mlir::isa<cir::IntType, cir::BoolType, cir::FPTypeInterface,
2436 mlir::IntegerType, cir::VectorType>(type))
2437 return op.emitError() <<
"operand type not supported yet";
2439 const mlir::Type llvmTy = getTypeConverter()->convertType(op.getType());
2440 const mlir::Type llvmEltTy = elementTypeIfVector(llvmTy);
2442 const mlir::Value rhs = adaptor.getRhs();
2443 const mlir::Value lhs = adaptor.getLhs();
2444 type = elementTypeIfVector(type);
2446 switch (op.getKind()) {
2447 case cir::BinOpKind::Add:
2448 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
2449 if (op.getSaturated()) {
2451 rewriter.replaceOpWithNewOp<mlir::LLVM::UAddSat>(op, lhs, rhs);
2454 rewriter.replaceOpWithNewOp<mlir::LLVM::SAddSat>(op, lhs, rhs);
2457 rewriter.replaceOpWithNewOp<mlir::LLVM::AddOp>(op, llvmTy, lhs, rhs,
2458 getIntOverflowFlag(op));
2460 rewriter.replaceOpWithNewOp<mlir::LLVM::FAddOp>(op, lhs, rhs);
2463 case cir::BinOpKind::Sub:
2464 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
2465 if (op.getSaturated()) {
2467 rewriter.replaceOpWithNewOp<mlir::LLVM::USubSat>(op, lhs, rhs);
2470 rewriter.replaceOpWithNewOp<mlir::LLVM::SSubSat>(op, lhs, rhs);
2473 rewriter.replaceOpWithNewOp<mlir::LLVM::SubOp>(op, llvmTy, lhs, rhs,
2474 getIntOverflowFlag(op));
2476 rewriter.replaceOpWithNewOp<mlir::LLVM::FSubOp>(op, lhs, rhs);
2479 case cir::BinOpKind::Mul:
2480 if (mlir::isa<mlir::IntegerType>(llvmEltTy))
2481 rewriter.replaceOpWithNewOp<mlir::LLVM::MulOp>(op, llvmTy, lhs, rhs,
2482 getIntOverflowFlag(op));
2484 rewriter.replaceOpWithNewOp<mlir::LLVM::FMulOp>(op, lhs, rhs);
2486 case cir::BinOpKind::Div:
2487 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
2490 rewriter.replaceOpWithNewOp<mlir::LLVM::UDivOp>(op, lhs, rhs);
2492 rewriter.replaceOpWithNewOp<mlir::LLVM::SDivOp>(op, lhs, rhs);
2494 rewriter.replaceOpWithNewOp<mlir::LLVM::FDivOp>(op, lhs, rhs);
2497 case cir::BinOpKind::Rem:
2498 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
2501 rewriter.replaceOpWithNewOp<mlir::LLVM::URemOp>(op, lhs, rhs);
2503 rewriter.replaceOpWithNewOp<mlir::LLVM::SRemOp>(op, lhs, rhs);
2505 rewriter.replaceOpWithNewOp<mlir::LLVM::FRemOp>(op, lhs, rhs);
2508 case cir::BinOpKind::And:
2509 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(op, lhs, rhs);
2511 case cir::BinOpKind::Or:
2512 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(op, lhs, rhs);
2514 case cir::BinOpKind::Xor:
2515 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, lhs, rhs);
2517 case cir::BinOpKind::Max:
2518 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
2521 rewriter.replaceOpWithNewOp<mlir::LLVM::UMaxOp>(op, llvmTy, lhs, rhs);
2523 rewriter.replaceOpWithNewOp<mlir::LLVM::SMaxOp>(op, llvmTy, lhs, rhs);
2527 return mlir::LogicalResult::success();
2531static mlir::LLVM::ICmpPredicate
2533 using CIR = cir::CmpOpKind;
2534 using LLVMICmp = mlir::LLVM::ICmpPredicate;
2537 return LLVMICmp::eq;
2539 return LLVMICmp::ne;
2541 return (isSigned ? LLVMICmp::slt : LLVMICmp::ult);
2543 return (isSigned ? LLVMICmp::sle : LLVMICmp::ule);
2545 return (isSigned ? LLVMICmp::sgt : LLVMICmp::ugt);
2547 return (isSigned ? LLVMICmp::sge : LLVMICmp::uge);
2549 llvm_unreachable(
"Unknown CmpOpKind");
2554static mlir::LLVM::FCmpPredicate
2556 using CIR = cir::CmpOpKind;
2557 using LLVMFCmp = mlir::LLVM::FCmpPredicate;
2560 return LLVMFCmp::oeq;
2562 return LLVMFCmp::une;
2564 return LLVMFCmp::olt;
2566 return LLVMFCmp::ole;
2568 return LLVMFCmp::ogt;
2570 return LLVMFCmp::oge;
2572 llvm_unreachable(
"Unknown CmpOpKind");
2575mlir::LogicalResult CIRToLLVMCmpOpLowering::matchAndRewrite(
2576 cir::CmpOp cmpOp, OpAdaptor adaptor,
2577 mlir::ConversionPatternRewriter &rewriter)
const {
2578 mlir::Type type = cmpOp.getLhs().getType();
2583 if (mlir::isa<cir::IntType, mlir::IntegerType>(type)) {
2584 bool isSigned = mlir::isa<cir::IntType>(type)
2585 ? mlir::cast<cir::IntType>(type).isSigned()
2586 : mlir::cast<mlir::IntegerType>(type).isSigned();
2587 mlir::LLVM::ICmpPredicate kind =
2589 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
2590 cmpOp, kind, adaptor.getLhs(), adaptor.getRhs());
2591 return mlir::success();
2594 if (
auto ptrTy = mlir::dyn_cast<cir::PointerType>(type)) {
2595 mlir::LLVM::ICmpPredicate kind =
2598 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
2599 cmpOp, kind, adaptor.getLhs(), adaptor.getRhs());
2600 return mlir::success();
2603 if (
auto vptrTy = mlir::dyn_cast<cir::VPtrType>(type)) {
2607 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
2608 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
2609 return mlir::success();
2612 if (mlir::isa<cir::FPTypeInterface>(type)) {
2613 mlir::LLVM::FCmpPredicate
kind =
2615 rewriter.replaceOpWithNewOp<mlir::LLVM::FCmpOp>(
2616 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
2617 return mlir::success();
2620 if (mlir::isa<cir::ComplexType>(type)) {
2621 mlir::Value lhs = adaptor.getLhs();
2622 mlir::Value rhs = adaptor.getRhs();
2623 mlir::Location loc = cmpOp.getLoc();
2625 auto complexType = mlir::cast<cir::ComplexType>(cmpOp.getLhs().getType());
2626 mlir::Type complexElemTy =
2627 getTypeConverter()->convertType(
complexType.getElementType());
2629 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
2630 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{0}));
2631 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
2632 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{1}));
2633 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
2634 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{0}));
2635 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
2636 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{1}));
2638 if (cmpOp.getKind() == cir::CmpOpKind::eq) {
2639 if (complexElemTy.isInteger()) {
2640 auto realCmp = mlir::LLVM::ICmpOp::create(
2641 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, lhsReal, rhsReal);
2642 auto imagCmp = mlir::LLVM::ICmpOp::create(
2643 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, lhsImag, rhsImag);
2644 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, imagCmp);
2645 return mlir::success();
2648 auto realCmp = mlir::LLVM::FCmpOp::create(
2649 rewriter, loc, mlir::LLVM::FCmpPredicate::oeq, lhsReal, rhsReal);
2650 auto imagCmp = mlir::LLVM::FCmpOp::create(
2651 rewriter, loc, mlir::LLVM::FCmpPredicate::oeq, lhsImag, rhsImag);
2652 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, imagCmp);
2653 return mlir::success();
2656 if (cmpOp.getKind() == cir::CmpOpKind::ne) {
2657 if (complexElemTy.isInteger()) {
2658 auto realCmp = mlir::LLVM::ICmpOp::create(
2659 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, lhsReal, rhsReal);
2660 auto imagCmp = mlir::LLVM::ICmpOp::create(
2661 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, lhsImag, rhsImag);
2662 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp);
2663 return mlir::success();
2666 auto realCmp = mlir::LLVM::FCmpOp::create(
2667 rewriter, loc, mlir::LLVM::FCmpPredicate::une, lhsReal, rhsReal);
2668 auto imagCmp = mlir::LLVM::FCmpOp::create(
2669 rewriter, loc, mlir::LLVM::FCmpPredicate::une, lhsImag, rhsImag);
2670 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp);
2671 return mlir::success();
2675 return cmpOp.emitError() <<
"unsupported type for CmpOp: " <<
type;
2678mlir::LogicalResult CIRToLLVMBinOpOverflowOpLowering::matchAndRewrite(
2679 cir::BinOpOverflowOp op, OpAdaptor adaptor,
2680 mlir::ConversionPatternRewriter &rewriter)
const {
2681 mlir::Location loc = op.getLoc();
2682 cir::BinOpOverflowKind arithKind = op.getKind();
2683 cir::IntType operandTy = op.getLhs().getType();
2684 cir::IntType resultTy = op.getResult().getType();
2686 EncompassedTypeInfo encompassedTyInfo =
2687 computeEncompassedTypeWidth(operandTy, resultTy);
2688 mlir::IntegerType encompassedLLVMTy =
2689 rewriter.getIntegerType(encompassedTyInfo.width);
2691 mlir::Value lhs = adaptor.getLhs();
2692 mlir::Value rhs = adaptor.getRhs();
2693 if (operandTy.getWidth() < encompassedTyInfo.width) {
2694 if (operandTy.isSigned()) {
2695 lhs = mlir::LLVM::SExtOp::create(rewriter, loc, encompassedLLVMTy, lhs);
2696 rhs = mlir::LLVM::SExtOp::create(rewriter, loc, encompassedLLVMTy, rhs);
2698 lhs = mlir::LLVM::ZExtOp::create(rewriter, loc, encompassedLLVMTy, lhs);
2699 rhs = mlir::LLVM::ZExtOp::create(rewriter, loc, encompassedLLVMTy, rhs);
2703 std::string intrinName = getLLVMIntrinName(arithKind, encompassedTyInfo.sign,
2704 encompassedTyInfo.width);
2705 auto intrinNameAttr = mlir::StringAttr::get(op.getContext(), intrinName);
2707 mlir::IntegerType overflowLLVMTy = rewriter.getI1Type();
2708 auto intrinRetTy = mlir::LLVM::LLVMStructType::getLiteral(
2709 rewriter.getContext(), {encompassedLLVMTy, overflowLLVMTy});
2711 auto callLLVMIntrinOp = mlir::LLVM::CallIntrinsicOp::create(
2712 rewriter, loc, intrinRetTy, intrinNameAttr, mlir::ValueRange{lhs, rhs});
2713 mlir::Value intrinRet = callLLVMIntrinOp.getResult(0);
2715 mlir::Value result = mlir::LLVM::ExtractValueOp::create(
2716 rewriter, loc, intrinRet, ArrayRef<int64_t>{0})
2718 mlir::Value overflow = mlir::LLVM::ExtractValueOp::create(
2719 rewriter, loc, intrinRet, ArrayRef<int64_t>{1})
2722 if (resultTy.getWidth() < encompassedTyInfo.width) {
2723 mlir::Type resultLLVMTy = getTypeConverter()->convertType(resultTy);
2725 mlir::LLVM::TruncOp::create(rewriter, loc, resultLLVMTy, result);
2729 mlir::Value truncResultExt;
2730 if (resultTy.isSigned())
2731 truncResultExt = mlir::LLVM::SExtOp::create(
2732 rewriter, loc, encompassedLLVMTy, truncResult);
2734 truncResultExt = mlir::LLVM::ZExtOp::create(
2735 rewriter, loc, encompassedLLVMTy, truncResult);
2736 auto truncOverflow = mlir::LLVM::ICmpOp::create(
2737 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, truncResultExt, result);
2739 result = truncResult;
2740 overflow = mlir::LLVM::OrOp::create(rewriter, loc, overflow, truncOverflow);
2743 mlir::Type boolLLVMTy =
2744 getTypeConverter()->convertType(op.getOverflow().getType());
2745 if (boolLLVMTy != rewriter.getI1Type())
2746 overflow = mlir::LLVM::ZExtOp::create(rewriter, loc, boolLLVMTy, overflow);
2748 rewriter.replaceOp(op, mlir::ValueRange{result, overflow});
2750 return mlir::success();
2753std::string CIRToLLVMBinOpOverflowOpLowering::getLLVMIntrinName(
2754 cir::BinOpOverflowKind opKind,
bool isSigned,
unsigned width) {
2757 std::string
name =
"llvm.";
2760 name.push_back(
's');
2762 name.push_back(
'u');
2765 case cir::BinOpOverflowKind::Add:
2766 name.append(
"add.");
2768 case cir::BinOpOverflowKind::Sub:
2769 name.append(
"sub.");
2771 case cir::BinOpOverflowKind::Mul:
2772 name.append(
"mul.");
2776 name.append(
"with.overflow.i");
2777 name.append(std::to_string(width));
2782CIRToLLVMBinOpOverflowOpLowering::EncompassedTypeInfo
2783CIRToLLVMBinOpOverflowOpLowering::computeEncompassedTypeWidth(
2784 cir::IntType operandTy, cir::IntType resultTy) {
2785 bool sign = operandTy.getIsSigned() || resultTy.getIsSigned();
2787 std::max(operandTy.getWidth() + (
sign && operandTy.isUnsigned()),
2788 resultTy.getWidth() + (
sign && resultTy.isUnsigned()));
2789 return {
sign, width};
2792mlir::LogicalResult CIRToLLVMShiftOpLowering::matchAndRewrite(
2793 cir::ShiftOp op, OpAdaptor adaptor,
2794 mlir::ConversionPatternRewriter &rewriter)
const {
2795 assert((op.getValue().getType() == op.getType()) &&
2796 "inconsistent operands' types NYI");
2798 const mlir::Type llvmTy = getTypeConverter()->convertType(op.getType());
2799 mlir::Value amt = adaptor.getAmount();
2800 mlir::Value val = adaptor.getValue();
2802 auto cirAmtTy = mlir::dyn_cast<cir::IntType>(op.getAmount().getType());
2805 auto cirValTy = mlir::cast<cir::IntType>(op.getValue().getType());
2813 amt =
getLLVMIntCast(rewriter, amt, llvmTy,
true, cirAmtTy.getWidth(),
2814 cirValTy.getWidth());
2816 auto cirValVTy = mlir::cast<cir::VectorType>(op.getValue().getType());
2818 mlir::cast<cir::IntType>(cirValVTy.getElementType()).isUnsigned();
2822 if (op.getIsShiftleft()) {
2823 rewriter.replaceOpWithNewOp<mlir::LLVM::ShlOp>(op, llvmTy, val, amt);
2824 return mlir::success();
2828 rewriter.replaceOpWithNewOp<mlir::LLVM::LShrOp>(op, llvmTy, val, amt);
2830 rewriter.replaceOpWithNewOp<mlir::LLVM::AShrOp>(op, llvmTy, val, amt);
2831 return mlir::success();
2834mlir::LogicalResult CIRToLLVMSelectOpLowering::matchAndRewrite(
2835 cir::SelectOp op, OpAdaptor adaptor,
2836 mlir::ConversionPatternRewriter &rewriter)
const {
2837 auto getConstantBool = [](mlir::Value value) -> cir::BoolAttr {
2838 auto definingOp = value.getDefiningOp<cir::ConstantOp>();
2842 auto constValue = definingOp.getValueAttr<cir::BoolAttr>();
2852 if (mlir::isa<cir::BoolType>(op.getTrueValue().getType())) {
2853 cir::BoolAttr trueValue = getConstantBool(op.getTrueValue());
2854 cir::BoolAttr falseValue = getConstantBool(op.getFalseValue());
2855 if (falseValue && !falseValue.getValue()) {
2857 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(op, adaptor.getCondition(),
2858 adaptor.getTrueValue());
2859 return mlir::success();
2861 if (trueValue && trueValue.getValue()) {
2863 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(op, adaptor.getCondition(),
2864 adaptor.getFalseValue());
2865 return mlir::success();
2869 mlir::Value llvmCondition = adaptor.getCondition();
2870 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(
2871 op, llvmCondition, adaptor.getTrueValue(), adaptor.getFalseValue());
2873 return mlir::success();
2877 mlir::PatternRewriter rewriter{
module->getContext()};
2882 if (!module->hasAttr(cir::CIRDialect::getTripleAttrName()))
2888 mlir::DataLayout &dataLayout,
2890 converter.addConversion([&](cir::PointerType type) -> mlir::Type {
2891 unsigned addrSpace =
2892 type.getAddrSpace() ? type.getAddrSpace().getValue().getUInt() : 0;
2893 return mlir::LLVM::LLVMPointerType::get(type.getContext(), addrSpace);
2895 converter.addConversion([&](cir::VPtrType type) -> mlir::Type {
2897 return mlir::LLVM::LLVMPointerType::get(type.getContext());
2899 converter.addConversion(
2900 [&, lowerModule](cir::DataMemberType type) -> mlir::Type {
2901 assert(lowerModule &&
"CXXABI is not available");
2902 mlir::Type abiType =
2904 return converter.convertType(abiType);
2906 converter.addConversion([&](cir::ArrayType type) -> mlir::Type {
2909 return mlir::LLVM::LLVMArrayType::get(ty, type.getSize());
2911 converter.addConversion([&](cir::VectorType type) -> mlir::Type {
2912 const mlir::Type ty = converter.convertType(type.getElementType());
2913 return mlir::VectorType::get(type.getSize(), ty, {type.getIsScalable()});
2915 converter.addConversion([&](cir::BoolType type) -> mlir::Type {
2916 return mlir::IntegerType::get(type.getContext(), 1,
2917 mlir::IntegerType::Signless);
2919 converter.addConversion([&](cir::IntType type) -> mlir::Type {
2921 return mlir::IntegerType::get(type.getContext(), type.getWidth());
2923 converter.addConversion([&](cir::SingleType type) -> mlir::Type {
2924 return mlir::Float32Type::get(type.getContext());
2926 converter.addConversion([&](cir::DoubleType type) -> mlir::Type {
2927 return mlir::Float64Type::get(type.getContext());
2929 converter.addConversion([&](cir::FP80Type type) -> mlir::Type {
2930 return mlir::Float80Type::get(type.getContext());
2932 converter.addConversion([&](cir::FP128Type type) -> mlir::Type {
2933 return mlir::Float128Type::get(type.getContext());
2935 converter.addConversion([&](cir::LongDoubleType type) -> mlir::Type {
2936 return converter.convertType(type.getUnderlying());
2938 converter.addConversion([&](cir::FP16Type type) -> mlir::Type {
2939 return mlir::Float16Type::get(type.getContext());
2941 converter.addConversion([&](cir::BF16Type type) -> mlir::Type {
2942 return mlir::BFloat16Type::get(type.getContext());
2944 converter.addConversion([&](cir::ComplexType type) -> mlir::Type {
2947 mlir::Type elementTy = converter.convertType(type.getElementType());
2948 mlir::Type structFields[2] = {elementTy, elementTy};
2949 return mlir::LLVM::LLVMStructType::getLiteral(type.getContext(),
2952 converter.addConversion([&](cir::FuncType type) -> std::optional<mlir::Type> {
2953 auto result = converter.convertType(type.getReturnType());
2955 arguments.reserve(type.getNumInputs());
2956 if (converter.convertTypes(type.getInputs(), arguments).failed())
2957 return std::nullopt;
2958 auto varArg = type.isVarArg();
2959 return mlir::LLVM::LLVMFunctionType::get(result, arguments, varArg);
2961 converter.addConversion([&](cir::RecordType type) -> mlir::Type {
2964 switch (type.getKind()) {
2965 case cir::RecordType::Class:
2966 case cir::RecordType::Struct:
2967 for (mlir::Type ty : type.getMembers())
2971 case cir::RecordType::Union:
2972 if (
auto largestMember = type.getLargestMember(dataLayout))
2973 llvmMembers.push_back(
2975 if (type.getPadded()) {
2976 auto last = *type.getMembers().rbegin();
2977 llvmMembers.push_back(
2984 mlir::LLVM::LLVMStructType llvmStruct;
2985 if (type.getName()) {
2986 llvmStruct = mlir::LLVM::LLVMStructType::getIdentified(
2987 type.getContext(), type.getPrefixedName());
2988 if (llvmStruct.setBody(llvmMembers, type.getPacked()).failed())
2989 llvm_unreachable(
"Failed to set body of record");
2991 llvmStruct = mlir::LLVM::LLVMStructType::getLiteral(
2992 type.getContext(), llvmMembers, type.getPacked());
2997 converter.addConversion([&](cir::VoidType type) -> mlir::Type {
2998 return mlir::LLVM::LLVMVoidType::get(type.getContext());
3003 mlir::ModuleOp module, StringRef globalXtorName, StringRef llvmXtorName,
3004 llvm::function_ref<std::pair<StringRef, int>(mlir::Attribute)> createXtor) {
3006 for (
const mlir::NamedAttribute namedAttr : module->getAttrs()) {
3007 if (namedAttr.getName() == globalXtorName) {
3008 for (
auto attr : mlir::cast<mlir::ArrayAttr>(namedAttr.getValue()))
3009 globalXtors.emplace_back(createXtor(attr));
3014 if (globalXtors.empty())
3017 mlir::OpBuilder builder(module.getContext());
3018 builder.setInsertionPointToEnd(&module.getBodyRegion().back());
3022 auto ctorPFTy = mlir::LLVM::LLVMPointerType::get(builder.getContext());
3024 ctorStructFields.push_back(builder.getI32Type());
3025 ctorStructFields.push_back(ctorPFTy);
3026 ctorStructFields.push_back(ctorPFTy);
3028 auto ctorStructTy = mlir::LLVM::LLVMStructType::getLiteral(
3029 builder.getContext(), ctorStructFields);
3030 auto ctorStructArrayTy =
3031 mlir::LLVM::LLVMArrayType::get(ctorStructTy, globalXtors.size());
3033 mlir::Location loc =
module.getLoc();
3034 auto newGlobalOp = mlir::LLVM::GlobalOp::create(
3035 builder, loc, ctorStructArrayTy,
false,
3036 mlir::LLVM::Linkage::Appending, llvmXtorName, mlir::Attribute());
3038 builder.createBlock(&newGlobalOp.getRegion());
3039 builder.setInsertionPointToEnd(newGlobalOp.getInitializerBlock());
3041 mlir::Value result =
3042 mlir::LLVM::UndefOp::create(builder, loc, ctorStructArrayTy);
3044 for (
auto [index, fn] : llvm::enumerate(globalXtors)) {
3045 mlir::Value structInit =
3046 mlir::LLVM::UndefOp::create(builder, loc, ctorStructTy);
3047 mlir::Value initPriority = mlir::LLVM::ConstantOp::create(
3048 builder, loc, ctorStructFields[0], fn.second);
3049 mlir::Value initFuncAddr = mlir::LLVM::AddressOfOp::create(
3050 builder, loc, ctorStructFields[1], fn.first);
3051 mlir::Value initAssociate =
3052 mlir::LLVM::ZeroOp::create(builder, loc, ctorStructFields[2]);
3055 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
3056 initPriority, zero);
3057 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
3060 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
3062 result = mlir::LLVM::InsertValueOp::create(builder, loc, result, structInit,
3066 mlir::LLVM::ReturnOp::create(builder, loc, result);
3104 parent->walk([&](mlir::Block *blk) {
3105 if (blk->hasNoPredecessors() && !blk->isEntryBlock())
3106 unreachableBlocks.push_back(blk);
3109 std::set<mlir::Block *> visited;
3110 for (mlir::Block *root : unreachableBlocks) {
3113 std::deque<mlir::Block *> workList;
3114 workList.push_back(root);
3116 while (!workList.empty()) {
3117 mlir::Block *blk = workList.back();
3118 workList.pop_back();
3119 if (visited.count(blk))
3121 visited.emplace(blk);
3123 for (mlir::Operation &op : *blk)
3126 for (mlir::Block *succ : blk->getSuccessors())
3127 workList.push_back(succ);
3132mlir::LogicalResult CIRToLLVMObjSizeOpLowering::matchAndRewrite(
3133 cir::ObjSizeOp op, OpAdaptor adaptor,
3134 mlir::ConversionPatternRewriter &rewriter)
const {
3135 mlir::Type llvmResTy = getTypeConverter()->convertType(op.getType());
3136 mlir::Location loc = op->getLoc();
3138 mlir::IntegerType i1Ty = rewriter.getI1Type();
3140 auto i1Val = [&rewriter, &loc, &i1Ty](
bool val) {
3141 return mlir::LLVM::ConstantOp::create(rewriter, loc, i1Ty, val);
3148 i1Val(op.getNullunknown()),
3149 i1Val(op.getDynamic()),
3152 return mlir::LogicalResult::success();
3157 if (mlir::Attribute tripleAttr =
3158 module->getAttr(cir::CIRDialect::getTripleAttrName()))
3159 module->setAttr(mlir::LLVM::LLVMDialect::getTargetTripleAttrName(),
3162 if (mlir::Attribute asmAttr =
3163 module->getAttr(cir::CIRDialect::getModuleLevelAsmAttrName()))
3164 module->setAttr(mlir::LLVM::LLVMDialect::getModuleLevelAsmAttrName(),
3169 llvm::TimeTraceScope scope(
"Convert CIR to LLVM Pass");
3171 mlir::ModuleOp module = getOperation();
3172 mlir::DataLayout dl(module);
3173 mlir::LLVMTypeConverter converter(&getContext());
3177 mlir::RewritePatternSet patterns(&getContext());
3180#define GET_LLVM_LOWERING_PATTERNS_LIST
3181#include "clang/CIR/Dialect/IR/CIRLowering.inc"
3182#undef GET_LLVM_LOWERING_PATTERNS_LIST
3183 >(converter, patterns.getContext(), lowerModule.get(), dl);
3187 mlir::ConversionTarget target(getContext());
3188 target.addLegalOp<mlir::ModuleOp>();
3189 target.addLegalDialect<mlir::LLVM::LLVMDialect>();
3190 target.addIllegalDialect<mlir::BuiltinDialect, cir::CIRDialect,
3191 mlir::func::FuncDialect>();
3194 ops.push_back(module);
3197 if (failed(applyPartialConversion(ops, target, std::move(patterns))))
3198 signalPassFailure();
3202 "llvm.global_ctors", [](mlir::Attribute attr) {
3203 auto ctorAttr = mlir::cast<cir::GlobalCtorAttr>(attr);
3204 return std::make_pair(ctorAttr.getName(),
3205 ctorAttr.getPriority());
3209 "llvm.global_dtors", [](mlir::Attribute attr) {
3210 auto dtorAttr = mlir::cast<cir::GlobalDtorAttr>(attr);
3211 return std::make_pair(dtorAttr.getName(),
3212 dtorAttr.getPriority());
3216mlir::LogicalResult CIRToLLVMBrOpLowering::matchAndRewrite(
3217 cir::BrOp op, OpAdaptor adaptor,
3218 mlir::ConversionPatternRewriter &rewriter)
const {
3219 rewriter.replaceOpWithNewOp<mlir::LLVM::BrOp>(op, adaptor.getOperands(),
3221 return mlir::LogicalResult::success();
3224mlir::LogicalResult CIRToLLVMGetMemberOpLowering::matchAndRewrite(
3225 cir::GetMemberOp op, OpAdaptor adaptor,
3226 mlir::ConversionPatternRewriter &rewriter)
const {
3227 mlir::Type llResTy = getTypeConverter()->convertType(op.getType());
3228 const auto recordTy =
3229 mlir::cast<cir::RecordType>(op.getAddrTy().getPointee());
3230 assert(recordTy &&
"expected record type");
3232 switch (recordTy.getKind()) {
3233 case cir::RecordType::Class:
3234 case cir::RecordType::Struct: {
3238 const mlir::Type elementTy = getTypeConverter()->convertType(recordTy);
3239 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, llResTy, elementTy,
3240 adaptor.getAddr(), offset);
3241 return mlir::success();
3243 case cir::RecordType::Union:
3246 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(op, llResTy,
3248 return mlir::success();
3252mlir::LogicalResult CIRToLLVMGetRuntimeMemberOpLowering::matchAndRewrite(
3253 cir::GetRuntimeMemberOp op, OpAdaptor adaptor,
3254 mlir::ConversionPatternRewriter &rewriter)
const {
3255 assert(lowerMod &&
"lowering module is not available");
3256 mlir::Type llvmResTy = getTypeConverter()->convertType(op.getType());
3257 mlir::Operation *llvmOp = lowerMod->getCXXABI().lowerGetRuntimeMember(
3258 op, llvmResTy, adaptor.getAddr(), adaptor.getMember(), rewriter);
3259 rewriter.replaceOp(op, llvmOp);
3260 return mlir::success();
3263mlir::LogicalResult CIRToLLVMUnreachableOpLowering::matchAndRewrite(
3264 cir::UnreachableOp op, OpAdaptor adaptor,
3265 mlir::ConversionPatternRewriter &rewriter)
const {
3266 rewriter.replaceOpWithNewOp<mlir::LLVM::UnreachableOp>(op);
3267 return mlir::success();
3271 mlir::Operation *srcOp, llvm::StringRef fnName,
3273 auto modOp = srcOp->getParentOfType<mlir::ModuleOp>();
3274 auto enclosingFnOp = srcOp->getParentOfType<mlir::LLVM::LLVMFuncOp>();
3275 mlir::Operation *sourceSymbol =
3276 mlir::SymbolTable::lookupSymbolIn(modOp, fnName);
3277 if (!sourceSymbol) {
3278 mlir::OpBuilder::InsertionGuard guard(rewriter);
3279 rewriter.setInsertionPoint(enclosingFnOp);
3280 mlir::LLVM::LLVMFuncOp::create(rewriter, srcOp->getLoc(), fnName, fnTy);
3284mlir::LogicalResult CIRToLLVMThrowOpLowering::matchAndRewrite(
3285 cir::ThrowOp op, OpAdaptor adaptor,
3286 mlir::ConversionPatternRewriter &rewriter)
const {
3287 mlir::Location loc = op.getLoc();
3288 auto voidTy = mlir::LLVM::LLVMVoidType::get(getContext());
3290 if (op.rethrows()) {
3291 auto funcTy = mlir::LLVM::LLVMFunctionType::get(voidTy, {});
3294 const llvm::StringRef functionName =
"__cxa_rethrow";
3297 auto cxaRethrow = mlir::LLVM::CallOp::create(
3298 rewriter, loc, mlir::TypeRange{}, functionName);
3300 rewriter.replaceOp(op, cxaRethrow);
3301 return mlir::success();
3304 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3305 auto fnTy = mlir::LLVM::LLVMFunctionType::get(
3306 voidTy, {llvmPtrTy, llvmPtrTy, llvmPtrTy});
3309 const llvm::StringRef fnName =
"__cxa_throw";
3312 mlir::Value typeInfo = mlir::LLVM::AddressOfOp::create(
3313 rewriter, loc, mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
3314 adaptor.getTypeInfoAttr());
3318 dtor = mlir::LLVM::AddressOfOp::create(rewriter, loc, llvmPtrTy,
3319 adaptor.getDtorAttr());
3321 dtor = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmPtrTy);
3324 auto cxaThrowCall = mlir::LLVM::CallOp::create(
3325 rewriter, loc, mlir::TypeRange{}, fnName,
3326 mlir::ValueRange{adaptor.getExceptionPtr(), typeInfo, dtor});
3328 rewriter.replaceOp(op, cxaThrowCall);
3329 return mlir::success();
3332mlir::LogicalResult CIRToLLVMAllocExceptionOpLowering::matchAndRewrite(
3333 cir::AllocExceptionOp op, OpAdaptor adaptor,
3334 mlir::ConversionPatternRewriter &rewriter)
const {
3336 StringRef fnName =
"__cxa_allocate_exception";
3337 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3338 auto int64Ty = mlir::IntegerType::get(rewriter.getContext(), 64);
3339 auto fnTy = mlir::LLVM::LLVMFunctionType::get(llvmPtrTy, {int64Ty});
3342 auto exceptionSize = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
3343 adaptor.getSizeAttr());
3345 auto allocaExceptionCall = mlir::LLVM::CallOp::create(
3346 rewriter, op.getLoc(), mlir::TypeRange{llvmPtrTy}, fnName,
3347 mlir::ValueRange{exceptionSize});
3349 rewriter.replaceOp(op, allocaExceptionCall);
3350 return mlir::success();
3353static mlir::LLVM::LLVMStructType
3356 mlir::MLIRContext *ctx = rewriter.getContext();
3357 auto llvmPtr = mlir::LLVM::LLVMPointerType::get(ctx);
3359 return mlir::LLVM::LLVMStructType::getLiteral(ctx, structFields);
3362mlir::LogicalResult CIRToLLVMEhInflightOpLowering::matchAndRewrite(
3363 cir::EhInflightOp op, OpAdaptor adaptor,
3364 mlir::ConversionPatternRewriter &rewriter)
const {
3365 auto llvmFn = op->getParentOfType<mlir::LLVM::LLVMFuncOp>();
3366 assert(llvmFn &&
"expected LLVM function parent");
3367 mlir::Block *entryBlock = &llvmFn.getRegion().front();
3368 assert(entryBlock->isEntryBlock());
3370 mlir::ArrayAttr catchListAttr = op.getCatchTypeListAttr();
3371 mlir::SmallVector<mlir::Value> catchSymAddrs;
3373 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3374 mlir::Location loc = op.getLoc();
3379 if (catchListAttr) {
3382 for (mlir::Attribute catchAttr : catchListAttr) {
3383 auto symAttr = cast<mlir::FlatSymbolRefAttr>(catchAttr);
3386 mlir::OpBuilder::InsertionGuard guard(rewriter);
3387 rewriter.setInsertionPointToStart(entryBlock);
3388 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
3389 rewriter, loc, llvmPtrTy, symAttr.getValue());
3390 catchSymAddrs.push_back(addrOp);
3392 }
else if (!op.getCleanup()) {
3396 mlir::OpBuilder::InsertionGuard guard(rewriter);
3397 rewriter.setInsertionPointToStart(entryBlock);
3398 mlir::Value nullOp = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmPtrTy);
3399 catchSymAddrs.push_back(nullOp);
3404 mlir::LLVM::LLVMStructType llvmLandingPadStructTy =
3406 auto landingPadOp = mlir::LLVM::LandingpadOp::create(
3407 rewriter, loc, llvmLandingPadStructTy, catchSymAddrs);
3409 if (op.getCleanup())
3410 landingPadOp.setCleanup(
true);
3413 mlir::LLVM::ExtractValueOp::create(rewriter, loc, landingPadOp, 0);
3414 mlir::Value selector =
3415 mlir::LLVM::ExtractValueOp::create(rewriter, loc, landingPadOp, 1);
3416 rewriter.replaceOp(op, mlir::ValueRange{slot, selector});
3418 return mlir::success();
3421mlir::LogicalResult CIRToLLVMTrapOpLowering::matchAndRewrite(
3422 cir::TrapOp op, OpAdaptor adaptor,
3423 mlir::ConversionPatternRewriter &rewriter)
const {
3424 mlir::Location loc = op->getLoc();
3425 rewriter.eraseOp(op);
3427 mlir::LLVM::Trap::create(rewriter, loc);
3432 mlir::LLVM::UnreachableOp::create(rewriter, loc);
3434 return mlir::success();
3439 mlir::ConversionPatternRewriter &rewriter,
3440 const mlir::TypeConverter *converter,
3441 mlir::FlatSymbolRefAttr nameAttr, mlir::Type &eltType) {
3442 auto module = op->getParentOfType<mlir::ModuleOp>();
3443 mlir::Operation *symbol = mlir::SymbolTable::lookupSymbolIn(module, nameAttr);
3444 if (
auto llvmSymbol = mlir::dyn_cast<mlir::LLVM::GlobalOp>(symbol)) {
3445 eltType = llvmSymbol.getType();
3446 }
else if (
auto cirSymbol = mlir::dyn_cast<cir::GlobalOp>(symbol)) {
3447 eltType = converter->convertType(cirSymbol.getSymType());
3449 op->emitError() <<
"unexpected symbol type for " << symbol;
3453 return mlir::LLVM::AddressOfOp::create(
3454 rewriter, op->getLoc(),
3455 mlir::LLVM::LLVMPointerType::get(op->getContext()), nameAttr.getValue());
3458mlir::LogicalResult CIRToLLVMVTableAddrPointOpLowering::matchAndRewrite(
3459 cir::VTableAddrPointOp op, OpAdaptor adaptor,
3460 mlir::ConversionPatternRewriter &rewriter)
const {
3461 const mlir::TypeConverter *converter = getTypeConverter();
3462 mlir::Type targetType = converter->convertType(op.getType());
3466 op.getNameAttr(), eltType);
3468 return op.emitError() <<
"Unable to get value for vtable symbol";
3471 0, op.getAddressPointAttr().getIndex(),
3472 op.getAddressPointAttr().getOffset()};
3474 assert(eltType &&
"Shouldn't ever be missing an eltType here");
3475 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
3476 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
3477 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, targetType, eltType,
3478 symAddr, offsets, inboundsNuw);
3479 return mlir::success();
3482mlir::LogicalResult CIRToLLVMVTableGetVPtrOpLowering::matchAndRewrite(
3483 cir::VTableGetVPtrOp op, OpAdaptor adaptor,
3484 mlir::ConversionPatternRewriter &rewriter)
const {
3488 mlir::Value srcVal = adaptor.getSrc();
3489 rewriter.replaceOp(op, srcVal);
3490 return mlir::success();
3493mlir::LogicalResult CIRToLLVMVTableGetVirtualFnAddrOpLowering::matchAndRewrite(
3494 cir::VTableGetVirtualFnAddrOp op, OpAdaptor adaptor,
3495 mlir::ConversionPatternRewriter &rewriter)
const {
3496 mlir::Type targetType = getTypeConverter()->convertType(op.getType());
3497 auto eltType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3498 llvm::SmallVector<mlir::LLVM::GEPArg> offsets =
3499 llvm::SmallVector<mlir::LLVM::GEPArg>{op.getIndex()};
3500 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
3501 op, targetType, eltType, adaptor.getVptr(), offsets,
3502 mlir::LLVM::GEPNoWrapFlags::inbounds);
3503 return mlir::success();
3506mlir::LogicalResult CIRToLLVMVTTAddrPointOpLowering::matchAndRewrite(
3507 cir::VTTAddrPointOp op, OpAdaptor adaptor,
3508 mlir::ConversionPatternRewriter &rewriter)
const {
3509 const mlir::Type resultType = getTypeConverter()->convertType(op.getType());
3510 llvm::SmallVector<mlir::LLVM::GEPArg> offsets;
3512 mlir::Value llvmAddr = adaptor.getSymAddr();
3514 if (op.getSymAddr()) {
3515 if (op.getOffset() == 0) {
3516 rewriter.replaceOp(op, {llvmAddr});
3517 return mlir::success();
3520 offsets.push_back(adaptor.getOffset());
3521 eltType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3524 op.getNameAttr(), eltType);
3525 assert(eltType &&
"Shouldn't ever be missing an eltType here");
3526 offsets.push_back(0);
3527 offsets.push_back(adaptor.getOffset());
3529 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
3530 op, resultType, eltType, llvmAddr, offsets,
3531 mlir::LLVM::GEPNoWrapFlags::inbounds);
3532 return mlir::success();
3535mlir::LogicalResult CIRToLLVMStackSaveOpLowering::matchAndRewrite(
3536 cir::StackSaveOp op, OpAdaptor adaptor,
3537 mlir::ConversionPatternRewriter &rewriter)
const {
3538 const mlir::Type ptrTy = getTypeConverter()->convertType(op.getType());
3539 rewriter.replaceOpWithNewOp<mlir::LLVM::StackSaveOp>(op, ptrTy);
3540 return mlir::success();
3543mlir::LogicalResult CIRToLLVMStackRestoreOpLowering::matchAndRewrite(
3544 cir::StackRestoreOp op, OpAdaptor adaptor,
3545 mlir::ConversionPatternRewriter &rewriter)
const {
3546 rewriter.replaceOpWithNewOp<mlir::LLVM::StackRestoreOp>(op, adaptor.getPtr());
3547 return mlir::success();
3550mlir::LogicalResult CIRToLLVMVecCreateOpLowering::matchAndRewrite(
3551 cir::VecCreateOp op, OpAdaptor adaptor,
3552 mlir::ConversionPatternRewriter &rewriter)
const {
3555 const auto vecTy = mlir::cast<cir::VectorType>(op.getType());
3556 const mlir::Type llvmTy = typeConverter->convertType(vecTy);
3557 const mlir::Location loc = op.getLoc();
3558 mlir::Value result = mlir::LLVM::PoisonOp::create(rewriter, loc, llvmTy);
3559 assert(vecTy.getSize() == op.getElements().size() &&
3560 "cir.vec.create op count doesn't match vector type elements count");
3562 for (uint64_t i = 0; i < vecTy.getSize(); ++i) {
3563 const mlir::Value indexValue =
3564 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
3565 result = mlir::LLVM::InsertElementOp::create(
3566 rewriter, loc, result, adaptor.getElements()[i], indexValue);
3569 rewriter.replaceOp(op, result);
3570 return mlir::success();
3573mlir::LogicalResult CIRToLLVMVecExtractOpLowering::matchAndRewrite(
3574 cir::VecExtractOp op, OpAdaptor adaptor,
3575 mlir::ConversionPatternRewriter &rewriter)
const {
3576 rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractElementOp>(
3577 op, adaptor.getVec(), adaptor.getIndex());
3578 return mlir::success();
3581mlir::LogicalResult CIRToLLVMVecInsertOpLowering::matchAndRewrite(
3582 cir::VecInsertOp op, OpAdaptor adaptor,
3583 mlir::ConversionPatternRewriter &rewriter)
const {
3584 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertElementOp>(
3585 op, adaptor.getVec(), adaptor.getValue(), adaptor.getIndex());
3586 return mlir::success();
3589mlir::LogicalResult CIRToLLVMVecCmpOpLowering::matchAndRewrite(
3590 cir::VecCmpOp op, OpAdaptor adaptor,
3591 mlir::ConversionPatternRewriter &rewriter)
const {
3592 mlir::Type elementType = elementTypeIfVector(op.getLhs().getType());
3593 mlir::Value bitResult;
3594 if (
auto intType = mlir::dyn_cast<cir::IntType>(elementType)) {
3595 bitResult = mlir::LLVM::ICmpOp::create(
3596 rewriter, op.getLoc(),
3598 adaptor.getLhs(), adaptor.getRhs());
3599 }
else if (mlir::isa<cir::FPTypeInterface>(elementType)) {
3600 bitResult = mlir::LLVM::FCmpOp::create(
3602 adaptor.getLhs(), adaptor.getRhs());
3604 return op.emitError() <<
"unsupported type for VecCmpOp: " << elementType;
3609 rewriter.replaceOpWithNewOp<mlir::LLVM::SExtOp>(
3610 op, typeConverter->convertType(op.getType()), bitResult);
3611 return mlir::success();
3614mlir::LogicalResult CIRToLLVMVecSplatOpLowering::matchAndRewrite(
3615 cir::VecSplatOp op, OpAdaptor adaptor,
3616 mlir::ConversionPatternRewriter &rewriter)
const {
3622 cir::VectorType vecTy = op.getType();
3623 mlir::Type llvmTy = typeConverter->convertType(vecTy);
3624 mlir::Location loc = op.getLoc();
3625 mlir::Value poison = mlir::LLVM::PoisonOp::create(rewriter, loc, llvmTy);
3627 mlir::Value elementValue = adaptor.getValue();
3628 if (elementValue.getDefiningOp<mlir::LLVM::PoisonOp>()) {
3631 rewriter.replaceOp(op, poison);
3632 return mlir::success();
3635 if (
auto constValue = elementValue.getDefiningOp<mlir::LLVM::ConstantOp>()) {
3636 if (
auto intAttr = dyn_cast<mlir::IntegerAttr>(constValue.getValue())) {
3637 mlir::DenseIntElementsAttr denseVec = mlir::DenseIntElementsAttr::get(
3638 mlir::cast<mlir::ShapedType>(llvmTy), intAttr.getValue());
3639 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
3640 op, denseVec.getType(), denseVec);
3641 return mlir::success();
3644 if (
auto fpAttr = dyn_cast<mlir::FloatAttr>(constValue.getValue())) {
3645 mlir::DenseFPElementsAttr denseVec = mlir::DenseFPElementsAttr::get(
3646 mlir::cast<mlir::ShapedType>(llvmTy), fpAttr.getValue());
3647 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
3648 op, denseVec.getType(), denseVec);
3649 return mlir::success();
3653 mlir::Value indexValue =
3654 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), 0);
3655 mlir::Value oneElement = mlir::LLVM::InsertElementOp::create(
3656 rewriter, loc, poison, elementValue, indexValue);
3657 SmallVector<int32_t> zeroValues(vecTy.getSize(), 0);
3658 rewriter.replaceOpWithNewOp<mlir::LLVM::ShuffleVectorOp>(op, oneElement,
3659 poison, zeroValues);
3660 return mlir::success();
3663mlir::LogicalResult CIRToLLVMVecShuffleOpLowering::matchAndRewrite(
3664 cir::VecShuffleOp op, OpAdaptor adaptor,
3665 mlir::ConversionPatternRewriter &rewriter)
const {
3669 SmallVector<int, 8> indices;
3671 op.getIndices().begin(), op.getIndices().end(),
3672 std::back_inserter(indices), [](mlir::Attribute intAttr) {
3673 return mlir::cast<cir::IntAttr>(intAttr).getValue().getSExtValue();
3675 rewriter.replaceOpWithNewOp<mlir::LLVM::ShuffleVectorOp>(
3676 op, adaptor.getVec1(), adaptor.getVec2(), indices);
3677 return mlir::success();
3680mlir::LogicalResult CIRToLLVMVecShuffleDynamicOpLowering::matchAndRewrite(
3681 cir::VecShuffleDynamicOp op, OpAdaptor adaptor,
3682 mlir::ConversionPatternRewriter &rewriter)
const {
3694 mlir::Location loc = op.getLoc();
3695 mlir::Value input = adaptor.getVec();
3696 mlir::Type llvmIndexVecType =
3697 getTypeConverter()->convertType(op.getIndices().getType());
3698 mlir::Type llvmIndexType = getTypeConverter()->convertType(
3699 elementTypeIfVector(op.getIndices().getType()));
3701 mlir::cast<cir::VectorType>(op.getVec().getType()).getSize();
3703 uint64_t maskBits = llvm::NextPowerOf2(numElements - 1) - 1;
3704 mlir::Value maskValue = mlir::LLVM::ConstantOp::create(
3705 rewriter, loc, llvmIndexType,
3706 rewriter.getIntegerAttr(llvmIndexType, maskBits));
3707 mlir::Value maskVector =
3708 mlir::LLVM::UndefOp::create(rewriter, loc, llvmIndexVecType);
3710 for (uint64_t i = 0; i < numElements; ++i) {
3711 mlir::Value idxValue =
3712 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
3713 maskVector = mlir::LLVM::InsertElementOp::create(rewriter, loc, maskVector,
3714 maskValue, idxValue);
3717 mlir::Value maskedIndices = mlir::LLVM::AndOp::create(
3718 rewriter, loc, llvmIndexVecType, adaptor.getIndices(), maskVector);
3719 mlir::Value result = mlir::LLVM::UndefOp::create(
3720 rewriter, loc, getTypeConverter()->convertType(op.getVec().getType()));
3721 for (uint64_t i = 0; i < numElements; ++i) {
3722 mlir::Value iValue =
3723 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
3724 mlir::Value indexValue = mlir::LLVM::ExtractElementOp::create(
3725 rewriter, loc, maskedIndices, iValue);
3726 mlir::Value valueAtIndex =
3727 mlir::LLVM::ExtractElementOp::create(rewriter, loc, input, indexValue);
3728 result = mlir::LLVM::InsertElementOp::create(rewriter, loc, result,
3729 valueAtIndex, iValue);
3731 rewriter.replaceOp(op, result);
3732 return mlir::success();
3735mlir::LogicalResult CIRToLLVMVecTernaryOpLowering::matchAndRewrite(
3736 cir::VecTernaryOp op, OpAdaptor adaptor,
3737 mlir::ConversionPatternRewriter &rewriter)
const {
3739 mlir::Value bitVec = mlir::LLVM::ICmpOp::create(
3740 rewriter, op.getLoc(), mlir::LLVM::ICmpPredicate::ne, adaptor.getCond(),
3741 mlir::LLVM::ZeroOp::create(
3742 rewriter, op.getCond().getLoc(),
3743 typeConverter->convertType(op.getCond().getType())));
3744 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(
3745 op, bitVec, adaptor.getLhs(), adaptor.getRhs());
3746 return mlir::success();
3749mlir::LogicalResult CIRToLLVMComplexAddOpLowering::matchAndRewrite(
3750 cir::ComplexAddOp op, OpAdaptor adaptor,
3751 mlir::ConversionPatternRewriter &rewriter)
const {
3752 mlir::Value lhs = adaptor.getLhs();
3753 mlir::Value rhs = adaptor.getRhs();
3754 mlir::Location loc = op.getLoc();
3756 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
3757 mlir::Type complexElemTy =
3758 getTypeConverter()->convertType(
complexType.getElementType());
3759 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
3760 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{0}));
3761 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
3762 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{1}));
3763 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
3764 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{0}));
3765 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
3766 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{1}));
3768 mlir::Value newReal;
3769 mlir::Value newImag;
3770 if (complexElemTy.isInteger()) {
3771 newReal = mlir::LLVM::AddOp::create(rewriter, loc, complexElemTy, lhsReal,
3773 newImag = mlir::LLVM::AddOp::create(rewriter, loc, complexElemTy, lhsImag,
3778 newReal = mlir::LLVM::FAddOp::create(rewriter, loc, complexElemTy, lhsReal,
3780 newImag = mlir::LLVM::FAddOp::create(rewriter, loc, complexElemTy, lhsImag,
3784 mlir::Type complexLLVMTy =
3785 getTypeConverter()->convertType(op.getResult().getType());
3786 auto initialComplex =
3787 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), complexLLVMTy);
3789 auto realComplex = mlir::LLVM::InsertValueOp::create(
3790 rewriter, op->getLoc(), initialComplex, newReal, ArrayRef(int64_t{0}));
3792 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
3793 op, realComplex, newImag, ArrayRef(int64_t{1}));
3795 return mlir::success();
3798mlir::LogicalResult CIRToLLVMComplexCreateOpLowering::matchAndRewrite(
3799 cir::ComplexCreateOp op, OpAdaptor adaptor,
3800 mlir::ConversionPatternRewriter &rewriter)
const {
3801 mlir::Type complexLLVMTy =
3802 getTypeConverter()->convertType(op.getResult().getType());
3803 auto initialComplex =
3804 mlir::LLVM::UndefOp::create(rewriter, op->getLoc(), complexLLVMTy);
3806 auto realComplex = mlir::LLVM::InsertValueOp::create(
3807 rewriter, op->getLoc(), initialComplex, adaptor.getReal(),
3808 ArrayRef(int64_t{0}));
3810 auto complex = mlir::LLVM::InsertValueOp::create(
3811 rewriter, op->getLoc(), realComplex, adaptor.getImag(),
3812 ArrayRef(int64_t{1}));
3814 rewriter.replaceOp(op, complex);
3815 return mlir::success();
3818mlir::LogicalResult CIRToLLVMComplexRealOpLowering::matchAndRewrite(
3819 cir::ComplexRealOp op, OpAdaptor adaptor,
3820 mlir::ConversionPatternRewriter &rewriter)
const {
3821 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
3822 mlir::Value operand = adaptor.getOperand();
3823 if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) {
3824 operand = mlir::LLVM::ExtractValueOp::create(
3825 rewriter, op.getLoc(), resultLLVMTy, operand,
3826 llvm::ArrayRef<std::int64_t>{0});
3828 rewriter.replaceOp(op, operand);
3829 return mlir::success();
3832mlir::LogicalResult CIRToLLVMComplexSubOpLowering::matchAndRewrite(
3833 cir::ComplexSubOp op, OpAdaptor adaptor,
3834 mlir::ConversionPatternRewriter &rewriter)
const {
3835 mlir::Value lhs = adaptor.getLhs();
3836 mlir::Value rhs = adaptor.getRhs();
3837 mlir::Location loc = op.getLoc();
3839 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
3840 mlir::Type complexElemTy =
3841 getTypeConverter()->convertType(
complexType.getElementType());
3842 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
3843 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{0}));
3844 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
3845 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{1}));
3846 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
3847 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{0}));
3848 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
3849 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{1}));
3851 mlir::Value newReal;
3852 mlir::Value newImag;
3853 if (complexElemTy.isInteger()) {
3854 newReal = mlir::LLVM::SubOp::create(rewriter, loc, complexElemTy, lhsReal,
3856 newImag = mlir::LLVM::SubOp::create(rewriter, loc, complexElemTy, lhsImag,
3861 newReal = mlir::LLVM::FSubOp::create(rewriter, loc, complexElemTy, lhsReal,
3863 newImag = mlir::LLVM::FSubOp::create(rewriter, loc, complexElemTy, lhsImag,
3867 mlir::Type complexLLVMTy =
3868 getTypeConverter()->convertType(op.getResult().getType());
3869 auto initialComplex =
3870 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), complexLLVMTy);
3872 auto realComplex = mlir::LLVM::InsertValueOp::create(
3873 rewriter, op->getLoc(), initialComplex, newReal, ArrayRef(int64_t{0}));
3875 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
3876 op, realComplex, newImag, ArrayRef(int64_t{1}));
3878 return mlir::success();
3881mlir::LogicalResult CIRToLLVMComplexImagOpLowering::matchAndRewrite(
3882 cir::ComplexImagOp op, OpAdaptor adaptor,
3883 mlir::ConversionPatternRewriter &rewriter)
const {
3884 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
3885 mlir::Value operand = adaptor.getOperand();
3886 mlir::Location loc = op.getLoc();
3888 if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) {
3889 operand = mlir::LLVM::ExtractValueOp::create(
3890 rewriter, loc, resultLLVMTy, operand, llvm::ArrayRef<std::int64_t>{1});
3892 mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(resultLLVMTy);
3894 mlir::LLVM::ConstantOp::create(rewriter, loc, resultLLVMTy, zeroAttr);
3897 rewriter.replaceOp(op, operand);
3898 return mlir::success();
3902 mlir::MLIRContext *context,
3903 unsigned &storageSize) {
3904 return TypeSwitch<mlir::Type, mlir::IntegerType>(storageType)
3905 .Case<cir::ArrayType>([&](cir::ArrayType atTy) {
3906 storageSize = atTy.getSize() * 8;
3907 return mlir::IntegerType::get(context, storageSize);
3909 .Case<cir::IntType>([&](cir::IntType intTy) {
3910 storageSize = intTy.getWidth();
3911 return mlir::IntegerType::get(context, storageSize);
3913 .Default([](mlir::Type) -> mlir::IntegerType {
3915 "Either ArrayType or IntType expected for bitfields storage");
3919mlir::LogicalResult CIRToLLVMSetBitfieldOpLowering::matchAndRewrite(
3920 cir::SetBitfieldOp op, OpAdaptor adaptor,
3921 mlir::ConversionPatternRewriter &rewriter)
const {
3922 mlir::OpBuilder::InsertionGuard guard(rewriter);
3923 rewriter.setInsertionPoint(op);
3925 cir::BitfieldInfoAttr info = op.getBitfieldInfo();
3926 uint64_t size = info.getSize();
3927 uint64_t offset = info.getOffset();
3928 mlir::Type storageType = info.getStorageType();
3929 mlir::MLIRContext *context = storageType.getContext();
3931 unsigned storageSize = 0;
3933 mlir::IntegerType intType =
3936 mlir::Value srcVal =
createIntCast(rewriter, adaptor.getSrc(), intType);
3937 unsigned srcWidth = storageSize;
3938 mlir::Value resultVal = srcVal;
3940 if (storageSize != size) {
3941 assert(storageSize > size &&
"Invalid bitfield size.");
3943 mlir::Value val = mlir::LLVM::LoadOp::create(
3944 rewriter, op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(),
3945 op.getIsVolatile());
3948 createAnd(rewriter, srcVal, llvm::APInt::getLowBitsSet(srcWidth, size));
3950 srcVal =
createShL(rewriter, srcVal, offset);
3954 ~llvm::APInt::getBitsSet(srcWidth, offset, offset + size));
3957 srcVal = mlir::LLVM::OrOp::create(rewriter, op.getLoc(), val, srcVal);
3960 mlir::LLVM::StoreOp::create(rewriter, op.getLoc(), srcVal, adaptor.getAddr(),
3961 op.getAlignment(), op.getIsVolatile());
3963 mlir::Type resultTy = getTypeConverter()->convertType(op.getType());
3965 if (info.getIsSigned()) {
3966 assert(size <= storageSize);
3967 unsigned highBits = storageSize - size;
3970 resultVal =
createShL(rewriter, resultVal, highBits);
3971 resultVal =
createAShR(rewriter, resultVal, highBits);
3976 mlir::cast<mlir::IntegerType>(resultTy),
3977 info.getIsSigned());
3979 rewriter.replaceOp(op, resultVal);
3980 return mlir::success();
3983mlir::LogicalResult CIRToLLVMComplexImagPtrOpLowering::matchAndRewrite(
3984 cir::ComplexImagPtrOp op, OpAdaptor adaptor,
3985 mlir::ConversionPatternRewriter &rewriter)
const {
3986 cir::PointerType operandTy = op.getOperand().getType();
3987 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
3988 mlir::Type elementLLVMTy =
3989 getTypeConverter()->convertType(operandTy.getPointee());
3991 mlir::LLVM::GEPArg gepIndices[2] = {{0}, {1}};
3992 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
3993 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
3994 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
3995 op, resultLLVMTy, elementLLVMTy, adaptor.getOperand(), gepIndices,
3997 return mlir::success();
4000mlir::LogicalResult CIRToLLVMComplexRealPtrOpLowering::matchAndRewrite(
4001 cir::ComplexRealPtrOp op, OpAdaptor adaptor,
4002 mlir::ConversionPatternRewriter &rewriter)
const {
4003 cir::PointerType operandTy = op.getOperand().getType();
4004 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
4005 mlir::Type elementLLVMTy =
4006 getTypeConverter()->convertType(operandTy.getPointee());
4008 mlir::LLVM::GEPArg gepIndices[2] = {0, 0};
4009 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
4010 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
4011 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
4012 op, resultLLVMTy, elementLLVMTy, adaptor.getOperand(), gepIndices,
4014 return mlir::success();
4017mlir::LogicalResult CIRToLLVMGetBitfieldOpLowering::matchAndRewrite(
4018 cir::GetBitfieldOp op, OpAdaptor adaptor,
4019 mlir::ConversionPatternRewriter &rewriter)
const {
4021 mlir::OpBuilder::InsertionGuard guard(rewriter);
4022 rewriter.setInsertionPoint(op);
4024 cir::BitfieldInfoAttr info = op.getBitfieldInfo();
4026 uint64_t offset = info.getOffset();
4027 mlir::Type storageType = info.getStorageType();
4028 mlir::MLIRContext *context = storageType.getContext();
4029 unsigned storageSize = 0;
4031 mlir::IntegerType intType =
4034 mlir::Value val = mlir::LLVM::LoadOp::create(
4035 rewriter, op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(),
4036 op.getIsVolatile());
4037 val = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), intType, val);
4039 if (info.getIsSigned()) {
4040 assert(
static_cast<unsigned>(offset + size) <= storageSize);
4041 unsigned highBits = storageSize - offset - size;
4042 val =
createShL(rewriter, val, highBits);
4043 val =
createAShR(rewriter, val, offset + highBits);
4047 if (
static_cast<unsigned>(offset) + size < storageSize)
4049 llvm::APInt::getLowBitsSet(storageSize, size));
4052 mlir::Type resTy = getTypeConverter()->convertType(op.getType());
4054 rewriter, val, mlir::cast<mlir::IntegerType>(resTy), info.getIsSigned());
4055 rewriter.replaceOp(op, newOp);
4056 return mlir::success();
4059mlir::LogicalResult CIRToLLVMIsConstantOpLowering::matchAndRewrite(
4060 cir::IsConstantOp op, OpAdaptor adaptor,
4061 mlir::ConversionPatternRewriter &rewriter)
const {
4062 rewriter.replaceOpWithNewOp<mlir::LLVM::IsConstantOp>(op, adaptor.getVal());
4063 return mlir::success();
4066mlir::LogicalResult CIRToLLVMInlineAsmOpLowering::matchAndRewrite(
4067 cir::InlineAsmOp op, OpAdaptor adaptor,
4068 mlir::ConversionPatternRewriter &rewriter)
const {
4070 if (op.getNumResults())
4071 llResTy = getTypeConverter()->convertType(op.getType(0));
4073 cir::AsmFlavor dialect = op.getAsmFlavor();
4074 mlir::LLVM::AsmDialect llDialect = dialect == cir::AsmFlavor::x86_att
4075 ? mlir::LLVM::AsmDialect::AD_ATT
4076 : mlir::LLVM::AsmDialect::AD_Intel;
4078 SmallVector<mlir::Attribute> opAttrs;
4079 StringRef llvmAttrName = mlir::LLVM::InlineAsmOp::getElementTypeAttrName();
4085 if (!op.getNumResults())
4086 opAttrs.push_back(mlir::Attribute());
4088 SmallVector<mlir::Value> llvmOperands;
4089 SmallVector<mlir::Value> cirOperands;
4090 for (
auto const &[llvmOp, cirOp] :
4091 zip(adaptor.getAsmOperands(), op.getAsmOperands())) {
4092 append_range(llvmOperands, llvmOp);
4093 append_range(cirOperands, cirOp);
4098 for (
auto const &[cirOpAttr, cirOp] :
4099 zip(op.getOperandAttrs(), cirOperands)) {
4101 opAttrs.push_back(mlir::Attribute());
4105 llvm::SmallVector<mlir::NamedAttribute, 1> attrs;
4106 cir::PointerType typ = mlir::cast<cir::PointerType>(cirOp.getType());
4108 *getTypeConverter(), dataLayout, typ.getPointee()));
4110 attrs.push_back(rewriter.getNamedAttr(llvmAttrName, typAttr));
4111 mlir::DictionaryAttr newDict = rewriter.getDictionaryAttr(attrs);
4112 opAttrs.push_back(newDict);
4115 rewriter.replaceOpWithNewOp<mlir::LLVM::InlineAsmOp>(
4116 op, llResTy, llvmOperands, op.getAsmStringAttr(), op.getConstraintsAttr(),
4117 op.getSideEffectsAttr(),
4120 mlir::LLVM::TailCallKindAttr::get(
4121 getContext(), mlir::LLVM::tailcallkind::TailCallKind::None),
4122 mlir::LLVM::AsmDialectAttr::get(getContext(), llDialect),
4123 rewriter.getArrayAttr(opAttrs));
4125 return mlir::success();
4128mlir::LogicalResult CIRToLLVMVAStartOpLowering::matchAndRewrite(
4129 cir::VAStartOp op, OpAdaptor adaptor,
4130 mlir::ConversionPatternRewriter &rewriter)
const {
4131 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4132 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4133 adaptor.getArgList());
4134 rewriter.replaceOpWithNewOp<mlir::LLVM::VaStartOp>(op, vaList);
4135 return mlir::success();
4138mlir::LogicalResult CIRToLLVMVAEndOpLowering::matchAndRewrite(
4139 cir::VAEndOp op, OpAdaptor adaptor,
4140 mlir::ConversionPatternRewriter &rewriter)
const {
4141 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4142 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4143 adaptor.getArgList());
4144 rewriter.replaceOpWithNewOp<mlir::LLVM::VaEndOp>(op, vaList);
4145 return mlir::success();
4148mlir::LogicalResult CIRToLLVMVACopyOpLowering::matchAndRewrite(
4149 cir::VACopyOp op, OpAdaptor adaptor,
4150 mlir::ConversionPatternRewriter &rewriter)
const {
4151 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4152 auto dstList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4153 adaptor.getDstList());
4154 auto srcList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4155 adaptor.getSrcList());
4156 rewriter.replaceOpWithNewOp<mlir::LLVM::VaCopyOp>(op, dstList, srcList);
4157 return mlir::success();
4160mlir::LogicalResult CIRToLLVMVAArgOpLowering::matchAndRewrite(
4161 cir::VAArgOp op, OpAdaptor adaptor,
4162 mlir::ConversionPatternRewriter &rewriter)
const {
4164 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4165 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4166 adaptor.getArgList());
4168 mlir::Type llvmType =
4169 getTypeConverter()->convertType(op->getResultTypes().front());
4171 return mlir::failure();
4173 rewriter.replaceOpWithNewOp<mlir::LLVM::VaArgOp>(op, llvmType, vaList);
4174 return mlir::success();
4177mlir::LogicalResult CIRToLLVMBlockAddressOpLowering::matchAndRewrite(
4178 cir::BlockAddressOp op, OpAdaptor adaptor,
4179 mlir::ConversionPatternRewriter &rewriter)
const {
4180 return mlir::failure();
4183mlir::LogicalResult CIRToLLVMIndirectBrOpLowering::matchAndRewrite(
4184 cir::IndirectBrOp op, OpAdaptor adaptor,
4185 mlir::ConversionPatternRewriter &rewriter)
const {
4186 return mlir::failure();
4189mlir::LogicalResult CIRToLLVMAwaitOpLowering::matchAndRewrite(
4190 cir::AwaitOp op, OpAdaptor adaptor,
4191 mlir::ConversionPatternRewriter &rewriter)
const {
4192 return mlir::failure();
4196 return std::make_unique<ConvertCIRToLLVMPass>();
4204std::unique_ptr<llvm::Module>
4206 llvm::TimeTraceScope scope(
"lower from CIR to LLVM directly");
4208 mlir::MLIRContext *mlirCtx = mlirModule.getContext();
4210 mlir::PassManager pm(mlirCtx);
4213 (void)mlir::applyPassManagerCLOptions(pm);
4215 if (mlir::failed(pm.run(mlirModule))) {
4218 "The pass manager failed to lower CIR to LLVMIR dialect!");
4221 mlir::registerBuiltinDialectTranslation(*mlirCtx);
4222 mlir::registerLLVMDialectTranslation(*mlirCtx);
4225 llvm::TimeTraceScope translateScope(
"translateModuleToLLVMIR");
4227 StringRef moduleName = mlirModule.getName().value_or(
"CIRToLLVMModule");
4228 std::unique_ptr<llvm::Module> llvmModule =
4229 mlir::translateModuleToLLVMIR(mlirModule, llvmCtx, moduleName);
4233 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.
virtual mlir::Type lowerDataMemberType(cir::DataMemberType type, const mlir::TypeConverter &typeConverter) const =0
Lower the given data member pointer type to its ABI type.
CIRCXXABI & getCXXABI() const
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::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)