Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions llvm/include/llvm/ADT/APInt.h
Original file line number Diff line number Diff line change
Expand Up @@ -2294,6 +2294,12 @@ LLVM_ABI APInt mulhs(const APInt &C1, const APInt &C2);
/// Returns the high N bits of the multiplication result.
LLVM_ABI APInt mulhu(const APInt &C1, const APInt &C2);

/// Performs (2*N)-bit multiplication on sign-extended operands.
LLVM_ABI APInt mulxs(const APInt &C1, const APInt &C2);

/// Performs (2*N)-bit multiplication on zero-extended operands.
LLVM_ABI APInt mulxu(const APInt &C1, const APInt &C2);

/// Compute X^N for N>=0.
/// 0^0 is supported and returns 1.
LLVM_ABI APInt pow(const APInt &X, int64_t N);
Expand Down
16 changes: 16 additions & 0 deletions llvm/lib/Support/APInt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3136,6 +3136,22 @@ APInt APIntOps::mulhu(const APInt &C1, const APInt &C2) {
return (C1Ext * C2Ext).extractBits(C1.getBitWidth(), C1.getBitWidth());
}

APInt APIntOps::mulxs(const APInt &C1, const APInt &C2) {
assert(C1.getBitWidth() == C2.getBitWidth() && "Unequal bitwidths");
unsigned FullWidth = C1.getBitWidth() * 2;
APInt C1Ext = C1.sext(FullWidth);
APInt C2Ext = C2.sext(FullWidth);
return C1Ext * C2Ext;
}

APInt APIntOps::mulxu(const APInt &C1, const APInt &C2) {
assert(C1.getBitWidth() == C2.getBitWidth() && "Unequal bitwidths");
unsigned FullWidth = C1.getBitWidth() * 2;
APInt C1Ext = C1.zext(FullWidth);
APInt C2Ext = C2.zext(FullWidth);
return C1Ext * C2Ext;
}

APInt APIntOps::pow(const APInt &X, int64_t N) {
assert(N >= 0 && "negative exponents not supported.");
APInt Acc = APInt(X.getBitWidth(), 1);
Expand Down
47 changes: 47 additions & 0 deletions llvm/unittests/ADT/APIntTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3103,6 +3103,53 @@ TEST(APIntOpsTest, Mulh) {
EXPECT_EQ(APInt(128, "FFEB498812C66C68D4552DB89B8EBF8F", 16), i128Res);
}

TEST(APIntOpsTest, mulx) {
APInt u32a(32, 0x0001'E235);
APInt u32b(32, 0xF623'55AD);
EXPECT_EQ(0x0001'CFA1'7CA0'76D1, APIntOps::mulxu(u32a, u32b));

APInt u64a(64, 0x1234'5678'90AB'CDEF);
APInt u64b(64, 0xFEDC'BA09'8765'4321);
EXPECT_EQ(APInt(128, "121FA000A3723A57C24A442FE55618CF", 16),
APIntOps::mulxu(u64a, u64b));

APInt u128a(128, "1234567890ABCDEF1234567890ABCDEF", 16);
APInt u128b(128, "FEDCBA0987654321FEDCBA0987654321", 16);
EXPECT_EQ(
APInt(256,
"121FA000A3723A57E68984312C3A8D7E96B428606E1E6BF5C24A442FE55618CF",
16),
APIntOps::mulxu(u128a, u128b));

APInt s32a(32, 0x1234'5678);
APInt s32b(32, 0x10AB'CDEF);
APInt s32c(32, 0xFEDC'BA09);
EXPECT_EQ(0x012F'7D02'2A42'D208, APIntOps::mulxs(s32a, s32b));
EXPECT_EQ(0xFFEB'4988'09CA'3A38, APIntOps::mulxs(s32a, s32c));

APInt s64a(64, 0x1234'5678'90AB'CDEF);
APInt s64b(64, 0x1234'5678'90FE'DCBA);
APInt s64c(64, 0xFEDC'BA09'8765'4321);
EXPECT_EQ(APInt(128, "014B66DC328E10C1FB99704184EF03A6", 16),
APIntOps::mulxs(s64a, s64b));
EXPECT_EQ(APInt(128, "FFEB498812C66C68C24A442FE55618CF", 16),
APIntOps::mulxs(s64a, s64c));

APInt s128a(128, "1234567890ABCDEF1234567890ABCDEF", 16);
APInt s128b(128, "1234567890FEDCBA1234567890FEDCBA", 16);
APInt s128c(128, "FEDCBA0987654321FEDCBA0987654321", 16);
EXPECT_EQ(
APInt(256,
"014B66DC328E10C1FE303DF9EA0B2529F87E475F3C6C180DFB99704184EF03A6",
16),
APIntOps::mulxs(s128a, s128b));
EXPECT_EQ(
APInt(256,
"FFEB498812C66C68D4552DB89B8EBF8F96B428606E1E6BF5C24A442FE55618CF",
16),
APIntOps::mulxs(s128a, s128c));
}

TEST(APIntTest, RoundingUDiv) {
for (uint64_t Ai = 1; Ai <= 255; Ai++) {
APInt A(8, Ai);
Expand Down