digitalmars.D - Value Range Propigation Spec
- Shammah Chancellor (9/9) Oct 22 2014 A couple of us working on SDC are trying to get ValueRange propigation
- "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= (9/11) Oct 22 2014 Nice! Maybe you should also consider establishing error in
- Walter Bright (6/14) Oct 22 2014 VRP is definitely a language feature, not a compiler feature. The specif...
- Shammah Chancellor (18/37) Oct 23 2014 Walter,
- bearophile (33/40) Oct 23 2014 Currently this doesn't compile, and it's expected to not compile.
- deadalnix (7/9) Oct 23 2014 The problem is not really what enhancement to do. But what limit
- bearophile (14/18) Oct 23 2014 No, it's not right. VRP was recently improved to keep the value
- Stefan Koch (23/30) Oct 24 2014 Hi, I am the guy who implemented the (currently incomplete) vrp
- bearophile (11/23) Oct 24 2014 It's much better to remove bugs from the compiler than from an
- Stefan Koch (2/2) Oct 24 2014 you are right. I misread the code-snippt above. Of course this is
- Walter Bright (8/22) Oct 23 2014 No. As bearophile mentioned, VRP only applies to an expression. The comp...
- bearophile (6/7) Oct 23 2014 There are still several useful cases where dataflow analysis is
- John Colvin (5/29) Oct 23 2014 Seeing as it affects semantics, should there not be a minimum
- Timon Gehr (4/7) Oct 24 2014 This is only straightforward to state because it is so ill-defined.
- Andrei Alexandrescu (3/25) Oct 27 2014 I think specification is equally tricky because it needs to specify the
- Timon Gehr (13/22) Oct 24 2014 AFAIK:
A couple of us working on SDC are trying to get ValueRange propigation implemented. I was wonder if someone could offer some insight as to how VRP works in DMD. If for example, trying to get the value range of a global, what is the expected behavior? It seems as though VRP is a language feature, and not a compiler feature -- since this allows some code to compile and not others. Is there a specification for how it should work somewhere? If not, it's hard to implement other compilers that will not generate errors in the same circumstances as DMD.
Oct 22 2014
On Wednesday, 22 October 2014 at 09:27:09 UTC, Shammah Chancellor wrote:A couple of us working on SDC are trying to get ValueRange propigation implemented.Nice! Maybe you should also consider establishing error in floating point calculations by extending to interval arithmetic? http://en.wikipedia.org/wiki/Interval_arithmetic Then D would have to add some way to express acceptable tolerance. The advantage is that the compiler could then do heavy duty optimization on floating point. Like using single precision, a more SIMD friendly evaluation order, a look up table etc…
Oct 22 2014
On 10/22/2014 2:31 AM, Shammah Chancellor wrote:A couple of us working on SDC are trying to get ValueRange propigation implemented. I was wonder if someone could offer some insight as to how VRP works in DMD. If for example, trying to get the value range of a global, what is the expected behavior? It seems as though VRP is a language feature, and not a compiler feature -- since this allows some code to compile and not others. Is there a specification for how it should work somewhere? If not, it's hard to implement other compilers that will not generate errors in the same circumstances as DMD.VRP is definitely a language feature, not a compiler feature. The specification is straightforward - a narrowing conversion can be implicitly performed if it can be proved that it would not lose information. How it works, though, is kinda tricky, and the only guide to it is the compiler source code.
Oct 22 2014
On 2014-10-22 20:32:35 +0000, Walter Bright said:On 10/22/2014 2:31 AM, Shammah Chancellor wrote:Walter, Several of us working on it were a little surprised that DMD does not compile this: void main() { long l = 42; int i = l; } Is this expected to compile? Planned? My post was based on my thought that this *did* compile and we were wondering rules for when the range would be reset. If `l` were __gshared for example, the range wouldn't be deterministic. Surely there should be some rules document? What we've implemented, is that the value range is calculated at float80 precision, and it's min and max can fit in the ultimate type for a cast, then it's good to go. We only look at the actual expression being implicitly cast. Thanks, -ShammahA couple of us working on SDC are trying to get ValueRange propigation implemented. I was wonder if someone could offer some insight as to how VRP works in DMD. If for example, trying to get the value range of a global, what is the expected behavior? It seems as though VRP is a language feature, and not a compiler feature -- since this allows some code to compile and not others. Is there a specification for how it should work somewhere? If not, it's hard to implement other compilers that will not generate errors in the same circumstances as DMD.VRP is definitely a language feature, not a compiler feature. The specification is straightforward - a narrowing conversion can be implicitly performed if it can be proved that it would not lose information. How it works, though, is kinda tricky, and the only guide to it is the compiler source code.
Oct 23 2014
Shammah Chancellor:Several of us working on it were a little surprised that DMD does not compile this: void main() { long l = 42; int i = l; } Is this expected to compile? Planned?Currently this doesn't compile, and it's expected to not compile. Currently VRP works only inside one expression (I guess to keep low the compiler complexity). So the value range of l is lost when it's assigned to i. Very recently VRP was improved and now the value range of immutable values is kept. I don't know if there are plans to improve the VRP. I hope to see some improvements, like: void foo(in uint x) in { assert(x < 10_000); } body { ushort y = x; if (x < 100) { ubyte z = x; } } Another example: uint bar() out(result) { assert(result < 100); } body { return 99; } void spam(in ubyte x) {} void main() { spam(bar()); } Other improvements are possible, and very useful. I have some more enhancement requests in Bugzilla. Bye, bearophile
Oct 23 2014
On Thursday, 23 October 2014 at 15:39:55 UTC, bearophile wrote:Other improvements are possible, and very useful. I have some more enhancement requests in Bugzilla.The problem is not really what enhancement to do. But what limit do we fix to ourselves (ie, what is a bug and what is not). There are possibilities to do more, but compatibility require that we put the line somewhere. The current line seems to be to do VRP on expression and compile time know values. Is that right ?
Oct 23 2014
deadalnix:There are possibilities to do more, but compatibility require that we put the line somewhere.The line is still moving forward.The current line seems to be to do VRP on expression and compile time know values. Is that right ?No, it's not right. VRP was recently improved to keep the value range of run-time immutable values. And some VRP was added to foreach loops. So now this is accepted: void main(in string[] args) { immutable size_t len = args.length % 10; ubyte x = len; ubyte[] a; foreach (immutable i; 0u .. len) a ~= i; } Bye, bearophile
Oct 23 2014
Hi, I am the guy who implemented the (currently incomplete) vrp for sdc. I see vrp as a tool to avoid _unnecessary_ casts. _Not_ as means to avoid _all_ casts.void main(in string[] args) { immutable size_t len = args.length % 10; ubyte x = len; ubyte[] a; foreach (immutable i; 0u .. len) a ~= i; }The problem with vrp for non-static immutable values is, that vrp becomes a runtime-thing and I would like to avoid that! Tracking the range of a Variable at runtime could cause significant overhead! Doing static analysis and tracking Variable-Ranges and assignments at compile-time, is possible but difficult and there are a number of reasons why not to do it. 1. Slows compilation down 2. implementation is not straight-forward and bugs could be hard to find. 3. Code that relays on this may not be easy to read, and it may be hard for the programmer to see why a particular assignment does not need a cast! For simple code like the one posted above it is easy to see why it works. anything mod 10 can only be in the range of [-9 .. 9] But if we have much logic and control-flow between the assignment and the definition of the assigning variable then not haveing an explicit cast could cause a bit of puzzlement.
Oct 24 2014
Stefan Koch:The problem with vrp for non-static immutable values is, that vrp becomes a runtime-thing and I would like to avoid that! Tracking the range of a Variable at runtime could cause significant overhead!Nope, the value range tracking is purely compile-time.2. implementation is not straight-forward and bugs could be hard to find.It's much better to remove bugs from the compiler than from an unbound amount of user code that uses casts incorrectly.3. Code that relays on this may not be easy to read,I don't believe this. Please show one or more examples.and it may be hard for the programmer to see why a particular assignment does not need a cast!And this is bad because?But if we have much logic and control-flow between the assignment and the definition of the assigning variable then not haveing an explicit cast could cause a bit of puzzlement.I think most D programmers are used to C/C++ coding, that doesn't require most of those casts. I don't think that "puzzlement" is real, or problematic. Bye, bearophile
Oct 24 2014
you are right. I misread the code-snippt above. Of course this is staticly checkable!
Oct 24 2014
On 10/23/2014 8:29 AM, Shammah Chancellor wrote:Several of us working on it were a little surprised that DMD does not compile this: void main() { long l = 42; int i = l; } Is this expected to compile?No. As bearophile mentioned, VRP only applies to an expression. The compiler front end does not do dataflow analysis to affect semantics. (The optimizer does, but that is a later pass and does not affect the semantics.)Planned?Not currently.My post was based on my thought that this *did* compile and we were wondering rules for when the range would be reset. If `l` were __gshared for example, the range wouldn't be deterministic.To do it reliably would require dataflow analysis.Surely there should be some rules document? What we've implemented, is that the value range is calculated at float80 precision, and it's min and max can fit in the ultimate type for a cast, then it's good to go. We only look at the actual expression being implicitly cast.Just be careful with floats about accumulated roundoff errors. This is not a simple problem.
Oct 23 2014
Walter Bright:To do it reliably would require dataflow analysis.There are still several useful cases where dataflow analysis is not needed (like for immutable values) that are still missing. They could be added. Bye, bearophile
Oct 23 2014
On Wednesday, 22 October 2014 at 20:32:39 UTC, Walter Bright wrote:On 10/22/2014 2:31 AM, Shammah Chancellor wrote:Seeing as it affects semantics, should there not be a minimum standard of what must be provable by a D compiler? Inference is great, but portability matters too.A couple of us working on SDC are trying to get ValueRange propigation implemented. I was wonder if someone could offer some insight as to how VRP works in DMD. If for example, trying to get the value range of a global, what is the expected behavior? It seems as though VRP is a language feature, and not a compiler feature -- since this allows some code to compile and not others. Is there a specification for how it should work somewhere? If not, it's hard to implement other compilers that will not generate errors in the same circumstances as DMD.VRP is definitely a language feature, not a compiler feature. The specification is straightforward - a narrowing conversion can be implicitly performed if it can be proved that it would not lose information. How it works, though, is kinda tricky, and the only guide to it is the compiler source code.
Oct 23 2014
On 10/22/2014 10:32 PM, Walter Bright wrote:The specification is straightforward - a narrowing conversion can be implicitly performed if it can be proved that it would not lose information.This is only straightforward to state because it is so ill-defined. The main aspect in need of specification is the procedure to perform those automated proofs with.
Oct 24 2014
On 10/22/14 1:32 PM, Walter Bright wrote:On 10/22/2014 2:31 AM, Shammah Chancellor wrote:I think specification is equally tricky because it needs to specify the exact algorithms. -- AndreiA couple of us working on SDC are trying to get ValueRange propigation implemented. I was wonder if someone could offer some insight as to how VRP works in DMD. If for example, trying to get the value range of a global, what is the expected behavior? It seems as though VRP is a language feature, and not a compiler feature -- since this allows some code to compile and not others. Is there a specification for how it should work somewhere? If not, it's hard to implement other compilers that will not generate errors in the same circumstances as DMD.VRP is definitely a language feature, not a compiler feature. The specification is straightforward - a narrowing conversion can be implicitly performed if it can be proved that it would not lose information. How it works, though, is kinda tricky, and the only guide to it is the compiler source code.
Oct 27 2014
On 10/22/2014 11:31 AM, Shammah Chancellor wrote:A couple of us working on SDC are trying to get ValueRange propigation implemented. I was wonder if someone could offer some insight as to how VRP works in DMD. If for example, trying to get the value range of a global, what is the expected behavior? It seems as though VRP is a language feature, and not a compiler feature -- since this allows some code to compile and not others. Is there a specification for how it should work somewhere? If not, it's hard to implement other compilers that will not generate errors in the same circumstances as DMD.AFAIK: - arithmetic operators: new range is given by the minimum and maximum values that the whole expression can attain given that operands are arbitrary values from their respective ranges. (DMD currently does something worse for bitwise operators, and probably modulo.) If overflow may occur, the full data type range is assumed. Likewise if divide by zero may occur. (This despite the fact that divide by zero is supposedly undefined behaviour. Go figure.) - mutable variables: full data type range is assumed - immutable variables: range of initializer is assumed. If it is a foreach range index variable, combine value ranges of lower and upper bound appropriately.
Oct 24 2014