diff options
author | Andrew Pinski <pinskia@gcc.gnu.org> | 2007-06-15 22:42:36 -0700 |
---|---|---|
committer | Andrew Pinski <pinskia@gcc.gnu.org> | 2007-06-15 22:42:36 -0700 |
commit | 5be014d5b728cf754020b8ab4df1cd029f69922e (patch) | |
tree | a412e70be6f1d8732a8f791392c918ebc475f3e0 /gcc/fold-const.c | |
parent | 1d2b1d91675ba5a26e4d04b209355047421adf92 (diff) | |
download | gcc-5be014d5b728cf754020b8ab4df1cd029f69922e.zip gcc-5be014d5b728cf754020b8ab4df1cd029f69922e.tar.gz gcc-5be014d5b728cf754020b8ab4df1cd029f69922e.tar.bz2 |
[multiple changes]
2007-06-15 Andrew Pinski <andrew_pinski@playstation.sony.com>
Zdenek Dvorak <dvorakz@suse.cz>
Richard Guenther <rguenther@suse.de>
Kaz Kojima <kkojima@gcc.gnu.org>
* tree-vrp.c (compare_values_warnv): Convert val2 to
the type of val1.
(extract_range_from_assert): Create
POINTER_PLUS_EXPR for pointer types.
(extract_range_from_binary_expr): Handle
only POINTER_PLUS_EXPR, MIN_EXPR, and MAX_EXPR
for pointer types.
* doc/c-tree.texi (POINTER_PLUS_EXPR): Document.
* tree-ssa-loop-niter.c (split_to_var_and_offset): Handle
POINTER_PLUS_EXPR as PLUS_EXPR.
(number_of_iterations_lt_to_ne):
For pointer types, use sizetype when
creating MINUS_EXPR/PLUS_EXPRs.
(assert_loop_rolls_lt): For pointer types, use sizetype when
creating MINUS_EXPR/PLUS_EXPRs.
(number_of_iterations_le): Likewise.
(expand_simple_operations): POINTER_PLUS_EXPR are simple also.
(derive_constant_upper_bound): Handle POINTER_PLUS_EXPR just
like PLUS_EXPR and MINUS_EXPR.
* tree-pretty-print.c (dump_generic_node): Handle
POINTER_PLUS_EXPR.
(op_prio): Likewise.
(op_symbol_1): Likewise.
* optabs.c (optab_for_tree_code): Likewise.
* tree-ssa-loop-manip.c (create_iv): Handle pointer base
specially.
* tree-tailcall.c (process_assignment): Mention
POINTER_PLUS_EXPR in a TODO comment.
* tree.c (build2_stat): Assert when trying to use PLUS_EXPR or
MINUS_EXPR with a pointer. Also assert for POINTER_PLUS_EXPR
not used with a pointer and an integer type.
* tree-scalar-evolution.c (add_to_evolution_1): Convert the
increment using chrec_convert_rhs instead of chrec_convert.
(follow_ssa_edge_in_rhs): Handle POINTER_PLUS_EXPR like
PLUS_EXPR except for the right hand side's type will be
sizetype.
(interpret_rhs_modify_stmt): Handle POINTER_PLUS_EXPR.
(fold_used_pointer_cast): Kill.
(pointer_offset_p): Kill.
(fold_used_pointer): Kill.
(pointer_used_p): Kill.
(analyze_scalar_evolution_1 <case GIMPLE_MODIFY_STMT>): Don't
call fold_used_pointer.
(instantiate_parameters_1): Convert the increment
using chrec_convert_rhs instead of chrec_convert.
Handle POINTER_PLUS_EXPR as PLUS_EXPR.
* builtins.c (get_pointer_alignment): Handle POINTER_PLUS_EXPR
instead of PLUS_EXPR.
(expand_builtin_strcat): Create a POINTER_PLUS_EXPR instead of
PLUS_EXPR for pointers.
(std_gimplify_va_arg_expr): Likewise.
(fold_builtin_memory_op): Likewise.
(fold_builtin_strstr): Likewise.
(fold_builtin_strchr): Likewise.
(fold_builtin_strrchr): Likewise.
(fold_builtin_strpbrk): Likewise.
(expand_builtin_memory_chk): Likewise.
(fold_builtin_memory_chk): Likewise.
(std_expand_builtin_va_start): Use
sizetype for the call to make_tree and then convert
to the pointer type.
(fold_builtin_memchr): Use POINTER_PLUS_EXPR
instead of PLUS_EXPR for adding to a pointer.
(std_gimplify_va_arg_expr): Use fold_build2 for
the creating of POINTER_PLUS_EXPR. For the BIT_AND_EXPR, cast
the operands to sizetype first and then cast the BIT_AND_EXPR
back to the pointer type.
* fold-const.c (build_range_check): Handle pointer types
specially.
(extract_array_ref): Look for POINTER_PLUS_EXPR instead
of PLUS_EXPR's. Make sure the offset is converted to
sizetype.
(try_move_mult_to_index): Strip the NOPs from the offset.
Remove code argument and replace all uses with PLUS_EXPR.
(fold_to_nonsharp_ineq_using_bound): Handle pointer types
specially. Don't use a pointer type for MINUS_EXPR.
(fold_unary): Handle for (T1)(X op Y),
only p+ as that is the only as that can be handled for
binary operators now.
(fold_binary <case POINTER_PLUS_EXPR>): Add folding of
POINTER_PLUS_EXPR.
<case PLUS_EXPR>: Add folding of PTR+INT into
PTR p+ INT.
Don't call try_move_mult_to_index.
<case MINUS_EXPR>: Fold (PTR0 p+ A) - (PTR1 p+ B)
into (PTR0 - PTR1) + (A - B). Fold (PTR0 p+ A) - PTR1 into
(PTR0 - PTR1) + A iff (PTR0 - PTR1) simplifies.
Don't call try_move_mult_to_index.
(tree_expr_nonnegative_warnv_p): Handle POINTER_PLUS_EXPR.
(tree_expr_nonzero_p): Likewise.
(fold_indirect_ref_1): Look at POINTER_PLUS_EXPR instead
of PLUS_EXPR for the complex expression folding.
* tree-chrec.c (chrec_fold_plus_poly_poly): If the
first chrec is a pointer type, then the second should
be sizetype and not the first's type.
For POINTER_PLUS_EXPR, use a different right hand side type.
Handle POINTER_PLUS_EXPR like PLUS_EXPR.
(chrec_fold_plus_1): For POINTER_PLUS_EXPR, use a
different right hand side type.
Handle POINTER_PLUS_EXPR like PLUS_EXPR.
(chrec_fold_plus): For pointer types, use POINTER_PLUS_EXPR
instead of PLUS_EXPR.
When either operand is zero, convert the other operand.
(chrec_apply): Use chrec_convert_rhs
on the argument x instead of chrec_convert.
(reset_evolution_in_loop): For pointer types, the new_evol
should be sizetype.
(convert_affine_scev): For POINTER_PLUS_EXPR, use a
different right hand side type.
Handle POINTER_PLUS_EXPR like PLUS_EXPR.
(chrec_convert_rhs): New function.
(chrec_convert_aggressive): For POINTER_PLUS_EXPR, use a
different right hand side type.
Handle POINTER_PLUS_EXPR like PLUS_EXPR.
* tree-chrec.h (chrec_convert_rhs): New prototype.
(build_polynomial_chrec): For pointer types, the right hand
* tree-ssa-ccp.c (maybe_fold_stmt_indirect): Look for
POINTER_PLUS_EXPR instead of PLUS_EXPR's.
Remove subtraction case as it is always addition now.
Make sure the offset is converted to sizetype.
(fold_stmt_r): Don't handle PLUS_EXPR/MINUS_EXPR specially.
Handle POINTER_PLUS_EXPR like PLUS_EXPR was handled before.
* tree-ssa-loop-ivopts.c (determine_base_object): Abort for
PLUS_EXPR in pointer type.
Handle POINTER_PLUS_EXPR.
(tree_to_aff_combination): Likewise.
(force_expr_to_var_cost): Likewise.
(force_expr_to_var_cost): Likewise. Create a POINTER_PLUS_EXPR
instead of PLUS_EXPR for pointers.
* c-format.c (check_format_arg): Handle POINTER_PLUS_EXPR
instead of PLUS_EXPR of pointer types.
* tree-stdarg.c (va_list_counter_bump): Handle POINTER_PLUS_EXPR
as PLUS_EXPR.
(check_va_list_escapes): Likewise.
(check_all_va_list_escapes): Likewise.
* dwarf2out.c (loc_descriptor_from_tree_1):
Handle POINT_PLUS_EXPR as a PLUS_EXPR.
* expr.c (expand_expr_real_1): Handle POINTER_PLUS_EXPR.
(string_constant): Likewise.
* tree-ssa-address.c (tree_mem_ref_addr): When adding
the offset to the base, use POINTER_PLUS_EXPR.
(add_to_parts): Convert the index to sizetype.
(create_mem_ref): Create A POINTER_PLUS_EXPR for the one case.
* matrix-reorg.c (collect_data_for_malloc_call): Stmt
will now only be either INDIRECT_REF and POINTER_PLUS_EXPR.
Offset only holds something for PLUS_EXPR.
(ssa_accessed_in_tree): Handle POINTER_PLUS_EXPR just as
a PLUS_EXPR.
(analyze_transpose): POINTER_PLUS_EXPR will only show up now
and not PLUS_EXPR.
(analyze_accesses_for_modify_stmt): Likewise.
Remove comment about the type being integral type as it is
wrong now.
(can_calculate_expr_before_stmt): Handle POINTER_PLUS_EXPR as
PLUS_EXPR.
(transform_access_sites): POINTER_PLUS_EXPR will only show up now
and not PLUS_EXPR.
Correct the type which the artimentic is done in (is now
sizetype).
Reindent one loop.
* tree-data-ref.c (split_constant_offset): Handle
POINTER_PLUS_EXPR
* tree-affine.c (tree_to_aff_combination): Likewise.
* c-typeck.c (build_unary_op): For pointers create the increment
as a sizetype. Create a POINTER_PLUS_EXPR instead of PLUS_EXPR
for pointers.
* gimplify.c (gimplify_self_mod_expr): Create a
POINTER_PLUS_EXPR instead of PLUS_EXPR for pointers.
(gimplify_omp_atomic_fetch_op): Handle POINTER_PLUS_EXPR.
* tree.def (POINTER_PLUS_EXPR): New tree code.
* tree-predcom.c (ref_at_iteration): If we have a pointer
type do the multiplication in sizetype.
* tree-mudflap.c (mf_xform_derefs_1): Create a
POINTER_PLUS_EXPR instead of PLUS_EXPR for pointers.
* tree-ssa-forwprop.c
(forward_propagate_addr_into_variable_array_index):
Don't expect there to be a cast for the index as that
does not exist anymore.
(forward_propagate_addr_expr_1): Check for POINTER_PLUS_EXPR
instead of PLUS_EXPR.
Don't check for the first operand of the POINTER_PLUS_EXPR
was the index as it cannot be.
Call forward_propagate_addr_into_variable_array_index with
the SSA_NAME instead of the statement.
* varasm.c (const_hash_1): Handle POINTER_PLUS_EXPR.
(compare_constant): Likewise.
(copy_constant): Likewise.
(compute_reloc_for_constant): Likewise.
(output_addressed_constants): Likewise.
(initializer_constant_valid_p): Likewise.
* tree-ssa.c (tree_ssa_useless_type_conversion_1):
Convert the MIN/MAX of the inner type to the outer
type before comparing them.
* tree-ssa-loop-prefetch.c (idx_analyze_ref): Handle
POINTER_PLUS_EXPR instead of PLUS_EXPR.
(issue_prefetch_ref): Create a POINTER_PLUS_EXPR instead
of PLUS_EXPR for pointers.
* tree-inline.c (estimate_num_insns_1): Handle
POINTER_PLUS_EXPR.
* tree-vect-transform.c (vect_create_addr_base_for_vector_ref):
Create a POINTER_PLUS_EXPR instead of PLUS_EXPR for pointers.
(bump_vector_ptr): Create a POINTER_PLUS_EXPR
instead of PLUS_EXPR for the pointer increment statement.
(vect_update_ivs_after_vectorizer): For pointer types, create
POINTER_PLUS_EXPR instead of PLUS_EXPR and also create
MULT_EXPR in sizetype.
(vect_gen_niters_for_prolog_loop): Add a cast when creating
byte_misalign.
* tree-object-size.c (plus_expr_object_size): Handle
POINTER_PLUS_EXPR instead of PLUS_EXPR. Removing all the extra
code which is trying to figure out which side is a pointer and
is the index.
(check_for_plus_in_loops_1): Likewise.
(check_for_plus_in_loops): Likewise.
* c-common.c (pointer_int_sum): Create a
POINTER_PLUS_EXPR instead of PLUS_EXPR for pointers.
* tree-ssa-structalias.c (handle_ptr_arith): Handle
only POINTER_PLUS_EXPR. Removing all the extra
code which is trying to figure out which side is a pointer and
is the index.
* tree-cfg.c (verify_expr): Add extra checking for pointers and
PLUS_EXPR and MINUS_EXPR.
Also add checking to make sure the operands of POINTER_PLUS_EXPR
are correct.
* config/frv/frv.c (frv_expand_builtin_va_start): Use sizetype
with make_tree, instead of a pointer type.
* config/s390/s390.c (s390_va_start): Use POINTER_PLUS_EXPR
for pointers instead of PLUS_EXPR.
(s390_gimplify_va_arg): Likewise.
* config/spu/spu.c (spu_va_start): Create POINTER_PLUS_EXPR
instead of PLUS_EXPR when doing addition on pointer
types. Use sizetype for the second operand.
(spu_gimplify_va_arg_expr): Likewise.
* config/sparc/sparc.c (sparc_gimplify_va_arg): Use
POINTER_PLUS_EXPR instead of PLUS_EXPR when the operand was
a pointer. Don't create a BIT_AND_EXPR for pointer types.
* config/i386/i386.c (ix86_va_start): Use POINTER_PLUS_EXPR
for the pointer addition and also use size_int/sizetype
for the offset.
(ix86_gimplify_va_arg): Likewise.
Perform BIT_AND_EXPR on sizetype arguments.
* config/sh/sh.c (sh_va_start): Call make_tree with sizetype
and convert its result to a pointer type. Use POINTER_PLUS_EXPR
for the pointer additions and also use size_int for the offsets.
(sh_gimplify_va_arg_expr): Use POINTER_PLUS_EXPR for the pointer
additions and also use size_int for the offsets. Perform
BIT_AND_EXPR on sizetype arguments.
* config/ia64/ia64.c (ia64_gimplify_va_arg): Use
POINTER_PLUS_EXPR for pointers and create the
BIT_AND_EXPR in sizetype.
* config/rs6000/rs6000.c (rs6000_va_start): Use POINTER_PLUS_EXPR
instead of PLUS_EXPR for pointer addition.
(rs6000_va_start): Likewise.
Also use sizetype for the offset.
* config/pa/pa.c (reloc_needed): Handle POINTER_PLUS_EXPR
as PLUS_EXPR/MINUS_EXPR.
(hppa_gimplify_va_arg_expr): Don't create MINUS_EXPR or
PLUS_EXPR for pointers, instead use POINTER_PLUS_EXPR.
Don't use BIT_AND_EXPR on a pointer type, convert the
expression to sizetype first.
* config/mips/mips.c (mips_va_start): Use POINTER_PLUS_EXPR
for pointers.
(mips_gimplify_va_arg_expr): Likewise.
Don't create BIT_AND_EXPR in a pointer type.
2007-06-15 Andrew Pinski <andrew_pinski@playstation.sony.com>
* trans-intrinsic.c (gfc_conv_intrinsic_repeat): Use
POINTER_PLUS_EXPR instead of PLUS_EXPR for pointer addition.
* trans-expr.c (gfc_trans_string_copy): Create
POINTER_PLUS_EXPR instead of a PLUS_EXPR
for pointer types.
2007-06-15 Andrew Pinski <andrew_pinski@playstation.sony.com>
* typeck.c (build_binary_op): For templates build the
expression in pieces to avoid the assert in build2_stat.
(get_member_function_from_ptrfunc):
Change over to using POINTER_PLUS_EXPR and convert
the second operand to sizetype.
* typeck2.c (build_m_component_ref): Likewise.
* init.c (expand_virtual_init): Create a POINTER_PLUS_EXPR
instead of PLUS_EXPR for pointers.
(build_new_1): Likewise.
(build_vec_delete_1): Likewise.
(build_vec_delete): Likewise.
* class.c (build_base_path): Likewise.
(build_base_path): Likewise.
(convert_to_base_statically): Likewise.
(fixed_type_or_null): Handle POINTER_PLUS_EXPR.
(get_vtbl_decl_for_binfo): Handle POINTER_PLUS_EXPR
instead of PLUS_EXPR.
(dfs_accumulate_vtbl_inits): Create a POINTER_PLUS_EXPR
instead of PLUS_EXPR for pointers.
* call.c (build_special_member_call): Likewise.
* rtti.c (build_headof): Likewise.
Use sizetype instead of ptrdiff_type_node.
(tinfo_base_init): Create a POINTER_PLUS_EXPR
instead of PLUS_EXPR for pointers.
* except.c (expand_start_catch_block): Do a
NEGATIVE and then a POINTER_PLUS_EXPR instead
of a MINUS_EXPR.
* cp-gimplify.c (cxx_omp_clause_apply_fn): Convert
PLUS_EXPR on pointer types over to use
POINTER_PLUS_EXPR and remove the conversion
to the pointer types.
* method.c (thunk_adjust): Use POINTER_PLUS_EXPR for
adding to a pointer type. Use size_int instead of
ssize_int. Convert the index to sizetype before
adding it to the pointer.
2007-06-15 Andrew Pinski <andrew_pinski@playstation.sony.com>
* trans.c (Attribute_to_gnu): When subtracting an
offset from a pointer, use POINTER_PLUS_EXPR with
NEGATE_EXPR instead of MINUS_EXPR.
(gnat_to_gnu): Likewise.
* utils.c (convert): When converting between
thin pointers, use POINTER_PLUS_EXPR and sizetype
for the offset.
* utils2.c (known_alignment): POINTER_PLUS_EXPR
have the same semantics as PLUS_EXPR for alignment.
(build_binary_op): Add support for the semantics of
POINTER_PLUS_EXPR's operands.
When adding an offset to a pointer, use POINTER_PLUS_EXPR.
2007-06-15 Andrew Pinski <andrew_pinski@playstation.sony.com>
* class.c (make_class_data): Build the index in sizetype.
Use POINTER_PLUS_EXPR instead of PLUS_EXPR when
adding to a pointer type.
(build_symbol_entry): Likewise.
* expr.c (build_java_arrayaccess): Likewise.
(build_field_ref): Likewise.
(build_known_method_ref): Likewise.
(build_invokevirtual): Likewise.
* except.c (build_exception_object_ref): Do a
NEGATIVE and then a POINTER_PLUS_EXPR instead
of a MINUS_EXPR.
2007-06-15 Andrew Pinski <andrew_pinski@playstation.sony.com>
PR tree-opt/32225
* gcc.c-torture/compile/20070605-1.c: New test.
* gcc.c-torture/compile/20070603-1.c: New testcase.
* gcc.c-torture/compile/20070603-2.c: New testcase.
* gcc.c-torture/compile/20070531-1.c: New test.
PR tree-opt/32167
* gcc.c-torture/compile/20070531-2.c: New test.
PR tree-opt/32144
* gcc.c-torture/compile/20070529-1.c: New test.
PR tree-opt/32145
* gcc.c-torture/compile/20070529-2.c: New test.
PR tree-opt/32015
* gcc.c-torture/compile/20070520-1.c: New test.
* g++.dg/ext/java-1.C: New test.
* gcc.dg/vect/vect-106.c: We are now able to vectorize two
loops instead of one. Remove the "can't determine dependence"
check.
* gcc.dg/tree-ssa/20030815-1.c: Remove testcase which is no longer
needed as the cast is gone in the first place.
* gcc.dg/max-1.c: Change local variable a to be a global one.
* gcc.dg/tree-ssa/ssa-pre-8.c: Update testcase since we don't
have a cast which is PREd.
From-SVN: r125755
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r-- | gcc/fold-const.c | 182 |
1 files changed, 135 insertions, 47 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 814d033..9c6690c 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -4439,6 +4439,20 @@ build_range_check (tree type, tree exp, int in_p, tree low, tree high) value = const_binop (MINUS_EXPR, high, low, 0); + + if (POINTER_TYPE_P (etype)) + { + if (value != 0 && !TREE_OVERFLOW (value)) + { + low = fold_convert (sizetype, low); + low = fold_build1 (NEGATE_EXPR, sizetype, low); + return build_range_check (type, + fold_build2 (POINTER_PLUS_EXPR, etype, exp, low), + 1, build_int_cst (etype, 0), value); + } + return 0; + } + if (value != 0 && !TREE_OVERFLOW (value)) return build_range_check (type, fold_build2 (MINUS_EXPR, etype, exp, low), @@ -5992,7 +6006,7 @@ constant_boolean_node (int value, tree type) offset is set to NULL_TREE. Base will be canonicalized to something you can get the element type from using TREE_TYPE (TREE_TYPE (base)). Offset will be the offset - in bytes to the base. */ + in bytes to the base in sizetype. */ static bool extract_array_ref (tree expr, tree *base, tree *offset) @@ -6000,21 +6014,20 @@ extract_array_ref (tree expr, tree *base, tree *offset) /* One canonical form is a PLUS_EXPR with the first argument being an ADDR_EXPR with a possible NOP_EXPR attached. */ - if (TREE_CODE (expr) == PLUS_EXPR) + if (TREE_CODE (expr) == POINTER_PLUS_EXPR) { tree op0 = TREE_OPERAND (expr, 0); tree inner_base, dummy1; /* Strip NOP_EXPRs here because the C frontends and/or - folders present us (int *)&x.a + 4B possibly. */ + folders present us (int *)&x.a p+ 4 possibly. */ STRIP_NOPS (op0); if (extract_array_ref (op0, &inner_base, &dummy1)) { *base = inner_base; - if (dummy1 == NULL_TREE) - *offset = TREE_OPERAND (expr, 1); - else - *offset = fold_build2 (PLUS_EXPR, TREE_TYPE (expr), - dummy1, TREE_OPERAND (expr, 1)); + *offset = fold_convert (sizetype, TREE_OPERAND (expr, 1)); + if (dummy1 != NULL_TREE) + *offset = fold_build2 (PLUS_EXPR, sizetype, + dummy1, *offset); return true; } } @@ -6032,6 +6045,7 @@ extract_array_ref (tree expr, tree *base, tree *offset) *base = TREE_OPERAND (op0, 0); *offset = fold_build2 (MULT_EXPR, TREE_TYPE (idx), idx, array_ref_element_size (op0)); + *offset = fold_convert (sizetype, *offset); } else { @@ -6866,7 +6880,7 @@ fold_sign_changed_comparison (enum tree_code code, tree type, return fold_build2 (code, type, arg0_inner, arg1); } -/* Tries to replace &a[idx] CODE s * delta with &a[idx CODE delta], if s is +/* Tries to replace &a[idx] p+ s * delta with &a[idx + delta], if s is step of the array. Reconstructs s and delta in the case of s * delta being an integer constant (and thus already folded). ADDR is the address. MULT is the multiplicative expression. @@ -6874,7 +6888,7 @@ fold_sign_changed_comparison (enum tree_code code, tree type, NULL_TREE is returned. */ static tree -try_move_mult_to_index (enum tree_code code, tree addr, tree op1) +try_move_mult_to_index (tree addr, tree op1) { tree s, delta, step; tree ref = TREE_OPERAND (addr, 0), pref; @@ -6882,6 +6896,9 @@ try_move_mult_to_index (enum tree_code code, tree addr, tree op1) tree itype; bool mdim = false; + /* Strip the nops that might be added when converting op1 to sizetype. */ + STRIP_NOPS (op1); + /* Canonicalize op1 into a possibly non-constant delta and an INTEGER_CST s. */ if (TREE_CODE (op1) == MULT_EXPR) @@ -6958,7 +6975,7 @@ try_move_mult_to_index (enum tree_code code, tree addr, tree op1) || TREE_CODE (TYPE_MAX_VALUE (itype)) != INTEGER_CST) continue; - tmp = fold_binary (code, itype, + tmp = fold_binary (PLUS_EXPR, itype, fold_convert (itype, TREE_OPERAND (ref, 1)), fold_convert (itype, delta)); @@ -6991,7 +7008,7 @@ try_move_mult_to_index (enum tree_code code, tree addr, tree op1) pos = TREE_OPERAND (pos, 0); } - TREE_OPERAND (pos, 1) = fold_build2 (code, itype, + TREE_OPERAND (pos, 1) = fold_build2 (PLUS_EXPR, itype, fold_convert (itype, TREE_OPERAND (pos, 1)), fold_convert (itype, delta)); @@ -7037,9 +7054,18 @@ fold_to_nonsharp_ineq_using_bound (tree ineq, tree bound) if (TREE_TYPE (a1) != typea) return NULL_TREE; - diff = fold_build2 (MINUS_EXPR, typea, a1, a); - if (!integer_onep (diff)) - return NULL_TREE; + if (POINTER_TYPE_P (typea)) + { + /* Convert the pointer types into integer before taking the difference. */ + tree ta = fold_convert (ssizetype, a); + tree ta1 = fold_convert (ssizetype, a1); + diff = fold_binary (MINUS_EXPR, ssizetype, ta1, ta); + } + else + diff = fold_binary (MINUS_EXPR, typea, a1, a); + + if (!diff || !integer_onep (diff)) + return NULL_TREE; return fold_build2 (GE_EXPR, type, a, y); } @@ -7830,11 +7856,11 @@ fold_unary (enum tree_code code, tree type, tree op0) } } - /* Convert (T1)(X op Y) into ((T1)X op (T1)Y), for pointer type, + /* Convert (T1)(X p+ Y) into ((T1)X p+ Y), for pointer type, when one of the new casts will fold away. Conservatively we assume - that this happens when X or Y is NOP_EXPR or Y is INTEGER_CST. */ - if (POINTER_TYPE_P (type) && POINTER_TYPE_P (TREE_TYPE (arg0)) - && BINARY_CLASS_P (arg0) + that this happens when X or Y is NOP_EXPR or Y is INTEGER_CST. */ + if (POINTER_TYPE_P (type) + && TREE_CODE (arg0) == POINTER_PLUS_EXPR && (TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST || TREE_CODE (TREE_OPERAND (arg0, 0)) == NOP_EXPR || TREE_CODE (TREE_OPERAND (arg0, 1)) == NOP_EXPR)) @@ -7843,7 +7869,7 @@ fold_unary (enum tree_code code, tree type, tree op0) tree arg01 = TREE_OPERAND (arg0, 1); return fold_build2 (TREE_CODE (arg0), type, fold_convert (type, arg00), - fold_convert (type, arg01)); + fold_convert (sizetype, arg01)); } /* Convert (T1)(~(T2)X) into ~(T1)X if T1 and T2 are integral types @@ -9066,7 +9092,68 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) switch (code) { + case POINTER_PLUS_EXPR: + /* 0 +p index -> (type)index */ + if (integer_zerop (arg0)) + return non_lvalue (fold_convert (type, arg1)); + + /* PTR +p 0 -> PTR */ + if (integer_zerop (arg1)) + return non_lvalue (fold_convert (type, arg0)); + + /* INT +p INT -> (PTR)(INT + INT). Stripping types allows for this. */ + if (INTEGRAL_TYPE_P (TREE_TYPE (arg1)) + && INTEGRAL_TYPE_P (TREE_TYPE (arg0))) + return fold_convert (type, fold_build2 (PLUS_EXPR, sizetype, + fold_convert (sizetype, arg1), + fold_convert (sizetype, arg0))); + + /* index +p PTR -> PTR +p index */ + if (POINTER_TYPE_P (TREE_TYPE (arg1)) + && INTEGRAL_TYPE_P (TREE_TYPE (arg0))) + return fold_build2 (POINTER_PLUS_EXPR, type, + fold_convert (type, arg1), fold_convert (sizetype, arg0)); + + /* (PTR +p B) +p A -> PTR +p (B + A) */ + if (TREE_CODE (arg0) == POINTER_PLUS_EXPR) + { + tree inner; + tree arg01 = fold_convert (sizetype, TREE_OPERAND (arg0, 1)); + tree arg00 = TREE_OPERAND (arg0, 0); + inner = fold_build2 (PLUS_EXPR, sizetype, arg01, fold_convert (sizetype, arg1)); + return fold_build2 (POINTER_PLUS_EXPR, type, arg00, inner); + } + + /* PTR_CST +p CST -> CST1 */ + if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST) + return fold_build2 (PLUS_EXPR, type, arg0, fold_convert (type, arg1)); + + /* Try replacing &a[i1] +p c * i2 with &a[i1 + i2], if c is step + of the array. Loop optimizer sometimes produce this type of + expressions. */ + if (TREE_CODE (arg0) == ADDR_EXPR) + { + tem = try_move_mult_to_index (arg0, fold_convert (sizetype, arg1)); + if (tem) + return fold_convert (type, tem); + } + + return NULL_TREE; case PLUS_EXPR: + /* PTR + INT -> (INT)(PTR p+ INT) */ + if (POINTER_TYPE_P (TREE_TYPE (arg0)) + && INTEGRAL_TYPE_P (TREE_TYPE (arg1))) + return fold_convert (type, fold_build2 (POINTER_PLUS_EXPR, + TREE_TYPE (arg0), + arg0, + fold_convert (sizetype, arg1))); + /* INT + PTR -> (INT)(PTR p+ INT) */ + if (POINTER_TYPE_P (TREE_TYPE (arg1)) + && INTEGRAL_TYPE_P (TREE_TYPE (arg0))) + return fold_convert (type, fold_build2 (POINTER_PLUS_EXPR, + TREE_TYPE (arg1), + arg1, + fold_convert (sizetype, arg0))); /* A + (-B) -> A - B */ if (TREE_CODE (arg1) == NEGATE_EXPR) return fold_build2 (MINUS_EXPR, type, @@ -9173,22 +9260,6 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) fold_convert (type, parg1))); } - - /* Try replacing &a[i1] + c * i2 with &a[i1 + i2], if c is step - of the array. Loop optimizer sometimes produce this type of - expressions. */ - if (TREE_CODE (arg0) == ADDR_EXPR) - { - tem = try_move_mult_to_index (PLUS_EXPR, arg0, arg1); - if (tem) - return fold_convert (type, tem); - } - else if (TREE_CODE (arg1) == ADDR_EXPR) - { - tem = try_move_mult_to_index (PLUS_EXPR, arg1, arg0); - if (tem) - return fold_convert (type, tem); - } } else { @@ -9465,6 +9536,31 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) return NULL_TREE; case MINUS_EXPR: + /* Pointer simplifications for subtraction, simple reassociations. */ + if (POINTER_TYPE_P (TREE_TYPE (arg1)) && POINTER_TYPE_P (TREE_TYPE (arg0))) + { + /* (PTR0 p+ A) - (PTR1 p+ B) -> (PTR0 - PTR1) + (A - B) */ + if (TREE_CODE (arg0) == POINTER_PLUS_EXPR + && TREE_CODE (arg1) == POINTER_PLUS_EXPR) + { + tree arg00 = fold_convert (type, TREE_OPERAND (arg0, 0)); + tree arg01 = fold_convert (type, TREE_OPERAND (arg0, 1)); + tree arg10 = fold_convert (type, TREE_OPERAND (arg1, 0)); + tree arg11 = fold_convert (type, TREE_OPERAND (arg1, 1)); + return fold_build2 (PLUS_EXPR, type, + fold_build2 (MINUS_EXPR, type, arg00, arg10), + fold_build2 (MINUS_EXPR, type, arg01, arg11)); + } + /* (PTR0 p+ A) - PTR1 -> (PTR0 - PTR1) + A, assuming PTR0 - PTR1 simplifies. */ + else if (TREE_CODE (arg0) == POINTER_PLUS_EXPR) + { + tree arg00 = fold_convert (type, TREE_OPERAND (arg0, 0)); + tree arg01 = fold_convert (type, TREE_OPERAND (arg0, 1)); + tree tmp = fold_binary (MINUS_EXPR, type, arg00, fold_convert (type, arg1)); + if (tmp) + return fold_build2 (PLUS_EXPR, type, tmp, arg01); + } + } /* A - (-B) -> A + B */ if (TREE_CODE (arg1) == NEGATE_EXPR) return fold_build2 (PLUS_EXPR, type, arg0, TREE_OPERAND (arg1, 0)); @@ -9634,16 +9730,6 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) } } - /* Try replacing &a[i1] - c * i2 with &a[i1 - i2], if c is step - of the array. Loop optimizer sometimes produce this type of - expressions. */ - if (TREE_CODE (arg0) == ADDR_EXPR) - { - tem = try_move_mult_to_index (MINUS_EXPR, arg0, arg1); - if (tem) - return fold_convert (type, tem); - } - if (flag_unsafe_math_optimizations && (TREE_CODE (arg0) == RDIV_EXPR || TREE_CODE (arg0) == MULT_EXPR) && (TREE_CODE (arg1) == RDIV_EXPR || TREE_CODE (arg1) == MULT_EXPR) @@ -13231,6 +13317,7 @@ tree_expr_nonnegative_warnv_p (tree t, bool *strict_overflow_p) case REAL_CST: return ! REAL_VALUE_NEGATIVE (TREE_REAL_CST (t)); + case POINTER_PLUS_EXPR: case PLUS_EXPR: if (FLOAT_TYPE_P (TREE_TYPE (t))) return (tree_expr_nonnegative_warnv_p (TREE_OPERAND (t, 0), @@ -13586,6 +13673,7 @@ tree_expr_nonzero_warnv_p (tree t, bool *strict_overflow_p) case INTEGER_CST: return !integer_zerop (t); + case POINTER_PLUS_EXPR: case PLUS_EXPR: if (TYPE_OVERFLOW_UNDEFINED (type)) { @@ -14178,7 +14266,7 @@ fold_indirect_ref_1 (tree type, tree op0) } /* ((foo*)&complexfoo)[1] => __imag__ complexfoo */ - if (TREE_CODE (sub) == PLUS_EXPR + if (TREE_CODE (sub) == POINTER_PLUS_EXPR && TREE_CODE (TREE_OPERAND (sub, 1)) == INTEGER_CST) { tree op00 = TREE_OPERAND (sub, 0); |