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();
206 mlir::Value llvmSrc, mlir::Type llvmDstIntTy,
208 uint64_t cirDstIntWidth) {
209 if (cirSrcWidth == cirDstIntWidth)
212 auto loc = llvmSrc.getLoc();
213 if (cirSrcWidth < cirDstIntWidth) {
215 return mlir::LLVM::ZExtOp::create(rewriter, loc, llvmDstIntTy, llvmSrc);
216 return mlir::LLVM::SExtOp::create(rewriter, loc, llvmDstIntTy, llvmSrc);
220 return mlir::LLVM::TruncOp::create(rewriter, loc, llvmDstIntTy, llvmSrc);
226 mlir::ConversionPatternRewriter &rewriter,
227 const mlir::TypeConverter *converter)
228 : parentOp(parentOp), rewriter(rewriter), converter(converter) {}
230 mlir::Value
visit(mlir::Attribute attr) {
231 return llvm::TypeSwitch<mlir::Attribute, mlir::Value>(attr)
232 .Case<cir::IntAttr, cir::FPAttr, cir::ConstComplexAttr,
233 cir::ConstArrayAttr, cir::ConstRecordAttr, cir::ConstVectorAttr,
234 cir::ConstPtrAttr, cir::GlobalViewAttr, cir::TypeInfoAttr,
235 cir::VTableAttr, cir::ZeroAttr>(
237 .Default([&](
auto attrT) {
return mlir::Value(); });
242 mlir::Value
visitCirAttr(cir::ConstComplexAttr complexAttr);
253 mlir::Operation *parentOp;
254 mlir::ConversionPatternRewriter &rewriter;
255 const mlir::TypeConverter *converter;
260 const mlir::Attribute attr,
261 mlir::ConversionPatternRewriter &rewriter,
262 const mlir::TypeConverter *converter) {
264 mlir::Value value = valueConverter.
visit(attr);
266 llvm_unreachable(
"unhandled attribute type");
271 cir::SideEffect sideEffect,
272 mlir::LLVM::MemoryEffectsAttr &memoryEffect,
273 bool &noUnwind,
bool &willReturn) {
274 using mlir::LLVM::ModRefInfo;
276 switch (sideEffect) {
277 case cir::SideEffect::All:
279 noUnwind = isNothrow;
283 case cir::SideEffect::Pure:
284 memoryEffect = mlir::LLVM::MemoryEffectsAttr::get(
285 callOp->getContext(), ModRefInfo::Ref,
292 case cir::SideEffect::Const:
293 memoryEffect = mlir::LLVM::MemoryEffectsAttr::get(
294 callOp->getContext(), ModRefInfo::NoModRef,
295 ModRefInfo::NoModRef,
296 ModRefInfo::NoModRef);
303static mlir::LLVM::CallIntrinsicOp
305 mlir::Location loc,
const llvm::Twine &intrinsicName,
306 mlir::Type resultTy, mlir::ValueRange operands) {
307 auto intrinsicNameAttr =
308 mlir::StringAttr::get(rewriter.getContext(), intrinsicName);
309 return mlir::LLVM::CallIntrinsicOp::create(rewriter, loc, resultTy,
310 intrinsicNameAttr, operands);
314 mlir::ConversionPatternRewriter &rewriter, mlir::Operation *op,
315 const llvm::Twine &intrinsicName, mlir::Type resultTy,
316 mlir::ValueRange operands) {
318 rewriter, op->getLoc(), intrinsicName, resultTy, operands);
319 rewriter.replaceOp(op, callIntrinOp.getOperation());
325 mlir::Location loc = parentOp->getLoc();
326 return mlir::LLVM::ConstantOp::create(
327 rewriter, loc, converter->convertType(intAttr.getType()),
333 mlir::Location loc = parentOp->getLoc();
334 return mlir::LLVM::ConstantOp::create(
335 rewriter, loc, converter->convertType(fltAttr.getType()),
341 auto complexType = mlir::cast<cir::ComplexType>(complexAttr.getType());
342 mlir::Type complexElemTy = complexType.getElementType();
343 mlir::Type complexElemLLVMTy = converter->convertType(complexElemTy);
345 mlir::Attribute components[2];
346 if (
const auto intType = mlir::dyn_cast<cir::IntType>(complexElemTy)) {
347 components[0] = rewriter.getIntegerAttr(
349 mlir::cast<cir::IntAttr>(complexAttr.getReal()).getValue());
350 components[1] = rewriter.getIntegerAttr(
352 mlir::cast<cir::IntAttr>(complexAttr.getImag()).getValue());
354 components[0] = rewriter.getFloatAttr(
356 mlir::cast<cir::FPAttr>(complexAttr.getReal()).getValue());
357 components[1] = rewriter.getFloatAttr(
359 mlir::cast<cir::FPAttr>(complexAttr.getImag()).getValue());
362 mlir::Location loc = parentOp->getLoc();
363 return mlir::LLVM::ConstantOp::create(
364 rewriter, loc, converter->convertType(complexAttr.getType()),
365 rewriter.getArrayAttr(components));
370 mlir::Location loc = parentOp->getLoc();
371 if (ptrAttr.isNullValue()) {
372 return mlir::LLVM::ZeroOp::create(
373 rewriter, loc, converter->convertType(ptrAttr.getType()));
375 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
376 mlir::Value ptrVal = mlir::LLVM::ConstantOp::create(
378 rewriter.getIntegerType(layout.getTypeSizeInBits(ptrAttr.getType())),
379 ptrAttr.getValue().getInt());
380 return mlir::LLVM::IntToPtrOp::create(
381 rewriter, loc, converter->convertType(ptrAttr.getType()), ptrVal);
386 mlir::Type llvmTy = converter->convertType(attr.getType());
387 mlir::Location loc = parentOp->getLoc();
390 if (attr.hasTrailingZeros()) {
391 mlir::Type arrayTy = attr.getType();
392 result = mlir::LLVM::ZeroOp::create(rewriter, loc,
393 converter->convertType(arrayTy));
395 result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
399 if (
auto arrayAttr = mlir::dyn_cast<mlir::ArrayAttr>(attr.getElts())) {
400 for (
auto [idx, elt] : llvm::enumerate(arrayAttr)) {
401 mlir::DataLayout dataLayout(parentOp->getParentOfType<mlir::ModuleOp>());
402 mlir::Value init =
visit(elt);
404 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
406 }
else if (
auto strAttr = mlir::dyn_cast<mlir::StringAttr>(attr.getElts())) {
409 auto arrayTy = mlir::dyn_cast<cir::ArrayType>(strAttr.getType());
410 assert(arrayTy &&
"String attribute must have an array type");
411 mlir::Type eltTy = arrayTy.getElementType();
412 for (
auto [idx, elt] : llvm::enumerate(strAttr)) {
413 auto init = mlir::LLVM::ConstantOp::create(
414 rewriter, loc, converter->convertType(eltTy), elt);
416 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
419 llvm_unreachable(
"unexpected ConstArrayAttr elements");
427 const mlir::Type llvmTy = converter->convertType(constRecord.getType());
428 const mlir::Location loc = parentOp->getLoc();
429 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
432 for (
auto [idx, elt] : llvm::enumerate(constRecord.getMembers())) {
433 mlir::Value init =
visit(elt);
435 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
443 const mlir::Type llvmTy = converter->convertType(attr.getType());
444 const mlir::Location loc = parentOp->getLoc();
447 for (
const mlir::Attribute elementAttr : attr.getElts()) {
448 mlir::Attribute mlirAttr;
449 if (
auto intAttr = mlir::dyn_cast<cir::IntAttr>(elementAttr)) {
450 mlirAttr = rewriter.getIntegerAttr(
451 converter->convertType(intAttr.getType()), intAttr.getValue());
452 }
else if (
auto floatAttr = mlir::dyn_cast<cir::FPAttr>(elementAttr)) {
453 mlirAttr = rewriter.getFloatAttr(
454 converter->convertType(floatAttr.getType()), floatAttr.getValue());
457 "vector constant with an element that is neither an int nor a float");
459 mlirValues.push_back(mlirAttr);
462 return mlir::LLVM::ConstantOp::create(
463 rewriter, loc, llvmTy,
464 mlir::DenseElementsAttr::get(mlir::cast<mlir::ShapedType>(llvmTy),
470 auto moduleOp = parentOp->getParentOfType<mlir::ModuleOp>();
471 mlir::DataLayout dataLayout(moduleOp);
472 mlir::Type sourceType;
474 llvm::StringRef symName;
475 mlir::Operation *sourceSymbol =
476 mlir::SymbolTable::lookupSymbolIn(moduleOp, globalAttr.getSymbol());
477 if (
auto llvmSymbol = dyn_cast<mlir::LLVM::GlobalOp>(sourceSymbol)) {
478 sourceType = llvmSymbol.getType();
479 symName = llvmSymbol.getSymName();
480 }
else if (
auto cirSymbol = dyn_cast<cir::GlobalOp>(sourceSymbol)) {
483 symName = cirSymbol.getSymName();
484 }
else if (
auto llvmFun = dyn_cast<mlir::LLVM::LLVMFuncOp>(sourceSymbol)) {
485 sourceType = llvmFun.getFunctionType();
486 symName = llvmFun.getSymName();
487 }
else if (
auto fun = dyn_cast<cir::FuncOp>(sourceSymbol)) {
488 sourceType = converter->convertType(fun.getFunctionType());
489 symName = fun.getSymName();
490 }
else if (
auto alias = dyn_cast<mlir::LLVM::AliasOp>(sourceSymbol)) {
491 sourceType = alias.getType();
492 symName = alias.getSymName();
494 llvm_unreachable(
"Unexpected GlobalOp type");
497 mlir::Location loc = parentOp->getLoc();
498 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
499 rewriter, loc, mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
502 if (globalAttr.getIndices()) {
505 if (mlir::isa<mlir::LLVM::LLVMArrayType, mlir::LLVM::LLVMStructType>(
507 indices.push_back(0);
509 for (mlir::Attribute idx : globalAttr.getIndices()) {
510 auto intAttr = mlir::cast<mlir::IntegerAttr>(idx);
511 indices.push_back(intAttr.getValue().getSExtValue());
513 mlir::Type resTy = addrOp.getType();
514 mlir::Type eltTy = converter->convertType(sourceType);
516 mlir::LLVM::GEPOp::create(rewriter, loc, resTy, eltTy, addrOp, indices,
517 mlir::LLVM::GEPNoWrapFlags::none);
526 if (
auto ptrTy = mlir::dyn_cast<cir::PointerType>(globalAttr.getType())) {
527 mlir::Type llvmEltTy =
530 if (llvmEltTy == sourceType)
533 mlir::Type llvmDstTy = converter->convertType(globalAttr.getType());
534 return mlir::LLVM::BitcastOp::create(rewriter, parentOp->getLoc(),
538 llvm_unreachable(
"Expecting pointer or integer type for GlobalViewAttr");
543 mlir::Type llvmTy = converter->convertType(typeInfoAttr.getType());
544 mlir::Location loc = parentOp->getLoc();
545 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
547 for (
auto [idx, elt] : llvm::enumerate(typeInfoAttr.getData())) {
548 mlir::Value init =
visit(elt);
550 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
558 mlir::Type llvmTy = converter->convertType(vtableArr.getType());
559 mlir::Location loc = parentOp->getLoc();
560 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
562 for (
auto [idx, elt] : llvm::enumerate(vtableArr.getData())) {
563 mlir::Value init =
visit(elt);
565 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
573 mlir::Location loc = parentOp->getLoc();
574 return mlir::LLVM::ZeroOp::create(rewriter, loc,
575 converter->convertType(attr.getType()));
583 mlir::ConversionPatternRewriter &rewriter)
584 : llvmType(type), rewriter(rewriter) {}
586 mlir::Attribute
visit(mlir::Attribute attr) {
587 return llvm::TypeSwitch<mlir::Attribute, mlir::Attribute>(attr)
588 .Case<cir::IntAttr, cir::FPAttr, cir::BoolAttr>(
590 .Default([&](
auto attrT) {
return mlir::Attribute(); });
594 return rewriter.getIntegerAttr(llvmType, attr.getValue());
598 return rewriter.getFloatAttr(llvmType, attr.getValue());
602 return rewriter.getBoolAttr(attr.getValue());
607 mlir::ConversionPatternRewriter &rewriter;
615 :
public mlir::PassWrapper<ConvertCIRToLLVMPass,
616 mlir::OperationPass<mlir::ModuleOp>> {
618 registry.insert<mlir::BuiltinDialect, mlir::DLTIDialect,
619 mlir::LLVM::LLVMDialect, mlir::func::FuncDialect>();
626 return "Convert the prepared CIR dialect module to LLVM dialect";
629 StringRef
getArgument()
const override {
return "cir-flat-to-llvm"; }
632mlir::LogicalResult CIRToLLVMACosOpLowering::matchAndRewrite(
633 cir::ACosOp op, OpAdaptor adaptor,
634 mlir::ConversionPatternRewriter &rewriter)
const {
635 mlir::Type resTy = typeConverter->convertType(op.getType());
636 rewriter.replaceOpWithNewOp<mlir::LLVM::ACosOp>(op, resTy,
637 adaptor.getOperands()[0]);
638 return mlir::success();
641mlir::LogicalResult CIRToLLVMASinOpLowering::matchAndRewrite(
642 cir::ASinOp op, OpAdaptor adaptor,
643 mlir::ConversionPatternRewriter &rewriter)
const {
644 mlir::Type resTy = typeConverter->convertType(op.getType());
645 rewriter.replaceOpWithNewOp<mlir::LLVM::ASinOp>(op, resTy, adaptor.getSrc());
646 return mlir::success();
649mlir::LogicalResult CIRToLLVMAssumeOpLowering::matchAndRewrite(
650 cir::AssumeOp op, OpAdaptor adaptor,
651 mlir::ConversionPatternRewriter &rewriter)
const {
652 auto cond = adaptor.getPredicate();
653 rewriter.replaceOpWithNewOp<mlir::LLVM::AssumeOp>(op, cond);
654 return mlir::success();
657mlir::LogicalResult CIRToLLVMAssumeAlignedOpLowering::matchAndRewrite(
658 cir::AssumeAlignedOp op, OpAdaptor adaptor,
659 mlir::ConversionPatternRewriter &rewriter)
const {
660 SmallVector<mlir::Value, 3> opBundleArgs{adaptor.getPointer()};
662 auto alignment = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
663 adaptor.getAlignmentAttr());
664 opBundleArgs.push_back(alignment);
666 if (mlir::Value offset = adaptor.getOffset())
667 opBundleArgs.push_back(offset);
669 auto cond = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
670 rewriter.getI1Type(), 1);
671 mlir::LLVM::AssumeOp::create(rewriter, op.getLoc(), cond,
"align",
676 rewriter.replaceOp(op, adaptor.getPointer());
677 return mlir::success();
680mlir::LogicalResult CIRToLLVMAssumeSepStorageOpLowering::matchAndRewrite(
681 cir::AssumeSepStorageOp op, OpAdaptor adaptor,
682 mlir::ConversionPatternRewriter &rewriter)
const {
683 auto cond = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
684 rewriter.getI1Type(), 1);
685 rewriter.replaceOpWithNewOp<mlir::LLVM::AssumeOp>(
686 op, cond, mlir::LLVM::AssumeSeparateStorageTag{}, adaptor.getPtr1(),
688 return mlir::success();
691static mlir::LLVM::AtomicOrdering
694 return mlir::LLVM::AtomicOrdering::not_atomic;
696 case cir::MemOrder::Relaxed:
697 return mlir::LLVM::AtomicOrdering::monotonic;
698 case cir::MemOrder::Consume:
699 case cir::MemOrder::Acquire:
700 return mlir::LLVM::AtomicOrdering::acquire;
701 case cir::MemOrder::Release:
702 return mlir::LLVM::AtomicOrdering::release;
703 case cir::MemOrder::AcquireRelease:
704 return mlir::LLVM::AtomicOrdering::acq_rel;
705 case cir::MemOrder::SequentiallyConsistent:
706 return mlir::LLVM::AtomicOrdering::seq_cst;
708 llvm_unreachable(
"unknown memory order");
711mlir::LogicalResult CIRToLLVMAtomicCmpXchgOpLowering::matchAndRewrite(
712 cir::AtomicCmpXchgOp op, OpAdaptor adaptor,
713 mlir::ConversionPatternRewriter &rewriter)
const {
714 mlir::Value expected = adaptor.getExpected();
715 mlir::Value desired = adaptor.getDesired();
717 auto cmpxchg = mlir::LLVM::AtomicCmpXchgOp::create(
718 rewriter, op.getLoc(), adaptor.getPtr(), expected, desired,
722 cmpxchg.setAlignment(adaptor.getAlignment());
723 cmpxchg.setWeak(adaptor.getWeak());
724 cmpxchg.setVolatile_(adaptor.getIsVolatile());
727 auto old = mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(),
728 cmpxchg.getResult(), 0);
729 auto cmp = mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(),
730 cmpxchg.getResult(), 1);
732 rewriter.replaceOp(op, {old, cmp});
733 return mlir::success();
736mlir::LogicalResult CIRToLLVMAtomicXchgOpLowering::matchAndRewrite(
737 cir::AtomicXchgOp op, OpAdaptor adaptor,
738 mlir::ConversionPatternRewriter &rewriter)
const {
740 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(adaptor.getMemOrder());
741 rewriter.replaceOpWithNewOp<mlir::LLVM::AtomicRMWOp>(
742 op, mlir::LLVM::AtomicBinOp::xchg, adaptor.getPtr(), adaptor.getVal(),
744 return mlir::success();
747mlir::LogicalResult CIRToLLVMAtomicTestAndSetOpLowering::matchAndRewrite(
748 cir::AtomicTestAndSetOp op, OpAdaptor adaptor,
749 mlir::ConversionPatternRewriter &rewriter)
const {
752 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
754 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
755 rewriter.getI8Type(), 1);
756 auto rmw = mlir::LLVM::AtomicRMWOp::create(
757 rewriter, op.getLoc(), mlir::LLVM::AtomicBinOp::xchg, adaptor.getPtr(),
758 one, llvmOrder, llvm::StringRef(),
759 adaptor.getAlignment().value_or(0), op.getIsVolatile());
761 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
762 rewriter.getI8Type(), 0);
763 auto cmp = mlir::LLVM::ICmpOp::create(
764 rewriter, op.getLoc(), mlir::LLVM::ICmpPredicate::ne, rmw, zero);
766 rewriter.replaceOp(op, cmp);
767 return mlir::success();
770mlir::LogicalResult CIRToLLVMAtomicClearOpLowering::matchAndRewrite(
771 cir::AtomicClearOp op, OpAdaptor adaptor,
772 mlir::ConversionPatternRewriter &rewriter)
const {
775 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
776 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
777 rewriter.getI8Type(), 0);
778 auto store = mlir::LLVM::StoreOp::create(
779 rewriter, op.getLoc(), zero, adaptor.getPtr(),
780 adaptor.getAlignment().value_or(0), op.getIsVolatile(),
781 false,
false, llvmOrder);
783 rewriter.replaceOp(op, store);
784 return mlir::success();
787static mlir::LLVM::AtomicBinOp
790 case cir::AtomicFetchKind::Add:
791 return isInt ? mlir::LLVM::AtomicBinOp::add : mlir::LLVM::AtomicBinOp::fadd;
792 case cir::AtomicFetchKind::Sub:
793 return isInt ? mlir::LLVM::AtomicBinOp::sub : mlir::LLVM::AtomicBinOp::fsub;
794 case cir::AtomicFetchKind::And:
795 return mlir::LLVM::AtomicBinOp::_and;
796 case cir::AtomicFetchKind::Xor:
797 return mlir::LLVM::AtomicBinOp::_xor;
798 case cir::AtomicFetchKind::Or:
799 return mlir::LLVM::AtomicBinOp::_or;
800 case cir::AtomicFetchKind::Nand:
801 return mlir::LLVM::AtomicBinOp::nand;
802 case cir::AtomicFetchKind::Max: {
804 return mlir::LLVM::AtomicBinOp::fmax;
805 return isSignedInt ? mlir::LLVM::AtomicBinOp::max
806 : mlir::LLVM::AtomicBinOp::umax;
808 case cir::AtomicFetchKind::Min: {
810 return mlir::LLVM::AtomicBinOp::fmin;
811 return isSignedInt ? mlir::LLVM::AtomicBinOp::min
812 : mlir::LLVM::AtomicBinOp::umin;
815 llvm_unreachable(
"Unknown atomic fetch opcode");
818static llvm::StringLiteral
getLLVMBinop(cir::AtomicFetchKind k,
bool isInt) {
820 case cir::AtomicFetchKind::Add:
821 return isInt ? mlir::LLVM::AddOp::getOperationName()
822 : mlir::LLVM::FAddOp::getOperationName();
823 case cir::AtomicFetchKind::Sub:
824 return isInt ? mlir::LLVM::SubOp::getOperationName()
825 : mlir::LLVM::FSubOp::getOperationName();
826 case cir::AtomicFetchKind::And:
827 return mlir::LLVM::AndOp::getOperationName();
828 case cir::AtomicFetchKind::Xor:
829 return mlir::LLVM::XOrOp::getOperationName();
830 case cir::AtomicFetchKind::Or:
831 return mlir::LLVM::OrOp::getOperationName();
832 case cir::AtomicFetchKind::Nand:
834 return mlir::LLVM::AndOp::getOperationName();
835 case cir::AtomicFetchKind::Max:
836 case cir::AtomicFetchKind::Min:
837 llvm_unreachable(
"handled in buildMinMaxPostOp");
839 llvm_unreachable(
"Unknown atomic fetch opcode");
842mlir::Value CIRToLLVMAtomicFetchOpLowering::buildPostOp(
843 cir::AtomicFetchOp op, OpAdaptor adaptor,
844 mlir::ConversionPatternRewriter &rewriter, mlir::Value rmwVal,
850 rewriter.getStringAttr(
getLLVMBinop(op.getBinop(), isInt)),
851 atomicOperands, atomicResTys, {})
855mlir::Value CIRToLLVMAtomicFetchOpLowering::buildMinMaxPostOp(
856 cir::AtomicFetchOp op, OpAdaptor adaptor,
857 mlir::ConversionPatternRewriter &rewriter, mlir::Value rmwVal,
bool isInt,
858 bool isSigned)
const {
859 mlir::Location loc = op.getLoc();
862 if (op.getBinop() == cir::AtomicFetchKind::Max)
863 return mlir::LLVM::MaxNumOp::create(rewriter, loc, rmwVal,
865 return mlir::LLVM::MinNumOp::create(rewriter, loc, rmwVal,
869 mlir::LLVM::ICmpPredicate pred;
870 if (op.getBinop() == cir::AtomicFetchKind::Max) {
871 pred = isSigned ? mlir::LLVM::ICmpPredicate::sgt
872 : mlir::LLVM::ICmpPredicate::ugt;
874 pred = isSigned ? mlir::LLVM::ICmpPredicate::slt
875 : mlir::LLVM::ICmpPredicate::ult;
877 mlir::Value cmp = mlir::LLVM::ICmpOp::create(
879 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(), pred), rmwVal,
881 return mlir::LLVM::SelectOp::create(rewriter, loc, cmp, rmwVal,
885mlir::LogicalResult CIRToLLVMAtomicFetchOpLowering::matchAndRewrite(
886 cir::AtomicFetchOp op, OpAdaptor adaptor,
887 mlir::ConversionPatternRewriter &rewriter)
const {
889 bool isSignedInt =
false;
890 if (
auto intTy = mlir::dyn_cast<cir::IntType>(op.getVal().getType())) {
892 isSignedInt = intTy.isSigned();
893 }
else if (mlir::isa<cir::SingleType, cir::DoubleType>(
894 op.getVal().getType())) {
897 return op.emitError() <<
"Unsupported type: " << op.getVal().getType();
900 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
901 mlir::LLVM::AtomicBinOp llvmBinOp =
903 auto rmwVal = mlir::LLVM::AtomicRMWOp::create(rewriter, op.getLoc(),
904 llvmBinOp, adaptor.getPtr(),
905 adaptor.getVal(), llvmOrder);
907 mlir::Value result = rmwVal.getResult();
908 if (!op.getFetchFirst()) {
909 if (op.getBinop() == cir::AtomicFetchKind::Max ||
910 op.getBinop() == cir::AtomicFetchKind::Min)
911 result = buildMinMaxPostOp(op, adaptor, rewriter, rmwVal.getRes(), isInt,
914 result = buildPostOp(op, adaptor, rewriter, rmwVal.getRes(), isInt);
917 if (op.getBinop() == cir::AtomicFetchKind::Nand) {
918 auto negOne = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
919 result.getType(), -1);
920 result = mlir::LLVM::XOrOp::create(rewriter, op.getLoc(), result, negOne);
924 rewriter.replaceOp(op, result);
925 return mlir::success();
928mlir::LogicalResult CIRToLLVMBitClrsbOpLowering::matchAndRewrite(
929 cir::BitClrsbOp op, OpAdaptor adaptor,
930 mlir::ConversionPatternRewriter &rewriter)
const {
931 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
932 adaptor.getInput().getType(), 0);
933 auto isNeg = mlir::LLVM::ICmpOp::create(
934 rewriter, op.getLoc(),
935 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(),
936 mlir::LLVM::ICmpPredicate::slt),
937 adaptor.getInput(), zero);
939 auto negOne = mlir::LLVM::ConstantOp::create(
940 rewriter, op.getLoc(), adaptor.getInput().getType(), -1);
941 auto flipped = mlir::LLVM::XOrOp::create(rewriter, op.getLoc(),
942 adaptor.getInput(), negOne);
944 auto select = mlir::LLVM::SelectOp::create(rewriter, op.getLoc(), isNeg,
945 flipped, adaptor.getInput());
947 auto resTy = getTypeConverter()->convertType(op.getType());
948 auto clz = mlir::LLVM::CountLeadingZerosOp::create(
949 rewriter, op.getLoc(), resTy,
select,
false);
951 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
952 auto res = mlir::LLVM::SubOp::create(rewriter, op.getLoc(),
clz, one);
953 rewriter.replaceOp(op, res);
955 return mlir::LogicalResult::success();
958mlir::LogicalResult CIRToLLVMBitClzOpLowering::matchAndRewrite(
959 cir::BitClzOp op, OpAdaptor adaptor,
960 mlir::ConversionPatternRewriter &rewriter)
const {
961 auto resTy = getTypeConverter()->convertType(op.getType());
962 auto llvmOp = mlir::LLVM::CountLeadingZerosOp::create(
963 rewriter, op.getLoc(), resTy, adaptor.getInput(), op.getPoisonZero());
964 rewriter.replaceOp(op, llvmOp);
965 return mlir::LogicalResult::success();
968mlir::LogicalResult CIRToLLVMBitCtzOpLowering::matchAndRewrite(
969 cir::BitCtzOp op, OpAdaptor adaptor,
970 mlir::ConversionPatternRewriter &rewriter)
const {
971 auto resTy = getTypeConverter()->convertType(op.getType());
972 auto llvmOp = mlir::LLVM::CountTrailingZerosOp::create(
973 rewriter, op.getLoc(), resTy, adaptor.getInput(), op.getPoisonZero());
974 rewriter.replaceOp(op, llvmOp);
975 return mlir::LogicalResult::success();
978mlir::LogicalResult CIRToLLVMBitFfsOpLowering::matchAndRewrite(
979 cir::BitFfsOp op, OpAdaptor adaptor,
980 mlir::ConversionPatternRewriter &rewriter)
const {
981 auto resTy = getTypeConverter()->convertType(op.getType());
982 auto ctz = mlir::LLVM::CountTrailingZerosOp::create(rewriter, op.getLoc(),
983 resTy, adaptor.getInput(),
986 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
987 auto ctzAddOne = mlir::LLVM::AddOp::create(rewriter, op.getLoc(),
ctz, one);
989 auto zeroInputTy = mlir::LLVM::ConstantOp::create(
990 rewriter, op.getLoc(), adaptor.getInput().getType(), 0);
991 auto isZero = mlir::LLVM::ICmpOp::create(
992 rewriter, op.getLoc(),
993 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(),
994 mlir::LLVM::ICmpPredicate::eq),
995 adaptor.getInput(), zeroInputTy);
997 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 0);
998 auto res = mlir::LLVM::SelectOp::create(rewriter, op.getLoc(), isZero, zero,
1000 rewriter.replaceOp(op, res);
1002 return mlir::LogicalResult::success();
1005mlir::LogicalResult CIRToLLVMBitParityOpLowering::matchAndRewrite(
1006 cir::BitParityOp op, OpAdaptor adaptor,
1007 mlir::ConversionPatternRewriter &rewriter)
const {
1008 auto resTy = getTypeConverter()->convertType(op.getType());
1009 auto popcnt = mlir::LLVM::CtPopOp::create(rewriter, op.getLoc(), resTy,
1010 adaptor.getInput());
1012 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1014 mlir::LLVM::AndOp::create(rewriter, op.getLoc(), popcnt, one);
1015 rewriter.replaceOp(op, popcntMod2);
1017 return mlir::LogicalResult::success();
1020mlir::LogicalResult CIRToLLVMBitPopcountOpLowering::matchAndRewrite(
1021 cir::BitPopcountOp op, OpAdaptor adaptor,
1022 mlir::ConversionPatternRewriter &rewriter)
const {
1023 auto resTy = getTypeConverter()->convertType(op.getType());
1024 auto llvmOp = mlir::LLVM::CtPopOp::create(rewriter, op.getLoc(), resTy,
1025 adaptor.getInput());
1026 rewriter.replaceOp(op, llvmOp);
1027 return mlir::LogicalResult::success();
1030mlir::LogicalResult CIRToLLVMBitReverseOpLowering::matchAndRewrite(
1031 cir::BitReverseOp op, OpAdaptor adaptor,
1032 mlir::ConversionPatternRewriter &rewriter)
const {
1033 rewriter.replaceOpWithNewOp<mlir::LLVM::BitReverseOp>(op, adaptor.getInput());
1034 return mlir::success();
1037mlir::LogicalResult CIRToLLVMBrCondOpLowering::matchAndRewrite(
1038 cir::BrCondOp brOp, OpAdaptor adaptor,
1039 mlir::ConversionPatternRewriter &rewriter)
const {
1044 mlir::Value i1Condition = adaptor.getCond();
1046 rewriter.replaceOpWithNewOp<mlir::LLVM::CondBrOp>(
1047 brOp, i1Condition, brOp.getDestTrue(), adaptor.getDestOperandsTrue(),
1048 brOp.getDestFalse(), adaptor.getDestOperandsFalse());
1050 return mlir::success();
1053mlir::LogicalResult CIRToLLVMByteSwapOpLowering::matchAndRewrite(
1054 cir::ByteSwapOp op, OpAdaptor adaptor,
1055 mlir::ConversionPatternRewriter &rewriter)
const {
1056 rewriter.replaceOpWithNewOp<mlir::LLVM::ByteSwapOp>(op, adaptor.getInput());
1057 return mlir::LogicalResult::success();
1060mlir::Type CIRToLLVMCastOpLowering::convertTy(mlir::Type ty)
const {
1061 return getTypeConverter()->convertType(ty);
1064mlir::LogicalResult CIRToLLVMCastOpLowering::matchAndRewrite(
1065 cir::CastOp castOp, OpAdaptor adaptor,
1066 mlir::ConversionPatternRewriter &rewriter)
const {
1071 switch (castOp.getKind()) {
1072 case cir::CastKind::array_to_ptrdecay: {
1073 const auto ptrTy = mlir::cast<cir::PointerType>(castOp.getType());
1074 mlir::Value sourceValue = adaptor.getSrc();
1075 mlir::Type targetType = convertTy(ptrTy);
1077 ptrTy.getPointee());
1078 llvm::SmallVector<mlir::LLVM::GEPArg> offset{0};
1079 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1080 castOp, targetType, elementTy, sourceValue, offset);
1083 case cir::CastKind::int_to_bool: {
1084 mlir::Value llvmSrcVal = adaptor.getSrc();
1085 mlir::Value zeroInt = mlir::LLVM::ConstantOp::create(
1086 rewriter, castOp.getLoc(), llvmSrcVal.getType(), 0);
1087 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
1088 castOp, mlir::LLVM::ICmpPredicate::ne, llvmSrcVal, zeroInt);
1091 case cir::CastKind::integral: {
1092 mlir::Type srcType = castOp.getSrc().getType();
1093 mlir::Type dstType = castOp.getType();
1094 mlir::Value llvmSrcVal = adaptor.getSrc();
1095 mlir::Type llvmDstType = getTypeConverter()->convertType(dstType);
1096 cir::IntType srcIntType =
1097 mlir::cast<cir::IntType>(elementTypeIfVector(srcType));
1098 cir::IntType dstIntType =
1099 mlir::cast<cir::IntType>(elementTypeIfVector(dstType));
1100 rewriter.replaceOp(castOp,
getLLVMIntCast(rewriter, llvmSrcVal, llvmDstType,
1101 srcIntType.isUnsigned(),
1102 srcIntType.getWidth(),
1103 dstIntType.getWidth()));
1106 case cir::CastKind::floating: {
1107 mlir::Value llvmSrcVal = adaptor.getSrc();
1108 mlir::Type llvmDstTy = getTypeConverter()->convertType(castOp.getType());
1110 mlir::Type srcTy = elementTypeIfVector(castOp.getSrc().getType());
1111 mlir::Type dstTy = elementTypeIfVector(castOp.getType());
1113 if (!mlir::isa<cir::FPTypeInterface>(dstTy) ||
1114 !mlir::isa<cir::FPTypeInterface>(srcTy))
1115 return castOp.emitError() <<
"NYI cast from " << srcTy <<
" to " << dstTy;
1117 auto getFloatWidth = [](mlir::Type ty) ->
unsigned {
1118 return mlir::cast<cir::FPTypeInterface>(ty).getWidth();
1121 if (getFloatWidth(srcTy) > getFloatWidth(dstTy))
1122 rewriter.replaceOpWithNewOp<mlir::LLVM::FPTruncOp>(castOp, llvmDstTy,
1125 rewriter.replaceOpWithNewOp<mlir::LLVM::FPExtOp>(castOp, llvmDstTy,
1127 return mlir::success();
1129 case cir::CastKind::int_to_ptr: {
1130 auto dstTy = mlir::cast<cir::PointerType>(castOp.getType());
1131 mlir::Value llvmSrcVal = adaptor.getSrc();
1132 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1133 rewriter.replaceOpWithNewOp<mlir::LLVM::IntToPtrOp>(castOp, llvmDstTy,
1135 return mlir::success();
1137 case cir::CastKind::ptr_to_int: {
1138 auto dstTy = mlir::cast<cir::IntType>(castOp.getType());
1139 mlir::Value llvmSrcVal = adaptor.getSrc();
1140 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1141 rewriter.replaceOpWithNewOp<mlir::LLVM::PtrToIntOp>(castOp, llvmDstTy,
1143 return mlir::success();
1145 case cir::CastKind::float_to_bool: {
1146 mlir::Value llvmSrcVal = adaptor.getSrc();
1147 auto kind = mlir::LLVM::FCmpPredicate::une;
1150 auto zeroFloat = mlir::LLVM::ConstantOp::create(
1151 rewriter, castOp.getLoc(), llvmSrcVal.getType(),
1152 mlir::FloatAttr::get(llvmSrcVal.getType(), 0.0));
1155 rewriter.replaceOpWithNewOp<mlir::LLVM::FCmpOp>(castOp,
kind, llvmSrcVal,
1158 return mlir::success();
1160 case cir::CastKind::bool_to_int: {
1161 auto dstTy = mlir::cast<cir::IntType>(castOp.getType());
1162 mlir::Value llvmSrcVal = adaptor.getSrc();
1163 auto llvmSrcTy = mlir::cast<mlir::IntegerType>(llvmSrcVal.getType());
1165 mlir::cast<mlir::IntegerType>(getTypeConverter()->convertType(dstTy));
1166 if (llvmSrcTy.getWidth() == llvmDstTy.getWidth())
1167 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(castOp, llvmDstTy,
1170 rewriter.replaceOpWithNewOp<mlir::LLVM::ZExtOp>(castOp, llvmDstTy,
1172 return mlir::success();
1174 case cir::CastKind::bool_to_float: {
1175 mlir::Type dstTy = castOp.getType();
1176 mlir::Value llvmSrcVal = adaptor.getSrc();
1177 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1178 rewriter.replaceOpWithNewOp<mlir::LLVM::UIToFPOp>(castOp, llvmDstTy,
1180 return mlir::success();
1182 case cir::CastKind::int_to_float: {
1183 mlir::Type dstTy = castOp.getType();
1184 mlir::Value llvmSrcVal = adaptor.getSrc();
1185 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1186 if (mlir::cast<cir::IntType>(elementTypeIfVector(castOp.getSrc().getType()))
1188 rewriter.replaceOpWithNewOp<mlir::LLVM::SIToFPOp>(castOp, llvmDstTy,
1191 rewriter.replaceOpWithNewOp<mlir::LLVM::UIToFPOp>(castOp, llvmDstTy,
1193 return mlir::success();
1195 case cir::CastKind::float_to_int: {
1196 mlir::Type dstTy = castOp.getType();
1197 mlir::Value llvmSrcVal = adaptor.getSrc();
1198 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1199 if (mlir::cast<cir::IntType>(elementTypeIfVector(castOp.getType()))
1201 rewriter.replaceOpWithNewOp<mlir::LLVM::FPToSIOp>(castOp, llvmDstTy,
1204 rewriter.replaceOpWithNewOp<mlir::LLVM::FPToUIOp>(castOp, llvmDstTy,
1206 return mlir::success();
1208 case cir::CastKind::bitcast: {
1209 mlir::Type dstTy = castOp.getType();
1210 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1215 mlir::Value llvmSrcVal = adaptor.getSrc();
1216 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(castOp, llvmDstTy,
1218 return mlir::success();
1220 case cir::CastKind::ptr_to_bool: {
1221 mlir::Value llvmSrcVal = adaptor.getSrc();
1222 mlir::Value zeroPtr = mlir::LLVM::ZeroOp::create(rewriter, castOp.getLoc(),
1223 llvmSrcVal.getType());
1224 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
1225 castOp, mlir::LLVM::ICmpPredicate::ne, llvmSrcVal, zeroPtr);
1228 case cir::CastKind::address_space: {
1229 mlir::Type dstTy = castOp.getType();
1230 mlir::Value llvmSrcVal = adaptor.getSrc();
1231 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1232 rewriter.replaceOpWithNewOp<mlir::LLVM::AddrSpaceCastOp>(castOp, llvmDstTy,
1236 case cir::CastKind::member_ptr_to_bool:
1241 return castOp.emitError(
"Unhandled cast kind: ")
1242 << castOp.getKindAttrName();
1246 return mlir::success();
1249mlir::LogicalResult CIRToLLVMPtrStrideOpLowering::matchAndRewrite(
1250 cir::PtrStrideOp ptrStrideOp, OpAdaptor adaptor,
1251 mlir::ConversionPatternRewriter &rewriter)
const {
1253 const mlir::TypeConverter *tc = getTypeConverter();
1254 const mlir::Type resultTy = tc->convertType(ptrStrideOp.getType());
1256 mlir::Type elementTy =
1258 mlir::MLIRContext *ctx = elementTy.getContext();
1262 if (mlir::isa<mlir::LLVM::LLVMVoidType>(elementTy) ||
1263 mlir::isa<mlir::LLVM::LLVMFunctionType>(elementTy))
1264 elementTy = mlir::IntegerType::get(elementTy.getContext(), 8,
1265 mlir::IntegerType::Signless);
1267 mlir::Value index = adaptor.getStride();
1268 const unsigned width =
1269 mlir::cast<mlir::IntegerType>(index.getType()).getWidth();
1270 const std::optional<std::uint64_t> layoutWidth =
1271 dataLayout.getTypeIndexBitwidth(adaptor.getBase().getType());
1273 mlir::Operation *indexOp = index.getDefiningOp();
1274 if (indexOp && layoutWidth && width != *layoutWidth) {
1278 const auto sub = dyn_cast<mlir::LLVM::SubOp>(indexOp);
1279 auto unary = ptrStrideOp.getStride().getDefiningOp<cir::UnaryOp>();
1281 unary && unary.getKind() == cir::UnaryOpKind::Minus && sub;
1283 index = indexOp->getOperand(1);
1286 const auto llvmDstType = mlir::IntegerType::get(ctx, *layoutWidth);
1288 ptrStrideOp.getStride().getType().isUnsigned(),
1289 width, *layoutWidth);
1293 index = mlir::LLVM::SubOp::create(
1294 rewriter, index.getLoc(), index.getType(),
1295 mlir::LLVM::ConstantOp::create(rewriter, index.getLoc(),
1296 index.getType(), 0),
1298 rewriter.eraseOp(sub);
1302 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1303 ptrStrideOp, resultTy, elementTy, adaptor.getBase(), index);
1304 return mlir::success();
1307mlir::LogicalResult CIRToLLVMBaseClassAddrOpLowering::matchAndRewrite(
1308 cir::BaseClassAddrOp baseClassOp, OpAdaptor adaptor,
1309 mlir::ConversionPatternRewriter &rewriter)
const {
1310 const mlir::Type resultType =
1311 getTypeConverter()->convertType(baseClassOp.getType());
1312 mlir::Value derivedAddr = adaptor.getDerivedAddr();
1313 llvm::SmallVector<mlir::LLVM::GEPArg, 1> offset = {
1314 adaptor.getOffset().getZExtValue()};
1315 mlir::Type byteType = mlir::IntegerType::get(resultType.getContext(), 8,
1316 mlir::IntegerType::Signless);
1317 if (adaptor.getOffset().getZExtValue() == 0) {
1318 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(
1319 baseClassOp, resultType, adaptor.getDerivedAddr());
1320 return mlir::success();
1323 if (baseClassOp.getAssumeNotNull()) {
1324 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1325 baseClassOp, resultType, byteType, derivedAddr, offset);
1327 auto loc = baseClassOp.getLoc();
1328 mlir::Value isNull = mlir::LLVM::ICmpOp::create(
1329 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, derivedAddr,
1330 mlir::LLVM::ZeroOp::create(rewriter, loc, derivedAddr.getType()));
1331 mlir::Value adjusted = mlir::LLVM::GEPOp::create(
1332 rewriter, loc, resultType, byteType, derivedAddr, offset);
1333 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(baseClassOp, isNull,
1334 derivedAddr, adjusted);
1336 return mlir::success();
1339mlir::LogicalResult CIRToLLVMATanOpLowering::matchAndRewrite(
1340 cir::ATanOp op, OpAdaptor adaptor,
1341 mlir::ConversionPatternRewriter &rewriter)
const {
1342 mlir::Type resTy = typeConverter->convertType(op.getType());
1343 rewriter.replaceOpWithNewOp<mlir::LLVM::ATanOp>(op, resTy, adaptor.getSrc());
1344 return mlir::success();
1347mlir::LogicalResult CIRToLLVMCeilOpLowering::matchAndRewrite(
1348 cir::CeilOp op, OpAdaptor adaptor,
1349 mlir::ConversionPatternRewriter &rewriter)
const {
1350 mlir::Type resTy = typeConverter->convertType(op.getType());
1351 rewriter.replaceOpWithNewOp<mlir::LLVM::FCeilOp>(op, resTy, adaptor.getSrc());
1352 return mlir::success();
1355mlir::LogicalResult CIRToLLVMAllocaOpLowering::matchAndRewrite(
1356 cir::AllocaOp op, OpAdaptor adaptor,
1357 mlir::ConversionPatternRewriter &rewriter)
const {
1360 ? adaptor.getDynAllocSize()
1361 : mlir::LLVM::ConstantOp::create(
1362 rewriter, op.getLoc(),
1363 typeConverter->convertType(rewriter.getIndexType()), 1);
1364 mlir::Type elementTy =
1366 mlir::Type resultTy =
1372 rewriter.replaceOpWithNewOp<mlir::LLVM::AllocaOp>(
1373 op, resultTy, elementTy, size, op.getAlignmentAttr().getInt());
1375 return mlir::success();
1378mlir::LogicalResult CIRToLLVMReturnOpLowering::matchAndRewrite(
1379 cir::ReturnOp op, OpAdaptor adaptor,
1380 mlir::ConversionPatternRewriter &rewriter)
const {
1381 rewriter.replaceOpWithNewOp<mlir::LLVM::ReturnOp>(op, adaptor.getOperands());
1382 return mlir::LogicalResult::success();
1385mlir::LogicalResult CIRToLLVMRotateOpLowering::matchAndRewrite(
1386 cir::RotateOp op, OpAdaptor adaptor,
1387 mlir::ConversionPatternRewriter &rewriter)
const {
1390 mlir::Value input = adaptor.getInput();
1391 if (op.isRotateLeft())
1392 rewriter.replaceOpWithNewOp<mlir::LLVM::FshlOp>(op, input, input,
1393 adaptor.getAmount());
1395 rewriter.replaceOpWithNewOp<mlir::LLVM::FshrOp>(op, input, input,
1396 adaptor.getAmount());
1397 return mlir::LogicalResult::success();
1400static mlir::LogicalResult
1402 mlir::ConversionPatternRewriter &rewriter,
1403 const mlir::TypeConverter *converter,
1404 mlir::FlatSymbolRefAttr calleeAttr) {
1406 mlir::ValueTypeRange<mlir::ResultRange> cirResults = op->getResultTypes();
1407 auto call = cast<cir::CIRCallOpInterface>(op);
1409 if (converter->convertTypes(cirResults, llvmResults).failed())
1410 return mlir::failure();
1414 mlir::LLVM::MemoryEffectsAttr memoryEffects;
1415 bool noUnwind =
false;
1416 bool willReturn =
false;
1418 memoryEffects, noUnwind, willReturn);
1420 mlir::LLVM::LLVMFunctionType llvmFnTy;
1427 mlir::Operation *callee =
1428 mlir::SymbolTable::lookupNearestSymbolFrom(op, calleeAttr);
1429 if (
auto fn = mlir::dyn_cast<mlir::FunctionOpInterface>(callee)) {
1430 llvmFnTy = converter->convertType<mlir::LLVM::LLVMFunctionType>(
1431 fn.getFunctionType());
1432 assert(llvmFnTy &&
"Failed to convert function type");
1433 }
else if (
auto alias = mlir::cast<mlir::LLVM::AliasOp>(callee)) {
1441 auto symAttr = mlir::cast<mlir::FlatSymbolRefAttr>(calleeAttr);
1443 mlir::LLVM::AddressOfOp::create(
1444 rewriter, op->getLoc(),
1445 mlir::LLVM::LLVMPointerType::get(rewriter.getContext()), symAttr)
1447 adjustedCallOperands.push_back(addrOfAlias);
1450 llvm::append_range(adjustedCallOperands, callOperands);
1451 callOperands = adjustedCallOperands;
1455 llvmFnTy = mlir::cast<mlir::LLVM::LLVMFunctionType>(alias.getType());
1458 return op->emitError(
"Unexpected callee type!");
1461 assert(!op->getOperands().empty() &&
1462 "operands list must no be empty for the indirect call");
1463 auto calleeTy = op->getOperands().front().getType();
1464 auto calleePtrTy = cast<cir::PointerType>(calleeTy);
1465 auto calleeFuncTy = cast<cir::FuncType>(calleePtrTy.getPointee());
1466 llvm::append_range(adjustedCallOperands, callOperands);
1467 llvmFnTy = cast<mlir::LLVM::LLVMFunctionType>(
1468 converter->convertType(calleeFuncTy));
1475 auto newOp = rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(
1476 op, llvmFnTy, calleeAttr, callOperands);
1478 newOp.setMemoryEffectsAttr(memoryEffects);
1479 newOp.setNoUnwind(noUnwind);
1480 newOp.setWillReturn(willReturn);
1482 return mlir::success();
1485mlir::LogicalResult CIRToLLVMCallOpLowering::matchAndRewrite(
1486 cir::CallOp op, OpAdaptor adaptor,
1487 mlir::ConversionPatternRewriter &rewriter)
const {
1489 getTypeConverter(), op.getCalleeAttr());
1492mlir::LogicalResult CIRToLLVMReturnAddrOpLowering::matchAndRewrite(
1493 cir::ReturnAddrOp op, OpAdaptor adaptor,
1494 mlir::ConversionPatternRewriter &rewriter)
const {
1495 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
1497 llvmPtrTy, adaptor.getOperands());
1498 return mlir::success();
1501mlir::LogicalResult CIRToLLVMFrameAddrOpLowering::matchAndRewrite(
1502 cir::FrameAddrOp op, OpAdaptor adaptor,
1503 mlir::ConversionPatternRewriter &rewriter)
const {
1504 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
1506 adaptor.getOperands());
1507 return mlir::success();
1510mlir::LogicalResult CIRToLLVMLoadOpLowering::matchAndRewrite(
1511 cir::LoadOp op, OpAdaptor adaptor,
1512 mlir::ConversionPatternRewriter &rewriter)
const {
1513 const mlir::Type llvmTy =
1515 mlir::LLVM::AtomicOrdering ordering =
getLLVMMemOrder(op.getMemOrder());
1516 std::optional<size_t> opAlign = op.getAlignment();
1517 unsigned alignment =
1518 (unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmTy));
1524 mlir::LLVM::LoadOp newLoad = mlir::LLVM::LoadOp::create(
1525 rewriter, op->getLoc(), llvmTy, adaptor.getAddr(), alignment,
1526 op.getIsVolatile(),
false,
1527 false,
false, ordering);
1530 mlir::Value result =
1532 rewriter.replaceOp(op, result);
1534 return mlir::LogicalResult::success();
1537mlir::LogicalResult CIRToLLVMStoreOpLowering::matchAndRewrite(
1538 cir::StoreOp op, OpAdaptor adaptor,
1539 mlir::ConversionPatternRewriter &rewriter)
const {
1540 mlir::LLVM::AtomicOrdering memorder =
getLLVMMemOrder(op.getMemOrder());
1541 const mlir::Type llvmTy =
1542 getTypeConverter()->convertType(op.getValue().getType());
1543 std::optional<size_t> opAlign = op.getAlignment();
1544 unsigned alignment =
1545 (unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmTy));
1551 op.getValue().getType(), adaptor.getValue());
1555 mlir::LLVM::StoreOp storeOp = mlir::LLVM::StoreOp::create(
1556 rewriter, op->getLoc(), value, adaptor.getAddr(), alignment,
1558 false,
false, memorder);
1559 rewriter.replaceOp(op, storeOp);
1561 return mlir::LogicalResult::success();
1565 auto array = mlir::dyn_cast<mlir::ArrayAttr>(attr.getElts());
1566 return attr.hasTrailingZeros() ||
1567 (array && std::count_if(array.begin(), array.end(), [](
auto elt) {
1568 auto ar = dyn_cast<cir::ConstArrayAttr>(elt);
1569 return ar && hasTrailingZeros(ar);
1573mlir::LogicalResult CIRToLLVMConstantOpLowering::matchAndRewrite(
1574 cir::ConstantOp op, OpAdaptor adaptor,
1575 mlir::ConversionPatternRewriter &rewriter)
const {
1576 mlir::Attribute attr = op.getValue();
1578 if (mlir::isa<cir::PoisonAttr>(attr)) {
1579 rewriter.replaceOpWithNewOp<mlir::LLVM::PoisonOp>(
1580 op, getTypeConverter()->convertType(op.getType()));
1581 return mlir::success();
1584 if (mlir::isa<mlir::IntegerType>(op.getType())) {
1589 attr = op.getValue();
1590 }
else if (mlir::isa<cir::BoolType>(op.getType())) {
1591 int value = mlir::cast<cir::BoolAttr>(op.getValue()).getValue();
1592 attr = rewriter.getIntegerAttr(typeConverter->convertType(op.getType()),
1594 }
else if (mlir::isa<cir::IntType>(op.getType())) {
1596 if (
auto ga = mlir::dyn_cast<cir::GlobalViewAttr>(op.getValue())) {
1599 op.emitError() <<
"global view with integer type";
1600 return mlir::failure();
1603 attr = rewriter.getIntegerAttr(
1604 typeConverter->convertType(op.getType()),
1605 mlir::cast<cir::IntAttr>(op.getValue()).getValue());
1606 }
else if (mlir::isa<cir::FPTypeInterface>(op.getType())) {
1607 attr = rewriter.getFloatAttr(
1608 typeConverter->convertType(op.getType()),
1609 mlir::cast<cir::FPAttr>(op.getValue()).getValue());
1610 }
else if (mlir::isa<cir::PointerType>(op.getType())) {
1612 if (mlir::isa<cir::ConstPtrAttr>(op.getValue())) {
1613 if (mlir::cast<cir::ConstPtrAttr>(op.getValue()).isNullValue()) {
1614 rewriter.replaceOpWithNewOp<mlir::LLVM::ZeroOp>(
1615 op, typeConverter->convertType(op.getType()));
1616 return mlir::success();
1620 if (
auto gv = mlir::dyn_cast<cir::GlobalViewAttr>(op.getValue())) {
1622 rewriter.replaceOp(op, newOp);
1623 return mlir::success();
1625 attr = op.getValue();
1626 }
else if (
const auto arrTy = mlir::dyn_cast<cir::ArrayType>(op.getType())) {
1627 const auto constArr = mlir::dyn_cast<cir::ConstArrayAttr>(op.getValue());
1628 if (!constArr && !isa<cir::ZeroAttr, cir::UndefAttr>(op.getValue()))
1629 return op.emitError() <<
"array does not have a constant initializer";
1631 std::optional<mlir::Attribute> denseAttr;
1633 const mlir::Value newOp =
1635 rewriter.replaceOp(op, newOp);
1636 return mlir::success();
1637 }
else if (constArr &&
1639 attr = denseAttr.value();
1641 const mlir::Value initVal =
1643 rewriter.replaceOp(op, initVal);
1644 return mlir::success();
1646 }
else if (
const auto recordAttr =
1647 mlir::dyn_cast<cir::ConstRecordAttr>(op.getValue())) {
1649 rewriter.replaceOp(op, initVal);
1650 return mlir::success();
1651 }
else if (
const auto vecTy = mlir::dyn_cast<cir::VectorType>(op.getType())) {
1653 getTypeConverter()));
1654 return mlir::success();
1655 }
else if (
auto recTy = mlir::dyn_cast<cir::RecordType>(op.getType())) {
1656 if (mlir::isa<cir::ZeroAttr, cir::UndefAttr>(attr)) {
1657 mlir::Value initVal =
1659 rewriter.replaceOp(op, initVal);
1660 return mlir::success();
1662 return op.emitError() <<
"unsupported lowering for record constant type "
1664 }
else if (
auto complexTy = mlir::dyn_cast<cir::ComplexType>(op.getType())) {
1665 mlir::Type complexElemTy = complexTy.getElementType();
1666 mlir::Type complexElemLLVMTy = typeConverter->convertType(complexElemTy);
1668 if (
auto zeroInitAttr = mlir::dyn_cast<cir::ZeroAttr>(op.getValue())) {
1669 mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(complexElemLLVMTy);
1670 mlir::ArrayAttr array = rewriter.getArrayAttr({zeroAttr, zeroAttr});
1671 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
1672 op, getTypeConverter()->convertType(op.getType()), array);
1673 return mlir::success();
1676 auto complexAttr = mlir::cast<cir::ConstComplexAttr>(op.getValue());
1678 mlir::Attribute components[2];
1679 if (mlir::isa<cir::IntType>(complexElemTy)) {
1680 components[0] = rewriter.getIntegerAttr(
1682 mlir::cast<cir::IntAttr>(complexAttr.getReal()).getValue());
1683 components[1] = rewriter.getIntegerAttr(
1685 mlir::cast<cir::IntAttr>(complexAttr.getImag()).getValue());
1687 components[0] = rewriter.getFloatAttr(
1689 mlir::cast<cir::FPAttr>(complexAttr.getReal()).getValue());
1690 components[1] = rewriter.getFloatAttr(
1692 mlir::cast<cir::FPAttr>(complexAttr.getImag()).getValue());
1695 attr = rewriter.getArrayAttr(components);
1697 return op.emitError() <<
"unsupported constant type " << op.getType();
1700 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
1701 op, getTypeConverter()->convertType(op.getType()),
attr);
1703 return mlir::success();
1707 mlir::DataLayout layout(op.getParentOfType<mlir::ModuleOp>());
1709 if (isa<cir::VoidType>(type))
1710 type = cir::IntType::get(type.getContext(), 8,
false);
1711 return llvm::divideCeil(layout.getTypeSizeInBits(type), 8);
1714mlir::LogicalResult CIRToLLVMPrefetchOpLowering::matchAndRewrite(
1715 cir::PrefetchOp op, OpAdaptor adaptor,
1716 mlir::ConversionPatternRewriter &rewriter)
const {
1717 rewriter.replaceOpWithNewOp<mlir::LLVM::Prefetch>(
1718 op, adaptor.getAddr(), adaptor.getIsWrite(), adaptor.getLocality(),
1720 return mlir::success();
1723mlir::LogicalResult CIRToLLVMPtrDiffOpLowering::matchAndRewrite(
1724 cir::PtrDiffOp op, OpAdaptor adaptor,
1725 mlir::ConversionPatternRewriter &rewriter)
const {
1726 auto dstTy = mlir::cast<cir::IntType>(op.getType());
1727 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1729 auto lhs = mlir::LLVM::PtrToIntOp::create(rewriter, op.getLoc(), llvmDstTy,
1731 auto rhs = mlir::LLVM::PtrToIntOp::create(rewriter, op.getLoc(), llvmDstTy,
1735 mlir::LLVM::SubOp::create(rewriter, op.getLoc(), llvmDstTy, lhs, rhs);
1737 cir::PointerType ptrTy = op.getLhs().getType();
1739 uint64_t typeSize =
getTypeSize(ptrTy.getPointee(), *op);
1742 mlir::Value resultVal = diff.getResult();
1743 if (typeSize != 1) {
1744 auto typeSizeVal = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1745 llvmDstTy, typeSize);
1747 if (dstTy.isUnsigned()) {
1749 mlir::LLVM::UDivOp::create(rewriter, op.getLoc(), diff, typeSizeVal);
1750 uDiv.setIsExact(
true);
1751 resultVal = uDiv.getResult();
1754 mlir::LLVM::SDivOp::create(rewriter, op.getLoc(), diff, typeSizeVal);
1755 sDiv.setIsExact(
true);
1756 resultVal = sDiv.getResult();
1759 rewriter.replaceOp(op, resultVal);
1760 return mlir::success();
1763mlir::LogicalResult CIRToLLVMExpectOpLowering::matchAndRewrite(
1764 cir::ExpectOp op, OpAdaptor adaptor,
1765 mlir::ConversionPatternRewriter &rewriter)
const {
1769 std::optional<llvm::APFloat> prob = op.getProb();
1771 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpectWithProbabilityOp>(
1772 op, adaptor.getVal(), adaptor.getExpected(), prob.value());
1774 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpectOp>(op, adaptor.getVal(),
1775 adaptor.getExpected());
1776 return mlir::success();
1779mlir::LogicalResult CIRToLLVMFAbsOpLowering::matchAndRewrite(
1780 cir::FAbsOp op, OpAdaptor adaptor,
1781 mlir::ConversionPatternRewriter &rewriter)
const {
1782 mlir::Type resTy = typeConverter->convertType(op.getType());
1783 rewriter.replaceOpWithNewOp<mlir::LLVM::FAbsOp>(op, resTy,
1784 adaptor.getOperands()[0]);
1785 return mlir::success();
1792void CIRToLLVMFuncOpLowering::lowerFuncAttributes(
1793 cir::FuncOp func,
bool filterArgAndResAttrs,
1794 SmallVectorImpl<mlir::NamedAttribute> &result)
const {
1796 for (mlir::NamedAttribute attr : func->getAttrs()) {
1798 if (
attr.getName() == mlir::SymbolTable::getSymbolAttrName() ||
1799 attr.getName() == func.getFunctionTypeAttrName() ||
1801 attr.getName() == func.getGlobalVisibilityAttrName() ||
1802 attr.getName() == func.getDsoLocalAttrName() ||
1803 attr.getName() == func.getInlineKindAttrName() ||
1804 (filterArgAndResAttrs &&
1805 (
attr.getName() == func.getArgAttrsAttrName() ||
1806 attr.getName() == func.getResAttrsAttrName())))
1810 result.push_back(attr);
1814mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewriteAlias(
1815 cir::FuncOp op, llvm::StringRef aliasee, mlir::Type ty, OpAdaptor adaptor,
1816 mlir::ConversionPatternRewriter &rewriter)
const {
1817 SmallVector<mlir::NamedAttribute, 4> attributes;
1818 lowerFuncAttributes(op,
false, attributes);
1820 mlir::Location loc = op.getLoc();
1821 auto aliasOp = rewriter.replaceOpWithNewOp<mlir::LLVM::AliasOp>(
1822 op, ty,
convertLinkage(op.getLinkage()), op.getName(), op.getDsoLocal(),
1826 mlir::OpBuilder builder(op.getContext());
1827 mlir::Block *block = builder.createBlock(&aliasOp.getInitializerRegion());
1828 builder.setInsertionPointToStart(block);
1831 mlir::Type ptrTy = mlir::LLVM::LLVMPointerType::get(ty.getContext());
1832 auto addrOp = mlir::LLVM::AddressOfOp::create(builder, loc, ptrTy, aliasee);
1833 mlir::LLVM::ReturnOp::create(builder, loc, addrOp);
1835 return mlir::success();
1838mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewrite(
1839 cir::FuncOp op, OpAdaptor adaptor,
1840 mlir::ConversionPatternRewriter &rewriter)
const {
1842 cir::FuncType fnType = op.getFunctionType();
1843 bool isDsoLocal = op.getDsoLocal();
1844 mlir::TypeConverter::SignatureConversion signatureConversion(
1845 fnType.getNumInputs());
1847 for (
const auto &argType : llvm::enumerate(fnType.getInputs())) {
1848 mlir::Type convertedType = typeConverter->convertType(argType.value());
1850 return mlir::failure();
1851 signatureConversion.addInputs(argType.index(), convertedType);
1854 mlir::Type resultType =
1855 getTypeConverter()->convertType(fnType.getReturnType());
1858 mlir::Type llvmFnTy = mlir::LLVM::LLVMFunctionType::get(
1859 resultType ? resultType : mlir::LLVM::LLVMVoidType::get(getContext()),
1860 signatureConversion.getConvertedTypes(),
1864 if (std::optional<llvm::StringRef> aliasee = op.getAliasee())
1865 return matchAndRewriteAlias(op, *aliasee, llvmFnTy, adaptor, rewriter);
1869 mlir::Location loc = op.getLoc();
1870 if (mlir::FusedLoc fusedLoc = mlir::dyn_cast<mlir::FusedLoc>(loc))
1871 loc = fusedLoc.getLocations()[0];
1872 assert((mlir::isa<mlir::FileLineColLoc>(loc) ||
1873 mlir::isa<mlir::UnknownLoc>(loc)) &&
1874 "expected single location or unknown location here");
1878 mlir::LLVM::CConv cconv = mlir::LLVM::CConv::C;
1879 SmallVector<mlir::NamedAttribute, 4> attributes;
1880 lowerFuncAttributes(op,
false, attributes);
1882 mlir::LLVM::LLVMFuncOp fn = mlir::LLVM::LLVMFuncOp::create(
1883 rewriter, loc, op.getName(), llvmFnTy, linkage, isDsoLocal, cconv,
1884 mlir::SymbolRefAttr(), attributes);
1888 if (
auto inlineKind = op.getInlineKind()) {
1889 fn.setNoInline(inlineKind == cir::InlineKind::NoInline);
1890 fn.setInlineHint(inlineKind == cir::InlineKind::InlineHint);
1891 fn.setAlwaysInline(inlineKind == cir::InlineKind::AlwaysInline);
1894 fn.setVisibility_Attr(mlir::LLVM::VisibilityAttr::get(
1896 op.getGlobalVisibilityAttr().getValue())));
1898 rewriter.inlineRegionBefore(op.getBody(), fn.getBody(), fn.end());
1899 if (failed(rewriter.convertRegionTypes(&fn.getBody(), *typeConverter,
1900 &signatureConversion)))
1901 return mlir::failure();
1903 rewriter.eraseOp(op);
1905 return mlir::LogicalResult::success();
1908mlir::LogicalResult CIRToLLVMGetGlobalOpLowering::matchAndRewrite(
1909 cir::GetGlobalOp op, OpAdaptor adaptor,
1910 mlir::ConversionPatternRewriter &rewriter)
const {
1913 if (op->getUses().empty()) {
1914 rewriter.eraseOp(op);
1915 return mlir::success();
1918 mlir::Type
type = getTypeConverter()->convertType(op.getType());
1919 mlir::Operation *newop = mlir::LLVM::AddressOfOp::create(
1920 rewriter, op.getLoc(), type, op.getName());
1924 rewriter.replaceOp(op, newop);
1925 return mlir::success();
1930void CIRToLLVMGlobalOpLowering::setupRegionInitializedLLVMGlobalOp(
1931 cir::GlobalOp op, mlir::ConversionPatternRewriter &rewriter)
const {
1932 const mlir::Type llvmType =
1940 const bool isConst = op.getConstant();
1942 const unsigned addrSpace = 0;
1943 const bool isDsoLocal = op.getDsoLocal();
1945 const bool isThreadLocal =
false;
1946 const uint64_t alignment = op.getAlignment().value_or(0);
1947 const mlir::LLVM::Linkage linkage =
convertLinkage(op.getLinkage());
1948 const StringRef symbol = op.getSymName();
1949 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
1951 SmallVector<mlir::NamedAttribute> attributes;
1952 mlir::LLVM::GlobalOp newGlobalOp =
1953 rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
1954 op, llvmType, isConst, linkage, symbol,
nullptr, alignment, addrSpace,
1955 isDsoLocal, isThreadLocal, comdatAttr, attributes);
1956 newGlobalOp.getRegion().emplaceBlock();
1957 rewriter.setInsertionPointToEnd(newGlobalOp.getInitializerBlock());
1961CIRToLLVMGlobalOpLowering::matchAndRewriteRegionInitializedGlobal(
1962 cir::GlobalOp op, mlir::Attribute init,
1963 mlir::ConversionPatternRewriter &rewriter)
const {
1965 assert((isa<cir::ConstArrayAttr, cir::ConstRecordAttr, cir::ConstVectorAttr,
1966 cir::ConstPtrAttr, cir::ConstComplexAttr, cir::GlobalViewAttr,
1967 cir::TypeInfoAttr, cir::VTableAttr, cir::ZeroAttr>(init)));
1972 const mlir::Location loc = op.getLoc();
1973 setupRegionInitializedLLVMGlobalOp(op, rewriter);
1975 mlir::Value value = valueConverter.visit(init);
1976 mlir::LLVM::ReturnOp::create(rewriter, loc, value);
1977 return mlir::success();
1980mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite(
1981 cir::GlobalOp op, OpAdaptor adaptor,
1982 mlir::ConversionPatternRewriter &rewriter)
const {
1985 if (!op.getCtorRegion().empty() || !op.getDtorRegion().empty())
1986 return op.emitError() <<
"GlobalOp ctor and dtor regions should be removed "
1987 "in LoweringPrepare";
1989 std::optional<mlir::Attribute> init = op.getInitialValue();
1992 const mlir::Type cirSymType = op.getSymType();
1995 const mlir::Type llvmType =
2000 const bool isConst =
false;
2002 const unsigned addrSpace = 0;
2003 const bool isDsoLocal = op.getDsoLocal();
2005 const bool isThreadLocal =
false;
2006 const uint64_t alignment = op.getAlignment().value_or(0);
2007 const mlir::LLVM::Linkage linkage =
convertLinkage(op.getLinkage());
2008 const StringRef symbol = op.getSymName();
2009 SmallVector<mlir::NamedAttribute> attributes;
2011 if (init.has_value()) {
2012 if (mlir::isa<cir::FPAttr, cir::IntAttr, cir::BoolAttr>(init.value())) {
2014 init = initRewriter.visit(init.value());
2019 if (!init.value()) {
2020 op.emitError() <<
"unsupported initializer '" << init.value() <<
"'";
2021 return mlir::failure();
2023 }
else if (mlir::isa<cir::ConstArrayAttr, cir::ConstVectorAttr,
2024 cir::ConstRecordAttr, cir::ConstPtrAttr,
2025 cir::ConstComplexAttr, cir::GlobalViewAttr,
2026 cir::TypeInfoAttr, cir::VTableAttr, cir::ZeroAttr>(
2031 return matchAndRewriteRegionInitializedGlobal(op, init.value(), rewriter);
2035 op.emitError() <<
"unsupported initializer '" << init.value() <<
"'";
2036 return mlir::failure();
2041 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
2042 auto newOp = rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
2043 op, llvmType, isConst, linkage, symbol, init.value_or(mlir::Attribute()),
2044 alignment, addrSpace, isDsoLocal, isThreadLocal, comdatAttr, attributes);
2045 newOp.setVisibility_Attr(mlir::LLVM::VisibilityAttr::get(
2047 op.getGlobalVisibilityAttr().getValue())));
2049 return mlir::success();
2053CIRToLLVMGlobalOpLowering::getComdatAttr(cir::GlobalOp &op,
2054 mlir::OpBuilder &builder)
const {
2055 if (!op.getComdat())
2056 return mlir::SymbolRefAttr{};
2058 mlir::ModuleOp module = op->getParentOfType<mlir::ModuleOp>();
2059 mlir::OpBuilder::InsertionGuard guard(builder);
2060 StringRef comdatName(
"__llvm_comdat_globals");
2062 builder.setInsertionPointToStart(module.getBody());
2064 mlir::LLVM::ComdatOp::create(builder, module.getLoc(), comdatName);
2067 if (
auto comdatSelector = comdatOp.lookupSymbol<mlir::LLVM::ComdatSelectorOp>(
2069 return mlir::SymbolRefAttr::get(
2070 builder.getContext(), comdatName,
2071 mlir::FlatSymbolRefAttr::get(comdatSelector.getSymNameAttr()));
2074 builder.setInsertionPointToStart(&comdatOp.getBody().back());
2075 auto selectorOp = mlir::LLVM::ComdatSelectorOp::create(
2076 builder, comdatOp.getLoc(), op.getSymName(),
2077 mlir::LLVM::comdat::Comdat::Any);
2078 return mlir::SymbolRefAttr::get(
2079 builder.getContext(), comdatName,
2080 mlir::FlatSymbolRefAttr::get(selectorOp.getSymNameAttr()));
2083mlir::LogicalResult CIRToLLVMSwitchFlatOpLowering::matchAndRewrite(
2084 cir::SwitchFlatOp op, OpAdaptor adaptor,
2085 mlir::ConversionPatternRewriter &rewriter)
const {
2087 llvm::SmallVector<mlir::APInt, 8> caseValues;
2088 for (mlir::Attribute val : op.getCaseValues()) {
2089 auto intAttr = cast<cir::IntAttr>(val);
2090 caseValues.push_back(intAttr.getValue());
2093 llvm::SmallVector<mlir::Block *, 8> caseDestinations;
2094 llvm::SmallVector<mlir::ValueRange, 8> caseOperands;
2096 for (mlir::Block *x : op.getCaseDestinations())
2097 caseDestinations.push_back(x);
2099 for (mlir::OperandRange x : op.getCaseOperands())
2100 caseOperands.push_back(x);
2103 rewriter.setInsertionPoint(op);
2104 rewriter.replaceOpWithNewOp<mlir::LLVM::SwitchOp>(
2105 op, adaptor.getCondition(), op.getDefaultDestination(),
2106 op.getDefaultOperands(), caseValues, caseDestinations, caseOperands);
2107 return mlir::success();
2110mlir::LogicalResult CIRToLLVMUnaryOpLowering::matchAndRewrite(
2111 cir::UnaryOp op, OpAdaptor adaptor,
2112 mlir::ConversionPatternRewriter &rewriter)
const {
2113 assert(op.getType() == op.getInput().getType() &&
2114 "Unary operation's operand type and result type are different");
2115 mlir::Type
type = op.getType();
2116 mlir::Type elementType = elementTypeIfVector(type);
2117 bool isVector = mlir::isa<cir::VectorType>(type);
2118 mlir::Type llvmType = getTypeConverter()->convertType(type);
2119 mlir::Location loc = op.getLoc();
2122 if (mlir::isa<cir::IntType>(elementType)) {
2123 mlir::LLVM::IntegerOverflowFlags maybeNSW =
2124 op.getNoSignedWrap() ? mlir::LLVM::IntegerOverflowFlags::nsw
2125 : mlir::LLVM::IntegerOverflowFlags::none;
2126 switch (op.getKind()) {
2127 case cir::UnaryOpKind::Inc: {
2128 assert(!
isVector &&
"++ not allowed on vector types");
2129 auto one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
2130 rewriter.replaceOpWithNewOp<mlir::LLVM::AddOp>(
2131 op, llvmType, adaptor.getInput(), one, maybeNSW);
2132 return mlir::success();
2134 case cir::UnaryOpKind::Dec: {
2135 assert(!
isVector &&
"-- not allowed on vector types");
2136 auto one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
2137 rewriter.replaceOpWithNewOp<mlir::LLVM::SubOp>(op, adaptor.getInput(),
2139 return mlir::success();
2141 case cir::UnaryOpKind::Plus:
2142 rewriter.replaceOp(op, adaptor.getInput());
2143 return mlir::success();
2144 case cir::UnaryOpKind::Minus: {
2147 zero = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmType);
2149 zero = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 0);
2150 rewriter.replaceOpWithNewOp<mlir::LLVM::SubOp>(
2151 op, zero, adaptor.getInput(), maybeNSW);
2152 return mlir::success();
2154 case cir::UnaryOpKind::Not: {
2156 mlir::Value minusOne;
2159 mlir::dyn_cast<cir::VectorType>(type).getSize();
2160 std::vector<int32_t> values(numElements, -1);
2161 mlir::DenseIntElementsAttr denseVec = rewriter.getI32VectorAttr(values);
2163 mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, denseVec);
2165 minusOne = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, -1);
2167 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getInput(),
2169 return mlir::success();
2172 llvm_unreachable(
"Unexpected unary op for int");
2176 if (mlir::isa<cir::FPTypeInterface>(elementType)) {
2177 switch (op.getKind()) {
2178 case cir::UnaryOpKind::Inc: {
2179 assert(!
isVector &&
"++ not allowed on vector types");
2180 mlir::LLVM::ConstantOp one = mlir::LLVM::ConstantOp::create(
2181 rewriter, loc, llvmType, rewriter.getFloatAttr(llvmType, 1.0));
2182 rewriter.replaceOpWithNewOp<mlir::LLVM::FAddOp>(op, llvmType, one,
2183 adaptor.getInput());
2184 return mlir::success();
2186 case cir::UnaryOpKind::Dec: {
2187 assert(!
isVector &&
"-- not allowed on vector types");
2188 mlir::LLVM::ConstantOp minusOne = mlir::LLVM::ConstantOp::create(
2189 rewriter, loc, llvmType, rewriter.getFloatAttr(llvmType, -1.0));
2190 rewriter.replaceOpWithNewOp<mlir::LLVM::FAddOp>(op, llvmType, minusOne,
2191 adaptor.getInput());
2192 return mlir::success();
2194 case cir::UnaryOpKind::Plus:
2195 rewriter.replaceOp(op, adaptor.getInput());
2196 return mlir::success();
2197 case cir::UnaryOpKind::Minus:
2198 rewriter.replaceOpWithNewOp<mlir::LLVM::FNegOp>(op, llvmType,
2199 adaptor.getInput());
2200 return mlir::success();
2201 case cir::UnaryOpKind::Not:
2202 return op.emitError() <<
"Unary not is invalid for floating-point types";
2204 llvm_unreachable(
"Unexpected unary op for float");
2209 if (mlir::isa<cir::BoolType>(elementType)) {
2210 switch (op.getKind()) {
2211 case cir::UnaryOpKind::Inc:
2212 case cir::UnaryOpKind::Dec:
2213 case cir::UnaryOpKind::Plus:
2214 case cir::UnaryOpKind::Minus:
2217 return op.emitError() <<
"Unsupported unary operation on boolean type";
2218 case cir::UnaryOpKind::Not: {
2219 assert(!
isVector &&
"NYI: op! on vector mask");
2220 auto one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
2221 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getInput(),
2223 return mlir::success();
2226 llvm_unreachable(
"Unexpected unary op for bool");
2231 if (mlir::isa<cir::PointerType>(elementType)) {
2232 switch (op.getKind()) {
2233 case cir::UnaryOpKind::Plus:
2234 rewriter.replaceOp(op, adaptor.getInput());
2235 return mlir::success();
2237 op.emitError() <<
"Unknown pointer unary operation during CIR lowering";
2238 return mlir::failure();
2242 return op.emitError() <<
"Unary operation has unsupported type: "
2246mlir::LLVM::IntegerOverflowFlags
2247CIRToLLVMBinOpLowering::getIntOverflowFlag(cir::BinOp op)
const {
2248 if (op.getNoUnsignedWrap())
2249 return mlir::LLVM::IntegerOverflowFlags::nuw;
2251 if (op.getNoSignedWrap())
2252 return mlir::LLVM::IntegerOverflowFlags::nsw;
2254 return mlir::LLVM::IntegerOverflowFlags::none;
2259 return mlir::isa<cir::IntType>(type)
2260 ? mlir::cast<cir::IntType>(type).isUnsigned()
2261 : mlir::cast<mlir::IntegerType>(type).isUnsigned();
2264mlir::LogicalResult CIRToLLVMBinOpLowering::matchAndRewrite(
2265 cir::BinOp op, OpAdaptor adaptor,
2266 mlir::ConversionPatternRewriter &rewriter)
const {
2267 if (adaptor.getLhs().getType() != adaptor.getRhs().getType())
2268 return op.emitError() <<
"inconsistent operands' types not supported yet";
2270 mlir::Type type = op.getRhs().getType();
2271 if (!mlir::isa<cir::IntType, cir::BoolType, cir::FPTypeInterface,
2272 mlir::IntegerType, cir::VectorType>(type))
2273 return op.emitError() <<
"operand type not supported yet";
2275 const mlir::Type llvmTy = getTypeConverter()->convertType(op.getType());
2276 const mlir::Type llvmEltTy = elementTypeIfVector(llvmTy);
2278 const mlir::Value rhs = adaptor.getRhs();
2279 const mlir::Value lhs = adaptor.getLhs();
2280 type = elementTypeIfVector(type);
2282 switch (op.getKind()) {
2283 case cir::BinOpKind::Add:
2284 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
2285 if (op.getSaturated()) {
2287 rewriter.replaceOpWithNewOp<mlir::LLVM::UAddSat>(op, lhs, rhs);
2290 rewriter.replaceOpWithNewOp<mlir::LLVM::SAddSat>(op, lhs, rhs);
2293 rewriter.replaceOpWithNewOp<mlir::LLVM::AddOp>(op, llvmTy, lhs, rhs,
2294 getIntOverflowFlag(op));
2296 rewriter.replaceOpWithNewOp<mlir::LLVM::FAddOp>(op, lhs, rhs);
2299 case cir::BinOpKind::Sub:
2300 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
2301 if (op.getSaturated()) {
2303 rewriter.replaceOpWithNewOp<mlir::LLVM::USubSat>(op, lhs, rhs);
2306 rewriter.replaceOpWithNewOp<mlir::LLVM::SSubSat>(op, lhs, rhs);
2309 rewriter.replaceOpWithNewOp<mlir::LLVM::SubOp>(op, llvmTy, lhs, rhs,
2310 getIntOverflowFlag(op));
2312 rewriter.replaceOpWithNewOp<mlir::LLVM::FSubOp>(op, lhs, rhs);
2315 case cir::BinOpKind::Mul:
2316 if (mlir::isa<mlir::IntegerType>(llvmEltTy))
2317 rewriter.replaceOpWithNewOp<mlir::LLVM::MulOp>(op, llvmTy, lhs, rhs,
2318 getIntOverflowFlag(op));
2320 rewriter.replaceOpWithNewOp<mlir::LLVM::FMulOp>(op, lhs, rhs);
2322 case cir::BinOpKind::Div:
2323 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
2326 rewriter.replaceOpWithNewOp<mlir::LLVM::UDivOp>(op, lhs, rhs);
2328 rewriter.replaceOpWithNewOp<mlir::LLVM::SDivOp>(op, lhs, rhs);
2330 rewriter.replaceOpWithNewOp<mlir::LLVM::FDivOp>(op, lhs, rhs);
2333 case cir::BinOpKind::Rem:
2334 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
2337 rewriter.replaceOpWithNewOp<mlir::LLVM::URemOp>(op, lhs, rhs);
2339 rewriter.replaceOpWithNewOp<mlir::LLVM::SRemOp>(op, lhs, rhs);
2341 rewriter.replaceOpWithNewOp<mlir::LLVM::FRemOp>(op, lhs, rhs);
2344 case cir::BinOpKind::And:
2345 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(op, lhs, rhs);
2347 case cir::BinOpKind::Or:
2348 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(op, lhs, rhs);
2350 case cir::BinOpKind::Xor:
2351 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, lhs, rhs);
2353 case cir::BinOpKind::Max:
2354 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
2357 rewriter.replaceOpWithNewOp<mlir::LLVM::UMaxOp>(op, llvmTy, lhs, rhs);
2359 rewriter.replaceOpWithNewOp<mlir::LLVM::SMaxOp>(op, llvmTy, lhs, rhs);
2363 return mlir::LogicalResult::success();
2367static mlir::LLVM::ICmpPredicate
2369 using CIR = cir::CmpOpKind;
2370 using LLVMICmp = mlir::LLVM::ICmpPredicate;
2373 return LLVMICmp::eq;
2375 return LLVMICmp::ne;
2377 return (isSigned ? LLVMICmp::slt : LLVMICmp::ult);
2379 return (isSigned ? LLVMICmp::sle : LLVMICmp::ule);
2381 return (isSigned ? LLVMICmp::sgt : LLVMICmp::ugt);
2383 return (isSigned ? LLVMICmp::sge : LLVMICmp::uge);
2385 llvm_unreachable(
"Unknown CmpOpKind");
2390static mlir::LLVM::FCmpPredicate
2392 using CIR = cir::CmpOpKind;
2393 using LLVMFCmp = mlir::LLVM::FCmpPredicate;
2396 return LLVMFCmp::oeq;
2398 return LLVMFCmp::une;
2400 return LLVMFCmp::olt;
2402 return LLVMFCmp::ole;
2404 return LLVMFCmp::ogt;
2406 return LLVMFCmp::oge;
2408 llvm_unreachable(
"Unknown CmpOpKind");
2411mlir::LogicalResult CIRToLLVMCmpOpLowering::matchAndRewrite(
2412 cir::CmpOp cmpOp, OpAdaptor adaptor,
2413 mlir::ConversionPatternRewriter &rewriter)
const {
2414 mlir::Type type = cmpOp.getLhs().getType();
2419 if (mlir::isa<cir::IntType, mlir::IntegerType>(type)) {
2420 bool isSigned = mlir::isa<cir::IntType>(type)
2421 ? mlir::cast<cir::IntType>(type).isSigned()
2422 : mlir::cast<mlir::IntegerType>(type).isSigned();
2423 mlir::LLVM::ICmpPredicate kind =
2425 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
2426 cmpOp, kind, adaptor.getLhs(), adaptor.getRhs());
2427 return mlir::success();
2430 if (
auto ptrTy = mlir::dyn_cast<cir::PointerType>(type)) {
2431 mlir::LLVM::ICmpPredicate kind =
2434 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
2435 cmpOp, kind, adaptor.getLhs(), adaptor.getRhs());
2436 return mlir::success();
2439 if (
auto vptrTy = mlir::dyn_cast<cir::VPtrType>(type)) {
2443 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
2444 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
2445 return mlir::success();
2448 if (mlir::isa<cir::FPTypeInterface>(type)) {
2449 mlir::LLVM::FCmpPredicate
kind =
2451 rewriter.replaceOpWithNewOp<mlir::LLVM::FCmpOp>(
2452 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
2453 return mlir::success();
2456 if (mlir::isa<cir::ComplexType>(type)) {
2457 mlir::Value lhs = adaptor.getLhs();
2458 mlir::Value rhs = adaptor.getRhs();
2459 mlir::Location loc = cmpOp.getLoc();
2461 auto complexType = mlir::cast<cir::ComplexType>(cmpOp.getLhs().getType());
2462 mlir::Type complexElemTy =
2463 getTypeConverter()->convertType(
complexType.getElementType());
2465 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
2466 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{0}));
2467 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
2468 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{1}));
2469 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
2470 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{0}));
2471 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
2472 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{1}));
2474 if (cmpOp.getKind() == cir::CmpOpKind::eq) {
2475 if (complexElemTy.isInteger()) {
2476 auto realCmp = mlir::LLVM::ICmpOp::create(
2477 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, lhsReal, rhsReal);
2478 auto imagCmp = mlir::LLVM::ICmpOp::create(
2479 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, lhsImag, rhsImag);
2480 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, imagCmp);
2481 return mlir::success();
2484 auto realCmp = mlir::LLVM::FCmpOp::create(
2485 rewriter, loc, mlir::LLVM::FCmpPredicate::oeq, lhsReal, rhsReal);
2486 auto imagCmp = mlir::LLVM::FCmpOp::create(
2487 rewriter, loc, mlir::LLVM::FCmpPredicate::oeq, lhsImag, rhsImag);
2488 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, imagCmp);
2489 return mlir::success();
2492 if (cmpOp.getKind() == cir::CmpOpKind::ne) {
2493 if (complexElemTy.isInteger()) {
2494 auto realCmp = mlir::LLVM::ICmpOp::create(
2495 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, lhsReal, rhsReal);
2496 auto imagCmp = mlir::LLVM::ICmpOp::create(
2497 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, lhsImag, rhsImag);
2498 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp);
2499 return mlir::success();
2502 auto realCmp = mlir::LLVM::FCmpOp::create(
2503 rewriter, loc, mlir::LLVM::FCmpPredicate::une, lhsReal, rhsReal);
2504 auto imagCmp = mlir::LLVM::FCmpOp::create(
2505 rewriter, loc, mlir::LLVM::FCmpPredicate::une, lhsImag, rhsImag);
2506 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp);
2507 return mlir::success();
2511 return cmpOp.emitError() <<
"unsupported type for CmpOp: " <<
type;
2514mlir::LogicalResult CIRToLLVMShiftOpLowering::matchAndRewrite(
2515 cir::ShiftOp op, OpAdaptor adaptor,
2516 mlir::ConversionPatternRewriter &rewriter)
const {
2517 assert((op.getValue().getType() == op.getType()) &&
2518 "inconsistent operands' types NYI");
2520 const mlir::Type llvmTy = getTypeConverter()->convertType(op.getType());
2521 mlir::Value amt = adaptor.getAmount();
2522 mlir::Value val = adaptor.getValue();
2524 auto cirAmtTy = mlir::dyn_cast<cir::IntType>(op.getAmount().getType());
2527 auto cirValTy = mlir::cast<cir::IntType>(op.getValue().getType());
2535 amt =
getLLVMIntCast(rewriter, amt, llvmTy,
true, cirAmtTy.getWidth(),
2536 cirValTy.getWidth());
2538 auto cirValVTy = mlir::cast<cir::VectorType>(op.getValue().getType());
2540 mlir::cast<cir::IntType>(cirValVTy.getElementType()).isUnsigned();
2544 if (op.getIsShiftleft()) {
2545 rewriter.replaceOpWithNewOp<mlir::LLVM::ShlOp>(op, llvmTy, val, amt);
2546 return mlir::success();
2550 rewriter.replaceOpWithNewOp<mlir::LLVM::LShrOp>(op, llvmTy, val, amt);
2552 rewriter.replaceOpWithNewOp<mlir::LLVM::AShrOp>(op, llvmTy, val, amt);
2553 return mlir::success();
2556mlir::LogicalResult CIRToLLVMSelectOpLowering::matchAndRewrite(
2557 cir::SelectOp op, OpAdaptor adaptor,
2558 mlir::ConversionPatternRewriter &rewriter)
const {
2559 auto getConstantBool = [](mlir::Value value) -> cir::BoolAttr {
2560 auto definingOp = value.getDefiningOp<cir::ConstantOp>();
2564 auto constValue = definingOp.getValueAttr<cir::BoolAttr>();
2574 if (mlir::isa<cir::BoolType>(op.getTrueValue().getType())) {
2575 cir::BoolAttr trueValue = getConstantBool(op.getTrueValue());
2576 cir::BoolAttr falseValue = getConstantBool(op.getFalseValue());
2577 if (falseValue && !falseValue.getValue()) {
2579 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(op, adaptor.getCondition(),
2580 adaptor.getTrueValue());
2581 return mlir::success();
2583 if (trueValue && trueValue.getValue()) {
2585 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(op, adaptor.getCondition(),
2586 adaptor.getFalseValue());
2587 return mlir::success();
2591 mlir::Value llvmCondition = adaptor.getCondition();
2592 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(
2593 op, llvmCondition, adaptor.getTrueValue(), adaptor.getFalseValue());
2595 return mlir::success();
2599 mlir::DataLayout &dataLayout) {
2600 converter.addConversion([&](cir::PointerType type) -> mlir::Type {
2601 unsigned addrSpace =
2602 type.getAddrSpace() ? type.getAddrSpace().getValue().getUInt() : 0;
2603 return mlir::LLVM::LLVMPointerType::get(type.getContext(), addrSpace);
2605 converter.addConversion([&](cir::VPtrType type) -> mlir::Type {
2607 return mlir::LLVM::LLVMPointerType::get(type.getContext());
2609 converter.addConversion([&](cir::ArrayType type) -> mlir::Type {
2612 return mlir::LLVM::LLVMArrayType::get(ty, type.getSize());
2614 converter.addConversion([&](cir::VectorType type) -> mlir::Type {
2615 const mlir::Type ty = converter.convertType(type.getElementType());
2616 return mlir::VectorType::get(type.getSize(), ty);
2618 converter.addConversion([&](cir::BoolType type) -> mlir::Type {
2619 return mlir::IntegerType::get(type.getContext(), 1,
2620 mlir::IntegerType::Signless);
2622 converter.addConversion([&](cir::IntType type) -> mlir::Type {
2624 return mlir::IntegerType::get(type.getContext(), type.getWidth());
2626 converter.addConversion([&](cir::SingleType type) -> mlir::Type {
2627 return mlir::Float32Type::get(type.getContext());
2629 converter.addConversion([&](cir::DoubleType type) -> mlir::Type {
2630 return mlir::Float64Type::get(type.getContext());
2632 converter.addConversion([&](cir::FP80Type type) -> mlir::Type {
2633 return mlir::Float80Type::get(type.getContext());
2635 converter.addConversion([&](cir::FP128Type type) -> mlir::Type {
2636 return mlir::Float128Type::get(type.getContext());
2638 converter.addConversion([&](cir::LongDoubleType type) -> mlir::Type {
2639 return converter.convertType(type.getUnderlying());
2641 converter.addConversion([&](cir::FP16Type type) -> mlir::Type {
2642 return mlir::Float16Type::get(type.getContext());
2644 converter.addConversion([&](cir::BF16Type type) -> mlir::Type {
2645 return mlir::BFloat16Type::get(type.getContext());
2647 converter.addConversion([&](cir::ComplexType type) -> mlir::Type {
2650 mlir::Type elementTy = converter.convertType(type.getElementType());
2651 mlir::Type structFields[2] = {elementTy, elementTy};
2652 return mlir::LLVM::LLVMStructType::getLiteral(type.getContext(),
2655 converter.addConversion([&](cir::FuncType type) -> std::optional<mlir::Type> {
2656 auto result = converter.convertType(type.getReturnType());
2658 arguments.reserve(type.getNumInputs());
2659 if (converter.convertTypes(type.getInputs(), arguments).failed())
2660 return std::nullopt;
2661 auto varArg = type.isVarArg();
2662 return mlir::LLVM::LLVMFunctionType::get(result, arguments, varArg);
2664 converter.addConversion([&](cir::RecordType type) -> mlir::Type {
2667 switch (type.getKind()) {
2668 case cir::RecordType::Class:
2669 case cir::RecordType::Struct:
2670 for (mlir::Type ty : type.getMembers())
2674 case cir::RecordType::Union:
2675 if (
auto largestMember = type.getLargestMember(dataLayout))
2676 llvmMembers.push_back(
2678 if (type.getPadded()) {
2679 auto last = *type.getMembers().rbegin();
2680 llvmMembers.push_back(
2687 mlir::LLVM::LLVMStructType llvmStruct;
2688 if (type.getName()) {
2689 llvmStruct = mlir::LLVM::LLVMStructType::getIdentified(
2690 type.getContext(), type.getPrefixedName());
2691 if (llvmStruct.setBody(llvmMembers, type.getPacked()).failed())
2692 llvm_unreachable(
"Failed to set body of record");
2694 llvmStruct = mlir::LLVM::LLVMStructType::getLiteral(
2695 type.getContext(), llvmMembers, type.getPacked());
2700 converter.addConversion([&](cir::VoidType type) -> mlir::Type {
2701 return mlir::LLVM::LLVMVoidType::get(type.getContext());
2706 mlir::ModuleOp module, StringRef globalXtorName, StringRef llvmXtorName,
2707 llvm::function_ref<std::pair<StringRef, int>(mlir::Attribute)> createXtor) {
2709 for (
const mlir::NamedAttribute namedAttr : module->getAttrs()) {
2710 if (namedAttr.getName() == globalXtorName) {
2711 for (
auto attr : mlir::cast<mlir::ArrayAttr>(namedAttr.getValue()))
2712 globalXtors.emplace_back(createXtor(attr));
2717 if (globalXtors.empty())
2720 mlir::OpBuilder builder(module.getContext());
2721 builder.setInsertionPointToEnd(&module.getBodyRegion().back());
2725 auto ctorPFTy = mlir::LLVM::LLVMPointerType::get(builder.getContext());
2727 ctorStructFields.push_back(builder.getI32Type());
2728 ctorStructFields.push_back(ctorPFTy);
2729 ctorStructFields.push_back(ctorPFTy);
2731 auto ctorStructTy = mlir::LLVM::LLVMStructType::getLiteral(
2732 builder.getContext(), ctorStructFields);
2733 auto ctorStructArrayTy =
2734 mlir::LLVM::LLVMArrayType::get(ctorStructTy, globalXtors.size());
2736 mlir::Location loc =
module.getLoc();
2737 auto newGlobalOp = mlir::LLVM::GlobalOp::create(
2738 builder, loc, ctorStructArrayTy,
false,
2739 mlir::LLVM::Linkage::Appending, llvmXtorName, mlir::Attribute());
2741 builder.createBlock(&newGlobalOp.getRegion());
2742 builder.setInsertionPointToEnd(newGlobalOp.getInitializerBlock());
2744 mlir::Value result =
2745 mlir::LLVM::UndefOp::create(builder, loc, ctorStructArrayTy);
2747 for (
auto [index, fn] : llvm::enumerate(globalXtors)) {
2748 mlir::Value structInit =
2749 mlir::LLVM::UndefOp::create(builder, loc, ctorStructTy);
2750 mlir::Value initPriority = mlir::LLVM::ConstantOp::create(
2751 builder, loc, ctorStructFields[0], fn.second);
2752 mlir::Value initFuncAddr = mlir::LLVM::AddressOfOp::create(
2753 builder, loc, ctorStructFields[1], fn.first);
2754 mlir::Value initAssociate =
2755 mlir::LLVM::ZeroOp::create(builder, loc, ctorStructFields[2]);
2758 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
2759 initPriority, zero);
2760 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
2763 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
2765 result = mlir::LLVM::InsertValueOp::create(builder, loc, result, structInit,
2769 mlir::LLVM::ReturnOp::create(builder, loc, result);
2807 parent->walk([&](mlir::Block *blk) {
2808 if (blk->hasNoPredecessors() && !blk->isEntryBlock())
2809 unreachableBlocks.push_back(blk);
2812 std::set<mlir::Block *> visited;
2813 for (mlir::Block *root : unreachableBlocks) {
2816 std::deque<mlir::Block *> workList;
2817 workList.push_back(root);
2819 while (!workList.empty()) {
2820 mlir::Block *blk = workList.back();
2821 workList.pop_back();
2822 if (visited.count(blk))
2824 visited.emplace(blk);
2826 for (mlir::Operation &op : *blk)
2829 for (mlir::Block *succ : blk->getSuccessors())
2830 workList.push_back(succ);
2835mlir::LogicalResult CIRToLLVMObjSizeOpLowering::matchAndRewrite(
2836 cir::ObjSizeOp op, OpAdaptor adaptor,
2837 mlir::ConversionPatternRewriter &rewriter)
const {
2838 mlir::Type llvmResTy = getTypeConverter()->convertType(op.getType());
2839 mlir::Location loc = op->getLoc();
2841 mlir::IntegerType i1Ty = rewriter.getI1Type();
2843 auto i1Val = [&rewriter, &loc, &i1Ty](
bool val) {
2844 return mlir::LLVM::ConstantOp::create(rewriter, loc, i1Ty, val);
2851 i1Val(op.getNullunknown()),
2852 i1Val(op.getDynamic()),
2855 return mlir::LogicalResult::success();
2860 if (mlir::Attribute tripleAttr =
2861 module->getAttr(cir::CIRDialect::getTripleAttrName()))
2862 module->setAttr(mlir::LLVM::LLVMDialect::getTargetTripleAttrName(),
2865 if (mlir::Attribute asmAttr =
2866 module->getAttr(cir::CIRDialect::getModuleLevelAsmAttrName()))
2867 module->setAttr(mlir::LLVM::LLVMDialect::getModuleLevelAsmAttrName(),
2872 llvm::TimeTraceScope scope(
"Convert CIR to LLVM Pass");
2874 mlir::ModuleOp module = getOperation();
2875 mlir::DataLayout dl(module);
2876 mlir::LLVMTypeConverter converter(&getContext());
2879 mlir::RewritePatternSet patterns(&getContext());
2882#define GET_LLVM_LOWERING_PATTERNS_LIST
2883#include "clang/CIR/Dialect/IR/CIRLowering.inc"
2884#undef GET_LLVM_LOWERING_PATTERNS_LIST
2885 >(converter, patterns.getContext(), dl);
2889 mlir::ConversionTarget target(getContext());
2890 target.addLegalOp<mlir::ModuleOp>();
2891 target.addLegalDialect<mlir::LLVM::LLVMDialect>();
2892 target.addIllegalDialect<mlir::BuiltinDialect, cir::CIRDialect,
2893 mlir::func::FuncDialect>();
2896 ops.push_back(module);
2899 if (failed(applyPartialConversion(ops, target, std::move(patterns))))
2900 signalPassFailure();
2904 "llvm.global_ctors", [](mlir::Attribute attr) {
2905 auto ctorAttr = mlir::cast<cir::GlobalCtorAttr>(attr);
2906 return std::make_pair(ctorAttr.getName(),
2907 ctorAttr.getPriority());
2911 "llvm.global_dtors", [](mlir::Attribute attr) {
2912 auto dtorAttr = mlir::cast<cir::GlobalDtorAttr>(attr);
2913 return std::make_pair(dtorAttr.getName(),
2914 dtorAttr.getPriority());
2918mlir::LogicalResult CIRToLLVMBrOpLowering::matchAndRewrite(
2919 cir::BrOp op, OpAdaptor adaptor,
2920 mlir::ConversionPatternRewriter &rewriter)
const {
2921 rewriter.replaceOpWithNewOp<mlir::LLVM::BrOp>(op, adaptor.getOperands(),
2923 return mlir::LogicalResult::success();
2926mlir::LogicalResult CIRToLLVMGetMemberOpLowering::matchAndRewrite(
2927 cir::GetMemberOp op, OpAdaptor adaptor,
2928 mlir::ConversionPatternRewriter &rewriter)
const {
2929 mlir::Type llResTy = getTypeConverter()->convertType(op.getType());
2930 const auto recordTy =
2931 mlir::cast<cir::RecordType>(op.getAddrTy().getPointee());
2932 assert(recordTy &&
"expected record type");
2934 switch (recordTy.getKind()) {
2935 case cir::RecordType::Class:
2936 case cir::RecordType::Struct: {
2940 const mlir::Type elementTy = getTypeConverter()->convertType(recordTy);
2941 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, llResTy, elementTy,
2942 adaptor.getAddr(), offset);
2943 return mlir::success();
2945 case cir::RecordType::Union:
2948 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(op, llResTy,
2950 return mlir::success();
2954mlir::LogicalResult CIRToLLVMUnreachableOpLowering::matchAndRewrite(
2955 cir::UnreachableOp op, OpAdaptor adaptor,
2956 mlir::ConversionPatternRewriter &rewriter)
const {
2957 rewriter.replaceOpWithNewOp<mlir::LLVM::UnreachableOp>(op);
2958 return mlir::success();
2962 mlir::Operation *srcOp, llvm::StringRef fnName,
2964 auto modOp = srcOp->getParentOfType<mlir::ModuleOp>();
2965 auto enclosingFnOp = srcOp->getParentOfType<mlir::LLVM::LLVMFuncOp>();
2966 mlir::Operation *sourceSymbol =
2967 mlir::SymbolTable::lookupSymbolIn(modOp, fnName);
2968 if (!sourceSymbol) {
2969 mlir::OpBuilder::InsertionGuard guard(rewriter);
2970 rewriter.setInsertionPoint(enclosingFnOp);
2971 mlir::LLVM::LLVMFuncOp::create(rewriter, srcOp->getLoc(), fnName, fnTy);
2975mlir::LogicalResult CIRToLLVMThrowOpLowering::matchAndRewrite(
2976 cir::ThrowOp op, OpAdaptor adaptor,
2977 mlir::ConversionPatternRewriter &rewriter)
const {
2978 mlir::Location loc = op.getLoc();
2979 auto voidTy = mlir::LLVM::LLVMVoidType::get(getContext());
2981 if (op.rethrows()) {
2982 auto funcTy = mlir::LLVM::LLVMFunctionType::get(voidTy, {});
2985 const llvm::StringRef functionName =
"__cxa_rethrow";
2988 auto cxaRethrow = mlir::LLVM::CallOp::create(
2989 rewriter, loc, mlir::TypeRange{}, functionName);
2991 rewriter.replaceOp(op, cxaRethrow);
2992 return mlir::success();
2995 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
2996 auto fnTy = mlir::LLVM::LLVMFunctionType::get(
2997 voidTy, {llvmPtrTy, llvmPtrTy, llvmPtrTy});
3000 const llvm::StringRef fnName =
"__cxa_throw";
3003 mlir::Value typeInfo = mlir::LLVM::AddressOfOp::create(
3004 rewriter, loc, mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
3005 adaptor.getTypeInfoAttr());
3009 dtor = mlir::LLVM::AddressOfOp::create(rewriter, loc, llvmPtrTy,
3010 adaptor.getDtorAttr());
3012 dtor = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmPtrTy);
3015 auto cxaThrowCall = mlir::LLVM::CallOp::create(
3016 rewriter, loc, mlir::TypeRange{}, fnName,
3017 mlir::ValueRange{adaptor.getExceptionPtr(), typeInfo, dtor});
3019 rewriter.replaceOp(op, cxaThrowCall);
3020 return mlir::success();
3023mlir::LogicalResult CIRToLLVMAllocExceptionOpLowering::matchAndRewrite(
3024 cir::AllocExceptionOp op, OpAdaptor adaptor,
3025 mlir::ConversionPatternRewriter &rewriter)
const {
3027 StringRef fnName =
"__cxa_allocate_exception";
3028 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3029 auto int64Ty = mlir::IntegerType::get(rewriter.getContext(), 64);
3030 auto fnTy = mlir::LLVM::LLVMFunctionType::get(llvmPtrTy, {int64Ty});
3033 auto exceptionSize = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
3034 adaptor.getSizeAttr());
3036 auto allocaExceptionCall = mlir::LLVM::CallOp::create(
3037 rewriter, op.getLoc(), mlir::TypeRange{llvmPtrTy}, fnName,
3038 mlir::ValueRange{exceptionSize});
3040 rewriter.replaceOp(op, allocaExceptionCall);
3041 return mlir::success();
3044mlir::LogicalResult CIRToLLVMTrapOpLowering::matchAndRewrite(
3045 cir::TrapOp op, OpAdaptor adaptor,
3046 mlir::ConversionPatternRewriter &rewriter)
const {
3047 mlir::Location loc = op->getLoc();
3048 rewriter.eraseOp(op);
3050 mlir::LLVM::Trap::create(rewriter, loc);
3055 mlir::LLVM::UnreachableOp::create(rewriter, loc);
3057 return mlir::success();
3062 mlir::ConversionPatternRewriter &rewriter,
3063 const mlir::TypeConverter *converter,
3064 mlir::FlatSymbolRefAttr nameAttr, mlir::Type &eltType) {
3065 auto module = op->getParentOfType<mlir::ModuleOp>();
3066 mlir::Operation *symbol = mlir::SymbolTable::lookupSymbolIn(module, nameAttr);
3067 if (
auto llvmSymbol = mlir::dyn_cast<mlir::LLVM::GlobalOp>(symbol)) {
3068 eltType = llvmSymbol.getType();
3069 }
else if (
auto cirSymbol = mlir::dyn_cast<cir::GlobalOp>(symbol)) {
3070 eltType = converter->convertType(cirSymbol.getSymType());
3072 op->emitError() <<
"unexpected symbol type for " << symbol;
3076 return mlir::LLVM::AddressOfOp::create(
3077 rewriter, op->getLoc(),
3078 mlir::LLVM::LLVMPointerType::get(op->getContext()), nameAttr.getValue());
3081mlir::LogicalResult CIRToLLVMVTableAddrPointOpLowering::matchAndRewrite(
3082 cir::VTableAddrPointOp op, OpAdaptor adaptor,
3083 mlir::ConversionPatternRewriter &rewriter)
const {
3084 const mlir::TypeConverter *converter = getTypeConverter();
3085 mlir::Type targetType = converter->convertType(op.getType());
3089 op.getNameAttr(), eltType);
3091 return op.emitError() <<
"Unable to get value for vtable symbol";
3094 0, op.getAddressPointAttr().getIndex(),
3095 op.getAddressPointAttr().getOffset()};
3097 assert(eltType &&
"Shouldn't ever be missing an eltType here");
3098 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
3099 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
3100 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, targetType, eltType,
3101 symAddr, offsets, inboundsNuw);
3102 return mlir::success();
3105mlir::LogicalResult CIRToLLVMVTableGetVPtrOpLowering::matchAndRewrite(
3106 cir::VTableGetVPtrOp op, OpAdaptor adaptor,
3107 mlir::ConversionPatternRewriter &rewriter)
const {
3111 mlir::Value srcVal = adaptor.getSrc();
3112 rewriter.replaceOp(op, srcVal);
3113 return mlir::success();
3116mlir::LogicalResult CIRToLLVMVTableGetVirtualFnAddrOpLowering::matchAndRewrite(
3117 cir::VTableGetVirtualFnAddrOp op, OpAdaptor adaptor,
3118 mlir::ConversionPatternRewriter &rewriter)
const {
3119 mlir::Type targetType = getTypeConverter()->convertType(op.getType());
3120 auto eltType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3121 llvm::SmallVector<mlir::LLVM::GEPArg> offsets =
3122 llvm::SmallVector<mlir::LLVM::GEPArg>{op.getIndex()};
3123 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
3124 op, targetType, eltType, adaptor.getVptr(), offsets,
3125 mlir::LLVM::GEPNoWrapFlags::inbounds);
3126 return mlir::success();
3129mlir::LogicalResult CIRToLLVMVTTAddrPointOpLowering::matchAndRewrite(
3130 cir::VTTAddrPointOp op, OpAdaptor adaptor,
3131 mlir::ConversionPatternRewriter &rewriter)
const {
3132 const mlir::Type resultType = getTypeConverter()->convertType(op.getType());
3133 llvm::SmallVector<mlir::LLVM::GEPArg> offsets;
3135 mlir::Value llvmAddr = adaptor.getSymAddr();
3137 if (op.getSymAddr()) {
3138 if (op.getOffset() == 0) {
3139 rewriter.replaceOp(op, {llvmAddr});
3140 return mlir::success();
3143 offsets.push_back(adaptor.getOffset());
3144 eltType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3147 op.getNameAttr(), eltType);
3148 assert(eltType &&
"Shouldn't ever be missing an eltType here");
3149 offsets.push_back(0);
3150 offsets.push_back(adaptor.getOffset());
3152 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
3153 op, resultType, eltType, llvmAddr, offsets,
3154 mlir::LLVM::GEPNoWrapFlags::inbounds);
3155 return mlir::success();
3158mlir::LogicalResult CIRToLLVMStackSaveOpLowering::matchAndRewrite(
3159 cir::StackSaveOp op, OpAdaptor adaptor,
3160 mlir::ConversionPatternRewriter &rewriter)
const {
3161 const mlir::Type ptrTy = getTypeConverter()->convertType(op.getType());
3162 rewriter.replaceOpWithNewOp<mlir::LLVM::StackSaveOp>(op, ptrTy);
3163 return mlir::success();
3166mlir::LogicalResult CIRToLLVMStackRestoreOpLowering::matchAndRewrite(
3167 cir::StackRestoreOp op, OpAdaptor adaptor,
3168 mlir::ConversionPatternRewriter &rewriter)
const {
3169 rewriter.replaceOpWithNewOp<mlir::LLVM::StackRestoreOp>(op, adaptor.getPtr());
3170 return mlir::success();
3173mlir::LogicalResult CIRToLLVMVecCreateOpLowering::matchAndRewrite(
3174 cir::VecCreateOp op, OpAdaptor adaptor,
3175 mlir::ConversionPatternRewriter &rewriter)
const {
3178 const auto vecTy = mlir::cast<cir::VectorType>(op.getType());
3179 const mlir::Type llvmTy = typeConverter->convertType(vecTy);
3180 const mlir::Location loc = op.getLoc();
3181 mlir::Value result = mlir::LLVM::PoisonOp::create(rewriter, loc, llvmTy);
3182 assert(vecTy.getSize() == op.getElements().size() &&
3183 "cir.vec.create op count doesn't match vector type elements count");
3185 for (uint64_t i = 0; i < vecTy.getSize(); ++i) {
3186 const mlir::Value indexValue =
3187 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
3188 result = mlir::LLVM::InsertElementOp::create(
3189 rewriter, loc, result, adaptor.getElements()[i], indexValue);
3192 rewriter.replaceOp(op, result);
3193 return mlir::success();
3196mlir::LogicalResult CIRToLLVMVecExtractOpLowering::matchAndRewrite(
3197 cir::VecExtractOp op, OpAdaptor adaptor,
3198 mlir::ConversionPatternRewriter &rewriter)
const {
3199 rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractElementOp>(
3200 op, adaptor.getVec(), adaptor.getIndex());
3201 return mlir::success();
3204mlir::LogicalResult CIRToLLVMVecInsertOpLowering::matchAndRewrite(
3205 cir::VecInsertOp op, OpAdaptor adaptor,
3206 mlir::ConversionPatternRewriter &rewriter)
const {
3207 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertElementOp>(
3208 op, adaptor.getVec(), adaptor.getValue(), adaptor.getIndex());
3209 return mlir::success();
3212mlir::LogicalResult CIRToLLVMVecCmpOpLowering::matchAndRewrite(
3213 cir::VecCmpOp op, OpAdaptor adaptor,
3214 mlir::ConversionPatternRewriter &rewriter)
const {
3215 mlir::Type elementType = elementTypeIfVector(op.getLhs().getType());
3216 mlir::Value bitResult;
3217 if (
auto intType = mlir::dyn_cast<cir::IntType>(elementType)) {
3218 bitResult = mlir::LLVM::ICmpOp::create(
3219 rewriter, op.getLoc(),
3221 adaptor.getLhs(), adaptor.getRhs());
3222 }
else if (mlir::isa<cir::FPTypeInterface>(elementType)) {
3223 bitResult = mlir::LLVM::FCmpOp::create(
3225 adaptor.getLhs(), adaptor.getRhs());
3227 return op.emitError() <<
"unsupported type for VecCmpOp: " << elementType;
3232 rewriter.replaceOpWithNewOp<mlir::LLVM::SExtOp>(
3233 op, typeConverter->convertType(op.getType()), bitResult);
3234 return mlir::success();
3237mlir::LogicalResult CIRToLLVMVecSplatOpLowering::matchAndRewrite(
3238 cir::VecSplatOp op, OpAdaptor adaptor,
3239 mlir::ConversionPatternRewriter &rewriter)
const {
3245 cir::VectorType vecTy = op.getType();
3246 mlir::Type llvmTy = typeConverter->convertType(vecTy);
3247 mlir::Location loc = op.getLoc();
3248 mlir::Value poison = mlir::LLVM::PoisonOp::create(rewriter, loc, llvmTy);
3250 mlir::Value elementValue = adaptor.getValue();
3251 if (elementValue.getDefiningOp<mlir::LLVM::PoisonOp>()) {
3254 rewriter.replaceOp(op, poison);
3255 return mlir::success();
3258 if (
auto constValue = elementValue.getDefiningOp<mlir::LLVM::ConstantOp>()) {
3259 if (
auto intAttr = dyn_cast<mlir::IntegerAttr>(constValue.getValue())) {
3260 mlir::DenseIntElementsAttr denseVec = mlir::DenseIntElementsAttr::get(
3261 mlir::cast<mlir::ShapedType>(llvmTy), intAttr.getValue());
3262 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
3263 op, denseVec.getType(), denseVec);
3264 return mlir::success();
3267 if (
auto fpAttr = dyn_cast<mlir::FloatAttr>(constValue.getValue())) {
3268 mlir::DenseFPElementsAttr denseVec = mlir::DenseFPElementsAttr::get(
3269 mlir::cast<mlir::ShapedType>(llvmTy), fpAttr.getValue());
3270 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
3271 op, denseVec.getType(), denseVec);
3272 return mlir::success();
3276 mlir::Value indexValue =
3277 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), 0);
3278 mlir::Value oneElement = mlir::LLVM::InsertElementOp::create(
3279 rewriter, loc, poison, elementValue, indexValue);
3280 SmallVector<int32_t> zeroValues(vecTy.getSize(), 0);
3281 rewriter.replaceOpWithNewOp<mlir::LLVM::ShuffleVectorOp>(op, oneElement,
3282 poison, zeroValues);
3283 return mlir::success();
3286mlir::LogicalResult CIRToLLVMVecShuffleOpLowering::matchAndRewrite(
3287 cir::VecShuffleOp op, OpAdaptor adaptor,
3288 mlir::ConversionPatternRewriter &rewriter)
const {
3292 SmallVector<int, 8> indices;
3294 op.getIndices().begin(), op.getIndices().end(),
3295 std::back_inserter(indices), [](mlir::Attribute intAttr) {
3296 return mlir::cast<cir::IntAttr>(intAttr).getValue().getSExtValue();
3298 rewriter.replaceOpWithNewOp<mlir::LLVM::ShuffleVectorOp>(
3299 op, adaptor.getVec1(), adaptor.getVec2(), indices);
3300 return mlir::success();
3303mlir::LogicalResult CIRToLLVMVecShuffleDynamicOpLowering::matchAndRewrite(
3304 cir::VecShuffleDynamicOp op, OpAdaptor adaptor,
3305 mlir::ConversionPatternRewriter &rewriter)
const {
3317 mlir::Location loc = op.getLoc();
3318 mlir::Value input = adaptor.getVec();
3319 mlir::Type llvmIndexVecType =
3320 getTypeConverter()->convertType(op.getIndices().getType());
3321 mlir::Type llvmIndexType = getTypeConverter()->convertType(
3322 elementTypeIfVector(op.getIndices().getType()));
3324 mlir::cast<cir::VectorType>(op.getVec().getType()).getSize();
3326 uint64_t maskBits = llvm::NextPowerOf2(numElements - 1) - 1;
3327 mlir::Value maskValue = mlir::LLVM::ConstantOp::create(
3328 rewriter, loc, llvmIndexType,
3329 rewriter.getIntegerAttr(llvmIndexType, maskBits));
3330 mlir::Value maskVector =
3331 mlir::LLVM::UndefOp::create(rewriter, loc, llvmIndexVecType);
3333 for (uint64_t i = 0; i < numElements; ++i) {
3334 mlir::Value idxValue =
3335 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
3336 maskVector = mlir::LLVM::InsertElementOp::create(rewriter, loc, maskVector,
3337 maskValue, idxValue);
3340 mlir::Value maskedIndices = mlir::LLVM::AndOp::create(
3341 rewriter, loc, llvmIndexVecType, adaptor.getIndices(), maskVector);
3342 mlir::Value result = mlir::LLVM::UndefOp::create(
3343 rewriter, loc, getTypeConverter()->convertType(op.getVec().getType()));
3344 for (uint64_t i = 0; i < numElements; ++i) {
3345 mlir::Value iValue =
3346 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
3347 mlir::Value indexValue = mlir::LLVM::ExtractElementOp::create(
3348 rewriter, loc, maskedIndices, iValue);
3349 mlir::Value valueAtIndex =
3350 mlir::LLVM::ExtractElementOp::create(rewriter, loc, input, indexValue);
3351 result = mlir::LLVM::InsertElementOp::create(rewriter, loc, result,
3352 valueAtIndex, iValue);
3354 rewriter.replaceOp(op, result);
3355 return mlir::success();
3358mlir::LogicalResult CIRToLLVMVecTernaryOpLowering::matchAndRewrite(
3359 cir::VecTernaryOp op, OpAdaptor adaptor,
3360 mlir::ConversionPatternRewriter &rewriter)
const {
3362 mlir::Value bitVec = mlir::LLVM::ICmpOp::create(
3363 rewriter, op.getLoc(), mlir::LLVM::ICmpPredicate::ne, adaptor.getCond(),
3364 mlir::LLVM::ZeroOp::create(
3365 rewriter, op.getCond().getLoc(),
3366 typeConverter->convertType(op.getCond().getType())));
3367 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(
3368 op, bitVec, adaptor.getLhs(), adaptor.getRhs());
3369 return mlir::success();
3372mlir::LogicalResult CIRToLLVMComplexAddOpLowering::matchAndRewrite(
3373 cir::ComplexAddOp op, OpAdaptor adaptor,
3374 mlir::ConversionPatternRewriter &rewriter)
const {
3375 mlir::Value lhs = adaptor.getLhs();
3376 mlir::Value rhs = adaptor.getRhs();
3377 mlir::Location loc = op.getLoc();
3379 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
3380 mlir::Type complexElemTy =
3381 getTypeConverter()->convertType(
complexType.getElementType());
3382 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
3383 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{0}));
3384 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
3385 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{1}));
3386 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
3387 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{0}));
3388 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
3389 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{1}));
3391 mlir::Value newReal;
3392 mlir::Value newImag;
3393 if (complexElemTy.isInteger()) {
3394 newReal = mlir::LLVM::AddOp::create(rewriter, loc, complexElemTy, lhsReal,
3396 newImag = mlir::LLVM::AddOp::create(rewriter, loc, complexElemTy, lhsImag,
3401 newReal = mlir::LLVM::FAddOp::create(rewriter, loc, complexElemTy, lhsReal,
3403 newImag = mlir::LLVM::FAddOp::create(rewriter, loc, complexElemTy, lhsImag,
3407 mlir::Type complexLLVMTy =
3408 getTypeConverter()->convertType(op.getResult().getType());
3409 auto initialComplex =
3410 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), complexLLVMTy);
3412 auto realComplex = mlir::LLVM::InsertValueOp::create(
3413 rewriter, op->getLoc(), initialComplex, newReal, ArrayRef(int64_t{0}));
3415 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
3416 op, realComplex, newImag, ArrayRef(int64_t{1}));
3418 return mlir::success();
3421mlir::LogicalResult CIRToLLVMComplexCreateOpLowering::matchAndRewrite(
3422 cir::ComplexCreateOp op, OpAdaptor adaptor,
3423 mlir::ConversionPatternRewriter &rewriter)
const {
3424 mlir::Type complexLLVMTy =
3425 getTypeConverter()->convertType(op.getResult().getType());
3426 auto initialComplex =
3427 mlir::LLVM::UndefOp::create(rewriter, op->getLoc(), complexLLVMTy);
3429 auto realComplex = mlir::LLVM::InsertValueOp::create(
3430 rewriter, op->getLoc(), initialComplex, adaptor.getReal(),
3431 ArrayRef(int64_t{0}));
3433 auto complex = mlir::LLVM::InsertValueOp::create(
3434 rewriter, op->getLoc(), realComplex, adaptor.getImag(),
3435 ArrayRef(int64_t{1}));
3437 rewriter.replaceOp(op, complex);
3438 return mlir::success();
3441mlir::LogicalResult CIRToLLVMComplexRealOpLowering::matchAndRewrite(
3442 cir::ComplexRealOp op, OpAdaptor adaptor,
3443 mlir::ConversionPatternRewriter &rewriter)
const {
3444 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
3445 mlir::Value operand = adaptor.getOperand();
3446 if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) {
3447 operand = mlir::LLVM::ExtractValueOp::create(
3448 rewriter, op.getLoc(), resultLLVMTy, operand,
3449 llvm::ArrayRef<std::int64_t>{0});
3451 rewriter.replaceOp(op, operand);
3452 return mlir::success();
3455mlir::LogicalResult CIRToLLVMComplexSubOpLowering::matchAndRewrite(
3456 cir::ComplexSubOp op, OpAdaptor adaptor,
3457 mlir::ConversionPatternRewriter &rewriter)
const {
3458 mlir::Value lhs = adaptor.getLhs();
3459 mlir::Value rhs = adaptor.getRhs();
3460 mlir::Location loc = op.getLoc();
3462 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
3463 mlir::Type complexElemTy =
3464 getTypeConverter()->convertType(
complexType.getElementType());
3465 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
3466 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{0}));
3467 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
3468 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{1}));
3469 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
3470 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{0}));
3471 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
3472 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{1}));
3474 mlir::Value newReal;
3475 mlir::Value newImag;
3476 if (complexElemTy.isInteger()) {
3477 newReal = mlir::LLVM::SubOp::create(rewriter, loc, complexElemTy, lhsReal,
3479 newImag = mlir::LLVM::SubOp::create(rewriter, loc, complexElemTy, lhsImag,
3484 newReal = mlir::LLVM::FSubOp::create(rewriter, loc, complexElemTy, lhsReal,
3486 newImag = mlir::LLVM::FSubOp::create(rewriter, loc, complexElemTy, lhsImag,
3490 mlir::Type complexLLVMTy =
3491 getTypeConverter()->convertType(op.getResult().getType());
3492 auto initialComplex =
3493 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), complexLLVMTy);
3495 auto realComplex = mlir::LLVM::InsertValueOp::create(
3496 rewriter, op->getLoc(), initialComplex, newReal, ArrayRef(int64_t{0}));
3498 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
3499 op, realComplex, newImag, ArrayRef(int64_t{1}));
3501 return mlir::success();
3504mlir::LogicalResult CIRToLLVMComplexImagOpLowering::matchAndRewrite(
3505 cir::ComplexImagOp op, OpAdaptor adaptor,
3506 mlir::ConversionPatternRewriter &rewriter)
const {
3507 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
3508 mlir::Value operand = adaptor.getOperand();
3509 mlir::Location loc = op.getLoc();
3511 if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) {
3512 operand = mlir::LLVM::ExtractValueOp::create(
3513 rewriter, loc, resultLLVMTy, operand, llvm::ArrayRef<std::int64_t>{1});
3515 mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(resultLLVMTy);
3517 mlir::LLVM::ConstantOp::create(rewriter, loc, resultLLVMTy, zeroAttr);
3520 rewriter.replaceOp(op, operand);
3521 return mlir::success();
3525 mlir::MLIRContext *context,
3526 unsigned &storageSize) {
3527 return TypeSwitch<mlir::Type, mlir::IntegerType>(storageType)
3528 .Case<cir::ArrayType>([&](cir::ArrayType atTy) {
3529 storageSize = atTy.getSize() * 8;
3530 return mlir::IntegerType::get(context, storageSize);
3532 .Case<cir::IntType>([&](cir::IntType intTy) {
3533 storageSize = intTy.getWidth();
3534 return mlir::IntegerType::get(context, storageSize);
3536 .Default([](mlir::Type) -> mlir::IntegerType {
3538 "Either ArrayType or IntType expected for bitfields storage");
3542mlir::LogicalResult CIRToLLVMSetBitfieldOpLowering::matchAndRewrite(
3543 cir::SetBitfieldOp op, OpAdaptor adaptor,
3544 mlir::ConversionPatternRewriter &rewriter)
const {
3545 mlir::OpBuilder::InsertionGuard guard(rewriter);
3546 rewriter.setInsertionPoint(op);
3548 cir::BitfieldInfoAttr info = op.getBitfieldInfo();
3549 uint64_t size = info.getSize();
3550 uint64_t offset = info.getOffset();
3551 mlir::Type storageType = info.getStorageType();
3552 mlir::MLIRContext *context = storageType.getContext();
3554 unsigned storageSize = 0;
3556 mlir::IntegerType intType =
3559 mlir::Value srcVal =
createIntCast(rewriter, adaptor.getSrc(), intType);
3560 unsigned srcWidth = storageSize;
3561 mlir::Value resultVal = srcVal;
3563 if (storageSize != size) {
3564 assert(storageSize > size &&
"Invalid bitfield size.");
3566 mlir::Value val = mlir::LLVM::LoadOp::create(
3567 rewriter, op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(),
3568 op.getIsVolatile());
3571 createAnd(rewriter, srcVal, llvm::APInt::getLowBitsSet(srcWidth, size));
3573 srcVal =
createShL(rewriter, srcVal, offset);
3577 ~llvm::APInt::getBitsSet(srcWidth, offset, offset + size));
3580 srcVal = mlir::LLVM::OrOp::create(rewriter, op.getLoc(), val, srcVal);
3583 mlir::LLVM::StoreOp::create(rewriter, op.getLoc(), srcVal, adaptor.getAddr(),
3584 op.getAlignment(), op.getIsVolatile());
3586 mlir::Type resultTy = getTypeConverter()->convertType(op.getType());
3588 if (info.getIsSigned()) {
3589 assert(size <= storageSize);
3590 unsigned highBits = storageSize - size;
3593 resultVal =
createShL(rewriter, resultVal, highBits);
3594 resultVal =
createAShR(rewriter, resultVal, highBits);
3599 mlir::cast<mlir::IntegerType>(resultTy),
3600 info.getIsSigned());
3602 rewriter.replaceOp(op, resultVal);
3603 return mlir::success();
3606mlir::LogicalResult CIRToLLVMComplexImagPtrOpLowering::matchAndRewrite(
3607 cir::ComplexImagPtrOp op, OpAdaptor adaptor,
3608 mlir::ConversionPatternRewriter &rewriter)
const {
3609 cir::PointerType operandTy = op.getOperand().getType();
3610 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
3611 mlir::Type elementLLVMTy =
3612 getTypeConverter()->convertType(operandTy.getPointee());
3614 mlir::LLVM::GEPArg gepIndices[2] = {{0}, {1}};
3615 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
3616 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
3617 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
3618 op, resultLLVMTy, elementLLVMTy, adaptor.getOperand(), gepIndices,
3620 return mlir::success();
3623mlir::LogicalResult CIRToLLVMComplexRealPtrOpLowering::matchAndRewrite(
3624 cir::ComplexRealPtrOp op, OpAdaptor adaptor,
3625 mlir::ConversionPatternRewriter &rewriter)
const {
3626 cir::PointerType operandTy = op.getOperand().getType();
3627 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
3628 mlir::Type elementLLVMTy =
3629 getTypeConverter()->convertType(operandTy.getPointee());
3631 mlir::LLVM::GEPArg gepIndices[2] = {0, 0};
3632 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
3633 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
3634 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
3635 op, resultLLVMTy, elementLLVMTy, adaptor.getOperand(), gepIndices,
3637 return mlir::success();
3640mlir::LogicalResult CIRToLLVMGetBitfieldOpLowering::matchAndRewrite(
3641 cir::GetBitfieldOp op, OpAdaptor adaptor,
3642 mlir::ConversionPatternRewriter &rewriter)
const {
3644 mlir::OpBuilder::InsertionGuard guard(rewriter);
3645 rewriter.setInsertionPoint(op);
3647 cir::BitfieldInfoAttr info = op.getBitfieldInfo();
3649 uint64_t offset = info.getOffset();
3650 mlir::Type storageType = info.getStorageType();
3651 mlir::MLIRContext *context = storageType.getContext();
3652 unsigned storageSize = 0;
3654 mlir::IntegerType intType =
3657 mlir::Value val = mlir::LLVM::LoadOp::create(
3658 rewriter, op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(),
3659 op.getIsVolatile());
3660 val = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), intType, val);
3662 if (info.getIsSigned()) {
3663 assert(
static_cast<unsigned>(offset + size) <= storageSize);
3664 unsigned highBits = storageSize - offset - size;
3665 val =
createShL(rewriter, val, highBits);
3666 val =
createAShR(rewriter, val, offset + highBits);
3670 if (
static_cast<unsigned>(offset) + size < storageSize)
3672 llvm::APInt::getLowBitsSet(storageSize, size));
3675 mlir::Type resTy = getTypeConverter()->convertType(op.getType());
3677 rewriter, val, mlir::cast<mlir::IntegerType>(resTy), info.getIsSigned());
3678 rewriter.replaceOp(op, newOp);
3679 return mlir::success();
3682mlir::LogicalResult CIRToLLVMInlineAsmOpLowering::matchAndRewrite(
3683 cir::InlineAsmOp op, OpAdaptor adaptor,
3684 mlir::ConversionPatternRewriter &rewriter)
const {
3686 if (op.getNumResults())
3687 llResTy = getTypeConverter()->convertType(op.getType(0));
3689 cir::AsmFlavor dialect = op.getAsmFlavor();
3690 mlir::LLVM::AsmDialect llDialect = dialect == cir::AsmFlavor::x86_att
3691 ? mlir::LLVM::AsmDialect::AD_ATT
3692 : mlir::LLVM::AsmDialect::AD_Intel;
3694 SmallVector<mlir::Attribute> opAttrs;
3695 StringRef llvmAttrName = mlir::LLVM::InlineAsmOp::getElementTypeAttrName();
3701 if (!op.getNumResults())
3702 opAttrs.push_back(mlir::Attribute());
3704 SmallVector<mlir::Value> llvmOperands;
3705 SmallVector<mlir::Value> cirOperands;
3706 for (
auto const &[llvmOp, cirOp] :
3707 zip(adaptor.getAsmOperands(), op.getAsmOperands())) {
3708 append_range(llvmOperands, llvmOp);
3709 append_range(cirOperands, cirOp);
3714 for (
auto const &[cirOpAttr, cirOp] :
3715 zip(op.getOperandAttrs(), cirOperands)) {
3717 opAttrs.push_back(mlir::Attribute());
3721 llvm::SmallVector<mlir::NamedAttribute, 1> attrs;
3722 cir::PointerType typ = mlir::cast<cir::PointerType>(cirOp.getType());
3724 *getTypeConverter(), dataLayout, typ.getPointee()));
3726 attrs.push_back(rewriter.getNamedAttr(llvmAttrName, typAttr));
3727 mlir::DictionaryAttr newDict = rewriter.getDictionaryAttr(attrs);
3728 opAttrs.push_back(newDict);
3731 rewriter.replaceOpWithNewOp<mlir::LLVM::InlineAsmOp>(
3732 op, llResTy, llvmOperands, op.getAsmStringAttr(), op.getConstraintsAttr(),
3733 op.getSideEffectsAttr(),
3736 mlir::LLVM::TailCallKindAttr::get(
3737 getContext(), mlir::LLVM::tailcallkind::TailCallKind::None),
3738 mlir::LLVM::AsmDialectAttr::get(getContext(), llDialect),
3739 rewriter.getArrayAttr(opAttrs));
3741 return mlir::success();
3744mlir::LogicalResult CIRToLLVMVAStartOpLowering::matchAndRewrite(
3745 cir::VAStartOp op, OpAdaptor adaptor,
3746 mlir::ConversionPatternRewriter &rewriter)
const {
3747 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
3748 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
3749 adaptor.getArgList());
3750 rewriter.replaceOpWithNewOp<mlir::LLVM::VaStartOp>(op, vaList);
3751 return mlir::success();
3754mlir::LogicalResult CIRToLLVMVAEndOpLowering::matchAndRewrite(
3755 cir::VAEndOp op, OpAdaptor adaptor,
3756 mlir::ConversionPatternRewriter &rewriter)
const {
3757 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
3758 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
3759 adaptor.getArgList());
3760 rewriter.replaceOpWithNewOp<mlir::LLVM::VaEndOp>(op, vaList);
3761 return mlir::success();
3764mlir::LogicalResult CIRToLLVMVAArgOpLowering::matchAndRewrite(
3765 cir::VAArgOp op, OpAdaptor adaptor,
3766 mlir::ConversionPatternRewriter &rewriter)
const {
3768 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
3769 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
3770 adaptor.getArgList());
3772 mlir::Type llvmType =
3773 getTypeConverter()->convertType(op->getResultTypes().front());
3775 return mlir::failure();
3777 rewriter.replaceOpWithNewOp<mlir::LLVM::VaArgOp>(op, llvmType, vaList);
3778 return mlir::success();
3782 return std::make_unique<ConvertCIRToLLVMPass>();
3790std::unique_ptr<llvm::Module>
3792 llvm::TimeTraceScope scope(
"lower from CIR to LLVM directly");
3794 mlir::MLIRContext *mlirCtx = mlirModule.getContext();
3796 mlir::PassManager pm(mlirCtx);
3799 (void)mlir::applyPassManagerCLOptions(pm);
3801 if (mlir::failed(pm.run(mlirModule))) {
3804 "The pass manager failed to lower CIR to LLVMIR dialect!");
3807 mlir::registerBuiltinDialectTranslation(*mlirCtx);
3808 mlir::registerLLVMDialectTranslation(*mlirCtx);
3811 llvm::TimeTraceScope translateScope(
"translateModuleToLLVMIR");
3813 StringRef moduleName = mlirModule.getName().value_or(
"CIRToLLVMModule");
3814 std::unique_ptr<llvm::Module> llvmModule =
3815 mlir::translateModuleToLLVMIR(mlirModule, llvmCtx, moduleName);
3819 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)
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 length(float)
Return the length of vector p, i.e., sqrt(p.x2 + p.y 2 + ...)
char __ovld __cnfn select(char, char, char)
For each component of a vector type, result[i] = if MSB of c[i] is set ?
static bool dataMemberType()
static bool opGlobalConstant()
static bool addressSpace()
static bool opGlobalThreadLocal()
static bool globalViewIntLowering()
static bool opAllocaAnnotations()
static bool atomicScope()
static bool opLoadStoreTbaa()
static bool optInfoAttr()
static bool opFuncExtraAttrs()
static bool opCallLandingPad()
static bool vaArgABILowering()
static bool fpConstraints()
static bool lowerModeOptLevel()
static bool opCallCallConv()
static bool opFuncCallingConv()
static bool aggValueSlotVolatile()
static bool fastMathFlags()
static bool opCallContinueBlock()
static bool 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)