Sizes and offsets as runtime invariants
***************************************

GCC allows the size of a hardware register to be a runtime invariant rather than a compile-time constant.  This in turn means that various sizes and offsets must also be runtime invariants rather than compile-time constants, such as:

  * the size of a general machine_mode (see Machine Modes);

  * the size of a spill slot;

  * the offset of something within a stack frame;

  * the number of elements in a vector;

  * the size and offset of a mem rtx (see Regs and Memory); and

  * the byte offset in a subreg rtx (see Regs and Memory).

The motivating example is the Arm SVE ISA, whose vector registers can be any multiple of 128 bits between 128 and 2048 inclusive.  The compiler normally produces code that works for all SVE register sizes, with the actual size only being known at runtime.

GCC's main representation of such runtime invariants is the poly_int class.  This chapter describes what poly_int does, lists the available operations, and gives some general usage guidelines.

Overview of poly_int
====================

We define indeterminates X1, ..., XN whose values are only known at runtime and use polynomials of the form:

     C0 + C1 * X1 + ... + CN * XN

to represent a size or offset whose value might depend on some of these indeterminates.  The coefficients C0, ..., CN are always known at compile time, with the C0 term being the ``constant'' part that does not depend on any runtime value.

GCC uses the poly_int class to represent these coefficients. The class has two template parameters: the first specifies the number of coefficients (N + 1) and the second specifies the type of the coefficients.  For example, poly_int<2, unsigned short> represents a polynomial with two coefficients (and thus one indeterminate), with each coefficient having type unsigned short.  When N is 0, the class degenerates to a single compile-time constant C0.

The number of coefficients needed for compilation is a fixed property of each target and is specified by the configuration macro NUM_POLY_INT_COEFFS.  The default value is 1, since most targets do not have such runtime invariants.  Targets that need a different value should #define the macro in their CPU-modes.def file.  See Back End.

poly_int makes the simplifying requirement that each indeterminate must be a nonnegative integer.  An indeterminate value of 0 should usually represent the minimum possible runtime value, with C0 specifying the value in that case.

For example, when targetting the Arm SVE ISA, the single indeterminate represents the number of 128-bit blocks in a vector beyond the minimum length of 128 bits.  Thus the number of 64-bit doublewords in a vector is 2 + 2 * X1.  If an aggregate has a single SVE vector and 16 additional bytes, its total size is 32 + 16 * X1 bytes.

The header file poly-int-types.h provides typedefs for the most common forms of poly_int, all having NUM_POLY_INT_COEFFS coefficients:

poly_uint16
     a poly_int with unsigned short coefficients.

poly_int64
     a poly_int with HOST_WIDE_INT coefficients.

poly_uint64
     a poly_int with unsigned HOST_WIDE_INT coefficients.

poly_offset_int
     a poly_int with offset_int coefficients.

poly_wide_int
     a poly_int with wide_int coefficients.

poly_widest_int
     a poly_int with widest_int coefficients.

Since the main purpose of poly_int is to represent sizes and offsets, the last two typedefs are only rarely used.

Consequences of using poly_int
==============================

The two main consequences of using polynomial sizes and offsets are that:

  * there is no total ordering between the values at compile time, and

  * some operations might yield results that cannot be expressed as a poly_int.

For example, if X is a runtime invariant, we cannot tell at compile time whether:

     3 + 4X <= 1 + 5X

since the condition is false when X <= 1 and true when X >= 2.

Similarly, poly_int cannot represent the result of:

     (3 + 4X) * (1 + 5X)

since it cannot (and in practice does not need to) store powers greater than one.  It also cannot represent the result of:

     (3 + 4X) / (1 + 5X)

The following sections describe how we deal with these restrictions.

As described earlier, a poly_int<1, T> has no indeterminates and so degenerates to a compile-time constant of type T.  It would be possible in that case to do all normal arithmetic on the T, and to compare the T using the normal C++ operators.  We deliberately prevent target-independent code from doing this, since the compiler needs to support other poly_int<N, T> as well, regardless of the current target's NUM_POLY_INT_COEFFS.

However, it would be very artificial to force target-specific code to follow these restrictions if the target has no runtime indeterminates. There is therefore an implicit conversion from poly_int<1, T> to T when compiling target-specific translation units.

Comparisons involving poly_int
==============================

In general we need to compare sizes and offsets in two situations: those in which the values need to be ordered, and those in which the values can be unordered.  More loosely, the distinction is often between values that have a definite link (usually because they refer to the same underlying register or memory location) and values that have no definite link.  An example of the former is the relationship between the inner and outer sizes of a subreg, where we must know at compile time whether the subreg is paradoxical, partial, or complete.  An example of the latter is alias analysis: we might want to check whether two arbitrary memory references overlap.

Referring back to the examples in the previous section, it makes sense to ask whether a memory reference of size 3 + 4X overlaps one of size 1 + 5X, but it does not make sense to have a subreg in which the outer mode has 3 + 4X bytes and the inner mode has 1 + 5X bytes (or vice versa).  Such subregs are always invalid and should trigger an internal compiler error if formed.

The underlying operators are the same in both cases, but the distinction affects how they are used.

Comparison functions for poly_int
---------------------------------

poly_int provides the following routines for checking whether a particular condition ``may be'' (might be) true:

     maybe_lt maybe_le maybe_eq maybe_ge maybe_gt
                       maybe_ne

The functions have their natural meaning:

maybe_lt(A, B)
     Return true if A might be less than B.

maybe_le(A, B)
     Return true if A might be less than or equal to B.

maybe_eq(A, B)
     Return true if A might be equal to B.

maybe_ne(A, B)
     Return true if A might not be equal to B.

maybe_ge(A, B)
     Return true if A might be greater than or equal to B.

maybe_gt(A, B)
     Return true if A might be greater than B.

For readability, poly_int also provides ``known'' inverses of these functions:

     known_lt (A, B) == !maybe_ge (A, B)
     known_le (A, B) == !maybe_gt (A, B)
     known_eq (A, B) == !maybe_ne (A, B)
     known_ge (A, B) == !maybe_lt (A, B)
     known_gt (A, B) == !maybe_le (A, B)
     known_ne (A, B) == !maybe_eq (A, B)

Properties of the poly_int comparisons
--------------------------------------

All ``maybe'' relations except maybe_ne are transitive, so for example:

     maybe_lt (A, B) && maybe_lt (B, C) implies maybe_lt (A, C)

for all A, B and C.  maybe_lt, maybe_gt and maybe_ne are irreflexive, so for example:

     !maybe_lt (A, A)

is true for all A.  maybe_le, maybe_eq and maybe_ge are reflexive, so for example:

     maybe_le (A, A)

is true for all A.  maybe_eq and maybe_ne are symmetric, so:

     maybe_eq (A, B) == maybe_eq (B, A)
     maybe_ne (A, B) == maybe_ne (B, A)

for all A and B.  In addition:

     maybe_le (A, B) == maybe_lt (A, B) || maybe_eq (A, B)
     maybe_ge (A, B) == maybe_gt (A, B) || maybe_eq (A, B)
     maybe_lt (A, B) == maybe_gt (B, A)
     maybe_le (A, B) == maybe_ge (B, A)

However:

     maybe_le (A, B) && maybe_le (B, A) does not imply !maybe_ne (A, B) [== known_eq (A, B)]
     maybe_ge (A, B) && maybe_ge (B, A) does not imply !maybe_ne (A, B) [== known_eq (A, B)]

One example is again A == 3 + 4X and B == 1 + 5X, where maybe_le (A, B), maybe_ge (A, B) and maybe_ne (A, B) all hold.  maybe_le and maybe_ge are therefore not antisymetric and do not form a partial order.

From the above, it follows that:

  * All ``known'' relations except known_ne are transitive.

  * known_lt, known_ne and known_gt are irreflexive.

  * known_le, known_eq and known_ge are reflexive.

Also:

     known_lt (A, B) == known_gt (B, A)
     known_le (A, B) == known_ge (B, A)
     known_lt (A, B) implies !known_lt (B, A)  [asymmetry]
     known_gt (A, B) implies !known_gt (B, A)
     known_le (A, B) && known_le (B, A) == known_eq (A, B) [== !maybe_ne (A, B)]
     known_ge (A, B) && known_ge (B, A) == known_eq (A, B) [== !maybe_ne (A, B)]

known_le and known_ge are therefore antisymmetric and are partial orders.  However:

     known_le (A, B) does not imply known_lt (A, B) || known_eq (A, B)
     known_ge (A, B) does not imply known_gt (A, B) || known_eq (A, B)

For example, known_le (4, 4 + 4X) holds because the runtime indeterminate X is a nonnegative integer, but neither known_lt (4, 4 + 4X) nor known_eq (4, 4 + 4X) hold.

Comparing potentially-unordered poly_ints
-----------------------------------------

In cases where there is no definite link between two poly_ints, we can usually make a conservatively-correct assumption.  For example, the conservative assumption for alias analysis is that two references might alias.

One way of checking whether [BEGIN1, END1) might overlap [BEGIN2, END2) using the poly_int comparisons is:

     maybe_gt (END1, BEGIN2) && maybe_gt (END2, BEGIN1)

and another (equivalent) way is:

     !(known_le (END1, BEGIN2) || known_le (END2, BEGIN1))

However, in this particular example, it is better to use the range helper functions instead.  See Range checks on poly_ints.

Comparing ordered poly_ints
---------------------------

In cases where there is a definite link between two poly_ints, such as the outer and inner sizes of subregs, we usually require the sizes to be ordered by the known_le partial order.  poly_int provides the following utility functions for ordered values:

ordered_p (A, B)
     Return true if A and B are ordered by the known_le partial order.

ordered_min (A, B)
     Assert that A and B are ordered by known_le and return the minimum of the two.  When using this function, please add a comment explaining why the values are known to be ordered.

ordered_max (A, B)
     Assert that A and B are ordered by known_le and return the maximum of the two.  When using this function, please add a comment explaining why the values are known to be ordered.

For example, if a subreg has an outer mode of size OUTER and an inner mode of size INNER:

  * the subreg is complete if known_eq (INNER, OUTER)

  * otherwise, the subreg is paradoxical if known_le (INNER, OUTER)

  * otherwise, the subreg is partial if known_le (OUTER, INNER)

  * otherwise, the subreg is ill-formed

Thus the subreg is only valid if ordered_p (OUTER, INNER) is true.  If this condition is already known to be true then:

  * the subreg is complete if known_eq (INNER, OUTER)

  * the subreg is paradoxical if maybe_lt (INNER, OUTER)

  * the subreg is partial if maybe_lt (OUTER, INNER)

with the three conditions being mutually exclusive.

Code that checks whether a subreg is valid would therefore generally check whether ordered_p holds (in addition to whatever other checks are required for subreg validity).  Code that is dealing with existing subregs can assert that ordered_p holds and use either of the classifications above.

Checking for a poly_int marker value
------------------------------------

It is sometimes useful to have a special ``marker value'' that is not meant to be taken literally.  For example, some code uses a size of -1 to represent an unknown size, rather than having to carry around a separate boolean to say whether the size is known.

The best way of checking whether something is a marker value is known_eq.  Conversely the best way of checking whether something is not a marker value is maybe_ne.

Thus in the size example just mentioned, known_eq (size, -1) would check for an unknown size and maybe_ne (size, -1) would check for a known size.

Range checks on poly_ints
-------------------------

As well as the core comparisons (see Comparison functions for poly_int), poly_int provides utilities for various kinds of range check.  In each case the range is represented by a start position and a size rather than a start position and an end position; this is because the former is used much more often than the latter in GCC.  Also, the sizes can be -1 (or all ones for unsigned sizes) to indicate a range with a known start position but an unknown size.  All other sizes must be nonnegative. A range of size 0 does not contain anything or overlap anything.

known_size_p (SIZE)
     Return true if SIZE represents a known range size, false if it is -1 or all ones (for signed and unsigned types respectively).

ranges_maybe_overlap_p (POS1, SIZE1, POS2, SIZE2)
     Return true if the range described by POS1 and SIZE1 might overlap the range described by POS2 and SIZE2 (in other words, return true if we cannot prove that the ranges are disjoint).

ranges_known_overlap_p (POS1, SIZE1, POS2, SIZE2)
     Return true if the range described by POS1 and SIZE1 is known to overlap the range described by POS2 and SIZE2.

known_subrange_p (POS1, SIZE1, POS2, SIZE2)
     Return true if the range described by POS1 and SIZE1 is known to be contained in the range described by POS2 and SIZE2.

maybe_in_range_p (VALUE, POS, SIZE)
     Return true if VALUE might be in the range described by POS and SIZE (in other words, return true if we cannot prove that VALUE is outside that range).

known_in_range_p (VALUE, POS, SIZE)
     Return true if VALUE is known to be in the range described by POS and SIZE.

endpoint_representable_p (POS, SIZE)
     Return true if the range described by POS and SIZE is open-ended or if the endpoint (POS + SIZE) is representable in the same type as POS and SIZE.  The function returns false if adding SIZE to POS makes conceptual sense but could overflow.

There is also a poly_int version of the IN_RANGE_P macro:

coeffs_in_range_p (X, LOWER, UPPER)
     Return true if every coefficient of X is in the inclusive range [LOWER, UPPER].  This function can be useful when testing whether an operation would cause the values of coefficients to overflow.

     Note that the function does not indicate whether X itself is in the given range.  X can be either a constant or a poly_int.

Sorting poly_ints
-----------------

poly_int provides the following routine for sorting:

compare_sizes_for_sort (A, B)
     Compare A and B in reverse lexicographical order (that is, compare the highest-indexed coefficients first).  This can be useful when sorting data structures, since it has the effect of separating constant and non-constant values.  If all values are nonnegative, the constant values come first.

     Note that the values do not necessarily end up in numerical order. For example, 1 + 1X would come after 100 in the sort order, but may well be less than 100 at run time.

Arithmetic on poly_ints
=======================

Addition, subtraction, negation and bit inversion all work normally for poly_ints.  Multiplication by a constant multiplier and left shifting by a constant shift amount also work normally.  General multiplication of two poly_ints is not supported and is not useful in practice.

Other operations are only conditionally supported: the operation might succeed or might fail, depending on the inputs.

This section describes both types of operation.

Using poly_int with C++ arithmetic operators
--------------------------------------------

The following C++ expressions are supported, where P1 and P2 are poly_ints and where C1 and C2 are scalars:

     -P1
     ~P1

     P1 + P2
     P1 + C2
     C1 + P2

     P1 - P2
     P1 - C2
     C1 - P2

     C1 * P2
     P1 * C2

     P1 << C2

     P1 += P2
     P1 += C2

     P1 -= P2
     P1 -= C2

     P1 *= C2
     P1 <<= C2

These arithmetic operations handle integer ranks in a similar way to C++.  The main difference is that every coefficient narrower than HOST_WIDE_INT promotes to HOST_WIDE_INT, whereas in C++ everything narrower than int promotes to int. For example:

     poly_uint16     + int          -> poly_int64
     unsigned int    + poly_uint16  -> poly_int64
     poly_int64      + int          -> poly_int64
     poly_int32      + poly_uint64  -> poly_uint64
     uint64          + poly_int64   -> poly_uint64
     poly_offset_int + int32        -> poly_offset_int
     offset_int      + poly_uint16  -> poly_offset_int

In the first two examples, both coefficients are narrower than HOST_WIDE_INT, so the result has coefficients of type HOST_WIDE_INT.  In the other examples, the coefficient with the highest rank ``wins''.

If one of the operands is wide_int or poly_wide_int, the rules are the same as for wide_int arithmetic.

wi arithmetic on poly_ints
--------------------------

As well as the C++ operators, poly_int supports the following wi routines:

     wi::neg (P1, &OVERFLOW)

     wi::add (P1, P2)
     wi::add (P1, C2)
     wi::add (C1, P1)
     wi::add (P1, P2, SIGN, &OVERFLOW)

     wi::sub (P1, P2)
     wi::sub (P1, C2)
     wi::sub (C1, P1)
     wi::sub (P1, P2, SIGN, &OVERFLOW)

     wi::mul (P1, C2)
     wi::mul (C1, P1)
     wi::mul (P1, C2, SIGN, &OVERFLOW)

     wi::lshift (P1, C2)

These routines just check whether overflow occurs on any individual coefficient; it is not possible to know at compile time whether the final runtime value would overflow.

Division of poly_ints
---------------------

Division of poly_ints is possible for certain inputs.  The functions for division return true if the operation is possible and in most cases return the results by pointer.  The routines are:

multiple_p (A, B)
multiple_p (A, B, &QUOTIENT)
     Return true if A is an exact multiple of B, storing the result in QUOTIENT if so.  There are overloads for various combinations of polynomial and constant A, B and QUOTIENT.

constant_multiple_p (A, B)
constant_multiple_p (A, B, &QUOTIENT)
     Like multiple_p, but also test whether the multiple is a compile-time constant.

can_div_trunc_p (A, B, &QUOTIENT)
can_div_trunc_p (A, B, &QUOTIENT, &REMAINDER)
     Return true if we can calculate trunc (A / B) at compile time, storing the result in QUOTIENT and REMAINDER if so.

can_div_away_from_zero_p (A, B, &QUOTIENT)
     Return true if we can calculate A / B at compile time, rounding away from zero.  Store the result in QUOTIENT if so.

     Note that this is true if and only if can_div_trunc_p is true. The only difference is in the rounding of the result.

There is also an asserting form of division:

exact_div (A, B)
     Assert that A is a multiple of B and return A / B.  The result is a poly_int if A is a poly_int.

Other poly_int arithmetic
-------------------------

There are tentative routines for other operations besides division:

can_ior_p (A, B, &RESULT)
     Return true if we can calculate A | B at compile time, storing the result in RESULT if so.

Also, ANDs with a value (1 << Y) - 1 or its inverse can be treated as alignment operations.  See Alignment of poly_ints.

In addition, the following miscellaneous routines are available:

coeff_gcd (A)
     Return the greatest common divisor of all nonzero coefficients in A, or zero if A is known to be zero.

common_multiple (A, B)
     Return a value that is a multiple of both A and B, where one value is a poly_int and the other is a scalar.  The result will be the least common multiple for some indeterminate values but not necessarily for all.

force_common_multiple (A, B)
     Return a value that is a multiple of both poly_int A and poly_int B, asserting that such a value exists.  The result will be the least common multiple for some indeterminate values but not necessarily for all.

     When using this routine, please add a comment explaining why the assertion is known to hold.

Please add any other operations that you find to be useful.

Alignment of poly_ints
======================

poly_int provides various routines for aligning values and for querying misalignments.  In each case the alignment must be a power of 2.

can_align_p (VALUE, ALIGN)
     Return true if we can align VALUE up or down to the nearest multiple of ALIGN at compile time.  The answer is the same for both directions.

can_align_down (VALUE, ALIGN, &ALIGNED)
     Return true if can_align_p; if so, set ALIGNED to the greatest aligned value that is less than or equal to VALUE.

can_align_up (VALUE, ALIGN, &ALIGNED)
     Return true if can_align_p; if so, set ALIGNED to the lowest aligned value that is greater than or equal to VALUE.

known_equal_after_align_down (A, B, ALIGN)
     Return true if we can align A and B down to the nearest ALIGN boundary at compile time and if the two results are equal.

known_equal_after_align_up (A, B, ALIGN)
     Return true if we can align A and B up to the nearest ALIGN boundary at compile time and if the two results are equal.

aligned_lower_bound (VALUE, ALIGN)
     Return a result that is no greater than VALUE and that is aligned to ALIGN.  The result will the closest aligned value for some indeterminate values but not necessarily for all.

     For example, suppose we are allocating an object of SIZE bytes in a downward-growing stack whose current limit is given by LIMIT. If the object requires ALIGN bytes of alignment, the new stack limit is given by:

          aligned_lower_bound (LIMIT - SIZE, ALIGN)

aligned_upper_bound (VALUE, ALIGN)
     Likewise return a result that is no less than VALUE and that is aligned to ALIGN.  This is the routine that would be used for upward-growing stacks in the scenario just described.

known_misalignment (VALUE, ALIGN, &MISALIGN)
     Return true if we can calculate the misalignment of VALUE with respect to ALIGN at compile time, storing the result in MISALIGN if so.

known_alignment (VALUE)
     Return the minimum alignment that VALUE is known to have (in other words, the largest alignment that can be guaranteed whatever the values of the indeterminates turn out to be). Return 0 if VALUE is known to be 0.

force_align_down (VALUE, ALIGN)
     Assert that VALUE can be aligned down to ALIGN at compile time and return the result.  When using this routine, please add a comment explaining why the assertion is known to hold.

force_align_up (VALUE, ALIGN)
     Likewise, but aligning up.

force_align_down_and_div (VALUE, ALIGN)
     Divide the result of force_align_down by ALIGN.  Again, please add a comment explaining why the assertion in force_align_down is known to hold.

force_align_up_and_div (VALUE, ALIGN)
     Likewise for force_align_up.

force_get_misalignment (VALUE, ALIGN)
     Assert that we can calculate the misalignment of VALUE with respect to ALIGN at compile time and return the misalignment. When using this function, please add a comment explaining why the assertion is known to hold.

Computing bounds on poly_ints
=============================

poly_int also provides routines for calculating lower and upper bounds:

constant_lower_bound (A)
     Assert that A is nonnegative and return the smallest value it can have.

lower_bound (A, B)
     Return a value that is always less than or equal to both A and B. It will be the greatest such value for some indeterminate values but necessarily for all.

upper_bound (A, B)
     Return a value that is always greater than or equal to both A and B.  It will be the least such value for some indeterminate values but necessarily for all.

Converting poly_ints
====================

A poly_int<N, T> can be constructed from up to N individual T coefficients, with the remaining coefficients being implicitly zero.  In particular, this means that every poly_int<N, T> can be constructed from a single scalar T, or something compatible with T.

Also, a poly_int<N, T> can be constructed from a poly_int<N, U> if T can be constructed from U.

The following functions provide other forms of conversion, or test whether such a conversion would succeed.

VALUE.is_constant ()
     Return true if poly_int VALUE is a compile-time constant.

VALUE.is_constant (&C1)
     Return true if poly_int VALUE is a compile-time constant, storing it in C1 if so.  C1 must be able to hold all constant values of VALUE without loss of precision.

VALUE.to_constant ()
     Assert that VALUE is a compile-time constant and return its value. When using this function, please add a comment explaining why the condition is known to hold (for example, because an earlier phase of analysis rejected non-constants).

VALUE.to_shwi (&P2)
     Return true if poly_int<N, T> VALUE can be represented without loss of precision as a poly_int<N, HOST_WIDE_INT>, storing it in that form in P2 if so.

VALUE.to_uhwi (&P2)
     Return true if poly_int<N, T> VALUE can be represented without loss of precision as a poly_int<N, unsigned HOST_WIDE_INT>, storing it in that form in P2 if so.

VALUE.force_shwi ()
     Forcibly convert each coefficient of poly_int<N, T> VALUE to HOST_WIDE_INT, truncating any that are out of range. Return the result as a poly_int<N, HOST_WIDE_INT>.

VALUE.force_uhwi ()
     Forcibly convert each coefficient of poly_int<N, T> VALUE to unsigned HOST_WIDE_INT, truncating any that are out of range.  Return the result as a poly_int<N, unsigned HOST_WIDE_INT>.

wi::shwi (VALUE, PRECISION)
     Return a poly_int with the same value as VALUE, but with the coefficients converted from HOST_WIDE_INT to wide_int. PRECISION specifies the precision of the wide_int cofficients; if this is wider than a HOST_WIDE_INT, the coefficients of VALUE will be sign-extended to fit.

wi::uhwi (VALUE, PRECISION)
     Like wi::shwi, except that VALUE has coefficients of type unsigned HOST_WIDE_INT.  If PRECISION is wider than a HOST_WIDE_INT, the coefficients of VALUE will be zero-extended to fit.

wi::sext (VALUE, PRECISION)
     Return a poly_int of the same type as VALUE, sign-extending every coefficient from the low PRECISION bits.  This in effect applies wi::sext to each coefficient individually.

wi::zext (VALUE, PRECISION)
     Like wi::sext, but for zero extension.

poly_wide_int::from (VALUE, PRECISION, SIGN)
     Convert VALUE to a poly_wide_int in which each coefficient has PRECISION bits.  Extend the coefficients according to SIGN if the coefficients have fewer bits.

poly_offset_int::from (VALUE, SIGN)
     Convert VALUE to a poly_offset_int, extending its coefficients according to SIGN if they have fewer bits than offset_int.

poly_widest_int::from (VALUE, SIGN)
     Convert VALUE to a poly_widest_int, extending its coefficients according to SIGN if they have fewer bits than widest_int.

Miscellaneous poly_int routines
===============================

print_dec (VALUE, FILE, SIGN)
print_dec (VALUE, FILE)
     Print VALUE to FILE as a decimal value, interpreting the coefficients according to SIGN.  The final argument is optional if VALUE has an inherent sign; for example, poly_int64 values print as signed by default and poly_uint64 values print as unsigned by default.

     This is a simply a poly_int version of a wide-int routine.

Guidelines for using poly_int
=============================

One of the main design goals of poly_int was to make it easy to write target-independent code that handles variable-sized registers even when the current target has fixed-sized registers.  There are two aspects to this:

  * The set of poly_int operations should be complete enough that the question in most cases becomes ``Can we do this operation on these particular poly_int values?  If not, bail out'' rather than ``Are these poly_int values constant?  If so, do the operation, otherwise bail out''.

  * If target-independent code compiles and runs correctly on a target with one value of NUM_POLY_INT_COEFFS, and if the code does not use asserting functions like to_constant, it is reasonable to assume that the code also works on targets with other values of NUM_POLY_INT_COEFFS.  There is no need to check this during everyday development.

So the general principle is: if target-independent code is dealing with a poly_int value, it is better to operate on it as a poly_int if at all possible, choosing conservatively-correct behavior if a particular operation fails.  For example, the following code handles an index pos into a sequence of vectors that each have nunits elements:

     /* Calculate which vector contains the result, and which lane of
        that vector we need.  */
     if (!can_div_trunc_p (pos, nunits, &vec_entry, &vec_index))
       {
         if (dump_enabled_p ())
           dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
                            "Cannot determine which vector holds the"
                            " final result.\n");
         return false;
       }

However, there are some contexts in which operating on a poly_int is not possible or does not make sense.  One example is when handling static initializers, since no current target supports the concept of a variable-length static initializer.  In these situations, a reasonable fallback is:

     if (POLY_VALUE.is_constant (&CONST_VALUE))
       {
         ...
         /* Operate on CONST_VALUE.  */
         ...
       }
     else
       {
         ...
         /* Conservatively correct fallback.  */
         ...
       }

poly_int also provides some asserting functions like to_constant.  Please only use these functions if there is a good theoretical reason to believe that the assertion cannot fire. For example, if some work is divided into an analysis phase and an implementation phase, the analysis phase might reject inputs that are not is_constant, in which case the implementation phase can reasonably use to_constant on the remaining inputs.  The assertions should not be used to discover whether a condition ever occurs ``in the field''; in other words, they should not be used to restrict code to constants at first, with the intention of only implementing a poly_int version if a user hits the assertion.

If a particular asserting function like to_constant is needed more than once for the same reason, it is probably worth adding a helper function or macro for that situation, so that the justification only needs to be given once.  For example:

     /* Return the size of an element in a vector of size SIZE, given that
        the vector has NELTS elements.  The return value is in the same units
        as SIZE (either bits or bytes).

        to_constant () is safe in this situation because vector elements are
        always constant-sized scalars.  */
     #define vector_element_size(SIZE, NELTS) \
       (exact_div (SIZE, NELTS).to_constant ())

Target-specific code in config/CPU only needs to handle non-constant poly_ints if NUM_POLY_INT_COEFFS is greater than one.  For other targets, poly_int degenerates to a compile-time constant and is often interchangable with a normal scalar integer. There are two main exceptions:

  * Sometimes an explicit cast to an integer type might be needed, such as to resolve ambiguities in a ?: expression, or when passing values through ... to things like print functions.

  * Target macros are included in target-independent code and so do not have access to the implicit conversion to a scalar integer. If this becomes a problem for a particular target macro, the possible solutions, in order of preference, are:

       * Convert the target macro to a target hook (for all targets).

       * Put the target's implementation of the target macro in its CPU.c file and call it from the target macro in the CPU.h file.

       * Add to_constant () calls where necessary.  The previous option is preferable because it will help with any future conversion of the macro to a hook.