I am doing all that with a basic C pre-processor in my assembly source code. But the more I think about this, the more I think I should write my own pre-processor, which "should" be much simpler than a C pre-processor in the end and would do a cleaner job since taylored for those usages (the "annoying" thing is the arithmetics expression evaluation).
I would write this pre-processor in assembly, namely design a binary specification (that to be ready for other ISA implementations).
Then, they are the really important things: for all micro-architectures, how to be friendly to conditional branch predicition, how to handle BTB entries layout in a cache line, show how important the "cache line" is ubiquitous, etc.
I remember clearly one of the TheHeavyThing developers telling me than with a basic and naive hand compilation of gzip, he was beating the best compilers, at that time, by a consistent 10/15%. Let me remind people here of something: nobody is supposed to be able to beat a compiler on deep and hairy compilation units. If it is the case, something is wrong in that compiler.