value range propagation for _bitwise_ OR

Fawzi Mohamed fawzi at gmx.ch
Tue Apr 13 03:29:39 PDT 2010


On 13-apr-10, at 12:02, Don wrote:

> Fawzi Mohamed wrote:
>> On 12-apr-10, at 21:40, Steven Schveighoffer wrote:
>>> On Mon, 12 Apr 2010 13:45:14 -0400, Jérôme M. Berger <jeberger at free. 
>>> fr> wrote:
>>>
>>>> Steven Schveighoffer wrote:
>>>>> J�r�me M. Berger Wrote:
>>>>>
>>>>>> J�r�me M. Berger wrote:
>>>>>>>    OK, I found a solution that is optimal in over 99% of the  
>>>>>>> cases
>>>>>>> (99.195% to be precise), while still being fast (because it  
>>>>>>> avoids
>>>>>>> looping over the bits):
>>>>>>>
>>>>>>    I've run my function and Andrei's on all possible min, max  
>>>>>> pairs in
>>>>>> 0..299 without checking, just for the timing. On my computer  
>>>>>> (Athlon
>>>>>> X2 64 @2GHz), my function took 50s and Andrei's took 266s. The
>>>>>> difference should be even bigger for larger numbers.
>>>>>
>>>>> Can I ask, what is the point of having a non-exact solution  
>>>>> (unless you are just doing this for fun)?
>>>>>
>>>>> We are talking about range propagation, a function of the  
>>>>> compiler, not a function of the compiled program.  Therefore,  
>>>>> slower but more exact functions should be preferred, since they  
>>>>> only affect the compile time.  Note that you will only need to  
>>>>> do this range propagation on lines that "or" two values  
>>>>> together, and something that reduces the runtime of the compiler  
>>>>> by 216 seconds, but only when compiling enough code to have over  
>>>>> 8 billion 'or' operations in it (300^4), I don't think is really  
>>>>> that important.  Give me the exact solution that prevents me  
>>>>> from having to cast when the compiler can prove it, even if the  
>>>>> runtime of the compiler is slightly slower.
>>>>>
>>>>    Funny you should say that given the current thread comparing the
>>>> speed of the D compiler to that of the Go compiler...
>>>
>>> My point was simply that the amount of time saved is relative to  
>>> the size of the program being compiled.  If we assume  
>>> conservatively that every other line in a program has bitwise or  
>>> in it, then you are talking about a 16 billion line program,  
>>> meaning the 216 seconds you save is insignificant compared to the  
>>> total compile time.  My point was that your fast solution that is  
>>> inaccurate is not preferable because nobody notices the speed,  
>>> they just notice the inaccuracy.
>>>
>>>>    We are talking about range propagation, a function of the  
>>>> compiler,
>>>> not a function of the compiled program. Since we can't get a 100%
>>>> accurate representation of the possible values anyway (even yours
>>>> might leave holes in the middle after all), then it might be better
>>>> to choose a faster, slightly less precise algorithm if the
>>>> difference is not too great. That's the difference between a
>>>> compiler and a full-fledged static code analysis an program prover.
>>>
>>> When we're talking about the difference between O(1) and O(lgn),  
>>> I'll take accuracy over speed in my compiler any day.  The  
>>> solution should be 100% accurate for the problem statement.  If  
>>> the problem statement is not what we need, then we need a new  
>>> problem statement :)  Solving the problem statement for 99% of  
>>> values is not good enough.
>>>
>>>>
>>>>    Anyway, the point is moot, I have a new version of my algorithm
>>>> with 100% precision and high speed.
>>>
>>> Yes, I'm still trying to understand how it works :)
>> Sorry for the probably stupid question, but I don't understand much  
>> the need of all this range propagation, in the compiler either you  
>> have a a constant (and then you have the value at compile time, and  
>> you don't need any range propagation, you can compare with the  
>> value), or you have a runtime value.
>
>
> It's been part of DMD2 for a while now. It allows you to do things  
> like:
>
> ubyte lowbits(int x)
> {
>    return x & 7;
> }
>
> without an explicit cast. The compiler knows that x&7 can safely fit  
> inside a single byte.  Whereas   ((x&7) << 12) | (x&3);
> does not fit, and requires an explicit cast.

ah ok I understand, I thought that was treated like x & cast(ubyte)7 ,  
and so as comparison of the compile time value with the ranges of  
ubyte (no range propagation needed).
But I can understand why it is treated as cast(ubyte)((cast(int)x) &  
7), as it is probably easier for the compiler, as it upcasts by default.

Thanks for the explanation.




More information about the Digitalmars-d mailing list