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] Sanitize selection of real and virtual operands


The mechanism used to determine whether an operand was real or virtual
has always been convoluted and error prone.  We do have a validity check
on our way out of SSA to make sure we haven't mixed them, but given an
arbitrary variable it's not clear whether that variable will be renamed
or not by just looking at it.

This patch changes that.  The interface is very simple, if a variable
complies with is_gimple_reg(), it will always be used in real operands
(i.e., renamed into SSA and subjected to the scalar optimizers). 
Otherwise, the variable will be added to virtual operands.

If a variable needs virtual operands (structures, arrays, aliased
variables), a second test is done to see whether it's aliased or not. 
If it's not aliased, then the variable itself is added.  Otherwise, its
aliases are referenced.

I also added two new predicates: is_gimple_call_clobbered and
is_gimple_non_addressable.  The first one is obvious, the second one
returns true if the variable is a local variable that does not need to
live in memory, but which is not necessarily a register variable (e.g. a
structure).

It should now be possible to do things like only dump PHIs for real
operands when the -vops is not present.  I have not implemented this,
though.

Bootstrapped and tested x86 and amd64.



	* gimplify.c (gimplify_call_expr): Change gimple_test_f argument to
	return bool type.
	(mark_decls_volatile_r): New local function.
	(gimplify_expr): Make gimple_test_f return bool type.
	Call mark_decls_volatile_r when gimplifying VA_ARG_EXPR.
	* tree-dfa.c (struct walk_state): Remove field is_va_arg_expr.
	Update all callers.
	(opf_force_vop): Remove.  Update all users.
	(add_stmt_operand): Re-structure to add real operands only for
	GIMPLE register variables.
	(find_vars_r): Don't handle VA_ARG_EXPR nodes.
	(add_referenced_var): Also assign a UID to variables with hidden
	uses.
	Call is_gimple_call_clobbered to determine if a variable is call
	clobbered.
	(get_memory_tag_for): Mark memory tags volatile and static.
	* tree-flow.h (struct var_ann_d): Remove field is_in_va_arg_expr.
	Update all users.
	* tree-simple.c (is_gimple_*): Change return type to bool.  Update
	all users.
	(is_gimple_reg_type): Return true only for non aggregate types.
	(is_gimple_non_addressable_1): New local function.
	(is_gimple_reg): Call it.
	(is_gimple_non_addressable): New function.
	(is_gimple_call_clobbered): New function.
	* tree-simple.h (is_gimple_*): Change return type to bool.

Index: gimplify.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/gimplify.c,v
retrieving revision 1.1.2.117
diff -d -c -p -r1.1.2.117 gimplify.c
*** gimplify.c	17 Nov 2003 16:33:41 -0000	1.1.2.117
--- gimplify.c	17 Nov 2003 18:53:39 -0000
*************** gimplify_self_mod_expr (tree *expr_p, tr
*** 1641,1647 ****
  
  static enum gimplify_status
  gimplify_call_expr (tree *expr_p, tree *pre_p, tree *post_p,
! 		    int (*gimple_test_f) (tree))
  {
    tree decl;
    tree arglist;
--- 1641,1647 ----
  
  static enum gimplify_status
  gimplify_call_expr (tree *expr_p, tree *pre_p, tree *post_p,
! 		    bool (*gimple_test_f) (tree))
  {
    tree decl;
    tree arglist;
*************** gimplify_to_stmt_list (tree *stmt_p)
*** 2732,2737 ****
--- 2732,2752 ----
      }
  }
  
+ 
+ /* Mark all the _DECL nodes under *TP as volatile.  FIXME: This must die
+    after VA_ARG_EXPRs are properly lowered.  */
+ 
+ static tree
+ mark_decls_volatile_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
+ 		       void *data ATTRIBUTE_UNUSED)
+ {
+   if (SSA_VAR_P (*tp))
+     TREE_THIS_VOLATILE (*tp) = 1;
+ 
+   return NULL_TREE;
+ }
+ 
+ 
  /*  Gimplifies the expression tree pointed by EXPR_P.  Return 0 if
      gimplification failed.
  
*************** gimplify_to_stmt_list (tree *stmt_p)
*** 2763,2769 ****
  
  enum gimplify_status
  gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p,
! 	       int (* gimple_test_f) (tree), fallback_t fallback)
  {
    tree tmp;
    tree internal_pre = NULL_TREE;
--- 2778,2784 ----
  
  enum gimplify_status
  gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p,
! 	       bool (* gimple_test_f) (tree), fallback_t fallback)
  {
    tree tmp;
    tree internal_pre = NULL_TREE;
*************** gimplify_expr (tree *expr_p, tree *pre_p
*** 2887,2892 ****
--- 2902,2913 ----
  	  break;
  
  	case VA_ARG_EXPR:
+ 	  /* Mark any _DECL inside the operand as volatile to avoid the
+ 	     optimizers messing around with it. FIXME: Remove this once
+ 	     VA_ARG_EXPRs are properly lowered.  */
+ 	  walk_tree (&TREE_OPERAND (*expr_p, 0), mark_decls_volatile_r,
+ 		     NULL, NULL);
+ 
  	  /* va_arg expressions are in GIMPLE form already.  */
  	  ret = GS_ALL_DONE;
  	  break;
Index: tree-dfa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-dfa.c,v
retrieving revision 1.1.4.177
diff -d -c -p -r1.1.4.177 tree-dfa.c
*** tree-dfa.c	16 Nov 2003 11:00:40 -0000	1.1.4.177
--- tree-dfa.c	17 Nov 2003 18:53:40 -0000
*************** struct walk_state
*** 91,99 ****
    /* Nonzero if the walker is inside a non-GIMPLE expression.  */
    int is_not_gimple : 1;
  
-   /* Nonzero if the walker is inside a VA_ARG_EXPR node.  */
-   int is_va_arg_expr : 1;
- 
    /* Hash table used to avoid adding the same variable more than once.  */
    htab_t vars_found;
  
--- 91,96 ----
*************** static const int opf_none	= 0;
*** 111,119 ****
  /* Operand is the target of an assignment expression.  */
  static const int opf_is_def 	= 1 << 0;
  
- /* Consider the operand virtual, regardless of aliasing information.  */
- static const int opf_force_vop	= 1 << 1;
- 
  /* Debugging dumps.  */
  static FILE *dump_file;
  static int dump_flags;
--- 108,113 ----
*************** get_expr_operands (tree stmt, tree *expr
*** 360,366 ****
  	return;
  
        /* Avoid recursion.  */
-       flags |= opf_force_vop;
        code = subcode;
        class = TREE_CODE_CLASS (code);
        expr_p = &TREE_OPERAND (expr, 0);
--- 354,359 ----
*************** get_expr_operands (tree stmt, tree *expr
*** 388,395 ****
  	    ptr = SSA_NAME_VAR (ptr);
  	  ann = var_ann (ptr);
  	  if (ann->mem_tag)
! 	    add_stmt_operand (&ann->mem_tag, stmt, flags|opf_force_vop,
! 			      prev_vops);
  	}
  
        /* If a constant is used as a pointer, we can't generate a real
--- 381,387 ----
  	    ptr = SSA_NAME_VAR (ptr);
  	  ann = var_ann (ptr);
  	  if (ann->mem_tag)
! 	    add_stmt_operand (&ann->mem_tag, stmt, flags, prev_vops);
  	}
  
        /* If a constant is used as a pointer, we can't generate a real
*************** get_expr_operands (tree stmt, tree *expr
*** 547,563 ****
  
  
  /* Add *VAR_P to the appropriate operand array of STMT.  FLAGS is as in
!    get_expr_operands.  The following are the rules used to decide
!    whether an operand belongs in OPS or VOPS:
! 
!    1- Non-aliased scalar and pointer variables are real operands.
! 
!    2- If a variable is aliased, all its aliases are added to the virtual
!       operands.
! 
!    3- For non-scalar variables (arrays, structures, unions and complex
!       types), their virtual variable (see get_virtual_var) is added to the
!       virtual operands.
  
     PREV_VOPS is used when adding virtual operands to statements that
        already had them (See add_vdef and add_vuse).  */
--- 539,547 ----
  
  
  /* Add *VAR_P to the appropriate operand array of STMT.  FLAGS is as in
!    get_expr_operands.  If *VAR_P is a GIMPLE register, it will be added to
!    the statement's real operands, otherwise it is added to virtual
!    operands.
  
     PREV_VOPS is used when adding virtual operands to statements that
        already had them (See add_vdef and add_vuse).  */
*************** get_expr_operands (tree stmt, tree *expr
*** 565,571 ****
  static void
  add_stmt_operand (tree *var_p, tree stmt, int flags, voperands_t prev_vops)
  {
!   bool is_scalar;
    tree var, sym;
    varray_type aliases;
    size_t i;
--- 549,555 ----
  static void
  add_stmt_operand (tree *var_p, tree stmt, int flags, voperands_t prev_vops)
  {
!   bool is_real_op;
    tree var, sym;
    varray_type aliases;
    size_t i;
*************** add_stmt_operand (tree *var_p, tree stmt
*** 588,597 ****
    /* If the original variable is not a scalar, it will be added to the list
       of virtual operands.  In that case, use its base symbol as the virtual
       variable representing it.  */
!   is_scalar = (SSA_VAR_P (var)
!                && !AGGREGATE_TYPE_P (TREE_TYPE (var))
! 	       && TREE_CODE (TREE_TYPE (var)) != COMPLEX_TYPE);
!   if (!is_scalar && !DECL_P (var))
      var = get_virtual_var (var);
  
    /* If VAR is not a variable that we care to optimize, do nothing.  */
--- 572,579 ----
    /* If the original variable is not a scalar, it will be added to the list
       of virtual operands.  In that case, use its base symbol as the virtual
       variable representing it.  */
!   is_real_op = is_gimple_reg (var);
!   if (!is_real_op && !DECL_P (var))
      var = get_virtual_var (var);
  
    /* If VAR is not a variable that we care to optimize, do nothing.  */
*************** add_stmt_operand (tree *var_p, tree stmt
*** 613,691 ****
        return;
      }
  
!   /* Globals, call-clobbered, local statics and variables referenced in
!      VA_ARG_EXPR are always accessed using virtual operands.  */
!   if (decl_function_context (sym) != current_function_decl
!       || TREE_STATIC (sym)
!       || v_ann->is_call_clobbered
!       || v_ann->is_in_va_arg_expr)
!     flags |= opf_force_vop;
! 
!   /* If the variable is an alias tag, it means that its address has been
!      taken and it's being accessed directly and via pointers.  To avoid
!      mixing real and virtual operands, we treat all references to aliased
!      variables as virtual.  */
!   if (v_ann->is_alias_tag)
!     flags |= opf_force_vop;
! 
!   aliases = v_ann->may_aliases;
!   if (aliases == NULL)
      {
!       /* The variable is not aliased.  Add it as a real operand (unless
! 	 opf_force_vop is set).  */
        if (flags & opf_is_def)
! 	{
! 	  if (is_scalar && !(flags & opf_force_vop))
! 	    add_def (var_p, stmt);
! 	  else
! 	    add_vdef (var, stmt, prev_vops);
! 
! 	  /* If the variable is an alias tag, mark the statement.  */
! 	  if (v_ann->is_alias_tag)
! 	    s_ann->makes_aliased_stores = 1;
! 	}
        else
! 	{
! 	  if (is_scalar
! 	      && !(flags & opf_force_vop))
! 	    add_use (var_p, stmt);
! 	  else
! 	    add_vuse (var, stmt, prev_vops);
! 
! 	  /* If the variable is an alias tag, mark the statement.  */
! 	  if (v_ann->is_alias_tag)
! 	    s_ann->makes_aliased_loads = 1;
! 	}
      }
    else
      {
!       if (VARRAY_ACTIVE_SIZE (aliases) == 0)
! 	abort ();
! 
!       /* The variable is aliased.  Add its aliases to the virtual operands.  */
!       if (flags & opf_is_def)
  	{
! 	  /* If the variable is also an alias tag, add a virtual operand
! 	     for it, otherwise we will miss representing references to the
! 	     members of the variable's alias set.  This fixes the bug in
! 	     gcc.c-torture/execute/20020503-1.c.  */
! 	  if (v_ann->is_alias_tag)
! 	    add_vdef (var, stmt, prev_vops);
! 
! 	  for (i = 0; i < VARRAY_ACTIVE_SIZE (aliases); i++)
! 	    add_vdef (VARRAY_TREE (aliases, i), stmt, prev_vops);
! 
! 	  s_ann->makes_aliased_stores = 1;
  	}
        else
  	{
! 	  if (v_ann->is_alias_tag)
! 	    add_vuse (var, stmt, prev_vops);
  
! 	  for (i = 0; i < VARRAY_ACTIVE_SIZE (aliases); i++)
! 	    add_vuse (VARRAY_TREE (aliases, i), stmt, prev_vops);
  
! 	  s_ann->makes_aliased_loads = 1;
  	}
      }
  }
--- 595,659 ----
        return;
      }
  
!   if (is_real_op)
      {
!       /* The variable is a GIMPLE register.  Add it to real operands.  */
        if (flags & opf_is_def)
! 	add_def (var_p, stmt);
        else
! 	add_use (var_p, stmt);
      }
    else
      {
!       /* The variable is not a GIMPLE register.  Add it (or its aliases) to
! 	 virtual operands.  */
!       aliases = v_ann->may_aliases;
!       if (aliases == NULL)
  	{
! 	  /* The variable is not aliased or it is an alias tag.  */
! 	  if (flags & opf_is_def)
! 	    {
! 	      add_vdef (var, stmt, prev_vops);
! 	      if (v_ann->is_alias_tag)
! 		s_ann->makes_aliased_stores = 1;
! 	    }
! 	  else
! 	    {
! 	      add_vuse (var, stmt, prev_vops);
! 	      if (v_ann->is_alias_tag)
! 		s_ann->makes_aliased_loads = 1;
! 	    }
  	}
        else
  	{
! 	  /* The variable is aliased.  Add its aliases to the virtual operands.  */
! 	  if (VARRAY_ACTIVE_SIZE (aliases) == 0)
! 	    abort ();
  
! 	  if (flags & opf_is_def)
! 	    {
! 	      /* If the variable is also an alias tag, add a virtual operand
! 		for it, otherwise we will miss representing references to the
! 		members of the variable's alias set.  This fixes the bug in
! 		gcc.c-torture/execute/20020503-1.c.  */
! 	      if (v_ann->is_alias_tag)
! 		add_vdef (var, stmt, prev_vops);
  
! 	      for (i = 0; i < VARRAY_ACTIVE_SIZE (aliases); i++)
! 		add_vdef (VARRAY_TREE (aliases, i), stmt, prev_vops);
! 
! 	      s_ann->makes_aliased_stores = 1;
! 	    }
! 	  else
! 	    {
! 	      if (v_ann->is_alias_tag)
! 		add_vuse (var, stmt, prev_vops);
! 
! 	      for (i = 0; i < VARRAY_ACTIVE_SIZE (aliases); i++)
! 		add_vuse (VARRAY_TREE (aliases, i), stmt, prev_vops);
! 
! 	      s_ann->makes_aliased_loads = 1;
! 	    }
  	}
      }
  }
*************** add_call_clobber_ops (tree stmt, voperan
*** 900,906 ****
       operand for every call clobbered variable.  See add_referenced_var for
       the heuristic used to decide whether to create .GLOBAL_VAR or not.  */
    if (global_var)
!     add_stmt_operand (&global_var, stmt, opf_force_vop|opf_is_def, prev_vops);
    else
      {
        size_t i;
--- 868,874 ----
       operand for every call clobbered variable.  See add_referenced_var for
       the heuristic used to decide whether to create .GLOBAL_VAR or not.  */
    if (global_var)
!     add_stmt_operand (&global_var, stmt, opf_is_def, prev_vops);
    else
      {
        size_t i;
*************** add_call_clobber_ops (tree stmt, voperan
*** 911,919 ****
  
  	  /* If VAR is read-only, don't add a VDEF, just a VUSE operand.  */
  	  if (!TREE_READONLY (var))
! 	    add_stmt_operand (&var, stmt, opf_force_vop|opf_is_def, prev_vops);
  	  else
! 	    add_stmt_operand (&var, stmt, opf_force_vop, prev_vops);
  	}
      }
  }
--- 879,887 ----
  
  	  /* If VAR is read-only, don't add a VDEF, just a VUSE operand.  */
  	  if (!TREE_READONLY (var))
! 	    add_stmt_operand (&var, stmt, opf_is_def, prev_vops);
  	  else
! 	    add_stmt_operand (&var, stmt, opf_none, prev_vops);
  	}
      }
  }
*************** add_call_read_ops (tree stmt, voperands_
*** 930,936 ****
       for each call-clobbered variable.  See add_referenced_var for the
       heuristic used to decide whether to create .GLOBAL_VAR.  */
    if (global_var)
!     add_stmt_operand (&global_var, stmt, opf_force_vop, prev_vops);
    else
      {
        size_t i;
--- 898,904 ----
       for each call-clobbered variable.  See add_referenced_var for the
       heuristic used to decide whether to create .GLOBAL_VAR.  */
    if (global_var)
!     add_stmt_operand (&global_var, stmt, opf_none, prev_vops);
    else
      {
        size_t i;
*************** add_call_read_ops (tree stmt, voperands_
*** 938,944 ****
        for (i = 0; i < num_call_clobbered_vars; i++)
  	{
  	  tree var = call_clobbered_var (i);
! 	  add_stmt_operand (&var, stmt, opf_force_vop, prev_vops);
  	}
      }
  }
--- 906,912 ----
        for (i = 0; i < num_call_clobbered_vars; i++)
  	{
  	  tree var = call_clobbered_var (i);
! 	  add_stmt_operand (&var, stmt, opf_none, prev_vops);
  	}
      }
  }
*************** dump_variable (FILE *file, tree var)
*** 1531,1539 ****
    if (ann->is_stored)
      fprintf (file, ", is stored");
  
-   if (ann->is_in_va_arg_expr)
-     fprintf (file, ", is used in va_arg");
- 
    if (ann->default_def)
      {
        fprintf (file, ", default def: ");
--- 1499,1504 ----
*************** find_vars_r (tree *tp, int *walk_subtree
*** 2509,2521 ****
  	 references inside (structures and arrays).  */
        return NULL_TREE;
      }
-   else if (TREE_CODE (t) == VA_ARG_EXPR)
-     {
-       walk_state->is_va_arg_expr = 1;
-       walk_tree (&TREE_OPERAND (t, 0), find_vars_r, walk_state, NULL);
-       walk_state->is_va_arg_expr = 0;
-       return t;
-     }
  
    if (SSA_VAR_P (t))
      {
--- 2474,2479 ----
*************** add_referenced_var (tree var, struct wal
*** 2573,2583 ****
  
    v_ann = get_var_ann (var);
  
-   /* If the variable has already been flagged as having hidden uses,
-      ignore it.  */
-   if (v_ann->has_hidden_use)
-     return;
- 
    if (walk_state)
      slot = htab_find_slot (walk_state->vars_found, (void *) var, INSERT);
    else
--- 2531,2536 ----
*************** add_referenced_var (tree var, struct wal
*** 2627,2638 ****
  	  VARRAY_PUSH_GENERIC_PTR (addressable_vars, alias_map);
  	}
  
!       /* Addressable variables, memory tags, static locals and
! 	 DECL_NONLOCALs may be used or clobbered by function calls.  */
!       if (is_addressable
! 	  || v_ann->is_mem_tag
! 	  || (var != global_var && TREE_STATIC (var))
! 	  || DECL_NONLOCAL (var))
  	{
  	  add_call_clobbered_var (var);
  	  v_ann->is_call_clobbered = 1;
--- 2580,2587 ----
  	  VARRAY_PUSH_GENERIC_PTR (addressable_vars, alias_map);
  	}
  
!       /* Add call clobbered variables to a separate array.  */
!       if (is_gimple_call_clobbered (var))
  	{
  	  add_call_clobbered_var (var);
  	  v_ann->is_call_clobbered = 1;
*************** add_referenced_var (tree var, struct wal
*** 2664,2674 ****
    if (walk_state->is_not_gimple)
      v_ann->has_hidden_use = 1;
  
-   /* If VAR is being referenced inside a VA_ARG_EXPR, mark it so that all
-      operands to VAR are always virtual.  */
-   if (walk_state->is_va_arg_expr)
-     v_ann->is_in_va_arg_expr = 1;
- 
    /* If the variable is a pointer being clobbered by an ASM_EXPR, the
       pointer may end up pointing to global memory.  */
    if (POINTER_TYPE_P (TREE_TYPE (var))
--- 2613,2618 ----
*************** get_memory_tag_for (tree ptr)
*** 2744,2749 ****
--- 2688,2696 ----
        tag_ann = get_var_ann (tag);
        tag_ann->is_mem_tag = 1;
        tag_ann->mem_tag = NULL_TREE;
+ 
+       /* Mark the tag volatile to prevent using it as a real operand.  */
+       TREE_THIS_VOLATILE (tag) = 1;
  
        /* Add PTR to the POINTERS array.  Note that we are not interested in
  	 PTR's alias set.  Instead, we cache the alias set for the memory that
Index: tree-flow.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow.h,v
retrieving revision 1.1.4.152
diff -d -c -p -r1.1.4.152 tree-flow.h
*** tree-flow.h	16 Nov 2003 23:00:59 -0000	1.1.4.152
--- tree-flow.h	17 Nov 2003 18:53:40 -0000
*************** struct var_ann_d GTY(())
*** 118,129 ****
       applied.  We set this when translating out of SSA form.  */
    unsigned used : 1;
  
-   /* Nonzero if this variable is used as the argument to VA_ARG_EXPR.  This
-      forces all operands to this variable to always be virtual, because
-      VA_ARG_EXPR both reads and modifies its argument and it can't be
-      modified by optimizations.  */
-   unsigned is_in_va_arg_expr : 1;
- 
    /* This field indicates whether or not the variable may need PHI nodes.
       See the enum's definition for more detailed information about the
       states.  */
--- 118,123 ----
Index: tree-simple.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-simple.c,v
retrieving revision 1.1.4.60
diff -d -c -p -r1.1.4.60 tree-simple.c
*** tree-simple.c	12 Nov 2003 22:06:26 -0000	1.1.4.60
--- tree-simple.c	17 Nov 2003 18:53:40 -0000
*************** Boston, MA 02111-1307, USA.  */
*** 163,169 ****
  
  */
  
! static int is_gimple_id (tree);
  
  /* Validation of GIMPLE expressions.  */
  
--- 163,170 ----
  
  */
  
! static inline bool is_gimple_id (tree);
! static inline bool is_gimple_non_addressable_1 (tree t);
  
  /* Validation of GIMPLE expressions.  */
  
*************** static int is_gimple_id (tree);
*** 177,183 ****
  	      | val binop val
  	      | '(' cast ')' val  */
  
! int
  is_gimple_rhs (tree t)
  {
    enum tree_code code = TREE_CODE (t);
--- 178,184 ----
  	      | val binop val
  	      | '(' cast ')' val  */
  
! bool
  is_gimple_rhs (tree t)
  {
    enum tree_code code = TREE_CODE (t);
*************** is_gimple_rhs (tree t)
*** 219,225 ****
  /* Returns nonzero if T is a valid CONSTRUCTOR component in GIMPLE, either
     a val or another CONSTRUCTOR.  */
  
! int
  is_gimple_constructor_elt (tree t)
  {
    return (is_gimple_val (t)
--- 220,226 ----
  /* Returns nonzero if T is a valid CONSTRUCTOR component in GIMPLE, either
     a val or another CONSTRUCTOR.  */
  
! bool
  is_gimple_constructor_elt (tree t)
  {
    return (is_gimple_val (t)
*************** is_gimple_constructor_elt (tree t)
*** 228,234 ****
  
  /*  Return nonzero if T is a valid LHS for a GIMPLE assignment expression.  */
  
! int
  is_gimple_lvalue (tree t)
  {
    return (is_gimple_addr_expr_arg (t)
--- 229,235 ----
  
  /*  Return nonzero if T is a valid LHS for a GIMPLE assignment expression.  */
  
! bool
  is_gimple_lvalue (tree t)
  {
    return (is_gimple_addr_expr_arg (t)
*************** is_gimple_lvalue (tree t)
*** 245,251 ****
  	      : val
  	      | val relop val  */
  
! int
  is_gimple_condexpr (tree t)
  {
    return (is_gimple_val (t)
--- 246,252 ----
  	      : val
  	      | val relop val  */
  
! bool
  is_gimple_condexpr (tree t)
  {
    return (is_gimple_val (t)
*************** is_gimple_condexpr (tree t)
*** 260,266 ****
  	      | compref
  	      | ID     */
  
! int
  is_gimple_addr_expr_arg (tree t)
  {
    return (is_gimple_id (t)
--- 261,267 ----
  	      | compref
  	      | ID     */
  
! bool
  is_gimple_addr_expr_arg (tree t)
  {
    return (is_gimple_id (t)
*************** is_gimple_addr_expr_arg (tree t)
*** 275,281 ****
     looks deeper than the TREE_CODE; this is necessary because, e.g.,
     some GIMPLE PLUS_EXPRs are considered invariant and some are not.  */
  
! int
  is_gimple_min_invariant (tree t)
  {
    tree tmp = t;
--- 276,282 ----
     looks deeper than the TREE_CODE; this is necessary because, e.g.,
     some GIMPLE PLUS_EXPRs are considered invariant and some are not.  */
  
! bool
  is_gimple_min_invariant (tree t)
  {
    tree tmp = t;
*************** is_gimple_min_invariant (tree t)
*** 310,316 ****
  
  /* Return nonzero if T looks like a valid GIMPLE statement.  */
  
! int
  is_gimple_stmt (tree t)
  {
    enum tree_code code = TREE_CODE (t);
--- 311,317 ----
  
  /* Return nonzero if T looks like a valid GIMPLE statement.  */
  
! bool
  is_gimple_stmt (tree t)
  {
    enum tree_code code = TREE_CODE (t);
*************** is_gimple_stmt (tree t)
*** 359,365 ****
  
  /* Return nonzero if T is a variable.  */
  
! int
  is_gimple_variable (tree t)
  {
    return (TREE_CODE (t) == VAR_DECL
--- 360,366 ----
  
  /* Return nonzero if T is a variable.  */
  
! bool
  is_gimple_variable (tree t)
  {
    return (TREE_CODE (t) == VAR_DECL
*************** is_gimple_variable (tree t)
*** 370,376 ****
  
  /*  Return nonzero if T is a GIMPLE identifier (something with an address).  */
  
! static int
  is_gimple_id (tree t)
  {
    return (is_gimple_variable (t)
--- 371,377 ----
  
  /*  Return nonzero if T is a GIMPLE identifier (something with an address).  */
  
! static inline bool
  is_gimple_id (tree t)
  {
    return (is_gimple_variable (t)
*************** is_gimple_id (tree t)
*** 386,399 ****
  bool
  is_gimple_reg_type (tree type)
  {
!   return (TYPE_MODE (type) != BLKmode
! 	  && TREE_CODE (type) != ARRAY_TYPE
! 	  && !TREE_ADDRESSABLE (type));
  }
  
  /* Return nonzero if T is a scalar register variable.  */
  
! int
  is_gimple_reg (tree t)
  {
    if (TREE_CODE (t) == SSA_NAME)
--- 387,416 ----
  bool
  is_gimple_reg_type (tree type)
  {
!   return (!AGGREGATE_TYPE_P (type)
!           && TREE_CODE (type) != COMPLEX_TYPE);
! }
! 
! /* Helper for is_gimple_reg, is_gimple_non_addressable and
!    is_gimple_call_clobbbered.  It silently assumes that T is a gimple
!    variable.  */
! 
! static inline
! bool is_gimple_non_addressable_1 (tree t)
! {
!   return (! TREE_STATIC (t)
! 	  && ! DECL_EXTERNAL (t)
! 	  && ! TREE_ADDRESSABLE (t)
! 	  /* A volatile decl is not acceptable because we can't reuse it as
! 	     needed.  We need to copy it into a temp first.  */
! 	  && ! TREE_THIS_VOLATILE (t)
! 	  && ! DECL_NONLOCAL (t)
! 	  && decl_function_context (t) == current_function_decl);
  }
  
  /* Return nonzero if T is a scalar register variable.  */
  
! bool
  is_gimple_reg (tree t)
  {
    if (TREE_CODE (t) == SSA_NAME)
*************** is_gimple_reg (tree t)
*** 401,418 ****
  
    return (is_gimple_variable (t)
  	  && is_gimple_reg_type (TREE_TYPE (t))
! 	  && ! TREE_STATIC (t)
! 	  && ! DECL_EXTERNAL (t)
! 	  && ! TREE_ADDRESSABLE (t)
! 	  /* A volatile decl is not acceptable because we can't reuse it as
! 	     needed.  We need to copy it into a temp first.  */
! 	  && ! TREE_THIS_VOLATILE (t));
  }
  
  /*  Return nonzero if T is a GIMPLE rvalue, i.e. an identifier or a
      constant.  */
  
! int
  is_gimple_val (tree t)
  {
    /* Make loads from volatiles and memory vars explicit.  */
--- 418,454 ----
  
    return (is_gimple_variable (t)
  	  && is_gimple_reg_type (TREE_TYPE (t))
! 	  && is_gimple_non_addressable_1 (t));
! }
! 
! /* Return nonzero if T does not need to live in memory.  */
! 
! bool
! is_gimple_non_addressable (tree t)
! {
!   if (TREE_CODE (t) == SSA_NAME)
!     t = SSA_NAME_VAR (t);
! 
!   return (is_gimple_variable (t)
! 	  && is_gimple_non_addressable_1 (t));
! }
! 
! /* Return true if T may be clobbered by function calls.  */
! 
! bool
! is_gimple_call_clobbered (tree t)
! {
!   if (TREE_CODE (t) == SSA_NAME)
!     t = SSA_NAME_VAR (t);
! 
!   return (is_gimple_variable (t)
!           && !is_gimple_non_addressable_1 (t));
  }
  
  /*  Return nonzero if T is a GIMPLE rvalue, i.e. an identifier or a
      constant.  */
  
! bool
  is_gimple_val (tree t)
  {
    /* Make loads from volatiles and memory vars explicit.  */
*************** is_gimple_val (tree t)
*** 437,443 ****
      This never actually appears in the original SIMPLE grammar, but is
      repeated in several places.  */
  
! int
  is_gimple_min_lval (tree t)
  {
    return (is_gimple_id (t)
--- 473,479 ----
      This never actually appears in the original SIMPLE grammar, but is
      repeated in several places.  */
  
! bool
  is_gimple_min_lval (tree t)
  {
    return (is_gimple_id (t)
*************** is_gimple_min_lval (tree t)
*** 447,453 ****
  /*  Return nonzero if T is a typecast operation of the form
      '(' cast ')' val.  */
  
! int
  is_gimple_cast (tree t)
  {
    return (TREE_CODE (t) == NOP_EXPR
--- 483,489 ----
  /*  Return nonzero if T is a typecast operation of the form
      '(' cast ')' val.  */
  
! bool
  is_gimple_cast (tree t)
  {
    return (TREE_CODE (t) == NOP_EXPR
Index: tree-simple.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-simple.h,v
retrieving revision 1.1.4.41
diff -d -c -p -r1.1.4.41 tree-simple.h
*** tree-simple.h	17 Nov 2003 07:17:22 -0000	1.1.4.41
--- tree-simple.h	17 Nov 2003 18:53:40 -0000
*************** extern void annotate_all_with_locus (tre
*** 40,76 ****
     the basic form of the expression, they don't recurse to make sure that
     underlying nodes are also of the right form.  */
  
! /* Returns 1 iff T is a valid GIMPLE statement.  */
! int is_gimple_stmt (tree);
  
! /* Returns 1 iff TYPE is a valid type for a scalar register variable.  */
  bool is_gimple_reg_type (tree);
! /* Returns 1 iff T is a scalar register variable.  */
! int is_gimple_reg (tree);
! /* Returns 1 iff T is any sort of variable.  */
! int is_gimple_variable (tree);
! /* Returns 1 iff T is a variable or an INDIRECT_REF (of a variable).  */
! int is_gimple_min_lval (tree);
! /* Returns 1 iff T is an lvalue other than an INDIRECT_REF.  */
! int is_gimple_addr_expr_arg (tree);
! /* Returns 1 iff T is any valid GIMPLE lvalue.  */
! int is_gimple_lvalue (tree);
  
! /* Returns 1 iff T is a GIMPLE restricted function invariant.  */
! int is_gimple_min_invariant (tree);
! /* Returns 1 iff T is a GIMPLE rvalue.  */
! int is_gimple_val (tree);
! /* Returns 1 iff T is a valid rhs for a MODIFY_EXPR.  */
! int is_gimple_rhs (tree);
  
! /* Returns 1 iff T is a valid if-statement condition.  */
! int is_gimple_condexpr (tree);
  
! /* Returns 1 iff T is a type conversion.  */
! int is_gimple_cast (tree);
! /* Returns 1 iff T is a valid CONSTRUCTOR element (either an rvalue or
     another CONSTRUCTOR).  */
! int is_gimple_constructor_elt (tree);
  
  void recalculate_side_effects (tree);
  
--- 40,81 ----
     the basic form of the expression, they don't recurse to make sure that
     underlying nodes are also of the right form.  */
  
! /* Returns true iff T is a valid GIMPLE statement.  */
! bool is_gimple_stmt (tree);
  
! /* Returns true iff TYPE is a valid type for a scalar register variable.  */
  bool is_gimple_reg_type (tree);
! /* Returns true iff T is a scalar register variable.  */
! bool is_gimple_reg (tree);
! /* Returns true iff T is any sort of variable.  */
! bool is_gimple_variable (tree);
! /* Returns true iff T is a variable or an INDIRECT_REF (of a variable).  */
! bool is_gimple_min_lval (tree);
! /* Returns true iff T is an lvalue other than an INDIRECT_REF.  */
! bool is_gimple_addr_expr_arg (tree);
! /* Returns true iff T is any valid GIMPLE lvalue.  */
! bool is_gimple_lvalue (tree);
  
! /* Returns true iff T is a GIMPLE restricted function invariant.  */
! bool is_gimple_min_invariant (tree);
! /* Returns true iff T is a GIMPLE rvalue.  */
! bool is_gimple_val (tree);
! /* Returns true iff T is a valid rhs for a MODIFY_EXPR.  */
! bool is_gimple_rhs (tree);
  
! /* Returns true iff T is a valid if-statement condition.  */
! bool is_gimple_condexpr (tree);
  
! /* Returns true iff T is a type conversion.  */
! bool is_gimple_cast (tree);
! /* Returns true iff T is a valid CONSTRUCTOR element (either an rvalue or
     another CONSTRUCTOR).  */
! bool is_gimple_constructor_elt (tree);
! /* Returns true iff T is a variable that does not need to live in memory.  */
! bool is_gimple_non_addressable (tree t);
! /* Returns true iff T is a variable that may be modified by function
!    calls.  */
! bool is_gimple_call_clobbered (tree t);
  
  void recalculate_side_effects (tree);
  
*************** enum gimplify_status {
*** 95,101 ****
  };
  
  enum gimplify_status gimplify_expr (tree *, tree *, tree *,
! 				    int (*) (tree), fallback_t);
  void gimplify_stmt (tree *);
  void gimplify_to_stmt_list (tree *);
  void gimplify_body (tree *, tree);
--- 100,106 ----
  };
  
  enum gimplify_status gimplify_expr (tree *, tree *, tree *,
! 				    bool (*) (tree), fallback_t);
  void gimplify_stmt (tree *);
  void gimplify_to_stmt_list (tree *);
  void gimplify_body (tree *, tree);


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