In the following example, when DemoteRegToStack demotes %call.i.i.i14.i.i, it firsts scans all the uses of %call.i.i.i14.i.i and inserts load instructions before all its users. Since %0 is a phi instruction, a load instruction is inserted in the predecessor block, which is the entry basic block. Then it inserts a store instruction to save the value it is demoting to the stack. In this case, %call.i.i.i14.i.i is an invoke, so it creates a basic block that splits the critical edge (entry-do.body.i.i.i), and inserts the store there. This is incorrect because the store instruction should be executed before the load instruction.
define void @_Z4foo1c(i8 signext %a) {
entry:
... %call.i.i.i14.i.i = invoke noalias i8* @_Znwm(i32 1024) to label %do.body.i.i.i unwind label %lpad.body
do.body.i.i.i: ; preds = %entry, %_ZNSt3__116allocator_traitsINS_9allocatorIcEEE9constructIccEEvRS2_PT_RKT0_.exit.i.i.i
%0 = phi i8* [ %incdec.ptr.i.i.i, %_ZNSt3__116allocator_traitsINS_9allocatorIcEEE9constructIccEEvRS2_PT_RKT0_.exit.i.i.i ], [ %call.i.i.i14.i.i, %entry ] ...
The IR after SjLjEHPrepare pass looks like this:
define void @_Z4foo1c(i8 signext %a) {
entry:
%call.i.i.i14.i.i.reg2mem = alloca i8* ... %call.i.i.i14.i.i.reload = load volatile i8** %call.i.i.i14.i.i.reg2mem ... %call.i.i.i14.i.i = invoke noalias i8* @_Znwm(i32 1024) to label %entry.do.body.i.i.i_crit_edge unwind label %lpad.body
entry.do.body.i.i.i_crit_edge: ; preds = %entry
store i8* %call.i.i.i14.i.i, i8** %call.i.i.i14.i.i.reg2mem br label %do.body.i.i.i
do.body.i.i.i: ; preds = %entry.do.body.i.i.i_crit_edge, %_ZNSt3__116allocator_traitsINS_9allocatorIcEEE9constructIccEEvRS2_PT_RKT0_.exit.i.i.i
%3 = phi i8* [ %incdec.ptr.i.i.i, %_ZNSt3__116allocator_traitsINS_9allocatorIcEEE9constructIccEEvRS2_PT_RKT0_.exit.i.i.i ], [ %call.i.i.i14.i.i.reload, %entry.do.body.i.i.i_crit_edge ]
This patch fixes the bug by changing llvm::DemoteRegToStack to insert the store instruction and create basic blocks that split critical edges first, and then insert the instructions to reload the value.