llvm.org GIT mirror llvm / ea7650c
Revert "[APInt] Add ashrInPlace method and implement ashr using it. Also fix a bug in the shift by BitWidth handling." This reverts commit r301094, as it broke all ARM self-hosting bots. PR32754. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@301110 91177308-0d34-0410-b5e6-96231b3b80d8 Renato Golin 3 years ago
4 changed file(s) with 82 addition(s) and 82 deletion(s). Raw diff Collapse all Expand all
197197 /// out-of-line slow case for lshr.
198198 void lshrSlowCase(unsigned ShiftAmt);
199199
200 /// out-of-line slow case for ashr.
201 void ashrSlowCase(unsigned ShiftAmt);
202
203200 /// out-of-line slow case for operator=
204201 void AssignSlowCase(const APInt &RHS);
205202
907904 /// \brief Arithmetic right-shift function.
908905 ///
909906 /// Arithmetic right-shift this APInt by shiftAmt.
910 APInt ashr(unsigned ShiftAmt) const {
911 APInt R(*this);
912 R.ashrInPlace(ShiftAmt);
913 return R;
914 }
915
916 /// Arithmetic right-shift this APInt by ShiftAmt in place.
917 void ashrInPlace(unsigned ShiftAmt) {
918 assert(ShiftAmt <= BitWidth && "Invalid shift amount");
919 if (isSingleWord()) {
920 int64_t SExtVAL = SignExtend64(VAL, BitWidth);
921 if (ShiftAmt == BitWidth)
922 VAL = SExtVAL >> (APINT_BITS_PER_WORD - 1); // undefined
923 else
924 VAL = SExtVAL >> ShiftAmt;
925 clearUnusedBits();
926 return;
927 }
928 ashrSlowCase(ShiftAmt);
929 }
907 APInt ashr(unsigned shiftAmt) const;
930908
931909 /// \brief Logical right-shift function.
932910 ///
968946 /// \brief Arithmetic right-shift function.
969947 ///
970948 /// Arithmetic right-shift this APInt by shiftAmt.
971 APInt ashr(const APInt &ShiftAmt) const {
972 APInt R(*this);
973 R.ashrInPlace(ShiftAmt);
974 return R;
975 }
976
977 /// Arithmetic right-shift this APInt by shiftAmt in place.
978 void ashrInPlace(const APInt &shiftAmt);
949 APInt ashr(const APInt &shiftAmt) const;
979950
980951 /// \brief Logical right-shift function.
981952 ///
127127 if (IsUnsigned)
128128 lshrInPlace(Amt);
129129 else
130 ashrInPlace(Amt);
130 *this = *this >> Amt;
131131 return *this;
132132 }
133133
10281028
10291029 /// Arithmetic right-shift this APInt by shiftAmt.
10301030 /// @brief Arithmetic right-shift function.
1031 void APInt::ashrInPlace(const APInt &shiftAmt) {
1032 ashrInPlace((unsigned)shiftAmt.getLimitedValue(BitWidth));
1031 APInt APInt::ashr(const APInt &shiftAmt) const {
1032 return ashr((unsigned)shiftAmt.getLimitedValue(BitWidth));
10331033 }
10341034
10351035 /// Arithmetic right-shift this APInt by shiftAmt.
10361036 /// @brief Arithmetic right-shift function.
1037 void APInt::ashrSlowCase(unsigned ShiftAmt) {
1038 // Don't bother performing a no-op shift.
1039 if (!ShiftAmt)
1040 return;
1041
1042 bool Negative = isNegative();
1043
1044 // WordShift is the inter-part shift; BitShift is is intra-part shift.
1045 unsigned Words = getNumWords();
1046 unsigned WordShift = std::min(ShiftAmt / APINT_BITS_PER_WORD, Words);
1047 unsigned BitShift = ShiftAmt % APINT_BITS_PER_WORD;
1048
1049 unsigned WordsToMove = Words - WordShift;
1050 // Fastpath for moving by whole words.
1051 if (BitShift == 0) {
1052 std::memmove(pVal, pVal + WordShift, WordsToMove * APINT_WORD_SIZE);
1037 APInt APInt::ashr(unsigned shiftAmt) const {
1038 assert(shiftAmt <= BitWidth && "Invalid shift amount");
1039 // Handle a degenerate case
1040 if (shiftAmt == 0)
1041 return *this;
1042
1043 // Handle single word shifts with built-in ashr
1044 if (isSingleWord()) {
1045 if (shiftAmt == BitWidth)
1046 return APInt(BitWidth, 0); // undefined
1047 return APInt(BitWidth, SignExtend64(VAL, BitWidth) >> shiftAmt);
1048 }
1049
1050 // If all the bits were shifted out, the result is, technically, undefined.
1051 // We return -1 if it was negative, 0 otherwise. We check this early to avoid
1052 // issues in the algorithm below.
1053 if (shiftAmt == BitWidth) {
1054 if (isNegative())
1055 return APInt(BitWidth, WORD_MAX, true);
1056 else
1057 return APInt(BitWidth, 0);
1058 }
1059
1060 // Create some space for the result.
1061 uint64_t * val = new uint64_t[getNumWords()];
1062
1063 // Compute some values needed by the following shift algorithms
1064 unsigned wordShift = shiftAmt % APINT_BITS_PER_WORD; // bits to shift per word
1065 unsigned offset = shiftAmt / APINT_BITS_PER_WORD; // word offset for shift
1066 unsigned breakWord = getNumWords() - 1 - offset; // last word affected
1067 unsigned bitsInWord = whichBit(BitWidth); // how many bits in last word?
1068 if (bitsInWord == 0)
1069 bitsInWord = APINT_BITS_PER_WORD;
1070
1071 // If we are shifting whole words, just move whole words
1072 if (wordShift == 0) {
1073 // Move the words containing significant bits
1074 for (unsigned i = 0; i <= breakWord; ++i)
1075 val[i] = pVal[i+offset]; // move whole word
1076
1077 // Adjust the top significant word for sign bit fill, if negative
1078 if (isNegative())
1079 if (bitsInWord < APINT_BITS_PER_WORD)
1080 val[breakWord] |= WORD_MAX << bitsInWord; // set high bits
10531081 } else {
1054 for (unsigned i = 0; i != WordsToMove; ++i) {
1055 pVal[i] = pVal[i + WordShift] >> BitShift;
1056 if (i + 1 != WordsToMove)
1057 pVal[i] |= pVal[i + WordShift + 1] << (APINT_BITS_PER_WORD - BitShift);
1058 else if (Negative)
1059 pVal[i] |= WORD_MAX << (APINT_BITS_PER_WORD - BitShift);
1060 }
1061 }
1062
1063 // Fill in the remainder based on the original sign.
1064 std::memset(pVal + WordsToMove, Negative ? -1 : 0,
1065 WordShift * APINT_WORD_SIZE);
1066 clearUnusedBits();
1082 // Shift the low order words
1083 for (unsigned i = 0; i < breakWord; ++i) {
1084 // This combines the shifted corresponding word with the low bits from
1085 // the next word (shifted into this word's high bits).
1086 val[i] = (pVal[i+offset] >> wordShift) |
1087 (pVal[i+offset+1] << (APINT_BITS_PER_WORD - wordShift));
1088 }
1089
1090 // Shift the break word. In this case there are no bits from the next word
1091 // to include in this word.
1092 val[breakWord] = pVal[breakWord+offset] >> wordShift;
1093
1094 // Deal with sign extension in the break word, and possibly the word before
1095 // it.
1096 if (isNegative()) {
1097 if (wordShift > bitsInWord) {
1098 if (breakWord > 0)
1099 val[breakWord-1] |=
1100 WORD_MAX << (APINT_BITS_PER_WORD - (wordShift - bitsInWord));
1101 val[breakWord] |= WORD_MAX;
1102 } else
1103 val[breakWord] |= WORD_MAX << (bitsInWord - wordShift);
1104 }
1105 }
1106
1107 // Remaining words are 0 or -1, just assign them.
1108 uint64_t fillValue = (isNegative() ? WORD_MAX : 0);
1109 for (unsigned i = breakWord+1; i < getNumWords(); ++i)
1110 val[i] = fillValue;
1111 APInt Result(val, BitWidth);
1112 Result.clearUnusedBits();
1113 return Result;
10671114 }
10681115
10691116 /// Logical right-shift this APInt by shiftAmt.
287287 EXPECT_EQ(zero, one.shl(1));
288288 EXPECT_EQ(one, one.shl(0));
289289 EXPECT_EQ(zero, one.lshr(1));
290 EXPECT_EQ(one, one.ashr(1));
290 EXPECT_EQ(zero, one.ashr(1));
291291
292292 // Rotates.
293293 EXPECT_EQ(one, one.rotl(0));
20232023 EXPECT_EQ(0, neg_one.lshr(128));
20242024 }
20252025
2026 TEST(APIntTest, ArithmeticRightShift) {
2027 // Ensure we handle large shifts of multi-word.
2028 const APInt signmin32(APInt::getSignedMinValue(32));
2029 EXPECT_TRUE(signmin32.ashr(32).isAllOnesValue());
2030
2031 // Ensure we handle large shifts of multi-word.
2032 const APInt umax32(APInt::getSignedMaxValue(32));
2033 EXPECT_EQ(0, umax32.ashr(32));
2034
2035 // Ensure we handle large shifts of multi-word.
2036 const APInt signmin128(APInt::getSignedMinValue(128));
2037 EXPECT_TRUE(signmin128.ashr(128).isAllOnesValue());
2038
2039 // Ensure we handle large shifts of multi-word.
2040 const APInt umax128(APInt::getSignedMaxValue(128));
2041 EXPECT_EQ(0, umax128.ashr(128));
2042 }
2043
20442026 TEST(APIntTest, LeftShift) {
20452027 APInt i256(APInt::getLowBitsSet(256, 2));
20462028