While it did once have some performance implications, I think the real reason is for expressing your intent cleanly. The real question is whether something while (*d++=*s++);
expresses intent clearly or not. IMO, it does, and I find the alternatives you offer less clear -- but that may (easily) be a result of having spent decades becoming accustomed to how things are done. Having learned C from K&R (because there were almost no other books on C at the time) probably helps too.
To an extent, it's true that terseness was valued to a much greater degree in older code. Personally, I think this was largely a good thing -- understanding a few lines of code is usually fairly trivial; what's difficult is understanding large chunks of code. Tests and studies have shown repeatedly, that fitting all the code on screen at once is a major factor in understanding the code. As screens expand, this seems to remain true, so keeping code (reasonably) terse remains valuable.
Of course it's possible to go overboard, but I don't think this is. Specifically, I think it's going overboard when understanding a single line of code becomes extremely difficult or time consuming -- specifically, when understanding fewer lines of code consumes more effort than understanding more lines. That's frequent in Lisp and APL, but doesn't seem (at least to me) to be the case here.
I'm less concerned about compiler warnings -- it's my experience that many compilers emit utterly ridiculous warnings on a fairly regular basis. While I certainly think people should understand their code (and any warnings it might produce), decent code that happens to trigger a warning in some compiler is not necessarily wrong. Admittedly, beginners don't always know what they can safely ignore, but we don't stay beginners forever, and don't need to code like we are either.
I think it depends on what you want to achieve... Do you want to improve the code? parallelize the code? clean it? just understand it?
Besides the great comment given by @Calphool, what I've done in similar cases (but not with 100K lines code to be honest) is this:
Look for whoever wrote the code. Or has use it. Asked them what I needed to know, that saves you a lot of time. This may seem stupid, but is not.
I made a graph of the dependencies. Take a look at this for an example.
Depending on what you need to do, you could measure the execution time of some (or all) function.
Start playing with it... but with modern tools, like git. If possible, started to add some tests.
If you want to see what functions get called, you could just print the functions that are called (take a look at this question). You could add a printf at each function using a script, but I don't think that is a good idea. Also, you have to think how are you going to go through the generated output.
After you know what you want, and before making my implementations, I try to isolate the part I need to work on. Meaning, I cleanup the code a little, put in a different file if needed, compile it and test it. Only then I proceed to actually modify the code adding functionality or whatever needs to be done. This may also include port the code to use modern building tools if needed.
My two cents.
Best Answer
Think of it like an assignment operation.
Same order when using memcpy to copy an array.