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: patch to canonize small wide-ints.


On 10/03/2013 10:29 AM, Richard Sandiford wrote:
Kenneth Zadeck <zadeck@naturalbridge.com> writes:
+  /* Got to be careful of precision 0 values.  */
+  if (precision)
+    len = MIN (len, max_len);
+  if (TYPE_SIGN (TREE_TYPE (x)) == UNSIGNED)
      {
-      if (precision < HOST_BITS_PER_WIDE_INT
-	  && TYPE_SIGN (TREE_TYPE (x)) == UNSIGNED)
+      unsigned int small_prec = precision & (HOST_BITS_PER_WIDE_INT - 1);
+      if (small_prec)
  	{
-	  /* The rep of wide-int is signed, so if the value comes from
-	     an unsigned int_cst, we have to sign extend it to make it
-	     correct.  */
-	  scratch[0] = sext_hwi (val[0], precision);
-	  return wi::storage_ref (scratch, 1, precision);
+	  /* We have to futz with this because the canonization for
+	     short unsigned numbers in wide-int is different from the
+	     canonized short unsigned numbers in the tree-cst.  */
+	  if (len == max_len)
+	    {
+	      for (unsigned int i = 0; i < len - 1; i++)
+		scratch[i] = val[i];
+	      scratch[len - 1] = sext_hwi (val[len - 1], precision);
+	      return wi::storage_ref (scratch, len, precision);
+	    }
  	}
-      /* Otherwise we can use the constant as-is when not extending.  */
-      return wi::storage_ref (val, len, precision);
+
+      unsigned int xprecision = get_precision (x);
+      len = wi::force_to_size (scratch, val, len, xprecision, precision, UNSIGNED);
+      return wi::storage_ref (scratch, len, precision);
      }
- /* Widen the constant according to its sign. */
-  len = wi::force_to_size (scratch, val, len, xprecision, precision,
-			   TYPE_SIGN (TREE_TYPE (x)));
-  return wi::storage_ref (scratch, len, precision);
+  /* Signed and the rest of the unsigned cases are easy.  */
+  return wi::storage_ref (val, len, precision);
AFAICT, no unsigned cases fall through to the "rest of the unsigned cases"
statement.
You are seeing the result of me being corner cased to death.


Changing the representation of unsigned constants is only worthwhile
if we can avoid the force_to_size for some unsigned cases.  I think we can
avoid it for precision >= xprecision && !small_prec.  Either we should take
the hit of doing that comparison (but see below) or the change isn't
worthwhile.
i think that it is something closer to precision >= xprecision + HOST_BITS_PER_WIDE_INT && ... The problem is that the tree cst may have one extra block beyond the precision.

for my example say HBPWI is 8, not 64. The uint16 constant 0xffff must be represented by 3 hwi's in the tree-cst as 00 ff ff. This is why the patch came out today rather than yesterday.
I can fire up a run with this, if you want.

I was thinking that we should always be able to use the constant as-is
for max_wide_int-based and addr_wide_int-based operations.  The small_prec
again, you can get edge cased to death here. i think it would work for max because that really is bigger than anything else, but it is possible (though unlikely) to have something big converted to an address by truncation.

case will get optimised away (because precision is a compile-time constant)
and the force_to_size shouldn't be necessary (because "max" and "addr"
should always be wide enough).  Could we assert for precision >= xprecision
instead of the force_to_size?  Or are there cases in which we implicitly
truncate tree constants for (variable-precision) wide_int-based operations?
again the max is safe by definition. The addr is inherently unsafe because i believe that some of the places where the values are converted to addr-wide-int come from tree-csts where the type comes from the source program.

Thanks,
Richard


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