https://gcc.gnu.org/g:4d8dc152a8d9b2e8b86dbc524af8c2f7c51f8da1

commit 4d8dc152a8d9b2e8b86dbc524af8c2f7c51f8da1
Author: Austin Law <austink...@gmail.com>
Date:   Wed Sep 3 10:41:17 2025 -0600

    [RISC-V][PR target/121213] Avoid unnecessary sign extension in amoswap 
sequence
    
    This is Austin's work to remove the redundant sign extension seen in 
pr121213.
    
    --
    
    The .w form of amoswap will sign extend its result from 32 to 64 bits, thus 
any
    explicit sign extension insn doing the same is redundant.
    
    This uses Jivan's approach of allocating a DI temporary for an extended 
result
    and using a promoted subreg extraction to get that result into the final
    destination.
    
    Tested with no regressions on riscv32-elf and riscv64-elf and bootstrapped 
on
    the BPI and pioneer systems.
    
            PR target/121213
    gcc/
            * config/riscv/sync.md (amo_atomic_exchange_extended<mode>):
            Separate insn with sign extension for 64 bit targets.
    
    gcc/testsuite
            * gcc.target/riscv/amo/pr121213.c: Remove xfail.
    
    (cherry picked from commit b790606e492d33e0cdb8159e38cb148d3526071b)

Diff:
---
 gcc/config/riscv/sync.md                      | 27 ++++++++++++++++++++++++++-
 gcc/testsuite/gcc.target/riscv/amo/pr121213.c |  2 +-
 2 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/gcc/config/riscv/sync.md b/gcc/config/riscv/sync.md
index e47bb41adcc2..ab6f43066f10 100644
--- a/gcc/config/riscv/sync.md
+++ b/gcc/config/riscv/sync.md
@@ -376,7 +376,19 @@
    (match_operand:SI 3 "const_int_operand")] ;; model
   "TARGET_ZAAMO || TARGET_ZALRSC"
   {
-    if (TARGET_ZAAMO)
+    if (TARGET_ZAAMO && TARGET_64BIT && <MODE>mode == SImode)
+      {
+       rtx t = gen_reg_rtx (DImode);
+       emit_insn (gen_amo_atomic_exchange_extended (t,
+                                                    operands[1],
+                                                    operands[2],
+                                                    operands[3]));
+       t = gen_lowpart (SImode, t);
+       SUBREG_PROMOTED_VAR_P (t) = 1;
+       SUBREG_PROMOTED_SET (t, SRP_SIGNED);
+       emit_move_insn (operands[0], t);
+      }
+    else if (TARGET_ZAAMO)
       emit_insn (gen_amo_atomic_exchange<mode> (operands[0], operands[1],
                                            operands[2], operands[3]));
     else
@@ -398,6 +410,19 @@
   [(set_attr "type" "atomic")
    (set (attr "length") (const_int 4))])
 
+(define_insn "amo_atomic_exchange_extended"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+    (sign_extend:DI (unspec_volatile:SI
+      [(match_operand:SI 1 "memory_operand" "+A")
+       (match_operand:SI 3 "const_int_operand")] ;; model
+      UNSPEC_SYNC_EXCHANGE)))
+   (set (match_dup 1)
+    (match_operand:SI 2 "reg_or_0_operand" "rJ"))]
+  "TARGET_64BIT && TARGET_ZAAMO"
+  "amoswap.w%A3\t%0,%z2,%1"
+  [(set_attr "type" "atomic")
+   (set (attr "length") (const_int 4))])
+
 (define_insn "lrsc_atomic_exchange<mode>"
   [(set (match_operand:GPR 0 "register_operand" "=&r")
        (unspec_volatile:GPR
diff --git a/gcc/testsuite/gcc.target/riscv/amo/pr121213.c 
b/gcc/testsuite/gcc.target/riscv/amo/pr121213.c
index 3b2d694f9914..6dd59c09462e 100644
--- a/gcc/testsuite/gcc.target/riscv/amo/pr121213.c
+++ b/gcc/testsuite/gcc.target/riscv/amo/pr121213.c
@@ -13,5 +13,5 @@ void test1(unsigned* lock) {
 
 /* { dg-final { scan-assembler-not "\tli" } } */
 /* { dg-final { scan-assembler-times "\tamoswap...aq\t\[axt\]\[0-9\],zero," 2 
} } */
-/* { dg-final { scan-assembler-not "\tsext" { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-not "\tsext" } } */

Reply via email to