MLIR: lib/Dialect/LLVMIR/Transforms/InlinerInterfaceImpl.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

22#include "llvm/ADT/ScopeExit.h"

23#include "llvm/Support/Debug.h"

24

25#include "llvm/Support/DebugLog.h"

26

27#define DEBUG_TYPE "llvm-inliner"

28

29using namespace mlir;

30

31

32

33

36 allocaOp->getUsers().end());

37 while (!stack.empty()) {

38 Operation *op = stack.pop_back_val();

39 if (isa<LLVM::LifetimeStartOp, LLVM::LifetimeEndOp>(op))

40 return true;

41 if (isaLLVM::BitcastOp(op))

43 }

44 return false;

45}

46

47

48

49

50

51

52

53

54

55static void

58

59

60

61

62

63

64

65 Block *callerEntryBlock = nullptr;

71 break;

72 }

73 currentOp = parentOp;

74 }

75

76

77

78

79 Block *calleeEntryBlock = &(*inlinedBlocks.begin());

80 if (!callerEntryBlock || callerEntryBlock == calleeEntryBlock)

81 return;

82

84 bool shouldInsertLifetimes = false;

85 bool hasDynamicAlloca = false;

86

87

88

89 for (auto allocaOp : calleeEntryBlock->getOpsLLVM::AllocaOp()) {

90 IntegerAttr arraySize;

92 hasDynamicAlloca = true;

93 continue;

94 }

95 bool shouldInsertLifetime =

97 shouldInsertLifetimes |= shouldInsertLifetime;

98 allocasToMove.emplace_back(allocaOp, arraySize, shouldInsertLifetime);

99 }

100

101 for (Block &block : llvm::drop_begin(inlinedBlocks)) {

102 if (hasDynamicAlloca)

103 break;

104 hasDynamicAlloca =

105 llvm::any_of(block.getOpsLLVM::AllocaOp(), [](auto allocaOp) {

106 return !matchPattern(allocaOp.getArraySize(), m_Constant());

107 });

108 }

109 if (allocasToMove.empty() && !hasDynamicAlloca)

110 return;

111 OpBuilder builder(calleeEntryBlock, calleeEntryBlock->begin());

113 if (hasDynamicAlloca) {

114

115

116

117

118 stackPtr = LLVM::StackSaveOp::create(

119 builder, call->getLoc(),

120 LLVM::LLVMPointerType::get(call->getContext()));

121 }

123 for (auto &[allocaOp, arraySize, shouldInsertLifetime] : allocasToMove) {

124 auto newConstant =

125 LLVM::ConstantOp::create(builder, allocaOp->getLoc(),

126 allocaOp.getArraySize().getType(), arraySize);

127

128 if (shouldInsertLifetime) {

131 LLVM::LifetimeStartOp::create(builder, allocaOp.getLoc(),

132 allocaOp.getResult());

133 }

134 allocaOp->moveAfter(newConstant);

135 allocaOp.getArraySizeMutable().assign(newConstant.getResult());

136 }

137 if (!shouldInsertLifetimes && !hasDynamicAlloca)

138 return;

139

140 for (Block &block : inlinedBlocks) {

142 continue;

144 if (hasDynamicAlloca)

145 LLVM::StackRestoreOp::create(builder, call->getLoc(), stackPtr);

146 for (auto &[allocaOp, arraySize, shouldInsertLifetime] : allocasToMove) {

147 if (shouldInsertLifetime)

148 LLVM::LifetimeEndOp::create(builder, allocaOp.getLoc(),

149 allocaOp.getResult());

150 }

151 }

152}

153

154

155

156

157static void

160

161

162

163

165

166

167

168

169 walker.addWalk([&](LLVM::AliasScopeDomainAttr domainAttr) {

170 mapping[domainAttr] = LLVM::AliasScopeDomainAttr::get(

171 domainAttr.getContext(), domainAttr.getDescription());

172 });

173

174 walker.addWalk([&](LLVM::AliasScopeAttr scopeAttr) {

175 mapping[scopeAttr] = LLVM::AliasScopeAttr::get(

176 castLLVM::AliasScopeDomainAttr(mapping.lookup(scopeAttr.getDomain())),

177 scopeAttr.getDescription());

178 });

179

180

182 if (!arrayAttr)

183 return nullptr;

184

185

186 walker.walk(arrayAttr);

187

188 return ArrayAttr::get(arrayAttr.getContext(),

189 llvm::map_to_vector(arrayAttr, [&](Attribute attr) {

190 return mapping.lookup(attr);

191 }));

192 };

193

194 for (Block &block : inlinedBlocks) {

196 if (auto aliasInterface = dyn_castLLVM::AliasAnalysisOpInterface(op)) {

197 aliasInterface.setAliasScopes(

198 convertScopeList(aliasInterface.getAliasScopesOrNull()));

199 aliasInterface.setNoAliasScopes(

200 convertScopeList(aliasInterface.getNoAliasScopesOrNull()));

201 }

202

203 if (auto noAliasScope = dyn_castLLVM::NoAliasScopeDeclOp(op)) {

204

205 walker.walk(noAliasScope.getScopeAttr());

206

207 noAliasScope.setScopeAttr(castLLVM::AliasScopeAttr(

208 mapping.lookup(noAliasScope.getScopeAttr())));

209 }

210 });

211 }

212}

213

214

215

216

218 if (lhs)

219 return rhs;

220 if (rhs)

221 return lhs;

222

226 return ArrayAttr::get(lhs.getContext(), result);

227}

228

229

230

231

232static FailureOr<SmallVector>

236

237

238 if (auto viewOp = val.getDefiningOp()) {

239 if (val == viewOp.getViewDest())

241 }

242

243

244 std::optional<SmallVector> controlFlowPredecessors =

246 if (controlFlowPredecessors)

248

249

250 if (isa(val)) {

251 result.push_back(val);

253 }

254

255

256

257

258

260 });

261

263 return failure();

264

266}

267

268

269

270

273

274

275

276

277

278

279

280

283 for (Value argument : castLLVM::CallOp(call).getArgOperands()) {

285 auto ssaCopy = llvm::dyn_castLLVM::SSACopyOp(user);

286 if (!ssaCopy)

287 continue;

288 ssaCopies.insert(ssaCopy);

289

290 if (!ssaCopy->hasAttr(LLVM::LLVMDialect::getNoAliasAttrName()))

291 continue;

292 noAliasParams.insert(ssaCopy);

293 }

294 }

295

296

297

298 auto exit = llvm::make_scope_exit([&] {

299 for (LLVM::SSACopyOp ssaCopyOp : ssaCopies) {

300 ssaCopyOp.replaceAllUsesWith(ssaCopyOp.getOperand());

301 ssaCopyOp->erase();

302 }

303 });

304

305

306 if (noAliasParams.empty())

307 return;

308

309

310

311 auto functionDomain = LLVM::AliasScopeDomainAttr::get(

312 call->getContext(), castLLVM::CallOp(call).getCalleeAttr().getAttr());

314 for (LLVM::SSACopyOp copyOp : noAliasParams) {

315 auto scope = LLVM::AliasScopeAttr::get(functionDomain);

316 pointerScopes[copyOp] = scope;

317

319 LLVM::NoAliasScopeDeclOp::create(builder, call->getLoc(), scope);

320 }

321

322

323

324 for (Block &inlinedBlock : inlinedBlocks) {

325 inlinedBlock.walk([&](LLVM::AliasAnalysisOpInterface aliasInterface) {

326

327 SmallVector pointerArgs = aliasInterface.getAccessedOperands();

328

329

331 for (Value pointer : pointerArgs) {

332 FailureOr<SmallVector> underlyingObjectSet =

334 if (failed(underlyingObjectSet))

335 return;

336 llvm::copy(*underlyingObjectSet,

337 std::inserter(basedOnPointers, basedOnPointers.begin()));

338 }

339

340 bool aliasesOtherKnownObject = false;

341

342

343

344

345

346

347

348

349

350 if (llvm::any_of(basedOnPointers, [&](Value object) {

352 return false;

353

354 if (auto ssaCopy = object.getDefiningOpLLVM::SSACopyOp()) {

355

356

357 aliasesOtherKnownObject |= !noAliasParams.contains(ssaCopy);

358 return false;

359 }

360

361 if (isa_and_nonnull<LLVM::AllocaOp, LLVM::AddressOfOp>(

362 object.getDefiningOp())) {

363 aliasesOtherKnownObject = true;

364 return false;

365 }

366 return true;

367 }))

368 return;

369

370

371

373 for (LLVM::SSACopyOp noAlias : noAliasParams) {

374 if (basedOnPointers.contains(noAlias))

375 continue;

376

377 noAliasScopes.push_back(pointerScopes[noAlias]);

378 }

379

380 if (!noAliasScopes.empty())

381 aliasInterface.setNoAliasScopes(

383 ArrayAttr::get(call->getContext(), noAliasScopes)));

384

385

386

387

388

389

390

391

392

393

394

395

396

397

398

399

400

401

402

403

404

405

406

407

408

409 if (aliasesOtherKnownObject ||

410 isaLLVM::CallOp(aliasInterface.getOperation()))

411 return;

412

414 for (LLVM::SSACopyOp noAlias : noAliasParams)

415 if (basedOnPointers.contains(noAlias))

416 aliasScopes.push_back(pointerScopes[noAlias]);

417

418 if (!aliasScopes.empty())

419 aliasInterface.setAliasScopes(

421 ArrayAttr::get(call->getContext(), aliasScopes)));

422 });

423 }

424}

425

426

427

428static void

431 auto callAliasInterface = dyn_castLLVM::AliasAnalysisOpInterface(call);

432 if (!callAliasInterface)

433 return;

434

435 ArrayAttr aliasScopes = callAliasInterface.getAliasScopesOrNull();

436 ArrayAttr noAliasScopes = callAliasInterface.getNoAliasScopesOrNull();

437

438

439 if (!aliasScopes && !noAliasScopes)

440 return;

441

442

443

444 for (Block &block : inlinedBlocks) {

445 block.walk([&](LLVM::AliasAnalysisOpInterface aliasInterface) {

446 if (aliasScopes)

448 aliasInterface.getAliasScopesOrNull(), aliasScopes));

449

450 if (noAliasScopes)

452 aliasInterface.getNoAliasScopesOrNull(), noAliasScopes));

453 });

454 }

455}

456

457

464

465

466

469 auto callAccessGroupInterface = dyn_castLLVM::AccessGroupOpInterface(call);

470 if (!callAccessGroupInterface)

471 return;

472

473 auto accessGroups = callAccessGroupInterface.getAccessGroupsOrNull();

474 if (!accessGroups)

475 return;

476

477

478

479 for (Block &block : inlinedBlocks)

480 for (auto accessGroupOpInterface :

481 block.getOpsLLVM::AccessGroupOpInterface())

483 accessGroupOpInterface.getAccessGroupsOrNull(), accessGroups));

484}

485

486

487static void

490

493 return;

495 auto fusedLoc = dyn_cast_if_present(funcLoc);

496 if (!fusedLoc)

497 return;

498 auto scope =

499 dyn_cast_if_presentLLVM::DISubprogramAttr(fusedLoc.getMetadata());

500 if (!scope)

501 return;

502

503

504

506 if (!loc)

507 return {};

508 Location callSiteLoc = CallSiteLoc::get(loc, call->getLoc());

509 return FusedLoc::get(loc.getContext(), callSiteLoc, scope);

510 };

511

513 replacer.addReplacement([&](LLVM::LoopAnnotationAttr loopAnnotation)

514 -> std::pair<Attribute, WalkResult> {

515 FusedLoc newStartLoc = updateLoc(loopAnnotation.getStartLoc());

516 FusedLoc newEndLoc = updateLoc(loopAnnotation.getEndLoc());

517 if (!newStartLoc && !newEndLoc)

519 auto newLoopAnnotation = LLVM::LoopAnnotationAttr::get(

520 loopAnnotation.getContext(), loopAnnotation.getDisableNonforced(),

521 loopAnnotation.getVectorize(), loopAnnotation.getInterleave(),

522 loopAnnotation.getUnroll(), loopAnnotation.getUnrollAndJam(),

523 loopAnnotation.getLicm(), loopAnnotation.getDistribute(),

524 loopAnnotation.getPipeline(), loopAnnotation.getPeeled(),

525 loopAnnotation.getUnswitch(), loopAnnotation.getMustProgress(),

526 loopAnnotation.getIsVectorized(), newStartLoc, newEndLoc,

527 loopAnnotation.getParallelAccesses());

528

530 });

531

532 for (Block &block : inlinedBlocks)

535}

536

537

538

539

541 uint64_t requestedAlignment,

543 uint64_t allocaAlignment = alloca.getAlignment().value_or(1);

544 if (requestedAlignment <= allocaAlignment)

545

546 return allocaAlignment;

547 uint64_t naturalStackAlignmentBits = dataLayout.getStackAlignment();

548

549

550 if (naturalStackAlignmentBits == 0 ||

551

552

553 8 * requestedAlignment <= naturalStackAlignmentBits ||

554

555

556 8 * allocaAlignment > naturalStackAlignmentBits) {

557 alloca.setAlignment(requestedAlignment);

558 allocaAlignment = requestedAlignment;

559 }

560 return allocaAlignment;

561}

562

563

564

565

566

567

568

572 if (auto alloca = dyn_castLLVM::AllocaOp(definingOp))

574 dataLayout);

575 if (auto addressOf = dyn_castLLVM::AddressOfOp(definingOp))

577 definingOp, addressOf.getGlobalNameAttr()))

578 return global.getAlignment().value_or(1);

579

580 return 1;

581 }

582

583

585 if (auto func = dyn_castLLVM::LLVMFuncOp(parentOp)) {

586

587

588 auto blockArg = llvm::cast(value);

590 blockArg.getArgNumber(), LLVM::LLVMDialect::getAlignAttrName()))

591 return cast(alignAttr).getValue().getLimitedValue();

592 }

593

594 return 1;

595}

596

597

598

600 Value argument, Type elementType,

601 uint64_t elementTypeSize,

602 uint64_t targetAlignment) {

603

605 {

606

607

611 Value one = LLVM::ConstantOp::create(builder, loc, builder.getI64Type(),

613 allocaOp = LLVM::AllocaOp::create(builder, loc, argument.getType(),

614 elementType, one, targetAlignment);

615 }

616

618 LLVM::ConstantOp::create(builder, loc, builder.getI64Type(),

620 LLVM::MemcpyOp::create(builder, loc, allocaOp, argument, copySize,

621 false);

622 return allocaOp;

623}

624

625

626

627

628

629

631 Value argument, Type elementType,

632 uint64_t requestedAlignment) {

633 auto func = castLLVM::LLVMFuncOp(callable);

634 LLVM::MemoryEffectsAttr memoryEffects = func.getMemoryEffectsAttr();

635

636

637 bool isReadOnly = memoryEffects &&

638 memoryEffects.getArgMem() != LLVM::ModRefInfo::ModRef &&

639 memoryEffects.getArgMem() != LLVM::ModRefInfo::Mod;

640

643 if (isReadOnly) {

644 if (requestedAlignment <= minimumAlignment)

645 return argument;

646 uint64_t currentAlignment =

648 if (currentAlignment >= requestedAlignment)

649 return argument;

650 }

651 uint64_t targetAlignment = std::max(requestedAlignment, minimumAlignment);

653 builder, argument.getLoc(), argument, elementType,

654 dataLayout.getTypeSize(elementType), targetAlignment);

655}

656

657namespace {

658struct LLVMInlinerInterface : public DialectInlinerInterface {

659 using DialectInlinerInterface::DialectInlinerInterface;

660

661 LLVMInlinerInterface(Dialect *dialect)

662 : DialectInlinerInterface(dialect),

663

664 disallowedFunctionAttrs({

665 StringAttr::get(dialect->getContext(), "noduplicate"),

666 StringAttr::get(dialect->getContext(), "presplitcoroutine"),

667 StringAttr::get(dialect->getContext(), "returns_twice"),

668 StringAttr::get(dialect->getContext(), "strictfp"),

669 }) {}

670

671 bool isLegalToInline(Operation *call, Operation *callable,

672 bool wouldBeCloned) const final {

673 auto callOp = dyn_castLLVM::CallOp(call);

674 if (!callOp) {

675 LDBG() << "Cannot inline: call is not an '"

676 << LLVM::CallOp::getOperationName() << "' op";

677 return false;

678 }

679 if (callOp.getNoInline()) {

680 LDBG() << "Cannot inline: call is marked no_inline";

681 return false;

682 }

683 auto funcOp = dyn_castLLVM::LLVMFuncOp(callable);

684 if (!funcOp) {

685 LDBG() << "Cannot inline: callable is not an '"

686 << LLVM::LLVMFuncOp::getOperationName() << "' op";

687 return false;

688 }

689 if (funcOp.isNoInline()) {

690 LDBG() << "Cannot inline: function is marked no_inline";

691 return false;

692 }

693 if (funcOp.isVarArg()) {

694 LDBG() << "Cannot inline: callable is variadic";

695 return false;

696 }

697

698 if (auto attrs = funcOp.getArgAttrs()) {

699 for (DictionaryAttr attrDict : attrs->getAsRange()) {

700 if (attrDict.contains(LLVM::LLVMDialect::getInAllocaAttrName())) {

701 LDBG() << "Cannot inline " << funcOp.getSymName()

702 << ": inalloca arguments not supported";

703 return false;

704 }

705 }

706 }

707

708 if (funcOp.getPersonality()) {

709 LDBG() << "Cannot inline " << funcOp.getSymName()

710 << ": unhandled function personality";

711 return false;

712 }

713 if (funcOp.getPassthrough()) {

714

715 if (llvm::any_of(*funcOp.getPassthrough(), [&](Attribute attr) {

716 auto stringAttr = dyn_cast(attr);

717 if (!stringAttr)

718 return false;

719 if (disallowedFunctionAttrs.contains(stringAttr)) {

720 LDBG() << "Cannot inline " << funcOp.getSymName()

721 << ": found disallowed function attribute " << stringAttr;

722 return true;

723 }

724 return false;

725 }))

726 return false;

727 }

728 return true;

729 }

730

732 return true;

733 }

734

736

737

738

739 return !(isaLLVM::VaStartOp(op) || isaLLVM::BlockTagOp(op));

740 }

741

742

743

744 void handleTerminator(Operation *op, Block *newDest) const final {

745

746 auto returnOp = dyn_castLLVM::ReturnOp(op);

747 if (!returnOp)

748 return;

749

750

752 LLVM::BrOp::create(builder, op->getLoc(), returnOp.getOperands(), newDest);

753 op->erase();

754 }

755

756 bool allowSingleBlockOptimization(

758 return !(!inlinedBlocks.empty() &&

759 isaLLVM::UnreachableOp(inlinedBlocks.begin()->getTerminator()));

760 }

761

762

763

764

765 void handleTerminator(Operation *op, ValueRange valuesToRepl) const final {

766

767 auto returnOp = castLLVM::ReturnOp(op);

768

769

770 assert(returnOp.getNumOperands() == valuesToRepl.size());

771 for (auto [dst, src] : llvm::zip(valuesToRepl, returnOp.getOperands()))

772 dst.replaceAllUsesWith(src);

773 }

774

777 DictionaryAttr argumentAttrs) const final {

778 if (std::optional attr =

779 argumentAttrs.getNamed(LLVM::LLVMDialect::getByValAttrName())) {

780 Type elementType = cast(attr->getValue()).getValue();

781 uint64_t requestedAlignment = 1;

782 if (std::optional alignAttr =

783 argumentAttrs.getNamed(LLVM::LLVMDialect::getAlignAttrName())) {

784 requestedAlignment = cast(alignAttr->getValue())

785 .getValue()

786 .getLimitedValue();

787 }

789 requestedAlignment);

790 }

791

792

793

794

795

796

797

798

799

800

801

802

803

804 auto copyOp = LLVM::SSACopyOp::create(builder, call->getLoc(), argument);

805 if (argumentAttrs.contains(LLVM::LLVMDialect::getNoAliasAttrName()))

806 copyOp->setDiscardableAttr(

807 builder.getStringAttr(LLVM::LLVMDialect::getNoAliasAttrName()),

808 builder.getUnitAttr());

809 return copyOp;

810 }

811

812 void processInlinedCallBlocks(

819 }

820

821

822

823

825};

826

827}

828

831 dialect->addInterfaces();

832 });

833}

834

837 dialect->addInterfaces();

838 });

839}

static bool hasLifetimeMarkers(LLVM::AllocaOp allocaOp)

Check whether the given alloca is an input to a lifetime intrinsic, optionally passing through one or...

Definition InlinerInterfaceImpl.cpp:34

static void appendCallOpAliasScopes(Operation *call, iterator_range< Region::iterator > inlinedBlocks)

Appends any alias scopes of the call operation to any inlined memory operation.

Definition InlinerInterfaceImpl.cpp:429

static void handleLoopAnnotations(Operation *call, iterator_range< Region::iterator > inlinedBlocks)

Updates locations inside loop annotations to reflect that they were inlined.

Definition InlinerInterfaceImpl.cpp:488

static ArrayAttr concatArrayAttr(ArrayAttr lhs, ArrayAttr rhs)

Creates a new ArrayAttr by concatenating lhs with rhs.

Definition InlinerInterfaceImpl.cpp:217

static void createNewAliasScopesFromNoAliasParameter(Operation *call, iterator_range< Region::iterator > inlinedBlocks)

Creates a new AliasScopeAttr for every noalias parameter and attaches it to the appropriate inlined m...

Definition InlinerInterfaceImpl.cpp:271

static FailureOr< SmallVector< Value > > getUnderlyingObjectSet(Value pointerValue)

Attempts to return the set of all underlying pointer values that pointerValue is based on.

Definition InlinerInterfaceImpl.cpp:233

static void handleAccessGroups(Operation *call, iterator_range< Region::iterator > inlinedBlocks)

Appends any access groups of the call operation to any inlined memory operation.

Definition InlinerInterfaceImpl.cpp:467

static Value handleByValArgument(OpBuilder &builder, Operation *callable, Value argument, Type elementType, uint64_t requestedAlignment)

Handles a function argument marked with the byval attribute by introducing a memcpy or realigning the...

Definition InlinerInterfaceImpl.cpp:630

static void handleAliasScopes(Operation *call, iterator_range< Region::iterator > inlinedBlocks)

Handles all interactions with alias scopes during inlining.

Definition InlinerInterfaceImpl.cpp:458

static uint64_t tryToEnforceAllocaAlignment(LLVM::AllocaOp alloca, uint64_t requestedAlignment, DataLayout const &dataLayout)

If requestedAlignment is higher than the alignment specified on alloca, realigns alloca if this does ...

Definition InlinerInterfaceImpl.cpp:540

static uint64_t tryToEnforceAlignment(Value value, uint64_t requestedAlignment, DataLayout const &dataLayout)

Tries to find and return the alignment of the pointer value by looking for an alignment attribute on ...

Definition InlinerInterfaceImpl.cpp:569

static void deepCloneAliasScopes(iterator_range< Region::iterator > inlinedBlocks)

Maps all alias scopes in the inlined operations to deep clones of the scopes and domain.

Definition InlinerInterfaceImpl.cpp:158

static Value handleByValArgumentInit(OpBuilder &builder, Location loc, Value argument, Type elementType, uint64_t elementTypeSize, uint64_t targetAlignment)

Introduces a new alloca and copies the memory pointed to by argument to the address of the new alloca...

Definition InlinerInterfaceImpl.cpp:599

static void handleInlinedAllocas(Operation *call, iterator_range< Region::iterator > inlinedBlocks)

Handles alloca operations in the inlined blocks:

Definition InlinerInterfaceImpl.cpp:56

static bool isLegalToInline(InlinerInterface &interface, Region *src, Region *insertRegion, bool shouldCloneInlinedRegion, IRMapping &valueMapping)

Utility to check that all of the operations within 'src' can be inlined.

This is an attribute/type replacer that is naively cached.

void addWalk(WalkFn< Attribute > &&fn)

Register a walk function for a given attribute or type.

WalkResult walk(T element)

Walk the given attribute/type, and recursively walk any sub elements.

Attributes are known-constant values of operations.

Block represents an ordered list of Operations.

iterator_range< op_iterator< OpT > > getOps()

Return an iterator range over the operations within this block that are of 'OpT'.

Operation * getParentOp()

Returns the closest surrounding operation that contains this block.

IntegerAttr getI64IntegerAttr(int64_t value)

Ty getType(Args &&...args)

Get or construct an instance of the type Ty with provided arguments.

The main mechanism for performing data layout queries.

static DataLayout closest(Operation *op)

Returns the layout of the closest parent operation carrying layout info.

llvm::TypeSize getTypeSize(Type t) const

Returns the size of the given type in the current scope.

uint64_t getStackAlignment() const

Returns the natural alignment of the stack in bits.

uint64_t getTypeABIAlignment(Type t) const

Returns the required alignment of the given type in the current scope.

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.

MLIRContext * getContext() const

This is a utility class for mapping one set of IR entities to another.

Location objects represent source locations information in MLIR.

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

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

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.

void setInsertionPoint(Block *block, Block::iterator insertPoint)

Set the insertion point to the specified location.

A trait of region holding operations that define a new scope for automatic allocations,...

This class provides the API for ops that are known to be isolated from above.

Operation is the basic unit of execution within MLIR.

Location getLoc()

The source location the operation was defined or derived from.

Operation * getParentOp()

Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...

OpTy getParentOfType()

Return the closest surrounding parent operation that is of type 'OpTy'.

user_range getUsers()

Returns a range of all users.

Region * getParentRegion()

Returns the region to which the instruction belongs.

MLIRContext * getContext()

Return the context this operation is associated with.

This class contains a list of basic blocks and a link to the parent operation it is attached to.

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

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

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

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.

Block * getParentBlock()

Return the Block in which this Value is defined.

Location getLoc() const

Return the location of this value.

Operation * getDefiningOp() const

If this value is the result of an operation, return the operation that defines it.

Region * getParentRegion()

Return the Region in which this Value is defined.

A class to signal how to proceed with the walk of the backward slice:

bool wasInterrupted() const

Returns true if the walk was interrupted.

static WalkContinuation skip()

Creates a continuation that advances the walk without adding any predecessor values to the work list.

static WalkContinuation advanceTo(mlir::ValueRange nextValues)

Creates a continuation that adds the user-specified nextValues to the work list and advances the walk...

static WalkContinuation interrupt()

Creates a continuation that interrupts the walk.

static WalkResult advance()

void recursivelyReplaceElementsIn(Operation *op, bool replaceAttrs=true, bool replaceLocs=false, bool replaceTypes=false)

Replace the elements within the given operation, and all nested operations.

void addReplacement(ReplaceFn< Attribute > fn)

AttrTypeReplacerBase.

void registerInlinerInterface(DialectRegistry &registry)

Register the LLVMInlinerInterface implementation of DialectInlinerInterface with the LLVM dialect.

Definition InlinerInterfaceImpl.cpp:829

void registerInlinerInterface(DialectRegistry &registry)

Register the NVVMInlinerInterface implementation of DialectInlinerInterface with the NVVM dialect.

Definition InlinerInterfaceImpl.cpp:835

Include the generated interface declarations.

bool matchPattern(Value value, const Pattern &pattern)

Entry point for matching a pattern over a Value.

std::optional< SmallVector< Value > > getControlFlowPredecessors(Value value)

Computes a vector of all control predecessors of value.

llvm::DenseSet< ValueT, ValueInfoT > DenseSet

llvm::SetVector< T, Vector, Set, N > SetVector

WalkContinuation walkSlice(mlir::ValueRange rootValues, WalkCallback walkCallback)

Walks the slice starting from the rootValues using a depth-first traversal.

llvm::DenseMap< KeyT, ValueT, KeyInfoT, BucketT > DenseMap

detail::constant_op_matcher m_Constant()

Matches a constant foldable operation.

This trait indicates that a terminator operation is "return-like".