What might be useful though is something like -wall printing all flags representing current best practices, so you can have a snapshot of it when writing new code (the problem with current -wall is again potentially arbitrary changes on compiler updates as new warnings get added, if it actually did warn on everything)
Then you can choose when you want to update to whatever modern best practices
I've been the lead on a fairly large Fortran project, and we make a point to run our test suite on as many compilers as possible, with the strictest flags to avoid any kind of "undefined" behavior (which is rarer in Fortran than in C). I believe it's the only way to ensure long term maintainability.
1. load x into a register
2. spill the register holding x to the stack
3. call f
4. reload the "local" version of x from the stack
5. add
On the other hand, if the order of evaluation can be chosen by the compiler, it can do this:
1. call f
2. load x into a register
3. add
(Details depend on whether the caller or the callee saves x, but you get the idea.)
I think this is done early, during lowering to a "mid-end" intermediate representation (whether SSA or not). This is the best time to do it, since the legality of this reordering is a property of the source language, which you want to forget about in the mid-end. On the other hand, in this particular example (function call vs. global variable access), I don't think there is any reason to delay this; doing the call first should never be worse than loading the global first.
As for deciding other things later, instruction scheduling and global code motion can reorder a lot of things, though calls and memory accesses block many movements.