cfgexpand: Handle integral vector types and constructors for scope conflicts [PR105769]

This is an expansion of the last patch to also track pointers via vector types and the
constructor that are used with vector types.
In this case we had:
```
_15 = (long unsigned int) &bias;
_10 = (long unsigned int) &cov_jn;
_12 = {_10, _15};
...

MEM[(struct vec *)&cov_jn] ={v} {CLOBBER(bob)};
bias ={v} {CLOBBER(bob)};
MEM[(struct function *)&D.6156] ={v} {CLOBBER(bob)};

...
MEM <vector(2) long unsigned int> [(void *)&D.6172 + 32B] = _12;
MEM[(struct function *)&D.6157] ={v} {CLOBBER(bob)};
```

Anyways tracking the pointers via vector types to say they are alive
at the point where the store of the vector happens fixes the bug by saying
it is alive at the same time as another variable is alive.

Bootstrapped and tested on x86_64-linux-gnu.

	PR tree-optimization/105769

gcc/ChangeLog:

	* cfgexpand.cc (vars_ssa_cache::operator()): For constructors
	walk over the elements.

gcc/testsuite/ChangeLog:

	* g++.dg/torture/pr105769-1.C: New test.

Signed-off-by: Andrew Pinski <quic_apinski@quicinc.com>
This commit is contained in:
Andrew Pinski 2024-11-15 20:22:04 -08:00 committed by Tamar Christina
parent 0014a858a1
commit 4f4722b072
2 changed files with 83 additions and 4 deletions

View file

@ -728,7 +728,7 @@ vars_ssa_cache::operator() (tree name)
gcc_assert (TREE_CODE (name) == SSA_NAME);
if (!POINTER_TYPE_P (TREE_TYPE (name))
&& !INTEGRAL_TYPE_P (TREE_TYPE (name)))
&& !ANY_INTEGRAL_TYPE_P (TREE_TYPE (name)))
return empty;
if (exists (name))
@ -758,7 +758,7 @@ vars_ssa_cache::operator() (tree name)
continue;
if (!POINTER_TYPE_P (TREE_TYPE (use))
&& !INTEGRAL_TYPE_P (TREE_TYPE (use)))
&& !ANY_INTEGRAL_TYPE_P (TREE_TYPE (use)))
continue;
/* Mark the old ssa name needs to be update from the use. */
@ -772,10 +772,22 @@ vars_ssa_cache::operator() (tree name)
so we don't go into an infinite loop for some phi nodes with loops. */
create (use);
gimple *g = SSA_NAME_DEF_STMT (use);
/* CONSTRUCTOR here is always a vector initialization,
walk each element too. */
if (gimple_assign_single_p (g)
&& TREE_CODE (gimple_assign_rhs1 (g)) == CONSTRUCTOR)
{
tree ctr = gimple_assign_rhs1 (g);
unsigned i;
tree elm;
FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (ctr), i, elm)
work_list.safe_push (std::make_pair (elm, use));
}
/* For assignments, walk each operand for possible addresses.
For PHI nodes, walk each argument. */
gimple *g = SSA_NAME_DEF_STMT (use);
if (gassign *a = dyn_cast <gassign *> (g))
else if (gassign *a = dyn_cast <gassign *> (g))
{
/* operand 0 is the lhs. */
for (unsigned i = 1; i < gimple_num_ops (g); i++)

View file

@ -0,0 +1,67 @@
// { dg-do run }
// PR tree-optimization/105769
// The partitioning code would incorrectly have bias
// and a temporary in the same partitioning because
// it was thought bias was not alive when those were alive
// do to vectorization of a store of pointers (that included bias).
#include <functional>
template<size_t n, class T>
struct vec {
T dat[n];
vec() {}
explicit vec(const T& x) { for(size_t i = 0; i < n; i++) dat[i] = x; }
T& operator [](size_t i) { return dat[i]; }
const T& operator [](size_t i) const { return dat[i]; }
};
template<size_t m, size_t n, class T>
using mat = vec<m, vec<n, T>>;
template<size_t n, class T>
using sq_mat = mat<n, n, T>;
using map_t = std::function<size_t(size_t)>;
template<class T_v>
using est_t = std::function<T_v(map_t map)>;
template<class T_v> using est2_t = std::function<T_v(map_t map)>;
map_t id_map() { return [](size_t j) -> size_t { return j; }; }
template<size_t n, class T>
est2_t<void> jacknife(const est_t<vec<n, T>> est, sq_mat<n, T>& cov, vec<n, T>& bias) {
return [est, &cov, &bias](map_t map) -> void
{
bias = est(map);
for(size_t i = 0; i < n; i++)
{
bias[i].print();
}
};
}
template<class T>
void print_cov_ratio() {
sq_mat<2, T> cov_jn;
vec<2, T> bias;
jacknife<2, T>([](map_t map) -> vec<2, T> { vec<2, T> retv; retv[0] = 1; retv[1] = 1; return retv; }, cov_jn, bias)(id_map());
}
struct ab {
long long unsigned a;
short unsigned b;
double operator()() { return a; }
ab& operator=(double rhs) { a = rhs; return *this; }
void print();
};
void
ab::print()
{
}
int main() {
print_cov_ratio<ab>();
return 0;
}