Learning to Superoptimize real-world programs
arxiv.org
arxiv.org
Does that mean that the runtime is only 6.2% of the runtime after gcc optimization, or that there was a 6.2% reduction in runtime compared to gcc optimization?
And that's the ISA that actually executes on the gpu, including instruction encoding and whatnot - not just some IR
Similarly, try and work out how a compiler schedules and lays out code for a modern superscalar processor. Both things do matter (potentially a lot) but it's not like the old days where you have a very fixed model of the pipeline to evaluate your schedule with (or a simple one at least)
More boringly, treating the compilation metadata more as a database may also be waiting to be exploited. Right now we have feedback-directed optimization which basically takes a 1:many or 1:1 approach of one data set gives you one binary. Next compile you start with new input and run the process again, whereas retaining a history might allow for deeper tree searches.
It's always annoyed me a little that every single time my code loads or gets compiled that the runtime has to start from ground state and build up. If I run the same compile fifty times in a row it's always the same output and it always takes the same amount of time. If a big improvement is just beyond the search budget it will forever remain out of sight. Especially in a CI/CD world my ratio of changes to binaries is very, very low, and so the waste is much more pronounced.
If instead you store a map of decisions and constraints, can I test the constraints, flush all of the decisions whose constraints are violated, and begin my search tree from there? Going a little deeper every time in stable areas of the code?
If you want to go off the deep end of the possibilities of NNs in compilers, I suggest you look up wake-sleep program synthesis at the least: https://dl.acm.org/doi/10.1145/3453483.3454080
As I understand it, the model is trained on what compilers do anyway (the training data consists of compiler output from -O0 and -O3), so it won't come up with the kind of clever tricks that a human might.
One of their cherry-picked examples (fig5, prstree_empty) is incorrect: in one branch it is supposed to return true if the value at rdi+0x10 is a null pointer, but in the optimized version it falls through from "sete %al" to the next instruction, which overwrites that register so it will always return true.
It would be easy to fix by inserting another return instruction, but this clearly shows the neural net doesn't "understand" how to generate correct code. Besides some peephole optimizations, a lot of what it learned seems to be how to fool automated checks, and in this case even the authors who didn't spot the bug.
See also the section about verifier exploits, which are embarassingly simple: a completely empty "if statement" which depends on memory causes a function to pass when it clearly does nothing more than always return false.
The 6.2% figure is after "human verification" (again, one of the examples in the paper is broken!), down from 8.3% using only the automated verifier.
Not impressed.