I’m working on a research project and have come to the conclusion that to achieve what I want with LLVM I need to use a custom intrinsic function. The very top of the documentation page for extending LLVM however encourages me to ensure this is the correct course of action, so I want to outline my problem here, and the various solutions I’ve considered, to get people’s opinion.
I’m looking into emitting a new load opcode based on compiler analysis. For specific code patterns, I want to inform the backend to replace regular load instructions with these new load instruction opcodes, which carry out the same function but carry contextual information for out of order speculation.
So far I’ve tried to attach metadata to the source pointers of the load instructions, like the GEP instructions. Then, from a backend machine function pass, I find the IR level memory operand of each load instruction, and walk the def chain to see if the pointers have this metadata attached. However, by default metadata is stripped from IR when it’s lowered to machine specific representation, and so my only two choices there are to hack each individual pass that strips this metadata to make my new metadata count as known metadata (infeasible) or classify my new metadata as alias analysis metadata, which isn’t fitting for what it is and also hacky.
Another idea I was given was to set the address spaces of the pointers to differentiate loads on them as candidates for this new opcode, but pointers in different address spaces are not allowed to alias, which is not a guarantee I am making at all with my analysis so this would be unsound.
Lastly I’m considering using an intrinsic function that takes as arguments the relevant pointers, and then the machine function pass can scan the IR function and compare the intrinsic’s arguments against a given load’s IR memory operands. This seems like the most natural option by this point, but before pursuing this I wanted to ensure I was correct. Please let me know if there are better ways to do this.