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 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 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 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 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 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 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 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 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 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 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 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 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 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 57538fd1498Szrj debug (pt_solution &ref) 57638fd1498Szrj { 57738fd1498Szrj dump_points_to_solution (stderr, &ref); 57838fd1498Szrj } 57938fd1498Szrj 58038fd1498Szrj DEBUG_FUNCTION void 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 * 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 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 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