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]

Re: SRA bit-field optimization


On Oct  6, 2007, Richard Sandiford <rsandifo@nildram.co.uk> wrote:

> Ah, thanks.  I did have a quick look at it, and it seemed to be caused
> by a missing conversion at the tree level.  Expand was being given
> a BIT_AND_EXPR with a DImode-typed result and HImode-typed operand.
> I didn't try to track down where it was coming from.  So it does seem
> to be a tree-level bug after all.

Yep, fixed in the revised patch below.

It also fixes the endianness problem that was hitting machines that
had BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN, that caused the 20031211-1.c
and other regressions.  I remember having noticed at some point in the
development of the bit-field SRA patch that I was using the wrong
endianness macro and changing it, but BITS_BIG_ENDIAN wasn't what I
was looking for.  Doh.

I haven't given this patch much testing yet, but the two new changes
are obviously correct and do make progress.  I'm starting a test run
on a just-built mipsisa32-elf uberbaum tree, after having finally
figured out why dejagnu wasn't finding newlib (my uberbaum source tree
contained links to gcc and srcware sub-dirs, but site.exp set srcdir
with the pathname of the gcc source tree, rather than that of the
uberbaum tree, doesn't this bite anyone else?)

Ok to install if it passes bootstrap on x86_64-linux-gnu?

for  gcc/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* tree-sra.c (instantiate_element): Use BYTES_BIG_ENDIAN for
	bit-field layout.
	(sra_build_assignment): Likewise.  Set up mask depending on
	precision, not type.
	(sra_build_bf_assignment): Use BYTES_BIG_ENDIAN.  Don't overflow
	computing bit masks.  Fix type mismatch when applying negated
	mask.
	(sra_build_elt_assignment): Don't view-convert from signed to
	unsigned.
	(sra_explode_bitfield_assignment): Use bit-field type if
	possible.  Use BYTES_BIG_ENDIAN.

Index: gcc/tree-sra.c
===================================================================
--- gcc/tree-sra.c.orig	2007-10-06 08:46:59.000000000 -0300
+++ gcc/tree-sra.c	2007-10-07 20:20:11.000000000 -0300
@@ -1275,7 +1275,7 @@ instantiate_element (struct sra_elt *elt
       elt->in_bitfld_block = 1;
       elt->replacement = build3 (BIT_FIELD_REF, elt->type, var,
 				 DECL_SIZE (var),
-				 BITS_BIG_ENDIAN
+				 BYTES_BIG_ENDIAN
 				 ? size_binop (MINUS_EXPR,
 					       TYPE_SIZE (elt->type),
 					       DECL_SIZE (var))
@@ -2140,7 +2140,7 @@ sra_build_assignment (tree dst, tree src
       cst2 = size_binop (PLUS_EXPR, TREE_OPERAND (src, 1),
 			 TREE_OPERAND (src, 2));
 
-      if (BITS_BIG_ENDIAN)
+      if (BYTES_BIG_ENDIAN)
 	{
 	  maxshift = size_binop (MINUS_EXPR, TYPE_SIZE (TREE_TYPE (var)), cst);
 	  minshift = size_binop (MINUS_EXPR, TYPE_SIZE (TREE_TYPE (var)), cst2);
@@ -2168,7 +2168,7 @@ sra_build_assignment (tree dst, tree src
       list = NULL;
 
       cst2 = size_binop (MINUS_EXPR, maxshift, minshift);
-      if (tree_int_cst_equal (cst2, TYPE_SIZE (utype)))
+      if (TREE_INT_CST_LOW (cst2) == TYPE_PRECISION (utype))
 	{
 	  unsignedp = true;
 	  mask = NULL_TREE;
@@ -2322,7 +2322,7 @@ sra_build_bf_assignment (tree dst, tree 
 		     fold_convert (bitsizetype, TREE_OPERAND (dst, 1)),
 		     cst);
 
-  if (BITS_BIG_ENDIAN)
+  if (BYTES_BIG_ENDIAN)
     {
       maxshift = size_binop (MINUS_EXPR, TYPE_SIZE (TREE_TYPE (var)), cst);
       minshift = size_binop (MINUS_EXPR, TYPE_SIZE (TREE_TYPE (var)), cst2);
@@ -2343,8 +2343,14 @@ sra_build_bf_assignment (tree dst, tree 
     utype = unsigned_type_for (type);
 
   mask = build_int_cst_wide (utype, 1, 0);
-  cst = int_const_binop (LSHIFT_EXPR, mask, maxshift, true);
-  cst2 = int_const_binop (LSHIFT_EXPR, mask, minshift, true);
+  if (TREE_INT_CST_LOW (maxshift) == TYPE_PRECISION (utype))
+    cst = build_int_cst_wide (utype, 0, 0);
+  else
+    cst = int_const_binop (LSHIFT_EXPR, mask, maxshift, true);
+  if (integer_zerop (minshift))
+    cst2 = mask;
+  else
+    cst2 = int_const_binop (LSHIFT_EXPR, mask, minshift, true);
   mask = int_const_binop (MINUS_EXPR, cst, cst2, true);
   mask = fold_build1 (BIT_NOT_EXPR, utype, mask);
 
@@ -2508,13 +2514,13 @@ sra_build_elt_assignment (struct sra_elt
 	    {
 	      list = NULL;
 
-	      if (!INTEGRAL_TYPE_P (TREE_TYPE (src))
-		  || !TYPE_UNSIGNED (TREE_TYPE (src)))
+	      if (!INTEGRAL_TYPE_P (TREE_TYPE (src)))
 		src = fold_build1 (VIEW_CONVERT_EXPR,
 				   lang_hooks.types.type_for_size
 				   (TREE_INT_CST_LOW
 				    (TYPE_SIZE (TREE_TYPE (src))),
 				    1), src);
+	      gcc_assert (TYPE_UNSIGNED (TREE_TYPE (src)));
 
 	      tmp = make_rename_temp (TREE_TYPE (src), "SR");
 	      stmt = build_gimple_modify_stmt (tmp, src);
@@ -2976,16 +2982,20 @@ sra_explode_bitfield_assignment (tree va
 
       if (fld->replacement)
 	{
-	  tree infld, invar, st;
+	  tree infld, invar, st, type;
 
 	  infld = fld->replacement;
 
+	  type = TREE_TYPE (infld);
+	  if (TYPE_PRECISION (type) != TREE_INT_CST_LOW (flen))
+	    type = lang_hooks.types.type_for_size (TREE_INT_CST_LOW (flen), 1);
+
 	  if (TREE_CODE (infld) == BIT_FIELD_REF)
 	    {
 	      fpos = size_binop (PLUS_EXPR, fpos, TREE_OPERAND (infld, 2));
 	      infld = TREE_OPERAND (infld, 0);
 	    }
-	  else if (BITS_BIG_ENDIAN && DECL_P (fld->element)
+	  else if (BYTES_BIG_ENDIAN && DECL_P (fld->element)
 		   && !tree_int_cst_equal (TYPE_SIZE (TREE_TYPE (infld)),
 					   DECL_SIZE (fld->element)))
 	    {
@@ -2995,10 +3005,7 @@ sra_explode_bitfield_assignment (tree va
 				 DECL_SIZE (fld->element));
 	    }
 
-	  infld = fold_build3 (BIT_FIELD_REF,
-			       lang_hooks.types.type_for_size
-			       (TREE_INT_CST_LOW (flen), 1),
-			       infld, flen, fpos);
+	  infld = fold_build3 (BIT_FIELD_REF, type, infld, flen, fpos);
 	  BIT_FIELD_REF_UNSIGNED (infld) = 1;
 
 	  invar = size_binop (MINUS_EXPR, flp.field_pos, bpos);
@@ -3006,8 +3013,7 @@ sra_explode_bitfield_assignment (tree va
 	    invar = size_binop (PLUS_EXPR, invar, flp.overlap_pos);
 	  invar = size_binop (PLUS_EXPR, invar, vpos);
 
-	  invar = fold_build3 (BIT_FIELD_REF, TREE_TYPE (infld),
-			       var, flen, invar);
+	  invar = fold_build3 (BIT_FIELD_REF, type, var, flen, invar);
 	  BIT_FIELD_REF_UNSIGNED (invar) = 1;
 
 	  if (to_var)
-- 
Alexandre Oliva         http://www.lsd.ic.unicamp.br/~oliva/
FSF Latin America Board Member         http://www.fsfla.org/
Red Hat Compiler Engineer   aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist  oliva@{lsd.ic.unicamp.br, gnu.org}

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