this patch iplements new class ao_compare that is derived from operand_compare and adds a method to compare and hash ao_refs. This is used by ICF to enable more merging. Comparsion is done as follows 1) Verify that the memory access will happen at the same address and will have same size. For constant addresses this is done by comparing ao_ref_base and offset/size For varable accesses it uses operand_equal_p but with OEP_ADDRESS (that does not match TBAA metadata) and then operand_equal_p on type size. 2) Compare alignments. I use get_object_alignment_1 like ipa-icf did before revamp to operand_equal_p in gcc 9. I noticed that return value is bitodd so added a comment 3) Match MR_DEPENDENCE_CLIQUE At this point the memory refrences are same except for TBAA information. We continue by checking 4) ref and base alias sets. Now if lto streaming is going to happen instead of comparing alias sets themselves we compare alias_ptr_types (the patch depends on the ao_ref_alias_ptr_tyep and ao_ref_base_alias_ptr_type acessors I sent yesterday) 5) See if accesses are view converted. If they are we are done since access path is not present 6) Compare the part of access path relevant for TBAA. I recall FRE relies on the fact that if base and ref types are same the access path is, but I do not thing this is 100% reliable especially with LTO alias sets. The access path comparsion logic is also useful for modref (for next stage1). Tracking the access paths improves quite noticeably disambiguation in C++ code by being able to distinquish different fields of same type within a struct. I had the comparsion logic in my tree for some time and it seems to work quite well. During cc1plus build we have some cases where we find mismatch after matching the base/ref alias sets. These are due to failed type merging: access path oracle in LTO uses TYPE_MAIN_VARIANTs. I implemented relatively basic hashing using base and offset. gcc/ChangeLog: * ipa-icf-gimple.c: Include tree-ssa-alias-compare.h. (find_checker::func_checker): Initialize m_tbaa. (func_checker::hash_operand): Use hash_ao_ref for memory accesses. (func_checker::compare_operand): Use compare_ao_refs for memory accesses. (func_checker::cmopare_gimple_assign): Do not check LHS types of memory stores. * ipa-icf-gimple.h (func_checker): Derive from ao_compare; add m_tbaa. * ipa-icf.c: Include tree-ssa-alias-compare.h. (sem_function::equals_private): Update call of func_checker::func_checker. * ipa-utils.h (lto_streaming_expected_p): New inline predicate. * tree-ssa-alias-compare.h: New file. * tree-ssa-alias.c: Include tree-ssa-alias-compare.h and bultins.h (view_converted_memref_p): New function. (types_equal_for_same_type_for_tbaa_p): New function. (ao_ref_alias_ptr_type, ao_ref_base_alias_ptr_type): New functions. (ao_compare::compare_ao_refs): New member function. (ao_compare::hash_ao_ref): New function * tree-ssa-alias.h (ao_ref_base_alias_ptr_type, ao_ref_alias_ptr_type): Declare. gcc/testsuite/ChangeLog: * c-c++-common/Wstringop-overflow-2.c: Disable ICF. * g++.dg/warn/Warray-bounds-8.C: Disable ICF.
207 lines
7.5 KiB
C++
207 lines
7.5 KiB
C++
/* Tree based alias analysis and alias oracle.
|
|
Copyright (C) 2008-2020 Free Software Foundation, Inc.
|
|
Contributed by Richard Guenther <rguenther@suse.de>
|
|
|
|
This file is part of GCC.
|
|
|
|
GCC is free software; you can redistribute it and/or modify
|
|
under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
GCC is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with GCC; see the file COPYING3. If not see
|
|
<http://www.gnu.org/licenses/>. */
|
|
|
|
#ifndef TREE_SSA_ALIAS_H
|
|
#define TREE_SSA_ALIAS_H
|
|
|
|
/* The points-to solution.
|
|
|
|
The points-to solution is a union of pt_vars and the abstract
|
|
sets specified by the flags. */
|
|
struct GTY(()) pt_solution
|
|
{
|
|
/* Nonzero if points-to analysis couldn't determine where this pointer
|
|
is pointing to. */
|
|
unsigned int anything : 1;
|
|
|
|
/* Nonzero if the points-to set includes any global memory. Note that
|
|
even if this is zero pt_vars can still include global variables. */
|
|
unsigned int nonlocal : 1;
|
|
|
|
/* Nonzero if the points-to set includes the local escaped solution by
|
|
reference. */
|
|
unsigned int escaped : 1;
|
|
|
|
/* Nonzero if the points-to set includes the IPA escaped solution by
|
|
reference. */
|
|
unsigned int ipa_escaped : 1;
|
|
|
|
/* Nonzero if the points-to set includes 'nothing', the points-to set
|
|
includes memory at address NULL. */
|
|
unsigned int null : 1;
|
|
|
|
/* Nonzero if the vars bitmap includes a variable included in 'nonlocal'. */
|
|
unsigned int vars_contains_nonlocal : 1;
|
|
/* Nonzero if the vars bitmap includes a variable included in 'escaped'. */
|
|
unsigned int vars_contains_escaped : 1;
|
|
/* Nonzero if the vars bitmap includes a anonymous heap variable that
|
|
escaped the function and thus became global. */
|
|
unsigned int vars_contains_escaped_heap : 1;
|
|
/* Nonzero if the vars bitmap includes a anonymous variable used to
|
|
represent storage pointed to by a restrict qualified pointer. */
|
|
unsigned int vars_contains_restrict : 1;
|
|
/* Nonzero if the vars bitmap includes an interposable variable. */
|
|
unsigned int vars_contains_interposable : 1;
|
|
|
|
/* Set of variables that this pointer may point to. */
|
|
bitmap vars;
|
|
};
|
|
|
|
|
|
/* Simplified and cached information about a memory reference tree.
|
|
Used by the alias-oracle internally and externally in alternate
|
|
interfaces. */
|
|
class ao_ref
|
|
{
|
|
public:
|
|
/* The original full memory reference tree or NULL_TREE if that is
|
|
not available. */
|
|
tree ref;
|
|
|
|
/* The following fields are the decomposed reference as returned
|
|
by get_ref_base_and_extent. */
|
|
/* The base object of the memory reference or NULL_TREE if all of
|
|
the following fields are not yet computed. */
|
|
tree base;
|
|
/* The offset relative to the base. */
|
|
poly_int64 offset;
|
|
/* The size of the access. */
|
|
poly_int64 size;
|
|
/* The maximum possible extent of the access or -1 if unconstrained. */
|
|
poly_int64 max_size;
|
|
|
|
/* The alias set of the access or -1 if not yet computed. */
|
|
alias_set_type ref_alias_set;
|
|
|
|
/* The alias set of the base object or -1 if not yet computed. */
|
|
alias_set_type base_alias_set;
|
|
|
|
/* Whether the memory is considered a volatile access. */
|
|
bool volatile_p;
|
|
|
|
bool max_size_known_p () const;
|
|
};
|
|
|
|
/* Return true if the maximum size is known, rather than the special -1
|
|
marker. */
|
|
|
|
inline bool
|
|
ao_ref::max_size_known_p () const
|
|
{
|
|
return known_size_p (max_size);
|
|
}
|
|
|
|
/* In tree-ssa-alias.c */
|
|
extern void ao_ref_init (ao_ref *, tree);
|
|
extern void ao_ref_init_from_ptr_and_size (ao_ref *, tree, tree);
|
|
extern tree ao_ref_base (ao_ref *);
|
|
extern alias_set_type ao_ref_alias_set (ao_ref *);
|
|
extern alias_set_type ao_ref_base_alias_set (ao_ref *);
|
|
extern tree ao_ref_alias_ptr_type (ao_ref *);
|
|
extern tree ao_ref_base_alias_ptr_type (ao_ref *);
|
|
extern bool ptr_deref_may_alias_global_p (tree);
|
|
extern bool ptr_derefs_may_alias_p (tree, tree);
|
|
extern bool ptrs_compare_unequal (tree, tree);
|
|
extern bool ref_may_alias_global_p (tree);
|
|
extern bool ref_may_alias_global_p (ao_ref *);
|
|
extern bool refs_may_alias_p (tree, tree, bool = true);
|
|
extern bool refs_may_alias_p_1 (ao_ref *, ao_ref *, bool);
|
|
extern bool refs_anti_dependent_p (tree, tree);
|
|
extern bool refs_output_dependent_p (tree, tree);
|
|
extern bool ref_maybe_used_by_stmt_p (gimple *, tree, bool = true);
|
|
extern bool ref_maybe_used_by_stmt_p (gimple *, ao_ref *, bool = true);
|
|
extern bool stmt_may_clobber_global_p (gimple *);
|
|
extern bool stmt_may_clobber_ref_p (gimple *, tree, bool = true);
|
|
extern bool stmt_may_clobber_ref_p_1 (gimple *, ao_ref *, bool = true);
|
|
extern bool call_may_clobber_ref_p (gcall *, tree, bool = true);
|
|
extern bool call_may_clobber_ref_p_1 (gcall *, ao_ref *, bool = true);
|
|
extern bool stmt_kills_ref_p (gimple *, tree);
|
|
extern bool stmt_kills_ref_p (gimple *, ao_ref *);
|
|
enum translate_flags
|
|
{ TR_TRANSLATE, TR_VALUEIZE_AND_DISAMBIGUATE, TR_DISAMBIGUATE };
|
|
extern tree get_continuation_for_phi (gimple *, ao_ref *, bool,
|
|
unsigned int &, bitmap *, bool,
|
|
void *(*)(ao_ref *, tree, void *,
|
|
translate_flags *),
|
|
void *, translate_flags
|
|
= TR_VALUEIZE_AND_DISAMBIGUATE);
|
|
extern void *walk_non_aliased_vuses (ao_ref *, tree, bool,
|
|
void *(*)(ao_ref *, tree, void *),
|
|
void *(*)(ao_ref *, tree, void *,
|
|
translate_flags *),
|
|
tree (*)(tree), unsigned &, void *);
|
|
extern int walk_aliased_vdefs (ao_ref *, tree,
|
|
bool (*)(ao_ref *, tree, void *),
|
|
void *, bitmap *,
|
|
bool *function_entry_reached = NULL,
|
|
unsigned int limit = 0);
|
|
extern void dump_alias_info (FILE *);
|
|
extern void debug_alias_info (void);
|
|
extern void dump_points_to_solution (FILE *, struct pt_solution *);
|
|
extern void debug (pt_solution &ref);
|
|
extern void debug (pt_solution *ptr);
|
|
extern void dump_points_to_info_for (FILE *, tree);
|
|
extern void debug_points_to_info_for (tree);
|
|
extern void dump_alias_stats (FILE *);
|
|
|
|
|
|
/* In tree-ssa-structalias.c */
|
|
extern unsigned int compute_may_aliases (void);
|
|
extern bool pt_solution_empty_p (const pt_solution *);
|
|
extern bool pt_solution_singleton_or_null_p (struct pt_solution *, unsigned *);
|
|
extern bool pt_solution_includes_global (struct pt_solution *);
|
|
extern bool pt_solution_includes (struct pt_solution *, const_tree);
|
|
extern bool pt_solutions_intersect (struct pt_solution *, struct pt_solution *);
|
|
extern void pt_solution_reset (struct pt_solution *);
|
|
extern void pt_solution_set (struct pt_solution *, bitmap, bool);
|
|
extern void pt_solution_set_var (struct pt_solution *, tree);
|
|
|
|
extern void dump_pta_stats (FILE *);
|
|
|
|
extern GTY(()) struct pt_solution ipa_escaped_pt;
|
|
|
|
/* Return true, if the two ranges [POS1, SIZE1] and [POS2, SIZE2]
|
|
overlap. SIZE1 and/or SIZE2 can be (unsigned)-1 in which case the
|
|
range is open-ended. Otherwise return false. */
|
|
|
|
static inline bool
|
|
ranges_overlap_p (HOST_WIDE_INT pos1,
|
|
unsigned HOST_WIDE_INT size1,
|
|
HOST_WIDE_INT pos2,
|
|
unsigned HOST_WIDE_INT size2)
|
|
{
|
|
if (size1 == 0 || size2 == 0)
|
|
return false;
|
|
if (pos1 >= pos2
|
|
&& (size2 == (unsigned HOST_WIDE_INT)-1
|
|
|| pos1 < (pos2 + (HOST_WIDE_INT) size2)))
|
|
return true;
|
|
if (pos2 >= pos1
|
|
&& (size1 == (unsigned HOST_WIDE_INT)-1
|
|
|| pos2 < (pos1 + (HOST_WIDE_INT) size1)))
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
#endif /* TREE_SSA_ALIAS_H */
|