Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions llvm/include/llvm/ADT/APInt.h
Original file line number Diff line number Diff line change
Expand Up @@ -2263,6 +2263,9 @@ APInt mulhs(const APInt &C1, const APInt &C2);
/// Returns the high N bits of the multiplication result.
APInt mulhu(const APInt &C1, const APInt &C2);

/// Compute X^N for N>=0.
APInt pow(const APInt &X, int64_t N);

/// Compute GCD of two unsigned APInt values.
///
/// This function returns the greatest common divisor of the two APInt values
Expand Down
19 changes: 19 additions & 0 deletions llvm/lib/Support/APInt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3108,3 +3108,22 @@ APInt APIntOps::mulhu(const APInt &C1, const APInt &C2) {
APInt C2Ext = C2.zext(FullWidth);
return (C1Ext * C2Ext).extractBits(C1.getBitWidth(), C1.getBitWidth());
}

APInt APIntOps::pow(const APInt &X, int64_t N) {
assert(N >= 0 && "negative exponents not supported.");
APInt Acc = APInt(X.getBitWidth(), 1);
if (N == 0) {
return Acc;
}
APInt Base = X;
int64_t RemainingExponent = N;
while (RemainingExponent > 0) {
while (RemainingExponent % 2 == 0) {
Base = Base * Base;
RemainingExponent /= 2;
}
--RemainingExponent;
Acc = Acc * Base;
}
return Acc;
};
45 changes: 45 additions & 0 deletions llvm/unittests/ADT/APIntTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,51 @@ TEST(APIntTest, ValueInit) {
EXPECT_TRUE(!Zero.sext(64));
}

// Test that 0^5 == 0
TEST(APIntTest, PowZeroTo5) {
APInt Zero = APInt();
EXPECT_TRUE(!Zero);
APInt ZeroTo5 = APIntOps::pow(Zero, 5);
EXPECT_TRUE(!ZeroTo5);
}

// Test that 1^16 == 1
TEST(APIntTest, PowOneTo16) {
APInt One = APInt::getZero(32) + 1;
APInt OneTo16 = APIntOps::pow(One, 16);
EXPECT_EQ(One, OneTo16);
}

// Test that 2^10 == 1024
TEST(APIntTest, PowerTwoTo10) {
APInt Two = APInt::getZero(32) + 2;
APInt TwoTo20 = APIntOps::pow(Two, 10);
APInt V_1024 = APInt::getZero(32) + 1024;
EXPECT_EQ(TwoTo20, V_1024);
}

// Test that 3^3 == 27
TEST(APIntTest, PowerThreeTo3) {
APInt Three = APInt::getZero(32) + 3;
APInt ThreeTo3 = APIntOps::pow(Three, 3);
APInt V_27 = APInt::getZero(32) + 27;
EXPECT_EQ(ThreeTo3, V_27);
}

Copy link
Contributor

@arsenm arsenm Jan 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test getMaxValue, getMaxSignedValue, getMinSignedValue cases

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added tests for getSignedMaxValue and getMaxValue. I don't know what you mean by testing getMinSignedValue.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean APInt::getSignedMinValue

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this the right check?

// Test that SignedMinValue^3 == 0
TEST(APIntTest, PowerSignedMinValueTo3) {
  APInt SignedMinValue = APInt::getSignedMinValue(32);
  APInt MinTo3 = APIntOps::pow(SignedMinValue, 3);
  EXPECT_TRUE(MinTo3.isZero());
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes

// Test that SignedMaxValue^3 == SignedMaxValue
TEST(APIntTest, PowerSignedMaxValue) {
APInt SignedMaxValue = APInt::getSignedMaxValue(32);
APInt MaxTo3 = APIntOps::pow(SignedMaxValue, 3);
EXPECT_EQ(MaxTo3, SignedMaxValue);
}

// Test that MaxValue^3 == MaxValue
TEST(APIntTest, PowerMaxValue) {
APInt MaxValue = APInt::getMaxValue(32);
APInt MaxTo3 = APIntOps::pow(MaxValue, 3);
EXPECT_EQ(MaxValue, MaxTo3);
}

// Test that APInt shift left works when bitwidth > 64 and shiftamt == 0
TEST(APIntTest, ShiftLeftByZero) {
APInt One = APInt::getZero(65) + 1;
Expand Down
Loading