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 (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 +}