138fd1498Szrj /* Alias analysis for trees.
238fd1498Szrj Copyright (C) 2004-2018 Free Software Foundation, Inc.
338fd1498Szrj Contributed by Diego Novillo <dnovillo@redhat.com>
438fd1498Szrj
538fd1498Szrj This file is part of GCC.
638fd1498Szrj
738fd1498Szrj GCC is free software; you can redistribute it and/or modify
838fd1498Szrj it under the terms of the GNU General Public License as published by
938fd1498Szrj the Free Software Foundation; either version 3, or (at your option)
1038fd1498Szrj any later version.
1138fd1498Szrj
1238fd1498Szrj GCC is distributed in the hope that it will be useful,
1338fd1498Szrj but WITHOUT ANY WARRANTY; without even the implied warranty of
1438fd1498Szrj MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1538fd1498Szrj GNU General Public License for more details.
1638fd1498Szrj
1738fd1498Szrj You should have received a copy of the GNU General Public License
1838fd1498Szrj along with GCC; see the file COPYING3. If not see
1938fd1498Szrj <http://www.gnu.org/licenses/>. */
2038fd1498Szrj
2138fd1498Szrj #include "config.h"
2238fd1498Szrj #include "system.h"
2338fd1498Szrj #include "coretypes.h"
2438fd1498Szrj #include "backend.h"
2538fd1498Szrj #include "target.h"
2638fd1498Szrj #include "rtl.h"
2738fd1498Szrj #include "tree.h"
2838fd1498Szrj #include "gimple.h"
2938fd1498Szrj #include "timevar.h" /* for TV_ALIAS_STMT_WALK */
3038fd1498Szrj #include "ssa.h"
3138fd1498Szrj #include "cgraph.h"
3238fd1498Szrj #include "tree-pretty-print.h"
3338fd1498Szrj #include "alias.h"
3438fd1498Szrj #include "fold-const.h"
3538fd1498Szrj #include "langhooks.h"
3638fd1498Szrj #include "dumpfile.h"
3738fd1498Szrj #include "tree-eh.h"
3838fd1498Szrj #include "tree-dfa.h"
3938fd1498Szrj #include "ipa-reference.h"
4038fd1498Szrj #include "varasm.h"
4138fd1498Szrj
4238fd1498Szrj /* Broad overview of how alias analysis on gimple works:
4338fd1498Szrj
4438fd1498Szrj Statements clobbering or using memory are linked through the
4538fd1498Szrj virtual operand factored use-def chain. The virtual operand
4638fd1498Szrj is unique per function, its symbol is accessible via gimple_vop (cfun).
4738fd1498Szrj Virtual operands are used for efficiently walking memory statements
4838fd1498Szrj in the gimple IL and are useful for things like value-numbering as
4938fd1498Szrj a generation count for memory references.
5038fd1498Szrj
5138fd1498Szrj SSA_NAME pointers may have associated points-to information
5238fd1498Szrj accessible via the SSA_NAME_PTR_INFO macro. Flow-insensitive
5338fd1498Szrj points-to information is (re-)computed by the TODO_rebuild_alias
5438fd1498Szrj pass manager todo. Points-to information is also used for more
5538fd1498Szrj precise tracking of call-clobbered and call-used variables and
5638fd1498Szrj related disambiguations.
5738fd1498Szrj
5838fd1498Szrj This file contains functions for disambiguating memory references,
5938fd1498Szrj the so called alias-oracle and tools for walking of the gimple IL.
6038fd1498Szrj
6138fd1498Szrj The main alias-oracle entry-points are
6238fd1498Szrj
6338fd1498Szrj bool stmt_may_clobber_ref_p (gimple *, tree)
6438fd1498Szrj
6538fd1498Szrj This function queries if a statement may invalidate (parts of)
6638fd1498Szrj the memory designated by the reference tree argument.
6738fd1498Szrj
6838fd1498Szrj bool ref_maybe_used_by_stmt_p (gimple *, tree)
6938fd1498Szrj
7038fd1498Szrj This function queries if a statement may need (parts of) the
7138fd1498Szrj memory designated by the reference tree argument.
7238fd1498Szrj
7338fd1498Szrj There are variants of these functions that only handle the call
7438fd1498Szrj part of a statement, call_may_clobber_ref_p and ref_maybe_used_by_call_p.
7538fd1498Szrj Note that these do not disambiguate against a possible call lhs.
7638fd1498Szrj
7738fd1498Szrj bool refs_may_alias_p (tree, tree)
7838fd1498Szrj
7938fd1498Szrj This function tries to disambiguate two reference trees.
8038fd1498Szrj
8138fd1498Szrj bool ptr_deref_may_alias_global_p (tree)
8238fd1498Szrj
8338fd1498Szrj This function queries if dereferencing a pointer variable may
8438fd1498Szrj alias global memory.
8538fd1498Szrj
8638fd1498Szrj More low-level disambiguators are available and documented in
8738fd1498Szrj this file. Low-level disambiguators dealing with points-to
8838fd1498Szrj information are in tree-ssa-structalias.c. */
8938fd1498Szrj
9038fd1498Szrj
9138fd1498Szrj /* Query statistics for the different low-level disambiguators.
9238fd1498Szrj A high-level query may trigger multiple of them. */
9338fd1498Szrj
9438fd1498Szrj static struct {
9538fd1498Szrj unsigned HOST_WIDE_INT refs_may_alias_p_may_alias;
9638fd1498Szrj unsigned HOST_WIDE_INT refs_may_alias_p_no_alias;
9738fd1498Szrj unsigned HOST_WIDE_INT ref_maybe_used_by_call_p_may_alias;
9838fd1498Szrj unsigned HOST_WIDE_INT ref_maybe_used_by_call_p_no_alias;
9938fd1498Szrj unsigned HOST_WIDE_INT call_may_clobber_ref_p_may_alias;
10038fd1498Szrj unsigned HOST_WIDE_INT call_may_clobber_ref_p_no_alias;
10138fd1498Szrj } alias_stats;
10238fd1498Szrj
10338fd1498Szrj void
dump_alias_stats(FILE * s)10438fd1498Szrj dump_alias_stats (FILE *s)
10538fd1498Szrj {
10638fd1498Szrj fprintf (s, "\nAlias oracle query stats:\n");
10738fd1498Szrj fprintf (s, " refs_may_alias_p: "
10838fd1498Szrj HOST_WIDE_INT_PRINT_DEC" disambiguations, "
10938fd1498Szrj HOST_WIDE_INT_PRINT_DEC" queries\n",
11038fd1498Szrj alias_stats.refs_may_alias_p_no_alias,
11138fd1498Szrj alias_stats.refs_may_alias_p_no_alias
11238fd1498Szrj + alias_stats.refs_may_alias_p_may_alias);
11338fd1498Szrj fprintf (s, " ref_maybe_used_by_call_p: "
11438fd1498Szrj HOST_WIDE_INT_PRINT_DEC" disambiguations, "
11538fd1498Szrj HOST_WIDE_INT_PRINT_DEC" queries\n",
11638fd1498Szrj alias_stats.ref_maybe_used_by_call_p_no_alias,
11738fd1498Szrj alias_stats.refs_may_alias_p_no_alias
11838fd1498Szrj + alias_stats.ref_maybe_used_by_call_p_may_alias);
11938fd1498Szrj fprintf (s, " call_may_clobber_ref_p: "
12038fd1498Szrj HOST_WIDE_INT_PRINT_DEC" disambiguations, "
12138fd1498Szrj HOST_WIDE_INT_PRINT_DEC" queries\n",
12238fd1498Szrj alias_stats.call_may_clobber_ref_p_no_alias,
12338fd1498Szrj alias_stats.call_may_clobber_ref_p_no_alias
12438fd1498Szrj + alias_stats.call_may_clobber_ref_p_may_alias);
12538fd1498Szrj dump_alias_stats_in_alias_c (s);
12638fd1498Szrj }
12738fd1498Szrj
12838fd1498Szrj
12938fd1498Szrj /* Return true, if dereferencing PTR may alias with a global variable. */
13038fd1498Szrj
13138fd1498Szrj bool
ptr_deref_may_alias_global_p(tree ptr)13238fd1498Szrj ptr_deref_may_alias_global_p (tree ptr)
13338fd1498Szrj {
13438fd1498Szrj struct ptr_info_def *pi;
13538fd1498Szrj
13638fd1498Szrj /* If we end up with a pointer constant here that may point
13738fd1498Szrj to global memory. */
13838fd1498Szrj if (TREE_CODE (ptr) != SSA_NAME)
13938fd1498Szrj return true;
14038fd1498Szrj
14138fd1498Szrj pi = SSA_NAME_PTR_INFO (ptr);
14238fd1498Szrj
14338fd1498Szrj /* If we do not have points-to information for this variable,
14438fd1498Szrj we have to punt. */
14538fd1498Szrj if (!pi)
14638fd1498Szrj return true;
14738fd1498Szrj
14838fd1498Szrj /* ??? This does not use TBAA to prune globals ptr may not access. */
14938fd1498Szrj return pt_solution_includes_global (&pi->pt);
15038fd1498Szrj }
15138fd1498Szrj
15238fd1498Szrj /* Return true if dereferencing PTR may alias DECL.
15338fd1498Szrj The caller is responsible for applying TBAA to see if PTR
15438fd1498Szrj may access DECL at all. */
15538fd1498Szrj
15638fd1498Szrj static bool
ptr_deref_may_alias_decl_p(tree ptr,tree decl)15738fd1498Szrj ptr_deref_may_alias_decl_p (tree ptr, tree decl)
15838fd1498Szrj {
15938fd1498Szrj struct ptr_info_def *pi;
16038fd1498Szrj
16138fd1498Szrj /* Conversions are irrelevant for points-to information and
16238fd1498Szrj data-dependence analysis can feed us those. */
16338fd1498Szrj STRIP_NOPS (ptr);
16438fd1498Szrj
16538fd1498Szrj /* Anything we do not explicilty handle aliases. */
16638fd1498Szrj if ((TREE_CODE (ptr) != SSA_NAME
16738fd1498Szrj && TREE_CODE (ptr) != ADDR_EXPR
16838fd1498Szrj && TREE_CODE (ptr) != POINTER_PLUS_EXPR)
16938fd1498Szrj || !POINTER_TYPE_P (TREE_TYPE (ptr))
17038fd1498Szrj || (!VAR_P (decl)
17138fd1498Szrj && TREE_CODE (decl) != PARM_DECL
17238fd1498Szrj && TREE_CODE (decl) != RESULT_DECL))
17338fd1498Szrj return true;
17438fd1498Szrj
17538fd1498Szrj /* Disregard pointer offsetting. */
17638fd1498Szrj if (TREE_CODE (ptr) == POINTER_PLUS_EXPR)
17738fd1498Szrj {
17838fd1498Szrj do
17938fd1498Szrj {
18038fd1498Szrj ptr = TREE_OPERAND (ptr, 0);
18138fd1498Szrj }
18238fd1498Szrj while (TREE_CODE (ptr) == POINTER_PLUS_EXPR);
18338fd1498Szrj return ptr_deref_may_alias_decl_p (ptr, decl);
18438fd1498Szrj }
18538fd1498Szrj
18638fd1498Szrj /* ADDR_EXPR pointers either just offset another pointer or directly
18738fd1498Szrj specify the pointed-to set. */
18838fd1498Szrj if (TREE_CODE (ptr) == ADDR_EXPR)
18938fd1498Szrj {
19038fd1498Szrj tree base = get_base_address (TREE_OPERAND (ptr, 0));
19138fd1498Szrj if (base
19238fd1498Szrj && (TREE_CODE (base) == MEM_REF
19338fd1498Szrj || TREE_CODE (base) == TARGET_MEM_REF))
19438fd1498Szrj ptr = TREE_OPERAND (base, 0);
19538fd1498Szrj else if (base
19638fd1498Szrj && DECL_P (base))
19738fd1498Szrj return compare_base_decls (base, decl) != 0;
19838fd1498Szrj else if (base
19938fd1498Szrj && CONSTANT_CLASS_P (base))
20038fd1498Szrj return false;
20138fd1498Szrj else
20238fd1498Szrj return true;
20338fd1498Szrj }
20438fd1498Szrj
20538fd1498Szrj /* Non-aliased variables can not be pointed to. */
20638fd1498Szrj if (!may_be_aliased (decl))
20738fd1498Szrj return false;
20838fd1498Szrj
20938fd1498Szrj /* If we do not have useful points-to information for this pointer
21038fd1498Szrj we cannot disambiguate anything else. */
21138fd1498Szrj pi = SSA_NAME_PTR_INFO (ptr);
21238fd1498Szrj if (!pi)
21338fd1498Szrj return true;
21438fd1498Szrj
21538fd1498Szrj return pt_solution_includes (&pi->pt, decl);
21638fd1498Szrj }
21738fd1498Szrj
21838fd1498Szrj /* Return true if dereferenced PTR1 and PTR2 may alias.
21938fd1498Szrj The caller is responsible for applying TBAA to see if accesses
22038fd1498Szrj through PTR1 and PTR2 may conflict at all. */
22138fd1498Szrj
22238fd1498Szrj bool
ptr_derefs_may_alias_p(tree ptr1,tree ptr2)22338fd1498Szrj ptr_derefs_may_alias_p (tree ptr1, tree ptr2)
22438fd1498Szrj {
22538fd1498Szrj struct ptr_info_def *pi1, *pi2;
22638fd1498Szrj
22738fd1498Szrj /* Conversions are irrelevant for points-to information and
22838fd1498Szrj data-dependence analysis can feed us those. */
22938fd1498Szrj STRIP_NOPS (ptr1);
23038fd1498Szrj STRIP_NOPS (ptr2);
23138fd1498Szrj
23238fd1498Szrj /* Disregard pointer offsetting. */
23338fd1498Szrj if (TREE_CODE (ptr1) == POINTER_PLUS_EXPR)
23438fd1498Szrj {
23538fd1498Szrj do
23638fd1498Szrj {
23738fd1498Szrj ptr1 = TREE_OPERAND (ptr1, 0);
23838fd1498Szrj }
23938fd1498Szrj while (TREE_CODE (ptr1) == POINTER_PLUS_EXPR);
24038fd1498Szrj return ptr_derefs_may_alias_p (ptr1, ptr2);
24138fd1498Szrj }
24238fd1498Szrj if (TREE_CODE (ptr2) == POINTER_PLUS_EXPR)
24338fd1498Szrj {
24438fd1498Szrj do
24538fd1498Szrj {
24638fd1498Szrj ptr2 = TREE_OPERAND (ptr2, 0);
24738fd1498Szrj }
24838fd1498Szrj while (TREE_CODE (ptr2) == POINTER_PLUS_EXPR);
24938fd1498Szrj return ptr_derefs_may_alias_p (ptr1, ptr2);
25038fd1498Szrj }
25138fd1498Szrj
25238fd1498Szrj /* ADDR_EXPR pointers either just offset another pointer or directly
25338fd1498Szrj specify the pointed-to set. */
25438fd1498Szrj if (TREE_CODE (ptr1) == ADDR_EXPR)
25538fd1498Szrj {
25638fd1498Szrj tree base = get_base_address (TREE_OPERAND (ptr1, 0));
25738fd1498Szrj if (base
25838fd1498Szrj && (TREE_CODE (base) == MEM_REF
25938fd1498Szrj || TREE_CODE (base) == TARGET_MEM_REF))
26038fd1498Szrj return ptr_derefs_may_alias_p (TREE_OPERAND (base, 0), ptr2);
26138fd1498Szrj else if (base
26238fd1498Szrj && DECL_P (base))
26338fd1498Szrj return ptr_deref_may_alias_decl_p (ptr2, base);
26438fd1498Szrj else
26538fd1498Szrj return true;
26638fd1498Szrj }
26738fd1498Szrj if (TREE_CODE (ptr2) == ADDR_EXPR)
26838fd1498Szrj {
26938fd1498Szrj tree base = get_base_address (TREE_OPERAND (ptr2, 0));
27038fd1498Szrj if (base
27138fd1498Szrj && (TREE_CODE (base) == MEM_REF
27238fd1498Szrj || TREE_CODE (base) == TARGET_MEM_REF))
27338fd1498Szrj return ptr_derefs_may_alias_p (ptr1, TREE_OPERAND (base, 0));
27438fd1498Szrj else if (base
27538fd1498Szrj && DECL_P (base))
27638fd1498Szrj return ptr_deref_may_alias_decl_p (ptr1, base);
27738fd1498Szrj else
27838fd1498Szrj return true;
27938fd1498Szrj }
28038fd1498Szrj
28138fd1498Szrj /* From here we require SSA name pointers. Anything else aliases. */
28238fd1498Szrj if (TREE_CODE (ptr1) != SSA_NAME
28338fd1498Szrj || TREE_CODE (ptr2) != SSA_NAME
28438fd1498Szrj || !POINTER_TYPE_P (TREE_TYPE (ptr1))
28538fd1498Szrj || !POINTER_TYPE_P (TREE_TYPE (ptr2)))
28638fd1498Szrj return true;
28738fd1498Szrj
28838fd1498Szrj /* We may end up with two empty points-to solutions for two same pointers.
28938fd1498Szrj In this case we still want to say both pointers alias, so shortcut
29038fd1498Szrj that here. */
29138fd1498Szrj if (ptr1 == ptr2)
29238fd1498Szrj return true;
29338fd1498Szrj
29438fd1498Szrj /* If we do not have useful points-to information for either pointer
29538fd1498Szrj we cannot disambiguate anything else. */
29638fd1498Szrj pi1 = SSA_NAME_PTR_INFO (ptr1);
29738fd1498Szrj pi2 = SSA_NAME_PTR_INFO (ptr2);
29838fd1498Szrj if (!pi1 || !pi2)
29938fd1498Szrj return true;
30038fd1498Szrj
30138fd1498Szrj /* ??? This does not use TBAA to prune decls from the intersection
30238fd1498Szrj that not both pointers may access. */
30338fd1498Szrj return pt_solutions_intersect (&pi1->pt, &pi2->pt);
30438fd1498Szrj }
30538fd1498Szrj
30638fd1498Szrj /* Return true if dereferencing PTR may alias *REF.
30738fd1498Szrj The caller is responsible for applying TBAA to see if PTR
30838fd1498Szrj may access *REF at all. */
30938fd1498Szrj
31038fd1498Szrj static bool
ptr_deref_may_alias_ref_p_1(tree ptr,ao_ref * ref)31138fd1498Szrj ptr_deref_may_alias_ref_p_1 (tree ptr, ao_ref *ref)
31238fd1498Szrj {
31338fd1498Szrj tree base = ao_ref_base (ref);
31438fd1498Szrj
31538fd1498Szrj if (TREE_CODE (base) == MEM_REF
31638fd1498Szrj || TREE_CODE (base) == TARGET_MEM_REF)
31738fd1498Szrj return ptr_derefs_may_alias_p (ptr, TREE_OPERAND (base, 0));
31838fd1498Szrj else if (DECL_P (base))
31938fd1498Szrj return ptr_deref_may_alias_decl_p (ptr, base);
32038fd1498Szrj
32138fd1498Szrj return true;
32238fd1498Szrj }
32338fd1498Szrj
32438fd1498Szrj /* Returns true if PTR1 and PTR2 compare unequal because of points-to. */
32538fd1498Szrj
32638fd1498Szrj bool
ptrs_compare_unequal(tree ptr1,tree ptr2)32738fd1498Szrj ptrs_compare_unequal (tree ptr1, tree ptr2)
32838fd1498Szrj {
32938fd1498Szrj /* First resolve the pointers down to a SSA name pointer base or
33038fd1498Szrj a VAR_DECL, PARM_DECL or RESULT_DECL. This explicitely does
33138fd1498Szrj not yet try to handle LABEL_DECLs, FUNCTION_DECLs, CONST_DECLs
33238fd1498Szrj or STRING_CSTs which needs points-to adjustments to track them
33338fd1498Szrj in the points-to sets. */
33438fd1498Szrj tree obj1 = NULL_TREE;
33538fd1498Szrj tree obj2 = NULL_TREE;
33638fd1498Szrj if (TREE_CODE (ptr1) == ADDR_EXPR)
33738fd1498Szrj {
33838fd1498Szrj tree tem = get_base_address (TREE_OPERAND (ptr1, 0));
33938fd1498Szrj if (! tem)
34038fd1498Szrj return false;
34138fd1498Szrj if (VAR_P (tem)
34238fd1498Szrj || TREE_CODE (tem) == PARM_DECL
34338fd1498Szrj || TREE_CODE (tem) == RESULT_DECL)
34438fd1498Szrj obj1 = tem;
34538fd1498Szrj else if (TREE_CODE (tem) == MEM_REF)
34638fd1498Szrj ptr1 = TREE_OPERAND (tem, 0);
34738fd1498Szrj }
34838fd1498Szrj if (TREE_CODE (ptr2) == ADDR_EXPR)
34938fd1498Szrj {
35038fd1498Szrj tree tem = get_base_address (TREE_OPERAND (ptr2, 0));
35138fd1498Szrj if (! tem)
35238fd1498Szrj return false;
35338fd1498Szrj if (VAR_P (tem)
35438fd1498Szrj || TREE_CODE (tem) == PARM_DECL
35538fd1498Szrj || TREE_CODE (tem) == RESULT_DECL)
35638fd1498Szrj obj2 = tem;
35738fd1498Szrj else if (TREE_CODE (tem) == MEM_REF)
35838fd1498Szrj ptr2 = TREE_OPERAND (tem, 0);
35938fd1498Szrj }
36038fd1498Szrj
36138fd1498Szrj /* Canonicalize ptr vs. object. */
36238fd1498Szrj if (TREE_CODE (ptr1) == SSA_NAME && obj2)
36338fd1498Szrj {
36438fd1498Szrj std::swap (ptr1, ptr2);
36538fd1498Szrj std::swap (obj1, obj2);
36638fd1498Szrj }
36738fd1498Szrj
36838fd1498Szrj if (obj1 && obj2)
36938fd1498Szrj /* Other code handles this correctly, no need to duplicate it here. */;
37038fd1498Szrj else if (obj1 && TREE_CODE (ptr2) == SSA_NAME)
37138fd1498Szrj {
37238fd1498Szrj struct ptr_info_def *pi = SSA_NAME_PTR_INFO (ptr2);
37338fd1498Szrj /* We may not use restrict to optimize pointer comparisons.
37438fd1498Szrj See PR71062. So we have to assume that restrict-pointed-to
37538fd1498Szrj may be in fact obj1. */
37638fd1498Szrj if (!pi
37738fd1498Szrj || pi->pt.vars_contains_restrict
37838fd1498Szrj || pi->pt.vars_contains_interposable)
37938fd1498Szrj return false;
38038fd1498Szrj if (VAR_P (obj1)
38138fd1498Szrj && (TREE_STATIC (obj1) || DECL_EXTERNAL (obj1)))
38238fd1498Szrj {
38338fd1498Szrj varpool_node *node = varpool_node::get (obj1);
38438fd1498Szrj /* If obj1 may bind to NULL give up (see below). */
38538fd1498Szrj if (! node
38638fd1498Szrj || ! node->nonzero_address ()
38738fd1498Szrj || ! decl_binds_to_current_def_p (obj1))
38838fd1498Szrj return false;
38938fd1498Szrj }
39038fd1498Szrj return !pt_solution_includes (&pi->pt, obj1);
39138fd1498Szrj }
39238fd1498Szrj
39338fd1498Szrj /* ??? We'd like to handle ptr1 != NULL and ptr1 != ptr2
39438fd1498Szrj but those require pt.null to be conservatively correct. */
39538fd1498Szrj
39638fd1498Szrj return false;
39738fd1498Szrj }
39838fd1498Szrj
39938fd1498Szrj /* Returns whether reference REF to BASE may refer to global memory. */
40038fd1498Szrj
40138fd1498Szrj static bool
ref_may_alias_global_p_1(tree base)40238fd1498Szrj ref_may_alias_global_p_1 (tree base)
40338fd1498Szrj {
40438fd1498Szrj if (DECL_P (base))
40538fd1498Szrj return is_global_var (base);
40638fd1498Szrj else if (TREE_CODE (base) == MEM_REF
40738fd1498Szrj || TREE_CODE (base) == TARGET_MEM_REF)
40838fd1498Szrj return ptr_deref_may_alias_global_p (TREE_OPERAND (base, 0));
40938fd1498Szrj return true;
41038fd1498Szrj }
41138fd1498Szrj
41238fd1498Szrj bool
ref_may_alias_global_p(ao_ref * ref)41338fd1498Szrj ref_may_alias_global_p (ao_ref *ref)
41438fd1498Szrj {
41538fd1498Szrj tree base = ao_ref_base (ref);
41638fd1498Szrj return ref_may_alias_global_p_1 (base);
41738fd1498Szrj }
41838fd1498Szrj
41938fd1498Szrj bool
ref_may_alias_global_p(tree ref)42038fd1498Szrj ref_may_alias_global_p (tree ref)
42138fd1498Szrj {
42238fd1498Szrj tree base = get_base_address (ref);
42338fd1498Szrj return ref_may_alias_global_p_1 (base);
42438fd1498Szrj }
42538fd1498Szrj
42638fd1498Szrj /* Return true whether STMT may clobber global memory. */
42738fd1498Szrj
42838fd1498Szrj bool
stmt_may_clobber_global_p(gimple * stmt)42938fd1498Szrj stmt_may_clobber_global_p (gimple *stmt)
43038fd1498Szrj {
43138fd1498Szrj tree lhs;
43238fd1498Szrj
43338fd1498Szrj if (!gimple_vdef (stmt))
43438fd1498Szrj return false;
43538fd1498Szrj
43638fd1498Szrj /* ??? We can ask the oracle whether an artificial pointer
43738fd1498Szrj dereference with a pointer with points-to information covering
43838fd1498Szrj all global memory (what about non-address taken memory?) maybe
43938fd1498Szrj clobbered by this call. As there is at the moment no convenient
44038fd1498Szrj way of doing that without generating garbage do some manual
44138fd1498Szrj checking instead.
44238fd1498Szrj ??? We could make a NULL ao_ref argument to the various
44338fd1498Szrj predicates special, meaning any global memory. */
44438fd1498Szrj
44538fd1498Szrj switch (gimple_code (stmt))
44638fd1498Szrj {
44738fd1498Szrj case GIMPLE_ASSIGN:
44838fd1498Szrj lhs = gimple_assign_lhs (stmt);
44938fd1498Szrj return (TREE_CODE (lhs) != SSA_NAME
45038fd1498Szrj && ref_may_alias_global_p (lhs));
45138fd1498Szrj case GIMPLE_CALL:
45238fd1498Szrj return true;
45338fd1498Szrj default:
45438fd1498Szrj return true;
45538fd1498Szrj }
45638fd1498Szrj }
45738fd1498Szrj
45838fd1498Szrj
45938fd1498Szrj /* Dump alias information on FILE. */
46038fd1498Szrj
46138fd1498Szrj void
dump_alias_info(FILE * file)46238fd1498Szrj dump_alias_info (FILE *file)
46338fd1498Szrj {
46438fd1498Szrj unsigned i;
46538fd1498Szrj tree ptr;
46638fd1498Szrj const char *funcname
46738fd1498Szrj = lang_hooks.decl_printable_name (current_function_decl, 2);
46838fd1498Szrj tree var;
46938fd1498Szrj
47038fd1498Szrj fprintf (file, "\n\nAlias information for %s\n\n", funcname);
47138fd1498Szrj
47238fd1498Szrj fprintf (file, "Aliased symbols\n\n");
47338fd1498Szrj
47438fd1498Szrj FOR_EACH_LOCAL_DECL (cfun, i, var)
47538fd1498Szrj {
47638fd1498Szrj if (may_be_aliased (var))
47738fd1498Szrj dump_variable (file, var);
47838fd1498Szrj }
47938fd1498Szrj
48038fd1498Szrj fprintf (file, "\nCall clobber information\n");
48138fd1498Szrj
48238fd1498Szrj fprintf (file, "\nESCAPED");
48338fd1498Szrj dump_points_to_solution (file, &cfun->gimple_df->escaped);
48438fd1498Szrj
48538fd1498Szrj fprintf (file, "\n\nFlow-insensitive points-to information\n\n");
48638fd1498Szrj
48738fd1498Szrj FOR_EACH_SSA_NAME (i, ptr, cfun)
48838fd1498Szrj {
48938fd1498Szrj struct ptr_info_def *pi;
49038fd1498Szrj
49138fd1498Szrj if (!POINTER_TYPE_P (TREE_TYPE (ptr))
49238fd1498Szrj || SSA_NAME_IN_FREE_LIST (ptr))
49338fd1498Szrj continue;
49438fd1498Szrj
49538fd1498Szrj pi = SSA_NAME_PTR_INFO (ptr);
49638fd1498Szrj if (pi)
49738fd1498Szrj dump_points_to_info_for (file, ptr);
49838fd1498Szrj }
49938fd1498Szrj
50038fd1498Szrj fprintf (file, "\n");
50138fd1498Szrj }
50238fd1498Szrj
50338fd1498Szrj
50438fd1498Szrj /* Dump alias information on stderr. */
50538fd1498Szrj
50638fd1498Szrj DEBUG_FUNCTION void
debug_alias_info(void)50738fd1498Szrj debug_alias_info (void)
50838fd1498Szrj {
50938fd1498Szrj dump_alias_info (stderr);
51038fd1498Szrj }
51138fd1498Szrj
51238fd1498Szrj
51338fd1498Szrj /* Dump the points-to set *PT into FILE. */
51438fd1498Szrj
51538fd1498Szrj void
dump_points_to_solution(FILE * file,struct pt_solution * pt)51638fd1498Szrj dump_points_to_solution (FILE *file, struct pt_solution *pt)
51738fd1498Szrj {
51838fd1498Szrj if (pt->anything)
51938fd1498Szrj fprintf (file, ", points-to anything");
52038fd1498Szrj
52138fd1498Szrj if (pt->nonlocal)
52238fd1498Szrj fprintf (file, ", points-to non-local");
52338fd1498Szrj
52438fd1498Szrj if (pt->escaped)
52538fd1498Szrj fprintf (file, ", points-to escaped");
52638fd1498Szrj
52738fd1498Szrj if (pt->ipa_escaped)
52838fd1498Szrj fprintf (file, ", points-to unit escaped");
52938fd1498Szrj
53038fd1498Szrj if (pt->null)
53138fd1498Szrj fprintf (file, ", points-to NULL");
53238fd1498Szrj
53338fd1498Szrj if (pt->vars)
53438fd1498Szrj {
53538fd1498Szrj fprintf (file, ", points-to vars: ");
53638fd1498Szrj dump_decl_set (file, pt->vars);
53738fd1498Szrj if (pt->vars_contains_nonlocal
53838fd1498Szrj || pt->vars_contains_escaped
53938fd1498Szrj || pt->vars_contains_escaped_heap
54038fd1498Szrj || pt->vars_contains_restrict)
54138fd1498Szrj {
54238fd1498Szrj const char *comma = "";
54338fd1498Szrj fprintf (file, " (");
54438fd1498Szrj if (pt->vars_contains_nonlocal)
54538fd1498Szrj {
54638fd1498Szrj fprintf (file, "nonlocal");
54738fd1498Szrj comma = ", ";
54838fd1498Szrj }
54938fd1498Szrj if (pt->vars_contains_escaped)
55038fd1498Szrj {
55138fd1498Szrj fprintf (file, "%sescaped", comma);
55238fd1498Szrj comma = ", ";
55338fd1498Szrj }
55438fd1498Szrj if (pt->vars_contains_escaped_heap)
55538fd1498Szrj {
55638fd1498Szrj fprintf (file, "%sescaped heap", comma);
55738fd1498Szrj comma = ", ";
55838fd1498Szrj }
55938fd1498Szrj if (pt->vars_contains_restrict)
56038fd1498Szrj {
56138fd1498Szrj fprintf (file, "%srestrict", comma);
56238fd1498Szrj comma = ", ";
56338fd1498Szrj }
56438fd1498Szrj if (pt->vars_contains_interposable)
56538fd1498Szrj fprintf (file, "%sinterposable", comma);
56638fd1498Szrj fprintf (file, ")");
56738fd1498Szrj }
56838fd1498Szrj }
56938fd1498Szrj }
57038fd1498Szrj
57138fd1498Szrj
57238fd1498Szrj /* Unified dump function for pt_solution. */
57338fd1498Szrj
57438fd1498Szrj DEBUG_FUNCTION void
debug(pt_solution & ref)57538fd1498Szrj debug (pt_solution &ref)
57638fd1498Szrj {
57738fd1498Szrj dump_points_to_solution (stderr, &ref);
57838fd1498Szrj }
57938fd1498Szrj
58038fd1498Szrj DEBUG_FUNCTION void
debug(pt_solution * ptr)58138fd1498Szrj debug (pt_solution *ptr)
58238fd1498Szrj {
58338fd1498Szrj if (ptr)
58438fd1498Szrj debug (*ptr);
58538fd1498Szrj else
58638fd1498Szrj fprintf (stderr, "<nil>\n");
58738fd1498Szrj }
58838fd1498Szrj
58938fd1498Szrj
59038fd1498Szrj /* Dump points-to information for SSA_NAME PTR into FILE. */
59138fd1498Szrj
59238fd1498Szrj void
dump_points_to_info_for(FILE * file,tree ptr)59338fd1498Szrj dump_points_to_info_for (FILE *file, tree ptr)
59438fd1498Szrj {
59538fd1498Szrj struct ptr_info_def *pi = SSA_NAME_PTR_INFO (ptr);
59638fd1498Szrj
59738fd1498Szrj print_generic_expr (file, ptr, dump_flags);
59838fd1498Szrj
59938fd1498Szrj if (pi)
60038fd1498Szrj dump_points_to_solution (file, &pi->pt);
60138fd1498Szrj else
60238fd1498Szrj fprintf (file, ", points-to anything");
60338fd1498Szrj
60438fd1498Szrj fprintf (file, "\n");
60538fd1498Szrj }
60638fd1498Szrj
60738fd1498Szrj
60838fd1498Szrj /* Dump points-to information for VAR into stderr. */
60938fd1498Szrj
61038fd1498Szrj DEBUG_FUNCTION void
debug_points_to_info_for(tree var)61138fd1498Szrj debug_points_to_info_for (tree var)
61238fd1498Szrj {
61338fd1498Szrj dump_points_to_info_for (stderr, var);
61438fd1498Szrj }
61538fd1498Szrj
61638fd1498Szrj
61738fd1498Szrj /* Initializes the alias-oracle reference representation *R from REF. */
61838fd1498Szrj
61938fd1498Szrj void
ao_ref_init(ao_ref * r,tree ref)62038fd1498Szrj ao_ref_init (ao_ref *r, tree ref)
62138fd1498Szrj {
62238fd1498Szrj r->ref = ref;
62338fd1498Szrj r->base = NULL_TREE;
62438fd1498Szrj r->offset = 0;
62538fd1498Szrj r->size = -1;
62638fd1498Szrj r->max_size = -1;
62738fd1498Szrj r->ref_alias_set = -1;
62838fd1498Szrj r->base_alias_set = -1;
62938fd1498Szrj r->volatile_p = ref ? TREE_THIS_VOLATILE (ref) : false;
63038fd1498Szrj }
63138fd1498Szrj
63238fd1498Szrj /* Returns the base object of the memory reference *REF. */
63338fd1498Szrj
63438fd1498Szrj tree
ao_ref_base(ao_ref * ref)63538fd1498Szrj ao_ref_base (ao_ref *ref)
63638fd1498Szrj {
63738fd1498Szrj bool reverse;
63838fd1498Szrj
63938fd1498Szrj if (ref->base)
64038fd1498Szrj return ref->base;
64138fd1498Szrj ref->base = get_ref_base_and_extent (ref->ref, &ref->offset, &ref->size,
64238fd1498Szrj &ref->max_size, &reverse);
64338fd1498Szrj return ref->base;
64438fd1498Szrj }
64538fd1498Szrj
64638fd1498Szrj /* Returns the base object alias set of the memory reference *REF. */
64738fd1498Szrj
64838fd1498Szrj alias_set_type
ao_ref_base_alias_set(ao_ref * ref)64938fd1498Szrj ao_ref_base_alias_set (ao_ref *ref)
65038fd1498Szrj {
65138fd1498Szrj tree base_ref;
65238fd1498Szrj if (ref->base_alias_set != -1)
65338fd1498Szrj return ref->base_alias_set;
65438fd1498Szrj if (!ref->ref)
65538fd1498Szrj return 0;
65638fd1498Szrj base_ref = ref->ref;
65738fd1498Szrj while (handled_component_p (base_ref))
65838fd1498Szrj base_ref = TREE_OPERAND (base_ref, 0);
65938fd1498Szrj ref->base_alias_set = get_alias_set (base_ref);
66038fd1498Szrj return ref->base_alias_set;
66138fd1498Szrj }
66238fd1498Szrj
66338fd1498Szrj /* Returns the reference alias set of the memory reference *REF. */
66438fd1498Szrj
66538fd1498Szrj alias_set_type
ao_ref_alias_set(ao_ref * ref)66638fd1498Szrj ao_ref_alias_set (ao_ref *ref)
66738fd1498Szrj {
66838fd1498Szrj if (ref->ref_alias_set != -1)
66938fd1498Szrj return ref->ref_alias_set;
67038fd1498Szrj ref->ref_alias_set = get_alias_set (ref->ref);
67138fd1498Szrj return ref->ref_alias_set;
67238fd1498Szrj }
67338fd1498Szrj
67438fd1498Szrj /* Init an alias-oracle reference representation from a gimple pointer
67538fd1498Szrj PTR and a gimple size SIZE in bytes. If SIZE is NULL_TREE then the
67638fd1498Szrj size is assumed to be unknown. The access is assumed to be only
67738fd1498Szrj to or after of the pointer target, not before it. */
67838fd1498Szrj
67938fd1498Szrj void
ao_ref_init_from_ptr_and_size(ao_ref * ref,tree ptr,tree size)68038fd1498Szrj ao_ref_init_from_ptr_and_size (ao_ref *ref, tree ptr, tree size)
68138fd1498Szrj {
68238fd1498Szrj poly_int64 t, size_hwi, extra_offset = 0;
68338fd1498Szrj ref->ref = NULL_TREE;
68438fd1498Szrj if (TREE_CODE (ptr) == SSA_NAME)
68538fd1498Szrj {
68638fd1498Szrj gimple *stmt = SSA_NAME_DEF_STMT (ptr);
68738fd1498Szrj if (gimple_assign_single_p (stmt)
68838fd1498Szrj && gimple_assign_rhs_code (stmt) == ADDR_EXPR)
68938fd1498Szrj ptr = gimple_assign_rhs1 (stmt);
69038fd1498Szrj else if (is_gimple_assign (stmt)
69138fd1498Szrj && gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR
69238fd1498Szrj && ptrdiff_tree_p (gimple_assign_rhs2 (stmt), &extra_offset))
69338fd1498Szrj {
69438fd1498Szrj ptr = gimple_assign_rhs1 (stmt);
69538fd1498Szrj extra_offset *= BITS_PER_UNIT;
69638fd1498Szrj }
69738fd1498Szrj }
69838fd1498Szrj
69938fd1498Szrj if (TREE_CODE (ptr) == ADDR_EXPR)
70038fd1498Szrj {
70138fd1498Szrj ref->base = get_addr_base_and_unit_offset (TREE_OPERAND (ptr, 0), &t);
70238fd1498Szrj if (ref->base)
70338fd1498Szrj ref->offset = BITS_PER_UNIT * t;
70438fd1498Szrj else
70538fd1498Szrj {
70638fd1498Szrj size = NULL_TREE;
70738fd1498Szrj ref->offset = 0;
70838fd1498Szrj ref->base = get_base_address (TREE_OPERAND (ptr, 0));
70938fd1498Szrj }
71038fd1498Szrj }
71138fd1498Szrj else
71238fd1498Szrj {
71338fd1498Szrj ref->base = build2 (MEM_REF, char_type_node,
71438fd1498Szrj ptr, null_pointer_node);
71538fd1498Szrj ref->offset = 0;
71638fd1498Szrj }
71738fd1498Szrj ref->offset += extra_offset;
71838fd1498Szrj if (size
71938fd1498Szrj && poly_int_tree_p (size, &size_hwi)
72038fd1498Szrj && coeffs_in_range_p (size_hwi, 0, HOST_WIDE_INT_MAX / BITS_PER_UNIT))
72138fd1498Szrj ref->max_size = ref->size = size_hwi * BITS_PER_UNIT;
72238fd1498Szrj else
72338fd1498Szrj ref->max_size = ref->size = -1;
72438fd1498Szrj ref->ref_alias_set = 0;
72538fd1498Szrj ref->base_alias_set = 0;
72638fd1498Szrj ref->volatile_p = false;
72738fd1498Szrj }
72838fd1498Szrj
72938fd1498Szrj /* Return 1 if TYPE1 and TYPE2 are to be considered equivalent for the
73038fd1498Szrj purpose of TBAA. Return 0 if they are distinct and -1 if we cannot
73138fd1498Szrj decide. */
73238fd1498Szrj
73338fd1498Szrj static inline int
same_type_for_tbaa(tree type1,tree type2)73438fd1498Szrj same_type_for_tbaa (tree type1, tree type2)
73538fd1498Szrj {
73638fd1498Szrj type1 = TYPE_MAIN_VARIANT (type1);
73738fd1498Szrj type2 = TYPE_MAIN_VARIANT (type2);
73838fd1498Szrj
73938fd1498Szrj /* If we would have to do structural comparison bail out. */
74038fd1498Szrj if (TYPE_STRUCTURAL_EQUALITY_P (type1)
74138fd1498Szrj || TYPE_STRUCTURAL_EQUALITY_P (type2))
74238fd1498Szrj return -1;
74338fd1498Szrj
74438fd1498Szrj /* Compare the canonical types. */
74538fd1498Szrj if (TYPE_CANONICAL (type1) == TYPE_CANONICAL (type2))
74638fd1498Szrj return 1;
74738fd1498Szrj
74838fd1498Szrj /* ??? Array types are not properly unified in all cases as we have
74938fd1498Szrj spurious changes in the index types for example. Removing this
75038fd1498Szrj causes all sorts of problems with the Fortran frontend. */
75138fd1498Szrj if (TREE_CODE (type1) == ARRAY_TYPE
75238fd1498Szrj && TREE_CODE (type2) == ARRAY_TYPE)
75338fd1498Szrj return -1;
75438fd1498Szrj
75538fd1498Szrj /* ??? In Ada, an lvalue of an unconstrained type can be used to access an
75638fd1498Szrj object of one of its constrained subtypes, e.g. when a function with an
75738fd1498Szrj unconstrained parameter passed by reference is called on an object and
75838fd1498Szrj inlined. But, even in the case of a fixed size, type and subtypes are
75938fd1498Szrj not equivalent enough as to share the same TYPE_CANONICAL, since this
76038fd1498Szrj would mean that conversions between them are useless, whereas they are
76138fd1498Szrj not (e.g. type and subtypes can have different modes). So, in the end,
76238fd1498Szrj they are only guaranteed to have the same alias set. */
76338fd1498Szrj if (get_alias_set (type1) == get_alias_set (type2))
76438fd1498Szrj return -1;
76538fd1498Szrj
76638fd1498Szrj /* The types are known to be not equal. */
76738fd1498Szrj return 0;
76838fd1498Szrj }
76938fd1498Szrj
77038fd1498Szrj /* Determine if the two component references REF1 and REF2 which are
77138fd1498Szrj based on access types TYPE1 and TYPE2 and of which at least one is based
77238fd1498Szrj on an indirect reference may alias. REF2 is the only one that can
77338fd1498Szrj be a decl in which case REF2_IS_DECL is true.
77438fd1498Szrj REF1_ALIAS_SET, BASE1_ALIAS_SET, REF2_ALIAS_SET and BASE2_ALIAS_SET
77538fd1498Szrj are the respective alias sets. */
77638fd1498Szrj
77738fd1498Szrj static bool
aliasing_component_refs_p(tree ref1,alias_set_type ref1_alias_set,alias_set_type base1_alias_set,poly_int64 offset1,poly_int64 max_size1,tree ref2,alias_set_type ref2_alias_set,alias_set_type base2_alias_set,poly_int64 offset2,poly_int64 max_size2,bool ref2_is_decl)77838fd1498Szrj aliasing_component_refs_p (tree ref1,
77938fd1498Szrj alias_set_type ref1_alias_set,
78038fd1498Szrj alias_set_type base1_alias_set,
78138fd1498Szrj poly_int64 offset1, poly_int64 max_size1,
78238fd1498Szrj tree ref2,
78338fd1498Szrj alias_set_type ref2_alias_set,
78438fd1498Szrj alias_set_type base2_alias_set,
78538fd1498Szrj poly_int64 offset2, poly_int64 max_size2,
78638fd1498Szrj bool ref2_is_decl)
78738fd1498Szrj {
78838fd1498Szrj /* If one reference is a component references through pointers try to find a
78938fd1498Szrj common base and apply offset based disambiguation. This handles
79038fd1498Szrj for example
79138fd1498Szrj struct A { int i; int j; } *q;
79238fd1498Szrj struct B { struct A a; int k; } *p;
79338fd1498Szrj disambiguating q->i and p->a.j. */
79438fd1498Szrj tree base1, base2;
79538fd1498Szrj tree type1, type2;
79638fd1498Szrj tree *refp;
79738fd1498Szrj int same_p;
79838fd1498Szrj
79938fd1498Szrj /* Choose bases and base types to search for. */
80038fd1498Szrj base1 = ref1;
80138fd1498Szrj while (handled_component_p (base1))
80238fd1498Szrj base1 = TREE_OPERAND (base1, 0);
80338fd1498Szrj type1 = TREE_TYPE (base1);
80438fd1498Szrj base2 = ref2;
80538fd1498Szrj while (handled_component_p (base2))
80638fd1498Szrj base2 = TREE_OPERAND (base2, 0);
80738fd1498Szrj type2 = TREE_TYPE (base2);
80838fd1498Szrj
80938fd1498Szrj /* Now search for the type1 in the access path of ref2. This
81038fd1498Szrj would be a common base for doing offset based disambiguation on. */
81138fd1498Szrj refp = &ref2;
81238fd1498Szrj while (handled_component_p (*refp)
81338fd1498Szrj && same_type_for_tbaa (TREE_TYPE (*refp), type1) == 0)
81438fd1498Szrj refp = &TREE_OPERAND (*refp, 0);
81538fd1498Szrj same_p = same_type_for_tbaa (TREE_TYPE (*refp), type1);
81638fd1498Szrj /* If we couldn't compare types we have to bail out. */
81738fd1498Szrj if (same_p == -1)
81838fd1498Szrj return true;
81938fd1498Szrj else if (same_p == 1)
82038fd1498Szrj {
82138fd1498Szrj poly_int64 offadj, sztmp, msztmp;
82238fd1498Szrj bool reverse;
82338fd1498Szrj get_ref_base_and_extent (*refp, &offadj, &sztmp, &msztmp, &reverse);
82438fd1498Szrj offset2 -= offadj;
82538fd1498Szrj get_ref_base_and_extent (base1, &offadj, &sztmp, &msztmp, &reverse);
82638fd1498Szrj offset1 -= offadj;
82738fd1498Szrj return ranges_maybe_overlap_p (offset1, max_size1, offset2, max_size2);
82838fd1498Szrj }
82938fd1498Szrj /* If we didn't find a common base, try the other way around. */
83038fd1498Szrj refp = &ref1;
83138fd1498Szrj while (handled_component_p (*refp)
83238fd1498Szrj && same_type_for_tbaa (TREE_TYPE (*refp), type2) == 0)
83338fd1498Szrj refp = &TREE_OPERAND (*refp, 0);
83438fd1498Szrj same_p = same_type_for_tbaa (TREE_TYPE (*refp), type2);
83538fd1498Szrj /* If we couldn't compare types we have to bail out. */
83638fd1498Szrj if (same_p == -1)
83738fd1498Szrj return true;
83838fd1498Szrj else if (same_p == 1)
83938fd1498Szrj {
84038fd1498Szrj poly_int64 offadj, sztmp, msztmp;
84138fd1498Szrj bool reverse;
84238fd1498Szrj get_ref_base_and_extent (*refp, &offadj, &sztmp, &msztmp, &reverse);
84338fd1498Szrj offset1 -= offadj;
84438fd1498Szrj get_ref_base_and_extent (base2, &offadj, &sztmp, &msztmp, &reverse);
84538fd1498Szrj offset2 -= offadj;
84638fd1498Szrj return ranges_maybe_overlap_p (offset1, max_size1, offset2, max_size2);
84738fd1498Szrj }
84838fd1498Szrj
84938fd1498Szrj /* If we have two type access paths B1.path1 and B2.path2 they may
85038fd1498Szrj only alias if either B1 is in B2.path2 or B2 is in B1.path1.
85138fd1498Szrj But we can still have a path that goes B1.path1...B2.path2 with
85238fd1498Szrj a part that we do not see. So we can only disambiguate now
85338fd1498Szrj if there is no B2 in the tail of path1 and no B1 on the
85438fd1498Szrj tail of path2. */
85538fd1498Szrj if (base1_alias_set == ref2_alias_set
85638fd1498Szrj || alias_set_subset_of (base1_alias_set, ref2_alias_set))
85738fd1498Szrj return true;
85838fd1498Szrj /* If this is ptr vs. decl then we know there is no ptr ... decl path. */
85938fd1498Szrj if (!ref2_is_decl)
86038fd1498Szrj return (base2_alias_set == ref1_alias_set
86138fd1498Szrj || alias_set_subset_of (base2_alias_set, ref1_alias_set));
86238fd1498Szrj return false;
86338fd1498Szrj }
86438fd1498Szrj
86538fd1498Szrj /* Return true if we can determine that component references REF1 and REF2,
86638fd1498Szrj that are within a common DECL, cannot overlap. */
86738fd1498Szrj
86838fd1498Szrj static bool
nonoverlapping_component_refs_of_decl_p(tree ref1,tree ref2)86938fd1498Szrj nonoverlapping_component_refs_of_decl_p (tree ref1, tree ref2)
87038fd1498Szrj {
87138fd1498Szrj auto_vec<tree, 16> component_refs1;
87238fd1498Szrj auto_vec<tree, 16> component_refs2;
87338fd1498Szrj
87438fd1498Szrj /* Create the stack of handled components for REF1. */
87538fd1498Szrj while (handled_component_p (ref1))
87638fd1498Szrj {
87738fd1498Szrj component_refs1.safe_push (ref1);
87838fd1498Szrj ref1 = TREE_OPERAND (ref1, 0);
87938fd1498Szrj }
88038fd1498Szrj if (TREE_CODE (ref1) == MEM_REF)
88138fd1498Szrj {
88238fd1498Szrj if (!integer_zerop (TREE_OPERAND (ref1, 1)))
88338fd1498Szrj return false;
88438fd1498Szrj ref1 = TREE_OPERAND (TREE_OPERAND (ref1, 0), 0);
88538fd1498Szrj }
88638fd1498Szrj
88738fd1498Szrj /* Create the stack of handled components for REF2. */
88838fd1498Szrj while (handled_component_p (ref2))
88938fd1498Szrj {
89038fd1498Szrj component_refs2.safe_push (ref2);
89138fd1498Szrj ref2 = TREE_OPERAND (ref2, 0);
89238fd1498Szrj }
89338fd1498Szrj if (TREE_CODE (ref2) == MEM_REF)
89438fd1498Szrj {
89538fd1498Szrj if (!integer_zerop (TREE_OPERAND (ref2, 1)))
89638fd1498Szrj return false;
89738fd1498Szrj ref2 = TREE_OPERAND (TREE_OPERAND (ref2, 0), 0);
89838fd1498Szrj }
89938fd1498Szrj
90038fd1498Szrj /* Bases must be either same or uncomparable. */
90138fd1498Szrj gcc_checking_assert (ref1 == ref2
90238fd1498Szrj || (DECL_P (ref1) && DECL_P (ref2)
90338fd1498Szrj && compare_base_decls (ref1, ref2) != 0));
90438fd1498Szrj
90538fd1498Szrj /* Pop the stacks in parallel and examine the COMPONENT_REFs of the same
90638fd1498Szrj rank. This is sufficient because we start from the same DECL and you
90738fd1498Szrj cannot reference several fields at a time with COMPONENT_REFs (unlike
90838fd1498Szrj with ARRAY_RANGE_REFs for arrays) so you always need the same number
90938fd1498Szrj of them to access a sub-component, unless you're in a union, in which
91038fd1498Szrj case the return value will precisely be false. */
91138fd1498Szrj while (true)
91238fd1498Szrj {
91338fd1498Szrj do
91438fd1498Szrj {
91538fd1498Szrj if (component_refs1.is_empty ())
91638fd1498Szrj return false;
91738fd1498Szrj ref1 = component_refs1.pop ();
91838fd1498Szrj }
91938fd1498Szrj while (!RECORD_OR_UNION_TYPE_P (TREE_TYPE (TREE_OPERAND (ref1, 0))));
92038fd1498Szrj
92138fd1498Szrj do
92238fd1498Szrj {
92338fd1498Szrj if (component_refs2.is_empty ())
92438fd1498Szrj return false;
92538fd1498Szrj ref2 = component_refs2.pop ();
92638fd1498Szrj }
92738fd1498Szrj while (!RECORD_OR_UNION_TYPE_P (TREE_TYPE (TREE_OPERAND (ref2, 0))));
92838fd1498Szrj
92938fd1498Szrj /* Beware of BIT_FIELD_REF. */
93038fd1498Szrj if (TREE_CODE (ref1) != COMPONENT_REF
93138fd1498Szrj || TREE_CODE (ref2) != COMPONENT_REF)
93238fd1498Szrj return false;
93338fd1498Szrj
93438fd1498Szrj tree field1 = TREE_OPERAND (ref1, 1);
93538fd1498Szrj tree field2 = TREE_OPERAND (ref2, 1);
93638fd1498Szrj
93738fd1498Szrj /* ??? We cannot simply use the type of operand #0 of the refs here
93838fd1498Szrj as the Fortran compiler smuggles type punning into COMPONENT_REFs
93938fd1498Szrj for common blocks instead of using unions like everyone else. */
94038fd1498Szrj tree type1 = DECL_CONTEXT (field1);
94138fd1498Szrj tree type2 = DECL_CONTEXT (field2);
94238fd1498Szrj
94338fd1498Szrj /* We cannot disambiguate fields in a union or qualified union. */
94438fd1498Szrj if (type1 != type2 || TREE_CODE (type1) != RECORD_TYPE)
94538fd1498Szrj return false;
94638fd1498Szrj
94738fd1498Szrj if (field1 != field2)
94838fd1498Szrj {
94938fd1498Szrj /* A field and its representative need to be considered the
95038fd1498Szrj same. */
95138fd1498Szrj if (DECL_BIT_FIELD_REPRESENTATIVE (field1) == field2
95238fd1498Szrj || DECL_BIT_FIELD_REPRESENTATIVE (field2) == field1)
95338fd1498Szrj return false;
95438fd1498Szrj /* Different fields of the same record type cannot overlap.
95538fd1498Szrj ??? Bitfields can overlap at RTL level so punt on them. */
95638fd1498Szrj if (DECL_BIT_FIELD (field1) && DECL_BIT_FIELD (field2))
95738fd1498Szrj return false;
95838fd1498Szrj return true;
95938fd1498Szrj }
96038fd1498Szrj }
96138fd1498Szrj
96238fd1498Szrj return false;
96338fd1498Szrj }
96438fd1498Szrj
96538fd1498Szrj /* qsort compare function to sort FIELD_DECLs after their
96638fd1498Szrj DECL_FIELD_CONTEXT TYPE_UID. */
96738fd1498Szrj
96838fd1498Szrj static inline int
ncr_compar(const void * field1_,const void * field2_)96938fd1498Szrj ncr_compar (const void *field1_, const void *field2_)
97038fd1498Szrj {
97138fd1498Szrj const_tree field1 = *(const_tree *) const_cast <void *>(field1_);
97238fd1498Szrj const_tree field2 = *(const_tree *) const_cast <void *>(field2_);
97338fd1498Szrj unsigned int uid1 = TYPE_UID (DECL_FIELD_CONTEXT (field1));
97438fd1498Szrj unsigned int uid2 = TYPE_UID (DECL_FIELD_CONTEXT (field2));
97538fd1498Szrj if (uid1 < uid2)
97638fd1498Szrj return -1;
97738fd1498Szrj else if (uid1 > uid2)
97838fd1498Szrj return 1;
97938fd1498Szrj return 0;
98038fd1498Szrj }
98138fd1498Szrj
98238fd1498Szrj /* Return true if we can determine that the fields referenced cannot
98338fd1498Szrj overlap for any pair of objects. */
98438fd1498Szrj
98538fd1498Szrj static bool
nonoverlapping_component_refs_p(const_tree x,const_tree y)98638fd1498Szrj nonoverlapping_component_refs_p (const_tree x, const_tree y)
98738fd1498Szrj {
98838fd1498Szrj if (!flag_strict_aliasing
98938fd1498Szrj || !x || !y
99038fd1498Szrj || TREE_CODE (x) != COMPONENT_REF
99138fd1498Szrj || TREE_CODE (y) != COMPONENT_REF)
99238fd1498Szrj return false;
99338fd1498Szrj
99438fd1498Szrj auto_vec<const_tree, 16> fieldsx;
99538fd1498Szrj while (TREE_CODE (x) == COMPONENT_REF)
99638fd1498Szrj {
99738fd1498Szrj tree field = TREE_OPERAND (x, 1);
99838fd1498Szrj tree type = DECL_FIELD_CONTEXT (field);
99938fd1498Szrj if (TREE_CODE (type) == RECORD_TYPE)
100038fd1498Szrj fieldsx.safe_push (field);
100138fd1498Szrj x = TREE_OPERAND (x, 0);
100238fd1498Szrj }
100338fd1498Szrj if (fieldsx.length () == 0)
100438fd1498Szrj return false;
100538fd1498Szrj auto_vec<const_tree, 16> fieldsy;
100638fd1498Szrj while (TREE_CODE (y) == COMPONENT_REF)
100738fd1498Szrj {
100838fd1498Szrj tree field = TREE_OPERAND (y, 1);
100938fd1498Szrj tree type = DECL_FIELD_CONTEXT (field);
101038fd1498Szrj if (TREE_CODE (type) == RECORD_TYPE)
101138fd1498Szrj fieldsy.safe_push (TREE_OPERAND (y, 1));
101238fd1498Szrj y = TREE_OPERAND (y, 0);
101338fd1498Szrj }
101438fd1498Szrj if (fieldsy.length () == 0)
101538fd1498Szrj return false;
101638fd1498Szrj
101738fd1498Szrj /* Most common case first. */
101838fd1498Szrj if (fieldsx.length () == 1
101938fd1498Szrj && fieldsy.length () == 1)
102038fd1498Szrj return ((DECL_FIELD_CONTEXT (fieldsx[0])
102138fd1498Szrj == DECL_FIELD_CONTEXT (fieldsy[0]))
102238fd1498Szrj && fieldsx[0] != fieldsy[0]
102338fd1498Szrj && !(DECL_BIT_FIELD (fieldsx[0]) && DECL_BIT_FIELD (fieldsy[0])));
102438fd1498Szrj
102538fd1498Szrj if (fieldsx.length () == 2)
102638fd1498Szrj {
102738fd1498Szrj if (ncr_compar (&fieldsx[0], &fieldsx[1]) == 1)
102838fd1498Szrj std::swap (fieldsx[0], fieldsx[1]);
102938fd1498Szrj }
103038fd1498Szrj else
103138fd1498Szrj fieldsx.qsort (ncr_compar);
103238fd1498Szrj
103338fd1498Szrj if (fieldsy.length () == 2)
103438fd1498Szrj {
103538fd1498Szrj if (ncr_compar (&fieldsy[0], &fieldsy[1]) == 1)
103638fd1498Szrj std::swap (fieldsy[0], fieldsy[1]);
103738fd1498Szrj }
103838fd1498Szrj else
103938fd1498Szrj fieldsy.qsort (ncr_compar);
104038fd1498Szrj
104138fd1498Szrj unsigned i = 0, j = 0;
104238fd1498Szrj do
104338fd1498Szrj {
104438fd1498Szrj const_tree fieldx = fieldsx[i];
104538fd1498Szrj const_tree fieldy = fieldsy[j];
104638fd1498Szrj tree typex = DECL_FIELD_CONTEXT (fieldx);
104738fd1498Szrj tree typey = DECL_FIELD_CONTEXT (fieldy);
104838fd1498Szrj if (typex == typey)
104938fd1498Szrj {
105038fd1498Szrj /* We're left with accessing different fields of a structure,
105138fd1498Szrj no possible overlap. */
105238fd1498Szrj if (fieldx != fieldy)
105338fd1498Szrj {
105438fd1498Szrj /* A field and its representative need to be considered the
105538fd1498Szrj same. */
105638fd1498Szrj if (DECL_BIT_FIELD_REPRESENTATIVE (fieldx) == fieldy
105738fd1498Szrj || DECL_BIT_FIELD_REPRESENTATIVE (fieldy) == fieldx)
105838fd1498Szrj return false;
105938fd1498Szrj /* Different fields of the same record type cannot overlap.
106038fd1498Szrj ??? Bitfields can overlap at RTL level so punt on them. */
106138fd1498Szrj if (DECL_BIT_FIELD (fieldx) && DECL_BIT_FIELD (fieldy))
106238fd1498Szrj return false;
106338fd1498Szrj return true;
106438fd1498Szrj }
106538fd1498Szrj }
106638fd1498Szrj if (TYPE_UID (typex) < TYPE_UID (typey))
106738fd1498Szrj {
106838fd1498Szrj i++;
106938fd1498Szrj if (i == fieldsx.length ())
107038fd1498Szrj break;
107138fd1498Szrj }
107238fd1498Szrj else
107338fd1498Szrj {
107438fd1498Szrj j++;
107538fd1498Szrj if (j == fieldsy.length ())
107638fd1498Szrj break;
107738fd1498Szrj }
107838fd1498Szrj }
107938fd1498Szrj while (1);
108038fd1498Szrj
108138fd1498Szrj return false;
108238fd1498Szrj }
108338fd1498Szrj
108438fd1498Szrj
108538fd1498Szrj /* Return true if two memory references based on the variables BASE1
108638fd1498Szrj and BASE2 constrained to [OFFSET1, OFFSET1 + MAX_SIZE1) and
108738fd1498Szrj [OFFSET2, OFFSET2 + MAX_SIZE2) may alias. REF1 and REF2
108838fd1498Szrj if non-NULL are the complete memory reference trees. */
108938fd1498Szrj
109038fd1498Szrj static bool
decl_refs_may_alias_p(tree ref1,tree base1,poly_int64 offset1,poly_int64 max_size1,tree ref2,tree base2,poly_int64 offset2,poly_int64 max_size2)109138fd1498Szrj decl_refs_may_alias_p (tree ref1, tree base1,
109238fd1498Szrj poly_int64 offset1, poly_int64 max_size1,
109338fd1498Szrj tree ref2, tree base2,
109438fd1498Szrj poly_int64 offset2, poly_int64 max_size2)
109538fd1498Szrj {
109638fd1498Szrj gcc_checking_assert (DECL_P (base1) && DECL_P (base2));
109738fd1498Szrj
109838fd1498Szrj /* If both references are based on different variables, they cannot alias. */
109938fd1498Szrj if (compare_base_decls (base1, base2) == 0)
110038fd1498Szrj return false;
110138fd1498Szrj
110238fd1498Szrj /* If both references are based on the same variable, they cannot alias if
110338fd1498Szrj the accesses do not overlap. */
110438fd1498Szrj if (!ranges_maybe_overlap_p (offset1, max_size1, offset2, max_size2))
110538fd1498Szrj return false;
110638fd1498Szrj
110738fd1498Szrj /* For components with variable position, the above test isn't sufficient,
110838fd1498Szrj so we disambiguate component references manually. */
110938fd1498Szrj if (ref1 && ref2
111038fd1498Szrj && handled_component_p (ref1) && handled_component_p (ref2)
111138fd1498Szrj && nonoverlapping_component_refs_of_decl_p (ref1, ref2))
111238fd1498Szrj return false;
111338fd1498Szrj
111438fd1498Szrj return true;
111538fd1498Szrj }
111638fd1498Szrj
111738fd1498Szrj /* Return true if an indirect reference based on *PTR1 constrained
111838fd1498Szrj to [OFFSET1, OFFSET1 + MAX_SIZE1) may alias a variable based on BASE2
111938fd1498Szrj constrained to [OFFSET2, OFFSET2 + MAX_SIZE2). *PTR1 and BASE2 have
112038fd1498Szrj the alias sets BASE1_ALIAS_SET and BASE2_ALIAS_SET which can be -1
112138fd1498Szrj in which case they are computed on-demand. REF1 and REF2
112238fd1498Szrj if non-NULL are the complete memory reference trees. */
112338fd1498Szrj
112438fd1498Szrj static bool
indirect_ref_may_alias_decl_p(tree ref1 ATTRIBUTE_UNUSED,tree base1,poly_int64 offset1,poly_int64 max_size1,alias_set_type ref1_alias_set,alias_set_type base1_alias_set,tree ref2 ATTRIBUTE_UNUSED,tree base2,poly_int64 offset2,poly_int64 max_size2,alias_set_type ref2_alias_set,alias_set_type base2_alias_set,bool tbaa_p)112538fd1498Szrj indirect_ref_may_alias_decl_p (tree ref1 ATTRIBUTE_UNUSED, tree base1,
112638fd1498Szrj poly_int64 offset1, poly_int64 max_size1,
112738fd1498Szrj alias_set_type ref1_alias_set,
112838fd1498Szrj alias_set_type base1_alias_set,
112938fd1498Szrj tree ref2 ATTRIBUTE_UNUSED, tree base2,
113038fd1498Szrj poly_int64 offset2, poly_int64 max_size2,
113138fd1498Szrj alias_set_type ref2_alias_set,
113238fd1498Szrj alias_set_type base2_alias_set, bool tbaa_p)
113338fd1498Szrj {
113438fd1498Szrj tree ptr1;
113538fd1498Szrj tree ptrtype1, dbase2;
113638fd1498Szrj
113738fd1498Szrj gcc_checking_assert ((TREE_CODE (base1) == MEM_REF
113838fd1498Szrj || TREE_CODE (base1) == TARGET_MEM_REF)
113938fd1498Szrj && DECL_P (base2));
114038fd1498Szrj
114138fd1498Szrj ptr1 = TREE_OPERAND (base1, 0);
114238fd1498Szrj poly_offset_int moff = mem_ref_offset (base1) << LOG2_BITS_PER_UNIT;
114338fd1498Szrj
114438fd1498Szrj /* If only one reference is based on a variable, they cannot alias if
114538fd1498Szrj the pointer access is beyond the extent of the variable access.
114638fd1498Szrj (the pointer base cannot validly point to an offset less than zero
114738fd1498Szrj of the variable).
114838fd1498Szrj ??? IVOPTs creates bases that do not honor this restriction,
114938fd1498Szrj so do not apply this optimization for TARGET_MEM_REFs. */
115038fd1498Szrj if (TREE_CODE (base1) != TARGET_MEM_REF
115138fd1498Szrj && !ranges_maybe_overlap_p (offset1 + moff, -1, offset2, max_size2))
115238fd1498Szrj return false;
115338fd1498Szrj /* They also cannot alias if the pointer may not point to the decl. */
115438fd1498Szrj if (!ptr_deref_may_alias_decl_p (ptr1, base2))
115538fd1498Szrj return false;
115638fd1498Szrj
115738fd1498Szrj /* Disambiguations that rely on strict aliasing rules follow. */
115838fd1498Szrj if (!flag_strict_aliasing || !tbaa_p)
115938fd1498Szrj return true;
116038fd1498Szrj
116138fd1498Szrj ptrtype1 = TREE_TYPE (TREE_OPERAND (base1, 1));
116238fd1498Szrj
116338fd1498Szrj /* If the alias set for a pointer access is zero all bets are off. */
116438fd1498Szrj if (base1_alias_set == 0)
116538fd1498Szrj return true;
116638fd1498Szrj
116738fd1498Szrj /* When we are trying to disambiguate an access with a pointer dereference
116838fd1498Szrj as base versus one with a decl as base we can use both the size
116938fd1498Szrj of the decl and its dynamic type for extra disambiguation.
117038fd1498Szrj ??? We do not know anything about the dynamic type of the decl
117138fd1498Szrj other than that its alias-set contains base2_alias_set as a subset
117238fd1498Szrj which does not help us here. */
117338fd1498Szrj /* As we know nothing useful about the dynamic type of the decl just
117438fd1498Szrj use the usual conflict check rather than a subset test.
117538fd1498Szrj ??? We could introduce -fvery-strict-aliasing when the language
117638fd1498Szrj does not allow decls to have a dynamic type that differs from their
117738fd1498Szrj static type. Then we can check
117838fd1498Szrj !alias_set_subset_of (base1_alias_set, base2_alias_set) instead. */
117938fd1498Szrj if (base1_alias_set != base2_alias_set
118038fd1498Szrj && !alias_sets_conflict_p (base1_alias_set, base2_alias_set))
118138fd1498Szrj return false;
118238fd1498Szrj /* If the size of the access relevant for TBAA through the pointer
118338fd1498Szrj is bigger than the size of the decl we can't possibly access the
118438fd1498Szrj decl via that pointer. */
118538fd1498Szrj if (DECL_SIZE (base2) && COMPLETE_TYPE_P (TREE_TYPE (ptrtype1))
118638fd1498Szrj && poly_int_tree_p (DECL_SIZE (base2))
118738fd1498Szrj && poly_int_tree_p (TYPE_SIZE (TREE_TYPE (ptrtype1)))
118838fd1498Szrj /* ??? This in turn may run afoul when a decl of type T which is
118938fd1498Szrj a member of union type U is accessed through a pointer to
119038fd1498Szrj type U and sizeof T is smaller than sizeof U. */
119138fd1498Szrj && TREE_CODE (TREE_TYPE (ptrtype1)) != UNION_TYPE
119238fd1498Szrj && TREE_CODE (TREE_TYPE (ptrtype1)) != QUAL_UNION_TYPE
119338fd1498Szrj && known_lt (wi::to_poly_widest (DECL_SIZE (base2)),
119438fd1498Szrj wi::to_poly_widest (TYPE_SIZE (TREE_TYPE (ptrtype1)))))
119538fd1498Szrj return false;
119638fd1498Szrj
119738fd1498Szrj if (!ref2)
119838fd1498Szrj return true;
119938fd1498Szrj
120038fd1498Szrj /* If the decl is accessed via a MEM_REF, reconstruct the base
120138fd1498Szrj we can use for TBAA and an appropriately adjusted offset. */
120238fd1498Szrj dbase2 = ref2;
120338fd1498Szrj while (handled_component_p (dbase2))
120438fd1498Szrj dbase2 = TREE_OPERAND (dbase2, 0);
120538fd1498Szrj poly_int64 doffset1 = offset1;
120638fd1498Szrj poly_offset_int doffset2 = offset2;
120738fd1498Szrj if (TREE_CODE (dbase2) == MEM_REF
120838fd1498Szrj || TREE_CODE (dbase2) == TARGET_MEM_REF)
120938fd1498Szrj doffset2 -= mem_ref_offset (dbase2) << LOG2_BITS_PER_UNIT;
121038fd1498Szrj
121138fd1498Szrj /* If either reference is view-converted, give up now. */
121238fd1498Szrj if (same_type_for_tbaa (TREE_TYPE (base1), TREE_TYPE (ptrtype1)) != 1
121338fd1498Szrj || same_type_for_tbaa (TREE_TYPE (dbase2), TREE_TYPE (base2)) != 1)
121438fd1498Szrj return true;
121538fd1498Szrj
121638fd1498Szrj /* If both references are through the same type, they do not alias
121738fd1498Szrj if the accesses do not overlap. This does extra disambiguation
121838fd1498Szrj for mixed/pointer accesses but requires strict aliasing.
121938fd1498Szrj For MEM_REFs we require that the component-ref offset we computed
122038fd1498Szrj is relative to the start of the type which we ensure by
122138fd1498Szrj comparing rvalue and access type and disregarding the constant
122238fd1498Szrj pointer offset. */
122338fd1498Szrj if ((TREE_CODE (base1) != TARGET_MEM_REF
122438fd1498Szrj || (!TMR_INDEX (base1) && !TMR_INDEX2 (base1)))
122538fd1498Szrj && same_type_for_tbaa (TREE_TYPE (base1), TREE_TYPE (dbase2)) == 1)
122638fd1498Szrj return ranges_maybe_overlap_p (doffset1, max_size1, doffset2, max_size2);
122738fd1498Szrj
122838fd1498Szrj if (ref1 && ref2
122938fd1498Szrj && nonoverlapping_component_refs_p (ref1, ref2))
123038fd1498Szrj return false;
123138fd1498Szrj
123238fd1498Szrj /* Do access-path based disambiguation. */
123338fd1498Szrj if (ref1 && ref2
123438fd1498Szrj && (handled_component_p (ref1) || handled_component_p (ref2)))
123538fd1498Szrj return aliasing_component_refs_p (ref1,
123638fd1498Szrj ref1_alias_set, base1_alias_set,
123738fd1498Szrj offset1, max_size1,
123838fd1498Szrj ref2,
123938fd1498Szrj ref2_alias_set, base2_alias_set,
124038fd1498Szrj offset2, max_size2, true);
124138fd1498Szrj
124238fd1498Szrj return true;
124338fd1498Szrj }
124438fd1498Szrj
124538fd1498Szrj /* Return true if two indirect references based on *PTR1
124638fd1498Szrj and *PTR2 constrained to [OFFSET1, OFFSET1 + MAX_SIZE1) and
124738fd1498Szrj [OFFSET2, OFFSET2 + MAX_SIZE2) may alias. *PTR1 and *PTR2 have
124838fd1498Szrj the alias sets BASE1_ALIAS_SET and BASE2_ALIAS_SET which can be -1
124938fd1498Szrj in which case they are computed on-demand. REF1 and REF2
125038fd1498Szrj if non-NULL are the complete memory reference trees. */
125138fd1498Szrj
125238fd1498Szrj static bool
indirect_refs_may_alias_p(tree ref1 ATTRIBUTE_UNUSED,tree base1,poly_int64 offset1,poly_int64 max_size1,alias_set_type ref1_alias_set,alias_set_type base1_alias_set,tree ref2 ATTRIBUTE_UNUSED,tree base2,poly_int64 offset2,poly_int64 max_size2,alias_set_type ref2_alias_set,alias_set_type base2_alias_set,bool tbaa_p)125338fd1498Szrj indirect_refs_may_alias_p (tree ref1 ATTRIBUTE_UNUSED, tree base1,
125438fd1498Szrj poly_int64 offset1, poly_int64 max_size1,
125538fd1498Szrj alias_set_type ref1_alias_set,
125638fd1498Szrj alias_set_type base1_alias_set,
125738fd1498Szrj tree ref2 ATTRIBUTE_UNUSED, tree base2,
125838fd1498Szrj poly_int64 offset2, poly_int64 max_size2,
125938fd1498Szrj alias_set_type ref2_alias_set,
126038fd1498Szrj alias_set_type base2_alias_set, bool tbaa_p)
126138fd1498Szrj {
126238fd1498Szrj tree ptr1;
126338fd1498Szrj tree ptr2;
126438fd1498Szrj tree ptrtype1, ptrtype2;
126538fd1498Szrj
126638fd1498Szrj gcc_checking_assert ((TREE_CODE (base1) == MEM_REF
126738fd1498Szrj || TREE_CODE (base1) == TARGET_MEM_REF)
126838fd1498Szrj && (TREE_CODE (base2) == MEM_REF
126938fd1498Szrj || TREE_CODE (base2) == TARGET_MEM_REF));
127038fd1498Szrj
127138fd1498Szrj ptr1 = TREE_OPERAND (base1, 0);
127238fd1498Szrj ptr2 = TREE_OPERAND (base2, 0);
127338fd1498Szrj
127438fd1498Szrj /* If both bases are based on pointers they cannot alias if they may not
127538fd1498Szrj point to the same memory object or if they point to the same object
127638fd1498Szrj and the accesses do not overlap. */
127738fd1498Szrj if ((!cfun || gimple_in_ssa_p (cfun))
127838fd1498Szrj && operand_equal_p (ptr1, ptr2, 0)
127938fd1498Szrj && (((TREE_CODE (base1) != TARGET_MEM_REF
128038fd1498Szrj || (!TMR_INDEX (base1) && !TMR_INDEX2 (base1)))
128138fd1498Szrj && (TREE_CODE (base2) != TARGET_MEM_REF
128238fd1498Szrj || (!TMR_INDEX (base2) && !TMR_INDEX2 (base2))))
128338fd1498Szrj || (TREE_CODE (base1) == TARGET_MEM_REF
128438fd1498Szrj && TREE_CODE (base2) == TARGET_MEM_REF
128538fd1498Szrj && (TMR_STEP (base1) == TMR_STEP (base2)
128638fd1498Szrj || (TMR_STEP (base1) && TMR_STEP (base2)
128738fd1498Szrj && operand_equal_p (TMR_STEP (base1),
128838fd1498Szrj TMR_STEP (base2), 0)))
128938fd1498Szrj && (TMR_INDEX (base1) == TMR_INDEX (base2)
129038fd1498Szrj || (TMR_INDEX (base1) && TMR_INDEX (base2)
129138fd1498Szrj && operand_equal_p (TMR_INDEX (base1),
129238fd1498Szrj TMR_INDEX (base2), 0)))
129338fd1498Szrj && (TMR_INDEX2 (base1) == TMR_INDEX2 (base2)
129438fd1498Szrj || (TMR_INDEX2 (base1) && TMR_INDEX2 (base2)
129538fd1498Szrj && operand_equal_p (TMR_INDEX2 (base1),
129638fd1498Szrj TMR_INDEX2 (base2), 0))))))
129738fd1498Szrj {
129838fd1498Szrj poly_offset_int moff1 = mem_ref_offset (base1) << LOG2_BITS_PER_UNIT;
129938fd1498Szrj poly_offset_int moff2 = mem_ref_offset (base2) << LOG2_BITS_PER_UNIT;
130038fd1498Szrj return ranges_maybe_overlap_p (offset1 + moff1, max_size1,
130138fd1498Szrj offset2 + moff2, max_size2);
130238fd1498Szrj }
130338fd1498Szrj if (!ptr_derefs_may_alias_p (ptr1, ptr2))
130438fd1498Szrj return false;
130538fd1498Szrj
130638fd1498Szrj /* Disambiguations that rely on strict aliasing rules follow. */
130738fd1498Szrj if (!flag_strict_aliasing || !tbaa_p)
130838fd1498Szrj return true;
130938fd1498Szrj
131038fd1498Szrj ptrtype1 = TREE_TYPE (TREE_OPERAND (base1, 1));
131138fd1498Szrj ptrtype2 = TREE_TYPE (TREE_OPERAND (base2, 1));
131238fd1498Szrj
131338fd1498Szrj /* If the alias set for a pointer access is zero all bets are off. */
131438fd1498Szrj if (base1_alias_set == 0
131538fd1498Szrj || base2_alias_set == 0)
131638fd1498Szrj return true;
131738fd1498Szrj
131838fd1498Szrj /* If both references are through the same type, they do not alias
131938fd1498Szrj if the accesses do not overlap. This does extra disambiguation
132038fd1498Szrj for mixed/pointer accesses but requires strict aliasing. */
132138fd1498Szrj if ((TREE_CODE (base1) != TARGET_MEM_REF
132238fd1498Szrj || (!TMR_INDEX (base1) && !TMR_INDEX2 (base1)))
132338fd1498Szrj && (TREE_CODE (base2) != TARGET_MEM_REF
132438fd1498Szrj || (!TMR_INDEX (base2) && !TMR_INDEX2 (base2)))
132538fd1498Szrj && same_type_for_tbaa (TREE_TYPE (base1), TREE_TYPE (ptrtype1)) == 1
132638fd1498Szrj && same_type_for_tbaa (TREE_TYPE (base2), TREE_TYPE (ptrtype2)) == 1
132738fd1498Szrj && same_type_for_tbaa (TREE_TYPE (ptrtype1),
132838fd1498Szrj TREE_TYPE (ptrtype2)) == 1
132938fd1498Szrj /* But avoid treating arrays as "objects", instead assume they
133038fd1498Szrj can overlap by an exact multiple of their element size. */
133138fd1498Szrj && TREE_CODE (TREE_TYPE (ptrtype1)) != ARRAY_TYPE)
133238fd1498Szrj return ranges_maybe_overlap_p (offset1, max_size1, offset2, max_size2);
133338fd1498Szrj
133438fd1498Szrj /* Do type-based disambiguation. */
133538fd1498Szrj if (base1_alias_set != base2_alias_set
133638fd1498Szrj && !alias_sets_conflict_p (base1_alias_set, base2_alias_set))
133738fd1498Szrj return false;
133838fd1498Szrj
133938fd1498Szrj /* If either reference is view-converted, give up now. */
134038fd1498Szrj if (same_type_for_tbaa (TREE_TYPE (base1), TREE_TYPE (ptrtype1)) != 1
134138fd1498Szrj || same_type_for_tbaa (TREE_TYPE (base2), TREE_TYPE (ptrtype2)) != 1)
134238fd1498Szrj return true;
134338fd1498Szrj
134438fd1498Szrj if (ref1 && ref2
134538fd1498Szrj && nonoverlapping_component_refs_p (ref1, ref2))
134638fd1498Szrj return false;
134738fd1498Szrj
134838fd1498Szrj /* Do access-path based disambiguation. */
134938fd1498Szrj if (ref1 && ref2
135038fd1498Szrj && (handled_component_p (ref1) || handled_component_p (ref2)))
135138fd1498Szrj return aliasing_component_refs_p (ref1,
135238fd1498Szrj ref1_alias_set, base1_alias_set,
135338fd1498Szrj offset1, max_size1,
135438fd1498Szrj ref2,
135538fd1498Szrj ref2_alias_set, base2_alias_set,
135638fd1498Szrj offset2, max_size2, false);
135738fd1498Szrj
135838fd1498Szrj return true;
135938fd1498Szrj }
136038fd1498Szrj
136138fd1498Szrj /* Return true, if the two memory references REF1 and REF2 may alias. */
136238fd1498Szrj
136338fd1498Szrj bool
refs_may_alias_p_1(ao_ref * ref1,ao_ref * ref2,bool tbaa_p)136438fd1498Szrj refs_may_alias_p_1 (ao_ref *ref1, ao_ref *ref2, bool tbaa_p)
136538fd1498Szrj {
136638fd1498Szrj tree base1, base2;
136738fd1498Szrj poly_int64 offset1 = 0, offset2 = 0;
136838fd1498Szrj poly_int64 max_size1 = -1, max_size2 = -1;
136938fd1498Szrj bool var1_p, var2_p, ind1_p, ind2_p;
137038fd1498Szrj
137138fd1498Szrj gcc_checking_assert ((!ref1->ref
137238fd1498Szrj || TREE_CODE (ref1->ref) == SSA_NAME
137338fd1498Szrj || DECL_P (ref1->ref)
137438fd1498Szrj || TREE_CODE (ref1->ref) == STRING_CST
137538fd1498Szrj || handled_component_p (ref1->ref)
137638fd1498Szrj || TREE_CODE (ref1->ref) == MEM_REF
137738fd1498Szrj || TREE_CODE (ref1->ref) == TARGET_MEM_REF)
137838fd1498Szrj && (!ref2->ref
137938fd1498Szrj || TREE_CODE (ref2->ref) == SSA_NAME
138038fd1498Szrj || DECL_P (ref2->ref)
138138fd1498Szrj || TREE_CODE (ref2->ref) == STRING_CST
138238fd1498Szrj || handled_component_p (ref2->ref)
138338fd1498Szrj || TREE_CODE (ref2->ref) == MEM_REF
138438fd1498Szrj || TREE_CODE (ref2->ref) == TARGET_MEM_REF));
138538fd1498Szrj
138638fd1498Szrj /* Decompose the references into their base objects and the access. */
138738fd1498Szrj base1 = ao_ref_base (ref1);
138838fd1498Szrj offset1 = ref1->offset;
138938fd1498Szrj max_size1 = ref1->max_size;
139038fd1498Szrj base2 = ao_ref_base (ref2);
139138fd1498Szrj offset2 = ref2->offset;
139238fd1498Szrj max_size2 = ref2->max_size;
139338fd1498Szrj
139438fd1498Szrj /* We can end up with registers or constants as bases for example from
139538fd1498Szrj *D.1663_44 = VIEW_CONVERT_EXPR<struct DB_LSN>(__tmp$B0F64_59);
139638fd1498Szrj which is seen as a struct copy. */
139738fd1498Szrj if (TREE_CODE (base1) == SSA_NAME
139838fd1498Szrj || TREE_CODE (base1) == CONST_DECL
139938fd1498Szrj || TREE_CODE (base1) == CONSTRUCTOR
140038fd1498Szrj || TREE_CODE (base1) == ADDR_EXPR
140138fd1498Szrj || CONSTANT_CLASS_P (base1)
140238fd1498Szrj || TREE_CODE (base2) == SSA_NAME
140338fd1498Szrj || TREE_CODE (base2) == CONST_DECL
140438fd1498Szrj || TREE_CODE (base2) == CONSTRUCTOR
140538fd1498Szrj || TREE_CODE (base2) == ADDR_EXPR
140638fd1498Szrj || CONSTANT_CLASS_P (base2))
140738fd1498Szrj return false;
140838fd1498Szrj
140938fd1498Szrj /* We can end up referring to code via function and label decls.
141038fd1498Szrj As we likely do not properly track code aliases conservatively
141138fd1498Szrj bail out. */
141238fd1498Szrj if (TREE_CODE (base1) == FUNCTION_DECL
141338fd1498Szrj || TREE_CODE (base1) == LABEL_DECL
141438fd1498Szrj || TREE_CODE (base2) == FUNCTION_DECL
141538fd1498Szrj || TREE_CODE (base2) == LABEL_DECL)
141638fd1498Szrj return true;
141738fd1498Szrj
141838fd1498Szrj /* Two volatile accesses always conflict. */
141938fd1498Szrj if (ref1->volatile_p
142038fd1498Szrj && ref2->volatile_p)
142138fd1498Szrj return true;
142238fd1498Szrj
142338fd1498Szrj /* Defer to simple offset based disambiguation if we have
142438fd1498Szrj references based on two decls. Do this before defering to
142538fd1498Szrj TBAA to handle must-alias cases in conformance with the
142638fd1498Szrj GCC extension of allowing type-punning through unions. */
142738fd1498Szrj var1_p = DECL_P (base1);
142838fd1498Szrj var2_p = DECL_P (base2);
142938fd1498Szrj if (var1_p && var2_p)
143038fd1498Szrj return decl_refs_may_alias_p (ref1->ref, base1, offset1, max_size1,
143138fd1498Szrj ref2->ref, base2, offset2, max_size2);
143238fd1498Szrj
143338fd1498Szrj /* Handle restrict based accesses.
143438fd1498Szrj ??? ao_ref_base strips inner MEM_REF [&decl], recover from that
143538fd1498Szrj here. */
143638fd1498Szrj tree rbase1 = base1;
143738fd1498Szrj tree rbase2 = base2;
143838fd1498Szrj if (var1_p)
143938fd1498Szrj {
144038fd1498Szrj rbase1 = ref1->ref;
144138fd1498Szrj if (rbase1)
144238fd1498Szrj while (handled_component_p (rbase1))
144338fd1498Szrj rbase1 = TREE_OPERAND (rbase1, 0);
144438fd1498Szrj }
144538fd1498Szrj if (var2_p)
144638fd1498Szrj {
144738fd1498Szrj rbase2 = ref2->ref;
144838fd1498Szrj if (rbase2)
144938fd1498Szrj while (handled_component_p (rbase2))
145038fd1498Szrj rbase2 = TREE_OPERAND (rbase2, 0);
145138fd1498Szrj }
145238fd1498Szrj if (rbase1 && rbase2
145338fd1498Szrj && (TREE_CODE (base1) == MEM_REF || TREE_CODE (base1) == TARGET_MEM_REF)
145438fd1498Szrj && (TREE_CODE (base2) == MEM_REF || TREE_CODE (base2) == TARGET_MEM_REF)
145538fd1498Szrj /* If the accesses are in the same restrict clique... */
145638fd1498Szrj && MR_DEPENDENCE_CLIQUE (base1) == MR_DEPENDENCE_CLIQUE (base2)
145738fd1498Szrj /* But based on different pointers they do not alias. */
145838fd1498Szrj && MR_DEPENDENCE_BASE (base1) != MR_DEPENDENCE_BASE (base2))
145938fd1498Szrj return false;
146038fd1498Szrj
146138fd1498Szrj ind1_p = (TREE_CODE (base1) == MEM_REF
146238fd1498Szrj || TREE_CODE (base1) == TARGET_MEM_REF);
146338fd1498Szrj ind2_p = (TREE_CODE (base2) == MEM_REF
146438fd1498Szrj || TREE_CODE (base2) == TARGET_MEM_REF);
146538fd1498Szrj
146638fd1498Szrj /* Canonicalize the pointer-vs-decl case. */
146738fd1498Szrj if (ind1_p && var2_p)
146838fd1498Szrj {
146938fd1498Szrj std::swap (offset1, offset2);
147038fd1498Szrj std::swap (max_size1, max_size2);
147138fd1498Szrj std::swap (base1, base2);
147238fd1498Szrj std::swap (ref1, ref2);
147338fd1498Szrj var1_p = true;
147438fd1498Szrj ind1_p = false;
147538fd1498Szrj var2_p = false;
147638fd1498Szrj ind2_p = true;
147738fd1498Szrj }
147838fd1498Szrj
147938fd1498Szrj /* First defer to TBAA if possible. */
148038fd1498Szrj if (tbaa_p
148138fd1498Szrj && flag_strict_aliasing
148238fd1498Szrj && !alias_sets_conflict_p (ao_ref_alias_set (ref1),
148338fd1498Szrj ao_ref_alias_set (ref2)))
148438fd1498Szrj return false;
148538fd1498Szrj
148638fd1498Szrj /* Dispatch to the pointer-vs-decl or pointer-vs-pointer disambiguators. */
148738fd1498Szrj if (var1_p && ind2_p)
148838fd1498Szrj return indirect_ref_may_alias_decl_p (ref2->ref, base2,
148938fd1498Szrj offset2, max_size2,
149038fd1498Szrj ao_ref_alias_set (ref2),
149138fd1498Szrj ao_ref_base_alias_set (ref2),
149238fd1498Szrj ref1->ref, base1,
149338fd1498Szrj offset1, max_size1,
149438fd1498Szrj ao_ref_alias_set (ref1),
149538fd1498Szrj ao_ref_base_alias_set (ref1),
149638fd1498Szrj tbaa_p);
149738fd1498Szrj else if (ind1_p && ind2_p)
149838fd1498Szrj return indirect_refs_may_alias_p (ref1->ref, base1,
149938fd1498Szrj offset1, max_size1,
150038fd1498Szrj ao_ref_alias_set (ref1),
150138fd1498Szrj ao_ref_base_alias_set (ref1),
150238fd1498Szrj ref2->ref, base2,
150338fd1498Szrj offset2, max_size2,
150438fd1498Szrj ao_ref_alias_set (ref2),
150538fd1498Szrj ao_ref_base_alias_set (ref2),
150638fd1498Szrj tbaa_p);
150738fd1498Szrj
150838fd1498Szrj gcc_unreachable ();
150938fd1498Szrj }
151038fd1498Szrj
151138fd1498Szrj static bool
refs_may_alias_p(tree ref1,ao_ref * ref2)151238fd1498Szrj refs_may_alias_p (tree ref1, ao_ref *ref2)
151338fd1498Szrj {
151438fd1498Szrj ao_ref r1;
151538fd1498Szrj ao_ref_init (&r1, ref1);
151638fd1498Szrj return refs_may_alias_p_1 (&r1, ref2, true);
151738fd1498Szrj }
151838fd1498Szrj
151938fd1498Szrj bool
refs_may_alias_p(tree ref1,tree ref2)152038fd1498Szrj refs_may_alias_p (tree ref1, tree ref2)
152138fd1498Szrj {
152238fd1498Szrj ao_ref r1, r2;
152338fd1498Szrj bool res;
152438fd1498Szrj ao_ref_init (&r1, ref1);
152538fd1498Szrj ao_ref_init (&r2, ref2);
152638fd1498Szrj res = refs_may_alias_p_1 (&r1, &r2, true);
152738fd1498Szrj if (res)
152838fd1498Szrj ++alias_stats.refs_may_alias_p_may_alias;
152938fd1498Szrj else
153038fd1498Szrj ++alias_stats.refs_may_alias_p_no_alias;
153138fd1498Szrj return res;
153238fd1498Szrj }
153338fd1498Szrj
153438fd1498Szrj /* Returns true if there is a anti-dependence for the STORE that
153538fd1498Szrj executes after the LOAD. */
153638fd1498Szrj
153738fd1498Szrj bool
refs_anti_dependent_p(tree load,tree store)153838fd1498Szrj refs_anti_dependent_p (tree load, tree store)
153938fd1498Szrj {
154038fd1498Szrj ao_ref r1, r2;
154138fd1498Szrj ao_ref_init (&r1, load);
154238fd1498Szrj ao_ref_init (&r2, store);
154338fd1498Szrj return refs_may_alias_p_1 (&r1, &r2, false);
154438fd1498Szrj }
154538fd1498Szrj
154638fd1498Szrj /* Returns true if there is a output dependence for the stores
154738fd1498Szrj STORE1 and STORE2. */
154838fd1498Szrj
154938fd1498Szrj bool
refs_output_dependent_p(tree store1,tree store2)155038fd1498Szrj refs_output_dependent_p (tree store1, tree store2)
155138fd1498Szrj {
155238fd1498Szrj ao_ref r1, r2;
155338fd1498Szrj ao_ref_init (&r1, store1);
155438fd1498Szrj ao_ref_init (&r2, store2);
155538fd1498Szrj return refs_may_alias_p_1 (&r1, &r2, false);
155638fd1498Szrj }
155738fd1498Szrj
155838fd1498Szrj /* If the call CALL may use the memory reference REF return true,
155938fd1498Szrj otherwise return false. */
156038fd1498Szrj
156138fd1498Szrj static bool
ref_maybe_used_by_call_p_1(gcall * call,ao_ref * ref)156238fd1498Szrj ref_maybe_used_by_call_p_1 (gcall *call, ao_ref *ref)
156338fd1498Szrj {
156438fd1498Szrj tree base, callee;
156538fd1498Szrj unsigned i;
156638fd1498Szrj int flags = gimple_call_flags (call);
156738fd1498Szrj
156838fd1498Szrj /* Const functions without a static chain do not implicitly use memory. */
156938fd1498Szrj if (!gimple_call_chain (call)
157038fd1498Szrj && (flags & (ECF_CONST|ECF_NOVOPS)))
157138fd1498Szrj goto process_args;
157238fd1498Szrj
157338fd1498Szrj base = ao_ref_base (ref);
157438fd1498Szrj if (!base)
157538fd1498Szrj return true;
157638fd1498Szrj
157738fd1498Szrj /* A call that is not without side-effects might involve volatile
157838fd1498Szrj accesses and thus conflicts with all other volatile accesses. */
157938fd1498Szrj if (ref->volatile_p)
158038fd1498Szrj return true;
158138fd1498Szrj
158238fd1498Szrj /* If the reference is based on a decl that is not aliased the call
158338fd1498Szrj cannot possibly use it. */
158438fd1498Szrj if (DECL_P (base)
158538fd1498Szrj && !may_be_aliased (base)
158638fd1498Szrj /* But local statics can be used through recursion. */
158738fd1498Szrj && !is_global_var (base))
158838fd1498Szrj goto process_args;
158938fd1498Szrj
159038fd1498Szrj callee = gimple_call_fndecl (call);
159138fd1498Szrj
159238fd1498Szrj /* Handle those builtin functions explicitly that do not act as
159338fd1498Szrj escape points. See tree-ssa-structalias.c:find_func_aliases
159438fd1498Szrj for the list of builtins we might need to handle here. */
159538fd1498Szrj if (callee != NULL_TREE
159638fd1498Szrj && gimple_call_builtin_p (call, BUILT_IN_NORMAL))
159738fd1498Szrj switch (DECL_FUNCTION_CODE (callee))
159838fd1498Szrj {
159938fd1498Szrj /* All the following functions read memory pointed to by
160038fd1498Szrj their second argument. strcat/strncat additionally
160138fd1498Szrj reads memory pointed to by the first argument. */
160238fd1498Szrj case BUILT_IN_STRCAT:
160338fd1498Szrj case BUILT_IN_STRNCAT:
160438fd1498Szrj {
160538fd1498Szrj ao_ref dref;
160638fd1498Szrj ao_ref_init_from_ptr_and_size (&dref,
160738fd1498Szrj gimple_call_arg (call, 0),
160838fd1498Szrj NULL_TREE);
160938fd1498Szrj if (refs_may_alias_p_1 (&dref, ref, false))
161038fd1498Szrj return true;
161138fd1498Szrj }
161238fd1498Szrj /* FALLTHRU */
161338fd1498Szrj case BUILT_IN_STRCPY:
161438fd1498Szrj case BUILT_IN_STRNCPY:
161538fd1498Szrj case BUILT_IN_MEMCPY:
161638fd1498Szrj case BUILT_IN_MEMMOVE:
161738fd1498Szrj case BUILT_IN_MEMPCPY:
161838fd1498Szrj case BUILT_IN_STPCPY:
161938fd1498Szrj case BUILT_IN_STPNCPY:
162038fd1498Szrj case BUILT_IN_TM_MEMCPY:
162138fd1498Szrj case BUILT_IN_TM_MEMMOVE:
162238fd1498Szrj {
162338fd1498Szrj ao_ref dref;
162438fd1498Szrj tree size = NULL_TREE;
162538fd1498Szrj if (gimple_call_num_args (call) == 3)
162638fd1498Szrj size = gimple_call_arg (call, 2);
162738fd1498Szrj ao_ref_init_from_ptr_and_size (&dref,
162838fd1498Szrj gimple_call_arg (call, 1),
162938fd1498Szrj size);
163038fd1498Szrj return refs_may_alias_p_1 (&dref, ref, false);
163138fd1498Szrj }
163238fd1498Szrj case BUILT_IN_STRCAT_CHK:
163338fd1498Szrj case BUILT_IN_STRNCAT_CHK:
163438fd1498Szrj {
163538fd1498Szrj ao_ref dref;
163638fd1498Szrj ao_ref_init_from_ptr_and_size (&dref,
163738fd1498Szrj gimple_call_arg (call, 0),
163838fd1498Szrj NULL_TREE);
163938fd1498Szrj if (refs_may_alias_p_1 (&dref, ref, false))
164038fd1498Szrj return true;
164138fd1498Szrj }
164238fd1498Szrj /* FALLTHRU */
164338fd1498Szrj case BUILT_IN_STRCPY_CHK:
164438fd1498Szrj case BUILT_IN_STRNCPY_CHK:
164538fd1498Szrj case BUILT_IN_MEMCPY_CHK:
164638fd1498Szrj case BUILT_IN_MEMMOVE_CHK:
164738fd1498Szrj case BUILT_IN_MEMPCPY_CHK:
164838fd1498Szrj case BUILT_IN_STPCPY_CHK:
164938fd1498Szrj case BUILT_IN_STPNCPY_CHK:
165038fd1498Szrj {
165138fd1498Szrj ao_ref dref;
165238fd1498Szrj tree size = NULL_TREE;
165338fd1498Szrj if (gimple_call_num_args (call) == 4)
165438fd1498Szrj size = gimple_call_arg (call, 2);
165538fd1498Szrj ao_ref_init_from_ptr_and_size (&dref,
165638fd1498Szrj gimple_call_arg (call, 1),
165738fd1498Szrj size);
165838fd1498Szrj return refs_may_alias_p_1 (&dref, ref, false);
165938fd1498Szrj }
166038fd1498Szrj case BUILT_IN_BCOPY:
166138fd1498Szrj {
166238fd1498Szrj ao_ref dref;
166338fd1498Szrj tree size = gimple_call_arg (call, 2);
166438fd1498Szrj ao_ref_init_from_ptr_and_size (&dref,
166538fd1498Szrj gimple_call_arg (call, 0),
166638fd1498Szrj size);
166738fd1498Szrj return refs_may_alias_p_1 (&dref, ref, false);
166838fd1498Szrj }
166938fd1498Szrj
167038fd1498Szrj /* The following functions read memory pointed to by their
167138fd1498Szrj first argument. */
167238fd1498Szrj CASE_BUILT_IN_TM_LOAD (1):
167338fd1498Szrj CASE_BUILT_IN_TM_LOAD (2):
167438fd1498Szrj CASE_BUILT_IN_TM_LOAD (4):
167538fd1498Szrj CASE_BUILT_IN_TM_LOAD (8):
167638fd1498Szrj CASE_BUILT_IN_TM_LOAD (FLOAT):
167738fd1498Szrj CASE_BUILT_IN_TM_LOAD (DOUBLE):
167838fd1498Szrj CASE_BUILT_IN_TM_LOAD (LDOUBLE):
167938fd1498Szrj CASE_BUILT_IN_TM_LOAD (M64):
168038fd1498Szrj CASE_BUILT_IN_TM_LOAD (M128):
168138fd1498Szrj CASE_BUILT_IN_TM_LOAD (M256):
168238fd1498Szrj case BUILT_IN_TM_LOG:
168338fd1498Szrj case BUILT_IN_TM_LOG_1:
168438fd1498Szrj case BUILT_IN_TM_LOG_2:
168538fd1498Szrj case BUILT_IN_TM_LOG_4:
168638fd1498Szrj case BUILT_IN_TM_LOG_8:
168738fd1498Szrj case BUILT_IN_TM_LOG_FLOAT:
168838fd1498Szrj case BUILT_IN_TM_LOG_DOUBLE:
168938fd1498Szrj case BUILT_IN_TM_LOG_LDOUBLE:
169038fd1498Szrj case BUILT_IN_TM_LOG_M64:
169138fd1498Szrj case BUILT_IN_TM_LOG_M128:
169238fd1498Szrj case BUILT_IN_TM_LOG_M256:
169338fd1498Szrj return ptr_deref_may_alias_ref_p_1 (gimple_call_arg (call, 0), ref);
169438fd1498Szrj
169538fd1498Szrj /* These read memory pointed to by the first argument. */
169638fd1498Szrj case BUILT_IN_STRDUP:
169738fd1498Szrj case BUILT_IN_STRNDUP:
169838fd1498Szrj case BUILT_IN_REALLOC:
169938fd1498Szrj {
170038fd1498Szrj ao_ref dref;
170138fd1498Szrj tree size = NULL_TREE;
170238fd1498Szrj if (gimple_call_num_args (call) == 2)
170338fd1498Szrj size = gimple_call_arg (call, 1);
170438fd1498Szrj ao_ref_init_from_ptr_and_size (&dref,
170538fd1498Szrj gimple_call_arg (call, 0),
170638fd1498Szrj size);
170738fd1498Szrj return refs_may_alias_p_1 (&dref, ref, false);
170838fd1498Szrj }
170938fd1498Szrj /* These read memory pointed to by the first argument. */
171038fd1498Szrj case BUILT_IN_INDEX:
171138fd1498Szrj case BUILT_IN_STRCHR:
171238fd1498Szrj case BUILT_IN_STRRCHR:
171338fd1498Szrj {
171438fd1498Szrj ao_ref dref;
171538fd1498Szrj ao_ref_init_from_ptr_and_size (&dref,
171638fd1498Szrj gimple_call_arg (call, 0),
171738fd1498Szrj NULL_TREE);
171838fd1498Szrj return refs_may_alias_p_1 (&dref, ref, false);
171938fd1498Szrj }
172038fd1498Szrj /* These read memory pointed to by the first argument with size
172138fd1498Szrj in the third argument. */
172238fd1498Szrj case BUILT_IN_MEMCHR:
172338fd1498Szrj {
172438fd1498Szrj ao_ref dref;
172538fd1498Szrj ao_ref_init_from_ptr_and_size (&dref,
172638fd1498Szrj gimple_call_arg (call, 0),
172738fd1498Szrj gimple_call_arg (call, 2));
172838fd1498Szrj return refs_may_alias_p_1 (&dref, ref, false);
172938fd1498Szrj }
173038fd1498Szrj /* These read memory pointed to by the first and second arguments. */
173138fd1498Szrj case BUILT_IN_STRSTR:
173238fd1498Szrj case BUILT_IN_STRPBRK:
173338fd1498Szrj {
173438fd1498Szrj ao_ref dref;
173538fd1498Szrj ao_ref_init_from_ptr_and_size (&dref,
173638fd1498Szrj gimple_call_arg (call, 0),
173738fd1498Szrj NULL_TREE);
173838fd1498Szrj if (refs_may_alias_p_1 (&dref, ref, false))
173938fd1498Szrj return true;
174038fd1498Szrj ao_ref_init_from_ptr_and_size (&dref,
174138fd1498Szrj gimple_call_arg (call, 1),
174238fd1498Szrj NULL_TREE);
174338fd1498Szrj return refs_may_alias_p_1 (&dref, ref, false);
174438fd1498Szrj }
174538fd1498Szrj
174638fd1498Szrj /* The following builtins do not read from memory. */
174738fd1498Szrj case BUILT_IN_FREE:
174838fd1498Szrj case BUILT_IN_MALLOC:
174938fd1498Szrj case BUILT_IN_POSIX_MEMALIGN:
175038fd1498Szrj case BUILT_IN_ALIGNED_ALLOC:
175138fd1498Szrj case BUILT_IN_CALLOC:
175238fd1498Szrj CASE_BUILT_IN_ALLOCA:
175338fd1498Szrj case BUILT_IN_STACK_SAVE:
175438fd1498Szrj case BUILT_IN_STACK_RESTORE:
175538fd1498Szrj case BUILT_IN_MEMSET:
175638fd1498Szrj case BUILT_IN_TM_MEMSET:
175738fd1498Szrj case BUILT_IN_MEMSET_CHK:
175838fd1498Szrj case BUILT_IN_FREXP:
175938fd1498Szrj case BUILT_IN_FREXPF:
176038fd1498Szrj case BUILT_IN_FREXPL:
176138fd1498Szrj case BUILT_IN_GAMMA_R:
176238fd1498Szrj case BUILT_IN_GAMMAF_R:
176338fd1498Szrj case BUILT_IN_GAMMAL_R:
176438fd1498Szrj case BUILT_IN_LGAMMA_R:
176538fd1498Szrj case BUILT_IN_LGAMMAF_R:
176638fd1498Szrj case BUILT_IN_LGAMMAL_R:
176738fd1498Szrj case BUILT_IN_MODF:
176838fd1498Szrj case BUILT_IN_MODFF:
176938fd1498Szrj case BUILT_IN_MODFL:
177038fd1498Szrj case BUILT_IN_REMQUO:
177138fd1498Szrj case BUILT_IN_REMQUOF:
177238fd1498Szrj case BUILT_IN_REMQUOL:
177338fd1498Szrj case BUILT_IN_SINCOS:
177438fd1498Szrj case BUILT_IN_SINCOSF:
177538fd1498Szrj case BUILT_IN_SINCOSL:
177638fd1498Szrj case BUILT_IN_ASSUME_ALIGNED:
177738fd1498Szrj case BUILT_IN_VA_END:
177838fd1498Szrj return false;
177938fd1498Szrj /* __sync_* builtins and some OpenMP builtins act as threading
178038fd1498Szrj barriers. */
178138fd1498Szrj #undef DEF_SYNC_BUILTIN
178238fd1498Szrj #define DEF_SYNC_BUILTIN(ENUM, NAME, TYPE, ATTRS) case ENUM:
178338fd1498Szrj #include "sync-builtins.def"
178438fd1498Szrj #undef DEF_SYNC_BUILTIN
178538fd1498Szrj case BUILT_IN_GOMP_ATOMIC_START:
178638fd1498Szrj case BUILT_IN_GOMP_ATOMIC_END:
178738fd1498Szrj case BUILT_IN_GOMP_BARRIER:
178838fd1498Szrj case BUILT_IN_GOMP_BARRIER_CANCEL:
178938fd1498Szrj case BUILT_IN_GOMP_TASKWAIT:
179038fd1498Szrj case BUILT_IN_GOMP_TASKGROUP_END:
179138fd1498Szrj case BUILT_IN_GOMP_CRITICAL_START:
179238fd1498Szrj case BUILT_IN_GOMP_CRITICAL_END:
179338fd1498Szrj case BUILT_IN_GOMP_CRITICAL_NAME_START:
179438fd1498Szrj case BUILT_IN_GOMP_CRITICAL_NAME_END:
179538fd1498Szrj case BUILT_IN_GOMP_LOOP_END:
179638fd1498Szrj case BUILT_IN_GOMP_LOOP_END_CANCEL:
179738fd1498Szrj case BUILT_IN_GOMP_ORDERED_START:
179838fd1498Szrj case BUILT_IN_GOMP_ORDERED_END:
179938fd1498Szrj case BUILT_IN_GOMP_SECTIONS_END:
180038fd1498Szrj case BUILT_IN_GOMP_SECTIONS_END_CANCEL:
180138fd1498Szrj case BUILT_IN_GOMP_SINGLE_COPY_START:
180238fd1498Szrj case BUILT_IN_GOMP_SINGLE_COPY_END:
180338fd1498Szrj return true;
180438fd1498Szrj
180538fd1498Szrj default:
180638fd1498Szrj /* Fallthru to general call handling. */;
180738fd1498Szrj }
180838fd1498Szrj
180938fd1498Szrj /* Check if base is a global static variable that is not read
181038fd1498Szrj by the function. */
181138fd1498Szrj if (callee != NULL_TREE && VAR_P (base) && TREE_STATIC (base))
181238fd1498Szrj {
181338fd1498Szrj struct cgraph_node *node = cgraph_node::get (callee);
181438fd1498Szrj bitmap not_read;
181538fd1498Szrj
181638fd1498Szrj /* FIXME: Callee can be an OMP builtin that does not have a call graph
181738fd1498Szrj node yet. We should enforce that there are nodes for all decls in the
181838fd1498Szrj IL and remove this check instead. */
181938fd1498Szrj if (node
182038fd1498Szrj && (not_read = ipa_reference_get_not_read_global (node))
182138fd1498Szrj && bitmap_bit_p (not_read, ipa_reference_var_uid (base)))
182238fd1498Szrj goto process_args;
182338fd1498Szrj }
182438fd1498Szrj
182538fd1498Szrj /* Check if the base variable is call-used. */
182638fd1498Szrj if (DECL_P (base))
182738fd1498Szrj {
182838fd1498Szrj if (pt_solution_includes (gimple_call_use_set (call), base))
182938fd1498Szrj return true;
183038fd1498Szrj }
183138fd1498Szrj else if ((TREE_CODE (base) == MEM_REF
183238fd1498Szrj || TREE_CODE (base) == TARGET_MEM_REF)
183338fd1498Szrj && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
183438fd1498Szrj {
183538fd1498Szrj struct ptr_info_def *pi = SSA_NAME_PTR_INFO (TREE_OPERAND (base, 0));
183638fd1498Szrj if (!pi)
183738fd1498Szrj return true;
183838fd1498Szrj
183938fd1498Szrj if (pt_solutions_intersect (gimple_call_use_set (call), &pi->pt))
184038fd1498Szrj return true;
184138fd1498Szrj }
184238fd1498Szrj else
184338fd1498Szrj return true;
184438fd1498Szrj
184538fd1498Szrj /* Inspect call arguments for passed-by-value aliases. */
184638fd1498Szrj process_args:
184738fd1498Szrj for (i = 0; i < gimple_call_num_args (call); ++i)
184838fd1498Szrj {
184938fd1498Szrj tree op = gimple_call_arg (call, i);
185038fd1498Szrj int flags = gimple_call_arg_flags (call, i);
185138fd1498Szrj
185238fd1498Szrj if (flags & EAF_UNUSED)
185338fd1498Szrj continue;
185438fd1498Szrj
185538fd1498Szrj if (TREE_CODE (op) == WITH_SIZE_EXPR)
185638fd1498Szrj op = TREE_OPERAND (op, 0);
185738fd1498Szrj
185838fd1498Szrj if (TREE_CODE (op) != SSA_NAME
185938fd1498Szrj && !is_gimple_min_invariant (op))
186038fd1498Szrj {
186138fd1498Szrj ao_ref r;
186238fd1498Szrj ao_ref_init (&r, op);
186338fd1498Szrj if (refs_may_alias_p_1 (&r, ref, true))
186438fd1498Szrj return true;
186538fd1498Szrj }
186638fd1498Szrj }
186738fd1498Szrj
186838fd1498Szrj return false;
186938fd1498Szrj }
187038fd1498Szrj
187138fd1498Szrj static bool
ref_maybe_used_by_call_p(gcall * call,ao_ref * ref)187238fd1498Szrj ref_maybe_used_by_call_p (gcall *call, ao_ref *ref)
187338fd1498Szrj {
187438fd1498Szrj bool res;
187538fd1498Szrj res = ref_maybe_used_by_call_p_1 (call, ref);
187638fd1498Szrj if (res)
187738fd1498Szrj ++alias_stats.ref_maybe_used_by_call_p_may_alias;
187838fd1498Szrj else
187938fd1498Szrj ++alias_stats.ref_maybe_used_by_call_p_no_alias;
188038fd1498Szrj return res;
188138fd1498Szrj }
188238fd1498Szrj
188338fd1498Szrj
188438fd1498Szrj /* If the statement STMT may use the memory reference REF return
188538fd1498Szrj true, otherwise return false. */
188638fd1498Szrj
188738fd1498Szrj bool
ref_maybe_used_by_stmt_p(gimple * stmt,ao_ref * ref)188838fd1498Szrj ref_maybe_used_by_stmt_p (gimple *stmt, ao_ref *ref)
188938fd1498Szrj {
189038fd1498Szrj if (is_gimple_assign (stmt))
189138fd1498Szrj {
189238fd1498Szrj tree rhs;
189338fd1498Szrj
189438fd1498Szrj /* All memory assign statements are single. */
189538fd1498Szrj if (!gimple_assign_single_p (stmt))
189638fd1498Szrj return false;
189738fd1498Szrj
189838fd1498Szrj rhs = gimple_assign_rhs1 (stmt);
189938fd1498Szrj if (is_gimple_reg (rhs)
190038fd1498Szrj || is_gimple_min_invariant (rhs)
190138fd1498Szrj || gimple_assign_rhs_code (stmt) == CONSTRUCTOR)
190238fd1498Szrj return false;
190338fd1498Szrj
190438fd1498Szrj return refs_may_alias_p (rhs, ref);
190538fd1498Szrj }
190638fd1498Szrj else if (is_gimple_call (stmt))
190738fd1498Szrj return ref_maybe_used_by_call_p (as_a <gcall *> (stmt), ref);
190838fd1498Szrj else if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
190938fd1498Szrj {
191038fd1498Szrj tree retval = gimple_return_retval (return_stmt);
191138fd1498Szrj if (retval
191238fd1498Szrj && TREE_CODE (retval) != SSA_NAME
191338fd1498Szrj && !is_gimple_min_invariant (retval)
191438fd1498Szrj && refs_may_alias_p (retval, ref))
191538fd1498Szrj return true;
191638fd1498Szrj /* If ref escapes the function then the return acts as a use. */
191738fd1498Szrj tree base = ao_ref_base (ref);
191838fd1498Szrj if (!base)
191938fd1498Szrj ;
192038fd1498Szrj else if (DECL_P (base))
192138fd1498Szrj return is_global_var (base);
192238fd1498Szrj else if (TREE_CODE (base) == MEM_REF
192338fd1498Szrj || TREE_CODE (base) == TARGET_MEM_REF)
192438fd1498Szrj return ptr_deref_may_alias_global_p (TREE_OPERAND (base, 0));
192538fd1498Szrj return false;
192638fd1498Szrj }
192738fd1498Szrj
192838fd1498Szrj return true;
192938fd1498Szrj }
193038fd1498Szrj
193138fd1498Szrj bool
ref_maybe_used_by_stmt_p(gimple * stmt,tree ref)193238fd1498Szrj ref_maybe_used_by_stmt_p (gimple *stmt, tree ref)
193338fd1498Szrj {
193438fd1498Szrj ao_ref r;
193538fd1498Szrj ao_ref_init (&r, ref);
193638fd1498Szrj return ref_maybe_used_by_stmt_p (stmt, &r);
193738fd1498Szrj }
193838fd1498Szrj
193938fd1498Szrj /* If the call in statement CALL may clobber the memory reference REF
194038fd1498Szrj return true, otherwise return false. */
194138fd1498Szrj
194238fd1498Szrj bool
call_may_clobber_ref_p_1(gcall * call,ao_ref * ref)194338fd1498Szrj call_may_clobber_ref_p_1 (gcall *call, ao_ref *ref)
194438fd1498Szrj {
194538fd1498Szrj tree base;
194638fd1498Szrj tree callee;
194738fd1498Szrj
194838fd1498Szrj /* If the call is pure or const it cannot clobber anything. */
194938fd1498Szrj if (gimple_call_flags (call)
195038fd1498Szrj & (ECF_PURE|ECF_CONST|ECF_LOOPING_CONST_OR_PURE|ECF_NOVOPS))
195138fd1498Szrj return false;
195238fd1498Szrj if (gimple_call_internal_p (call))
195338fd1498Szrj switch (gimple_call_internal_fn (call))
195438fd1498Szrj {
195538fd1498Szrj /* Treat these internal calls like ECF_PURE for aliasing,
195638fd1498Szrj they don't write to any memory the program should care about.
195738fd1498Szrj They have important other side-effects, and read memory,
195838fd1498Szrj so can't be ECF_NOVOPS. */
195938fd1498Szrj case IFN_UBSAN_NULL:
196038fd1498Szrj case IFN_UBSAN_BOUNDS:
196138fd1498Szrj case IFN_UBSAN_VPTR:
196238fd1498Szrj case IFN_UBSAN_OBJECT_SIZE:
196338fd1498Szrj case IFN_UBSAN_PTR:
196438fd1498Szrj case IFN_ASAN_CHECK:
196538fd1498Szrj return false;
196638fd1498Szrj default:
196738fd1498Szrj break;
196838fd1498Szrj }
196938fd1498Szrj
197038fd1498Szrj base = ao_ref_base (ref);
197138fd1498Szrj if (!base)
197238fd1498Szrj return true;
197338fd1498Szrj
197438fd1498Szrj if (TREE_CODE (base) == SSA_NAME
197538fd1498Szrj || CONSTANT_CLASS_P (base))
197638fd1498Szrj return false;
197738fd1498Szrj
197838fd1498Szrj /* A call that is not without side-effects might involve volatile
197938fd1498Szrj accesses and thus conflicts with all other volatile accesses. */
198038fd1498Szrj if (ref->volatile_p)
198138fd1498Szrj return true;
198238fd1498Szrj
198338fd1498Szrj /* If the reference is based on a decl that is not aliased the call
198438fd1498Szrj cannot possibly clobber it. */
198538fd1498Szrj if (DECL_P (base)
198638fd1498Szrj && !may_be_aliased (base)
198738fd1498Szrj /* But local non-readonly statics can be modified through recursion
198838fd1498Szrj or the call may implement a threading barrier which we must
198938fd1498Szrj treat as may-def. */
199038fd1498Szrj && (TREE_READONLY (base)
199138fd1498Szrj || !is_global_var (base)))
199238fd1498Szrj return false;
199338fd1498Szrj
199438fd1498Szrj callee = gimple_call_fndecl (call);
199538fd1498Szrj
199638fd1498Szrj /* Handle those builtin functions explicitly that do not act as
199738fd1498Szrj escape points. See tree-ssa-structalias.c:find_func_aliases
199838fd1498Szrj for the list of builtins we might need to handle here. */
199938fd1498Szrj if (callee != NULL_TREE
200038fd1498Szrj && gimple_call_builtin_p (call, BUILT_IN_NORMAL))
200138fd1498Szrj switch (DECL_FUNCTION_CODE (callee))
200238fd1498Szrj {
200338fd1498Szrj /* All the following functions clobber memory pointed to by
200438fd1498Szrj their first argument. */
200538fd1498Szrj case BUILT_IN_STRCPY:
200638fd1498Szrj case BUILT_IN_STRNCPY:
200738fd1498Szrj case BUILT_IN_MEMCPY:
200838fd1498Szrj case BUILT_IN_MEMMOVE:
200938fd1498Szrj case BUILT_IN_MEMPCPY:
201038fd1498Szrj case BUILT_IN_STPCPY:
201138fd1498Szrj case BUILT_IN_STPNCPY:
201238fd1498Szrj case BUILT_IN_STRCAT:
201338fd1498Szrj case BUILT_IN_STRNCAT:
201438fd1498Szrj case BUILT_IN_MEMSET:
201538fd1498Szrj case BUILT_IN_TM_MEMSET:
201638fd1498Szrj CASE_BUILT_IN_TM_STORE (1):
201738fd1498Szrj CASE_BUILT_IN_TM_STORE (2):
201838fd1498Szrj CASE_BUILT_IN_TM_STORE (4):
201938fd1498Szrj CASE_BUILT_IN_TM_STORE (8):
202038fd1498Szrj CASE_BUILT_IN_TM_STORE (FLOAT):
202138fd1498Szrj CASE_BUILT_IN_TM_STORE (DOUBLE):
202238fd1498Szrj CASE_BUILT_IN_TM_STORE (LDOUBLE):
202338fd1498Szrj CASE_BUILT_IN_TM_STORE (M64):
202438fd1498Szrj CASE_BUILT_IN_TM_STORE (M128):
202538fd1498Szrj CASE_BUILT_IN_TM_STORE (M256):
202638fd1498Szrj case BUILT_IN_TM_MEMCPY:
202738fd1498Szrj case BUILT_IN_TM_MEMMOVE:
202838fd1498Szrj {
202938fd1498Szrj ao_ref dref;
203038fd1498Szrj tree size = NULL_TREE;
203138fd1498Szrj /* Don't pass in size for strncat, as the maximum size
203238fd1498Szrj is strlen (dest) + n + 1 instead of n, resp.
203338fd1498Szrj n + 1 at dest + strlen (dest), but strlen (dest) isn't
203438fd1498Szrj known. */
203538fd1498Szrj if (gimple_call_num_args (call) == 3
203638fd1498Szrj && DECL_FUNCTION_CODE (callee) != BUILT_IN_STRNCAT)
203738fd1498Szrj size = gimple_call_arg (call, 2);
203838fd1498Szrj ao_ref_init_from_ptr_and_size (&dref,
203938fd1498Szrj gimple_call_arg (call, 0),
204038fd1498Szrj size);
204138fd1498Szrj return refs_may_alias_p_1 (&dref, ref, false);
204238fd1498Szrj }
204338fd1498Szrj case BUILT_IN_STRCPY_CHK:
204438fd1498Szrj case BUILT_IN_STRNCPY_CHK:
204538fd1498Szrj case BUILT_IN_MEMCPY_CHK:
204638fd1498Szrj case BUILT_IN_MEMMOVE_CHK:
204738fd1498Szrj case BUILT_IN_MEMPCPY_CHK:
204838fd1498Szrj case BUILT_IN_STPCPY_CHK:
204938fd1498Szrj case BUILT_IN_STPNCPY_CHK:
205038fd1498Szrj case BUILT_IN_STRCAT_CHK:
205138fd1498Szrj case BUILT_IN_STRNCAT_CHK:
205238fd1498Szrj case BUILT_IN_MEMSET_CHK:
205338fd1498Szrj {
205438fd1498Szrj ao_ref dref;
205538fd1498Szrj tree size = NULL_TREE;
205638fd1498Szrj /* Don't pass in size for __strncat_chk, as the maximum size
205738fd1498Szrj is strlen (dest) + n + 1 instead of n, resp.
205838fd1498Szrj n + 1 at dest + strlen (dest), but strlen (dest) isn't
205938fd1498Szrj known. */
206038fd1498Szrj if (gimple_call_num_args (call) == 4
206138fd1498Szrj && DECL_FUNCTION_CODE (callee) != BUILT_IN_STRNCAT_CHK)
206238fd1498Szrj size = gimple_call_arg (call, 2);
206338fd1498Szrj ao_ref_init_from_ptr_and_size (&dref,
206438fd1498Szrj gimple_call_arg (call, 0),
206538fd1498Szrj size);
206638fd1498Szrj return refs_may_alias_p_1 (&dref, ref, false);
206738fd1498Szrj }
206838fd1498Szrj case BUILT_IN_BCOPY:
206938fd1498Szrj {
207038fd1498Szrj ao_ref dref;
207138fd1498Szrj tree size = gimple_call_arg (call, 2);
207238fd1498Szrj ao_ref_init_from_ptr_and_size (&dref,
207338fd1498Szrj gimple_call_arg (call, 1),
207438fd1498Szrj size);
207538fd1498Szrj return refs_may_alias_p_1 (&dref, ref, false);
207638fd1498Szrj }
207738fd1498Szrj /* Allocating memory does not have any side-effects apart from
207838fd1498Szrj being the definition point for the pointer. */
207938fd1498Szrj case BUILT_IN_MALLOC:
208038fd1498Szrj case BUILT_IN_ALIGNED_ALLOC:
208138fd1498Szrj case BUILT_IN_CALLOC:
208238fd1498Szrj case BUILT_IN_STRDUP:
208338fd1498Szrj case BUILT_IN_STRNDUP:
208438fd1498Szrj /* Unix98 specifies that errno is set on allocation failure. */
208538fd1498Szrj if (flag_errno_math
208638fd1498Szrj && targetm.ref_may_alias_errno (ref))
208738fd1498Szrj return true;
208838fd1498Szrj return false;
208938fd1498Szrj case BUILT_IN_STACK_SAVE:
209038fd1498Szrj CASE_BUILT_IN_ALLOCA:
209138fd1498Szrj case BUILT_IN_ASSUME_ALIGNED:
209238fd1498Szrj return false;
209338fd1498Szrj /* But posix_memalign stores a pointer into the memory pointed to
209438fd1498Szrj by its first argument. */
209538fd1498Szrj case BUILT_IN_POSIX_MEMALIGN:
209638fd1498Szrj {
209738fd1498Szrj tree ptrptr = gimple_call_arg (call, 0);
209838fd1498Szrj ao_ref dref;
209938fd1498Szrj ao_ref_init_from_ptr_and_size (&dref, ptrptr,
210038fd1498Szrj TYPE_SIZE_UNIT (ptr_type_node));
210138fd1498Szrj return (refs_may_alias_p_1 (&dref, ref, false)
210238fd1498Szrj || (flag_errno_math
210338fd1498Szrj && targetm.ref_may_alias_errno (ref)));
210438fd1498Szrj }
210538fd1498Szrj /* Freeing memory kills the pointed-to memory. More importantly
210638fd1498Szrj the call has to serve as a barrier for moving loads and stores
210738fd1498Szrj across it. */
210838fd1498Szrj case BUILT_IN_FREE:
210938fd1498Szrj case BUILT_IN_VA_END:
211038fd1498Szrj {
211138fd1498Szrj tree ptr = gimple_call_arg (call, 0);
211238fd1498Szrj return ptr_deref_may_alias_ref_p_1 (ptr, ref);
211338fd1498Szrj }
211438fd1498Szrj /* Realloc serves both as allocation point and deallocation point. */
211538fd1498Szrj case BUILT_IN_REALLOC:
211638fd1498Szrj {
211738fd1498Szrj tree ptr = gimple_call_arg (call, 0);
211838fd1498Szrj /* Unix98 specifies that errno is set on allocation failure. */
211938fd1498Szrj return ((flag_errno_math
212038fd1498Szrj && targetm.ref_may_alias_errno (ref))
212138fd1498Szrj || ptr_deref_may_alias_ref_p_1 (ptr, ref));
212238fd1498Szrj }
212338fd1498Szrj case BUILT_IN_GAMMA_R:
212438fd1498Szrj case BUILT_IN_GAMMAF_R:
212538fd1498Szrj case BUILT_IN_GAMMAL_R:
212638fd1498Szrj case BUILT_IN_LGAMMA_R:
212738fd1498Szrj case BUILT_IN_LGAMMAF_R:
212838fd1498Szrj case BUILT_IN_LGAMMAL_R:
212938fd1498Szrj {
213038fd1498Szrj tree out = gimple_call_arg (call, 1);
213138fd1498Szrj if (ptr_deref_may_alias_ref_p_1 (out, ref))
213238fd1498Szrj return true;
213338fd1498Szrj if (flag_errno_math)
213438fd1498Szrj break;
213538fd1498Szrj return false;
213638fd1498Szrj }
213738fd1498Szrj case BUILT_IN_FREXP:
213838fd1498Szrj case BUILT_IN_FREXPF:
213938fd1498Szrj case BUILT_IN_FREXPL:
214038fd1498Szrj case BUILT_IN_MODF:
214138fd1498Szrj case BUILT_IN_MODFF:
214238fd1498Szrj case BUILT_IN_MODFL:
214338fd1498Szrj {
214438fd1498Szrj tree out = gimple_call_arg (call, 1);
214538fd1498Szrj return ptr_deref_may_alias_ref_p_1 (out, ref);
214638fd1498Szrj }
214738fd1498Szrj case BUILT_IN_REMQUO:
214838fd1498Szrj case BUILT_IN_REMQUOF:
214938fd1498Szrj case BUILT_IN_REMQUOL:
215038fd1498Szrj {
215138fd1498Szrj tree out = gimple_call_arg (call, 2);
215238fd1498Szrj if (ptr_deref_may_alias_ref_p_1 (out, ref))
215338fd1498Szrj return true;
215438fd1498Szrj if (flag_errno_math)
215538fd1498Szrj break;
215638fd1498Szrj return false;
215738fd1498Szrj }
215838fd1498Szrj case BUILT_IN_SINCOS:
215938fd1498Szrj case BUILT_IN_SINCOSF:
216038fd1498Szrj case BUILT_IN_SINCOSL:
216138fd1498Szrj {
216238fd1498Szrj tree sin = gimple_call_arg (call, 1);
216338fd1498Szrj tree cos = gimple_call_arg (call, 2);
216438fd1498Szrj return (ptr_deref_may_alias_ref_p_1 (sin, ref)
216538fd1498Szrj || ptr_deref_may_alias_ref_p_1 (cos, ref));
216638fd1498Szrj }
216738fd1498Szrj /* __sync_* builtins and some OpenMP builtins act as threading
216838fd1498Szrj barriers. */
216938fd1498Szrj #undef DEF_SYNC_BUILTIN
217038fd1498Szrj #define DEF_SYNC_BUILTIN(ENUM, NAME, TYPE, ATTRS) case ENUM:
217138fd1498Szrj #include "sync-builtins.def"
217238fd1498Szrj #undef DEF_SYNC_BUILTIN
217338fd1498Szrj case BUILT_IN_GOMP_ATOMIC_START:
217438fd1498Szrj case BUILT_IN_GOMP_ATOMIC_END:
217538fd1498Szrj case BUILT_IN_GOMP_BARRIER:
217638fd1498Szrj case BUILT_IN_GOMP_BARRIER_CANCEL:
217738fd1498Szrj case BUILT_IN_GOMP_TASKWAIT:
217838fd1498Szrj case BUILT_IN_GOMP_TASKGROUP_END:
217938fd1498Szrj case BUILT_IN_GOMP_CRITICAL_START:
218038fd1498Szrj case BUILT_IN_GOMP_CRITICAL_END:
218138fd1498Szrj case BUILT_IN_GOMP_CRITICAL_NAME_START:
218238fd1498Szrj case BUILT_IN_GOMP_CRITICAL_NAME_END:
218338fd1498Szrj case BUILT_IN_GOMP_LOOP_END:
218438fd1498Szrj case BUILT_IN_GOMP_LOOP_END_CANCEL:
218538fd1498Szrj case BUILT_IN_GOMP_ORDERED_START:
218638fd1498Szrj case BUILT_IN_GOMP_ORDERED_END:
218738fd1498Szrj case BUILT_IN_GOMP_SECTIONS_END:
218838fd1498Szrj case BUILT_IN_GOMP_SECTIONS_END_CANCEL:
218938fd1498Szrj case BUILT_IN_GOMP_SINGLE_COPY_START:
219038fd1498Szrj case BUILT_IN_GOMP_SINGLE_COPY_END:
219138fd1498Szrj return true;
219238fd1498Szrj default:
219338fd1498Szrj /* Fallthru to general call handling. */;
219438fd1498Szrj }
219538fd1498Szrj
219638fd1498Szrj /* Check if base is a global static variable that is not written
219738fd1498Szrj by the function. */
219838fd1498Szrj if (callee != NULL_TREE && VAR_P (base) && TREE_STATIC (base))
219938fd1498Szrj {
220038fd1498Szrj struct cgraph_node *node = cgraph_node::get (callee);
220138fd1498Szrj bitmap not_written;
220238fd1498Szrj
220338fd1498Szrj if (node
220438fd1498Szrj && (not_written = ipa_reference_get_not_written_global (node))
220538fd1498Szrj && bitmap_bit_p (not_written, ipa_reference_var_uid (base)))
220638fd1498Szrj return false;
220738fd1498Szrj }
220838fd1498Szrj
220938fd1498Szrj /* Check if the base variable is call-clobbered. */
221038fd1498Szrj if (DECL_P (base))
221138fd1498Szrj return pt_solution_includes (gimple_call_clobber_set (call), base);
221238fd1498Szrj else if ((TREE_CODE (base) == MEM_REF
221338fd1498Szrj || TREE_CODE (base) == TARGET_MEM_REF)
221438fd1498Szrj && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
221538fd1498Szrj {
221638fd1498Szrj struct ptr_info_def *pi = SSA_NAME_PTR_INFO (TREE_OPERAND (base, 0));
221738fd1498Szrj if (!pi)
221838fd1498Szrj return true;
221938fd1498Szrj
222038fd1498Szrj return pt_solutions_intersect (gimple_call_clobber_set (call), &pi->pt);
222138fd1498Szrj }
222238fd1498Szrj
222338fd1498Szrj return true;
222438fd1498Szrj }
222538fd1498Szrj
222638fd1498Szrj /* If the call in statement CALL may clobber the memory reference REF
222738fd1498Szrj return true, otherwise return false. */
222838fd1498Szrj
222938fd1498Szrj bool
call_may_clobber_ref_p(gcall * call,tree ref)223038fd1498Szrj call_may_clobber_ref_p (gcall *call, tree ref)
223138fd1498Szrj {
223238fd1498Szrj bool res;
223338fd1498Szrj ao_ref r;
223438fd1498Szrj ao_ref_init (&r, ref);
223538fd1498Szrj res = call_may_clobber_ref_p_1 (call, &r);
223638fd1498Szrj if (res)
223738fd1498Szrj ++alias_stats.call_may_clobber_ref_p_may_alias;
223838fd1498Szrj else
223938fd1498Szrj ++alias_stats.call_may_clobber_ref_p_no_alias;
224038fd1498Szrj return res;
224138fd1498Szrj }
224238fd1498Szrj
224338fd1498Szrj
224438fd1498Szrj /* If the statement STMT may clobber the memory reference REF return true,
224538fd1498Szrj otherwise return false. */
224638fd1498Szrj
224738fd1498Szrj bool
stmt_may_clobber_ref_p_1(gimple * stmt,ao_ref * ref)224838fd1498Szrj stmt_may_clobber_ref_p_1 (gimple *stmt, ao_ref *ref)
224938fd1498Szrj {
225038fd1498Szrj if (is_gimple_call (stmt))
225138fd1498Szrj {
225238fd1498Szrj tree lhs = gimple_call_lhs (stmt);
225338fd1498Szrj if (lhs
225438fd1498Szrj && TREE_CODE (lhs) != SSA_NAME)
225538fd1498Szrj {
225638fd1498Szrj ao_ref r;
225738fd1498Szrj ao_ref_init (&r, lhs);
225838fd1498Szrj if (refs_may_alias_p_1 (ref, &r, true))
225938fd1498Szrj return true;
226038fd1498Szrj }
226138fd1498Szrj
226238fd1498Szrj return call_may_clobber_ref_p_1 (as_a <gcall *> (stmt), ref);
226338fd1498Szrj }
226438fd1498Szrj else if (gimple_assign_single_p (stmt))
226538fd1498Szrj {
226638fd1498Szrj tree lhs = gimple_assign_lhs (stmt);
226738fd1498Szrj if (TREE_CODE (lhs) != SSA_NAME)
226838fd1498Szrj {
226938fd1498Szrj ao_ref r;
227038fd1498Szrj ao_ref_init (&r, lhs);
227138fd1498Szrj return refs_may_alias_p_1 (ref, &r, true);
227238fd1498Szrj }
227338fd1498Szrj }
227438fd1498Szrj else if (gimple_code (stmt) == GIMPLE_ASM)
227538fd1498Szrj return true;
227638fd1498Szrj
227738fd1498Szrj return false;
227838fd1498Szrj }
227938fd1498Szrj
228038fd1498Szrj bool
stmt_may_clobber_ref_p(gimple * stmt,tree ref)228138fd1498Szrj stmt_may_clobber_ref_p (gimple *stmt, tree ref)
228238fd1498Szrj {
228338fd1498Szrj ao_ref r;
228438fd1498Szrj ao_ref_init (&r, ref);
228538fd1498Szrj return stmt_may_clobber_ref_p_1 (stmt, &r);
228638fd1498Szrj }
228738fd1498Szrj
228838fd1498Szrj /* Return true if store1 and store2 described by corresponding tuples
228938fd1498Szrj <BASE, OFFSET, SIZE, MAX_SIZE> have the same size and store to the same
229038fd1498Szrj address. */
229138fd1498Szrj
229238fd1498Szrj static bool
same_addr_size_stores_p(tree base1,poly_int64 offset1,poly_int64 size1,poly_int64 max_size1,tree base2,poly_int64 offset2,poly_int64 size2,poly_int64 max_size2)229338fd1498Szrj same_addr_size_stores_p (tree base1, poly_int64 offset1, poly_int64 size1,
229438fd1498Szrj poly_int64 max_size1,
229538fd1498Szrj tree base2, poly_int64 offset2, poly_int64 size2,
229638fd1498Szrj poly_int64 max_size2)
229738fd1498Szrj {
229838fd1498Szrj /* Offsets need to be 0. */
229938fd1498Szrj if (maybe_ne (offset1, 0)
230038fd1498Szrj || maybe_ne (offset2, 0))
230138fd1498Szrj return false;
230238fd1498Szrj
230338fd1498Szrj bool base1_obj_p = SSA_VAR_P (base1);
230438fd1498Szrj bool base2_obj_p = SSA_VAR_P (base2);
230538fd1498Szrj
230638fd1498Szrj /* We need one object. */
230738fd1498Szrj if (base1_obj_p == base2_obj_p)
230838fd1498Szrj return false;
230938fd1498Szrj tree obj = base1_obj_p ? base1 : base2;
231038fd1498Szrj
231138fd1498Szrj /* And we need one MEM_REF. */
231238fd1498Szrj bool base1_memref_p = TREE_CODE (base1) == MEM_REF;
231338fd1498Szrj bool base2_memref_p = TREE_CODE (base2) == MEM_REF;
231438fd1498Szrj if (base1_memref_p == base2_memref_p)
231538fd1498Szrj return false;
231638fd1498Szrj tree memref = base1_memref_p ? base1 : base2;
231738fd1498Szrj
231838fd1498Szrj /* Sizes need to be valid. */
231938fd1498Szrj if (!known_size_p (max_size1)
232038fd1498Szrj || !known_size_p (max_size2)
232138fd1498Szrj || !known_size_p (size1)
232238fd1498Szrj || !known_size_p (size2))
232338fd1498Szrj return false;
232438fd1498Szrj
232538fd1498Szrj /* Max_size needs to match size. */
232638fd1498Szrj if (maybe_ne (max_size1, size1)
232738fd1498Szrj || maybe_ne (max_size2, size2))
232838fd1498Szrj return false;
232938fd1498Szrj
233038fd1498Szrj /* Sizes need to match. */
233138fd1498Szrj if (maybe_ne (size1, size2))
233238fd1498Szrj return false;
233338fd1498Szrj
233438fd1498Szrj
233538fd1498Szrj /* Check that memref is a store to pointer with singleton points-to info. */
233638fd1498Szrj if (!integer_zerop (TREE_OPERAND (memref, 1)))
233738fd1498Szrj return false;
233838fd1498Szrj tree ptr = TREE_OPERAND (memref, 0);
233938fd1498Szrj if (TREE_CODE (ptr) != SSA_NAME)
234038fd1498Szrj return false;
234138fd1498Szrj struct ptr_info_def *pi = SSA_NAME_PTR_INFO (ptr);
234238fd1498Szrj unsigned int pt_uid;
234338fd1498Szrj if (pi == NULL
234438fd1498Szrj || !pt_solution_singleton_or_null_p (&pi->pt, &pt_uid))
234538fd1498Szrj return false;
234638fd1498Szrj
234738fd1498Szrj /* Be conservative with non-call exceptions when the address might
234838fd1498Szrj be NULL. */
2349*58e805e6Szrj if (cfun->can_throw_non_call_exceptions && pi->pt.null)
235038fd1498Szrj return false;
235138fd1498Szrj
235238fd1498Szrj /* Check that ptr points relative to obj. */
235338fd1498Szrj unsigned int obj_uid = DECL_PT_UID (obj);
235438fd1498Szrj if (obj_uid != pt_uid)
235538fd1498Szrj return false;
235638fd1498Szrj
235738fd1498Szrj /* Check that the object size is the same as the store size. That ensures us
235838fd1498Szrj that ptr points to the start of obj. */
235938fd1498Szrj return (DECL_SIZE (obj)
236038fd1498Szrj && poly_int_tree_p (DECL_SIZE (obj))
236138fd1498Szrj && known_eq (wi::to_poly_offset (DECL_SIZE (obj)), size1));
236238fd1498Szrj }
236338fd1498Szrj
236438fd1498Szrj /* If STMT kills the memory reference REF return true, otherwise
236538fd1498Szrj return false. */
236638fd1498Szrj
236738fd1498Szrj bool
stmt_kills_ref_p(gimple * stmt,ao_ref * ref)236838fd1498Szrj stmt_kills_ref_p (gimple *stmt, ao_ref *ref)
236938fd1498Szrj {
237038fd1498Szrj if (!ao_ref_base (ref))
237138fd1498Szrj return false;
237238fd1498Szrj
237338fd1498Szrj if (gimple_has_lhs (stmt)
237438fd1498Szrj && TREE_CODE (gimple_get_lhs (stmt)) != SSA_NAME
237538fd1498Szrj /* The assignment is not necessarily carried out if it can throw
237638fd1498Szrj and we can catch it in the current function where we could inspect
237738fd1498Szrj the previous value.
237838fd1498Szrj ??? We only need to care about the RHS throwing. For aggregate
237938fd1498Szrj assignments or similar calls and non-call exceptions the LHS
238038fd1498Szrj might throw as well. */
238138fd1498Szrj && !stmt_can_throw_internal (stmt))
238238fd1498Szrj {
238338fd1498Szrj tree lhs = gimple_get_lhs (stmt);
238438fd1498Szrj /* If LHS is literally a base of the access we are done. */
238538fd1498Szrj if (ref->ref)
238638fd1498Szrj {
238738fd1498Szrj tree base = ref->ref;
238838fd1498Szrj tree innermost_dropped_array_ref = NULL_TREE;
238938fd1498Szrj if (handled_component_p (base))
239038fd1498Szrj {
239138fd1498Szrj tree saved_lhs0 = NULL_TREE;
239238fd1498Szrj if (handled_component_p (lhs))
239338fd1498Szrj {
239438fd1498Szrj saved_lhs0 = TREE_OPERAND (lhs, 0);
239538fd1498Szrj TREE_OPERAND (lhs, 0) = integer_zero_node;
239638fd1498Szrj }
239738fd1498Szrj do
239838fd1498Szrj {
239938fd1498Szrj /* Just compare the outermost handled component, if
240038fd1498Szrj they are equal we have found a possible common
240138fd1498Szrj base. */
240238fd1498Szrj tree saved_base0 = TREE_OPERAND (base, 0);
240338fd1498Szrj TREE_OPERAND (base, 0) = integer_zero_node;
240438fd1498Szrj bool res = operand_equal_p (lhs, base, 0);
240538fd1498Szrj TREE_OPERAND (base, 0) = saved_base0;
240638fd1498Szrj if (res)
240738fd1498Szrj break;
240838fd1498Szrj /* Remember if we drop an array-ref that we need to
240938fd1498Szrj double-check not being at struct end. */
241038fd1498Szrj if (TREE_CODE (base) == ARRAY_REF
241138fd1498Szrj || TREE_CODE (base) == ARRAY_RANGE_REF)
241238fd1498Szrj innermost_dropped_array_ref = base;
241338fd1498Szrj /* Otherwise drop handled components of the access. */
241438fd1498Szrj base = saved_base0;
241538fd1498Szrj }
241638fd1498Szrj while (handled_component_p (base));
241738fd1498Szrj if (saved_lhs0)
241838fd1498Szrj TREE_OPERAND (lhs, 0) = saved_lhs0;
241938fd1498Szrj }
242038fd1498Szrj /* Finally check if the lhs has the same address and size as the
242138fd1498Szrj base candidate of the access. Watch out if we have dropped
242238fd1498Szrj an array-ref that was at struct end, this means ref->ref may
242338fd1498Szrj be outside of the TYPE_SIZE of its base. */
242438fd1498Szrj if ((! innermost_dropped_array_ref
242538fd1498Szrj || ! array_at_struct_end_p (innermost_dropped_array_ref))
242638fd1498Szrj && (lhs == base
242738fd1498Szrj || (((TYPE_SIZE (TREE_TYPE (lhs))
242838fd1498Szrj == TYPE_SIZE (TREE_TYPE (base)))
242938fd1498Szrj || (TYPE_SIZE (TREE_TYPE (lhs))
243038fd1498Szrj && TYPE_SIZE (TREE_TYPE (base))
243138fd1498Szrj && operand_equal_p (TYPE_SIZE (TREE_TYPE (lhs)),
243238fd1498Szrj TYPE_SIZE (TREE_TYPE (base)),
243338fd1498Szrj 0)))
243438fd1498Szrj && operand_equal_p (lhs, base,
243538fd1498Szrj OEP_ADDRESS_OF
243638fd1498Szrj | OEP_MATCH_SIDE_EFFECTS))))
243738fd1498Szrj return true;
243838fd1498Szrj }
243938fd1498Szrj
244038fd1498Szrj /* Now look for non-literal equal bases with the restriction of
244138fd1498Szrj handling constant offset and size. */
244238fd1498Szrj /* For a must-alias check we need to be able to constrain
244338fd1498Szrj the access properly. */
244438fd1498Szrj if (!ref->max_size_known_p ())
244538fd1498Szrj return false;
244638fd1498Szrj poly_int64 size, offset, max_size, ref_offset = ref->offset;
244738fd1498Szrj bool reverse;
244838fd1498Szrj tree base = get_ref_base_and_extent (lhs, &offset, &size, &max_size,
244938fd1498Szrj &reverse);
245038fd1498Szrj /* We can get MEM[symbol: sZ, index: D.8862_1] here,
245138fd1498Szrj so base == ref->base does not always hold. */
245238fd1498Szrj if (base != ref->base)
245338fd1498Szrj {
245438fd1498Szrj /* Try using points-to info. */
245538fd1498Szrj if (same_addr_size_stores_p (base, offset, size, max_size, ref->base,
245638fd1498Szrj ref->offset, ref->size, ref->max_size))
245738fd1498Szrj return true;
245838fd1498Szrj
245938fd1498Szrj /* If both base and ref->base are MEM_REFs, only compare the
246038fd1498Szrj first operand, and if the second operand isn't equal constant,
246138fd1498Szrj try to add the offsets into offset and ref_offset. */
246238fd1498Szrj if (TREE_CODE (base) == MEM_REF && TREE_CODE (ref->base) == MEM_REF
246338fd1498Szrj && TREE_OPERAND (base, 0) == TREE_OPERAND (ref->base, 0))
246438fd1498Szrj {
246538fd1498Szrj if (!tree_int_cst_equal (TREE_OPERAND (base, 1),
246638fd1498Szrj TREE_OPERAND (ref->base, 1)))
246738fd1498Szrj {
246838fd1498Szrj poly_offset_int off1 = mem_ref_offset (base);
246938fd1498Szrj off1 <<= LOG2_BITS_PER_UNIT;
247038fd1498Szrj off1 += offset;
247138fd1498Szrj poly_offset_int off2 = mem_ref_offset (ref->base);
247238fd1498Szrj off2 <<= LOG2_BITS_PER_UNIT;
247338fd1498Szrj off2 += ref_offset;
247438fd1498Szrj if (!off1.to_shwi (&offset) || !off2.to_shwi (&ref_offset))
247538fd1498Szrj size = -1;
247638fd1498Szrj }
247738fd1498Szrj }
247838fd1498Szrj else
247938fd1498Szrj size = -1;
248038fd1498Szrj }
248138fd1498Szrj /* For a must-alias check we need to be able to constrain
248238fd1498Szrj the access properly. */
248338fd1498Szrj if (known_eq (size, max_size)
248438fd1498Szrj && known_subrange_p (ref_offset, ref->max_size, offset, size))
248538fd1498Szrj return true;
248638fd1498Szrj }
248738fd1498Szrj
248838fd1498Szrj if (is_gimple_call (stmt))
248938fd1498Szrj {
249038fd1498Szrj tree callee = gimple_call_fndecl (stmt);
249138fd1498Szrj if (callee != NULL_TREE
249238fd1498Szrj && gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
249338fd1498Szrj switch (DECL_FUNCTION_CODE (callee))
249438fd1498Szrj {
249538fd1498Szrj case BUILT_IN_FREE:
249638fd1498Szrj {
249738fd1498Szrj tree ptr = gimple_call_arg (stmt, 0);
249838fd1498Szrj tree base = ao_ref_base (ref);
249938fd1498Szrj if (base && TREE_CODE (base) == MEM_REF
250038fd1498Szrj && TREE_OPERAND (base, 0) == ptr)
250138fd1498Szrj return true;
250238fd1498Szrj break;
250338fd1498Szrj }
250438fd1498Szrj
250538fd1498Szrj case BUILT_IN_MEMCPY:
250638fd1498Szrj case BUILT_IN_MEMPCPY:
250738fd1498Szrj case BUILT_IN_MEMMOVE:
250838fd1498Szrj case BUILT_IN_MEMSET:
250938fd1498Szrj case BUILT_IN_MEMCPY_CHK:
251038fd1498Szrj case BUILT_IN_MEMPCPY_CHK:
251138fd1498Szrj case BUILT_IN_MEMMOVE_CHK:
251238fd1498Szrj case BUILT_IN_MEMSET_CHK:
251338fd1498Szrj case BUILT_IN_STRNCPY:
251438fd1498Szrj case BUILT_IN_STPNCPY:
251538fd1498Szrj {
251638fd1498Szrj /* For a must-alias check we need to be able to constrain
251738fd1498Szrj the access properly. */
251838fd1498Szrj if (!ref->max_size_known_p ())
251938fd1498Szrj return false;
252038fd1498Szrj tree dest = gimple_call_arg (stmt, 0);
252138fd1498Szrj tree len = gimple_call_arg (stmt, 2);
252238fd1498Szrj if (!poly_int_tree_p (len))
252338fd1498Szrj return false;
252438fd1498Szrj tree rbase = ref->base;
252538fd1498Szrj poly_offset_int roffset = ref->offset;
252638fd1498Szrj ao_ref dref;
252738fd1498Szrj ao_ref_init_from_ptr_and_size (&dref, dest, len);
252838fd1498Szrj tree base = ao_ref_base (&dref);
252938fd1498Szrj poly_offset_int offset = dref.offset;
253038fd1498Szrj if (!base || !known_size_p (dref.size))
253138fd1498Szrj return false;
253238fd1498Szrj if (TREE_CODE (base) == MEM_REF)
253338fd1498Szrj {
253438fd1498Szrj if (TREE_CODE (rbase) != MEM_REF)
253538fd1498Szrj return false;
253638fd1498Szrj // Compare pointers.
253738fd1498Szrj offset += mem_ref_offset (base) << LOG2_BITS_PER_UNIT;
253838fd1498Szrj roffset += mem_ref_offset (rbase) << LOG2_BITS_PER_UNIT;
253938fd1498Szrj base = TREE_OPERAND (base, 0);
254038fd1498Szrj rbase = TREE_OPERAND (rbase, 0);
254138fd1498Szrj }
254238fd1498Szrj if (base == rbase
254338fd1498Szrj && known_subrange_p (roffset, ref->max_size, offset,
254438fd1498Szrj wi::to_poly_offset (len)
254538fd1498Szrj << LOG2_BITS_PER_UNIT))
254638fd1498Szrj return true;
254738fd1498Szrj break;
254838fd1498Szrj }
254938fd1498Szrj
255038fd1498Szrj case BUILT_IN_VA_END:
255138fd1498Szrj {
255238fd1498Szrj tree ptr = gimple_call_arg (stmt, 0);
255338fd1498Szrj if (TREE_CODE (ptr) == ADDR_EXPR)
255438fd1498Szrj {
255538fd1498Szrj tree base = ao_ref_base (ref);
255638fd1498Szrj if (TREE_OPERAND (ptr, 0) == base)
255738fd1498Szrj return true;
255838fd1498Szrj }
255938fd1498Szrj break;
256038fd1498Szrj }
256138fd1498Szrj
256238fd1498Szrj default:;
256338fd1498Szrj }
256438fd1498Szrj }
256538fd1498Szrj return false;
256638fd1498Szrj }
256738fd1498Szrj
256838fd1498Szrj bool
stmt_kills_ref_p(gimple * stmt,tree ref)256938fd1498Szrj stmt_kills_ref_p (gimple *stmt, tree ref)
257038fd1498Szrj {
257138fd1498Szrj ao_ref r;
257238fd1498Szrj ao_ref_init (&r, ref);
257338fd1498Szrj return stmt_kills_ref_p (stmt, &r);
257438fd1498Szrj }
257538fd1498Szrj
257638fd1498Szrj
257738fd1498Szrj /* Walk the virtual use-def chain of VUSE until hitting the virtual operand
257838fd1498Szrj TARGET or a statement clobbering the memory reference REF in which
257938fd1498Szrj case false is returned. The walk starts with VUSE, one argument of PHI. */
258038fd1498Szrj
258138fd1498Szrj static bool
maybe_skip_until(gimple * phi,tree target,ao_ref * ref,tree vuse,unsigned int * cnt,bitmap * visited,bool abort_on_visited,void * (* translate)(ao_ref *,tree,void *,bool *),void * data)258238fd1498Szrj maybe_skip_until (gimple *phi, tree target, ao_ref *ref,
258338fd1498Szrj tree vuse, unsigned int *cnt, bitmap *visited,
258438fd1498Szrj bool abort_on_visited,
258538fd1498Szrj void *(*translate)(ao_ref *, tree, void *, bool *),
258638fd1498Szrj void *data)
258738fd1498Szrj {
258838fd1498Szrj basic_block bb = gimple_bb (phi);
258938fd1498Szrj
259038fd1498Szrj if (!*visited)
259138fd1498Szrj *visited = BITMAP_ALLOC (NULL);
259238fd1498Szrj
259338fd1498Szrj bitmap_set_bit (*visited, SSA_NAME_VERSION (PHI_RESULT (phi)));
259438fd1498Szrj
259538fd1498Szrj /* Walk until we hit the target. */
259638fd1498Szrj while (vuse != target)
259738fd1498Szrj {
259838fd1498Szrj gimple *def_stmt = SSA_NAME_DEF_STMT (vuse);
259938fd1498Szrj /* Recurse for PHI nodes. */
260038fd1498Szrj if (gimple_code (def_stmt) == GIMPLE_PHI)
260138fd1498Szrj {
260238fd1498Szrj /* An already visited PHI node ends the walk successfully. */
260338fd1498Szrj if (bitmap_bit_p (*visited, SSA_NAME_VERSION (PHI_RESULT (def_stmt))))
260438fd1498Szrj return !abort_on_visited;
260538fd1498Szrj vuse = get_continuation_for_phi (def_stmt, ref, cnt,
260638fd1498Szrj visited, abort_on_visited,
260738fd1498Szrj translate, data);
260838fd1498Szrj if (!vuse)
260938fd1498Szrj return false;
261038fd1498Szrj continue;
261138fd1498Szrj }
261238fd1498Szrj else if (gimple_nop_p (def_stmt))
261338fd1498Szrj return false;
261438fd1498Szrj else
261538fd1498Szrj {
261638fd1498Szrj /* A clobbering statement or the end of the IL ends it failing. */
261738fd1498Szrj ++*cnt;
261838fd1498Szrj if (stmt_may_clobber_ref_p_1 (def_stmt, ref))
261938fd1498Szrj {
262038fd1498Szrj bool disambiguate_only = true;
262138fd1498Szrj if (translate
262238fd1498Szrj && (*translate) (ref, vuse, data, &disambiguate_only) == NULL)
262338fd1498Szrj ;
262438fd1498Szrj else
262538fd1498Szrj return false;
262638fd1498Szrj }
262738fd1498Szrj }
262838fd1498Szrj /* If we reach a new basic-block see if we already skipped it
262938fd1498Szrj in a previous walk that ended successfully. */
263038fd1498Szrj if (gimple_bb (def_stmt) != bb)
263138fd1498Szrj {
263238fd1498Szrj if (!bitmap_set_bit (*visited, SSA_NAME_VERSION (vuse)))
263338fd1498Szrj return !abort_on_visited;
263438fd1498Szrj bb = gimple_bb (def_stmt);
263538fd1498Szrj }
263638fd1498Szrj vuse = gimple_vuse (def_stmt);
263738fd1498Szrj }
263838fd1498Szrj return true;
263938fd1498Szrj }
264038fd1498Szrj
264138fd1498Szrj
264238fd1498Szrj /* Starting from a PHI node for the virtual operand of the memory reference
264338fd1498Szrj REF find a continuation virtual operand that allows to continue walking
264438fd1498Szrj statements dominating PHI skipping only statements that cannot possibly
264538fd1498Szrj clobber REF. Increments *CNT for each alias disambiguation done.
264638fd1498Szrj Returns NULL_TREE if no suitable virtual operand can be found. */
264738fd1498Szrj
264838fd1498Szrj tree
get_continuation_for_phi(gimple * phi,ao_ref * ref,unsigned int * cnt,bitmap * visited,bool abort_on_visited,void * (* translate)(ao_ref *,tree,void *,bool *),void * data)264938fd1498Szrj get_continuation_for_phi (gimple *phi, ao_ref *ref,
265038fd1498Szrj unsigned int *cnt, bitmap *visited,
265138fd1498Szrj bool abort_on_visited,
265238fd1498Szrj void *(*translate)(ao_ref *, tree, void *, bool *),
265338fd1498Szrj void *data)
265438fd1498Szrj {
265538fd1498Szrj unsigned nargs = gimple_phi_num_args (phi);
265638fd1498Szrj
265738fd1498Szrj /* Through a single-argument PHI we can simply look through. */
265838fd1498Szrj if (nargs == 1)
265938fd1498Szrj return PHI_ARG_DEF (phi, 0);
266038fd1498Szrj
266138fd1498Szrj /* For two or more arguments try to pairwise skip non-aliasing code
266238fd1498Szrj until we hit the phi argument definition that dominates the other one. */
266338fd1498Szrj basic_block phi_bb = gimple_bb (phi);
266438fd1498Szrj tree arg0, arg1;
266538fd1498Szrj unsigned i;
266638fd1498Szrj
266738fd1498Szrj /* Find a candidate for the virtual operand which definition
266838fd1498Szrj dominates those of all others. */
266938fd1498Szrj /* First look if any of the args themselves satisfy this. */
267038fd1498Szrj for (i = 0; i < nargs; ++i)
267138fd1498Szrj {
267238fd1498Szrj arg0 = PHI_ARG_DEF (phi, i);
267338fd1498Szrj if (SSA_NAME_IS_DEFAULT_DEF (arg0))
267438fd1498Szrj break;
267538fd1498Szrj basic_block def_bb = gimple_bb (SSA_NAME_DEF_STMT (arg0));
267638fd1498Szrj if (def_bb != phi_bb
267738fd1498Szrj && dominated_by_p (CDI_DOMINATORS, phi_bb, def_bb))
267838fd1498Szrj break;
267938fd1498Szrj arg0 = NULL_TREE;
268038fd1498Szrj }
268138fd1498Szrj /* If not, look if we can reach such candidate by walking defs
268238fd1498Szrj of a PHI arg without crossing other PHIs. */
268338fd1498Szrj if (! arg0)
268438fd1498Szrj for (i = 0; i < nargs; ++i)
268538fd1498Szrj {
268638fd1498Szrj arg0 = PHI_ARG_DEF (phi, i);
268738fd1498Szrj gimple *def = SSA_NAME_DEF_STMT (arg0);
268838fd1498Szrj /* Backedges can't work. */
268938fd1498Szrj if (dominated_by_p (CDI_DOMINATORS,
269038fd1498Szrj gimple_bb (def), phi_bb))
269138fd1498Szrj continue;
269238fd1498Szrj /* See below. */
269338fd1498Szrj if (gimple_code (def) == GIMPLE_PHI)
269438fd1498Szrj continue;
269538fd1498Szrj while (! dominated_by_p (CDI_DOMINATORS,
269638fd1498Szrj phi_bb, gimple_bb (def)))
269738fd1498Szrj {
269838fd1498Szrj arg0 = gimple_vuse (def);
269938fd1498Szrj if (SSA_NAME_IS_DEFAULT_DEF (arg0))
270038fd1498Szrj break;
270138fd1498Szrj def = SSA_NAME_DEF_STMT (arg0);
270238fd1498Szrj if (gimple_code (def) == GIMPLE_PHI)
270338fd1498Szrj {
270438fd1498Szrj /* Do not try to look through arbitrarily complicated
270538fd1498Szrj CFGs. For those looking for the first VUSE starting
270638fd1498Szrj from the end of the immediate dominator of phi_bb
270738fd1498Szrj is likely faster. */
270838fd1498Szrj arg0 = NULL_TREE;
270938fd1498Szrj goto next;
271038fd1498Szrj }
271138fd1498Szrj }
271238fd1498Szrj break;
271338fd1498Szrj next:;
271438fd1498Szrj }
271538fd1498Szrj if (! arg0)
271638fd1498Szrj return NULL_TREE;
271738fd1498Szrj
271838fd1498Szrj /* Then check against the found candidate. */
271938fd1498Szrj for (i = 0; i < nargs; ++i)
272038fd1498Szrj {
272138fd1498Szrj arg1 = PHI_ARG_DEF (phi, i);
272238fd1498Szrj if (arg1 == arg0)
272338fd1498Szrj ;
272438fd1498Szrj else if (! maybe_skip_until (phi, arg0, ref, arg1, cnt, visited,
272538fd1498Szrj abort_on_visited, translate, data))
272638fd1498Szrj return NULL_TREE;
272738fd1498Szrj }
272838fd1498Szrj
272938fd1498Szrj return arg0;
273038fd1498Szrj }
273138fd1498Szrj
273238fd1498Szrj /* Based on the memory reference REF and its virtual use VUSE call
273338fd1498Szrj WALKER for each virtual use that is equivalent to VUSE, including VUSE
273438fd1498Szrj itself. That is, for each virtual use for which its defining statement
273538fd1498Szrj does not clobber REF.
273638fd1498Szrj
273738fd1498Szrj WALKER is called with REF, the current virtual use and DATA. If
273838fd1498Szrj WALKER returns non-NULL the walk stops and its result is returned.
273938fd1498Szrj At the end of a non-successful walk NULL is returned.
274038fd1498Szrj
274138fd1498Szrj TRANSLATE if non-NULL is called with a pointer to REF, the virtual
274238fd1498Szrj use which definition is a statement that may clobber REF and DATA.
274338fd1498Szrj If TRANSLATE returns (void *)-1 the walk stops and NULL is returned.
274438fd1498Szrj If TRANSLATE returns non-NULL the walk stops and its result is returned.
274538fd1498Szrj If TRANSLATE returns NULL the walk continues and TRANSLATE is supposed
274638fd1498Szrj to adjust REF and *DATA to make that valid.
274738fd1498Szrj
274838fd1498Szrj VALUEIZE if non-NULL is called with the next VUSE that is considered
274938fd1498Szrj and return value is substituted for that. This can be used to
275038fd1498Szrj implement optimistic value-numbering for example. Note that the
275138fd1498Szrj VUSE argument is assumed to be valueized already.
275238fd1498Szrj
275338fd1498Szrj TODO: Cache the vector of equivalent vuses per ref, vuse pair. */
275438fd1498Szrj
275538fd1498Szrj void *
walk_non_aliased_vuses(ao_ref * ref,tree vuse,void * (* walker)(ao_ref *,tree,unsigned int,void *),void * (* translate)(ao_ref *,tree,void *,bool *),tree (* valueize)(tree),void * data)275638fd1498Szrj walk_non_aliased_vuses (ao_ref *ref, tree vuse,
275738fd1498Szrj void *(*walker)(ao_ref *, tree, unsigned int, void *),
275838fd1498Szrj void *(*translate)(ao_ref *, tree, void *, bool *),
275938fd1498Szrj tree (*valueize)(tree),
276038fd1498Szrj void *data)
276138fd1498Szrj {
276238fd1498Szrj bitmap visited = NULL;
276338fd1498Szrj void *res;
276438fd1498Szrj unsigned int cnt = 0;
276538fd1498Szrj bool translated = false;
276638fd1498Szrj
276738fd1498Szrj timevar_push (TV_ALIAS_STMT_WALK);
276838fd1498Szrj
276938fd1498Szrj do
277038fd1498Szrj {
277138fd1498Szrj gimple *def_stmt;
277238fd1498Szrj
277338fd1498Szrj /* ??? Do we want to account this to TV_ALIAS_STMT_WALK? */
277438fd1498Szrj res = (*walker) (ref, vuse, cnt, data);
277538fd1498Szrj /* Abort walk. */
277638fd1498Szrj if (res == (void *)-1)
277738fd1498Szrj {
277838fd1498Szrj res = NULL;
277938fd1498Szrj break;
278038fd1498Szrj }
278138fd1498Szrj /* Lookup succeeded. */
278238fd1498Szrj else if (res != NULL)
278338fd1498Szrj break;
278438fd1498Szrj
278538fd1498Szrj if (valueize)
278638fd1498Szrj vuse = valueize (vuse);
278738fd1498Szrj def_stmt = SSA_NAME_DEF_STMT (vuse);
278838fd1498Szrj if (gimple_nop_p (def_stmt))
278938fd1498Szrj break;
279038fd1498Szrj else if (gimple_code (def_stmt) == GIMPLE_PHI)
279138fd1498Szrj vuse = get_continuation_for_phi (def_stmt, ref, &cnt,
279238fd1498Szrj &visited, translated, translate, data);
279338fd1498Szrj else
279438fd1498Szrj {
279538fd1498Szrj cnt++;
279638fd1498Szrj if (stmt_may_clobber_ref_p_1 (def_stmt, ref))
279738fd1498Szrj {
279838fd1498Szrj if (!translate)
279938fd1498Szrj break;
280038fd1498Szrj bool disambiguate_only = false;
280138fd1498Szrj res = (*translate) (ref, vuse, data, &disambiguate_only);
280238fd1498Szrj /* Failed lookup and translation. */
280338fd1498Szrj if (res == (void *)-1)
280438fd1498Szrj {
280538fd1498Szrj res = NULL;
280638fd1498Szrj break;
280738fd1498Szrj }
280838fd1498Szrj /* Lookup succeeded. */
280938fd1498Szrj else if (res != NULL)
281038fd1498Szrj break;
281138fd1498Szrj /* Translation succeeded, continue walking. */
281238fd1498Szrj translated = translated || !disambiguate_only;
281338fd1498Szrj }
281438fd1498Szrj vuse = gimple_vuse (def_stmt);
281538fd1498Szrj }
281638fd1498Szrj }
281738fd1498Szrj while (vuse);
281838fd1498Szrj
281938fd1498Szrj if (visited)
282038fd1498Szrj BITMAP_FREE (visited);
282138fd1498Szrj
282238fd1498Szrj timevar_pop (TV_ALIAS_STMT_WALK);
282338fd1498Szrj
282438fd1498Szrj return res;
282538fd1498Szrj }
282638fd1498Szrj
282738fd1498Szrj
282838fd1498Szrj /* Based on the memory reference REF call WALKER for each vdef which
282938fd1498Szrj defining statement may clobber REF, starting with VDEF. If REF
283038fd1498Szrj is NULL_TREE, each defining statement is visited.
283138fd1498Szrj
283238fd1498Szrj WALKER is called with REF, the current vdef and DATA. If WALKER
283338fd1498Szrj returns true the walk is stopped, otherwise it continues.
283438fd1498Szrj
283538fd1498Szrj If function entry is reached, FUNCTION_ENTRY_REACHED is set to true.
283638fd1498Szrj The pointer may be NULL and then we do not track this information.
283738fd1498Szrj
283838fd1498Szrj At PHI nodes walk_aliased_vdefs forks into one walk for reach
283938fd1498Szrj PHI argument (but only one walk continues on merge points), the
284038fd1498Szrj return value is true if any of the walks was successful.
284138fd1498Szrj
284238fd1498Szrj The function returns the number of statements walked or -1 if
284338fd1498Szrj LIMIT stmts were walked and the walk was aborted at this point.
284438fd1498Szrj If LIMIT is zero the walk is not aborted. */
284538fd1498Szrj
284638fd1498Szrj static int
walk_aliased_vdefs_1(ao_ref * ref,tree vdef,bool (* walker)(ao_ref *,tree,void *),void * data,bitmap * visited,unsigned int cnt,bool * function_entry_reached,unsigned limit)284738fd1498Szrj walk_aliased_vdefs_1 (ao_ref *ref, tree vdef,
284838fd1498Szrj bool (*walker)(ao_ref *, tree, void *), void *data,
284938fd1498Szrj bitmap *visited, unsigned int cnt,
285038fd1498Szrj bool *function_entry_reached, unsigned limit)
285138fd1498Szrj {
285238fd1498Szrj do
285338fd1498Szrj {
285438fd1498Szrj gimple *def_stmt = SSA_NAME_DEF_STMT (vdef);
285538fd1498Szrj
285638fd1498Szrj if (*visited
285738fd1498Szrj && !bitmap_set_bit (*visited, SSA_NAME_VERSION (vdef)))
285838fd1498Szrj return cnt;
285938fd1498Szrj
286038fd1498Szrj if (gimple_nop_p (def_stmt))
286138fd1498Szrj {
286238fd1498Szrj if (function_entry_reached)
286338fd1498Szrj *function_entry_reached = true;
286438fd1498Szrj return cnt;
286538fd1498Szrj }
286638fd1498Szrj else if (gimple_code (def_stmt) == GIMPLE_PHI)
286738fd1498Szrj {
286838fd1498Szrj unsigned i;
286938fd1498Szrj if (!*visited)
287038fd1498Szrj *visited = BITMAP_ALLOC (NULL);
287138fd1498Szrj for (i = 0; i < gimple_phi_num_args (def_stmt); ++i)
287238fd1498Szrj {
287338fd1498Szrj int res = walk_aliased_vdefs_1 (ref,
287438fd1498Szrj gimple_phi_arg_def (def_stmt, i),
287538fd1498Szrj walker, data, visited, cnt,
287638fd1498Szrj function_entry_reached, limit);
287738fd1498Szrj if (res == -1)
287838fd1498Szrj return -1;
287938fd1498Szrj cnt = res;
288038fd1498Szrj }
288138fd1498Szrj return cnt;
288238fd1498Szrj }
288338fd1498Szrj
288438fd1498Szrj /* ??? Do we want to account this to TV_ALIAS_STMT_WALK? */
288538fd1498Szrj cnt++;
288638fd1498Szrj if (cnt == limit)
288738fd1498Szrj return -1;
288838fd1498Szrj if ((!ref
288938fd1498Szrj || stmt_may_clobber_ref_p_1 (def_stmt, ref))
289038fd1498Szrj && (*walker) (ref, vdef, data))
289138fd1498Szrj return cnt;
289238fd1498Szrj
289338fd1498Szrj vdef = gimple_vuse (def_stmt);
289438fd1498Szrj }
289538fd1498Szrj while (1);
289638fd1498Szrj }
289738fd1498Szrj
289838fd1498Szrj int
walk_aliased_vdefs(ao_ref * ref,tree vdef,bool (* walker)(ao_ref *,tree,void *),void * data,bitmap * visited,bool * function_entry_reached,unsigned int limit)289938fd1498Szrj walk_aliased_vdefs (ao_ref *ref, tree vdef,
290038fd1498Szrj bool (*walker)(ao_ref *, tree, void *), void *data,
290138fd1498Szrj bitmap *visited,
290238fd1498Szrj bool *function_entry_reached, unsigned int limit)
290338fd1498Szrj {
290438fd1498Szrj bitmap local_visited = NULL;
290538fd1498Szrj int ret;
290638fd1498Szrj
290738fd1498Szrj timevar_push (TV_ALIAS_STMT_WALK);
290838fd1498Szrj
290938fd1498Szrj if (function_entry_reached)
291038fd1498Szrj *function_entry_reached = false;
291138fd1498Szrj
291238fd1498Szrj ret = walk_aliased_vdefs_1 (ref, vdef, walker, data,
291338fd1498Szrj visited ? visited : &local_visited, 0,
291438fd1498Szrj function_entry_reached, limit);
291538fd1498Szrj if (local_visited)
291638fd1498Szrj BITMAP_FREE (local_visited);
291738fd1498Szrj
291838fd1498Szrj timevar_pop (TV_ALIAS_STMT_WALK);
291938fd1498Szrj
292038fd1498Szrj return ret;
292138fd1498Szrj }
292238fd1498Szrj
2923