aboutsummaryrefslogtreecommitdiff
path: root/gcc/alias.c
diff options
context:
space:
mode:
authorThomas Koenig <tkoenig@gcc.gnu.org>2021-09-13 19:49:49 +0200
committerThomas Koenig <tkoenig@gcc.gnu.org>2021-09-13 19:49:49 +0200
commitb18a97e5dd0935e1c4a626c230f21457d0aad3d5 (patch)
treec1818f41af6fe780deafb6cd6a183f32085fe654 /gcc/alias.c
parente76a53644c9d70e998c0d050e9a456af388c6b61 (diff)
downloadgcc-b18a97e5dd0935e1c4a626c230f21457d0aad3d5.zip
gcc-b18a97e5dd0935e1c4a626c230f21457d0aad3d5.tar.gz
gcc-b18a97e5dd0935e1c4a626c230f21457d0aad3d5.tar.bz2
Merged current trunk to branch.
Diffstat (limited to 'gcc/alias.c')
-rw-r--r--gcc/alias.c61
1 files changed, 32 insertions, 29 deletions
diff --git a/gcc/alias.c b/gcc/alias.c
index f6d7a17..099acab 100644
--- a/gcc/alias.c
+++ b/gcc/alias.c
@@ -1,5 +1,5 @@
/* Alias analysis for GNU C
- Copyright (C) 1997-2020 Free Software Foundation, Inc.
+ Copyright (C) 1997-2021 Free Software Foundation, Inc.
Contributed by John Carr (jfc@mit.edu).
This file is part of GCC.
@@ -159,7 +159,8 @@ static tree decl_for_component_ref (tree);
static int write_dependence_p (const_rtx,
const_rtx, machine_mode, rtx,
bool, bool, bool);
-static int compare_base_symbol_refs (const_rtx, const_rtx);
+static int compare_base_symbol_refs (const_rtx, const_rtx,
+ HOST_WIDE_INT * = NULL);
static void memory_modified_1 (rtx, const_rtx, void *);
@@ -1837,7 +1838,11 @@ rtx_equal_for_memref_p (const_rtx x, const_rtx y)
return label_ref_label (x) == label_ref_label (y);
case SYMBOL_REF:
- return compare_base_symbol_refs (x, y) == 1;
+ {
+ HOST_WIDE_INT distance = 0;
+ return (compare_base_symbol_refs (x, y, &distance) == 1
+ && distance == 0);
+ }
case ENTRY_VALUE:
/* This is magic, don't go through canonicalization et al. */
@@ -2172,10 +2177,20 @@ compare_base_decls (tree base1, tree base2)
return ret;
}
-/* Same as compare_base_decls but for SYMBOL_REF. */
+/* Compare SYMBOL_REFs X_BASE and Y_BASE.
+
+ - Return 1 if Y_BASE - X_BASE is constant, adding that constant
+ to *DISTANCE if DISTANCE is nonnull.
+
+ - Return 0 if no accesses based on X_BASE can alias Y_BASE.
+
+ - Return -1 if one of the two results applies, but we can't tell
+ which at compile time. Update DISTANCE in the same way as
+ for a return value of 1, for the case in which that holds. */
static int
-compare_base_symbol_refs (const_rtx x_base, const_rtx y_base)
+compare_base_symbol_refs (const_rtx x_base, const_rtx y_base,
+ HOST_WIDE_INT *distance)
{
tree x_decl = SYMBOL_REF_DECL (x_base);
tree y_decl = SYMBOL_REF_DECL (y_base);
@@ -2192,8 +2207,8 @@ compare_base_symbol_refs (const_rtx x_base, const_rtx y_base)
std::swap (x_decl, y_decl);
std::swap (x_base, y_base);
}
- /* We handle specially only section anchors and assume that other
- labels may overlap with user variables in an arbitrary way. */
+ /* We handle specially only section anchors. Other symbols are
+ either equal (via aliasing) or refer to different objects. */
if (!SYMBOL_REF_HAS_BLOCK_INFO_P (y_base))
return -1;
/* Anchors contains static VAR_DECLs and CONST_DECLs. We are safe
@@ -2222,14 +2237,13 @@ compare_base_symbol_refs (const_rtx x_base, const_rtx y_base)
{
if (SYMBOL_REF_BLOCK (x_base) != SYMBOL_REF_BLOCK (y_base))
return 0;
- if (SYMBOL_REF_BLOCK_OFFSET (x_base) == SYMBOL_REF_BLOCK_OFFSET (y_base))
- return binds_def ? 1 : -1;
- if (SYMBOL_REF_ANCHOR_P (x_base) != SYMBOL_REF_ANCHOR_P (y_base))
- return -1;
- return 0;
+ if (distance)
+ *distance += (SYMBOL_REF_BLOCK_OFFSET (y_base)
+ - SYMBOL_REF_BLOCK_OFFSET (x_base));
+ return binds_def ? 1 : -1;
}
- /* In general we assume that memory locations pointed to by different labels
- may overlap in undefined ways. */
+ /* Either the symbols are equal (via aliasing) or they refer to
+ different objects. */
return -1;
}
@@ -2513,11 +2527,12 @@ memrefs_conflict_p (poly_int64 xsize, rtx x, poly_int64 ysize, rtx y,
if (GET_CODE (x) == SYMBOL_REF && GET_CODE (y) == SYMBOL_REF)
{
- int cmp = compare_base_symbol_refs (x,y);
+ HOST_WIDE_INT distance = 0;
+ int cmp = compare_base_symbol_refs (x, y, &distance);
/* If both decls are the same, decide by offsets. */
if (cmp == 1)
- return offset_overlap_p (c, xsize, ysize);
+ return offset_overlap_p (c + distance, xsize, ysize);
/* Assume a potential overlap for symbolic addresses that went
through alignment adjustments (i.e., that have negative
sizes), because we can't know how far they are from each
@@ -2526,7 +2541,7 @@ memrefs_conflict_p (poly_int64 xsize, rtx x, poly_int64 ysize, rtx y,
return -1;
/* If decls are different or we know by offsets that there is no overlap,
we win. */
- if (!cmp || !offset_overlap_p (c, xsize, ysize))
+ if (!cmp || !offset_overlap_p (c + distance, xsize, ysize))
return 0;
/* Decls may or may not be different and offsets overlap....*/
return -1;
@@ -3391,14 +3406,6 @@ init_alias_analysis (void)
rpo = XNEWVEC (int, n_basic_blocks_for_fn (cfun));
rpo_cnt = pre_and_rev_post_order_compute (NULL, rpo, false);
- /* The prologue/epilogue insns are not threaded onto the
- insn chain until after reload has completed. Thus,
- there is no sense wasting time checking if INSN is in
- the prologue/epilogue until after reload has completed. */
- bool could_be_prologue_epilogue = ((targetm.have_prologue ()
- || targetm.have_epilogue ())
- && reload_completed);
-
pass = 0;
do
{
@@ -3444,10 +3451,6 @@ init_alias_analysis (void)
{
rtx note, set;
- if (could_be_prologue_epilogue
- && prologue_epilogue_contains (insn))
- continue;
-
/* If this insn has a noalias note, process it, Otherwise,
scan for sets. A simple set will have no side effects
which could change the base value of any other register. */