mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
Fix compile-time regression caused by rL371928
Summary: Also fixup rL371928 for cases that occur on our out-of-tree backend There were still quite a few intermediate APInts and this caused the compile time of MCCodeEmitter for our target to jump from 16s up to ~5m40s. This patch, brings it back down to ~17s by eliminating pretty much all of them using two new APInt functions (extractBitsAsZExtValue(), insertBits() but with a uint64_t). The exact conditions for eliminating them is that the field extracted/inserted must be <=64-bit which is almost always true. Note: The two new APInt API's assume that APInt::WordSize is at least 64-bit because that means they touch at most 2 APInt words. They statically assert that's true. It seems very unlikely that someone is patching it to be smaller so this should be fine. Reviewers: jmolloy Reviewed By: jmolloy Subscribers: hiraditya, dexonsmith, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D67686 llvm-svn: 372243
This commit is contained in:
parent
a1b459b553
commit
1c646a78c0
@ -1503,9 +1503,11 @@ public:
|
|||||||
|
|
||||||
/// Insert the bits from a smaller APInt starting at bitPosition.
|
/// Insert the bits from a smaller APInt starting at bitPosition.
|
||||||
void insertBits(const APInt &SubBits, unsigned bitPosition);
|
void insertBits(const APInt &SubBits, unsigned bitPosition);
|
||||||
|
void insertBits(uint64_t SubBits, unsigned bitPosition, unsigned numBits);
|
||||||
|
|
||||||
/// Return an APInt with the extracted bits [bitPosition,bitPosition+numBits).
|
/// Return an APInt with the extracted bits [bitPosition,bitPosition+numBits).
|
||||||
APInt extractBits(unsigned numBits, unsigned bitPosition) const;
|
APInt extractBits(unsigned numBits, unsigned bitPosition) const;
|
||||||
|
uint64_t extractBitsAsZExtValue(unsigned numBits, unsigned bitPosition) const;
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
/// \name Value Characterization Functions
|
/// \name Value Characterization Functions
|
||||||
|
@ -401,6 +401,33 @@ void APInt::insertBits(const APInt &subBits, unsigned bitPosition) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void APInt::insertBits(uint64_t subBits, unsigned bitPosition, unsigned numBits) {
|
||||||
|
uint64_t maskBits = maskTrailingOnes<uint64_t>(numBits);
|
||||||
|
subBits &= maskBits;
|
||||||
|
if (isSingleWord()) {
|
||||||
|
U.VAL &= ~(maskBits << bitPosition);
|
||||||
|
U.VAL |= subBits << bitPosition;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned loBit = whichBit(bitPosition);
|
||||||
|
unsigned loWord = whichWord(bitPosition);
|
||||||
|
unsigned hiWord = whichWord(bitPosition + numBits - 1);
|
||||||
|
if (loWord == hiWord) {
|
||||||
|
U.pVal[loWord] &= ~(maskBits << loBit);
|
||||||
|
U.pVal[loWord] |= subBits << loBit;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static_assert(8 * sizeof(WordType) <= 64, "This code assumes only two words affected");
|
||||||
|
unsigned wordBits = 8 * sizeof(WordType);
|
||||||
|
U.pVal[loWord] &= ~(maskBits << loBit);
|
||||||
|
U.pVal[loWord] |= subBits << loBit;
|
||||||
|
|
||||||
|
U.pVal[hiWord] &= ~(maskBits >> (wordBits - loBit));
|
||||||
|
U.pVal[hiWord] |= subBits >> (wordBits - loBit);
|
||||||
|
}
|
||||||
|
|
||||||
APInt APInt::extractBits(unsigned numBits, unsigned bitPosition) const {
|
APInt APInt::extractBits(unsigned numBits, unsigned bitPosition) const {
|
||||||
assert(numBits > 0 && "Can't extract zero bits");
|
assert(numBits > 0 && "Can't extract zero bits");
|
||||||
assert(bitPosition < BitWidth && (numBits + bitPosition) <= BitWidth &&
|
assert(bitPosition < BitWidth && (numBits + bitPosition) <= BitWidth &&
|
||||||
@ -438,6 +465,31 @@ APInt APInt::extractBits(unsigned numBits, unsigned bitPosition) const {
|
|||||||
return Result.clearUnusedBits();
|
return Result.clearUnusedBits();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t APInt::extractBitsAsZExtValue(unsigned numBits,
|
||||||
|
unsigned bitPosition) const {
|
||||||
|
assert(numBits > 0 && "Can't extract zero bits");
|
||||||
|
assert(bitPosition < BitWidth && (numBits + bitPosition) <= BitWidth &&
|
||||||
|
"Illegal bit extraction");
|
||||||
|
assert(numBits <= 64 && "Illegal bit extraction");
|
||||||
|
|
||||||
|
uint64_t maskBits = maskTrailingOnes<uint64_t>(numBits);
|
||||||
|
if (isSingleWord())
|
||||||
|
return (U.VAL >> bitPosition) & maskBits;
|
||||||
|
|
||||||
|
unsigned loBit = whichBit(bitPosition);
|
||||||
|
unsigned loWord = whichWord(bitPosition);
|
||||||
|
unsigned hiWord = whichWord(bitPosition + numBits - 1);
|
||||||
|
if (loWord == hiWord)
|
||||||
|
return (U.pVal[loWord] >> loBit) & maskBits;
|
||||||
|
|
||||||
|
static_assert(8 * sizeof(WordType) <= 64, "This code assumes only two words affected");
|
||||||
|
unsigned wordBits = 8 * sizeof(WordType);
|
||||||
|
uint64_t retBits = U.pVal[loWord] >> loBit;
|
||||||
|
retBits |= U.pVal[hiWord] << (wordBits - loBit);
|
||||||
|
retBits &= maskBits;
|
||||||
|
return retBits;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned APInt::getBitsNeeded(StringRef str, uint8_t radix) {
|
unsigned APInt::getBitsNeeded(StringRef str, uint8_t radix) {
|
||||||
assert(!str.empty() && "Invalid string length");
|
assert(!str.empty() && "Invalid string length");
|
||||||
assert((radix == 10 || radix == 8 || radix == 16 || radix == 2 ||
|
assert((radix == 10 || radix == 8 || radix == 16 || radix == 2 ||
|
||||||
|
@ -46,21 +46,12 @@ def biz : Instruction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-LABEL: case ::biz: {
|
// CHECK-LABEL: case ::biz: {
|
||||||
// CHECK: const APInt [[x:M[0-9]+]] = APInt::getBitsSet(65, 3, 7);
|
// CHECK: Value.insertBits(op.extractBitsAsZExtValue(4, 3), 12, 4);
|
||||||
// CHECK-NEXT: Value |= (op & [[x]]) << 9;
|
// CHECK-NEXT: Value.insertBits(op.extractBitsAsZExtValue(4, 7), 8, 4);
|
||||||
// CHECK-NEXT: const APInt [[y:M[0-9]+]] = APInt::getBitsSet(65, 7, 11);
|
|
||||||
// CHECK-NEXT: Value |= (op & [[y]]) << 1;
|
|
||||||
|
|
||||||
// CHECK-LABEL: case ::foo: {
|
// CHECK-LABEL: case ::foo: {
|
||||||
// CHECK: const APInt [[x:M[0-9]+]] = APInt::getBitsSet(65, 0, 7);
|
// CHECK: Value.insertBits(op.extractBitsAsZExtValue(7, 0), 8, 7);
|
||||||
// CHECK-NEXT: op &= [[x]];
|
|
||||||
// CHECK-NEXT: op <<= 8;
|
|
||||||
// CHECK-NEXT: Value |= op;
|
|
||||||
|
|
||||||
// CHECK-LABEL: case ::bar: {
|
// CHECK-LABEL: case ::bar: {
|
||||||
// CHECK: const APInt [[x:M[0-9]+]] = APInt::getBitsSet(65, 3, 11);
|
// CHECK: Value.insertBits(op.extractBitsAsZExtValue(8, 3), 8, 8);
|
||||||
// CHECK-NEXT: op &= [[x]];
|
|
||||||
// CHECK-NEXT: op <<= 5;
|
|
||||||
// CHECK-NEXT: Value |= op;
|
|
||||||
|
@ -1858,6 +1858,64 @@ TEST(APIntTest, insertBits) {
|
|||||||
EXPECT_EQ(i260.extractBits(4, 256).getZExtValue(), 0x000000000000000Full);
|
EXPECT_EQ(i260.extractBits(4, 256).getZExtValue(), 0x000000000000000Full);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(APIntTest, insertBitsUInt64) {
|
||||||
|
// Tests cloned from insertBits but adapted to the numBits <= 64 constraint
|
||||||
|
uint64_t iSrc = 0x00123456;
|
||||||
|
|
||||||
|
// Direct copy.
|
||||||
|
APInt i31(31, 0x76543210ull);
|
||||||
|
i31.insertBits(iSrc, 0, 31);
|
||||||
|
EXPECT_EQ(static_cast<int64_t>(0x00123456ull), i31.getSExtValue());
|
||||||
|
|
||||||
|
// Single word src/dst insertion.
|
||||||
|
APInt i63(63, 0x01234567FFFFFFFFull);
|
||||||
|
i63.insertBits(iSrc, 4, 31);
|
||||||
|
EXPECT_EQ(static_cast<int64_t>(0x012345600123456Full), i63.getSExtValue());
|
||||||
|
|
||||||
|
// Insert single word src into one word of dst.
|
||||||
|
APInt i120(120, UINT64_MAX, true);
|
||||||
|
i120.insertBits(iSrc, 8, 31);
|
||||||
|
EXPECT_EQ(static_cast<int64_t>(0xFFFFFF80123456FFull), i120.getSExtValue());
|
||||||
|
|
||||||
|
// Insert single word src into two words of dst.
|
||||||
|
APInt i127(127, UINT64_MAX, true);
|
||||||
|
i127.insertBits(iSrc, 48, 31);
|
||||||
|
EXPECT_EQ(i127.extractBits(64, 0).getZExtValue(), 0x3456FFFFFFFFFFFFull);
|
||||||
|
EXPECT_EQ(i127.extractBits(63, 64).getZExtValue(), 0x7FFFFFFFFFFF8012ull);
|
||||||
|
|
||||||
|
// Insert on word boundaries.
|
||||||
|
APInt i128(128, 0);
|
||||||
|
i128.insertBits(UINT64_MAX, 0, 64);
|
||||||
|
i128.insertBits(UINT64_MAX, 64, 64);
|
||||||
|
EXPECT_EQ(-1, i128.getSExtValue());
|
||||||
|
|
||||||
|
APInt i256(256, UINT64_MAX, true);
|
||||||
|
i256.insertBits(0, 0, 64);
|
||||||
|
i256.insertBits(0, 64, 1);
|
||||||
|
i256.insertBits(0, 64, 64);
|
||||||
|
i256.insertBits(0, 128, 5);
|
||||||
|
i256.insertBits(0, 128, 64);
|
||||||
|
i256.insertBits(0, 192, 64);
|
||||||
|
EXPECT_EQ(0u, i256.getSExtValue());
|
||||||
|
|
||||||
|
APInt i257(257, 0);
|
||||||
|
i257.insertBits(APInt(96, UINT64_MAX, true), 64);
|
||||||
|
EXPECT_EQ(i257.extractBitsAsZExtValue(64, 0), 0x0000000000000000ull);
|
||||||
|
EXPECT_EQ(i257.extractBitsAsZExtValue(64, 64), 0xFFFFFFFFFFFFFFFFull);
|
||||||
|
EXPECT_EQ(i257.extractBitsAsZExtValue(64, 128), 0x00000000FFFFFFFFull);
|
||||||
|
EXPECT_EQ(i257.extractBitsAsZExtValue(64, 192), 0x0000000000000000ull);
|
||||||
|
EXPECT_EQ(i257.extractBitsAsZExtValue(1, 256), 0x0000000000000000ull);
|
||||||
|
|
||||||
|
// General insertion.
|
||||||
|
APInt i260(260, UINT64_MAX, true);
|
||||||
|
i260.insertBits(APInt(129, 1ull << 48), 15);
|
||||||
|
EXPECT_EQ(i260.extractBitsAsZExtValue(64, 0), 0x8000000000007FFFull);
|
||||||
|
EXPECT_EQ(i260.extractBitsAsZExtValue(64, 64), 0x0000000000000000ull);
|
||||||
|
EXPECT_EQ(i260.extractBitsAsZExtValue(64, 128), 0xFFFFFFFFFFFF0000ull);
|
||||||
|
EXPECT_EQ(i260.extractBitsAsZExtValue(64, 192), 0xFFFFFFFFFFFFFFFFull);
|
||||||
|
EXPECT_EQ(i260.extractBitsAsZExtValue(4, 256), 0x000000000000000Full);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(APIntTest, extractBits) {
|
TEST(APIntTest, extractBits) {
|
||||||
APInt i32(32, 0x1234567);
|
APInt i32(32, 0x1234567);
|
||||||
EXPECT_EQ(0x3456, i32.extractBits(16, 4));
|
EXPECT_EQ(0x3456, i32.extractBits(16, 4));
|
||||||
@ -1881,6 +1939,33 @@ TEST(APIntTest, extractBits) {
|
|||||||
APInt(144, "281474976710655", 10).extractBits(48, 1));
|
APInt(144, "281474976710655", 10).extractBits(48, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(APIntTest, extractBitsAsZExtValue) {
|
||||||
|
// Tests based on extractBits
|
||||||
|
APInt i32(32, 0x1234567);
|
||||||
|
EXPECT_EQ(0x3456u, i32.extractBitsAsZExtValue(16, 4));
|
||||||
|
|
||||||
|
APInt i257(257, 0xFFFFFFFFFF0000FFull, true);
|
||||||
|
EXPECT_EQ(0xFFu, i257.extractBitsAsZExtValue(16, 0));
|
||||||
|
EXPECT_EQ((0xFFu >> 1), i257.extractBitsAsZExtValue(16, 1));
|
||||||
|
EXPECT_EQ(0xFFFFFFFFull, i257.extractBitsAsZExtValue(32, 64));
|
||||||
|
EXPECT_EQ(0xFFFFFFFFFFFFFFFFull, i257.extractBitsAsZExtValue(64, 128));
|
||||||
|
EXPECT_EQ(0xFFFFFFFFFFFFFFFFull, i257.extractBitsAsZExtValue(64, 192));
|
||||||
|
EXPECT_EQ(0xFFFFFFFFFFFFFFFFull, i257.extractBitsAsZExtValue(64, 191));
|
||||||
|
EXPECT_EQ(0x3u, i257.extractBitsAsZExtValue(2, 255));
|
||||||
|
EXPECT_EQ(0xFFFFFFFFFF80007Full, i257.extractBitsAsZExtValue(64, 1));
|
||||||
|
EXPECT_EQ(0xFFFFFFFFFFFFFFFFull, i257.extractBitsAsZExtValue(64, 65));
|
||||||
|
EXPECT_EQ(0xFFFFFFFFFF80007Full, i257.extractBitsAsZExtValue(64, 1));
|
||||||
|
EXPECT_EQ(0xFFFFFFFFFFFFFFFFull, i257.extractBitsAsZExtValue(64, 65));
|
||||||
|
EXPECT_EQ(0x1ull, i257.extractBitsAsZExtValue(1, 129));
|
||||||
|
|
||||||
|
EXPECT_EQ(APInt(48, 0),
|
||||||
|
APInt(144, "281474976710655", 10).extractBitsAsZExtValue(48, 48));
|
||||||
|
EXPECT_EQ(APInt(48, 0x0000ffffffffffffull),
|
||||||
|
APInt(144, "281474976710655", 10).extractBitsAsZExtValue(48, 0));
|
||||||
|
EXPECT_EQ(APInt(48, 0x00007fffffffffffull),
|
||||||
|
APInt(144, "281474976710655", 10).extractBitsAsZExtValue(48, 1));
|
||||||
|
}
|
||||||
|
|
||||||
TEST(APIntTest, getLowBitsSet) {
|
TEST(APIntTest, getLowBitsSet) {
|
||||||
APInt i128lo64 = APInt::getLowBitsSet(128, 64);
|
APInt i128lo64 = APInt::getLowBitsSet(128, 64);
|
||||||
EXPECT_EQ(0u, i128lo64.countLeadingOnes());
|
EXPECT_EQ(0u, i128lo64.countLeadingOnes());
|
||||||
|
@ -212,24 +212,30 @@ AddCodeToMergeInOperand(Record *R, BitsInit *BI, const std::string &VarName,
|
|||||||
std::string maskStr;
|
std::string maskStr;
|
||||||
int opShift;
|
int opShift;
|
||||||
|
|
||||||
if (UseAPInt) {
|
|
||||||
unsigned loBit = beginVarBit - N + 1;
|
unsigned loBit = beginVarBit - N + 1;
|
||||||
unsigned hiBit = loBit + N;
|
unsigned hiBit = loBit + N;
|
||||||
maskStr = "M" + itostr(bit);
|
unsigned loInstBit = beginInstBit - N + 1;
|
||||||
Case += " const APInt " + maskStr + " = APInt::getBitsSet(" +
|
if (UseAPInt) {
|
||||||
itostr(BitWidth) + ", " + itostr(loBit) + ", " + itostr(hiBit) +
|
std::string extractStr;
|
||||||
");\n";
|
if (N >= 64) {
|
||||||
|
extractStr = "op.extractBits(" + itostr(hiBit - loBit) + ", " +
|
||||||
|
itostr(loBit) + ")";
|
||||||
|
Case += " Value.insertBits(" + extractStr + ", " +
|
||||||
|
itostr(loInstBit) + ");\n";
|
||||||
|
} else {
|
||||||
|
extractStr = "op.extractBitsAsZExtValue(" + itostr(hiBit - loBit) +
|
||||||
|
", " + itostr(loBit) + ")";
|
||||||
|
Case += " Value.insertBits(" + extractStr + ", " +
|
||||||
|
itostr(loInstBit) + ", " + itostr(hiBit - loBit) + ");\n";
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
uint64_t opMask = ~(uint64_t)0 >> (64 - N);
|
uint64_t opMask = ~(uint64_t)0 >> (64 - N);
|
||||||
opShift = beginVarBit - N + 1;
|
opShift = beginVarBit - N + 1;
|
||||||
opMask <<= opShift;
|
opMask <<= opShift;
|
||||||
maskStr = "UINT64_C(" + utostr(opMask) + ")";
|
maskStr = "UINT64_C(" + utostr(opMask) + ")";
|
||||||
}
|
|
||||||
opShift = beginInstBit - beginVarBit;
|
opShift = beginInstBit - beginVarBit;
|
||||||
|
|
||||||
if (numOperandLits == 1) {
|
if (numOperandLits == 1) {
|
||||||
// Because Op may be an APInt, ensure all arithmetic is done in-place
|
|
||||||
// where possible to elide copies.
|
|
||||||
Case += " op &= " + maskStr + ";\n";
|
Case += " op &= " + maskStr + ";\n";
|
||||||
if (opShift > 0) {
|
if (opShift > 0) {
|
||||||
Case += " op <<= " + itostr(opShift) + ";\n";
|
Case += " op <<= " + itostr(opShift) + ";\n";
|
||||||
@ -239,17 +245,18 @@ AddCodeToMergeInOperand(Record *R, BitsInit *BI, const std::string &VarName,
|
|||||||
Case += " Value |= op;\n";
|
Case += " Value |= op;\n";
|
||||||
} else {
|
} else {
|
||||||
if (opShift > 0) {
|
if (opShift > 0) {
|
||||||
Case += " Value |= (op & " + maskStr + ") << " + itostr(opShift) +
|
Case += " Value |= (op & " + maskStr + ") << " +
|
||||||
";\n";
|
itostr(opShift) + ";\n";
|
||||||
} else if (opShift < 0) {
|
} else if (opShift < 0) {
|
||||||
Case += " Value |= (op & " + maskStr + ") >> " + itostr(-opShift) +
|
Case += " Value |= (op & " + maskStr + ") >> " +
|
||||||
";\n";
|
itostr(-opShift) + ";\n";
|
||||||
} else {
|
} else {
|
||||||
Case += " Value |= (op & " + maskStr + ");\n";
|
Case += " Value |= (op & " + maskStr + ");\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string CodeEmitterGen::getInstructionCase(Record *R,
|
std::string CodeEmitterGen::getInstructionCase(Record *R,
|
||||||
CodeGenTarget &Target) {
|
CodeGenTarget &Target) {
|
||||||
@ -436,9 +443,12 @@ void CodeEmitterGen::run(raw_ostream &o) {
|
|||||||
<< " raw_string_ostream Msg(msg);\n"
|
<< " raw_string_ostream Msg(msg);\n"
|
||||||
<< " Msg << \"Not supported instr: \" << MI;\n"
|
<< " Msg << \"Not supported instr: \" << MI;\n"
|
||||||
<< " report_fatal_error(Msg.str());\n"
|
<< " report_fatal_error(Msg.str());\n"
|
||||||
<< " }\n"
|
<< " }\n";
|
||||||
<< " return Value;\n"
|
if (UseAPInt)
|
||||||
<< "}\n\n";
|
o << " Inst = Value;\n";
|
||||||
|
else
|
||||||
|
o << " return Value;\n";
|
||||||
|
o << "}\n\n";
|
||||||
|
|
||||||
const auto &All = SubtargetFeatureInfo::getAll(Records);
|
const auto &All = SubtargetFeatureInfo::getAll(Records);
|
||||||
std::map<Record *, SubtargetFeatureInfo, LessRecordByID> SubtargetFeatures;
|
std::map<Record *, SubtargetFeatureInfo, LessRecordByID> SubtargetFeatures;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user