This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[tree-ssa] [RFC] An interface to fold (tree)


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);
}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]