https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80080
Jakub Jelinek <jakub at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |jakub at gcc dot gnu.org --- Comment #4 from Jakub Jelinek <jakub at gcc dot gnu.org> --- (In reply to Dominik Vogt from comment #3) > Most of this can be fixed in the backend, but all attempts to get rid of the > additional load ("lr %r3,%31") in "bar" within the backend have failed. > This is caused by overly complicated code being generated in > expand_compare_and_swap_loop(). I'm currently testing the patch below which > eliminates the superfluous variable cmp_reg (and the register allocated for > it). Is there any chance to get something like this into Gcc7? The patch > could possibly also help other targets. (Will post on gcc-patches when the > tests are complete.) > > > --- a/gcc/optabs.c > +++ b/gcc/optabs.c > @@ -5798,17 +5798,15 @@ find_cc_set (rtx x, const_rtx pat, void *data) > static bool > expand_compare_and_swap_loop (rtx mem, rtx old_reg, rtx new_reg, rtx seq) > { > - machine_mode mode = GET_MODE (mem); > rtx_code_label *label; > - rtx cmp_reg, success, oldval; > + rtx success, oldval; > > /* The loop we want to generate looks like > > - cmp_reg = mem; > + old_reg = mem; > label: > - old_reg = cmp_reg; > seq; > - (success, cmp_reg) = compare-and-swap(mem, old_reg, new_reg) > + (success, old_reg) = compare-and-swap(mem, old_reg, new_reg) > if (success) > goto label; > > @@ -5816,23 +5814,21 @@ expand_compare_and_swap_loop (rtx mem, rtx old_reg, > rtx new_reg, rtx seq) > iterations use the value loaded by the compare-and-swap pattern. */ > > label = gen_label_rtx (); > - cmp_reg = gen_reg_rtx (mode); > > - emit_move_insn (cmp_reg, mem); > + emit_move_insn (old_reg, mem); > emit_label (label); > - emit_move_insn (old_reg, cmp_reg); > if (seq) > emit_insn (seq); > > success = NULL_RTX; > - oldval = cmp_reg; > + oldval = old_reg; > if (!expand_atomic_compare_and_swap (&success, &oldval, mem, old_reg, > new_reg, false, MEMMODEL_SYNC_SEQ_CST, > MEMMODEL_RELAXED)) > return false; > > - if (oldval != cmp_reg) > - emit_move_insn (cmp_reg, oldval); > + if (oldval != old_reg) > + emit_move_insn (old_reg, oldval); > > /* Mark this jump predicted not taken. */ > emit_cmp_and_jump_insns (success, const0_rtx, EQ, const0_rtx, That doesn't look correct. expand_compare_and_swap_loop is called from two places and at least in the first case it wants old_reg to contain on success something that is the target that will be returned. While with your patch it might be something different.