This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH 3/5] Build ARRAY_REFs when the base is of ARRAY_TYPE.


When SRA completely scalarizes an array, this patch changes the generated accesses from e.g.

   MEM[(int[8] *)&a + 4B] = 1;

to

   a[1] = 1;

This overcomes a limitation in dom2, that accesses to equivalent chunks of e.g. MEM[(int[8] *)&a] are not hashable_expr_equal_p with accesses to e.g. MEM[(int[8] *)&a]. This is necessary for constant propagation in the ssa-dom-cse-2.c testcase (after the next patch that makes SRA handle constant-pool loads).

I tried to work around this by making dom2's hashable_expr_equal_p less conservative, but found that on platforms without AArch64's vectorized reductions (specifically Alpha, hppa, PowerPC, and SPARC, mentioned in ssa-dom-cse-2.c), I also needed to make MEM[(int[8] *)&a] equivalent to a[0], etc.; a complete overhaul of hashable_expr_equal_p seems like a larger task than this patch series.

I can't see how to write a testcase for this in C though as direct assignment to an array is not possible; such assignments occur only with constant pool data, which is dealt with in the next patch.

Bootstrap + check-gcc on x86-none-linux-gnu, arm-none-linux-gnueabihf, aarch64-none-linux-gnu.

gcc/ChangeLog:

	* tree-sra.c (completely_scalarize): Move some code into:
	(get_elem_size): New.
	(build_ref_for_offset): Build ARRAY_REF if base is aligned array.
---
 gcc/tree-sra.c | 110 ++++++++++++++++++++++++++++++++++++---------------------
 1 file changed, 69 insertions(+), 41 deletions(-)

diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index 08fa8dc..af35fcc 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -957,6 +957,20 @@ scalarizable_type_p (tree type)
   }
 }
 
+static bool
+get_elem_size (const_tree type, unsigned HOST_WIDE_INT *sz_out)
+{
+  gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
+  tree t_size = TYPE_SIZE (TREE_TYPE (type));
+  if (!t_size || !tree_fits_uhwi_p (t_size))
+    return false;
+  unsigned HOST_WIDE_INT sz = tree_to_uhwi (t_size);
+  if (!sz)
+    return false;
+  *sz_out = sz;
+  return true;
+}
+
 static void scalarize_elem (tree, HOST_WIDE_INT, HOST_WIDE_INT, tree, tree);
 
 /* Create total_scalarization accesses for all scalar fields of a member
@@ -985,10 +999,9 @@ completely_scalarize (tree base, tree decl_type, HOST_WIDE_INT offset, tree ref)
     case ARRAY_TYPE:
       {
 	tree elemtype = TREE_TYPE (decl_type);
-	tree elem_size = TYPE_SIZE (elemtype);
-	gcc_assert (elem_size && tree_fits_uhwi_p (elem_size));
-	int el_size = tree_to_uhwi (elem_size);
-	gcc_assert (el_size);
+	unsigned HOST_WIDE_INT el_size;
+	if (!get_elem_size (decl_type, &el_size))
+	  gcc_assert (false);
 
 	tree minidx = TYPE_MIN_VALUE (TYPE_DOMAIN (decl_type));
 	tree maxidx = TYPE_MAX_VALUE (TYPE_DOMAIN (decl_type));
@@ -1563,7 +1576,7 @@ build_ref_for_offset (location_t loc, tree base, HOST_WIDE_INT offset,
   tree off;
   tree mem_ref;
   HOST_WIDE_INT base_offset;
-  unsigned HOST_WIDE_INT misalign;
+  unsigned HOST_WIDE_INT misalign, el_sz;
   unsigned int align;
 
   gcc_checking_assert (offset % BITS_PER_UNIT == 0);
@@ -1572,47 +1585,62 @@ build_ref_for_offset (location_t loc, tree base, HOST_WIDE_INT offset,
 
   /* get_addr_base_and_unit_offset returns NULL for references with a variable
      offset such as array[var_index].  */
-  if (!base)
-    {
-      gassign *stmt;
-      tree tmp, addr;
-
-      gcc_checking_assert (gsi);
-      tmp = make_ssa_name (build_pointer_type (TREE_TYPE (prev_base)));
-      addr = build_fold_addr_expr (unshare_expr (prev_base));
-      STRIP_USELESS_TYPE_CONVERSION (addr);
-      stmt = gimple_build_assign (tmp, addr);
-      gimple_set_location (stmt, loc);
-      if (insert_after)
-	gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
-      else
-	gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
-
-      off = build_int_cst (reference_alias_ptr_type (prev_base),
-			   offset / BITS_PER_UNIT);
-      base = tmp;
-    }
-  else if (TREE_CODE (base) == MEM_REF)
-    {
-      off = build_int_cst (TREE_TYPE (TREE_OPERAND (base, 1)),
-			   base_offset + offset / BITS_PER_UNIT);
-      off = int_const_binop (PLUS_EXPR, TREE_OPERAND (base, 1), off);
-      base = unshare_expr (TREE_OPERAND (base, 0));
+  if (base
+      && TREE_CODE (TREE_TYPE (base)) == ARRAY_TYPE
+      && misalign == 0
+      && get_elem_size (TREE_TYPE (base), &el_sz)
+      && ((offset % el_sz) == 0)
+      && useless_type_conversion_p (exp_type, TREE_TYPE (TREE_TYPE (base)))
+      && (align >= TYPE_ALIGN (exp_type)))
+    {
+      tree idx = build_int_cst (TYPE_DOMAIN (TREE_TYPE (base)), offset / el_sz);
+      base = unshare_expr (base);
+      mem_ref = build4 (ARRAY_REF, exp_type, base, idx, NULL_TREE, NULL_TREE);
     }
   else
     {
-      off = build_int_cst (reference_alias_ptr_type (base),
-			   base_offset + offset / BITS_PER_UNIT);
-      base = build_fold_addr_expr (unshare_expr (base));
-    }
+      if (!base)
+	{
+	  gassign *stmt;
+	  tree tmp, addr;
+
+	  gcc_checking_assert (gsi);
+	  tmp = make_ssa_name (build_pointer_type (TREE_TYPE (prev_base)));
+	  addr = build_fold_addr_expr (unshare_expr (prev_base));
+	  STRIP_USELESS_TYPE_CONVERSION (addr);
+	  stmt = gimple_build_assign (tmp, addr);
+	  gimple_set_location (stmt, loc);
+	  if (insert_after)
+	    gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
+	  else
+	    gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
 
-  misalign = (misalign + offset) & (align - 1);
-  if (misalign != 0)
-    align = (misalign & -misalign);
-  if (align != TYPE_ALIGN (exp_type))
-    exp_type = build_aligned_type (exp_type, align);
+	  off = build_int_cst (reference_alias_ptr_type (prev_base),
+			       offset / BITS_PER_UNIT);
+	  base = tmp;
+	}
+      else if (TREE_CODE (base) == MEM_REF)
+	{
+	  off = build_int_cst (TREE_TYPE (TREE_OPERAND (base, 1)),
+			       base_offset + offset / BITS_PER_UNIT);
+	  off = int_const_binop (PLUS_EXPR, TREE_OPERAND (base, 1), off);
+	  base = unshare_expr (TREE_OPERAND (base, 0));
+	}
+      else
+	{
+	  off = build_int_cst (reference_alias_ptr_type (base),
+			       base_offset + offset / BITS_PER_UNIT);
+	  base = build_fold_addr_expr (unshare_expr (base));
+	}
 
-  mem_ref = fold_build2_loc (loc, MEM_REF, exp_type, base, off);
+      misalign = (misalign + offset) & (align - 1);
+      if (misalign != 0)
+	align = (misalign & -misalign);
+      if (align != TYPE_ALIGN (exp_type))
+	exp_type = build_aligned_type (exp_type, align);
+
+      mem_ref = fold_build2_loc (loc, MEM_REF, exp_type, base, off);
+    }
   if (TREE_THIS_VOLATILE (prev_base))
     TREE_THIS_VOLATILE (mem_ref) = 1;
   if (TREE_SIDE_EFFECTS (prev_base))
-- 
1.8.3


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]