# MLIR

Multi-Level IR Compiler Framework

# '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 APInts 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.

## Operation definition ¶

### index.add (::mlir::index::AddOp) ¶

Syntax:

operation ::= index.add $lhs ,$rhs attr-dict


The index.add operation takes two index values and computes their sum.

Example:

// c = a + b


Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, InferIntRangeInterface, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

#### Operands: ¶

OperandDescription
lhsindex
rhsindex

#### Results: ¶

ResultDescription
resultindex

### index.and (::mlir::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

Interfaces: ConditionallySpeculatable, InferIntRangeInterface, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

#### Operands: ¶

OperandDescription
lhsindex
rhsindex

#### Results: ¶

ResultDescription
resultindex

### index.bool.constant (::mlir::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: ¶ AttributeMLIR TypeDescription value::mlir::BoolAttrbool attribute #### Results: ¶ ResultDescription result1-bit signless integer ### index.casts (::mlir::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: ¶

OperandDescription
inputinteger or index

#### Results: ¶

ResultDescription
outputinteger or index

### index.castu (::mlir::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: ¶ OperandDescription inputinteger or index #### Results: ¶ ResultDescription outputinteger or index ### index.ceildivs (::mlir::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  Traits: AlwaysSpeculatableImplTrait Interfaces: ConditionallySpeculatable, InferIntRangeInterface, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface) Effects: MemoryEffects::Effect{} #### Operands: ¶ OperandDescription lhsindex rhsindex #### Results: ¶ ResultDescription resultindex ### index.ceildivu (::mlir::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  Traits: AlwaysSpeculatableImplTrait Interfaces: ConditionallySpeculatable, InferIntRangeInterface, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface) Effects: MemoryEffects::Effect{} #### Operands: ¶ OperandDescription lhsindex rhsindex #### Results: ¶ ResultDescription resultindex ### index.cmp (::mlir::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: 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:

// 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: ¶

AttributeMLIR TypeDescription
pred::mlir::index::IndexCmpPredicateAttrindex comparison predicate kind

#### Operands: ¶

OperandDescription
lhsindex
rhsindex

#### Results: ¶

ResultDescription
result1-bit signless integer

### index.constant (::mlir::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: ¶ AttributeMLIR TypeDescription value::mlir::IntegerAttrindex attribute #### Results: ¶ ResultDescription resultindex ### index.divs (::mlir::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  Traits: AlwaysSpeculatableImplTrait Interfaces: ConditionallySpeculatable, InferIntRangeInterface, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface) Effects: MemoryEffects::Effect{} #### Operands: ¶ OperandDescription lhsindex rhsindex #### Results: ¶ ResultDescription resultindex ### index.divu (::mlir::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  Traits: AlwaysSpeculatableImplTrait Interfaces: ConditionallySpeculatable, InferIntRangeInterface, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface) Effects: MemoryEffects::Effect{} #### Operands: ¶ OperandDescription lhsindex rhsindex #### Results: ¶ ResultDescription resultindex ### index.floordivs (::mlir::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  Traits: AlwaysSpeculatableImplTrait Interfaces: ConditionallySpeculatable, InferIntRangeInterface, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface) Effects: MemoryEffects::Effect{} #### Operands: ¶ OperandDescription lhsindex rhsindex #### Results: ¶ ResultDescription resultindex ### index.maxs (::mlir::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 Interfaces: ConditionallySpeculatable, InferIntRangeInterface, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface) Effects: MemoryEffects::Effect{} #### Operands: ¶ OperandDescription lhsindex rhsindex #### Results: ¶ ResultDescription resultindex ### index.maxu (::mlir::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 Interfaces: ConditionallySpeculatable, InferIntRangeInterface, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface) Effects: MemoryEffects::Effect{} #### Operands: ¶ OperandDescription lhsindex rhsindex #### Results: ¶ ResultDescription resultindex ### index.mins (::mlir::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 Interfaces: ConditionallySpeculatable, InferIntRangeInterface, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface) Effects: MemoryEffects::Effect{} #### Operands: ¶ OperandDescription lhsindex rhsindex #### Results: ¶ ResultDescription resultindex ### index.minu (::mlir::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 Interfaces: ConditionallySpeculatable, InferIntRangeInterface, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface) Effects: MemoryEffects::Effect{} #### Operands: ¶ OperandDescription lhsindex rhsindex #### Results: ¶ ResultDescription resultindex ### index.mul (::mlir::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 Interfaces: ConditionallySpeculatable, InferIntRangeInterface, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface) Effects: MemoryEffects::Effect{} #### Operands: ¶ OperandDescription lhsindex rhsindex #### Results: ¶ ResultDescription resultindex ### index.or (::mlir::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 Interfaces: ConditionallySpeculatable, InferIntRangeInterface, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface) Effects: MemoryEffects::Effect{} #### Operands: ¶ OperandDescription lhsindex rhsindex #### Results: ¶ ResultDescription resultindex ### index.rems (::mlir::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  Traits: AlwaysSpeculatableImplTrait Interfaces: ConditionallySpeculatable, InferIntRangeInterface, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface) Effects: MemoryEffects::Effect{} #### Operands: ¶ OperandDescription lhsindex rhsindex #### Results: ¶ ResultDescription resultindex ### index.remu (::mlir::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  Traits: AlwaysSpeculatableImplTrait Interfaces: ConditionallySpeculatable, InferIntRangeInterface, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface) Effects: MemoryEffects::Effect{} #### Operands: ¶ OperandDescription lhsindex rhsindex #### Results: ¶ ResultDescription resultindex ### index.shl (::mlir::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 operation is undefined. Example: // c = a << b %c = index.shl %a, %b  Traits: AlwaysSpeculatableImplTrait Interfaces: ConditionallySpeculatable, InferIntRangeInterface, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface) Effects: MemoryEffects::Effect{} #### Operands: ¶ OperandDescription lhsindex rhsindex #### Results: ¶ ResultDescription resultindex ### index.shrs (::mlir::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 operation is undefined. Example: // c = a >> b %c = index.shrs %a, %b  Traits: AlwaysSpeculatableImplTrait Interfaces: ConditionallySpeculatable, InferIntRangeInterface, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface) Effects: MemoryEffects::Effect{} #### Operands: ¶ OperandDescription lhsindex rhsindex #### Results: ¶ ResultDescription resultindex ### index.shru (::mlir::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 operation is undefined. Example: // c = a >> b %c = index.shru %a, %b  Traits: AlwaysSpeculatableImplTrait Interfaces: ConditionallySpeculatable, InferIntRangeInterface, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface) Effects: MemoryEffects::Effect{} #### Operands: ¶ OperandDescription lhsindex rhsindex #### Results: ¶ ResultDescription resultindex ### index.sizeof (::mlir::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: ¶ ResultDescription resultindex ### index.sub (::mlir::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: ¶ OperandDescription lhsindex rhsindex #### Results: ¶ ResultDescription resultindex ### index.xor (::mlir::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

Interfaces: ConditionallySpeculatable, InferIntRangeInterface, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

#### Operands: ¶

OperandDescription
lhsindex
rhsindex

#### Results: ¶

ResultDescription
resultindex

## Attribute definition ¶

### IndexCmpPredicateAttr ¶

index comparison predicate kind

Syntax:

#index.cmp_predicate<
::mlir::index::IndexCmpPredicate   # value
>


#### Parameters: ¶

ParameterC++ typeDescription
value::mlir::index::IndexCmpPredicatean enum of type IndexCmpPredicate