blob: 49dae69c350176b58e3af81e5bd69d5e652d1e06 [file] [log] [blame]
// IREE low-level sequencer op definitions.
// These map 1:1 with the bytecode, accept only MemRef types and generally use
// output parameters instead of return types.
//
// The source of truth for bytecode opcodes is:
// iree/schemas/bytecode/sequencer_bytecode_v0.h
//
// Note that in this dialect we cannot use folders: they require that all
// operands are possible to make constants where we use output arguments that
// will never be constant. Instead we can use canonicalization patterns to
// match constant input operands and do the folding by replacing output operands
// with the new values.
#ifdef IREE_SEQUENCER_LL_OPS
#else
#define IREE_SEQUENCER_LL_OPS
#ifdef IREE_OP_BASE
#else
include "third_party/mlir_edge/iree/compiler/IR/OpBase.td"
#endif // IREE_OP_BASE
def IREESeqLL_Dialect : Dialect {
let name = "iree_ll_seq";
let cppNamespace = "IREESeq::LL";
}
//===----------------------------------------------------------------------===//
// Base op classes
//===----------------------------------------------------------------------===//
class IREESeqLL_Op<string mnemonic, list<OpTrait> traits = []> :
Op<IREESeqLL_Dialect, mnemonic, traits> {
bit hasCustomSerializer = 0;
}
class IREESeqLL_PureOp<string mnemonic, list<OpTrait> traits = []> :
IREESeqLL_Op<mnemonic, !listconcat(traits, [NoSideEffect])>;
class IREESeqLL_UnaryOp<string mnemonic, Type type = IREELL_MemRef,
list<OpTrait> traits = []> : IREESeqLL_Op<mnemonic, traits> {
let arguments = (ins type:$input, type:$dst);
}
class IREESeqLL_BinaryOp<string mnemonic, Type type = IREELL_MemRef,
list<OpTrait> traits = []> : IREESeqLL_Op<mnemonic, traits> {
let arguments = (ins type:$lhs, type:$rhs, type:$dst);
}
class IREESeqLL_TernaryOp<string mnemonic, Type type = IREELL_MemRef,
list<OpTrait> traits = []>
: IREESeqLL_Op<mnemonic, traits> {
let arguments = (ins type : $a, type : $b, type : $c, type : $dst);
}
//===----------------------------------------------------------------------===//
// Low-level sequencer ops
//===----------------------------------------------------------------------===//
def IREESeqLL_ConstantOp : IREESeqLL_PureOp<"constant"> {
let arguments = (ins ElementsAttr:$value);
let results = (outs IREELL_MemRef);
// TODO(b/132296600): make tablegen follow the style guide.
let extraClassDeclaration = [{
Attribute getValue() { return value(); }
}];
let hasFolder = 1;
}
def IREESeqLL_CallOp : IREESeqLL_Op<"call"> {
let arguments = (ins SymbolRefAttr:$callee, Variadic<IREELL_MemRef>);
let results = (outs Variadic<IREELL_MemRef>);
let builders = [OpBuilder<
"Builder *builder, OperationState *result, FuncOp callee,"
"ArrayRef<Value *> operands = {}", [{
result->addOperands(operands);
result->addAttribute("callee", builder->getSymbolRefAttr(callee));
result->addTypes(callee.getType().getResults());
}]>, OpBuilder<
"Builder *builder, OperationState *result, StringRef callee,"
"ArrayRef<Type> results, ArrayRef<Value *> operands = {}", [{
result->addOperands(operands);
result->addAttribute("callee", builder->getSymbolRefAttr(callee));
result->addTypes(results);
}]>];
let extraClassDeclaration = [{
// TODO(b/132296600): make tablegen follow the style guide.
StringRef getCallee() { return callee(); }
FunctionType getCalleeType();
// TODO(b/133879130): make tablegen support variadic operand accessors.
/// Get the argument operands to the called function.
operand_range getArgOperands() {
return {arg_operand_begin(), arg_operand_end()};
}
operand_iterator arg_operand_begin() { return operand_begin(); }
operand_iterator arg_operand_end() { return operand_end(); }
}];
let parser = [{ return parse$cppClass(parser, result); }];
let printer = [{ return print$cppClass(p, *this); }];
}
// TODO(benvanik): add verifier that target isExternal.
def IREESeqLL_CallImportOp : IREESeqLL_Op<"call_import"> {
let arguments = (ins SymbolRefAttr:$callee, Variadic<IREELL_MemRef>);
let results = (outs Variadic<IREELL_MemRef>);
let builders = [OpBuilder<
"Builder *builder, OperationState *result, FuncOp callee,"
"ArrayRef<Value *> operands = {}", [{
result->addOperands(operands);
result->addAttribute("callee", builder->getSymbolRefAttr(callee));
result->addTypes(callee.getType().getResults());
}]>, OpBuilder<
"Builder *builder, OperationState *result, StringRef callee,"
"ArrayRef<Type> results, ArrayRef<Value *> operands = {}", [{
result->addOperands(operands);
result->addAttribute("callee", builder->getSymbolRefAttr(callee));
result->addTypes(results);
}]>];
let extraClassDeclaration = [{
// TODO(b/132296600): make tablegen follow the style guide.
StringRef getCallee() { return callee(); }
FunctionType getCalleeType();
// TODO(b/133879130): make tablegen support variadic operand accessors.
/// Get the argument operands to the called function.
operand_range getArgOperands() {
return {arg_operand_begin(), arg_operand_end()};
}
operand_iterator arg_operand_begin() { return operand_begin(); }
operand_iterator arg_operand_end() { return operand_end(); }
}];
let parser = [{ return parse$cppClass(parser, result); }];
let printer = [{ return print$cppClass(p, *this); }];
}
def IREESeqLL_CallIndirectOp : IREESeqLL_Op<"call_indirect"> {
let arguments = (ins FunctionType:$callee, Variadic<IREELL_MemRef>:$operands);
let results = (outs Variadic<IREELL_MemRef>);
let builders = [OpBuilder<
"Builder *, OperationState *result, Value *callee,"
"ArrayRef<Value *> operands = {}", [{
result->operands.push_back(callee);
result->addOperands(operands);
result->addTypes(callee->getType().cast<FunctionType>().getResults());
}]>];
let extraClassDeclaration = [{
Value *getCallee() { return getOperand(0); }
/// Get the argument operands to the called function.
operand_range getArgOperands() {
return {arg_operand_begin(), arg_operand_end()};
}
operand_iterator arg_operand_begin() { return ++operand_begin(); }
operand_iterator arg_operand_end() { return operand_end(); }
}];
let parser = [{ return parse$cppClass(parser, result); }];
let printer = [{ return print$cppClass(p, *this); }];
}
def IREESeqLL_ReturnOp : IREESeqLL_Op<"return", [Terminator]> {
let arguments = (ins Variadic<IREELL_MemRef>:$operands);
let builders = [OpBuilder<
"Builder *b, OperationState *result", [{ build(b, result, llvm::None); }]
>];
let parser = [{ return parse$cppClass(parser, result); }];
let printer = [{ return print$cppClass(p, *this); }];
}
def IREESeqLL_BranchOp : IREESeqLL_Op<"br", [Terminator]> {
let arguments = (ins Variadic<IREELL_MemRef>:$operands);
let skipDefaultBuilders = 1;
let builders = [OpBuilder<
"Builder *, OperationState *result, Block *dest, "
"ArrayRef<Value *> operands = {}", [{
result->addSuccessor(dest, operands);
}]>];
let extraClassDeclaration = [{
Block *getDest();
void setDest(Block *block);
/// Erase the operand at 'index' from the operand list.
void eraseOperand(unsigned index);
}];
let parser = [{ return parse$cppClass(parser, result); }];
let printer = [{ return print$cppClass(p, *this); }];
}
def IREESeqLL_CondBranchOp : IREESeqLL_Op<"cond_br", [Terminator]> {
let arguments = (ins
IREELL_BoolScalar:$condition,
Variadic<IREELL_MemRef>:$branchOperands
);
let skipDefaultBuilders = 1;
let builders = [OpBuilder<
"Builder *, OperationState *result, Value *condition,"
"Block *trueDest, ArrayRef<Value *> trueOperands,"
"Block *falseDest, ArrayRef<Value *> falseOperands", [{
result->addOperands(condition);
result->addSuccessor(trueDest, trueOperands);
result->addSuccessor(falseDest, falseOperands);
}]>];
let extraClassDeclaration = [{
// These are the indices into the dests list.
enum { trueIndex = 0, falseIndex = 1 };
// The condition operand is the first operand in the list.
Value *getCondition() { return getOperand(0); }
/// Return the destination if the condition is true.
Block *getTrueDest() {
return getOperation()->getSuccessor(trueIndex);
}
/// Return the destination if the condition is false.
Block *getFalseDest() {
return getOperation()->getSuccessor(falseIndex);
}
// Accessors for operands to the 'true' destination.
Value *getTrueOperand(unsigned idx) {
assert(idx < getNumTrueOperands());
return getOperand(getTrueDestOperandIndex() + idx);
}
void setTrueOperand(unsigned idx, Value *value) {
assert(idx < getNumTrueOperands());
setOperand(getTrueDestOperandIndex() + idx, value);
}
operand_iterator true_operand_begin() {
return operand_begin() + getTrueDestOperandIndex();
}
operand_iterator true_operand_end() {
return true_operand_begin() + getNumTrueOperands();
}
operand_range getTrueOperands() {
return {true_operand_begin(), true_operand_end()};
}
unsigned getNumTrueOperands() {
return getOperation()->getNumSuccessorOperands(trueIndex);
}
/// Erase the operand at 'index' from the true operand list.
void eraseTrueOperand(unsigned index) {
getOperation()->eraseSuccessorOperand(trueIndex, index);
}
// Accessors for operands to the 'false' destination.
Value *getFalseOperand(unsigned idx) {
assert(idx < getNumFalseOperands());
return getOperand(getFalseDestOperandIndex() + idx);
}
void setFalseOperand(unsigned idx, Value *value) {
assert(idx < getNumFalseOperands());
setOperand(getFalseDestOperandIndex() + idx, value);
}
operand_iterator false_operand_begin() { return true_operand_end(); }
operand_iterator false_operand_end() {
return false_operand_begin() + getNumFalseOperands();
}
operand_range getFalseOperands() {
return {false_operand_begin(), false_operand_end()};
}
unsigned getNumFalseOperands() {
return getOperation()->getNumSuccessorOperands(falseIndex);
}
/// Erase the operand at 'index' from the false operand list.
void eraseFalseOperand(unsigned index) {
getOperation()->eraseSuccessorOperand(falseIndex, index);
}
private:
/// Get the index of the first true destination operand.
unsigned getTrueDestOperandIndex() { return 1; }
/// Get the index of the first false destination operand.
unsigned getFalseDestOperandIndex() {
return getTrueDestOperandIndex() + getNumTrueOperands();
}
}];
let parser = [{ return parse$cppClass(parser, result); }];
let printer = [{ return print$cppClass(p, *this); }];
}
def IREESeqLL_DynamicDispatchOp : IREESeqLL_Op<"dynamic_dispatch"> {
let arguments = (ins
SymbolRefAttr:$executable,
SymbolRefAttr:$entry_point,
IREELL_IntMemRef:$workload,
Variadic<IREELL_MemRef>:$operands
);
let results = (outs Variadic<IREELL_MemRef>);
let builders = [OpBuilder<
"Builder *builder, OperationState *result, StringRef executable,"
"StringRef entry_point, Value *workload,"
"ArrayRef<Type> results, ArrayRef<Value *> operands = {}", [{
result->addOperands({workload});
result->addOperands(operands);
result->addAttribute("executable", builder->getSymbolRefAttr(executable));
result->addAttribute("entry_point", builder->getSymbolRefAttr(entry_point));
result->addTypes(results);
}]>];
let extraClassDeclaration = [{
// TODO(b/132296600): make tablegen follow the style guide.
StringRef getExecutable() { return executable(); }
StringRef getEntryPoint() { return entry_point(); }
FunctionType getEntryPointType();
Value *getWorkload() { return getOperand(0); }
// TODO(b/133879130): make tablegen support variadic operand accessors.
operand_range getArgOperands() {
return {arg_operand_begin(), arg_operand_end()};
}
operand_iterator arg_operand_begin() { return operand_begin() + 1; }
operand_iterator arg_operand_end() { return operand_end(); }
operand_type_range getArgOperandTypes() {
return {arg_operand_type_begin(), arg_operand_type_end()};
}
operand_type_iterator arg_operand_type_begin() {
return operand_type_iterator(arg_operand_begin());
}
operand_type_iterator arg_operand_type_end() {
return operand_type_iterator(arg_operand_end());
}
}];
let parser = [{ return parse$cppClass(parser, result); }];
let printer = [{ return print$cppClass(p, *this); }];
let verifier = [{ return verify$cppClass(*this); }];
let hasCanonicalizer = 1;
}
def IREESeqLL_StaticDispatchOp : IREESeqLL_Op<"static_dispatch"> {
let arguments = (ins
SymbolRefAttr:$executable,
SymbolRefAttr:$entry_point,
I32ElementsAttr:$workload,
Variadic<IREELL_MemRef>:$operands
);
let results = (outs Variadic<IREELL_MemRef>);
let builders = [OpBuilder<
"Builder *builder, OperationState *result, StringRef executable,"
"StringRef entry_point, ElementsAttr workload,"
"ArrayRef<Type> results, ArrayRef<Value *> operands = {}", [{
result->addAttribute("workload", workload);
result->addOperands(operands);
result->addAttribute("executable", builder->getSymbolRefAttr(executable));
result->addAttribute("entry_point", builder->getSymbolRefAttr(entry_point));
result->addTypes(results);
}]>];
let extraClassDeclaration = [{
// TODO(b/132296600): make tablegen follow the style guide.
StringRef getExecutable() { return executable(); }
StringRef getEntryPoint() { return entry_point(); }
FunctionType getEntryPointType();
ElementsAttr getWorkload() { return workload(); }
// TODO(b/133879130): make tablegen support variadic operand accessors.
operand_range getArgOperands() {
return {arg_operand_begin(), arg_operand_end()};
}
operand_iterator arg_operand_begin() { return operand_begin(); }
operand_iterator arg_operand_end() { return operand_end(); }
operand_type_range getArgOperandTypes() {
return {arg_operand_type_begin(), arg_operand_type_end()};
}
operand_type_iterator arg_operand_type_begin() {
return operand_type_iterator(arg_operand_begin());
}
operand_type_iterator arg_operand_type_end() {
return operand_type_iterator(arg_operand_end());
}
}];
let parser = [{ return parse$cppClass(parser, result); }];
let printer = [{ return print$cppClass(p, *this); }];
let verifier = [{ return verify$cppClass(*this); }];
}
def IREESeqLL_AllocStaticOp : IREESeqLL_PureOp<"alloc_static"> {
// TODO(benvanik): attributes and args.
let results = (outs IREELL_MemRef);
}
def IREESeqLL_AllocStackOp : IREESeqLL_PureOp<"alloc_stack"> {
// TODO(benvanik): attributes and args.
let arguments = (ins Variadic<IREELL_IntMemRef>:$dim_pieces);
let results = (outs IREELL_MemRef);
}
def IREESeqLL_AllocStackInitOp : IREESeqLL_PureOp<"alloc_stack_init"> {
// TODO(benvanik): attributes and args.
let arguments = (ins Variadic<IREELL_IntMemRef>:$dim_pieces);
let results = (outs IREELL_MemRef);
}
def IREESeqLL_AllocHeapOp : IREESeqLL_PureOp<"alloc_heap"> {
// TODO(benvanik): attributes and args.
let arguments = (ins Variadic<IREELL_IntMemRef>:$dim_pieces);
let results = (outs IREELL_MemRef);
}
def IREESeqLL_DiscardOp : IREESeqLL_Op<"discard"> {
let arguments = (ins IREELL_MemRef);
}
def IREESeqLL_ShapeOp : IREESeqLL_Op<"shape"> {
let arguments = (ins IREELL_MemRef:$input, IREELL_I32MemRef:$dst);
let hasCanonicalizer = 1;
}
def IREESeqLL_LengthOp : IREESeqLL_Op<"length"> {
let arguments = (ins IREELL_MemRef:$input, IREELL_I32Scalar:$dst);
let hasCanonicalizer = 1;
}
def IREESeqLL_ComputeOffsetOp : IREESeqLL_Op<"compute_offset"> {
let arguments = (ins
IREELL_1DIntMemRef:$shape,
I8Attr:$elementSize,
IREELL_1DIntMemRef:$indices,
IREELL_I32Scalar:$dst
);
let hasCanonicalizer = 1;
}
def IREESeqLL_ComputeRangeOp : IREESeqLL_Op<"compute_range"> {
let arguments = (ins
IREELL_1DIntMemRef:$shape,
I8Attr:$elementSize,
IREELL_1DIntMemRef:$indices,
IREELL_1DIntMemRef:$lengths,
IREELL_I32Scalar:$dstOffset,
IREELL_I32Scalar:$dstLength
);
let hasCanonicalizer = 1;
}
def IREESeqLL_DynamicSliceOp : IREESeqLL_PureOp<"dynamic_slice", [
AllElementTypesMatch<["src", "result"]>
]> {
let arguments = (ins
IREELL_MemRef:$src,
IREELL_IntScalar:$offset,
IREELL_IntScalar:$length
);
let results = (outs IREELL_MemRef:$result);
}
def IREESeqLL_StaticSliceOp : IREESeqLL_PureOp<"static_slice", [
AllElementTypesMatch<["src", "result"]>
]> {
let arguments = (ins
IREELL_MemRef:$src,
I64Attr:$offset,
I64Attr:$length
);
let results = (outs IREELL_MemRef:$result);
}
def IREESeqLL_DynamicCopyOp : IREESeqLL_Op<"dynamic_copy"> {
let arguments = (ins
IREELL_MemRef:$src,
IREELL_IndexScalar:$srcOffset,
IREELL_MemRef:$dst,
IREELL_IndexScalar:$dstOffset,
IREELL_IndexScalar:$length
);
let hasCanonicalizer = 1;
}
def IREESeqLL_StaticCopyOp : IREESeqLL_Op<"static_copy"> {
let arguments = (ins
IREELL_MemRef:$src,
I64Attr:$srcOffset,
IREELL_MemRef:$dst,
I64Attr:$dstOffset,
I64Attr:$length
);
}
def IREESeqLL_DynamicFillOp : IREESeqLL_Op<"dynamic_fill"> {
let arguments = (ins
IREELL_I32Scalar:$value,
IREELL_MemRef:$dst,
IREELL_IndexScalar:$dstOffset,
IREELL_IndexScalar:$length
);
let hasCanonicalizer = 1;
}
def IREESeqLL_StaticFillOp : IREESeqLL_Op<"static_fill"> {
let arguments = (ins
I32Attr:$value,
IREELL_MemRef:$dst,
I64Attr:$dstOffset,
I64Attr:$length
);
}
def IREESeqLL_CloneOp :
IREESeqLL_PureOp<"clone", [SameOperandsAndResultType]> {
let arguments = (ins IREELL_MemRef:$src);
let results = (outs IREELL_MemRef);
}
def IREESeqLL_AssignOp :
IREESeqLL_Op<"assign", [SameOperandsAndResultType]> {
let arguments = (ins IREELL_MemRef:$src);
let results = (outs IREELL_MemRef);
}
def IREESeqLL_CondAssignOp : IREESeqLL_Op<"cond_assign"> {
let arguments = (ins
IREELL_BoolScalar:$cond,
IREELL_MemRef:$lhs,
IREELL_MemRef:$rhs
);
let results = (outs IREELL_MemRef);
}
def IREESeqLL_ReshapeOp : IREESeqLL_Op<"reshape"> {
let arguments = (ins IREELL_MemRef:$input, IREELL_1DIntMemRef:$shape);
let results = (outs IREELL_MemRef);
}
def IREESeqLL_TraceOp : IREESeqLL_Op<"trace"> {
let arguments = (ins Variadic<IREELL_MemRef>:$srcs);
}
def IREESeqLL_CondBreakOp : IREESeqLL_Op<"cond_break"> {
let arguments = (ins IREELL_BoolScalar:$cond);
}
def IREESeqLL_BreakOp : IREESeqLL_Op<"break">;
#endif // IREE_SEQUENCER_LL_OPS