648 lines
19 KiB
TableGen
648 lines
19 KiB
TableGen
//===- IndexOps.td - Index operation definitions -----------*- tablegen -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef INDEX_OPS
|
|
#define INDEX_OPS
|
|
|
|
include "mlir/Dialect/Index/IR/IndexDialect.td"
|
|
include "mlir/Dialect/Index/IR/IndexEnums.td"
|
|
include "mlir/Interfaces/CastInterfaces.td"
|
|
include "mlir/Interfaces/InferIntRangeInterface.td"
|
|
include "mlir/Interfaces/InferTypeOpInterface.td"
|
|
include "mlir/Interfaces/SideEffectInterfaces.td"
|
|
include "mlir/IR/OpAsmInterface.td"
|
|
include "mlir/IR/OpBase.td"
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// IndexOp
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// Base class for Index dialect operations.
|
|
class IndexOp<string mnemonic, list<Trait> traits = []>
|
|
: Op<IndexDialect, mnemonic,
|
|
[DeclareOpInterfaceMethods<InferIntRangeInterface, ["inferResultRanges"]>] # traits>;
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// IndexBinaryOp
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// Base class for binary Index dialect operations.
|
|
class IndexBinaryOp<string mnemonic, list<Trait> traits = []>
|
|
: IndexOp<mnemonic, traits> {
|
|
let arguments = (ins Index:$lhs, Index:$rhs);
|
|
let results = (outs Index:$result);
|
|
let assemblyFormat = "$lhs `,` $rhs attr-dict";
|
|
let hasFolder = 1;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// AddOp
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
def Index_AddOp : IndexBinaryOp<"add", [Commutative, Pure]> {
|
|
let summary = "index addition";
|
|
let description = [{
|
|
The `index.add` operation takes two index values and computes their sum.
|
|
|
|
Example:
|
|
|
|
```mlir
|
|
// c = a + b
|
|
%c = index.add %a, %b
|
|
```
|
|
}];
|
|
|
|
let hasCanonicalizeMethod = 1;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// SubOp
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
def Index_SubOp : IndexBinaryOp<"sub", [Pure]> {
|
|
let summary = "index subtraction";
|
|
let description = [{
|
|
The `index.sub` operation takes two index values and computes the difference
|
|
of the first from the second operand.
|
|
|
|
Example:
|
|
|
|
```mlir
|
|
// c = a - b
|
|
%c = index.sub %a, %b
|
|
```
|
|
}];
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// MulOp
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
def Index_MulOp : IndexBinaryOp<"mul", [Commutative, Pure]> {
|
|
let summary = "index multiplication";
|
|
let description = [{
|
|
The `index.mul` operation takes two index values and computes their product.
|
|
|
|
Example:
|
|
|
|
```mlir
|
|
// c = a * b
|
|
%c = index.mul %a, %b
|
|
```
|
|
}];
|
|
|
|
let hasCanonicalizeMethod = 1;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// DivSOp
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
def Index_DivSOp : IndexBinaryOp<"divs", [NoMemoryEffect]> {
|
|
let summary = "index signed division";
|
|
let description = [{
|
|
The `index.divs` operation takes two index values and computes their signed
|
|
quotient. Treats the leading bit as the sign and rounds towards zero, i.e.
|
|
`6 / -2 = -3`.
|
|
|
|
Note: division by zero and signed division overflow are undefined behaviour.
|
|
|
|
Example:
|
|
|
|
```mlir
|
|
// c = a / b
|
|
%c = index.divs %a, %b
|
|
```
|
|
}];
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// DivUOp
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
def Index_DivUOp : IndexBinaryOp<"divu", [NoMemoryEffect]> {
|
|
let summary = "index unsigned division";
|
|
let description = [{
|
|
The `index.divu` operation takes two index values and computes their
|
|
unsigned quotient. Treats the leading bit as the most significant and rounds
|
|
towards zero, i.e. `6 / -2 = 0`.
|
|
|
|
Note: division by zero is undefined behaviour.
|
|
|
|
Example:
|
|
|
|
```mlir
|
|
// c = a / b
|
|
%c = index.divu %a, %b
|
|
```
|
|
}];
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// CeilDivSOp
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
def Index_CeilDivSOp : IndexBinaryOp<"ceildivs", [NoMemoryEffect]> {
|
|
let summary = "index signed ceil division";
|
|
let description = [{
|
|
The `index.ceildivs` operation takes two index values and computes their
|
|
signed quotient. Treats the leading bit as the sign and rounds towards
|
|
positive infinity, i.e. `7 / -2 = -3`.
|
|
|
|
Note: division by zero and signed division overflow are undefined behaviour.
|
|
|
|
Example:
|
|
|
|
```mlir
|
|
// c = ceil(a / b)
|
|
%c = index.ceildivs %a, %b
|
|
```
|
|
}];
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// CeilDivUOp
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
def Index_CeilDivUOp : IndexBinaryOp<"ceildivu", [NoMemoryEffect]> {
|
|
let summary = "index unsigned ceil division";
|
|
let description = [{
|
|
The `index.ceildivu` operation takes two index values and computes their
|
|
unsigned quotient. Treats the leading bit as the most significant and rounds
|
|
towards positive infinity, i.e. `6 / -2 = 1`.
|
|
|
|
Note: division by zero is undefined behaviour.
|
|
|
|
Example:
|
|
|
|
```mlir
|
|
// c = ceil(a / b)
|
|
%c = index.ceildivu %a, %b
|
|
```
|
|
}];
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// FloorDivSOp
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
def Index_FloorDivSOp : IndexBinaryOp<"floordivs", [NoMemoryEffect]> {
|
|
let summary = "index signed floor division";
|
|
let description = [{
|
|
The `index.floordivs` operation takes two index values and computes their
|
|
signed quotient. Treats the leading bit as the sign and rounds towards
|
|
negative infinity, i.e. `5 / -2 = -3`.
|
|
|
|
Note: division by zero and signed division overflow are undefined behaviour.
|
|
|
|
Example:
|
|
|
|
```mlir
|
|
// c = floor(a / b)
|
|
%c = index.floordivs %a, %b
|
|
```
|
|
}];
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// RemSOp
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
def Index_RemSOp : IndexBinaryOp<"rems", [NoMemoryEffect]> {
|
|
let summary = "index signed remainder";
|
|
let description = [{
|
|
The `index.rems` operation takes two index values and computes their signed
|
|
remainder. Treats the leading bit as the sign, i.e. `6 % -2 = 0`.
|
|
|
|
Example:
|
|
|
|
```mlir
|
|
// c = a % b
|
|
%c = index.rems %a, %b
|
|
```
|
|
}];
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// RemUOp
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
def Index_RemUOp : IndexBinaryOp<"remu", [NoMemoryEffect]> {
|
|
let summary = "index unsigned remainder";
|
|
let description = [{
|
|
The `index.remu` operation takes two index values and computes their
|
|
unsigned remainder. Treats the leading bit as the most significant, i.e.
|
|
`6 % -2 = 6`.
|
|
|
|
Example:
|
|
|
|
```mlir
|
|
// c = a % b
|
|
%c = index.remu %a, %b
|
|
```
|
|
}];
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// MaxSOp
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
def Index_MaxSOp : IndexBinaryOp<"maxs", [Commutative, Pure]> {
|
|
let summary = "index signed maximum";
|
|
let description = [{
|
|
The `index.maxs` operation takes two index values and computes their signed
|
|
maximum value. Treats the leading bit as the sign, i.e. `max(-2, 6) = 6`.
|
|
|
|
Example:
|
|
|
|
```mlir
|
|
// c = max(a, b)
|
|
%c = index.maxs %a, %b
|
|
```
|
|
}];
|
|
|
|
let hasCanonicalizeMethod = 1;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// MaxUOp
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
def Index_MaxUOp : IndexBinaryOp<"maxu", [Commutative, Pure]> {
|
|
let summary = "index unsigned maximum";
|
|
let description = [{
|
|
The `index.maxu` operation takes two index values and computes their
|
|
unsigned maximum value. Treats the leading bit as the most significant, i.e.
|
|
`max(15, 6) = 15` or `max(-2, 6) = -2`.
|
|
|
|
Example:
|
|
|
|
```mlir
|
|
// c = max(a, b)
|
|
%c = index.maxu %a, %b
|
|
```
|
|
}];
|
|
|
|
let hasCanonicalizeMethod = 1;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// MinSOp
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
def Index_MinSOp : IndexBinaryOp<"mins", [Commutative, Pure]> {
|
|
let summary = "index signed minimum";
|
|
let description = [{
|
|
The `index.mins` operation takes two index values and computes their signed
|
|
minimum value. Treats the leading bit as the sign, i.e. `min(-2, 6) = -2`.
|
|
|
|
Example:
|
|
|
|
```mlir
|
|
// c = min(a, b)
|
|
%c = index.mins %a, %b
|
|
```
|
|
}];
|
|
|
|
let hasCanonicalizeMethod = 1;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// MinUOp
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
def Index_MinUOp : IndexBinaryOp<"minu", [Commutative, Pure]> {
|
|
let summary = "index unsigned minimum";
|
|
let description = [{
|
|
The `index.minu` operation takes two index values and computes their
|
|
unsigned minimum value. Treats the leading bit as the most significant, i.e.
|
|
`min(15, 6) = 6` or `min(-2, 6) = 6`.
|
|
|
|
Example:
|
|
|
|
```mlir
|
|
// c = min(a, b)
|
|
%c = index.minu %a, %b
|
|
```
|
|
}];
|
|
|
|
let hasCanonicalizeMethod = 1;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// ShlOp
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
def Index_ShlOp : IndexBinaryOp<"shl", [Pure]> {
|
|
let summary = "index shift left";
|
|
let description = [{
|
|
The `index.shl` operation shifts an index value to the left by a variable
|
|
amount. The low order bits are filled with zeroes. The RHS operand is always
|
|
treated as unsigned. If the RHS operand is equal to or greater than the
|
|
index bitwidth, the result is a poison value.
|
|
|
|
Example:
|
|
|
|
```mlir
|
|
// c = a << b
|
|
%c = index.shl %a, %b
|
|
```
|
|
}];
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// ShrSOp
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
def Index_ShrSOp : IndexBinaryOp<"shrs", [Pure]> {
|
|
let summary = "signed index shift right";
|
|
let description = [{
|
|
The `index.shrs` operation shifts an index value to the right by a variable
|
|
amount. The LHS operand is treated as signed. The high order bits are filled
|
|
with copies of the most significant bit. If the RHS operand is equal to or
|
|
greater than the index bitwidth, the result is a poison value.
|
|
|
|
Example:
|
|
|
|
```mlir
|
|
// c = a >> b
|
|
%c = index.shrs %a, %b
|
|
```
|
|
}];
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// ShrUOp
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
def Index_ShrUOp : IndexBinaryOp<"shru", [Pure]> {
|
|
let summary = "unsigned index shift right";
|
|
let description = [{
|
|
The `index.shru` operation shifts an index value to the right by a variable
|
|
amount. The LHS operand is treated as unsigned. The high order bits are
|
|
filled with zeroes. If the RHS operand is equal to or greater than the index
|
|
bitwidth, the result is a poison value.
|
|
|
|
Example:
|
|
|
|
```mlir
|
|
// c = a >> b
|
|
%c = index.shru %a, %b
|
|
```
|
|
}];
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// AndOp
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
def Index_AndOp : IndexBinaryOp<"and", [Commutative, Pure]> {
|
|
let summary = "index bitwise and";
|
|
let description = [{
|
|
The `index.and` operation takes two index values and computes their bitwise
|
|
and.
|
|
|
|
Example:
|
|
|
|
```mlir
|
|
// c = a & b
|
|
%c = index.and %a, %b
|
|
```
|
|
}];
|
|
|
|
let hasCanonicalizeMethod = 1;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// OrOp
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
def Index_OrOp : IndexBinaryOp<"or", [Commutative, Pure]> {
|
|
let summary = "index bitwise or";
|
|
let description = [{
|
|
The `index.or` operation takes two index values and computes their bitwise
|
|
or.
|
|
|
|
Example:
|
|
|
|
```mlir
|
|
// c = a | b
|
|
%c = index.or %a, %b
|
|
```
|
|
}];
|
|
|
|
let hasCanonicalizeMethod = 1;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// XorOp
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
def Index_XOrOp : IndexBinaryOp<"xor", [Commutative, Pure]> {
|
|
let summary = "index bitwise xor";
|
|
let description = [{
|
|
The `index.xor` operation takes two index values and computes their bitwise
|
|
xor.
|
|
|
|
Example:
|
|
|
|
```mlir
|
|
// c = a ^ b
|
|
%c = index.xor %a, %b
|
|
```
|
|
}];
|
|
|
|
let hasCanonicalizeMethod = 1;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// CastSOp
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
def Index_CastSOp : IndexOp<"casts", [Pure,
|
|
DeclareOpInterfaceMethods<CastOpInterface>]> {
|
|
let summary = "index signed cast";
|
|
let description = [{
|
|
The `index.casts` operation enables conversions between values of index type
|
|
and concrete fixed-width integer types. If casting to a wider integer, the
|
|
value is sign-extended. If casting to a narrower integer, the value is
|
|
truncated.
|
|
|
|
Example:
|
|
|
|
```mlir
|
|
// Cast to i32
|
|
%0 = index.casts %a : index to i32
|
|
|
|
// Cast from i64
|
|
%1 = index.casts %b : i64 to index
|
|
```
|
|
}];
|
|
|
|
let arguments = (ins AnyTypeOf<[AnyInteger, Index]>:$input);
|
|
let results = (outs AnyTypeOf<[AnyInteger, Index]>:$output);
|
|
let assemblyFormat = "$input attr-dict `:` type($input) `to` type($output)";
|
|
let hasFolder = 1;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// CastUOp
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
def Index_CastUOp : IndexOp<"castu", [Pure,
|
|
DeclareOpInterfaceMethods<CastOpInterface>]> {
|
|
let summary = "index unsigned cast";
|
|
let description = [{
|
|
The `index.castu` operation enables conversions between values of index type
|
|
and concrete fixed-width integer types. If casting to a wider integer, the
|
|
value is zero-extended. If casting to a narrower integer, the value is
|
|
truncated.
|
|
|
|
Example:
|
|
|
|
```mlir
|
|
// Cast to i32
|
|
%0 = index.castu %a : index to i32
|
|
|
|
// Cast from i64
|
|
%1 = index.castu %b : i64 to index
|
|
```
|
|
}];
|
|
|
|
let arguments = (ins AnyTypeOf<[AnyInteger, Index]>:$input);
|
|
let results = (outs AnyTypeOf<[AnyInteger, Index]>:$output);
|
|
let assemblyFormat = "$input attr-dict `:` type($input) `to` type($output)";
|
|
let hasFolder = 1;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// CmpOp
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
def Index_CmpOp : IndexOp<"cmp", [Pure]> {
|
|
let summary = "index compare";
|
|
let description = [{
|
|
The `index.cmp` operation takes two index values and compares them according
|
|
to the comparison predicate and returns an `i1`. The following comparisons
|
|
are supported:
|
|
|
|
- `eq`: equal
|
|
- `ne`: not equal
|
|
- `slt`: signed less than
|
|
- `sle`: signed less than or equal
|
|
- `sgt`: signed greater than
|
|
- `sge`: signed greater than or equal
|
|
- `ult`: unsigned less than
|
|
- `ule`: unsigned less than or equal
|
|
- `ugt`: unsigned greater than
|
|
- `uge`: unsigned greater than or equal
|
|
|
|
The result is `1` if the comparison is true and `0` otherwise.
|
|
|
|
Example:
|
|
|
|
```mlir
|
|
// Signed less than comparison.
|
|
%0 = index.cmp slt(%a, %b)
|
|
|
|
// Unsigned greater than or equal comparison.
|
|
%1 = index.cmp uge(%a, %b)
|
|
|
|
// Not equal comparison.
|
|
%2 = index.cmp ne(%a, %b)
|
|
```
|
|
}];
|
|
|
|
let arguments = (ins IndexCmpPredicateAttr:$pred, Index:$lhs, Index:$rhs);
|
|
let results = (outs I1:$result);
|
|
let assemblyFormat = "$pred `(` $lhs `,` $rhs `)` attr-dict";
|
|
let hasFolder = 1;
|
|
let hasCanonicalizeMethod = 1;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// SizeOfOp
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
def Index_SizeOfOp : IndexOp<"sizeof", [Pure]> {
|
|
let summary = "size in bits of the index type";
|
|
let description = [{
|
|
The `index.sizeof` operation produces an index-typed SSA value equal to the
|
|
size in bits of the `index` type. For example, on 32-bit systems, the result
|
|
is `32 : index`, and on 64-bit systems, the result is `64 : index`.
|
|
|
|
Example:
|
|
|
|
```mlir
|
|
%0 = index.sizeof
|
|
```
|
|
}];
|
|
|
|
let results = (outs Index:$result);
|
|
let assemblyFormat = "attr-dict";
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// ConstantOp
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
def Index_ConstantOp : IndexOp<"constant", [
|
|
ConstantLike, Pure,
|
|
DeclareOpInterfaceMethods<OpAsmOpInterface, ["getAsmResultNames"]>
|
|
]> {
|
|
let summary = "index constant";
|
|
let description = [{
|
|
The `index.constant` operation produces an index-typed SSA value equal to
|
|
some index-typed integer constant.
|
|
|
|
Example:
|
|
|
|
```mlir
|
|
%0 = index.constant 42
|
|
```
|
|
}];
|
|
|
|
let arguments = (ins IndexAttr:$value);
|
|
let results = (outs Index:$result);
|
|
let assemblyFormat = "attr-dict $value";
|
|
let hasFolder = 1;
|
|
|
|
let builders = [OpBuilder<(ins "int64_t":$value)>];
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// BoolConstantOp
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
def Index_BoolConstantOp : IndexOp<"bool.constant", [
|
|
ConstantLike, Pure,
|
|
DeclareOpInterfaceMethods<OpAsmOpInterface, ["getAsmResultNames"]>
|
|
]> {
|
|
let summary = "boolean constant";
|
|
let description = [{
|
|
The `index.bool.constant` operation produces an bool-typed SSA value equal
|
|
to either `true` or `false`.
|
|
|
|
This operation is used to materialize bool constants that arise when folding
|
|
`index.cmp`.
|
|
|
|
Example:
|
|
|
|
```mlir
|
|
%0 = index.bool.constant true
|
|
```
|
|
}];
|
|
|
|
let arguments = (ins BoolAttr:$value);
|
|
let results = (outs I1:$result);
|
|
let assemblyFormat = "attr-dict $value";
|
|
let hasFolder = 1;
|
|
}
|
|
|
|
#endif // INDEX_OPS
|