aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-alias.c
diff options
context:
space:
mode:
authorRichard Guenther <rguenther@suse.de>2010-07-01 08:49:19 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2010-07-01 08:49:19 +0000
commit70f348148c09468b05aa09fcfa91b61611003c27 (patch)
tree4cc8d9c35ed3127dbf885a1f08a83776819bed41 /gcc/tree-ssa-alias.c
parent952b984e86f884d08d2e1ae5675ce518381692c5 (diff)
downloadgcc-70f348148c09468b05aa09fcfa91b61611003c27.zip
gcc-70f348148c09468b05aa09fcfa91b61611003c27.tar.gz
gcc-70f348148c09468b05aa09fcfa91b61611003c27.tar.bz2
re PR middle-end/42834 (memcpy folding overeager)
2010-07-01 Richard Guenther <rguenther@suse.de> PR middle-end/42834 PR middle-end/44468 * doc/gimple.texi (is_gimple_mem_ref_addr): Document. * doc/generic.texi (References to storage): Document MEM_REF. * tree-pretty-print.c (dump_generic_node): Handle MEM_REF. (print_call_name): Likewise. * tree.c (recompute_tree_invariant_for_addr_expr): Handle MEM_REF. (build_simple_mem_ref_loc): New function. (mem_ref_offset): Likewise. * tree.h (build_simple_mem_ref_loc): Declare. (build_simple_mem_ref): Define. (mem_ref_offset): Declare. * fold-const.c: Include tree-flow.h. (operand_equal_p): Handle MEM_REF. (build_fold_addr_expr_with_type_loc): Likewise. (fold_comparison): Likewise. (fold_unary_loc): Fold VIEW_CONVERT_EXPR <T1, MEM_REF <T2, ...>> to MEM_REF <T1, ...>. (fold_binary_loc): Fold MEM[&MEM[p, CST1], CST2] to MEM[p, CST1 + CST2], fold MEM[&a.b, CST2] to MEM[&a, offsetof (a, b) + CST2]. * tree-ssa-alias.c (ptr_deref_may_alias_decl_p): Handle MEM_REF. (ptr_deref_may_alias_ref_p_1): Likewise. (ao_ref_base_alias_set): Properly differentiate base object for offset and TBAA. (ao_ref_init_from_ptr_and_size): Use MEM_REF. (indirect_ref_may_alias_decl_p): Handle MEM_REFs properly. (indirect_refs_may_alias_p): Likewise. (refs_may_alias_p_1): Likewise. Remove pointer SSA name def chasing code. (ref_maybe_used_by_call_p_1): Handle MEM_REF. (call_may_clobber_ref_p_1): Likewise. * dwarf2out.c (loc_list_from_tree): Handle MEM_REF. * expr.c (expand_assignment): Handle MEM_REF. (store_expr): Handle MEM_REFs from STRING_CSTs. (store_field): If expanding a MEM_REF of a non-addressable decl use bitfield operations. (get_inner_reference): Handle MEM_REF. (expand_expr_addr_expr_1): Likewise. (expand_expr_real_1): Likewise. * tree-eh.c (tree_could_trap_p): Handle MEM_REF. * alias.c (ao_ref_from_mem): Handle MEM_REF. (get_alias_set): Likewise. Properly handle VIEW_CONVERT_EXPRs. * tree-data-ref.c (dr_analyze_innermost): Handle MEM_REF. (dr_analyze_indices): Likewise. (dr_analyze_alias): Likewise. (object_address_invariant_in_loop_p): Likewise. * gimplify.c (mark_addressable): Handle MEM_REF. (gimplify_cond_expr): Build MEM_REFs. (gimplify_modify_expr_to_memcpy): Likewise. (gimplify_init_ctor_preeval_1): Handle MEM_REF. (gimple_fold_indirect_ref): Adjust. (gimplify_expr): Handle MEM_REF. Gimplify INDIRECT_REF to MEM_REF. * tree.def (MEM_REF): New tree code. * tree-dfa.c: Include toplev.h. (get_ref_base_and_extent): Handle MEM_REF. (get_addr_base_and_unit_offset): New function. * emit-rtl.c (set_mem_attributes_minus_bitpos): Handle MEM_REF. * gimple-fold.c (may_propagate_address_into_dereference): Handle MEM_REF. (maybe_fold_offset_to_array_ref): Allow possibly out-of bounds accesses if the array has just one dimension. Remove always true parameter. Do not require type compatibility here. (maybe_fold_offset_to_component_ref): Remove. (maybe_fold_stmt_indirect): Remove. (maybe_fold_reference): Remove INDIRECT_REF handling. Fold back to non-MEM_REF. (maybe_fold_offset_to_address): Simplify. Deal with type mismatches here. (maybe_fold_reference): Likewise. (maybe_fold_stmt_addition): Likewise. Also handle &ARRAY + I in addition to &ARRAY[0] + I. (fold_gimple_assign): Handle ADDR_EXPR of MEM_REFs. (gimple_get_relevant_ref_binfo): Handle MEM_REF. * cfgexpand.c (expand_debug_expr): Handle MEM_REF. * tree-ssa.c (useless_type_conversion_p): Make most pointer conversions useless. (warn_uninitialized_var): Handle MEM_REF. (maybe_rewrite_mem_ref_base): New function. (execute_update_addresses_taken): Implement re-writing of MEM_REFs to SSA form. * tree-inline.c (remap_gimple_op_r): Handle MEM_REF, remove INDIRECT_REF handling. (copy_tree_body_r): Handle MEM_REF. * gimple.c (is_gimple_addressable): Adjust. (is_gimple_address): Likewise. (is_gimple_invariant_address): ADDR_EXPRs of MEM_REFs with invariant base are invariant. (is_gimple_min_lval): Adjust. (is_gimple_mem_ref_addr): New function. (get_base_address): Handle MEM_REF. (count_ptr_derefs): Likewise. (get_base_loadstore): Likewise. * gimple.h (is_gimple_mem_ref_addr): Declare. (gimple_call_fndecl): Handle invariant MEM_REF addresses. * tree-cfg.c (verify_address): New function, split out from ... (verify_expr): ... here. Use for verifying ADDR_EXPRs and the address operand of MEM_REFs. Verify MEM_REFs. Reject INDIRECT_REFs. (verify_types_in_gimple_min_lval): Handle MEM_REF. Disallow INDIRECT_REF. Allow conversions. (verify_types_in_gimple_reference): Verify VIEW_CONVERT_EXPR of a register does not change its size. (verify_types_in_gimple_reference): Verify MEM_REF. (verify_gimple_assign_single): Disallow INDIRECT_REF. Handle MEM_REF. * tree-ssa-operands.c (opf_non_addressable, opf_not_non_addressable): New. (mark_address_taken): Handle MEM_REF. (get_indirect_ref_operands): Pass through opf_not_non_addressable. (get_asm_expr_operands): Pass opf_not_non_addressable. (get_expr_operands): Handle opf_[not_]non_addressable. Handle MEM_REF. Remove INDIRECT_REF handling. * tree-vrp.c: (check_array_ref): Handle MEM_REF. (search_for_addr_array): Likewise. (check_array_bounds): Likewise. (vrp_stmt_computes_nonzero): Adjust for MEM_REF. * tree-ssa-loop-im.c (for_each_index): Handle MEM_REF. (ref_always_accessed_p): Likewise. (gen_lsm_tmp_name): Likewise. Handle ADDR_EXPR. * tree-complex.c (extract_component): Do not handle INDIRECT_REF. Handle MEM_REF. * cgraphbuild.c (mark_load): Properly check for NULL result from get_base_address. (mark_store): Likewise. * tree-ssa-loop-niter.c (array_at_struct_end_p): Handle MEM_REF. * tree-loop-distribution.c (generate_builtin): Exchange INDIRECT_REF handling for MEM_REF. * tree-scalar-evolution.c (follow_ssa_edge_expr): Handle &MEM[ptr + CST] similar to POINTER_PLUS_EXPR. * builtins.c (stabilize_va_list_loc): Use the function ABI valist type if we couldn't canonicalize the argument type. Always dereference with the canonical va-list type. (maybe_emit_free_warning): Handle MEM_REF. (fold_builtin_memory_op): Simplify and handle MEM_REFs in folding memmove to memcpy. * builtins.c (fold_builtin_memory_op): Use ref-all types for all memcpy foldings. * omp-low.c (build_receiver_ref): Adjust for MEM_REF. (build_outer_var_ref): Likewise. (scan_omp_1_op): Likewise. (lower_rec_input_clauses): Likewise. (lower_lastprivate_clauses): Likewise. (lower_reduction_clauses): Likewise. (lower_copyprivate_clauses): Likewise. (expand_omp_atomic_pipeline): Likewise. (expand_omp_atomic_mutex): Likewise. (create_task_copyfn): Likewise. * tree-ssa-sccvn.c (copy_reference_ops_from_ref): Handle MEM_REF. Remove old union trick. Initialize constant offsets. (ao_ref_init_from_vn_reference): Likewise. Do not handle INDIRECT_REF. Init base_alias_set properly. (vn_reference_lookup_3): Replace INDIRECT_REF handling with MEM_REF. (vn_reference_fold_indirect): Adjust for MEM_REFs. (valueize_refs): Fold MEM_REFs. Re-evaluate constant offset for ARRAY_REFs. (may_insert): Remove. (visit_reference_op_load): Do not test may_insert. (run_scc_vn): Remove parameter, do not fiddle with may_insert. * tree-ssa-sccvn.h (struct vn_reference_op_struct): Add a field to store the constant offset this op applies. (run_scc_vn): Adjust prototype. * cgraphunit.c (thunk_adjust): Adjust for MEM_REF. * tree-ssa-ccp.c (ccp_fold): Replace INDIRECT_REF folding with MEM_REF. Propagate &foo + CST as &MEM[&foo, CST]. Do not bother about volatile qualifiers on pointers. (fold_const_aggregate_ref): Handle MEM_REF, do not handle INDIRECT_REF. * tree-ssa-loop-ivopts.c * tree-ssa-loop-ivopts.c (determine_base_object): Adjust for MEM_REF. (strip_offset_1): Likewise. (find_interesting_uses_address): Replace INDIRECT_REF handling with MEM_REF handling. (get_computation_cost_at): Likewise. * ipa-pure-const.c (check_op): Handle MEM_REF. * tree-stdarg.c (check_all_va_list_escapes): Adjust for MEM_REF. * tree-ssa-sink.c (is_hidden_global_store): Handle MEM_REF and constants. * ipa-inline.c (likely_eliminated_by_inlining_p): Handle MEM_REF. * tree-parloops.c (take_address_of): Adjust for MEM_REF. (eliminate_local_variables_1): Likewise. (create_call_for_reduction_1): Likewise. (create_loads_for_reductions): Likewise. (create_loads_and_stores_for_name): Likewise. * matrix-reorg.c (may_flatten_matrices_1): Sanitize. (ssa_accessed_in_tree): Handle MEM_REF. (ssa_accessed_in_assign_rhs): Likewise. (update_type_size): Likewise. (analyze_accesses_for_call_stmt): Likewise. (analyze_accesses_for_assign_stmt): Likewise. (transform_access_sites): Likewise. (transform_allocation_sites): Likewise. * tree-affine.c (tree_to_aff_combination): Handle MEM_REF. * tree-vect-data-refs.c (vect_create_addr_base_for_vector_ref): Do not handle INDIRECT_REF. * tree-ssa-phiopt.c (add_or_mark_expr): Handle MEM_REF. (cond_store_replacement): Likewise. * tree-ssa-pre.c (create_component_ref_by_pieces_1): Handle MEM_REF, no not handle INDIRECT_REFs. (insert_into_preds_of_block): Properly initialize avail. (phi_translate_1): Fold MEM_REFs. Re-evaluate constant offset for ARRAY_REFs. Properly handle reference lookups that require a bit re-interpretation. (can_PRE_operation): Do not handle INDIRECT_REF. Handle MEM_REF. * tree-sra.c * tree-sra.c (build_access_from_expr_1): Handle MEM_REF. (build_ref_for_offset_1): Remove. (build_ref_for_offset): Build MEM_REFs. (gate_intra_sra): Disable for now. (sra_ipa_modify_expr): Handle MEM_REF. (ipa_early_sra_gate): Disable for now. * tree-sra.c (create_access): Swap INDIRECT_REF handling for MEM_REF handling. (disqualify_base_of_expr): Likewise. (ptr_parm_has_direct_uses): Swap INDIRECT_REF handling for MEM_REF handling. (sra_ipa_modify_expr): Remove INDIRECT_REF handling. Use mem_ref_offset. Remove bogus folding. (build_access_from_expr_1): Properly handle MEM_REF for non IPA-SRA. (make_fancy_name_1): Add support for MEM_REF. * tree-predcom.c (ref_at_iteration): Handle MEM_REFs. * tree-mudflap.c (mf_xform_derefs_1): Adjust for MEM_REF. * ipa-prop.c (compute_complex_assign_jump_func): Handle MEM_REF. (compute_complex_ancestor_jump_func): Likewise. (ipa_analyze_virtual_call_uses): Likewise. * tree-ssa-forwprop.c (forward_propagate_addr_expr_1): Replace INDIRECT_REF folding with more generalized MEM_REF folding. (tree_ssa_forward_propagate_single_use_vars): Adjust accordingly. (forward_propagate_addr_into_variable_array_index): Also handle &ARRAY + I in addition to &ARRAY[0] + I. * tree-ssa-dce.c (ref_may_be_aliased): Handle MEM_REF. * tree-ssa-ter.c (find_replaceable_in_bb): Avoid TER if that creates assignments with overlap. * tree-nested.c (get_static_chain): Adjust for MEM_REF. (get_frame_field): Likewise. (get_nonlocal_debug_decl): Likewise. (convert_nonlocal_reference_op): Likewise. (struct nesting_info): Add mem_refs pointer-set. (create_nesting_tree): Allocate it. (convert_local_reference_op): Insert to be folded mem-refs. (fold_mem_refs): New function. (finalize_nesting_tree_1): Perform defered folding of mem-refs (free_nesting_tree): Free the pointer-set. * tree-vect-stmts.c (vectorizable_store): Adjust for MEM_REF. (vectorizable_load): Likewise. * tree-ssa-phiprop.c (phiprop_insert_phi): Adjust for MEM_REF. (propagate_with_phi): Likewise. * tree-object-size.c (addr_object_size): Handle MEM_REFs instead of INDIRECT_REFs. (compute_object_offset): Handle MEM_REF. (plus_stmt_object_size): Handle MEM_REF. (collect_object_sizes_for): Dispatch to plus_stmt_object_size for &MEM_REF. * tree-flow.h (get_addr_base_and_unit_offset): Declare. (symbol_marked_for_renaming): Likewise. * Makefile.in (tree-dfa.o): Add $(TOPLEV_H). (fold-const.o): Add $(TREE_FLOW_H). * tree-ssa-structalias.c (get_constraint_for_1): Handle MEM_REF. (find_func_clobbers): Likewise. * ipa-struct-reorg.c (decompose_indirect_ref_acc): Handle MEM_REF. (decompose_access): Likewise. (replace_field_acc): Likewise. (replace_field_access_stmt): Likewise. (insert_new_var_in_stmt): Likewise. (get_stmt_accesses): Likewise. (reorg_structs_drive): Disable. * config/i386/i386.c (ix86_va_start): Adjust for MEM_REF. (ix86_canonical_va_list_type): Likewise. cp/ * cp-gimplify.c (cp_gimplify_expr): Open-code the rhs predicate we are looking for, allow non-gimplified INDIRECT_REFs. testsuite/ * gcc.c-torture/execute/20100316-1.c: New testcase. * gcc.c-torture/execute/pr44468.c: Likewise. * gcc.c-torture/compile/20100609-1.c: Likewise. * gcc.dg/volatile2.c: Adjust. * gcc.dg/plugin/selfassign.c: Likewise. * gcc.dg/pr36902.c: Likewise. * gcc.dg/tree-ssa/foldaddr-2.c: Remove. * gcc.dg/tree-ssa/foldaddr-3.c: Likewise. * gcc.dg/tree-ssa/forwprop-8.c: Adjust. * gcc.dg/tree-ssa/pr17141-1.c: Likewise. * gcc.dg/tree-ssa/ssa-fre-13.c: Likewise. * gcc.dg/tree-ssa/ssa-fre-14.c: Likewise. * gcc.dg/tree-ssa/ssa-ccp-21.c: Likewise. * gcc.dg/tree-ssa/pta-ptrarith-1.c: Likewise. * gcc.dg/tree-ssa/20030807-7.c: Likewise. * gcc.dg/tree-ssa/forwprop-10.c: Likewise. * gcc.dg/tree-ssa/ssa-fre-1.c: Likewise. * gcc.dg/tree-ssa/pta-ptrarith-2.c: Likewise. * gcc.dg/tree-ssa/ssa-ccp-23.c: Likewise. * gcc.dg/tree-ssa/forwprop-1.c: Likewise. * gcc.dg/tree-ssa/forwprop-2.c: Likewise. * gcc.dg/tree-ssa/struct-aliasing-1.c: Likewise. * gcc.dg/tree-ssa/ssa-ccp-25.c: Likewise. * gcc.dg/tree-ssa/ssa-pre-26.c: Likewise. * gcc.dg/tree-ssa/struct-aliasing-2.c: Likewise. * gcc.dg/tree-ssa/ssa-ccp-26.c: Likewise. * gcc.dg/tree-ssa/ssa-sccvn-4.c: Likewise. * gcc.dg/tree-ssa/ssa-pre-7.c: Likewise. * gcc.dg/tree-ssa/forwprop-5.c: Likewise. * gcc.dg/struct/w_prof_two_strs.c: XFAIL. * gcc.dg/struct/wo_prof_escape_arg_to_local.c: Likewise. * gcc.dg/struct/wo_prof_global_var.c: Likewise. * gcc.dg/struct/wo_prof_malloc_size_var.c: Likewise. * gcc.dg/struct/w_prof_local_array.c: Likewise. * gcc.dg/struct/w_prof_single_str_global.c: Likewise. * gcc.dg/struct/wo_prof_escape_str_init.c: Likewise. * gcc.dg/struct/wo_prof_array_through_pointer.c: Likewise. * gcc.dg/struct/w_prof_global_array.c: Likewise. * gcc.dg/struct/wo_prof_array_field.c: Likewise. * gcc.dg/struct/wo_prof_single_str_local.c: Likewise. * gcc.dg/struct/w_prof_local_var.c: Likewise. * gcc.dg/struct/wo_prof_two_strs.c: Likewise. * gcc.dg/struct/wo_prof_empty_str.c: Likewise. * gcc.dg/struct/wo_prof_local_array.c: Likewise. * gcc.dg/struct/w_prof_global_var.c: Likewise. * gcc.dg/struct/wo_prof_single_str_global.c: Likewise. * gcc.dg/struct/wo_prof_escape_substr_value.c: Likewise. * gcc.dg/struct/wo_prof_global_array.c: Likewise. * gcc.dg/struct/wo_prof_escape_return.c: Likewise. * gcc.dg/struct/wo_prof_escape_substr_array.c: Likewise. * gcc.dg/struct/wo_prof_double_malloc.c: Likewise. * gcc.dg/struct/w_ratio_cold_str.c: Likewise. * gcc.dg/struct/wo_prof_escape_substr_pointer.c: Likewise. * gcc.dg/struct/wo_prof_local_var.c: Likewise. * gcc.dg/tree-prof/stringop-1.c: Adjust. * g++.dg/tree-ssa/pr31146.C: Likewise. * g++.dg/tree-ssa/copyprop-1.C: Likewise. * g++.dg/tree-ssa/pr33604.C: Likewise. * g++.dg/plugin/selfassign.c: Likewise. * gfortran.dg/array_memcpy_3.f90: Likewise. * gfortran.dg/array_memcpy_4.f90: Likewise. * c-c++-common/torture/pr42834.c: New testcase. From-SVN: r161655
Diffstat (limited to 'gcc/tree-ssa-alias.c')
-rw-r--r--gcc/tree-ssa-alias.c238
1 files changed, 136 insertions, 102 deletions
diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c
index 28b8fb7..78eb362 100644
--- a/gcc/tree-ssa-alias.c
+++ b/gcc/tree-ssa-alias.c
@@ -182,7 +182,8 @@ ptr_deref_may_alias_decl_p (tree ptr, tree decl)
{
tree base = get_base_address (TREE_OPERAND (ptr, 0));
if (base
- && INDIRECT_REF_P (base))
+ && (INDIRECT_REF_P (base)
+ || TREE_CODE (base) == MEM_REF))
ptr = TREE_OPERAND (base, 0);
else if (base
&& SSA_VAR_P (base))
@@ -238,7 +239,8 @@ ptr_derefs_may_alias_p (tree ptr1, tree ptr2)
{
tree base = get_base_address (TREE_OPERAND (ptr1, 0));
if (base
- && INDIRECT_REF_P (base))
+ && (INDIRECT_REF_P (base)
+ || TREE_CODE (base) == MEM_REF))
ptr1 = TREE_OPERAND (base, 0);
else if (base
&& SSA_VAR_P (base))
@@ -250,7 +252,8 @@ ptr_derefs_may_alias_p (tree ptr1, tree ptr2)
{
tree base = get_base_address (TREE_OPERAND (ptr2, 0));
if (base
- && INDIRECT_REF_P (base))
+ && (INDIRECT_REF_P (base)
+ || TREE_CODE (base) == MEM_REF))
ptr2 = TREE_OPERAND (base, 0);
else if (base
&& SSA_VAR_P (base))
@@ -299,7 +302,8 @@ ptr_deref_may_alias_ref_p_1 (tree ptr, ao_ref *ref)
{
tree base = ao_ref_base (ref);
- if (INDIRECT_REF_P (base))
+ if (INDIRECT_REF_P (base)
+ || TREE_CODE (base) == MEM_REF)
return ptr_derefs_may_alias_p (ptr, TREE_OPERAND (base, 0));
else if (SSA_VAR_P (base))
return ptr_deref_may_alias_decl_p (ptr, base);
@@ -470,12 +474,18 @@ ao_ref_base (ao_ref *ref)
/* Returns the base object alias set of the memory reference *REF. */
-static alias_set_type ATTRIBUTE_UNUSED
+static alias_set_type
ao_ref_base_alias_set (ao_ref *ref)
{
+ tree base_ref;
if (ref->base_alias_set != -1)
return ref->base_alias_set;
- ref->base_alias_set = get_alias_set (ao_ref_base (ref));
+ if (!ref->ref)
+ return 0;
+ base_ref = ref->ref;
+ while (handled_component_p (base_ref))
+ base_ref = TREE_OPERAND (base_ref, 0);
+ ref->base_alias_set = get_alias_set (base_ref);
return ref->base_alias_set;
}
@@ -505,7 +515,8 @@ ao_ref_init_from_ptr_and_size (ao_ref *ref, tree ptr, tree size)
&ref->offset, &t1, &t2);
else
{
- ref->base = build1 (INDIRECT_REF, char_type_node, ptr);
+ ref->base = build2 (MEM_REF, char_type_node,
+ ptr, build_int_cst (ptr_type_node, 0));
ref->offset = 0;
}
if (size
@@ -665,33 +676,45 @@ decl_refs_may_alias_p (tree base1,
if non-NULL are the complete memory reference trees. */
static bool
-indirect_ref_may_alias_decl_p (tree ref1, tree ptr1,
- HOST_WIDE_INT offset1, HOST_WIDE_INT max_size1,
+indirect_ref_may_alias_decl_p (tree ref1 ATTRIBUTE_UNUSED, tree base1,
+ HOST_WIDE_INT offset1,
+ HOST_WIDE_INT max_size1 ATTRIBUTE_UNUSED,
alias_set_type ref1_alias_set,
alias_set_type base1_alias_set,
- tree ref2, tree base2,
+ tree ref2 ATTRIBUTE_UNUSED, tree base2,
HOST_WIDE_INT offset2, HOST_WIDE_INT max_size2,
alias_set_type ref2_alias_set,
- alias_set_type base2_alias_set)
+ alias_set_type base2_alias_set, bool tbaa_p)
{
+ tree ptr1 = TREE_OPERAND (base1, 0);
+ tree ptrtype1;
+ HOST_WIDE_INT offset1p = offset1;
+
+ if (TREE_CODE (base1) == MEM_REF)
+ offset1p = offset1 + mem_ref_offset (base1).low * BITS_PER_UNIT;
+
/* If only one reference is based on a variable, they cannot alias if
the pointer access is beyond the extent of the variable access.
(the pointer base cannot validly point to an offset less than zero
of the variable).
They also cannot alias if the pointer may not point to the decl. */
- if (max_size2 != -1
- && !ranges_overlap_p (offset1, max_size1, 0, offset2 + max_size2))
+ if (!ranges_overlap_p (MAX (0, offset1p), -1, offset2, max_size2))
return false;
if (!ptr_deref_may_alias_decl_p (ptr1, base2))
return false;
/* Disambiguations that rely on strict aliasing rules follow. */
- if (!flag_strict_aliasing)
+ if (!flag_strict_aliasing || !tbaa_p)
return true;
+ if (TREE_CODE (base1) == MEM_REF)
+ ptrtype1 = TREE_TYPE (TREE_OPERAND (base1, 1));
+ else
+ ptrtype1 = TREE_TYPE (ptr1);
+
/* If the alias set for a pointer access is zero all bets are off. */
if (base1_alias_set == -1)
- base1_alias_set = get_deref_alias_set (ptr1);
+ base1_alias_set = get_deref_alias_set (ptrtype1);
if (base1_alias_set == 0)
return true;
if (base2_alias_set == -1)
@@ -699,22 +722,52 @@ indirect_ref_may_alias_decl_p (tree ref1, tree ptr1,
/* If both references are through the same type, they do not alias
if the accesses do not overlap. This does extra disambiguation
- for mixed/pointer accesses but requires strict aliasing. */
- if (same_type_for_tbaa (TREE_TYPE (TREE_TYPE (ptr1)),
- TREE_TYPE (base2)) == 1)
+ for mixed/pointer accesses but requires strict aliasing.
+ For MEM_REFs we require that the component-ref offset we computed
+ is relative to the start of the type which we ensure by
+ comparing rvalue and access type and disregarding the constant
+ pointer offset. */
+ if ((TREE_CODE (base1) != MEM_REF
+ || same_type_for_tbaa (TREE_TYPE (base1), TREE_TYPE (ptrtype1)) == 1)
+ && same_type_for_tbaa (TREE_TYPE (ptrtype1), TREE_TYPE (base2)) == 1)
return ranges_overlap_p (offset1, max_size1, offset2, max_size2);
- /* The only way to access a variable is through a pointer dereference
- of the same alias set or a subset of it. */
+ /* When we are trying to disambiguate an access with a pointer dereference
+ as base versus one with a decl as base we can use both the size
+ of the decl and its dynamic type for extra disambiguation.
+ ??? We do not know anything about the dynamic type of the decl
+ other than that its alias-set contains base2_alias_set as a subset
+ which does not help us here. */
+ /* As we know nothing useful about the dynamic type of the decl just
+ use the usual conflict check rather than a subset test.
+ ??? We could introduce -fvery-strict-aliasing when the language
+ does not allow decls to have a dynamic type that differs from their
+ static type. Then we can check
+ !alias_set_subset_of (base1_alias_set, base2_alias_set) instead. */
if (base1_alias_set != base2_alias_set
- && !alias_set_subset_of (base1_alias_set, base2_alias_set))
+ && !alias_sets_conflict_p (base1_alias_set, base2_alias_set))
+ return false;
+ /* If the size of the access relevant for TBAA through the pointer
+ is bigger than the size of the decl we can't possibly access the
+ decl via that pointer. */
+ if (DECL_SIZE (base2) && COMPLETE_TYPE_P (TREE_TYPE (ptrtype1))
+ && TREE_CODE (DECL_SIZE (base2)) == INTEGER_CST
+ && TREE_CODE (TYPE_SIZE (TREE_TYPE (ptrtype1))) == INTEGER_CST
+ /* ??? This in turn may run afoul when a decl of type T which is
+ a member of union type U is accessed through a pointer to
+ type U and sizeof T is smaller than sizeof U. */
+ && TREE_CODE (TREE_TYPE (ptrtype1)) != UNION_TYPE
+ && TREE_CODE (TREE_TYPE (ptrtype1)) != QUAL_UNION_TYPE
+ && tree_int_cst_lt (DECL_SIZE (base2), TYPE_SIZE (TREE_TYPE (ptrtype1))))
return false;
/* Do access-path based disambiguation. */
if (ref1 && ref2
&& handled_component_p (ref1)
- && handled_component_p (ref2))
- return aliasing_component_refs_p (ref1, TREE_TYPE (TREE_TYPE (ptr1)),
+ && handled_component_p (ref2)
+ && (TREE_CODE (base1) != MEM_REF
+ || same_type_for_tbaa (TREE_TYPE (base1), TREE_TYPE (ptrtype1)) == 1))
+ return aliasing_component_refs_p (ref1, TREE_TYPE (ptrtype1),
ref1_alias_set, base1_alias_set,
offset1, max_size1,
ref2, TREE_TYPE (base2),
@@ -732,42 +785,65 @@ indirect_ref_may_alias_decl_p (tree ref1, tree ptr1,
if non-NULL are the complete memory reference trees. */
static bool
-indirect_refs_may_alias_p (tree ref1, tree ptr1,
+indirect_refs_may_alias_p (tree ref1 ATTRIBUTE_UNUSED, tree base1,
HOST_WIDE_INT offset1, HOST_WIDE_INT max_size1,
alias_set_type ref1_alias_set,
alias_set_type base1_alias_set,
- tree ref2, tree ptr2,
+ tree ref2 ATTRIBUTE_UNUSED, tree base2,
HOST_WIDE_INT offset2, HOST_WIDE_INT max_size2,
alias_set_type ref2_alias_set,
- alias_set_type base2_alias_set)
+ alias_set_type base2_alias_set, bool tbaa_p)
{
+ tree ptr1 = TREE_OPERAND (base1, 0);
+ tree ptr2 = TREE_OPERAND (base2, 0);
+ tree ptrtype1, ptrtype2;
+
/* If both bases are based on pointers they cannot alias if they may not
point to the same memory object or if they point to the same object
and the accesses do not overlap. */
if (operand_equal_p (ptr1, ptr2, 0))
- return ranges_overlap_p (offset1, max_size1, offset2, max_size2);
+ {
+ if (TREE_CODE (base1) == MEM_REF)
+ offset1 += mem_ref_offset (base1).low * BITS_PER_UNIT;
+ if (TREE_CODE (base2) == MEM_REF)
+ offset2 += mem_ref_offset (base2).low * BITS_PER_UNIT;
+ return ranges_overlap_p (offset1, max_size1, offset2, max_size2);
+ }
if (!ptr_derefs_may_alias_p (ptr1, ptr2))
return false;
/* Disambiguations that rely on strict aliasing rules follow. */
- if (!flag_strict_aliasing)
+ if (!flag_strict_aliasing || !tbaa_p)
return true;
+ if (TREE_CODE (base1) == MEM_REF)
+ ptrtype1 = TREE_TYPE (TREE_OPERAND (base1, 1));
+ else
+ ptrtype1 = TREE_TYPE (ptr1);
+ if (TREE_CODE (base2) == MEM_REF)
+ ptrtype2 = TREE_TYPE (TREE_OPERAND (base2, 1));
+ else
+ ptrtype2 = TREE_TYPE (ptr2);
+
/* If the alias set for a pointer access is zero all bets are off. */
if (base1_alias_set == -1)
- base1_alias_set = get_deref_alias_set (ptr1);
+ base1_alias_set = get_deref_alias_set (ptrtype1);
if (base1_alias_set == 0)
return true;
if (base2_alias_set == -1)
- base2_alias_set = get_deref_alias_set (ptr2);
+ base2_alias_set = get_deref_alias_set (ptrtype2);
if (base2_alias_set == 0)
return true;
/* If both references are through the same type, they do not alias
if the accesses do not overlap. This does extra disambiguation
for mixed/pointer accesses but requires strict aliasing. */
- if (same_type_for_tbaa (TREE_TYPE (TREE_TYPE (ptr1)),
- TREE_TYPE (TREE_TYPE (ptr2))) == 1)
+ if ((TREE_CODE (base1) != MEM_REF
+ || same_type_for_tbaa (TREE_TYPE (base1), TREE_TYPE (ptrtype1)) == 1)
+ && (TREE_CODE (base2) != MEM_REF
+ || same_type_for_tbaa (TREE_TYPE (base2), TREE_TYPE (ptrtype2)) == 1)
+ && same_type_for_tbaa (TREE_TYPE (ptrtype1),
+ TREE_TYPE (ptrtype2)) == 1)
return ranges_overlap_p (offset1, max_size1, offset2, max_size2);
/* Do type-based disambiguation. */
@@ -778,11 +854,15 @@ indirect_refs_may_alias_p (tree ref1, tree ptr1,
/* Do access-path based disambiguation. */
if (ref1 && ref2
&& handled_component_p (ref1)
- && handled_component_p (ref2))
- return aliasing_component_refs_p (ref1, TREE_TYPE (TREE_TYPE (ptr1)),
+ && handled_component_p (ref2)
+ && (TREE_CODE (base1) != MEM_REF
+ || same_type_for_tbaa (TREE_TYPE (base1), TREE_TYPE (ptrtype1)) == 1)
+ && (TREE_CODE (base2) != MEM_REF
+ || same_type_for_tbaa (TREE_TYPE (base2), TREE_TYPE (ptrtype2)) == 1))
+ return aliasing_component_refs_p (ref1, TREE_TYPE (ptrtype1),
ref1_alias_set, base1_alias_set,
offset1, max_size1,
- ref2, TREE_TYPE (TREE_TYPE (ptr2)),
+ ref2, TREE_TYPE (ptrtype2),
ref2_alias_set, base2_alias_set,
offset2, max_size2, false);
@@ -798,19 +878,20 @@ refs_may_alias_p_1 (ao_ref *ref1, ao_ref *ref2, bool tbaa_p)
HOST_WIDE_INT offset1 = 0, offset2 = 0;
HOST_WIDE_INT max_size1 = -1, max_size2 = -1;
bool var1_p, var2_p, ind1_p, ind2_p;
- alias_set_type set;
gcc_checking_assert ((!ref1->ref
|| TREE_CODE (ref1->ref) == SSA_NAME
|| DECL_P (ref1->ref)
|| handled_component_p (ref1->ref)
|| INDIRECT_REF_P (ref1->ref)
+ || TREE_CODE (ref1->ref) == MEM_REF
|| TREE_CODE (ref1->ref) == TARGET_MEM_REF)
&& (!ref2->ref
|| TREE_CODE (ref2->ref) == SSA_NAME
|| DECL_P (ref2->ref)
|| handled_component_p (ref2->ref)
|| INDIRECT_REF_P (ref2->ref)
+ || TREE_CODE (ref2->ref) == MEM_REF
|| TREE_CODE (ref2->ref) == TARGET_MEM_REF));
/* Decompose the references into their base objects and the access. */
@@ -851,8 +932,9 @@ refs_may_alias_p_1 (ao_ref *ref1, ao_ref *ref2, bool tbaa_p)
return decl_refs_may_alias_p (base1, offset1, max_size1,
base2, offset2, max_size2);
- ind1_p = INDIRECT_REF_P (base1);
- ind2_p = INDIRECT_REF_P (base2);
+ ind1_p = INDIRECT_REF_P (base1) || (TREE_CODE (base1) == MEM_REF);
+ ind2_p = INDIRECT_REF_P (base2) || (TREE_CODE (base2) == MEM_REF);
+
/* Canonicalize the pointer-vs-decl case. */
if (ind1_p && var2_p)
{
@@ -869,59 +951,6 @@ refs_may_alias_p_1 (ao_ref *ref1, ao_ref *ref2, bool tbaa_p)
ind2_p = true;
}
- /* If we are about to disambiguate pointer-vs-decl try harder to
- see must-aliases and give leeway to some invalid cases.
- This covers a pretty minimal set of cases only and does not
- when called from the RTL oracle. It handles cases like
-
- int i = 1;
- return *(float *)&i;
-
- and also fixes gfortran.dg/lto/pr40725. */
- if (var1_p && ind2_p
- && cfun
- && gimple_in_ssa_p (cfun)
- && TREE_CODE (TREE_OPERAND (base2, 0)) == SSA_NAME)
- {
- gimple def_stmt = SSA_NAME_DEF_STMT (TREE_OPERAND (base2, 0));
- while (is_gimple_assign (def_stmt)
- && (gimple_assign_rhs_code (def_stmt) == SSA_NAME
- || CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt))))
- {
- tree rhs = gimple_assign_rhs1 (def_stmt);
- HOST_WIDE_INT offset, size, max_size;
-
- /* Look through SSA name copies and pointer conversions. */
- if (TREE_CODE (rhs) == SSA_NAME
- && POINTER_TYPE_P (TREE_TYPE (rhs)))
- {
- def_stmt = SSA_NAME_DEF_STMT (rhs);
- continue;
- }
- if (TREE_CODE (rhs) != ADDR_EXPR)
- break;
-
- /* If the pointer is defined as an address based on a decl
- use plain offset disambiguation and ignore TBAA. */
- rhs = TREE_OPERAND (rhs, 0);
- rhs = get_ref_base_and_extent (rhs, &offset, &size, &max_size);
- if (SSA_VAR_P (rhs))
- {
- base2 = rhs;
- offset2 += offset;
- if (size != max_size
- || max_size == -1)
- max_size2 = -1;
- return decl_refs_may_alias_p (base1, offset1, max_size1,
- base2, offset2, max_size2);
- }
-
- /* Do not continue looking through &p->x to limit time
- complexity. */
- break;
- }
- }
-
/* First defer to TBAA if possible. */
if (tbaa_p
&& flag_strict_aliasing
@@ -937,21 +966,23 @@ refs_may_alias_p_1 (ao_ref *ref1, ao_ref *ref2, bool tbaa_p)
return true;
/* Dispatch to the pointer-vs-decl or pointer-vs-pointer disambiguators. */
- set = tbaa_p ? -1 : 0;
if (var1_p && ind2_p)
- return indirect_ref_may_alias_decl_p (ref2->ref, TREE_OPERAND (base2, 0),
+ return indirect_ref_may_alias_decl_p (ref2->ref, base2,
offset2, max_size2,
- ao_ref_alias_set (ref2), set,
+ ao_ref_alias_set (ref2), -1,
ref1->ref, base1,
offset1, max_size1,
- ao_ref_alias_set (ref1), set);
+ ao_ref_alias_set (ref1),
+ ao_ref_base_alias_set (ref1),
+ tbaa_p);
else if (ind1_p && ind2_p)
- return indirect_refs_may_alias_p (ref1->ref, TREE_OPERAND (base1, 0),
+ return indirect_refs_may_alias_p (ref1->ref, base1,
offset1, max_size1,
- ao_ref_alias_set (ref1), set,
- ref2->ref, TREE_OPERAND (base2, 0),
+ ao_ref_alias_set (ref1), -1,
+ ref2->ref, base2,
offset2, max_size2,
- ao_ref_alias_set (ref2), set);
+ ao_ref_alias_set (ref2), -1,
+ tbaa_p);
gcc_unreachable ();
}
@@ -1110,7 +1141,8 @@ ref_maybe_used_by_call_p_1 (gimple call, ao_ref *ref)
if (pt_solution_includes (gimple_call_use_set (call), base))
return true;
}
- else if (INDIRECT_REF_P (base)
+ else if ((INDIRECT_REF_P (base)
+ || TREE_CODE (base) == MEM_REF)
&& TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
{
struct ptr_info_def *pi = SSA_NAME_PTR_INFO (TREE_OPERAND (base, 0));
@@ -1281,7 +1313,8 @@ call_may_clobber_ref_p_1 (gimple call, ao_ref *ref)
if (DECL_P (base)
&& !TREE_STATIC (base))
return true;
- else if (INDIRECT_REF_P (base)
+ else if ((INDIRECT_REF_P (base)
+ || TREE_CODE (base) == MEM_REF)
&& TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME
&& (pi = SSA_NAME_PTR_INFO (TREE_OPERAND (base, 0))))
return pi->pt.anything || pi->pt.nonlocal;
@@ -1360,7 +1393,8 @@ call_may_clobber_ref_p_1 (gimple call, ao_ref *ref)
/* Check if the base variable is call-clobbered. */
if (DECL_P (base))
return pt_solution_includes (gimple_call_clobber_set (call), base);
- else if (INDIRECT_REF_P (base)
+ else if ((INDIRECT_REF_P (base)
+ || TREE_CODE (base) == MEM_REF)
&& TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
{
struct ptr_info_def *pi = SSA_NAME_PTR_INFO (TREE_OPERAND (base, 0));