https://github.com/topperc updated 
https://github.com/llvm/llvm-project/pull/188121

>From c615904a7d839cadf3074f8c4842b26007877b5a Mon Sep 17 00:00:00 2001
From: Craig Topper <[email protected]>
Date: Fri, 13 Mar 2026 16:33:07 -0700
Subject: [PATCH 1/7] [RISCV] Use uimm3/4/5/6_plus1 for (P)SATI instructions.

The encoded immediate is the number of trailing 1s in the maximum value.
Mailing list discussion has a preference to print and parse this
value plus one. https://lists.riscv.org/g/tech-p-ext/message/910

With this patch, saturing to a signed 8-bit integer would be
"sati a0, a0, 8". Previously it was "sati a0, a0, 7".

I will be making a spec update to https://github.com/riscv/riscv-p-spec
after a previous patch merges.
---
 .../Target/RISCV/AsmParser/RISCVAsmParser.cpp | 14 +++++
 .../Target/RISCV/MCTargetDesc/RISCVBaseInfo.h |  2 +
 llvm/lib/Target/RISCV/RISCVInstrInfoP.td      | 52 ++++++++++++++-----
 llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td   | 20 -------
 llvm/test/MC/RISCV/rv32p-invalid.s            |  4 +-
 llvm/test/MC/RISCV/rv32p-valid.s              |  8 +--
 llvm/test/MC/RISCV/rv64p-invalid.s            |  6 +--
 llvm/test/MC/RISCV/rv64p-valid.s              | 12 ++---
 .../TableGen/Common/CodeGenDAGPatterns.cpp    |  2 +-
 9 files changed, 72 insertions(+), 48 deletions(-)

diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp 
b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index 9bf3bb4bdcaa0..0d9b9b06f9973 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -749,11 +749,21 @@ struct RISCVOperand final : public MCParsedAsmOperand {
     return isUImmPred([](int64_t Imm) { return isUInt<5>(Imm) && Imm > 3; });
   }
 
+  bool isUImm4Plus1() const {
+    return isUImmPred(
+        [](int64_t Imm) { return Imm > 0 && isUInt<4>(Imm - 1); });
+  }
+
   bool isUImm5Plus1() const {
     return isUImmPred(
         [](int64_t Imm) { return Imm > 0 && isUInt<5>(Imm - 1); });
   }
 
+  bool isUImm6Plus1() const {
+    return isUImmPred(
+        [](int64_t Imm) { return Imm > 0 && isUInt<6>(Imm - 1); });
+  }
+
   bool isUImm5GE6Plus1() const {
     return isUImmPred(
         [](int64_t Imm) { return Imm >= 6 && isUInt<5>(Imm - 1); });
@@ -1512,6 +1522,8 @@ bool RISCVAsmParser::matchAndEmitInstruction(SMLoc IDLoc, 
unsigned &Opcode,
     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 3) - 1);
   case Match_InvalidUImm4:
     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 4) - 1);
+  case Match_InvalidUImm4Plus1:
+    return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 4));
   case Match_InvalidUImm5:
     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
   case Match_InvalidUImm5NonZero:
@@ -1529,6 +1541,8 @@ bool RISCVAsmParser::matchAndEmitInstruction(SMLoc IDLoc, 
unsigned &Opcode,
   }
   case Match_InvalidUImm6:
     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1);
+  case Match_InvalidUImm6Plus1:
+    return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 6));
   case Match_InvalidUImm7:
     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 7) - 1);
   case Match_InvalidUImm8:
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h 
b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
index c4d54bdd60737..b5aade96d4093 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
@@ -33,6 +33,7 @@ enum OperandType : unsigned {
   OPERAND_UIMM2_LSB0,
   OPERAND_UIMM3,
   OPERAND_UIMM4,
+  OPERAND_UIMM4_PLUS1,
   OPERAND_UIMM5,
   OPERAND_UIMM5_NONZERO,
   OPERAND_UIMM5_GT3,
@@ -41,6 +42,7 @@ enum OperandType : unsigned {
   OPERAND_UIMM5_LSB0,
   OPERAND_UIMM5_SLIST,
   OPERAND_UIMM6,
+  OPERAND_UIMM6_PLUS1,
   OPERAND_UIMM6_LSB0,
   OPERAND_UIMM7,
   OPERAND_UIMM7_LSB00,
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td 
b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
index 23950c4478a1b..1530061f8c702 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
@@ -105,6 +105,30 @@ def simm10_pli_w : RISCVOp {
   }];
 }
 
+class UImmPlus1AsmOperand<int width> : AsmOperandClass {
+  let Name = "UImm" # width # "Plus1";
+  let RenderMethod = "addImmOperands";
+  let DiagnosticType = "InvalidUImm" # width # "Plus1";
+}
+
+class RISCVUImmPlus1Op<int bitsNum>
+    : RISCVOp, ImmLeaf<XLenVT, "return Imm > 0 && isUInt<" # bitsNum # ">(Imm 
- 1);"> {
+  let ParserMatchClass = UImmPlus1AsmOperand<bitsNum>;
+  let EncoderMethod = "getImmOpValueMinus1";
+  let DecoderMethod = "decodeUImmPlus1Operand<" # bitsNum # ">";
+  let OperandType = "OPERAND_UIMM" # bitsNum # "_PLUS1";
+  let MCOperandPredicate = [{
+    int64_t Imm;
+    if (!MCOp.evaluateAsConstantImm(Imm))
+      return false;
+    return Imm > 0 && isUInt<}] # bitsNum # [{>(Imm - 1);
+  }];
+}
+
+def uimm4_plus1 : RISCVUImmPlus1Op<4>;
+def uimm5_plus1 : RISCVUImmPlus1Op<5>;
+def uimm6_plus1 : RISCVUImmPlus1Op<6>;
+
 
//===----------------------------------------------------------------------===//
 // Instruction class templates
 
//===----------------------------------------------------------------------===//
@@ -220,32 +244,36 @@ class RVPShift_ri<bits<3> f, bits<3> funct3, string 
opcodestr, Operand ImmType>
   let Inst{27}    = 0b0;
 }
 
-class RVPShiftD_ri<bits<3> f, bits<3> funct3, string opcodestr>
-    : RVPShift_ri<f, funct3, opcodestr, uimm6> {
+class RVPShiftD_ri<bits<3> f, bits<3> funct3, string opcodestr,
+                   Operand ImmType = uimm6>
+    : RVPShift_ri<f, funct3, opcodestr, ImmType> {
   bits<6> shamt;
 
   let Inst{26} = 0b1;
   let Inst{25-20} = shamt;
 }
 
-class RVPShiftW_ri<bits<3> f, bits<3> funct3, string opcodestr>
-    : RVPShift_ri<f, funct3, opcodestr, uimm5> {
+class RVPShiftW_ri<bits<3> f, bits<3> funct3, string opcodestr,
+                   Operand ImmType = uimm5>
+    : RVPShift_ri<f, funct3, opcodestr, ImmType> {
   bits<5> shamt;
 
   let Inst{26-25} = 0b01;
   let Inst{24-20} = shamt;
 }
 
-class RVPShiftH_ri<bits<3> f, bits<3> funct3, string opcodestr>
-    : RVPShift_ri<f, funct3, opcodestr, uimm4> {
+class RVPShiftH_ri<bits<3> f, bits<3> funct3, string opcodestr,
+                   Operand ImmType = uimm4>
+    : RVPShift_ri<f, funct3, opcodestr, ImmType> {
   bits<4> shamt;
 
   let Inst{26-24} = 0b001;
   let Inst{23-20} = shamt;
 }
 
-class RVPShiftB_ri<bits<3> f, bits<3> funct3, string opcodestr>
-    : RVPShift_ri<f, funct3, opcodestr, uimm3> {
+class RVPShiftB_ri<bits<3> f, bits<3> funct3, string opcodestr,
+                   Operand ImmType = uimm3>
+    : RVPShift_ri<f, funct3, opcodestr, ImmType> {
   bits<3> shamt;
 
   let Inst{26-23} = 0b0001;
@@ -636,7 +664,7 @@ let Predicates = [HasStdExtP] in {
   def PSRARI_H   : RVPShiftH_ri<0b101, 0b100, "psrari.h">;
 
   let Defs = [VXSAT] in
-  def PSATI_H    : RVPShiftH_ri<0b110, 0b100, "psati.h">;
+  def PSATI_H    : RVPShiftH_ri<0b110, 0b100, "psati.h", uimm4_plus1>;
 } // Predicates = [HasStdExtP]
 let Predicates = [HasStdExtP, IsRV32], DecoderNamespace = "RV32Only" in {
   let Defs = [VXSAT] in
@@ -645,7 +673,7 @@ let Predicates = [HasStdExtP, IsRV32], DecoderNamespace = 
"RV32Only" in {
   def SRARI_RV32 : RVPShiftW_ri<0b101, 0b100, "srari">;
 
   let Defs = [VXSAT] in
-  def SATI_RV32  : RVPShiftW_ri<0b110, 0b100, "sati">;
+  def SATI_RV32  : RVPShiftW_ri<0b110, 0b100, "sati", uimm5_plus1>;
 } // Predicates = [HasStdExtP, IsRV32], DecoderNamespace = "RV32Only"
 let Predicates = [HasStdExtP, IsRV64] in {
   def PSRLI_W    : RVPShiftW_ri<0b000, 0b100, "psrli.w">;
@@ -660,8 +688,8 @@ let Predicates = [HasStdExtP, IsRV64] in {
   def SRARI_RV64 : RVPShiftD_ri<0b101, 0b100, "srari">;
 
   let Defs = [VXSAT] in {
-  def PSATI_W    : RVPShiftW_ri<0b110, 0b100, "psati.w">;
-  def SATI_RV64  : RVPShiftD_ri<0b110, 0b100, "sati">;
+  def PSATI_W    : RVPShiftW_ri<0b110, 0b100, "psati.w", uimm5_plus1>;
+  def SATI_RV64  : RVPShiftD_ri<0b110, 0b100, "sati", uimm6_plus1>;
   } // Defs = [VXSAT]
 } // Predicates = [HasStdExtP, IsRV64]
 
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td 
b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
index c2051973be186..aca8376d73356 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
@@ -55,26 +55,6 @@ def uimm5gt3 : RISCVOp<XLenVT>, ImmLeaf<XLenVT,
 
 def tuimm5gt3 : TImmLeaf<XLenVT, [{return (Imm > 3) && isUInt<5>(Imm);}]>;
 
-def UImm5Plus1AsmOperand : AsmOperandClass {
-  let Name = "UImm5Plus1";
-  let RenderMethod = "addImmOperands";
-  let DiagnosticType = "InvalidUImm5Plus1";
-}
-
-def uimm5_plus1 : RISCVOp, ImmLeaf<XLenVT,
-  [{return Imm >= 1 && Imm <= 32;}]> {
-  let ParserMatchClass = UImm5Plus1AsmOperand;
-  let EncoderMethod = "getImmOpValueMinus1";
-  let DecoderMethod = "decodeUImmPlus1Operand<5>";
-  let OperandType = "OPERAND_UIMM5_PLUS1";
-  let MCOperandPredicate = [{
-    int64_t Imm;
-    if (!MCOp.evaluateAsConstantImm(Imm))
-      return false;
-    return Imm >= 1 && Imm <= 32;
-  }];
-}
-
 def uimm5ge6_plus1 : RISCVOp<XLenVT>, ImmLeaf<XLenVT,
   [{return Imm >= 6 && Imm <= 32;}]> {
   let ParserMatchClass = UImmAsmOperand<5, "GE6Plus1">;
diff --git a/llvm/test/MC/RISCV/rv32p-invalid.s 
b/llvm/test/MC/RISCV/rv32p-invalid.s
index 105444cf6b300..6ff44b9dc4fe0 100644
--- a/llvm/test/MC/RISCV/rv32p-invalid.s
+++ b/llvm/test/MC/RISCV/rv32p-invalid.s
@@ -37,9 +37,9 @@ psrari.h ra, sp, 100 # CHECK: :[[@LINE]]:18: error: immediate 
must be an integer
 psrari.w ra, sp, 15 # CHECK: :[[@LINE]]:1: error: instruction requires the 
following: RV64I Base Instruction Set
 srari ra, sp, 100 # CHECK: :[[@LINE]]:15: error: immediate must be an integer 
in the range [0, 31]
 
-psati.h ra, sp, 100 # CHECK: :[[@LINE]]:17: error: immediate must be an 
integer in the range [0, 15]
+psati.h ra, sp, 100 # CHECK: :[[@LINE]]:17: error: immediate must be an 
integer in the range [1, 16]
 psati.w ra, sp, 24 # CHECK: :[[@LINE]]:1: error: instruction requires the 
following: RV64I Base Instruction Set
-sati ra, sp, 100 # CHECK: :[[@LINE]]:14: error: immediate must be an integer 
in the range [0, 31]
+sati ra, sp, 100 # CHECK: :[[@LINE]]:14: error: immediate must be an integer 
in the range [1, 32]
 
 psrl.ws a0, a1, a2 # CHECK: :[[@LINE]]:1: error: instruction requires the 
following: RV64I Base Instruction Set
 predsum.ws a0, a1, a2 # CHECK: :[[@LINE]]:1: error: instruction requires the 
following: RV64I Base Instruction Set
diff --git a/llvm/test/MC/RISCV/rv32p-valid.s b/llvm/test/MC/RISCV/rv32p-valid.s
index a37669086c67b..9729fd6610147 100644
--- a/llvm/test/MC/RISCV/rv32p-valid.s
+++ b/llvm/test/MC/RISCV/rv32p-valid.s
@@ -109,12 +109,12 @@ psrari.h t4, t5, 6
 # CHECK-ASM-AND-OBJ: srari t5, t6, 7
 # CHECK-ASM: encoding: [0x1b,0xcf,0x7f,0xd2]
 srari t5, t6, 7
-# CHECK-ASM-AND-OBJ: psati.h t6, s11, 8
+# CHECK-ASM-AND-OBJ: psati.h t6, s11, 9
 # CHECK-ASM: encoding: [0x9b,0xcf,0x8d,0xe1]
-psati.h t6, s11, 8
-# CHECK-ASM-AND-OBJ: sati s11, s10, 9
+psati.h t6, s11, 9
+# CHECK-ASM-AND-OBJ: sati s11, s10, 10
 # CHECK-ASM: encoding: [0x9b,0x4d,0x9d,0xe2]
-sati s11, s10, 9
+sati s11, s10, 10
 # CHECK-ASM-AND-OBJ: psrl.hs a6, a7, a1
 # CHECK-ASM: encoding: [0x1b,0xc8,0xb8,0x88]
 psrl.hs a6, a7, a1
diff --git a/llvm/test/MC/RISCV/rv64p-invalid.s 
b/llvm/test/MC/RISCV/rv64p-invalid.s
index e18c9ec0e29ea..434abf54be3da 100644
--- a/llvm/test/MC/RISCV/rv64p-invalid.s
+++ b/llvm/test/MC/RISCV/rv64p-invalid.s
@@ -33,9 +33,9 @@ psrari.h ra, sp, 100 # CHECK: :[[@LINE]]:18: error: immediate 
must be an integer
 psrari.w ra, sp, 100 # CHECK: :[[@LINE]]:18: error: immediate must be an 
integer in the range [0, 31]
 srari ra, sp, 100 # CHECK: :[[@LINE]]:15: error: immediate must be an integer 
in the range [0, 63]
 
-psati.h ra, sp, 100 # CHECK: :[[@LINE]]:17: error: immediate must be an 
integer in the range [0, 15]
-psati.w ra, sp, 100 # CHECK: :[[@LINE]]:17: error: immediate must be an 
integer in the range [0, 31]
-sati ra, sp, 100 # CHECK: :[[@LINE]]:14: error: immediate must be an integer 
in the range [0, 63]
+psati.h ra, sp, 100 # CHECK: :[[@LINE]]:17: error: immediate must be an 
integer in the range [1, 16]
+psati.w ra, sp, 100 # CHECK: :[[@LINE]]:17: error: immediate must be an 
integer in the range [1, 32]
+sati ra, sp, 100 # CHECK: :[[@LINE]]:14: error: immediate must be an integer 
in the range [1, 64]
 
 sadd t1, a7, a0 # CHECK: :[[@LINE]]:1: error: instruction requires the 
following: RV32I Base Instruction Set
 aadd t1, a7, a0 # CHECK: :[[@LINE]]:1: error: instruction requires the 
following: RV32I Base Instruction Set
diff --git a/llvm/test/MC/RISCV/rv64p-valid.s b/llvm/test/MC/RISCV/rv64p-valid.s
index bb96b067c448c..7d91057327117 100644
--- a/llvm/test/MC/RISCV/rv64p-valid.s
+++ b/llvm/test/MC/RISCV/rv64p-valid.s
@@ -160,15 +160,15 @@ psrari.w t5, t6, 7
 # CHECK-ASM-AND-OBJ: srari t6, s11, 63
 # CHECK-ASM: encoding: [0x9b,0xcf,0xfd,0xd7]
 srari t6, s11, 63
-# CHECK-ASM-AND-OBJ: psati.h s11, s10, 9
+# CHECK-ASM-AND-OBJ: psati.h s11, s10, 10
 # CHECK-ASM: encoding: [0x9b,0x4d,0x9d,0xe1]
-psati.h s11, s10, 9
-# CHECK-ASM-AND-OBJ: psati.w s10, s9, 10
+psati.h s11, s10, 10
+# CHECK-ASM-AND-OBJ: psati.w s10, s9, 11
 # CHECK-ASM: encoding: [0x1b,0xcd,0xac,0xe2]
-psati.w s10, s9, 10
-# CHECK-ASM-AND-OBJ: sati s9, s8, 32
+psati.w s10, s9, 11
+# CHECK-ASM-AND-OBJ: sati s9, s8, 33
 # CHECK-ASM: encoding: [0x9b,0x4c,0x0c,0xe6]
-sati s9, s8, 32
+sati s9, s8, 33
 # CHECK-ASM-AND-OBJ: psrl.hs a6, a7, a1
 # CHECK-ASM: encoding: [0x1b,0xc8,0xb8,0x88]
 psrl.hs a6, a7, a1
diff --git a/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp 
b/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp
index c75d35feadc01..c20a53ccc104c 100644
--- a/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp
+++ b/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp
@@ -2076,7 +2076,7 @@ void TreePatternNode::print(raw_ostream &OS) const {
   for (const ScopedName &Name : NamesAsPredicateArg)
     OS << ":$pred:" << Name.getScope() << ":" << Name.getIdentifier();
 }
-void TreePatternNode::dump() const { print(dbgs()); }
+void TreePatternNode::dump() const { print(dbgs()); dbgs() << '\n'; }
 
 /// isIsomorphicTo - Return true if this node is recursively
 /// isomorphic to the specified node.  For this comparison, the node's

>From 154a975904ffcfec46a7c3af71bdf951ec470458 Mon Sep 17 00:00:00 2001
From: Craig Topper <[email protected]>
Date: Fri, 13 Mar 2026 17:41:02 -0700
Subject: [PATCH 2/7] fixup! remove stray change

---
 llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp 
b/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp
index c20a53ccc104c..c75d35feadc01 100644
--- a/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp
+++ b/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp
@@ -2076,7 +2076,7 @@ void TreePatternNode::print(raw_ostream &OS) const {
   for (const ScopedName &Name : NamesAsPredicateArg)
     OS << ":$pred:" << Name.getScope() << ":" << Name.getIdentifier();
 }
-void TreePatternNode::dump() const { print(dbgs()); dbgs() << '\n'; }
+void TreePatternNode::dump() const { print(dbgs()); }
 
 /// isIsomorphicTo - Return true if this node is recursively
 /// isomorphic to the specified node.  For this comparison, the node's

>From d8e858684b1ace0138dc10ffe265487d02b4cab9 Mon Sep 17 00:00:00 2001
From: Craig Topper <[email protected]>
Date: Fri, 20 Mar 2026 15:36:12 -0700
Subject: [PATCH 3/7] fixup! bump to version 0.20 and update the doc link

---
 clang/test/Driver/print-supported-extensions-riscv.c |  2 +-
 clang/test/Preprocessor/riscv-target-features.c      | 10 ++++++++++
 llvm/docs/RISCVUsage.rst                             |  2 +-
 llvm/lib/Target/RISCV/RISCVFeatures.td               |  2 +-
 llvm/test/CodeGen/RISCV/attributes.ll                |  2 +-
 llvm/test/MC/RISCV/attribute-arch.s                  |  8 ++++----
 6 files changed, 18 insertions(+), 8 deletions(-)

diff --git a/clang/test/Driver/print-supported-extensions-riscv.c 
b/clang/test/Driver/print-supported-extensions-riscv.c
index b0e82b08f07e0..f9d1bfa2c2059 100644
--- a/clang/test/Driver/print-supported-extensions-riscv.c
+++ b/clang/test/Driver/print-supported-extensions-riscv.c
@@ -241,7 +241,7 @@
 // CHECK-NEXT:     xwchc                2.2       'Xwchc' (WCH/QingKe 
additional compressed opcodes)
 // CHECK-EMPTY:
 // CHECK-NEXT: Experimental extensions
-// CHECK-NEXT:     p                    0.19      'P' ('Base P' (Packed SIMD))
+// CHECK-NEXT:     p                    0.20      'P' ('Base P' (Packed SIMD))
 // CHECK-NEXT:     y                    0.96      'Y' ('Base Y' (CHERI))
 // CHECK-NEXT:     zibi                 0.1       'Zibi' (Branch with 
Immediate)
 // CHECK-NEXT:     zicfilp              1.0       'Zicfilp' (Landing pad)
diff --git a/clang/test/Preprocessor/riscv-target-features.c 
b/clang/test/Preprocessor/riscv-target-features.c
index 863ff3f08a9ea..1c8018c57ece2 100644
--- a/clang/test/Preprocessor/riscv-target-features.c
+++ b/clang/test/Preprocessor/riscv-target-features.c
@@ -180,6 +180,7 @@
 
 // Experimental extensions
 
+// CHECK-NOT: __riscv_p {{.*$}}
 // CHECK-NOT: __riscv_zicfilp {{.*$}}
 // CHECK-NOT: __riscv_zicfiss {{.*$}}
 // CHECK-NOT: __riscv_zvbc32e {{.*$}}
@@ -1583,6 +1584,15 @@
 // CHECK-ZVKT-EXT: __riscv_zvkt 1000000{{$}}
 
 // Experimental extensions
+
+// RUN: %clang --target=riscv32 -menable-experimental-extensions \
+// RUN:   -march=rv32i_p0p20 -E -dM %s \
+// RUN:   -o - | FileCheck --check-prefix=CHECK-P-EXT %s
+// RUN: %clang --target=riscv64 -menable-experimental-extensions \
+// RUN:   -march=rv64i_p0p20 -E -dM %s \
+// RUN:   -o - | FileCheck --check-prefix=CHECK-P-EXT %s
+// CHECK-P-EXT: __riscv_p 20000{{$}}
+//
 // RUN: %clang --target=riscv32 -menable-experimental-extensions \
 // RUN:   -march=rv32izfbfmin1p0 -E -dM %s \
 // RUN:   -o - | FileCheck --check-prefix=CHECK-ZFBFMIN-EXT %s
diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst
index d1befbd645900..23ea436c51048 100644
--- a/llvm/docs/RISCVUsage.rst
+++ b/llvm/docs/RISCVUsage.rst
@@ -336,7 +336,7 @@ LLVM supports (to various degrees) a number of experimental 
extensions.  All exp
 The primary goal of experimental support is to assist in the process of 
ratification by providing an existence proof of an implementation, and 
simplifying efforts to validate the value of a proposed extension against large 
code bases.  Experimental extensions are expected to either transition to 
ratified status, or be eventually removed.  The decision on whether to accept 
an experimental extension is currently done on an entirely case by case basis; 
if you want to propose one, attending the bi-weekly RISC-V sync-up call is 
strongly advised.
 
 ``experimental-p``
-  LLVM implements the `019 draft specification 
<https://www.jhauser.us/RISCV/ext-P/>`__.
+  LLVM implements the `0.20 draft specification 
<https://github.com/riscv/riscv-p-spec/blob/master/P-ext-proposal.adoc>`__.
 
 ``experimental-zibi``
   LLVM implements the `0.1 release specification 
<https://github.com/riscv/zibi/releases/tag/v0.1.0>`__.
diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td 
b/llvm/lib/Target/RISCV/RISCVFeatures.td
index 356e742dbbec9..d2d36a2a234d9 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -1114,7 +1114,7 @@ def HasStdExtSmctrOrSsctr : 
Predicate<"Subtarget->hasStdExtSmctrOrSsctr()">,
 
 // Packed SIMD Extensions
 def FeatureStdExtP
-    : RISCVExperimentalExtension<0, 19,
+    : RISCVExperimentalExtension<0, 20,
                                  "'Base P' (Packed SIMD)",
                                  [FeatureStdExtZmmul, FeatureStdExtZba,
                                   FeatureStdExtZbb, FeatureStdExtZicsr]>;
diff --git a/llvm/test/CodeGen/RISCV/attributes.ll 
b/llvm/test/CodeGen/RISCV/attributes.ll
index 3cac9c56503a9..2f0e35d339f01 100644
--- a/llvm/test/CodeGen/RISCV/attributes.ll
+++ b/llvm/test/CodeGen/RISCV/attributes.ll
@@ -626,7 +626,7 @@
 ; RV64SSCTR: .attribute 5, "rv64i2p1_sscsrind1p0_ssctr1p0"
 ; RV64SDEXT: .attribute 5, "rv64i2p1_sdext1p0"
 ; RV64SDTRIG: .attribute 5, "rv64i2p1_sdtrig1p0"
-; RV64P: .attribute 5, "rv64i2p1_p0p19_zicsr2p0_zmmul1p0_zba1p0_zbb1p0"
+; RV64P: .attribute 5, "rv64i2p1_p0p20_zicsr2p0_zmmul1p0_zba1p0_zbb1p0"
 ; RV64Y: .attribute 5, "rv64i2p1_y0p96"
 ; RV64ZIBI: .attribute 5, "rv64i2p1_zibi0p1"
 
diff --git a/llvm/test/MC/RISCV/attribute-arch.s 
b/llvm/test/MC/RISCV/attribute-arch.s
index 1ad595b28efaa..7d49558295cb3 100644
--- a/llvm/test/MC/RISCV/attribute-arch.s
+++ b/llvm/test/MC/RISCV/attribute-arch.s
@@ -510,8 +510,8 @@
 .attribute arch, "rv32i_sdtrig1p0"
 # CHECK: attribute      5, "rv32i2p1_sdtrig1p0"
 
-.attribute arch, "rv32i_p0p19"
-# CHECK: attribute      5, "rv32i2p1_p0p19_zicsr2p0_zmmul1p0_zba1p0_zbb1p0"
+.attribute arch, "rv32i_p0p20"
+# CHECK: attribute      5, "rv32i2p1_p0p20_zicsr2p0_zmmul1p0_zba1p0_zbb1p0"
 
-.attribute arch, "rv64i_p0p19"
-# CHECK: attribute      5, "rv64i2p1_p0p19_zicsr2p0_zmmul1p0_zba1p0_zbb1p0"
+.attribute arch, "rv64i_p0p20"
+# CHECK: attribute      5, "rv64i2p1_p0p20_zicsr2p0_zmmul1p0_zba1p0_zbb1p0"

>From 0bbd98b0717f79ec1d433927db1cd3dac00b898c Mon Sep 17 00:00:00 2001
From: Craig Topper <[email protected]>
Date: Fri, 20 Mar 2026 15:42:09 -0700
Subject: [PATCH 4/7] fixup! release notes

---
 llvm/docs/ReleaseNotes.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 2053e087ba23e..34cd0b4682267 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -149,7 +149,7 @@ Changes to the RISC-V Backend
 
 * `llvm-objdump` now has support for `--symbolize-operands` with RISC-V.
 * `-mcpu=spacemit-x100` was added.
-* Change P extension version to match the 019 draft specification. Encoded in 
`-march` as `0p19`.
+* Change P extension version to match the 0.20 draft specification.
 * Mnemonics for MOP/HINT-based instructions (`lpad`, `pause`, `ntl.*`, 
`c.ntl.*`,
   `sspush`, `sspopchk`, `ssrdp`, `c.sspush`, `c.sspopchk`) are now always
   available in the assembler and disassembler without requiring their 
respective

>From 4a118b308869e6e3bbcef508e5843f8a21589198 Mon Sep 17 00:00:00 2001
From: Craig Topper <[email protected]>
Date: Fri, 20 Mar 2026 17:18:11 -0700
Subject: [PATCH 5/7] fixup! update RISCVISAInfoTest.cpp

---
 llvm/unittests/TargetParser/RISCVISAInfoTest.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp 
b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
index 89efc4734f35b..38efdb87ee88a 100644
--- a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
+++ b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
@@ -1372,7 +1372,7 @@ R"(All available -march extensions for RISC-V
     xwchc                2.2
 
 Experimental extensions
-    p                    0.19
+    p                    0.20
     y                    0.96
     zibi                 0.1
     zicfilp              1.0       This is a long dummy description

>From 116c5f99bf014a6f36a938a62bf01004581ee5a0 Mon Sep 17 00:00:00 2001
From: Craig Topper <[email protected]>
Date: Mon, 23 Mar 2026 13:15:30 -0700
Subject: [PATCH 6/7] [RISCV] Update P extension to 0.21

Add the new shift and pnclip instructions.

Spec PR https://github.com/riscv/riscv-p-spec/pull/237
---
 .../Driver/print-supported-extensions-riscv.c |  2 +-
 .../test/Preprocessor/riscv-target-features.c |  6 +-
 llvm/docs/RISCVUsage.rst                      |  2 +-
 llvm/lib/Target/RISCV/RISCVFeatures.td        |  2 +-
 llvm/lib/Target/RISCV/RISCVInstrInfoP.td      | 70 +++++++++++++++----
 llvm/test/CodeGen/RISCV/attributes.ll         |  2 +-
 llvm/test/MC/RISCV/attribute-arch.s           |  8 +--
 llvm/test/MC/RISCV/rv32p-valid.s              | 24 +++++++
 llvm/test/MC/RISCV/rv64p-valid.s              | 36 ++++++++++
 .../TargetParser/RISCVISAInfoTest.cpp         |  2 +-
 10 files changed, 129 insertions(+), 25 deletions(-)

diff --git a/clang/test/Driver/print-supported-extensions-riscv.c 
b/clang/test/Driver/print-supported-extensions-riscv.c
index f9d1bfa2c2059..430f4e43dfafc 100644
--- a/clang/test/Driver/print-supported-extensions-riscv.c
+++ b/clang/test/Driver/print-supported-extensions-riscv.c
@@ -241,7 +241,7 @@
 // CHECK-NEXT:     xwchc                2.2       'Xwchc' (WCH/QingKe 
additional compressed opcodes)
 // CHECK-EMPTY:
 // CHECK-NEXT: Experimental extensions
-// CHECK-NEXT:     p                    0.20      'P' ('Base P' (Packed SIMD))
+// CHECK-NEXT:     p                    0.21      'P' ('Base P' (Packed SIMD))
 // CHECK-NEXT:     y                    0.96      'Y' ('Base Y' (CHERI))
 // CHECK-NEXT:     zibi                 0.1       'Zibi' (Branch with 
Immediate)
 // CHECK-NEXT:     zicfilp              1.0       'Zicfilp' (Landing pad)
diff --git a/clang/test/Preprocessor/riscv-target-features.c 
b/clang/test/Preprocessor/riscv-target-features.c
index 1c8018c57ece2..3882f2889eb59 100644
--- a/clang/test/Preprocessor/riscv-target-features.c
+++ b/clang/test/Preprocessor/riscv-target-features.c
@@ -1586,12 +1586,12 @@
 // Experimental extensions
 
 // RUN: %clang --target=riscv32 -menable-experimental-extensions \
-// RUN:   -march=rv32i_p0p20 -E -dM %s \
+// RUN:   -march=rv32i_p0p21 -E -dM %s \
 // RUN:   -o - | FileCheck --check-prefix=CHECK-P-EXT %s
 // RUN: %clang --target=riscv64 -menable-experimental-extensions \
-// RUN:   -march=rv64i_p0p20 -E -dM %s \
+// RUN:   -march=rv64i_p0p21 -E -dM %s \
 // RUN:   -o - | FileCheck --check-prefix=CHECK-P-EXT %s
-// CHECK-P-EXT: __riscv_p 20000{{$}}
+// CHECK-P-EXT: __riscv_p 21000{{$}}
 //
 // RUN: %clang --target=riscv32 -menable-experimental-extensions \
 // RUN:   -march=rv32izfbfmin1p0 -E -dM %s \
diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst
index 23ea436c51048..57bf6fc57bbc0 100644
--- a/llvm/docs/RISCVUsage.rst
+++ b/llvm/docs/RISCVUsage.rst
@@ -336,7 +336,7 @@ LLVM supports (to various degrees) a number of experimental 
extensions.  All exp
 The primary goal of experimental support is to assist in the process of 
ratification by providing an existence proof of an implementation, and 
simplifying efforts to validate the value of a proposed extension against large 
code bases.  Experimental extensions are expected to either transition to 
ratified status, or be eventually removed.  The decision on whether to accept 
an experimental extension is currently done on an entirely case by case basis; 
if you want to propose one, attending the bi-weekly RISC-V sync-up call is 
strongly advised.
 
 ``experimental-p``
-  LLVM implements the `0.20 draft specification 
<https://github.com/riscv/riscv-p-spec/blob/master/P-ext-proposal.adoc>`__.
+  LLVM implements the `0.21 draft specification 
<https://github.com/riscv/riscv-p-spec/blob/master/P-ext-proposal.adoc>`__.
 
 ``experimental-zibi``
   LLVM implements the `0.1 release specification 
<https://github.com/riscv/zibi/releases/tag/v0.1.0>`__.
diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td 
b/llvm/lib/Target/RISCV/RISCVFeatures.td
index d2d36a2a234d9..5b1d5a880de17 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -1114,7 +1114,7 @@ def HasStdExtSmctrOrSsctr : 
Predicate<"Subtarget->hasStdExtSmctrOrSsctr()">,
 
 // Packed SIMD Extensions
 def FeatureStdExtP
-    : RISCVExperimentalExtension<0, 20,
+    : RISCVExperimentalExtension<0, 21,
                                  "'Base P' (Packed SIMD)",
                                  [FeatureStdExtZmmul, FeatureStdExtZba,
                                   FeatureStdExtZbb, FeatureStdExtZicsr]>;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td 
b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
index 1530061f8c702..5ff030921a9ab 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
@@ -622,6 +622,12 @@ let Predicates = [HasStdExtP] in {
   def PADD_HS   : RVPBinaryScalar_rr<0b001, 0b00, 0b010, "padd.hs">;
   def PADD_BS   : RVPBinaryScalar_rr<0b001, 0b10, 0b010, "padd.bs">;
 
+  let Defs = [VXSAT] in
+  def PSSHL_HS  : RVPBinaryScalar_rr<0b010, 0b00, 0b010, "psshl.hs">;
+
+  let Defs = [VXSAT] in
+  def PSSHLR_HS : RVPBinaryScalar_rr<0b011, 0b00, 0b010, "psshlr.hs">;
+
   let Defs = [VXSAT] in
   def PSSHA_HS  : RVPBinaryScalar_rr<0b110, 0b00, 0b010, "pssha.hs">;
 
@@ -629,6 +635,12 @@ let Predicates = [HasStdExtP] in {
   def PSSHAR_HS : RVPBinaryScalar_rr<0b111, 0b00, 0b010, "psshar.hs">;
 } // Predicates = [HasStdExtP]
 let Predicates = [HasStdExtP, IsRV32], DecoderNamespace = "RV32Only" in {
+  let Defs = [VXSAT] in
+  def SSHL      : RVPBinaryScalar_rr<0b010, 0b01, 0b010, "sshl">;
+
+  let Defs = [VXSAT] in
+  def SSHLR     : RVPBinaryScalar_rr<0b011, 0b01, 0b010, "sshlr">;
+
   let Defs = [VXSAT] in
   def SSHA      : RVPBinaryScalar_rr<0b110, 0b01, 0b010, "ssha">;
 
@@ -640,6 +652,16 @@ let Predicates = [HasStdExtP, IsRV64] in {
 
   def PADD_WS   : RVPBinaryScalar_rr<0b001, 0b01, 0b010, "padd.ws">;
 
+  let Defs = [VXSAT] in {
+  def PSSHL_WS  : RVPBinaryScalar_rr<0b010, 0b01, 0b010, "psshl.ws">;
+  def SHL       : RVPBinaryScalar_rr<0b010, 0b11, 0b010, "shl">;
+  } // Defs = [VXSAT]
+
+  let Defs = [VXSAT] in {
+  def PSSHLR_WS : RVPBinaryScalar_rr<0b011, 0b01, 0b010, "psshlr.ws">;
+  def SHLR      : RVPBinaryScalar_rr<0b011, 0b11, 0b010, "shlr">;
+  } // Defs = [VXSAT]
+
   let Defs = [VXSAT] in {
   def PSSHA_WS  : RVPBinaryScalar_rr<0b110, 0b01, 0b010, "pssha.ws">;
   def SHA       : RVPBinaryScalar_rr<0b110, 0b11, 0b010, "sha">;
@@ -849,30 +871,42 @@ let Predicates = [HasStdExtP, IsRV64] in {
 // Note the spec has a 3-bit f field in bits 30:28 with 0 in bit 27.
 // Here we include the 0 in the f field to reduce number of tablegen classes.
 let Predicates = [HasStdExtP] in {
-  def PSH1ADD_H   : RVPBinary_rr<0b0100, 0b00, 0b010, "psh1add.h">;
+  def PSH1ADD_H    : RVPBinary_rr<0b0100, 0b00, 0b010, "psh1add.h">;
 
   let Defs = [VXSAT] in
-  def PSSH1SADD_H : RVPBinary_rr<0b0110, 0b00, 0b010, "pssh1sadd.h">;
+  def PSSH1SADD_H  : RVPBinary_rr<0b0110, 0b00, 0b010, "pssh1sadd.h">;
 } // Predicates = [HasStdExtP]
 let Predicates = [HasStdExtP, IsRV32], DecoderNamespace = "RV32Only" in {
   let Defs = [VXSAT] in
-  def SSH1SADD    : RVPBinary_rr<0b0110, 0b01, 0b010, "ssh1sadd">;
+  def SSH1SADD     : RVPBinary_rr<0b0110, 0b01, 0b010, "ssh1sadd">;
 } // Predicates = [HasStdExtP, IsRV32], DecoderNamespace = "RV32Only"
 let Predicates = [HasStdExtP, IsRV64] in {
-  def PSH1ADD_W   : RVPBinary_rr<0b0100, 0b01, 0b010, "psh1add.w">;
+  let Defs = [VXSAT] in {
+    def PNCLIPUP_B : RVPBinary_rr<0b0000, 0b00, 0b010, "pnclipup.b">;
+    def PNCLIPUP_H : RVPBinary_rr<0b0000, 0b01, 0b010, "pnclipup.h">;
+    def PNCLIPUP_W : RVPBinary_rr<0b0000, 0b11, 0b010, "pnclipup.w">;
+  }
+
+  def PSH1ADD_W    : RVPBinary_rr<0b0100, 0b01, 0b010, "psh1add.w">;
 
   let Defs = [VXSAT] in
-  def PSSH1SADD_W : RVPBinary_rr<0b0110, 0b01, 0b010, "pssh1sadd.w">;
+  def PSSH1SADD_W  : RVPBinary_rr<0b0110, 0b01, 0b010, "pssh1sadd.w">;
+
+  let Defs = [VXSAT] in {
+    def PNCLIPP_B  : RVPBinary_rr<0b1000, 0b00, 0b010, "pnclipp.b">;
+    def PNCLIPP_H  : RVPBinary_rr<0b1000, 0b01, 0b010, "pnclipp.h">;
+    def PNCLIPP_W  : RVPBinary_rr<0b1000, 0b11, 0b010, "pnclipp.w">;
+  }
 
-  def UNZIP8P     : RVPBinary_rr<0b1100, 0b00, 0b010, "unzip8p">;
-  def UNZIP16P    : RVPBinary_rr<0b1100, 0b01, 0b010, "unzip16p">;
-  def UNZIP8HP    : RVPBinary_rr<0b1100, 0b10, 0b010, "unzip8hp">;
-  def UNZIP16HP   : RVPBinary_rr<0b1100, 0b11, 0b010, "unzip16hp">;
+  def UNZIP8P      : RVPBinary_rr<0b1100, 0b00, 0b010, "unzip8p">;
+  def UNZIP16P     : RVPBinary_rr<0b1100, 0b01, 0b010, "unzip16p">;
+  def UNZIP8HP     : RVPBinary_rr<0b1100, 0b10, 0b010, "unzip8hp">;
+  def UNZIP16HP    : RVPBinary_rr<0b1100, 0b11, 0b010, "unzip16hp">;
 
-  def ZIP8P       : RVPBinary_rr<0b1110, 0b00, 0b010, "zip8p">;
-  def ZIP16P      : RVPBinary_rr<0b1110, 0b01, 0b010, "zip16p">;
-  def ZIP8HP      : RVPBinary_rr<0b1110, 0b10, 0b010, "zip8hp">;
-  def ZIP16HP     : RVPBinary_rr<0b1110, 0b11, 0b010, "zip16hp">;
+  def ZIP8P        : RVPBinary_rr<0b1110, 0b00, 0b010, "zip8p">;
+  def ZIP16P       : RVPBinary_rr<0b1110, 0b01, 0b010, "zip16p">;
+  def ZIP8HP       : RVPBinary_rr<0b1110, 0b10, 0b010, "zip8hp">;
+  def ZIP16HP      : RVPBinary_rr<0b1110, 0b11, 0b010, "zip16hp">;
 } // Predicates = [HasStdExtP, IsRV64]
 
 let Predicates = [HasStdExtP] in {
@@ -1477,6 +1511,16 @@ let Predicates = [HasStdExtP, IsRV32] in {
   def PADD_DWS     : RVPPairShift_rr<0b001, 0b01, "padd.dws">;
   def PADD_DBS     : RVPPairShift_rr<0b001, 0b10, "padd.dbs">;
 
+  let Defs = [VXSAT] in {
+  def PSSHL_DHS    : RVPPairShift_rr<0b010, 0b00, "psshl.dhs">;
+  def PSSHL_DWS    : RVPPairShift_rr<0b010, 0b01, "psshl.dws">;
+  } // Defs = [VXSAT]
+
+  let Defs = [VXSAT] in {
+  def PSSHLR_DHS   : RVPPairShift_rr<0b011, 0b00, "psshlr.dhs">;
+  def PSSHLR_DWS   : RVPPairShift_rr<0b011, 0b01, "psshlr.dws">;
+  } // Defs = [VXSAT]
+
   let Defs = [VXSAT] in {
   def PSSHA_DHS    : RVPPairShift_rr<0b110, 0b00, "pssha.dhs">;
   def PSSHA_DWS    : RVPPairShift_rr<0b110, 0b01, "pssha.dws">;
diff --git a/llvm/test/CodeGen/RISCV/attributes.ll 
b/llvm/test/CodeGen/RISCV/attributes.ll
index 2f0e35d339f01..311418fc845ab 100644
--- a/llvm/test/CodeGen/RISCV/attributes.ll
+++ b/llvm/test/CodeGen/RISCV/attributes.ll
@@ -626,7 +626,7 @@
 ; RV64SSCTR: .attribute 5, "rv64i2p1_sscsrind1p0_ssctr1p0"
 ; RV64SDEXT: .attribute 5, "rv64i2p1_sdext1p0"
 ; RV64SDTRIG: .attribute 5, "rv64i2p1_sdtrig1p0"
-; RV64P: .attribute 5, "rv64i2p1_p0p20_zicsr2p0_zmmul1p0_zba1p0_zbb1p0"
+; RV64P: .attribute 5, "rv64i2p1_p0p21_zicsr2p0_zmmul1p0_zba1p0_zbb1p0"
 ; RV64Y: .attribute 5, "rv64i2p1_y0p96"
 ; RV64ZIBI: .attribute 5, "rv64i2p1_zibi0p1"
 
diff --git a/llvm/test/MC/RISCV/attribute-arch.s 
b/llvm/test/MC/RISCV/attribute-arch.s
index 7d49558295cb3..241fac8f2bd17 100644
--- a/llvm/test/MC/RISCV/attribute-arch.s
+++ b/llvm/test/MC/RISCV/attribute-arch.s
@@ -510,8 +510,8 @@
 .attribute arch, "rv32i_sdtrig1p0"
 # CHECK: attribute      5, "rv32i2p1_sdtrig1p0"
 
-.attribute arch, "rv32i_p0p20"
-# CHECK: attribute      5, "rv32i2p1_p0p20_zicsr2p0_zmmul1p0_zba1p0_zbb1p0"
+.attribute arch, "rv32i_p0p21"
+# CHECK: attribute      5, "rv32i2p1_p0p21_zicsr2p0_zmmul1p0_zba1p0_zbb1p0"
 
-.attribute arch, "rv64i_p0p20"
-# CHECK: attribute      5, "rv64i2p1_p0p20_zicsr2p0_zmmul1p0_zba1p0_zbb1p0"
+.attribute arch, "rv64i_p0p21"
+# CHECK: attribute      5, "rv64i2p1_p0p21_zicsr2p0_zmmul1p0_zba1p0_zbb1p0"
diff --git a/llvm/test/MC/RISCV/rv32p-valid.s b/llvm/test/MC/RISCV/rv32p-valid.s
index 9729fd6610147..70dae5b5cd81e 100644
--- a/llvm/test/MC/RISCV/rv32p-valid.s
+++ b/llvm/test/MC/RISCV/rv32p-valid.s
@@ -73,6 +73,18 @@ padd.hs t0, t1, t2
 # CHECK-ASM-AND-OBJ: padd.bs ra, a1, a2
 # CHECK-ASM: encoding: [0x9b,0xa0,0xc5,0x9c]
 padd.bs ra, a1, a2
+# CHECK-ASM-AND-OBJ: psshl.hs a3, a4, a5
+# CHECK-ASM: encoding: [0x9b,0x26,0xf7,0xa8]
+psshl.hs a3, a4, a5
+# CHECK-ASM-AND-OBJ: sshl gp, a4, a5
+# CHECK-ASM: encoding: [0x9b,0x21,0xf7,0xaa]
+sshl gp, a4, a5
+# CHECK-ASM-AND-OBJ: psshlr.hs a6, a7, a0
+# CHECK-ASM: encoding: [0x1b,0xa8,0xa8,0xb8]
+psshlr.hs a6, a7, a0
+# CHECK-ASM-AND-OBJ: sshlr t1, a7, a0
+# CHECK-ASM: encoding: [0x1b,0xa3,0xa8,0xba]
+sshlr t1, a7, a0
 # CHECK-ASM-AND-OBJ: pssha.hs a3, a4, a5
 # CHECK-ASM: encoding: [0x9b,0x26,0xf7,0xe8]
 pssha.hs a3, a4, a5
@@ -1065,6 +1077,18 @@ psshar.dhs a2, a4, t3
 # CHECK-ASM-AND-OBJ: psshar.dws s0, t3, s0
 # CHECK-ASM: encoding: [0x1b,0x64,0x8e,0x7a]
 psshar.dws s0, t3, s0
+# CHECK-ASM-AND-OBJ: psshl.dhs a0, s0, s2
+# CHECK-ASM: encoding: [0x1b,0x65,0x24,0x29]
+psshl.dhs a0, s0, s2
+# CHECK-ASM-AND-OBJ: psshl.dws a0, t1, s2
+# CHECK-ASM: encoding: [0x1b,0x65,0x23,0x2b]
+psshl.dws a0, t1, s2
+# CHECK-ASM-AND-OBJ: psshlr.dhs a2, a4, t3
+# CHECK-ASM: encoding: [0x1b,0x66,0xc7,0x39]
+psshlr.dhs a2, a4, t3
+# CHECK-ASM-AND-OBJ: psshlr.dws s0, t3, s0
+# CHECK-ASM: encoding: [0x1b,0x64,0x8e,0x3a]
+psshlr.dws s0, t3, s0
 # CHECK-ASM-AND-OBJ: psrli.db t5, a2, 0
 # CHECK-ASM: encoding: [0x1b,0xef,0x86,0x00]
 psrli.db t5, a2, 0
diff --git a/llvm/test/MC/RISCV/rv64p-valid.s b/llvm/test/MC/RISCV/rv64p-valid.s
index 7d91057327117..755b0524b604e 100644
--- a/llvm/test/MC/RISCV/rv64p-valid.s
+++ b/llvm/test/MC/RISCV/rv64p-valid.s
@@ -100,6 +100,12 @@ padd.hs t1, a2, s0
 # CHECK-ASM-AND-OBJ: padd.bs t3, t1, t3
 # CHECK-ASM: encoding: [0x1b,0x2e,0xc3,0x9d]
 padd.bs t3, t1, t3
+# CHECK-ASM-AND-OBJ: psshl.hs a3, a4, a5
+# CHECK-ASM: encoding: [0x9b,0x26,0xf7,0xa8]
+psshl.hs a3, a4, a5
+# CHECK-ASM-AND-OBJ: psshlr.hs a6, a7, a0
+# CHECK-ASM: encoding: [0x1b,0xa8,0xa8,0xb8]
+psshlr.hs a6, a7, a0
 # CHECK-ASM-AND-OBJ: pssha.hs s0, t1, a2
 # CHECK-ASM: encoding: [0x1b,0x24,0xc3,0xe8]
 pssha.hs s0, t1, a2
@@ -112,12 +118,24 @@ psll.ws s0, t1, a0
 # CHECK-ASM-AND-OBJ: padd.ws s2, a2, a0
 # CHECK-ASM: encoding: [0x1b,0x29,0xa6,0x9a]
 padd.ws s2, a2, a0
+# CHECK-ASM-AND-OBJ: psshl.ws a3, a4, a5
+# CHECK-ASM: encoding: [0x9b,0x26,0xf7,0xaa]
+psshl.ws a3, a4, a5
+# CHECK-ASM-AND-OBJ: psshlr.ws a6, a7, a0
+# CHECK-ASM: encoding: [0x1b,0xa8,0xa8,0xba]
+psshlr.ws a6, a7, a0
 # CHECK-ASM-AND-OBJ: pssha.ws a4, a2, t1
 # CHECK-ASM: encoding: [0x1b,0x27,0x66,0xea]
 pssha.ws a4, a2, t1
 # CHECK-ASM-AND-OBJ: psshar.ws a2, a0, a4
 # CHECK-ASM: encoding: [0x1b,0x26,0xe5,0xfa]
 psshar.ws a2, a0, a4
+# CHECK-ASM-AND-OBJ: shl gp, a4, a5
+# CHECK-ASM: encoding: [0x9b,0x21,0xf7,0xae]
+shl gp, a4, a5
+# CHECK-ASM-AND-OBJ: shlr t1, a7, a0
+# CHECK-ASM: encoding: [0x1b,0xa3,0xa8,0xbe]
+shlr t1, a7, a0
 # CHECK-ASM-AND-OBJ: sha a0, t5, t5
 # CHECK-ASM: encoding: [0x1b,0x25,0xef,0xef]
 sha a0, t5, t5
@@ -358,6 +376,15 @@ pabdsumau.b s2, a2, a0
 # CHECK-ASM-AND-OBJ: maccu.w01 a0, a0, t1
 # CHECK-ASM: encoding: [0x3b,0x15,0x65,0xbe]
 maccu.w01 a0, a0, t1
+# CHECK-ASM-AND-OBJ: pnclipup.b a0, a1, a2
+# CHECK-ASM: encoding: [0x3b,0xa5,0xc5,0x80]
+pnclipup.b a0, a1, a2
+# CHECK-ASM-AND-OBJ: pnclipup.h a3, a4, a5
+# CHECK-ASM: encoding: [0xbb,0x26,0xf7,0x82]
+pnclipup.h a3, a4, a5
+# CHECK-ASM-AND-OBJ: pnclipup.w a6, a7, s0
+# CHECK-ASM: encoding: [0x3b,0xa8,0x88,0x86]
+pnclipup.w a6, a7, s0
 # CHECK-ASM-AND-OBJ: psh1add.h a2, a2, t3
 # CHECK-ASM: encoding: [0x3b,0x26,0xc6,0xa1]
 psh1add.h a2, a2, t3
@@ -370,6 +397,15 @@ psh1add.w s2, t5, a2
 # CHECK-ASM-AND-OBJ: pssh1sadd.w a4, t3, s0
 # CHECK-ASM: encoding: [0x3b,0x27,0x8e,0xb2]
 pssh1sadd.w a4, t3, s0
+# CHECK-ASM-AND-OBJ: pnclipp.b s1, s2, s3
+# CHECK-ASM: encoding: [0xbb,0x24,0x39,0xc1]
+pnclipp.b s1, s2, s3
+# CHECK-ASM-AND-OBJ: pnclipp.h s4, s5, s6
+# CHECK-ASM: encoding: [0x3b,0xaa,0x6a,0xc3]
+pnclipp.h s4, s5, s6
+# CHECK-ASM-AND-OBJ: pnclipp.w s7, s8, s9
+# CHECK-ASM: encoding: [0xbb,0x2b,0x9c,0xc7]
+pnclipp.w s7, s8, s9
 # CHECK-ASM-AND-OBJ: unzip8p a4, t3, t1
 # CHECK-ASM: encoding: [0x3b,0x27,0x6e,0xe0]
 unzip8p a4, t3, t1
diff --git a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp 
b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
index 38efdb87ee88a..336c4d355ece9 100644
--- a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
+++ b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
@@ -1372,7 +1372,7 @@ R"(All available -march extensions for RISC-V
     xwchc                2.2
 
 Experimental extensions
-    p                    0.20
+    p                    0.21
     y                    0.96
     zibi                 0.1
     zicfilp              1.0       This is a long dummy description

>From dc4d9ad27e8349c79807970dde5fef566f8dccd4 Mon Sep 17 00:00:00 2001
From: Craig Topper <[email protected]>
Date: Mon, 23 Mar 2026 19:38:41 -0700
Subject: [PATCH 7/7] Update llvm/docs/ReleaseNotes.md

Co-authored-by: Kito Cheng <[email protected]>
---
 llvm/docs/ReleaseNotes.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 34cd0b4682267..d79d5e1a1d909 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -149,7 +149,7 @@ Changes to the RISC-V Backend
 
 * `llvm-objdump` now has support for `--symbolize-operands` with RISC-V.
 * `-mcpu=spacemit-x100` was added.
-* Change P extension version to match the 0.20 draft specification.
+* Change P extension version to match the 0.21 draft specification.
 * Mnemonics for MOP/HINT-based instructions (`lpad`, `pause`, `ntl.*`, 
`c.ntl.*`,
   `sspush`, `sspopchk`, `ssrdp`, `c.sspush`, `c.sspopchk`) are now always
   available in the assembler and disassembler without requiring their 
respective

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to