This is being done all the time by the JIT. It is a standard optimization for pretty much any JIT and native compiler.
Don't confuse the logical IL stack with the physical x86 stack that the jitted code uses. They are very weakly related. IL stack contents and IL locals are being stored preferably in registers and spilled to the x86 stack only if needed.
The only exception are structs which are usually stack-allocated in both the .NET 4.5 JIT and the vNext RyuJIT (as of VS2015 Preview). This is not documented but testing clearly shows that not even in the simplest cases structs are being enregistered. Maybe I missed some case where it happens but it is clearly a rare case.
Primitive types and object references are consistently stored in registers (if available) according to my testing.