[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