https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70164
--- Comment #11 from Jeffrey A. Law <law at redhat dot com> --- So given the conflicts during IRA I can't see a way for IRA to do a better job. Essentially the key allocno/pseudo wants hard reg 0 to avoid the spillage, but it also conflicts with hard reg 0. Prior to CSE1 we have the following key statements: (insn 15 14 16 2 (set (reg/v/f:SI 116 [ <retval> ]) (reg:SI 0 r0)) j.c:23 748 {*thumb1_movsi_insn} (nil)) [ ... (jump_insn 19 18 20 2 (set (pc) (if_then_else (ne (reg/v/f:SI 117 [ line ]) (reg/v/f:SI 116 [ <retval> ])) (label_ref:SI 36) (pc))) j.c:25 756 {cbranchsi4_insn} (int_list:REG_BR_PROB 8987 (nil)) -> 36) [ ... ] (insn 21 20 22 3 (set (reg:SI 0 r0) (reg/v/f:SI 117 [ line ])) j.c:25 748 {*thumb1_movsi_insn} (nil)) [ ... ] (insn 31 30 36 3 (set (reg/v/f:SI 116 [ <retval> ]) (reg:SI 0 r0)) j.c:25 748 {*thumb1_movsi_insn} (nil)) [ ... ] (insn 28 27 29 3 (set (reg:SI 1 r1) (reg/v/f:SI 117 [ line ])) j.c:25 748 {*thumb1_movsi_insn} (nil)) [ ... ] (insn 37 39 38 4 (set (reg/i:SI 0 r0) (reg/v/f:SI 116 [ <retval> ])) j.c:26 748 {*thumb1_movsi_insn} (nil)) (insn 38 37 0 4 (use (reg/i:SI 0 r0)) j.c:26 -1 (nil)) Of particular interest is that r116 is not live-in to bb3. If you do the full analysis, it can be shown that r116 does not conflict with r0 before cse1. And that's key because to get the code we want r116 needs to be assigned to r0. cse (like DOM) has the ability to look at a equality conditional and propagate equivalences into the true or false arm. ANd if we look at insn 19, we've got a equality conditional between r117 and r116 which will set up an equivalence between r116 and r117 for bb3. So in bb3, cse1 will change the initial assignment from: (insn 21 20 22 3 (set (reg:SI 0 r0) (reg/v/f:SI 117 [ line ])) j.c:25 748 {*thumb1_movsi_insn} (nil)) to: (insn 21 20 22 3 (set (reg:SI 0 r0) (reg/v/f:SI 116 [ <retval> ])) j.c:25 748 {*thumb1_movsi_insn} (nil)) Which makes r116 live-in for bb3. But note that it doesn't change insn 28 (yet). forwprop then comes along and changes insn 28 to look like: (insn 28 27 29 3 (set (reg:SI 1 r1) (reg/v/f:SI 116 [ <retval> ])) j.c:25 748 {*thumb1_movsi_insn} (expr_list:REG_DEAD (reg/v/f:SI 116 [ <retval> ]) (nil))) Now r116 is both live-in to bb3 and conflicts with r0 within bb3. At which point we have lost. I've got a couple things I want to poke at... But nothing that I think has a high probability of success.