diff --git a/llvm/include/llvm/ADT/APInt.h b/llvm/include/llvm/ADT/APInt.h --- a/llvm/include/llvm/ADT/APInt.h +++ b/llvm/include/llvm/ADT/APInt.h @@ -1490,6 +1490,16 @@ return U.pVal[0]; } + /// Get zero extended value if possible + /// + /// This method attempts to return the value of this APInt as a zero extended + /// uint64_t. The bitwidth must be <= 64 or the value must fit within a + /// uint64_t. Otherwise no value is returned. + std::optional tryZExtValue() const { + return (getActiveBits() <= 64) ? std::optional(getZExtValue()) + : std::nullopt; + }; + /// Get sign extended value /// /// This method attempts to return the value of this APInt as a sign extended @@ -1502,6 +1512,16 @@ return int64_t(U.pVal[0]); } + /// Get sign extended value if possible + /// + /// This method attempts to return the value of this APInt as a sign extended + /// int64_t. The bitwidth must be <= 64 or the value must fit within an + /// int64_t. Otherwise no value is returned. + std::optional trySExtValue() const { + return (getSignificantBits() <= 64) ? std::optional(getSExtValue()) + : std::nullopt; + }; + /// Get bits required for string value. /// /// This method determines how many bits are required to hold the APInt diff --git a/llvm/unittests/ADT/APIntTest.cpp b/llvm/unittests/ADT/APIntTest.cpp --- a/llvm/unittests/ADT/APIntTest.cpp +++ b/llvm/unittests/ADT/APIntTest.cpp @@ -3134,4 +3134,25 @@ Map.find(ZeroWidthInt); } +TEST(APIntTest, TryExt) { + APInt small(32, 42); + APInt large(128, {0xffff, 0xffff}); + ASSERT_TRUE(small.tryZExtValue().has_value()); + ASSERT_TRUE(small.trySExtValue().has_value()); + ASSERT_FALSE(large.tryZExtValue().has_value()); + ASSERT_FALSE(large.trySExtValue().has_value()); + ASSERT_EQ(small.trySExtValue().value_or(41), 42); + ASSERT_EQ(large.trySExtValue().value_or(41), 41); + + APInt negOne32(32, 0); + negOne32.setAllBits(); + ASSERT_EQ(negOne32.trySExtValue().value_or(42), -1); + APInt negOne64(64, 0); + negOne64.setAllBits(); + ASSERT_EQ(negOne64.trySExtValue().value_or(42), -1); + APInt negOne128(128, 0); + negOne128.setAllBits(); + ASSERT_EQ(negOne128.trySExtValue().value_or(42), 42); +} + } // end anonymous namespace