add isl_aff_mod_val
[platform/upstream/isl.git] / isl_ast_build_expr.c
index 81688de..81d8fbf 100644 (file)
 #include <isl_ast_private.h>
 #include <isl_ast_build_private.h>
 
-/* Compute the minimum of the integer affine expression "obj" over the points
- * in build->domain and put the result in *opt.
- */
-enum isl_lp_result isl_ast_build_min(__isl_keep isl_ast_build *build,
-       __isl_keep isl_aff *obj, isl_int *opt)
-{
-       if (!build)
-               return isl_lp_error;
-
-       return isl_set_min(build->domain, obj, opt);
-}
-
-/* Compute the maximum of the integer affine expression "obj" over the points
- * in build->domain and put the result in *opt.
- */
-enum isl_lp_result isl_ast_build_max(__isl_keep isl_ast_build *build,
-       __isl_keep isl_aff *obj, isl_int *opt)
-{
-       if (!build)
-               return isl_lp_error;
-
-       return isl_set_max(build->domain, obj, opt);
-}
-
 /* Compute the "opposite" of the (numerator of the) argument of a div
  * with denonimator "d".
  *
@@ -582,18 +558,31 @@ static __isl_give isl_ast_expr *add_signed_terms(__isl_take isl_ast_expr *expr,
                }
        }
 
-       isl_aff_get_constant(aff, &v);
-       if (sign * isl_int_sgn(v) > 0) {
-               isl_int_abs(v, v);
-               expr = isl_ast_expr_add_int(expr, v);
-       }
-
        isl_local_space_free(ls);
        isl_int_clear(v);
 
        return expr;
 }
 
+/* Should the constant term "v" be considered positive?
+ *
+ * A positive constant will be added to "pos" by the caller,
+ * while a negative constant will be added to "neg".
+ * If either "pos" or "neg" is exactly zero, then we prefer
+ * to add the constant "v" to that side, irrespective of the sign of "v".
+ * This results in slightly shorter expressions and may reduce the risk
+ * of overflows.
+ */
+static int constant_is_considered_positive(isl_int v,
+       __isl_keep isl_ast_expr *pos, __isl_keep isl_ast_expr *neg)
+{
+       if (ast_expr_is_zero(pos))
+               return 1;
+       if (ast_expr_is_zero(neg))
+               return 0;
+       return isl_int_is_pos(v);
+}
+
 /* Construct an isl_ast_expr that evaluates the condition "constraint",
  * The result is simplified in terms of build->domain.
  *
@@ -613,6 +602,10 @@ static __isl_give isl_ast_expr *add_signed_terms(__isl_take isl_ast_expr *expr,
  * However, if the first expression is an integer constant (and the second
  * is not), then we swap the two expressions.  This ensures that we construct,
  * e.g., "i <= 5" rather than "5 >= i".
+ *
+ * Furthermore, is there are no terms with positive coefficients (or no terms
+ * with negative coefficients), then the constant term is added to "pos"
+ * (or "neg"), ignoring the sign of the constant term.
  */
 static __isl_give isl_ast_expr *isl_ast_expr_from_constraint(
        __isl_take isl_constraint *constraint, __isl_keep isl_ast_build *build)
@@ -622,6 +615,7 @@ static __isl_give isl_ast_expr *isl_ast_expr_from_constraint(
        isl_ast_expr *expr_neg;
        isl_ast_expr *expr;
        isl_aff *aff;
+       isl_int v;
        int eq;
        enum isl_ast_op_type type;
 
@@ -639,6 +633,16 @@ static __isl_give isl_ast_expr *isl_ast_expr_from_constraint(
        expr_pos = add_signed_terms(expr_pos, aff, 1, build);
        expr_neg = add_signed_terms(expr_neg, aff, -1, build);
 
+       isl_int_init(v);
+       isl_aff_get_constant(aff, &v);
+       if (constant_is_considered_positive(v, expr_pos, expr_neg)) {
+               expr_pos = isl_ast_expr_add_int(expr_pos, v);
+       } else {
+               isl_int_neg(v, v);
+               expr_neg = isl_ast_expr_add_int(expr_neg, v);
+       }
+       isl_int_clear(v);
+
        eq = isl_constraint_is_equality(constraint);
 
        if (isl_ast_expr_get_type(expr_pos) == isl_ast_expr_int &&