'index' Dialect
The Index dialect
The Index dialect contains operations for manipulating values of the builtin
index
type. The index type models target-specific values of pointer width,
like intptr_t
. Index values are typically used as loop bounds, array
subscripts, tensor dimensions, etc.
The operations in this dialect operate exclusively on scalar index types. The dialect and its operations treat the index type as signless and contains signed and unsigned versions of certain operations where the distinction is meaningful. In particular, the operations and transformations are careful to be aware of the target-independent-ness of the index type, such as when folding.
The folding semantics of the Index dialect operations ensure that folding
produces the same results irrespective of the eventual target pointer width.
All index constants are stored in APInt
s of maximum index bitwidth: 64.
Operations are folded using 64-bit integer arithmetic.
For operations where the values of the upper 32 bits don’t impact the values of the lower 32 bits, no additional handling is required because if the target is 32-bit, the truncated folded result will be the same as if the operation were computed with 32-bit arithmetic, and if the target is 64-bit, the fold result is valid by default.
Consider addition: an overflow in 32-bit is the same as truncating the
result computed in 64-bit. For example, add(0x800000008, 0x800000008)
is
0x1000000010
in 64-bit, which truncates to 0x10
, the same result as
truncating the operands first: add(0x08, 0x08)
. Specifically, an operation
f
can always be folded if it satisfies the following for all 64-bit values
of a
and b
:
trunc(f(a, b)) = f(trunc(a), trunc(b))
When materializing target-specific code, constants just need to be truncated as appropriate.
Operations where the values of the upper 32 bits do impact the values of the
lower 32 bits are not folded if the results would be different in 32-bit.
These are operations that right shift – division, remainder, etc. These
operations are only folded for subsets of a
and b
for which the above
property is satisfied. This is checked per fold attempt.
Consider division: the 32-bit computation will differ from 64-bit if the
latter results in a high bit shifted into the lower 32 bits. For example,
div(0x100000002, 2)
is 0x80000001
in 64-bit but 0x01
in 32-bit; it
cannot be folded. However, div(0x200000002, 2)
can be folded. The 64-bit
result is 0x100000001
, which truncated to 32 bits is 0x01
. The 32-bit
result of the operation with truncated operands div(0x02, 2)
which is
0x01
, the same as truncating the 64-bit result.
Operations ¶
index.add
(index::AddOp) ¶
Index addition
Syntax:
operation ::= `index.add` $lhs `,` $rhs attr-dict
The index.add
operation takes two index values and computes their sum.
Example:
// c = a + b
%c = index.add %a, %b
Traits: AlwaysSpeculatableImplTrait
, Commutative
Interfaces: ConditionallySpeculatable
, InferIntRangeInterface
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operands: ¶
Operand | Description |
---|---|
lhs | index |
rhs | index |
Results: ¶
Result | Description |
---|---|
result | index |
index.and
(index::AndOp) ¶
Index bitwise and
Syntax:
operation ::= `index.and` $lhs `,` $rhs attr-dict
The index.and
operation takes two index values and computes their bitwise
and.
Example:
// c = a & b
%c = index.and %a, %b
Traits: AlwaysSpeculatableImplTrait
, Commutative
Interfaces: ConditionallySpeculatable
, InferIntRangeInterface
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operands: ¶
Operand | Description |
---|---|
lhs | index |
rhs | index |
Results: ¶
Result | Description |
---|---|
result | index |
index.bool.constant
(index::BoolConstantOp) ¶
Boolean constant
Syntax:
operation ::= `index.bool.constant` attr-dict $value
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:
%0 = index.bool.constant true
Traits: AlwaysSpeculatableImplTrait
, ConstantLike
Interfaces: ConditionallySpeculatable
, InferIntRangeInterface
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
, OpAsmOpInterface
Effects: MemoryEffects::Effect{}
Attributes: ¶
Attribute | MLIR Type | Description |
---|---|---|
value | ::mlir::BoolAttr | bool attribute |
Results: ¶
Result | Description |
---|---|
result | 1-bit signless integer |
index.casts
(index::CastSOp) ¶
Index signed cast
Syntax:
operation ::= `index.casts` $input attr-dict `:` type($input) `to` type($output)
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:
// Cast to i32
%0 = index.casts %a : index to i32
// Cast from i64
%1 = index.casts %b : i64 to index
Traits: AlwaysSpeculatableImplTrait
Interfaces: CastOpInterface
, ConditionallySpeculatable
, InferIntRangeInterface
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operands: ¶
Operand | Description |
---|---|
input | integer or index |
Results: ¶
Result | Description |
---|---|
output | integer or index |
index.castu
(index::CastUOp) ¶
Index unsigned cast
Syntax:
operation ::= `index.castu` $input attr-dict `:` type($input) `to` type($output)
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:
// Cast to i32
%0 = index.castu %a : index to i32
// Cast from i64
%1 = index.castu %b : i64 to index
Traits: AlwaysSpeculatableImplTrait
Interfaces: CastOpInterface
, ConditionallySpeculatable
, InferIntRangeInterface
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operands: ¶
Operand | Description |
---|---|
input | integer or index |
Results: ¶
Result | Description |
---|---|
output | integer or index |
index.ceildivs
(index::CeilDivSOp) ¶
Index signed ceil division
Syntax:
operation ::= `index.ceildivs` $lhs `,` $rhs attr-dict
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:
// c = ceil(a / b)
%c = index.ceildivs %a, %b
Interfaces: InferIntRangeInterface
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operands: ¶
Operand | Description |
---|---|
lhs | index |
rhs | index |
Results: ¶
Result | Description |
---|---|
result | index |
index.ceildivu
(index::CeilDivUOp) ¶
Index unsigned ceil division
Syntax:
operation ::= `index.ceildivu` $lhs `,` $rhs attr-dict
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:
// c = ceil(a / b)
%c = index.ceildivu %a, %b
Interfaces: InferIntRangeInterface
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operands: ¶
Operand | Description |
---|---|
lhs | index |
rhs | index |
Results: ¶
Result | Description |
---|---|
result | index |
index.cmp
(index::CmpOp) ¶
Index compare
Syntax:
operation ::= `index.cmp` `` $pred `(` $lhs `,` $rhs `)` attr-dict
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
: equalne
: not equalslt
: signed less thansle
: signed less than or equalsgt
: signed greater thansge
: signed greater than or equalult
: unsigned less thanule
: unsigned less than or equalugt
: unsigned greater thanuge
: unsigned greater than or equal
The result is 1
if the comparison is true and 0
otherwise.
Example:
// 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)
Traits: AlwaysSpeculatableImplTrait
Interfaces: ConditionallySpeculatable
, InferIntRangeInterface
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Attributes: ¶
Attribute | MLIR Type | Description |
---|---|---|
pred | ::mlir::index::IndexCmpPredicateAttr | index comparison predicate kindEnum cases:
|
Operands: ¶
Operand | Description |
---|---|
lhs | index |
rhs | index |
Results: ¶
Result | Description |
---|---|
result | 1-bit signless integer |
index.constant
(index::ConstantOp) ¶
Index constant
Syntax:
operation ::= `index.constant` attr-dict $value
The index.constant
operation produces an index-typed SSA value equal to
some index-typed integer constant.
Example:
%0 = index.constant 42
Traits: AlwaysSpeculatableImplTrait
, ConstantLike
Interfaces: ConditionallySpeculatable
, InferIntRangeInterface
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
, OpAsmOpInterface
Effects: MemoryEffects::Effect{}
Attributes: ¶
Attribute | MLIR Type | Description |
---|---|---|
value | ::mlir::IntegerAttr | index attribute |
Results: ¶
Result | Description |
---|---|
result | index |
index.divs
(index::DivSOp) ¶
Index signed division
Syntax:
operation ::= `index.divs` $lhs `,` $rhs attr-dict
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:
// c = a / b
%c = index.divs %a, %b
Interfaces: InferIntRangeInterface
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operands: ¶
Operand | Description |
---|---|
lhs | index |
rhs | index |
Results: ¶
Result | Description |
---|---|
result | index |
index.divu
(index::DivUOp) ¶
Index unsigned division
Syntax:
operation ::= `index.divu` $lhs `,` $rhs attr-dict
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:
// c = a / b
%c = index.divu %a, %b
Interfaces: InferIntRangeInterface
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operands: ¶
Operand | Description |
---|---|
lhs | index |
rhs | index |
Results: ¶
Result | Description |
---|---|
result | index |
index.floordivs
(index::FloorDivSOp) ¶
Index signed floor division
Syntax:
operation ::= `index.floordivs` $lhs `,` $rhs attr-dict
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:
// c = floor(a / b)
%c = index.floordivs %a, %b
Interfaces: InferIntRangeInterface
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operands: ¶
Operand | Description |
---|---|
lhs | index |
rhs | index |
Results: ¶
Result | Description |
---|---|
result | index |
index.maxs
(index::MaxSOp) ¶
Index signed maximum
Syntax:
operation ::= `index.maxs` $lhs `,` $rhs attr-dict
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:
// c = max(a, b)
%c = index.maxs %a, %b
Traits: AlwaysSpeculatableImplTrait
, Commutative
Interfaces: ConditionallySpeculatable
, InferIntRangeInterface
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operands: ¶
Operand | Description |
---|---|
lhs | index |
rhs | index |
Results: ¶
Result | Description |
---|---|
result | index |
index.maxu
(index::MaxUOp) ¶
Index unsigned maximum
Syntax:
operation ::= `index.maxu` $lhs `,` $rhs attr-dict
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:
// c = max(a, b)
%c = index.maxu %a, %b
Traits: AlwaysSpeculatableImplTrait
, Commutative
Interfaces: ConditionallySpeculatable
, InferIntRangeInterface
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operands: ¶
Operand | Description |
---|---|
lhs | index |
rhs | index |
Results: ¶
Result | Description |
---|---|
result | index |
index.mins
(index::MinSOp) ¶
Index signed minimum
Syntax:
operation ::= `index.mins` $lhs `,` $rhs attr-dict
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:
// c = min(a, b)
%c = index.mins %a, %b
Traits: AlwaysSpeculatableImplTrait
, Commutative
Interfaces: ConditionallySpeculatable
, InferIntRangeInterface
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operands: ¶
Operand | Description |
---|---|
lhs | index |
rhs | index |
Results: ¶
Result | Description |
---|---|
result | index |
index.minu
(index::MinUOp) ¶
Index unsigned minimum
Syntax:
operation ::= `index.minu` $lhs `,` $rhs attr-dict
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:
// c = min(a, b)
%c = index.minu %a, %b
Traits: AlwaysSpeculatableImplTrait
, Commutative
Interfaces: ConditionallySpeculatable
, InferIntRangeInterface
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operands: ¶
Operand | Description |
---|---|
lhs | index |
rhs | index |
Results: ¶
Result | Description |
---|---|
result | index |
index.mul
(index::MulOp) ¶
Index multiplication
Syntax:
operation ::= `index.mul` $lhs `,` $rhs attr-dict
The index.mul
operation takes two index values and computes their product.
Example:
// c = a * b
%c = index.mul %a, %b
Traits: AlwaysSpeculatableImplTrait
, Commutative
Interfaces: ConditionallySpeculatable
, InferIntRangeInterface
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operands: ¶
Operand | Description |
---|---|
lhs | index |
rhs | index |
Results: ¶
Result | Description |
---|---|
result | index |
index.or
(index::OrOp) ¶
Index bitwise or
Syntax:
operation ::= `index.or` $lhs `,` $rhs attr-dict
The index.or
operation takes two index values and computes their bitwise
or.
Example:
// c = a | b
%c = index.or %a, %b
Traits: AlwaysSpeculatableImplTrait
, Commutative
Interfaces: ConditionallySpeculatable
, InferIntRangeInterface
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operands: ¶
Operand | Description |
---|---|
lhs | index |
rhs | index |
Results: ¶
Result | Description |
---|---|
result | index |
index.rems
(index::RemSOp) ¶
Index signed remainder
Syntax:
operation ::= `index.rems` $lhs `,` $rhs attr-dict
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:
// c = a % b
%c = index.rems %a, %b
Interfaces: InferIntRangeInterface
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operands: ¶
Operand | Description |
---|---|
lhs | index |
rhs | index |
Results: ¶
Result | Description |
---|---|
result | index |
index.remu
(index::RemUOp) ¶
Index unsigned remainder
Syntax:
operation ::= `index.remu` $lhs `,` $rhs attr-dict
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:
// c = a % b
%c = index.remu %a, %b
Interfaces: InferIntRangeInterface
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operands: ¶
Operand | Description |
---|---|
lhs | index |
rhs | index |
Results: ¶
Result | Description |
---|---|
result | index |
index.shl
(index::ShlOp) ¶
Index shift left
Syntax:
operation ::= `index.shl` $lhs `,` $rhs attr-dict
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:
// c = a << b
%c = index.shl %a, %b
Traits: AlwaysSpeculatableImplTrait
Interfaces: ConditionallySpeculatable
, InferIntRangeInterface
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operands: ¶
Operand | Description |
---|---|
lhs | index |
rhs | index |
Results: ¶
Result | Description |
---|---|
result | index |
index.shrs
(index::ShrSOp) ¶
Signed index shift right
Syntax:
operation ::= `index.shrs` $lhs `,` $rhs attr-dict
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:
// c = a >> b
%c = index.shrs %a, %b
Traits: AlwaysSpeculatableImplTrait
Interfaces: ConditionallySpeculatable
, InferIntRangeInterface
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operands: ¶
Operand | Description |
---|---|
lhs | index |
rhs | index |
Results: ¶
Result | Description |
---|---|
result | index |
index.shru
(index::ShrUOp) ¶
Unsigned index shift right
Syntax:
operation ::= `index.shru` $lhs `,` $rhs attr-dict
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:
// c = a >> b
%c = index.shru %a, %b
Traits: AlwaysSpeculatableImplTrait
Interfaces: ConditionallySpeculatable
, InferIntRangeInterface
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operands: ¶
Operand | Description |
---|---|
lhs | index |
rhs | index |
Results: ¶
Result | Description |
---|---|
result | index |
index.sizeof
(index::SizeOfOp) ¶
Size in bits of the index type
Syntax:
operation ::= `index.sizeof` attr-dict
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:
%0 = index.sizeof
Traits: AlwaysSpeculatableImplTrait
Interfaces: ConditionallySpeculatable
, InferIntRangeInterface
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Results: ¶
Result | Description |
---|---|
result | index |
index.sub
(index::SubOp) ¶
Index subtraction
Syntax:
operation ::= `index.sub` $lhs `,` $rhs attr-dict
The index.sub
operation takes two index values and computes the difference
of the first from the second operand.
Example:
// c = a - b
%c = index.sub %a, %b
Traits: AlwaysSpeculatableImplTrait
Interfaces: ConditionallySpeculatable
, InferIntRangeInterface
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operands: ¶
Operand | Description |
---|---|
lhs | index |
rhs | index |
Results: ¶
Result | Description |
---|---|
result | index |
index.xor
(index::XOrOp) ¶
Index bitwise xor
Syntax:
operation ::= `index.xor` $lhs `,` $rhs attr-dict
The index.xor
operation takes two index values and computes their bitwise
xor.
Example:
// c = a ^ b
%c = index.xor %a, %b
Traits: AlwaysSpeculatableImplTrait
, Commutative
Interfaces: ConditionallySpeculatable
, InferIntRangeInterface
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operands: ¶
Operand | Description |
---|---|
lhs | index |
rhs | index |
Results: ¶
Result | Description |
---|---|
result | index |
Attributes ¶
IndexCmpPredicateAttr ¶
index comparison predicate kind
Syntax:
#index.cmp_predicate<
::mlir::index::IndexCmpPredicate # value
>
Enum cases:
- eq (
EQ
) - ne (
NE
) - slt (
SLT
) - sle (
SLE
) - sgt (
SGT
) - sge (
SGE
) - ult (
ULT
) - ule (
ULE
) - ugt (
UGT
) - uge (
UGE
)
Parameters: ¶
Parameter | C++ type | Description |
---|---|---|
value | ::mlir::index::IndexCmpPredicate | an enum of type IndexCmpPredicate |
Enums ¶
IndexCmpPredicate ¶
index comparison predicate kind
Cases: ¶
Symbol | Value | String |
---|---|---|
EQ | 0 | eq |
NE | 1 | ne |
SLT | 2 | slt |
SLE | 3 | sle |
SGT | 4 | sgt |
SGE | 5 | sge |
ULT | 6 | ult |
ULE | 7 | ule |
UGT | 8 | ugt |
UGE | 9 | uge |