18#include "mlir/Conversion/LLVMCommon/TypeConverter.h"
19#include "mlir/Dialect/DLTI/DLTI.h"
20#include "mlir/Dialect/Func/IR/FuncOps.h"
21#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
22#include "mlir/Dialect/LLVMIR/LLVMTypes.h"
23#include "mlir/IR/BuiltinAttributes.h"
24#include "mlir/IR/BuiltinDialect.h"
25#include "mlir/IR/BuiltinOps.h"
26#include "mlir/IR/Types.h"
27#include "mlir/Pass/Pass.h"
28#include "mlir/Pass/PassManager.h"
29#include "mlir/Target/LLVMIR/Dialect/Builtin/BuiltinToLLVMIRTranslation.h"
30#include "mlir/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.h"
31#include "mlir/Target/LLVMIR/Export.h"
32#include "mlir/Transforms/DialectConversion.h"
40#include "llvm/ADT/TypeSwitch.h"
41#include "llvm/IR/Module.h"
42#include "llvm/Support/ErrorHandling.h"
43#include "llvm/Support/TimeProfiler.h"
58mlir::Type elementTypeIfVector(mlir::Type type) {
59 return llvm::TypeSwitch<mlir::Type, mlir::Type>(type)
60 .Case<cir::VectorType, mlir::VectorType>(
61 [](
auto p) {
return p.getElementType(); })
62 .
Default([](mlir::Type p) {
return p; });
70 mlir::DataLayout
const &dataLayout,
74 if (isa<cir::BoolType>(type)) {
75 return mlir::IntegerType::get(type.getContext(),
76 dataLayout.getTypeSizeInBits(type));
79 return converter.convertType(type);
83 mlir::IntegerType dstTy,
84 bool isSigned =
false) {
85 mlir::Type srcTy = src.getType();
86 assert(mlir::isa<mlir::IntegerType>(srcTy));
88 unsigned srcWidth = mlir::cast<mlir::IntegerType>(srcTy).getWidth();
89 unsigned dstWidth = mlir::cast<mlir::IntegerType>(dstTy).getWidth();
90 mlir::Location loc = src.getLoc();
92 if (dstWidth > srcWidth && isSigned)
93 return bld.create<mlir::LLVM::SExtOp>(loc, dstTy, src);
94 if (dstWidth > srcWidth)
95 return bld.create<mlir::LLVM::ZExtOp>(loc, dstTy, src);
96 if (dstWidth < srcWidth)
97 return bld.create<mlir::LLVM::TruncOp>(loc, dstTy, src);
98 return bld.create<mlir::LLVM::BitcastOp>(loc, dstTy, src);
101static mlir::LLVM::Visibility
103 switch (visibilityKind) {
104 case cir::VisibilityKind::Default:
105 return ::mlir::LLVM::Visibility::Default;
106 case cir::VisibilityKind::Hidden:
107 return ::mlir::LLVM::Visibility::Hidden;
108 case cir::VisibilityKind::Protected:
109 return ::mlir::LLVM::Visibility::Protected;
117 mlir::DataLayout
const &dataLayout,
118 cir::LoadOp op, mlir::Value value) {
121 if (
auto boolTy = mlir::dyn_cast<cir::BoolType>(op.getType())) {
123 assert(value.getType().isInteger(dataLayout.getTypeSizeInBits(boolTy)));
133static mlir::Value
emitToMemory(mlir::ConversionPatternRewriter &rewriter,
134 mlir::DataLayout
const &dataLayout,
135 mlir::Type origType, mlir::Value value) {
138 if (
auto boolTy = mlir::dyn_cast<cir::BoolType>(origType)) {
140 mlir::IntegerType memType =
141 rewriter.getIntegerType(dataLayout.getTypeSizeInBits(boolTy));
149 using CIR = cir::GlobalLinkageKind;
150 using LLVM = mlir::LLVM::Linkage;
153 case CIR::AvailableExternallyLinkage:
154 return LLVM::AvailableExternally;
155 case CIR::CommonLinkage:
157 case CIR::ExternalLinkage:
158 return LLVM::External;
159 case CIR::ExternalWeakLinkage:
160 return LLVM::ExternWeak;
161 case CIR::InternalLinkage:
162 return LLVM::Internal;
163 case CIR::LinkOnceAnyLinkage:
164 return LLVM::Linkonce;
165 case CIR::LinkOnceODRLinkage:
166 return LLVM::LinkonceODR;
167 case CIR::PrivateLinkage:
168 return LLVM::Private;
169 case CIR::WeakAnyLinkage:
171 case CIR::WeakODRLinkage:
172 return LLVM::WeakODR;
174 llvm_unreachable(
"Unknown CIR linkage type");
177mlir::LogicalResult CIRToLLVMCopyOpLowering::matchAndRewrite(
178 cir::CopyOp op, OpAdaptor adaptor,
179 mlir::ConversionPatternRewriter &rewriter)
const {
180 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
181 const mlir::Value
length = mlir::LLVM::ConstantOp::create(
182 rewriter, op.getLoc(), rewriter.getI32Type(), op.getLength(layout));
184 rewriter.replaceOpWithNewOp<mlir::LLVM::MemcpyOp>(
185 op, adaptor.getDst(), adaptor.getSrc(),
length,
false);
186 return mlir::success();
189mlir::LogicalResult CIRToLLVMCosOpLowering::matchAndRewrite(
190 cir::CosOp op, OpAdaptor adaptor,
191 mlir::ConversionPatternRewriter &rewriter)
const {
192 mlir::Type resTy = typeConverter->convertType(op.getType());
193 rewriter.replaceOpWithNewOp<mlir::LLVM::CosOp>(op, resTy, adaptor.getSrc());
194 return mlir::success();
198 mlir::Value llvmSrc, mlir::Type llvmDstIntTy,
200 uint64_t cirDstIntWidth) {
201 if (cirSrcWidth == cirDstIntWidth)
204 auto loc = llvmSrc.getLoc();
205 if (cirSrcWidth < cirDstIntWidth) {
207 return rewriter.create<mlir::LLVM::ZExtOp>(loc, llvmDstIntTy, llvmSrc);
208 return rewriter.create<mlir::LLVM::SExtOp>(loc, llvmDstIntTy, llvmSrc);
212 return rewriter.create<mlir::LLVM::TruncOp>(loc, llvmDstIntTy, llvmSrc);
218 mlir::ConversionPatternRewriter &rewriter,
219 const mlir::TypeConverter *converter)
220 : parentOp(parentOp), rewriter(rewriter), converter(converter) {}
222 mlir::Value
visit(mlir::Attribute attr) {
223 return llvm::TypeSwitch<mlir::Attribute, mlir::Value>(attr)
224 .Case<cir::IntAttr, cir::FPAttr, cir::ConstComplexAttr,
225 cir::ConstArrayAttr, cir::ConstRecordAttr, cir::ConstVectorAttr,
226 cir::ConstPtrAttr, cir::GlobalViewAttr, cir::TypeInfoAttr,
227 cir::VTableAttr, cir::ZeroAttr>(
229 .Default([&](
auto attrT) {
return mlir::Value(); });
234 mlir::Value
visitCirAttr(cir::ConstComplexAttr complexAttr);
245 mlir::Operation *parentOp;
246 mlir::ConversionPatternRewriter &rewriter;
247 const mlir::TypeConverter *converter;
252 const mlir::Attribute attr,
253 mlir::ConversionPatternRewriter &rewriter,
254 const mlir::TypeConverter *converter) {
256 mlir::Value value = valueConverter.
visit(attr);
258 llvm_unreachable(
"unhandled attribute type");
263 cir::SideEffect sideEffect,
264 mlir::LLVM::MemoryEffectsAttr &memoryEffect,
265 bool &noUnwind,
bool &willReturn) {
266 using mlir::LLVM::ModRefInfo;
268 switch (sideEffect) {
269 case cir::SideEffect::All:
271 noUnwind = isNothrow;
275 case cir::SideEffect::Pure:
276 memoryEffect = mlir::LLVM::MemoryEffectsAttr::get(
277 callOp->getContext(), ModRefInfo::Ref,
284 case cir::SideEffect::Const:
285 memoryEffect = mlir::LLVM::MemoryEffectsAttr::get(
286 callOp->getContext(), ModRefInfo::NoModRef,
287 ModRefInfo::NoModRef,
288 ModRefInfo::NoModRef);
295static mlir::LLVM::CallIntrinsicOp
297 mlir::Location loc,
const llvm::Twine &intrinsicName,
298 mlir::Type resultTy, mlir::ValueRange operands) {
299 auto intrinsicNameAttr =
300 mlir::StringAttr::get(rewriter.getContext(), intrinsicName);
301 return mlir::LLVM::CallIntrinsicOp::create(rewriter, loc, resultTy,
302 intrinsicNameAttr, operands);
306 mlir::ConversionPatternRewriter &rewriter, mlir::Operation *op,
307 const llvm::Twine &intrinsicName, mlir::Type resultTy,
308 mlir::ValueRange operands) {
310 rewriter, op->getLoc(), intrinsicName, resultTy, operands);
311 rewriter.replaceOp(op, callIntrinOp.getOperation());
317 mlir::Location loc = parentOp->getLoc();
318 return rewriter.create<mlir::LLVM::ConstantOp>(
319 loc, converter->convertType(intAttr.getType()), intAttr.getValue());
324 mlir::Location loc = parentOp->getLoc();
325 return rewriter.create<mlir::LLVM::ConstantOp>(
326 loc, converter->convertType(fltAttr.getType()), fltAttr.getValue());
331 auto complexType = mlir::cast<cir::ComplexType>(complexAttr.getType());
332 mlir::Type complexElemTy = complexType.getElementType();
333 mlir::Type complexElemLLVMTy = converter->convertType(complexElemTy);
335 mlir::Attribute components[2];
336 if (
const auto intType = mlir::dyn_cast<cir::IntType>(complexElemTy)) {
337 components[0] = rewriter.getIntegerAttr(
339 mlir::cast<cir::IntAttr>(complexAttr.getReal()).getValue());
340 components[1] = rewriter.getIntegerAttr(
342 mlir::cast<cir::IntAttr>(complexAttr.getImag()).getValue());
344 components[0] = rewriter.getFloatAttr(
346 mlir::cast<cir::FPAttr>(complexAttr.getReal()).getValue());
347 components[1] = rewriter.getFloatAttr(
349 mlir::cast<cir::FPAttr>(complexAttr.getImag()).getValue());
352 mlir::Location loc = parentOp->getLoc();
353 return rewriter.create<mlir::LLVM::ConstantOp>(
354 loc, converter->convertType(complexAttr.getType()),
355 rewriter.getArrayAttr(components));
360 mlir::Location loc = parentOp->getLoc();
361 if (ptrAttr.isNullValue()) {
362 return rewriter.create<mlir::LLVM::ZeroOp>(
363 loc, converter->convertType(ptrAttr.getType()));
365 mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
366 mlir::Value ptrVal = rewriter.create<mlir::LLVM::ConstantOp>(
367 loc, rewriter.getIntegerType(layout.getTypeSizeInBits(ptrAttr.getType())),
368 ptrAttr.getValue().getInt());
369 return rewriter.create<mlir::LLVM::IntToPtrOp>(
370 loc, converter->convertType(ptrAttr.getType()), ptrVal);
375 mlir::Type llvmTy = converter->convertType(attr.getType());
376 mlir::Location loc = parentOp->getLoc();
379 if (attr.hasTrailingZeros()) {
380 mlir::Type arrayTy = attr.getType();
381 result = rewriter.create<mlir::LLVM::ZeroOp>(
382 loc, converter->convertType(arrayTy));
384 result = rewriter.create<mlir::LLVM::UndefOp>(loc, llvmTy);
388 if (
auto arrayAttr = mlir::dyn_cast<mlir::ArrayAttr>(attr.getElts())) {
389 for (
auto [idx, elt] : llvm::enumerate(arrayAttr)) {
390 mlir::DataLayout dataLayout(parentOp->getParentOfType<mlir::ModuleOp>());
391 mlir::Value init =
visit(elt);
393 rewriter.create<mlir::LLVM::InsertValueOp>(loc, result, init, idx);
395 }
else if (
auto strAttr = mlir::dyn_cast<mlir::StringAttr>(attr.getElts())) {
398 auto arrayTy = mlir::dyn_cast<cir::ArrayType>(strAttr.getType());
399 assert(arrayTy &&
"String attribute must have an array type");
400 mlir::Type eltTy = arrayTy.getElementType();
401 for (
auto [idx, elt] : llvm::enumerate(strAttr)) {
402 auto init = rewriter.create<mlir::LLVM::ConstantOp>(
403 loc, converter->convertType(eltTy), elt);
405 rewriter.create<mlir::LLVM::InsertValueOp>(loc, result, init, idx);
408 llvm_unreachable(
"unexpected ConstArrayAttr elements");
416 const mlir::Type llvmTy = converter->convertType(constRecord.getType());
417 const mlir::Location loc = parentOp->getLoc();
418 mlir::Value result = rewriter.create<mlir::LLVM::UndefOp>(loc, llvmTy);
421 for (
auto [idx, elt] : llvm::enumerate(constRecord.getMembers())) {
422 mlir::Value init =
visit(elt);
423 result = rewriter.create<mlir::LLVM::InsertValueOp>(loc, result, init, idx);
431 const mlir::Type llvmTy = converter->convertType(attr.getType());
432 const mlir::Location loc = parentOp->getLoc();
435 for (
const mlir::Attribute elementAttr : attr.getElts()) {
436 mlir::Attribute mlirAttr;
437 if (
auto intAttr = mlir::dyn_cast<cir::IntAttr>(elementAttr)) {
438 mlirAttr = rewriter.getIntegerAttr(
439 converter->convertType(intAttr.getType()), intAttr.getValue());
440 }
else if (
auto floatAttr = mlir::dyn_cast<cir::FPAttr>(elementAttr)) {
441 mlirAttr = rewriter.getFloatAttr(
442 converter->convertType(floatAttr.getType()), floatAttr.getValue());
445 "vector constant with an element that is neither an int nor a float");
447 mlirValues.push_back(mlirAttr);
450 return rewriter.create<mlir::LLVM::ConstantOp>(
452 mlir::DenseElementsAttr::get(mlir::cast<mlir::ShapedType>(llvmTy),
458 auto moduleOp = parentOp->getParentOfType<mlir::ModuleOp>();
459 mlir::DataLayout dataLayout(moduleOp);
460 mlir::Type sourceType;
462 llvm::StringRef symName;
463 mlir::Operation *sourceSymbol =
464 mlir::SymbolTable::lookupSymbolIn(moduleOp, globalAttr.getSymbol());
465 if (
auto llvmSymbol = dyn_cast<mlir::LLVM::GlobalOp>(sourceSymbol)) {
466 sourceType = llvmSymbol.getType();
467 symName = llvmSymbol.getSymName();
468 }
else if (
auto cirSymbol = dyn_cast<cir::GlobalOp>(sourceSymbol)) {
471 symName = cirSymbol.getSymName();
472 }
else if (
auto llvmFun = dyn_cast<mlir::LLVM::LLVMFuncOp>(sourceSymbol)) {
473 sourceType = llvmFun.getFunctionType();
474 symName = llvmFun.getSymName();
475 }
else if (
auto fun = dyn_cast<cir::FuncOp>(sourceSymbol)) {
476 sourceType = converter->convertType(fun.getFunctionType());
477 symName = fun.getSymName();
478 }
else if (
auto alias = dyn_cast<mlir::LLVM::AliasOp>(sourceSymbol)) {
479 sourceType = alias.getType();
480 symName = alias.getSymName();
482 llvm_unreachable(
"Unexpected GlobalOp type");
485 mlir::Location loc = parentOp->getLoc();
486 mlir::Value addrOp = rewriter.create<mlir::LLVM::AddressOfOp>(
487 loc, mlir::LLVM::LLVMPointerType::get(rewriter.getContext()), symName);
489 if (globalAttr.getIndices()) {
492 if (mlir::isa<mlir::LLVM::LLVMArrayType, mlir::LLVM::LLVMStructType>(
494 indices.push_back(0);
496 for (mlir::Attribute idx : globalAttr.getIndices()) {
497 auto intAttr = mlir::cast<mlir::IntegerAttr>(idx);
498 indices.push_back(intAttr.getValue().getSExtValue());
500 mlir::Type resTy = addrOp.getType();
501 mlir::Type eltTy = converter->convertType(sourceType);
502 addrOp = rewriter.create<mlir::LLVM::GEPOp>(
503 loc, resTy, eltTy, addrOp, indices, mlir::LLVM::GEPNoWrapFlags::none);
512 if (
auto ptrTy = mlir::dyn_cast<cir::PointerType>(globalAttr.getType())) {
513 mlir::Type llvmEltTy =
516 if (llvmEltTy == sourceType)
519 mlir::Type llvmDstTy = converter->convertType(globalAttr.getType());
520 return rewriter.create<mlir::LLVM::BitcastOp>(parentOp->getLoc(), llvmDstTy,
524 llvm_unreachable(
"Expecting pointer or integer type for GlobalViewAttr");
529 mlir::Type llvmTy = converter->convertType(typeInfoAttr.getType());
530 mlir::Location loc = parentOp->getLoc();
531 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
533 for (
auto [idx, elt] : llvm::enumerate(typeInfoAttr.getData())) {
534 mlir::Value init =
visit(elt);
536 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
544 mlir::Type llvmTy = converter->convertType(vtableArr.getType());
545 mlir::Location loc = parentOp->getLoc();
546 mlir::Value result = mlir::LLVM::UndefOp::create(rewriter, loc, llvmTy);
548 for (
auto [idx, elt] : llvm::enumerate(vtableArr.getData())) {
549 mlir::Value init =
visit(elt);
551 mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
559 mlir::Location loc = parentOp->getLoc();
560 return rewriter.create<mlir::LLVM::ZeroOp>(
561 loc, converter->convertType(attr.getType()));
569 mlir::ConversionPatternRewriter &rewriter)
570 : llvmType(type), rewriter(rewriter) {}
572 mlir::Attribute
visit(mlir::Attribute attr) {
573 return llvm::TypeSwitch<mlir::Attribute, mlir::Attribute>(attr)
574 .Case<cir::IntAttr, cir::FPAttr, cir::BoolAttr>(
576 .Default([&](
auto attrT) {
return mlir::Attribute(); });
580 return rewriter.getIntegerAttr(llvmType, attr.getValue());
584 return rewriter.getFloatAttr(llvmType, attr.getValue());
588 return rewriter.getBoolAttr(attr.getValue());
593 mlir::ConversionPatternRewriter &rewriter;
601 :
public mlir::PassWrapper<ConvertCIRToLLVMPass,
602 mlir::OperationPass<mlir::ModuleOp>> {
604 registry.insert<mlir::BuiltinDialect, mlir::DLTIDialect,
605 mlir::LLVM::LLVMDialect, mlir::func::FuncDialect>();
612 return "Convert the prepared CIR dialect module to LLVM dialect";
615 StringRef
getArgument()
const override {
return "cir-flat-to-llvm"; }
618mlir::LogicalResult CIRToLLVMACosOpLowering::matchAndRewrite(
619 cir::ACosOp op, OpAdaptor adaptor,
620 mlir::ConversionPatternRewriter &rewriter)
const {
621 mlir::Type resTy = typeConverter->convertType(op.getType());
622 rewriter.replaceOpWithNewOp<mlir::LLVM::ACosOp>(op, resTy,
623 adaptor.getOperands()[0]);
624 return mlir::success();
627mlir::LogicalResult CIRToLLVMASinOpLowering::matchAndRewrite(
628 cir::ASinOp op, OpAdaptor adaptor,
629 mlir::ConversionPatternRewriter &rewriter)
const {
630 mlir::Type resTy = typeConverter->convertType(op.getType());
631 rewriter.replaceOpWithNewOp<mlir::LLVM::ASinOp>(op, resTy, adaptor.getSrc());
632 return mlir::success();
635mlir::LogicalResult CIRToLLVMAssumeOpLowering::matchAndRewrite(
636 cir::AssumeOp op, OpAdaptor adaptor,
637 mlir::ConversionPatternRewriter &rewriter)
const {
638 auto cond = adaptor.getPredicate();
639 rewriter.replaceOpWithNewOp<mlir::LLVM::AssumeOp>(op, cond);
640 return mlir::success();
643mlir::LogicalResult CIRToLLVMAssumeAlignedOpLowering::matchAndRewrite(
644 cir::AssumeAlignedOp op, OpAdaptor adaptor,
645 mlir::ConversionPatternRewriter &rewriter)
const {
646 SmallVector<mlir::Value, 3> opBundleArgs{adaptor.getPointer()};
648 auto alignment = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
649 adaptor.getAlignmentAttr());
650 opBundleArgs.push_back(alignment);
652 if (mlir::Value offset = adaptor.getOffset())
653 opBundleArgs.push_back(offset);
655 auto cond = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
656 rewriter.getI1Type(), 1);
657 mlir::LLVM::AssumeOp::create(rewriter, op.getLoc(), cond,
"align",
662 rewriter.replaceOp(op, adaptor.getPointer());
663 return mlir::success();
666mlir::LogicalResult CIRToLLVMAssumeSepStorageOpLowering::matchAndRewrite(
667 cir::AssumeSepStorageOp op, OpAdaptor adaptor,
668 mlir::ConversionPatternRewriter &rewriter)
const {
669 auto cond = rewriter.create<mlir::LLVM::ConstantOp>(op.getLoc(),
670 rewriter.getI1Type(), 1);
671 rewriter.replaceOpWithNewOp<mlir::LLVM::AssumeOp>(
672 op, cond, mlir::LLVM::AssumeSeparateStorageTag{}, adaptor.getPtr1(),
674 return mlir::success();
677static mlir::LLVM::AtomicOrdering
680 return mlir::LLVM::AtomicOrdering::not_atomic;
682 case cir::MemOrder::Relaxed:
683 return mlir::LLVM::AtomicOrdering::monotonic;
684 case cir::MemOrder::Consume:
685 case cir::MemOrder::Acquire:
686 return mlir::LLVM::AtomicOrdering::acquire;
687 case cir::MemOrder::Release:
688 return mlir::LLVM::AtomicOrdering::release;
689 case cir::MemOrder::AcquireRelease:
690 return mlir::LLVM::AtomicOrdering::acq_rel;
691 case cir::MemOrder::SequentiallyConsistent:
692 return mlir::LLVM::AtomicOrdering::seq_cst;
694 llvm_unreachable(
"unknown memory order");
697mlir::LogicalResult CIRToLLVMAtomicCmpXchgOpLowering::matchAndRewrite(
698 cir::AtomicCmpXchgOp op, OpAdaptor adaptor,
699 mlir::ConversionPatternRewriter &rewriter)
const {
700 mlir::Value expected = adaptor.getExpected();
701 mlir::Value desired = adaptor.getDesired();
703 auto cmpxchg = mlir::LLVM::AtomicCmpXchgOp::create(
704 rewriter, op.getLoc(), adaptor.getPtr(), expected, desired,
708 cmpxchg.setAlignment(adaptor.getAlignment());
709 cmpxchg.setWeak(adaptor.getWeak());
710 cmpxchg.setVolatile_(adaptor.getIsVolatile());
713 auto old = mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(),
714 cmpxchg.getResult(), 0);
715 auto cmp = mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(),
716 cmpxchg.getResult(), 1);
718 rewriter.replaceOp(op, {old, cmp});
719 return mlir::success();
722mlir::LogicalResult CIRToLLVMAtomicXchgOpLowering::matchAndRewrite(
723 cir::AtomicXchgOp op, OpAdaptor adaptor,
724 mlir::ConversionPatternRewriter &rewriter)
const {
726 mlir::LLVM::AtomicOrdering llvmOrder =
getLLVMMemOrder(adaptor.getMemOrder());
727 rewriter.replaceOpWithNewOp<mlir::LLVM::AtomicRMWOp>(
728 op, mlir::LLVM::AtomicBinOp::xchg, adaptor.getPtr(), adaptor.getVal(),
730 return mlir::success();
733mlir::LogicalResult CIRToLLVMBitClrsbOpLowering::matchAndRewrite(
734 cir::BitClrsbOp op, OpAdaptor adaptor,
735 mlir::ConversionPatternRewriter &rewriter)
const {
736 auto zero = rewriter.create<mlir::LLVM::ConstantOp>(
737 op.getLoc(), adaptor.getInput().getType(), 0);
738 auto isNeg = rewriter.create<mlir::LLVM::ICmpOp>(
740 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(),
741 mlir::LLVM::ICmpPredicate::slt),
742 adaptor.getInput(), zero);
744 auto negOne = rewriter.create<mlir::LLVM::ConstantOp>(
745 op.getLoc(), adaptor.getInput().getType(), -1);
746 auto flipped = rewriter.create<mlir::LLVM::XOrOp>(op.getLoc(),
747 adaptor.getInput(), negOne);
749 auto select = rewriter.create<mlir::LLVM::SelectOp>(
750 op.getLoc(), isNeg, flipped, adaptor.getInput());
752 auto resTy = getTypeConverter()->convertType(op.getType());
753 auto clz = rewriter.create<mlir::LLVM::CountLeadingZerosOp>(
754 op.getLoc(), resTy,
select,
false);
756 auto one = rewriter.create<mlir::LLVM::ConstantOp>(op.getLoc(), resTy, 1);
757 auto res = rewriter.create<mlir::LLVM::SubOp>(op.getLoc(),
clz, one);
758 rewriter.replaceOp(op, res);
760 return mlir::LogicalResult::success();
763mlir::LogicalResult CIRToLLVMBitClzOpLowering::matchAndRewrite(
764 cir::BitClzOp op, OpAdaptor adaptor,
765 mlir::ConversionPatternRewriter &rewriter)
const {
766 auto resTy = getTypeConverter()->convertType(op.getType());
767 auto llvmOp = rewriter.create<mlir::LLVM::CountLeadingZerosOp>(
768 op.getLoc(), resTy, adaptor.getInput(), op.getPoisonZero());
769 rewriter.replaceOp(op, llvmOp);
770 return mlir::LogicalResult::success();
773mlir::LogicalResult CIRToLLVMBitCtzOpLowering::matchAndRewrite(
774 cir::BitCtzOp op, OpAdaptor adaptor,
775 mlir::ConversionPatternRewriter &rewriter)
const {
776 auto resTy = getTypeConverter()->convertType(op.getType());
777 auto llvmOp = rewriter.create<mlir::LLVM::CountTrailingZerosOp>(
778 op.getLoc(), resTy, adaptor.getInput(), op.getPoisonZero());
779 rewriter.replaceOp(op, llvmOp);
780 return mlir::LogicalResult::success();
783mlir::LogicalResult CIRToLLVMBitFfsOpLowering::matchAndRewrite(
784 cir::BitFfsOp op, OpAdaptor adaptor,
785 mlir::ConversionPatternRewriter &rewriter)
const {
786 auto resTy = getTypeConverter()->convertType(op.getType());
787 auto ctz = rewriter.create<mlir::LLVM::CountTrailingZerosOp>(
788 op.getLoc(), resTy, adaptor.getInput(),
true);
790 auto one = rewriter.create<mlir::LLVM::ConstantOp>(op.getLoc(), resTy, 1);
791 auto ctzAddOne = rewriter.create<mlir::LLVM::AddOp>(op.getLoc(),
ctz, one);
793 auto zeroInputTy = rewriter.create<mlir::LLVM::ConstantOp>(
794 op.getLoc(), adaptor.getInput().getType(), 0);
795 auto isZero = rewriter.create<mlir::LLVM::ICmpOp>(
797 mlir::LLVM::ICmpPredicateAttr::get(rewriter.getContext(),
798 mlir::LLVM::ICmpPredicate::eq),
799 adaptor.getInput(), zeroInputTy);
801 auto zero = rewriter.create<mlir::LLVM::ConstantOp>(op.getLoc(), resTy, 0);
802 auto res = rewriter.create<mlir::LLVM::SelectOp>(op.getLoc(), isZero, zero,
804 rewriter.replaceOp(op, res);
806 return mlir::LogicalResult::success();
809mlir::LogicalResult CIRToLLVMBitParityOpLowering::matchAndRewrite(
810 cir::BitParityOp op, OpAdaptor adaptor,
811 mlir::ConversionPatternRewriter &rewriter)
const {
812 auto resTy = getTypeConverter()->convertType(op.getType());
813 auto popcnt = rewriter.create<mlir::LLVM::CtPopOp>(op.getLoc(), resTy,
816 auto one = rewriter.create<mlir::LLVM::ConstantOp>(op.getLoc(), resTy, 1);
818 rewriter.create<mlir::LLVM::AndOp>(op.getLoc(), popcnt, one);
819 rewriter.replaceOp(op, popcntMod2);
821 return mlir::LogicalResult::success();
824mlir::LogicalResult CIRToLLVMBitPopcountOpLowering::matchAndRewrite(
825 cir::BitPopcountOp op, OpAdaptor adaptor,
826 mlir::ConversionPatternRewriter &rewriter)
const {
827 auto resTy = getTypeConverter()->convertType(op.getType());
828 auto llvmOp = rewriter.create<mlir::LLVM::CtPopOp>(op.getLoc(), resTy,
830 rewriter.replaceOp(op, llvmOp);
831 return mlir::LogicalResult::success();
834mlir::LogicalResult CIRToLLVMBitReverseOpLowering::matchAndRewrite(
835 cir::BitReverseOp op, OpAdaptor adaptor,
836 mlir::ConversionPatternRewriter &rewriter)
const {
837 rewriter.replaceOpWithNewOp<mlir::LLVM::BitReverseOp>(op, adaptor.getInput());
838 return mlir::success();
841mlir::LogicalResult CIRToLLVMBrCondOpLowering::matchAndRewrite(
842 cir::BrCondOp brOp, OpAdaptor adaptor,
843 mlir::ConversionPatternRewriter &rewriter)
const {
848 mlir::Value i1Condition = adaptor.getCond();
850 rewriter.replaceOpWithNewOp<mlir::LLVM::CondBrOp>(
851 brOp, i1Condition, brOp.getDestTrue(), adaptor.getDestOperandsTrue(),
852 brOp.getDestFalse(), adaptor.getDestOperandsFalse());
854 return mlir::success();
857mlir::LogicalResult CIRToLLVMByteSwapOpLowering::matchAndRewrite(
858 cir::ByteSwapOp op, OpAdaptor adaptor,
859 mlir::ConversionPatternRewriter &rewriter)
const {
860 rewriter.replaceOpWithNewOp<mlir::LLVM::ByteSwapOp>(op, adaptor.getInput());
861 return mlir::LogicalResult::success();
864mlir::Type CIRToLLVMCastOpLowering::convertTy(mlir::Type ty)
const {
865 return getTypeConverter()->convertType(ty);
868mlir::LogicalResult CIRToLLVMCastOpLowering::matchAndRewrite(
869 cir::CastOp castOp, OpAdaptor adaptor,
870 mlir::ConversionPatternRewriter &rewriter)
const {
875 switch (castOp.getKind()) {
876 case cir::CastKind::array_to_ptrdecay: {
877 const auto ptrTy = mlir::cast<cir::PointerType>(castOp.getType());
878 mlir::Value sourceValue = adaptor.getSrc();
879 mlir::Type targetType = convertTy(ptrTy);
882 llvm::SmallVector<mlir::LLVM::GEPArg> offset{0};
883 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
884 castOp, targetType, elementTy, sourceValue, offset);
887 case cir::CastKind::int_to_bool: {
888 mlir::Value llvmSrcVal = adaptor.getSrc();
889 mlir::Value zeroInt = rewriter.create<mlir::LLVM::ConstantOp>(
890 castOp.getLoc(), llvmSrcVal.getType(), 0);
891 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
892 castOp, mlir::LLVM::ICmpPredicate::ne, llvmSrcVal, zeroInt);
895 case cir::CastKind::integral: {
896 mlir::Type srcType = castOp.getSrc().getType();
897 mlir::Type dstType = castOp.getType();
898 mlir::Value llvmSrcVal = adaptor.getSrc();
899 mlir::Type llvmDstType = getTypeConverter()->convertType(dstType);
900 cir::IntType srcIntType =
901 mlir::cast<cir::IntType>(elementTypeIfVector(srcType));
902 cir::IntType dstIntType =
903 mlir::cast<cir::IntType>(elementTypeIfVector(dstType));
904 rewriter.replaceOp(castOp,
getLLVMIntCast(rewriter, llvmSrcVal, llvmDstType,
905 srcIntType.isUnsigned(),
906 srcIntType.getWidth(),
907 dstIntType.getWidth()));
910 case cir::CastKind::floating: {
911 mlir::Value llvmSrcVal = adaptor.getSrc();
912 mlir::Type llvmDstTy = getTypeConverter()->convertType(castOp.getType());
914 mlir::Type srcTy = elementTypeIfVector(castOp.getSrc().getType());
915 mlir::Type dstTy = elementTypeIfVector(castOp.getType());
917 if (!mlir::isa<cir::FPTypeInterface>(dstTy) ||
918 !mlir::isa<cir::FPTypeInterface>(srcTy))
919 return castOp.emitError() <<
"NYI cast from " << srcTy <<
" to " << dstTy;
921 auto getFloatWidth = [](mlir::Type ty) ->
unsigned {
922 return mlir::cast<cir::FPTypeInterface>(ty).getWidth();
925 if (getFloatWidth(srcTy) > getFloatWidth(dstTy))
926 rewriter.replaceOpWithNewOp<mlir::LLVM::FPTruncOp>(castOp, llvmDstTy,
929 rewriter.replaceOpWithNewOp<mlir::LLVM::FPExtOp>(castOp, llvmDstTy,
931 return mlir::success();
933 case cir::CastKind::int_to_ptr: {
934 auto dstTy = mlir::cast<cir::PointerType>(castOp.getType());
935 mlir::Value llvmSrcVal = adaptor.getSrc();
936 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
937 rewriter.replaceOpWithNewOp<mlir::LLVM::IntToPtrOp>(castOp, llvmDstTy,
939 return mlir::success();
941 case cir::CastKind::ptr_to_int: {
942 auto dstTy = mlir::cast<cir::IntType>(castOp.getType());
943 mlir::Value llvmSrcVal = adaptor.getSrc();
944 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
945 rewriter.replaceOpWithNewOp<mlir::LLVM::PtrToIntOp>(castOp, llvmDstTy,
947 return mlir::success();
949 case cir::CastKind::float_to_bool: {
950 mlir::Value llvmSrcVal = adaptor.getSrc();
951 auto kind = mlir::LLVM::FCmpPredicate::une;
954 auto zeroFloat = rewriter.create<mlir::LLVM::ConstantOp>(
955 castOp.getLoc(), llvmSrcVal.getType(),
956 mlir::FloatAttr::get(llvmSrcVal.getType(), 0.0));
959 rewriter.replaceOpWithNewOp<mlir::LLVM::FCmpOp>(castOp,
kind, llvmSrcVal,
962 return mlir::success();
964 case cir::CastKind::bool_to_int: {
965 auto dstTy = mlir::cast<cir::IntType>(castOp.getType());
966 mlir::Value llvmSrcVal = adaptor.getSrc();
967 auto llvmSrcTy = mlir::cast<mlir::IntegerType>(llvmSrcVal.getType());
969 mlir::cast<mlir::IntegerType>(getTypeConverter()->convertType(dstTy));
970 if (llvmSrcTy.getWidth() == llvmDstTy.getWidth())
971 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(castOp, llvmDstTy,
974 rewriter.replaceOpWithNewOp<mlir::LLVM::ZExtOp>(castOp, llvmDstTy,
976 return mlir::success();
978 case cir::CastKind::bool_to_float: {
979 mlir::Type dstTy = castOp.getType();
980 mlir::Value llvmSrcVal = adaptor.getSrc();
981 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
982 rewriter.replaceOpWithNewOp<mlir::LLVM::UIToFPOp>(castOp, llvmDstTy,
984 return mlir::success();
986 case cir::CastKind::int_to_float: {
987 mlir::Type dstTy = castOp.getType();
988 mlir::Value llvmSrcVal = adaptor.getSrc();
989 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
990 if (mlir::cast<cir::IntType>(elementTypeIfVector(castOp.getSrc().getType()))
992 rewriter.replaceOpWithNewOp<mlir::LLVM::SIToFPOp>(castOp, llvmDstTy,
995 rewriter.replaceOpWithNewOp<mlir::LLVM::UIToFPOp>(castOp, llvmDstTy,
997 return mlir::success();
999 case cir::CastKind::float_to_int: {
1000 mlir::Type dstTy = castOp.getType();
1001 mlir::Value llvmSrcVal = adaptor.getSrc();
1002 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1003 if (mlir::cast<cir::IntType>(elementTypeIfVector(castOp.getType()))
1005 rewriter.replaceOpWithNewOp<mlir::LLVM::FPToSIOp>(castOp, llvmDstTy,
1008 rewriter.replaceOpWithNewOp<mlir::LLVM::FPToUIOp>(castOp, llvmDstTy,
1010 return mlir::success();
1012 case cir::CastKind::bitcast: {
1013 mlir::Type dstTy = castOp.getType();
1014 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1019 mlir::Value llvmSrcVal = adaptor.getSrc();
1020 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(castOp, llvmDstTy,
1022 return mlir::success();
1024 case cir::CastKind::ptr_to_bool: {
1025 mlir::Value llvmSrcVal = adaptor.getSrc();
1026 mlir::Value zeroPtr = rewriter.create<mlir::LLVM::ZeroOp>(
1027 castOp.getLoc(), llvmSrcVal.getType());
1028 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
1029 castOp, mlir::LLVM::ICmpPredicate::ne, llvmSrcVal, zeroPtr);
1032 case cir::CastKind::address_space: {
1033 mlir::Type dstTy = castOp.getType();
1034 mlir::Value llvmSrcVal = adaptor.getSrc();
1035 mlir::Type llvmDstTy = getTypeConverter()->convertType(dstTy);
1036 rewriter.replaceOpWithNewOp<mlir::LLVM::AddrSpaceCastOp>(castOp, llvmDstTy,
1040 case cir::CastKind::member_ptr_to_bool:
1045 return castOp.emitError(
"Unhandled cast kind: ")
1046 << castOp.getKindAttrName();
1050 return mlir::success();
1053mlir::LogicalResult CIRToLLVMPtrStrideOpLowering::matchAndRewrite(
1054 cir::PtrStrideOp ptrStrideOp, OpAdaptor adaptor,
1055 mlir::ConversionPatternRewriter &rewriter)
const {
1057 const mlir::TypeConverter *tc = getTypeConverter();
1058 const mlir::Type resultTy = tc->convertType(ptrStrideOp.getType());
1060 mlir::Type elementTy =
1062 mlir::MLIRContext *ctx = elementTy.getContext();
1066 if (mlir::isa<mlir::LLVM::LLVMVoidType>(elementTy) ||
1067 mlir::isa<mlir::LLVM::LLVMFunctionType>(elementTy))
1068 elementTy = mlir::IntegerType::get(elementTy.getContext(), 8,
1069 mlir::IntegerType::Signless);
1071 mlir::Value index = adaptor.getStride();
1072 const unsigned width =
1073 mlir::cast<mlir::IntegerType>(index.getType()).getWidth();
1074 const std::optional<std::uint64_t> layoutWidth =
1075 dataLayout.getTypeIndexBitwidth(adaptor.getBase().getType());
1077 mlir::Operation *indexOp = index.getDefiningOp();
1078 if (indexOp && layoutWidth && width != *layoutWidth) {
1082 const auto sub = dyn_cast<mlir::LLVM::SubOp>(indexOp);
1083 auto unary = ptrStrideOp.getStride().getDefiningOp<cir::UnaryOp>();
1085 unary && unary.getKind() == cir::UnaryOpKind::Minus && sub;
1087 index = indexOp->getOperand(1);
1090 const auto llvmDstType = mlir::IntegerType::get(ctx, *layoutWidth);
1092 ptrStrideOp.getStride().getType().isUnsigned(),
1093 width, *layoutWidth);
1097 index = rewriter.create<mlir::LLVM::SubOp>(
1098 index.getLoc(), index.getType(),
1099 rewriter.create<mlir::LLVM::ConstantOp>(index.getLoc(),
1100 index.getType(), 0),
1102 rewriter.eraseOp(sub);
1106 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1107 ptrStrideOp, resultTy, elementTy, adaptor.getBase(), index);
1108 return mlir::success();
1111mlir::LogicalResult CIRToLLVMBaseClassAddrOpLowering::matchAndRewrite(
1112 cir::BaseClassAddrOp baseClassOp, OpAdaptor adaptor,
1113 mlir::ConversionPatternRewriter &rewriter)
const {
1114 const mlir::Type resultType =
1115 getTypeConverter()->convertType(baseClassOp.getType());
1116 mlir::Value derivedAddr = adaptor.getDerivedAddr();
1117 llvm::SmallVector<mlir::LLVM::GEPArg, 1> offset = {
1118 adaptor.getOffset().getZExtValue()};
1119 mlir::Type byteType = mlir::IntegerType::get(resultType.getContext(), 8,
1120 mlir::IntegerType::Signless);
1121 if (adaptor.getOffset().getZExtValue() == 0) {
1122 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(
1123 baseClassOp, resultType, adaptor.getDerivedAddr());
1124 return mlir::success();
1127 if (baseClassOp.getAssumeNotNull()) {
1128 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1129 baseClassOp, resultType, byteType, derivedAddr, offset);
1131 auto loc = baseClassOp.getLoc();
1132 mlir::Value isNull = rewriter.create<mlir::LLVM::ICmpOp>(
1133 loc, mlir::LLVM::ICmpPredicate::eq, derivedAddr,
1134 rewriter.create<mlir::LLVM::ZeroOp>(loc, derivedAddr.getType()));
1135 mlir::Value adjusted = rewriter.create<mlir::LLVM::GEPOp>(
1136 loc, resultType, byteType, derivedAddr, offset);
1137 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(baseClassOp, isNull,
1138 derivedAddr, adjusted);
1140 return mlir::success();
1143mlir::LogicalResult CIRToLLVMATanOpLowering::matchAndRewrite(
1144 cir::ATanOp op, OpAdaptor adaptor,
1145 mlir::ConversionPatternRewriter &rewriter)
const {
1146 mlir::Type resTy = typeConverter->convertType(op.getType());
1147 rewriter.replaceOpWithNewOp<mlir::LLVM::ATanOp>(op, resTy, adaptor.getSrc());
1148 return mlir::success();
1151mlir::LogicalResult CIRToLLVMAllocaOpLowering::matchAndRewrite(
1152 cir::AllocaOp op, OpAdaptor adaptor,
1153 mlir::ConversionPatternRewriter &rewriter)
const {
1156 ? adaptor.getDynAllocSize()
1157 : rewriter.create<mlir::LLVM::ConstantOp>(
1159 typeConverter->convertType(rewriter.getIndexType()), 1);
1160 mlir::Type elementTy =
1162 mlir::Type resultTy =
1168 rewriter.replaceOpWithNewOp<mlir::LLVM::AllocaOp>(
1169 op, resultTy, elementTy, size, op.getAlignmentAttr().getInt());
1171 return mlir::success();
1174mlir::LogicalResult CIRToLLVMReturnOpLowering::matchAndRewrite(
1175 cir::ReturnOp op, OpAdaptor adaptor,
1176 mlir::ConversionPatternRewriter &rewriter)
const {
1177 rewriter.replaceOpWithNewOp<mlir::LLVM::ReturnOp>(op, adaptor.getOperands());
1178 return mlir::LogicalResult::success();
1181mlir::LogicalResult CIRToLLVMRotateOpLowering::matchAndRewrite(
1182 cir::RotateOp op, OpAdaptor adaptor,
1183 mlir::ConversionPatternRewriter &rewriter)
const {
1186 mlir::Value input = adaptor.getInput();
1187 if (op.isRotateLeft())
1188 rewriter.replaceOpWithNewOp<mlir::LLVM::FshlOp>(op, input, input,
1189 adaptor.getAmount());
1191 rewriter.replaceOpWithNewOp<mlir::LLVM::FshrOp>(op, input, input,
1192 adaptor.getAmount());
1193 return mlir::LogicalResult::success();
1196static mlir::LogicalResult
1198 mlir::ConversionPatternRewriter &rewriter,
1199 const mlir::TypeConverter *converter,
1200 mlir::FlatSymbolRefAttr calleeAttr) {
1202 mlir::ValueTypeRange<mlir::ResultRange> cirResults = op->getResultTypes();
1203 auto call = cast<cir::CIRCallOpInterface>(op);
1205 if (converter->convertTypes(cirResults, llvmResults).failed())
1206 return mlir::failure();
1210 mlir::LLVM::MemoryEffectsAttr memoryEffects;
1211 bool noUnwind =
false;
1212 bool willReturn =
false;
1214 memoryEffects, noUnwind, willReturn);
1216 mlir::LLVM::LLVMFunctionType llvmFnTy;
1223 mlir::Operation *callee =
1224 mlir::SymbolTable::lookupNearestSymbolFrom(op, calleeAttr);
1225 if (
auto fn = mlir::dyn_cast<mlir::FunctionOpInterface>(callee)) {
1226 llvmFnTy = converter->convertType<mlir::LLVM::LLVMFunctionType>(
1227 fn.getFunctionType());
1228 assert(llvmFnTy &&
"Failed to convert function type");
1229 }
else if (
auto alias = mlir::cast<mlir::LLVM::AliasOp>(callee)) {
1237 auto symAttr = mlir::cast<mlir::FlatSymbolRefAttr>(calleeAttr);
1239 mlir::LLVM::AddressOfOp::create(
1240 rewriter, op->getLoc(),
1241 mlir::LLVM::LLVMPointerType::get(rewriter.getContext()), symAttr)
1243 adjustedCallOperands.push_back(addrOfAlias);
1246 llvm::append_range(adjustedCallOperands, callOperands);
1247 callOperands = adjustedCallOperands;
1251 llvmFnTy = mlir::cast<mlir::LLVM::LLVMFunctionType>(alias.getType());
1254 return op->emitError(
"Unexpected callee type!");
1257 assert(!op->getOperands().empty() &&
1258 "operands list must no be empty for the indirect call");
1259 auto calleeTy = op->getOperands().front().getType();
1260 auto calleePtrTy = cast<cir::PointerType>(calleeTy);
1261 auto calleeFuncTy = cast<cir::FuncType>(calleePtrTy.getPointee());
1262 llvm::append_range(adjustedCallOperands, callOperands);
1263 llvmFnTy = cast<mlir::LLVM::LLVMFunctionType>(
1264 converter->convertType(calleeFuncTy));
1271 auto newOp = rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(
1272 op, llvmFnTy, calleeAttr, callOperands);
1274 newOp.setMemoryEffectsAttr(memoryEffects);
1275 newOp.setNoUnwind(noUnwind);
1276 newOp.setWillReturn(willReturn);
1278 return mlir::success();
1281mlir::LogicalResult CIRToLLVMCallOpLowering::matchAndRewrite(
1282 cir::CallOp op, OpAdaptor adaptor,
1283 mlir::ConversionPatternRewriter &rewriter)
const {
1285 getTypeConverter(), op.getCalleeAttr());
1288mlir::LogicalResult CIRToLLVMReturnAddrOpLowering::matchAndRewrite(
1289 cir::ReturnAddrOp op, OpAdaptor adaptor,
1290 mlir::ConversionPatternRewriter &rewriter)
const {
1291 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
1293 llvmPtrTy, adaptor.getOperands());
1294 return mlir::success();
1297mlir::LogicalResult CIRToLLVMFrameAddrOpLowering::matchAndRewrite(
1298 cir::FrameAddrOp op, OpAdaptor adaptor,
1299 mlir::ConversionPatternRewriter &rewriter)
const {
1300 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
1302 adaptor.getOperands());
1303 return mlir::success();
1306mlir::LogicalResult CIRToLLVMLoadOpLowering::matchAndRewrite(
1307 cir::LoadOp op, OpAdaptor adaptor,
1308 mlir::ConversionPatternRewriter &rewriter)
const {
1309 const mlir::Type llvmTy =
1311 mlir::LLVM::AtomicOrdering ordering =
getLLVMMemOrder(op.getMemOrder());
1312 std::optional<size_t> opAlign = op.getAlignment();
1313 unsigned alignment =
1314 (unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmTy));
1320 mlir::LLVM::LoadOp newLoad = mlir::LLVM::LoadOp::create(
1321 rewriter, op->getLoc(), llvmTy, adaptor.getAddr(), alignment,
1322 op.getIsVolatile(),
false,
1323 false,
false, ordering);
1326 mlir::Value result =
1328 rewriter.replaceOp(op, result);
1330 return mlir::LogicalResult::success();
1333mlir::LogicalResult CIRToLLVMStoreOpLowering::matchAndRewrite(
1334 cir::StoreOp op, OpAdaptor adaptor,
1335 mlir::ConversionPatternRewriter &rewriter)
const {
1336 mlir::LLVM::AtomicOrdering memorder =
getLLVMMemOrder(op.getMemOrder());
1337 const mlir::Type llvmTy =
1338 getTypeConverter()->convertType(op.getValue().getType());
1339 std::optional<size_t> opAlign = op.getAlignment();
1340 unsigned alignment =
1341 (unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmTy));
1347 op.getValue().getType(), adaptor.getValue());
1351 mlir::LLVM::StoreOp storeOp = mlir::LLVM::StoreOp::create(
1352 rewriter, op->getLoc(), value, adaptor.getAddr(), alignment,
1354 false,
false, memorder);
1355 rewriter.replaceOp(op, storeOp);
1357 return mlir::LogicalResult::success();
1361 auto array = mlir::dyn_cast<mlir::ArrayAttr>(attr.getElts());
1362 return attr.hasTrailingZeros() ||
1363 (array && std::count_if(array.begin(), array.end(), [](
auto elt) {
1364 auto ar = dyn_cast<cir::ConstArrayAttr>(elt);
1365 return ar && hasTrailingZeros(ar);
1369mlir::LogicalResult CIRToLLVMConstantOpLowering::matchAndRewrite(
1370 cir::ConstantOp op, OpAdaptor adaptor,
1371 mlir::ConversionPatternRewriter &rewriter)
const {
1372 mlir::Attribute attr = op.getValue();
1374 if (mlir::isa<cir::PoisonAttr>(attr)) {
1375 rewriter.replaceOpWithNewOp<mlir::LLVM::PoisonOp>(
1376 op, getTypeConverter()->convertType(op.getType()));
1377 return mlir::success();
1380 if (mlir::isa<mlir::IntegerType>(op.getType())) {
1385 attr = op.getValue();
1386 }
else if (mlir::isa<cir::BoolType>(op.getType())) {
1387 int value = mlir::cast<cir::BoolAttr>(op.getValue()).getValue();
1388 attr = rewriter.getIntegerAttr(typeConverter->convertType(op.getType()),
1390 }
else if (mlir::isa<cir::IntType>(op.getType())) {
1392 if (
auto ga = mlir::dyn_cast<cir::GlobalViewAttr>(op.getValue())) {
1395 op.emitError() <<
"global view with integer type";
1396 return mlir::failure();
1399 attr = rewriter.getIntegerAttr(
1400 typeConverter->convertType(op.getType()),
1401 mlir::cast<cir::IntAttr>(op.getValue()).getValue());
1402 }
else if (mlir::isa<cir::FPTypeInterface>(op.getType())) {
1403 attr = rewriter.getFloatAttr(
1404 typeConverter->convertType(op.getType()),
1405 mlir::cast<cir::FPAttr>(op.getValue()).getValue());
1406 }
else if (mlir::isa<cir::PointerType>(op.getType())) {
1408 if (mlir::isa<cir::ConstPtrAttr>(op.getValue())) {
1409 if (mlir::cast<cir::ConstPtrAttr>(op.getValue()).isNullValue()) {
1410 rewriter.replaceOpWithNewOp<mlir::LLVM::ZeroOp>(
1411 op, typeConverter->convertType(op.getType()));
1412 return mlir::success();
1416 if (
auto gv = mlir::dyn_cast<cir::GlobalViewAttr>(op.getValue())) {
1418 rewriter.replaceOp(op, newOp);
1419 return mlir::success();
1421 attr = op.getValue();
1422 }
else if (
const auto arrTy = mlir::dyn_cast<cir::ArrayType>(op.getType())) {
1423 const auto constArr = mlir::dyn_cast<cir::ConstArrayAttr>(op.getValue());
1424 if (!constArr && !isa<cir::ZeroAttr, cir::UndefAttr>(op.getValue()))
1425 return op.emitError() <<
"array does not have a constant initializer";
1427 std::optional<mlir::Attribute> denseAttr;
1429 const mlir::Value newOp =
1431 rewriter.replaceOp(op, newOp);
1432 return mlir::success();
1433 }
else if (constArr &&
1435 attr = denseAttr.value();
1437 const mlir::Value initVal =
1439 rewriter.replaceOp(op, initVal);
1440 return mlir::success();
1442 }
else if (
const auto recordAttr =
1443 mlir::dyn_cast<cir::ConstRecordAttr>(op.getValue())) {
1445 rewriter.replaceOp(op, initVal);
1446 return mlir::success();
1447 }
else if (
const auto vecTy = mlir::dyn_cast<cir::VectorType>(op.getType())) {
1449 getTypeConverter()));
1450 return mlir::success();
1451 }
else if (
auto recTy = mlir::dyn_cast<cir::RecordType>(op.getType())) {
1452 if (mlir::isa<cir::ZeroAttr, cir::UndefAttr>(attr)) {
1453 mlir::Value initVal =
1455 rewriter.replaceOp(op, initVal);
1456 return mlir::success();
1458 return op.emitError() <<
"unsupported lowering for record constant type "
1460 }
else if (
auto complexTy = mlir::dyn_cast<cir::ComplexType>(op.getType())) {
1461 mlir::Type complexElemTy = complexTy.getElementType();
1462 mlir::Type complexElemLLVMTy = typeConverter->convertType(complexElemTy);
1464 if (
auto zeroInitAttr = mlir::dyn_cast<cir::ZeroAttr>(op.getValue())) {
1465 mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(complexElemLLVMTy);
1466 mlir::ArrayAttr array = rewriter.getArrayAttr({zeroAttr, zeroAttr});
1467 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
1468 op, getTypeConverter()->convertType(op.getType()), array);
1469 return mlir::success();
1472 auto complexAttr = mlir::cast<cir::ConstComplexAttr>(op.getValue());
1474 mlir::Attribute components[2];
1475 if (mlir::isa<cir::IntType>(complexElemTy)) {
1476 components[0] = rewriter.getIntegerAttr(
1478 mlir::cast<cir::IntAttr>(complexAttr.getReal()).getValue());
1479 components[1] = rewriter.getIntegerAttr(
1481 mlir::cast<cir::IntAttr>(complexAttr.getImag()).getValue());
1483 components[0] = rewriter.getFloatAttr(
1485 mlir::cast<cir::FPAttr>(complexAttr.getReal()).getValue());
1486 components[1] = rewriter.getFloatAttr(
1488 mlir::cast<cir::FPAttr>(complexAttr.getImag()).getValue());
1491 attr = rewriter.getArrayAttr(components);
1493 return op.emitError() <<
"unsupported constant type " << op.getType();
1496 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
1497 op, getTypeConverter()->convertType(op.getType()),
attr);
1499 return mlir::success();
1502mlir::LogicalResult CIRToLLVMExpectOpLowering::matchAndRewrite(
1503 cir::ExpectOp op, OpAdaptor adaptor,
1504 mlir::ConversionPatternRewriter &rewriter)
const {
1508 std::optional<llvm::APFloat> prob = op.getProb();
1510 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpectWithProbabilityOp>(
1511 op, adaptor.getVal(), adaptor.getExpected(), prob.value());
1513 rewriter.replaceOpWithNewOp<mlir::LLVM::ExpectOp>(op, adaptor.getVal(),
1514 adaptor.getExpected());
1515 return mlir::success();
1518mlir::LogicalResult CIRToLLVMFAbsOpLowering::matchAndRewrite(
1519 cir::FAbsOp op, OpAdaptor adaptor,
1520 mlir::ConversionPatternRewriter &rewriter)
const {
1521 mlir::Type resTy = typeConverter->convertType(op.getType());
1522 rewriter.replaceOpWithNewOp<mlir::LLVM::FAbsOp>(op, resTy,
1523 adaptor.getOperands()[0]);
1524 return mlir::success();
1531void CIRToLLVMFuncOpLowering::lowerFuncAttributes(
1532 cir::FuncOp func,
bool filterArgAndResAttrs,
1533 SmallVectorImpl<mlir::NamedAttribute> &result)
const {
1535 for (mlir::NamedAttribute attr : func->getAttrs()) {
1537 if (
attr.getName() == mlir::SymbolTable::getSymbolAttrName() ||
1538 attr.getName() == func.getFunctionTypeAttrName() ||
1540 attr.getName() == func.getGlobalVisibilityAttrName() ||
1541 attr.getName() == func.getDsoLocalAttrName() ||
1542 (filterArgAndResAttrs &&
1543 (
attr.getName() == func.getArgAttrsAttrName() ||
1544 attr.getName() == func.getResAttrsAttrName())))
1548 result.push_back(attr);
1552mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewriteAlias(
1553 cir::FuncOp op, llvm::StringRef aliasee, mlir::Type ty, OpAdaptor adaptor,
1554 mlir::ConversionPatternRewriter &rewriter)
const {
1555 SmallVector<mlir::NamedAttribute, 4> attributes;
1556 lowerFuncAttributes(op,
false, attributes);
1558 mlir::Location loc = op.getLoc();
1559 auto aliasOp = rewriter.replaceOpWithNewOp<mlir::LLVM::AliasOp>(
1560 op, ty,
convertLinkage(op.getLinkage()), op.getName(), op.getDsoLocal(),
1564 mlir::OpBuilder builder(op.getContext());
1565 mlir::Block *block = builder.createBlock(&aliasOp.getInitializerRegion());
1566 builder.setInsertionPointToStart(block);
1569 mlir::Type ptrTy = mlir::LLVM::LLVMPointerType::get(ty.getContext());
1570 auto addrOp = mlir::LLVM::AddressOfOp::create(builder, loc, ptrTy, aliasee);
1571 mlir::LLVM::ReturnOp::create(builder, loc, addrOp);
1573 return mlir::success();
1576mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewrite(
1577 cir::FuncOp op, OpAdaptor adaptor,
1578 mlir::ConversionPatternRewriter &rewriter)
const {
1580 cir::FuncType fnType = op.getFunctionType();
1581 bool isDsoLocal = op.getDsoLocal();
1582 mlir::TypeConverter::SignatureConversion signatureConversion(
1583 fnType.getNumInputs());
1585 for (
const auto &argType : llvm::enumerate(fnType.getInputs())) {
1586 mlir::Type convertedType = typeConverter->convertType(argType.value());
1588 return mlir::failure();
1589 signatureConversion.addInputs(argType.index(), convertedType);
1592 mlir::Type resultType =
1593 getTypeConverter()->convertType(fnType.getReturnType());
1596 mlir::Type llvmFnTy = mlir::LLVM::LLVMFunctionType::get(
1597 resultType ? resultType : mlir::LLVM::LLVMVoidType::get(getContext()),
1598 signatureConversion.getConvertedTypes(),
1602 if (std::optional<llvm::StringRef> aliasee = op.getAliasee())
1603 return matchAndRewriteAlias(op, *aliasee, llvmFnTy, adaptor, rewriter);
1607 mlir::Location loc = op.getLoc();
1608 if (mlir::FusedLoc fusedLoc = mlir::dyn_cast<mlir::FusedLoc>(loc))
1609 loc = fusedLoc.getLocations()[0];
1610 assert((mlir::isa<mlir::FileLineColLoc>(loc) ||
1611 mlir::isa<mlir::UnknownLoc>(loc)) &&
1612 "expected single location or unknown location here");
1616 mlir::LLVM::CConv cconv = mlir::LLVM::CConv::C;
1617 SmallVector<mlir::NamedAttribute, 4> attributes;
1618 lowerFuncAttributes(op,
false, attributes);
1620 mlir::LLVM::LLVMFuncOp fn = rewriter.create<mlir::LLVM::LLVMFuncOp>(
1621 loc, op.getName(), llvmFnTy, linkage, isDsoLocal, cconv,
1622 mlir::SymbolRefAttr(), attributes);
1626 fn.setVisibility_Attr(mlir::LLVM::VisibilityAttr::get(
1628 op.getGlobalVisibilityAttr().getValue())));
1630 rewriter.inlineRegionBefore(op.getBody(), fn.getBody(), fn.end());
1631 if (failed(rewriter.convertRegionTypes(&fn.getBody(), *typeConverter,
1632 &signatureConversion)))
1633 return mlir::failure();
1635 rewriter.eraseOp(op);
1637 return mlir::LogicalResult::success();
1640mlir::LogicalResult CIRToLLVMGetGlobalOpLowering::matchAndRewrite(
1641 cir::GetGlobalOp op, OpAdaptor adaptor,
1642 mlir::ConversionPatternRewriter &rewriter)
const {
1645 if (op->getUses().empty()) {
1646 rewriter.eraseOp(op);
1647 return mlir::success();
1650 mlir::Type
type = getTypeConverter()->convertType(op.getType());
1651 mlir::Operation *newop =
1652 rewriter.create<mlir::LLVM::AddressOfOp>(op.getLoc(), type, op.getName());
1656 rewriter.replaceOp(op, newop);
1657 return mlir::success();
1662void CIRToLLVMGlobalOpLowering::setupRegionInitializedLLVMGlobalOp(
1663 cir::GlobalOp op, mlir::ConversionPatternRewriter &rewriter)
const {
1664 const mlir::Type llvmType =
1672 const bool isConst = op.getConstant();
1674 const unsigned addrSpace = 0;
1675 const bool isDsoLocal = op.getDsoLocal();
1677 const bool isThreadLocal =
false;
1678 const uint64_t alignment = op.getAlignment().value_or(0);
1679 const mlir::LLVM::Linkage linkage =
convertLinkage(op.getLinkage());
1680 const StringRef symbol = op.getSymName();
1681 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
1683 SmallVector<mlir::NamedAttribute> attributes;
1684 mlir::LLVM::GlobalOp newGlobalOp =
1685 rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
1686 op, llvmType, isConst, linkage, symbol,
nullptr, alignment, addrSpace,
1687 isDsoLocal, isThreadLocal, comdatAttr, attributes);
1688 newGlobalOp.getRegion().emplaceBlock();
1689 rewriter.setInsertionPointToEnd(newGlobalOp.getInitializerBlock());
1693CIRToLLVMGlobalOpLowering::matchAndRewriteRegionInitializedGlobal(
1694 cir::GlobalOp op, mlir::Attribute init,
1695 mlir::ConversionPatternRewriter &rewriter)
const {
1697 assert((isa<cir::ConstArrayAttr, cir::ConstRecordAttr, cir::ConstVectorAttr,
1698 cir::ConstPtrAttr, cir::ConstComplexAttr, cir::GlobalViewAttr,
1699 cir::TypeInfoAttr, cir::VTableAttr, cir::ZeroAttr>(init)));
1704 const mlir::Location loc = op.getLoc();
1705 setupRegionInitializedLLVMGlobalOp(op, rewriter);
1707 mlir::Value value = valueConverter.visit(init);
1708 rewriter.create<mlir::LLVM::ReturnOp>(loc, value);
1709 return mlir::success();
1712mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite(
1713 cir::GlobalOp op, OpAdaptor adaptor,
1714 mlir::ConversionPatternRewriter &rewriter)
const {
1717 if (!op.getCtorRegion().empty() || !op.getDtorRegion().empty())
1718 return op.emitError() <<
"GlobalOp ctor and dtor regions should be removed "
1719 "in LoweringPrepare";
1721 std::optional<mlir::Attribute> init = op.getInitialValue();
1724 const mlir::Type cirSymType = op.getSymType();
1727 const mlir::Type llvmType =
1732 const bool isConst =
false;
1734 const unsigned addrSpace = 0;
1735 const bool isDsoLocal = op.getDsoLocal();
1737 const bool isThreadLocal =
false;
1738 const uint64_t alignment = op.getAlignment().value_or(0);
1739 const mlir::LLVM::Linkage linkage =
convertLinkage(op.getLinkage());
1740 const StringRef symbol = op.getSymName();
1741 SmallVector<mlir::NamedAttribute> attributes;
1743 if (init.has_value()) {
1744 if (mlir::isa<cir::FPAttr, cir::IntAttr, cir::BoolAttr>(init.value())) {
1746 init = initRewriter.visit(init.value());
1751 if (!init.value()) {
1752 op.emitError() <<
"unsupported initializer '" << init.value() <<
"'";
1753 return mlir::failure();
1755 }
else if (mlir::isa<cir::ConstArrayAttr, cir::ConstVectorAttr,
1756 cir::ConstRecordAttr, cir::ConstPtrAttr,
1757 cir::ConstComplexAttr, cir::GlobalViewAttr,
1758 cir::TypeInfoAttr, cir::VTableAttr, cir::ZeroAttr>(
1763 return matchAndRewriteRegionInitializedGlobal(op, init.value(), rewriter);
1767 op.emitError() <<
"unsupported initializer '" << init.value() <<
"'";
1768 return mlir::failure();
1773 mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
1774 auto newOp = rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
1775 op, llvmType, isConst, linkage, symbol, init.value_or(mlir::Attribute()),
1776 alignment, addrSpace, isDsoLocal, isThreadLocal, comdatAttr, attributes);
1777 newOp.setVisibility_Attr(mlir::LLVM::VisibilityAttr::get(
1779 op.getGlobalVisibilityAttr().getValue())));
1781 return mlir::success();
1785CIRToLLVMGlobalOpLowering::getComdatAttr(cir::GlobalOp &op,
1786 mlir::OpBuilder &builder)
const {
1787 if (!op.getComdat())
1788 return mlir::SymbolRefAttr{};
1790 mlir::ModuleOp module = op->getParentOfType<mlir::ModuleOp>();
1791 mlir::OpBuilder::InsertionGuard guard(builder);
1792 StringRef comdatName(
"__llvm_comdat_globals");
1794 builder.setInsertionPointToStart(module.getBody());
1796 mlir::LLVM::ComdatOp::create(builder, module.getLoc(), comdatName);
1799 if (
auto comdatSelector = comdatOp.lookupSymbol<mlir::LLVM::ComdatSelectorOp>(
1801 return mlir::SymbolRefAttr::get(
1802 builder.getContext(), comdatName,
1803 mlir::FlatSymbolRefAttr::get(comdatSelector.getSymNameAttr()));
1806 builder.setInsertionPointToStart(&comdatOp.getBody().back());
1807 auto selectorOp = mlir::LLVM::ComdatSelectorOp::create(
1808 builder, comdatOp.getLoc(), op.getSymName(),
1809 mlir::LLVM::comdat::Comdat::Any);
1810 return mlir::SymbolRefAttr::get(
1811 builder.getContext(), comdatName,
1812 mlir::FlatSymbolRefAttr::get(selectorOp.getSymNameAttr()));
1815mlir::LogicalResult CIRToLLVMSwitchFlatOpLowering::matchAndRewrite(
1816 cir::SwitchFlatOp op, OpAdaptor adaptor,
1817 mlir::ConversionPatternRewriter &rewriter)
const {
1819 llvm::SmallVector<mlir::APInt, 8> caseValues;
1820 for (mlir::Attribute val : op.getCaseValues()) {
1821 auto intAttr = cast<cir::IntAttr>(val);
1822 caseValues.push_back(intAttr.getValue());
1825 llvm::SmallVector<mlir::Block *, 8> caseDestinations;
1826 llvm::SmallVector<mlir::ValueRange, 8> caseOperands;
1828 for (mlir::Block *x : op.getCaseDestinations())
1829 caseDestinations.push_back(x);
1831 for (mlir::OperandRange x : op.getCaseOperands())
1832 caseOperands.push_back(x);
1835 rewriter.setInsertionPoint(op);
1836 rewriter.replaceOpWithNewOp<mlir::LLVM::SwitchOp>(
1837 op, adaptor.getCondition(), op.getDefaultDestination(),
1838 op.getDefaultOperands(), caseValues, caseDestinations, caseOperands);
1839 return mlir::success();
1842mlir::LogicalResult CIRToLLVMUnaryOpLowering::matchAndRewrite(
1843 cir::UnaryOp op, OpAdaptor adaptor,
1844 mlir::ConversionPatternRewriter &rewriter)
const {
1845 assert(op.getType() == op.getInput().getType() &&
1846 "Unary operation's operand type and result type are different");
1847 mlir::Type
type = op.getType();
1848 mlir::Type elementType = elementTypeIfVector(type);
1849 bool isVector = mlir::isa<cir::VectorType>(type);
1850 mlir::Type llvmType = getTypeConverter()->convertType(type);
1851 mlir::Location loc = op.getLoc();
1854 if (mlir::isa<cir::IntType>(elementType)) {
1855 mlir::LLVM::IntegerOverflowFlags maybeNSW =
1856 op.getNoSignedWrap() ? mlir::LLVM::IntegerOverflowFlags::nsw
1857 : mlir::LLVM::IntegerOverflowFlags::none;
1858 switch (op.getKind()) {
1859 case cir::UnaryOpKind::Inc: {
1860 assert(!
isVector &&
"++ not allowed on vector types");
1861 auto one = rewriter.create<mlir::LLVM::ConstantOp>(loc, llvmType, 1);
1862 rewriter.replaceOpWithNewOp<mlir::LLVM::AddOp>(
1863 op, llvmType, adaptor.getInput(), one, maybeNSW);
1864 return mlir::success();
1866 case cir::UnaryOpKind::Dec: {
1867 assert(!
isVector &&
"-- not allowed on vector types");
1868 auto one = rewriter.create<mlir::LLVM::ConstantOp>(loc, llvmType, 1);
1869 rewriter.replaceOpWithNewOp<mlir::LLVM::SubOp>(op, adaptor.getInput(),
1871 return mlir::success();
1873 case cir::UnaryOpKind::Plus:
1874 rewriter.replaceOp(op, adaptor.getInput());
1875 return mlir::success();
1876 case cir::UnaryOpKind::Minus: {
1879 zero = rewriter.create<mlir::LLVM::ZeroOp>(loc, llvmType);
1881 zero = rewriter.create<mlir::LLVM::ConstantOp>(loc, llvmType, 0);
1882 rewriter.replaceOpWithNewOp<mlir::LLVM::SubOp>(
1883 op, zero, adaptor.getInput(), maybeNSW);
1884 return mlir::success();
1886 case cir::UnaryOpKind::Not: {
1888 mlir::Value minusOne;
1891 mlir::dyn_cast<cir::VectorType>(type).getSize();
1892 std::vector<int32_t> values(numElements, -1);
1893 mlir::DenseIntElementsAttr denseVec = rewriter.getI32VectorAttr(values);
1895 rewriter.create<mlir::LLVM::ConstantOp>(loc, llvmType, denseVec);
1897 minusOne = rewriter.create<mlir::LLVM::ConstantOp>(loc, llvmType, -1);
1899 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getInput(),
1901 return mlir::success();
1904 llvm_unreachable(
"Unexpected unary op for int");
1908 if (mlir::isa<cir::FPTypeInterface>(elementType)) {
1909 switch (op.getKind()) {
1910 case cir::UnaryOpKind::Inc: {
1911 assert(!
isVector &&
"++ not allowed on vector types");
1912 mlir::LLVM::ConstantOp one = rewriter.create<mlir::LLVM::ConstantOp>(
1913 loc, llvmType, rewriter.getFloatAttr(llvmType, 1.0));
1914 rewriter.replaceOpWithNewOp<mlir::LLVM::FAddOp>(op, llvmType, one,
1915 adaptor.getInput());
1916 return mlir::success();
1918 case cir::UnaryOpKind::Dec: {
1919 assert(!
isVector &&
"-- not allowed on vector types");
1920 mlir::LLVM::ConstantOp minusOne = rewriter.create<mlir::LLVM::ConstantOp>(
1921 loc, llvmType, rewriter.getFloatAttr(llvmType, -1.0));
1922 rewriter.replaceOpWithNewOp<mlir::LLVM::FAddOp>(op, llvmType, minusOne,
1923 adaptor.getInput());
1924 return mlir::success();
1926 case cir::UnaryOpKind::Plus:
1927 rewriter.replaceOp(op, adaptor.getInput());
1928 return mlir::success();
1929 case cir::UnaryOpKind::Minus:
1930 rewriter.replaceOpWithNewOp<mlir::LLVM::FNegOp>(op, llvmType,
1931 adaptor.getInput());
1932 return mlir::success();
1933 case cir::UnaryOpKind::Not:
1934 return op.emitError() <<
"Unary not is invalid for floating-point types";
1936 llvm_unreachable(
"Unexpected unary op for float");
1941 if (mlir::isa<cir::BoolType>(elementType)) {
1942 switch (op.getKind()) {
1943 case cir::UnaryOpKind::Inc:
1944 case cir::UnaryOpKind::Dec:
1945 case cir::UnaryOpKind::Plus:
1946 case cir::UnaryOpKind::Minus:
1949 return op.emitError() <<
"Unsupported unary operation on boolean type";
1950 case cir::UnaryOpKind::Not: {
1951 assert(!
isVector &&
"NYI: op! on vector mask");
1952 auto one = rewriter.create<mlir::LLVM::ConstantOp>(loc, llvmType, 1);
1953 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, adaptor.getInput(),
1955 return mlir::success();
1958 llvm_unreachable(
"Unexpected unary op for bool");
1963 if (mlir::isa<cir::PointerType>(elementType)) {
1964 switch (op.getKind()) {
1965 case cir::UnaryOpKind::Plus:
1966 rewriter.replaceOp(op, adaptor.getInput());
1967 return mlir::success();
1969 op.emitError() <<
"Unknown pointer unary operation during CIR lowering";
1970 return mlir::failure();
1974 return op.emitError() <<
"Unary operation has unsupported type: "
1978mlir::LLVM::IntegerOverflowFlags
1979CIRToLLVMBinOpLowering::getIntOverflowFlag(cir::BinOp op)
const {
1980 if (op.getNoUnsignedWrap())
1981 return mlir::LLVM::IntegerOverflowFlags::nuw;
1983 if (op.getNoSignedWrap())
1984 return mlir::LLVM::IntegerOverflowFlags::nsw;
1986 return mlir::LLVM::IntegerOverflowFlags::none;
1991 return mlir::isa<cir::IntType>(type)
1992 ? mlir::cast<cir::IntType>(type).isUnsigned()
1993 : mlir::cast<mlir::IntegerType>(type).isUnsigned();
1996mlir::LogicalResult CIRToLLVMBinOpLowering::matchAndRewrite(
1997 cir::BinOp op, OpAdaptor adaptor,
1998 mlir::ConversionPatternRewriter &rewriter)
const {
1999 if (adaptor.getLhs().getType() != adaptor.getRhs().getType())
2000 return op.emitError() <<
"inconsistent operands' types not supported yet";
2002 mlir::Type type = op.getRhs().getType();
2003 if (!mlir::isa<cir::IntType, cir::BoolType, cir::FPTypeInterface,
2004 mlir::IntegerType, cir::VectorType>(type))
2005 return op.emitError() <<
"operand type not supported yet";
2007 const mlir::Type llvmTy = getTypeConverter()->convertType(op.getType());
2008 const mlir::Type llvmEltTy = elementTypeIfVector(llvmTy);
2010 const mlir::Value rhs = adaptor.getRhs();
2011 const mlir::Value lhs = adaptor.getLhs();
2012 type = elementTypeIfVector(type);
2014 switch (op.getKind()) {
2015 case cir::BinOpKind::Add:
2016 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
2017 if (op.getSaturated()) {
2019 rewriter.replaceOpWithNewOp<mlir::LLVM::UAddSat>(op, lhs, rhs);
2022 rewriter.replaceOpWithNewOp<mlir::LLVM::SAddSat>(op, lhs, rhs);
2025 rewriter.replaceOpWithNewOp<mlir::LLVM::AddOp>(op, llvmTy, lhs, rhs,
2026 getIntOverflowFlag(op));
2028 rewriter.replaceOpWithNewOp<mlir::LLVM::FAddOp>(op, lhs, rhs);
2031 case cir::BinOpKind::Sub:
2032 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
2033 if (op.getSaturated()) {
2035 rewriter.replaceOpWithNewOp<mlir::LLVM::USubSat>(op, lhs, rhs);
2038 rewriter.replaceOpWithNewOp<mlir::LLVM::SSubSat>(op, lhs, rhs);
2041 rewriter.replaceOpWithNewOp<mlir::LLVM::SubOp>(op, llvmTy, lhs, rhs,
2042 getIntOverflowFlag(op));
2044 rewriter.replaceOpWithNewOp<mlir::LLVM::FSubOp>(op, lhs, rhs);
2047 case cir::BinOpKind::Mul:
2048 if (mlir::isa<mlir::IntegerType>(llvmEltTy))
2049 rewriter.replaceOpWithNewOp<mlir::LLVM::MulOp>(op, llvmTy, lhs, rhs,
2050 getIntOverflowFlag(op));
2052 rewriter.replaceOpWithNewOp<mlir::LLVM::FMulOp>(op, lhs, rhs);
2054 case cir::BinOpKind::Div:
2055 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
2058 rewriter.replaceOpWithNewOp<mlir::LLVM::UDivOp>(op, lhs, rhs);
2060 rewriter.replaceOpWithNewOp<mlir::LLVM::SDivOp>(op, lhs, rhs);
2062 rewriter.replaceOpWithNewOp<mlir::LLVM::FDivOp>(op, lhs, rhs);
2065 case cir::BinOpKind::Rem:
2066 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
2069 rewriter.replaceOpWithNewOp<mlir::LLVM::URemOp>(op, lhs, rhs);
2071 rewriter.replaceOpWithNewOp<mlir::LLVM::SRemOp>(op, lhs, rhs);
2073 rewriter.replaceOpWithNewOp<mlir::LLVM::FRemOp>(op, lhs, rhs);
2076 case cir::BinOpKind::And:
2077 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(op, lhs, rhs);
2079 case cir::BinOpKind::Or:
2080 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(op, lhs, rhs);
2082 case cir::BinOpKind::Xor:
2083 rewriter.replaceOpWithNewOp<mlir::LLVM::XOrOp>(op, lhs, rhs);
2085 case cir::BinOpKind::Max:
2086 if (mlir::isa<mlir::IntegerType>(llvmEltTy)) {
2089 rewriter.replaceOpWithNewOp<mlir::LLVM::UMaxOp>(op, llvmTy, lhs, rhs);
2091 rewriter.replaceOpWithNewOp<mlir::LLVM::SMaxOp>(op, llvmTy, lhs, rhs);
2095 return mlir::LogicalResult::success();
2099static mlir::LLVM::ICmpPredicate
2101 using CIR = cir::CmpOpKind;
2102 using LLVMICmp = mlir::LLVM::ICmpPredicate;
2105 return LLVMICmp::eq;
2107 return LLVMICmp::ne;
2109 return (isSigned ? LLVMICmp::slt : LLVMICmp::ult);
2111 return (isSigned ? LLVMICmp::sle : LLVMICmp::ule);
2113 return (isSigned ? LLVMICmp::sgt : LLVMICmp::ugt);
2115 return (isSigned ? LLVMICmp::sge : LLVMICmp::uge);
2117 llvm_unreachable(
"Unknown CmpOpKind");
2122static mlir::LLVM::FCmpPredicate
2124 using CIR = cir::CmpOpKind;
2125 using LLVMFCmp = mlir::LLVM::FCmpPredicate;
2128 return LLVMFCmp::oeq;
2130 return LLVMFCmp::une;
2132 return LLVMFCmp::olt;
2134 return LLVMFCmp::ole;
2136 return LLVMFCmp::ogt;
2138 return LLVMFCmp::oge;
2140 llvm_unreachable(
"Unknown CmpOpKind");
2143mlir::LogicalResult CIRToLLVMCmpOpLowering::matchAndRewrite(
2144 cir::CmpOp cmpOp, OpAdaptor adaptor,
2145 mlir::ConversionPatternRewriter &rewriter)
const {
2146 mlir::Type type = cmpOp.getLhs().getType();
2151 if (mlir::isa<cir::IntType, mlir::IntegerType>(type)) {
2152 bool isSigned = mlir::isa<cir::IntType>(type)
2153 ? mlir::cast<cir::IntType>(type).isSigned()
2154 : mlir::cast<mlir::IntegerType>(type).isSigned();
2155 mlir::LLVM::ICmpPredicate kind =
2157 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
2158 cmpOp, kind, adaptor.getLhs(), adaptor.getRhs());
2159 return mlir::success();
2162 if (
auto ptrTy = mlir::dyn_cast<cir::PointerType>(type)) {
2163 mlir::LLVM::ICmpPredicate kind =
2166 rewriter.replaceOpWithNewOp<mlir::LLVM::ICmpOp>(
2167 cmpOp, kind, adaptor.getLhs(), adaptor.getRhs());
2168 return mlir::success();
2171 if (mlir::isa<cir::FPTypeInterface>(type)) {
2172 mlir::LLVM::FCmpPredicate
kind =
2174 rewriter.replaceOpWithNewOp<mlir::LLVM::FCmpOp>(
2175 cmpOp,
kind, adaptor.getLhs(), adaptor.getRhs());
2176 return mlir::success();
2179 if (mlir::isa<cir::ComplexType>(type)) {
2180 mlir::Value lhs = adaptor.getLhs();
2181 mlir::Value rhs = adaptor.getRhs();
2182 mlir::Location loc = cmpOp.getLoc();
2184 auto complexType = mlir::cast<cir::ComplexType>(cmpOp.getLhs().getType());
2185 mlir::Type complexElemTy =
2186 getTypeConverter()->convertType(
complexType.getElementType());
2189 rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, lhs, 0);
2191 rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, lhs, 1);
2193 rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, rhs, 0);
2195 rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, rhs, 1);
2197 if (cmpOp.getKind() == cir::CmpOpKind::eq) {
2198 if (complexElemTy.isInteger()) {
2199 auto realCmp = rewriter.create<mlir::LLVM::ICmpOp>(
2200 loc, mlir::LLVM::ICmpPredicate::eq, lhsReal, rhsReal);
2201 auto imagCmp = rewriter.create<mlir::LLVM::ICmpOp>(
2202 loc, mlir::LLVM::ICmpPredicate::eq, lhsImag, rhsImag);
2203 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, imagCmp);
2204 return mlir::success();
2207 auto realCmp = rewriter.create<mlir::LLVM::FCmpOp>(
2208 loc, mlir::LLVM::FCmpPredicate::oeq, lhsReal, rhsReal);
2209 auto imagCmp = rewriter.create<mlir::LLVM::FCmpOp>(
2210 loc, mlir::LLVM::FCmpPredicate::oeq, lhsImag, rhsImag);
2211 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(cmpOp, realCmp, imagCmp);
2212 return mlir::success();
2215 if (cmpOp.getKind() == cir::CmpOpKind::ne) {
2216 if (complexElemTy.isInteger()) {
2217 auto realCmp = rewriter.create<mlir::LLVM::ICmpOp>(
2218 loc, mlir::LLVM::ICmpPredicate::ne, lhsReal, rhsReal);
2219 auto imagCmp = rewriter.create<mlir::LLVM::ICmpOp>(
2220 loc, mlir::LLVM::ICmpPredicate::ne, lhsImag, rhsImag);
2221 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp);
2222 return mlir::success();
2225 auto realCmp = rewriter.create<mlir::LLVM::FCmpOp>(
2226 loc, mlir::LLVM::FCmpPredicate::une, lhsReal, rhsReal);
2227 auto imagCmp = rewriter.create<mlir::LLVM::FCmpOp>(
2228 loc, mlir::LLVM::FCmpPredicate::une, lhsImag, rhsImag);
2229 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(cmpOp, realCmp, imagCmp);
2230 return mlir::success();
2234 return cmpOp.emitError() <<
"unsupported type for CmpOp: " <<
type;
2237mlir::LogicalResult CIRToLLVMShiftOpLowering::matchAndRewrite(
2238 cir::ShiftOp op, OpAdaptor adaptor,
2239 mlir::ConversionPatternRewriter &rewriter)
const {
2240 assert((op.getValue().getType() == op.getType()) &&
2241 "inconsistent operands' types NYI");
2243 const mlir::Type llvmTy = getTypeConverter()->convertType(op.getType());
2244 mlir::Value amt = adaptor.getAmount();
2245 mlir::Value val = adaptor.getValue();
2247 auto cirAmtTy = mlir::dyn_cast<cir::IntType>(op.getAmount().getType());
2250 auto cirValTy = mlir::cast<cir::IntType>(op.getValue().getType());
2258 amt =
getLLVMIntCast(rewriter, amt, llvmTy,
true, cirAmtTy.getWidth(),
2259 cirValTy.getWidth());
2261 auto cirValVTy = mlir::cast<cir::VectorType>(op.getValue().getType());
2263 mlir::cast<cir::IntType>(cirValVTy.getElementType()).isUnsigned();
2267 if (op.getIsShiftleft()) {
2268 rewriter.replaceOpWithNewOp<mlir::LLVM::ShlOp>(op, llvmTy, val, amt);
2269 return mlir::success();
2273 rewriter.replaceOpWithNewOp<mlir::LLVM::LShrOp>(op, llvmTy, val, amt);
2275 rewriter.replaceOpWithNewOp<mlir::LLVM::AShrOp>(op, llvmTy, val, amt);
2276 return mlir::success();
2279mlir::LogicalResult CIRToLLVMSelectOpLowering::matchAndRewrite(
2280 cir::SelectOp op, OpAdaptor adaptor,
2281 mlir::ConversionPatternRewriter &rewriter)
const {
2282 auto getConstantBool = [](mlir::Value value) -> cir::BoolAttr {
2283 auto definingOp = value.getDefiningOp<cir::ConstantOp>();
2287 auto constValue = definingOp.getValueAttr<cir::BoolAttr>();
2297 if (mlir::isa<cir::BoolType>(op.getTrueValue().getType())) {
2298 cir::BoolAttr trueValue = getConstantBool(op.getTrueValue());
2299 cir::BoolAttr falseValue = getConstantBool(op.getFalseValue());
2300 if (falseValue && !falseValue.getValue()) {
2302 rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(op, adaptor.getCondition(),
2303 adaptor.getTrueValue());
2304 return mlir::success();
2306 if (trueValue && trueValue.getValue()) {
2308 rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(op, adaptor.getCondition(),
2309 adaptor.getFalseValue());
2310 return mlir::success();
2314 mlir::Value llvmCondition = adaptor.getCondition();
2315 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(
2316 op, llvmCondition, adaptor.getTrueValue(), adaptor.getFalseValue());
2318 return mlir::success();
2322 mlir::DataLayout &dataLayout) {
2323 converter.addConversion([&](cir::PointerType type) -> mlir::Type {
2324 unsigned addrSpace =
2325 type.getAddrSpace() ? type.getAddrSpace().getValue().getUInt() : 0;
2326 return mlir::LLVM::LLVMPointerType::get(type.getContext(), addrSpace);
2328 converter.addConversion([&](cir::VPtrType type) -> mlir::Type {
2330 return mlir::LLVM::LLVMPointerType::get(type.getContext());
2332 converter.addConversion([&](cir::ArrayType type) -> mlir::Type {
2335 return mlir::LLVM::LLVMArrayType::get(ty, type.getSize());
2337 converter.addConversion([&](cir::VectorType type) -> mlir::Type {
2338 const mlir::Type ty = converter.convertType(type.getElementType());
2339 return mlir::VectorType::get(type.getSize(), ty);
2341 converter.addConversion([&](cir::BoolType type) -> mlir::Type {
2342 return mlir::IntegerType::get(type.getContext(), 1,
2343 mlir::IntegerType::Signless);
2345 converter.addConversion([&](cir::IntType type) -> mlir::Type {
2347 return mlir::IntegerType::get(type.getContext(), type.getWidth());
2349 converter.addConversion([&](cir::SingleType type) -> mlir::Type {
2350 return mlir::Float32Type::get(type.getContext());
2352 converter.addConversion([&](cir::DoubleType type) -> mlir::Type {
2353 return mlir::Float64Type::get(type.getContext());
2355 converter.addConversion([&](cir::FP80Type type) -> mlir::Type {
2356 return mlir::Float80Type::get(type.getContext());
2358 converter.addConversion([&](cir::FP128Type type) -> mlir::Type {
2359 return mlir::Float128Type::get(type.getContext());
2361 converter.addConversion([&](cir::LongDoubleType type) -> mlir::Type {
2362 return converter.convertType(type.getUnderlying());
2364 converter.addConversion([&](cir::FP16Type type) -> mlir::Type {
2365 return mlir::Float16Type::get(type.getContext());
2367 converter.addConversion([&](cir::BF16Type type) -> mlir::Type {
2368 return mlir::BFloat16Type::get(type.getContext());
2370 converter.addConversion([&](cir::ComplexType type) -> mlir::Type {
2373 mlir::Type elementTy = converter.convertType(type.getElementType());
2374 mlir::Type structFields[2] = {elementTy, elementTy};
2375 return mlir::LLVM::LLVMStructType::getLiteral(type.getContext(),
2378 converter.addConversion([&](cir::FuncType type) -> std::optional<mlir::Type> {
2379 auto result = converter.convertType(type.getReturnType());
2381 arguments.reserve(type.getNumInputs());
2382 if (converter.convertTypes(type.getInputs(), arguments).failed())
2383 return std::nullopt;
2384 auto varArg = type.isVarArg();
2385 return mlir::LLVM::LLVMFunctionType::get(result, arguments, varArg);
2387 converter.addConversion([&](cir::RecordType type) -> mlir::Type {
2390 switch (type.getKind()) {
2391 case cir::RecordType::Class:
2392 case cir::RecordType::Struct:
2393 for (mlir::Type ty : type.getMembers())
2397 case cir::RecordType::Union:
2398 if (
auto largestMember = type.getLargestMember(dataLayout))
2399 llvmMembers.push_back(
2401 if (type.getPadded()) {
2402 auto last = *type.getMembers().rbegin();
2403 llvmMembers.push_back(
2410 mlir::LLVM::LLVMStructType llvmStruct;
2411 if (type.getName()) {
2412 llvmStruct = mlir::LLVM::LLVMStructType::getIdentified(
2413 type.getContext(), type.getPrefixedName());
2414 if (llvmStruct.setBody(llvmMembers, type.getPacked()).failed())
2415 llvm_unreachable(
"Failed to set body of record");
2417 llvmStruct = mlir::LLVM::LLVMStructType::getLiteral(
2418 type.getContext(), llvmMembers, type.getPacked());
2423 converter.addConversion([&](cir::VoidType type) -> mlir::Type {
2424 return mlir::LLVM::LLVMVoidType::get(type.getContext());
2429 mlir::ModuleOp module, StringRef globalXtorName, StringRef llvmXtorName,
2430 llvm::function_ref<std::pair<StringRef, int>(mlir::Attribute)> createXtor) {
2432 for (
const mlir::NamedAttribute namedAttr : module->getAttrs()) {
2433 if (namedAttr.getName() == globalXtorName) {
2434 for (
auto attr : mlir::cast<mlir::ArrayAttr>(namedAttr.getValue()))
2435 globalXtors.emplace_back(createXtor(attr));
2440 if (globalXtors.empty())
2443 mlir::OpBuilder builder(module.getContext());
2444 builder.setInsertionPointToEnd(&module.getBodyRegion().back());
2448 auto ctorPFTy = mlir::LLVM::LLVMPointerType::get(builder.getContext());
2450 ctorStructFields.push_back(builder.getI32Type());
2451 ctorStructFields.push_back(ctorPFTy);
2452 ctorStructFields.push_back(ctorPFTy);
2454 auto ctorStructTy = mlir::LLVM::LLVMStructType::getLiteral(
2455 builder.getContext(), ctorStructFields);
2456 auto ctorStructArrayTy =
2457 mlir::LLVM::LLVMArrayType::get(ctorStructTy, globalXtors.size());
2459 mlir::Location loc =
module.getLoc();
2460 auto newGlobalOp = mlir::LLVM::GlobalOp::create(
2461 builder, loc, ctorStructArrayTy,
false,
2462 mlir::LLVM::Linkage::Appending, llvmXtorName, mlir::Attribute());
2464 builder.createBlock(&newGlobalOp.getRegion());
2465 builder.setInsertionPointToEnd(newGlobalOp.getInitializerBlock());
2467 mlir::Value result =
2468 mlir::LLVM::UndefOp::create(builder, loc, ctorStructArrayTy);
2470 for (
auto [index, fn] : llvm::enumerate(globalXtors)) {
2471 mlir::Value structInit =
2472 mlir::LLVM::UndefOp::create(builder, loc, ctorStructTy);
2473 mlir::Value initPriority = mlir::LLVM::ConstantOp::create(
2474 builder, loc, ctorStructFields[0], fn.second);
2475 mlir::Value initFuncAddr = mlir::LLVM::AddressOfOp::create(
2476 builder, loc, ctorStructFields[1], fn.first);
2477 mlir::Value initAssociate =
2478 mlir::LLVM::ZeroOp::create(builder, loc, ctorStructFields[2]);
2481 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
2482 initPriority, zero);
2483 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
2486 structInit = mlir::LLVM::InsertValueOp::create(builder, loc, structInit,
2488 result = mlir::LLVM::InsertValueOp::create(builder, loc, result, structInit,
2492 builder.create<mlir::LLVM::ReturnOp>(loc, result);
2530 parent->walk([&](mlir::Block *blk) {
2531 if (blk->hasNoPredecessors() && !blk->isEntryBlock())
2532 unreachableBlocks.push_back(blk);
2535 std::set<mlir::Block *> visited;
2536 for (mlir::Block *root : unreachableBlocks) {
2539 std::deque<mlir::Block *> workList;
2540 workList.push_back(root);
2542 while (!workList.empty()) {
2543 mlir::Block *blk = workList.back();
2544 workList.pop_back();
2545 if (visited.count(blk))
2547 visited.emplace(blk);
2549 for (mlir::Operation &op : *blk)
2552 for (mlir::Block *succ : blk->getSuccessors())
2553 workList.push_back(succ);
2560 if (mlir::Attribute tripleAttr =
2561 module->getAttr(cir::CIRDialect::getTripleAttrName()))
2562 module->setAttr(mlir::LLVM::LLVMDialect::getTargetTripleAttrName(),
2565 if (mlir::Attribute asmAttr =
2566 module->getAttr(cir::CIRDialect::getModuleLevelAsmAttrName()))
2567 module->setAttr(mlir::LLVM::LLVMDialect::getModuleLevelAsmAttrName(),
2572 llvm::TimeTraceScope scope(
"Convert CIR to LLVM Pass");
2574 mlir::ModuleOp module = getOperation();
2575 mlir::DataLayout dl(module);
2576 mlir::LLVMTypeConverter converter(&getContext());
2579 mlir::RewritePatternSet patterns(&getContext());
2582#define GET_LLVM_LOWERING_PATTERNS_LIST
2583#include "clang/CIR/Dialect/IR/CIRLowering.inc"
2584#undef GET_LLVM_LOWERING_PATTERNS_LIST
2585 >(converter, patterns.getContext(), dl);
2589 mlir::ConversionTarget target(getContext());
2590 target.addLegalOp<mlir::ModuleOp>();
2591 target.addLegalDialect<mlir::LLVM::LLVMDialect>();
2592 target.addIllegalDialect<mlir::BuiltinDialect, cir::CIRDialect,
2593 mlir::func::FuncDialect>();
2596 ops.push_back(module);
2599 if (failed(applyPartialConversion(ops, target, std::move(patterns))))
2600 signalPassFailure();
2604 "llvm.global_ctors", [](mlir::Attribute attr) {
2605 auto ctorAttr = mlir::cast<cir::GlobalCtorAttr>(attr);
2606 return std::make_pair(ctorAttr.getName(),
2607 ctorAttr.getPriority());
2611 "llvm.global_dtors", [](mlir::Attribute attr) {
2612 auto dtorAttr = mlir::cast<cir::GlobalDtorAttr>(attr);
2613 return std::make_pair(dtorAttr.getName(),
2614 dtorAttr.getPriority());
2618mlir::LogicalResult CIRToLLVMBrOpLowering::matchAndRewrite(
2619 cir::BrOp op, OpAdaptor adaptor,
2620 mlir::ConversionPatternRewriter &rewriter)
const {
2621 rewriter.replaceOpWithNewOp<mlir::LLVM::BrOp>(op, adaptor.getOperands(),
2623 return mlir::LogicalResult::success();
2626mlir::LogicalResult CIRToLLVMGetMemberOpLowering::matchAndRewrite(
2627 cir::GetMemberOp op, OpAdaptor adaptor,
2628 mlir::ConversionPatternRewriter &rewriter)
const {
2629 mlir::Type llResTy = getTypeConverter()->convertType(op.getType());
2630 const auto recordTy =
2631 mlir::cast<cir::RecordType>(op.getAddrTy().getPointee());
2632 assert(recordTy &&
"expected record type");
2634 switch (recordTy.getKind()) {
2635 case cir::RecordType::Class:
2636 case cir::RecordType::Struct: {
2640 const mlir::Type elementTy = getTypeConverter()->convertType(recordTy);
2641 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, llResTy, elementTy,
2642 adaptor.getAddr(), offset);
2643 return mlir::success();
2645 case cir::RecordType::Union:
2648 rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(op, llResTy,
2650 return mlir::success();
2654mlir::LogicalResult CIRToLLVMUnreachableOpLowering::matchAndRewrite(
2655 cir::UnreachableOp op, OpAdaptor adaptor,
2656 mlir::ConversionPatternRewriter &rewriter)
const {
2657 rewriter.replaceOpWithNewOp<mlir::LLVM::UnreachableOp>(op);
2658 return mlir::success();
2662 mlir::Operation *srcOp, llvm::StringRef fnName,
2664 auto modOp = srcOp->getParentOfType<mlir::ModuleOp>();
2665 auto enclosingFnOp = srcOp->getParentOfType<mlir::LLVM::LLVMFuncOp>();
2666 mlir::Operation *sourceSymbol =
2667 mlir::SymbolTable::lookupSymbolIn(modOp, fnName);
2668 if (!sourceSymbol) {
2669 mlir::OpBuilder::InsertionGuard guard(rewriter);
2670 rewriter.setInsertionPoint(enclosingFnOp);
2671 rewriter.create<mlir::LLVM::LLVMFuncOp>(srcOp->getLoc(), fnName, fnTy);
2675mlir::LogicalResult CIRToLLVMThrowOpLowering::matchAndRewrite(
2676 cir::ThrowOp op, OpAdaptor adaptor,
2677 mlir::ConversionPatternRewriter &rewriter)
const {
2678 mlir::Location loc = op.getLoc();
2679 auto voidTy = mlir::LLVM::LLVMVoidType::get(getContext());
2681 if (op.rethrows()) {
2682 auto funcTy = mlir::LLVM::LLVMFunctionType::get(voidTy, {});
2685 const llvm::StringRef functionName =
"__cxa_rethrow";
2688 auto cxaRethrow = mlir::LLVM::CallOp::create(
2689 rewriter, loc, mlir::TypeRange{}, functionName);
2691 rewriter.replaceOp(op, cxaRethrow);
2692 return mlir::success();
2695 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
2696 auto fnTy = mlir::LLVM::LLVMFunctionType::get(
2697 voidTy, {llvmPtrTy, llvmPtrTy, llvmPtrTy});
2700 const llvm::StringRef fnName =
"__cxa_throw";
2703 mlir::Value typeInfo = mlir::LLVM::AddressOfOp::create(
2704 rewriter, loc, mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
2705 adaptor.getTypeInfoAttr());
2709 dtor = mlir::LLVM::AddressOfOp::create(rewriter, loc, llvmPtrTy,
2710 adaptor.getDtorAttr());
2712 dtor = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmPtrTy);
2715 auto cxaThrowCall = mlir::LLVM::CallOp::create(
2716 rewriter, loc, mlir::TypeRange{}, fnName,
2717 mlir::ValueRange{adaptor.getExceptionPtr(), typeInfo, dtor});
2719 rewriter.replaceOp(op, cxaThrowCall);
2720 return mlir::success();
2723mlir::LogicalResult CIRToLLVMAllocExceptionOpLowering::matchAndRewrite(
2724 cir::AllocExceptionOp op, OpAdaptor adaptor,
2725 mlir::ConversionPatternRewriter &rewriter)
const {
2727 StringRef fnName =
"__cxa_allocate_exception";
2728 auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
2729 auto int64Ty = mlir::IntegerType::get(rewriter.getContext(), 64);
2730 auto fnTy = mlir::LLVM::LLVMFunctionType::get(llvmPtrTy, {int64Ty});
2733 auto exceptionSize = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(),
2734 adaptor.getSizeAttr());
2736 auto allocaExceptionCall = mlir::LLVM::CallOp::create(
2737 rewriter, op.getLoc(), mlir::TypeRange{llvmPtrTy}, fnName,
2738 mlir::ValueRange{exceptionSize});
2740 rewriter.replaceOp(op, allocaExceptionCall);
2741 return mlir::success();
2744mlir::LogicalResult CIRToLLVMTrapOpLowering::matchAndRewrite(
2745 cir::TrapOp op, OpAdaptor adaptor,
2746 mlir::ConversionPatternRewriter &rewriter)
const {
2747 mlir::Location loc = op->getLoc();
2748 rewriter.eraseOp(op);
2750 rewriter.create<mlir::LLVM::Trap>(loc);
2755 rewriter.create<mlir::LLVM::UnreachableOp>(loc);
2757 return mlir::success();
2762 mlir::ConversionPatternRewriter &rewriter,
2763 const mlir::TypeConverter *converter,
2764 mlir::FlatSymbolRefAttr nameAttr, mlir::Type &eltType) {
2765 auto module = op->getParentOfType<mlir::ModuleOp>();
2766 mlir::Operation *symbol = mlir::SymbolTable::lookupSymbolIn(module, nameAttr);
2767 if (
auto llvmSymbol = mlir::dyn_cast<mlir::LLVM::GlobalOp>(symbol)) {
2768 eltType = llvmSymbol.getType();
2769 }
else if (
auto cirSymbol = mlir::dyn_cast<cir::GlobalOp>(symbol)) {
2770 eltType = converter->convertType(cirSymbol.getSymType());
2772 op->emitError() <<
"unexpected symbol type for " << symbol;
2776 return mlir::LLVM::AddressOfOp::create(
2777 rewriter, op->getLoc(),
2778 mlir::LLVM::LLVMPointerType::get(op->getContext()), nameAttr.getValue());
2781mlir::LogicalResult CIRToLLVMVTableAddrPointOpLowering::matchAndRewrite(
2782 cir::VTableAddrPointOp op, OpAdaptor adaptor,
2783 mlir::ConversionPatternRewriter &rewriter)
const {
2784 const mlir::TypeConverter *converter = getTypeConverter();
2785 mlir::Type targetType = converter->convertType(op.getType());
2789 op.getNameAttr(), eltType);
2791 return op.emitError() <<
"Unable to get value for vtable symbol";
2794 0, op.getAddressPointAttr().getIndex(),
2795 op.getAddressPointAttr().getOffset()};
2797 assert(eltType &&
"Shouldn't ever be missing an eltType here");
2798 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
2799 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
2800 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, targetType, eltType,
2801 symAddr, offsets, inboundsNuw);
2802 return mlir::success();
2805mlir::LogicalResult CIRToLLVMVTableGetVPtrOpLowering::matchAndRewrite(
2806 cir::VTableGetVPtrOp op, OpAdaptor adaptor,
2807 mlir::ConversionPatternRewriter &rewriter)
const {
2811 mlir::Value srcVal = adaptor.getSrc();
2812 rewriter.replaceOp(op, srcVal);
2813 return mlir::success();
2816mlir::LogicalResult CIRToLLVMVTableGetVirtualFnAddrOpLowering::matchAndRewrite(
2817 cir::VTableGetVirtualFnAddrOp op, OpAdaptor adaptor,
2818 mlir::ConversionPatternRewriter &rewriter)
const {
2819 mlir::Type targetType = getTypeConverter()->convertType(op.getType());
2820 auto eltType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
2821 llvm::SmallVector<mlir::LLVM::GEPArg> offsets =
2822 llvm::SmallVector<mlir::LLVM::GEPArg>{op.getIndex()};
2823 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
2824 op, targetType, eltType, adaptor.getVptr(), offsets,
2825 mlir::LLVM::GEPNoWrapFlags::inbounds);
2826 return mlir::success();
2829mlir::LogicalResult CIRToLLVMVTTAddrPointOpLowering::matchAndRewrite(
2830 cir::VTTAddrPointOp op, OpAdaptor adaptor,
2831 mlir::ConversionPatternRewriter &rewriter)
const {
2832 const mlir::Type resultType = getTypeConverter()->convertType(op.getType());
2833 llvm::SmallVector<mlir::LLVM::GEPArg> offsets;
2835 mlir::Value llvmAddr = adaptor.getSymAddr();
2837 if (op.getSymAddr()) {
2838 if (op.getOffset() == 0) {
2839 rewriter.replaceOp(op, {llvmAddr});
2840 return mlir::success();
2843 offsets.push_back(adaptor.getOffset());
2844 eltType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
2847 op.getNameAttr(), eltType);
2848 assert(eltType &&
"Shouldn't ever be missing an eltType here");
2849 offsets.push_back(0);
2850 offsets.push_back(adaptor.getOffset());
2852 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
2853 op, resultType, eltType, llvmAddr, offsets,
2854 mlir::LLVM::GEPNoWrapFlags::inbounds);
2855 return mlir::success();
2858mlir::LogicalResult CIRToLLVMStackSaveOpLowering::matchAndRewrite(
2859 cir::StackSaveOp op, OpAdaptor adaptor,
2860 mlir::ConversionPatternRewriter &rewriter)
const {
2861 const mlir::Type ptrTy = getTypeConverter()->convertType(op.getType());
2862 rewriter.replaceOpWithNewOp<mlir::LLVM::StackSaveOp>(op, ptrTy);
2863 return mlir::success();
2866mlir::LogicalResult CIRToLLVMStackRestoreOpLowering::matchAndRewrite(
2867 cir::StackRestoreOp op, OpAdaptor adaptor,
2868 mlir::ConversionPatternRewriter &rewriter)
const {
2869 rewriter.replaceOpWithNewOp<mlir::LLVM::StackRestoreOp>(op, adaptor.getPtr());
2870 return mlir::success();
2873mlir::LogicalResult CIRToLLVMVecCreateOpLowering::matchAndRewrite(
2874 cir::VecCreateOp op, OpAdaptor adaptor,
2875 mlir::ConversionPatternRewriter &rewriter)
const {
2878 const auto vecTy = mlir::cast<cir::VectorType>(op.getType());
2879 const mlir::Type llvmTy = typeConverter->convertType(vecTy);
2880 const mlir::Location loc = op.getLoc();
2881 mlir::Value result = rewriter.create<mlir::LLVM::PoisonOp>(loc, llvmTy);
2882 assert(vecTy.getSize() == op.getElements().size() &&
2883 "cir.vec.create op count doesn't match vector type elements count");
2885 for (uint64_t i = 0; i < vecTy.getSize(); ++i) {
2886 const mlir::Value indexValue =
2887 rewriter.create<mlir::LLVM::ConstantOp>(loc, rewriter.getI64Type(), i);
2888 result = rewriter.create<mlir::LLVM::InsertElementOp>(
2889 loc, result, adaptor.getElements()[i], indexValue);
2892 rewriter.replaceOp(op, result);
2893 return mlir::success();
2896mlir::LogicalResult CIRToLLVMVecExtractOpLowering::matchAndRewrite(
2897 cir::VecExtractOp op, OpAdaptor adaptor,
2898 mlir::ConversionPatternRewriter &rewriter)
const {
2899 rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractElementOp>(
2900 op, adaptor.getVec(), adaptor.getIndex());
2901 return mlir::success();
2904mlir::LogicalResult CIRToLLVMVecInsertOpLowering::matchAndRewrite(
2905 cir::VecInsertOp op, OpAdaptor adaptor,
2906 mlir::ConversionPatternRewriter &rewriter)
const {
2907 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertElementOp>(
2908 op, adaptor.getVec(), adaptor.getValue(), adaptor.getIndex());
2909 return mlir::success();
2912mlir::LogicalResult CIRToLLVMVecCmpOpLowering::matchAndRewrite(
2913 cir::VecCmpOp op, OpAdaptor adaptor,
2914 mlir::ConversionPatternRewriter &rewriter)
const {
2915 mlir::Type elementType = elementTypeIfVector(op.getLhs().getType());
2916 mlir::Value bitResult;
2917 if (
auto intType = mlir::dyn_cast<cir::IntType>(elementType)) {
2918 bitResult = rewriter.create<mlir::LLVM::ICmpOp>(
2921 adaptor.getLhs(), adaptor.getRhs());
2922 }
else if (mlir::isa<cir::FPTypeInterface>(elementType)) {
2923 bitResult = rewriter.create<mlir::LLVM::FCmpOp>(
2925 adaptor.getLhs(), adaptor.getRhs());
2927 return op.emitError() <<
"unsupported type for VecCmpOp: " << elementType;
2932 rewriter.replaceOpWithNewOp<mlir::LLVM::SExtOp>(
2933 op, typeConverter->convertType(op.getType()), bitResult);
2934 return mlir::success();
2937mlir::LogicalResult CIRToLLVMVecSplatOpLowering::matchAndRewrite(
2938 cir::VecSplatOp op, OpAdaptor adaptor,
2939 mlir::ConversionPatternRewriter &rewriter)
const {
2945 cir::VectorType vecTy = op.getType();
2946 mlir::Type llvmTy = typeConverter->convertType(vecTy);
2947 mlir::Location loc = op.getLoc();
2948 mlir::Value poison = rewriter.create<mlir::LLVM::PoisonOp>(loc, llvmTy);
2950 mlir::Value elementValue = adaptor.getValue();
2951 if (elementValue.getDefiningOp<mlir::LLVM::PoisonOp>()) {
2954 rewriter.replaceOp(op, poison);
2955 return mlir::success();
2958 if (
auto constValue = elementValue.getDefiningOp<mlir::LLVM::ConstantOp>()) {
2959 if (
auto intAttr = dyn_cast<mlir::IntegerAttr>(constValue.getValue())) {
2960 mlir::DenseIntElementsAttr denseVec = mlir::DenseIntElementsAttr::get(
2961 mlir::cast<mlir::ShapedType>(llvmTy), intAttr.getValue());
2962 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
2963 op, denseVec.getType(), denseVec);
2964 return mlir::success();
2967 if (
auto fpAttr = dyn_cast<mlir::FloatAttr>(constValue.getValue())) {
2968 mlir::DenseFPElementsAttr denseVec = mlir::DenseFPElementsAttr::get(
2969 mlir::cast<mlir::ShapedType>(llvmTy), fpAttr.getValue());
2970 rewriter.replaceOpWithNewOp<mlir::LLVM::ConstantOp>(
2971 op, denseVec.getType(), denseVec);
2972 return mlir::success();
2976 mlir::Value indexValue =
2977 rewriter.create<mlir::LLVM::ConstantOp>(loc, rewriter.getI64Type(), 0);
2978 mlir::Value oneElement = rewriter.create<mlir::LLVM::InsertElementOp>(
2979 loc, poison, elementValue, indexValue);
2980 SmallVector<int32_t> zeroValues(vecTy.getSize(), 0);
2981 rewriter.replaceOpWithNewOp<mlir::LLVM::ShuffleVectorOp>(op, oneElement,
2982 poison, zeroValues);
2983 return mlir::success();
2986mlir::LogicalResult CIRToLLVMVecShuffleOpLowering::matchAndRewrite(
2987 cir::VecShuffleOp op, OpAdaptor adaptor,
2988 mlir::ConversionPatternRewriter &rewriter)
const {
2992 SmallVector<int, 8> indices;
2994 op.getIndices().begin(), op.getIndices().end(),
2995 std::back_inserter(indices), [](mlir::Attribute intAttr) {
2996 return mlir::cast<cir::IntAttr>(intAttr).getValue().getSExtValue();
2998 rewriter.replaceOpWithNewOp<mlir::LLVM::ShuffleVectorOp>(
2999 op, adaptor.getVec1(), adaptor.getVec2(), indices);
3000 return mlir::success();
3003mlir::LogicalResult CIRToLLVMVecShuffleDynamicOpLowering::matchAndRewrite(
3004 cir::VecShuffleDynamicOp op, OpAdaptor adaptor,
3005 mlir::ConversionPatternRewriter &rewriter)
const {
3017 mlir::Location loc = op.getLoc();
3018 mlir::Value input = adaptor.getVec();
3019 mlir::Type llvmIndexVecType =
3020 getTypeConverter()->convertType(op.getIndices().getType());
3021 mlir::Type llvmIndexType = getTypeConverter()->convertType(
3022 elementTypeIfVector(op.getIndices().getType()));
3024 mlir::cast<cir::VectorType>(op.getVec().getType()).getSize();
3026 uint64_t maskBits = llvm::NextPowerOf2(numElements - 1) - 1;
3027 mlir::Value maskValue = rewriter.create<mlir::LLVM::ConstantOp>(
3028 loc, llvmIndexType, rewriter.getIntegerAttr(llvmIndexType, maskBits));
3029 mlir::Value maskVector =
3030 rewriter.create<mlir::LLVM::UndefOp>(loc, llvmIndexVecType);
3032 for (uint64_t i = 0; i < numElements; ++i) {
3033 mlir::Value idxValue =
3034 rewriter.create<mlir::LLVM::ConstantOp>(loc, rewriter.getI64Type(), i);
3035 maskVector = rewriter.create<mlir::LLVM::InsertElementOp>(
3036 loc, maskVector, maskValue, idxValue);
3039 mlir::Value maskedIndices = rewriter.create<mlir::LLVM::AndOp>(
3040 loc, llvmIndexVecType, adaptor.getIndices(), maskVector);
3041 mlir::Value result = rewriter.create<mlir::LLVM::UndefOp>(
3042 loc, getTypeConverter()->convertType(op.getVec().getType()));
3043 for (uint64_t i = 0; i < numElements; ++i) {
3044 mlir::Value iValue =
3045 rewriter.create<mlir::LLVM::ConstantOp>(loc, rewriter.getI64Type(), i);
3046 mlir::Value indexValue = rewriter.create<mlir::LLVM::ExtractElementOp>(
3047 loc, maskedIndices, iValue);
3048 mlir::Value valueAtIndex =
3049 rewriter.create<mlir::LLVM::ExtractElementOp>(loc, input, indexValue);
3050 result = rewriter.create<mlir::LLVM::InsertElementOp>(loc, result,
3051 valueAtIndex, iValue);
3053 rewriter.replaceOp(op, result);
3054 return mlir::success();
3057mlir::LogicalResult CIRToLLVMVecTernaryOpLowering::matchAndRewrite(
3058 cir::VecTernaryOp op, OpAdaptor adaptor,
3059 mlir::ConversionPatternRewriter &rewriter)
const {
3061 mlir::Value bitVec = rewriter.create<mlir::LLVM::ICmpOp>(
3062 op.getLoc(), mlir::LLVM::ICmpPredicate::ne, adaptor.getCond(),
3063 rewriter.create<mlir::LLVM::ZeroOp>(
3064 op.getCond().getLoc(),
3065 typeConverter->convertType(op.getCond().getType())));
3066 rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>(
3067 op, bitVec, adaptor.getLhs(), adaptor.getRhs());
3068 return mlir::success();
3071mlir::LogicalResult CIRToLLVMComplexAddOpLowering::matchAndRewrite(
3072 cir::ComplexAddOp op, OpAdaptor adaptor,
3073 mlir::ConversionPatternRewriter &rewriter)
const {
3074 mlir::Value lhs = adaptor.getLhs();
3075 mlir::Value rhs = adaptor.getRhs();
3076 mlir::Location loc = op.getLoc();
3078 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
3079 mlir::Type complexElemTy =
3080 getTypeConverter()->convertType(
complexType.getElementType());
3082 rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, lhs, 0);
3084 rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, lhs, 1);
3086 rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, rhs, 0);
3088 rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, rhs, 1);
3090 mlir::Value newReal;
3091 mlir::Value newImag;
3092 if (complexElemTy.isInteger()) {
3093 newReal = rewriter.create<mlir::LLVM::AddOp>(loc, complexElemTy, lhsReal,
3095 newImag = rewriter.create<mlir::LLVM::AddOp>(loc, complexElemTy, lhsImag,
3100 newReal = rewriter.create<mlir::LLVM::FAddOp>(loc, complexElemTy, lhsReal,
3102 newImag = rewriter.create<mlir::LLVM::FAddOp>(loc, complexElemTy, lhsImag,
3106 mlir::Type complexLLVMTy =
3107 getTypeConverter()->convertType(op.getResult().getType());
3108 auto initialComplex =
3109 rewriter.create<mlir::LLVM::PoisonOp>(op->getLoc(), complexLLVMTy);
3111 auto realComplex = rewriter.create<mlir::LLVM::InsertValueOp>(
3112 op->getLoc(), initialComplex, newReal, 0);
3114 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(op, realComplex,
3117 return mlir::success();
3120mlir::LogicalResult CIRToLLVMComplexCreateOpLowering::matchAndRewrite(
3121 cir::ComplexCreateOp op, OpAdaptor adaptor,
3122 mlir::ConversionPatternRewriter &rewriter)
const {
3123 mlir::Type complexLLVMTy =
3124 getTypeConverter()->convertType(op.getResult().getType());
3125 auto initialComplex =
3126 rewriter.create<mlir::LLVM::UndefOp>(op->getLoc(), complexLLVMTy);
3128 auto realComplex = rewriter.create<mlir::LLVM::InsertValueOp>(
3129 op->getLoc(), initialComplex, adaptor.getReal(), 0);
3131 auto complex = rewriter.create<mlir::LLVM::InsertValueOp>(
3132 op->getLoc(), realComplex, adaptor.getImag(), 1);
3134 rewriter.replaceOp(op, complex);
3135 return mlir::success();
3138mlir::LogicalResult CIRToLLVMComplexRealOpLowering::matchAndRewrite(
3139 cir::ComplexRealOp op, OpAdaptor adaptor,
3140 mlir::ConversionPatternRewriter &rewriter)
const {
3141 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
3142 mlir::Value operand = adaptor.getOperand();
3143 if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) {
3144 operand = mlir::LLVM::ExtractValueOp::create(
3145 rewriter, op.getLoc(), resultLLVMTy, operand,
3146 llvm::ArrayRef<std::int64_t>{0});
3148 rewriter.replaceOp(op, operand);
3149 return mlir::success();
3152mlir::LogicalResult CIRToLLVMComplexSubOpLowering::matchAndRewrite(
3153 cir::ComplexSubOp op, OpAdaptor adaptor,
3154 mlir::ConversionPatternRewriter &rewriter)
const {
3155 mlir::Value lhs = adaptor.getLhs();
3156 mlir::Value rhs = adaptor.getRhs();
3157 mlir::Location loc = op.getLoc();
3159 auto complexType = mlir::cast<cir::ComplexType>(op.getLhs().getType());
3160 mlir::Type complexElemTy =
3161 getTypeConverter()->convertType(
complexType.getElementType());
3163 rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, lhs, 0);
3165 rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, lhs, 1);
3167 rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, rhs, 0);
3169 rewriter.create<mlir::LLVM::ExtractValueOp>(loc, complexElemTy, rhs, 1);
3171 mlir::Value newReal;
3172 mlir::Value newImag;
3173 if (complexElemTy.isInteger()) {
3174 newReal = rewriter.create<mlir::LLVM::SubOp>(loc, complexElemTy, lhsReal,
3176 newImag = rewriter.create<mlir::LLVM::SubOp>(loc, complexElemTy, lhsImag,
3181 newReal = rewriter.create<mlir::LLVM::FSubOp>(loc, complexElemTy, lhsReal,
3183 newImag = rewriter.create<mlir::LLVM::FSubOp>(loc, complexElemTy, lhsImag,
3187 mlir::Type complexLLVMTy =
3188 getTypeConverter()->convertType(op.getResult().getType());
3189 auto initialComplex =
3190 rewriter.create<mlir::LLVM::PoisonOp>(op->getLoc(), complexLLVMTy);
3192 auto realComplex = rewriter.create<mlir::LLVM::InsertValueOp>(
3193 op->getLoc(), initialComplex, newReal, 0);
3195 rewriter.replaceOpWithNewOp<mlir::LLVM::InsertValueOp>(op, realComplex,
3198 return mlir::success();
3201mlir::LogicalResult CIRToLLVMComplexImagOpLowering::matchAndRewrite(
3202 cir::ComplexImagOp op, OpAdaptor adaptor,
3203 mlir::ConversionPatternRewriter &rewriter)
const {
3204 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
3205 mlir::Value operand = adaptor.getOperand();
3206 mlir::Location loc = op.getLoc();
3208 if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) {
3209 operand = mlir::LLVM::ExtractValueOp::create(
3210 rewriter, loc, resultLLVMTy, operand, llvm::ArrayRef<std::int64_t>{1});
3212 mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(resultLLVMTy);
3214 mlir::LLVM::ConstantOp::create(rewriter, loc, resultLLVMTy, zeroAttr);
3217 rewriter.replaceOp(op, operand);
3218 return mlir::success();
3222 mlir::MLIRContext *context,
3223 unsigned &storageSize) {
3224 return TypeSwitch<mlir::Type, mlir::IntegerType>(storageType)
3225 .Case<cir::ArrayType>([&](cir::ArrayType atTy) {
3226 storageSize = atTy.getSize() * 8;
3227 return mlir::IntegerType::get(context, storageSize);
3229 .Case<cir::IntType>([&](cir::IntType intTy) {
3230 storageSize = intTy.getWidth();
3231 return mlir::IntegerType::get(context, storageSize);
3233 .Default([](mlir::Type) -> mlir::IntegerType {
3235 "Either ArrayType or IntType expected for bitfields storage");
3239mlir::LogicalResult CIRToLLVMSetBitfieldOpLowering::matchAndRewrite(
3240 cir::SetBitfieldOp op, OpAdaptor adaptor,
3241 mlir::ConversionPatternRewriter &rewriter)
const {
3242 mlir::OpBuilder::InsertionGuard guard(rewriter);
3243 rewriter.setInsertionPoint(op);
3245 cir::BitfieldInfoAttr info = op.getBitfieldInfo();
3246 uint64_t size = info.getSize();
3247 uint64_t offset = info.getOffset();
3248 mlir::Type storageType = info.getStorageType();
3249 mlir::MLIRContext *context = storageType.getContext();
3251 unsigned storageSize = 0;
3253 mlir::IntegerType intType =
3256 mlir::Value srcVal =
createIntCast(rewriter, adaptor.getSrc(), intType);
3257 unsigned srcWidth = storageSize;
3258 mlir::Value resultVal = srcVal;
3260 if (storageSize != size) {
3261 assert(storageSize > size &&
"Invalid bitfield size.");
3263 mlir::Value val = rewriter.create<mlir::LLVM::LoadOp>(
3264 op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(),
3265 op.getIsVolatile());
3268 createAnd(rewriter, srcVal, llvm::APInt::getLowBitsSet(srcWidth, size));
3270 srcVal =
createShL(rewriter, srcVal, offset);
3274 ~llvm::APInt::getBitsSet(srcWidth, offset, offset + size));
3277 srcVal = rewriter.create<mlir::LLVM::OrOp>(op.getLoc(), val, srcVal);
3280 rewriter.create<mlir::LLVM::StoreOp>(op.getLoc(), srcVal, adaptor.getAddr(),
3281 op.getAlignment(), op.getIsVolatile());
3283 mlir::Type resultTy = getTypeConverter()->convertType(op.getType());
3285 if (info.getIsSigned()) {
3286 assert(size <= storageSize);
3287 unsigned highBits = storageSize - size;
3290 resultVal =
createShL(rewriter, resultVal, highBits);
3291 resultVal =
createAShR(rewriter, resultVal, highBits);
3296 mlir::cast<mlir::IntegerType>(resultTy),
3297 info.getIsSigned());
3299 rewriter.replaceOp(op, resultVal);
3300 return mlir::success();
3303mlir::LogicalResult CIRToLLVMComplexImagPtrOpLowering::matchAndRewrite(
3304 cir::ComplexImagPtrOp op, OpAdaptor adaptor,
3305 mlir::ConversionPatternRewriter &rewriter)
const {
3306 cir::PointerType operandTy = op.getOperand().getType();
3307 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
3308 mlir::Type elementLLVMTy =
3309 getTypeConverter()->convertType(operandTy.getPointee());
3311 mlir::LLVM::GEPArg gepIndices[2] = {{0}, {1}};
3312 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
3313 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
3314 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
3315 op, resultLLVMTy, elementLLVMTy, adaptor.getOperand(), gepIndices,
3317 return mlir::success();
3320mlir::LogicalResult CIRToLLVMComplexRealPtrOpLowering::matchAndRewrite(
3321 cir::ComplexRealPtrOp op, OpAdaptor adaptor,
3322 mlir::ConversionPatternRewriter &rewriter)
const {
3323 cir::PointerType operandTy = op.getOperand().getType();
3324 mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
3325 mlir::Type elementLLVMTy =
3326 getTypeConverter()->convertType(operandTy.getPointee());
3328 mlir::LLVM::GEPArg gepIndices[2] = {0, 0};
3329 mlir::LLVM::GEPNoWrapFlags inboundsNuw =
3330 mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
3331 rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
3332 op, resultLLVMTy, elementLLVMTy, adaptor.getOperand(), gepIndices,
3334 return mlir::success();
3337mlir::LogicalResult CIRToLLVMGetBitfieldOpLowering::matchAndRewrite(
3338 cir::GetBitfieldOp op, OpAdaptor adaptor,
3339 mlir::ConversionPatternRewriter &rewriter)
const {
3341 mlir::OpBuilder::InsertionGuard guard(rewriter);
3342 rewriter.setInsertionPoint(op);
3344 cir::BitfieldInfoAttr info = op.getBitfieldInfo();
3346 uint64_t offset = info.getOffset();
3347 mlir::Type storageType = info.getStorageType();
3348 mlir::MLIRContext *context = storageType.getContext();
3349 unsigned storageSize = 0;
3351 mlir::IntegerType intType =
3354 mlir::Value val = rewriter.create<mlir::LLVM::LoadOp>(
3355 op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(),
3356 op.getIsVolatile());
3357 val = rewriter.create<mlir::LLVM::BitcastOp>(op.getLoc(), intType, val);
3359 if (info.getIsSigned()) {
3360 assert(
static_cast<unsigned>(offset + size) <= storageSize);
3361 unsigned highBits = storageSize - offset - size;
3362 val =
createShL(rewriter, val, highBits);
3363 val =
createAShR(rewriter, val, offset + highBits);
3367 if (
static_cast<unsigned>(offset) + size < storageSize)
3369 llvm::APInt::getLowBitsSet(storageSize, size));
3372 mlir::Type resTy = getTypeConverter()->convertType(op.getType());
3374 rewriter, val, mlir::cast<mlir::IntegerType>(resTy), info.getIsSigned());
3375 rewriter.replaceOp(op, newOp);
3376 return mlir::success();
3379mlir::LogicalResult CIRToLLVMInlineAsmOpLowering::matchAndRewrite(
3380 cir::InlineAsmOp op, OpAdaptor adaptor,
3381 mlir::ConversionPatternRewriter &rewriter)
const {
3383 if (op.getNumResults())
3384 llResTy = getTypeConverter()->convertType(op.getType(0));
3386 cir::AsmFlavor dialect = op.getAsmFlavor();
3387 mlir::LLVM::AsmDialect llDialect = dialect == cir::AsmFlavor::x86_att
3388 ? mlir::LLVM::AsmDialect::AD_ATT
3389 : mlir::LLVM::AsmDialect::AD_Intel;
3391 SmallVector<mlir::Attribute> opAttrs;
3392 StringRef llvmAttrName = mlir::LLVM::InlineAsmOp::getElementTypeAttrName();
3398 if (!op.getNumResults())
3399 opAttrs.push_back(mlir::Attribute());
3401 SmallVector<mlir::Value> llvmOperands;
3402 SmallVector<mlir::Value> cirOperands;
3403 for (
auto const &[llvmOp, cirOp] :
3404 zip(adaptor.getAsmOperands(), op.getAsmOperands())) {
3405 append_range(llvmOperands, llvmOp);
3406 append_range(cirOperands, cirOp);
3411 for (
auto const &[cirOpAttr, cirOp] :
3412 zip(op.getOperandAttrs(), cirOperands)) {
3414 opAttrs.push_back(mlir::Attribute());
3418 llvm::SmallVector<mlir::NamedAttribute, 1> attrs;
3419 cir::PointerType typ = mlir::cast<cir::PointerType>(cirOp.getType());
3421 *getTypeConverter(), dataLayout, typ.getPointee()));
3423 attrs.push_back(rewriter.getNamedAttr(llvmAttrName, typAttr));
3424 mlir::DictionaryAttr newDict = rewriter.getDictionaryAttr(attrs);
3425 opAttrs.push_back(newDict);
3428 rewriter.replaceOpWithNewOp<mlir::LLVM::InlineAsmOp>(
3429 op, llResTy, llvmOperands, op.getAsmStringAttr(), op.getConstraintsAttr(),
3430 op.getSideEffectsAttr(),
3433 mlir::LLVM::TailCallKindAttr::get(
3434 getContext(), mlir::LLVM::tailcallkind::TailCallKind::None),
3435 mlir::LLVM::AsmDialectAttr::get(getContext(), llDialect),
3436 rewriter.getArrayAttr(opAttrs));
3438 return mlir::success();
3441mlir::LogicalResult CIRToLLVMVAStartOpLowering::matchAndRewrite(
3442 cir::VAStartOp op, OpAdaptor adaptor,
3443 mlir::ConversionPatternRewriter &rewriter)
const {
3444 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
3445 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
3446 adaptor.getArgList());
3447 rewriter.replaceOpWithNewOp<mlir::LLVM::VaStartOp>(op, vaList);
3448 return mlir::success();
3451mlir::LogicalResult CIRToLLVMVAEndOpLowering::matchAndRewrite(
3452 cir::VAEndOp op, OpAdaptor adaptor,
3453 mlir::ConversionPatternRewriter &rewriter)
const {
3454 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
3455 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
3456 adaptor.getArgList());
3457 rewriter.replaceOpWithNewOp<mlir::LLVM::VaEndOp>(op, vaList);
3458 return mlir::success();
3461mlir::LogicalResult CIRToLLVMVAArgOpLowering::matchAndRewrite(
3462 cir::VAArgOp op, OpAdaptor adaptor,
3463 mlir::ConversionPatternRewriter &rewriter)
const {
3465 auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
3466 auto vaList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
3467 adaptor.getArgList());
3469 mlir::Type llvmType =
3470 getTypeConverter()->convertType(op->getResultTypes().front());
3472 return mlir::failure();
3474 rewriter.replaceOpWithNewOp<mlir::LLVM::VaArgOp>(op, llvmType, vaList);
3475 return mlir::success();
3479 return std::make_unique<ConvertCIRToLLVMPass>();
3487std::unique_ptr<llvm::Module>
3489 llvm::TimeTraceScope scope(
"lower from CIR to LLVM directly");
3491 mlir::MLIRContext *mlirCtx = mlirModule.getContext();
3493 mlir::PassManager pm(mlirCtx);
3496 (void)mlir::applyPassManagerCLOptions(pm);
3498 if (mlir::failed(pm.run(mlirModule))) {
3501 "The pass manager failed to lower CIR to LLVMIR dialect!");
3504 mlir::registerBuiltinDialectTranslation(*mlirCtx);
3505 mlir::registerLLVMDialectTranslation(*mlirCtx);
3508 llvm::TimeTraceScope translateScope(
"translateModuleToLLVMIR");
3510 StringRef moduleName = mlirModule.getName().value_or(
"CIRToLLVMModule");
3511 std::unique_ptr<llvm::Module> llvmModule =
3512 mlir::translateModuleToLLVMIR(mlirModule, llvmCtx, moduleName);
3516 report_fatal_error(
"Lowering from LLVMIR dialect to llvm IR failed!");
static bool isUnsigned(SValBuilder &SVB, NonLoc Value)
static llvm::StringRef getLinkageAttrNameString()
Returns the name used for the linkage attribute.
mlir::Value createLShR(mlir::OpBuilder &bld, mlir::Value lhs, unsigned rhs)
mlir::Value createShL(mlir::OpBuilder &bld, mlir::Value lhs, unsigned rhs)
std::optional< mlir::Attribute > lowerConstArrayAttr(cir::ConstArrayAttr constArr, const mlir::TypeConverter *converter)
mlir::Value createAShR(mlir::OpBuilder &bld, mlir::Value lhs, unsigned rhs)
mlir::Value createAnd(mlir::OpBuilder &bld, mlir::Value lhs, const llvm::APInt &rhs)
static bool isVector(QualType QT, QualType ElementType)
This helper function returns true if QT is a vector type that has element type ElementType.
mlir::Value visitCirAttr(cir::IntAttr intAttr)
IntAttr visitor.
mlir::Value visit(mlir::Attribute attr)
CIRAttrToValue(mlir::Operation *parentOp, mlir::ConversionPatternRewriter &rewriter, const mlir::TypeConverter *converter)
mlir::Attribute visit(mlir::Attribute attr)
mlir::Attribute visitCirAttr(cir::FPAttr attr)
mlir::Attribute visitCirAttr(cir::BoolAttr attr)
GlobalInitAttrRewriter(mlir::Type type, mlir::ConversionPatternRewriter &rewriter)
mlir::Attribute visitCirAttr(cir::IntAttr attr)
void createLLVMFuncOpIfNotExist(mlir::ConversionPatternRewriter &rewriter, mlir::Operation *srcOp, llvm::StringRef fnName, mlir::Type fnTy)
static void collectUnreachable(mlir::Operation *parent, llvm::SmallVector< mlir::Operation * > &ops)
static mlir::LLVM::ICmpPredicate convertCmpKindToICmpPredicate(cir::CmpOpKind kind, bool isSigned)
Convert from a CIR comparison kind to an LLVM IR integral comparison kind.
static mlir::Value getLLVMIntCast(mlir::ConversionPatternRewriter &rewriter, mlir::Value llvmSrc, mlir::Type llvmDstIntTy, bool isUnsigned, uint64_t cirSrcWidth, uint64_t cirDstIntWidth)
void convertSideEffectForCall(mlir::Operation *callOp, bool isNothrow, cir::SideEffect sideEffect, mlir::LLVM::MemoryEffectsAttr &memoryEffect, bool &noUnwind, bool &willReturn)
static mlir::Value emitFromMemory(mlir::ConversionPatternRewriter &rewriter, mlir::DataLayout const &dataLayout, cir::LoadOp op, mlir::Value value)
Emits the value from memory as expected by its users.
mlir::IntegerType computeBitfieldIntType(mlir::Type storageType, mlir::MLIRContext *context, unsigned &storageSize)
static mlir::LLVM::CallIntrinsicOp createCallLLVMIntrinsicOp(mlir::ConversionPatternRewriter &rewriter, mlir::Location loc, const llvm::Twine &intrinsicName, mlir::Type resultTy, mlir::ValueRange operands)
bool hasTrailingZeros(cir::ConstArrayAttr attr)
static mlir::LogicalResult rewriteCallOrInvoke(mlir::Operation *op, mlir::ValueRange callOperands, mlir::ConversionPatternRewriter &rewriter, const mlir::TypeConverter *converter, mlir::FlatSymbolRefAttr calleeAttr)
std::unique_ptr< llvm::Module > lowerDirectlyFromCIRToLLVMIR(mlir::ModuleOp mlirModule, llvm::LLVMContext &llvmCtx)
mlir::Value lowerCirAttrAsValue(mlir::Operation *parentOp, const mlir::Attribute attr, mlir::ConversionPatternRewriter &rewriter, const mlir::TypeConverter *converter)
Switches on the type of attribute and calls the appropriate conversion.
static mlir::LLVM::CallIntrinsicOp replaceOpWithCallLLVMIntrinsicOp(mlir::ConversionPatternRewriter &rewriter, mlir::Operation *op, const llvm::Twine &intrinsicName, mlir::Type resultTy, mlir::ValueRange operands)
static void prepareTypeConverter(mlir::LLVMTypeConverter &converter, mlir::DataLayout &dataLayout)
static mlir::LLVM::AtomicOrdering getLLVMMemOrder(std::optional< cir::MemOrder > memorder)
std::unique_ptr< mlir::Pass > createConvertCIRToLLVMPass()
Create a pass that fully lowers CIR to the LLVMIR dialect.
static mlir::LLVM::FCmpPredicate convertCmpKindToFCmpPredicate(cir::CmpOpKind kind)
Convert from a CIR comparison kind to an LLVM IR floating-point comparison kind.
static mlir::LLVM::Visibility lowerCIRVisibilityToLLVMVisibility(cir::VisibilityKind visibilityKind)
void populateCIRToLLVMPasses(mlir::OpPassManager &pm)
Adds passes that fully lower CIR to the LLVMIR dialect.
mlir::LLVM::Linkage convertLinkage(cir::GlobalLinkageKind linkage)
static void buildCtorDtorList(mlir::ModuleOp module, StringRef globalXtorName, StringRef llvmXtorName, llvm::function_ref< std::pair< StringRef, int >(mlir::Attribute)> createXtor)
static mlir::Type convertTypeForMemory(const mlir::TypeConverter &converter, mlir::DataLayout const &dataLayout, mlir::Type type)
Given a type convertor and a data layout, convert the given type to a type that is suitable for memor...
static mlir::Value createIntCast(mlir::OpBuilder &bld, mlir::Value src, mlir::IntegerType dstTy, bool isSigned=false)
static mlir::Value getValueForVTableSymbol(mlir::Operation *op, mlir::ConversionPatternRewriter &rewriter, const mlir::TypeConverter *converter, mlir::FlatSymbolRefAttr nameAttr, mlir::Type &eltType)
static mlir::Value emitToMemory(mlir::ConversionPatternRewriter &rewriter, mlir::DataLayout const &dataLayout, mlir::Type origType, mlir::Value value)
Emits a value to memory with the expected scalar type.
static bool isIntTypeUnsigned(mlir::Type type)
const internal::VariadicAllOfMatcher< Attr > attr
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const AstTypeMatcher< ComplexType > complexType
unsigned kind
All of the diagnostics that can be emitted by the frontend.
Diagnostic wrappers for TextAPI types for error reporting.
void populateCIRPreLoweringPasses(mlir::OpPassManager &pm)
void registerCIRDialectTranslation(mlir::MLIRContext &context)
char __ovld __cnfn clz(char)
Returns the number of leading 0-bits in x, starting at the most significant bit position.
char __ovld __cnfn ctz(char)
Returns the count of trailing 0-bits in x.
float __ovld __cnfn length(float)
Return the length of vector p, i.e., sqrt(p.x2 + p.y 2 + ...)
char __ovld __cnfn select(char, char, char)
For each component of a vector type, result[i] = if MSB of c[i] is set ?
static bool dataMemberType()
static bool opGlobalConstant()
static bool addressSpace()
static bool opGlobalThreadLocal()
static bool globalViewIntLowering()
static bool opAllocaAnnotations()
static bool atomicScope()
static bool opLoadStoreTbaa()
static bool optInfoAttr()
static bool opFuncExtraAttrs()
static bool opCallLandingPad()
static bool vaArgABILowering()
static bool fpConstraints()
static bool lowerModeOptLevel()
static bool opCallCallConv()
static bool opFuncCallingConv()
static bool aggValueSlotVolatile()
static bool fastMathFlags()
static bool opCallContinueBlock()
static bool opLoadStoreNontemporal()
static bool atomicSyncScopeID()
static bool opFuncMultipleReturnVals()
void runOnOperation() final
StringRef getDescription() const override
StringRef getArgument() const override
void getDependentDialects(mlir::DialectRegistry ®istry) const override
void processCIRAttrs(mlir::ModuleOp module)