Begin the intermediate language reference.

This commit is contained in:
Jakob Olesen
2016-01-12 16:54:49 -08:00
parent c8f20534d3
commit b5ee157d46
2 changed files with 586 additions and 0 deletions

View File

@@ -6,6 +6,7 @@ Contents:
.. toctree:: .. toctree::
:maxdepth: 2 :maxdepth: 2
langref
Indices and tables Indices and tables
================== ==================

585
docs/langref.rst Normal file
View 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