[APInt] Remove self move check from move assignment operator

This was added to work around a bug in MSVC 2013's implementation of stable_sort. That bug has been fixed as of MSVC 2015 so we shouldn't need this anymore.

Technically the current implementation has undefined behavior because we only protect the deleting of the pVal array with the self move check. There is still a memcpy of that.VAL to VAL that isn't protected. In the case of self move those are the same local and memcpy is undefined for src and dst overlapping.

This reduces the size of the opt binary on my local x86-64 build by about 4k.

Differential Revision: https://reviews.llvm.org/D32116




git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@300477 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Craig Topper 2017-04-17 18:44:27 +00:00
parent 7b19c164ad
commit ef47b09cd9
2 changed files with 5 additions and 41 deletions

View File

@ -693,24 +693,16 @@ public:
/// @brief Move assignment operator.
APInt &operator=(APInt &&that) {
if (!isSingleWord()) {
// The MSVC STL shipped in 2013 requires that self move assignment be a
// no-op. Otherwise algorithms like stable_sort will produce answers
// where half of the output is left in a moved-from state.
if (this == &that)
return *this;
assert(this != &that && "Self-move not supported");
if (!isSingleWord())
delete[] pVal;
}
// Use memcpy so that type based alias analysis sees both VAL and pVal
// as modified.
memcpy(&VAL, &that.VAL, sizeof(uint64_t));
// If 'this == &that', avoid zeroing our own bitwidth by storing to 'that'
// first.
unsigned ThatBitWidth = that.BitWidth;
BitWidth = that.BitWidth;
that.BitWidth = 0;
BitWidth = ThatBitWidth;
return *this;
}

View File

@ -1606,36 +1606,6 @@ TEST(APIntTest, isShiftedMask) {
}
}
#if defined(__clang__)
// Disable the pragma warning from versions of Clang without -Wself-move
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunknown-pragmas"
// Disable the warning that triggers on exactly what is being tested.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wself-move"
#endif
TEST(APIntTest, SelfMoveAssignment) {
APInt X(32, 0xdeadbeef);
X = std::move(X);
EXPECT_EQ(32u, X.getBitWidth());
EXPECT_EQ(0xdeadbeefULL, X.getLimitedValue());
uint64_t Bits[] = {0xdeadbeefdeadbeefULL, 0xdeadbeefdeadbeefULL};
APInt Y(128, Bits);
Y = std::move(Y);
EXPECT_EQ(128u, Y.getBitWidth());
EXPECT_EQ(~0ULL, Y.getLimitedValue());
const uint64_t *Raw = Y.getRawData();
EXPECT_EQ(2u, Y.getNumWords());
EXPECT_EQ(0xdeadbeefdeadbeefULL, Raw[0]);
EXPECT_EQ(0xdeadbeefdeadbeefULL, Raw[1]);
}
#if defined(__clang__)
#pragma clang diagnostic pop
#pragma clang diagnostic pop
#endif
}
TEST(APIntTest, reverseBits) {
EXPECT_EQ(1, APInt(1, 1).reverseBits());
EXPECT_EQ(0, APInt(1, 0).reverseBits());
@ -2025,3 +1995,5 @@ TEST(APIntTest, GCD) {
APInt C = GreatestCommonDivisor(A, B);
EXPECT_EQ(C, HugePrime);
}
} // end anonymous namespace