[llvm] [SelectionDAG]: Deduce known bits from SMIN and SMAX (PR #85722)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Mar 20 16:54:21 PDT 2024
https://github.com/AtariDreams updated https://github.com/llvm/llvm-project/pull/85722
>From 8e9ca522f32e0ddce2513f49244b3ddb1ef695fb Mon Sep 17 00:00:00 2001
From: Rose <gfunni234 at gmail.com>
Date: Mon, 18 Mar 2024 20:40:32 -0400
Subject: [PATCH 1/2] [SelectionDAG]: Pre-commit tests (NFC)
---
llvm/test/CodeGen/X86/known-never-zero.ll | 122 ++++++++++++++--------
1 file changed, 78 insertions(+), 44 deletions(-)
diff --git a/llvm/test/CodeGen/X86/known-never-zero.ll b/llvm/test/CodeGen/X86/known-never-zero.ll
index cc9862769f2b66..f192ddd73a4810 100644
--- a/llvm/test/CodeGen/X86/known-never-zero.ll
+++ b/llvm/test/CodeGen/X86/known-never-zero.ll
@@ -267,6 +267,21 @@ define i32 @smin_known_nonzero(i32 %xx, i32 %yy) {
ret i32 %r
}
+define i32 @smin_known_zero_2(i32 %x, i32 %y) {
+; CHECK-LABEL: smin_known_zero_2:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cmpl $-54, %edi
+; CHECK-NEXT: movl $-54, %eax
+; CHECK-NEXT: cmovll %edi, %eax
+; CHECK-NEXT: bsfl %eax, %ecx
+; CHECK-NEXT: movl $32, %eax
+; CHECK-NEXT: cmovnel %ecx, %eax
+; CHECK-NEXT: retq
+ %z = call i32 @llvm.smin.i32(i32 %x, i32 -54)
+ %r = call i32 @llvm.cttz.i32(i32 %z, i1 false)
+ ret i32 %r
+}
+
define i32 @smin_maybe_zero(i32 %x, i32 %y) {
; CHECK-LABEL: smin_maybe_zero:
; CHECK: # %bb.0:
@@ -274,11 +289,11 @@ define i32 @smin_maybe_zero(i32 %x, i32 %y) {
; CHECK-NEXT: movl $54, %eax
; CHECK-NEXT: cmovll %edi, %eax
; CHECK-NEXT: testl %eax, %eax
-; CHECK-NEXT: je .LBB15_1
+; CHECK-NEXT: je .LBB16_1
; CHECK-NEXT: # %bb.2: # %cond.false
; CHECK-NEXT: rep bsfl %eax, %eax
; CHECK-NEXT: retq
-; CHECK-NEXT: .LBB15_1:
+; CHECK-NEXT: .LBB16_1:
; CHECK-NEXT: movl $32, %eax
; CHECK-NEXT: retq
%z = call i32 @llvm.smin.i32(i32 %x, i32 54)
@@ -305,8 +320,8 @@ define i32 @smax_known_nonzero(i32 %xx, i32 %yy) {
ret i32 %r
}
-define i32 @smax_maybe_zero(i32 %x, i32 %y) {
-; CHECK-LABEL: smax_maybe_zero:
+define i32 @smax_known_zero_2(i32 %x, i32 %y) {
+; CHECK-LABEL: smax_known_zero_2:
; CHECK: # %bb.0:
; CHECK-NEXT: cmpl $55, %edi
; CHECK-NEXT: movl $54, %eax
@@ -320,6 +335,25 @@ define i32 @smax_maybe_zero(i32 %x, i32 %y) {
ret i32 %r
}
+define i32 @smax_maybe_zero(i32 %x, i32 %y) {
+; CHECK-LABEL: smax_maybe_zero:
+; CHECK: # %bb.0:
+; CHECK-NEXT: testl %edi, %edi
+; CHECK-NEXT: movl $-1, %eax
+; CHECK-NEXT: cmovnsl %edi, %eax
+; CHECK-NEXT: testl %eax, %eax
+; CHECK-NEXT: je .LBB19_1
+; CHECK-NEXT: # %bb.2: # %cond.false
+; CHECK-NEXT: rep bsfl %eax, %eax
+; CHECK-NEXT: retq
+; CHECK-NEXT: .LBB19_1:
+; CHECK-NEXT: movl $32, %eax
+; CHECK-NEXT: retq
+ %z = call i32 @llvm.smax.i32(i32 %x, i32 -1)
+ %r = call i32 @llvm.cttz.i32(i32 %z, i1 false)
+ ret i32 %r
+}
+
define i32 @rotr_known_nonzero(i32 %xx, i32 %y) {
; CHECK-LABEL: rotr_known_nonzero:
; CHECK: # %bb.0:
@@ -328,11 +362,11 @@ define i32 @rotr_known_nonzero(i32 %xx, i32 %y) {
; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
; CHECK-NEXT: rorl %cl, %edi
; CHECK-NEXT: testl %edi, %edi
-; CHECK-NEXT: je .LBB18_1
+; CHECK-NEXT: je .LBB20_1
; CHECK-NEXT: # %bb.2: # %cond.false
; CHECK-NEXT: rep bsfl %edi, %eax
; CHECK-NEXT: retq
-; CHECK-NEXT: .LBB18_1:
+; CHECK-NEXT: .LBB20_1:
; CHECK-NEXT: movl $32, %eax
; CHECK-NEXT: retq
%x = or i32 %xx, 256
@@ -351,11 +385,11 @@ define i32 @rotr_maybe_zero(i32 %x, i32 %y) {
; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
; CHECK-NEXT: rorl %cl, %edi
; CHECK-NEXT: testl %edi, %edi
-; CHECK-NEXT: je .LBB19_1
+; CHECK-NEXT: je .LBB21_1
; CHECK-NEXT: # %bb.2: # %cond.false
; CHECK-NEXT: rep bsfl %edi, %eax
; CHECK-NEXT: retq
-; CHECK-NEXT: .LBB19_1:
+; CHECK-NEXT: .LBB21_1:
; CHECK-NEXT: movl $32, %eax
; CHECK-NEXT: retq
%shr = lshr i32 %x, %y
@@ -388,11 +422,11 @@ define i32 @rotr_with_fshr_maybe_zero(i32 %x, i32 %y) {
; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
; CHECK-NEXT: rorl %cl, %edi
; CHECK-NEXT: testl %edi, %edi
-; CHECK-NEXT: je .LBB21_1
+; CHECK-NEXT: je .LBB23_1
; CHECK-NEXT: # %bb.2: # %cond.false
; CHECK-NEXT: rep bsfl %edi, %eax
; CHECK-NEXT: retq
-; CHECK-NEXT: .LBB21_1:
+; CHECK-NEXT: .LBB23_1:
; CHECK-NEXT: movl $32, %eax
; CHECK-NEXT: retq
%z = call i32 @llvm.fshr.i32(i32 %x, i32 %x, i32 %y)
@@ -408,11 +442,11 @@ define i32 @rotl_known_nonzero(i32 %xx, i32 %y) {
; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
; CHECK-NEXT: roll %cl, %edi
; CHECK-NEXT: testl %edi, %edi
-; CHECK-NEXT: je .LBB22_1
+; CHECK-NEXT: je .LBB24_1
; CHECK-NEXT: # %bb.2: # %cond.false
; CHECK-NEXT: rep bsfl %edi, %eax
; CHECK-NEXT: retq
-; CHECK-NEXT: .LBB22_1:
+; CHECK-NEXT: .LBB24_1:
; CHECK-NEXT: movl $32, %eax
; CHECK-NEXT: retq
%x = or i32 %xx, 256
@@ -431,11 +465,11 @@ define i32 @rotl_maybe_zero(i32 %x, i32 %y) {
; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
; CHECK-NEXT: roll %cl, %edi
; CHECK-NEXT: testl %edi, %edi
-; CHECK-NEXT: je .LBB23_1
+; CHECK-NEXT: je .LBB25_1
; CHECK-NEXT: # %bb.2: # %cond.false
; CHECK-NEXT: rep bsfl %edi, %eax
; CHECK-NEXT: retq
-; CHECK-NEXT: .LBB23_1:
+; CHECK-NEXT: .LBB25_1:
; CHECK-NEXT: movl $32, %eax
; CHECK-NEXT: retq
%shl = shl i32 %x, %y
@@ -468,11 +502,11 @@ define i32 @rotl_with_fshl_maybe_zero(i32 %x, i32 %y) {
; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
; CHECK-NEXT: roll %cl, %edi
; CHECK-NEXT: testl %edi, %edi
-; CHECK-NEXT: je .LBB25_1
+; CHECK-NEXT: je .LBB27_1
; CHECK-NEXT: # %bb.2: # %cond.false
; CHECK-NEXT: rep bsfl %edi, %eax
; CHECK-NEXT: retq
-; CHECK-NEXT: .LBB25_1:
+; CHECK-NEXT: .LBB27_1:
; CHECK-NEXT: movl $32, %eax
; CHECK-NEXT: retq
%z = call i32 @llvm.fshl.i32(i32 %x, i32 %x, i32 %y)
@@ -516,11 +550,11 @@ define i32 @sra_maybe_zero(i32 %x, i32 %y) {
; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
; CHECK-NEXT: sarl %cl, %esi
; CHECK-NEXT: testl %esi, %esi
-; CHECK-NEXT: je .LBB28_1
+; CHECK-NEXT: je .LBB30_1
; CHECK-NEXT: # %bb.2: # %cond.false
; CHECK-NEXT: rep bsfl %esi, %eax
; CHECK-NEXT: retq
-; CHECK-NEXT: .LBB28_1:
+; CHECK-NEXT: .LBB30_1:
; CHECK-NEXT: movl $32, %eax
; CHECK-NEXT: retq
%z = ashr exact i32 %y, %x
@@ -564,11 +598,11 @@ define i32 @srl_maybe_zero(i32 %x, i32 %y) {
; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
; CHECK-NEXT: shrl %cl, %esi
; CHECK-NEXT: testl %esi, %esi
-; CHECK-NEXT: je .LBB31_1
+; CHECK-NEXT: je .LBB33_1
; CHECK-NEXT: # %bb.2: # %cond.false
; CHECK-NEXT: rep bsfl %esi, %eax
; CHECK-NEXT: retq
-; CHECK-NEXT: .LBB31_1:
+; CHECK-NEXT: .LBB33_1:
; CHECK-NEXT: movl $32, %eax
; CHECK-NEXT: retq
%z = lshr exact i32 %y, %x
@@ -598,11 +632,11 @@ define i32 @udiv_maybe_zero(i32 %x, i32 %y) {
; CHECK-NEXT: xorl %edx, %edx
; CHECK-NEXT: divl %esi
; CHECK-NEXT: testl %eax, %eax
-; CHECK-NEXT: je .LBB33_1
+; CHECK-NEXT: je .LBB35_1
; CHECK-NEXT: # %bb.2: # %cond.false
; CHECK-NEXT: rep bsfl %eax, %eax
; CHECK-NEXT: retq
-; CHECK-NEXT: .LBB33_1:
+; CHECK-NEXT: .LBB35_1:
; CHECK-NEXT: movl $32, %eax
; CHECK-NEXT: retq
%z = udiv exact i32 %x, %y
@@ -632,11 +666,11 @@ define i32 @sdiv_maybe_zero(i32 %x, i32 %y) {
; CHECK-NEXT: cltd
; CHECK-NEXT: idivl %esi
; CHECK-NEXT: testl %eax, %eax
-; CHECK-NEXT: je .LBB35_1
+; CHECK-NEXT: je .LBB37_1
; CHECK-NEXT: # %bb.2: # %cond.false
; CHECK-NEXT: rep bsfl %eax, %eax
; CHECK-NEXT: retq
-; CHECK-NEXT: .LBB35_1:
+; CHECK-NEXT: .LBB37_1:
; CHECK-NEXT: movl $32, %eax
; CHECK-NEXT: retq
%z = sdiv exact i32 %x, %y
@@ -662,11 +696,11 @@ define i32 @add_maybe_zero(i32 %xx, i32 %y) {
; CHECK: # %bb.0:
; CHECK-NEXT: orl $1, %edi
; CHECK-NEXT: addl %esi, %edi
-; CHECK-NEXT: je .LBB37_1
+; CHECK-NEXT: je .LBB39_1
; CHECK-NEXT: # %bb.2: # %cond.false
; CHECK-NEXT: rep bsfl %edi, %eax
; CHECK-NEXT: retq
-; CHECK-NEXT: .LBB37_1:
+; CHECK-NEXT: .LBB39_1:
; CHECK-NEXT: movl $32, %eax
; CHECK-NEXT: retq
%x = or i32 %xx, 1
@@ -713,11 +747,11 @@ define i32 @sub_maybe_zero(i32 %x) {
; CHECK-NEXT: movl %edi, %eax
; CHECK-NEXT: orl $64, %eax
; CHECK-NEXT: subl %edi, %eax
-; CHECK-NEXT: je .LBB40_1
+; CHECK-NEXT: je .LBB42_1
; CHECK-NEXT: # %bb.2: # %cond.false
; CHECK-NEXT: rep bsfl %eax, %eax
; CHECK-NEXT: retq
-; CHECK-NEXT: .LBB40_1:
+; CHECK-NEXT: .LBB42_1:
; CHECK-NEXT: movl $32, %eax
; CHECK-NEXT: retq
%y = or i32 %x, 64
@@ -730,11 +764,11 @@ define i32 @sub_maybe_zero2(i32 %x) {
; CHECK-LABEL: sub_maybe_zero2:
; CHECK: # %bb.0:
; CHECK-NEXT: negl %edi
-; CHECK-NEXT: je .LBB41_1
+; CHECK-NEXT: je .LBB43_1
; CHECK-NEXT: # %bb.2: # %cond.false
; CHECK-NEXT: rep bsfl %edi, %eax
; CHECK-NEXT: retq
-; CHECK-NEXT: .LBB41_1:
+; CHECK-NEXT: .LBB43_1:
; CHECK-NEXT: movl $32, %eax
; CHECK-NEXT: retq
%z = sub i32 0, %x
@@ -748,11 +782,11 @@ define i32 @mul_known_nonzero_nsw(i32 %x, i32 %yy) {
; CHECK-NEXT: orl $256, %esi # imm = 0x100
; CHECK-NEXT: imull %edi, %esi
; CHECK-NEXT: testl %esi, %esi
-; CHECK-NEXT: je .LBB42_1
+; CHECK-NEXT: je .LBB44_1
; CHECK-NEXT: # %bb.2: # %cond.false
; CHECK-NEXT: rep bsfl %esi, %eax
; CHECK-NEXT: retq
-; CHECK-NEXT: .LBB42_1:
+; CHECK-NEXT: .LBB44_1:
; CHECK-NEXT: movl $32, %eax
; CHECK-NEXT: retq
%y = or i32 %yy, 256
@@ -767,11 +801,11 @@ define i32 @mul_known_nonzero_nuw(i32 %x, i32 %yy) {
; CHECK-NEXT: orl $256, %esi # imm = 0x100
; CHECK-NEXT: imull %edi, %esi
; CHECK-NEXT: testl %esi, %esi
-; CHECK-NEXT: je .LBB43_1
+; CHECK-NEXT: je .LBB45_1
; CHECK-NEXT: # %bb.2: # %cond.false
; CHECK-NEXT: rep bsfl %esi, %eax
; CHECK-NEXT: retq
-; CHECK-NEXT: .LBB43_1:
+; CHECK-NEXT: .LBB45_1:
; CHECK-NEXT: movl $32, %eax
; CHECK-NEXT: retq
%y = or i32 %yy, 256
@@ -785,11 +819,11 @@ define i32 @mul_maybe_zero(i32 %x, i32 %y) {
; CHECK: # %bb.0:
; CHECK-NEXT: imull %esi, %edi
; CHECK-NEXT: testl %edi, %edi
-; CHECK-NEXT: je .LBB44_1
+; CHECK-NEXT: je .LBB46_1
; CHECK-NEXT: # %bb.2: # %cond.false
; CHECK-NEXT: rep bsfl %edi, %eax
; CHECK-NEXT: retq
-; CHECK-NEXT: .LBB44_1:
+; CHECK-NEXT: .LBB46_1:
; CHECK-NEXT: movl $32, %eax
; CHECK-NEXT: retq
%z = mul nuw nsw i32 %y, %x
@@ -822,11 +856,11 @@ define i32 @bitcast_maybe_zero(<2 x i16> %x) {
; CHECK: # %bb.0:
; CHECK-NEXT: movd %xmm0, %eax
; CHECK-NEXT: testl %eax, %eax
-; CHECK-NEXT: je .LBB46_1
+; CHECK-NEXT: je .LBB48_1
; CHECK-NEXT: # %bb.2: # %cond.false
; CHECK-NEXT: rep bsfl %eax, %eax
; CHECK-NEXT: retq
-; CHECK-NEXT: .LBB46_1:
+; CHECK-NEXT: .LBB48_1:
; CHECK-NEXT: movl $32, %eax
; CHECK-NEXT: retq
%z = bitcast <2 x i16> %x to i32
@@ -839,11 +873,11 @@ define i32 @bitcast_from_float(float %x) {
; CHECK: # %bb.0:
; CHECK-NEXT: movd %xmm0, %eax
; CHECK-NEXT: testl %eax, %eax
-; CHECK-NEXT: je .LBB47_1
+; CHECK-NEXT: je .LBB49_1
; CHECK-NEXT: # %bb.2: # %cond.false
; CHECK-NEXT: rep bsfl %eax, %eax
; CHECK-NEXT: retq
-; CHECK-NEXT: .LBB47_1:
+; CHECK-NEXT: .LBB49_1:
; CHECK-NEXT: movl $32, %eax
; CHECK-NEXT: retq
%z = bitcast float %x to i32
@@ -871,12 +905,12 @@ define i32 @zext_maybe_zero(i16 %x) {
; CHECK-LABEL: zext_maybe_zero:
; CHECK: # %bb.0:
; CHECK-NEXT: testw %di, %di
-; CHECK-NEXT: je .LBB49_1
+; CHECK-NEXT: je .LBB51_1
; CHECK-NEXT: # %bb.2: # %cond.false
; CHECK-NEXT: movzwl %di, %eax
; CHECK-NEXT: rep bsfl %eax, %eax
; CHECK-NEXT: retq
-; CHECK-NEXT: .LBB49_1:
+; CHECK-NEXT: .LBB51_1:
; CHECK-NEXT: movl $32, %eax
; CHECK-NEXT: retq
%z = zext i16 %x to i32
@@ -904,12 +938,12 @@ define i32 @sext_maybe_zero(i16 %x) {
; CHECK-LABEL: sext_maybe_zero:
; CHECK: # %bb.0:
; CHECK-NEXT: testw %di, %di
-; CHECK-NEXT: je .LBB51_1
+; CHECK-NEXT: je .LBB53_1
; CHECK-NEXT: # %bb.2: # %cond.false
; CHECK-NEXT: movswl %di, %eax
; CHECK-NEXT: rep bsfl %eax, %eax
; CHECK-NEXT: retq
-; CHECK-NEXT: .LBB51_1:
+; CHECK-NEXT: .LBB53_1:
; CHECK-NEXT: movl $32, %eax
; CHECK-NEXT: retq
%z = sext i16 %x to i32
>From 3fc470c980e77dd75e7b94bedb982b2ce51bb5e0 Mon Sep 17 00:00:00 2001
From: Rose <gfunni234 at gmail.com>
Date: Mon, 18 Mar 2024 23:17:15 -0400
Subject: [PATCH 2/2] [SelectionDAG]: Deduce known bits from SMIN and SMAX
---
.../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 37 +++++++++++++++++--
llvm/test/CodeGen/X86/known-never-zero.ll | 8 +---
2 files changed, 36 insertions(+), 9 deletions(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 9d73a42df2a479..7710e47d2ff14c 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -5360,10 +5360,41 @@ bool SelectionDAG::isKnownNeverZero(SDValue Op, unsigned Depth) const {
return isKnownNeverZero(Op.getOperand(1), Depth + 1) ||
isKnownNeverZero(Op.getOperand(0), Depth + 1);
- // TODO for smin/smax: If either operand is known negative/positive
+ // For smin/smax: If either operand is known negative/positive
// respectively we don't need the other to be known at all.
- case ISD::SMAX:
- case ISD::SMIN:
+ case ISD::SMAX: {
+ KnownBits Op1 = computeKnownBits(Op.getOperand(1), Depth + 1);
+ if (Op1.isStrictlyPositive())
+ return true;
+
+ KnownBits Op0 = computeKnownBits(Op.getOperand(0), Depth + 1);
+
+ if (Op0.isStrictlyPositive())
+ return true;
+
+ if (Op1.isNonZero() && Op0.isNonZero())
+ return true;
+
+ return isKnownNeverZero(Op.getOperand(1), Depth + 1) &&
+ isKnownNeverZero(Op.getOperand(0), Depth + 1);
+ }
+ case ISD::SMIN: {
+ KnownBits Op1 = computeKnownBits(Op.getOperand(1), Depth + 1);
+ if (Op1.isNegative())
+ return true;
+
+ KnownBits Op0 = computeKnownBits(Op.getOperand(0), Depth + 1);
+
+ if (Op0.isNegative())
+ return true;
+
+ if (computeKnownBits(Op.getOperand(1), Depth + 1).isNonZero() &&
+ computeKnownBits(Op.getOperand(0), Depth + 1).isNonZero())
+ return true;
+
+ return isKnownNeverZero(Op.getOperand(1), Depth + 1) &&
+ isKnownNeverZero(Op.getOperand(0), Depth + 1);
+ }
case ISD::UMIN:
return isKnownNeverZero(Op.getOperand(1), Depth + 1) &&
isKnownNeverZero(Op.getOperand(0), Depth + 1);
diff --git a/llvm/test/CodeGen/X86/known-never-zero.ll b/llvm/test/CodeGen/X86/known-never-zero.ll
index f192ddd73a4810..41182879f9a160 100644
--- a/llvm/test/CodeGen/X86/known-never-zero.ll
+++ b/llvm/test/CodeGen/X86/known-never-zero.ll
@@ -273,9 +273,7 @@ define i32 @smin_known_zero_2(i32 %x, i32 %y) {
; CHECK-NEXT: cmpl $-54, %edi
; CHECK-NEXT: movl $-54, %eax
; CHECK-NEXT: cmovll %edi, %eax
-; CHECK-NEXT: bsfl %eax, %ecx
-; CHECK-NEXT: movl $32, %eax
-; CHECK-NEXT: cmovnel %ecx, %eax
+; CHECK-NEXT: rep bsfl %eax, %eax
; CHECK-NEXT: retq
%z = call i32 @llvm.smin.i32(i32 %x, i32 -54)
%r = call i32 @llvm.cttz.i32(i32 %z, i1 false)
@@ -326,9 +324,7 @@ define i32 @smax_known_zero_2(i32 %x, i32 %y) {
; CHECK-NEXT: cmpl $55, %edi
; CHECK-NEXT: movl $54, %eax
; CHECK-NEXT: cmovgel %edi, %eax
-; CHECK-NEXT: bsfl %eax, %ecx
-; CHECK-NEXT: movl $32, %eax
-; CHECK-NEXT: cmovnel %ecx, %eax
+; CHECK-NEXT: rep bsfl %eax, %eax
; CHECK-NEXT: retq
%z = call i32 @llvm.smax.i32(i32 %x, i32 54)
%r = call i32 @llvm.cttz.i32(i32 %z, i1 false)
More information about the llvm-commits
mailing list