MLIR: lib/Conversion/FuncToLLVM/FuncToLLVM.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

15

40 #include "llvm/ADT/SmallVector.h"

41 #include "llvm/ADT/TypeSwitch.h"

42 #include "llvm/IR/DerivedTypes.h"

43 #include "llvm/IR/IRBuilder.h"

44 #include "llvm/IR/Type.h"

45 #include "llvm/Support/Casting.h"

46 #include "llvm/Support/CommandLine.h"

47 #include "llvm/Support/FormatVariadic.h"

48 #include

49 #include

50 #include

51

52 namespace mlir {

53 #define GEN_PASS_DEF_CONVERTFUNCTOLLVMPASS

54 #define GEN_PASS_DEF_SETLLVMMODULEDATALAYOUTPASS

55 #include "mlir/Conversion/Passes.h.inc"

56 }

57

58 using namespace mlir;

59

60 #define PASS_NAME "convert-func-to-llvm"

61

65

66

71 }

72

73

74

77 for (const NamedAttribute &attr : func->getDiscardableAttrs()) {

80 attr.getName() == LLVM::LLVMDialect::getReadnoneAttrName())

81 continue;

82 result.push_back(attr);

83 }

84 }

85

86

88 FunctionOpInterface funcOp,

89 LLVM::LLVMFuncOp wrapperFuncOp) {

90 auto argAttrs = funcOp.getAllArgAttrs();

91 if (!resultStructType) {

92 if (auto resAttrs = funcOp.getAllResultAttrs())

93 wrapperFuncOp.setAllResultAttrs(resAttrs);

94 if (argAttrs)

95 wrapperFuncOp.setAllArgAttrs(argAttrs);

96 } else {

98

99

100 if (argAttrs) {

102 argAttributes.append(argAttrs.begin(), argAttrs.end());

103 wrapperFuncOp.setAllArgAttrs(argAttributes);

104 }

105 }

106 cast(wrapperFuncOp.getOperation())

107 .setVisibility(funcOp.getVisibility());

108 }

109

110

111

112

113

114

115

116

117

120 FunctionOpInterface funcOp,

121 LLVM::LLVMFuncOp newFuncOp) {

122 auto type = cast(funcOp.getFunctionType());

123 auto [wrapperFuncType, resultStructType] =

125

128

129 auto wrapperFuncOp = rewriter.createLLVM::LLVMFuncOp(

130 loc, llvm::formatv("_mlir_ciface_{0}", funcOp.getName()).str(),

131 wrapperFuncType, LLVM::Linkage::External, false,

132 LLVM::CConv::C, nullptr, attributes);

134

137

139 size_t argOffset = resultStructType ? 1 : 0;

140 for (auto [index, argType] : llvm::enumerate(type.getInputs())) {

141 Value arg = wrapperFuncOp.getArgument(index + argOffset);

142 if (auto memrefType = dyn_cast(argType)) {

143 Value loaded = rewriter.createLLVM::LoadOp(

144 loc, typeConverter.convertType(memrefType), arg);

146 continue;

147 }

148 if (isa(argType)) {

149 Value loaded = rewriter.createLLVM::LoadOp(

150 loc, typeConverter.convertType(argType), arg);

152 continue;

153 }

154

155 args.push_back(arg);

156 }

157

158 auto call = rewriter.createLLVM::CallOp(loc, newFuncOp, args);

159

160 if (resultStructType) {

161 rewriter.createLLVM::StoreOp(loc, call.getResult(),

162 wrapperFuncOp.getArgument(0));

164 } else {

165 rewriter.createLLVM::ReturnOp(loc, call.getResults());

166 }

167 }

168

169

170

171

172

173

174

175

176

177

180 FunctionOpInterface funcOp,

181 LLVM::LLVMFuncOp newFuncOp) {

183

184 auto [wrapperType, resultStructType] =

186 cast(funcOp.getFunctionType()));

187

188

189

190 assert(wrapperType && "unexpected type conversion failure");

191

194

195

196 auto wrapperFunc = builder.createLLVM::LLVMFuncOp(

197 loc, llvm::formatv("_mlir_ciface_{0}", funcOp.getName()).str(),

198 wrapperType, LLVM::Linkage::External, false,

199 LLVM::CConv::C, nullptr, attributes);

201

202

203 newFuncOp.setLinkage(LLVM::Linkage::Private);

205

206

207 FunctionType type = cast(funcOp.getFunctionType());

209 args.reserve(type.getNumInputs());

210 ValueRange wrapperArgsRange(newFuncOp.getArguments());

211

212 if (resultStructType) {

213

214 Type resultType = castLLVM::LLVMFunctionType(wrapperType).getParamType(0);

215 Value one = builder.createLLVM::ConstantOp(

219 builder.createLLVM::AllocaOp(loc, resultType, resultStructType, one);

220 args.push_back(result);

221 }

222

223

224

225 for (Type input : type.getInputs()) {

227 int numToDrop = 1;

228 auto memRefType = dyn_cast(input);

229 auto unrankedMemRefType = dyn_cast(input);

230 if (memRefType || unrankedMemRefType) {

231 numToDrop = memRefType

235 memRefType

237 wrapperArgsRange.take_front(numToDrop))

239 builder, loc, typeConverter, unrankedMemRefType,

240 wrapperArgsRange.take_front(numToDrop));

241

243 Value one = builder.createLLVM::ConstantOp(

246 Value allocated = builder.createLLVM::AllocaOp(

247 loc, ptrTy, packed.getType(), one, 0);

248 builder.createLLVM::StoreOp(loc, packed, allocated);

249 arg = allocated;

250 } else {

251 arg = wrapperArgsRange[0];

252 }

253

254 args.push_back(arg);

255 wrapperArgsRange = wrapperArgsRange.drop_front(numToDrop);

256 }

257 assert(wrapperArgsRange.empty() && "did not map some of the arguments");

258

259 auto call = builder.createLLVM::CallOp(loc, wrapperFunc, args);

260

261 if (resultStructType) {

263 builder.createLLVM::LoadOp(loc, resultStructType, args.front());

264 builder.createLLVM::ReturnOp(loc, result);

265 } else {

266 builder.createLLVM::ReturnOp(loc, call.getResults());

267 }

268 }

269

270

271

272

275 ArrayRef<std::optional> byValRefNonPtrAttrs,

277

278 if (funcOp.isExternal())

279 return;

280

281 ConversionPatternRewriter::InsertionGuard guard(rewriter);

283

284 for (const auto &[arg, oldArg, byValRefAttr] :

285 llvm::zip(funcOp.getArguments(), oldBlockArgs, byValRefNonPtrAttrs)) {

286

287 if (!byValRefAttr)

288 continue;

289

290

291 assert(isaLLVM::LLVMPointerType(arg.getType()) &&

292 "Expected LLVM pointer type for argument with "

293 "`llvm.byval`/`llvm.byref` attribute");

295 cast(byValRefAttr->getValue()).getValue());

296

297 auto valueArg = rewriter.createLLVM::LoadOp(arg.getLoc(), resTy, arg);

299 }

300 }

301

302 FailureOrLLVM::LLVMFuncOp

306

307 auto funcTy = dyn_cast(funcOp.getFunctionType());

308 if (!funcTy)

310 funcOp, "Only support FunctionOpInterface with FunctionType");

311

312

314 llvm::to_vector(funcOp.getArguments());

315

316

317

319

320

323 auto llvmType = dyn_cast_or_nullLLVM::LLVMFunctionType(

325 funcOp, varargsAttr && varargsAttr.getValue(),

327 byValRefNonPtrAttrs));

328 if (!llvmType)

329 return rewriter.notifyMatchFailure(funcOp, "signature conversion failed");

330

331

333 if (funcOp->getAttrOfType(

334 LLVM::LLVMDialect::getEmitCWrapperAttrName()))

335 if (llvmType.isVarArg())

336 return funcOp.emitError("C interface for variadic functions is not "

337 "supported yet.");

338

339

340

341 LLVM::Linkage linkage = LLVM::Linkage::External;

343 auto attr =

344 dyn_castmlir::LLVM::LinkageAttr(funcOp->getAttr(linkageAttrName));

345 if (!attr) {

347 << " attribute not of type LLVM::LinkageAttr";

349 funcOp, "Contains linkage attribute not of type LLVM::LinkageAttr");

350 }

351 linkage = attr.getLinkage();

352 }

353

354

355 StringRef readnoneAttrName = LLVM::LLVMDialect::getReadnoneAttrName();

356 if (funcOp->hasAttr(readnoneAttrName)) {

357 auto attr = funcOp->getAttrOfType(readnoneAttrName);

358 if (!attr) {

359 funcOp->emitError() << "Contains " << readnoneAttrName

360 << " attribute not of type UnitAttr";

362 funcOp, "Contains readnone attribute not of type UnitAttr");

363 }

364 }

365

368 auto newFuncOp = rewriter.createLLVM::LLVMFuncOp(

369 funcOp.getLoc(), funcOp.getName(), llvmType, linkage,

370 false, LLVM::CConv::C, nullptr,

371 attributes);

372 cast(newFuncOp.getOperation())

373 .setVisibility(funcOp.getVisibility());

374

375

376 if (funcOp->hasAttr(readnoneAttrName)) {

379 {LLVM::ModRefInfo::NoModRef, LLVM::ModRefInfo::NoModRef,

380 LLVM::ModRefInfo::NoModRef});

381 newFuncOp.setMemoryEffectsAttr(memoryAttr);

382 }

383

384

385

386 if (ArrayAttr resAttrDicts = funcOp.getAllResultAttrs()) {

387 assert(!resAttrDicts.empty() && "expected array to be non-empty");

388 if (funcOp.getNumResults() == 1)

389 newFuncOp.setAllResultAttrs(resAttrDicts);

390 }

391 if (ArrayAttr argAttrDicts = funcOp.getAllArgAttrs()) {

393 castLLVM::LLVMFunctionType(llvmType).getNumParams());

394 for (unsigned i = 0, e = funcOp.getNumArguments(); i < e; ++i) {

395

396

397

399 auto attrsDict = cast(argAttrDicts[i]);

400 convertedAttrs.reserve(attrsDict.size());

402 const auto convert = [&](const NamedAttribute &attr) {

404 cast(attr.getValue()).getValue()));

405 };

406 if (attr.getName().getValue() ==

407 LLVM::LLVMDialect::getByValAttrName()) {

408 convertedAttrs.push_back(rewriter.getNamedAttr(

409 LLVM::LLVMDialect::getByValAttrName(), convert(attr)));

410 } else if (attr.getName().getValue() ==

411 LLVM::LLVMDialect::getByRefAttrName()) {

412 convertedAttrs.push_back(rewriter.getNamedAttr(

413 LLVM::LLVMDialect::getByRefAttrName(), convert(attr)));

414 } else if (attr.getName().getValue() ==

415 LLVM::LLVMDialect::getStructRetAttrName()) {

416 convertedAttrs.push_back(rewriter.getNamedAttr(

417 LLVM::LLVMDialect::getStructRetAttrName(), convert(attr)));

418 } else if (attr.getName().getValue() ==

419 LLVM::LLVMDialect::getInAllocaAttrName()) {

420 convertedAttrs.push_back(rewriter.getNamedAttr(

421 LLVM::LLVMDialect::getInAllocaAttrName(), convert(attr)));

422 } else {

423 convertedAttrs.push_back(attr);

424 }

425 }

427 assert(mapping && "unexpected deletion of function argument");

428

429

430

431 if (mapping->size == 1) {

432 newArgAttrs[mapping->inputNo] =

434 continue;

435 }

436

437

438 for (size_t j = 0; j < mapping->size; ++j)

439 newArgAttrs[mapping->inputNo + j] =

441 }

442 if (!newArgAttrs.empty())

443 newFuncOp.setAllArgAttrs(rewriter.getArrayAttr(newArgAttrs));

444 }

445

446 rewriter.inlineRegionBefore(funcOp.getFunctionBody(), newFuncOp.getBody(),

447 newFuncOp.end());

448

449

450 if (!newFuncOp.getBody().empty())

452 &converter);

453

454

455

456

458 oldBlockArgs, newFuncOp);

459

461 if (funcOp->getAttrOfType(

462 LLVM::LLVMDialect::getEmitCWrapperAttrName())) {

463 if (newFuncOp.isExternal())

465 newFuncOp);

466 else

468 newFuncOp);

469 }

470 }

471

472 return newFuncOp;

473 }

474

475 namespace {

476

477

478

479

483

484 LogicalResult

485 matchAndRewrite(func::FuncOp funcOp, OpAdaptor adaptor,

488 cast(funcOp.getOperation()), rewriter,

489 *getTypeConverter());

490 if (failed(newFuncOp))

491 return rewriter.notifyMatchFailure(funcOp, "Could not convert funcop");

492

493 rewriter.eraseOp(funcOp);

494 return success();

495 }

496 };

497

500

501 LogicalResult

502 matchAndRewrite(func::ConstantOp op, OpAdaptor adaptor,

504 auto type = typeConverter->convertType(op.getResult().getType());

506 return rewriter.notifyMatchFailure(op, "failed to convert result type");

507

508 auto newOp =

509 rewriter.createLLVM::AddressOfOp(op.getLoc(), type, op.getValue());

511 if (attr.getName().strref() == "value")

512 continue;

513 newOp->setAttr(attr.getName(), attr.getValue());

514 }

515 rewriter.replaceOp(op, newOp->getResults());

516 return success();

517 }

518 };

519

520

521

522 template

525 using Super = CallOpInterfaceLowering;

527

528 LogicalResult matchAndRewriteImpl(CallOpType callOp,

529 typename CallOpType::Adaptor adaptor,

531 bool useBarePtrCallConv = false) const {

532

533 Type packedResult = nullptr;

534 unsigned numResults = callOp.getNumResults();

535 auto resultTypes = llvm::to_vector<4>(callOp.getResultTypes());

536

537 if (numResults != 0) {

538 if (!(packedResult = this->getTypeConverter()->packFunctionResults(

539 resultTypes, useBarePtrCallConv)))

540 return failure();

541 }

542

543 if (useBarePtrCallConv) {

544 for (auto it : callOp->getOperands()) {

545 Type operandType = it.getType();

546 if (isa(operandType)) {

547

548

549 return failure();

550 }

551 }

552 }

553 auto promoted = this->getTypeConverter()->promoteOperands(

554 callOp.getLoc(), callOp->getOperands(),

555 adaptor.getOperands(), rewriter, useBarePtrCallConv);

556 auto newOp = rewriter.createLLVM::CallOp(

557 callOp.getLoc(), packedResult ? TypeRange(packedResult) : TypeRange(),

558 promoted, callOp->getAttrs());

559

560 newOp.getProperties().operandSegmentSizes = {

561 static_cast<int32_t>(promoted.size()), 0};

563

565 if (numResults < 2) {

566

567 results.append(newOp.result_begin(), newOp.result_end());

568 } else {

569

570

571 results.reserve(numResults);

572 for (unsigned i = 0; i < numResults; ++i) {

573 results.push_back(rewriter.createLLVM::ExtractValueOp(

574 callOp.getLoc(), newOp->getResult(0), i));

575 }

576 }

577

578 if (useBarePtrCallConv) {

579

580

581 assert(results.size() == resultTypes.size() &&

582 "The number of arguments and types doesn't match");

583 this->getTypeConverter()->promoteBarePtrsToDescriptors(

584 rewriter, callOp.getLoc(), resultTypes, results);

585 } else if (failed(this->copyUnrankedDescriptors(rewriter, callOp.getLoc(),

586 resultTypes, results,

587 false))) {

588 return failure();

589 }

590

591 rewriter.replaceOp(callOp, results);

592 return success();

593 }

594 };

595

596 class CallOpLowering : public CallOpInterfaceLoweringfunc::CallOp {

597 public:

599

601 : CallOpInterfaceLoweringfunc::CallOp(typeConverter, benefit),

602 symbolTable(symbolTable) {}

603

604 LogicalResult

605 matchAndRewrite(func::CallOp callOp, OpAdaptor adaptor,

607 bool useBarePtrCallConv = false;

608 if (getTypeConverter()->getOptions().useBarePtrCallConv) {

609 useBarePtrCallConv = true;

610 } else if (symbolTable != nullptr) {

611

613 symbolTable->lookup(callOp.getCalleeAttr().getValue());

614 useBarePtrCallConv =

616 } else {

617

620 useBarePtrCallConv =

622 }

623 return matchAndRewriteImpl(callOp, adaptor, rewriter, useBarePtrCallConv);

624 }

625

626 private:

627 const SymbolTable *symbolTable = nullptr;

628 };

629

630 struct CallIndirectOpLowering

631 : public CallOpInterfaceLoweringfunc::CallIndirectOp {

632 using Super::Super;

633

634 LogicalResult

635 matchAndRewrite(func::CallIndirectOp callIndirectOp, OpAdaptor adaptor,

637 return matchAndRewriteImpl(callIndirectOp, adaptor, rewriter);

638 }

639 };

640

641 struct UnrealizedConversionCastOpLowering

645

646 LogicalResult

647 matchAndRewrite(UnrealizedConversionCastOp op, OpAdaptor adaptor,

650 if (succeeded(typeConverter->convertTypes(op.getOutputs().getTypes(),

651 convertedTypes)) &&

652 convertedTypes == adaptor.getInputs().getTypes()) {

653 rewriter.replaceOp(op, adaptor.getInputs());

654 return success();

655 }

656

657 convertedTypes.clear();

658 if (succeeded(typeConverter->convertTypes(adaptor.getInputs().getTypes(),

659 convertedTypes)) &&

660 convertedTypes == op.getOutputs().getType()) {

661 rewriter.replaceOp(op, adaptor.getInputs());

662 return success();

663 }

664 return failure();

665 }

666 };

667

668

669

670

671

672

673

676

677 LogicalResult

678 matchAndRewrite(func::ReturnOp op, OpAdaptor adaptor,

681 unsigned numArguments = op.getNumOperands();

683

684 auto funcOp = op->getParentOfTypeLLVM::LLVMFuncOp();

685 bool useBarePtrCallConv =

687 if (useBarePtrCallConv) {

688

689

690 for (auto it : llvm::zip(op->getOperands(), adaptor.getOperands())) {

691 Type oldTy = std::get<0>(it).getType();

692 Value newOperand = std::get<1>(it);

693 if (isa(oldTy) && getTypeConverter()->canConvertToBarePtr(

694 cast(oldTy))) {

696 newOperand = memrefDesc.allocatedPtr(rewriter, loc);

697 } else if (isa(oldTy)) {

698

699

700 return failure();

701 }

702 updatedOperands.push_back(newOperand);

703 }

704 } else {

705 updatedOperands = llvm::to_vector<4>(adaptor.getOperands());

706 (void)copyUnrankedDescriptors(rewriter, loc, op.getOperands().getTypes(),

707 updatedOperands,

708 true);

709 }

710

711

712 if (numArguments <= 1) {

714 op, TypeRange(), updatedOperands, op->getAttrs());

715 return success();

716 }

717

718

719

720 auto packedType = getTypeConverter()->packFunctionResults(

721 op.getOperandTypes(), useBarePtrCallConv);

722 if (!packedType) {

723 return rewriter.notifyMatchFailure(op, "could not convert result types");

724 }

725

726 Value packed = rewriter.createLLVM::PoisonOp(loc, packedType);

727 for (auto [idx, operand] : llvm::enumerate(updatedOperands)) {

728 packed = rewriter.createLLVM::InsertValueOp(loc, packed, operand, idx);

729 }

731 op->getAttrs());

732 return success();

733 }

734 };

735 }

736

739 patterns.add(converter);

740 }

741

746 patterns.add(converter);

747 patterns.add(converter, symbolTable);

748 patterns.add(converter);

749 patterns.add(converter);

750 }

751

752 namespace {

753

754 struct ConvertFuncToLLVMPass

755 : public impl::ConvertFuncToLLVMPassBase {

756 using Base::Base;

757

758

759 void runOnOperation() override {

760 ModuleOp m = getOperation();

761 StringRef dataLayout;

762 auto dataLayoutAttr = dyn_cast_or_null(

763 m->getAttr(LLVM::LLVMDialect::getDataLayoutAttrName()));

764 if (dataLayoutAttr)

765 dataLayout = dataLayoutAttr.getValue();

766

767 if (failed(LLVM::LLVMDialect::verifyDataLayoutString(

768 dataLayout, [this](const Twine &message) {

769 getOperation().emitError() << message.str();

770 }))) {

771 signalPassFailure();

772 return;

773 }

774

775 const auto &dataLayoutAnalysis = getAnalysis();

776

778 dataLayoutAnalysis.getAtOrAbove(m));

779 options.useBarePtrCallConv = useBarePtrCallConv;

781 options.overrideIndexBitwidth(indexBitwidth);

782 options.dataLayout = llvm::DataLayout(dataLayout);

783

785 &dataLayoutAnalysis);

786

787 std::optional optSymbolTable = std::nullopt;

788 const SymbolTable *symbolTable = nullptr;

789 if (options.useBarePtrCallConv) {

790 optSymbolTable.emplace(m);

791 symbolTable = &optSymbolTable.value();

792 }

793

796

799 signalPassFailure();

800 }

801 };

802

803 struct SetLLVMModuleDataLayoutPass

804 : public impl::SetLLVMModuleDataLayoutPassBase<

805 SetLLVMModuleDataLayoutPass> {

806 using Base::Base;

807

808

809 void runOnOperation() override {

810 if (failed(LLVM::LLVMDialect::verifyDataLayoutString(

811 this->dataLayout, [this](const Twine &message) {

812 getOperation().emitError() << message.str();

813 }))) {

814 signalPassFailure();

815 return;

816 }

817 ModuleOp m = getOperation();

818 m->setAttr(LLVM::LLVMDialect::getDataLayoutAttrName(),

820 }

821 };

822 }

823

824

825

826

827

828 namespace {

829

832

833

834 void populateConvertToLLVMConversionPatterns(

838 }

839 };

840 }

841

844 dialect->addInterfaces();

845 });

846 }

static void propagateArgResAttrs(OpBuilder &builder, bool resultStructType, FunctionOpInterface funcOp, LLVM::LLVMFuncOp wrapperFuncOp)

Propagate argument/results attributes.

static constexpr StringRef barePtrAttrName

static constexpr StringRef varargsAttrName

static constexpr StringRef linkageAttrName

static void filterFuncAttributes(FunctionOpInterface func, SmallVectorImpl< NamedAttribute > &result)

Only retain those attributes that are not constructed by LLVMFuncOp::build.

static bool shouldUseBarePtrCallConv(Operation *op, const LLVMTypeConverter *typeConverter)

Return true if the op should use bare pointer calling convention.

static void restoreByValRefArgumentType(ConversionPatternRewriter &rewriter, const LLVMTypeConverter &typeConverter, ArrayRef< std::optional< NamedAttribute >> byValRefNonPtrAttrs, ArrayRef< BlockArgument > oldBlockArgs, LLVM::LLVMFuncOp funcOp)

Inserts llvm.load ops in the function body to restore the expected pointee value from llvm....

static void wrapExternalFunction(OpBuilder &builder, Location loc, const LLVMTypeConverter &typeConverter, FunctionOpInterface funcOp, LLVM::LLVMFuncOp newFuncOp)

Creates an auxiliary function with pointer-to-memref-descriptor-struct arguments instead of unpacked ...

static void wrapForExternalCallers(OpBuilder &rewriter, Location loc, const LLVMTypeConverter &typeConverter, FunctionOpInterface funcOp, LLVM::LLVMFuncOp newFuncOp)

Creates an auxiliary function with pointer-to-memref-descriptor-struct arguments instead of unpacked ...

static MLIRContext * getContext(OpFoldResult val)

static llvm::ManagedStatic< PassManagerOptions > options

Special case of IntegerAttr to represent boolean integers, i.e., signless i1 integers.

DenseI32ArrayAttr getDenseI32ArrayAttr(ArrayRef< int32_t > values)

IntegerAttr getIntegerAttr(Type type, int64_t value)

MLIRContext * getContext() const

ArrayAttr getArrayAttr(ArrayRef< Attribute > value)

DictionaryAttr getDictionaryAttr(ArrayRef< NamedAttribute > value)

NamedAttribute getNamedAttr(StringRef name, Attribute val)

This class implements a pattern rewriter for use with ConversionPatterns.

void replaceOp(Operation *op, ValueRange newValues) override

Replace the given operation with the new values.

Block * applySignatureConversion(Block *block, TypeConverter::SignatureConversion &conversion, const TypeConverter *converter=nullptr)

Apply a signature conversion to given block.

void eraseOp(Operation *op) override

PatternRewriter hook for erasing a dead operation.

void replaceUsesOfBlockArgument(BlockArgument from, Value to)

Replace all the uses of the block argument from with value to.

This class describes a specific conversion target.

Utility class for operation conversions targeting the LLVM dialect that match exactly one source oper...

Base class for dialect interfaces providing translation to LLVM IR.

ConvertToLLVMPatternInterface(Dialect *dialect)

The DialectRegistry maps a dialect namespace to a constructor for the matching dialect.

bool addExtension(TypeID extensionID, std::unique_ptr< DialectExtensionBase > extension)

Add the given extension to the registry.

Derived class that automatically populates legalization information for different LLVM ops.

Conversion from types to the LLVM IR dialect.

const LowerToLLVMOptions & getOptions() const

Type convertFunctionSignature(FunctionType funcTy, bool isVariadic, bool useBarePtrCallConv, SignatureConversion &result) const

Convert a function type.

LogicalResult convertType(Type t, SmallVectorImpl< Type > &results) const

Convert the given type.

std::pair< LLVM::LLVMFunctionType, LLVM::LLVMStructType > convertFunctionTypeCWrapper(FunctionType type) const

Converts the function type to a C-compatible format, in particular using pointers to memref descripto...

This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...

Options to control the LLVM lowering.

MLIRContext is the top-level object for a collection of MLIR operations.

Helper class to produce LLVM dialect operations extracting or inserting elements of a MemRef descript...

static void unpack(OpBuilder &builder, Location loc, Value packed, MemRefType type, SmallVectorImpl< Value > &results)

Builds IR extracting individual elements of a MemRef descriptor structure and returning them as resul...

static unsigned getNumUnpackedValues(MemRefType type)

Returns the number of non-aggregate values that would be produced by unpack.

static Value pack(OpBuilder &builder, Location loc, const LLVMTypeConverter &converter, MemRefType type, ValueRange values)

Builds IR populating a MemRef descriptor structure from a list of individual values composing that de...

NamedAttribute represents a combination of a name and an Attribute value.

RAII guard to reset the insertion point of the builder when destroyed.

This class helps build Operations.

void setInsertionPointToStart(Block *block)

Sets the insertion point to the start of the specified block.

Operation * create(const OperationState &state)

Creates an operation given the fields represented as an OperationState.

Operation is the basic unit of execution within MLIR.

bool hasAttr(StringAttr name)

Return true if the operation has an attribute with the provided name, false otherwise.

void setAttr(StringAttr name, Attribute value)

If the an attribute exists with the specified name, change it to the new value.

This class represents the benefit of a pattern match in a unitless scheme that ranges from 0 (very li...

std::enable_if_t<!std::is_convertible< CallbackT, Twine >::value, LogicalResult > notifyMatchFailure(Location loc, CallbackT &&reasonCallback)

Used to notify the listener that the IR failed to be rewritten because of a match failure,...

void inlineRegionBefore(Region &region, Region &parent, Region::iterator before)

Move the blocks that belong to "region" before the given position in another region "parent".

OpTy replaceOpWithNewOp(Operation *op, Args &&...args)

Replace the results of the given (original) op with a new op that is created without verification (re...

This class allows for representing and managing the symbol table used by operations with the 'SymbolT...

static Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)

Returns the operation registered with the given symbol name within the closest parent operation of,...

This class provides all of the information necessary to convert a type signature.

std::optional< InputMapping > getInputMapping(unsigned input) const

Get the input mapping for the given argument.

This class provides an abstraction over the various different ranges of value types.

Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...

static Value pack(OpBuilder &builder, Location loc, const LLVMTypeConverter &converter, UnrankedMemRefType type, ValueRange values)

Builds IR populating an unranked MemRef descriptor structure from a list of individual constituent va...

static void unpack(OpBuilder &builder, Location loc, Value packed, SmallVectorImpl< Value > &results)

Builds IR extracting individual elements that compose an unranked memref descriptor and returns them ...

static unsigned getNumUnpackedValues()

Returns the number of non-aggregate values that would be produced by unpack.

This class provides an abstraction over the different types of ranges over Values.

This class represents an instance of an SSA value in the MLIR system, representing a computable value...

Type getType() const

Return the type of this value.

bool isCompatibleType(Type type)

Returns true if the given type is compatible with the LLVM dialect.

constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)

Include the generated interface declarations.

static constexpr unsigned kDeriveIndexBitwidthFromDataLayout

Value to pass as bitwidth for the index type when the converter is expected to derive the bitwidth fr...

void populateFuncToLLVMFuncOpConversionPattern(const LLVMTypeConverter &converter, RewritePatternSet &patterns)

Collect the default pattern to convert a FuncOp to the LLVM dialect.

void registerConvertFuncToLLVMInterface(DialectRegistry &registry)

const FrozenRewritePatternSet & patterns

FailureOr< LLVM::LLVMFuncOp > convertFuncOpToLLVMFuncOp(FunctionOpInterface funcOp, ConversionPatternRewriter &rewriter, const LLVMTypeConverter &converter)

Convert input FunctionOpInterface operation to LLVMFuncOp by using the provided LLVMTypeConverter.

auto get(MLIRContext *context, Ts &&...params)

Helper method that injects context only if needed, this helps unify some of the attribute constructio...

void populateFuncToLLVMConversionPatterns(const LLVMTypeConverter &converter, RewritePatternSet &patterns, const SymbolTable *symbolTable=nullptr)

Collect the patterns to convert from the Func dialect to LLVM.

LogicalResult applyPartialConversion(ArrayRef< Operation * > ops, const ConversionTarget &target, const FrozenRewritePatternSet &patterns, ConversionConfig config=ConversionConfig())

Below we define several entry points for operation conversion.

Eliminates variable at the specified position using Fourier-Motzkin variable elimination.