This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH]: MEM_REF
- From: Daniel Berlin <dberlin at dberlin dot org>
- To: Diego Novillo <dnovillo at redhat dot com>, irar at il dot ibm dot com, GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Mon, 16 May 2005 15:52:12 -0400
- Subject: [PATCH]: MEM_REF
MEM_REF is a generic array-like index + deref operation that looks like
an ARRAY_REF, except is performed on pointers. ARRAY_REF requires it's
argument to be an aggregate, and this is not easy nor necessarily
desirable to change.
However, lowering array like pointer accesses (IE p[0], p[i]) to address
arithmetic early is also not desirable, as the array form is much easier
for dependence analysis, disambiguation, prefetching, and structure
transformations.
It also avoids the nasty casts often seen with the compiler lowered
pointer arithmetic (though after lowering MEM_REF, you again have these
nasty casts :P).
Thus, MEM_REF exists to keep array like pointer accesses looking array
like (in fact, XLC does significant amounts of "recovering" pointer
arithmetic into array like operations, which we may want to do as well).
At some point during the optimization path, most likely after high level
loop optimizations, we should lower memref, run PRE and other redundancy
eliminations, run some strength reduction, etc.
However, the only current users of MEM_REF are actually interprocedural
passes that have not been submitted.
As such, i've kept the lowering to be right after SSA building (there is
also a lowering pass after all opts passes that is there to catch the
-O0 case).
The assumption is that some higher level loop opts (like the vectorizer)
and dependence analysis will work on MEM_REF just as well by the time
stage2 is over, so that we can move this lowering to after those
transforms.
Right now, for example, dependence analysis goes through a lot of
contortions to try to rediscover the same information mem_ref already
provides it, so that the vectorizer can vectorize pointer based things.
Once changed to use MEM_REF, it would work the same as array dependence
works, without any contortions
Moving it anywhere will work as long as you rerun may-alias after it,
I've experimented with it in various parts of the compiler.
This currently causes vectorizer regressions (not correctness,
optimization) because the vectorizer doesn't like the lowered mem_ref
form (probably because of the cast from index * size to a pointer, so
that instead of adding a pointer and an int, we add a pointer and a
pointer)
This would of course go away if the vectorizer understood MEM_REF, which
i'm happy to help work on doing before stage2 is done (and would be
willing to disable MEM_REF generation if that doesn't get done in time
or whatever else is deemed necessary).
Bootstrapped and regtested on powerpc-linux-gnu and i686-pc-linux-gnu.
Only the vectorizer regressions mentioned above occur.
--Dan
2005-05-16 Daniel Berlin <dberlin@dberlin.org>
* Makefile.in (gimple-low.o): Add pointer-set.h
* c-typeck.c (build_array_ref): Build MEM_REF when possible.
(build_unary_op): Decay MEM_REF too.
(lvalue_p): Handle MEM_REF.
* expr.c (expand_expr_real_1): MEM_REF should be gone by the time
we get to RTL generation.
* gimple-low.c: Include pointer-set.h
(lower_memref): New function.
(lower_memrefs): Ditto.
(pass_lower_memref): New structure.
* gimplify.c: Handle MEM_REF.
(check_pointer_types_r): Ditto.
* tree-eh.c (tree_could_trap_p): MEM_REF can trap.
* tree-gimple.c (is_gimple_addressable): Add MEM_REF.
(is_gimple_min_lval): Ditto.
(get_base_address): Ditto.
* tree-inline.h (estimate_num_insns_1): Ditto.
* tree-optimize.c (init_tree_optimization_passes): Add
pass_lower_memref.
* tree-pass.h (pass_lower_memref): New.
* tree-pretty-print.c (dump_generic_node): Print out MEM_REF.
* tree-ssa-alias.c (count_ptr_derefs): Handle MEM_REF.
* tree-ssa-loop-im.c (for_each_index): Ditto.
* tree-ssa-operands.c (parse_ssa_operands): Handle MEM_REF.
(get_expr_operands): Ditto.
(get_mem_ref_operands): New function.
* tree.def (MEM_REF): New tree code.
* tree.h (MEM_REF_SYMBOL): New macro.
(MEM_REF_INDEX): Ditto.
* doc/c-tree.texi: Document MEM_REF.
* doc/tree-ssa.texi: Ditto.
Index: Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v
retrieving revision 1.1484
diff -u -p -r1.1484 Makefile.in
--- Makefile.in 11 May 2005 16:25:24 -0000 1.1484
+++ Makefile.in 16 May 2005 18:56:26 -0000
@@ -1828,7 +1828,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) errors.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.441
diff -u -p -r1.441 c-typeck.c
--- c-typeck.c 10 May 2005 13:46:38 -0000 1.441
+++ c-typeck.c 16 May 2005 18:56:26 -0000
@@ -1790,15 +1791,33 @@ 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 it doesn't matter if we build a MEM_REF here or not. */
+ if (TYPE_SIZE_UNIT (type)
+ && TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST)
+ {
+ res = build2 (MEM_REF, type, ar, index);
+ 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");
}
}
@@ -2738,7 +2757,14 @@ build_unary_op (enum tree_code code, tre
return build_binary_op (PLUS_EXPR, TREE_OPERAND (arg, 0),
TREE_OPERAND (arg, 1), 1);
}
-
+ /* Same for the equivalent MEM_REF */
+ if (TREE_CODE (arg) == MEM_REF)
+ {
+ return build_binary_op (PLUS_EXPR,
+ MEM_REF_SYMBOL (arg),
+ MEM_REF_INDEX (arg), 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
@@ -2815,6 +2841,7 @@ lvalue_p (tree ref)
case VAR_DECL:
case PARM_DECL:
case RESULT_DECL:
+ case MEM_REF:
case ERROR_MARK:
return (TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE
&& TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE);
Index: expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.c,v
retrieving revision 1.789
diff -u -p -r1.789 expr.c
--- expr.c 3 May 2005 22:21:48 -0000 1.789
+++ expr.c 16 May 2005 18:56:26 -0000
@@ -6911,7 +6910,8 @@ expand_expr_real_1 (tree exp, rtx target
return temp;
}
-
+ case MEM_REF:
+ gcc_unreachable ();
case ARRAY_REF:
{
Index: gimple-low.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gimple-low.c,v
retrieving revision 2.23
diff -u -p -r2.23 gimple-low.c
--- gimple-low.c 8 Mar 2005 16:18:17 -0000 2.23
+++ gimple-low.c 16 May 2005 18:56:26 -0000
@@ -41,7 +41,7 @@ Software Foundation, 59 Temple Place - S
#include "expr.h"
#include "toplev.h"
#include "tree-pass.h"
-
+#include "pointer-set.h"
struct lower_data
{
/* Block the current statement belongs to. */
@@ -659,3 +659,89 @@ struct tree_opt_pass pass_mark_used_bloc
TODO_dump_func, /* todo_flags_finish */
0 /* letter */
};
+
+/* Lower a MEM_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_memref (tree *tp,
+ int *walk_subtrees ATTRIBUTE_UNUSED,
+ void *data)
+{
+ block_stmt_iterator *bsip = (block_stmt_iterator *)data;
+ if (TREE_CODE (*tp) == MEM_REF)
+ {
+ tree indirect;
+ tree stmts;
+ tree with;
+ with = build2 (MULT_EXPR, TREE_TYPE (MEM_REF_INDEX (*tp)),
+ MEM_REF_INDEX (*tp),
+ size_in_bytes (TREE_TYPE (TREE_TYPE (MEM_REF_SYMBOL (*tp)))));
+ with = fold_convert (TREE_TYPE (MEM_REF_SYMBOL (*tp)), with);
+ with = build2 (PLUS_EXPR, TREE_TYPE (MEM_REF_SYMBOL (*tp)),
+ MEM_REF_SYMBOL (*tp), with);
+
+
+ with = force_gimple_operand (with, &stmts, false, NULL_TREE);
+ if (stmts)
+ bsi_insert_before (bsip, stmts, BSI_SAME_STMT);
+
+ 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);
+ *tp = indirect;
+ }
+ return NULL_TREE;
+}
+
+/* Convert MEM_REF trees into their equivalent INDIRECT_REF form
+ across the entire function. MEM_REF (symbol, index) = INDIRECT_REF
+ (symbol + (index * size in bytes of the type symbol points to)) */
+
+static void
+lower_memrefs (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_memref, (void *)&bsi, visited_nodes);
+ if (in_ssa_p)
+ update_stmt (stmt);
+ pointer_set_destroy (visited_nodes);
+
+ }
+ }
+}
+struct tree_opt_pass pass_lower_memref =
+{
+ "memrefs", /* name */
+ NULL, /* gate */
+ lower_memrefs, /* execute */
+ NULL, /* sub */
+ NULL, /* next */
+ 0, /* static_pass_number */
+ 0, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_dump_func, /* todo_flags_finish */
+ 0 /* letter */
+};
+
Index: gimplify.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gimplify.c,v
retrieving revision 2.126
diff -u -p -r2.126 gimplify.c
--- gimplify.c 1 May 2005 23:23:33 -0000 2.126
+++ gimplify.c 16 May 2005 18:56:26 -0000
@@ -3901,7 +3901,20 @@ gimplify_expr (tree *expr_p, tree *pre_p
recalculate_side_effects (*expr_p);
break;
+ case MEM_REF:
+ {
+ enum gimplify_status r0, r1;
+
+ r0 = gimplify_expr (&MEM_REF_SYMBOL (*expr_p), pre_p, post_p,
+ is_gimple_reg, fb_rvalue);
+ r1 = gimplify_expr (&MEM_REF_INDEX (*expr_p), pre_p, post_p,
+ is_gimple_reg, fb_rvalue);
+ recalculate_side_effects (*expr_p);
+ ret = MIN (r0, r1);
+ }
+ break;
+
case INDIRECT_REF:
*expr_p = fold_indirect_ref (*expr_p);
if (*expr_p != save_expr)
@@ -4485,6 +4497,7 @@ check_pointer_types_r (tree *tp, int *wa
switch (TREE_CODE (t))
{
case INDIRECT_REF:
+ case MEM_REF:
case ARRAY_REF:
otype = TREE_TYPE (t);
ptype = TREE_TYPE (TREE_OPERAND (t, 0));
Index: tree-eh.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-eh.c,v
retrieving revision 2.38
diff -u -p -r2.38 tree-eh.c
--- tree-eh.c 14 May 2005 14:32:39 -0000 2.38
+++ tree-eh.c 16 May 2005 18:56:26 -0000
@@ -1896,6 +1896,7 @@ tree_could_trap_p (tree expr)
return !in_array_bounds_p (expr);
+ case MEM_REF:
case INDIRECT_REF:
case ALIGN_INDIRECT_REF:
case MISALIGNED_INDIRECT_REF:
Index: tree-gimple.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-gimple.c,v
retrieving revision 2.38
diff -u -p -r2.38 tree-gimple.c
--- tree-gimple.c 9 Apr 2005 01:37:23 -0000 2.38
+++ tree-gimple.c 16 May 2005 18:56:26 -0000
@@ -161,8 +161,8 @@ is_gimple_condexpr (tree t)
bool
is_gimple_addressable (tree t)
{
- return (is_gimple_id (t) || handled_component_p (t)
- || INDIRECT_REF_P (t));
+ return (is_gimple_id (t) || handled_component_p (t)
+ || TREE_CODE (t) == MEM_REF || INDIRECT_REF_P (t));
}
/* Return true if T is function invariant. Or rather a restricted
@@ -380,7 +380,8 @@ bool
is_gimple_min_lval (tree t)
{
return (is_gimple_id (t)
- || TREE_CODE (t) == INDIRECT_REF);
+ || TREE_CODE (t) == INDIRECT_REF
+ || TREE_CODE (t) == MEM_REF);
}
/* Return true if T is a typecast operation. */
@@ -438,7 +439,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)
+ || TREE_CODE (t) == MEM_REF)
return t;
else
return NULL_TREE;
Index: tree-inline.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-inline.c,v
retrieving revision 1.183
diff -u -p -r1.183 tree-inline.c
--- tree-inline.c 13 May 2005 13:56:54 -0000 1.183
+++ tree-inline.c 16 May 2005 18:56:26 -0000
@@ -1213,6 +1213,7 @@ estimate_num_insns_1 (tree *tp, int *wal
case BLOCK:
case COMPONENT_REF:
case BIT_FIELD_REF:
+ case MEM_REF:
case INDIRECT_REF:
case ALIGN_INDIRECT_REF:
case MISALIGNED_INDIRECT_REF:
Index: tree-optimize.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-optimize.c,v
retrieving revision 2.95
diff -u -p -r2.95 tree-optimize.c
--- tree-optimize.c 14 May 2005 20:22:58 -0000 2.95
+++ tree-optimize.c 16 May 2005 18:56:26 -0000
@@ -332,6 +332,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_memref);
NEXT_PASS (pass_mudflap_2);
NEXT_PASS (pass_free_datastructures);
NEXT_PASS (pass_expand);
@@ -342,6 +343,7 @@ init_tree_optimization_passes (void)
NEXT_PASS (pass_referenced_vars);
NEXT_PASS (pass_create_structure_vars);
NEXT_PASS (pass_build_ssa);
+ NEXT_PASS (pass_lower_memref);
NEXT_PASS (pass_may_alias);
NEXT_PASS (pass_rename_ssa_copies);
NEXT_PASS (pass_early_warn_uninitialized);
Index: tree-pass.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-pass.h,v
retrieving revision 2.34
diff -u -p -r2.34 tree-pass.h
--- tree-pass.h 14 May 2005 14:24:47 -0000 2.34
+++ tree-pass.h 16 May 2005 18:56:26 -0000
@@ -161,6 +161,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_memref;
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-pretty-print.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-pretty-print.c,v
retrieving revision 2.58
diff -u -p -r2.58 tree-pretty-print.c
--- tree-pretty-print.c 3 May 2005 12:19:41 -0000 2.58
+++ tree-pretty-print.c 16 May 2005 18:56:26 -0000
@@ -444,6 +444,15 @@ dump_generic_node (pretty_printer *buffe
pp_string (buffer, "::");
break;
+ case MEM_REF:
+ {
+ dump_generic_node (buffer, MEM_REF_SYMBOL (node), spc, flags, false);
+ pp_string (buffer, "[");
+ dump_generic_node (buffer, MEM_REF_INDEX (node), spc, flags, false);
+ pp_string (buffer, "]");
+ }
+ break;
+
case ARRAY_TYPE:
{
tree tmp;
Index: tree-ssa-alias.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-alias.c,v
retrieving revision 2.91
diff -u -p -r2.91 tree-ssa-alias.c
--- tree-ssa-alias.c 28 Apr 2005 07:58:29 -0000 2.91
+++ tree-ssa-alias.c 16 May 2005 18:56:26 -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)
+ || (TREE_CODE (*tp) == MEM_REF && MEM_REF_SYMBOL (*tp) == count_p->ptr))
count_p->count++;
return NULL_TREE;
Index: tree-ssa-loop-im.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-loop-im.c,v
retrieving revision 2.41
diff -u -p -r2.41 tree-ssa-loop-im.c
--- tree-ssa-loop-im.c 12 May 2005 19:41:10 -0000 2.41
+++ tree-ssa-loop-im.c 16 May 2005 18:56:26 -0000
@@ -203,6 +203,18 @@ for_each_index (tree *addr_p, bool (*cbc
case RESULT_DECL:
return true;
+ case MEM_REF:
+ idx = &MEM_REF_SYMBOL (*addr_p);
+ if (*idx
+ && !cbck (*addr_p, idx, data))
+ return false;
+ return true;
+ idx = &MEM_REF_INDEX (*addr_p);
+ if (*idx
+ && !cbck (*addr_p, idx, data))
+ return false;
+ return true;
+
default:
gcc_unreachable ();
}
Index: tree-ssa-operands.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-operands.c,v
retrieving revision 2.82
diff -u -p -r2.82 tree-ssa-operands.c
--- tree-ssa-operands.c 6 May 2005 14:04:11 -0000 2.82
+++ tree-ssa-operands.c 16 May 2005 18:56:26 -0000
@@ -148,6 +148,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_mem_ref_operands (tree, tree *, int);
static void get_call_expr_operands (tree, tree);
static inline void append_def (tree *);
static inline void append_use (tree *);
@@ -893,7 +894,9 @@ 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) != MEM_REF
&& TREE_CODE (lhs) != BIT_FIELD_REF
&& TREE_CODE (lhs) != REALPART_EXPR
&& TREE_CODE (lhs) != IMAGPART_EXPR)
@@ -1285,6 +1288,10 @@ get_expr_operands (tree stmt, tree *expr
get_indirect_ref_operands (stmt, expr, flags);
return;
+ case MEM_REF:
+ get_mem_ref_operands (stmt, expr_p, flags);
+ return;
+
case ARRAY_REF:
case ARRAY_RANGE_REF:
/* Treat array references as references to the virtual variable
@@ -1369,6 +1376,7 @@ get_expr_operands (tree stmt, tree *expr
if (TREE_CODE (op) == WITH_SIZE_EXPR)
op = TREE_OPERAND (expr, 0);
if (TREE_CODE (op) == ARRAY_REF
+ || TREE_CODE (op) == MEM_REF
|| TREE_CODE (op) == ARRAY_RANGE_REF
|| TREE_CODE (op) == REALPART_EXPR
|| TREE_CODE (op) == IMAGPART_EXPR)
@@ -1589,7 +1597,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;
@@ -1668,6 +1676,65 @@ get_indirect_ref_operands (tree stmt, tr
get_expr_operands (stmt, pptr, opf_none);
}
+/* A subroutine of get_expr_operands to handle MEM_REF. */
+
+static void
+get_mem_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, &MEM_REF_INDEX (expr), opf_none);
+
+ ptr = MEM_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);
+ }
+ }
+ /* Add a use operand for the base pointer */
+ get_expr_operands (stmt, &MEM_REF_SYMBOL (expr), opf_none);
+
+}
+
/* A subroutine of get_expr_operands to handle CALL_EXPR. */
static void
Index: tree.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.def,v
retrieving revision 1.115
diff -u -p -r1.115 tree.def
--- tree.def 9 Apr 2005 01:37:28 -0000 1.115
+++ tree.def 16 May 2005 18:56:26 -0000
@@ -935,6 +935,13 @@ DEFTREECODE (WITH_SIZE_EXPR, "with_size_
generated by the builtin targetm.vectorize.mask_for_load_builtin_decl. */
DEFTREECODE (REALIGN_LOAD_EXPR, "realign_load", tcc_expression, 3)
+/* Array like memory addressing for pointers. Operands are SYMBOL
+ (static or global variable),INDEX (register), STEP (integer
+ constant) Corresponding address is SYMBOL + (INDEX * TYPE_SIZE_UNIT
+ (TREE_TYPE (SYMBOL))). */
+
+DEFTREECODE (MEM_REF, "mem_ref", tcc_reference, 2)
+
/*
Local variables:
mode:c
Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.727
diff -u -p -r1.727 tree.h
--- tree.h 11 May 2005 16:25:30 -0000 1.727
+++ tree.h 16 May 2005 18:56:26 -0000
@@ -1240,6 +1240,10 @@ 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 MEM_REF. */
+#define MEM_REF_SYMBOL(NODE) (TREE_OPERAND (MEM_REF_CHECK (NODE), 0))
+#define MEM_REF_INDEX(NODE) (TREE_OPERAND (MEM_REF_CHECK (NODE), 1))
+
/* The operands of a BIND_EXPR. */
#define BIND_EXPR_VARS(NODE) (TREE_OPERAND (BIND_EXPR_CHECK (NODE), 0))
#define BIND_EXPR_BODY(NODE) (TREE_OPERAND (BIND_EXPR_CHECK (NODE), 1))
Index: doc/c-tree.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/c-tree.texi,v
retrieving revision 1.72
diff -u -p -r1.72 c-tree.texi
--- doc/c-tree.texi 5 Mar 2005 19:56:27 -0000 1.72
+++ doc/c-tree.texi 16 May 2005 18:56:28 -0000
@@ -1712,6 +1712,7 @@ This macro returns the attributes on the
@tindex EXACT_DIV_EXPR
@tindex ARRAY_REF
@tindex ARRAY_RANGE_REF
+@tindex MEM_REF
@tindex LT_EXPR
@tindex LE_EXPR
@tindex GT_EXPR
@@ -2103,6 +2104,12 @@ meanings. The type of these expressions
type is the same as that of the first operand. The range of that array
type determines the amount of data these expressions access.
+@item MEM_REF
+These nodes represent array operations on pointers. The first operand
+is the pointer we are operating on; the second is the index. To
+calculate the address of the memory accessed, you must scale the index
+by the size of the type of the pointed-to elements.
+
@item LT_EXPR
@itemx LE_EXPR
@itemx GT_EXPR
Index: doc/tree-ssa.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/tree-ssa.texi,v
retrieving revision 1.27
diff -u -p -r1.27 tree-ssa.texi
--- doc/tree-ssa.texi 4 May 2005 17:15:31 -0000 1.27
+++ doc/tree-ssa.texi 16 May 2005 18:56:28 -0000
@@ -614,6 +614,10 @@ void f()
with-size-arg: addressable
| call-stmt
+ memref : MEM_REF
+ op0 -> val
+ op1 -> val
+
indirectref : INDIRECT_REF
op0 -> val
@@ -625,6 +629,7 @@ void f()
min-lval : ID
| indirectref
+ | memref
bitfieldref : BIT_FIELD_REF
op0 -> inner-compref