-
Notifications
You must be signed in to change notification settings - Fork 11.4k
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
Conversation
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.
@llvm/pr-subscribers-backend-risc-v Author: Craig Topper (topperc) ChangesThis 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:
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]
|
There was a problem hiding this 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 |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See #77669
There was a problem hiding this comment.
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
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 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.