xref: /dflybsd-src/contrib/gcc-8.0/gcc/tree-ssa-alias.c (revision 95059079af47f9a66a175f374f2da1a5020e3255)
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