[llvm] [SelectionDAG] Calculate Knownbits for SMIN (PR #85584)

via llvm-commits llvm-commits at lists.llvm.org
Sun Mar 17 16:52:40 PDT 2024


https://github.com/AtariDreams updated https://github.com/llvm/llvm-project/pull/85584

>From e40104469f9de05f1c69641ee67c360e9d714db6 Mon Sep 17 00:00:00 2001
From: Rose <gfunni234 at gmail.com>
Date: Sun, 17 Mar 2024 17:56:01 -0400
Subject: [PATCH] [SelectionDAG] Calculate KnownBits for SMIN

---
 .../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 12 ++-
 llvm/test/CodeGen/RISCV/min-max.ll            | 82 +++++++++++++++----
 2 files changed, 78 insertions(+), 16 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 2670f48aebcff5..f6ac5d98d1d402 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -4007,8 +4007,6 @@ KnownBits SelectionDAG::computeKnownBits(SDValue Op, const APInt &DemandedElts,
 
     // 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.
     if (IsMax && CstLow) {
       const APInt &ValueLow = CstLow->getAPIntValue();
       if (ValueLow.isNonNegative()) {
@@ -4017,6 +4015,16 @@ KnownBits SelectionDAG::computeKnownBits(SDValue Op, const APInt &DemandedElts,
       }
     }
 
+    // For SMIN, if CstHigh is negative we know the result will be
+    // negative and thus all sign bits are 1.
+    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;
   }
   case ISD::UINT_TO_FP: {
diff --git a/llvm/test/CodeGen/RISCV/min-max.ll b/llvm/test/CodeGen/RISCV/min-max.ll
index 0115b48b7124c9..cc691a7374d985 100644
--- a/llvm/test/CodeGen/RISCV/min-max.ll
+++ b/llvm/test/CodeGen/RISCV/min-max.ll
@@ -599,15 +599,69 @@ define signext i32 @smax_i32_pos_constant(i32 signext %a) {
   ret i32 %c
 }
 
+define signext i32 @smin_i32_neg_constant(i32 signext %a) {
+; RV32I-LABEL: smin_i32_neg_constant:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    addi sp, sp, -16
+; RV32I-NEXT:    .cfi_def_cfa_offset 16
+; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT:    .cfi_offset ra, -4
+; RV32I-NEXT:    li a1, -10
+; RV32I-NEXT:    call llvm.min.i32
+; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT:    addi sp, sp, 16
+; RV32I-NEXT:    ret
+;
+; RV64I-LABEL: smin_i32_neg_constant:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    addi sp, sp, -16
+; RV64I-NEXT:    .cfi_def_cfa_offset 16
+; RV64I-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT:    .cfi_offset ra, -8
+; RV64I-NEXT:    li a1, -10
+; RV64I-NEXT:    call llvm.min.i32
+; RV64I-NEXT:    sext.w a0, a0
+; RV64I-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT:    addi sp, sp, 16
+; RV64I-NEXT:    ret
+;
+; RV32ZBB-LABEL: smin_i32_neg_constant:
+; RV32ZBB:       # %bb.0:
+; RV32ZBB-NEXT:    addi sp, sp, -16
+; RV32ZBB-NEXT:    .cfi_def_cfa_offset 16
+; RV32ZBB-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
+; RV32ZBB-NEXT:    .cfi_offset ra, -4
+; RV32ZBB-NEXT:    li a1, -10
+; RV32ZBB-NEXT:    call llvm.min.i32
+; RV32ZBB-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
+; RV32ZBB-NEXT:    addi sp, sp, 16
+; RV32ZBB-NEXT:    ret
+;
+; RV64ZBB-LABEL: smin_i32_neg_constant:
+; RV64ZBB:       # %bb.0:
+; RV64ZBB-NEXT:    addi sp, sp, -16
+; RV64ZBB-NEXT:    .cfi_def_cfa_offset 16
+; RV64ZBB-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
+; RV64ZBB-NEXT:    .cfi_offset ra, -8
+; RV64ZBB-NEXT:    li a1, -10
+; RV64ZBB-NEXT:    call llvm.min.i32
+; RV64ZBB-NEXT:    sext.w a0, a0
+; RV64ZBB-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
+; RV64ZBB-NEXT:    addi sp, sp, 16
+; RV64ZBB-NEXT:    ret
+  %c = call i32 @llvm.min.i32(i32 %a, i32 -10)
+  ret i32 %c
+}
+
 define signext i32 @smax_i32_pos_constant_trailing_zeros(i32 signext %a) {
 ; NOZBB-LABEL: smax_i32_pos_constant_trailing_zeros:
 ; NOZBB:       # %bb.0:
 ; NOZBB-NEXT:    andi a0, a0, -8
 ; NOZBB-NEXT:    li a1, 16
-; NOZBB-NEXT:    blt a1, a0, .LBB25_2
+; NOZBB-NEXT:    blt a1, a0, .LBB26_2
 ; NOZBB-NEXT:  # %bb.1:
 ; NOZBB-NEXT:    li a0, 16
-; NOZBB-NEXT:  .LBB25_2:
+; NOZBB-NEXT:  .LBB26_2:
 ; NOZBB-NEXT:    ret
 ;
 ; ZBB-LABEL: smax_i32_pos_constant_trailing_zeros:
@@ -680,15 +734,15 @@ define i64 @umax_i64_one(i64 %a, i64 %b) {
 ; RV32I-LABEL: umax_i64_one:
 ; RV32I:       # %bb.0:
 ; RV32I-NEXT:    mv a2, a0
-; RV32I-NEXT:    beqz a1, .LBB28_3
+; RV32I-NEXT:    beqz a1, .LBB29_3
 ; RV32I-NEXT:  # %bb.1:
-; RV32I-NEXT:    beqz a1, .LBB28_4
-; RV32I-NEXT:  .LBB28_2:
+; RV32I-NEXT:    beqz a1, .LBB29_4
+; RV32I-NEXT:  .LBB29_2:
 ; RV32I-NEXT:    ret
-; RV32I-NEXT:  .LBB28_3:
+; RV32I-NEXT:  .LBB29_3:
 ; RV32I-NEXT:    li a0, 1
-; RV32I-NEXT:    bnez a1, .LBB28_2
-; RV32I-NEXT:  .LBB28_4:
+; RV32I-NEXT:    bnez a1, .LBB29_2
+; RV32I-NEXT:  .LBB29_4:
 ; RV32I-NEXT:    seqz a0, a2
 ; RV32I-NEXT:    add a0, a2, a0
 ; RV32I-NEXT:    ret
@@ -703,15 +757,15 @@ define i64 @umax_i64_one(i64 %a, i64 %b) {
 ; RV32ZBB:       # %bb.0:
 ; RV32ZBB-NEXT:    mv a2, a0
 ; RV32ZBB-NEXT:    li a3, 1
-; RV32ZBB-NEXT:    beqz a1, .LBB28_3
+; RV32ZBB-NEXT:    beqz a1, .LBB29_3
 ; RV32ZBB-NEXT:  # %bb.1:
-; RV32ZBB-NEXT:    beqz a1, .LBB28_4
-; RV32ZBB-NEXT:  .LBB28_2:
+; RV32ZBB-NEXT:    beqz a1, .LBB29_4
+; RV32ZBB-NEXT:  .LBB29_2:
 ; RV32ZBB-NEXT:    ret
-; RV32ZBB-NEXT:  .LBB28_3:
+; RV32ZBB-NEXT:  .LBB29_3:
 ; RV32ZBB-NEXT:    li a0, 1
-; RV32ZBB-NEXT:    bnez a1, .LBB28_2
-; RV32ZBB-NEXT:  .LBB28_4:
+; RV32ZBB-NEXT:    bnez a1, .LBB29_2
+; RV32ZBB-NEXT:  .LBB29_4:
 ; RV32ZBB-NEXT:    maxu a0, a2, a3
 ; RV32ZBB-NEXT:    ret
 ;



More information about the llvm-commits mailing list