[llvm] ac485e4 - [SelectionDAG] Add/Improve cases in `isKnownNeverZero`
Noah Goldstein via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 15 23:59:30 PDT 2023
Author: Noah Goldstein
Date: 2023-08-16T02:00:15-05:00
New Revision: ac485e40720fcdae3b1f5664143056e3dc89beb1
URL: https://github.com/llvm/llvm-project/commit/ac485e40720fcdae3b1f5664143056e3dc89beb1
DIFF: https://github.com/llvm/llvm-project/commit/ac485e40720fcdae3b1f5664143056e3dc89beb1.diff
LOG: [SelectionDAG] Add/Improve cases in `isKnownNeverZero`
1) Handle casts a bit more cleanly just with a loop rather than with
recursion.
2) Add additional cases for smin/smax
3 ) For shifts we can also deduce non-zero if the maximum shift amount
on the known 1s is non-zero.
Differential Revision: https://reviews.llvm.org/D156777
Added:
Modified:
llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
llvm/test/CodeGen/X86/known-never-zero.ll
Removed:
################################################################################
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 01043920530d9c..0271cad146aeaa 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -5088,21 +5088,29 @@ bool SelectionDAG::isKnownNeverZero(SDValue Op, unsigned Depth) const {
return isKnownNeverZero(Op.getOperand(1), Depth + 1) &&
isKnownNeverZero(Op.getOperand(2), Depth + 1);
- case ISD::SHL:
+ case ISD::SHL: {
if (Op->getFlags().hasNoSignedWrap() || Op->getFlags().hasNoUnsignedWrap())
return isKnownNeverZero(Op.getOperand(0), Depth + 1);
-
- // 1 << X is never zero. TODO: This can be expanded if we can bound X.
- // The expression is really !Known.One[BitWidth-MaxLog2(Known):0].isZero()
- if (computeKnownBits(Op.getOperand(0), Depth + 1).One[0])
+ KnownBits ValKnown = computeKnownBits(Op.getOperand(0), Depth + 1);
+ // 1 << X is never zero.
+ if (ValKnown.One[0])
+ return true;
+ // If max shift cnt of known ones is non-zero, result is non-zero.
+ APInt MaxCnt = computeKnownBits(Op.getOperand(1), Depth + 1).getMaxValue();
+ if (MaxCnt.ult(ValKnown.getBitWidth()) &&
+ !ValKnown.One.shl(MaxCnt).isZero())
return true;
break;
-
+ }
case ISD::UADDSAT:
case ISD::UMAX:
return isKnownNeverZero(Op.getOperand(1), Depth + 1) ||
isKnownNeverZero(Op.getOperand(0), Depth + 1);
+ // TODO 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::UMIN:
return isKnownNeverZero(Op.getOperand(1), Depth + 1) &&
isKnownNeverZero(Op.getOperand(0), Depth + 1);
@@ -5116,16 +5124,19 @@ bool SelectionDAG::isKnownNeverZero(SDValue Op, unsigned Depth) const {
return isKnownNeverZero(Op.getOperand(0), Depth + 1);
case ISD::SRA:
- case ISD::SRL:
+ case ISD::SRL: {
if (Op->getFlags().hasExact())
return isKnownNeverZero(Op.getOperand(0), Depth + 1);
- // Signed >> X is never zero. TODO: This can be expanded if we can bound X.
- // The expression is really
- // !Known.One[SignBit:SignBit-(BitWidth-MaxLog2(Known))].isZero()
- if (computeKnownBits(Op.getOperand(0), Depth + 1).isNegative())
+ KnownBits ValKnown = computeKnownBits(Op.getOperand(0), Depth + 1);
+ if (ValKnown.isNegative())
+ return true;
+ // If max shift cnt of known ones is non-zero, result is non-zero.
+ APInt MaxCnt = computeKnownBits(Op.getOperand(1), Depth + 1).getMaxValue();
+ if (MaxCnt.ult(ValKnown.getBitWidth()) &&
+ !ValKnown.One.lshr(MaxCnt).isZero())
return true;
break;
-
+ }
case ISD::UDIV:
case ISD::SDIV:
// div exact can only produce a zero if the dividend is zero.
diff --git a/llvm/test/CodeGen/X86/known-never-zero.ll b/llvm/test/CodeGen/X86/known-never-zero.ll
index 2c059f72a062c9..cc9862769f2b66 100644
--- a/llvm/test/CodeGen/X86/known-never-zero.ll
+++ b/llvm/test/CodeGen/X86/known-never-zero.ll
@@ -258,9 +258,7 @@ define i32 @smin_known_nonzero(i32 %xx, i32 %yy) {
; CHECK-NEXT: addl $4, %esi
; CHECK-NEXT: cmpl %esi, %eax
; CHECK-NEXT: cmovll %eax, %esi
-; CHECK-NEXT: bsfl %esi, %ecx
-; CHECK-NEXT: movl $32, %eax
-; CHECK-NEXT: cmovnel %ecx, %eax
+; CHECK-NEXT: rep bsfl %esi, %eax
; CHECK-NEXT: retq
%x = shl nuw i32 4, %xx
%y = add nuw nsw i32 %yy, 4
@@ -298,9 +296,7 @@ define i32 @smax_known_nonzero(i32 %xx, i32 %yy) {
; CHECK-NEXT: addl $4, %esi
; CHECK-NEXT: cmpl %esi, %eax
; CHECK-NEXT: cmovgl %eax, %esi
-; CHECK-NEXT: bsfl %esi, %ecx
-; CHECK-NEXT: movl $32, %eax
-; CHECK-NEXT: cmovnel %ecx, %eax
+; CHECK-NEXT: rep bsfl %esi, %eax
; CHECK-NEXT: retq
%x = shl nuw i32 4, %xx
%y = add nuw nsw i32 %yy, 4
More information about the llvm-commits
mailing list