aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-ccp.c
diff options
context:
space:
mode:
authorRichard Kenner <kenner@vlsi1.ultra.nyu.edu>2004-06-22 03:07:05 +0000
committerRichard Kenner <kenner@gcc.gnu.org>2004-06-21 23:07:05 -0400
commit44de5aeb00a66307236cb5b7ccfca1a21aaca080 (patch)
tree0f08ba8e2fff4040497202121f17db146e774840 /gcc/tree-ssa-ccp.c
parent6264b0a68d820604c6b85a4c093de22bef6382cf (diff)
downloadgcc-44de5aeb00a66307236cb5b7ccfca1a21aaca080.zip
gcc-44de5aeb00a66307236cb5b7ccfca1a21aaca080.tar.gz
gcc-44de5aeb00a66307236cb5b7ccfca1a21aaca080.tar.bz2
alias.c (adjust_offset_for_component_ref): Use component_ref_field_offset.
* alias.c (adjust_offset_for_component_ref): Use component_ref_field_offset. * c-decl.c (build_array_declarator): Add news args for ARRAY_REF. * c-gimplify.c (gimplify_expr_stmt): Use alloc_stmt_list. (gimplify_decl_stmt): Call gimplify_type_sizes for type. For decl, call gimplify_one_sizepos and use statement list. (gimplify_compound_literal_expr): New arg PRE_P. Add statement to PRE_P list and return DECL. (c_gimplify_expr, case COMPOUND_LITERAL_EXPR): Add arg to gimplify_compound_literal_expr. * c-tree.h (getdecls): Deleted. * c-typeck.c (build_component_ref): Add operand for COMPONENT_REF. (build_array_ref): Add two operands for ARRAY_REF. (build_unary_op): Set TREE_INVARIANT and TREE_CONSTANT for COMPOUND_LITERAL_EXPR. * coverage.c (tree_coverage_counter_ref): Add new operands for ARRAY_REF. * emit-rtl.c (component_ref_for_mem_expr): Add new operand for COMPONENT_REF. (set_mem_attributes_minus_bitpos): Use array_ref_low_bound and array_ref_element_size. (widen_memory_access):Use component_ref_field_offset. * explow.c (update_nonlocal_goto_save_area): Add two operands for ARRAY_REF. * expr.c (array_ref_element_size, array_ref_low_bound): New functions. (component_ref_field_offset): Likewise. (get_inner_reference): Use them. (expand_expr_real_1, case ARRAY_REF): Use array_ref_low_bound. * fold-const.c (fold, case EQ_EXPR): Properly handle DECL_SIZE. (fold_read_from_constant_string): Use array_ref_low_bound. Verify that result is a character type. (build_fold_indirect_ref): Add two operands for ARRAY_REF. * function.c (expand_function_start): Likewise. * gimple-low.c (expand_var_p): Delete duplicated line. * gimplify.c: Add static decls for local functions. (cgraph.h): Now included. (create_tmp_var): Remove check for ARRAY_TYPE. (copy_if_shared_r): Look at bounds and sizes of types. (build_and_jump): Return alloc_stmt_list instead of build_empty_stmt. (gimplify_exit_expr, shortcut_cond_expr): Likewise. (gimplify_save_expr, gimple_push_cleanup): Likewise. (gimplify_init_constructor): Likewise. WANT_VALUE now bool. If empty list with no result wanted, return GS_UNHANDLED. Add additional operands for ARRAY_REF and COMPONENT_REF. (canonicalize_component_ref): Convert to &array[L]. (gimplify_array_ref_to_plus): Use array_ref_element_size and array_ref_lower_bound. (build_addr_expr_with_type, build_addr_expr): New functions. (gimplify_compound_lval): WANT_LVALUE now bool. Major rework to allow handle_component_p and initialize and gimplify new operands for ARRAY_REF, ARRAY_RANGE_REF, and COMPONENT_REF. (gimplify_array_ref): Deleted. (gimplify_self_mod_expr): WANT_VALUE now bool. (gimplify_modify_expr): Gimplify to_p and from_p later. Factor out code into gimplify_modify_expr_rhs and call twice. Move variable-size code earlier and handle PLACEHOLDER_EXPR. (gimplify_modify_expr_rhs, gimplify_variable_sized_compare): New fns. (gimplify_addr_expr, case VIEW_CONVERT_EXPR): New case. (gimplify_expr, case ARRAY_REF): Delete special case. Instead handle like COMPONENT_REF; also do ARRAY_RANGE_REF, IMAGPART, and REALPART the same way. (gimplify_expr, case VIEW_CONVERT_EXPR): New case. (gimplify_expr): Call gimplify_variable_sized_compare if applicable. Call alloc_stmt_list instead of build_empty_stmt. Deal with _REF that's volatile. (gimplify_type_sizes, gimplify_one_sizepos): New functions. (unshare_body, unvisit_body): New functions. (gimplify_body): Call them. * stmt.c (expand_stack_alloc): Don't expand TYPE_MAX_VALUE. * stor-layout.c (get_pending_sizes): Don't change SAVE_EXPR_CONTEXT. * tree-alias-common.c (get_alias_var): Also skip ARRAY_RANGE_REF. * tree-cfg.c (tree_node_can_be_shared): Treat ARRAY_RANGE_REF like ARRAY_REF. (verify_expr, case ADDR_EXPR): Use handled_component_p. * tree-dfa.c (get_virtual_var): Likewise. * tree-dump.c (dequeue_and_dump, case COMPONENT_REF, ARRAY_REF): New cases to dump new operands; likewise for ARRAY_RANGE_REF. * tree-eh.c (tree_could_trap, case ARRAY_RANGE_REF): Like ARRAY_REF. * tree-gimple.c (is_gimple_addr_expr_arg): Add ARRAY_RANGE_REF and INDIRECT_REF. (get_base_address): Use handled_component_p. * tree-gimple.h (gimplify_type_sizes, gimplify_one_sizepos): New. * tree-line.c (walk_tree): Walk more things for types and decls. * tree-mudflap.c (mf_build_check_statement_for): Add new operands for ARRAY_REF and COMPONENT_REF. (mx_xform_derefs_1): Clean up usage of decl sizes. * tree-nested.c (build_addr): Use handled_component_p. (walk_stmts, case CATCH_EXPR): Add missing "break". (get_static_chain, get_frame_field): Add new operand for COMPONENT_REF. (finalize_nesting_tree_1): Likewise. (convert_nonlocal_reference, case ARRAY_RANGE_REF): Like ARRAY_REF and process additional operands. (convert_local_reference): Likewise. * tree-outof-ssa.c (discover_nonconstant_array_refs_r): Treat ARRAY_RANGE_REF similarly to ARRAY_REF. * tree-pretty-print.c (dump_generic_node, case QUAL_UNION_TYPE): Handle like RECORD_TYPE. (dump_generic_node, case COMPONENT_REF): Print offset operand. (dump_generic_node, case ARRAY_RANGE_REF): Treat like ARRAY_REF and print lower bound and element size for both. (op_prio, case ARRAY_RANGE_REF): Like ARRAY_REF. * tree-sra.c (csc_build_component_ref): Add new operand. (scalarize_call_expr): Use get_base_address. * tree-ssa-ccp.c (widen_bitfield): Clean up size handling. (maybe_fold_offset_to_array_ref): Rework to handle input having an ARRAY_REF, refine handling of lower bound, and add new operands for ARRAY_REF. (maybe_fold_to_component_ref): Add new operand for COMPONENT_REF. (maybe_fold_stmt_indirect): Only fold *&B to B if types match. (maybe_fold_stmt_addition): Only handle constant lower bound. * tree-ssa-operands.c (get_expr_operands): Minor rearrangements. Treat ARRAY_REF and ARRAY_RANGE_REF the same; look at extra operands. Look at new offset operand of COMPONENT_REF. * tree-ssa.c (set_is_used): Use handled_component_p. * tree.c (substitute_in_expr, case COMPONENT_REF): Add new operand. (stabilize_reference, case COMPONENT_REF): Likewise. (stabilize_reference, case ARRAY_RANGE_REF, ARRAY_REF): Similarly. (recompute_tree_invariant_for_addr_expr): Completely rework to be more precise. Also set TREE_SIDE_EFFECTS. (build1_stat, case ARRAY_EXPR): Don't handle TREE_SIDE_EFFECTS here. (build2_stat, build3_stat, build4_stat): For references, propagate TREE_THIS_VOLATILE. (get_unwidened): Add new operand for COMPONENT_REF. (get_narrower): Likewise; use host_integerp for DECL_SIZE. * tree.def (COMPONENT_REF): Add new operand. (ARRAY_REF, ARRAY_RANGE_REF): Add two new operands. * tree.h (array_ref_element_size, array_ref_low_bound): New decls. (component_ref_field_offset): Likewise. * config/alpha/alpha.c (alpha_va_start): Add new op for COMPONENT_REF. (alpha_gimplify_va_arg): Likewise. * config/i386/i386.c (ix86_va_start, ix86_gimplify_va_arg): Likewise. * config/i860/i860.c (i860_va_start, i860_va_arg): Likewise. * config/iq2000/iq2000.c (iq2000_va_arg): Likewise. * config/mips/mips.c (mips_va_start, mips_va_arg): Likewise. * config/rs6000/rs6000.c (rs6000_va_start, rs6000_gimplify_va_arg): Likewise. * config/s390/s390.c (s390_va_start, s390_gimplify_va_arg): Likewise. * config/sh/sh.c (sh_va_start, sh_va_arg): Likewise. * config/stormy16/stormy16.c (xstormy1_expand_builin_va_start): Likewise. (xstormy16_expand_builtin_va_arg): Likewise. * config/xtensa/xtensa.c (xtensa_va_start, xtensa_va_arg): Likewise. * cp/call.c (build_vfield_ref): Add new operand for COMPONENT_REF. (build_new_method_call): Likewise. * cp/decl.c (local_variable_p_walkfn): Don't walk into types. * cp/decl2.c (grok_array_decl): Add new operands for ARRAY_REF. (build_anon_union_vars): Add new operand for COMPONENT_REF. * cp/init.c (buld_new): Add new operand for ARRAY_REF. * cp/method.c (do_build_copy_constructor): New op for COMPONENT_REF. (do_build_assign_ref): Likewise. * cp/parser.c (cp_parser_direct_new_declarator): Add new operands for ARRAY_REF. (cp_parser_direct_declarator): Likewise. * cp/pt.c (tsubst): Likewise. (tsubst_copy, tsubst_copy_and_build): Likewise; also add new operand for COMPONENT_REF. * cp/semantics.c (finish_non_static_data_member): Add new operand for COMPONENT_REF. * cp/typeck.c (build_class_member_access_expr): Likewise. (build_class_member_access_expr, finish_class_member_access_expr): Likewise. (build_ptrmemfunc_access_expr): Likewise. (build_array_ref): Add new operands for ARRAY_REF. * cp/typeck2.c (split_nonconstant_init_1): Likewise; COMPONENT_REF too. * cp/tree.c (count_trees_r, no_linkage_helper): Don't walk in types. * fortran/f95-lang.c (LANG_HOOKS_GIMPLE_BEFORE_INLINING): Deleted. * fortran/trans-array.c (gfc_conv_descriptor_data): Add operand for COMPONENT_REF. (gfc_conv_descriptor_offset, gfc_conv_descriptor_dtype): Likewise. (gfc_conv_descriptor_dimension, gfc_conv_descriptor_stride): Likewise. (gfc_conv_descriptor_lbound, gfc_conv_descriptor_ubound): Likewise. * fortran/trans-common.c (create_common): Likewise. * fortran/trans-expr.c (gfc_conv_component_ref): Likewise. * fortran/trans-io.c (set_parameter_value): Likewise. (set_parameter_ref, set_string, set_flag, io_result): Likewise. (transfer_expr): Likewise. * fortran/trans-decl.c (gfc_trans_auto_character_variable): Set up to get DECL_SIZE and DECL_SIZE_UNIT gimplified. (gfc_simplify_function): New function. (gfc_generate_function-code): Properly handle nested functions. * fortran/trans.c (gfc_build_array_ref): Add two new operands for ARRAY_REF. * java/class.c (build_class_ref): Add new operand for COMPONENT_REF. (build_static_field_ref): Likewise and add new operands for ARRAY_REF. * java/constants.c (build_ref_from_constant_pool): Likewise. * java/expr.c (build_java_array_length_access): Likewise. (build_get_class, build_field_ref, build_known_method_ref): Likewise. (invoke_build_dtable, build_invokevirtual): Likewise. (build_invokeinterface, java_expand_expr): Likewise. (emit_init_test_initialization): Likewise. * java/java-gimplify.c (java_gimplify_new_array_init): Likewise. * java/parse.y (make_qualifed_name, build_array_ref): Likewise. * objc/ojbc-act.c (generate_static_references): Add additional operands to ARRAY_REF. (generate_strings, build_method_prototype_list_template): Likewise. (generate_protocol_list): Likewise. From-SVN: r83474
Diffstat (limited to 'gcc/tree-ssa-ccp.c')
-rw-r--r--gcc/tree-ssa-ccp.c151
1 files changed, 101 insertions, 50 deletions
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index fb7a825..658a2cb 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -1041,40 +1041,43 @@ dump_lattice_value (FILE *outf, const char *prefix, value val)
tree
widen_bitfield (tree val, tree field, tree var)
{
- unsigned var_size, field_size;
+ unsigned HOST_WIDE_INT var_size, field_size;
tree wide_val;
unsigned HOST_WIDE_INT mask;
- unsigned i;
+ unsigned int i;
- var_size = TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE ((var))));
- field_size = TREE_INT_CST_LOW (DECL_SIZE (field));
+ /* We can only do this if the size of the type and field and VAL are
+ all constants representable in HOST_WIDE_INT. */
+ if (!host_integerp (TYPE_SIZE (TREE_TYPE (var)), 1)
+ || !host_integerp (DECL_SIZE (field), 1)
+ || !host_integerp (val, 0))
+ return NULL_TREE;
+
+ var_size = tree_low_cst (TYPE_SIZE (TREE_TYPE (var)), 1);
+ field_size = tree_low_cst (DECL_SIZE (field), 1);
/* Give up if either the bitfield or the variable are too wide. */
if (field_size > HOST_BITS_PER_WIDE_INT || var_size > HOST_BITS_PER_WIDE_INT)
- return NULL;
+ return NULL_TREE;
#if defined ENABLE_CHECKING
if (var_size < field_size)
abort ();
#endif
- /* If VAL is not an integer constant, then give up. */
- if (TREE_CODE (val) != INTEGER_CST)
- return NULL;
-
- /* If the sign bit of the value is not set, or the field's type is
- unsigned, then just mask off the high order bits of the value. */
- if ((TREE_INT_CST_LOW (val) & (1 << (field_size - 1))) == 0
- || DECL_UNSIGNED (field))
+ /* If the sign bit of the value is not set or the field's type is unsigned,
+ just mask off the high order bits of the value. */
+ if (DECL_UNSIGNED (field)
+ || !(tree_low_cst (val, 0) & (((HOST_WIDE_INT)1) << (field_size - 1))))
{
/* Zero extension. Build a mask with the lower 'field_size' bits
set and a BIT_AND_EXPR node to clear the high order bits of
the value. */
for (i = 0, mask = 0; i < field_size; i++)
- mask |= 1 << i;
+ mask |= ((HOST_WIDE_INT) 1) << i;
wide_val = build (BIT_AND_EXPR, TREE_TYPE (var), val,
- build_int_2 (mask, 0));
+ fold_convert (TREE_TYPE (var), build_int_2 (mask, 0)));
}
else
{
@@ -1082,10 +1085,10 @@ widen_bitfield (tree val, tree field, tree var)
bits set and a BIT_IOR_EXPR to set the high order bits of the
value. */
for (i = 0, mask = 0; i < (var_size - field_size); i++)
- mask |= 1 << (var_size - i - 1);
+ mask |= ((HOST_WIDE_INT) 1) << (var_size - i - 1);
wide_val = build (BIT_IOR_EXPR, TREE_TYPE (var), val,
- build_int_2 (mask, 0));
+ fold_convert (TREE_TYPE (var), build_int_2 (mask, 0)));
}
return fold (wide_val);
@@ -1493,10 +1496,26 @@ likely_value (tree stmt)
static tree
maybe_fold_offset_to_array_ref (tree base, tree offset, tree orig_type)
{
- unsigned HOST_WIDE_INT lquo, lrem;
- HOST_WIDE_INT hquo, hrem;
- tree elt_size, min_idx, idx;
- tree array_type, elt_type;
+ tree min_idx, idx, elt_offset = integer_zero_node;
+ tree array_type, elt_type, elt_size;
+
+ /* If BASE is an ARRAY_REF, we can pick up another offset (this time
+ measured in units of the size of elements type) from that ARRAY_REF).
+ We can't do anything if either is variable.
+
+ The case we handle here is *(&A[N]+O). */
+ if (TREE_CODE (base) == ARRAY_REF)
+ {
+ tree low_bound = array_ref_low_bound (base);
+
+ elt_offset = TREE_OPERAND (base, 1);
+ if (TREE_CODE (low_bound) != INTEGER_CST
+ || TREE_CODE (elt_offset) != INTEGER_CST)
+ return NULL_TREE;
+
+ elt_offset = int_const_binop (MINUS_EXPR, elt_offset, low_bound, 0);
+ base = TREE_OPERAND (base, 0);
+ }
/* Ignore stupid user tricks of indexing non-array variables. */
array_type = TREE_TYPE (base);
@@ -1506,37 +1525,62 @@ maybe_fold_offset_to_array_ref (tree base, tree offset, tree orig_type)
if (!lang_hooks.types_compatible_p (orig_type, elt_type))
return NULL_TREE;
- /* Whee. Ignore indexing of variable sized types. */
+ /* If OFFSET and ELT_OFFSET are zero, we don't care about the size of the
+ element type (so we can use the alignment if it's not constant).
+ Otherwise, compute the offset as an index by using a division. If the
+ division isn't exact, then don't do anything. */
elt_size = TYPE_SIZE_UNIT (elt_type);
- if (TREE_CODE (elt_size) != INTEGER_CST)
- return NULL_TREE;
+ if (integer_zerop (offset))
+ {
+ if (TREE_CODE (elt_size) != INTEGER_CST)
+ elt_size = size_int (TYPE_ALIGN (elt_type));
- /* If the division isn't exact, then don't do anything. Equally
- invalid as the above indexing of non-array variables. */
- if (div_and_round_double (TRUNC_DIV_EXPR, 1,
- TREE_INT_CST_LOW (offset),
- TREE_INT_CST_HIGH (offset),
- TREE_INT_CST_LOW (elt_size),
- TREE_INT_CST_HIGH (elt_size),
- &lquo, &hquo, &lrem, &hrem)
- || lrem || hrem)
- return NULL_TREE;
- idx = build_int_2_wide (lquo, hquo);
+ idx = integer_zero_node;
+ }
+ else
+ {
+ unsigned HOST_WIDE_INT lquo, lrem;
+ HOST_WIDE_INT hquo, hrem;
+
+ if (TREE_CODE (elt_size) != INTEGER_CST
+ || div_and_round_double (TRUNC_DIV_EXPR, 1,
+ TREE_INT_CST_LOW (offset),
+ TREE_INT_CST_HIGH (offset),
+ TREE_INT_CST_LOW (elt_size),
+ TREE_INT_CST_HIGH (elt_size),
+ &lquo, &hquo, &lrem, &hrem)
+ || lrem || hrem)
+ return NULL_TREE;
- /* Re-bias the index by the min index of the array type. */
- min_idx = TYPE_DOMAIN (TREE_TYPE (base));
- if (min_idx)
+ idx = build_int_2_wide (lquo, hquo);
+ }
+
+ /* Assume the low bound is zero. If there is a domain type, get the
+ low bound, if any, convert the index into that type, and add the
+ low bound. */
+ min_idx = integer_zero_node;
+ if (TYPE_DOMAIN (array_type))
{
- min_idx = TYPE_MIN_VALUE (min_idx);
- if (min_idx)
- {
- idx = convert (TREE_TYPE (min_idx), idx);
- if (!integer_zerop (min_idx))
- idx = int_const_binop (PLUS_EXPR, idx, min_idx, 1);
- }
+ if (TYPE_MIN_VALUE (TYPE_DOMAIN (array_type)))
+ min_idx = TYPE_MIN_VALUE (TYPE_DOMAIN (array_type));
+ else
+ min_idx = fold_convert (TYPE_DOMAIN (array_type), min_idx);
+
+ if (TREE_CODE (min_idx) != INTEGER_CST)
+ return NULL_TREE;
+
+ idx = fold_convert (TYPE_DOMAIN (array_type), idx);
+ elt_offset = fold_convert (TYPE_DOMAIN (array_type), elt_offset);
}
- return build (ARRAY_REF, orig_type, base, idx);
+ if (!integer_zerop (min_idx))
+ idx = int_const_binop (PLUS_EXPR, idx, min_idx, 0);
+ if (!integer_zerop (elt_offset))
+ idx = int_const_binop (PLUS_EXPR, idx, elt_offset, 0);
+
+ return build (ARRAY_REF, orig_type, base, idx, min_idx,
+ size_int (tree_low_cst (elt_size, 1)
+ / (TYPE_ALIGN (elt_type) / BITS_PER_UNIT)));
}
/* A subroutine of fold_stmt_r. Attempts to fold *(S+O) to S.X.
@@ -1617,7 +1661,7 @@ maybe_fold_offset_to_component_ref (tree record_type, tree base, tree offset,
{
if (base_is_ptr)
base = build1 (INDIRECT_REF, record_type, base);
- t = build (COMPONENT_REF, field_type, base, f);
+ t = build (COMPONENT_REF, field_type, base, f, NULL_TREE);
return t;
}
@@ -1639,7 +1683,7 @@ maybe_fold_offset_to_component_ref (tree record_type, tree base, tree offset,
nonzero offset into them. Recurse and hope for a valid match. */
if (base_is_ptr)
base = build1 (INDIRECT_REF, record_type, base);
- base = build (COMPONENT_REF, field_type, base, f);
+ base = build (COMPONENT_REF, field_type, base, f, NULL_TREE);
t = maybe_fold_offset_to_array_ref (base, offset, orig_type);
if (t)
@@ -1697,8 +1741,12 @@ maybe_fold_stmt_indirect (tree expr, tree base, tree offset)
if (t)
return t;
- /* Fold *&B to B. */
- if (integer_zerop (offset))
+ /* Fold *&B to B. We can only do this if EXPR is the same type
+ as BASE. We can't do this if EXPR is the element type of an array
+ and BASE is the array. */
+ if (integer_zerop (offset)
+ && lang_hooks.types_compatible_p (TREE_TYPE (base),
+ TREE_TYPE (expr)))
return base;
}
else
@@ -1803,6 +1851,9 @@ maybe_fold_stmt_addition (tree expr)
min_idx = TYPE_MIN_VALUE (min_idx);
if (min_idx)
{
+ if (TREE_CODE (min_idx) != INTEGER_CST)
+ break;
+
array_idx = convert (TREE_TYPE (min_idx), array_idx);
if (!integer_zerop (min_idx))
array_idx = int_const_binop (MINUS_EXPR, array_idx,