aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Support/KnownBits.cpp
diff options
context:
space:
mode:
authorNoah Goldstein <goldstein.w.n@gmail.com>2023-05-06 20:58:08 -0500
committerNoah Goldstein <goldstein.w.n@gmail.com>2023-05-16 18:58:12 -0500
commit8c569c922bc5bbe9fb67ff3ff3ac28e17b012360 (patch)
treebd1a9c7178b906a26bcac9c709aed88f024f013d /llvm/lib/Support/KnownBits.cpp
parent53a079c8f723ca6a33c76a4818d47a66fd65ca38 (diff)
downloadllvm-8c569c922bc5bbe9fb67ff3ff3ac28e17b012360.zip
llvm-8c569c922bc5bbe9fb67ff3ff3ac28e17b012360.tar.gz
llvm-8c569c922bc5bbe9fb67ff3ff3ac28e17b012360.tar.bz2
[KnownBits] Add implementation for `KnownBits::sdiv`
Can figure out some of the upper bits (similiar to `udiv`) if we know the sign of the inputs. As well, if we have the `exact` flag we can sometimes determine some low-bits. Differential Revision: https://reviews.llvm.org/D150093
Diffstat (limited to 'llvm/lib/Support/KnownBits.cpp')
-rw-r--r--llvm/lib/Support/KnownBits.cpp68
1 files changed, 68 insertions, 0 deletions
diff --git a/llvm/lib/Support/KnownBits.cpp b/llvm/lib/Support/KnownBits.cpp
index ddeb6a4..a00cc04 100644
--- a/llvm/lib/Support/KnownBits.cpp
+++ b/llvm/lib/Support/KnownBits.cpp
@@ -536,6 +536,74 @@ KnownBits KnownBits::mulhu(const KnownBits &LHS, const KnownBits &RHS) {
return mul(WideLHS, WideRHS).extractBits(BitWidth, BitWidth);
}
+KnownBits KnownBits::sdiv(const KnownBits &LHS, const KnownBits &RHS,
+ bool Exact) {
+ // Equivilent of `udiv`. We must have caught this before it was folded.
+ if (LHS.isNonNegative() && RHS.isNonNegative())
+ return udiv(LHS, RHS);
+
+ unsigned BitWidth = LHS.getBitWidth();
+ assert(!LHS.hasConflict() && !RHS.hasConflict() && "Bad inputs");
+ KnownBits Known(BitWidth);
+
+ APInt Num, Denum;
+ // Positive -> true
+ // Negative -> false
+ // Unknown -> nullopt
+ std::optional<bool> ResultSign;
+ if (LHS.isNegative() && RHS.isNegative()) {
+ Denum = RHS.getSignedMaxValue();
+ Num = LHS.getSignedMinValue();
+ ResultSign = true;
+ // Result non-negative.
+ } else if (LHS.isNegative() && RHS.isStrictlyPositive()) {
+ // Result is non-negative if Exact OR -LHS u>= RHS.
+ if (Exact || (-LHS.getSignedMaxValue()).uge(RHS.getSignedMaxValue())) {
+ Denum = RHS.getSignedMinValue();
+ Num = LHS.getSignedMinValue();
+ ResultSign = false;
+ }
+ } else if (LHS.isStrictlyPositive() && RHS.isNegative()) {
+ // Result is non-negative if Exact OR LHS u>= -RHS.
+ if (Exact || LHS.getSignedMinValue().uge(-RHS.getSignedMinValue())) {
+ Denum = RHS.getSignedMaxValue();
+ Num = LHS.getSignedMaxValue();
+ ResultSign = false;
+ }
+ }
+
+ if (ResultSign) {
+ APInt Res = Num.sdiv(Denum);
+ if (*ResultSign) {
+ unsigned LeadZ = Res.countLeadingZeros();
+ Known.Zero.setHighBits(LeadZ);
+ Known.makeNonNegative();
+ } else {
+ unsigned LeadO = Res.countLeadingOnes();
+ Known.One.setHighBits(LeadO);
+ Known.makeNegative();
+ }
+ }
+
+ if (Exact) {
+ // Odd / Odd -> Odd
+ if (LHS.One[0] && RHS.One[0]) {
+ Known.Zero.clearBit(0);
+ Known.One.setBit(0);
+ }
+ // Even / Odd -> Even
+ else if (LHS.Zero[0] && RHS.One[0]) {
+ Known.One.clearBit(0);
+ Known.Zero.setBit(0);
+ }
+ // Odd / Even -> impossible
+ // Even / Even -> unknown
+ }
+
+ assert(!Known.hasConflict() && "Bad Output");
+ return Known;
+}
+
KnownBits KnownBits::udiv(const KnownBits &LHS, const KnownBits &RHS) {
unsigned BitWidth = LHS.getBitWidth();
assert(!LHS.hasConflict() && !RHS.hasConflict());