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 CIRToLLVMCosOpLowering::matchAndRewrite(
190 cir::CosOp op, OpAdaptor adaptor,
191 mlir::ConversionPatternRewriter &rewriter)
const {
192 mlir::Type resTy = typeConverter->convertType(op.getType());
193 rewriter.replaceOpWithNewOp<mlir::LLVM::CosOp>(op, resTy, adaptor.getSrc());
194 return mlir::success();
197mlir::LogicalResult CIRToLLVMExpOpLowering::matchAndRewrite(
198 cir::ExpOp op, OpAdaptor adaptor,
199 mlir::ConversionPatternRewriter &rewriter)
const {
200 mlir::Type resTy = typeConverter->convertType(op.getType());
201 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpOp>(op, resTy, adaptor.getSrc());
202 return mlir::success();
205mlir::LogicalResult CIRToLLVMExp2OpLowering::matchAndRewrite(
206 cir::Exp2Op op, OpAdaptor adaptor,
207 mlir::ConversionPatternRewriter &rewriter)
const {
208 mlir::Type resTy = typeConverter->convertType(op.getType());
209 rewriter.replaceOpWithNewOp<mlir::LLVM::Exp2Op>(op, resTy, adaptor.getSrc());
210 return mlir::success();
214 mlir::Value llvmSrc, mlir::Type llvmDstIntTy,
216 uint64_t cirDstIntWidth) {
217 if (cirSrcWidth == cirDstIntWidth)
220 auto loc = llvmSrc.getLoc();
221 if (cirSrcWidth < cirDstIntWidth) {
223 return mlir::LLVM::ZExtOp::create(rewriter, loc, llvmDstIntTy, llvmSrc);
224 return mlir::LLVM::SExtOp::create(rewriter, loc, llvmDstIntTy, llvmSrc);
228 return mlir::LLVM::TruncOp::create(rewriter, loc, llvmDstIntTy, llvmSrc);
234 mlir::ConversionPatternRewriter &rewriter,
235 const mlir::TypeConverter *converter)
236 : parentOp(parentOp), rewriter(rewriter), converter(converter) {}
238 mlir::Value
visit(mlir::Attribute attr) {
239 return llvm::TypeSwitch<mlir::Attribute, mlir::Value>(attr)
240 .Case<cir::IntAttr, cir::FPAttr, cir::ConstComplexAttr,
241 cir::ConstArrayAttr, cir::ConstRecordAttr, cir::ConstVectorAttr,
242 cir::ConstPtrAttr, cir::GlobalViewAttr, cir::TypeInfoAttr,
243 cir::UndefAttr, cir::VTableAttr, cir::ZeroAttr>(
245 .Default([&](
auto attrT) {
return mlir::Value(); });
250 mlir::Value
visitCirAttr(cir::ConstComplexAttr complexAttr);
262 mlir::Operation *parentOp;
263 mlir::ConversionPatternRewriter &rewriter;
264 const mlir::TypeConverter *converter;
269 const mlir::Attribute attr,
270 mlir::ConversionPatternRewriter &rewriter,
271 const mlir::TypeConverter *converter) {
273 mlir::Value value = valueConverter.
visit(attr);
275 llvm_unreachable(
"unhandled attribute type");
280 cir::SideEffect sideEffect,
281 mlir::LLVM::MemoryEffectsAttr &memoryEffect,
282 bool &noUnwind,
bool &willReturn) {
283 using mlir::LLVM::ModRefInfo;
285 switch (sideEffect) {
286 case cir::SideEffect::All:
288 noUnwind = isNothrow;
292 case cir::SideEffect::Pure:
293 memoryEffect = mlir::LLVM::MemoryEffectsAttr::get(
294 callOp->getContext(), ModRefInfo::Ref,
304 case cir::SideEffect::Const:
305 memoryEffect = mlir::LLVM::MemoryEffectsAttr::get(
306 callOp->getContext(), ModRefInfo::NoModRef,
307 ModRefInfo::NoModRef,
308 ModRefInfo::NoModRef,
309 ModRefInfo::NoModRef,
310 ModRefInfo::NoModRef,
311 ModRefInfo::NoModRef);
318static mlir::LLVM::CallIntrinsicOp
320 mlir::Location loc,
const llvm::Twine &intrinsicName,
321 mlir::Type resultTy, mlir::ValueRange operands) {
322 auto intrinsicNameAttr =
323 mlir::StringAttr::get(rewriter.getContext(), intrinsicName);
324 return mlir::LLVM::CallIntrinsicOp::create(rewriter, loc, resultTy,
325 intrinsicNameAttr, operands);
329 mlir::ConversionPatternRewriter &rewriter, mlir::Operation *op,
330 const llvm::Twine &intrinsicName, mlir::Type resultTy,
331 mlir::ValueRange operands) {
333 rewriter, op->getLoc(), intrinsicName, resultTy, operands);
334 rewriter.replaceOp(op, callIntrinOp.getOperation());
338mlir::LogicalResult CIRToLLVMLLVMIntrinsicCallOpLowering::matchAndRewrite(
339 cir::LLVMIntrinsicCallOp op, OpAdaptor adaptor,
340 mlir::ConversionPatternRewriter &rewriter)
const {
341 mlir::Type llvmResTy =
342 getTypeConverter()->convertType(op->getResultTypes()[0]);
344 return op.emitError(
"expected LLVM result type");
345 StringRef name = op.getIntrinsicName();
358 adaptor.getOperands());
359 return mlir::success();
364 mlir::Location loc = parentOp->getLoc();
365 return mlir::LLVM::ConstantOp::create(
366 rewriter, loc, converter->convertType(intAttr.getType()),
372 mlir::Location loc = parentOp->getLoc();
373 return mlir::LLVM::ConstantOp::create(
374 rewriter, loc, converter->convertType(fltAttr.getType()),
380 auto complexType = mlir::cast<cir::ComplexType>(complexAttr.getType());
381 mlir::Type complexElemTy = complexType.getElementType();
382 mlir::Type complexElemLLVMTy = converter->convertType(complexElemTy);
384 mlir::Attribute components[2];
385 if (
const auto intType = mlir::dyn_cast<cir::IntType>(complexElemTy)) {
386 components[0] = rewriter.getIntegerAttr(
388 mlir::cast<cir::IntAttr>(complexAttr.getReal()).getValue());
389 components[1] = rewriter.getIntegerAttr(
391 mlir::cast<cir::IntAttr>(complexAttr.getImag()).getValue());
393 components[0] = rewriter.getFloatAttr(
395 mlir::cast<cir::FPAttr>(complexAttr.getReal()).getValue());
396 components[1] = rewriter.getFloatAttr(
398 mlir::cast<cir::FPAttr>(complexAttr.getImag()).getValue());
401 mlir::Location loc = parentOp->getLoc();
402 return mlir::LLVM::ConstantOp::create(
403 rewriter, loc, converter->convertType(complexAttr.getType()),
404 rewriter.getArrayAttr(components));
409 mlir::Location loc = parentOp->getLoc();
410 if (ptrAttr.isNullValue()) {
411 return mlir::LLVM::ZeroOp::create(
412 rewriter, loc, converter->convertType(ptrAttr.getType()));
414 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
415 mlir::Value ptrVal = mlir::LLVM::ConstantOp::create(
417 rewriter.getIntegerType(layout.getTypeSizeInBits(ptrAttr.getType())),
418 ptrAttr.getValue().getInt());
419 return mlir::LLVM::IntToPtrOp::create(
420 rewriter, loc, converter->convertType(ptrAttr.getType()), ptrVal);
425 mlir::Type llvmTy = converter->convertType(attr.getType());
426 mlir::Location loc = parentOp->getLoc();
429 if (attr.hasTrailingZeros()) {
430 mlir::Type arrayTy = attr.getType();
431 result = mlir::LLVM::ZeroOp::create(rewriter, loc,
432 converter->convertType(arrayTy));
434 result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
438 if (
auto arrayAttr = mlir::dyn_cast<mlir::ArrayAttr>(attr.getElts())) {
439 for (
auto [idx, elt] : llvm::enumerate(arrayAttr)) {
440 mlir::DataLayout dataLayout(parentOp->getParentOfType<mlir::ModuleOp>());
441 mlir::Value init =
visit(elt);
443 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
445 }
else if (
auto strAttr = mlir::dyn_cast<mlir::StringAttr>(attr.getElts())) {
448 auto arrayTy = mlir::dyn_cast<cir::ArrayType>(strAttr.getType());
449 assert(arrayTy &&
"String attribute must have an array type");
450 mlir::Type eltTy = arrayTy.getElementType();
451 for (
auto [idx, elt] : llvm::enumerate(strAttr)) {
452 auto init = mlir::LLVM::ConstantOp::create(
453 rewriter, loc, converter->convertType(eltTy), elt);
455 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
458 llvm_unreachable(
"unexpected ConstArrayAttr elements");
466 const mlir::Type llvmTy = converter->convertType(constRecord.getType());
467 const mlir::Location loc = parentOp->getLoc();
468 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
471 for (
auto [idx, elt] : llvm::enumerate(constRecord.getMembers())) {
472 mlir::Value init =
visit(elt);
474 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
482 const mlir::Type llvmTy = converter->convertType(attr.getType());
483 const mlir::Location loc = parentOp->getLoc();
486 for (
const mlir::Attribute elementAttr : attr.getElts()) {
487 mlir::Attribute mlirAttr;
488 if (
auto intAttr = mlir::dyn_cast<cir::IntAttr>(elementAttr)) {
489 mlirAttr = rewriter.getIntegerAttr(
490 converter->convertType(intAttr.getType()), intAttr.getValue());
491 }
else if (
auto floatAttr = mlir::dyn_cast<cir::FPAttr>(elementAttr)) {
492 mlirAttr = rewriter.getFloatAttr(
493 converter->convertType(floatAttr.getType()), floatAttr.getValue());
496 "vector constant with an element that is neither an int nor a float");
498 mlirValues.push_back(mlirAttr);
501 return mlir::LLVM::ConstantOp::create(
502 rewriter, loc, llvmTy,
503 mlir::DenseElementsAttr::get(mlir::cast<mlir::ShapedType>(llvmTy),
509 auto moduleOp = parentOp->getParentOfType<mlir::ModuleOp>();
510 mlir::DataLayout dataLayout(moduleOp);
511 mlir::Type sourceType;
513 llvm::StringRef symName;
514 mlir::Operation *sourceSymbol =
515 mlir::SymbolTable::lookupSymbolIn(moduleOp, globalAttr.getSymbol());
516 if (
auto llvmSymbol = dyn_cast<mlir::LLVM::GlobalOp>(sourceSymbol)) {
517 sourceType = llvmSymbol.getType();
518 symName = llvmSymbol.getSymName();
519 }
else if (
auto cirSymbol = dyn_cast<cir::GlobalOp>(sourceSymbol)) {
522 symName = cirSymbol.getSymName();
523 }
else if (
auto llvmFun = dyn_cast<mlir::LLVM::LLVMFuncOp>(sourceSymbol)) {
524 sourceType = llvmFun.getFunctionType();
525 symName = llvmFun.getSymName();
526 }
else if (
auto fun = dyn_cast<cir::FuncOp>(sourceSymbol)) {
527 sourceType = converter->convertType(fun.getFunctionType());
528 symName = fun.getSymName();
529 }
else if (
auto alias = dyn_cast<mlir::LLVM::AliasOp>(sourceSymbol)) {
530 sourceType = alias.getType();
531 symName = alias.getSymName();
533 llvm_unreachable(
"Unexpected GlobalOp type");
536 mlir::Location loc = parentOp->getLoc();
537 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
538 rewriter, loc, mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
541 if (globalAttr.getIndices()) {
544 if (mlir::isa<mlir::LLVM::LLVMArrayType, mlir::LLVM::LLVMStructType>(
546 indices.push_back(0);
548 for (mlir::Attribute idx : globalAttr.getIndices()) {
549 auto intAttr = mlir::cast<mlir::IntegerAttr>(idx);
550 indices.push_back(intAttr.getValue().getSExtValue());
552 mlir::Type resTy = addrOp.getType();
553 mlir::Type eltTy = converter->convertType(sourceType);
555 mlir::LLVM::GEPOp::create(rewriter, loc, resTy, eltTy, addrOp, indices,
556 mlir::LLVM::GEPNoWrapFlags::none);
565 if (
auto ptrTy = mlir::dyn_cast<cir::PointerType>(globalAttr.getType())) {
566 mlir::Type llvmEltTy =
569 if (llvmEltTy == sourceType)
572 mlir::Type llvmDstTy = converter->convertType(globalAttr.getType());
573 return mlir::LLVM::BitcastOp::create(rewriter, parentOp->getLoc(),
577 llvm_unreachable(
"Expecting pointer or integer type for GlobalViewAttr");
582 mlir::Type llvmTy = converter->convertType(typeInfoAttr.getType());
583 mlir::Location loc = parentOp->getLoc();
584 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
586 for (
auto [idx, elt] : llvm::enumerate(typeInfoAttr.getData())) {
587 mlir::Value init =
visit(elt);
589 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
597 mlir::Location loc = parentOp->getLoc();
598 return mlir::LLVM::UndefOp::create(
599 rewriter, loc, converter->convertType(undefAttr.getType()));
604 mlir::Type llvmTy = converter->convertType(vtableArr.getType());
605 mlir::Location loc = parentOp->getLoc();
606 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
608 for (
auto [idx, elt] : llvm::enumerate(vtableArr.getData())) {
609 mlir::Value init =
visit(elt);
611 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
619 mlir::Location loc = parentOp->getLoc();
620 return mlir::LLVM::ZeroOp::create(rewriter, loc,
621 converter->convertType(attr.getType()));
629 mlir::ConversionPatternRewriter &rewriter)
630 : llvmType(type), rewriter(rewriter) {}
632 mlir::Attribute
visit(mlir::Attribute attr) {
633 return llvm::TypeSwitch<mlir::Attribute, mlir::Attribute>(attr)
634 .Case<cir::IntAttr, cir::FPAttr, cir::BoolAttr>(
636 .Default([&](
auto attrT) {
return mlir::Attribute(); });
640 return rewriter.getIntegerAttr(llvmType, attr.getValue());
644 return rewriter.getFloatAttr(llvmType, attr.getValue());
648 return rewriter.getBoolAttr(attr.getValue());
653 mlir::ConversionPatternRewriter &rewriter;
661 :
public mlir::PassWrapper<ConvertCIRToLLVMPass,
662 mlir::OperationPass<mlir::ModuleOp>> {
664 registry.insert<mlir::BuiltinDialect, mlir::DLTIDialect,
665 mlir::LLVM::LLVMDialect, mlir::func::FuncDialect>();
672 return "Convert the prepared CIR dialect module to LLVM dialect";
675 StringRef
getArgument()
const override {
return "cir-flat-to-llvm"; }
678mlir::LogicalResult CIRToLLVMACosOpLowering::matchAndRewrite(
679 cir::ACosOp op, OpAdaptor adaptor,
680 mlir::ConversionPatternRewriter &rewriter)
const {
681 mlir::Type resTy = typeConverter->convertType(op.getType());
682 rewriter.replaceOpWithNewOp<mlir::LLVM::ACosOp>(op, resTy,
683 adaptor.getOperands()[0]);
684 return mlir::success();
687mlir::LogicalResult CIRToLLVMASinOpLowering::matchAndRewrite(
688 cir::ASinOp op, OpAdaptor adaptor,
689 mlir::ConversionPatternRewriter &rewriter)
const {
690 mlir::Type resTy = typeConverter->convertType(op.getType());
691 rewriter.replaceOpWithNewOp<mlir::LLVM::ASinOp>(op, resTy, adaptor.getSrc());
692 return mlir::success();
695mlir::LogicalResult CIRToLLVMIsFPClassOpLowering::matchAndRewrite(
696 cir::IsFPClassOp op, OpAdaptor adaptor,
697 mlir::ConversionPatternRewriter &rewriter)
const {
698 mlir::Value src = adaptor.getSrc();
699 cir::FPClassTest flags = adaptor.getFlags();
700 mlir::IntegerType retTy = rewriter.getI1Type();
702 rewriter.replaceOpWithNewOp<mlir::LLVM::IsFPClass>(
703 op, retTy, src,
static_cast<uint32_t>(flags));
704 return mlir::success();
707mlir::LogicalResult CIRToLLVMAssumeOpLowering::matchAndRewrite(
708 cir::AssumeOp op, OpAdaptor adaptor,
709 mlir::ConversionPatternRewriter &rewriter)
const {
710 auto cond = adaptor.getPredicate();
711 rewriter.replaceOpWithNewOp<mlir::LLVM::AssumeOp>(op, cond);
712 return mlir::success();
715mlir::LogicalResult CIRToLLVMAssumeAlignedOpLowering::matchAndRewrite(
716 cir::AssumeAlignedOp op, OpAdaptor adaptor,
717 mlir::ConversionPatternRewriter &rewriter)
const {
718 SmallVector<mlir::Value, 3> opBundleArgs{adaptor.getPointer()};
720 auto alignment = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
721 adaptor.getAlignmentAttr());
722 opBundleArgs.push_back(alignment);
724 if (mlir::Value offset = adaptor.getOffset())
725 opBundleArgs.push_back(offset);
727 auto cond = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
728 rewriter.getI1Type(), 1);
729 mlir::LLVM::AssumeOp::create(rewriter, op.getLoc(), cond,
"align",
734 rewriter.replaceOp(op, adaptor.getPointer());
735 return mlir::success();
738mlir::LogicalResult CIRToLLVMAssumeSepStorageOpLowering::matchAndRewrite(
739 cir::AssumeSepStorageOp op, OpAdaptor adaptor,
740 mlir::ConversionPatternRewriter &rewriter)
const {
741 auto cond = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
742 rewriter.getI1Type(), 1);
743 rewriter.replaceOpWithNewOp<mlir::LLVM::AssumeOp>(
744 op, cond, mlir::LLVM::AssumeSeparateStorageTag{}, adaptor.getPtr1(),
746 return mlir::success();
749static mlir::LLVM::AtomicOrdering
752 return mlir::LLVM::AtomicOrdering::not_atomic;
754 case cir::MemOrder::Relaxed:
755 return mlir::LLVM::AtomicOrdering::monotonic;
756 case cir::MemOrder::Consume:
757 case cir::MemOrder::Acquire:
758 return mlir::LLVM::AtomicOrdering::acquire;
759 case cir::MemOrder::Release:
760 return mlir::LLVM::AtomicOrdering::release;
761 case cir::MemOrder::AcquireRelease:
762 return mlir::LLVM::AtomicOrdering::acq_rel;
763 case cir::MemOrder::SequentiallyConsistent:
764 return mlir::LLVM::AtomicOrdering::seq_cst;
766 llvm_unreachable(
"unknown memory order");
769mlir::LogicalResult CIRToLLVMAtomicCmpXchgOpLowering::matchAndRewrite(
770 cir::AtomicCmpXchgOp op, OpAdaptor adaptor,
771 mlir::ConversionPatternRewriter &rewriter)
const {
772 mlir::Value expected = adaptor.getExpected();
773 mlir::Value desired = adaptor.getDesired();
775 auto cmpxchg = mlir::LLVM::AtomicCmpXchgOp::create(
776 rewriter, op.getLoc(), adaptor.getPtr(), expected, desired,
780 cmpxchg.setAlignment(adaptor.getAlignment());
781 cmpxchg.setWeak(adaptor.getWeak());
782 cmpxchg.setVolatile_(adaptor.getIsVolatile());
785 auto old = mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(),
786 cmpxchg.getResult(), 0);
787 auto cmp = mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(),
788 cmpxchg.getResult(), 1);
790 rewriter.replaceOp(op, {old, cmp});
791 return mlir::success();
794mlir::LogicalResult CIRToLLVMAtomicXchgOpLowering::matchAndRewrite(
795 cir::AtomicXchgOp op, OpAdaptor adaptor,
796 mlir::ConversionPatternRewriter &rewriter)
const {
798 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(adaptor.getMemOrder());
799 rewriter.replaceOpWithNewOp<mlir::LLVM::AtomicRMWOp>(
800 op, mlir::LLVM::AtomicBinOp::xchg, adaptor.getPtr(), adaptor.getVal(),
802 return mlir::success();
805mlir::LogicalResult CIRToLLVMAtomicTestAndSetOpLowering::matchAndRewrite(
806 cir::AtomicTestAndSetOp op, OpAdaptor adaptor,
807 mlir::ConversionPatternRewriter &rewriter)
const {
810 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
812 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
813 rewriter.getI8Type(), 1);
814 auto rmw = mlir::LLVM::AtomicRMWOp::create(
815 rewriter, op.getLoc(), mlir::LLVM::AtomicBinOp::xchg, adaptor.getPtr(),
816 one, llvmOrder, llvm::StringRef(),
817 adaptor.getAlignment().value_or(0), op.getIsVolatile());
819 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
820 rewriter.getI8Type(), 0);
821 auto cmp = mlir::LLVM::ICmpOp::create(
822 rewriter, op.getLoc(), mlir::LLVM::ICmpPredicate::ne, rmw, zero);
824 rewriter.replaceOp(op, cmp);
825 return mlir::success();
828mlir::LogicalResult CIRToLLVMAtomicClearOpLowering::matchAndRewrite(
829 cir::AtomicClearOp op, OpAdaptor adaptor,
830 mlir::ConversionPatternRewriter &rewriter)
const {
833 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
834 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
835 rewriter.getI8Type(), 0);
836 auto store = mlir::LLVM::StoreOp::create(
837 rewriter, op.getLoc(), zero, adaptor.getPtr(),
838 adaptor.getAlignment().value_or(0), op.getIsVolatile(),
839 false,
false, llvmOrder);
841 rewriter.replaceOp(op, store);
842 return mlir::success();
845static mlir::LLVM::AtomicBinOp
848 case cir::AtomicFetchKind::Add:
849 return isInt ? mlir::LLVM::AtomicBinOp::add : mlir::LLVM::AtomicBinOp::fadd;
850 case cir::AtomicFetchKind::Sub:
851 return isInt ? mlir::LLVM::AtomicBinOp::sub : mlir::LLVM::AtomicBinOp::fsub;
852 case cir::AtomicFetchKind::And:
853 return mlir::LLVM::AtomicBinOp::_and;
854 case cir::AtomicFetchKind::Xor:
855 return mlir::LLVM::AtomicBinOp::_xor;
856 case cir::AtomicFetchKind::Or:
857 return mlir::LLVM::AtomicBinOp::_or;
858 case cir::AtomicFetchKind::Nand:
859 return mlir::LLVM::AtomicBinOp::nand;
860 case cir::AtomicFetchKind::Max: {
862 return mlir::LLVM::AtomicBinOp::fmax;
863 return isSignedInt ? mlir::LLVM::AtomicBinOp::max
864 : mlir::LLVM::AtomicBinOp::umax;
866 case cir::AtomicFetchKind::Min: {
868 return mlir::LLVM::AtomicBinOp::fmin;
869 return isSignedInt ? mlir::LLVM::AtomicBinOp::min
870 : mlir::LLVM::AtomicBinOp::umin;
873 llvm_unreachable(
"Unknown atomic fetch opcode");
876static llvm::StringLiteral
getLLVMBinop(cir::AtomicFetchKind k,
bool isInt) {
878 case cir::AtomicFetchKind::Add:
879 return isInt ? mlir::LLVM::AddOp::getOperationName()
880 : mlir::LLVM::FAddOp::getOperationName();
881 case cir::AtomicFetchKind::Sub:
882 return isInt ? mlir::LLVM::SubOp::getOperationName()
883 : mlir::LLVM::FSubOp::getOperationName();
884 case cir::AtomicFetchKind::And:
885 return mlir::LLVM::AndOp::getOperationName();
886 case cir::AtomicFetchKind::Xor:
887 return mlir::LLVM::XOrOp::getOperationName();
888 case cir::AtomicFetchKind::Or:
889 return mlir::LLVM::OrOp::getOperationName();
890 case cir::AtomicFetchKind::Nand:
892 return mlir::LLVM::AndOp::getOperationName();
893 case cir::AtomicFetchKind::Max:
894 case cir::AtomicFetchKind::Min:
895 llvm_unreachable(
"handled in buildMinMaxPostOp");
897 llvm_unreachable(
"Unknown atomic fetch opcode");
900mlir::Value CIRToLLVMAtomicFetchOpLowering::buildPostOp(
901 cir::AtomicFetchOp op, OpAdaptor adaptor,
902 mlir::ConversionPatternRewriter &rewriter, mlir::Value rmwVal,
908 rewriter.getStringAttr(
getLLVMBinop(op.getBinop(), isInt)),
909 atomicOperands, atomicResTys, {})
913mlir::Value CIRToLLVMAtomicFetchOpLowering::buildMinMaxPostOp(
914 cir::AtomicFetchOp op, OpAdaptor adaptor,
915 mlir::ConversionPatternRewriter &rewriter, mlir::Value rmwVal,
bool isInt,
916 bool isSigned)
const {
917 mlir::Location loc = op.getLoc();
920 if (op.getBinop() == cir::AtomicFetchKind::Max)
921 return mlir::LLVM::MaxNumOp::create(rewriter, loc, rmwVal,
923 return mlir::LLVM::MinNumOp::create(rewriter, loc, rmwVal,
927 mlir::LLVM::ICmpPredicate pred;
928 if (op.getBinop() == cir::AtomicFetchKind::Max) {
929 pred = isSigned ? mlir::LLVM::ICmpPredicate::sgt
930 : mlir::LLVM::ICmpPredicate::ugt;
932 pred = isSigned ? mlir::LLVM::ICmpPredicate::slt
933 : mlir::LLVM::ICmpPredicate::ult;
935 mlir::Value cmp = mlir::LLVM::ICmpOp::create(
937 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(), pred), rmwVal,
939 return mlir::LLVM::SelectOp::create(rewriter, loc, cmp, rmwVal,
943mlir::LogicalResult CIRToLLVMAtomicFetchOpLowering::matchAndRewrite(
944 cir::AtomicFetchOp op, OpAdaptor adaptor,
945 mlir::ConversionPatternRewriter &rewriter)
const {
947 bool isSignedInt =
false;
948 if (
auto intTy = mlir::dyn_cast<cir::IntType>(op.getVal().getType())) {
950 isSignedInt = intTy.isSigned();
951 }
else if (mlir::isa<cir::SingleType, cir::DoubleType>(
952 op.getVal().getType())) {
955 return op.emitError() <<
"Unsupported type: " << op.getVal().getType();
958 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
959 mlir::LLVM::AtomicBinOp llvmBinOp =
961 auto rmwVal = mlir::LLVM::AtomicRMWOp::create(rewriter, op.getLoc(),
962 llvmBinOp, adaptor.getPtr(),
963 adaptor.getVal(), llvmOrder);
965 mlir::Value result = rmwVal.getResult();
966 if (!op.getFetchFirst()) {
967 if (op.getBinop() == cir::AtomicFetchKind::Max ||
968 op.getBinop() == cir::AtomicFetchKind::Min)
969 result = buildMinMaxPostOp(op, adaptor, rewriter, rmwVal.getRes(), isInt,
972 result = buildPostOp(op, adaptor, rewriter, rmwVal.getRes(), isInt);
975 if (op.getBinop() == cir::AtomicFetchKind::Nand) {
976 auto negOne = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
977 result.getType(), -1);
978 result = mlir::LLVM::XOrOp::create(rewriter, op.getLoc(), result, negOne);
982 rewriter.replaceOp(op, result);
983 return mlir::success();
986mlir::LogicalResult CIRToLLVMBitClrsbOpLowering::matchAndRewrite(
987 cir::BitClrsbOp op, OpAdaptor adaptor,
988 mlir::ConversionPatternRewriter &rewriter)
const {
989 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
990 adaptor.getInput().getType(), 0);
991 auto isNeg = mlir::LLVM::ICmpOp::create(
992 rewriter, op.getLoc(),
993 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(),
994 mlir::LLVM::ICmpPredicate::slt),
995 adaptor.getInput(), zero);
997 auto negOne = mlir::LLVM::ConstantOp::create(
998 rewriter, op.getLoc(), adaptor.getInput().getType(), -1);
999 auto flipped = mlir::LLVM::XOrOp::create(rewriter, op.getLoc(),
1000 adaptor.getInput(), negOne);
1002 auto select = mlir::LLVM::SelectOp::create(rewriter, op.getLoc(), isNeg,
1003 flipped, adaptor.getInput());
1005 auto resTy = getTypeConverter()->convertType(op.getType());
1006 auto clz = mlir::LLVM::CountLeadingZerosOp::create(
1007 rewriter, op.getLoc(), resTy,
select,
false);
1009 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1010 auto res = mlir::LLVM::SubOp::create(rewriter, op.getLoc(),
clz, one);
1011 rewriter.replaceOp(op, res);
1013 return mlir::LogicalResult::success();
1016mlir::LogicalResult CIRToLLVMBitClzOpLowering::matchAndRewrite(
1017 cir::BitClzOp op, OpAdaptor adaptor,
1018 mlir::ConversionPatternRewriter &rewriter)
const {
1019 auto resTy = getTypeConverter()->convertType(op.getType());
1020 auto llvmOp = mlir::LLVM::CountLeadingZerosOp::create(
1021 rewriter, op.getLoc(), resTy, adaptor.getInput(), op.getPoisonZero());
1022 rewriter.replaceOp(op, llvmOp);
1023 return mlir::LogicalResult::success();
1026mlir::LogicalResult CIRToLLVMBitCtzOpLowering::matchAndRewrite(
1027 cir::BitCtzOp op, OpAdaptor adaptor,
1028 mlir::ConversionPatternRewriter &rewriter)
const {
1029 auto resTy = getTypeConverter()->convertType(op.getType());
1030 auto llvmOp = mlir::LLVM::CountTrailingZerosOp::create(
1031 rewriter, op.getLoc(), resTy, adaptor.getInput(), op.getPoisonZero());
1032 rewriter.replaceOp(op, llvmOp);
1033 return mlir::LogicalResult::success();
1036mlir::LogicalResult CIRToLLVMBitFfsOpLowering::matchAndRewrite(
1037 cir::BitFfsOp op, OpAdaptor adaptor,
1038 mlir::ConversionPatternRewriter &rewriter)
const {
1039 auto resTy = getTypeConverter()->convertType(op.getType());
1040 auto ctz = mlir::LLVM::CountTrailingZerosOp::create(rewriter, op.getLoc(),
1041 resTy, adaptor.getInput(),
1044 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1045 auto ctzAddOne = mlir::LLVM::AddOp::create(rewriter, op.getLoc(),
ctz, one);
1047 auto zeroInputTy = mlir::LLVM::ConstantOp::create(
1048 rewriter, op.getLoc(), adaptor.getInput().getType(), 0);
1049 auto isZero = mlir::LLVM::ICmpOp::create(
1050 rewriter, op.getLoc(),
1051 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(),
1052 mlir::LLVM::ICmpPredicate::eq),
1053 adaptor.getInput(), zeroInputTy);
1055 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 0);
1056 auto res = mlir::LLVM::SelectOp::create(rewriter, op.getLoc(), isZero, zero,
1058 rewriter.replaceOp(op, res);
1060 return mlir::LogicalResult::success();
1063mlir::LogicalResult CIRToLLVMBitParityOpLowering::matchAndRewrite(
1064 cir::BitParityOp op, OpAdaptor adaptor,
1065 mlir::ConversionPatternRewriter &rewriter)
const {
1066 auto resTy = getTypeConverter()->convertType(op.getType());
1067 auto popcnt = mlir::LLVM::CtPopOp::create(rewriter, op.getLoc(), resTy,
1068 adaptor.getInput());
1070 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1072 mlir::LLVM::AndOp::create(rewriter, op.getLoc(), popcnt, one);
1073 rewriter.replaceOp(op, popcntMod2);
1075 return mlir::LogicalResult::success();
1078mlir::LogicalResult CIRToLLVMBitPopcountOpLowering::matchAndRewrite(
1079 cir::BitPopcountOp op, OpAdaptor adaptor,
1080 mlir::ConversionPatternRewriter &rewriter)
const {
1081 auto resTy = getTypeConverter()->convertType(op.getType());
1082 auto llvmOp = mlir::LLVM::CtPopOp::create(rewriter, op.getLoc(), resTy,
1083 adaptor.getInput());
1084 rewriter.replaceOp(op, llvmOp);
1085 return mlir::LogicalResult::success();
1088mlir::LogicalResult CIRToLLVMBitReverseOpLowering::matchAndRewrite(
1089 cir::BitReverseOp op, OpAdaptor adaptor,
1090 mlir::ConversionPatternRewriter &rewriter)
const {
1091 rewriter.replaceOpWithNewOp<mlir::LLVM::BitReverseOp>(op, adaptor.getInput());
1092 return mlir::success();
1095mlir::LogicalResult CIRToLLVMBrCondOpLowering::matchAndRewrite(
1096 cir::BrCondOp brOp, OpAdaptor adaptor,
1097 mlir::ConversionPatternRewriter &rewriter)
const {
1102 mlir::Value i1Condition = adaptor.getCond();
1104 rewriter.replaceOpWithNewOp<mlir::LLVM::CondBrOp>(
1105 brOp, i1Condition, brOp.getDestTrue(), adaptor.getDestOperandsTrue(),
1106 brOp.getDestFalse(), adaptor.getDestOperandsFalse());
1108 return mlir::success();
1111mlir::LogicalResult CIRToLLVMByteSwapOpLowering::matchAndRewrite(
1112 cir::ByteSwapOp op, OpAdaptor adaptor,
1113 mlir::ConversionPatternRewriter &rewriter)
const {
1114 rewriter.replaceOpWithNewOp<mlir::LLVM::ByteSwapOp>(op, adaptor.getInput());
1115 return mlir::LogicalResult::success();
1118mlir::Type CIRToLLVMCastOpLowering::convertTy(mlir::Type ty)
const {
1119 return getTypeConverter()->convertType(ty);
1122mlir::LogicalResult CIRToLLVMCastOpLowering::matchAndRewrite(
1123 cir::CastOp castOp, OpAdaptor adaptor,
1124 mlir::ConversionPatternRewriter &rewriter)
const {
1129 switch (castOp.getKind()) {
1130 case cir::CastKind::array_to_ptrdecay: {
1131 const auto ptrTy = mlir::cast<cir::PointerType>(castOp.getType());
1132 mlir::Value sourceValue = adaptor.getSrc();
1133 mlir::Type targetType = convertTy(ptrTy);
1135 ptrTy.getPointee());
1136 llvm::SmallVector<mlir::LLVM::GEPArg> offset{0};
1137 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1138 castOp, targetType, elementTy, sourceValue, offset);
1141 case cir::CastKind::int_to_bool: {
1142 mlir::Value llvmSrcVal = adaptor.getSrc();
1143 mlir::Value zeroInt = mlir::LLVM::ConstantOp::create(
1144 rewriter, castOp.getLoc(), llvmSrcVal.getType(), 0);
1145 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
1146 castOp, mlir::LLVM::ICmpPredicate::ne, llvmSrcVal, zeroInt);
1149 case cir::CastKind::integral: {
1150 mlir::Type srcType = castOp.getSrc().getType();
1151 mlir::Type dstType = castOp.getType();
1152 mlir::Value llvmSrcVal = adaptor.getSrc();
1153 mlir::Type llvmDstType = getTypeConverter()->convertType(dstType);
1154 cir::IntType srcIntType =
1155 mlir::cast<cir::IntType>(elementTypeIfVector(srcType));
1156 cir::IntType dstIntType =
1157 mlir::cast<cir::IntType>(elementTypeIfVector(dstType));
1158 rewriter.replaceOp(castOp,
getLLVMIntCast(rewriter, llvmSrcVal, llvmDstType,
1159 srcIntType.isUnsigned(),
1160 srcIntType.getWidth(),
1161 dstIntType.getWidth()));
1164 case cir::CastKind::floating: {
1165 mlir::Value llvmSrcVal = adaptor.getSrc();
1166 mlir::Type llvmDstTy = getTypeConverter()->convertType(castOp.getType());
1168 mlir::Type srcTy = elementTypeIfVector(castOp.getSrc().getType());
1169 mlir::Type dstTy = elementTypeIfVector(castOp.getType());
1171 if (!mlir::isa<cir::FPTypeInterface>(dstTy) ||
1172 !mlir::isa<cir::FPTypeInterface>(srcTy))
1173 return castOp.emitError() <<
"NYI cast from " << srcTy <<
" to " << dstTy;
1175 auto getFloatWidth = [](mlir::Type ty) ->
unsigned {
1176 return mlir::cast<cir::FPTypeInterface>(ty).getWidth();
1179 if (getFloatWidth(srcTy) > getFloatWidth(dstTy))
1180 rewriter.replaceOpWithNewOp<mlir::LLVM::FPTruncOp>(castOp, llvmDstTy,
1183 rewriter.replaceOpWithNewOp<mlir::LLVM::FPExtOp>(castOp, llvmDstTy,
1185 return mlir::success();
1187 case cir::CastKind::int_to_ptr: {
1188 auto dstTy = mlir::cast<cir::PointerType>(castOp.getType());
1189 mlir::Value llvmSrcVal = adaptor.getSrc();
1190 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1191 rewriter.replaceOpWithNewOp<mlir::LLVM::IntToPtrOp>(castOp, llvmDstTy,
1193 return mlir::success();
1195 case cir::CastKind::ptr_to_int: {
1196 auto dstTy = mlir::cast<cir::IntType>(castOp.getType());
1197 mlir::Value llvmSrcVal = adaptor.getSrc();
1198 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1199 rewriter.replaceOpWithNewOp<mlir::LLVM::PtrToIntOp>(castOp, llvmDstTy,
1201 return mlir::success();
1203 case cir::CastKind::float_to_bool: {
1204 mlir::Value llvmSrcVal = adaptor.getSrc();
1205 auto kind = mlir::LLVM::FCmpPredicate::une;
1208 auto zeroFloat = mlir::LLVM::ConstantOp::create(
1209 rewriter, castOp.getLoc(), llvmSrcVal.getType(),
1210 mlir::FloatAttr::get(llvmSrcVal.getType(), 0.0));
1213 rewriter.replaceOpWithNewOp<mlir::LLVM::FCmpOp>(castOp,
kind, llvmSrcVal,
1216 return mlir::success();
1218 case cir::CastKind::bool_to_int: {
1219 auto dstTy = mlir::cast<cir::IntType>(castOp.getType());
1220 mlir::Value llvmSrcVal = adaptor.getSrc();
1221 auto llvmSrcTy = mlir::cast<mlir::IntegerType>(llvmSrcVal.getType());
1223 mlir::cast<mlir::IntegerType>(getTypeConverter()->convertType(dstTy));
1224 if (llvmSrcTy.getWidth() == llvmDstTy.getWidth())
1225 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(castOp, llvmDstTy,
1228 rewriter.replaceOpWithNewOp<mlir::LLVM::ZExtOp>(castOp, llvmDstTy,
1230 return mlir::success();
1232 case cir::CastKind::bool_to_float: {
1233 mlir::Type dstTy = castOp.getType();
1234 mlir::Value llvmSrcVal = adaptor.getSrc();
1235 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1236 rewriter.replaceOpWithNewOp<mlir::LLVM::UIToFPOp>(castOp, llvmDstTy,
1238 return mlir::success();
1240 case cir::CastKind::int_to_float: {
1241 mlir::Type dstTy = castOp.getType();
1242 mlir::Value llvmSrcVal = adaptor.getSrc();
1243 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1244 if (mlir::cast<cir::IntType>(elementTypeIfVector(castOp.getSrc().getType()))
1246 rewriter.replaceOpWithNewOp<mlir::LLVM::SIToFPOp>(castOp, llvmDstTy,
1249 rewriter.replaceOpWithNewOp<mlir::LLVM::UIToFPOp>(castOp, llvmDstTy,
1251 return mlir::success();
1253 case cir::CastKind::float_to_int: {
1254 mlir::Type dstTy = castOp.getType();
1255 mlir::Value llvmSrcVal = adaptor.getSrc();
1256 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1257 if (mlir::cast<cir::IntType>(elementTypeIfVector(castOp.getType()))
1259 rewriter.replaceOpWithNewOp<mlir::LLVM::FPToSIOp>(castOp, llvmDstTy,
1262 rewriter.replaceOpWithNewOp<mlir::LLVM::FPToUIOp>(castOp, llvmDstTy,
1264 return mlir::success();
1266 case cir::CastKind::bitcast: {
1267 mlir::Type dstTy = castOp.getType();
1268 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1273 mlir::Value llvmSrcVal = adaptor.getSrc();
1274 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(castOp, llvmDstTy,
1276 return mlir::success();
1278 case cir::CastKind::ptr_to_bool: {
1279 mlir::Value llvmSrcVal = adaptor.getSrc();
1280 mlir::Value zeroPtr = mlir::LLVM::ZeroOp::create(rewriter, castOp.getLoc(),
1281 llvmSrcVal.getType());
1282 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
1283 castOp, mlir::LLVM::ICmpPredicate::ne, llvmSrcVal, zeroPtr);
1286 case cir::CastKind::address_space: {
1287 mlir::Type dstTy = castOp.getType();
1288 mlir::Value llvmSrcVal = adaptor.getSrc();
1289 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1290 rewriter.replaceOpWithNewOp<mlir::LLVM::AddrSpaceCastOp>(castOp, llvmDstTy,
1294 case cir::CastKind::member_ptr_to_bool:
1299 return castOp.emitError(
"Unhandled cast kind: ")
1300 << castOp.getKindAttrName();
1304 return mlir::success();
1307mlir::LogicalResult CIRToLLVMPtrStrideOpLowering::matchAndRewrite(
1308 cir::PtrStrideOp ptrStrideOp, OpAdaptor adaptor,
1309 mlir::ConversionPatternRewriter &rewriter)
const {
1311 const mlir::TypeConverter *tc = getTypeConverter();
1312 const mlir::Type resultTy = tc->convertType(ptrStrideOp.getType());
1314 mlir::Type elementTy =
1316 mlir::MLIRContext *ctx = elementTy.getContext();
1320 if (mlir::isa<mlir::LLVM::LLVMVoidType>(elementTy) ||
1321 mlir::isa<mlir::LLVM::LLVMFunctionType>(elementTy))
1322 elementTy = mlir::IntegerType::get(elementTy.getContext(), 8,
1323 mlir::IntegerType::Signless);
1325 mlir::Value index = adaptor.getStride();
1326 const unsigned width =
1327 mlir::cast<mlir::IntegerType>(index.getType()).getWidth();
1328 const std::optional<std::uint64_t> layoutWidth =
1329 dataLayout.getTypeIndexBitwidth(adaptor.getBase().getType());
1331 mlir::Operation *indexOp = index.getDefiningOp();
1332 if (indexOp && layoutWidth && width != *layoutWidth) {
1336 const auto sub = dyn_cast<mlir::LLVM::SubOp>(indexOp);
1337 auto unary = ptrStrideOp.getStride().getDefiningOp<cir::UnaryOp>();
1339 unary && unary.getKind() == cir::UnaryOpKind::Minus && sub;
1341 index = indexOp->getOperand(1);
1344 const auto llvmDstType = mlir::IntegerType::get(ctx, *layoutWidth);
1346 ptrStrideOp.getStride().getType().isUnsigned(),
1347 width, *layoutWidth);
1351 index = mlir::LLVM::SubOp::create(
1352 rewriter, index.getLoc(), index.getType(),
1353 mlir::LLVM::ConstantOp::create(rewriter, index.getLoc(),
1354 index.getType(), 0),
1356 rewriter.eraseOp(sub);
1360 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1361 ptrStrideOp, resultTy, elementTy, adaptor.getBase(), index);
1362 return mlir::success();
1365mlir::LogicalResult CIRToLLVMBaseClassAddrOpLowering::matchAndRewrite(
1366 cir::BaseClassAddrOp baseClassOp, OpAdaptor adaptor,
1367 mlir::ConversionPatternRewriter &rewriter)
const {
1368 const mlir::Type resultType =
1369 getTypeConverter()->convertType(baseClassOp.getType());
1370 mlir::Value derivedAddr = adaptor.getDerivedAddr();
1371 llvm::SmallVector<mlir::LLVM::GEPArg, 1> offset = {
1372 adaptor.getOffset().getZExtValue()};
1373 mlir::Type byteType = mlir::IntegerType::get(resultType.getContext(), 8,
1374 mlir::IntegerType::Signless);
1375 if (adaptor.getOffset().getZExtValue() == 0) {
1376 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(
1377 baseClassOp, resultType, adaptor.getDerivedAddr());
1378 return mlir::success();
1381 if (baseClassOp.getAssumeNotNull()) {
1382 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1383 baseClassOp, resultType, byteType, derivedAddr, offset);
1385 auto loc = baseClassOp.getLoc();
1386 mlir::Value isNull = mlir::LLVM::ICmpOp::create(
1387 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, derivedAddr,
1388 mlir::LLVM::ZeroOp::create(rewriter, loc, derivedAddr.getType()));
1389 mlir::Value adjusted = mlir::LLVM::GEPOp::create(
1390 rewriter, loc, resultType, byteType, derivedAddr, offset);
1391 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(baseClassOp, isNull,
1392 derivedAddr, adjusted);
1394 return mlir::success();
1397mlir::LogicalResult CIRToLLVMDerivedClassAddrOpLowering::matchAndRewrite(
1398 cir::DerivedClassAddrOp derivedClassOp, OpAdaptor adaptor,
1399 mlir::ConversionPatternRewriter &rewriter)
const {
1400 const mlir::Type resultType =
1401 getTypeConverter()->convertType(derivedClassOp.getType());
1402 mlir::Value baseAddr = adaptor.getBaseAddr();
1405 int64_t offsetVal = -(adaptor.getOffset().getZExtValue());
1406 if (offsetVal == 0) {
1408 rewriter.replaceOp(derivedClassOp, baseAddr);
1409 return mlir::success();
1411 llvm::SmallVector<mlir::LLVM::GEPArg, 1> offset = {offsetVal};
1412 mlir::Type byteType = mlir::IntegerType::get(resultType.getContext(), 8,
1413 mlir::IntegerType::Signless);
1414 if (derivedClassOp.getAssumeNotNull()) {
1415 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1416 derivedClassOp, resultType, byteType, baseAddr, offset,
1417 mlir::LLVM::GEPNoWrapFlags::inbounds);
1419 mlir::Location loc = derivedClassOp.getLoc();
1420 mlir::Value isNull = mlir::LLVM::ICmpOp::create(
1421 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, baseAddr,
1422 mlir::LLVM::ZeroOp::create(rewriter, loc, baseAddr.getType()));
1423 mlir::Value adjusted =
1424 mlir::LLVM::GEPOp::create(rewriter, loc, resultType, byteType, baseAddr,
1425 offset, mlir::LLVM::GEPNoWrapFlags::inbounds);
1426 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(derivedClassOp, isNull,
1427 baseAddr, adjusted);
1429 return mlir::success();
1432mlir::LogicalResult CIRToLLVMATanOpLowering::matchAndRewrite(
1433 cir::ATanOp op, OpAdaptor adaptor,
1434 mlir::ConversionPatternRewriter &rewriter)
const {
1435 mlir::Type resTy = typeConverter->convertType(op.getType());
1436 rewriter.replaceOpWithNewOp<mlir::LLVM::ATanOp>(op, resTy, adaptor.getSrc());
1437 return mlir::success();
1440mlir::LogicalResult CIRToLLVMCeilOpLowering::matchAndRewrite(
1441 cir::CeilOp op, OpAdaptor adaptor,
1442 mlir::ConversionPatternRewriter &rewriter)
const {
1443 mlir::Type resTy = typeConverter->convertType(op.getType());
1444 rewriter.replaceOpWithNewOp<mlir::LLVM::FCeilOp>(op, resTy, adaptor.getSrc());
1445 return mlir::success();
1448mlir::LogicalResult CIRToLLVMAllocaOpLowering::matchAndRewrite(
1449 cir::AllocaOp op, OpAdaptor adaptor,
1450 mlir::ConversionPatternRewriter &rewriter)
const {
1453 ? adaptor.getDynAllocSize()
1454 : mlir::LLVM::ConstantOp::create(
1455 rewriter, op.getLoc(),
1456 typeConverter->convertType(rewriter.getIndexType()), 1);
1457 mlir::Type elementTy =
1459 mlir::Type resultTy =
1465 rewriter.replaceOpWithNewOp<mlir::LLVM::AllocaOp>(
1466 op, resultTy, elementTy, size, op.getAlignmentAttr().getInt());
1468 return mlir::success();
1471mlir::LogicalResult CIRToLLVMReturnOpLowering::matchAndRewrite(
1472 cir::ReturnOp op, OpAdaptor adaptor,
1473 mlir::ConversionPatternRewriter &rewriter)
const {
1474 rewriter.replaceOpWithNewOp<mlir::LLVM::ReturnOp>(op, adaptor.getOperands());
1475 return mlir::LogicalResult::success();
1478mlir::LogicalResult CIRToLLVMRotateOpLowering::matchAndRewrite(
1479 cir::RotateOp op, OpAdaptor adaptor,
1480 mlir::ConversionPatternRewriter &rewriter)
const {
1483 mlir::Value input = adaptor.getInput();
1484 if (op.isRotateLeft())
1485 rewriter.replaceOpWithNewOp<mlir::LLVM::FshlOp>(op, input, input,
1486 adaptor.getAmount());
1488 rewriter.replaceOpWithNewOp<mlir::LLVM::FshrOp>(op, input, input,
1489 adaptor.getAmount());
1490 return mlir::LogicalResult::success();
1493static mlir::LogicalResult
1495 mlir::ConversionPatternRewriter &rewriter,
1496 const mlir::TypeConverter *converter,
1497 mlir::FlatSymbolRefAttr calleeAttr) {
1499 mlir::ValueTypeRange<mlir::ResultRange> cirResults = op->getResultTypes();
1500 auto call = cast<cir::CIRCallOpInterface>(op);
1502 if (converter->convertTypes(cirResults, llvmResults).failed())
1503 return mlir::failure();
1507 mlir::LLVM::MemoryEffectsAttr memoryEffects;
1508 bool noUnwind =
false;
1509 bool willReturn =
false;
1511 memoryEffects, noUnwind, willReturn);
1513 mlir::LLVM::LLVMFunctionType llvmFnTy;
1520 mlir::Operation *callee =
1521 mlir::SymbolTable::lookupNearestSymbolFrom(op, calleeAttr);
1522 if (
auto fn = mlir::dyn_cast<mlir::FunctionOpInterface>(callee)) {
1523 llvmFnTy = converter->convertType<mlir::LLVM::LLVMFunctionType>(
1524 fn.getFunctionType());
1525 assert(llvmFnTy &&
"Failed to convert function type");
1526 }
else if (
auto alias = mlir::cast<mlir::LLVM::AliasOp>(callee)) {
1534 auto symAttr = mlir::cast<mlir::FlatSymbolRefAttr>(calleeAttr);
1536 mlir::LLVM::AddressOfOp::create(
1537 rewriter, op->getLoc(),
1538 mlir::LLVM::LLVMPointerType::get(rewriter.getContext()), symAttr)
1540 adjustedCallOperands.push_back(addrOfAlias);
1543 llvm::append_range(adjustedCallOperands, callOperands);
1544 callOperands = adjustedCallOperands;
1548 llvmFnTy = mlir::cast<mlir::LLVM::LLVMFunctionType>(alias.getType());
1551 return op->emitError(
"Unexpected callee type!");
1554 assert(!op->getOperands().empty() &&
1555 "operands list must no be empty for the indirect call");
1556 auto calleeTy = op->getOperands().front().getType();
1557 auto calleePtrTy = cast<cir::PointerType>(calleeTy);
1558 auto calleeFuncTy = cast<cir::FuncType>(calleePtrTy.getPointee());
1559 llvm::append_range(adjustedCallOperands, callOperands);
1560 llvmFnTy = cast<mlir::LLVM::LLVMFunctionType>(
1561 converter->convertType(calleeFuncTy));
1568 auto newOp = rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(
1569 op, llvmFnTy, calleeAttr, callOperands);
1571 newOp.setMemoryEffectsAttr(memoryEffects);
1572 newOp.setNoUnwind(noUnwind);
1573 newOp.setWillReturn(willReturn);
1575 return mlir::success();
1578mlir::LogicalResult CIRToLLVMCallOpLowering::matchAndRewrite(
1579 cir::CallOp op, OpAdaptor adaptor,
1580 mlir::ConversionPatternRewriter &rewriter)
const {
1582 getTypeConverter(), op.getCalleeAttr());
1585mlir::LogicalResult CIRToLLVMReturnAddrOpLowering::matchAndRewrite(
1586 cir::ReturnAddrOp op, OpAdaptor adaptor,
1587 mlir::ConversionPatternRewriter &rewriter)
const {
1588 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
1590 llvmPtrTy, adaptor.getOperands());
1591 return mlir::success();
1594mlir::LogicalResult CIRToLLVMFrameAddrOpLowering::matchAndRewrite(
1595 cir::FrameAddrOp op, OpAdaptor adaptor,
1596 mlir::ConversionPatternRewriter &rewriter)
const {
1597 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
1599 adaptor.getOperands());
1600 return mlir::success();
1603mlir::LogicalResult CIRToLLVMLoadOpLowering::matchAndRewrite(
1604 cir::LoadOp op, OpAdaptor adaptor,
1605 mlir::ConversionPatternRewriter &rewriter)
const {
1606 const mlir::Type llvmTy =
1608 mlir::LLVM::AtomicOrdering ordering =
getLLVMMemOrder(op.getMemOrder());
1609 std::optional<size_t> opAlign = op.getAlignment();
1610 unsigned alignment =
1611 (unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmTy));
1617 mlir::LLVM::LoadOp newLoad = mlir::LLVM::LoadOp::create(
1618 rewriter, op->getLoc(), llvmTy, adaptor.getAddr(), alignment,
1619 op.getIsVolatile(),
false,
1620 false,
false, ordering);
1623 mlir::Value result =
1625 rewriter.replaceOp(op, result);
1627 return mlir::LogicalResult::success();
1630mlir::LogicalResult CIRToLLVMStoreOpLowering::matchAndRewrite(
1631 cir::StoreOp op, OpAdaptor adaptor,
1632 mlir::ConversionPatternRewriter &rewriter)
const {
1633 mlir::LLVM::AtomicOrdering memorder =
getLLVMMemOrder(op.getMemOrder());
1634 const mlir::Type llvmTy =
1635 getTypeConverter()->convertType(op.getValue().getType());
1636 std::optional<size_t> opAlign = op.getAlignment();
1637 unsigned alignment =
1638 (unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmTy));
1644 op.getValue().getType(), adaptor.getValue());
1648 mlir::LLVM::StoreOp storeOp = mlir::LLVM::StoreOp::create(
1649 rewriter, op->getLoc(), value, adaptor.getAddr(), alignment,
1651 false,
false, memorder);
1652 rewriter.replaceOp(op, storeOp);
1654 return mlir::LogicalResult::success();
1658 auto array = mlir::dyn_cast<mlir::ArrayAttr>(attr.getElts());
1659 return attr.hasTrailingZeros() ||
1660 (array && std::count_if(array.begin(), array.end(), [](
auto elt) {
1661 auto ar = dyn_cast<cir::ConstArrayAttr>(elt);
1662 return ar && hasTrailingZeros(ar);
1666mlir::LogicalResult CIRToLLVMConstantOpLowering::matchAndRewrite(
1667 cir::ConstantOp op, OpAdaptor adaptor,
1668 mlir::ConversionPatternRewriter &rewriter)
const {
1669 mlir::Attribute attr = op.getValue();
1671 if (mlir::isa<cir::PoisonAttr>(attr)) {
1672 rewriter.replaceOpWithNewOp<mlir::LLVM::PoisonOp>(
1673 op, getTypeConverter()->convertType(op.getType()));
1674 return mlir::success();
1677 if (mlir::isa<mlir::IntegerType>(op.getType())) {
1682 attr = op.getValue();
1683 }
else if (mlir::isa<cir::BoolType>(op.getType())) {
1684 int value = mlir::cast<cir::BoolAttr>(op.getValue()).getValue();
1685 attr = rewriter.getIntegerAttr(typeConverter->convertType(op.getType()),
1687 }
else if (mlir::isa<cir::IntType>(op.getType())) {
1689 if (
auto ga = mlir::dyn_cast<cir::GlobalViewAttr>(op.getValue())) {
1692 op.emitError() <<
"global view with integer type";
1693 return mlir::failure();
1696 attr = rewriter.getIntegerAttr(
1697 typeConverter->convertType(op.getType()),
1698 mlir::cast<cir::IntAttr>(op.getValue()).getValue());
1699 }
else if (mlir::isa<cir::FPTypeInterface>(op.getType())) {
1700 attr = rewriter.getFloatAttr(
1701 typeConverter->convertType(op.getType()),
1702 mlir::cast<cir::FPAttr>(op.getValue()).getValue());
1703 }
else if (mlir::isa<cir::PointerType>(op.getType())) {
1705 if (mlir::isa<cir::ConstPtrAttr>(op.getValue())) {
1706 if (mlir::cast<cir::ConstPtrAttr>(op.getValue()).isNullValue()) {
1707 rewriter.replaceOpWithNewOp<mlir::LLVM::ZeroOp>(
1708 op, typeConverter->convertType(op.getType()));
1709 return mlir::success();
1713 if (
auto gv = mlir::dyn_cast<cir::GlobalViewAttr>(op.getValue())) {
1715 rewriter.replaceOp(op, newOp);
1716 return mlir::success();
1718 attr = op.getValue();
1719 }
else if (
const auto arrTy = mlir::dyn_cast<cir::ArrayType>(op.getType())) {
1720 const auto constArr = mlir::dyn_cast<cir::ConstArrayAttr>(op.getValue());
1721 if (!constArr && !isa<cir::ZeroAttr, cir::UndefAttr>(op.getValue()))
1722 return op.emitError() <<
"array does not have a constant initializer";
1724 std::optional<mlir::Attribute> denseAttr;
1726 const mlir::Value newOp =
1728 rewriter.replaceOp(op, newOp);
1729 return mlir::success();
1730 }
else if (constArr &&
1732 attr = denseAttr.value();
1734 const mlir::Value initVal =
1736 rewriter.replaceOp(op, initVal);
1737 return mlir::success();
1739 }
else if (
const auto recordAttr =
1740 mlir::dyn_cast<cir::ConstRecordAttr>(op.getValue())) {
1742 rewriter.replaceOp(op, initVal);
1743 return mlir::success();
1744 }
else if (
const auto vecTy = mlir::dyn_cast<cir::VectorType>(op.getType())) {
1746 getTypeConverter()));
1747 return mlir::success();
1748 }
else if (
auto recTy = mlir::dyn_cast<cir::RecordType>(op.getType())) {
1749 if (mlir::isa<cir::ZeroAttr, cir::UndefAttr>(attr)) {
1750 mlir::Value initVal =
1752 rewriter.replaceOp(op, initVal);
1753 return mlir::success();
1755 return op.emitError() <<
"unsupported lowering for record constant type "
1757 }
else if (
auto complexTy = mlir::dyn_cast<cir::ComplexType>(op.getType())) {
1758 mlir::Type complexElemTy = complexTy.getElementType();
1759 mlir::Type complexElemLLVMTy = typeConverter->convertType(complexElemTy);
1761 if (
auto zeroInitAttr = mlir::dyn_cast<cir::ZeroAttr>(op.getValue())) {
1762 mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(complexElemLLVMTy);
1763 mlir::ArrayAttr array = rewriter.getArrayAttr({zeroAttr, zeroAttr});
1764 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
1765 op, getTypeConverter()->convertType(op.getType()), array);
1766 return mlir::success();
1769 auto complexAttr = mlir::cast<cir::ConstComplexAttr>(op.getValue());
1771 mlir::Attribute components[2];
1772 if (mlir::isa<cir::IntType>(complexElemTy)) {
1773 components[0] = rewriter.getIntegerAttr(
1775 mlir::cast<cir::IntAttr>(complexAttr.getReal()).getValue());
1776 components[1] = rewriter.getIntegerAttr(
1778 mlir::cast<cir::IntAttr>(complexAttr.getImag()).getValue());
1780 components[0] = rewriter.getFloatAttr(
1782 mlir::cast<cir::FPAttr>(complexAttr.getReal()).getValue());
1783 components[1] = rewriter.getFloatAttr(
1785 mlir::cast<cir::FPAttr>(complexAttr.getImag()).getValue());
1788 attr = rewriter.getArrayAttr(components);
1790 return op.emitError() <<
"unsupported constant type " << op.getType();
1793 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
1794 op, getTypeConverter()->convertType(op.getType()),
attr);
1796 return mlir::success();
1800 mlir::DataLayout layout(op.getParentOfType<mlir::ModuleOp>());
1802 if (isa<cir::VoidType>(type))
1803 type = cir::IntType::get(type.getContext(), 8,
false);
1804 return llvm::divideCeil(layout.getTypeSizeInBits(type), 8);
1807mlir::LogicalResult CIRToLLVMPrefetchOpLowering::matchAndRewrite(
1808 cir::PrefetchOp op, OpAdaptor adaptor,
1809 mlir::ConversionPatternRewriter &rewriter)
const {
1810 rewriter.replaceOpWithNewOp<mlir::LLVM::Prefetch>(
1811 op, adaptor.getAddr(), adaptor.getIsWrite(), adaptor.getLocality(),
1813 return mlir::success();
1816mlir::LogicalResult CIRToLLVMPtrDiffOpLowering::matchAndRewrite(
1817 cir::PtrDiffOp op, OpAdaptor adaptor,
1818 mlir::ConversionPatternRewriter &rewriter)
const {
1819 auto dstTy = mlir::cast<cir::IntType>(op.getType());
1820 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1822 auto lhs = mlir::LLVM::PtrToIntOp::create(rewriter, op.getLoc(), llvmDstTy,
1824 auto rhs = mlir::LLVM::PtrToIntOp::create(rewriter, op.getLoc(), llvmDstTy,
1828 mlir::LLVM::SubOp::create(rewriter, op.getLoc(), llvmDstTy, lhs, rhs);
1830 cir::PointerType ptrTy = op.getLhs().getType();
1832 uint64_t typeSize =
getTypeSize(ptrTy.getPointee(), *op);
1835 mlir::Value resultVal = diff.getResult();
1836 if (typeSize != 1) {
1837 auto typeSizeVal = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1838 llvmDstTy, typeSize);
1840 if (dstTy.isUnsigned()) {
1842 mlir::LLVM::UDivOp::create(rewriter, op.getLoc(), diff, typeSizeVal);
1843 uDiv.setIsExact(
true);
1844 resultVal = uDiv.getResult();
1847 mlir::LLVM::SDivOp::create(rewriter, op.getLoc(), diff, typeSizeVal);
1848 sDiv.setIsExact(
true);
1849 resultVal = sDiv.getResult();
1852 rewriter.replaceOp(op, resultVal);
1853 return mlir::success();
1856mlir::LogicalResult CIRToLLVMExpectOpLowering::matchAndRewrite(
1857 cir::ExpectOp op, OpAdaptor adaptor,
1858 mlir::ConversionPatternRewriter &rewriter)
const {
1862 std::optional<llvm::APFloat> prob = op.getProb();
1864 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpectWithProbabilityOp>(
1865 op, adaptor.getVal(), adaptor.getExpected(), prob.value());
1867 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpectOp>(op, adaptor.getVal(),
1868 adaptor.getExpected());
1869 return mlir::success();
1872mlir::LogicalResult CIRToLLVMFAbsOpLowering::matchAndRewrite(
1873 cir::FAbsOp op, OpAdaptor adaptor,
1874 mlir::ConversionPatternRewriter &rewriter)
const {
1875 mlir::Type resTy = typeConverter->convertType(op.getType());
1876 rewriter.replaceOpWithNewOp<mlir::LLVM::FAbsOp>(op, resTy,
1877 adaptor.getOperands()[0]);
1878 return mlir::success();
1885void CIRToLLVMFuncOpLowering::lowerFuncAttributes(
1886 cir::FuncOp func,
bool filterArgAndResAttrs,
1887 SmallVectorImpl<mlir::NamedAttribute> &result)
const {
1889 for (mlir::NamedAttribute attr : func->getAttrs()) {
1891 if (
attr.getName() == mlir::SymbolTable::getSymbolAttrName() ||
1892 attr.getName() == func.getFunctionTypeAttrName() ||
1894 attr.getName() == func.getGlobalVisibilityAttrName() ||
1895 attr.getName() == func.getDsoLocalAttrName() ||
1896 attr.getName() == func.getInlineKindAttrName() ||
1897 (filterArgAndResAttrs &&
1898 (
attr.getName() == func.getArgAttrsAttrName() ||
1899 attr.getName() == func.getResAttrsAttrName())))
1903 result.push_back(attr);
1907mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewriteAlias(
1908 cir::FuncOp op, llvm::StringRef aliasee, mlir::Type ty, OpAdaptor adaptor,
1909 mlir::ConversionPatternRewriter &rewriter)
const {
1910 SmallVector<mlir::NamedAttribute, 4> attributes;
1911 lowerFuncAttributes(op,
false, attributes);
1913 mlir::Location loc = op.getLoc();
1914 auto aliasOp = rewriter.replaceOpWithNewOp<mlir::LLVM::AliasOp>(
1915 op, ty,
convertLinkage(op.getLinkage()), op.getName(), op.getDsoLocal(),
1919 mlir::OpBuilder builder(op.getContext());
1920 mlir::Block *block = builder.createBlock(&aliasOp.getInitializerRegion());
1921 builder.setInsertionPointToStart(block);
1924 mlir::Type ptrTy = mlir::LLVM::LLVMPointerType::get(ty.getContext());
1925 auto addrOp = mlir::LLVM::AddressOfOp::create(builder, loc, ptrTy, aliasee);
1926 mlir::LLVM::ReturnOp::create(builder, loc, addrOp);
1928 return mlir::success();
1931mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewrite(
1932 cir::FuncOp op, OpAdaptor adaptor,
1933 mlir::ConversionPatternRewriter &rewriter)
const {
1935 cir::FuncType fnType = op.getFunctionType();
1936 bool isDsoLocal = op.getDsoLocal();
1937 mlir::TypeConverter::SignatureConversion signatureConversion(
1938 fnType.getNumInputs());
1940 for (
const auto &argType : llvm::enumerate(fnType.getInputs())) {
1941 mlir::Type convertedType = typeConverter->convertType(argType.value());
1943 return mlir::failure();
1944 signatureConversion.addInputs(argType.index(), convertedType);
1947 mlir::Type resultType =
1948 getTypeConverter()->convertType(fnType.getReturnType());
1951 mlir::Type llvmFnTy = mlir::LLVM::LLVMFunctionType::get(
1952 resultType ? resultType : mlir::LLVM::LLVMVoidType::get(getContext()),
1953 signatureConversion.getConvertedTypes(),
1957 if (std::optional<llvm::StringRef> aliasee = op.getAliasee())
1958 return matchAndRewriteAlias(op, *aliasee, llvmFnTy, adaptor, rewriter);
1962 mlir::Location loc = op.getLoc();
1963 if (mlir::FusedLoc fusedLoc = mlir::dyn_cast<mlir::FusedLoc>(loc))
1964 loc = fusedLoc.getLocations()[0];
1965 assert((mlir::isa<mlir::FileLineColLoc>(loc) ||
1966 mlir::isa<mlir::UnknownLoc>(loc)) &&
1967 "expected single location or unknown location here");
1971 mlir::LLVM::CConv cconv = mlir::LLVM::CConv::C;
1972 SmallVector<mlir::NamedAttribute, 4> attributes;
1973 lowerFuncAttributes(op,
false, attributes);
1975 mlir::LLVM::LLVMFuncOp fn = mlir::LLVM::LLVMFuncOp::create(
1976 rewriter, loc, op.getName(), llvmFnTy, linkage, isDsoLocal, cconv,
1977 mlir::SymbolRefAttr(), attributes);
1981 if (
auto inlineKind = op.getInlineKind()) {
1982 fn.setNoInline(inlineKind == cir::InlineKind::NoInline);
1983 fn.setInlineHint(inlineKind == cir::InlineKind::InlineHint);
1984 fn.setAlwaysInline(inlineKind == cir::InlineKind::AlwaysInline);
1987 fn.setVisibility_Attr(mlir::LLVM::VisibilityAttr::get(
1989 op.getGlobalVisibilityAttr().getValue())));
1991 rewriter.inlineRegionBefore(op.getBody(), fn.getBody(), fn.end());
1992 if (failed(rewriter.convertRegionTypes(&fn.getBody(), *typeConverter,
1993 &signatureConversion)))
1994 return mlir::failure();
1996 rewriter.eraseOp(op);
1998 return mlir::LogicalResult::success();
2001mlir::LogicalResult CIRToLLVMGetGlobalOpLowering::matchAndRewrite(
2002 cir::GetGlobalOp op, OpAdaptor adaptor,
2003 mlir::ConversionPatternRewriter &rewriter)
const {
2006 if (op->getUses().empty()) {
2007 rewriter.eraseOp(op);
2008 return mlir::success();
2011 mlir::Type
type = getTypeConverter()->convertType(op.getType());
2012 mlir::Operation *newop = mlir::LLVM::AddressOfOp::create(
2013 rewriter, op.getLoc(), type, op.getName());
2017 rewriter.replaceOp(op, newop);
2018 return mlir::success();
2023void CIRToLLVMGlobalOpLowering::setupRegionInitializedLLVMGlobalOp(
2024 cir::GlobalOp op, mlir::ConversionPatternRewriter &rewriter)
const {
2025 const mlir::Type llvmType =
2032 const bool isConst = op.getConstant();
2034 const unsigned addrSpace = 0;
2035 const bool isDsoLocal = op.getDsoLocal();
2037 const bool isThreadLocal =
false;
2038 const uint64_t alignment = op.getAlignment().value_or(0);
2039 const mlir::LLVM::Linkage linkage =
convertLinkage(op.getLinkage());
2040 const StringRef symbol = op.getSymName();
2041 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
2043 SmallVector<mlir::NamedAttribute> attributes;
2044 mlir::LLVM::GlobalOp newGlobalOp =
2045 rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
2046 op, llvmType, isConst, linkage, symbol,
nullptr, alignment, addrSpace,
2047 isDsoLocal, isThreadLocal, comdatAttr, attributes);
2048 newGlobalOp.getRegion().emplaceBlock();
2049 rewriter.setInsertionPointToEnd(newGlobalOp.getInitializerBlock());
2053CIRToLLVMGlobalOpLowering::matchAndRewriteRegionInitializedGlobal(
2054 cir::GlobalOp op, mlir::Attribute init,
2055 mlir::ConversionPatternRewriter &rewriter)
const {
2058 (isa<cir::ConstArrayAttr, cir::ConstRecordAttr, cir::ConstVectorAttr,
2059 cir::ConstPtrAttr, cir::ConstComplexAttr, cir::GlobalViewAttr,
2060 cir::TypeInfoAttr, cir::UndefAttr, cir::VTableAttr, cir::ZeroAttr>(
2066 const mlir::Location loc = op.getLoc();
2067 setupRegionInitializedLLVMGlobalOp(op, rewriter);
2069 mlir::Value value = valueConverter.visit(init);
2070 mlir::LLVM::ReturnOp::create(rewriter, loc, value);
2071 return mlir::success();
2074mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite(
2075 cir::GlobalOp op, OpAdaptor adaptor,
2076 mlir::ConversionPatternRewriter &rewriter)
const {
2079 if (!op.getCtorRegion().empty() || !op.getDtorRegion().empty())
2080 return op.emitError() <<
"GlobalOp ctor and dtor regions should be removed "
2081 "in LoweringPrepare";
2083 std::optional<mlir::Attribute> init = op.getInitialValue();
2086 const mlir::Type cirSymType = op.getSymType();
2089 const mlir::Type llvmType =
2093 const bool isConst = op.getConstant();
2095 const unsigned addrSpace = 0;
2096 const bool isDsoLocal = op.getDsoLocal();
2098 const bool isThreadLocal =
false;
2099 const uint64_t alignment = op.getAlignment().value_or(0);
2100 const mlir::LLVM::Linkage linkage =
convertLinkage(op.getLinkage());
2101 const StringRef symbol = op.getSymName();
2102 SmallVector<mlir::NamedAttribute> attributes;
2104 if (init.has_value()) {
2105 if (mlir::isa<cir::FPAttr, cir::IntAttr, cir::BoolAttr>(init.value())) {
2107 init = initRewriter.visit(init.value());
2112 if (!init.value()) {
2113 op.emitError() <<
"unsupported initializer '" << init.value() <<
"'";
2114 return mlir::failure();
2116 }
else if (mlir::isa<cir::ConstArrayAttr, cir::ConstVectorAttr,
2117 cir::ConstRecordAttr, cir::ConstPtrAttr,
2118 cir::ConstComplexAttr, cir::GlobalViewAttr,
2119 cir::TypeInfoAttr, cir::UndefAttr, cir::VTableAttr,
2120 cir::ZeroAttr>(init.value())) {
2124 return matchAndRewriteRegionInitializedGlobal(op, init.value(), rewriter);
2128 op.emitError() <<
"unsupported initializer '" << init.value() <<
"'";
2129 return mlir::failure();
2134 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
2135 auto newOp = rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
2136 op, llvmType, isConst, linkage, symbol, init.value_or(mlir::Attribute()),
2137 alignment, addrSpace, isDsoLocal, isThreadLocal, comdatAttr, attributes);
2138 newOp.setVisibility_Attr(mlir::LLVM::VisibilityAttr::get(
2140 op.getGlobalVisibilityAttr().getValue())));
2142 return mlir::success();
2146CIRToLLVMGlobalOpLowering::getComdatAttr(cir::GlobalOp &op,
2147 mlir::OpBuilder &builder)
const {
2148 if (!op.getComdat())
2149 return mlir::SymbolRefAttr{};
2151 mlir::ModuleOp module = op->getParentOfType<mlir::ModuleOp>();
2152 mlir::OpBuilder::InsertionGuard guard(builder);
2153 StringRef comdatName(
"__llvm_comdat_globals");
2155 builder.setInsertionPointToStart(module.getBody());
2157 mlir::LLVM::ComdatOp::create(builder, module.getLoc(), comdatName);
2160 if (
auto comdatSelector = comdatOp.lookupSymbol<mlir::LLVM::ComdatSelectorOp>(
2162 return mlir::SymbolRefAttr::get(
2163 builder.getContext(), comdatName,
2164 mlir::FlatSymbolRefAttr::get(comdatSelector.getSymNameAttr()));
2167 builder.setInsertionPointToStart(&comdatOp.getBody().back());
2168 auto selectorOp = mlir::LLVM::ComdatSelectorOp::create(
2169 builder, comdatOp.getLoc(), op.getSymName(),
2170 mlir::LLVM::comdat::Comdat::Any);
2171 return mlir::SymbolRefAttr::get(
2172 builder.getContext(), comdatName,
2173 mlir::FlatSymbolRefAttr::get(selectorOp.getSymNameAttr()));
2176mlir::LogicalResult CIRToLLVMSwitchFlatOpLowering::matchAndRewrite(
2177 cir::SwitchFlatOp op, OpAdaptor adaptor,
2178 mlir::ConversionPatternRewriter &rewriter)
const {
2180 llvm::SmallVector<mlir::APInt, 8> caseValues;
2181 for (mlir::Attribute val : op.getCaseValues()) {
2182 auto intAttr = cast<cir::IntAttr>(val);
2183 caseValues.push_back(intAttr.getValue());
2186 llvm::SmallVector<mlir::Block *, 8> caseDestinations;
2187 llvm::SmallVector<mlir::ValueRange, 8> caseOperands;
2189 for (mlir::Block *x : op.getCaseDestinations())
2190 caseDestinations.push_back(x);
2192 for (mlir::OperandRange x : op.getCaseOperands())
2193 caseOperands.push_back(x);
2196 rewriter.setInsertionPoint(op);
2197 rewriter.replaceOpWithNewOp<mlir::LLVM::SwitchOp>(
2198 op, adaptor.getCondition(), op.getDefaultDestination(),
2199 op.getDefaultOperands(), caseValues, caseDestinations, caseOperands);
2200 return mlir::success();
2203mlir::LogicalResult CIRToLLVMUnaryOpLowering::matchAndRewrite(
2204 cir::UnaryOp op, OpAdaptor adaptor,
2205 mlir::ConversionPatternRewriter &rewriter)
const {
2206 assert(op.getType() == op.getInput().getType() &&
2207 "Unary operation's operand type and result type are different");
2208 mlir::Type
type = op.getType();
2209 mlir::Type elementType = elementTypeIfVector(type);
2210 bool isVector = mlir::isa<cir::VectorType>(type);
2211 mlir::Type llvmType = getTypeConverter()->convertType(type);
2212 mlir::Location loc = op.getLoc();
2215 if (mlir::isa<cir::IntType>(elementType)) {
2216 mlir::LLVM::IntegerOverflowFlags maybeNSW =
2217 op.getNoSignedWrap() ? mlir::LLVM::IntegerOverflowFlags::nsw
2218 : mlir::LLVM::IntegerOverflowFlags::none;
2219 switch (op.getKind()) {
2220 case cir::UnaryOpKind::Inc: {
2221 assert(!
isVector &&
"++ not allowed on vector types");
2222 auto one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
2223 rewriter.replaceOpWithNewOp<mlir::LLVM::AddOp>(
2224 op, llvmType, adaptor.getInput(), one, maybeNSW);
2225 return mlir::success();
2227 case cir::UnaryOpKind::Dec: {
2228 assert(!
isVector &&
"-- not allowed on vector types");
2229 auto one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
2230 rewriter.replaceOpWithNewOp<mlir::LLVM::SubOp>(op, adaptor.getInput(),
2232 return mlir::success();
2234 case cir::UnaryOpKind::Plus:
2235 rewriter.replaceOp(op, adaptor.getInput());
2236 return mlir::success();
2237 case cir::UnaryOpKind::Minus: {
2240 zero = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmType);
2242 zero = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 0);
2243 rewriter.replaceOpWithNewOp<mlir::LLVM::SubOp>(
2244 op, zero, adaptor.getInput(), maybeNSW);
2245 return mlir::success();
2247 case cir::UnaryOpKind::Not: {
2249 mlir::Value minusOne;
2252 mlir::dyn_cast<cir::VectorType>(type).getSize();
2253 std::vector<int32_t> values(numElements, -1);
2254 mlir::DenseIntElementsAttr denseVec = rewriter.getI32VectorAttr(values);
2256 mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, denseVec);
2258 minusOne = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, -1);
2260 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getInput(),
2262 return mlir::success();
2265 llvm_unreachable(
"Unexpected unary op for int");
2269 if (mlir::isa<cir::FPTypeInterface>(elementType)) {
2270 switch (op.getKind()) {
2271 case cir::UnaryOpKind::Inc: {
2272 assert(!
isVector &&
"++ not allowed on vector types");
2273 mlir::LLVM::ConstantOp one = mlir::LLVM::ConstantOp::create(
2274 rewriter, loc, llvmType, rewriter.getFloatAttr(llvmType, 1.0));
2275 rewriter.replaceOpWithNewOp<mlir::LLVM::FAddOp>(op, llvmType, one,
2276 adaptor.getInput());
2277 return mlir::success();
2279 case cir::UnaryOpKind::Dec: {
2280 assert(!
isVector &&
"-- not allowed on vector types");
2281 mlir::LLVM::ConstantOp minusOne = mlir::LLVM::ConstantOp::create(
2282 rewriter, loc, llvmType, rewriter.getFloatAttr(llvmType, -1.0));
2283 rewriter.replaceOpWithNewOp<mlir::LLVM::FAddOp>(op, llvmType, minusOne,
2284 adaptor.getInput());
2285 return mlir::success();
2287 case cir::UnaryOpKind::Plus:
2288 rewriter.replaceOp(op, adaptor.getInput());
2289 return mlir::success();
2290 case cir::UnaryOpKind::Minus:
2291 rewriter.replaceOpWithNewOp<mlir::LLVM::FNegOp>(op, llvmType,
2292 adaptor.getInput());
2293 return mlir::success();
2294 case cir::UnaryOpKind::Not:
2295 return op.emitError() <<
"Unary not is invalid for floating-point types";
2297 llvm_unreachable(
"Unexpected unary op for float");
2302 if (mlir::isa<cir::BoolType>(elementType)) {
2303 switch (op.getKind()) {
2304 case cir::UnaryOpKind::Inc:
2305 case cir::UnaryOpKind::Dec:
2306 case cir::UnaryOpKind::Plus:
2307 case cir::UnaryOpKind::Minus:
2310 return op.emitError() <<
"Unsupported unary operation on boolean type";
2311 case cir::UnaryOpKind::Not: {
2312 assert(!
isVector &&
"NYI: op! on vector mask");
2313 auto one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
2314 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getInput(),
2316 return mlir::success();
2319 llvm_unreachable(
"Unexpected unary op for bool");
2324 if (mlir::isa<cir::PointerType>(elementType)) {
2325 switch (op.getKind()) {
2326 case cir::UnaryOpKind::Plus:
2327 rewriter.replaceOp(op, adaptor.getInput());
2328 return mlir::success();
2330 op.emitError() <<
"Unknown pointer unary operation during CIR lowering";
2331 return mlir::failure();
2335 return op.emitError() <<
"Unary operation has unsupported type: "
2339mlir::LLVM::IntegerOverflowFlags
2340CIRToLLVMBinOpLowering::getIntOverflowFlag(cir::BinOp op)
const {
2341 if (op.getNoUnsignedWrap())
2342 return mlir::LLVM::IntegerOverflowFlags::nuw;
2344 if (op.getNoSignedWrap())
2345 return mlir::LLVM::IntegerOverflowFlags::nsw;
2347 return mlir::LLVM::IntegerOverflowFlags::none;
2352 return mlir::isa<cir::IntType>(type)
2353 ? mlir::cast<cir::IntType>(type).isUnsigned()
2354 : mlir::cast<mlir::IntegerType>(type).isUnsigned();
2357mlir::LogicalResult CIRToLLVMBinOpLowering::matchAndRewrite(
2358 cir::BinOp op, OpAdaptor adaptor,
2359 mlir::ConversionPatternRewriter &rewriter)
const {
2360 if (adaptor.getLhs().getType() != adaptor.getRhs().getType())
2361 return op.emitError() <<
"inconsistent operands' types not supported yet";
2363 mlir::Type type = op.getRhs().getType();
2364 if (!mlir::isa<cir::IntType, cir::BoolType, cir::FPTypeInterface,
2365 mlir::IntegerType, cir::VectorType>(type))
2366 return op.emitError() <<
"operand type not supported yet";
2368 const mlir::Type llvmTy = getTypeConverter()->convertType(op.getType());
2369 const mlir::Type llvmEltTy = elementTypeIfVector(llvmTy);
2371 const mlir::Value rhs = adaptor.getRhs();
2372 const mlir::Value lhs = adaptor.getLhs();
2373 type = elementTypeIfVector(type);
2375 switch (op.getKind()) {
2376 case cir::BinOpKind::Add:
2377 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
2378 if (op.getSaturated()) {
2380 rewriter.replaceOpWithNewOp<mlir::LLVM::UAddSat>(op, lhs, rhs);
2383 rewriter.replaceOpWithNewOp<mlir::LLVM::SAddSat>(op, lhs, rhs);
2386 rewriter.replaceOpWithNewOp<mlir::LLVM::AddOp>(op, llvmTy, lhs, rhs,
2387 getIntOverflowFlag(op));
2389 rewriter.replaceOpWithNewOp<mlir::LLVM::FAddOp>(op, lhs, rhs);
2392 case cir::BinOpKind::Sub:
2393 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
2394 if (op.getSaturated()) {
2396 rewriter.replaceOpWithNewOp<mlir::LLVM::USubSat>(op, lhs, rhs);
2399 rewriter.replaceOpWithNewOp<mlir::LLVM::SSubSat>(op, lhs, rhs);
2402 rewriter.replaceOpWithNewOp<mlir::LLVM::SubOp>(op, llvmTy, lhs, rhs,
2403 getIntOverflowFlag(op));
2405 rewriter.replaceOpWithNewOp<mlir::LLVM::FSubOp>(op, lhs, rhs);
2408 case cir::BinOpKind::Mul:
2409 if (mlir::isa<mlir::IntegerType>(llvmEltTy))
2410 rewriter.replaceOpWithNewOp<mlir::LLVM::MulOp>(op, llvmTy, lhs, rhs,
2411 getIntOverflowFlag(op));
2413 rewriter.replaceOpWithNewOp<mlir::LLVM::FMulOp>(op, lhs, rhs);
2415 case cir::BinOpKind::Div:
2416 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
2419 rewriter.replaceOpWithNewOp<mlir::LLVM::UDivOp>(op, lhs, rhs);
2421 rewriter.replaceOpWithNewOp<mlir::LLVM::SDivOp>(op, lhs, rhs);
2423 rewriter.replaceOpWithNewOp<mlir::LLVM::FDivOp>(op, lhs, rhs);
2426 case cir::BinOpKind::Rem:
2427 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
2430 rewriter.replaceOpWithNewOp<mlir::LLVM::URemOp>(op, lhs, rhs);
2432 rewriter.replaceOpWithNewOp<mlir::LLVM::SRemOp>(op, lhs, rhs);
2434 rewriter.replaceOpWithNewOp<mlir::LLVM::FRemOp>(op, lhs, rhs);
2437 case cir::BinOpKind::And:
2438 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(op, lhs, rhs);
2440 case cir::BinOpKind::Or:
2441 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(op, lhs, rhs);
2443 case cir::BinOpKind::Xor:
2444 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, lhs, rhs);
2446 case cir::BinOpKind::Max:
2447 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
2450 rewriter.replaceOpWithNewOp<mlir::LLVM::UMaxOp>(op, llvmTy, lhs, rhs);
2452 rewriter.replaceOpWithNewOp<mlir::LLVM::SMaxOp>(op, llvmTy, lhs, rhs);
2456 return mlir::LogicalResult::success();
2460static mlir::LLVM::ICmpPredicate
2462 using CIR = cir::CmpOpKind;
2463 using LLVMICmp = mlir::LLVM::ICmpPredicate;
2466 return LLVMICmp::eq;
2468 return LLVMICmp::ne;
2470 return (isSigned ? LLVMICmp::slt : LLVMICmp::ult);
2472 return (isSigned ? LLVMICmp::sle : LLVMICmp::ule);
2474 return (isSigned ? LLVMICmp::sgt : LLVMICmp::ugt);
2476 return (isSigned ? LLVMICmp::sge : LLVMICmp::uge);
2478 llvm_unreachable(
"Unknown CmpOpKind");
2483static mlir::LLVM::FCmpPredicate
2485 using CIR = cir::CmpOpKind;
2486 using LLVMFCmp = mlir::LLVM::FCmpPredicate;
2489 return LLVMFCmp::oeq;
2491 return LLVMFCmp::une;
2493 return LLVMFCmp::olt;
2495 return LLVMFCmp::ole;
2497 return LLVMFCmp::ogt;
2499 return LLVMFCmp::oge;
2501 llvm_unreachable(
"Unknown CmpOpKind");
2504mlir::LogicalResult CIRToLLVMCmpOpLowering::matchAndRewrite(
2505 cir::CmpOp cmpOp, OpAdaptor adaptor,
2506 mlir::ConversionPatternRewriter &rewriter)
const {
2507 mlir::Type type = cmpOp.getLhs().getType();
2512 if (mlir::isa<cir::IntType, mlir::IntegerType>(type)) {
2513 bool isSigned = mlir::isa<cir::IntType>(type)
2514 ? mlir::cast<cir::IntType>(type).isSigned()
2515 : mlir::cast<mlir::IntegerType>(type).isSigned();
2516 mlir::LLVM::ICmpPredicate kind =
2518 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
2519 cmpOp, kind, adaptor.getLhs(), adaptor.getRhs());
2520 return mlir::success();
2523 if (
auto ptrTy = mlir::dyn_cast<cir::PointerType>(type)) {
2524 mlir::LLVM::ICmpPredicate kind =
2527 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
2528 cmpOp, kind, adaptor.getLhs(), adaptor.getRhs());
2529 return mlir::success();
2532 if (
auto vptrTy = mlir::dyn_cast<cir::VPtrType>(type)) {
2536 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
2537 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
2538 return mlir::success();
2541 if (mlir::isa<cir::FPTypeInterface>(type)) {
2542 mlir::LLVM::FCmpPredicate
kind =
2544 rewriter.replaceOpWithNewOp<mlir::LLVM::FCmpOp>(
2545 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
2546 return mlir::success();
2549 if (mlir::isa<cir::ComplexType>(type)) {
2550 mlir::Value lhs = adaptor.getLhs();
2551 mlir::Value rhs = adaptor.getRhs();
2552 mlir::Location loc = cmpOp.getLoc();
2554 auto complexType = mlir::cast<cir::ComplexType>(cmpOp.getLhs().getType());
2555 mlir::Type complexElemTy =
2556 getTypeConverter()->convertType(
complexType.getElementType());
2558 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
2559 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{0}));
2560 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
2561 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{1}));
2562 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
2563 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{0}));
2564 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
2565 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{1}));
2567 if (cmpOp.getKind() == cir::CmpOpKind::eq) {
2568 if (complexElemTy.isInteger()) {
2569 auto realCmp = mlir::LLVM::ICmpOp::create(
2570 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, lhsReal, rhsReal);
2571 auto imagCmp = mlir::LLVM::ICmpOp::create(
2572 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, lhsImag, rhsImag);
2573 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, imagCmp);
2574 return mlir::success();
2577 auto realCmp = mlir::LLVM::FCmpOp::create(
2578 rewriter, loc, mlir::LLVM::FCmpPredicate::oeq, lhsReal, rhsReal);
2579 auto imagCmp = mlir::LLVM::FCmpOp::create(
2580 rewriter, loc, mlir::LLVM::FCmpPredicate::oeq, lhsImag, rhsImag);
2581 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, imagCmp);
2582 return mlir::success();
2585 if (cmpOp.getKind() == cir::CmpOpKind::ne) {
2586 if (complexElemTy.isInteger()) {
2587 auto realCmp = mlir::LLVM::ICmpOp::create(
2588 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, lhsReal, rhsReal);
2589 auto imagCmp = mlir::LLVM::ICmpOp::create(
2590 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, lhsImag, rhsImag);
2591 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp);
2592 return mlir::success();
2595 auto realCmp = mlir::LLVM::FCmpOp::create(
2596 rewriter, loc, mlir::LLVM::FCmpPredicate::une, lhsReal, rhsReal);
2597 auto imagCmp = mlir::LLVM::FCmpOp::create(
2598 rewriter, loc, mlir::LLVM::FCmpPredicate::une, lhsImag, rhsImag);
2599 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp);
2600 return mlir::success();
2604 return cmpOp.emitError() <<
"unsupported type for CmpOp: " <<
type;
2607mlir::LogicalResult CIRToLLVMBinOpOverflowOpLowering::matchAndRewrite(
2608 cir::BinOpOverflowOp op, OpAdaptor adaptor,
2609 mlir::ConversionPatternRewriter &rewriter)
const {
2610 mlir::Location loc = op.getLoc();
2611 cir::BinOpOverflowKind arithKind = op.getKind();
2612 cir::IntType operandTy = op.getLhs().getType();
2613 cir::IntType resultTy = op.getResult().getType();
2615 EncompassedTypeInfo encompassedTyInfo =
2616 computeEncompassedTypeWidth(operandTy, resultTy);
2617 mlir::IntegerType encompassedLLVMTy =
2618 rewriter.getIntegerType(encompassedTyInfo.width);
2620 mlir::Value lhs = adaptor.getLhs();
2621 mlir::Value rhs = adaptor.getRhs();
2622 if (operandTy.getWidth() < encompassedTyInfo.width) {
2623 if (operandTy.isSigned()) {
2624 lhs = mlir::LLVM::SExtOp::create(rewriter, loc, encompassedLLVMTy, lhs);
2625 rhs = mlir::LLVM::SExtOp::create(rewriter, loc, encompassedLLVMTy, rhs);
2627 lhs = mlir::LLVM::ZExtOp::create(rewriter, loc, encompassedLLVMTy, lhs);
2628 rhs = mlir::LLVM::ZExtOp::create(rewriter, loc, encompassedLLVMTy, rhs);
2632 std::string intrinName = getLLVMIntrinName(arithKind, encompassedTyInfo.sign,
2633 encompassedTyInfo.width);
2634 auto intrinNameAttr = mlir::StringAttr::get(op.getContext(), intrinName);
2636 mlir::IntegerType overflowLLVMTy = rewriter.getI1Type();
2637 auto intrinRetTy = mlir::LLVM::LLVMStructType::getLiteral(
2638 rewriter.getContext(), {encompassedLLVMTy, overflowLLVMTy});
2640 auto callLLVMIntrinOp = mlir::LLVM::CallIntrinsicOp::create(
2641 rewriter, loc, intrinRetTy, intrinNameAttr, mlir::ValueRange{lhs, rhs});
2642 mlir::Value intrinRet = callLLVMIntrinOp.getResult(0);
2644 mlir::Value result = mlir::LLVM::ExtractValueOp::create(
2645 rewriter, loc, intrinRet, ArrayRef<int64_t>{0})
2647 mlir::Value overflow = mlir::LLVM::ExtractValueOp::create(
2648 rewriter, loc, intrinRet, ArrayRef<int64_t>{1})
2651 if (resultTy.getWidth() < encompassedTyInfo.width) {
2652 mlir::Type resultLLVMTy = getTypeConverter()->convertType(resultTy);
2654 mlir::LLVM::TruncOp::create(rewriter, loc, resultLLVMTy, result);
2658 mlir::Value truncResultExt;
2659 if (resultTy.isSigned())
2660 truncResultExt = mlir::LLVM::SExtOp::create(
2661 rewriter, loc, encompassedLLVMTy, truncResult);
2663 truncResultExt = mlir::LLVM::ZExtOp::create(
2664 rewriter, loc, encompassedLLVMTy, truncResult);
2665 auto truncOverflow = mlir::LLVM::ICmpOp::create(
2666 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, truncResultExt, result);
2668 result = truncResult;
2669 overflow = mlir::LLVM::OrOp::create(rewriter, loc, overflow, truncOverflow);
2672 mlir::Type boolLLVMTy =
2673 getTypeConverter()->convertType(op.getOverflow().getType());
2674 if (boolLLVMTy != rewriter.getI1Type())
2675 overflow = mlir::LLVM::ZExtOp::create(rewriter, loc, boolLLVMTy, overflow);
2677 rewriter.replaceOp(op, mlir::ValueRange{result, overflow});
2679 return mlir::success();
2682std::string CIRToLLVMBinOpOverflowOpLowering::getLLVMIntrinName(
2683 cir::BinOpOverflowKind opKind,
bool isSigned,
unsigned width) {
2686 std::string
name =
"llvm.";
2689 name.push_back(
's');
2691 name.push_back(
'u');
2694 case cir::BinOpOverflowKind::Add:
2695 name.append(
"add.");
2697 case cir::BinOpOverflowKind::Sub:
2698 name.append(
"sub.");
2700 case cir::BinOpOverflowKind::Mul:
2701 name.append(
"mul.");
2705 name.append(
"with.overflow.i");
2706 name.append(std::to_string(width));
2711CIRToLLVMBinOpOverflowOpLowering::EncompassedTypeInfo
2712CIRToLLVMBinOpOverflowOpLowering::computeEncompassedTypeWidth(
2713 cir::IntType operandTy, cir::IntType resultTy) {
2714 bool sign = operandTy.getIsSigned() || resultTy.getIsSigned();
2716 std::max(operandTy.getWidth() + (
sign && operandTy.isUnsigned()),
2717 resultTy.getWidth() + (
sign && resultTy.isUnsigned()));
2718 return {
sign, width};
2721mlir::LogicalResult CIRToLLVMShiftOpLowering::matchAndRewrite(
2722 cir::ShiftOp op, OpAdaptor adaptor,
2723 mlir::ConversionPatternRewriter &rewriter)
const {
2724 assert((op.getValue().getType() == op.getType()) &&
2725 "inconsistent operands' types NYI");
2727 const mlir::Type llvmTy = getTypeConverter()->convertType(op.getType());
2728 mlir::Value amt = adaptor.getAmount();
2729 mlir::Value val = adaptor.getValue();
2731 auto cirAmtTy = mlir::dyn_cast<cir::IntType>(op.getAmount().getType());
2734 auto cirValTy = mlir::cast<cir::IntType>(op.getValue().getType());
2742 amt =
getLLVMIntCast(rewriter, amt, llvmTy,
true, cirAmtTy.getWidth(),
2743 cirValTy.getWidth());
2745 auto cirValVTy = mlir::cast<cir::VectorType>(op.getValue().getType());
2747 mlir::cast<cir::IntType>(cirValVTy.getElementType()).isUnsigned();
2751 if (op.getIsShiftleft()) {
2752 rewriter.replaceOpWithNewOp<mlir::LLVM::ShlOp>(op, llvmTy, val, amt);
2753 return mlir::success();
2757 rewriter.replaceOpWithNewOp<mlir::LLVM::LShrOp>(op, llvmTy, val, amt);
2759 rewriter.replaceOpWithNewOp<mlir::LLVM::AShrOp>(op, llvmTy, val, amt);
2760 return mlir::success();
2763mlir::LogicalResult CIRToLLVMSelectOpLowering::matchAndRewrite(
2764 cir::SelectOp op, OpAdaptor adaptor,
2765 mlir::ConversionPatternRewriter &rewriter)
const {
2766 auto getConstantBool = [](mlir::Value value) -> cir::BoolAttr {
2767 auto definingOp = value.getDefiningOp<cir::ConstantOp>();
2771 auto constValue = definingOp.getValueAttr<cir::BoolAttr>();
2781 if (mlir::isa<cir::BoolType>(op.getTrueValue().getType())) {
2782 cir::BoolAttr trueValue = getConstantBool(op.getTrueValue());
2783 cir::BoolAttr falseValue = getConstantBool(op.getFalseValue());
2784 if (falseValue && !falseValue.getValue()) {
2786 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(op, adaptor.getCondition(),
2787 adaptor.getTrueValue());
2788 return mlir::success();
2790 if (trueValue && trueValue.getValue()) {
2792 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(op, adaptor.getCondition(),
2793 adaptor.getFalseValue());
2794 return mlir::success();
2798 mlir::Value llvmCondition = adaptor.getCondition();
2799 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(
2800 op, llvmCondition, adaptor.getTrueValue(), adaptor.getFalseValue());
2802 return mlir::success();
2806 mlir::DataLayout &dataLayout) {
2807 converter.addConversion([&](cir::PointerType type) -> mlir::Type {
2808 unsigned addrSpace =
2809 type.getAddrSpace() ? type.getAddrSpace().getValue().getUInt() : 0;
2810 return mlir::LLVM::LLVMPointerType::get(type.getContext(), addrSpace);
2812 converter.addConversion([&](cir::VPtrType type) -> mlir::Type {
2814 return mlir::LLVM::LLVMPointerType::get(type.getContext());
2816 converter.addConversion([&](cir::ArrayType type) -> mlir::Type {
2819 return mlir::LLVM::LLVMArrayType::get(ty, type.getSize());
2821 converter.addConversion([&](cir::VectorType type) -> mlir::Type {
2822 const mlir::Type ty = converter.convertType(type.getElementType());
2823 return mlir::VectorType::get(type.getSize(), ty);
2825 converter.addConversion([&](cir::BoolType type) -> mlir::Type {
2826 return mlir::IntegerType::get(type.getContext(), 1,
2827 mlir::IntegerType::Signless);
2829 converter.addConversion([&](cir::IntType type) -> mlir::Type {
2831 return mlir::IntegerType::get(type.getContext(), type.getWidth());
2833 converter.addConversion([&](cir::SingleType type) -> mlir::Type {
2834 return mlir::Float32Type::get(type.getContext());
2836 converter.addConversion([&](cir::DoubleType type) -> mlir::Type {
2837 return mlir::Float64Type::get(type.getContext());
2839 converter.addConversion([&](cir::FP80Type type) -> mlir::Type {
2840 return mlir::Float80Type::get(type.getContext());
2842 converter.addConversion([&](cir::FP128Type type) -> mlir::Type {
2843 return mlir::Float128Type::get(type.getContext());
2845 converter.addConversion([&](cir::LongDoubleType type) -> mlir::Type {
2846 return converter.convertType(type.getUnderlying());
2848 converter.addConversion([&](cir::FP16Type type) -> mlir::Type {
2849 return mlir::Float16Type::get(type.getContext());
2851 converter.addConversion([&](cir::BF16Type type) -> mlir::Type {
2852 return mlir::BFloat16Type::get(type.getContext());
2854 converter.addConversion([&](cir::ComplexType type) -> mlir::Type {
2857 mlir::Type elementTy = converter.convertType(type.getElementType());
2858 mlir::Type structFields[2] = {elementTy, elementTy};
2859 return mlir::LLVM::LLVMStructType::getLiteral(type.getContext(),
2862 converter.addConversion([&](cir::FuncType type) -> std::optional<mlir::Type> {
2863 auto result = converter.convertType(type.getReturnType());
2865 arguments.reserve(type.getNumInputs());
2866 if (converter.convertTypes(type.getInputs(), arguments).failed())
2867 return std::nullopt;
2868 auto varArg = type.isVarArg();
2869 return mlir::LLVM::LLVMFunctionType::get(result, arguments, varArg);
2871 converter.addConversion([&](cir::RecordType type) -> mlir::Type {
2874 switch (type.getKind()) {
2875 case cir::RecordType::Class:
2876 case cir::RecordType::Struct:
2877 for (mlir::Type ty : type.getMembers())
2881 case cir::RecordType::Union:
2882 if (
auto largestMember = type.getLargestMember(dataLayout))
2883 llvmMembers.push_back(
2885 if (type.getPadded()) {
2886 auto last = *type.getMembers().rbegin();
2887 llvmMembers.push_back(
2894 mlir::LLVM::LLVMStructType llvmStruct;
2895 if (type.getName()) {
2896 llvmStruct = mlir::LLVM::LLVMStructType::getIdentified(
2897 type.getContext(), type.getPrefixedName());
2898 if (llvmStruct.setBody(llvmMembers, type.getPacked()).failed())
2899 llvm_unreachable(
"Failed to set body of record");
2901 llvmStruct = mlir::LLVM::LLVMStructType::getLiteral(
2902 type.getContext(), llvmMembers, type.getPacked());
2907 converter.addConversion([&](cir::VoidType type) -> mlir::Type {
2908 return mlir::LLVM::LLVMVoidType::get(type.getContext());
2913 mlir::ModuleOp module, StringRef globalXtorName, StringRef llvmXtorName,
2914 llvm::function_ref<std::pair<StringRef, int>(mlir::Attribute)> createXtor) {
2916 for (
const mlir::NamedAttribute namedAttr : module->getAttrs()) {
2917 if (namedAttr.getName() == globalXtorName) {
2918 for (
auto attr : mlir::cast<mlir::ArrayAttr>(namedAttr.getValue()))
2919 globalXtors.emplace_back(createXtor(attr));
2924 if (globalXtors.empty())
2927 mlir::OpBuilder builder(module.getContext());
2928 builder.setInsertionPointToEnd(&module.getBodyRegion().back());
2932 auto ctorPFTy = mlir::LLVM::LLVMPointerType::get(builder.getContext());
2934 ctorStructFields.push_back(builder.getI32Type());
2935 ctorStructFields.push_back(ctorPFTy);
2936 ctorStructFields.push_back(ctorPFTy);
2938 auto ctorStructTy = mlir::LLVM::LLVMStructType::getLiteral(
2939 builder.getContext(), ctorStructFields);
2940 auto ctorStructArrayTy =
2941 mlir::LLVM::LLVMArrayType::get(ctorStructTy, globalXtors.size());
2943 mlir::Location loc =
module.getLoc();
2944 auto newGlobalOp = mlir::LLVM::GlobalOp::create(
2945 builder, loc, ctorStructArrayTy,
false,
2946 mlir::LLVM::Linkage::Appending, llvmXtorName, mlir::Attribute());
2948 builder.createBlock(&newGlobalOp.getRegion());
2949 builder.setInsertionPointToEnd(newGlobalOp.getInitializerBlock());
2951 mlir::Value result =
2952 mlir::LLVM::UndefOp::create(builder, loc, ctorStructArrayTy);
2954 for (
auto [index, fn] : llvm::enumerate(globalXtors)) {
2955 mlir::Value structInit =
2956 mlir::LLVM::UndefOp::create(builder, loc, ctorStructTy);
2957 mlir::Value initPriority = mlir::LLVM::ConstantOp::create(
2958 builder, loc, ctorStructFields[0], fn.second);
2959 mlir::Value initFuncAddr = mlir::LLVM::AddressOfOp::create(
2960 builder, loc, ctorStructFields[1], fn.first);
2961 mlir::Value initAssociate =
2962 mlir::LLVM::ZeroOp::create(builder, loc, ctorStructFields[2]);
2965 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
2966 initPriority, zero);
2967 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
2970 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
2972 result = mlir::LLVM::InsertValueOp::create(builder, loc, result, structInit,
2976 mlir::LLVM::ReturnOp::create(builder, loc, result);
3014 parent->walk([&](mlir::Block *blk) {
3015 if (blk->hasNoPredecessors() && !blk->isEntryBlock())
3016 unreachableBlocks.push_back(blk);
3019 std::set<mlir::Block *> visited;
3020 for (mlir::Block *root : unreachableBlocks) {
3023 std::deque<mlir::Block *> workList;
3024 workList.push_back(root);
3026 while (!workList.empty()) {
3027 mlir::Block *blk = workList.back();
3028 workList.pop_back();
3029 if (visited.count(blk))
3031 visited.emplace(blk);
3033 for (mlir::Operation &op : *blk)
3036 for (mlir::Block *succ : blk->getSuccessors())
3037 workList.push_back(succ);
3042mlir::LogicalResult CIRToLLVMObjSizeOpLowering::matchAndRewrite(
3043 cir::ObjSizeOp op, OpAdaptor adaptor,
3044 mlir::ConversionPatternRewriter &rewriter)
const {
3045 mlir::Type llvmResTy = getTypeConverter()->convertType(op.getType());
3046 mlir::Location loc = op->getLoc();
3048 mlir::IntegerType i1Ty = rewriter.getI1Type();
3050 auto i1Val = [&rewriter, &loc, &i1Ty](
bool val) {
3051 return mlir::LLVM::ConstantOp::create(rewriter, loc, i1Ty, val);
3058 i1Val(op.getNullunknown()),
3059 i1Val(op.getDynamic()),
3062 return mlir::LogicalResult::success();
3067 if (mlir::Attribute tripleAttr =
3068 module->getAttr(cir::CIRDialect::getTripleAttrName()))
3069 module->setAttr(mlir::LLVM::LLVMDialect::getTargetTripleAttrName(),
3072 if (mlir::Attribute asmAttr =
3073 module->getAttr(cir::CIRDialect::getModuleLevelAsmAttrName()))
3074 module->setAttr(mlir::LLVM::LLVMDialect::getModuleLevelAsmAttrName(),
3079 llvm::TimeTraceScope scope(
"Convert CIR to LLVM Pass");
3081 mlir::ModuleOp module = getOperation();
3082 mlir::DataLayout dl(module);
3083 mlir::LLVMTypeConverter converter(&getContext());
3086 mlir::RewritePatternSet patterns(&getContext());
3089#define GET_LLVM_LOWERING_PATTERNS_LIST
3090#include "clang/CIR/Dialect/IR/CIRLowering.inc"
3091#undef GET_LLVM_LOWERING_PATTERNS_LIST
3092 >(converter, patterns.getContext(), dl);
3096 mlir::ConversionTarget target(getContext());
3097 target.addLegalOp<mlir::ModuleOp>();
3098 target.addLegalDialect<mlir::LLVM::LLVMDialect>();
3099 target.addIllegalDialect<mlir::BuiltinDialect, cir::CIRDialect,
3100 mlir::func::FuncDialect>();
3103 ops.push_back(module);
3106 if (failed(applyPartialConversion(ops, target, std::move(patterns))))
3107 signalPassFailure();
3111 "llvm.global_ctors", [](mlir::Attribute attr) {
3112 auto ctorAttr = mlir::cast<cir::GlobalCtorAttr>(attr);
3113 return std::make_pair(ctorAttr.getName(),
3114 ctorAttr.getPriority());
3118 "llvm.global_dtors", [](mlir::Attribute attr) {
3119 auto dtorAttr = mlir::cast<cir::GlobalDtorAttr>(attr);
3120 return std::make_pair(dtorAttr.getName(),
3121 dtorAttr.getPriority());
3125mlir::LogicalResult CIRToLLVMBrOpLowering::matchAndRewrite(
3126 cir::BrOp op, OpAdaptor adaptor,
3127 mlir::ConversionPatternRewriter &rewriter)
const {
3128 rewriter.replaceOpWithNewOp<mlir::LLVM::BrOp>(op, adaptor.getOperands(),
3130 return mlir::LogicalResult::success();
3133mlir::LogicalResult CIRToLLVMGetMemberOpLowering::matchAndRewrite(
3134 cir::GetMemberOp op, OpAdaptor adaptor,
3135 mlir::ConversionPatternRewriter &rewriter)
const {
3136 mlir::Type llResTy = getTypeConverter()->convertType(op.getType());
3137 const auto recordTy =
3138 mlir::cast<cir::RecordType>(op.getAddrTy().getPointee());
3139 assert(recordTy &&
"expected record type");
3141 switch (recordTy.getKind()) {
3142 case cir::RecordType::Class:
3143 case cir::RecordType::Struct: {
3147 const mlir::Type elementTy = getTypeConverter()->convertType(recordTy);
3148 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, llResTy, elementTy,
3149 adaptor.getAddr(), offset);
3150 return mlir::success();
3152 case cir::RecordType::Union:
3155 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(op, llResTy,
3157 return mlir::success();
3161mlir::LogicalResult CIRToLLVMUnreachableOpLowering::matchAndRewrite(
3162 cir::UnreachableOp op, OpAdaptor adaptor,
3163 mlir::ConversionPatternRewriter &rewriter)
const {
3164 rewriter.replaceOpWithNewOp<mlir::LLVM::UnreachableOp>(op);
3165 return mlir::success();
3169 mlir::Operation *srcOp, llvm::StringRef fnName,
3171 auto modOp = srcOp->getParentOfType<mlir::ModuleOp>();
3172 auto enclosingFnOp = srcOp->getParentOfType<mlir::LLVM::LLVMFuncOp>();
3173 mlir::Operation *sourceSymbol =
3174 mlir::SymbolTable::lookupSymbolIn(modOp, fnName);
3175 if (!sourceSymbol) {
3176 mlir::OpBuilder::InsertionGuard guard(rewriter);
3177 rewriter.setInsertionPoint(enclosingFnOp);
3178 mlir::LLVM::LLVMFuncOp::create(rewriter, srcOp->getLoc(), fnName, fnTy);
3182mlir::LogicalResult CIRToLLVMThrowOpLowering::matchAndRewrite(
3183 cir::ThrowOp op, OpAdaptor adaptor,
3184 mlir::ConversionPatternRewriter &rewriter)
const {
3185 mlir::Location loc = op.getLoc();
3186 auto voidTy = mlir::LLVM::LLVMVoidType::get(getContext());
3188 if (op.rethrows()) {
3189 auto funcTy = mlir::LLVM::LLVMFunctionType::get(voidTy, {});
3192 const llvm::StringRef functionName =
"__cxa_rethrow";
3195 auto cxaRethrow = mlir::LLVM::CallOp::create(
3196 rewriter, loc, mlir::TypeRange{}, functionName);
3198 rewriter.replaceOp(op, cxaRethrow);
3199 return mlir::success();
3202 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3203 auto fnTy = mlir::LLVM::LLVMFunctionType::get(
3204 voidTy, {llvmPtrTy, llvmPtrTy, llvmPtrTy});
3207 const llvm::StringRef fnName =
"__cxa_throw";
3210 mlir::Value typeInfo = mlir::LLVM::AddressOfOp::create(
3211 rewriter, loc, mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
3212 adaptor.getTypeInfoAttr());
3216 dtor = mlir::LLVM::AddressOfOp::create(rewriter, loc, llvmPtrTy,
3217 adaptor.getDtorAttr());
3219 dtor = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmPtrTy);
3222 auto cxaThrowCall = mlir::LLVM::CallOp::create(
3223 rewriter, loc, mlir::TypeRange{}, fnName,
3224 mlir::ValueRange{adaptor.getExceptionPtr(), typeInfo, dtor});
3226 rewriter.replaceOp(op, cxaThrowCall);
3227 return mlir::success();
3230mlir::LogicalResult CIRToLLVMAllocExceptionOpLowering::matchAndRewrite(
3231 cir::AllocExceptionOp op, OpAdaptor adaptor,
3232 mlir::ConversionPatternRewriter &rewriter)
const {
3234 StringRef fnName =
"__cxa_allocate_exception";
3235 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3236 auto int64Ty = mlir::IntegerType::get(rewriter.getContext(), 64);
3237 auto fnTy = mlir::LLVM::LLVMFunctionType::get(llvmPtrTy, {int64Ty});
3240 auto exceptionSize = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
3241 adaptor.getSizeAttr());
3243 auto allocaExceptionCall = mlir::LLVM::CallOp::create(
3244 rewriter, op.getLoc(), mlir::TypeRange{llvmPtrTy}, fnName,
3245 mlir::ValueRange{exceptionSize});
3247 rewriter.replaceOp(op, allocaExceptionCall);
3248 return mlir::success();
3251static mlir::LLVM::LLVMStructType
3254 mlir::MLIRContext *ctx = rewriter.getContext();
3255 auto llvmPtr = mlir::LLVM::LLVMPointerType::get(ctx);
3257 return mlir::LLVM::LLVMStructType::getLiteral(ctx, structFields);
3260mlir::LogicalResult CIRToLLVMEhInflightOpLowering::matchAndRewrite(
3261 cir::EhInflightOp op, OpAdaptor adaptor,
3262 mlir::ConversionPatternRewriter &rewriter)
const {
3263 auto llvmFn = op->getParentOfType<mlir::LLVM::LLVMFuncOp>();
3264 assert(llvmFn &&
"expected LLVM function parent");
3265 mlir::Block *entryBlock = &llvmFn.getRegion().front();
3266 assert(entryBlock->isEntryBlock());
3268 mlir::ArrayAttr catchListAttr = op.getCatchTypeListAttr();
3269 mlir::SmallVector<mlir::Value> catchSymAddrs;
3271 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3272 mlir::Location loc = op.getLoc();
3277 if (catchListAttr) {
3280 for (mlir::Attribute catchAttr : catchListAttr) {
3281 auto symAttr = cast<mlir::FlatSymbolRefAttr>(catchAttr);
3284 mlir::OpBuilder::InsertionGuard guard(rewriter);
3285 rewriter.setInsertionPointToStart(entryBlock);
3286 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
3287 rewriter, loc, llvmPtrTy, symAttr.getValue());
3288 catchSymAddrs.push_back(addrOp);
3290 }
else if (!op.getCleanup()) {
3294 mlir::OpBuilder::InsertionGuard guard(rewriter);
3295 rewriter.setInsertionPointToStart(entryBlock);
3296 mlir::Value nullOp = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmPtrTy);
3297 catchSymAddrs.push_back(nullOp);
3302 mlir::LLVM::LLVMStructType llvmLandingPadStructTy =
3304 auto landingPadOp = mlir::LLVM::LandingpadOp::create(
3305 rewriter, loc, llvmLandingPadStructTy, catchSymAddrs);
3307 if (op.getCleanup())
3308 landingPadOp.setCleanup(
true);
3311 mlir::LLVM::ExtractValueOp::create(rewriter, loc, landingPadOp, 0);
3312 mlir::Value selector =
3313 mlir::LLVM::ExtractValueOp::create(rewriter, loc, landingPadOp, 1);
3314 rewriter.replaceOp(op, mlir::ValueRange{slot, selector});
3321 mlir::OpBuilder::InsertionGuard guard(rewriter);
3323 rewriter.setInsertionPoint(llvmFn);
3324 auto personalityFnTy =
3325 mlir::LLVM::LLVMFunctionType::get(rewriter.getI32Type(), {},
3328 const StringRef fnName =
"__gxx_personality_v0";
3330 llvmFn.setPersonality(fnName);
3332 return mlir::success();
3335mlir::LogicalResult CIRToLLVMTrapOpLowering::matchAndRewrite(
3336 cir::TrapOp op, OpAdaptor adaptor,
3337 mlir::ConversionPatternRewriter &rewriter)
const {
3338 mlir::Location loc = op->getLoc();
3339 rewriter.eraseOp(op);
3341 mlir::LLVM::Trap::create(rewriter, loc);
3346 mlir::LLVM::UnreachableOp::create(rewriter, loc);
3348 return mlir::success();
3353 mlir::ConversionPatternRewriter &rewriter,
3354 const mlir::TypeConverter *converter,
3355 mlir::FlatSymbolRefAttr nameAttr, mlir::Type &eltType) {
3356 auto module = op->getParentOfType<mlir::ModuleOp>();
3357 mlir::Operation *symbol = mlir::SymbolTable::lookupSymbolIn(module, nameAttr);
3358 if (
auto llvmSymbol = mlir::dyn_cast<mlir::LLVM::GlobalOp>(symbol)) {
3359 eltType = llvmSymbol.getType();
3360 }
else if (
auto cirSymbol = mlir::dyn_cast<cir::GlobalOp>(symbol)) {
3361 eltType = converter->convertType(cirSymbol.getSymType());
3363 op->emitError() <<
"unexpected symbol type for " << symbol;
3367 return mlir::LLVM::AddressOfOp::create(
3368 rewriter, op->getLoc(),
3369 mlir::LLVM::LLVMPointerType::get(op->getContext()), nameAttr.getValue());
3372mlir::LogicalResult CIRToLLVMVTableAddrPointOpLowering::matchAndRewrite(
3373 cir::VTableAddrPointOp op, OpAdaptor adaptor,
3374 mlir::ConversionPatternRewriter &rewriter)
const {
3375 const mlir::TypeConverter *converter = getTypeConverter();
3376 mlir::Type targetType = converter->convertType(op.getType());
3380 op.getNameAttr(), eltType);
3382 return op.emitError() <<
"Unable to get value for vtable symbol";
3385 0, op.getAddressPointAttr().getIndex(),
3386 op.getAddressPointAttr().getOffset()};
3388 assert(eltType &&
"Shouldn't ever be missing an eltType here");
3389 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
3390 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
3391 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, targetType, eltType,
3392 symAddr, offsets, inboundsNuw);
3393 return mlir::success();
3396mlir::LogicalResult CIRToLLVMVTableGetVPtrOpLowering::matchAndRewrite(
3397 cir::VTableGetVPtrOp op, OpAdaptor adaptor,
3398 mlir::ConversionPatternRewriter &rewriter)
const {
3402 mlir::Value srcVal = adaptor.getSrc();
3403 rewriter.replaceOp(op, srcVal);
3404 return mlir::success();
3407mlir::LogicalResult CIRToLLVMVTableGetVirtualFnAddrOpLowering::matchAndRewrite(
3408 cir::VTableGetVirtualFnAddrOp op, OpAdaptor adaptor,
3409 mlir::ConversionPatternRewriter &rewriter)
const {
3410 mlir::Type targetType = getTypeConverter()->convertType(op.getType());
3411 auto eltType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3412 llvm::SmallVector<mlir::LLVM::GEPArg> offsets =
3413 llvm::SmallVector<mlir::LLVM::GEPArg>{op.getIndex()};
3414 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
3415 op, targetType, eltType, adaptor.getVptr(), offsets,
3416 mlir::LLVM::GEPNoWrapFlags::inbounds);
3417 return mlir::success();
3420mlir::LogicalResult CIRToLLVMVTTAddrPointOpLowering::matchAndRewrite(
3421 cir::VTTAddrPointOp op, OpAdaptor adaptor,
3422 mlir::ConversionPatternRewriter &rewriter)
const {
3423 const mlir::Type resultType = getTypeConverter()->convertType(op.getType());
3424 llvm::SmallVector<mlir::LLVM::GEPArg> offsets;
3426 mlir::Value llvmAddr = adaptor.getSymAddr();
3428 if (op.getSymAddr()) {
3429 if (op.getOffset() == 0) {
3430 rewriter.replaceOp(op, {llvmAddr});
3431 return mlir::success();
3434 offsets.push_back(adaptor.getOffset());
3435 eltType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3438 op.getNameAttr(), eltType);
3439 assert(eltType &&
"Shouldn't ever be missing an eltType here");
3440 offsets.push_back(0);
3441 offsets.push_back(adaptor.getOffset());
3443 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
3444 op, resultType, eltType, llvmAddr, offsets,
3445 mlir::LLVM::GEPNoWrapFlags::inbounds);
3446 return mlir::success();
3449mlir::LogicalResult CIRToLLVMStackSaveOpLowering::matchAndRewrite(
3450 cir::StackSaveOp op, OpAdaptor adaptor,
3451 mlir::ConversionPatternRewriter &rewriter)
const {
3452 const mlir::Type ptrTy = getTypeConverter()->convertType(op.getType());
3453 rewriter.replaceOpWithNewOp<mlir::LLVM::StackSaveOp>(op, ptrTy);
3454 return mlir::success();
3457mlir::LogicalResult CIRToLLVMStackRestoreOpLowering::matchAndRewrite(
3458 cir::StackRestoreOp op, OpAdaptor adaptor,
3459 mlir::ConversionPatternRewriter &rewriter)
const {
3460 rewriter.replaceOpWithNewOp<mlir::LLVM::StackRestoreOp>(op, adaptor.getPtr());
3461 return mlir::success();
3464mlir::LogicalResult CIRToLLVMVecCreateOpLowering::matchAndRewrite(
3465 cir::VecCreateOp op, OpAdaptor adaptor,
3466 mlir::ConversionPatternRewriter &rewriter)
const {
3469 const auto vecTy = mlir::cast<cir::VectorType>(op.getType());
3470 const mlir::Type llvmTy = typeConverter->convertType(vecTy);
3471 const mlir::Location loc = op.getLoc();
3472 mlir::Value result = mlir::LLVM::PoisonOp::create(rewriter, loc, llvmTy);
3473 assert(vecTy.getSize() == op.getElements().size() &&
3474 "cir.vec.create op count doesn't match vector type elements count");
3476 for (uint64_t i = 0; i < vecTy.getSize(); ++i) {
3477 const mlir::Value indexValue =
3478 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
3479 result = mlir::LLVM::InsertElementOp::create(
3480 rewriter, loc, result, adaptor.getElements()[i], indexValue);
3483 rewriter.replaceOp(op, result);
3484 return mlir::success();
3487mlir::LogicalResult CIRToLLVMVecExtractOpLowering::matchAndRewrite(
3488 cir::VecExtractOp op, OpAdaptor adaptor,
3489 mlir::ConversionPatternRewriter &rewriter)
const {
3490 rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractElementOp>(
3491 op, adaptor.getVec(), adaptor.getIndex());
3492 return mlir::success();
3495mlir::LogicalResult CIRToLLVMVecInsertOpLowering::matchAndRewrite(
3496 cir::VecInsertOp op, OpAdaptor adaptor,
3497 mlir::ConversionPatternRewriter &rewriter)
const {
3498 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertElementOp>(
3499 op, adaptor.getVec(), adaptor.getValue(), adaptor.getIndex());
3500 return mlir::success();
3503mlir::LogicalResult CIRToLLVMVecCmpOpLowering::matchAndRewrite(
3504 cir::VecCmpOp op, OpAdaptor adaptor,
3505 mlir::ConversionPatternRewriter &rewriter)
const {
3506 mlir::Type elementType = elementTypeIfVector(op.getLhs().getType());
3507 mlir::Value bitResult;
3508 if (
auto intType = mlir::dyn_cast<cir::IntType>(elementType)) {
3509 bitResult = mlir::LLVM::ICmpOp::create(
3510 rewriter, op.getLoc(),
3512 adaptor.getLhs(), adaptor.getRhs());
3513 }
else if (mlir::isa<cir::FPTypeInterface>(elementType)) {
3514 bitResult = mlir::LLVM::FCmpOp::create(
3516 adaptor.getLhs(), adaptor.getRhs());
3518 return op.emitError() <<
"unsupported type for VecCmpOp: " << elementType;
3523 rewriter.replaceOpWithNewOp<mlir::LLVM::SExtOp>(
3524 op, typeConverter->convertType(op.getType()), bitResult);
3525 return mlir::success();
3528mlir::LogicalResult CIRToLLVMVecSplatOpLowering::matchAndRewrite(
3529 cir::VecSplatOp op, OpAdaptor adaptor,
3530 mlir::ConversionPatternRewriter &rewriter)
const {
3536 cir::VectorType vecTy = op.getType();
3537 mlir::Type llvmTy = typeConverter->convertType(vecTy);
3538 mlir::Location loc = op.getLoc();
3539 mlir::Value poison = mlir::LLVM::PoisonOp::create(rewriter, loc, llvmTy);
3541 mlir::Value elementValue = adaptor.getValue();
3542 if (elementValue.getDefiningOp<mlir::LLVM::PoisonOp>()) {
3545 rewriter.replaceOp(op, poison);
3546 return mlir::success();
3549 if (
auto constValue = elementValue.getDefiningOp<mlir::LLVM::ConstantOp>()) {
3550 if (
auto intAttr = dyn_cast<mlir::IntegerAttr>(constValue.getValue())) {
3551 mlir::DenseIntElementsAttr denseVec = mlir::DenseIntElementsAttr::get(
3552 mlir::cast<mlir::ShapedType>(llvmTy), intAttr.getValue());
3553 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
3554 op, denseVec.getType(), denseVec);
3555 return mlir::success();
3558 if (
auto fpAttr = dyn_cast<mlir::FloatAttr>(constValue.getValue())) {
3559 mlir::DenseFPElementsAttr denseVec = mlir::DenseFPElementsAttr::get(
3560 mlir::cast<mlir::ShapedType>(llvmTy), fpAttr.getValue());
3561 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
3562 op, denseVec.getType(), denseVec);
3563 return mlir::success();
3567 mlir::Value indexValue =
3568 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), 0);
3569 mlir::Value oneElement = mlir::LLVM::InsertElementOp::create(
3570 rewriter, loc, poison, elementValue, indexValue);
3571 SmallVector<int32_t> zeroValues(vecTy.getSize(), 0);
3572 rewriter.replaceOpWithNewOp<mlir::LLVM::ShuffleVectorOp>(op, oneElement,
3573 poison, zeroValues);
3574 return mlir::success();
3577mlir::LogicalResult CIRToLLVMVecShuffleOpLowering::matchAndRewrite(
3578 cir::VecShuffleOp op, OpAdaptor adaptor,
3579 mlir::ConversionPatternRewriter &rewriter)
const {
3583 SmallVector<int, 8> indices;
3585 op.getIndices().begin(), op.getIndices().end(),
3586 std::back_inserter(indices), [](mlir::Attribute intAttr) {
3587 return mlir::cast<cir::IntAttr>(intAttr).getValue().getSExtValue();
3589 rewriter.replaceOpWithNewOp<mlir::LLVM::ShuffleVectorOp>(
3590 op, adaptor.getVec1(), adaptor.getVec2(), indices);
3591 return mlir::success();
3594mlir::LogicalResult CIRToLLVMVecShuffleDynamicOpLowering::matchAndRewrite(
3595 cir::VecShuffleDynamicOp op, OpAdaptor adaptor,
3596 mlir::ConversionPatternRewriter &rewriter)
const {
3608 mlir::Location loc = op.getLoc();
3609 mlir::Value input = adaptor.getVec();
3610 mlir::Type llvmIndexVecType =
3611 getTypeConverter()->convertType(op.getIndices().getType());
3612 mlir::Type llvmIndexType = getTypeConverter()->convertType(
3613 elementTypeIfVector(op.getIndices().getType()));
3615 mlir::cast<cir::VectorType>(op.getVec().getType()).getSize();
3617 uint64_t maskBits = llvm::NextPowerOf2(numElements - 1) - 1;
3618 mlir::Value maskValue = mlir::LLVM::ConstantOp::create(
3619 rewriter, loc, llvmIndexType,
3620 rewriter.getIntegerAttr(llvmIndexType, maskBits));
3621 mlir::Value maskVector =
3622 mlir::LLVM::UndefOp::create(rewriter, loc, llvmIndexVecType);
3624 for (uint64_t i = 0; i < numElements; ++i) {
3625 mlir::Value idxValue =
3626 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
3627 maskVector = mlir::LLVM::InsertElementOp::create(rewriter, loc, maskVector,
3628 maskValue, idxValue);
3631 mlir::Value maskedIndices = mlir::LLVM::AndOp::create(
3632 rewriter, loc, llvmIndexVecType, adaptor.getIndices(), maskVector);
3633 mlir::Value result = mlir::LLVM::UndefOp::create(
3634 rewriter, loc, getTypeConverter()->convertType(op.getVec().getType()));
3635 for (uint64_t i = 0; i < numElements; ++i) {
3636 mlir::Value iValue =
3637 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
3638 mlir::Value indexValue = mlir::LLVM::ExtractElementOp::create(
3639 rewriter, loc, maskedIndices, iValue);
3640 mlir::Value valueAtIndex =
3641 mlir::LLVM::ExtractElementOp::create(rewriter, loc, input, indexValue);
3642 result = mlir::LLVM::InsertElementOp::create(rewriter, loc, result,
3643 valueAtIndex, iValue);
3645 rewriter.replaceOp(op, result);
3646 return mlir::success();
3649mlir::LogicalResult CIRToLLVMVecTernaryOpLowering::matchAndRewrite(
3650 cir::VecTernaryOp op, OpAdaptor adaptor,
3651 mlir::ConversionPatternRewriter &rewriter)
const {
3653 mlir::Value bitVec = mlir::LLVM::ICmpOp::create(
3654 rewriter, op.getLoc(), mlir::LLVM::ICmpPredicate::ne, adaptor.getCond(),
3655 mlir::LLVM::ZeroOp::create(
3656 rewriter, op.getCond().getLoc(),
3657 typeConverter->convertType(op.getCond().getType())));
3658 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(
3659 op, bitVec, adaptor.getLhs(), adaptor.getRhs());
3660 return mlir::success();
3663mlir::LogicalResult CIRToLLVMComplexAddOpLowering::matchAndRewrite(
3664 cir::ComplexAddOp op, OpAdaptor adaptor,
3665 mlir::ConversionPatternRewriter &rewriter)
const {
3666 mlir::Value lhs = adaptor.getLhs();
3667 mlir::Value rhs = adaptor.getRhs();
3668 mlir::Location loc = op.getLoc();
3670 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
3671 mlir::Type complexElemTy =
3672 getTypeConverter()->convertType(
complexType.getElementType());
3673 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
3674 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{0}));
3675 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
3676 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{1}));
3677 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
3678 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{0}));
3679 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
3680 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{1}));
3682 mlir::Value newReal;
3683 mlir::Value newImag;
3684 if (complexElemTy.isInteger()) {
3685 newReal = mlir::LLVM::AddOp::create(rewriter, loc, complexElemTy, lhsReal,
3687 newImag = mlir::LLVM::AddOp::create(rewriter, loc, complexElemTy, lhsImag,
3692 newReal = mlir::LLVM::FAddOp::create(rewriter, loc, complexElemTy, lhsReal,
3694 newImag = mlir::LLVM::FAddOp::create(rewriter, loc, complexElemTy, lhsImag,
3698 mlir::Type complexLLVMTy =
3699 getTypeConverter()->convertType(op.getResult().getType());
3700 auto initialComplex =
3701 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), complexLLVMTy);
3703 auto realComplex = mlir::LLVM::InsertValueOp::create(
3704 rewriter, op->getLoc(), initialComplex, newReal, ArrayRef(int64_t{0}));
3706 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
3707 op, realComplex, newImag, ArrayRef(int64_t{1}));
3709 return mlir::success();
3712mlir::LogicalResult CIRToLLVMComplexCreateOpLowering::matchAndRewrite(
3713 cir::ComplexCreateOp op, OpAdaptor adaptor,
3714 mlir::ConversionPatternRewriter &rewriter)
const {
3715 mlir::Type complexLLVMTy =
3716 getTypeConverter()->convertType(op.getResult().getType());
3717 auto initialComplex =
3718 mlir::LLVM::UndefOp::create(rewriter, op->getLoc(), complexLLVMTy);
3720 auto realComplex = mlir::LLVM::InsertValueOp::create(
3721 rewriter, op->getLoc(), initialComplex, adaptor.getReal(),
3722 ArrayRef(int64_t{0}));
3724 auto complex = mlir::LLVM::InsertValueOp::create(
3725 rewriter, op->getLoc(), realComplex, adaptor.getImag(),
3726 ArrayRef(int64_t{1}));
3728 rewriter.replaceOp(op, complex);
3729 return mlir::success();
3732mlir::LogicalResult CIRToLLVMComplexRealOpLowering::matchAndRewrite(
3733 cir::ComplexRealOp op, OpAdaptor adaptor,
3734 mlir::ConversionPatternRewriter &rewriter)
const {
3735 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
3736 mlir::Value operand = adaptor.getOperand();
3737 if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) {
3738 operand = mlir::LLVM::ExtractValueOp::create(
3739 rewriter, op.getLoc(), resultLLVMTy, operand,
3740 llvm::ArrayRef<std::int64_t>{0});
3742 rewriter.replaceOp(op, operand);
3743 return mlir::success();
3746mlir::LogicalResult CIRToLLVMComplexSubOpLowering::matchAndRewrite(
3747 cir::ComplexSubOp op, OpAdaptor adaptor,
3748 mlir::ConversionPatternRewriter &rewriter)
const {
3749 mlir::Value lhs = adaptor.getLhs();
3750 mlir::Value rhs = adaptor.getRhs();
3751 mlir::Location loc = op.getLoc();
3753 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
3754 mlir::Type complexElemTy =
3755 getTypeConverter()->convertType(
complexType.getElementType());
3756 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
3757 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{0}));
3758 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
3759 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{1}));
3760 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
3761 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{0}));
3762 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
3763 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{1}));
3765 mlir::Value newReal;
3766 mlir::Value newImag;
3767 if (complexElemTy.isInteger()) {
3768 newReal = mlir::LLVM::SubOp::create(rewriter, loc, complexElemTy, lhsReal,
3770 newImag = mlir::LLVM::SubOp::create(rewriter, loc, complexElemTy, lhsImag,
3775 newReal = mlir::LLVM::FSubOp::create(rewriter, loc, complexElemTy, lhsReal,
3777 newImag = mlir::LLVM::FSubOp::create(rewriter, loc, complexElemTy, lhsImag,
3781 mlir::Type complexLLVMTy =
3782 getTypeConverter()->convertType(op.getResult().getType());
3783 auto initialComplex =
3784 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), complexLLVMTy);
3786 auto realComplex = mlir::LLVM::InsertValueOp::create(
3787 rewriter, op->getLoc(), initialComplex, newReal, ArrayRef(int64_t{0}));
3789 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
3790 op, realComplex, newImag, ArrayRef(int64_t{1}));
3792 return mlir::success();
3795mlir::LogicalResult CIRToLLVMComplexImagOpLowering::matchAndRewrite(
3796 cir::ComplexImagOp op, OpAdaptor adaptor,
3797 mlir::ConversionPatternRewriter &rewriter)
const {
3798 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
3799 mlir::Value operand = adaptor.getOperand();
3800 mlir::Location loc = op.getLoc();
3802 if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) {
3803 operand = mlir::LLVM::ExtractValueOp::create(
3804 rewriter, loc, resultLLVMTy, operand, llvm::ArrayRef<std::int64_t>{1});
3806 mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(resultLLVMTy);
3808 mlir::LLVM::ConstantOp::create(rewriter, loc, resultLLVMTy, zeroAttr);
3811 rewriter.replaceOp(op, operand);
3812 return mlir::success();
3816 mlir::MLIRContext *context,
3817 unsigned &storageSize) {
3818 return TypeSwitch<mlir::Type, mlir::IntegerType>(storageType)
3819 .Case<cir::ArrayType>([&](cir::ArrayType atTy) {
3820 storageSize = atTy.getSize() * 8;
3821 return mlir::IntegerType::get(context, storageSize);
3823 .Case<cir::IntType>([&](cir::IntType intTy) {
3824 storageSize = intTy.getWidth();
3825 return mlir::IntegerType::get(context, storageSize);
3827 .Default([](mlir::Type) -> mlir::IntegerType {
3829 "Either ArrayType or IntType expected for bitfields storage");
3833mlir::LogicalResult CIRToLLVMSetBitfieldOpLowering::matchAndRewrite(
3834 cir::SetBitfieldOp op, OpAdaptor adaptor,
3835 mlir::ConversionPatternRewriter &rewriter)
const {
3836 mlir::OpBuilder::InsertionGuard guard(rewriter);
3837 rewriter.setInsertionPoint(op);
3839 cir::BitfieldInfoAttr info = op.getBitfieldInfo();
3840 uint64_t size = info.getSize();
3841 uint64_t offset = info.getOffset();
3842 mlir::Type storageType = info.getStorageType();
3843 mlir::MLIRContext *context = storageType.getContext();
3845 unsigned storageSize = 0;
3847 mlir::IntegerType intType =
3850 mlir::Value srcVal =
createIntCast(rewriter, adaptor.getSrc(), intType);
3851 unsigned srcWidth = storageSize;
3852 mlir::Value resultVal = srcVal;
3854 if (storageSize != size) {
3855 assert(storageSize > size &&
"Invalid bitfield size.");
3857 mlir::Value val = mlir::LLVM::LoadOp::create(
3858 rewriter, op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(),
3859 op.getIsVolatile());
3862 createAnd(rewriter, srcVal, llvm::APInt::getLowBitsSet(srcWidth, size));
3864 srcVal =
createShL(rewriter, srcVal, offset);
3868 ~llvm::APInt::getBitsSet(srcWidth, offset, offset + size));
3871 srcVal = mlir::LLVM::OrOp::create(rewriter, op.getLoc(), val, srcVal);
3874 mlir::LLVM::StoreOp::create(rewriter, op.getLoc(), srcVal, adaptor.getAddr(),
3875 op.getAlignment(), op.getIsVolatile());
3877 mlir::Type resultTy = getTypeConverter()->convertType(op.getType());
3879 if (info.getIsSigned()) {
3880 assert(size <= storageSize);
3881 unsigned highBits = storageSize - size;
3884 resultVal =
createShL(rewriter, resultVal, highBits);
3885 resultVal =
createAShR(rewriter, resultVal, highBits);
3890 mlir::cast<mlir::IntegerType>(resultTy),
3891 info.getIsSigned());
3893 rewriter.replaceOp(op, resultVal);
3894 return mlir::success();
3897mlir::LogicalResult CIRToLLVMComplexImagPtrOpLowering::matchAndRewrite(
3898 cir::ComplexImagPtrOp op, OpAdaptor adaptor,
3899 mlir::ConversionPatternRewriter &rewriter)
const {
3900 cir::PointerType operandTy = op.getOperand().getType();
3901 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
3902 mlir::Type elementLLVMTy =
3903 getTypeConverter()->convertType(operandTy.getPointee());
3905 mlir::LLVM::GEPArg gepIndices[2] = {{0}, {1}};
3906 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
3907 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
3908 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
3909 op, resultLLVMTy, elementLLVMTy, adaptor.getOperand(), gepIndices,
3911 return mlir::success();
3914mlir::LogicalResult CIRToLLVMComplexRealPtrOpLowering::matchAndRewrite(
3915 cir::ComplexRealPtrOp op, OpAdaptor adaptor,
3916 mlir::ConversionPatternRewriter &rewriter)
const {
3917 cir::PointerType operandTy = op.getOperand().getType();
3918 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
3919 mlir::Type elementLLVMTy =
3920 getTypeConverter()->convertType(operandTy.getPointee());
3922 mlir::LLVM::GEPArg gepIndices[2] = {0, 0};
3923 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
3924 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
3925 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
3926 op, resultLLVMTy, elementLLVMTy, adaptor.getOperand(), gepIndices,
3928 return mlir::success();
3931mlir::LogicalResult CIRToLLVMGetBitfieldOpLowering::matchAndRewrite(
3932 cir::GetBitfieldOp op, OpAdaptor adaptor,
3933 mlir::ConversionPatternRewriter &rewriter)
const {
3935 mlir::OpBuilder::InsertionGuard guard(rewriter);
3936 rewriter.setInsertionPoint(op);
3938 cir::BitfieldInfoAttr info = op.getBitfieldInfo();
3940 uint64_t offset = info.getOffset();
3941 mlir::Type storageType = info.getStorageType();
3942 mlir::MLIRContext *context = storageType.getContext();
3943 unsigned storageSize = 0;
3945 mlir::IntegerType intType =
3948 mlir::Value val = mlir::LLVM::LoadOp::create(
3949 rewriter, op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(),
3950 op.getIsVolatile());
3951 val = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), intType, val);
3953 if (info.getIsSigned()) {
3954 assert(
static_cast<unsigned>(offset + size) <= storageSize);
3955 unsigned highBits = storageSize - offset - size;
3956 val =
createShL(rewriter, val, highBits);
3957 val =
createAShR(rewriter, val, offset + highBits);
3961 if (
static_cast<unsigned>(offset) + size < storageSize)
3963 llvm::APInt::getLowBitsSet(storageSize, size));
3966 mlir::Type resTy = getTypeConverter()->convertType(op.getType());
3968 rewriter, val, mlir::cast<mlir::IntegerType>(resTy), info.getIsSigned());
3969 rewriter.replaceOp(op, newOp);
3970 return mlir::success();
3973mlir::LogicalResult CIRToLLVMInlineAsmOpLowering::matchAndRewrite(
3974 cir::InlineAsmOp op, OpAdaptor adaptor,
3975 mlir::ConversionPatternRewriter &rewriter)
const {
3977 if (op.getNumResults())
3978 llResTy = getTypeConverter()->convertType(op.getType(0));
3980 cir::AsmFlavor dialect = op.getAsmFlavor();
3981 mlir::LLVM::AsmDialect llDialect = dialect == cir::AsmFlavor::x86_att
3982 ? mlir::LLVM::AsmDialect::AD_ATT
3983 : mlir::LLVM::AsmDialect::AD_Intel;
3985 SmallVector<mlir::Attribute> opAttrs;
3986 StringRef llvmAttrName = mlir::LLVM::InlineAsmOp::getElementTypeAttrName();
3992 if (!op.getNumResults())
3993 opAttrs.push_back(mlir::Attribute());
3995 SmallVector<mlir::Value> llvmOperands;
3996 SmallVector<mlir::Value> cirOperands;
3997 for (
auto const &[llvmOp, cirOp] :
3998 zip(adaptor.getAsmOperands(), op.getAsmOperands())) {
3999 append_range(llvmOperands, llvmOp);
4000 append_range(cirOperands, cirOp);
4005 for (
auto const &[cirOpAttr, cirOp] :
4006 zip(op.getOperandAttrs(), cirOperands)) {
4008 opAttrs.push_back(mlir::Attribute());
4012 llvm::SmallVector<mlir::NamedAttribute, 1> attrs;
4013 cir::PointerType typ = mlir::cast<cir::PointerType>(cirOp.getType());
4015 *getTypeConverter(), dataLayout, typ.getPointee()));
4017 attrs.push_back(rewriter.getNamedAttr(llvmAttrName, typAttr));
4018 mlir::DictionaryAttr newDict = rewriter.getDictionaryAttr(attrs);
4019 opAttrs.push_back(newDict);
4022 rewriter.replaceOpWithNewOp<mlir::LLVM::InlineAsmOp>(
4023 op, llResTy, llvmOperands, op.getAsmStringAttr(), op.getConstraintsAttr(),
4024 op.getSideEffectsAttr(),
4027 mlir::LLVM::TailCallKindAttr::get(
4028 getContext(), mlir::LLVM::tailcallkind::TailCallKind::None),
4029 mlir::LLVM::AsmDialectAttr::get(getContext(), llDialect),
4030 rewriter.getArrayAttr(opAttrs));
4032 return mlir::success();
4035mlir::LogicalResult CIRToLLVMVAStartOpLowering::matchAndRewrite(
4036 cir::VAStartOp op, OpAdaptor adaptor,
4037 mlir::ConversionPatternRewriter &rewriter)
const {
4038 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4039 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4040 adaptor.getArgList());
4041 rewriter.replaceOpWithNewOp<mlir::LLVM::VaStartOp>(op, vaList);
4042 return mlir::success();
4045mlir::LogicalResult CIRToLLVMVAEndOpLowering::matchAndRewrite(
4046 cir::VAEndOp op, OpAdaptor adaptor,
4047 mlir::ConversionPatternRewriter &rewriter)
const {
4048 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4049 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4050 adaptor.getArgList());
4051 rewriter.replaceOpWithNewOp<mlir::LLVM::VaEndOp>(op, vaList);
4052 return mlir::success();
4055mlir::LogicalResult CIRToLLVMVAArgOpLowering::matchAndRewrite(
4056 cir::VAArgOp op, OpAdaptor adaptor,
4057 mlir::ConversionPatternRewriter &rewriter)
const {
4059 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4060 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4061 adaptor.getArgList());
4063 mlir::Type llvmType =
4064 getTypeConverter()->convertType(op->getResultTypes().front());
4066 return mlir::failure();
4068 rewriter.replaceOpWithNewOp<mlir::LLVM::VaArgOp>(op, llvmType, vaList);
4069 return mlir::success();
4072mlir::LogicalResult CIRToLLVMBlockAddressOpLowering::matchAndRewrite(
4073 cir::BlockAddressOp op, OpAdaptor adaptor,
4074 mlir::ConversionPatternRewriter &rewriter)
const {
4075 return mlir::failure();
4078mlir::LogicalResult CIRToLLVMAwaitOpLowering::matchAndRewrite(
4079 cir::AwaitOp op, OpAdaptor adaptor,
4080 mlir::ConversionPatternRewriter &rewriter)
const {
4081 return mlir::failure();
4085 return std::make_unique<ConvertCIRToLLVMPass>();
4093std::unique_ptr<llvm::Module>
4095 llvm::TimeTraceScope scope(
"lower from CIR to LLVM directly");
4097 mlir::MLIRContext *mlirCtx = mlirModule.getContext();
4099 mlir::PassManager pm(mlirCtx);
4102 (void)mlir::applyPassManagerCLOptions(pm);
4104 if (mlir::failed(pm.run(mlirModule))) {
4107 "The pass manager failed to lower CIR to LLVMIR dialect!");
4110 mlir::registerBuiltinDialectTranslation(*mlirCtx);
4111 mlir::registerLLVMDialectTranslation(*mlirCtx);
4114 llvm::TimeTraceScope translateScope(
"translateModuleToLLVMIR");
4116 StringRef moduleName = mlirModule.getName().value_or(
"CIRToLLVMModule");
4117 std::unique_ptr<llvm::Module> llvmModule =
4118 mlir::translateModuleToLLVMIR(mlirModule, llvmCtx, moduleName);
4122 report_fatal_error(
"Lowering from LLVMIR dialect to llvm IR failed!");
static bool isUnsigned(SValBuilder &SVB, NonLoc Value)
static llvm::StringRef getLinkageAttrNameString()
Returns the name used for the linkage attribute.
mlir::Value createLShR(mlir::OpBuilder &bld, mlir::Value lhs, unsigned rhs)
mlir::Value createShL(mlir::OpBuilder &bld, mlir::Value lhs, unsigned rhs)
std::optional< mlir::Attribute > lowerConstArrayAttr(cir::ConstArrayAttr constArr, const mlir::TypeConverter *converter)
mlir::Value createAShR(mlir::OpBuilder &bld, mlir::Value lhs, unsigned rhs)
mlir::Value createAnd(mlir::OpBuilder &bld, mlir::Value lhs, const llvm::APInt &rhs)
static bool isVector(QualType QT, QualType ElementType)
This helper function returns true if QT is a vector type that has element type ElementType.
mlir::Value visitCirAttr(cir::IntAttr intAttr)
IntAttr visitor.
mlir::Value visit(mlir::Attribute attr)
CIRAttrToValue(mlir::Operation *parentOp, mlir::ConversionPatternRewriter &rewriter, const mlir::TypeConverter *converter)
mlir::Attribute visit(mlir::Attribute attr)
mlir::Attribute visitCirAttr(cir::FPAttr attr)
mlir::Attribute visitCirAttr(cir::BoolAttr attr)
GlobalInitAttrRewriter(mlir::Type type, mlir::ConversionPatternRewriter &rewriter)
mlir::Attribute visitCirAttr(cir::IntAttr attr)
void createLLVMFuncOpIfNotExist(mlir::ConversionPatternRewriter &rewriter, mlir::Operation *srcOp, llvm::StringRef fnName, mlir::Type fnTy)
static void collectUnreachable(mlir::Operation *parent, llvm::SmallVector< mlir::Operation * > &ops)
static mlir::LLVM::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.
static mlir::Value getLLVMIntCast(mlir::ConversionPatternRewriter &rewriter, mlir::Value llvmSrc, mlir::Type llvmDstIntTy, bool isUnsigned, uint64_t cirSrcWidth, uint64_t cirDstIntWidth)
void convertSideEffectForCall(mlir::Operation *callOp, bool isNothrow, cir::SideEffect sideEffect, mlir::LLVM::MemoryEffectsAttr &memoryEffect, bool &noUnwind, bool &willReturn)
static mlir::Value emitFromMemory(mlir::ConversionPatternRewriter &rewriter, mlir::DataLayout const &dataLayout, cir::LoadOp op, mlir::Value value)
Emits the value from memory as expected by its users.
mlir::IntegerType computeBitfieldIntType(mlir::Type storageType, mlir::MLIRContext *context, unsigned &storageSize)
static mlir::LLVM::CallIntrinsicOp createCallLLVMIntrinsicOp(mlir::ConversionPatternRewriter &rewriter, mlir::Location loc, const llvm::Twine &intrinsicName, mlir::Type resultTy, mlir::ValueRange operands)
bool hasTrailingZeros(cir::ConstArrayAttr attr)
static mlir::LogicalResult rewriteCallOrInvoke(mlir::Operation *op, mlir::ValueRange callOperands, mlir::ConversionPatternRewriter &rewriter, const mlir::TypeConverter *converter, mlir::FlatSymbolRefAttr calleeAttr)
static mlir::LLVM::LLVMStructType getLLVMLandingPadStructTy(mlir::ConversionPatternRewriter &rewriter)
std::unique_ptr< llvm::Module > lowerDirectlyFromCIRToLLVMIR(mlir::ModuleOp mlirModule, llvm::LLVMContext &llvmCtx)
mlir::Value lowerCirAttrAsValue(mlir::Operation *parentOp, const mlir::Attribute attr, mlir::ConversionPatternRewriter &rewriter, const mlir::TypeConverter *converter)
Switches on the type of attribute and calls the appropriate conversion.
static 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 void prepareTypeConverter(mlir::LLVMTypeConverter &converter, mlir::DataLayout &dataLayout)
static mlir::LLVM::AtomicOrdering getLLVMMemOrder(std::optional< cir::MemOrder > memorder)
std::unique_ptr< mlir::Pass > createConvertCIRToLLVMPass()
Create a pass that fully lowers CIR to the LLVMIR dialect.
static mlir::LLVM::FCmpPredicate convertCmpKindToFCmpPredicate(cir::CmpOpKind kind)
Convert from a CIR comparison kind to an LLVM IR floating-point comparison kind.
static mlir::LLVM::Visibility lowerCIRVisibilityToLLVMVisibility(cir::VisibilityKind visibilityKind)
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)
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 opGlobalThreadLocal()
static bool globalViewIntLowering()
static bool opAllocaAnnotations()
static bool atomicScope()
static bool opLoadStoreTbaa()
static bool optInfoAttr()
static bool opFuncExtraAttrs()
static bool opCallLandingPad()
static bool vaArgABILowering()
static bool fpConstraints()
static bool 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 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)