From b5ee157d4653baecc3e90f7bd47dad83a32c12ba Mon Sep 17 00:00:00 2001 From: Jakob Olesen Date: Tue, 12 Jan 2016 16:54:49 -0800 Subject: [PATCH] Begin the intermediate language reference. --- docs/index.rst | 1 + docs/langref.rst | 585 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 586 insertions(+) create mode 100644 docs/langref.rst diff --git a/docs/index.rst b/docs/index.rst index 5f8e7c2df1..137e7b1e84 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -6,6 +6,7 @@ Contents: .. toctree:: :maxdepth: 2 + langref Indices and tables ================== diff --git a/docs/langref.rst b/docs/langref.rst new file mode 100644 index 0000000000..31f79df0c2 --- /dev/null +++ b/docs/langref.rst @@ -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 +