On 09.04.2012 5:11, Daniel Murphy wrote:
"Dmitry Olshansky"<[email protected]> wrote in message
news:[email protected]...
The refinement is merging prefixes and suffixes of course.
And for that one needs to calculate hashes for all of prefixes and all of
suffixes. I will define _all_ later on.
I think you'll find that this is better done in the compiler instead of the
linker. Merging prefixes is problematic because at some point you will need
to work out which tail to execute, so you'll always need to modify the
generated code.
"Easy": just add a hidden pointer argument to functions that have merged
prefix (call it dispatch). The prefix part of code is followed by an
indirect jump to this pointer.
Compiler arranges so that every time function is called the correct
dispatch address is passed behind the scenes.
BTW there are no extra checks and such it's one naked indirect jump, and
it's totally predictable unlike say switch jump.
(well unless you use a few copy-paste-susceptible functions in the same
loop that turn out to have prefixes merged)
It still implies that prefix merging should be applied with more care
then suffix merging. Once this tested and working even merging arbitrary
parts of functions is doable with this approach.
Merging suffixes is easier, you can merge all returning blocks with
identical code, and then merge all blocks that always jump to the same
blocks, etc.
This will need to happen after code generation if you want to merge int/uint
code, which would be difficult in dmd's back end.
Any chance to fit this into IR-->CodeGen step? Like use alternative
comparison then memcmp. Or better do basically the same algorithm but on
map!(....)(IR) that morphs things so that some identical ops (e.g.
uint/int == and !=) are considered the same. In fact this might be even
faster then generating useless machine code!
Merging functions with identical bodies is of course much easier, and can be
done in the linker without needing to modify any code (just the
relocations).
--
Dmitry Olshansky