Skip to content

Commit

Permalink
[APInt] Add unsigned overloads of shift functions
Browse files Browse the repository at this point in the history
Add overloads of sshl_ov, ushl_ov, sshl_sat and ushl_sat that take the
shift amount as unsigned instead of APInt. This matches what we do for
the normal shift operators and can help to avoid creating temporary
APInts in some cases.

Differential Revision: https://reviews.llvm.org/D151420
  • Loading branch information
jayfoad committed May 25, 2023
1 parent 298843c commit bf358e2
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 5 deletions.
4 changes: 4 additions & 0 deletions llvm/include/llvm/ADT/APInt.h
Original file line number Diff line number Diff line change
Expand Up @@ -1003,7 +1003,9 @@ class [[nodiscard]] APInt {
APInt smul_ov(const APInt &RHS, bool &Overflow) const;
APInt umul_ov(const APInt &RHS, bool &Overflow) const;
APInt sshl_ov(const APInt &Amt, bool &Overflow) const;
APInt sshl_ov(unsigned Amt, bool &Overflow) const;
APInt ushl_ov(const APInt &Amt, bool &Overflow) const;
APInt ushl_ov(unsigned Amt, bool &Overflow) const;

// Operations that saturate
APInt sadd_sat(const APInt &RHS) const;
Expand All @@ -1013,7 +1015,9 @@ class [[nodiscard]] APInt {
APInt smul_sat(const APInt &RHS) const;
APInt umul_sat(const APInt &RHS) const;
APInt sshl_sat(const APInt &RHS) const;
APInt sshl_sat(unsigned RHS) const;
APInt ushl_sat(const APInt &RHS) const;
APInt ushl_sat(unsigned RHS) const;

/// Array-indexing support.
///
Expand Down
26 changes: 21 additions & 5 deletions llvm/lib/Support/APInt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1984,24 +1984,32 @@ APInt APInt::umul_ov(const APInt &RHS, bool &Overflow) const {
}

APInt APInt::sshl_ov(const APInt &ShAmt, bool &Overflow) const {
Overflow = ShAmt.uge(getBitWidth());
return sshl_ov(ShAmt.getLimitedValue(getBitWidth()), Overflow);
}

APInt APInt::sshl_ov(unsigned ShAmt, bool &Overflow) const {
Overflow = ShAmt >= getBitWidth();
if (Overflow)
return APInt(BitWidth, 0);

if (isNonNegative()) // Don't allow sign change.
Overflow = ShAmt.uge(countl_zero());
Overflow = ShAmt >= countl_zero();
else
Overflow = ShAmt.uge(countl_one());
Overflow = ShAmt >= countl_one();

return *this << ShAmt;
}

APInt APInt::ushl_ov(const APInt &ShAmt, bool &Overflow) const {
Overflow = ShAmt.uge(getBitWidth());
return ushl_ov(ShAmt.getLimitedValue(getBitWidth()), Overflow);
}

APInt APInt::ushl_ov(unsigned ShAmt, bool &Overflow) const {
Overflow = ShAmt >= getBitWidth();
if (Overflow)
return APInt(BitWidth, 0);

Overflow = ShAmt.ugt(countl_zero());
Overflow = ShAmt > countl_zero();

return *this << ShAmt;
}
Expand Down Expand Up @@ -2067,6 +2075,10 @@ APInt APInt::umul_sat(const APInt &RHS) const {
}

APInt APInt::sshl_sat(const APInt &RHS) const {
return sshl_sat(RHS.getLimitedValue(getBitWidth()));
}

APInt APInt::sshl_sat(unsigned RHS) const {
bool Overflow;
APInt Res = sshl_ov(RHS, Overflow);
if (!Overflow)
Expand All @@ -2077,6 +2089,10 @@ APInt APInt::sshl_sat(const APInt &RHS) const {
}

APInt APInt::ushl_sat(const APInt &RHS) const {
return ushl_sat(RHS.getLimitedValue(getBitWidth()));
}

APInt APInt::ushl_sat(unsigned RHS) const {
bool Overflow;
APInt Res = ushl_ov(RHS, Overflow);
if (!Overflow)
Expand Down

0 comments on commit bf358e2

Please sign in to comment.