From 4f4722b0722ec343df70e5ec5fd9d5c682ff8149 Mon Sep 17 00:00:00 2001
From: Andrew Pinski <quic_apinski@quicinc.com>
Date: Fri, 15 Nov 2024 20:22:04 -0800
Subject: [PATCH] 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>
---
 gcc/cfgexpand.cc                          | 20 +++++--
 gcc/testsuite/g++.dg/torture/pr105769-1.C | 67 +++++++++++++++++++++++
 2 files changed, 83 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/torture/pr105769-1.C

diff --git a/gcc/cfgexpand.cc b/gcc/cfgexpand.cc
index f6c9f7755a4c..2b27076658fd 100644
--- a/gcc/cfgexpand.cc
+++ b/gcc/cfgexpand.cc
@@ -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++)
diff --git a/gcc/testsuite/g++.dg/torture/pr105769-1.C b/gcc/testsuite/g++.dg/torture/pr105769-1.C
new file mode 100644
index 000000000000..3fe973656b84
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr105769-1.C
@@ -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;
+}
+
-- 
GitLab