20 #include "llvm/ADT/BitVector.h" 21 #include "llvm/ADT/SmallString.h" 22 #include "llvm/ADT/StringExtras.h" 23 #include "llvm/ADT/StringRef.h" 24 #include "llvm/ADT/StringSwitch.h" 25 #include "llvm/ADT/TypeSwitch.h" 28 #include "mlir/Dialect/OpenMP/OpenMPOpsDialect.cpp.inc" 29 #include "mlir/Dialect/OpenMP/OpenMPOpsEnums.cpp.inc" 30 #include "mlir/Dialect/OpenMP/OpenMPOpsInterfaces.cpp.inc" 31 #include "mlir/Dialect/OpenMP/OpenMPTypeInterfaces.cpp.inc" 39 struct PointerLikeModel
40 :
public PointerLikeType::ExternalModel<PointerLikeModel<T>, T> {
47 void OpenMPDialect::initialize() {
50 #include "mlir/Dialect/OpenMP/OpenMPOps.cpp.inc" 53 #define GET_ATTRDEF_LIST 54 #include "mlir/Dialect/OpenMP/OpenMPOpsAttributes.cpp.inc" 58 PointerLikeModel<LLVM::LLVMPointerType>>(*getContext());
59 MemRefType::attachInterface<PointerLikeModel<MemRefType>>(*getContext());
84 operandsAllocator.push_back(operand);
85 typesAllocator.push_back(type);
91 operandsAllocate.push_back(operand);
92 typesAllocate.push_back(type);
103 for (
unsigned i = 0; i < varsAllocate.size(); ++i) {
104 std::string separator = i == varsAllocate.size() - 1 ?
"" :
", ";
105 p << varsAllocator[i] <<
" : " << typesAllocator[i] <<
" -> ";
106 p << varsAllocate[i] <<
" : " << typesAllocate[i] << separator;
114 template <
typename ClauseAttr>
116 using ClauseT = decltype(std::declval<ClauseAttr>().getValue());
122 attr = ClauseAttr::get(parser.
getContext(), *enumValue);
125 return parser.
emitError(loc,
"invalid clause value: '") << enumStr <<
"'";
128 template <
typename ClauseAttr>
130 p << stringifyEnum(attr.getValue());
154 types.push_back(type);
155 stepVars.push_back(stepVar);
164 size_t linearVarsSize = linearVars.size();
165 for (
unsigned i = 0; i < linearVarsSize; ++i) {
166 std::string separator = i == linearVarsSize - 1 ?
"" :
", ";
168 if (linearStepVars.size() > i)
169 p <<
" = " << linearStepVars[i];
170 p <<
" : " << linearVars[i].getType() << separator;
181 if (modifiers.size() > 2)
183 for (
const auto &
mod : modifiers) {
186 auto symbol = symbolizeScheduleModifier(
mod);
189 <<
" unknown modifier type: " <<
mod;
194 if (modifiers.size() == 1) {
195 if (symbolizeScheduleModifier(modifiers[0]) == ScheduleModifier::simd) {
196 modifiers.push_back(modifiers[0]);
197 modifiers[0] = stringifyScheduleModifier(ScheduleModifier::none);
199 }
else if (modifiers.size() == 2) {
202 if (symbolizeScheduleModifier(modifiers[0]) == ScheduleModifier::simd ||
203 symbolizeScheduleModifier(modifiers[1]) != ScheduleModifier::simd)
205 <<
" incorrect modifier order";
221 ScheduleModifierAttr &scheduleModifier, UnitAttr &simdModifier,
227 symbolizeClauseScheduleKind(keyword);
231 scheduleAttr = ClauseScheduleKindAttr::get(parser.
getContext(), *schedule);
233 case ClauseScheduleKind::Static:
234 case ClauseScheduleKind::Dynamic:
235 case ClauseScheduleKind::Guided:
244 case ClauseScheduleKind::Auto:
255 modifiers.push_back(mod);
261 if (!modifiers.empty()) {
264 symbolizeScheduleModifier(modifiers[0])) {
265 scheduleModifier = ScheduleModifierAttr::get(parser.
getContext(), *
mod);
267 return parser.
emitError(loc,
"invalid schedule modifier");
270 if (modifiers.size() > 1) {
271 assert(symbolizeScheduleModifier(modifiers[1]) == ScheduleModifier::simd);
281 ClauseScheduleKindAttr schedAttr,
282 ScheduleModifierAttr modifier, UnitAttr simd,
283 Value scheduleChunkVar,
284 Type scheduleChunkType) {
285 p << stringifyClauseScheduleKind(schedAttr.getValue());
286 if (scheduleChunkVar)
287 p <<
" = " << scheduleChunkVar <<
" : " << scheduleChunkVar.
getType();
289 p <<
", " << stringifyScheduleModifier(modifier.getValue());
305 ArrayAttr &redcuctionSymbols) {
308 if (parser.parseAttribute(reductionVec.emplace_back()) ||
309 parser.parseArrow() ||
310 parser.parseOperand(operands.emplace_back()) ||
311 parser.parseColonType(types.emplace_back()))
317 redcuctionSymbols = ArrayAttr::get(parser.
getContext(), reductions);
326 for (
unsigned i = 0, e = reductions->size(); i < e; ++i) {
329 p << (*reductions)[i] <<
" -> " << reductionVars[i] <<
" : " 338 if (!reductionVars.empty()) {
339 if (!reductions || reductions->size() != reductionVars.size())
341 <<
"expected as many reduction symbol references " 342 "as reduction variables";
345 return op->
emitOpError() <<
"unexpected reduction symbol references";
352 for (
auto args : llvm::zip(reductionVars, *reductions)) {
353 Value accum = std::get<0>(args);
355 if (!accumulators.insert(accum).second)
356 return op->
emitOpError() <<
"accumulator variable used more than once";
359 auto symbolRef = std::get<1>(args).cast<SymbolRefAttr>();
361 SymbolTable::lookupNearestSymbolFrom<ReductionDeclareOp>(op, symbolRef);
363 return op->emitOpError() <<
"expected symbol reference " << symbolRef
364 <<
" to point to a reduction declaration";
366 if (decl.getAccumulatorType() && decl.getAccumulatorType() != varType)
367 return op->emitOpError()
368 <<
"expected accumulator (" << varType
369 <<
") to be the same type as reduction declaration (" 370 << decl.getAccumulatorType() <<
")";
385 IntegerAttr &hintAttr) {
386 StringRef hintKeyword;
395 if (hintKeyword ==
"uncontended")
397 else if (hintKeyword ==
"contended")
399 else if (hintKeyword ==
"nonspeculative")
401 else if (hintKeyword ==
"speculative")
405 << hintKeyword <<
" is not a valid hint";
416 IntegerAttr hintAttr) {
417 int64_t hint = hintAttr.getInt();
425 auto bitn = [](
int value,
int n) ->
bool {
return value & (1 << n); };
427 bool uncontended = bitn(hint, 0);
428 bool contended = bitn(hint, 1);
429 bool nonspeculative = bitn(hint, 2);
430 bool speculative = bitn(hint, 3);
434 hints.push_back(
"uncontended");
436 hints.push_back(
"contended");
438 hints.push_back(
"nonspeculative");
440 hints.push_back(
"speculative");
442 llvm::interleaveComma(hints, p);
449 auto bitn = [](
int value,
int n) ->
bool {
return value & (1 << n); };
451 bool uncontended = bitn(hint, 0);
452 bool contended = bitn(hint, 1);
453 bool nonspeculative = bitn(hint, 2);
454 bool speculative = bitn(hint, 3);
456 if (uncontended && contended)
457 return op->
emitOpError() <<
"the hints omp_sync_hint_uncontended and " 458 "omp_sync_hint_contended cannot be combined";
459 if (nonspeculative && speculative)
460 return op->
emitOpError() <<
"the hints omp_sync_hint_nonspeculative and " 461 "omp_sync_hint_speculative cannot be combined.";
472 builder, state,
nullptr,
nullptr,
480 if (allocate_vars().size() != allocators_vars().size())
482 "expected equal sizes for allocate and allocator variables");
491 if (allocate_vars().size() != allocators_vars().size())
493 "expected equal sizes for allocate and allocator variables");
499 for (
auto &inst : *region().begin()) {
500 if (!(isa<SectionOp>(inst) || isa<TerminatorOp>(inst))) {
502 <<
"expected omp.section op or terminator op inside region";
511 if (allocate_vars().size() != allocators_vars().size())
513 "expected equal sizes for allocate and allocator variables");
556 iv.type = loopVarType;
563 UnitAttr inclusive) {
565 p <<
" (" << args <<
") : " << args[0].getType() <<
" = (" << lowerBound
566 <<
") to (" << upperBound <<
") ";
569 p <<
"step (" << steps <<
") ";
578 if (this->lowerBound().empty()) {
579 return emitOpError() <<
"empty lowerbound for simd loop operation";
596 ReductionDeclareOp op,
Region ®ion) {
599 printer <<
"atomic ";
604 if (initializerRegion().empty())
605 return emitOpError() <<
"expects non-empty initializer region";
606 Block &initializerEntryBlock = initializerRegion().
front();
609 return emitOpError() <<
"expects initializer region with one argument " 610 "of the reduction type";
613 for (YieldOp yieldOp : initializerRegion().getOps<YieldOp>()) {
614 if (yieldOp.results().size() != 1 ||
615 yieldOp.results().getTypes()[0] != type())
616 return emitOpError() <<
"expects initializer region to yield a value " 617 "of the reduction type";
620 if (reductionRegion().empty())
621 return emitOpError() <<
"expects non-empty reduction region";
622 Block &reductionEntryBlock = reductionRegion().
front();
627 return emitOpError() <<
"expects reduction region with two arguments of " 628 "the reduction type";
629 for (YieldOp yieldOp : reductionRegion().getOps<YieldOp>()) {
630 if (yieldOp.results().size() != 1 ||
631 yieldOp.results().getTypes()[0] != type())
632 return emitOpError() <<
"expects reduction region to yield a value " 633 "of the reduction type";
636 if (atomicReductionRegion().empty())
639 Block &atomicReductionEntryBlock = atomicReductionRegion().
front();
643 return emitOpError() <<
"expects atomic reduction region with two " 644 "arguments of the same type";
646 .dyn_cast<PointerLikeType>();
647 if (!ptrType || ptrType.getElementType() != type())
648 return emitOpError() <<
"expects atomic reduction region arguments to " 649 "be accumulators containing the reduction type";
654 auto *op = (*this)->getParentWithTrait<ReductionClauseInterface::Trait>();
656 return emitOpError() <<
"must be used within an operation supporting " 657 "reduction clause interface";
659 for (
const auto &var :
660 cast<ReductionClauseInterface>(op).getReductionVars())
661 if (var == accumulator())
663 op = op->getParentWithTrait<ReductionClauseInterface::Trait>();
665 return emitOpError() <<
"the accumulator is not used by the parent";
680 task_reduction_vars());
688 in_reduction_vars().end());
689 all_reduction_nvars.insert(all_reduction_nvars.end(),
690 reduction_vars().begin(), reduction_vars().end());
691 return all_reduction_nvars;
695 if (allocate_vars().size() != allocators_vars().size())
697 "expected equal sizes for allocate and allocator variables");
703 if (reduction_vars().size() > 0 && nogroup())
704 return emitError(
"if a reduction clause is present on the taskloop " 705 "directive, the nogroup clause must not be specified");
706 for (
auto var : reduction_vars()) {
707 if (llvm::is_contained(in_reduction_vars(), var))
708 return emitError(
"the same list item cannot appear in both a reduction " 709 "and an in_reduction clause");
712 if (grain_size() && num_tasks()) {
714 "the grainsize clause and num_tasks clause are mutually exclusive and " 715 "may not appear on the same taskloop directive");
727 build(builder, state, lowerBound, upperBound, step,
732 false,
false,
nullptr,
751 SymbolRefAttr symbolRef = nameAttr();
755 return emitOpError() <<
"expected symbol reference " << symbolRef
756 <<
" to point to a critical declaration";
768 auto container = (*this)->getParentOfType<WsLoopOp>();
769 if (!container || !container.ordered_valAttr() ||
770 container.ordered_valAttr().getInt() == 0)
771 return emitOpError() <<
"ordered depend directive must be closely " 772 <<
"nested inside a worksharing-loop with ordered " 773 <<
"clause with parameter present";
775 if (container.ordered_valAttr().getInt() != (int64_t)*num_loops_val())
776 return emitOpError() <<
"number of variables in depend clause does not " 777 <<
"match number of iteration variables in the " 788 if (
auto container = (*this)->getParentOfType<WsLoopOp>()) {
789 if (!container.ordered_valAttr() ||
790 container.ordered_valAttr().getInt() != 0)
791 return emitOpError() <<
"ordered region must be closely nested inside " 792 <<
"a worksharing-loop region with an ordered " 793 <<
"clause without parameter present";
804 if (
auto mo = memory_order_val()) {
805 if (*mo == ClauseMemoryOrderKind::Acq_rel ||
806 *mo == ClauseMemoryOrderKind::Release) {
808 "memory-order must not be acq_rel or release for atomic reads");
813 "read and write must not be to the same location for atomic reads");
822 if (
auto mo = memory_order_val()) {
823 if (*mo == ClauseMemoryOrderKind::Acq_rel ||
824 *mo == ClauseMemoryOrderKind::Acquire) {
826 "memory-order must not be acq_rel or acquire for atomic writes");
829 if (address().getType().cast<PointerLikeType>().
getElementType() !=
831 return emitError(
"address must dereference to value type");
839 bool AtomicUpdateOp::isNoOp() {
840 YieldOp yieldOp = dyn_cast<omp::YieldOp>(getFirstOp());
842 yieldOp.results().front() == getRegion().front().getArgument(0));
845 Value AtomicUpdateOp::getWriteOpVal() {
846 YieldOp yieldOp = dyn_cast<omp::YieldOp>(getFirstOp());
848 yieldOp.results().front() != getRegion().front().getArgument(0))
849 return yieldOp.results().front();
853 LogicalResult AtomicUpdateOp::canonicalize(AtomicUpdateOp op,
859 if (
Value writeVal = op.getWriteOpVal()) {
861 op, op.x(), writeVal, op.hint_valAttr(), op.memory_order_valAttr());
868 if (
auto mo = memory_order_val()) {
869 if (*mo == ClauseMemoryOrderKind::Acq_rel ||
870 *mo == ClauseMemoryOrderKind::Acquire) {
872 "memory-order must not be acq_rel or acquire for atomic updates");
876 if (region().getNumArguments() != 1)
877 return emitError(
"the region must accept exactly one argument");
880 region().getArgument(0).getType()) {
881 return emitError(
"the type of the operand must be a pointer type whose " 882 "element type is the same as that of the region argument");
890 YieldOp yieldOp = *region().getOps<YieldOp>().begin();
892 if (yieldOp.results().size() != 1)
893 return emitError(
"only updated value must be returned");
894 if (yieldOp.results().front().getType() != region().getArgument(0).getType())
895 return emitError(
"input and yielded value must have the same type");
903 Operation *AtomicCaptureOp::getFirstOp() {
904 return &getRegion().front().getOperations().front();
907 Operation *AtomicCaptureOp::getSecondOp() {
908 auto &ops = getRegion().front().getOperations();
909 return ops.getNextNode(ops.front());
912 AtomicReadOp AtomicCaptureOp::getAtomicReadOp() {
913 if (
auto op = dyn_cast<AtomicReadOp>(getFirstOp()))
915 return dyn_cast<AtomicReadOp>(getSecondOp());
918 AtomicWriteOp AtomicCaptureOp::getAtomicWriteOp() {
919 if (
auto op = dyn_cast<AtomicWriteOp>(getFirstOp()))
921 return dyn_cast<AtomicWriteOp>(getSecondOp());
924 AtomicUpdateOp AtomicCaptureOp::getAtomicUpdateOp() {
925 if (
auto op = dyn_cast<AtomicUpdateOp>(getFirstOp()))
927 return dyn_cast<AtomicUpdateOp>(getSecondOp());
938 <<
"expected three operations in omp.atomic.capture region (one " 939 "terminator, and two atomic ops)";
940 auto &firstOp = ops.front();
941 auto &secondOp = *ops.getNextNode(firstOp);
942 auto firstReadStmt = dyn_cast<AtomicReadOp>(firstOp);
943 auto firstUpdateStmt = dyn_cast<AtomicUpdateOp>(firstOp);
944 auto secondReadStmt = dyn_cast<AtomicReadOp>(secondOp);
945 auto secondUpdateStmt = dyn_cast<AtomicUpdateOp>(secondOp);
946 auto secondWriteStmt = dyn_cast<AtomicWriteOp>(secondOp);
948 if (!((firstUpdateStmt && secondReadStmt) ||
949 (firstReadStmt && secondUpdateStmt) ||
950 (firstReadStmt && secondWriteStmt)))
951 return ops.front().emitError()
952 <<
"invalid sequence of operations in the capture region";
953 if (firstUpdateStmt && secondReadStmt &&
954 firstUpdateStmt.x() != secondReadStmt.x())
955 return firstUpdateStmt.emitError()
956 <<
"updated variable in omp.atomic.update must be captured in " 958 if (firstReadStmt && secondUpdateStmt &&
959 firstReadStmt.x() != secondUpdateStmt.x())
960 return firstReadStmt.emitError()
961 <<
"captured variable in omp.atomic.read must be updated in second " 963 if (firstReadStmt && secondWriteStmt &&
964 firstReadStmt.x() != secondWriteStmt.address())
965 return firstReadStmt.emitError()
966 <<
"captured variable in omp.atomic.read must be updated in " 969 if (getFirstOp()->getAttr(
"hint_val") || getSecondOp()->getAttr(
"hint_val"))
971 "operations inside capture region must not have hint clause");
973 if (getFirstOp()->getAttr(
"memory_order_val") ||
974 getSecondOp()->getAttr(
"memory_order_val"))
976 "operations inside capture region must not have memory_order clause");
985 ClauseCancellationConstructType cct = cancellation_construct_type_val();
989 return emitOpError() <<
"must be used within a region supporting " 994 !isa<ParallelOp>(parentOp)) {
995 return emitOpError() <<
"cancel parallel must appear " 996 <<
"inside a parallel region";
998 if (cct == ClauseCancellationConstructType::Loop) {
999 if (!isa<WsLoopOp>(parentOp)) {
1000 return emitOpError() <<
"cancel loop must appear " 1001 <<
"inside a worksharing-loop region";
1003 if (cast<WsLoopOp>(parentOp).nowaitAttr()) {
1004 return emitError() <<
"A worksharing construct that is canceled " 1005 <<
"must not have a nowait clause";
1007 if (cast<WsLoopOp>(parentOp).ordered_valAttr()) {
1008 return emitError() <<
"A worksharing construct that is canceled " 1009 <<
"must not have an ordered clause";
1012 }
else if (cct == ClauseCancellationConstructType::Sections) {
1013 if (!(isa<SectionsOp>(parentOp) || isa<SectionOp>(parentOp))) {
1014 return emitOpError() <<
"cancel sections must appear " 1015 <<
"inside a sections region";
1017 if (isa_and_nonnull<SectionsOp>(parentOp->
getParentOp()) &&
1018 cast<SectionsOp>(parentOp->
getParentOp()).nowaitAttr()) {
1019 return emitError() <<
"A sections construct that is canceled " 1020 <<
"must not have a nowait clause";
1031 ClauseCancellationConstructType cct = cancellation_construct_type_val();
1035 return emitOpError() <<
"must be used within a region supporting " 1036 "cancellation point directive";
1040 !(isa<ParallelOp>(parentOp))) {
1041 return emitOpError() <<
"cancellation point parallel must appear " 1042 <<
"inside a parallel region";
1044 if ((cct == ClauseCancellationConstructType::Loop) &&
1045 !isa<WsLoopOp>(parentOp)) {
1046 return emitOpError() <<
"cancellation point loop must appear " 1047 <<
"inside a worksharing-loop region";
1049 if ((cct == ClauseCancellationConstructType::Sections) &&
1050 !(isa<SectionsOp>(parentOp) || isa<SectionOp>(parentOp))) {
1051 return emitOpError() <<
"cancellation point sections must appear " 1052 <<
"inside a sections region";
1058 #define GET_ATTRDEF_CLASSES 1059 #include "mlir/Dialect/OpenMP/OpenMPOpsAttributes.cpp.inc" 1061 #define GET_OP_CLASSES 1062 #include "mlir/Dialect/OpenMP/OpenMPOps.cpp.inc" Include the generated interface declarations.
static void printScheduleClause(OpAsmPrinter &p, Operation *op, ClauseScheduleKindAttr schedAttr, ScheduleModifierAttr modifier, UnitAttr simd, Value scheduleChunkVar, Type scheduleChunkType)
Print schedule clause.
virtual SMLoc getNameLoc() const =0
Return the location of the original name token.
static ParseResult parseAtomicReductionRegion(OpAsmParser &parser, Region ®ion)
This class contains a list of basic blocks and a link to the parent operation it is attached to...
MLIRContext * getContext() const
A special type of RewriterBase that coordinates the application of a rewrite pattern on the current I...
Operation is a basic unit of execution within MLIR.
virtual SMLoc getCurrentLocation()=0
Get the location of the next token and store it into the argument.
static ParseResult parseAllocateAndAllocator(OpAsmParser &parser, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &operandsAllocate, SmallVectorImpl< Type > &typesAllocate, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &operandsAllocator, SmallVectorImpl< Type > &typesAllocator)
Parse an allocate clause with allocators and a list of operands with types.
Block represents an ordered list of Operations.
virtual void eraseOp(Operation *op)
This method erases an operation that is known to have no uses.
virtual ParseResult parseCommaSeparatedList(Delimiter delimiter, function_ref< ParseResult()> parseElementFn, StringRef contextMessage=StringRef())=0
Parse a list of comma-separated items with an optional delimiter.
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value...
static Type getElementType(Type type, ArrayRef< int32_t > indices, function_ref< InFlightDiagnostic(StringRef)> emitErrorFn)
Walks the given type hierarchy with the given indices, potentially down to component granularity...
static ParseResult parseScheduleClause(OpAsmParser &parser, ClauseScheduleKindAttr &scheduleAttr, ScheduleModifierAttr &scheduleModifier, UnitAttr &simdModifier, Optional< OpAsmParser::UnresolvedOperand > &chunkSize, Type &chunkType)
schedule ::= schedule ( sched-list ) sched-list ::= sched-val | sched-val sched-list | sched-val ...
void printClauseAttr(OpAsmPrinter &p, Operation *op, ClauseAttr attr)
static void printAllocateAndAllocator(OpAsmPrinter &p, Operation *op, OperandRange varsAllocate, TypeRange typesAllocate, OperandRange varsAllocator, TypeRange typesAllocator)
Print allocate clause.
bool succeeded(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a success value...
This is the representation of an operand reference.
static LogicalResult verifySynchronizationHint(Operation *op, uint64_t hint)
Verifies a synchronization hint clause.
The OpAsmParser has methods for interacting with the asm parser: parsing things from it...
virtual Builder & getBuilder() const =0
Return a builder which provides useful access to MLIRContext, global objects like types and attribute...
virtual ParseResult parseOptionalKeyword(StringRef keyword)=0
Parse the given keyword if present.
BlockArgument getArgument(unsigned i)
static constexpr const bool value
Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)
Returns the operation registered with the given symbol name within the closest parent operation of...
virtual ParseResult parseOptionalComma()=0
Parse a , token if present.
static LogicalResult verifyReductionVarList(Operation *op, Optional< ArrayAttr > reductions, OperandRange reductionVars)
Verifies Reduction Clause.
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
This class represents an efficient way to signal success or failure.
LogicalResult failure(bool isFailure=true)
Utility function to generate a LogicalResult.
This class represents a collection of SymbolTables.
virtual InFlightDiagnostic emitError(SMLoc loc, const Twine &message={})=0
Emit a diagnostic at the specified location and return failure.
static void printLinearClause(OpAsmPrinter &p, Operation *op, ValueRange linearVars, TypeRange linearVarTypes, ValueRange linearStepVars)
Print Linear Clause.
unsigned getNumArguments()
ParseResult parseLoopControl(OpAsmParser &parser, Region ®ion, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &lowerBound, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &upperBound, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &steps, SmallVectorImpl< Type > &loopVarTypes, UnitAttr &inclusive)
loop-control ::= ( ssa-id-list ) : type = loop-bounds loop-bounds := ( ssa-id-list ) to ( ssa-id-list...
Operation * getParentOp()
Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...
static void printSynchronizationHint(OpAsmPrinter &p, Operation *op, IntegerAttr hintAttr)
Prints a Synchronization Hint clause.
void addAttributes(ArrayRef< NamedAttribute > newAttributes)
Add an array of named attributes.
int64_t mod(int64_t lhs, int64_t rhs)
Returns MLIR's mod operation on constants.
This class provides an abstraction over the various different ranges of value types.
This is a pure-virtual base class that exposes the asmprinter hooks necessary to implement a custom p...
This represents an operation in an abstracted form, suitable for use with the builder APIs...
virtual ParseResult parseOperand(UnresolvedOperand &result, bool allowResultNumber=true)=0
Parse a single SSA value operand name along with a result number if allowResultNumber is true...
static ParseResult parseSynchronizationHint(OpAsmParser &parser, IntegerAttr &hintAttr)
Parses a Synchronization Hint clause.
Parens surrounding zero or more operands.
static ParseResult parseLinearClause(OpAsmParser &parser, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &vars, SmallVectorImpl< Type > &types, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &stepVars)
linear ::= linear ( linear-list ) linear-list := linear-val | linear-val linear-list linear-val := ss...
BlockArgListType getArguments()
This base class exposes generic asm parser hooks, usable across the various derived parsers...
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Runtime
Potential runtimes for AMD GPU kernels.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
ParseResult parseKeyword(StringRef keyword)
Parse a given keyword.
virtual ParseResult parseArrow()=0
Parse a '->' token.
static void attachInterface(MLIRContext &context)
Attach the given models as implementations of the corresponding interfaces for the concrete storage u...
ValueTypeRange< BlockArgListType > getArgumentTypes()
Return a range containing the types of the arguments for this block.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
Type getType() const
Return the type of this value.
llvm::iplist< Operation > OpListType
This is the list of operations in the block.
OpTy replaceOpWithNewOp(Operation *op, Args &&...args)
Replaces the result op with a new op that is created without verification.
virtual ParseResult parseArgumentList(SmallVectorImpl< Argument > &result, Delimiter delimiter=Delimiter::None, bool allowType=false, bool allowAttrs=false)=0
Parse zero or more arguments with a specified surrounding delimiter.
static void printReductionVarList(OpAsmPrinter &p, Operation *op, OperandRange reductionVars, TypeRange reductionTypes, Optional< ArrayAttr > reductions)
Print Reduction clause.
type_range getType() const
virtual ParseResult parseRegion(Region ®ion, ArrayRef< Argument > arguments={}, bool enableNameShadowing=false)=0
Parses a region.
static void printAtomicReductionRegion(OpAsmPrinter &printer, ReductionDeclareOp op, Region ®ion)
This class implements the operand iterators for the Operation class.
LogicalResult verify(Operation *op, bool verifyRecursively=true)
Perform (potentially expensive) checks of invariants, used to detect compiler bugs, on this operation and any nested operations.
virtual ParseResult parseEqual()=0
Parse a = token.
InFlightDiagnostic emitOpError(const Twine &message={})
Emit an error with the op name prefixed, like "'dim' op " which is convenient for verifiers...
static ParseResult verifyScheduleModifiers(OpAsmParser &parser, SmallVectorImpl< SmallString< 12 >> &modifiers)
MLIRContext * getContext() const
This class represents success/failure for parsing-like operations that find it important to chain tog...
void printLoopControl(OpAsmPrinter &p, Operation *op, Region ®ion, ValueRange lowerBound, ValueRange upperBound, ValueRange steps, TypeRange loopVarTypes, UnitAttr inclusive)
This class helps build Operations.
This class provides an abstraction over the different types of ranges over Values.
virtual ParseResult parseOptionalEqual()=0
Parse a = token if present.
static ParseResult parseClauseAttr(AsmParser &parser, ClauseAttr &attr)
virtual ParseResult parseOperandList(SmallVectorImpl< UnresolvedOperand > &result, Delimiter delimiter=Delimiter::None, bool allowResultNumber=true, int requiredOperandCount=-1)=0
Parse zero or more SSA comma-separated operand references with a specified surrounding delimiter...
virtual ParseResult parseColonType(Type &result)=0
Parse a colon followed by a type.
virtual void printRegion(Region &blocks, bool printEntryBlockArgs=true, bool printBlockTerminators=true, bool printEmptyBlock=false)=0
Prints a region.
static ParseResult parseReductionVarList(OpAsmParser &parser, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &operands, SmallVectorImpl< Type > &types, ArrayAttr &redcuctionSymbols)
reduction-entry-list ::= reduction-entry | reduction-entry-list , reduction-entry reduction-entry ::=...