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]

[PATCH]: Add ability to have ARRAY_REF on pointers


This patch is the replacement for the earlier MEM_REF patch (the same
reasons for wanting it apply).

Instead of MEM_REF, we allow ARRAY_REF on pointers.

There are a number of places that care for purposes of finding
dereferences (pointer array access is a deref, regular array access is
not), etc.  I introduced a macro POINTER_ARRAY_ACCESS_P that tells
whether a given array_ref is an access to a pointer or not to use in
these places.  I also added ARRAY_REF_SYMBOL and ARRAY_REF_INDEX to
avoid getting the operands mixed up, as sometimes happens :(.


ARRAY_REF of a pointer will normally be lowered sometime during
optimizations, both to expose it to redundancy elimination
I have placed the lowering where it is (before optimization) for the
moment
because 

1. Only Kenny's stuff uses it, of the ptaches submitted so far for
stage2 (though there are plans and code to use it for data dependence,
etc, that will come either RSN or at the beginning of the next stage 1)

2. It is useful for Kenny's stuff, because we avoid useless casts that
cause his analysis to make worst case assumptions.

3. Given #1, i didn't want to perturb the optimizer path until there is
code on the regular SSA path that uses it.  

However, it is usable and can be moved to wherever we want (most of the
code in there is handling the "in-the-ssa optimizer path" case)
Bootstrapped and regtested on i686-pc-linux-gnu, okay for mainline?

2005-06-27  Daniel Berlin  <dberlin@dberlin.org>

	* Makefile.in (gimple-low.o): Add pointer-set.h
	* c-typeck.c (build_array_ref): Build ARRAY_REF for pointers when
	possible.
	(build_unary_op): Decay pointer ARRAY_REF too.
	(c_mark_addressable): Handle pointer array accesses.
	* expr.c (get_inner_reference): Don't deal with pointer array
	accesses.
	(array_ref_lower_bound): Ditto.
	(handled_component_p): Match get_inner_reference)
	(expand_expr_real_1): Pointer ARRAY_REF should be gone by the time
	we get to RTL generation.
	* gimple-low.c: Include pointer-set.h
	(lower_pointer_array_ref): New function.
	(lower_pointer_array_refs): Ditto.
	(pass_lower_pointer_array_ref): New structure.
	* gimplify.c: Handle pointer array accesses.
	* tree-eh.c (tree_could_trap_p): Ditto.
	* tree-gimple.c (is_gimple_addressable): Ditto.
	(is_gimple_min_lval): Ditto.
	(get_base_address): Ditto.
	* tree-nested.c (convert_nonlocal_reference): Need to do non-local
	references to pointer arrays like INDIRECT_REF's.
	* tree-optimize.c (init_tree_optimization_passes): Add
	pass_lower_pointer_array_ref.
	* tree-pass.h (pass_lower_pointer_array_ref): New.
	* tree-ssa-alias.c (count_ptr_derefs): Handle pointer array
	accesses. 
	* tree-ssa-ccp.c (fold_stmt_r): Teach it to fold pointer array
	accesses.
	* tree-ssa-operands.c (parse_ssa_operands): Handle pointer array
	accesses. 
	(get_expr_operands): Ditto.
	(get_pointer_array_ref_operands): New function.
	* tree-ssa-sink.c (is_hidden_global_store): Handle pointer array
	accesses. 
	* tree-ssa-structalias.c (get_constraint_for): Ditto.
	* tree.h (ARRAY_REF_SYMBOL): New.
	(ARRAY_REF_INDEX): New.

Index: Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v
retrieving revision 1.1510
diff -u -p -r1.1510 Makefile.in
--- Makefile.in	26 Jun 2005 03:26:49 -0000	1.1510
+++ Makefile.in	27 Jun 2005 22:48:12 -0000
@@ -1907,7 +1907,7 @@ gimple-low.o : gimple-low.c $(CONFIG_H) 
    $(DIAGNOSTIC_H) $(TREE_GIMPLE_H) tree-inline.h $(VARRAY_H) langhooks.h \
    $(LANGHOOKS_DEF_H) $(TREE_FLOW_H) $(TIMEVAR_H) $(TM_H) coretypes.h \
    except.h $(FLAGS_H) $(RTL_H) function.h $(EXPR_H) tree-pass.h \
-   $(HASHTAB_H) toplev.h
+   $(HASHTAB_H) toplev.h pointer-set.h
 tree-browser.o : tree-browser.c tree-browser.def $(CONFIG_H) $(SYSTEM_H) \
    $(TREE_H) tree-inline.h $(DIAGNOSTIC_H) $(HASHTAB_H) \
    $(TM_H) coretypes.h
Index: c-typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-typeck.c,v
retrieving revision 1.458
diff -u -p -r1.458 c-typeck.c
--- c-typeck.c	25 Jun 2005 01:59:24 -0000	1.458
+++ c-typeck.c	27 Jun 2005 22:48:14 -0000
@@ -1792,15 +1793,34 @@ build_array_ref (tree array, tree index)
   else
     {
       tree ar = default_conversion (array);
-
+      tree type;
+      tree res;
       if (ar == error_mark_node)
 	return ar;
 
       gcc_assert (TREE_CODE (TREE_TYPE (ar)) == POINTER_TYPE);
       gcc_assert (TREE_CODE (TREE_TYPE (TREE_TYPE (ar))) != FUNCTION_TYPE);
+      type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (ar)));
 
-      return build_indirect_ref (build_binary_op (PLUS_EXPR, ar, index, 0),
-				 "array indexing");
+      /* If this type has no size, either we're screwed or we've issued an
+	 error, so building an ARRAY_REF or not isn't going to help
+	 us.  */
+      if (TYPE_SIZE_UNIT (type) 
+	  && TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST)
+        {
+	  res = build4 (ARRAY_REF, type, ar, index, NULL_TREE, NULL_TREE);
+	  TREE_READONLY (res) = TYPE_READONLY (TREE_TYPE (TREE_TYPE (ar)));
+	  TREE_SIDE_EFFECTS (res)
+	    |= (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (ar)))
+		| TREE_SIDE_EFFECTS (ar));
+	  TREE_THIS_VOLATILE (res)
+	    |= (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (ar)))
+		| TREE_THIS_VOLATILE (ar));
+	  return res;
+	 }
+      else
+	return build_indirect_ref (build_binary_op (PLUS_EXPR, ar, index, 0),
+				   "array indexing"); 
     }
 }
 
@@ -2719,14 +2739,18 @@ build_unary_op (enum tree_code code, tre
       /* For &x[y], return x+y */
       if (TREE_CODE (arg) == ARRAY_REF)
 	{
-	  if (!c_mark_addressable (TREE_OPERAND (arg, 0)))
+	  /* The pointer array form is equivalent to *(a + offset),
+	     so &(*(a + something)) is  just a + offset, not an
+	     addressable op.  */
+	  if (!POINTER_ARRAY_ACCESS_P (arg)
+	      && !c_mark_addressable (TREE_OPERAND (arg, 0)))
 	    return error_mark_node;
 	  return build_binary_op (PLUS_EXPR,
 				  default_function_array_conversion
 				    (TREE_OPERAND (arg, 0)),
 				  TREE_OPERAND (arg, 1), 1);
 	}
-
+							      
       /* Anything not already handled and not a true memory reference
 	 or a non-lvalue array is an error.  */
       else if (typecode != FUNCTION_TYPE && !flag
@@ -2886,8 +2910,10 @@ c_mark_addressable (tree exp)
 
 	/* ... fall through ...  */
 
-      case ADDR_EXPR:
       case ARRAY_REF:
+	if (POINTER_ARRAY_ACCESS_P (x))
+	  return true;
+      case ADDR_EXPR:
       case REALPART_EXPR:
       case IMAGPART_EXPR:
 	x = TREE_OPERAND (x, 0);
Index: expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.c,v
retrieving revision 1.798
diff -u -p -r1.798 expr.c
--- expr.c	25 Jun 2005 01:59:50 -0000	1.798
+++ expr.c	27 Jun 2005 22:48:18 -0000
@@ -5487,8 +5487,9 @@ get_inner_reference (tree exp, HOST_WIDE
 	    /* ??? Right now we don't do anything with DECL_OFFSET_ALIGN.  */
 	  }
 	  break;
-
 	case ARRAY_REF:
+	  if (POINTER_ARRAY_ACCESS_P (exp))
+	    goto done;
 	case ARRAY_RANGE_REF:
 	  {
 	    tree index = TREE_OPERAND (exp, 1);
@@ -5589,17 +5590,21 @@ array_ref_element_size (tree exp)
 tree
 array_ref_low_bound (tree exp)
 {
-  tree domain_type = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (exp, 0)));
-
-  /* If a lower bound is specified in EXP, use it.  */
-  if (TREE_OPERAND (exp, 2))
-    return TREE_OPERAND (exp, 2);
-
-  /* Otherwise, if there is a domain type and it has a lower bound, use it,
-     substituting for a PLACEHOLDER_EXPR as needed.  */
-  if (domain_type && TYPE_MIN_VALUE (domain_type))
+  tree domain_type;
+  
+  if (!POINTER_ARRAY_ACCESS_P (exp))
+    {
+      domain_type  = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (exp, 0)));
+      
+      /* If a lower bound is specified in EXP, use it.  */
+      if (TREE_OPERAND (exp, 2))
+	return TREE_OPERAND (exp, 2);
+      
+      /* Otherwise, if there is a domain type and it has a lower bound, use it,
+	 substituting for a PLACEHOLDER_EXPR as needed.  */
+      if (domain_type && TYPE_MIN_VALUE (domain_type))
     return SUBSTITUTE_PLACEHOLDER_IN_EXPR (TYPE_MIN_VALUE (domain_type), exp);
-
+    }
   /* Otherwise, return a zero of the appropriate type.  */
   return build_int_cst (TREE_TYPE (TREE_OPERAND (exp, 1)), 0);
 }
@@ -5658,12 +5663,13 @@ handled_component_p (tree t)
     {
     case BIT_FIELD_REF:
     case COMPONENT_REF:
-    case ARRAY_REF:
     case ARRAY_RANGE_REF:
     case VIEW_CONVERT_EXPR:
     case REALPART_EXPR:
     case IMAGPART_EXPR:
       return 1;
+    case ARRAY_REF:
+      return !POINTER_ARRAY_ACCESS_P (t);
 
     default:
       return 0;
@@ -6934,6 +6940,9 @@ expand_expr_real_1 (tree exp, rtx target
 	tree array = TREE_OPERAND (exp, 0);
 	tree index = TREE_OPERAND (exp, 1);
 
+	/* All pointer array-like accesses should have been lowered
+	   before now.  */
+	gcc_assert (!POINTER_ARRAY_ACCESS_P (exp));
 	/* Fold an expression like: "foo"[2].
 	   This is not done in fold so it won't happen inside &.
 	   Don't fold if this is for wide characters since it's too
Index: gimple-low.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gimple-low.c,v
retrieving revision 2.25
diff -u -p -r2.25 gimple-low.c
--- gimple-low.c	25 Jun 2005 02:00:19 -0000	2.25
+++ gimple-low.c	27 Jun 2005 22:48:18 -0000
@@ -40,7 +40,7 @@ Software Foundation, 51 Franklin Street,
 #include "expr.h"
 #include "toplev.h"
 #include "tree-pass.h"
-
+#include "pointer-set.h"
 struct lower_data
 {
   /* Block the current statement belongs to.  */
@@ -658,3 +658,145 @@ struct tree_opt_pass pass_mark_used_bloc
   TODO_dump_func,			/* todo_flags_finish */
   0					/* letter */
 };
+
+static bool lowered_this_stmt = false;
+
+/* Lower a pointer array-like access ARRAY_REF tree to it's equivalent
+   INDIRECT_REF form.  TP is a pointer to the tree we are currently
+   walking, and DATA is a pointer to it's block_stmt_iterator, used
+   for inserting whatever expressions are necessary to create GIMPLE
+   from it.  */ 
+
+static tree
+lower_pointer_array_ref (tree *tp,
+	      int *walk_subtrees ATTRIBUTE_UNUSED,
+	      void *data)
+{
+  block_stmt_iterator *bsip = (block_stmt_iterator *)data;
+  tree_stmt_iterator tsi;
+
+  /* A pointer array reference to p[q] becomes p + (q * sizeof (*p)) */
+  if (POINTER_ARRAY_ACCESS_P (*tp))
+    {
+      tree indirect;
+      tree stmts;
+      tree with;
+      tree symtype = TREE_TYPE (ARRAY_REF_SYMBOL (*tp));
+
+
+      with = build2 (MULT_EXPR, TREE_TYPE (ARRAY_REF_INDEX (*tp)),
+		     ARRAY_REF_INDEX (*tp),
+		     size_in_bytes (TREE_TYPE (symtype)));
+
+      with = fold_convert (symtype, with);
+      with = build2 (PLUS_EXPR, symtype, ARRAY_REF_SYMBOL (*tp), with);
+      
+
+      with = force_gimple_operand (with, &stmts, false, NULL_TREE);
+      if (stmts)
+	{
+	  bsi_insert_before (bsip, stmts, BSI_SAME_STMT);
+	  if (in_ssa_p)
+	    {
+	      tsi = tsi_start (stmts);
+	      for (; !tsi_end_p (tsi); tsi_next (&tsi))
+		{
+		  tree stmt = tsi_stmt (tsi);
+		  tree var;
+		  ssa_op_iter iter;
+		  FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, 
+					     SSA_OP_ALL_VIRTUALS)
+		    mark_sym_for_renaming (SSA_NAME_VAR (var));
+		}
+	    }
+	}               
+      
+      indirect = build1 (INDIRECT_REF, TREE_TYPE (*tp), with);
+      TREE_READONLY (indirect) = TREE_READONLY (*tp);
+      TREE_SIDE_EFFECTS (indirect) = TREE_SIDE_EFFECTS (*tp);
+      TREE_THIS_VOLATILE (indirect) = TREE_THIS_VOLATILE (*tp);
+      
+      indirect = force_gimple_operand (indirect, &stmts, false, 
+				       NULL_TREE);
+      if (stmts)
+	{
+	  bsi_insert_before (bsip, stmts, BSI_SAME_STMT);
+	  if (in_ssa_p)
+	    {
+	      tsi = tsi_start (stmts);
+	      for (; !tsi_end_p (tsi); tsi_next (&tsi))
+		{
+		  tree stmt = tsi_stmt (tsi);
+		  tree var;
+		  ssa_op_iter iter;
+		  FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter,
+					     SSA_OP_ALL_VIRTUALS)
+		    mark_sym_for_renaming (SSA_NAME_VAR (var));
+		}
+	    }
+	}
+      *tp = indirect;
+      lowered_this_stmt = true;
+    }
+  return NULL_TREE;
+}
+      
+/* Convert pointer array-like access ARRAY_REF trees into their
+   equivalent INDIRECT_REF form across the entire function.  ARRAY_REF
+   (symbol, index) = INDIRECT_REF (symbol + (index * size in bytes of
+   the type symbol points to))  */
+
+static void
+lower_pointer_array_refs (void)
+{
+  struct pointer_set_t *visited_nodes;
+  basic_block bb;
+  FOR_ALL_BB (bb)
+    {
+      block_stmt_iterator bsi;
+      for (bsi = bsi_start (bb);
+	   !bsi_end_p (bsi);
+	   bsi_next (&bsi))
+      {
+	tree stmt = bsi_stmt (bsi);
+	visited_nodes = pointer_set_create ();
+	walk_tree (&stmt,  lower_pointer_array_ref, (void *)&bsi, 
+		   visited_nodes);
+
+	if (in_ssa_p && lowered_this_stmt)
+	  {
+	    tree var;
+	    ssa_op_iter iter;
+
+	    update_stmt (stmt);
+	    lowered_this_stmt = false;
+	    FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_ALL_VIRTUALS)
+	      {
+		if (TREE_CODE (var) == VAR_DECL)
+		  mark_sym_for_renaming (var);
+		else
+		  mark_sym_for_renaming (SSA_NAME_VAR (var));
+	      }
+	  }
+	pointer_set_destroy (visited_nodes);
+		   
+      }
+    }
+}
+struct tree_opt_pass pass_lower_pointer_array_ref = 
+{
+  "lowerprefs",				/* name */
+  NULL,					/* gate */
+  lower_pointer_array_refs,	        /* execute */
+  NULL,					/* sub */
+  NULL,					/* next */
+  0,					/* static_pass_number */
+  0,					/* tv_id */
+  PROP_cfg,					/* properties_required */
+  0,					/* properties_provided */
+  0,					/* properties_destroyed */
+  0,					/* todo_flags_start */
+  TODO_update_ssa | TODO_dump_func,	/* todo_flags_finish */
+  0					/* letter */
+};
+
Index: gimplify.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gimplify.c,v
retrieving revision 2.139
diff -u -p -r2.139 gimplify.c
--- gimplify.c	26 Jun 2005 05:23:38 -0000	2.139
+++ gimplify.c	27 Jun 2005 22:48:19 -0000
@@ -3968,6 +3968,18 @@ gimplify_expr (tree *expr_p, tree *pre_p
 	  break;
 
 	case ARRAY_REF:
+	  if (POINTER_ARRAY_ACCESS_P (*expr_p))
+	    {
+	      enum gimplify_status r0, r1;
+
+	      r0 = gimplify_expr (&ARRAY_REF_SYMBOL (*expr_p), pre_p, post_p,
+		  is_gimple_reg, fb_rvalue);
+	      r1 = gimplify_expr (&ARRAY_REF_INDEX (*expr_p), pre_p, post_p,
+		  is_gimple_reg, fb_rvalue);
+	      recalculate_side_effects (*expr_p);
+	      ret = MIN (r0, r1);
+	      break;
+	    }
 	case ARRAY_RANGE_REF:
 	case REALPART_EXPR:
 	case IMAGPART_EXPR:
@@ -4390,7 +4401,10 @@ gimplify_expr (tree *expr_p, tree *pre_p
 			     gimple_test_f, fallback);
 	      break;
 
-	    case ARRAY_REF: case ARRAY_RANGE_REF:
+	    case ARRAY_REF: 
+	      if (POINTER_ARRAY_ACCESS_P (*expr_p))
+		  gcc_unreachable ();
+  	    case ARRAY_RANGE_REF:
 	      gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
 			     gimple_test_f, fallback);
 	      gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p, post_p,
Index: tree-eh.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-eh.c,v
retrieving revision 2.44
diff -u -p -r2.44 tree-eh.c
--- tree-eh.c	25 Jun 2005 02:01:20 -0000	2.44
+++ tree-eh.c	27 Jun 2005 22:48:19 -0000
@@ -1895,6 +1895,8 @@ tree_could_trap_p (tree expr)
       return tree_could_trap_p (base);
 
     case ARRAY_REF:
+      if (POINTER_ARRAY_ACCESS_P (expr))
+	return !TREE_THIS_NOTRAP (expr);
       base = TREE_OPERAND (expr, 0);
       if (tree_could_trap_p (base))
 	return true;
Index: tree-gimple.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-gimple.c,v
retrieving revision 2.40
diff -u -p -r2.40 tree-gimple.c
--- tree-gimple.c	25 Jun 2005 02:01:22 -0000	2.40
+++ tree-gimple.c	27 Jun 2005 22:48:19 -0000
@@ -161,7 +161,8 @@ is_gimple_condexpr (tree t)
 bool
 is_gimple_addressable (tree t)
 {
-  return (is_gimple_id (t) || handled_component_p (t)
+  return (is_gimple_id (t) || handled_component_p (t) 
+	  || POINTER_ARRAY_ACCESS_P (t)
 	  || INDIRECT_REF_P (t));
 }
 
@@ -384,7 +385,9 @@ bool
 is_gimple_min_lval (tree t)
 {
   return (is_gimple_id (t)
-	  || TREE_CODE (t) == INDIRECT_REF);
+	  || TREE_CODE (t) == INDIRECT_REF
+	  || POINTER_ARRAY_ACCESS_P (t));
+	     
 }
 
 /* Return true if T is a typecast operation.  */
@@ -442,7 +445,8 @@ get_base_address (tree t)
   if (SSA_VAR_P (t)
       || TREE_CODE (t) == STRING_CST
       || TREE_CODE (t) == CONSTRUCTOR
-      || INDIRECT_REF_P (t))
+      || INDIRECT_REF_P (t)
+      || POINTER_ARRAY_ACCESS_P (t))
     return t;
   else
     return NULL_TREE;
Index: tree-nested.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-nested.c,v
retrieving revision 2.28
diff -u -p -r2.28 tree-nested.c
--- tree-nested.c	25 Jun 2005 02:01:28 -0000	2.28
+++ tree-nested.c	27 Jun 2005 22:48:20 -0000
@@ -889,10 +889,18 @@ convert_nonlocal_reference (tree *tp, in
       }
       break;
 
+    case ARRAY_REF:
+      if (POINTER_ARRAY_ACCESS_P (t))
+	{
+	  *walk_subtrees = 1;
+	  wi->val_only = true;
+	  wi->is_lhs = false;
+	  break;
+	}
+
     case REALPART_EXPR:
     case IMAGPART_EXPR:
     case COMPONENT_REF:
-    case ARRAY_REF:
     case ARRAY_RANGE_REF:
     case BIT_FIELD_REF:
       /* Go down this entire nest and just look at the final prefix and
@@ -1019,10 +1027,17 @@ convert_local_reference (tree *tp, int *
       }
       break;
 
+    case ARRAY_REF:
+      if (POINTER_ARRAY_ACCESS_P (t))
+	{
+	  *walk_subtrees = 1;
+	  wi->val_only = true;
+	  wi->is_lhs = false;
+	break;
+	}
     case REALPART_EXPR:
     case IMAGPART_EXPR:
     case COMPONENT_REF:
-    case ARRAY_REF:
     case ARRAY_RANGE_REF:
     case BIT_FIELD_REF:
       /* Go down this entire nest and just look at the final prefix and
Index: tree-pass.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-pass.h,v
retrieving revision 2.44
diff -u -p -r2.44 tree-pass.h
--- tree-pass.h	25 Jun 2005 02:01:29 -0000	2.44
+++ tree-pass.h	27 Jun 2005 22:48:20 -0000
@@ -162,6 +162,7 @@ extern struct tree_opt_pass pass_mudflap
 extern struct tree_opt_pass pass_remove_useless_stmts;
 extern struct tree_opt_pass pass_lower_cf;
 extern struct tree_opt_pass pass_lower_eh;
+extern struct tree_opt_pass pass_lower_pointer_array_ref;
 extern struct tree_opt_pass pass_build_cfg;
 extern struct tree_opt_pass pass_tree_profile;
 extern struct tree_opt_pass pass_referenced_vars;
Index: tree-sra.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-sra.c,v
retrieving revision 2.64
diff -u -p -r2.64 tree-sra.c
--- tree-sra.c	25 Jun 2005 02:01:31 -0000	2.64
+++ tree-sra.c	27 Jun 2005 22:48:20 -0000
@@ -555,6 +555,8 @@ maybe_lookup_element_for_expr (tree expr
       return NULL;
 
     case ARRAY_REF:
+      if (POINTER_ARRAY_ACCESS_P (expr))
+	return NULL;
       /* We can't scalarize variable array indicies.  */
       if (is_valid_const_index (expr))
         child = TREE_OPERAND (expr, 1);
@@ -689,7 +691,7 @@ sra_walk_expr (tree *expr_p, block_stmt_
 	   the effort.  */
 	/* ??? Hack.  Figure out how to push this into the scan routines
 	   without duplicating too much code.  */
-	if (!is_valid_const_index (inner))
+	if (POINTER_ARRAY_ACCESS_P (inner) || !is_valid_const_index (inner))
 	  {
 	    disable_scalarization = true;
 	    goto use_all;
Index: tree-ssa-alias.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-alias.c,v
retrieving revision 2.98
diff -u -p -r2.98 tree-ssa-alias.c
--- tree-ssa-alias.c	25 Jun 2005 02:01:32 -0000	2.98
+++ tree-ssa-alias.c	27 Jun 2005 22:48:21 -0000
@@ -395,7 +395,8 @@ count_ptr_derefs (tree *tp, int *walk_su
 {
   struct count_ptr_d *count_p = (struct count_ptr_d *) data;
 
-  if (INDIRECT_REF_P (*tp) && TREE_OPERAND (*tp, 0) == count_p->ptr)
+  if ((INDIRECT_REF_P (*tp) && TREE_OPERAND (*tp, 0) == count_p->ptr)
+      || (POINTER_ARRAY_ACCESS_P (*tp) && ARRAY_REF_SYMBOL (*tp) == count_p->ptr))
     count_p->count++;
 
   return NULL_TREE;
Index: tree-ssa-ccp.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-ccp.c,v
retrieving revision 2.80
diff -u -p -r2.80 tree-ssa-ccp.c
--- tree-ssa-ccp.c	25 Jun 2005 02:01:33 -0000	2.80
+++ tree-ssa-ccp.c	27 Jun 2005 22:48:21 -0000
@@ -1883,9 +1883,37 @@ fold_stmt_r (tree *expr_p, int *walk_sub
   bool *changed_p = data;
   tree expr = *expr_p, t;
 
+  t = NULL_TREE;
   /* ??? It'd be nice if walk_tree had a pre-order option.  */
   switch (TREE_CODE (expr))
     {
+    case ARRAY_REF:
+      /* Attempt to fold a pointer array-like access as if it were
+       *(symbol + offset) */
+      if (POINTER_ARRAY_ACCESS_P (*expr_p))
+	{
+	  tree offsetb;
+	  tree sym; 
+	  tree symtype; 
+	  tree psymtype;
+	  
+	  t = walk_tree (&ARRAY_REF_SYMBOL (expr), fold_stmt_r, data, NULL);
+	  if (t)
+	    return t;
+	  *walk_subtrees = 0;
+	  sym = ARRAY_REF_SYMBOL (expr);
+	  symtype = TREE_TYPE (sym);
+	  psymtype = TREE_TYPE (symtype);
+	  offsetb = fold (build2 (MULT_EXPR, 
+				  TREE_TYPE (ARRAY_REF_INDEX (expr)),
+				  ARRAY_REF_INDEX (expr),
+				  size_in_bytes (psymtype)));
+	  if (TREE_CODE (offsetb) == INTEGER_CST)
+	    t = maybe_fold_stmt_indirect (expr, ARRAY_REF_SYMBOL (expr),
+		offsetb);
+	  break;
+	}
+      break;
     case INDIRECT_REF:
       t = walk_tree (&TREE_OPERAND (expr, 0), fold_stmt_r, data, NULL);
       if (t)
Index: tree-ssa-operands.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-operands.c,v
retrieving revision 2.90
diff -u -p -r2.90 tree-ssa-operands.c
--- tree-ssa-operands.c	25 Jun 2005 02:01:43 -0000	2.90
+++ tree-ssa-operands.c	27 Jun 2005 22:48:22 -0000
@@ -152,6 +152,7 @@ static void note_addressable (tree, stmt
 static void get_expr_operands (tree, tree *, int);
 static void get_asm_expr_operands (tree);
 static void get_indirect_ref_operands (tree, tree, int);
+static void get_pointer_array_ref_operands (tree, tree *, int);
 static void get_tmr_operands (tree, tree, int);
 static void get_call_expr_operands (tree, tree);
 static inline void append_def (tree *);
@@ -898,7 +899,8 @@ parse_ssa_operands (tree stmt)
 	if (TREE_CODE (lhs) == VIEW_CONVERT_EXPR)
 	  lhs = TREE_OPERAND (lhs, 0);
 
-	if (TREE_CODE (lhs) != ARRAY_REF && TREE_CODE (lhs) != ARRAY_RANGE_REF
+	if (TREE_CODE (lhs) != ARRAY_REF
+	    && TREE_CODE (lhs) != ARRAY_RANGE_REF
 	    && TREE_CODE (lhs) != BIT_FIELD_REF
 	    && TREE_CODE (lhs) != REALPART_EXPR
 	    && TREE_CODE (lhs) != IMAGPART_EXPR)
@@ -1295,6 +1297,11 @@ get_expr_operands (tree stmt, tree *expr
       return;
 
     case ARRAY_REF:
+      if (POINTER_ARRAY_ACCESS_P (expr))
+	{
+	  get_pointer_array_ref_operands (stmt, expr_p, flags);
+	  return;
+	}
     case ARRAY_RANGE_REF:
       /* Treat array references as references to the virtual variable
 	 representing the array.  The virtual variable for an ARRAY_REF
@@ -1602,7 +1609,7 @@ get_indirect_ref_operands (tree stmt, tr
 
   /* Stores into INDIRECT_REF operands are never killing definitions.  */
   flags &= ~opf_kill_def;
-
+  
   if (SSA_VAR_P (ptr))
     {
       struct ptr_info_def *pi = NULL;
@@ -1681,6 +1688,79 @@ get_indirect_ref_operands (tree stmt, tr
   get_expr_operands (stmt, pptr, opf_none);
 }
 
+
+/* A subroutine of get_expr_operands to handle pointer array-like
+   accesses that are ARRAY_REF's.  */
+
+static void
+get_pointer_array_ref_operands (tree stmt, tree *expr_p, int flags)
+{
+  stmt_ann_t s_ann  = stmt_ann (stmt);
+  tree expr = *expr_p;
+  tree ptr;
+
+  /* First record the real operands.  */
+  get_expr_operands (stmt, &ARRAY_REF_INDEX (expr), opf_none);
+
+  ptr = ARRAY_REF_SYMBOL (expr);
+
+  if (SSA_VAR_P (ptr))
+    {
+      struct ptr_info_def *pi = NULL;
+
+      /* If PTR has flow-sensitive points-to information, use it.  */
+      if (TREE_CODE (ptr) == SSA_NAME
+	  && (pi = SSA_NAME_PTR_INFO (ptr)) != NULL
+	  && pi->name_mem_tag)
+	{
+	  /* PTR has its own memory tag.  Use it.  */
+	  add_stmt_operand (&pi->name_mem_tag, s_ann, flags);
+	}
+      else
+	{
+	  /* If PTR is not an SSA_NAME or it doesn't have a name
+	     tag, use its type memory tag.  */
+	  var_ann_t v_ann;
+
+	  /* If we are emitting debugging dumps, display a warning if
+	     PTR is an SSA_NAME with no flow-sensitive alias
+	     information.  That means that we may need to compute
+	     aliasing again.  */
+	  if (dump_file
+	      && TREE_CODE (ptr) == SSA_NAME
+	      && pi == NULL)
+	    {
+	      fprintf (dump_file,
+		  "NOTE: no flow-sensitive alias info for ");
+	      print_generic_expr (dump_file, ptr, dump_flags);
+	      fprintf (dump_file, " in ");
+	      print_generic_stmt (dump_file, stmt, dump_flags);
+	    }
+
+	  if (TREE_CODE (ptr) == SSA_NAME)
+	    ptr = SSA_NAME_VAR (ptr);
+	  v_ann = var_ann (ptr);
+	  if (v_ann->type_mem_tag)
+	    add_stmt_operand (&v_ann->type_mem_tag, s_ann, flags);
+	}
+    }
+  /* (&a)[q] is a VDEF of a */
+  else if (TREE_CODE (ptr) == ADDR_EXPR)
+    {
+      /* Make sure we know the object is addressable.  */
+      tree *pptr = &ARRAY_REF_SYMBOL (expr);
+      add_stmt_operand (pptr, s_ann, 0);
+
+      /* Mark the object itself with a VUSE/VDEF.  */
+      pptr = &TREE_OPERAND (*pptr, 0);
+      get_expr_operands (stmt, pptr, flags);
+    }
+
+  /* Also add a use operand for the base pointer */
+  get_expr_operands (stmt, &ARRAY_REF_SYMBOL (expr), opf_none);
+
+}
+
 /* A subroutine of get_expr_operands to handle TARGET_MEM_REF.  */
 
 static void
Index: tree-ssa-sink.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-sink.c,v
retrieving revision 1.12
diff -u -p -r1.12 tree-ssa-sink.c
--- tree-ssa-sink.c	25 Jun 2005 02:01:47 -0000	1.12
+++ tree-ssa-sink.c	27 Jun 2005 22:48:22 -0000
@@ -189,7 +189,7 @@ is_hidden_global_store (tree stmt)
 	    return true;
 
 	}
-      else if (INDIRECT_REF_P (lhs))
+      else if (INDIRECT_REF_P (lhs) || POINTER_ARRAY_ACCESS_P (lhs))
 	{
 	  tree ptr = TREE_OPERAND (lhs, 0);
 	  struct ptr_info_def *pi = SSA_NAME_PTR_INFO (ptr);
Index: tree-ssa-structalias.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-structalias.c,v
retrieving revision 2.6
diff -u -p -r2.6 tree-ssa-structalias.c
--- tree-ssa-structalias.c	25 Jun 2005 02:01:47 -0000	2.6
+++ tree-ssa-structalias.c	27 Jun 2005 22:48:23 -0000
@@ -2129,6 +2129,14 @@ get_constraint_for (tree t)
 	      return temp;
 	    }
 	  case ARRAY_REF:
+	    {
+	      if (POINTER_ARRAY_ACCESS_P (t))
+		{		 
+		  temp = get_constraint_for (ARRAY_REF_SYMBOL (t));
+		  temp = do_deref (temp);
+		  return temp;
+		}
+	    }
 	  case COMPONENT_REF:
 	    temp = get_constraint_for_component_ref (t);
 	    return temp;
Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.739
diff -u -p -r1.739 tree.h
--- tree.h	25 Jun 2005 02:01:56 -0000	1.739
+++ tree.h	27 Jun 2005 22:48:24 -0000
@@ -1236,6 +1236,13 @@ struct tree_vec GTY(())
 #define CASE_HIGH(NODE)         	TREE_OPERAND (CASE_LABEL_EXPR_CHECK (NODE), 1)
 #define CASE_LABEL(NODE)		TREE_OPERAND (CASE_LABEL_EXPR_CHECK (NODE), 2)
 
+/* The operands of a ARRAY_REF.  */
+#define ARRAY_REF_SYMBOL(NODE) (TREE_OPERAND (ARRAY_REF_CHECK (NODE), 0))
+#define ARRAY_REF_INDEX(NODE) (TREE_OPERAND (ARRAY_REF_CHECK (NODE), 1))
+
+#define POINTER_ARRAY_ACCESS_P(NODE) (TREE_CODE ((NODE)) == ARRAY_REF \
+				      && POINTER_TYPE_P (TREE_TYPE (ARRAY_REF_SYMBOL((NODE)))))
+
 /* The operands of a TARGET_MEM_REF.  */
 #define TMR_SYMBOL(NODE) (TREE_OPERAND (TARGET_MEM_REF_CHECK (NODE), 0))
 #define TMR_BASE(NODE) (TREE_OPERAND (TARGET_MEM_REF_CHECK (NODE), 1))
Index: tree-optimize.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-optimize.c,v
retrieving revision 2.111
diff -u -p -r2.111 tree-optimize.c
--- tree-optimize.c	25 Jun 2005 02:01:28 -0000	2.111
+++ tree-optimize.c	27 Jun 2005 22:54:44 -0000
@@ -385,6 +385,7 @@ init_tree_optimization_passes (void)
   NEXT_PASS (pass_init_datastructures);
   NEXT_PASS (pass_all_optimizations);
   NEXT_PASS (pass_warn_function_noreturn);
+  NEXT_PASS (pass_lower_pointer_array_ref);
   NEXT_PASS (pass_mudflap_2);
   NEXT_PASS (pass_free_datastructures);
   NEXT_PASS (pass_expand);
@@ -393,6 +394,7 @@ init_tree_optimization_passes (void)
 
   p = &pass_all_optimizations.sub;
   NEXT_PASS (pass_referenced_vars);
+  NEXT_PASS (pass_lower_pointer_array_ref);
   NEXT_PASS (pass_create_structure_vars);
   NEXT_PASS (pass_build_ssa);
   NEXT_PASS (pass_build_pta);  

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