Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RISCV] Support isel for Zacas for XLen and i32. #77666

Merged
merged 1 commit into from
Jan 10, 2024

Conversation

topperc
Copy link
Collaborator

@topperc topperc commented Jan 10, 2024

This adds new isel patterns for Zacas that take priority over the pseudoinstructions we use for the A extension.

Support for 2x XLen types will come in a separate patch since they need to be done differently.

This is an alternative to #67918.

This adds new isel patterns for Zacas that take priority over the
pseudoinstructions we use for the A extension.

Support for 2x XLen types will come in a separate patch since they
need to be done differently.
@llvmbot
Copy link
Collaborator

llvmbot commented Jan 10, 2024

@llvm/pr-subscribers-backend-risc-v

Author: Craig Topper (topperc)

Changes

This adds new isel patterns for Zacas that take priority over the pseudoinstructions we use for the A extension.

Support for 2x XLen types will come in a separate patch since they need to be done differently.

This is an alternative to #67918.


Patch is 122.35 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/77666.diff

5 Files Affected:

  • (modified) llvm/lib/Target/RISCV/RISCVFeatures.td (+1)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfoA.td (+8-6)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfoZa.td (+51)
  • (modified) llvm/test/CodeGen/RISCV/atomic-cmpxchg-branch-on-result.ll (+217-57)
  • (modified) llvm/test/CodeGen/RISCV/atomic-cmpxchg.ll (+1700-124)
diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td
index bb7a3291085d43..279509575bb52a 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -736,6 +736,7 @@ def FeatureStdExtZacas
 def HasStdExtZacas : Predicate<"Subtarget->hasStdExtZacas()">,
                                AssemblerPredicate<(all_of FeatureStdExtZacas),
                                "'Zacas' (Atomic Compare-And-Swap Instructions)">;
+def NoStdExtZacas : Predicate<"!Subtarget->hasStdExtZacas()">;
 
 //===----------------------------------------------------------------------===//
 // Vendor extensions
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoA.td b/llvm/lib/Target/RISCV/RISCVInstrInfoA.td
index 1ff5189260a9c7..44552c00c62e55 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoA.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoA.td
@@ -333,11 +333,17 @@ multiclass PseudoCmpXchgPat<string Op, Pseudo CmpXchgInst,
             (CmpXchgInst GPR:$addr, GPR:$cmp, GPR:$new, 7)>;
 }
 
-let Predicates = [HasStdExtA] in {
-
+let Predicates = [HasStdExtA, NoStdExtZacas] in {
 def PseudoCmpXchg32 : PseudoCmpXchg;
 defm : PseudoCmpXchgPat<"atomic_cmp_swap_32", PseudoCmpXchg32>;
+}
+
+let Predicates = [HasStdExtA, NoStdExtZacas, IsRV64] in {
+def PseudoCmpXchg64 : PseudoCmpXchg;
+defm : PseudoCmpXchgPat<"atomic_cmp_swap_64", PseudoCmpXchg64, i64>;
+}
 
+let Predicates = [HasStdExtA] in {
 def PseudoMaskedCmpXchg32
     : Pseudo<(outs GPR:$res, GPR:$scratch),
              (ins GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask,
@@ -356,10 +362,6 @@ def : Pat<(int_riscv_masked_cmpxchg_i32
 } // Predicates = [HasStdExtA]
 
 let Predicates = [HasStdExtA, IsRV64] in {
-
-def PseudoCmpXchg64 : PseudoCmpXchg;
-defm : PseudoCmpXchgPat<"atomic_cmp_swap_64", PseudoCmpXchg64, i64>;
-
 def : Pat<(int_riscv_masked_cmpxchg_i64
             GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask, timm:$ordering),
           (PseudoMaskedCmpXchg32
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZa.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZa.td
index ea8046d119d042..ffcdd001074938 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoZa.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZa.td
@@ -67,6 +67,57 @@ defm AMOCAS_D_RV64 : AMO_cas_aq_rl<0b00101, 0b011, "amocas.d", GPR>;
 defm AMOCAS_Q : AMO_cas_aq_rl<0b00101, 0b100, "amocas.q", GPRPairRV64>;
 } // Predicates = [HasStdExtZacas, IsRV64]
 
+multiclass AMOCASPat<string AtomicOp, string BaseInst, ValueType vt = XLenVT,
+                     list<Predicate> ExtraPreds = []> {
+  let Predicates = !listconcat([HasStdExtZacas, NotHasStdExtZtso], ExtraPreds) in {
+    def : Pat<(!cast<PatFrag>(AtomicOp#"_monotonic") (vt GPR:$addr),
+                                                     (vt GPR:$cmp),
+                                                     (vt GPR:$new)),
+              (!cast<RVInst>(BaseInst) GPR:$cmp, GPR:$addr, GPR:$new)>;
+    def : Pat<(!cast<PatFrag>(AtomicOp#"_acquire") (vt GPR:$addr),
+                                                   (vt GPR:$cmp),
+                                                   (vt GPR:$new)),
+              (!cast<RVInst>(BaseInst#"_AQ") GPR:$cmp, GPR:$addr, GPR:$new)>;
+    def : Pat<(!cast<PatFrag>(AtomicOp#"_release") (vt GPR:$addr),
+                                                   (vt GPR:$cmp),
+                                                   (vt GPR:$new)),
+              (!cast<RVInst>(BaseInst#"_RL") GPR:$cmp, GPR:$addr, GPR:$new)>;
+    def : Pat<(!cast<PatFrag>(AtomicOp#"_acq_rel") (vt GPR:$addr),
+                                                   (vt GPR:$cmp),
+                                                   (vt GPR:$new)),
+              (!cast<RVInst>(BaseInst#"_AQ_RL") GPR:$cmp, GPR:$addr, GPR:$new)>;
+    def : Pat<(!cast<PatFrag>(AtomicOp#"_seq_cst") (vt GPR:$addr),
+                                                   (vt GPR:$cmp),
+                                                   (vt GPR:$new)),
+              (!cast<RVInst>(BaseInst#"_AQ_RL") GPR:$cmp, GPR:$addr, GPR:$new)>;
+  } // Predicates = !listconcat([HasStdExtZacas, NotHasStdExtZtso], ExtraPreds)
+  let Predicates = !listconcat([HasStdExtZacas, HasStdExtZtso], ExtraPreds) in {
+    def : Pat<(!cast<PatFrag>(AtomicOp#"_monotonic") (vt GPR:$addr),
+                                                     (vt GPR:$cmp),
+                                                     (vt GPR:$new)),
+              (!cast<RVInst>(BaseInst) GPR:$cmp, GPR:$addr, GPR:$new)>;
+    def : Pat<(!cast<PatFrag>(AtomicOp#"_acquire") (vt GPR:$addr),
+                                                   (vt GPR:$cmp),
+                                                   (vt GPR:$new)),
+              (!cast<RVInst>(BaseInst) GPR:$cmp, GPR:$addr, GPR:$new)>;
+    def : Pat<(!cast<PatFrag>(AtomicOp#"_release") (vt GPR:$addr),
+                                                   (vt GPR:$cmp),
+                                                   (vt GPR:$new)),
+              (!cast<RVInst>(BaseInst) GPR:$cmp, GPR:$addr, GPR:$new)>;
+    def : Pat<(!cast<PatFrag>(AtomicOp#"_acq_rel") (vt GPR:$addr),
+                                                   (vt GPR:$cmp),
+                                                   (vt GPR:$new)),
+              (!cast<RVInst>(BaseInst) GPR:$cmp, GPR:$addr, GPR:$new)>;
+    def : Pat<(!cast<PatFrag>(AtomicOp#"_seq_cst") (vt GPR:$addr),
+                                                   (vt GPR:$cmp),
+                                                   (vt GPR:$new)),
+              (!cast<RVInst>(BaseInst) GPR:$cmp, GPR:$addr, GPR:$new)>;
+  } // Predicates = !listconcat([HasStdExtZacas, HasStdExtZtso], ExtraPreds)
+}
+
+defm : AMOCASPat<"atomic_cmp_swap_32", "AMOCAS_W">;
+defm : AMOCASPat<"atomic_cmp_swap_64", "AMOCAS_D_RV64", i64, [IsRV64]>;
+
 //===----------------------------------------------------------------------===//
 // Zawrs (Wait-on-Reservation-Set)
 //===----------------------------------------------------------------------===//
diff --git a/llvm/test/CodeGen/RISCV/atomic-cmpxchg-branch-on-result.ll b/llvm/test/CodeGen/RISCV/atomic-cmpxchg-branch-on-result.ll
index 651f58d324422f..a8477cc550fe6a 100644
--- a/llvm/test/CodeGen/RISCV/atomic-cmpxchg-branch-on-result.ll
+++ b/llvm/test/CodeGen/RISCV/atomic-cmpxchg-branch-on-result.ll
@@ -1,30 +1,44 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
 ; RUN: llc -mtriple=riscv32 -mattr=+a -verify-machineinstrs < %s \
-; RUN:   | FileCheck -check-prefixes=CHECK,RV32IA %s
+; RUN:   | FileCheck -check-prefixes=NOZACAS,RV32IA %s
+; RUN: llc -mtriple=riscv32 -mattr=+a,+experimental-zacas -verify-machineinstrs < %s \
+; RUN:   | FileCheck -check-prefixes=ZACAS,RV32IA-ZACAS %s
 ; RUN: llc -mtriple=riscv64 -mattr=+a -verify-machineinstrs < %s \
-; RUN:   | FileCheck -check-prefixes=CHECK,RV64IA %s
+; RUN:   | FileCheck -check-prefixes=NOZACAS,RV64IA %s
+; RUN: llc -mtriple=riscv64 -mattr=+a,+experimental-zacas -verify-machineinstrs < %s \
+; RUN:   | FileCheck -check-prefixes=ZACAS,RV64IA-ZACAS %s
 
 ; Test cmpxchg followed by a branch on the cmpxchg success value to see if the
 ; branch is folded into the cmpxchg expansion.
 
 define void @cmpxchg_and_branch1(ptr %ptr, i32 signext %cmp, i32 signext %val) nounwind {
-; CHECK-LABEL: cmpxchg_and_branch1:
-; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:  .LBB0_1: # %do_cmpxchg
-; CHECK-NEXT:    # =>This Loop Header: Depth=1
-; CHECK-NEXT:    # Child Loop BB0_3 Depth 2
-; CHECK-NEXT:  .LBB0_3: # %do_cmpxchg
-; CHECK-NEXT:    # Parent Loop BB0_1 Depth=1
-; CHECK-NEXT:    # => This Inner Loop Header: Depth=2
-; CHECK-NEXT:    lr.w.aqrl a3, (a0)
-; CHECK-NEXT:    bne a3, a1, .LBB0_1
-; CHECK-NEXT:  # %bb.4: # %do_cmpxchg
-; CHECK-NEXT:    # in Loop: Header=BB0_3 Depth=2
-; CHECK-NEXT:    sc.w.rl a4, a2, (a0)
-; CHECK-NEXT:    bnez a4, .LBB0_3
-; CHECK-NEXT:  # %bb.5: # %do_cmpxchg
-; CHECK-NEXT:  # %bb.2: # %exit
-; CHECK-NEXT:    ret
+; NOZACAS-LABEL: cmpxchg_and_branch1:
+; NOZACAS:       # %bb.0: # %entry
+; NOZACAS-NEXT:  .LBB0_1: # %do_cmpxchg
+; NOZACAS-NEXT:    # =>This Loop Header: Depth=1
+; NOZACAS-NEXT:    # Child Loop BB0_3 Depth 2
+; NOZACAS-NEXT:  .LBB0_3: # %do_cmpxchg
+; NOZACAS-NEXT:    # Parent Loop BB0_1 Depth=1
+; NOZACAS-NEXT:    # => This Inner Loop Header: Depth=2
+; NOZACAS-NEXT:    lr.w.aqrl a3, (a0)
+; NOZACAS-NEXT:    bne a3, a1, .LBB0_1
+; NOZACAS-NEXT:  # %bb.4: # %do_cmpxchg
+; NOZACAS-NEXT:    # in Loop: Header=BB0_3 Depth=2
+; NOZACAS-NEXT:    sc.w.rl a4, a2, (a0)
+; NOZACAS-NEXT:    bnez a4, .LBB0_3
+; NOZACAS-NEXT:  # %bb.5: # %do_cmpxchg
+; NOZACAS-NEXT:  # %bb.2: # %exit
+; NOZACAS-NEXT:    ret
+;
+; ZACAS-LABEL: cmpxchg_and_branch1:
+; ZACAS:       # %bb.0: # %entry
+; ZACAS-NEXT:  .LBB0_1: # %do_cmpxchg
+; ZACAS-NEXT:    # =>This Inner Loop Header: Depth=1
+; ZACAS-NEXT:    mv a3, a1
+; ZACAS-NEXT:    amocas.w.aqrl a3, a2, (a0)
+; ZACAS-NEXT:    bne a3, a1, .LBB0_1
+; ZACAS-NEXT:  # %bb.2: # %exit
+; ZACAS-NEXT:    ret
 entry:
   br label %do_cmpxchg
 do_cmpxchg:
@@ -36,25 +50,35 @@ exit:
 }
 
 define void @cmpxchg_and_branch2(ptr %ptr, i32 signext %cmp, i32 signext %val) nounwind {
-; CHECK-LABEL: cmpxchg_and_branch2:
-; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:  .LBB1_1: # %do_cmpxchg
-; CHECK-NEXT:    # =>This Loop Header: Depth=1
-; CHECK-NEXT:    # Child Loop BB1_3 Depth 2
-; CHECK-NEXT:  .LBB1_3: # %do_cmpxchg
-; CHECK-NEXT:    # Parent Loop BB1_1 Depth=1
-; CHECK-NEXT:    # => This Inner Loop Header: Depth=2
-; CHECK-NEXT:    lr.w.aqrl a3, (a0)
-; CHECK-NEXT:    bne a3, a1, .LBB1_5
-; CHECK-NEXT:  # %bb.4: # %do_cmpxchg
-; CHECK-NEXT:    # in Loop: Header=BB1_3 Depth=2
-; CHECK-NEXT:    sc.w.rl a4, a2, (a0)
-; CHECK-NEXT:    bnez a4, .LBB1_3
-; CHECK-NEXT:  .LBB1_5: # %do_cmpxchg
-; CHECK-NEXT:    # in Loop: Header=BB1_1 Depth=1
-; CHECK-NEXT:    beq a3, a1, .LBB1_1
-; CHECK-NEXT:  # %bb.2: # %exit
-; CHECK-NEXT:    ret
+; NOZACAS-LABEL: cmpxchg_and_branch2:
+; NOZACAS:       # %bb.0: # %entry
+; NOZACAS-NEXT:  .LBB1_1: # %do_cmpxchg
+; NOZACAS-NEXT:    # =>This Loop Header: Depth=1
+; NOZACAS-NEXT:    # Child Loop BB1_3 Depth 2
+; NOZACAS-NEXT:  .LBB1_3: # %do_cmpxchg
+; NOZACAS-NEXT:    # Parent Loop BB1_1 Depth=1
+; NOZACAS-NEXT:    # => This Inner Loop Header: Depth=2
+; NOZACAS-NEXT:    lr.w.aqrl a3, (a0)
+; NOZACAS-NEXT:    bne a3, a1, .LBB1_5
+; NOZACAS-NEXT:  # %bb.4: # %do_cmpxchg
+; NOZACAS-NEXT:    # in Loop: Header=BB1_3 Depth=2
+; NOZACAS-NEXT:    sc.w.rl a4, a2, (a0)
+; NOZACAS-NEXT:    bnez a4, .LBB1_3
+; NOZACAS-NEXT:  .LBB1_5: # %do_cmpxchg
+; NOZACAS-NEXT:    # in Loop: Header=BB1_1 Depth=1
+; NOZACAS-NEXT:    beq a3, a1, .LBB1_1
+; NOZACAS-NEXT:  # %bb.2: # %exit
+; NOZACAS-NEXT:    ret
+;
+; ZACAS-LABEL: cmpxchg_and_branch2:
+; ZACAS:       # %bb.0: # %entry
+; ZACAS-NEXT:  .LBB1_1: # %do_cmpxchg
+; ZACAS-NEXT:    # =>This Inner Loop Header: Depth=1
+; ZACAS-NEXT:    mv a3, a1
+; ZACAS-NEXT:    amocas.w.aqrl a3, a2, (a0)
+; ZACAS-NEXT:    beq a3, a1, .LBB1_1
+; ZACAS-NEXT:  # %bb.2: # %exit
+; ZACAS-NEXT:    ret
 entry:
   br label %do_cmpxchg
 do_cmpxchg:
@@ -96,6 +120,36 @@ define void @cmpxchg_masked_and_branch1(ptr %ptr, i8 signext %cmp, i8 signext %v
 ; RV32IA-NEXT:  # %bb.2: # %exit
 ; RV32IA-NEXT:    ret
 ;
+; RV32IA-ZACAS-LABEL: cmpxchg_masked_and_branch1:
+; RV32IA-ZACAS:       # %bb.0: # %entry
+; RV32IA-ZACAS-NEXT:    andi a3, a0, -4
+; RV32IA-ZACAS-NEXT:    slli a4, a0, 3
+; RV32IA-ZACAS-NEXT:    li a0, 255
+; RV32IA-ZACAS-NEXT:    sll a0, a0, a4
+; RV32IA-ZACAS-NEXT:    andi a1, a1, 255
+; RV32IA-ZACAS-NEXT:    sll a1, a1, a4
+; RV32IA-ZACAS-NEXT:    andi a2, a2, 255
+; RV32IA-ZACAS-NEXT:    sll a2, a2, a4
+; RV32IA-ZACAS-NEXT:  .LBB2_1: # %do_cmpxchg
+; RV32IA-ZACAS-NEXT:    # =>This Loop Header: Depth=1
+; RV32IA-ZACAS-NEXT:    # Child Loop BB2_3 Depth 2
+; RV32IA-ZACAS-NEXT:  .LBB2_3: # %do_cmpxchg
+; RV32IA-ZACAS-NEXT:    # Parent Loop BB2_1 Depth=1
+; RV32IA-ZACAS-NEXT:    # => This Inner Loop Header: Depth=2
+; RV32IA-ZACAS-NEXT:    lr.w.aqrl a4, (a3)
+; RV32IA-ZACAS-NEXT:    and a5, a4, a0
+; RV32IA-ZACAS-NEXT:    bne a5, a1, .LBB2_1
+; RV32IA-ZACAS-NEXT:  # %bb.4: # %do_cmpxchg
+; RV32IA-ZACAS-NEXT:    # in Loop: Header=BB2_3 Depth=2
+; RV32IA-ZACAS-NEXT:    xor a5, a4, a2
+; RV32IA-ZACAS-NEXT:    and a5, a5, a0
+; RV32IA-ZACAS-NEXT:    xor a5, a4, a5
+; RV32IA-ZACAS-NEXT:    sc.w.rl a5, a5, (a3)
+; RV32IA-ZACAS-NEXT:    bnez a5, .LBB2_3
+; RV32IA-ZACAS-NEXT:  # %bb.5: # %do_cmpxchg
+; RV32IA-ZACAS-NEXT:  # %bb.2: # %exit
+; RV32IA-ZACAS-NEXT:    ret
+;
 ; RV64IA-LABEL: cmpxchg_masked_and_branch1:
 ; RV64IA:       # %bb.0: # %entry
 ; RV64IA-NEXT:    andi a3, a0, -4
@@ -125,6 +179,36 @@ define void @cmpxchg_masked_and_branch1(ptr %ptr, i8 signext %cmp, i8 signext %v
 ; RV64IA-NEXT:  # %bb.5: # %do_cmpxchg
 ; RV64IA-NEXT:  # %bb.2: # %exit
 ; RV64IA-NEXT:    ret
+;
+; RV64IA-ZACAS-LABEL: cmpxchg_masked_and_branch1:
+; RV64IA-ZACAS:       # %bb.0: # %entry
+; RV64IA-ZACAS-NEXT:    andi a3, a0, -4
+; RV64IA-ZACAS-NEXT:    slli a4, a0, 3
+; RV64IA-ZACAS-NEXT:    li a0, 255
+; RV64IA-ZACAS-NEXT:    sllw a0, a0, a4
+; RV64IA-ZACAS-NEXT:    andi a1, a1, 255
+; RV64IA-ZACAS-NEXT:    sllw a1, a1, a4
+; RV64IA-ZACAS-NEXT:    andi a2, a2, 255
+; RV64IA-ZACAS-NEXT:    sllw a2, a2, a4
+; RV64IA-ZACAS-NEXT:  .LBB2_1: # %do_cmpxchg
+; RV64IA-ZACAS-NEXT:    # =>This Loop Header: Depth=1
+; RV64IA-ZACAS-NEXT:    # Child Loop BB2_3 Depth 2
+; RV64IA-ZACAS-NEXT:  .LBB2_3: # %do_cmpxchg
+; RV64IA-ZACAS-NEXT:    # Parent Loop BB2_1 Depth=1
+; RV64IA-ZACAS-NEXT:    # => This Inner Loop Header: Depth=2
+; RV64IA-ZACAS-NEXT:    lr.w.aqrl a4, (a3)
+; RV64IA-ZACAS-NEXT:    and a5, a4, a0
+; RV64IA-ZACAS-NEXT:    bne a5, a1, .LBB2_1
+; RV64IA-ZACAS-NEXT:  # %bb.4: # %do_cmpxchg
+; RV64IA-ZACAS-NEXT:    # in Loop: Header=BB2_3 Depth=2
+; RV64IA-ZACAS-NEXT:    xor a5, a4, a2
+; RV64IA-ZACAS-NEXT:    and a5, a5, a0
+; RV64IA-ZACAS-NEXT:    xor a5, a4, a5
+; RV64IA-ZACAS-NEXT:    sc.w.rl a5, a5, (a3)
+; RV64IA-ZACAS-NEXT:    bnez a5, .LBB2_3
+; RV64IA-ZACAS-NEXT:  # %bb.5: # %do_cmpxchg
+; RV64IA-ZACAS-NEXT:  # %bb.2: # %exit
+; RV64IA-ZACAS-NEXT:    ret
 entry:
   br label %do_cmpxchg
 do_cmpxchg:
@@ -169,6 +253,39 @@ define void @cmpxchg_masked_and_branch2(ptr %ptr, i8 signext %cmp, i8 signext %v
 ; RV32IA-NEXT:  # %bb.2: # %exit
 ; RV32IA-NEXT:    ret
 ;
+; RV32IA-ZACAS-LABEL: cmpxchg_masked_and_branch2:
+; RV32IA-ZACAS:       # %bb.0: # %entry
+; RV32IA-ZACAS-NEXT:    andi a3, a0, -4
+; RV32IA-ZACAS-NEXT:    slli a4, a0, 3
+; RV32IA-ZACAS-NEXT:    li a0, 255
+; RV32IA-ZACAS-NEXT:    sll a0, a0, a4
+; RV32IA-ZACAS-NEXT:    andi a1, a1, 255
+; RV32IA-ZACAS-NEXT:    sll a1, a1, a4
+; RV32IA-ZACAS-NEXT:    andi a2, a2, 255
+; RV32IA-ZACAS-NEXT:    sll a2, a2, a4
+; RV32IA-ZACAS-NEXT:  .LBB3_1: # %do_cmpxchg
+; RV32IA-ZACAS-NEXT:    # =>This Loop Header: Depth=1
+; RV32IA-ZACAS-NEXT:    # Child Loop BB3_3 Depth 2
+; RV32IA-ZACAS-NEXT:  .LBB3_3: # %do_cmpxchg
+; RV32IA-ZACAS-NEXT:    # Parent Loop BB3_1 Depth=1
+; RV32IA-ZACAS-NEXT:    # => This Inner Loop Header: Depth=2
+; RV32IA-ZACAS-NEXT:    lr.w.aqrl a4, (a3)
+; RV32IA-ZACAS-NEXT:    and a5, a4, a0
+; RV32IA-ZACAS-NEXT:    bne a5, a1, .LBB3_5
+; RV32IA-ZACAS-NEXT:  # %bb.4: # %do_cmpxchg
+; RV32IA-ZACAS-NEXT:    # in Loop: Header=BB3_3 Depth=2
+; RV32IA-ZACAS-NEXT:    xor a5, a4, a2
+; RV32IA-ZACAS-NEXT:    and a5, a5, a0
+; RV32IA-ZACAS-NEXT:    xor a5, a4, a5
+; RV32IA-ZACAS-NEXT:    sc.w.rl a5, a5, (a3)
+; RV32IA-ZACAS-NEXT:    bnez a5, .LBB3_3
+; RV32IA-ZACAS-NEXT:  .LBB3_5: # %do_cmpxchg
+; RV32IA-ZACAS-NEXT:    # in Loop: Header=BB3_1 Depth=1
+; RV32IA-ZACAS-NEXT:    and a4, a4, a0
+; RV32IA-ZACAS-NEXT:    beq a1, a4, .LBB3_1
+; RV32IA-ZACAS-NEXT:  # %bb.2: # %exit
+; RV32IA-ZACAS-NEXT:    ret
+;
 ; RV64IA-LABEL: cmpxchg_masked_and_branch2:
 ; RV64IA:       # %bb.0: # %entry
 ; RV64IA-NEXT:    andi a3, a0, -4
@@ -201,6 +318,39 @@ define void @cmpxchg_masked_and_branch2(ptr %ptr, i8 signext %cmp, i8 signext %v
 ; RV64IA-NEXT:    beq a1, a4, .LBB3_1
 ; RV64IA-NEXT:  # %bb.2: # %exit
 ; RV64IA-NEXT:    ret
+;
+; RV64IA-ZACAS-LABEL: cmpxchg_masked_and_branch2:
+; RV64IA-ZACAS:       # %bb.0: # %entry
+; RV64IA-ZACAS-NEXT:    andi a3, a0, -4
+; RV64IA-ZACAS-NEXT:    slli a4, a0, 3
+; RV64IA-ZACAS-NEXT:    li a0, 255
+; RV64IA-ZACAS-NEXT:    sllw a0, a0, a4
+; RV64IA-ZACAS-NEXT:    andi a1, a1, 255
+; RV64IA-ZACAS-NEXT:    sllw a1, a1, a4
+; RV64IA-ZACAS-NEXT:    andi a2, a2, 255
+; RV64IA-ZACAS-NEXT:    sllw a2, a2, a4
+; RV64IA-ZACAS-NEXT:  .LBB3_1: # %do_cmpxchg
+; RV64IA-ZACAS-NEXT:    # =>This Loop Header: Depth=1
+; RV64IA-ZACAS-NEXT:    # Child Loop BB3_3 Depth 2
+; RV64IA-ZACAS-NEXT:  .LBB3_3: # %do_cmpxchg
+; RV64IA-ZACAS-NEXT:    # Parent Loop BB3_1 Depth=1
+; RV64IA-ZACAS-NEXT:    # => This Inner Loop Header: Depth=2
+; RV64IA-ZACAS-NEXT:    lr.w.aqrl a4, (a3)
+; RV64IA-ZACAS-NEXT:    and a5, a4, a0
+; RV64IA-ZACAS-NEXT:    bne a5, a1, .LBB3_5
+; RV64IA-ZACAS-NEXT:  # %bb.4: # %do_cmpxchg
+; RV64IA-ZACAS-NEXT:    # in Loop: Header=BB3_3 Depth=2
+; RV64IA-ZACAS-NEXT:    xor a5, a4, a2
+; RV64IA-ZACAS-NEXT:    and a5, a5, a0
+; RV64IA-ZACAS-NEXT:    xor a5, a4, a5
+; RV64IA-ZACAS-NEXT:    sc.w.rl a5, a5, (a3)
+; RV64IA-ZACAS-NEXT:    bnez a5, .LBB3_3
+; RV64IA-ZACAS-NEXT:  .LBB3_5: # %do_cmpxchg
+; RV64IA-ZACAS-NEXT:    # in Loop: Header=BB3_1 Depth=1
+; RV64IA-ZACAS-NEXT:    and a4, a4, a0
+; RV64IA-ZACAS-NEXT:    beq a1, a4, .LBB3_1
+; RV64IA-ZACAS-NEXT:  # %bb.2: # %exit
+; RV64IA-ZACAS-NEXT:    ret
 entry:
   br label %do_cmpxchg
 do_cmpxchg:
@@ -212,25 +362,35 @@ exit:
 }
 
 define void @cmpxchg_and_irrelevant_branch(ptr %ptr, i32 signext %cmp, i32 signext %val, i1 zeroext %bool) nounwind {
-; CHECK-LABEL: cmpxchg_and_irrelevant_branch:
-; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:  .LBB4_1: # %do_cmpxchg
-; CHECK-NEXT:    # =>This Loop Header: Depth=1
-; CHECK-NEXT:    # Child Loop BB4_3 Depth 2
-; CHECK-NEXT:  .LBB4_3: # %do_cmpxchg
-; CHECK-NEXT:    # Parent Loop BB4_1 Depth=1
-; CHECK-NEXT:    # => This Inner Loop Header: Depth=2
-; CHECK-NEXT:    lr.w.aqrl a4, (a0)
-; CHECK-NEXT:    bne a4, a1, .LBB4_5
-; CHECK-NEXT:  # %bb.4: # %do_cmpxchg
-; CHECK-NEXT:    # in Loop: Header=BB4_3 Depth=2
-; CHECK-NEXT:    sc.w.rl a5, a2, (a0)
-; CHECK-NEXT:    bnez a5, .LBB4_3
-; CHECK-NEXT:  .LBB4_5: # %do_cmpxchg
-; CHECK-NEXT:    # in Loop: Header=BB4_1 Depth=1
-; CHECK-NEXT:    beqz a3, .LBB4_1
-; CHECK-NEXT:  # %bb.2: # %exit
-; CHECK-NEXT:    ret
+; NOZACAS-LABEL: cmpxchg_and_irrelevant_branch:
+; NOZACAS:       # %bb.0: # %entry
+; NOZACAS-NEXT:  .LBB4_1: # %do_cmpxchg
+; NOZACAS-NEXT:    # =>This Loop Header: Depth=1
+; NOZACAS-NEXT:    # Child Loop BB4_3 Depth 2
+; NOZACAS-NEXT:  .LBB4_3: # %do_cmpxchg
+; NOZACAS-NEXT:    # Parent Loop BB4_1 Depth=1
+; NOZACAS-NEXT:    # => This Inner Loop Header: Depth=2
+; NOZACAS-NEXT:    lr.w.aqrl a4, (a0)
+; NOZACAS-NEXT:    bne a4, a1, .LBB4_5
+; NOZACAS-NEXT:  # %bb.4: # %do_cmpxchg
+; NOZACAS-NEXT:    # in Loop: Header=BB4_3 Depth=2
+; NOZACAS-NEXT:    sc.w.rl a5, a2, (a0)
+; NOZACAS-NEXT:    bnez a5, .LBB4_3
+; NOZACAS-NEXT:  .LBB4_5: # %do_cmpxchg
+; NOZACAS-NEXT:    # in Loop: Header=BB4_1 Depth=1
+; NOZACAS-NEXT:    beqz a3, .LBB4_1
+; NOZACAS-NEXT:  # %bb.2: # %exit
+; NOZACAS-NEXT:    ret
+;
+; ZACAS-LABEL: cmpxchg_and_irrelevant_branch:
+; ZACAS:       # %bb.0: # %entry
+; ZACAS-NEXT:  .LBB4_1: # %do_cmpxchg
+; ZACAS-NEXT:    # =>This Inner Loop Header: Depth=1
+; ZACAS-NEXT:    mv a4, a1
+; ZACAS-NEXT:    amocas.w.aqrl a4, a2, (a0)
+; ZACAS-NEXT:    beqz a3, .LBB4_1
+; ZACAS-NEXT:  # %bb.2: # %exit
+; ZACAS-NEXT:    ret
 entry:
   br label %do_cmpxchg
 do_cmpxchg:
diff --git a/llvm/test/CodeGen/RISCV/atomic-cmpxchg.ll b/llvm/test/CodeGen/RISCV/atomic-cmpxchg.ll
index 46ed01b11584f9..b3c9224646ed98 100644
--- a/llvm/test/CodeGen/RISCV/atomic-cmpxchg.ll
+++ b/llvm/test/CodeGen/RISCV/atomic-cmpxchg.ll
@@ -3,14 +3,22 @@
 ; RUN:   | FileCheck -check-prefix=RV32I %s
 ; RUN: llc -mtriple=riscv32 -mattr=+a -verify-machineinstrs < %s \
 ; RUN:   | FileCheck -check-prefixes=RV32IA,RV32IA-WMO %s
+; RUN: llc -mtriple=riscv32 -mattr=+a,+experimental-zacas -verify-machineinstrs < %s \
+; RUN:   | FileCheck -check-prefixes=RV32IA,RV32IA-ZACAS,RV32IA-WMO-ZACAS %s
 ; RUN: llc -mtriple=riscv32 -mattr=+a,+experimental-ztso -verify-machineinstrs < %s \
 ; RUN:   | FileCheck -check-prefixes=RV32IA,RV32IA-TSO %s
+; RUN: ...
[truncated]

Copy link
Member

@dtcxzyw dtcxzyw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks!

;
; RV64IA-ZACAS-LABEL: cmpxchg_i32_monotonic_monotonic:
; RV64IA-ZACAS: # %bb.0:
; RV64IA-ZACAS-NEXT: sext.w a1, a1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the sext.w required? Can we mark amocas.w as a W user/producer?

Copy link
Collaborator Author

@topperc topperc Jan 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See #77669

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for fixing my typo

@topperc topperc merged commit 0a1b066 into llvm:main Jan 10, 2024
4 of 5 checks passed
@topperc topperc deleted the pr/zacas-xlen branch January 10, 2024 20:00
justinfargnoli pushed a commit to justinfargnoli/llvm-project that referenced this pull request Jan 28, 2024
This adds new isel patterns for Zacas that take priority over the
pseudoinstructions we use for the A extension.

Support for 2x XLen types will come in a separate patch since they need
to be done differently.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants