diff options
author | Richard Kenner <kenner@vlsi1.ultra.nyu.edu> | 2000-02-27 21:39:40 +0000 |
---|---|---|
committer | Richard Kenner <kenner@gcc.gnu.org> | 2000-02-27 16:39:40 -0500 |
commit | fed3cef0dbbd17e3d7b8860f42cd8490f0325340 (patch) | |
tree | da73c398c9c03435ecc0d3821031b7c0fe89911d /gcc/fold-const.c | |
parent | 43931371e2321b6c50c3e0b9095d46606ec48ce1 (diff) | |
download | gcc-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.c | 134 |
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)) |