To me, it is more of a mystery why StorageLive(_2) was created for let _y;
when no type and value were yet available.
No doubt something will be said about copying items on the stack but even so, one copy should not need two more locations?
This is just a guess but,
MIR is just an internal representation of the compiler. Its generation is not optimized for such efficiency because it later optimized in LLVM passes but more optimized for implementation simplicity.
So the answer to the question is probably because it was simpler to implement in that way and there is no real reason.
There are probably more complex cases, such as types with Drop or construction of struct literals, that may require some kind of two-phase assignment. I wouldn't be surprised if complex MIR was generated in all cases just to handle the special cases.
_1 is a bool, which is Copy. So when it's read out of, it's copied (_3 = _1) and then that copy is moved into the target (_2 = move _3). It's not necessary, but it's easier to generate that way than special-casing situations where it's not needed. LLVM can optimize it away just fine (in either mem2reg or just in SSA building), so it being generates this way is fine.