There was an assumption in the emitPrologue and emitEpilogue codes that register R0 could be used as a scratch register when saving/restoring several registers (Link Register, Base Pointer, etc.). When shrink wrapping has moved the location of the prologue/epilogue, it is possible that R0 has already been assigned and is in use at the location where the prologue/epilogue are inserted, resulting in bad code generation. This is a problem that was exposed in the self-hosting build of Clang.
The solution is to use the canUseAsPrologue and canUseAsEpilogue methods to determine if a register is available to be used as the scratch register in the prologue/epilogue. If a register is available, it is saved in the PPCFrameLowering class for use by the emitProlog and emitEpilog methods. If no register can be found, the the blocks identified by shrink wrapping are not valid, and the optimization will not make any changes.
A reduced test case was created based on the failing file in the self-host build (BreakableToken.cpp)
Unless I am mistaking, FrameLowering instances can be shared by several MachineFunctions.
Although I believe it can’t happen with the current pipeline of MachineInstr passes, you have no guarantee that you won’t have a call to canUseAsPrologue with a different MachineFunction/MachineBasicBlock before emitPrologue. I.e., the information in here may be invalid between when you compute it and when you use it.
If you want to keep the information here, you would need a map MBB -> scratch reg, but given our current scheme you may use a pair MMB, scratch reg, and assert that MBB is the same in emitXXX as the last one you saw from canUseAsXXX.
That being said, it may make more sense to keep this information into PPCFunctionInfo that is bound to the function.