True, it's not always possible because there are certain constrained cases where the value in a fixed destination register immediately needs to go to a fixed source one, but from my experience a lot of cases have intervening operations that don't need a fixed source/dest, and yet the compiler didn't arrange things so that the results of preceding operations naturally went to the right place as the instruction came up, but instead had to generate a MOV. I suppose it's because there's a certain amount of "working backwards" (alternatively, "looking ahead") that's required, and traditional code generation techniques don't consider this case. A good human programmer would think "I'll need to divide, so I should compute the dividend in eax" or "there's a shift coming up, so the computation leading up to the shift amount should use ecx".
Calling conventions are similar (e.g. eax needs to be the return value), so you see things like this:
mov ecx, [ebp+16]
add ecx, edx
mov eax, ecx ; superfluous move
ret
when this could've been done instead: mov eax, [ebp+16]
add eax, edx
ret