[clang] [flang] [llvm] [MathExtras][NFC] Optimize NextPowerOf2 similar to PowerOf2Ceil (PR #189160)
Max Graey via cfe-commits
cfe-commits at lists.llvm.org
Sat Mar 28 06:36:26 PDT 2026
https://github.com/MaxGraey updated https://github.com/llvm/llvm-project/pull/189160
>From 88ca557592ed9e5b6a6be515f3fdef97d7157ac8 Mon Sep 17 00:00:00 2001
From: MaxGraey <maxgraey at gmail.com>
Date: Sat, 28 Mar 2026 14:30:04 +0200
Subject: [PATCH 1/3] optimize NextPowerOf2
---
llvm/include/llvm/Support/MathExtras.h | 12 ++++--------
1 file changed, 4 insertions(+), 8 deletions(-)
diff --git a/llvm/include/llvm/Support/MathExtras.h b/llvm/include/llvm/Support/MathExtras.h
index de2813094a950..59e7e40b742aa 100644
--- a/llvm/include/llvm/Support/MathExtras.h
+++ b/llvm/include/llvm/Support/MathExtras.h
@@ -370,14 +370,10 @@ constexpr uint64_t MinAlign(uint64_t A, uint64_t B) {
/// Returns the next power of two (in 64-bits) that is strictly greater than A.
/// Returns zero on overflow.
-constexpr uint64_t NextPowerOf2(uint64_t A) {
- A |= (A >> 1);
- A |= (A >> 2);
- A |= (A >> 4);
- A |= (A >> 8);
- A |= (A >> 16);
- A |= (A >> 32);
- return A + 1;
+inline uint64_t NextPowerOf2(uint64_t A) {
+ if (A > UINT64_MAX / 2)
+ return 0;
+ return UINT64_C(1) << Log2_64_Ceil(A + 1);
}
/// Returns the power of two which is greater than or equal to the given value.
>From 018b4ca86510dff8e80571aa449bd205bf1510dd Mon Sep 17 00:00:00 2001
From: MaxGraey <maxgraey at gmail.com>
Date: Sat, 28 Mar 2026 14:56:54 +0200
Subject: [PATCH 2/3] add NextPowerOf2Constexpr
---
llvm/include/llvm/ADT/BitmaskEnum.h | 2 +-
llvm/include/llvm/Support/MathExtras.h | 13 +++++++++++++
llvm/include/llvm/Support/TypeSize.h | 2 +-
3 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/llvm/include/llvm/ADT/BitmaskEnum.h b/llvm/include/llvm/ADT/BitmaskEnum.h
index c10a38c8ce4cb..53fae55e2c1ea 100644
--- a/llvm/include/llvm/ADT/BitmaskEnum.h
+++ b/llvm/include/llvm/ADT/BitmaskEnum.h
@@ -126,7 +126,7 @@ namespace BitmaskEnumDetail {
template <typename E> constexpr std::underlying_type_t<E> Mask() {
// On overflow, NextPowerOf2 returns zero with the type uint64_t, so
// subtracting 1 gives us the mask with all bits set, like we want.
- return NextPowerOf2(largest_bitmask_enum_bit<E>::value) - 1;
+ return NextPowerOf2Constexpr(largest_bitmask_enum_bit<E>::value) - 1;
}
/// Check that Val is in range for E, and return Val cast to E's underlying
diff --git a/llvm/include/llvm/Support/MathExtras.h b/llvm/include/llvm/Support/MathExtras.h
index 59e7e40b742aa..321ddf3329806 100644
--- a/llvm/include/llvm/Support/MathExtras.h
+++ b/llvm/include/llvm/Support/MathExtras.h
@@ -368,6 +368,19 @@ constexpr uint64_t MinAlign(uint64_t A, uint64_t B) {
return (A | B) & (1 + ~(A | B));
}
+/// Returns the next power of two (in 64-bits) that is strictly greater than A.
+/// A constexpr version of NextPowerOf2.
+/// Returns zero on overflow.
+constexpr uint64_t NextPowerOf2Constexpr(uint64_t A) {
+ A |= (A >> 1);
+ A |= (A >> 2);
+ A |= (A >> 4);
+ A |= (A >> 8);
+ A |= (A >> 16);
+ A |= (A >> 32);
+ return A + 1;
+}
+
/// Returns the next power of two (in 64-bits) that is strictly greater than A.
/// Returns zero on overflow.
inline uint64_t NextPowerOf2(uint64_t A) {
diff --git a/llvm/include/llvm/Support/TypeSize.h b/llvm/include/llvm/Support/TypeSize.h
index 421d6613bfafc..0a6e285935e1e 100644
--- a/llvm/include/llvm/Support/TypeSize.h
+++ b/llvm/include/llvm/Support/TypeSize.h
@@ -259,7 +259,7 @@ template <typename LeafTy, typename ValueTy> class FixedOrScalableQuantity {
constexpr LeafTy coefficientNextPowerOf2() const {
return LeafTy::get(
- static_cast<ScalarTy>(llvm::NextPowerOf2(getKnownMinValue())),
+ static_cast<ScalarTy>(llvm::NextPowerOf2Constexpr(getKnownMinValue())),
isScalable());
}
>From e43d871333b6b9d0a254598bdc0d09b1791bbc75 Mon Sep 17 00:00:00 2001
From: MaxGraey <maxgraey at gmail.com>
Date: Sat, 28 Mar 2026 15:36:10 +0200
Subject: [PATCH 3/3] fixes
---
.../clang/DependencyScanning/DependencyScanningService.h | 2 +-
flang/lib/Parser/openmp-parsers.cpp | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang/include/clang/DependencyScanning/DependencyScanningService.h b/clang/include/clang/DependencyScanning/DependencyScanningService.h
index 0575dbc7cca9a..407de737f1468 100644
--- a/clang/include/clang/DependencyScanning/DependencyScanningService.h
+++ b/clang/include/clang/DependencyScanning/DependencyScanningService.h
@@ -46,7 +46,7 @@ enum class ScanningOutputFormat {
};
#define DSS_LAST_BITMASK_ENUM(Id) \
- LLVM_MARK_AS_BITMASK_ENUM(Id), All = llvm::NextPowerOf2(Id) - 1
+ LLVM_MARK_AS_BITMASK_ENUM(Id), All = llvm::NextPowerOf2Constexpr(Id) - 1
enum class ScanningOptimizations {
None = 0,
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index 3b5d43db56ec2..4978ce66942b9 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -44,7 +44,7 @@ namespace Fortran::parser {
using namespace Fortran::parser::omp;
using DirectiveSet =
- llvm::Bitset<llvm::NextPowerOf2(llvm::omp::Directive_enumSize)>;
+ llvm::Bitset<llvm::NextPowerOf2Constexpr(llvm::omp::Directive_enumSize)>;
// Helper function to print the buffer contents starting at the current point.
[[maybe_unused]] static std::string ahead(const ParseState &state) {
More information about the cfe-commits
mailing list