[llvm] [RISCV] Use `experimental-p` extension for zero-extended narrow unsigned types (PR #213260)

Rajveer Singh Bharadwaj via llvm-commits llvm-commits at lists.llvm.org
Sun Aug 2 05:49:58 PDT 2026


https://github.com/Rajveer100 updated https://github.com/llvm/llvm-project/pull/213260

>From 5298ce2aeb0b88e93de4442e578ba5f5ddc22a3a Mon Sep 17 00:00:00 2001
From: Rajveer <rajveer.developer at icloud.com>
Date: Fri, 31 Jul 2026 17:41:45 +0530
Subject: [PATCH] [RISCV] Use `experimental-p` extension for zero-extended
 narrow unsigned types

Resolves #211361

The bits `31:8` remain zero after packed addition due to `padd.b`
carry-out as per ABI, hence we can generate more optimised code instead
of `zext.b` + `add`.
---
 llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp   | 26 ++++++++++++++++++
 ...-p-extension-narrow-unsigned-arithmetic.ll | 27 +++++++++++++++++++
 2 files changed, 53 insertions(+)
 create mode 100644 llvm/test/CodeGen/RISCV/experimental-p-extension-narrow-unsigned-arithmetic.ll

diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
index f36f27769a353..921c5e1eff79c 100644
--- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
@@ -1816,6 +1816,32 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
     if (tryShrinkShlLogicImm(Node))
       return;
 
+    if (Subtarget->hasStdExtP()) {
+      if (N0->getOpcode() == ISD::ADD) {
+        SDValue AddN0 = N0->getOperand(0);
+        SDValue AddN1 = N0.getOperand(1);
+
+        EVT ValTyN0 = AddN0.getValueType(), ValTyN1 = AddN1.getValueType();
+        if (AddN0.getOpcode() == ISD::AssertZext &&
+            AddN1.getOpcode() == ISD::AssertZext && ValTyN0 == ValTyN1) {
+
+          if (N1C->getZExtValue() == ((1 << 8) - 1)) {
+            SDNode *PADDB = CurDAG->getMachineNode(RISCV::PADD_B, DL, ValTyN0,
+                                                   AddN0, AddN1);
+            ReplaceNode(Node, PADDB);
+            return;
+          }
+
+          if (N1C->getZExtValue() == ((1 << 16) - 1)) {
+            SDNode *PADDH = CurDAG->getMachineNode(RISCV::PADD_H, DL, ValTyN0,
+                                                   AddN0, AddN1);
+            ReplaceNode(Node, PADDH);
+            return;
+          }
+        }
+      }
+    }
+
     break;
   }
   case ISD::MUL: {
diff --git a/llvm/test/CodeGen/RISCV/experimental-p-extension-narrow-unsigned-arithmetic.ll b/llvm/test/CodeGen/RISCV/experimental-p-extension-narrow-unsigned-arithmetic.ll
new file mode 100644
index 0000000000000..7009587a22164
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/experimental-p-extension-narrow-unsigned-arithmetic.ll
@@ -0,0 +1,27 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-p \
+; RUN:   -verify-machineinstrs < %s | \
+; RUN:   FileCheck --check-prefixes=CHECK,RV32 %s
+
+define zeroext i8 @zexti8_paddb(i8 zeroext %x, i8 zeroext %y) {
+; CHECK-LABEL: zexti8_paddb:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    padd.b a0, a1, a0
+; CHECK-NEXT:    ret
+entry:
+  %add = add i8 %y, %x
+  ret i8 %add
+}
+
+define zeroext i16 @zexti16_paddh(i16 zeroext %x, i16 zeroext %y) {
+; CHECK-LABEL: zexti16_paddh:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    padd.h a0, a1, a0
+; CHECK-NEXT:    ret
+entry:
+  %add = add i16 %y, %x
+  ret i16 %add
+}
+
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; RV32: {{.*}}



More information about the llvm-commits mailing list