Thanks for all the responses.
@Brian Leach, there's always a case for old school and a very good point.
Further testing raised the interesting situation that I can call a subroutine that is not cataloged - hence my confusion that both CALL *SUB and CALL SUB ran the same code. In fact CALL *SUB ran the globally catalog code while CALL SUB ran the object code from the .O file even though there is no catalog for SUB. Case 00933081 raised as I did not expect that behaviour.
@Neil Morris, my testing has been using routine we have for code analysis, so many levels of recursive calls and complex enough to make it hard to provide for you to test. I'll keep digging and perhaps can some to some easy-to-publish code that demonstrates my findings.
What I'm really after this the details of the CALL logic used to find the the object code to execute including how already loaded code is used/reused.
@John Jenkins, I agree the benefit of SHM.TO.LOAD seems small, especially in the Web DE scenario where the responder process is running for long periods and therefore subroutines remain in memory once called.