-
Notifications
You must be signed in to change notification settings - Fork 11.1k
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
[ConstantRange] Handle Intrinsic::ctpop
#68310
Conversation
@llvm/pr-subscribers-llvm-transforms @llvm/pr-subscribers-llvm-ir ChangesThis patch adds support for Migrated from https://reviews.llvm.org/D153505. Full diff: https://github.com/llvm/llvm-project/pull/68310.diff 4 Files Affected:
diff --git a/llvm/include/llvm/IR/ConstantRange.h b/llvm/include/llvm/IR/ConstantRange.h
index ca36732e4e2e8c2..017f1f36d8a663e 100644
--- a/llvm/include/llvm/IR/ConstantRange.h
+++ b/llvm/include/llvm/IR/ConstantRange.h
@@ -530,6 +530,9 @@ class [[nodiscard]] ConstantRange {
/// ignoring a possible zero value contained in the input range.
ConstantRange ctlz(bool ZeroIsPoison = false) const;
+ /// Calculate ctpop range.
+ ConstantRange ctpop() const;
+
/// Represents whether an operation on the given constant range is known to
/// always or never overflow.
enum class OverflowResult {
diff --git a/llvm/lib/IR/ConstantRange.cpp b/llvm/lib/IR/ConstantRange.cpp
index 3d71b20f7e853e0..f00fb1f1b9f36cc 100644
--- a/llvm/lib/IR/ConstantRange.cpp
+++ b/llvm/lib/IR/ConstantRange.cpp
@@ -949,6 +949,7 @@ bool ConstantRange::isIntrinsicSupported(Intrinsic::ID IntrinsicID) {
case Intrinsic::smax:
case Intrinsic::abs:
case Intrinsic::ctlz:
+ case Intrinsic::ctpop:
return true;
default:
return false;
@@ -986,6 +987,8 @@ ConstantRange ConstantRange::intrinsic(Intrinsic::ID IntrinsicID,
assert(ZeroIsPoison->getBitWidth() == 1 && "Must be boolean");
return Ops[0].ctlz(ZeroIsPoison->getBoolValue());
}
+ case Intrinsic::ctpop:
+ return Ops[0].ctpop();
default:
assert(!isIntrinsicSupported(IntrinsicID) && "Shouldn't be supported");
llvm_unreachable("Unsupported intrinsic");
@@ -1736,6 +1739,52 @@ ConstantRange ConstantRange::ctlz(bool ZeroIsPoison) const {
APInt(getBitWidth(), getUnsignedMin().countl_zero() + 1));
}
+static ConstantRange getUnsignedPopCountRange(const APInt &Lower,
+ const APInt &Upper) {
+ assert(Lower.ule(Upper) && "Unexpected wrapped set.");
+ unsigned BitWidth = Lower.getBitWidth();
+ if (Lower == Upper)
+ return ConstantRange::getEmpty(BitWidth);
+ if (Lower + 1 == Upper)
+ return ConstantRange(APInt(BitWidth, Lower.popcount()));
+
+ APInt Max = Upper - 1;
+ // Calculate longest common prefix.
+ unsigned LCPLength = (Lower ^ Max).countl_zero();
+ unsigned LCPPopCount = Lower.getHiBits(LCPLength).popcount();
+ // If Lower is {LCP, 000...}, the minimum is the popcount of LCP.
+ // Otherwise, the minimum is the popcount of LCP + 1.
+ unsigned MinBits =
+ LCPPopCount + (Lower.countr_zero() < BitWidth - LCPLength ? 1 : 0);
+ // If Max is {LCP, 111...}, the maximum is the popcount of LCP + (BitWidth -
+ // length of LCP).
+ // Otherwise, the minimum is the popcount of LCP + (BitWidth -
+ // length of LCP - 1).
+ unsigned MaxBits = LCPPopCount + (BitWidth - LCPLength) +
+ (Max.countr_one() >= BitWidth - LCPLength ? 1 : 0);
+ return ConstantRange(APInt(BitWidth, MinBits), APInt(BitWidth, MaxBits));
+}
+
+ConstantRange ConstantRange::ctpop() const {
+ if (isEmptySet())
+ return getEmpty();
+
+ unsigned BitWidth = getBitWidth();
+ APInt Zero = APInt::getZero(BitWidth);
+ if (isFullSet()) {
+ return getNonEmpty(Zero, APInt(BitWidth, BitWidth + 1));
+ }
+ if (!isUpperWrapped()) {
+ return getUnsignedPopCountRange(getLower(), getUpper());
+ }
+ ConstantRange CR1 = ConstantRange(
+ APInt(BitWidth,
+ BitWidth - (getUnsignedMax() - getLower() + 1).logBase2()),
+ APInt(BitWidth, BitWidth + 1)); // [lower, intmax]
+ ConstantRange CR2 = getUnsignedPopCountRange(Zero, getUpper()); // [0, upper)
+ return CR1.unionWith(CR2);
+}
+
ConstantRange::OverflowResult ConstantRange::unsignedAddMayOverflow(
const ConstantRange &Other) const {
if (isEmptySet() || Other.isEmptySet())
diff --git a/llvm/test/Transforms/CorrelatedValuePropagation/range.ll b/llvm/test/Transforms/CorrelatedValuePropagation/range.ll
index 5c10fdcd2b49217..cf85753e59c8083 100644
--- a/llvm/test/Transforms/CorrelatedValuePropagation/range.ll
+++ b/llvm/test/Transforms/CorrelatedValuePropagation/range.ll
@@ -1085,8 +1085,7 @@ define i1 @ctpop_fold(i16 %x) {
; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[ELSE:%.*]]
; CHECK: if:
; CHECK-NEXT: [[CTPOP:%.*]] = call i16 @llvm.ctpop.i16(i16 [[X]])
-; CHECK-NEXT: [[RES:%.*]] = icmp ule i16 [[CTPOP]], 8
-; CHECK-NEXT: ret i1 [[RES]]
+; CHECK-NEXT: ret i1 true
; CHECK: else:
; CHECK-NEXT: ret i1 true
;
diff --git a/llvm/unittests/IR/ConstantRangeTest.cpp b/llvm/unittests/IR/ConstantRangeTest.cpp
index 1cb358a26062ca5..12facfb22fb3c73 100644
--- a/llvm/unittests/IR/ConstantRangeTest.cpp
+++ b/llvm/unittests/IR/ConstantRangeTest.cpp
@@ -2438,6 +2438,12 @@ TEST_F(ConstantRangeTest, Ctlz) {
});
}
+TEST_F(ConstantRangeTest, Ctpop) {
+ TestUnaryOpExhaustive(
+ [](const ConstantRange &CR) { return CR.ctpop(); },
+ [](const APInt &N) { return APInt(N.getBitWidth(), N.popcount()); });
+}
+
TEST_F(ConstantRangeTest, castOps) {
ConstantRange A(APInt(16, 66), APInt(16, 128));
ConstantRange FpToI8 = A.castOp(Instruction::FPToSI, 8);
|
Ping. |
LGTM. |
@nikic Any comments about this PR? |
0b1ce72
to
8483054
Compare
8483054
to
77efe2e
Compare
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.
LGTM
Address comments.
This patch adds support for
Intrinsic::ctpop
in ConstantRange. It calculates the range in O(1) with the LCP-based method.Migrated from https://reviews.llvm.org/D153505.