diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -12202,8 +12202,10 @@ if (KeptBits == 32 || KeptBits == 64) return true; - // With Zbb we can use sext.h. sext.b does not seem to be profitable. - return Subtarget.hasStdExtZbb() && KeptBits == 16; + // With Zbb we can use sext.h/sext.b. + return Subtarget.hasStdExtZbb() && + ((KeptBits == 8 && XVT == MVT::i64 && !Subtarget.is64Bit()) || + KeptBits == 16); } bool RISCVTargetLowering::isDesirableToCommuteWithShift( diff --git a/llvm/test/CodeGen/RISCV/lack-of-signed-truncation-check.ll b/llvm/test/CodeGen/RISCV/lack-of-signed-truncation-check.ll --- a/llvm/test/CodeGen/RISCV/lack-of-signed-truncation-check.ll +++ b/llvm/test/CodeGen/RISCV/lack-of-signed-truncation-check.ll @@ -394,26 +394,36 @@ } define i1 @add_ultcmp_i64_i8(i64 %x) nounwind { -; RV32-LABEL: add_ultcmp_i64_i8: -; RV32: # %bb.0: -; RV32-NEXT: addi a2, a0, -128 -; RV32-NEXT: sltu a0, a2, a0 -; RV32-NEXT: add a0, a1, a0 -; RV32-NEXT: addi a0, a0, -1 -; RV32-NEXT: li a1, -1 -; RV32-NEXT: beq a0, a1, .LBB11_2 -; RV32-NEXT: # %bb.1: -; RV32-NEXT: sltiu a0, a0, -1 -; RV32-NEXT: ret -; RV32-NEXT: .LBB11_2: -; RV32-NEXT: sltiu a0, a2, -256 -; RV32-NEXT: ret +; RV32I-LABEL: add_ultcmp_i64_i8: +; RV32I: # %bb.0: +; RV32I-NEXT: addi a2, a0, -128 +; RV32I-NEXT: sltu a0, a2, a0 +; RV32I-NEXT: add a0, a1, a0 +; RV32I-NEXT: addi a0, a0, -1 +; RV32I-NEXT: li a1, -1 +; RV32I-NEXT: beq a0, a1, .LBB11_2 +; RV32I-NEXT: # %bb.1: +; RV32I-NEXT: sltiu a0, a0, -1 +; RV32I-NEXT: ret +; RV32I-NEXT: .LBB11_2: +; RV32I-NEXT: sltiu a0, a2, -256 +; RV32I-NEXT: ret ; ; RV64-LABEL: add_ultcmp_i64_i8: ; RV64: # %bb.0: ; RV64-NEXT: addi a0, a0, -128 ; RV64-NEXT: sltiu a0, a0, -256 ; RV64-NEXT: ret +; +; RV32ZBB-LABEL: add_ultcmp_i64_i8: +; RV32ZBB: # %bb.0: +; RV32ZBB-NEXT: sext.b a2, a0 +; RV32ZBB-NEXT: xor a0, a2, a0 +; RV32ZBB-NEXT: srai a2, a2, 31 +; RV32ZBB-NEXT: xor a1, a2, a1 +; RV32ZBB-NEXT: or a0, a0, a1 +; RV32ZBB-NEXT: snez a0, a0 +; RV32ZBB-NEXT: ret %tmp0 = add i64 %x, -128 ; ~0U << (8-1) %tmp1 = icmp ult i64 %tmp0, -256 ; ~0U << 8 ret i1 %tmp1 @@ -600,19 +610,19 @@ } define i1 @add_ugecmp_i64_i8(i64 %x) nounwind { -; RV32-LABEL: add_ugecmp_i64_i8: -; RV32: # %bb.0: -; RV32-NEXT: addi a2, a0, 128 -; RV32-NEXT: sltu a0, a2, a0 -; RV32-NEXT: add a1, a1, a0 -; RV32-NEXT: beqz a1, .LBB18_2 -; RV32-NEXT: # %bb.1: -; RV32-NEXT: snez a0, a1 -; RV32-NEXT: ret -; RV32-NEXT: .LBB18_2: -; RV32-NEXT: sltiu a0, a2, 256 -; RV32-NEXT: xori a0, a0, 1 -; RV32-NEXT: ret +; RV32I-LABEL: add_ugecmp_i64_i8: +; RV32I: # %bb.0: +; RV32I-NEXT: addi a2, a0, 128 +; RV32I-NEXT: sltu a0, a2, a0 +; RV32I-NEXT: add a1, a1, a0 +; RV32I-NEXT: beqz a1, .LBB18_2 +; RV32I-NEXT: # %bb.1: +; RV32I-NEXT: snez a0, a1 +; RV32I-NEXT: ret +; RV32I-NEXT: .LBB18_2: +; RV32I-NEXT: sltiu a0, a2, 256 +; RV32I-NEXT: xori a0, a0, 1 +; RV32I-NEXT: ret ; ; RV64-LABEL: add_ugecmp_i64_i8: ; RV64: # %bb.0: @@ -620,6 +630,16 @@ ; RV64-NEXT: sltiu a0, a0, 256 ; RV64-NEXT: xori a0, a0, 1 ; RV64-NEXT: ret +; +; RV32ZBB-LABEL: add_ugecmp_i64_i8: +; RV32ZBB: # %bb.0: +; RV32ZBB-NEXT: sext.b a2, a0 +; RV32ZBB-NEXT: xor a0, a2, a0 +; RV32ZBB-NEXT: srai a2, a2, 31 +; RV32ZBB-NEXT: xor a1, a2, a1 +; RV32ZBB-NEXT: or a0, a0, a1 +; RV32ZBB-NEXT: snez a0, a0 +; RV32ZBB-NEXT: ret %tmp0 = add i64 %x, 128 ; 1U << (8-1) %tmp1 = icmp uge i64 %tmp0, 256 ; 1U << 8 ret i1 %tmp1 diff --git a/llvm/test/CodeGen/RISCV/signed-truncation-check.ll b/llvm/test/CodeGen/RISCV/signed-truncation-check.ll --- a/llvm/test/CodeGen/RISCV/signed-truncation-check.ll +++ b/llvm/test/CodeGen/RISCV/signed-truncation-check.ll @@ -437,16 +437,16 @@ } define i1 @add_ugecmp_i64_i8(i64 %x) nounwind { -; RV32-LABEL: add_ugecmp_i64_i8: -; RV32: # %bb.0: -; RV32-NEXT: addi a2, a0, -128 -; RV32-NEXT: sltu a0, a2, a0 -; RV32-NEXT: add a0, a1, a0 -; RV32-NEXT: seqz a0, a0 -; RV32-NEXT: sltiu a1, a2, -256 -; RV32-NEXT: xori a1, a1, 1 -; RV32-NEXT: and a0, a0, a1 -; RV32-NEXT: ret +; RV32I-LABEL: add_ugecmp_i64_i8: +; RV32I: # %bb.0: +; RV32I-NEXT: addi a2, a0, -128 +; RV32I-NEXT: sltu a0, a2, a0 +; RV32I-NEXT: add a0, a1, a0 +; RV32I-NEXT: seqz a0, a0 +; RV32I-NEXT: sltiu a1, a2, -256 +; RV32I-NEXT: xori a1, a1, 1 +; RV32I-NEXT: and a0, a0, a1 +; RV32I-NEXT: ret ; ; RV64-LABEL: add_ugecmp_i64_i8: ; RV64: # %bb.0: @@ -454,6 +454,16 @@ ; RV64-NEXT: sltiu a0, a0, -256 ; RV64-NEXT: xori a0, a0, 1 ; RV64-NEXT: ret +; +; RV32ZBB-LABEL: add_ugecmp_i64_i8: +; RV32ZBB: # %bb.0: +; RV32ZBB-NEXT: sext.b a2, a0 +; RV32ZBB-NEXT: xor a0, a2, a0 +; RV32ZBB-NEXT: srai a2, a2, 31 +; RV32ZBB-NEXT: xor a1, a2, a1 +; RV32ZBB-NEXT: or a0, a0, a1 +; RV32ZBB-NEXT: seqz a0, a0 +; RV32ZBB-NEXT: ret %tmp0 = add i64 %x, -128 ; ~0U << (8-1) %tmp1 = icmp uge i64 %tmp0, -256 ; ~0U << 8 ret i1 %tmp1 @@ -636,21 +646,31 @@ } define i1 @add_ultcmp_i64_i8(i64 %x) nounwind { -; RV32-LABEL: add_ultcmp_i64_i8: -; RV32: # %bb.0: -; RV32-NEXT: addi a2, a0, 128 -; RV32-NEXT: sltu a0, a2, a0 -; RV32-NEXT: add a0, a1, a0 -; RV32-NEXT: seqz a0, a0 -; RV32-NEXT: sltiu a1, a2, 256 -; RV32-NEXT: and a0, a0, a1 -; RV32-NEXT: ret +; RV32I-LABEL: add_ultcmp_i64_i8: +; RV32I: # %bb.0: +; RV32I-NEXT: addi a2, a0, 128 +; RV32I-NEXT: sltu a0, a2, a0 +; RV32I-NEXT: add a0, a1, a0 +; RV32I-NEXT: seqz a0, a0 +; RV32I-NEXT: sltiu a1, a2, 256 +; RV32I-NEXT: and a0, a0, a1 +; RV32I-NEXT: ret ; ; RV64-LABEL: add_ultcmp_i64_i8: ; RV64: # %bb.0: ; RV64-NEXT: addi a0, a0, 128 ; RV64-NEXT: sltiu a0, a0, 256 ; RV64-NEXT: ret +; +; RV32ZBB-LABEL: add_ultcmp_i64_i8: +; RV32ZBB: # %bb.0: +; RV32ZBB-NEXT: sext.b a2, a0 +; RV32ZBB-NEXT: xor a0, a2, a0 +; RV32ZBB-NEXT: srai a2, a2, 31 +; RV32ZBB-NEXT: xor a1, a2, a1 +; RV32ZBB-NEXT: or a0, a0, a1 +; RV32ZBB-NEXT: seqz a0, a0 +; RV32ZBB-NEXT: ret %tmp0 = add i64 %x, 128 ; 1U << (8-1) %tmp1 = icmp ult i64 %tmp0, 256 ; 1U << 8 ret i1 %tmp1