[llvm] [clang] [RISCV] Add experimental support of Zaamo and Zalrsc (PR #77424)

Wang Pengcheng via cfe-commits cfe-commits at lists.llvm.org
Tue Jan 9 00:44:30 PST 2024


https://github.com/wangpc-pp created https://github.com/llvm/llvm-project/pull/77424

`A` extension has been split into two parts: Zaamo (Atomic Memory
Operations) and Zalrsc (Load-Reserved/Store-Conditional). See also
https://github.com/riscv/riscv-zaamo-zalrsc.

This patch adds the basic compiler support.

Tests for `A` extension are reused.


>From a16ff19b7666060db74bebd4cb7e7132776285a7 Mon Sep 17 00:00:00 2001
From: wangpc <wangpengcheng.pp at bytedance.com>
Date: Tue, 9 Jan 2024 16:12:40 +0800
Subject: [PATCH] [RISCV] Add experimental support of Zaamo and Zalrsc

`A` extension has been split into two parts: Zaamo (Atomic Memory
Operations) and Zalrsc (Load-Reserved/Store-Conditional). See also
https://github.com/riscv/riscv-zaamo-zalrsc.

This patch adds the basic compiler support.

Tests for `A` extension are reused.
---
 clang/lib/Basic/Targets/RISCV.cpp             |   2 +-
 .../test/Preprocessor/riscv-target-features.c |  19 +++
 llvm/docs/RISCVUsage.rst                      |   2 +
 llvm/lib/Support/RISCVISAInfo.cpp             |   2 +
 llvm/lib/Target/RISCV/RISCVFeatures.td        |  26 ++-
 llvm/lib/Target/RISCV/RISCVISelLowering.cpp   |   7 +-
 llvm/lib/Target/RISCV/RISCVInstrInfoA.td      |  32 ++--
 .../RISCV/atomic-cmpxchg-branch-on-result.ll  |   4 +
 .../test/CodeGen/RISCV/atomic-cmpxchg-flag.ll |   2 +
 llvm/test/CodeGen/RISCV/atomic-cmpxchg.ll     |   8 +
 llvm/test/CodeGen/RISCV/atomic-rmw-discard.ll |   4 +
 llvm/test/CodeGen/RISCV/atomic-rmw-sub.ll     |   4 +
 llvm/test/CodeGen/RISCV/atomic-rmw.ll         |   8 +
 llvm/test/CodeGen/RISCV/atomic-signext.ll     |   4 +
 .../CodeGen/RISCV/atomicrmw-uinc-udec-wrap.ll |   4 +
 llvm/test/CodeGen/RISCV/attributes.ll         |   8 +
 llvm/test/MC/RISCV/rv32i-invalid.s            |   2 +-
 llvm/test/MC/RISCV/rv32zaamo-invalid.s        |  11 ++
 llvm/test/MC/RISCV/rv32zaamo-valid.s          | 122 ++++++++++++++
 llvm/test/MC/RISCV/rv32zalrsc-invalid.s       |   7 +
 llvm/test/MC/RISCV/rv32zalrsc-valid.s         |  36 ++++
 llvm/test/MC/RISCV/rv64zaamo-invalid.s        |  11 ++
 llvm/test/MC/RISCV/rv64zaamo-valid.s          | 157 ++++++++++++++++++
 llvm/test/MC/RISCV/rv64zalrsc-invalid.s       |   7 +
 llvm/test/MC/RISCV/rv64zalrsc-valid.s         |  42 +++++
 llvm/unittests/Support/RISCVISAInfoTest.cpp   |   2 +
 26 files changed, 515 insertions(+), 18 deletions(-)
 create mode 100644 llvm/test/MC/RISCV/rv32zaamo-invalid.s
 create mode 100644 llvm/test/MC/RISCV/rv32zaamo-valid.s
 create mode 100644 llvm/test/MC/RISCV/rv32zalrsc-invalid.s
 create mode 100644 llvm/test/MC/RISCV/rv32zalrsc-valid.s
 create mode 100644 llvm/test/MC/RISCV/rv64zaamo-invalid.s
 create mode 100644 llvm/test/MC/RISCV/rv64zaamo-valid.s
 create mode 100644 llvm/test/MC/RISCV/rv64zalrsc-invalid.s
 create mode 100644 llvm/test/MC/RISCV/rv64zalrsc-valid.s

diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp
index daaa8639ae8358..7aff435b715ca1 100644
--- a/clang/lib/Basic/Targets/RISCV.cpp
+++ b/clang/lib/Basic/Targets/RISCV.cpp
@@ -176,7 +176,7 @@ void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts,
     Builder.defineMacro("__riscv_muldiv");
   }
 
-  if (ISAInfo->hasExtension("a")) {
+  if (ISAInfo->hasExtension("a") || ISAInfo->hasExtension("zaamo")) {
     Builder.defineMacro("__riscv_atomic");
     Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
     Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
diff --git a/clang/test/Preprocessor/riscv-target-features.c b/clang/test/Preprocessor/riscv-target-features.c
index 02d8d34116f804..69ba912880f800 100644
--- a/clang/test/Preprocessor/riscv-target-features.c
+++ b/clang/test/Preprocessor/riscv-target-features.c
@@ -114,7 +114,9 @@
 
 // CHECK-NOT: __riscv_smaia {{.*$}}
 // CHECK-NOT: __riscv_ssaia {{.*$}}
+// CHECK-NOT: __riscv_zaamo {{.*$}}
 // CHECK-NOT: __riscv_zacas {{.*$}}
+// CHECK-NOT: __riscv_zalrsc {{.*$}}
 // CHECK-NOT: __riscv_zfa {{.*$}}
 // CHECK-NOT: __riscv_zfbfmin {{.*$}}
 // CHECK-NOT: __riscv_zicfilp {{.*$}}
@@ -1025,6 +1027,15 @@
 // RUN: -o - | FileCheck --check-prefix=CHECK-SSAIA-EXT %s
 // CHECK-SSAIA-EXT: __riscv_ssaia  1000000{{$}}
 
+// RUN: %clang --target=riscv32 -menable-experimental-extensions \
+// RUN: -march=rv32i_zaamo0p1 -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-ZAAMO-EXT %s
+// RUN: %clang --target=riscv64 -menable-experimental-extensions \
+// RUN: -march=rv64i_zaamo0p1 -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-ZAAMO-EXT %s
+// CHECK-ZAAMO-EXT: __riscv_atomic 1
+// CHECK-ZAAMO-EXT: __riscv_zaamo 1000{{$}}
+
 // RUN: %clang --target=riscv32 -menable-experimental-extensions \
 // RUN: -march=rv32i_zacas1p0 -x c -E -dM %s \
 // RUN: -o - | FileCheck --check-prefix=CHECK-ZACAS-EXT %s
@@ -1033,6 +1044,14 @@
 // RUN: -o - | FileCheck --check-prefix=CHECK-ZACAS-EXT %s
 // CHECK-ZACAS-EXT: __riscv_zacas 1000000{{$}}
 
+// RUN: %clang --target=riscv32 -menable-experimental-extensions \
+// RUN: -march=rv32i_zalrsc0p1 -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-ZALRSC-EXT %s
+// RUN: %clang --target=riscv64 -menable-experimental-extensions \
+// RUN: -march=rv64i_zalrsc0p1 -x c -E -dM %s \
+// RUN: -o - | FileCheck --check-prefix=CHECK-ZALRSC-EXT %s
+// CHECK-ZALRSC-EXT: __riscv_zalrsc 1000{{$}}
+
 // RUN: %clang --target=riscv32-unknown-linux-gnu \
 // RUN: -march=rv32izfa -x c -E -dM %s \
 // RUN: -o - | FileCheck --check-prefix=CHECK-ZFA-EXT %s
diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst
index 99c7146825f5ee..1eb1823faebac1 100644
--- a/llvm/docs/RISCVUsage.rst
+++ b/llvm/docs/RISCVUsage.rst
@@ -96,6 +96,8 @@ on support follow.
      ``Svnapot``      Assembly Support
      ``Svpbmt``       Supported
      ``V``            Supported
+     ``Zaamo``        Supported
+     ``Zalrsc``       Supported
      ``Zawrs``        Assembly Support
      ``Zba``          Supported
      ``Zbb``          Supported
diff --git a/llvm/lib/Support/RISCVISAInfo.cpp b/llvm/lib/Support/RISCVISAInfo.cpp
index 70f531e40b90e6..51bef21c324ce5 100644
--- a/llvm/lib/Support/RISCVISAInfo.cpp
+++ b/llvm/lib/Support/RISCVISAInfo.cpp
@@ -188,7 +188,9 @@ static const RISCVSupportedExtension SupportedExtensions[] = {
 
 // NOTE: This table should be sorted alphabetically by extension name.
 static const RISCVSupportedExtension SupportedExperimentalExtensions[] = {
+    {"zaamo", RISCVExtensionVersion{0, 1}},
     {"zacas", RISCVExtensionVersion{1, 0}},
+    {"zalrsc", RISCVExtensionVersion{0, 1}},
 
     {"zcmop", RISCVExtensionVersion{0, 2}},
 
diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td
index bb7a3291085d43..69ca7161254408 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -41,6 +41,30 @@ def HasStdExtA : Predicate<"Subtarget->hasStdExtA()">,
                            AssemblerPredicate<(all_of FeatureStdExtA),
                            "'A' (Atomic Instructions)">;
 
+def FeatureStdExtZaamo
+    : SubtargetFeature<"experimental-zaamo", "HasStdExtZaamo", "true",
+                       "'Zaamo' (Atomic Memory Operations)">;
+def HasStdExtZaamo : Predicate<"Subtarget->hasStdExtZaamo()">,
+                               AssemblerPredicate<(all_of FeatureStdExtZaamo),
+                               "'Zaamo' (Atomic Memory Operations)">;
+def HasStdExtAOrZaamo
+    : Predicate<"Subtarget->hasStdExtA() || Subtarget->hasStdExtZaamo()">,
+                AssemblerPredicate<(any_of FeatureStdExtA, FeatureStdExtZaamo),
+                                   "'A' (Atomic Instructions) or "
+                                   "'Zaamo' (Atomic Memory Operations)">;
+
+def FeatureStdExtZalrsc
+    : SubtargetFeature<"experimental-zalrsc", "HasStdExtZalrsc", "true",
+                       "'Zalrsc' (Load-Reserved/Store-Conditional)">;
+def HasStdExtZalrsc : Predicate<"Subtarget->hasStdExtZalrsc()">,
+                                AssemblerPredicate<(all_of FeatureStdExtZalrsc),
+                                "'Zalrsc' (Load-Reserved/Store-Conditional)">;
+def HasStdExtAOrZalrsc
+    : Predicate<"Subtarget->hasStdExtA() || Subtarget->hasStdExtZalrsc()">,
+                AssemblerPredicate<(any_of FeatureStdExtA, FeatureStdExtZalrsc),
+                                   "'A' (Atomic Instructions) or "
+                                   "'Zalrsc' (Load-Reserved/Store-Conditional)">;
+
 def FeatureStdExtF
     : SubtargetFeature<"f", "HasStdExtF", "true",
                        "'F' (Single-Precision Floating-Point)",
@@ -1044,7 +1068,7 @@ def FeatureForcedAtomics : SubtargetFeature<
     "forced-atomics", "HasForcedAtomics", "true",
     "Assume that lock-free native-width atomics are available">;
 def HasAtomicLdSt
-    : Predicate<"Subtarget->hasStdExtA() || Subtarget->hasForcedAtomics()">;
+    : Predicate<"Subtarget->hasStdExtA() || Subtarget->hasStdExtZalrsc() || Subtarget->hasForcedAtomics()">;
 
 def FeatureTaggedGlobals : SubtargetFeature<"tagged-globals",
     "AllowTaggedGlobals",
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index a5b33e8e293a17..3f3ad7ba496381 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -628,7 +628,8 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
     setOperationAction(ISD::PREFETCH, MVT::Other, Legal);
   }
 
-  if (Subtarget.hasStdExtA()) {
+  if (Subtarget.hasStdExtA() || Subtarget.hasStdExtZaamo() ||
+      Subtarget.hasStdExtZalrsc()) {
     setMaxAtomicSizeInBitsSupported(Subtarget.getXLen());
     setMinCmpXchgSizeInBits(32);
   } else if (Subtarget.hasForcedAtomics()) {
@@ -1334,7 +1335,7 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
     }
   }
 
-  if (Subtarget.hasStdExtA()) {
+  if (Subtarget.hasStdExtA() || Subtarget.hasStdExtZaamo()) {
     setOperationAction(ISD::ATOMIC_LOAD_SUB, XLenVT, Expand);
     if (RV64LegalI32 && Subtarget.is64Bit())
       setOperationAction(ISD::ATOMIC_LOAD_SUB, MVT::i32, Expand);
@@ -16215,7 +16216,7 @@ unsigned RISCVTargetLowering::ComputeNumSignBitsForTargetNode(
       // 32 for both 64 and 32.
       assert(Subtarget.getXLen() == 64);
       assert(getMinCmpXchgSizeInBits() == 32);
-      assert(Subtarget.hasStdExtA());
+      assert(Subtarget.hasStdExtA() || Subtarget.hasStdExtZalrsc());
       return 33;
     }
     break;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoA.td b/llvm/lib/Target/RISCV/RISCVInstrInfoA.td
index 4d0567e41abcb7..8d2283d2a306b4 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoA.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoA.td
@@ -47,10 +47,14 @@ multiclass AMO_rr_aq_rl<bits<5> funct5, bits<3> funct3, string opcodestr> {
 // Instructions
 //===----------------------------------------------------------------------===//
 
-let Predicates = [HasStdExtA], IsSignExtendingOpW = 1 in {
+let IsSignExtendingOpW = 1 in {
+let Predicates = [HasStdExtAOrZalrsc] in {
 defm LR_W       : LR_r_aq_rl<0b010, "lr.w">, Sched<[WriteAtomicLDW, ReadAtomicLDW]>;
 defm SC_W       : AMO_rr_aq_rl<0b00011, 0b010, "sc.w">,
                   Sched<[WriteAtomicSTW, ReadAtomicSTW, ReadAtomicSTW]>;
+} // Predicates = [HasStdExtAOrZalrsc]
+
+let Predicates = [HasStdExtAOrZaamo] in {
 defm AMOSWAP_W  : AMO_rr_aq_rl<0b00001, 0b010, "amoswap.w">,
                   Sched<[WriteAtomicW, ReadAtomicWA, ReadAtomicWD]>;
 defm AMOADD_W   : AMO_rr_aq_rl<0b00000, 0b010, "amoadd.w">,
@@ -69,12 +73,16 @@ defm AMOMINU_W  : AMO_rr_aq_rl<0b11000, 0b010, "amominu.w">,
                   Sched<[WriteAtomicW, ReadAtomicWA, ReadAtomicWD]>;
 defm AMOMAXU_W  : AMO_rr_aq_rl<0b11100, 0b010, "amomaxu.w">,
                   Sched<[WriteAtomicW, ReadAtomicWA, ReadAtomicWD]>;
-} // Predicates = [HasStdExtA]
+} // Predicates = [HasStdExtAOrZaamo]
+} // IsSignExtendingOpW = 1
 
-let Predicates = [HasStdExtA, IsRV64] in {
+let Predicates = [HasStdExtAOrZalrsc, IsRV64] in {
 defm LR_D       : LR_r_aq_rl<0b011, "lr.d">, Sched<[WriteAtomicLDD, ReadAtomicLDD]>;
 defm SC_D       : AMO_rr_aq_rl<0b00011, 0b011, "sc.d">,
                   Sched<[WriteAtomicSTD, ReadAtomicSTD, ReadAtomicSTD]>;
+} // Predicates = [HasStdExtAOrZalrsc, IsRV64]
+
+let Predicates = [HasStdExtAOrZaamo, IsRV64] in {
 defm AMOSWAP_D  : AMO_rr_aq_rl<0b00001, 0b011, "amoswap.d">,
                   Sched<[WriteAtomicD, ReadAtomicDA, ReadAtomicDD]>;
 defm AMOADD_D   : AMO_rr_aq_rl<0b00000, 0b011, "amoadd.d">,
@@ -93,7 +101,7 @@ defm AMOMINU_D  : AMO_rr_aq_rl<0b11000, 0b011, "amominu.d">,
                   Sched<[WriteAtomicD, ReadAtomicDA, ReadAtomicDD]>;
 defm AMOMAXU_D  : AMO_rr_aq_rl<0b11100, 0b011, "amomaxu.d">,
                   Sched<[WriteAtomicD, ReadAtomicDA, ReadAtomicDD]>;
-} // Predicates = [HasStdExtA, IsRV64]
+} // Predicates = [HasStdExtAOrZaamo, IsRV64]
 
 //===----------------------------------------------------------------------===//
 // Pseudo-instructions and codegen patterns
@@ -121,7 +129,7 @@ let Predicates = [HasAtomicLdSt, IsRV64] in {
 
 multiclass AMOPat<string AtomicOp, string BaseInst, ValueType vt = XLenVT,
                   list<Predicate> ExtraPreds = []> {
-let Predicates = !listconcat([HasStdExtA, NotHasStdExtZtso], ExtraPreds) in {
+let Predicates = !listconcat([HasStdExtAOrZaamo, NotHasStdExtZtso], ExtraPreds) in {
   def : PatGprGpr<!cast<PatFrag>(AtomicOp#"_monotonic"),
                   !cast<RVInst>(BaseInst), vt>;
   def : PatGprGpr<!cast<PatFrag>(AtomicOp#"_acquire"),
@@ -133,7 +141,7 @@ let Predicates = !listconcat([HasStdExtA, NotHasStdExtZtso], ExtraPreds) in {
   def : PatGprGpr<!cast<PatFrag>(AtomicOp#"_seq_cst"),
                   !cast<RVInst>(BaseInst#"_AQ_RL"), vt>;
 }
-let Predicates = !listconcat([HasStdExtA, HasStdExtZtso], ExtraPreds) in {
+let Predicates = !listconcat([HasStdExtAOrZaamo, HasStdExtZtso], ExtraPreds) in {
   def : PatGprGpr<!cast<PatFrag>(AtomicOp#"_monotonic"),
                   !cast<RVInst>(BaseInst), vt>;
   def : PatGprGpr<!cast<PatFrag>(AtomicOp#"_acquire"),
@@ -157,7 +165,7 @@ defm : AMOPat<"atomic_load_min_32", "AMOMIN_W">;
 defm : AMOPat<"atomic_load_umax_32", "AMOMAXU_W">;
 defm : AMOPat<"atomic_load_umin_32", "AMOMINU_W">;
 
-let Predicates = [HasStdExtA] in {
+let Predicates = [HasStdExtAOrZalrsc] in {
 
 /// Pseudo AMOs
 
@@ -304,7 +312,7 @@ def : Pat<(int_riscv_masked_cmpxchg_i32
           (PseudoMaskedCmpXchg32
             GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask, timm:$ordering)>;
 
-} // Predicates = [HasStdExtA]
+} // Predicates = [HasStdExtAOrZalrsc]
 
 defm : AMOPat<"atomic_swap_64", "AMOSWAP_D", i64, [IsRV64]>;
 defm : AMOPat<"atomic_load_add_64", "AMOADD_D", i64, [IsRV64]>;
@@ -316,7 +324,7 @@ defm : AMOPat<"atomic_load_min_64", "AMOMIN_D", i64, [IsRV64]>;
 defm : AMOPat<"atomic_load_umax_64", "AMOMAXU_D", i64, [IsRV64]>;
 defm : AMOPat<"atomic_load_umin_64", "AMOMINU_D", i64, [IsRV64]>;
 
-let Predicates = [HasStdExtA, IsRV64] in {
+let Predicates = [HasStdExtAOrZalrsc, IsRV64] in {
 
 /// 64-bit pseudo AMOs
 
@@ -361,7 +369,7 @@ def : Pat<(int_riscv_masked_cmpxchg_i64
             GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask, timm:$ordering),
           (PseudoMaskedCmpXchg32
             GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask, timm:$ordering)>;
-} // Predicates = [HasStdExtA, IsRV64]
+} // Predicates = [HasStdExtAOrZalrsc, IsRV64]
 
 //===----------------------------------------------------------------------===//
 // Experimental RV64 i32 legalization patterns.
@@ -372,7 +380,7 @@ class PatGprGprA<SDPatternOperator OpNode, RVInst Inst, ValueType vt>
 
 multiclass AMOPat2<string AtomicOp, string BaseInst, ValueType vt = XLenVT,
                    list<Predicate> ExtraPreds = []> {
-let Predicates = !listconcat([HasStdExtA, NotHasStdExtZtso], ExtraPreds) in {
+let Predicates = !listconcat([HasStdExtAOrZaamo, NotHasStdExtZtso], ExtraPreds) in {
   def : PatGprGprA<!cast<PatFrag>(AtomicOp#"_monotonic"),
                    !cast<RVInst>(BaseInst), vt>;
   def : PatGprGprA<!cast<PatFrag>(AtomicOp#"_acquire"),
@@ -384,7 +392,7 @@ let Predicates = !listconcat([HasStdExtA, NotHasStdExtZtso], ExtraPreds) in {
   def : PatGprGprA<!cast<PatFrag>(AtomicOp#"_seq_cst"),
                    !cast<RVInst>(BaseInst#"_AQ_RL"), vt>;
 }
-let Predicates = !listconcat([HasStdExtA, HasStdExtZtso], ExtraPreds) in {
+let Predicates = !listconcat([HasStdExtAOrZaamo, HasStdExtZtso], ExtraPreds) in {
   def : PatGprGprA<!cast<PatFrag>(AtomicOp#"_monotonic"),
                    !cast<RVInst>(BaseInst), vt>;
   def : PatGprGprA<!cast<PatFrag>(AtomicOp#"_acquire"),
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..86a6dd5df5e316 100644
--- a/llvm/test/CodeGen/RISCV/atomic-cmpxchg-branch-on-result.ll
+++ b/llvm/test/CodeGen/RISCV/atomic-cmpxchg-branch-on-result.ll
@@ -3,6 +3,10 @@
 ; RUN:   | FileCheck -check-prefixes=CHECK,RV32IA %s
 ; RUN: llc -mtriple=riscv64 -mattr=+a -verify-machineinstrs < %s \
 ; RUN:   | FileCheck -check-prefixes=CHECK,RV64IA %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-zalrsc -verify-machineinstrs < %s \
+; RUN:   | FileCheck -check-prefixes=CHECK,RV32IA %s
+; RUN: llc -mtriple=riscv64 -mattr=+experimental-zalrsc -verify-machineinstrs < %s \
+; RUN:   | FileCheck -check-prefixes=CHECK,RV64IA %s
 
 ; Test cmpxchg followed by a branch on the cmpxchg success value to see if the
 ; branch is folded into the cmpxchg expansion.
diff --git a/llvm/test/CodeGen/RISCV/atomic-cmpxchg-flag.ll b/llvm/test/CodeGen/RISCV/atomic-cmpxchg-flag.ll
index f25571b5cf2531..9934b1ed0cdc62 100644
--- a/llvm/test/CodeGen/RISCV/atomic-cmpxchg-flag.ll
+++ b/llvm/test/CodeGen/RISCV/atomic-cmpxchg-flag.ll
@@ -1,6 +1,8 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
 ; RUN: llc -mtriple=riscv64 -mattr=+a -verify-machineinstrs < %s \
 ; RUN:   | FileCheck -check-prefix=RV64IA %s
+; RUN: llc -mtriple=riscv64 -mattr=+experimental-zalrsc -verify-machineinstrs < %s \
+; RUN:   | FileCheck -check-prefixes=RV64IA %s
 
 ; This test ensures that the output of the 'lr.w' instruction is sign-extended.
 ; Previously, the default zero-extension was being used and 'cmp' parameter
diff --git a/llvm/test/CodeGen/RISCV/atomic-cmpxchg.ll b/llvm/test/CodeGen/RISCV/atomic-cmpxchg.ll
index 46ed01b11584f9..b56f956cb22c81 100644
--- a/llvm/test/CodeGen/RISCV/atomic-cmpxchg.ll
+++ b/llvm/test/CodeGen/RISCV/atomic-cmpxchg.ll
@@ -5,12 +5,20 @@
 ; RUN:   | FileCheck -check-prefixes=RV32IA,RV32IA-WMO %s
 ; RUN: llc -mtriple=riscv32 -mattr=+a,+experimental-ztso -verify-machineinstrs < %s \
 ; RUN:   | FileCheck -check-prefixes=RV32IA,RV32IA-TSO %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-zalrsc -verify-machineinstrs < %s \
+; RUN:   | FileCheck -check-prefixes=RV32IA,RV32IA-WMO %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-zalrsc,+experimental-ztso -verify-machineinstrs < %s \
+; RUN:   | FileCheck -check-prefixes=RV32IA,RV32IA-TSO %s
 ; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
 ; RUN:   | FileCheck -check-prefix=RV64I %s
 ; RUN: llc -mtriple=riscv64 -mattr=+a -verify-machineinstrs < %s \
 ; RUN:   | FileCheck -check-prefixes=RV64IA,RV64IA-WMO %s
 ; RUN: llc -mtriple=riscv64 -mattr=+a,+experimental-ztso -verify-machineinstrs < %s \
 ; RUN:   | FileCheck -check-prefixes=RV64IA,RV64IA-TSO %s
+; RUN: llc -mtriple=riscv64 -mattr=+experimental-zalrsc -verify-machineinstrs < %s \
+; RUN:   | FileCheck -check-prefixes=RV64IA,RV64IA-WMO %s
+; RUN: llc -mtriple=riscv64 -mattr=+experimental-zalrsc,+experimental-ztso -verify-machineinstrs < %s \
+; RUN:   | FileCheck -check-prefixes=RV64IA,RV64IA-TSO %s
 
 define void @cmpxchg_i8_monotonic_monotonic(ptr %ptr, i8 %cmp, i8 %val) nounwind {
 ; RV32I-LABEL: cmpxchg_i8_monotonic_monotonic:
diff --git a/llvm/test/CodeGen/RISCV/atomic-rmw-discard.ll b/llvm/test/CodeGen/RISCV/atomic-rmw-discard.ll
index 8d3fc96109262e..d3741c53c5818b 100644
--- a/llvm/test/CodeGen/RISCV/atomic-rmw-discard.ll
+++ b/llvm/test/CodeGen/RISCV/atomic-rmw-discard.ll
@@ -3,6 +3,10 @@
 ; RUN:   | FileCheck -check-prefixes=RV32 %s
 ; RUN: llc -O3 -mtriple=riscv64 -mattr=+a -verify-machineinstrs < %s \
 ; RUN:   | FileCheck -check-prefixes=RV64 %s
+; RUN: llc -O3 -mtriple=riscv32 -mattr=+experimental-zaamo -verify-machineinstrs < %s \
+; RUN:   | FileCheck -check-prefixes=RV32 %s
+; RUN: llc -O3 -mtriple=riscv64 -mattr=+experimental-zaamo -verify-machineinstrs < %s \
+; RUN:   | FileCheck -check-prefixes=RV64 %s
 
 define void @amoswap_w_discard(ptr %a, i32 %b) nounwind {
 ; RV32-LABEL: amoswap_w_discard:
diff --git a/llvm/test/CodeGen/RISCV/atomic-rmw-sub.ll b/llvm/test/CodeGen/RISCV/atomic-rmw-sub.ll
index 4dafd6a08d973b..016d5fd21ffa6f 100644
--- a/llvm/test/CodeGen/RISCV/atomic-rmw-sub.ll
+++ b/llvm/test/CodeGen/RISCV/atomic-rmw-sub.ll
@@ -3,10 +3,14 @@
 ; RUN:   | FileCheck -check-prefix=RV32I %s
 ; RUN: llc -mtriple=riscv32 -mattr=+a -verify-machineinstrs < %s \
 ; RUN:   | FileCheck -check-prefixes=RV32IA %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-zaamo -verify-machineinstrs < %s \
+; RUN:   | FileCheck -check-prefixes=RV32IA %s
 ; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
 ; RUN:   | FileCheck -check-prefix=RV64I %s
 ; RUN: llc -mtriple=riscv64 -mattr=+a -verify-machineinstrs < %s \
 ; RUN:   | FileCheck -check-prefixes=RV64IA %s
+; RUN: llc -mtriple=riscv64 -mattr=+experimental-zaamo -verify-machineinstrs < %s \
+; RUN:   | FileCheck -check-prefixes=RV64IA %s
 
 define i32 @atomicrmw_sub_i32_constant(ptr %a) nounwind {
 ; RV32I-LABEL: atomicrmw_sub_i32_constant:
diff --git a/llvm/test/CodeGen/RISCV/atomic-rmw.ll b/llvm/test/CodeGen/RISCV/atomic-rmw.ll
index d4c067b7b8a40c..2e850e6f0bb43d 100644
--- a/llvm/test/CodeGen/RISCV/atomic-rmw.ll
+++ b/llvm/test/CodeGen/RISCV/atomic-rmw.ll
@@ -5,12 +5,20 @@
 ; RUN:   | FileCheck -check-prefixes=RV32IA,RV32IA-WMO %s
 ; RUN: llc -mtriple=riscv32 -mattr=+a,+experimental-ztso -verify-machineinstrs < %s \
 ; RUN:   | FileCheck -check-prefixes=RV32IA,RV32IA-TSO %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-zaamo,+experimental-zalrsc -verify-machineinstrs < %s \
+; RUN:   | FileCheck -check-prefixes=RV32IA,RV32IA-WMO %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-zaamo,+experimental-zalrsc,+experimental-ztso -verify-machineinstrs < %s \
+; RUN:   | FileCheck -check-prefixes=RV32IA,RV32IA-TSO %s
 ; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
 ; RUN:   | FileCheck -check-prefix=RV64I %s
 ; RUN: llc -mtriple=riscv64 -mattr=+a -verify-machineinstrs < %s \
 ; RUN:   | FileCheck -check-prefixes=RV64IA,RV64IA-WMO %s
 ; RUN: llc -mtriple=riscv64 -mattr=+a,+experimental-ztso -verify-machineinstrs < %s \
 ; RUN:   | FileCheck -check-prefixes=RV64IA,RV64IA-TSO %s
+; RUN: llc -mtriple=riscv64 -mattr=+experimental-zaamo,+experimental-zalrsc -verify-machineinstrs < %s \
+; RUN:   | FileCheck -check-prefixes=RV64IA,RV64IA-WMO %s
+; RUN: llc -mtriple=riscv64 -mattr=+experimental-zaamo,+experimental-zalrsc,+experimental-ztso -verify-machineinstrs < %s \
+; RUN:   | FileCheck -check-prefixes=RV64IA,RV64IA-TSO %s
 
 define i8 @atomicrmw_xchg_i8_monotonic(ptr %a, i8 %b) nounwind {
 ; RV32I-LABEL: atomicrmw_xchg_i8_monotonic:
diff --git a/llvm/test/CodeGen/RISCV/atomic-signext.ll b/llvm/test/CodeGen/RISCV/atomic-signext.ll
index ef0c27f3280105..7c5e1cb489f825 100644
--- a/llvm/test/CodeGen/RISCV/atomic-signext.ll
+++ b/llvm/test/CodeGen/RISCV/atomic-signext.ll
@@ -3,10 +3,14 @@
 ; RUN:   | FileCheck -check-prefix=RV32I %s
 ; RUN: llc -mtriple=riscv32 -mattr=+a -verify-machineinstrs < %s \
 ; RUN:   | FileCheck -check-prefix=RV32IA %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-zaamo,+experimental-zalrsc -verify-machineinstrs < %s \
+; RUN:   | FileCheck -check-prefix=RV32IA %s
 ; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
 ; RUN:   | FileCheck -check-prefix=RV64I %s
 ; RUN: llc -mtriple=riscv64 -mattr=+a -verify-machineinstrs < %s \
 ; RUN:   | FileCheck -check-prefix=RV64IA %s
+; RUN: llc -mtriple=riscv64 -mattr=+experimental-zaamo,+experimental-zalrsc -verify-machineinstrs < %s \
+; RUN:   | FileCheck -check-prefix=RV64IA %s
 
 define signext i8 @atomic_load_i8_unordered(ptr %a) nounwind {
 ; RV32I-LABEL: atomic_load_i8_unordered:
diff --git a/llvm/test/CodeGen/RISCV/atomicrmw-uinc-udec-wrap.ll b/llvm/test/CodeGen/RISCV/atomicrmw-uinc-udec-wrap.ll
index aa962d68fc5285..0e37194a21c296 100644
--- a/llvm/test/CodeGen/RISCV/atomicrmw-uinc-udec-wrap.ll
+++ b/llvm/test/CodeGen/RISCV/atomicrmw-uinc-udec-wrap.ll
@@ -3,12 +3,16 @@
 ; RUN:   | FileCheck -check-prefix=RV32I %s
 ; RUN: llc -mtriple=riscv32 -mattr=+a -verify-machineinstrs < %s \
 ; RUN:   | FileCheck -check-prefix=RV32IA %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-zalrsc -verify-machineinstrs < %s \
+; RUN:   | FileCheck -check-prefix=RV32IA %s
 ; RUN: llc -mtriple=riscv32 -mattr=+a,+experimental-ztso -verify-machineinstrs < %s \
 ; RUN:   | FileCheck -check-prefix=RV32IA %s
 ; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
 ; RUN:   | FileCheck -check-prefix=RV64I %s
 ; RUN: llc -mtriple=riscv64 -mattr=+a -verify-machineinstrs < %s \
 ; RUN:   | FileCheck -check-prefix=RV64IA %s
+; RUN: llc -mtriple=riscv64 -mattr=+experimental-zalrsc -verify-machineinstrs < %s \
+; RUN:   | FileCheck -check-prefix=RV64IA %s
 ; RUN: llc -mtriple=riscv64 -mattr=+a,+experimental-ztso -verify-machineinstrs < %s \
 ; RUN:   | FileCheck -check-prefix=RV64IA %s
 
diff --git a/llvm/test/CodeGen/RISCV/attributes.ll b/llvm/test/CodeGen/RISCV/attributes.ll
index 9a6e78c09ad8c3..b0cf8df11f3c0d 100644
--- a/llvm/test/CodeGen/RISCV/attributes.ll
+++ b/llvm/test/CodeGen/RISCV/attributes.ll
@@ -92,7 +92,9 @@
 ; RUN: llc -mtriple=riscv32 -mattr=+experimental-zfbfmin %s -o - | FileCheck --check-prefixes=CHECK,RV32ZFBFMIN %s
 ; RUN: llc -mtriple=riscv32 -mattr=+experimental-zvfbfmin %s -o - | FileCheck --check-prefixes=CHECK,RV32ZVFBFMIN %s
 ; RUN: llc -mtriple=riscv32 -mattr=+experimental-zvfbfwma %s -o - | FileCheck --check-prefixes=CHECK,RV32ZVFBFWMA %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-zaamo %s -o - | FileCheck --check-prefix=RV32ZAAMO %s
 ; RUN: llc -mtriple=riscv32 -mattr=+experimental-zacas %s -o - | FileCheck --check-prefix=RV32ZACAS %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-zalrsc %s -o - | FileCheck --check-prefix=RV32ZALRSC %s
 ; RUN: llc -mtriple=riscv32 -mattr=+experimental-zicfilp %s -o - | FileCheck --check-prefix=RV32ZICFILP %s
 
 ; RUN: llc -mtriple=riscv64 %s -o - | FileCheck %s
@@ -186,7 +188,9 @@
 ; RUN: llc -mtriple=riscv64 -mattr=+experimental-zfbfmin %s -o - | FileCheck --check-prefixes=CHECK,RV64ZFBFMIN %s
 ; RUN: llc -mtriple=riscv64 -mattr=+experimental-zvfbfmin %s -o - | FileCheck --check-prefixes=CHECK,RV64ZVFBFMIN %s
 ; RUN: llc -mtriple=riscv64 -mattr=+experimental-zvfbfwma %s -o - | FileCheck --check-prefixes=CHECK,RV64ZVFBFWMA %s
+; RUN: llc -mtriple=riscv64 -mattr=+experimental-zaamo %s -o - | FileCheck --check-prefix=RV64ZAAMO %s
 ; RUN: llc -mtriple=riscv64 -mattr=+experimental-zacas %s -o - | FileCheck --check-prefix=RV64ZACAS %s
+; RUN: llc -mtriple=riscv64 -mattr=+experimental-zalrsc %s -o - | FileCheck --check-prefix=RV64ZALRSC %s
 ; RUN: llc -mtriple=riscv64 -mattr=+experimental-zicfilp %s -o - | FileCheck --check-prefix=RV64ZICFILP %s
 
 ; CHECK: .attribute 4, 16
@@ -282,7 +286,9 @@
 ; RV32ZFBFMIN: .attribute 5, "rv32i2p1_f2p2_zicsr2p0_zfbfmin0p8"
 ; RV32ZVFBFMIN: .attribute 5, "rv32i2p1_f2p2_zicsr2p0_zve32f1p0_zve32x1p0_zvfbfmin0p8_zvl32b1p0"
 ; RV32ZVFBFWMA: .attribute 5, "rv32i2p1_f2p2_zicsr2p0_zfbfmin0p8_zve32f1p0_zve32x1p0_zvfbfmin0p8_zvfbfwma0p8_zvl32b1p0"
+; RV32ZAAMO: .attribute 5, "rv32i2p1_zaamo0p1"
 ; RV32ZACAS: .attribute 5, "rv32i2p1_a2p1_zacas1p0"
+; RV32ZALRSC: .attribute 5, "rv32i2p1_zalrsc0p1"
 ; RV32ZICFILP: .attribute 5, "rv32i2p1_zicfilp0p4"
 
 ; RV64M: .attribute 5, "rv64i2p1_m2p0"
@@ -375,7 +381,9 @@
 ; RV64ZFBFMIN: .attribute 5, "rv64i2p1_f2p2_zicsr2p0_zfbfmin0p8"
 ; RV64ZVFBFMIN: .attribute 5, "rv64i2p1_f2p2_zicsr2p0_zve32f1p0_zve32x1p0_zvfbfmin0p8_zvl32b1p0"
 ; RV64ZVFBFWMA: .attribute 5, "rv64i2p1_f2p2_zicsr2p0_zfbfmin0p8_zve32f1p0_zve32x1p0_zvfbfmin0p8_zvfbfwma0p8_zvl32b1p0"
+; RV64ZAAMO: .attribute 5, "rv64i2p1_zaamo0p1"
 ; RV64ZACAS: .attribute 5, "rv64i2p1_a2p1_zacas1p0"
+; RV64ZALRSC: .attribute 5, "rv64i2p1_zalrsc0p1"
 ; RV64ZICFILP: .attribute 5, "rv64i2p1_zicfilp0p4"
 
 define i32 @addi(i32 %a) {
diff --git a/llvm/test/MC/RISCV/rv32i-invalid.s b/llvm/test/MC/RISCV/rv32i-invalid.s
index c5e0657b838094..25a419cbefd4d0 100644
--- a/llvm/test/MC/RISCV/rv32i-invalid.s
+++ b/llvm/test/MC/RISCV/rv32i-invalid.s
@@ -170,7 +170,7 @@ xor s2, s2 # CHECK: :[[@LINE]]:1: error: too few operands for instruction
 
 # Instruction not in the base ISA
 div a4, ra, s0 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'M' (Integer Multiplication and Division){{$}}
-amomaxu.w s5, s4, (s3) # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'A' (Atomic Instructions){{$}}
+amomaxu.w s5, s4, (s3) # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'A' (Atomic Instructions) or 'Zaamo' (Atomic Memory Operations){{$}}
 fadd.s ft0, ft1, ft2 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'F' (Single-Precision Floating-Point){{$}}
 fadd.h ft0, ft1, ft2 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zfh' (Half-Precision Floating-Point){{$}}
 fadd.s a0, a1, a2 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zfinx' (Float in Integer){{$}}
diff --git a/llvm/test/MC/RISCV/rv32zaamo-invalid.s b/llvm/test/MC/RISCV/rv32zaamo-invalid.s
new file mode 100644
index 00000000000000..f5974828d90c4a
--- /dev/null
+++ b/llvm/test/MC/RISCV/rv32zaamo-invalid.s
@@ -0,0 +1,11 @@
+# RUN: not llvm-mc -triple riscv32 -mattr=+experimental-zaamo < %s 2>&1 | FileCheck %s
+
+# Final operand must have parentheses
+amoswap.w a1, a2, a3 # CHECK: :[[@LINE]]:19: error: expected '(' or optional integer offset
+amomin.w a1, a2, 1 # CHECK: :[[@LINE]]:20: error: expected '(' after optional integer offset
+amomin.w a1, a2, 1(a3) # CHECK: :[[@LINE]]:18: error: optional integer offset must be 0
+
+# Only .aq, .rl, and .aqrl suffixes are valid
+amoxor.w.rlqa a2, a3, (a4) # CHECK: :[[@LINE]]:1: error: unrecognized instruction mnemonic
+amoor.w.aq.rl a4, a5, (a6) # CHECK: :[[@LINE]]:1: error: unrecognized instruction mnemonic
+amoor.w. a4, a5, (a6) # CHECK: :[[@LINE]]:1: error: unrecognized instruction mnemonic
diff --git a/llvm/test/MC/RISCV/rv32zaamo-valid.s b/llvm/test/MC/RISCV/rv32zaamo-valid.s
new file mode 100644
index 00000000000000..18b31cd0083363
--- /dev/null
+++ b/llvm/test/MC/RISCV/rv32zaamo-valid.s
@@ -0,0 +1,122 @@
+# RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-zaamo -riscv-no-aliases -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc %s -triple=riscv64 -mattr=+experimental-zaamo -riscv-no-aliases -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+experimental-zaamo < %s \
+# RUN:     | llvm-objdump --mattr=+experimental-zaamo -M no-aliases -d -r - \
+# RUN:     | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+experimental-zaamo < %s \
+# RUN:     | llvm-objdump --mattr=+experimental-zaamo -M no-aliases -d -r - \
+# RUN:     | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s
+
+# CHECK-ASM-AND-OBJ: amoswap.w a4, ra, (s0)
+# CHECK-ASM: encoding: [0x2f,0x27,0x14,0x08]
+amoswap.w a4, ra, (s0)
+# CHECK-ASM-AND-OBJ: amoadd.w a1, a2, (a3)
+# CHECK-ASM: encoding: [0xaf,0xa5,0xc6,0x00]
+amoadd.w a1, a2, (a3)
+# CHECK-ASM-AND-OBJ: amoxor.w a2, a3, (a4)
+# CHECK-ASM: encoding: [0x2f,0x26,0xd7,0x20]
+amoxor.w a2, a3, (a4)
+# CHECK-ASM-AND-OBJ: amoand.w a3, a4, (a5)
+# CHECK-ASM: encoding: [0xaf,0xa6,0xe7,0x60]
+amoand.w a3, a4, (a5)
+# CHECK-ASM-AND-OBJ: amoor.w a4, a5, (a6)
+# CHECK-ASM: encoding: [0x2f,0x27,0xf8,0x40]
+amoor.w a4, a5, (a6)
+# CHECK-ASM-AND-OBJ: amomin.w a5, a6, (a7)
+# CHECK-ASM: encoding: [0xaf,0xa7,0x08,0x81]
+amomin.w a5, a6, (a7)
+# CHECK-ASM-AND-OBJ: amomax.w s7, s6, (s5)
+# CHECK-ASM: encoding: [0xaf,0xab,0x6a,0xa1]
+amomax.w s7, s6, (s5)
+# CHECK-ASM-AND-OBJ: amominu.w s6, s5, (s4)
+# CHECK-ASM: encoding: [0x2f,0x2b,0x5a,0xc1]
+amominu.w s6, s5, (s4)
+# CHECK-ASM-AND-OBJ: amomaxu.w s5, s4, (s3)
+# CHECK-ASM: encoding: [0xaf,0xaa,0x49,0xe1]
+amomaxu.w s5, s4, (s3)
+
+# CHECK-ASM-AND-OBJ: amoswap.w.aq a4, ra, (s0)
+# CHECK-ASM: encoding: [0x2f,0x27,0x14,0x0c]
+amoswap.w.aq a4, ra, (s0)
+# CHECK-ASM-AND-OBJ: amoadd.w.aq a1, a2, (a3)
+# CHECK-ASM: encoding: [0xaf,0xa5,0xc6,0x04]
+amoadd.w.aq a1, a2, (a3)
+# CHECK-ASM-AND-OBJ: amoxor.w.aq a2, a3, (a4)
+# CHECK-ASM: encoding: [0x2f,0x26,0xd7,0x24]
+amoxor.w.aq a2, a3, (a4)
+# CHECK-ASM-AND-OBJ: amoand.w.aq a3, a4, (a5)
+# CHECK-ASM: encoding: [0xaf,0xa6,0xe7,0x64]
+amoand.w.aq a3, a4, (a5)
+# CHECK-ASM-AND-OBJ: amoor.w.aq a4, a5, (a6)
+# CHECK-ASM: encoding: [0x2f,0x27,0xf8,0x44]
+amoor.w.aq a4, a5, (a6)
+# CHECK-ASM-AND-OBJ: amomin.w.aq a5, a6, (a7)
+# CHECK-ASM: encoding: [0xaf,0xa7,0x08,0x85]
+amomin.w.aq a5, a6, (a7)
+# CHECK-ASM-AND-OBJ: amomax.w.aq s7, s6, (s5)
+# CHECK-ASM: encoding: [0xaf,0xab,0x6a,0xa5]
+amomax.w.aq s7, s6, (s5)
+# CHECK-ASM-AND-OBJ: amominu.w.aq s6, s5, (s4)
+# CHECK-ASM: encoding: [0x2f,0x2b,0x5a,0xc5]
+amominu.w.aq s6, s5, (s4)
+# CHECK-ASM-AND-OBJ: amomaxu.w.aq s5, s4, (s3)
+# CHECK-ASM: encoding: [0xaf,0xaa,0x49,0xe5]
+amomaxu.w.aq s5, s4, (s3)
+
+# CHECK-ASM-AND-OBJ: amoswap.w.rl a4, ra, (s0)
+# CHECK-ASM: encoding: [0x2f,0x27,0x14,0x0a]
+amoswap.w.rl a4, ra, (s0)
+# CHECK-ASM-AND-OBJ: amoadd.w.rl a1, a2, (a3)
+# CHECK-ASM: encoding: [0xaf,0xa5,0xc6,0x02]
+amoadd.w.rl a1, a2, (a3)
+# CHECK-ASM-AND-OBJ: amoxor.w.rl a2, a3, (a4)
+# CHECK-ASM: encoding: [0x2f,0x26,0xd7,0x22]
+amoxor.w.rl a2, a3, (a4)
+# CHECK-ASM-AND-OBJ: amoand.w.rl a3, a4, (a5)
+# CHECK-ASM: encoding: [0xaf,0xa6,0xe7,0x62]
+amoand.w.rl a3, a4, (a5)
+# CHECK-ASM-AND-OBJ: amoor.w.rl a4, a5, (a6)
+# CHECK-ASM: encoding: [0x2f,0x27,0xf8,0x42]
+amoor.w.rl a4, a5, (a6)
+# CHECK-ASM-AND-OBJ: amomin.w.rl a5, a6, (a7)
+# CHECK-ASM: encoding: [0xaf,0xa7,0x08,0x83]
+amomin.w.rl a5, a6, (a7)
+# CHECK-ASM-AND-OBJ: amomax.w.rl s7, s6, (s5)
+# CHECK-ASM: encoding: [0xaf,0xab,0x6a,0xa3]
+amomax.w.rl s7, s6, (s5)
+# CHECK-ASM-AND-OBJ: amominu.w.rl s6, s5, (s4)
+# CHECK-ASM: encoding: [0x2f,0x2b,0x5a,0xc3]
+amominu.w.rl s6, s5, (s4)
+# CHECK-ASM-AND-OBJ: amomaxu.w.rl s5, s4, (s3)
+# CHECK-ASM: encoding: [0xaf,0xaa,0x49,0xe3]
+amomaxu.w.rl s5, s4, (s3)
+
+# CHECK-ASM-AND-OBJ: amoswap.w.aqrl a4, ra, (s0)
+# CHECK-ASM: encoding: [0x2f,0x27,0x14,0x0e]
+amoswap.w.aqrl a4, ra, (s0)
+# CHECK-ASM-AND-OBJ: amoadd.w.aqrl a1, a2, (a3)
+# CHECK-ASM: encoding: [0xaf,0xa5,0xc6,0x06]
+amoadd.w.aqrl a1, a2, (a3)
+# CHECK-ASM-AND-OBJ: amoxor.w.aqrl a2, a3, (a4)
+# CHECK-ASM: encoding: [0x2f,0x26,0xd7,0x26]
+amoxor.w.aqrl a2, a3, (a4)
+# CHECK-ASM-AND-OBJ: amoand.w.aqrl a3, a4, (a5)
+# CHECK-ASM: encoding: [0xaf,0xa6,0xe7,0x66]
+amoand.w.aqrl a3, a4, (a5)
+# CHECK-ASM-AND-OBJ: amoor.w.aqrl a4, a5, (a6)
+# CHECK-ASM: encoding: [0x2f,0x27,0xf8,0x46]
+amoor.w.aqrl a4, a5, (a6)
+# CHECK-ASM-AND-OBJ: amomin.w.aqrl a5, a6, (a7)
+# CHECK-ASM: encoding: [0xaf,0xa7,0x08,0x87]
+amomin.w.aqrl a5, a6, (a7)
+# CHECK-ASM-AND-OBJ: amomax.w.aqrl s7, s6, (s5)
+# CHECK-ASM: encoding: [0xaf,0xab,0x6a,0xa7]
+amomax.w.aqrl s7, s6, (s5)
+# CHECK-ASM-AND-OBJ: amominu.w.aqrl s6, s5, (s4)
+# CHECK-ASM: encoding: [0x2f,0x2b,0x5a,0xc7]
+amominu.w.aqrl s6, s5, (s4)
+# CHECK-ASM-AND-OBJ: amomaxu.w.aqrl s5, s4, (s3)
+# CHECK-ASM: encoding: [0xaf,0xaa,0x49,0xe7]
+amomaxu.w.aqrl s5, s4, (s3)
diff --git a/llvm/test/MC/RISCV/rv32zalrsc-invalid.s b/llvm/test/MC/RISCV/rv32zalrsc-invalid.s
new file mode 100644
index 00000000000000..01e5a19a335aff
--- /dev/null
+++ b/llvm/test/MC/RISCV/rv32zalrsc-invalid.s
@@ -0,0 +1,7 @@
+# RUN: not llvm-mc -triple riscv32 -mattr=+experimental-zalrsc < %s 2>&1 | FileCheck %s
+
+# Final operand must have parentheses
+lr.w a4, a5 # CHECK: :[[@LINE]]:10: error: expected '(' or optional integer offset
+
+# lr only takes two operands
+lr.w s0, (s1), s2 # CHECK: :[[@LINE]]:16: error: invalid operand for instruction
diff --git a/llvm/test/MC/RISCV/rv32zalrsc-valid.s b/llvm/test/MC/RISCV/rv32zalrsc-valid.s
new file mode 100644
index 00000000000000..08c84f88979290
--- /dev/null
+++ b/llvm/test/MC/RISCV/rv32zalrsc-valid.s
@@ -0,0 +1,36 @@
+# RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-zalrsc -riscv-no-aliases -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc %s -triple=riscv64 -mattr=+experimental-zalrsc -riscv-no-aliases -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+experimental-zalrsc < %s \
+# RUN:     | llvm-objdump --mattr=+experimental-zalrsc -M no-aliases -d -r - \
+# RUN:     | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+experimental-zalrsc < %s \
+# RUN:     | llvm-objdump --mattr=+experimental-zalrsc -M no-aliases -d -r - \
+# RUN:     | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s
+
+# CHECK-ASM-AND-OBJ: lr.w t0, (t1)
+# CHECK-ASM: encoding: [0xaf,0x22,0x03,0x10]
+lr.w t0, (t1)
+# CHECK-ASM-AND-OBJ: lr.w.aq t1, (t2)
+# CHECK-ASM: encoding: [0x2f,0xa3,0x03,0x14]
+lr.w.aq t1, (t2)
+# CHECK-ASM-AND-OBJ: lr.w.rl t2, (t3)
+# CHECK-ASM: encoding: [0xaf,0x23,0x0e,0x12]
+lr.w.rl t2, (t3)
+# CHECK-ASM-AND-OBJ: lr.w.aqrl t3, (t4)
+# CHECK-ASM: encoding: [0x2f,0xae,0x0e,0x16]
+lr.w.aqrl t3, (t4)
+
+# CHECK-ASM-AND-OBJ: sc.w t6, t5, (t4)
+# CHECK-ASM: encoding: [0xaf,0xaf,0xee,0x19]
+sc.w t6, t5, (t4)
+# CHECK-ASM-AND-OBJ: sc.w.aq t5, t4, (t3)
+# CHECK-ASM: encoding: [0x2f,0x2f,0xde,0x1d]
+sc.w.aq t5, t4, (t3)
+# CHECK-ASM-AND-OBJ: sc.w.rl t4, t3, (t2)
+# CHECK-ASM: encoding: [0xaf,0xae,0xc3,0x1b]
+sc.w.rl t4, t3, (t2)
+# CHECK-ASM-AND-OBJ: sc.w.aqrl t3, t2, (t1)
+# CHECK-ASM: encoding: [0x2f,0x2e,0x73,0x1e]
+sc.w.aqrl t3, t2, (t1)
diff --git a/llvm/test/MC/RISCV/rv64zaamo-invalid.s b/llvm/test/MC/RISCV/rv64zaamo-invalid.s
new file mode 100644
index 00000000000000..d196de83034261
--- /dev/null
+++ b/llvm/test/MC/RISCV/rv64zaamo-invalid.s
@@ -0,0 +1,11 @@
+# RUN: not llvm-mc -triple riscv64 -mattr=+experimental-zaamo < %s 2>&1 | FileCheck %s
+
+# Final operand must have parentheses
+amoswap.d a1, a2, a3 # CHECK: :[[@LINE]]:19: error: expected '(' or optional integer offset
+amomin.d a1, a2, 1 # CHECK: :[[@LINE]]:20: error: expected '(' after optional integer offset
+amomin.d a1, a2, 1(a3) # CHECK: :[[@LINE]]:18: error: optional integer offset must be 0
+
+# Only .aq, .rl, and .aqrl suffixes are valid
+amoxor.d.rlqa a2, a3, (a4) # CHECK: :[[@LINE]]:1: error: unrecognized instruction mnemonic
+amoor.d.aq.rl a4, a5, (a6) # CHECK: :[[@LINE]]:1: error: unrecognized instruction mnemonic
+amoor.d. a4, a5, (a6) # CHECK: :[[@LINE]]:1: error: unrecognized instruction mnemonic
diff --git a/llvm/test/MC/RISCV/rv64zaamo-valid.s b/llvm/test/MC/RISCV/rv64zaamo-valid.s
new file mode 100644
index 00000000000000..01bb8f56c120af
--- /dev/null
+++ b/llvm/test/MC/RISCV/rv64zaamo-valid.s
@@ -0,0 +1,157 @@
+# RUN: llvm-mc %s -triple=riscv64 -mattr=+experimental-zaamo -riscv-no-aliases -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+experimental-zaamo < %s \
+# RUN:     | llvm-objdump --mattr=+experimental-zaamo -M no-aliases -d -r - \
+# RUN:     | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s
+#
+# RUN: not llvm-mc -triple riscv32 -mattr=+experimental-zaamo < %s 2>&1 \
+# RUN:     | FileCheck -check-prefix=CHECK-RV32 %s
+
+# CHECK-ASM-AND-OBJ: amoswap.d a4, ra, (s0)
+# CHECK-ASM: encoding: [0x2f,0x37,0x14,0x08]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+amoswap.d a4, ra, (s0)
+# CHECK-ASM-AND-OBJ: amoadd.d a1, a2, (a3)
+# CHECK-ASM: encoding: [0xaf,0xb5,0xc6,0x00]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+amoadd.d a1, a2, (a3)
+# CHECK-ASM-AND-OBJ: amoxor.d a2, a3, (a4)
+# CHECK-ASM: encoding: [0x2f,0x36,0xd7,0x20]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+amoxor.d a2, a3, (a4)
+# CHECK-ASM-AND-OBJ: amoand.d a3, a4, (a5)
+# CHECK-ASM: encoding: [0xaf,0xb6,0xe7,0x60]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+amoand.d a3, a4, (a5)
+# CHECK-ASM-AND-OBJ: amoor.d a4, a5, (a6)
+# CHECK-ASM: encoding: [0x2f,0x37,0xf8,0x40]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+amoor.d a4, a5, (a6)
+# CHECK-ASM-AND-OBJ: amomin.d a5, a6, (a7)
+# CHECK-ASM: encoding: [0xaf,0xb7,0x08,0x81]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+amomin.d a5, a6, (a7)
+# CHECK-ASM-AND-OBJ: amomax.d s7, s6, (s5)
+# CHECK-ASM: encoding: [0xaf,0xbb,0x6a,0xa1]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+amomax.d s7, s6, (s5)
+# CHECK-ASM-AND-OBJ: amominu.d s6, s5, (s4)
+# CHECK-ASM: encoding: [0x2f,0x3b,0x5a,0xc1]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+amominu.d s6, s5, (s4)
+# CHECK-ASM-AND-OBJ: amomaxu.d s5, s4, (s3)
+# CHECK-ASM: encoding: [0xaf,0xba,0x49,0xe1]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+amomaxu.d s5, s4, (s3)
+
+
+# CHECK-ASM-AND-OBJ: amoswap.d.aq a4, ra, (s0)
+# CHECK-ASM: encoding: [0x2f,0x37,0x14,0x0c]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+amoswap.d.aq a4, ra, (s0)
+# CHECK-ASM-AND-OBJ: amoadd.d.aq a1, a2, (a3)
+# CHECK-ASM: encoding: [0xaf,0xb5,0xc6,0x04]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+amoadd.d.aq a1, a2, (a3)
+# CHECK-ASM-AND-OBJ: amoxor.d.aq a2, a3, (a4)
+# CHECK-ASM: encoding: [0x2f,0x36,0xd7,0x24]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+amoxor.d.aq a2, a3, (a4)
+# CHECK-ASM-AND-OBJ: amoand.d.aq a3, a4, (a5)
+# CHECK-ASM: encoding: [0xaf,0xb6,0xe7,0x64]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+amoand.d.aq a3, a4, (a5)
+# CHECK-ASM-AND-OBJ: amoor.d.aq a4, a5, (a6)
+# CHECK-ASM: encoding: [0x2f,0x37,0xf8,0x44]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+amoor.d.aq a4, a5, (a6)
+# CHECK-ASM-AND-OBJ: amomin.d.aq a5, a6, (a7)
+# CHECK-ASM: encoding: [0xaf,0xb7,0x08,0x85]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+amomin.d.aq a5, a6, (a7)
+# CHECK-ASM-AND-OBJ: amomax.d.aq s7, s6, (s5)
+# CHECK-ASM: encoding: [0xaf,0xbb,0x6a,0xa5]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+amomax.d.aq s7, s6, (s5)
+# CHECK-ASM-AND-OBJ: amominu.d.aq s6, s5, (s4)
+# CHECK-ASM: encoding: [0x2f,0x3b,0x5a,0xc5]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+amominu.d.aq s6, s5, (s4)
+# CHECK-ASM-AND-OBJ: amomaxu.d.aq s5, s4, (s3)
+# CHECK-ASM: encoding: [0xaf,0xba,0x49,0xe5]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+amomaxu.d.aq s5, s4, (s3)
+
+# CHECK-ASM-AND-OBJ: amoswap.d.rl a4, ra, (s0)
+# CHECK-ASM: encoding: [0x2f,0x37,0x14,0x0a]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+amoswap.d.rl a4, ra, (s0)
+# CHECK-ASM-AND-OBJ: amoadd.d.rl a1, a2, (a3)
+# CHECK-ASM: encoding: [0xaf,0xb5,0xc6,0x02]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+amoadd.d.rl a1, a2, (a3)
+# CHECK-ASM-AND-OBJ: amoxor.d.rl a2, a3, (a4)
+# CHECK-ASM: encoding: [0x2f,0x36,0xd7,0x22]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+amoxor.d.rl a2, a3, (a4)
+# CHECK-ASM-AND-OBJ: amoand.d.rl a3, a4, (a5)
+# CHECK-ASM: encoding: [0xaf,0xb6,0xe7,0x62]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+amoand.d.rl a3, a4, (a5)
+# CHECK-ASM-AND-OBJ: amoor.d.rl a4, a5, (a6)
+# CHECK-ASM: encoding: [0x2f,0x37,0xf8,0x42]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+amoor.d.rl a4, a5, (a6)
+# CHECK-ASM-AND-OBJ: amomin.d.rl a5, a6, (a7)
+# CHECK-ASM: encoding: [0xaf,0xb7,0x08,0x83]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+amomin.d.rl a5, a6, (a7)
+# CHECK-ASM-AND-OBJ: amomax.d.rl s7, s6, (s5)
+# CHECK-ASM: encoding: [0xaf,0xbb,0x6a,0xa3]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+amomax.d.rl s7, s6, (s5)
+# CHECK-ASM-AND-OBJ: amominu.d.rl s6, s5, (s4)
+# CHECK-ASM: encoding: [0x2f,0x3b,0x5a,0xc3]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+amominu.d.rl s6, s5, (s4)
+# CHECK-ASM-AND-OBJ: amomaxu.d.rl s5, s4, (s3)
+# CHECK-ASM: encoding: [0xaf,0xba,0x49,0xe3]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+amomaxu.d.rl s5, s4, (s3)
+
+# CHECK-ASM-AND-OBJ: amoswap.d.aqrl a4, ra, (s0)
+# CHECK-ASM: encoding: [0x2f,0x37,0x14,0x0e]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+amoswap.d.aqrl a4, ra, (s0)
+# CHECK-ASM-AND-OBJ: amoadd.d.aqrl a1, a2, (a3)
+# CHECK-ASM: encoding: [0xaf,0xb5,0xc6,0x06]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+amoadd.d.aqrl a1, a2, (a3)
+# CHECK-ASM-AND-OBJ: amoxor.d.aqrl a2, a3, (a4)
+# CHECK-ASM: encoding: [0x2f,0x36,0xd7,0x26]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+amoxor.d.aqrl a2, a3, (a4)
+# CHECK-ASM-AND-OBJ: amoand.d.aqrl a3, a4, (a5)
+# CHECK-ASM: encoding: [0xaf,0xb6,0xe7,0x66]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+amoand.d.aqrl a3, a4, (a5)
+# CHECK-ASM-AND-OBJ: amoor.d.aqrl a4, a5, (a6)
+# CHECK-ASM: encoding: [0x2f,0x37,0xf8,0x46]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+amoor.d.aqrl a4, a5, (a6)
+# CHECK-ASM-AND-OBJ: amomin.d.aqrl a5, a6, (a7)
+# CHECK-ASM: encoding: [0xaf,0xb7,0x08,0x87]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+amomin.d.aqrl a5, a6, (a7)
+# CHECK-ASM-AND-OBJ: amomax.d.aqrl s7, s6, (s5)
+# CHECK-ASM: encoding: [0xaf,0xbb,0x6a,0xa7]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+amomax.d.aqrl s7, s6, (s5)
+# CHECK-ASM-AND-OBJ: amominu.d.aqrl s6, s5, (s4)
+# CHECK-ASM: encoding: [0x2f,0x3b,0x5a,0xc7]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+amominu.d.aqrl s6, s5, (s4)
+# CHECK-ASM-AND-OBJ: amomaxu.d.aqrl s5, s4, (s3)
+# CHECK-ASM: encoding: [0xaf,0xba,0x49,0xe7]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+amomaxu.d.aqrl s5, s4, (s3)
diff --git a/llvm/test/MC/RISCV/rv64zalrsc-invalid.s b/llvm/test/MC/RISCV/rv64zalrsc-invalid.s
new file mode 100644
index 00000000000000..5a756847ac9636
--- /dev/null
+++ b/llvm/test/MC/RISCV/rv64zalrsc-invalid.s
@@ -0,0 +1,7 @@
+# RUN: not llvm-mc -triple riscv64 -mattr=+experimental-zalrsc < %s 2>&1 | FileCheck %s
+
+# Final operand must have parentheses
+lr.d a4, a5 # CHECK: :[[@LINE]]:10: error: expected '(' or optional integer offset
+
+# lr only takes two operands
+lr.d s0, (s1), s2 # CHECK: :[[@LINE]]:16: error: invalid operand for instruction
diff --git a/llvm/test/MC/RISCV/rv64zalrsc-valid.s b/llvm/test/MC/RISCV/rv64zalrsc-valid.s
new file mode 100644
index 00000000000000..2c338afcdb5d68
--- /dev/null
+++ b/llvm/test/MC/RISCV/rv64zalrsc-valid.s
@@ -0,0 +1,42 @@
+# RUN: llvm-mc %s -triple=riscv64 -mattr=+experimental-zalrsc -riscv-no-aliases -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+experimental-zalrsc < %s \
+# RUN:     | llvm-objdump --mattr=+experimental-zalrsc -M no-aliases -d -r - \
+# RUN:     | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s
+#
+# RUN: not llvm-mc -triple riscv32 -mattr=+experimental-zalrsc < %s 2>&1 \
+# RUN:     | FileCheck -check-prefix=CHECK-RV32 %s
+
+# CHECK-ASM-AND-OBJ: lr.d t0, (t1)
+# CHECK-ASM: encoding: [0xaf,0x32,0x03,0x10]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+lr.d t0, (t1)
+# CHECK-ASM-AND-OBJ: lr.d.aq t1, (t2)
+# CHECK-ASM: encoding: [0x2f,0xb3,0x03,0x14]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+lr.d.aq t1, (t2)
+# CHECK-ASM-AND-OBJ: lr.d.rl t2, (t3)
+# CHECK-ASM: encoding: [0xaf,0x33,0x0e,0x12]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+lr.d.rl t2, (t3)
+# CHECK-ASM-AND-OBJ: lr.d.aqrl t3, (t4)
+# CHECK-ASM: encoding: [0x2f,0xbe,0x0e,0x16]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+lr.d.aqrl t3, (t4)
+
+# CHECK-ASM-AND-OBJ: sc.d t6, t5, (t4)
+# CHECK-ASM: encoding: [0xaf,0xbf,0xee,0x19]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+sc.d t6, t5, (t4)
+# CHECK-ASM-AND-OBJ: sc.d.aq t5, t4, (t3)
+# CHECK-ASM: encoding: [0x2f,0x3f,0xde,0x1d]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+sc.d.aq t5, t4, (t3)
+# CHECK-ASM-AND-OBJ: sc.d.rl t4, t3, (t2)
+# CHECK-ASM: encoding: [0xaf,0xbe,0xc3,0x1b]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+sc.d.rl t4, t3, (t2)
+# CHECK-ASM-AND-OBJ: sc.d.aqrl t3, t2, (t1)
+# CHECK-ASM: encoding: [0x2f,0x3e,0x73,0x1e]
+# CHECK-RV32: :[[@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+sc.d.aqrl t3, t2, (t1)
diff --git a/llvm/unittests/Support/RISCVISAInfoTest.cpp b/llvm/unittests/Support/RISCVISAInfoTest.cpp
index 42759f30fd1bc3..d8edf4b35c934e 100644
--- a/llvm/unittests/Support/RISCVISAInfoTest.cpp
+++ b/llvm/unittests/Support/RISCVISAInfoTest.cpp
@@ -777,7 +777,9 @@ Experimental extensions
     zicfiss             0.4
     zicond              1.0
     zimop               0.1
+    zaamo               0.1
     zacas               1.0
+    zalrsc              0.1
     zfbfmin             0.8
     zcmop               0.2
     ztso                0.1



More information about the cfe-commits mailing list