-
-
Notifications
You must be signed in to change notification settings - Fork 619
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
DMD emits a lot of unnecessary bounds checks #20869
Comments
I suggest just trawling some code and looking for array bounds checks; you'll find so many that are redundant because there was a condition immediately prior. I find myself writing this a LOT: Basically, my assessment over the last several months has been that in this current state, bounds checking is mostly useless, and I'm starting to think I should stop butchering my code with |
Honestly, if you care about performance this much, you should probably be using ldc or gdc and not dmd. It would be great if dmd could detect and eliminate redundant checks, but Walter is allergic to data flow analysis, so the frontend is unlikely to detect this sort of thing, and I have no clue how capable the dmd backend is at finding stuff like this (but however good it is or isn't, ldc is bound to do better unless separate compilation is making it so that it can't see the checks, though those particular hooks have been templated by now IIRC). Either way, in general, ldc and gdc are going to do a better job of optimizing code, since they have a lot more people working on them to make them produce optimized code. So, while I'm all for dmd doing a better job of it, normally, folks who really care about performance to that degree just don't use dmd outside of development (e.g. at Symmetry, we primarily use dmd during development so that we get faster compilation times, but ldc is used for production code). As for D code in general, bounds checking is required for the code to actually be So, I don't disagree with the idea behind the issue here. Ideally, dmd would do a better job of this (and with better data flow analysis, it may be the case that the frontend would be a good place to detect it given that it understands D in a way that the backends don't), but for the most part, the kind of folks who are concerned about performance to this degree don't use dmd in production. |
And to respond to this specifically, yes, bounds checking is supposed to be redundant in most cases, because it's an But it's certainly true that if the compiler can detect that the check has already been done (or if it can detect that the check is unnecessary for other reasons), it would ideally remove the check that it automatically inserts with indexing or slicing, since if it knows that the check has been done, it knows that it's redundant and thus unnecessary to guarantee memory safety. So, improvements in this area would be welcome, but the language design here makes it so that you should expect that bounds checking in general is redundant and simply there to ensure memory safety when you do make mistakes. The more unnecessary checks that gets optimized out the better, but they're redundant by their very nature - at least so long as you write correct code. |
Agreed. No bounds checking seen here: https://compiler-explorer.com/z/ofjYYzEoc |
DMD is a very productive compiler. Obviously DMD makes SOME effort here already or the case with |
@ibuclaw FYI, there's something odd about the GDC output there; see how it initialises the array with a series of load-immediates, and then puts assert test AFTER initialising the array... the array is unused by the assert branch, so I would expect optimisation to move the branch before the initialisation. LDC got it right; the assert branch is the very first instruction. I would expect the same from GDC...? |
Not my problem. https://compiler-explorer.com/z/9T551xKs5 |
True, although I wonder if that difference where the GCC compiler does one 8-byte load, where GDC does 8 1-byte loads is though? Definitely better codegen to do one reg-sized load... I wonder why the difference :/ |
Ah, you're assuming |
I'm finding a lot of my low-level perf issues are because DMD emits bounds checks everywhere, even where they're not needed, because error checking prior to the index has already caught the cases where the index is out of bounds.
Take this for instance:
In that case, we are certain that
f < 8
, but DMD emits a bounds check:If I write:
Then the bounds check disappears; so it seems that it is keeping track of
f & 7
to determine a value range, but the if/assert immediately above didn't do it...?There are a million cases like this; but this is just the one I have right in front of me.
The text was updated successfully, but these errors were encountered: