This patch completely eliminates the ptr_info_def structure. THe 3
fields are moved into a prange_storage object, and all the routines are
adjusted to pick up the fields there. None of the API changes because
everything keys off the SSA_NAME now. Again, fairly mechanical,
although I did clean up a few functions whose naming over the set had
gotten kind of confusing.
I shuffled some of the bits in a prange_storage object so that this
adjustment costs a bit less memory.
Bootstrapped on x86_64-pc-linux-gnu with no regressions.
Andrew
From 0cf7646e7e26bdea97966239fa71ccdf56f706a2 Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <[email protected]>
Date: Thu, 22 Oct 2026 16:24:27 -0400
Subject: [PATCH 7/9] Eliminate ptr_info_def structure
This eliminates the ptr_info_def structure, and puts the three component
members directly into a prange_storage object.
Assisted-by: Claude Opus 5
Assisted-by: GPT-6.1-Sol
* tree-core.h (struct ptr_info_def): Remove declaration.
* tree-ssanames.cc (range_info_p): Remove.
(range_info_fits_p): Adjust.
(ssa_name_prange_storage): Rename from ssa_name_ptr_info and adjust.
(set_pt_solution): New.
(get_pt_solution): Rename from get_ptr_info and adjust.
(ssa_name_pt_solution): Adjust.
(set_ssa_name_pt_solution): Adjust.
(range_info_set_range): Adjust.
(set_range_info): Adjust.
(set_ptr_nonnull): Adjust.
(get_nonzero_bits_1): Adjust.
(get_known_nonzero_bits_1 ): Adjust.
(get_ptr_info_alignment): Adjust.
(mark_ptr_info_alignment_unknown): Adjust.
(set_ptr_info_alignment): Adjust.
(set_ssa_name_ptr_info): Remove.
(duplicate_ssa_name_ptr_info): Adjust.
(duplicate_ssa_name_range_info): Adjust.
(duplicate_ssa_name_fn): Adjust.
(reset_flow_sensitive_info): Adjust.
(flow_sensitive_info_storage::save): Adjust.
(flow_sensitive_info_storage::restore): Adjust.
* tree-ssanames.h (struct ptr_info_def): Remove.
(flow_sensitive_info_storage::align): Remove.
(flow_sensitive_info_storage::misalign): Remove.
* value-range-storage.cc (prange_storage::prange_storage): Set
new fields.
* value-range-storage.h (prange_storage::ptr_info): Remove.
(prange_storage::pt): New.
(prange_storage::align): New.
(prange_storage::misalign): New.
---
gcc/tree-core.h | 1 -
gcc/tree-ssanames.cc | 210 +++++++++++++++++--------------------
gcc/tree-ssanames.h | 33 +-----
gcc/value-range-storage.cc | 9 +-
gcc/value-range-storage.h | 22 ++--
5 files changed, 121 insertions(+), 154 deletions(-)
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index 6bab44f3c6d..bea6bb5cc11 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -32,7 +32,6 @@ along with GCC; see the file COPYING3. If not see
struct function;
struct real_value;
struct fixed_value;
-struct ptr_info_def;
struct die_struct;
class irange;
diff --git a/gcc/tree-ssanames.cc b/gcc/tree-ssanames.cc
index e244c34a799..c0e5de75f59 100644
--- a/gcc/tree-ssanames.cc
+++ b/gcc/tree-ssanames.cc
@@ -73,20 +73,12 @@ unsigned int ssa_name_nodes_created;
#define FREE_SSANAMES(fun) (fun)->gimple_df->free_ssanames
#define FREE_SSANAMES_QUEUE(fun) (fun)->gimple_df->free_ssanames_queue
-/* Return TRUE if NAME has global range info. */
-
-inline bool
-range_info_p (const_tree name)
-{
- return SSA_NAME_RANGE_INFO (name);
-}
-
/* Return TRUE if R fits in the global range of NAME. */
inline bool
range_info_fits_p (tree name, const vrange &r)
{
- gcc_checking_assert (range_info_p (name));
+ gcc_checking_assert (SSA_NAME_RANGE_INFO (name));
vrange_storage *mem = SSA_NAME_RANGE_INFO (name);
return mem->fits_p (r);
}
@@ -111,38 +103,58 @@ range_info_free (tree name)
ggc_free (mem);
}
-/* Return the aliasing information for ssa-name NAME, or NULL if there
- is none. Return NULL for non pointer types. */
+/* Return NAME's pointer range storage, or NULL if none exists. */
-static inline struct ptr_info_def *
-ssa_name_ptr_info (const_tree name)
+static inline prange_storage *
+ssa_name_prange_storage (const_tree name)
{
vrange_storage *mem = SSA_NAME_RANGE_INFO (name);
if (!mem || mem->m_discriminator != VR_PRANGE)
return NULL;
- return static_cast <prange_storage *> (mem)->ptr_info;
+ return static_cast <prange_storage *> (mem);
+}
+
+/* Attach PT to NAME, creating range storage if necessary. */
+
+static void
+set_pt_solution (tree name, pt_solution *pt)
+{
+ gcc_checking_assert (POINTER_TYPE_P (TREE_TYPE (name)));
+ if (!SSA_NAME_RANGE_INFO (name))
+ SSA_NAME_RANGE_INFO (name) = ggc_alloc_vrange_storage (TREE_TYPE (name));
+ ssa_name_prange_storage (name)->pt = pt;
}
-/* Defined below. */
-static struct ptr_info_def *get_ptr_info (tree);
+/* Return NAME's solution, creating an unknown solution if necessary. */
-/* Return the points-to solution for ssa-name NAME. Return NULL if it has
- none or is a non pointer types. */
+static pt_solution *
+get_pt_solution (tree name)
+{
+ gcc_assert (POINTER_TYPE_P (TREE_TYPE (name)));
+ prange_storage *s = ssa_name_prange_storage (name);
+ if (s && s->pt)
+ return s->pt;
+ pt_solution *pt = ggc_cleared_alloc<pt_solution> ();
+ pt_solution_reset (pt);
+ set_pt_solution (name, pt);
+ return pt;
+}
+
+/* Return NAME's points-to solution, or NULL if none exists. */
const pt_solution *
ssa_name_pt_solution (const_tree name)
{
- struct ptr_info_def *pi = ssa_name_ptr_info (name);
- return pi ? &pi->pt : NULL;
+ prange_storage *s = ssa_name_prange_storage (name);
+ return s ? s->pt : NULL;
}
-/* Make PT the points-to solution for NAME, which must have pointer type. */
+/* Make PT the points-to solution for NAME. */
void
set_ssa_name_pt_solution (tree name, const pt_solution &pt)
{
- /* get_ptr_info asserts NAME is a pointer type. */
- get_ptr_info (name)->pt = pt;
+ *get_pt_solution (name) = pt;
}
/* Return the global range for NAME in R. */
@@ -159,20 +171,29 @@ range_info_get_range (const_tree name, vrange &r)
inline bool
range_info_set_range (tree name, const vrange &r)
{
- if (!range_info_p (name) || !range_info_fits_p (name, r))
+ if (!SSA_NAME_RANGE_INFO (name) || !range_info_fits_p (name, r))
{
- // Aliasing info belongs to NAME, not to the prange storage object which
- // might get reallocated. ptr_info_def addresses may be cached
- // elsewhere, so save and copy it back after any reallocation.
- ptr_info_def *pi = ssa_name_ptr_info (name);
- if (range_info_p (name))
+ // Preserve SSA-owned points-to and alignment information when the
+ // variable-sized range storage must grow.
+ pt_solution *pt = NULL;
+ unsigned int align = 0, misalign = 0;
+ if (prange_storage *old = ssa_name_prange_storage (name))
+ {
+ pt = old->pt;
+ align = old->align;
+ misalign = old->misalign;
+ }
+ if (SSA_NAME_RANGE_INFO (name))
range_info_free (name);
vrange_storage *mem = range_info_alloc (name, r);
- if (pi && mem)
+ if (mem && (pt || align))
{
gcc_checking_assert (mem->m_discriminator == VR_PRANGE);
- static_cast <prange_storage *> (mem)->ptr_info = pi;
+ prange_storage *s = static_cast <prange_storage *> (mem);
+ s->pt = pt;
+ s->align = align;
+ s->misalign = misalign;
}
return mem != NULL;
}
@@ -467,7 +488,7 @@ set_range_info (tree name, const vrange &r)
// Pick up the current range, or VARYING if none.
tree type = TREE_TYPE (name);
value_range tmp (type);
- if (range_info_p (name))
+ if (SSA_NAME_RANGE_INFO (name))
range_info_get_range (name, tmp);
else
tmp.set_varying (type);
@@ -478,9 +499,9 @@ set_range_info (tree name, const vrange &r)
if (POINTER_TYPE_P (type))
{
- // If R is nonnull and pi is not, set nonnull.
- struct ptr_info_def *pi = get_ptr_info (name);
- if (!tmp.contains_zero_p () && pi->pt.null)
+ // Preserve nonnullness in the points-to solution as well.
+ pt_solution *pt = get_pt_solution (name);
+ if (!tmp.contains_zero_p () && pt->null)
set_ptr_nonnull (name);
}
@@ -508,8 +529,7 @@ void
set_ptr_nonnull (tree name)
{
gcc_assert (POINTER_TYPE_P (TREE_TYPE (name)));
- struct ptr_info_def *pi = get_ptr_info (name);
- pi->pt.null = 0;
+ get_pt_solution (name)->null = 0;
}
/* Update the non-zero bits bitmask of NAME. */
@@ -574,7 +594,7 @@ get_nonzero_bits_1 (const_tree name)
return wi::shwi (-1, precision);
}
- if (!range_info_p (name) || !irange::supports_p (TREE_TYPE (name)))
+ if (!SSA_NAME_RANGE_INFO (name) || !irange::supports_p (TREE_TYPE (name)))
return wi::shwi (-1, precision);
int_range_max tmp;
@@ -622,7 +642,7 @@ get_known_nonzero_bits_1 (const_tree name)
if (TREE_CODE (name) != SSA_NAME || POINTER_TYPE_P (TREE_TYPE (name)))
return wi::shwi (0, precision);
- if (!range_info_p (name) || !irange::supports_p (TREE_TYPE (name)))
+ if (!SSA_NAME_RANGE_INFO (name) || !irange::supports_p (TREE_TYPE (name)))
return wi::shwi (0, precision);
int_range_max tmp;
@@ -776,7 +796,7 @@ bool
get_ptr_info_alignment (const_tree name, unsigned int *alignp,
unsigned int *misalignp)
{
- struct ptr_info_def *pi = ssa_name_ptr_info (name);
+ prange_storage *pi = ssa_name_prange_storage (name);
if (pi && pi->align)
{
@@ -795,7 +815,7 @@ get_ptr_info_alignment (const_tree name, unsigned int *alignp,
void
mark_ptr_info_alignment_unknown (tree name)
{
- struct ptr_info_def *pi = ssa_name_ptr_info (name);
+ prange_storage *pi = ssa_name_prange_storage (name);
if (pi)
{
@@ -815,50 +835,14 @@ set_ptr_info_alignment (tree name, unsigned int align, unsigned int misalign)
gcc_assert ((align & (align - 1)) == 0);
gcc_assert ((misalign & ~(align - 1)) == 0);
- struct ptr_info_def *pi = get_ptr_info (name);
+ gcc_assert (POINTER_TYPE_P (TREE_TYPE (name)));
+ if (!SSA_NAME_RANGE_INFO (name))
+ SSA_NAME_RANGE_INFO (name) = ggc_alloc_vrange_storage (TREE_TYPE (name));
+ prange_storage *pi = ssa_name_prange_storage (name);
pi->align = align;
pi->misalign = misalign;
}
-/* Make PI the aliasing information for NAME. Allocate a VARYING range if
- NAME does not already have a range. */
-
-static void
-set_ssa_name_ptr_info (tree name, struct ptr_info_def *pi)
-{
- gcc_checking_assert (POINTER_TYPE_P (TREE_TYPE (name)));
-
- if (!range_info_p (name))
- SSA_NAME_RANGE_INFO (name) = ggc_alloc_vrange_storage (TREE_TYPE (name));
-
- vrange_storage *mem = SSA_NAME_RANGE_INFO (name);
- gcc_checking_assert (mem && mem->m_discriminator == VR_PRANGE);
- static_cast <prange_storage *> (mem)->ptr_info = pi;
-}
-
-/* Return the alias information associated with pointer T. It creates a
- new instance if none existed. */
-
-static struct ptr_info_def *
-get_ptr_info (tree t)
-{
- struct ptr_info_def *pi;
-
- gcc_assert (POINTER_TYPE_P (TREE_TYPE (t)));
-
- pi = ssa_name_ptr_info (t);
- if (pi == NULL)
- {
- // The cleared allocation leaves align and misalign zero, which is
- // what unknown alignment is, so there is nothing more to initialize.
- pi = ggc_cleared_alloc<ptr_info_def> ();
- pt_solution_reset (&pi->pt);
- set_ssa_name_ptr_info (t, pi);
- }
-
- return pi;
-}
-
/* Creates a new SSA name using the template NAME tobe defined by
statement STMT in function FN. */
@@ -888,16 +872,22 @@ void
duplicate_ssa_name_ptr_info (tree dest, tree src)
{
gcc_assert (POINTER_TYPE_P (TREE_TYPE (dest)));
- gcc_assert (!ssa_name_ptr_info (dest));
+ gcc_assert (!ssa_name_pt_solution (dest));
- struct ptr_info_def *ptr_info = (src ? ssa_name_ptr_info (src) : NULL);
- if (!ptr_info)
+ prange_storage *s = src ? ssa_name_prange_storage (src) : NULL;
+ if (!s || (!s->pt && !s->align))
return;
- struct ptr_info_def *new_ptr_info = ggc_alloc<ptr_info_def> ();
- *new_ptr_info = *ptr_info;
-
- set_ssa_name_ptr_info (dest, new_ptr_info);
+ /* Copy alignment independently of whether SRC has a PTA solution. */
+ unsigned int align = s->align, misalign = s->misalign;
+ if (s->pt)
+ {
+ pt_solution *copy = ggc_alloc<pt_solution> ();
+ *copy = *s->pt;
+ set_pt_solution (dest, copy);
+ }
+ if (align)
+ set_ptr_info_alignment (dest, align, misalign);
}
/* Copy any global range and aliasing information from SRC to NAME. */
@@ -905,9 +895,9 @@ duplicate_ssa_name_ptr_info (tree dest, tree src)
void
duplicate_ssa_name_range_info (tree name, tree src)
{
- gcc_checking_assert (!range_info_p (name));
+ gcc_checking_assert (!SSA_NAME_RANGE_INFO (name));
- if (!range_info_p (src))
+ if (!SSA_NAME_RANGE_INFO (src))
return;
value_range src_range (TREE_TYPE (src));
@@ -945,7 +935,7 @@ duplicate_ssa_name_fn (struct function *fn, tree name, gimple *stmt)
{
tree new_name = copy_ssa_name_fn (fn, name, stmt);
- if (range_info_p (name))
+ if (SSA_NAME_RANGE_INFO (name))
duplicate_ssa_name_range_info (new_name, name);
return new_name;
@@ -959,15 +949,16 @@ void
reset_flow_sensitive_info (tree name)
{
/* Aliasing info is not flow sensitive, so preserve it if present. */
- ptr_info_def *pi = ssa_name_ptr_info (name);
+ prange_storage *s = ssa_name_prange_storage (name);
+ pt_solution *pt = s ? s->pt : NULL;
SSA_NAME_RANGE_INFO (name) = NULL;
- if (pi)
+ if (pt)
{
- set_ssa_name_ptr_info (name, pi);
+ set_pt_solution (name, pt);
/* [E]VRP can derive context sensitive alignment info and
- non-nullness properties. We must reset both. */
- mark_ptr_info_alignment_unknown (name);
- pi->pt.null = 1;
+ non-nullness properties. We must reset both. The alignment went
+ with the range storage above; only the nullness is left. */
+ pt->null = 1;
}
// Clear range info in the current range query.
@@ -1118,13 +1109,8 @@ flow_sensitive_info_storage::save (tree name)
return;
}
state = -1;
- if (!get_ptr_info_alignment (name, &align, &misalign))
- {
- align = 0;
- misalign = 0;
- }
- auto ptr_info = ssa_name_ptr_info (name);
- null = ptr_info ? ptr_info->pt.null : true;
+ const pt_solution *pt = ssa_name_pt_solution (name);
+ null = pt ? pt->null : true;
}
/* Restore the flow sensitive info from NAME. */
@@ -1133,6 +1119,9 @@ void
flow_sensitive_info_storage::restore (tree name)
{
gcc_assert (state != 0);
+ /* The storage carries the range, its bitmask and -- for now -- the
+ alignment, so reinstating it restores all three. Only the nullness
+ lives outside it. */
SSA_NAME_RANGE_INFO (name) = range_info;
if (!POINTER_TYPE_P (TREE_TYPE (name)))
{
@@ -1140,16 +1129,9 @@ flow_sensitive_info_storage::restore (tree name)
return;
}
gcc_assert (state == -1);
- auto ptr_info = ssa_name_ptr_info (name);
- /* If there was no flow sensitive info on the pointer
- just return, there is nothing to restore to. */
- if (!ptr_info)
- return;
- if (align != 0)
- set_ptr_info_alignment (name, align, misalign);
- else
- mark_ptr_info_alignment_unknown (name);
- ssa_name_ptr_info (name)->pt.null = null;
+ prange_storage *s = ssa_name_prange_storage (name);
+ if (s && s->pt)
+ s->pt->null = null;
}
/* Save off the flow sensitive info from NAME.
diff --git a/gcc/tree-ssanames.h b/gcc/tree-ssanames.h
index fa066f7f8ea..68afacb0f29 100644
--- a/gcc/tree-ssanames.h
+++ b/gcc/tree-ssanames.h
@@ -20,32 +20,6 @@ along with GCC; see the file COPYING3. If not see
#ifndef GCC_TREE_SSANAMES_H
#define GCC_TREE_SSANAMES_H
-/* Aliasing information for SSA_NAMEs representing pointer variables. */
-
-struct GTY(()) ptr_info_def
-{
- /* The points-to solution. */
- struct pt_solution pt;
-
- /* Alignment and misalignment of the pointer in bytes. Together
- align and misalign specify low known bits of the pointer.
- ptr & (align - 1) == misalign. */
-
- /* When known, this is the power-of-two byte alignment of the object this
- pointer points into. This is usually DECL_ALIGN_UNIT for decls and
- MALLOC_ABI_ALIGNMENT for allocated storage. When the alignment is not
- known, it is zero. Do not access directly: the only accessors are
- get_ptr_info_alignment, set_ptr_info_alignment and
- mark_ptr_info_alignment_unknown, and they take the SSA name rather
- than this structure, so that the representation can move. */
- unsigned int align;
-
- /* When alignment is known, the byte offset this pointer differs from the
- above alignment. Access only through the same helper functions as align
- above. */
- unsigned int misalign;
-};
-
/* Return NAME's points-to solution, or NULL if it has none. Returns NULL
for a non pointer type. */
extern const pt_solution *ssa_name_pt_solution (const_tree name);
@@ -157,11 +131,10 @@ private:
-1 means a pointer type is saved.
-2 means a pointer type is saved but no information was saved. */
int state = 0;
- /* The range info for non pointers */
+ /* The range info, which for a pointer also carries the bitmask and the
+ alignment, so those need no separate slot here. */
vrange_storage *range_info = nullptr;
- /* Flow sensitive pointer information. */
- unsigned int align = 0;
- unsigned int misalign = 0;
+ /* Flow sensitive pointer information not held in the range. */
bool null = true;
};
diff --git a/gcc/value-range-storage.cc b/gcc/value-range-storage.cc
index b121ffac754..35997372e7c 100644
--- a/gcc/value-range-storage.cc
+++ b/gcc/value-range-storage.cc
@@ -638,9 +638,12 @@ prange_storage::alloc (vrange_internal_alloc &allocator, const prange &r,
prange_storage::prange_storage (const prange &r) : vrange_storage (VR_PRANGE)
{
- // Aliasing info is not part of the range, so it is never copied from one.
- // Only set_ssa_name_ptr_info() in tree-ssanames.cc ever makes this non-null.
- ptr_info = NULL;
+ // None of these is part of the range, so none is ever copied from one.
+ // Only the accessors in tree-ssanames.cc ever make them non-zero, and
+ // range_info_set_range carries them across a reallocation.
+ pt = NULL;
+ align = 0;
+ misalign = 0;
unsigned num_words;
enum prange_kind kind = prange_format (r, num_words);
diff --git a/gcc/value-range-storage.h b/gcc/value-range-storage.h
index 46e98684360..f4c264d5ede 100644
--- a/gcc/value-range-storage.h
+++ b/gcc/value-range-storage.h
@@ -113,6 +113,13 @@ const unsigned int PRANGE_STORAGE_NINTS = 4;
// Efficient memory storage for a prange.
class GTY((tag ("VR_PRANGE"))) prange_storage : public vrange_storage
{
+private:
+ // vrange_storage ends after four bytes but the first pointer member below
+ // needs eight-byte alignment, so there is a four-byte hole.
+ enum prange_kind m_kind : 4;
+ unsigned int m_has_bitmask : 1;
+ unsigned int m_points_to_p : 1;
+
public:
friend void gt_ggc_mx_vrange_storage(void *);
friend void gt_pch_nx_vrange_storage(void *);
@@ -126,18 +133,21 @@ public:
bool fits_p (const prange &r) const;
void dump () const;
- // Pointer aliasing information. Managed separately, and reached only
- // through the accessors in tree-ssanames.h.
- struct ptr_info_def *ptr_info;
+ // The points-to solution for the SSA name is flow insensitive and is
+ // reached only through ssa_name_pt_solution.
+ struct pt_solution *pt;
+
+ // Alignment and misalignment of the pointer in bytes. Together
+ // align and misalign specify low known bits of the pointer.
+ // ptr & (align - 1) == misalign.
+ unsigned int align;
+ unsigned int misalign;
private:
DISABLE_COPY_AND_ASSIGN (prange_storage);
prange_storage (const prange &r);
static enum prange_kind prange_format (const prange &r, unsigned &num_words);
- enum prange_kind m_kind;
- bool m_has_bitmask;
- bool m_points_to_p;
tree m_pt;
// We don't use TRAILING_WIDE_INT_ACCESSOR because the getters here
--
2.56.0