diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -3699,8 +3699,8 @@ } // For SMAX, if CstLow is non-negative we know the result will be // non-negative and thus all sign bits are 0. - // TODO: There's an equivalent of this for smin with negative constant for - // known ones. + // For SMIN, if CstHigh is negative we know the result will be + // negative and thus all sign bits are 1. if (IsMax && CstLow) { const APInt &ValueLow = CstLow->getAPIntValue(); if (ValueLow.isNonNegative()) { @@ -3710,6 +3710,15 @@ } } + if (!IsMax && CstHigh) { + const APInt &ValueHigh = CstHigh->getAPIntValue(); + if (ValueHigh.isNegative()) { + unsigned SignBits = ComputeNumSignBits(Op.getOperand(0), Depth + 1); + Known.One.setHighBits(std::min(SignBits, ValueHigh.getNumSignBits())); + break; + } + } + Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1); Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1); if (IsMax) diff --git a/llvm/test/CodeGen/RISCV/min-max.ll b/llvm/test/CodeGen/RISCV/min-max.ll --- a/llvm/test/CodeGen/RISCV/min-max.ll +++ b/llvm/test/CodeGen/RISCV/min-max.ll @@ -638,3 +638,22 @@ %c = call i32 @llvm.smax.i32(i32 %a, i32 10) ret i32 %c } + +define signext i32 @smin_i32_pos_constant(i32 signext %a) { +; NOZBB-LABEL: smin_i32_pos_constant: +; NOZBB: # %bb.0: +; NOZBB-NEXT: li a1, -10 +; NOZBB-NEXT: blt a0, a1, .LBB25_2 +; NOZBB-NEXT: # %bb.1: +; NOZBB-NEXT: li a0, -10 +; NOZBB-NEXT: .LBB25_2: +; NOZBB-NEXT: ret +; +; ZBB-LABEL: smin_i32_pos_constant: +; ZBB: # %bb.0: +; ZBB-NEXT: li a1, -10 +; ZBB-NEXT: min a0, a0, a1 +; ZBB-NEXT: ret + %c = call i32 @llvm.smin.i32(i32 %a, i32 -10) + ret i32 %c +}