[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