[llvm] d5072b9 - [RISCV] Select (and (shl X, 8), 0xff00) -> (packh zero, X) (#170654)

via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 4 11:25:20 PST 2025


Author: Piotr Fusik
Date: 2025-12-04T20:25:16+01:00
New Revision: d5072b94ddc0e9311b67fe4742857c7d2f306e9a

URL: https://github.com/llvm/llvm-project/commit/d5072b94ddc0e9311b67fe4742857c7d2f306e9a
DIFF: https://github.com/llvm/llvm-project/commit/d5072b94ddc0e9311b67fe4742857c7d2f306e9a.diff

LOG: [RISCV] Select (and (shl X, 8), 0xff00) -> (packh zero, X) (#170654)

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

Added: 
    

Modified: 
    llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
    llvm/lib/Target/RISCV/RISCVInstrInfoZb.td
    llvm/test/CodeGen/RISCV/rv32zbkb.ll
    llvm/test/CodeGen/RISCV/rv64zbkb.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
index b92926e63d880..59cc2ac43be8b 100644
--- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
@@ -1500,8 +1500,16 @@ 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
+}


        


More information about the llvm-commits mailing list