https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94042
--- Comment #24 from Andrew Pinski <pinskia at gcc dot gnu.org> --- (In reply to Martin Liška from comment #23) > (In reply to Andrew Pinski from comment #20) > > The return value of the first _Z11tsubst_exprP9tree_nodeS0_iS0_b.part.0 was > > being copied into r8 and then copied back into r3 (return value), but not r0 > > is used and that r0 is used for mtlr (moving back the return address). > > This is the correct explanation, thanks Adrew. > > In good version > │0x104c9128 <._Z19tsubst_template_argP9tree_nodeS0_iS0_+104> bl > 0x1049f300 <._Z11tsubst_exprP9tree_nodeS0_iS0_b.part.0> > > sets return value to $r3, which is then returned ($r8 = $r3, $r3 = $r8): > (gdb) p /x $r3 > $60 = 0x3fffaf3814d0 > > while in bad version we return value of: > │0x104c9134 <._Z19tsubst_template_argP9tree_nodeS0_iS0_+116> mtlr > r0 > (gdb) p /x $r3 > $31 = 0x104c92a4 > > which is the return address (can be seen in back-trace). Note I bet after LRA, there is a move between r0 and r3 after the call to _Z11tsubst_exprP9tree_nodeS0_iS0_b.part.0 but it gets removed as r0 is clobbered by the load. So we need to understand why LRA/IRA assigns the r_5/_34/_21 as r0 and then what also decides to use r0 for load/storing the LR.