2019-11-12 10:31:56 +08:00
|
|
|
//===--------------------- krnl_ops.cpp - MLIR Operations -----------------===//
|
|
|
|
//
|
|
|
|
// Copyright 2019 The IBM Research Authors.
|
|
|
|
//
|
|
|
|
// =============================================================================
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include <iostream>
|
|
|
|
#include <queue>
|
|
|
|
|
2019-11-28 11:56:34 +08:00
|
|
|
#include "mlir/Dialect/AffineOps/AffineOps.h"
|
|
|
|
#include "mlir/Dialect/StandardOps/Ops.h"
|
2019-11-12 10:31:56 +08:00
|
|
|
#include "mlir/IR/Block.h"
|
|
|
|
#include "mlir/IR/Builders.h"
|
|
|
|
#include "mlir/IR/Function.h"
|
|
|
|
#include "mlir/IR/IntegerSet.h"
|
|
|
|
#include "mlir/IR/Matchers.h"
|
|
|
|
#include "mlir/IR/Module.h"
|
|
|
|
#include "mlir/IR/OpImplementation.h"
|
|
|
|
#include "mlir/IR/Operation.h"
|
|
|
|
#include "mlir/IR/PatternMatch.h"
|
|
|
|
#include "mlir/Transforms/DialectConversion.h"
|
2019-12-20 02:27:15 +08:00
|
|
|
#include "llvm/ADT/SetVector.h"
|
|
|
|
#include "llvm/ADT/SmallBitVector.h"
|
2019-11-12 10:31:56 +08:00
|
|
|
|
2019-12-23 13:13:52 +08:00
|
|
|
#include "krnl_helper.hpp"
|
2019-11-28 11:56:34 +08:00
|
|
|
|
2019-11-12 10:31:56 +08:00
|
|
|
#include "krnl_ops.hpp"
|
|
|
|
|
|
|
|
using namespace mlir;
|
|
|
|
|
|
|
|
namespace mlir {
|
2019-12-20 02:27:15 +08:00
|
|
|
KrnlOpsDialect::KrnlOpsDialect(MLIRContext *context)
|
2019-11-12 10:31:56 +08:00
|
|
|
: Dialect(getDialectNamespace(), context) {
|
|
|
|
addOperations<
|
|
|
|
#define GET_OP_LIST
|
2019-12-23 13:13:52 +08:00
|
|
|
#include "src/krnl.cpp.inc"
|
2019-11-12 10:31:56 +08:00
|
|
|
>();
|
|
|
|
addTypes<LoopType>();
|
|
|
|
}
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// KrnlDefineLoopsOp
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2019-12-20 02:27:15 +08:00
|
|
|
void KrnlDefineLoopsOp::build(Builder *builder, OperationState &result,
|
|
|
|
int64_t num_loops) {
|
2019-11-12 10:31:56 +08:00
|
|
|
// Create the same number of dimension handlers as the number of
|
|
|
|
// dimensions in the associated integer set.
|
|
|
|
result.types.append(num_loops, LoopType::get(builder->getContext()));
|
2019-12-20 02:27:15 +08:00
|
|
|
result.addAttribute(getNumLoopsAttrName(),
|
|
|
|
builder->getI32IntegerAttr(num_loops));
|
2019-11-12 10:31:56 +08:00
|
|
|
}
|
|
|
|
|
2019-12-20 02:27:15 +08:00
|
|
|
void print(OpAsmPrinter &p, KrnlDefineLoopsOp &op) {
|
2019-11-28 11:56:34 +08:00
|
|
|
auto numLoopAttr =
|
|
|
|
op.getAttrOfType<IntegerAttr>(KrnlDefineLoopsOp::getNumLoopsAttrName());
|
|
|
|
p << "krnl.define_loops " << numLoopAttr.getValue().getSExtValue();
|
2019-11-12 10:31:56 +08:00
|
|
|
}
|
|
|
|
|
2019-12-20 02:27:15 +08:00
|
|
|
ParseResult parseKrnlDefineLoopsOp(OpAsmParser &parser,
|
|
|
|
OperationState &result) {
|
2019-11-12 10:31:56 +08:00
|
|
|
// Parse the attribute indicating number of loops defined.
|
2019-11-28 11:56:34 +08:00
|
|
|
IntegerAttr numLoops;
|
2019-12-20 02:27:15 +08:00
|
|
|
auto &builder = parser.getBuilder();
|
2019-11-28 11:56:34 +08:00
|
|
|
auto intType = builder.getIntegerType(64);
|
|
|
|
if (parser.parseAttribute(numLoops, intType,
|
2019-12-20 02:27:15 +08:00
|
|
|
KrnlDefineLoopsOp::getNumLoopsAttrName(),
|
|
|
|
result.attributes))
|
2019-11-12 10:31:56 +08:00
|
|
|
return failure();
|
|
|
|
|
2019-11-28 11:56:34 +08:00
|
|
|
auto loopTypes = llvm::SmallVector<Type, 4>(
|
|
|
|
numLoops.getValue().getSExtValue(), LoopType::get(builder.getContext()));
|
|
|
|
if (parser.addTypesToList(loopTypes, result.types))
|
2019-11-12 10:31:56 +08:00
|
|
|
return failure();
|
|
|
|
}
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// KrnlOptimizeLoopsOp
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2019-12-20 02:27:15 +08:00
|
|
|
void KrnlOptimizeLoopsOp::build(Builder *builder, OperationState &result,
|
|
|
|
int num_optimized_loops) {
|
|
|
|
result.types.append(num_optimized_loops,
|
|
|
|
LoopType::get(builder->getContext()));
|
2019-11-12 10:31:56 +08:00
|
|
|
// Create a region and a block for the body.
|
|
|
|
// Schedule intrinsics will be placed into this region.
|
2019-12-20 02:27:15 +08:00
|
|
|
Region *region = result.addRegion();
|
|
|
|
auto *body = new Block();
|
2019-11-12 10:31:56 +08:00
|
|
|
region->push_back(body);
|
|
|
|
}
|
|
|
|
|
2019-12-20 02:27:15 +08:00
|
|
|
void print(OpAsmPrinter &p, KrnlOptimizeLoopsOp &op) {
|
2019-11-12 10:31:56 +08:00
|
|
|
p << "krnl.optimize_loops ";
|
|
|
|
p.printRegion(op.region(), /*printEntryBlockArgs=*/false,
|
2019-12-20 02:27:15 +08:00
|
|
|
/*printBlockTerminators=*/true);
|
2019-11-12 10:31:56 +08:00
|
|
|
p << " : ";
|
|
|
|
p.printFunctionalType(op);
|
|
|
|
}
|
|
|
|
|
2019-12-20 02:27:15 +08:00
|
|
|
ParseResult parseKrnlOptimizeLoopsOp(OpAsmParser &parser,
|
|
|
|
OperationState &result) {
|
2019-11-12 10:31:56 +08:00
|
|
|
// Parse the schedule body region.
|
2019-12-20 02:27:15 +08:00
|
|
|
Region *region = result.addRegion();
|
2019-11-12 10:31:56 +08:00
|
|
|
if (parser.parseRegion(*region, llvm::None, llvm::None))
|
|
|
|
return failure();
|
|
|
|
|
|
|
|
// Parse the function type for the schedule operation.
|
|
|
|
// Then following the hint of this parsed function type, parse the
|
|
|
|
// returned timestamp space dimension handlers.
|
|
|
|
FunctionType schedule_func_type;
|
|
|
|
if (parser.parseColonType(schedule_func_type) ||
|
|
|
|
parser.addTypesToList(schedule_func_type.getResults(), result.types)) {
|
|
|
|
failure();
|
|
|
|
}
|
|
|
|
|
|
|
|
return success();
|
|
|
|
}
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// KrnlIterateOp
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* Build a Krnl Dialect iterate operation.
|
|
|
|
* input_loops: a collection of input krnl.loops being optimized.
|
|
|
|
* optimized_loops: a collection of optimized (scheduled) krnl.loops.
|
|
|
|
* operand_bounds: a collection of SSA value bounds.
|
|
|
|
* const_bounds: a collection of constant bounds.
|
|
|
|
* bound_types: a collection of integer values indicating how bounds are given.
|
|
|
|
* 0 : bound is given as an integer in const_bounds.
|
|
|
|
* 1 : bound is given as an operand in operand_bounds.
|
|
|
|
* 2 : bound is given as an affine map. (TODO).
|
|
|
|
*
|
|
|
|
* The following example illustrates how induction variable bounds are parsed
|
|
|
|
* from builder function inputs:
|
|
|
|
*
|
|
|
|
* - operand_bounds = [N, M]
|
|
|
|
* - const_bounds = [10, 20]
|
|
|
|
* - bound_types = [0, 1, 1, 0]
|
|
|
|
*
|
|
|
|
* Then the bounds will be parsed as:
|
|
|
|
* %i0 = 10 to N : %i1 = M to 20
|
|
|
|
*/
|
2019-12-20 02:27:15 +08:00
|
|
|
void KrnlIterateOp::build(Builder *builder, OperationState &result,
|
|
|
|
KrnlIterateOperandPack operandPack) {
|
2019-11-12 10:31:56 +08:00
|
|
|
// Record optimized loops and the number of such loops.
|
2019-11-28 11:56:34 +08:00
|
|
|
result.addOperands(operandPack.getOperands());
|
2019-12-20 02:27:15 +08:00
|
|
|
result.addAttribute(KrnlIterateOp::getBoundsAttrName(),
|
|
|
|
operandPack.getAttributes());
|
2019-11-12 10:31:56 +08:00
|
|
|
|
2019-12-20 02:27:15 +08:00
|
|
|
result.addAttribute(
|
|
|
|
getNumOptimizedLoopsAttrName(),
|
2019-11-28 11:56:34 +08:00
|
|
|
builder->getI64IntegerAttr(operandPack.getNumOptimizedLoops()));
|
2019-11-12 10:31:56 +08:00
|
|
|
|
2019-11-27 02:55:44 +08:00
|
|
|
// Create a region and a block for the body. The arguments of the region are
|
2019-11-12 10:31:56 +08:00
|
|
|
// the loop induction variables; there can be multiple induction variables
|
|
|
|
// associated with the same krnl.iterate operation.
|
2019-12-20 02:27:15 +08:00
|
|
|
Region *bodyRegion = result.addRegion();
|
|
|
|
auto *body = new Block();
|
2019-11-12 10:31:56 +08:00
|
|
|
auto body_args = llvm::SmallVector<Type, 4>(
|
2019-11-28 11:56:34 +08:00
|
|
|
operandPack.getNumInputLoops(), IndexType::get(builder->getContext()));
|
2019-11-12 10:31:56 +08:00
|
|
|
body->addArguments(body_args);
|
|
|
|
bodyRegion->push_back(body);
|
|
|
|
|
|
|
|
ensureTerminator(*bodyRegion, *builder, result.location);
|
|
|
|
}
|
|
|
|
|
2019-12-20 02:27:15 +08:00
|
|
|
void print(OpAsmPrinter &p, KrnlIterateOp &op) {
|
2019-11-12 10:31:56 +08:00
|
|
|
p << "krnl.iterate(";
|
|
|
|
// Print optimized loops:
|
2019-11-28 11:56:34 +08:00
|
|
|
auto numOptimizedLoops = op.getNumOptimizedLoops();
|
|
|
|
p.printOperands(op.operand_begin(), op.operand_begin() + numOptimizedLoops);
|
2019-11-12 10:31:56 +08:00
|
|
|
p << ") with (";
|
|
|
|
|
2019-11-28 11:56:34 +08:00
|
|
|
auto inductionVars = op.bodyRegion().begin()->getArguments();
|
|
|
|
auto boundItr =
|
|
|
|
op.getAttrOfType<ArrayAttr>(KrnlIterateOp::getBoundsAttrName())
|
|
|
|
.getValue()
|
|
|
|
.begin();
|
|
|
|
auto operandItr = op.operand_begin() + numOptimizedLoops;
|
|
|
|
|
|
|
|
std::string delimiter;
|
2019-12-20 02:27:15 +08:00
|
|
|
for (auto &var : inductionVars) {
|
2019-11-28 11:56:34 +08:00
|
|
|
p << delimiter;
|
|
|
|
p.printOperand(*operandItr++);
|
2019-11-12 10:31:56 +08:00
|
|
|
p << " -> ";
|
2019-11-28 11:56:34 +08:00
|
|
|
p.printOperand(var);
|
2019-11-12 10:31:56 +08:00
|
|
|
p << " = ";
|
2019-11-28 11:56:34 +08:00
|
|
|
onnf::printBound((*boundItr++).cast<AffineMapAttr>(), operandItr, "max", p);
|
2019-11-12 10:31:56 +08:00
|
|
|
p << " to ";
|
2019-11-28 11:56:34 +08:00
|
|
|
onnf::printBound((*boundItr++).cast<AffineMapAttr>(), operandItr, "min", p);
|
|
|
|
delimiter = ", ";
|
2019-11-12 10:31:56 +08:00
|
|
|
}
|
|
|
|
|
2019-11-28 11:56:34 +08:00
|
|
|
p << ")";
|
2019-11-12 10:31:56 +08:00
|
|
|
p.printRegion(op.bodyRegion(), /*printEntryBlockArgs=*/false,
|
2019-12-20 02:27:15 +08:00
|
|
|
/*printBlockTerminators=*/false);
|
2019-11-12 10:31:56 +08:00
|
|
|
}
|
|
|
|
|
2019-12-20 02:27:15 +08:00
|
|
|
ParseResult parseKrnlIterateOp(OpAsmParser &parser, OperationState &result) {
|
2019-11-12 10:31:56 +08:00
|
|
|
auto builder = parser.getBuilder();
|
|
|
|
auto context = builder.getContext();
|
2019-11-28 11:56:34 +08:00
|
|
|
onnf::KrnlDialectOperandParser operandParser(parser);
|
2019-11-12 10:31:56 +08:00
|
|
|
|
|
|
|
// Parse optimized loops:
|
2019-11-28 11:56:34 +08:00
|
|
|
SmallVector<OpAsmParser::OperandType, 4> optimizedLoopRefs;
|
2019-12-20 02:27:15 +08:00
|
|
|
if (parser.parseOperandList(optimizedLoopRefs,
|
|
|
|
OpAsmParser::Delimiter::Paren) ||
|
2019-11-28 11:56:34 +08:00
|
|
|
parser.resolveOperands(optimizedLoopRefs,
|
2019-12-20 02:27:15 +08:00
|
|
|
LoopType::get(result.getContext()),
|
|
|
|
result.operands))
|
2019-11-12 10:31:56 +08:00
|
|
|
return failure();
|
|
|
|
|
|
|
|
// Record how many optimized loops did we parse.
|
|
|
|
result.addAttribute(KrnlIterateOp::getNumOptimizedLoopsAttrName(),
|
2019-12-20 02:27:15 +08:00
|
|
|
builder.getI64IntegerAttr(optimizedLoopRefs.size()));
|
2019-11-12 10:31:56 +08:00
|
|
|
|
|
|
|
// Parse input loops and their lower and upper bounds.
|
2019-11-28 11:56:34 +08:00
|
|
|
SmallVector<OpAsmParser::OperandType, 4> inductionVarRefs;
|
|
|
|
SmallVector<Attribute, 4> boundMaps;
|
2019-11-12 10:31:56 +08:00
|
|
|
|
|
|
|
if (parser.parseKeyword("with") || parser.parseLParen())
|
|
|
|
return failure();
|
|
|
|
|
|
|
|
// A function to parse a lower or upper bound.
|
2019-12-20 02:27:15 +08:00
|
|
|
auto parseBound = [&result, &builder, &parser, &operandParser,
|
|
|
|
&boundMaps](bool isUpper) -> ParseResult {
|
2019-11-28 11:56:34 +08:00
|
|
|
// 'min' / 'max' prefixes are generally syntactic sugar, but are required if
|
|
|
|
// the map has multiple results.
|
|
|
|
bool failedToParsedMinMax =
|
|
|
|
failed(parser.parseOptionalKeyword(isUpper ? "min" : "max"));
|
|
|
|
|
2019-11-12 10:31:56 +08:00
|
|
|
// Try parse an SSA operand.
|
2019-12-20 02:27:15 +08:00
|
|
|
if (succeeded(operandParser.ParseOptionalOperand(builder.getIndexType(),
|
|
|
|
result.operands))) {
|
2019-11-28 11:56:34 +08:00
|
|
|
AffineMap map = builder.getSymbolIdentityMap();
|
|
|
|
boundMaps.emplace_back(AffineMapAttr::get(map));
|
|
|
|
return success();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Bound is not an SSA id, then it must be an integer.
|
|
|
|
// Parse an integer constant attribute.
|
|
|
|
// Get the attribute location.
|
|
|
|
llvm::SMLoc attrLoc = parser.getCurrentLocation();
|
|
|
|
Attribute boundAttr;
|
|
|
|
llvm::SmallVector<NamedAttribute, 1> tempBoundAttrContainer;
|
2019-12-20 02:27:15 +08:00
|
|
|
if (parser.parseAttribute(boundAttr, builder.getIndexType(), "temp",
|
|
|
|
tempBoundAttrContainer))
|
2019-11-28 11:56:34 +08:00
|
|
|
return failure();
|
|
|
|
|
|
|
|
if (auto affineMapAttr = boundAttr.dyn_cast<AffineMapAttr>()) {
|
|
|
|
unsigned currentNumOperands = result.operands.size();
|
|
|
|
unsigned numDims = 0;
|
|
|
|
if (parseDimAndSymbolList(parser, result.operands, numDims))
|
2019-11-12 10:31:56 +08:00
|
|
|
return failure();
|
|
|
|
|
2019-11-28 11:56:34 +08:00
|
|
|
auto map = affineMapAttr.getValue();
|
|
|
|
if (map.getNumDims() != numDims)
|
2019-12-20 02:27:15 +08:00
|
|
|
return parser.emitError(
|
|
|
|
parser.getNameLoc(),
|
2019-11-28 11:56:34 +08:00
|
|
|
"dim operand count and integer set dim count must match");
|
|
|
|
|
|
|
|
unsigned numDimAndSymbolOperands =
|
|
|
|
result.operands.size() - currentNumOperands;
|
|
|
|
if (numDims + map.getNumSymbols() != numDimAndSymbolOperands)
|
2019-12-20 02:27:15 +08:00
|
|
|
return parser.emitError(
|
|
|
|
parser.getNameLoc(),
|
2019-11-28 11:56:34 +08:00
|
|
|
"symbol operand count and integer set symbol count must match");
|
|
|
|
|
|
|
|
// If the map has multiple results, make sure that we parsed the min/max
|
|
|
|
// prefix.
|
|
|
|
if (map.getNumResults() > 1 && failedToParsedMinMax) {
|
|
|
|
if (isUpper)
|
|
|
|
return parser.emitError(attrLoc,
|
2019-12-20 02:27:15 +08:00
|
|
|
"upper loop bound affine map with multiple "
|
|
|
|
"results requires 'min' prefix");
|
2019-11-28 11:56:34 +08:00
|
|
|
return parser.emitError(attrLoc,
|
2019-12-20 02:27:15 +08:00
|
|
|
"lower loop bound affine mapwith "
|
|
|
|
"multiple results requires 'max' prefix");
|
2019-11-28 11:56:34 +08:00
|
|
|
}
|
|
|
|
boundMaps.emplace_back(AffineMapAttr::get(map));
|
|
|
|
return success();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (auto integerAttr = boundAttr.dyn_cast<IntegerAttr>()) {
|
|
|
|
AffineMap map =
|
|
|
|
builder.getConstantAffineMap(integerAttr.getValue().getSExtValue());
|
|
|
|
boundMaps.emplace_back(AffineMapAttr::get(map));
|
2019-11-12 10:31:56 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-12-20 02:27:15 +08:00
|
|
|
bool keepParsing; // Do we keep parsing loops/bounds?
|
2019-11-12 10:31:56 +08:00
|
|
|
do {
|
|
|
|
// Parse an input loop operand;
|
2019-11-28 11:56:34 +08:00
|
|
|
operandParser.ParseOperand(LoopType::get(context), result.operands);
|
2019-11-12 10:31:56 +08:00
|
|
|
parser.parseArrow();
|
|
|
|
|
|
|
|
// Parse induction variable.
|
2019-11-28 11:56:34 +08:00
|
|
|
OpAsmParser::OperandType inductionVar;
|
|
|
|
if (parser.parseRegionArgument(inductionVar) || parser.parseEqual())
|
2019-11-12 10:31:56 +08:00
|
|
|
return failure();
|
2019-11-28 11:56:34 +08:00
|
|
|
inductionVarRefs.emplace_back(inductionVar);
|
2019-11-12 10:31:56 +08:00
|
|
|
|
|
|
|
// Parse bound par (min to max).
|
2019-11-28 11:56:34 +08:00
|
|
|
if (parseBound(/*isUpper=*/false) || parser.parseKeyword("to") ||
|
|
|
|
parseBound(/*isUpper=*/true))
|
2019-11-12 10:31:56 +08:00
|
|
|
return failure();
|
|
|
|
|
|
|
|
// We may fail to parse a comma if an operand bound is followed by
|
|
|
|
// a comma and the next input loop operand, in which case
|
|
|
|
// the entire "{operand bound}, {input_loop_operand}" sequence will
|
|
|
|
// be parsed as an operand list.
|
|
|
|
parser.parseOptionalComma();
|
|
|
|
|
|
|
|
// If we don't see a RParen token, we keep parsing.
|
2019-11-28 11:56:34 +08:00
|
|
|
keepParsing = failed(parser.parseOptionalRParen());
|
|
|
|
} while (keepParsing);
|
2019-11-12 10:31:56 +08:00
|
|
|
|
|
|
|
// At this point, there shouldn't be any operands left to parse.
|
2019-11-28 11:56:34 +08:00
|
|
|
if (operandParser.hasOperandLeft())
|
2019-11-12 10:31:56 +08:00
|
|
|
return parser.emitError(parser.getCurrentLocation());
|
2019-12-20 02:27:15 +08:00
|
|
|
result.addAttribute(KrnlIterateOp::getBoundsAttrName(),
|
|
|
|
builder.getArrayAttr(boundMaps));
|
2019-11-12 10:31:56 +08:00
|
|
|
|
2019-12-20 02:27:15 +08:00
|
|
|
Region *region = result.addRegion();
|
|
|
|
SmallVector<Type, 4> inductionVarTypes(inductionVarRefs.size(),
|
|
|
|
builder.getIndexType());
|
2019-11-28 11:56:34 +08:00
|
|
|
if (parser.parseRegion(*region, inductionVarRefs, inductionVarTypes))
|
2019-11-12 10:31:56 +08:00
|
|
|
return failure();
|
|
|
|
|
|
|
|
// Ensure iterate region is closed off with krnl.terminate.
|
2019-12-20 02:27:15 +08:00
|
|
|
KrnlIterateOp::ensureTerminator(*region, parser.getBuilder(),
|
|
|
|
result.location);
|
2019-11-12 10:31:56 +08:00
|
|
|
|
|
|
|
return success();
|
|
|
|
}
|
|
|
|
|
|
|
|
static LogicalResult verify(KrnlIterateOp op) {
|
|
|
|
// TODO: Verify number of induction variable bounds matches the number of
|
|
|
|
// input loops.
|
|
|
|
}
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// KrnlReturnLoopsOp
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2019-12-20 02:27:15 +08:00
|
|
|
void print(OpAsmPrinter &p, KrnlReturnLoopsOp &op) {
|
2019-11-12 10:31:56 +08:00
|
|
|
p << "krnl.return_loops ";
|
|
|
|
p.printOperands(op.operand_begin(), op.operand_end());
|
|
|
|
}
|
|
|
|
|
2019-12-20 02:27:15 +08:00
|
|
|
ParseResult parseKrnlReturnLoopsOp(OpAsmParser &parser,
|
|
|
|
OperationState &result) {
|
2019-11-12 10:31:56 +08:00
|
|
|
// Parse the loops to return.
|
|
|
|
SmallVector<OpAsmParser::OperandType, 4> timestamp_dim_handlers;
|
|
|
|
if (parser.parseOperandList(timestamp_dim_handlers) ||
|
|
|
|
parser.resolveOperands(timestamp_dim_handlers,
|
2019-12-20 02:27:15 +08:00
|
|
|
LoopType::get(result.getContext()),
|
|
|
|
result.operands))
|
2019-11-12 10:31:56 +08:00
|
|
|
return failure();
|
|
|
|
|
|
|
|
return success();
|
|
|
|
}
|
|
|
|
|
2019-12-22 13:25:02 +08:00
|
|
|
void KrnlEntryPointOp::build(mlir::Builder *builder, OperationState &state,
|
|
|
|
SymbolRefAttr funcAttr, IntegerAttr numInputs,
|
|
|
|
IntegerAttr numOutputs) {
|
|
|
|
state.addAttribute(KrnlEntryPointOp::getEntryPointFuncAttrName(), funcAttr);
|
|
|
|
state.addAttribute(KrnlEntryPointOp::getNumInputsAttrName(), numInputs);
|
|
|
|
state.addAttribute(KrnlEntryPointOp::getNumOutputsAttrName(), numOutputs);
|
|
|
|
}
|
|
|
|
|
2019-11-12 10:31:56 +08:00
|
|
|
#define GET_OP_CLASSES
|
2019-12-23 13:13:52 +08:00
|
|
|
#include "src/krnl.cpp.inc"
|
2019-12-20 02:27:15 +08:00
|
|
|
} // namespace mlir
|