https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110606
--- Comment #11 from Jeevitha <jeevitha at gcc dot gnu.org> --- Regarding the test case provided by Matthias Klose: Within the AllocMemory() routine, the compiler aimed to eliminate the entire if block but faced difficulties in removing references to the variable 'sMemPool'. The corresponding source code is as follows: if (sMemPool) { __trans_tmp_2 = operator new(AllocMemory_size); return __trans_tmp_2; } void *ptr = operator new(AllocMemory_size); return ptr; The subsequent details are pertaining to the body of if statement [BB5], which includes a 'mov' [insn 35] for "AllocMemory_size" and a 'call' [insn 36] for "operator new." Furthermore, regarding the code after the if body [BB6], there was another 'mov' [insn 43] and 'call' [insn 44], similar to those in BB5. Before SCHED1: -------------- BB5: insn 35 set r3, r124 insn 36 call [`operator new`] -> Uses r3,r2 ... insn 78 jump L47 L41: BB6: insn 43 set r3, r124 insn 44 call [`operator new`] -> Uses r3,r2 ... L47: BB7: insn 49 set r5, 0 insn 50 set r4, 1 During the 'sched1' pass, a reordering occurred that moved insn 35 before insn 31 from BB5 to BB4. BB4 contains the check for the 'sMempool' variable [insn 33]: if it's zero, there's a branch to label 41, leading to BB6; otherwise, it continues with BB5. After SCHED1: ------------- BB3: insn 80 set r145, high(unspec[r2]) insn 81 set r139, r145+low(unspec[r2])' BB4: insn 72 set r3, r139 insn 23 set r124, [r138] insn 26 call [`__tls_get_addr`] -> Uses r3,r2 insn 75 set r142, r3 insn 28 set r132, unspec[r142, symbol_ref: `_ZL8sMemPool`] insn 29 set r130, unspec[r132, symbol_ref: `_ZL8sMemPool`] insn 35 set r3, r124 insn 31 set r133, [r130] insn 32 set r134, cmp(r133, 0) insn 33 set pc, { (r134 == 0) ? L41 : pc } BB5: insn 36 call [`operator new`] -> Uses r3,r2 ... insn 78 jump L47 L41: BB6 insn 43 set r3, r124 insn 44 call [`operator new`] -> Uses r3,r2 ... L47: BB7: insn 49 set r5, 0 insn 50 set r4, 1 In the 'Jump2' pass, the compiler successfully removed the if body (bb5) consisting of insn 36 and insn 78. However, it couldn't remove insn 35, which was moved to bb4. Additionally, it changed insn 43 to be in bb6 and moved the remaining instructions from insn 44 to bb10. As insn 43 and insn 35 are similar instructions, insn 43 was chosen for deletion in the later pass. After JUMP2: ----------- BB3: .... insn 80 set r28[orig:r145], high(unspec[r2]) insn 81 set r28[orig:r139], r28[orig:r145]+low(unspec[r2])' .... BB4: .... .... insn 32 set cr0[orig:r134], cmp(r9[orig:r133], 0) insn 33 set pc, { (cr0[orig:r134] == 0) ? L41 : pc } BB5: insn 134 set pc, L133 L41: BB6: insn 43 set r3, r30[orig:r124] L133: BB10: insn 44 call [`operator new`] -> Uses r3,r2 insn 49 set r5,0 insn 50 set r4, 1 .... In cprop_hardreg pass, insn 43 in BB6 is removed After cprop_hardreg: -------------------- BB3: .... insn 80 set r28, high(unspec[r2]) insn 81 set r139, r28+low(unspec[r2])' .... BB4: insn 72 set r3, r28[orig:r139] insn 23 set r30[orig:r124], r27[orig:r138] insn 26 call [`__tls_get_addr`] -> Uses r3,r2 insn 28 set r9[orig:r132], unspec[r3[orig:r142],symbol_ref: `_ZL8sMemPool'] insn 29 set r9[orig:r130], unspec[r9[orig:r132],symbol_ref: `_ZL8sMemPool'] insn 35 set r3, r30[orig:r124] insn 31 set r9[orig:r133], [r9][orig:r130] insn 32 set cr0[orig:r134], cmp(r9[orig:r133], 0) insn 33 set pc, { (cr0[orig:r134] == 0) ? L41 : pc } BB5: insn 134 set pc, L133 L41: BB6: L133: BB10: insn 44 call [`operator new`] -> Uses r3,r2 insn 49 set r5,0 insn 50 set r4, 1 .... Following the removal of insn 43 in the 'cprop_hardreg' pass, both insn 134 and 33 became unnecessary due to jumping to the same location, which was removed in the basic block reordering pass. After BBRO: ----------- BB3: ... insn 80 set r28, high(unspec[r2]) insn 81 set r28, r28+low(unspec[r2])' ... BB4: insn 72 set r3, r28 insn 23 set r30, r27 insn 26 call [`__tls_get_addr`] -> Uses r3,r2 insn 28 set r9, unspec[r3,`_ZL8sMemPool'] insn 29 set r9, unspec[r9,`_ZL8sMemPool'] insn 35 set r3, r30 insn 31 set r9, [r9] insn 32 set cr0, cmp(r9, 0) insn 44 call [`operator new`] -> Uses r3,r2 insn 49 set r5,0 insn 50 set r4, 1 ... Upon the removal of these jumps, instructions 32, 31, 29, and 28 in bb4 became dead, since r9, r3 were used for those jumps. During 'sched2 DCE,' those instructions in BB4 were removed, rendering r3 unused (which was populated in insn 26). However, its not deleted in this pass: After SCHED2: ------------ BB3: ... insn 80 set r28, high(unspec[r2]) insn 81 set r28, r28+low(unspec[r2])' ... BB4: insn 23 set r30, r27 insn 72 set r3, r28 insn 26 call [`__tls_get_addr`] -> Uses r3,r2 insn 35 set r3, r30 insn 44 call [`operator new`] -> Uses r3,r2 insn 49 set r5,0 insn 50 set r4, 1 ... ... The flag 'df_in_progress' is avoiding the call deletion in 'sched2 DCE'. If the insn 26 is removed, insn 72 can be removed. Consequently, below instructions in BB3 could be removed if insn 72 were removed, BB3: insn 80 set r28, high(unspec[r2]) insn 81 set r28, r28+low(unspec[r2]) Currently, we have an ICE in insn 80 and 81. Despite of being dead instructions, they remain unremoved until the final pass. The final pass attempts to retrieve a dynamic symbol for insn 80 by iterating over all instruction below, it was present in insn 28. However, insn 28 has already been removed in 'sched2.' Enabling 'sched2' to handle call deletion successfully removed call_insn 26 and insn 72 in BB4. However, insns 80 and 81 were not removed because live registers (specifically, r28, which is unused) weren't updated for BB3 in the same pass. Another 'DCE' pass is required, but our GCC does not have 'DCE' after the 'sched2' pass.