Skip to content

Conversation

@pfusik
Copy link
Contributor

@pfusik pfusik commented Dec 4, 2025

Similar transforms with "pack" and "packw" are not useful:
(pack zero, X) == (slli X, XLEN/2)
(packw zero, X) == (slliw X, 16)

Similar transforms with "pack" and "packw" are not useful:
(pack  zero, X) == (slli  X, XLEN/2)
(packw zero, X) == (slliw X, 16)
@llvmbot
Copy link
Member

llvmbot commented Dec 4, 2025

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

Author: Piotr Fusik (pfusik)

Changes

Similar transforms with "pack" and "packw" are not useful:
(pack zero, X) == (slli X, XLEN/2)
(packw zero, X) == (slliw X, 16)


Full diff: https://github.com/llvm/llvm-project/pull/170654.diff

4 Files Affected:

  • (modified) llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp (+10-1)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfoZb.td (+3)
  • (modified) llvm/test/CodeGen/RISCV/rv32zbkb.ll (+85)
  • (modified) llvm/test/CodeGen/RISCV/rv64zbkb.ll (+81)
diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
index b92926e63d880..162de7e99ec9e 100644
--- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
@@ -1500,8 +1500,17 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
           if (tryUnsignedBitfieldInsertInZero(Node, DL, VT, X, Msb, Lsb))
             return;
 
-          // (srli (slli c2+c3), c3)
           if (OneUseOrZExtW && !IsCANDI) {
+            // (packh x0, X)
+            if (Subtarget->hasStdExtZbkb() && C1 == 0xff00 && C2 == 8) {
+              SDNode *PACKH = CurDAG->getMachineNode(
+                RISCV::PACKH, DL, VT,
+                CurDAG->getRegister(RISCV::X0, Subtarget->getXLenVT()),
+                X);
+              ReplaceNode(Node, PACKH);
+              return;
+            }
+            // (srli (slli c2+c3), c3)
             SDNode *SLLI = CurDAG->getMachineNode(
                 RISCV::SLLI, DL, VT, X,
                 CurDAG->getTargetConstant(C2 + Leading, DL, VT));
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td
index 5429c2a1a21b0..443173b997a28 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td
@@ -652,6 +652,9 @@ def : Pat<(and (or (shl GPR:$rs2, (XLenVT 8)),
 def : Pat<(binop_allhusers<or> (shl GPR:$rs2, (XLenVT 8)),
                                zexti8:$rs1),
           (PACKH zexti8:$rs1, GPR:$rs2)>;
+
+def : Pat<(shl (and GPR:$rs2, 0xFF), (XLenVT 8)),
+          (PACKH (XLenVT X0), GPR:$rs2)>;
 } // Predicates = [HasStdExtZbkb]
 
 let Predicates = [HasStdExtZbkb, IsRV32] in {
diff --git a/llvm/test/CodeGen/RISCV/rv32zbkb.ll b/llvm/test/CodeGen/RISCV/rv32zbkb.ll
index 42d326e359d9f..a0d5d26143c35 100644
--- a/llvm/test/CodeGen/RISCV/rv32zbkb.ll
+++ b/llvm/test/CodeGen/RISCV/rv32zbkb.ll
@@ -458,3 +458,88 @@ define i32 @pack_lo_noext_hi_packh_nozeroext(i32 %a, i8 %1, i8 %2) nounwind {
   %g = or i32 %f, %a
   ret i32 %g
 }
+
+define i32 @packh_zero_i32(i32 %a) nounwind {
+; RV32I-LABEL: packh_zero_i32:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    slli a0, a0, 24
+; RV32I-NEXT:    srli a0, a0, 16
+; RV32I-NEXT:    ret
+;
+; RV32ZBKB-LABEL: packh_zero_i32:
+; RV32ZBKB:       # %bb.0:
+; RV32ZBKB-NEXT:    packh a0, zero, a0
+; RV32ZBKB-NEXT:    ret
+  %shl = shl i32 %a, 8
+  %and = and i32 %shl, 65280
+  ret i32 %and
+}
+
+define i32 @packh_zero_i32_2(i32 %a) nounwind {
+; RV32I-LABEL: packh_zero_i32_2:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    zext.b a0, a0
+; RV32I-NEXT:    slli a0, a0, 8
+; RV32I-NEXT:    ret
+;
+; RV32ZBKB-LABEL: packh_zero_i32_2:
+; RV32ZBKB:       # %bb.0:
+; RV32ZBKB-NEXT:    packh a0, zero, a0
+; RV32ZBKB-NEXT:    ret
+  %and = and i32 %a, 255
+  %shl = shl i32 %and, 8
+  ret i32 %shl
+}
+
+define i64 @packh_zero_i64(i64 %a) nounwind {
+; RV32I-LABEL: packh_zero_i64:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    slli a0, a0, 24
+; RV32I-NEXT:    srli a0, a0, 16
+; RV32I-NEXT:    li a1, 0
+; RV32I-NEXT:    ret
+;
+; RV32ZBKB-LABEL: packh_zero_i64:
+; RV32ZBKB:       # %bb.0:
+; RV32ZBKB-NEXT:    packh a0, zero, a0
+; RV32ZBKB-NEXT:    li a1, 0
+; RV32ZBKB-NEXT:    ret
+  %shl = shl i64 %a, 8
+  %and = and i64 %shl, 65280
+  ret i64 %and
+}
+
+define i64 @packh_zero_i64_2(i64 %a) nounwind {
+; RV32I-LABEL: packh_zero_i64_2:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    zext.b a0, a0
+; RV32I-NEXT:    slli a0, a0, 8
+; RV32I-NEXT:    li a1, 0
+; RV32I-NEXT:    ret
+;
+; RV32ZBKB-LABEL: packh_zero_i64_2:
+; RV32ZBKB:       # %bb.0:
+; RV32ZBKB-NEXT:    packh a0, zero, a0
+; RV32ZBKB-NEXT:    li a1, 0
+; RV32ZBKB-NEXT:    ret
+  %and = and i64 %a, 255
+  %shl = shl i64 %and, 8
+  ret i64 %shl
+}
+
+define i32 @packh_zero_i8(i8 %a) nounwind {
+; RV32I-LABEL: packh_zero_i8:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    zext.b a0, a0
+; RV32I-NEXT:    slli a0, a0, 8
+; RV32I-NEXT:    ret
+;
+; RV32ZBKB-LABEL: packh_zero_i8:
+; RV32ZBKB:       # %bb.0:
+; RV32ZBKB-NEXT:    packh a0, zero, a0
+; RV32ZBKB-NEXT:    ret
+  %zext = zext i8 %a to i32
+  %shl = shl i32 %zext, 8
+  %and = and i32 %shl, 65280
+  ret i32 %and
+}
diff --git a/llvm/test/CodeGen/RISCV/rv64zbkb.ll b/llvm/test/CodeGen/RISCV/rv64zbkb.ll
index b2ad8d76ba953..43e4309a858f9 100644
--- a/llvm/test/CodeGen/RISCV/rv64zbkb.ll
+++ b/llvm/test/CodeGen/RISCV/rv64zbkb.ll
@@ -636,3 +636,84 @@ define i64 @pack_i64_lo_noext_hi_packh_nozeroext(i64 %a, i8 %1, i8 %2, ptr %p) n
   %g = or i64 %f, %a
   ret i64 %g
 }
+
+define i32 @packh_zero_i32(i32 %a) nounwind {
+; RV64I-LABEL: packh_zero_i32:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    slli a0, a0, 56
+; RV64I-NEXT:    srli a0, a0, 48
+; RV64I-NEXT:    ret
+;
+; RV64ZBKB-LABEL: packh_zero_i32:
+; RV64ZBKB:       # %bb.0:
+; RV64ZBKB-NEXT:    packh a0, zero, a0
+; RV64ZBKB-NEXT:    ret
+  %shl = shl i32 %a, 8
+  %and = and i32 %shl, 65280
+  ret i32 %and
+}
+
+define i32 @packh_zero_i32_2(i32 %a) nounwind {
+; RV64I-LABEL: packh_zero_i32_2:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    zext.b a0, a0
+; RV64I-NEXT:    slli a0, a0, 8
+; RV64I-NEXT:    ret
+;
+; RV64ZBKB-LABEL: packh_zero_i32_2:
+; RV64ZBKB:       # %bb.0:
+; RV64ZBKB-NEXT:    packh a0, zero, a0
+; RV64ZBKB-NEXT:    ret
+  %and = and i32 %a, 255
+  %shl = shl i32 %and, 8
+  ret i32 %shl
+}
+
+define i64 @packh_zero_i64(i64 %a) nounwind {
+; RV64I-LABEL: packh_zero_i64:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    slli a0, a0, 56
+; RV64I-NEXT:    srli a0, a0, 48
+; RV64I-NEXT:    ret
+;
+; RV64ZBKB-LABEL: packh_zero_i64:
+; RV64ZBKB:       # %bb.0:
+; RV64ZBKB-NEXT:    packh a0, zero, a0
+; RV64ZBKB-NEXT:    ret
+  %shl = shl i64 %a, 8
+  %and = and i64 %shl, 65280
+  ret i64 %and
+}
+
+define i64 @packh_zero_i64_2(i64 %a) nounwind {
+; RV64I-LABEL: packh_zero_i64_2:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    zext.b a0, a0
+; RV64I-NEXT:    slli a0, a0, 8
+; RV64I-NEXT:    ret
+;
+; RV64ZBKB-LABEL: packh_zero_i64_2:
+; RV64ZBKB:       # %bb.0:
+; RV64ZBKB-NEXT:    packh a0, zero, a0
+; RV64ZBKB-NEXT:    ret
+  %and = and i64 %a, 255
+  %shl = shl i64 %and, 8
+  ret i64 %shl
+}
+
+define i32 @packh_zero_i8(i8 %a) nounwind {
+; RV64I-LABEL: packh_zero_i8:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    zext.b a0, a0
+; RV64I-NEXT:    slli a0, a0, 8
+; RV64I-NEXT:    ret
+;
+; RV64ZBKB-LABEL: packh_zero_i8:
+; RV64ZBKB:       # %bb.0:
+; RV64ZBKB-NEXT:    packh a0, zero, a0
+; RV64ZBKB-NEXT:    ret
+  %zext = zext i8 %a to i32
+  %shl = shl i32 %zext, 8
+  %and = and i32 %shl, 65280
+  ret i32 %and
+}

@github-actions
Copy link

github-actions bot commented Dec 4, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

Copy link
Collaborator

@topperc topperc left a comment

Choose a reason for hiding this comment

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

LGTM

@pfusik pfusik merged commit d5072b9 into llvm:main Dec 4, 2025
10 checks passed
honeygoyal pushed a commit to honeygoyal/llvm-project that referenced this pull request Dec 9, 2025
Similar transforms with "pack" and "packw" are not useful:
(pack  zero, X) == (slli  X, XLEN/2)
(packw zero, X) == (slliw X, 16)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants