aboutsummaryrefslogtreecommitdiff
path: root/gcc/fold-const.c
diff options
context:
space:
mode:
authorRichard Kenner <kenner@vlsi1.ultra.nyu.edu>2000-02-27 21:39:40 +0000
committerRichard Kenner <kenner@gcc.gnu.org>2000-02-27 16:39:40 -0500
commitfed3cef0dbbd17e3d7b8860f42cd8490f0325340 (patch)
treeda73c398c9c03435ecc0d3821031b7c0fe89911d /gcc/fold-const.c
parent43931371e2321b6c50c3e0b9095d46606ec48ce1 (diff)
downloadgcc-fed3cef0dbbd17e3d7b8860f42cd8490f0325340.zip
gcc-fed3cef0dbbd17e3d7b8860f42cd8490f0325340.tar.gz
gcc-fed3cef0dbbd17e3d7b8860f42cd8490f0325340.tar.bz2
builtins.c (c_strlen): Use size_diffop and return ssizetype value.
* builtins.c (c_strlen): Use size_diffop and return ssizetype value. (expand_builtin_strcpy): Pass correct type to size_binop. (expand_builtin_strcmp): Likewise. Clean up conditional structure. * c-decl.c (init_decl_processing): Don't call set_sizetype twice. (complete_array_type): Don't use size_binop for MAXINDEX. * c-typeck.c (c_sizeof): Use size_one_node and TYPE_SIZE_UNIT. (c_sizeof_nowarn, c_size_in_bytes): Likewise. (c_alignof): Use size_one_node. (build_unary_op): Pass arg of proper type to size_binop. (really_start_incremental_init, push_init_level): Use sizetype for constructor{,_bit,_unfilled}_index. (pop_init_label, output_init_element): Likewise. (output_pending_init_elements, process_init_element): Likewise. * calls.c (compute_argument_block_size): Field VAR is ssizetype. * expr.c (store_expr): Use size_int. (store_constructor): Use proper types for size_binop args. (get_inner_reference, expand_expr, case ARRAY_REF): Likewise. (expand_expr_unaligned): Likewise. (string_contant): Return object of sizetype. * expr.h (SUB_PARM_SIZE): Call size_diffop and pass proper types. (ARGS_SIZE_RTX): Call ARGS_SIZE_TREE. (ARGS_SIZE_TREE): Pass proper types to size_binop. * fold-const.c (int_const_binop): Refine when size_int is called. (fold_convert): Likewise. (size_int_wide): Rework to take KIND as arg, only take low order bits, handle new sizetype_tab datatype, and chain entries in size_table. (size_int_type_wide): New function. (size_binop): Validate types of arguments. (ssize_binop): Deleted. (size_diffop): New function. (extract_muldiv): Only fold division into multiplication for sizetypes. * function.c (assign_parms): Use size_diffop and make sure VAR field is of ssizetype; also pass proper type to size_binop. (locate_and_pad_parm, pad_to_arg_alignment): Likewise. (round_down): Deleted from here. * store-layout.c (sizetype_tab): Now an array. (sizetype_set, early_root_list): New variables. (variable_size): Use size_one_node. (round_up): Pass proper type to size_binop. (round_down): Moved to here and corrected as above. (layout_record): Pass proper arg types to size_binop. (layout_type): Likewise. If sizetype_set is zero, record the type just laid out. (make_unsigned_type): Don't call set_sizetype; (make_signed_type): Likewise; also, call fixup_signed_type. (initialize_sizetypes): New function. (set_sizetype): Make copy of types, set TYPE_IS_SIZETYPE, and set name of bitsizetype to "bit_size_type". Fix up type of sizes of all types made before call. * tm.texi (ROUND_TYPE_SIZE_UNIT): New macro. * tree.c (fix_sizetype): Deleted. (build_common_tree_nodes): Call initialize_sizetypes. (build_common_tree_nodes_2): Don't call fix_sizetype. * tree.h (TYPE_IS_SIZETYPE): New macro. (initialize_sizetype): New declaration. (enum size_type_kind): New type. (struct sizetype_tab): Deleted. (sizetype_tab): Now array; adjust sizetype macros. (size_diffop, size_int_type_wide): New functions. (size_int_wide): Change number of args and type; access macros changed. (ssize_int, sbitsize_int): New macros. * config/i960/i960.h (ROUND_TYPE_SIZE): Use size_int. (ROUND_TYPE_SIZE_UNIT): New macro. * ch/actions.c (chill_convert_for_assignment): Don't use size_binop for things that aren't sizes. (expand_varying_length_assignment): Likewise. * ch/convert.c (digest_array_tuple, convert): Likewise. * ch/typeck.c (build_chill_slice, smash_dummy_type): Likewise. (build_chill_slice_with_range): Likewise. (build_chill_slice_with_length): Likewise. (build_array_from_set): Adjust types for size_binop. * ch/expr.c (build_concat_expr, build_chill_repetition_op): Likewise. (build_chill_sizeof): Use TYPE_SIZE_UNIT. * ch/tree.c (build_string_type): Pass proper type to size_binop. * cp/class.c (dfs_build_vtable_offset_vtbl_entries): Don't use size_binop on things that are not sizes; ssize_binop deleted. Call size_diffop when appropriate. (dfs_build_vcall_offset_vtbl_entries): Likewise. (build_primary_vtable, build_secondary_vtable): Likewise. (dfs_set_offset_for_unshared_vbases, dfs_modify_vtables): Likewise. Variable I is HOST_WIDE_INT. (get_vfield_offset): Pass proper types to size_binop. (size_extra_vtbl_entries, layout_virtual_bases): Likewise. (finish_struct_1): Likewise. (skip_rtti_stuff): Arg N is now pointer to signed. (layout_class_type): Use size_zero_node. * cp/cp-tree.h (skip_rtti_stuff): Arg N is pointer to signed. * cp/cvt.c (cp_convert_to_pointer): Pass proper types to size_binop. * cp/decl.c (complete_arry_type): Pass proper types to size_binop. (xref_basetypes): BINFO_OFFSET is sizetype. * cp/error.c (dump_expr): Don't use size_binop non-sizes. * cp/expr.c (cplus_expand_constant): Pass proper types to size_binop. * cp/init.c (construct_virtual_bases): Fix type error. (build_vec_delete_1): Pass proper type to size_binop and don't fold result. * cp/lex.c (cp_make_lang_type): BINFO_OFFSET is sizetype. * cp/rtti.c (get_base_offset): Pass proper type to size_binop. * cp/search.c (dfs_find_vbases): Fix type error. (expand_upcast_fixups): Arg to skip_rtti_stuff is pointer to signed. (dfs_get_vbase_types): BINFO_OFFSET is sizetype. * cp/tree.c (debug_binfo): Variable N is signed. Use HOST_WIDE_INT_PRINT_DEC. * cp/typeck.c (comptypes): sizetype is same as equivalent integer type. (c_sizeof, c_sizeof_nowarn, expr_sizeof): Use TYPE_SIZE_UNIT, size_one_node and size_zero_node. (c_alignof): Use size_one_node. (build_component_addr): Pass proper types to size_binop. (expand_ptrmemfunc_cst): Don't use size_binop on non-sizes. * f/com.c (ffecom_arrayref_): Convert args to size_binop to proper type. (ffecom_tree_canonize_ptr_): Don't use size_binop for non-sizes. (ffecom_tree_canonize_ref_): Likewise. (type_for_mode): Handle TImode. * f/ste.c (ffeste_io_dofio_, ffeste_io_douio_): Use TYPE_SIZE_UNIT. (ffeste_io_ciclist_): Likewise. * java/expr.c (build_java_ret): Pass proper type to size_binop. From-SVN: r32225
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r--gcc/fold-const.c134
1 files changed, 83 insertions, 51 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index ff925c9..24bf6f1 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -1559,13 +1559,8 @@ int_const_binop (code, arg1, arg2, notrunc, forsize)
abort ();
}
- if (TREE_TYPE (arg1) == sizetype && hi == 0
- && low >= 0
- && (TYPE_MAX_VALUE (sizetype) == NULL
- || low <= TREE_INT_CST_LOW (TYPE_MAX_VALUE (sizetype)))
- && ! overflow
- && ! TREE_OVERFLOW (arg1) && ! TREE_OVERFLOW (arg2))
- t = size_int (low);
+ if (forsize && hi == 0 && low >= 0 && low < 1000)
+ return size_int_type_wide (low, TREE_TYPE (arg1));
else
{
t = build_int_2 (low, hi);
@@ -1797,19 +1792,25 @@ const_binop (code, arg1, arg2, notrunc)
}
/* Return an INTEGER_CST with value whose low-order HOST_BITS_PER_WIDE_INT
- bits are given by NUMBER.
+ bits are given by NUMBER and of the sizetype represented by KIND. */
- If BIT_P is nonzero, this represents a size in bit and the type of the
- result will be bitsizetype, othewise it represents a size in bytes and
- the type of the result will be sizetype. */
+tree
+size_int_wide (number, kind)
+ HOST_WIDE_INT number;
+ enum size_type_kind kind;
+{
+ return size_int_type_wide (number, sizetype_tab[(int) kind]);
+}
+
+/* Likewise, but the desired type is specified explicitly. */
tree
-size_int_wide (number, bit_p)
+size_int_type_wide (number, type)
HOST_WIDE_INT number;
- int bit_p;
+ tree type;
{
/* Type-size nodes already made for small sizes. */
- static tree size_table[2 * HOST_BITS_PER_WIDE_INT + 1][2];
+ static tree size_table[2 * HOST_BITS_PER_WIDE_INT + 1];
static int init_p = 0;
tree t;
@@ -1826,8 +1827,10 @@ size_int_wide (number, bit_p)
if (number >= 0
&& number < (int) (sizeof size_table / sizeof size_table[0]) / 2)
{
- if (size_table[number][bit_p] != 0)
- return size_table[number][bit_p];
+ if (size_table[number] != 0)
+ for (t = size_table[number]; t != 0; t = TREE_CHAIN (t))
+ if (TREE_TYPE (t) == type)
+ return t;
if (! ggc_p)
{
@@ -1837,8 +1840,9 @@ size_int_wide (number, bit_p)
}
t = build_int_2 (number, 0);
- TREE_TYPE (t) = bit_p ? bitsizetype : sizetype;
- size_table[number][bit_p] = t;
+ TREE_TYPE (t) = type;
+ TREE_CHAIN (t) = size_table[number];
+ size_table[number] = t;
if (! ggc_p)
pop_obstacks ();
@@ -1846,14 +1850,15 @@ size_int_wide (number, bit_p)
return t;
}
- t = build_int_2 (number, 0);
- TREE_TYPE (t) = bit_p ? bitsizetype : sizetype;
+ t = build_int_2 (number, number < 0 ? -1 : 0);
+ TREE_TYPE (t) = type;
TREE_OVERFLOW (t) = TREE_CONSTANT_OVERFLOW (t) = force_fit_type (t, 0);
return t;
}
-/* Combine operands OP1 and OP2 with arithmetic operation CODE.
- CODE is a tree code. Data type is taken from `sizetype',
+/* Combine operands OP1 and OP2 with arithmetic operation CODE. CODE
+ is a tree code. The type of the result is taken from the operands.
+ Both must be the same type integer type and it must be a size type.
If the operands are constant, so is the result. */
tree
@@ -1861,6 +1866,12 @@ size_binop (code, arg0, arg1)
enum tree_code code;
tree arg0, arg1;
{
+ tree type = TREE_TYPE (arg0);
+
+ if (type != TREE_TYPE (arg1)
+ || TREE_CODE (type) != INTEGER_TYPE || ! TYPE_IS_SIZETYPE (type))
+ abort ();
+
/* Handle the special case of two integer constants faster. */
if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST)
{
@@ -1880,41 +1891,49 @@ size_binop (code, arg0, arg1)
if (arg0 == error_mark_node || arg1 == error_mark_node)
return error_mark_node;
- return fold (build (code, sizetype, arg0, arg1));
+ return fold (build (code, type, arg0, arg1));
}
-/* Combine operands OP1 and OP2 with arithmetic operation CODE.
- CODE is a tree code. Data type is taken from `ssizetype',
- If the operands are constant, so is the result. */
+/* Given two values, either both of sizetype or both of bitsizetype,
+ compute the difference between the two values. Return the value
+ in signed type corresponding to the type of the operands. */
tree
-ssize_binop (code, arg0, arg1)
- enum tree_code code;
+size_diffop (arg0, arg1)
tree arg0, arg1;
{
- /* Handle the special case of two integer constants faster. */
- if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST)
- {
- /* And some specific cases even faster than that. */
- if (code == PLUS_EXPR && integer_zerop (arg0))
- return arg1;
- else if ((code == MINUS_EXPR || code == PLUS_EXPR)
- && integer_zerop (arg1))
- return arg0;
- else if (code == MULT_EXPR && integer_onep (arg0))
- return arg1;
+ tree type = TREE_TYPE (arg0);
+ tree ctype;
- /* Handle general case of two integer constants. We convert
- arg0 to ssizetype because int_const_binop uses its type for the
- return value. */
- arg0 = convert (ssizetype, arg0);
- return int_const_binop (code, arg0, arg1, 0, 0);
- }
-
- if (arg0 == error_mark_node || arg1 == error_mark_node)
- return error_mark_node;
+ if (TREE_TYPE (arg1) != type || TREE_CODE (type) != INTEGER_TYPE
+ || ! TYPE_IS_SIZETYPE (type))
+ abort ();
- return fold (build (code, ssizetype, arg0, arg1));
+ /* If the type is already signed, just do the simple thing. */
+ if (! TREE_UNSIGNED (type))
+ return size_binop (MINUS_EXPR, arg0, arg1);
+
+ ctype = (type == bitsizetype || type == ubitsizetype
+ ? sbitsizetype : ssizetype);
+
+ /* If either operand is not a constant, do the conversions to the signed
+ type and subtract. The hardware will do the right thing with any
+ overflow in the subtraction. */
+ if (TREE_CODE (arg0) != INTEGER_CST || TREE_CODE (arg1) != INTEGER_CST)
+ return size_binop (MINUS_EXPR, convert (ctype, arg0),
+ convert (ctype, arg1));
+
+ /* If ARG0 is larger than ARG1, subtract and return the result in CTYPE.
+ Otherwise, subtract the other way, convert to CTYPE (we know that can't
+ overflow) and negate (which can't either). Special-case a result
+ of zero while we're here. */
+ if (tree_int_cst_equal (arg0, arg1))
+ return convert (ctype, integer_zero_node);
+ else if (tree_int_cst_lt (arg1, arg0))
+ return convert (ctype, size_binop (MINUS_EXPR, arg0, arg1));
+ else
+ return size_binop (MINUS_EXPR, convert (ctype, integer_zero_node),
+ convert (ctype, size_binop (MINUS_EXPR, arg1, arg0)));
}
/* This structure is used to communicate arguments to fold_convert_1. */
@@ -1959,6 +1978,14 @@ fold_convert (t, arg1)
if (TYPE_PRECISION (type) > 2 * HOST_BITS_PER_WIDE_INT)
return t;
+ /* If we are trying to make a sizetype for a small integer, use
+ size_int to pick up cached types to reduce duplicate nodes. */
+ if (TREE_CODE (type) == INTEGER_CST && TYPE_IS_SIZETYPE (type)
+ && TREE_INT_CST_HIGH (arg1) == 0
+ && TREE_INT_CST_LOW (arg1) >= 0
+ && TREE_INT_CST_LOW (arg1) < 1000)
+ return size_int_type_wide (TREE_INT_CST_LOW (arg1), type);
+
/* Given an integer constant, make new constant with new type,
appropriately sign-extended or truncated. */
t = build_int_2 (TREE_INT_CST_LOW (arg1),
@@ -4471,8 +4498,13 @@ extract_muldiv (t, c, code, wide_type)
/* If these operations "cancel" each other, we have the main
optimizations of this pass, which occur when either constant is a
multiple of the other, in which case we replace this with either an
- operation or CODE or TCODE. */
- if ((code == MULT_EXPR && tcode == EXACT_DIV_EXPR)
+ operation or CODE or TCODE. If we have an unsigned type that is
+ not a sizetype, we canot do this for division since it will change
+ the result if the original computation overflowed. */
+ if ((code == MULT_EXPR && tcode == EXACT_DIV_EXPR
+ && (! TREE_UNSIGNED (ctype)
+ || (TREE_CODE (ctype) == INTEGER_TYPE
+ && TYPE_IS_SIZETYPE (ctype))))
|| (tcode == MULT_EXPR
&& code != TRUNC_MOD_EXPR && code != CEIL_MOD_EXPR
&& code != FLOOR_MOD_EXPR && code != ROUND_MOD_EXPR))