From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 7877) id 74A77385DC3A; Sat, 9 Mar 2024 07:26:58 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 74A77385DC3A DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1709969218; bh=FSMRIeDf71YKRcX3RHe0N9yJvcIZdW5/AOFg8qnlyaU=; h=From:To:Subject:Date:From; b=xoisEI1VyNSuZwqohn7tzioayelm0yL/bEnYIkHWewHcM2OSsRYbDGoWX9uABJcfz jh3ajobmD7y+ZKXWcLTL2if6WYZC0q6hJB1sdVBfuDPyxKU+IHC88F3G9wNRC89xEW 3eYIfKj3EajG82QpSz8SUQT88bCM3TS5BrmA1514= MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: LuluCheng To: gcc-cvs@gcc.gnu.org Subject: [gcc r12-10200] LoongArch: Fixed an issue with the implementation of the template atomic_compare_and_swapsi. X-Act-Checkin: gcc X-Git-Author: Lulu Cheng X-Git-Refname: refs/heads/releases/gcc-12 X-Git-Oldrev: 1cd8245d698eb1a5d26a68e898fb23e0b29d8527 X-Git-Newrev: d77ed1d6eb82fb5ef5cd94c06f5c67db753fb7c2 Message-Id: <20240309072658.74A77385DC3A@sourceware.org> Date: Sat, 9 Mar 2024 07:26:58 +0000 (GMT) List-Id: https://gcc.gnu.org/g:d77ed1d6eb82fb5ef5cd94c06f5c67db753fb7c2 commit r12-10200-gd77ed1d6eb82fb5ef5cd94c06f5c67db753fb7c2 Author: Lulu Cheng Date: Tue Mar 5 14:43:04 2024 +0800 LoongArch: Fixed an issue with the implementation of the template atomic_compare_and_swapsi. If the hardware does not support LAMCAS, atomic_compare_and_swapsi needs to be implemented through "ll.w+sc.w". In the implementation of the instruction sequence, it is necessary to determine whether the two registers are equal. Since LoongArch's comparison instructions do not distinguish between 32-bit and 64-bit, the two operand registers that need to be compared are symbolically extended, and one of the operand registers is obtained from memory through the "ll.w" instruction, which can ensure that the symbolic expansion is carried out. However, the value of the other operand register is not guaranteed to be the value of the sign extension. gcc/ChangeLog: * config/loongarch/sync.md (atomic_cas_value_strong): In loongarch64, a sign extension operation is added when operands[2] is a register operand and the mode is SImode. gcc/testsuite/ChangeLog: * g++.target/loongarch/atomic-cas-int.C: New test. (cherry picked from commit 3a3fbec0a4d3f36de58df9ef0b3992a3ffb359c2) Diff: --- gcc/config/loongarch/sync.md | 46 ++++++++++++++++------ .../g++.target/loongarch/atomic-cas-int.C | 32 +++++++++++++++ 2 files changed, 67 insertions(+), 11 deletions(-) diff --git a/gcc/config/loongarch/sync.md b/gcc/config/loongarch/sync.md index b8763b8f9d1..c2f0d33ab21 100644 --- a/gcc/config/loongarch/sync.md +++ b/gcc/config/loongarch/sync.md @@ -129,18 +129,42 @@ (clobber (match_scratch:GPR 6 "=&r"))] "" { - return "1:\\n\\t" - "ll.\\t%0,%1\\n\\t" - "bne\\t%0,%z2,2f\\n\\t" - "or%i3\\t%6,$zero,%3\\n\\t" - "sc.\\t%6,%1\\n\\t" - "beqz\\t%6,1b\\n\\t" - "b\\t3f\\n\\t" - "2:\\n\\t" - "%G5\\n\\t" - "3:\\n\\t"; + output_asm_insn ("1:", operands); + output_asm_insn ("ll.\t%0,%1", operands); + + /* Like the test case atomic-cas-int.C, in loongarch64, O1 and higher, the + return value of the val_without_const_folding will not be truncated and + will be passed directly to the function compare_exchange_strong. + However, the instruction 'bne' does not distinguish between 32-bit and + 64-bit operations. so if the upper 32 bits of the register are not + extended by the 32nd bit symbol, then the comparison may not be valid + here. This will affect the result of the operation. */ + + if (TARGET_64BIT && REG_P (operands[2]) + && GET_MODE (operands[2]) == SImode) + { + output_asm_insn ("addi.w\t%6,%2,0", operands); + output_asm_insn ("bne\t%0,%6,2f", operands); + } + else + output_asm_insn ("bne\t%0,%z2,2f", operands); + + output_asm_insn ("or%i3\t%6,$zero,%3", operands); + output_asm_insn ("sc.\t%6,%1", operands); + output_asm_insn ("beqz\t%6,1b", operands); + output_asm_insn ("b\t3f", operands); + output_asm_insn ("2:", operands); + output_asm_insn ("%G5", operands); + output_asm_insn ("3:", operands); + + return ""; } - [(set (attr "length") (const_int 28))]) + [(set (attr "length") + (if_then_else + (and (match_test "GET_MODE (operands[2]) == SImode") + (match_test "REG_P (operands[2])")) + (const_int 32) + (const_int 28)))]) (define_expand "atomic_compare_and_swap" [(match_operand:SI 0 "register_operand" "") ;; bool output diff --git a/gcc/testsuite/g++.target/loongarch/atomic-cas-int.C b/gcc/testsuite/g++.target/loongarch/atomic-cas-int.C new file mode 100644 index 00000000000..830ce48267a --- /dev/null +++ b/gcc/testsuite/g++.target/loongarch/atomic-cas-int.C @@ -0,0 +1,32 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +#include +#include + +__attribute__ ((noinline)) long +val_without_const_folding (long val) +{ + return val; +} + +int +main () +{ + int oldval = 0xaa; + int newval = 0xbb; + std::atomic amo; + + amo.store (oldval); + + long longval = val_without_const_folding (0xff80000000000000 + oldval); + oldval = static_cast (longval); + + amo.compare_exchange_strong (oldval, newval); + + if (newval != amo.load (std::memory_order_relaxed)) + __builtin_abort (); + + return 0; +} +