The problem in this PR is an off-by-one bug. We should've allocated num_ssa_names + 1. However, in fixing this, I noticed that num_ssa_names can change between queries, so I have replaced the array with an auto_vec and added code to grow the vector as necessary.
Tested on x86-64 Linux. PR 103062 gcc/ChangeLog: PR tree-optimization/103062 * value-pointer-equiv.cc (ssa_equiv_stack::ssa_equiv_stack): Increase size of allocation by 1. (ssa_equiv_stack::push_replacement): Grow as needed. (ssa_equiv_stack::get_replacement): Same. (pointer_equiv_analyzer::pointer_equiv_analyzer): Same. (pointer_equiv_analyzer::~pointer_equiv_analyzer): Remove delete. (pointer_equiv_analyzer::set_global_equiv): Grow as needed. (pointer_equiv_analyzer::get_equiv): Same. (pointer_equiv_analyzer::get_equiv_expr): Remove const. * value-pointer-equiv.h (class pointer_equiv_analyzer): Remove const markers. Use auto_vec instead of tree *. gcc/testsuite/ChangeLog: * gcc.dg/pr103062.c: New test. --- gcc/testsuite/gcc.dg/pr103062.c | 7 ++++++ gcc/value-pointer-equiv.cc | 43 ++++++++++++++++++++++++--------- gcc/value-pointer-equiv.h | 6 ++--- 3 files changed, 41 insertions(+), 15 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/pr103062.c diff --git a/gcc/testsuite/gcc.dg/pr103062.c b/gcc/testsuite/gcc.dg/pr103062.c new file mode 100644 index 00000000000..cbc371b4cd5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr103062.c @@ -0,0 +1,7 @@ +// { dg-do compile } +// { dg-options "-O2 -fno-tree-forwprop" } + +void *a, *b, *c; +void foo(void) { + c = (void *)((__INTPTR_TYPE__)a & (__INTPTR_TYPE__)b); +} diff --git a/gcc/value-pointer-equiv.cc b/gcc/value-pointer-equiv.cc index 7d2658b77a4..f07d5d5c7ce 100644 --- a/gcc/value-pointer-equiv.cc +++ b/gcc/value-pointer-equiv.cc @@ -58,7 +58,7 @@ public: void enter (basic_block); void leave (basic_block); void push_replacement (tree name, tree replacement); - tree get_replacement (tree name) const; + tree get_replacement (tree name); private: auto_vec<std::pair <tree, tree>> m_stack; @@ -68,7 +68,7 @@ private: ssa_equiv_stack::ssa_equiv_stack () { - m_replacements.safe_grow_cleared (num_ssa_names); + m_replacements.safe_grow_cleared (num_ssa_names + 1); } // Pushes a marker at the given point. @@ -99,29 +99,38 @@ ssa_equiv_stack::leave (basic_block) void ssa_equiv_stack::push_replacement (tree name, tree replacement) { - tree old = m_replacements[SSA_NAME_VERSION (name)]; - m_replacements[SSA_NAME_VERSION (name)] = replacement; + unsigned v = SSA_NAME_VERSION (name); + + if (v >= m_replacements.length ()) + m_replacements.safe_grow_cleared (num_ssa_names + 1); + + tree old = m_replacements[v]; + m_replacements[v] = replacement; m_stack.safe_push (std::make_pair (name, old)); } // Return the equivalence of NAME. tree -ssa_equiv_stack::get_replacement (tree name) const +ssa_equiv_stack::get_replacement (tree name) { - return m_replacements[SSA_NAME_VERSION (name)]; + unsigned v = SSA_NAME_VERSION (name); + + if (v >= m_replacements.length ()) + m_replacements.safe_grow_cleared (num_ssa_names + 1); + + return m_replacements[v]; } pointer_equiv_analyzer::pointer_equiv_analyzer (gimple_ranger *r) { m_ranger = r; - m_global_points = new tree[num_ssa_names] (); + m_global_points.safe_grow_cleared (num_ssa_names + 1); m_cond_points = new ssa_equiv_stack; } pointer_equiv_analyzer::~pointer_equiv_analyzer () { - delete[] m_global_points; delete m_cond_points; } @@ -130,7 +139,12 @@ pointer_equiv_analyzer::~pointer_equiv_analyzer () void pointer_equiv_analyzer::set_global_equiv (tree ssa, tree pointee) { - m_global_points[SSA_NAME_VERSION (ssa)] = pointee; + unsigned v = SSA_NAME_VERSION (ssa); + + if (v >= m_global_points.length ()) + m_global_points.safe_grow_cleared (num_ssa_names + 1); + + m_global_points[v] = pointee; } // Set the conditional pointer equivalency for SSA to POINTEE. @@ -146,9 +160,14 @@ pointer_equiv_analyzer::set_cond_equiv (tree ssa, tree pointee) // conditional info. tree -pointer_equiv_analyzer::get_equiv (tree ssa) const +pointer_equiv_analyzer::get_equiv (tree ssa) { - tree ret = m_global_points[SSA_NAME_VERSION (ssa)]; + unsigned v = SSA_NAME_VERSION (ssa); + + if (v >= m_global_points.length ()) + m_global_points.safe_grow_cleared (num_ssa_names + 1); + + tree ret = m_global_points[v]; if (ret) return ret; return m_cond_points->get_replacement (ssa); @@ -211,7 +230,7 @@ pointer_equiv_analyzer::leave (basic_block bb) // nor an invariant. tree -pointer_equiv_analyzer::get_equiv_expr (tree_code code, tree expr) const +pointer_equiv_analyzer::get_equiv_expr (tree_code code, tree expr) { if (code == SSA_NAME) return get_equiv (expr); diff --git a/gcc/value-pointer-equiv.h b/gcc/value-pointer-equiv.h index 0921579d52a..dc747d0af70 100644 --- a/gcc/value-pointer-equiv.h +++ b/gcc/value-pointer-equiv.h @@ -38,17 +38,17 @@ public: void enter (basic_block); void leave (basic_block); void visit_stmt (gimple *stmt); - tree get_equiv (tree ssa) const; + tree get_equiv (tree ssa); private: void visit_edge (edge e); - tree get_equiv_expr (tree_code code, tree expr) const; + tree get_equiv_expr (tree_code code, tree expr); void set_global_equiv (tree ssa, tree pointee); void set_cond_equiv (tree ssa, tree pointee); gimple_ranger *m_ranger; // Global pointer equivalency indexed by SSA_NAME_VERSION. - tree *m_global_points; + auto_vec<tree> m_global_points; // Conditional pointer equivalency. class ssa_equiv_stack *m_cond_points; }; -- 2.31.1