This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[tree-ssa] [RFC] An interface to fold (tree)
- From: Pop Sébastian <pop at gauvain dot u-strasbg dot fr>
- To: law at redhat dot com
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Mon, 6 Oct 2003 14:20:11 +0200
- Subject: [tree-ssa] [RFC] An interface to fold (tree)
- References: <200309301719.h8UHJhpW029478@speedy.slc.redhat.com>
Hi,
I have detected several similarities between the VRP patch and some parts
of the project on which I work. For example,
On Tue, Sep 30, 2003 at 11:19:43AM -0600, law@redhat.com wrote:
>
> + low = fold (build (MAX_EXPR, TREE_TYPE (low),
> + low, tmp_low));
> + high = fold (build (MIN_EXPR, TREE_TYPE (high),
> + high, tmp_high));
> +
What I propose is to use an interface for accessing a specific part of the
folder. For example instead of writing:
> + if (integer_onep (fold (build (GT_EXPR, boolean_type_node,
> + low, cond_low)))
one would write: "if (integer_onep (tree_fold_bool_gt (low, cond_low)))"
The following patch implements this idea for the folding of boolean and
integer operations.
2003-10-06 Sebastian Pop <pop@cri.ensmp.fr>
* tree-fold-const.h: New file.
* tree-fold-const.c: New file.
/* Fold GENERIC expressions.
Copyright (C) 2003 Free Software Foundation, Inc.
Contributed by Sebastian Pop <s.pop@laposte.net>
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
/* This file defines an interface of the tree folder.
For the moment, the functions in this file are just wrappers around
the "big-ugly" fold function. The final aim is to completely split
up the fold function into small pieces in such a way that client
passes don't see the changes to the underlying implementation. */
extern tree id_tree (tree);
/* Interface for boolean operations folding. */
static inline tree tree_fold_bool_lt (tree, tree);
static inline tree tree_fold_bool_le (tree, tree);
static inline tree tree_fold_bool_gt (tree, tree);
static inline tree tree_fold_bool_ge (tree, tree);
static inline tree tree_fold_bool_eq (tree, tree);
static inline tree tree_fold_bool_ne (tree, tree);
/* Interface for integer operations folding. */
extern tree tree_fold_int_lcm (tree, tree);
extern tree tree_fold_int_gcd (tree, tree);
static inline tree tree_fold_int_plus (tree, tree);
static inline tree tree_fold_int_minus (tree, tree);
static inline tree tree_fold_int_multiply (tree, tree);
static inline tree tree_fold_int_trunc_div (tree, tree);
static inline tree tree_fold_int_ceil_div (tree, tree);
static inline tree tree_fold_int_floor_div (tree, tree);
static inline tree tree_fold_int_round_div (tree, tree);
static inline tree tree_fold_int_trunc_mod (tree, tree);
static inline tree tree_fold_int_ceil_mod (tree, tree);
static inline tree tree_fold_int_floor_mod (tree, tree);
static inline tree tree_fold_int_round_mod (tree, tree);
static inline tree tree_fold_int_exact_div (tree, tree);
static inline tree tree_fold_int_min (tree, tree);
static inline tree tree_fold_int_max (tree, tree);
static inline tree
tree_fold_bool_lt (tree a,
tree b)
{
return fold (build (LT_EXPR, boolean_type_node, a, b));
}
static inline tree
tree_fold_bool_le (tree a,
tree b)
{
return fold (build (LE_EXPR, boolean_type_node, a, b));
}
static inline tree
tree_fold_bool_gt (tree a,
tree b)
{
return fold (build (GT_EXPR, boolean_type_node, a, b));
}
static inline tree
tree_fold_bool_ge (tree a,
tree b)
{
return fold (build (GE_EXPR, boolean_type_node, a, b));
}
static inline tree
tree_fold_bool_eq (tree a,
tree b)
{
return fold (build (EQ_EXPR, boolean_type_node, a, b));
}
static inline tree
tree_fold_bool_ne (tree a,
tree b)
{
return fold (build (NE_EXPR, boolean_type_node, a, b));
}
/* Fold the addition. */
static inline tree
tree_fold_int_plus (tree a,
tree b)
{
return fold (build (PLUS_EXPR, integer_type_node, a, b));
}
/* Fold the substraction. */
static inline tree
tree_fold_int_minus (tree a,
tree b)
{
return fold (build (MINUS_EXPR, integer_type_node, a, b));
}
/* Fold the multiplication. */
static inline tree
tree_fold_int_multiply (tree a,
tree b)
{
return fold (build (MULT_EXPR, integer_type_node, a, b));
}
/* Division for integer result that rounds the quotient toward zero. */
static inline tree
tree_fold_int_trunc_div (tree a,
tree b)
{
return fold (build (TRUNC_DIV_EXPR, integer_type_node, a, b));
}
/* Division for integer result that rounds the quotient toward infinity. */
static inline tree
tree_fold_int_ceil_div (tree a,
tree b)
{
return fold (build (CEIL_DIV_EXPR, integer_type_node, a, b));
}
/* Division for integer result that rounds toward minus infinity. */
static inline tree
tree_fold_int_floor_div (tree a,
tree b)
{
return fold (build (FLOOR_DIV_EXPR, integer_type_node, a, b));
}
/* Division for integer result that rounds toward nearest integer. */
static inline tree
tree_fold_int_round_div (tree a,
tree b)
{
return fold (build (ROUND_DIV_EXPR, integer_type_node, a, b));
}
/* Remainder of the division for integer result that rounds the quotient
toward zero. */
static inline tree
tree_fold_int_trunc_mod (tree a,
tree b)
{
return fold (build (TRUNC_MOD_EXPR, integer_type_node, a, b));
}
/* Remainder of the division for integer result that rounds the quotient
toward infinity. */
static inline tree
tree_fold_int_ceil_mod (tree a,
tree b)
{
return fold (build (CEIL_MOD_EXPR, integer_type_node, a, b));
}
/* Remainder of the division for integer result that rounds the quotient
toward minus infinity. */
static inline tree
tree_fold_int_floor_mod (tree a,
tree b)
{
return fold (build (FLOOR_MOD_EXPR, integer_type_node, a, b));
}
/* Remainder of the division for integer result that rounds the quotient
toward nearest integer. */
static inline tree
tree_fold_int_round_mod (tree a,
tree b)
{
return fold (build (ROUND_MOD_EXPR, integer_type_node, a, b));
}
/* Division which is not supposed to need rounding. */
static inline tree
tree_fold_int_exact_div (tree a,
tree b)
{
return fold (build (EXACT_DIV_EXPR, integer_type_node, a, b));
}
/* Computes the minimum. */
static inline tree
tree_fold_int_min (tree a,
tree b)
{
return fold (build (MIN_EXPR, integer_type_node, a, b));
}
/* Computes the maximum. */
static inline tree
tree_fold_int_max (tree a,
tree b)
{
return fold (build (MAX_EXPR, integer_type_node, a, b));
}
/* Fold GENERIC expressions.
Copyright (C) 2003 Free Software Foundation, Inc.
Contributed by Sebastian Pop <s.pop@laposte.net>
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "errors.h"
#include "ggc.h"
#include "tree.h"
#include "tree-fold-const.h"
/* Debugging functions. */
/* This is the identity function. It can be used to insert breakpoints
in complex tree constructions such as those in the fold functions. */
tree
id_tree (tree t)
{
debug_generic_expr (t);
return t;
}
/* Least common multiple. */
tree
tree_fold_int_lcm (tree a,
tree b)
{
tree pgcd;
#if defined ENABLE_CHECKING
if (TREE_CODE (a) != INTEGER_CST
|| TREE_CODE (b) != INTEGER_CST)
abort ();
#endif
if (integer_onep (a))
return b;
if (integer_onep (b))
return a;
if (integer_zerop (a)
|| integer_zerop (b))
return integer_zero_node;
pgcd = tree_fold_int_gcd (a, b);
if (integer_onep (pgcd))
return tree_fold_int_multiply (a, b);
else
return tree_fold_int_multiply
(pgcd, tree_fold_int_lcm (tree_fold_int_exact_div (a, pgcd),
tree_fold_int_exact_div (b, pgcd)));
}
/* Greatest common divisor. */
tree
tree_fold_int_gcd (tree a,
tree b)
{
tree a_minus_b;
#if defined ENABLE_CHECKING
if (TREE_CODE (a) != INTEGER_CST
|| TREE_CODE (b) != INTEGER_CST)
abort ();
#endif
if (integer_zerop (a))
return b;
if (integer_zerop (b))
return a;
if (tree_int_cst_sgn (a) == -1)
a = tree_fold_int_multiply (a, integer_minus_one_node);
if (tree_int_cst_sgn (b) == -1)
b = tree_fold_int_multiply (b, integer_minus_one_node);
a_minus_b = tree_fold_int_minus (a, b);
if (integer_zerop (a_minus_b))
return a;
if (tree_int_cst_sgn (a_minus_b) == 1)
return tree_fold_int_gcd (a_minus_b, b);
return tree_fold_int_gcd (tree_fold_int_minus (b, a), a);
}