27#include "llvm/ADT/STLExtras.h"
28#include "llvm/ADT/SmallVector.h"
55struct RemoveEmptyKernelEnvironment
57 using OpRewritePattern<acc::KernelEnvironmentOp>::OpRewritePattern;
59 LogicalResult matchAndRewrite(acc::KernelEnvironmentOp op,
60 PatternRewriter &rewriter)
const override {
61 assert(op->getNumRegions() == 1 &&
"expected op to have one region");
63 Block &block = op.getRegion().front();
72 if (
auto deviceTypeAttr = op.getWaitOperandsDeviceTypeAttr()) {
73 for (
auto attr : deviceTypeAttr) {
74 if (
auto dtAttr = mlir::dyn_cast<acc::DeviceTypeAttr>(attr)) {
75 if (dtAttr.getValue() != mlir::acc::DeviceType::None)
82 if (
auto hasDevnumAttr = op.getHasWaitDevnumAttr()) {
83 for (
auto attr : hasDevnumAttr) {
84 if (
auto boolAttr = mlir::dyn_cast<mlir::BoolAttr>(attr)) {
85 if (boolAttr.getValue())
92 if (
auto segmentsAttr = op.getWaitOperandsSegmentsAttr()) {
93 if (segmentsAttr.size() > 1)
99 if (!op.getWaitOperands().empty() || op.getWaitOnlyAttr())
112static void updateComputeRegionInputOperandSegments(ComputeRegionOp op,
115 const size_t numLaunch = op.getLaunchArgs().size();
116 op->setAttr(ComputeRegionOp::getOperandSegmentSizeAttr(),
118 static_cast<int32_t>(numInput),
119 op.getStream() ? 1 : 0}));
122struct ComputeRegionRemoveDuplicateArgs
126 LogicalResult matchAndRewrite(ComputeRegionOp op,
127 PatternRewriter &rewriter)
const override {
128 Block *body = op.getBody();
129 const size_t numLaunch = op.getLaunchArgs().size();
130 size_t numInput = op.getInputArgs().size();
132 "region args mismatch");
134 bool mergedAny =
false;
137 for (
size_t j = 1; j < numInput && !merged; ++j) {
138 for (
size_t i = 0; i < j; ++i) {
139 if (op->getOperand(
static_cast<unsigned>(numLaunch + i)) !=
140 op->getOperand(
static_cast<unsigned>(numLaunch + j)))
142 unsigned keepIdx =
static_cast<unsigned>(numLaunch + i);
143 unsigned dropIdx =
static_cast<unsigned>(numLaunch + j);
147 op->eraseOperand(dropIdx);
160 updateComputeRegionInputOperandSegments(op, rewriter, numInput);
165struct ComputeRegionRemoveUnusedArgs
169 LogicalResult matchAndRewrite(ComputeRegionOp op,
170 PatternRewriter &rewriter)
const override {
171 Block *body = op.getBody();
172 const size_t numLaunch = op.getLaunchArgs().size();
173 size_t numInput = op.getInputArgs().size();
175 "region args mismatch");
177 bool changed =
false;
178 for (
size_t k = numLaunch; k < numLaunch + numInput;) {
184 op->eraseOperand(
static_cast<unsigned>(k));
191 updateComputeRegionInputOperandSegments(op, rewriter, numInput);
196template <
typename EffectTy>
201 for (
unsigned i = 0, e = operand.
size(); i < e; ++i)
202 effects.emplace_back(EffectTy::get(), &operand[i]);
205template <
typename EffectTy>
210 effects.emplace_back(EffectTy::get(), mlir::cast<mlir::OpResult>(
result));
213static int64_t gpuProcessorIndex(gpu::Processor p) {
215 case gpu::Processor::Sequential:
217 case gpu::Processor::ThreadX:
219 case gpu::Processor::ThreadY:
221 case gpu::Processor::ThreadZ:
223 case gpu::Processor::BlockX:
225 case gpu::Processor::BlockY:
227 case gpu::Processor::BlockZ:
230 llvm_unreachable(
"unhandled gpu::Processor");
233static gpu::Processor indexToGpuProcessor(
int64_t idx) {
236 return gpu::Processor::Sequential;
238 return gpu::Processor::ThreadX;
240 return gpu::Processor::ThreadY;
242 return gpu::Processor::ThreadZ;
244 return gpu::Processor::BlockX;
246 return gpu::Processor::BlockY;
248 return gpu::Processor::BlockZ;
250 return gpu::Processor::Sequential;
255 return GPUParallelDimAttr::get(
256 context, IntegerAttr::get(IndexType::get(context), dimInt));
259static GPUParallelDimAttr processorParDim(
MLIRContext *context,
260 gpu::Processor proc) {
261 return GPUParallelDimAttr::get(
263 IntegerAttr::get(IndexType::get(context), gpuProcessorIndex(proc)));
266static ParseResult parseProcessorValue(
AsmParser &parser,
267 GPUParallelDimAttr &dim) {
272 auto maybeProcessor = gpu::symbolizeProcessor(keyword);
275 <<
"expected one of ::mlir::gpu::Processor enum names";
276 dim = intToParDim(parser.
getContext(), gpuProcessorIndex(*maybeProcessor));
280static void printProcessorValue(
AsmPrinter &printer,
281 const GPUParallelDimAttr &attr) {
282 gpu::Processor processor = indexToGpuProcessor(attr.getValue().getInt());
283 printer << gpu::stringifyProcessor(processor);
292void KernelEnvironmentOp::getSuccessorRegions(
302void KernelEnvironmentOp::getCanonicalizationPatterns(
304 results.
add<RemoveEmptyKernelEnvironment>(context);
307template <
typename ComputeConstructT>
309KernelEnvironmentOp::createAndPopulate(ComputeConstructT computeConstruct,
311 auto kernelEnvironment = KernelEnvironmentOp::create(
312 builder, computeConstruct->getLoc(),
313 computeConstruct.getDataClauseOperands(),
314 computeConstruct.getAsyncOperands(),
315 computeConstruct.getAsyncOperandsDeviceTypeAttr(),
316 computeConstruct.getAsyncOnlyAttr(), computeConstruct.getWaitOperands(),
317 computeConstruct.getWaitOperandsSegmentsAttr(),
318 computeConstruct.getWaitOperandsDeviceTypeAttr(),
319 computeConstruct.getHasWaitDevnumAttr(),
320 computeConstruct.getWaitOnlyAttr());
321 Block &block = kernelEnvironment.getRegion().emplaceBlock();
323 return kernelEnvironment;
326template KernelEnvironmentOp
327KernelEnvironmentOp::createAndPopulate<ParallelOp>(ParallelOp,
OpBuilder &);
328template KernelEnvironmentOp
329KernelEnvironmentOp::createAndPopulate<KernelsOp>(KernelsOp,
OpBuilder &);
330template KernelEnvironmentOp
331KernelEnvironmentOp::createAndPopulate<SerialOp>(SerialOp,
OpBuilder &);
337LogicalResult FirstprivateMapInitialOp::verify() {
339 return emitError(
"data clause associated with firstprivate operation must "
342 return emitError(
"must have var operand");
343 if (!mlir::isa<mlir::acc::PointerLikeType>(
getVar().
getType()) &&
345 return emitError(
"var must be mappable or pointer-like");
346 if (mlir::isa<mlir::acc::PointerLikeType>(
getVar().
getType()) &&
348 return emitError(
"varType must capture the element type of var");
349 if (getModifiers() != acc::DataClauseModifier::none)
350 return emitError(
"no data clause modifiers are allowed");
354void FirstprivateMapInitialOp::getEffects(
367void ReductionInitOp::getSuccessorRegions(
373void ReductionInitOp::getRegionInvocationBounds(
376 invocationBounds.emplace_back(1, 1);
383LogicalResult ReductionInitOp::verify() {
385 if (
auto yieldOp = dyn_cast<acc::YieldOp>(block.
getTerminator())) {
386 if (yieldOp.getNumOperands() != 1)
388 "region must yield exactly one value (private storage)");
390 return emitOpError(
"yielded value type must match var type");
399void ReductionCombineRegionOp::getSuccessorRegions(
405void ReductionCombineRegionOp::getRegionInvocationBounds(
408 invocationBounds.emplace_back(1, 1);
412ReductionCombineRegionOp::getSuccessorInputs(
RegionSuccessor successor) {
416LogicalResult ReductionCombineRegionOp::verify() {
418 if (
auto yieldOp = dyn_cast<acc::YieldOp>(block.
getTerminator())) {
419 if (yieldOp.getNumOperands() != 0)
420 return emitOpError(
"region must be terminated by acc.yield with no "
430void ReductionCombineOp::getEffects(
446 GPUParallelDimAttr parDim) {
447 for (
auto launchArg : op.getLaunchArgs()) {
448 auto parOp = launchArg.getDefiningOp<ParWidthOp>();
451 auto launchArgDim = cast<GPUParallelDimAttr>(parOp.getParDim());
452 if (launchArgDim == parDim)
458std::optional<Value> ComputeRegionOp::getLaunchArg(GPUParallelDimAttr parDim) {
460 return parWidthOp.getResult();
465ComputeRegionOp::getKnownLaunchArg(GPUParallelDimAttr parDim) {
467 if (parWidthOp.getLaunchArg())
468 return parWidthOp.getLaunchArg();
472std::optional<uint64_t>
473ComputeRegionOp::getKnownConstantLaunchArg(GPUParallelDimAttr parDim) {
474 auto knownParWidth = getKnownLaunchArg(parDim);
475 if (knownParWidth.has_value())
481 getInputArgsMutable().append(value);
482 return getBody()->addArgument(value.
getType(), getLoc());
485std::optional<BlockArgument>
486ComputeRegionOp::wireHoistedValueThroughIns(
Value value) {
487 Region ®ion = getRegion();
489 auto useIsInRegion = [&](
OpOperand &use) ->
bool {
490 return region.
isAncestor(use.getOwner()->getParentRegion());
494 !llvm::any_of(value.
getUses(), useIsInRegion))
502bool ComputeRegionOp::isEffectivelySerial() {
505 if (getLaunchArg(GPUParallelDimAttr::seqDim(ctx)))
508 auto checkDim = [&](GPUParallelDimAttr dim) ->
bool {
509 auto val = getKnownConstantLaunchArg(dim);
510 return val && *val == 1;
513 return checkDim(GPUParallelDimAttr::threadXDim(ctx)) &&
514 checkDim(GPUParallelDimAttr::threadYDim(ctx)) &&
515 checkDim(GPUParallelDimAttr::threadZDim(ctx)) &&
516 checkDim(GPUParallelDimAttr::blockXDim(ctx)) &&
517 checkDim(GPUParallelDimAttr::blockYDim(ctx)) &&
518 checkDim(GPUParallelDimAttr::blockZDim(ctx));
521BlockArgument ComputeRegionOp::parDimToWidth(GPUParallelDimAttr parDim) {
522 for (
auto [pos, launchArg] : llvm::enumerate(getLaunchArgs())) {
523 auto parOp = launchArg.getDefiningOp<ParWidthOp>();
525 auto launchArgDim = cast<GPUParallelDimAttr>(parOp.getParDim());
526 if (launchArgDim == parDim) {
527 assert(pos < getRegion().front().getNumArguments() &&
528 "launch arg position out of range");
529 return getRegion().front().getArgument(pos);
532 llvm_unreachable(
"attempting to get unspecified parDim");
537 for (
auto launchArg : getLaunchArgs()) {
538 auto parOp = launchArg.getDefiningOp<ParWidthOp>();
539 auto launchArgDim = cast<GPUParallelDimAttr>(parOp.getParDim());
540 int64_t dimInt = launchArgDim.getValue().getInt();
541 parDims.push_back(intToParDim(
getContext(), dimInt));
547 Block *body = getBody();
551 unsigned numLaunchArgs = getLaunchArgs().size();
552 unsigned numInputArgs = getInputArgs().size();
553 if (argNumber >= numLaunchArgs + numInputArgs)
555 if (argNumber < numLaunchArgs)
556 return getLaunchArgs()[argNumber];
557 return getInputArgs()[argNumber - numLaunchArgs];
560std::optional<BlockArgument> ComputeRegionOp::getBlockArg(
Value value) {
561 Block *body = getBody();
562 for (
auto [idx, launchVal] : llvm::enumerate(getLaunchArgs())) {
563 if (launchVal == value)
566 unsigned numLaunch = getLaunchArgs().size();
567 for (
auto [idx, inputVal] : llvm::enumerate(getInputArgs())) {
568 if (inputVal == value)
576 results.
add<ComputeRegionRemoveDuplicateArgs, ComputeRegionRemoveUnusedArgs>(
580BlockArgument ComputeRegionOp::gpuParWidth(gpu::Processor processor) {
581 return parDimToWidth(GPUParallelDimAttr::get(
getContext(), processor));
584LogicalResult ComputeRegionOp::verify() {
585 for (
auto op : getLaunchArgs())
586 if (!op.getDefiningOp<acc::ParWidthOp>())
588 "launch arguments must be results of acc.par_width operations");
590 unsigned expectedBlockArgs = getLaunchArgs().size() + getInputArgs().size();
591 unsigned actualBlockArgs = getRegion().front().getNumArguments();
592 if (expectedBlockArgs != actualBlockArgs)
594 << expectedBlockArgs <<
" block arguments (launch + input), got "
601 ValueRange regionArgs = getBody()->getArguments();
605 assert(regionArgs.size() == (launchArgs.size() + inputArgs.size()) &&
606 "region args mismatch");
609 p <<
" stream(" << getStream() <<
" : " << getStream().getType() <<
")";
612 if (!launchArgs.empty()) {
614 for (
size_t j = 0;
j < launchArgs.size(); ++
j, ++i) {
615 p << regionArgs[i] <<
" = " << launchArgs[
j];
616 if (
j < launchArgs.size() - 1)
621 if (!inputArgs.empty()) {
623 for (
size_t j = 0;
j < inputArgs.size(); ++
j, ++i) {
624 p << regionArgs[i] <<
" = " << inputArgs[
j];
625 if (
j < inputArgs.size() - 1)
629 for (
size_t j = 0;
j < inputArgs.size(); ++
j) {
630 p << inputArgs[
j].getType();
631 if (
j < inputArgs.size() - 1)
640 getOperandSegmentSizeAttr());
643ParseResult ComputeRegionOp::parse(
OpAsmParser &parser,
654 bool hasStream =
false;
667 for (
size_t i = 0; i < regionArgs.size(); ++i)
668 types.push_back(indexType);
681 for (
auto [iterArg, type] : llvm::zip_equal(regionArgs, types))
688 const size_t numLaunchOperands = launchOperands.size();
689 const size_t numInputOperands = inputOperands.size();
690 assert(numLaunchOperands + numInputOperands == regionArgs.size() &&
691 "compute region args mismatch");
694 ComputeRegionOp::getOperandSegmentSizeAttr(),
696 static_cast<int32_t>(numInputOperands),
697 hasStream ? 1 : 0}));
699 for (
size_t i = 0; i < numLaunchOperands; ++i) {
704 for (
size_t i = numLaunchOperands; i < regionArgs.size(); ++i) {
705 if (parser.
resolveOperand(inputOperands[i - numLaunchOperands], types[i],
725GPUParallelDimAttr GPUParallelDimAttr::get(
MLIRContext *context,
726 gpu::Processor proc) {
727 return processorParDim(context, proc);
730GPUParallelDimAttr GPUParallelDimAttr::seqDim(
MLIRContext *context) {
731 return processorParDim(context, gpu::Processor::Sequential);
734GPUParallelDimAttr GPUParallelDimAttr::threadXDim(
MLIRContext *context) {
735 return processorParDim(context, gpu::Processor::ThreadX);
738GPUParallelDimAttr GPUParallelDimAttr::threadYDim(
MLIRContext *context) {
739 return processorParDim(context, gpu::Processor::ThreadY);
742GPUParallelDimAttr GPUParallelDimAttr::threadZDim(
MLIRContext *context) {
743 return processorParDim(context, gpu::Processor::ThreadZ);
746GPUParallelDimAttr GPUParallelDimAttr::blockXDim(
MLIRContext *context) {
747 return processorParDim(context, gpu::Processor::BlockX);
750GPUParallelDimAttr GPUParallelDimAttr::blockYDim(
MLIRContext *context) {
751 return processorParDim(context, gpu::Processor::BlockY);
754GPUParallelDimAttr GPUParallelDimAttr::blockZDim(
MLIRContext *context) {
755 return processorParDim(context, gpu::Processor::BlockZ);
759 GPUParallelDimAttr dim;
760 if (parser.
parseLess() || parseProcessorValue(parser, dim) ||
763 "expected format `<` processor_name `>`");
769void GPUParallelDimAttr::print(
AsmPrinter &printer)
const {
771 printProcessorValue(printer, *
this);
775GPUParallelDimAttr GPUParallelDimAttr::threadDim(
MLIRContext *context,
777 assert(
index <= 2 &&
"thread dimension index must be 0, 1, or 2");
780 return threadXDim(context);
782 return threadYDim(context);
784 return threadZDim(context);
786 llvm_unreachable(
"validated thread dimension index");
789GPUParallelDimAttr GPUParallelDimAttr::blockDim(
MLIRContext *context,
791 assert(
index <= 2 &&
"block dimension index must be 0, 1, or 2");
794 return blockXDim(context);
796 return blockYDim(context);
798 return blockZDim(context);
800 llvm_unreachable(
"validated block dimension index");
803gpu::Processor GPUParallelDimAttr::getProcessor()
const {
804 return indexToGpuProcessor(getValue().getInt());
807int GPUParallelDimAttr::getOrder()
const {
808 return gpuProcessorIndex(getProcessor());
811GPUParallelDimAttr GPUParallelDimAttr::getOneHigher()
const {
812 int order = getOrder();
818GPUParallelDimAttr GPUParallelDimAttr::getOneLower()
const {
819 int order = getOrder();
825bool GPUParallelDimAttr::isSeq()
const {
826 return getProcessor() == gpu::Processor::Sequential;
828bool GPUParallelDimAttr::isThreadX()
const {
829 return getProcessor() == gpu::Processor::ThreadX;
831bool GPUParallelDimAttr::isThreadY()
const {
832 return getProcessor() == gpu::Processor::ThreadY;
834bool GPUParallelDimAttr::isThreadZ()
const {
835 return getProcessor() == gpu::Processor::ThreadZ;
837bool GPUParallelDimAttr::isBlockX()
const {
838 return getProcessor() == gpu::Processor::BlockX;
840bool GPUParallelDimAttr::isBlockY()
const {
841 return getProcessor() == gpu::Processor::BlockY;
843bool GPUParallelDimAttr::isBlockZ()
const {
844 return getProcessor() == gpu::Processor::BlockZ;
846bool GPUParallelDimAttr::isAnyThread()
const {
847 return isThreadX() || isThreadY() || isThreadZ();
849bool GPUParallelDimAttr::isAnyBlock()
const {
850 return isBlockX() || isBlockY() || isBlockZ();
857GPUParallelDimsAttr GPUParallelDimsAttr::seq(
MLIRContext *ctx) {
858 return GPUParallelDimsAttr::get(ctx, {GPUParallelDimAttr::seqDim(ctx)});
861bool GPUParallelDimsAttr::isSeq()
const {
862 assert(!getArray().empty() &&
"no par_dims found");
863 if (getArray().size() == 1) {
864 auto parDim = dyn_cast<GPUParallelDimAttr>(getArray()[0]);
865 assert(parDim &&
"expected GPUParallelDimAttr");
866 return parDim.isSeq();
871bool GPUParallelDimsAttr::isParallel()
const {
return !isSeq(); }
873bool GPUParallelDimsAttr::isMultiDim()
const {
return getArray().size() > 1; }
875bool GPUParallelDimsAttr::hasAnyBlockLevel()
const {
877 getArray(), [](
const GPUParallelDimAttr &p) {
return p.isAnyBlock(); });
880bool GPUParallelDimsAttr::hasOnlyBlockLevel()
const {
881 return !getArray().empty() &&
882 llvm::all_of(getArray(), [](
const GPUParallelDimAttr &p) {
883 return p.isAnyBlock();
887bool GPUParallelDimsAttr::hasOnlyThreadYLevel()
const {
888 return !getArray().empty() &&
889 llvm::all_of(getArray(), [](
const GPUParallelDimAttr &p) {
890 return p.isThreadY();
894bool GPUParallelDimsAttr::hasOnlyThreadXLevel()
const {
895 return !getArray().empty() &&
896 llvm::all_of(getArray(), [](
const GPUParallelDimAttr &p) {
897 return p.isThreadX();
904 auto parseParDim = [&]() -> ParseResult {
905 GPUParallelDimAttr dim;
906 if (parseProcessorValue(parser, dim))
908 parDims.push_back(dim);
912 "list of OpenACC GPU parallel dimensions"))
914 return GPUParallelDimsAttr::get(parser.
getContext(), parDims);
917void GPUParallelDimsAttr::print(
AsmPrinter &printer)
const {
919 llvm::interleaveComma(getArray(), printer,
920 [&printer](
const GPUParallelDimAttr &p) {
921 printProcessorValue(printer, p);
p<< " : "<< getMemRefType()<< ", "<< getType();}static LogicalResult verifyVectorMemoryOp(Operation *op, MemRefType memrefType, VectorType vectorType) { if(memrefType.getElementType() !=vectorType.getElementType()) return op-> emitOpError("requires memref and vector types of the same elemental type")
Given a list of lists of parsed operands, populates uniqueOperands with unique operands.
static void addOperandEffect(SmallVectorImpl< SideEffects::EffectInstance< MemoryEffects::Effect > > &effects, MutableOperandRange operand)
Helper to add an effect on an operand, referenced by its mutable range.
static void addResultEffect(SmallVectorImpl< SideEffects::EffectInstance< MemoryEffects::Effect > > &effects, Value result)
Helper to add an effect on a result value.
static void getSingleRegionOpSuccessorRegions(Operation *op, Region ®ion, RegionBranchPoint point, SmallVectorImpl< RegionSuccessor > ®ions)
Generic helper for single-region OpenACC ops that execute their body once and then return to the pare...
static ValueRange getSingleRegionSuccessorInputs(Operation *op, RegionSuccessor successor)
static ParWidthOp getParWidthOpForLaunchArg(ComputeRegionOp op, GPUParallelDimAttr parDim)
This base class exposes generic asm parser hooks, usable across the various derived parsers.
@ Square
Square brackets surrounding zero or more operands.
virtual Builder & getBuilder() const =0
Return a builder which provides useful access to MLIRContext, global objects like types and attribute...
virtual ParseResult parseCommaSeparatedList(Delimiter delimiter, function_ref< ParseResult()> parseElementFn, StringRef contextMessage=StringRef())=0
Parse a list of comma-separated items with an optional delimiter.
virtual ParseResult parseOptionalAttrDict(NamedAttrList &result)=0
Parse a named dictionary into 'result' if it is present.
virtual ParseResult parseOptionalKeyword(StringRef keyword)=0
Parse the given keyword if present.
MLIRContext * getContext() const
virtual ParseResult parseRParen()=0
Parse a ) token.
virtual InFlightDiagnostic emitError(SMLoc loc, const Twine &message={})=0
Emit a diagnostic at the specified location and return failure.
ParseResult parseKeywordOrString(std::string *result)
Parse a keyword or a quoted string.
virtual ParseResult parseLess()=0
Parse a '<' token.
virtual SMLoc getCurrentLocation()=0
Get the location of the next token and store it into the argument.
virtual ParseResult parseColon()=0
Parse a : token.
virtual ParseResult parseGreater()=0
Parse a '>' token.
virtual ParseResult parseLParen()=0
Parse a ( token.
virtual ParseResult parseType(Type &result)=0
Parse a type.
virtual ParseResult parseOptionalArrowTypeList(SmallVectorImpl< Type > &result)=0
Parse an optional arrow followed by a type list.
ParseResult parseTypeList(SmallVectorImpl< Type > &result)
Parse a type list.
This base class exposes generic asm printer hooks, usable across the various derived printers.
void printOptionalArrowTypeList(TypeRange &&types)
Print an optional arrow followed by a type list.
Attributes are known-constant values of operations.
This class represents an argument of a Block.
unsigned getArgNumber() const
Returns the number of this argument.
Block * getOwner() const
Returns the block that owns this argument.
Block represents an ordered list of Operations.
BlockArgument getArgument(unsigned i)
unsigned getNumArguments()
Operation * getTerminator()
Get the terminator operation of this block.
void eraseArgument(unsigned index)
Erase the argument at 'index' and remove it from the argument list.
DenseI32ArrayAttr getDenseI32ArrayAttr(ArrayRef< int32_t > values)
MLIRContext is the top-level object for a collection of MLIR operations.
This class provides a mutable adaptor for a range of operands.
unsigned size() const
Returns the current size of the range.
The OpAsmParser has methods for interacting with the asm parser: parsing things from it,...
virtual ParseResult parseRegion(Region ®ion, ArrayRef< Argument > arguments={}, bool enableNameShadowing=false)=0
Parses a region.
ParseResult parseAssignmentList(SmallVectorImpl< Argument > &lhs, SmallVectorImpl< UnresolvedOperand > &rhs)
Parse a list of assignments of the form (x1 = y1, x2 = y2, ...)
virtual ParseResult resolveOperand(const UnresolvedOperand &operand, Type type, SmallVectorImpl< Value > &result)=0
Resolve an operand to an SSA value, emitting an error on failure.
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.
This is a pure-virtual base class that exposes the asmprinter hooks necessary to implement a custom p...
virtual void printOptionalAttrDict(ArrayRef< NamedAttribute > attrs, ArrayRef< StringRef > elidedAttrs={})=0
If the specified operation has attributes, print out an attribute dictionary with their values.
virtual void printRegion(Region &blocks, bool printEntryBlockArgs=true, bool printBlockTerminators=true, bool printEmptyBlock=false)=0
Prints a region.
This class helps build Operations.
void setInsertionPointToStart(Block *block)
Sets the insertion point to the start of the specified block.
This class represents an operand of an operation.
Operation is the basic unit of execution within MLIR.
result_range getResults()
A special type of RewriterBase that coordinates the application of a rewrite pattern on the current I...
This class represents a point being branched from in the methods of the RegionBranchOpInterface.
bool isParent() const
Returns true if branching from the parent op.
This class represents a successor of a region.
static RegionSuccessor parent()
Initialize a successor that branches after/out of the parent operation.
bool isParent() const
Return true if the successor is the parent operation.
This class contains a list of basic blocks and a link to the parent operation it is attached to.
bool isAncestor(Region *other)
Return true if this region is ancestor of the other region.
RewritePatternSet & add(ConstructorArg &&arg, ConstructorArgs &&...args)
Add an instance of each of the pattern types 'Ts' to the pattern list with the given arguments.
virtual void eraseOp(Operation *op)
This method erases an operation that is known to have no uses.
virtual void replaceAllUsesWith(Value from, Value to)
Find uses of from and replace them with to.
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 represents a specific instance of an effect.
static DerivedEffect * get()
static CurrentDeviceIdResource * get()
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...
bool use_empty() const
Returns true if this value has no uses.
Type getType() const
Return the type of this value.
use_range getUses() const
Returns a range of all uses, which is useful for iterating over all uses.
mlir::Value getAccVar(mlir::Operation *accDataClauseOp)
Used to obtain the accVar from a data clause operation.
mlir::Value getVar(mlir::Operation *accDataClauseOp)
Used to obtain the var from a data clause operation.
std::optional< mlir::acc::DataClause > getDataClause(mlir::Operation *accDataEntryOp)
Used to obtain the dataClause from a data entry operation.
mlir::Type getVarType(mlir::Operation *accDataClauseOp)
Used to obtains the varType from a data clause operation which records the type of variable.
Include the generated interface declarations.
void replaceAllUsesInRegionWith(Value orig, Value replacement, Region ®ion)
Replace all uses of orig within the given region with replacement.
std::optional< int64_t > getConstantIntValue(OpFoldResult ofr)
If ofr is a constant integer or an IntegerAttr, return the integer.
Type getType(OpFoldResult ofr)
Returns the int type of the integer in ofr.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
bool areValuesDefinedAbove(Range values, Region &limit)
Check if all values in the provided range are defined above the limit region.
This is the representation of an operand reference.
OpRewritePattern is a wrapper around RewritePattern that allows for matching and rewriting against an...
OpRewritePattern(MLIRContext *context, PatternBenefit benefit=1, ArrayRef< StringRef > generatedNames={})
Patterns must specify the root operation name they match against, and can also specify the benefit of...
This represents an operation in an abstracted form, suitable for use with the builder APIs.
Eliminates variable at the specified position using Fourier-Motzkin variable elimination.