diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.h b/llvm/lib/Target/RISCV/RISCVISelLowering.h --- a/llvm/lib/Target/RISCV/RISCVISelLowering.h +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.h @@ -550,6 +550,9 @@ return ISD::SIGN_EXTEND; } + bool shouldTransformSignedTruncationCheck(EVT XVT, + unsigned KeptBits) const override; + TargetLowering::ShiftLegalizationStrategy preferredShiftLegalizationStrategy(SelectionDAG &DAG, SDNode *N, unsigned ExpansionFactor) const override { 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 @@ -12155,6 +12155,23 @@ return SDValue(); } +bool RISCVTargetLowering::shouldTransformSignedTruncationCheck( + EVT XVT, unsigned KeptBits) const { + // For vectors, we don't have a preference.. + if (XVT.isVector()) + return false; + + if (XVT != MVT::i32 && XVT != MVT::i64) + return false; + + // We can use sext.w for RV64 or an srai 31 on RV32. + 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; +} + bool RISCVTargetLowering::isDesirableToCommuteWithShift( const SDNode *N, CombineLevel Level) const { assert((N->getOpcode() == ISD::SHL || N->getOpcode() == ISD::SRA || 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 @@ -275,21 +275,36 @@ } define i1 @add_ultcmp_i32_i16(i32 %x) nounwind { -; RV32-LABEL: add_ultcmp_i32_i16: -; RV32: # %bb.0: -; RV32-NEXT: lui a1, 1048568 -; RV32-NEXT: add a0, a0, a1 -; RV32-NEXT: lui a1, 1048560 -; RV32-NEXT: sltu a0, a0, a1 -; RV32-NEXT: ret +; RV32I-LABEL: add_ultcmp_i32_i16: +; RV32I: # %bb.0: +; RV32I-NEXT: lui a1, 1048568 +; RV32I-NEXT: add a0, a0, a1 +; RV32I-NEXT: lui a1, 1048560 +; RV32I-NEXT: sltu a0, a0, a1 +; RV32I-NEXT: ret ; -; RV64-LABEL: add_ultcmp_i32_i16: -; RV64: # %bb.0: -; RV64-NEXT: lui a1, 1048568 -; RV64-NEXT: addw a0, a0, a1 -; RV64-NEXT: lui a1, 1048560 -; RV64-NEXT: sltu a0, a0, a1 -; RV64-NEXT: ret +; RV64I-LABEL: add_ultcmp_i32_i16: +; RV64I: # %bb.0: +; RV64I-NEXT: lui a1, 1048568 +; RV64I-NEXT: addw a0, a0, a1 +; RV64I-NEXT: lui a1, 1048560 +; RV64I-NEXT: sltu a0, a0, a1 +; RV64I-NEXT: ret +; +; RV32ZBB-LABEL: add_ultcmp_i32_i16: +; RV32ZBB: # %bb.0: +; RV32ZBB-NEXT: sext.h a1, a0 +; RV32ZBB-NEXT: xor a0, a1, a0 +; RV32ZBB-NEXT: snez a0, a0 +; RV32ZBB-NEXT: ret +; +; RV64ZBB-LABEL: add_ultcmp_i32_i16: +; RV64ZBB: # %bb.0: +; RV64ZBB-NEXT: sext.w a1, a0 +; RV64ZBB-NEXT: sext.h a0, a0 +; RV64ZBB-NEXT: xor a0, a0, a1 +; RV64ZBB-NEXT: snez a0, a0 +; RV64ZBB-NEXT: ret %tmp0 = add i32 %x, -32768 ; ~0U << (16-1) %tmp1 = icmp ult i32 %tmp0, -65536 ; ~0U << 16 ret i1 %tmp1 @@ -315,20 +330,16 @@ define i1 @add_ultcmp_i64_i32(i64 %x) nounwind { ; RV32-LABEL: add_ultcmp_i64_i32: ; RV32: # %bb.0: -; RV32-NEXT: lui a2, 524288 -; RV32-NEXT: add a2, a0, a2 -; RV32-NEXT: sltu a0, a2, a0 -; RV32-NEXT: add a0, a1, a0 +; RV32-NEXT: srai a0, a0, 31 +; RV32-NEXT: xor a0, a0, a1 ; RV32-NEXT: snez a0, a0 ; RV32-NEXT: ret ; ; RV64-LABEL: add_ultcmp_i64_i32: ; RV64: # %bb.0: -; RV64-NEXT: lui a1, 524288 -; RV64-NEXT: add a0, a0, a1 -; RV64-NEXT: li a1, -1 -; RV64-NEXT: slli a1, a1, 32 -; RV64-NEXT: sltu a0, a0, a1 +; RV64-NEXT: sext.w a1, a0 +; RV64-NEXT: xor a0, a1, a0 +; RV64-NEXT: snez a0, a0 ; RV64-NEXT: ret %tmp0 = add i64 %x, -2147483648 ; ~0U << (32-1) %tmp1 = icmp ult i64 %tmp0, -4294967296 ; ~0U << 32 @@ -336,30 +347,47 @@ } define i1 @add_ultcmp_i64_i16(i64 %x) nounwind { -; RV32-LABEL: add_ultcmp_i64_i16: -; RV32: # %bb.0: -; RV32-NEXT: lui a2, 1048568 -; RV32-NEXT: add a2, a0, a2 -; 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, .LBB10_2 -; RV32-NEXT: # %bb.1: -; RV32-NEXT: sltiu a0, a0, -1 -; RV32-NEXT: ret -; RV32-NEXT: .LBB10_2: -; RV32-NEXT: lui a0, 1048560 -; RV32-NEXT: sltu a0, a2, a0 -; RV32-NEXT: ret +; RV32I-LABEL: add_ultcmp_i64_i16: +; RV32I: # %bb.0: +; RV32I-NEXT: lui a2, 1048568 +; RV32I-NEXT: add a2, a0, a2 +; 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, .LBB10_2 +; RV32I-NEXT: # %bb.1: +; RV32I-NEXT: sltiu a0, a0, -1 +; RV32I-NEXT: ret +; RV32I-NEXT: .LBB10_2: +; RV32I-NEXT: lui a0, 1048560 +; RV32I-NEXT: sltu a0, a2, a0 +; RV32I-NEXT: ret ; -; RV64-LABEL: add_ultcmp_i64_i16: -; RV64: # %bb.0: -; RV64-NEXT: lui a1, 1048568 -; RV64-NEXT: add a0, a0, a1 -; RV64-NEXT: lui a1, 1048560 -; RV64-NEXT: sltu a0, a0, a1 -; RV64-NEXT: ret +; RV64I-LABEL: add_ultcmp_i64_i16: +; RV64I: # %bb.0: +; RV64I-NEXT: lui a1, 1048568 +; RV64I-NEXT: add a0, a0, a1 +; RV64I-NEXT: lui a1, 1048560 +; RV64I-NEXT: sltu a0, a0, a1 +; RV64I-NEXT: ret +; +; RV32ZBB-LABEL: add_ultcmp_i64_i16: +; RV32ZBB: # %bb.0: +; RV32ZBB-NEXT: sext.h 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 +; +; RV64ZBB-LABEL: add_ultcmp_i64_i16: +; RV64ZBB: # %bb.0: +; RV64ZBB-NEXT: sext.h a1, a0 +; RV64ZBB-NEXT: xor a0, a1, a0 +; RV64ZBB-NEXT: snez a0, a0 +; RV64ZBB-NEXT: ret %tmp0 = add i64 %x, -32768 ; ~0U << (16-1) %tmp1 = icmp ult i64 %tmp0, -65536 ; ~0U << 16 ret i1 %tmp1 @@ -457,21 +485,36 @@ } define i1 @add_ugecmp_i32_i16(i32 %x) nounwind { -; RV32-LABEL: add_ugecmp_i32_i16: -; RV32: # %bb.0: -; RV32-NEXT: lui a1, 8 -; RV32-NEXT: add a0, a0, a1 -; RV32-NEXT: srli a0, a0, 16 -; RV32-NEXT: snez a0, a0 -; RV32-NEXT: ret +; RV32I-LABEL: add_ugecmp_i32_i16: +; RV32I: # %bb.0: +; RV32I-NEXT: lui a1, 8 +; RV32I-NEXT: add a0, a0, a1 +; RV32I-NEXT: srli a0, a0, 16 +; RV32I-NEXT: snez a0, a0 +; RV32I-NEXT: ret ; -; RV64-LABEL: add_ugecmp_i32_i16: -; RV64: # %bb.0: -; RV64-NEXT: lui a1, 8 -; RV64-NEXT: add a0, a0, a1 -; RV64-NEXT: srliw a0, a0, 16 -; RV64-NEXT: snez a0, a0 -; RV64-NEXT: ret +; RV64I-LABEL: add_ugecmp_i32_i16: +; RV64I: # %bb.0: +; RV64I-NEXT: lui a1, 8 +; RV64I-NEXT: add a0, a0, a1 +; RV64I-NEXT: srliw a0, a0, 16 +; RV64I-NEXT: snez a0, a0 +; RV64I-NEXT: ret +; +; RV32ZBB-LABEL: add_ugecmp_i32_i16: +; RV32ZBB: # %bb.0: +; RV32ZBB-NEXT: sext.h a1, a0 +; RV32ZBB-NEXT: xor a0, a1, a0 +; RV32ZBB-NEXT: snez a0, a0 +; RV32ZBB-NEXT: ret +; +; RV64ZBB-LABEL: add_ugecmp_i32_i16: +; RV64ZBB: # %bb.0: +; RV64ZBB-NEXT: sext.w a1, a0 +; RV64ZBB-NEXT: sext.h a0, a0 +; RV64ZBB-NEXT: xor a0, a0, a1 +; RV64ZBB-NEXT: snez a0, a0 +; RV64ZBB-NEXT: ret %tmp0 = add i32 %x, 32768 ; 1U << (16-1) %tmp1 = icmp uge i32 %tmp0, 65536 ; 1U << 16 ret i1 %tmp1 @@ -499,19 +542,15 @@ define i1 @add_ugecmp_i64_i32(i64 %x) nounwind { ; RV32-LABEL: add_ugecmp_i64_i32: ; RV32: # %bb.0: -; RV32-NEXT: lui a2, 524288 -; RV32-NEXT: add a2, a0, a2 -; RV32-NEXT: sltu a0, a2, a0 -; RV32-NEXT: add a0, a1, a0 +; RV32-NEXT: srai a0, a0, 31 +; RV32-NEXT: xor a0, a0, a1 ; RV32-NEXT: snez a0, a0 ; RV32-NEXT: ret ; ; RV64-LABEL: add_ugecmp_i64_i32: ; RV64: # %bb.0: -; RV64-NEXT: li a1, 1 -; RV64-NEXT: slli a1, a1, 31 -; RV64-NEXT: add a0, a0, a1 -; RV64-NEXT: srli a0, a0, 32 +; RV64-NEXT: sext.w a1, a0 +; RV64-NEXT: xor a0, a1, a0 ; RV64-NEXT: snez a0, a0 ; RV64-NEXT: ret %tmp0 = add i64 %x, 2147483648 ; 1U << (32-1) @@ -520,24 +559,41 @@ } define i1 @add_ugecmp_i64_i16(i64 %x) nounwind { -; RV32-LABEL: add_ugecmp_i64_i16: -; RV32: # %bb.0: -; RV32-NEXT: lui a2, 8 -; RV32-NEXT: add a2, a0, a2 -; RV32-NEXT: sltu a0, a2, a0 -; RV32-NEXT: add a0, a1, a0 -; RV32-NEXT: srli a2, a2, 16 -; RV32-NEXT: or a0, a0, a2 -; RV32-NEXT: snez a0, a0 -; RV32-NEXT: ret +; RV32I-LABEL: add_ugecmp_i64_i16: +; RV32I: # %bb.0: +; RV32I-NEXT: lui a2, 8 +; RV32I-NEXT: add a2, a0, a2 +; RV32I-NEXT: sltu a0, a2, a0 +; RV32I-NEXT: add a0, a1, a0 +; RV32I-NEXT: srli a2, a2, 16 +; RV32I-NEXT: or a0, a0, a2 +; RV32I-NEXT: snez a0, a0 +; RV32I-NEXT: ret ; -; RV64-LABEL: add_ugecmp_i64_i16: -; RV64: # %bb.0: -; RV64-NEXT: lui a1, 8 -; RV64-NEXT: add a0, a0, a1 -; RV64-NEXT: srli a0, a0, 16 -; RV64-NEXT: snez a0, a0 -; RV64-NEXT: ret +; RV64I-LABEL: add_ugecmp_i64_i16: +; RV64I: # %bb.0: +; RV64I-NEXT: lui a1, 8 +; RV64I-NEXT: add a0, a0, a1 +; RV64I-NEXT: srli a0, a0, 16 +; RV64I-NEXT: snez a0, a0 +; RV64I-NEXT: ret +; +; RV32ZBB-LABEL: add_ugecmp_i64_i16: +; RV32ZBB: # %bb.0: +; RV32ZBB-NEXT: sext.h 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 +; +; RV64ZBB-LABEL: add_ugecmp_i64_i16: +; RV64ZBB: # %bb.0: +; RV64ZBB-NEXT: sext.h a1, a0 +; RV64ZBB-NEXT: xor a0, a1, a0 +; RV64ZBB-NEXT: snez a0, a0 +; RV64ZBB-NEXT: ret %tmp0 = add i64 %x, 32768 ; 1U << (16-1) %tmp1 = icmp uge i64 %tmp0, 65536 ; 1U << 16 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 @@ -317,23 +317,38 @@ } define i1 @add_ugecmp_i32_i16(i32 %x) nounwind { -; RV32-LABEL: add_ugecmp_i32_i16: -; RV32: # %bb.0: -; RV32-NEXT: lui a1, 1048568 -; RV32-NEXT: add a0, a0, a1 -; RV32-NEXT: lui a1, 1048560 -; RV32-NEXT: addi a1, a1, -1 -; RV32-NEXT: sltu a0, a1, a0 -; RV32-NEXT: ret +; RV32I-LABEL: add_ugecmp_i32_i16: +; RV32I: # %bb.0: +; RV32I-NEXT: lui a1, 1048568 +; RV32I-NEXT: add a0, a0, a1 +; RV32I-NEXT: lui a1, 1048560 +; RV32I-NEXT: addi a1, a1, -1 +; RV32I-NEXT: sltu a0, a1, a0 +; RV32I-NEXT: ret ; -; RV64-LABEL: add_ugecmp_i32_i16: -; RV64: # %bb.0: -; RV64-NEXT: lui a1, 1048568 -; RV64-NEXT: addw a0, a0, a1 -; RV64-NEXT: lui a1, 1048560 -; RV64-NEXT: addiw a1, a1, -1 -; RV64-NEXT: sltu a0, a1, a0 -; RV64-NEXT: ret +; RV64I-LABEL: add_ugecmp_i32_i16: +; RV64I: # %bb.0: +; RV64I-NEXT: lui a1, 1048568 +; RV64I-NEXT: addw a0, a0, a1 +; RV64I-NEXT: lui a1, 1048560 +; RV64I-NEXT: addiw a1, a1, -1 +; RV64I-NEXT: sltu a0, a1, a0 +; RV64I-NEXT: ret +; +; RV32ZBB-LABEL: add_ugecmp_i32_i16: +; RV32ZBB: # %bb.0: +; RV32ZBB-NEXT: sext.h a1, a0 +; RV32ZBB-NEXT: xor a0, a1, a0 +; RV32ZBB-NEXT: seqz a0, a0 +; RV32ZBB-NEXT: ret +; +; RV64ZBB-LABEL: add_ugecmp_i32_i16: +; RV64ZBB: # %bb.0: +; RV64ZBB-NEXT: sext.w a1, a0 +; RV64ZBB-NEXT: sext.h a0, a0 +; RV64ZBB-NEXT: xor a0, a0, a1 +; RV64ZBB-NEXT: seqz a0, a0 +; RV64ZBB-NEXT: ret %tmp0 = add i32 %x, -32768 ; ~0U << (16-1) %tmp1 = icmp uge i32 %tmp0, -65536 ; ~0U << 16 ret i1 %tmp1 @@ -361,58 +376,61 @@ define i1 @add_ugecmp_i64_i32(i64 %x) nounwind { ; RV32-LABEL: add_ugecmp_i64_i32: ; RV32: # %bb.0: -; RV32-NEXT: lui a2, 524288 -; RV32-NEXT: add a2, a0, a2 -; RV32-NEXT: sltu a0, a2, a0 -; RV32-NEXT: add a0, a1, a0 +; RV32-NEXT: srai a0, a0, 31 +; RV32-NEXT: xor a0, a0, a1 ; RV32-NEXT: seqz a0, a0 ; RV32-NEXT: ret ; -; RV64I-LABEL: add_ugecmp_i64_i32: -; RV64I: # %bb.0: -; RV64I-NEXT: lui a1, 524288 -; RV64I-NEXT: add a0, a0, a1 -; RV64I-NEXT: li a1, -1 -; RV64I-NEXT: slli a1, a1, 32 -; RV64I-NEXT: addi a1, a1, -1 -; RV64I-NEXT: sltu a0, a1, a0 -; RV64I-NEXT: ret -; -; RV64ZBB-LABEL: add_ugecmp_i64_i32: -; RV64ZBB: # %bb.0: -; RV64ZBB-NEXT: lui a1, 524288 -; RV64ZBB-NEXT: add a0, a0, a1 -; RV64ZBB-NEXT: li a1, -2 -; RV64ZBB-NEXT: rori a1, a1, 32 -; RV64ZBB-NEXT: sltu a0, a1, a0 -; RV64ZBB-NEXT: ret +; RV64-LABEL: add_ugecmp_i64_i32: +; RV64: # %bb.0: +; RV64-NEXT: sext.w a1, a0 +; RV64-NEXT: xor a0, a1, a0 +; RV64-NEXT: seqz a0, a0 +; RV64-NEXT: ret %tmp0 = add i64 %x, -2147483648 ; ~0U << (32-1) %tmp1 = icmp uge i64 %tmp0, -4294967296 ; ~0U << 32 ret i1 %tmp1 } define i1 @add_ugecmp_i64_i16(i64 %x) nounwind { -; RV32-LABEL: add_ugecmp_i64_i16: -; RV32: # %bb.0: -; RV32-NEXT: lui a2, 1048568 -; RV32-NEXT: add a2, a0, a2 -; RV32-NEXT: sltu a0, a2, a0 -; RV32-NEXT: add a0, a1, a0 -; RV32-NEXT: lui a1, 1048560 -; RV32-NEXT: addi a1, a1, -1 -; RV32-NEXT: sltu a1, a1, a2 -; RV32-NEXT: seqz a0, a0 -; RV32-NEXT: and a0, a0, a1 -; RV32-NEXT: ret +; RV32I-LABEL: add_ugecmp_i64_i16: +; RV32I: # %bb.0: +; RV32I-NEXT: lui a2, 1048568 +; RV32I-NEXT: add a2, a0, a2 +; RV32I-NEXT: sltu a0, a2, a0 +; RV32I-NEXT: add a0, a1, a0 +; RV32I-NEXT: lui a1, 1048560 +; RV32I-NEXT: addi a1, a1, -1 +; RV32I-NEXT: sltu a1, a1, a2 +; RV32I-NEXT: seqz a0, a0 +; RV32I-NEXT: and a0, a0, a1 +; RV32I-NEXT: ret ; -; RV64-LABEL: add_ugecmp_i64_i16: -; RV64: # %bb.0: -; RV64-NEXT: lui a1, 1048568 -; RV64-NEXT: add a0, a0, a1 -; RV64-NEXT: lui a1, 1048560 -; RV64-NEXT: addiw a1, a1, -1 -; RV64-NEXT: sltu a0, a1, a0 -; RV64-NEXT: ret +; RV64I-LABEL: add_ugecmp_i64_i16: +; RV64I: # %bb.0: +; RV64I-NEXT: lui a1, 1048568 +; RV64I-NEXT: add a0, a0, a1 +; RV64I-NEXT: lui a1, 1048560 +; RV64I-NEXT: addiw a1, a1, -1 +; RV64I-NEXT: sltu a0, a1, a0 +; RV64I-NEXT: ret +; +; RV32ZBB-LABEL: add_ugecmp_i64_i16: +; RV32ZBB: # %bb.0: +; RV32ZBB-NEXT: sext.h 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 +; +; RV64ZBB-LABEL: add_ugecmp_i64_i16: +; RV64ZBB: # %bb.0: +; RV64ZBB-NEXT: sext.h a1, a0 +; RV64ZBB-NEXT: xor a0, a1, a0 +; RV64ZBB-NEXT: seqz a0, a0 +; RV64ZBB-NEXT: ret %tmp0 = add i64 %x, -32768 ; ~0U << (16-1) %tmp1 = icmp uge i64 %tmp0, -65536 ; ~0U << 16 ret i1 %tmp1 @@ -505,21 +523,36 @@ } define i1 @add_ultcmp_i32_i16(i32 %x) nounwind { -; RV32-LABEL: add_ultcmp_i32_i16: -; RV32: # %bb.0: -; RV32-NEXT: lui a1, 8 -; RV32-NEXT: add a0, a0, a1 -; RV32-NEXT: srli a0, a0, 16 -; RV32-NEXT: seqz a0, a0 -; RV32-NEXT: ret +; RV32I-LABEL: add_ultcmp_i32_i16: +; RV32I: # %bb.0: +; RV32I-NEXT: lui a1, 8 +; RV32I-NEXT: add a0, a0, a1 +; RV32I-NEXT: srli a0, a0, 16 +; RV32I-NEXT: seqz a0, a0 +; RV32I-NEXT: ret ; -; RV64-LABEL: add_ultcmp_i32_i16: -; RV64: # %bb.0: -; RV64-NEXT: lui a1, 8 -; RV64-NEXT: add a0, a0, a1 -; RV64-NEXT: srliw a0, a0, 16 -; RV64-NEXT: seqz a0, a0 -; RV64-NEXT: ret +; RV64I-LABEL: add_ultcmp_i32_i16: +; RV64I: # %bb.0: +; RV64I-NEXT: lui a1, 8 +; RV64I-NEXT: add a0, a0, a1 +; RV64I-NEXT: srliw a0, a0, 16 +; RV64I-NEXT: seqz a0, a0 +; RV64I-NEXT: ret +; +; RV32ZBB-LABEL: add_ultcmp_i32_i16: +; RV32ZBB: # %bb.0: +; RV32ZBB-NEXT: sext.h a1, a0 +; RV32ZBB-NEXT: xor a0, a1, a0 +; RV32ZBB-NEXT: seqz a0, a0 +; RV32ZBB-NEXT: ret +; +; RV64ZBB-LABEL: add_ultcmp_i32_i16: +; RV64ZBB: # %bb.0: +; RV64ZBB-NEXT: sext.w a1, a0 +; RV64ZBB-NEXT: sext.h a0, a0 +; RV64ZBB-NEXT: xor a0, a0, a1 +; RV64ZBB-NEXT: seqz a0, a0 +; RV64ZBB-NEXT: ret %tmp0 = add i32 %x, 32768 ; 1U << (16-1) %tmp1 = icmp ult i32 %tmp0, 65536 ; 1U << 16 ret i1 %tmp1 @@ -545,19 +578,15 @@ define i1 @add_ultcmp_i64_i32(i64 %x) nounwind { ; RV32-LABEL: add_ultcmp_i64_i32: ; RV32: # %bb.0: -; RV32-NEXT: lui a2, 524288 -; RV32-NEXT: add a2, a0, a2 -; RV32-NEXT: sltu a0, a2, a0 -; RV32-NEXT: add a0, a1, a0 +; RV32-NEXT: srai a0, a0, 31 +; RV32-NEXT: xor a0, a0, a1 ; RV32-NEXT: seqz a0, a0 ; RV32-NEXT: ret ; ; RV64-LABEL: add_ultcmp_i64_i32: ; RV64: # %bb.0: -; RV64-NEXT: li a1, 1 -; RV64-NEXT: slli a1, a1, 31 -; RV64-NEXT: add a0, a0, a1 -; RV64-NEXT: srli a0, a0, 32 +; RV64-NEXT: sext.w a1, a0 +; RV64-NEXT: xor a0, a1, a0 ; RV64-NEXT: seqz a0, a0 ; RV64-NEXT: ret %tmp0 = add i64 %x, 2147483648 ; 1U << (32-1) @@ -566,24 +595,41 @@ } define i1 @add_ultcmp_i64_i16(i64 %x) nounwind { -; RV32-LABEL: add_ultcmp_i64_i16: -; RV32: # %bb.0: -; RV32-NEXT: lui a2, 8 -; RV32-NEXT: add a2, a0, a2 -; RV32-NEXT: sltu a0, a2, a0 -; RV32-NEXT: add a0, a1, a0 -; RV32-NEXT: srli a2, a2, 16 -; RV32-NEXT: or a0, a0, a2 -; RV32-NEXT: seqz a0, a0 -; RV32-NEXT: ret +; RV32I-LABEL: add_ultcmp_i64_i16: +; RV32I: # %bb.0: +; RV32I-NEXT: lui a2, 8 +; RV32I-NEXT: add a2, a0, a2 +; RV32I-NEXT: sltu a0, a2, a0 +; RV32I-NEXT: add a0, a1, a0 +; RV32I-NEXT: srli a2, a2, 16 +; RV32I-NEXT: or a0, a0, a2 +; RV32I-NEXT: seqz a0, a0 +; RV32I-NEXT: ret ; -; RV64-LABEL: add_ultcmp_i64_i16: -; RV64: # %bb.0: -; RV64-NEXT: lui a1, 8 -; RV64-NEXT: add a0, a0, a1 -; RV64-NEXT: srli a0, a0, 16 -; RV64-NEXT: seqz a0, a0 -; RV64-NEXT: ret +; RV64I-LABEL: add_ultcmp_i64_i16: +; RV64I: # %bb.0: +; RV64I-NEXT: lui a1, 8 +; RV64I-NEXT: add a0, a0, a1 +; RV64I-NEXT: srli a0, a0, 16 +; RV64I-NEXT: seqz a0, a0 +; RV64I-NEXT: ret +; +; RV32ZBB-LABEL: add_ultcmp_i64_i16: +; RV32ZBB: # %bb.0: +; RV32ZBB-NEXT: sext.h 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 +; +; RV64ZBB-LABEL: add_ultcmp_i64_i16: +; RV64ZBB: # %bb.0: +; RV64ZBB-NEXT: sext.h a1, a0 +; RV64ZBB-NEXT: xor a0, a1, a0 +; RV64ZBB-NEXT: seqz a0, a0 +; RV64ZBB-NEXT: ret %tmp0 = add i64 %x, 32768 ; 1U << (16-1) %tmp1 = icmp ult i64 %tmp0, 65536 ; 1U << 16 ret i1 %tmp1