3 ms·
Not only do you only have 4KB of instruction cache, but it's direct mapped. So if the linker just so happens to place the function you are calling at some addr
by phire 3y ago
Not only do you only have 4KB of instruction cache, but it's direct mapped.
So if the linker just so happens to place the function you are calling at some address that's some multiple of 4KB away from your current hot loop, then the code for your hot loop, and the function you call will get continually evicted and reloaded for each loop iteration.
A small change to a random function could have large impacts on the alignment of all other functions in your game, and could result in large performance impact. The simple solution is to just inline everything your hot loops call. That avoids the chance of the pathological cases (and has the bonus of avoiding function call overhead), but at the cost of increasing code bloat in general (which the cache hates).
I've been vaguely considering making linker that's aware of direct mapped caches, and uses the call graph to guide the placement of functions (and data too, for machines with direct mapped data caches). Not only would it be useful for retro consoles with direct mapped caches like the ps1 and n64 (and probably help for the PS2 too, which is only 2-way set associative) but it would be useful for modern microcontrollers that do XIP execution of code from flash. They often have simplistic direct mapped caches too.