Well, most architectures do not use plain jumps with implicit arguments for function calls, but have explicit call/ret or branch-with-link instructions. Even those that used jumps had branch hints. The reason is that the microarchitecture must know about call/ret pairs to be able to predict the return path as the generic dynamic predictor is just not good enough for such a common path.
Reduced prediction performance compared normal calls is actually a concern for some coroutine and async code.
> in C we don’t have any dynamic lookup inside functions—every dynamic jump comes from an explicit conditional statement
function pointers.