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 ()
219 return rhs;
220 if ()
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 ®istry)
Register the LLVMInlinerInterface implementation of DialectInlinerInterface with the LLVM dialect.
Definition InlinerInterfaceImpl.cpp:829
void registerInlinerInterface(DialectRegistry ®istry)
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".