Maxim Kuvyrkov <[email protected]> writes:
> diff --git a/gcc/config/mips/sync.md b/gcc/config/mips/sync.md
> index 604aefa..ac953b5 100644
> --- a/gcc/config/mips/sync.md
> +++ b/gcc/config/mips/sync.md
> @@ -607,10 +607,32 @@
> (match_operand:GPR 1 "memory_operand")
> (match_operand:GPR 2 "arith_operand")
> (match_operand:SI 3 "const_int_operand")]
> - "GENERATE_LL_SC"
> + "GENERATE_LL_SC || ISA_HAS_SWAP"
> {
> + if (!ISA_HAS_SWAP)
> emit_insn (gen_atomic_exchange<mode>_llsc (operands[0], operands[1],
> operands[2], operands[3]));
> + else
Please swap this round so that the ISA_HAS_SWAP stuff comes first.
The LLSC code then remains the fallback if new variations are added.
> + {
> + rtx addr;
> +
> + gcc_assert (MEM_P (operands[1]));
> + addr = XEXP (operands[1], 0);
> + if (!REG_P (addr) && can_create_pseudo_p ())
> + /* Workaround a reload bug that hits (lo_sum (reg) (symbol_ref))
> + addresses. Spill the address to a register upfront to simplify
> + reload's job. */
> + addr = force_reg (GET_MODE (addr), addr);
If there's a reload bug here, let's fix it. But...
> @@ -631,15 +653,52 @@
> (set_attr "sync_insn1_op2" "2")
> (set_attr "sync_memmodel" "3")])
>
> +;; Swap/ldadd instruction accepts only register, no offset, for the address.
["SWAP accepts only register addresses."]
> +;; Therefore, we spell out the MEM verbatim and constrain its address to "d".
> +;; XLP issues implicit sync for swap/ldadd, so no need for an explicit one.
...we should instead define a memory predicate/constraint pair that only
allows register addresses. Then the expand code would be:
if (!mem_reg_operand (operands[1], <MODE>mode))
{
addr = force_reg (Pmode, XEXP (operands[1], 0));
operands[1] = replace_equiv_address (operands[1], addr);
}
> +(define_insn "atomic_exchange<GPR:mode>_swap_<P:mode>"
> + [(set (match_operand:GPR 0 "register_operand" "=d")
> + (unspec_volatile:GPR
> + [(mem:GPR (match_operand:P 1 "address_operand" "d"))]
> + UNSPEC_ATOMIC_EXCHANGE))
> + (set (mem:GPR (match_dup 1))
> + (unspec_volatile:GPR [(match_operand:GPR 2 "arith_operand" "0")]
Should be "register_operand", with a force_reg in the expander.
Same kind of comments for LDADD.
Richard