This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH][RFT] Structure aliasing for arrays
- From: Richard Guenther <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 28 Jul 2005 14:44:58 +0200 (CEST)
- Subject: [PATCH][RFT] Structure aliasing for arrays
Finally I might have squeezed out all issues with the patch. You may
find it useful or want to experiment with it. Tune --param
max-salias-array-elements (it's currently low at 4, f.i. gfortran
would like 7 to disambiguate array descriptor stuff).
Bootstrapped and tested on x86_64-unknown-linux-gnu with all
default languages (including gfortran).
Comments?
Thanks,
Richard.
2005-07-22 Richard Guenther <rguenther@suse.de>
PR tree-optimization/22555
* Makefile.in (tree-ssa-structalias.o): Depend on $(PARAMS_H).
* expr.c (get_inner_reference): Fold constant offsets
in COMPONENT_REF and ARRAY_REF into bit_offset, if possible.
Handles a.a[1].a[i].
* params.def (salias-max-array-elements): New parameter.
* params.h (SALIAS_MAX_ARRAY_ELEMENTS): Define.
* doc/invoke.texi (salias-max-array-elements): Document.
* tree-cfg.c (replace_uses_by): Mark stmt for renaming.
* tree-dfa.c (okay_component_ref_for_subvars): Do not give up,
if one structure field is an array. Use more precise results
from get_inner_reference.
* tree-flow-inline.h (var_can_have_subvars): We also handle
arrays now.
* tree-flow.h (struct fieldoff): Use separate type and offset
field instead of storing FIELD_DECL in field.
* tree-ssa-alias.c (create_sft): We now take field type as
2nd argument.
(find_used_portions): Handle ARRAY_REF as COMPONENT_REF.
Use more precise information from get_inner_reference.
(create_overlap_variables_for): Do not give up, if one
structure field is an array. Adjust for field now
storing field type.
* tree-ssa-structalias.c (create_variable_info_for): Likewise.
(fieldoff_compare): Likewise.
(push_fields_onto_fieldstack): Likewise. Handle ARRAY_TYPE.
(params.h): Include.
(offset_overlaps_with_access): Avoid possible integer overflow.
(get_constraint_for_component_ref): Disable assert for accessing
non-existant fields.
(find_func_aliases): As for aggregate types, add anyoffset
constraint to array references.
* tree-ssa-loop-ivopts.c (get_ref_tag): Handle subvars.
(rewrite_use): Mark stmt for renaming.
* tree-ssa-operands.c (parse_ssa_operands): Handle ARRAY_REF
for creating MUST_DEFs.
(get_expr_operands): Treat ARRAY_REF like COMPONENT_REF wrt subvars.
(get_tmr_operands): For DECL_P TMR_TAGs add all possible subvars.
* tree-ssa-loop.c (pass_scev_prop): Schedule TODO_update_ssa.
(pass_complete_unroll): Likewise.
(pass_iv_optimize): Likewise.
(pass_tree_loop_done): Likewise.
Index: Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v
retrieving revision 1.1530
diff -c -3 -p -r1.1530 Makefile.in
*** Makefile.in 25 Jul 2005 23:04:33 -0000 1.1530
--- Makefile.in 28 Jul 2005 12:17:28 -0000
*************** stor-layout.o : stor-layout.c $(CONFIG_H
*** 1726,1732 ****
toplev.h
tree-ssa-structalias.o: tree-ssa-structalias.c tree-ssa-structalias.h \
$(SYSTEM_H) $(CONFIG_H) $(GGC_H) $(TREE_H) $(TREE_FLOW_H) \
! $(TM_H) coretypes.h cgraph.h tree-pass.h $(TIMEVAR_H)
tree-ssa.o : tree-ssa.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
$(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) output.h $(DIAGNOSTIC_H) \
toplev.h function.h $(TIMEVAR_H) $(TM_H) coretypes.h \
--- 1726,1732 ----
toplev.h
tree-ssa-structalias.o: tree-ssa-structalias.c tree-ssa-structalias.h \
$(SYSTEM_H) $(CONFIG_H) $(GGC_H) $(TREE_H) $(TREE_FLOW_H) \
! $(TM_H) coretypes.h cgraph.h tree-pass.h $(TIMEVAR_H) $(PARAMS_H)
tree-ssa.o : tree-ssa.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
$(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) output.h $(DIAGNOSTIC_H) \
toplev.h function.h $(TIMEVAR_H) $(TM_H) coretypes.h \
Index: expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.c,v
retrieving revision 1.806
diff -c -3 -p -r1.806 expr.c
*** expr.c 25 Jul 2005 12:04:45 -0000 1.806
--- expr.c 28 Jul 2005 12:17:28 -0000
*************** get_inner_reference (tree exp, HOST_WIDE
*** 5452,5457 ****
--- 5452,5458 ----
tree size_tree = 0;
enum machine_mode mode = VOIDmode;
tree offset = size_zero_node;
+ tree coffset = size_zero_node;
tree bit_offset = bitsize_zero_node;
tree tem;
*************** get_inner_reference (tree exp, HOST_WIDE
*** 5511,5517 ****
if (this_offset == 0)
break;
! offset = size_binop (PLUS_EXPR, offset, this_offset);
bit_offset = size_binop (PLUS_EXPR, bit_offset,
DECL_FIELD_BIT_OFFSET (field));
--- 5512,5522 ----
if (this_offset == 0)
break;
! if (TREE_CODE (this_offset) == INTEGER_CST)
! coffset = size_binop (PLUS_EXPR, coffset, this_offset);
! else
! offset = size_binop (PLUS_EXPR, offset, this_offset);
!
bit_offset = size_binop (PLUS_EXPR, bit_offset,
DECL_FIELD_BIT_OFFSET (field));
*************** get_inner_reference (tree exp, HOST_WIDE
*** 5533,5543 ****
if (! integer_zerop (low_bound))
index = fold_build2 (MINUS_EXPR, TREE_TYPE (index),
index, low_bound);
!
! offset = size_binop (PLUS_EXPR, offset,
! size_binop (MULT_EXPR,
! convert (sizetype, index),
! unit_size));
}
break;
--- 5538,5548 ----
if (! integer_zerop (low_bound))
index = fold_build2 (MINUS_EXPR, TREE_TYPE (index),
index, low_bound);
! index = size_binop (MULT_EXPR, convert (sizetype, index), unit_size);
! if (TREE_CODE (index) == INTEGER_CST)
! coffset = size_binop (PLUS_EXPR, coffset, index);
! else
! offset = size_binop (PLUS_EXPR, offset, index);
}
break;
*************** get_inner_reference (tree exp, HOST_WIDE
*** 5572,5587 ****
}
done:
! /* If OFFSET is constant, see if we can return the whole thing as a
! constant bit position. Otherwise, split it up. */
! if (host_integerp (offset, 0)
! && 0 != (tem = size_binop (MULT_EXPR, convert (bitsizetype, offset),
bitsize_unit_node))
&& 0 != (tem = size_binop (PLUS_EXPR, tem, bit_offset))
&& host_integerp (tem, 0))
! *pbitpos = tree_low_cst (tem, 0), *poffset = 0;
else
! *pbitpos = tree_low_cst (bit_offset, 0), *poffset = offset;
*pmode = mode;
return exp;
--- 5577,5600 ----
}
done:
! /* See, if we can return COFFSET in the constant bit position, otherwise
! fold into OFFSET. */
! if (host_integerp (coffset, 0)
! && 0 != (tem = size_binop (MULT_EXPR, convert (bitsizetype, coffset),
bitsize_unit_node))
&& 0 != (tem = size_binop (PLUS_EXPR, tem, bit_offset))
&& host_integerp (tem, 0))
! {
! *pbitpos = tree_low_cst (tem, 0);
! *poffset = offset;
! }
else
! {
! *pbitpos = tree_low_cst (bit_offset, 0);
! *poffset = size_binop (PLUS_EXPR, coffset, offset);
! }
! if (integer_zerop (*poffset))
! *poffset = NULL_TREE;
*pmode = mode;
return exp;
Index: params.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/params.def,v
retrieving revision 1.62
diff -c -3 -p -r1.62 params.def
*** params.def 2 Jul 2005 13:18:25 -0000 1.62
--- params.def 28 Jul 2005 12:17:28 -0000
*************** DEFPARAM (PARAM_SALIAS_MAX_IMPLICIT_FIEL
*** 42,48 ****
"salias-max-implicit-fields",
"The maximum number of fields in a structure variable without direct structure accesses that GCC will attempt to track separately",
5, 0, 0)
!
/* The maximum structure size at which the scalar replacement of
aggregates (SRA) pass will perform block copies. The default
value, 0, implies that GCC will select the most appropriate size
--- 42,55 ----
"salias-max-implicit-fields",
"The maximum number of fields in a structure variable without direct structure accesses that GCC will attempt to track separately",
5, 0, 0)
!
! /* The maximum number of array elements structure aliasing will decompose
! an array for. The default is 4. */
! DEFPARAM (PARAM_SALIAS_MAX_ARRAY_ELEMENTS,
! "salias-max-array-elements",
! "The maximum number of elements in an array for wich we track its elements separately",
! 4, 0, 0)
!
/* The maximum structure size at which the scalar replacement of
aggregates (SRA) pass will perform block copies. The default
value, 0, implies that GCC will select the most appropriate size
Index: params.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/params.h,v
retrieving revision 1.31
diff -c -3 -p -r1.31 params.h
*** params.h 25 Jun 2005 02:00:43 -0000 1.31
--- params.h 28 Jul 2005 12:17:28 -0000
*************** typedef enum compiler_param
*** 91,96 ****
--- 91,98 ----
/* Macros for the various parameters. */
#define SALIAS_MAX_IMPLICIT_FIELDS \
PARAM_VALUE (PARAM_SALIAS_MAX_IMPLICIT_FIELDS)
+ #define SALIAS_MAX_ARRAY_ELEMENTS \
+ PARAM_VALUE (PARAM_SALIAS_MAX_ARRAY_ELEMENTS)
#define SRA_MAX_STRUCTURE_SIZE \
PARAM_VALUE (PARAM_SRA_MAX_STRUCTURE_SIZE)
#define SRA_FIELD_STRUCTURE_RATIO \
Index: doc/invoke.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/invoke.texi,v
retrieving revision 1.655
diff -c -3 -p -r1.655 invoke.texi
*** doc/invoke.texi 25 Jul 2005 19:42:02 -0000 1.655
--- doc/invoke.texi 28 Jul 2005 12:40:27 -0000
*************** The maximum number of fields in a variab
*** 5666,5671 ****
--- 5666,5675 ----
structure accesses for which structure aliasing will consider trying
to track each field. The default is 5
+ @item salias-max-array-elements
+ The maximum number of elements an array can have and its elements
+ still be tracked individually by structure aliasing. The default is 4
+
@item sra-max-structure-size
The maximum structure size, in bytes, at which the scalar replacement
of aggregates (SRA) optimization will perform block copies. The
Index: tree-cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-cfg.c,v
retrieving revision 2.211
diff -c -3 -p -r2.211 tree-cfg.c
*** tree-cfg.c 12 Jul 2005 13:20:28 -0000 2.211
--- tree-cfg.c 28 Jul 2005 12:17:28 -0000
*************** replace_uses_by (tree name, tree val)
*** 1225,1230 ****
--- 1225,1231 ----
stmt = USE_STMT (use);
SET_USE (use, val);
+ mark_new_vars_to_rename (stmt);
if (TREE_CODE (stmt) == PHI_NODE)
{
Index: tree-dfa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-dfa.c,v
retrieving revision 2.62
diff -c -3 -p -r2.62 tree-dfa.c
*** tree-dfa.c 25 Jul 2005 14:00:59 -0000 2.62
--- tree-dfa.c 28 Jul 2005 12:17:28 -0000
*************** okay_component_ref_for_subvars (tree ref
*** 810,817 ****
*poffset = 0;
*psize = (unsigned int) -1;
- if (ref_contains_array_ref (ref))
- return result;
ref = get_inner_reference (ref, &bitsize, &bitpos, &offset, &mode,
&unsignedp, &volatilep, false);
if (TREE_CODE (ref) == INDIRECT_REF)
--- 810,815 ----
*************** okay_component_ref_for_subvars (tree ref
*** 823,828 ****
--- 821,834 ----
if (get_subvars_for_var (ref) != NULL)
return ref;
}
+ else if (offset && bitsize != -1 && SSA_VAR_P (ref))
+ {
+ /* We assume the offset part is positive only. A resonable assumption. */
+ *poffset = bitpos;
+ *psize = (unsigned int) -1;
+ if (get_subvars_for_var (ref) != NULL)
+ return ref;
+ }
else if (SSA_VAR_P (ref))
{
if (get_subvars_for_var (ref) != NULL)
Index: tree-flow-inline.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-flow-inline.h,v
retrieving revision 2.54
diff -c -3 -p -r2.54 tree-flow-inline.h
*** tree-flow-inline.h 25 Jul 2005 14:01:02 -0000 2.54
--- tree-flow-inline.h 28 Jul 2005 12:17:28 -0000
*************** get_subvar_at (tree var, unsigned HOST_W
*** 1477,1484 ****
static inline bool
var_can_have_subvars (tree v)
{
! return (AGGREGATE_TYPE_P (TREE_TYPE (v)) &&
! TREE_CODE (TREE_TYPE (v)) != ARRAY_TYPE);
}
--- 1477,1483 ----
static inline bool
var_can_have_subvars (tree v)
{
! return (AGGREGATE_TYPE_P (TREE_TYPE (v)));
}
Index: tree-flow.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-flow.h,v
retrieving revision 2.130
diff -c -3 -p -r2.130 tree-flow.h
*** tree-flow.h 25 Jul 2005 12:04:49 -0000 2.130
--- tree-flow.h 28 Jul 2005 12:17:28 -0000
*************** tree maybe_fold_tmr (tree);
*** 874,880 ****
struct fieldoff
{
! tree field;
HOST_WIDE_INT offset;
};
typedef struct fieldoff fieldoff_s;
--- 874,881 ----
struct fieldoff
{
! tree type;
! tree size;
HOST_WIDE_INT offset;
};
typedef struct fieldoff fieldoff_s;
Index: tree-ssa-alias.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-alias.c,v
retrieving revision 2.108
diff -c -3 -p -r2.108 tree-ssa-alias.c
*** tree-ssa-alias.c 26 Jul 2005 19:53:42 -0000 2.108
--- tree-ssa-alias.c 28 Jul 2005 12:17:28 -0000
*************** static tree
*** 2502,2508 ****
create_sft (tree var, tree field)
{
var_ann_t ann;
! tree subvar = create_tmp_var_raw (TREE_TYPE (field), "SFT");
/* We need to copy the various flags from VAR to SUBVAR, so that
they are is_global_var iff the original variable was. */
--- 2504,2510 ----
create_sft (tree var, tree field)
{
var_ann_t ann;
! tree subvar = create_tmp_var_raw (field, "SFT");
/* We need to copy the various flags from VAR to SUBVAR, so that
they are is_global_var iff the original variable was. */
*************** create_overlap_variables_for (tree var)
*** 2559,2567 ****
for (i = 0; VEC_iterate (fieldoff_s, fieldstack, i, fo); i++)
{
! if (!DECL_SIZE (fo->field)
! || TREE_CODE (DECL_SIZE (fo->field)) != INTEGER_CST
! || TREE_CODE (TREE_TYPE (fo->field)) == ARRAY_TYPE
|| fo->offset < 0)
{
notokay = true;
--- 2561,2568 ----
for (i = 0; VEC_iterate (fieldoff_s, fieldstack, i, fo); i++)
{
! if (! fo->size
! || TREE_CODE (fo->size) != INTEGER_CST
|| fo->offset < 0)
{
notokay = true;
*************** create_overlap_variables_for (tree var)
*** 2601,2606 ****
--- 2602,2615 ----
return;
}
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "Variable ");
+ print_generic_expr (dump_file, var, 0);
+ fprintf (dump_file, " has uses from offset " HOST_WIDE_INT_PRINT_DEC
+ " to " HOST_WIDE_INT_PRINT_DEC "\n", up->minused, up->maxused);
+ }
+
/* Otherwise, create the variables. */
subvars = lookup_subvars_for_var (var);
*************** create_overlap_variables_for (tree var)
*** 2613,2620 ****
HOST_WIDE_INT fosize;
tree currfotype;
! fosize = TREE_INT_CST_LOW (DECL_SIZE (fo->field));
! currfotype = TREE_TYPE (fo->field);
/* If this field isn't in the used portion,
or it has the exact same offset and size as the last
--- 2622,2629 ----
HOST_WIDE_INT fosize;
tree currfotype;
! fosize = TREE_INT_CST_LOW (fo->size);
! currfotype = fo->type;
/* If this field isn't in the used portion,
or it has the exact same offset and size as the last
*************** create_overlap_variables_for (tree var)
*** 2631,2637 ****
sv->offset = fo->offset;
sv->size = fosize;
sv->next = *subvars;
! sv->var = create_sft (var, fo->field);
if (dump_file)
{
--- 2640,2646 ----
sv->offset = fo->offset;
sv->size = fosize;
sv->next = *subvars;
! sv->var = create_sft (var, fo->type);
if (dump_file)
{
*************** find_used_portions (tree *tp, int *walk_
*** 2677,2682 ****
--- 2686,2692 ----
switch (TREE_CODE (*tp))
{
case COMPONENT_REF:
+ case ARRAY_REF:
{
HOST_WIDE_INT bitsize;
HOST_WIDE_INT bitpos;
*************** find_used_portions (tree *tp, int *walk_
*** 2705,2710 ****
--- 2715,2742 ----
*walk_subtrees = 0;
return NULL_TREE;
}
+ else if (DECL_P (ref) && offset && bitsize != -1)
+ {
+ if (DECL_SIZE (ref)
+ && var_can_have_subvars (ref)
+ && TREE_CODE (DECL_SIZE (ref)) == INTEGER_CST)
+ {
+ used_part_t up;
+ size_t uid = DECL_UID (ref);
+
+ up = get_or_create_used_part_for (uid);
+
+ if (bitpos <= up->minused)
+ up->minused = bitpos;
+ up->maxused = TREE_INT_CST_LOW (DECL_SIZE (ref));
+
+ up->implicit_uses = true;
+ up_insert (uid, up);
+
+ *walk_subtrees = 0;
+ return NULL_TREE;
+ }
+ }
else if (DECL_P (ref))
{
if (DECL_SIZE (ref)
Index: tree-ssa-loop-ivopts.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-loop-ivopts.c,v
retrieving revision 2.85
diff -c -3 -p -r2.85 tree-ssa-loop-ivopts.c
*** tree-ssa-loop-ivopts.c 21 Jul 2005 07:24:10 -0000 2.85
--- tree-ssa-loop-ivopts.c 28 Jul 2005 12:17:28 -0000
*************** unshare_and_remove_ssa_names (tree ref)
*** 5428,5438 ****
and extracts this single useful piece of information. */
static tree
! get_ref_tag (tree ref)
{
! tree var = get_base_address (ref);
tree tag;
if (!var)
return NULL_TREE;
--- 5428,5453 ----
and extracts this single useful piece of information. */
static tree
! get_ref_tag (tree ref_)
{
! tree var = get_base_address (ref_);
! unsigned HOST_WIDE_INT offset, size;
! tree ref = okay_component_ref_for_subvars (ref_, &offset, &size);
tree tag;
+ if (ref)
+ {
+ subvar_t svars = get_subvars_for_var (ref);
+ subvar_t sv;
+ for (sv = svars; sv; sv = sv->next)
+ {
+ bool exact;
+ if (overlap_subvar (offset, size, sv, &exact)
+ && exact)
+ return sv->var;
+ }
+ }
+
if (!var)
return NULL_TREE;
*************** rewrite_use (struct ivopts_data *data,
*** 5746,5751 ****
--- 5761,5767 ----
gcc_unreachable ();
}
update_stmt (use->stmt);
+ mark_new_vars_to_rename (use->stmt);
}
/* Rewrite the uses using the selected induction variables. */
Index: tree-ssa-loop.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-loop.c,v
retrieving revision 2.33
diff -c -3 -p -r2.33 tree-ssa-loop.c
*** tree-ssa-loop.c 19 Jul 2005 00:44:45 -0000 2.33
--- tree-ssa-loop.c 28 Jul 2005 12:17:28 -0000
*************** struct tree_opt_pass pass_scev_cprop =
*** 307,313 ****
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
! TODO_dump_func, /* todo_flags_finish */
0 /* letter */
};
--- 332,338 ----
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
! TODO_dump_func | TODO_update_ssa, /* todo_flags_finish */
0 /* letter */
};
*************** struct tree_opt_pass pass_complete_unrol
*** 401,407 ****
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
! TODO_dump_func | TODO_verify_loops, /* todo_flags_finish */
0 /* letter */
};
--- 426,432 ----
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
! TODO_dump_func | TODO_verify_loops | TODO_update_ssa, /* todo_flags_finish */
0 /* letter */
};
*************** struct tree_opt_pass pass_iv_optimize =
*** 435,441 ****
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
! TODO_dump_func | TODO_verify_loops, /* todo_flags_finish */
0 /* letter */
};
--- 460,466 ----
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
! TODO_dump_func | TODO_verify_loops | TODO_update_ssa, /* todo_flags_finish */
0 /* letter */
};
*************** struct tree_opt_pass pass_tree_loop_done
*** 467,472 ****
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
! TODO_cleanup_cfg | TODO_dump_func, /* todo_flags_finish */
0 /* letter */
};
--- 492,497 ----
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
! TODO_cleanup_cfg | TODO_dump_func | TODO_update_ssa, /* todo_flags_finish */
0 /* letter */
};
Index: tree-ssa-operands.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-operands.c,v
retrieving revision 2.98
diff -c -3 -p -r2.98 tree-ssa-operands.c
*** tree-ssa-operands.c 21 Jul 2005 11:52:59 -0000 2.98
--- tree-ssa-operands.c 28 Jul 2005 12:17:28 -0000
*************** parse_ssa_operands (tree stmt)
*** 897,904 ****
if (TREE_CODE (lhs) == VIEW_CONVERT_EXPR)
lhs = TREE_OPERAND (lhs, 0);
! 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)
--- 897,903 ----
if (TREE_CODE (lhs) == VIEW_CONVERT_EXPR)
lhs = TREE_OPERAND (lhs, 0);
! if (TREE_CODE (lhs) != ARRAY_RANGE_REF
&& TREE_CODE (lhs) != BIT_FIELD_REF
&& TREE_CODE (lhs) != REALPART_EXPR
&& TREE_CODE (lhs) != IMAGPART_EXPR)
*************** get_expr_operands (tree stmt, tree *expr
*** 1288,1316 ****
case ARRAY_REF:
case ARRAY_RANGE_REF:
- /* Treat array references as references to the virtual variable
- representing the array. The virtual variable for an ARRAY_REF
- is the VAR_DECL for the array. */
-
- /* Add the virtual variable for the ARRAY_REF to VDEFS or VUSES
- according to the value of IS_DEF. Recurse if the LHS of the
- ARRAY_REF node is not a regular variable. */
- if (SSA_VAR_P (TREE_OPERAND (expr, 0)))
- add_stmt_operand (expr_p, s_ann, flags);
- else
- get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags);
-
- get_expr_operands (stmt, &TREE_OPERAND (expr, 1), opf_none);
- get_expr_operands (stmt, &TREE_OPERAND (expr, 2), opf_none);
- get_expr_operands (stmt, &TREE_OPERAND (expr, 3), opf_none);
- return;
-
case COMPONENT_REF:
case REALPART_EXPR:
case IMAGPART_EXPR:
{
tree ref;
unsigned HOST_WIDE_INT offset, size;
/* This component ref becomes an access to all of the subvariables
it can touch, if we can determine that, but *NOT* the real one.
If we can't determine which fields we could touch, the recursion
--- 1287,1299 ----
case ARRAY_REF:
case ARRAY_RANGE_REF:
case COMPONENT_REF:
case REALPART_EXPR:
case IMAGPART_EXPR:
{
tree ref;
unsigned HOST_WIDE_INT offset, size;
+ bool none = true;
/* This component ref becomes an access to all of the subvariables
it can touch, if we can determine that, but *NOT* the real one.
If we can't determine which fields we could touch, the recursion
*************** get_expr_operands (tree stmt, tree *expr
*** 1328,1342 ****
if (overlap_subvar (offset, size, sv, &exact))
{
int subvar_flags = flags;
if (!exact)
subvar_flags &= ~opf_kill_def;
add_stmt_operand (&sv->var, s_ann, subvar_flags);
}
}
}
! else
! get_expr_operands (stmt, &TREE_OPERAND (expr, 0),
! flags & ~opf_kill_def);
if (code == COMPONENT_REF)
{
--- 1311,1327 ----
if (overlap_subvar (offset, size, sv, &exact))
{
int subvar_flags = flags;
+ none = false;
if (!exact)
subvar_flags &= ~opf_kill_def;
add_stmt_operand (&sv->var, s_ann, subvar_flags);
}
}
+ if (! none)
+ flags |= opf_no_vops;
}
! get_expr_operands (stmt, &TREE_OPERAND (expr, 0),
! flags & ~opf_kill_def);
if (code == COMPONENT_REF)
{
*************** get_expr_operands (tree stmt, tree *expr
*** 1344,1349 ****
--- 1329,1341 ----
s_ann->has_volatile_ops = true;
get_expr_operands (stmt, &TREE_OPERAND (expr, 2), opf_none);
}
+ else if (code == ARRAY_REF
+ || code == ARRAY_RANGE_REF)
+ {
+ get_expr_operands (stmt, &TREE_OPERAND (expr, 1), opf_none);
+ get_expr_operands (stmt, &TREE_OPERAND (expr, 2), opf_none);
+ get_expr_operands (stmt, &TREE_OPERAND (expr, 3), opf_none);
+ }
return;
}
case WITH_SIZE_EXPR:
*************** get_expr_operands (tree stmt, tree *expr
*** 1374,1381 ****
op = TREE_OPERAND (expr, 0);
if (TREE_CODE (op) == WITH_SIZE_EXPR)
op = TREE_OPERAND (expr, 0);
! if (TREE_CODE (op) == ARRAY_REF
! || TREE_CODE (op) == ARRAY_RANGE_REF
|| TREE_CODE (op) == REALPART_EXPR
|| TREE_CODE (op) == IMAGPART_EXPR)
subflags = opf_is_def;
--- 1366,1372 ----
op = TREE_OPERAND (expr, 0);
if (TREE_CODE (op) == WITH_SIZE_EXPR)
op = TREE_OPERAND (expr, 0);
! if (TREE_CODE (op) == ARRAY_RANGE_REF
|| TREE_CODE (op) == REALPART_EXPR
|| TREE_CODE (op) == IMAGPART_EXPR)
subflags = opf_is_def;
*************** get_tmr_operands (tree stmt, tree expr,
*** 1698,1704 ****
}
if (tag)
! add_stmt_operand (&tag, stmt_ann (stmt), flags);
else
/* Something weird, so ensure that we will be careful. */
stmt_ann (stmt)->has_volatile_ops = true;
--- 1689,1700 ----
}
if (tag)
! {
! if (! DECL_P (tag))
! add_stmt_operand (&tag, stmt_ann (stmt), flags);
! else
! get_expr_operands (stmt, &tag, flags);
! }
else
/* Something weird, so ensure that we will be careful. */
stmt_ann (stmt)->has_volatile_ops = true;
Index: tree-ssa-structalias.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-structalias.c,v
retrieving revision 2.24
diff -c -3 -p -r2.24 tree-ssa-structalias.c
*** tree-ssa-structalias.c 26 Jul 2005 13:53:51 -0000 2.24
--- tree-ssa-structalias.c 28 Jul 2005 12:17:28 -0000
*************** Foundation, Inc., 51 Franklin Street, Fi
*** 48,53 ****
--- 48,54 ----
#include "timevar.h"
#include "alloc-pool.h"
#include "splay-tree.h"
+ #include "params.h"
#include "tree-ssa-structalias.h"
/* The idea behind this analyzer is to generate set constraints from the
*************** offset_overlaps_with_access (const unsig
*** 1989,1997 ****
{
if (fieldpos == accesspos && fieldsize == accesssize)
return true;
! if (accesspos >= fieldpos && accesspos < (fieldpos + fieldsize))
return true;
! if (accesspos < fieldpos && (accesspos + accesssize > fieldpos))
return true;
return false;
--- 1990,1998 ----
{
if (fieldpos == accesspos && fieldsize == accesssize)
return true;
! if (accesspos >= fieldpos && (accesspos - fieldpos) < fieldsize)
return true;
! if (accesspos < fieldpos && accesssize > (fieldpos - accesspos))
return true;
return false;
*************** get_constraint_for_component_ref (tree t
*** 2075,2082 ****
}
/* assert that we found *some* field there. The user couldn't be
accessing *only* padding. */
!
! gcc_assert (curr);
}
else
if (dump_file && (dump_flags & TDF_DETAILS))
--- 2076,2084 ----
}
/* assert that we found *some* field there. The user couldn't be
accessing *only* padding. */
! /* Still the user could access one past the end of an array
! embedded in a struct resulting in accessing *only* padding. */
! /* gcc_assert (curr); */
}
else
if (dump_file && (dump_flags & TDF_DETAILS))
*************** find_func_aliases (tree t, struct alias_
*** 2829,2835 ****
of the RHS. */
if (rhs.type == ADDRESSOF
&& !(get_varinfo (rhs.var)->is_special_var)
! && AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (rhsop))))
{
rhs.var = anyoffset_id;
rhs.type = ADDRESSOF;
--- 2831,2839 ----
of the RHS. */
if (rhs.type == ADDRESSOF
&& !(get_varinfo (rhs.var)->is_special_var)
! && (AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (rhsop)))
! || TREE_CODE (TREE_TYPE (TREE_OPERAND (rhsop, 0))) == ARRAY_TYPE
! || TREE_CODE (TREE_OPERAND (rhsop, 0)) == ARRAY_REF))
{
rhs.var = anyoffset_id;
rhs.type = ADDRESSOF;
*************** fieldoff_compare (const void *pa, const
*** 2939,2946 ****
if (foa->offset != fob->offset)
return foa->offset - fob->offset;
! foasize = TREE_INT_CST_LOW (DECL_SIZE (foa->field));
! fobsize = TREE_INT_CST_LOW (DECL_SIZE (fob->field));
return foasize - fobsize;
}
--- 2943,2950 ----
if (foa->offset != fob->offset)
return foa->offset - fob->offset;
! foasize = TREE_INT_CST_LOW (foa->size);
! fobsize = TREE_INT_CST_LOW (fob->size);
return foasize - fobsize;
}
*************** push_fields_onto_fieldstack (tree type,
*** 2968,2973 ****
--- 2972,3026 ----
tree field;
int count = 0;
+ if (TREE_CODE (type) == ARRAY_TYPE)
+ {
+ tree sz = TYPE_SIZE (type);
+ tree elsz = TYPE_SIZE (TREE_TYPE (type));
+ HOST_WIDE_INT nr;
+ int i;
+ if (! sz || ! host_integerp (sz, 1)
+ || ! elsz || ! host_integerp (elsz, 1))
+ return 0;
+ nr = TREE_INT_CST_LOW (sz) / TREE_INT_CST_LOW (elsz);
+ if (nr > SALIAS_MAX_ARRAY_ELEMENTS)
+ return 0;
+ for (i = 0; i<nr; ++i)
+ {
+ bool push = false;
+ int pushed = 0;
+
+ if (has_union
+ && (TREE_CODE (TREE_TYPE (type)) == QUAL_UNION_TYPE
+ || TREE_CODE (TREE_TYPE (type)) == UNION_TYPE))
+ *has_union = true;
+
+ if (!AGGREGATE_TYPE_P (TREE_TYPE (type))) /* var_can_have_subvars */
+ push = true;
+ else if (!(pushed = push_fields_onto_fieldstack
+ (TREE_TYPE (type), fieldstack,
+ offset + i * TREE_INT_CST_LOW (elsz), has_union)))
+ /* Empty structures may have actual size, like in C++. So
+ see if we didn't push any subfields and the size is
+ nonzero, push the field onto the stack */
+ push = true;
+
+ if (push)
+ {
+ fieldoff_s *pair;
+
+ pair = VEC_safe_push (fieldoff_s, heap, *fieldstack, NULL);
+ pair->type = TREE_TYPE (type);
+ pair->size = elsz;
+ pair->offset = offset + i * TREE_INT_CST_LOW (elsz);
+ count++;
+ }
+ else
+ count += pushed;
+ }
+ /*return 1;*/
+ }
+ else
+ {
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
if (TREE_CODE (field) == FIELD_DECL)
{
*************** push_fields_onto_fieldstack (tree type,
*** 2996,3009 ****
fieldoff_s *pair;
pair = VEC_safe_push (fieldoff_s, heap, *fieldstack, NULL);
! pair->field = field;
pair->offset = offset + bitpos_of_field (field);
count++;
}
else
count += pushed;
}
!
return count;
}
--- 3049,3063 ----
fieldoff_s *pair;
pair = VEC_safe_push (fieldoff_s, heap, *fieldstack, NULL);
! pair->type = TREE_TYPE (field);
! pair->size = DECL_SIZE (field);
pair->offset = offset + bitpos_of_field (field);
count++;
}
else
count += pushed;
}
! }
return count;
}
*************** create_variable_info_for (tree decl, con
*** 3057,3063 ****
vi->has_union = hasunion;
if (!TYPE_SIZE (decltype)
|| TREE_CODE (TYPE_SIZE (decltype)) != INTEGER_CST
- || TREE_CODE (decltype) == ARRAY_TYPE
|| TREE_CODE (decltype) == UNION_TYPE
|| TREE_CODE (decltype) == QUAL_UNION_TYPE)
{
--- 3114,3119 ----
*************** create_variable_info_for (tree decl, con
*** 3085,3097 ****
unsigned int newindex = VEC_length (varinfo_t, varmap);
fieldoff_s *fo = NULL;
unsigned int i;
- tree field;
for (i = 0; !notokay && VEC_iterate (fieldoff_s, fieldstack, i, fo); i++)
{
! if (!DECL_SIZE (fo->field)
! || TREE_CODE (DECL_SIZE (fo->field)) != INTEGER_CST
! || TREE_CODE (TREE_TYPE (fo->field)) == ARRAY_TYPE
|| fo->offset < 0)
{
notokay = true;
--- 3141,3151 ----
unsigned int newindex = VEC_length (varinfo_t, varmap);
fieldoff_s *fo = NULL;
unsigned int i;
for (i = 0; !notokay && VEC_iterate (fieldoff_s, fieldstack, i, fo); i++)
{
! if (! fo->size
! || TREE_CODE (fo->size) != INTEGER_CST
|| fo->offset < 0)
{
notokay = true;
*************** create_variable_info_for (tree decl, con
*** 3118,3125 ****
return index;
}
! field = fo->field;
! vi->size = TREE_INT_CST_LOW (DECL_SIZE (field));
vi->offset = fo->offset;
for (i = 1; VEC_iterate (fieldoff_s, fieldstack, i, fo); i++)
{
--- 3172,3178 ----
return index;
}
! vi->size = TREE_INT_CST_LOW (fo->size);
vi->offset = fo->offset;
for (i = 1; VEC_iterate (fieldoff_s, fieldstack, i, fo); i++)
{
*************** create_variable_info_for (tree decl, con
*** 3127,3140 ****
const char *newname;
char *tempname;
- field = fo->field;
newindex = VEC_length (varinfo_t, varmap);
! asprintf (&tempname, "%s.%s", vi->name, alias_get_name (field));
newname = ggc_strdup (tempname);
free (tempname);
newvi = new_var_info (decl, newindex, newname, newindex);
newvi->offset = fo->offset;
! newvi->size = TREE_INT_CST_LOW (DECL_SIZE (field));
newvi->fullsize = vi->fullsize;
insert_into_field_list (vi, newvi);
VEC_safe_push (varinfo_t, heap, varmap, newvi);
--- 3180,3192 ----
const char *newname;
char *tempname;
newindex = VEC_length (varinfo_t, varmap);
! asprintf (&tempname, "%s.%u", vi->name, i);
newname = ggc_strdup (tempname);
free (tempname);
newvi = new_var_info (decl, newindex, newname, newindex);
newvi->offset = fo->offset;
! newvi->size = TREE_INT_CST_LOW (fo->size);
newvi->fullsize = vi->fullsize;
insert_into_field_list (vi, newvi);
VEC_safe_push (varinfo_t, heap, varmap, newvi);