19#include "mlir/Conversion/LLVMCommon/TypeConverter.h"
20#include "mlir/Dialect/DLTI/DLTI.h"
21#include "mlir/Dialect/Func/IR/FuncOps.h"
22#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
23#include "mlir/Dialect/LLVMIR/LLVMTypes.h"
24#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
25#include "mlir/IR/BuiltinAttributes.h"
26#include "mlir/IR/BuiltinDialect.h"
27#include "mlir/IR/BuiltinOps.h"
28#include "mlir/IR/Types.h"
29#include "mlir/Pass/Pass.h"
30#include "mlir/Pass/PassManager.h"
31#include "mlir/Support/LLVM.h"
32#include "mlir/Target/LLVMIR/Dialect/Builtin/BuiltinToLLVMIRTranslation.h"
33#include "mlir/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.h"
34#include "mlir/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.h"
35#include "mlir/Target/LLVMIR/Export.h"
36#include "mlir/Transforms/DialectConversion.h"
44#include "llvm/ADT/TypeSwitch.h"
45#include "llvm/IR/Module.h"
46#include "llvm/Support/Casting.h"
47#include "llvm/Support/ErrorHandling.h"
48#include "llvm/Support/TimeProfiler.h"
63mlir::Type elementTypeIfVector(mlir::Type type) {
64 return llvm::TypeSwitch<mlir::Type, mlir::Type>(type)
65 .Case<cir::VectorType, mlir::VectorType>(
66 [](
auto p) {
return p.getElementType(); })
67 .
Default([](mlir::Type p) {
return p; });
75 mlir::DataLayout
const &dataLayout,
79 if (isa<cir::BoolType>(type)) {
80 return mlir::IntegerType::get(type.getContext(),
81 dataLayout.getTypeSizeInBits(type));
84 return converter.convertType(type);
88 mlir::IntegerType dstTy,
89 bool isSigned =
false) {
90 mlir::Type srcTy = src.getType();
91 assert(mlir::isa<mlir::IntegerType>(srcTy));
93 unsigned srcWidth = mlir::cast<mlir::IntegerType>(srcTy).getWidth();
94 unsigned dstWidth = mlir::cast<mlir::IntegerType>(dstTy).getWidth();
95 mlir::Location loc = src.getLoc();
97 if (dstWidth > srcWidth && isSigned)
98 return mlir::LLVM::SExtOp::create(bld, loc, dstTy, src);
99 if (dstWidth > srcWidth)
100 return mlir::LLVM::ZExtOp::create(bld, loc, dstTy, src);
101 if (dstWidth < srcWidth)
102 return mlir::LLVM::TruncOp::create(bld, loc, dstTy, src);
103 return mlir::LLVM::BitcastOp::create(bld, loc, dstTy, src);
106static mlir::LLVM::Visibility
108 switch (visibilityKind) {
109 case cir::VisibilityKind::Default:
110 return ::mlir::LLVM::Visibility::Default;
111 case cir::VisibilityKind::Hidden:
112 return ::mlir::LLVM::Visibility::Hidden;
113 case cir::VisibilityKind::Protected:
114 return ::mlir::LLVM::Visibility::Protected;
122 mlir::DataLayout
const &dataLayout,
123 cir::LoadOp op, mlir::Value value) {
126 if (
auto boolTy = mlir::dyn_cast<cir::BoolType>(op.getType())) {
128 assert(value.getType().isInteger(dataLayout.getTypeSizeInBits(boolTy)));
138static mlir::Value
emitToMemory(mlir::ConversionPatternRewriter &rewriter,
139 mlir::DataLayout
const &dataLayout,
140 mlir::Type origType, mlir::Value value) {
143 if (
auto boolTy = mlir::dyn_cast<cir::BoolType>(origType)) {
145 mlir::IntegerType memType =
146 rewriter.getIntegerType(dataLayout.getTypeSizeInBits(boolTy));
154 using CIR = cir::GlobalLinkageKind;
155 using LLVM = mlir::LLVM::Linkage;
158 case CIR::AppendingLinkage:
159 return LLVM::Appending;
160 case CIR::AvailableExternallyLinkage:
161 return LLVM::AvailableExternally;
162 case CIR::CommonLinkage:
164 case CIR::ExternalLinkage:
165 return LLVM::External;
166 case CIR::ExternalWeakLinkage:
167 return LLVM::ExternWeak;
168 case CIR::InternalLinkage:
169 return LLVM::Internal;
170 case CIR::LinkOnceAnyLinkage:
171 return LLVM::Linkonce;
172 case CIR::LinkOnceODRLinkage:
173 return LLVM::LinkonceODR;
174 case CIR::PrivateLinkage:
175 return LLVM::Private;
176 case CIR::WeakAnyLinkage:
178 case CIR::WeakODRLinkage:
179 return LLVM::WeakODR;
181 llvm_unreachable(
"Unknown CIR linkage type");
184mlir::LogicalResult CIRToLLVMCopyOpLowering::matchAndRewrite(
185 cir::CopyOp op, OpAdaptor adaptor,
186 mlir::ConversionPatternRewriter &rewriter)
const {
187 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
188 const mlir::Value
length = mlir::LLVM::ConstantOp::create(
189 rewriter, op.getLoc(), rewriter.getI64Type(), op.getLength(layout));
191 rewriter.replaceOpWithNewOp<mlir::LLVM::MemcpyOp>(
192 op, adaptor.getDst(), adaptor.getSrc(),
length, op.getIsVolatile());
193 return mlir::success();
196mlir::LogicalResult CIRToLLVMMemCpyOpLowering::matchAndRewrite(
197 cir::MemCpyOp op, OpAdaptor adaptor,
198 mlir::ConversionPatternRewriter &rewriter)
const {
199 rewriter.replaceOpWithNewOp<mlir::LLVM::MemcpyOp>(
200 op, adaptor.getDst(), adaptor.getSrc(), adaptor.getLen(),
202 return mlir::success();
205mlir::LogicalResult CIRToLLVMMemSetOpLowering::matchAndRewrite(
206 cir::MemSetOp op, OpAdaptor adaptor,
207 mlir::ConversionPatternRewriter &rewriter)
const {
209 auto memset = rewriter.replaceOpWithNewOp<mlir::LLVM::MemsetOp>(
210 op, adaptor.getDst(), adaptor.getVal(), adaptor.getLen(),
213 if (op.getAlignmentAttr()) {
215 llvm::SmallVector<mlir::Attribute> attrs{
memset.getNumOperands(),
216 rewriter.getDictionaryAttr({})};
217 llvm::SmallVector<mlir::NamedAttribute> destAttrs;
219 {mlir::LLVM::LLVMDialect::getAlignAttrName(), op.getAlignmentAttr()});
220 attrs[
memset.odsIndex_dst] = rewriter.getDictionaryAttr(destAttrs);
222 auto arrayAttr = rewriter.getArrayAttr(attrs);
223 memset.setArgAttrsAttr(arrayAttr);
226 return mlir::success();
229mlir::LogicalResult CIRToLLVMSqrtOpLowering::matchAndRewrite(
230 cir::SqrtOp op, OpAdaptor adaptor,
231 mlir::ConversionPatternRewriter &rewriter)
const {
232 mlir::Type resTy = typeConverter->convertType(op.getType());
233 rewriter.replaceOpWithNewOp<mlir::LLVM::SqrtOp>(op, resTy, adaptor.getSrc());
234 return mlir::success();
237mlir::LogicalResult CIRToLLVMCosOpLowering::matchAndRewrite(
238 cir::CosOp op, OpAdaptor adaptor,
239 mlir::ConversionPatternRewriter &rewriter)
const {
240 mlir::Type resTy = typeConverter->convertType(op.getType());
241 rewriter.replaceOpWithNewOp<mlir::LLVM::CosOp>(op, resTy, adaptor.getSrc());
242 return mlir::success();
245mlir::LogicalResult CIRToLLVMExpOpLowering::matchAndRewrite(
246 cir::ExpOp op, OpAdaptor adaptor,
247 mlir::ConversionPatternRewriter &rewriter)
const {
248 mlir::Type resTy = typeConverter->convertType(op.getType());
249 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpOp>(op, resTy, adaptor.getSrc());
250 return mlir::success();
253mlir::LogicalResult CIRToLLVMExp2OpLowering::matchAndRewrite(
254 cir::Exp2Op op, OpAdaptor adaptor,
255 mlir::ConversionPatternRewriter &rewriter)
const {
256 mlir::Type resTy = typeConverter->convertType(op.getType());
257 rewriter.replaceOpWithNewOp<mlir::LLVM::Exp2Op>(op, resTy, adaptor.getSrc());
258 return mlir::success();
261mlir::LogicalResult CIRToLLVMLogOpLowering::matchAndRewrite(
262 cir::LogOp op, OpAdaptor adaptor,
263 mlir::ConversionPatternRewriter &rewriter)
const {
264 mlir::Type resTy = typeConverter->convertType(op.getType());
265 rewriter.replaceOpWithNewOp<mlir::LLVM::LogOp>(op, resTy, adaptor.getSrc());
266 return mlir::success();
269mlir::LogicalResult CIRToLLVMLog10OpLowering::matchAndRewrite(
270 cir::Log10Op op, OpAdaptor adaptor,
271 mlir::ConversionPatternRewriter &rewriter)
const {
272 mlir::Type resTy = typeConverter->convertType(op.getType());
273 rewriter.replaceOpWithNewOp<mlir::LLVM::Log10Op>(op, resTy, adaptor.getSrc());
274 return mlir::success();
277mlir::LogicalResult CIRToLLVMLog2OpLowering::matchAndRewrite(
278 cir::Log2Op op, OpAdaptor adaptor,
279 mlir::ConversionPatternRewriter &rewriter)
const {
280 mlir::Type resTy = typeConverter->convertType(op.getType());
281 rewriter.replaceOpWithNewOp<mlir::LLVM::Log2Op>(op, resTy, adaptor.getSrc());
282 return mlir::success();
285mlir::LogicalResult CIRToLLVMNearbyintOpLowering::matchAndRewrite(
286 cir::NearbyintOp op, OpAdaptor adaptor,
287 mlir::ConversionPatternRewriter &rewriter)
const {
288 mlir::Type resTy = typeConverter->convertType(op.getType());
289 rewriter.replaceOpWithNewOp<mlir::LLVM::NearbyintOp>(op, resTy,
291 return mlir::success();
294mlir::LogicalResult CIRToLLVMRintOpLowering::matchAndRewrite(
295 cir::RintOp op, OpAdaptor adaptor,
296 mlir::ConversionPatternRewriter &rewriter)
const {
297 mlir::Type resTy = typeConverter->convertType(op.getType());
298 rewriter.replaceOpWithNewOp<mlir::LLVM::RintOp>(op, resTy, adaptor.getSrc());
299 return mlir::success();
302mlir::LogicalResult CIRToLLVMRoundOpLowering::matchAndRewrite(
303 cir::RoundOp op, OpAdaptor adaptor,
304 mlir::ConversionPatternRewriter &rewriter)
const {
305 mlir::Type resTy = typeConverter->convertType(op.getType());
306 rewriter.replaceOpWithNewOp<mlir::LLVM::RoundOp>(op, resTy, adaptor.getSrc());
307 return mlir::success();
310mlir::LogicalResult CIRToLLVMRoundEvenOpLowering::matchAndRewrite(
311 cir::RoundEvenOp op, OpAdaptor adaptor,
312 mlir::ConversionPatternRewriter &rewriter)
const {
313 mlir::Type resTy = typeConverter->convertType(op.getType());
314 rewriter.replaceOpWithNewOp<mlir::LLVM::RoundEvenOp>(op, resTy,
316 return mlir::success();
319mlir::LogicalResult CIRToLLVMSinOpLowering::matchAndRewrite(
320 cir::SinOp op, OpAdaptor adaptor,
321 mlir::ConversionPatternRewriter &rewriter)
const {
322 mlir::Type resTy = typeConverter->convertType(op.getType());
323 rewriter.replaceOpWithNewOp<mlir::LLVM::SinOp>(op, resTy, adaptor.getSrc());
324 return mlir::success();
327mlir::LogicalResult CIRToLLVMTanOpLowering::matchAndRewrite(
328 cir::TanOp op, OpAdaptor adaptor,
329 mlir::ConversionPatternRewriter &rewriter)
const {
330 mlir::Type resTy = typeConverter->convertType(op.getType());
331 rewriter.replaceOpWithNewOp<mlir::LLVM::TanOp>(op, resTy, adaptor.getSrc());
332 return mlir::success();
335mlir::LogicalResult CIRToLLVMTruncOpLowering::matchAndRewrite(
336 cir::TruncOp op, OpAdaptor adaptor,
337 mlir::ConversionPatternRewriter &rewriter)
const {
338 mlir::Type resTy = typeConverter->convertType(op.getType());
339 rewriter.replaceOpWithNewOp<mlir::LLVM::FTruncOp>(op, resTy,
341 return mlir::success();
344mlir::LogicalResult CIRToLLVMFloorOpLowering::matchAndRewrite(
345 cir::FloorOp op, OpAdaptor adaptor,
346 mlir::ConversionPatternRewriter &rewriter)
const {
347 mlir::Type resTy = typeConverter->convertType(op.getType());
348 rewriter.replaceOpWithNewOp<mlir::LLVM::FFloorOp>(op, resTy,
350 return mlir::success();
354 mlir::Value llvmSrc, mlir::Type llvmDstIntTy,
356 uint64_t cirDstIntWidth) {
357 if (cirSrcWidth == cirDstIntWidth)
360 auto loc = llvmSrc.getLoc();
361 if (cirSrcWidth < cirDstIntWidth) {
363 return mlir::LLVM::ZExtOp::create(rewriter, loc, llvmDstIntTy, llvmSrc);
364 return mlir::LLVM::SExtOp::create(rewriter, loc, llvmDstIntTy, llvmSrc);
368 return mlir::LLVM::TruncOp::create(rewriter, loc, llvmDstIntTy, llvmSrc);
374 mlir::ConversionPatternRewriter &rewriter,
375 const mlir::TypeConverter *converter)
376 : parentOp(parentOp), rewriter(rewriter), converter(converter) {}
378 mlir::Value
visit(mlir::Attribute attr) {
379 return llvm::TypeSwitch<mlir::Attribute, mlir::Value>(attr)
380 .Case<cir::IntAttr, cir::FPAttr, cir::ConstComplexAttr,
381 cir::ConstArrayAttr, cir::ConstRecordAttr, cir::ConstVectorAttr,
382 cir::ConstPtrAttr, cir::GlobalViewAttr, cir::TypeInfoAttr,
383 cir::UndefAttr, cir::VTableAttr, cir::ZeroAttr>(
385 .Default([&](
auto attrT) {
return mlir::Value(); });
390 mlir::Value
visitCirAttr(cir::ConstComplexAttr complexAttr);
402 mlir::Operation *parentOp;
403 mlir::ConversionPatternRewriter &rewriter;
404 const mlir::TypeConverter *converter;
409 const mlir::Attribute attr,
410 mlir::ConversionPatternRewriter &rewriter,
411 const mlir::TypeConverter *converter) {
413 mlir::Value value = valueConverter.
visit(attr);
415 llvm_unreachable(
"unhandled attribute type");
420 cir::SideEffect sideEffect,
421 mlir::LLVM::MemoryEffectsAttr &memoryEffect,
422 bool &noUnwind,
bool &willReturn,
424 using mlir::LLVM::ModRefInfo;
426 switch (sideEffect) {
427 case cir::SideEffect::All:
429 noUnwind = isNothrow;
433 case cir::SideEffect::Pure:
434 memoryEffect = mlir::LLVM::MemoryEffectsAttr::get(
435 callOp->getContext(), ModRefInfo::Ref,
445 case cir::SideEffect::Const:
446 memoryEffect = mlir::LLVM::MemoryEffectsAttr::get(
447 callOp->getContext(), ModRefInfo::NoModRef,
448 ModRefInfo::NoModRef,
449 ModRefInfo::NoModRef,
450 ModRefInfo::NoModRef,
451 ModRefInfo::NoModRef,
452 ModRefInfo::NoModRef);
458 noReturn = callOp->hasAttr(CIRDialect::getNoReturnAttrName());
461static mlir::LLVM::CallIntrinsicOp
463 mlir::Location loc,
const llvm::Twine &intrinsicName,
464 mlir::Type resultTy, mlir::ValueRange operands) {
465 auto intrinsicNameAttr =
466 mlir::StringAttr::get(rewriter.getContext(), intrinsicName);
467 return mlir::LLVM::CallIntrinsicOp::create(rewriter, loc, resultTy,
468 intrinsicNameAttr, operands);
472 mlir::ConversionPatternRewriter &rewriter, mlir::Operation *op,
473 const llvm::Twine &intrinsicName, mlir::Type resultTy,
474 mlir::ValueRange operands) {
476 rewriter, op->getLoc(), intrinsicName, resultTy, operands);
477 rewriter.replaceOp(op, callIntrinOp.getOperation());
481mlir::LogicalResult CIRToLLVMLLVMIntrinsicCallOpLowering::matchAndRewrite(
482 cir::LLVMIntrinsicCallOp op, OpAdaptor adaptor,
483 mlir::ConversionPatternRewriter &rewriter)
const {
484 mlir::Type llvmResTy =
485 getTypeConverter()->convertType(op->getResultTypes()[0]);
487 return op.emitError(
"expected LLVM result type");
488 StringRef name = op.getIntrinsicName();
501 adaptor.getOperands());
502 return mlir::success();
507 mlir::Location loc = parentOp->getLoc();
508 return mlir::LLVM::ConstantOp::create(
509 rewriter, loc, converter->convertType(intAttr.getType()),
515 mlir::Location loc = parentOp->getLoc();
516 return mlir::LLVM::ConstantOp::create(
517 rewriter, loc, converter->convertType(fltAttr.getType()),
523 auto complexType = mlir::cast<cir::ComplexType>(complexAttr.getType());
524 mlir::Type complexElemTy = complexType.getElementType();
525 mlir::Type complexElemLLVMTy = converter->convertType(complexElemTy);
527 mlir::Attribute components[2];
528 if (
const auto intType = mlir::dyn_cast<cir::IntType>(complexElemTy)) {
529 components[0] = rewriter.getIntegerAttr(
531 mlir::cast<cir::IntAttr>(complexAttr.getReal()).getValue());
532 components[1] = rewriter.getIntegerAttr(
534 mlir::cast<cir::IntAttr>(complexAttr.getImag()).getValue());
536 components[0] = rewriter.getFloatAttr(
538 mlir::cast<cir::FPAttr>(complexAttr.getReal()).getValue());
539 components[1] = rewriter.getFloatAttr(
541 mlir::cast<cir::FPAttr>(complexAttr.getImag()).getValue());
544 mlir::Location loc = parentOp->getLoc();
545 return mlir::LLVM::ConstantOp::create(
546 rewriter, loc, converter->convertType(complexAttr.getType()),
547 rewriter.getArrayAttr(components));
552 mlir::Location loc = parentOp->getLoc();
553 if (ptrAttr.isNullValue()) {
554 return mlir::LLVM::ZeroOp::create(
555 rewriter, loc, converter->convertType(ptrAttr.getType()));
557 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
558 mlir::Value ptrVal = mlir::LLVM::ConstantOp::create(
560 rewriter.getIntegerType(layout.getTypeSizeInBits(ptrAttr.getType())),
561 ptrAttr.getValue().getInt());
562 return mlir::LLVM::IntToPtrOp::create(
563 rewriter, loc, converter->convertType(ptrAttr.getType()), ptrVal);
568 mlir::Type llvmTy = converter->convertType(attr.getType());
569 mlir::Location loc = parentOp->getLoc();
572 if (attr.hasTrailingZeros()) {
573 mlir::Type arrayTy = attr.getType();
574 result = mlir::LLVM::ZeroOp::create(rewriter, loc,
575 converter->convertType(arrayTy));
577 result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
581 if (
auto arrayAttr = mlir::dyn_cast<mlir::ArrayAttr>(attr.getElts())) {
582 for (
auto [idx, elt] : llvm::enumerate(arrayAttr)) {
583 mlir::DataLayout dataLayout(parentOp->getParentOfType<mlir::ModuleOp>());
584 mlir::Value init =
visit(elt);
586 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
588 }
else if (
auto strAttr = mlir::dyn_cast<mlir::StringAttr>(attr.getElts())) {
591 auto arrayTy = mlir::dyn_cast<cir::ArrayType>(strAttr.getType());
592 assert(arrayTy &&
"String attribute must have an array type");
593 mlir::Type eltTy = arrayTy.getElementType();
594 for (
auto [idx, elt] : llvm::enumerate(strAttr)) {
595 auto init = mlir::LLVM::ConstantOp::create(
596 rewriter, loc, converter->convertType(eltTy), elt);
598 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
601 llvm_unreachable(
"unexpected ConstArrayAttr elements");
609 const mlir::Type llvmTy = converter->convertType(constRecord.getType());
610 const mlir::Location loc = parentOp->getLoc();
611 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
614 for (
auto [idx, elt] : llvm::enumerate(constRecord.getMembers())) {
615 mlir::Value init =
visit(elt);
617 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
625 const mlir::Type llvmTy = converter->convertType(attr.getType());
626 const mlir::Location loc = parentOp->getLoc();
629 for (
const mlir::Attribute elementAttr : attr.getElts()) {
630 mlir::Attribute mlirAttr;
631 if (
auto intAttr = mlir::dyn_cast<cir::IntAttr>(elementAttr)) {
632 mlirAttr = rewriter.getIntegerAttr(
633 converter->convertType(intAttr.getType()), intAttr.getValue());
634 }
else if (
auto floatAttr = mlir::dyn_cast<cir::FPAttr>(elementAttr)) {
635 mlirAttr = rewriter.getFloatAttr(
636 converter->convertType(floatAttr.getType()), floatAttr.getValue());
639 "vector constant with an element that is neither an int nor a float");
641 mlirValues.push_back(mlirAttr);
644 return mlir::LLVM::ConstantOp::create(
645 rewriter, loc, llvmTy,
646 mlir::DenseElementsAttr::get(mlir::cast<mlir::ShapedType>(llvmTy),
652 auto moduleOp = parentOp->getParentOfType<mlir::ModuleOp>();
653 mlir::DataLayout dataLayout(moduleOp);
654 mlir::Type sourceType;
656 llvm::StringRef symName;
657 mlir::Operation *sourceSymbol =
658 mlir::SymbolTable::lookupSymbolIn(moduleOp, globalAttr.getSymbol());
659 if (
auto llvmSymbol = dyn_cast<mlir::LLVM::GlobalOp>(sourceSymbol)) {
660 sourceType = llvmSymbol.getType();
661 symName = llvmSymbol.getSymName();
662 }
else if (
auto cirSymbol = dyn_cast<cir::GlobalOp>(sourceSymbol)) {
665 symName = cirSymbol.getSymName();
666 }
else if (
auto llvmFun = dyn_cast<mlir::LLVM::LLVMFuncOp>(sourceSymbol)) {
667 sourceType = llvmFun.getFunctionType();
668 symName = llvmFun.getSymName();
669 }
else if (
auto fun = dyn_cast<cir::FuncOp>(sourceSymbol)) {
670 sourceType = converter->convertType(fun.getFunctionType());
671 symName = fun.getSymName();
672 }
else if (
auto alias = dyn_cast<mlir::LLVM::AliasOp>(sourceSymbol)) {
673 sourceType = alias.getType();
674 symName = alias.getSymName();
676 llvm_unreachable(
"Unexpected GlobalOp type");
679 mlir::Location loc = parentOp->getLoc();
680 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
681 rewriter, loc, mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
684 if (globalAttr.getIndices()) {
687 if (mlir::isa<mlir::LLVM::LLVMArrayType, mlir::LLVM::LLVMStructType>(
689 indices.push_back(0);
691 for (mlir::Attribute idx : globalAttr.getIndices()) {
692 auto intAttr = mlir::cast<mlir::IntegerAttr>(idx);
693 indices.push_back(intAttr.getValue().getSExtValue());
695 mlir::Type resTy = addrOp.getType();
696 mlir::Type eltTy = converter->convertType(sourceType);
698 mlir::LLVM::GEPOp::create(rewriter, loc, resTy, eltTy, addrOp, indices,
699 mlir::LLVM::GEPNoWrapFlags::none);
706 if (
auto intTy = mlir::dyn_cast<cir::IntType>(globalAttr.getType())) {
707 mlir::Type llvmDstTy = converter->convertType(globalAttr.getType());
708 return mlir::LLVM::PtrToIntOp::create(rewriter, parentOp->getLoc(),
712 if (
auto ptrTy = mlir::dyn_cast<cir::PointerType>(globalAttr.getType())) {
713 mlir::Type llvmEltTy =
716 if (llvmEltTy == sourceType)
719 mlir::Type llvmDstTy = converter->convertType(globalAttr.getType());
720 return mlir::LLVM::BitcastOp::create(rewriter, parentOp->getLoc(),
724 llvm_unreachable(
"Expecting pointer or integer type for GlobalViewAttr");
729 mlir::Type llvmTy = converter->convertType(typeInfoAttr.getType());
730 mlir::Location loc = parentOp->getLoc();
731 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
733 for (
auto [idx, elt] : llvm::enumerate(typeInfoAttr.getData())) {
734 mlir::Value init =
visit(elt);
736 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
744 mlir::Location loc = parentOp->getLoc();
745 return mlir::LLVM::UndefOp::create(
746 rewriter, loc, converter->convertType(undefAttr.getType()));
751 mlir::Type llvmTy = converter->convertType(vtableArr.getType());
752 mlir::Location loc = parentOp->getLoc();
753 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
755 for (
auto [idx, elt] : llvm::enumerate(vtableArr.getData())) {
756 mlir::Value init =
visit(elt);
758 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
766 mlir::Location loc = parentOp->getLoc();
767 return mlir::LLVM::ZeroOp::create(rewriter, loc,
768 converter->convertType(attr.getType()));
776 mlir::ConversionPatternRewriter &rewriter)
777 : llvmType(type), rewriter(rewriter) {}
779 mlir::Attribute
visit(mlir::Attribute attr) {
780 return llvm::TypeSwitch<mlir::Attribute, mlir::Attribute>(attr)
781 .Case<cir::IntAttr, cir::FPAttr, cir::BoolAttr>(
783 .Default([&](
auto attrT) {
return mlir::Attribute(); });
787 return rewriter.getIntegerAttr(llvmType, attr.getValue());
791 return rewriter.getFloatAttr(llvmType, attr.getValue());
795 return rewriter.getBoolAttr(attr.getValue());
800 mlir::ConversionPatternRewriter &rewriter;
808 :
public mlir::PassWrapper<ConvertCIRToLLVMPass,
809 mlir::OperationPass<mlir::ModuleOp>> {
811 registry.insert<mlir::BuiltinDialect, mlir::DLTIDialect,
812 mlir::LLVM::LLVMDialect, mlir::func::FuncDialect>();
821 return "Convert the prepared CIR dialect module to LLVM dialect";
824 StringRef
getArgument()
const override {
return "cir-flat-to-llvm"; }
827mlir::LogicalResult CIRToLLVMACosOpLowering::matchAndRewrite(
828 cir::ACosOp op, OpAdaptor adaptor,
829 mlir::ConversionPatternRewriter &rewriter)
const {
830 mlir::Type resTy = typeConverter->convertType(op.getType());
831 rewriter.replaceOpWithNewOp<mlir::LLVM::ACosOp>(op, resTy,
832 adaptor.getOperands()[0]);
833 return mlir::success();
836mlir::LogicalResult CIRToLLVMASinOpLowering::matchAndRewrite(
837 cir::ASinOp op, OpAdaptor adaptor,
838 mlir::ConversionPatternRewriter &rewriter)
const {
839 mlir::Type resTy = typeConverter->convertType(op.getType());
840 rewriter.replaceOpWithNewOp<mlir::LLVM::ASinOp>(op, resTy, adaptor.getSrc());
841 return mlir::success();
844mlir::LogicalResult CIRToLLVMIsFPClassOpLowering::matchAndRewrite(
845 cir::IsFPClassOp op, OpAdaptor adaptor,
846 mlir::ConversionPatternRewriter &rewriter)
const {
847 mlir::Value src = adaptor.getSrc();
848 cir::FPClassTest flags = adaptor.getFlags();
849 mlir::IntegerType retTy = rewriter.getI1Type();
851 rewriter.replaceOpWithNewOp<mlir::LLVM::IsFPClass>(
852 op, retTy, src,
static_cast<uint32_t>(flags));
853 return mlir::success();
856mlir::LogicalResult CIRToLLVMSignBitOpLowering::matchAndRewrite(
857 cir::SignBitOp op, OpAdaptor adaptor,
858 mlir::ConversionPatternRewriter &rewriter)
const {
861 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
862 int width = layout.getTypeSizeInBits(op.getInput().getType());
863 if (
auto longDoubleType =
864 mlir::dyn_cast<cir::LongDoubleType>(op.getInput().getType())) {
865 if (mlir::isa<cir::FP80Type>(longDoubleType.getUnderlying())) {
873 mlir::Type intTy = mlir::IntegerType::get(rewriter.getContext(), width);
874 auto bitcast = mlir::LLVM::BitcastOp::create(rewriter, op->getLoc(), intTy,
877 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op->getLoc(), intTy, 0);
878 auto cmpResult = mlir::LLVM::ICmpOp::create(rewriter, op.getLoc(),
879 mlir::LLVM::ICmpPredicate::slt,
880 bitcast.getResult(), zero);
881 rewriter.replaceOp(op, cmpResult);
882 return mlir::success();
885mlir::LogicalResult CIRToLLVMAssumeOpLowering::matchAndRewrite(
886 cir::AssumeOp op, OpAdaptor adaptor,
887 mlir::ConversionPatternRewriter &rewriter)
const {
888 auto cond = adaptor.getPredicate();
889 rewriter.replaceOpWithNewOp<mlir::LLVM::AssumeOp>(op, cond);
890 return mlir::success();
893mlir::LogicalResult CIRToLLVMAssumeAlignedOpLowering::matchAndRewrite(
894 cir::AssumeAlignedOp op, OpAdaptor adaptor,
895 mlir::ConversionPatternRewriter &rewriter)
const {
896 SmallVector<mlir::Value, 3> opBundleArgs{adaptor.getPointer()};
898 auto alignment = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
899 adaptor.getAlignmentAttr());
900 opBundleArgs.push_back(alignment);
902 if (mlir::Value offset = adaptor.getOffset())
903 opBundleArgs.push_back(offset);
905 auto cond = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
906 rewriter.getI1Type(), 1);
907 mlir::LLVM::AssumeOp::create(rewriter, op.getLoc(), cond,
"align",
912 rewriter.replaceOp(op, adaptor.getPointer());
913 return mlir::success();
916mlir::LogicalResult CIRToLLVMAssumeSepStorageOpLowering::matchAndRewrite(
917 cir::AssumeSepStorageOp op, OpAdaptor adaptor,
918 mlir::ConversionPatternRewriter &rewriter)
const {
919 auto cond = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
920 rewriter.getI1Type(), 1);
921 rewriter.replaceOpWithNewOp<mlir::LLVM::AssumeOp>(
922 op, cond, mlir::LLVM::AssumeSeparateStorageTag{}, adaptor.getPtr1(),
924 return mlir::success();
927static mlir::LLVM::AtomicOrdering
930 return mlir::LLVM::AtomicOrdering::not_atomic;
932 case cir::MemOrder::Relaxed:
933 return mlir::LLVM::AtomicOrdering::monotonic;
934 case cir::MemOrder::Consume:
935 case cir::MemOrder::Acquire:
936 return mlir::LLVM::AtomicOrdering::acquire;
937 case cir::MemOrder::Release:
938 return mlir::LLVM::AtomicOrdering::release;
939 case cir::MemOrder::AcquireRelease:
940 return mlir::LLVM::AtomicOrdering::acq_rel;
941 case cir::MemOrder::SequentiallyConsistent:
942 return mlir::LLVM::AtomicOrdering::seq_cst;
944 llvm_unreachable(
"unknown memory order");
948 return syncScope == cir::SyncScopeKind::SingleThread ?
"singlethread" :
"";
951static std::optional<llvm::StringRef>
953 if (syncScope.has_value())
958mlir::LogicalResult CIRToLLVMAtomicCmpXchgOpLowering::matchAndRewrite(
959 cir::AtomicCmpXchgOp op, OpAdaptor adaptor,
960 mlir::ConversionPatternRewriter &rewriter)
const {
961 mlir::Value expected = adaptor.getExpected();
962 mlir::Value desired = adaptor.getDesired();
964 auto cmpxchg = mlir::LLVM::AtomicCmpXchgOp::create(
965 rewriter, op.getLoc(), adaptor.getPtr(), expected, desired,
970 cmpxchg.setAlignment(adaptor.getAlignment());
971 cmpxchg.setWeak(adaptor.getWeak());
972 cmpxchg.setVolatile_(adaptor.getIsVolatile());
975 auto old = mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(),
976 cmpxchg.getResult(), 0);
977 auto cmp = mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(),
978 cmpxchg.getResult(), 1);
980 rewriter.replaceOp(op, {old, cmp});
981 return mlir::success();
984mlir::LogicalResult CIRToLLVMAtomicXchgOpLowering::matchAndRewrite(
985 cir::AtomicXchgOp op, OpAdaptor adaptor,
986 mlir::ConversionPatternRewriter &rewriter)
const {
988 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(adaptor.getMemOrder());
990 rewriter.replaceOpWithNewOp<mlir::LLVM::AtomicRMWOp>(
991 op, mlir::LLVM::AtomicBinOp::xchg, adaptor.getPtr(), adaptor.getVal(),
992 llvmOrder, llvmSyncScope);
993 return mlir::success();
996mlir::LogicalResult CIRToLLVMAtomicTestAndSetOpLowering::matchAndRewrite(
997 cir::AtomicTestAndSetOp op, OpAdaptor adaptor,
998 mlir::ConversionPatternRewriter &rewriter)
const {
1001 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
1003 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1004 rewriter.getI8Type(), 1);
1005 auto rmw = mlir::LLVM::AtomicRMWOp::create(
1006 rewriter, op.getLoc(), mlir::LLVM::AtomicBinOp::xchg, adaptor.getPtr(),
1007 one, llvmOrder, llvm::StringRef(),
1008 adaptor.getAlignment().value_or(0), op.getIsVolatile());
1010 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1011 rewriter.getI8Type(), 0);
1012 auto cmp = mlir::LLVM::ICmpOp::create(
1013 rewriter, op.getLoc(), mlir::LLVM::ICmpPredicate::ne, rmw, zero);
1015 rewriter.replaceOp(op, cmp);
1016 return mlir::success();
1019mlir::LogicalResult CIRToLLVMAtomicClearOpLowering::matchAndRewrite(
1020 cir::AtomicClearOp op, OpAdaptor adaptor,
1021 mlir::ConversionPatternRewriter &rewriter)
const {
1024 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
1025 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1026 rewriter.getI8Type(), 0);
1027 auto store = mlir::LLVM::StoreOp::create(
1028 rewriter, op.getLoc(), zero, adaptor.getPtr(),
1029 adaptor.getAlignment().value_or(0), op.getIsVolatile(),
1030 false,
false, llvmOrder);
1032 rewriter.replaceOp(op, store);
1033 return mlir::success();
1036mlir::LogicalResult CIRToLLVMAtomicFenceOpLowering::matchAndRewrite(
1037 cir::AtomicFenceOp op, OpAdaptor adaptor,
1038 mlir::ConversionPatternRewriter &rewriter)
const {
1039 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(adaptor.getOrdering());
1041 auto fence = mlir::LLVM::FenceOp::create(rewriter, op.getLoc(), llvmOrder);
1044 rewriter.replaceOp(op, fence);
1046 return mlir::success();
1049static mlir::LLVM::AtomicBinOp
1052 case cir::AtomicFetchKind::Add:
1053 return isInt ? mlir::LLVM::AtomicBinOp::add : mlir::LLVM::AtomicBinOp::fadd;
1054 case cir::AtomicFetchKind::Sub:
1055 return isInt ? mlir::LLVM::AtomicBinOp::sub : mlir::LLVM::AtomicBinOp::fsub;
1056 case cir::AtomicFetchKind::And:
1057 return mlir::LLVM::AtomicBinOp::_and;
1058 case cir::AtomicFetchKind::Xor:
1059 return mlir::LLVM::AtomicBinOp::_xor;
1060 case cir::AtomicFetchKind::Or:
1061 return mlir::LLVM::AtomicBinOp::_or;
1062 case cir::AtomicFetchKind::Nand:
1063 return mlir::LLVM::AtomicBinOp::nand;
1064 case cir::AtomicFetchKind::Max: {
1066 return mlir::LLVM::AtomicBinOp::fmax;
1067 return isSignedInt ? mlir::LLVM::AtomicBinOp::max
1068 : mlir::LLVM::AtomicBinOp::umax;
1070 case cir::AtomicFetchKind::Min: {
1072 return mlir::LLVM::AtomicBinOp::fmin;
1073 return isSignedInt ? mlir::LLVM::AtomicBinOp::min
1074 : mlir::LLVM::AtomicBinOp::umin;
1077 llvm_unreachable(
"Unknown atomic fetch opcode");
1080static llvm::StringLiteral
getLLVMBinop(cir::AtomicFetchKind k,
bool isInt) {
1082 case cir::AtomicFetchKind::Add:
1083 return isInt ? mlir::LLVM::AddOp::getOperationName()
1084 : mlir::LLVM::FAddOp::getOperationName();
1085 case cir::AtomicFetchKind::Sub:
1086 return isInt ? mlir::LLVM::SubOp::getOperationName()
1087 : mlir::LLVM::FSubOp::getOperationName();
1088 case cir::AtomicFetchKind::And:
1089 return mlir::LLVM::AndOp::getOperationName();
1090 case cir::AtomicFetchKind::Xor:
1091 return mlir::LLVM::XOrOp::getOperationName();
1092 case cir::AtomicFetchKind::Or:
1093 return mlir::LLVM::OrOp::getOperationName();
1094 case cir::AtomicFetchKind::Nand:
1096 return mlir::LLVM::AndOp::getOperationName();
1097 case cir::AtomicFetchKind::Max:
1098 case cir::AtomicFetchKind::Min:
1099 llvm_unreachable(
"handled in buildMinMaxPostOp");
1101 llvm_unreachable(
"Unknown atomic fetch opcode");
1104mlir::Value CIRToLLVMAtomicFetchOpLowering::buildPostOp(
1105 cir::AtomicFetchOp op, OpAdaptor adaptor,
1106 mlir::ConversionPatternRewriter &rewriter, mlir::Value rmwVal,
1111 .create(op.getLoc(),
1112 rewriter.getStringAttr(
getLLVMBinop(op.getBinop(), isInt)),
1113 atomicOperands, atomicResTys, {})
1117mlir::Value CIRToLLVMAtomicFetchOpLowering::buildMinMaxPostOp(
1118 cir::AtomicFetchOp op, OpAdaptor adaptor,
1119 mlir::ConversionPatternRewriter &rewriter, mlir::Value rmwVal,
bool isInt,
1120 bool isSigned)
const {
1121 mlir::Location loc = op.getLoc();
1124 if (op.getBinop() == cir::AtomicFetchKind::Max)
1125 return mlir::LLVM::MaxNumOp::create(rewriter, loc, rmwVal,
1127 return mlir::LLVM::MinNumOp::create(rewriter, loc, rmwVal,
1131 mlir::LLVM::ICmpPredicate pred;
1132 if (op.getBinop() == cir::AtomicFetchKind::Max) {
1133 pred = isSigned ? mlir::LLVM::ICmpPredicate::sgt
1134 : mlir::LLVM::ICmpPredicate::ugt;
1136 pred = isSigned ? mlir::LLVM::ICmpPredicate::slt
1137 : mlir::LLVM::ICmpPredicate::ult;
1139 mlir::Value cmp = mlir::LLVM::ICmpOp::create(
1141 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(), pred), rmwVal,
1143 return mlir::LLVM::SelectOp::create(rewriter, loc, cmp, rmwVal,
1147mlir::LogicalResult CIRToLLVMAtomicFetchOpLowering::matchAndRewrite(
1148 cir::AtomicFetchOp op, OpAdaptor adaptor,
1149 mlir::ConversionPatternRewriter &rewriter)
const {
1151 bool isSignedInt =
false;
1152 if (
auto intTy = mlir::dyn_cast<cir::IntType>(op.getVal().getType())) {
1154 isSignedInt = intTy.isSigned();
1155 }
else if (mlir::isa<cir::SingleType, cir::DoubleType>(
1156 op.getVal().getType())) {
1159 return op.emitError() <<
"Unsupported type: " << op.getVal().getType();
1162 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
1164 mlir::LLVM::AtomicBinOp llvmBinOp =
1166 auto rmwVal = mlir::LLVM::AtomicRMWOp::create(
1167 rewriter, op.getLoc(), llvmBinOp, adaptor.getPtr(), adaptor.getVal(),
1168 llvmOrder, llvmSyncScope);
1170 mlir::Value result = rmwVal.getResult();
1171 if (!op.getFetchFirst()) {
1172 if (op.getBinop() == cir::AtomicFetchKind::Max ||
1173 op.getBinop() == cir::AtomicFetchKind::Min)
1174 result = buildMinMaxPostOp(op, adaptor, rewriter, rmwVal.getRes(), isInt,
1177 result = buildPostOp(op, adaptor, rewriter, rmwVal.getRes(), isInt);
1180 if (op.getBinop() == cir::AtomicFetchKind::Nand) {
1181 auto negOne = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1182 result.getType(), -1);
1183 result = mlir::LLVM::XOrOp::create(rewriter, op.getLoc(), result, negOne);
1187 rewriter.replaceOp(op, result);
1188 return mlir::success();
1191mlir::LogicalResult CIRToLLVMBitClrsbOpLowering::matchAndRewrite(
1192 cir::BitClrsbOp op, OpAdaptor adaptor,
1193 mlir::ConversionPatternRewriter &rewriter)
const {
1194 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1195 adaptor.getInput().getType(), 0);
1196 auto isNeg = mlir::LLVM::ICmpOp::create(
1197 rewriter, op.getLoc(),
1198 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(),
1199 mlir::LLVM::ICmpPredicate::slt),
1200 adaptor.getInput(), zero);
1202 auto negOne = mlir::LLVM::ConstantOp::create(
1203 rewriter, op.getLoc(), adaptor.getInput().getType(), -1);
1204 auto flipped = mlir::LLVM::XOrOp::create(rewriter, op.getLoc(),
1205 adaptor.getInput(), negOne);
1207 auto select = mlir::LLVM::SelectOp::create(rewriter, op.getLoc(), isNeg,
1208 flipped, adaptor.getInput());
1210 auto resTy = getTypeConverter()->convertType(op.getType());
1211 auto clz = mlir::LLVM::CountLeadingZerosOp::create(
1212 rewriter, op.getLoc(), resTy,
select,
false);
1214 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1215 auto res = mlir::LLVM::SubOp::create(rewriter, op.getLoc(),
clz, one,
1216 mlir::LLVM::IntegerOverflowFlags::nuw);
1217 rewriter.replaceOp(op, res);
1219 return mlir::LogicalResult::success();
1222mlir::LogicalResult CIRToLLVMBitClzOpLowering::matchAndRewrite(
1223 cir::BitClzOp op, OpAdaptor adaptor,
1224 mlir::ConversionPatternRewriter &rewriter)
const {
1225 auto resTy = getTypeConverter()->convertType(op.getType());
1226 auto llvmOp = mlir::LLVM::CountLeadingZerosOp::create(
1227 rewriter, op.getLoc(), resTy, adaptor.getInput(), op.getPoisonZero());
1228 rewriter.replaceOp(op, llvmOp);
1229 return mlir::LogicalResult::success();
1232mlir::LogicalResult CIRToLLVMBitCtzOpLowering::matchAndRewrite(
1233 cir::BitCtzOp op, OpAdaptor adaptor,
1234 mlir::ConversionPatternRewriter &rewriter)
const {
1235 auto resTy = getTypeConverter()->convertType(op.getType());
1236 auto llvmOp = mlir::LLVM::CountTrailingZerosOp::create(
1237 rewriter, op.getLoc(), resTy, adaptor.getInput(), op.getPoisonZero());
1238 rewriter.replaceOp(op, llvmOp);
1239 return mlir::LogicalResult::success();
1242mlir::LogicalResult CIRToLLVMBitFfsOpLowering::matchAndRewrite(
1243 cir::BitFfsOp op, OpAdaptor adaptor,
1244 mlir::ConversionPatternRewriter &rewriter)
const {
1245 auto resTy = getTypeConverter()->convertType(op.getType());
1246 auto ctz = mlir::LLVM::CountTrailingZerosOp::create(rewriter, op.getLoc(),
1247 resTy, adaptor.getInput(),
1250 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1251 auto ctzAddOne = mlir::LLVM::AddOp::create(rewriter, op.getLoc(),
ctz, one);
1253 auto zeroInputTy = mlir::LLVM::ConstantOp::create(
1254 rewriter, op.getLoc(), adaptor.getInput().getType(), 0);
1255 auto isZero = mlir::LLVM::ICmpOp::create(
1256 rewriter, op.getLoc(),
1257 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(),
1258 mlir::LLVM::ICmpPredicate::eq),
1259 adaptor.getInput(), zeroInputTy);
1261 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 0);
1262 auto res = mlir::LLVM::SelectOp::create(rewriter, op.getLoc(), isZero, zero,
1264 rewriter.replaceOp(op, res);
1266 return mlir::LogicalResult::success();
1269mlir::LogicalResult CIRToLLVMBitParityOpLowering::matchAndRewrite(
1270 cir::BitParityOp op, OpAdaptor adaptor,
1271 mlir::ConversionPatternRewriter &rewriter)
const {
1272 auto resTy = getTypeConverter()->convertType(op.getType());
1273 auto popcnt = mlir::LLVM::CtPopOp::create(rewriter, op.getLoc(), resTy,
1274 adaptor.getInput());
1276 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1278 mlir::LLVM::AndOp::create(rewriter, op.getLoc(), popcnt, one);
1279 rewriter.replaceOp(op, popcntMod2);
1281 return mlir::LogicalResult::success();
1284mlir::LogicalResult CIRToLLVMBitPopcountOpLowering::matchAndRewrite(
1285 cir::BitPopcountOp op, OpAdaptor adaptor,
1286 mlir::ConversionPatternRewriter &rewriter)
const {
1287 auto resTy = getTypeConverter()->convertType(op.getType());
1288 auto llvmOp = mlir::LLVM::CtPopOp::create(rewriter, op.getLoc(), resTy,
1289 adaptor.getInput());
1290 rewriter.replaceOp(op, llvmOp);
1291 return mlir::LogicalResult::success();
1294mlir::LogicalResult CIRToLLVMBitReverseOpLowering::matchAndRewrite(
1295 cir::BitReverseOp op, OpAdaptor adaptor,
1296 mlir::ConversionPatternRewriter &rewriter)
const {
1297 rewriter.replaceOpWithNewOp<mlir::LLVM::BitReverseOp>(op, adaptor.getInput());
1298 return mlir::success();
1301mlir::LogicalResult CIRToLLVMBrCondOpLowering::matchAndRewrite(
1302 cir::BrCondOp brOp, OpAdaptor adaptor,
1303 mlir::ConversionPatternRewriter &rewriter)
const {
1308 mlir::Value i1Condition = adaptor.getCond();
1310 rewriter.replaceOpWithNewOp<mlir::LLVM::CondBrOp>(
1311 brOp, i1Condition, brOp.getDestTrue(), adaptor.getDestOperandsTrue(),
1312 brOp.getDestFalse(), adaptor.getDestOperandsFalse());
1314 return mlir::success();
1317mlir::LogicalResult CIRToLLVMByteSwapOpLowering::matchAndRewrite(
1318 cir::ByteSwapOp op, OpAdaptor adaptor,
1319 mlir::ConversionPatternRewriter &rewriter)
const {
1320 rewriter.replaceOpWithNewOp<mlir::LLVM::ByteSwapOp>(op, adaptor.getInput());
1321 return mlir::LogicalResult::success();
1324mlir::Type CIRToLLVMCastOpLowering::convertTy(mlir::Type ty)
const {
1325 return getTypeConverter()->convertType(ty);
1328mlir::LogicalResult CIRToLLVMCastOpLowering::matchAndRewrite(
1329 cir::CastOp castOp, OpAdaptor adaptor,
1330 mlir::ConversionPatternRewriter &rewriter)
const {
1335 switch (castOp.getKind()) {
1336 case cir::CastKind::array_to_ptrdecay: {
1337 const auto ptrTy = mlir::cast<cir::PointerType>(castOp.getType());
1338 mlir::Value sourceValue = adaptor.getSrc();
1339 mlir::Type targetType = convertTy(ptrTy);
1341 ptrTy.getPointee());
1342 llvm::SmallVector<mlir::LLVM::GEPArg> offset{0};
1343 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1344 castOp, targetType, elementTy, sourceValue, offset);
1347 case cir::CastKind::int_to_bool: {
1348 mlir::Value llvmSrcVal = adaptor.getSrc();
1349 mlir::Value zeroInt = mlir::LLVM::ConstantOp::create(
1350 rewriter, castOp.getLoc(), llvmSrcVal.getType(), 0);
1351 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
1352 castOp, mlir::LLVM::ICmpPredicate::ne, llvmSrcVal, zeroInt);
1355 case cir::CastKind::integral: {
1356 mlir::Type srcType = castOp.getSrc().getType();
1357 mlir::Type dstType = castOp.getType();
1358 mlir::Value llvmSrcVal = adaptor.getSrc();
1359 mlir::Type llvmDstType = getTypeConverter()->convertType(dstType);
1360 cir::IntType srcIntType =
1361 mlir::cast<cir::IntType>(elementTypeIfVector(srcType));
1362 cir::IntType dstIntType =
1363 mlir::cast<cir::IntType>(elementTypeIfVector(dstType));
1364 rewriter.replaceOp(castOp,
getLLVMIntCast(rewriter, llvmSrcVal, llvmDstType,
1365 srcIntType.isUnsigned(),
1366 srcIntType.getWidth(),
1367 dstIntType.getWidth()));
1370 case cir::CastKind::floating: {
1371 mlir::Value llvmSrcVal = adaptor.getSrc();
1372 mlir::Type llvmDstTy = getTypeConverter()->convertType(castOp.getType());
1374 mlir::Type srcTy = elementTypeIfVector(castOp.getSrc().getType());
1375 mlir::Type dstTy = elementTypeIfVector(castOp.getType());
1377 if (!mlir::isa<cir::FPTypeInterface>(dstTy) ||
1378 !mlir::isa<cir::FPTypeInterface>(srcTy))
1379 return castOp.emitError() <<
"NYI cast from " << srcTy <<
" to " << dstTy;
1381 auto getFloatWidth = [](mlir::Type ty) ->
unsigned {
1382 return mlir::cast<cir::FPTypeInterface>(ty).getWidth();
1385 if (getFloatWidth(srcTy) > getFloatWidth(dstTy))
1386 rewriter.replaceOpWithNewOp<mlir::LLVM::FPTruncOp>(castOp, llvmDstTy,
1389 rewriter.replaceOpWithNewOp<mlir::LLVM::FPExtOp>(castOp, llvmDstTy,
1391 return mlir::success();
1393 case cir::CastKind::int_to_ptr: {
1394 auto dstTy = mlir::cast<cir::PointerType>(castOp.getType());
1395 mlir::Value llvmSrcVal = adaptor.getSrc();
1396 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1397 rewriter.replaceOpWithNewOp<mlir::LLVM::IntToPtrOp>(castOp, llvmDstTy,
1399 return mlir::success();
1401 case cir::CastKind::ptr_to_int: {
1402 auto dstTy = mlir::cast<cir::IntType>(castOp.getType());
1403 mlir::Value llvmSrcVal = adaptor.getSrc();
1404 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1405 rewriter.replaceOpWithNewOp<mlir::LLVM::PtrToIntOp>(castOp, llvmDstTy,
1407 return mlir::success();
1409 case cir::CastKind::float_to_bool: {
1410 mlir::Value llvmSrcVal = adaptor.getSrc();
1411 auto kind = mlir::LLVM::FCmpPredicate::une;
1414 auto zeroFloat = mlir::LLVM::ConstantOp::create(
1415 rewriter, castOp.getLoc(), llvmSrcVal.getType(),
1416 mlir::FloatAttr::get(llvmSrcVal.getType(), 0.0));
1419 rewriter.replaceOpWithNewOp<mlir::LLVM::FCmpOp>(castOp,
kind, llvmSrcVal,
1422 return mlir::success();
1424 case cir::CastKind::bool_to_int: {
1425 auto dstTy = mlir::cast<cir::IntType>(castOp.getType());
1426 mlir::Value llvmSrcVal = adaptor.getSrc();
1427 auto llvmSrcTy = mlir::cast<mlir::IntegerType>(llvmSrcVal.getType());
1429 mlir::cast<mlir::IntegerType>(getTypeConverter()->convertType(dstTy));
1431 if (llvmSrcTy.getWidth() == llvmDstTy.getWidth())
1432 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(castOp, llvmDstTy,
1435 rewriter.replaceOpWithNewOp<mlir::LLVM::ZExtOp>(castOp, llvmDstTy,
1437 return mlir::success();
1439 case cir::CastKind::bool_to_float: {
1440 mlir::Type dstTy = castOp.getType();
1441 mlir::Value llvmSrcVal = adaptor.getSrc();
1442 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1443 rewriter.replaceOpWithNewOp<mlir::LLVM::UIToFPOp>(castOp, llvmDstTy,
1445 return mlir::success();
1447 case cir::CastKind::int_to_float: {
1448 mlir::Type dstTy = castOp.getType();
1449 mlir::Value llvmSrcVal = adaptor.getSrc();
1450 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1451 if (mlir::cast<cir::IntType>(elementTypeIfVector(castOp.getSrc().getType()))
1453 rewriter.replaceOpWithNewOp<mlir::LLVM::SIToFPOp>(castOp, llvmDstTy,
1456 rewriter.replaceOpWithNewOp<mlir::LLVM::UIToFPOp>(castOp, llvmDstTy,
1458 return mlir::success();
1460 case cir::CastKind::float_to_int: {
1461 mlir::Type dstTy = castOp.getType();
1462 mlir::Value llvmSrcVal = adaptor.getSrc();
1463 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1464 if (mlir::cast<cir::IntType>(elementTypeIfVector(castOp.getType()))
1466 rewriter.replaceOpWithNewOp<mlir::LLVM::FPToSIOp>(castOp, llvmDstTy,
1469 rewriter.replaceOpWithNewOp<mlir::LLVM::FPToUIOp>(castOp, llvmDstTy,
1471 return mlir::success();
1473 case cir::CastKind::bitcast: {
1474 mlir::Type dstTy = castOp.getType();
1475 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1480 mlir::Value llvmSrcVal = adaptor.getSrc();
1481 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(castOp, llvmDstTy,
1483 return mlir::success();
1485 case cir::CastKind::ptr_to_bool: {
1486 mlir::Value llvmSrcVal = adaptor.getSrc();
1487 mlir::Value zeroPtr = mlir::LLVM::ZeroOp::create(rewriter, castOp.getLoc(),
1488 llvmSrcVal.getType());
1489 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
1490 castOp, mlir::LLVM::ICmpPredicate::ne, llvmSrcVal, zeroPtr);
1493 case cir::CastKind::address_space: {
1494 mlir::Type dstTy = castOp.getType();
1495 mlir::Value llvmSrcVal = adaptor.getSrc();
1496 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1497 rewriter.replaceOpWithNewOp<mlir::LLVM::AddrSpaceCastOp>(castOp, llvmDstTy,
1501 case cir::CastKind::member_ptr_to_bool:
1506 return castOp.emitError(
"Unhandled cast kind: ")
1507 << castOp.getKindAttrName();
1511 return mlir::success();
1515 mlir::ModuleOp mod, mlir::Value index,
1516 mlir::Type baseTy, cir::IntType strideTy) {
1517 mlir::Operation *indexOp = index.getDefiningOp();
1521 auto indexType = mlir::cast<mlir::IntegerType>(index.getType());
1522 mlir::DataLayout llvmLayout(mod);
1523 std::optional<uint64_t> layoutWidth = llvmLayout.getTypeIndexBitwidth(baseTy);
1526 if (!layoutWidth || *layoutWidth == indexType.getWidth())
1532 auto sub = dyn_cast<mlir::LLVM::SubOp>(indexOp);
1533 bool rewriteSub =
false;
1536 dyn_cast<mlir::LLVM::ConstantOp>(sub.getLhs().getDefiningOp())) {
1537 auto lhsConstInt = mlir::dyn_cast<mlir::IntegerAttr>(lhsConst.getValue());
1538 if (lhsConstInt && lhsConstInt.getValue() == 0) {
1539 index = sub.getRhs();
1545 auto llvmDstType = rewriter.getIntegerType(*layoutWidth);
1546 bool isUnsigned = strideTy && strideTy.isUnsigned();
1548 indexType.getWidth(), *layoutWidth);
1551 index = mlir::LLVM::SubOp::create(
1552 rewriter, index.getLoc(),
1553 mlir::LLVM::ConstantOp::create(rewriter, index.getLoc(),
1554 index.getType(), 0),
1557 rewriter.eraseOp(sub);
1563mlir::LogicalResult CIRToLLVMPtrStrideOpLowering::matchAndRewrite(
1564 cir::PtrStrideOp ptrStrideOp, OpAdaptor adaptor,
1565 mlir::ConversionPatternRewriter &rewriter)
const {
1567 const mlir::TypeConverter *tc = getTypeConverter();
1568 const mlir::Type resultTy = tc->convertType(ptrStrideOp.getType());
1570 mlir::Type elementTy =
1575 if (mlir::isa<mlir::LLVM::LLVMVoidType>(elementTy) ||
1576 mlir::isa<mlir::LLVM::LLVMFunctionType>(elementTy))
1577 elementTy = mlir::IntegerType::get(elementTy.getContext(), 8,
1578 mlir::IntegerType::Signless);
1580 mlir::Value index = adaptor.getStride();
1582 rewriter, ptrStrideOp->getParentOfType<mlir::ModuleOp>(), index,
1583 adaptor.getBase().getType(),
1584 dyn_cast<cir::IntType>(ptrStrideOp.getOperand(1).getType()));
1586 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1587 ptrStrideOp, resultTy, elementTy, adaptor.getBase(), index);
1588 return mlir::success();
1591mlir::LogicalResult CIRToLLVMGetElementOpLowering::matchAndRewrite(
1592 cir::GetElementOp op, OpAdaptor adaptor,
1593 mlir::ConversionPatternRewriter &rewriter)
const {
1595 mlir::dyn_cast<cir::ArrayType>(op.getBaseType().getPointee())) {
1596 const mlir::TypeConverter *converter = getTypeConverter();
1597 const mlir::Type llArrayTy = converter->convertType(arrayTy);
1598 const mlir::Type llResultTy = converter->convertType(op.getType());
1599 mlir::Type elementTy =
1604 if (mlir::isa<mlir::LLVM::LLVMVoidType>(elementTy) ||
1605 mlir::isa<mlir::LLVM::LLVMFunctionType>(elementTy))
1606 elementTy = rewriter.getIntegerType(8);
1608 mlir::Value index = adaptor.getIndex();
1611 adaptor.getBase().getType(),
1612 dyn_cast<cir::IntType>(op.getOperand(1).getType()));
1617 std::array<mlir::LLVM::GEPArg, 2> offset{0, index};
1618 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, llResultTy, llArrayTy,
1619 adaptor.getBase(), offset);
1620 return mlir::success();
1623 op.emitError() <<
"NYI: GetElementOp lowering to LLVM for non-array";
1624 return mlir::failure();
1627mlir::LogicalResult CIRToLLVMBaseClassAddrOpLowering::matchAndRewrite(
1628 cir::BaseClassAddrOp baseClassOp, OpAdaptor adaptor,
1629 mlir::ConversionPatternRewriter &rewriter)
const {
1630 const mlir::Type resultType =
1631 getTypeConverter()->convertType(baseClassOp.getType());
1632 mlir::Value derivedAddr = adaptor.getDerivedAddr();
1633 llvm::SmallVector<mlir::LLVM::GEPArg, 1> offset = {
1634 adaptor.getOffset().getZExtValue()};
1635 mlir::Type byteType = mlir::IntegerType::get(resultType.getContext(), 8,
1636 mlir::IntegerType::Signless);
1637 if (adaptor.getOffset().getZExtValue() == 0) {
1638 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(
1639 baseClassOp, resultType, adaptor.getDerivedAddr());
1640 return mlir::success();
1643 if (baseClassOp.getAssumeNotNull()) {
1644 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1645 baseClassOp, resultType, byteType, derivedAddr, offset);
1647 auto loc = baseClassOp.getLoc();
1648 mlir::Value isNull = mlir::LLVM::ICmpOp::create(
1649 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, derivedAddr,
1650 mlir::LLVM::ZeroOp::create(rewriter, loc, derivedAddr.getType()));
1651 mlir::Value adjusted = mlir::LLVM::GEPOp::create(
1652 rewriter, loc, resultType, byteType, derivedAddr, offset);
1653 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(baseClassOp, isNull,
1654 derivedAddr, adjusted);
1656 return mlir::success();
1659mlir::LogicalResult CIRToLLVMDerivedClassAddrOpLowering::matchAndRewrite(
1660 cir::DerivedClassAddrOp derivedClassOp, OpAdaptor adaptor,
1661 mlir::ConversionPatternRewriter &rewriter)
const {
1662 const mlir::Type resultType =
1663 getTypeConverter()->convertType(derivedClassOp.getType());
1664 mlir::Value baseAddr = adaptor.getBaseAddr();
1667 int64_t offsetVal = -(adaptor.getOffset().getZExtValue());
1668 if (offsetVal == 0) {
1670 rewriter.replaceOp(derivedClassOp, baseAddr);
1671 return mlir::success();
1673 llvm::SmallVector<mlir::LLVM::GEPArg, 1> offset = {offsetVal};
1674 mlir::Type byteType = mlir::IntegerType::get(resultType.getContext(), 8,
1675 mlir::IntegerType::Signless);
1676 if (derivedClassOp.getAssumeNotNull()) {
1677 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1678 derivedClassOp, resultType, byteType, baseAddr, offset,
1679 mlir::LLVM::GEPNoWrapFlags::inbounds);
1681 mlir::Location loc = derivedClassOp.getLoc();
1682 mlir::Value isNull = mlir::LLVM::ICmpOp::create(
1683 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, baseAddr,
1684 mlir::LLVM::ZeroOp::create(rewriter, loc, baseAddr.getType()));
1685 mlir::Value adjusted =
1686 mlir::LLVM::GEPOp::create(rewriter, loc, resultType, byteType, baseAddr,
1687 offset, mlir::LLVM::GEPNoWrapFlags::inbounds);
1688 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(derivedClassOp, isNull,
1689 baseAddr, adjusted);
1691 return mlir::success();
1694mlir::LogicalResult CIRToLLVMATanOpLowering::matchAndRewrite(
1695 cir::ATanOp op, OpAdaptor adaptor,
1696 mlir::ConversionPatternRewriter &rewriter)
const {
1697 mlir::Type resTy = typeConverter->convertType(op.getType());
1698 rewriter.replaceOpWithNewOp<mlir::LLVM::ATanOp>(op, resTy, adaptor.getSrc());
1699 return mlir::success();
1702mlir::LogicalResult CIRToLLVMCeilOpLowering::matchAndRewrite(
1703 cir::CeilOp op, OpAdaptor adaptor,
1704 mlir::ConversionPatternRewriter &rewriter)
const {
1705 mlir::Type resTy = typeConverter->convertType(op.getType());
1706 rewriter.replaceOpWithNewOp<mlir::LLVM::FCeilOp>(op, resTy, adaptor.getSrc());
1707 return mlir::success();
1710mlir::LogicalResult CIRToLLVMCopysignOpLowering::matchAndRewrite(
1711 cir::CopysignOp op, OpAdaptor adaptor,
1712 mlir::ConversionPatternRewriter &rewriter)
const {
1713 mlir::Type resTy = typeConverter->convertType(op.getType());
1714 rewriter.replaceOpWithNewOp<mlir::LLVM::CopySignOp>(
1715 op, resTy, adaptor.getLhs(), adaptor.getRhs());
1716 return mlir::success();
1719mlir::LogicalResult CIRToLLVMFMaxNumOpLowering::matchAndRewrite(
1720 cir::FMaxNumOp op, OpAdaptor adaptor,
1721 mlir::ConversionPatternRewriter &rewriter)
const {
1722 mlir::Type resTy = typeConverter->convertType(op.getType());
1723 rewriter.replaceOpWithNewOp<mlir::LLVM::MaxNumOp>(
1724 op, resTy, adaptor.getLhs(), adaptor.getRhs(),
1725 mlir::LLVM::FastmathFlags::nsz);
1726 return mlir::success();
1729mlir::LogicalResult CIRToLLVMFMinNumOpLowering::matchAndRewrite(
1730 cir::FMinNumOp op, OpAdaptor adaptor,
1731 mlir::ConversionPatternRewriter &rewriter)
const {
1732 mlir::Type resTy = typeConverter->convertType(op.getType());
1733 rewriter.replaceOpWithNewOp<mlir::LLVM::MinNumOp>(
1734 op, resTy, adaptor.getLhs(), adaptor.getRhs(),
1735 mlir::LLVM::FastmathFlags::nsz);
1736 return mlir::success();
1739mlir::LogicalResult CIRToLLVMFMaximumOpLowering::matchAndRewrite(
1740 cir::FMaximumOp op, OpAdaptor adaptor,
1741 mlir::ConversionPatternRewriter &rewriter)
const {
1742 mlir::Type resTy = typeConverter->convertType(op.getType());
1743 rewriter.replaceOpWithNewOp<mlir::LLVM::MaximumOp>(
1744 op, resTy, adaptor.getLhs(), adaptor.getRhs());
1745 return mlir::success();
1748mlir::LogicalResult CIRToLLVMFMinimumOpLowering::matchAndRewrite(
1749 cir::FMinimumOp op, OpAdaptor adaptor,
1750 mlir::ConversionPatternRewriter &rewriter)
const {
1751 mlir::Type resTy = typeConverter->convertType(op.getType());
1752 rewriter.replaceOpWithNewOp<mlir::LLVM::MinimumOp>(
1753 op, resTy, adaptor.getLhs(), adaptor.getRhs());
1754 return mlir::success();
1757mlir::LogicalResult CIRToLLVMFModOpLowering::matchAndRewrite(
1758 cir::FModOp op, OpAdaptor adaptor,
1759 mlir::ConversionPatternRewriter &rewriter)
const {
1760 mlir::Type resTy = typeConverter->convertType(op.getType());
1761 rewriter.replaceOpWithNewOp<mlir::LLVM::FRemOp>(op, resTy, adaptor.getLhs(),
1763 return mlir::success();
1766mlir::LogicalResult CIRToLLVMPowOpLowering::matchAndRewrite(
1767 cir::PowOp op, OpAdaptor adaptor,
1768 mlir::ConversionPatternRewriter &rewriter)
const {
1769 mlir::Type resTy = typeConverter->convertType(op.getType());
1770 rewriter.replaceOpWithNewOp<mlir::LLVM::PowOp>(op, resTy, adaptor.getLhs(),
1772 return mlir::success();
1775mlir::LogicalResult CIRToLLVMATan2OpLowering::matchAndRewrite(
1776 cir::ATan2Op op, OpAdaptor adaptor,
1777 mlir::ConversionPatternRewriter &rewriter)
const {
1778 mlir::Type resTy = typeConverter->convertType(op.getType());
1779 rewriter.replaceOpWithNewOp<mlir::LLVM::ATan2Op>(op, resTy, adaptor.getLhs(),
1781 return mlir::success();
1784mlir::LogicalResult CIRToLLVMLroundOpLowering::matchAndRewrite(
1785 cir::LroundOp op, OpAdaptor adaptor,
1786 mlir::ConversionPatternRewriter &rewriter)
const {
1787 mlir::Type resTy = typeConverter->convertType(op.getType());
1788 rewriter.replaceOpWithNewOp<mlir::LLVM::LroundOp>(op, resTy,
1790 return mlir::success();
1793mlir::LogicalResult CIRToLLVMLlroundOpLowering::matchAndRewrite(
1794 cir::LlroundOp op, OpAdaptor adaptor,
1795 mlir::ConversionPatternRewriter &rewriter)
const {
1796 mlir::Type resTy = typeConverter->convertType(op.getType());
1797 rewriter.replaceOpWithNewOp<mlir::LLVM::LlroundOp>(op, resTy,
1799 return mlir::success();
1802mlir::LogicalResult CIRToLLVMLrintOpLowering::matchAndRewrite(
1803 cir::LrintOp op, OpAdaptor adaptor,
1804 mlir::ConversionPatternRewriter &rewriter)
const {
1805 mlir::Type resTy = typeConverter->convertType(op.getType());
1806 rewriter.replaceOpWithNewOp<mlir::LLVM::LrintOp>(op, resTy, adaptor.getSrc());
1807 return mlir::success();
1810mlir::LogicalResult CIRToLLVMLlrintOpLowering::matchAndRewrite(
1811 cir::LlrintOp op, OpAdaptor adaptor,
1812 mlir::ConversionPatternRewriter &rewriter)
const {
1813 mlir::Type resTy = typeConverter->convertType(op.getType());
1814 rewriter.replaceOpWithNewOp<mlir::LLVM::LlrintOp>(op, resTy,
1816 return mlir::success();
1819mlir::LogicalResult CIRToLLVMAllocaOpLowering::matchAndRewrite(
1820 cir::AllocaOp op, OpAdaptor adaptor,
1821 mlir::ConversionPatternRewriter &rewriter)
const {
1824 ? adaptor.getDynAllocSize()
1825 : mlir::LLVM::ConstantOp::create(
1826 rewriter, op.getLoc(),
1827 typeConverter->convertType(rewriter.getIndexType()), 1);
1828 mlir::Type elementTy =
1830 mlir::Type resultTy =
1836 rewriter.replaceOpWithNewOp<mlir::LLVM::AllocaOp>(op, resultTy, elementTy,
1837 size, op.getAlignment());
1839 return mlir::success();
1842mlir::LogicalResult CIRToLLVMReturnOpLowering::matchAndRewrite(
1843 cir::ReturnOp op, OpAdaptor adaptor,
1844 mlir::ConversionPatternRewriter &rewriter)
const {
1845 rewriter.replaceOpWithNewOp<mlir::LLVM::ReturnOp>(op, adaptor.getOperands());
1846 return mlir::LogicalResult::success();
1849mlir::LogicalResult CIRToLLVMRotateOpLowering::matchAndRewrite(
1850 cir::RotateOp op, OpAdaptor adaptor,
1851 mlir::ConversionPatternRewriter &rewriter)
const {
1854 mlir::Value input = adaptor.getInput();
1855 if (op.isRotateLeft())
1856 rewriter.replaceOpWithNewOp<mlir::LLVM::FshlOp>(op, input, input,
1857 adaptor.getAmount());
1859 rewriter.replaceOpWithNewOp<mlir::LLVM::FshrOp>(op, input, input,
1860 adaptor.getAmount());
1861 return mlir::LogicalResult::success();
1866 for (mlir::NamedAttribute attr : op->getAttrs()) {
1868 if (attr.getName() == CIRDialect::getCalleeAttrName() ||
1869 attr.getName() == CIRDialect::getSideEffectAttrName() ||
1870 attr.getName() == CIRDialect::getNoThrowAttrName() ||
1871 attr.getName() == CIRDialect::getNoUnwindAttrName() ||
1872 attr.getName() == CIRDialect::getNoReturnAttrName())
1876 result.push_back(attr);
1880static mlir::LogicalResult
1882 mlir::ConversionPatternRewriter &rewriter,
1883 const mlir::TypeConverter *converter,
1884 mlir::FlatSymbolRefAttr calleeAttr,
1885 mlir::Block *continueBlock =
nullptr,
1886 mlir::Block *landingPadBlock =
nullptr) {
1888 mlir::ValueTypeRange<mlir::ResultRange> cirResults = op->getResultTypes();
1889 auto call = cast<cir::CIRCallOpInterface>(op);
1891 if (converter->convertTypes(cirResults, llvmResults).failed())
1892 return mlir::failure();
1896 mlir::LLVM::MemoryEffectsAttr memoryEffects;
1897 bool noUnwind =
false;
1898 bool willReturn =
false;
1899 bool noReturn =
false;
1901 memoryEffects, noUnwind, willReturn, noReturn);
1906 mlir::LLVM::LLVMFunctionType llvmFnTy;
1913 mlir::Operation *callee =
1914 mlir::SymbolTable::lookupNearestSymbolFrom(op, calleeAttr);
1915 if (
auto fn = mlir::dyn_cast<mlir::FunctionOpInterface>(callee)) {
1916 llvmFnTy = converter->convertType<mlir::LLVM::LLVMFunctionType>(
1917 fn.getFunctionType());
1918 assert(llvmFnTy &&
"Failed to convert function type");
1919 }
else if (
auto alias = mlir::cast<mlir::LLVM::AliasOp>(callee)) {
1927 auto symAttr = mlir::cast<mlir::FlatSymbolRefAttr>(calleeAttr);
1929 mlir::LLVM::AddressOfOp::create(
1930 rewriter, op->getLoc(),
1931 mlir::LLVM::LLVMPointerType::get(rewriter.getContext()), symAttr)
1933 adjustedCallOperands.push_back(addrOfAlias);
1936 llvm::append_range(adjustedCallOperands, callOperands);
1937 callOperands = adjustedCallOperands;
1941 llvmFnTy = mlir::cast<mlir::LLVM::LLVMFunctionType>(alias.getType());
1944 return op->emitError(
"Unexpected callee type!");
1947 assert(!op->getOperands().empty() &&
1948 "operands list must no be empty for the indirect call");
1949 auto calleeTy = op->getOperands().front().getType();
1950 auto calleePtrTy = cast<cir::PointerType>(calleeTy);
1951 auto calleeFuncTy = cast<cir::FuncType>(calleePtrTy.getPointee());
1952 llvm::append_range(adjustedCallOperands, callOperands);
1953 llvmFnTy = cast<mlir::LLVM::LLVMFunctionType>(
1954 converter->convertType(calleeFuncTy));
1959 if (landingPadBlock) {
1960 auto newOp = rewriter.replaceOpWithNewOp<mlir::LLVM::InvokeOp>(
1961 op, llvmFnTy, calleeAttr, callOperands, continueBlock,
1962 mlir::ValueRange{}, landingPadBlock, mlir::ValueRange{});
1963 newOp->setAttrs(attributes);
1965 auto newOp = rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(
1966 op, llvmFnTy, calleeAttr, callOperands);
1967 newOp->setAttrs(attributes);
1969 newOp.setMemoryEffectsAttr(memoryEffects);
1970 newOp.setNoUnwind(noUnwind);
1971 newOp.setWillReturn(willReturn);
1972 newOp.setNoreturn(noReturn);
1975 return mlir::success();
1978mlir::LogicalResult CIRToLLVMCallOpLowering::matchAndRewrite(
1979 cir::CallOp op, OpAdaptor adaptor,
1980 mlir::ConversionPatternRewriter &rewriter)
const {
1982 getTypeConverter(), op.getCalleeAttr());
1985mlir::LogicalResult CIRToLLVMTryCallOpLowering::matchAndRewrite(
1986 cir::TryCallOp op, OpAdaptor adaptor,
1987 mlir::ConversionPatternRewriter &rewriter)
const {
1990 getTypeConverter(), op.getCalleeAttr(),
1991 op.getNormalDest(), op.getUnwindDest());
1994mlir::LogicalResult CIRToLLVMReturnAddrOpLowering::matchAndRewrite(
1995 cir::ReturnAddrOp op, OpAdaptor adaptor,
1996 mlir::ConversionPatternRewriter &rewriter)
const {
1997 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
1999 llvmPtrTy, adaptor.getOperands());
2000 return mlir::success();
2003mlir::LogicalResult CIRToLLVMFrameAddrOpLowering::matchAndRewrite(
2004 cir::FrameAddrOp op, OpAdaptor adaptor,
2005 mlir::ConversionPatternRewriter &rewriter)
const {
2006 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
2008 adaptor.getOperands());
2009 return mlir::success();
2012mlir::LogicalResult CIRToLLVMClearCacheOpLowering::matchAndRewrite(
2013 cir::ClearCacheOp op, OpAdaptor adaptor,
2014 mlir::ConversionPatternRewriter &rewriter)
const {
2015 mlir::Value begin = adaptor.getBegin();
2016 mlir::Value end = adaptor.getEnd();
2017 auto intrinNameAttr =
2018 mlir::StringAttr::get(op.getContext(),
"llvm.clear_cache");
2019 rewriter.replaceOpWithNewOp<mlir::LLVM::CallIntrinsicOp>(
2020 op, mlir::Type{}, intrinNameAttr, mlir::ValueRange{begin, end});
2022 return mlir::success();
2025mlir::LogicalResult CIRToLLVMAddrOfReturnAddrOpLowering::matchAndRewrite(
2026 cir::AddrOfReturnAddrOp op, OpAdaptor adaptor,
2027 mlir::ConversionPatternRewriter &rewriter)
const {
2028 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
2030 llvmPtrTy, adaptor.getOperands());
2031 return mlir::success();
2034mlir::LogicalResult CIRToLLVMLoadOpLowering::matchAndRewrite(
2035 cir::LoadOp op, OpAdaptor adaptor,
2036 mlir::ConversionPatternRewriter &rewriter)
const {
2037 const mlir::Type llvmTy =
2039 mlir::LLVM::AtomicOrdering ordering =
getLLVMMemOrder(op.getMemOrder());
2040 std::optional<size_t> opAlign = op.getAlignment();
2041 unsigned alignment =
2042 (unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmTy));
2049 std::optional<llvm::StringRef> llvmSyncScope =
2052 mlir::LLVM::LoadOp newLoad = mlir::LLVM::LoadOp::create(
2053 rewriter, op->getLoc(), llvmTy, adaptor.getAddr(), alignment,
2054 op.getIsVolatile(),
false,
2055 false,
false, ordering,
2056 llvmSyncScope.value_or(std::string()));
2059 mlir::Value result =
2061 rewriter.replaceOp(op, result);
2063 return mlir::LogicalResult::success();
2067cir::direct::CIRToLLVMVecMaskedLoadOpLowering::matchAndRewrite(
2068 cir::VecMaskedLoadOp op, OpAdaptor adaptor,
2069 mlir::ConversionPatternRewriter &rewriter)
const {
2070 const mlir::Type llvmResTy =
2073 std::optional<size_t> opAlign = op.getAlignment();
2074 unsigned alignment =
2075 (unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmResTy));
2077 mlir::IntegerAttr alignAttr = rewriter.getI32IntegerAttr(alignment);
2079 auto newLoad = mlir::LLVM::MaskedLoadOp::create(
2080 rewriter, op.getLoc(), llvmResTy, adaptor.getAddr(), adaptor.getMask(),
2081 adaptor.getPassThru(), alignAttr);
2083 rewriter.replaceOp(op, newLoad.getResult());
2084 return mlir::success();
2087mlir::LogicalResult CIRToLLVMStoreOpLowering::matchAndRewrite(
2088 cir::StoreOp op, OpAdaptor adaptor,
2089 mlir::ConversionPatternRewriter &rewriter)
const {
2090 mlir::LLVM::AtomicOrdering memorder =
getLLVMMemOrder(op.getMemOrder());
2091 const mlir::Type llvmTy =
2092 getTypeConverter()->convertType(op.getValue().getType());
2093 std::optional<size_t> opAlign = op.getAlignment();
2094 unsigned alignment =
2095 (unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmTy));
2101 op.getValue().getType(), adaptor.getValue());
2106 std::optional<llvm::StringRef> llvmSyncScope =
2109 mlir::LLVM::StoreOp storeOp = mlir::LLVM::StoreOp::create(
2110 rewriter, op->getLoc(), value, adaptor.getAddr(), alignment,
2112 false,
false, memorder,
2113 llvmSyncScope.value_or(std::string()));
2114 rewriter.replaceOp(op, storeOp);
2116 return mlir::LogicalResult::success();
2120 auto array = mlir::dyn_cast<mlir::ArrayAttr>(attr.getElts());
2121 return attr.hasTrailingZeros() ||
2122 (array && std::count_if(array.begin(), array.end(), [](
auto elt) {
2123 auto ar = dyn_cast<cir::ConstArrayAttr>(elt);
2124 return ar && hasTrailingZeros(ar);
2128mlir::LogicalResult CIRToLLVMConstantOpLowering::matchAndRewrite(
2129 cir::ConstantOp op, OpAdaptor adaptor,
2130 mlir::ConversionPatternRewriter &rewriter)
const {
2131 mlir::Attribute attr = op.getValue();
2133 if (mlir::isa<cir::PoisonAttr>(attr)) {
2134 rewriter.replaceOpWithNewOp<mlir::LLVM::PoisonOp>(
2135 op, getTypeConverter()->convertType(op.getType()));
2136 return mlir::success();
2139 if (mlir::isa<mlir::IntegerType>(op.getType())) {
2144 attr = op.getValue();
2145 }
else if (mlir::isa<cir::BoolType>(op.getType())) {
2146 int value = mlir::cast<cir::BoolAttr>(op.getValue()).getValue();
2147 attr = rewriter.getIntegerAttr(typeConverter->convertType(op.getType()),
2149 }
else if (mlir::isa<cir::IntType>(op.getType())) {
2151 if (
auto ga = mlir::dyn_cast<cir::GlobalViewAttr>(op.getValue())) {
2157 op.emitError() <<
"global view with integer type";
2158 return mlir::failure();
2161 attr = rewriter.getIntegerAttr(
2162 typeConverter->convertType(op.getType()),
2163 mlir::cast<cir::IntAttr>(op.getValue()).getValue());
2164 }
else if (mlir::isa<cir::FPTypeInterface>(op.getType())) {
2165 attr = rewriter.getFloatAttr(
2166 typeConverter->convertType(op.getType()),
2167 mlir::cast<cir::FPAttr>(op.getValue()).getValue());
2168 }
else if (mlir::isa<cir::PointerType>(op.getType())) {
2170 if (mlir::isa<cir::ConstPtrAttr>(op.getValue())) {
2171 if (mlir::cast<cir::ConstPtrAttr>(op.getValue()).isNullValue()) {
2172 rewriter.replaceOpWithNewOp<mlir::LLVM::ZeroOp>(
2173 op, typeConverter->convertType(op.getType()));
2174 return mlir::success();
2178 if (
auto gv = mlir::dyn_cast<cir::GlobalViewAttr>(op.getValue())) {
2180 rewriter.replaceOp(op, newOp);
2181 return mlir::success();
2183 attr = op.getValue();
2184 }
else if (
const auto arrTy = mlir::dyn_cast<cir::ArrayType>(op.getType())) {
2185 const auto constArr = mlir::dyn_cast<cir::ConstArrayAttr>(op.getValue());
2186 if (!constArr && !isa<cir::ZeroAttr, cir::UndefAttr>(op.getValue()))
2187 return op.emitError() <<
"array does not have a constant initializer";
2189 std::optional<mlir::Attribute> denseAttr;
2191 const mlir::Value newOp =
2193 rewriter.replaceOp(op, newOp);
2194 return mlir::success();
2195 }
else if (constArr &&
2197 attr = denseAttr.value();
2199 const mlir::Value initVal =
2201 rewriter.replaceOp(op, initVal);
2202 return mlir::success();
2204 }
else if (
const auto recordAttr =
2205 mlir::dyn_cast<cir::ConstRecordAttr>(op.getValue())) {
2207 rewriter.replaceOp(op, initVal);
2208 return mlir::success();
2209 }
else if (
const auto vecTy = mlir::dyn_cast<cir::VectorType>(op.getType())) {
2211 getTypeConverter()));
2212 return mlir::success();
2213 }
else if (
auto recTy = mlir::dyn_cast<cir::RecordType>(op.getType())) {
2214 if (mlir::isa<cir::ZeroAttr, cir::UndefAttr>(attr)) {
2215 mlir::Value initVal =
2217 rewriter.replaceOp(op, initVal);
2218 return mlir::success();
2220 return op.emitError() <<
"unsupported lowering for record constant type "
2222 }
else if (
auto complexTy = mlir::dyn_cast<cir::ComplexType>(op.getType())) {
2223 mlir::Type complexElemTy = complexTy.getElementType();
2224 mlir::Type complexElemLLVMTy = typeConverter->convertType(complexElemTy);
2226 if (
auto zeroInitAttr = mlir::dyn_cast<cir::ZeroAttr>(op.getValue())) {
2227 mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(complexElemLLVMTy);
2228 mlir::ArrayAttr array = rewriter.getArrayAttr({zeroAttr, zeroAttr});
2229 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
2230 op, getTypeConverter()->convertType(op.getType()), array);
2231 return mlir::success();
2234 auto complexAttr = mlir::cast<cir::ConstComplexAttr>(op.getValue());
2236 mlir::Attribute components[2];
2237 if (mlir::isa<cir::IntType>(complexElemTy)) {
2238 components[0] = rewriter.getIntegerAttr(
2240 mlir::cast<cir::IntAttr>(complexAttr.getReal()).getValue());
2241 components[1] = rewriter.getIntegerAttr(
2243 mlir::cast<cir::IntAttr>(complexAttr.getImag()).getValue());
2245 components[0] = rewriter.getFloatAttr(
2247 mlir::cast<cir::FPAttr>(complexAttr.getReal()).getValue());
2248 components[1] = rewriter.getFloatAttr(
2250 mlir::cast<cir::FPAttr>(complexAttr.getImag()).getValue());
2253 attr = rewriter.getArrayAttr(components);
2255 return op.emitError() <<
"unsupported constant type " << op.getType();
2258 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
2259 op, getTypeConverter()->convertType(op.getType()),
attr);
2261 return mlir::success();
2265 mlir::DataLayout layout(op.getParentOfType<mlir::ModuleOp>());
2267 if (isa<cir::VoidType>(type))
2268 type = cir::IntType::get(type.getContext(), 8,
false);
2269 return llvm::divideCeil(layout.getTypeSizeInBits(type), 8);
2272mlir::LogicalResult CIRToLLVMPrefetchOpLowering::matchAndRewrite(
2273 cir::PrefetchOp op, OpAdaptor adaptor,
2274 mlir::ConversionPatternRewriter &rewriter)
const {
2275 rewriter.replaceOpWithNewOp<mlir::LLVM::Prefetch>(
2276 op, adaptor.getAddr(), adaptor.getIsWrite(), adaptor.getLocality(),
2278 return mlir::success();
2281mlir::LogicalResult CIRToLLVMPtrDiffOpLowering::matchAndRewrite(
2282 cir::PtrDiffOp op, OpAdaptor adaptor,
2283 mlir::ConversionPatternRewriter &rewriter)
const {
2284 auto dstTy = mlir::cast<cir::IntType>(op.getType());
2285 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
2287 auto lhs = mlir::LLVM::PtrToIntOp::create(rewriter, op.getLoc(), llvmDstTy,
2289 auto rhs = mlir::LLVM::PtrToIntOp::create(rewriter, op.getLoc(), llvmDstTy,
2293 mlir::LLVM::SubOp::create(rewriter, op.getLoc(), llvmDstTy, lhs, rhs);
2295 cir::PointerType ptrTy = op.getLhs().getType();
2297 uint64_t typeSize =
getTypeSize(ptrTy.getPointee(), *op);
2300 mlir::Value resultVal = diff.getResult();
2301 if (typeSize != 1) {
2302 auto typeSizeVal = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
2303 llvmDstTy, typeSize);
2305 if (dstTy.isUnsigned()) {
2307 mlir::LLVM::UDivOp::create(rewriter, op.getLoc(), diff, typeSizeVal);
2308 uDiv.setIsExact(
true);
2309 resultVal = uDiv.getResult();
2312 mlir::LLVM::SDivOp::create(rewriter, op.getLoc(), diff, typeSizeVal);
2313 sDiv.setIsExact(
true);
2314 resultVal = sDiv.getResult();
2317 rewriter.replaceOp(op, resultVal);
2318 return mlir::success();
2321mlir::LogicalResult CIRToLLVMExpectOpLowering::matchAndRewrite(
2322 cir::ExpectOp op, OpAdaptor adaptor,
2323 mlir::ConversionPatternRewriter &rewriter)
const {
2327 std::optional<llvm::APFloat> prob = op.getProb();
2329 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpectWithProbabilityOp>(
2330 op, adaptor.getVal(), adaptor.getExpected(), prob.value());
2332 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpectOp>(op, adaptor.getVal(),
2333 adaptor.getExpected());
2334 return mlir::success();
2337mlir::LogicalResult CIRToLLVMFAbsOpLowering::matchAndRewrite(
2338 cir::FAbsOp op, OpAdaptor adaptor,
2339 mlir::ConversionPatternRewriter &rewriter)
const {
2340 mlir::Type resTy = typeConverter->convertType(op.getType());
2341 rewriter.replaceOpWithNewOp<mlir::LLVM::FAbsOp>(op, resTy,
2342 adaptor.getOperands()[0]);
2343 return mlir::success();
2346mlir::LogicalResult CIRToLLVMAbsOpLowering::matchAndRewrite(
2347 cir::AbsOp op, OpAdaptor adaptor,
2348 mlir::ConversionPatternRewriter &rewriter)
const {
2349 mlir::Type resTy = typeConverter->convertType(op.getType());
2350 auto absOp = mlir::LLVM::AbsOp::create(rewriter, op.getLoc(), resTy,
2351 adaptor.getOperands()[0],
2352 adaptor.getMinIsPoison());
2353 rewriter.replaceOp(op, absOp);
2354 return mlir::success();
2361void CIRToLLVMFuncOpLowering::lowerFuncAttributes(
2362 cir::FuncOp func,
bool filterArgAndResAttrs,
2363 SmallVectorImpl<mlir::NamedAttribute> &result)
const {
2365 for (mlir::NamedAttribute attr : func->getAttrs()) {
2367 if (
attr.getName() == mlir::SymbolTable::getSymbolAttrName() ||
2368 attr.getName() == func.getFunctionTypeAttrName() ||
2370 attr.getName() == func.getGlobalVisibilityAttrName() ||
2371 attr.getName() == func.getDsoLocalAttrName() ||
2372 attr.getName() == func.getInlineKindAttrName() ||
2373 attr.getName() == func.getSideEffectAttrName() ||
2374 attr.getName() == CIRDialect::getNoReturnAttrName() ||
2375 (filterArgAndResAttrs &&
2376 (
attr.getName() == func.getArgAttrsAttrName() ||
2377 attr.getName() == func.getResAttrsAttrName())))
2381 result.push_back(attr);
2385mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewriteAlias(
2386 cir::FuncOp op, llvm::StringRef aliasee, mlir::Type ty, OpAdaptor adaptor,
2387 mlir::ConversionPatternRewriter &rewriter)
const {
2388 SmallVector<mlir::NamedAttribute, 4> attributes;
2389 lowerFuncAttributes(op,
false, attributes);
2391 mlir::Location loc = op.getLoc();
2392 auto aliasOp = rewriter.replaceOpWithNewOp<mlir::LLVM::AliasOp>(
2393 op, ty,
convertLinkage(op.getLinkage()), op.getName(), op.getDsoLocal(),
2397 mlir::OpBuilder builder(op.getContext());
2398 mlir::Block *block = builder.createBlock(&aliasOp.getInitializerRegion());
2399 builder.setInsertionPointToStart(block);
2402 mlir::Type ptrTy = mlir::LLVM::LLVMPointerType::get(ty.getContext());
2403 auto addrOp = mlir::LLVM::AddressOfOp::create(builder, loc, ptrTy, aliasee);
2404 mlir::LLVM::ReturnOp::create(builder, loc, addrOp);
2406 return mlir::success();
2409mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewrite(
2410 cir::FuncOp op, OpAdaptor adaptor,
2411 mlir::ConversionPatternRewriter &rewriter)
const {
2413 cir::FuncType fnType = op.getFunctionType();
2414 bool isDsoLocal = op.getDsoLocal();
2415 mlir::TypeConverter::SignatureConversion signatureConversion(
2416 fnType.getNumInputs());
2418 for (
const auto &argType : llvm::enumerate(fnType.getInputs())) {
2419 mlir::Type convertedType = typeConverter->convertType(argType.value());
2421 return mlir::failure();
2422 signatureConversion.addInputs(argType.index(), convertedType);
2425 mlir::Type resultType =
2426 getTypeConverter()->convertType(fnType.getReturnType());
2429 mlir::Type llvmFnTy = mlir::LLVM::LLVMFunctionType::get(
2430 resultType ? resultType : mlir::LLVM::LLVMVoidType::get(getContext()),
2431 signatureConversion.getConvertedTypes(),
2435 if (std::optional<llvm::StringRef> aliasee = op.getAliasee())
2436 return matchAndRewriteAlias(op, *aliasee, llvmFnTy, adaptor, rewriter);
2440 mlir::Location loc = op.getLoc();
2441 if (mlir::FusedLoc fusedLoc = mlir::dyn_cast<mlir::FusedLoc>(loc))
2442 loc = fusedLoc.getLocations()[0];
2443 assert((mlir::isa<mlir::FileLineColLoc>(loc) ||
2444 mlir::isa<mlir::UnknownLoc>(loc)) &&
2445 "expected single location or unknown location here");
2449 mlir::LLVM::CConv cconv = mlir::LLVM::CConv::C;
2450 SmallVector<mlir::NamedAttribute, 4> attributes;
2451 lowerFuncAttributes(op,
false, attributes);
2453 mlir::LLVM::LLVMFuncOp fn = mlir::LLVM::LLVMFuncOp::create(
2454 rewriter, loc, op.getName(), llvmFnTy, linkage, isDsoLocal, cconv,
2455 mlir::SymbolRefAttr(), attributes);
2459 if (std::optional<cir::SideEffect> sideEffectKind = op.getSideEffect()) {
2460 switch (*sideEffectKind) {
2461 case cir::SideEffect::All:
2463 case cir::SideEffect::Pure:
2464 fn.setMemoryEffectsAttr(mlir::LLVM::MemoryEffectsAttr::get(
2466 mlir::LLVM::ModRefInfo::Ref,
2467 mlir::LLVM::ModRefInfo::Ref,
2468 mlir::LLVM::ModRefInfo::Ref,
2469 mlir::LLVM::ModRefInfo::Ref,
2470 mlir::LLVM::ModRefInfo::Ref,
2471 mlir::LLVM::ModRefInfo::Ref));
2472 fn.setNoUnwind(
true);
2473 fn.setWillReturn(
true);
2475 case cir::SideEffect::Const:
2476 fn.setMemoryEffectsAttr(mlir::LLVM::MemoryEffectsAttr::get(
2478 mlir::LLVM::ModRefInfo::NoModRef,
2479 mlir::LLVM::ModRefInfo::NoModRef,
2480 mlir::LLVM::ModRefInfo::NoModRef,
2481 mlir::LLVM::ModRefInfo::NoModRef,
2482 mlir::LLVM::ModRefInfo::NoModRef,
2483 mlir::LLVM::ModRefInfo::NoModRef));
2484 fn.setNoUnwind(
true);
2485 fn.setWillReturn(
true);
2490 if (op->hasAttr(CIRDialect::getNoReturnAttrName()))
2491 fn.setNoreturn(
true);
2493 if (std::optional<cir::InlineKind> inlineKind = op.getInlineKind()) {
2494 fn.setNoInline(*inlineKind == cir::InlineKind::NoInline);
2495 fn.setInlineHint(*inlineKind == cir::InlineKind::InlineHint);
2496 fn.setAlwaysInline(*inlineKind == cir::InlineKind::AlwaysInline);
2499 if (std::optional<llvm::StringRef> personality = op.getPersonality())
2500 fn.setPersonality(*personality);
2505 rewriter.inlineRegionBefore(op.getBody(), fn.getBody(), fn.end());
2506 if (failed(rewriter.convertRegionTypes(&fn.getBody(), *typeConverter,
2507 &signatureConversion)))
2508 return mlir::failure();
2510 rewriter.eraseOp(op);
2512 return mlir::LogicalResult::success();
2515mlir::LogicalResult CIRToLLVMGetGlobalOpLowering::matchAndRewrite(
2516 cir::GetGlobalOp op, OpAdaptor adaptor,
2517 mlir::ConversionPatternRewriter &rewriter)
const {
2520 if (op->getUses().empty()) {
2521 rewriter.eraseOp(op);
2522 return mlir::success();
2525 mlir::Type
type = getTypeConverter()->convertType(op.getType());
2526 mlir::Operation *newop = mlir::LLVM::AddressOfOp::create(
2527 rewriter, op.getLoc(), type, op.getName());
2531 newop = mlir::LLVM::ThreadlocalAddressOp::create(rewriter, op.getLoc(),
2532 type, newop->getResult(0));
2535 rewriter.replaceOp(op, newop);
2536 return mlir::success();
2541void CIRToLLVMGlobalOpLowering::setupRegionInitializedLLVMGlobalOp(
2542 cir::GlobalOp op, mlir::ConversionPatternRewriter &rewriter)
const {
2543 const mlir::Type llvmType =
2550 const bool isConst = op.getConstant();
2552 const unsigned addrSpace = 0;
2553 const bool isDsoLocal = op.getDsoLocal();
2554 const bool isThreadLocal = (
bool)op.getTlsModelAttr();
2555 const uint64_t alignment = op.getAlignment().value_or(0);
2556 const mlir::LLVM::Linkage linkage =
convertLinkage(op.getLinkage());
2557 const StringRef symbol = op.getSymName();
2558 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
2560 SmallVector<mlir::NamedAttribute> attributes;
2561 mlir::LLVM::GlobalOp newGlobalOp =
2562 rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
2563 op, llvmType, isConst, linkage, symbol,
nullptr, alignment, addrSpace,
2564 isDsoLocal, isThreadLocal, comdatAttr, attributes);
2565 newGlobalOp.getRegion().emplaceBlock();
2566 rewriter.setInsertionPointToEnd(newGlobalOp.getInitializerBlock());
2570CIRToLLVMGlobalOpLowering::matchAndRewriteRegionInitializedGlobal(
2571 cir::GlobalOp op, mlir::Attribute init,
2572 mlir::ConversionPatternRewriter &rewriter)
const {
2575 (isa<cir::ConstArrayAttr, cir::ConstRecordAttr, cir::ConstVectorAttr,
2576 cir::ConstPtrAttr, cir::ConstComplexAttr, cir::GlobalViewAttr,
2577 cir::TypeInfoAttr, cir::UndefAttr, cir::VTableAttr, cir::ZeroAttr>(
2583 const mlir::Location loc = op.getLoc();
2584 setupRegionInitializedLLVMGlobalOp(op, rewriter);
2586 mlir::Value value = valueConverter.visit(init);
2587 mlir::LLVM::ReturnOp::create(rewriter, loc, value);
2588 return mlir::success();
2591mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite(
2592 cir::GlobalOp op, OpAdaptor adaptor,
2593 mlir::ConversionPatternRewriter &rewriter)
const {
2596 if (!op.getCtorRegion().empty() || !op.getDtorRegion().empty())
2597 return op.emitError() <<
"GlobalOp ctor and dtor regions should be removed "
2598 "in LoweringPrepare";
2600 std::optional<mlir::Attribute> init = op.getInitialValue();
2603 const mlir::Type cirSymType = op.getSymType();
2606 const mlir::Type llvmType =
2610 const bool isConst = op.getConstant();
2612 const unsigned addrSpace = 0;
2613 const bool isDsoLocal = op.getDsoLocal();
2614 const bool isThreadLocal = (
bool)op.getTlsModelAttr();
2615 const uint64_t alignment = op.getAlignment().value_or(0);
2616 const mlir::LLVM::Linkage linkage =
convertLinkage(op.getLinkage());
2617 const StringRef symbol = op.getSymName();
2618 SmallVector<mlir::NamedAttribute> attributes;
2620 if (init.has_value()) {
2621 if (mlir::isa<cir::FPAttr, cir::IntAttr, cir::BoolAttr>(init.value())) {
2623 init = initRewriter.visit(init.value());
2628 if (!init.value()) {
2629 op.emitError() <<
"unsupported initializer '" << init.value() <<
"'";
2630 return mlir::failure();
2632 }
else if (mlir::isa<cir::ConstArrayAttr, cir::ConstVectorAttr,
2633 cir::ConstRecordAttr, cir::ConstPtrAttr,
2634 cir::ConstComplexAttr, cir::GlobalViewAttr,
2635 cir::TypeInfoAttr, cir::UndefAttr, cir::VTableAttr,
2636 cir::ZeroAttr>(init.value())) {
2640 return matchAndRewriteRegionInitializedGlobal(op, init.value(), rewriter);
2644 op.emitError() <<
"unsupported initializer '" << init.value() <<
"'";
2645 return mlir::failure();
2649 mlir::LLVM::Visibility visibility =
2651 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
2652 auto newOp = rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
2653 op, llvmType, isConst, linkage, symbol, init.value_or(mlir::Attribute()),
2654 alignment, addrSpace, isDsoLocal, isThreadLocal, comdatAttr, attributes);
2655 newOp.setVisibility_(visibility);
2657 return mlir::success();
2661CIRToLLVMGlobalOpLowering::getComdatAttr(cir::GlobalOp &op,
2662 mlir::OpBuilder &builder)
const {
2663 if (!op.getComdat())
2664 return mlir::SymbolRefAttr{};
2666 mlir::ModuleOp module = op->getParentOfType<mlir::ModuleOp>();
2667 mlir::OpBuilder::InsertionGuard guard(builder);
2668 StringRef comdatName(
"__llvm_comdat_globals");
2670 builder.setInsertionPointToStart(module.getBody());
2672 mlir::LLVM::ComdatOp::create(builder, module.getLoc(), comdatName);
2675 if (
auto comdatSelector = comdatOp.lookupSymbol<mlir::LLVM::ComdatSelectorOp>(
2677 return mlir::SymbolRefAttr::get(
2678 builder.getContext(), comdatName,
2679 mlir::FlatSymbolRefAttr::get(comdatSelector.getSymNameAttr()));
2682 builder.setInsertionPointToStart(&comdatOp.getBody().back());
2683 auto selectorOp = mlir::LLVM::ComdatSelectorOp::create(
2684 builder, comdatOp.getLoc(), op.getSymName(),
2685 mlir::LLVM::comdat::Comdat::Any);
2686 return mlir::SymbolRefAttr::get(
2687 builder.getContext(), comdatName,
2688 mlir::FlatSymbolRefAttr::get(selectorOp.getSymNameAttr()));
2691mlir::LogicalResult CIRToLLVMSwitchFlatOpLowering::matchAndRewrite(
2692 cir::SwitchFlatOp op, OpAdaptor adaptor,
2693 mlir::ConversionPatternRewriter &rewriter)
const {
2695 llvm::SmallVector<mlir::APInt, 8> caseValues;
2696 for (mlir::Attribute val : op.getCaseValues()) {
2697 auto intAttr = cast<cir::IntAttr>(val);
2698 caseValues.push_back(intAttr.getValue());
2701 llvm::SmallVector<mlir::Block *, 8> caseDestinations;
2702 llvm::SmallVector<mlir::ValueRange, 8> caseOperands;
2704 for (mlir::Block *x : op.getCaseDestinations())
2705 caseDestinations.push_back(x);
2707 for (mlir::OperandRange x : op.getCaseOperands())
2708 caseOperands.push_back(x);
2711 rewriter.setInsertionPoint(op);
2712 rewriter.replaceOpWithNewOp<mlir::LLVM::SwitchOp>(
2713 op, adaptor.getCondition(), op.getDefaultDestination(),
2714 op.getDefaultOperands(), caseValues, caseDestinations, caseOperands);
2715 return mlir::success();
2718mlir::LogicalResult CIRToLLVMUnaryOpLowering::matchAndRewrite(
2719 cir::UnaryOp op, OpAdaptor adaptor,
2720 mlir::ConversionPatternRewriter &rewriter)
const {
2721 assert(op.getType() == op.getInput().getType() &&
2722 "Unary operation's operand type and result type are different");
2723 mlir::Type
type = op.getType();
2724 mlir::Type elementType = elementTypeIfVector(type);
2725 bool isVector = mlir::isa<cir::VectorType>(type);
2726 mlir::Type llvmType = getTypeConverter()->convertType(type);
2727 mlir::Location loc = op.getLoc();
2730 if (mlir::isa<cir::IntType>(elementType)) {
2731 mlir::LLVM::IntegerOverflowFlags maybeNSW =
2732 op.getNoSignedWrap() ? mlir::LLVM::IntegerOverflowFlags::nsw
2733 : mlir::LLVM::IntegerOverflowFlags::none;
2734 switch (op.getKind()) {
2735 case cir::UnaryOpKind::Inc: {
2736 assert(!
isVector &&
"++ not allowed on vector types");
2737 auto one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
2738 rewriter.replaceOpWithNewOp<mlir::LLVM::AddOp>(
2739 op, llvmType, adaptor.getInput(), one, maybeNSW);
2740 return mlir::success();
2742 case cir::UnaryOpKind::Dec: {
2743 assert(!
isVector &&
"-- not allowed on vector types");
2744 auto one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
2745 rewriter.replaceOpWithNewOp<mlir::LLVM::SubOp>(op, adaptor.getInput(),
2747 return mlir::success();
2749 case cir::UnaryOpKind::Plus:
2750 rewriter.replaceOp(op, adaptor.getInput());
2751 return mlir::success();
2752 case cir::UnaryOpKind::Minus: {
2755 zero = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmType);
2757 zero = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 0);
2758 rewriter.replaceOpWithNewOp<mlir::LLVM::SubOp>(
2759 op, zero, adaptor.getInput(), maybeNSW);
2760 return mlir::success();
2762 case cir::UnaryOpKind::Not: {
2764 mlir::Value minusOne;
2767 mlir::dyn_cast<cir::VectorType>(type).getSize();
2768 std::vector<int32_t> values(numElements, -1);
2769 mlir::DenseIntElementsAttr denseVec = rewriter.getI32VectorAttr(values);
2771 mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, denseVec);
2773 minusOne = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, -1);
2775 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getInput(),
2777 return mlir::success();
2780 llvm_unreachable(
"Unexpected unary op for int");
2784 if (mlir::isa<cir::FPTypeInterface>(elementType)) {
2785 switch (op.getKind()) {
2786 case cir::UnaryOpKind::Inc: {
2787 assert(!
isVector &&
"++ not allowed on vector types");
2788 mlir::LLVM::ConstantOp one = mlir::LLVM::ConstantOp::create(
2789 rewriter, loc, llvmType, rewriter.getFloatAttr(llvmType, 1.0));
2790 rewriter.replaceOpWithNewOp<mlir::LLVM::FAddOp>(op, llvmType, one,
2791 adaptor.getInput());
2792 return mlir::success();
2794 case cir::UnaryOpKind::Dec: {
2795 assert(!
isVector &&
"-- not allowed on vector types");
2796 mlir::LLVM::ConstantOp minusOne = mlir::LLVM::ConstantOp::create(
2797 rewriter, loc, llvmType, rewriter.getFloatAttr(llvmType, -1.0));
2798 rewriter.replaceOpWithNewOp<mlir::LLVM::FAddOp>(op, llvmType, minusOne,
2799 adaptor.getInput());
2800 return mlir::success();
2802 case cir::UnaryOpKind::Plus:
2803 rewriter.replaceOp(op, adaptor.getInput());
2804 return mlir::success();
2805 case cir::UnaryOpKind::Minus:
2806 rewriter.replaceOpWithNewOp<mlir::LLVM::FNegOp>(op, llvmType,
2807 adaptor.getInput());
2808 return mlir::success();
2809 case cir::UnaryOpKind::Not:
2810 return op.emitError() <<
"Unary not is invalid for floating-point types";
2812 llvm_unreachable(
"Unexpected unary op for float");
2817 if (mlir::isa<cir::BoolType>(elementType)) {
2818 switch (op.getKind()) {
2819 case cir::UnaryOpKind::Inc:
2820 case cir::UnaryOpKind::Dec:
2821 case cir::UnaryOpKind::Plus:
2822 case cir::UnaryOpKind::Minus:
2825 return op.emitError() <<
"Unsupported unary operation on boolean type";
2826 case cir::UnaryOpKind::Not: {
2827 assert(!
isVector &&
"NYI: op! on vector mask");
2828 auto one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
2829 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getInput(),
2831 return mlir::success();
2834 llvm_unreachable(
"Unexpected unary op for bool");
2839 if (mlir::isa<cir::PointerType>(elementType)) {
2840 switch (op.getKind()) {
2841 case cir::UnaryOpKind::Plus:
2842 rewriter.replaceOp(op, adaptor.getInput());
2843 return mlir::success();
2845 op.emitError() <<
"Unknown pointer unary operation during CIR lowering";
2846 return mlir::failure();
2850 return op.emitError() <<
"Unary operation has unsupported type: "
2856 return mlir::isa<cir::IntType>(type)
2857 ? mlir::cast<cir::IntType>(type).isUnsigned()
2858 : mlir::cast<mlir::IntegerType>(type).isUnsigned();
2865template <
typename BinOp>
2867 if (op.getNoUnsignedWrap())
2868 return mlir::LLVM::IntegerOverflowFlags::nuw;
2869 if (op.getNoSignedWrap())
2870 return mlir::LLVM::IntegerOverflowFlags::nsw;
2871 return mlir::LLVM::IntegerOverflowFlags::none;
2876template <
typename UIntSatOp,
typename SIntSatOp,
typename IntOp,
typename FPOp,
2878static mlir::LogicalResult
2880 mlir::ConversionPatternRewriter &rewriter) {
2881 const mlir::Type eltType = elementTypeIfVector(op.getRhs().getType());
2882 if (cir::isIntOrBoolType(eltType)) {
2883 if (op.getSaturated()) {
2885 rewriter.replaceOpWithNewOp<UIntSatOp>(op, lhs, rhs);
2887 rewriter.replaceOpWithNewOp<SIntSatOp>(op, lhs, rhs);
2888 return mlir::success();
2890 rewriter.replaceOpWithNewOp<IntOp>(op, lhs, rhs,
intOverflowFlag(op));
2892 rewriter.replaceOpWithNewOp<FPOp>(op, lhs, rhs);
2894 return mlir::success();
2897mlir::LogicalResult CIRToLLVMAddOpLowering::matchAndRewrite(
2898 cir::AddOp op, OpAdaptor adaptor,
2899 mlir::ConversionPatternRewriter &rewriter)
const {
2901 mlir::LLVM::AddOp, mlir::LLVM::FAddOp>(
2902 op, adaptor.getLhs(), adaptor.getRhs(), rewriter);
2905mlir::LogicalResult CIRToLLVMSubOpLowering::matchAndRewrite(
2906 cir::SubOp op, OpAdaptor adaptor,
2907 mlir::ConversionPatternRewriter &rewriter)
const {
2909 mlir::LLVM::SubOp, mlir::LLVM::FSubOp>(
2910 op, adaptor.getLhs(), adaptor.getRhs(), rewriter);
2913mlir::LogicalResult CIRToLLVMMulOpLowering::matchAndRewrite(
2914 cir::MulOp op, OpAdaptor adaptor,
2915 mlir::ConversionPatternRewriter &rewriter)
const {
2916 const mlir::Value lhs = adaptor.getLhs();
2917 const mlir::Value rhs = adaptor.getRhs();
2918 if (cir::isIntOrBoolType(elementTypeIfVector(op.getRhs().getType()))) {
2919 rewriter.replaceOpWithNewOp<mlir::LLVM::MulOp>(op, lhs, rhs,
2922 rewriter.replaceOpWithNewOp<mlir::LLVM::FMulOp>(op, lhs, rhs);
2924 return mlir::success();
2929template <
typename UIntOp,
typename SIntOp,
typename FPOp,
typename CIROp>
2930static mlir::LogicalResult
2932 mlir::ConversionPatternRewriter &rewriter) {
2933 const mlir::Type eltType = elementTypeIfVector(op.getRhs().getType());
2934 if (cir::isIntOrBoolType(eltType)) {
2936 rewriter.replaceOpWithNewOp<UIntOp>(op, lhs, rhs);
2938 rewriter.replaceOpWithNewOp<SIntOp>(op, lhs, rhs);
2940 rewriter.replaceOpWithNewOp<FPOp>(op, lhs, rhs);
2942 return mlir::success();
2945mlir::LogicalResult CIRToLLVMDivOpLowering::matchAndRewrite(
2946 cir::DivOp op, OpAdaptor adaptor,
2947 mlir::ConversionPatternRewriter &rewriter)
const {
2949 mlir::LLVM::FDivOp>(op, adaptor.getLhs(),
2950 adaptor.getRhs(), rewriter);
2953mlir::LogicalResult CIRToLLVMRemOpLowering::matchAndRewrite(
2954 cir::RemOp op, OpAdaptor adaptor,
2955 mlir::ConversionPatternRewriter &rewriter)
const {
2957 mlir::LLVM::FRemOp>(op, adaptor.getLhs(),
2958 adaptor.getRhs(), rewriter);
2961mlir::LogicalResult CIRToLLVMAndOpLowering::matchAndRewrite(
2962 cir::AndOp op, OpAdaptor adaptor,
2963 mlir::ConversionPatternRewriter &rewriter)
const {
2964 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(op, adaptor.getLhs(),
2966 return mlir::success();
2969mlir::LogicalResult CIRToLLVMOrOpLowering::matchAndRewrite(
2970 cir::OrOp op, OpAdaptor adaptor,
2971 mlir::ConversionPatternRewriter &rewriter)
const {
2972 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(op, adaptor.getLhs(),
2974 return mlir::success();
2977mlir::LogicalResult CIRToLLVMXorOpLowering::matchAndRewrite(
2978 cir::XorOp op, OpAdaptor adaptor,
2979 mlir::ConversionPatternRewriter &rewriter)
const {
2980 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getLhs(),
2982 return mlir::success();
2985mlir::LogicalResult CIRToLLVMMaxOpLowering::matchAndRewrite(
2986 cir::MaxOp op, OpAdaptor adaptor,
2987 mlir::ConversionPatternRewriter &rewriter)
const {
2988 const mlir::Value lhs = adaptor.getLhs();
2989 const mlir::Value rhs = adaptor.getRhs();
2991 rewriter.replaceOpWithNewOp<mlir::LLVM::UMaxOp>(op, lhs, rhs);
2993 rewriter.replaceOpWithNewOp<mlir::LLVM::SMaxOp>(op, lhs, rhs);
2994 return mlir::success();
2998static mlir::LLVM::ICmpPredicate
3000 using CIR = cir::CmpOpKind;
3001 using LLVMICmp = mlir::LLVM::ICmpPredicate;
3004 return LLVMICmp::eq;
3006 return LLVMICmp::ne;
3008 return (isSigned ? LLVMICmp::slt : LLVMICmp::ult);
3010 return (isSigned ? LLVMICmp::sle : LLVMICmp::ule);
3012 return (isSigned ? LLVMICmp::sgt : LLVMICmp::ugt);
3014 return (isSigned ? LLVMICmp::sge : LLVMICmp::uge);
3016 llvm_unreachable(
"Unknown CmpOpKind");
3021static mlir::LLVM::FCmpPredicate
3023 using CIR = cir::CmpOpKind;
3024 using LLVMFCmp = mlir::LLVM::FCmpPredicate;
3027 return LLVMFCmp::oeq;
3029 return LLVMFCmp::une;
3031 return LLVMFCmp::olt;
3033 return LLVMFCmp::ole;
3035 return LLVMFCmp::ogt;
3037 return LLVMFCmp::oge;
3039 llvm_unreachable(
"Unknown CmpOpKind");
3042mlir::LogicalResult CIRToLLVMCmpOpLowering::matchAndRewrite(
3043 cir::CmpOp cmpOp, OpAdaptor adaptor,
3044 mlir::ConversionPatternRewriter &rewriter)
const {
3045 mlir::Type type = cmpOp.getLhs().getType();
3047 if (mlir::isa<cir::IntType, mlir::IntegerType>(type)) {
3048 bool isSigned = mlir::isa<cir::IntType>(type)
3049 ? mlir::cast<cir::IntType>(type).isSigned()
3050 : mlir::cast<mlir::IntegerType>(type).isSigned();
3051 mlir::LLVM::ICmpPredicate
kind =
3053 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
3054 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
3055 return mlir::success();
3058 if (
auto ptrTy = mlir::dyn_cast<cir::PointerType>(type)) {
3059 mlir::LLVM::ICmpPredicate
kind =
3062 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
3063 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
3064 return mlir::success();
3067 if (
auto vptrTy = mlir::dyn_cast<cir::VPtrType>(type)) {
3071 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
3072 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
3073 return mlir::success();
3076 if (mlir::isa<cir::FPTypeInterface>(type)) {
3077 mlir::LLVM::FCmpPredicate
kind =
3079 rewriter.replaceOpWithNewOp<mlir::LLVM::FCmpOp>(
3080 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
3081 return mlir::success();
3084 if (mlir::isa<cir::ComplexType>(type)) {
3085 mlir::Value lhs = adaptor.getLhs();
3086 mlir::Value rhs = adaptor.getRhs();
3087 mlir::Location loc = cmpOp.getLoc();
3089 auto complexType = mlir::cast<cir::ComplexType>(cmpOp.getLhs().getType());
3090 mlir::Type complexElemTy =
3091 getTypeConverter()->convertType(
complexType.getElementType());
3093 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
3094 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{0}));
3095 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
3096 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{1}));
3097 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
3098 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{0}));
3099 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
3100 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{1}));
3102 if (cmpOp.getKind() == cir::CmpOpKind::eq) {
3103 if (complexElemTy.isInteger()) {
3104 auto realCmp = mlir::LLVM::ICmpOp::create(
3105 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, lhsReal, rhsReal);
3106 auto imagCmp = mlir::LLVM::ICmpOp::create(
3107 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, lhsImag, rhsImag);
3108 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, imagCmp);
3109 return mlir::success();
3112 auto realCmp = mlir::LLVM::FCmpOp::create(
3113 rewriter, loc, mlir::LLVM::FCmpPredicate::oeq, lhsReal, rhsReal);
3114 auto imagCmp = mlir::LLVM::FCmpOp::create(
3115 rewriter, loc, mlir::LLVM::FCmpPredicate::oeq, lhsImag, rhsImag);
3116 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, imagCmp);
3117 return mlir::success();
3120 if (cmpOp.getKind() == cir::CmpOpKind::ne) {
3121 if (complexElemTy.isInteger()) {
3122 auto realCmp = mlir::LLVM::ICmpOp::create(
3123 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, lhsReal, rhsReal);
3124 auto imagCmp = mlir::LLVM::ICmpOp::create(
3125 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, lhsImag, rhsImag);
3126 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp);
3127 return mlir::success();
3130 auto realCmp = mlir::LLVM::FCmpOp::create(
3131 rewriter, loc, mlir::LLVM::FCmpPredicate::une, lhsReal, rhsReal);
3132 auto imagCmp = mlir::LLVM::FCmpOp::create(
3133 rewriter, loc, mlir::LLVM::FCmpPredicate::une, lhsImag, rhsImag);
3134 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp);
3135 return mlir::success();
3139 return cmpOp.emitError() <<
"unsupported type for CmpOp: " <<
type;
3142mlir::LogicalResult CIRToLLVMBinOpOverflowOpLowering::matchAndRewrite(
3143 cir::BinOpOverflowOp op, OpAdaptor adaptor,
3144 mlir::ConversionPatternRewriter &rewriter)
const {
3145 mlir::Location loc = op.getLoc();
3146 cir::BinOpOverflowKind arithKind = op.getKind();
3147 cir::IntType operandTy = op.getLhs().getType();
3148 cir::IntType resultTy = op.getResult().getType();
3150 EncompassedTypeInfo encompassedTyInfo =
3151 computeEncompassedTypeWidth(operandTy, resultTy);
3152 mlir::IntegerType encompassedLLVMTy =
3153 rewriter.getIntegerType(encompassedTyInfo.width);
3155 mlir::Value lhs = adaptor.getLhs();
3156 mlir::Value rhs = adaptor.getRhs();
3157 if (operandTy.getWidth() < encompassedTyInfo.width) {
3158 if (operandTy.isSigned()) {
3159 lhs = mlir::LLVM::SExtOp::create(rewriter, loc, encompassedLLVMTy, lhs);
3160 rhs = mlir::LLVM::SExtOp::create(rewriter, loc, encompassedLLVMTy, rhs);
3162 lhs = mlir::LLVM::ZExtOp::create(rewriter, loc, encompassedLLVMTy, lhs);
3163 rhs = mlir::LLVM::ZExtOp::create(rewriter, loc, encompassedLLVMTy, rhs);
3167 std::string intrinName = getLLVMIntrinName(arithKind, encompassedTyInfo.sign,
3168 encompassedTyInfo.width);
3169 auto intrinNameAttr = mlir::StringAttr::get(op.getContext(), intrinName);
3171 mlir::IntegerType overflowLLVMTy = rewriter.getI1Type();
3172 auto intrinRetTy = mlir::LLVM::LLVMStructType::getLiteral(
3173 rewriter.getContext(), {encompassedLLVMTy, overflowLLVMTy});
3175 auto callLLVMIntrinOp = mlir::LLVM::CallIntrinsicOp::create(
3176 rewriter, loc, intrinRetTy, intrinNameAttr, mlir::ValueRange{lhs, rhs});
3177 mlir::Value intrinRet = callLLVMIntrinOp.getResult(0);
3179 mlir::Value result = mlir::LLVM::ExtractValueOp::create(
3180 rewriter, loc, intrinRet, ArrayRef<int64_t>{0})
3182 mlir::Value overflow = mlir::LLVM::ExtractValueOp::create(
3183 rewriter, loc, intrinRet, ArrayRef<int64_t>{1})
3186 if (resultTy.getWidth() < encompassedTyInfo.width) {
3187 mlir::Type resultLLVMTy = getTypeConverter()->convertType(resultTy);
3189 mlir::LLVM::TruncOp::create(rewriter, loc, resultLLVMTy, result);
3193 mlir::Value truncResultExt;
3194 if (resultTy.isSigned())
3195 truncResultExt = mlir::LLVM::SExtOp::create(
3196 rewriter, loc, encompassedLLVMTy, truncResult);
3198 truncResultExt = mlir::LLVM::ZExtOp::create(
3199 rewriter, loc, encompassedLLVMTy, truncResult);
3200 auto truncOverflow = mlir::LLVM::ICmpOp::create(
3201 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, truncResultExt, result);
3203 result = truncResult;
3204 overflow = mlir::LLVM::OrOp::create(rewriter, loc, overflow, truncOverflow);
3207 mlir::Type boolLLVMTy =
3208 getTypeConverter()->convertType(op.getOverflow().getType());
3209 if (boolLLVMTy != rewriter.getI1Type())
3210 overflow = mlir::LLVM::ZExtOp::create(rewriter, loc, boolLLVMTy, overflow);
3212 rewriter.replaceOp(op, mlir::ValueRange{result, overflow});
3214 return mlir::success();
3217std::string CIRToLLVMBinOpOverflowOpLowering::getLLVMIntrinName(
3218 cir::BinOpOverflowKind opKind,
bool isSigned,
unsigned width) {
3221 std::string
name =
"llvm.";
3224 name.push_back(
's');
3226 name.push_back(
'u');
3229 case cir::BinOpOverflowKind::Add:
3230 name.append(
"add.");
3232 case cir::BinOpOverflowKind::Sub:
3233 name.append(
"sub.");
3235 case cir::BinOpOverflowKind::Mul:
3236 name.append(
"mul.");
3240 name.append(
"with.overflow.i");
3241 name.append(std::to_string(width));
3246CIRToLLVMBinOpOverflowOpLowering::EncompassedTypeInfo
3247CIRToLLVMBinOpOverflowOpLowering::computeEncompassedTypeWidth(
3248 cir::IntType operandTy, cir::IntType resultTy) {
3249 bool sign = operandTy.getIsSigned() || resultTy.getIsSigned();
3251 std::max(operandTy.getWidth() + (
sign && operandTy.isUnsigned()),
3252 resultTy.getWidth() + (
sign && resultTy.isUnsigned()));
3253 return {
sign, width};
3256mlir::LogicalResult CIRToLLVMShiftOpLowering::matchAndRewrite(
3257 cir::ShiftOp op, OpAdaptor adaptor,
3258 mlir::ConversionPatternRewriter &rewriter)
const {
3259 assert((op.getValue().getType() == op.getType()) &&
3260 "inconsistent operands' types NYI");
3262 const mlir::Type llvmTy = getTypeConverter()->convertType(op.getType());
3263 mlir::Value amt = adaptor.getAmount();
3264 mlir::Value val = adaptor.getValue();
3266 auto cirAmtTy = mlir::dyn_cast<cir::IntType>(op.getAmount().getType());
3269 auto cirValTy = mlir::cast<cir::IntType>(op.getValue().getType());
3277 amt =
getLLVMIntCast(rewriter, amt, llvmTy,
true, cirAmtTy.getWidth(),
3278 cirValTy.getWidth());
3280 auto cirValVTy = mlir::cast<cir::VectorType>(op.getValue().getType());
3282 mlir::cast<cir::IntType>(cirValVTy.getElementType()).isUnsigned();
3286 if (op.getIsShiftleft()) {
3287 rewriter.replaceOpWithNewOp<mlir::LLVM::ShlOp>(op, llvmTy, val, amt);
3288 return mlir::success();
3292 rewriter.replaceOpWithNewOp<mlir::LLVM::LShrOp>(op, llvmTy, val, amt);
3294 rewriter.replaceOpWithNewOp<mlir::LLVM::AShrOp>(op, llvmTy, val, amt);
3295 return mlir::success();
3298mlir::LogicalResult CIRToLLVMSelectOpLowering::matchAndRewrite(
3299 cir::SelectOp op, OpAdaptor adaptor,
3300 mlir::ConversionPatternRewriter &rewriter)
const {
3301 auto getConstantBool = [](mlir::Value value) -> cir::BoolAttr {
3302 auto definingOp = value.getDefiningOp<cir::ConstantOp>();
3306 auto constValue = definingOp.getValueAttr<cir::BoolAttr>();
3316 if (mlir::isa<cir::BoolType>(op.getTrueValue().getType())) {
3317 cir::BoolAttr trueValue = getConstantBool(op.getTrueValue());
3318 cir::BoolAttr falseValue = getConstantBool(op.getFalseValue());
3319 if (falseValue && !falseValue.getValue()) {
3321 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(op, adaptor.getCondition(),
3322 adaptor.getTrueValue());
3323 return mlir::success();
3325 if (trueValue && trueValue.getValue()) {
3327 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(op, adaptor.getCondition(),
3328 adaptor.getFalseValue());
3329 return mlir::success();
3333 mlir::Value llvmCondition = adaptor.getCondition();
3334 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(
3335 op, llvmCondition, adaptor.getTrueValue(), adaptor.getFalseValue());
3337 return mlir::success();
3341 mlir::DataLayout &dataLayout) {
3342 converter.addConversion([&](cir::PointerType type) -> mlir::Type {
3343 mlir::ptr::MemorySpaceAttrInterface addrSpaceAttr = type.getAddrSpace();
3344 unsigned numericAS = 0;
3346 if (
auto langAsAttr =
3347 mlir::dyn_cast_if_present<cir::LangAddressSpaceAttr>(addrSpaceAttr))
3348 llvm_unreachable(
"lowering LangAddressSpaceAttr NYI");
3349 else if (
auto targetAsAttr =
3350 mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
3352 numericAS = targetAsAttr.getValue();
3353 return mlir::LLVM::LLVMPointerType::get(type.getContext(), numericAS);
3355 converter.addConversion([&](cir::VPtrType type) -> mlir::Type {
3357 return mlir::LLVM::LLVMPointerType::get(type.getContext());
3359 converter.addConversion([&](cir::ArrayType type) -> mlir::Type {
3362 return mlir::LLVM::LLVMArrayType::get(ty, type.getSize());
3364 converter.addConversion([&](cir::VectorType type) -> mlir::Type {
3365 const mlir::Type ty = converter.convertType(type.getElementType());
3366 return mlir::VectorType::get(type.getSize(), ty, {type.getIsScalable()});
3368 converter.addConversion([&](cir::BoolType type) -> mlir::Type {
3369 return mlir::IntegerType::get(type.getContext(), 1,
3370 mlir::IntegerType::Signless);
3372 converter.addConversion([&](cir::IntType type) -> mlir::Type {
3374 return mlir::IntegerType::get(type.getContext(), type.getWidth());
3376 converter.addConversion([&](cir::SingleType type) -> mlir::Type {
3377 return mlir::Float32Type::get(type.getContext());
3379 converter.addConversion([&](cir::DoubleType type) -> mlir::Type {
3380 return mlir::Float64Type::get(type.getContext());
3382 converter.addConversion([&](cir::FP80Type type) -> mlir::Type {
3383 return mlir::Float80Type::get(type.getContext());
3385 converter.addConversion([&](cir::FP128Type type) -> mlir::Type {
3386 return mlir::Float128Type::get(type.getContext());
3388 converter.addConversion([&](cir::LongDoubleType type) -> mlir::Type {
3389 return converter.convertType(type.getUnderlying());
3391 converter.addConversion([&](cir::FP16Type type) -> mlir::Type {
3392 return mlir::Float16Type::get(type.getContext());
3394 converter.addConversion([&](cir::BF16Type type) -> mlir::Type {
3395 return mlir::BFloat16Type::get(type.getContext());
3397 converter.addConversion([&](cir::ComplexType type) -> mlir::Type {
3400 mlir::Type elementTy = converter.convertType(type.getElementType());
3401 mlir::Type structFields[2] = {elementTy, elementTy};
3402 return mlir::LLVM::LLVMStructType::getLiteral(type.getContext(),
3405 converter.addConversion([&](cir::FuncType type) -> std::optional<mlir::Type> {
3406 auto result = converter.convertType(type.getReturnType());
3408 arguments.reserve(type.getNumInputs());
3409 if (converter.convertTypes(type.getInputs(), arguments).failed())
3410 return std::nullopt;
3411 auto varArg = type.isVarArg();
3412 return mlir::LLVM::LLVMFunctionType::get(result, arguments, varArg);
3414 converter.addConversion([&](cir::RecordType type) -> mlir::Type {
3417 switch (type.getKind()) {
3418 case cir::RecordType::Class:
3419 case cir::RecordType::Struct:
3420 for (mlir::Type ty : type.getMembers())
3424 case cir::RecordType::Union:
3425 if (type.getMembers().empty())
3427 if (
auto largestMember = type.getLargestMember(dataLayout))
3428 llvmMembers.push_back(
3430 if (type.getPadded()) {
3431 auto last = *type.getMembers().rbegin();
3432 llvmMembers.push_back(
3439 mlir::LLVM::LLVMStructType llvmStruct;
3440 if (type.getName()) {
3441 llvmStruct = mlir::LLVM::LLVMStructType::getIdentified(
3442 type.getContext(), type.getPrefixedName());
3443 if (llvmStruct.setBody(llvmMembers, type.getPacked()).failed())
3444 llvm_unreachable(
"Failed to set body of record");
3446 llvmStruct = mlir::LLVM::LLVMStructType::getLiteral(
3447 type.getContext(), llvmMembers, type.getPacked());
3452 converter.addConversion([&](cir::VoidType type) -> mlir::Type {
3453 return mlir::LLVM::LLVMVoidType::get(type.getContext());
3458 mlir::ModuleOp module, StringRef globalXtorName, StringRef llvmXtorName,
3459 llvm::function_ref<std::pair<StringRef, int>(mlir::Attribute)> createXtor) {
3461 for (
const mlir::NamedAttribute namedAttr : module->getAttrs()) {
3462 if (namedAttr.getName() == globalXtorName) {
3463 for (
auto attr : mlir::cast<mlir::ArrayAttr>(namedAttr.getValue()))
3464 globalXtors.emplace_back(createXtor(attr));
3469 if (globalXtors.empty())
3472 mlir::OpBuilder builder(module.getContext());
3473 builder.setInsertionPointToEnd(&module.getBodyRegion().back());
3477 auto ctorPFTy = mlir::LLVM::LLVMPointerType::get(builder.getContext());
3479 ctorStructFields.push_back(builder.getI32Type());
3480 ctorStructFields.push_back(ctorPFTy);
3481 ctorStructFields.push_back(ctorPFTy);
3483 auto ctorStructTy = mlir::LLVM::LLVMStructType::getLiteral(
3484 builder.getContext(), ctorStructFields);
3485 auto ctorStructArrayTy =
3486 mlir::LLVM::LLVMArrayType::get(ctorStructTy, globalXtors.size());
3488 mlir::Location loc =
module.getLoc();
3489 auto newGlobalOp = mlir::LLVM::GlobalOp::create(
3490 builder, loc, ctorStructArrayTy,
false,
3491 mlir::LLVM::Linkage::Appending, llvmXtorName, mlir::Attribute());
3493 builder.createBlock(&newGlobalOp.getRegion());
3494 builder.setInsertionPointToEnd(newGlobalOp.getInitializerBlock());
3496 mlir::Value result =
3497 mlir::LLVM::UndefOp::create(builder, loc, ctorStructArrayTy);
3499 for (
auto [index, fn] : llvm::enumerate(globalXtors)) {
3500 mlir::Value structInit =
3501 mlir::LLVM::UndefOp::create(builder, loc, ctorStructTy);
3502 mlir::Value initPriority = mlir::LLVM::ConstantOp::create(
3503 builder, loc, ctorStructFields[0], fn.second);
3504 mlir::Value initFuncAddr = mlir::LLVM::AddressOfOp::create(
3505 builder, loc, ctorStructFields[1], fn.first);
3506 mlir::Value initAssociate =
3507 mlir::LLVM::ZeroOp::create(builder, loc, ctorStructFields[2]);
3510 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
3511 initPriority, zero);
3512 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
3515 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
3517 result = mlir::LLVM::InsertValueOp::create(builder, loc, result, structInit,
3521 mlir::LLVM::ReturnOp::create(builder, loc, result);
3559 parent->walk([&](mlir::Block *blk) {
3560 if (blk->hasNoPredecessors() && !blk->isEntryBlock())
3561 unreachableBlocks.push_back(blk);
3564 std::set<mlir::Block *> visited;
3565 for (mlir::Block *root : unreachableBlocks) {
3568 std::deque<mlir::Block *> workList;
3569 workList.push_back(root);
3571 while (!workList.empty()) {
3572 mlir::Block *blk = workList.back();
3573 workList.pop_back();
3574 if (visited.count(blk))
3576 visited.emplace(blk);
3578 for (mlir::Operation &op : *blk)
3581 for (mlir::Block *succ : blk->getSuccessors())
3582 workList.push_back(succ);
3587mlir::LogicalResult CIRToLLVMObjSizeOpLowering::matchAndRewrite(
3588 cir::ObjSizeOp op, OpAdaptor adaptor,
3589 mlir::ConversionPatternRewriter &rewriter)
const {
3590 mlir::Type llvmResTy = getTypeConverter()->convertType(op.getType());
3591 mlir::Location loc = op->getLoc();
3593 mlir::IntegerType i1Ty = rewriter.getI1Type();
3595 auto i1Val = [&rewriter, &loc, &i1Ty](
bool val) {
3596 return mlir::LLVM::ConstantOp::create(rewriter, loc, i1Ty, val);
3603 i1Val(op.getNullunknown()),
3604 i1Val(op.getDynamic()),
3607 return mlir::LogicalResult::success();
3613 mlir::ModuleOp module = getOperation();
3614 mlir::OpBuilder opBuilder(module.getContext());
3615 for (
auto &[blockAddOp, blockInfo] :
3617 mlir::LLVM::BlockTagOp resolvedLabel =
3619 assert(resolvedLabel &&
"expected BlockTagOp to already be emitted");
3620 mlir::FlatSymbolRefAttr fnSym = blockInfo.getFunc();
3621 auto blkAddTag = mlir::LLVM::BlockAddressAttr::get(
3622 opBuilder.getContext(), fnSym, resolvedLabel.getTagAttr());
3623 blockAddOp.setBlockAddrAttr(blkAddTag);
3630 if (mlir::Attribute tripleAttr =
3631 module->getAttr(cir::CIRDialect::getTripleAttrName()))
3632 module->setAttr(mlir::LLVM::LLVMDialect::getTargetTripleAttrName(),
3635 if (mlir::Attribute asmAttr =
3636 module->getAttr(cir::CIRDialect::getModuleLevelAsmAttrName()))
3637 module->setAttr(mlir::LLVM::LLVMDialect::getModuleLevelAsmAttrName(),
3642 llvm::TimeTraceScope scope(
"Convert CIR to LLVM Pass");
3644 mlir::ModuleOp module = getOperation();
3645 mlir::DataLayout dl(module);
3646 mlir::LLVMTypeConverter converter(&getContext());
3654 mlir::RewritePatternSet patterns(&getContext());
3655 patterns.add<CIRToLLVMBlockAddressOpLowering, CIRToLLVMLabelOpLowering>(
3656 converter, patterns.getContext(), dl, blockInfoAddr);
3659#define GET_LLVM_LOWERING_PATTERNS_LIST
3660#include "clang/CIR/Dialect/IR/CIRLowering.inc"
3661#undef GET_LLVM_LOWERING_PATTERNS_LIST
3662 >(converter, patterns.getContext(), dl);
3666 mlir::ConversionTarget target(getContext());
3667 target.addLegalOp<mlir::ModuleOp>();
3668 target.addLegalDialect<mlir::LLVM::LLVMDialect>();
3669 target.addIllegalDialect<mlir::BuiltinDialect, cir::CIRDialect,
3670 mlir::func::FuncDialect>();
3673 ops.push_back(module);
3676 if (failed(applyPartialConversion(ops, target, std::move(patterns))))
3677 signalPassFailure();
3681 "llvm.global_ctors", [](mlir::Attribute attr) {
3682 auto ctorAttr = mlir::cast<cir::GlobalCtorAttr>(attr);
3683 return std::make_pair(ctorAttr.getName(),
3684 ctorAttr.getPriority());
3688 "llvm.global_dtors", [](mlir::Attribute attr) {
3689 auto dtorAttr = mlir::cast<cir::GlobalDtorAttr>(attr);
3690 return std::make_pair(dtorAttr.getName(),
3691 dtorAttr.getPriority());
3696mlir::LogicalResult CIRToLLVMBrOpLowering::matchAndRewrite(
3697 cir::BrOp op, OpAdaptor adaptor,
3698 mlir::ConversionPatternRewriter &rewriter)
const {
3699 rewriter.replaceOpWithNewOp<mlir::LLVM::BrOp>(op, adaptor.getOperands(),
3701 return mlir::LogicalResult::success();
3704mlir::LogicalResult CIRToLLVMGetMemberOpLowering::matchAndRewrite(
3705 cir::GetMemberOp op, OpAdaptor adaptor,
3706 mlir::ConversionPatternRewriter &rewriter)
const {
3707 mlir::Type llResTy = getTypeConverter()->convertType(op.getType());
3708 const auto recordTy =
3709 mlir::cast<cir::RecordType>(op.getAddrTy().getPointee());
3710 assert(recordTy &&
"expected record type");
3712 switch (recordTy.getKind()) {
3713 case cir::RecordType::Class:
3714 case cir::RecordType::Struct: {
3718 const mlir::Type elementTy = getTypeConverter()->convertType(recordTy);
3719 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, llResTy, elementTy,
3720 adaptor.getAddr(), offset);
3721 return mlir::success();
3723 case cir::RecordType::Union:
3726 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(op, llResTy,
3728 return mlir::success();
3732mlir::LogicalResult CIRToLLVMExtractMemberOpLowering::matchAndRewrite(
3733 cir::ExtractMemberOp op, OpAdaptor adaptor,
3734 mlir::ConversionPatternRewriter &rewriter)
const {
3735 std::int64_t indices[1] = {
static_cast<std::int64_t
>(op.getIndex())};
3737 mlir::Type recordTy = op.getRecord().getType();
3738 auto cirRecordTy = mlir::cast<cir::RecordType>(recordTy);
3739 switch (cirRecordTy.getKind()) {
3740 case cir::RecordType::Struct:
3741 case cir::RecordType::Class:
3742 rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractValueOp>(
3743 op, adaptor.getRecord(), indices);
3744 return mlir::success();
3746 case cir::RecordType::Union:
3747 op.emitError(
"cir.extract_member cannot extract member from a union");
3748 return mlir::failure();
3750 llvm_unreachable(
"Unexpected record kind");
3753mlir::LogicalResult CIRToLLVMInsertMemberOpLowering::matchAndRewrite(
3754 cir::InsertMemberOp op, OpAdaptor adaptor,
3755 mlir::ConversionPatternRewriter &rewriter)
const {
3756 std::int64_t indecies[1] = {
static_cast<std::int64_t
>(op.getIndex())};
3757 mlir::Type recordTy = op.getRecord().getType();
3759 if (
auto cirRecordTy = mlir::dyn_cast<cir::RecordType>(recordTy)) {
3760 if (cirRecordTy.getKind() == cir::RecordType::Union) {
3761 op.emitError(
"cir.update_member cannot update member of a union");
3762 return mlir::failure();
3766 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
3767 op, adaptor.getRecord(), adaptor.getValue(), indecies);
3768 return mlir::success();
3771mlir::LogicalResult CIRToLLVMUnreachableOpLowering::matchAndRewrite(
3772 cir::UnreachableOp op, OpAdaptor adaptor,
3773 mlir::ConversionPatternRewriter &rewriter)
const {
3774 rewriter.replaceOpWithNewOp<mlir::LLVM::UnreachableOp>(op);
3775 return mlir::success();
3779 mlir::Operation *srcOp, llvm::StringRef fnName,
3781 auto modOp = srcOp->getParentOfType<mlir::ModuleOp>();
3782 auto enclosingFnOp = srcOp->getParentOfType<mlir::LLVM::LLVMFuncOp>();
3783 mlir::Operation *sourceSymbol =
3784 mlir::SymbolTable::lookupSymbolIn(modOp, fnName);
3785 if (!sourceSymbol) {
3786 mlir::OpBuilder::InsertionGuard guard(rewriter);
3787 rewriter.setInsertionPoint(enclosingFnOp);
3788 mlir::LLVM::LLVMFuncOp::create(rewriter, srcOp->getLoc(), fnName, fnTy);
3792mlir::LogicalResult CIRToLLVMThrowOpLowering::matchAndRewrite(
3793 cir::ThrowOp op, OpAdaptor adaptor,
3794 mlir::ConversionPatternRewriter &rewriter)
const {
3795 mlir::Location loc = op.getLoc();
3796 auto voidTy = mlir::LLVM::LLVMVoidType::get(getContext());
3798 if (op.rethrows()) {
3799 auto funcTy = mlir::LLVM::LLVMFunctionType::get(voidTy, {});
3802 const llvm::StringRef functionName =
"__cxa_rethrow";
3805 auto cxaRethrow = mlir::LLVM::CallOp::create(
3806 rewriter, loc, mlir::TypeRange{}, functionName);
3808 rewriter.replaceOp(op, cxaRethrow);
3809 return mlir::success();
3812 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3813 auto fnTy = mlir::LLVM::LLVMFunctionType::get(
3814 voidTy, {llvmPtrTy, llvmPtrTy, llvmPtrTy});
3817 const llvm::StringRef fnName =
"__cxa_throw";
3820 mlir::Value typeInfo = mlir::LLVM::AddressOfOp::create(
3821 rewriter, loc, mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
3822 adaptor.getTypeInfoAttr());
3826 dtor = mlir::LLVM::AddressOfOp::create(rewriter, loc, llvmPtrTy,
3827 adaptor.getDtorAttr());
3829 dtor = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmPtrTy);
3832 auto cxaThrowCall = mlir::LLVM::CallOp::create(
3833 rewriter, loc, mlir::TypeRange{}, fnName,
3834 mlir::ValueRange{adaptor.getExceptionPtr(), typeInfo, dtor});
3836 rewriter.replaceOp(op, cxaThrowCall);
3837 return mlir::success();
3840mlir::LogicalResult CIRToLLVMAllocExceptionOpLowering::matchAndRewrite(
3841 cir::AllocExceptionOp op, OpAdaptor adaptor,
3842 mlir::ConversionPatternRewriter &rewriter)
const {
3844 StringRef fnName =
"__cxa_allocate_exception";
3845 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3846 auto int64Ty = mlir::IntegerType::get(rewriter.getContext(), 64);
3847 auto fnTy = mlir::LLVM::LLVMFunctionType::get(llvmPtrTy, {int64Ty});
3850 auto exceptionSize = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
3851 adaptor.getSizeAttr());
3853 auto allocaExceptionCall = mlir::LLVM::CallOp::create(
3854 rewriter, op.getLoc(), mlir::TypeRange{llvmPtrTy}, fnName,
3855 mlir::ValueRange{exceptionSize});
3857 rewriter.replaceOp(op, allocaExceptionCall);
3858 return mlir::success();
3861static mlir::LLVM::LLVMStructType
3864 mlir::MLIRContext *ctx = rewriter.getContext();
3865 auto llvmPtr = mlir::LLVM::LLVMPointerType::get(ctx);
3867 return mlir::LLVM::LLVMStructType::getLiteral(ctx, structFields);
3870mlir::LogicalResult CIRToLLVMEhInflightOpLowering::matchAndRewrite(
3871 cir::EhInflightOp op, OpAdaptor adaptor,
3872 mlir::ConversionPatternRewriter &rewriter)
const {
3873 auto llvmFn = op->getParentOfType<mlir::LLVM::LLVMFuncOp>();
3874 assert(llvmFn &&
"expected LLVM function parent");
3875 mlir::Block *entryBlock = &llvmFn.getRegion().front();
3876 assert(entryBlock->isEntryBlock());
3878 mlir::ArrayAttr catchListAttr = op.getCatchTypeListAttr();
3879 mlir::SmallVector<mlir::Value> catchSymAddrs;
3881 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3882 mlir::Location loc = op.getLoc();
3887 if (catchListAttr) {
3890 for (mlir::Attribute catchAttr : catchListAttr) {
3891 auto symAttr = cast<mlir::FlatSymbolRefAttr>(catchAttr);
3894 mlir::OpBuilder::InsertionGuard guard(rewriter);
3895 rewriter.setInsertionPointToStart(entryBlock);
3896 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
3897 rewriter, loc, llvmPtrTy, symAttr.getValue());
3898 catchSymAddrs.push_back(addrOp);
3900 }
else if (!op.getCleanup()) {
3904 mlir::OpBuilder::InsertionGuard guard(rewriter);
3905 rewriter.setInsertionPointToStart(entryBlock);
3906 mlir::Value nullOp = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmPtrTy);
3907 catchSymAddrs.push_back(nullOp);
3912 mlir::LLVM::LLVMStructType llvmLandingPadStructTy =
3914 auto landingPadOp = mlir::LLVM::LandingpadOp::create(
3915 rewriter, loc, llvmLandingPadStructTy, catchSymAddrs);
3917 if (op.getCleanup())
3918 landingPadOp.setCleanup(
true);
3921 mlir::LLVM::ExtractValueOp::create(rewriter, loc, landingPadOp, 0);
3922 mlir::Value selector =
3923 mlir::LLVM::ExtractValueOp::create(rewriter, loc, landingPadOp, 1);
3924 rewriter.replaceOp(op, mlir::ValueRange{slot, selector});
3926 return mlir::success();
3929mlir::LogicalResult CIRToLLVMResumeFlatOpLowering::matchAndRewrite(
3930 cir::ResumeFlatOp op, OpAdaptor adaptor,
3931 mlir::ConversionPatternRewriter &rewriter)
const {
3936 mlir::Value poison = mlir::LLVM::PoisonOp::create(rewriter, op.getLoc(),
3937 llvmLandingPadStructTy);
3939 SmallVector<int64_t> slotIdx = {0};
3940 mlir::Value slot = mlir::LLVM::InsertValueOp::create(
3941 rewriter, op.getLoc(), poison, adaptor.getExceptionPtr(), slotIdx);
3943 SmallVector<int64_t> selectorIdx = {1};
3944 mlir::Value selector = mlir::LLVM::InsertValueOp::create(
3945 rewriter, op.getLoc(), slot, adaptor.getTypeId(), selectorIdx);
3947 rewriter.replaceOpWithNewOp<mlir::LLVM::ResumeOp>(op, selector);
3948 return mlir::success();
3951mlir::LogicalResult CIRToLLVMEhTypeIdOpLowering::matchAndRewrite(
3952 cir::EhTypeIdOp op, OpAdaptor adaptor,
3953 mlir::ConversionPatternRewriter &rewriter)
const {
3954 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
3955 rewriter, op.getLoc(),
3956 mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
3957 op.getTypeSymAttr());
3958 rewriter.replaceOpWithNewOp<mlir::LLVM::EhTypeidForOp>(
3959 op, rewriter.getI32Type(), addrOp);
3960 return mlir::success();
3963mlir::LogicalResult CIRToLLVMEhSetjmpOpLowering::matchAndRewrite(
3964 cir::EhSetjmpOp op, OpAdaptor adaptor,
3965 mlir::ConversionPatternRewriter &rewriter)
const {
3966 mlir::Type returnType = typeConverter->convertType(op.getType());
3967 mlir::LLVM::CallIntrinsicOp newOp =
3969 returnType, adaptor.getEnv());
3970 rewriter.replaceOp(op, newOp);
3971 return mlir::success();
3974mlir::LogicalResult CIRToLLVMEhLongjmpOpLowering::matchAndRewrite(
3975 cir::EhLongjmpOp op, OpAdaptor adaptor,
3976 mlir::ConversionPatternRewriter &rewriter)
const {
3978 {}, adaptor.getOperands());
3979 return mlir::success();
3982mlir::LogicalResult CIRToLLVMTrapOpLowering::matchAndRewrite(
3983 cir::TrapOp op, OpAdaptor adaptor,
3984 mlir::ConversionPatternRewriter &rewriter)
const {
3985 mlir::Location loc = op->getLoc();
3986 rewriter.eraseOp(op);
3988 mlir::LLVM::Trap::create(rewriter, loc);
3993 mlir::LLVM::UnreachableOp::create(rewriter, loc);
3995 return mlir::success();
4000 mlir::ConversionPatternRewriter &rewriter,
4001 const mlir::TypeConverter *converter,
4002 mlir::FlatSymbolRefAttr nameAttr, mlir::Type &eltType) {
4003 auto module = op->getParentOfType<mlir::ModuleOp>();
4004 mlir::Operation *symbol = mlir::SymbolTable::lookupSymbolIn(module, nameAttr);
4005 if (
auto llvmSymbol = mlir::dyn_cast<mlir::LLVM::GlobalOp>(symbol)) {
4006 eltType = llvmSymbol.getType();
4007 }
else if (
auto cirSymbol = mlir::dyn_cast<cir::GlobalOp>(symbol)) {
4008 eltType = converter->convertType(cirSymbol.getSymType());
4010 op->emitError() <<
"unexpected symbol type for " << symbol;
4014 return mlir::LLVM::AddressOfOp::create(
4015 rewriter, op->getLoc(),
4016 mlir::LLVM::LLVMPointerType::get(op->getContext()), nameAttr.getValue());
4019mlir::LogicalResult CIRToLLVMVTableAddrPointOpLowering::matchAndRewrite(
4020 cir::VTableAddrPointOp op, OpAdaptor adaptor,
4021 mlir::ConversionPatternRewriter &rewriter)
const {
4022 const mlir::TypeConverter *converter = getTypeConverter();
4023 mlir::Type targetType = converter->convertType(op.getType());
4027 op.getNameAttr(), eltType);
4029 return op.emitError() <<
"Unable to get value for vtable symbol";
4032 0, op.getAddressPointAttr().getIndex(),
4033 op.getAddressPointAttr().getOffset()};
4035 assert(eltType &&
"Shouldn't ever be missing an eltType here");
4036 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
4037 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
4038 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, targetType, eltType,
4039 symAddr, offsets, inboundsNuw);
4040 return mlir::success();
4043mlir::LogicalResult CIRToLLVMVTableGetVPtrOpLowering::matchAndRewrite(
4044 cir::VTableGetVPtrOp op, OpAdaptor adaptor,
4045 mlir::ConversionPatternRewriter &rewriter)
const {
4049 mlir::Value srcVal = adaptor.getSrc();
4050 rewriter.replaceOp(op, srcVal);
4051 return mlir::success();
4054mlir::LogicalResult CIRToLLVMVTableGetVirtualFnAddrOpLowering::matchAndRewrite(
4055 cir::VTableGetVirtualFnAddrOp op, OpAdaptor adaptor,
4056 mlir::ConversionPatternRewriter &rewriter)
const {
4057 mlir::Type targetType = getTypeConverter()->convertType(op.getType());
4058 auto eltType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4059 llvm::SmallVector<mlir::LLVM::GEPArg> offsets =
4060 llvm::SmallVector<mlir::LLVM::GEPArg>{op.getIndex()};
4061 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
4062 op, targetType, eltType, adaptor.getVptr(), offsets,
4063 mlir::LLVM::GEPNoWrapFlags::inbounds);
4064 return mlir::success();
4067mlir::LogicalResult CIRToLLVMVTTAddrPointOpLowering::matchAndRewrite(
4068 cir::VTTAddrPointOp op, OpAdaptor adaptor,
4069 mlir::ConversionPatternRewriter &rewriter)
const {
4070 const mlir::Type resultType = getTypeConverter()->convertType(op.getType());
4071 llvm::SmallVector<mlir::LLVM::GEPArg> offsets;
4073 mlir::Value llvmAddr = adaptor.getSymAddr();
4075 if (op.getSymAddr()) {
4076 if (op.getOffset() == 0) {
4077 rewriter.replaceOp(op, {llvmAddr});
4078 return mlir::success();
4081 offsets.push_back(adaptor.getOffset());
4082 eltType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4085 op.getNameAttr(), eltType);
4086 assert(eltType &&
"Shouldn't ever be missing an eltType here");
4087 offsets.push_back(0);
4088 offsets.push_back(adaptor.getOffset());
4090 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
4091 op, resultType, eltType, llvmAddr, offsets,
4092 mlir::LLVM::GEPNoWrapFlags::inbounds);
4093 return mlir::success();
4096mlir::LogicalResult CIRToLLVMStackSaveOpLowering::matchAndRewrite(
4097 cir::StackSaveOp op, OpAdaptor adaptor,
4098 mlir::ConversionPatternRewriter &rewriter)
const {
4099 const mlir::Type ptrTy = getTypeConverter()->convertType(op.getType());
4100 rewriter.replaceOpWithNewOp<mlir::LLVM::StackSaveOp>(op, ptrTy);
4101 return mlir::success();
4104mlir::LogicalResult CIRToLLVMStackRestoreOpLowering::matchAndRewrite(
4105 cir::StackRestoreOp op, OpAdaptor adaptor,
4106 mlir::ConversionPatternRewriter &rewriter)
const {
4107 rewriter.replaceOpWithNewOp<mlir::LLVM::StackRestoreOp>(op, adaptor.getPtr());
4108 return mlir::success();
4111mlir::LogicalResult CIRToLLVMVecCreateOpLowering::matchAndRewrite(
4112 cir::VecCreateOp op, OpAdaptor adaptor,
4113 mlir::ConversionPatternRewriter &rewriter)
const {
4116 const auto vecTy = mlir::cast<cir::VectorType>(op.getType());
4117 const mlir::Type llvmTy = typeConverter->convertType(vecTy);
4118 const mlir::Location loc = op.getLoc();
4119 mlir::Value result = mlir::LLVM::PoisonOp::create(rewriter, loc, llvmTy);
4120 assert(vecTy.getSize() == op.getElements().size() &&
4121 "cir.vec.create op count doesn't match vector type elements count");
4123 for (uint64_t i = 0; i < vecTy.getSize(); ++i) {
4124 const mlir::Value indexValue =
4125 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
4126 result = mlir::LLVM::InsertElementOp::create(
4127 rewriter, loc, result, adaptor.getElements()[i], indexValue);
4130 rewriter.replaceOp(op, result);
4131 return mlir::success();
4134mlir::LogicalResult CIRToLLVMVecExtractOpLowering::matchAndRewrite(
4135 cir::VecExtractOp op, OpAdaptor adaptor,
4136 mlir::ConversionPatternRewriter &rewriter)
const {
4137 rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractElementOp>(
4138 op, adaptor.getVec(), adaptor.getIndex());
4139 return mlir::success();
4142mlir::LogicalResult CIRToLLVMVecInsertOpLowering::matchAndRewrite(
4143 cir::VecInsertOp op, OpAdaptor adaptor,
4144 mlir::ConversionPatternRewriter &rewriter)
const {
4145 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertElementOp>(
4146 op, adaptor.getVec(), adaptor.getValue(), adaptor.getIndex());
4147 return mlir::success();
4150mlir::LogicalResult CIRToLLVMVecCmpOpLowering::matchAndRewrite(
4151 cir::VecCmpOp op, OpAdaptor adaptor,
4152 mlir::ConversionPatternRewriter &rewriter)
const {
4153 mlir::Type elementType = elementTypeIfVector(op.getLhs().getType());
4154 mlir::Value bitResult;
4155 if (
auto intType = mlir::dyn_cast<cir::IntType>(elementType)) {
4156 bitResult = mlir::LLVM::ICmpOp::create(
4157 rewriter, op.getLoc(),
4159 adaptor.getLhs(), adaptor.getRhs());
4160 }
else if (mlir::isa<cir::FPTypeInterface>(elementType)) {
4161 bitResult = mlir::LLVM::FCmpOp::create(
4163 adaptor.getLhs(), adaptor.getRhs());
4165 return op.emitError() <<
"unsupported type for VecCmpOp: " << elementType;
4171 if (cast<cir::IntType>(cast<cir::VectorType>(op.getType()).getElementType())
4173 rewriter.replaceOpWithNewOp<mlir::LLVM::SExtOp>(
4174 op, typeConverter->convertType(op.getType()), bitResult);
4176 rewriter.replaceOp(op, bitResult);
4177 return mlir::success();
4180mlir::LogicalResult CIRToLLVMVecSplatOpLowering::matchAndRewrite(
4181 cir::VecSplatOp op, OpAdaptor adaptor,
4182 mlir::ConversionPatternRewriter &rewriter)
const {
4188 cir::VectorType vecTy = op.getType();
4189 mlir::Type llvmTy = typeConverter->convertType(vecTy);
4190 mlir::Location loc = op.getLoc();
4191 mlir::Value poison = mlir::LLVM::PoisonOp::create(rewriter, loc, llvmTy);
4193 mlir::Value elementValue = adaptor.getValue();
4194 if (elementValue.getDefiningOp<mlir::LLVM::PoisonOp>()) {
4197 rewriter.replaceOp(op, poison);
4198 return mlir::success();
4201 if (
auto constValue = elementValue.getDefiningOp<mlir::LLVM::ConstantOp>()) {
4202 if (
auto intAttr = dyn_cast<mlir::IntegerAttr>(constValue.getValue())) {
4203 mlir::DenseIntElementsAttr denseVec = mlir::DenseIntElementsAttr::get(
4204 mlir::cast<mlir::ShapedType>(llvmTy), intAttr.getValue());
4205 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
4206 op, denseVec.getType(), denseVec);
4207 return mlir::success();
4210 if (
auto fpAttr = dyn_cast<mlir::FloatAttr>(constValue.getValue())) {
4211 mlir::DenseFPElementsAttr denseVec = mlir::DenseFPElementsAttr::get(
4212 mlir::cast<mlir::ShapedType>(llvmTy), fpAttr.getValue());
4213 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
4214 op, denseVec.getType(), denseVec);
4215 return mlir::success();
4219 mlir::Value indexValue =
4220 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), 0);
4221 mlir::Value oneElement = mlir::LLVM::InsertElementOp::create(
4222 rewriter, loc, poison, elementValue, indexValue);
4223 SmallVector<int32_t> zeroValues(vecTy.getSize(), 0);
4224 rewriter.replaceOpWithNewOp<mlir::LLVM::ShuffleVectorOp>(op, oneElement,
4225 poison, zeroValues);
4226 return mlir::success();
4229mlir::LogicalResult CIRToLLVMVecShuffleOpLowering::matchAndRewrite(
4230 cir::VecShuffleOp op, OpAdaptor adaptor,
4231 mlir::ConversionPatternRewriter &rewriter)
const {
4235 SmallVector<int, 8> indices;
4237 op.getIndices().begin(), op.getIndices().end(),
4238 std::back_inserter(indices), [](mlir::Attribute intAttr) {
4239 return mlir::cast<cir::IntAttr>(intAttr).getValue().getSExtValue();
4241 rewriter.replaceOpWithNewOp<mlir::LLVM::ShuffleVectorOp>(
4242 op, adaptor.getVec1(), adaptor.getVec2(), indices);
4243 return mlir::success();
4246mlir::LogicalResult CIRToLLVMVecShuffleDynamicOpLowering::matchAndRewrite(
4247 cir::VecShuffleDynamicOp op, OpAdaptor adaptor,
4248 mlir::ConversionPatternRewriter &rewriter)
const {
4260 mlir::Location loc = op.getLoc();
4261 mlir::Value input = adaptor.getVec();
4262 mlir::Type llvmIndexVecType =
4263 getTypeConverter()->convertType(op.getIndices().getType());
4264 mlir::Type llvmIndexType = getTypeConverter()->convertType(
4265 elementTypeIfVector(op.getIndices().getType()));
4267 mlir::cast<cir::VectorType>(op.getVec().getType()).getSize();
4269 uint64_t maskBits = llvm::NextPowerOf2(numElements - 1) - 1;
4270 mlir::Value maskValue = mlir::LLVM::ConstantOp::create(
4271 rewriter, loc, llvmIndexType,
4272 rewriter.getIntegerAttr(llvmIndexType, maskBits));
4273 mlir::Value maskVector =
4274 mlir::LLVM::UndefOp::create(rewriter, loc, llvmIndexVecType);
4276 for (uint64_t i = 0; i < numElements; ++i) {
4277 mlir::Value idxValue =
4278 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
4279 maskVector = mlir::LLVM::InsertElementOp::create(rewriter, loc, maskVector,
4280 maskValue, idxValue);
4283 mlir::Value maskedIndices = mlir::LLVM::AndOp::create(
4284 rewriter, loc, llvmIndexVecType, adaptor.getIndices(), maskVector);
4285 mlir::Value result = mlir::LLVM::UndefOp::create(
4286 rewriter, loc, getTypeConverter()->convertType(op.getVec().getType()));
4287 for (uint64_t i = 0; i < numElements; ++i) {
4288 mlir::Value iValue =
4289 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
4290 mlir::Value indexValue = mlir::LLVM::ExtractElementOp::create(
4291 rewriter, loc, maskedIndices, iValue);
4292 mlir::Value valueAtIndex =
4293 mlir::LLVM::ExtractElementOp::create(rewriter, loc, input, indexValue);
4294 result = mlir::LLVM::InsertElementOp::create(rewriter, loc, result,
4295 valueAtIndex, iValue);
4297 rewriter.replaceOp(op, result);
4298 return mlir::success();
4301mlir::LogicalResult CIRToLLVMVecTernaryOpLowering::matchAndRewrite(
4302 cir::VecTernaryOp op, OpAdaptor adaptor,
4303 mlir::ConversionPatternRewriter &rewriter)
const {
4305 mlir::Value bitVec = mlir::LLVM::ICmpOp::create(
4306 rewriter, op.getLoc(), mlir::LLVM::ICmpPredicate::ne, adaptor.getCond(),
4307 mlir::LLVM::ZeroOp::create(
4308 rewriter, op.getCond().getLoc(),
4309 typeConverter->convertType(op.getCond().getType())));
4310 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(
4311 op, bitVec, adaptor.getLhs(), adaptor.getRhs());
4312 return mlir::success();
4315mlir::LogicalResult CIRToLLVMComplexAddOpLowering::matchAndRewrite(
4316 cir::ComplexAddOp op, OpAdaptor adaptor,
4317 mlir::ConversionPatternRewriter &rewriter)
const {
4318 mlir::Value lhs = adaptor.getLhs();
4319 mlir::Value rhs = adaptor.getRhs();
4320 mlir::Location loc = op.getLoc();
4322 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
4323 mlir::Type complexElemTy =
4324 getTypeConverter()->convertType(
complexType.getElementType());
4325 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
4326 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{0}));
4327 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
4328 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{1}));
4329 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
4330 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{0}));
4331 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
4332 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{1}));
4334 mlir::Value newReal;
4335 mlir::Value newImag;
4336 if (complexElemTy.isInteger()) {
4337 newReal = mlir::LLVM::AddOp::create(rewriter, loc, complexElemTy, lhsReal,
4339 newImag = mlir::LLVM::AddOp::create(rewriter, loc, complexElemTy, lhsImag,
4344 newReal = mlir::LLVM::FAddOp::create(rewriter, loc, complexElemTy, lhsReal,
4346 newImag = mlir::LLVM::FAddOp::create(rewriter, loc, complexElemTy, lhsImag,
4350 mlir::Type complexLLVMTy =
4351 getTypeConverter()->convertType(op.getResult().getType());
4352 auto initialComplex =
4353 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), complexLLVMTy);
4355 auto realComplex = mlir::LLVM::InsertValueOp::create(
4356 rewriter, op->getLoc(), initialComplex, newReal, ArrayRef(int64_t{0}));
4358 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
4359 op, realComplex, newImag, ArrayRef(int64_t{1}));
4361 return mlir::success();
4364mlir::LogicalResult CIRToLLVMComplexCreateOpLowering::matchAndRewrite(
4365 cir::ComplexCreateOp op, OpAdaptor adaptor,
4366 mlir::ConversionPatternRewriter &rewriter)
const {
4367 mlir::Type complexLLVMTy =
4368 getTypeConverter()->convertType(op.getResult().getType());
4369 auto initialComplex =
4370 mlir::LLVM::UndefOp::create(rewriter, op->getLoc(), complexLLVMTy);
4372 auto realComplex = mlir::LLVM::InsertValueOp::create(
4373 rewriter, op->getLoc(), initialComplex, adaptor.getReal(),
4374 ArrayRef(int64_t{0}));
4376 auto complex = mlir::LLVM::InsertValueOp::create(
4377 rewriter, op->getLoc(), realComplex, adaptor.getImag(),
4378 ArrayRef(int64_t{1}));
4380 rewriter.replaceOp(op, complex);
4381 return mlir::success();
4384mlir::LogicalResult CIRToLLVMComplexRealOpLowering::matchAndRewrite(
4385 cir::ComplexRealOp op, OpAdaptor adaptor,
4386 mlir::ConversionPatternRewriter &rewriter)
const {
4387 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
4388 mlir::Value operand = adaptor.getOperand();
4389 if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) {
4390 operand = mlir::LLVM::ExtractValueOp::create(
4391 rewriter, op.getLoc(), resultLLVMTy, operand,
4392 llvm::ArrayRef<std::int64_t>{0});
4394 rewriter.replaceOp(op, operand);
4395 return mlir::success();
4398mlir::LogicalResult CIRToLLVMComplexSubOpLowering::matchAndRewrite(
4399 cir::ComplexSubOp op, OpAdaptor adaptor,
4400 mlir::ConversionPatternRewriter &rewriter)
const {
4401 mlir::Value lhs = adaptor.getLhs();
4402 mlir::Value rhs = adaptor.getRhs();
4403 mlir::Location loc = op.getLoc();
4405 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
4406 mlir::Type complexElemTy =
4407 getTypeConverter()->convertType(
complexType.getElementType());
4408 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
4409 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{0}));
4410 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
4411 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{1}));
4412 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
4413 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{0}));
4414 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
4415 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{1}));
4417 mlir::Value newReal;
4418 mlir::Value newImag;
4419 if (complexElemTy.isInteger()) {
4420 newReal = mlir::LLVM::SubOp::create(rewriter, loc, complexElemTy, lhsReal,
4422 newImag = mlir::LLVM::SubOp::create(rewriter, loc, complexElemTy, lhsImag,
4427 newReal = mlir::LLVM::FSubOp::create(rewriter, loc, complexElemTy, lhsReal,
4429 newImag = mlir::LLVM::FSubOp::create(rewriter, loc, complexElemTy, lhsImag,
4433 mlir::Type complexLLVMTy =
4434 getTypeConverter()->convertType(op.getResult().getType());
4435 auto initialComplex =
4436 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), complexLLVMTy);
4438 auto realComplex = mlir::LLVM::InsertValueOp::create(
4439 rewriter, op->getLoc(), initialComplex, newReal, ArrayRef(int64_t{0}));
4441 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
4442 op, realComplex, newImag, ArrayRef(int64_t{1}));
4444 return mlir::success();
4447mlir::LogicalResult CIRToLLVMComplexImagOpLowering::matchAndRewrite(
4448 cir::ComplexImagOp op, OpAdaptor adaptor,
4449 mlir::ConversionPatternRewriter &rewriter)
const {
4450 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
4451 mlir::Value operand = adaptor.getOperand();
4452 mlir::Location loc = op.getLoc();
4454 if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) {
4455 operand = mlir::LLVM::ExtractValueOp::create(
4456 rewriter, loc, resultLLVMTy, operand, llvm::ArrayRef<std::int64_t>{1});
4458 mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(resultLLVMTy);
4460 mlir::LLVM::ConstantOp::create(rewriter, loc, resultLLVMTy, zeroAttr);
4463 rewriter.replaceOp(op, operand);
4464 return mlir::success();
4468 mlir::MLIRContext *context,
4469 unsigned &storageSize) {
4470 return TypeSwitch<mlir::Type, mlir::IntegerType>(storageType)
4471 .Case<cir::ArrayType>([&](cir::ArrayType atTy) {
4472 storageSize = atTy.getSize() * 8;
4473 return mlir::IntegerType::get(context, storageSize);
4475 .Case<cir::IntType>([&](cir::IntType intTy) {
4476 storageSize = intTy.getWidth();
4477 return mlir::IntegerType::get(context, storageSize);
4479 .Default([](mlir::Type) -> mlir::IntegerType {
4481 "Either ArrayType or IntType expected for bitfields storage");
4485mlir::LogicalResult CIRToLLVMSetBitfieldOpLowering::matchAndRewrite(
4486 cir::SetBitfieldOp op, OpAdaptor adaptor,
4487 mlir::ConversionPatternRewriter &rewriter)
const {
4488 mlir::OpBuilder::InsertionGuard guard(rewriter);
4489 rewriter.setInsertionPoint(op);
4491 cir::BitfieldInfoAttr info = op.getBitfieldInfo();
4492 uint64_t size = info.getSize();
4493 uint64_t offset = info.getOffset();
4494 mlir::Type storageType = info.getStorageType();
4495 mlir::MLIRContext *context = storageType.getContext();
4497 unsigned storageSize = 0;
4499 mlir::IntegerType intType =
4502 mlir::Value srcVal =
createIntCast(rewriter, adaptor.getSrc(), intType);
4503 unsigned srcWidth = storageSize;
4504 mlir::Value resultVal = srcVal;
4506 if (storageSize != size) {
4507 assert(storageSize > size &&
"Invalid bitfield size.");
4509 mlir::Value val = mlir::LLVM::LoadOp::create(
4510 rewriter, op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(),
4511 op.getIsVolatile());
4514 createAnd(rewriter, srcVal, llvm::APInt::getLowBitsSet(srcWidth, size));
4516 srcVal =
createShL(rewriter, srcVal, offset);
4520 ~llvm::APInt::getBitsSet(srcWidth, offset, offset + size));
4523 srcVal = mlir::LLVM::OrOp::create(rewriter, op.getLoc(), val, srcVal);
4526 mlir::LLVM::StoreOp::create(rewriter, op.getLoc(), srcVal, adaptor.getAddr(),
4527 op.getAlignment(), op.getIsVolatile());
4529 mlir::Type resultTy = getTypeConverter()->convertType(op.getType());
4531 if (info.getIsSigned()) {
4532 assert(size <= storageSize);
4533 unsigned highBits = storageSize - size;
4536 resultVal =
createShL(rewriter, resultVal, highBits);
4537 resultVal =
createAShR(rewriter, resultVal, highBits);
4542 mlir::cast<mlir::IntegerType>(resultTy),
4543 info.getIsSigned());
4545 rewriter.replaceOp(op, resultVal);
4546 return mlir::success();
4549mlir::LogicalResult CIRToLLVMComplexImagPtrOpLowering::matchAndRewrite(
4550 cir::ComplexImagPtrOp op, OpAdaptor adaptor,
4551 mlir::ConversionPatternRewriter &rewriter)
const {
4552 cir::PointerType operandTy = op.getOperand().getType();
4553 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
4554 mlir::Type elementLLVMTy =
4555 getTypeConverter()->convertType(operandTy.getPointee());
4557 mlir::LLVM::GEPArg gepIndices[2] = {{0}, {1}};
4558 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
4559 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
4560 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
4561 op, resultLLVMTy, elementLLVMTy, adaptor.getOperand(), gepIndices,
4563 return mlir::success();
4566mlir::LogicalResult CIRToLLVMComplexRealPtrOpLowering::matchAndRewrite(
4567 cir::ComplexRealPtrOp op, OpAdaptor adaptor,
4568 mlir::ConversionPatternRewriter &rewriter)
const {
4569 cir::PointerType operandTy = op.getOperand().getType();
4570 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
4571 mlir::Type elementLLVMTy =
4572 getTypeConverter()->convertType(operandTy.getPointee());
4574 mlir::LLVM::GEPArg gepIndices[2] = {0, 0};
4575 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
4576 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
4577 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
4578 op, resultLLVMTy, elementLLVMTy, adaptor.getOperand(), gepIndices,
4580 return mlir::success();
4583mlir::LogicalResult CIRToLLVMGetBitfieldOpLowering::matchAndRewrite(
4584 cir::GetBitfieldOp op, OpAdaptor adaptor,
4585 mlir::ConversionPatternRewriter &rewriter)
const {
4587 mlir::OpBuilder::InsertionGuard guard(rewriter);
4588 rewriter.setInsertionPoint(op);
4590 cir::BitfieldInfoAttr info = op.getBitfieldInfo();
4592 uint64_t offset = info.getOffset();
4593 mlir::Type storageType = info.getStorageType();
4594 mlir::MLIRContext *context = storageType.getContext();
4595 unsigned storageSize = 0;
4597 mlir::IntegerType intType =
4600 mlir::Value val = mlir::LLVM::LoadOp::create(
4601 rewriter, op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(),
4602 op.getIsVolatile());
4603 val = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), intType, val);
4605 if (info.getIsSigned()) {
4606 assert(
static_cast<unsigned>(offset + size) <= storageSize);
4607 unsigned highBits = storageSize - offset - size;
4608 val =
createShL(rewriter, val, highBits);
4609 val =
createAShR(rewriter, val, offset + highBits);
4613 if (
static_cast<unsigned>(offset) + size < storageSize)
4615 llvm::APInt::getLowBitsSet(storageSize, size));
4618 mlir::Type resTy = getTypeConverter()->convertType(op.getType());
4620 rewriter, val, mlir::cast<mlir::IntegerType>(resTy), info.getIsSigned());
4621 rewriter.replaceOp(op, newOp);
4622 return mlir::success();
4625mlir::LogicalResult CIRToLLVMIsConstantOpLowering::matchAndRewrite(
4626 cir::IsConstantOp op, OpAdaptor adaptor,
4627 mlir::ConversionPatternRewriter &rewriter)
const {
4628 rewriter.replaceOpWithNewOp<mlir::LLVM::IsConstantOp>(op, adaptor.getVal());
4629 return mlir::success();
4632mlir::LogicalResult CIRToLLVMInlineAsmOpLowering::matchAndRewrite(
4633 cir::InlineAsmOp op, OpAdaptor adaptor,
4634 mlir::ConversionPatternRewriter &rewriter)
const {
4636 if (op.getNumResults())
4637 llResTy = getTypeConverter()->convertType(op.getType(0));
4639 cir::AsmFlavor dialect = op.getAsmFlavor();
4640 mlir::LLVM::AsmDialect llDialect = dialect == cir::AsmFlavor::x86_att
4641 ? mlir::LLVM::AsmDialect::AD_ATT
4642 : mlir::LLVM::AsmDialect::AD_Intel;
4644 SmallVector<mlir::Attribute> opAttrs;
4645 StringRef llvmAttrName = mlir::LLVM::InlineAsmOp::getElementTypeAttrName();
4651 if (!op.getNumResults())
4652 opAttrs.push_back(mlir::Attribute());
4654 SmallVector<mlir::Value> llvmOperands;
4655 SmallVector<mlir::Value> cirOperands;
4656 for (
auto const &[llvmOp, cirOp] :
4657 zip(adaptor.getAsmOperands(), op.getAsmOperands())) {
4658 append_range(llvmOperands, llvmOp);
4659 append_range(cirOperands, cirOp);
4664 for (
auto const &[cirOpAttr, cirOp] :
4665 zip(op.getOperandAttrs(), cirOperands)) {
4667 opAttrs.push_back(mlir::Attribute());
4671 llvm::SmallVector<mlir::NamedAttribute, 1> attrs;
4672 cir::PointerType typ = mlir::cast<cir::PointerType>(cirOp.getType());
4674 *getTypeConverter(), dataLayout, typ.getPointee()));
4676 attrs.push_back(rewriter.getNamedAttr(llvmAttrName, typAttr));
4677 mlir::DictionaryAttr newDict = rewriter.getDictionaryAttr(attrs);
4678 opAttrs.push_back(newDict);
4681 rewriter.replaceOpWithNewOp<mlir::LLVM::InlineAsmOp>(
4682 op, llResTy, llvmOperands, op.getAsmStringAttr(), op.getConstraintsAttr(),
4683 op.getSideEffectsAttr(),
4686 mlir::LLVM::TailCallKindAttr::get(
4687 getContext(), mlir::LLVM::tailcallkind::TailCallKind::None),
4688 mlir::LLVM::AsmDialectAttr::get(getContext(), llDialect),
4689 rewriter.getArrayAttr(opAttrs));
4691 return mlir::success();
4694mlir::LogicalResult CIRToLLVMVAStartOpLowering::matchAndRewrite(
4695 cir::VAStartOp op, OpAdaptor adaptor,
4696 mlir::ConversionPatternRewriter &rewriter)
const {
4697 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4698 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4699 adaptor.getArgList());
4700 rewriter.replaceOpWithNewOp<mlir::LLVM::VaStartOp>(op, vaList);
4701 return mlir::success();
4704mlir::LogicalResult CIRToLLVMVAEndOpLowering::matchAndRewrite(
4705 cir::VAEndOp op, OpAdaptor adaptor,
4706 mlir::ConversionPatternRewriter &rewriter)
const {
4707 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4708 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4709 adaptor.getArgList());
4710 rewriter.replaceOpWithNewOp<mlir::LLVM::VaEndOp>(op, vaList);
4711 return mlir::success();
4714mlir::LogicalResult CIRToLLVMVACopyOpLowering::matchAndRewrite(
4715 cir::VACopyOp op, OpAdaptor adaptor,
4716 mlir::ConversionPatternRewriter &rewriter)
const {
4717 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4718 auto dstList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4719 adaptor.getDstList());
4720 auto srcList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4721 adaptor.getSrcList());
4722 rewriter.replaceOpWithNewOp<mlir::LLVM::VaCopyOp>(op, dstList, srcList);
4723 return mlir::success();
4726mlir::LogicalResult CIRToLLVMVAArgOpLowering::matchAndRewrite(
4727 cir::VAArgOp op, OpAdaptor adaptor,
4728 mlir::ConversionPatternRewriter &rewriter)
const {
4730 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4731 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4732 adaptor.getArgList());
4734 mlir::Type llvmType =
4735 getTypeConverter()->convertType(op->getResultTypes().front());
4737 return mlir::failure();
4739 rewriter.replaceOpWithNewOp<mlir::LLVM::VaArgOp>(op, llvmType, vaList);
4740 return mlir::success();
4743mlir::LogicalResult CIRToLLVMLabelOpLowering::matchAndRewrite(
4744 cir::LabelOp op, OpAdaptor adaptor,
4745 mlir::ConversionPatternRewriter &rewriter)
const {
4746 mlir::MLIRContext *ctx = rewriter.getContext();
4747 mlir::Block *block = op->getBlock();
4750 if (block->isEntryBlock()) {
4751 mlir::Block *newBlock =
4752 rewriter.splitBlock(op->getBlock(), mlir::Block::iterator(op));
4753 rewriter.setInsertionPointToEnd(block);
4754 mlir::LLVM::BrOp::create(rewriter, op.getLoc(), newBlock);
4757 mlir::LLVM::BlockTagAttr::get(ctx, blockInfoAddr.getTagIndex());
4758 rewriter.setInsertionPoint(op);
4761 mlir::LLVM::BlockTagOp::create(rewriter, op->getLoc(), tagAttr);
4762 mlir::LLVM::LLVMFuncOp func = op->getParentOfType<mlir::LLVM::LLVMFuncOp>();
4763 auto blockInfoAttr =
4764 cir::BlockAddrInfoAttr::get(ctx, func.getSymName(), op.getLabel());
4765 blockInfoAddr.mapBlockTag(blockInfoAttr, blockTagOp);
4766 rewriter.eraseOp(op);
4768 return mlir::success();
4771mlir::LogicalResult CIRToLLVMBlockAddressOpLowering::matchAndRewrite(
4772 cir::BlockAddressOp op, OpAdaptor adaptor,
4773 mlir::ConversionPatternRewriter &rewriter)
const {
4774 mlir::MLIRContext *ctx = rewriter.getContext();
4776 mlir::LLVM::BlockTagOp matchLabel =
4777 blockInfoAddr.lookupBlockTag(op.getBlockAddrInfoAttr());
4778 mlir::LLVM::BlockTagAttr tagAttr;
4785 tagAttr = matchLabel.getTag();
4787 auto blkAddr = mlir::LLVM::BlockAddressAttr::get(
4788 rewriter.getContext(), op.getBlockAddrInfoAttr().getFunc(), tagAttr);
4789 rewriter.setInsertionPoint(op);
4790 auto newOp = mlir::LLVM::BlockAddressOp::create(
4791 rewriter, op.getLoc(), mlir::LLVM::LLVMPointerType::get(ctx), blkAddr);
4793 blockInfoAddr.addUnresolvedBlockAddress(newOp, op.getBlockAddrInfoAttr());
4794 rewriter.replaceOp(op, newOp);
4795 return mlir::success();
4798mlir::LogicalResult CIRToLLVMIndirectBrOpLowering::matchAndRewrite(
4799 cir::IndirectBrOp op, OpAdaptor adaptor,
4800 mlir::ConversionPatternRewriter &rewriter)
const {
4802 llvm::SmallVector<mlir::Block *, 8> successors;
4803 llvm::SmallVector<mlir::ValueRange, 8> succOperands;
4804 bool poison = op.getPoison();
4805 for (mlir::Block *succ : op->getSuccessors())
4806 successors.push_back(succ);
4808 for (mlir::ValueRange operand : op.getSuccOperands()) {
4809 succOperands.push_back(operand);
4812 auto llvmPtrType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4813 mlir::Value targetAddr;
4815 targetAddr = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(),
4816 llvmPtrType, adaptor.getAddr());
4819 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), llvmPtrType);
4822 op->getBlock()->eraseArgument(0);
4825 auto newOp = mlir::LLVM::IndirectBrOp::create(
4826 rewriter, op.getLoc(), targetAddr, succOperands, successors);
4827 rewriter.replaceOp(op, newOp);
4828 return mlir::success();
4831mlir::LogicalResult CIRToLLVMAwaitOpLowering::matchAndRewrite(
4832 cir::AwaitOp op, OpAdaptor adaptor,
4833 mlir::ConversionPatternRewriter &rewriter)
const {
4834 return mlir::failure();
4837mlir::LogicalResult CIRToLLVMCpuIdOpLowering::matchAndRewrite(
4838 cir::CpuIdOp op, OpAdaptor adaptor,
4839 mlir::ConversionPatternRewriter &rewriter)
const {
4840 mlir::Type i32Ty = rewriter.getI32Type();
4841 mlir::Type i64Ty = rewriter.getI64Type();
4842 mlir::Type i32PtrTy = mlir::LLVM::LLVMPointerType::get(i32Ty.getContext(), 0);
4844 mlir::Type cpuidRetTy = mlir::LLVM::LLVMStructType::getLiteral(
4845 rewriter.getContext(), {i32Ty, i32Ty, i32Ty, i32Ty});
4847 mlir::Value functionId = adaptor.getFunctionId();
4848 mlir::Value subFunctionId = adaptor.getSubFunctionId();
4850 StringRef asmString, constraints;
4851 mlir::ModuleOp moduleOp = op->getParentOfType<mlir::ModuleOp>();
4852 llvm::Triple triple(
4853 mlir::cast<mlir::StringAttr>(
4854 moduleOp->getAttr(cir::CIRDialect::getTripleAttrName()))
4856 if (triple.getArch() == llvm::Triple::x86) {
4857 asmString =
"cpuid";
4858 constraints =
"={ax},={bx},={cx},={dx},{ax},{cx}";
4861 asmString =
"xchgq %rbx, ${1:q}\n"
4863 "xchgq %rbx, ${1:q}";
4864 constraints =
"={ax},=r,={cx},={dx},0,2";
4867 mlir::Value inlineAsm =
4868 mlir::LLVM::InlineAsmOp::create(
4869 rewriter, op.getLoc(), cpuidRetTy, {functionId, subFunctionId},
4870 rewriter.getStringAttr(asmString),
4871 rewriter.getStringAttr(constraints),
4874 mlir::LLVM::TailCallKindAttr{},
4875 mlir::LLVM::AsmDialectAttr{},
4879 mlir::Value basePtr = adaptor.getCpuInfo();
4881 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
4882 unsigned alignment = layout.getTypeABIAlignment(i32Ty);
4883 for (
unsigned i = 0; i < 4; i++) {
4884 mlir::Value extracted =
4885 mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(), inlineAsm, i)
4887 mlir::Value index = mlir::LLVM::ConstantOp::create(
4888 rewriter, op.getLoc(), i64Ty, rewriter.getI64IntegerAttr(i));
4889 llvm::SmallVector<mlir::Value, 1> gepIndices = {index};
4890 mlir::Value storePtr = mlir::LLVM::GEPOp::create(
4891 rewriter, op.getLoc(), i32PtrTy, i32Ty, basePtr,
4892 gepIndices, mlir::LLVM::GEPNoWrapFlags::none)
4894 mlir::LLVM::StoreOp::create(rewriter, op.getLoc(), extracted, storePtr,
4898 rewriter.eraseOp(op);
4899 return mlir::success();
4902mlir::LogicalResult CIRToLLVMMemChrOpLowering::matchAndRewrite(
4903 cir::MemChrOp op, OpAdaptor adaptor,
4904 mlir::ConversionPatternRewriter &rewriter)
const {
4905 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4906 mlir::Type srcTy = getTypeConverter()->convertType(op.getSrc().getType());
4907 mlir::Type patternTy =
4908 getTypeConverter()->convertType(op.getPattern().getType());
4909 mlir::Type lenTy = getTypeConverter()->convertType(op.getLen().getType());
4911 mlir::LLVM::LLVMFunctionType::get(llvmPtrTy, {srcTy, patternTy, lenTy},
4913 llvm::StringRef fnName =
"memchr";
4915 rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(
4916 op, mlir::TypeRange{llvmPtrTy}, fnName,
4917 mlir::ValueRange{adaptor.getSrc(), adaptor.getPattern(),
4919 return mlir::success();
4923 return std::make_unique<ConvertCIRToLLVMPass>();
4931std::unique_ptr<llvm::Module>
4933 llvm::TimeTraceScope scope(
"lower from CIR to LLVM directly");
4935 mlir::MLIRContext *mlirCtx = mlirModule.getContext();
4937 mlir::PassManager pm(mlirCtx);
4940 (void)mlir::applyPassManagerCLOptions(pm);
4942 if (mlir::failed(pm.run(mlirModule))) {
4945 "The pass manager failed to lower CIR to LLVMIR dialect!");
4948 mlir::registerBuiltinDialectTranslation(*mlirCtx);
4949 mlir::registerLLVMDialectTranslation(*mlirCtx);
4950 mlir::registerOpenMPDialectTranslation(*mlirCtx);
4953 llvm::TimeTraceScope translateScope(
"translateModuleToLLVMIR");
4955 StringRef moduleName = mlirModule.getName().value_or(
"CIRToLLVMModule");
4956 std::unique_ptr<llvm::Module> llvmModule =
4957 mlir::translateModuleToLLVMIR(mlirModule, llvmCtx, moduleName);
4961 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)
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
static bool isVector(QualType QT, QualType ElementType)
This helper function returns true if QT is a vector type that has element type ElementType.
__DEVICE__ void * memset(void *__a, int __b, size_t __c)
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.
void convertSideEffectForCall(mlir::Operation *callOp, bool isNothrow, cir::SideEffect sideEffect, mlir::LLVM::MemoryEffectsAttr &memoryEffect, bool &noUnwind, bool &willReturn, bool &noReturn)
static mlir::LLVM::IntegerOverflowFlags intOverflowFlag(BinOp op)
static mlir::LogicalResult lowerIntFPBinaryOp(CIROp op, mlir::Value lhs, mlir::Value rhs, mlir::ConversionPatternRewriter &rewriter)
Lower a binary op that maps to unsigned/signed/FP LLVM ops depending on operand type.
static mlir::Value getLLVMIntCast(mlir::ConversionPatternRewriter &rewriter, mlir::Value llvmSrc, mlir::Type llvmDstIntTy, bool isUnsigned, uint64_t cirSrcWidth, uint64_t cirDstIntWidth)
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::LLVM::LLVMStructType getLLVMLandingPadStructTy(mlir::ConversionPatternRewriter &rewriter)
std::unique_ptr< llvm::Module > lowerDirectlyFromCIRToLLVMIR(mlir::ModuleOp mlirModule, llvm::LLVMContext &llvmCtx)
mlir::Value lowerCirAttrAsValue(mlir::Operation *parentOp, const mlir::Attribute attr, mlir::ConversionPatternRewriter &rewriter, const mlir::TypeConverter *converter)
Switches on the type of attribute and calls the appropriate conversion.
static llvm::StringLiteral getLLVMBinop(cir::AtomicFetchKind k, bool isInt)
static mlir::Value convertToIndexTy(mlir::ConversionPatternRewriter &rewriter, mlir::ModuleOp mod, mlir::Value index, mlir::Type baseTy, cir::IntType strideTy)
static mlir::LogicalResult lowerSaturatableArithOp(CIROp op, mlir::Value lhs, mlir::Value rhs, mlir::ConversionPatternRewriter &rewriter)
Lower an arithmetic op that supports saturation, overflow flags, and an FP variant.
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 llvm::StringRef getLLVMSyncScope(cir::SyncScopeKind syncScope)
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 void lowerCallAttributes(cir::CIRCallOpInterface op, SmallVectorImpl< mlir::NamedAttribute > &result)
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 mlir::LogicalResult rewriteCallOrInvoke(mlir::Operation *op, mlir::ValueRange callOperands, mlir::ConversionPatternRewriter &rewriter, const mlir::TypeConverter *converter, mlir::FlatSymbolRefAttr calleeAttr, mlir::Block *continueBlock=nullptr, mlir::Block *landingPadBlock=nullptr)
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
Diagnostic wrappers for TextAPI types for error reporting.
void populateCIRPreLoweringPasses(mlir::OpPassManager &pm)
void registerCIRDialectTranslation(mlir::MLIRContext &context)
char __ovld __cnfn clz(char)
Returns the number of leading 0-bits in x, starting at the most significant bit position.
char __ovld __cnfn ctz(char)
Returns the count of trailing 0-bits in x.
float __ovld __cnfn sign(float)
Returns 1.0 if x > 0, -0.0 if x = -0.0, +0.0 if x = +0.0, or -1.0 if x < 0.
float __ovld __cnfn length(float)
Return the length of vector p, i.e., sqrt(p.x2 + p.y 2 + ...)
char __ovld __cnfn select(char, char, char)
For each component of a vector type, result[i] = if MSB of c[i] is set ?
static bool dataMemberType()
static bool addressSpace()
static bool globalViewIntLowering()
static bool opAllocaAnnotations()
static bool opLoadStoreTbaa()
static bool optInfoAttr()
static bool opFuncExtraAttrs()
static bool isPPC_FP128Ty()
static bool vaArgABILowering()
static bool fpConstraints()
static bool intrinsicElementTypeSupport()
static bool lowerModeOptLevel()
static bool opCallCallConv()
static bool opFuncCallingConv()
static bool aggValueSlotVolatile()
static bool fastMathFlags()
static bool 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 resolveBlockAddressOp(LLVMBlockAddressInfo &blockInfoAddr)
void processCIRAttrs(mlir::ModuleOp module)
mlir::LLVM::BlockTagOp lookupBlockTag(cir::BlockAddrInfoAttr info) const
void clearUnresolvedMap()
llvm::DenseMap< mlir::LLVM::BlockAddressOp, cir::BlockAddrInfoAttr > & getUnresolvedBlockAddress()