Re: [000/nnn] poly_int: representation of runtime offsets and sizes

2017-11-08 Thread Richard Biener
On Wed, Nov 8, 2017 at 10:39 AM, Richard Sandiford
 wrote:
> Richard Biener  writes:
>> On Wed, Oct 25, 2017 at 1:26 PM, Richard Sandiford
>>  wrote:
>>> Richard Biener  writes:
 On Tue, Oct 24, 2017 at 3:24 PM, Richard Sandiford
  wrote:
> Richard Biener  writes:
>> On Tue, Oct 24, 2017 at 2:48 PM, Richard Sandiford
>>  wrote:
>>> Richard Biener  writes:
 On Tue, Oct 24, 2017 at 1:23 PM, Richard Sandiford
  wrote:
> Eric Botcazou  writes:
>>> Yeah.  E.g. for ==, the two options would be:
>>>
>>> a) must_eq (a, b)   -> a == b
>>>must_ne (a, b)   -> a != b
>>>
>>>which has the weird property that (a == b) != (!(a != b))
>>>
>>> b) must_eq (a, b)   -> a == b
>>>may_ne (a, b)-> a != b
>>>
>>>which has the weird property that a can be equal to b when a != b
>>
>> Yes, a) was the one I had in mind, i.e. the traditional operators are
>> the must
>> variants and you use an outer ! in order to express the may.  Of
>> course this
>> would require a bit of discipline but, on the other hand, if most of
>> the cases
>> fall in the must category, that could be less ugly.
>
> I just think that discipline is going to be hard to maintain in
> practice,
> since it's so natural to assume (a == b || a != b) == true.  With the
> may/must approach, static type checking forces the issue.
>
>>> Sorry about that.  It's the best I could come up with without losing
>>> the may/must distinction.
>>
>> Which variant is known_zero though?  Must or may?
>
> must.  maybe_nonzero is the may version.

 Can you rename known_zero to must_be_zero then?
>>>
>>> That'd be OK with me.
>>>
>>> Another alternative I wondered about was must_eq_0 / may_ne_0.
>>>
 What's wrong with must_eq (X, 0) / may_eq (X, 0) btw?
>>>
>>> must_eq (X, 0) generated a warning if X is unsigned, so sometimes you'd
>>> need must_eq (X, 0) and sometimes must_eq (X, 0U).
>>
>> Is that because they are templates?  Maybe providing a partial
>> specialization
>> would help?
>
> I don't think it's templates specifically.  We end up with something like:
>
>   int f (unsigned int x, const int y)
>   {
> return x != y;
>   }
>
>   int g (unsigned int x) { return f (x, 0); }
>
> which generates a warning too.
>
>> I'd be fine with must_eq_p and may_eq_0.
>
> OK, I'll switch to that if there are no objections.

 Hum.  But then we still warn for must_eq_p (x, 1), no?
>>>
>>> Yeah.  The patch also had a known_one and known_all_ones for
>>> those two (fairly) common cases.  For other values the patches
>>> just add "U" where necessary.
>>>
>>> If you think it would be better to use U consistently and not
>>> have the helpers, then I'm happy to do that instead.
>>>
 So why does

   int f (unsigned int x)
   {
  return x != 0;
   }

 not warn?  Probably because of promotion of the arg.
>>>
>>> [Jakub's already answered this part.]
>>>
 Shouldn't we then simply never have a may/must_*_p (T1, T2)
 with T1 and T2 being not compatible?  That is, force promotion
 rules on them with template magic?
>>>
>>> This was what I meant by:
>>>
>>>   Or we could suppress warnings by forcibly converting the input.
>>>   Sometimes the warnings are useful though.
>>>
>>> We already do this kind of conversion for arithmetic, to ensure
>>> that poly_uint16 + poly_uint16 -> poly_int64 promotes before the
>>> addition rather than after it.  But it defeats the point of the
>>> comparison warning, which is that you're potentially redefining
>>> the sign bit.
>>>
>>> I think the warning's just as valuable for may/must comparison of
>>> non-literals as it is for normal comparison operators.  It's just
>>> unfortunate that we no longer get the special handling of literals.
>>
>> Ok, I see.
>>
>> I think I have a slight preference for using 0U consistently but I haven't
>> looked at too many patches yet to see how common/ugly that would be.
>
> OK.  FWIW, that's also how we had it until very recently.  I added the
> known/maybe stuff in a late and probably misguided attempt to make
> things prettier.
>
> I've pulled that part out and switched back to using U.  I'll post the
> new 001 patch in a sec.  Should I repost all the other patches that
> changed as well, or isn't it worth it for a change like that?

Not worth re-posting IMHO.


Re: [000/nnn] poly_int: representation of runtime offsets and sizes

2017-11-08 Thread Richard Sandiford
Richard Biener  writes:
> On Wed, Oct 25, 2017 at 1:26 PM, Richard Sandiford
>  wrote:
>> Richard Biener  writes:
>>> On Tue, Oct 24, 2017 at 3:24 PM, Richard Sandiford
>>>  wrote:
 Richard Biener  writes:
> On Tue, Oct 24, 2017 at 2:48 PM, Richard Sandiford
>  wrote:
>> Richard Biener  writes:
>>> On Tue, Oct 24, 2017 at 1:23 PM, Richard Sandiford
>>>  wrote:
 Eric Botcazou  writes:
>> Yeah.  E.g. for ==, the two options would be:
>>
>> a) must_eq (a, b)   -> a == b
>>must_ne (a, b)   -> a != b
>>
>>which has the weird property that (a == b) != (!(a != b))
>>
>> b) must_eq (a, b)   -> a == b
>>may_ne (a, b)-> a != b
>>
>>which has the weird property that a can be equal to b when a != b
>
> Yes, a) was the one I had in mind, i.e. the traditional operators are
> the must
> variants and you use an outer ! in order to express the may.  Of
> course this
> would require a bit of discipline but, on the other hand, if most of
> the cases
> fall in the must category, that could be less ugly.

 I just think that discipline is going to be hard to maintain in
 practice,
 since it's so natural to assume (a == b || a != b) == true.  With the
 may/must approach, static type checking forces the issue.

>> Sorry about that.  It's the best I could come up with without losing
>> the may/must distinction.
>
> Which variant is known_zero though?  Must or may?

 must.  maybe_nonzero is the may version.
>>>
>>> Can you rename known_zero to must_be_zero then?
>>
>> That'd be OK with me.
>>
>> Another alternative I wondered about was must_eq_0 / may_ne_0.
>>
>>> What's wrong with must_eq (X, 0) / may_eq (X, 0) btw?
>>
>> must_eq (X, 0) generated a warning if X is unsigned, so sometimes you'd
>> need must_eq (X, 0) and sometimes must_eq (X, 0U).
>
> Is that because they are templates?  Maybe providing a partial
> specialization
> would help?

 I don't think it's templates specifically.  We end up with something like:

   int f (unsigned int x, const int y)
   {
 return x != y;
   }

   int g (unsigned int x) { return f (x, 0); }

 which generates a warning too.

> I'd be fine with must_eq_p and may_eq_0.

 OK, I'll switch to that if there are no objections.
>>>
>>> Hum.  But then we still warn for must_eq_p (x, 1), no?
>>
>> Yeah.  The patch also had a known_one and known_all_ones for
>> those two (fairly) common cases.  For other values the patches
>> just add "U" where necessary.
>>
>> If you think it would be better to use U consistently and not
>> have the helpers, then I'm happy to do that instead.
>>
>>> So why does
>>>
>>>   int f (unsigned int x)
>>>   {
>>>  return x != 0;
>>>   }
>>>
>>> not warn?  Probably because of promotion of the arg.
>>
>> [Jakub's already answered this part.]
>>
>>> Shouldn't we then simply never have a may/must_*_p (T1, T2)
>>> with T1 and T2 being not compatible?  That is, force promotion
>>> rules on them with template magic?
>>
>> This was what I meant by:
>>
>>   Or we could suppress warnings by forcibly converting the input.
>>   Sometimes the warnings are useful though.
>>
>> We already do this kind of conversion for arithmetic, to ensure
>> that poly_uint16 + poly_uint16 -> poly_int64 promotes before the
>> addition rather than after it.  But it defeats the point of the
>> comparison warning, which is that you're potentially redefining
>> the sign bit.
>>
>> I think the warning's just as valuable for may/must comparison of
>> non-literals as it is for normal comparison operators.  It's just
>> unfortunate that we no longer get the special handling of literals.
>
> Ok, I see.
>
> I think I have a slight preference for using 0U consistently but I haven't
> looked at too many patches yet to see how common/ugly that would be.

OK.  FWIW, that's also how we had it until very recently.  I added the
known/maybe stuff in a late and probably misguided attempt to make
things prettier.

I've pulled that part out and switched back to using U.  I'll post the
new 001 patch in a sec.  Should I repost all the other patches that
changed as well, or isn't it worth it for a change like that?

Thanks,
Richard


Re: [000/nnn] poly_int: representation of runtime offsets and sizes

2017-10-25 Thread Richard Biener
On Wed, Oct 25, 2017 at 1:26 PM, Richard Sandiford
 wrote:
> Richard Biener  writes:
>> On Tue, Oct 24, 2017 at 3:24 PM, Richard Sandiford
>>  wrote:
>>> Richard Biener  writes:
 On Tue, Oct 24, 2017 at 2:48 PM, Richard Sandiford
  wrote:
> Richard Biener  writes:
>> On Tue, Oct 24, 2017 at 1:23 PM, Richard Sandiford
>>  wrote:
>>> Eric Botcazou  writes:
> Yeah.  E.g. for ==, the two options would be:
>
> a) must_eq (a, b)   -> a == b
>must_ne (a, b)   -> a != b
>
>which has the weird property that (a == b) != (!(a != b))
>
> b) must_eq (a, b)   -> a == b
>may_ne (a, b)-> a != b
>
>which has the weird property that a can be equal to b when a != b

 Yes, a) was the one I had in mind, i.e. the traditional operators are
 the must
 variants and you use an outer ! in order to express the may.  Of
 course this
 would require a bit of discipline but, on the other hand, if most of
 the cases
 fall in the must category, that could be less ugly.
>>>
>>> I just think that discipline is going to be hard to maintain in 
>>> practice,
>>> since it's so natural to assume (a == b || a != b) == true.  With the
>>> may/must approach, static type checking forces the issue.
>>>
> Sorry about that.  It's the best I could come up with without losing
> the may/must distinction.

 Which variant is known_zero though?  Must or may?
>>>
>>> must.  maybe_nonzero is the may version.
>>
>> Can you rename known_zero to must_be_zero then?
>
> That'd be OK with me.
>
> Another alternative I wondered about was must_eq_0 / may_ne_0.
>
>> What's wrong with must_eq (X, 0) / may_eq (X, 0) btw?
>
> must_eq (X, 0) generated a warning if X is unsigned, so sometimes you'd
> need must_eq (X, 0) and sometimes must_eq (X, 0U).

 Is that because they are templates?  Maybe providing a partial 
 specialization
 would help?
>>>
>>> I don't think it's templates specifically.  We end up with something like:
>>>
>>>   int f (unsigned int x, const int y)
>>>   {
>>> return x != y;
>>>   }
>>>
>>>   int g (unsigned int x) { return f (x, 0); }
>>>
>>> which generates a warning too.
>>>
 I'd be fine with must_eq_p and may_eq_0.
>>>
>>> OK, I'll switch to that if there are no objections.
>>
>> Hum.  But then we still warn for must_eq_p (x, 1), no?
>
> Yeah.  The patch also had a known_one and known_all_ones for
> those two (fairly) common cases.  For other values the patches
> just add "U" where necessary.
>
> If you think it would be better to use U consistently and not
> have the helpers, then I'm happy to do that instead.
>
>> So why does
>>
>>   int f (unsigned int x)
>>   {
>>  return x != 0;
>>   }
>>
>> not warn?  Probably because of promotion of the arg.
>
> [Jakub's already answered this part.]
>
>> Shouldn't we then simply never have a may/must_*_p (T1, T2)
>> with T1 and T2 being not compatible?  That is, force promotion
>> rules on them with template magic?
>
> This was what I meant by:
>
>   Or we could suppress warnings by forcibly converting the input.
>   Sometimes the warnings are useful though.
>
> We already do this kind of conversion for arithmetic, to ensure
> that poly_uint16 + poly_uint16 -> poly_int64 promotes before the
> addition rather than after it.  But it defeats the point of the
> comparison warning, which is that you're potentially redefining
> the sign bit.
>
> I think the warning's just as valuable for may/must comparison of
> non-literals as it is for normal comparison operators.  It's just
> unfortunate that we no longer get the special handling of literals.

Ok, I see.

I think I have a slight preference for using 0U consistently but I haven't
looked at too many patches yet to see how common/ugly that would be.

Richard.

> Thanks,
> Richard


Re: [000/nnn] poly_int: representation of runtime offsets and sizes

2017-10-25 Thread Richard Sandiford
Richard Biener  writes:
> On Tue, Oct 24, 2017 at 3:24 PM, Richard Sandiford
>  wrote:
>> Richard Biener  writes:
>>> On Tue, Oct 24, 2017 at 2:48 PM, Richard Sandiford
>>>  wrote:
 Richard Biener  writes:
> On Tue, Oct 24, 2017 at 1:23 PM, Richard Sandiford
>  wrote:
>> Eric Botcazou  writes:
 Yeah.  E.g. for ==, the two options would be:

 a) must_eq (a, b)   -> a == b
must_ne (a, b)   -> a != b

which has the weird property that (a == b) != (!(a != b))

 b) must_eq (a, b)   -> a == b
may_ne (a, b)-> a != b

which has the weird property that a can be equal to b when a != b
>>>
>>> Yes, a) was the one I had in mind, i.e. the traditional operators are
>>> the must
>>> variants and you use an outer ! in order to express the may.  Of
>>> course this
>>> would require a bit of discipline but, on the other hand, if most of
>>> the cases
>>> fall in the must category, that could be less ugly.
>>
>> I just think that discipline is going to be hard to maintain in practice,
>> since it's so natural to assume (a == b || a != b) == true.  With the
>> may/must approach, static type checking forces the issue.
>>
 Sorry about that.  It's the best I could come up with without losing
 the may/must distinction.
>>>
>>> Which variant is known_zero though?  Must or may?
>>
>> must.  maybe_nonzero is the may version.
>
> Can you rename known_zero to must_be_zero then?

 That'd be OK with me.

 Another alternative I wondered about was must_eq_0 / may_ne_0.

> What's wrong with must_eq (X, 0) / may_eq (X, 0) btw?

 must_eq (X, 0) generated a warning if X is unsigned, so sometimes you'd
 need must_eq (X, 0) and sometimes must_eq (X, 0U).
>>>
>>> Is that because they are templates?  Maybe providing a partial 
>>> specialization
>>> would help?
>>
>> I don't think it's templates specifically.  We end up with something like:
>>
>>   int f (unsigned int x, const int y)
>>   {
>> return x != y;
>>   }
>>
>>   int g (unsigned int x) { return f (x, 0); }
>>
>> which generates a warning too.
>>
>>> I'd be fine with must_eq_p and may_eq_0.
>>
>> OK, I'll switch to that if there are no objections.
>
> Hum.  But then we still warn for must_eq_p (x, 1), no?

Yeah.  The patch also had a known_one and known_all_ones for
those two (fairly) common cases.  For other values the patches
just add "U" where necessary.

If you think it would be better to use U consistently and not
have the helpers, then I'm happy to do that instead.

> So why does
>
>   int f (unsigned int x)
>   {
>  return x != 0;
>   }
>
> not warn?  Probably because of promotion of the arg.

[Jakub's already answered this part.]

> Shouldn't we then simply never have a may/must_*_p (T1, T2)
> with T1 and T2 being not compatible?  That is, force promotion
> rules on them with template magic?

This was what I meant by:

  Or we could suppress warnings by forcibly converting the input.
  Sometimes the warnings are useful though.

We already do this kind of conversion for arithmetic, to ensure
that poly_uint16 + poly_uint16 -> poly_int64 promotes before the
addition rather than after it.  But it defeats the point of the
comparison warning, which is that you're potentially redefining
the sign bit.

I think the warning's just as valuable for may/must comparison of
non-literals as it is for normal comparison operators.  It's just
unfortunate that we no longer get the special handling of literals.

Thanks,
Richard


Re: [000/nnn] poly_int: representation of runtime offsets and sizes

2017-10-25 Thread Jakub Jelinek
On Wed, Oct 25, 2017 at 12:19:37PM +0200, Richard Biener wrote:
> Hum.  But then we still warn for must_eq_p (x, 1), no?
> 
> So why does
> 
>   int f (unsigned int x)
>   {
>  return x != 0;
>   }
> 
> not warn?  Probably because of promotion of the arg.

Because then one comparison operand is positive constant smaller
than the signed maximum.
We warn when both comparison operands are variable and one is signed and the
other is unsigned.

Jakub


Re: [000/nnn] poly_int: representation of runtime offsets and sizes

2017-10-25 Thread Richard Biener
On Tue, Oct 24, 2017 at 3:24 PM, Richard Sandiford
 wrote:
> Richard Biener  writes:
>> On Tue, Oct 24, 2017 at 2:48 PM, Richard Sandiford
>>  wrote:
>>> Richard Biener  writes:
 On Tue, Oct 24, 2017 at 1:23 PM, Richard Sandiford
  wrote:
> Eric Botcazou  writes:
>>> Yeah.  E.g. for ==, the two options would be:
>>>
>>> a) must_eq (a, b)   -> a == b
>>>must_ne (a, b)   -> a != b
>>>
>>>which has the weird property that (a == b) != (!(a != b))
>>>
>>> b) must_eq (a, b)   -> a == b
>>>may_ne (a, b)-> a != b
>>>
>>>which has the weird property that a can be equal to b when a != b
>>
>> Yes, a) was the one I had in mind, i.e. the traditional operators are
>> the must
>> variants and you use an outer ! in order to express the may.  Of
>> course this
>> would require a bit of discipline but, on the other hand, if most of
>> the cases
>> fall in the must category, that could be less ugly.
>
> I just think that discipline is going to be hard to maintain in practice,
> since it's so natural to assume (a == b || a != b) == true.  With the
> may/must approach, static type checking forces the issue.
>
>>> Sorry about that.  It's the best I could come up with without losing
>>> the may/must distinction.
>>
>> Which variant is known_zero though?  Must or may?
>
> must.  maybe_nonzero is the may version.

 Can you rename known_zero to must_be_zero then?
>>>
>>> That'd be OK with me.
>>>
>>> Another alternative I wondered about was must_eq_0 / may_ne_0.
>>>
 What's wrong with must_eq (X, 0) / may_eq (X, 0) btw?
>>>
>>> must_eq (X, 0) generated a warning if X is unsigned, so sometimes you'd
>>> need must_eq (X, 0) and sometimes must_eq (X, 0U).
>>
>> Is that because they are templates?  Maybe providing a partial specialization
>> would help?
>
> I don't think it's templates specifically.  We end up with something like:
>
>   int f (unsigned int x, const int y)
>   {
> return x != y;
>   }
>
>   int g (unsigned int x) { return f (x, 0); }
>
> which generates a warning too.
>
>> I'd be fine with must_eq_p and may_eq_0.
>
> OK, I'll switch to that if there are no objections.

Hum.  But then we still warn for must_eq_p (x, 1), no?

So why does

  int f (unsigned int x)
  {
 return x != 0;
  }

not warn?  Probably because of promotion of the arg.

Shouldn't we then simply never have a may/must_*_p (T1, T2)
with T1 and T2 being not compatible?  That is, force promotion
rules on them with template magic?

Richard.


> Thanks,
> Richard


Re: [000/nnn] poly_int: representation of runtime offsets and sizes

2017-10-24 Thread Richard Sandiford
Richard Biener  writes:
> On Tue, Oct 24, 2017 at 2:48 PM, Richard Sandiford
>  wrote:
>> Richard Biener  writes:
>>> On Tue, Oct 24, 2017 at 1:23 PM, Richard Sandiford
>>>  wrote:
 Eric Botcazou  writes:
>> Yeah.  E.g. for ==, the two options would be:
>>
>> a) must_eq (a, b)   -> a == b
>>must_ne (a, b)   -> a != b
>>
>>which has the weird property that (a == b) != (!(a != b))
>>
>> b) must_eq (a, b)   -> a == b
>>may_ne (a, b)-> a != b
>>
>>which has the weird property that a can be equal to b when a != b
>
> Yes, a) was the one I had in mind, i.e. the traditional operators are
> the must
> variants and you use an outer ! in order to express the may.  Of
> course this
> would require a bit of discipline but, on the other hand, if most of
> the cases
> fall in the must category, that could be less ugly.

 I just think that discipline is going to be hard to maintain in practice,
 since it's so natural to assume (a == b || a != b) == true.  With the
 may/must approach, static type checking forces the issue.

>> Sorry about that.  It's the best I could come up with without losing
>> the may/must distinction.
>
> Which variant is known_zero though?  Must or may?

 must.  maybe_nonzero is the may version.
>>>
>>> Can you rename known_zero to must_be_zero then?
>>
>> That'd be OK with me.
>>
>> Another alternative I wondered about was must_eq_0 / may_ne_0.
>>
>>> What's wrong with must_eq (X, 0) / may_eq (X, 0) btw?
>>
>> must_eq (X, 0) generated a warning if X is unsigned, so sometimes you'd
>> need must_eq (X, 0) and sometimes must_eq (X, 0U).
>
> Is that because they are templates?  Maybe providing a partial specialization
> would help?

I don't think it's templates specifically.  We end up with something like:

  int f (unsigned int x, const int y)
  {
return x != y;
  }

  int g (unsigned int x) { return f (x, 0); }

which generates a warning too.

> I'd be fine with must_eq_p and may_eq_0.

OK, I'll switch to that if there are no objections.

Thanks,
Richard


Re: [000/nnn] poly_int: representation of runtime offsets and sizes

2017-10-24 Thread Richard Biener
On Tue, Oct 24, 2017 at 2:48 PM, Richard Sandiford
 wrote:
> Richard Biener  writes:
>> On Tue, Oct 24, 2017 at 1:23 PM, Richard Sandiford
>>  wrote:
>>> Eric Botcazou  writes:
> Yeah.  E.g. for ==, the two options would be:
>
> a) must_eq (a, b)   -> a == b
>must_ne (a, b)   -> a != b
>
>which has the weird property that (a == b) != (!(a != b))
>
> b) must_eq (a, b)   -> a == b
>may_ne (a, b)-> a != b
>
>which has the weird property that a can be equal to b when a != b

 Yes, a) was the one I had in mind, i.e. the traditional operators are
 the must
 variants and you use an outer ! in order to express the may.  Of course 
 this
 would require a bit of discipline but, on the other hand, if most of
 the cases
 fall in the must category, that could be less ugly.
>>>
>>> I just think that discipline is going to be hard to maintain in practice,
>>> since it's so natural to assume (a == b || a != b) == true.  With the
>>> may/must approach, static type checking forces the issue.
>>>
> Sorry about that.  It's the best I could come up with without losing
> the may/must distinction.

 Which variant is known_zero though?  Must or may?
>>>
>>> must.  maybe_nonzero is the may version.
>>
>> Can you rename known_zero to must_be_zero then?
>
> That'd be OK with me.
>
> Another alternative I wondered about was must_eq_0 / may_ne_0.
>
>> What's wrong with must_eq (X, 0) / may_eq (X, 0) btw?
>
> must_eq (X, 0) generated a warning if X is unsigned, so sometimes you'd
> need must_eq (X, 0) and sometimes must_eq (X, 0U).

Is that because they are templates?  Maybe providing a partial specialization
would help?

I'd be fine with must_eq_p and may_eq_0.

Richard.

>  Having a specific
> function seemed cleaner, especially in routines that were polymorphic
> in X.
>
> Or we could suppress warnings by forcibly converting the input.
> Sometimes the warnings are useful though.
>
> Thanks,
> Richard


Re: [000/nnn] poly_int: representation of runtime offsets and sizes

2017-10-24 Thread Richard Sandiford
Richard Biener  writes:
> On Tue, Oct 24, 2017 at 1:23 PM, Richard Sandiford
>  wrote:
>> Eric Botcazou  writes:
 Yeah.  E.g. for ==, the two options would be:

 a) must_eq (a, b)   -> a == b
must_ne (a, b)   -> a != b

which has the weird property that (a == b) != (!(a != b))

 b) must_eq (a, b)   -> a == b
may_ne (a, b)-> a != b

which has the weird property that a can be equal to b when a != b
>>>
>>> Yes, a) was the one I had in mind, i.e. the traditional operators are
>>> the must
>>> variants and you use an outer ! in order to express the may.  Of course this
>>> would require a bit of discipline but, on the other hand, if most of
>>> the cases
>>> fall in the must category, that could be less ugly.
>>
>> I just think that discipline is going to be hard to maintain in practice,
>> since it's so natural to assume (a == b || a != b) == true.  With the
>> may/must approach, static type checking forces the issue.
>>
 Sorry about that.  It's the best I could come up with without losing
 the may/must distinction.
>>>
>>> Which variant is known_zero though?  Must or may?
>>
>> must.  maybe_nonzero is the may version.
>
> Can you rename known_zero to must_be_zero then?

That'd be OK with me.

Another alternative I wondered about was must_eq_0 / may_ne_0.

> What's wrong with must_eq (X, 0) / may_eq (X, 0) btw?

must_eq (X, 0) generated a warning if X is unsigned, so sometimes you'd
need must_eq (X, 0) and sometimes must_eq (X, 0U).  Having a specific
function seemed cleaner, especially in routines that were polymorphic
in X.

Or we could suppress warnings by forcibly converting the input.
Sometimes the warnings are useful though.

Thanks,
Richard


Re: [000/nnn] poly_int: representation of runtime offsets and sizes

2017-10-24 Thread Richard Biener
On Tue, Oct 24, 2017 at 1:23 PM, Richard Sandiford
 wrote:
> Eric Botcazou  writes:
>>> Yeah.  E.g. for ==, the two options would be:
>>>
>>> a) must_eq (a, b)   -> a == b
>>>must_ne (a, b)   -> a != b
>>>
>>>which has the weird property that (a == b) != (!(a != b))
>>>
>>> b) must_eq (a, b)   -> a == b
>>>may_ne (a, b)-> a != b
>>>
>>>which has the weird property that a can be equal to b when a != b
>>
>> Yes, a) was the one I had in mind, i.e. the traditional operators are the 
>> must
>> variants and you use an outer ! in order to express the may.  Of course this
>> would require a bit of discipline but, on the other hand, if most of the 
>> cases
>> fall in the must category, that could be less ugly.
>
> I just think that discipline is going to be hard to maintain in practice,
> since it's so natural to assume (a == b || a != b) == true.  With the
> may/must approach, static type checking forces the issue.
>
>>> Sorry about that.  It's the best I could come up with without losing
>>> the may/must distinction.
>>
>> Which variant is known_zero though?  Must or may?
>
> must.  maybe_nonzero is the may version.

Can you rename known_zero to must_be_zero then?  What's wrong with
must_eq (X, 0) / may_eq (X, 0) btw?

Richard.

> Thanks,
> Richard


Re: [000/nnn] poly_int: representation of runtime offsets and sizes

2017-10-24 Thread Richard Sandiford
Eric Botcazou  writes:
>> Yeah.  E.g. for ==, the two options would be:
>> 
>> a) must_eq (a, b)   -> a == b
>>must_ne (a, b)   -> a != b
>> 
>>which has the weird property that (a == b) != (!(a != b))
>> 
>> b) must_eq (a, b)   -> a == b
>>may_ne (a, b)-> a != b
>> 
>>which has the weird property that a can be equal to b when a != b
>
> Yes, a) was the one I had in mind, i.e. the traditional operators are the 
> must 
> variants and you use an outer ! in order to express the may.  Of course this 
> would require a bit of discipline but, on the other hand, if most of the 
> cases 
> fall in the must category, that could be less ugly.

I just think that discipline is going to be hard to maintain in practice,
since it's so natural to assume (a == b || a != b) == true.  With the
may/must approach, static type checking forces the issue.

>> Sorry about that.  It's the best I could come up with without losing
>> the may/must distinction.
>
> Which variant is known_zero though?  Must or may?

must.  maybe_nonzero is the may version.

Thanks,
Richard


Re: [000/nnn] poly_int: representation of runtime offsets and sizes

2017-10-24 Thread Eric Botcazou
> Yeah.  E.g. for ==, the two options would be:
> 
> a) must_eq (a, b)   -> a == b
>must_ne (a, b)   -> a != b
> 
>which has the weird property that (a == b) != (!(a != b))
> 
> b) must_eq (a, b)   -> a == b
>may_ne (a, b)-> a != b
> 
>which has the weird property that a can be equal to b when a != b

Yes, a) was the one I had in mind, i.e. the traditional operators are the must 
variants and you use an outer ! in order to express the may.  Of course this 
would require a bit of discipline but, on the other hand, if most of the cases 
fall in the must category, that could be less ugly.

> Sorry about that.  It's the best I could come up with without losing
> the may/must distinction.

Which variant is known_zero though?  Must or may?

-- 
Eric Botcazou


Re: [000/nnn] poly_int: representation of runtime offsets and sizes

2017-10-24 Thread Richard Sandiford
Eric Botcazou  writes:
>> The patch that adds poly_int has detailed documentation, but the main
>> points are:
>> 
>> * there's no total ordering between poly_ints, so the best we can do
>>   when comparing them is to ask whether two values *might* or *must*
>>   be related in a particular way.  E.g. if mode A has size 2 + 2X
>>   and mode B has size 4, the condition:
>> 
>> GET_MODE_SIZE (A) <= GET_MODE_SIZE (B)
>> 
>>   is true for X<=1 and false for X>=2.  This translates to:
>> 
>> may_le (GET_MODE_SIZE (A), GET_MODE_SIZE (B)) == true
>> must_le (GET_MODE_SIZE (A), GET_MODE_SIZE (B)) == false
>> 
>>   Of course, the may/must distinction already exists in things like
>>   alias analysis.
>
> I presume that you considered using traditional operators instead of awkward 
> names, despite the lack of total ordering, and rejected it?

Yeah.  E.g. for ==, the two options would be:

a) must_eq (a, b)   -> a == b
   must_ne (a, b)   -> a != b

   which has the weird property that (a == b) != (!(a != b))

b) must_eq (a, b)   -> a == b
   may_ne (a, b)-> a != b

   which has the weird property that a can be equal to b when a != b

may/must matters in a similar way as it does for alias analysis:
"may" usually selects conservatively-correct, just-in-case behaviour
while "must" selects something that would be wrong if the condition
didn't hold.

> Because:
>
> -  && (bitpos == 0 || MEM_P (target)))
> +  && (known_zero (bitpos) || MEM_P (target)))
>
> - && bitsize == TYPE_PRECISION (type))
> + && must_eq (bitsize, TYPE_PRECISION (type)))
>
> -   if (need_to_clear && size > 0)
> +   if (need_to_clear && may_gt (size, 0))
>
> is really ugly...

Sorry about that.  It's the best I could come up with without losing
the may/must distinction.

Thanks,
Richard


Re: [000/nnn] poly_int: representation of runtime offsets and sizes

2017-10-24 Thread Eric Botcazou
> The patch that adds poly_int has detailed documentation, but the main
> points are:
> 
> * there's no total ordering between poly_ints, so the best we can do
>   when comparing them is to ask whether two values *might* or *must*
>   be related in a particular way.  E.g. if mode A has size 2 + 2X
>   and mode B has size 4, the condition:
> 
> GET_MODE_SIZE (A) <= GET_MODE_SIZE (B)
> 
>   is true for X<=1 and false for X>=2.  This translates to:
> 
> may_le (GET_MODE_SIZE (A), GET_MODE_SIZE (B)) == true
> must_le (GET_MODE_SIZE (A), GET_MODE_SIZE (B)) == false
> 
>   Of course, the may/must distinction already exists in things like
>   alias analysis.

I presume that you considered using traditional operators instead of awkward 
names, despite the lack of total ordering, and rejected it?  Because:

-  && (bitpos == 0 || MEM_P (target)))
+  && (known_zero (bitpos) || MEM_P (target)))

- && bitsize == TYPE_PRECISION (type))
+ && must_eq (bitsize, TYPE_PRECISION (type)))

-   if (need_to_clear && size > 0)
+   if (need_to_clear && may_gt (size, 0))

is really ugly...

-- 
Eric Botcazou