21 Star 27 Fork 151

src-openEuler/gcc

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
0145-LoongArch-Fixed-an-issue-with-the-implementation-of-.patch 4.20 KB
一键复制 编辑 原始数据 按行查看 历史
ticat_fp 提交于 2024-10-31 10:33 +08:00 . LoongArch: Sync to upstream
From 44a9ae67e19c0d744bd744cb0e9ae9e0069e40f1 Mon Sep 17 00:00:00 2001
From: Lulu Cheng <chenglulu@loongson.cn>
Date: Tue, 5 Mar 2024 14:43:04 +0800
Subject: [PATCH 145/188] 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<mode>):
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.
---
gcc/config/loongarch/sync.md | 46 ++++++++++++++-----
.../g++.target/loongarch/atomic-cas-int.C | 32 +++++++++++++
2 files changed, 67 insertions(+), 11 deletions(-)
create mode 100644 gcc/testsuite/g++.target/loongarch/atomic-cas-int.C
diff --git a/gcc/config/loongarch/sync.md b/gcc/config/loongarch/sync.md
index 5da5c2780..2e008c487 100644
--- a/gcc/config/loongarch/sync.md
+++ b/gcc/config/loongarch/sync.md
@@ -245,18 +245,42 @@
(clobber (match_scratch:GPR 5 "=&r"))]
""
{
- return "1:\\n\\t"
- "ll.<amo>\\t%0,%1\\n\\t"
- "bne\\t%0,%z2,2f\\n\\t"
- "or%i3\\t%5,$zero,%3\\n\\t"
- "sc.<amo>\\t%5,%1\\n\\t"
- "beqz\\t%5,1b\\n\\t"
- "b\\t3f\\n\\t"
- "2:\\n\\t"
- "%G4\\n\\t"
- "3:\\n\\t";
+ output_asm_insn ("1:", operands);
+ output_asm_insn ("ll.<amo>\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%5,%2,0", operands);
+ output_asm_insn ("bne\t%0,%5,2f", operands);
+ }
+ else
+ output_asm_insn ("bne\t%0,%z2,2f", operands);
+
+ output_asm_insn ("or%i3\t%5,$zero,%3", operands);
+ output_asm_insn ("sc.<amo>\t%5,%1", operands);
+ output_asm_insn ("beqz\t%5,1b", operands);
+ output_asm_insn ("b\t3f", operands);
+ output_asm_insn ("2:", operands);
+ output_asm_insn ("%G4", 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_insn "atomic_cas_value_strong<mode>_amcas"
[(set (match_operand:QHWD 0 "register_operand" "=&r")
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 000000000..830ce4826
--- /dev/null
+++ b/gcc/testsuite/g++.target/loongarch/atomic-cas-int.C
@@ -0,0 +1,32 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+#include <atomic>
+#include <cstdio>
+
+__attribute__ ((noinline)) long
+val_without_const_folding (long val)
+{
+ return val;
+}
+
+int
+main ()
+{
+ int oldval = 0xaa;
+ int newval = 0xbb;
+ std::atomic<int> amo;
+
+ amo.store (oldval);
+
+ long longval = val_without_const_folding (0xff80000000000000 + oldval);
+ oldval = static_cast<int> (longval);
+
+ amo.compare_exchange_strong (oldval, newval);
+
+ if (newval != amo.load (std::memory_order_relaxed))
+ __builtin_abort ();
+
+ return 0;
+}
+
--
2.43.0
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/src-openeuler/gcc.git
git@gitee.com:src-openeuler/gcc.git
src-openeuler
gcc
gcc
master

搜索帮助