-
Notifications
You must be signed in to change notification settings - Fork 10.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[SelectionDAG] Add more cases for UDIV and SDIV #86452
base: main
Are you sure you want to change the base?
Conversation
Also have UDIV just exit early if it can calculate that LHS is less than the RHS.
@llvm/pr-subscribers-llvm-selectiondag @llvm/pr-subscribers-llvm-support Author: AtariDreams (AtariDreams) ChangesAlso have UDIV just exit early if it can calculate that LHS is less than the RHS. Full diff: https://github.com/llvm/llvm-project/pull/86452.diff 2 Files Affected:
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 0ab5142ab81676..5f80c7c7315ee4 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -5392,14 +5392,39 @@ bool SelectionDAG::isKnownNeverZero(SDValue Op, unsigned Depth) const {
return true;
break;
}
- case ISD::UDIV:
- case ISD::SDIV:
+ case ISD::UDIV: {
// div exact can only produce a zero if the dividend is zero.
- // TODO: For udiv this is also true if Op1 u<= Op0
if (Op->getFlags().hasExact())
return isKnownNeverZero(Op.getOperand(0), Depth + 1);
+
+ // If Op1 <= Op0, then Op0 is at least 1, and therefore not 0.
+ KnownBits Op0 = computeKnownBits(Op.getOperand(0), Depth + 1);
+ KnownBits Op1 = computeKnownBits(Op.getOperand(1), Depth + 1);
+ std::optional<bool> uge = KnownBits::uge(Op0, Op1);
+ if (uge && *uge)
+ return true;
+
+ if (KnownBits::udiv(Op0, Op1).isNonZero())
+ return true;
break;
+ }
+ case ISD::SDIV: {
+ // div exact can only produce a zero if the dividend is zero.
+ if (Op->getFlags().hasExact())
+ return isKnownNeverZero(Op.getOperand(0), Depth + 1);
+ KnownBits Op0 = computeKnownBits(Op.getOperand(0), Depth + 1);
+ KnownBits Op1 = computeKnownBits(Op.getOperand(1), Depth + 1);
+ if (Op0.isStrictlyPositive() && Op1.isStrictlyPositive()) {
+ std::optional<bool> uge = KnownBits::uge(Op0, Op1);
+ if (uge && *uge)
+ return true;
+ }
+
+ if (KnownBits::sdiv(Op0, Op1).isNonZero())
+ return true;
+ break;
+ }
case ISD::ADD:
if (Op->getFlags().hasNoUnsignedWrap())
if (isKnownNeverZero(Op.getOperand(1), Depth + 1) ||
diff --git a/llvm/lib/Support/KnownBits.cpp b/llvm/lib/Support/KnownBits.cpp
index d72355dab6f1d3..fac9980a9349fc 100644
--- a/llvm/lib/Support/KnownBits.cpp
+++ b/llvm/lib/Support/KnownBits.cpp
@@ -979,7 +979,9 @@ KnownBits KnownBits::udiv(const KnownBits &LHS, const KnownBits &RHS,
assert(!LHS.hasConflict() && !RHS.hasConflict());
KnownBits Known(BitWidth);
- if (LHS.isZero() || RHS.isZero()) {
+ // if LHS < RHS, then LHS / RHS is 0.
+ std::optional<bool> ult = KnownBits::ult(LHS, RHS);
+ if (LHS.isZero() || RHS.isZero() || (ult && *ult)) {
// Result is either known Zero or UB. Return Zero either way.
// Checking this earlier saves us a lot of special cases later on.
Known.setAllZero();
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
✅ With the latest revision this PR passed the Python code formatter. |
Can you make the title more descriptive? Add more cases where? |
Tests? |
if (uge && *uge) | ||
return true; | ||
|
||
if (KnownBits::udiv(Op0, Op1).isNonZero()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We fall back to calling computeKnownBits(Op, Depth).isNonZero()
after the switch in this function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just return KnownBits::udiv(Op0, Op1).isNonZero();
if (Op->getFlags().hasExact()) | ||
return isKnownNeverZero(Op.getOperand(0), Depth + 1); | ||
|
||
// If Op1 <= Op0, then Op0 is at least 1, and therefore not 0. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// If Op1 <= Op0, then Op0 is at least 1, and therefore not 0. | |
// If Op0 >= Op1, then the result is at least 1, and therefore not 0. |
// If Op1 <= Op0, then Op0 is at least 1, and therefore not 0. | ||
KnownBits Op0 = computeKnownBits(Op.getOperand(0), Depth + 1); | ||
KnownBits Op1 = computeKnownBits(Op.getOperand(1), Depth + 1); | ||
std::optional<bool> uge = KnownBits::uge(Op0, Op1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CamelCase for variables, here and elsewhere.
// if LHS < RHS, then LHS / RHS is 0. | ||
std::optional<bool> ult = KnownBits::ult(LHS, RHS); | ||
if (LHS.isZero() || RHS.isZero() || (ult && *ult)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please split this into a separate patch with unit test coverage.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please branch off the KnownBits.cpp changes into its own PR
Also, still waiting for test cases :)
std::optional<bool> uge = KnownBits::uge(Op0, Op1); | ||
if (uge && *uge) | ||
return true; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (Op0.isStrictlyPositive() && Op1.isStrictlyPositive() &&
KnownBits::uge(Op0, Op1).value_or(false))
return true;
if (uge && *uge) | ||
return true; | ||
|
||
if (KnownBits::udiv(Op0, Op1).isNonZero()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just return KnownBits::udiv(Op0, Op1).isNonZero();
|
||
if (KnownBits::sdiv(Op0, Op1).isNonZero()) | ||
return true; | ||
break; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return KnownBits::sdiv(Op0, Op1).isNonZero();
Also have UDIV just exit early if it can calculate that LHS is less than the RHS.