-
-
Notifications
You must be signed in to change notification settings - Fork 608
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add VRP-based constant folding for integer comparisons. #5229
base: master
Are you sure you want to change the base?
Conversation
27a8679
to
e00c100
Compare
|
If this breaks Phobos, then that begs the question of what other code this could break in the wild. I think it would be prudent to at least try to compile some popular dub libraries with this just to be sure. |
|
@JackStouffer Because of the With this PR, code which is potentially effected will mostly either:
Edit: I forgot that it turned out to be a This issue is only really likely to come up in unicode codecs; even then only one line in all of The other required Phobos change is potentially of greater concern, though, as it indicates that it is at least possible for integer comparison folding to interact with templates and dead code detection in awkward ways. So, I guess I can try compiling some other people's stuff to see how common that issue is. |
|
@JackStouffer So I tried building some stuff from dub and learned:
Upon further investigation, I have determined that (3) is caused by the pre-existing DMD issue #14835. The problem is, the better that VRP and constant folding get, the worse that issue 14835 becomes. |
|
I think the dchar.max patch should be filed separately. It is a bug and should get fixed asap. https://issues.dlang.org/show_bug.cgi?id=14627 |
|
@lionello This PR does not fix issue 14627. Your demo code still compiles and runs, even with this patch applied. This PR does not change |
e00c100
to
0446c50
Compare
|
Since the companion Phobos PR #3767 has been merged now, I tweaked the comment on line 1007 of |
src/constfold.d
Outdated
| n = e1.type.isunsigned() || e2.type.isunsigned() ? | ||
| intUnsignedCmp(op, n1, n2) : | ||
| intSignedCmp(op, n1, n2); | ||
| } | ||
| } | ||
| else |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about combining line 1002 with 1004 to make it else if? I think it would flow a little nicer.
0446c50
to
70119d8
Compare
|
@WalterBright Done. Is this likely to get merged soon, or is issue 14835 a blocker? |
|
I added a couple of "compilable" tests. The test for the Although it is not my motivation, I noticed that this PR is a partial fix for issue 13010. |
|
I made a forum thread to discuss fixing issue 14385. There is no consensus that it is even a bug; several people argued that the current behaviour is correct. In any case, it is not obvious that there is a good way to fix it short of just removing the warning. I do not think 14385 should block this PR. Are there other objections? |
a32474a
to
80b1231
Compare
80b1231
to
e84b1a1
Compare
src/constfold.d
Outdated
| assert(0); | ||
| } | ||
| else | ||
| else if (e1.isConst() == 1 && e2.isConst() == 1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't isConst return a bool? Seems strange to explicitly compare it's return value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does not. It returns 2 for some stuff that isn't const but can be accessed in ctfe.
|
Note that the auto-tester failure is due to DMD 14835 again. |
@quickfur I'll split the |
|
@tsbockman @lionello : Thank you so much for working on this. It is IMO a change of great importance for the end user. I agree that https://issues.dlang.org/show_bug.cgi?id=14835 is a big annoyance, and can only get worse in the future. However, in this case, it is actually helpful. (EDIT: Actually, after testing, I couldn't find any case where it was). However, changing |
How so? In general, there is absolutely nothing wrong with the code that triggers that warning with my VRP improvements. The warning is essentially spurious. There is nothing to "fix" - it's just noise that must be ignored or worked around, in a very tedious fashion.
I'd like to, but I haven't found any reliable way of actually demonstrating the problem without the rest of this patch. (That's why it hasn't been a big problem so far: the compiler is not yet "smart enough" for the faulty assumption to cause real problems.) I'm not really comfortable submitting a "fix" without a test case to go with it. |
be32621
to
d3e7577
Compare
It has never been a problem to submit separate P.R. like this. void check (T) (T a) { assert(a <= T.max); } |
d3e7577
to
7ded4e4
Compare
This possibility is definitely worth looking into. The most important part would be to suppress the warning in template functions, and functions that are nested inside of templates (even if the function itself is not templated). I'm not sure if scanning the body for conditional compilation statements is necessary or not; spurious warnings can occur outside of templates - even in code with no
I'd be very surprised if DScanner can do this better than the compiler, but would be happy to be proven wrong. At least if the warning were coming from DScanner, people wouldn't feel obligated to "fix" the code when it's not actually broken. EDIT: Looking back, the "goto fail" case is simple enough that a linter like DScanner should be able to detect it without too much trouble - especially since the bad code formatting, alone, is sufficient cause to issue a warning there.
It doesn't, and shouldn't, generate a warning. But, some others I've discussed it with expect it to anyway - maybe because of confusion about the precise difference between run-time |
I still believe this is doable, but I don't understand the compiler internals well enough to easily do it myself. Since I am ending my participation in the dlang project, I'm going to close this now. It would probably just be rejected anyway, since WalterBright doesn't seem the slightest bit interested in the long-term goal of fixing issue 259 (despite having pre-approved the fix). |
|
This is valuable work. I haven't been able to get to it (I'm currently working on all the complaints about @safe problems). |
Well then, the aspect of this that really needs your input is how to mitigate issue 14385, which I consider to be a blocker for this. If that is dealt with, the rest of this should be fairly straightforward, as most of the work was already done by @lionello ages ago. |
|
I'll look into it. |
b5da01b
to
54c4c82
Compare
src/intrange.d
Outdated
| else if (!isUnsigned) | ||
| /* Although dchar.max is officially 0x10FFFF, do *NOT* initialize upper to this value. | ||
| Doing so will cause attempts to guard against invalid out-of-range dchar values to | ||
| be considered unreachable. */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So with this change, dchar.max will still be 0x10FFFF ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. Raising dchar.max would be a massive breaking change, and is not needed for my purposes.
All I did is remove the special casing for dchar in the VRP code, so this fix will remain correct even if someone else gets permission to actually set dchar.max == unit.max later.
54c4c82
to
2614955
Compare
|
|
Ping @WalterBright . Any update on issue 14385? Is this PR going anywhere, or not? |
|
This still isn't going anywhere, so I'm moving on. |
|
The submitter moving on is not a sufficient reason to close good work. |
|
Thanks for your pull request and interest in making D better, @tsbockman! We are looking forward to reviewing it, and you should be hearing from a maintainer soon.
Please see CONTRIBUTING.md for more information. If you have addressed all reviews or aren't sure how to proceed, don't hesitate to ping us with a simple comment. Bugzilla references
Testing this PR locallyIf you don't have a local development environment setup, you can use Digger to test this PR: dub run digger -- build "master + dmd#5229" |
Should have added the phantom zone label. |
|
Nah, I think this is of more immediate value. |
This is the first instalment of my translated and improved rendition of @lionello 's PR #1913, which I have decided to break up into chunks, since it makes several changes which do not need to be evaluated on an all-or-nothing basis.
This first piece:
dcharvalues fromdchar.maxtouint.max.statement is not reachablewarning. That warning interacts very badly with effective VRP in generic code (DMD issue #14835), and when I made a forum thread to discuss the issue, the conclusion was that a true fix is not feasible.Strategically, my goal is to enhance VRP and constant folding capabilities to the point that issue 259's pre-approved solution to the problem of dangerous signed/unsigned comparisons can be implemented without causing too many "false positive" errors.
This PR does not accomplish that goal by itself, but it is a useful step. In the mean time, it modestly improve the front-end's ability to optimize logic and detect unreachable code.
The change to
dchar's initial VRP maximum is required to prevent the compiler from treating attempts to handle invalid out-of-rangedcharvalues as dead code. I got @WalterBright 's approval for this part earlier on the forums: http://forum.dlang.org/post/oionrfexehapzicgpbrw@forum.dlang.org