diff options
author | Fangrui Song <maskray@google.com> | 2019-04-19 02:06:06 +0000 |
---|---|---|
committer | Fangrui Song <maskray@google.com> | 2019-04-19 02:06:06 +0000 |
commit | acc7641bcb9df243e7c2e0e8c4636929e21642e8 (patch) | |
tree | d83e501952ef4e055f288699cbb06b59aeac0fee /llvm/lib/Support/APInt.cpp | |
parent | 9206335e9d100e65f85a73168400875839405f20 (diff) | |
download | llvm-acc7641bcb9df243e7c2e0e8c4636929e21642e8.zip llvm-acc7641bcb9df243e7c2e0e8c4636929e21642e8.tar.gz llvm-acc7641bcb9df243e7c2e0e8c4636929e21642e8.tar.bz2 |
[APInt] Optimize umul_ov
Change two costly udiv() calls to lshr(1)*RHS + left-shift + plus
On one 64-bit umul_ov benchmark, I measured an obvious improvement: 12.8129s -> 3.6257s
Note, there may be some value to special case 64-bit (the most common
case) with __builtin_umulll_overflow().
Differential Revision: https://reviews.llvm.org/D60669
llvm-svn: 358730
Diffstat (limited to 'llvm/lib/Support/APInt.cpp')
-rw-r--r-- | llvm/lib/Support/APInt.cpp | 17 |
1 files changed, 12 insertions, 5 deletions
diff --git a/llvm/lib/Support/APInt.cpp b/llvm/lib/Support/APInt.cpp index 5ed176f..9c59d93 100644 --- a/llvm/lib/Support/APInt.cpp +++ b/llvm/lib/Support/APInt.cpp @@ -1914,12 +1914,19 @@ APInt APInt::smul_ov(const APInt &RHS, bool &Overflow) const { } APInt APInt::umul_ov(const APInt &RHS, bool &Overflow) const { - APInt Res = *this * RHS; + if (countLeadingZeros() + RHS.countLeadingZeros() + 2 <= BitWidth) { + Overflow = true; + return *this * RHS; + } - if (*this != 0 && RHS != 0) - Overflow = Res.udiv(RHS) != *this || Res.udiv(*this) != RHS; - else - Overflow = false; + APInt Res = lshr(1) * RHS; + Overflow = Res.isNegative(); + Res <<= 1; + if ((*this)[0]) { + Res += RHS; + if (Res.ult(RHS)) + Overflow = true; + } return Res; } |