It was maybe cool 50 years ago or so. Nowadays it's no longer needed. Possible performance gains of such code are marginal and modern programming languages allow generating many specialized and optimized code pieces using the same template, so that self-modification is no longer needed.
There is also JIT (like in regexp engines), but it's different story.
It's still beneficial on some x86-64 implementations to rewrite indirect jumps (as used in PLT stubs) to direct jumps when feasible. For example, AMD says this about the Zen 4 architecture:
> Only a limited number of indirect targets that cross a 64MB aligned boundary relative to the branch address can be tracked in the indirect target predictor. Software should limit the number of indirect branch targets that cross such a boundary.
And one way doing this is to replace the indirect branch with a direct branch, which supports a 32-bit signed displacement.