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"
49#include "llvm/Support/raw_ostream.h"
64mlir::Type elementTypeIfVector(mlir::Type type) {
65 return llvm::TypeSwitch<mlir::Type, mlir::Type>(type)
66 .Case<cir::VectorType, mlir::VectorType>(
67 [](
auto p) {
return p.getElementType(); })
68 .
Default([](mlir::Type p) {
return p; });
76 mlir::DataLayout
const &dataLayout,
80 if (isa<cir::BoolType>(type)) {
81 return mlir::IntegerType::get(type.getContext(),
82 dataLayout.getTypeSizeInBits(type));
85 return converter.convertType(type);
89 mlir::IntegerType dstTy,
90 bool isSigned =
false) {
91 mlir::Type srcTy = src.getType();
92 assert(mlir::isa<mlir::IntegerType>(srcTy));
94 unsigned srcWidth = mlir::cast<mlir::IntegerType>(srcTy).getWidth();
95 unsigned dstWidth = mlir::cast<mlir::IntegerType>(dstTy).getWidth();
96 mlir::Location loc = src.getLoc();
98 if (dstWidth > srcWidth && isSigned)
99 return mlir::LLVM::SExtOp::create(bld, loc, dstTy, src);
100 if (dstWidth > srcWidth)
101 return mlir::LLVM::ZExtOp::create(bld, loc, dstTy, src);
102 if (dstWidth < srcWidth)
103 return mlir::LLVM::TruncOp::create(bld, loc, dstTy, src);
104 return mlir::LLVM::BitcastOp::create(bld, loc, dstTy, src);
107static mlir::LLVM::Visibility
109 switch (visibilityKind) {
110 case cir::VisibilityKind::Default:
111 return ::mlir::LLVM::Visibility::Default;
112 case cir::VisibilityKind::Hidden:
113 return ::mlir::LLVM::Visibility::Hidden;
114 case cir::VisibilityKind::Protected:
115 return ::mlir::LLVM::Visibility::Protected;
123 mlir::DataLayout
const &dataLayout,
124 cir::LoadOp op, mlir::Value value) {
127 if (
auto boolTy = mlir::dyn_cast<cir::BoolType>(op.getType())) {
129 assert(value.getType().isInteger(dataLayout.getTypeSizeInBits(boolTy)));
139static mlir::Value
emitToMemory(mlir::ConversionPatternRewriter &rewriter,
140 mlir::DataLayout
const &dataLayout,
141 mlir::Type origType, mlir::Value value) {
144 if (
auto boolTy = mlir::dyn_cast<cir::BoolType>(origType)) {
146 mlir::IntegerType memType =
147 rewriter.getIntegerType(dataLayout.getTypeSizeInBits(boolTy));
155 using CIR = cir::GlobalLinkageKind;
156 using LLVM = mlir::LLVM::Linkage;
159 case CIR::AppendingLinkage:
160 return LLVM::Appending;
161 case CIR::AvailableExternallyLinkage:
162 return LLVM::AvailableExternally;
163 case CIR::CommonLinkage:
165 case CIR::ExternalLinkage:
166 return LLVM::External;
167 case CIR::ExternalWeakLinkage:
168 return LLVM::ExternWeak;
169 case CIR::InternalLinkage:
170 return LLVM::Internal;
171 case CIR::LinkOnceAnyLinkage:
172 return LLVM::Linkonce;
173 case CIR::LinkOnceODRLinkage:
174 return LLVM::LinkonceODR;
175 case CIR::PrivateLinkage:
176 return LLVM::Private;
177 case CIR::WeakAnyLinkage:
179 case CIR::WeakODRLinkage:
180 return LLVM::WeakODR;
182 llvm_unreachable(
"Unknown CIR linkage type");
185mlir::LogicalResult CIRToLLVMCopyOpLowering::matchAndRewrite(
186 cir::CopyOp op, OpAdaptor adaptor,
187 mlir::ConversionPatternRewriter &rewriter)
const {
188 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
189 const mlir::Value
length = mlir::LLVM::ConstantOp::create(
190 rewriter, op.getLoc(), rewriter.getI64Type(), op.getLength(layout));
192 rewriter.replaceOpWithNewOp<mlir::LLVM::MemcpyOp>(
193 op, adaptor.getDst(), adaptor.getSrc(),
length, op.getIsVolatile());
194 return mlir::success();
197mlir::LogicalResult CIRToLLVMMemCpyOpLowering::matchAndRewrite(
198 cir::MemCpyOp op, OpAdaptor adaptor,
199 mlir::ConversionPatternRewriter &rewriter)
const {
200 rewriter.replaceOpWithNewOp<mlir::LLVM::MemcpyOp>(
201 op, adaptor.getDst(), adaptor.getSrc(), adaptor.getLen(),
203 return mlir::success();
206mlir::LogicalResult CIRToLLVMMemMoveOpLowering::matchAndRewrite(
207 cir::MemMoveOp op, OpAdaptor adaptor,
208 mlir::ConversionPatternRewriter &rewriter)
const {
209 rewriter.replaceOpWithNewOp<mlir::LLVM::MemmoveOp>(
210 op, adaptor.getDst(), adaptor.getSrc(), adaptor.getLen(),
212 return mlir::success();
215mlir::LogicalResult CIRToLLVMMemSetOpLowering::matchAndRewrite(
216 cir::MemSetOp op, OpAdaptor adaptor,
217 mlir::ConversionPatternRewriter &rewriter)
const {
219 auto memset = rewriter.replaceOpWithNewOp<mlir::LLVM::MemsetOp>(
220 op, adaptor.getDst(), adaptor.getVal(), adaptor.getLen(),
223 if (op.getAlignmentAttr()) {
225 llvm::SmallVector<mlir::Attribute> attrs{
memset.getNumOperands(),
226 rewriter.getDictionaryAttr({})};
227 llvm::SmallVector<mlir::NamedAttribute> destAttrs;
229 {mlir::LLVM::LLVMDialect::getAlignAttrName(), op.getAlignmentAttr()});
230 attrs[
memset.odsIndex_dst] = rewriter.getDictionaryAttr(destAttrs);
232 auto arrayAttr = rewriter.getArrayAttr(attrs);
233 memset.setArgAttrsAttr(arrayAttr);
236 return mlir::success();
239mlir::LogicalResult CIRToLLVMSqrtOpLowering::matchAndRewrite(
240 cir::SqrtOp op, OpAdaptor adaptor,
241 mlir::ConversionPatternRewriter &rewriter)
const {
242 mlir::Type resTy = typeConverter->convertType(op.getType());
243 rewriter.replaceOpWithNewOp<mlir::LLVM::SqrtOp>(op, resTy, adaptor.getSrc());
244 return mlir::success();
247mlir::LogicalResult CIRToLLVMCosOpLowering::matchAndRewrite(
248 cir::CosOp op, OpAdaptor adaptor,
249 mlir::ConversionPatternRewriter &rewriter)
const {
250 mlir::Type resTy = typeConverter->convertType(op.getType());
251 rewriter.replaceOpWithNewOp<mlir::LLVM::CosOp>(op, resTy, adaptor.getSrc());
252 return mlir::success();
255mlir::LogicalResult CIRToLLVMExpOpLowering::matchAndRewrite(
256 cir::ExpOp op, OpAdaptor adaptor,
257 mlir::ConversionPatternRewriter &rewriter)
const {
258 mlir::Type resTy = typeConverter->convertType(op.getType());
259 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpOp>(op, resTy, adaptor.getSrc());
260 return mlir::success();
263mlir::LogicalResult CIRToLLVMExp2OpLowering::matchAndRewrite(
264 cir::Exp2Op op, OpAdaptor adaptor,
265 mlir::ConversionPatternRewriter &rewriter)
const {
266 mlir::Type resTy = typeConverter->convertType(op.getType());
267 rewriter.replaceOpWithNewOp<mlir::LLVM::Exp2Op>(op, resTy, adaptor.getSrc());
268 return mlir::success();
271mlir::LogicalResult CIRToLLVMLogOpLowering::matchAndRewrite(
272 cir::LogOp op, OpAdaptor adaptor,
273 mlir::ConversionPatternRewriter &rewriter)
const {
274 mlir::Type resTy = typeConverter->convertType(op.getType());
275 rewriter.replaceOpWithNewOp<mlir::LLVM::LogOp>(op, resTy, adaptor.getSrc());
276 return mlir::success();
279mlir::LogicalResult CIRToLLVMLog10OpLowering::matchAndRewrite(
280 cir::Log10Op op, OpAdaptor adaptor,
281 mlir::ConversionPatternRewriter &rewriter)
const {
282 mlir::Type resTy = typeConverter->convertType(op.getType());
283 rewriter.replaceOpWithNewOp<mlir::LLVM::Log10Op>(op, resTy, adaptor.getSrc());
284 return mlir::success();
287mlir::LogicalResult CIRToLLVMLog2OpLowering::matchAndRewrite(
288 cir::Log2Op op, OpAdaptor adaptor,
289 mlir::ConversionPatternRewriter &rewriter)
const {
290 mlir::Type resTy = typeConverter->convertType(op.getType());
291 rewriter.replaceOpWithNewOp<mlir::LLVM::Log2Op>(op, resTy, adaptor.getSrc());
292 return mlir::success();
295mlir::LogicalResult CIRToLLVMNearbyintOpLowering::matchAndRewrite(
296 cir::NearbyintOp op, OpAdaptor adaptor,
297 mlir::ConversionPatternRewriter &rewriter)
const {
298 mlir::Type resTy = typeConverter->convertType(op.getType());
299 rewriter.replaceOpWithNewOp<mlir::LLVM::NearbyintOp>(op, resTy,
301 return mlir::success();
304mlir::LogicalResult CIRToLLVMRintOpLowering::matchAndRewrite(
305 cir::RintOp op, OpAdaptor adaptor,
306 mlir::ConversionPatternRewriter &rewriter)
const {
307 mlir::Type resTy = typeConverter->convertType(op.getType());
308 rewriter.replaceOpWithNewOp<mlir::LLVM::RintOp>(op, resTy, adaptor.getSrc());
309 return mlir::success();
312mlir::LogicalResult CIRToLLVMRoundOpLowering::matchAndRewrite(
313 cir::RoundOp op, OpAdaptor adaptor,
314 mlir::ConversionPatternRewriter &rewriter)
const {
315 mlir::Type resTy = typeConverter->convertType(op.getType());
316 rewriter.replaceOpWithNewOp<mlir::LLVM::RoundOp>(op, resTy, adaptor.getSrc());
317 return mlir::success();
320mlir::LogicalResult CIRToLLVMRoundEvenOpLowering::matchAndRewrite(
321 cir::RoundEvenOp op, OpAdaptor adaptor,
322 mlir::ConversionPatternRewriter &rewriter)
const {
323 mlir::Type resTy = typeConverter->convertType(op.getType());
324 rewriter.replaceOpWithNewOp<mlir::LLVM::RoundEvenOp>(op, resTy,
326 return mlir::success();
329mlir::LogicalResult CIRToLLVMSinOpLowering::matchAndRewrite(
330 cir::SinOp op, OpAdaptor adaptor,
331 mlir::ConversionPatternRewriter &rewriter)
const {
332 mlir::Type resTy = typeConverter->convertType(op.getType());
333 rewriter.replaceOpWithNewOp<mlir::LLVM::SinOp>(op, resTy, adaptor.getSrc());
334 return mlir::success();
337mlir::LogicalResult CIRToLLVMTanOpLowering::matchAndRewrite(
338 cir::TanOp op, OpAdaptor adaptor,
339 mlir::ConversionPatternRewriter &rewriter)
const {
340 mlir::Type resTy = typeConverter->convertType(op.getType());
341 rewriter.replaceOpWithNewOp<mlir::LLVM::TanOp>(op, resTy, adaptor.getSrc());
342 return mlir::success();
345mlir::LogicalResult CIRToLLVMTruncOpLowering::matchAndRewrite(
346 cir::TruncOp op, OpAdaptor adaptor,
347 mlir::ConversionPatternRewriter &rewriter)
const {
348 mlir::Type resTy = typeConverter->convertType(op.getType());
349 rewriter.replaceOpWithNewOp<mlir::LLVM::FTruncOp>(op, resTy,
351 return mlir::success();
354mlir::LogicalResult CIRToLLVMFloorOpLowering::matchAndRewrite(
355 cir::FloorOp op, OpAdaptor adaptor,
356 mlir::ConversionPatternRewriter &rewriter)
const {
357 mlir::Type resTy = typeConverter->convertType(op.getType());
358 rewriter.replaceOpWithNewOp<mlir::LLVM::FFloorOp>(op, resTy,
360 return mlir::success();
364 mlir::Value llvmSrc, mlir::Type llvmDstIntTy,
366 uint64_t cirDstIntWidth) {
367 if (cirSrcWidth == cirDstIntWidth)
370 auto loc = llvmSrc.getLoc();
371 if (cirSrcWidth < cirDstIntWidth) {
373 return mlir::LLVM::ZExtOp::create(rewriter, loc, llvmDstIntTy, llvmSrc);
374 return mlir::LLVM::SExtOp::create(rewriter, loc, llvmDstIntTy, llvmSrc);
378 return mlir::LLVM::TruncOp::create(rewriter, loc, llvmDstIntTy, llvmSrc);
384 mlir::ConversionPatternRewriter &rewriter,
385 const mlir::TypeConverter *converter)
386 : parentOp(parentOp), rewriter(rewriter), converter(converter) {}
389 return llvm::TypeSwitch<mlir::Attribute, mlir::Value>(
attr)
390 .Case<cir::BoolAttr, cir::IntAttr, cir::FPAttr, cir::ConstComplexAttr,
391 cir::ConstArrayAttr, cir::ConstRecordAttr, cir::ConstVectorAttr,
392 cir::ConstPtrAttr, cir::GlobalViewAttr, cir::TypeInfoAttr,
393 cir::UndefAttr, cir::VTableAttr, cir::ZeroAttr>(
395 .
Default([&](
auto attrT) {
return mlir::Value(); });
401 mlir::Value
visitCirAttr(cir::ConstComplexAttr complexAttr);
413 mlir::Operation *parentOp;
414 mlir::ConversionPatternRewriter &rewriter;
415 const mlir::TypeConverter *converter;
420 const mlir::Attribute attr,
421 mlir::ConversionPatternRewriter &rewriter,
422 const mlir::TypeConverter *converter) {
424 mlir::Value value = valueConverter.
visit(attr);
426 llvm_unreachable(
"unhandled attribute type");
431 cir::SideEffect sideEffect,
432 mlir::LLVM::MemoryEffectsAttr &memoryEffect,
433 bool &noUnwind,
bool &willReturn,
435 using mlir::LLVM::ModRefInfo;
437 switch (sideEffect) {
438 case cir::SideEffect::All:
440 noUnwind = isNothrow;
444 case cir::SideEffect::Pure:
445 memoryEffect = mlir::LLVM::MemoryEffectsAttr::get(
446 callOp->getContext(), ModRefInfo::Ref,
456 case cir::SideEffect::Const:
457 memoryEffect = mlir::LLVM::MemoryEffectsAttr::get(
458 callOp->getContext(), ModRefInfo::NoModRef,
459 ModRefInfo::NoModRef,
460 ModRefInfo::NoModRef,
461 ModRefInfo::NoModRef,
462 ModRefInfo::NoModRef,
463 ModRefInfo::NoModRef);
469 noReturn = callOp->hasAttr(CIRDialect::getNoReturnAttrName());
472static mlir::LLVM::CallIntrinsicOp
474 mlir::Location loc,
const llvm::Twine &intrinsicName,
475 mlir::Type resultTy, mlir::ValueRange operands) {
476 auto intrinsicNameAttr =
477 mlir::StringAttr::get(rewriter.getContext(), intrinsicName);
478 return mlir::LLVM::CallIntrinsicOp::create(rewriter, loc, resultTy,
479 intrinsicNameAttr, operands);
483 mlir::ConversionPatternRewriter &rewriter, mlir::Operation *op,
484 const llvm::Twine &intrinsicName, mlir::Type resultTy,
485 mlir::ValueRange operands) {
487 rewriter, op->getLoc(), intrinsicName, resultTy, operands);
488 rewriter.replaceOp(op, callIntrinOp.getOperation());
492mlir::LogicalResult CIRToLLVMLLVMIntrinsicCallOpLowering::matchAndRewrite(
493 cir::LLVMIntrinsicCallOp op, OpAdaptor adaptor,
494 mlir::ConversionPatternRewriter &rewriter)
const {
495 mlir::Type llvmResTy =
496 getTypeConverter()->convertType(op->getResultTypes()[0]);
498 return op.emitError(
"expected LLVM result type");
499 StringRef name = op.getIntrinsicName();
512 adaptor.getOperands());
513 return mlir::success();
518 mlir::Location loc = parentOp->getLoc();
519 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
520 mlir::Value boolVal = mlir::LLVM::ConstantOp::create(
521 rewriter, loc, converter->convertType(boolAttr.getType()),
522 boolAttr.getValue());
523 return emitToMemory(rewriter, layout, boolAttr.getType(), boolVal);
528 mlir::Location loc = parentOp->getLoc();
529 return mlir::LLVM::ConstantOp::create(
530 rewriter, loc, converter->convertType(intAttr.getType()),
536 mlir::Location loc = parentOp->getLoc();
537 return mlir::LLVM::ConstantOp::create(
538 rewriter, loc, converter->convertType(fltAttr.getType()),
544 auto complexType = mlir::cast<cir::ComplexType>(complexAttr.getType());
545 mlir::Type complexElemTy =
complexType.getElementType();
546 mlir::Type complexElemLLVMTy = converter->convertType(complexElemTy);
548 mlir::Attribute components[2];
549 if (
const auto intType = mlir::dyn_cast<cir::IntType>(complexElemTy)) {
550 components[0] = rewriter.getIntegerAttr(
552 mlir::cast<cir::IntAttr>(complexAttr.getReal()).getValue());
553 components[1] = rewriter.getIntegerAttr(
555 mlir::cast<cir::IntAttr>(complexAttr.getImag()).getValue());
557 components[0] = rewriter.getFloatAttr(
559 mlir::cast<cir::FPAttr>(complexAttr.getReal()).getValue());
560 components[1] = rewriter.getFloatAttr(
562 mlir::cast<cir::FPAttr>(complexAttr.getImag()).getValue());
565 mlir::Location loc = parentOp->getLoc();
566 return mlir::LLVM::ConstantOp::create(
567 rewriter, loc, converter->convertType(complexAttr.getType()),
568 rewriter.getArrayAttr(components));
573 mlir::Location loc = parentOp->getLoc();
574 if (ptrAttr.isNullValue()) {
575 return mlir::LLVM::ZeroOp::create(
576 rewriter, loc, converter->convertType(ptrAttr.getType()));
578 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
579 mlir::Value ptrVal = mlir::LLVM::ConstantOp::create(
581 rewriter.getIntegerType(layout.getTypeSizeInBits(ptrAttr.getType())),
582 ptrAttr.getValue().getInt());
583 return mlir::LLVM::IntToPtrOp::create(
584 rewriter, loc, converter->convertType(ptrAttr.getType()), ptrVal);
589 mlir::Type llvmTy = converter->convertType(
attr.getType());
590 mlir::Location loc = parentOp->getLoc();
593 if (
attr.hasTrailingZeros()) {
594 mlir::Type arrayTy =
attr.getType();
595 result = mlir::LLVM::ZeroOp::create(rewriter, loc,
596 converter->convertType(arrayTy));
598 result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
602 if (
auto arrayAttr = mlir::dyn_cast<mlir::ArrayAttr>(
attr.getElts())) {
603 for (
auto [idx, elt] : llvm::enumerate(arrayAttr)) {
604 mlir::DataLayout dataLayout(parentOp->getParentOfType<mlir::ModuleOp>());
605 mlir::Value init =
visit(elt);
607 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
609 }
else if (
auto strAttr = mlir::dyn_cast<mlir::StringAttr>(
attr.getElts())) {
612 auto arrayTy = mlir::dyn_cast<cir::ArrayType>(strAttr.getType());
613 assert(arrayTy &&
"String attribute must have an array type");
614 mlir::Type eltTy = arrayTy.getElementType();
615 for (
auto [idx, elt] : llvm::enumerate(strAttr)) {
616 auto init = mlir::LLVM::ConstantOp::create(
617 rewriter, loc, converter->convertType(eltTy), elt);
619 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
622 llvm_unreachable(
"unexpected ConstArrayAttr elements");
630 const mlir::Type llvmTy = converter->convertType(constRecord.getType());
631 const mlir::Location loc = parentOp->getLoc();
632 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
635 for (
auto [idx, elt] : llvm::enumerate(constRecord.getMembers())) {
636 mlir::Value init =
visit(elt);
638 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
646 const mlir::Type llvmTy = converter->convertType(
attr.getType());
647 const mlir::Location loc = parentOp->getLoc();
650 for (
const mlir::Attribute elementAttr :
attr.getElts()) {
651 mlir::Attribute mlirAttr;
652 if (
auto intAttr = mlir::dyn_cast<cir::IntAttr>(elementAttr)) {
653 mlirAttr = rewriter.getIntegerAttr(
654 converter->convertType(intAttr.getType()), intAttr.getValue());
655 }
else if (
auto floatAttr = mlir::dyn_cast<cir::FPAttr>(elementAttr)) {
656 mlirAttr = rewriter.getFloatAttr(
657 converter->convertType(floatAttr.getType()), floatAttr.getValue());
660 "vector constant with an element that is neither an int nor a float");
662 mlirValues.push_back(mlirAttr);
665 return mlir::LLVM::ConstantOp::create(
666 rewriter, loc, llvmTy,
667 mlir::DenseElementsAttr::get(mlir::cast<mlir::ShapedType>(llvmTy),
673 auto moduleOp = parentOp->getParentOfType<mlir::ModuleOp>();
674 mlir::DataLayout dataLayout(moduleOp);
675 mlir::Type sourceType;
677 llvm::StringRef symName;
678 mlir::Operation *sourceSymbol =
679 mlir::SymbolTable::lookupSymbolIn(moduleOp, globalAttr.getSymbol());
680 if (
auto llvmSymbol = dyn_cast<mlir::LLVM::GlobalOp>(sourceSymbol)) {
681 sourceType = llvmSymbol.getType();
682 symName = llvmSymbol.getSymName();
683 }
else if (
auto cirSymbol = dyn_cast<cir::GlobalOp>(sourceSymbol)) {
686 symName = cirSymbol.getSymName();
687 }
else if (
auto llvmFun = dyn_cast<mlir::LLVM::LLVMFuncOp>(sourceSymbol)) {
688 sourceType = llvmFun.getFunctionType();
689 symName = llvmFun.getSymName();
690 }
else if (
auto fun = dyn_cast<cir::FuncOp>(sourceSymbol)) {
691 sourceType = converter->convertType(fun.getFunctionType());
692 symName = fun.getSymName();
693 }
else if (
auto alias = dyn_cast<mlir::LLVM::AliasOp>(sourceSymbol)) {
694 sourceType = alias.getType();
695 symName = alias.getSymName();
697 llvm_unreachable(
"Unexpected GlobalOp type");
700 mlir::Location loc = parentOp->getLoc();
701 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
702 rewriter, loc, mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
705 if (globalAttr.getIndices()) {
708 if (mlir::isa<mlir::LLVM::LLVMArrayType, mlir::LLVM::LLVMStructType>(
710 indices.push_back(0);
712 for (mlir::Attribute idx : globalAttr.getIndices()) {
713 auto intAttr = mlir::cast<mlir::IntegerAttr>(idx);
714 indices.push_back(intAttr.getValue().getSExtValue());
716 mlir::Type resTy = addrOp.getType();
717 mlir::Type eltTy = converter->convertType(sourceType);
719 mlir::LLVM::GEPOp::create(rewriter, loc, resTy, eltTy, addrOp, indices,
720 mlir::LLVM::GEPNoWrapFlags::none);
727 if (
auto intTy = mlir::dyn_cast<cir::IntType>(globalAttr.getType())) {
728 mlir::Type llvmDstTy = converter->convertType(globalAttr.getType());
729 return mlir::LLVM::PtrToIntOp::create(rewriter, parentOp->getLoc(),
733 if (
auto ptrTy = mlir::dyn_cast<cir::PointerType>(globalAttr.getType())) {
734 mlir::Type llvmEltTy =
737 if (llvmEltTy == sourceType)
740 mlir::Type llvmDstTy = converter->convertType(globalAttr.getType());
741 return mlir::LLVM::BitcastOp::create(rewriter, parentOp->getLoc(),
745 llvm_unreachable(
"Expecting pointer or integer type for GlobalViewAttr");
750 mlir::Type llvmTy = converter->convertType(typeInfoAttr.getType());
751 mlir::Location loc = parentOp->getLoc();
752 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
754 for (
auto [idx, elt] : llvm::enumerate(typeInfoAttr.getData())) {
755 mlir::Value init =
visit(elt);
757 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
765 mlir::Location loc = parentOp->getLoc();
766 return mlir::LLVM::UndefOp::create(
767 rewriter, loc, converter->convertType(undefAttr.getType()));
772 mlir::Type llvmTy = converter->convertType(vtableArr.getType());
773 mlir::Location loc = parentOp->getLoc();
774 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
776 for (
auto [idx, elt] : llvm::enumerate(vtableArr.getData())) {
777 mlir::Value init =
visit(elt);
779 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
787 mlir::Location loc = parentOp->getLoc();
788 return mlir::LLVM::ZeroOp::create(rewriter, loc,
789 converter->convertType(
attr.getType()));
797 mlir::ConversionPatternRewriter &rewriter)
798 : llvmType(type), rewriter(rewriter) {}
801 return llvm::TypeSwitch<mlir::Attribute, mlir::Attribute>(
attr)
802 .Case<cir::IntAttr, cir::FPAttr, cir::BoolAttr>(
804 .
Default([&](
auto attrT) {
return mlir::Attribute(); });
808 return rewriter.getIntegerAttr(llvmType,
attr.getValue());
812 return rewriter.getFloatAttr(llvmType,
attr.getValue());
816 return rewriter.getBoolAttr(
attr.getValue());
821 mlir::ConversionPatternRewriter &rewriter;
829 :
public mlir::PassWrapper<ConvertCIRToLLVMPass,
830 mlir::OperationPass<mlir::ModuleOp>> {
832 registry.insert<mlir::BuiltinDialect, mlir::DLTIDialect,
833 mlir::LLVM::LLVMDialect, mlir::func::FuncDialect>();
842 return "Convert the prepared CIR dialect module to LLVM dialect";
845 StringRef
getArgument()
const override {
return "cir-flat-to-llvm"; }
848mlir::LogicalResult CIRToLLVMACosOpLowering::matchAndRewrite(
849 cir::ACosOp op, OpAdaptor adaptor,
850 mlir::ConversionPatternRewriter &rewriter)
const {
851 mlir::Type resTy = typeConverter->convertType(op.getType());
852 rewriter.replaceOpWithNewOp<mlir::LLVM::ACosOp>(op, resTy,
853 adaptor.getOperands()[0]);
854 return mlir::success();
857mlir::LogicalResult CIRToLLVMASinOpLowering::matchAndRewrite(
858 cir::ASinOp op, OpAdaptor adaptor,
859 mlir::ConversionPatternRewriter &rewriter)
const {
860 mlir::Type resTy = typeConverter->convertType(op.getType());
861 rewriter.replaceOpWithNewOp<mlir::LLVM::ASinOp>(op, resTy, adaptor.getSrc());
862 return mlir::success();
865mlir::LogicalResult CIRToLLVMIsFPClassOpLowering::matchAndRewrite(
866 cir::IsFPClassOp op, OpAdaptor adaptor,
867 mlir::ConversionPatternRewriter &rewriter)
const {
868 mlir::Value src = adaptor.getSrc();
869 cir::FPClassTest flags = adaptor.getFlags();
870 mlir::IntegerType retTy = rewriter.getI1Type();
872 rewriter.replaceOpWithNewOp<mlir::LLVM::IsFPClass>(
873 op, retTy, src,
static_cast<uint32_t>(flags));
874 return mlir::success();
877mlir::LogicalResult CIRToLLVMSignBitOpLowering::matchAndRewrite(
878 cir::SignBitOp op, OpAdaptor adaptor,
879 mlir::ConversionPatternRewriter &rewriter)
const {
882 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
883 int width = layout.getTypeSizeInBits(op.getInput().getType());
884 if (
auto longDoubleType =
885 mlir::dyn_cast<cir::LongDoubleType>(op.getInput().getType())) {
886 if (mlir::isa<cir::FP80Type>(longDoubleType.getUnderlying())) {
894 mlir::Type intTy = mlir::IntegerType::get(rewriter.getContext(), width);
895 auto bitcast = mlir::LLVM::BitcastOp::create(rewriter, op->getLoc(), intTy,
898 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op->getLoc(), intTy, 0);
899 auto cmpResult = mlir::LLVM::ICmpOp::create(rewriter, op.getLoc(),
900 mlir::LLVM::ICmpPredicate::slt,
901 bitcast.getResult(), zero);
902 rewriter.replaceOp(op, cmpResult);
903 return mlir::success();
906mlir::LogicalResult CIRToLLVMAssumeOpLowering::matchAndRewrite(
907 cir::AssumeOp op, OpAdaptor adaptor,
908 mlir::ConversionPatternRewriter &rewriter)
const {
909 auto cond = adaptor.getPredicate();
910 rewriter.replaceOpWithNewOp<mlir::LLVM::AssumeOp>(op, cond);
911 return mlir::success();
914mlir::LogicalResult CIRToLLVMAssumeAlignedOpLowering::matchAndRewrite(
915 cir::AssumeAlignedOp op, OpAdaptor adaptor,
916 mlir::ConversionPatternRewriter &rewriter)
const {
917 SmallVector<mlir::Value, 3> opBundleArgs{adaptor.getPointer()};
919 auto alignment = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
920 adaptor.getAlignmentAttr());
921 opBundleArgs.push_back(alignment);
923 if (mlir::Value offset = adaptor.getOffset())
924 opBundleArgs.push_back(offset);
926 auto cond = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
927 rewriter.getI1Type(), 1);
928 mlir::LLVM::AssumeOp::create(rewriter, op.getLoc(), cond,
"align",
933 rewriter.replaceOp(op, adaptor.getPointer());
934 return mlir::success();
937mlir::LogicalResult CIRToLLVMAssumeSepStorageOpLowering::matchAndRewrite(
938 cir::AssumeSepStorageOp op, OpAdaptor adaptor,
939 mlir::ConversionPatternRewriter &rewriter)
const {
940 auto cond = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
941 rewriter.getI1Type(), 1);
942 rewriter.replaceOpWithNewOp<mlir::LLVM::AssumeOp>(
943 op, cond, mlir::LLVM::AssumeSeparateStorageTag{}, adaptor.getPtr1(),
945 return mlir::success();
948static mlir::LLVM::AtomicOrdering
951 return mlir::LLVM::AtomicOrdering::not_atomic;
953 case cir::MemOrder::Relaxed:
954 return mlir::LLVM::AtomicOrdering::monotonic;
955 case cir::MemOrder::Consume:
956 case cir::MemOrder::Acquire:
957 return mlir::LLVM::AtomicOrdering::acquire;
958 case cir::MemOrder::Release:
959 return mlir::LLVM::AtomicOrdering::release;
960 case cir::MemOrder::AcquireRelease:
961 return mlir::LLVM::AtomicOrdering::acq_rel;
962 case cir::MemOrder::SequentiallyConsistent:
963 return mlir::LLVM::AtomicOrdering::seq_cst;
965 llvm_unreachable(
"unknown memory order");
969 return syncScope == cir::SyncScopeKind::SingleThread ?
"singlethread" :
"";
972static std::optional<llvm::StringRef>
974 if (syncScope.has_value())
979mlir::LogicalResult CIRToLLVMAtomicCmpXchgOpLowering::matchAndRewrite(
980 cir::AtomicCmpXchgOp op, OpAdaptor adaptor,
981 mlir::ConversionPatternRewriter &rewriter)
const {
982 mlir::Value expected = adaptor.getExpected();
983 mlir::Value desired = adaptor.getDesired();
985 auto cmpxchg = mlir::LLVM::AtomicCmpXchgOp::create(
986 rewriter, op.getLoc(), adaptor.getPtr(), expected, desired,
991 cmpxchg.setAlignment(adaptor.getAlignment());
992 cmpxchg.setWeak(adaptor.getWeak());
993 cmpxchg.setVolatile_(adaptor.getIsVolatile());
996 auto old = mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(),
997 cmpxchg.getResult(), 0);
998 auto cmp = mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(),
999 cmpxchg.getResult(), 1);
1001 rewriter.replaceOp(op, {old, cmp});
1002 return mlir::success();
1005mlir::LogicalResult CIRToLLVMAtomicXchgOpLowering::matchAndRewrite(
1006 cir::AtomicXchgOp op, OpAdaptor adaptor,
1007 mlir::ConversionPatternRewriter &rewriter)
const {
1009 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(adaptor.getMemOrder());
1011 rewriter.replaceOpWithNewOp<mlir::LLVM::AtomicRMWOp>(
1012 op, mlir::LLVM::AtomicBinOp::xchg, adaptor.getPtr(), adaptor.getVal(),
1013 llvmOrder, llvmSyncScope);
1014 return mlir::success();
1017mlir::LogicalResult CIRToLLVMAtomicTestAndSetOpLowering::matchAndRewrite(
1018 cir::AtomicTestAndSetOp op, OpAdaptor adaptor,
1019 mlir::ConversionPatternRewriter &rewriter)
const {
1022 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
1024 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1025 rewriter.getI8Type(), 1);
1026 auto rmw = mlir::LLVM::AtomicRMWOp::create(
1027 rewriter, op.getLoc(), mlir::LLVM::AtomicBinOp::xchg, adaptor.getPtr(),
1028 one, llvmOrder, llvm::StringRef(),
1029 adaptor.getAlignment().value_or(0), op.getIsVolatile());
1031 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1032 rewriter.getI8Type(), 0);
1033 auto cmp = mlir::LLVM::ICmpOp::create(
1034 rewriter, op.getLoc(), mlir::LLVM::ICmpPredicate::ne, rmw, zero);
1036 rewriter.replaceOp(op, cmp);
1037 return mlir::success();
1040mlir::LogicalResult CIRToLLVMAtomicClearOpLowering::matchAndRewrite(
1041 cir::AtomicClearOp op, OpAdaptor adaptor,
1042 mlir::ConversionPatternRewriter &rewriter)
const {
1045 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
1046 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1047 rewriter.getI8Type(), 0);
1048 auto store = mlir::LLVM::StoreOp::create(
1049 rewriter, op.getLoc(), zero, adaptor.getPtr(),
1050 adaptor.getAlignment().value_or(0), op.getIsVolatile(),
1051 false,
false, llvmOrder);
1053 rewriter.replaceOp(op, store);
1054 return mlir::success();
1057mlir::LogicalResult CIRToLLVMAtomicFenceOpLowering::matchAndRewrite(
1058 cir::AtomicFenceOp op, OpAdaptor adaptor,
1059 mlir::ConversionPatternRewriter &rewriter)
const {
1060 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(adaptor.getOrdering());
1062 auto fence = mlir::LLVM::FenceOp::create(rewriter, op.getLoc(), llvmOrder);
1065 rewriter.replaceOp(op, fence);
1067 return mlir::success();
1070static mlir::LLVM::AtomicBinOp
1073 case cir::AtomicFetchKind::Add:
1074 return isInt ? mlir::LLVM::AtomicBinOp::add : mlir::LLVM::AtomicBinOp::fadd;
1075 case cir::AtomicFetchKind::Sub:
1076 return isInt ? mlir::LLVM::AtomicBinOp::sub : mlir::LLVM::AtomicBinOp::fsub;
1077 case cir::AtomicFetchKind::And:
1078 return mlir::LLVM::AtomicBinOp::_and;
1079 case cir::AtomicFetchKind::Xor:
1080 return mlir::LLVM::AtomicBinOp::_xor;
1081 case cir::AtomicFetchKind::Or:
1082 return mlir::LLVM::AtomicBinOp::_or;
1083 case cir::AtomicFetchKind::Nand:
1084 return mlir::LLVM::AtomicBinOp::nand;
1085 case cir::AtomicFetchKind::Max: {
1087 return mlir::LLVM::AtomicBinOp::fmax;
1088 return isSignedInt ? mlir::LLVM::AtomicBinOp::max
1089 : mlir::LLVM::AtomicBinOp::umax;
1091 case cir::AtomicFetchKind::Min: {
1093 return mlir::LLVM::AtomicBinOp::fmin;
1094 return isSignedInt ? mlir::LLVM::AtomicBinOp::min
1095 : mlir::LLVM::AtomicBinOp::umin;
1097 case cir::AtomicFetchKind::UIncWrap:
1098 return mlir::LLVM::AtomicBinOp::uinc_wrap;
1099 case cir::AtomicFetchKind::UDecWrap:
1100 return mlir::LLVM::AtomicBinOp::udec_wrap;
1102 llvm_unreachable(
"Unknown atomic fetch opcode");
1108 case cir::AtomicFetchKind::Add:
1109 return isInt ? mlir::LLVM::AddOp::getOperationName()
1110 : mlir::LLVM::FAddOp::getOperationName();
1111 case cir::AtomicFetchKind::Sub:
1112 return isInt ? mlir::LLVM::SubOp::getOperationName()
1113 : mlir::LLVM::FSubOp::getOperationName();
1114 case cir::AtomicFetchKind::And:
1115 return mlir::LLVM::AndOp::getOperationName();
1116 case cir::AtomicFetchKind::Xor:
1117 return mlir::LLVM::XOrOp::getOperationName();
1118 case cir::AtomicFetchKind::Or:
1119 return mlir::LLVM::OrOp::getOperationName();
1120 case cir::AtomicFetchKind::Nand:
1122 return mlir::LLVM::AndOp::getOperationName();
1123 case cir::AtomicFetchKind::Max:
1124 case cir::AtomicFetchKind::Min:
1125 llvm_unreachable(
"handled in buildMinMaxPostOp");
1126 case cir::AtomicFetchKind::UIncWrap:
1127 case cir::AtomicFetchKind::UDecWrap:
1128 llvm_unreachable(
"uinc_wrap and udec_wrap are always fetch_first");
1130 llvm_unreachable(
"Unknown atomic fetch opcode");
1133mlir::Value CIRToLLVMAtomicFetchOpLowering::buildPostOp(
1134 cir::AtomicFetchOp op, OpAdaptor adaptor,
1135 mlir::ConversionPatternRewriter &rewriter, mlir::Value rmwVal,
1140 .create(op.getLoc(),
1141 rewriter.getStringAttr(
1143 atomicOperands, atomicResTys, {})
1147mlir::Value CIRToLLVMAtomicFetchOpLowering::buildMinMaxPostOp(
1148 cir::AtomicFetchOp op, OpAdaptor adaptor,
1149 mlir::ConversionPatternRewriter &rewriter, mlir::Value rmwVal,
bool isInt,
1150 bool isSigned)
const {
1151 mlir::Location loc = op.getLoc();
1154 if (op.getBinop() == cir::AtomicFetchKind::Max)
1155 return mlir::LLVM::MaxNumOp::create(rewriter, loc, rmwVal,
1157 return mlir::LLVM::MinNumOp::create(rewriter, loc, rmwVal,
1161 mlir::LLVM::ICmpPredicate pred;
1162 if (op.getBinop() == cir::AtomicFetchKind::Max) {
1163 pred = isSigned ? mlir::LLVM::ICmpPredicate::sgt
1164 : mlir::LLVM::ICmpPredicate::ugt;
1166 pred = isSigned ? mlir::LLVM::ICmpPredicate::slt
1167 : mlir::LLVM::ICmpPredicate::ult;
1169 mlir::Value cmp = mlir::LLVM::ICmpOp::create(
1171 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(), pred), rmwVal,
1173 return mlir::LLVM::SelectOp::create(rewriter, loc, cmp, rmwVal,
1177mlir::LogicalResult CIRToLLVMAtomicFetchOpLowering::matchAndRewrite(
1178 cir::AtomicFetchOp op, OpAdaptor adaptor,
1179 mlir::ConversionPatternRewriter &rewriter)
const {
1181 bool isSignedInt =
false;
1182 if (
auto intTy = mlir::dyn_cast<cir::IntType>(op.getVal().getType())) {
1184 isSignedInt = intTy.isSigned();
1185 }
else if (mlir::isa<cir::SingleType, cir::DoubleType>(
1186 op.getVal().getType())) {
1189 return op.emitError() <<
"Unsupported type: " << op.getVal().getType();
1192 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(op.getMemOrder());
1194 mlir::LLVM::AtomicBinOp llvmBinOp =
1196 auto rmwVal = mlir::LLVM::AtomicRMWOp::create(
1197 rewriter, op.getLoc(), llvmBinOp, adaptor.getPtr(), adaptor.getVal(),
1198 llvmOrder, llvmSyncScope);
1200 mlir::Value result = rmwVal.getResult();
1201 if (!op.getFetchFirst()) {
1202 if (op.getBinop() == cir::AtomicFetchKind::Max ||
1203 op.getBinop() == cir::AtomicFetchKind::Min)
1204 result = buildMinMaxPostOp(op, adaptor, rewriter, rmwVal.getRes(), isInt,
1207 result = buildPostOp(op, adaptor, rewriter, rmwVal.getRes(), isInt);
1210 if (op.getBinop() == cir::AtomicFetchKind::Nand) {
1211 auto negOne = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1212 result.getType(), -1);
1213 result = mlir::LLVM::XOrOp::create(rewriter, op.getLoc(), result, negOne);
1217 rewriter.replaceOp(op, result);
1218 return mlir::success();
1221mlir::LogicalResult CIRToLLVMBitClrsbOpLowering::matchAndRewrite(
1222 cir::BitClrsbOp op, OpAdaptor adaptor,
1223 mlir::ConversionPatternRewriter &rewriter)
const {
1224 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
1225 adaptor.getInput().getType(), 0);
1226 auto isNeg = mlir::LLVM::ICmpOp::create(
1227 rewriter, op.getLoc(),
1228 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(),
1229 mlir::LLVM::ICmpPredicate::slt),
1230 adaptor.getInput(), zero);
1232 auto negOne = mlir::LLVM::ConstantOp::create(
1233 rewriter, op.getLoc(), adaptor.getInput().getType(), -1);
1234 auto flipped = mlir::LLVM::XOrOp::create(rewriter, op.getLoc(),
1235 adaptor.getInput(), negOne);
1237 auto select = mlir::LLVM::SelectOp::create(rewriter, op.getLoc(), isNeg,
1238 flipped, adaptor.getInput());
1240 auto resTy = getTypeConverter()->convertType(op.getType());
1241 auto clz = mlir::LLVM::CountLeadingZerosOp::create(
1242 rewriter, op.getLoc(), resTy,
select,
false);
1244 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1245 auto res = mlir::LLVM::SubOp::create(rewriter, op.getLoc(),
clz, one,
1246 mlir::LLVM::IntegerOverflowFlags::nuw);
1247 rewriter.replaceOp(op, res);
1249 return mlir::LogicalResult::success();
1252mlir::LogicalResult CIRToLLVMBitClzOpLowering::matchAndRewrite(
1253 cir::BitClzOp op, OpAdaptor adaptor,
1254 mlir::ConversionPatternRewriter &rewriter)
const {
1255 auto resTy = getTypeConverter()->convertType(op.getType());
1256 auto llvmOp = mlir::LLVM::CountLeadingZerosOp::create(
1257 rewriter, op.getLoc(), resTy, adaptor.getInput(), op.getPoisonZero());
1258 rewriter.replaceOp(op, llvmOp);
1259 return mlir::LogicalResult::success();
1262mlir::LogicalResult CIRToLLVMBitCtzOpLowering::matchAndRewrite(
1263 cir::BitCtzOp op, OpAdaptor adaptor,
1264 mlir::ConversionPatternRewriter &rewriter)
const {
1265 auto resTy = getTypeConverter()->convertType(op.getType());
1266 auto llvmOp = mlir::LLVM::CountTrailingZerosOp::create(
1267 rewriter, op.getLoc(), resTy, adaptor.getInput(), op.getPoisonZero());
1268 rewriter.replaceOp(op, llvmOp);
1269 return mlir::LogicalResult::success();
1272mlir::LogicalResult CIRToLLVMBitFfsOpLowering::matchAndRewrite(
1273 cir::BitFfsOp op, OpAdaptor adaptor,
1274 mlir::ConversionPatternRewriter &rewriter)
const {
1275 auto resTy = getTypeConverter()->convertType(op.getType());
1276 auto ctz = mlir::LLVM::CountTrailingZerosOp::create(rewriter, op.getLoc(),
1277 resTy, adaptor.getInput(),
1280 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1281 auto ctzAddOne = mlir::LLVM::AddOp::create(rewriter, op.getLoc(),
ctz, one);
1283 auto zeroInputTy = mlir::LLVM::ConstantOp::create(
1284 rewriter, op.getLoc(), adaptor.getInput().getType(), 0);
1285 auto isZero = mlir::LLVM::ICmpOp::create(
1286 rewriter, op.getLoc(),
1287 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(),
1288 mlir::LLVM::ICmpPredicate::eq),
1289 adaptor.getInput(), zeroInputTy);
1291 auto zero = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 0);
1292 auto res = mlir::LLVM::SelectOp::create(rewriter, op.getLoc(), isZero, zero,
1294 rewriter.replaceOp(op, res);
1296 return mlir::LogicalResult::success();
1299mlir::LogicalResult CIRToLLVMBitParityOpLowering::matchAndRewrite(
1300 cir::BitParityOp op, OpAdaptor adaptor,
1301 mlir::ConversionPatternRewriter &rewriter)
const {
1302 auto resTy = getTypeConverter()->convertType(op.getType());
1303 auto popcnt = mlir::LLVM::CtPopOp::create(rewriter, op.getLoc(), resTy,
1304 adaptor.getInput());
1306 auto one = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), resTy, 1);
1308 mlir::LLVM::AndOp::create(rewriter, op.getLoc(), popcnt, one);
1309 rewriter.replaceOp(op, popcntMod2);
1311 return mlir::LogicalResult::success();
1314mlir::LogicalResult CIRToLLVMBitPopcountOpLowering::matchAndRewrite(
1315 cir::BitPopcountOp op, OpAdaptor adaptor,
1316 mlir::ConversionPatternRewriter &rewriter)
const {
1317 auto resTy = getTypeConverter()->convertType(op.getType());
1318 auto llvmOp = mlir::LLVM::CtPopOp::create(rewriter, op.getLoc(), resTy,
1319 adaptor.getInput());
1320 rewriter.replaceOp(op, llvmOp);
1321 return mlir::LogicalResult::success();
1324mlir::LogicalResult CIRToLLVMBitReverseOpLowering::matchAndRewrite(
1325 cir::BitReverseOp op, OpAdaptor adaptor,
1326 mlir::ConversionPatternRewriter &rewriter)
const {
1327 rewriter.replaceOpWithNewOp<mlir::LLVM::BitReverseOp>(op, adaptor.getInput());
1328 return mlir::success();
1331mlir::LogicalResult CIRToLLVMBrCondOpLowering::matchAndRewrite(
1332 cir::BrCondOp brOp, OpAdaptor adaptor,
1333 mlir::ConversionPatternRewriter &rewriter)
const {
1338 mlir::Value i1Condition = adaptor.getCond();
1340 rewriter.replaceOpWithNewOp<mlir::LLVM::CondBrOp>(
1341 brOp, i1Condition, brOp.getDestTrue(), adaptor.getDestOperandsTrue(),
1342 brOp.getDestFalse(), adaptor.getDestOperandsFalse());
1344 return mlir::success();
1347mlir::LogicalResult CIRToLLVMByteSwapOpLowering::matchAndRewrite(
1348 cir::ByteSwapOp op, OpAdaptor adaptor,
1349 mlir::ConversionPatternRewriter &rewriter)
const {
1350 rewriter.replaceOpWithNewOp<mlir::LLVM::ByteSwapOp>(op, adaptor.getInput());
1351 return mlir::LogicalResult::success();
1354mlir::Type CIRToLLVMCastOpLowering::convertTy(mlir::Type ty)
const {
1355 return getTypeConverter()->convertType(ty);
1358mlir::LogicalResult CIRToLLVMCastOpLowering::matchAndRewrite(
1359 cir::CastOp castOp, OpAdaptor adaptor,
1360 mlir::ConversionPatternRewriter &rewriter)
const {
1365 switch (castOp.getKind()) {
1366 case cir::CastKind::array_to_ptrdecay: {
1367 const auto ptrTy = mlir::cast<cir::PointerType>(castOp.getType());
1368 mlir::Value sourceValue = adaptor.getSrc();
1369 mlir::Type targetType = convertTy(ptrTy);
1371 ptrTy.getPointee());
1372 llvm::SmallVector<mlir::LLVM::GEPArg> offset{0};
1373 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1374 castOp, targetType, elementTy, sourceValue, offset);
1377 case cir::CastKind::int_to_bool: {
1378 mlir::Value llvmSrcVal = adaptor.getSrc();
1379 mlir::Value zeroInt = mlir::LLVM::ConstantOp::create(
1380 rewriter, castOp.getLoc(), llvmSrcVal.getType(), 0);
1381 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
1382 castOp, mlir::LLVM::ICmpPredicate::ne, llvmSrcVal, zeroInt);
1385 case cir::CastKind::integral: {
1386 mlir::Type srcType = castOp.getSrc().getType();
1387 mlir::Type dstType = castOp.getType();
1388 mlir::Value llvmSrcVal = adaptor.getSrc();
1389 mlir::Type llvmDstType = getTypeConverter()->convertType(dstType);
1390 cir::IntType srcIntType =
1391 mlir::cast<cir::IntType>(elementTypeIfVector(srcType));
1392 cir::IntType dstIntType =
1393 mlir::cast<cir::IntType>(elementTypeIfVector(dstType));
1394 rewriter.replaceOp(castOp,
getLLVMIntCast(rewriter, llvmSrcVal, llvmDstType,
1395 srcIntType.isUnsigned(),
1396 srcIntType.getWidth(),
1397 dstIntType.getWidth()));
1400 case cir::CastKind::floating: {
1401 mlir::Value llvmSrcVal = adaptor.getSrc();
1402 mlir::Type llvmDstTy = getTypeConverter()->convertType(castOp.getType());
1404 mlir::Type srcTy = elementTypeIfVector(castOp.getSrc().getType());
1405 mlir::Type dstTy = elementTypeIfVector(castOp.getType());
1407 if (!mlir::isa<cir::FPTypeInterface>(dstTy) ||
1408 !mlir::isa<cir::FPTypeInterface>(srcTy))
1409 return castOp.emitError() <<
"NYI cast from " << srcTy <<
" to " << dstTy;
1411 auto getFloatWidth = [](mlir::Type ty) ->
unsigned {
1412 return mlir::cast<cir::FPTypeInterface>(ty).getWidth();
1415 if (getFloatWidth(srcTy) > getFloatWidth(dstTy))
1416 rewriter.replaceOpWithNewOp<mlir::LLVM::FPTruncOp>(castOp, llvmDstTy,
1419 rewriter.replaceOpWithNewOp<mlir::LLVM::FPExtOp>(castOp, llvmDstTy,
1421 return mlir::success();
1423 case cir::CastKind::int_to_ptr: {
1424 auto dstTy = mlir::cast<cir::PointerType>(castOp.getType());
1425 mlir::Value llvmSrcVal = adaptor.getSrc();
1426 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1427 rewriter.replaceOpWithNewOp<mlir::LLVM::IntToPtrOp>(castOp, llvmDstTy,
1429 return mlir::success();
1431 case cir::CastKind::ptr_to_int: {
1432 auto dstTy = mlir::cast<cir::IntType>(castOp.getType());
1433 mlir::Value llvmSrcVal = adaptor.getSrc();
1434 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1435 rewriter.replaceOpWithNewOp<mlir::LLVM::PtrToIntOp>(castOp, llvmDstTy,
1437 return mlir::success();
1439 case cir::CastKind::float_to_bool: {
1440 mlir::Value llvmSrcVal = adaptor.getSrc();
1441 auto kind = mlir::LLVM::FCmpPredicate::une;
1444 auto zeroFloat = mlir::LLVM::ConstantOp::create(
1445 rewriter, castOp.getLoc(), llvmSrcVal.getType(),
1446 mlir::FloatAttr::get(llvmSrcVal.getType(), 0.0));
1449 rewriter.replaceOpWithNewOp<mlir::LLVM::FCmpOp>(castOp,
kind, llvmSrcVal,
1452 return mlir::success();
1454 case cir::CastKind::bool_to_int: {
1455 auto dstTy = mlir::cast<cir::IntType>(castOp.getType());
1456 mlir::Value llvmSrcVal = adaptor.getSrc();
1457 auto llvmSrcTy = mlir::cast<mlir::IntegerType>(llvmSrcVal.getType());
1459 mlir::cast<mlir::IntegerType>(getTypeConverter()->convertType(dstTy));
1461 if (llvmSrcTy.getWidth() == llvmDstTy.getWidth())
1462 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(castOp, llvmDstTy,
1465 rewriter.replaceOpWithNewOp<mlir::LLVM::ZExtOp>(castOp, llvmDstTy,
1467 return mlir::success();
1469 case cir::CastKind::bool_to_float: {
1470 mlir::Type dstTy = castOp.getType();
1471 mlir::Value llvmSrcVal = adaptor.getSrc();
1472 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1473 rewriter.replaceOpWithNewOp<mlir::LLVM::UIToFPOp>(castOp, llvmDstTy,
1475 return mlir::success();
1477 case cir::CastKind::int_to_float: {
1478 mlir::Type dstTy = castOp.getType();
1479 mlir::Value llvmSrcVal = adaptor.getSrc();
1480 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1481 if (mlir::cast<cir::IntType>(elementTypeIfVector(castOp.getSrc().getType()))
1483 rewriter.replaceOpWithNewOp<mlir::LLVM::SIToFPOp>(castOp, llvmDstTy,
1486 rewriter.replaceOpWithNewOp<mlir::LLVM::UIToFPOp>(castOp, llvmDstTy,
1488 return mlir::success();
1490 case cir::CastKind::float_to_int: {
1491 mlir::Type dstTy = castOp.getType();
1492 mlir::Value llvmSrcVal = adaptor.getSrc();
1493 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1494 if (mlir::cast<cir::IntType>(elementTypeIfVector(castOp.getType()))
1496 rewriter.replaceOpWithNewOp<mlir::LLVM::FPToSIOp>(castOp, llvmDstTy,
1499 rewriter.replaceOpWithNewOp<mlir::LLVM::FPToUIOp>(castOp, llvmDstTy,
1501 return mlir::success();
1503 case cir::CastKind::bitcast: {
1504 mlir::Type dstTy = castOp.getType();
1505 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1510 mlir::Value llvmSrcVal = adaptor.getSrc();
1511 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(castOp, llvmDstTy,
1513 return mlir::success();
1515 case cir::CastKind::ptr_to_bool: {
1516 mlir::Value llvmSrcVal = adaptor.getSrc();
1517 mlir::Value zeroPtr = mlir::LLVM::ZeroOp::create(rewriter, castOp.getLoc(),
1518 llvmSrcVal.getType());
1519 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
1520 castOp, mlir::LLVM::ICmpPredicate::ne, llvmSrcVal, zeroPtr);
1523 case cir::CastKind::address_space: {
1524 mlir::Type dstTy = castOp.getType();
1525 mlir::Value llvmSrcVal = adaptor.getSrc();
1526 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1527 rewriter.replaceOpWithNewOp<mlir::LLVM::AddrSpaceCastOp>(castOp, llvmDstTy,
1531 case cir::CastKind::member_ptr_to_bool:
1536 return castOp.emitError(
"Unhandled cast kind: ")
1537 << castOp.getKindAttrName();
1541 return mlir::success();
1545 mlir::ModuleOp mod, mlir::Value index,
1546 mlir::Type baseTy, cir::IntType strideTy) {
1547 mlir::Operation *indexOp = index.getDefiningOp();
1551 auto indexType = mlir::cast<mlir::IntegerType>(index.getType());
1552 mlir::DataLayout llvmLayout(mod);
1553 std::optional<uint64_t> layoutWidth = llvmLayout.getTypeIndexBitwidth(baseTy);
1556 if (!layoutWidth || *layoutWidth == indexType.getWidth())
1562 auto sub = dyn_cast<mlir::LLVM::SubOp>(indexOp);
1563 bool rewriteSub =
false;
1566 dyn_cast<mlir::LLVM::ConstantOp>(sub.getLhs().getDefiningOp())) {
1567 auto lhsConstInt = mlir::dyn_cast<mlir::IntegerAttr>(lhsConst.getValue());
1568 if (lhsConstInt && lhsConstInt.getValue() == 0) {
1569 index = sub.getRhs();
1575 auto llvmDstType = rewriter.getIntegerType(*layoutWidth);
1576 bool isUnsigned = strideTy && strideTy.isUnsigned();
1578 indexType.getWidth(), *layoutWidth);
1581 index = mlir::LLVM::SubOp::create(
1582 rewriter, index.getLoc(),
1583 mlir::LLVM::ConstantOp::create(rewriter, index.getLoc(),
1584 index.getType(), 0),
1587 rewriter.eraseOp(sub);
1593mlir::LogicalResult CIRToLLVMPtrStrideOpLowering::matchAndRewrite(
1594 cir::PtrStrideOp ptrStrideOp, OpAdaptor adaptor,
1595 mlir::ConversionPatternRewriter &rewriter)
const {
1597 const mlir::TypeConverter *tc = getTypeConverter();
1598 const mlir::Type resultTy = tc->convertType(ptrStrideOp.getType());
1600 mlir::Type elementTy =
1605 if (mlir::isa<mlir::LLVM::LLVMVoidType>(elementTy) ||
1606 mlir::isa<mlir::LLVM::LLVMFunctionType>(elementTy))
1607 elementTy = mlir::IntegerType::get(elementTy.getContext(), 8,
1608 mlir::IntegerType::Signless);
1610 mlir::Value index = adaptor.getStride();
1612 rewriter, ptrStrideOp->getParentOfType<mlir::ModuleOp>(), index,
1613 adaptor.getBase().getType(),
1614 dyn_cast<cir::IntType>(ptrStrideOp.getOperand(1).getType()));
1616 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1617 ptrStrideOp, resultTy, elementTy, adaptor.getBase(), index);
1618 return mlir::success();
1621mlir::LogicalResult CIRToLLVMGetElementOpLowering::matchAndRewrite(
1622 cir::GetElementOp op, OpAdaptor adaptor,
1623 mlir::ConversionPatternRewriter &rewriter)
const {
1625 mlir::dyn_cast<cir::ArrayType>(op.getBaseType().getPointee())) {
1626 const mlir::TypeConverter *converter = getTypeConverter();
1627 const mlir::Type llArrayTy = converter->convertType(arrayTy);
1628 const mlir::Type llResultTy = converter->convertType(op.getType());
1629 mlir::Type elementTy =
1634 if (mlir::isa<mlir::LLVM::LLVMVoidType>(elementTy) ||
1635 mlir::isa<mlir::LLVM::LLVMFunctionType>(elementTy))
1636 elementTy = rewriter.getIntegerType(8);
1638 mlir::Value index = adaptor.getIndex();
1641 adaptor.getBase().getType(),
1642 dyn_cast<cir::IntType>(op.getOperand(1).getType()));
1647 std::array<mlir::LLVM::GEPArg, 2> offset{0, index};
1648 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, llResultTy, llArrayTy,
1649 adaptor.getBase(), offset);
1650 return mlir::success();
1653 op.emitError() <<
"NYI: GetElementOp lowering to LLVM for non-array";
1654 return mlir::failure();
1657mlir::LogicalResult CIRToLLVMBaseClassAddrOpLowering::matchAndRewrite(
1658 cir::BaseClassAddrOp baseClassOp, OpAdaptor adaptor,
1659 mlir::ConversionPatternRewriter &rewriter)
const {
1660 const mlir::Type resultType =
1661 getTypeConverter()->convertType(baseClassOp.getType());
1662 mlir::Value derivedAddr = adaptor.getDerivedAddr();
1663 llvm::SmallVector<mlir::LLVM::GEPArg, 1> offset = {
1664 adaptor.getOffset().getZExtValue()};
1665 mlir::Type byteType = mlir::IntegerType::get(resultType.getContext(), 8,
1666 mlir::IntegerType::Signless);
1667 if (adaptor.getOffset().getZExtValue() == 0) {
1668 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(
1669 baseClassOp, resultType, adaptor.getDerivedAddr());
1670 return mlir::success();
1673 if (baseClassOp.getAssumeNotNull()) {
1674 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1675 baseClassOp, resultType, byteType, derivedAddr, offset);
1677 auto loc = baseClassOp.getLoc();
1678 mlir::Value isNull = mlir::LLVM::ICmpOp::create(
1679 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, derivedAddr,
1680 mlir::LLVM::ZeroOp::create(rewriter, loc, derivedAddr.getType()));
1681 mlir::Value adjusted = mlir::LLVM::GEPOp::create(
1682 rewriter, loc, resultType, byteType, derivedAddr, offset);
1683 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(baseClassOp, isNull,
1684 derivedAddr, adjusted);
1686 return mlir::success();
1689mlir::LogicalResult CIRToLLVMDerivedClassAddrOpLowering::matchAndRewrite(
1690 cir::DerivedClassAddrOp derivedClassOp, OpAdaptor adaptor,
1691 mlir::ConversionPatternRewriter &rewriter)
const {
1692 const mlir::Type resultType =
1693 getTypeConverter()->convertType(derivedClassOp.getType());
1694 mlir::Value baseAddr = adaptor.getBaseAddr();
1697 int64_t offsetVal = -(adaptor.getOffset().getZExtValue());
1698 if (offsetVal == 0) {
1700 rewriter.replaceOp(derivedClassOp, baseAddr);
1701 return mlir::success();
1703 llvm::SmallVector<mlir::LLVM::GEPArg, 1> offset = {offsetVal};
1704 mlir::Type byteType = mlir::IntegerType::get(resultType.getContext(), 8,
1705 mlir::IntegerType::Signless);
1706 if (derivedClassOp.getAssumeNotNull()) {
1707 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1708 derivedClassOp, resultType, byteType, baseAddr, offset,
1709 mlir::LLVM::GEPNoWrapFlags::inbounds);
1711 mlir::Location loc = derivedClassOp.getLoc();
1712 mlir::Value isNull = mlir::LLVM::ICmpOp::create(
1713 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, baseAddr,
1714 mlir::LLVM::ZeroOp::create(rewriter, loc, baseAddr.getType()));
1715 mlir::Value adjusted =
1716 mlir::LLVM::GEPOp::create(rewriter, loc, resultType, byteType, baseAddr,
1717 offset, mlir::LLVM::GEPNoWrapFlags::inbounds);
1718 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(derivedClassOp, isNull,
1719 baseAddr, adjusted);
1721 return mlir::success();
1724mlir::LogicalResult CIRToLLVMATanOpLowering::matchAndRewrite(
1725 cir::ATanOp op, OpAdaptor adaptor,
1726 mlir::ConversionPatternRewriter &rewriter)
const {
1727 mlir::Type resTy = typeConverter->convertType(op.getType());
1728 rewriter.replaceOpWithNewOp<mlir::LLVM::ATanOp>(op, resTy, adaptor.getSrc());
1729 return mlir::success();
1732mlir::LogicalResult CIRToLLVMCeilOpLowering::matchAndRewrite(
1733 cir::CeilOp op, OpAdaptor adaptor,
1734 mlir::ConversionPatternRewriter &rewriter)
const {
1735 mlir::Type resTy = typeConverter->convertType(op.getType());
1736 rewriter.replaceOpWithNewOp<mlir::LLVM::FCeilOp>(op, resTy, adaptor.getSrc());
1737 return mlir::success();
1740mlir::LogicalResult CIRToLLVMCopysignOpLowering::matchAndRewrite(
1741 cir::CopysignOp op, OpAdaptor adaptor,
1742 mlir::ConversionPatternRewriter &rewriter)
const {
1743 mlir::Type resTy = typeConverter->convertType(op.getType());
1744 rewriter.replaceOpWithNewOp<mlir::LLVM::CopySignOp>(
1745 op, resTy, adaptor.getLhs(), adaptor.getRhs());
1746 return mlir::success();
1749mlir::LogicalResult CIRToLLVMFMaxNumOpLowering::matchAndRewrite(
1750 cir::FMaxNumOp op, OpAdaptor adaptor,
1751 mlir::ConversionPatternRewriter &rewriter)
const {
1752 mlir::Type resTy = typeConverter->convertType(op.getType());
1753 rewriter.replaceOpWithNewOp<mlir::LLVM::MaxNumOp>(
1754 op, resTy, adaptor.getLhs(), adaptor.getRhs(),
1755 mlir::LLVM::FastmathFlags::nsz);
1756 return mlir::success();
1759mlir::LogicalResult CIRToLLVMFMinNumOpLowering::matchAndRewrite(
1760 cir::FMinNumOp op, OpAdaptor adaptor,
1761 mlir::ConversionPatternRewriter &rewriter)
const {
1762 mlir::Type resTy = typeConverter->convertType(op.getType());
1763 rewriter.replaceOpWithNewOp<mlir::LLVM::MinNumOp>(
1764 op, resTy, adaptor.getLhs(), adaptor.getRhs(),
1765 mlir::LLVM::FastmathFlags::nsz);
1766 return mlir::success();
1769mlir::LogicalResult CIRToLLVMFMaximumOpLowering::matchAndRewrite(
1770 cir::FMaximumOp op, OpAdaptor adaptor,
1771 mlir::ConversionPatternRewriter &rewriter)
const {
1772 mlir::Type resTy = typeConverter->convertType(op.getType());
1773 rewriter.replaceOpWithNewOp<mlir::LLVM::MaximumOp>(
1774 op, resTy, adaptor.getLhs(), adaptor.getRhs());
1775 return mlir::success();
1778mlir::LogicalResult CIRToLLVMFMinimumOpLowering::matchAndRewrite(
1779 cir::FMinimumOp op, OpAdaptor adaptor,
1780 mlir::ConversionPatternRewriter &rewriter)
const {
1781 mlir::Type resTy = typeConverter->convertType(op.getType());
1782 rewriter.replaceOpWithNewOp<mlir::LLVM::MinimumOp>(
1783 op, resTy, adaptor.getLhs(), adaptor.getRhs());
1784 return mlir::success();
1787mlir::LogicalResult CIRToLLVMFModOpLowering::matchAndRewrite(
1788 cir::FModOp op, OpAdaptor adaptor,
1789 mlir::ConversionPatternRewriter &rewriter)
const {
1790 mlir::Type resTy = typeConverter->convertType(op.getType());
1791 rewriter.replaceOpWithNewOp<mlir::LLVM::FRemOp>(op, resTy, adaptor.getLhs(),
1793 return mlir::success();
1796mlir::LogicalResult CIRToLLVMPowOpLowering::matchAndRewrite(
1797 cir::PowOp op, OpAdaptor adaptor,
1798 mlir::ConversionPatternRewriter &rewriter)
const {
1799 mlir::Type resTy = typeConverter->convertType(op.getType());
1800 rewriter.replaceOpWithNewOp<mlir::LLVM::PowOp>(op, resTy, adaptor.getLhs(),
1802 return mlir::success();
1805mlir::LogicalResult CIRToLLVMATan2OpLowering::matchAndRewrite(
1806 cir::ATan2Op op, OpAdaptor adaptor,
1807 mlir::ConversionPatternRewriter &rewriter)
const {
1808 mlir::Type resTy = typeConverter->convertType(op.getType());
1809 rewriter.replaceOpWithNewOp<mlir::LLVM::ATan2Op>(op, resTy, adaptor.getLhs(),
1811 return mlir::success();
1814mlir::LogicalResult CIRToLLVMLroundOpLowering::matchAndRewrite(
1815 cir::LroundOp op, OpAdaptor adaptor,
1816 mlir::ConversionPatternRewriter &rewriter)
const {
1817 mlir::Type resTy = typeConverter->convertType(op.getType());
1818 rewriter.replaceOpWithNewOp<mlir::LLVM::LroundOp>(op, resTy,
1820 return mlir::success();
1823mlir::LogicalResult CIRToLLVMLlroundOpLowering::matchAndRewrite(
1824 cir::LlroundOp op, OpAdaptor adaptor,
1825 mlir::ConversionPatternRewriter &rewriter)
const {
1826 mlir::Type resTy = typeConverter->convertType(op.getType());
1827 rewriter.replaceOpWithNewOp<mlir::LLVM::LlroundOp>(op, resTy,
1829 return mlir::success();
1832mlir::LogicalResult CIRToLLVMLrintOpLowering::matchAndRewrite(
1833 cir::LrintOp op, OpAdaptor adaptor,
1834 mlir::ConversionPatternRewriter &rewriter)
const {
1835 mlir::Type resTy = typeConverter->convertType(op.getType());
1836 rewriter.replaceOpWithNewOp<mlir::LLVM::LrintOp>(op, resTy, adaptor.getSrc());
1837 return mlir::success();
1840mlir::LogicalResult CIRToLLVMLlrintOpLowering::matchAndRewrite(
1841 cir::LlrintOp op, OpAdaptor adaptor,
1842 mlir::ConversionPatternRewriter &rewriter)
const {
1843 mlir::Type resTy = typeConverter->convertType(op.getType());
1844 rewriter.replaceOpWithNewOp<mlir::LLVM::LlrintOp>(op, resTy,
1846 return mlir::success();
1849mlir::LogicalResult CIRToLLVMAllocaOpLowering::matchAndRewrite(
1850 cir::AllocaOp op, OpAdaptor adaptor,
1851 mlir::ConversionPatternRewriter &rewriter)
const {
1854 ? adaptor.getDynAllocSize()
1855 : mlir::LLVM::ConstantOp::create(
1856 rewriter, op.getLoc(),
1857 typeConverter->convertType(rewriter.getIndexType()), 1);
1858 mlir::Type elementTy =
1860 mlir::Type resultTy =
1866 rewriter.replaceOpWithNewOp<mlir::LLVM::AllocaOp>(op, resultTy, elementTy,
1867 size, op.getAlignment());
1869 return mlir::success();
1872mlir::LogicalResult CIRToLLVMReturnOpLowering::matchAndRewrite(
1873 cir::ReturnOp op, OpAdaptor adaptor,
1874 mlir::ConversionPatternRewriter &rewriter)
const {
1875 rewriter.replaceOpWithNewOp<mlir::LLVM::ReturnOp>(op, adaptor.getOperands());
1876 return mlir::LogicalResult::success();
1879mlir::LogicalResult CIRToLLVMRotateOpLowering::matchAndRewrite(
1880 cir::RotateOp op, OpAdaptor adaptor,
1881 mlir::ConversionPatternRewriter &rewriter)
const {
1884 mlir::Value input = adaptor.getInput();
1885 if (op.isRotateLeft())
1886 rewriter.replaceOpWithNewOp<mlir::LLVM::FshlOp>(op, input, input,
1887 adaptor.getAmount());
1889 rewriter.replaceOpWithNewOp<mlir::LLVM::FshrOp>(op, input, input,
1890 adaptor.getAmount());
1891 return mlir::LogicalResult::success();
1896 for (mlir::NamedAttribute attr : op->getAttrs()) {
1898 if (attr.getName() == CIRDialect::getCalleeAttrName() ||
1899 attr.getName() == CIRDialect::getSideEffectAttrName() ||
1900 attr.getName() == CIRDialect::getNoThrowAttrName() ||
1901 attr.getName() == CIRDialect::getNoUnwindAttrName() ||
1902 attr.getName() == CIRDialect::getNoReturnAttrName())
1906 result.push_back(attr);
1910static mlir::LogicalResult
1912 mlir::ConversionPatternRewriter &rewriter,
1913 const mlir::TypeConverter *converter,
1914 mlir::FlatSymbolRefAttr calleeAttr,
1915 mlir::Block *continueBlock =
nullptr,
1916 mlir::Block *landingPadBlock =
nullptr) {
1918 mlir::ValueTypeRange<mlir::ResultRange> cirResults = op->getResultTypes();
1919 auto call = cast<cir::CIRCallOpInterface>(op);
1921 if (converter->convertTypes(cirResults, llvmResults).failed())
1922 return mlir::failure();
1926 mlir::LLVM::MemoryEffectsAttr memoryEffects;
1927 bool noUnwind =
false;
1928 bool willReturn =
false;
1929 bool noReturn =
false;
1931 memoryEffects, noUnwind, willReturn, noReturn);
1936 mlir::LLVM::LLVMFunctionType llvmFnTy;
1943 mlir::Operation *callee =
1944 mlir::SymbolTable::lookupNearestSymbolFrom(op, calleeAttr);
1945 if (
auto fn = mlir::dyn_cast<mlir::FunctionOpInterface>(callee)) {
1946 llvmFnTy = converter->convertType<mlir::LLVM::LLVMFunctionType>(
1947 fn.getFunctionType());
1948 assert(llvmFnTy &&
"Failed to convert function type");
1949 }
else if (
auto alias = mlir::cast<mlir::LLVM::AliasOp>(callee)) {
1957 auto symAttr = mlir::cast<mlir::FlatSymbolRefAttr>(calleeAttr);
1959 mlir::LLVM::AddressOfOp::create(
1960 rewriter, op->getLoc(),
1961 mlir::LLVM::LLVMPointerType::get(rewriter.getContext()), symAttr)
1963 adjustedCallOperands.push_back(addrOfAlias);
1966 llvm::append_range(adjustedCallOperands, callOperands);
1967 callOperands = adjustedCallOperands;
1971 llvmFnTy = mlir::cast<mlir::LLVM::LLVMFunctionType>(alias.getType());
1974 return op->emitError(
"Unexpected callee type!");
1977 assert(!op->getOperands().empty() &&
1978 "operands list must no be empty for the indirect call");
1979 auto calleeTy = op->getOperands().front().getType();
1980 auto calleePtrTy = cast<cir::PointerType>(calleeTy);
1981 auto calleeFuncTy = cast<cir::FuncType>(calleePtrTy.getPointee());
1982 llvm::append_range(adjustedCallOperands, callOperands);
1983 llvmFnTy = cast<mlir::LLVM::LLVMFunctionType>(
1984 converter->convertType(calleeFuncTy));
1989 if (landingPadBlock) {
1990 auto newOp = rewriter.replaceOpWithNewOp<mlir::LLVM::InvokeOp>(
1991 op, llvmFnTy, calleeAttr, callOperands, continueBlock,
1992 mlir::ValueRange{}, landingPadBlock, mlir::ValueRange{});
1993 newOp->setAttrs(attributes);
1995 auto newOp = rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(
1996 op, llvmFnTy, calleeAttr, callOperands);
1997 newOp->setAttrs(attributes);
1999 newOp.setMemoryEffectsAttr(memoryEffects);
2000 newOp.setNoUnwind(noUnwind);
2001 newOp.setWillReturn(willReturn);
2002 newOp.setNoreturn(noReturn);
2005 return mlir::success();
2008mlir::LogicalResult CIRToLLVMCallOpLowering::matchAndRewrite(
2009 cir::CallOp op, OpAdaptor adaptor,
2010 mlir::ConversionPatternRewriter &rewriter)
const {
2012 getTypeConverter(), op.getCalleeAttr());
2015mlir::LogicalResult CIRToLLVMTryCallOpLowering::matchAndRewrite(
2016 cir::TryCallOp op, OpAdaptor adaptor,
2017 mlir::ConversionPatternRewriter &rewriter)
const {
2020 getTypeConverter(), op.getCalleeAttr(),
2021 op.getNormalDest(), op.getUnwindDest());
2024mlir::LogicalResult CIRToLLVMReturnAddrOpLowering::matchAndRewrite(
2025 cir::ReturnAddrOp op, OpAdaptor adaptor,
2026 mlir::ConversionPatternRewriter &rewriter)
const {
2027 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
2029 llvmPtrTy, adaptor.getOperands());
2030 return mlir::success();
2033mlir::LogicalResult CIRToLLVMFrameAddrOpLowering::matchAndRewrite(
2034 cir::FrameAddrOp op, OpAdaptor adaptor,
2035 mlir::ConversionPatternRewriter &rewriter)
const {
2036 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
2038 adaptor.getOperands());
2039 return mlir::success();
2042mlir::LogicalResult CIRToLLVMClearCacheOpLowering::matchAndRewrite(
2043 cir::ClearCacheOp op, OpAdaptor adaptor,
2044 mlir::ConversionPatternRewriter &rewriter)
const {
2045 mlir::Value begin = adaptor.getBegin();
2046 mlir::Value end = adaptor.getEnd();
2047 auto intrinNameAttr =
2048 mlir::StringAttr::get(op.getContext(),
"llvm.clear_cache");
2049 rewriter.replaceOpWithNewOp<mlir::LLVM::CallIntrinsicOp>(
2050 op, mlir::Type{}, intrinNameAttr, mlir::ValueRange{begin, end});
2052 return mlir::success();
2055mlir::LogicalResult CIRToLLVMAddrOfReturnAddrOpLowering::matchAndRewrite(
2056 cir::AddrOfReturnAddrOp op, OpAdaptor adaptor,
2057 mlir::ConversionPatternRewriter &rewriter)
const {
2058 const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType());
2060 llvmPtrTy, adaptor.getOperands());
2061 return mlir::success();
2064mlir::LogicalResult CIRToLLVMLoadOpLowering::matchAndRewrite(
2065 cir::LoadOp op, OpAdaptor adaptor,
2066 mlir::ConversionPatternRewriter &rewriter)
const {
2067 const mlir::Type llvmTy =
2069 mlir::LLVM::AtomicOrdering ordering =
getLLVMMemOrder(op.getMemOrder());
2070 std::optional<size_t> opAlign = op.getAlignment();
2071 unsigned alignment =
2072 (unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmTy));
2079 std::optional<llvm::StringRef> llvmSyncScope =
2082 mlir::LLVM::LoadOp newLoad = mlir::LLVM::LoadOp::create(
2083 rewriter, op->getLoc(), llvmTy, adaptor.getAddr(), alignment,
2084 op.getIsVolatile(),
false,
2085 false,
false, ordering,
2086 llvmSyncScope.value_or(std::string()));
2089 mlir::Value result =
2091 rewriter.replaceOp(op, result);
2093 return mlir::LogicalResult::success();
2097cir::direct::CIRToLLVMVecMaskedLoadOpLowering::matchAndRewrite(
2098 cir::VecMaskedLoadOp op, OpAdaptor adaptor,
2099 mlir::ConversionPatternRewriter &rewriter)
const {
2100 const mlir::Type llvmResTy =
2103 std::optional<size_t> opAlign = op.getAlignment();
2104 unsigned alignment =
2105 (unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmResTy));
2107 mlir::IntegerAttr alignAttr = rewriter.getI32IntegerAttr(alignment);
2109 auto newLoad = mlir::LLVM::MaskedLoadOp::create(
2110 rewriter, op.getLoc(), llvmResTy, adaptor.getAddr(), adaptor.getMask(),
2111 adaptor.getPassThru(), alignAttr);
2113 rewriter.replaceOp(op, newLoad.getResult());
2114 return mlir::success();
2117mlir::LogicalResult CIRToLLVMStoreOpLowering::matchAndRewrite(
2118 cir::StoreOp op, OpAdaptor adaptor,
2119 mlir::ConversionPatternRewriter &rewriter)
const {
2120 mlir::LLVM::AtomicOrdering memorder =
getLLVMMemOrder(op.getMemOrder());
2121 const mlir::Type llvmTy =
2122 getTypeConverter()->convertType(op.getValue().getType());
2123 std::optional<size_t> opAlign = op.getAlignment();
2124 unsigned alignment =
2125 (unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmTy));
2131 op.getValue().getType(), adaptor.getValue());
2136 std::optional<llvm::StringRef> llvmSyncScope =
2139 mlir::LLVM::StoreOp storeOp = mlir::LLVM::StoreOp::create(
2140 rewriter, op->getLoc(), value, adaptor.getAddr(), alignment,
2142 false,
false, memorder,
2143 llvmSyncScope.value_or(std::string()));
2144 rewriter.replaceOp(op, storeOp);
2146 return mlir::LogicalResult::success();
2150 auto array = mlir::dyn_cast<mlir::ArrayAttr>(attr.getElts());
2151 return attr.hasTrailingZeros() ||
2152 (array && std::count_if(array.begin(), array.end(), [](
auto elt) {
2153 auto ar = dyn_cast<cir::ConstArrayAttr>(elt);
2154 return ar && hasTrailingZeros(ar);
2158mlir::LogicalResult CIRToLLVMConstantOpLowering::matchAndRewrite(
2159 cir::ConstantOp op, OpAdaptor adaptor,
2160 mlir::ConversionPatternRewriter &rewriter)
const {
2161 mlir::Attribute attr = op.getValue();
2163 if (mlir::isa<cir::PoisonAttr>(attr)) {
2164 rewriter.replaceOpWithNewOp<mlir::LLVM::PoisonOp>(
2165 op, getTypeConverter()->convertType(op.getType()));
2166 return mlir::success();
2169 if (mlir::isa<mlir::IntegerType>(op.getType())) {
2174 attr = op.getValue();
2175 }
else if (mlir::isa<cir::BoolType>(op.getType())) {
2176 int value = mlir::cast<cir::BoolAttr>(op.getValue()).getValue();
2177 attr = rewriter.getIntegerAttr(typeConverter->convertType(op.getType()),
2179 }
else if (mlir::isa<cir::IntType>(op.getType())) {
2181 if (
auto ga = mlir::dyn_cast<cir::GlobalViewAttr>(op.getValue())) {
2187 op.emitError() <<
"global view with integer type";
2188 return mlir::failure();
2191 attr = rewriter.getIntegerAttr(
2192 typeConverter->convertType(op.getType()),
2193 mlir::cast<cir::IntAttr>(op.getValue()).getValue());
2194 }
else if (mlir::isa<cir::FPTypeInterface>(op.getType())) {
2195 attr = rewriter.getFloatAttr(
2196 typeConverter->convertType(op.getType()),
2197 mlir::cast<cir::FPAttr>(op.getValue()).getValue());
2198 }
else if (mlir::isa<cir::PointerType>(op.getType())) {
2200 if (mlir::isa<cir::ConstPtrAttr>(op.getValue())) {
2201 if (mlir::cast<cir::ConstPtrAttr>(op.getValue()).isNullValue()) {
2202 rewriter.replaceOpWithNewOp<mlir::LLVM::ZeroOp>(
2203 op, typeConverter->convertType(op.getType()));
2204 return mlir::success();
2208 if (
auto gv = mlir::dyn_cast<cir::GlobalViewAttr>(op.getValue())) {
2210 rewriter.replaceOp(op, newOp);
2211 return mlir::success();
2213 attr = op.getValue();
2214 }
else if (
const auto arrTy = mlir::dyn_cast<cir::ArrayType>(op.getType())) {
2215 const auto constArr = mlir::dyn_cast<cir::ConstArrayAttr>(op.getValue());
2216 if (!constArr && !isa<cir::ZeroAttr, cir::UndefAttr>(op.getValue()))
2217 return op.emitError() <<
"array does not have a constant initializer";
2219 std::optional<mlir::Attribute> denseAttr;
2221 const mlir::Value newOp =
2223 rewriter.replaceOp(op, newOp);
2224 return mlir::success();
2225 }
else if (constArr &&
2227 attr = denseAttr.value();
2229 const mlir::Value initVal =
2231 rewriter.replaceOp(op, initVal);
2232 return mlir::success();
2234 }
else if (
const auto recordAttr =
2235 mlir::dyn_cast<cir::ConstRecordAttr>(op.getValue())) {
2237 rewriter.replaceOp(op, initVal);
2238 return mlir::success();
2239 }
else if (
const auto vecTy = mlir::dyn_cast<cir::VectorType>(op.getType())) {
2241 getTypeConverter()));
2242 return mlir::success();
2243 }
else if (
auto recTy = mlir::dyn_cast<cir::RecordType>(op.getType())) {
2244 if (mlir::isa<cir::ZeroAttr, cir::UndefAttr>(attr)) {
2245 mlir::Value initVal =
2247 rewriter.replaceOp(op, initVal);
2248 return mlir::success();
2250 return op.emitError() <<
"unsupported lowering for record constant type "
2252 }
else if (
auto complexTy = mlir::dyn_cast<cir::ComplexType>(op.getType())) {
2253 mlir::Type complexElemTy = complexTy.getElementType();
2254 mlir::Type complexElemLLVMTy = typeConverter->convertType(complexElemTy);
2256 if (
auto zeroInitAttr = mlir::dyn_cast<cir::ZeroAttr>(op.getValue())) {
2257 mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(complexElemLLVMTy);
2258 mlir::ArrayAttr array = rewriter.getArrayAttr({zeroAttr, zeroAttr});
2259 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
2260 op, getTypeConverter()->convertType(op.getType()), array);
2261 return mlir::success();
2264 auto complexAttr = mlir::cast<cir::ConstComplexAttr>(op.getValue());
2266 mlir::Attribute components[2];
2267 if (mlir::isa<cir::IntType>(complexElemTy)) {
2268 components[0] = rewriter.getIntegerAttr(
2270 mlir::cast<cir::IntAttr>(complexAttr.getReal()).getValue());
2271 components[1] = rewriter.getIntegerAttr(
2273 mlir::cast<cir::IntAttr>(complexAttr.getImag()).getValue());
2275 components[0] = rewriter.getFloatAttr(
2277 mlir::cast<cir::FPAttr>(complexAttr.getReal()).getValue());
2278 components[1] = rewriter.getFloatAttr(
2280 mlir::cast<cir::FPAttr>(complexAttr.getImag()).getValue());
2283 attr = rewriter.getArrayAttr(components);
2285 return op.emitError() <<
"unsupported constant type " << op.getType();
2288 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
2289 op, getTypeConverter()->convertType(op.getType()),
attr);
2291 return mlir::success();
2295 mlir::DataLayout layout(op.getParentOfType<mlir::ModuleOp>());
2297 if (isa<cir::VoidType>(type))
2298 type = cir::IntType::get(type.getContext(), 8,
false);
2299 return llvm::divideCeil(layout.getTypeSizeInBits(type), 8);
2302mlir::LogicalResult CIRToLLVMPrefetchOpLowering::matchAndRewrite(
2303 cir::PrefetchOp op, OpAdaptor adaptor,
2304 mlir::ConversionPatternRewriter &rewriter)
const {
2305 rewriter.replaceOpWithNewOp<mlir::LLVM::Prefetch>(
2306 op, adaptor.getAddr(), adaptor.getIsWrite(), adaptor.getLocality(),
2308 return mlir::success();
2311mlir::LogicalResult CIRToLLVMPtrDiffOpLowering::matchAndRewrite(
2312 cir::PtrDiffOp op, OpAdaptor adaptor,
2313 mlir::ConversionPatternRewriter &rewriter)
const {
2314 auto dstTy = mlir::cast<cir::IntType>(op.getType());
2315 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
2317 auto lhs = mlir::LLVM::PtrToIntOp::create(rewriter, op.getLoc(), llvmDstTy,
2319 auto rhs = mlir::LLVM::PtrToIntOp::create(rewriter, op.getLoc(), llvmDstTy,
2323 mlir::LLVM::SubOp::create(rewriter, op.getLoc(), llvmDstTy, lhs, rhs);
2325 cir::PointerType ptrTy = op.getLhs().getType();
2327 uint64_t typeSize =
getTypeSize(ptrTy.getPointee(), *op);
2330 mlir::Value resultVal = diff.getResult();
2331 if (typeSize != 1) {
2332 auto typeSizeVal = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
2333 llvmDstTy, typeSize);
2335 if (dstTy.isUnsigned()) {
2337 mlir::LLVM::UDivOp::create(rewriter, op.getLoc(), diff, typeSizeVal);
2338 uDiv.setIsExact(
true);
2339 resultVal = uDiv.getResult();
2342 mlir::LLVM::SDivOp::create(rewriter, op.getLoc(), diff, typeSizeVal);
2343 sDiv.setIsExact(
true);
2344 resultVal = sDiv.getResult();
2347 rewriter.replaceOp(op, resultVal);
2348 return mlir::success();
2351mlir::LogicalResult CIRToLLVMExpectOpLowering::matchAndRewrite(
2352 cir::ExpectOp op, OpAdaptor adaptor,
2353 mlir::ConversionPatternRewriter &rewriter)
const {
2357 std::optional<llvm::APFloat> prob = op.getProb();
2359 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpectWithProbabilityOp>(
2360 op, adaptor.getVal(), adaptor.getExpected(), prob.value());
2362 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpectOp>(op, adaptor.getVal(),
2363 adaptor.getExpected());
2364 return mlir::success();
2367mlir::LogicalResult CIRToLLVMFAbsOpLowering::matchAndRewrite(
2368 cir::FAbsOp op, OpAdaptor adaptor,
2369 mlir::ConversionPatternRewriter &rewriter)
const {
2370 mlir::Type resTy = typeConverter->convertType(op.getType());
2371 rewriter.replaceOpWithNewOp<mlir::LLVM::FAbsOp>(op, resTy,
2372 adaptor.getOperands()[0]);
2373 return mlir::success();
2376mlir::LogicalResult CIRToLLVMAbsOpLowering::matchAndRewrite(
2377 cir::AbsOp op, OpAdaptor adaptor,
2378 mlir::ConversionPatternRewriter &rewriter)
const {
2379 mlir::Type resTy = typeConverter->convertType(op.getType());
2380 auto absOp = mlir::LLVM::AbsOp::create(rewriter, op.getLoc(), resTy,
2381 adaptor.getOperands()[0],
2382 adaptor.getMinIsPoison());
2383 rewriter.replaceOp(op, absOp);
2384 return mlir::success();
2391void CIRToLLVMFuncOpLowering::lowerFuncAttributes(
2392 cir::FuncOp func,
bool filterArgAndResAttrs,
2393 SmallVectorImpl<mlir::NamedAttribute> &result)
const {
2395 for (mlir::NamedAttribute attr : func->getAttrs()) {
2397 if (
attr.getName() == mlir::SymbolTable::getSymbolAttrName() ||
2398 attr.getName() == func.getFunctionTypeAttrName() ||
2400 attr.getName() == func.getGlobalVisibilityAttrName() ||
2401 attr.getName() == func.getDsoLocalAttrName() ||
2402 attr.getName() == func.getInlineKindAttrName() ||
2403 attr.getName() == func.getSideEffectAttrName() ||
2404 attr.getName() == CIRDialect::getNoReturnAttrName() ||
2405 (filterArgAndResAttrs &&
2406 (
attr.getName() == func.getArgAttrsAttrName() ||
2407 attr.getName() == func.getResAttrsAttrName())))
2411 result.push_back(attr);
2415mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewriteAlias(
2416 cir::FuncOp op, llvm::StringRef aliasee, mlir::Type ty, OpAdaptor adaptor,
2417 mlir::ConversionPatternRewriter &rewriter)
const {
2418 SmallVector<mlir::NamedAttribute, 4> attributes;
2419 lowerFuncAttributes(op,
false, attributes);
2421 mlir::Location loc = op.getLoc();
2422 auto aliasOp = rewriter.replaceOpWithNewOp<mlir::LLVM::AliasOp>(
2423 op, ty,
convertLinkage(op.getLinkage()), op.getName(), op.getDsoLocal(),
2427 mlir::OpBuilder builder(op.getContext());
2428 mlir::Block *block = builder.createBlock(&aliasOp.getInitializerRegion());
2429 builder.setInsertionPointToStart(block);
2432 mlir::Type ptrTy = mlir::LLVM::LLVMPointerType::get(ty.getContext());
2433 auto addrOp = mlir::LLVM::AddressOfOp::create(builder, loc, ptrTy, aliasee);
2434 mlir::LLVM::ReturnOp::create(builder, loc, addrOp);
2436 return mlir::success();
2439mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewrite(
2440 cir::FuncOp op, OpAdaptor adaptor,
2441 mlir::ConversionPatternRewriter &rewriter)
const {
2443 cir::FuncType fnType = op.getFunctionType();
2444 bool isDsoLocal = op.getDsoLocal();
2445 mlir::TypeConverter::SignatureConversion signatureConversion(
2446 fnType.getNumInputs());
2448 for (
const auto &argType : llvm::enumerate(fnType.getInputs())) {
2449 mlir::Type convertedType = typeConverter->convertType(argType.value());
2451 return mlir::failure();
2452 signatureConversion.addInputs(argType.index(), convertedType);
2455 mlir::Type resultType =
2456 getTypeConverter()->convertType(fnType.getReturnType());
2459 mlir::Type llvmFnTy = mlir::LLVM::LLVMFunctionType::get(
2460 resultType ? resultType : mlir::LLVM::LLVMVoidType::get(getContext()),
2461 signatureConversion.getConvertedTypes(),
2465 if (std::optional<llvm::StringRef> aliasee = op.getAliasee())
2466 return matchAndRewriteAlias(op, *aliasee, llvmFnTy, adaptor, rewriter);
2470 mlir::Location loc = op.getLoc();
2471 if (mlir::FusedLoc fusedLoc = mlir::dyn_cast<mlir::FusedLoc>(loc))
2472 loc = fusedLoc.getLocations()[0];
2473 assert((mlir::isa<mlir::FileLineColLoc>(loc) ||
2474 mlir::isa<mlir::UnknownLoc>(loc)) &&
2475 "expected single location or unknown location here");
2479 mlir::LLVM::CConv cconv = mlir::LLVM::CConv::C;
2480 SmallVector<mlir::NamedAttribute, 4> attributes;
2481 lowerFuncAttributes(op,
false, attributes);
2483 mlir::LLVM::LLVMFuncOp fn = mlir::LLVM::LLVMFuncOp::create(
2484 rewriter, loc, op.getName(), llvmFnTy, linkage, isDsoLocal, cconv,
2485 mlir::SymbolRefAttr(), attributes);
2489 if (std::optional<cir::SideEffect> sideEffectKind = op.getSideEffect()) {
2490 switch (*sideEffectKind) {
2491 case cir::SideEffect::All:
2493 case cir::SideEffect::Pure:
2494 fn.setMemoryEffectsAttr(mlir::LLVM::MemoryEffectsAttr::get(
2496 mlir::LLVM::ModRefInfo::Ref,
2497 mlir::LLVM::ModRefInfo::Ref,
2498 mlir::LLVM::ModRefInfo::Ref,
2499 mlir::LLVM::ModRefInfo::Ref,
2500 mlir::LLVM::ModRefInfo::Ref,
2501 mlir::LLVM::ModRefInfo::Ref));
2502 fn.setNoUnwind(
true);
2503 fn.setWillReturn(
true);
2505 case cir::SideEffect::Const:
2506 fn.setMemoryEffectsAttr(mlir::LLVM::MemoryEffectsAttr::get(
2508 mlir::LLVM::ModRefInfo::NoModRef,
2509 mlir::LLVM::ModRefInfo::NoModRef,
2510 mlir::LLVM::ModRefInfo::NoModRef,
2511 mlir::LLVM::ModRefInfo::NoModRef,
2512 mlir::LLVM::ModRefInfo::NoModRef,
2513 mlir::LLVM::ModRefInfo::NoModRef));
2514 fn.setNoUnwind(
true);
2515 fn.setWillReturn(
true);
2520 if (op->hasAttr(CIRDialect::getNoReturnAttrName()))
2521 fn.setNoreturn(
true);
2523 if (std::optional<cir::InlineKind> inlineKind = op.getInlineKind()) {
2524 fn.setNoInline(*inlineKind == cir::InlineKind::NoInline);
2525 fn.setInlineHint(*inlineKind == cir::InlineKind::InlineHint);
2526 fn.setAlwaysInline(*inlineKind == cir::InlineKind::AlwaysInline);
2529 if (std::optional<llvm::StringRef> personality = op.getPersonality())
2530 fn.setPersonality(*personality);
2535 rewriter.inlineRegionBefore(op.getBody(), fn.getBody(), fn.end());
2536 if (failed(rewriter.convertRegionTypes(&fn.getBody(), *typeConverter,
2537 &signatureConversion)))
2538 return mlir::failure();
2540 rewriter.eraseOp(op);
2542 return mlir::LogicalResult::success();
2545mlir::LogicalResult CIRToLLVMGetGlobalOpLowering::matchAndRewrite(
2546 cir::GetGlobalOp op, OpAdaptor adaptor,
2547 mlir::ConversionPatternRewriter &rewriter)
const {
2550 if (op->getUses().empty()) {
2551 rewriter.eraseOp(op);
2552 return mlir::success();
2555 mlir::Type
type = getTypeConverter()->convertType(op.getType());
2556 mlir::Operation *newop = mlir::LLVM::AddressOfOp::create(
2557 rewriter, op.getLoc(), type, op.getName());
2561 newop = mlir::LLVM::ThreadlocalAddressOp::create(rewriter, op.getLoc(),
2562 type, newop->getResult(0));
2565 rewriter.replaceOp(op, newop);
2566 return mlir::success();
2571void CIRToLLVMGlobalOpLowering::setupRegionInitializedLLVMGlobalOp(
2572 cir::GlobalOp op, mlir::ConversionPatternRewriter &rewriter)
const {
2573 const mlir::Type llvmType =
2580 const bool isConst = op.getConstant();
2581 unsigned addrSpace = 0;
2582 if (
auto targetAS = mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
2583 op.getAddrSpaceAttr()))
2584 addrSpace = targetAS.getValue();
2585 const bool isDsoLocal = op.getDsoLocal();
2586 const bool isThreadLocal = (
bool)op.getTlsModelAttr();
2587 const uint64_t alignment = op.getAlignment().value_or(0);
2588 const mlir::LLVM::Linkage linkage =
convertLinkage(op.getLinkage());
2589 const StringRef symbol = op.getSymName();
2590 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
2592 SmallVector<mlir::NamedAttribute> attributes;
2593 mlir::LLVM::GlobalOp newGlobalOp =
2594 rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
2595 op, llvmType, isConst, linkage, symbol,
nullptr, alignment, addrSpace,
2596 isDsoLocal, isThreadLocal, comdatAttr, attributes);
2597 newGlobalOp.getRegion().emplaceBlock();
2598 rewriter.setInsertionPointToEnd(newGlobalOp.getInitializerBlock());
2602CIRToLLVMGlobalOpLowering::matchAndRewriteRegionInitializedGlobal(
2603 cir::GlobalOp op, mlir::Attribute init,
2604 mlir::ConversionPatternRewriter &rewriter)
const {
2607 (isa<cir::ConstArrayAttr, cir::ConstRecordAttr, cir::ConstVectorAttr,
2608 cir::ConstPtrAttr, cir::ConstComplexAttr, cir::GlobalViewAttr,
2609 cir::TypeInfoAttr, cir::UndefAttr, cir::VTableAttr, cir::ZeroAttr>(
2615 const mlir::Location loc = op.getLoc();
2616 setupRegionInitializedLLVMGlobalOp(op, rewriter);
2618 mlir::Value value = valueConverter.visit(init);
2619 mlir::LLVM::ReturnOp::create(rewriter, loc, value);
2620 return mlir::success();
2623mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite(
2624 cir::GlobalOp op, OpAdaptor adaptor,
2625 mlir::ConversionPatternRewriter &rewriter)
const {
2628 if (!op.getCtorRegion().empty() || !op.getDtorRegion().empty())
2629 return op.emitError() <<
"GlobalOp ctor and dtor regions should be removed "
2630 "in LoweringPrepare";
2632 std::optional<mlir::Attribute> init = op.getInitialValue();
2635 const mlir::Type cirSymType = op.getSymType();
2638 const mlir::Type llvmType =
2643 const bool isConst = op.getConstant();
2644 unsigned addrSpace = 0;
2645 if (
auto targetAS = mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
2646 op.getAddrSpaceAttr()))
2647 addrSpace = targetAS.getValue();
2648 const bool isDsoLocal = op.getDsoLocal();
2649 const bool isThreadLocal = (
bool)op.getTlsModelAttr();
2650 const uint64_t alignment = op.getAlignment().value_or(0);
2651 const mlir::LLVM::Linkage linkage =
convertLinkage(op.getLinkage());
2652 const StringRef symbol = op.getSymName();
2653 SmallVector<mlir::NamedAttribute> attributes;
2657 op->getAttr(CUDAExternallyInitializedAttr::getMnemonic())) {
2658 attributes.push_back(rewriter.getNamedAttr(
"externally_initialized",
2659 rewriter.getUnitAttr()));
2662 if (init.has_value()) {
2663 if (mlir::isa<cir::FPAttr, cir::IntAttr, cir::BoolAttr>(init.value())) {
2665 init = initRewriter.visit(init.value());
2670 if (!init.value()) {
2671 op.emitError() <<
"unsupported initializer '" << init.value() <<
"'";
2672 return mlir::failure();
2674 }
else if (mlir::isa<cir::ConstArrayAttr, cir::ConstVectorAttr,
2675 cir::ConstRecordAttr, cir::ConstPtrAttr,
2676 cir::ConstComplexAttr, cir::GlobalViewAttr,
2677 cir::TypeInfoAttr, cir::UndefAttr, cir::VTableAttr,
2678 cir::ZeroAttr>(init.value())) {
2682 return matchAndRewriteRegionInitializedGlobal(op, init.value(), rewriter);
2686 op.emitError() <<
"unsupported initializer '" << init.value() <<
"'";
2687 return mlir::failure();
2691 mlir::LLVM::Visibility visibility =
2693 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
2694 auto newOp = rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
2695 op, llvmType, isConst, linkage, symbol, init.value_or(mlir::Attribute()),
2696 alignment, addrSpace, isDsoLocal, isThreadLocal, comdatAttr, attributes);
2697 newOp.setVisibility_(visibility);
2699 return mlir::success();
2703CIRToLLVMGlobalOpLowering::getComdatAttr(cir::GlobalOp &op,
2704 mlir::OpBuilder &builder)
const {
2705 if (!op.getComdat())
2706 return mlir::SymbolRefAttr{};
2708 mlir::ModuleOp module = op->getParentOfType<mlir::ModuleOp>();
2709 mlir::OpBuilder::InsertionGuard guard(builder);
2710 StringRef comdatName(
"__llvm_comdat_globals");
2712 builder.setInsertionPointToStart(module.getBody());
2714 mlir::LLVM::ComdatOp::create(builder, module.getLoc(), comdatName);
2717 if (
auto comdatSelector = comdatOp.lookupSymbol<mlir::LLVM::ComdatSelectorOp>(
2719 return mlir::SymbolRefAttr::get(
2720 builder.getContext(), comdatName,
2721 mlir::FlatSymbolRefAttr::get(comdatSelector.getSymNameAttr()));
2724 builder.setInsertionPointToStart(&comdatOp.getBody().back());
2725 auto selectorOp = mlir::LLVM::ComdatSelectorOp::create(
2726 builder, comdatOp.getLoc(), op.getSymName(),
2727 mlir::LLVM::comdat::Comdat::Any);
2728 return mlir::SymbolRefAttr::get(
2729 builder.getContext(), comdatName,
2730 mlir::FlatSymbolRefAttr::get(selectorOp.getSymNameAttr()));
2733mlir::LogicalResult CIRToLLVMSwitchFlatOpLowering::matchAndRewrite(
2734 cir::SwitchFlatOp op, OpAdaptor adaptor,
2735 mlir::ConversionPatternRewriter &rewriter)
const {
2737 llvm::SmallVector<mlir::APInt, 8> caseValues;
2738 for (mlir::Attribute val : op.getCaseValues()) {
2739 auto intAttr = cast<cir::IntAttr>(val);
2740 caseValues.push_back(intAttr.getValue());
2743 llvm::SmallVector<mlir::Block *, 8> caseDestinations;
2744 llvm::SmallVector<mlir::ValueRange, 8> caseOperands;
2746 for (mlir::Block *x : op.getCaseDestinations())
2747 caseDestinations.push_back(x);
2749 for (mlir::OperandRange x : op.getCaseOperands())
2750 caseOperands.push_back(x);
2753 rewriter.setInsertionPoint(op);
2754 rewriter.replaceOpWithNewOp<mlir::LLVM::SwitchOp>(
2755 op, adaptor.getCondition(), op.getDefaultDestination(),
2756 op.getDefaultOperands(), caseValues, caseDestinations, caseOperands);
2757 return mlir::success();
2760static mlir::LLVM::IntegerOverflowFlags
nswFlag(
bool nsw) {
2761 return nsw ? mlir::LLVM::IntegerOverflowFlags::nsw
2762 : mlir::LLVM::IntegerOverflowFlags::none;
2765template <
typename CIROp,
typename LLVMIntOp>
2766static mlir::LogicalResult
2768 mlir::ConversionPatternRewriter &rewriter,
double fpConstant) {
2769 mlir::Type elementType = elementTypeIfVector(op.getType());
2770 mlir::Type llvmType = adaptor.getInput().getType();
2771 mlir::Location loc = op.getLoc();
2773 if (mlir::isa<cir::IntType>(elementType)) {
2774 auto maybeNSW =
nswFlag(op.getNoSignedWrap());
2775 auto one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
2776 rewriter.replaceOpWithNewOp<LLVMIntOp>(op, adaptor.getInput(), one,
2778 return mlir::success();
2780 if (mlir::isa<cir::FPTypeInterface>(elementType)) {
2781 auto fpConst = mlir::LLVM::ConstantOp::create(
2782 rewriter, loc, rewriter.getFloatAttr(llvmType, fpConstant));
2783 rewriter.replaceOpWithNewOp<mlir::LLVM::FAddOp>(op, fpConst,
2784 adaptor.getInput());
2785 return mlir::success();
2787 return op.emitError() <<
"Unsupported type for IncOp/DecOp";
2790mlir::LogicalResult CIRToLLVMIncOpLowering::matchAndRewrite(
2791 cir::IncOp op, OpAdaptor adaptor,
2792 mlir::ConversionPatternRewriter &rewriter)
const {
2797mlir::LogicalResult CIRToLLVMDecOpLowering::matchAndRewrite(
2798 cir::DecOp op, OpAdaptor adaptor,
2799 mlir::ConversionPatternRewriter &rewriter)
const {
2804mlir::LogicalResult CIRToLLVMMinusOpLowering::matchAndRewrite(
2805 cir::MinusOp op, OpAdaptor adaptor,
2806 mlir::ConversionPatternRewriter &rewriter)
const {
2807 mlir::Type elementType = elementTypeIfVector(op.getType());
2808 bool isVector = mlir::isa<cir::VectorType>(op.getType());
2809 mlir::Type llvmType = adaptor.getInput().getType();
2810 mlir::Location loc = op.getLoc();
2812 if (mlir::isa<cir::IntType>(elementType)) {
2813 auto maybeNSW =
nswFlag(op.getNoSignedWrap());
2816 zero = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmType);
2818 zero = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 0);
2819 rewriter.replaceOpWithNewOp<mlir::LLVM::SubOp>(op, zero, adaptor.getInput(),
2821 return mlir::success();
2823 if (mlir::isa<cir::FPTypeInterface>(elementType)) {
2824 rewriter.replaceOpWithNewOp<mlir::LLVM::FNegOp>(op, adaptor.getInput());
2825 return mlir::success();
2827 return op.emitError() <<
"Unsupported type for unary minus";
2830mlir::LogicalResult CIRToLLVMNotOpLowering::matchAndRewrite(
2831 cir::NotOp op, OpAdaptor adaptor,
2832 mlir::ConversionPatternRewriter &rewriter)
const {
2833 mlir::Type elementType = elementTypeIfVector(op.getType());
2834 bool isVector = mlir::isa<cir::VectorType>(op.getType());
2835 mlir::Type llvmType = adaptor.getInput().getType();
2836 mlir::Location loc = op.getLoc();
2838 if (mlir::isa<cir::IntType>(elementType)) {
2839 mlir::Value minusOne;
2842 mlir::dyn_cast<cir::VectorType>(op.getType()).getSize();
2843 SmallVector<int32_t> values(numElements, -1);
2844 mlir::DenseIntElementsAttr denseVec = rewriter.getI32VectorAttr(values);
2846 mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, denseVec);
2848 minusOne = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, -1);
2850 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getInput(),
2852 return mlir::success();
2854 if (mlir::isa<cir::BoolType>(elementType)) {
2855 auto one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
2856 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getInput(), one);
2857 return mlir::success();
2859 return op.emitError() <<
"Unsupported type for bitwise NOT";
2864 return mlir::isa<cir::IntType>(type)
2865 ? mlir::cast<cir::IntType>(type).isUnsigned()
2866 : mlir::cast<mlir::IntegerType>(type).isUnsigned();
2873template <
typename BinOp>
2875 if (op.getNoUnsignedWrap())
2876 return mlir::LLVM::IntegerOverflowFlags::nuw;
2877 if (op.getNoSignedWrap())
2878 return mlir::LLVM::IntegerOverflowFlags::nsw;
2879 return mlir::LLVM::IntegerOverflowFlags::none;
2884template <
typename UIntSatOp,
typename SIntSatOp,
typename IntOp,
typename FPOp,
2886static mlir::LogicalResult
2888 mlir::ConversionPatternRewriter &rewriter) {
2889 const mlir::Type eltType = elementTypeIfVector(op.getRhs().getType());
2890 if (cir::isIntOrBoolType(eltType)) {
2891 if (op.getSaturated()) {
2893 rewriter.replaceOpWithNewOp<UIntSatOp>(op, lhs, rhs);
2895 rewriter.replaceOpWithNewOp<SIntSatOp>(op, lhs, rhs);
2896 return mlir::success();
2898 rewriter.replaceOpWithNewOp<IntOp>(op, lhs, rhs,
intOverflowFlag(op));
2900 rewriter.replaceOpWithNewOp<FPOp>(op, lhs, rhs);
2902 return mlir::success();
2905mlir::LogicalResult CIRToLLVMAddOpLowering::matchAndRewrite(
2906 cir::AddOp op, OpAdaptor adaptor,
2907 mlir::ConversionPatternRewriter &rewriter)
const {
2909 mlir::LLVM::AddOp, mlir::LLVM::FAddOp>(
2910 op, adaptor.getLhs(), adaptor.getRhs(), rewriter);
2913mlir::LogicalResult CIRToLLVMSubOpLowering::matchAndRewrite(
2914 cir::SubOp op, OpAdaptor adaptor,
2915 mlir::ConversionPatternRewriter &rewriter)
const {
2917 mlir::LLVM::SubOp, mlir::LLVM::FSubOp>(
2918 op, adaptor.getLhs(), adaptor.getRhs(), rewriter);
2921mlir::LogicalResult CIRToLLVMMulOpLowering::matchAndRewrite(
2922 cir::MulOp op, OpAdaptor adaptor,
2923 mlir::ConversionPatternRewriter &rewriter)
const {
2924 const mlir::Value lhs = adaptor.getLhs();
2925 const mlir::Value rhs = adaptor.getRhs();
2926 if (cir::isIntOrBoolType(elementTypeIfVector(op.getRhs().getType()))) {
2927 rewriter.replaceOpWithNewOp<mlir::LLVM::MulOp>(op, lhs, rhs,
2930 rewriter.replaceOpWithNewOp<mlir::LLVM::FMulOp>(op, lhs, rhs);
2932 return mlir::success();
2937template <
typename UIntOp,
typename SIntOp,
typename FPOp,
typename CIROp>
2938static mlir::LogicalResult
2940 mlir::ConversionPatternRewriter &rewriter) {
2941 const mlir::Type eltType = elementTypeIfVector(op.getRhs().getType());
2942 if (cir::isIntOrBoolType(eltType)) {
2944 rewriter.replaceOpWithNewOp<UIntOp>(op, lhs, rhs);
2946 rewriter.replaceOpWithNewOp<SIntOp>(op, lhs, rhs);
2948 rewriter.replaceOpWithNewOp<FPOp>(op, lhs, rhs);
2950 return mlir::success();
2953mlir::LogicalResult CIRToLLVMDivOpLowering::matchAndRewrite(
2954 cir::DivOp op, OpAdaptor adaptor,
2955 mlir::ConversionPatternRewriter &rewriter)
const {
2957 mlir::LLVM::FDivOp>(op, adaptor.getLhs(),
2958 adaptor.getRhs(), rewriter);
2961mlir::LogicalResult CIRToLLVMRemOpLowering::matchAndRewrite(
2962 cir::RemOp op, OpAdaptor adaptor,
2963 mlir::ConversionPatternRewriter &rewriter)
const {
2965 mlir::LLVM::FRemOp>(op, adaptor.getLhs(),
2966 adaptor.getRhs(), rewriter);
2969mlir::LogicalResult CIRToLLVMAndOpLowering::matchAndRewrite(
2970 cir::AndOp op, OpAdaptor adaptor,
2971 mlir::ConversionPatternRewriter &rewriter)
const {
2972 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(op, adaptor.getLhs(),
2974 return mlir::success();
2977mlir::LogicalResult CIRToLLVMOrOpLowering::matchAndRewrite(
2978 cir::OrOp op, OpAdaptor adaptor,
2979 mlir::ConversionPatternRewriter &rewriter)
const {
2980 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(op, adaptor.getLhs(),
2982 return mlir::success();
2985mlir::LogicalResult CIRToLLVMXorOpLowering::matchAndRewrite(
2986 cir::XorOp op, OpAdaptor adaptor,
2987 mlir::ConversionPatternRewriter &rewriter)
const {
2988 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getLhs(),
2990 return mlir::success();
2993template <
typename CIROp,
typename UIntOp,
typename SIntOp>
2994static mlir::LogicalResult
2996 mlir::ConversionPatternRewriter &rewriter) {
2997 const mlir::Value lhs = adaptor.getLhs();
2998 const mlir::Value rhs = adaptor.getRhs();
3000 rewriter.replaceOpWithNewOp<UIntOp>(op, lhs, rhs);
3002 rewriter.replaceOpWithNewOp<SIntOp>(op, lhs, rhs);
3003 return mlir::success();
3006mlir::LogicalResult CIRToLLVMMaxOpLowering::matchAndRewrite(
3007 cir::MaxOp op, OpAdaptor adaptor,
3008 mlir::ConversionPatternRewriter &rewriter)
const {
3010 op, adaptor, rewriter);
3013mlir::LogicalResult CIRToLLVMMinOpLowering::matchAndRewrite(
3014 cir::MinOp op, OpAdaptor adaptor,
3015 mlir::ConversionPatternRewriter &rewriter)
const {
3017 op, adaptor, rewriter);
3021static mlir::LLVM::ICmpPredicate
3023 using CIR = cir::CmpOpKind;
3024 using LLVMICmp = mlir::LLVM::ICmpPredicate;
3027 return LLVMICmp::eq;
3029 return LLVMICmp::ne;
3031 return (isSigned ? LLVMICmp::slt : LLVMICmp::ult);
3033 return (isSigned ? LLVMICmp::sle : LLVMICmp::ule);
3035 return (isSigned ? LLVMICmp::sgt : LLVMICmp::ugt);
3037 return (isSigned ? LLVMICmp::sge : LLVMICmp::uge);
3039 llvm_unreachable(
"Unknown CmpOpKind");
3044static mlir::LLVM::FCmpPredicate
3046 using CIR = cir::CmpOpKind;
3047 using LLVMFCmp = mlir::LLVM::FCmpPredicate;
3050 return LLVMFCmp::oeq;
3052 return LLVMFCmp::une;
3054 return LLVMFCmp::olt;
3056 return LLVMFCmp::ole;
3058 return LLVMFCmp::ogt;
3060 return LLVMFCmp::oge;
3062 llvm_unreachable(
"Unknown CmpOpKind");
3065mlir::LogicalResult CIRToLLVMCmpOpLowering::matchAndRewrite(
3066 cir::CmpOp cmpOp, OpAdaptor adaptor,
3067 mlir::ConversionPatternRewriter &rewriter)
const {
3068 mlir::Type type = cmpOp.getLhs().getType();
3070 if (mlir::isa<cir::IntType, mlir::IntegerType>(type)) {
3071 bool isSigned = mlir::isa<cir::IntType>(type)
3072 ? mlir::cast<cir::IntType>(type).isSigned()
3073 : mlir::cast<mlir::IntegerType>(type).isSigned();
3074 mlir::LLVM::ICmpPredicate
kind =
3076 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
3077 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
3078 return mlir::success();
3081 if (
auto ptrTy = mlir::dyn_cast<cir::PointerType>(type)) {
3082 mlir::LLVM::ICmpPredicate
kind =
3085 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
3086 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
3087 return mlir::success();
3090 if (
auto vptrTy = mlir::dyn_cast<cir::VPtrType>(type)) {
3094 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
3095 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
3096 return mlir::success();
3099 if (mlir::isa<cir::FPTypeInterface>(type)) {
3100 mlir::LLVM::FCmpPredicate
kind =
3102 rewriter.replaceOpWithNewOp<mlir::LLVM::FCmpOp>(
3103 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
3104 return mlir::success();
3107 if (mlir::isa<cir::ComplexType>(type)) {
3108 mlir::Value lhs = adaptor.getLhs();
3109 mlir::Value rhs = adaptor.getRhs();
3110 mlir::Location loc = cmpOp.getLoc();
3112 auto complexType = mlir::cast<cir::ComplexType>(cmpOp.getLhs().getType());
3113 mlir::Type complexElemTy =
3114 getTypeConverter()->convertType(
complexType.getElementType());
3116 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
3117 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{0}));
3118 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
3119 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{1}));
3120 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
3121 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{0}));
3122 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
3123 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{1}));
3125 if (cmpOp.getKind() == cir::CmpOpKind::eq) {
3126 if (complexElemTy.isInteger()) {
3127 auto realCmp = mlir::LLVM::ICmpOp::create(
3128 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, lhsReal, rhsReal);
3129 auto imagCmp = mlir::LLVM::ICmpOp::create(
3130 rewriter, loc, mlir::LLVM::ICmpPredicate::eq, lhsImag, rhsImag);
3131 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, imagCmp);
3132 return mlir::success();
3135 auto realCmp = mlir::LLVM::FCmpOp::create(
3136 rewriter, loc, mlir::LLVM::FCmpPredicate::oeq, lhsReal, rhsReal);
3137 auto imagCmp = mlir::LLVM::FCmpOp::create(
3138 rewriter, loc, mlir::LLVM::FCmpPredicate::oeq, lhsImag, rhsImag);
3139 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, imagCmp);
3140 return mlir::success();
3143 if (cmpOp.getKind() == cir::CmpOpKind::ne) {
3144 if (complexElemTy.isInteger()) {
3145 auto realCmp = mlir::LLVM::ICmpOp::create(
3146 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, lhsReal, rhsReal);
3147 auto imagCmp = mlir::LLVM::ICmpOp::create(
3148 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, lhsImag, rhsImag);
3149 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp);
3150 return mlir::success();
3153 auto realCmp = mlir::LLVM::FCmpOp::create(
3154 rewriter, loc, mlir::LLVM::FCmpPredicate::une, lhsReal, rhsReal);
3155 auto imagCmp = mlir::LLVM::FCmpOp::create(
3156 rewriter, loc, mlir::LLVM::FCmpPredicate::une, lhsImag, rhsImag);
3157 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp);
3158 return mlir::success();
3162 return cmpOp.emitError() <<
"unsupported type for CmpOp: " <<
type;
3168template <
typename OpTy>
3169static mlir::LogicalResult
3171 mlir::ConversionPatternRewriter &rewriter,
3172 const mlir::TypeConverter *typeConverter,
3173 llvm::StringRef opStr) {
3174 mlir::Location loc = op.getLoc();
3175 cir::IntType operandTy = op.getLhs().getType();
3176 cir::IntType resultTy = op.getResult().getType();
3178 bool sign = operandTy.getIsSigned() || resultTy.getIsSigned();
3180 std::max(operandTy.getWidth() + (
sign && operandTy.isUnsigned()),
3181 resultTy.getWidth() + (
sign && resultTy.isUnsigned()));
3183 mlir::IntegerType encompassedLLVMTy = rewriter.getIntegerType(width);
3185 mlir::Value lhs = adaptor.getLhs();
3186 mlir::Value rhs = adaptor.getRhs();
3187 if (operandTy.getWidth() < width) {
3188 if (operandTy.isSigned()) {
3189 lhs = mlir::LLVM::SExtOp::create(rewriter, loc, encompassedLLVMTy, lhs);
3190 rhs = mlir::LLVM::SExtOp::create(rewriter, loc, encompassedLLVMTy, rhs);
3192 lhs = mlir::LLVM::ZExtOp::create(rewriter, loc, encompassedLLVMTy, lhs);
3193 rhs = mlir::LLVM::ZExtOp::create(rewriter, loc, encompassedLLVMTy, rhs);
3198 std::string intrinName = (
"llvm." + llvm::Twine(
sign ?
's' :
'u') + opStr +
3199 ".with.overflow.i" + llvm::Twine(width))
3201 auto intrinNameAttr = mlir::StringAttr::get(op.getContext(), intrinName);
3203 mlir::IntegerType overflowLLVMTy = rewriter.getI1Type();
3204 auto intrinRetTy = mlir::LLVM::LLVMStructType::getLiteral(
3205 rewriter.getContext(), {encompassedLLVMTy, overflowLLVMTy});
3207 auto callLLVMIntrinOp = mlir::LLVM::CallIntrinsicOp::create(
3208 rewriter, loc, intrinRetTy, intrinNameAttr, mlir::ValueRange{lhs, rhs});
3209 mlir::Value intrinRet = callLLVMIntrinOp.getResult(0);
3211 mlir::Value result = mlir::LLVM::ExtractValueOp::create(
3214 mlir::Value overflow = mlir::LLVM::ExtractValueOp::create(
3218 if (resultTy.getWidth() < width) {
3219 mlir::Type resultLLVMTy = typeConverter->convertType(resultTy);
3221 mlir::LLVM::TruncOp::create(rewriter, loc, resultLLVMTy, result);
3225 mlir::Value truncResultExt;
3226 if (resultTy.isSigned())
3227 truncResultExt = mlir::LLVM::SExtOp::create(
3228 rewriter, loc, encompassedLLVMTy, truncResult);
3230 truncResultExt = mlir::LLVM::ZExtOp::create(
3231 rewriter, loc, encompassedLLVMTy, truncResult);
3232 auto truncOverflow = mlir::LLVM::ICmpOp::create(
3233 rewriter, loc, mlir::LLVM::ICmpPredicate::ne, truncResultExt, result);
3235 result = truncResult;
3236 overflow = mlir::LLVM::OrOp::create(rewriter, loc, overflow, truncOverflow);
3239 mlir::Type boolLLVMTy =
3240 typeConverter->convertType(op.getOverflow().getType());
3241 if (boolLLVMTy != rewriter.getI1Type())
3242 overflow = mlir::LLVM::ZExtOp::create(rewriter, loc, boolLLVMTy, overflow);
3244 rewriter.replaceOp(op, mlir::ValueRange{result, overflow});
3246 return mlir::success();
3249mlir::LogicalResult CIRToLLVMAddOverflowOpLowering::matchAndRewrite(
3250 cir::AddOverflowOp op, OpAdaptor adaptor,
3251 mlir::ConversionPatternRewriter &rewriter)
const {
3255mlir::LogicalResult CIRToLLVMSubOverflowOpLowering::matchAndRewrite(
3256 cir::SubOverflowOp op, OpAdaptor adaptor,
3257 mlir::ConversionPatternRewriter &rewriter)
const {
3261mlir::LogicalResult CIRToLLVMMulOverflowOpLowering::matchAndRewrite(
3262 cir::MulOverflowOp op, OpAdaptor adaptor,
3263 mlir::ConversionPatternRewriter &rewriter)
const {
3267mlir::LogicalResult CIRToLLVMShiftOpLowering::matchAndRewrite(
3268 cir::ShiftOp op, OpAdaptor adaptor,
3269 mlir::ConversionPatternRewriter &rewriter)
const {
3270 assert((op.getValue().getType() == op.getType()) &&
3271 "inconsistent operands' types NYI");
3273 const mlir::Type llvmTy = getTypeConverter()->convertType(op.getType());
3274 mlir::Value amt = adaptor.getAmount();
3275 mlir::Value val = adaptor.getValue();
3277 auto cirAmtTy = mlir::dyn_cast<cir::IntType>(op.getAmount().getType());
3280 auto cirValTy = mlir::cast<cir::IntType>(op.getValue().getType());
3288 amt =
getLLVMIntCast(rewriter, amt, llvmTy,
true, cirAmtTy.getWidth(),
3289 cirValTy.getWidth());
3291 auto cirValVTy = mlir::cast<cir::VectorType>(op.getValue().getType());
3293 mlir::cast<cir::IntType>(cirValVTy.getElementType()).isUnsigned();
3297 if (op.getIsShiftleft()) {
3298 rewriter.replaceOpWithNewOp<mlir::LLVM::ShlOp>(op, llvmTy, val, amt);
3299 return mlir::success();
3303 rewriter.replaceOpWithNewOp<mlir::LLVM::LShrOp>(op, llvmTy, val, amt);
3305 rewriter.replaceOpWithNewOp<mlir::LLVM::AShrOp>(op, llvmTy, val, amt);
3306 return mlir::success();
3309mlir::LogicalResult CIRToLLVMSelectOpLowering::matchAndRewrite(
3310 cir::SelectOp op, OpAdaptor adaptor,
3311 mlir::ConversionPatternRewriter &rewriter)
const {
3312 auto getConstantBool = [](mlir::Value value) -> cir::BoolAttr {
3313 auto definingOp = value.getDefiningOp<cir::ConstantOp>();
3317 auto constValue = definingOp.getValueAttr<cir::BoolAttr>();
3327 if (mlir::isa<cir::BoolType>(op.getTrueValue().getType())) {
3328 cir::BoolAttr trueValue = getConstantBool(op.getTrueValue());
3329 cir::BoolAttr falseValue = getConstantBool(op.getFalseValue());
3330 if (falseValue && !falseValue.getValue()) {
3332 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(op, adaptor.getCondition(),
3333 adaptor.getTrueValue());
3334 return mlir::success();
3336 if (trueValue && trueValue.getValue()) {
3338 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(op, adaptor.getCondition(),
3339 adaptor.getFalseValue());
3340 return mlir::success();
3344 mlir::Value llvmCondition = adaptor.getCondition();
3345 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(
3346 op, llvmCondition, adaptor.getTrueValue(), adaptor.getFalseValue());
3348 return mlir::success();
3352 mlir::DataLayout &dataLayout) {
3353 converter.addConversion([&](cir::PointerType type) -> mlir::Type {
3354 mlir::ptr::MemorySpaceAttrInterface addrSpaceAttr = type.getAddrSpace();
3355 unsigned numericAS = 0;
3357 if (
auto langAsAttr =
3358 mlir::dyn_cast_if_present<cir::LangAddressSpaceAttr>(addrSpaceAttr))
3359 llvm_unreachable(
"lowering LangAddressSpaceAttr NYI");
3360 else if (
auto targetAsAttr =
3361 mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
3363 numericAS = targetAsAttr.getValue();
3364 return mlir::LLVM::LLVMPointerType::get(type.getContext(), numericAS);
3366 converter.addConversion([&](cir::VPtrType type) -> mlir::Type {
3368 return mlir::LLVM::LLVMPointerType::get(type.getContext());
3370 converter.addConversion([&](cir::ArrayType type) -> mlir::Type {
3373 return mlir::LLVM::LLVMArrayType::get(ty, type.getSize());
3375 converter.addConversion([&](cir::VectorType type) -> mlir::Type {
3376 const mlir::Type ty = converter.convertType(type.getElementType());
3377 return mlir::VectorType::get(type.getSize(), ty, {type.getIsScalable()});
3379 converter.addConversion([&](cir::BoolType type) -> mlir::Type {
3380 return mlir::IntegerType::get(type.getContext(), 1,
3381 mlir::IntegerType::Signless);
3383 converter.addConversion([&](cir::IntType type) -> mlir::Type {
3385 return mlir::IntegerType::get(type.getContext(), type.getWidth());
3387 converter.addConversion([&](cir::SingleType type) -> mlir::Type {
3388 return mlir::Float32Type::get(type.getContext());
3390 converter.addConversion([&](cir::DoubleType type) -> mlir::Type {
3391 return mlir::Float64Type::get(type.getContext());
3393 converter.addConversion([&](cir::FP80Type type) -> mlir::Type {
3394 return mlir::Float80Type::get(type.getContext());
3396 converter.addConversion([&](cir::FP128Type type) -> mlir::Type {
3397 return mlir::Float128Type::get(type.getContext());
3399 converter.addConversion([&](cir::LongDoubleType type) -> mlir::Type {
3400 return converter.convertType(type.getUnderlying());
3402 converter.addConversion([&](cir::FP16Type type) -> mlir::Type {
3403 return mlir::Float16Type::get(type.getContext());
3405 converter.addConversion([&](cir::BF16Type type) -> mlir::Type {
3406 return mlir::BFloat16Type::get(type.getContext());
3408 converter.addConversion([&](cir::ComplexType type) -> mlir::Type {
3411 mlir::Type elementTy = converter.convertType(type.getElementType());
3412 mlir::Type structFields[2] = {elementTy, elementTy};
3413 return mlir::LLVM::LLVMStructType::getLiteral(type.getContext(),
3416 converter.addConversion([&](cir::FuncType type) -> std::optional<mlir::Type> {
3417 auto result = converter.convertType(type.getReturnType());
3419 arguments.reserve(type.getNumInputs());
3420 if (converter.convertTypes(type.getInputs(), arguments).failed())
3421 return std::nullopt;
3422 auto varArg = type.isVarArg();
3423 return mlir::LLVM::LLVMFunctionType::get(result, arguments, varArg);
3425 converter.addConversion([&](cir::RecordType type) -> mlir::Type {
3428 switch (type.getKind()) {
3429 case cir::RecordType::Class:
3430 case cir::RecordType::Struct:
3431 for (mlir::Type ty : type.getMembers())
3435 case cir::RecordType::Union:
3436 if (type.getMembers().empty())
3438 if (
auto largestMember = type.getLargestMember(dataLayout))
3439 llvmMembers.push_back(
3441 if (type.getPadded()) {
3442 auto last = *type.getMembers().rbegin();
3443 llvmMembers.push_back(
3450 mlir::LLVM::LLVMStructType llvmStruct;
3451 if (type.getName()) {
3452 llvmStruct = mlir::LLVM::LLVMStructType::getIdentified(
3453 type.getContext(), type.getPrefixedName());
3454 if (llvmStruct.setBody(llvmMembers, type.getPacked()).failed())
3455 llvm_unreachable(
"Failed to set body of record");
3457 llvmStruct = mlir::LLVM::LLVMStructType::getLiteral(
3458 type.getContext(), llvmMembers, type.getPacked());
3463 converter.addConversion([&](cir::VoidType type) -> mlir::Type {
3464 return mlir::LLVM::LLVMVoidType::get(type.getContext());
3469 mlir::ModuleOp module, StringRef globalXtorName, StringRef llvmXtorName,
3470 llvm::function_ref<std::pair<StringRef, int>(mlir::Attribute)> createXtor) {
3472 for (
const mlir::NamedAttribute namedAttr : module->getAttrs()) {
3473 if (namedAttr.getName() == globalXtorName) {
3474 for (
auto attr : mlir::cast<mlir::ArrayAttr>(namedAttr.getValue()))
3475 globalXtors.emplace_back(createXtor(attr));
3480 if (globalXtors.empty())
3483 mlir::OpBuilder builder(module.getContext());
3484 builder.setInsertionPointToEnd(&module.getBodyRegion().back());
3488 auto ctorPFTy = mlir::LLVM::LLVMPointerType::get(builder.getContext());
3490 ctorStructFields.push_back(builder.getI32Type());
3491 ctorStructFields.push_back(ctorPFTy);
3492 ctorStructFields.push_back(ctorPFTy);
3494 auto ctorStructTy = mlir::LLVM::LLVMStructType::getLiteral(
3495 builder.getContext(), ctorStructFields);
3496 auto ctorStructArrayTy =
3497 mlir::LLVM::LLVMArrayType::get(ctorStructTy, globalXtors.size());
3499 mlir::Location loc =
module.getLoc();
3500 auto newGlobalOp = mlir::LLVM::GlobalOp::create(
3501 builder, loc, ctorStructArrayTy,
false,
3502 mlir::LLVM::Linkage::Appending, llvmXtorName, mlir::Attribute());
3504 builder.createBlock(&newGlobalOp.getRegion());
3505 builder.setInsertionPointToEnd(newGlobalOp.getInitializerBlock());
3507 mlir::Value result =
3508 mlir::LLVM::UndefOp::create(builder, loc, ctorStructArrayTy);
3510 for (
auto [index, fn] : llvm::enumerate(globalXtors)) {
3511 mlir::Value structInit =
3512 mlir::LLVM::UndefOp::create(builder, loc, ctorStructTy);
3513 mlir::Value initPriority = mlir::LLVM::ConstantOp::create(
3514 builder, loc, ctorStructFields[0], fn.second);
3515 mlir::Value initFuncAddr = mlir::LLVM::AddressOfOp::create(
3516 builder, loc, ctorStructFields[1], fn.first);
3517 mlir::Value initAssociate =
3518 mlir::LLVM::ZeroOp::create(builder, loc, ctorStructFields[2]);
3521 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
3522 initPriority, zero);
3523 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
3526 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
3528 result = mlir::LLVM::InsertValueOp::create(builder, loc, result, structInit,
3532 mlir::LLVM::ReturnOp::create(builder, loc, result);
3570 parent->walk([&](mlir::Block *blk) {
3571 if (blk->hasNoPredecessors() && !blk->isEntryBlock())
3572 unreachableBlocks.push_back(blk);
3575 std::set<mlir::Block *> visited;
3576 for (mlir::Block *root : unreachableBlocks) {
3579 std::deque<mlir::Block *> workList;
3580 workList.push_back(root);
3582 while (!workList.empty()) {
3583 mlir::Block *blk = workList.back();
3584 workList.pop_back();
3585 if (visited.count(blk))
3587 visited.emplace(blk);
3589 for (mlir::Operation &op : *blk)
3592 for (mlir::Block *succ : blk->getSuccessors())
3593 workList.push_back(succ);
3598mlir::LogicalResult CIRToLLVMObjSizeOpLowering::matchAndRewrite(
3599 cir::ObjSizeOp op, OpAdaptor adaptor,
3600 mlir::ConversionPatternRewriter &rewriter)
const {
3601 mlir::Type llvmResTy = getTypeConverter()->convertType(op.getType());
3602 mlir::Location loc = op->getLoc();
3604 mlir::IntegerType i1Ty = rewriter.getI1Type();
3606 auto i1Val = [&rewriter, &loc, &i1Ty](
bool val) {
3607 return mlir::LLVM::ConstantOp::create(rewriter, loc, i1Ty, val);
3614 i1Val(op.getNullunknown()),
3615 i1Val(op.getDynamic()),
3618 return mlir::LogicalResult::success();
3624 mlir::ModuleOp module = getOperation();
3625 mlir::OpBuilder opBuilder(module.getContext());
3626 for (
auto &[blockAddOp, blockInfo] :
3628 mlir::LLVM::BlockTagOp resolvedLabel =
3630 assert(resolvedLabel &&
"expected BlockTagOp to already be emitted");
3631 mlir::FlatSymbolRefAttr fnSym = blockInfo.getFunc();
3632 auto blkAddTag = mlir::LLVM::BlockAddressAttr::get(
3633 opBuilder.getContext(), fnSym, resolvedLabel.getTagAttr());
3634 blockAddOp.setBlockAddrAttr(blkAddTag);
3641 if (mlir::Attribute tripleAttr =
3642 module->getAttr(cir::CIRDialect::getTripleAttrName()))
3643 module->setAttr(mlir::LLVM::LLVMDialect::getTargetTripleAttrName(),
3646 if (mlir::Attribute asmAttr =
3647 module->getAttr(cir::CIRDialect::getModuleLevelAsmAttrName()))
3648 module->setAttr(mlir::LLVM::LLVMDialect::getModuleLevelAsmAttrName(),
3653 llvm::TimeTraceScope scope(
"Convert CIR to LLVM Pass");
3655 mlir::ModuleOp module = getOperation();
3656 mlir::DataLayout dl(module);
3657 mlir::LLVMTypeConverter converter(&getContext());
3665 mlir::RewritePatternSet patterns(&getContext());
3666 patterns.add<CIRToLLVMBlockAddressOpLowering, CIRToLLVMLabelOpLowering>(
3667 converter, patterns.getContext(), dl, blockInfoAddr);
3670#define GET_LLVM_LOWERING_PATTERNS_LIST
3671#include "clang/CIR/Dialect/IR/CIRLowering.inc"
3672#undef GET_LLVM_LOWERING_PATTERNS_LIST
3673 >(converter, patterns.getContext(), dl);
3677 mlir::ConversionTarget target(getContext());
3678 target.addLegalOp<mlir::ModuleOp>();
3679 target.addLegalDialect<mlir::LLVM::LLVMDialect>();
3680 target.addIllegalDialect<mlir::BuiltinDialect, cir::CIRDialect,
3681 mlir::func::FuncDialect>();
3684 ops.push_back(module);
3687 if (failed(applyPartialConversion(ops, target, std::move(patterns))))
3688 signalPassFailure();
3692 "llvm.global_ctors", [](mlir::Attribute
attr) {
3693 auto ctorAttr = mlir::cast<cir::GlobalCtorAttr>(
attr);
3694 return std::make_pair(ctorAttr.getName(),
3695 ctorAttr.getPriority());
3699 "llvm.global_dtors", [](mlir::Attribute
attr) {
3700 auto dtorAttr = mlir::cast<cir::GlobalDtorAttr>(
attr);
3701 return std::make_pair(dtorAttr.getName(),
3702 dtorAttr.getPriority());
3707mlir::LogicalResult CIRToLLVMBrOpLowering::matchAndRewrite(
3708 cir::BrOp op, OpAdaptor adaptor,
3709 mlir::ConversionPatternRewriter &rewriter)
const {
3710 rewriter.replaceOpWithNewOp<mlir::LLVM::BrOp>(op, adaptor.getOperands(),
3712 return mlir::LogicalResult::success();
3715mlir::LogicalResult CIRToLLVMGetMemberOpLowering::matchAndRewrite(
3716 cir::GetMemberOp op, OpAdaptor adaptor,
3717 mlir::ConversionPatternRewriter &rewriter)
const {
3718 mlir::Type llResTy = getTypeConverter()->convertType(op.getType());
3719 const auto recordTy =
3720 mlir::cast<cir::RecordType>(op.getAddrTy().getPointee());
3721 assert(recordTy &&
"expected record type");
3723 switch (recordTy.getKind()) {
3724 case cir::RecordType::Class:
3725 case cir::RecordType::Struct: {
3729 const mlir::Type elementTy = getTypeConverter()->convertType(recordTy);
3730 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, llResTy, elementTy,
3731 adaptor.getAddr(), offset);
3732 return mlir::success();
3734 case cir::RecordType::Union:
3737 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(op, llResTy,
3739 return mlir::success();
3743mlir::LogicalResult CIRToLLVMExtractMemberOpLowering::matchAndRewrite(
3744 cir::ExtractMemberOp op, OpAdaptor adaptor,
3745 mlir::ConversionPatternRewriter &rewriter)
const {
3746 std::int64_t indices[1] = {
static_cast<std::int64_t
>(op.getIndex())};
3748 mlir::Type recordTy = op.getRecord().getType();
3749 auto cirRecordTy = mlir::cast<cir::RecordType>(recordTy);
3750 switch (cirRecordTy.getKind()) {
3751 case cir::RecordType::Struct:
3752 case cir::RecordType::Class:
3753 rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractValueOp>(
3754 op, adaptor.getRecord(), indices);
3755 return mlir::success();
3757 case cir::RecordType::Union:
3758 op.emitError(
"cir.extract_member cannot extract member from a union");
3759 return mlir::failure();
3761 llvm_unreachable(
"Unexpected record kind");
3764mlir::LogicalResult CIRToLLVMInsertMemberOpLowering::matchAndRewrite(
3765 cir::InsertMemberOp op, OpAdaptor adaptor,
3766 mlir::ConversionPatternRewriter &rewriter)
const {
3767 std::int64_t indecies[1] = {
static_cast<std::int64_t
>(op.getIndex())};
3768 mlir::Type recordTy = op.getRecord().getType();
3770 if (
auto cirRecordTy = mlir::dyn_cast<cir::RecordType>(recordTy)) {
3771 if (cirRecordTy.getKind() == cir::RecordType::Union) {
3772 op.emitError(
"cir.update_member cannot update member of a union");
3773 return mlir::failure();
3777 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
3778 op, adaptor.getRecord(), adaptor.getValue(), indecies);
3779 return mlir::success();
3782mlir::LogicalResult CIRToLLVMUnreachableOpLowering::matchAndRewrite(
3783 cir::UnreachableOp op, OpAdaptor adaptor,
3784 mlir::ConversionPatternRewriter &rewriter)
const {
3785 rewriter.replaceOpWithNewOp<mlir::LLVM::UnreachableOp>(op);
3786 return mlir::success();
3790 mlir::Operation *srcOp, llvm::StringRef fnName,
3792 auto modOp = srcOp->getParentOfType<mlir::ModuleOp>();
3793 auto enclosingFnOp = srcOp->getParentOfType<mlir::LLVM::LLVMFuncOp>();
3794 mlir::Operation *sourceSymbol =
3795 mlir::SymbolTable::lookupSymbolIn(modOp, fnName);
3796 if (!sourceSymbol) {
3797 mlir::OpBuilder::InsertionGuard guard(rewriter);
3798 rewriter.setInsertionPoint(enclosingFnOp);
3799 mlir::LLVM::LLVMFuncOp::create(rewriter, srcOp->getLoc(), fnName, fnTy);
3803mlir::LogicalResult CIRToLLVMThrowOpLowering::matchAndRewrite(
3804 cir::ThrowOp op, OpAdaptor adaptor,
3805 mlir::ConversionPatternRewriter &rewriter)
const {
3806 mlir::Location loc = op.getLoc();
3807 auto voidTy = mlir::LLVM::LLVMVoidType::get(getContext());
3809 if (op.rethrows()) {
3810 auto funcTy = mlir::LLVM::LLVMFunctionType::get(voidTy, {});
3813 const llvm::StringRef functionName =
"__cxa_rethrow";
3816 auto cxaRethrow = mlir::LLVM::CallOp::create(
3817 rewriter, loc, mlir::TypeRange{}, functionName);
3819 rewriter.replaceOp(op, cxaRethrow);
3820 return mlir::success();
3823 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3824 auto fnTy = mlir::LLVM::LLVMFunctionType::get(
3825 voidTy, {llvmPtrTy, llvmPtrTy, llvmPtrTy});
3828 const llvm::StringRef fnName =
"__cxa_throw";
3831 mlir::Value typeInfo = mlir::LLVM::AddressOfOp::create(
3832 rewriter, loc, mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
3833 adaptor.getTypeInfoAttr());
3837 dtor = mlir::LLVM::AddressOfOp::create(rewriter, loc, llvmPtrTy,
3838 adaptor.getDtorAttr());
3840 dtor = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmPtrTy);
3843 auto cxaThrowCall = mlir::LLVM::CallOp::create(
3844 rewriter, loc, mlir::TypeRange{}, fnName,
3845 mlir::ValueRange{adaptor.getExceptionPtr(), typeInfo, dtor});
3847 rewriter.replaceOp(op, cxaThrowCall);
3848 return mlir::success();
3851mlir::LogicalResult CIRToLLVMAllocExceptionOpLowering::matchAndRewrite(
3852 cir::AllocExceptionOp op, OpAdaptor adaptor,
3853 mlir::ConversionPatternRewriter &rewriter)
const {
3855 StringRef fnName =
"__cxa_allocate_exception";
3856 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3857 auto int64Ty = mlir::IntegerType::get(rewriter.getContext(), 64);
3858 auto fnTy = mlir::LLVM::LLVMFunctionType::get(llvmPtrTy, {int64Ty});
3861 auto exceptionSize = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
3862 adaptor.getSizeAttr());
3864 auto allocaExceptionCall = mlir::LLVM::CallOp::create(
3865 rewriter, op.getLoc(), mlir::TypeRange{llvmPtrTy}, fnName,
3866 mlir::ValueRange{exceptionSize});
3868 rewriter.replaceOp(op, allocaExceptionCall);
3869 return mlir::success();
3872static mlir::LLVM::LLVMStructType
3875 mlir::MLIRContext *ctx = rewriter.getContext();
3876 auto llvmPtr = mlir::LLVM::LLVMPointerType::get(ctx);
3878 return mlir::LLVM::LLVMStructType::getLiteral(ctx, structFields);
3881mlir::LogicalResult CIRToLLVMEhInflightOpLowering::matchAndRewrite(
3882 cir::EhInflightOp op, OpAdaptor adaptor,
3883 mlir::ConversionPatternRewriter &rewriter)
const {
3884 auto llvmFn = op->getParentOfType<mlir::LLVM::LLVMFuncOp>();
3885 assert(llvmFn &&
"expected LLVM function parent");
3886 mlir::Block *entryBlock = &llvmFn.getRegion().front();
3887 assert(entryBlock->isEntryBlock());
3889 mlir::ArrayAttr catchListAttr = op.getCatchTypeListAttr();
3890 mlir::SmallVector<mlir::Value> catchSymAddrs;
3892 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3893 mlir::Location loc = op.getLoc();
3898 if (catchListAttr) {
3901 for (mlir::Attribute catchAttr : catchListAttr) {
3902 auto symAttr = cast<mlir::FlatSymbolRefAttr>(catchAttr);
3905 mlir::OpBuilder::InsertionGuard guard(rewriter);
3906 rewriter.setInsertionPointToStart(entryBlock);
3907 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
3908 rewriter, loc, llvmPtrTy, symAttr.getValue());
3909 catchSymAddrs.push_back(addrOp);
3911 }
else if (!op.getCleanup()) {
3915 mlir::OpBuilder::InsertionGuard guard(rewriter);
3916 rewriter.setInsertionPointToStart(entryBlock);
3917 mlir::Value nullOp = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmPtrTy);
3918 catchSymAddrs.push_back(nullOp);
3923 mlir::LLVM::LLVMStructType llvmLandingPadStructTy =
3925 auto landingPadOp = mlir::LLVM::LandingpadOp::create(
3926 rewriter, loc, llvmLandingPadStructTy, catchSymAddrs);
3928 if (op.getCleanup())
3929 landingPadOp.setCleanup(
true);
3932 mlir::LLVM::ExtractValueOp::create(rewriter, loc, landingPadOp, 0);
3933 mlir::Value selector =
3934 mlir::LLVM::ExtractValueOp::create(rewriter, loc, landingPadOp, 1);
3935 rewriter.replaceOp(op, mlir::ValueRange{slot, selector});
3937 return mlir::success();
3940mlir::LogicalResult CIRToLLVMResumeFlatOpLowering::matchAndRewrite(
3941 cir::ResumeFlatOp op, OpAdaptor adaptor,
3942 mlir::ConversionPatternRewriter &rewriter)
const {
3947 mlir::Value poison = mlir::LLVM::PoisonOp::create(rewriter, op.getLoc(),
3948 llvmLandingPadStructTy);
3950 SmallVector<int64_t> slotIdx = {0};
3951 mlir::Value slot = mlir::LLVM::InsertValueOp::create(
3952 rewriter, op.getLoc(), poison, adaptor.getExceptionPtr(), slotIdx);
3954 SmallVector<int64_t> selectorIdx = {1};
3955 mlir::Value selector = mlir::LLVM::InsertValueOp::create(
3956 rewriter, op.getLoc(), slot, adaptor.getTypeId(), selectorIdx);
3958 rewriter.replaceOpWithNewOp<mlir::LLVM::ResumeOp>(op, selector);
3959 return mlir::success();
3962mlir::LogicalResult CIRToLLVMEhTypeIdOpLowering::matchAndRewrite(
3963 cir::EhTypeIdOp op, OpAdaptor adaptor,
3964 mlir::ConversionPatternRewriter &rewriter)
const {
3965 mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
3966 rewriter, op.getLoc(),
3967 mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
3968 op.getTypeSymAttr());
3969 rewriter.replaceOpWithNewOp<mlir::LLVM::EhTypeidForOp>(
3970 op, rewriter.getI32Type(), addrOp);
3971 return mlir::success();
3974mlir::LogicalResult CIRToLLVMEhSetjmpOpLowering::matchAndRewrite(
3975 cir::EhSetjmpOp op, OpAdaptor adaptor,
3976 mlir::ConversionPatternRewriter &rewriter)
const {
3977 mlir::Type returnType = typeConverter->convertType(op.getType());
3978 mlir::LLVM::CallIntrinsicOp newOp =
3980 returnType, adaptor.getEnv());
3981 rewriter.replaceOp(op, newOp);
3982 return mlir::success();
3985mlir::LogicalResult CIRToLLVMEhLongjmpOpLowering::matchAndRewrite(
3986 cir::EhLongjmpOp op, OpAdaptor adaptor,
3987 mlir::ConversionPatternRewriter &rewriter)
const {
3989 {}, adaptor.getOperands());
3990 return mlir::success();
3993mlir::LogicalResult CIRToLLVMTrapOpLowering::matchAndRewrite(
3994 cir::TrapOp op, OpAdaptor adaptor,
3995 mlir::ConversionPatternRewriter &rewriter)
const {
3996 mlir::Location loc = op->getLoc();
3997 rewriter.eraseOp(op);
3999 mlir::LLVM::Trap::create(rewriter, loc);
4004 mlir::LLVM::UnreachableOp::create(rewriter, loc);
4006 return mlir::success();
4011 mlir::ConversionPatternRewriter &rewriter,
4012 const mlir::TypeConverter *converter,
4013 mlir::FlatSymbolRefAttr nameAttr, mlir::Type &eltType) {
4014 auto module = op->getParentOfType<mlir::ModuleOp>();
4015 mlir::Operation *symbol = mlir::SymbolTable::lookupSymbolIn(module, nameAttr);
4016 if (
auto llvmSymbol = mlir::dyn_cast<mlir::LLVM::GlobalOp>(symbol)) {
4017 eltType = llvmSymbol.getType();
4018 }
else if (
auto cirSymbol = mlir::dyn_cast<cir::GlobalOp>(symbol)) {
4019 eltType = converter->convertType(cirSymbol.getSymType());
4021 op->emitError() <<
"unexpected symbol type for " << symbol;
4025 return mlir::LLVM::AddressOfOp::create(
4026 rewriter, op->getLoc(),
4027 mlir::LLVM::LLVMPointerType::get(op->getContext()), nameAttr.getValue());
4030mlir::LogicalResult CIRToLLVMVTableAddrPointOpLowering::matchAndRewrite(
4031 cir::VTableAddrPointOp op, OpAdaptor adaptor,
4032 mlir::ConversionPatternRewriter &rewriter)
const {
4033 const mlir::TypeConverter *converter = getTypeConverter();
4034 mlir::Type targetType = converter->convertType(op.getType());
4038 op.getNameAttr(), eltType);
4040 return op.emitError() <<
"Unable to get value for vtable symbol";
4043 0, op.getAddressPointAttr().getIndex(),
4044 op.getAddressPointAttr().getOffset()};
4046 assert(eltType &&
"Shouldn't ever be missing an eltType here");
4047 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
4048 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
4049 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, targetType, eltType,
4050 symAddr, offsets, inboundsNuw);
4051 return mlir::success();
4054mlir::LogicalResult CIRToLLVMVTableGetVPtrOpLowering::matchAndRewrite(
4055 cir::VTableGetVPtrOp op, OpAdaptor adaptor,
4056 mlir::ConversionPatternRewriter &rewriter)
const {
4060 mlir::Value srcVal = adaptor.getSrc();
4061 rewriter.replaceOp(op, srcVal);
4062 return mlir::success();
4065mlir::LogicalResult CIRToLLVMVTableGetVirtualFnAddrOpLowering::matchAndRewrite(
4066 cir::VTableGetVirtualFnAddrOp op, OpAdaptor adaptor,
4067 mlir::ConversionPatternRewriter &rewriter)
const {
4068 mlir::Type targetType = getTypeConverter()->convertType(op.getType());
4069 auto eltType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4070 llvm::SmallVector<mlir::LLVM::GEPArg> offsets =
4071 llvm::SmallVector<mlir::LLVM::GEPArg>{op.getIndex()};
4072 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
4073 op, targetType, eltType, adaptor.getVptr(), offsets,
4074 mlir::LLVM::GEPNoWrapFlags::inbounds);
4075 return mlir::success();
4078mlir::LogicalResult CIRToLLVMVTTAddrPointOpLowering::matchAndRewrite(
4079 cir::VTTAddrPointOp op, OpAdaptor adaptor,
4080 mlir::ConversionPatternRewriter &rewriter)
const {
4081 const mlir::Type resultType = getTypeConverter()->convertType(op.getType());
4082 llvm::SmallVector<mlir::LLVM::GEPArg> offsets;
4084 mlir::Value llvmAddr = adaptor.getSymAddr();
4086 if (op.getSymAddr()) {
4087 if (op.getOffset() == 0) {
4088 rewriter.replaceOp(op, {llvmAddr});
4089 return mlir::success();
4092 offsets.push_back(adaptor.getOffset());
4093 eltType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4096 op.getNameAttr(), eltType);
4097 assert(eltType &&
"Shouldn't ever be missing an eltType here");
4098 offsets.push_back(0);
4099 offsets.push_back(adaptor.getOffset());
4101 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
4102 op, resultType, eltType, llvmAddr, offsets,
4103 mlir::LLVM::GEPNoWrapFlags::inbounds);
4104 return mlir::success();
4107mlir::LogicalResult CIRToLLVMStackSaveOpLowering::matchAndRewrite(
4108 cir::StackSaveOp op, OpAdaptor adaptor,
4109 mlir::ConversionPatternRewriter &rewriter)
const {
4110 const mlir::Type ptrTy = getTypeConverter()->convertType(op.getType());
4111 rewriter.replaceOpWithNewOp<mlir::LLVM::StackSaveOp>(op, ptrTy);
4112 return mlir::success();
4115mlir::LogicalResult CIRToLLVMStackRestoreOpLowering::matchAndRewrite(
4116 cir::StackRestoreOp op, OpAdaptor adaptor,
4117 mlir::ConversionPatternRewriter &rewriter)
const {
4118 rewriter.replaceOpWithNewOp<mlir::LLVM::StackRestoreOp>(op, adaptor.getPtr());
4119 return mlir::success();
4122mlir::LogicalResult CIRToLLVMVecCreateOpLowering::matchAndRewrite(
4123 cir::VecCreateOp op, OpAdaptor adaptor,
4124 mlir::ConversionPatternRewriter &rewriter)
const {
4127 const auto vecTy = mlir::cast<cir::VectorType>(op.getType());
4128 const mlir::Type llvmTy = typeConverter->convertType(vecTy);
4129 const mlir::Location loc = op.getLoc();
4130 mlir::Value result = mlir::LLVM::PoisonOp::create(rewriter, loc, llvmTy);
4131 assert(vecTy.getSize() == op.getElements().size() &&
4132 "cir.vec.create op count doesn't match vector type elements count");
4134 for (uint64_t i = 0; i < vecTy.getSize(); ++i) {
4135 const mlir::Value indexValue =
4136 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
4137 result = mlir::LLVM::InsertElementOp::create(
4138 rewriter, loc, result, adaptor.getElements()[i], indexValue);
4141 rewriter.replaceOp(op, result);
4142 return mlir::success();
4145mlir::LogicalResult CIRToLLVMVecExtractOpLowering::matchAndRewrite(
4146 cir::VecExtractOp op, OpAdaptor adaptor,
4147 mlir::ConversionPatternRewriter &rewriter)
const {
4148 rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractElementOp>(
4149 op, adaptor.getVec(), adaptor.getIndex());
4150 return mlir::success();
4153mlir::LogicalResult CIRToLLVMVecInsertOpLowering::matchAndRewrite(
4154 cir::VecInsertOp op, OpAdaptor adaptor,
4155 mlir::ConversionPatternRewriter &rewriter)
const {
4156 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertElementOp>(
4157 op, adaptor.getVec(), adaptor.getValue(), adaptor.getIndex());
4158 return mlir::success();
4161mlir::LogicalResult CIRToLLVMVecCmpOpLowering::matchAndRewrite(
4162 cir::VecCmpOp op, OpAdaptor adaptor,
4163 mlir::ConversionPatternRewriter &rewriter)
const {
4164 mlir::Type elementType = elementTypeIfVector(op.getLhs().getType());
4165 mlir::Value bitResult;
4166 if (
auto intType = mlir::dyn_cast<cir::IntType>(elementType)) {
4167 bitResult = mlir::LLVM::ICmpOp::create(
4168 rewriter, op.getLoc(),
4170 adaptor.getLhs(), adaptor.getRhs());
4171 }
else if (mlir::isa<cir::FPTypeInterface>(elementType)) {
4172 bitResult = mlir::LLVM::FCmpOp::create(
4174 adaptor.getLhs(), adaptor.getRhs());
4176 return op.emitError() <<
"unsupported type for VecCmpOp: " << elementType;
4182 if (cast<cir::IntType>(cast<cir::VectorType>(op.getType()).getElementType())
4184 rewriter.replaceOpWithNewOp<mlir::LLVM::SExtOp>(
4185 op, typeConverter->convertType(op.getType()), bitResult);
4187 rewriter.replaceOp(op, bitResult);
4188 return mlir::success();
4191mlir::LogicalResult CIRToLLVMVecSplatOpLowering::matchAndRewrite(
4192 cir::VecSplatOp op, OpAdaptor adaptor,
4193 mlir::ConversionPatternRewriter &rewriter)
const {
4199 cir::VectorType vecTy = op.getType();
4200 mlir::Type llvmTy = typeConverter->convertType(vecTy);
4201 mlir::Location loc = op.getLoc();
4202 mlir::Value poison = mlir::LLVM::PoisonOp::create(rewriter, loc, llvmTy);
4204 mlir::Value elementValue = adaptor.getValue();
4205 if (elementValue.getDefiningOp<mlir::LLVM::PoisonOp>()) {
4208 rewriter.replaceOp(op, poison);
4209 return mlir::success();
4212 if (
auto constValue = elementValue.getDefiningOp<mlir::LLVM::ConstantOp>()) {
4213 if (
auto intAttr = dyn_cast<mlir::IntegerAttr>(constValue.getValue())) {
4214 mlir::DenseIntElementsAttr denseVec = mlir::DenseIntElementsAttr::get(
4215 mlir::cast<mlir::ShapedType>(llvmTy), intAttr.getValue());
4216 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
4217 op, denseVec.getType(), denseVec);
4218 return mlir::success();
4221 if (
auto fpAttr = dyn_cast<mlir::FloatAttr>(constValue.getValue())) {
4222 mlir::DenseFPElementsAttr denseVec = mlir::DenseFPElementsAttr::get(
4223 mlir::cast<mlir::ShapedType>(llvmTy), fpAttr.getValue());
4224 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
4225 op, denseVec.getType(), denseVec);
4226 return mlir::success();
4230 mlir::Value indexValue =
4231 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), 0);
4232 mlir::Value oneElement = mlir::LLVM::InsertElementOp::create(
4233 rewriter, loc, poison, elementValue, indexValue);
4234 SmallVector<int32_t> zeroValues(vecTy.getSize(), 0);
4235 rewriter.replaceOpWithNewOp<mlir::LLVM::ShuffleVectorOp>(op, oneElement,
4236 poison, zeroValues);
4237 return mlir::success();
4240mlir::LogicalResult CIRToLLVMVecShuffleOpLowering::matchAndRewrite(
4241 cir::VecShuffleOp op, OpAdaptor adaptor,
4242 mlir::ConversionPatternRewriter &rewriter)
const {
4246 SmallVector<int, 8> indices;
4248 op.getIndices().begin(), op.getIndices().end(),
4249 std::back_inserter(indices), [](mlir::Attribute intAttr) {
4250 return mlir::cast<cir::IntAttr>(intAttr).getValue().getSExtValue();
4252 rewriter.replaceOpWithNewOp<mlir::LLVM::ShuffleVectorOp>(
4253 op, adaptor.getVec1(), adaptor.getVec2(), indices);
4254 return mlir::success();
4257mlir::LogicalResult CIRToLLVMVecShuffleDynamicOpLowering::matchAndRewrite(
4258 cir::VecShuffleDynamicOp op, OpAdaptor adaptor,
4259 mlir::ConversionPatternRewriter &rewriter)
const {
4271 mlir::Location loc = op.getLoc();
4272 mlir::Value input = adaptor.getVec();
4273 mlir::Type llvmIndexVecType =
4274 getTypeConverter()->convertType(op.getIndices().getType());
4275 mlir::Type llvmIndexType = getTypeConverter()->convertType(
4276 elementTypeIfVector(op.getIndices().getType()));
4278 mlir::cast<cir::VectorType>(op.getVec().getType()).getSize();
4280 uint64_t maskBits = llvm::NextPowerOf2(numElements - 1) - 1;
4281 mlir::Value maskValue = mlir::LLVM::ConstantOp::create(
4282 rewriter, loc, llvmIndexType,
4283 rewriter.getIntegerAttr(llvmIndexType, maskBits));
4284 mlir::Value maskVector =
4285 mlir::LLVM::UndefOp::create(rewriter, loc, llvmIndexVecType);
4287 for (uint64_t i = 0; i < numElements; ++i) {
4288 mlir::Value idxValue =
4289 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
4290 maskVector = mlir::LLVM::InsertElementOp::create(rewriter, loc, maskVector,
4291 maskValue, idxValue);
4294 mlir::Value maskedIndices = mlir::LLVM::AndOp::create(
4295 rewriter, loc, llvmIndexVecType, adaptor.getIndices(), maskVector);
4296 mlir::Value result = mlir::LLVM::UndefOp::create(
4297 rewriter, loc, getTypeConverter()->convertType(op.getVec().getType()));
4298 for (uint64_t i = 0; i < numElements; ++i) {
4299 mlir::Value iValue =
4300 mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), i);
4301 mlir::Value indexValue = mlir::LLVM::ExtractElementOp::create(
4302 rewriter, loc, maskedIndices, iValue);
4303 mlir::Value valueAtIndex =
4304 mlir::LLVM::ExtractElementOp::create(rewriter, loc, input, indexValue);
4305 result = mlir::LLVM::InsertElementOp::create(rewriter, loc, result,
4306 valueAtIndex, iValue);
4308 rewriter.replaceOp(op, result);
4309 return mlir::success();
4312mlir::LogicalResult CIRToLLVMVecTernaryOpLowering::matchAndRewrite(
4313 cir::VecTernaryOp op, OpAdaptor adaptor,
4314 mlir::ConversionPatternRewriter &rewriter)
const {
4316 mlir::Value bitVec = mlir::LLVM::ICmpOp::create(
4317 rewriter, op.getLoc(), mlir::LLVM::ICmpPredicate::ne, adaptor.getCond(),
4318 mlir::LLVM::ZeroOp::create(
4319 rewriter, op.getCond().getLoc(),
4320 typeConverter->convertType(op.getCond().getType())));
4321 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(
4322 op, bitVec, adaptor.getLhs(), adaptor.getRhs());
4323 return mlir::success();
4326mlir::LogicalResult CIRToLLVMComplexAddOpLowering::matchAndRewrite(
4327 cir::ComplexAddOp op, OpAdaptor adaptor,
4328 mlir::ConversionPatternRewriter &rewriter)
const {
4329 mlir::Value lhs = adaptor.getLhs();
4330 mlir::Value rhs = adaptor.getRhs();
4331 mlir::Location loc = op.getLoc();
4333 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
4334 mlir::Type complexElemTy =
4335 getTypeConverter()->convertType(
complexType.getElementType());
4336 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
4337 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{0}));
4338 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
4339 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{1}));
4340 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
4341 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{0}));
4342 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
4343 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{1}));
4345 mlir::Value newReal;
4346 mlir::Value newImag;
4347 if (complexElemTy.isInteger()) {
4348 newReal = mlir::LLVM::AddOp::create(rewriter, loc, complexElemTy, lhsReal,
4350 newImag = mlir::LLVM::AddOp::create(rewriter, loc, complexElemTy, lhsImag,
4355 newReal = mlir::LLVM::FAddOp::create(rewriter, loc, complexElemTy, lhsReal,
4357 newImag = mlir::LLVM::FAddOp::create(rewriter, loc, complexElemTy, lhsImag,
4361 mlir::Type complexLLVMTy =
4362 getTypeConverter()->convertType(op.getResult().getType());
4363 auto initialComplex =
4364 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), complexLLVMTy);
4366 auto realComplex = mlir::LLVM::InsertValueOp::create(
4367 rewriter, op->getLoc(), initialComplex, newReal, ArrayRef(int64_t{0}));
4369 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
4370 op, realComplex, newImag, ArrayRef(int64_t{1}));
4372 return mlir::success();
4375mlir::LogicalResult CIRToLLVMComplexCreateOpLowering::matchAndRewrite(
4376 cir::ComplexCreateOp op, OpAdaptor adaptor,
4377 mlir::ConversionPatternRewriter &rewriter)
const {
4378 mlir::Type complexLLVMTy =
4379 getTypeConverter()->convertType(op.getResult().getType());
4380 auto initialComplex =
4381 mlir::LLVM::UndefOp::create(rewriter, op->getLoc(), complexLLVMTy);
4383 auto realComplex = mlir::LLVM::InsertValueOp::create(
4384 rewriter, op->getLoc(), initialComplex, adaptor.getReal(),
4385 ArrayRef(int64_t{0}));
4387 auto complex = mlir::LLVM::InsertValueOp::create(
4388 rewriter, op->getLoc(), realComplex, adaptor.getImag(),
4389 ArrayRef(int64_t{1}));
4391 rewriter.replaceOp(op, complex);
4392 return mlir::success();
4395mlir::LogicalResult CIRToLLVMComplexRealOpLowering::matchAndRewrite(
4396 cir::ComplexRealOp op, OpAdaptor adaptor,
4397 mlir::ConversionPatternRewriter &rewriter)
const {
4398 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
4399 mlir::Value operand = adaptor.getOperand();
4400 if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) {
4401 operand = mlir::LLVM::ExtractValueOp::create(
4402 rewriter, op.getLoc(), resultLLVMTy, operand,
4403 llvm::ArrayRef<std::int64_t>{0});
4405 rewriter.replaceOp(op, operand);
4406 return mlir::success();
4409mlir::LogicalResult CIRToLLVMComplexSubOpLowering::matchAndRewrite(
4410 cir::ComplexSubOp op, OpAdaptor adaptor,
4411 mlir::ConversionPatternRewriter &rewriter)
const {
4412 mlir::Value lhs = adaptor.getLhs();
4413 mlir::Value rhs = adaptor.getRhs();
4414 mlir::Location loc = op.getLoc();
4416 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
4417 mlir::Type complexElemTy =
4418 getTypeConverter()->convertType(
complexType.getElementType());
4419 auto lhsReal = mlir::LLVM::ExtractValueOp::create(
4420 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{0}));
4421 auto lhsImag = mlir::LLVM::ExtractValueOp::create(
4422 rewriter, loc, complexElemTy, lhs, ArrayRef(int64_t{1}));
4423 auto rhsReal = mlir::LLVM::ExtractValueOp::create(
4424 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{0}));
4425 auto rhsImag = mlir::LLVM::ExtractValueOp::create(
4426 rewriter, loc, complexElemTy, rhs, ArrayRef(int64_t{1}));
4428 mlir::Value newReal;
4429 mlir::Value newImag;
4430 if (complexElemTy.isInteger()) {
4431 newReal = mlir::LLVM::SubOp::create(rewriter, loc, complexElemTy, lhsReal,
4433 newImag = mlir::LLVM::SubOp::create(rewriter, loc, complexElemTy, lhsImag,
4438 newReal = mlir::LLVM::FSubOp::create(rewriter, loc, complexElemTy, lhsReal,
4440 newImag = mlir::LLVM::FSubOp::create(rewriter, loc, complexElemTy, lhsImag,
4444 mlir::Type complexLLVMTy =
4445 getTypeConverter()->convertType(op.getResult().getType());
4446 auto initialComplex =
4447 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), complexLLVMTy);
4449 auto realComplex = mlir::LLVM::InsertValueOp::create(
4450 rewriter, op->getLoc(), initialComplex, newReal, ArrayRef(int64_t{0}));
4452 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(
4453 op, realComplex, newImag, ArrayRef(int64_t{1}));
4455 return mlir::success();
4458mlir::LogicalResult CIRToLLVMComplexImagOpLowering::matchAndRewrite(
4459 cir::ComplexImagOp op, OpAdaptor adaptor,
4460 mlir::ConversionPatternRewriter &rewriter)
const {
4461 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
4462 mlir::Value operand = adaptor.getOperand();
4463 mlir::Location loc = op.getLoc();
4465 if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) {
4466 operand = mlir::LLVM::ExtractValueOp::create(
4467 rewriter, loc, resultLLVMTy, operand, llvm::ArrayRef<std::int64_t>{1});
4469 mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(resultLLVMTy);
4471 mlir::LLVM::ConstantOp::create(rewriter, loc, resultLLVMTy, zeroAttr);
4474 rewriter.replaceOp(op, operand);
4475 return mlir::success();
4479 mlir::MLIRContext *context,
4480 unsigned &storageSize) {
4481 return TypeSwitch<mlir::Type, mlir::IntegerType>(storageType)
4482 .Case<cir::ArrayType>([&](cir::ArrayType atTy) {
4483 storageSize = atTy.getSize() * 8;
4484 return mlir::IntegerType::get(context, storageSize);
4486 .Case<cir::IntType>([&](cir::IntType intTy) {
4487 storageSize = intTy.getWidth();
4488 return mlir::IntegerType::get(context, storageSize);
4490 .Default([](mlir::Type) -> mlir::IntegerType {
4492 "Either ArrayType or IntType expected for bitfields storage");
4496mlir::LogicalResult CIRToLLVMSetBitfieldOpLowering::matchAndRewrite(
4497 cir::SetBitfieldOp op, OpAdaptor adaptor,
4498 mlir::ConversionPatternRewriter &rewriter)
const {
4499 mlir::OpBuilder::InsertionGuard guard(rewriter);
4500 rewriter.setInsertionPoint(op);
4502 cir::BitfieldInfoAttr info = op.getBitfieldInfo();
4503 uint64_t size = info.getSize();
4504 uint64_t offset = info.getOffset();
4505 mlir::Type storageType = info.getStorageType();
4506 mlir::MLIRContext *context = storageType.getContext();
4508 unsigned storageSize = 0;
4510 mlir::IntegerType intType =
4513 mlir::Value srcVal =
createIntCast(rewriter, adaptor.getSrc(), intType);
4514 unsigned srcWidth = storageSize;
4515 mlir::Value resultVal = srcVal;
4517 if (storageSize != size) {
4518 assert(storageSize > size &&
"Invalid bitfield size.");
4520 mlir::Value val = mlir::LLVM::LoadOp::create(
4521 rewriter, op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(),
4522 op.getIsVolatile());
4525 createAnd(rewriter, srcVal, llvm::APInt::getLowBitsSet(srcWidth, size));
4527 srcVal =
createShL(rewriter, srcVal, offset);
4531 ~llvm::APInt::getBitsSet(srcWidth, offset, offset + size));
4534 srcVal = mlir::LLVM::OrOp::create(rewriter, op.getLoc(), val, srcVal);
4537 mlir::LLVM::StoreOp::create(rewriter, op.getLoc(), srcVal, adaptor.getAddr(),
4538 op.getAlignment(), op.getIsVolatile());
4540 mlir::Type resultTy = getTypeConverter()->convertType(op.getType());
4542 if (info.getIsSigned()) {
4543 assert(size <= storageSize);
4544 unsigned highBits = storageSize - size;
4547 resultVal =
createShL(rewriter, resultVal, highBits);
4548 resultVal =
createAShR(rewriter, resultVal, highBits);
4553 mlir::cast<mlir::IntegerType>(resultTy),
4554 info.getIsSigned());
4556 rewriter.replaceOp(op, resultVal);
4557 return mlir::success();
4560mlir::LogicalResult CIRToLLVMComplexImagPtrOpLowering::matchAndRewrite(
4561 cir::ComplexImagPtrOp op, OpAdaptor adaptor,
4562 mlir::ConversionPatternRewriter &rewriter)
const {
4563 cir::PointerType operandTy = op.getOperand().getType();
4564 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
4565 mlir::Type elementLLVMTy =
4566 getTypeConverter()->convertType(operandTy.getPointee());
4568 mlir::LLVM::GEPArg gepIndices[2] = {{0}, {1}};
4569 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
4570 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
4571 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
4572 op, resultLLVMTy, elementLLVMTy, adaptor.getOperand(), gepIndices,
4574 return mlir::success();
4577mlir::LogicalResult CIRToLLVMComplexRealPtrOpLowering::matchAndRewrite(
4578 cir::ComplexRealPtrOp op, OpAdaptor adaptor,
4579 mlir::ConversionPatternRewriter &rewriter)
const {
4580 cir::PointerType operandTy = op.getOperand().getType();
4581 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
4582 mlir::Type elementLLVMTy =
4583 getTypeConverter()->convertType(operandTy.getPointee());
4585 mlir::LLVM::GEPArg gepIndices[2] = {0, 0};
4586 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
4587 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
4588 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
4589 op, resultLLVMTy, elementLLVMTy, adaptor.getOperand(), gepIndices,
4591 return mlir::success();
4594mlir::LogicalResult CIRToLLVMGetBitfieldOpLowering::matchAndRewrite(
4595 cir::GetBitfieldOp op, OpAdaptor adaptor,
4596 mlir::ConversionPatternRewriter &rewriter)
const {
4598 mlir::OpBuilder::InsertionGuard guard(rewriter);
4599 rewriter.setInsertionPoint(op);
4601 cir::BitfieldInfoAttr info = op.getBitfieldInfo();
4603 uint64_t offset = info.getOffset();
4604 mlir::Type storageType = info.getStorageType();
4605 mlir::MLIRContext *context = storageType.getContext();
4606 unsigned storageSize = 0;
4608 mlir::IntegerType intType =
4611 mlir::Value val = mlir::LLVM::LoadOp::create(
4612 rewriter, op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(),
4613 op.getIsVolatile());
4614 val = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), intType, val);
4616 if (info.getIsSigned()) {
4617 assert(
static_cast<unsigned>(offset + size) <= storageSize);
4618 unsigned highBits = storageSize - offset - size;
4619 val =
createShL(rewriter, val, highBits);
4620 val =
createAShR(rewriter, val, offset + highBits);
4624 if (
static_cast<unsigned>(offset) + size < storageSize)
4626 llvm::APInt::getLowBitsSet(storageSize, size));
4629 mlir::Type resTy = getTypeConverter()->convertType(op.getType());
4631 rewriter, val, mlir::cast<mlir::IntegerType>(resTy), info.getIsSigned());
4632 rewriter.replaceOp(op, newOp);
4633 return mlir::success();
4636mlir::LogicalResult CIRToLLVMIsConstantOpLowering::matchAndRewrite(
4637 cir::IsConstantOp op, OpAdaptor adaptor,
4638 mlir::ConversionPatternRewriter &rewriter)
const {
4639 rewriter.replaceOpWithNewOp<mlir::LLVM::IsConstantOp>(op, adaptor.getVal());
4640 return mlir::success();
4643mlir::LogicalResult CIRToLLVMInlineAsmOpLowering::matchAndRewrite(
4644 cir::InlineAsmOp op, OpAdaptor adaptor,
4645 mlir::ConversionPatternRewriter &rewriter)
const {
4647 if (op.getNumResults())
4648 llResTy = getTypeConverter()->convertType(op.getType(0));
4650 cir::AsmFlavor dialect = op.getAsmFlavor();
4651 mlir::LLVM::AsmDialect llDialect = dialect == cir::AsmFlavor::x86_att
4652 ? mlir::LLVM::AsmDialect::AD_ATT
4653 : mlir::LLVM::AsmDialect::AD_Intel;
4655 SmallVector<mlir::Attribute> opAttrs;
4656 StringRef llvmAttrName = mlir::LLVM::InlineAsmOp::getElementTypeAttrName();
4662 if (!op.getNumResults())
4663 opAttrs.push_back(mlir::Attribute());
4665 SmallVector<mlir::Value> llvmOperands;
4666 SmallVector<mlir::Value> cirOperands;
4667 for (
auto const &[llvmOp, cirOp] :
4668 zip(adaptor.getAsmOperands(), op.getAsmOperands())) {
4669 append_range(llvmOperands, llvmOp);
4670 append_range(cirOperands, cirOp);
4675 for (
auto const &[cirOpAttr, cirOp] :
4676 zip(op.getOperandAttrs(), cirOperands)) {
4678 opAttrs.push_back(mlir::Attribute());
4682 llvm::SmallVector<mlir::NamedAttribute, 1> attrs;
4683 cir::PointerType typ = mlir::cast<cir::PointerType>(cirOp.getType());
4685 *getTypeConverter(), dataLayout, typ.getPointee()));
4687 attrs.push_back(rewriter.getNamedAttr(llvmAttrName, typAttr));
4688 mlir::DictionaryAttr newDict = rewriter.getDictionaryAttr(attrs);
4689 opAttrs.push_back(newDict);
4692 rewriter.replaceOpWithNewOp<mlir::LLVM::InlineAsmOp>(
4693 op, llResTy, llvmOperands, op.getAsmStringAttr(), op.getConstraintsAttr(),
4694 op.getSideEffectsAttr(),
4697 mlir::LLVM::TailCallKindAttr::get(
4698 getContext(), mlir::LLVM::tailcallkind::TailCallKind::None),
4699 mlir::LLVM::AsmDialectAttr::get(getContext(), llDialect),
4700 rewriter.getArrayAttr(opAttrs));
4702 return mlir::success();
4705mlir::LogicalResult CIRToLLVMVAStartOpLowering::matchAndRewrite(
4706 cir::VAStartOp op, OpAdaptor adaptor,
4707 mlir::ConversionPatternRewriter &rewriter)
const {
4708 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4709 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4710 adaptor.getArgList());
4711 rewriter.replaceOpWithNewOp<mlir::LLVM::VaStartOp>(op, vaList);
4712 return mlir::success();
4715mlir::LogicalResult CIRToLLVMVAEndOpLowering::matchAndRewrite(
4716 cir::VAEndOp op, OpAdaptor adaptor,
4717 mlir::ConversionPatternRewriter &rewriter)
const {
4718 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4719 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4720 adaptor.getArgList());
4721 rewriter.replaceOpWithNewOp<mlir::LLVM::VaEndOp>(op, vaList);
4722 return mlir::success();
4725mlir::LogicalResult CIRToLLVMVACopyOpLowering::matchAndRewrite(
4726 cir::VACopyOp op, OpAdaptor adaptor,
4727 mlir::ConversionPatternRewriter &rewriter)
const {
4728 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4729 auto dstList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4730 adaptor.getDstList());
4731 auto srcList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4732 adaptor.getSrcList());
4733 rewriter.replaceOpWithNewOp<mlir::LLVM::VaCopyOp>(op, dstList, srcList);
4734 return mlir::success();
4737mlir::LogicalResult CIRToLLVMVAArgOpLowering::matchAndRewrite(
4738 cir::VAArgOp op, OpAdaptor adaptor,
4739 mlir::ConversionPatternRewriter &rewriter)
const {
4741 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
4742 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
4743 adaptor.getArgList());
4745 mlir::Type llvmType =
4746 getTypeConverter()->convertType(op->getResultTypes().front());
4748 return mlir::failure();
4750 rewriter.replaceOpWithNewOp<mlir::LLVM::VaArgOp>(op, llvmType, vaList);
4751 return mlir::success();
4754mlir::LogicalResult CIRToLLVMLabelOpLowering::matchAndRewrite(
4755 cir::LabelOp op, OpAdaptor adaptor,
4756 mlir::ConversionPatternRewriter &rewriter)
const {
4757 mlir::MLIRContext *ctx = rewriter.getContext();
4758 mlir::Block *block = op->getBlock();
4761 if (block->isEntryBlock()) {
4762 mlir::Block *newBlock =
4763 rewriter.splitBlock(op->getBlock(), mlir::Block::iterator(op));
4764 rewriter.setInsertionPointToEnd(block);
4765 mlir::LLVM::BrOp::create(rewriter, op.getLoc(), newBlock);
4768 mlir::LLVM::BlockTagAttr::get(ctx, blockInfoAddr.getTagIndex());
4769 rewriter.setInsertionPoint(op);
4772 mlir::LLVM::BlockTagOp::create(rewriter, op->getLoc(), tagAttr);
4773 mlir::LLVM::LLVMFuncOp func = op->getParentOfType<mlir::LLVM::LLVMFuncOp>();
4774 auto blockInfoAttr =
4775 cir::BlockAddrInfoAttr::get(ctx, func.getSymName(), op.getLabel());
4776 blockInfoAddr.mapBlockTag(blockInfoAttr, blockTagOp);
4777 rewriter.eraseOp(op);
4779 return mlir::success();
4782mlir::LogicalResult CIRToLLVMBlockAddressOpLowering::matchAndRewrite(
4783 cir::BlockAddressOp op, OpAdaptor adaptor,
4784 mlir::ConversionPatternRewriter &rewriter)
const {
4785 mlir::MLIRContext *ctx = rewriter.getContext();
4787 mlir::LLVM::BlockTagOp matchLabel =
4788 blockInfoAddr.lookupBlockTag(op.getBlockAddrInfoAttr());
4789 mlir::LLVM::BlockTagAttr tagAttr;
4796 tagAttr = matchLabel.getTag();
4798 auto blkAddr = mlir::LLVM::BlockAddressAttr::get(
4799 rewriter.getContext(), op.getBlockAddrInfoAttr().getFunc(), tagAttr);
4800 rewriter.setInsertionPoint(op);
4801 auto newOp = mlir::LLVM::BlockAddressOp::create(
4802 rewriter, op.getLoc(), mlir::LLVM::LLVMPointerType::get(ctx), blkAddr);
4804 blockInfoAddr.addUnresolvedBlockAddress(newOp, op.getBlockAddrInfoAttr());
4805 rewriter.replaceOp(op, newOp);
4806 return mlir::success();
4809mlir::LogicalResult CIRToLLVMIndirectBrOpLowering::matchAndRewrite(
4810 cir::IndirectBrOp op, OpAdaptor adaptor,
4811 mlir::ConversionPatternRewriter &rewriter)
const {
4813 llvm::SmallVector<mlir::Block *, 8> successors;
4814 llvm::SmallVector<mlir::ValueRange, 8> succOperands;
4815 bool poison = op.getPoison();
4816 for (mlir::Block *succ : op->getSuccessors())
4817 successors.push_back(succ);
4819 for (mlir::ValueRange operand : op.getSuccOperands()) {
4820 succOperands.push_back(operand);
4823 auto llvmPtrType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4824 mlir::Value targetAddr;
4826 targetAddr = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(),
4827 llvmPtrType, adaptor.getAddr());
4830 mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), llvmPtrType);
4833 op->getBlock()->eraseArgument(0);
4836 auto newOp = mlir::LLVM::IndirectBrOp::create(
4837 rewriter, op.getLoc(), targetAddr, succOperands, successors);
4838 rewriter.replaceOp(op, newOp);
4839 return mlir::success();
4842mlir::LogicalResult CIRToLLVMAwaitOpLowering::matchAndRewrite(
4843 cir::AwaitOp op, OpAdaptor adaptor,
4844 mlir::ConversionPatternRewriter &rewriter)
const {
4845 return mlir::failure();
4848mlir::LogicalResult CIRToLLVMCpuIdOpLowering::matchAndRewrite(
4849 cir::CpuIdOp op, OpAdaptor adaptor,
4850 mlir::ConversionPatternRewriter &rewriter)
const {
4851 mlir::Type i32Ty = rewriter.getI32Type();
4852 mlir::Type i64Ty = rewriter.getI64Type();
4853 mlir::Type i32PtrTy = mlir::LLVM::LLVMPointerType::get(i32Ty.getContext(), 0);
4855 mlir::Type cpuidRetTy = mlir::LLVM::LLVMStructType::getLiteral(
4856 rewriter.getContext(), {i32Ty, i32Ty, i32Ty, i32Ty});
4858 mlir::Value functionId = adaptor.getFunctionId();
4859 mlir::Value subFunctionId = adaptor.getSubFunctionId();
4861 StringRef asmString, constraints;
4862 mlir::ModuleOp moduleOp = op->getParentOfType<mlir::ModuleOp>();
4863 llvm::Triple triple(
4864 mlir::cast<mlir::StringAttr>(
4865 moduleOp->getAttr(cir::CIRDialect::getTripleAttrName()))
4867 if (triple.getArch() == llvm::Triple::x86) {
4868 asmString =
"cpuid";
4869 constraints =
"={ax},={bx},={cx},={dx},{ax},{cx}";
4872 asmString =
"xchgq %rbx, ${1:q}\n"
4874 "xchgq %rbx, ${1:q}";
4875 constraints =
"={ax},=r,={cx},={dx},0,2";
4878 mlir::Value inlineAsm =
4879 mlir::LLVM::InlineAsmOp::create(
4880 rewriter, op.getLoc(), cpuidRetTy, {functionId, subFunctionId},
4881 rewriter.getStringAttr(asmString),
4882 rewriter.getStringAttr(constraints),
4885 mlir::LLVM::TailCallKindAttr{},
4886 mlir::LLVM::AsmDialectAttr{},
4890 mlir::Value basePtr = adaptor.getCpuInfo();
4892 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
4893 unsigned alignment = layout.getTypeABIAlignment(i32Ty);
4894 for (
unsigned i = 0; i < 4; i++) {
4895 mlir::Value extracted =
4896 mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(), inlineAsm, i)
4898 mlir::Value index = mlir::LLVM::ConstantOp::create(
4899 rewriter, op.getLoc(), i64Ty, rewriter.getI64IntegerAttr(i));
4900 llvm::SmallVector<mlir::Value, 1> gepIndices = {index};
4901 mlir::Value storePtr = mlir::LLVM::GEPOp::create(
4902 rewriter, op.getLoc(), i32PtrTy, i32Ty, basePtr,
4903 gepIndices, mlir::LLVM::GEPNoWrapFlags::none)
4905 mlir::LLVM::StoreOp::create(rewriter, op.getLoc(), extracted, storePtr,
4909 rewriter.eraseOp(op);
4910 return mlir::success();
4913mlir::LogicalResult CIRToLLVMMemChrOpLowering::matchAndRewrite(
4914 cir::MemChrOp op, OpAdaptor adaptor,
4915 mlir::ConversionPatternRewriter &rewriter)
const {
4916 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4917 mlir::Type srcTy = getTypeConverter()->convertType(op.getSrc().getType());
4918 mlir::Type patternTy =
4919 getTypeConverter()->convertType(op.getPattern().getType());
4920 mlir::Type lenTy = getTypeConverter()->convertType(op.getLen().getType());
4922 mlir::LLVM::LLVMFunctionType::get(llvmPtrTy, {srcTy, patternTy, lenTy},
4924 llvm::StringRef fnName =
"memchr";
4926 rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(
4927 op, mlir::TypeRange{llvmPtrTy}, fnName,
4928 mlir::ValueRange{adaptor.getSrc(), adaptor.getPattern(),
4930 return mlir::success();
4934 return std::make_unique<ConvertCIRToLLVMPass>();
4942std::unique_ptr<llvm::Module>
4944 StringRef mlirSaveTempsOutFile) {
4945 llvm::TimeTraceScope scope(
"lower from CIR to LLVM directly");
4947 mlir::MLIRContext *mlirCtx = mlirModule.getContext();
4949 mlir::PassManager pm(mlirCtx);
4952 (void)mlir::applyPassManagerCLOptions(pm);
4954 if (mlir::failed(pm.run(mlirModule))) {
4957 "The pass manager failed to lower CIR to LLVMIR dialect!");
4960 if (!mlirSaveTempsOutFile.empty()) {
4962 llvm::raw_fd_ostream out(mlirSaveTempsOutFile, ec);
4964 mlirModule->print(out);
4967 mlir::registerBuiltinDialectTranslation(*mlirCtx);
4968 mlir::registerLLVMDialectTranslation(*mlirCtx);
4969 mlir::registerOpenMPDialectTranslation(*mlirCtx);
4972 llvm::TimeTraceScope translateScope(
"translateModuleToLLVMIR");
4974 StringRef moduleName = mlirModule.getName().value_or(
"CIRToLLVMModule");
4975 std::unique_ptr<llvm::Module> llvmModule =
4976 mlir::translateModuleToLLVMIR(mlirModule, llvmCtx, moduleName);
4980 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 visit(mlir::Attribute attr)
mlir::Value visitCirAttr(cir::BoolAttr boolAttr)
BoolAttr visitor.
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::LogicalResult lowerIncDecOp(CIROp op, typename CIROp::Adaptor adaptor, mlir::ConversionPatternRewriter &rewriter, double fpConstant)
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.
std::unique_ptr< llvm::Module > lowerDirectlyFromCIRToLLVMIR(mlir::ModuleOp mlirModule, llvm::LLVMContext &llvmCtx, llvm::StringRef mlirSaveTempsOutFile={})
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::LogicalResult lowerMinMaxOp(CIROp op, typename CIROp::Adaptor adaptor, mlir::ConversionPatternRewriter &rewriter)
static mlir::LLVM::LLVMStructType getLLVMLandingPadStructTy(mlir::ConversionPatternRewriter &rewriter)
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 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.
static llvm::StringLiteral getLLVMBinopForPostAtomic(cir::AtomicFetchKind k, bool isInt)
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::LogicalResult lowerBinOpOverflow(OpTy op, typename OpTy::Adaptor adaptor, mlir::ConversionPatternRewriter &rewriter, const mlir::TypeConverter *typeConverter, llvm::StringRef opStr)
Shared lowering logic for checked binary arithmetic overflow operations.
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::LLVM::IntegerOverflowFlags nswFlag(bool nsw)
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()