[llvm] [Support][APint] Fix APInt::urem for edge case. Use `U.pVal[0] instead getZExtValue() (PR #189441)
Max Graey via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 30 11:00:56 PDT 2026
https://github.com/MaxGraey created https://github.com/llvm/llvm-project/pull/189441
Use `U.pVal[0]` instead of `getZExtValue()` in the `APInt::urem(uint64_t)` power-of-two fast path. `getZExtValue()` requires the entire APInt to fit into 64 bits, but this code can be reached for multi-word values, which may trigger assertions or otherwise mis-handle wide integers.
Aslo add simple test for edge cases.
Fix edge case for https://github.com/llvm/llvm-project/pull/189245
>From 0a091bc26bcd06ae0d795ddf8d3936f0384a2ba1 Mon Sep 17 00:00:00 2001
From: MaxGraey <maxgraey at gmail.com>
Date: Mon, 30 Mar 2026 20:56:00 +0300
Subject: [PATCH] init
---
llvm/lib/Support/APInt.cpp | 2 +-
llvm/unittests/ADT/APIntTest.cpp | 16 ++++++++++++++++
2 files changed, 17 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/Support/APInt.cpp b/llvm/lib/Support/APInt.cpp
index f546de5e5da22..13fd5f47f578a 100644
--- a/llvm/lib/Support/APInt.cpp
+++ b/llvm/lib/Support/APInt.cpp
@@ -1755,7 +1755,7 @@ uint64_t APInt::urem(uint64_t RHS) const {
return U.pVal[0] % RHS;
if (llvm::isPowerOf2_64(RHS))
// X % 2^w ===> X & (2^w - 1)
- return getZExtValue() & (RHS - 1);
+ return U.pVal[0] & (RHS - 1);
// We have to compute it the hard way. Invoke the Knuth divide algorithm.
uint64_t Remainder;
diff --git a/llvm/unittests/ADT/APIntTest.cpp b/llvm/unittests/ADT/APIntTest.cpp
index 34efc4ff8ccf5..c25032d69d606 100644
--- a/llvm/unittests/ADT/APIntTest.cpp
+++ b/llvm/unittests/ADT/APIntTest.cpp
@@ -1186,6 +1186,22 @@ TEST(APIntTest, divrem_simple) {
EXPECT_EQ(R, APInt(65, 0));
}
+TEST(APIntTest, URemUint64PowerOf2Wide) {
+ // Edge case tests for urem with power of two arguments
+ APInt V(128, 0);
+ V.setBit(127);
+ V.setLowBits(12);
+
+ EXPECT_EQ(15u, V.urem(16));
+ EXPECT_EQ(255u, V.urem(256));
+ EXPECT_EQ(4095u, V.urem(4096));
+
+ APInt AllOnes = APInt::getAllOnes(128);
+ EXPECT_EQ(static_cast<uint64_t>(63), AllOnes.urem(64));
+ EXPECT_EQ(static_cast<uint64_t>(255), AllOnes.urem(256));
+ EXPECT_EQ(static_cast<uint64_t>(4095), AllOnes.urem(4096));
+}
+
TEST(APIntTest, fromString) {
EXPECT_EQ(APInt(32, 0), APInt(32, "0", 2));
EXPECT_EQ(APInt(32, 1), APInt(32, "1", 2));
More information about the llvm-commits
mailing list