10.9 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:

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: