Skip to content

add power function to APInt #122788

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

Merged
merged 16 commits into from
Jan 17, 2025
Merged

Conversation

ImanHosseini
Copy link
Contributor

I am trying to calculate power function for APFloat, APInt to constant fold vector reductions: #122450
I need this utility to fold N muls into power.

@llvmbot
Copy link
Member

llvmbot commented Jan 13, 2025

@llvm/pr-subscribers-llvm-adt

@llvm/pr-subscribers-llvm-support

Author: Iman Hosseini (ImanHosseini)

Changes

I am trying to calculate power function for APFloat, APInt to constant fold vector reductions: #122450
I need this utility to fold N muls into power.


Full diff: https://github.com/llvm/llvm-project/pull/122788.diff

3 Files Affected:

  • (modified) llvm/include/llvm/ADT/APFloat.h (+20)
  • (modified) llvm/include/llvm/ADT/APInt.h (+3)
  • (modified) llvm/lib/Support/APInt.cpp (+19)
diff --git a/llvm/include/llvm/ADT/APFloat.h b/llvm/include/llvm/ADT/APFloat.h
index bf80fa5a06580b..236469d43678fe 100644
--- a/llvm/include/llvm/ADT/APFloat.h
+++ b/llvm/include/llvm/ADT/APFloat.h
@@ -1531,6 +1531,26 @@ inline APFloat abs(APFloat X) {
   return X;
 }
 
+/// Returns X^N for N >= 0.
+inline APFloat pow(const APFloat &X, const int &N) {
+  assert(N >= 0 && "negative exponents not supported.");
+  if (N == 0) {
+    return APFloat::getOne(X.getSemantics());
+  }
+  APFloat Acc = X;
+  int64_t RemainingExponent = N;
+  while (RemainingExponent > 1) {
+    if (RemainingExponent % 2 == 0) {
+      Acc = Acc * Acc;
+      RemainingExponent /= 2;
+    } else {
+      Acc = Acc * X;
+      RemainingExponent--;
+    }
+  }
+  return Acc;
+};
+
 /// Returns the negated value of the argument.
 inline APFloat neg(APFloat X) {
   X.changeSign();
diff --git a/llvm/include/llvm/ADT/APInt.h b/llvm/include/llvm/ADT/APInt.h
index 225390f1af60b3..e93f1759875688 100644
--- a/llvm/include/llvm/ADT/APInt.h
+++ b/llvm/include/llvm/ADT/APInt.h
@@ -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, const int &N);
+
 /// Compute GCD of two unsigned APInt values.
 ///
 /// This function returns the greatest common divisor of the two APInt values
diff --git a/llvm/lib/Support/APInt.cpp b/llvm/lib/Support/APInt.cpp
index ea8295f95c751a..d95c1bc8e7194e 100644
--- a/llvm/lib/Support/APInt.cpp
+++ b/llvm/lib/Support/APInt.cpp
@@ -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, const int &N) {
+  assert(N >= 0 && "negative exponents not supported.");
+  if (N == 0) {
+    return APInt(X.getBitWidth(), 1);
+  }
+  APInt Acc = X;
+  int64_t RemainingExponent = N;
+  while (RemainingExponent > 1) {
+    if (RemainingExponent % 2 == 0) {
+      Acc = Acc * Acc;
+      RemainingExponent /= 2;
+    } else {
+      Acc = Acc * X;
+      RemainingExponent--;
+    }
+  }
+  return Acc;
+};

@ImanHosseini ImanHosseini requested a review from arsenm January 13, 2025 20:57
Copy link
Member

@kuhar kuhar left a comment

Choose a reason for hiding this comment

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

Can you add unit tests?

@ImanHosseini ImanHosseini changed the title add power function to APFloat and APInt add power function to APInt Jan 14, 2025
@ImanHosseini
Copy link
Contributor Author

Added unit tests. Removed APFloat change- this change is now only for APInt.

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

@ImanHosseini ImanHosseini requested a review from arsenm January 14, 2025 13:54
@ImanHosseini ImanHosseini requested a review from kuhar January 14, 2025 15:31
Copy link
Member

@kuhar kuhar left a comment

Choose a reason for hiding this comment

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

LGTM % nit

Copy link

github-actions bot commented Jan 16, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@ImanHosseini ImanHosseini merged commit 8ae1cb2 into llvm:main Jan 17, 2025
8 checks passed
@ImanHosseini ImanHosseini mentioned this pull request Jan 17, 2025
ImanHosseini added a commit that referenced this pull request Jan 17, 2025
Remove erroneous extra semicolon in:
#122788

Co-authored-by: ImanHosseini <[email protected]>
github-actions bot pushed a commit to arm/arm-toolchain that referenced this pull request Jan 17, 2025
Remove erroneous extra semicolon in:
llvm/llvm-project#122788

Co-authored-by: ImanHosseini <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants