#ifndef GCC_TREE_FOLD_H
#define GCC_TREE_FOLD_H
extern tree tree_fold_lcm (tree, tree);
extern tree tree_fold_gcd (tree, tree);
extern tree tree_fold_bezout (tree, tree, tree *, tree *, tree *, tree *);
extern tree tree_fold_factorial (tree);
static inline tree
tree_fold_plus (tree type,
tree a,
tree b)
{
tree res = fold (build (PLUS_EXPR, type, a, b));
if (TREE_CODE (res) == NON_LVALUE_EXPR)
return TREE_OPERAND (res, 0);
else
return res;
}
static inline tree
tree_fold_minus (tree type,
tree a,
tree b)
{
tree res = fold (build (MINUS_EXPR, type, a, b));
if (TREE_CODE (res) == NON_LVALUE_EXPR)
return TREE_OPERAND (res, 0);
else
return res;
}
static inline tree
tree_fold_multiply (tree type,
tree a,
tree b)
{
tree res = fold (build (MULT_EXPR, type, a, b));
if (TREE_CODE (res) == NON_LVALUE_EXPR)
return TREE_OPERAND (res, 0);
else
return res;
}
static inline tree
tree_fold_trunc_div (tree type,
tree a,
tree b)
{
return fold (build (TRUNC_DIV_EXPR, type, a, b));
}
static inline tree
tree_fold_ceil_div (tree type,
tree a,
tree b)
{
return fold (build (CEIL_DIV_EXPR, type, a, b));
}
static inline tree
tree_fold_floor_div (tree type,
tree a,
tree b)
{
return fold (build (FLOOR_DIV_EXPR, type, a, b));
}
static inline tree
tree_fold_exact_div (tree type,
tree a,
tree b)
{
return fold (build (EXACT_DIV_EXPR, type, a, b));
}
static inline tree
tree_fold_min (tree type,
tree a,
tree b)
{
return fold (build (MIN_EXPR, type, a, b));
}
static inline tree
tree_fold_max (tree type,
tree a,
tree b)
{
return fold (build (MAX_EXPR, type, a, b));
}
static inline tree
tree_fold_abs (tree type,
tree a)
{
return fold (build1 (ABS_EXPR, type, a));
}
static inline tree
tree_fold_binomial (tree n,
tree k)
{
return tree_fold_exact_div
(integer_type_node, tree_fold_factorial (n),
tree_fold_multiply
(integer_type_node, tree_fold_factorial (k),
tree_fold_factorial
(tree_fold_minus (integer_type_node, n, k))));
}
static inline bool
tree_fold_divides_p (tree type,
tree a,
tree b)
{
if (integer_onep (a))
return true;
return integer_zerop
(tree_fold_minus
(type, a, tree_fold_gcd (a, b)));
}
static inline bool
tree_is_ge (tree a, tree b, bool *res)
{
tree cmp = fold (build (GE_EXPR, boolean_type_node, a, b));
if (TREE_CODE (cmp) != INTEGER_CST)
return false;
*res = (tree_int_cst_sgn (cmp) != 0);
return true;
}
static inline bool
tree_is_gt (tree a, tree b, bool *res)
{
tree cmp = fold (build (GT_EXPR, boolean_type_node, a, b));
if (TREE_CODE (cmp) != INTEGER_CST)
return false;
*res = (tree_int_cst_sgn (cmp) != 0);
return true;
}
static inline bool
tree_is_le (tree a, tree b, bool *res)
{
tree cmp = fold (build (LE_EXPR, boolean_type_node, a, b));
if (TREE_CODE (cmp) != INTEGER_CST)
return false;
*res = (tree_int_cst_sgn (cmp) != 0);
return true;
}
static inline bool
tree_is_lt (tree a, tree b, bool *res)
{
tree cmp = fold (build (LT_EXPR, boolean_type_node, a, b));
if (TREE_CODE (cmp) != INTEGER_CST)
return false;
*res = (tree_int_cst_sgn (cmp) != 0);
return true;
}
static inline bool
tree_is_eq (tree a, tree b, bool *res)
{
tree cmp = fold (build (EQ_EXPR, boolean_type_node, a, b));
if (TREE_CODE (cmp) != INTEGER_CST)
return false;
*res = (tree_int_cst_sgn (cmp) != 0);
return true;
}
static inline bool
tree_is_ne (tree a, tree b, bool *res)
{
tree cmp = fold (build (NE_EXPR, boolean_type_node, a, b));
if (TREE_CODE (cmp) != INTEGER_CST)
return false;
*res = (tree_int_cst_sgn (cmp) != 0);
return true;
}
#endif