&& DECL_BY_REFERENCE (DECL_RESULT (current_function_decl))
&& t == ssa_default_def (cfun, DECL_RESULT (current_function_decl)))
return true;
- return !ptr_deref_may_alias_global_p (t);
+ return !ptr_deref_may_alias_global_p (t, false);
}
if (TREE_CODE (t) == ADDR_EXPR)
return refs_local_or_readonly_memory_p (TREE_OPERAND (t, 0));
--- /dev/null
+-- { dg-do run }
+-- { dg-options "-O" }
+
+with Concat5_Pkg1; use Concat5_Pkg1;
+
+procedure Concat5 is
+begin
+ Scan ("-RTS=none");
+end;
--- /dev/null
+with Concat5_Pkg2; use Concat5_Pkg2;
+
+package body Concat5_Pkg1 is
+
+ procedure Make_Failed (S : String);
+ pragma No_Inline (Make_Failed);
+
+ procedure Make_Failed (S : String) is
+ begin
+ Compare (S);
+ end;
+
+ procedure Scan (S : String) is
+ begin
+ Make_Failed ("option " & S & " should start with '--'");
+ end;
+
+end Concat5_Pkg1;
--- /dev/null
+package Concat5_Pkg1 is
+
+ procedure Scan (S : String);
+
+end Concat5_Pkg1;
--- /dev/null
+package body Concat5_Pkg2 is
+
+ procedure Compare (S : String) is
+ begin
+ if S /= "option -RTS=none should start with '--'" then
+ raise Program_Error;
+ end if;
+ end;
+
+end Concat5_Pkg2;
--- /dev/null
+package Concat5_Pkg2 is
+
+ procedure Compare (S : String);
+
+end Concat5_Pkg2;
/* Search DEF chain to find the original definition of this address. */
do
{
- if (ptr_deref_may_alias_global_p (x))
+ if (ptr_deref_may_alias_global_p (x, true))
{
/* Address escapes. This is not thread-private. */
retval = mem_non_local;
}
-/* Return true, if dereferencing PTR may alias with a global variable. */
+/* Return true, if dereferencing PTR may alias with a global variable.
+ When ESCAPED_LOCAL_P is true escaped local memory is also considered
+ global. */
bool
-ptr_deref_may_alias_global_p (tree ptr)
+ptr_deref_may_alias_global_p (tree ptr, bool escaped_local_p)
{
struct ptr_info_def *pi;
return true;
/* ??? This does not use TBAA to prune globals ptr may not access. */
- return pt_solution_includes_global (&pi->pt);
+ return pt_solution_includes_global (&pi->pt, escaped_local_p);
}
/* Return true if dereferencing PTR may alias DECL.
return false;
}
-/* Returns whether reference REF to BASE may refer to global memory. */
+/* Returns whether reference REF to BASE may refer to global memory.
+ When ESCAPED_LOCAL_P is true escaped local memory is also considered
+ global. */
static bool
-ref_may_alias_global_p_1 (tree base)
+ref_may_alias_global_p_1 (tree base, bool escaped_local_p)
{
if (DECL_P (base))
- return is_global_var (base);
+ return (is_global_var (base)
+ || (escaped_local_p
+ && pt_solution_includes (&cfun->gimple_df->escaped, base)));
else if (TREE_CODE (base) == MEM_REF
|| TREE_CODE (base) == TARGET_MEM_REF)
- return ptr_deref_may_alias_global_p (TREE_OPERAND (base, 0));
+ return ptr_deref_may_alias_global_p (TREE_OPERAND (base, 0),
+ escaped_local_p);
return true;
}
bool
-ref_may_alias_global_p (ao_ref *ref)
+ref_may_alias_global_p (ao_ref *ref, bool escaped_local_p)
{
tree base = ao_ref_base (ref);
- return ref_may_alias_global_p_1 (base);
+ return ref_may_alias_global_p_1 (base, escaped_local_p);
}
bool
-ref_may_alias_global_p (tree ref)
+ref_may_alias_global_p (tree ref, bool escaped_local_p)
{
tree base = get_base_address (ref);
- return ref_may_alias_global_p_1 (base);
+ return ref_may_alias_global_p_1 (base, escaped_local_p);
}
-/* Return true whether STMT may clobber global memory. */
+/* Return true whether STMT may clobber global memory.
+ When ESCAPED_LOCAL_P is true escaped local memory is also considered
+ global. */
bool
-stmt_may_clobber_global_p (gimple *stmt)
+stmt_may_clobber_global_p (gimple *stmt, bool escaped_local_p)
{
tree lhs;
case GIMPLE_ASSIGN:
lhs = gimple_assign_lhs (stmt);
return (TREE_CODE (lhs) != SSA_NAME
- && ref_may_alias_global_p (lhs));
+ && ref_may_alias_global_p (lhs, escaped_local_p));
case GIMPLE_CALL:
return true;
default:
return refs_may_alias_p_1 (&r1, &r2, false);
}
-/* Return ture if REF may access global memory. */
-
-bool
-ref_may_access_global_memory_p (ao_ref *ref)
-{
- if (!ref->ref)
- return true;
- tree base = ao_ref_base (ref);
- if (TREE_CODE (base) == MEM_REF
- || TREE_CODE (base) == TARGET_MEM_REF)
- {
- if (ptr_deref_may_alias_global_p (TREE_OPERAND (base, 0)))
- return true;
- }
- else
- {
- if (!auto_var_in_fn_p (base, current_function_decl)
- || pt_solution_includes (&cfun->gimple_df->escaped,
- base))
- return true;
- }
- return false;
-}
-
/* Returns true if and only if REF may alias any access stored in TT.
IF TBAA_P is true, use TBAA oracle. */
{
if (global_memory_ok)
continue;
- if (ref_may_access_global_memory_p (ref))
+ if (ref_may_alias_global_p (ref, true))
return true;
global_memory_ok = true;
num_tests++;
return is_global_var (base);
else if (TREE_CODE (base) == MEM_REF
|| TREE_CODE (base) == TARGET_MEM_REF)
- return ptr_deref_may_alias_global_p (TREE_OPERAND (base, 0));
+ return ptr_deref_may_alias_global_p (TREE_OPERAND (base, 0), false);
return false;
}
extern tree ao_ref_base_alias_ptr_type (ao_ref *);
extern bool ao_ref_alignment (ao_ref *, unsigned int *,
unsigned HOST_WIDE_INT *);
-extern bool ptr_deref_may_alias_global_p (tree);
+extern bool ptr_deref_may_alias_global_p (tree, bool);
extern bool ptr_derefs_may_alias_p (tree, tree);
extern bool ptrs_compare_unequal (tree, tree);
-extern bool ref_may_alias_global_p (tree);
-extern bool ref_may_alias_global_p (ao_ref *);
+extern bool ref_may_alias_global_p (tree, bool);
+extern bool ref_may_alias_global_p (ao_ref *, bool);
extern bool refs_may_alias_p (tree, tree, bool = true);
extern bool refs_may_alias_p_1 (ao_ref *, ao_ref *, bool);
extern bool refs_anti_dependent_p (tree, tree);
extern bool refs_output_dependent_p (tree, tree);
extern bool ref_maybe_used_by_stmt_p (gimple *, tree, bool = true);
extern bool ref_maybe_used_by_stmt_p (gimple *, ao_ref *, bool = true);
-extern bool stmt_may_clobber_global_p (gimple *);
+extern bool stmt_may_clobber_global_p (gimple *, bool);
extern bool stmt_may_clobber_ref_p (gimple *, tree, bool = true);
extern bool stmt_may_clobber_ref_p_1 (gimple *, ao_ref *, bool = true);
extern bool call_may_clobber_ref_p (gcall *, tree, bool = true);
extern unsigned int compute_may_aliases (void);
extern bool pt_solution_empty_p (const pt_solution *);
extern bool pt_solution_singleton_or_null_p (struct pt_solution *, unsigned *);
-extern bool pt_solution_includes_global (struct pt_solution *);
+extern bool pt_solution_includes_global (struct pt_solution *, bool);
extern bool pt_solution_includes (struct pt_solution *, const_tree);
extern bool pt_solutions_intersect (struct pt_solution *, struct pt_solution *);
extern void pt_solution_reset (struct pt_solution *);
}
if ((gimple_vdef (stmt) && keep_all_vdefs_p ())
- || stmt_may_clobber_global_p (stmt))
+ || stmt_may_clobber_global_p (stmt, true))
{
mark_stmt_necessary (stmt, true);
return;
just pretend the stmt makes itself dead. Otherwise fail. */
if (defs.is_empty ())
{
- if (ref_may_alias_global_p (ref))
+ if (ref_may_alias_global_p (ref, false))
return DSE_STORE_LIVE;
if (by_clobber_p)
{
/* But if the store is to global memory it is definitely
not dead. */
- if (ref_may_alias_global_p (ref))
+ if (ref_may_alias_global_p (ref, false))
return DSE_STORE_LIVE;
defs.unordered_remove (i);
}
return true;
}
-/* Return true if the points-to solution *PT includes global memory. */
+/* Return true if the points-to solution *PT includes global memory.
+ If ESCAPED_LOCAL_P is true then escaped local variables are also
+ considered global. */
bool
-pt_solution_includes_global (struct pt_solution *pt)
+pt_solution_includes_global (struct pt_solution *pt, bool escaped_local_p)
{
if (pt->anything
|| pt->nonlocal
|| pt->vars_contains_escaped_heap)
return true;
+ if (escaped_local_p && pt->vars_contains_escaped)
+ return true;
+
/* 'escaped' is also a placeholder so we have to look into it. */
if (pt->escaped)
- return pt_solution_includes_global (&cfun->gimple_df->escaped);
+ return pt_solution_includes_global (&cfun->gimple_df->escaped,
+ escaped_local_p);
if (pt->ipa_escaped)
- return pt_solution_includes_global (&ipa_escaped_pt);
+ return pt_solution_includes_global (&ipa_escaped_pt,
+ escaped_local_p);
return false;
}