Begin the intermediate language reference.
This commit is contained in:
@@ -6,6 +6,7 @@ Contents:
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
langref
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
||||
585
cranelift/docs/langref.rst
Normal file
585
cranelift/docs/langref.rst
Normal file
@@ -0,0 +1,585 @@
|
||||
****************************************
|
||||
Cretonne Intermediate Language Reference
|
||||
****************************************
|
||||
|
||||
Type system
|
||||
===========
|
||||
|
||||
.. default-domain:: cton
|
||||
|
||||
All SSA values have a type which determines the size and shape (for SIMD
|
||||
vectors) of the value. Many instructions are polymorphic -- they can operate on
|
||||
different types.
|
||||
|
||||
.. type:: bool
|
||||
|
||||
A boolean value that is either true or false. Booleans can't be stored in
|
||||
memory.
|
||||
|
||||
Integer types
|
||||
-------------
|
||||
|
||||
Integer values have a fixed size and can be interpreted as either signed or
|
||||
unsigned. Some instructions will interpret an operand as a signed or unsigned
|
||||
number, others don't care.
|
||||
|
||||
.. type:: i8
|
||||
|
||||
A 8-bit integer value taking up 1 byte in memory.
|
||||
|
||||
.. type:: i16
|
||||
|
||||
A 16-bit integer value taking up 2 bytes in memory.
|
||||
|
||||
.. type:: i32
|
||||
|
||||
A 32-bit integer value taking up 4 bytes in memory.
|
||||
|
||||
.. type:: i64
|
||||
|
||||
A 64-bit integer value taking up 8 bytes in memory.
|
||||
|
||||
Floating point types
|
||||
--------------------
|
||||
|
||||
The floating point types have the IEEE semantics that are supported by most
|
||||
hardware. There is no support for higher-precision types like quads or
|
||||
double-double formats.
|
||||
|
||||
.. type:: f32
|
||||
|
||||
A 32-bit floating point type represented in the IEEE 754 *Single precision*
|
||||
format. This corresponds to the :c:type:`float` type in most C
|
||||
implementations.
|
||||
|
||||
.. type:: f64
|
||||
|
||||
A 64-bit floating point type represented in the IEEE 754 *Double precision*
|
||||
format. This corresponds to the :c:type:`double` type in most C
|
||||
implementations.
|
||||
|
||||
SIMD vector types
|
||||
-----------------
|
||||
|
||||
A SIMD vector type represents a vector of values from one of the scalar types
|
||||
(:type:`bool`, integer, and floating point). Each scalar value in a SIMD type is
|
||||
called a *lane*. The number of lanes must be a power of two in the range 2-256.
|
||||
|
||||
.. type:: vNiB
|
||||
|
||||
A SIMD vector of integers. The lane type :type:`iB` must be one of the
|
||||
integer types :type:`i8` ... :type:`i64`.
|
||||
|
||||
Some concrete integer vector types are :type:`v4i32`, :type:`v8i64`, and
|
||||
:type:`v4i16`.
|
||||
|
||||
The size of a SIMD integer vector in memory is :math:`N B\over 8` bytes.
|
||||
|
||||
.. type:: vNf32
|
||||
|
||||
A SIMD vector of single precision floating point numbers.
|
||||
|
||||
Some concrete :type:`f32` vector types are: :type:`v2f32`, :type:`v4f32`,
|
||||
and :type:`v8f32`.
|
||||
|
||||
The size of a :type:`f32` vector in memory is :math:`4N` bytes.
|
||||
|
||||
.. type:: vNf64
|
||||
|
||||
A SIMD vector of double precision floating point numbers.
|
||||
|
||||
Some concrete :type:`f64` vector types are: :type:`v2f64`, :type:`v4f64`,
|
||||
and :type:`v8f64`.
|
||||
|
||||
The size of a :type:`f64` vector in memory is :math:`8N` bytes.
|
||||
|
||||
.. type:: vNbool
|
||||
|
||||
A boolean SIMD vector.
|
||||
|
||||
Like the :type:`bool` type, a boolean vector cannot be stored in memory. It
|
||||
can only be used for ephemeral SSA values.
|
||||
|
||||
Instructions
|
||||
============
|
||||
|
||||
Control flow instructions
|
||||
-------------------------
|
||||
|
||||
.. inst:: br EBB(args...)
|
||||
|
||||
Branch.
|
||||
|
||||
Unconditionally branch to an extended basic block, passing the specified
|
||||
EBB arguments. The number and types of arguments must match the destination
|
||||
EBB.
|
||||
|
||||
.. inst:: brz x, EBB(args...)
|
||||
|
||||
Branch when zero.
|
||||
|
||||
If ``x`` is a :type:`bool` value, take the branch when ``x`` is false. If
|
||||
``x`` is an integer value, take the branch when ``x = 0``.
|
||||
|
||||
:param iN/bool x: Value to test.
|
||||
:param EBB: Destination extended basic block.
|
||||
|
||||
.. inst:: brnz x, EBB(args...)
|
||||
|
||||
Branch when non-zero.
|
||||
|
||||
If ``x`` is a :type:`bool` value, take the branch when ``x`` is true. If
|
||||
``x`` is an integer value, take the branch when ``x != 0``.
|
||||
|
||||
:param iN/bool x: Value to test.
|
||||
:param EBB: Destination extended basic block.
|
||||
|
||||
Special operations
|
||||
==================
|
||||
|
||||
Most operations are easily classified as arithmetic or control flow. These
|
||||
instructions are not so easily classified.
|
||||
|
||||
.. inst:: a = iconst n
|
||||
|
||||
Integer constant.
|
||||
|
||||
.. inst:: a = fconst n
|
||||
|
||||
Floating point constant.
|
||||
|
||||
.. inst:: a = vconst n
|
||||
|
||||
Vector constant (floating point or integer).
|
||||
|
||||
.. inst:: a = select c, x, y
|
||||
|
||||
Conditional select.
|
||||
|
||||
:param c bool: Controlling flag.
|
||||
:param x: Value to return when ``c`` is true.
|
||||
:param y: Value to return when ``c`` is false. Must be same type as ``x``.
|
||||
:rtype: Same type as ``x`` and ``y``.
|
||||
|
||||
This instruction selects whole values. Use :inst:`vselect` for
|
||||
lane-wise selection.
|
||||
|
||||
Vector operations
|
||||
=================
|
||||
|
||||
.. inst:: a = vselect c, x, y
|
||||
|
||||
Vector lane select.
|
||||
|
||||
Select lanes from ``x`` or ``y`` controlled by the lanes of the boolean
|
||||
vector ``c``.
|
||||
|
||||
:arg vNbool c: Controlling flag vector.
|
||||
:arg x: Vector with lanes selected by the true lanes of ``c``.
|
||||
Must be a vector type with the same number of lanes as ``c``.
|
||||
:arg y: Vector with lanes selected by the false lanes of ``c``.
|
||||
Must be same type as ``x``.
|
||||
:rtype: Same type as ``x`` and ``y``.
|
||||
|
||||
.. inst:: a = vbuild x, y, z, ...
|
||||
|
||||
Vector build.
|
||||
|
||||
Build a vector value from the provided lanes.
|
||||
|
||||
.. inst:: a = splat x
|
||||
|
||||
Vector splat.
|
||||
|
||||
Return a vector whose lanes are all ``x``.
|
||||
|
||||
.. inst:: a = insertlane x, idx, y
|
||||
|
||||
Insert ``y`` as lane ``idx`` in x.
|
||||
|
||||
The lane index, ``idx``, is an immediate value, not an SSA value. It must
|
||||
indicate a valid lane index for the type of ``x``.
|
||||
|
||||
.. inst:: a = extractlane x, idx
|
||||
|
||||
Extract lane ``idx`` from ``x``.
|
||||
|
||||
The lane index, ``idx``, is an immediate value, not an SSA value. It must
|
||||
indicate a valid lane index for the type of ``x``.
|
||||
|
||||
Integer operations
|
||||
==================
|
||||
|
||||
.. inst:: a = icmp cond, x, y
|
||||
|
||||
Integer comparison.
|
||||
|
||||
:param cond: Condition code determining how ``x`` and ``y`` are compared.
|
||||
:param x, y: Integer scalar or vector values of the same type.
|
||||
:rtype: :type:`bool` or :type:`vNbool` with the same number of lanes as
|
||||
``x`` and ``y``.
|
||||
|
||||
The condition code determines if the operands are interpreted as signed or
|
||||
unsigned integers.
|
||||
|
||||
====== ======== =========
|
||||
Signed Unsigned Condition
|
||||
====== ======== =========
|
||||
eq eq Equal
|
||||
ne ne Not equal
|
||||
slt ult Less than
|
||||
sge uge Greater than or equal
|
||||
sgt ugt Greater than
|
||||
sle ule Less than or equal
|
||||
====== ======== =========
|
||||
|
||||
.. inst:: a = iadd x, y
|
||||
|
||||
Wrapping integer addition: :math:`a := x + y \pmod{2^B}`. This instruction
|
||||
does not depend on the signed/unsigned interpretation of the operands.
|
||||
|
||||
.. inst:: a = isub x, y
|
||||
|
||||
Wrapping integer subtraction: :math:`a := x - y \pmod{2^B}`. This
|
||||
instruction does not depend on the signed/unsigned interpretation of the
|
||||
operands.
|
||||
|
||||
.. todo:: Overflow arithmetic
|
||||
|
||||
Add instructions for add with carry out / carry in and so on. Enough to
|
||||
implement larger integer types efficiently. It should also be possible to
|
||||
legalize :type:`i64` arithmetic to terms of :type:`i32` operations.
|
||||
|
||||
.. inst:: a = ineg x
|
||||
|
||||
Wrapping integer negation: :math:`a := -x \pmod{2^B}`. This instruction does
|
||||
not depend on the signed/unsigned interpretation of the operand.
|
||||
|
||||
.. inst:: a = imul x, y
|
||||
|
||||
Wrapping integer multiplication: :math:`a := x y \pmod{2^B}`. This
|
||||
instruction does not depend on the signed/unsigned interpretation of the
|
||||
operands.
|
||||
|
||||
.. todo:: Larger multiplication results.
|
||||
|
||||
For example, ``smulx`` which multiplies :type:`i32` operands to produce a
|
||||
:type:`i64` result. Alternatively, ``smulhi`` and ``smullo`` pairs.
|
||||
|
||||
.. inst:: a = udiv x, y
|
||||
|
||||
Unsigned integer division: :math:`a := \lfloor {x \over y} \rfloor`. This
|
||||
operation traps if the divisor is zero.
|
||||
|
||||
.. todo::
|
||||
Add a ``udiv_imm`` variant with an immediate divisor greater than 1.
|
||||
This is useful for pattern-matching divide-by-constant, and this
|
||||
instruction would be non-trapping.
|
||||
|
||||
.. inst:: a = sdiv x, y
|
||||
|
||||
Signed integer division rounded toward zero: :math:`a := sign(xy) \lfloor
|
||||
{|x| \over |y|}\rfloor`. This operation traps if the divisor is zero, or if
|
||||
the result is not representable in :math:`B` bits two's complement. This only
|
||||
happens when :math:`x = -2^{B-1}, y = -1`.
|
||||
|
||||
.. todo::
|
||||
Add a ``sdiv_imm`` variant with an immediate non-zero divisor. This is
|
||||
useful for pattern-matching divide-by-constant, and this instruction
|
||||
would be non-trapping. Don't allow divisors 0, 1, or -1.
|
||||
|
||||
.. inst:: a = urem x, y
|
||||
|
||||
Unsigned integer remainder. This operation traps if the divisor is zero.
|
||||
|
||||
.. todo::
|
||||
Add a ``urem_imm`` non-trapping variant.
|
||||
|
||||
.. inst:: a = srem x, y
|
||||
|
||||
Signed integer remainder. This operation traps if the divisor is zero.
|
||||
|
||||
.. todo::
|
||||
Clarify whether the result has the sign of the divisor or the dividend.
|
||||
Should we add a ``smod`` instruction for the case where the result has
|
||||
the same sign as the divisor?
|
||||
|
||||
.. todo:: Minimum / maximum.
|
||||
|
||||
NEON has ``smin``, ``smax``, ``umin``, and ``umax`` instructions. We should
|
||||
replicate those for both scalar and vector integer types. Even if the
|
||||
target ISA doesn't have scalar operations, these are good pattern mtching
|
||||
targets.
|
||||
|
||||
.. todo:: Saturating arithmetic.
|
||||
|
||||
Mostly for SIMD use, but again these are good paterns to contract.
|
||||
Something like ``usatadd``, ``usatsub``, ``ssatadd``, and ``ssatsub`` is a
|
||||
good start.
|
||||
|
||||
Bitwise operations
|
||||
==================
|
||||
|
||||
.. inst:: a = and x, y
|
||||
|
||||
Bitwise and.
|
||||
|
||||
:rtype: bool, iB, vNiB, vNfB?
|
||||
|
||||
.. inst:: a = or x, y
|
||||
|
||||
Bitwise or.
|
||||
|
||||
:rtype: bool, iB, vNiB, vNfB?
|
||||
|
||||
.. inst:: a = xor x, y
|
||||
|
||||
Bitwise xor.
|
||||
|
||||
:rtype: bool, iB, vNiB, vNfB?
|
||||
|
||||
.. inst:: a = not x
|
||||
|
||||
Bitwise not.
|
||||
|
||||
:rtype: bool, iB, vNiB, vNfB?
|
||||
|
||||
.. todo:: Redundant bitwise operators.
|
||||
|
||||
ARM has instructions like ``bic(x,y) = x & ~y``, ``orn(x,y) = x | ~y``, and
|
||||
``eon(x,y) = x ^ ~y``.
|
||||
|
||||
.. inst:: a = rotl x, y
|
||||
|
||||
Rotate left.
|
||||
|
||||
Rotate the bits in ``x`` by ``y`` places.
|
||||
|
||||
:param x: Integer value to be rotated.
|
||||
:param y: Number of bits to shift. Any integer type, not necessarily the
|
||||
same type as ``x``.
|
||||
:rtype: Same type as ``x``.
|
||||
|
||||
.. inst:: a = rotr x, y
|
||||
|
||||
Rotate right.
|
||||
|
||||
Rotate the bits in ``x`` by ``y`` places.
|
||||
|
||||
:param x: Integer value to be rotated.
|
||||
:param y: Number of bits to shift. Any integer type, not necessarily the
|
||||
same type as ``x``.
|
||||
:rtype: Same type as ``x``.
|
||||
|
||||
.. inst:: a = ishl x, y
|
||||
|
||||
Integer shift left. Shift the bits in ``x`` towards the MSB by ``y``
|
||||
places. Shift in zero bits to the LSB.
|
||||
|
||||
The shift amount is masked to the size of ``x``.
|
||||
|
||||
:param x: Integer value to be shifted.
|
||||
:param y: Number of bits to shift. Any integer type, not necessarily the
|
||||
same type as ``x``.
|
||||
:rtype: Same type as ``x``.
|
||||
|
||||
When shifting a B-bits integer type, this instruction computes:
|
||||
|
||||
.. math::
|
||||
s &:= y \pmod B, \\
|
||||
a &:= x \cdot 2^s \pmod{2^B}.
|
||||
|
||||
.. todo:: Add ``ishl_imm`` variant with an immediate ``y``.
|
||||
|
||||
.. inst:: a = ushr x, y
|
||||
|
||||
Unsigned shift right. Shift bits in ``x`` towards the LSB by ``y`` places,
|
||||
shifting in zero bits to the MSB. Also called a *logical shift*.
|
||||
|
||||
The shift amount is masked to the size of the register.
|
||||
|
||||
:param x: Integer value to be shifted.
|
||||
:param y: Number of bits to shift. Can be any integer type, not necessarily
|
||||
the same type as ``x``.
|
||||
:rtype: Same type as ``x``.
|
||||
|
||||
When shifting a B-bits integer type, this instruction computes:
|
||||
|
||||
.. math::
|
||||
s &:= y \pmod B, \\
|
||||
a &:= \lfloor x \cdot 2^{-s} \rfloor.
|
||||
|
||||
.. todo:: Add ``ushr_imm`` variant with an immediate ``y``.
|
||||
|
||||
.. inst:: a = sshr x, y
|
||||
|
||||
Signed shift right. Shift bits in ``x`` towards the LSB by ``y`` places,
|
||||
shifting in sign bits to the MSB. Also called an *arithmetic shift*.
|
||||
|
||||
The shift amount is masked to the size of the register.
|
||||
|
||||
:param x: Integer value to be shifted.
|
||||
:param y: Number of bits to shift. Can be any integer type, not necessarily
|
||||
the same type as ``x``.
|
||||
:rtype: Same type as ``x``.
|
||||
|
||||
.. todo:: Add ``sshr_imm`` variant with an immediate ``y``.
|
||||
|
||||
.. inst:: a = clz x
|
||||
|
||||
Count leading zero bits.
|
||||
|
||||
:param x: Integer value.
|
||||
:rtype: :type:`i8`
|
||||
|
||||
Starting from the MSB in ``x``, count the number of zero bits before
|
||||
reaching the first one bit. When ``x`` is zero, returns the size of x in
|
||||
bits.
|
||||
|
||||
.. inst:: a = cls x
|
||||
|
||||
Count leading sign bits.
|
||||
|
||||
:param x: Integer value.
|
||||
:rtype: :type:`i8`
|
||||
|
||||
Starting from the MSB after the sign bit in ``x``, count the number of
|
||||
consecutive bits identical to the sign bit. When ``x`` is 0 or -1, returns
|
||||
one less than the size of x in bits.
|
||||
|
||||
.. inst:: a = ctz x
|
||||
|
||||
Count trailing zeros.
|
||||
|
||||
:param x: Integer value.
|
||||
:rtype: :type:`i8`
|
||||
|
||||
Starting from the LSB in ``x``, count the number of zero bits before
|
||||
reaching the first one bit. When ``x`` is zero, returns the size of x in
|
||||
bits.
|
||||
|
||||
.. inst:: a = popcnt x
|
||||
|
||||
Population count
|
||||
|
||||
:param x: Integer value.
|
||||
:rtype: :type:`i8`
|
||||
|
||||
Count the number of one bits in ``x``.
|
||||
|
||||
|
||||
Floating point operations
|
||||
=========================
|
||||
|
||||
.. inst:: a = fcmp cond, x, y
|
||||
|
||||
Floating point comparison.
|
||||
|
||||
:param cond: Condition code determining how ``x`` and ``y`` are compared.
|
||||
:param x, y: Floating point scalar or vector values of the same type.
|
||||
:rtype: :type:`bool` or :type:`vNbool` with the same number of lanes as
|
||||
``x`` and ``y``.
|
||||
|
||||
An 'ordered' condition code yields ``false`` if either operand is Nan.
|
||||
|
||||
An 'unordered' condition code yields ``true`` if either operand is Nan.
|
||||
|
||||
======= ========= =========
|
||||
Ordered Unordered Condition
|
||||
======= ========= =========
|
||||
ord uno None (ord = no NaNs, uno = some NaNs)
|
||||
oeq ueq Equal
|
||||
one une Not equal
|
||||
olt ult Less than
|
||||
oge uge Greater than or equal
|
||||
ogt ugt Greater than
|
||||
ole ule Less than or equal
|
||||
======= ========= =========
|
||||
|
||||
.. inst:: fadd x,y
|
||||
|
||||
Floating point addition.
|
||||
|
||||
.. inst:: fsub x,y
|
||||
|
||||
Floating point subtraction.
|
||||
|
||||
.. inst:: fneg x
|
||||
|
||||
Floating point negation.
|
||||
|
||||
:returns: ``x`` with its sign bit inverted.
|
||||
|
||||
Note that this is a pure bitwise operation.
|
||||
|
||||
.. inst:: fabs x
|
||||
|
||||
Floating point absolute value.
|
||||
|
||||
:returns: ``x`` with its sign bit cleared.
|
||||
|
||||
Note that this is a pure bitwise operation.
|
||||
|
||||
.. inst:: a = fcopysign x, y
|
||||
|
||||
Floating point copy sign.
|
||||
|
||||
:returns: ``x`` with its sign changed to that of ``y``.
|
||||
|
||||
Note that this is a pure bitwise operation. The sign bit from ``y`` is
|
||||
copied to the sign bit of ``x``.
|
||||
|
||||
.. inst:: fmul x, y
|
||||
.. inst:: fdiv x, y
|
||||
.. inst:: fmin x, y
|
||||
.. inst:: fminnum x, y
|
||||
.. inst:: fmax x, y
|
||||
.. inst:: fmaxnum x, y
|
||||
.. inst:: ceil x
|
||||
|
||||
Round floating point round to integral, towards positive infinity.
|
||||
|
||||
.. inst:: floor x
|
||||
|
||||
Round floating point round to integral, towards negative infinity.
|
||||
|
||||
.. inst:: trunc x
|
||||
|
||||
Round floating point round to integral, towards zero.
|
||||
|
||||
.. inst:: nearest x
|
||||
|
||||
Round floating point round to integral, towards nearest with ties to even.
|
||||
|
||||
.. inst:: sqrt x
|
||||
|
||||
Floating point square root.
|
||||
|
||||
.. inst:: a = fma x, y, z
|
||||
|
||||
Floating point fused multiply-and-add.
|
||||
|
||||
Computes :math:`a := xy+z` wihtout any intermediate rounding of the
|
||||
product.
|
||||
|
||||
Conversion operations
|
||||
=====================
|
||||
|
||||
.. inst:: a = bitcast x
|
||||
|
||||
Reinterpret the bits in ``x`` as a different type.
|
||||
|
||||
The input and output types must be storable to memory and of the same size.
|
||||
A bitcast is equivalent to storing one type and loading the other type from
|
||||
the same address.
|
||||
|
||||
.. inst:: a = itrunc x
|
||||
.. inst:: a = uext x
|
||||
.. inst:: a = sext x
|
||||
.. inst:: a = ftrunc x
|
||||
.. inst:: a = fext x
|
||||
.. inst:: a = cvt_ftou x
|
||||
.. inst:: a = cvt_ftos x
|
||||
.. inst:: a = cvt_utof x
|
||||
.. inst:: a = cvt_stof x
|
||||
|
||||
Reference in New Issue
Block a user