Constants (GNU Compiler Collection (GCC) Internals)

### 15.7 Constant Expression Types ¶

The simplest RTL expressions are those that represent constant values.

`(const_int i)` ¶

  This type of expression represents the integer value i. i is customarily accessed with the macro `INTVAL` as in `INTVAL (exp)`, which is equivalent to `XWINT (exp, 0)`.

  Constants generated for modes with fewer bits than in `HOST_WIDE_INT` must be sign extended to full width (e.g., with `gen_int_mode`). For constants for modes with more bits than in `HOST_WIDE_INT` the implied high order bits of that constant are copies of the top bit. Note however that values are neither inherently signed nor inherently unsigned; where necessary, signedness is determined by the rtl operation instead.

  There is only one expression object for the integer value zero; it is the value of the variable `const0_rtx`. Likewise, the only expression for integer value one is found in `const1_rtx`, the only expression for integer value two is found in `const2_rtx`, and the only expression for integer value negative one is found in `constm1_rtx`. Any attempt to create an expression of code `const_int` and value zero, one, two or negative one will return `const0_rtx`, `const1_rtx`, `const2_rtx` or `constm1_rtx` as appropriate.

  Similarly, there is only one object for the integer whose value is `STORE_FLAG_VALUE`. It is found in `const_true_rtx`. If `STORE_FLAG_VALUE` is one, `const_true_rtx` and `const1_rtx` will point to the same object. If `STORE_FLAG_VALUE` is −1, `const_true_rtx` and `constm1_rtx` will point to the same object.

`(const_double:m i0 i1 …)` ¶

  This represents either a floating-point constant of mode m or (on older ports that do not define `TARGET_SUPPORTS_WIDE_INT`) an integer constant too large to fit into `HOST_BITS_PER_WIDE_INT` bits but small enough to fit within twice that number of bits. In the latter case, m will be `VOIDmode`. For integral values constants for modes with more bits than twice the number in `HOST_WIDE_INT` the implied high order bits of that constant are copies of the top bit of `CONST_DOUBLE_HIGH`. Note however that integral values are neither inherently signed nor inherently unsigned; where necessary, signedness is determined by the rtl operation instead.

  On more modern ports, `CONST_DOUBLE` only represents floating point values. New ports define `TARGET_SUPPORTS_WIDE_INT` to make this designation.

  If m is `VOIDmode`, the bits of the value are stored in i0 and i1. i0 is customarily accessed with the macro `CONST_DOUBLE_LOW` and i1 with `CONST_DOUBLE_HIGH`.

  If the constant is floating point (regardless of its precision), then the number of integers used to store the value depends on the size of `REAL_VALUE_TYPE` (see Cross Compilation and Floating Point). The integers represent a floating point number, but not precisely in the target machine’s or host machine’s floating point format. To convert them to the precise bit pattern used by the target machine, use the macro `REAL_VALUE_TO_TARGET_DOUBLE` and friends (see Output of Data).

  The host dependency for the number of integers used to store a double value makes it problematic for machine descriptions to use expressions of code `const_double` and therefore a syntactic alias has been provided:

      (const_double_zero:m)

  standing for:

      (const_double:m 0 0 ...)

  for matching the floating-point value zero, possibly the only useful one.

`(const_wide_int:m nunits elt0 …)` ¶

  This contains an array of `HOST_WIDE_INT`s that is large enough to hold any constant that can be represented on the target. This form of rtl is only used on targets that define `TARGET_SUPPORTS_WIDE_INT` to be nonzero and then `CONST_DOUBLE`s are only used to hold floating-point values. If the target leaves `TARGET_SUPPORTS_WIDE_INT` defined as 0, `CONST_WIDE_INT`s are not used and `CONST_DOUBLE`s are as they were before.

  The values are stored in a compressed format. The higher-order 0s or -1s are not represented if they are just the logical sign extension of the number that is represented.

`CONST_WIDE_INT_VEC (code)` ¶

  Returns the entire array of `HOST_WIDE_INT`s that are used to store the value. This macro should be rarely used.

`CONST_WIDE_INT_NUNITS (code)` ¶

  The number of `HOST_WIDE_INT`s used to represent the number. Note that this generally is smaller than the number of `HOST_WIDE_INT`s implied by the mode size.

`CONST_WIDE_INT_ELT (code,i)` ¶

  Returns the `i`th element of the array. Element 0 is contains the low order bits of the constant.

`(const_fixed:m …)` ¶

  Represents a fixed-point constant of mode m. The operand is a data structure of type `struct fixed_value` and is accessed with the macro `CONST_FIXED_VALUE`. The high part of data is accessed with `CONST_FIXED_VALUE_HIGH`; the low part is accessed with `CONST_FIXED_VALUE_LOW`.

`(const_poly_int:m [c0 c1 …])` ¶

  Represents a `poly_int`-style polynomial integer with coefficients c0, c1, …. The coefficients are `wide_int`-based integers rather than rtxes. `CONST_POLY_INT_COEFFS` gives the values of individual coefficients (which is mostly only useful in low-level routines) and `const_poly_int_value` gives the full `poly_int` value.

`(const_vector:m [x0 x1 …])` ¶

  Represents a vector constant. The values in square brackets are elements of the vector, which are always `const_int`, `const_wide_int`, `const_double` or `const_fixed` expressions.

  Each vector constant v is treated as a specific instance of an arbitrary-length sequence that itself contains ‘`CONST_VECTOR_NPATTERNS (v)`’ interleaved patterns. Each pattern has the form:

      { base0, base1, base1 + step, base1 + step * 2, ... }

  The first three elements in each pattern are enough to determine the values of the other elements. However, if all steps are zero, only the first two elements are needed. If in addition each base1 is equal to the corresponding base0, only the first element in each pattern is needed. The number of determining elements per pattern is given by ‘`CONST_VECTOR_NELTS_PER_PATTERN (v)`’.

  For example, the constant:

      { 0, 1, 2, 6, 3, 8, 4, 10, 5, 12, 6, 14, 7, 16, 8, 18 }

  is interpreted as an interleaving of the sequences:

      { 0, 2, 3, 4, 5, 6, 7, 8 }
      { 1, 6, 8, 10, 12, 14, 16, 18 }

  where the sequences are represented by the following patterns:

      base0 == 0, base1 == 2, step == 1
      base0 == 1, base1 == 6, step == 2

  In this case:

      CONST_VECTOR_NPATTERNS (v) == 2
      CONST_VECTOR_NELTS_PER_PATTERN (v) == 3

  Thus the first 6 elements (‘`{ 0, 1, 2, 6, 3, 8 }`’) are enough to determine the whole sequence; we refer to them as the “encoded” elements. They are the only elements present in the square brackets for variable-length `const_vector`s (i.e. for `const_vector`s whose mode m has a variable number of elements). However, as a convenience to code that needs to handle both `const_vector`s and `parallel`s, all elements are present in the square brackets for fixed-length `const_vector`s; the encoding scheme simply reduces the amount of work involved in processing constants that follow a regular pattern.

  Sometimes this scheme can create two possible encodings of the same vector. For example { 0, 1 } could be seen as two patterns with one element each or one pattern with two elements (base0 and base1). The canonical encoding is always the one with the fewest patterns or (if both encodings have the same number of patterns) the one with the fewest encoded elements.

  ‘`const_vector_encoding_nelts (v)`’ gives the total number of encoded elements in v, which is 6 in the example above. `CONST_VECTOR_ENCODED_ELT (v, i)` accesses the value of encoded element i.

  ‘`CONST_VECTOR_DUPLICATE_P (v)`’ is true if v simply contains repeated instances of ‘`CONST_VECTOR_NPATTERNS (v)`’ values. This is a shorthand for testing ‘`CONST_VECTOR_NELTS_PER_PATTERN (v) == 1`’.

  ‘`CONST_VECTOR_STEPPED_P (v)`’ is true if at least one pattern in v has a nonzero step. This is a shorthand for testing ‘`CONST_VECTOR_NELTS_PER_PATTERN (v) == 3`’.

  `CONST_VECTOR_NUNITS (v)` gives the total number of elements in v; it is a shorthand for getting the number of units in ‘`GET_MODE (v)`’.

  The utility function `const_vector_elt` gives the value of an arbitrary element as an `rtx`. `const_vector_int_elt` gives the same value as a `wide_int`.

`(const_string str)` ¶

  Represents a constant string with value str. Currently this is used only for insn attributes (see Instruction Attributes) since constant strings in C are placed in memory.

`(symbol_ref:mode symbol)` ¶

  Represents the value of an assembler label for data. symbol is a string that describes the name of the assembler label. If it starts with a ‘`*`’, the label is the rest of symbol not including the ‘`*`’. Otherwise, the label is symbol, usually prefixed with ‘`_`’.

  The `symbol_ref` contains a mode, which is usually `Pmode`. Usually that is the only mode for which a symbol is directly valid.

`(label_ref:mode label)` ¶

  Represents the value of an assembler label for code. It contains one operand, an expression, which must be a `code_label` or a `note` of type `NOTE_INSN_DELETED_LABEL` that appears in the instruction sequence to identify the place where the label should go.

  The reason for using a distinct expression type for code label references is so that jump optimization can distinguish them.

  The `label_ref` contains a mode, which is usually `Pmode`. Usually that is the only mode for which a label is directly valid.

`(const:m exp)` ¶

  Represents a constant that is the result of an assembly-time arithmetic computation. The operand, exp, contains only `const_int`, `symbol_ref`, `label_ref` or `unspec` expressions, combined with `plus` and `minus`. Any such `unspec`s are target-specific and typically represent some form of relocation operator. m should be a valid address mode.

`(high:m exp)` ¶

  Represents the high-order bits of exp. The number of bits is machine-dependent and is normally the number of bits specified in an instruction that initializes the high order bits of a register. It is used with `lo_sum` to represent the typical two-instruction sequence used in RISC machines to reference large immediate values and/or link-time constants such as global memory addresses. In the latter case, m is `Pmode` and exp is usually a constant expression involving `symbol_ref`.

The macro `CONST0_RTX (mode)` refers to an expression with value 0 in mode mode. If mode mode is of mode class `MODE_INT`, it returns `const0_rtx`. If mode mode is of mode class `MODE_FLOAT`, it returns a `CONST_DOUBLE` expression in mode mode. Otherwise, it returns a `CONST_VECTOR` expression in mode mode. Similarly, the macro `CONST1_RTX (mode)` refers to an expression with value 1 in mode mode and similarly for `CONST2_RTX`. The `CONST1_RTX` and `CONST2_RTX` macros are undefined for vector modes.