diff --git a/llvm/lib/Target/RISCV/RISCV.td b/llvm/lib/Target/RISCV/RISCV.td --- a/llvm/lib/Target/RISCV/RISCV.td +++ b/llvm/lib/Target/RISCV/RISCV.td @@ -116,6 +116,8 @@ def HasStdExtZbbOrZbp : Predicate<"Subtarget->hasStdExtZbb() || Subtarget->hasStdExtZbp()">, AssemblerPredicate<(any_of FeatureExtZbb, FeatureExtZbp)>; +def NotHasStdExtZbbOrZbp + : Predicate<"!(Subtarget->hasStdExtZbb() || Subtarget->hasStdExtZbp())">; def FeatureExtZbproposedc : SubtargetFeature<"experimental-zbproposedc", "HasStdExtZbproposedc", "true", diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td @@ -1120,12 +1120,14 @@ /// RV64 patterns +let Predicates = [IsRV64, NotHasStdExtZbbOrZbp] in +def : Pat<(and GPR:$rs1, 0xffffffff), (SRLI (SLLI GPR:$rs1, 32), 32)>; + let Predicates = [IsRV64] in { /// sext and zext def : Pat<(sext_inreg GPR:$rs1, i32), (ADDIW GPR:$rs1, 0)>; -def : Pat<(and GPR:$rs1, 0xffffffff), (SRLI (SLLI GPR:$rs1, 32), 32)>; /// ALU operations diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoB.td b/llvm/lib/Target/RISCV/RISCVInstrInfoB.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfoB.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoB.td @@ -882,6 +882,13 @@ (and GPR:$rs1, 0x00FF)), (PACKH GPR:$rs1, GPR:$rs2)>; +let Predicates = [HasStdExtZbbOrZbp, IsRV32] in +def : Pat<(and GPR:$rs, 0x0000FFFF), (PACK GPR:$rs, X0)>; +let Predicates = [HasStdExtZbbOrZbp, IsRV64] in { +def : Pat<(and GPR:$rs, 0x000000000000FFFF), (PACKW GPR:$rs, X0)>; +def : Pat<(and GPR:$rs, 0x00000000FFFFFFFF), (PACK GPR:$rs, X0)>; +} + let Predicates = [HasStdExtZbp, IsRV32] in { def : Pat<(or (or (and (shl GPR:$rs1, (i32 8)), (i32 0x00FF0000)), (and GPR:$rs1, (i32 0xFF0000FF))), diff --git a/llvm/test/CodeGen/RISCV/rv32Zbbp.ll b/llvm/test/CodeGen/RISCV/rv32Zbbp.ll --- a/llvm/test/CodeGen/RISCV/rv32Zbbp.ll +++ b/llvm/test/CodeGen/RISCV/rv32Zbbp.ll @@ -959,3 +959,59 @@ %or = or i64 %shl, %and ret i64 %or } + +define i32 @zexth_i32(i32 %a) nounwind { +; RV32I-LABEL: zexth_i32: +; RV32I: # %bb.0: +; RV32I-NEXT: lui a1, 16 +; RV32I-NEXT: addi a1, a1, -1 +; RV32I-NEXT: and a0, a0, a1 +; RV32I-NEXT: ret +; +; RV32IB-LABEL: zexth_i32: +; RV32IB: # %bb.0: +; RV32IB-NEXT: zext.h a0, a0 +; RV32IB-NEXT: ret +; +; RV32IBB-LABEL: zexth_i32: +; RV32IBB: # %bb.0: +; RV32IBB-NEXT: zext.h a0, a0 +; RV32IBB-NEXT: ret +; +; RV32IBP-LABEL: zexth_i32: +; RV32IBP: # %bb.0: +; RV32IBP-NEXT: pack a0, a0, zero +; RV32IBP-NEXT: ret + %and = and i32 %a, 65535 + ret i32 %and +} + +define i64 @zexth_i64(i64 %a) nounwind { +; RV32I-LABEL: zexth_i64: +; RV32I: # %bb.0: +; RV32I-NEXT: lui a1, 16 +; RV32I-NEXT: addi a1, a1, -1 +; RV32I-NEXT: and a0, a0, a1 +; RV32I-NEXT: mv a1, zero +; RV32I-NEXT: ret +; +; RV32IB-LABEL: zexth_i64: +; RV32IB: # %bb.0: +; RV32IB-NEXT: zext.h a0, a0 +; RV32IB-NEXT: mv a1, zero +; RV32IB-NEXT: ret +; +; RV32IBB-LABEL: zexth_i64: +; RV32IBB: # %bb.0: +; RV32IBB-NEXT: zext.h a0, a0 +; RV32IBB-NEXT: mv a1, zero +; RV32IBB-NEXT: ret +; +; RV32IBP-LABEL: zexth_i64: +; RV32IBP: # %bb.0: +; RV32IBP-NEXT: pack a0, a0, zero +; RV32IBP-NEXT: mv a1, zero +; RV32IBP-NEXT: ret + %and = and i64 %a, 65535 + ret i64 %and +} diff --git a/llvm/test/CodeGen/RISCV/rv64Zbbp.ll b/llvm/test/CodeGen/RISCV/rv64Zbbp.ll --- a/llvm/test/CodeGen/RISCV/rv64Zbbp.ll +++ b/llvm/test/CodeGen/RISCV/rv64Zbbp.ll @@ -662,3 +662,28 @@ %or = or i64 %shl, %and ret i64 %or } + +define i64 @zextw_i64(i64 %a) nounwind { +; RV64I-LABEL: zextw_i64: +; RV64I: # %bb.0: +; RV64I-NEXT: slli a0, a0, 32 +; RV64I-NEXT: srli a0, a0, 32 +; RV64I-NEXT: ret +; +; RV64IB-LABEL: zextw_i64: +; RV64IB: # %bb.0: +; RV64IB-NEXT: zext.w a0, a0 +; RV64IB-NEXT: ret +; +; RV64IBB-LABEL: zextw_i64: +; RV64IBB: # %bb.0: +; RV64IBB-NEXT: zext.w a0, a0 +; RV64IBB-NEXT: ret +; +; RV64IBP-LABEL: zextw_i64: +; RV64IBP: # %bb.0: +; RV64IBP-NEXT: pack a0, a0, zero +; RV64IBP-NEXT: ret + %and = and i64 %a, 4294967295 + ret i64 %and +}