+/* Return the precision needed to represent the value VAL. */
+
+static int
+precision_for_value (mpz_t val)
+{
+ mpz_t x, y, two;
+ int precision;
+
+ value_init (x);
+ value_init (y);
+ value_init (two);
+ value_set_si (x, 2);
+ value_assign (y, val);
+ value_set_si (two, 2);
+ precision = 1;
+
+ if (value_neg_p (y))
+ value_oppose (y, y);
+
+ while (value_gt (y, x))
+ {
+ value_multiply (x, x, two);
+ precision++;
+ }
+
+ value_clear (x);
+ value_clear (y);
+ value_clear (two);
+
+ return precision;
+}
+
+/* Return the precision needed to represent the values between LOW and
+ UP. */
+
+static int
+precision_for_interval (mpz_t low, mpz_t up)
+{
+ mpz_t diff;
+ int precision;
+
+ gcc_assert (value_le (low, up));
+
+ value_init (diff);
+ value_subtract (diff, up, low);
+ precision = precision_for_value (diff);
+ value_clear (diff);
+
+ return precision;
+}
+
+/* Return a type that could represent the integer value VAL, or
+ otherwise return NULL_TREE. */
+
+static tree
+gcc_type_for_interval (mpz_t low, mpz_t up, tree old_type)
+{
+ bool unsigned_p = true;
+ int precision, prec_up, prec_int;
+ tree type;
+
+ gcc_assert (value_le (low, up));
+
+ /* Preserve the signedness of the old IV. */
+ if ((old_type && !TYPE_UNSIGNED (old_type))
+ || value_neg_p (low))
+ unsigned_p = false;
+
+ prec_up = precision_for_value (up);
+ prec_int = precision_for_interval (low, up);
+ precision = prec_up > prec_int ? prec_up : prec_int;
+
+ type = lang_hooks.types.type_for_size (precision, unsigned_p);
+ if (!type)
+ {
+ gloog_error = true;
+ return integer_type_node;
+ }
+
+ return type;
+}
+
+/* Return a type that could represent the integer value VAL, or
+ otherwise return NULL_TREE. */
+
+static tree
+gcc_type_for_value (mpz_t val)
+{
+ return gcc_type_for_interval (val, val, NULL_TREE);
+}
+
+/* Return the type for the clast_term T used in STMT. */
+
+static tree
+gcc_type_for_clast_term (struct clast_term *t,
+ sese region, VEC (tree, heap) *newivs,
+ htab_t newivs_index, htab_t params_index)
+{
+ gcc_assert (t->expr.type == expr_term);
+
+ if (!t->var)
+ return gcc_type_for_value (t->val);
+
+ return TREE_TYPE (clast_name_to_gcc (t->var, region, newivs,
+ newivs_index, params_index));
+}
+
+static tree
+gcc_type_for_clast_expr (struct clast_expr *, sese,
+ VEC (tree, heap) *, htab_t, htab_t);
+
+/* Return the type for the clast_reduction R used in STMT. */
+
+static tree
+gcc_type_for_clast_red (struct clast_reduction *r, sese region,
+ VEC (tree, heap) *newivs,
+ htab_t newivs_index, htab_t params_index)
+{
+ int i;
+ tree type = NULL_TREE;
+
+ if (r->n == 1)
+ return gcc_type_for_clast_expr (r->elts[0], region, newivs,
+ newivs_index, params_index);
+
+ switch (r->type)
+ {
+ case clast_red_sum:
+ case clast_red_min:
+ case clast_red_max:
+ type = gcc_type_for_clast_expr (r->elts[0], region, newivs,
+ newivs_index, params_index);
+ for (i = 1; i < r->n; i++)
+ type = max_precision_type (type, gcc_type_for_clast_expr
+ (r->elts[i], region, newivs,
+ newivs_index, params_index));
+
+ return type;
+
+ default:
+ break;
+ }
+
+ gcc_unreachable ();
+ return NULL_TREE;
+}
+
+/* Return the type for the clast_binary B used in STMT. */
+
+static tree
+gcc_type_for_clast_bin (struct clast_binary *b,
+ sese region, VEC (tree, heap) *newivs,
+ htab_t newivs_index, htab_t params_index)
+{
+ tree l = gcc_type_for_clast_expr ((struct clast_expr *) b->LHS, region,
+ newivs, newivs_index, params_index);
+ tree r = gcc_type_for_value (b->RHS);
+ return max_signed_precision_type (l, r);
+}
+
+/* Returns the type for the CLAST expression E when used in statement
+ STMT. */