Loop unrolling, escape analysis and other things like this are solved like in any other JIT, you have some internal representation, optimize it, lower it, assemble it into memory, make the pages executable, and jump to your inmemory machinecode. There are vast amounts of details glossed over, but these would be the same problems if you wrote your JIT in C, Python or anything.
The only Go related problem is how do you actually run the machine code once it's loaded in memory. I would take a look at how wazero handles this as they must already solve this problem. You could handle this by writing assembly, spawning another OS thread, ...