Re: [patch] Fix PR middle-end/56474

2013-04-22 Thread Richard Biener
On Fri, Apr 19, 2013 at 11:01 PM, Eric Botcazou ebotca...@adacore.com wrote:
 Maybe we should detect overflow as if the input and output were signed
 while computing an unsigned result.  As far as I can see int_const_binop_1
 does detect overflow as if operations were signed (it passes 'false' as
 uns to all double-int operations rather than TYPE_UNSIGNED).
 For example sub_with_overflow simply does

   neg_double (b.low, b.high, ret.low, ret.high);
   add_double (low, high, ret.low, ret.high, ret.low, ret.high);
   *overflow = OVERFLOW_SUM_SIGN (ret.high, b.high, high);

 which I believe is wrong.  Shouldn't it be

   neg_double (b.low, b.high, ret.low, ret.high);
   HOST_WIDE_INT tem = ret.high;
   add_double (low, high, ret.low, ret.high, ret.low, ret.high);
   *overflow = OVERFLOW_SUM_SIGN (ret.high, tem, high);

 ?  Because we are computing a + (-b) and thus OVERFLOW_SUM_SIGN
 expects the sign of a and -b, not a and b to verify against the
 sign of ret.

 But int_const_binop_1 is called from int_const_binop, so why would we want to
 introduce any overflow for unsigned types other than sizetypes?

 I'm sceptical.  Where do you compute the size expression for variable-sized
 arrays?  I suppose with the testcase in the initial patch I can then inspect
 myself what actually happens?

 Sure, but we already went through this in the PR.  It's because of the formula
 used for the length of variable-sized arrays, which needs to handle the case
 of superflat arrays.

Ah, indeed.  I added a comment there.

Richard.

 --
 Eric Botcazou


Re: [patch] Fix PR middle-end/56474

2013-04-19 Thread Eric Botcazou
 Maybe we should detect overflow as if the input and output were signed
 while computing an unsigned result.  As far as I can see int_const_binop_1
 does detect overflow as if operations were signed (it passes 'false' as
 uns to all double-int operations rather than TYPE_UNSIGNED).
 For example sub_with_overflow simply does
 
   neg_double (b.low, b.high, ret.low, ret.high);
   add_double (low, high, ret.low, ret.high, ret.low, ret.high);
   *overflow = OVERFLOW_SUM_SIGN (ret.high, b.high, high);
 
 which I believe is wrong.  Shouldn't it be
 
   neg_double (b.low, b.high, ret.low, ret.high);
   HOST_WIDE_INT tem = ret.high;
   add_double (low, high, ret.low, ret.high, ret.low, ret.high);
   *overflow = OVERFLOW_SUM_SIGN (ret.high, tem, high);
 
 ?  Because we are computing a + (-b) and thus OVERFLOW_SUM_SIGN
 expects the sign of a and -b, not a and b to verify against the
 sign of ret.

But int_const_binop_1 is called from int_const_binop, so why would we want to 
introduce any overflow for unsigned types other than sizetypes?

 I'm sceptical.  Where do you compute the size expression for variable-sized
 arrays?  I suppose with the testcase in the initial patch I can then inspect
 myself what actually happens?

Sure, but we already went through this in the PR.  It's because of the formula 
used for the length of variable-sized arrays, which needs to handle the case 
of superflat arrays.

-- 
Eric Botcazou


Re: [patch] Fix PR middle-end/56474

2013-04-17 Thread Richard Biener
On Wed, Apr 17, 2013 at 1:12 AM, Eric Botcazou ebotca...@adacore.com wrote:
 For the C family I found exactly one - the layout_type case, and fixed
 it in the FEs by making empty arrays use [1, 0] domains or signed domains
 (I don't remember exactly).  I believe the layout_type change was to make
 Ada happy.

 I'm skeptical, I had to narrow down the initial kludge because it hurted Ada.

 It may be that enabling overflow detection for even unsigned sizetype was
 because of Ada as well.  After all only Ada changed its sizetype sign
 recently.

 Not true, overflow detection has _always_ been enabled for sizetypes.
 But sizetypes, including unsigned ones, were sign-extended so 0 -1 didn't
 overflow and we need that behavior back for Ada to work properly,

Yeah, well - they were effectively signed.

 I don't like special casing 0 - 1 in a general compute function.  Maybe
 you want to use size_diffop for the computation?  That would result in
 a signed result and thus no overflow for 0 - 1.

 But it's not a general compute function, it's size_binop which is meant to be
 used for sizetypes only and which forces overflow on unsigned types.  We need
 overflow detection for sizetypes but we can also tailor it to fit our needs.

I'm not against tailoring it to fit our needs - I'm just against special casing
behavior for specific values.  That just sounds wrong.

Maybe we should detect overflow as if the input and output were signed
while computing an unsigned result.  As far as I can see int_const_binop_1
does detect overflow as if operations were signed (it passes 'false' as
uns to all double-int operations rather than TYPE_UNSIGNED).
For example sub_with_overflow simply does

  neg_double (b.low, b.high, ret.low, ret.high);
  add_double (low, high, ret.low, ret.high, ret.low, ret.high);
  *overflow = OVERFLOW_SUM_SIGN (ret.high, b.high, high);

which I believe is wrong.  Shouldn't it be

  neg_double (b.low, b.high, ret.low, ret.high);
  HOST_WIDE_INT tem = ret.high;
  add_double (low, high, ret.low, ret.high, ret.low, ret.high);
  *overflow = OVERFLOW_SUM_SIGN (ret.high, tem, high);

?  Because we are computing a + (-b) and thus OVERFLOW_SUM_SIGN
expects the sign of a and -b, not a and b to verify against the
sign of ret.

 The other option is to for example disable overflow handling for _all_
 constants and MINUS_EXPR (and then please PLUS_EXPR as well)
 in size_binop.  Maybe it's only the MULT_EXPR overflow we want to
 know (byte-to-bit conversion / element size scaling IIRC).

 Well, we just need 0 - 1 because of the way we compute size expressions for
 variable-sized arrays.

I'm sceptical.  Where do you compute the size expression for variable-sized
arrays?  I suppose with the testcase in the initial patch I can then inspect
myself what actually happens?

Thanks,
Richard.

 --
 Eric Botcazou


Re: [patch] Fix PR middle-end/56474

2013-04-16 Thread Eric Botcazou
 For the C family I found exactly one - the layout_type case, and fixed
 it in the FEs by making empty arrays use [1, 0] domains or signed domains
 (I don't remember exactly).  I believe the layout_type change was to make
 Ada happy.

I'm skeptical, I had to narrow down the initial kludge because it hurted Ada.

 It may be that enabling overflow detection for even unsigned sizetype was
 because of Ada as well.  After all only Ada changed its sizetype sign
 recently.

Not true, overflow detection has _always_ been enabled for sizetypes.
But sizetypes, including unsigned ones, were sign-extended so 0 -1 didn't 
overflow and we need that behavior back for Ada to work properly, 

 I don't like special casing 0 - 1 in a general compute function.  Maybe
 you want to use size_diffop for the computation?  That would result in
 a signed result and thus no overflow for 0 - 1.

But it's not a general compute function, it's size_binop which is meant to be 
used for sizetypes only and which forces overflow on unsigned types.  We need 
overflow detection for sizetypes but we can also tailor it to fit our needs.

 The other option is to for example disable overflow handling for _all_
 constants and MINUS_EXPR (and then please PLUS_EXPR as well)
 in size_binop.  Maybe it's only the MULT_EXPR overflow we want to
 know (byte-to-bit conversion / element size scaling IIRC).

Well, we just need 0 - 1 because of the way we compute size expressions for 
variable-sized arrays.

-- 
Eric Botcazou


Re: [patch] Fix PR middle-end/56474

2013-04-15 Thread Richard Biener
On Sun, Apr 14, 2013 at 10:05 AM, Eric Botcazou ebotca...@adacore.com wrote:
 Hi,

 this is a regression present on the mainline and 4.8 branch and introduced by
 the latest series of sizetype changes.  Associated adjustments were made in
 the various front-ends for it, most notably Ada which was the most affected,
 but this issue slipped through the cracks in the form of a bogus overflow
 detection for 0-based arrays with variable upper bound included in a record
 with discriminant.

 The proposed fix is to disable overflow detection in sizetype for one special
 case (0 - 1) in size_binop_loc.  An equivalent kludge was added to layout_type
 to disable overflow detection for the size expression of [0, -1] arrays.

 Tested on x86_64-suse-linux, OK for the mainline and 4.8 branch?

I think I already rejected this and asked you to fix the users (like
layout_type is a user).  Clearly 0 - 1 in unsigned arithmetic overflows.
Not indicating this may cause bugs elsewhere as easily as it fixes
code not dealing with this fact.

Richard.


 2013-04-14  Eric Botcazou  ebotca...@adacore.com

 PR middle-end/56474
 * fold-const.c (size_binop_loc): Disable overflow detection for 0 - 1.


 2013-04-14  Eric Botcazou  ebotca...@adacore.com

 * gnat.dg/specs/array3.ads: New test.


 --
 Eric Botcazou


Re: [patch] Fix PR middle-end/56474

2013-04-15 Thread Eric Botcazou
 I think I already rejected this and asked you to fix the users (like
 layout_type is a user).

Yes, but that would be a pain, there are too many users in the Ada front-end.

 Clearly 0 - 1 in unsigned arithmetic overflows.  Not indicating this may
 cause bugs elsewhere as easily as it fixes code not dealing with this fact.

!?? There is no overflow in unsigned arithmetics.  Instead size_binop forces 
overflows artificially and I don't see the problem in deciding that 0 - 1 is a 
special case, like [0, -1] is a special case for layout_type.  And note that 
this was the historical behavior, before the latest sizetype changes.

-- 
Eric Botcazou


Re: [patch] Fix PR middle-end/56474

2013-04-15 Thread Richard Biener
On Mon, Apr 15, 2013 at 12:04 PM, Eric Botcazou ebotca...@adacore.com wrote:
 I think I already rejected this and asked you to fix the users (like
 layout_type is a user).

 Yes, but that would be a pain, there are too many users in the Ada front-end.

Users that care about the special casing of  0 - 1 and overflow detection?
For the C family I found exactly one - the layout_type case, and fixed
it in the FEs by making empty arrays use [1, 0] domains or signed domains
(I don't remember exactly).  I believe the layout_type change was to make
Ada happy.

 Clearly 0 - 1 in unsigned arithmetic overflows.  Not indicating this may
 cause bugs elsewhere as easily as it fixes code not dealing with this fact.

 !?? There is no overflow in unsigned arithmetics.  Instead size_binop forces
 overflows artificially and I don't see the problem in deciding that 0 - 1 is a
 special case, like [0, -1] is a special case for layout_type.  And note that
 this was the historical behavior, before the latest sizetype changes.

Historically sizetype didn't overflow because it was supposed to never overflow.
Well, unless we check for overflow.

It may be that enabling overflow detection for even unsigned sizetype was
because of Ada as well.  After all only Ada changed its sizetype sign recently.

I don't like special casing 0 - 1 in a general compute function.  Maybe
you want to use size_diffop for the computation?  That would result in
a signed result and thus no overflow for 0 - 1.

The other option is to for example disable overflow handling for _all_
constants and MINUS_EXPR (and then please PLUS_EXPR as well)
in size_binop.  Maybe it's only the MULT_EXPR overflow we want to
know (byte-to-bit conversion / element size scaling IIRC).

Richard.

 --
 Eric Botcazou


[patch] Fix PR middle-end/56474

2013-04-14 Thread Eric Botcazou
Hi,

this is a regression present on the mainline and 4.8 branch and introduced by 
the latest series of sizetype changes.  Associated adjustments were made in 
the various front-ends for it, most notably Ada which was the most affected, 
but this issue slipped through the cracks in the form of a bogus overflow 
detection for 0-based arrays with variable upper bound included in a record 
with discriminant.

The proposed fix is to disable overflow detection in sizetype for one special 
case (0 - 1) in size_binop_loc.  An equivalent kludge was added to layout_type 
to disable overflow detection for the size expression of [0, -1] arrays.

Tested on x86_64-suse-linux, OK for the mainline and 4.8 branch?


2013-04-14  Eric Botcazou  ebotca...@adacore.com

PR middle-end/56474
* fold-const.c (size_binop_loc): Disable overflow detection for 0 - 1.


2013-04-14  Eric Botcazou  ebotca...@adacore.com

* gnat.dg/specs/array3.ads: New test.


-- 
Eric BotcazouIndex: fold-const.c
===
--- fold-const.c	(revision 197926)
+++ fold-const.c	(working copy)
@@ -1422,9 +1422,13 @@ size_binop_loc (location_t loc, enum tre
   gcc_assert (int_binop_types_match_p (code, TREE_TYPE (arg0),
TREE_TYPE (arg1)));
 
-  /* Handle the special case of two integer constants faster.  */
+  /* Handle general case of two integer constants.  For sizetype constant
+ calculations, we always want to know about overflow, even in the
+ unsigned case.  */
   if (TREE_CODE (arg0) == INTEGER_CST  TREE_CODE (arg1) == INTEGER_CST)
 {
+  int overflowable = -1;
+
   /* And some specific cases even faster than that.  */
   if (code == PLUS_EXPR)
 	{
@@ -1437,6 +1441,11 @@ size_binop_loc (location_t loc, enum tre
 	{
 	  if (integer_zerop (arg1)  !TREE_OVERFLOW (arg1))
 	return arg0;
+
+	  /* ??? We make an exception for 0 - 1 because it's an idiom
+	 used in length calculations for zero-based arrays.  */
+	  if (integer_zerop (arg0)  integer_onep (arg1))
+	overflowable = 1;
 	}
   else if (code == MULT_EXPR)
 	{
@@ -1444,10 +1453,7 @@ size_binop_loc (location_t loc, enum tre
 	return arg1;
 	}
 
-  /* Handle general case of two integer constants.  For sizetype
- constant calculations we always want to know about overflow,
-	 even in the unsigned case.  */
-  return int_const_binop_1 (code, arg0, arg1, -1);
+  return int_const_binop_1 (code, arg0, arg1, overflowable);
 }
 
   return fold_build2_loc (loc, code, type, arg0, arg1);-- PR middle-end/56474
-- Reported by Pavel Zhukov pa...@zhukoff.net

-- { dg-do compile }

with Ada.Streams;

package Array3 is

   use type Ada.Streams.Stream_Element_Offset;

   type Vector (Size : Ada.Streams.Stream_Element_Offset) is record
  Value : Ada.Streams.Stream_Element_Array (0 .. Size);
   end record;

   Empty_Vector : Vector (-1);

end Array3;