Skip to content

Commit a92fd0b

Browse files
committedMay 12, 2017
[APInt] Add a utility method to change the bit width and storage size of an APInt.
Summary: This adds a resize method to APInt that manages deleting/allocating storage for an APInt and changes its bit width. Use this to simplify code in copy assignment and divide. The assignment code in particular was overly complicated. Treating every possible case as a separate implementation. I'm also pretty sure the clearUnusedBits code at the end was unnecessary. Since we always copying whole words from the source APInt. All unused bits should be clear in the source. Reviewers: hans, RKSimon Reviewed By: RKSimon Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D33073 llvm-svn: 302863
1 parent 5750a3f commit a92fd0b

File tree

2 files changed

+36
-42
lines changed

2 files changed

+36
-42
lines changed
 

‎llvm/include/llvm/ADT/APInt.h

+5
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,11 @@ class LLVM_NODISCARD APInt {
157157
return isSingleWord() ? U.VAL : U.pVal[whichWord(bitPosition)];
158158
}
159159

160+
/// Utility method to change the bit width of this APInt to new bit width,
161+
/// allocating and/or deallocating as necessary. There is no guarantee on the
162+
/// value of any bits upon return. Caller should populate the bits after.
163+
void reallocate(unsigned NewBitWidth);
164+
160165
/// \brief Convert a char array into an APInt
161166
///
162167
/// \param radix 2, 8, 10, 16, or 36

‎llvm/lib/Support/APInt.cpp

+31-42
Original file line numberDiff line numberDiff line change
@@ -122,35 +122,38 @@ APInt::APInt(unsigned numbits, StringRef Str, uint8_t radix)
122122
fromString(numbits, Str, radix);
123123
}
124124

125+
void APInt::reallocate(unsigned NewBitWidth) {
126+
// If the number of words is the same we can just change the width and stop.
127+
if (getNumWords() == getNumWords(NewBitWidth)) {
128+
BitWidth = NewBitWidth;
129+
return;
130+
}
131+
132+
// If we have an allocation, delete it.
133+
if (!isSingleWord())
134+
delete [] U.pVal;
135+
136+
// Update BitWidth.
137+
BitWidth = NewBitWidth;
138+
139+
// If we are supposed to have an allocation, create it.
140+
if (!isSingleWord())
141+
U.pVal = getMemory(getNumWords());
142+
}
143+
125144
void APInt::AssignSlowCase(const APInt& RHS) {
126145
// Don't do anything for X = X
127146
if (this == &RHS)
128147
return;
129148

130-
if (BitWidth == RHS.getBitWidth()) {
131-
// assume same bit-width single-word case is already handled
132-
assert(!isSingleWord());
133-
memcpy(U.pVal, RHS.U.pVal, getNumWords() * APINT_WORD_SIZE);
134-
return;
135-
}
149+
// Adjust the bit width and handle allocations as necessary.
150+
reallocate(RHS.getBitWidth());
136151

137-
if (isSingleWord()) {
138-
// assume case where both are single words is already handled
139-
assert(!RHS.isSingleWord());
140-
U.pVal = getMemory(RHS.getNumWords());
141-
memcpy(U.pVal, RHS.U.pVal, RHS.getNumWords() * APINT_WORD_SIZE);
142-
} else if (getNumWords() == RHS.getNumWords())
143-
memcpy(U.pVal, RHS.U.pVal, RHS.getNumWords() * APINT_WORD_SIZE);
144-
else if (RHS.isSingleWord()) {
145-
delete [] U.pVal;
152+
// Copy the data.
153+
if (isSingleWord())
146154
U.VAL = RHS.U.VAL;
147-
} else {
148-
delete [] U.pVal;
149-
U.pVal = getMemory(RHS.getNumWords());
150-
memcpy(U.pVal, RHS.U.pVal, RHS.getNumWords() * APINT_WORD_SIZE);
151-
}
152-
BitWidth = RHS.BitWidth;
153-
clearUnusedBits();
155+
else
156+
memcpy(U.pVal, RHS.U.pVal, getNumWords() * APINT_WORD_SIZE);
154157
}
155158

156159
/// This method 'profiles' an APInt for use with FoldingSet.
@@ -1500,16 +1503,9 @@ void APInt::divide(const APInt &LHS, unsigned lhsWords, const APInt &RHS,
15001503
// If the caller wants the quotient
15011504
if (Quotient) {
15021505
// Set up the Quotient value's memory.
1503-
if (Quotient->BitWidth != LHS.BitWidth) {
1504-
if (Quotient->isSingleWord())
1505-
Quotient->U.VAL = 0;
1506-
else
1507-
delete [] Quotient->U.pVal;
1508-
Quotient->BitWidth = LHS.BitWidth;
1509-
if (!Quotient->isSingleWord())
1510-
Quotient->U.pVal = getClearedMemory(Quotient->getNumWords());
1511-
} else
1512-
Quotient->clearAllBits();
1506+
Quotient->reallocate(LHS.BitWidth);
1507+
// Clear out any previous bits.
1508+
Quotient->clearAllBits();
15131509

15141510
// The quotient is in Q. Reconstitute the quotient into Quotient's low
15151511
// order words.
@@ -1531,16 +1527,9 @@ void APInt::divide(const APInt &LHS, unsigned lhsWords, const APInt &RHS,
15311527
// If the caller wants the remainder
15321528
if (Remainder) {
15331529
// Set up the Remainder value's memory.
1534-
if (Remainder->BitWidth != RHS.BitWidth) {
1535-
if (Remainder->isSingleWord())
1536-
Remainder->U.VAL = 0;
1537-
else
1538-
delete [] Remainder->U.pVal;
1539-
Remainder->BitWidth = RHS.BitWidth;
1540-
if (!Remainder->isSingleWord())
1541-
Remainder->U.pVal = getClearedMemory(Remainder->getNumWords());
1542-
} else
1543-
Remainder->clearAllBits();
1530+
Remainder->reallocate(RHS.BitWidth);
1531+
// Clear out any previous bits.
1532+
Remainder->clearAllBits();
15441533

15451534
// The remainder is in R. Reconstitute the remainder into Remainder's low
15461535
// order words.

0 commit comments

Comments
 (0)
Please sign in to comment.