https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80080
Dominik Vogt <vogt at linux dot vnet.ibm.com> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |vogt at linux dot vnet.ibm.com --- Comment #3 from Dominik Vogt <vogt at linux dot vnet.ibm.com> --- 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,