A code like this is often seen in r-value references articles:
Dave Abrams: Move It With Rvalue References
void g(X);
void f()
{
X b;
g(b);
Could a compiler do it? Only as an explicit language extension, because the standard doesn't allow them to make such an optimization without that.
Should they do it? No. The meaning of g(b) should be based on the definition of g and b. g should be some callable type, which has an overload that takes something that b can be implicitly converted into. Given access to the definition of all available gs, and the definition of b, you should be able to determine exactly what function will be called.
To allow this "optimization" now means that this is impossible. g(b) might perform a move, and it might not, depending on exactly where g(b) happens to be in a function. That's not a good thing.
return is allowed to get away with it, but only because it still has the same meaning. return b will always attempt to move from b if b is a value-type who's lifetime is restricted to the scope of the function.